|
23 | 23 | Provides access to the supervisor module of the Crazyflie platform. |
24 | 24 | """ |
25 | 25 | import logging |
| 26 | +import struct |
26 | 27 | import threading |
27 | 28 | import time |
28 | 29 | import warnings |
29 | 30 |
|
| 31 | +from cflib.crazyflie.localization import Localization |
| 32 | +from cflib.crazyflie.platformservice import PLATFORM_COMMAND |
| 33 | +from cflib.crazyflie.platformservice import PLATFORM_REQUEST_ARMING |
| 34 | +from cflib.crazyflie.platformservice import PLATFORM_REQUEST_CRASH_RECOVERY |
30 | 35 | from cflib.crtp.crtpstack import CRTPPacket |
31 | 36 | from cflib.crtp.crtpstack import CRTPPort |
32 | 37 |
|
@@ -93,18 +98,19 @@ def __init__(self, crazyflie): |
93 | 98 | self._cf.add_port_callback(CRTPPort.SUPERVISOR, self._supervisor_callback) |
94 | 99 | self._bitfield_received = threading.Event() |
95 | 100 |
|
96 | | - def _check_protocol_version(self): |
97 | | - """Returns True if the protocol version is supported, False otherwise.""" |
| 101 | + def _is_legacy_firmware(self): |
| 102 | + """Returns True if the firmware does not support the supervisor port.""" |
| 103 | + return self._cf.platform.get_protocol_version() < 12 |
| 104 | + |
| 105 | + def _warn_legacy_firmware(self): |
| 106 | + """Warn that the firmware is too old for the supervisor port.""" |
98 | 107 | version = self._cf.platform.get_protocol_version() |
99 | | - if version < 12: |
100 | | - warnings.warn( |
101 | | - 'The supervisor subsystem requires CRTP protocol version 12 or later. ' |
102 | | - f'Connected Crazyflie reports version {version}. ' |
103 | | - 'Update your Crazyflie firmware.', |
104 | | - stacklevel=3, |
105 | | - ) |
106 | | - return False |
107 | | - return True |
| 108 | + warnings.warn( |
| 109 | + 'The supervisor subsystem requires CRTP protocol version 12 or later. ' |
| 110 | + f'Connected Crazyflie reports version {version}. ' |
| 111 | + 'Update your Crazyflie firmware. Using legacy fallback.', |
| 112 | + stacklevel=3, |
| 113 | + ) |
108 | 114 |
|
109 | 115 | def _supervisor_callback(self, pk: CRTPPacket): |
110 | 116 | """ |
@@ -136,7 +142,8 @@ def _fetch_bitfield(self, timeout=0.2): |
136 | 142 | Request the bitfield and wait for response (blocking). |
137 | 143 | Uses time-based cache to avoid sending packages too frequently. |
138 | 144 | """ |
139 | | - if not self._check_protocol_version(): |
| 145 | + if self._is_legacy_firmware(): |
| 146 | + self._warn_legacy_firmware() |
140 | 147 | return 0 |
141 | 148 | now = time.time() |
142 | 149 |
|
@@ -253,50 +260,82 @@ def send_arming_request(self, do_arm: bool): |
253 | 260 | """ |
254 | 261 | Send system arm/disarm request. |
255 | 262 |
|
| 263 | + If the connected Crazyflie does not support CRTP protocol version 12 |
| 264 | + or later, the legacy platform channel is used as a fallback. |
| 265 | +
|
256 | 266 | Args: |
257 | 267 | do_arm (bool): True = arm the system, False = disarm the system |
258 | 268 | """ |
259 | | - if not self._check_protocol_version(): |
260 | | - return |
261 | | - pk = CRTPPacket() |
262 | | - pk.set_header(CRTPPort.SUPERVISOR, SUPERVISOR_CH_COMMAND) |
263 | | - pk.data = (CMD_ARM_SYSTEM, do_arm) |
264 | | - self._cf.send_packet(pk) |
| 269 | + if self._is_legacy_firmware(): |
| 270 | + self._warn_legacy_firmware() |
| 271 | + pk = CRTPPacket() |
| 272 | + pk.set_header(CRTPPort.PLATFORM, PLATFORM_COMMAND) |
| 273 | + pk.data = (PLATFORM_REQUEST_ARMING, do_arm) |
| 274 | + self._cf.send_packet(pk) |
| 275 | + else: |
| 276 | + pk = CRTPPacket() |
| 277 | + pk.set_header(CRTPPort.SUPERVISOR, SUPERVISOR_CH_COMMAND) |
| 278 | + pk.data = (CMD_ARM_SYSTEM, do_arm) |
| 279 | + self._cf.send_packet(pk) |
265 | 280 | logger.debug(f'Sent arming request: do_arm={do_arm}') |
266 | 281 |
|
267 | 282 | def send_crash_recovery_request(self): |
268 | 283 | """ |
269 | 284 | Send crash recovery request. |
| 285 | +
|
| 286 | + If the connected Crazyflie does not support CRTP protocol version 12 |
| 287 | + or later, the legacy platform channel is used as a fallback. |
270 | 288 | """ |
271 | | - if not self._check_protocol_version(): |
272 | | - return |
273 | | - pk = CRTPPacket() |
274 | | - pk.set_header(CRTPPort.SUPERVISOR, SUPERVISOR_CH_COMMAND) |
275 | | - pk.data = (CMD_RECOVER_SYSTEM,) |
276 | | - self._cf.send_packet(pk) |
| 289 | + if self._is_legacy_firmware(): |
| 290 | + self._warn_legacy_firmware() |
| 291 | + pk = CRTPPacket() |
| 292 | + pk.set_header(CRTPPort.PLATFORM, PLATFORM_COMMAND) |
| 293 | + pk.data = (PLATFORM_REQUEST_CRASH_RECOVERY,) |
| 294 | + self._cf.send_packet(pk) |
| 295 | + else: |
| 296 | + pk = CRTPPacket() |
| 297 | + pk.set_header(CRTPPort.SUPERVISOR, SUPERVISOR_CH_COMMAND) |
| 298 | + pk.data = (CMD_RECOVER_SYSTEM,) |
| 299 | + self._cf.send_packet(pk) |
277 | 300 | logger.debug('Sent crash recovery request') |
278 | 301 |
|
279 | 302 | def send_emergency_stop(self): |
280 | 303 | """ |
281 | 304 | Send emergency stop. The Crazyflie will immediately stop all motors. |
| 305 | +
|
| 306 | + If the connected Crazyflie does not support CRTP protocol version 12 |
| 307 | + or later, the legacy localization channel is used as a fallback. |
282 | 308 | """ |
283 | | - if not self._check_protocol_version(): |
284 | | - return |
285 | | - pk = CRTPPacket() |
286 | | - pk.set_header(CRTPPort.SUPERVISOR, SUPERVISOR_CH_COMMAND) |
287 | | - pk.data = (CMD_EMERGENCY_STOP,) |
288 | | - self._cf.send_packet(pk) |
| 309 | + if self._is_legacy_firmware(): |
| 310 | + self._warn_legacy_firmware() |
| 311 | + pk = CRTPPacket() |
| 312 | + pk.set_header(CRTPPort.LOCALIZATION, Localization.GENERIC_CH) |
| 313 | + pk.data = struct.pack('<B', Localization.EMERGENCY_STOP) |
| 314 | + self._cf.send_packet(pk) |
| 315 | + else: |
| 316 | + pk = CRTPPacket() |
| 317 | + pk.set_header(CRTPPort.SUPERVISOR, SUPERVISOR_CH_COMMAND) |
| 318 | + pk.data = (CMD_EMERGENCY_STOP,) |
| 319 | + self._cf.send_packet(pk) |
289 | 320 | logger.debug('Sent emergency stop') |
290 | 321 |
|
291 | 322 | def send_emergency_stop_watchdog(self): |
292 | 323 | """ |
293 | 324 | Send emergency stop watchdog. The Crazyflie will stop all motors |
294 | 325 | unless this command is repeated at regular intervals. |
| 326 | +
|
| 327 | + If the connected Crazyflie does not support CRTP protocol version 12 |
| 328 | + or later, the legacy localization channel is used as a fallback. |
295 | 329 | """ |
296 | | - if not self._check_protocol_version(): |
297 | | - return |
298 | | - pk = CRTPPacket() |
299 | | - pk.set_header(CRTPPort.SUPERVISOR, SUPERVISOR_CH_COMMAND) |
300 | | - pk.data = (CMD_EMERGENCY_STOP_WATCHDOG,) |
301 | | - self._cf.send_packet(pk) |
| 330 | + if self._is_legacy_firmware(): |
| 331 | + self._warn_legacy_firmware() |
| 332 | + pk = CRTPPacket() |
| 333 | + pk.set_header(CRTPPort.LOCALIZATION, Localization.GENERIC_CH) |
| 334 | + pk.data = struct.pack('<B', Localization.EMERGENCY_STOP_WATCHDOG) |
| 335 | + self._cf.send_packet(pk) |
| 336 | + else: |
| 337 | + pk = CRTPPacket() |
| 338 | + pk.set_header(CRTPPort.SUPERVISOR, SUPERVISOR_CH_COMMAND) |
| 339 | + pk.data = (CMD_EMERGENCY_STOP_WATCHDOG,) |
| 340 | + self._cf.send_packet(pk) |
302 | 341 | logger.debug('Sent emergency stop watchdog') |
0 commit comments