在 ROS 通信协议中,数据载体是一个较为重要组成部分,ROS 中通过 std_msgs 封装了一些原生的数据类型,比如:String、Int32、Int64、Char、Bool、Empty.... 但是,这些数据一般只包含一个 data 字段,结构的单一意味着功能上的局限性,当传输一些复杂的数据,比如: 相机的信息... std_msgs 由于描述性较差而显得力不从心,这种场景下可以使用自定义的消息类型。
ROS中还有一种特殊类型:Header,标头包含时间戳和ROS中常用的坐标帧信息。会经常看到msg文件的第一行具有Header标头。
一、定义msg文件
功能包下新建 msg 目录,添加文件 Person.msg。复合消息类型由标准消息类型组成,语法和写结构体差不多。

二、编辑配置文件
2.1 package.xml
在package.xml文件中添加编译依赖和执行依赖

2.2 CMakeLists.txt
a、find_package
编译自定义的功能包时需要依赖find_package中的功能包
find_package(catkin REQUIRED COMPONENTS roscpp rospy std_msgs message_generation ) # 需要加入 message_generation,必须有 std_msgs
讯享网
b、add_message_files
配置msg源文件
讯享网add_message_files( FILES Person.msg )
c、 generate_messages
生成消息是依赖于std_mags。因为自定义msg也是由std_msgs 中一些原生的数据类型组成的
generate_messages( DEPENDENCIES std_msgs )
d、catkin_package

编译find_package中的依赖包时,依赖于catkin_package中的功能包
讯享网catkin_package( # INCLUDE_DIRS include # LIBRARIES demo02_talker_listener CATKIN_DEPENDS roscpp rospy std_msgs message_runtime # DEPENDS system_lib )
三、编译
快捷键ctrl+alt+B,配置方法之前分享过。
编译后的中间文件会放在工作空间的dev目录下,C++的中间文件在include中,python的在lib中,
后续调用相关 msg 时,是从这些中间文件调用的。
四、自定义msg调用实例
4.1 vscode 配置
为了方便代码提示以及避免误抛异常,需要先配置 vscode,将前面生成的 head 文件路径配置进 c_cpp_properties.json 的 includePath属性:

4.2 发布方
相较于最普通的发布文本信息,这里需要添加中间文件的头文件,并且实例化发布者对象的时候,发布的消息类型有所变化。
#include "ros/ros.h" #include "topic_pub_sub/Person.h" //添加头文件 #include <sstream> #include <iostream> int main(int argc, char *argv[]) { /* code */ setlocale(LC_ALL,""); ros::init(argc,argv,"pub_person"); ros::NodeHandle nh; //实例化发布者对象 ros::Publisher pub = nh.advertise<topic_pub_sub::Person>("chatter_person",10); topic_pub_sub::Person p; p.id = 0; p.name = "Robot"; p.score = 100; ros::Rate rate(1); ros::Duration(3).sleep(); while(ros::ok()) { std::stringstream ss; ss << p.name << p.score; pub.publish(p); p.id += 1; ROS_INFO("name:%s%d,score:%.2f",p.name.c_str(),p.id,p.score); rate.sleep(); } return 0; }
4.3 订阅方
讯享网#include "ros/ros.h" #include "topic_pub_sub/Person.h" //添加头文件 #include <sstream> #include <iostream> //消息类型 void doPerson(const topic_pub_sub::Person::ConstPtr p) { ROS_INFO("name:%s%d,score:%.2f",p->name.c_str(),p->id,p->score); } int main(int argc, char *argv[]) { /* code */ setlocale(LC_ALL,""); ros::init(argc,argv,"sub_person"); ros::NodeHandle nh; ros::Subscriber sub = nh.subscribe<topic_pub_sub::Person>("chatter_person",10,doPerson); ros::spin(); return 0; }
4.4 配置 CMakeLists.txt
除了常规的add_executable和target_link_libraries配置之外。还需要配置add_dependencies,这是为了编译msg文件之后,再编译包含msg文件的cpp文件,保证不会出现逻辑错误。
add_executable(topic_pub_person src/topic_pub_person.cpp) add_executable(topic_sub_person src/topic_sub_person.cpp) target_link_libraries(topic_pub_person ${catkin_LIBRARIES}) target_link_libraries(topic_sub_person ${catkin_LIBRARIES}) add_dependencies(topic_pub_person ${PROJECT_NAME}_generate_messages_cpp) add_dependencies(topic_sub_person ${PROJECT_NAME}_generate_messages_cpp)
4.5 执行结果



版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/37529.html