I’d like to collect the possible reasons for the drone to refuse to take-off (e.g. low battery, magnetometer needing a calibration, etc.).
However, Olympe keeps returning me takeoff_checklist state is uninitialized, even when e.g. my drone refuses to take off because of a low battery. Am I doing something wrong?
(setup: I have plugged via USB my SkyController 3, which is connected to an Anafi USA).
Also, all alarms are retrieved as “OFF”, even after an emergency landing (where I could unplug my PC, plug a tablet with FreeFlight, that immediately showed me the engines have been cut off by emergency)
Here are the results I am having:
import logging
import olympe
from olympe.messages.alarms import alarms, takeoff_checklist
from olympe.enums.alarms import state as AlarmState
ip="192.168.53.1"
drone = olympe.Drone(ip)
drone.connect()
drone.get_state(takeoff_checklist)
# Traceback (most recent call last):
# File "<stdin>", line 1, in <module>
# File "/home/user/src/sailor/venv38/lib/python3.8/site-packages/olympe/arsdkng/cmd_itf.py", line 754, in get_state
# return self._get_message(message.id).state()
# File "/home/user/src/sailor/venv38/lib/python3.8/site-packages/olympe/arsdkng/messages.py", line 951, in state
# raise RuntimeError(f"{self.fullName} state is uninitialized")
# RuntimeError: alarms.takeoff_checklist state is uninitialized
alarms = drone.get_state(alarms)
for (k, v) in alarms.items():
if v["state"] == AlarmState.on:
print(f"ON {k}")
else:
print(f"OFF {k}")
# This prints all alarms as OFF, even when FreeFlight tells me otherwise
# OFF type.user_emergency
# OFF type.motor_cutout
# OFF type.drone_inclination_too_high
# OFF type.magneto_perturbation
# OFF type.magneto_low_earth_field
# OFF type.horizontal_geofence_reached
# OFF type.vertical_geofence_reached
There are a few mistakes in the documentation and we apologize for that. get_state(alarms) and get_state(takeoff_checklist) are not compatible with Anafi USA (only with Anafi AI). To get “alarms” events with Anafi USA, use an EventListener to listen events from AlertStateChanged. This message is not deprecated on Anafi USA.
Thanks a lot for your answer!
I can now grab these alarms, although I am now facing another issue. I can listen for all events, but not filter them. I’m not sure what I’m doing wrong.
Here is a minimal reproducer
import time
import olympe
from olympe.messages.ardrone3.PilotingState import AttitudeChanged
ip="192.168.42.1"
drone = olympe.Drone(ip)
drone.connect()
class FlightListener(olympe.EventListener):
@olympe.listen_event(AttitudeChanged())
def onAttitudeEvent(self, event, scheduler):
print("----------")
@olympe.listen_event()
def onAnyEvent(self, event, scheduler):
print(f" {event.message.fullName}")
with FlightListener(drone):
time.sleep(10)
Running this gives this output
/home/user/venv38/lib/python3.8/site-packages/olympe/arsdkng/proto.py:314: UserWarning: MessageFactory class is deprecated. Please use GetMessageClass() instead of MessageFactory.GetPrototype. MessageFactory class will be removed after 2024.
return self.message_factory.GetPrototype(message_descriptor)
skyctrl.SkyControllerState.AttitudeChanged
skyctrl.SkyControllerState.AttitudeChanged
skyctrl.SkyControllerState.AttitudeChanged
2023-11-16 16:03:24,009 [WARNING] olympe.drone.Skycontroller 3 - _recv_cmd_cb - Unknown message id 0xa2000005
2023-11-16 16:03:24,009 [WARNING] olympe.drone.Skycontroller 3 - _recv_cmd_cb - Unknown message id 0xa2000004
common.CommonState.BootId
ardrone3.PilotingState.FlyingStateChanged
common.CalibrationState.MagnetoCalibrationRequiredState
common.CommonState.BatteryStateChanged
alarms.alarms
alarms.alarms
[...]
ardrone3.PilotingState.SpeedChanged
ardrone3.PilotingState.AltitudeChanged
ardrone3.PilotingState.AltitudeAboveGroundChanged
ardrone3.PilotingState.AttitudeChanged
[...]
^CTraceback (most recent call last):
File "repro.py", line 23, in <module>
time.sleep(10)
KeyboardInterrupt
As you can see, onAnyEvent picked events (including AttitudeChangeds), but onAttitudeEvent did not.
I’m not experienced enough in Python decorators to really understand what’s going wrong by staring at Olympe source code.
Also, type(event) tells me AttitudeChanged actually are ``, but I cannot import this in my script (because “”), so I suppose this is not an issue.
(in my case, I achieved what I wanted by listening to all events, then filtering by event.message.fullName, but that’s terrible dirty I’d be happy to use any cleaner solution)
Also, the AlertStates I’m able to monitor are not as many as the takeoff_checklist items.
Does that mean there is no way no monitor e.g. a required magneto_calibration on an Anafi USA?
the parameter _policy is missing in your listen_event decorator:
class FlightListener(olympe.EventListener):
@olympe.listen_event(AttitudeChanged(_policy="wait"))
def onAttitudeEvent(self, event, scheduler):
print("----------")
I think there’s some information missing from this sentence.
Not all events are necessarily in AlertStateChanged_State, for example, you can catch this this event for the magneto_calibration. Feel free to consult the Olympe documentation to find the event you want.
Thank you so much for this quick and helpful reply
This _policy="wait" was indeed there in the example on Github, but it turns out I did not read it as carefully as I did with the Olympe doc. Silly me. (would it be worth upgrading the doc?)
Not all events are necessarily in AlertStateChanged_State, for example, you can catch this this event for the magneto_calibration.
Absolutely. That’s what I’m already doing. However, is there a comprehensive list somewhere of items that could prevent the drone from taking-off?
For context: I’m controlling my drone through Olympe, and I’d like not to need to rely on FreeFlight to troubleshoot a drone not taking-off. I’d be happy to know everything I’m supposed to monitor to warn the user in case they are unable to take-off.
I know by experience that a critically low battery or a miscalibrated magnetometer are such items. What are all the others? I thought collecting the takeoff_checklists would be enough, but since I can only monitor AlertState, I’m now confused about what I’m supposed to monitor after all.
I think there’s some information missing from this sentence.
Indeed, I forgot to copy/paste the right term after I wrote the message. Never mind, I can achieve what I wanted (for completeness, and as far as I can remember, the received message was a olympe.message.arsdkng.whatever, but I could only import olympe.message.whatever, as Python complained arsdkng is not a module).