Robot OS#

http://www.autolabor.com.cn/book/ROSTutorials/ (ROS 1 教程,老系统)

下面记 ROS 2 实用部分。ROS 1 Noetic 已 2025-05 EOL,老项目兼容用。

版本和系统对应#

  • ROS 2 Humble:Ubuntu 22.04,LTS 到 2027-05
  • ROS 2 Jazzy:Ubuntu 24.04,LTS 到 2029-05(新装选这个)
  • ROS 2 Iron / Foxy / Galactic:已 EOL,别用

版本只能装一个发行版对应的 Ubuntu,不要混。

装#

Ubuntu 22.04 + Humble 示例:

sudo add-apt-repository universe
sudo apt update && sudo apt install curl gnupg lsb-release -y

sudo curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key \
  -o /usr/share/keyrings/ros-archive-keyring.gpg

echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] \
http://packages.ros.org/ros2/ubuntu $(lsb_release -cs) main" \
  | sudo tee /etc/apt/sources.list.d/ros2.list

sudo apt update
sudo apt install ros-humble-desktop ros-dev-tools

每个新 shell 都要 source(写进 ~/.bashrc 一劳永逸):

echo "source /opt/ros/humble/setup.bash" >> ~/.bashrc

Jazzy 同样套路,把 humble 全部换成 jazzy,系统换成 24.04。

非 Ubuntu 系统装 ROS 2#

官方 Tier 1 只支持 Ubuntu。Fedora / Arch / openSUSE 等系统按推荐度选:

1. Distrobox + Ubuntu 容器 ⭐ 推荐#

跟主机共享 HOME / DBus / X / Wayland,体验等同原生 Ubuntu,rviz / gazebo 直接显示在主机桌面。

sudo dnf install distrobox       # Fedora
# 或 sudo pacman -S distrobox    # Arch
# 或 sudo zypper in distrobox    # openSUSE

distrobox create --name ros2 --image ubuntu:22.04
distrobox enter ros2
# 进去之后照上面 ## 装 那一节 apt 命令走

distrobox export --bin /opt/ros/humble/bin/... 还能把容器内命令暴露到主机 PATH。

2. Docker osrf/ros 官方镜像#

docker run -it --rm \
  -e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix --net=host \
  osrf/ros:humble-desktop

适合 CI / 一次性试。日常开发不爽:每次 source、IDE 不好对接、传感器要 --device 映射、Wayland 下 GUI 转发还要折腾。

3. RoboStack(conda 预编译)#

mamba create -n ros2 -c robostack-staging ros-humble-desktop
mamba activate ros2

社区维护,跨平台。但厂商驱动 / 部分导航栈不全,要自己 build。

4. 其它#

  • COPR 第三方仓库:版本滞后,不推荐当主用
  • 源码编译:依赖地狱,除非要给上游提 PR,别走

工作区 + colcon#

ROS 2 用 colcon,不再是 ROS 1 的 catkin_make。

mkdir -p ~/ros2_ws/src && cd ~/ros2_ws

colcon build                              # 全量
colcon build --packages-select my_pkg     # 只 build 一个
colcon build --symlink-install            # 改 Python 文件不用重 build
colcon build --cmake-args -DCMAKE_BUILD_TYPE=Release

source install/setup.bash                 # build 完要 source

--symlink-install 之后,改 .py 即生效;但改 setup.py / CMakeLists.txt / package.xml 还是要重 build。

建包#

# Python 包
ros2 pkg create --build-type ament_python my_py_pkg --node-name hello

# C++ 包
ros2 pkg create --build-type ament_cmake my_cpp_pkg --node-name hello

依赖写在 package.xml(<depend>rclpy</depend> / <depend>rclcpp</depend>),C++ 还要在 CMakeLists.txt 里 find_package + ament_target_dependencies,两边都得加。

CLI 速查#

# 节点
ros2 node list
ros2 node info /node_name

# 话题
ros2 topic list -t                        # -t 顺便看类型
ros2 topic info /topic -v                 # -v 看 QoS
ros2 topic echo /topic
ros2 topic hz /topic                      # 实测频率
ros2 topic bw /topic                      # 实测带宽
ros2 topic pub /chat std_msgs/msg/String "{data: 'hi'}" --once

# 服务
ros2 service list -t
ros2 service call /add_two_ints example_interfaces/srv/AddTwoInts "{a: 1, b: 2}"

# Action
ros2 action list -t
ros2 action send_goal /fib example_interfaces/action/Fibonacci "{order: 5}"

# 消息/服务定义
ros2 interface show std_msgs/msg/String
ros2 interface list

参数#

ROS 2 参数是节点级的(ROS 1 是全局 master 上的)。

ros2 param list
ros2 param get /node_name param_name
ros2 param set /node_name param_name 3.14

ros2 param dump /node_name > params.yaml  # 存档
ros2 param load /node_name params.yaml    # 还原

launch 时直接传:

ros2 run my_pkg my_node --ros-args -p rate:=10.0
ros2 run my_pkg my_node --ros-args --params-file params.yaml

Launch(Python,不再是 XML)#

# launch/demo.launch.py
from launch import LaunchDescription
from launch_ros.actions import Node

def generate_launch_description():
    return LaunchDescription([
        Node(
            package='demo_nodes_cpp',
            executable='talker',
            name='my_talker',
            parameters=[{'rate': 5.0}],
            remappings=[('/chatter', '/my_chat')],
        ),
        Node(package='demo_nodes_py', executable='listener'),
    ])
ros2 launch my_pkg demo.launch.py
ros2 launch my_pkg demo.launch.py rate:=10  # 传 launch 参数

XML 和 YAML 格式也支持,但 Python 表达力强、社区主流。

bag 录制 / 回放#

ros2 bag record -o my_bag /topic1 /topic2
ros2 bag record -a                        # 录全部话题
ros2 bag info my_bag
ros2 bag play my_bag
ros2 bag play my_bag --rate 0.5 --loop    # 半速 + 循环
ros2 bag play my_bag --topics /scan       # 只回放部分话题

格式默认是 .mcap(Jazzy+),老的 sqlite3 也支持,转换工具:ros2 bag convert。

TF (tf2)#

ros2 run tf2_ros tf2_echo base_link camera_link    # 实时看两 frame 的变换
ros2 run tf2_tools view_frames                     # 生成 frames.pdf,看树
ros2 topic echo /tf
ros2 topic echo /tf_static

# 手动发一个 static transform
ros2 run tf2_ros static_transform_publisher --x 1 --y 0 --z 0 --frame-id world --child-frame-id base

调试#

rqt_graph                                  # 节点话题拓扑
ros2 run rqt_console rqt_console           # 日志窗口
ros2 run rqt_plot rqt_plot                 # 实时画 topic 数值
ros2 run rqt_reconfigure rqt_reconfigure   # 动态调参

# 想看节点都在干啥
ros2 doctor
ros2 doctor --report

常见坑#

  • 新 shell 不 source → ros2: command not found 或 ros2 run 找不到自己的包

  • 改 Python 源码不生效 → 装的时候没 --symlink-install,或者改的是 setup.py 没重 build

  • 同网段多人开发互相串话题 → 用 ROS_DOMAIN_ID 隔离:

    export ROS_DOMAIN_ID=42        # 0~101,每人一个
  • colcon build 卡在某包上不动 → 加 --executor sequential 看哪个包死锁,多半是 CMake 依赖循环

  • 跨机器 ROS 2 通信不通 →

    • 防火墙没开(默认 multicast 7400 + 7401+ 端口动态分配)
    • ROS_DOMAIN_ID 不一致
    • WiFi 路由器禁了 multicast,试 CycloneDDS 改 unicast
  • 切 DDS 实现:

    export RMW_IMPLEMENTATION=rmw_cyclonedds_cpp     # 装包:ros-humble-rmw-cyclonedds-cpp
  • bag record 默认 BEST_EFFORT QoS,丢包严重 → 用 --qos-profile-overrides-path 改成 RELIABLE

  • ament_python 包要在 setup.py 的 entry_points 里注册 console_scripts,节点才能 ros2 run

参考#