Striker
进入上篇文章提到的Options下的Roles。发现其中自带一个Striker.h文件
下面我们模拟一下比赛的过程
首先返回Options目录
进入GameControl。比赛开始进入ready状态执行ReadyState.h
/** behavior for the ready state */ option(ReadyState) { /* position has been reached -> stand and wait */ initial_state(stand) { action { theHeadControlMode = HeadControl::lookForward; Stand(); } } }
此时机器人头朝前且站立,play状态时执行PlayingState.h
option(PlayingState) { initial_state(demo) { action { Demo(); } } }
我们找到option(Demo),发现它直接跳转到Striker.h(分析见代码注释)
/** A test striker option without common decision */ option(Striker) { initial_state(start) //初始化状态start { transition { if(state_time > 1000) //当此状态停留时间超过1000ms,跳到turnToBall状态 goto turnToBall; } action { theHeadControlMode = HeadControl::lookForward; //状态跳转之前头朝前站立 Stand(); } } state(turnToBall) { transition //调用相关representations接口进行判断然后跳转状态 { if(theLibCodeRelease.timeSinceBallWasSeen > theBehaviorParameters.ballNotSeenTimeOut) goto searchForBall; if(std::abs(theBallModel.estimate.position.angle()) < 5_deg) goto walkToBall; } action //在此状态执行走到目的地点 { theHeadControlMode = HeadControl::lookForward; WalkToTarget(Pose2f(50.f, 50.f, 50.f), Pose2f(theBallModel.estimate.position.angle(), 0.f, 0.f)); } } state(walkToBall) { transition { if(theLibCodeRelease.timeSinceBallWasSeen > theBehaviorParameters.ballNotSeenTimeOut) goto searchForBall; if(theBallModel.estimate.position.norm() < 500.f) goto alignToGoal; } action { theHeadControlMode = HeadControl::lookForward; WalkToTarget(Pose2f(50.f, 50.f, 50.f), theBallModel.estimate.position); //走到球所在的位置 } } state(alignToGoal) { transition { if(theLibCodeRelease.timeSinceBallWasSeen > theBehaviorParameters.ballNotSeenTimeOut) goto searchForBall; if(std::abs(theLibCodeRelease.angleToGoal) < 10_deg && std::abs(theBallModel.estimate.position.y()) < 100.f) goto alignBehindBall; } action //走到球的后面对准球门 { theHeadControlMode = HeadControl::lookForward; WalkToTarget(Pose2f(100.f, 100.f, 100.f), Pose2f(theLibCodeRelease.angleToGoal, theBallModel.estimate.position.x() - 400.f, theBallModel.estimate.position.y())); } } state(alignBehindBall) { transition { if(theLibCodeRelease.timeSinceBallWasSeen > theBehaviorParameters.ballNotSeenTimeOut) goto searchForBall; if(theLibCodeRelease.between(theBallModel.estimate.position.y(), 20.f, 50.f) && theLibCodeRelease.between(theBallModel.estimate.position.x(), 140.f, 170.f) && std::abs(theLibCodeRelease.angleToGoal) < 2_deg) goto kick; } action//对球 { theHeadControlMode = HeadControl::lookForward; WalkToTarget(Pose2f(80.f, 80.f, 80.f), Pose2f(theLibCodeRelease.angleToGoal, theBallModel.estimate.position.x() - 150.f, theBallModel.estimate.position.y() - 30.f)); } } state(kick) { transition { if(state_time > 3000 || (state_time > 10 && action_done)) goto start; } action //射门 { theHeadControlMode = HeadControl::lookForward; InWalkKick(WalkKickVariant(WalkKicks::forward, Legs::left), Pose2f(theLibCodeRelease.angleToGoal, theBallModel.estimate.position.x() - 160.f, theBallModel.estimate.position.y() - 55.f)); } } state(searchForBall) { transition { if(theLibCodeRelease.timeSinceBallWasSeen < 300) goto turnToBall; } action { theHeadControlMode = HeadControl::lookForward; WalkAtRelativeSpeed(Pose2f(1.f, 0.f, 0.f)); //原地旋转找球 } } }
representations下的调用:the + str(Name).对象名,例如
theLibCodeRelease.timeSinceBallWasSeen调用的是LibCodeRelease下的timeSinceBallWasSeen对象
CABSL结构
若有不详之处,参考pdf第六章的第一节cabsl
该结构是以图的结构表示,Option()第一个参数为图的名字,一般与文件名相同; 第二或以后的参数为变量,一般可省略
- common_transition: 最高优先级转换,不管在其中图的哪个节点状态,满足条件一定跳出到指定位置,可跳出图
- initial_state(stateName): 进入图的初始状态的状态名,与state区别不大
- state(stateName): 状态,只能通过goto语句跳转(以下符号部分为state中的结构)
- transition:图节点的连接部分,通过条件是否满足跳转到其他状态,通常是if 条件 goto 状态
- action:进入此状态的行为,执行部分,通常是Options下的图或行为接口调用(需在Options新建文件下声明)
例如上面的原地找球的action: WalkAtRelativeSpeed(Pose2f(1.f, 0.f, 0.f))
执行的是WalkAtRelativeSpeed.h文件。其中Pose2f(1.f, 0.f, 0.f)为第一个参数,该文件的结构为
option(WalkAtRelativeSpeed, (const Pose2f&) speed) //传入参数为一个Pose2f对象 { /** Set the motion request. */ initial_state(setRequest) { transition { if(theMotionInfo.motion == MotionRequest::walk) goto requestIsExecuted; } action { theMotionRequest.motion = MotionRequest::walk; theMotionRequest.walkRequest.mode = WalkRequest::relativeSpeedMode; theMotionRequest.walkRequest.speed = speed; theMotionRequest.walkRequest.walkKickRequest = WalkRequest::WalkKickRequest(); } } /** The motion process has started executing the request. */ target_state(requestIsExecuted) { transition { if(theMotionInfo.motion != MotionRequest::walk) goto setRequest; } action { theMotionRequest.motion = MotionRequest::walk; theMotionRequest.walkRequest.mode = WalkRequest::relativeSpeedMode; theMotionRequest.walkRequest.speed = speed; theMotionRequest.walkRequest.walkKickRequest = WalkRequest::WalkKickRequest(); } } }
优先级高的图的切换可强行关闭优先级低的图里面的state进程
添加角色文件
在Roles目录可以添加其他的角色文件,只需在上面的options.h文件中添加include即可,上篇文章中提到。
重新编译已改好的项目
进入bhuman下的Make/Linux, 若没有语法错误,右击打开终端执行 make SimRobot 或 make Nao 即可重新编译
make SimRobot是编译仿真的环境,即可让其在SimRobot下运行。
make Nao是编译实体机器人,能够在机器人上运行。