WEBVTT

00:00.200 --> 00:06.140
Now that we know how to create and use an action server and how to interact with it through the Ros

00:06.140 --> 00:12.860
to command line interface, let's see how to create a C plus plus action client node that use the Fibonacci

00:12.890 --> 00:16.220
action server we created in the last laboratory lesson.

00:18.010 --> 00:20.890
Just as we did for the action server node.

00:20.920 --> 00:26.310
Let's also place the node for the action client within the Arduino CP Examples package.

00:26.320 --> 00:34.900
And so within the source folder, let's create a new file called Simple Action Client Dot CPP.

00:35.260 --> 00:39.220
And here let's start by importing the CPP library.

00:39.820 --> 00:43.630
So let's include the CPP.

00:45.900 --> 00:48.090
And then let's create a new class.

00:48.090 --> 00:56.730
So a new node called Simple Action Client, which inherits from the node class.

00:56.910 --> 01:02.220
So from the CPP namespace from the node class.

01:03.210 --> 01:05.790
And so let's define this function here.

01:06.900 --> 01:09.450
Now let's include all these code.

01:09.450 --> 01:14.850
So let's include this class within our new namespace, as we did also for the action server.

01:15.480 --> 01:20.460
And so let's create a new namespace called as the name of the package.

01:20.460 --> 01:23.670
So Arduino boot CP

01:26.460 --> 01:27.420
examples.

01:27.780 --> 01:30.780
And within this one let's define our class.

01:31.230 --> 01:35.610
So here, let's start by creating the constructor.

01:35.610 --> 01:44.970
So the explicit constructor of the Simple Action Client class and this constructor here receives as

01:44.970 --> 01:48.150
input an object of type node options.

01:48.150 --> 01:57.240
So from RCL, CP, it receives a node options that we call options.

01:57.330 --> 01:58.560
And first.

01:58.560 --> 02:04.950
So when we create an object of the simple action client class, let's start by initializing the node

02:04.950 --> 02:05.550
class.

02:05.550 --> 02:11.530
So the base class and this receives a string as input that is the name that we want to give to the node,

02:11.560 --> 02:21.670
for example, simple action client, and also it eventually receives some node options that we have

02:21.670 --> 02:27.910
stored in the variable options now in order to create the actual action client.

02:27.910 --> 02:35.080
So the one that will communicate with the action server, we need to include another library and this

02:35.080 --> 02:38.230
is the CP action.

02:38.800 --> 02:43.630
So let's include this library and from this library let's create a new object.

02:43.630 --> 02:46.990
So here let's create a new private variable.

02:47.560 --> 02:51.160
So first let's make sure that the constructor is public.

02:52.270 --> 02:54.340
And now among the private variables.

02:54.340 --> 02:56.430
Instead, let's create a new object.

02:56.440 --> 03:04.960
So from the CP Action library that we have just imported, let's use the definition.

03:04.960 --> 03:11.470
So let's create a new object of type client as we saw in the previous Cplusplus laboratory lesson.

03:11.470 --> 03:18.460
To create the action server, we created a new instance of the server class from the CP action here.

03:18.460 --> 03:24.280
Instead to create the action client, we are creating an instance of the client class and so also this

03:24.280 --> 03:30.100
one is a template class to which we need to pass the message interface for the communication with the

03:30.100 --> 03:31.000
action server.

03:31.000 --> 03:34.720
And this is the same interface that we used for the action server.

03:34.720 --> 03:38.470
So the one that is defined in the Arduino bot messages package.

03:38.470 --> 03:47.140
So let's include this interface from the Arduino board messages from the action folder, let's include

03:47.140 --> 03:49.090
the Fibonacci interface.

03:49.090 --> 03:56.290
And so now let's declare that this client is going to use from the Arduino bot messages.

03:56.920 --> 04:04.690
This client from the action is going to use the Fibonacci interface.

04:05.080 --> 04:08.280
Now let's also take a shared pointer.

04:08.280 --> 04:14.370
So let's create a shared pointer to this class, so to the client class, and let's call this variable

04:14.460 --> 04:15.300
client.

04:15.510 --> 04:24.630
Since we are creating a shared pointer, let's also include the usage of the memory library.

04:24.630 --> 04:27.870
So of the memory module of the C plus plus standard library.

04:28.200 --> 04:34.560
And now we can initialize this client variable so we can initialize this shared pointer here within

04:34.560 --> 04:37.440
the constructor and we can use the function.

04:37.680 --> 04:44.550
So from the CP Action library, let's use the function create client also.

04:44.550 --> 04:50.670
This one is a template function and also this one requires that we pass as input the type of the interface.

04:50.670 --> 04:58.620
So once more the Fibonacci interface in order to create a shared pointer to the client object.

04:59.210 --> 05:01.040
And then it also requires.

05:01.040 --> 05:08.600
So in the parentheses here, it requires the instance of the ros2 node that contains the action client.

05:08.600 --> 05:11.600
So actually this is the current object.

05:11.600 --> 05:15.710
So the current class and we refer with the pointer.

05:15.710 --> 05:19.940
This also it receives the name of the action.

05:19.940 --> 05:27.710
So the name of the action server as recognized by Ros2 and this is the Fibonacci Action server.

05:28.620 --> 05:34.770
Now, let's also create another shared pointer, this time to a timer object.

05:34.890 --> 05:45.300
So still among the private variable, this time from the RCL, cpp from the timer base, let's create

05:45.480 --> 05:49.650
a shared pointer and let's call this one timer.

05:49.770 --> 05:51.480
And we already use this object.

05:51.480 --> 05:58.530
So the timer base object in a previous laboratory lesson in order to repeatedly execute a certain function

05:58.530 --> 06:00.930
at regular time intervals.

06:01.170 --> 06:03.570
So let's use this object also here.

06:03.570 --> 06:14.610
So let's initialize it within the constructor and let's use the function create wall timer that we inherited

06:14.610 --> 06:16.080
from the node class.

06:16.200 --> 06:23.430
And now let's also here use using the namespace

06:25.560 --> 06:26.310
Chrono

06:29.160 --> 06:38.360
Literals and using this namespace, let's specify that our wall timer will be executed every second,

06:38.370 --> 06:42.360
so the timer will expire every second.

06:42.360 --> 06:49.410
And now also within the create wall timer function, we also need to set so to define which is the function

06:49.410 --> 06:51.480
that has to be executed every second.

06:51.480 --> 06:59.280
So whenever the timer expires again, let's use the bind function from the standard C plus plus library.

06:59.280 --> 07:07.740
And we want to execute a function called timer callback that we are going to define within the simple

07:07.740 --> 07:09.240
action client class.

07:09.420 --> 07:16.890
So let's indicate that this function is defined or will be defined within the simple action client class.

07:17.190 --> 07:22.290
Then let's also use the pointer this to indicate that we want to use the current object.

07:22.290 --> 07:25.770
So the implementation of this function within the current object.

07:25.770 --> 07:27.060
And then that's all.

07:27.060 --> 07:31.870
So this will not receive any parameters, so we will not receive any input.

07:32.290 --> 07:33.490
Now let's move on.

07:33.490 --> 07:38.860
And among the private methods of this class, let's define this function.

07:39.040 --> 07:47.530
So the timer callback function and actually we don't need this function to be executed repeatedly every

07:47.530 --> 07:50.920
second we need it just to be executed once.

07:50.920 --> 07:53.050
So just the first time.

07:53.140 --> 08:01.900
So whenever we execute it for the first time, let's take the timer object and let's cancel it so that

08:01.900 --> 08:03.460
it will not be executed again.

08:03.460 --> 08:10.570
So basically, with this trick we made possible that the timer callback function is executed only once

08:10.570 --> 08:15.550
and also is executed after one second from the node initialization.

08:16.210 --> 08:21.820
Now, in this function, we just want to use the action client to send a goal to the action server and

08:21.820 --> 08:27.730
also receive the feedback, print the feedback and then print the result message once the server is

08:27.730 --> 08:28.240
done.

08:29.040 --> 08:34.230
However, before sending a goal to the action server, let's first verify that the action server is

08:34.230 --> 08:37.350
actually running and we can use the function.

08:37.620 --> 08:44.670
So on the client object, we can use the function wait for action server.

08:44.940 --> 08:52.050
This function blocks the execution of the client so blocks the execution of this current script until

08:52.050 --> 08:58.890
an action server that is called Fibonacci and that uses the Fibonacci interface becomes available in

08:58.890 --> 08:59.640
Ros two.

08:59.880 --> 09:06.370
So if this one never becomes available.

09:06.390 --> 09:09.510
So let's set that.

09:09.520 --> 09:11.400
It is not available.

09:11.580 --> 09:14.010
Let's print an error message in the terminal.

09:14.100 --> 09:18.420
So with the Http error.

09:25.620 --> 09:32.610
And let's print the message action server not available.

09:33.180 --> 09:35.640
After waiting.

09:35.640 --> 09:39.840
And in this case, let's shut down also the Ros two interface.

09:39.840 --> 09:41.820
So the CP.

09:43.750 --> 09:47.440
Shut down function otherwise.

09:47.450 --> 09:55.770
So if we go outside so here, if the server exists, we can request its execution by sending a new goal

09:55.790 --> 09:56.810
message to it.

09:57.800 --> 10:05.540
So let's start by creating a new goal variable that we call goal message.

10:05.540 --> 10:09.980
And this is an instance of the Arduino board message interface.

10:09.980 --> 10:13.610
And so of the action Fibonacci.

10:13.610 --> 10:17.990
And from this action, let's create an instance of the goal message.

10:20.110 --> 10:25.720
Now, for example, let's request the calculation of the Fibonacci sequence up to the order ten.

10:26.020 --> 10:31.630
So let's set the goal message and the order to be ten.

10:31.990 --> 10:34.480
Then let's also print an informative message.

10:41.280 --> 10:42.720
So here, let's say.

10:48.350 --> 10:55.880
Let's get the CP logger and let's print the message sending goal.

10:56.940 --> 11:00.300
Now to send actually the goal to the action server.

11:00.300 --> 11:04.260
We need to create a new object of the client class.

11:04.440 --> 11:12.060
So let's call this object, send goal options.

11:12.390 --> 11:20.820
And this is an instance of the Xcp action package of the client object.

11:20.940 --> 11:23.070
And this is a template function.

11:23.220 --> 11:27.780
And also in this case, we need to use the Fibonacci.

11:27.810 --> 11:29.430
So here we need to pass.

11:30.170 --> 11:36.920
The Fibonacci interface that the client has to use in order to communicate with the server and from

11:36.920 --> 11:37.880
this class.

11:38.420 --> 11:45.200
So from the client class, let's create an instance of the send goal options class.

11:45.200 --> 11:52.070
And now we can use this send goal option class to define a series of callback functions that will be

11:52.070 --> 11:58.100
executed when some event occurs during the interaction between the client and the server.

11:58.640 --> 12:06.090
So let's use this send goal option for example, to add a goal response callback.

12:06.110 --> 12:13.940
So with the goal response callback and with this we can define the function so the behavior that the

12:13.940 --> 12:17.870
client will execute after sending the goal to the action server.

12:17.870 --> 12:24.650
So basically when the action server responds to the action client saying whether or not it accepted

12:24.650 --> 12:25.670
the goal.

12:26.090 --> 12:34.970
So let's use again the bind function of C plus plus, and let's say that we are going to execute a function

12:34.970 --> 12:43.370
called goal callback and that we are going to define this function within the simple action client.

12:44.000 --> 12:50.810
So let's say that here we are going to define this function within the simple action client class and

12:50.810 --> 12:55.850
also that we want to use the current object, the current implementation.

12:55.850 --> 13:00.170
And then also this function will receive one parameter as input.

13:00.350 --> 13:03.410
So here let's use.

13:06.420 --> 13:10.620
The namespace placeholders.

13:11.040 --> 13:18.090
And from this namespace let's use the placeholder one to indicate that the goal callback function will

13:18.090 --> 13:19.590
receive one variable.

13:19.590 --> 13:21.210
So one parameter as input.

13:21.800 --> 13:25.310
Now let's still use the send goal option class.

13:25.640 --> 13:32.120
So the send goal option instance that we have just created.

13:34.510 --> 13:37.960
And let set also a feedback callback function.

13:37.960 --> 13:43.960
So let's set the feedback callback function that is the function that will be executed every time the

13:43.960 --> 13:49.990
action server sends a feedback message to the client to inform it about the progress of the action.

13:50.500 --> 13:57.100
Again, let's use the bind function to set the name of the function and we are going to call this one

13:57.760 --> 14:00.520
feedback callback.

14:00.550 --> 14:05.500
Again, we are going to define this one within the simple action client class.

14:06.640 --> 14:14.560
Let's pass the pointer This and the feedback callback function will receive two inputs.

14:14.560 --> 14:16.660
So two variables as input.

14:16.660 --> 14:22.870
And so let's use the placeholders one and two to indicate that it's going to receive two inputs.

14:23.110 --> 14:33.910
Finally, let's use one more time the send goal option object that we have created in order to set a

14:33.910 --> 14:35.750
result callback function.

14:35.750 --> 14:42.200
So the function that will be executed when the action server terminates its execution and returns a

14:42.200 --> 14:44.000
result message to the client.

14:44.330 --> 14:55.730
And also let's use the bind function also in this case and we are going to execute the result callback

14:55.730 --> 15:04.610
function still defined within the simple action client class and we want to use the current implementation

15:04.610 --> 15:09.380
of this function and it is going to receive just one parameter as input.

15:10.330 --> 15:10.900
At this point.

15:10.900 --> 15:18.010
We have here the goal message that contains the actual goal that we want to send to the action server.

15:18.010 --> 15:22.990
And so, for example, the order of the Fibonacci sequence that we are going to execute is ten.

15:23.410 --> 15:29.710
And then also we have defined several callback functions, one for each event that is generated by the

15:29.710 --> 15:30.610
action server.

15:30.610 --> 15:37.060
So this one, the goal callback function, then the feedback callback function and the result callback

15:37.060 --> 15:37.810
function.

15:37.930 --> 15:42.340
Now we can finally send the goal to the action server.

15:42.340 --> 15:51.250
So let's use the client variable and then let's use the function async send goal.

15:51.400 --> 15:56.380
So let's use this function here and it receives as input the goal message.

15:57.160 --> 16:03.430
So the actual goal that contains the order of the Fibonacci sequence and also the goal options.

16:03.430 --> 16:10.970
So the variable that we called send goal options, which contains all the callback functions that are

16:10.970 --> 16:12.410
going to be executed.

16:12.950 --> 16:20.420
Now let's proceed to define each of these callback functions, starting from the goal callback function

16:20.420 --> 16:25.970
which is executed when the client has finished sending the goal message to the server and the server

16:25.970 --> 16:28.730
has accepted or rejected the goal.

16:29.300 --> 16:37.130
So here, still within the private attributes of the simple action client class, let's define the goal

16:37.130 --> 16:38.420
callback function.

16:38.570 --> 16:41.480
And it receives as input an object.

16:41.660 --> 16:55.040
So from the CPP action library, it is an object of type client goal and this is a template class.

16:55.040 --> 17:00.140
And also we receive a shared pointer to this object.

17:00.380 --> 17:04.370
And let's call this one goal Endl.

17:05.330 --> 17:12.830
As the client goal and class is a template class we need to provide to this class the type of the interface

17:12.830 --> 17:16.100
that is used in order to communicate with the action server.

17:16.490 --> 17:18.800
And so the interface is this one.

17:18.800 --> 17:24.530
So the Fibonacci interface defined in the Arduino board messages within this function.

17:24.530 --> 17:30.860
So within the goal callback function, the first thing that we are going to do is to check whether or

17:30.860 --> 17:34.040
not the goal has been accepted by the action server.

17:34.220 --> 17:39.910
So let's check if not goal and all.

17:39.950 --> 17:43.850
So this means that the goal has not been accepted in this case.

17:43.850 --> 17:45.620
Let's print an error message.

17:47.960 --> 17:50.240
So let's print an error message.

17:50.570 --> 18:02.870
Let's use the Http get logger function to get the Xcp logger and let's print the message.

18:02.960 --> 18:07.820
Goal was rejected by the server.

18:09.470 --> 18:11.230
And otherwise.

18:11.240 --> 18:19.760
So else this means that the goal has been accepted and so we can print an informative message in the

18:19.760 --> 18:20.420
terminal.

18:25.320 --> 18:27.630
So let's still get the longer.

18:35.670 --> 18:38.940
And the message says go.

18:40.760 --> 18:43.820
Accepted by the server.

18:44.720 --> 18:47.900
Waiting for a result.

18:49.310 --> 18:52.820
And with this, our goal callback function is completed.

18:52.820 --> 18:58.970
So basically it will just print two messages in the terminal whether or not the goal has been accepted

18:58.970 --> 19:00.800
by the server or rejected.

19:01.570 --> 19:05.420
Next, let's move on to define the feedback callback function.

19:05.440 --> 19:13.150
So still here among the private attributes of the simple action client class, let's define the feedback

19:13.390 --> 19:14.770
callback function.

19:16.210 --> 19:22.120
And it receives also a shared pointer to a client goal handle object.

19:22.150 --> 19:25.570
So the input is the same as this one.

19:26.500 --> 19:30.040
So let's copy this one and let's paste it.

19:30.160 --> 19:35.170
And then it also receives the actual feedback message of the Fibonacci interface.

19:35.260 --> 19:42.610
So it takes two parameters as input and the second one is another shared pointer.

19:46.870 --> 19:53.170
This time to a const object of the class Arduino board messages.

19:53.590 --> 19:57.370
So from the interface Fibonacci.

20:00.040 --> 20:02.230
The feedback message.

20:03.350 --> 20:06.710
And let's call this one feedback.

20:07.010 --> 20:13.400
Let's format it a little bit better so that we can easily see it.

20:14.610 --> 20:18.540
Actually in the feedback callback function, this doesn't need to be const.

20:18.840 --> 20:24.630
And also we can remove the name of the variable since we are not going to use the goal endl object,

20:24.630 --> 20:29.880
but you are just going to print in the terminal the feedback message that was just received.

20:30.240 --> 20:37.350
So in this function here, upon receiving the new feedback message, let's simply print the partial

20:37.350 --> 20:38.910
sequence into the terminal.

20:39.030 --> 20:48.540
So let's create a new object of type string stream, and let's call this one string stream.

20:48.540 --> 21:01.230
And then let's add to this stream, the string next number in sequence received.

21:01.830 --> 21:04.800
And so let's print the number.

21:04.800 --> 21:11.850
So here now for each of the elements that appear in the partial Fibonacci sequence, let's add them

21:11.850 --> 21:13.200
to the string stream.

21:13.560 --> 21:26.410
So for each number that appear in the feedback message and in the partial sequence, let's simply add

21:26.410 --> 21:27.700
it to the string stream.

21:27.700 --> 21:37.210
So to the SS object, let's append the number and then let's also append a space in order to improve

21:37.210 --> 21:38.380
its readability.

21:39.070 --> 21:43.450
And then after this for loop, let's simply print a new message into the terminal.

21:58.520 --> 22:02.480
And so in this message, let's just print the SS object.

22:02.510 --> 22:10.370
Let's convert this one into a string and then into a C type string so that we can print it with the

22:10.790 --> 22:12.860
CP info function.

22:13.250 --> 22:17.420
Now we are only missing to define the result callback function.

22:17.420 --> 22:20.210
So still let's define this one.

22:24.230 --> 22:29.510
And this function receives as input an object of the wrapped result class.

22:30.020 --> 22:35.330
This class is defined within the CPP action.

22:35.870 --> 22:43.250
Then within the definition of the client goal end class, which is a template class and which takes

22:43.250 --> 22:45.430
as input the type of the interface.

22:45.440 --> 22:47.930
So the Fibonacci interface.

22:48.620 --> 22:58.130
And then from this one, let's take the rapid result class and let's call this variable result in order

22:58.130 --> 23:01.310
to access to the result of the action server.

23:01.460 --> 23:09.440
So this variable contains some codes, so different codes that represents the result of the action execution.

23:09.440 --> 23:16.280
And so we can use a switch statement in order to check which was the output of the action server.

23:16.640 --> 23:25.860
So let's use a switch statement on the result variable and on the code that it returns in order to check

23:25.860 --> 23:26.730
the status.

23:27.090 --> 23:31.700
So if the action server completed successfully, then the status.

23:31.710 --> 23:41.970
So the result code is of type CPP action, then result code succeeded.

23:42.510 --> 23:47.190
So this is the status when the action server execution is completed correctly.

23:47.340 --> 23:54.360
In this case, we don't print any message into the terminal and let's simply break the switch statement.

23:55.050 --> 23:56.010
Otherwise.

23:56.010 --> 24:03.720
So case, if it's concluded in an aborted state, the code that is returned by the result variable is

24:03.720 --> 24:07.470
of type lclc-rp action.

24:08.260 --> 24:10.450
And still from the result code.

24:10.450 --> 24:13.090
This is of type aborted.

24:13.630 --> 24:16.840
And in this case, let's print an error message in the terminal.

24:16.840 --> 24:17.470
So.

24:22.490 --> 24:28.730
Let's use the TCP get logger function.

24:32.480 --> 24:38.030
To print the message goal was aborted.

24:38.030 --> 24:41.810
And also in this case, let's terminate the execution of the function.

24:42.050 --> 24:45.170
So with the return otherwise.

24:45.200 --> 24:50.180
So a new case if the action server completed with a cancel code.

24:50.420 --> 24:59.210
So it returns a code of type Lclc-rp action result code cancelled.

24:59.450 --> 25:02.840
And so in this case, let's print a message in the terminal.

25:02.840 --> 25:04.730
So let's copy this one.

25:05.840 --> 25:11.360
And the message says goal was cancelled.

25:11.360 --> 25:13.490
And also in this case, let's return.

25:13.490 --> 25:16.430
So let's terminate the execution of this function.

25:16.550 --> 25:21.590
Finally, if none of this code is returned.

25:21.590 --> 25:27.740
So if the code of the action server doesn't fall into any of the previous categories, let's print another

25:27.740 --> 25:31.280
error message in the terminal that says so here.

25:31.280 --> 25:34.160
Unknown result code.

25:34.160 --> 25:37.190
And also in this case, let's return.

25:37.190 --> 25:41.480
So let's terminate the execution of the function after the switch statement.

25:41.480 --> 25:48.260
So after this statement here, if this script so the result callback function is still executing, it

25:48.260 --> 25:53.390
means that basically the result code of the action server was succeeded.

25:53.480 --> 26:00.110
So we felt in this case because otherwise we would have returned the function.

26:00.110 --> 26:03.380
So the function will not still be executing.

26:03.380 --> 26:09.650
So in this function let's just print the full Fibonacci sequence that we received in the result message.

26:09.650 --> 26:14.840
So it means that the action completed successfully and so we can print the full sequence.

26:14.840 --> 26:20.180
So the full Fibonacci sequence into the terminal, we can copy exactly what we did for the feedback

26:20.180 --> 26:20.900
message.

26:21.140 --> 26:24.860
So let's copy this one and let's paste it here.

26:24.860 --> 26:29.930
And the only thing that we need to change is that here we don't have the feedback message, but we have

26:29.930 --> 26:31.850
the result message.

26:31.850 --> 26:35.540
And from this one, let's take the result.

26:35.540 --> 26:40.070
And then from the result interface the object.

26:40.070 --> 26:44.210
So the variable that contains the full sequence is called simply sequence.

26:45.350 --> 26:46.130
Finally.

26:46.130 --> 26:51.970
So here within this function, since with this, the client has successfully sent the goal to the action

26:51.980 --> 26:55.280
server and also has successfully received the result.

26:55.310 --> 27:03.290
We can shut down already this node with rcl cp-rp shut down function.

27:04.730 --> 27:10.790
With this, the simple action client node is completed and now we can define the main function where

27:10.820 --> 27:13.040
actually its functionalities are used.

27:13.770 --> 27:16.890
To start a ros2 node that implements an action client.

27:16.920 --> 27:23.820
We can follow the same approach that we used for the action server and namely we can import a new library.

27:24.930 --> 27:28.380
So let's include the library Rql CPP

27:31.650 --> 27:32.790
components.

27:32.790 --> 27:41.550
And from this library let's include the register node macro and then from this library at the end of

27:41.550 --> 27:46.000
this script and also take care of inserting it at the end of the namespace.

27:46.020 --> 27:56.040
Let's use the macro Rql CPP components register node.

27:56.910 --> 28:01.350
And now let's pass the name of the class which implements the action client.

28:01.590 --> 28:07.020
So this is in the Arduino CPP examples and is called the Simple Action Client.

28:07.870 --> 28:09.330
Let's save this note.

28:09.340 --> 28:15.670
And now we can instruct the compiler on how it should build and make this a C plus plus script and executable.

28:16.090 --> 28:23.080
So here in the cmakelists.txt for installing the node that implements the action client, we can copy

28:23.080 --> 28:26.850
paste the same instructions that we used also for the action server.

28:26.860 --> 28:31.480
So all of these instructions and let's paste it below.

28:31.480 --> 28:36.430
And now we need to do some small changes, like for example the name of the executable.

28:36.580 --> 28:39.520
That is a simple action client.

28:40.240 --> 28:41.230
Let's copy this one.

28:41.230 --> 28:46.600
Also, the name of this script is the Simple Action Client Dot CP here.

28:46.600 --> 28:48.790
Let's change the name of the executable.

28:49.180 --> 28:56.770
Let's also change it here, the name of the executable and also here in the C plus plus building DLL.

28:57.160 --> 29:00.760
This is the simple action client.

29:01.030 --> 29:06.220
Also here, let's change the name of the executable, the dependencies of this script.

29:06.220 --> 29:09.140
So this simple action client node are the same.

29:09.680 --> 29:14.600
Let's also change the name of the executable here and let's change it here.

29:15.200 --> 29:21.740
So we are going to call this one simple action client node and the plugin is defined still in the Arduino

29:21.890 --> 29:29.270
CP examples namespace, but this time the class is the simple action client.

29:30.130 --> 29:33.010
Finally, let's also copy the name of this library.

29:33.010 --> 29:37.390
So the simple action client and let's list it where we list it.

29:37.390 --> 29:42.820
So in the install instruction where we already inserted and we already installed this simple action

29:42.820 --> 29:43.420
server.

29:43.990 --> 29:46.090
So let's save also this file.

29:46.090 --> 29:52.720
And since we haven't added any new dependencies, we don't need to modify the package dot XML file so

29:52.720 --> 29:56.710
we can directly proceed to build our workspace and run our node.

29:56.710 --> 30:02.620
So in a new terminal, let's go to the workspace and let's build it.

30:06.900 --> 30:09.030
We can see that the build failed.

30:09.030 --> 30:12.210
So most probably we did something wrong.

30:12.240 --> 30:19.110
So normally, in order to correctly debug some cplusplus node, let's go at the beginning of the error.

30:19.790 --> 30:25.430
And so we can see that there is an error in the declaration of the feedback callback function.

30:25.610 --> 30:28.160
So let's go back to Visual Studio Code.

30:29.040 --> 30:30.360
The simple action client.

30:31.380 --> 30:38.070
And actually this function doesn't need a reference, so let's save this one.

30:38.710 --> 30:45.430
Now also, we can see that Visual Studio code is correctly recognizing this function and we can build

30:45.430 --> 30:46.690
our workspace again.

30:50.180 --> 30:52.750
And also there is another error.

30:52.760 --> 30:58.610
So this time it is related to the node options which the required form.

30:58.610 --> 31:01.940
So the required node option format is to be const.

31:02.670 --> 31:08.160
So back in Visual Studio code, this one here needs to be const.

31:08.850 --> 31:11.790
Let's try to build it one more time.

31:12.480 --> 31:13.980
So Qualcomm build.

31:17.140 --> 31:23.890
And now everything is fine so we can move on to start first our action server and then the action client

31:23.890 --> 31:25.660
that we created in this lesson.

31:25.990 --> 31:29.500
So let's start by opening a new terminal here.

31:29.500 --> 31:30.910
Let's source the workspace.

31:31.450 --> 31:37.480
So the file setup dot bash and from the Arduino bot.

31:38.060 --> 31:39.620
CP examples.

31:39.650 --> 31:43.250
Let's start the simple Action server node.

31:43.280 --> 31:45.110
So let's press enter.

31:45.110 --> 31:49.790
And now that the action server is running, we can also start the client.

31:50.090 --> 31:56.540
So in a new terminal, let's still source the setup dot batch file.

31:56.630 --> 31:58.340
And here let's run.

31:58.340 --> 32:04.550
So with the command Ros to run from the Arduino but Pi examples package.

32:04.820 --> 32:09.110
Let's start the simple action client node.

32:09.140 --> 32:10.070
Okay, this one.

32:10.280 --> 32:17.420
So let's press enter and as soon as we start the client, we see that the message that appears is call

32:17.420 --> 32:18.410
accepted.

32:18.410 --> 32:24.590
And also it means that the action server has accepted our goal and also we can see that it begins to

32:24.590 --> 32:25.010
send.

32:25.010 --> 32:31.940
And so to print also feedback messages with the partial Fibonacci sequence calculated up to this moment.

32:32.240 --> 32:35.510
Then also we can see that at the end of the execution of the action.

32:35.510 --> 32:42.360
So when the sequence has reached the desired order that we specified in the goal message, the server

32:42.360 --> 32:45.750
also returns the result with the complete sequence.

32:45.750 --> 32:49.230
And so then the client terminates its execution.

32:49.840 --> 32:52.120
Now let's try a different thing.

32:52.120 --> 32:58.180
So, for example, let's try to interrupt the action server and let's try.

32:58.210 --> 33:07.330
So if we use the command Ros2 action list, actually we can see that there are no action servers available

33:07.330 --> 33:08.350
in Ros2.

33:08.770 --> 33:13.660
And now if we start the client again, we can see that basically nothing happens.

33:13.660 --> 33:19.090
So this node remains idle and this is waiting for the action server to be started.

33:19.270 --> 33:23.950
And this is thanks to the function wait for action server.

33:23.950 --> 33:27.100
So this is thanks to this statement here.

33:28.380 --> 33:33.990
In fact, we can see that as soon as we start the action server again, then the action client is able

33:33.990 --> 33:34.840
to send the goal.

33:34.860 --> 33:42.120
So the goal is accepted and also it starts receiving feedback messages and then at the end it also receives

33:42.120 --> 33:43.620
the result message.
