实验四 复杂的动作决策(含WorldModel)
1.实验目的
1.了解 doPreprocess 的工作原理
2.会对 doPreprocess 进行简单的修改 ,能通过底层动作的简单组合控制场上队员做出一些复杂动作决策
3.对WorldModel有初步的认识
2.实验设备
硬件环境:PC机
软件环境:操作系统Linux
3.实验内容
1.截球
截球用到的函数主要有Body_Intercept(),以及Body_Intercept::getBestIntercept();
Body_Intercept( const bool save_recovery = true,
const Vector2D & face_point = Vector2D::INVALIDATED )//设置朝向位置
//如果save recovery=true,dash_power也会自动调整以保证单位时间体力恢复值不至于减少。
//截球。在搜索过程中,会自动选择评价最高的截球路径。
//当未搜索到截球路径的时候,不执行任何动作,body_pass()::execute()将返回false。
//调用这一动作之前,调用静态成员函数Body Pass::get best pass()以确认是否存在适合的截球路径,以下是详细参数
Body_Intercept::getBestIntercept( const WorldModel & wm,
const InterceptTable * table ) //初始化预测信息
截球示例:
#include <rcsc/action/body_intercept.h>
const WorldModel & wm = this->world();
int self_min = wm.interceptTable()->selfReachCycle();
//获取预测的球员捕获到球的最小周期数
Vector2D intercept_pos = wm.ball().inertiaPoint( self_min );
//获取在经过该最小周期数后球的位置
if ( ! wm.existKickableTeammate()//不存在可踢球的成员
&& wm.ball().posCount() <= 1//球位置满足的条件
&& wm.ball().velCount() <= 1//球速度满足的条件
&& self_min < 20 //捕获球时间满足的条件
)//满足截球条件
{
Body_Intercept().execute( this );//执行截球动作
this->setNeckAction( new Neck_TurnToBall() );//调整视角对准球
}
2.在Sample_player里添加状态函数
①打开Sample_player.cpp,在里面写入
bool isOpponentAtAngleEx( AngleDeg angA , AngleDeg angB ,double dDist );
该函数用来
判断当前球员角度在angA~angB之间距离小于dDist的范围内是否有对方队员
填加一个新函数
bool isOpponentAtAngleEx(const WorldModel & wm, AngleDeg angA , AngleDeg angB ,double dDist )
{
Vector2D selfpos=wm.self().pos();
Sector2D sector(selfpos, 0, dDist, wm.self().body()+angA,wm.self().body()+angB);
const PlayerPtrCont & players=wm.opponentsFromSelf();
const PlayerPtrCont::const_iterator end = players.end();
for ( PlayerPtrCont::const_iterator it = players.begin();it != end;++it )
if ( sector.contains( (*it)->pos() ) )
return true;
return false
}
③在doReprocess中添加:
if( wm.self().isKickable())
{
double ang = (Vector2D(52.5,0)-wm.self().pos()).th().degree();
if ( isOpponentAtAngleEx(wm, ang-45, ang, 6) )
ang+=45;
else if ( isOpponentAtAngleEx(wm, ang,ang+45,6) )
ang-=45;
Body_KickToRelative( 12,ang,true );
}
然后编译运行程序,观察球员的行为,试分析球员的行为。
附:指定方向踢球
#include <rcsc/action/body_kick_to_relative.h>
Body_KickToRelative( const double & target_dist,
const AngleDeg & target_angle_rel,
const bool stop );
//向与身体朝向target_angle_rel角度的方向,将球踢出target_dist距离。
//根据需要进行多步踢法的规划。但是,因为踢球动作不能被持续执行,在下个周期内,必须要重新进行踢球设计。
//如果stop = true,则需要调整踢球规划,以便能够在设定位置处停住球。
到此为止,doReprocess的基本内容已经向大家介绍完毕,希望大家能够熟练的应用doReprocess 函数。
根据以上描述完成练习:通过基本动作的组合实现球员的以下行为(要求至少做出1~2 个题目,更多基本动作请查询BodyAction的各个派生类,或其他有关书籍,也希望大家能做出更多的动 作来)
判断守门员的位置,朝球门空隙较大的一方射门,(通过在WorldModel里建立新状态来判断,球门哪一方空隙较大,守门员的位置为Vector2D posGoalie = wm->getOpponentGoalie().pos();
球门位置坐标为(52.5,0), 可尝试朝(52.5,6.5)(52.5,-6.5)两点射门)在 SamplePlayer里填加一个带球函数,要求如果无人阻挡(带球将要经过的路线附近 没有对方球员)就朝球门方向带球,否则想办法避开对方球员带球前进(要求只要 作出闪避的动作即可,不要求效果)。
尝试修改视觉函数使得球员能更多的获得场上信息(要求不影响球员的动作)。