本博客记录一下26年暑期参与的协同感知建图与导航的前期准备工作,主要记录一下我当时为整个项目做整体的架构设计的思考
我们要研究的问题是:在城市的未知环境里,无人机和地面小车如何协同感知与建图。至于为什么选择这个问题,以及研究背景和当前面临的主要问题等详细信息,这里先暂且按下不表,留在下一章交给我们的组长蒋书恒详述。
因此我们需要先搞一个相对复杂的城市仿真环境——
在这个环境中模拟城市建筑;还原无人机和地面小车这两种异构平台;并为它们构建搭载在其上的各类传感器。
另外多说一句,在最终的具体呈现场景的选择上,最后选择了战场场景,让 Agent 去操控 UE 里的小车和无人机完成相应的作战任务。
那么接下来,我将会分为技术选型与框架搭建的两大部分,拆解还原当时的构建思路。
为什么是战场,为什么是 UE
之所以选择战场,是因为相比物流运输这类相对固定的场景,战场环境对决策、协同、配合能力的要求要高得多,情况也更加多变,不容易在有限的规则下被过拟合得太严重,能更真实地检验 Agent 的协同感知与决策能力。
引擎选 UE,则是因为2020 年疫情当时在家实在太闲,和好哥们白极冰一拍即合,决定自己做游戏来着的,UE 就是那时候的起点。那个时代还没有 AI ,我们只能自己照着社区的视频教程,一个节点一个节点地连接蓝图(UE的一个内置的图形化编程语言),去慢慢弄明白每个节点是干什么的,深刻体会了一顿古法编程的乐趣。社区改版之前,我还挺沉迷收集里面的学习勋章,hhhhhhhh。
因此这次选它,一是自己用着比较舒服,二是看中了它的功能、生态,以及底下的 OOP 设计。
SensorCore:给仿真里的传感器写驱动
为了能够较好地完成仿真任务,接下来自然需要设计一套传感器组件,为整个仿真环境实现较为真实的模拟效果
首先对于传感器的基础设计上,除了每个传感器的基础功能的实现之外,还搭载了自己的噪声模型,例如惯性导航计会引入累计漂移误差,让仿真数据更贴近真实传感器的输出特性。
通信方面的设计上对标了 ROS2,一方面是对接了 ROS 里 topic 的发布订阅模式;二是数据格式上直接对接 ROS 的传感器消息,比如 3D 激光雷达回传的点云,拿到 Rviz 里就能看,不用额外转换。

这样设计的好处是,一方面可以很方便地接入现成的算法模型进行验证,另一方面,我们在仿真环境里跑出来的算法,也可以直接迁移到采用 ROS 系统的真实硬件平台上运行。换句话说,对于上层的算法模型而言,底层究竟是仿真还是真实硬件,其实是完全透明的,它们只关心 topic 上发布的数据,并不知道,也不需要知道这些数据究竟来自仿真环境还是真实传感器。
至于具体是如何与 ROS2 打通通信的,插件本身其实并不直接依赖 ROS,而是通过 TempoROS 这个开源项目作为桥接层来实现的,这部分留到下一节的通信架构将会详细展开。
此外,插件包里的各类传感器组件,本质上都是一个个可以独立拿出来用的"零件",在 UE 的 Actor 组件面板里可以很自由地把它们挂载、组装到不同的平台上,按需搭配。比如给无人机挂上 3D 激光雷达和 RGB 相机,用来完成空中视角的建图与识别任务;给地面小车挂上 2D 激光雷达和里程计,用来完成贴地导航与避障任务,各个平台都可以根据自己的任务类型选择合适的传感器进行安装。
Agent 和 UE 之间的通信
前面提到的 SensorCore 插件,解决的是"如何在 UE 里采集到贴近真实的传感器数据"这一层问题。但光有数据还不够,我们真正想做的,是让一个具备决策能力的 AI Agent 去理解这些数据,并反过来指挥 UE 里的 Actor 完成相应的行动,这也是我们做这整套仿真环境最终想要服务的目标。而那些基于传感器数据训练出来的 VLA、SLAM 建图导航等小型算法模块,则扮演 Actor 的"小脑"角色,负责一些更局部、更即时的反应。围绕这个思路,设计了如图所示的通信架构。

从底层来看,每一个 Actor 内部都挂载着若干传感器和控制驱动模块,它们统一通过 TempoROS 这个通信桥接层,注册为对应的 ROS topic。上层的 Agent 只需要订阅相应传感器的 topic 就能拿到需要的数据;而当需要下发控制指令时,只需向对应的控制驱动 topic 发布命令,Actor 上的驱动模块就会自动做出相应的响应——想要操控小车移动,只需要发布预期的速度方向 cmd_vel,小车底层的驱动就会自动协调四个轮子的转速,逐步逼近这个目标速度方向。
值得一提的是,这里的** Agent 并不需要和 UE 仿真环境运行在同一台机器上**,完全可以分布在其他主机上。实际部署时,我们用一台性能较好的台式机作为主机来运行 UE 仿真并发布 ROS 消息,再通过交换机组建了一个局域网,这样其他主机上的 Agent 只要接入这个局域网,就都能订阅到相应的数据,不受限于本机运行。
同样地,当 Agent 调用一些已经训练好的模型或算法模块时,走的也是类似的通信链路:模型从 ROS topic 上订阅所需数据,计算完成后,再把控制指令发布回对应的控制 topic。
另外,考虑到有一些简单的控制接口并不需要绕这么一大圈,还专门设计了 Agent UE MCP 插件,用来实现旁路通信,让数据可以绕开 TempoROS 和 ROS2 的 topic 转发流程,直接进行点对点通信。
地图准备
首先遇到的一个比较"难绷"的问题是,Fab 里下载的城市素材疑似是程序化生成的,地图里虽然设计了高架和地下道,但两者之间实际上并不连通(见图)。因此我们要做的第一步,就是在合适的位置手动加上缓坡,把上下两层道路重新连接起来。

第二步,是划分地图区域,确定哪一侧作为进攻方(也就是 Agent 所在的阵营),哪一侧作为防守方(沿用游戏引擎自带的传统 AI 阵营)。

可以很清楚地看到,我们这张城市地图中间有一条河流横穿而过,很自然地把整座城市划分成了两部分。其中右侧区域更为开阔,纵深也更深,因此我们选择把它划为防守方区域。
第三步,是实现地图里的一些装备设施。由于时间有限,目前只做了近防炮和榴弹炮两种固定武器设施。这就引出了下一节的内容:设施准备。
设施准备
近防炮
近防炮的主体沿用了 Fab 商城里面的 1130 近防炮素材,火控算法的设计其实还算比较简单,核心思路如下:雷达搜索目标 → 提前量计算 → 转炮瞄准 → 开火条件判断 → 开火。
为了平衡性考虑,进一步加入了开火升温、停火冷却降温、过热则无法开火的设计,和很多游戏里面的固定机枪的射击机制类似。
雷达索敌这块目前实现得还比较简单,并不是去模拟真实的雷达回波检测,而是直接以当前炮塔为圆心,定期在半径 3000 米的球形范围内做射线检测。当然,这里也考虑了建筑物的遮挡,加入了可视性检查,确保炮台不会隔着墙锁定目标。
提前量的计算同样走的是一个比较简化的思路,就是很简单的差分计算,假设目标是匀直运动的,再加上当前炮弹的抛物线弹道,而且并不是去求精确的解析解,而是直接二分逼近解一个数值解出来,保证解算速度足够快。
榴弹炮
榴弹炮的部分则简单得多。榴弹炮主要负责打击固定目标,因此火控要做的事情也很纯粹:接收目标坐标,解算弹道,下达炮口角度。
但是需要注意的是,该弹道解算也是使用的是二分法逼近的数值解,因此仍然存在一定的误差,为此参考真实的火炮的发射流程,加入了一个"校射"机制:根据弹着点和目标点之间的误差,在下一轮射击时进行修正。这里为了简化处理,弹着点坐标直接从 UE 场景中读取获得。
相比之下,近防炮虽然同样存在解算误差,但由于持续开火,而且交火距离较近,可以实现范围火力覆盖来弥补单发精度上的不足,因此只有榴弹炮设计有校射机制。
无人机与小车
至于无人机和地面小车这两类平台,它们的核心部分主要已经在前面分散讲过了:传感器插件负责让它们具备感知能力,ROS 通信链路负责把这些数据和控制指令串联起来,而底层驱动则接收 cmd_vel 这类指令完成实际的运动控制,这里就不再重复展开。
至此,仿真环境这部分的技术选型与框架搭建就基本告一段落了。而我们真正想要研究的核心工作——无人机与地面小车在城市未知环境下的协同感知与建图,将会在下一篇文章中详细展开。





评论
Discussion · 0登录后参与讨论 · Sign in to join the discussion
用 GitHub 账号登录,就可以评论、回复和表情回应。
使用 GitHub 登录还没有评论 · 来写下第一条吧。