WEBVTT

00:00.640 --> 00:07.360
In this laboratory lesson, we will develop a simple service server in C plus plus that will provide

00:07.360 --> 00:10.660
the functionality of calculating the sum of two integers.

00:10.930 --> 00:16.840
Then we will also develop a client that will use this service within another Ros two node.

00:17.470 --> 00:23.770
This will help us to understand how services works practically and how to use the Ros to command line

00:23.770 --> 00:25.780
interface to interact with them.

00:26.660 --> 00:30.920
Let's start by creating a new Cplusplus script inside the Arduino.

00:31.190 --> 00:32.390
CPP examples.

00:32.390 --> 00:34.160
So inside the source folder.

00:34.780 --> 00:39.340
And let's call this script simple service.

00:40.300 --> 00:41.980
Server dot cpp.

00:42.340 --> 00:49.090
Here, as always, let's start by importing the CPP library.

00:49.090 --> 00:53.110
And so let's include the CPP dot PHP.

00:53.470 --> 00:58.420
And then from this library, let's use the node class to create a new Ros2 node.

00:58.960 --> 01:12.460
So let's call this one simple service server that inherits from the CPP library and so from the node

01:12.460 --> 01:13.120
class.

01:13.420 --> 01:22.570
So let's define this class and among the public methods of this class, let's start as always by declaring

01:22.570 --> 01:24.210
the constructor of this class.

01:24.220 --> 01:30.310
So the function simple service server and here, as we did in the previous lesson.

01:30.310 --> 01:34.460
Also, let's start by initializing the node class.

01:34.460 --> 01:41.210
So the base class and we need to provide as input of the constructor the name of the node, let's call

01:41.210 --> 01:46.910
it, for example, simple service server.

01:47.710 --> 01:51.070
Now among the private variables of this class.

01:51.070 --> 01:56.680
So here let's create a new object of type service.

01:56.680 --> 02:01.840
So from RCL, CP, let's create a new service.

02:02.110 --> 02:10.420
And this is a template class and we take a shared pointer to this class and let's call this variable

02:11.140 --> 02:12.100
service.

02:12.460 --> 02:24.280
Now let's also remember to include here include the memory library from C plus plus in order to be able

02:24.280 --> 02:28.600
to use the shared pointer and now the service template class.

02:28.600 --> 02:31.180
So this one here needs as input.

02:31.180 --> 02:35.350
So among the angular parentheses, the name of the message interface.

02:35.350 --> 02:41.170
So the one that contains the request and response message that should be used in order to communicate

02:41.170 --> 02:42.730
with the service server.

02:43.400 --> 02:44.120
To do this.

02:44.150 --> 02:47.900
If you haven't followed me in the Python laboratory lessons.

02:47.900 --> 02:53.720
We need to create a new message interface for the communication with the server that we are going to

02:53.720 --> 02:55.640
create by convention.

02:55.640 --> 03:02.510
And also as a general rule in Ros2, it is recommended that all the new message types, both those for

03:02.510 --> 03:08.240
interaction with topics and those for the communication with services are placed in a different package

03:08.240 --> 03:11.630
than the ones that contains instead the robots functionalities.

03:11.750 --> 03:18.890
So if you haven't done so, let's open a new terminal and let's go to the Arduino Bot workspace and

03:18.890 --> 03:20.300
then to the source folder.

03:20.300 --> 03:22.310
And here let's create a new package.

03:22.310 --> 03:33.860
So to package, create and let's use as a build type, amend CMake and let's call this package Arduino

03:33.860 --> 03:39.650
bot messages as it will contain just message interface for the communication in Ros2.

03:40.220 --> 03:45.510
I have already created this package in my workspace, so I'm not going to run this command again.

03:45.510 --> 03:49.050
But anyway, you can see it created here.

03:49.170 --> 03:56.520
So now you need to go back to your workspace and build it again with the command called build so that

03:56.520 --> 04:01.050
the new package is recognized and is ready to use in Cplusplus.

04:01.860 --> 04:04.210
So go back in Visual Studio code.

04:04.210 --> 04:10.920
And now here we can define the new message interface that the service server must use for the communication

04:10.920 --> 04:12.390
with the service server.

04:12.390 --> 04:18.330
So within the Arduino bot messages still, if you haven't followed me in the Python lessons, you need

04:18.330 --> 04:20.700
to create the serve folder.

04:20.700 --> 04:26.850
That by convention is where we place all the message interface with the service servers.

04:26.850 --> 04:31.590
And so here you need to create the add joints.sv file.

04:31.650 --> 04:37.890
And inside this file we need to define the structure of the request message that is the one that the

04:37.890 --> 04:40.110
client sends to the server.

04:40.110 --> 04:45.840
And this one contains just two integers, two numbers that are the two numbers that we want the server

04:45.840 --> 04:49.200
to send and then separated by three dashes.

04:49.230 --> 04:55.800
We also need to declare the response message and this server will simply return another integer, which

04:55.800 --> 05:00.840
is the sum of the two integers received as inputs or received in the request.

05:01.140 --> 05:07.740
With this we have completed the definition of the add joints and so in order to use it, we need also

05:07.740 --> 05:15.960
to declare it inside the cmakelists.txt so that the compiler is aware of the existence of this message

05:15.960 --> 05:19.440
interface here in the previous lesson.

05:19.440 --> 05:24.510
First of all, we declared the usage of the standard message library, which contains the definition

05:24.510 --> 05:26.450
of the integer message.

05:26.460 --> 05:32.520
Then we also define the usage of the Ros IDL Default Generators library.

05:32.520 --> 05:37.230
That is the one in charge of compiling our SV files.

05:37.230 --> 05:43.080
So in general our Ros to interface messages and make them available to the node.

05:43.080 --> 05:46.110
So to the scripts both Cplusplus and Python.

05:46.640 --> 05:54.620
Then also we used the instruction Ros generate interfaces in order to generate the interface for the

05:54.620 --> 05:55.580
current project.

05:55.580 --> 06:02.720
So for the current package that is the Arduino board messages and we declared the existence of the Arduino

06:03.110 --> 06:06.950
dot SVG file within the SVG folder.

06:08.380 --> 06:08.950
Next.

06:08.950 --> 06:16.270
We need to also to modify the package dot XML file and here we need to add the dependency still from

06:16.270 --> 06:18.010
the standard message library.

06:18.040 --> 06:24.780
Also, we need to add a build dependency from the Ros IDL Default Generators library.

06:24.790 --> 06:28.570
That is the one that we are going to use to build our messages.

06:28.600 --> 06:34.750
Then we also need an execution dependency from the Ros IDL default runtime.

06:34.900 --> 06:41.620
And finally, we also need to use this tag so the member of group in order to declare and so in order

06:41.620 --> 06:45.400
to use the ros IDL interface packages.

06:45.700 --> 06:50.920
And this is all we need in order to define and declare this interface.

06:50.920 --> 06:56.770
So the Add joins interface that from now on we can use within our script.

06:56.770 --> 07:00.690
So both within our Python and our C plus plus script.

07:00.700 --> 07:07.720
But before doing so, so after you create this interface in the Arduino board messages in order for

07:07.820 --> 07:15.800
it to be recognized by Roscoe, let's go back again in the workspace and let's build it with the command

07:15.800 --> 07:16.820
called build.

07:18.960 --> 07:26.220
Now the interface is compiled and we can go back to our simple service server here and we can start

07:26.220 --> 07:27.870
using this interface.

07:27.870 --> 07:36.390
So let's include and from the Arduino board messages here, if you don't have the autocompletion of

07:36.390 --> 07:43.110
the text, you need to press Ctrl shift P and then look for Ros.

07:43.140 --> 07:45.450
Update Cplusplus properties.

07:45.600 --> 07:51.630
So this will scan again the workspace and will enable the Autocompletion for Ros two.

07:51.960 --> 07:58.710
And so then from the Arduino bot messages, we have the Autocompletion now from the SR folder, let's

07:58.710 --> 08:05.130
import the Add joints interface and now we can use this interface within the angular brackets.

08:05.130 --> 08:12.210
So here inside the service to declare that the service server that we are going to use is using the

08:12.210 --> 08:18.910
interface from the Arduino board messages from the service and that is called add to INS.

08:20.120 --> 08:27.800
Now here in the body of the constructor of the Simple Service Server class, let's initialize the service

08:27.800 --> 08:28.540
variable.

08:28.550 --> 08:36.680
So this shared pointer and as we used the create publisher function to initialize our Ros to publisher

08:36.680 --> 08:43.490
and the create subscription function to initialize our subscriber, we can use the Create service function.

08:43.490 --> 08:50.450
So create service function to initialize our service server.

08:50.600 --> 08:57.320
This is a template function that requires, again among the angular parentheses the type of the interface

08:57.320 --> 09:03.980
used for the communication with the service server, which once again is this one is the one that we

09:03.980 --> 09:08.600
declared in the Arduino board messages and that is called Add joins.

09:09.620 --> 09:11.260
Inside the parentheses instead.

09:11.270 --> 09:16.790
So here, as the input of the function, we need to pass the name to give to this service.

09:16.790 --> 09:25.010
So the name by which this service will be recognized in Russia, for example, let's call it add two

09:25.880 --> 09:26.690
ins.

09:27.110 --> 09:31.640
Then also as input, we need to provide a callback function.

09:31.640 --> 09:38.510
So namely a function that has to be executed by the service server every time it receives a new request.

09:38.510 --> 09:42.920
So every time a new client requests the execution of the server.

09:42.920 --> 09:50.600
And so the execution of this of the two integers to do so, we can use the bind function of the C plus

09:50.600 --> 09:59.690
plus standard library and let's call the function service callback, which we are going to declare still

09:59.750 --> 10:02.390
within the simple service server class.

10:02.720 --> 10:09.930
So let's say that this service callback function will be a member of the simple service server class

10:09.930 --> 10:14.130
and that we want to use the one declared in the current instance.

10:14.130 --> 10:15.720
So in the current object.

10:15.720 --> 10:19.350
And then also let's use the placeholder namespace.

10:19.470 --> 10:31.530
So using from the standard library, the namespace STD placeholders.

10:31.980 --> 10:40.740
And so from this namespace, let's use the placeholders one and two to indicate that this callback function.

10:40.740 --> 10:44.700
So the service callback function will require two inputs.

10:44.700 --> 10:47.550
So we require two variables as input.

10:47.550 --> 10:52.560
That will be exactly the two messages contained in the interface with the server.

10:52.560 --> 10:55.530
So the request and the response message.

10:56.140 --> 11:01.970
To finish the constructor of this class, let's just print an informative message in the terminal.

11:01.990 --> 11:09.460
So with the CP info and let's print the message.

11:09.580 --> 11:18.460
Let's take the reference to the logger with the get logger function and let's print the message.

11:18.640 --> 11:20.470
So service.

11:21.790 --> 11:29.200
And then the name of the service that is at two ends is ready.

11:30.440 --> 11:35.450
So that we can confirm that the service has been correctly instantiated.

11:35.720 --> 11:43.220
Now, still here, among the private attributes of the simple service class, we can define the service

11:43.220 --> 11:44.490
callback function.

11:44.510 --> 11:49.130
So let's copy this one and let's define this function.

11:49.850 --> 11:51.440
So it returns void.

11:51.440 --> 11:53.630
So it returns no parameters.

11:53.630 --> 11:59.960
And as this is a callback function, as we said previously, it requires a input the message interface

11:59.960 --> 12:01.790
to be used for the communication.

12:01.790 --> 12:09.440
And so for the data exchange with the service server, therefore it receives a shared pointer to a request

12:09.440 --> 12:10.160
message.

12:10.160 --> 12:13.250
So it receives a constant

12:15.740 --> 12:26.810
shared pointer of type Arduino, both messages and then from the service from the Arduino interface

12:26.870 --> 12:27.650
of.

12:28.070 --> 12:33.270
So it receives a request message and let's call this variable request.

12:33.510 --> 12:40.680
And then the second input of this, one of this function is still another constant pointer.

12:40.680 --> 12:43.500
So another shared pointer.

12:46.670 --> 12:53.390
And this time still from the Arduino bot messages.

12:54.080 --> 13:03.470
Let's take from these services the add to into service and let's take the response and let's call this

13:03.470 --> 13:05.060
one response.

13:05.890 --> 13:11.590
As a first thing in this callback function, let's print another informative message in the terminal.

13:11.590 --> 13:19.750
So with the rql cpp info stream function.

13:20.170 --> 13:26.740
And here let's use the function Rcpp get logger.

13:27.430 --> 13:29.620
And then let's print the message.

13:29.950 --> 13:35.920
New request received followed by the two numbers.

13:35.920 --> 13:39.930
So the two integers that were received in the request message.

13:39.940 --> 13:46.120
So a that is in the request message.

13:47.140 --> 13:56.260
And also let's print B and also this one is in the request message under the name of the variable B.

13:57.860 --> 14:05.000
Then after this message, we can execute the actual logic of the server that basically consists of calculating

14:05.000 --> 14:08.100
the sum of the two integers that were received as input.

14:08.120 --> 14:18.530
So it calculates the sum between the variable A plus the variable B that are in the request message.

14:18.530 --> 14:26.480
And let's store the content of this operation within the response message and within the sum variable.

14:26.690 --> 14:34.100
So within the sum variable, let's store the sum of these two and let's finally print one more message

14:34.100 --> 14:34.940
in the terminal.

14:39.600 --> 14:41.310
Still, let's use the jet logger

14:45.510 --> 14:49.920
and let's print the message returning some.

14:50.130 --> 14:51.420
Followed by the sum.

14:52.020 --> 14:54.120
So here, let's use the double quotes.

14:55.350 --> 14:56.940
And now let's print.

14:58.330 --> 15:04.540
The sum of the two numbers that is in the response message under the name of the variable sum.

15:05.920 --> 15:11.740
This is all we need for the moment, for the definition of all the components of this simple service

15:11.740 --> 15:13.020
server class.

15:13.030 --> 15:16.240
And now we can move on to create the main function.

15:26.240 --> 15:29.390
And let's return zero.

15:29.390 --> 15:32.800
And here let's initialize the node with rcl.

15:33.060 --> 15:35.690
CPP init.

15:36.200 --> 15:38.810
Then let's create a new shared pointer.

15:38.810 --> 15:42.950
So a new shared pointer to the simple service server class.

15:43.130 --> 15:54.350
So let's create a new variable called Node and then let's use the function make shared from the standard

15:54.350 --> 15:55.670
C plus plus library.

15:56.360 --> 15:59.600
And we want this one to create a pointer.

15:59.600 --> 16:04.250
So a shared pointer to an object of the simple service server class.

16:05.330 --> 16:08.660
And so let's save this one within the node variable.

16:08.780 --> 16:15.260
And now let's keep this node up and running with the CPP spin function.

16:15.260 --> 16:17.510
So let's keep the node running.

16:17.510 --> 16:23.420
And then if, for example, we terminate the execution of the node with control C, let's shut down

16:23.420 --> 16:29.450
Ross with RCL cpp shut down function.

16:30.540 --> 16:34.740
With this, we have completed also our simple service server node.

16:34.770 --> 16:41.940
So before executing this node, let's modify also the file Cmakelists.txt in order to install it.

16:41.940 --> 16:48.000
So in order to declare the missing dependencies and also to install the new executable, first, we

16:48.000 --> 16:52.470
need to declare the dependency from the Arduino board messages library.

16:52.530 --> 16:55.560
So Arduino board messages.

16:55.560 --> 17:00.780
That is the package that contains the definition of the interface with the service.

17:01.630 --> 17:08.860
Then we can add a new execute table so we can basically copy these two instructions and we can paste

17:08.860 --> 17:09.580
it below.

17:09.580 --> 17:16.360
And so let's call this new executable simple service server.

17:17.420 --> 17:18.830
So let's copy this one.

17:18.980 --> 17:20.090
The Executable.

17:20.090 --> 17:23.760
So the script is also called Simple Service Server Dot CP.

17:24.320 --> 17:33.920
And then let's also add the the target dependencies to this script that are the RCL, CP and the Arduino

17:33.920 --> 17:34.890
board messages.

17:34.910 --> 17:36.980
So let's copy this one.

17:37.280 --> 17:39.620
Finally in the install section.

17:39.620 --> 17:42.320
So here we also need to install this new node.

17:42.320 --> 17:44.140
So the simple service server.

17:44.150 --> 17:50.150
So let's list it below the other executable that we have already created so far.

17:50.970 --> 17:56.310
Last but not least, since we used the Arduino bot messages in the new executable.

17:56.340 --> 18:00.900
Now we need also to declare its usage in the package dot XML.

18:00.960 --> 18:08.490
So here let's add a new dependency from the Arduino bot messages package.

18:08.670 --> 18:12.870
Now everything is set and we can proceed to run our node.

18:13.020 --> 18:19.380
So let's open a new terminal and let's go into the workspace and here let's build it.

18:19.770 --> 18:26.460
So click on Build so that the new node is compiled and we have an executable that we can run.

18:27.490 --> 18:27.910
Here.

18:27.910 --> 18:30.940
We forgot in the main function.

18:32.400 --> 18:32.940
Yes.

18:32.940 --> 18:33.300
Here.

18:33.300 --> 18:39.570
We forgot to pass the argument of the main to the cpp init.

18:39.690 --> 18:42.600
So let's save and build again.

18:43.790 --> 18:51.140
And also here we have another error because in the get logger we need to specify that we want the logger

18:51.140 --> 18:52.910
for the CP.

18:53.730 --> 18:57.930
So let's copy this one also here and here.

18:57.930 --> 19:00.930
So whenever we use the get logger function.

19:01.170 --> 19:03.690
So let's give it one more try.

19:07.710 --> 19:12.150
And now the build is finally successful so we can start using our node.

19:12.810 --> 19:14.400
So let's open a new terminal.

19:14.880 --> 19:16.890
And here let's search the workspace.

19:17.280 --> 19:20.010
So the file setup dot bash.

19:20.280 --> 19:23.700
And now we can finally run our service server.

19:23.700 --> 19:25.770
So, Ros to run.

19:26.340 --> 19:32.790
And from the Arduino bot CP examples, let's start the simple service server node.

19:33.120 --> 19:39.260
So let's press enter and as soon as we launch it, we have the confirmation that the server is ready.

19:39.270 --> 19:43.560
So the service server is ready and we can also double check it.

19:43.800 --> 19:50.670
If we open a new terminal and we launch the command Ros two service list.

19:50.880 --> 19:56.910
Actually we can see that among other services that were automatically created by Ros2, there is a word

19:56.910 --> 19:59.850
service, so the Add Chewins service.

20:00.240 --> 20:07.590
Furthermore, if we source the workspace also in this terminal, we can get additional information about

20:07.590 --> 20:14.320
the service and so about the type of the communication interface that the service Atkins is using.

20:14.320 --> 20:22.810
And we can do so with the command Ros2 service type, followed by the name of the service that is the

20:22.810 --> 20:24.250
Atkins.

20:24.400 --> 20:32.410
So let's press enter and we can see that this service is using the interface, Atkins declared in the

20:32.410 --> 20:33.790
Arduino bot messages.

20:34.770 --> 20:36.060
Also from the terminal.

20:36.060 --> 20:44.310
We can also send a request message to the service and so we can use the command rescue service call

20:44.310 --> 20:48.510
this time and then followed by the name of the service which we want to call.

20:48.720 --> 20:51.060
And this is the Add Chewins.

20:51.060 --> 20:57.270
And this is followed then by the type of the message interface that we need to use in order to contact

20:57.270 --> 20:58.400
with the server.

20:58.410 --> 21:05.400
If we press tab twice, we can see that Ross two is able to automatically detect the type of the interface.

21:05.610 --> 21:13.440
So let's type the interface and then if we use double quotes and press tab twice again, and then type

21:13.440 --> 21:18.990
the letter A and tab again, Ros two is able to autocomplete the text.

21:18.990 --> 21:22.200
And so here we have a prototype of the message.

21:22.200 --> 21:27.090
So of the request message that we can send directly to the service server.

21:27.240 --> 21:35.740
For example, let's ask the service server to calculate the sum between the number seven and five.

21:35.770 --> 21:37.300
So let's press enter.

21:37.300 --> 21:40.750
And as you can see, the request is sent to the service.

21:40.750 --> 21:47.680
So here it is, informing us that it received a new request and the request contains the numbers seven

21:47.680 --> 21:54.460
and five and also that it returned, it calculated correctly the sum and it is returning the correct

21:54.460 --> 21:58.330
sum to the client that then is receiving correctly.

21:58.450 --> 22:02.950
So here is the response that the client is receiving from the server.
