WEBVTT

00:00.050 --> 00:05.810
Now that you understand what a ros2 topic is, let's create a publisher with Python.

00:05.810 --> 00:09.680
So what we are going to do here is we are first going to create a node.

00:09.680 --> 00:15.320
And in this node we're going to add a publisher that's going to publish some text twice per second on

00:15.320 --> 00:15.980
a topic.

00:15.980 --> 00:17.060
And how to get started.

00:17.060 --> 00:21.680
Well as I told you, we need to create a node because the publisher is going to be inside the node.

00:21.680 --> 00:23.630
And where do we create nodes?

00:23.630 --> 00:29.270
Well, we are going to go back to our roster workspace in the source folder.

00:29.270 --> 00:31.670
And then we already have a Python package.

00:31.670 --> 00:33.290
So I'm just going to use that one okay.

00:33.320 --> 00:38.150
For the examples we do in this course I'm going to go to my Python package.

00:38.150 --> 00:43.910
And inside this package I also have another folder with the same name okay.

00:43.940 --> 00:49.310
And you can simply see that we already have my first node.py.

00:49.340 --> 00:53.810
I've also added the template okay, that you could download from the section three.

00:53.810 --> 00:56.420
And we are going to create a new file.

00:56.420 --> 01:03.460
So I'm going to name it Robot News station dot p y.

01:03.490 --> 01:09.760
So the ID here is just to imagine we are creating a news station that's going to publish some text on

01:09.760 --> 01:10.420
a topic.

01:10.450 --> 01:10.630
Okay.

01:10.630 --> 01:11.680
Very simple example.

01:11.710 --> 01:17.770
So I create the file and I'm going to make it executable chmod plus x.

01:17.860 --> 01:24.700
That's because for the symlink install to work if you're going to use symlink install for installing

01:24.700 --> 01:28.990
your Python package you have to have the file executable.

01:29.020 --> 01:29.470
Great.

01:29.470 --> 01:35.500
So now we can go back here I'm going to open VSCode once again.

01:35.530 --> 01:38.260
I open it from the source folder of the workspace.

01:38.440 --> 01:42.010
And from there we can edit that file.

01:43.210 --> 01:49.840
So let's open the new file here the robot news station.

01:49.840 --> 01:52.000
And we have a blank page.

01:52.000 --> 01:55.030
But from now on we're going to use this template.

01:55.030 --> 01:59.900
So this is a template we have written in the section on nodes.

01:59.900 --> 02:04.580
So we can just take that template here and put it there.

02:04.610 --> 02:05.240
Okay.

02:05.240 --> 02:08.930
And the only thing we need to do is to modify the names.

02:08.930 --> 02:13.850
So the name of the class here and also the name of the node.

02:13.850 --> 02:23.330
So here my custom node is going to be let's name it Robot News Station node okay.

02:23.360 --> 02:25.550
And that's going to be the same here.

02:26.300 --> 02:29.600
And then I need to give a name to the node.

02:29.600 --> 02:35.210
So let's simply name it Robot News Station.

02:35.210 --> 02:40.070
And as you can see here already I'm using the same name for the file name here.

02:40.070 --> 02:44.960
And for the node name that's something that's quite common okay.

02:44.990 --> 02:46.400
Those are two different things.

02:46.400 --> 02:49.100
Once again this is the file name and this is the node name.

02:49.100 --> 02:51.590
But you can use the same if you want.

02:51.590 --> 02:55.490
Let's just remove those comments that are not needed.

02:56.240 --> 02:56.630
All right.

02:56.660 --> 02:57.850
And let's save the file.

02:57.880 --> 02:58.450
Great.

02:58.450 --> 02:59.800
And now we can start from this.

02:59.800 --> 03:05.470
So we have the imports here we have our class where we can write everything that's related to the node.

03:05.470 --> 03:09.730
And then we have the main function where we initialize ros2 communications.

03:09.730 --> 03:10.900
We start the node.

03:10.900 --> 03:13.930
We make the node spin and then shut down.

03:13.930 --> 03:17.770
And how to create a publisher and also where to create it.

03:17.800 --> 03:21.850
Well we're going to do that in the constructor of the class.

03:21.880 --> 03:22.060
Okay.

03:22.090 --> 03:26.590
So we have the class robot new station node here after the super.

03:26.590 --> 03:28.960
So the super is going to be the first line okay.

03:28.990 --> 03:32.020
After this I can create a publisher.

03:32.020 --> 03:37.990
So let's also do self dot publisher okay.

03:38.020 --> 03:43.090
We're going to save it as an attribute of the class and how to create a publisher.

03:43.090 --> 03:47.920
I'm going to do self dot create publisher.

03:47.920 --> 03:51.760
And as you can see I have the auto completion here okay.

03:51.760 --> 03:56.300
So I use the create publisher method from the node class.

03:57.050 --> 04:01.460
And if you remember from the previous video for a topic, we need two things.

04:01.460 --> 04:05.270
We need a name and we also need a data type.

04:05.270 --> 04:07.760
So what type are we going to use.

04:07.760 --> 04:11.000
Because you see we have to provide the type here as the first argument.

04:11.000 --> 04:15.200
And well here to get started I'm going to give you directly the type we're going to use.

04:15.200 --> 04:22.160
So there are already some data types for messages for topics that are existing and already installed

04:22.160 --> 04:23.360
for you to use.

04:23.390 --> 04:26.660
And then we will be able to also create our own types.

04:26.660 --> 04:32.390
But this is going to be the focus on one full section just a bit later in this course.

04:32.480 --> 04:36.350
So I'm just going to show you I'm going to go back to the terminal and I'm just going to show you,

04:36.380 --> 04:39.830
let's just clear that we have a comment.

04:39.860 --> 04:43.910
It's called Ross to Interface show.

04:43.970 --> 04:44.240
Okay.

04:44.270 --> 04:45.740
So still a rose to command line.

04:45.740 --> 04:52.010
And then interface show to display an interface that you can use and that's already installed.

04:52.010 --> 04:56.620
And you can type Example interfaces.

04:56.620 --> 05:04.840
You can press tab, you see, and you should have the auto completion and then MSG slash and then string

05:04.870 --> 05:07.600
with an S uppercase okay.

05:07.630 --> 05:11.470
If you type this and you press enter you see we have here.

05:11.470 --> 05:13.840
So it's found we have an interface.

05:13.840 --> 05:15.550
So we have an interface.

05:15.550 --> 05:19.750
We have a message called string which contains that.

05:19.750 --> 05:21.970
So we have a few commented lines you see.

05:21.970 --> 05:24.280
So you don't need to worry about those lines.

05:24.280 --> 05:26.800
And then we have string data.

05:26.830 --> 05:34.210
This means that we have a field named data inside this message and of type string.

05:34.210 --> 05:37.480
And this is exactly what we want for this topic.

05:37.480 --> 05:40.450
We want to publish a string on a topic.

05:40.450 --> 05:42.760
So we're going to use that message.

05:42.760 --> 05:45.640
So you see the example interface package.

05:45.640 --> 05:46.750
So that's a package.

05:46.750 --> 05:49.720
And that's an interface inside the package okay.

05:49.750 --> 05:52.060
So this package is quite useful for you to get started.

05:52.060 --> 05:58.520
So we can use all kinds of basic data types without having to create messages by ourselves, which is

05:58.520 --> 06:00.710
going to be the focus later in this course.

06:00.740 --> 06:06.680
So let's import that one inside our code and how to import that.

06:06.710 --> 06:12.890
Well we will need to do here from example interfaces.

06:12.890 --> 06:16.310
And as you can see it's also found because of the Ross extension.

06:16.310 --> 06:21.260
So from example interfaces dot msg.

06:21.710 --> 06:30.680
Okay we have an MSG folder that's for topics import and then string you see as uppercase.

06:30.680 --> 06:31.880
And it should be found.

06:32.060 --> 06:39.170
So now what I can do in my create publisher I can provide the message type which is string.

06:39.200 --> 06:39.500
Okay.

06:39.530 --> 06:41.270
That's the class here that I'm using.

06:41.270 --> 06:46.040
Now before we go further here, as you can see we have a new import.

06:46.070 --> 06:48.410
And the first import was RCL pipe.

06:48.440 --> 06:48.800
Okay.

06:48.830 --> 06:52.750
With rcl p we already had if I go to package XML.

06:52.750 --> 06:59.050
We already had a depend tag for this package for this dependency, but now we are using a new one.

06:59.050 --> 07:03.070
We are using the package named example interfaces.

07:03.070 --> 07:10.090
So because we are depending on a new package, I'm going to add the dependency to the package dot XML.

07:10.090 --> 07:18.790
So I'm going to add depend example interfaces just like that.

07:18.820 --> 07:19.300
Okay.

07:19.300 --> 07:26.440
So that will specify that this package Mypy pkg depends on the example interfaces.

07:26.860 --> 07:29.890
So I'm going to save and go back here.

07:29.890 --> 07:33.040
And that's basically it for the package dot XML.

07:33.070 --> 07:33.250
Okay.

07:33.280 --> 07:39.910
So whenever you import a new package here make sure you also add the depend tag on the package dot XML.

07:39.940 --> 07:40.330
Great.

07:40.330 --> 07:41.950
And now let's finish this publisher.

07:41.950 --> 07:44.410
So to create a publisher we have a data type.

07:44.410 --> 07:46.540
And we have a name okay.

07:46.570 --> 07:48.700
So what name do we use.

07:48.700 --> 07:54.680
Well here we can create a name Because we create a publisher, we can publish to whatever name we want.

07:54.680 --> 07:58.940
And as a reminder, you need to start the name with a letter.

07:58.970 --> 08:01.910
Then you can use some numbers, some underscores, etc..

08:01.910 --> 08:06.290
Here I'm going to name it Robot News just like that.

08:06.290 --> 08:10.550
And there is one more thing actually you need to add for the publisher.

08:10.550 --> 08:12.140
Otherwise you might get an error.

08:12.140 --> 08:14.930
You need to add a queue size.

08:14.930 --> 08:16.340
So I'm just going to put ten.

08:16.340 --> 08:24.290
So very basically that can be useful if you are going to publish let's say big messages like images

08:24.320 --> 08:30.410
that are very big or if you're going to publish very fast in a network, in a Wi-Fi network that's not

08:30.410 --> 08:35.510
very stable, maybe publishers and subscribers can't keep up with the messages.

08:35.510 --> 08:43.070
So this is going to create kind of a buffer so that the publisher can have a buffer of up to ten messages

08:43.070 --> 08:43.880
to send.

08:43.910 --> 08:44.390
Okay.

08:44.390 --> 08:47.660
So you can choose for example, one you could put ten 1000.

08:47.690 --> 08:49.810
Well it doesn't really matter at this point.

08:49.840 --> 08:50.110
Okay.

08:50.140 --> 08:56.650
As I told you, maybe if you have a lousy network or big messages, you're going to have to tweak this.

08:56.650 --> 09:01.690
But for everything we do in this course and most things you will do anyway with roster, you don't need

09:01.690 --> 09:02.680
to worry about that.

09:02.680 --> 09:04.810
So I'm just going to keep ten.

09:04.840 --> 09:05.290
Okay.

09:05.320 --> 09:07.540
For everything we do in this course.

09:07.570 --> 09:08.050
All right.

09:08.050 --> 09:09.760
And now we have our publisher.

09:09.760 --> 09:14.380
So create publisher with a data type and a name.

09:14.500 --> 09:18.070
The thing is this publisher is not going to do anything because we create the node.

09:18.070 --> 09:18.820
We have a publisher.

09:18.850 --> 09:19.120
Great.

09:19.120 --> 09:20.770
But it's not doing anything.

09:20.800 --> 09:25.150
I'm going to add another method in the class here.

09:25.180 --> 09:30.370
I'm going to call it for example publish news.

09:31.240 --> 09:39.250
And I need to put self because we are in a Python class and how to publish a message on that topic.

09:39.250 --> 09:40.870
Well, we need to do two things.

09:40.870 --> 09:45.160
First, we need to create the message and then we need to publish it.

09:45.160 --> 09:47.140
So let's create a message.

09:47.140 --> 09:49.140
We are going to use the string here.

09:49.170 --> 09:52.470
The string class and create a string object.

09:52.470 --> 09:56.250
Then inside this string I can do msg dot.

09:56.250 --> 09:59.370
We have you see msg dot data.

09:59.370 --> 10:00.600
Why data?

10:00.630 --> 10:08.730
Because if you remember in the interface we have a field named data which is of type string.

10:08.730 --> 10:13.980
So I will use a string here and let's just say hello.

10:14.010 --> 10:20.640
So I have created a message I have filled all the the fields of the message.

10:20.640 --> 10:22.050
So it's just one here.

10:22.050 --> 10:25.290
And then I can publish it using the publisher.

10:25.290 --> 10:31.560
So I will do self dot publisher dot publish.

10:32.010 --> 10:32.400
Okay.

10:32.430 --> 10:33.780
So it's quite simple.

10:33.780 --> 10:38.490
You publish and you publish what the message that you have just created.

10:38.610 --> 10:41.760
And that's how you publish a message on a topic.

10:41.760 --> 10:47.860
Now once again this code is not going to do anything because well we have a publisher, we have a function,

10:47.860 --> 10:49.510
but we don't call the function.

10:49.540 --> 10:51.340
So how to call the function?

10:51.340 --> 10:54.520
Let's say we want to call the function twice per second.

10:54.550 --> 11:00.760
Well, if you remember what we did previously when we created the first node we added a timer.

11:00.760 --> 11:03.370
So I'm going to add a timer here as well.

11:03.400 --> 11:05.680
Let's do self timer.

11:05.680 --> 11:08.950
So let's save it as also an attribute of the class.

11:08.950 --> 11:13.240
And we can do self dot create timer.

11:13.240 --> 11:16.150
As you can see I also created that in the constructor.

11:16.150 --> 11:19.120
And I will create it also after the publisher.

11:19.120 --> 11:24.100
So the author doesn't necessarily matter in this case okay.

11:24.130 --> 11:27.760
But you see I create a publisher and then I create a timer in the constructor.

11:27.760 --> 11:30.040
So self dot create timer.

11:30.070 --> 11:34.570
The first thing I need to provide is the timer period in second.

11:34.570 --> 11:39.430
So if I want to publish twice per second it means every 0.5 second.

11:39.430 --> 11:42.160
And then what is the function?

11:42.160 --> 11:46.860
What is the method that I need to call back for this timer that one.

11:46.890 --> 11:53.370
So self dot publish news with no parentheses.

11:53.760 --> 11:53.940
Okay.

11:53.940 --> 11:56.640
It's just the reference of the function.

11:56.640 --> 12:02.040
And with this code then that function is going to be called because.

12:02.040 --> 12:03.900
So we initialize Ros to communications.

12:03.900 --> 12:07.770
Then we create the node that's going to create the publisher and the timer.

12:07.770 --> 12:12.060
And then when the node is spinning the node is going to be kept alive.

12:12.090 --> 12:12.270
Okay.

12:12.300 --> 12:13.980
The program is going to be stuck here.

12:13.980 --> 12:15.600
So the node is kept alive.

12:15.600 --> 12:18.930
And we can execute all the callbacks for that node.

12:18.930 --> 12:24.900
And because we have a timer, then we will have a callback that will be triggered every 0.5 second.

12:24.900 --> 12:30.090
So that function will be executed every 0.5 seconds.

12:30.120 --> 12:31.320
That's it for the code.

12:31.320 --> 12:37.770
But there is one thing I like to do is after I finish the constructor here, you see there is no log.

12:37.770 --> 12:43.290
So when we start the node we will not see anything printed on the terminal.

12:43.290 --> 12:46.120
So what I like to do usually is to add a log.

12:46.120 --> 12:50.890
So self get logger info.

12:51.130 --> 12:54.430
And just to say that the node has been started.

12:54.430 --> 13:02.110
So let's say robot news station has been started okay.

13:02.140 --> 13:07.390
It could be just uh okay or whatever message, but I like to have a message at the end.

13:07.420 --> 13:09.550
So log at the end of the constructor.

13:09.580 --> 13:10.030
Great.

13:10.030 --> 13:13.300
And now it seems that the code is complete.

13:13.300 --> 13:17.560
What I will do is I will now install this executable.

13:17.560 --> 13:20.080
And to do that I will go to setup.py.

13:20.080 --> 13:26.380
And here you can see at the end we already have in the console script we have our first node.

13:26.380 --> 13:28.600
So I'm going to add a comma.

13:28.630 --> 13:30.130
That's very important here.

13:30.130 --> 13:33.370
Make sure you add a comma and then go back to a new line.

13:33.370 --> 13:35.920
And I will create a new executable.

13:35.920 --> 13:38.620
Now what name to give to the executable.

13:38.620 --> 13:43.140
Well I can name it for example Robot News Station.

13:43.140 --> 13:49.620
So here, as you can see, I'm going to use the same name for the executable, for the file name and

13:49.620 --> 13:51.000
for the node name.

13:51.030 --> 13:51.210
Okay.

13:51.210 --> 13:52.410
That's completely valid.

13:52.410 --> 13:55.350
Once again those are three different things.

13:55.350 --> 13:57.120
But I can use the same name.

13:57.750 --> 14:02.130
So robot new station is equal to what's the folder name.

14:02.130 --> 14:06.120
My pi pkg dot.

14:06.150 --> 14:07.560
What's the file name.

14:07.590 --> 14:08.160
Robot.

14:08.190 --> 14:13.350
New station use station without the extension.

14:13.350 --> 14:17.250
And then what is the function we want to call?

14:17.250 --> 14:23.130
Well it's always going to be main because I'm always going to use the the main with the node template.

14:23.130 --> 14:26.790
So we want to execute the main function.

14:27.360 --> 14:27.840
All right.

14:27.870 --> 14:29.190
As simple as that.

14:29.730 --> 14:34.410
And for every new executable you just add a comma and you create a new one here.

14:34.650 --> 14:38.070
It's not complicated if you ever make a mistake.

14:38.070 --> 14:42.790
For example, if you forgot the comma and then it's going to build something, but it's going to be

14:42.790 --> 14:44.590
weird and you're going to have some errors.

14:44.620 --> 14:44.980
Okay.

14:45.010 --> 14:46.930
In this case I recommend that.

14:46.930 --> 14:53.710
So you go to your workspace and if you have built something that is wrong I recommend that you remove

14:53.740 --> 14:55.960
those build install and log.

14:55.990 --> 14:56.170
Okay.

14:56.200 --> 15:00.160
So our m r build install log.

15:00.160 --> 15:05.590
So in case you mess up with something and you build it, then you can always remove everything that's

15:05.590 --> 15:07.210
going to be a bit cleaner.

15:07.240 --> 15:08.020
Okay.

15:08.500 --> 15:10.450
But now we don't have any mistakes.

15:10.450 --> 15:12.370
So let's save all the files.

15:12.370 --> 15:14.320
Let's make sure we have saved all the files.

15:14.320 --> 15:16.660
You see, we should have crosses here on VSCode.

15:16.660 --> 15:18.160
And let's go back.

15:18.160 --> 15:25.450
And once again, let's go back to our roster workspace and let's do a call on build with I'm going to

15:25.450 --> 15:32.200
do packages select with my pi pkg.

15:32.200 --> 15:42.150
And I'm also going to use the symlink install so that I don't need to compile This anymore.

15:42.450 --> 15:45.930
So I need to use I need to compile it first once.

15:45.960 --> 15:48.120
At least with the Simulink install option.

15:48.120 --> 15:55.260
But then if I modify this file here, I should be able to run it without installing it again.

15:55.260 --> 15:55.620
Great.

15:55.620 --> 15:57.480
So it has been built.

15:57.480 --> 16:02.970
What I'm going to do is I'm going to open a new terminal so that I have everything correctly sourced.

16:03.120 --> 16:07.560
Let's just split that for example, and let's run our publisher.

16:07.560 --> 16:14.730
So let's run the node which contains a publisher Ros to run my Pi PG.

16:14.730 --> 16:17.130
And if I press tab twice, you see that.

16:17.130 --> 16:19.530
Now I have two executables.

16:20.070 --> 16:22.590
I have the first one that I've created and Robot New Station.

16:22.590 --> 16:26.430
So I can start robot new station using the auto completion.

16:26.670 --> 16:32.310
And you see so we have this log robot news station has been started.

16:32.490 --> 16:36.870
Now I can use the rose two command line tools that we have seen previously.

16:36.870 --> 16:46.810
For example Ros two Not least I see I have my robot news station Ros2 node info with robot news station.

16:46.840 --> 16:54.940
Don't forget the slash and well, we have a bunch of stuff, but you can see on the publishers we have

16:54.970 --> 16:57.070
robot news.

16:57.100 --> 16:59.350
Okay, you can see there is added slash okay.

16:59.380 --> 17:02.140
There is no slash in the code.

17:02.440 --> 17:02.590
Okay.

17:02.620 --> 17:03.910
You don't need to provide a slash.

17:04.000 --> 17:07.930
If you don't it's going to add automatically a slash for you.

17:07.930 --> 17:16.480
And so you see we have the robot news topic with the string interface from the example interfaces package.

17:16.480 --> 17:21.100
Now to be able to see what we published we need a subscriber.

17:21.100 --> 17:23.020
So we will need to write a subscriber.

17:23.020 --> 17:27.400
But before we do that I'm going to show you there is another command line.

17:27.400 --> 17:31.420
And I'm going to come back to this also in a dedicated lesson in this section.

17:31.480 --> 17:35.710
So we have Ros2 topic list.

17:36.010 --> 17:43.800
If you do Ros2 topic list, you can see we have the robot news topic and if I do rose to topic equal

17:43.830 --> 17:51.960
with the name of the topic here with slash robot News, then I can basically create a subscriber and

17:51.960 --> 17:56.700
I can display what we receive on that topic directly in the terminal.

17:56.700 --> 17:59.100
So make sure that the publisher is running here.

17:59.100 --> 18:01.860
And then you should see that we receive data.

18:01.890 --> 18:02.340
Hello.

18:02.340 --> 18:02.790
Hello.

18:02.790 --> 18:05.280
Every 0.5 seconds okay.

18:05.310 --> 18:07.560
And well it's still receiving.

18:07.560 --> 18:09.900
Now if I kill the publisher.

18:10.170 --> 18:13.440
You see now we don't receive any more data.

18:13.440 --> 18:19.320
So we can see that what we receive here was directly published by that node right here.

18:19.500 --> 18:22.770
And I'm just going to finish with a slight improvement.

18:22.770 --> 18:30.450
So let's say we want to say hi this is and then a name.

18:30.450 --> 18:36.030
So for example C-3po from the Robot News.

18:37.480 --> 18:38.440
station.

18:39.070 --> 18:44.140
And let's also say that instead of hard coding this, I'm going to use a variable.

18:44.140 --> 18:53.380
So I'm going to do this self dot robot name is equal to C-3po.

18:53.980 --> 18:55.630
And then I can use.

18:56.440 --> 19:03.700
So I can use this plus self robot name plus.

19:04.030 --> 19:04.450
All right.

19:04.450 --> 19:08.080
So I construct a string and I put this attribute here.

19:08.080 --> 19:12.010
So that also later on we will see ways to modify that.

19:12.010 --> 19:13.540
Let's save.

19:13.540 --> 19:16.600
And because I have built the workspace with Simulink install.

19:16.600 --> 19:21.220
So this package with Simulink install I should be able to run again.

19:21.220 --> 19:23.830
And we should see you see.

19:23.860 --> 19:27.670
Hi, this is C-3po from the robot news station.

19:27.700 --> 19:30.430
Okay, so now we have the new data.

19:30.460 --> 19:31.240
Great.

19:31.240 --> 19:35.770
And you have created your first Python publisher in Ros two.
