WEBVTT

00:00.520 --> 00:07.540
In this laboratory lesson, we will implement our first rose to node in Python that will use the publisher

00:07.540 --> 00:12.820
subscriber communication protocol to publish a message within a ros2 topic.

00:13.210 --> 00:18.790
If you are only interested in the cplusplus software development, then you can skip directly to the

00:18.790 --> 00:24.430
next lesson where we will implement the same node with the same functionalities in C plus plus.

00:25.150 --> 00:28.300
Let's start by opening Visual Studio code.

00:28.300 --> 00:31.710
And here let's open the robots workspace.

00:31.720 --> 00:36.490
So let's open the folder that is called Arduino Bot Workspace.

00:39.170 --> 00:42.980
Inside the workspace within the source folder.

00:44.250 --> 00:51.900
So here we created already the two packages, Arduino bot, CP examples and the Arduino bot Pi examples

00:51.900 --> 00:59.100
with the Ros two package create command in the previous lesson and this already created also several

00:59.100 --> 01:02.550
folders and several files within the two packages.

01:03.250 --> 01:11.920
The files and the folder created in the Arduino Pi example is the typical structure of any Python package

01:11.920 --> 01:13.390
used in Ros2.

01:13.480 --> 01:16.960
So there is a sub folder which has the same name of the package.

01:16.960 --> 01:22.240
So in this case Arduino Pi examples and this will contain the source code.

01:22.240 --> 01:25.840
So all the Python scripts that we are going to develop.

01:25.840 --> 01:36.640
So here let's create also a new file and let's call it simple publisher dot pi to indicate that it is

01:36.640 --> 01:38.890
a python file here.

01:38.890 --> 01:43.390
Let's start by importing the Pi library.

01:46.020 --> 01:51.730
Which will allow us to use all the ros2 functionalities within our Python script.

01:51.750 --> 01:56.670
Then still from the rql py library.

01:56.700 --> 01:59.610
This time from the node module.

01:59.610 --> 02:07.560
Let's import the node class and we can use this class to create a new ros2 node.

02:07.740 --> 02:18.540
So let's create a new class called for example Simple publisher and let's make this class inherit from

02:18.540 --> 02:21.690
the node class of the Pi library.

02:22.170 --> 02:26.100
So in this class, let's first define the constructor of the class.

02:26.100 --> 02:32.250
So the function that is automatically executed when a new object of the class is created.

02:33.120 --> 02:36.150
So this is called the init function.

02:39.320 --> 02:40.370
And here.

02:40.370 --> 02:47.330
So when we initialize a new object of type simple publisher, the first thing we do is to initialize

02:47.330 --> 02:49.520
the components of the base class.

02:49.520 --> 02:55.670
So namely the components of the node class from which the simple publisher is inheriting.

02:55.850 --> 03:05.900
So let's call the super init that will call the constructor of the node class and let's assign a name

03:05.900 --> 03:11.570
to our node that we call Simple Publisher.

03:12.440 --> 03:19.130
Now that we have initialized the Ros two node class, let's create a new publisher object.

03:19.160 --> 03:21.020
So let's create a new variable.

03:24.120 --> 03:26.940
And to initialize a publisher object.

03:26.970 --> 03:33.930
Let's use the create publisher function that is defined in the node class from which we are inheriting.

03:34.410 --> 03:36.960
So let's use the create.

03:39.030 --> 03:40.440
Publisher function.

03:40.560 --> 03:44.220
And in this function we need to indicate the message type.

03:44.220 --> 03:49.650
So the type of the interface that we need to use for the message exchange with the topic.

03:49.770 --> 03:56.880
In practice, we need to specify which type of messages the publisher object will send through the topic.

03:57.150 --> 04:02.280
For example, let's say that we want to send text messages, so we want to send strings.

04:02.640 --> 04:08.640
The string message is contained, is defined in another Ros two library.

04:08.850 --> 04:17.080
So let's import it from the standard messages library from the messages that are defined in this library.

04:17.100 --> 04:20.820
Let's import the string message.

04:22.770 --> 04:30.990
And let's use it to indicate that within the create publisher function we are going to use string messages

04:30.990 --> 04:33.000
to interact with the topic.

04:33.750 --> 04:39.390
We also need to specify the name of the topic in which we want the messages to be published.

04:39.420 --> 04:43.290
So, for example, let's call this one chatter.

04:43.710 --> 04:49.320
Furthermore, we also need to indicate the size of the queue, namely the size of the message queue

04:49.350 --> 04:51.000
that works as a buffer.

04:51.000 --> 04:55.890
If the subscriber to this topic is not receiving and processing messages fast enough.

04:56.530 --> 04:58.900
Let's set this 1 to 10.

04:59.800 --> 05:06.460
Let's add some more supporting variables to the simple publisher class, and let's call the first one,

05:06.490 --> 05:14.140
the variable counter that we initialize to zero, and it will count the number of messages that we are

05:14.140 --> 05:16.060
going to publish within the topic.

05:16.330 --> 05:19.540
Then let's also define a frequency variable

05:22.840 --> 05:29.590
that we initialize to 1.0, so to one hertz, and this one will define the frequency at which we want

05:29.590 --> 05:32.080
to publish messages within the topic.

05:32.080 --> 05:35.650
So we are going to publish them at a frequency of one hertz.

05:35.650 --> 05:40.270
So we are going to publish one message per second within the chapter topic.

05:41.150 --> 05:44.090
At this point during the initialization of the node.

05:44.120 --> 05:50.210
Let's also print an informative message in the terminal using the get logger function, which we are

05:50.210 --> 05:52.940
still inheriting from the node class.

05:53.690 --> 05:58.220
So let's use the get logger function.

05:58.220 --> 06:04.440
And then from this one let's use the info function to print an informative message in the terminal.

06:04.460 --> 06:09.770
And the message says publishing at.

06:11.360 --> 06:14.630
And then the number of earths that we are using.

06:14.630 --> 06:20.210
So followed by the variable frequency.

06:21.520 --> 06:28.300
Lastly, inside the constructor of the Simple Publisher class, let's also create a new timer object

06:28.330 --> 06:30.790
using the create timer function.

06:30.790 --> 06:35.260
So let's call this one timer.

06:35.650 --> 06:42.490
And still from the node class, let's use the create timer function.

06:43.550 --> 06:50.750
So they create timer function takes as input the frequency at which we want to execute a certain function

06:50.750 --> 07:00.260
and we store this one in the frequency variable and it also takes the name of the function to be executed

07:00.260 --> 07:01.880
at regular time intervals.

07:01.880 --> 07:10.430
So at each expiration of the timer, so at a frequency of one hertz and let's call this function timer

07:11.390 --> 07:12.350
callback.

07:12.800 --> 07:18.620
With this, the constructor of the simple publisher class is completed and we can proceed to define

07:18.620 --> 07:24.410
the timer callback function, which will be the one that is repeatedly executed with a frequency of

07:24.410 --> 07:26.600
one hertz by the timer object.

07:26.750 --> 07:32.630
So let's define this function, the timer callback function.

07:32.870 --> 07:39.800
And this is a member of the simple publisher class and the goal is to publish a new message within the

07:39.800 --> 07:42.650
chapter topic every time this function is called.

07:42.650 --> 07:46.110
So every time this function is executed by the timer.

07:47.190 --> 07:52.590
So here, let's start by creating a new message to be published within the topic.

07:52.590 --> 07:57.150
So let's call this variable message and this is of type string.

07:57.150 --> 08:02.100
So from the string interface that is defined in the standard messages.

08:02.250 --> 08:15.360
And now let's publish, for example, the message that says Hello Ross to and then let's also print

08:15.780 --> 08:17.130
the counter.

08:19.500 --> 08:25.200
And so let's print the variable that we called counter.

08:27.030 --> 08:32.970
Then with this done, we can use the publish function of the publisher object.

08:32.970 --> 08:35.280
So of this object here.

08:37.850 --> 08:43.820
Let's call the publish function to publish the message we just created.

08:43.820 --> 08:46.220
So the variable MSG.

08:46.850 --> 08:53.330
And then once we have published the message within a topic, let's also increment the counter variable

08:53.360 --> 08:56.960
by one since we have just published a new message.

09:02.490 --> 09:03.330
With this.

09:03.330 --> 09:09.480
The simple publisher class is complete and now we can proceed to define the main function.

09:09.480 --> 09:14.250
And so the one that is automatically called upon the execution of this script.

09:14.430 --> 09:15.210
So.

09:20.870 --> 09:25.160
And here let's call the main function.

09:25.160 --> 09:27.110
So let's execute the main function.

09:27.110 --> 09:31.730
But first let's define this main function.

09:32.400 --> 09:40.550
And here as our first step, let's initialize rows using the init function from the PY library.

09:40.560 --> 09:43.230
So from rql py.

09:44.040 --> 09:50.970
Let's use the init function to instantiate the communication with rows and then let's create a new object

09:50.970 --> 09:53.010
of the simple publisher class.

09:53.010 --> 10:01.830
So let's call this variable simple publisher and is an instance of the simple publisher class and let's

10:01.830 --> 10:03.330
keep this node up and running.

10:03.330 --> 10:09.600
So keeping the timer and the publisher active so that they can continuously send messages within the

10:09.600 --> 10:10.770
chapter topic.

10:10.770 --> 10:20.220
And to do so we can use still from the PY library the spin function to keep the simple publisher node

10:20.220 --> 10:21.300
up and running.

10:21.660 --> 10:27.720
Finally, if we terminate the execution of the node by pressing Ctrl Z in the terminal, we need to

10:27.720 --> 10:31.110
ensure that also the simple publisher node is properly destroyed.

10:31.470 --> 10:38.800
So let's call the function destroy node on the simple publisher function.

10:38.800 --> 10:43.030
And also in this case, let's shut down Ros two.

10:43.750 --> 10:45.910
Let's save this script.

10:45.910 --> 10:52.270
And now in order to execute this node, we first need to instruct the compiler on how it should build

10:52.270 --> 10:55.180
our script to make it an executable in Ros.

10:55.180 --> 10:55.540
To.

10:56.110 --> 11:03.790
To do so, we need to modify another file that was automatically created within the Arduino bot Pi examples

11:03.790 --> 11:04.450
package.

11:04.450 --> 11:07.180
And this is the Setup.py file.

11:07.700 --> 11:14.390
You can think of this file as a kind of instruction sheet that tells the compiler how to translate our

11:14.390 --> 11:17.090
Python scripts into executable files.

11:18.220 --> 11:24.130
To do this in the entry points section in the console script list.

11:24.160 --> 11:26.440
Let's add a new executable.

11:26.440 --> 11:33.490
So here, let's add a new one and let's call this one simple publisher.

11:33.640 --> 11:44.670
And the script that we want to install is located within the Arduino Boot Pi examples folder.

11:44.680 --> 11:49.900
Then within the simple publisher file.

11:49.900 --> 11:52.360
And from this one we want to start.

11:52.360 --> 11:57.280
So we want the starting point to be the main function.

11:57.730 --> 12:00.130
So let's save also this file.

12:00.130 --> 12:06.100
And finally, before actually building the workspace and starting the node, we also need to declare

12:06.100 --> 12:07.840
the dependencies of the new node.

12:07.840 --> 12:12.400
So namely, we need to declare the libraries that it uses for its execution.

12:12.980 --> 12:18.650
To do this, we need also to modify the file that was automatically created and that is called package

12:18.650 --> 12:23.510
dot XML and that is still in the Arduino dot pi example package.

12:24.250 --> 12:24.820
Here.

12:24.820 --> 12:29.920
We need to add some dependencies, some execution dependencies.

12:30.940 --> 12:38.410
And let's start by adding the one from the Pi library, which we used in our script and which allowed

12:38.410 --> 12:42.160
us to use all the functionalities within the Python script.

12:42.870 --> 12:52.650
Also, let's add another exec dependency from the standard messages library from which we use the declaration

12:52.680 --> 12:54.300
of the string message.

12:54.960 --> 12:57.240
Let's save also this file.

12:57.240 --> 13:03.240
And these are the only two libraries that we need in the simple PowerShell script so we can finally

13:03.240 --> 13:04.500
execute our node.

13:04.620 --> 13:06.660
So let's open a new terminal.

13:06.900 --> 13:14.760
Let's go to the workspace and let's run the command on build.

13:16.350 --> 13:21.030
So this will build the entire workspace again, including also the new node.

13:21.180 --> 13:26.370
And now to execute the node, let's split the terminal.

13:26.400 --> 13:28.120
So let's take another terminal.

13:28.140 --> 13:30.150
Here, let's source the workspace.

13:30.300 --> 13:36.480
So let's source the file setup dot bash that is in the install folder.

13:37.130 --> 13:41.090
And this way the Arduino board by example is recognized.

13:41.090 --> 13:45.770
And so we can execute now the script, the nodes that it contains.

13:46.560 --> 13:55.230
To start a ros2 node, we can use the command Ros to run followed by the name of the package where the

13:55.230 --> 14:04.290
node is located, which in our case is the Arduino bot pi examples so we can use Tab to exploit the

14:04.290 --> 14:06.000
Ros2 Autocompletion.

14:06.370 --> 14:11.940
Then if we press tab twice we can see that the simple publisher node is recognized.

14:12.030 --> 14:15.780
So let's execute the simple publisher node.

14:15.780 --> 14:18.690
So let's press enter to start the node.

14:18.690 --> 14:26.760
And as you will see, it appears the message publishing at one hertz in the terminal and to verify that

14:26.760 --> 14:34.590
indeed the node is publishing a message within the charter topic, we can split our terminal again and

14:34.590 --> 14:41.310
we can take a look at all the topics that are currently available in Ros2 with the command Ros2.

14:43.330 --> 14:45.150
Topic list.

14:45.160 --> 14:47.110
So let's press enter.

14:47.110 --> 14:53.560
And as the name of the command suggests, it will show all the topics available in Russia at this moment.

14:53.560 --> 15:00.130
And among these topics, we can see that it appears the chapter topic, which is exactly the name we

15:00.130 --> 15:02.620
gave to the topic in the publisher node.

15:03.280 --> 15:09.850
If we stop, for example, the execution of our publisher node and we execute again, the command Ros2

15:09.880 --> 15:10.840
topic list.

15:11.020 --> 15:17.320
Now, as you can see, the chatter topic is no longer available since the node that was publishing messages

15:17.320 --> 15:19.060
on it is no longer running.

15:19.240 --> 15:27.220
So let's relaunch the node again and let's use again the Ros2 topic list and the chatter topic is back

15:27.220 --> 15:27.910
on track.

15:28.180 --> 15:34.570
We can also take a look at which are the messages that are currently traveling within this topic using

15:34.570 --> 15:42.330
the command Ros2 topic Echo followed by the name of the topic, which is chatter.

15:42.340 --> 15:50.020
So let's press enter and all the messages that are now published within this topic are now printed in

15:50.020 --> 15:50.860
the terminal.

15:50.860 --> 15:58.150
And so we can see that each message contains the string l0 ros2 followed by the counter that is increasing

15:58.150 --> 16:00.730
at each new message that is being published.

16:01.590 --> 16:08.010
Now, if we stop again, the execution of the node, we can see that there are no new messages published

16:08.160 --> 16:14.430
within the topic and it will restart as we restart here the node.

16:16.200 --> 16:23.130
There are other two useful ros2 commands that we can use to provide additional information about a topic,

16:23.130 --> 16:31.530
and these are ros2 topic info still followed by the name of the topic from which we want to obtain more

16:31.530 --> 16:32.160
info.

16:32.700 --> 16:34.890
So for example the chatter topic.

16:35.830 --> 16:40.030
And here we can see the type of the message that is being published.

16:40.180 --> 16:47.350
And also, if we use the verbose flag, we get even more information about it.

16:47.350 --> 16:54.520
So for example, we get the name of which Node is interacting with this topic that in this case is the

16:54.520 --> 16:56.200
simple publisher node.

16:57.150 --> 17:04.330
Finally, the last command that we are going to use in this lesson is the Ros2 topic.

17:04.920 --> 17:08.220
Earth's still followed by the name of the topic.

17:08.220 --> 17:15.270
So chatter, let's press enter and this command analyzes the messages that are published in the chatter

17:15.270 --> 17:19.310
topic and calculates the frequency at which they are published.

17:19.320 --> 17:25.920
In this case, as we can see, it is calculating a frequency so an average rate of one hertz, which

17:25.920 --> 17:30.810
is exactly the value that we set for the timer in the Visual Studio code.

17:30.810 --> 17:34.430
So here we set the frequency of one hertz.
