ROS 实践——用Python发布一个自定义消息,用C++订阅这个自定义消息

背景:(background)

当一个ros项目由多种编程语言编写,为了实现不同编程程语言的码块之间的通讯,他们之间需要通讯。有很多案例等待着介绍和实施。本文从最基础的地方开始讲起(When a ROS project is written in multiple programming languages, in order to achieve communication between code blocks in different programming languages, they need to communicate with each other. There are so many cases waiting to introduce and implement。Let's start from the basics。)

如何使用Python发布一个自定义消息,并用C++订阅这个自定义消息 ?(How to publish a custom message with python and subscribe the message with C++ ?)

  1. 自定义消息(Custom Message)
  2. Python发布自定义消息 (Publish the custom message uing the python)
  3. C++ 订阅自定义消息 (Subscribe the custom message using the C++)
  4. 文件配置(File Configuration)
  5. 参考 (References)

自定义消息 (Custom Message)

建立ros工作空间和软件包之后,建立一个自定义消息:PathDrop_msg.msg. (create a custom message named PathDrop_msg.msg after building the workspace and pacage of ros)

在软件包下建立一个名为msg的文件夹 在内部建立一个名为PathDrop_msg.msg的自定义文件,然后在上面给出基于ros 基本消息类型的自定义消息

(make a directory named msg in the package of ros and touch a file named PathDrop_msg.msg. give your custom message inside.)

使用以下命令验证是否成功构建自定义消息:

bash 复制代码
$ rosmsg show ros_demo_pkg/demo_msg
python 复制代码
# the start point dropping point and end point of the trajectory planning
float64 start_point_x
float64 start_point_y
float64 dropping_point_x
float64 dropping_point_y
float64 end_point_x
float64 end_point_y

Python发布自定义消息 (Publish the custom message uing the python)

python 复制代码
#!/usr/bin/env python3
# -*- coding: utf-8 -*- #
"""
Created on Thu Jan 30 20:45:17 2024
"""
import os
import sys
PKG_PATH = os.path.expanduser('~/rosws1/src/trajectoryplanning/') # corresponding the workspace name and package name 
sys.path.append(PKG_PATH + 'scripts/')
from trajectoryplanning.msg import PathDrop_msg # trajectoryplanning is the package name and PathDrop_msg is message file name
import rospy
import numpy as np
import matplotlib.pyplot as plt
import random
import math

class MultipleFireSpotsTrajectoryPlanning():
    "how to get the optimal trajectory to extinguish the forest fire"
    def __init__(self):
        self.pathpoints = PathDrop_msg()
        print("initialization done for fire spots and home locaiton!")
    
    def run(self):
        self.path_point_pub = rospy.Publisher("trajectoryplanning/key_path_points", PathDrop_msg, queue_size=10)
        rospy.sleep(2.0)
        #### for trajectory plannnnig -------------
        publish_n = 0  # only publish once !!!
        
        while not rospy.is_shutdown() and (publish_n == 0):
        
            self.pathpoints.start_point_x = 1
            self.pathpoints.start_point_y = 2
            self.pathpoints.dropping_point_x = 3
            self.pathpoints.dropping_point_y = 4
            self.pathpoints.end_point_x = 5
            self.pathpoints.end_point_y = 6
            self.path_point_pub.publish(self.pathpoints)
            

            rospy.Rate(15).sleep()
            publish_n = publish_n + 1;
  

if __name__ == '__main__':
    #rospy.init_node("RANSAC_Based_Trajectory_Planning", anonymous=True)
    rospy.init_node("ransac_path_points_node", anonymous=True)
    tp = MultipleFireSpotsTrajectoryPlanning()
    tp.run()

关键语句解释 (Interpretation)

  1. 导入自定义文件 (import custom message from pakage)
python 复制代码
from trajectoryplanning.msg import PathDrop_msg 

trajectoryplanning 对应软件包名,PathDrop_msg 对应自定义消息名

( trajectoryplanning is the package name and PathDrop_msg is custom message file name)

  1. 实例化一个消息变量 (Instantiate a variable)
python 复制代码
self.pathpoints = PathDrop_msg()
  1. 运行py 文件之前你必须授权他们为可执行文件( you must chmod the .py file before running it !)
bash 复制代码
chmod +x listener.py

C++订阅自定义消息 (Subscribe the custom message using the C++)

创建一个名为 getPathpoints.cpp的文件 在src 文件下下 (buid a file named getPathpoints.cpp in the src directory )

cpp 复制代码
#include <ros/ros.h>
#include "std_msgs/Float64.h"
#include "trajectoryplanning/PathDrop_msg.h"

// 接收到订阅的消息后,会进入消息回调函数
void personInfoCallback(const trajectoryplanning::PathDrop_msg::ConstPtr& msg)
{
	ROS_INFO("Subcribe start_point_x:%f start_point_y:%f", msg->start_point_x, msg->start_point_y);		// 将接收到的消息打印出来
	ROS_INFO("Subcribe dropping_point_x:%f dropping_point_y:%f", msg->dropping_point_x, msg->dropping_point_y);		// 将接收到的消息打印出来
	ROS_INFO("Subcribe end_point_x:%f end_point_y:%f", msg->end_point_x, msg->end_point_y);		// 将接收到的消息打印出来
 }
int main(int argc, char **argv)
{
	ros::init(argc, argv, "getPathpoints");		// 初始化ROS节点
	ros::NodeHandle n;								// 创建节点句柄
	ros::Subscriber person_info_sub = n.subscribe("trajectoryplanning/key_path_points", 10, personInfoCallback);
						// 创建一个Subscriber,订阅名为/person_info的topic,注册回调函数personInfoCallback
						
	ros::spin();  		// ros::spin()循环等待回调函数,用于调用所有可触发的回调函数,将进入循环,不会返回,
						// 类似于在循环里反复调用spinOnce(),而ros::spinOnce()只会去触发一次
	return 0;
}

关键语句解释 (Interpretation)

  1. 导入自定义文件 (include the h files corresponding to the custom message file)
cpp 复制代码
#include "trajectoryplanning/PathDrop_msg.h"
  1. 回调函数输出订阅数据 (print the date of subscriping in the callback function)
cpp 复制代码
void personInfoCallback(const trajectoryplanning::PathDrop_msg::ConstPtr& msg)
// trajectoryplanning::PathDrop_msg 对应软件包名和消息文件名
ROS_INFO("Subcribe start_point_x:%f start_point_y:%f", msg->start_point_x, msg->start_point_y);	
// msg->start_point_x 消息分量
  1. CMakeLists文件里面加入对应的C++文件,生成可执行文件
bash 复制代码
add_executable(getPathpoints src/getPathpoints.cpp)		# 生成可执行文件person_subscriber
target_link_libraries(getPathpoints ${catkin_LIBRARIES})	# 链接

文件配置(File Configuration)

  1. 设置 package.xml 文件 (set the package.xml file)
    添加依赖包:(add some depend packages if need)
bash 复制代码
  <build_depend>roscpp</build_depend>
  <build_depend>rosmsg</build_depend>
  <build_depend>rospy</build_depend>
  <build_depend>std_msgs</build_depend>
  <build_depend>message_generation</build_depend>
  
  <build_export_depend>roscpp</build_export_depend>
  <build_export_depend>rosmsg</build_export_depend>
  <build_export_depend>rospy</build_export_depend>
  <build_export_depend>std_msgs</build_export_depend>
  
  <exec_depend>roscpp</exec_depend>
  <exec_depend>rosmsg</exec_depend>
  <exec_depend>rospy</exec_depend>
  <exec_depend>message_generation</exec_depend>
  <exec_depend>message_runtime</exec_depend>
  <exec_depend>std_msgs</exec_depend>
  
  1. 设置 CMakelist 文件 (set the CMakelist file)
bash 复制代码
find_package(catkin REQUIRED COMPONENTS
  roscpp
  rosmsg
  rospy
  std_msgs
  message_generation
)
bash 复制代码
add_message_files(
  FILES
  PathDrop_msg.msg

)

generate_messages(
  DEPENDENCIES
  std_msgs
)
bash 复制代码
catkin_package(
	CATKIN_DEPENDS
	roscpp
	rospy
	std_msgs
	message_runtime
#  INCLUDE_DIRS include
#  LIBRARIES trajectoryplanning
#  CATKIN_DEPENDS roscpp rosmsg rospy
#  DEPENDS system_lib
)

文章最后留个问题:

命令行如何查看ros message 基本类型?

参考 (References)

自定义消息1
如何查看自定义消息内容
自定义消息2
ros 消息总结
c++ 和python 相互发布和和订阅

相关推荐
小xin过拟合27 分钟前
day20 二叉树part7
开发语言·数据结构·c++·笔记·算法
EstrangedZ37 分钟前
vscode(MSVC)进行c++开发的时,在debug时查看一个eigen数组内部的数值
c++·ide·vscode
没有bug.的程序员1 小时前
AOT 编译与 GraalVM 实战:Java 云原生的终极进化
java·python·云原生·graalvm·aot
深兰科技1 小时前
深兰科技:搬迁公告,我们搬家了
javascript·人工智能·python·科技·typescript·laravel·深兰科技
啟明起鸣1 小时前
【数据结构】B 树——高度近似可”独木成林“的榕树——详细解说与其 C 代码实现
c语言·开发语言·数据结构
牛奶yu茶1 小时前
Python学习笔记之(二)变量和简单的数据类型
笔记·python·学习
乌萨奇也要立志学C++1 小时前
【C++详解】哈希表概念与实现 开放定址法和链地址法、处理哈希冲突、哈希函数介绍
c++·哈希算法·散列表
WSSWWWSSW2 小时前
Seaborn数据可视化实战:Seaborn高级使用与性能优化教程
python·信息可视化·matplotlib·seaborn
十八旬2 小时前
苍穹外卖项目实战(日记十)-记录实战教程及问题的解决方法-(day3-2)新增菜品功能完整版
java·开发语言·spring boot·mysql·idea·苍穹外卖
这周也會开心2 小时前
Java-多态
java·开发语言