Regarding MaxPitchRollRotationSpeed

I’m trying to figure the lower/upper limits of MaxPitchRollRotationSpeed, MaxRotationSpeed, MaxVerticalSpeed and others.

From this image (source unknown) I was under the impression, that at least for MaxPitchRollRotationSpeed values between 0 and 180 can be set:

but I’m not getting a clear picture. My aim is to vary the step distance of PCMD pitch/rolls, but…

  • things like assert drone(MaxPitchRollRotationSpeed(10)).wait().success() raise an assertion, while other values (180) seem to work
  • I cannot see a major difference in behaviour between 90 deg/s and 180 deg/s. Shouldn’t there be one? I mean I would expect that the 180 setup produces a wider step than the other, but there seems to be no difference to me

Here is a little test app. I’m using simulator empty-world as test field.

import olympe
import os
from olympe.messages.ardrone3.Piloting import TakeOff, moveBy, Landing, PCMD
from olympe.messages.ardrone3.SpeedSettings import MaxPitchRollRotationSpeed, MaxRotationSpeed, MaxVerticalSpeed
from olympe.messages import gimbal

DRONE_IP = os.environ.get("DRONE_IP", "")

class Getch:
    def __init__(self):
        import tty
        import sys

    def __call__(self):
        import sys
        import tty
        import termios
        fd = sys.stdin.fileno()
        old_settings = termios.tcgetattr(fd)
            ch =
            termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
        return ch

def test():
    getch = Getch()
    drone = olympe.Drone(DRONE_IP)
    assert drone(MaxPitchRollRotationSpeed(45)).wait().success()
    assert drone(TakeOff()).wait().success()
    assert drone(gimbal.set_target(
    while True:
        c = str(getch.__call__())
        if c == 'q':
            assert drone(Landing()).wait().success()
        if c == 'm':
            drone(PCMD(1, 0, 1, 0, 0, 0)).wait().success()

if __name__ == "__main__":

# import olympe
# import os
# import time
# from olympe.messages import camera

# DRONE_IP = os.environ.get("DRONE_IP", "")

# olympe.log.update_config({"loggers": {"olympe": {"level": "INFO"}}})

# class _Getch:
#     def __init__(self):
#         import tty
#         import sys

#     def __call__(self):
#         import sys
#         import tty
#         import termios
#         fd = sys.stdin.fileno()
#         old_settings = termios.tcgetattr(fd)
#         try:
#             tty.setraw(sys.stdin.fileno())
#             ch =
#         finally:
#             termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
#         return ch

# def yuv_frame_cb(yuv_frame):
#     #print(".", end="", flush=True)
#     pass

# def yuv_start_cb():
#     print("yuv start cb")
# def yuv_end_cb():
#     print("yuv end cb")
# def yuv_flush_cb(stream):
#     print("yuv flush cb")
#     return True
# def set_photo_mode(drone):
#     ''' Set photo mode '''
#     print("set photo mode")
#     assert(drone(camera.set_camera_mode(cam_id=0, value='photo')).wait().success())
#     assert(drone(camera.set_photo_mode(
#             cam_id=0,
#             mode='single',
#             format='full_frame',
#             file_format='jpeg',
#             burst='burst_4_over_1s',
#             bracketing='preset_1ev',
#             capture_interval=0
#     )).wait().success())
# def set_video_mode(drone):
#     ''' Set video mode '''
#     print("set video mode")
#     assert(drone(camera.set_camera_mode(cam_id=0, value='recording')).wait().success())
# def take_photo(drone):
#     assert(drone(camera.take_photo(cam_id=0)).wait().success())
#     print("photo taken")

# def test_streaming():
#     getch = _Getch()
#     drone = olympe.Drone(DRONE_IP)
#     if drone.connect():
#         drone.streaming.set_callbacks(
#                 raw_cb=yuv_frame_cb,
#                 start_cb=yuv_start_cb,
#                 end_cb=yuv_end_cb,
#                 flush_raw_cb=yuv_flush_cb,
#         )
#         if drone.streaming.start():
#             print("streaming started")
#             while True:
#                 c = str(getch.__call__())
#                 if c == 'q':
#                     drone.streaming.stop()
#                     break
#                 if c == 'p':
#                     set_photo_mode(drone)
#                 if c == 'v':
#                     set_video_mode(drone)
#                 if c == 't':
#                     take_photo(drone)


# if __name__ == "__main__":
#     test_streaming()

EDIT: If not obvious: This scripts configures MaxPitchRollRotationSpeed, starts the drone, puts the gimbal down and on “m” from the keyboard it pitches 1 unit forward. ‘q’ lands and terminates


The MaxPitchRollRotationSpeed command does not change the maximum angle of the Pitch/Roll axes of the drone, but the maximum rotation speed that the drone can take on those axes (i.e. a lower value will cause the drone to have a lower acceleration, not speed).
The command you need is olympe.messages.ardrone3.PilotingSettings.MaxTilt, which sets the maximum angle the drone can take, so with a MaxTilt of 20 and a PCMD of 50, the drone should converge to an angle of ~10 degrees.

You can get the min/max values directly from the drone with the olympe.messages.ardrone3.PilotingSettingsState.MaxTiltChanged message :

from olympe.messages.ardrone3.PilotingSettingsState import MaxTiltChanged
>>> OrderedDict([('current', 20.0), ('min', 0.25), ('max', 30.0)])

(Values taken from an Anafi Ai, they might change from model to model)


Ah, great. Thank you very much, that was the missing link. How could I oversee this.


I tested the settings with the simulator.

from olympe.messages.ardrone3.PilotingSettingsState import MaxTiltChanged 
from olympe.messages.ardrone3.SpeedSettingsState import MaxVerticalSpeedChanged, MaxPitchRollRotationSpeedChanged, MaxRotationSpeedChanged

OrderedDict([('current', 20.0), ('min', 1.0), ('max', 40.0)])
OrderedDict([('current', 1.0), ('min', 0.10000000149011612), ('max', 4.0)])
OrderedDict([('current', 150.0), ('min', 40.0), ('max', 300.0)])
OrderedDict([('current', 70.0), ('min', 3.0), ('max', 200.0)])

Could you please provide some information, when these “current” settings are taken? Is this some power on default or will the drone remember the last setting?

Sorry, I’m currently just testing with the simulator

I suppose the drone is keeping these settings, because my current readings from a real drone are similar to what I have configured lately:

OrderedDict([('current', 10.0), ('min', 1.0), ('max', 40.0)])
OrderedDict([('current', 3.9000000953674316), ('min', 0.10000000149011612), ('max', 4.0)])
OrderedDict([('current', 180.0), ('min', 40.0), ('max', 300.0)])
OrderedDict([('current', 200.0), ('min', 3.0), ('max', 200.0)])

So the table above seems to be outdated, right? At least the “tilt speed” is not matching and also the “vertical speed” thing.

It is possible that the ranges were changed in a firmware update (I don’t know either where this table is from, but the information it contains is indeed outdated). Anyway, getting the ranges directly from the firmware is the best way, as you will always get up-to-date values.

Yepp, that works fine.

Is there a similar means to obtain the gimbal min/max/currents?


The following event messages should give you this information for the gimbal : gimbal.absolute_attitude_bounds (min/max values for each axis in the absolute frame of reference) and gimbal.attitude (current value for each axis in the absolute and relative frames of reference).

Well, it is not so, that I didn’t try already… Just to no avail…

        gimbal_attitude = self.drone(gimbal.attitude(gimbal_id = 0, yaw_frame_of_reference=1, pitch_frame_of_reference=1, roll_frame_of_reference=1))



Hmm… Adding a wait() hangs.

This topic was automatically closed after 30 days. New replies are no longer allowed.