Skip to content

04. Publisher | Subscriber with C

Davood Dorostkar edited this page Jul 21, 2021 · 8 revisions

Rationale

You need to have a package created in the ROS workspace. Inside package's src place your .cpp files.

Every time you make changes to your files, you have to re-make with catkin_make in the workspace folder.

Two file types can be run in ROS: python files and binary files. C++ files are being compiled to binary before execution.


Make the file executable

Create your files inside src. Then make them executable with:

chmod 777 talker.cpp

Configuration For C++ only

In CMakeLists.txt:

add_executable(<package> src/file.cpp)

Publisher & Subscriber

Here we have a node called planner. The two first lines initialize the node. The next lines introduce the node as a publisher and subscriber respectively. The advertise line does not publish anything (just defines) until you publish the publisher object (here velocityCommand). Here it publishes to the /turtle1/cmd_vel topic which has a message of types geometry_msgs::Twist. You can then publish it like:

velocityCommand.publish(velocity_msg);

However, the subscriber line is enough as soon as you define the callback function (here updatePose). Here it is subscribing to the /turtle1/pose topic that has a message of type turtlesim::Pose::ConstPtr.


Execution speed

The ros::Rate object handles the frequency at which data transfer is being done. You can then execute it like:

ros::Rate loop(100);
.
.
.
loop.sleep();

The ros::spin() function waits until you kill the process with Ctrl+C. If using ros::spinOnce() it is executed only once.


Time

To get time in seconds:

ros::Time::now().toSec()

or

std::time_t time = std::chrono::system_clock::now();

Data manipulation

You can create messages and access their member data like:

geometry_msgs::Twist velocity_msg;
velocity_msg.linear.x = speed;

Handle Ctrl+C

while(ros::ok()){
...
}

Input and output from/to terminal

using namespace std
cout << "Enter data:" << endl;
cin >> position.x;

or

ROS_INFO("Enter data:");

Structure

The overall structure of a node is like:

#include "ros/ros.h"
#include "geometry_msgs/Twist.h"
#include "turtlesim/Pose.h"
#include <sstream>
using namespace std;
ros::Publisher velocityCommand;
ros::Subscriber poseSensor;
turtlesim::Pose currentPosition;
const double PI = 3.14159265359;

double now();
void updatePose(const turtlesim::Pose::ConstPtr &pose_msg);
void plan();

int main(int argc, char **argv)
{
    ros::init(argc, argv, "planner");
    ros::NodeHandle node;
    velocityCommand = node.advertise<geometry_msgs::Twist>("/turtle1/cmd_vel", 1000);
    poseSensor = node.subscribe("/turtle1/pose", 10, updatePose);
    ros::Rate loop(0.5);
    plan();
    ros::spin();
    return 0;
}