📄 worldmodelpredict.cpp
字号:
{
angBody = ( angBodyIn == NULL ) ? getGlobalBodyAngle( obj ) : *angBodyIn;
pos = ( posIn == NULL ) ? getGlobalPosition ( obj ) : *posIn;
vel = ( velIn == NULL ) ? getGlobalVelocity ( obj ) : *velIn;
ang = (posTo - posPred).getDirection() + 180;
ang = VecPosition::normalizeAngle( ang - angBody );
soc = SoccerCommand(CMD_TURN,getAngleForTurn(ang,vel.getMagnitude(),obj));
predictStateAfterTurn( soc.dAngle,&pos,&vel,&angBody,&angNeck,obj,&sta);
line = Line::makeLineFromPositionAndAngle( posPred, angBody );
dDist = line.getDistanceWithPoint( posTo );
if( dDist < 0.9*getMaximalKickDist( obj ) )
{
Log.log( 463, "turn around and intercept with back" );
return soc;
}
}
return socFirst;
}
/*! This method returns the command to move to a position, first it checks
whether a turn is necessary. When this is the case, it performs the turn.
Otherwise a dash command is generated to move in 'iCycles' cycles to
the point 'posTo'. */
SoccerCommand WorldModel::predictCommandToMoveToPos( ObjectT obj,
VecPosition posTo, int iCycles, double dDistBack,
bool bMoveBack,VecPosition *posIn, VecPosition *velIn, AngDeg *angBodyIn)
{
VecPosition pos, vel;
AngDeg angBody;
SoccerCommand soc;
double dPower;
// fill in all values
angBody = ( angBodyIn == NULL ) ? getGlobalBodyAngle( obj ) : *angBodyIn;
pos = ( posIn == NULL ) ? getGlobalPosition ( obj ) : *posIn;
vel = ( velIn == NULL ) ? getGlobalVelocity ( obj ) : *velIn;
soc = predictCommandTurnTowards(obj, posTo, iCycles, dDistBack, bMoveBack,
posIn, velIn, angBodyIn);
if( ! soc.isIllegal() )
return soc;
dPower = getPowerForDash( posTo-pos, angBody, vel,getAgentEffort(),iCycles );
return SoccerCommand( CMD_DASH, dPower );
}
/*! This command returns the command for object 'obj' to intercept the ball.
It needs the command 'socClose' as the command to intercept a close ball
(may be CMD_ILLEGAL). 'iCycles' will be filled with the number of cycles
to get to this ball position and 'posIntercept' will be filled with the
final interception point. When posIn, velInn, angBody are equal to NULL,
the agent information is used in the calculations. */
SoccerCommand WorldModel::predictCommandToInterceptBall( ObjectT obj,
SoccerCommand socClose, int *iCycles, VecPosition *posIntercept,
VecPosition *posIn, VecPosition *velIn, AngDeg *angBodyIn )
{
FeatureT feature_type = FEATURE_INTERCEPTION_POINT_BALL;
// check whether we already have calculated this value
if( isFeatureRelevant( feature_type ) )
{
int i = max(0,((int)getFeature(feature_type).getInfo()-getCurrentCycle()));
if( iCycles != NULL )
*iCycles = i;
if( posIntercept != NULL )
*posIntercept = predictPosAfterNrCycles( OBJECT_BALL, i );
Log.log( 463, "intercept, use old info, feature %d: %d", feature_type,
max(0,((int)getFeature( feature_type ).getInfo()-getCurrentCycle())));
return getFeature( feature_type ).getCommand();
}
// declare all needed variables
SoccerCommand soc;
VecPosition pos, vel, posPred, posBall(0,0), posBallTmp, velBall, posAgent;
AngDeg angBody, angNeck;
int iMinCyclesBall=100, iFirstBall=100;
double dMaxDist = getMaximalKickDist( obj );
double dBestX = UnknownDoubleValue;
Stamina sta;
double dMinOldIntercept = 100, dDistanceOfIntercept = 10.0;
int iOldIntercept = UnknownIntValue;
static Time timeLastIntercepted(-1,0);
static VecPosition posOldIntercept;
// didn't intercept ball in last two cycles -> reset old interception point
if( (getCurrentTime() - timeLastIntercepted) > 2 )
posOldIntercept.setVecPosition( UnknownDoubleValue, UnknownDoubleValue);
timeLastIntercepted = getCurrentTime();
int iCyclesBall = 0;
Log.log( 468, "old interception point: (%f,%f)", posOldIntercept.getX(),
posOldIntercept.getY() );
// for each new pos of the ball, check whether agent can reach ball
// and update the best interception point
while( iCyclesBall <= PS->getPlayerWhenToIntercept() &&
iCyclesBall <= iFirstBall + 20 &&
isInField( posBall ) == true )
{
// re-initialize all variables
angBody = ( angBodyIn == NULL ) ? getGlobalBodyAngle( obj ) : *angBodyIn;
angNeck = getGlobalNeckAngle( obj );
pos = ( posIn == NULL ) ? getGlobalPosition ( obj ) : *posIn;
vel = ( velIn == NULL ) ? getGlobalVelocity ( obj ) : *velIn;
sta = getAgentStamina();
soc.commandType = CMD_ILLEGAL;
// predict the ball position after iCycles and from that its velocity
posBallTmp = predictPosAfterNrCycles( OBJECT_BALL, iCyclesBall );
if( iCyclesBall == 0 )
velBall = getGlobalVelocity( OBJECT_BALL );
else
velBall = posBallTmp - posBall;
posBall = posBallTmp;
// predict the agent position
posPred = predictPosAfterNrCycles( obj, min(iCyclesBall,4), 0 );
posAgent = getGlobalPosition( obj );
// if too far away, we can never reach it and try next cycle
if( posPred.getDistanceTo(posBall)/getPlayerSpeedMax( obj )
> iCyclesBall + dMaxDist || isInField( posBall ) == false )
{
iCyclesBall++;
continue;
}
// predict our position after the same nr of cycles when intercepting
for( int i = 0; i < iCyclesBall; i++ )
{
soc = predictCommandToMoveToPos( obj, posBall, iCyclesBall - i ,
2.5, false, &pos, &vel, &angBody );
predictStateAfterCommand( soc, &pos, &vel, &angBody, &angNeck, obj );
}
// if in kickable distance, we can reach the ball!
if (pos.getDistanceTo( posBall ) < dMaxDist )
{
Log.log( 468, "can intercept ball in %d cycles, dist %f, old %f obj %d",
iCyclesBall, pos.getDistanceTo( posBall ),
posBall.getDistanceTo( posOldIntercept ), obj );
if( iMinCyclesBall == 100 ) // log first possible interception point
iFirstBall = iMinCyclesBall = iCyclesBall;
// too get some consistency in the interception point and avoid
// too many turns, also keep track of the current possible
// interception point. This is the point close to the old
// interception point. Two constraints are that the ball has to
// have some speed (else it does not really matter where to
// intercept) and the ball must be intercepted safely, that is
// the ball is close to the body when intercepting.
if( posBall.getDistanceTo( posOldIntercept ) <
min( 1.0, dMinOldIntercept ) &&
pos.getDistanceTo( posBall ) < 0.70*getMaximalKickDist( obj ) &&
velBall.getMagnitude() > 0.6 )
{
Log.log( 468, "update old interception point %d", iCyclesBall );
dBestX = posBall.getX();
iOldIntercept = iCyclesBall;
dDistanceOfIntercept = pos.getDistanceTo( posBall );
dMinOldIntercept = posBall.getDistanceTo( posOldIntercept );
}
// determine the safest interception point. This point must be
// better than the current intercept, the distance to ball must
// be very small after interception and close to the previous
// calculated interception point
else if( pos.getDistanceTo( posBall ) < dDistanceOfIntercept &&
dDistanceOfIntercept > 0.50*getMaximalKickDist( obj ) &&
( iCyclesBall <= iMinCyclesBall + 3 ||
iCyclesBall <= iOldIntercept + 3 ) &&
fabs( posBall.getY() ) < 32.0 &&
fabs( posBall.getX() ) < 50.0 )
{
iMinCyclesBall = iCyclesBall;
dDistanceOfIntercept = pos.getDistanceTo( posBall );
Log.log( 468, "safer interception at %d", iMinCyclesBall );
if( iOldIntercept == iMinCyclesBall - 1 )
{
Log.log( 468, "old interception point -> safer" );
iOldIntercept = iMinCyclesBall;
}
}
}
else
Log.log( 468, "cannot intercept ball in %d cycles, dist %f, %f and %f",
iCyclesBall, pos.getDistanceTo(posBall), pos.getDistanceTo( posAgent ),
posBall.getDistanceTo( posAgent ) - dMaxDist);;
iCyclesBall++;
}
Log.log( 463, "first interception point: %d cycles", iFirstBall );
Log.log( 463, "best interception point: %d cycles", iMinCyclesBall );
Log.log( 463, "old interception point %d cycles", iOldIntercept );
// check special situations where we move to special position.
if( !( iMinCyclesBall > iOldIntercept + 2 ) &&
iOldIntercept != UnknownIntValue )
{
Log.log( 463, "move to old interception point." );
iMinCyclesBall = iOldIntercept;
}
else
{
Log.log( 463, "move to first intercept" );
iMinCyclesBall = iFirstBall;
}
posBall = predictPosAfterNrCycles( OBJECT_BALL, iMinCyclesBall );
Log.log( 463, "choose %d cycles", iMinCyclesBall );
logCircle( 463, posBall, 1.0 );
if( iCycles != NULL )
*iCycles = iMinCyclesBall;
posOldIntercept = posBall;
posPred = predictPosAfterNrCycles( obj, min(iMinCyclesBall,4), 0 );
if( posIntercept != NULL )
*posIntercept = posBall;
if( iMinCyclesBall < 3 && ! socClose.isIllegal() )
{
Log.log( 463, "do close intercept" );
iMinCyclesBall = 1;
soc = socClose;
}
else if( posPred.getDistanceTo( posBall ) < 0.5 )
{
Log.log( 463, "intercept: do not move already close" );
soc = SoccerCommand( CMD_ILLEGAL );
}
else
{
Log.log( 463, "intercept: move to (%f,%f)", posBall.getX(),posBall.getY());
Log.log( 560, "intercept: move to (%f,%f) in %d cycles",
posBall.getX(),posBall.getY(), iMinCyclesBall);
if( isDeadBallUs() && !isGoalKickUs()) // do not dash backwards
soc = predictCommandToMoveToPos( obj, posBall, iMinCyclesBall, 0 );
else
soc = predictCommandToMoveToPos( obj, posBall, iMinCyclesBall );
}
// store the calculated action as a feature
if( obj == getAgentObjectType() )
setFeature( feature_type,
Feature( getTimeLastSeeMessage(),
getTimeLastSenseMessage(),
getTimeLastHearMessage(),
OBJECT_ILLEGAL,
getTimeLastSeeMessage().getTime() + iMinCyclesBall,
soc ) );
return soc;
}
/*! This method determines whether a dash command (supplied as the first
argument) will result in collision with another player.
This is checked by determing the global position after the command
and then check whether the positions of one of the other players lies
with the player size. Since it cannot be known what kind of action the
other player takes in this cycle, it is also difficult to predict what the
global position of the player will be in the next cycle. This method
therefore assumes the other players have issued a dash with maximum power
in the last cycle.
\return bool indicating whether dash will result in a collision. */
bool WorldModel::isCollisionAfterCommand( SoccerCommand soc )
{
VecPosition posPred, velPred;
AngDeg ang1, ang2;
Stamina sta;
predictAgentStateAfterCommand( soc, &posPred, &velPred, &ang1,&ang2,&sta );
velPred /= SS->getPlayerDecay();
VecPosition posBall = predictPosAfterNrCycles( OBJECT_BALL, 1 );
if( soc.commandType == CMD_KICK )
predictBallInfoAfterCommand( soc, &posBall );
double dDist = posPred.getDistanceTo( posBall ) -
SS->getPlayerSize() - SS->getBallSize();
Log.log( 510, "check collision dist %f, noise_ball %f noise_me %f",
dDist, getBallSpeed()*SS->getBallRand(),
velPred.getMagnitude()*SS->getPlayerRand() );
// we could also take into account the error in player movement, but this
// is very large, so we would in many cases get a dash
if( dDist < getBallSpeed()*SS->getBallRand() )
return true;
return false;
}
//预测当前情况下,假设球速度为velBall
//o去截球的截球周期
int WorldModel::predictInterCyc(ObjectT o, const VecPosition& posBall, const VecPosition& velBall)
{
interUtil.ballPos = posBall;
interUtil.playerPos = getGlobalPosition(o);
interUtil.playerVel = getGlobalVelocity(o);
interUtil.angBody = getGlobalBodyAngle(o);
interUtil.maxSpeed = getPlayerSpeedMax(o);
interUtil.maxDashEffect = SS->getMaxPower() * getDashPowerRate(o) *getEffortMax(o);
if (o==getOppGoalieType()||o==getOwnGoalieType())
interUtil.kickableArea = SS->getCatchableAreaL();
else
interUtil.kickableArea = getMaximalKickDist(o);
return interUtil.getInterceptCyc(velBall);
}
int WorldModel::predictFastestOppInterCyc(const VecPosition& posBall, const VecPosition& velBall)
{
int minCyc = 100;
int iIndex;
for( ObjectT o = iterateObjectStart( iIndex, OBJECT_SET_OPPONENTS, 0 );
o != OBJECT_ILLEGAL;
o = iterateObjectNext ( iIndex, OBJECT_SET_OPPONENTS, 0 ) )
{
int cyc = predictInterCyc(o, posBall, velBall);
if (cyc<minCyc)
minCyc = cyc;
}
iterateObjectDone( iIndex );
return minCyc;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -