1ROS自定义msg类型及使用
http://blog.csdn.net/u013453604/article/details/72903398
首先创建一个空的package单独存放msg类型(当然也可以在任意的package中自定义msg类型)
这里为便于说明,建立一个名为test_msgs的包,用于对自定义msg类型的用法举例
2参考西工大
https://github.com/HANDS-FREE/handsfree
一、创建msg消息
首先创建一个空的package单独存放msg类型(当然也可以在任意的package中自定义msg类型)
这里为便于说明,建立一个名为test_msgs的包,用于对自定义msg类型的用法举例
cd catkin_arduino_ros/src catkin_create_pkg test_msgs
1.新建msg文件
cd test_msgs mkdir msg
创建Test.msg
的内容如下,
基本类型可参考: std_msgs、common_msgs
float32[] data float32 vel geometry_msgs/Pose pose string name
2.修改package.xml
接下来需要message_generation生成C++或Python能使用的代码,需要message_runtime提供运行时的支持,所以package.xml中添加以下两句
<build_depend>message_generation</build_depend> <run_depend>message_runtime</run_depend>
3.修改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)
(2)然后是add_message_files
,指定msg文件
add_message_files( FILES Test.msg # Message2.msg )
(3)然后是generate_messages
,指定生成消息文件时的依赖项,比如上面嵌套了其他消息类型geometry_msgs
,那么必须注明
#generate_messages必须在catkin_package前面 generate_messages( DEPENDENCIES geometry_msgs )
(4)然后是catkin_package
设置运行依赖
catkin_package( CATKIN_DEPENDS message_runtime )
到这里新的msg类型test_msgs/Test
就可以使用了,下面编译这个包,然后利用rosmsg show
指令查看
$ cd catkin_ws $ catkin_make $ rosmsg show test_msgs/Test float32[] data float32 vel geometry_msgs/Pose pose geometry_msgs/Point position float64 x float64 y float64 z geometry_msgs/Quaternion orientation float64 x float64 y float64 z float64 w string name
二、msg的使用
要使用自定义的消息类型必须source自定义消息所在的工作空间,否则rosmsg show test_msgs/Test
和rostopic echo /test_msg
(/test_msg
是节点中使用自定义消息类型test_msgs/Test
的topic)都会报错,因为没有source的情况下自定义消息类型是不可见的,被认为是未定义类型
1.其他包调用自定义msg类型
如果是在test_msgs包内的节点中调用test_msgs/Test
类型,只需要在.cpp文件中如下调用即可
#include <test_msgs/Test.h> test_msgs::Test msg;
如果是在其他包调用test_msgs/Test
类型则需要修改package.xml和CMakeLists.txt,比如同样在工作空间catkin_arduino_ros内有一个名为test1_pub_sub的包,我们可以在这个包内写一个节点talker.cpp,使用我们刚才自定义的消息类型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>
(2)修改CMakeLists.txt
调用自定义消息类型主要修改两个地方,以下是重点: 一是find_package
中需要声明查找包含该消息类型的包; 二是add_dependencies
要注明该消息的依赖,其他地方和普通节点一样
find_package(catkin REQUIRED COMPONENTS roscpp geometry_msgs test_msgs ) add_dependencies(test1 test_msgs_gencpp)#调用同一工作空间的自定义消息类型时注明依赖关系,防止发生头文件找不到的报错
如果缺少add_dependencies
中对test_msgs_gencpp
的依赖声明,在编译的时候如果先编译test包再编译test_msgs包则会出现如下报错(ROS工作空间各个软件包的编译顺序是随机的),因为头文件test_msgs/Test.h
还未生成
fatal error: test_msgs/Test.h: 没有那个文件或目录 #include "test_msgs/Test.h"
2 程序调用
#include "ros/ros.h" #include "std_msgs/String.h"
#include <test_msgs/Test.h> // 添加自定义的消息
// 文件包 test_msgs下面 有一个自定义的 Test.msg
#include <sstream> int main(int argc, char **argv){ ros::init(argc, argv, "talker"); ros::NodeHandle n; //ros::Publisher chatter_pub = n.advertise<std_msgs::String>("chatter", 1000); ros::Publisher chatter_pub = n.advertise<test_msgs::Test>("chatter", 1000); ros::Rate loop_rate(10); //发布自定义消息类型test_msgs::Test int count = 0; while (ros::ok()) { std_msgs::String msg; std::stringstream ss; ss << "hello world " << count; msg.data = ss.str(); ROS_INFO("%s", msg.data.c_str()); test_msgs::Test mymsg; //创建自定义消息test_msgs::Test /* float32[] data float32 vel geometry_msgs/Pose pose string name */ mymsg.name=ss.str(); // 为其中的分量 mymsg.vel=1; // chatter_pub.publish(msg); chatter_pub.publish(mymsg); //发布 ros::spinOnce(); loop_rate.sleep(); ++count; } return 0; }
3 查看结果
运行
roscore rosrun test1_pub_sub talker
查看消息
rostopic list rostopic type /chatter rosmsg show test_msgs/Test
结果看到和我们定义的是一样的。