WEBVTT

00:00.080 --> 00:04.370
Let's now create a service server so you can practice as soon as possible.

00:04.370 --> 00:06.140
And we will start with Python.

00:06.140 --> 00:13.460
We will create a service server that will take two numbers as a request and return the sum as a response.

00:13.460 --> 00:18.080
I'm using this example so we can use an existing interface that's already installed.

00:18.080 --> 00:22.160
And we will see how to create custom interfaces in the next section.

00:22.190 --> 00:22.400
Okay.

00:22.430 --> 00:26.090
So before we write any code let's focus on the interface.

00:26.090 --> 00:32.180
Because a service is defined by a name and an interface, the interface we will use.

00:32.180 --> 00:39.500
So you can do Ros2 interface show is also in the example interfaces package.

00:39.500 --> 00:45.770
But then so for topics you had MSG for services you have serve.

00:46.040 --> 00:48.050
And then we have Add.

00:48.050 --> 00:50.870
So you can find the add to interface.

00:50.870 --> 00:53.600
That's the service interface that we will be using.

00:53.600 --> 00:55.130
And let's press enter.

00:55.130 --> 01:00.880
And this is the interface the first big important thing that you can notice.

01:00.910 --> 01:01.810
And that's the most important.

01:01.840 --> 01:04.960
Here you can see we have three dashes here.

01:04.960 --> 01:06.490
Why do we have three dashes?

01:06.490 --> 01:11.170
Because as I told you previously, a service will contain two messages.

01:11.170 --> 01:13.060
It will contain a request.

01:13.060 --> 01:16.210
So that's what's going from the client to the server.

01:16.210 --> 01:19.150
And then it will contain a response.

01:19.150 --> 01:22.210
And that's the response from the server to the client.

01:22.240 --> 01:29.080
This here those three dashes is the separation between the request and the response.

01:29.080 --> 01:35.110
So you can see that as basically two different messages together with a separation here.

01:35.110 --> 01:37.570
And what do we have in the request.

01:37.600 --> 01:39.670
We have two fields here.

01:39.670 --> 01:46.150
So you see that this time we have two fields two integer numbers named a and b.

01:46.150 --> 01:49.450
So we need to send a and b as a request from the client.

01:49.450 --> 01:52.900
And then the response is a integer number.

01:52.900 --> 01:54.670
Which name is some.

01:54.700 --> 01:55.000
All right.

01:55.030 --> 01:57.130
So from the client you need to send a and b.

01:57.130 --> 02:03.180
And then you receive that in the server you process the service and then you return the response with

02:03.180 --> 02:05.100
a sum field.

02:05.130 --> 02:05.730
All right.

02:05.730 --> 02:09.840
And now let's see how we can actually use that inside our code.

02:09.870 --> 02:12.840
Let's go back to our workspace.

02:12.840 --> 02:18.990
And I'm still going to go to my Python package that was already set up in this.

02:19.020 --> 02:22.290
We already have all the previous nodes from the previous sections.

02:22.290 --> 02:26.730
I'm going to add a new file for the server.

02:26.730 --> 02:29.250
So the name of the interface is add to int.

02:29.250 --> 02:35.460
I'm just going to name it add to int server dot pi.

02:35.460 --> 02:39.900
And later on we're going to also create the add to int client.py.

02:39.900 --> 02:41.640
So like this.

02:41.640 --> 02:45.090
Let's make it executable okay.

02:45.090 --> 02:47.100
And we have the file right here.

02:47.130 --> 02:59.620
Now let's open vs code from the source folder of the workspace with code dot okay let's go back to This

02:59.620 --> 03:01.330
package and the file.

03:01.330 --> 03:05.470
And no surprise here we will start with the template.

03:05.500 --> 03:05.740
Okay.

03:05.770 --> 03:07.480
Because we're creating a new node.

03:07.480 --> 03:13.480
So I'm just going to take the code from here and add it to add to in server.

03:13.990 --> 03:24.010
And I'm going to name this add to int seven node for example like that.

03:24.010 --> 03:31.780
And let's name the node add to int um with with server.

03:33.370 --> 03:38.260
Let's remove that and that and that one.

03:38.260 --> 03:38.770
Great.

03:38.770 --> 03:42.550
And now how to import a service interface.

03:42.550 --> 03:45.460
Well that's the same thing as we did for topics.

03:45.790 --> 03:47.500
We're going to just import that.

03:47.500 --> 03:51.790
But you see the difference here is that we don't have an MSG folder.

03:51.790 --> 03:52.900
It's an SV.

03:53.020 --> 04:06.900
So we are going to do from example interfaces Dot and you see we have s r v and then import add to ints.

04:06.930 --> 04:07.170
Okay.

04:07.200 --> 04:08.790
You can see it's found here.

04:08.790 --> 04:10.800
And as you can see we're going to use that later.

04:10.800 --> 04:15.210
We have added to INTs request and add to ints response.

04:15.390 --> 04:17.550
So let's import add to it.

04:17.580 --> 04:21.240
Now we are using the example interfaces package.

04:21.240 --> 04:26.850
We've already set the dependency in the package dot XML, but make sure that it's here.

04:26.970 --> 04:28.800
Okay so nothing more to do with that.

04:28.800 --> 04:31.470
And let's create a service server.

04:31.470 --> 04:33.450
Where do we create service server.

04:33.450 --> 04:36.000
We're going to do that in the constructor of the node.

04:36.120 --> 04:36.270
Okay.

04:36.300 --> 04:41.220
So just like we did for publishers and subscribers you're going to create your service servers inside

04:41.220 --> 04:42.120
the constructor.

04:42.120 --> 04:44.850
And so let's do self server.

04:44.880 --> 04:46.230
Let's name it server.

04:46.620 --> 04:47.220
Okay.

04:47.250 --> 04:49.800
We're going to save it as an attribute of the class.

04:49.800 --> 04:51.510
And how to create a server.

04:51.510 --> 04:56.490
Well it's quite easy you do self so you get access to the node functionalities.

04:56.490 --> 04:58.850
Create Service.

04:59.120 --> 05:03.140
When you do create service, it's going to create a service server.

05:03.170 --> 05:07.190
The first thing you need to provide is the service type which is that one.

05:07.190 --> 05:09.830
So add two ints.

05:09.860 --> 05:12.830
The second thing you need to provide is the name.

05:12.860 --> 05:16.550
Okay, so that's very similar to what we did with publishers and subscribers.

05:16.550 --> 05:19.190
You need to provide a type and a name.

05:19.190 --> 05:20.210
What is the name.

05:20.210 --> 05:23.300
So the name you choose it when you create the service.

05:23.300 --> 05:28.670
So you choose it here I'm going to use add to int okay.

05:28.700 --> 05:32.840
Because we are adding two ints and one very important thing.

05:32.870 --> 05:34.280
It's quite an important tip here.

05:34.280 --> 05:39.050
I would recommend to use a verb okay for a service name.

05:39.050 --> 05:39.500
Why?

05:39.530 --> 05:44.780
Because service will be used for mainly two things when you need to do some actions.

05:44.780 --> 05:46.610
So do something.

05:46.610 --> 05:53.450
Enable motor, disable motor, turn on LED okay that kind of stuff or a computation.

05:53.450 --> 05:56.450
So add to ints compute area.

05:56.480 --> 05:58.540
Compute inverse kinematics.

05:58.570 --> 05:58.930
Okay.

05:58.960 --> 06:01.750
Those are things that you can use services for.

06:01.750 --> 06:06.970
And because it's an action so action or computation you are going to use a verb.

06:07.000 --> 06:07.450
Great.

06:07.450 --> 06:12.250
So now we have the type name and we need to provide a callback.

06:12.250 --> 06:12.970
Why is that.

06:12.970 --> 06:17.560
Because well when you create a server the server is not going to do anything on its own.

06:17.560 --> 06:18.130
You need.

06:18.160 --> 06:21.820
Then you need a client to send a request to the server.

06:21.820 --> 06:25.270
So we are going to process the request as we receive them.

06:25.270 --> 06:27.490
And for that we need a callback.

06:27.490 --> 06:30.340
So I'm going to create a callback here.

06:30.340 --> 06:35.200
Let's call it callback add two ints.

06:35.200 --> 06:41.260
So what I do usually to name the callbacks for the service servers I use something similar as I do for

06:41.260 --> 06:46.360
subscribers is I start with callback, and then I put the name of the service and we have self.

06:46.360 --> 06:49.000
And then what do we receive as parameters?

06:49.000 --> 06:50.740
We are going to receive two parameters.

06:50.740 --> 06:54.670
We are going to receive the request and also the response.

06:54.670 --> 06:57.720
So we get a request object and a response object.

06:57.720 --> 07:01.020
From that we can get the request from the client.

07:01.020 --> 07:06.270
And then the response is well, already the response object that then we need to return.

07:06.270 --> 07:16.050
I'm going to make it a bit more explicit by saying that this is an add to insert dot request, and that

07:16.050 --> 07:21.570
one is an add to insert dot response.

07:23.190 --> 07:23.520
Okay.

07:23.520 --> 07:26.010
So this way it's more explicit.

07:26.040 --> 07:27.360
We're going to make less mistakes.

07:27.360 --> 07:31.920
And we also have nice auto completion features here for this callback okay.

07:31.950 --> 07:36.810
You can see that the add to insert here you can clearly see it's not one message.

07:36.810 --> 07:38.790
It's a combination of two messages.

07:38.790 --> 07:42.120
And the first message is add to insert request.

07:42.150 --> 07:45.450
The second message is add to insert response.

07:45.450 --> 07:47.100
And so what do we want to do here.

07:47.100 --> 07:48.330
Well it's pretty simple.

07:48.330 --> 07:51.000
We want to compute the sum of.

07:51.030 --> 08:00.250
So if I go back here of the a and the b fields that we receive from the request so I can do some is

08:00.250 --> 08:08.050
equal to request dot a plus request dot b.

08:08.050 --> 08:12.400
And I have the autocompletion here because I have provided the type okay.

08:12.430 --> 08:25.000
And then I can put the some inside the response so I can actually do directly response dot some okay

08:25.030 --> 08:26.170
response dot some.

08:26.170 --> 08:28.420
Because that's what we have here.

08:29.560 --> 08:36.280
Response dot some is equal to request dot a plus request dot b.

08:36.280 --> 08:37.210
And that's it.

08:37.240 --> 08:42.850
Actually there is one more thing you need to do is to return the response object.

08:42.880 --> 08:43.060
Okay.

08:43.090 --> 08:50.200
So that's a quite common mistake with services in Python is that you fill the response correctly but

08:50.200 --> 08:52.210
then you forget to return something okay.

08:52.240 --> 08:54.220
This method needs to return.

08:54.220 --> 08:57.600
This callback needs to return the response if you don't do it.

08:57.630 --> 08:59.640
Well, your program is going to be installed.

08:59.640 --> 09:05.670
You can run your node, but then when you send a request, you will get an exception from that callback.

09:05.670 --> 09:07.380
So just in case no.

09:07.380 --> 09:11.400
Again, once again, I repeat that you should absolutely return the response.

09:11.400 --> 09:13.350
And I'm also going to add a log.

09:13.350 --> 09:17.430
So it's going to be better for us to visualize what's happening.

09:17.970 --> 09:26.220
So self get logger I'm going to say so info I'm just going to print the equation okay.

09:26.220 --> 09:33.480
So let's cast to string request dot a plus.

09:33.480 --> 09:35.490
So let's add a plus sign.

09:35.910 --> 09:43.410
And then let's just go back to a new line with request dot b.

09:44.490 --> 09:46.800
And then we add the equal sign.

09:47.520 --> 09:54.360
And then we add the response dot sum.

09:54.390 --> 09:55.140
All right.

09:55.140 --> 09:58.640
So we just print a plus B is equal to sum.

09:58.640 --> 10:01.250
So we can see what's happening.

10:01.280 --> 10:03.530
The callback is now finished.

10:03.530 --> 10:05.600
We also need to set it here.

10:05.630 --> 10:05.900
Okay.

10:05.930 --> 10:07.730
So we have the create service.

10:07.760 --> 10:11.990
We come back to this with the type the name and callback.

10:11.990 --> 10:16.430
So self dot callback add to ints.

10:16.430 --> 10:18.830
And I'm going to go back to a new line here.

10:19.250 --> 10:19.820
Okay.

10:19.820 --> 10:21.530
So we have three parameters here.

10:21.560 --> 10:23.390
And let's finish with a log.

10:23.390 --> 10:26.990
Get logger with info.

10:26.990 --> 10:34.910
And let's say add to in server has been started.

10:35.600 --> 10:35.990
All right.

10:35.990 --> 10:36.440
And that's it.

10:36.440 --> 10:38.480
So let's do a very quick recap here.

10:38.480 --> 10:40.880
You will first initialize Rosetta communications.

10:40.880 --> 10:45.410
And then you create your node which is going to run the code inside the constructor.

10:45.410 --> 10:47.930
So you have the super line.

10:47.930 --> 10:50.840
And then we create the service server.

10:50.870 --> 10:54.910
You provide the type and name and we also provide a Callback.

10:54.940 --> 10:56.500
Okay, so nothing's going to happen now.

10:56.500 --> 10:58.750
It's just going to register a callback.

10:58.750 --> 11:01.510
When the node spins, it's going to be kept alive.

11:01.510 --> 11:04.330
And when you receive a request okay.

11:04.360 --> 11:08.980
For the add to in server, then this callback is going to be called.

11:08.980 --> 11:13.690
In this callback, you can get the request from the request field here from the parameter.

11:13.690 --> 11:17.290
And then you need to well you need to process that request.

11:17.290 --> 11:19.450
So you may want to validate the data.

11:19.480 --> 11:21.880
You may want to do whatever you want okay.

11:21.910 --> 11:23.200
Depends on your application.

11:23.200 --> 11:28.630
And then you need to fill the response parameter plus return it.

11:28.660 --> 11:29.230
Great.

11:29.230 --> 11:30.760
So let's test that.

11:30.760 --> 11:43.180
Let's go to setup.py and let's add yet another executable add to it server that's going to be my pi

11:43.630 --> 11:48.220
pkg add to server.

11:48.220 --> 11:52.330
So that's the file name here and the main function.

11:52.510 --> 11:52.930
All right.

11:52.930 --> 11:54.600
So you can see it's always the same thing.

11:54.600 --> 12:00.720
We save all the files and let's go back to our roster workspace.

12:00.750 --> 12:04.470
Let's do a click on build packages.

12:04.470 --> 12:08.100
Select with my pi pkg.

12:08.130 --> 12:11.100
You can add the symlink install if you want to.

12:11.100 --> 12:12.570
I'm just going to build it like that.

12:13.200 --> 12:19.620
And now let's just open some new terminals or use the ones that you already have.

12:20.280 --> 12:28.470
And I'm going to run Ros to run my Pi pkg with add two ints server.

12:28.470 --> 12:33.210
And you see the node has been started and now it's waiting.

12:33.210 --> 12:37.230
And so here for example let's do Ros two node list.

12:37.560 --> 12:38.640
We have the node.

12:38.640 --> 12:40.590
Let's do Ros two node info.

12:40.620 --> 12:45.030
We have that and in the service server.

12:45.030 --> 12:47.850
So I'm going to come back to all of those later in this section.

12:47.850 --> 12:51.300
But you can see we have the add two ints okay.

12:51.330 --> 12:54.220
With example interfaces service add to it.

12:54.220 --> 12:55.450
That's the one we have created.

12:55.450 --> 12:56.860
So it's a service server.

12:56.890 --> 12:59.050
Now what we can do already.

12:59.050 --> 13:01.180
So we have the server.

13:01.180 --> 13:03.280
We will need to write a client to test it.

13:03.280 --> 13:07.540
But what we can do already is to test this from the terminal okay.

13:07.570 --> 13:10.900
So I'm going to write the command and I'm going to give more details about that.

13:10.900 --> 13:16.810
There's a dedicated lesson about the Ros two command line tool for services a bit later in this section.

13:16.810 --> 13:19.180
So here I'm just going to write the command to test it.

13:19.180 --> 13:21.370
And you'll get more details later.

13:21.370 --> 13:27.490
We can do Ros two service call and use the service name.

13:27.490 --> 13:30.880
So call add to it.

13:30.910 --> 13:34.120
Then we need to provide the interface.

13:34.120 --> 13:37.300
So the interface is example interfaces etc..

13:37.300 --> 13:39.940
So just type the beginning and press tab.

13:39.940 --> 13:44.380
So Ros two service call with the service name then the interface.

13:44.380 --> 13:47.830
And then we can provide the request.

13:47.830 --> 13:52.390
So the request if you remember we have an A and a B field.

13:52.390 --> 13:53.760
So we only need to provide this.

13:53.790 --> 13:57.150
We don't provide the response because that's what we're going to receive.

13:57.240 --> 13:59.880
So let's use double quotes.

13:59.880 --> 14:05.370
And in curly brackets we can say a colon and then a space important.

14:05.400 --> 14:13.650
Let's say three and then comma B colon space let's say seven.

14:13.980 --> 14:15.300
Let's press enter.

14:16.110 --> 14:20.640
And you can see on the server side we have this log okay.

14:20.640 --> 14:27.960
And on the client side here on the terminal you see that we sent a request and we get a response with

14:27.960 --> 14:29.370
the sum ten.

14:29.550 --> 14:33.810
So with that we can already validate that the server is working.

14:33.810 --> 14:39.540
But just note that it's only going to work for very simple requests.

14:39.570 --> 14:41.130
Here we just have two fields.

14:41.130 --> 14:47.610
If you have arrays of many different fields, it's going to be very complicated to create a request

14:47.610 --> 14:48.300
from the terminal.

14:48.300 --> 14:50.220
So for that you will need to write some code.

14:50.220 --> 14:53.520
And that's exactly what we're going to do in the next lesson.
