Changing a drone setting - Understand the “expectation” mechanism#
In this example, we will change the “maximum tilt” drone setting. This setting indirectly controls the maximum drone acceleration and speed. The more the drone can tilt, the more the drone gain speed.
The maximum tilt setting itself must be within a minimum and maximum range. A drone with a max tilt value of 0° is not particularly useful while a maximum tilt over 180° might only be useful for a racer drone. For ANAFI the maximum tilt setting must be within 1° and 40°.
You might be wondering:
What is happening when you send an invalid setting value (ex: 180°)?
How does the drone respond to that?
How do we catch this kind of error with Olympe?
Let’s see how this is done in the following example. Some important explanations will follow.
First, reset the simulation (
sphinx-cli action -m world fwman world_reset_all in a terminal).
Create the following Python
maxtilt.py script somewhere in your home directory:
1import olympe 2import os 3from olympe.messages.ardrone3.PilotingSettings import MaxTilt 4 5DRONE_IP = os.environ.get("DRONE_IP", "10.202.0.1") 6 7 8def test_maxtilt(): 9 drone = olympe.Drone(DRONE_IP) 10 drone.connect() 11 maxTiltAction = drone(MaxTilt(10)).wait() 12 if maxTiltAction.success(): 13 print("MaxTilt(10) success") 14 elif maxTiltAction.timedout(): 15 print("MaxTilt(10) timedout") 16 else: 17 # If ".wait()" is called on the ``maxTiltAction`` this shouldn't happen 18 print("MaxTilt(10) is still in progress") 19 maxTiltAction = drone(MaxTilt(0)).wait() 20 if maxTiltAction.success(): 21 print("MaxTilt(0) success") 22 elif maxTiltAction.timedout(): 23 print("MaxTilt(0) timedout") 24 else: 25 # If ".wait()" is called on the ``maxTiltAction`` this shouldn't happen 26 print("MaxTilt(0) is still in progress") 27 drone.disconnect() 28 29 30if __name__ == "__main__": 31 test_maxtilt()
This time, the script starts by importing the
MaxTilt() command from the
Then, it connects to the drone and sends two MaxTilt commands. The first one with a 10° tilt value,
the second with a 0° tilt value.
Note that this time, we are assigning into the
maxTiltAction variable the object returned by the
.wait() method. For now, all you have to know is that you can call
.success() -> bool on an
“action” object (the more general term is “expectation” object) if you want to know if your command
succeeded or not. The
success() function just returns
True in case of success and
You can also call
.timedout() -> bool on an “action” object to know if your command message
timed out. This
.timedout() method is not particularly useful in this example because we always
.wait() on the action object, so the action is either successful or has timed out.
To execute this script, from the same shell/terminal you have source’d the
shell script in:
$ python ./maxtilt.py
If all goes well, you should see the following output in your terminal:
MaxTilt(10) success MaxTilt(0) timedout
Obviously, the 10° maximum tilt value is correct, so the first command succeeded while the second command failed to set an incorrect 0° maximum tilt value.
It is important to understand how Olympe knows if a particular command succeeded or not. When Olympe sends a command message, it usually implicitly expects an event message in return.
Up until now, we have only explicitly used command messages. Command messages and event messages are somewhat similar. They are both associated with an internal unique ID and eventually with some arguments (ex: the maximum tilt value) and they both travel from one source to a destination.
A command message travel from the controller (Olympe) to the drone while an event message travel the other way around.
Here, when Olympe sends the
MaxTilt(10) command message it implicitly expects a
MaxTiltChanged(10) event message in return. If the event is received in time, everything is
maxTiltAction.success() is True and maxTiltAction.timedout() is False. Otherwise, the
maxTiltAction times out (
maxTiltAction.success() is False and maxTiltAction.timedout() is
The following sequence diagram illustrates what is happening here.
For the second maximum tilt command, when Olympe sends the
MaxTilt(0) command message it
MaxTiltChanged(1) event message because 0° is an invalid setting value, so the
drone just informs the controller that it has set the minimum setting value instead (1°). Olympe
does not assume that this response means “No, I won’t do what you are asking”. Instead, it still
waits for a
MaxTiltChanged(0) event that will never come and the command message times out:
maxTiltAction.success() is False and maxTiltAction.timedout() is True). This behavior is
identical for every command message: when Olympe sends a command message to a drone, it either
result in a success or a timeout.
The arsdk protocol defined in arsdk-xml does not provide a way to report errors uniformly. This is why Olympe cannot detect errors like this one and just time out instead. Olympe associates to each command a default timeout that can be overridden with the _timeout message parameter. For example:
maxTiltAction = drone(MaxTilt(10, _timeout=1)).wait()