WEBVTT

00:00.080 --> 00:05.390
And now let's integrate this service client inside a node that uses OOP.

00:05.480 --> 00:09.590
That first example here was great to start working with service clients.

00:09.590 --> 00:15.620
And you can use this exact code as a template whenever you want to quickly test a service server that

00:15.620 --> 00:17.030
you have just written.

00:17.060 --> 00:23.930
Now as you can see, if we want to add this inside a node that uses object oriented programming, well,

00:23.930 --> 00:28.250
if I come back to the template, you see we make the node spin okay.

00:28.280 --> 00:32.300
And in this script we have a spin until future complete.

00:32.300 --> 00:38.870
So if we use that we are basically going to make a node spin while it is already spinning.

00:38.870 --> 00:41.510
And that can lead to very weird behaviors.

00:41.510 --> 00:43.400
So we are not going to use that.

00:43.400 --> 00:46.310
And I'm going to show you how to solve that challenge right now.

00:46.310 --> 00:49.670
So let's create a new file okay.

00:50.180 --> 00:55.940
Let's go back to Ros2 workspace Source Python package.

00:56.150 --> 01:00.170
And let's create a add.

01:01.270 --> 01:04.090
to its client.

01:04.090 --> 01:06.670
So this one is just going to be the add to its client.

01:06.700 --> 01:07.270
Okay.

01:07.300 --> 01:11.410
With the normal OOP node dot p y.

01:11.530 --> 01:13.570
And let's make it executable.

01:15.400 --> 01:18.400
Add to its client dot p y.

01:18.850 --> 01:22.870
Okay let's take the template.

01:23.470 --> 01:25.810
And let's go to the client.

01:25.810 --> 01:28.120
And let's use this template this time.

01:28.120 --> 01:33.400
And let's call it add to int client.

01:34.810 --> 01:35.440
Okay.

01:35.440 --> 01:40.300
And add to int client.

01:42.520 --> 01:47.680
Let's remove those and remove the column here.

01:47.710 --> 01:48.190
Okay.

01:48.220 --> 01:55.120
So first things first before we even create the service client we need to import the interface.

01:55.150 --> 01:57.790
And the interface is going to be the same okay.

01:57.970 --> 01:59.020
From the server.

01:59.020 --> 02:07.920
a sort from example interfaces dot csv import add to ints.

02:07.950 --> 02:10.020
Okay, we have that interface.

02:10.020 --> 02:16.020
And now what I'm going to do is I'm going to do the first step which is to create a service client.

02:16.020 --> 02:19.980
I'm going to do that in the constructor self dot.

02:20.100 --> 02:32.880
Let's name it client is equal to self create client with add to int and add two ints okay.

02:32.910 --> 02:34.950
So that's the same thing.

02:34.950 --> 02:38.400
Here we provide the type and the name.

02:38.430 --> 02:39.690
Make sure it's the same.

02:39.690 --> 02:44.310
But this time you see we use self because we are directly inside the node class.

02:44.310 --> 02:50.010
So this is a node we can use self and we store that as an attribute of the class.

02:50.010 --> 02:55.860
Then what I will do is I will create a method that we will use to call the service to send the request.

02:55.890 --> 03:01.420
Let's name this call Add two ints, for example.

03:01.420 --> 03:04.750
So call and then the name of the service self.

03:04.750 --> 03:08.710
And let's say we are going to give a and b okay.

03:08.740 --> 03:11.710
So to match the a and b in the request.

03:11.950 --> 03:19.390
And in this method what I will do is well before I send the request, I will first make sure that you

03:19.390 --> 03:21.700
see the service is up.

03:21.700 --> 03:26.830
So I can just take that line here and use it right here.

03:27.310 --> 03:29.590
And let's put the correct indentation.

03:29.590 --> 03:31.270
And you see we need to replace stuff.

03:31.270 --> 03:35.830
So it's not client it's self client.

03:36.370 --> 03:37.810
That's the one we've created here.

03:37.810 --> 03:41.470
And the node is not just node it's self all right.

03:41.500 --> 03:42.730
But the code stays the same.

03:42.730 --> 03:45.460
So we create the client here in the constructor.

03:45.460 --> 03:50.680
And then in this method that we're going to call later we first wait for the service.

03:50.710 --> 03:52.210
We make sure that it's up.

03:52.210 --> 03:55.090
After that we can create a request.

03:55.090 --> 03:59.220
So to create a request well we use the same code.

03:59.610 --> 04:02.850
So I'm just going to take that code here and put it there.

04:05.430 --> 04:05.850
Okay.

04:05.850 --> 04:10.950
We create a request which is an add to insert request.

04:10.950 --> 04:15.960
And we give some numbers request a and request dot b.

04:15.990 --> 04:21.030
The next step is to send the request how to send the request.

04:21.060 --> 04:28.860
We do self client call async with the request.

04:28.890 --> 04:30.480
Okay so nothing new here.

04:30.480 --> 04:31.710
That's the same thing we did.

04:31.710 --> 04:34.200
And this is going to give us a future.

04:34.200 --> 04:35.970
So we save it as a future.

04:35.970 --> 04:38.700
And then this is the big difference.

04:38.700 --> 04:42.450
We are not going to do a spin inside the spin.

04:42.450 --> 04:44.610
We are not going to spin while we are spinning.

04:44.610 --> 04:50.250
What I'm going to do is I'm going to do future dot add done callback.

04:50.280 --> 04:57.470
You see we have add done callback and I will create a callback function that will be called when the

04:57.470 --> 05:00.020
client receives the response, okay.

05:00.020 --> 05:02.510
And that's going to work because the node is spinning.

05:02.510 --> 05:07.790
So if the node is spinning, we can execute all of the callbacks for this node including that one.

05:07.790 --> 05:13.910
So let's do callback call add to insert for example.

05:13.910 --> 05:16.190
That's the callback for this method here.

05:16.190 --> 05:17.510
What do we receive.

05:17.510 --> 05:20.690
So we have self and then we receive future.

05:20.960 --> 05:24.380
All right so you can register I'm just going to put.

05:24.380 --> 05:25.670
So I'm going to put pass.

05:25.670 --> 05:26.450
If you don't know pass.

05:26.450 --> 05:29.090
It just means you don't want to do anything in a function.

05:29.090 --> 05:31.430
So here just useful.

05:31.430 --> 05:33.530
So we don't have an errors in VS code.

05:33.530 --> 05:41.780
For now I'm going to do future dot add done callback and I'm going to provide self callback call add

05:41.810 --> 05:42.530
to ints.

05:42.560 --> 05:42.920
All right.

05:42.920 --> 05:45.350
So here I wait for the service.

05:45.350 --> 05:46.520
I create the request.

05:46.520 --> 05:48.770
I send the request asynchronously.

05:48.770 --> 05:51.710
And then I add a callback for when we get the response.

05:51.710 --> 05:54.650
So when we get the response we go to this code.

05:54.650 --> 06:01.180
And we can do response is equal to future dot result.

06:01.540 --> 06:13.930
And then we can do uh, not print but self getlogger for example.info let's say got response.

06:14.410 --> 06:16.660
It's going to be the same plus.

06:16.660 --> 06:22.120
So let's cast as a string response dot sum okay.

06:22.150 --> 06:26.290
We get the response object inside the response object we have the sum.

06:26.320 --> 06:26.770
All right.

06:26.770 --> 06:29.560
And now there's just one thing that's missing.

06:29.590 --> 06:32.350
Because if we start this node well we're going to start the client.

06:32.350 --> 06:37.420
But then no request is going to be sent because we don't call this function.

06:37.420 --> 06:42.700
So what I'm going to do in the main I'm going to create the node.

06:42.730 --> 06:44.020
So it's going to create the client.

06:44.020 --> 06:48.940
And then I'm going to do node dot call add to ints.

06:48.970 --> 06:52.390
I'm going to call this function right away with.

06:52.420 --> 06:55.210
So let's say actually here I put three and eight.

06:55.210 --> 06:59.150
But it's going to be A and B.

06:59.180 --> 07:02.420
Those are the parameters that I get from the method here.

07:02.450 --> 07:04.490
Let's say two and seven.

07:04.820 --> 07:10.160
And so what's going to happen here when we create the node it's going to create the client then.

07:10.160 --> 07:12.530
Well you could call that from anywhere.

07:12.530 --> 07:14.630
But here we don't have other callbacks for now.

07:14.630 --> 07:17.000
So I'm just calling it here.

07:17.030 --> 07:18.860
So that's going to wait for the service.

07:18.860 --> 07:25.880
Create a request, send a request and then register a callback so that when we get the response we can

07:25.880 --> 07:29.270
get it in this callback method after that.

07:29.270 --> 07:33.950
So we're going to execute this return here make the node spin.

07:33.950 --> 07:36.590
So the node is spinning and can execute the callbacks.

07:36.590 --> 07:42.620
That's why when we get the response from the server we can get to that part okay.

07:42.650 --> 07:46.640
So the node needs to be spinning in order to receive the response.

07:46.640 --> 07:52.640
And here well as I told you, if we had let's say a subscriber callback or if we had a timer callback,

07:52.640 --> 07:56.600
we could decide at some point to call this one from one of those callbacks.

07:56.600 --> 08:00.020
But because I don't have this here, I just call it here.

08:00.020 --> 08:01.280
It's going to be the same.

08:01.280 --> 08:05.690
Now let's save this and let's go back to the setup.py.

08:05.690 --> 08:18.230
And let's add the last executable here, add to its client which is going to be my pi pkg dot add to

08:18.260 --> 08:20.120
its client.

08:20.180 --> 08:22.250
And that's the main function.

08:22.250 --> 08:22.760
Great.

08:22.760 --> 08:24.230
Let's go back here.

08:24.230 --> 08:29.720
Let's go to the roster workspace and call call build.

08:29.720 --> 08:39.980
So if I go back here I can find call build with the Python package and symlink install okay let's open

08:39.980 --> 08:41.210
some terminals.

08:43.430 --> 08:46.250
I'm going to start a server here.

08:46.250 --> 08:55.320
So ros2 run my pi pkg with add to intz server Okay.

08:55.320 --> 09:04.650
And then I'm going to start the client Ros to run my Pi PG with add two ints client.

09:04.650 --> 09:07.620
So this time you see I can choose between client.

09:07.650 --> 09:08.400
No OOP.

09:08.430 --> 09:09.660
That's the previous script.

09:09.660 --> 09:11.790
And that one is the one we have just written.

09:11.790 --> 09:17.790
So I'm going to run the latest and you can see it's working.

09:18.000 --> 09:21.990
We have the log on the server side and the log on the client side.

09:22.020 --> 09:25.050
Now let's say we also want to.

09:25.080 --> 09:27.960
So here you see in this no.

09:27.990 --> 09:28.470
Where is it.

09:28.500 --> 09:33.690
Here in this callback I only get access to the response okay.

09:33.690 --> 09:40.590
If I wanted to print a plus B is equal to sum I could pass for example the request here.

09:40.590 --> 09:43.860
So I could put request.

09:43.860 --> 09:49.770
And then here I would need to do request is equal to request.

09:49.860 --> 09:55.040
So then I can pass the request object also in the callback.

09:55.040 --> 09:57.620
So we get access to what was the previous request.

09:57.620 --> 10:01.910
And in this case that request corresponds to that name here.

10:01.910 --> 10:03.830
And this is the object we've created.

10:03.830 --> 10:07.130
I'm just going to save and see if we get an error here.

10:07.760 --> 10:09.200
So let's start again.

10:10.520 --> 10:12.410
And you see we have an error okay.

10:12.410 --> 10:19.430
Because the future add on callback got an unexpected keyword argument because you've added an extra

10:19.460 --> 10:20.330
argument here.

10:20.330 --> 10:26.270
So you need to use the partial function from func tools okay.

10:26.300 --> 10:28.700
That's something specific to Python.

10:28.700 --> 10:32.120
You cannot really know that without having looked on the internet.

10:32.120 --> 10:36.470
So I'm going to import well for example here from Func tools.

10:36.470 --> 10:40.730
That's a Python module import partial.

10:40.730 --> 10:50.570
And then when you do add on callback you need to do partial here partial of that okay.

10:50.600 --> 10:56.790
So just remember that if you want to add extra arguments to a callback with add on callback for a future

10:56.790 --> 11:01.530
object, you need to add the partial function here from func tools.

11:01.530 --> 11:05.160
And let's just go back to new line here, because it takes a lot of space.

11:05.190 --> 11:11.250
Now let's save and that should work okay it's working.

11:11.250 --> 11:15.840
So now that it's working we can use the request here.

11:15.840 --> 11:19.380
And let's just do the same thing we did before here.

11:19.380 --> 11:21.750
Let's print that.

11:21.750 --> 11:26.400
So let's take this log and let's print that instead.

11:27.360 --> 11:30.150
It's going to be self okay.

11:30.150 --> 11:32.760
So we print the full equation.

11:32.760 --> 11:34.020
Let's save.

11:34.020 --> 11:37.110
And now I'm gonna run again.

11:37.140 --> 11:38.550
Let's see if it works.

11:39.840 --> 11:43.080
And you see we have the two plus seven is equal to nine.

11:43.080 --> 11:47.520
So in the callback we have the response.

11:47.520 --> 11:50.400
But we can also pass the requests okay.

11:50.430 --> 11:53.030
To know what was the request fields?

11:53.060 --> 11:53.570
Great.

11:53.570 --> 12:00.500
And the last thing we can do as a test is, well, we just call the function once, but let's call it

12:00.530 --> 12:02.570
actually three times.

12:02.600 --> 12:04.340
I'm going to use different numbers.

12:04.340 --> 12:10.610
So one plus four and then maybe ten plus 20.

12:11.090 --> 12:12.860
Okay let's save.

12:12.860 --> 12:15.470
And let's see what happens if we call it three times.

12:16.790 --> 12:18.500
Um let's run that here.

12:21.650 --> 12:23.360
You can see that it's working.

12:23.390 --> 12:23.630
Okay.

12:23.660 --> 12:26.510
We can send as many requests as we want.

12:26.540 --> 12:29.180
You can see it's going to process all three requests.

12:29.180 --> 12:32.000
So it's going to process them one by one.

12:32.000 --> 12:33.830
But you can see here it was very fast.

12:33.830 --> 12:35.690
So it looks like it's at the same time.

12:35.690 --> 12:37.700
And then for each request it's going to send back.

12:37.700 --> 12:40.670
So the server is going to send back the response to the client.

12:40.700 --> 12:41.030
All right.

12:41.030 --> 12:46.580
So with one client you can send several requests as you want.

12:46.610 --> 12:47.060
Great.

12:47.060 --> 12:52.130
And you have successfully written a full Python service server and client.
