ROS学习第八节——话题通信自定义msg

news2024/11/24 7:40:32

1.介绍

在 ROS 通信协议中,数据载体是一个较为重要组成部分,ROS 中通过 std_msgs 封装了一些原生的数据类型,比如:String、Int32、Int64、Char、Bool、Empty.... 但是,这些数据一般只包含一个 data 字段,结构的单一意味着功能上的局限性,当传输一些复杂的数据,比如: 激光雷达的信息... std_msgs 由于描述性较差而显得力不从心,这种场景下可以使用自定义的消息类型

msgs只是简单的文本文件,每行具有字段类型和字段名称,可以使用的字段类型有:

  • int8, int16, int32, int64 (或者无符号类型: uint*)

  • float32, float64

  • string

  • time, duration

  • other msg files

  • variable-length array[] and fixed-length array[C]

ROS中还有一种特殊类型:Header,标头包含时间戳和ROS中常用的坐标帧信息。会经常看到msg文件的第一行具有Header标头

2C++实现

2.1相关文件配置

创建文件夹以及文件

输入以下代码

string name
uint16 age
float64 height

 package.xml中添加编译依赖与执行依赖

  <build_depend>message_generation</build_depend>
  <exec_depend>message_runtime</exec_depend>
  <!-- 
  exce_depend 以前对应的是 run_depend 现在非法
  -->

 CMakeLists.txt编辑 msg 相关配置

find_package(catkin REQUIRED COMPONENTS
  roscpp
  rospy
  std_msgs
  message_generation
)
# 需要加入 message_generation,必须有 std_msgs

## 配置 msg 源文件
add_message_files(
  FILES
  Person.msg
)

# 生成消息时依赖于 std_msgs
generate_messages(
  DEPENDENCIES
  std_msgs
)

#执行时依赖
catkin_package(
#  INCLUDE_DIRS include
#  LIBRARIES demo02_talker_listener
  CATKIN_DEPENDS roscpp rospy std_msgs message_runtime
#  DEPENDS system_lib
)

 编译一下就会出现中间文件

C++ 需要调用的中间文件(.../工作空间/devel/include/包名/xxx.h)

Python 需要调用的中间文件(.../工作空间/devel/lib/python3/dist-packages/包名/msg)

后续调用相关 msg 时,是从这些中间文件调用的

为了方便代码提示以及避免误抛异常,需要先配置 vscode,将前面生成的 head 文件路径配置进 c_cpp_properties.json 的 includepath属性

右键该文件夹在终端中打开

 输入指令 pwd 查看路径

 复制路径到该文件,并把最后改成**,如图

"/home/xiaoming/demo0/devel/**"

{
  "configurations": [
    {
      "browse": {
        "databaseFilename": "${default}",
        "limitSymbolsToIncludedHeaders": false
      },
      "includePath": [
        "/opt/ros/melodic/include/**",
        "/home/xiaoming/demo0/src/helloworld/include/**",
        "/usr/include/**",
        "/home/xiaoming/demo0/devel/**"
      ],
      "name": "ROS",
      "intelliSenseMode": "gcc-x64",
      "compilerPath": "/usr/bin/gcc",
      "cStandard": "gnu11",
      "cppStandard": "c++14"
    }
  ],
  "version": 4
}

2.2发布者实现

新建代码文件,如图

 编写以下代码

/*
    需求: 循环发布人的信息

*/

#include "ros/ros.h"
#include "pub_sub/Person.h"

int main(int argc, char *argv[])
{
    setlocale(LC_ALL,"");

    //1.初始化 ROS 节点
    ros::init(argc,argv,"talker_person");

    //2.创建 ROS 句柄
    ros::NodeHandle nh;

    //3.创建发布者对象
    ros::Publisher pub = nh.advertise<pub_sub::Person>("chatter_person",1000);

    //4.组织被发布的消息,编写发布逻辑并发布消息
    pub_sub::Person p;
    p.name = "sunwukong";
    p.age = 2000;
    p.height = 1.45;

    ros::Rate r(1);
    while (ros::ok())
    {
        pub.publish(p);
        p.age += 1;
        ROS_INFO("我叫:%s,今年%d岁,高%.2f米", p.name.c_str(), p.age, p.height);

        r.sleep();
        ros::spinOnce();
    }



    return 0;
}

编辑配置文件

这个地方不知道为什么,文件的替代名字不能使用跟文件明一样的demo03_pub_person,一使用就会报错,无奈只能改名

add_executable(person_talker src/demo03_pub_person.cpp)
add_dependencies(person_talker ${PROJECT_NAME}_generate_messages_cpp )
target_link_libraries(person_talker
  ${catkin_LIBRARIES}
)

打开终端,常规操作运行程序

 如果此时想要使用rostopic工具打印,需要先在终端 source ./devel/setup.bash 以下,再使用rostopic echo chatter_person

效果如下

 3.3订阅者实现

创建文件如图

 编写代码

/*
    需求: 订阅人的信息

*/

#include "ros/ros.h"
#include "demo02_talker_listener/Person.h"

void doPerson(const demo02_talker_listener::Person::ConstPtr& person_p){
    ROS_INFO("订阅的人信息:%s, %d, %.2f", person_p->name.c_str(), person_p->age, person_p->height);
}

int main(int argc, char *argv[])
{   
    setlocale(LC_ALL,"");

    //1.初始化 ROS 节点
    ros::init(argc,argv,"listener_person");
    //2.创建 ROS 句柄
    ros::NodeHandle nh;
    //3.创建订阅对象
    ros::Subscriber sub = nh.subscribe<demo02_talker_listener::Person>("chatter_person",10,doPerson);

    //4.回调函数中处理 person

    //5.ros::spin();
    ros::spin();    
    return 0;
}

修改配置文件

add_executable(person_listener src/demo04_sub_person.cpp)
add_dependencies(person_listener ${PROJECT_NAME}_generate_messages_cpp )
target_link_libraries(person_listener
  ${catkin_LIBRARIES}
)

开启终端运行程序

3.Python实现

3.1相关配置文件

右键该文件夹在终端中打开

 pwd

查看路径,并复制路径到图片所示文件中

 3.2Python实现发布端

新建代码文件

 编写以下代码

#! /usr/bin/env python
# -*- coding: UTF-8 -*-
"""
    发布方:
        循环发送消息

"""
import rospy
#此处form的是功能包.msg,我也不知道为啥
from pub_sub.msg import Person


if __name__ == "__main__":
    #1.初始化 ROS 节点
    rospy.init_node("talker_person_p")
    #2.创建发布者对象
    pub = rospy.Publisher("chatter_person",Person,queue_size=10)
    #3.组织消息
    p = Person()
    p.name = "葫芦娃"
    p.age = 18
    p.height = 0.75

    #4.编写消息发布逻辑
    rate = rospy.Rate(1)
    while not rospy.is_shutdown():
        pub.publish(p)  #发布消息
        rate.sleep()  #休眠
        rospy.loginfo("姓名:%s, 年龄:%d, 身高:%.2f",p.name, p.age, p.height)

给py文件添加可执行权限

修改配置文件

catkin_install_python(PROGRAMS
  scripts/demo01_pub_p.py
  scripts/demo02_sub_p.py
  scripts/demo03_pub_person_p.py
  DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)

 执行程序查看效果

 3.3Python实现订阅端

新建编程文件

 编写以下代码

#! /usr/bin/env python
# -*- coding: UTF-8 -*-
"""
    订阅方:
        订阅消息

"""
import rospy
from pub_sub.msg import Person

def doPerson(p):
    rospy.loginfo("接收到的人的信息:%s, %d, %.2f",p.name, p.age, p.height)


if __name__ == "__main__":
    #1.初始化节点
    rospy.init_node("listener_person_p")
    #2.创建订阅者对象
    sub = rospy.Subscriber("chatter_person",Person,doPerson,queue_size=10)
    rospy.spin() #4.循环

添加可执行权限

 修改配置文件

catkin_install_python(PROGRAMS
  scripts/demo01_pub_p.py
  scripts/demo02_sub_p.py
  scripts/demo03_pub_person_p.py
  scripts/demo04_sub_person_p.py

运行查看结果

https://mp.csdn.net/mp_download/manage/download/UpDetailed

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

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

相关文章

Java基础(九)多线程

我们之前学习的程序在没有跳转语句的情况下&#xff0c;都是由上至下沿着一条路径依次执行。现在想要设计一个程序&#xff0c;可以同时有多条执行路径同时执行。比如&#xff0c;一边游戏&#xff0c;一边qq聊天&#xff0c;一边听歌&#xff0c;怎么设计&#xff1f; 要解决…

每日一个小技巧:今天告诉你拍照识别文字的软件有哪些

在现代社会里&#xff0c;手机已经成为了人们生活中必不可少的工具。它的功能众多&#xff0c;比如通讯、上网、拍照以及导航等&#xff0c;为我们的生活带来了许多便利。除此之外&#xff0c;手机还能帮助我们解决一些实际的问题&#xff0c;例如&#xff0c;当你需要识别图片…

Spring Aop详解汇总

文章目录 近期想法什么是AOPSpringAOP与AspectjSpringAOP体系概述概念详解连接点- Jointpoint切入点- Pointcut通知- Advice切面- Aspect织入- Weaving 实现原理—动态代理JDK动态代理描述原理代码示例注意执行结果 优点缺点 CGLib动态代理描述原理代码示例注意执行结果 优点缺…

ChatGPT会凉吗?巴菲特、马斯克呼吁暂停

ChatGPT 迅速“风靡”全球&#xff0c;无疑成为了人工智能领域备受瞩目的“明星产品”&#xff0c;然而随着 ChatGPT 应用越来越广泛&#xff0c;陆续爆出被用于学术造假、制作黑客武器以及泄露用户敏感聊天信息等一系列负面新闻。至此&#xff0c;社会开始重新审视类似 ChatGP…

图像傅里叶变换以及频谱中心化

图像的空域滤波&#xff1a; I ∗ G I*G I∗G 矩阵 I I I与一个小矩阵 G G G进行卷积 图像的频域滤波&#xff1a; F − 1 [ F [ I ] H ] F^{-1}[F[I]\times H] F−1[F[I]H] 矩阵 I I I的傅里叶变换与同样大小的矩阵 H H H进行对应元素相乘&#xff0c;然后将结果通过逆傅里…

并查集解决图的连通性问题

并查集 1. 定义2.并查集3.模板代码4. 力扣例题4.1 剑指 Offer II 118. 多余的边4.2 力扣695. 岛屿的最大面积 1. 定义 在计算机科学中&#xff0c;并查集&#xff08;英文&#xff1a;Disjoint-set data structure&#xff0c;直译为不交集数据结构&#xff09;是一种数据结构&…

卷积神经网络轻量化教程之通道剪枝【附代码】

这两天自己手写了一个可以简单实现通道剪枝的代码&#xff0c;在这篇文章中也会对代码进行讲解&#xff0c;方便大家在自己代码中的使用。 如果还想学习YOLO系列的剪枝代码&#xff0c;可以参考我其他文章&#xff0c;下面的这些文章都是我根据通道剪枝的论文在YOLO上进行的实…

React框架----路由管理

文章目录 SPA路由路由基本使用路由组件与一般组件NavLink SPA single page application只有一个页面异步请求数据&#xff0c;局部更新页面本地局部切换页面&#xff08;不会向服务端加载整个页面&#xff09; 路由 地址栏路径与组件的对应关系切换路径&#xff0c;则切换组…

YOLOv5+单目跟踪(python)

YOLOv5单目跟踪&#xff08;python&#xff09; 1. 目标跟踪2. 测距模块2.1 设置测距模块2.2 添加测距 3. 主代码4. 实验效果 相关链接 1. YOLOv5单目测距&#xff08;python&#xff09; 2. YOLOv7单目测距&#xff08;python&#xff09; 3. YOLOv7单目跟踪&#xff08;pytho…

JDBC详解(一):JDBC概述

JDBC概述 前言一、数据的持久化1、概念2、应用 二、Java中的数据存储技术三、JDBC介绍四、JDBC体系结构五、JDBC程序编写步骤 前言 本博主将用CSDN记录软件开发求学之路上亲身所得与所学的心得与知识&#xff0c;有兴趣的小伙伴可以关注博主&#xff01;也许一个人独行&#…

全志 Orange Pi相关网站集

Orange Pi 系统安装的常识 看到有教程说android系统需要用win32diskimager才能成功烧写运行镜像名称与版本的对应关系 ubuntu版本号代号16.04Xenial Xerus&#xff08;好客的非洲地鼠&#xff09;18.04Bionio Beaver &#xff08;仿生海狸}20.04Focal Fossa &#xff08;类似…

DFIG控制10-b: 双馈发电机的转矩方程推导

DFIG控制10-b 双馈发电机的转矩方程推导 接上DFIG控制10&#xff1a; 双馈发电机的动态模型_Fantasy237的博客&#xff0c;DFIG的转矩方程和推导。 &#xff08;字数限制&#xff0c;只能放在新的一篇博文里了。。&#xff09; 转矩方程 定子αβ静止坐标系 从三相坐标系下…

Linux网络套接字(二)

学习任务&#xff1a; 继网络套接字&#xff08;一&#xff09;&#xff0c;继续学习套接字socket编程接口&#xff08;已经学习了socket和bind&#xff09;&#xff0c;实现TCP客户端/服务器(单连接版本, 多进程版本, 多线程版本&#xff0c;进程或线程池版本)&#xff0c;并且…

JavaScript(JS)-1.JS基础知识

1.JavaScript概念 (1)JavaScript是一门跨平台&#xff0c;面向对象的脚本语言&#xff0c;来控制网页行为的&#xff0c;它能使网页可交互 (2)W3C标准&#xff1a;网页主要由三部分组成 ①结构&#xff1a;HTML负责网页的基本结构&#xff08;页面元素和内容&#xff09;。 …

SPI协议——同步全双工串行通信方式

文章目录 前言一、简要介绍1、优点2、缺点 二、信号线和连接方式1、四根信号线2、连接方式2.1 多NSS形式2.2 菊花链形式 三、SPI配置1、时钟极性CPOL2、时钟相位CPHA3、四种模式4、数据大小5、其他配置参数 四、通信过程 前言 2023.4.22 阴 一、简要介绍 SPI&#xff1a;Seri…

什么是分组卷积、深度可分离卷积?附上深度可分离卷积代码

文章目录 分组卷积 Group Converlution1、由来和用途2、常规卷积和分组卷积的区别2.1、常规卷积&#xff1a;常规卷积的运算量&#xff1a; 2.2、分组卷积&#xff1a; 3、分组卷积的作用4、深度可分离卷积总结:先做分组卷积&#xff0c;再做1 x 1卷积深度可分离卷积代码 参考博…

【U-Net】训练自己的数据集

代码用的是b导的 整个训练流程也是根据b导的视频来的 源码地址&#xff1a;https://github.com/bubbliiiing/unet-pytorch 博客地址&#xff1a;https://blog.csdn.net/weixin_44791964/article/details/108866828 # 一、准备数据集 1、使用labelme软件标注数据&#xff0c;得…

深度学习 -- 什么是张量 pytorch中张量的几种创建方法

前言 在学习深度学习的过程中&#xff0c;遇到的第一个概念就是张量&#xff0c;张量在pytorch中的计算十分重要&#xff0c;所以本篇博客记录本人学习张量的过程&#xff0c;以及自己的理解。 张量是什么&#xff1f; 张量是一个多维数组&#xff0c;它是标量、向量、矩阵的…

SpringBoot的创建及配置文件

文章目录&#xff1a;一.Spring项目的创建&#xff08;1&#xff09;SpringBoot的含义 &#xff08;2&#xff09;SpringBoot的优点 &#xff08;3&#xff09;项目目录的运行和介绍 二.SpringBoot的配置文件 &#xff08;1&#xff09;配置文件的作用 &#xff08;2&#xff0…

E5--Aurora 8/10Bip核实现光纤接口通信2023-04-22

1.场景 使用两块开发板A和B&#xff0c;通过光纤接口将在A板上ROM中存储的图片数据转发到B板并显示在B板连接的显示屏上&#xff0c;实现光纤接口通信。 具体场景是&#xff0c;由于A735T片上资源有限&#xff0c;因此ROM IP存储了一张1024*600&#xff08;LVDS屏幕&#xff0…