WEBVTT

00:00.080 --> 00:02.600
This is the second step for this activity.

00:02.630 --> 00:08.420
In this step, we are going to improve this LED panel node with a service server.

00:08.420 --> 00:15.230
And this service server will allow us to modify the state of an LED from the outside of the node.

00:15.230 --> 00:19.400
So basically by using a service client from another node.

00:19.400 --> 00:25.370
And now if we think about what kind of data we need to send, well we will need to send the number of

00:25.370 --> 00:27.380
the LED and then the state.

00:27.410 --> 00:30.920
The question is do we have an existing interface that does that.

00:30.920 --> 00:34.910
If yes, we might use it, but if not we will need to create it.

00:34.910 --> 00:36.980
And here we're going to create a new interface.

00:36.980 --> 00:41.270
So a new service interface for that new service server.

00:41.300 --> 00:41.900
All right.

00:41.900 --> 00:49.250
So let's go here and let's go to our source folder my robot interfaces.

00:49.250 --> 00:52.100
And let's go to the service folder.

00:52.100 --> 00:54.950
We already have one service I'm going to create another one.

00:54.950 --> 00:59.450
Let's just name it set led.sv.

00:59.450 --> 01:03.430
RV, just like for the example we used in the real life analogy.

01:03.460 --> 01:03.850
Okay.

01:03.880 --> 01:10.060
And let's edit that file which is in the my robot interfaces.

01:10.060 --> 01:13.060
So in SV set LED.

01:13.180 --> 01:19.420
So I have the three dashes for the separation between the request and the response.

01:19.450 --> 01:22.900
First I want to give an LED number.

01:22.930 --> 01:24.610
LED number is going to be an integer.

01:24.610 --> 01:26.140
So int 64.

01:26.170 --> 01:30.190
Let's call it LED number which can be one, two, three etc..

01:30.190 --> 01:36.760
And then after we have provided the LED number, we also want to provide the state, which I have decided

01:36.760 --> 01:39.670
that the state is going to be an integer number also.

01:39.670 --> 01:42.130
So it's going to be 0 or 1.

01:42.670 --> 01:44.110
Let's call it state.

01:44.140 --> 01:44.380
Okay.

01:44.410 --> 01:46.030
So led number and state.

01:46.030 --> 01:48.700
That's what we send from the client to the server.

01:48.700 --> 01:51.640
And then the server is going to execute this.

01:51.640 --> 01:55.210
And it could be nice to know if it worked or not.

01:55.210 --> 02:03.180
So I'm going to add a bool success here there's going to be a flag that we can return to the client.

02:03.210 --> 02:07.500
You could also add, for example, a string message if you want to.

02:07.530 --> 02:09.210
I'm just going to keep it like this.

02:09.210 --> 02:10.800
So I save the file.

02:10.830 --> 02:12.690
I go to Cmakelists.txt.

02:12.690 --> 02:15.360
And then you see we already have three interfaces.

02:15.390 --> 02:16.980
I'm going to add another one.

02:16.980 --> 02:25.500
Here's RV set LED dot s RV and save.

02:25.500 --> 02:26.670
And that's it.

02:26.700 --> 02:27.570
Super quick.

02:27.600 --> 02:27.900
Okay.

02:27.960 --> 02:34.200
So make sure you have created the service in the right folder here that you have saved all the files

02:34.200 --> 02:37.110
and that you have this line in the Cmakelists.txt.

02:37.470 --> 02:43.770
Now we can go back here and build the package.

02:43.800 --> 02:49.110
Package is select with my robot interfaces.

02:52.110 --> 02:52.920
Okay.

02:52.920 --> 02:57.780
So because I have built a new interface that I'm going to use directly in my code.

02:57.780 --> 03:00.120
Let's close this code.

03:00.420 --> 03:03.600
Let's close everything like here.

03:03.600 --> 03:06.060
And let's reopen terminals.

03:07.020 --> 03:12.150
Okay, it might seem that it takes some time, but you're going to actually save more time doing this

03:12.150 --> 03:20.220
than trying to debug stuff when you have weird errors in the future and you see it's actually very quick.

03:21.360 --> 03:21.810
Great.

03:21.810 --> 03:25.800
So now I'm going to go to I don't need all of that.

03:25.800 --> 03:30.630
I'm going to go back to my LED panel, Dot Pi, and here I will.

03:30.660 --> 03:34.050
So let's wait that it's initialized okay.

03:34.050 --> 03:36.270
We have the auto completion and all that stuff.

03:36.300 --> 03:47.100
Now how do we add simply my new interface my robot interfaces, dot CSV import set LED.

03:47.400 --> 03:53.250
And because we have used the My Robot interfaces package before here, we don't need to add anything

03:53.250 --> 03:54.900
else in the package dot XML.

03:54.900 --> 03:56.600
You see it's already there.

03:56.690 --> 03:57.230
All right.

03:57.260 --> 03:59.630
And now let's create a service server.

03:59.660 --> 04:05.690
Before I create the service server I'm just going to create the callback here.

04:05.780 --> 04:07.580
That's going to be callback.

04:07.580 --> 04:10.190
So the service name is going to be set LED.

04:10.520 --> 04:11.270
Okay.

04:11.420 --> 04:19.670
We get self and then we get request which is set LED dot request.

04:19.700 --> 04:21.200
Okay I provide the type.

04:21.200 --> 04:24.440
This is optional but it's a best practice to do so.

04:24.770 --> 04:31.880
Response which is a set LED dot response.

04:33.380 --> 04:34.670
Okay so what do we do.

04:34.700 --> 04:39.170
We will need to take from that request.

04:39.200 --> 04:39.500
Okay.

04:39.530 --> 04:41.690
We have two things in the request.

04:41.720 --> 04:43.880
We have so I can see it here.

04:43.880 --> 04:45.830
We have the LED number and the state.

04:45.830 --> 04:53.300
So we need to modify the elements of the list that corresponds to the LED number and apply the state.

04:53.300 --> 05:01.030
But before we do this It could be nice to actually validate the data, because what if you send an LED

05:01.030 --> 05:06.220
number that is negative or that is outside of the list?

05:06.430 --> 05:10.450
Well, you're going to try then to modify an element outside of the list and you're going to get an

05:10.450 --> 05:11.950
exception in your code.

05:12.010 --> 05:15.970
Or what if you get a state that is not 0 or 1?

05:16.000 --> 05:21.100
Well, we have decided that the state is only 0 or 1, so that's specific to the application.

05:21.130 --> 05:22.960
Now what if I give you three?

05:22.990 --> 05:25.660
Are you going to put three inside the array.

05:25.690 --> 05:26.800
No you will not.

05:26.800 --> 05:29.860
So for that you need to validate the data.

05:29.890 --> 05:30.460
Okay.

05:30.490 --> 05:33.310
First what I'm going to do is just create some variables here.

05:33.340 --> 05:38.230
And the number is equal to request dot led number.

05:38.230 --> 05:41.140
So we don't have to write the whole thing every time.

05:41.140 --> 05:45.790
And state request dot state.

05:46.630 --> 05:50.860
And then first let's validate the LED number.

05:50.860 --> 05:54.330
And so actually because in programming we start to count from zero.

05:54.330 --> 05:57.660
So we're going to have index zero one and two.

05:57.690 --> 06:00.210
Well let's use that in our code.

06:00.210 --> 06:05.160
You could decide to just say that the LED number is one two and three.

06:05.160 --> 06:10.650
And then you could do minus one in your code to get access to the corresponding array.

06:10.650 --> 06:16.410
But because this service is going to be used by a client from another node, and basically that person

06:16.410 --> 06:18.690
writing the other node is a developer.

06:18.690 --> 06:21.390
So they know we start to count from zero.

06:21.420 --> 06:21.720
Okay.

06:21.750 --> 06:25.320
You could put it explicitly in the service here.

06:25.320 --> 06:32.670
You could add a comment for example here LED number or just maybe a comment here okay LED number starting

06:32.700 --> 06:34.170
at zero something like that.

06:34.170 --> 06:47.730
So if LED number is greater or equal than the length of a self led state.

06:48.540 --> 06:48.990
All right.

06:48.990 --> 06:52.790
So if we provide three so One, two, three.

06:52.820 --> 07:00.650
We are outside of the array or if LED number is strictly lower than zero.

07:00.650 --> 07:05.630
Basically, if we are going before I mean there is nothing before zero in the list.

07:05.630 --> 07:09.110
So in this case we know that we have a wrong LED number.

07:09.110 --> 07:16.130
And so we are going to do response dot success is equal to false.

07:16.130 --> 07:20.120
So we fill the response with what we have here.

07:20.120 --> 07:24.800
And then we return the response okay.

07:24.830 --> 07:29.120
So if we don't pass this test we're just going to return right away.

07:29.150 --> 07:30.740
We don't do anything else.

07:30.920 --> 07:32.540
Then I'm going to do another test.

07:32.540 --> 07:39.920
If state let's say state not in zero one okay.

07:39.950 --> 07:42.110
So state must be 0 or 1.

07:42.110 --> 07:44.510
If not same thing we do.

07:44.540 --> 07:52.820
Response dot success false and return The response.

07:52.820 --> 07:58.670
If you had added a message, for example, a string, you could add a different string message here

07:58.670 --> 08:00.620
to explain what was the issue.

08:00.620 --> 08:08.390
And now if I reach this line of code, I know that we have a correct LED number that corresponds to

08:08.420 --> 08:12.380
an index of that list and the state is correct.

08:12.380 --> 08:22.220
So I can just do self led state and reach the LED number index.

08:22.370 --> 08:29.180
And I can just say that that becomes the state, because now I know all the data is correct.

08:29.180 --> 08:38.120
And if I do this I can also do response dot success is equal to true and return.

08:38.120 --> 08:40.790
Let's not forget to return the response okay?

08:41.270 --> 08:42.680
It's a very common mistake.

08:42.710 --> 08:43.340
Great.

08:43.340 --> 08:47.030
And that's going to be the end for this callback right.

08:47.030 --> 08:50.380
So we first get the different elements of the request.

08:50.380 --> 08:58.390
If needed, we might want to validate the data, and then we do the action and we return a response.

08:58.780 --> 09:06.400
So let's actually create a service because this callback is not going to be called if we don't create

09:06.430 --> 09:07.330
a service.

09:07.330 --> 09:19.960
So here for example after the timer we can do self set LED service is equal to self dot create service.

09:20.470 --> 09:25.000
We need to provide the service type which is set LED.

09:25.570 --> 09:28.360
We need to provide a name which we decide here.

09:28.360 --> 09:36.610
So I gave you set LED before and then the callback self dot callback set LED.

09:38.740 --> 09:39.130
All right.

09:39.130 --> 09:40.000
And that's it.

09:40.000 --> 09:44.950
So you see in this node we have one publisher one timer and one service.

09:45.130 --> 09:47.140
So in the end we have two callbacks.

09:47.140 --> 09:50.730
You see we have one callback for the timer.

09:50.760 --> 09:55.980
There's going to be triggered every five seconds, and then we have one callback for the service that's

09:55.980 --> 10:00.900
going to be triggered whenever we get an incoming request from a client.

10:01.380 --> 10:03.750
So let's save that.

10:03.840 --> 10:05.340
Let's go back to the terminal.

10:05.340 --> 10:12.330
And I have used Simulink install, so I should be able to run it without building again.

10:12.360 --> 10:16.320
Let's just do a source bashrc still just in case.

10:17.940 --> 10:25.770
And just to run my Python package with LED panel.

10:27.300 --> 10:31.260
Okay, so you can see we have reached the end of the constructor.

10:31.290 --> 10:40.440
Now if I do rust to service list, you see I have my set LED and so I can already test it.

10:40.440 --> 10:43.950
And because this is quite easy.

10:43.950 --> 10:45.840
So the request actually is quite easy.

10:45.870 --> 10:47.280
It's just two integers.

10:47.280 --> 10:50.240
We can easily test it from the terminal.

10:50.270 --> 10:56.900
Okay, so I can do ros2 service call and then set LED.

10:57.260 --> 11:02.720
Then I need to provide the interface so my I can just press tab here.

11:02.720 --> 11:03.830
It's going to find it.

11:03.860 --> 11:06.200
My robot interface is set LED.

11:06.380 --> 11:10.730
And then I can build the request.

11:10.730 --> 11:22.520
So if you don't remember Ros2 interface show my robot interfaces solve set LED okay.

11:22.520 --> 11:26.510
So we need to provide LED number.

11:27.470 --> 11:29.060
Let's say zero.

11:29.090 --> 11:30.110
That's the first one.

11:30.110 --> 11:32.960
And state let's say one.

11:32.960 --> 11:39.890
We want to turn on the LED and to verify that so we can run it and see if it's working.

11:40.010 --> 11:45.770
But to double check we can also see what's going to happen on the topic.

11:45.830 --> 11:46.780
So Series two.

11:46.810 --> 11:47.290
Topic.

11:47.320 --> 11:50.740
Eco led panel.

11:50.740 --> 11:51.820
State.

11:52.780 --> 11:55.780
Let's see for the first message to arrive.

11:56.350 --> 11:56.860
Okay.

11:56.860 --> 11:58.570
And then let's run that.

11:59.590 --> 12:00.940
You see it's working.

12:00.940 --> 12:02.020
We have response success.

12:02.020 --> 12:07.000
And the next time that we have the topic the first LED here is turned on.

12:07.270 --> 12:07.840
Okay.

12:07.870 --> 12:10.900
Now I can turn it off with zero.

12:12.370 --> 12:12.940
Okay.

12:12.940 --> 12:16.270
But what you can see is when I do this, it's working.

12:16.660 --> 12:21.280
But then we receive the topic because we publish every five seconds.

12:21.280 --> 12:26.500
So we might wait as long as five seconds to receive the new data on the topic.

12:26.500 --> 12:29.350
And how can we kind of solve that?

12:29.380 --> 12:30.490
Well, there are two ways.

12:30.490 --> 12:38.260
First, you could increase the frequency a lot and say that, for example, you publish every 0.1 second

12:38.290 --> 12:42.790
or something like that, but then you're going to publish a lot of messages and still you will not get

12:42.790 --> 12:45.910
exactly immediately the new data on the topic.

12:45.910 --> 12:54.310
So what we can do is that directly after we set the new state here, and before we return the response,

12:54.310 --> 12:56.500
we could publish here.

12:56.500 --> 13:02.560
From there we could do self-publish led state.

13:02.620 --> 13:03.400
All right.

13:03.430 --> 13:10.150
I told you that you could publish on a topic from anywhere so you can publish from a timer callback.

13:10.180 --> 13:12.310
You can publish from a subscriber callback.

13:12.310 --> 13:13.540
We have done that previously.

13:13.540 --> 13:17.710
You can also publish from a service callback.

13:17.740 --> 13:18.010
Okay.

13:18.040 --> 13:19.210
There is no problem with that.

13:19.240 --> 13:22.750
And so here what we do is we publish every five seconds.

13:22.840 --> 13:27.970
But then whenever we change the state, we publish immediately the new state.

13:27.970 --> 13:31.450
So let's save that and let's go back.

13:31.450 --> 13:35.380
Let's run everything again okay.

13:35.380 --> 13:39.610
And let's do this.

13:40.900 --> 13:41.620
Okay.

13:41.830 --> 13:44.080
Now I'm going to wait for the next one.

13:45.210 --> 13:45.510
Okay.

13:45.540 --> 13:47.220
And I'm going to run the service.

13:48.120 --> 13:54.810
And you see, as soon as we have gotten a response here, we also see the new state here.

13:55.320 --> 13:55.440
Okay.

13:55.470 --> 13:57.270
We don't have to wait five seconds.

13:57.990 --> 14:03.420
So here you see, as soon as we have that we get the new state.

14:03.420 --> 14:06.210
So there is a new message on the topic.

14:07.350 --> 14:07.740
Great.

14:07.740 --> 14:08.970
So that's currently working.

14:08.970 --> 14:13.770
And let's just test the cases where we're going to get an error.

14:13.770 --> 14:15.900
So when the success is going to be false.

14:15.900 --> 14:24.270
So for example LED number if I put four you see I should get success false.

14:24.660 --> 14:27.390
And then let's put zero.

14:27.390 --> 14:28.740
So that's the correct number.

14:28.920 --> 14:32.580
But then let's put two for the state.

14:33.300 --> 14:35.730
And you see we have success false.

14:36.090 --> 14:40.770
So we can validate that our data validation is also working great.

14:40.770 --> 14:43.680
And that's the end of the second step for this activity.
