The packet protocol used to communicate with the Crazyflie is called CRTP. It
provides data to the packet that allows to route it to the different Crazyflie
subsystems. In the context of this documentation, the term CRTP
is used both
to describe the packet protocol and its format as well as the collection of
data packets that are used to communicate with the Crazyflie.
Unless otherwise noted, this protocol documentation covers Crazyflie 2.x
, the
Crazyflie Bolt
and the Roadrunner
.
Protocol version and stability guarantee
In order to allow for improvement and breaking change the protocol is versioned. The version is available using the getProtocolVersion packet.
The version is currently 5.
When removing functionality from the protocol, packet will be depreciated for at least one version before being removed. Depreciated functionality prints a Warning in the console. This rule allows for the Crazyflie firmware to evolve and remove old functionalities when needed and for a client or lib to have some compatibility guarantee. For example if a client support the protocol version 5, it is guarantee to work with version 6 but should likely not accept to connect a Crazyflie on version 7 of the protocol.
Communication stack
The Crayzyflie communication is implemented as a stack of independent layers:
+-------------------+
+ Subsystems + <- Log/Param/Commander/...
+-------------------+
+ CRTP + <- (port, channel, payload)
+-------------------+
+ Link + <- Radio link or USB link
+-------------------+
+ Physical medium + <- radio or USB
+-------------------+
- The physical layer is responsible for transmitting packet to and from the Crazyflie. Currently USB and Radio are actively supported.
- The link is responsible of implementing safe and ordered packet channels to and from the Crazyflie. The link abstract the physical medium and implement one transmit and one receive packet channels to and from the Crazyflie.
- CRTP implements port and channel information used to route the packet to various subsystem. port are very similar to UDP port, they are assigned to subsystems. channel are intended to be used in subsystems to route packets to different functionalities.
- Subsystems implements the Crazyflie functionalities that can be controlled over CRTP. There is one port assigned to each subsystem.
Link implementations
There is currently two actively supported link implementation. They are documented on their own thread:
- The radio link implements CRTP link over nRF24 compatible radios
- The USB link implements CRTP link over USB to the Crazylfie 2.x USB port
Packet ordering and real-time support
CTRP stands for Crazy RealTime Protocol
. It was designed to allow packet
prioritization to help real-time control of the Crazyflie.
The Link guarantees strict packet ordering within a port. Packets for different ports can be re-organized and sent out of order.
If implemented, the packet prioritization works by assigning higher priority to lower port number.
This allows use-case like uploading a trajectory while still controlling the Crazyflie in real-time to work seamlessly as long as the trajectory upload uses a higher port number as the real-time setpoints.
CRTP packer metadata
Each CRTP packets carries one port number, a channel number as well as a Payload:
- The
port
range between 0 and 15 (4 bits) - The
channel
ranges between 0 and 3 (2 bits) - The payload is a data buffer of up to 31 bytes
The couple port
:channel
can be written separated by a color in this documentation.
Null packet and special packets
The port:channel 15:3 is a special case and is called a null packet. This packet is ignored by the Crazyflie and should be ignored by any CRTP lib on the ground.
The radio link requires on packet to be sent in order to receive a packet, in this context the null packet is used to poll downlink data when there is no data to be sent.
The NULL packet has been extensively used by links to implement side-channel packets that are communicated outside the CRTP data flows. For example this is used to implement bootloader packets that should be interpreted by the Crazyflie’s nRF51 radio chip without being passed to the STM32 application processor.
Port allocation
CRTP ports are allocated to subsytem in the Crazyflie. The intention is to provide a bidirectional communication between one subsystem in the Crazyflie and its handling on the ground.
Port | Target | Used for |
---|---|---|
0 | Console | Read console text that is printed to the console on the Crazyflie using consoleprintf |
2 | Parameters | Get/set parameters from the Crazyflie. Parameters are defined using a macro in the Crazyflie source-code |
3 | Commander | Sending low level (instantaneous) control set-points for the roll/pitch/yaw/thrust regulators |
4 | Memory access | Memory access for physical memories and register-mapped functionalities |
5 | Data logging | Set up log blocks with variables that will be sent back to the Crazyflie at a specified period. Log variables are defined using a macro in the Crazyflie source-code |
6 | Localization | Packets related to localization |
7 | Generic Setpoint | Generic instantaneous setpoints (ie. position control and more) |
13 | Platform | Used for misc platform control, like debugging and power off |
14 | Client-side debugging | Debugging the UI and exists only in the Crazyflie Python API and not in the Crazyflie itself. |
15 | Link layer | Low level link-related service. For example echo to ping the Crazyflie |
Connection procedure
Generaly speaking CRTP is connection-less and most of the subsystem in the Crazyflie will strive to be stateless. This is not true for all the subsystem or links though:
- The USB link needs to be enabled in the Crazyflie using a USB control packet
- The Radio link maintains two packet counters to ensure that there are no packet loss and strict packet ordering. This is called Safelink and needs to be enabled early when connecting a Crazyflie
- The Log subsystem maintain a state of all the currently enabled log blocks
and will continue sending data even if the link is lost. Therefore, the log
subsystem implement a
reset
commands to reset the internal state.
When implementing a Crazyflie client the connection procedure will usually look like:
- Initialize the link
- Initialize all the supported subsystem (this will be a no-op for most of them)