📄 basicplayer.c
字号:
{ Log.log( 101, "turnWithBall: freeze ball" ); return freezeBall(); } else { Log.log( 101, "turnWithBall: kick ball close to desired turn angle" ); return kickBallCloseToBody( VecPosition::normalizeAngle( ang - angBody ) ); }}/*! This skill enables an agent to move along a line to a given position 'pos' on this line. It is used, for example, by the goalkeeper who often wants to stay on a line in front of his goal and move to different positions on this line depending on where the ball is located. Furthermore, it can also used by defenders for marking an opponent player by moving along a line between this player and the ball. The idea is that the agent must try to move as fast as possible to the desired point 'pos' along the line thereby keeping the number of turns to a minimum to avoid wasting cycles. Apart from the target position 'pos', this skill receives several additional arguments for determining whether the agent should turn or dash in the current situation. Since the agent can only move forwards or backwards into the direction of his body, it is important that he tries to keep the orientation of his body aligned with the direction of the line in order to be able to move quickly to the target point. A given angle 'ang' denotes the desired body angle (global) of the agent in the point 'pos'. The line l can thus be defined as going through 'pos' and having global direction 'ang'. Due to the noise that is added to the movement of the agent, the orientation of his body will never be exactly equal to 'ang' and as a result the agent' s position will start to deviate from the line. Each time when this skill is called, the agent's desired orientation is therefore slightly adjusted depending on his position with respect to l. If the distance d between the agent's current position and the line l is smaller than the given value 'dDistThr' then 'ang' remains unchanged. However, if d exceeds 'dDistThr' then 'ang' is adjusted in such a way that the agent will move closer to l in subsequent cycles. This is done by either increasing or decreasing the desired orientation 'ang' by 'angCorr' degrees depending on which side of the line the agent is located and on a prediction of the agent's movement in the forthcoming cycles. This prediction is represented by a given value 'iSign' which equals 1 if the agent is expected to move in the same direction as 'ang' and -1 if he will move in the opposite direction. Adjusting 'ang' in this way has the effect that in subsequent cycles the agent will move closer to the line again if this is necessary. The final decision whether to turn or dash is now made by comparing the agent's current body angle to the desired orientation. If the difference between these two angles is larger than 'angThr' degrees then the agent uses the turnBodyToPoint skill to turn in the desired direction. Otherwise, the dashToPoint skill is called to move towards the target position. \param pos global position to which the agent wants to move \param ang desired global body angle of agent in position 'pos' \param dDistThr threshold value that defines if desired angle is adjusted \param iSign indication whether agent predicts that he will move in the same direction as 'ang' in the subsequent cycles (iSign=1) or in the opposite direction (iSign=-1) \param angThr threshold value that specifies when agent will perform a turn command \param angCorr correction term with which angle is adjusted if necessary \return SoccerCommand that will move agent along line defined by position 'pos' and angle 'ang'. */SoccerCommand BasicPlayer::moveToPosAlongLine( VecPosition pos, AngDeg ang, double dDistThr, int iSign, AngDeg angThr, AngDeg angCorr ){ Line l = Line::makeLineFromPositionAndAngle( pos, ang ); VecPosition posBall = WM->getBallPos(); VecPosition posAgent = WM->getAgentGlobalPosition(); AngDeg angBody = WM->getAgentGlobalBodyAngle(); VecPosition posProj = l.getPointOnLineClosestTo( posAgent ); double dDist = posAgent.getDistanceTo( posProj ); double dDiff = pos.getDistanceTo ( posProj ); // if deviated too much from line, compensate if( dDist > dDistThr ) { // check on which side of line agent is located VecPosition posOrg(0,0); Line m = Line::makeLineFromTwoPoints( posOrg, posAgent ); VecPosition posIntersect = l.getIntersection( m ); int iSide; if( posAgent.getDistanceTo(posOrg) < posIntersect.getDistanceTo( posOrg ) ) iSide = +1; else iSide = -1; // adjust desired turning angle to move back to line in coming cycles ang = ang + iSign * iSide * angCorr; } Log.log( 553, "y difference to defend point %f", dDiff ); // if current body angle differs much from desired turning angle, turn body if( fabs( VecPosition::normalizeAngle( ang - angBody ) ) > angThr ) { Log.log( 553, "angle differs too much body = %f, des = %f", angBody, ang ); return turnBodyToPoint( posAgent + VecPosition( 1.0, ang, POLAR ) ); } else if( ( posBall.getX() > -PITCH_LENGTH/4.0 && dDiff > 0.6 ) ) return dashToPoint( pos ); // move later when ball is far from pen. area. else if( ( posBall.getX() < -PITCH_LENGTH/4.0 && dDiff > 0.3 ) ) return dashToPoint( pos ); // move earlier when is ball near pen. area. else return SoccerCommand( CMD_ILLEGAL );}/********************** HIGH LEVEL SKILLS ************************************//*! When the ball-interception skill is called, it is first determined whether it is possible for the agent to intercept the ball within two cycles using the intermediate player skill closeIntercept (for the goalkeeper closeIntereptGoalie). If it turns out that the ball cannot be intercepted within two cycles then the agent uses an iterative scheme to compute the optimal interception point. This is done using the method 'getInterceptionPointBall'. \param isGoalie indicates whether the current player is a goalkeeper or not \return SoccerCommand to intercept the ball. */SoccerCommand BasicPlayer::intercept( bool isGoalie ){ SoccerCommand soc = (isGoalie) ? interceptCloseGoalie() : interceptClose(); if( soc.commandType != CMD_ILLEGAL ) { Log.log( 502, "intercept in two cycles" ); return soc; } // else find the best interception point int iSol; VecPosition posBall = getInterceptionPointBall( &iSol, isGoalie ); Log.log( 502, "intercept ball in %d cycles", iSol ); return moveToPos( posBall, PS->getPlayerWhenToTurnAngle(), 3.0 );}/*! This skill enables an agent to dribble with the ball, i.e. to move with the ball while keeping it within a certain distance. This amounts to repeatedly kicking the ball at a certain speed into a desired direction and then intercepting it again. Two arguments, the angle 'ang' and type 'dribbleT', are supplied to this skill which respectively denote the global direction towards which the agent wants to dribble and the kind of dribble that must be performed. We distinguish three kinds of dribbling: - DRIBBLE FAST: a fast dribble action in which the agent kicks the ball relatively far ahead of him. - DRIBBLE SLOW: a slower dribble action in which the agent keeps the ball closer than on a fast dribble. - DRIBBLE WITH BALL: a safe dribble action in which the agent keeps the ball very close to his body. It is important to realize that this skill is only called when the ball is located within the agent's kickable range. This means that it is only responsible for the kicking part of the overall dribbling behavior, i.e. it only causes the ball to be kicked a certain distance ahead into the desired direction 'ang'. If the absolute angle between 'ang' and the agent's body direction is larger than DribbleTurnAngle (which currently has a value of 30 degrees) then the agent uses the turnWithBallTo skill to turn with the ball towards the global angle 'ang'. Otherwise, he uses the kickTo skill to kick the ball into the desired direction towards a point that lies a certain distance ahead depending on the type of dribble. After the kick, the ball will move out of the agent's kickable range and as a result the agent will try to intercept it using the intercept skill. The dribbling skill can then be called again once the agent has succeeded in intercepting the ball. This sequence of kicking and intercepting will repeat itself until the agent decides to perform another skill. Note that during the dribble the power of a kick depends on the distance that the ball should travel and on the speed that it should have when it reaches the target point. In our current implementation this speed equals 0.5 (=DribbleKickEndSpeed) for any type of dribble. Experiments have shown that lower end speed values cause the agent to intercept the ball before it reaches the target point which slows the dribble down significantly. \param ang global direction in which should be dribbled \param dribbleT type of dribble that should be performed \return SoccerCommand to dribble in direction 'ang' */SoccerCommand BasicPlayer::dribble( AngDeg ang, DribbleT dribbleT ){ double dLength; AngDeg angBody = WM->getAgentGlobalBodyAngle(); VecPosition posAgent = WM->getAgentGlobalPosition(); SoccerCommand soc; // if not turned into correct direction, turn with the ball to that angle AngDeg angDiff = VecPosition::normalizeAngle( ang - angBody ); if( fabs( angDiff ) > PS->getDribbleAngThr() ) return turnWithBallTo( ang, PS->getTurnWithBallAngThr(), PS->getTurnWithBallFreezeThr() ); switch( dribbleT ) { case DRIBBLE_WITHBALL: dLength = 4.0; break; case DRIBBLE_SLOW: dLength = 5.0; break; case DRIBBLE_FAST: dLength = 10.0; break; default: dLength = 0.0; break; } // determine shooting point, relative to agent since moving in that dir. VecPosition posDribble = posAgent + VecPosition( dLength, angBody, POLAR ); // adjust when point lies outside side of field // to a point that lies at distance 2.0 from the side of the field if( fabs( posDribble.getY() ) > PITCH_WIDTH/2.0 - 3.0 ) posDribble.setY( (PITCH_WIDTH/2.0 - 3.0)*sign(posDribble.getY()) ); if( fabs( posDribble.getX() ) > PITCH_LENGTH/2.0 - 3.0 ) posDribble.setX( (PITCH_LENGTH/2.0 - 3.0)*sign(posDribble.getX()) ); soc = kickTo( posDribble, 0.5 ); // if ball is kickable but already heading in the right direction, so only // small correction term is necessary, start intercepting SoccerCommand soc2 = intercept( false ); if( soc.dPower < 7 && WM->isCollisionAfterDash( soc2 ) == false ) { Log.log( 560, "wanted to dribble, but only small kick %f", soc.dPower ); return soc2; } return soc;}/*! This skill enables an agent to pass the ball directly to another player. It receives two arguments, 'pos' and 'passType', which respectively denote the position (of usually a teammate) to which the agent wants to pass the ball and the kind of pass (either normal or fast) that should be given. This skill uses the kickTo skill to pass the ball to the specified position with a certain desired end speed depending on the type of pass. \param pos position of object to which a direct pass should be given \param passType kind of pass (either PASS_NORMAL or PASS_FAST ) \return SoccerCommand to perform a direct pass to object 'o' */SoccerCommand BasicPlayer::directPass( VecPosition pos, PassT passType){ if( passType == PASS_NORMAL ) return kickTo( pos, PS->getPassEndSpeed() ); else if( passType == PASS_FAST ) return kickTo( pos, PS->getFastPassEndSpeed() ); else return SoccerCommand( CMD_ILLEGAL );}/*! This skill enables an agent to give a leading pass to another player. A leading pass is a pass into open space that `leads' the receiver, i.e. instead of passing the ball di:rectly to another player it is kicked just ahead of him. In this way the receiver is able to intercept
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -