1.比赛环境的搭建

1.1 查看本机wsl子系统的版本号

==wsl -l -v==

wsl.png

1.2 导入命令

首先进入想要导入的目录,如图我在E盘中创建了wslstorage目录,将压缩包移到此目录下,打开cmd输入以下代码

==wsl –import ubuntu ./wsl ./Ubuntu.tar==

daoru.png

补充:

注销wsl子系统:==wsl –unregister Ubuntu==

成功导入以后,我们就基本完成了比赛环境的搭建,这之后我们还需要一个roboviz,可以让我们用肉眼观察到仿真足球赛中发生的状况,详细的下载地址可以看学长的博客,上面写的很详细https://blog.flyme.tech/2020/11/29/robocup3d_wsl/

一切完成后,大功告成

下面我给大家演示以下如何进入我们的比赛环境,在cmd中输入==wsl==命令进入wsl子系统,进入后,输入==rcsoccersim3d==命令,如下所示

cwrc.png

接着打开roboviz,这样我们环境的搭建就完成了。

play.png

2.常用函数简介

WorldModel类

WorldModel类保存了场上许多的信息,是机器人利用场上信息的重要途径,它在机器人NaoBehavior中实例化了一个对象指针WorldModel。

在机器人策略中使用时,应使用worldmodel->方法名([参数列表])的形式。

1
2
3
4
// 返回当前机器人的编号
inline int getUNum() const {
return uNum;
}

常用于判断自己是几号,可以在策略中设定类似“如果是几号球员,就执行什么动作”

例如在初始化beam函数中,根据unum来分配球员位置

1
2
3
4
5
6
7
8
// 如果是一号球员则它的位置是
if (worldModel -> getUNum() == 1)
{
beamX = -15;
beamY = 0;
beamAngel = 0;
}
else if ... (其他情况)
1
2
3
4
// 返回比赛当前时间(距离开始的秒数)(返回的是一个浮点数)
inline double getGameTime() const {
return gametime;
}
1
2
3
4
// 返回当前比赛的周期数(每一秒是20个周期,一个周期agent和server进行通讯,server进行仿真处理后将场上的信息返回发送给agent)
inline unsigned long getCycle() const {
return cycle;
}
1
2
3
4
5
6
7
// 获取编号为i的对象的位置(以下两函数仅名称不同,效果是一样的)
inline VecPosition getOpponent(const int &i) const {
return worldObjects[i].pos;
}
inline VecPosition getTeammate(const int &i) const {
return worldObjects[i].pos;
}

如何利用这个函数来检索指定的球员的位置呢?

在头文件WorldObject.h中,定义了一个枚举worldObjType内容如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
enum WorldObjType {   // Types of objects
WO_BALL,

// Self and Teammates
WO_TEAMMATE1,
WO_TEAMMATE2,
WO_TEAMMATE3,
WO_TEAMMATE4,
WO_TEAMMATE5,
WO_TEAMMATE6,
WO_TEAMMATE7,
WO_TEAMMATE8,
WO_TEAMMATE9,
WO_TEAMMATE10,
WO_TEAMMATE11,

// Opponents
WO_OPPONENT1,
WO_OPPONENT2,
WO_OPPONENT3,
WO_OPPONENT4,
WO_OPPONENT5,
WO_OPPONENT6,
WO_OPPONENT7,
WO_OPPONENT8,
WO_OPPONENT9,
WO_OPPONENT10,
WO_OPPONENT11,


// 后面还有很多比如关节什么的枚举量
};

众所周知枚举类其实就是给整数起了个别名,例如此处第一个枚举WO_BALL

在代码中和0作用一样,此后的每一个枚举在前一个的基础上加1,所以检索球员的代码可以这样写:

1
2
3
4
for (int i = WO_OPPONENT; i<WO_OPPONENT + OPPONENT_NUM; i++){
VecPosition pos = worldModel->getOpponent(i);
// ...
}
1
2
3
4
// 获取编号为index的WorldObject的指针
inline WorldObject* getWorldObject(int index){
return &worldObjects[index];
}

上文的getOpponent与此函数内容类似,都是在worldObjects数组中获取对应下标的对象

WorldObjects类描述了某物体(球,球员等)的一些基本属性,可以说,是WorldObject们构成了WorldModel。

关于WorldObjects类此处不展开介绍,其方法与属性都浅显易懂,有兴趣自行学习。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 以下还有一些常用函数

// 获取此球员的位置
inline VecPosition getMyPosition() const {
return myPosition;
};

// 获取球的位置
inline VecPosition getBall() const {
return worldObjects[WO_BALL].pos;
};

// 获取当前比赛模式(比赛进行到不同阶段会有不同模式,比如任意球,门球...有兴趣可以查看源码自行观看)
inline VecPosition getPlayMode() const {
return playMode;
}

// 获取机器人是否摔跤
inline bool isFallen() const {
return fFallen;
}

Naobehaviors类

Naobehaviors类中有许许多多机器人可以执行的高级动作,怎么使用只要关注他的返回值即可,返回值为SkillType的可以直接在selectskill()中return(或者在其他返回值为SkillType的函数中return,比如gototarget()调用了gototargetrelative(),gototargetrelative调用了getwalk()等),返回值为VecPosition的可以用表达式和判断条件中,Bool类型的判断情况的函数,多用于条件判断。下面是一些常用的:

1
void NaoBehavior::beam( double& beamX, double& beamY, double& beamAngle );

决定球员上场位置的函数,可以依次对不同的number给其beamX和beamY赋值,也可以都设为default

1
double trim(const double& value,const double& min, const double& max);

trim:修剪。返回值为经过判断修改的value,满足大于min,小于max

—————————分割线(持续更新中)—————————-