跳到主要内容

ROS 2 Humble 部署

本指南介绍如何在 MTT E300 或 Ubuntu 22.04 环境中部署 ROS 2 Humble。完成部署后,你将使用 TurtlesimRQT 练习节点运行、主题查看、服务调用和主题重映射等基础操作。

概念简介

本指南以 ROS 2 Humble 为基础环境,使用 Turtlesim 演示节点、主题和服务,再使用 RQT 以图形化方式调用和调试服务。

  • ROS(Robot Operating System):开源生态系统,为机器人应用的构建、部署、运行和维护提供框架、工具和库。相关操作参见环境部署查看节点、主题、服务和动作
  • Turtlesim:ROS 2 提供的轻量级二维模拟器,用于演示节点、主题和服务等基础机制。相关操作参见使用 Turtlesim
  • RQT:基于 Qt 的 ROS 图形化工具框架,以插件形式提供可视化和调试功能。相关操作参见使用 RQT

学习目标

完成本指南后,你可以:

  • 使用原生安装或 Docker 镜像部署 ROS 2 Humble。
  • 启动 Turtlesim,并通过键盘控制乌龟移动。
  • 使用命令行工具查看 ROS 2 节点、主题、服务和动作。
  • 使用 RQT 调用服务,生成新乌龟并修改画笔属性。
  • 使用主题重映射分别控制多只乌龟。

适用对象

本指南适用于 ROS 2 初学者、使用 MTT E300 的开发者,以及在 Ubuntu 22.04 环境中学习 ROS 2 的用户。

前置条件

开始前,请准备以下硬件和软件:

硬件

  • MTT E300。
  • 符合设备供电要求的电源适配器。
  • 可下载安装包的有线或无线网络。
  • 键盘、鼠标和显示器,或支持 SSH 的远程主机。

软件

  • Ubuntu 22.04 ARM64 Jammy。
  • 使用 Docker 镜像时,已安装 Docker Engine,并将当前用户加入 docker 用户组。
  • 可以访问 ROS 2 软件源及相关资源。

环境部署

你可以使用原生安装或 Docker 镜像部署 ROS 2 Humble。

选择安装方式

  • Ubuntu 22.04 主机原生安装:适用于需要长期使用 ROS 2 的场景。
  • Docker 镜像:适用于快速体验或需要避免依赖冲突的场景。

方式一:原生安装 ROS 2 Humble

  1. 创建脚本 install_host_ros_humble.sh

    #!/bin/bash

    sudo -v

    set -e

    OS_DISTRO="jammy"
    ROS_DISTRO="humble"
    APT_SRC="http://mirrors.tuna.tsinghua.edu.cn/ubuntu-ports"
    PIP_SRC="https://pypi.tuna.tsinghua.edu.cn/simple"

    echo "Starting ROS 2 Humble installation script for Ubuntu ${OS_DISTRO}..."
    echo "Using additional APT source: ${APT_SRC}"
    echo "Using PIP source: ${PIP_SRC}"

    # --- Add Tsinghua Mirror configuration to a separate file ---
    # This *adds* the mirror, keeping the original system sources intact.
    TSINGHUA_SOURCES_FILE="/etc/apt/sources.list.d/tsinghua-mirror.list"
    echo "Adding Tsinghua mirror configuration to ${TSINGHUA_SOURCES_FILE}..."
    sudo bash -c "cat <<EOL > ${TSINGHUA_SOURCES_FILE}
    # Added by install script on $(date)
    # Mirror: ${APT_SRC}
    # OS: ${OS_DISTRO}

    deb ${APT_SRC} ${OS_DISTRO} main restricted
    # deb-src ${APT_SRC} ${OS_DISTRO} main restricted

    deb ${APT_SRC} ${OS_DISTRO}-updates main restricted
    # deb-src ${APT_SRC} ${OS_DISTRO}-updates main restricted

    deb ${APT_SRC} ${OS_DISTRO} universe
    # deb-src ${APT_SRC} ${OS_DISTRO} universe
    deb ${APT_SRC} ${OS_DISTRO}-updates universe
    # deb-src ${APT_SRC} ${OS_DISTRO}-updates universe

    deb ${APT_SRC} ${OS_DISTRO} multiverse
    # deb-src ${APT_SRC} ${OS_DISTRO} multiverse
    deb ${APT_SRC} ${OS_DISTRO}-updates multiverse
    # deb-src ${APT_SRC} ${OS_DISTRO}-updates multiverse

    deb ${APT_SRC} ${OS_DISTRO}-backports main restricted universe multiverse
    # deb-src ${APT_SRC} ${OS_DISTRO}-backports main restricted universe multiverse

    deb ${APT_SRC} ${OS_DISTRO}-security main restricted
    # deb-src ${APT_SRC} ${OS_DISTRO}-security main restricted
    deb ${APT_SRC} ${OS_DISTRO}-security universe
    # deb-src ${APT_SRC} ${OS_DISTRO}-security universe
    deb ${APT_SRC} ${OS_DISTRO}-security multiverse
    # deb-src ${APT_SRC} ${OS_DISTRO}-security multiverse
    EOL"
    echo "Added custom APT sources file: ${TSINGHUA_SOURCES_FILE}"
    # --- End of Tsinghua Mirror addition ---

    echo "Adding ROS 2 APT repository..."
    # Add the ROS 2 GPG key (Ensure required packages are installed first)
    sudo apt install -y curl gnupg lsb-release software-properties-common
    sudo curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key -o /usr/share/keyrings/ros-archive-keyring.gpg
    echo "ROS GPG Key added."

    # Add the ROS 2 repository
    ROS2_SOURCES_FILE="/etc/apt/sources.list.d/ros2.list"
    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 ${ROS2_SOURCES_FILE} > /dev/ null
    echo "Added ROS 2 APT repository file: ${ROS2_SOURCES_FILE}"

    echo "Configuring PIP source for the current user..."
    mkdir -p ~/.config/pip # Changed from /root/.pip to user's home config
    cat <<EOL > ~/.config/pip/pip.conf
    [global]
    index-url = ${PIP_SRC}
    EOL
    echo "Configured PIP to use ${PIP_SRC} for the current user in ~/.config/pip/pip.conf."

    echo "Updating package lists after adding new sources..."
    sudo apt-get update

    echo "Installing system dependencies and ROS 2 packages..."
    # Note: software-properties-common was already installed earlier for ROS repo setup
    sudo apt-get install -y --fix-missing --allow-downgrades \
    net-tools vim curl wget tmux build-essential \
    libicu70=70.1-2 libsqlite3-0=3.37.2-2ubuntu0.3 libzstd1=1.4.8+dfsg-3build1 \
    libedit-dev libdrm-dev libspdlog-dev sox libsox-fmt-all librapidxml-dev

    sudo apt-get install -y --fix-missing --allow-downgrades \
    ros-${ROS_DISTRO}-desktop \
    ros-${ROS_DISTRO}-perception \
    ros-${ROS_DISTRO}-simulation \
    ros-${ROS_DISTRO}-desktop-full \
    ros-${ROS_DISTRO}-rosbridge-suite \
    ros-${ROS_DISTRO}-ros-ign-gazebo-demos \
    ros-${ROS_DISTRO}-turtlesim

    echo "Configuring environment variables in ~/.bashrc..."
    grep -qxF "source /opt/ros/${ROS_DISTRO}/setup.bash" ~/.bashrc || echo "source /opt/ros/${ROS_DISTRO}/setup.bash" >> ~/.bashrc
    source ~/.bashrc

    echo "------------------------------------------------------------------------"
    echo "Installation and configuration complete!"
    echo "NOTE: Added custom APT sources to ${TSINGHUA_SOURCES_FILE}"
    echo "NOTE: Added ROS 2 APT sources to ${ROS2_SOURCES_FILE}"
    echo "------------------------------------------------------------------------"
  2. 运行脚本

    bash install_host_ros_humble.sh
  3. 使环境生效

    source ~/.bashrc

方式二:使用 Docker 镜像

  1. 创建脚本 install_docker_ros_humble.sh

    #!/bin/bash

    # --- 配置变量 (可按需修改) ---
    OS_DISTRO="jammy" # 基础操作系统 (Ubuntu 22.04)
    ROS_DISTRO="humble" # ROS 2 发行版
    IMAGE_BASE="${ROS_DISTRO}-ros-base-${OS_DISTRO}" # 基础镜像名称部分
    IMAGE_NAME="mcconline-cn-beijing.cr.volces.com/m1000/refapps/ros" # 完整镜像仓库/名称
    IMAGE_TAG="${IMAGE_BASE}" # 镜像标签

    echo "--- 正在启动 Docker 容器 ---"
    echo "镜像: ${IMAGE_NAME}:${IMAGE_TAG}"

    # --- Docker 启动命令 ---
    # -it: 交互式终端
    # -d: 后台运行
    # --privileged: 赋予容器特权 (访问设备需要)
    # -v /dev:/dev: 挂载设备目录
    # -e DISPLAY=unix$DISPLAY: 传递 X11 Display 变量以显示 GUI
    # --net=host: 使用主机网络 (简化网络配置)
    # -v /usr/local/musa...: (如果需要)挂载特定硬件驱动 (示例)
    # -v /home/$USER:/home/$USER: 挂载用户主目录 (方便文件共享)
    # -v /tmp/.X11-unix:/tmp/.X11-unix: 挂载 X11 socket 目录
    docker run -it -d \
    --privileged \
    -v /dev:/dev \
    -e DISPLAY=unix$DISPLAY \
    --net=host \
    -v /usr/local/musa:/usr/local/musa \
    -v /usr/lib/aarch64-linux-gnu/musa:/usr/lib/aarch64-linux-gnu/musa \
    -v /usr/lib/aarch64-linux-gnu/dri/musa_dri.so:/usr/lib/aarch64-linux-gnu/dri/musa_dri.so \
    -v /usr/lib/aarch64-linux-gnu/dri/musa_drv_video.so:/usr/lib/aarch64-linux-gnu/dri/musa_drv_video.so \
    -v /home/$USER:/home/$USER \
    -v /tmp/.X11-unix:/tmp/.X11-unix \
    ${IMAGE_NAME}:${IMAGE_TAG}

    echo "--- 容器已在后台启动 ---"
    echo "你可以使用 'docker ps' 查看运行中的容器 ID。"
    echo "使用 'docker exec -it <container_id> /bin/bash' 进入容器的交互式终端。"
  2. 查找容器 ID 并进入容器

    docker ps # 查看运行中的容器 ID
    docker exec -it <container_id> /bin/bash # 将 <container_id> 替换为实际 ID

检查和配置环境

完成 环境部署 后,检查 ROS 2 环境并加载环境脚本。以下步骤适用于原生安装和 Docker 镜像。

检查先决条件

  • ROS 2 Humble 环境已就绪。
  • 可以在主机或 Docker 容器中打开并操作终端。
  • 熟悉 cdlsmkdir 等基本 Linux 命令。

验证 ROS 2 环境

在一个新的终端(或已进入的 Docker 容器终端)中,运行以下命令:

printenv | grep ROS

输出应包含以 ROS_ 开头的环境变量。确认其中包含 ROS_DISTRO=humble,表示 ROS 2 的基本环境变量已加载。

加载 ROS 2 环境脚本

备注

ros2 runros2 topic list 等命令依赖 ROS 2 环境变量。每次打开新终端后,都需要加载对应的环境脚本。

根据安装方式加载环境脚本:

  • 原生安装或大多数 Docker 镜像

    source /opt/ros/humble/setup.bash
  • 自定义工作空间:加载工作空间中的 install/setup.bash,例如:

    # 假设工作空间位于 ~/ros2_ws
    source ~/ros2_ws/install/setup.bash

后续步骤中,每次打开新终端后,请先执行 source /opt/ros/humble/setup.bash 或加载对应的工作空间脚本。

使用 Turtlesim

安装 turtlesim 包(可选)

Docker 镜像以及安装了 ros-humble-desktop-fullros-humble-turtlesim 的原生环境通常已包含 turtlesim。如果未安装,请执行以下步骤:

  1. 打开终端并加载 ROS 2 环境。

  2. 更新软件包列表

    sudo apt update
  3. 安装 turtlesim

    sudo apt install ros-humble-turtlesim
  4. 验证安装:检查 turtlesim 提供的可执行文件。

    ros2 pkg executables turtlesim

    输出应包含以下可执行文件:

    turtlesim draw_square
    turtlesim mimic
    turtlesim turtle_teleop_key
    turtlesim turtlesim_node

启动 Turtlesim 模拟器节点

在已加载 ROS 2 环境的终端中,启动 turtlesim 模拟器节点:

ros2 run turtlesim turtlesim_node

启动后,将打开标题为 Turtlesim 的图形窗口。终端输出类似如下:

[INFO] [1678886400.123456] [turtlesim]: Starting turtlesim with node name /turtlesim
[INFO] [1678886400.123567] [turtlesim]: Spawning turtle [turtle1] at x=[5.544445], y=[5.544445], theta=[0.000000]

该输出表示 /turtlesim 节点已启动,并生成了默认名称为 turtle1 的乌龟。保持该终端运行。

使用键盘控制乌龟

打开另一个终端,启动键盘控制节点:

  1. 打开新终端。

  2. 加载 ROS 2 环境

    source /opt/ros/humble/setup.bash
  3. 运行 turtle_teleop_key 节点

    ros2 run turtlesim turtle_teleop_key

    终端将显示以下提示:

    Reading from keyboard
    ---------------------------
    Use arrow keys to move the turtle.
    'q' to quit.
  4. 控制乌龟:保持该终端为活动窗口,使用方向键()控制 turtle1 移动。

按下方向键后,乌龟会移动一小段距离并停止,这是预期行为。

查看节点、主题、服务和动作

保持 turtlesim_nodeturtle_teleop_key 运行。打开新终端并加载 ROS 2 环境,然后使用 ros2 命令行工具查看当前系统。

查看节点

节点是 ROS 2 中的基本计算单元,可以理解为一个程序或进程。

ros2 node list

输出至少包含以下节点:

/turtlesim
/teleop_turtle

/turtlesim 是模拟器节点,/teleop_turtle 是键盘控制节点。

查看主题

主题用于节点之间发布和订阅消息,实现异步数据传输。

ros2 topic list -t # -t 参数用于显示消息类型

输出类似如下:

/parameter_events [rcl_interfaces/msg/ParameterEvent]
/rosout [rcl_interfaces/msg/Log]
/turtle1/cmd_vel [geometry_msgs/msg/Twist]
/turtle1/color_sensor [turtlesim/msg/Color]
/turtle1/pose [turtlesim/msg/Pose]
  • /turtle1/cmd_velteleop_turtle 节点向该主题发布速度指令,turtlesim 节点订阅该主题并控制乌龟移动。消息类型为 geometry_msgs/msg/Twist
  • /turtle1/poseturtlesim 节点向该主题发布乌龟的当前位置和方向。消息类型为 turtlesim/msg/Pose

查看服务

服务用于节点之间的同步请求和响应。

ros2 service list -t # -t 参数用于显示服务类型

输出类似如下:

/clear [std_srvs/srv/Empty]
/kill [turtlesim/srv/Kill]
/reset [std_srvs/srv/Empty]
/spawn [turtlesim/srv/Spawn]
/teleop_turtle/describe_parameters [rcl_interfaces/srv/DescribeParameters]
/teleop_turtle/get_parameter_types [rcl_interfaces/srv/GetParameterTypes]
# ... 其他参数服务 ...
/turtle1/set_pen [turtlesim/srv/SetPen]
/turtle1/teleport_absolute [turtlesim/srv/TeleportAbsolute]
/turtle1/teleport_relative [turtlesim/srv/TeleportRelative]
/turtlesim/describe_parameters [rcl_interfaces/srv/DescribeParameters]
# ... 其他参数服务 ...
  • /spawn:由 /turtlesim 节点提供,用于生成新乌龟。服务类型为 turtlesim/srv/Spawn
  • /kill:由 /turtlesim 节点提供,用于移除乌龟。
  • /set_pen:由 /turtlesim 节点提供,用于设置指定乌龟的画笔颜色和宽度。
  • /describe_parameters/get_parameter_types 等服务由 ROS 2 用于处理节点参数。

查看动作

动作用于执行长时间运行、可抢占且需要反馈的任务。

ros2 action list -t

当前场景下,输出通常为空或包含以下动作:

/turtle1/rotate_absolute [turtlesim/action/RotateAbsolute]

完成上述检查后,可以使用 RQT 以图形化方式查看 ROS 2 服务。


使用 RQT

RQT 是一个图形化工具框架,可通过不同插件查看和调试 ROS 2 系统。

安装 RQT 及常用插件(可选)

Docker 镜像或原生安装脚本可能已安装 RQT 及其常用插件。如果未安装,请执行以下步骤:

  1. 打开终端并加载 ROS 2 环境。
  2. 更新软件包列表
    sudo apt update
  3. 安装 RQT 及其常用插件
    # 使用通配符安装所有 rqt 相关包 (会安装较多插件)
    sudo apt install ~nros-humble-rqt*
    # 或者只安装核心和常用插件
    # sudo apt install ros-humble-rqt ros-humble-rqt-common-plugins

启动 RQT

在已加载 ROS 2 环境的新终端中运行:

rqt

命令运行后将打开 RQT 主窗口。

使用 Service Caller

使用 RQT 的 Service Caller 插件调用 turtlesim 节点提供的服务:

  1. 打开插件:在 RQT 窗口顶部选择 Plugins > Services > Service Caller

  2. 刷新服务列表:在 Service Caller 插件窗口中,单击 Service 下拉列表左侧的刷新按钮。

    如果列表为空或缺少 /spawn/kill/turtle1/set_pen 等服务,请确认 turtlesim_node 仍在运行,并确认运行 RQT 的终端已加载 ROS 2 环境。仍无法显示时,关闭 RQT 并运行以下命令:

    rqt --force-discover

调用 /spawn 服务生成新乌龟

调用 /spawn 服务,在模拟器中添加第二只乌龟:

  1. 选择服务:在 Service 下拉列表中选择 /spawn

  2. 填写请求参数/spawn 服务需要新乌龟的名称(name)、初始位置(xy)和朝向(theta)。

    • Request 区域找到 name 对应的行。

    • 双击 Expression 列中的值,在单引号之间输入唯一名称,例如 'turtle2',然后按 Enter。

      # 只需修改 Expression 列
      name: 'turtle2' # String
      x: 0.0 # Float
      y: 0.0 # Float
      theta: 0.0 # Float
    • 修改 xy,为新乌龟设置不同的初始位置,例如:

      x: 2.0
      y: 8.0

    保持 theta: 0.0,使乌龟朝向右侧。

  3. 调用服务:单击 Service Caller 插件窗口右上角的 Call

调用成功后,Turtlesim 窗口将在 (2.0, 8.0) 位置生成名为 turtle2 的乌龟。刷新服务列表后,可以看到 /turtle2/set_pen/turtle2/teleport_absolute 等服务。

警告

新乌龟的名称必须唯一。如果再次使用 turtle1,服务调用将失败。

调用 /set_pen 服务修改画笔

调用 /turtle1/set_pen 服务,修改 turtle1 画笔的颜色和粗细:

  1. 选择服务:在 Service 下拉列表中选择 /turtle1/set_pen

  2. 填写请求参数rgb 表示 RGB 颜色值,范围为 0–255;width 表示线条宽度;off 为 0 时绘制轨迹,为 1 时停止绘制。以下参数将画笔设置为红色,宽度设置为 5:

    r: 255 # Red component
    g: 0 # Green component
    b: 0 # Blue component
    width: 5 # Line width
    off: 0 # Pen down (drawing enabled)
  3. 调用服务:单击 Call

切换到运行 turtle_teleop_key 的终端并移动 turtle1。此时,乌龟将绘制宽度为 5 的红色轨迹。


使用主题重映射控制多只乌龟

turtle_teleop_key 默认向 /turtle1/cmd_vel 主题发布速度指令,因此只能控制 turtle1。要控制 turtle2,请启动另一个 turtle_teleop_key 节点,并将主题重映射到 /turtle2/cmd_vel

  1. 打开新终端。

  2. 加载 ROS 2 环境

    source /opt/ros/humble/setup.bash
  3. 启动 turtle_teleop_key 并重映射主题

    ros2 run turtlesim turtle_teleop_key --ros-args --remap turtle1/cmd_vel:=turtle2/cmd_vel
    • --ros-args:表示后续参数是 ROS 2 参数。
    • --remap <原始名称>:=<新名称>:将节点使用的原始主题名称替换为新的主题名称。
  4. 验证控制效果

    • 在运行重映射命令的终端中按方向键,确认 turtle2 移动。
    • 切换到第一个运行 turtle_teleop_key 的终端并按方向键,确认 turtle1 移动。

通过主题重映射,两个 turtle_teleop_key 节点可以分别控制不同的乌龟。


关闭 Turtlesim

完成练习后,关闭相关节点和窗口:

  1. 停止键盘控制节点:在两个运行 turtle_teleop_key 的终端中按 qCtrl+C
  2. 停止 Turtlesim 模拟器节点:在运行 turtlesim_node 的终端中按 Ctrl+C
  3. 关闭 RQT:关闭 RQT 窗口。
  4. 退出 Docker 容器(如果使用 Docker)
    • 运行 exit 退出容器终端。
    • 运行 docker stop <container_id> 停止后台容器。将 <container_id> 替换为实际容器 ID。

总结

本指南介绍了以下操作:

  • 使用原生安装或 Docker 镜像部署 ROS 2 Humble。
  • 启动 Turtlesim,并使用 turtle_teleop_key 控制乌龟。
  • 使用 ros2 命令查看节点、主题、服务和动作。
  • 使用 RQT 的 Service Caller 插件调用 /spawn/set_pen 服务。
  • 使用主题重映射分别控制 turtle1turtle2

进一步学习

如需进一步了解 ROS 2 核心概念,请参见 FishROS ROS 2 Humble 教程

  • 节点:了解 ROS 2 系统中的基本执行单元。
  • 主题:了解节点之间如何通过发布和订阅异步交换数据。
  • 服务:了解节点之间如何通过请求和响应进行同步通信。
  • 参数:了解如何配置和修改节点运行时参数。
  • 动作:了解如何执行长时间运行、可抢占且需要反馈的任务。

附录

常见问题

问题描述可能原因解决方案
找不到 ros2 命令未加载 ROS 2 环境执行 source /opt/ros/humble/setup.bash,并确认该命令已添加到 ~/.bashrc
Turtlesim 或 RQT 窗口无法显示1. Docker 环境未配置 DISPLAY
2. X Server 权限不足
1. 确认 Docker 启动命令包含 -e DISPLAY=unix$DISPLAY-v /tmp/.X11-unix:/tmp/.X11-unix
2. 执行 xhost +local: 临时允许本地访问 X Server。
RQT 中未显示服务列表1. Turtlesim 节点未运行
2. 网络发现异常
1. 确认 turtlesim_node 正常运行。
2. 关闭 RQT,然后运行 rqt --force-discover
重映射后无法控制乌龟重映射语法错误检查重映射参数 --remap turtle1/cmd_vel:=turtle2/cmd_vel,确认使用 := 而不是 =

相关资源