【ROS】ROS2编程示例:话题订阅-发布-C++版

news2024/11/25 12:44:07

1、准备

1)安装ROS2
【ROS】Ubuntu22.04安装ROS2(Humble Hawksbill)

2)ROS2命令
【ROS】ROS2命令行工具详解

3)配置工作空间
【ROS】ROS2中的概念和名词解释中第一节:工作空间 workspace

4)ROS2源码及官方示例:

https://github.com/ros2
https://github.com/ros2/examples

2、编辑

2.1 创建功能包

cd ~/ros/src
mkdir laoerExample
cd laoerExample
ros2 pkg create --build-type ament_cmake cPubSub

注意:创建功能包时一定要先创建好目录,进入相应的目录后创建,不要使用下面的方法,否则会在编译时报错

cd ~/ros/src
ros2 pkg create --build-type ament_cmake laoerExample/cPubSub

解决方法参见博文最后的错误处理一节

2.2 编辑源码

2.2.1 发布者

官方示例源码

#include <chrono>
#include <functional>
#include <memory>
#include <string>

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

using namespace std::chrono_literals;

class MinimalPublisher : public rclcpp::Node
{
  public:
    /* 公共构造函数将节点命名为minimal_publisher,并将count_初始化为0 */
    MinimalPublisher()
    : Node("minimal_publisher"), count_(0)
    {
      /* 初始化发布者publisher_ ,使用String消息类型、主题名称topic和在发生备份时限制消息所需的队列大小10 */
      publisher_ = this->create_publisher<std_msgs::msg::String>("topic", 10);

      /* 初始化timer_,设置timer_callback函数每500ms执行一次 */
      timer_ = this->create_wall_timer(500ms, std::bind(&MinimalPublisher::timer_callback, this));
    }

  private:
    /* 定义定时器回调函数 */
    void timer_callback()
    {
      /* 打印并发布字符串信息 */
      auto message = std_msgs::msg::String();
      message.data = "Hello, world: " + std::to_string(count_++);
      RCLCPP_INFO(this->get_logger(), "Publishing: '%s'", message.data.c_str());
      publisher_->publish(message);
    }

    /* 计时器、发布者和计数器字段的声明 */
    rclcpp::TimerBase::SharedPtr timer_;
    rclcpp::Publisher<std_msgs::msg::String>::SharedPtr publisher_;
    size_t count_;
};

int main(int argc, char * argv[])
{
  /* 初始化ROS2 */
  rclcpp::init(argc, argv);

  /* 运行节点MinimalPublisher */
  rclcpp::spin(std::make_shared<MinimalPublisher>());

  /* 退出ROS2 */
  rclcpp::shutdown();
  return 0;
}

2.2.2 订阅者
官方示例源码

#include <memory>

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

/* 占位符,代替回调函数中的第一个参数 */
using std::placeholders::_1;


/* 继承rclcpp:: node创建节点类MinimalSubscriber */
class MinimalSubscriber : public rclcpp::Node
{
  public:
    /* 公共构造函数将节点命名为minimal_subscriber */
    MinimalSubscriber()
    : Node("minimal_subscriber")
    {
      /* 初始化订阅者subscription_  ,使用String消息类型、主题名称topic和在发生备份时限制消息所需的队列大小10,
         订阅话题回调函数topic_callback */
      subscription_ = this->create_subscription<std_msgs::msg::String>(
      "topic", 10, std::bind(&MinimalSubscriber::topic_callback, this, _1));
    }

  private:
    /* 定义订阅话题回调函数 */
    void topic_callback(const std_msgs::msg::String & msg) const
    {
      /* 打印话题消息的字符串信息 */
      RCLCPP_INFO(this->get_logger(), "I heard: '%s'", msg.data.c_str());
    }

    /* 订阅者字段的声明 */
    rclcpp::Subscription<std_msgs::msg::String>::SharedPtr subscription_;
};

int main(int argc, char * argv[])
{
  /* 初始化ROS2 */
  rclcpp::init(argc, argv);

  /* 运行节点MinimalSubscriber*/
  rclcpp::spin(std::make_shared<MinimalSubscriber>());

  /* 退出ROS2 */
  rclcpp::shutdown();
  return 0;
}

2.3 添加依赖配置

路径:~/ros/src/laoerExample/cPubSub/package.xml

修改package.xml,添加依赖:rclcpp和std_msgs

<build_depend>rclcpp</build_depend>
<build_depend>std_msgs</build_depend>

<exec_depend>rclcpp</exec_depend>
<exec_depend>std_msgs</exec_depend>

完整package.xml 如下:

<?xml version="1.0"?>
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="3">
  <name>cPubSub</name>
  <version>0.0.0</version>
  <description>TODO: Package description</description>
  <maintainer email="lesen@todo.todo">lesen</maintainer>
  <license>TODO: License declaration</license>

  <buildtool_depend>ament_cmake</buildtool_depend>

  <build_depend>rclcpp</build_depend>
  <build_depend>std_msgs</build_depend>

  <exec_depend>rclcpp</exec_depend>
  <exec_depend>std_msgs</exec_depend>

  <test_depend>ament_lint_auto</test_depend>
  <test_depend>ament_lint_common</test_depend>

  <export>
    <build_type>ament_cmake</build_type>
  </export>
</package>

2.4 修改编译配置

路径:~/ros/src/laoerExample/cPubSub/CMakeLists.txt
1)设置功能包编译工程名

project(cPubSub)

2)添加需要搜索的依赖:rclcpp和std_msgs

find_package(rclcpp REQUIRED)
find_package(std_msgs REQUIRED)

3)添加可执行程序、对应的源码和依赖项

add_executable(talker src/cPub.cpp)
ament_target_dependencies(talker rclcpp std_msgs)
add_executable(listener src/cSub.cpp)
ament_target_dependencies(listener rclcpp std_msgs)

4)添加安装相关的配置

install(TARGETS
	talker
	listener
	DESTINATION lib/${PROJECT_NAME})

5)完整的CMakeLists.txt 如下:

cmake_minimum_required(VERSION 3.8)
project(cPubSub)

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)
# uncomment the following section in order to fill in
# further dependencies manually.
# find_package(<dependency> REQUIRED)
find_package(rclcpp REQUIRED)
find_package(std_msgs REQUIRED)

if(BUILD_TESTING)
  find_package(ament_lint_auto REQUIRED)
  # the following line skips the linter which checks for copyrights
  # comment the line when a copyright and license is added to all source files
  set(ament_cmake_copyright_FOUND TRUE)
  # the following line skips cpplint (only works in a git repo)
  # comment the line when this package is in a git repo and when
  # a copyright and license is added to all source files
  set(ament_cmake_cpplint_FOUND TRUE)
  ament_lint_auto_find_test_dependencies()
endif()
  
add_executable(talker src/cPub.cpp)
ament_target_dependencies(talker rclcpp std_msgs)
add_executable(listener src/cSub.cpp)
ament_target_dependencies(listener rclcpp std_msgs)

install(TARGETS
  talker
  listener
  DESTINATION lib/${PROJECT_NAME})

ament_package()

3、编译

在工作空间根目录中编译:

cd ~/ros
~/ros$ colcon build

4、运行

在终端1中运行监听者:

source install/setup.sh 
ros2 run cPubSub listener

在终端2中运行发布者:

source install/setup.sh 
ros2 run cPubSub talker

终端2输出打印信息:

[INFO] [1685584069.664099791] [minimal_publisher]: Publishing: 'Hello, world: 0'
[INFO] [1685584070.164132203] [minimal_publisher]: Publishing: 'Hello, world: 1'
[INFO] [1685584070.664138610] [minimal_publisher]: Publishing: 'Hello, world: 2'
……

终端1输出打印信息:

[INFO] [1685584069.664645713] [minimal_subscriber]: I heard: 'Hello, world: 0'
[INFO] [1685584070.164559773] [minimal_subscriber]: I heard: 'Hello, world: 1'
[INFO] [1685584070.664552715] [minimal_subscriber]: I heard: 'Hello, world: 2'
……

5、测试

1)查看节点信息
在终端3中查看节点信息,运行命令:ros2 node list

~/ros$ ros2 node list
/minimal_publisher
/minimal_subscriber

对应源码中定义节点时:

MinimalPublisher() : Node("minimal_publisher"), count_(0)

2)查看话题信息
在终端3中查看话题信息,运行命令:ros2 topic list

~/ros$ ros2 topic list 
/parameter_events
/rosout
/topic

话题topic对应源码创建话题时:

publisher_ = this->create_publisher<std_msgs::msg::String>("topic", 10);

3)查看节点连接信息,运行命令:rqt_graph
在这里插入图片描述

6、错误处理

6.1 arget names may not contain a slash

1)错误信息

CMake Error at /opt/ros/humble/share/ament_cmake_core/cmake/ament_cmake_uninstall_target-extras.cmake:40 (add_custom_target):
  add_custom_target called with invalid target name
  "laoerExample/cPubSub_uninstall".  Target names may not contain a slash.

2)原因
在创建功能包时,对包名加入了路径信息,如下

ros2 pkg create --build-type ament_cmake laoerExample/cPubSub

导致在CMakeLists.txt中定义目标名称时,自动加入了路径,从而产生了反斜杠,最终导致cmake不能识别而报错:

project(laoerExample/cPubSub)

3)解决方法
去掉路径描述

project(cPubSub)

或者在创建功能包时,不要加入路径信息

6.2 CMake Error at …… package.xml

1)错误信息

CMake Error at /opt/ros/humble/share/ament_cmake_core/cmake/core/ament_package_xml.cmake:95 (message):
  execute_process(/usr/bin/python3.10
  /opt/ros/humble/share/ament_cmake_core/cmake/core/package_xml_2_cmake.py
  /home/lesen/ros/src/laoerExample/cPubSub/package.xml
  /home/lesen/ros/build/cPubSub/ament_cmake_core/package.cmake) returned
  error code 1

2)原因
在创建功能包时,对包名加入了路径信息,如下

ros2 pkg create --build-type ament_cmake laoerExample/cPubSub

导致在package.xml中定义name标签时,自动加入了路径,从而产生了反斜杠,最终导致ackage_xml_2_cmake.py脚本不能识别而报错:

<name>laoerExample/cPubSub</name>

3)解决方法
去掉路径描述

<name>cPubSub</name>

或者在创建功能包时,不要加入路径信息

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/596340.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MySQL-12-SQL优化

一、MySQL体系结构 1.1、体系结构 # 1.2、查询执行流程 参考&#xff1a;https://www.cnblogs.com/xfeiyun/p/15899990.html 1.3、组件说明 管理工具&#xff1a;MySQL服务软件安装后提供的命令连接池&#xff1a;检查本机是否有空闲资源&#xff08;线程&#xff0c;内存&…

Geoffrey Hinton、姚期智、张钹、Sam Altman等专家共话AI安全与对齐丨2023智源大会议程公开...

6月9日&#xff0c;2023北京智源大会&#xff0c;将邀请AI领域的探索者、实践者、以及关心智能科学的每个人&#xff0c;共同拉开未来舞台的帷幕&#xff0c;你准备好了吗&#xff1f;与会知名嘉宾包括&#xff0c;图灵奖得主Yann LeCun、OpenAI创始人Sam Altman、图灵奖得主Ge…

Linux教程——Linux和UNIX的关系及区别(详解版)

UNIX 与 Linux 之间的关系是一个很有意思的话题。在目前主流的服务器端操作系统中&#xff0c;UNIX 诞生于 20 世纪 60 年代末&#xff0c;Windows 诞生于 20 世纪 80 年代中期&#xff0c;Linux 诞生于 20 世纪 90 年代初&#xff0c;可以说 UNIX 是操作系统中的"老大哥&…

开始梳理大学课程体系(二)--万字数据结构总结上

数据结构总结 第一章 概述1.1 基本概念和术语1.2 数据结构1. 2.1 逻辑结构1.2.2 存储结构 1.3 数据类型和抽象数据类型1.3.1 数据类型1.3.2 抽象数据类型 1.4 算法和算法分析1.4.1 算法的定义及特性1.4.2 评价算法优劣的基本标准1.4.3 算法的时间复杂度1.4.4 算法的空间复杂度 …

chatgpt赋能python:用Python优化交通

用Python优化交通 作为一种功能强大的编程语言&#xff0c;Python已经被广泛应用于各个领域。交通领域也不例外。在交通领域&#xff0c;Python可以发挥重要作用&#xff0c;帮助优化交通运行&#xff0c;提高安全性和效率。 实时路况预测 Python可以通过机器学习算法来对实…

【Linux】进程与文件系统(详细解析)

文章目录 1.前言&#xff08;提出问题&#xff09;2.认识问题3.回顾c文件接口4.学习系统文件IOopen函数第一个参数第二个参数第三个参数函数的返回值 write函数read函数close函数 5.文件描述符 1.前言&#xff08;提出问题&#xff09; 在C语言阶段学习文件操作的时候&#xf…

基于PP-OCRv3的车牌检测和识别

本项目基于百度飞桨AI Studio平台进行实现&#xff0c;百度出品的深度学习平台飞桨&#xff08;PaddlePaddle&#xff09;是主流深度学习框架中一款完全国产化的产品&#xff0c;与Google TensorFlow、Facebook Pytorch齐名。2016 年飞桨正式开源&#xff0c;是国内首个全面开源…

【SpringMVC】| 域对象共享数据

目录 前期准备 域对象共享数据 一&#xff1a;向request域共享数据&#xff08;五种方法&#xff09; 1. 使用ServletAPI向request域对象共享数据&#xff08;了解&#xff09; 2. 使用ModelAndView向request域对象共享数据 3. 使用Model向request域对象共享数据 4. 使用…

chatgpt赋能python:Python代码怎么找?这里介绍几种方法

Python代码怎么找&#xff1f;这里介绍几种方法 在编写Python程序的时候&#xff0c;经常会遇到需要查找已有代码的情况。那么&#xff0c;在这里&#xff0c;我们将介绍几种查找Python代码的方法&#xff0c;希望能对大家有所帮助。 使用文本编辑器的查找功能 在大多数文本…

3.场(field)

目录 1.复习 2.引言 3.数量场 1.概念 2.例题 4.矢量场 1.概念 2.例题 5.坐标变换和坐标单位矢 1.坐标变换 2.单位矢 1.复习 2.引言 如果说矢量分析研究的是矢量的时间变化&#xff0c;那么场就是它的空间变化. 场是客观存在的&#xff0c;杨振宁先生在总结20世…

Spring Boot 3.1中如何整合Spring Security和Keycloak

在今年2月14日的时候&#xff0c;Keycloak 团队宣布他们正在弃用大多数 Keycloak 适配器。其中包括Spring Security和Spring Boot的适配器&#xff0c;这意味着今后Keycloak团队将不再提供针对Spring Security和Spring Boot的集成方案。但是&#xff0c;如此强大的Keycloak&…

数据库|TiDB 数据库大版本升级-基于TiCDC异机升级

作者&#xff1a;高文峰 | 神州数码云基地TiDB团队成员 目录 一、前言 二、升级架构图 三、升级流程 1.下游TiDB集群部署过程 2. 上游TiCDC节点的扩容 3. 上游数据全备恢复到下游 4. TiCDC启用正向同步任务 5. 应用停服务&#xff0c;tidb 无业务会话连接 6. 确认数据…

2023年6月跟产品开发专家学NPDP产品经理认证课到这里

NPDP产品经理国际资格认证是国际公认的唯一的新产品开发专业认证&#xff0c;集理论、方法与实践为一体的全方位的知识体系&#xff0c;为公司组织层级进行规划、决策、执行提供良好的方法体系支撑。 我们针对互联网时代的个人、互联网企业、与传统企业推出一系列学习。 课程从…

小车跑迷宫,如何完成?

先看视频1&#xff1a; 先看视频2&#xff1a; 要制作一个能顺利走到迷宫终点&#xff0c;并能按最短路径回来的小车&#xff0c;重中之重就是寻找其最短路径的算法&#xff0c;迷宫情况复杂多变&#xff0c;多个路口交错纵横&#xff0c;想要完美的找出最短路径并不容易&#…

事件相关功能磁共振波谱技术(fMRS)

导读 质子磁共振波谱(MRS)是一种非侵入性脑成像技术&#xff0c;用于测量不同神经化学物质的浓度。“单体素”MRS数据通常在几分钟内采集&#xff0c;然后对单个瞬态进行平均&#xff0c;从而测量神经化学物质浓度。然而&#xff0c;这种方法对更快速的神经化学物质的时间动态…

chatgpt赋能python:Python人脸身份识别:提高安全性和效率的先进技术

Python人脸身份识别&#xff1a;提高安全性和效率的先进技术 随着科技的发展&#xff0c;人类对于安全性和效率的需求逐渐增加。而人脸身份识别技术正是一个能够满足这一需求的先进技术。在过去的几年中&#xff0c;这种技术已经逐渐发展成为一种普及的安全措施&#xff0c;这…

串口组件:ZylSerialPort.NET 1.83 Crack

ZylSerialPort.NET 1.83 .NET 组件 库 ZylSerialPort.NET 是一个基于线程、事件驱动、异步/同步串口的.NET 组件库。 使用 ZylSerialPort.NET 组件可以轻松地通过串行端口连接与外部设备进行通信&#xff0c;例如调制解调器、条形码阅读器、GSM 模块等。 您也可以将它与 USB、…

Volatile、Synchronized、ReentrantLock锁机制使用说明

一、Volatile底层原理 volatile是轻量级的同步机制&#xff0c;volatile保证变量对所有线程的可见性&#xff0c;不保证原子性。 当对volatile变量进行写操作的时候&#xff0c;JVM会向处理器发送一条LOCK前缀的指令&#xff0c;将该变量所在缓存行的数据写回系统内存。由于缓…

DJ4-7 请求分页存储管理方式

目录 4.7.1 请求分页中的硬件支持 1、页表机制 2、缺页中断机构 4.7.2 内存分配策略和分配算法 1、最小物理块数的确定 2、物理块的分配策略 3、物理块的分配算法 4.7.3 调页策略 1、系统应当在何时把一个页面装入内存&#xff1f; 2、从何处调入页面&#xff1f;…

机器学习常识 12: SVM

摘要: 支持向量机 (support vector machine, SVM) 有很多闪光点, 理论方面有 VC 维的支撑, 技术上有核函数将线性不可分变成线性可分, 实践上是小样本学习效果最好的算法. 1. 线性分类器 如图 1 所示, 基础的 SVM 仍然是一个线性二分类器, 这一点与 logistic 回归一致. 图 1.…