📄 basicplayer.cpp
字号:
//球的角度是否在球员身体右侧180以内?返回1:返回-1 iSign = ( isAngInInterval( angBall, angBody, VecPosition::normalizeAngle(angBody+180) ) ) ? 1 : -1 ; //这里刚刚取得的iSign就十分的有用了,根据这个iSign会选择左转还是右转 // if( iSign == -1 ) // angBall = VecPosition::normalizeAngle( angBall + 180 ); //调用上面的turnBodyToPoint函数完成找球功能,左或者右转60度 soc = turnBodyToPoint( posAgent + VecPosition(1.0, VecPosition::normalizeAngle(angBody+60*iSign), POLAR ) ); //记录到LOG Log.log( 556, "search ball: turn to %f s %d t(%d %d) %f", angBall, iSign, WM->getCurrentTime().getTime(), timeLastSearch.getTime(), soc.dAngle ); //记录开始寻找的时间,并返回指令 timeLastSearch = WM->getCurrentTime(); return soc;}/*! This method can be called to create a SoccerCommand that dashes to a point. This skill enables an agent to dash to a given point. It receives a global position 'pos' as its only argument and returns a dash command that causes the agent to come as close to this point as possible. Since the agent can only move forwards or backwards, the closest point to the target position that he can reach by dashing is the orthogonal projection of 'pos' onto the line that extends into the direction of his body (forwards and backwards). The power that must be supplied to the dash command is computed using the 'getPowerForDash' method which takes the position of 'pos' relative to the agent as input and 'iCycles' which denotes in how many cycles we want to reach that point. \param pos global position to which the agent wants to dash \param iCycles desired number of cycles to reach point 'pos' \return SoccerCommand dash command to move closer to 'pos' *//* 这个方法返回一个指令,让球员冲向一个点 需要注意的是,冲刺的方向只能是正前方或者正后方,所以将从同自己朝向同向的直线取得 一个目标点的投影作为目标。 pos : 目标点 iVCycles : 跑到指定点的期望周期数,默认为1 */SoccerCommand BasicPlayer::dashToPoint( VecPosition pos, int iCycles ){ //根据球员当前的位置,方向,速度,体力,期望周期计算出跑动所需的力量 double dDashPower = WM->getPowerForDash( pos - WM->getAgentGlobalPosition(), WM->getAgentGlobalBodyAngle(), WM->getAgentGlobalVelocity(), WM->getAgentEffort(), iCycles ); //返回命令 return SoccerCommand( CMD_DASH, dDashPower );}/*! This skill enables an agent to freeze a moving ball, i.e. it returns a kick command that stops the ball dead at its current position. Since ball movement in the soccer server is implemented as a vector addition, the ball will stop in the next cycle when it is kicked in such a way that the resulting acceleration vector has the same length and opposite direction to the current ball velocity. The desired speed that should be given to the ball on the kick thus equals the current ball speed. Furthermore, the direction of the kick should equal the direction of the current ball velocity plus 180 degrees. Note that this direction must be made relative to the agent's global body angle before it can be passed as an argument to the kick command. \return SoccerCommand to freeze the ball. *//* 停球指令,原理就是给球一个速度和角度相反的反作用力 */SoccerCommand BasicPlayer::freezeBall( ){ // determine power needed to kick the ball to compensate for current speed // 取得当前的球速计算出需要的力度 // get opposite direction (current direction + 180) relative to body // 取得球速的反方向(+180度)相对于身体的角度 // and make the kick command. // 并且返回踢球指令 VecPosition posAgentPred = WM->predictAgentPos( 1, 0 ); double dPower = WM->getKickPowerForSpeed( WM->getBallSpeed() ); if( dPower > SS->getMaxPower() ) { Log.log( 552, "%d: freeze ball has to much power", WM->getCurrentCycle() ); dPower = (double)SS->getMaxPower(); } double dAngle = WM->getBallDirection() + 180 - WM->getAgentGlobalBodyAngle(); dAngle = VecPosition::normalizeAngle( dAngle ); SoccerCommand soc( CMD_KICK, dPower, dAngle ); VecPosition posBall, velBall; WM->predictBallInfoAfterCommand( soc, &posBall, &velBall ); if( posBall.getDistanceTo( posAgentPred ) < 0.8 * SS->getMaximalKickDist() ) return soc; Log.log( 101, "freeze ball will end up oustide -> accelerate" ); posBall = WM->getBallPos(); // kick ball to position inside to compensate when agent is moving // 需要补偿如果球员正在运动中 VecPosition posTo = posAgentPred + VecPosition( min( 0.7 * SS->getMaximalKickDist(), posBall.getDistanceTo( posAgentPred ) - 0.1 ), (posBall-posAgentPred).getDirection(), POLAR ); VecPosition velDes( posTo - posBall ); return accelerateBallToVelocity( velDes );}/*! This skill enables an agent to kick the ball close to his body. It receives an angle 'ang' as its only argument and returns a kick command that causes the ball to move to a point at a relative angle of 'ang' degrees and at a close distance (kickable margin/6 to be precise) from the agent's body. To this end the ball has to be kicked from its current position to the desired point relative to the predicted position of the agent in the next cycle. In general, this skill will be used when the agent wants to kick the ball to a certain position on the field which cannot be reached with a single kick. Since the efficiency of a kick is highest when the ball is positioned just in front of the agent's body, calling this skill with 'ang = 0' will have the effect that the agent can kick the ball with more power after it is executed. Note that this skill will only be executed if it is possible to actually reach the desired ball position with a single kick. If the required power does exceed the maximum then the ball is frozen at its current position using the freezeBall skill. In general, it will then always be possible to shoot the motionless ball to the desired point in the next cycle. \param 'ang' relative angle to body to which the ball should be kicked \param dKickRatio ratio to which the ball is kicked \return SoccerCommand to kick the ball close to the body *//* 把球踢向自己的身体,主要用于护球 ang : 角度,传递要将球放在自己身体的哪个方向 dKickRatio : 球被踢的比率? */SoccerCommand BasicPlayer::kickBallCloseToBody( AngDeg ang, double dKickRatio ){ AngDeg angBody = WM->getAgentGlobalBodyAngle(); VecPosition posAgent = WM->predictAgentPos( 1, 0 ); //分别取得球员和球的尺寸,以及可踢球差距*踢球比率参数(dKickRatio) double dDist = SS->getPlayerSize() + SS->getBallSize() + SS->getKickableMargin()*dKickRatio; //计算出目标角度 AngDeg angGlobal = VecPosition::normalizeAngle( angBody + ang ); //计算出踢球的目标点 VecPosition posDesBall = posAgent + VecPosition( dDist, angGlobal, POLAR ); //判断目标点是否已经出界 if( fabs( posDesBall.getY() ) > PITCH_W_HALF || fabs( posDesBall.getX() ) > PITCH_L_HALF ) { Line lineBody = Line::makeLineFromPositionAndAngle( posAgent, angGlobal ); Line lineSide(0,0,0); //在这里使用自定义的HALF类变量,代替原来的“/2.0”运算减少运算次数 if( fabs( posDesBall.getY() ) > PITCH_W_HALF ) //Y出界的情况下,将以中场线的末端(可能是上下两方的)为一个点生成一个角度为0的直线(生成的就是边界线) //这里将边界线想球场内移动了0.2米,用来防止带球失误带来的出界 lineSide = Line::makeLineFromPositionAndAngle( VecPosition( 0, sign(posDesBall.getY()) * PITCH_W_HALF )- 0.2 * sign(posDesBall.getY()) , 0 ); else //X出界的情况下,以当前将要出界的底线作直线(原算法错误,如下注释) //部分修改处理如上 /*lineSide = Line::makeLineFromPositionAndAngle( VecPosition( 0, sign(posDesBall.getX() )* PITCH_LENGTH_HALF ), 90 );*/ lineSide = Line::makeLineFromPositionAndAngle( VecPosition( sign(posDesBall.getX()) * PITCH_L_HALF, 0 )-0.2 * sign(posDesBall.getX()) , 90 ); //取得lineSide和lineBody的相交点 VecPosition posIntersect = lineSide.getIntersection( lineBody ); //目标点为这个相交点略作修改之后的点 posDesBall = posAgent + VecPosition( posIntersect.getDistanceTo( posAgent ) - 0.1, angGlobal, POLAR ); } VecPosition vecDesired = posDesBall - WM->getBallPos(); VecPosition vecShoot = vecDesired - WM->getGlobalVelocity( OBJECT_BALL ); double dPower = WM->getKickPowerForSpeed( vecShoot.getMagnitude() ); AngDeg angActual = vecShoot.getDirection() - angBody; angActual = VecPosition::normalizeAngle( angActual ); //这里的dPower是求得的所需要的踢球力度,这个条件是说 需要力量>最大力量 if( dPower > SS->getMaxPower() ) { //球是有速度的 if(WM->getBallSpeed() > 0.1) { //不能补偿球速,尽力停球 Log.log( 500, "kickBallCloseToBody: cannot compensate ball speed, freeze"); Log.log( 101, "kickBallCloseToBody: cannot compensate ball speed, freeze"); return freezeBall(); } //这里球就是没有速度的了 else { //如果因为是死球的话,转向球观察 if( WM->isDeadBallUs() ) { if( WM->getRelativeAngle( OBJECT_BALL ) > 25 ) { Log.log( 101, "dead ball situation, turn to ball" ); return turnBodyToObject( OBJECT_BALL ); } } //否则的话,说明是球太远了,设定dPower为100 else { Log.log( 101, "kickBallCloseToBody: ball has no speed, but far away" ); dPower = 100; } } } //正常的护球 else { Log.log( 101, "(kick %f %f), vecDesired (%f,%f) %f posDes(%f,%f)", dPower, angActual,vecDesired.getX(), vecDesired.getY(),ang, posDesBall.getX(), posDesBall.getY() ); } return SoccerCommand( CMD_KICK, dPower, angActual );}/*! This skill enables an agent to accelerate the ball in such a way that it gets a certain velocity after the kick. It receives the desired velocity 'vecDes' as its only argument and returns a kick command that causes the ball to be accelerated to this velocity. If the power that must be supplied to the kick command to get the desired result does not exceed the maximum kick power then the desired velocity can be realized with a single kick. The kick direction should then be equal to the direction of the acceleration vector relative to the agent's global body angle. However, if the desired velocity is too great or if the current ball velocity is too high then the required acceleration cannot be realized with a single kick. In this case, the ball is kicked in such a way that the acceleration vector has the maximum possible length and a direction that aligns the resulting ball movement with 'vecDes'. This means that after the kick the ball will move in the same direction as 'vecDes' but at a lower speed. To this end the acceleration vector has to compensate for the current ball velocity in the `wrong' direction (y-component). \param velDes desired ball velocity \return SoccerCommand that accelerates the ball to 'vecDes' *//* 这个动作将球加速到一个指定的水平,当然无法加速到指定水平的话将尽力加速 velDes : 所期望的目的速度 */SoccerCommand BasicPlayer::accelerateBallToVelocity( VecPosition velDes ){ AngDeg angBody = WM->getAgentGlobalBodyAngle(); VecPosition velBall = WM->getGlobalVelocity( OBJECT_BALL ); VecPosition accDes = velDes - velBall;//这个计算出的是需要增加的相对速度 double dPower; double angActual; // if acceleration can be reached, create shooting vector // 加速可以完成的情况下 if( accDes.getMagnitude() < SS->getBallAccelMax() ) { dPower = WM->getKickPowerForSpeed ( accDes.getMagnitude() ); angActual = VecPosition::normalizeAngle( accDes.getDirection() - angBody ); // 当可以提供足够大的力度时 if( dPower <= SS->getMaxPower() )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -