WEBVTT

00:00.370 --> 00:07.270
In this laboratory lesson, we will create a simple Python action server that calculates the Fibonacci

00:07.270 --> 00:08.050
sequence.

00:08.470 --> 00:16.090
By implementing these actions, we will have a practical example of how to use the Ros two actions and

00:16.090 --> 00:22.330
then we will use this as a template for implementing a more complex application in the upcoming lesson

00:22.360 --> 00:23.230
of the course.

00:24.290 --> 00:29.990
If you are only interested in the C plus plus development, then you can skip to the next lesson in

00:29.990 --> 00:33.860
which we are going to implement the same action server in C plus plus.

00:35.550 --> 00:41.880
In this lesson, we want to use the two actions to implement a node that calculates the Fibonacci sequence.

00:42.360 --> 00:49.690
In mathematics, the Fibonacci sequence, also known as Golden sequence, is a sequence of integers

00:49.710 --> 00:56.010
numbers where each number is the sum of the two preceding ones, except for the first two numbers,

00:56.010 --> 00:58.890
which are by definition zero and one.

00:59.250 --> 01:03.630
The length of the Fibonacci sequence is defined as the order.

01:03.630 --> 01:09.900
For example, the first two numbers of this sequence indicate the order, one of this sequence.

01:09.930 --> 01:16.230
Then the order two of the sequence is represented by the other number one, which is the sum of the

01:16.230 --> 01:17.730
two preceding numbers.

01:17.730 --> 01:22.620
And then the order three of this sequence is represented by the number two and so on.

01:22.650 --> 01:25.170
The sequence continues indefinitely.

01:26.150 --> 01:32.240
Diction server we are going to implement in this lesson will receive the order of the Fibonacci sequence

01:32.240 --> 01:39.620
as a goal and will return the entire Fibonacci sequence up to the requested order as an output referred

01:39.620 --> 01:41.990
to as the result of the action.

01:42.320 --> 01:49.730
So let's add this node that contains the action server in the Arduino bot Pi examples package.

01:49.730 --> 02:01.040
So here in the Arduino Pi example sub folder, let's create a new file called Simple Action Server dot

02:01.040 --> 02:01.310
pi.

02:01.880 --> 02:09.110
As usual, let's start by importing the Pi library and then still from this library.

02:09.110 --> 02:18.290
So from the Pi, from the node modules, let's import the node class and let's use it to define a new

02:18.290 --> 02:18.860
node.

02:19.190 --> 02:25.400
So let's define a new class called Simple Action Server.

02:25.400 --> 02:29.700
And this one inherits from the Node class.

02:29.970 --> 02:33.420
And then let's start by defining the constructor of this class.

02:34.080 --> 02:41.220
So the init function that is a member of this class and within the constructor, the first thing that

02:41.220 --> 02:44.250
we do is to call the constructor of the base class.

02:44.250 --> 02:45.870
So of the node class.

02:46.830 --> 02:54.390
So let's call the init function of the base class to which we pass the name of the node that we call

02:54.390 --> 02:58.140
simple Action server.

02:58.720 --> 03:07.930
Now to create an action server inside this node, let's import from the SQL Pi Library and this time

03:07.930 --> 03:14.200
from the action module, let's import the definition of the Action server class.

03:14.200 --> 03:17.740
And now let's create this class to instantiate a new object.

03:17.740 --> 03:25.210
So here in the constructor, let's create a new variable called Action Server.

03:25.330 --> 03:29.440
As an instance of the Action server class.

03:29.440 --> 03:34.930
And this class is responsible for creating and managing the communication of an action server.

03:35.320 --> 03:39.640
The constructor of this class takes as input the Ross to node.

03:39.640 --> 03:45.220
So the implementation of the node class, which is the current object.

03:45.220 --> 03:47.140
And so the simple action server.

03:47.140 --> 03:53.140
This is our implementation and we access to this one with the self variable.

03:53.140 --> 03:57.520
So we refer to the simple action server with the variable self.

03:57.880 --> 04:03.410
It also takes as input the communication interface that has to be used for the communication with the

04:03.410 --> 04:03.950
action.

04:03.950 --> 04:10.700
And so the interface which specifies how the goal, the feedback and the response messages for the communication

04:10.700 --> 04:12.260
with the action are done.

04:12.710 --> 04:15.470
So let's start by defining this interface.

04:15.470 --> 04:22.430
And once again, as this is a Ros two interface, we can define it within the Arduino Bot messages package.

04:22.640 --> 04:30.710
And so here in this package, as we defined the interface with a service in the SRV folder to define

04:30.710 --> 04:36.380
the interface with an action, we need to create a new folder called Action.

04:36.380 --> 04:43.400
And this folder let's create a new file called Fibonacci Dot Action.

04:43.400 --> 04:49.190
And here we need to indicate how the goal result and feedback messages are done.

04:49.760 --> 04:52.460
So let's start with the goal message.

04:53.750 --> 05:00.110
And this is composed by a single integer that indicates the order of the Fibonacci sequence that we

05:00.110 --> 05:01.850
want the server to calculate.

05:02.150 --> 05:06.740
So this is an integer and is called order.

05:06.920 --> 05:14.420
Next, let's use three dashes and then let's also define the result message.

05:14.630 --> 05:20.810
And so the result message should contain a list of integer, this time representing the full Fibonacci

05:20.840 --> 05:23.360
sequence that was calculated by the server.

05:23.570 --> 05:30.080
So let's use an array of integers and let's call this one sequence.

05:30.080 --> 05:37.400
And finally, still, by using three dashes, let's also define the feedback message.

05:37.400 --> 05:43.730
And so the message that the server will send periodically whenever we add a new element to the sequence.

05:43.730 --> 05:52.010
And also this one is an array, so an array of integers and let's call this one partial sequence.

05:52.220 --> 05:54.380
So let's save this interface.

05:54.380 --> 06:00.950
And now let's make sure that this interface is installed and also it's usable by other node by modifying

06:00.950 --> 06:04.130
once again the file Cmakelists.txt.

06:05.130 --> 06:10.020
Now still in the Ros generate interfaces instruction.

06:10.020 --> 06:13.370
We can also define the interface with an action.

06:13.380 --> 06:22.830
And so let's define the interface that we declared in the action folder and that is called Fibonacci

06:23.490 --> 06:24.900
dot action.

06:25.260 --> 06:27.000
Let's save this file.

06:27.000 --> 06:29.990
And finally in the package dot XML.

06:30.000 --> 06:34.850
So here of the Arduino bot messages, let's also add a dependency.

06:34.860 --> 06:44.580
So here let's add a dependency from the action messages.

06:44.580 --> 06:49.290
And now we can finally save also this file and we can move on.

06:49.290 --> 06:55.980
And so we can build our workspace so that the new interface, the Fibonacci action interface is compiled

06:55.980 --> 06:59.490
and we can start using it within our simple action server.

06:59.910 --> 07:01.620
So let's open a new terminal.

07:02.670 --> 07:06.360
Let's go to the workspace and let's build it.

07:11.610 --> 07:14.130
Now we can finally start using our interface.

07:14.460 --> 07:26.250
So here from the Arduino bot messages and from the action folder, let's import the Fibonacci interface.

07:26.250 --> 07:30.360
And now let's use this one to initialize the action server object.

07:30.360 --> 07:36.180
So here in the constructor of the action server object, let's say that this action server is going

07:36.180 --> 07:39.570
to use the Fibonacci interface.

07:39.570 --> 07:43.440
And also let's assign a name to the action server.

07:43.560 --> 07:51.690
Let's call this one for example, Fibonacci, and this is the name that other Ros two nodes can use

07:51.720 --> 07:54.870
in order to send goals to the action server.

07:54.870 --> 08:01.710
And so in order to calculate the Fibonacci sequence, finally for the constructor, we also have to

08:01.710 --> 08:08.310
define the name of the function that this server will execute whenever a new goal message is received,

08:08.340 --> 08:13.750
which is the function that contains the logic for the calculation of the Fibonacci sequence itself.

08:14.310 --> 08:17.100
We call this the call callback function.

08:17.100 --> 08:26.190
So let's use the goal callback function and we are going to define this function still within the simple

08:26.190 --> 08:26.790
action server.

08:26.820 --> 08:34.020
So as a member of the Simple Action server class, with this we have instantiated and initialized a

08:34.020 --> 08:41.730
new action server that is called Fibonacci, which uses a message interface called Fibonacci that is

08:41.730 --> 08:44.550
defined in the Arduino board messages package.

08:45.210 --> 08:45.930
Next.

08:45.930 --> 08:49.140
Still in the constructor, let's print an informative message.

08:49.500 --> 09:02.280
So with the get logger function, let's print an informative message that says Starting the server.

09:02.370 --> 09:06.990
And now let's go on and also define the callback function.

09:06.990 --> 09:13.800
So the goal callback function as a member of the simple action server class.

09:14.520 --> 09:16.440
As this function will be executed.

09:16.440 --> 09:23.120
Whenever a client sends a new goal to an action server, it receives the goal message as an input.

09:23.130 --> 09:27.810
So the one that we defined in the Fibonacci action interface.

09:28.020 --> 09:32.250
And so let's call this variable goal Endl.

09:33.180 --> 09:37.440
So when this function is called, let's start by printing an informative message.

09:38.100 --> 09:42.210
So still with the get logger function.

09:42.720 --> 09:45.060
Let's print an informative message.

09:45.060 --> 09:54.030
And this message says received call request with order.

09:54.210 --> 09:57.920
And then let's print the order that was just received.

09:57.930 --> 10:04.340
And so basically we can display the order by accessing the goal handle.

10:04.380 --> 10:11.520
And from this one, let's access to the request and then to the order.

10:12.270 --> 10:18.570
Next, let's create a new feedback message that will be sent periodically to the client, informing

10:18.570 --> 10:22.260
it about the progress of the Fibonacci sequence calculation.

10:22.620 --> 10:32.880
So let's call this one feedback message, and this is from the Fibonacci interface, an instance of

10:32.980 --> 10:35.470
the feedback message feedback.

10:36.580 --> 10:37.210
Okay.

10:37.210 --> 10:43.390
And we can already initialize it with the first two numbers that always make up a Fibonacci sequence.

10:43.390 --> 10:53.650
So let's access to the feedback message and to the partial sequence and let's initialize the sequence

10:53.650 --> 10:59.350
with the numbers zero and one that always are present within the Fibonacci sequence.

10:59.930 --> 11:04.320
And now we can implement the actual logic for the Fibonacci sequence calculation.

11:04.340 --> 11:08.150
So let's create a for loop that goes from one.

11:08.150 --> 11:12.110
So let's create a new variable E in range.

11:12.680 --> 11:16.250
And so this goes from one until the requested order.

11:16.670 --> 11:22.370
So the goal Endl request order.

11:23.210 --> 11:28.070
So this for loop goes from one to the requested order of the Fibonacci sequence.

11:28.250 --> 11:33.380
And then at each iteration of this loop, let's add a new element to the partial sequence.

11:33.380 --> 11:41.180
So to the feedback message, to the partial sequence, which is an array.

11:41.210 --> 11:49.670
Let's append a new element, and this new element is given by the sum with the last element that is

11:49.670 --> 11:51.350
present in the partial sequence.

11:51.680 --> 11:55.070
So let's take again the partial sequence.

11:56.440 --> 12:00.100
Here and let's access to the last element.

12:00.100 --> 12:06.220
So to the element, to the position I and let's add to this one the element at the previous position.

12:06.220 --> 12:08.170
So the second last one position.

12:08.380 --> 12:15.880
So still to the partial sequence, let's access to the element I minus one at each iteration.

12:15.880 --> 12:18.880
Let's also print an informative message in the terminal.

12:20.140 --> 12:31.270
So with the get logger function, let's print an informative message with the current feedback.

12:31.270 --> 12:33.580
So feedback.

12:34.090 --> 12:36.460
And then let's print the partial sequence.

12:36.970 --> 12:44.110
So let's format this string in order to print the feedback message partial sequence.

12:44.110 --> 12:49.540
So in order to print the Fibonacci sequence that we have calculated up to this moment, so up to this

12:49.540 --> 12:50.650
loop iteration.

12:51.680 --> 12:59.180
Then by using the goal and object, we can send this feedback message also to the client, informing

12:59.180 --> 13:01.310
it about the progress of the server.

13:01.760 --> 13:09.740
To do so, let's use the function, publish feedback of the goal and object.

13:09.740 --> 13:13.070
And to this one we pass the feedback message.

13:14.150 --> 13:20.120
Finally to simulate that the action server is performing as low and resource intensive operation.

13:20.120 --> 13:22.940
So an operation that takes some time to complete.

13:22.970 --> 13:25.040
Let's add a slip to the loop.

13:25.040 --> 13:28.520
And so this will pause the execution of the script for a second.

13:28.520 --> 13:33.140
So at each iteration of this loop, let's pause the execution for one second.

13:33.620 --> 13:38.120
To do so, let's import the Python time library.

13:38.450 --> 13:40.090
And now from this library.

13:40.100 --> 13:47.750
So from the time library, let's use the slip function to make this script slip for one second and then

13:47.750 --> 13:52.910
it will continue with the execution of the for loop once the loop is finished.

13:52.910 --> 13:58.550
So the action server will have calculated all the numbers in the Fibonacci sequence and also will have

13:58.550 --> 14:02.990
sent a feedback message for each of the elements that it has calculated.

14:03.080 --> 14:08.270
And so now we can conclude the action and return a result message to the client.

14:08.510 --> 14:15.120
So let's use the goal and goal variable and let's set this one to succeed.

14:15.930 --> 14:22.590
And then let's also create a new result message as an instance of the Fibonacci interface.

14:23.610 --> 14:27.510
And so of the result message that we declared in this interface.

14:27.510 --> 14:31.620
And now so this is the result variable.

14:31.920 --> 14:37.770
And now let's set to the result variable to the sequence.

14:37.770 --> 14:44.670
Let's set basically the full Fibonacci sequence and so we can set this one equal to the feedback message,

14:44.670 --> 14:45.990
partial sequence.

14:45.990 --> 14:52.800
Since up to this point, the partial sequence already contains all the elements that makes up the Fibonacci

14:52.800 --> 14:56.670
sequence up to the requested order so we can set this one.

14:56.760 --> 15:02.790
The sequence of the result equal to the last partial sequence that is in the feedback message.

15:03.030 --> 15:12.210
And so let's return exactly this result message to the client which requested the execution of these

15:12.240 --> 15:13.230
actions.

15:13.860 --> 15:16.260
With this the simple action server node.

15:16.380 --> 15:20.730
So this class is completed and now we can define the main function.

15:27.840 --> 15:34.560
And this calls the function main that we can define here.

15:35.940 --> 15:37.980
So let's define the function main.

15:37.980 --> 15:45.420
And now within this function, let's start by initializing ros2 with rcl pi init.

15:45.840 --> 15:49.320
Then let's create a new instance of the simple action server.

15:49.560 --> 15:57.870
So let's call this variable simple action server as an instance of the simple action server and let's

15:57.870 --> 15:59.130
keep this node up and running.

15:59.130 --> 16:03.590
So let's keep the action server up and running ready to receive new goals.

16:03.600 --> 16:11.490
So let's use the Pi spin function to spin the simple action server.

16:11.490 --> 16:18.840
And as usual, when we press control C, let's make the shutdown of this node so simple Action server.

16:18.840 --> 16:27.750
Let's destroy the node, destroy the node and also let's make the Pi shut down.

16:27.750 --> 16:29.970
So let's call this shutdown of this node.

16:31.140 --> 16:38.910
As usual, in order to compile and install this script, we need to add it into the setup.py file.

16:38.940 --> 16:43.200
So here we need to add a new line in the console script.

16:43.200 --> 16:50.700
So in the entry points so we can copy the one for the simple service client and let's call this one.

16:51.410 --> 17:00.440
So the new executable Simple action server and its source code is still in the Arduino, but by examples

17:00.470 --> 17:06.260
this time is in the simple action server.

17:06.260 --> 17:10.070
And still from this script we want to execute the main function.

17:10.520 --> 17:16.880
Now we can save also this file and we just need to compile our workspace again so that the new node

17:16.880 --> 17:18.620
becomes an executable.

17:18.980 --> 17:26.300
So let's open a new terminal, go to the workspace and let's build it with the command.

17:26.300 --> 17:27.230
Click on Build.

17:27.620 --> 17:33.560
Once the build is succeeded, we can open a new window of the terminal and finally we can start our

17:33.560 --> 17:34.610
action server.

17:34.910 --> 17:42.050
So let's source the file setup dot bash so that the Arduino Pi example package is recognized.

17:42.230 --> 17:48.200
And now from this package, so from the Arduino Pi examples.

17:48.200 --> 17:53.610
So if we press tab twice now we can see that there is the simple action server available.

17:53.790 --> 18:00.360
So let's start this one, the simple action server, let's press enter and we get the confirmation that

18:00.360 --> 18:06.390
the action server is running from the terminal so we can see that the simple action server is saying

18:06.420 --> 18:14.100
starting the server and also we can actually double check it by opening a new terminal.

18:14.250 --> 18:20.040
And here we can use the command Ros2 action list.

18:20.040 --> 18:22.050
So let's press enter.

18:22.050 --> 18:28.080
And since we have started only one node, so the one that creates and starts the Fibonacci action server,

18:28.110 --> 18:32.580
this is also the only action server that is currently available in Ros two.

18:32.610 --> 18:37.080
So this one if we search the workspace also in this new terminal.

18:37.080 --> 18:39.330
So let's source the file setup dot bash.

18:39.480 --> 18:48.960
We can have additional information about this action server using the command Ros2 action info followed

18:48.960 --> 18:57.080
by the name of the action, which is the Fibonacci, followed by the minus D flag in order to show also

18:57.080 --> 18:58.460
the message interface.

18:58.460 --> 19:01.880
So the type of the interface that this action is using.

19:02.000 --> 19:08.540
So let's press enter and currently we can see that for this action server there is only one node that

19:08.540 --> 19:10.100
is interacting with it.

19:10.250 --> 19:16.610
So here that is the simple action server node that actually creates this action server.

19:16.610 --> 19:24.920
And also we can see that this action server is using the interface Fibonacci as declared in the Arduino

19:24.920 --> 19:26.120
board messages.

19:26.720 --> 19:32.870
At this moment we can see that there are no clients, so actually there is nobody that is interested

19:32.870 --> 19:38.510
in the functionalities of this server and we can send a new goal to this server.

19:38.510 --> 19:44.510
So to the Fibonacci server in order to see how it works, to send a goal to an action server, we can

19:44.510 --> 19:55.050
use the command Ros2 action and then send goal followed by the name of the action, which is the Fibonacci,

19:55.080 --> 19:56.190
the action server.

19:56.220 --> 20:03.810
Then if we press tab twice we can see that the Ros two autocompletion is able to detect that we need

20:03.810 --> 20:07.140
an interface of type Arduino board messages Fibonacci.

20:08.040 --> 20:12.090
So let's use this interface to send a new goal to the action server.

20:12.120 --> 20:13.740
Then let's use double quote.

20:14.260 --> 20:16.000
And then let's set the order.

20:16.000 --> 20:17.320
So let's press tab.

20:17.590 --> 20:24.010
And so this has inserted an empty prototype of the goal message that we are going to send to the Fibonacci

20:24.010 --> 20:24.970
action server.

20:25.180 --> 20:27.750
So, for example, let's set the order to ten.

20:27.760 --> 20:33.010
So we are asking the action server to calculate the Fibonacci sequence up to the order ten.

20:33.710 --> 20:41.570
Let's also use the flag minus F in order to print the feedback messages that the server will send in

20:41.570 --> 20:42.500
this same terminal.

20:42.500 --> 20:44.870
So minus F stands for feedback.

20:45.170 --> 20:51.320
So let's press enter and as soon as we send this goal, we can see how the action server informs us

20:51.320 --> 20:57.350
that it has received a new goal and also that it starts processing the Fibonacci sequence element by

20:57.350 --> 21:00.560
element up to the order ten for each number.

21:00.560 --> 21:05.030
Also, we can see that for each new element that the server is adding to the sequence.

21:05.060 --> 21:10.280
It also sending a feedback message that informs us about the progress of the goal.

21:10.610 --> 21:16.490
And finally, once the desired order is reached, the action server also returns a result message.

21:16.490 --> 21:19.490
So this one here with default.

21:19.520 --> 21:22.580
So the complete sequence up to the desired order.

21:22.580 --> 21:24.260
So up to the order ten.
