Commands
In this guide we will use Airbotics to send commands to our robot.
Goals
- Publish to a topic, Call a service, Send a goal to an action.
- Verifying command states
- Understand when and why commands fail.
Prerequisites
- An account with Airbotics.
- A valid API key with the
commands:read
andcommands:write
permissions. - Device running Ubuntu 22.04 with ROS 2 installed.
- Physical or SSH access to your device.
Prepare environment
Ensure you have the following two environment variables set before you get started:
export AIR_API_KEY=<your_api_key>
export AIR_ROBOT_ID=<your_robot_id>
Run the agent and the application nodes
ros2 run turtlesim turtlesim_node
airbotics
Publish to a topic
Now we will publish to a ROS topic through the REST API. We will send a Twist
message on the /turtle1/cmd_vel
topic, which will cause the robot to turn.
curl --request POST https://api.airbotics.io/robots/$AIR_ROBOT_ID/commands \
--header "content-type: application/json" \
--header "air-api-key: $AIR_API_KEY" \
--data '{
"interface": "topic",
"name": "/turtle1/cmd_vel",
"type": "geometry_msgs/msg/Twist",
"payload": {
"linear": {
"x": 2.0,
"y": 0.0,
"z": 0.0
},
"angular": {
"x": 0.0,
"y": 0.0,
"z": 2.0
}
}
}'
You should now see your turtle start to turn in a circle.
Call a ROS service
You can also use Commands to call ROS services on your robots. Let’s send another API request to call a service, we will call the /turtle1/teleport_absolute
service to move the turtle.
curl --request POST https://api.airbotics.io/robots/$AIR_ROBOT_ID/commands \
--header "content-type: application/json" \
--header "air-api-key: $AIR_API_KEY" \
--data '{
"interface": "service",
"name": "/turtle1/teleport_absolute",
"type": "turtlesim/srv/TeleportAbsolute",
"payload": {
"x": 10.0,
"y": 5.0,
"theta": 1.57
}
}'
You should now see the turtle move.
Send a goal to an action server
Finally, we will send a goal to the /turtle1/rotate_absolute
action to turn the turtle around with the below command:
curl --request POST https://api.airbotics.io/robots/$AIR_ROBOT_ID/commands \
--header "content-type: application/json" \
--header "air-api-key: $AIR_API_KEY" \
--data '{
"interface": "action_send_goal",
"name": "/turtle1/rotate_absolute",
"type": "turtlesim/action/RotateAbsolute",
"payload": {
"theta": 0.0
}
}'
Verifying command states
In the previous examples, if the agent was running and connected to the network, the commands should have executed almost immediately.
Each command you try to send has an associated state and you can make another API call to check command state:
curl --request GET https://api.airbotics.io/robots/$AIR_ROBOT_ID/commands \
--header 'content-type: application/json' \
--header "air-api-key: $AIR_API_KEY"
The response shows a list of previous commands sent to the robot, and each command has a state
and error_code
field.
If the command was executed successfully, all the command states should be executed
and the error_code null
.
Why commands fail
However under certain circumstances, commands will either fail to reach the robot or will reach the robot but fail to execute as expected.
Thankfully the state
and error_code
fields can let you know if and why a command was not executed.
To see a complete list of error codes and what them, refer to the error codes table in the commands docs.
To show you a failed command in action let’s send a command with an invalid payload;
curl --request POST https://api.airbotics.io/robots/$AIR_ROBOT_ID/commands \
--header "content-type: application/json" \
--header "air-api-key: $AIR_API_KEY" \
--data '{
"interface": "topic",
"name": "/chatter",
"type": "std_msgs/msg/String",
"payload": {
"x": 10.0,
}
}'
In the above command we’re asking to send a command to publish a message to the chatter
topic. The ROS message type is
std_msgs/msg/String
, but the payload we’re sending contains {"x": 10}
which does not match the datatype that std_msgs/msg/String
expects. If you query the command state again you’ll see the following:
{
"uuid": "5807bb36-aa37-47cd-8701-9722b672e60c",
"state": "error",
"error_code": "invalid_payload",
"interface": "topic",
"name": "/chatter",
"type": "std_msgs/msg/String",
"payload": {
"x": 10.0
},
"created_at": "2023-07-28T08:14:30.133Z"
}
Another failure reason is that a robot is not online when you attempt to send a command. Airbotics adopts a fire and forget approach to commands, there is no queueing or resending logic. This is to avoid unexpected behaviour of executing commands at a time other than when they were sent.
Wrapping up
In this deep dive you have sent commands for 3 ROS interfaces, topics, services and actions. You’ve also learnt about when and why commands fail and how to query and interpret command states and error codes.
Cleaning up
If you want to delete the commands you send in the guide, you can make an API call(s) with the uuid of each command you’d like to delete.
Dont forget to replace <command-uuid>
with the uuid of each command you would like to delete:
curl --request DELETE "localhost:8000/commands/<command-uuid>" \
--header "content-type: application/json" \
--header "air-api-key: $AIR_API_KEY"