In the second laboratory lesson, we will implement a subscriber node in C plus plus that use the publisher
subscriber communication protocol to receive and read all the messages that pass through a topic.
Let's add these new nodes inside the Arduino examples package.
So within the SRC folder where we have already created the simple publisher node.
So let's add a new file called Simple Subscriber dot CPP here.
Let's start as always by importing.
So let's include the RTL CPP library.
So let's include the CPP module.
And we can use this one to create a new ros2 node.
So let's create a new class called, for example, simple subscriber that inherits.
So let's make this inherit from the Rql CPP module and from the node class that is defined in this module.
First among the public methods of the simple subscriber class.
So among the public one, let's define the constructor of the class, which is the function that is
automatically executed when a new object of this class is created.
So let's call this one simple subscriber.
And when we initialize a new object of the simple subscriber class as our first step, we initialize
the components of the base class and therefore of the node class by calling its constructor.
So by calling the constructor of the node class to which we can pass a name so we can provide a name
to the node.
For example.
Simple subscriber.
Now that we have initialized the two node class, let's create a new subscriber object using the Create
subscription function.
So in the body of the constructor, let's use the create subscription function that we inherited from
the Node class and let's save the output of this function among a private variable of the simple subscriber
class that is of type rcl cpp.
Subscription class.
And we need to indicate to create an object of the of this class of the subscription class, we need
to indicate the message type.
So the type of the interface that will be used for the message exchange.
In practice, we need to indicate what type of message the subscriber object will receive within the
topic.
For example, let's assume that we are going to publish text messages.
So string messages.
So let's include from the standard messages library, from the messages, the string Http module.
And here when we create the subscription object among the angular parentheses of this object, let's
use.
So let's declare that we want to create a subscriber that receives string messages from the standard
message library.
Let's take a shared pointer to an object of this class and let's name this variable soup.
Now we can save the output of the create subscription function to the sub variable.
And we still need to indicate here among the angular parentheses of this template function.
So of the create subscription function, the type of the message that will be used on this topic.
So still from the standard messages from the messages, let's take the string message then within the
parentheses as an input to the create subscription function, we need to indicate the name of the topic
on which we want to listen to receive the messages.
So let's call this one chapter.
And furthermore, we also need to indicate the size of the queue.
So namely the size of the message queue that works as a buffer if the subscriber to the topic is not
receiving and processing messages fast enough.
Let's set, for example, this 1 to 10.
Finally, when we create a subscriber to a rose True topic, we also need to define a callback function,
a function that needs to be executed when a new message is received within the topic.
So let's use the bind function from the standard CPP library and let's name this function message callback
that we are going to define within the simple subscriber class.
So let's use the simple subscriber class.
And also let's pass the pointer.
This to indicate that we want to use the version that is implemented in the current object of this class.
Finally, since the message callback is a callback function that is called upon receiving a new message
in a ros2 topic.
This function will receive as input also the content of the message that was just received.
So here, let's also declare the usage of the place holders module from which we take the placeholder
one and let's use it inside the bind function.
So after the this, let's use the placeholder one to indicate that this function takes a parameter.
So it takes one input.
Now with this, the constructor of the simple subscriber class is completed and we can proceed to define
the message callback function.
In fact, here is in red because we haven't still defined this function.
So let's do so by defining this function.
It returns nothing, so it returns void.
And this is a const function, meaning that it's not going to change the private attributes of the class.
And as we just mentioned, this function receives as input the message that was just published in the
chapter topic.
So as we know, this is a standard message of type string.
And let's call this variable message.
In this function, every time a new message is received by the subscriber, we simply decide to print
it in the terminal using the Rql CPP info stream function that is available in the CPP library.
This function takes as input the logger scope which we obtain with the get logger function which we
inherited from the node class.
And it also takes the text.
So the content of the message that we want to display in the terminal.
So for example, let's display the message hi Earth, followed by the actual content of the message
and so followed by the message data.
And let's take this one into a string.
With this, the simple subscriber class is completed.
It's very simple and we can now define the main function.
So the one that is automatically executed when we execute this node.
Let's return zero If everything goes well and here as a first step, let's initialize Ros to use the
init function
and let's provide the arguments of the main and then let's create a pointer to an object of the simple
subscriber class as our shared pointer named node
and we use the make shared function.
To create this shared pointer to an object of type simple subscriber.
Then let's keep this node up and running, thus keeping the subscriber active to continuously receive
messages that pass through the chatter topic.
Using the spin function.
So let's use the spin function and let's keep the node up and running.
Finally, if we end the execution of the node with control C, let's ensure that the simple subscriber
node is properly destroyed using the shutdown function.
So rcl cp.
Shuts down.
To execute this node.
First, we need to instruct the compiler on how it should build our script and make it an executable
in Ros two.
To do so as we did for the simple publisher, let's open the Cmakelists.txt file that is in the Arduino
CPP examples.
So here we can copy paste these two lines that we already used in order to install the simple publisher
node and let's change the name of the executable into simple subscriber.
Then the name of the script is still in the source folder and is called Simple Subscriber Dot CP.
Let's also add the dependencies to this executable.
So to the simple subscriber and the dependencies are the same.
So we used basically the same libraries for the two nodes that are Rql CP and standard messages.
And finally, for this list, we also need to declare the new executable.
So the simple subscriber also here also in the install instruction and now above the node will be installed.
With this, we have instructed the compiler on how it should install the simple subscriber node and
we can proceed to rebuild our workspace.
So to start the node.
So let's open a new terminal and let's go to our workspace and here let's execute the command on build.
So this will rebuild our workspace.
And so also the new node that we created now to execute the publisher node, let's split the terminal.
So let's open a new terminal, let's search the workspace.
So the install setup dot bash and to start the node, let's use the command Ross to run and from the
Arduino boot CP Examples package.
If we press tab twice now, we can see that there are two nodes available the simple publisher and the
simple subscriber.
So let's run the simple subscriber node.
We can actually verify that this node is up and running by opening a new terminal and using the command
Ros2 topic list.
And actually we can see that the chapter topic is there and also we can obtain more information on this
topic with Ros2 topic info.
Let's get more information about the chapter topic.
Let's also add the flag verbose and we can see actually that there is only one node that is interacting
with this topic and actually it's a subscriber node that is called Simple Subscriber.
Now let's try to publish a new message on this topic.
To observe that the node actually triggers an event upon receiving the message.
To do so, we can use the command Ros2 topic poop to publish a message.
Then let's specify the name of the topic where we want to publish the message.
So the chatter topic.
And then followed by the type of the message we want to publish.
So if we press tab twice, we can see that Ros is able to automatically detect that in this topic are
only accepted string messages.
So let's use this type.
So the standard message string.
And then we need to specify the content.
So which is the message that we want to publish.
To do so, let's use the double quote.
Let's press tab twice again.
And we can see that here there is an empty prototype of this message.
So let's use the data to publish an empty prototype of the message and let's print the message.
Hello, Ros Choo.
So let's press enter.
And as we do so, we can see that we are constantly publishing the rescue message.
If we stop to publish this message, the interesting thing that we can see is that our simple subscriber
was able to receive all the messages that we were publishing and is displaying inside the terminal the
content of the message.
So this string allows us to that we were publishing here inside this topic.
Finally, let me show you another interesting feature of Ros2, which makes this framework language
agnostic, namely that it works in the same way, regardless of the programming language that is being
used.
So in this terminal window, so the one above, let's keep our C plus plus node that is the simple subscriber
running.
So listening on the chatter topic and here in the terminal below, let's start a new node.
So the publisher node that we instead developed in Python.
So let's source also in the terminal, the file setup dot bash, and then let's run the publisher node
that we developed in Python.
So with the Ros to run command from the Arduino board by examples, let's start the simple publisher
node, let's press enter.
And now in one terminal we have a node that we developed in Python.
So this one below that is constantly publishing messages on the chatter topic at a frequency of one
hertz.
So it's publishing one message per second basically.
And here instead in the terminal above, we have a node that is developed in C plus plus that we just
developed that is listening on this topic and it is constantly printing any new message it receives.
Among the other things, this is one of the advantages of using Ros2 to enable the communication between
different nodes that perform different operations and potentially that are developed with different
programming languages.
And this is done without any effort from the developer of this node for the integration.