In ROS (Robot Operating System), you can create a node that both publishes and subscribes to messages by initializing a `ros::Publisher` and a `ros::Subscriber` within the same node, enabling it to communicate with other nodes efficiently.
Here's an example of how to implement this:
#include "ros/ros.h"
#include "std_msgs/String.h"
void messageCallback(const std_msgs::String::ConstPtr& msg) {
ROS_INFO("Received: %s", msg->data.c_str());
}
int main(int argc, char** argv) {
ros::init(argc, argv, "pub_sub_node");
ros::NodeHandle nh;
ros::Publisher publisher = nh.advertise<std_msgs::String>("topic_name", 1000);
ros::Subscriber subscriber = nh.subscribe("topic_name", 1000, messageCallback);
ros::Rate loop_rate(10);
while (ros::ok()) {
std_msgs::String msg;
msg.data = "Hello from publisher!";
publisher.publish(msg);
ros::spinOnce();
loop_rate.sleep();
}
return 0;
}
Understanding ROS Communication Model
What is a Publisher?
A Publisher in ROS is a vital component responsible for sending messages to a specific topic. It allows different nodes in a ROS system to communicate with one another. The Publisher is linked to a defined message type and topic name. When nodes publish their messages, they provide valuable data that can be consumed by other nodes looking to subscribe to the same topic. Common use cases include sensor data transmission, command messages to actuators, or state notifications.
What is a Subscriber?
On the opposite side of the communication model is the Subscriber, which receives messages from a specific topic. Subscribers enable nodes to respond to incoming data, leading to effective data processing and actions based on that information. This is essential for creating reactive and interactive robotic systems. For instance, a node might subscribe to sensor data to make decisions about navigating an environment or controlling motors.
Setting Up Your Development Environment
Prerequisites
Before diving into coding, ensure you have a robust development environment. You’ll need to install ROS (Robot Operating System) and set up necessary development tools such as CMake and Catkin workspaces.
Creating a New ROS Package
Creating a new package is straightforward with ROS. Open your terminal and follow these commands:
-
Navigate to your Catkin workspace source directory:
cd ~/catkin_ws/src
-
Create a new package with dependencies:
catkin_create_pkg your_package_name std_msgs roscpp
-
After successfully creating the package, you’ll see a structured directory with essential files like `CMakeLists.txt` and `package.xml`.
Writing a Node with Both Publisher and Subscriber
Initial Setup
To start, include the necessary ROS headers in your C++ file:
#include "ros/ros.h"
#include "std_msgs/String.h"
Next, set up the main function and initialize the ROS node:
int main(int argc, char **argv) {
ros::init(argc, argv, "talker_listener");
ros::NodeHandle nh;
Defining the Publisher
To define a publisher object, use the `advertise` function method:
ros::Publisher pub = nh.advertise<std_msgs::String>("chatter", 1000);
In this line of code:
- "chatter" is the topic name where messages will be published.
- 1000 represents the size of the message queue, which is crucial for managing the flow of data.
Defining the Subscriber
Similarly, to create a subscriber object:
ros::Subscriber sub = nh.subscribe("chatter", 1000, callback);
Here, the callback function is integral. It defines the action that occurs upon receiving a message. The parameters here are:
- "chatter": Topic you are listening to.
- 1000: Size of the queue.
- callback: The function that will be triggered when a new message is available.
Creating a Callback Function
The callback function processes the incoming messages. Here’s a simple example:
void callback(const std_msgs::String::ConstPtr& msg) {
ROS_INFO("I heard: [%s]", msg->data.c_str());
}
This function takes the incoming message pointer as an argument, allowing you to perform actions based on the data received. In our example, it logs the received message to the ROS console.
Putting It All Together
The complete C++ code would look like the following:
#include "ros/ros.h"
#include "std_msgs/String.h"
void callback(const std_msgs::String::ConstPtr& msg) {
ROS_INFO("I heard: [%s]", msg->data.c_str());
}
int main(int argc, char **argv) {
ros::init(argc, argv, "talker_listener");
ros::NodeHandle nh;
ros::Publisher pub = nh.advertise<std_msgs::String>("chatter", 1000);
ros::Subscriber sub = nh.subscribe("chatter", 1000, callback);
ros::Rate loop_rate(10);
while (ros::ok()) {
std_msgs::String msg;
msg.data = "Hello, ROS!";
pub.publish(msg);
ros::spinOnce();
loop_rate.sleep();
}
return 0;
}
In this code:
- msg.data = "Hello, ROS!"; initializes the message to be sent.
- pub.publish(msg); is the method that triggers the sending of the message.
- ros::spinOnce(); processes incoming messages and calls any subscribers when messages arrive.
- loop_rate.sleep(); maintains a loop update rate of 10 Hz.
Running the Node
Building the Package
After writing your code, it’s essential to build the package using the terminal. Execute the following commands:
cd ~/catkin_ws
catkin_make
This command compiles your package and makes it ready for execution.
Launching Your Node
Once everything is built, you can launch your node a couple of ways. The easiest is using:
rosrun your_package_name talker_listener
This command runs the node directly, allowing you to see the output in your terminal. Alternatively, for more complex applications, you can set up a launch file with `roslaunch`.
Debugging Common Issues
Common Errors and Solutions
When working with `ros::publisher and subscriber in same node C++`, several common issues may arise:
- Topics Not Matching: Ensure that the publisher and subscriber are using the same topic name.
- No Data Being Sent/Received: Debug using `rostopic list` and `rostopic echo <topic_name>` to see if your messages appear in ROS.
- Callback Not Triggering: Verify that your subscriber is correctly set up with the callback function.
Conclusion
In conclusion, mastering `ros::publisher and subscriber in same node C++` is fundamental for anyone working with ROS. This powerful communication model allows for efficient inter-node communication, facilitating the creation of sophisticated robotic applications. By following the steps outlined in this guide, you can effectively set up both publishers and subscribers within a single node and enhance your ROS skills significantly.
Additional Resources
To broaden your knowledge even further, consider checking official ROS tutorials, engaging with community forums, and exploring advanced topics in ROS documentation. These resources can provide greater insights and troubleshooting techniques essential for developing in the ROS ecosystem.