WEBVTT

00:01.320 --> 00:08.130
In the second laboratory lesson, we will implement a subscriber node in C plus plus that use the publisher

00:08.130 --> 00:13.470
subscriber communication protocol to receive and read all the messages that pass through a topic.

00:14.870 --> 00:19.460
Let's add these new nodes inside the Arduino examples package.

00:19.460 --> 00:24.860
So within the SRC folder where we have already created the simple publisher node.

00:24.860 --> 00:33.650
So let's add a new file called Simple Subscriber dot CPP here.

00:33.650 --> 00:36.730
Let's start as always by importing.

00:36.740 --> 00:41.780
So let's include the RTL CPP library.

00:42.020 --> 00:45.410
So let's include the CPP module.

00:46.390 --> 00:49.930
And we can use this one to create a new ros2 node.

00:49.960 --> 00:58.120
So let's create a new class called, for example, simple subscriber that inherits.

00:58.120 --> 01:06.970
So let's make this inherit from the Rql CPP module and from the node class that is defined in this module.

01:08.000 --> 01:12.860
First among the public methods of the simple subscriber class.

01:14.090 --> 01:20.210
So among the public one, let's define the constructor of the class, which is the function that is

01:20.210 --> 01:24.770
automatically executed when a new object of this class is created.

01:24.980 --> 01:28.600
So let's call this one simple subscriber.

01:28.610 --> 01:35.390
And when we initialize a new object of the simple subscriber class as our first step, we initialize

01:35.390 --> 01:41.990
the components of the base class and therefore of the node class by calling its constructor.

01:41.990 --> 01:48.680
So by calling the constructor of the node class to which we can pass a name so we can provide a name

01:48.680 --> 01:49.430
to the node.

01:49.820 --> 01:50.780
For example.

01:50.780 --> 01:54.260
Simple subscriber.

01:55.140 --> 02:01.890
Now that we have initialized the two node class, let's create a new subscriber object using the Create

02:01.890 --> 02:03.390
subscription function.

02:03.390 --> 02:12.930
So in the body of the constructor, let's use the create subscription function that we inherited from

02:12.930 --> 02:23.670
the Node class and let's save the output of this function among a private variable of the simple subscriber

02:23.670 --> 02:27.600
class that is of type rcl cpp.

02:30.590 --> 02:32.060
Subscription class.

02:32.060 --> 02:37.850
And we need to indicate to create an object of the of this class of the subscription class, we need

02:37.850 --> 02:39.260
to indicate the message type.

02:39.260 --> 02:43.120
So the type of the interface that will be used for the message exchange.

02:43.130 --> 02:48.920
In practice, we need to indicate what type of message the subscriber object will receive within the

02:48.920 --> 02:49.600
topic.

02:49.610 --> 02:53.420
For example, let's assume that we are going to publish text messages.

02:53.420 --> 02:55.370
So string messages.

02:55.520 --> 03:06.350
So let's include from the standard messages library, from the messages, the string Http module.

03:06.590 --> 03:13.820
And here when we create the subscription object among the angular parentheses of this object, let's

03:13.820 --> 03:14.420
use.

03:14.420 --> 03:21.830
So let's declare that we want to create a subscriber that receives string messages from the standard

03:21.830 --> 03:23.000
message library.

03:23.330 --> 03:30.770
Let's take a shared pointer to an object of this class and let's name this variable soup.

03:31.660 --> 03:40.630
Now we can save the output of the create subscription function to the sub variable.

03:40.630 --> 03:46.180
And we still need to indicate here among the angular parentheses of this template function.

03:46.180 --> 03:51.610
So of the create subscription function, the type of the message that will be used on this topic.

03:51.610 --> 04:00.190
So still from the standard messages from the messages, let's take the string message then within the

04:00.190 --> 04:06.700
parentheses as an input to the create subscription function, we need to indicate the name of the topic

04:06.700 --> 04:09.760
on which we want to listen to receive the messages.

04:09.760 --> 04:12.970
So let's call this one chapter.

04:12.970 --> 04:16.390
And furthermore, we also need to indicate the size of the queue.

04:16.390 --> 04:22.390
So namely the size of the message queue that works as a buffer if the subscriber to the topic is not

04:22.390 --> 04:25.390
receiving and processing messages fast enough.

04:25.720 --> 04:27.910
Let's set, for example, this 1 to 10.

04:28.060 --> 04:34.610
Finally, when we create a subscriber to a rose True topic, we also need to define a callback function,

04:34.670 --> 04:39.260
a function that needs to be executed when a new message is received within the topic.

04:39.530 --> 04:50.480
So let's use the bind function from the standard CPP library and let's name this function message callback

04:50.510 --> 04:55.070
that we are going to define within the simple subscriber class.

04:55.250 --> 05:00.020
So let's use the simple subscriber class.

05:01.550 --> 05:04.340
And also let's pass the pointer.

05:05.150 --> 05:11.870
This to indicate that we want to use the version that is implemented in the current object of this class.

05:12.830 --> 05:18.770
Finally, since the message callback is a callback function that is called upon receiving a new message

05:18.770 --> 05:20.090
in a ros2 topic.

05:20.090 --> 05:25.190
This function will receive as input also the content of the message that was just received.

05:25.490 --> 05:35.900
So here, let's also declare the usage of the place holders module from which we take the placeholder

05:35.900 --> 05:39.620
one and let's use it inside the bind function.

05:39.620 --> 05:47.660
So after the this, let's use the placeholder one to indicate that this function takes a parameter.

05:47.660 --> 05:48.890
So it takes one input.

05:49.740 --> 05:56.760
Now with this, the constructor of the simple subscriber class is completed and we can proceed to define

05:56.760 --> 05:58.510
the message callback function.

05:58.530 --> 06:03.210
In fact, here is in red because we haven't still defined this function.

06:03.510 --> 06:07.470
So let's do so by defining this function.

06:07.470 --> 06:11.010
It returns nothing, so it returns void.

06:11.220 --> 06:19.470
And this is a const function, meaning that it's not going to change the private attributes of the class.

06:19.470 --> 06:26.550
And as we just mentioned, this function receives as input the message that was just published in the

06:26.550 --> 06:27.450
chapter topic.

06:27.450 --> 06:35.160
So as we know, this is a standard message of type string.

06:35.920 --> 06:39.100
And let's call this variable message.

06:40.510 --> 06:47.980
In this function, every time a new message is received by the subscriber, we simply decide to print

06:47.980 --> 06:59.080
it in the terminal using the Rql CPP info stream function that is available in the CPP library.

06:59.410 --> 07:08.200
This function takes as input the logger scope which we obtain with the get logger function which we

07:08.200 --> 07:10.590
inherited from the node class.

07:10.600 --> 07:12.250
And it also takes the text.

07:12.250 --> 07:16.060
So the content of the message that we want to display in the terminal.

07:16.060 --> 07:24.250
So for example, let's display the message hi Earth, followed by the actual content of the message

07:24.250 --> 07:28.990
and so followed by the message data.

07:29.140 --> 07:32.740
And let's take this one into a string.

07:33.540 --> 07:37.320
With this, the simple subscriber class is completed.

07:37.320 --> 07:41.310
It's very simple and we can now define the main function.

07:41.310 --> 07:45.510
So the one that is automatically executed when we execute this node.

07:55.810 --> 08:04.390
Let's return zero If everything goes well and here as a first step, let's initialize Ros to use the

08:04.390 --> 08:05.440
init function

08:07.840 --> 08:16.840
and let's provide the arguments of the main and then let's create a pointer to an object of the simple

08:16.840 --> 08:20.560
subscriber class as our shared pointer named node

08:22.960 --> 08:26.230
and we use the make shared function.

08:31.140 --> 08:38.340
To create this shared pointer to an object of type simple subscriber.

08:40.880 --> 08:47.060
Then let's keep this node up and running, thus keeping the subscriber active to continuously receive

08:47.060 --> 08:50.010
messages that pass through the chatter topic.

08:50.030 --> 08:52.040
Using the spin function.

08:52.040 --> 09:00.680
So let's use the spin function and let's keep the node up and running.

09:01.330 --> 09:08.140
Finally, if we end the execution of the node with control C, let's ensure that the simple subscriber

09:08.140 --> 09:11.920
node is properly destroyed using the shutdown function.

09:11.920 --> 09:13.930
So rcl cp.

09:16.210 --> 09:17.140
Shuts down.

09:18.410 --> 09:19.490
To execute this node.

09:19.520 --> 09:26.060
First, we need to instruct the compiler on how it should build our script and make it an executable

09:26.060 --> 09:26.900
in Ros two.

09:27.320 --> 09:35.120
To do so as we did for the simple publisher, let's open the Cmakelists.txt file that is in the Arduino

09:35.330 --> 09:36.650
CPP examples.

09:36.950 --> 09:43.670
So here we can copy paste these two lines that we already used in order to install the simple publisher

09:43.670 --> 09:50.030
node and let's change the name of the executable into simple subscriber.

09:50.390 --> 09:56.450
Then the name of the script is still in the source folder and is called Simple Subscriber Dot CP.

09:56.780 --> 10:00.320
Let's also add the dependencies to this executable.

10:00.320 --> 10:03.800
So to the simple subscriber and the dependencies are the same.

10:03.800 --> 10:10.190
So we used basically the same libraries for the two nodes that are Rql CP and standard messages.

10:10.970 --> 10:15.230
And finally, for this list, we also need to declare the new executable.

10:15.230 --> 10:23.450
So the simple subscriber also here also in the install instruction and now above the node will be installed.

10:23.960 --> 10:29.930
With this, we have instructed the compiler on how it should install the simple subscriber node and

10:29.930 --> 10:32.630
we can proceed to rebuild our workspace.

10:32.780 --> 10:34.070
So to start the node.

10:34.220 --> 10:42.910
So let's open a new terminal and let's go to our workspace and here let's execute the command on build.

10:42.920 --> 10:45.380
So this will rebuild our workspace.

10:45.380 --> 10:53.060
And so also the new node that we created now to execute the publisher node, let's split the terminal.

10:53.060 --> 10:56.510
So let's open a new terminal, let's search the workspace.

10:56.870 --> 11:07.610
So the install setup dot bash and to start the node, let's use the command Ross to run and from the

11:07.610 --> 11:09.980
Arduino boot CP Examples package.

11:09.980 --> 11:15.950
If we press tab twice now, we can see that there are two nodes available the simple publisher and the

11:15.950 --> 11:17.060
simple subscriber.

11:17.210 --> 11:21.500
So let's run the simple subscriber node.

11:22.590 --> 11:29.520
We can actually verify that this node is up and running by opening a new terminal and using the command

11:29.520 --> 11:32.520
Ros2 topic list.

11:32.520 --> 11:38.220
And actually we can see that the chapter topic is there and also we can obtain more information on this

11:38.220 --> 11:42.450
topic with Ros2 topic info.

11:43.020 --> 11:46.020
Let's get more information about the chapter topic.

11:46.350 --> 11:53.700
Let's also add the flag verbose and we can see actually that there is only one node that is interacting

11:53.700 --> 11:59.730
with this topic and actually it's a subscriber node that is called Simple Subscriber.

12:01.600 --> 12:04.930
Now let's try to publish a new message on this topic.

12:04.960 --> 12:10.270
To observe that the node actually triggers an event upon receiving the message.

12:10.630 --> 12:16.690
To do so, we can use the command Ros2 topic poop to publish a message.

12:16.900 --> 12:21.040
Then let's specify the name of the topic where we want to publish the message.

12:21.160 --> 12:22.810
So the chatter topic.

12:22.900 --> 12:26.110
And then followed by the type of the message we want to publish.

12:26.200 --> 12:32.770
So if we press tab twice, we can see that Ros is able to automatically detect that in this topic are

12:32.770 --> 12:35.410
only accepted string messages.

12:35.740 --> 12:38.470
So let's use this type.

12:38.470 --> 12:40.900
So the standard message string.

12:41.020 --> 12:43.150
And then we need to specify the content.

12:43.150 --> 12:45.580
So which is the message that we want to publish.

12:45.850 --> 12:47.950
To do so, let's use the double quote.

12:47.980 --> 12:49.990
Let's press tab twice again.

12:49.990 --> 12:54.450
And we can see that here there is an empty prototype of this message.

12:54.460 --> 13:02.390
So let's use the data to publish an empty prototype of the message and let's print the message.

13:02.900 --> 13:05.210
Hello, Ros Choo.

13:05.510 --> 13:07.430
So let's press enter.

13:08.220 --> 13:14.130
And as we do so, we can see that we are constantly publishing the rescue message.

13:14.220 --> 13:21.060
If we stop to publish this message, the interesting thing that we can see is that our simple subscriber

13:21.090 --> 13:26.910
was able to receive all the messages that we were publishing and is displaying inside the terminal the

13:26.910 --> 13:27.960
content of the message.

13:27.960 --> 13:34.950
So this string allows us to that we were publishing here inside this topic.

13:35.430 --> 13:41.550
Finally, let me show you another interesting feature of Ros2, which makes this framework language

13:41.550 --> 13:47.190
agnostic, namely that it works in the same way, regardless of the programming language that is being

13:47.190 --> 13:47.820
used.

13:47.850 --> 13:55.200
So in this terminal window, so the one above, let's keep our C plus plus node that is the simple subscriber

13:55.200 --> 13:55.860
running.

13:55.860 --> 14:02.520
So listening on the chatter topic and here in the terminal below, let's start a new node.

14:02.520 --> 14:06.130
So the publisher node that we instead developed in Python.

14:06.150 --> 14:13.840
So let's source also in the terminal, the file setup dot bash, and then let's run the publisher node

14:13.840 --> 14:15.700
that we developed in Python.

14:15.700 --> 14:26.800
So with the Ros to run command from the Arduino board by examples, let's start the simple publisher

14:26.800 --> 14:28.960
node, let's press enter.

14:28.960 --> 14:32.980
And now in one terminal we have a node that we developed in Python.

14:32.980 --> 14:39.320
So this one below that is constantly publishing messages on the chatter topic at a frequency of one

14:39.320 --> 14:39.700
hertz.

14:39.700 --> 14:42.610
So it's publishing one message per second basically.

14:42.940 --> 14:49.570
And here instead in the terminal above, we have a node that is developed in C plus plus that we just

14:49.570 --> 14:56.230
developed that is listening on this topic and it is constantly printing any new message it receives.

14:57.060 --> 15:03.060
Among the other things, this is one of the advantages of using Ros2 to enable the communication between

15:03.060 --> 15:09.060
different nodes that perform different operations and potentially that are developed with different

15:09.060 --> 15:10.320
programming languages.

15:10.320 --> 15:15.990
And this is done without any effort from the developer of this node for the integration.
