Custom Message Type Definition and Utilization in ROS Communication

Defining Custom Topic Messages

To enable structured data exchange between nodes via ROS topics, custom message types must be defined and integrated into the build system.

  1. Define Message Interface Create a .msg file in the msg/ directory of your package, e.g., Person.msg:
string name
uint8 sex
uint8 age

# Constants for sex
uint8 UNKNOWN = 0
uint8 MALE = 1
uint8 FEMALE = 2
  1. ** Declare Message Dependencies in package.xml** Add the following entries to enable message generation at build time:
<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>
  1. Configuring CMakeLists.txt for Message Compilation Ensure the following lines are included in CMakeLists.txt:
find_package(catkin REQUIRED COMPONENTS
  ...
  message_generation
)

add_message_files(
  FILES
  Person.msg
)

generate_messages(
  DEPENDENCIES std_msgs
)

catkin_package(
  ...
  CATKIN_DEPENDS message_runtime ...
)

After running catkin_make, generated headers (e.g., Person.h) will appear under devel/include/learning_topic/.

  1. Generate Language-Specific Code The generate_messages() macro automatically produces C++ headers and Python modules for use in source code.

Implementing a Message Publisher

C++ Publisher Implementation The following node advertises a topic using the custom Person message type.

#include <ros/ros.h>
#include "learning_topic/Person.h"

int main(int argc, char** argv) {
  ros::init(argc, argv, "person_advertiser");
  ros::NodeHandle nh;

  ros::Publisher info_pub = nh.advertise<learning_topic::Person>("/user_profile", 10);

  ros::Rate loop_time(1.0);

  while (ros::ok()) {
    learning_topic::Person profile;
    profile.name = "Alice";
    profile.age = 25;
    profile.sex = learning_topic::Person::FEMALE;

    info_pub.publish(profile);
    ROS_INFO_STREAM("Broadcasting profile: " << profile.name 
                    << ", Age: " << profile.age 
                    << ", Sex: " << profile.sex);

    loop_time.sleep();
  }

  return 0;
}

Python Publisher Implementation Equivalent behavior using Python:

import rospy
from learning_topic.msg import Person

def announce_profile():
    rospy.init_node('profile_publisher', anonymous=True)
    pupil_pub = rospy.Publisher('/user_profile', Person, queue_size=10)
    tick_rate = rospy.Rate(10)

    while not rospy.is_shutdown():
        data = Person()
        data.name = "Bob"
        data.age = 30
        data.sex = Person.MALE

        pupil_pub.publish(data)
        rospy.loginfo("Updated profile → name: %s, age: %d, sex: %d",
                      data.name, data.age, data.sex)

        tick_rate.sleep()

if __name__ == '__main__':
    try:
        announce_profile()
    except rospy.ROSInterruptException:
        pass

Note: Message constants like MALE, FEMALE, etc., map directly to numeric values defined in the .msg file—ensure consistency between definitions and usage.


Implementing a Message Subscriber

C++ Subscriber Logic A subscriber node is configured to process incoming messages with a callback.

#include <ros/ros.h>
#include "learning_topic/Person.h"

void handle_user_data(const learning_topic::Person::ConstPtr& info) {
  ROS_INFO("Received user data → Name: %s, Age: %d, Sex: %d",
           info->name.c_str(), info->age, info->sex);
}

int main(int argc, char** argv) {
  ros::init(argc, argv, "profile_listener");
  ros::NodeHandle nh;

  ros::Subscriber profile_sub = nh.subscribe("/user_profile", 10, handle_user_data);

  ros::spin();
  return 0;
}

Python Subscriber Logic Simplified handling via Python callback:

import rospy
from learning_topic.msg import Person

def on_profile_received(msg):
    rospy.loginfo("Subscribed profile: %s (%d years, sex=%d)",
                  msg.name, msg.age, msg.sex)

def listen_to_profiles():
    rospy.init_node('profile_watchdog', anonymous=True)
    rospy.Subscriber('/user_profile', Person, on_profile_received)
    rospy.spin()

if __name__ == '__main__':
    listen_to_profiles()

Build Configuration for Executables

In CMakeLists.txt, declare executable targets and link against required libraries and message generation dependencies:

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

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

Execution Workflow

To launch the system:

$ cd ~/catkin_ws
$ catkin_make
$ source devel/setup.bash
$ roscore

In separate terminals:

$ rosrun learning_topic profile_listener
$ rosrun learning_topic profile_advertiser

msg exchange will begin, with the advertiser sending structured Person messages and the listener logging received content.

Thẻ: ROS custom-message catkin topic-publisher topic-subscriber

Đăng vào ngày 27 tháng 6 lúc 21:22