跳转至

RosTrans


RosTrans 是 RflySim 工具链中的 ROS 多协议转换网关。它把外部的 UDP、串口、共享内存或 MAVLink 字节流转换为 ROS1/ROS2 的 Topic/Service,也能把 ROS 控制消息反向打包发送给仿真器、飞控或 UE4,从而让标准 ROS 算法生态无缝接入 RflySim 仿真闭环。

一句话理解:RosTrans 是一个规则驱动、插件化的多协议网关,本身不绑定任何具体协议,而是用统一的转发规则把“从哪里来、到哪里去、怎么转换”描述清楚。

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) 屏蔽 roscpprclcpp 的发布订阅差异
业务规则生成 业务插件(DllModel/MavRos/Vision/UE) 把具体场景翻译成动态转发规则

正因为解耦,新增一种协议通常不用改主程序,只需写一个 Codec 并生成一条规则即可。

2. 总体架构

RosTrans 总体架构

  • ParamManager:读取 rostrans.paramrostrans.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             单链路限流

规则来自两处:静态 YAMLros_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/posevelocity_localglobal_position/globalodom 等多个话题,既减少 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 等接口;ROS1AdapterShapeShifter 收发任意类型消息,ROS2Adapter 用类型化或 generic 发布订阅,并对高频话题支持直接发布函数缓存以降低延迟。

UDP → ROS Topic 数据流

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. 启动方式

基本启动:

rostrans -c rostrans.param

推荐在无界面环境中使用(服务器/WSL):

rostrans -platform offscreen -c rostrans.param

同时指定主题过滤文件:

rostrans -platform offscreen -c rostrans.param -f rostrans.filter

rostrans.param 使用 key=value 格式,命令行参数优先级高于配置文件

rostrans -c rostrans.param --enable_vision=true --coptersim_count=2

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/imu/data_raw=false
/rflysim/sensor*/img_cine=false
/rflysim/sensor*/gimbal_status=true

支持精确匹配、通配符、前缀和正则:

# 精确匹配
/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 两条路径):

UE4 图像/点云进入 ROS 的链路

v1.0.3 内置透明字节路由,可用于 MAVLink,也可用于普通 UDP/串口字节流。路由层不解析、不修改数据内容

模式 说明 典型用途
UDP <-> UDP 从 UDP 源学习 FCU 地址,向多个 UDP 终点转发 SITL/仿真器接 QGC、MavROS
Serial -> UDP 从串口读飞控数据并广播给 UDP 终点 实机 Pixhawk 接 QGC
Serial <-> UDP 串口与 UDP 双向透明转发 需 YAML bytes_route 配置上行监听端口

MAVLink 透明路由到 QGC 与 MAVROS

工作逻辑:第一批非 endpoint 来源数据被认为是 FCU source 并记录;下行数据广播给所有 endpoint;endpoint 的上行数据回发给已学习到的 FCU source;全过程不解码、不经过 ROS Adapter。

UDP 路由

router_enable=true
router_source=0.0.0.0:14560
router_endpoints=127.0.0.1:14550
  • router_source=0.0.0.0:14560:RosTrans 监听本机 14560 端口;
  • 仿真器/飞控向 14560 发送 MAVLink 后,路由器学习该 FCU 源地址;
  • 数据转发到 router_endpoints 的所有终点;多个终点用逗号分隔:
router_endpoints=127.0.0.1:14550,127.0.0.1:20101

串口路由

# Windows
router_source=COM3:921600
# Linux
router_source=/dev/ttyUSB0:921600

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

145501455518570 视为常见地面站端口,多机时保持不递增;其他终点端口按 +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 已按发布侧适配):

python3 test/python/test_gimbal_ctrl_ros2.py

MAVRouter UDP 测试:先确保 router_enable=truerouter_source=0.0.0.0:14560router_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):

python3 test/python/test_mavrouter.py --mode serial --create-pty --wait-start

2. 常见问题

问题 可能原因 处理方式
GimbalStatus 收不到 ROS 2 QoS 不匹配 订阅端使用 Best Effort
MAVRouter 没有转发 router_enable=false 或端口不匹配 检查 router_sourcerouter_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/串口是否与外部系统一致。


扩展新协议

得益于解耦设计,新增一种协议通常不用改主程序

  1. 定义新的 Codec,实现 decode()encode();ROS1 自定义消息还需补 getMD5()getMsgDefinition()
  2. 在适配器 codec 文件或业务插件中调用 CodecFactory::registerCodec("name", creator)
  3. 在 YAML 或业务插件中生成 ForwardRule,把 link.codec 指向新 codec;
  4. 如需业务开关,把参数加到 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,运行时数据就在这条已绑定的管道中低延迟流动。