RoboCup仿真2D入门:从零编译agent2d到球队上场
2026/9/15 17:05:20 网站建设 项目流程

RoboCup 仿真2D 入门,最劝退人的往往不是战术代码的复杂,而是“编译”和“上场”这两道坎。我见过不少朋友下载了知名开源球队 agent2d,结果卡在 make 报错、连不上服务器这类基础问题上,误以为自己不适合搞机器人足球。其实大部分问题都能在半小时内解决。这篇笔记记录的是我从零编译 agent2d、启动模拟器服务器、把一支球队真正跑到赛场上的完整过程,适合已经装好 Linux 环境、准备正式入坑 RoboCup 仿真2D 的初学者。看完之后,你应该能在监视器里看到 11 个属于自己球队的小人在场上跑起来。

1. 一场仿真2D比赛是如何把“代码”变成“球队”的

1.1 服务器与客户端:你的球队其实是个网络程序

一上来得先把概念理清,否则后面操作全是盲区。RoboCup 仿真2D 并不是像实况足球那样,你在一个有画面的软件里用一个球队去和电脑踢。它的核心架构是“服务器 + 客户端”:服务器程序叫 rcssserver,负责模拟足球场地、球员身体、碰撞、裁判规则,还有最重要的“感知与动作周期”。你的球队代码,本质上是一个网络客户端程序,和服务器的交互一共有两个动作:每个周期服务器把本队每个球员能看到的信息发送过来,客户端程序处理完这些信息之后,再把每个球员的动作命令(跑动、踢球、转身等)发回去。整个比赛就是在这样一个高频的“收发数据”循环中进行的。

理解了这一点,你就会明白“让球队上场”的本质:把你的程序连上 rcssserver,按照它的网络协议完成注册和信息交换。所以球队代码编译出来的东西,不是像 .exe 一样双击就弹出一个界面的游戏,而是一个面向服务器的客户端进程。

1.2 为什么不能直接下载二进制,必须先自己编译

很多新手会问:agent2d 这个球队,官方不是有源码包吗,为什么不能直接给我一个能跑的二进制?原因有几点:

  • 这些代码是用 C++ 写的,依赖了系统库(boost、zlib 等等)。不同发行版、不同编译器版本,原来编译出来的二进制很可能跑不起来,官方也只能提供源码。
  • RoboCup 仿真2D 比赛规则要求队伍提交的是可执行程序,参赛队伍必须保证自己的代码能在官方指定环境的机器上编译运行。不会有人替你编译。
  • 更实际的原因是,你后面要修改战术、调参、加代码,所有这些操作最后都要重新编译才能生效。所以“编译”不是一次性工具,而是你整个 RoboCup 周期里反复使用的基本功。

这篇文章的目标就是让你跑通一条最基础的链路:拿到 agent2d 源码 → 编译出可执行文件 → 连接 rcssserver → 在监视器里看到自己的球队上场。后续你在这个链路上做的任何战术修改,都只是“改代码 → 重新 make → 重新跑”。

1.3 为什么只生成一个可执行文件,却能控制 11 个人?

这里顺便说一个让不少人困惑的点。第一次看到 agent2d 编译产物时,我以为会生成 11 个球员程序,结果就一个 soccer。实际上,agent2d 用一个进程管理全部球员:进程内部会创建 11 个 player agent(对应场上 1-11 号),再加上一个教练 agent(12 号),每个 agent 单独与服务器建立连接,但逻辑都在同一个进程里。这种设计让球队内部通信变得简单高效。所以之后你跑“队伍”,只需要启动一个进程,而不是开 11 个终端手动复制粘贴。

2. 编译前必须落实的三件事:依赖、源码和目录认知

这一节内容,说白了就是“磨刀不误砍柴工”。我见过太多人跳过依赖管理,直接 clone 源码开始 make,结果报错信息一行接一行,最后心态崩了。先把基础打牢,后面编译会顺畅得多。

2.1 在 Ubuntu 上安装依赖:boost、zlib 和编译工具链

我以 Ubuntu 为例(建议 20.04 或 22.04,LTS 版本用起来省心)。首先把编译工具和相关库一次性装齐:

sudo apt update sudo apt install -y build-essential cmake git zlib1g-dev libboost-all-dev

逐个解释下为什么需要这些:

  • build-essential:包含 gcc、g++、make 等基础编译工具。C++ 项目没它寸步难行。
  • cmake:新版 agent2d 和 librcsc 的 CMake 构建方式会用到。老一辈的 autotools 方式不需要,但装了不亏。
  • git:拉取源码用,RoboCup 生态的项目基本都在 GitHub 上。
  • zlib1g-dev:这是 agent2d 编译的一个常见坑。simulator 和客户端之间的网络传输数据是经过 zlib 压缩的,agent2d 代码里直接调用了 zlib 的接口。如果没装这个开发库,编译到链接阶段时经常会出现/usr/bin/ld: cannot find -lz之类的错误。
  • libboost-all-dev:agent2d 大量使用 boost 库,比如字符串处理、socket、线程等。直接装全家桶最省事,没必要去细抠具体依赖了哪一个模块。

如果你的环境里还没有模拟器软件,还需要安装 rcssserver 和 rcssmonitor。优先用 apt 试一下:

sudo apt install -y rcssserver rcssmonitor

如果 Ubuntu 仓库里没有(新版 Ubuntu 有时会移除这些包),就从源码编译。顺序是 rcssbase → rcssserver → rcssmonitor,依赖要额外装 qtbase5-dev:

sudo apt install -y qtbase5-dev git clone https://github.com/rcsoccersim/rcssbase.git git clone https://github.com/rcsoccersim/rcssserver.git git clone https://github.com/rcsoccersim/rcssmonitor.git

三个项目都是 cmake 构建,分别进目录执行mkdir build && cd build && cmake .. && make && sudo make install即可。装上之后终端里就能敲 rcssserver 和 rcssmonitor 了。

2.2 获取源码:agent2d 和 librcsc 都要拉下来

RoboCup 仿真2D 的经典开源球队是日本的 Helios 团队发布的 agent2d,几乎所有入门教程都会提它。很多人不知道的是,agent2d 还依赖一个独立的基础库 librcsc,里面封装了坐标系换算、几何计算、动作链、消息解析等底层能力。两者必须同时拿到:

mkdir -p ~/robocup2d && cd ~/robocup2d git clone https://github.com/helios-base/librcsc.git git clone https://github.com/helios-base/agent2d.git

如果你是在 GitHub 上找的是别的组织维护的 fork 版本,clone 之后一定要注意检查有没有子模块(submodule)。agent2d 的一些 fork 会把 librcsc 作为子模块引用,你需要执行:

git submodule update --init --recursive

不然编译时会发现找不到 librcsc 的头文件,然后又一脸懵。

2.3 源码目录结构:动手前先花五分钟看懂布局

代码拉下来后,建议先 ls 看一下目录,心里有个地图。

cd ~/robocup2d/agent2d && ls -l cd ~/robocup2d/librcsc && ls -l

agent2d 根目录下会看到 src、conf、Makefile 之类的东西。需要重点关注:

  • src:球员主体逻辑,包括基础动作、决策模型、阵型执行等;
  • src/coach:教练智能体,负责阵型调整、策略选择等;
  • conf:配置文件目录,里面定义了默认阵型、比赛条件等;
  • Makefile.conf:编译配置文件,可以在这里指定 librcsc 的路径、是否开启调试等。

librcsc 目录下则是各种基础模块。这个库不是你日常频繁修改的地方,大多数人的代码改动都集中在 agent2d 的 src 里。但编译顺序上,librcsc 必须先编译并安装,因为 agent2d 链接时要用到它的库文件。

3. agent2d 完整编译流程:从基础库到你的可执行文件

3.1 第一步:编译并安装 librcsc 基础库

新版 librcsc 默认用 CMake 构建。推荐这样做:

cd ~/robocup2d/librcsc mkdir build && cd build cmake .. make -j$(nproc) sudo make install sudo ldconfig

解释一下其中几个关键操作。make -j$(nproc)的意思是并行编译,核数越多越快;首次编译可以不用 -j,方便看到完整日志。sudo make install会把库文件和头文件安装到系统默认路径(一般是 /usr/local/lib 和 /usr/local/include/librcsc)。最后那句 sudo ldconfig 非常重要,它让系统刷新动态库缓存,否则后面运行 agent2d 时可能报错找不到 liblibrcsc.so。

如果库比较老,或者你拿到的是 autotools 时代的版本,见不到 CMakeLists.txt,那就用传统方式:

cd ~/robocup2d/librcsc autoreconf -i ./configure make -j$(nproc) sudo make install sudo ldconfig

这里 autoreconf -i 的作用是生成 configure 脚本,老版本源码里往往没直接带。

安装完成后,可以检查一下库是否就位:

ls /usr/local/lib | grep librcsc

看到 liblibrcsc.a、liblibrcsc.so 之类的文件,说明基础库部分稳了。

3.2 第二步:编译 agent2d 本体

librcsc 就绪后,回到 agent2d 目录直接编译:

cd ~/robocup2d/agent2d make clean make -j$(nproc)

这里我不推荐跳过 make clean。因为你可能之前编译失败过,残留的 .o 文件会干扰新的编译,甚至导致修改不生效。每次更换编译选项、升级源码后,先 clean 再 make 是 RoboCup 圈里公认的好习惯。

如果编译过程中提示找不到 librcsc,比如fatal error: librcsc/... No such file or directory,先看一眼 agent2d 根目录下的 Makefile.conf 里有没有指定库路径。默认情况下它会去 /usr/local/include 和 /usr/local/lib 找,而 librcsc 默认也安在这两个位置,所以正常情况是不用手动配的。只有当你把 librcsc 装到了自定义路径(比如--prefix=/opt/librcsc)时,才需要手动改 Makefile.conf:

cppflags = -I/opt/librcsc/include ldflags = -L/opt/librcsc/lib -lz

注意最后那个 -lz,zlib 库的链接需求在这里体现。

3.3 编译产物和改名技巧:让球队拥有自己的名字

编译完成后,找一下生成的可执行文件:

find . -name soccer -type f 2>/dev/null

不同版本的 agent2d 生成位置有差异,有的在根目录,有的在 src 目录下。看到结果后,比如显示./src/soccer,那运行路径就是 src/soccer;如果显示./soccer,就直接在根目录运行。

顺便看一眼教练程序:

find . -name coach -type f 2>/dev/null

soccer 是主力程序,比赛时跑它。coach 是教练智能体,基础测试时可以不启动。如果你想把它改名成自己的队伍名(比如 MyTeam):

cp src/soccer MyTeam ./MyTeam --help

复制而不是直接 mv,是为了保留原始编译产物。以后每次重新编译,只需要把新的 soccer 再复制一份过去即可。这个“复制可执行文件”的习惯很实用,因为正式比赛时你可能准备多个队伍版本对比,复制改名是最快的区分方式。

4. 上场实操:连接服务器、看监视器、和另一支球队踢一场

代码编译好了,接下来就是最激动人心的“上场”环节。先把模拟器跑起来,再让球队程序连进去。

4.1 启动模拟器服务器和监视器

打开一个终端,启动服务器:

rcssserver

正常情况下终端会停在某个状态等待客户端连接,不会有报错。再开一个终端,启动监视器:

rcssmonitor

监视器会弹出一个图形界面,显示一个绿色球场。注意监视器连接的是服务器的 6001 端口,用来接收可视化数据;球员客户端连接的是 6000 端口。两个端口不能搞混。如果你是在本机测试,默认都能连通;如果服务器在另一台机器,监视器和球队程序里都要指定 IP。

4.2 用命令行参数启动你的球队

回到 agent2d 目录,运行编译好的程序。根据你刚才 find 的结果,假设 soccer 在根目录:

cd ~/robocup2d/agent2d ./soccer -t MyTeam

如果 soccer 在 src 下,就执行:

./src/soccer -t MyTeam

这里 -t 指定队伍名,会在监视器显示出来。还有几个常用参数:

  • --host=127.0.0.1:连接服务器的 IP,默认本机;
  • -p 6000:连接服务器的端口,默认就是 6000;
  • -h--help:查看全部参数。

球队程序跑起来后,终端里会持续输出日志。如果你看到大量状态信息,而不是 Connection refused,说明网络层面已经通了。

4.3 怎么确认你的球队真的“上场”了

很多第一次跑的人,看到日志输出反而慌了,不知道算没算成功。我从三个角度给你判断标准:

  1. 看日志:agent2d 启动后会打印队伍名、连接信息,随后持续输出球员的感知和决策日志。如果几秒钟内没有“连接失败”“初始化错误”,基本就成功了。
  2. 看监视器:这是最直观的方式。球场里应该出现 22 个小人,分成两队。如果你的球队程序正常,你的 11 个小人应该出现在球场中圈附近;另一队的 11 个小人可能是 AI 默认行为或者什么都不做。
  3. 看服务器终端:服务器端会打印有球员注册进来的信息,比如某些版本的 rcssserver 会输出 registered team 之类的字样。

如果比赛没有自动开始(服务器默认可能停在开球前的准备状态),可以对监视器窗口里的操作按钮点一下,比如 Kick Off 或 Play,让比赛跑起来。这时应该能看到球员开始跑动、追球。

4.4 本地双人对战:让你的球队和另一个队真正踢起来

想测试自己的队伍强度,最简单的方法是再启动一支队伍,让它和当前球队同场竞技:

./soccer -t Opponent

注意一点:第二个进程也必须用不同队伍名,如果两个进程都叫 MyTeam,服务器会认为它们是同一支队伍,导致注册出问题。两个进程都连 6000 端口,服务器根据队伍名自动把球员分成两队。比赛开始后,监视器里两支球队会按照各自的逻辑抢球、防守、进攻。

这个“双开对战”是本地迭代战术时的核心测试方式。实际比赛中,你的队伍会作为客户端连接官方服务器的某个端口。但本地自测时,双开两个 agent2d 进程就够了。我这里再给一个更省事的启动脚本,保存为 start.sh:

#!/bin/bash cd ~/robocup2d/agent2d ./soccer -t MyTeam & sleep 1 ./soccer -t Opponent & wait

如果你的 soccer 在 src 下,记得把脚本里的路径改成 ./src/soccer。给脚本加执行权限后,以后测试一句话搞定:

chmod +x start.sh ./start.sh

5. 编译和连接过程中的常见坑,以及我的排查思路

这一节是我写完整篇文章最想强调的部分。RoboCup 仿真2D 的门槛并不是算法,而是各种工具链和网络层面的零碎问题。我把新手最常踩的几个坑整理一下,每个都附带排查链路。

5.1 编译时报错:找不到 boost、找不到 zlib、找不到 librcsc

编译期的问题,本质就是“头文件没找到”和“库没找到”两类。

第一类:头文件缺失。

fatal error: boost/asio.hpp: No such file or directory

这说明 boost 开发库没装上,或者装的不全。去执行:

sudo apt install -y libboost-all-dev

装完后重新 make clean && make。

第二类:链接器找不到库。

/usr/bin/ld: cannot find -lz

-lz 是链接 zlib 库的标记。缺这个就装:

sudo apt install -y zlib1g-dev

同理,如果报cannot find -lboost_...之类,也基本是 boost 相关 deb 包没装全。

第三类:找不到 librcsc 里的符号。

undefined reference to `librcsc::...`

一般是 librcsc 没安装成功,或者安装后没有执行 ldconfig。先验证库文件是否存在,再 sudo ldconfig 刷新。再不行,把 librcsc 重编重装一遍。我遇到过最诡异的情况是系统里同时存在多个 librcsc 版本,agent2d 链接了旧版,导致运行时报一堆符号缺失。解决办法是把自定义路径下的旧安装清干净,只保留系统默认目录的那个版本。

5.2 运行时报错:连接不上服务器

这个问题的核心是网络链路没通。排查顺序:

  1. 确认 rcssserver 真的在运行。终端执行ps aux | grep rcssserver,看到进程再往下查。
  2. 确认端口正确。客户端默认连 6000,监视器用 6001。千万别把客户端程序配置成 6001 去连。
  3. 确认 host 正确。在本机跑用 127.0.0.1 没问题;如果用到虚拟机,需要特别注意网络模式的区别,建议直接用桥接或 host-only,省得折腾端口映射。
  4. 确认防火墙没拦截。Ubuntu 默认不拦本机回环,但如果你在服务器上开了 ufw,记得放行 6000/6001/6002/6003 这些端口。

还有一个隐藏情况:如果你之前手动启动过 soccer,进程没退出,端口被占用了。先ps aux | grep soccer看一下,有残留就 kill 掉再重新启动。

5.3 监视器里没有球员,或者球员数量不对

如果你已经启动了球队程序,日志也正常,但监视器里空荡荡,按这个顺序排查:

  1. 检查监视器是否真的连上了服务器。可以退出去重开一次 rcssmonitor,如果服务器已经就绪,窗口里应该会刷新出球场。
  2. 检查球队进程是否还在。终端里跑 soccer 的窗口如果报错退出了,说明程序内部出现了终止性错误。把最后几十行日志贴出来找原因。
  3. 检查队伍名是否唯一。两个进程用同名时,服务器会表现得很奇怪,比如球员数量不对、某个进程被踢掉。给每个进程指定不同的 -t 即可。
  4. 检查时间信息。监视器窗口角落如果显示比赛时间一直不动,说明服务器没开球,用监视器里的按钮手动开赛即可。

从我的经验看,80% 的“看不见球员”问题出在第三个:自己跟自己同名了。因为 agent2d 默认队伍名可能是一样的,你同时在终端跑两个,第二个就会出问题。

5.4 关于自动开球和正式比赛的几个延伸注意点

如果你以后要跑离线批量测试,手动点监视器按钮太慢。可以了解下服务器支持的自动模式,比如某些版本 rcssserver 支持通过参数开启自动开球:

rcssserver --auto_mode=true --auto_kick_off=true

具体参数名因版本而异,建议rcssserver --help看一下。不过本地入门阶段,手动点一下开球按钮完全够用,没必要在这一步花太多时间。

正式比赛环境中,你的球队会被要求在指定时间连接服务器并完成注册。最常见的失败原因是连接时机不对:有的队伍主程序默认是启动后立即连接,如果你启动太早,服务器还没就绪,连接就失败了。这种情况下你可以把球队程序写一个简单的重试循环,或者手动确认服务器就绪后再启动进程。别小看这种细节,真到了比赛现场,紧张到连服务器没启动就点了运行也不是没有的事。

最后再分享一点个人体会

在 RoboCup 仿真2D 这条路上,编译和上场只是起点,但也是很关键的一步。我自己的切身体会是,编译这类 C++ 项目时,耐心比技术重要:报错信息要看完整,不要只看第一行;修改环境配置后一定要 make clean,否则旧的对象文件会反复坑你;链接阶段的“undefined reference”大多数不是代码问题,而是库没装好。

过了编译这关之后,我强烈建议你把“编译-开服-跑队-开赛-看回放”这条链路脚本化。哪怕只是一个 50 行的 shell 脚本,也能帮你节省大量重复劳动。后面当你开始调阵型、改动作链、写战术时,每一次迭代都是重新走一遍这条链路。尽早把它弄顺,后面才能真正把精力花在足球智能本身,而不是被工具链拖后腿。

嗯,这篇就到这。下一篇我打算写一写 agent2d 里最基础的“球员决策循环”和“坐标系转换”这块内容。如果你也在搞 RoboCup 仿真2D,欢迎一起交流踩坑经验。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询