WEBVTT

00:00.050 --> 00:06.320
Let's now create a subscriber to listen to the publisher we have just created in the previous lesson.

00:06.320 --> 00:12.230
So we will create a node for a smartphone here and inside it create a topic subscriber.

00:12.260 --> 00:17.720
As you can guess, a node which is handling a smartphone can have many features such as reading and

00:17.720 --> 00:23.300
publishing the battery state, sending a text message to a contact, increase or decrease the speaker

00:23.300 --> 00:30.380
volume, etc., etc. the subscriber that we create here is one part is just one part of this node.

00:30.380 --> 00:34.400
So let's go back to our workspace source.

00:34.400 --> 00:37.670
And then in the Python package again.

00:38.150 --> 00:43.790
And there we have the robot new station I will create.

00:44.270 --> 00:55.580
So I will create a smartphone dot Pi and make it executable okay for the Simulink install to work.

00:56.720 --> 01:02.570
Also if you have a you see if you have a Pi cache folder like that, you might want to remove it.

01:03.260 --> 01:03.440
Okay.

01:03.460 --> 01:05.470
We don't really need that.

01:06.190 --> 01:06.610
All right.

01:06.610 --> 01:11.770
So now we have our file here and we can open VSCode again.

01:11.770 --> 01:13.420
So it was already open here.

01:14.140 --> 01:16.300
Let's go to smartphone Dot Pi.

01:16.300 --> 01:23.230
And let's use the template again in smartphone dot Pi.

01:24.040 --> 01:24.430
Okay.

01:24.460 --> 01:34.330
So we have my custom node that's going to become smartphone node which inherits from node and then smartphone

01:34.330 --> 01:35.830
node here again.

01:35.830 --> 01:37.990
And let's keep things simple.

01:37.990 --> 01:40.870
Let's name the node smartphone.

01:40.870 --> 01:42.760
And maybe I've said that already.

01:42.760 --> 01:43.270
Maybe not.

01:43.270 --> 01:48.640
But don't name your nodes for example smartphone node okay.

01:48.670 --> 01:51.040
Because it's already a node name okay.

01:51.070 --> 01:54.250
So you don't say it's the smartphone node node.

01:54.280 --> 01:57.340
You say it's the smartphone node okay.

01:57.370 --> 02:00.370
So don't add underscore node or something like that.

02:00.370 --> 02:03.190
You might see this in existing packages okay.

02:03.220 --> 02:05.990
But that's basically not a good practice.

02:06.020 --> 02:07.580
All right, let's modify.

02:08.210 --> 02:10.640
Let's remove the modify commands.

02:10.640 --> 02:13.880
And we are done with the node structure.

02:13.880 --> 02:16.670
So you can see once we use the template it's very easy.

02:16.670 --> 02:18.800
Just make sure you correctly understand this template.

02:18.830 --> 02:22.670
Of course now we are going to create a Python subscriber.

02:22.670 --> 02:25.550
Where do we create the subscriber.

02:25.580 --> 02:29.780
Well we are also going to create it here in the constructor.

02:29.780 --> 02:32.540
And of course after the super.

02:33.170 --> 02:39.200
So let's do self dot subscriber I'm going to save it as an attribute of the class.

02:39.260 --> 02:41.390
And we do self dot.

02:41.570 --> 02:47.180
And once again we're going to use the functionalities of the node class create sub.

02:47.180 --> 02:50.270
And you see we have create subscription.

02:50.270 --> 02:54.260
So it's not create subscriber it's create subscription.

02:54.260 --> 03:00.350
Then I open the parentheses and you see the first thing again that we need to provide is the message

03:00.350 --> 03:01.100
type.

03:01.100 --> 03:07.010
So message type that's going to be the same as the one we have on the publisher okay.

03:07.040 --> 03:12.580
If you want a publisher and a subscriber to be able to communicate, then you need to use the exact

03:12.580 --> 03:14.320
same message type.

03:14.320 --> 03:19.780
And in the previous lesson I've already explained to you what is this example interfaces message with

03:19.780 --> 03:20.350
the string.

03:20.350 --> 03:22.630
So we're going to use the exact same here.

03:22.630 --> 03:32.860
So from example interfaces dot msg import string okay.

03:32.860 --> 03:38.950
Just make sure that it's the exact same here between the publisher and the subscriber.

03:38.950 --> 03:45.280
And then as we use the example interfaces we make sure that in package dot XML we have the dependency

03:45.280 --> 03:50.020
which I already set that because I wrote the publisher before.

03:50.950 --> 03:51.400
Great.

03:51.400 --> 03:54.850
So now I can provide string.

03:54.940 --> 03:57.010
Then I need to give the topic name.

03:57.010 --> 04:03.940
And here again it is very important that you use the same topic name for the publisher and the subscriber,

04:03.940 --> 04:09.460
because if you use the wrong name, then this is going to publish to one topic.

04:09.490 --> 04:15.600
This is going to to try to receive data from another topic and then the communication will not work.

04:15.600 --> 04:22.440
So make sure here I'm just going to copy robot News and paste it here to make sure it's the same name.

04:22.470 --> 04:23.100
All right.

04:23.100 --> 04:30.120
And then after that you see we need to provide a callback because, well, a publisher, when you have

04:30.120 --> 04:32.820
a publisher you decide when to publish.

04:32.820 --> 04:34.860
So in this case you create a publisher.

04:34.860 --> 04:41.760
And when you want to publish, you do publisher dot publish, but a subscriber doesn't know when it's

04:41.760 --> 04:44.040
going to receive messages, okay.

04:44.070 --> 04:47.250
It's going to receive messages when the publisher is publishing it.

04:47.250 --> 04:50.580
But on the subscriber side, we have no control over that.

04:50.580 --> 04:56.490
So that's why we're going to provide a callback function that's going to be called whenever we receive

04:56.520 --> 04:57.630
a message.

04:57.660 --> 05:01.770
And so let's create a function here a method inside the class.

05:01.800 --> 05:07.200
And let's name it Callback robot news with self.

05:07.200 --> 05:09.810
And we are going to receive a message.

05:09.810 --> 05:14.750
I can also use a colon here And type string.

05:14.780 --> 05:16.880
Okay, that's not mandatory.

05:16.880 --> 05:17.990
That's optional with Python.

05:17.990 --> 05:23.690
But this way you make the type a bit more explicit, which is, I would say, never a bad thing.

05:23.720 --> 05:26.930
And so you see I named this function.

05:26.930 --> 05:33.950
You can name it as you want, but usually for subscriber callbacks I will start with callback and then

05:33.950 --> 05:35.750
the name of the topic.

05:35.870 --> 05:36.410
Okay.

05:36.440 --> 05:37.460
First callback.

05:37.460 --> 05:42.140
Because then it's a good way not to make mistakes in the future because you don't want to call this

05:42.140 --> 05:44.030
function by yourself from the class.

05:44.060 --> 05:44.210
Okay.

05:44.240 --> 05:46.880
This is something that's going to be called automatically.

05:46.880 --> 05:49.130
And then this is to recognize the topic.

05:49.130 --> 05:53.180
So when we receive a message what do we do with that message.

05:53.210 --> 05:54.560
Well you can do whatever you want here.

05:54.560 --> 05:55.910
We are just going to print it.

05:55.910 --> 06:02.870
So self dot get logger and then info message.

06:02.870 --> 06:04.760
And actually we don't just print the message.

06:04.760 --> 06:06.170
The message is an object.

06:06.200 --> 06:10.670
We're going to print the message dot data.

06:10.670 --> 06:16.280
And you see I have the auto completion here because I have provided the type string and message dot

06:16.310 --> 06:23.030
data once again, because in you see in the string object we have a data field.

06:23.300 --> 06:24.680
So that's why it's data.

06:24.680 --> 06:26.060
So we just print it.

06:26.060 --> 06:31.280
But for example I don't know let's say you have let's say this is a temperature sensor that's going

06:31.310 --> 06:34.820
to publish the temperature of whatever in your robot.

06:34.850 --> 06:40.250
Then this could be a node that monitors the temperature of several sensors.

06:40.250 --> 06:44.330
And then if the temperature is too high, maybe you need to take some actions.

06:44.330 --> 06:48.950
So in this case in this callback you could monitor the temperature.

06:48.950 --> 06:53.990
And if it's too high then you could well you could do whatever you want and take some actions here from

06:53.990 --> 06:54.650
that node.

06:54.650 --> 06:55.100
Great.

06:55.100 --> 06:56.870
So we have the callback.

06:56.900 --> 06:59.270
You can see just one line here.

06:59.270 --> 07:02.690
We need to provide the callback here in the create subscription.

07:02.690 --> 07:07.850
So I'm going to do self dot callback robot news.

07:07.850 --> 07:13.250
And finally we have one last parameter here which is the queue size.

07:13.250 --> 07:16.520
So exact same thing as for the publisher.

07:16.670 --> 07:19.180
We have a queue size just in case.

07:19.210 --> 07:20.740
Well, there are too many messages.

07:20.740 --> 07:22.000
Messages are too big.

07:22.000 --> 07:27.610
The network is lossy, so you have kind of a buffer and make sure that the messages can arrive.

07:27.640 --> 07:27.880
All right.

07:27.910 --> 07:33.880
So we have here the data type the name the callback and the queue size.

07:33.910 --> 07:37.840
Now this line is quite long I'm just going to do this okay.

07:37.870 --> 07:39.160
To make it a bit more readable.

07:39.160 --> 07:42.310
And that's it for the code for the subscriber.

07:42.310 --> 07:46.870
So what's going to happen is that once again you initialize rows to communications.

07:46.870 --> 07:48.070
Then you create the node.

07:48.070 --> 07:50.770
When you create the node you're going to create a subscriber.

07:50.770 --> 07:55.330
When you create a subscriber, you see we register a callback and then you make the node spin.

07:55.330 --> 07:57.250
So the node is spinning.

07:57.250 --> 07:58.990
We stop the execution here.

07:58.990 --> 08:02.530
The node is still alive and it can process any callbacks.

08:02.530 --> 08:08.770
So this callback is going to be processed when we receive a message from a publisher somewhere else.

08:08.770 --> 08:10.210
So whenever a publisher.

08:10.210 --> 08:15.880
So for example that one is publishing a message on the robot news topic with the string data type,

08:15.880 --> 08:18.040
then this callback is going to be called.

08:18.040 --> 08:23.980
And we receive the message and we can process it inside the node, and this is going to last as long

08:23.980 --> 08:24.910
as the node is alive.

08:24.910 --> 08:28.870
So until we press Ctrl C let's save.

08:28.900 --> 08:32.680
And then let's go back to the terminal and let's go back to.

08:32.710 --> 08:35.890
So let's go back to the roster workspace.

08:35.890 --> 08:42.190
And even though we used Simulink install before, the thing is here this is a new file.

08:42.190 --> 08:44.050
This is going to be a new executable.

08:44.050 --> 08:46.000
So we need to build it anyway.

08:46.180 --> 08:51.280
And actually to build it it's going to be better if we add the instruction to build it.

08:51.280 --> 08:54.280
So here I'm going to add another comma.

08:54.430 --> 08:56.920
And then let's call it smartphone.

08:56.920 --> 09:00.040
That's going to be the name of the executable is equal.

09:00.040 --> 09:04.420
My pi pkg dot.

09:04.900 --> 09:07.030
Uh the name is smartphone dot pi.

09:07.060 --> 09:09.520
So smartphone.

09:09.670 --> 09:14.650
And then the main function as always I'm going to save that.

09:14.680 --> 09:29.280
Go back to the terminal and then run call build with packages Select I select my package so my pi pkg

09:29.280 --> 09:33.270
and then Simulink install.

09:34.770 --> 09:41.910
Okay it was built and now I'm just going to open once again new terminals so that everything is correctly

09:41.910 --> 09:42.360
sourced.

09:42.360 --> 09:45.270
That's probably the easiest way to make sure everything is working fine.

09:45.270 --> 09:48.420
And let's run um let's run it here.

09:48.450 --> 09:55.110
Ros, to run my Pi pkg, if I press tab twice, you can see that.

09:55.110 --> 09:57.660
Now we should have also a smartphone executable.

09:58.020 --> 10:02.280
So let's run smartphone and you can see we have okay.

10:02.310 --> 10:03.810
We don't have any log.

10:03.840 --> 10:09.840
I'm just going to go back and add a log at the end of the constructor.

10:09.840 --> 10:14.400
Self dot get logger info.

10:15.480 --> 10:21.600
Smartphone has been started.

10:21.660 --> 10:28.770
It's not very important but just I like it when you can see that the node has been started and we have

10:28.770 --> 10:30.510
reached the end of the constructor.

10:31.110 --> 10:32.790
So let's run again.

10:32.820 --> 10:38.880
You can see the smartphone has been started and well, nothing happens because well, we have a callback

10:38.910 --> 10:42.960
that's going to print some messages, but we are not publishing any messages.

10:42.960 --> 10:51.750
So now let's start the publisher Ros2 run my pi pkg with Robot News Station.

10:51.750 --> 10:58.680
And as soon as I start you should see we receive messages here on that terminal.

10:59.010 --> 11:04.470
You see, if I stop the publisher, then the subscriber is still running.

11:04.470 --> 11:06.960
But we don't receive any more messages.

11:06.990 --> 11:08.490
I start the publisher again.

11:09.420 --> 11:13.740
You see, we continue to receive messages and congratulations.

11:13.740 --> 11:18.270
You now have two nodes which are communicating with a topic.

11:18.300 --> 11:24.270
As you can see, once you understand how topics work, creating a topic, publisher or subscriber inside

11:24.270 --> 11:28.470
the node is not that hard and it's going to be always the same thing.
