Let's conclude the voice interaction model of our Alexa skill with the robot by adding new, more handlers
for each of the skills intent.
So once again, we refer to the documentation that Amazon provides to the Python skill developers.
So go to this link here that I also live in the description of this lesson.
So here in the developing your first skill this time let's copy the second intent.
So this one we have already implemented.
Let's copy the second one.
So the hello world intent handler.
So let's copy this one and let's paste it.
So in our script.
So in the Arduino bot remote then in the Arduino bot remote folder and in the Alexa interface.
So here below the launch request handler, let's paste the code that we have just copied.
So let's add one more space here to improve the readability of the code.
And now let's first change the name of this class into.
So this one let's call peak intent handler.
And let's also change the name of the intent for which the functionalities in this class will be executed.
And so we want this class to be executed when the.
Peak intent is triggered.
So when the Alexa assistant sends us a message in which it's triggering the peak intent.
In this case let's also change the response.
So here that the voice assistant will pronounce when we activate this intent.
And let's set this one to okay I'm moving.
So when we activate this intent so the peak intent by saying for example the phrase pick up that pen
or pick that pen, then Alexa will respond with this phrase here.
Let's also change the name of the simple card.
So here to be.
peak.
And now, before moving on to defining the next handler.
Remember to register this handler in the skill builder using the add request handler function.
So here basically let's copy this line and let's paste it.
And now we want to register also this handler here.
So the peak intent handler.
Next let's create another handler so we can copy all of these.
And we can paste it here below.
And let's call this one.
So here let's change the name of this class.
And let's call it sleep intent handler.
And this class will be activated when a message is received from the Amazon Alexa assistant.
That is of type sleep intent.
So when this intent is triggered by the Alexa assistant, we want it to say the phrase Okay.
See you later.
And let's also change the name of this simple card to zlib.
And as always, we need to register this handler.
So let's copy this one.
And let's register now the sleep intent handler.
And now let's define also the handler for the wake intent.
Again we can copy this class here.
And we can paste it here.
And let's change the name of the class into.
Wake intent handler.
And this class is going to be triggered when the wake intent is triggered by the Amazon Alexa.
And we want the assistant to respond with the phrase I am ready.
Okay.
And let's also change here the name of the simple card to be the wake.
And as well let's register also this new handler.
So the wake intent handler.
So let's paste it here.
Now with this we have added the handlers for all the functionalities.
So for all the intent that we created in the previous lessons for the Alexa skill.
So here we have managed all the handlers that Alexa can send to our script.
So to our web service.
So the communication will start always with the launch request.
And then depending on what we say so on what we ask to the assistant it will trigger the pick intent
or the sleep intent or the wake intent.
Now let's also add one last handler, this time for cases when the command enters.
The intent request that Alexa sent to us doesn't fall into any of the previous category.
This typically happens when we activate the skill and send a command to the robot, but Alexa doesn't
understand the command correctly.
So let's go back here to the documentation, and let's add a handler to manage exceptions.
And we can copy this still from this documentation, if we go the exception handler section here, we
can copy this one.
The all exception handler that as the name says will catch any exception and so will manage any command
that was not properly understood by Alexa.
So let's copy this one and let's paste it here.
Let's move this one.
So the import at the beginning of the file.
So let's move it here.
And now as I said this handler will be triggered whenever none of the previous one is activated.
And so when it is activated we want the voice assistant to say so let's make it say the phrase Sorry.
I didn't.
Understand?
Could you repeat?
So whenever Alexa is not able to understand a command.
So whenever the command that we have sent doesn't fall into any of these categories, it will respond
with this phrase here.
So sorry, I didn't understand.
Could you repeat.
And now also we need to register this one so we can register it here.
So let's use the Skill builder.
And on this one let's use the function this time.
Add exception handler.
So we can see that there is a difference.
So in order to register a normal handler so an event handler we use the add request handler function
instead in order to manage the exceptions.
So in order to register an exception handler or use the function add exception handler.
And so let's register this class.
So the all exception handler class.
With this we have completed our voice interaction model with the assistant.
And we have configured not only the responses that the assistant will give upon receiving a known command,
but also the response for an unclear or unrecognized command.
If you notice so far, this is a regular Python script, and in fact we started in the previous lesson
with the command Python.
And this actually doesn't use any element of the CLP library and thus is not integrating.
So it is not communicating with Ros2.
Now it's time to integrate this script with Ros2 and make it send a goal to the action server, which
we called Task Server, upon receiving a specific voice command to do so.
Let's start by importing the CLP library and as always from the CLP library from the node modules.
Let's import the node class to create our Ros2 node.
And now, since we want to send a goal to the task server, which we implemented as a Ros2 action server,
we need also to create an action client.
Of course for this again, let's also import from the CLP library and this time from the action module.
Let's import the action client.
And now let's use it to create a new class.
So a new instance of this action client.
So here let's create a new object a new variable called action client as an instance of the action client
class.
And to this one we need to pass the instance of the node.
So the ros2 node that hosts the action client.
And so let's create simply a new node.
So a new Ross two node.
And let's call this one Alexa interface.
Next, for the creation of the action client, we also need to specify the message type.
So the interface that the action client should use for the communication with the server.
This is defined within the Arduino bot messages package and within the action folder.
We defined this one in the Arduino bot task interface.
And so now let's define that this action client is going to use the Arduino bot task interface.
And also that this has to communicate.
So the name of the action server is the task server.
So we want this one to be a client of the server called task Server that uses the interface Arduino
bot task.
With this we have created our action client.
Now we need to keep our ros2 node running so that we can keep this node active.
And so we can send goal to the action server upon receiving a new command from Alexa.
So within of these handlers since in the main function of this script.
So this one here we are already keeping the main application thread busy with the flask web service.
For the interface with Alexa, we are going to create the interface with Ros2 in a separate thread in
order to allow both the functionalities.
So the Alexa interface, this one through the web service, and also the Ros2 node interface through
the action client to run in parallel.
So we will enable these two applications to run in parallel by creating a separate thread.
To do this in Python, let's import another library.
So let's import the threading library.
And from this one let's create a new thread.
So from the trading library, let's create a new thread.
And in this thread we simply want to keep our Ros2 node running.
And so we can achieve this by using a lambda function.
So target.
Let's use a lambda function that is an anonymous function.
And this simply says rcl pi dot init.
So we are initializing the ros2 node.
And then let's also start this thread.
So which means that we start keeping the Ros2 node running using the start function of the thread.
Now everything is set also for the communication with Ros2.
So between this script and Ros2.
And so with the task server that is available in Ros2.
And now we can start using this variable here.
So the action client to send goal to the task server.
And so to move the robot every time the web service saw the flask web service receives a new request
from the Alexa assistant.
Let's start with the first handler.
So this one the launch request handler.
When this one is activated, we are going to send a new goal.
And so here before the return statement let's create a new variable called goal that belongs to the
Arduino bot task interface.
And this is a goal message.
And in this case, since we are in the intent that handles the activation of the robot with Alexa,
we simply want the robot to execute the task number zero, which if you remember, is the one that moves
the arm to the home position.
So to the default position and opens the gripper.
So on the goal object, let's set the task number to be the task zero.
So we want to execute the task at zero.
And then let's simply send this goal to the action server by using the action client descent goal async.
And so let's send the goal message.
We can do the same for all the other handlers.
So let's copy this goal here.
And now for the pick handler.
So still here before returning from this function here let's just change the task number.
And so in this case as we are requesting the execution of the pick intent, we want the robot to execute
the task number one that if you remember, corresponds to move the robot to a hypothetical pick position
and also closes the gripper.
Then let's paste it again also here within the slip handler.
And in this case we want the robot to perform the task number two that, if you remember, corresponds
to a hypothetical rest position of the robot.
And finally for the wake intent handler.
So still here before Or returning.
Let's execute instead the task number zero.
So let's still execute the task number zero.
Since we are in the wake intent handler and the task number zero brings the robot to the on position
with this, for each command that we receive from the Amazon Alexa assistant, we have encoded a behavior
of the robot.
And so we are sending a goal to the robot that moves it in a particular position.
Let's conclude this lesson by adding this node.
So the Alexa interface to the launch file that starts all the functionalities that we developed in this
package here.
So in the Arduino bot remote package and this is the launch file that we have created and that we have
called remote interface launch dot Pi.
So here after the task server let's also start the Alexa interface node.
So also this one is an instance of the node class.
And now from the Package that is the Arduino bot remote package.
We want to start the executable.
That is called.
So this one here the Alexa interface.
Dot pi.
Perfect.
And we can also set a parameter.
Actually this is a list.
And we only just need to set the parameter.
Use sim time.
And we can use this variable here.
So the is sim variable that will contain.
So the value of this argument here.
And so that will be either true if we are using.
So if we are launching this launch file for the simulated robot or it will be false if we are using
it for the real robot.
Perfect.
So with this one we have created a new node.
And now in order to start it when this launch file is started, we need to add it here.
So in the launch description list.
Perfect.
Then once we have added this node we also need to install it.
So we need to install the Alexa interface dot pi here within the cmake list dot.
TXT file.
And actually in the install instructions here where we have already installed the task server dot pi.
We can copy this command and we can paste it in order to install also the Alexa interface dot pi.
So this node here perfect.
So we can save also this file.
And that's it.
In the next lesson we're going to integrate all the functionalities that we have started here in the
Arduino bot remote interface in the software architecture.
So in the entire bring up package of the robot so that we will be able to start all the functionalities
of the robot and to control our robot sending voice commands with Alexa using a single launch file.