📄 basicplayer.cpp
字号:
//如果有交点的话 if (iSol > 0) { //选择两个交点中间的点 if (iSol == 2) { s1=(s1+s2)/2.0; ang = VecPosition::normalizeAngle((posBall - s1).getDirection() -angBody); } // try one dash // 尝试一次冲刺 // now we have the interception point we try to reach in one cycle. We // calculate the needed dash power from the current position to this point, // predict were we will stand if we execute this command and check whether // we are in the kickable distance // 现在我们尝试在一个周期以内截球,计算~~~ dPower = WM->getPowerForDash(s1-posAgent, angBody, velMe,sta.getEffort() );//冲刺需要的力量 posDash1 = WM->predictAgentPos(1, (int)dPower);//预测一个周期后用这个力量可以冲刺到的点 // 可以冲刺到的话就去截球 if ( posDash1.getDistanceTo( posBall ) < 0.9*SS->getMaximalKickDist() ) { Log.log( 508, "dash 1x possible at s1" ); socDash1 = SoccerCommand( CMD_DASH, dPower ); } } // try one dash by getting close to ball // 尝试一次冲刺去靠近球 // this handles situation where ball cannot be reached within distance KickableMargin/6 // 这里无效指令表示第一次的冲刺指令没有实现,无法冲刺到可踢距离的1/6以内 if( socDash1.commandType == CMD_ILLEGAL ) { //尝试向球的方向靠近,如果一次冲刺可以靠近球到一定的范围,选择冲刺 soc = dashToPoint( posBall ); WM->predictAgentStateAfterCommand(soc,&posDash1,&velMe, &angBody,&ang,&sta ); if ( posDash1.getDistanceTo( posBall ) < 0.9*SS->getMaximalKickDist() ) { Log.log( 508, "dash 1x possible (special)" ); socDash1 = soc; } } //在距离不是很远的时候(可能截球的时候) if( WM->getRelativeDistance( OBJECT_BALL ) < dDist ) { //附近有球员而且指令1不是无效指令(表示前面已经决定向球冲刺) if( bOppClose && ! socDash1.isIllegal() ) { //最终指令确定为向球冲刺 Log.log( 508, "do dash 1x, opponent close" ); WM->logCircle( 508, posDash1, SS->getMaximalKickDist(), true ); socFinal = socDash1; } else { //否则尝试先转身(转身到期望方向) soc = turnBodyToPoint( posPred1 + VecPosition(1.0,dDesBody, POLAR), 1 ); //预测转身指令之后球员的状态 WM->predictAgentStateAfterCommand(soc, &posPred, &velMe, &angBody, &ang, &sta); //重新预测球的位置 posBall = WM->predictPosAfterNrCycles( OBJECT_BALL, 1 ); //如果转身更有利于下一步截球 if( posPred.getDistanceTo( posBall ) < 0.8*SS->getMaximalKickDist() ) { socTurn = soc; // we can do turn and end up ok, but can maybe improve ang = VecPosition::normalizeAngle(dDesBody-angBody); //角度绝对值在阀值以内的话(表示可以转到期望角度) if( fabs(ang) < angThreshold ) { //选择最后的指令为转身 socFinal = soc; Log.log( 508, "turn 1x, dist %f, angle %f, opp %f", dDist1, angTurn, dDistOppA ); WM->logCircle( 508, posPred1, SS->getMaximalKickDist(), true ); } } //如果到了这里,最终指令仍就没有确定的话 if( socFinal.isIllegal() ) { ang = VecPosition::normalizeAngle(dDesBody-angBody); WM->predictStateAfterTurn( WM->getAngleForTurn(ang,velMe.getMagnitude()), &posPred, &velMe, &angBody, &angNeck, WM->getAgentObjectType(), &sta ); //这里是如果转身可以在两个周期后触球,就进行转身,这样是可以提高截球成功率的 posBall = WM->predictPosAfterNrCycles( OBJECT_BALL, 2 ); if( posPred.getDistanceTo( posBall ) < 0.8*SS->getMaximalKickDist() ) { socTurn = soc; // we can do turn and end up ok, but can maybe improve ang = VecPosition::normalizeAngle(dDesBody-angBody); //这里的条件是表示转身动作可以完成 if( fabs(ang) < angThreshold ) { Log.log( 508, "turn 2x, dist %f, angle %f, opp %f", dDist2, angTurn, dDistOppA ); WM->logCircle( 508, posPred2, SS->getMaximalKickDist(), true ); socFinal = soc; } } } //调用触球指令 socCollide = collideWithBall( ); //最终指令没有指定,但是触球指令却有效&&转身角度>25的时候 //这时候是转身发完成的情况,就可以考虑首先触球让球停下,然后再去转身 if( socFinal.isIllegal() && ! socCollide.isIllegal() && fabs( angTurn ) > angThreshold ) { //触球指令 Log.log( 508, "collide with ball on purpose" ); posBall = WM->predictPosAfterNrCycles( OBJECT_BALL, 1 ); WM->logCircle( 508, posBall, SS->getMaximalKickDist(), true ); socFinal = socCollide; } //触球仍旧无效的情况下,判断冲刺一次会不会在两个周期后取得球 if( socFinal.isIllegal() && fabs( angTurn ) > angThreshold ) { //预测两个周期之后球的位置 posBall = WM->predictPosAfterNrCycles( OBJECT_BALL, 2 ); soc = dashToPoint( posBall ); WM->predictAgentStateAfterCommand(soc, &posPred,&velMe,&angBody,&ang,&sta ); //预测的点在最大踢球范围之内,冲刺一次 if( posPred.getDistanceTo( posBall ) < 0.8*SS->getMaximalKickDist() ) { Log.log( 508, "dash 1x (stop), turn 1x, dist %f, angle %f, opp %f", dDist2, angTurn, dDistOppA ); WM->logCircle( 508, posPred, SS->getMaximalKickDist(), true ); socFinal = soc; } } //以下这两个if可能用于排除错误吧... //转身有效,进行转身 //冲刺有效,进此冲刺 if( socFinal.isIllegal() && ! socTurn.isIllegal() ) { Log.log( 508, "can do turn" ); WM->logCircle( 508, posPred1, SS->getMaximalKickDist(), true ); socFinal = socTurn; } if( socFinal.isIllegal() && ! socDash1.isIllegal() ) { Log.log( 508, "do dash 1x" ); WM->logCircle( 508, posDash1, SS->getMaximalKickDist(), true ); socFinal = socDash1; } } } // if there are no opponents, we are wrongly directed, and we will be closely // to the ball, see whether we can first update our heading // 感觉下面这些也是用于特殊情况的处理(可能是用于排除错误),因为几乎已经是计算出距离无法完成截球 // 如果没有对手的话,我们的身体朝向不好,并且球正在靠近我们,尝试首先更新身体朝向 else if( fabs( angTurn ) > angThreshold && !bOppClose && dDist1 < 0.7*SS->getMaximalKickDist() ) { soc = turnBodyToPoint( posPred2 - VecPosition(1.0,dDesBody, POLAR), 1 ); Log.log( 508, "turn 1x, dist %f, angle %f, opp %f", dDist1, angTurn, dDistOppA ); WM->logCircle( 508, posPred1, SS->getMaximalKickDist(), true ); socFinal = soc; } // 看看转向球两个周期后的方向时,球能否两个周期后到达身边 else if( !bOppClose && //fabs( angTurn ) > angThreshold && dDist2 < 0.7*SS->getMaximalKickDist() ) { soc = turnBodyToPoint( posPred3 - VecPosition(1.0,dDesBody, POLAR), 2 ); Log.log( 508, "turn 2x, dist %f, angle %f, opp %f", dDist2, angTurn, dDistOppA ); WM->logCircle( 508, posPred2, SS->getMaximalKickDist(), true ); socFinal = soc; } // 看看触球是否可行 else if( socCollide.commandType != CMD_ILLEGAL && fabs( angTurn ) > angThreshold ) { Log.log( 508, "collide with ball on purpose" ); WM->logCircle( 508, posDash1, SS->getMaximalKickDist(), true ); socFinal = socCollide; } // 冲刺指令可行 else if( socDash1.commandType != CMD_ILLEGAL ) { Log.log( 508, "do dash 1x" ); WM->logCircle( 508, posDash1, SS->getMaximalKickDist(), true ); socFinal = socDash1; } // 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 Bas
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -