Docker镜像进行ROS2开发的实现步骤

 更新时间:2026年08月04日 09:58:59   作者:爱就是恒久忍耐  
本文主要介绍了Docker镜像进行ROS2开发的实现步骤,以jazzy版本为例,从下载官方桌面镜像到运行小乌龟测试,再到使用VSCode进行容器开发,全程免去环境配置的痛苦,感兴趣的可以了解一下

ROS2的每个版本都有对应的Ubuntu版本,如果本机的Linux系统和ROS2要求的版本不一致,还得重新安装,但是如果使用Docker镜像,就不用关心本机的Linux版本了。

本文讲述如何使用ROS2的官方镜像来进行开发。本人的本地Linux是WSL2 Debian

一 下载镜像

本文写作时,ROS2处于LTS状态的有三个版本,

  • humble:2022-05发布,支持到2027-05
  • jazzy:2024-05发布,支持到2029-05
  • lyrical:2026-05发布,支持到2031-05

这里以jazzy举例,进入ROS2的docker hub地址https://hub.docker.com/r/osrf/ros/tags,找到jazzy-desktop-full,如下,

然后copy红框中的docker指令,最后进入Linux终端执行这个指令。

下载完毕后通过docker images查看,

二 测试镜像

执行指令

docker run --rm -it --env DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix osrf/ros:jazzy-desktop-full bash 

进入容器后,需要执行

source /opt/ros/jazzy/setup.bash

这样才能执行ros2指令。然后运行ROS2自带的小乌龟例子,

ros2 run turtlesim turtlesim_node

然后弹出界面,

此时在宿主机里开启另外一个终端,并使用docker ps来查看容器ID,

然后使用docker指令在当前终端接入这个容器,

docker exec -it 919ff4e779a0 bash

进入后还需再执行source /opt/ros/jazzy/setup.bash,最后执行下面指令开启按键控制节点,

ros2 run turtlesim turtle_teleop_key

开启按键的终端必须保持选中激活,然后按方向键来操作小乌龟移动,

三 使用VSCode基于ROS2容器开发

配置 (由AI生成)

在宿主机里创建一个目录ros2_test,然后里面添加一个docker-compose.yml,内容如下,

services:
  ros2_jazzy:
    image: osrf/ros:jazzy-desktop-full
    stdin_open: true
    tty: true
    environment:
      DISPLAY: ${DISPLAY}
      TZ: Asia/Shanghai
    volumes:
      - /tmp/.X11-unix:/tmp/.X11-unix
      # 当前项目目录挂载到容器 /root/ros2_ws
      - .:/root/ros2_ws:cached

这个配置是把当前工程目录挂载到容器里的/root/ros2_ws/下。

然后创建目录.devcontainer,最后在里面添加devcontainer.json,内容如下,

{
    "name": "ROS2 Jazzy Dev",
    "dockerComposeFile": "../docker-compose.yml",
    "service": "ros2_jazzy",
    "workspaceFolder": "/root/ros2_ws",
    "customizations": {
        "vscode": {
            "extensions": [
                "ms-vscode.cpptools",
                "ms-python.python",
                "twxs.cmake",
                "eamodio.gitlens",
                "redhat.vscode-yaml",
                "Ranch-Hand-Robotics.rde-pack"
            ]
        }
    },
    "runArgs": ["--cap-add=SYS_PTRACE","--security-opt","seccomp=unconfined"],
    "containerEnv": {
        "ROS_DOMAIN_ID": "0"
    }
}

最后创建src目录,里面的结构如下,

package.xml内容如下,

<?xml version="1.0"?>
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" rel="external nofollow"  schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="3">
  <name>cpp_demo</name>
  <version>0.0.0</version>
  <description>ROS2 C++ simple demo</description>
  <maintainer email="user@todo.todo">user</maintainer>
  <license>Apache-2.0</license>

  <buildtool_depend>ament_cmake</buildtool_depend>

  <depend>rclcpp</depend>
  <depend>std_msgs</depend>

  <buildtool_depend>ament_cmake_auto</buildtool_depend>
  <export>
    <build_type>ament_cmake</build_type>
  </export>
</package>

CMakeLists.txt内容如下,

cmake_minimum_required(VERSION 3.8)
project(cpp_demo)

if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
  add_compile_options(-Wall -Wextra -Wpedantic)
endif()

# find dependencies
find_package(ament_cmake REQUIRED)
find_package(rclcpp REQUIRED)
find_package(std_msgs REQUIRED)

# ---------------- talker ----------------
add_executable(talker src/talker.cpp)
ament_target_dependencies(talker rclcpp std_msgs)

# ---------------- listener ----------------
add_executable(listener src/listener.cpp)
ament_target_dependencies(listener rclcpp std_msgs)

# 安装可执行文件
install(TARGETS
  talker
  listener
  DESTINATION lib/${PROJECT_NAME}
)

ament_package()

listener.cpp内容如下,

#include <rclcpp/rclcpp.hpp>
#include <std_msgs/msg/string.hpp>

class ListenerNode : public rclcpp::Node
{
public:
    ListenerNode() : Node("listener")
    {
        subscription_ = this->create_subscription<std_msgs::msg::String>(
            "/chatter",
            10,
            std::bind(&ListenerNode::callback, this, std::placeholders::_1)
        );
    }

private:
    void callback(const std_msgs::msg::String::SharedPtr msg) const
    {
        RCLCPP_INFO(this->get_logger(), "[接收] %s", msg->data.c_str());
    }

    rclcpp::Subscription<std_msgs::msg::String>::SharedPtr subscription_;
};

int main(int argc, char * argv[])
{
    rclcpp::init(argc, argv);
    rclcpp::spin(std::make_shared<ListenerNode>());
    rclcpp::shutdown();
    return 0;
}

talker.cpp内容如下,

#include <rclcpp/rclcpp.hpp>
#include <std_msgs/msg/string.hpp>
#include <chrono>

using namespace std::chrono_literals;

class TalkerNode : public rclcpp::Node
{
public:
    TalkerNode() : Node("talker"), count_(0)
    {
        // 创建发布者,话题名 "/chatter"
        publisher_ = this->create_publisher<std_msgs::msg::String>("/chatter", 10);
        timer_ = this->create_wall_timer(
            500ms,
            std::bind(&TalkerNode::timer_callback, this)
        );
    }

private:
    void timer_callback()
    {
        auto msg = std_msgs::msg::String();
        msg.data = "Hello ROS2! count: " + std::to_string(count_++);
        RCLCPP_INFO(this->get_logger(), "[发布] %s", msg.data.c_str());
        publisher_->publish(msg);
    }

    rclcpp::Publisher<std_msgs::msg::String>::SharedPtr publisher_;
    rclcpp::TimerBase::SharedPtr timer_;
    size_t count_;
};

int main(int argc, char * argv[])
{
    rclcpp::init(argc, argv);
    rclcpp::spin(std::make_shared<TalkerNode>());
    rclcpp::shutdown();
    return 0;
}

进入容器

按Ctrl+Shift+p,弹出命令框,选择Reopen in Container

VSCode会自动根据docker-compose.yml和devcontainer.json来创建容器连接,成功之后可以看下左下角,如下

编译

在VSCode里开启一个终端,然后执行下面指令,

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

这样在容器里开启终端就可以自动source,最后执行编译指令

colcon build --symlink-install

显示如下,

编译成功后把这个项目package添加到系统路径里,

source install/setup.bash

此时再开启一个终端,也执行一下上面的source install/setup.bash,这样准备工作就做好了。

测试

现在容器里开启了2个终端,第一个终端执行命令,

ros2 run cpp_demo talker

显示如下,

第二个终端执行命令,

ros2 run cpp_demo listener

显示如下,

验证成功!

四 总结

本文讲述如何使用Docker镜像进行ROS2开发,利用了镜像的方便之处,免除了环境准备的工作,非常方便。更多相关Docker进行ROS2开发内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 一篇文章学会Docker命令小结

    一篇文章学会Docker命令小结

    这篇文章主要介绍了一篇文章学会Docker命令小结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-07-07
  • Docker四种网络模式演示及连通性测试

    Docker四种网络模式演示及连通性测试

    这篇文章主要为大家介绍了Docker四种网络模式演示及连通性测试,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步早日升职加薪
    2022-04-04
  • Jenkins+Docker 一键自动化部署 SpringBoot 项目的详细步骤

    Jenkins+Docker 一键自动化部署 SpringBoot 项目的详细步骤

    这篇文章主要介绍了Jenkins+Docker 一键自动化部署SpringBoot 项目,本文章实现最简单全面的Jenkins+docker+springboot 一键自动部署项目,步骤齐全,少走坑路,需要的朋友可以参考下
    2022-08-08
  • Docker、Docker Compose部署实践过程

    Docker、Docker Compose部署实践过程

    这篇文章主要介绍了Docker、Docker Compose部署实践过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2026-03-03
  • 解决docker容器中出现Access denied for user 'root'@'172.17.0.2'(using password: YES)问题

    解决docker容器中出现Access denied for user &apo

    这篇文章主要介绍了解决docker容器中出现Access denied for user 'root'@'172.17.0.2'(using password: YES)问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-06-06
  • Docker容器添加新端口映射的方法与详细步骤

    Docker容器添加新端口映射的方法与详细步骤

    这篇文章主要给大家介绍了关于Docker容器添加新端口映射的方法与详细步骤,Docker 端口映射即映射容器内应用的服务端口到本机宿主机器,文中通过代码示例介绍的非常详细,需要的朋友可以参考下
    2023-08-08
  • Docker部署MongoDb的详细过程记录

    Docker部署MongoDb的详细过程记录

    这篇文章主要介绍了如何使用Docker Compose启动MongoDB副本集,包括配置文件编写、容器启动命令、副本集初始化、角色和用户创建等步骤,需要的朋友可以参考下
    2024-12-12
  • Docker启动常用容器命令及配置详解

    Docker启动常用容器命令及配置详解

    本文主要介绍了Docker启动常用容器命令及配置详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-03-03
  • docker无法删除镜像报Error: No such container的错误问题

    docker无法删除镜像报Error: No such container的错误问题

    docker无法删除镜像的解决方法很简单,只需要简单三步即可完美解决docker删除镜像过程中,一直报Error: No such container的错误问题,感兴趣的朋友跟随小编一起看看吧
    2023-01-01
  • Docker安装wordpress并配置数据库超详细介绍版

    Docker安装wordpress并配置数据库超详细介绍版

    安装WordPress是一项常见的任务,使用Docker可以使这个过程更加简单和可靠,下面这篇文章主要给大家介绍了关于Docker安装wordpress并配置数据库的相关资料,需要的朋友可以参考下
    2023-11-11

最新评论