📄 basicplayer.cpp
字号:
return SoccerCommand( CMD_ATTENTIONTO, -1.0, -1.0 );
return SoccerCommand( CMD_ATTENTIONTO,
1.0, // 1.0 denotes our team
SoccerTypes::getIndex( obj ) + 1 );
}
/*! This method returns the command to tackle the ball. */
SoccerCommand BasicPlayer::tackle( )
{
return SoccerCommand( CMD_TACKLE, 100.0 );
}
/********************** INTERMEDIATE LEVEL SKILLS ****************************/
/*! This skill enables an agent to turn his body towards an object o which is
supplied to it as an argument. To this end the object's global position
o in the next cycle is predicted based on its current velocity.
This predicted position is passed as an argument to the turnBodyToPoint
skill which generates a turn command that causes the agent to turn his
body towards the object.
\param o object to which agent wants to turn
\return SoccerCommand that turns to this object */
SoccerCommand BasicPlayer::turnBodyToObject( ObjectT o )
{
return turnBodyToPoint( WM->predictPosAfterNrCycles(o, 1) );
}
///*! This skill enables an agent to turn his neck towards an object. It
// receives as arguments this object o as well as a primary action command
// 'soc' that will be executed by the agent at the end of the current cycle.
// Turning the neck towards an object amounts to predicting the object's
// global position in the next cycle and passing this predicted position
// together with the 'soc' command as arguments to the turnNeckToPoint skill.
// This low-level skill will then generate a turn neck command that causes the
// agent to turn his neck towards the given object. Note that the 'soc'
// command is supplied as an argument for predicting the agent's global
// position and neck angle after executing the command. This is necessary
// because a turn neck command can be executed in the same cycle as a kick,
// dash, turn , move or catch command.
// \param o object to which the agent wants to turn his neck
// \param soc SoccerCommand that is performed in this cycle.
// \return SoccerCommand that turns the neck of the agent to this object */
//SoccerCommand BasicPlayer::turnNeckToObject( ObjectT o, SoccerCommand soc )
//{
// return turnNeckToPoint( WM->predictPosAfterNrCycles(o, 1), soc );
//}
SoccerCommand BasicPlayer::directTowards( VecPosition posTurnTo,
AngDeg angWhenToTurn, VecPosition *pos, VecPosition *vel, AngDeg *angBody )
{
// return turnBodyToPoint( posTurnTo );
// copy values or initialize when not set
VecPosition posAgent= (pos ==NULL)?WM->getAgentGlobalPosition ():*pos;
VecPosition velAgent= (vel ==NULL)?WM->getAgentGlobalVelocity ():*vel;
AngDeg angBodyAgent= (angBody==NULL)?WM->getAgentGlobalBodyAngle():*angBody;
// first predict what happens when the agents rolls out.
VecPosition posPred = WM->predictFinalAgentPos();
AngDeg angTo = ( posTurnTo - posPred ).getDirection();
AngDeg ang = VecPosition::normalizeAngle( angTo - angBodyAgent );
AngDeg angNeck = 0;
int iTurn = 0;
while( fabs( ang ) > angWhenToTurn && iTurn < 5 )
{
iTurn++;
WM->predictStateAfterTurn(
WM->getAngleForTurn( ang, velAgent.getMagnitude() ),
&posAgent,
&velAgent,
&angBodyAgent,
&angNeck );
ang = VecPosition::normalizeAngle( angTo - angBodyAgent );
}
Log.log( 509, "direct towards: %d turns", iTurn );
posAgent = (pos ==NULL)?WM->getAgentGlobalPosition ():*pos;
velAgent = (vel ==NULL)?WM->getAgentGlobalVelocity ():*vel;
angBodyAgent = (angBody==NULL)?WM->getAgentGlobalBodyAngle():*angBody;
switch( iTurn )
{
case 0: cerr << "direct towards: 0 turns" ;
return SoccerCommand( CMD_ILLEGAL );
case 1:
case 2: return turnBodyToPoint( posTurnTo, 2 );
default: return dashToPoint(
(pos==NULL)?WM->getAgentGlobalPosition ():*pos ); // stop
}
}
/*! This skill enables an agent to move to a global position 'pos' on
the field which is supplied to it as an argument. Since the agent
can only move forwards or backwards into the direction of his
body, the crucial decision in the execution of this skill is
whether he should perform a turn or a dash. Turning has the
advantage that in the next cycle the agent will be orientated
correctly towards the point he wants to reach. However, it has the
disadvantage that performing the turn will cost a cycle and will
reduce the agent's velocity since no acceleration vector is added
in that cycle. Apart from the target position 'pos', this skill
receives several additional arguments for determining whether a
turn or dash should be performed in the current situation. If the
target point is in front of the agent then a dash is performed
when the relative angle to this point is smaller than a given
angle 'angWhenToTurn'. However, if the target point is behind the
agent then a dash is only performed if the distance to point is
less than a given value 'dDistBack' and if the angle relative to
the back direction of the agent is smaller than
'angWhenToTurn'. In all other cases a turn is performed. Note that
in the case of the goalkeeper it is sometimes desirable that he
moves backwards towards his goal in order to keep sight of the
rest of the field. To this end an additional boolean argument
'bMoveBack' is supplied to this skill that indicates whether the
agent should always move backwards to the target point. If this
value equals true then the agent will turn his back towards the
target point if the angle relative to his back direction is larger
than 'angToTurn'. In all other cases he will perform a (backward)
dash towards 'posTo' regardless of whether the distance to this
point is larger than 'dDistBack'.
\param posTo global target position to which the agent wants to move
\param angWhenToTurn angle determining when turn command is returned
\param dDistBack when posTo lies closer than this value to the back of
the agent (and within angWhenToTurn) a backward dash is returned
\param bMoveBack boolean determing whether to move backwards to 'posTo'
\return SoccerCommand that determines next action to move to 'posTo' */
SoccerCommand BasicPlayer::moveToPos( VecPosition posTo, AngDeg angWhenToTurn,
double dDistBack, bool bMoveBack, int iCycles )
{
// previously we only turned relative to position in next cycle, now take
// angle relative to position when you're totally rolled out...
// VecPosition posPred = WM->predictAgentPos( 1, 0 );
VecPosition posAgent = WM->getAgentGlobalPosition();
VecPosition posPred = WM->predictFinalAgentPos();
AngDeg angBody = WM->getAgentGlobalBodyAngle();
AngDeg angTo = ( posTo - posPred ).getDirection();
angTo = VecPosition::normalizeAngle( angTo - angBody );
AngDeg angBackTo = VecPosition::normalizeAngle( angTo + 180 );
double dDist = posAgent.getDistanceTo( posTo );
Log.log( 509, "moveToPos (%f,%f): body %f to %f diff %f now %f when %f",
posTo.getX(), posTo.getY(), angBody,
( posTo - posPred ).getDirection(), angTo,
( posTo - WM->predictAgentPos( 1, 0 )).getDirection(),
angWhenToTurn );
if( bMoveBack )
{
if( fabs( angBackTo ) < angWhenToTurn )
return dashToPoint( posTo, iCycles );
else
return turnBackToPoint( posTo );
}
else if( fabs( angTo ) < angWhenToTurn ||
(fabs( angBackTo ) < angWhenToTurn && dDist < dDistBack ) )
return dashToPoint( posTo, iCycles );
else
return directTowards( posTo, angWhenToTurn );
//return turnBodyToPoint( posTo );
}
/*! This method returns a command that can be used to collide with the ball
on purpose. When this is not possible. CMD_ILLEGAL is returned. Colliding
with the ball may be useful when the player is turned with his back to the
opponent goal and is intercepting a moving ball, by colliding both the ball
and the player will loose all their velocity. Now the player can turn at
once to the desired direction. Otherwise he first has to freeze the ball,
freeze his own speed and then turn around. */
SoccerCommand BasicPlayer::collideWithBall( )
{
SoccerCommand soc( CMD_ILLEGAL );
if( WM->getRelativeDistance( OBJECT_BALL ) >
WM->getBallSpeed() + SS->getPlayerSpeedMax() )
return soc;
VecPosition posBallPred = WM->predictPosAfterNrCycles( OBJECT_BALL, 1 );
// first try turn
soc = turnBodyToPoint( WM->getAgentGlobalPosition() +
VecPosition( 1, 0, POLAR ) );
VecPosition posAgentPred = WM->predictAgentPosAfterCommand( soc );
if( posAgentPred.getDistanceTo( posBallPred ) <
SS->getBallSize() + SS->getPlayerSize() )
{
Log.log( 511, "can collide with ball by turning" );
return soc;
}
soc = dashToPoint( posBallPred, 1 );
posAgentPred = WM->predictAgentPosAfterCommand( soc );
if( posAgentPred.getDistanceTo( posBallPred ) <
SS->getBallSize() + SS->getPlayerSize() )
{
Log.log( 511, "can collide with ball by dashing %f", soc.dPower );
return soc;
}
return SoccerCommand( CMD_ILLEGAL );
}
/*! This skill enables an agent to intercept a ball which is close to him. The
objective is to move in such a way that the ball will come within the
kickable distance from the agent in one or two cycles. To this end the
prediction methods from the world model are used to predict the ball
position in the next cycle and two cycles into the future. It is then
determined whether it is possible to move the agent within kickable
distance from one of these positions using all logical combinations of
turn and dash commands. If it is not possible to intercept the ball within
two cycles then this skill returns an illegal command to indicate that
it cannot be performed. First it is determined whether the agent can
intercept the ball in one cycle. To this end the position of the ball in
the next cycle is predicted and a calculation is performed to decide
whether a single dash can move the agent within the kickable distance from
this position. In order to be able to kick the ball efficiently after
intercepting it, it is important that the agent moves to a good position
relative to the ball (i.e. the ball must be in front of him). At the same
time the agent must make sure that he does not collide with the ball when
trying to intercept it. Let l be a line that runs forwards and backwards
from the predicted position of the agent in the next cycle into the
direction of his body. This line thus denotes the possible movement
direction of the agent. Note that we have to use the agent's predicted
position in the next cycle since his current velocity must be taken into
account. In addition, let c be a circle which is centered on the predicted
ball position and which has a radius equal to the sum of the radius of the
agent, the radius of the ball and a small buffer (kickable margin/6). It
is now determined whether the agent can intercept the ball in the next
cycle by looking at the number of intersection points between l and c. If
l and c have exactly one point in common then this point is the desired
interception point for the next cycle. However, if the number of
intersection points equals two then the desired point is the one for
which the absolute angle of the ball relative to that point is the
smallest. This amounts to the intersection point which is closest to
the agent when the ball lies in front of him and to the furthest one when
the ball is behind his back. As a result, the desired interception point
will always be such that the agent has the ball in front of him in the
next cycle. Then a dash command is generated
that will bring the agent as close as possible to the desired point.
Next, the position of the agent after executing this command is predicted
and if it turns out that this predicted position lies within the kickable
distance from the ball then the dash is performed. However, if the
predicted position is not close enough to the ball or if l and c have no
points in common then it is assumed that the ball cannot be intercepted
with a single dash. In these cases, two alternatives are explored to see
if the ball can be intercepted in two cycles.
The first alternative is to determine whether the agent can intercept the
ball by performing a turn followed by a dash. To this end the global
position of the ball is predicted two cycles into the future and a turn
command is generated that will turn
the agent towards this point. The agent's position after executing this
command is then predicted after which a dash command is generated
that will bring the agent as close as possible to
the predicted ball position in two cycles. If it turns out that the
predicted position of the agent after the dash lies within kickable
distance from the ball then the first command (i.e. the turn) in the
sequence of two is performed. Otherwise, a second alternative is tried to
determine whether the agent can intercept the ball by performing two dash
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -