当前位置: 首页 > article >正文

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

在这里插入图片描述

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

目录

  • 一、Hello World工程简介
  • 二、ROS2 Hello World C++版
    • 2.1 创建工作空间目录
    • 2.2 创建功能包
    • 2.3 编辑源文件
    • 2.4 编辑编译配置文件CMakeList.txt
    • 2.5 编译工程
    • 2.6 运行节点

万物始于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


http://www.kler.cn/a/417533.html

相关文章:

  • JAVA异步的TCP 通讯-客户端
  • 如何利用maven更优雅的打包
  • 【论文精读】Taming Transformers for High-Resolution Image Synthesis
  • SQL 秒变 ER 图 sql转er图
  • C#面试常考随笔13: 泛型的主要约束和次要约束是什么?
  • java项目验证码登录
  • Keras构建卷积神经网络
  • 48-基于单片机的LCD12864时间调控和串口抱站
  • Oracle对比表与表之间的结构
  • 【Lucene】单个cpu 每秒能支持多少个bm25公式的计算
  • Apache Flink从Kafka中消费商品数据,并进行商品分类的数量统计题
  • 【测试工具JMeter篇】JMeter性能测试入门级教程(四):JMeter中BeanShell内置方法使用
  • 拓扑排序(C++实现)
  • ffmpeg安装(windows)
  • updatexml报错注入原理分析
  • kylinos-server源码安装xrdp
  • 丹摩征文活动 | SD3+ComfyUI的图像部署实践 AIGC图像
  • 基于Java Springboot蛋糕订购小程序
  • 【大模型实战篇】基于大模型GLM的检索增强实践
  • dpcas - v1 (Deep Learning Componentized Application System):深度学习组件化应用系统
  • VBA代码解决方案第二十讲:EXCEL工作表的添加与删除
  • PID模糊控制算法(附MATLAB仿真程序)
  • 【Java】设计模式——策略模式
  • PVE中的VLAN问题
  • 多线程(3)线程中的常用结构
  • 如何实现字符串反转-多语言