Robcup2D足球学习记录【2020.01.10】

对于代码的理解与存在的疑问(用注释标出)

注释格式如下:
/*
问题:
xxxx

理解:
xxxx
By ChenYanTing
*/

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include "bhv_chain_action.h"

#include "action_chain_holder.h"
#include "action_chain_graph.h"
#include "action_state_pair.h"
#include "field_analyzer.h"

#include "bhv_pass_kick_find_receiver.h"
#include "bhv_normal_dribble.h"
#include "body_force_shoot.h"

#include "neck_turn_to_receiver.h"

#include <rcsc/action/bhv_scan_field.h>
#include <rcsc/action/body_clear_ball.h>
#include <rcsc/action/body_go_to_point.h>
#include <rcsc/action/body_smart_kick.h>
#include <rcsc/action/body_hold_ball.h>
#include <rcsc/action/body_turn_to_point.h>
#include <rcsc/action/neck_scan_field.h>
#include <rcsc/action/neck_turn_to_goalie_or_scan.h>

#include <rcsc/action/kick_table.h>

#include <rcsc/player/intercept_table.h>
#include <rcsc/player/soccer_intention.h>
#include <rcsc/player/player_agent.h>
#include <rcsc/common/server_param.h>
#include <rcsc/common/logger.h>

using namespace rcsc;

namespace {

class IntentionTurnTo
    : public SoccerIntention {
private:
    int M_step;
    Vector2D M_target_point;

public:

    IntentionTurnTo( const Vector2D & target_point )
        : M_step( 0 ),
          M_target_point( target_point )
      { }

    bool finished( const PlayerAgent * agent );

    bool execute( PlayerAgent * agent );

private:

};

/*-------------------------------------------------------------------*/
/*!

 */
    

/*
 问题:
 wm.interceptTable()中的一些属性分别有什么,可以在哪里查看?
     
 理解:
 此函数为每次球员移动结束后的提示函数,其主要功能为:每次球员完成了移动动作后,输出移动完成时的球员状态或者其他状态
 此函数的内容如下:
 记录步数的变量自加,然后输出移动的步数
 如果移动的步数大于二,则输出时间溢出,并且返回true
 如果自己是不可踢球状态,则输出(finished) no kickable并且返回true
 如果存在可踢球的敌人,则输出(finished) exist kickable opponent
 如果拦截表中,敌人的可达半径小于1,则输出(finished) opponent may be kickable
 如果自己下一步距离球的距离大于可以踢球的距离,输出 (finished) unkickable at next cycle
 
 By ChenYanTing
*/
bool
IntentionTurnTo::finished( const PlayerAgent * agent )
{
    ++M_step;
    dlog.addText( Logger::TEAM,
                  __FILE__": (finished) step=%d",
                  M_step );

    if ( M_step >= 2 )
    {
        dlog.addText( Logger::TEAM,
                      __FILE__": (finished) time over" );
        return true;
    }

    const WorldModel & wm = agent->world();

    //
    // check kickable
    //

    if ( ! wm.self().isKickable() )
    {
        dlog.addText( Logger::TEAM,
                      __FILE__": (finished) no kickable" );
        return true;
    }

    //
    // check opponent
    //

    if ( wm.existKickableOpponent() )
    {
        dlog.addText( Logger::TEAM,
                      __FILE__": (finished) exist kickable opponent" );
        return true;
    }

    if ( wm.interceptTable()->opponentReachCycle() <= 1 )
    {
        dlog.addText( Logger::TEAM,
                      __FILE__": (finished) opponent may be kickable" );
        return true;
    }

    //
    // check next kickable
    //

    double kickable2 = std::pow( wm.self().playerType().kickableArea()
                                 - wm.self().vel().r() * ServerParam::i().playerRand()
                                 - wm.ball().vel().r() * ServerParam::i().ballRand()
                                 - 0.15,
                                 2 );
    Vector2D self_next = wm.self().pos() + wm.self().vel();
    Vector2D ball_next = wm.ball().pos() + wm.ball().vel();

    if ( self_next.dist2( ball_next ) > kickable2 )
    {
        // unkickable if turn is performed.
        dlog.addText( Logger::TEAM,
                      __FILE__": (finished) unkickable at next cycle" );
        return true;
    }

    return false;
}

/*-------------------------------------------------------------------*/



    
/*
 问题:
 agent->setNeckAction( new Neck_ScanField() ),这个设置颈部动作是不是在那个agent代码里面,属于后面看的代码?
     
 理解:
 这是球员移动到目标点的执行函数
 函数内容如下:
 首先输出目标点的x,y坐标
 然后执行Body_TurnToPoint( M_target_point ).execute( agent )函数,执行移动到目标点的函数
 最后设置颈部动作,环顾四周
 By ChenYanTing
*/
bool
IntentionTurnTo::execute( PlayerAgent * agent )
{
    dlog.addText( Logger::TEAM,
                  __FILE__": (intention) facePoint=(%.1f %.1f)",
                  M_target_point.x, M_target_point.y );
    agent->debugClient().addMessage( "IntentionTurnToForward" );

    Body_TurnToPoint( M_target_point ).execute( agent );
    agent->setNeckAction( new Neck_ScanField() );

    return true;
}

}

/*-------------------------------------------------------------------*/
/*!

 */
Bhv_ChainAction::Bhv_ChainAction( const ActionChainGraph & chain_graph )
    : M_chain_graph( chain_graph )
{

}

/*-------------------------------------------------------------------*/
/*!

 */
Bhv_ChainAction::Bhv_ChainAction()
    : M_chain_graph( ActionChainHolder::i().graph() )
{

}

/*-------------------------------------------------------------------*/

/*
 问题:
 ServerParam::i()代表什么?ServerParam这个类有必要看源代码吗?
 M_chain_graph.getFirstAction(),这里获得的第一个动作指的什么?
 agent->setNeckAction( new Neck_TurnToReceiver( M_chain_graph ) )这个设置的颈部动作是什么意思?
 wm.gameMode().type(),不理解,vm的源代码需要看吗?
 整个球场的中心坐标在哪里,球场的长和宽是多少?如果需要自己了解这些,可以在哪里查看数据?
 Body_ClearBall(),这是指的什么意思?
 
 
 理解:
 这个函数为动作链的执行函数,简单通俗的讲,就是判断链式动作里面的第一个动作属于什么动作(射门、运球、持球等等),然后通过switch语句,根据不同的判断结果,给出不同的执行过程。
 函数的内容如下:
 首先输出Bhv_ChainAction
 判断是否正在执行doTurnToForward( agent ),如果是则返回true
 获得动作链式图里面的第一个动作,然后进行进入switch语句,判断第一个动作属于什么,根据不同的判断结果执行不同的过程。
 如果当前比赛暂停或者处于不是正在比赛的过程中,则返回false。其他球员正在执行动作的情况,返回true。
 */
bool
Bhv_ChainAction::execute( PlayerAgent * agent )
{
    dlog.addText( Logger::TEAM,
                  __FILE__": Bhv_ChainAction" );

    if ( doTurnToForward( agent ) )
    {
        return true;
    }

    const ServerParam & SP = ServerParam::i();
    const WorldModel & wm = agent->world();

    const CooperativeAction & first_action = M_chain_graph.getFirstAction();

    ActionChainGraph::debug_send_chain( agent, M_chain_graph.getAllChain() );

    const Vector2D goal_pos = SP.theirTeamGoalPos();
    agent->setNeckAction( new Neck_TurnToReceiver( M_chain_graph ) );

    switch ( first_action.category() ) {
    case CooperativeAction::Shoot:
        {
            dlog.addText( Logger::TEAM,
                          __FILE__" (Bhv_ChainAction) shoot" );
            if ( Body_ForceShoot().execute( agent ) )
            {
                agent->setNeckAction( new Neck_TurnToGoalieOrScan() );
                #ifdef DEBUG2014
                std::cerr << wm.time().cycle() << __FILE__ << wm.self().unum() << ": (Bhv_ChainAction) shoot...
";
                #endif // DEBUG2014

                return true;
            }
            #ifdef DEBUG2014
            std::cerr << wm.time().cycle() << __FILE__ << wm.self().unum() << ": (Bhv_ChainAction) shoot failed...
";
            #endif // DEBUG2014


            break;
        }

    case CooperativeAction::Dribble:
        {
            if ( wm.gameMode().type() != GameMode::PlayOn
                 && ! wm.gameMode().isPenaltyKickMode() )
            {
                agent->debugClient().addMessage( "CancelChainDribble" );
                dlog.addText( Logger::TEAM,
                              __FILE__" (Bhv_ChainAction) cancel dribble" );
                return false;
            }

            const Vector2D & dribble_target = first_action.targetPoint();

            dlog.addText( Logger::TEAM,
                          __FILE__" (Bhv_ChainAction) dribble target=(%.1f %.1f)",
                          dribble_target.x, dribble_target.y );

            NeckAction::Ptr neck;
            double goal_dist = goal_pos.dist( dribble_target );
            if ( goal_dist < 18.0 )
            {
                int count_thr = 0;
                if ( goal_dist < 13.0 )
                {
                    count_thr = -1;
                }
                agent->debugClient().addMessage( "ChainDribble:LookGoalie" );
                neck = NeckAction::Ptr( new Neck_TurnToGoalieOrScan( count_thr ) );
            }

            if ( Bhv_NormalDribble( first_action, neck ).execute( agent ) )
            {
                #ifdef DEBUG2014
                std::cerr << wm.time().cycle() << __FILE__ << wm.self().unum() << ": (Bhv_ChainAction) Dribble...
";
                #endif // DEBUG2014

                return true;
            }
            break;
        }

    case CooperativeAction::Hold:
        {
            if ( wm.gameMode().type() != GameMode::PlayOn )
            {
                agent->debugClient().addMessage( "CancelChainHold" );
                dlog.addText( Logger::TEAM,
                              __FILE__" (Bhv_ChainAction) cancel hold" );
                return false;
            }

            if ( wm.ball().pos().x < -SP.pitchHalfLength() + 8.0
                 && wm.ball().pos().absY() < SP.goalHalfWidth() + 1.0 )
            {
                agent->debugClient().addMessage( "ChainHold:Clear" );
                dlog.addText( Logger::TEAM,
                              __FILE__" (Bhv_ChainAction) cancel hold. clear ball" );
                Body_ClearBall().execute( agent );
                agent->setNeckAction( new Neck_ScanField() );
                return true;
            }

            agent->debugClient().addMessage( "hold" );
            dlog.addText( Logger::TEAM,
                          __FILE__" (Bhv_ChainAction) hold" );

            if ( Body_HoldBall().execute( agent ) )
            {
                agent->setNeckAction( new Neck_ScanField() );
                #ifdef DEBUG2014
                std::cerr << wm.time().cycle() << __FILE__ << wm.self().unum() << ": (Bhv_ChainAction) Hold ball...
";
                #endif // DEBUG2014

                return true;
            }

            break;
        }

    case CooperativeAction::Pass:
        {
            dlog.addText( Logger::TEAM,
                          __FILE__" (Bhv_ChainAction) pass" );
            if ( first_action.targetPlayerUnum() == 1 )
            {
                #ifdef DEBUG2014
                std::cerr << wm.time().cycle() << __FILE__ << wm.self().unum() << ": DO NOT PASS TO OUR GOALIE!!!

";
                #endif // DEBUG2014

                break;
            }
            if ( Bhv_PassKickFindReceiver( M_chain_graph ).execute( agent ) )
            {
                if ( wm.self().pos().x < -42.0 )
                {
                    #ifdef DEBUG2014
                    std::cerr << "wm.gameMode().type() = " << wm.gameMode().type() << std::endl;
                    std::cerr << "targetPoint = " << '(' << first_action.targetPoint().x << first_action.targetPoint().y << ')'
                              << std::endl;
                    std::cerr << "targetPlayerUnum = " << first_action.targetPlayerUnum() << std::endl;
                    #endif // DEBUG2014

                }
                #ifdef DEBUG2014
                std::cerr << wm.time().cycle() << __FILE__ << wm.self().unum() << ": (Bhv_ChainAction) Pass...

";
                #endif // DEBUG2014

                return true;
            }

            break;
        }

    case CooperativeAction::Move:
        {
            dlog.addText( Logger::TEAM,
                          __FILE__" (Bhv_ChainAction) move" );

            if ( Body_GoToPoint( first_action.targetPoint(),
                                 1.0,
                                 SP.maxDashPower() ).execute( agent ) )
            {
                agent->setNeckAction( new Neck_ScanField() );
                #ifdef DEBUG2014
                std::cerr << wm.time().cycle() << __FILE__ << wm.self().unum()
                            << ": (Bhv_ChainAction) Move to "
                            << first_action.targetPoint().x << ',' << first_action.targetPoint().y << std::endl;
                #endif // DEBUG2014

                return true;
            }

            break;
        }

    case CooperativeAction::Clear:
        {
            dlog.addText( Logger::TEAM,
                          __FILE__" (Bhv_ChainAction) clear" );

            if ( Body_SmartKick( first_action.targetPoint(),
                                first_action.firstBallSpeed(),
                                first_action.firstBallSpeed() * 0.99,
                                first_action.kickCount() ).execute( agent ) )

            {
                agent->setNeckAction( new Neck_ScanField() );
                #ifdef DEBUG2014
                std::cerr << wm.time().cycle() << __FILE__ << wm.self().unum() << ": (Bhv_ChainAction) Clear...
";
                #endif // DEBUG2014

                return true;
            }
            #ifdef DEBUG2014
            std::cerr << wm.time().cycle() << __FILE__ << wm.self().unum() << ": (Bhv_ChainAction) Clear failed...
";
            #endif // DEBUG2014


            break;
        }

    case CooperativeAction::NoAction:
        {
            dlog.addText( Logger::TEAM,
                          __FILE__" (Bhv_ChainAction) no action" );

            return true;
            break;
        }

    default:
        dlog.addText( Logger::TEAM,
                      __FILE__" (Bhv_ChainAction) invalid category" );
        break;
    }

    return false;
}


/*-------------------------------------------------------------------*/
/*
 问题:
 ( face_point - wm.self().pos() ).th(),face_point是指的面向的坐标吗?.th是指的什么?我又忘记这个了
 opponent_dist_thr的意义?
 (*o)->posCount(),地方的位置数代表的意义是?
 getKeepBallVel( agent->world() ),获得的是球的什么速度?
 
 
 理解:
 这个函数为执行转向的函数。
 函数的内容如下:
 首先判断游戏是否正在进行,如果游戏不是正在进行,则返回false
 获取身体面向与脸面向的角度差
 如果角度差在110以内,则认为不需要转向,返回false
 否则,尝试转向
 判断地方的每个敌人距离自己的距离,如果距离小于某一临界值,则返回false,不执行转向
 如果自己接下来距离球接下来的距离小于kikable2的距离,则执行转向函数,并且返回true
 

 */
bool
Bhv_ChainAction::doTurnToForward( PlayerAgent * agent )
{
    const WorldModel & wm = agent->world();

    if ( wm.gameMode().type() != GameMode::PlayOn )
    {
        return false;
    }

    Vector2D face_point( 42.0, 0.0 );

    const double body_angle_diff = ( ( face_point - wm.self().pos() ).th() - wm.self().body() ).abs();
    if ( body_angle_diff < 110.0 )
    {
        dlog.addText( Logger::TEAM,
                      __FILE__" (doTurnToForward) already facing the forward direction. angle_diff=%.1f",
                      body_angle_diff );
        return false;
    }

    dlog.addText( Logger::TEAM,
                  __FILE__" (doTurnToForward) angle_diff=%.1f. try turn",
                  body_angle_diff );

    // const double opponent_dist_thr = ( wm.self().pos().x > ServerParam::i().theirPenaltyAreaLineX() - 2.0
    //                                    && wm.self().pos().absY() > ServerParam::i().goalHalfWidth()
    //                                    ? 2.7
    //                                    : 4.0 );
    const double opponent_dist_thr = 4.0;

    const PlayerPtrCont::const_iterator o_end = wm.opponentsFromSelf().end();
    for ( PlayerPtrCont::const_iterator o = wm.opponentsFromSelf().begin();
          o != o_end;
          ++o )
    {
        double dist = (*o)->distFromSelf();
        dist -= bound( 0, (*o)->posCount(), 3 ) * (*o)->playerTypePtr()->realSpeedMax();

        if ( dist < opponent_dist_thr )
        {
            dlog.addText( Logger::TEAM,
                      __FILE__" (doTurnToForward) exist opponent" );
            return false;
        }

        if ( dist > 10.0 )
        {
            break;
        }
    }

    // TODO: find the best scan target angle
    face_point.y = wm.self().pos().y * 0.5;


    double kickable2 = std::pow( wm.self().playerType().kickableArea()
                                 - wm.self().vel().r() * ServerParam::i().playerRand()
                                 - wm.ball().vel().r() * ServerParam::i().ballRand()
                                 - 0.2,
                                 2 );
    Vector2D self_next = wm.self().pos() + wm.self().vel();
    Vector2D ball_next = wm.ball().pos() + wm.ball().vel();

    if ( self_next.dist2( ball_next ) < kickable2 )
    {
        Body_TurnToPoint( face_point ).execute( agent );
        agent->setNeckAction( new Neck_ScanField() );
        return true;
    }


    Vector2D ball_vel = getKeepBallVel( agent->world() );

    if ( ! ball_vel.isValid() )
    {
        dlog.addText( Logger::TEAM,
                      __FILE__": (doKeepBall) no candidate." );

        return false;
    }

    //
    // perform first kick
    //

    Vector2D kick_accel = ball_vel - wm.ball().vel();
    double kick_power = kick_accel.r() / wm.self().kickRate();
    AngleDeg kick_angle = kick_accel.th() - wm.self().body();

    dlog.addText( Logger::TEAM,
                  __FILE__": (doTurnToForward) "
                  " ballVel=(%.2f %.2f)"
                  " kickPower=%.1f kickAngle=%.1f",
                  ball_vel.x, ball_vel.y,
                  kick_power,
                  kick_angle.degree() );

    if ( kick_power > ServerParam::i().maxPower() )
    {
        dlog.addText( Logger::TEAM,
                      __FILE__": (doTurnToForward) over kick power" );
        Body_HoldBall( true,
                       face_point ).execute( agent );
        agent->setNeckAction( new Neck_ScanField() );
        #ifdef DEBUG2014
std::cerr << wm.time().cycle() << __FILE__ << wm.self().unum() << ": (Bhv_ChainAction) doTurnToForward: Hold???
";
        #endif // DEBUG2014


    }
    else
    {
        agent->doKick( kick_power, kick_angle );
        agent->setNeckAction( new Neck_ScanField() );
        #ifdef DEBUG2014
std::cerr << wm.time().cycle() << __FILE__ << wm.self().unum() << ": (Bhv_ChainAction) doTurnToForward: Kick???n";
        #endif // DEBUG2014

    }

    agent->debugClient().addMessage( "Chain:Turn:Keep" );
    agent->debugClient().setTarget( face_point );

    //
    // set turn intention
    //

    dlog.addText( Logger::TEAM,
                  __FILE__": (doTurnToFoward) register intention" );
    agent->setIntention( new IntentionTurnTo( face_point ) );

    return true;
}

/*-------------------------------------------------------------------*/

/*
 问题:
 keep_pos代表什么?
 std::pow( ptype.playerSize()+ SP.ballSize(),2 ),这个pow代表什么?是代表的指数运算吗?还是和power有关的函数?
 playerSize和ballSize,这个size是指的什么size?
 ptype.kickableMargin(),球员类型的可踢边境?这个代表着每个球员类型都有自己的可踢边境的划分吗?
 keep_dist的含义代表什么?
 keep_pos的含义代表什么?
 Vector2D::INVALIDATED代表什么数据?这个可以从哪里看到?
 Vector2D::from_polar()函数的作用是什么?如果不懂可以从哪里找到?
 Vector2D.r()是指的向量的大小吗?那Vector2D.r2()又是什么?
 
 
 理解:
 说实话这个函数,我看不太懂。。。
 我的所有理解都写成注释,写在函数里面了,但是因为这个函数里面太多调用我都不明白原理,所以我理解起来很困难。
 看了几遍,还是不能把这些东西串起来,先放放吧。。。看看以后再看是不是就能看懂了。。。
 
 */
Vector2D
Bhv_ChainAction::getKeepBallVel( const WorldModel & wm )
{
    //初始化s_update_time时间为0
    static GameTime s_update_time( 0, 0 );
    
    //初始化s_best_ball_vel,横向速度和纵向速度都为零
    static Vector2D s_best_ball_vel( 0.0, 0.0 );

    //如果wm.time()与s_update_time相等,即wm.time()等于零,那么返回s_best_ball_vel
    if ( s_update_time == wm.time() )
    {
        return s_best_ball_vel;
    }
    //设置s_update_time为wm.time()
    s_update_time = wm.time();

    //ANGLE_DIVS代表将360度分割成了十二份
    const int ANGLE_DIVS = 12;

    //获得SP参数对象、ptype球员类型对象
    const ServerParam & SP = ServerParam::i();
    const PlayerType & ptype = wm.self().playerType();
    //定义collide_dist2(碰撞距离),但是pow具体是指什么?
    const double collide_dist2 = std::pow( ptype.playerSize()
                                           + SP.ballSize(),
                                           2 );
    
    //keep_dist的含义代表什么?
    const double keep_dist = ptype.playerSize()
        + ptype.kickableMargin() * 0.5
        + ServerParam::i().ballSize();

    //获得自己下一个与下下个自己所处的位置
    const Vector2D next_self_pos
        = wm.self().pos() + wm.self().vel();
    const Vector2D next2_self_pos
        = next_self_pos
        + wm.self().vel() * ptype.playerDecay();

    //
    // create keep target point
    //

    // 初始化几个变量
    int best_angle = -1;
    Vector2D best_ball_vel = Vector2D::INVALIDATED;
    int best_opponent_step = 0;
    double best_ball_speed = 1000.0;

    /*
     将三百六十度分成十二份,每次转三十度。每次线获取keep_pos,如果keep_pos符合某个条件则不进行处理
     否则,则进行如下处理(看下面的注释)。
     */
    for ( int a = 0; a < ANGLE_DIVS; ++a )
    {
        Vector2D keep_pos
            = next2_self_pos
            + Vector2D::from_polar( keep_dist,
                                    360.0/ANGLE_DIVS * a );
        if ( keep_pos.absX() > SP.pitchHalfLength() - 0.2
             || keep_pos.absY() > SP.pitchHalfWidth() - 0.2 )
        {
            continue;
        }
        
        //初始化ball_move、ball_speed,这里的ball_move是一个向量
        Vector2D ball_move = keep_pos - wm.ball().pos();
        double ball_speed = ball_move.r() / ( 1.0 + SP.ballDecay() );

        
        Vector2D max_vel
            = KickTable::calc_max_velocity( ball_move.th(),
                                            wm.self().kickRate(),
                                            wm.ball().vel() );
        //这个临界条件的设定不是很明白
        if ( max_vel.r2() < std::pow( ball_speed, 2 ) )
        {
            continue;
        }

        
        Vector2D ball_next_next = keep_pos;

        Vector2D ball_vel = ball_move.setLengthVector( ball_speed );
        Vector2D ball_next = wm.ball().pos() + ball_vel;

        if ( next_self_pos.dist2( ball_next ) < collide_dist2 )
        {
            ball_next_next = ball_next;
            ball_next_next += ball_vel * ( SP.ballDecay() * -0.1 );
        }

#ifdef DEBUG_PRINT
        dlog.addText( Logger::TEAM,
                      __FILE__": (getKeepBallVel) %d: ball_move th=%.1f speed=%.2f max=%.2f",
                      a,
                      ball_move.th().degree(),
                      ball_speed,
                      max_vel.r() );
        dlog.addText( Logger::TEAM,
                      __FILE__": __ ball_next=(%.2f %.2f) ball_next2=(%.2f %.2f)",
                      ball_next.x, ball_next.y,
                      ball_next_next.x, ball_next_next.y );
#endif

        //
        // check opponent
        //

        
        int min_step = 1000;
        for ( PlayerPtrCont::const_iterator o = wm.opponentsFromSelf().begin();
              o != wm.opponentsFromSelf().end();
              ++o )
        {
            if ( (*o)->distFromSelf() > 10.0 )
            {
                break;
            }

            int o_step = FieldAnalyzer::predict_player_reach_cycle( *o,
                                                                    ball_next_next,
                                                                    (*o)->playerTypePtr()->kickableArea(),
                                                                    0.0, // penalty distance
                                                                    1, // body count thr
                                                                    1, // default turn step
                                                                    0, // wait cycle
                                                                    true );

            if ( o_step <= 0 )
            {
                break;
            }

            if ( o_step < min_step )
            {
                min_step = o_step;
            }
        }
#ifdef DEBUG_PRINT
        dlog.addText( Logger::TEAM,
                      __FILE__": (getKeepBallVel) %d: keepPos=(%.2f %.2f)"
                      " ballNext2=(%.2f %.2f) ballVel=(%.2f %.2f) speed=%.2f o_step=%d",
                      a,
                      keep_pos.x, keep_pos.y,
                      ball_next_next.x, ball_next_next.y,
                      ball_vel.x, ball_vel.y,
                      ball_speed,
                      min_step );
#endif
        if ( min_step > best_opponent_step )
        {
            best_angle = a;
            best_ball_vel = ball_vel;
            best_opponent_step = min_step;
            best_ball_speed = ball_speed;
        }
        else if ( min_step == best_opponent_step )
        {
            if ( best_ball_speed > ball_speed )
            {
                best_angle = a;
                best_ball_vel = ball_vel;
                best_opponent_step = min_step;
                best_ball_speed = ball_speed;
            }
        }
    }

    s_best_ball_vel = best_ball_vel;
    return s_best_ball_vel;
}

学习心得与体会

这一次只看了一个cpp文件,感觉进度比较,我认为原因有以下几点吧。第一点就是自己没有安排好学习计划,经常会被其他的事情占用了我的学习robcup的时间,导致我花费在robcup上面的时间比我预计的要少。第二点就是,许多的函数里面调用了很多底层的东西,这些东西如何自己去查找?或者这个东西值不值得去理解原理,我把握不好这个度。
所以,这一次的学习过程,最大的收获的其实不是robcup的函数又掌握了多少,而是我明白了学习过程中让我成长缓慢的痛点,而这个痛点越早察觉到,对我以后的学习过程的帮助越大。希望自己能够有所改进!

原文地址:https://www.cnblogs.com/782687539-nanfu/p/12707603.html