ROS study notes (5) - the definition and use of topic messages

1 Introduction

In the previous two articles "Programming implementation of publisher publisher" and "subscriber Programming Implementation of Subscriber》Learn how publisher and subscriber publish and subscribe to messages. But whether it is the Twist message published by the publisher or the turtle position post information subscribed by the subscriber, they have been defined in ROS and we can use them directly. Then during our own development process, when these ROS-defined messages cannot meet our needs, we can define the message types ourselves. The following is to complete the customization of the message.

2. Model

Insert image description here

3. Start customizing messages

Step 1: Define msg file

Create a new folder in the learning_topic directory to store subsequent message files. Enter the folder and open the command line in the folder, and use the command to create a new file. msg
Insert image description here
touch Person.msgPerson.msg
Insert image description here

Open the file, enter the following and save:

string name
uint8 sex
uint8 age

uint8 unknown = 0
uint8 male = 1
uint8 female = 2

What is written here is not cpp or python. But it will be automatically compiled into cpp or python by ros during the compilation process.

Step 2: Add function package dependencies in package.xml

Openinglearning_topicText item addedpackage.xmlText item.

If your computer has a browser installed, the xml file may be opened by the browser by default and cannot be edited. You can open the command line in this directory and enter the gedit package.xml command to open the file.

Add the following statement at the bottom as shown in the picture and save:

<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>

Insert image description here

<build_depend> is used to add compilation dependencies, add heremessage_generationFunction package
<exec_depend< is used to add execution dependencies, add here< /span>message_runtimeFunction package

Step 3: Add compilation options to CMakeLists.txt

Openinglearning_topicText item addedCMakeLists.txt.

  1. Add to the topfind_package: This step is to add function package dependencies. ----- ----- message_generation
    Insert image description here
  2. Find the positionDeclare ROS dynamic reconfigure parameters and add the following sentence above:
add_message_files(FILES Person.msg)
generate_messages(DEPENDENCIES std_msgs)
  • The first sentence tells the compiler that Person.msg is the message interface we defined

  • The second sentence tells the compiler which libraries/packages it needs to depend on when compilingPerson.msg the file. Here we need to rely on std_msgs. What we just wrote like string, uint8 is in std_msgs defined in.

Insert image description here
-----

  1. Findcatkin specific configuration (that is, above ## Build ##), add the following statement at the location shown (I am special here, the commented out statement directly above is the same as The statements to be added are exactly the same. In this case, you can directly uncomment that sentence without adding a new statement)
CATKIN_DEPENDS geometry_msgs roscpp rospy std_msgs turtlesim

Insert image description hereAfter completing the above three steps, save and exit.

Go back to the root directory of the workspacecatkin_ws, open the command line, and enter the commandcatkin_make to compile.

After is compiled successfully, you can find the file you just wrote under the /learning_topic/devel/include/learning_topic/ path and it has been compiled into document. Person.msgPerson.h

Step 4: Write cpp program

Create two cpp files in the path shown in the figure. code show as below.
Insert image description here
person_publisher.cpp:

/**
 * 该例程将发布/person_info话题,自定义消息类型learning_topic::Person
 */
 
#include <ros/ros.h>
//!!!!!关键!!!!!
#include "learning_topic/Person.h"

int main(int argc, char **argv)
{
    
    
    // ROS节点初始化
    ros::init(argc, argv, "person_publisher");

    // 创建节点句柄
    ros::NodeHandle n;

    // 创建一个Publisher,发布名为/person_info的topic,消息类型为learning_topic::Person,队列长度10
    //!!!!!关键!!!!!
    ros::Publisher person_info_pub = n.advertise<learning_topic::Person>("/person_info", 10);

    // 设置循环的频率
    ros::Rate loop_rate(1);

    int count = 0;
    while (ros::ok())
    {
    
    
        // 初始化learning_topic::Person类型的消息
        learning_topic::Person person_msg;
        person_msg.name = "Tom";
        person_msg.age  = 18;
        person_msg.sex  = learning_topic::Person::male;

        // 发布消息
        person_info_pub.publish(person_msg);

        ROS_INFO("Publish Person Info: name:%s  age:%d  sex:%d", 
                  person_msg.name.c_str(), person_msg.age, person_msg.sex);

        // 按照循环频率延时
        loop_rate.sleep();
    }

    return 0;
}

person_subscriber.cpp:

/**
 * 该例程将订阅/person_info话题,自定义消息类型learning_topic::Person
 */
 
#include <ros/ros.h>
//!!!!!关键!!!!!
#include "learning_topic/Person.h"

// 接收到订阅的消息后,会进入消息回调函数
void personInfoCallback(const learning_topic::Person::ConstPtr& msg)
{
    
    
    // 将接收到的消息打印出来
    ROS_INFO("Subcribe Person Info: name:%s  age:%d  sex:%d", 
             msg->name.c_str(), msg->age, msg->sex);
}

int main(int argc, char **argv)
{
    
    
    // 初始化ROS节点
    ros::init(argc, argv, "person_subscriber");

    // 创建节点句柄
    ros::NodeHandle n;

    // 创建一个Subscriber,订阅名为/person_info的topic,注册回调函数personInfoCallback
    //!!!!!关键!!!!!
    ros::Subscriber person_info_sub = n.subscribe("/person_info", 10, personInfoCallback);

    // 循环等待回调函数
    ros::spin();

    return 0;
}

After the cpp file is written, write the justCMakeLists.txt file again and configure the cpp content just written.

Find above the ## Install ## position, add the following statement, and save.

Note: Compared with the previous configurationCMakeLists.txt, there are more add_dependencies statements to make the executable file (the work done by the first two sentences) and Dynamically generated files generate dependencies

Insert image description here

add_executable(person_publisher src/person_publisher.cpp)
target_link_libraries(person_publisher ${
    
    catkin_LIBRARIES})
add_dependencies(person_publisher ${
    
    PROJECT_NAME}_generate_messages_cpp)

add_executable(person_subscriber src/person_subscriber.cpp)
target_link_libraries(person_subscriber ${
    
    catkin_LIBRARIES})
add_dependencies(person_subscriber ${
    
    PROJECT_NAME}_generate_messages_cpp)

Step 5: Compile and run

The steps are exactly the same as before. (If you have modified the .bashrc file before, you can omit the source devel/setup.bash statement)

cd ~/catkin_ws
catkin_make
source devel/setup.bash
roscore
rosrun learning_topic person_subscriber
rosrun learning_topic person_publisher

Insert image description hereAs you can see, the message sender publisher and the message receiver subscriber have established a relationship.

If the environment variables have been modified and the executable file corresponding to the function package can be found, but the function package name cannot be automatically completed when executing the rosrun command, execute it again at this time< /span>rospack list command is enough.

4. Little knowledge

ROS Master helps with the creation and linking of nodes. Once a node is successfully created and linked, it is no longer affected by ROS Master.

At this time, if you press Exit on the terminal executing the commandroscore (that is, exit ROS Master), You will find that the subscriber and publisher are still sending and receiving data as usual. ctrl+croscore

The participation of ROS Master is only required when the parameters involved by ROS Master need to be accessed again. For example, if there is a third node that wants to communicate with any of the two nodes, this communication is impossible without the help of ROS Master. ongoing.

Guess you like

Origin blog.csdn.net/weixin_44415639/article/details/122452011