X:000 · Y:000SECTOR / AIv0.9.SIGNALNO_ADS // NO_TRACK
CILLIAN.AI
← MEMORY

ROS 2 要点:DDS、QoS 与从 ROS 1 迁过来

对照 ROS 1 讲清 ROS 2 的架构变化:无 Master、DDS/QoS、生命周期节点、launch 与常用发行版选择,附迁移检查清单。

3 MIN READ~2100 CHARS
ROS 2 要点:DDS、QoS 与从 ROS 1 迁过来
SIGNAL COVER · ros2-essentials

如果你已经会 ROS 1 的节点与话题,学 ROS 2 不是「换一套命令」,而是换了一套发现机制与服务质量(QoS)哲学。新项目默认应选 ROS 2;旧栈则要评估包生态与实时/多机需求再迁。

ROS 1 → ROS 2:先改世界观

维度 ROS 1 ROS 2
发现 中心化 roscore / Master 去中心化,靠 DDS 发现
通信后端 自研 TCPROS/UDPROS DDS(多种 RMW 实现)
服务质量 基本靠约定 显式 QoS(可靠性、历史、耐久等)
启动 roslaunch XML launch.py(Python)为主
构建 catkin / catkin_tools colcon + ament
客户端库 roscpp / rospy rclcpp / rclpy
长任务 actionlib rclcpp_action / 统一 Action 接口
节点生命周期 较弱 Lifecycle Node(配置/激活/停用)

没有 Master 的好处:少一个单点故障;代价是:你必须理解 DDS 域、网卡、组播/发现,否则「明明起了节点却互相看不见」。

发行版怎么选(实务)

常见稳定线(以社区惯用为准,部署前再核对 LTS):

  • Humble(Ubuntu 22.04):很多产线与开源栈的「默认最大公约数」
  • Jazzy 及更新版:新功能与依赖更新,适合能跟发行版的团队

选版原则:和系统 Ubuntu、驱动、仿真器(Gazebo / Isaac)对齐,比追最新代号更重要。

最小 pub/sub(rclpy)

source /opt/ros/$ROS_DISTRO/setup.bash
mkdir -p ~/ros2_ws/src && cd ~/ros2_ws/src
ros2 pkg create --build-type ament_python demo_talker --dependencies rclpy std_msgs

发布者骨架:

import rclpy
from rclpy.node import Node
from std_msgs.msg import String

class Talker(Node):
    def __init__(self):
        super().__init__("talker")
        self.pub = self.create_publisher(String, "chatter", 10)
        self.timer = self.create_timer(0.1, self.tick)
        self.i = 0

    def tick(self):
        msg = String()
        msg.data = f"hello ROS2 {self.i}"
        self.pub.publish(msg)
        self.i += 1

def main():
    rclpy.init()
    node = Talker()
    rclpy.spin(node)
    node.destroy_node()
    rclpy.shutdown()

构建与运行:

cd ~/ros2_ws && colcon build --packages-select demo_talker
source install/setup.bash
ros2 run demo_talker talker   # 按你 package.xml / setup 里入口名为准

常用自检:

ros2 node list
ros2 topic list
ros2 topic echo /chatter
ros2 interface show std_msgs/msg/String

QoS:ROS 2 里最该认真看的开关

同一话题名、同一消息类型,QoS 不兼容就订不上阅——这是从 ROS 1 迁过来时最阴的坑。

常见旋钮:

  • ReliabilityRELIABLE vs BEST_EFFORT(激光/图像常用 BEST_EFFORT)
  • HistoryKEEP_LAST + depth,或 KEEP_ALL
  • DurabilityVOLATILE vs TRANSIENT_LOCAL(晚订阅还想拿到「最后一帧地图」时会用到)

经验法则:

  • 传感器高速流:偏 BEST_EFFORT + 小 depth
  • 控制指令、关键状态:偏 RELIABLE
  • 调试时用 ros2 topic info -v /xxx 看双方 QoS 是否对得上

Lifecycle:把「启动成功」变成状态机

长期运行的驱动/规划节点,推荐 Lifecycle:

unconfigured → inactive → active → finalized

好处:配置失败可以停在 inactive;热切换参数或传感器时不必杀进程。代价:launch 与监控要会管状态转换,而不是 ros2 run 完事。

Launch(Python)直觉

from launch import LaunchDescription
from launch_ros.actions import Node

def generate_launch_description():
    return LaunchDescription([
        Node(
            package="demo_talker",
            executable="talker",
            name="talker",
            output="screen",
            remappings=[("chatter", "robot/chatter")],
        )
    ])

组合多机、多 namespace、参数文件时,Python launch 比 ROS 1 XML 更好组合——但也更容易写成「无法阅读的脚本」,记得拆文件、抽函数。

从 ROS 1 迁移:检查清单

  1. 消息/服务定义msg/srv 语法细微差异;自定义接口进独立 *_msgs 包。
  2. 时间:统一用 rclcpp::Time / node.get_clock(),注意仿真钟 use_sim_time
  3. TFtftf2;补全 frame_id / child_frame_id 纪律。
  4. 参数:ROS 2 参数声明(declare)更严格,未声明就访问会失败。
  5. 桥接:短期可用 ros1_bridge 双栈共存,长期别当架构。
  6. 包有没有 ROS 2 版:先查 ros2 分支 / vendor;没有就评估自己 port 的成本。
  7. 网络:多机务必验证 DDS 发现(防火墙、VPN、Docker 网桥都会坑)。

和仿真、硬件的交界

  • Gazebo / Ignition:话题名与 QoS 要对齐控制栈
  • 真机驱动:优先找官方或厂商维护的 ROS 2 驱动,别长期跑「半移植」
  • 录包ros2 bag record;分析时同样先确认时钟与 frame

小结

学 ROS 2 的优先级建议:

  1. 跑通 pub/sub + colcon
  2. 弄懂 QoS 不匹配 现象
  3. 会写最小 launch.py
  4. 再上 Lifecycle、组件容器、安全与实时调参

ROS 1 教你「怎么拆节点」;ROS 2 逼你「怎么在真实网络与质量约束下拆节点」。下一篇把镜头拉远:Physical AI——模型如何长到机器人身上,以及 ROS 在这条链路上站哪一环。

RELATED SIGNALS

SIGNAL FOOTER

本篇已归档到 MEMORY。欢迎继续解码相邻信号,或回到档案首页。