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

📄 worldmodelpredict.cpp

📁 根据 trilearn_base_sources-3.3 (一般称做UVA底层)修改的robocup球队代码,对某些模块进行了详细的注释(例如BasicPlayer,WorldMode模块),并且进行
💻 CPP
📖 第 1 页 / 共 4 页
字号:
    Log.log( 560, "intercept: move to (%f,%f) in %d cycles",              posTo.getX(),posTo.getY(), iCycle);    //是我们的死球,并且不是门球    if( isDeadBallUs() && !isGoalKickUs())     // do not dash backwards      //不向后跑,就是说优先转身,然后跑向目标点      soc = predictCommandToMoveToPos( obj, posTo, iCycle, 0 );    else      //预测跑向目标点的指令      soc = predictCommandToMoveToPos( obj, posTo, iCycle );  }  //返回指令  return soc;}/*! 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, velIn, angBodyIn are equal to NULL,    the agent information is used in the calculations. *//*  返回obj物体截球的指令。它需要利用interceptClose指令返回的指令去截住近距离的球。    iCycles记录了截球需要周期数,posIntercept记录了最终的截球点。    posIn,velIn,angBodyIn都是NULL时,将取得当前球员的状态用来计算。*/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;//用来取得(/预测)球员的位置和速度  Stamina       sta;//用来取得(/预测)球员的体力  VecPosition   posPred, posBall(0,0), posBallTmp, velBall, posAgent;//...  AngDeg        angBody, angNeck;//...  double        dMaxDist = getMaximalKickDist( obj );//取得最大可踢距离  int           iMinCyclesBall=100, iFirstBall=100;//记录最小周期截球点,首个截球点  double        dBestX = UnknownDoubleValue;//最佳截球X坐标  double        dMinOldIntercept = 100;//求新的截球点和原来截球点的距离  double        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();  }  Log.log( 468, "old interception point: (%f,%f)", posOldIntercept.getX(),   posOldIntercept.getY() );  // 对于之后球会到达的所有的点,取得最佳截球点  int iCyclesBall = 0;  // 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 + 10 && //这个条件主要用于选择最佳截球点         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    // 从球当前的速度预测出球在iCycles周期后的位置以及速度    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    // 如果太远了,我们不可能到达那里,尝试更多的周期能否到达    // 或者是球已经出界了,同样通过"continue"可以在循环判断条件时退出循环    if((posPred.getDistanceTo(posBall)-dMaxDist)/getPlayerSpeedMax(obj)          > iCyclesBall || isInField( posBall ) == false )    {      iCyclesBall++;      continue;    }    // predict our position after the same nr of cycles when intercepting    // 预测我们在iCyclesBall周期的截球动作后所在的位置    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  );      //计算出的第一个截球点,不仅记录到iMinCyclesBall,还要记录到iFirstBall      if( iMinCyclesBall == 100 ) // log first possible interception point        iFirstBall = iMinCyclesBall = iCyclesBall;      // to 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.60*getMaximalKickDist( obj ) &&          velBall.getMagnitude() > 0.5 )      {        Log.log( 468, "update old interception point %d", iCyclesBall );        dBestX           = posBall.getX();//记录最佳截球X坐标        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.40*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 )//如果截球周期相差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.  // 判断特征状态/局势,我们移动到哪个特征点  // 如果最佳截球点和最快截球点相差不超过2个周期  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;  //记录计算出的截球点,和obj物体随惯性会移动到的位置  posOldIntercept = posBall;  posPred = predictPosAfterNrCycles( obj, min(iMinCyclesBall,4), 0 );  //返回截球点  if( posIntercept != NULL )    *posIntercept = posBall;  //如果截球周期小于三,并且socClose不是无效的,直接用socClose  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  // 把计算的结果记录到 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;}

⌨️ 快捷键说明

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