Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve the low level CRTP documentation #940

Merged
merged 5 commits into from
Feb 16, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 17 additions & 6 deletions docs/functional-areas/crtp/crtp_console.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,26 @@ Crazyflie to a host using the consoleprintf function.
Communication protocol
======================

Answer (Crazyflie to host):
Port: 0
Channel: 0

Payload (Crazyflie to host):
+---------//-----------+
| PRINTED CONSOLE TEXT |
+---------//-----------+
Length 0-31

The contents of the buffer on the copter side is sent if any of the
following is fulfilled:
The content is the text from the console. The encoding is ascii/UTF8 however
this cannot be guaranteed so the packet receiver should be ready for binary
buffer.

The best is to not make any assumption about the data received on the console
port: it could be a line, multiple line, part of a line, ...


The current algorithm in the Crazyflie is to send a console packet is any of
these condition are fulfilled:

- The output buffer (of 31 bytes) is full
- A \"newline\" character has to be send (\\n and/or \\r)
- A flush command as been issued
- The output buffer (of 31 bytes) is full
- A \"newline\" character has to be send (\\n and/or \\r)
- The flush function has been called
37 changes: 37 additions & 0 deletions docs/functional-areas/crtp/crtp_link.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
---
title: Link layer services
page_id: crtp_link
---

This ports handle various link-related low level services. It most notably host the *null packet* used by the radio
link to pull downlink packets.

## CRTP channels

| port | channel | Function |
|------|---------|----------|
| 13 | 0 | [Echo](#platform-commands) |
| 13 | 1 | [Source](#platform-commands) |
| 13 | 2 | [Sink](#app-channel) |
| 13 | 3 | [*Null packets*](#null-packet) |

## Echo

Packets sent to the Echo channel are send back unaltered.

## Source

When receiving any packet on the source channel, the Crazyflie sends back a 32 bytes packet on the source channel.

Since protocol version 1, this packet contains the string "Bitcraze Crazyflie" followed by zeros. Before version 1 the
content of the packet was not defined. This allows to detect firmware protocol version bellow 1 (the getProtocolVersion
packet was only implemented after version 1 of the protocol).

## Sink

Packet sent to the sink channel are dropped and ignored.

## Null packet

Null packets must be dropped. The data part of NULL packet is used for some out-of-band communication at the link
level or by the bootloader. The Crazyflie firmware and lib should ignore them.
117 changes: 117 additions & 0 deletions docs/functional-areas/crtp/crtp_platform.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
---
title: Platform services
page_id: crtp_platform
---

This ports implements miscellaneous platform-related functionality for the Crazyflie.

## CRTP channels

| port | channel | Function |
|------|---------|----------|
| 13 | 0 | [Platform commands](#platform-commands) |
| 13 | 1 | [Version commands](#platform-commands) |
| 13 | 2 | [App channel](#app-channel) |
| 13 | 3 | *Reserved for future use* |

## Platform commands

The first byte describe the command:

| value | Command |
|-------|---------|
| 0 | [Set continuous wave](#set-continuous-wave) |

### Set continuous wave

Command and answer:

| Byte | Description |
|------|-------------|
| 0 | setContinuousWave (0) |
| 1 | Enable |

If enable is not 0, the Crazyflie radio will start transmitting a continuous sine wave at the currently setup
freqency. The same packet is sent back to confirm the value has been set.

This command should only be sent over USB (it disables the radio communication).
It is used in production to test the Crazyflie radio path and should not be used outside of a lab or
other very controlled environment. It will effectively jam local radio communication on the channel.

## Version commands

The first byte describes the command:

| value | Command |
|-------|---------|
| 0 | Get protocol version |
| 1 | Get firmware version |
| 2 | Get device type name |

### Get protocol version

Command:

| Byte | Description |
|------|-------------|
| 0 | getProtocolVersion (0) |

Answer:

| Byte | Description |
|------|-------------|
| 0 | getProtocolVersion (0) |
| 1 | Version |

Returns the CRTP protocol version. See the
[protocol versioning and stability guarantee](index.md#protocol-version-and-stability-guarantee) documentation for more
information.

### Get firmware version

Command:

| Byte | Description |
|------|-------------|
| 0 | getFirmwareVersion (1) |

Answer:

| Byte | Description |
|------|-------------|
| 0 | getFirmwareVersion (1) |
| 1.. | Version string |

Returns a string representation of the current firmware version. This returns the GIT tag of the source code where the
firmware was built. For a release the version string will look like "2022.01". For a build between releases the
number of commit since the release will be added, for example "2022.01 +42".

### Get device type name

Command:

| Byte | Description |
|------|-------------|
| 0 | getDeviceTypeName (2) |

Answer:

| Byte | Description |
|------|-------------|
| 0 | getDeviceTypeName (2) |
| 1.. | Device type name string |

Returns a String representation of the device type the firmware is running on. The currently existing device type are:

| Device Type | Device type name |
|-------------|------------------|
| RZ10 | Crzyflie Bold |
| CF20 | Crazyflie 2.0 |
| CF2.1 | Crazyflie 2.1 |
| RR10 | Roadrunner 1.0 |

## App channel

The app channel is intended to be used by user apps on the Crazyflie and on the ground to exchange data. Every packet
sent and received from the app channel (port:channel) (13:2) will be available through the
[app channel API](/docs/userguides/app_layer.md#app-channel-packet-based-communication-between-the-crazyflie-and-the-python-lib).
154 changes: 111 additions & 43 deletions docs/functional-areas/crtp/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,69 +3,137 @@ title: CRTP - Communication with the Crazyflie
page_id: crtp_index
---

For communicating with the Crazyflie we have implemented our own
high-level protocol named CRTP (Crazy RealTime Protocol). It\'s a fairly
simple protocol using a number of target ports where data can be sent
and received in either direction, but in most cases the communication is
driven from the host. The protocol can be implemented on a number of
mediums, currently we have USB and Crazyradio support.
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.

CRTP
====
Unless otherwise noted, this protocol documentation covers `Crazyflie 2.x`, the
`Crazyflie Bolt` and the `Roadrunner`.

Physical carriers
-----------------
## Protocol version and stability guarantee

Currently CRTP is supported over Crazyradio and USB.
In order to allow for improvement and breaking change the protocol is versioned.
The version is available using the [getProtocolVersion](crtp_platform#get-protocol-version) packet.

| Carrier | Supports|
| -----------------| -------------------|
| Crazyradio (PA) | Crazyflie 1.0/2.X|
| USB | Crazyflie 2.X|
The version is currently 5.

Header
------
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](crtp_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.

Each packet has a 1 byte header and can carry up to 31 bytes data
payload. The header field has the following layout:
## Communication stack

7 6 5 4 3 2 1 0
+----+----+----+----+----+----+----+----+
| Port | Link | Chan. |
+----+----+----+----+----+----+----+----+
The Crayzyflie communication is implemented as a stack of independent layers:

Where:
+-------------------+
+ Subsystems + <- Log/Param/Commander/...
+-------------------+
+ CRTP + <- (port, channel, payload)
+-------------------+
+ Link + <- Radio link or USB link
+-------------------+
+ Physical medium + <- radio or USB
+-------------------+

- **Port**: Used to identify the functionality or task that is
associated with this message
- **Link**: Reserved for future use
- **Channel**: Used to identify the sub-task/functionality
- 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*.

Port allocation
---------------

Current port allocation:
## 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](crtp_console.md) | Read console text that is printed to the console on the Crazyflie using consoleprintf|
| 2 | [Parameters](crtp_parameters.md) | Get/set parameters from the Crazyflie. Parameters are defined using a [macro in the Crazyflie source-code](/docs/userguides/logparam.md)|
| 3 | [Commander](crtp_commander.md) | Sending control set-points for the roll/pitch/yaw/thrust regulators|
| 4 | [Memory access](crtp_mem.md) | Accessing non-volatile memories like 1-wire and I2C |
| 3 | [Commander](crtp_commander.md) | Sending low level (instantaneous) control set-points for the roll/pitch/yaw/thrust regulators|
| 4 | [Memory access](crtp_mem.md) | Memory access for physical memories and register-mapped functionalities |
| 5 | [Data logging](crtp_log.md) | 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](/docs/userguides/logparam.md)
| 6 | [Localization](crtp_localization.md) | Packets related to localization|
| 7 | [Generic Setpoint](crtp_generic_setpoint.md) | Allows to send setpoint and control modes|
| 13 | Platform | Used for misc platform control, like debugging and power off|
| 7 | [Generic Setpoint](crtp_generic_setpoint.md) | Generic instantaneous setpoints (ie. position control and more) |
| 13 | [Platform](crtp_platform.md) | 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 | Used to control and query the communication link|
| 15 | [Link layer](crtp_link.md) | Low level link-related service. For example *echo* to ping the Crazyflie |

Connection procedure
--------------------

CRTP is designed to be state-less, so there\'s no handshaking procedure
that is needed. Any command can be sent at any time, but for some
logging/param/mem commands the TOC (table of contents) needs to be
downloaded in order for the host to be able to send the correct
information. The implementation of the Pyton API will download the
param/log/mem TOC at connect in order to be able to use all the
functionality.
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)