深入浅出FantasiaXN孙洪峰.docx
- 文档编号:7373133
- 上传时间:2023-01-23
- 格式:DOCX
- 页数:27
- 大小:31.59KB
深入浅出FantasiaXN孙洪峰.docx
《深入浅出FantasiaXN孙洪峰.docx》由会员分享,可在线阅读,更多相关《深入浅出FantasiaXN孙洪峰.docx(27页珍藏版)》请在冰豆网上搜索。
深入浅出FantasiaXN孙洪峰
代码记录
——孙洪峰
StrParser类用于字符串解析:
floatStrParser:
:
GetFloat(char**pszMsg)
用于从一个string中得到一个浮点数。
(留待详细研究)
boolStrParser:
:
GetFloat(char**pszMsg,float&value)
同样用于从一个string中得到一个浮点数,用value进行返回。
boolStrParser:
:
GetInt(char**pszMsg,int&value)
用于从pszMsg标记的字符串中得到一个10进制整数,用value返回。
boolStrParser:
:
GetValue(char**pszMsg,constchar*strSearch,char*value)
从str标示的string中按strSearch作为标志进行查找,找到后,跳过strSearch,将后面的内容存入value标示的string进行返回。
KeyFrame类中的
staticfloatmKeyFrame[ST_MAX][MAX_FRAME_COUNT][FRAME_COLUMN_COUNT];
维度ST_MAX表示桢名,维度MAX_FRAME_COUNT表示一个关键针中的子桢,维度FRAME_COLUMN_COUNT表示此子桢中的各个关节,存放的是角度(弧度制)。
ReadFileFromFile()就是将关键针的数据从配置文件中读入到这个数组中。
保存以供后用。
三维数组用于保存桢的所有信息,其中,最低维的大小FRAME_COLUMN_COUNT大小为24,当等于0时,所保存的数据是duration,即此桢持续的时间。
似乎:
这个大小为24的数组,第一个数据存duration,第3到第24个(2-23)这22个数据存放22个关节的角度。
mKeyFrameCount[]这个数组似乎保存的是每一桢所包含的子桢数。
不允许超过100。
voidKeyFrame:
:
ReadFrameFromFile(constchar*fileName)
负责读配置文件(.cfg)内容。
将fileName.cfg中的数据读入到KeyFrame类的乘员数组中。
voidKeyFrame:
:
init()
会调用ReadFrameFromFile()来读取KeyFrame.cfg中的关键针数据,只在初始化时读一次(?
),保存在相关数组(mKeyFrame[],mKeyFrameCount[])中。
voidKeyFrame:
:
UpdateFrameExecCycle()
更新各个桢所需的周期数。
staticconstintFrameCount(intstageIdx)
返回该stageIdx标示的桢的子桢个数。
Math类中的
inlinefloatDegToRad(constfloatdeg)用于将角度制转换为弧度制。
intTestTeam(intargc,char*argv[])
会在main()中被调用。
在intTestTeam(intargc,char*argv[])中,先调用Setting:
:
Init(),后KeyFrame:
:
init(),WM->Init()(WorldModel:
:
Init())。
Setting类中:
voidSetting:
:
Init()会被TestTeam()调用,在voidSetting:
:
Init()中,先调用InitUserConfData(),此函数未被定义,是一个空函数。
再调用ReadUserConfig("user.cfg");将user.cfg中的配置信息读入。
voidSetting:
:
ReadUserConfig(constchar*fileName)
ReadUserConfig()会调用StrParser:
:
GetValue()将配置信息读入到
ConfigFileName[]和nUserDefineData[]两个数组中。
第一个数组用于存放配置文件信息,第二个数组用于存放用户定义的配置信息。
SoccerSkill类中:
Init()会被TestTeam()调用,在Init()中先后调用SoccerSkill类的如下两个函数:
InitBeamPos();
mRobotTrace.ReadConfigData();
在InitBeamPos()中会用CfgReader:
:
GetLine()从配置文件formation.cfg
(formation:
编队)中读取球队中各球员的起始位置。
读入到staticfloatmBeamPosition[NUM_PLAYERS][3]这个数组中,第一个维度表示球员号,共11个,第二个维度表示坐标,共三个(x,y,z)。
也就是说InitBeamPos()只是从配置文件中将球员的站位读入到了数组中而已。
这些信息何时被使用有待进一步研究。
接下来Init()的动作是:
mRobotTrace.ReadConfigData();
mRobotTrace是一个RobotTrace类的对象,RobotTrace类在trace.h中定义。
是一个非常大的类。
应该是整个工程的核心部分。
应该是主管走路的类(?
),定义了很多非常重要的方法。
后面会把它的公共成员函数列出来。
继续往下走。
voidRobotTrace:
:
ReadConfigData()
此函数调用ReadSampleFromFile()从footstep.cfg中读取footstep格式的信息,然后调用WriteSampleToFile("footstep.log");将数据转换为关键针的格式,写入到footstep.log中,以供使用(?
)。
至此,完成了SoccerSkill:
:
Init()。
这里先把它的公共成员函数列出来:
public:
RobotTrace();
//旋转矩阵形式转换为SFoot格式
voidMatrixToFoot(constfloatiMat[4][3],SFoot*foot);
//SFoot格式转换为旋转矩阵形式
staticvoidFootToMatrix(constSFootfoot,floatiMat[4][3]);
staticvoidFootToMatrix2(constSFootfoot,floatiMat[4][3]);
//根据一只脚得到另一直脚的自然状态位置
staticSFootGetLeftFootByRightFoot(SFootrightFoot);
staticSFootGetRightFootByLeftFoot(SFootleftFoot);
voidSimulateWalkGoBall();
//更新jointAngle
staticvoidUpdateFrameAngle(Frame&frame,//要更新的frame
booluseSelfAngleAsInitAngle//是否用frame自身的角度作为初始值
);
constFootStep&GetFootStep(intidx)const
{
returnmSampleVector[idx];
}
constFootStep&GetFootStep(stringsampleName)
{
AssertLog(mStepMap.find(sampleName)!
=mStepMap.end(),"Error:
(sampleName%s)",sampleName.c_str());
intidx=mStepMap[sampleName];
returnmSampleVector[idx];
}
FootStepGoToBall2(constVector2&ballPos,
floattargetDir,
constSFootfoots[2],
constFootStep&lastFootStep
);
FootStepGoToPoint(constVector2&fTargetPos,floatfTargetDir,constSFootfoot[2],
constFootStep&uCurrFootStep,floatfTorsoDir,constfloatfDisTolerance=0.05f,constfloatfAngleTolerance=Math:
:
DegToRad(10),boolbShouldStop=true);
constFootStep&GetFootStepByActType(ActionTypeactType,constFootStep&lastFootStep);
constmap
{
returnmStepMap;
}
voidReadConfigData();
//点p0到直线(p1p2)的距离
floatPointToLineDist(constfloatp0[2],constfloatp1[2],constfloatp2[2]);
//两脚是否碰撞,f为脚局部坐标系下的参数
boolFootLittleCrash(constSFootf);
//点c到凸包f的距离
floatGetConvexHullDist(constSFootf,constSCentc);
//两脚间距离
floatGetFootDist(constSFootf0,constSFootf1);
//两个重心距离
floatGetCentDist(constSCentc0,constSCentc1);
//脚到目标距离
floatGetFootTargDist(constSFootf,//脚
intfootIdx,//f是左脚或右脚
constSTargett,//目标
floatangleRatio//角度所占比重(0~1.0)
);
//脚的插值
SFootGetCorrespondingFoot(constSFoot&sampleFirstFoot,
constSFoot&sampleLastFoot,
constSFoot&planFirstFoot,
constSFoot&planLastFoot,
constSFoot&sampleFoot);
//根据样本脚和样本重心,得到指定脚对应的重心
SCentGetCorrespondingCent(constSFootsampleFoot,//样本帧中的Foot
constSFootplanFoot,//规划帧的Foot
constSCentsampleCent//样本帧中的cent
);
//计算foot在orig下的坐标vect
voidGetRelativeFoot(constSFootorig,constSFootfoot,SFoot*vect);
//voidGetGlobalFoot(constSFootorig,constSFootrelativeFoot,SFoot*vect);
//计算重心cent在orig下的坐标vect
voidGeRelativeCent(constSFootorig,constSCentcent,SCent*vect);
//计算targ在orig下的坐标vect
voidGetRelativeTarget(constSFootorig,constSTargettarg,STarget*vect);
//计算orig坐标下的脚foot在世界坐标系下的旋转矩阵iMat
voidGetFootMatrix(constSFootorig,constSFootfoot,floatiMat[4][3]);
//计算orig坐标下的cent在世界坐标系下的向量vect
voidGetCentVect(constSFootorig,constSCentcent,floatvect[2]);
SFootGetGlobalFoot(constSFoot&orig,constSFoot&relativeFoot);
//获取样本数
constintGetSampleCount()const
{
returnstatic_cast
}
//根据距离和角度,得到角度所占比重,取值范围:
[0,1.0]
floatGetAngleRatio(floatx,floaty,floatfAimDirection,floatfCurDirection);
//检查阶段名的合法性,不能有冲突。
voidCheckStageName();
//从文件中读FootSetp
voidReadSampleFromFile(constchar*fileName);
voidReadSampleFromArray();
voidWriteSampleToFile(constchar*fileName);
//voidWriteSampleAsStringArray(constchar*fileName);
voidUpdateFrame(Frame&frame,intsupportFootIdx,floatdata[10]);
//更新样本,根据样本名,更新正对应的编号
voidUpdateSample();
boolIsInitSample(intsampleIdx)const
{
return(sampleIdx==InitLeftSampleIdx||sampleIdx==InitRightSampleIdx);
}
voidChangeFootStepForKick(FootStep&footStep);
boolIsTurnAction(intactionType)const
{
return(actionType<=ActTurnLeft_10||actionType<=ActTurnRight_30);
}
boolIsWalkForwardAction(intactionType)const
{
return(actionType==ActWalkFast);
}
boolIsRoundAction(intactionType)const
{
return(actionType<=ActRoundLeft_10||actionType<=ActRoundRight_20);
}
FootStepExecuteTurn(floatangleError,constSFootfoots[2],constFootStep&lastFootStep);
FootStepExecuteWalk(floatangleError,floatdistError,constSFootfoots[2],constFootStep&lastFootStep);
FootStepExecuteRound(floatfaceBallError,floatdistBallError,floatroundError,constSFootfoots[2],constFootStep&lastFootStep);
FootStepExecuteStop(constFootStep&lastFootStep);
boolExecuteKick(constFootStep&lastFootStep,constSFootfoots[2],constVector2ballPos,
constVector2goalUp,constVector2goalDown,constfloatgoalValues[21],
FootStep&footStep);
SFootGetRelativeMoveFoot(constSFootfoots[2],intsupportIdx);
SFootGetLastFootForTurn(constFootStep&sampleFootStep,floatangleError);
SFootGetLastFootForRound(constFootStep&sampleFootStep,Vector2roundCenter,floatroundRadius,floattargetAngle);
SFootGetLastFootForWalk(constFootStep&sampleFootStep,constSFoot&targetFoot);
voidInterpolateFootStep(FootStep&footStep,constSFoot&planFirstFoot,constSFoot&planLastFoot);
voidTest();
以上为RobotTrace类的所有公共成员函数
World:
:
Agent类中:
TestTeam()中会构造一个World:
:
Agent类的对象deepSoul,然后通过deepSoul调用boolAgent:
:
Init(intargc,char*argv[])
再来看看Agent类:
这个类是一个球员还是一个球队?
里面定义了很多重要的决策函数。
类声明如下:
classAgent
{
public:
Agent();
//!
Processesthemessagesreceivedfromtheserver.
boolProcess(constchar*msg);
//!
Initstheagentprogram.
boolInit(intargc,char*argv[]);
//!
Sendscreateagentmessage.
voidCreateAgent();
//!
Sendsinitagentmessage.
voidInitAgent();
//!
Agent'sdecisionmethod.
voidBehave();
voidBehaveForRelease();
voidBehaveForTest();
voidBehaveForWalkToBall();
//!
Behavesbeforekickoff.
voidBehaveBeforeKickOff();
//!
Behavesmourkickoff.
voidBehaveOurKickOff();
//!
Behavestheirkickoff.
voidBehaveOppKickOff();
//!
Behavesplayon.
voidBehavePlayOn();
//!
Behavesgoalieplayon.
voidGoalieBehavePlayOn();
//!
Behavesmykickin.
voidBehaveOurKickIn();
//!
Behavestheirkickin.
voidBehaveOppKickIn();
//!
Behavesmycornerkick.
voidBehaveOurCornerKick();
//!
Behavestheircornerkick.
voidBehaveOppCornerKick();
//Addbyhighlight
voidBehaveOurGoalKickEX();
//!
Behavestheirgoalkick.
voidBehaveOppGoalKick();
//!
Showlogo.
voidShowLogo();
voidTestByCGB();
voidTestByGL();
voidTestByCHX();
voidTestByAnonymous();
//!
Getstheservermessagefilename.
constchar*GetServerMsgFileName()const{returnmServerMsgFileName;}
private:
constchar*mServerMsgFileName;//server消息文件名
};
回到主线,先看被TestTeam()调用的Agent:
:
Init()。
Agent:
:
Init()中,主要是存储球队运行时通过命令行传进来的各个参数,如—host,--help,--teamname,--unmu,--message等等。
然后调用WorldModel:
:
SetTemaName()和WorldModel:
:
SetPlayerNum()设置这些信息。
调用完Agent:
:
Init()后,TestTeam()会调用Agent:
:
ShowLogo(),然后调用WorldModel:
:
Init()。
WorldModel类
WorldModel:
:
Init()只会被调用一次,在Init()中,先通过AgentObject类的对象mAgentObject调用AgentObject:
:
Init()。
先看AgentObject:
:
Init()。
AgentObject:
:
Init()调用InitRobotStateMap()来完成mRobotStateNameMap[]数组的初始化,存入机器人所有状态的名字:
mRobotStateNameMap[RS_Stand]="RS_Stand";
mRobotStateNameMap[RS_Lie_Down]="RS_Lie_Down";
mRobotStateNameMap[RS_Lie_Up]="RS_
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 深入浅出 FantasiaXN 洪峰
