详细介绍如何在ROS 中使用自定义 msg 消息

本文介绍如何在ROS中自定义Msg消息格式,包括创建自定义消息包、编写Publisher和Subscriber程序的过程。通过实例演示了如何定义包含员工姓名和年龄的消息,并实现了消息的发布与订阅。

首先我们对Ros中的msg 消息做以简单的回顾:

          msg 消息是 ROS topic 通讯时,节点之间进行传递的内容。msg 消息描述的是业务之间传递数据,也可以理解为业务之间数据的抽象化。

常见 Msg 消息:

  • std 消息:std 消息是属于基本数据类型的消息。和 Python 类似,描述的是数字、字符串、布尔等类型。
  • geometry 消息:描述的是空间相关数据。
  • sensor 消息:描述的是传感器相关消息。

 下面我们通过一个例子进行msg消息的深入理解:

如果我们现在有两个节点,一个节点是 Publisher,另外一个节点是 Subscriber。Publisher 发布的消息是员工相关数据,其中包含了员工的姓名和年龄。需要编写程序实现这两个节点,然后模拟数据的发布和订阅。

字段名字段类型字段描述
namestring员工姓名
ageint16员工年龄

这时就需要我们自己定义消息格式,在自定义的消息格式中,需要包含 name 和 age。通常在编程语言中,我们是要去确定消息字段中的类型。例如 Python 中表达数据类型是这样的。

name = ''
age = 11

敲黑板啦!!!在自定义 msg 消息时,需要把 Python的类型修改成对应的 msg 类型,详细对应关系如下:

msg类型C++对应类型Python对应类型
booluint8_tbool
int8int8_tint
int16int16_tint
int32int32_tint
int64int64_tint, long
uint8uint8_tint
uint16uint16_tint
uint32uint32_tint
uint64uint64_tint, long
float32floatfloat
float64floatfloat
stringstd:stringstr, bytes
timeros:Timerospy.Time
durationros::Durationrospy.Duration

下面我们就进入实操环节,开始动手自定义一个msg消息

  在Ros中,当没有现成的消息类型来描述要传递的消息时,我们会自定义消息。通常会新建一个Package去自定义消息,这个Package一般不去写任何的业务逻辑,只是用来声明自定义的消息类型,可以只定义一种或多种消息类型,根据业务需求来定。

首先初始化一个工作空间:

mkdir -p kk
cd ~/kk
mkdir -p ws
cd ~/kk/ws
mkdir -p src
# 对工作空间进行编译
catkin_make

1.创建package

package取名也是有讲究的,一般为:  业务名_msgs,比如std_msg、gps_msgs。因为是发送员工的信息,我们取包名为staff_msgs。

cd ~/kk/ws/src
catkin_create_pkg staff_msgs roscpp rospy rosmsg
mkdir /home/kk/ws/src/staff_msgs/scripts
cd ~/kk/ws/src/staff_msgs
mkdir scripts

2.创建msg 目录

在package包下新建一个msg文件夹

mkdir msg
cd ~/kk/ws/src/staff_msgs/msg
touch staff.msg

3.创建msg文件

在msg文件夹下创建.msg文件。msg文件就是自定义消息文件,用来描述消息格式。这里我们创建staff.msg文件,内容如下:

string name
int64 age

这个自定义消息包包含两种数据形式: name和 age,neme的类型是string,age的类型是int64。

一般msg文件遵循一定的规范:每一行表示一种数据。前面是类型,后面是名称。

4.在staff_msgs/package.xml文件中添加配置。

<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>
  • build_depend:编译时依赖。
  • message_generation:消息自动生成,目的就是把我们编写的msg文件自动转为python文件。
  • exec_depend:执行时依赖。
  • message_runtime:把自定义的消息加载进来。

5.配置staff_msgs/CMakeLists.txt文件。

在find_package中添加message_generation依赖

find_package(
   ...
   message_generation
)

添加add_message_files,这里的staff.msg要和你创建的msg文件名称一致,且必须放在msg目录下:

add_message_files(
          FILES
          staff.msg
)

generate_messages配置:

generate_messages(
    DEPENDENCIES
    std_msgs
)

 修改 catkin_package:为 catkin编译提供了依赖 message_runtime:

catkin_package(
     ...message_runtime
)

 编译项目:

cd /~/kk/ws
catkin_make
source devel/setup.bash

命令校验,可以看到我们刚才定义的消息:

rosmsg show staff_msgs/staff

 

devel 文件夹校验:

进入 /home/kyf/kk/ws/devel/lib/python2.7/dist-packages 目录下,查看是否生成和 package名称staff_msgs相同的目录,以及目录内是否生成对应的py文件。

 编写程序对自定义msg消息进行发布和订阅

1.编写publisher程序

在staff_msgs/scripts 目录下新建一个 sta_msg_publisher.py 文件,并赋予该文件可执行权限:

sudo chmod +x ~/kk/ws/src/staff_msgs/scripts/sta_msg_publisher.py 

(图片中stu_msg_publisher.py名称有误,有改文件名)

导入刚才自定义的消息类型,通过发布者把自定义的 staff 消息发布出去。

#! /usr/bin/env python
# coding: utf-8

import rospy
from staff_msgs.msg import staff

if __name__ == '__main__':
    # 创建 node
    node_name = "stu_publisher"
    rospy.init_node(node_name)

    # 创建 publisher
    topic_name = "/my_sta"
    publisher = rospy.Publisher(topic_name, staff, queue_size=1000)

    rate = rospy.Rate(2)
    index = 0
    while not rospy.is_shutdown():

        msg = staff()
        msg.name = 'staff{}'.format(index)
        msg.age = index
        # 通过 publisher 广播数据
        publisher.publish(msg)
        index += 1

        rate.sleep()

2.创建 stu_msg_subscriber.py 文件

在staff_msgs/scripts 目录下新建一个 sta_msg_subscriber.py 文件。并赋予该文件可执行权限:

sudo chmod +x ~/kk/ws/src/staff_msgs/scripts/sta_msg_subscriber.py

导入刚才自定义的消息类型,通过订阅者去接收自定义的 staff 消息。 注意 topic_name要和发布者的保持一致。

#! /usr/bin/env python
# coding: utf-8

import rospy
from staff_msgs.msg import staff


def topic_callback(msg):
    if not isinstance(msg, staff):
        return
    print msg.age
    print msg.name


if __name__ == '__main__':
    # 创建 node
    node_name = "stu_subscriber"
    rospy.init_node(node_name)

    # 创建 subscriber
    topic_name = "/my_sta"
    rospy.Subscriber(topic_name, staff, callback=topic_callback)

    # 阻塞
    rospy.spin()

3.调试

# 新开一个终端,启动 ROS Master
roscore
# 切换到工作空间目录下
cd ~/kk/ws
# 使用 catkin_make 编译项目
catkin_make
# source 开发环境 && 运行编译
source devel/setup.bash
rosrun staff_msgs sta_msg_publisher.py
#  新开一个终端, source 开发环境 && 运行编译
source devel/setup.bash
rosrun staff_msgs sta_msg_subscriber.py

程序运行后则在订阅窗口可以打印出发布的员工消息

至此 msg 自定义消息的创建和使用就可以说基本掌握了。


草帽专门将自己的源码上传以供大家参考学习,有需要的童鞋可以点击链接下载!!!

https://download.youkuaiyun.com/download/Yifancoder/85170251icon-default.png?t=M3C8https://download.youkuaiyun.com/download/Yifancoder/85170251

### 如何在ROS 2中使用自定义消息类型 为了在ROS 2项目中创建并使用自定义消息类型,需遵循特定的过程来配置`CMakeLists.txt`文件以及确保依赖项被正确声明。当包内含有两个位于名为“msg”的目录下的消息文件“MyMessage1.msg”和“MyMessage2.msg”,这些消息依赖于`std_msgs`和`sensor_msgs`,并且存在服务文件"MyService.srv"[^1]。 对于上述情况,在`CMakeLists.txt`里应当加入必要的指令以处理消息和服务文件,并指定哪些可执行文件会利用到这些自定义消息或服务。如果有一个叫作`message_program`的程序需要用到前述提到的消息和服务,则应该适当地设置该程序的相关构建规则;而对于另一个不涉及本地消息/服务使用的程序`does_not_use_local_messages_program`来说,则不需要对其进行额外针对新消息类型的特殊设定。 另外,为了让ROS 2能够识别新的消息类型,还需要更新`package.xml`中的依赖关系,像这样添加一条语句: ```xml <build_depend>rosidl_tutorials_msgs</build_depend> ``` 这表明当前包在编译期间需要访问由`rosidl_tutorials_msgs`提供的接口描述[^3]。 最后值得注意的是,在编写代码的过程中应保持良好的编程习惯,比如按照官方开发者指南的要求应用相应的编码风格指导方针,从而有助于维护整洁有序的源码结构[^2]。 #### 创建自定义消息的例子 假设要创建一个新的消息类型叫做`CustomMsg`,可以这样做: 1. 在工作空间内的某个包下建立一个名为`msg`的新文件夹; 2. 将想要定义的内容写入至这个路径下面的一个`.msg`结尾的文本文件之中,例如`CustomMsg.msg`: ``` string name int32 age ``` 3. 修改对应的`CMakeLists.txt`,增加如下几行用于指示系统去查找此位置的消息资源: ```cmake find_package(ament_cmake REQUIRED) find_package(builtin_interfaces REQUIRED) rosidl_generate_interfaces(${PROJECT_NAME} "msg/CustomMsg.msg" ) ``` 4. 同样地调整`package.xml`里的内容,使其包含对所需库的支持说明: ```xml <depend>builtin_interfaces</depend> <exec_dependency>rosidl_default_runtime</exec_dependency> ``` 完成以上步骤之后就可以正常发布订阅这种新型的数据格式了。
评论 10
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值