RosTrans¶
RosTrans 是 RflySim 工具链中的 ROS 多协议转换网关。它把外部的 UDP、串口、共享内存或 MAVLink 字节流转换为 ROS1/ROS2 的 Topic/Service,也能把 ROS 控制消息反向打包发送给仿真器、飞控或 UE4,从而让标准 ROS 算法生态无缝接入 RflySim 仿真闭环。
一句话理解:RosTrans 是一个规则驱动、插件化的多协议网关,本身不绑定任何具体协议,而是用统一的转发规则把“从哪里来、到哪里去、怎么转换”描述清楚。
软件定位¶
当实验需要把 RflySim 的数据接入 ROS 生态时,RosTrans 就会变得重要,典型场景包括:
- 用标准 MAVROS 风格接口(
/mavros/...)控制 CopterSim 或 PX4 仿真飞机 - 把 RflySim3D/UE4 的图像、深度、点云、激光雷达等视觉数据发布为 ROS
sensor_msgs - 让 ROS Offboard 算法节点直接给仿真飞机发位置/速度/姿态指令
- 把真实 Pixhawk(串口)或 PX4 SITL(UDP)的 MAVLink 透明路由给 QGC 与 MAVROS
因此,RosTrans 解决的不是“仿真怎么做”,而是“仿真数据如何与 ROS 算法双向打通”。
在工具链中的角色¶
RosTrans 处于 RflySim 仿真组件与 ROS 算法生态之间,承担双向桥接(见上方拓扑图)。
正向:外部数据源(UDP / Serial / Mem / MAVLink / UE4 / CopterSim)经 Transport 收发 → ForwardRule 选择链路 → Codec 编解码 → ROS Adapter 发布/订阅/服务 → ROS1/ROS2 算法生态。
反向:ROS 控制消息经 Adapter 收到后,由 Codec 编码成目标协议字节,再经 Transport 发送给 CopterSim / PX4 / UE4 / QGC / 外部设备。
一、工作原理¶
1. 核心思想:四件事解耦¶
RosTrans 最关键的设计,是把下面四件事彻底分开,互不依赖:
| 关注点 | 由谁负责 | 解决的问题 |
|---|---|---|
| 传输 | Transport(UDP/串口/共享内存/字节路由) | 面向字节流的异步收发 |
| 协议转换 | Codec(编解码器) | 外部协议字节 ↔ ROS 序列化消息 |
| ROS 版本差异 | ROS Adapter(ROS1/ROS2) | 屏蔽 roscpp 与 rclcpp 的发布订阅差异 |
| 业务规则生成 | 业务插件(DllModel/MavRos/Vision/UE) | 把具体场景翻译成动态转发规则 |
正因为解耦,新增一种协议通常不用改主程序,只需写一个 Codec 并生成一条规则即可。
2. 总体架构¶
- ParamManager:读取
rostrans.param与rostrans.filter,决定启用哪些业务插件、端口和话题。 - PluginManager:用 Qt 插件机制按优先级动态加载 ROS 适配器与业务插件。
- DataTransCore:转发核心,内含
RosTransManager(规则/线程/生命周期)、MessageProcessor(Topic/Service 管道)与BytesRouter(透明字节路由)。
为什么要插件化
ROS1 的 roscpp 和 ROS2 的 rclcpp 依赖、初始化方式、运行时上下文都不同。RosTrans 用统一的 BaseROSAdapter 接口,把 ROS1/ROS2 适配器编译成独立动态库,按当前 ROS_VERSION/ROS_DISTRO 环境加载。这样核心转发层既不直接依赖 ROS1 也不依赖 ROS2,避免符号冲突与环境耦合。
3. 转发规则模型 ForwardRule¶
ForwardRule 是 RosTrans 的核心配置对象,描述“一个输入如何转换并派生出多个输出”:
ForwardRule
rule_id 规则唯一ID,用于日志和监控
enable 是否启用
direction 转发方向(见下表)
ros_version ros1 / ros2 / all
udp_listen_ip UDP监听IP
udp_listen_port UDP监听端口
links[] 一个输入可派生出多个输出链路(LinkConfig)
LinkConfig
link_name
codec 使用哪个编解码器
send_ros_config.topic 外部 -> ROS 方向的目标 topic 与消息类型
udp_dst_ip / udp_dst_port ROS -> 外部 的目标地址
serial_port 串口目标
rate_limit 单链路限流
规则来自两处:静态 YAML(ros_trans_config.yaml,基础能力)与业务插件运行时动态生成(多数业务链路在此产生)。
支持的转发方向:
| direction | 工作含义 |
|---|---|
udp_to_rostopic |
监听 UDP,解码后发布 ROS Topic |
rostopic_to_udp |
订阅 ROS Topic,编码后发 UDP |
udp_to_rosservice |
监听 UDP,请求 ROS Service,可选把响应发回 UDP 源 |
rosservice_to_udp |
对 ROS 提供虚拟 Service,调用时转发 UDP 请求并等待响应 |
mem_to_rostopic |
读取共享内存数据,解码后发布 ROS Topic |
serial_to_ros |
读串口字节,解码后发布 ROS Topic |
ros_to_serial |
订阅 ROS Topic,编码后写串口 |
bytes_route |
完全绕过 ROS 和 Codec,做透明 UDP/串口字节路由 |
一条规则多条 Link
一个 UDP 输入包往往包含多种业务字段。RosTrans 允许同一个输入包被多个 Codec 解出不同 ROS 消息。例如同一帧 CopterSim 数据可同时发布 /mavros/local_position/pose、velocity_local、global_position/global、odom 等多个话题,既减少 socket 数量,也让同源处理集中在一条规则里。
4. 四层流水线¶
数据在已绑定的管道中流动,依次经过四层:
Transport 传输层¶
| 传输 | 特点 |
|---|---|
| UDPTransport | Boost.Asio 异步 UDP,支持单播/组播;接收缓冲 8 MB 适配图像点云突发;一个监听 socket 可被多个处理器复用 |
| SerialTransport | 异步串口收发,内部能按 MAVLink v1/v2 帧头(0xFE/0xFD)切出完整帧;写串口加锁避免多源字节交织 |
| MemTransport | 共享内存,主要用于 RflySim3D 图像/点云;按 flag(2=待读/3=读取中/4=读完)协议轮询 |
| BytesRouter | 完全绕开 ROS 与 Codec 的透明字节路径,用于 MAVLink/QGC/MAVROS/Pixhawk 等场景 |
Codec 编解码层¶
Codec 是 RosTrans 的协议边界,只暴露两个核心方法:decode()(外部字节 → ROS 序列化消息)与 encode()(ROS 消息 → 外部字节)。所有 Codec 通过 CodecFactory 全局注册与创建,按 link.codec 名称取用。
ROS Adapter 层¶
BaseROSAdapter 统一了 subscribe / advertise / publish / callService / advertiseService / spin 等接口;ROS1Adapter 用 ShapeShifter 收发任意类型消息,ROS2Adapter 用类型化或 generic 发布订阅,并对高频话题支持直接发布函数缓存以降低延迟。
5. 业务插件¶
四个业务插件把具体场景翻译成动态规则,激活后读取参数 → 判断 ROS 版本 → 按过滤裁剪功能 → 生成 ForwardRule 并加入核心:
| 插件 | 定位 | 主要内容 |
|---|---|---|
| DllModelAssistant | 把 CopterSim 自定义 UDP 协议映射成 MAVROS 兼容 topic/service | 遥测上行(pose/vel/gps/odom)、控制下行(setpoint 系列)、/mavros 服务(arming/set_mode/takeoff/land)+ 1 Hz /mavros/state |
| MavRosAssistant | 标准 MAVLink ↔ MAVROS 桥接,支持 PX4 SITL(UDP)与 Pixhawk(串口) | MAVLink→ROS(pose/imu/gps/state/battery…)、ROS→MAVLink(setpoint/rc_override…)、MAVROS 服务(COMMAND_LONG 等) |
| VisionAssistant | 把 RflySim3D/UE4 视觉传感器、IMU、吊舱接入 ROS | 按 Config.json 传感器列表生成图像/点云/雷达/红外话题,吊舱状态与控制,共享内存或 UDP 接收 |
| Sim3DUEAssistant | UE4 场景控制与反馈桥接 | ROS→UE4 控制命令(位姿、标签、附着等),UE4→ROS 反馈(碰撞、请求数据等) |
6. 高性能机制¶
面向高频 MAVLink、IMU、图像和点云,RosTrans 做了热路径优化:
- MAVLink 快速路径:Codec 通过
getTargetMsgIds()声明关注的 msgid,命中后跳过队列与工作线程,直接发布,减少线程切换与锁开销。 - 通用队列路径:无目标 msgid 的协议走队列(上限约 64 包,溢出丢最老包),避免高带宽输入造成延迟无限累积。
- 直接发布函数缓存:ROS2Adapter 初始化时缓存发布 lambda,运行时避免每包做
topic 字符串 → map 查找 → 加锁。 - 限频:每个 link 可设
rate_limit,按 1 秒窗口计数超限丢弃(Vision IMU 默认限 200 Hz)。
二、使用说明¶
1. 启动方式¶
基本启动:
推荐在无界面环境中使用(服务器/WSL):
同时指定主题过滤文件:
rostrans.param 使用 key=value 格式,命令行参数优先级高于配置文件:
2. 常用参数 rostrans.param¶
| 参数 | 默认值 | 说明 |
|---|---|---|
enable_monitor |
false |
是否打印转发统计 |
monitor_interval |
5 |
统计打印间隔(秒) |
enable_vision |
false |
启用 VisionAssistant |
enable_mavros |
false |
启用 MavRosAssistant |
enable_dllModel |
false |
启用 CopterSim/DllModelAssistant |
enable_ue3d |
false |
启用 Sim3DUEAssistant |
router_enable |
false |
启用 MAVLink/字节路由 |
3. 主题过滤 rostrans.filter¶
v1.0.3 的过滤器按黑名单模式工作:
- 未出现在
rostrans.filter中的话题/服务默认启用; - 配置为
false的被禁用,配置为true的显式启用; - 对 Topic 和 Service 都生效。
支持精确匹配、通配符、前缀和正则:
# 精确匹配
/mavros/state=true
# 通配符(* 和 ?)
/rflysim/sensor*/gimbal_*=true
# 前缀匹配
prefix:/rflysim/sensor0/=false
# 正则匹配
regex:^/mavros[0-9]*/imu/.*=false
re:^/rflysim/sensor[0-9]+/img_.*=false
匹配优先级:精确匹配最优先 → 模式匹配按文件顺序、后者覆盖前者 → 未匹配默认启用。
Tip
建议只把需要禁用的高带宽话题写成 false(如图像、点云、原始 IMU),其余保持默认启用即可。
4. Vision 话题清单¶
Vision 相关话题以当前实现为准,常用配置:
# 图像与点云
/rflysim/sensor*/img_rgb=true
/rflysim/sensor*/img_depth=true
/rflysim/sensor*/img_gray=true
/rflysim/sensor*/img_Segmentation=true
/rflysim/sensor*/fisheye=true
/rflysim/sensor*/img_cine=false
/rflysim/sensor*/img_Infrared_Gray=true
/rflysim/sensor*/img_Infrared=true
/rflysim/sensor*/range=true
/rflysim/sensor*/Depth_Cloud=true
# 激光雷达
/rflysim/sensor*/vehicle_lidar=true
/rflysim/sensor*/global_lidar=true
/rflysim/sensor*/livox_lidar=true
/rflysim/sensor*/mid360_lidar=true
# 吊舱/相机
/rflysim/sensor*/camera_data=false
/rflysim/sensor*/gimbal_status=true
/rflysim/sensor*/gimbal_ctrl=true
/rflysim/sensor*/pod/vision_sensor_req=false
# IMU 与里程计
/rflysim/imu=true
/rflysim/uav*/global/odom=true
/rflysim/uav*/local/odom=true
ROS 2 QoS 注意
RosTrans 的 ROS 2 发布侧使用 Best Effort。外部节点或测试脚本订阅时也必须使用 Best Effort,否则 DDS 会报 incompatible QoS: RELIABILITY,导致收不到数据。
下面是 UE4 图像/点云进入 ROS 的链路(共享内存或 UDP 两条路径):
5. MAVLink 字节路由(MavRouter / BytesRouter)¶
v1.0.3 内置透明字节路由,可用于 MAVLink,也可用于普通 UDP/串口字节流。路由层不解析、不修改数据内容。
| 模式 | 说明 | 典型用途 |
|---|---|---|
UDP <-> UDP |
从 UDP 源学习 FCU 地址,向多个 UDP 终点转发 | SITL/仿真器接 QGC、MavROS |
Serial -> UDP |
从串口读飞控数据并广播给 UDP 终点 | 实机 Pixhawk 接 QGC |
Serial <-> UDP |
串口与 UDP 双向透明转发 | 需 YAML bytes_route 配置上行监听端口 |
工作逻辑:第一批非 endpoint 来源数据被认为是 FCU source 并记录;下行数据广播给所有 endpoint;endpoint 的上行数据回发给已学习到的 FCU source;全过程不解码、不经过 ROS Adapter。
UDP 路由¶
router_source=0.0.0.0:14560:RosTrans 监听本机 14560 端口;- 仿真器/飞控向 14560 发送 MAVLink 后,路由器学习该 FCU 源地址;
- 数据转发到
router_endpoints的所有终点;多个终点用逗号分隔:
串口路由¶
Note
rostrans.param 的 CLI 串口模式当前默认用于 Serial -> UDP 下行广播。若需要 UDP -> Serial 上行回传,请改用 YAML bytes_route 配置,并设置 udp_listen_port > 0。
多机端口规则¶
当 mavros_copter_count > 1 时,UDP 路由按每架飞机 +2 创建多个路由实例:
| 飞机 | 路由监听端口 | QGC 端口 | MavROS 端口 |
|---|---|---|---|
| 1 | 14560 |
14550 |
20101 |
| 2 | 14562 |
14550 |
20103 |
| 3 | 14564 |
14550 |
20105 |
14550、14555、18570 视为常见地面站端口,多机时保持不递增;其他终点端口按 +2 递增。
YAML bytes_route 示例¶
forward_rules:
- rule_id: mavlink_router_udp
enable: true
direction: bytes_route
udp_listen_ip: 0.0.0.0
udp_listen_port: 14560
links:
- link_name: qgc
udp_dst_ip: 127.0.0.1
udp_dst_port: 14550
三、测试与排错¶
1. 测试脚本¶
吊舱 ROS 2 测试(QoS 已按发布侧适配):
MAVRouter UDP 测试:先确保 router_enable=true 且 router_source=0.0.0.0:14560、router_endpoints=127.0.0.1:14550,再运行:
python3 test/python/test_mavrouter.py
# 自定义端口
python3 test/python/test_mavrouter.py --router-port 14560 --endpoint 127.0.0.1:14550
脚本会验证下行到达、上行回传到已学习 FCU 源、以及多包 burst 转发是否完整。
MAVRouter 串口测试(Linux PTY 虚拟串口,测 Serial -> UDP):
2. 常见问题¶
| 问题 | 可能原因 | 处理方式 |
|---|---|---|
GimbalStatus 收不到 |
ROS 2 QoS 不匹配 | 订阅端使用 Best Effort |
| MAVRouter 没有转发 | router_enable=false 或端口不匹配 |
检查 router_source、router_endpoints |
| UDP 上行无法回 FCU | 路由器尚未学习 FCU 源 | 先让 FCU/仿真器向 router_source 发送一包 |
| 串口下行可以、上行不通 | CLI 串口模式没有 UDP 监听端口 | 改用 YAML bytes_route 并配置 udp_listen_port |
| 串口打开失败 | 权限不足或设备名错误 | Linux 下检查 dialout 权限和 /dev/tty* 路径 |
Linux 运行 .sh 报 $'\r' |
脚本是 CRLF 换行 | 用 dos2unix 转为 LF(仓库 .gitattributes 已约束 pack/**/*.sh eol=lf) |
3. 配置文件总览¶
| 文件 | 作用 |
|---|---|
rostrans.param |
总开关、端口、IP、飞机数量、串口、router 参数 |
rostrans.filter |
topic/service 粒度启停 |
plugins_config.ini |
插件加载、初始化、优先级 |
ros_trans_config.yaml |
通用静态转发规则 |
Config.json |
Vision 传感器列表、类型、分辨率、SendProtocol |
fastdds_wsl2.xml |
ROS2 DDS/WSL2 网络相关配置 |
功能缺失排查顺序
静态 YAML 只是基础能力,多数业务链路由插件按参数动态生成。排查某功能不工作时,按此顺序检查:① 对应业务插件是否启用(如 enable_mavros=true)→ ② 当前 ROS 环境是否正确、是否加载了匹配的 Adapter → ③ rostrans.filter 是否禁用了该 topic/service → ④ 对应 codec 是否注册成功 → ⑤ 端口/IP/串口是否与外部系统一致。
扩展新协议¶
得益于解耦设计,新增一种协议通常不用改主程序:
- 定义新的
Codec,实现decode()和encode();ROS1 自定义消息还需补getMD5()和getMsgDefinition(); - 在适配器 codec 文件或业务插件中调用
CodecFactory::registerCodec("name", creator); - 在 YAML 或业务插件中生成
ForwardRule,把link.codec指向新 codec; - 如需业务开关,把参数加到
rostrans.param;如需 ROS service,实现ServiceBase并注册到ServiceFactory。
最小工作模型:
registerCodec("my_codec", ...)
ForwardRule:
direction: udp_to_rostopic
udp_listen_ip: 0.0.0.0
udp_listen_port: 9000
links:
- topic: /my/topic
msg_type: std_msgs/msg/String
codec: my_codec
抓住一条主线即可理解 RosTrans:每个功能最终都会落到一条或多条
ForwardRule,每条规则会绑定对应的 Transport、Codec 和 ROS Adapter,运行时数据就在这条已绑定的管道中低延迟流动。