[ROS](09)ROS通信 —— 话题(Topic)通信编程之msg(C++)(Python)

17 篇文章 12 订阅
本文详细介绍了ROS中的msg文件,包括其结构、类型和命令,如`rosmsg`用于查看和操作消息。通过实例展示了如何创建、配置和使用自定义msg,以及编写C++和Python程序进行话题通信。内容涵盖创建msg、配置CMakeLists.txt和package.xml、消息命令实操和发布者、订阅者的编程实现。
摘要由CSDN通过智能技术生成

  文章只是个人学习过程中学习笔记,主要参考ROS教程1 2 3


[ROS](01)创建ROS工作空间

[ROS](02)创建&编译ROS软件包Package

1、概述

  msg(消息)文件就是文本文件,用于描述ROS消息的字段。它们用于为不同编程语言编写的消息生成源代码。
  msg文件存放在软件包的msg目录下。

2、msg结构和类型

  msg4文件就是简单的文本文件,每行都有一个字段类型和字段名称。它的结构为:
    fieldtype + fieldname

2.1 类型

  可以使用的类型为:

  • int8, int16, int32, int64 (以及 uint*)
  • float32, float64
  • string
  • time, duration
  • 其他msg文件
  • variable-length array[] 和 fixed-length array[C]

2.2 举例

# 特殊的Header类型,它含有时间戳和ROS中广泛使用的坐标帧信息
# 在msg文件的第一行经常可以看到Header header。
std_msgs/Header header
uint8	is_true
uint32	height
uint32	width
string child_frame_id
time	stamp
geometry_msgs/PoseWithCovariance pose
geometry_msgs/TwistWithCovariance twist
uint8[]	data

3、msg命令rosmsg

rosmsg显示有关ROS消息类型的信息。

命令功能
rosmsg show显示消息的描述(详细信息)
rosmsg inforosmsg show的别名,功能一样
rosmsg list列出所有消息
rosmsg md5显示md5加密的消息
rosmsg package列出某个软件包(package)的消息
rosmsg packages列出包含消息的软件包(packages)

4、msg的用法

4.1 创建msg

  还是在原来创建的软件包 beginner_tutorials 中定义一个新的消息。

# 切换到软件包的目录路径
roscd beginner_tutorials
# 创建msg文件夹目录
mkdir msg
# 创建名为Num.msg的文件,并添加一个消息字段
echo "int64 num" > msg/Num.msg

4.2 配置CMakeLists.txt

  1. 为已经存在里面的find_package调用添加message_generation依赖项(),这样就能生成消息了。(添加 message_generation 依赖项,必须有 std_msgs 。)

find_package(catkin REQUIRED COMPONENTS
  roscpp
  rospy
  std_msgs
  message_generation
)

  2. 添加自定义的消息文件。将你msg文件夹中自定义的*.msg文件添加在这里。

add_message_files(
  FILES
  Num.msg
)

  3. 用于生成所有定义的message文件,需要添加本文件需要依赖的packages。其实就是告诉编译器,编译 *.msg 文件时,需要依赖的库或package。

generate_messages(
  DEPENDENCIES
  std_msgs
)

  4. 导出消息的运行时依赖关系。

catkin_package(
  ...
  CATKIN_DEPENDS message_runtime ...
  ...)

4.3 配置package.xml

  添加编译依赖与执行依赖。

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

Node :在构建时,其实只需要message_generation,而在运行时,我们只需要message_runtime

4.4 编译package

  已经创建了一些新消息,所以需要重新make一下软件包:

cd
cd catkin_ws
catkin_make

msg bulid
  msg目录中的任何.msg文件都将生成所有支持语言的代码。

  • C++消息的头文件将生成在~/catkin_ws/devel/include/beginner_tutorials/

msg 生成C++头文件的位置.png

  • python脚本将创建在~/catkin_ws/devel/lib/python2.7/dist-packages/beginner_tutorials/msg

msg 生成python头文件的位置.png

5、msg命令实操

5.1 rosmsg list

  rosmsg list 列出ROS中的所有消息(msg)。

5.2 rosmsg packages

  rosmsg packages [options] 列出包含消息的软件包。

# 列出包含消息的软件包,每行显示一个软件包名
rosmsg packages
# 在一行中列出包含消息的软件包
rosmsg packages -s 

5.3 rosmsg package

  rosmsg package [package-name] 列出某个软件包(package)的消息。

rosmsg package turtlesim

5.4 rosmsg show / rosmsg info

  rosmsg show [message type] 显示消息的详细信息。
rosmsg show message type.png

5.5 rosmsg md5

  rosmsg md5[message type] 显示md5加密的消息。如果编译的版本不匹配,这也会发出警告。

Node:md5 命令仅供专家用户使用。(??)

6、实操编程 – 话题通信发送自定义消息

  功能:基于话题通信,发布者以一定频率发布自定义消息并打印输出消息,订阅者订阅自定义消息并打印输出消息。
  实现
    1. 创建发布者(talker)节点,该节点不断广播自定义消息。
    2. 创建订阅者(listener)节点,该节点持续接收自定义消息。
    3. 创建自定义消息(Num.msg),(见4.1小节 创建msg
    4. 发布订阅话题chatter

Num.msg
Num.msg
talker
chatter
listener

6.1 编写程序(C++)

  在beginner_tutorials软件包的src目录下创建发布者和订阅者源文件:

roscd beginner_tutorials
cd src
touch talker.cpp listener.cpp

6.1.1 发布者程序(talker.cpp)

#include "ros/ros.h"
#include "beginner_tutorials/Num.h"  // 在 /devel/include 目录下

int main(int argc, char **argv)
{
    /* 防止中文乱码 */
    setlocale(LC_ALL,"");
    
    /* 初始化ROS节点 */
    ros::init(argc, argv, "talker");
    /* 为这个进程节点创建句柄 */
    ros::NodeHandle nh;
    /* 创建发布者对象 */
    ros::Publisher pub = nh.advertise<beginner_tutorials::Num>("chatter", 1000);
    /* 设定循环发布的频率为1Hz */
    ros::Rate loop_rate(1);
    /* 要发布的消息 */
    beginner_tutorials::Num msg;
    msg.num = 0;

    while(ros::ok())
    {
       ROS_INFO("当前num值为: %d",msg.num);
       
        /* 发布消息 */
        pub.publish(msg);

        ros::spinOnce();

        loop_rate.sleep();

        msg.num += 1;
    }

    return 0;

}

对上边的内容进行一下总结:

  • 初始化ROS系统
  • 向主节点宣告我们将要在chatter话题上发布beginner_tutorials/Num类型的消息
  • 以每秒1次的速率向chatter话题循环发布消息

6.1.2 订阅者程序(listener.cpp)

#include "ros/ros.h"
#include "beginner_tutorials/Num.h"  // 在 /devel/include 目录下

/* 回调函数,当有新消息到达chatter话题时就会调用 */
void chatterCallback(const beginner_tutorials::Num::ConstPtr& msg)
{
    ROS_INFO("已收到的Num的值: %d",msg->num);
}

int main(int argc, char **argv)
{
     /* 防止中文乱码 */
    setlocale(LC_ALL,"");
    
    /* 初始化ROS节点 */
    ros::init(argc, argv, "listener");
    /* 为这个进程节点创建句柄 */
    ros::NodeHandle nh;
    /* 创建订阅者对象 
     * 通过节点管理器订阅chatter话题。收到消息,调用回调函数chatterCallback。
     * 第2个参数是队列大小,>1000时,丢弃旧消息。
     */
    ros::Subscriber sub = nh.subscribe("chatter",1000, chatterCallback);

    /* 启动自循环 回调函数处理, 不占用太多CPU */
    ros::spin();

    return 0;
}

同样地,我们来总结一下:

  • 初始化ROS系统
  • 订阅chatter话题
  • 开始spin自循环,等待消息的到达
  • 当消息到达后,调用chatterCallback()函数

6.1.3 配置CMakeLists.txt

  只需将这几行添加到CMakeLists.txt文件的底部:

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

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

6.1.4 编译、运行

  编译后,在终端中执行过程如下所示。
话题(Topic)通信编程之msg(C++)

6.2 编写程序(python)

  在beginner_tutorials软件包的scripts目录下创建发布者和订阅者源文件:

roscd beginner_tutorials
cd scripts
touch talker.py listener.py
chmod +x talker.py listener.py

6.2.1 发布者程序(talker.py)

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

import rospy
from beginner_tutorials.msg import Num

def talker():
    # 初始化ROS节点
    rospy.init_node("talker",anonymous=True)
    # 创建发布者对象
    pub = rospy.Publisher('chatter', Num, queue_size=1000)

    
    # 创建一个Rate对象rate,1Hz
    rate = rospy.Rate(1)

    # 要发布的消息
    msg = Num()
    msg.num = 0

    # 循环
    while not rospy.is_shutdown():
        rospy.loginfo("当前num值为: %d",msg.num)
        pub.publish(msg)
        rate.sleep()
        msg.num += 1


if __name__ == '__main__':
    try:
        talker()
    except rospy.ROSInterruptException:
        pass

6.2.2 订阅者程序(listener.py)

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

import rospy
from beginner_tutorials.msg import Num


def callback(msg):
    rospy.loginfo("已收到的Num的值: %d",msg.num)

def listener():
    # 初始化ROS节点
    rospy.init_node("listener",anonymous=True)
    # 创建发布者对象
    pub = rospy.Subscriber('chatter', Num, callback, queue_size=1000)

    rospy.spin()

if __name__ == '__main__':
    listener()

6.2.3 配置CMakeLists.txt

# 安装python可执行脚本
catkin_install_python(PROGRAMS 
  scripts/turtle_publisher.py
  scripts/talker.py
  scripts/listener.py 
  DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
  )

6.1.4 编译、运行

  编译后,在终端中执行过程如下所示。
话题(Topic)通信编程之msg(Python)


  1. ROS.otg. ROS教程[EB/OL]. 2020-12-22[2022-7-5].
    http://wiki.ros.org/cn/ROS/Tutorials. ↩︎

  2. .ROS.org. 编写简单的发布者和订阅者(C++)[EB/OL]. 2020-12-25[2022-07-30]. https://wiki.ros.org/cn/ROS/Tutorials/WritingPublisherSubscriber%28c%2B%2B%29. ↩︎

  3. .ROS.org. 编写简单的发布者和订阅者(Python)[EB/OL]. 2020-12-25[2022-07-30]. https://wiki.ros.org/cn/ROS/Tutorials/WritingPublisherSubscriber%28python%29. ↩︎

  4. ROS.org. msg[EB/OL]. https://wiki.ros.org/msg[2022-07-30]. https://wiki.ros.org/msg. ↩︎

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值