ROS话题(Topic)通信:自定义msg - 例程与讲解

在 ROS 通信协议中,数据是以约定好的结构传输的,即数据类型,比如Topic使用的msg,Service使用的srv,ROS 中的 std_msgs 封装了一些原生的数据类型,比如:Bool、Char、Float32、Int64、String等,但这些类型结构简单,常常不能满足我们的需要,这时我们可以使用自定义的消息类型。

比如我们创建一个自定义消息,定义一个机器人的ID,位置(x, y)。

一、创建RobotPose.msg

我们仍然使用前文创建的 topic_hello_world 功能包,结构如下:

在这里插入图片描述

src的同级目录创建 msg 目录,在msg目录创建 RobotPose.msg 文件,内容如下:

string id
float64 x
float64 y
float64 angle

二、配置编译文件

需要对 CMakeLists.txt 作以下修改:

2.1 添加message_generation功能包

message_generation功能包,在构建时根据msgsrv生成消息和服务的接口文件(比如C++头文件和Python包),以便在 ROS 节点中使用。

find_package(catkin REQUIRED COMPONENTSroscpprospystd_msgsmessage_generation
)

注意这里需要同时在package.xml中添加以下内容:

<build_depend>message_generation</build_depend>

2.2 添加msg文件

添加自定义msg,该函数依赖message_generation功能包。

add_message_files(FILESRobotPose.msg
)

2.3 配置依赖并生成接口文件

添加处理msgsrv所需要的依赖,并生成接口文件,该函数依赖message_generation功能包。

generate_messages(DEPENDENCIESstd_msgs
)

2.4 添加message_runtime依赖

message_runtime 用于在运行时提供消息的序列化和反序列化支持。

这里注意,有时可能会看到没有显式添加 message_runtime 也能正常运行,这通常是因为其他依赖项(例如roscppstd_msgs)可能已经隐含地包含了 message_runtime。在这种情况下,构建系统已经处理了消息生成的任务。

然而,为了确保你的软件包在所有情况下都能正常工作,最好显示添加 message_runtime 作为你的软件包的依赖项。这样可以确保你的消息定义在构建和运行时得到正确处理。

需要对 CMakeLists.txt 作以下修改:

catkin_package(CATKIN_DEPENDS roscpp rospy std_msgs message_runtime
)

同时在package.xml中添加以下内容:

<exec_depend>message_runtime</exec_depend>

节外生枝的小知识:

catkin_package 是在ROS软件包的 CMakeLists.txt 文件中用于配置Catkin软件包的一条命令。它主要用于描述ROS软件包的元信息,并在构建系统中定义软件包的依赖关系。以下是 catkin_package 的一般用途:

  1. 软件包元信息配置: catkin_package 允许你指定软件包的元信息,例如软件包的名称、版本、作者、描述等。这些信息将用于标识和描述你的ROS软件包。

    cmakeCopy codecatkin_package(NAME your_package_nameVERSION 0.1.0DESCRIPTION "Your package description"AUTHOR "Your Name")
    
  2. 设置软件包的依赖项: catkin_package 允许你指定你的软件包依赖于其他ROS软件包的哪些部分。这些依赖项将在构建和运行时被解析和满足。

    cmakeCopy codecatkin_package(...CATKIN_DEPENDS roscpp std_msgs message_runtime)
    
  3. 导出软件包的目标: 通过 ${PROJECT_NAME}_EXPORTED_TARGETS 这样的参数,你可以导出软件包的目标,以便其他软件包能够正确地依赖你的软件包,并包含所有必要的目标。

    cmakeCopy codecatkin_package(...EXPORTED_TARGETS ${PROJECT_NAME}_EXPORTED_TARGETS)
    

总体而言,catkin_package 提供了一个中心化的地方,用于指定ROS软件包的基本信息和配置,以便构建系统和其他软件包能够正确地使用和依赖你的软件包。在ROS中,它是配置软件包最重要的命令之一。

三、实现发布者与订阅者(C++版)

3.1 源码

在创建的 topic_hello_world 包路径的 src 目录中创建 user_msg_pub.cpp 以实现发布者,编辑内容如下:

#include <ros/ros.h>
#include "topic_hello_world/RobotPose.h"int main(int argc, char **argv)
{ros::init(argc, argv, "user_msg_pub");ros::NodeHandle nh;ros::Publisher pose_pub = nh.advertise<topic_hello_world::RobotPose>("/robot_pose", 10);topic_hello_world::RobotPose pose;pose.id = "vbot";pose.x = 23.6;pose.y = 12.8;pose.angle = 90.0;while(ros::ok()){pose_pub.publish(pose);ROS_INFO("Pub robot: %s, pose(%lf, %lf, %lf)", pose.id.c_str(), pose.x, pose.y, pose.angle);ros::Duration(1).sleep();ros::spinOnce();}return 0;
}

创建 user_msg_sub.cpp 以实现订阅者,编辑内容如下:

#include <ros/ros.h>
#include "topic_hello_world/RobotPose.h"void robotPoseCallback(const topic_hello_world::RobotPose::ConstPtr &pose)
{ROS_INFO("Sub robot: %s, pose(%lf, %lf, %lf)", pose->id.c_str(), pose->x, pose->y, pose->angle);
}int main(int argc, char **argv)
{ros::init(argc, argv, "user_msg_sub");ros::NodeHandle nh;ros::Subscriber pose_sub = nh.subscribe<topic_hello_world::RobotPose>("/robot_pose", 10, robotPoseCallback);ros::spin();return 0;
}

修改 CMakeLists.txt ,只需添加如下内容:

add_executable(${PROJECT_NAME}_user_msg_pub src/user_msg_pub.cpp)
add_executable(${PROJECT_NAME}_user_msg_sub src/user_msg_sub.cpp)target_link_libraries(${PROJECT_NAME}_user_msg_pub${catkin_LIBRARIES}
)target_link_libraries(${PROJECT_NAME}_user_msg_sub${catkin_LIBRARIES}
)

3.2 编译运行

进入工作空间执行 catkin_make 命令编译工程,你可能会遇到如下错误:

在这里插入图片描述

这是因为上文提到的message_generation功能包,在它编译自定义msg生成对应接口文件之前,编译了c++源文件,但这时头文件RobotPose.h还没有生成,所以报错了。

到这里你有没有发现,如果各功能包间有依赖关系,他们的编译是有先后顺序的,那我们怎么控制这个先后顺序呢?答案是:不需要。哈哈,CMake已经替我们做了,我们只需告诉它哪个模块需要什么依赖,CMake内部会自动分析项目中的依赖关系,并根据这些依赖关系计算一个拓扑排序。然后,CMake会按照这个顺序处理各个功能包,以确保在构建过程中满足所有依赖关系。

我们可以在 CMakeLists.txt中使用 add_dependencies() 来添加这个依赖关系,语法如下:

add_dependencies(target_name dependency_target_name)

其中,target_name 是要添加依赖关系的目标名称,dependency_target_name 是要添加的依赖目标名称。

例如,如果你有一个名为 my_node 的目标,你想要添加一个名为 my_dependency 的库作为其依赖项,可以使用以下命令:

add_dependencies(my_node my_dependency)

所以,为解决上述报错,我们在 topic_hello_world/CMakeLists.txt中添加如下内容:

# 注意他们要放在add_executable之后,即先告诉CMake是哪个节点,再告诉CMake它需要什么依赖
add_dependencies(${PROJECT_NAME}_user_msg_pub ${PROJECT_NAME}_generate_messages_cpp)
add_dependencies(${PROJECT_NAME}_user_msg_sub ${PROJECT_NAME}_generate_messages_cpp)

其中,第一项是我们生成的节点,第二项 ${PROJECT_NAME}_generate_messages_cpp 是一个用于生成消息类型的C++文件的宏,它的作用是根据 .msg.srv 文件生成对应的 .h.cpp 文件。

3.3 节外生枝的小知识:

在ROS软件包的构建过程中,除了${PROJECT_NAME}_generate_messages_cpp,还有一些其他与消息生成和编译相关的宏。这些宏通常都是与 Catkin 工具链和 ROS 构建系统的一部分。

以下是一些常见的与消息生成相关的宏:

  1. ${PROJECT_NAME}_generate_messages 这个宏表示生成所有与消息相关的任务。通常,在调用 catkin_package(...) 时,CATKIN_DEPENDS 部分会包含 ${PROJECT_NAME}_generate_messages,以确保在构建软件包时执行消息生成任务。

    catkin_package(CATKIN_DEPENDS roscpp std_msgs message_runtime${PROJECT_NAME}_generate_messages
    )
    
  2. ${PROJECT_NAME}_generate_messages_py 类似于 ${PROJECT_NAME}_generate_messages_cpp,这个宏用于指定生成与消息相关的Python代码的路径。当你的ROS软件包包含使用Python编写的节点或服务时,可能会用到这个宏。

  3. ${PROJECT_NAME}_EXPORTED_TARGETS 这个宏用于导出所有与软件包相关的目标,包括消息生成任务。通常,在调用 catkin_package(...) 时,EXPORTED_TARGETS 部分会包含 ${PROJECT_NAME}_EXPORTED_TARGETS,以确保其他软件包能够正确地依赖你的软件包,并包括所有必要的目标。

    cmakeCopy codecatkin_package(...INCLUDE_DIRS includeLIBRARIES ${PROJECT_NAME}_libraryCATKIN_DEPENDS roscpp std_msgs message_runtimeDEPENDS system_libEXPORTED_TARGETS ${PROJECT_NAME}_EXPORTED_TARGETS
    )
    

请注意,具体的宏可能会受到ROS版本、Catkin工具链版本和软件包的配置选项的影响。上述宏的名称中的 ${PROJECT_NAME} 部分会根据你的软件包的名称而变化。

3.4 编译成功后,使用如下命令依次启动发布者和订阅者。

1. 启动ros master
roscore
2. 启动发布者
rosrun topic_hello_world topic_hello_world_user_msg_pub
3. 启动订阅者
rosrun topic_hello_world topic_hello_world_user_msg_sub

结果如下:

在这里插入图片描述

目前为止,Topic Hello World 的自定义msg已经成功了。

四、实现发布者与订阅者(Python版)

4.1 源码

topic_hello_world 包路径下的 scripts 目录中,创建 user_msg_pub.py 以实现发布者,编辑内容如下:

#! /usr/bin pythonimport rospy
from topic_hello_world.msg import RobotPosedef main():rospy.init_node("user_msg_pub")pub = rospy.Publisher("/robot_pose", RobotPose, queue_size=10)msg = RobotPose()msg.id = "vbot"msg.x = 52.1msg.y = 12.6msg.angle = 180.0while not rospy.is_shutdown():pub.publish(msg)rospy.loginfo("Pub robot: {}, pose({}, {}, {})".format(msg.id, msg.x, msg.y, msg.angle))rospy.sleep(1)if __name__ == "__main__":main()

scrips中创建 user_msg_sub.py 以实现订阅者,编辑内容如下:

#! /usr/bin pythonimport rospy
from topic_hello_world.msg import RobotPosedef robotPoseCallback(msg):rospy.loginfo("Sub robot: {}, pose({}, {}, {})".format(msg.id, msg.x, msg.y, msg.angle))def main():rospy.init_node("user_msg_sub")rospy.Subscriber("/robot_pose", RobotPose, robotPoseCallback, queue_size=10)rospy.spin()if __name__ == "__main__":main()

修改 CMakeLists.txt ,只需添加如下内容:

catkin_install_python(PROGRAMSscripts/user_msg_pub.pyscripts/user_msg_sub.pyDESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)

4.2 编译运行

进入工作空间执行 catkin_make 命令编译工程,编译成功后,使用如下命令依次启动发布者和订阅者。

1. 启动ros master(如果已启动,无需再启动)
roscore
2. 启动发布者
rosrun topic_hello_world user_msg_pub.py
3. 启动订阅者
rosrun topic_hello_world user_msg_sub.py

结果如下:

在这里插入图片描述

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

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

相关文章

002 OpenCV dft 傅里叶变换

目录 一、傅里叶变换 1.1 傅里叶变换概念 1.2 opencv中傅里叶变换 二、实验代码 一、环境 本文使用环境为&#xff1a; Windows10Python 3.9.17opencv-python 4.8.0.74 二、傅里叶变换 2.1 傅里叶变换概念 傅里叶变换&#xff08;Fourier Transform&#xff09;是一种…

Java怎么对复杂的数据类型排序和比大小

目录 一.对复杂的数据类型比大小 Comparable接口 compareTo方法 二.对复杂数据类型排序 三.总结 一.对复杂的数据类型比大小 假如我们现在有个学生类&#xff0c;并且我们实例化出了俩个学生对象&#xff0c;他们各自有各自的名字和年龄属性&#xff0c;我们如何对他们进…

【C语言】深入解开指针(三)

&#x1f308;write in front :&#x1f50d;个人主页 &#xff1a; 啊森要自信的主页 真正相信奇迹的家伙&#xff0c;本身和奇迹一样了不起啊&#xff01; 欢迎大家关注&#x1f50d;点赞&#x1f44d;收藏⭐️留言&#x1f4dd;>希望看完我的文章对你有小小的帮助&#x…

springboot项目的可执行jar以后台本地服务的方式运行在Windows机器上

文章目录 用到的工具先上一个效果图准备可执行文件注册及启动服务 前段时间遇到一个项目&#xff0c;需要我们提供一个驱动控件&#xff0c;可以以后台服务的方式运行在Windows机器上。开始寻找各种解决办法。 最后发现一个不错的解决方式。分享给大家一下。 用到的工具 链接&…

验证k8s中HPA功能及测试

部署 使用yaml部署服务 apiVersion: apps/v1 kind: Deployment metadata:name: php-apachenamespace: tools spec:replicas: 1selector:matchLabels:app: php-apachetemplate:metadata:labels:app: php-apachespec:containers:- name: php-apacheimage: registry.cn-beijing.…

基于JavaWeb+SpringBoot+Vue电子商城微信小程序系统的设计和实现

基于JavaWebSpringBootVue电子商城微信小程序系统的设计和实现 源码获取入口前言系统设计功能截图Lun文目录订阅经典源码专栏Java项目精品实战案例《500套》 源码获取 源码获取入口 前言 身处互联网时代&#xff0c;互联网无形中影响着人们的吃穿住行&#xff0c;人们享受着不…

基于SSM+Vue的校园共享单车管理系统

基于SSMVue的校园共享单车管理系统的设计与实现~ 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;SpringMyBatisSpringMVC工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统展示 主页 登录界面 管理员界面 用户界面 摘要 随着城市交通的不断发展和人们出…

asp.net core mvc之 RAZOR共享指令和标签助手 TagHelpers

一、RAZOR共享指令 RAZOR共享指令&#xff1a;在视图中导入命名空间&#xff0c;执行依赖注入。 RAZOR共享指令是写在 Views目录下的 _ViewImports.cshtml 文件 支持指令如下&#xff1a; addTagHelper 增加标签助手 removeTagHelper 移除标签助手 tagHelperPrefix 标签助手…

【flink理论】动态表:关系查询处理流的思路:连续查询、状态维护;表转换为流需要编码编码

文章目录 一. 使用关系查询处理流的讨论二. 动态表 & 连续查询(Continuous Query)三. 在流上定义表1. 连续查询2. 查询限制2.1. 维护状态2.2. 计算更新 四. 表到流的转换1. Append-only 流2. Retract 流3. Upsert 流 本文主要讨论了&#xff1a; 讨论通过关系查询处理无界流…

Django+vue前后端分离实战--vue后台管理系统--vue环境安装项目创建

Djangovue前后端分离实战--vue后台管理系统 安装nodejsvue clivue-cli创建项目 安装nodejsvue cli 1、下载nodejs并安装 https://nodejs.org/dist/v20.9.0/node-v20.9.0-x64.msi 2、修改npm 默认仓库地址&#xff0c;要修改成taobao的镜像npm 仓库地址 cmd下命令&#xff1a…

系列八、JVM的内存结构【方法区】

一、概述 方法区是一个供各线程共享的运行时内存区域。它存储了每一个类的结构信息&#xff0c;例如运行时常量池&#xff08;Runtime Constant Pool&#xff09;、字段和方法数据、构造函数和普通方法的字节码内容。上面讲的是规范&#xff0c;在不同的虚拟机里面实现是不一样…

74基于matlab的PSO-ELM的多输入,单输出结果预测,输出训练集和测试机预测结果及误差。

基于matlab的PSO-ELM的多输入&#xff0c;单输出结果预测&#xff0c;输出训练集和测试机预测结果及误差&#xff0c;适应度值。数据可更换自己的&#xff0c;程序已调通&#xff0c;可直接运行。 74matlabPSO-ELM多输入单输出 (xiaohongshu.com)

微信小程序:tabbar、事件绑定、数据绑定、模块化、模板语法、尺寸单位

目录 1. tabbar 1.1 什么是tabbar 1.2 配置tabbar 2. 事件绑定 2.1 准备表单 2.2 事件绑定 2.3 冒泡事件及非冒泡事件 3. 数据绑定 3.1 官方文档 4. 关于模块化 5. 模板语法 6. 尺寸单位 1. tabbar 1.1 什么是tabbar 下图中标记出来的部分即为tabbar&#xff1a…

Uniapp导出的iOS应用上架详解

目录 Uniapp导出的iOS应用上架详解 摘要 引言 苹果审核标准 苹果调试 注意事项和建议 总结 摘要 本文将探讨Uniapp导出的iOS应用能否成功上架的问题。我们将从苹果审核标准、性能影响、调试流程等多个方面进行深入分析&#xff0c;以及向开发者提供相关注意事项和建议。…

【论文阅读】(VAE-GAN)Autoencoding beyond pixels using a learned similarity metric

论文地址;[1512.09300] Autoencoding beyond pixels using a learned similarity metric (arxiv.org) / 一、Introduction 主要讲了深度学习中生成模型存在的问题&#xff0c;即常用的相似度度量方式&#xff08;使用元素误差度量&#xff09;对于学习良好的生成模型存在一定…

基于JavaWeb+SSM+购物系统微信小程序的设计和实现

基于JavaWebSSM购物系统微信小程序的设计和实现 源码获取入口前言主要技术系统设计功能截图Lun文目录订阅经典源码专栏Java项目精品实战案例《500套》 源码获取 源码获取入口 前言 第一章 绪 论 1.1选题背景 互联网是人类的基本需求&#xff0c;特别是在现代社会&#xff0c;…

制造业工厂的MES系统数据采集功能概述

一、MES系统与数据采集 MES系统是专门针对制造业工厂的信息化管理系统&#xff0c;旨在提高生产效率、降低成本、优化资源配置。数据采集作为MES系统的重要功能之一&#xff0c;能够实时获取生产现场的数据信息&#xff0c;为生产管理提供可靠的决策依据。 二、MES数据采集功能…

LLM(四)| Chinese-LLaMA-Alpaca:包含中文 LLaMA 模型和经过指令微调的 Alpaca 大型模型

论文题目&#xff1a;《EFFICIENT AND EFFECTIVE TEXT ENCODING FOR CHINESE LL AMA AND ALPACA》 ​论文地址&#xff1a;https://arxiv.org/pdf/2304.08177v1.pdf Github地址&#xff1a;https://github.com/ymcui/Chinese-LLaMA-Alpaca 一、项目介绍 通过在原有的LLaMA词…

基于ssm+vue交通事故档案系统

摘要 摘要是对文章、论文或其他文本的主要观点、结论和关键信息的简洁概括。由于你没有提供具体的文章或主题&#xff0c;我将为你创建一个通用的摘要。 本文介绍了一种基于SSM&#xff08;Spring Spring MVC MyBatis&#xff09;和Vue.js的交通事故档案管理系统的设计与实现…

NewStarCTF2023 Reverse方向Week3 ez_chal WP

分析 题目&#xff1a;ez_chal 一个XTEA加密&#xff0c; V6是key&#xff0c;v5是输入&#xff0c;然后v7就是密文。 看了v6&#xff0c;要用动调。 ELF文件用ida的远程调试。 然后在kali上输入长度为32的flag 全部转换成dd 再提取密文。 EXP #include <stdio.h>…