Skip to content

Commit c8bf364

Browse files
authored
Merge pull request #597 from bitcraze/rik/supervisor-backward-compat
Supervisor: legacy CRTP fallback for pre-protocol-12 firmware
2 parents 1532485 + 53d55a4 commit c8bf364

File tree

2 files changed

+77
-36
lines changed

2 files changed

+77
-36
lines changed

cflib/crazyflie/platformservice.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@
4141
APP_CHANNEL = 2
4242

4343
PLATFORM_SET_CONT_WAVE = 0
44+
PLATFORM_REQUEST_ARMING = 1 # Deprecated: use supervisor.send_arming_request()
45+
PLATFORM_REQUEST_CRASH_RECOVERY = 2 # Deprecated: use supervisor.send_crash_recovery_request()
4446

4547
VERSION_GET_PROTOCOL = 0
4648
VERSION_GET_FIRMWARE = 1

cflib/crazyflie/supervisor.py

Lines changed: 75 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,15 @@
2323
Provides access to the supervisor module of the Crazyflie platform.
2424
"""
2525
import logging
26+
import struct
2627
import threading
2728
import time
2829
import warnings
2930

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
3035
from cflib.crtp.crtpstack import CRTPPacket
3136
from cflib.crtp.crtpstack import CRTPPort
3237

@@ -93,18 +98,19 @@ def __init__(self, crazyflie):
9398
self._cf.add_port_callback(CRTPPort.SUPERVISOR, self._supervisor_callback)
9499
self._bitfield_received = threading.Event()
95100

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."""
98107
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+
)
108114

109115
def _supervisor_callback(self, pk: CRTPPacket):
110116
"""
@@ -136,7 +142,8 @@ def _fetch_bitfield(self, timeout=0.2):
136142
Request the bitfield and wait for response (blocking).
137143
Uses time-based cache to avoid sending packages too frequently.
138144
"""
139-
if not self._check_protocol_version():
145+
if self._is_legacy_firmware():
146+
self._warn_legacy_firmware()
140147
return 0
141148
now = time.time()
142149

@@ -253,50 +260,82 @@ def send_arming_request(self, do_arm: bool):
253260
"""
254261
Send system arm/disarm request.
255262
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+
256266
Args:
257267
do_arm (bool): True = arm the system, False = disarm the system
258268
"""
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)
265280
logger.debug(f'Sent arming request: do_arm={do_arm}')
266281

267282
def send_crash_recovery_request(self):
268283
"""
269284
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.
270288
"""
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)
277300
logger.debug('Sent crash recovery request')
278301

279302
def send_emergency_stop(self):
280303
"""
281304
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.
282308
"""
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)
289320
logger.debug('Sent emergency stop')
290321

291322
def send_emergency_stop_watchdog(self):
292323
"""
293324
Send emergency stop watchdog. The Crazyflie will stop all motors
294325
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.
295329
"""
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)
302341
logger.debug('Sent emergency stop watchdog')

0 commit comments

Comments
 (0)