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

📄 basicplayer.cpp

📁 根据 trilearn_base_sources-3.3 (一般称做UVA底层)修改的robocup球队代码,对某些模块进行了详细的注释(例如BasicPlayer,WorldMode模块),并且进行
💻 CPP
📖 第 1 页 / 共 5 页
字号:
    //不需要转体的时候    if( fabs( angBackTo ) < angWhenToTurn )      return dashToPoint( posTo, iCycles );    //否则将背对的方向转向目标点    else      return turnBackToPoint( posTo );  }  //正常的跑动情况,如果小于转体条件就冲刺  else if(  fabs( angTo     ) < angWhenToTurn )    return dashToPoint( posTo, iCycles );  //满足了向后跑的条件  //因为向后跑的时候一般需要尽量面对球,所以将目标位置向后平移了1米  else if(fabs( angBackTo ) < angWhenToTurn && dDist < dDistBack )     return dashToPoint( posTo-VecPosition(1,0), iCycles );  //否则首先转体,准备下次的冲刺  else    return directTowards( posTo, angWhenToTurn );}/*! 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    commands. To this end two dash commands are generated to get closer to the    predicted ball position after two cycles.    If the predicted position of the agent after these two dashes lies within    kickable distance from the ball then the first dash is performed.    Otherwise, an illegal command is returned to indicate that the skill    cannot be performed. The close interception procedure is heavily based on    a similar method introduced in CMU'99 by Peter Stone.    \return command to intercept ball in two cycles, CMD_ILLEGAL otherwise *//*  2个周期内能截球的话就去截球,否则返回一个错误指令。    实际上使用的方法就是测试2个周期的dash和turn指令配合可否冲到球附近 */SoccerCommand BasicPlayer::interceptClose( ){  FeatureT feature_type = FEATURE_INTERCEPT_CLOSE;  if( WM->isFeatureRelevant( feature_type ) )    return WM->getFeature( feature_type ).getCommand();  SoccerCommand socDash1(CMD_ILLEGAL),socFinal(CMD_ILLEGAL),                socCollide(CMD_ILLEGAL),soc(CMD_ILLEGAL),socTurn(CMD_ILLEGAL);  double        dPower, dDist;  // first determine whether the distance to the ball is not too large  // 首先判断球的距离是不是太远,太远两个周期的动作是不可能触球的  // 这里加入了角度的影响,不用角度不同的距离判断  // 判断球速度的角度angBallMove和球相对于球员的角度angAgentToBall  // 以及球是否正在向球员的方向移动angX(angX==0表示在向球员移动,==180则是远离)  AngDeg angBallMove,angAgentToBall,angX;  angBallMove = WM->getGlobalVelocity(OBJECT_BALL).getDirection();  angAgentToBall = WM->getRelativePosition(OBJECT_BALL).getDirection();  angX = fabs( angBallMove - (angAgentToBall + 180.0) );  //根据角度的不同指定不同的最大距离  if(angX<45.0)  {    dDist = 2 * SS->getPlayerSpeedMax()            + 2.7 * SS->getBallSpeedMax()            + SS->getMaximalKickDist();  }  else if(angX>135.0)  {    dDist = 2 * SS->getPlayerSpeedMax()            - 1.9 * SS->getBallSpeedMax()            + SS->getMaximalKickDist();  }  else if(angX>90.0)  {    dDist = 2 * SS->getPlayerSpeedMax()            + 1.9 * SS->getBallSpeedMax()            + SS->getMaximalKickDist();  }  else  {    dDist = 2 * SS->getPlayerSpeedMax()            + SS->getMaximalKickDist();  }  // initialize all variables with information from the worldmodel.  // 从世界模型取得所有的初始化状态  VecPosition   posAgent = WM->getAgentGlobalPosition( );  VecPosition   posPred  = WM->predictAgentPos( 1, 0 ), posDash1;  VecPosition   posBall  = WM->predictPosAfterNrCycles( OBJECT_BALL, 1 );  VecPosition   velMe    = WM->getAgentGlobalVelocity( );  Stamina       sta      = WM->getAgentStamina( );  AngDeg        angBody  = WM->getAgentGlobalBodyAngle( ), angNeck=0;  //期望截球后方向为向前  double        dDesBody = 0.0;  // our desired heading after the intercept is 0 degrees, only when we  // are far up front we want to be headed toward the opponent goal  // 当我们现在的X坐标已经超过对方的禁区线时  if( posAgent.getX() > PENALTY_X )    //取得球门到我们的方向为期望方向    dDesBody = (WM->getPosOpponentGoal()-posAgent).getDirection();  //略微调整期望朝向,使得朝向靠近球门两侧  dDesBody -= sign(dDesBody)*10.0;  //转身起始角度阀值  AngDeg angThreshold = 25.0;  // get the distance to the closest opponent  // 取得现在距离当前球员的最近敌方球员  double dDistOppA;  ObjectT objOppA = WM->getClosestInSetTo( OBJECT_SET_OPPONENTS,    posAgent, &dDistOppA );  // 取得现在距离足球的最近敌方球员  double dDistOppB;  ObjectT objOppB = WM->getClosestInSetTo( OBJECT_SET_OPPONENTS,    posBall, &dDistOppB );  // check the distance to the ball when we do not dash (e.g., and only turn)  // 我们不选择冲刺的时候 判断到球的距离,这里预测了三个周期内到球的距离  // 这里似乎仅仅是记录一个日志,并没有实际用途  VecPosition posPred1 = WM->predictAgentPos( 1, 0 );  double dDist1 = posPred1.getDistanceTo( posBall );  posBall = WM->predictPosAfterNrCycles( OBJECT_BALL, 2 );  VecPosition posPred2 = WM->predictAgentPos( 2, 0 );  double dDist2 = posPred2.getDistanceTo( posBall );  posBall = WM->predictPosAfterNrCycles( OBJECT_BALL, 3 );  VecPosition posPred3 = WM->predictAgentPos( 3, 0 );  double dDist3 = posPred3.getDistanceTo( posBall );  Log.log( 508, "dist 1: %f, 2: %f 3: %f, 0.6: %f", dDist1, dDist2, dDist3,                                        0.7*SS->getMaximalKickDist() );  //记录是否有球员靠近当前球员(3米以内)  bool   bOppCloseA = ( objOppA != OBJECT_ILLEGAL && dDistOppA < 3.0 )  ;  //记录是否有球员靠近足球(3米以内)  bool   bOppCloseB = ( objOppB != OBJECT_ILLEGAL && dDistOppB < 3.0 )  ;  //记录是不是有对方球员靠近球或者当前队员  bool   bOppClose = bOppCloseA || bOppCloseB;  //取得期望目标角度和当前身体的相对角度 -> angTurn  double angTurn =VecPosition::normalizeAngle(dDesBody-WM->getAgentGlobalBodyAngle());  // make a line from center of body in next cycle with direction of body  // use next cycle since current velocity is always propogated to position in  // next cycle.  Make a circle around the ball with a radius equal to the  // sum of your own body, the ball size and a small buffer. Then calculate  // the intersection between the line and this circle. These are the (two)  // points that denote the possible agent locations close to the ball  // From these two points we take the point where the body direction of the  // agent makes the smallest angle with the ball (with backward  // dashing we sometime have to dash "over" the ball to face it up front)  // 以下一个周期身体的方向生成一条直线,然后以足球为圆心生成一个圆,圆的半径为球员的身体尺寸+球的尺寸+  // 一个可踢球距离~然后计算他们的相交点,在这两个交点中我们将选择一个相对较好的点,如果是背向球跑的话  // 一般还会多跑一段距离以保证球在我们的面前。  Line line = Line::makeLineFromPositionAndAngle(posPred1,angBody);  dDist     = SS->getPlayerSize()+SS->getBallSize()+SS->getMaximalKickDist()/6.0;  VecPosition s1,s2;  AngDeg      ang;  int  iSol = line.getCircleIntersectionPoints(Circle(posBall,dDist), &s1, &s2);

⌨️ 快捷键说明

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