自定义msg类型以及使用"/>
ROS自定义msg类型以及使用
一、创建msg消息
参考:
CreatingMsgAndSrv
首先创建一个空的package单独存放msg类型(当然也可以在任意的package中自定义msg类型)
这里为便于说明,建立一个名为test_msgs的包,用于对自定义msg类型的用法举例
$ cd catkin_ws/src
$ catkin_create_pkg test_msgs
- 1
- 2
1.新建msg文件
然后在test_msgs中创建msg文件夹,在msg文件夹其中新建一个名为Test.msg
消息类型文件
$ cd test_msgs
$ mkdir msg
- 1
- 2
Test.msg
的内容如下,
基本类型可参考: std_msgs、common_msgs
float32[] data
float32 vel
geometry_msgs/Pose pose
string name
- 1
- 2
- 3
- 4
2.修改package.xml
接下来需要message_generation生成C++或Python能使用的代码,需要message_runtime提供运行时的支持,所以package.xml中添加以下两句
<build_depend>message_generation</build_depend>
<run_depend>message_runtime</run_depend>
- 1
- 2
3.修改CMakeLists.txt
CMakeLists.txt
要注意四个地方
(1)首先调用find_package
查找依赖的包,必备的有roscpp rospy message_generation
,其他根据具体类型添加,比如上面的msg文件中用到了geometry_msgs/Pose pose
类型,那么必须查找geometry_msgs
find_package(catkin REQUIRED COMPONENTS roscpp rospy message_generation std_msgs geometry_msgs)
- 1
(2)然后是add_message_files
,指定msg文件
add_message_files(FILESTest.msg# Message2.msg
)
- 1
- 2
- 3
- 4
- 5
(3)然后是generate_messages
,指定生成消息文件时的依赖项,比如上面嵌套了其他消息类型geometry_msgs
,那么必须注明
#generate_messages必须在catkin_package前面
generate_messages(DEPENDENCIESgeometry_msgs
)
- 1
- 2
- 3
- 4
- 5
(4)然后是catkin_package
设置运行依赖
catkin_package(CATKIN_DEPENDS message_runtime)
- 1
- 2
- 3
- 4
- 5
到这里新的msg类型test_msgs/Test
就可以使用了,下面编译这个包,然后利用rosmsg show
指令查看
$ cd catkin_ws
$ catkin_make
$ rosmsg show test_msgs/Test
float32[] data
float32 vel
geometry_msgs/Pose posegeometry_msgs/Point positionfloat64 xfloat64 yfloat64 zgeometry_msgs/Quaternion orientationfloat64 xfloat64 yfloat64 zfloat64 w
string name
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
二、msg的使用
要使用自定义的消息类型必须source自定义消息所在的工作空间,否则rosmsg show test_msgs/Test
和rostopic echo /test_msg
(/test_msg
是节点中使用自定义消息类型test_msgs/Test
的topic)都会报错,因为没有source的情况下自定义消息类型是不可见的,被认为是未定义类型
1.其他包调用自定义msg类型
参考:
DefiningCustomMessages
如果是在test_msgs包内的节点中调用test_msgs/Test
类型,只需要在.cpp文件中如下调用即可
#include <test_msgs/Test.h>test_msgs::Test msg;
- 1
- 2
- 3
如果是在其他包调用test_msgs/Test
类型则需要修改package.xml和CMakeLists.txt,比如同样在工作空间catkin_ws内有一个名为test的包,我们可以在这个包内写一个节点,使用我们刚才自定义的消息类型test_msgs/Test
,如下:
(1)修改package.xml
养成好习惯,维护软件包清单的更新,以便于别人使用你的软件前安装各种依赖项,当然这个文件不影响程序编译
<build_depend>roscpp</build_depend>
<run_depend>roscpp</run_depend><build_depend>test_msgs</build_depend>
<run_depend>test_msgs</run_depend>
- 1
- 2
- 3
- 4
- 5
(2)修改CMakeLists.txt
调用自定义消息类型主要修改两个地方,以下是重点:
一是find_package
中需要声明查找包含该消息类型的包;
二是add_dependencies
要注明该消息的依赖,其他地方和普通节点一样
find_package(catkin REQUIRED COMPONENTSroscppgeometry_msgstest_msgs
)add_dependencies(test1 test_msgs_gencpp)#调用同一工作空间的自定义消息类型时注明依赖关系,防止发生头文件找不到的报错
- 1
- 2
- 3
- 4
- 5
- 6
- 7
如果缺少add_dependencies
中对test_msgs_gencpp
的依赖声明,在编译的时候如果先编译test包再编译test_msgs包则会出现如下报错(ROS工作空间各个软件包的编译顺序是随机的),因为头文件test_msgs/Test.h
还未生成
fatal error: test_msgs/Test.h: 没有那个文件或目录#include "test_msgs/Test.h"
- 1
- 2
2.msg类型数组的使用
需要说明的是std_msgs中有些数组用法和C++标准库中不一样
比如Float32MultiArray,其定义如下:
std_msgs/MultiArrayLayout layout
float32[] data
- 1
- 2
其中data
是一个浮点数组,但是方括号只是一个用来表明它是数组的符号,我们不能在定义的时候在方括号中给定数组长度,实际上ROS中类似float32[]
,int8[]
这样的数组类型都是std::vector
,使用方法也和std::vector
一样
测试代码可以从这里下载
下面是一个消息订阅节点,用于测试
/************************ * @Author: Jinglin Zhang * @DateTime: 2017-06-07 19:57:30 * @Description: 节点test1,订阅了test_msgs包下talker节点发布的"test_msg"话题,用于测试test_msgs::Test消息类型
************************/
#include <ros/ros.h>
#include <test_msgs/Test.h>void msgCallback(const test_msgs::Test::ConstPtr &msg)
{//test_msgs::Test类型里的float32[]数据传到vectorstd::vector<float> array = msg->data;std::cout << "msg->data[0]=" << msg->data[0] << std::endl;std::cout << "msg->data.size=" << msg->data.size() << std::endl;std::cout << "msg->data=" << msg->data[0] << ", " << msg->data[1] << ", " << msg->data[2] << ", " << msg->data[3] << ", " << msg->data[4] << ", " << msg->data[5] << std::endl;}int main(int argc,char ** argv)
{ros::init(argc,argv,"test1");ros::NodeHandle n;ros::Subscriber msg_sub = n.subscribe("test_msg", 100, msgCallback);ros::spin();return 0;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
下面是一个消息发布节点,用于测试
/************************ * @Author: Jinglin Zhang * @DateTime: 2017-06-07 20:03:35 * @Description: 节点talker,发布"test_msg"话题,用于测试test_msgs::Test消息类型
************************/
#include <ros/ros.h>
#include <test_msgs/Test.h>int main(int argc, char **argv)
{ros::init(argc, argv, "msg_talker");ros::NodeHandle n;ros::Publisher msg_pub = n.advertise<test_msgs::Test>("test_msg", 1000);ros::Rate loop_rate(10);int count = 0;while (ros::ok()){test_msgs::Test msg;std::cout << "msg.data.size=" << msg.data.size() << std::endl;//用vector给float32[]数组赋值float array[3] = {1.1,1.2,0.3};std::vector<float> array1(array,array+3);msg.data = array1;std::cout << "msg.data3[0]=" << msg.data[0] << std::endl;std::cout << "msg.data3.size=" << msg.data.size() << std::endl;//下标访问float32[]数组msg.data[0] = 0.1;std::cout << "msg.data3[0]=" << msg.data[0] << std::endl;float array4[4] = {1.0,2.0,0.3,6.6};std::vector<float> array41(array4,array4+4);msg.data = array41;std::cout << "msg.data4.size=" << msg.data.size() << std::endl;std::cout << "msg.data4=" << msg.data[0] << " " << msg.data[1] << " " << msg.data[2] << " " << msg.data[3] << std::endl;msg.data.push_back(5.5);std::cout << "msg.data[5]=" << msg.data[4] << std::endl;//使用迭代器msg.data.resize(6);std::cout << "msg.data6.size=" << msg.data.size() << std::endl;std::cout << "msg.data6=" ;for(std::vector<float>::iterator it = msg.data.begin(); it != msg.data.end(); ++it){*it = 0.6;std::cout << *it << " ";}std::cout << std::endl;msg_pub.publish(msg);ros::spinOnce();loop_rate.sleep();++count;}return 0;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
更多推荐
ROS自定义msg类型以及使用
发布评论