⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 basicplayer.cpp

📁 自己写的robocup-2d程序
💻 CPP
📖 第 1 页 / 共 5 页
字号:

  // cannot intercept ball in three cycles
  WM->setFeature( feature_type,
              Feature( WM->getTimeLastSeeMessage(),
                       WM->getTimeLastSenseMessage(),
                       WM->getTimeLastHearMessage(),                       
                       OBJECT_ILLEGAL,
                       -1,
                       socFinal ) );
  return socFinal;
}

/*! This skill enables a goalkeeper 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
    catchable 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 the
    catchable area 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 goalkeeper
    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 catchable distance from
    this position. If it turns out that this is the case, the corresponding
    dash is performed. However, if the predicted position is not close enough
    to the ball 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 two dash commands. To this end two dash commands are
    generated. If the predicted position of the agent after these two
    dashes lies within catchable distance from the ball then the first dash is
    performed. Otherwise, a second alternative is tried 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. If it turns out that the predicted position of the agent
    after the dash lies within catchable distance from the ball then the first
    command (i.e. the turn) in the sequence of two is performed.
    Otherwise, an illegal command is returned to indicate that the
    skill cannot be performed. The close interception procedure is heavily
    based on the method used by CMU'99 by Peter Stone.
    \return command to intercept ball in two cycles, CMD_ILLEGAL otherwise */
SoccerCommand BasicPlayer::interceptCloseGoalie( )
{
  SoccerCommand soc;
  double        dPower, dDist;
  AngDeg        ang;
  VecPosition   posClosestToBall;

  // initialize all variables with information from worldmodel.
  VecPosition   posPred   = WM->predictAgentPos( 1, 0 );
  VecPosition   posBall   = WM->predictPosAfterNrCycles( OBJECT_BALL, 1 );
  VecPosition   velMe     = WM->getAgentGlobalVelocity( );
  Stamina       sta       = WM->getAgentStamina( );
  AngDeg        angBody   = WM->getAgentGlobalBodyAngle( );
  Line          lineGoalie=Line::makeLineFromPositionAndAngle(posPred,angBody);

  // when it is theoretical possible
  // try one dash and check whether ball is in catchable area
  dDist =SS->getBallSpeedMax()+SS->getPlayerSpeedMax()+SS->getCatchableAreaL();
  if( WM->getRelativeDistance( OBJECT_BALL ) < dDist )
  {
    posClosestToBall = lineGoalie.getPointOnLineClosestTo( posBall );
    dPower           = WM->getPowerForDash(
                          posClosestToBall-posPred,
                          angBody,
                          velMe,
                          sta.getEffort()           );
    posPred          = WM->predictAgentPos( 1, (int)dPower);
    if ( posPred.getDistanceTo( posBall ) < SS->getCatchableAreaL() )
      return SoccerCommand( CMD_DASH, dPower );
  }

  // when it is theoretical possible
  // try two dashes and check whether ball is in catchable area
  // otherwise try first two  dashes and check whether ball is in catchable
  // area, thereafter for turn and dash.
  dDist = SS->getBallSpeedMax()*(1.0+SS->getBallDecay())
           + 2*SS->getPlayerSpeedMax()
           + SS->getCatchableAreaL();
  if( WM->getRelativeDistance( OBJECT_BALL ) < dDist )
  {
    // try two dashes
    // first predict the position in the next cycle when dash with full power
    // is performed. Then calculate the dash power to reach the point where the
    // ball will be in two cycles and predict the global position of the agent
    // after a dash with this power. If the position is in the catchable area
    // return a dash with full power.
    posBall = WM->predictPosAfterNrCycles( OBJECT_BALL, 2 );
    soc     = dashToPoint( posBall );
    WM->predictAgentStateAfterCommand(soc,&posPred,&velMe,&angBody,&ang,&sta );
    dPower=WM->getPowerForDash(posBall-posPred,angBody,velMe,sta.getEffort());
    WM->predictStateAfterDash( dPower, &posPred, &velMe, &sta, angBody,
                               WM->getAgentObjectType() );
    if( posPred.getDistanceTo(posBall) < SS->getCatchableAreaL() )
      return soc;

    // try one turn and a dash
    posBall = WM->predictPosAfterNrCycles( OBJECT_BALL, 2 );
    posPred = WM->predictAgentPos( 2, 0 );
    ang     = (posBall - posPred).getDirection();
    ang     = VecPosition::normalizeAngle( ang - angBody );
    if (fabs( ang ) > PS->getPlayerWhenToTurnAngle() ) // if we want to turn
    {
      soc = turnBodyToPoint( posBall, 2 );             // perform turn
      WM->predictAgentStateAfterCommand(soc,&posPred,&velMe,&angBody,&ang,&sta
);
      dPower=WM->getPowerForDash(posBall-posPred, angBody, 
                                 velMe, sta.getEffort());
      WM->predictStateAfterDash( dPower, &posPred, &velMe, &sta, angBody);
      if( posPred.getDistanceTo(posBall) < SS->getCatchableAreaL() )
        return soc;
    }
  }

  // did not succeed
  return SoccerCommand( CMD_ILLEGAL );
}

/*! This skill enables an agent to kick the ball from its current
    position to a given position 'posTarget' in such a way that it has
    a remaining speed equal to 'dEndSpeed' when it reaches this
    position. However, it is possible that the ball cannot reach this
    velocity with a single kick either because the needed magnitude of
    the generated velocity vector exceeds the maximum speed of the
    ball or due to the fact that the current ball speed in combination
    with the position of the ball relative to the agent make it
    impossible to achieve the required acceleration. If the magnitude
    of needed velocity vector is larger than ball speed max it is
    certain that even in the optimal situation (i.e. if the ball lies
    directly in front of the agent and has zero velocity) the agent
    will not be able to kick the ball to the target position at the
    desired speed. In this case the expected ball movement is computed
    after executing a kick with maximum power into the direction of
    'posTarget'.  If the magnitude of the resulting movement vector is
    larger than a given percentage ('getPlayerWhenToKick' defined in
    the PlayerSettings) of the maximum ball speed then this kick is
    actually performed despite the fact that it cannot produce the
    wanted effect. Otherwise, the agent shoots the ball close to his
    body and directly in front of him using the kickBallCloseToBody
    skill. In this way he will be able to kick the ball with more
    power in the next cycle. However, if the magnitude of the desired
    velocity vector is smaller than ball speed max it is possible to
    reach the target point at the desired speed in the optimal
    situation.  If the power that must be supplied to the kick command
    to achieve this acceleration is less than or equal to the maximum
    power the accelerateBallToVelocity skill is used to perform the
    desired kick.  Otherwise, the agent uses the kickBallCloseToBody
    skill to put the ball in a better kicking position for the next
    cycle.

   \param posTarget target position where the ball should be shot to
   \param endSpeed desired speed ball should have in target position
   \return SoccerCommand that produces kick  */
SoccerCommand BasicPlayer::kickTo( VecPosition posTarget, double dEndSpeed )
{
  VecPosition posBall  = WM->getBallPos();
  VecPosition velBall  = WM->getGlobalVelocity(OBJECT_BALL);
  VecPosition posTraj  = posTarget - posBall;
  VecPosition posAgent = WM->getAgentGlobalPosition();
  VecPosition velDes   = VecPosition(
               WM->getKickSpeedToTravel( posTraj.getMagnitude(), dEndSpeed ),
               posTraj.getDirection(),
               POLAR                                                       ); 
  double      dPower;
  AngDeg      angActual;

  if( WM->predictAgentPos(1, 0 ).getDistanceTo( posBall + velDes ) < 
      SS->getBallSize() + SS->getPlayerSize() )
  {
    Line line = Line::makeLineFromTwoPoints( posBall, posBall + velDes );
    VecPosition posBodyProj = line.getPointOnLineClosestTo( posAgent );
    double dDist = posBall.getDistanceTo( posBodyProj );
    if( velDes.getMagnitude() < dDist )
      dDist -=  SS->getBallSize() + SS->getPlayerSize();
    else
      dDist +=  SS->getBallSize() + SS->getPlayerSize();
    Log.log( 101, "kick results in collision, change velDes from (%f,%f)",
	     velDes.getX(), velDes.getY() );
    velDes.setVecPosition( dDist, velDes.getDirection(), POLAR );
  }

  Log.log( 101, "ball (%f,%f), agent (%f,%f), to (%f,%f) ang %f %f" ,
          WM->getBallPos().getX(), WM->getBallPos().getY(),
          WM->getAgentGlobalPosition().getX(),
          WM->getAgentGlobalPosition().getY(),
          posTarget.getX(), posTarget.getY(),
          WM->getAgentGlobalBodyAngle(),
          WM->getAgentGlobalNeckAngle() );
  Log.log( 101, "relpos body (%f,%f), vel. ball:(%f,%f) dist: %f (%f,%f,%f)" ,
          WM->getRelativeDistance( OBJECT_BALL ),
          WM->getRelativeAngle( OBJECT_BALL, true ),
           velBall.getX(), velBall.getY(),
           SS->getMaximalKickDist(), SS->getPlayerSize(), SS->getBallSize(),
             SS->getKickableMargin() );


  double   dDistOpp;
  ObjectT  objOpp     = WM->getClosestInSetTo( OBJECT_SET_OPPONENTS, 
                                                 OBJECT_BALL, &dDistOpp );

  if( velDes.getMagnitude() > SS->getBallSpeedMax() ) // can never reach point
  {
             dPower     = SS->getMaxPower();
    double   dSpeed     = WM->getActualKickPowerRate() * dPower;
    double   tmp        = velBall.rotate(-velDes.getDirection()).getY();
             angActual  = velDes.getDirection() - asinDeg( tmp / dSpeed );
    double   dSpeedPred = (WM->getGlobalVelocity(OBJECT_BALL)+
                           VecPosition(dSpeed,angActual, POLAR )
                          ).getMagnitude();
  
    // but ball acceleration in right direction is very high
    if( dSpeedPred > PS->getPlayerWhenToKick()*SS->getBallAccelMax() )
    {
      Log.log( 101, "pos (%f,%f) too far, but can acc ball good to %f k=%f,%f",
               velDes.getX(), velDes.getY(), dSpeedPred, dSpeed, tmp );
      return accelerateBallToVelocity( velDes );    // shoot nevertheless
    }
    else if( WM->getActualKickPowerRate() >
             PS->getPlayerWhenToKick() * SS->getKickPowerRate() )
    {
      Log.log( 101, "point too far, freeze ball" ); // ball well-positioned
      return freezeBall();                          // freeze ball
    }
    else
    {
      Log.log( 101, "point too far, reposition ball (k_r = %f)",
               WM->getActualKickPowerRate()/(SS->getKickPowerRate()) );
      return kickBallCloseToBody( 0 );            // else position ball better
    }
  }
  else                                            // can reach point
  {
    VecPosition accBallDes = velDes - velBall;
    dPower = WM->getKickPowerForSpeed(accBallDes.getMagnitude());
    if( dPower <= 1.05*SS->getMaxPower() || // with current ball speed
	(dDistOpp < 2.0 && dPower <= 1.30*SS->getMaxPower() ) )
    {                               // 1.05 since cannot get ball fully perfect
      Log.log( 101, "point good and can reach point %f", dPower );
      return accelerateBallToVelocity( velDes );  // perform shooting action
    }
    else
    {
      Log.log( 101, "point good, but reposition ball since need %f",dPower );
      SoccerCommand soc = kickBallCloseToBody( 0 );
      VecPosition   posPredBall;
      WM->predictBallInfoAfterCommand( soc, &posPredBall );
      dDistOpp = posPredBall.getDistanceTo( WM->getGlobalPosition( objOpp ) );
      return soc;            // position ball better
    }
  }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -