燕清扬
我相信未来!

  自定义消息一般存储在功能包的msg文件夹下的.msg文件中,这些定义可告诉ROS这些数据的类型和名称,以便于在ROS 节点中使用。添加完这些自定义消息后,ROS会将其转为等效的C++节点,从而可在其他节点中使用。


1、编写msg文件

  自定义消息必须在.msg文件中编写且保存在功能包的msg文件夹中。在上一节<ROS-4 : ROS节点和主题>创建的功能包ros_demo_pkg下创建文件夹msg,并在其中添加文件demo_msg.msg,该文件内容为:

string greeting

int32 number

 

 

2、修改package.xml文件

  由于自定义消息需要依赖于其他功能包,所以在功能包ros_demo_pkgpackage.xml文件中添加或uncomment以下行:

<build_depend>message_generation</build_depend>

<exec_depend>message_runtime</exec_depend>

 

 

3、修改CMakeList.txt文件

  编辑该功能包的CMakeList.txt文件,添加message_generation:

  find_package(catkin REQUIRED COMPONENTS)
    roscpp
    rospy
    std_msgs
    actionlib
    actionlib_msgs
    message_generation
)

 

  添加自定义的message文件:

    add_message_files(
    FILES
    demo_msg.msg
  )   ## Generate added messages and services with any dependencies listed here   generate_messages(
    DEPENDENCIES
    std_msgs
    actionlib_msgs
  )

 

 

4、编译并构建该功能包

$ cd ~/catkin_ws

$ catkin_ws

 

 

5、验证自定义消息

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

 

$ rosmsg show ros_demo_pkg/demo_msg

 

 

6、使用自定义消息

  在功能包ros_demo_pkg,创建使用该自定义消息的publishersubscriber节点,分别为msg_pubsher.cppmsg_subscriber.cpp,保存在该功能包的src文件夹中。其中msg_publisher.cpp的代码如下:

#include "ros/ros.h"
#include "std_msgs/Int32.h"
#include "ros_demo_pkg/demo_msg.h"
#include <iostream>

using namespace std;

int main(int argc, char **argv)
{
    //Initializing ROS node with a name of demo_topic_publisher
  ros::init(argc, argv,"msg_publisher");
  //Created a nodehandle object
  ros::NodeHandle node_obj;

  //Create a publisher object   ros::Publisher number_publisher = node_obj.advertise<ros_demo_pkg::demo_msg>("/msg_topic",10);   ros::Rate loop_rate(10);   int number_count = 0;   //While loop for incrementing number and publishing to topic /numbers   while (ros::ok())
  {     
//Created a Int32 message     ros_demo_pkg::demo_msg msg;     //Inserted data to message header     string ss="hello world ";     msg.greeting = ss;     msg.number = number_count;
    
//Printing message data     ROS_INFO("%d",msg.number);     ROS_INFO("%s",msg.greeting.c_str());     //Publishing the message     number_publisher.publish(msg);     //Spining once for doing the all operation once     ros::spinOnce();     //Setting the loop rate     loop_rate.sleep();     //Increamenting the count     ++number_count;
  }   
return 0; }

 


  msg_subscriber.cpp的代码如下:

#include "ros/ros.h"
#include "ros_demo_pkg/demo_msg.h"
#include <iostream>

void number_callback(const ros_demo_pkg::demo_msg::ConstPtr& msg)
{
  ROS_INFO("Recieved greeting [%s]",msg->greeting.c_str());
  ROS_INFO("Recieved [%d]",msg->number);
}

int main(int argc, char **argv)
{
  //Initializing ROS node with a name of demo_topic_subscriber
  ros::init(argc, argv,"msg_subscriber");
  //Created a nodehandle object
  ros::NodeHandle node_obj;
  ros::Subscriber number_subscriber = node_obj.subscribe("/msg_topic",10,number_callback);
  //Spinning the node
  ros::spin();
  return 0;
}

 


  接下来修改该功能包的CMakeList.txt文件,添加以下行:

add_executable(msg_publisher src/msg_publisher.cpp)

add_executable(msg_subscriber src/demo_msg_subscriber.cpp)

add_dependencies(msg_publisher ros_demo_pkg_generate_messages_cpp)

add_dependencies(msg_subscriber ros_demo_pkg_generate_messages_cpp)

target_link_libraries(msg_publisher ${catkin_LIBRARIES})

target_link_libraries(msg_subscriber ${catkin_LIBRARIES})

 


  然后编译并构建该功能包,在终端分别启动roscore、自定义消息发布节点和自定义消息订阅节点:

$ roscore


$ rosrun ros_demo_pkg msg_publisher


$ rosrun ros_demo_pkg msg_subscriber

 

  可看到发布者发布一个字符串和一个整数,订阅者节点订阅该topic并打印信息。

 

 

 


  使用rqt_graph可查看主题msg_topic的连接关系:

 

 

7、总结

  ROS nodes中使用自定义节点包括以下几个步骤:

1. 在功能包的msg文件夹下定义消息的.msg文件;

2. 修改功能包的package.xmlCMakeList.txt文件,添加依赖项和构建信息;

3. 编译并构建功能包,生成自定义消息节点;

4. 在需要使用该自定义消息的节点代码中添加该消息头文件,如 #include “ros_demo_pkg/demo_msg.h”


 

posted on 2018-10-28 10:49  燕清扬  阅读(1284)  评论(0编辑  收藏  举报