【ROS2】ROS2 Hello World (C++实现)

在这里插入图片描述

ROS 系列学习教程(总目录)
ROS2 系列学习教程(总目录)

万物始于Hello World,为了体验ROS2,使用Hello World介绍ROS2的简单使用。

一、Hello World工程简介

首先需要创建工程,流程为:

  1. 创建工作空间目录(即工程根目录,与ROS1不同,ROS2不需要再初始化工作空间)
  2. 创建功能包(ROS基本单元,可以理解为一个功能模块,每个工程至少有一个功能包)
  3. 编辑源文件(写代码实现需求)
  4. 编辑编译配置文件(ROS2使用ament编译系统,这里编辑CMakeList.txt文件)
  5. 编译工程(使用colcon编译ROS2工程,生成可执行文件,即ros节点,下文均称作节点)

不只是Hello World,所有ROS2工程都是这样的流程。

二、ROS2 Hello World C++版

注:其中ros2_learning是工作空间的自定义名称。

2.1 创建工作空间目录

# 递归创建工作空间目录
mkdir -p ros2_learning/src

2.2 创建功能包

cd ros2_learning/src
ros2 pkg create --build-type ament_cmake hello_world_cpp

其中,

使用 --build-type 指定编译系统为 ament_cmake

hello_world_cpp:自定义功能包名称

结果如下图:

在这里插入图片描述

其中,有 [WARNING]: Unknown license 'TODO: License declaration'. ROS2建议创建一个 License 文件以说明该功能包的发布许可。可以使用 --license LICENSE 参数指定。

ros2 pkg create --build-type ament_cmake --license Apache-2.0 hello_world_cpp

生成的目录结构如下:

hello_world_cpp
├── CMakeLists.txt
├── include
│   └── hello_world_cpp
├── LICENSE
├── package.xml
└── src

2.3 编辑源文件

hello_world_cpp/src 目录下新增 publisher.cpp 文件,文件内容如下:

#include <chrono>

#include "rclcpp/rclcpp.hpp"
#include "std_msgs/msg/string.hpp"

using namespace std::chrono_literals;

class HelloWorldPublisher : public rclcpp::Node
{
    
    
public:
    HelloWorldPublisher()
        : Node("publisher"), m_count(0)
    {
    
    
        m_publisher = this->create_publisher<std_msgs::msg::String>("/hello_world", 10);
        m_timer = this->create_wall_timer(500ms, std::bind(&HelloWorldPublisher::timercallback, this));
    }

private:
    void timercallback()
    {
    
    
        auto message = std_msgs::msg::String();
        message.data = "Hello, world! " + std::to_string(this->m_count++);
        RCLCPP_INFO(this->get_logger(), "Publishing: '%s'", message.data.c_str());
        this->m_publisher->publish(message);
    }

private:
    rclcpp::TimerBase::SharedPtr m_timer;
    rclcpp::Publisher<std_msgs::msg::String>::SharedPtr m_publisher;
    size_t m_count;
};

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

2.4 编辑编译配置文件CMakeList.txt

默认生成的 CMakeList.txt 文件内容如下:

在这里插入图片描述

由于新增了源文件publisher.cpp,所以要配置该文件的编译规则。

找到ros2_learning/src/hello_world_cpp/CMakeLists.txt,修改如下:

在这里插入图片描述

修改说明如下:

# 添加 rclcpp 和 std_msgs 依赖包
find_package(rclcpp REQUIRED)
find_package(std_msgs REQUIRED)

# 指定源文件,生成可执行文件
add_executable(talker src/publisher.cpp)
# 指定可执行文件的依赖项
ament_target_dependencies(talker rclcpp std_msgs)

# 定义安装规则,指定可执行文件的安装目录
install(TARGETS
  talker
  DESTINATION lib/${
    
    PROJECT_NAME})

2.5 编译工程

进入到工作空间 ros2_learning 目录,执行如下指令编译该工程:

colcon build

编译成功后,会在ros2_learning目录下生成 buildinstalllog 目录。

  • build: 存放编译过程中产生的中间文件,包括临时文件、对象文件、依赖关系等。用户通常不需要直接访问这个目录,因为构建工具会自动管理其中的内容。然而,在调试构建问题时,有时可能需要查看这个目录中的文件以获取更多信息。
  • install: 存放最终编译生成的可执行文件、库文件、配置文件、环境设置文件等资源。这些资源是构建完成后准备发布的独立包,可以被其他项目或用户直接使用。通常包含多个子目录,如bin(可执行文件)、lib(库文件)、share(配置文件、资源文件等)等。用户可以在 install 目录中查找可执行文件或库文件来运行或链接ROS2节点或服务。此外,ROS2环境设置文件(如setup.bash)也存放在该目录,用于将ROS2包添加到用户的 PATH 和其他环境变量中。
  • log: 存放编译和运行过程中产生的各种日志信息。这些日志信息包括警告、错误、信息等,对于调试和监控 ROS2 系统的运行状态非常有用。这些日志文件可以是文本文件,也可以是其他格式的文件,具体取决于 ROS2 日志系统的配置。用户可以通过查看log目录中的日志文件来了解 ROS2 系统在编译或运行过程中的行为。此外,ROS2 还提供了日志查看工具(如rqt_console),这些工具可以方便地查看和分析日志文件中的内容。

2.6 运行节点

生成的节点在 install/hello_world_cpp/lib/hello_world_cpp 中,我们可以直接执行:

在这里插入图片描述

不过这样需要知道节点的具体路径,实际中操作较麻烦。

ROS2 提供了 run 命令,可以根据包名和节点名,在任何目录执行。

但需要先设置环境变量,即让系统可以找到节点,进入到工作空间目录,执行如下指令:

source install/setup.bash

在这里插入图片描述

但单次执行 source install/setup.bash 只对当前终端有效,新打开终端仍需再执行该命令,为了避免每次执行,可以把该命令加到当前用户的 .bashrc 文件中,该文件在用户的 home 目录下。

方法一:直接打开 ~/.bashrc 文件,在末尾添加 source 你的工作空间目录/install/setup.bash ,保存。

方法二:使用命令 echo "source 你的工作空间目录/install/setup.bash" >> ~/.bashrc

最后,使用命令 source ~/.bashrc 使修改生效。

在这里插入图片描述

运行 talker 节点后,还可以通过 topic 指令订阅 talker 发布的信息,如下:

在这里插入图片描述



欢迎大家加QQ群,一起讨论学习:894013891