WEBVTT

00:00.200 --> 00:06.530
Let's conclude the voice interaction model of our Alexa skill with the robot by adding new, more handlers

00:06.530 --> 00:08.600
for each of the skills intent.

00:08.750 --> 00:14.870
So once again, we refer to the documentation that Amazon provides to the Python skill developers.

00:14.870 --> 00:19.430
So go to this link here that I also live in the description of this lesson.

00:19.910 --> 00:26.660
So here in the developing your first skill this time let's copy the second intent.

00:26.660 --> 00:28.580
So this one we have already implemented.

00:28.610 --> 00:30.080
Let's copy the second one.

00:30.080 --> 00:32.780
So the hello world intent handler.

00:32.840 --> 00:36.020
So let's copy this one and let's paste it.

00:36.020 --> 00:37.550
So in our script.

00:37.550 --> 00:44.060
So in the Arduino bot remote then in the Arduino bot remote folder and in the Alexa interface.

00:44.060 --> 00:50.570
So here below the launch request handler, let's paste the code that we have just copied.

00:50.720 --> 00:55.490
So let's add one more space here to improve the readability of the code.

00:55.490 --> 00:59.330
And now let's first change the name of this class into.

01:00.370 --> 01:06.760
So this one let's call peak intent handler.

01:06.880 --> 01:12.640
And let's also change the name of the intent for which the functionalities in this class will be executed.

01:12.640 --> 01:15.880
And so we want this class to be executed when the.

01:17.980 --> 01:20.290
Peak intent is triggered.

01:20.290 --> 01:26.830
So when the Alexa assistant sends us a message in which it's triggering the peak intent.

01:27.430 --> 01:30.130
In this case let's also change the response.

01:30.130 --> 01:34.870
So here that the voice assistant will pronounce when we activate this intent.

01:35.080 --> 01:41.680
And let's set this one to okay I'm moving.

01:42.040 --> 01:49.540
So when we activate this intent so the peak intent by saying for example the phrase pick up that pen

01:49.540 --> 01:54.700
or pick that pen, then Alexa will respond with this phrase here.

01:55.120 --> 01:57.550
Let's also change the name of the simple card.

01:57.550 --> 01:59.260
So here to be.

02:00.540 --> 02:01.140
peak.

02:01.860 --> 02:04.980
And now, before moving on to defining the next handler.

02:05.010 --> 02:12.000
Remember to register this handler in the skill builder using the add request handler function.

02:12.540 --> 02:18.270
So here basically let's copy this line and let's paste it.

02:18.270 --> 02:23.100
And now we want to register also this handler here.

02:23.100 --> 02:25.470
So the peak intent handler.

02:25.830 --> 02:30.960
Next let's create another handler so we can copy all of these.

02:31.620 --> 02:34.230
And we can paste it here below.

02:34.380 --> 02:36.120
And let's call this one.

02:36.510 --> 02:38.850
So here let's change the name of this class.

02:38.850 --> 02:42.630
And let's call it sleep intent handler.

02:42.630 --> 02:48.570
And this class will be activated when a message is received from the Amazon Alexa assistant.

02:48.600 --> 02:51.750
That is of type sleep intent.

02:51.750 --> 02:59.750
So when this intent is triggered by the Alexa assistant, we want it to say the phrase Okay.

03:01.550 --> 03:02.840
See you later.

03:03.920 --> 03:07.970
And let's also change the name of this simple card to zlib.

03:08.060 --> 03:11.150
And as always, we need to register this handler.

03:11.150 --> 03:12.860
So let's copy this one.

03:13.370 --> 03:17.690
And let's register now the sleep intent handler.

03:19.430 --> 03:23.090
And now let's define also the handler for the wake intent.

03:23.120 --> 03:26.270
Again we can copy this class here.

03:27.230 --> 03:29.720
And we can paste it here.

03:29.720 --> 03:32.600
And let's change the name of the class into.

03:34.970 --> 03:37.040
Wake intent handler.

03:37.040 --> 03:43.700
And this class is going to be triggered when the wake intent is triggered by the Amazon Alexa.

03:44.360 --> 03:53.420
And we want the assistant to respond with the phrase I am ready.

03:54.590 --> 03:55.280
Okay.

03:55.280 --> 03:59.920
And let's also change here the name of the simple card to be the wake.

04:00.070 --> 04:05.200
And as well let's register also this new handler.

04:05.200 --> 04:07.450
So the wake intent handler.

04:07.960 --> 04:09.670
So let's paste it here.

04:10.060 --> 04:13.840
Now with this we have added the handlers for all the functionalities.

04:13.840 --> 04:19.210
So for all the intent that we created in the previous lessons for the Alexa skill.

04:19.210 --> 04:24.760
So here we have managed all the handlers that Alexa can send to our script.

04:24.760 --> 04:26.320
So to our web service.

04:26.320 --> 04:30.310
So the communication will start always with the launch request.

04:30.310 --> 04:36.550
And then depending on what we say so on what we ask to the assistant it will trigger the pick intent

04:36.580 --> 04:39.460
or the sleep intent or the wake intent.

04:40.480 --> 04:45.850
Now let's also add one last handler, this time for cases when the command enters.

04:45.850 --> 04:52.120
The intent request that Alexa sent to us doesn't fall into any of the previous category.

04:52.480 --> 04:57.870
This typically happens when we activate the skill and send a command to the robot, but Alexa doesn't

04:57.870 --> 04:59.850
understand the command correctly.

05:00.450 --> 05:06.450
So let's go back here to the documentation, and let's add a handler to manage exceptions.

05:06.450 --> 05:16.440
And we can copy this still from this documentation, if we go the exception handler section here, we

05:16.440 --> 05:17.550
can copy this one.

05:17.550 --> 05:24.810
The all exception handler that as the name says will catch any exception and so will manage any command

05:24.840 --> 05:27.600
that was not properly understood by Alexa.

05:28.260 --> 05:31.710
So let's copy this one and let's paste it here.

05:32.670 --> 05:34.530
Let's move this one.

05:34.530 --> 05:38.070
So the import at the beginning of the file.

05:38.100 --> 05:40.110
So let's move it here.

05:41.160 --> 05:47.280
And now as I said this handler will be triggered whenever none of the previous one is activated.

05:47.280 --> 05:56.270
And so when it is activated we want the voice assistant to say so let's make it say the phrase Sorry.

05:59.060 --> 06:02.060
I didn't.

06:04.550 --> 06:05.900
Understand?

06:07.400 --> 06:10.850
Could you repeat?

06:11.270 --> 06:14.750
So whenever Alexa is not able to understand a command.

06:14.780 --> 06:21.380
So whenever the command that we have sent doesn't fall into any of these categories, it will respond

06:21.740 --> 06:22.820
with this phrase here.

06:22.820 --> 06:24.890
So sorry, I didn't understand.

06:24.920 --> 06:26.150
Could you repeat.

06:26.450 --> 06:32.060
And now also we need to register this one so we can register it here.

06:33.050 --> 06:36.830
So let's use the Skill builder.

06:36.830 --> 06:39.530
And on this one let's use the function this time.

06:39.560 --> 06:42.590
Add exception handler.

06:42.590 --> 06:44.300
So we can see that there is a difference.

06:44.300 --> 06:51.980
So in order to register a normal handler so an event handler we use the add request handler function

06:51.980 --> 06:54.290
instead in order to manage the exceptions.

06:54.290 --> 07:00.310
So in order to register an exception handler or use the function add exception handler.

07:00.310 --> 07:02.410
And so let's register this class.

07:03.490 --> 07:06.490
So the all exception handler class.

07:06.490 --> 07:10.870
With this we have completed our voice interaction model with the assistant.

07:10.870 --> 07:16.900
And we have configured not only the responses that the assistant will give upon receiving a known command,

07:16.930 --> 07:21.910
but also the response for an unclear or unrecognized command.

07:22.630 --> 07:28.570
If you notice so far, this is a regular Python script, and in fact we started in the previous lesson

07:28.570 --> 07:30.190
with the command Python.

07:30.190 --> 07:36.940
And this actually doesn't use any element of the CLP library and thus is not integrating.

07:36.940 --> 07:39.370
So it is not communicating with Ros2.

07:39.790 --> 07:45.760
Now it's time to integrate this script with Ros2 and make it send a goal to the action server, which

07:45.760 --> 07:51.640
we called Task Server, upon receiving a specific voice command to do so.

07:51.640 --> 08:03.240
Let's start by importing the CLP library and as always from the CLP library from the node modules.

08:03.270 --> 08:07.470
Let's import the node class to create our Ros2 node.

08:07.680 --> 08:13.530
And now, since we want to send a goal to the task server, which we implemented as a Ros2 action server,

08:13.530 --> 08:15.420
we need also to create an action client.

08:15.420 --> 08:24.900
Of course for this again, let's also import from the CLP library and this time from the action module.

08:24.990 --> 08:28.380
Let's import the action client.

08:28.650 --> 08:31.320
And now let's use it to create a new class.

08:31.320 --> 08:33.840
So a new instance of this action client.

08:33.840 --> 08:43.410
So here let's create a new object a new variable called action client as an instance of the action client

08:43.410 --> 08:44.130
class.

08:44.190 --> 08:47.550
And to this one we need to pass the instance of the node.

08:47.550 --> 08:51.030
So the ros2 node that hosts the action client.

08:51.030 --> 08:53.840
And so let's create simply a new node.

08:53.840 --> 08:55.460
So a new Ross two node.

08:55.460 --> 09:00.470
And let's call this one Alexa interface.

09:00.470 --> 09:05.720
Next, for the creation of the action client, we also need to specify the message type.

09:05.720 --> 09:10.700
So the interface that the action client should use for the communication with the server.

09:11.060 --> 09:19.070
This is defined within the Arduino bot messages package and within the action folder.

09:19.100 --> 09:25.940
We defined this one in the Arduino bot task interface.

09:25.940 --> 09:34.490
And so now let's define that this action client is going to use the Arduino bot task interface.

09:34.490 --> 09:37.100
And also that this has to communicate.

09:37.100 --> 09:41.750
So the name of the action server is the task server.

09:41.750 --> 09:49.220
So we want this one to be a client of the server called task Server that uses the interface Arduino

09:49.220 --> 09:50.120
bot task.

09:50.150 --> 09:53.470
With this we have created our action client.

09:53.770 --> 09:58.630
Now we need to keep our ros2 node running so that we can keep this node active.

09:58.630 --> 10:03.790
And so we can send goal to the action server upon receiving a new command from Alexa.

10:03.820 --> 10:08.590
So within of these handlers since in the main function of this script.

10:08.590 --> 10:16.540
So this one here we are already keeping the main application thread busy with the flask web service.

10:16.540 --> 10:22.480
For the interface with Alexa, we are going to create the interface with Ros2 in a separate thread in

10:22.480 --> 10:24.610
order to allow both the functionalities.

10:24.610 --> 10:30.250
So the Alexa interface, this one through the web service, and also the Ros2 node interface through

10:30.250 --> 10:32.710
the action client to run in parallel.

10:32.710 --> 10:38.380
So we will enable these two applications to run in parallel by creating a separate thread.

10:38.590 --> 10:42.310
To do this in Python, let's import another library.

10:42.820 --> 10:48.250
So let's import the threading library.

10:48.250 --> 10:50.740
And from this one let's create a new thread.

10:50.740 --> 10:57.300
So from the trading library, let's create a new thread.

10:57.300 --> 11:01.440
And in this thread we simply want to keep our Ros2 node running.

11:01.440 --> 11:04.980
And so we can achieve this by using a lambda function.

11:04.980 --> 11:06.810
So target.

11:06.810 --> 11:11.970
Let's use a lambda function that is an anonymous function.

11:11.970 --> 11:17.760
And this simply says rcl pi dot init.

11:17.760 --> 11:21.240
So we are initializing the ros2 node.

11:21.240 --> 11:25.200
And then let's also start this thread.

11:25.200 --> 11:31.590
So which means that we start keeping the Ros2 node running using the start function of the thread.

11:32.430 --> 11:36.270
Now everything is set also for the communication with Ros2.

11:36.270 --> 11:38.940
So between this script and Ros2.

11:38.940 --> 11:42.120
And so with the task server that is available in Ros2.

11:42.270 --> 11:45.330
And now we can start using this variable here.

11:45.330 --> 11:48.450
So the action client to send goal to the task server.

11:48.450 --> 11:55.340
And so to move the robot every time the web service saw the flask web service receives a new request

11:55.340 --> 11:57.320
from the Alexa assistant.

11:58.100 --> 12:00.080
Let's start with the first handler.

12:00.080 --> 12:03.050
So this one the launch request handler.

12:03.470 --> 12:07.010
When this one is activated, we are going to send a new goal.

12:07.010 --> 12:15.020
And so here before the return statement let's create a new variable called goal that belongs to the

12:15.020 --> 12:17.000
Arduino bot task interface.

12:17.540 --> 12:19.460
And this is a goal message.

12:19.460 --> 12:25.130
And in this case, since we are in the intent that handles the activation of the robot with Alexa,

12:25.130 --> 12:31.190
we simply want the robot to execute the task number zero, which if you remember, is the one that moves

12:31.190 --> 12:32.780
the arm to the home position.

12:32.780 --> 12:35.990
So to the default position and opens the gripper.

12:36.110 --> 12:43.340
So on the goal object, let's set the task number to be the task zero.

12:43.340 --> 12:45.320
So we want to execute the task at zero.

12:45.410 --> 12:54.370
And then let's simply send this goal to the action server by using the action client descent goal async.

12:54.370 --> 12:56.830
And so let's send the goal message.

12:56.890 --> 12:59.800
We can do the same for all the other handlers.

12:59.800 --> 13:03.730
So let's copy this goal here.

13:03.730 --> 13:06.070
And now for the pick handler.

13:06.070 --> 13:12.940
So still here before returning from this function here let's just change the task number.

13:12.940 --> 13:19.120
And so in this case as we are requesting the execution of the pick intent, we want the robot to execute

13:19.120 --> 13:25.570
the task number one that if you remember, corresponds to move the robot to a hypothetical pick position

13:25.570 --> 13:27.580
and also closes the gripper.

13:28.900 --> 13:34.240
Then let's paste it again also here within the slip handler.

13:34.240 --> 13:40.330
And in this case we want the robot to perform the task number two that, if you remember, corresponds

13:40.330 --> 13:43.240
to a hypothetical rest position of the robot.

13:43.240 --> 13:46.570
And finally for the wake intent handler.

13:46.570 --> 13:49.110
So still here before Or returning.

13:49.500 --> 13:52.740
Let's execute instead the task number zero.

13:52.740 --> 13:54.990
So let's still execute the task number zero.

13:55.020 --> 14:01.260
Since we are in the wake intent handler and the task number zero brings the robot to the on position

14:01.800 --> 14:08.070
with this, for each command that we receive from the Amazon Alexa assistant, we have encoded a behavior

14:08.070 --> 14:08.940
of the robot.

14:08.940 --> 14:14.040
And so we are sending a goal to the robot that moves it in a particular position.

14:14.820 --> 14:17.580
Let's conclude this lesson by adding this node.

14:17.580 --> 14:23.970
So the Alexa interface to the launch file that starts all the functionalities that we developed in this

14:23.970 --> 14:24.720
package here.

14:24.720 --> 14:30.390
So in the Arduino bot remote package and this is the launch file that we have created and that we have

14:30.390 --> 14:33.420
called remote interface launch dot Pi.

14:33.450 --> 14:42.990
So here after the task server let's also start the Alexa interface node.

14:43.020 --> 14:45.900
So also this one is an instance of the node class.

14:45.930 --> 14:53.330
And now from the Package that is the Arduino bot remote package.

14:53.510 --> 14:55.790
We want to start the executable.

14:58.490 --> 14:59.660
That is called.

14:59.660 --> 15:03.170
So this one here the Alexa interface.

15:06.980 --> 15:07.550
Dot pi.

15:07.580 --> 15:08.270
Perfect.

15:08.300 --> 15:11.150
And we can also set a parameter.

15:12.020 --> 15:13.460
Actually this is a list.

15:13.550 --> 15:16.550
And we only just need to set the parameter.

15:16.580 --> 15:19.220
Use sim time.

15:19.220 --> 15:21.290
And we can use this variable here.

15:21.290 --> 15:25.040
So the is sim variable that will contain.

15:25.070 --> 15:28.010
So the value of this argument here.

15:28.010 --> 15:30.740
And so that will be either true if we are using.

15:30.740 --> 15:36.500
So if we are launching this launch file for the simulated robot or it will be false if we are using

15:36.500 --> 15:38.270
it for the real robot.

15:38.300 --> 15:39.200
Perfect.

15:39.200 --> 15:42.200
So with this one we have created a new node.

15:42.200 --> 15:47.770
And now in order to start it when this launch file is started, we need to add it here.

15:47.770 --> 15:50.380
So in the launch description list.

15:50.530 --> 15:51.520
Perfect.

15:51.520 --> 15:54.850
Then once we have added this node we also need to install it.

15:54.850 --> 16:00.100
So we need to install the Alexa interface dot pi here within the cmake list dot.

16:00.130 --> 16:01.330
TXT file.

16:01.330 --> 16:07.930
And actually in the install instructions here where we have already installed the task server dot pi.

16:08.020 --> 16:16.990
We can copy this command and we can paste it in order to install also the Alexa interface dot pi.

16:17.020 --> 16:19.510
So this node here perfect.

16:19.510 --> 16:21.160
So we can save also this file.

16:21.160 --> 16:22.210
And that's it.

16:22.240 --> 16:28.540
In the next lesson we're going to integrate all the functionalities that we have started here in the

16:28.540 --> 16:32.380
Arduino bot remote interface in the software architecture.

16:32.380 --> 16:38.500
So in the entire bring up package of the robot so that we will be able to start all the functionalities

16:38.500 --> 16:46.270
of the robot and to control our robot sending voice commands with Alexa using a single launch file.
