ROS 话题订阅模型之自定义消息类型 C++实现

news2024/10/7 6:45:02

ROS 话题订阅模型之自定义消息类型

1.自定义消息类型好处

ROS提供了许多标准的消息类型,如 std_msgs/Stringsensor_msgs/Image 等,涵盖了很多常见的数据类型和传感器数据。但是,在实际的开发中,我们经常会遇到需要传输的数据类型是标准消息类型中没有的,或者我们希望定义自己的数据结构以适应特定的应用场景。

因此,ROS允许用户定义自己的消息类型,这样用户可以更灵活地描述和传输数据。一些常见的情况包括:

  1. 特定的传感器数据:例如,你可能有一种特殊类型的传感器,它输出的数据类型在标准消息中没有涵盖。
  2. 自定义控制命令:你可能需要向机器人或设备发送一些自定义的控制命令,以便执行特定的动作或行为。
  3. 自定义数据结构:你可能需要在ROS系统中传输一些复杂的数据结构,例如地图、路径规划数据等。

自定义消息使得ROS更加灵活,能够满足各种各样的应用需求。通过定义自己的消息类型,用户可以更好地组织和传输数据,从而更容易地开发复杂的ROS应用。

2. 使用自定义消息类型

以发送模拟相机数据自定义类型数据为例:

2.1 定义msg 文件

在功能包下新建msg目录,添加Image.msg 文件,用来模拟相机数据

添加以下内容:

uint16 frame_id  # 图像帧的ID  
uint16 width     # 图像的宽度  
uint16 height    # 图像的高度  
int64 timestamp  # 图像的时间戳,通常以纳秒为单位

2.2 编辑配置文件

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

  <build_depend>message_generation</build_depend>
  <exec_depend>message_runtime</exec_depend>

CMakeLists.txt编辑 msg 相关配置

find_package(catkin REQUIRED COMPONENTS
  roscpp
  std_msgs
  message_generation
)
## 配置 msg 源文件
add_message_files(
  FILES
  Image.msg
)
# 生成消息时依赖于 std_msgs
generate_messages(
  DEPENDENCIES
  std_msgs
)
#执行时依赖
catkin_package(
  CATKIN_DEPENDS roscpp rospy std_msgs message_runtime
)

2.3 编译

使用编译命令之后,在 工程目录下的 devel/include/包名 会生成对应的C++头文件

后续编写代码要引用这些头文件

3.编写简单用例 C++ 传输模拟相机数据

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

{
    "configurations": [
        {
            "browse": {
                "databaseFilename": "${default}",
                "limitSymbolsToIncludedHeaders": false
            },
            "includePath": [
                "/opt/ros/melodic/include/**",
                "/usr/include/**",
                "/opt/ros/melodic/include",
                "/home/marxist/userdata/catkin_ws/devel/include/*"

            ],
            "name": "ROS",
            "intelliSenseMode": "gcc-x64",
            "compilerPath": "/usr/bin/gcc",
            "cStandard": "gnu17",
            "cppStandard": "c++17"
        },
        {
            "name": "ros_inc",
            "includePath": [
                "${workspaceFolder}/**"
            ],
            "defines": [],
            "compilerPath": "/usr/bin/gcc",
            "cStandard": "c11",
            "cppStandard": "gnu++14",
            "intelliSenseMode": "linux-gcc-x64"
        }
    ],
    "version": 4
}

3.1 发布模拟相机数据

#include "ros/ros.h"
#include "image_node/Image.h"

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

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

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

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

    //4.组织被发布的消息,编写发布逻辑并发布消息
   image_node::Image image_data;
 
    int start_id =0;
    image_data.height=1080;
    image_data.width=1920;

    ros::Rate r(1);
    while (ros::ok())
    {

  // 获取当前时间  
    ros::Time current_time = ros::Time::now();  
// 将当前时间转换为int64纳秒时间戳  
     image_data.timestamp = current_time.toNSec();  
        pub.publish(image_data);
         // 打印消息字段  

        ROS_INFO("Image frame ID: %d, Width: %d, Height: %d, Timestamp: %ld",image_data.frame_id,image_data.width,image_data.height,image_data.timestamp);
        ros::spinOnce();
    }
    return 0;
}

3.2 接受模拟相机数据



#include "ros/ros.h"
#include "image_node/Image.h"

void doGetData(const image_node::Image::ConstPtr& image_data){
  ROS_INFO("Image frame ID: %d, Width: %d, Height: %d, Timestamp: %ld",image_data->frame_id,image_data->width,image_data->height,image_data->timestamp);
}
int main(int argc, char *argv[])
{   
    setlocale(LC_ALL,"");
    //1.初始化 ROS 节点
    ros::init(argc,argv,"get_image");
    //2.创建 ROS 句柄
    ros::NodeHandle nh;
    //3.创建订阅对象
    ros::Subscriber sub = nh.subscribe<image_node::Image>("image_info",10,doGetData);
    
    //4.回调函数中处理 person

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

3.3 配置CmakeLists.txt

add_executable(
  image_pub  src/Image_pub.cpp)

add_dependencies(image_pub ${PROJECT_NAME}_generate_messages_cpp)

target_link_libraries(image_pub
  ${catkin_LIBRARIES}
)

add_executable(
  image_sub  src/Image_sub.cpp)

add_dependencies(image_sub ${PROJECT_NAME}_generate_messages_cpp)

target_link_libraries(image_sub
  ${catkin_LIBRARIES}
)

4. 效果图

在这里插入图片描述

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

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

相关文章

云计算中的过度授权:安全隐患与应对策略

云计算凭借其弹性、可扩展等优势&#xff0c;已经成为诸多企业组织拓展业务的重要基础设施之一。然而&#xff0c;与传统IT架构相比&#xff0c;云计算环境的安全管理也面临着新的挑战。过度授权 (Overprivileging) 便是云安全领域亟待解决的主要问题之一&#xff0c;本文将带领…

CPPTest实例分析(C++ Test)

1 概述 CppTest是一个可移植、功能强大但简单的单元测试框架&#xff0c;用于处理C中的自动化测试。重点在于可用性和可扩展性。支持多种输出格式&#xff0c;并且可以轻松添加新的输出格式。 CppTest下载地址&#xff1a;下载地址1  下载地址2 下面结合实例分析下CppTest如…

【Linux】解决ubuntu20.04版本插入无线网卡没有wifi显示【无线网卡Realtek 8811cu】

ubuntu为Realtek 8811cu安装驱动&#xff0c;解决wifi连接问题 1、确认无线网卡的型号-Realtek 8810cu2、下载并配置驱动 一句话总结&#xff1a;先确定网卡的型号&#xff0c;然后根据网卡的型号区寻找对应的驱动下载&#xff0c;下载完成之后在ubuntu系统中进行编译&#xff…

【STM32+HAL+Proteus】系列学习教程4---GPIO输入模式(独立按键)

实现目标 1、掌握GPIO 输入模式控制 2、学会STM32CubeMX配置GPIO的输入模式 3、具体目标&#xff1a;1、按键K1按下&#xff0c;LED1点亮&#xff1b;2、按键K2按下&#xff0c;LED1熄灭&#xff1b;2、按键K3按下&#xff0c;LED2状态取反&#xff1b; 一、STM32 GPIO 输入…

C语言 字符类型

下面 我们来说字符类型 我们来看这个 保险单 金额 和 总额 都可以用数字类型 而性别则需要字符型 字符数据的存储 – ASCI码 字符类型 char 就是专为存储字符(如字母&#xff0c;标点和数字)而设计的类型。 使用单引号包含单个字符或转义字符去表示一个 char 类型的常量。 …

mac电脑搭建vue环境(上篇)

第一步&#xff1a;mac电脑要有homebrew&#xff0c;如何安装homebrew 点击下方 MAC安装homebrew-CSDN博客 第二步&#xff1a;homebrew安装node.js 第三步&#xff1a;安装npm 第四步&#xff1a;安装webpack 第五步&#xff1a;安装vue脚手架 第六步&#xff1a;可以在…

解决双击PDF文件出现打印的问题【Adobe DC】

问题描述 电脑安装Adobe Acrobat DC之后&#xff0c;双击PDF文件就会出现打印&#xff0c;而无法直接打开。 右键PDF文件就会发现&#xff0c;第一栏出现的不是用Adobe打开&#xff0c;而是打印。 重装软件多次仍然无法解决。 原因 右键菜单被改写了。双击其实是执行右键菜…

idea上传项目到gitee(码云)

1、打开码云&#xff0c;新建仓库 2、创建 3、这就是创建成功的页面 4、复制仓库地址&#xff0c;后面需要用到 2、打开我们的项目&#xff1a;例如我现在的项目 1、idea创建git仓库 2、选择我们项目文件夹的目录 3、查看文件是否变色&#xff0c;变色表示成功了 4、添加到缓…

Amazon云计算AWS之[2]弹性计算云EC2

文章目录 说明EC2基本架构Amazon机器映象&#xff08;AMI&#xff09;实例&#xff08;Instance&#xff09;弹性块存储&#xff08;EBS&#xff09; EC2关键技术地理区域和可用区域EC2通信机制弹性负载均衡监控服务自动缩放服务管理控制台 EC2安全及容错机制EC2弹性IP地址 说明…

网盘——查看文件

本文主要讲解文件操作过程中&#xff0c;查看文件如何实现&#xff0c;实现步骤如下&#xff1a; 1、实现步骤&#xff1a; A、首先客户端发送查看请求&#xff08;包含目录信息&#xff09; B、服务器将文件名字还有文件的类型发送给客户端&#xff08;只发送文件的名字&am…

FebHost:科技企业如何规划并注册.AI域名?

为确保企业使用.AI域名的方式准确反映其对人工智能技术的关注&#xff0c;企业应考虑以下步骤&#xff1a; 了解法律和合规要求&#xff1a; 第一步是了解与 .AI 域名相关的独特法律和合规要求。由于.AI域名源于安圭拉&#xff0c;企业必须遵守安圭拉的限制和法律规定。这包括…

简单谈谈URL过滤在网络安全中的作用

用户花在网络上的时间越来越多&#xff0c;浏览他们最喜欢的网站&#xff0c;点击电子邮件链接&#xff0c;或利用各种基于网络的 SaaS 应用程序供个人和企业使用。虽然这种不受约束的网络活动对提高企业生产力非常有用&#xff0c;但也会使组织面临一系列安全和业务风险&#…

学习Rust第14天:HashMaps

今天我们来看看Rust中的hashmaps&#xff0c;在 std::collections crate中可用&#xff0c;是存储键值对的有效数据结构。本文介绍了创建、插入、访问、更新和迭代散列表等基本操作。通过一个计算单词出现次数的实际例子&#xff0c;我们展示了它们在现实世界中的实用性。Hashm…

笔记本电脑耗电和发热比较厉害怎么处理

工作中会遇到有同事反馈笔记本电脑耗电和发热比较厉害&#xff0c;主要检查以下几个地方 1、CPU频率 很多人觉得是cpu使用率高就代表电脑跑得快&#xff0c;发热量就大&#xff0c;其实不是的&#xff0c;主要是看的cpu频率&#xff0c;频率越高&#xff0c;电脑发热量越大。如…

分类预测 | Matlab实现CNN-GRU-SAM-Attention卷积门控循环单元融合空间注意力机制的数据分类预测

分类预测 | Matlab实现CNN-GRU-SAM-Attention卷积门控循环单元融合空间注意力机制的数据分类预测 目录 分类预测 | Matlab实现CNN-GRU-SAM-Attention卷积门控循环单元融合空间注意力机制的数据分类预测分类效果基本描述程序设计参考资料 分类效果 基本描述 1.Matlab实现CNN-GRU…

关于Java的三个小题目(很容易错!)

第一题 char运算后的数据类型 最后输出的是什么类型&#xff1f; 答案&#xff1a;int char与byte的联系和区别 char是无符号型的&#xff0c;能够表示一个整数&#xff0c;不能表示负数&#xff08;0~65535&#xff09;&#xff1b;而byte是有符号型的&#xff0c;能够表示…

AI视频改字个性化祝福豪车装X系统uniapp前端开源源码下载

装X系统源码简介 创意无限&#xff01;AI视频改字祝福&#xff0c;豪车装X系统源码开源&#xff0c;打造个性化祝福视频不再难&#xff01; 想要为你的朋友或家人送上一份特别的祝福&#xff0c;让他们感受到你的真诚与关怀吗&#xff1f;现在&#xff0c; 通过开源的AI视频…

fnm:Rust开发的高效Node版本管理工具

简介 fnm 是一个基于 Rust 开发的 Node 版本管理工具&#xff0c;它的目标是提供一个快速、简单且可靠的方式来管理 Node.js 的不同版本。同时&#xff0c;它是跨平台的&#xff0c;支持 macOS、Linux、Windows。&#x1f680; Fast and simple Node.js version manager, buil…

MySQL创建数据库与表

要求&#xff1a; 1.在本机安装数据库 2.创建一个数据库db_classes 3.创建一行表db_hero 4.将四大名著中的常见人物插入这个英雄表 目录 要求&#xff1a; 过程&#xff1a; 结果&#xff1a; 命令总结&#xff1a; 过程&#xff1a; 1.安装数据库 http://t.csdnimg…

android openGL ES详解

1、渲染线程与主线程的通信 两个线程之间的通信可以用如下方法: 在主线程中的 GLSurfaceView 实例可以调用 queueEvent( &#xff09;方法传递一个 Runnable 给后台渲染线程&#xff0c;渲染线程可以调用 Activity 的 runOnUIThread()来传递事件 (event) 给主线程。 2、顶点…