Giter Club home page Giter Club logo

dsdl's Introduction

DroneCAN DSDL definitions

This repository contains the DSDL definitions of the standard DroneCAN messages and services.

This DSDL is based on DroneCAN v1

For information about the Message type IDs (including how the unqiue IDs are allocated), see id distribution

Message ID

For broadcast messages the following should be used:

  • [0, 20000) Standard message types
  • [20000, 21000) Vendor-specific message types
  • [21000, 65536) Reserved for future use

For service types, the following should be used:

  • [0, 100) Standard service types
  • [100, 200) Reserved for future use
  • [200, 256) Vendor-specific service types

dsdl's People

Contributors

bugobliterator avatar dagar avatar dakejahl avatar iampete1 avatar magicrub avatar peterbarker avatar rabad-matternet avatar rishabsingh3003 avatar rmackay9 avatar tridge avatar vanja-apd avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

dsdl's Issues

Proposal: Fixed len size on FD

Proposal: In FD mode, All variable-length arrays are prepended with a 1-byte length field

Current behavior: They're prepended with a bit-aligned field that changes length depending on maximum array length.

Why:
Variable-length arrays are common in DroneCAN messages, including fundamental types defined in uavcan.protocol. These introduce bit-level alignment. Bit-level alignment, vice byte is not user-friendly to develop for for these reasons:

  • Computer registers are byte-aligned
  • Programming languages like C and Rust have good byte-level APIs, but poor or non-existant bit-level APIs
  • ICs and wire protocols (other than DC's) almost always use byte-level alignment
  • Common message view protocols, like in DroneCAN GUI, print bytes.

Overall, implementing and debugging byte-aligned protocols is much easier than bit-aligned ones.

Bit-level alignment can save bandwidth in some cases, but often these arrays use byte-aligned variables, like uint8.

This doesn't come up in many cases in non-FD mode, since variable-length arrays are often placed at the end of payloads. In non-FD Dronecan, the len field is removed in this cases due to tail optimization. In FD mode, these len fields introduce bit-level alignment, even when the message is otherwise byte-aligned.

Is this a breaking change?

Maybe. I don't think that means we should dismiss it; rather now is a good time to implement this. Here's why:

  • Few devices currently support FD mode. This is likely to change in the near future
  • Ardupilot currently doesn't support FD mode in official releases; this will change in the next release if I understand correctly
  • FD mode's implementation currently is already a breaking change by removing tail optimization
  • The Dronecan spec page currently doesn't discuss FD implementation details like the removed TCO

For basic/BX CAN, I don't think we should make this change, because it would break many devices, and is not worth forcing the change. For FD, I think this is an ideal time to do it, with a narrowing window.

Device settings / configuration checksum

Currently the DSDL supports firmware checksum / CRC for a device - but not the configuration checksum. A config checksum is an easy way to determine (as part of a pre-flight check, for example) that all devices are correctly configured. Store the known good checksum in the AP / GCS / etc and compare the reported device values to ensure no configs have changed.

Is there any appetite for adding this?

Format proposal, with covariance as an example

Currently, implementation of DSDL types if often complicated. The causes manifest in these related ways:

  • Bit-level alignment
  • Strings used as enums
  • Variable field sizes
  • Variable message sizes
  • Non-constant, and/or non-documented indexes.

This makes writing firmware to read from or write to DroneCAN devices more complicated than for other common communications protocols. I recommend something like this instead. This is from the UBLOX M10 interface description:

image

Note that it uses byte-level alignment, an explicit length, and explicit indexes. It lists the fields in a standard format, without mixing enums, comments, and fields. This is substantially easier to code for than DroneCAN messages. I propose considering something like this for future messages, and adding new messages for existing functionality that uses something like this. This specific example could be used as a replacement for this in the Fix2 message:

#
# Precision
#
float16[<=36] covariance    # Position and velocity covariance. Units are
                            # m^2 for position, (m/s)^2 for velocity and
                            # m^2/s for position/velocity.

float16 pdop

#
# Position and velocity solution in ECEF, if available
#
ECEFPositionVelocity[<=1] ecef_position_velocity

Note how this, from the DSDL uses bit-level alignment due to its length field, changes the index of future values, and is effectively useless for describing what values go in it.

Baro Alt

It seems weird to me that barometric height (i.e. pressure altitude) is part of the navigation message. Typically the only data needed to compute and send barometric height would be the static pressure. I get that this is an estimated state, but so is indicated airspeed and true airspeed, which are grouped as separate messages in equipment/air_data.

I would argue that this is more important than just semantics. We have an air data computer CAN module, which has static and differential pressure transducers and an RTD front-end for an Outside Air Temperature (OAT) probe. I would expect our air data module to estimate and send the air data states (i.e. airspeeds and altitudes), but right now I have to either:

  1. Send static pressure and expect baro alt to be computed elsewhere
  2. Send the navigation message, which is huge, just to send the baro alt estimation

So, I propose that baro alt should be it's own message under equipment/air_data, just like the airspeed messages.

Proposal: Add control reception support

I propose adding control channel data reception to the DroneCAN protocol. This post is a collaboration between Hydra and myself.

This is a common use case, and would be a good fit for various vehicle types that use DroneCAN. I’m also interested in Cyphal support, but will focus on DroneCAN for now. I have concerns about Cyphal’s complexity that may delay or preclude using it.

Requirements:

  • The device transmits control channel data with low latency. The canonical use case is a radio transmitter connected to a manual controller, with 4 high-resolution channels for pitch, roll, yaw, and throttle, and several more lower-resolution "aux" channels assoc. The aux channels are intended for buttons, and switches that have fixed positions. They might be used for changing flight mode, cycling steer points, activating payloads, arming motors etc. This is an example use and is common, but a more general solution is desired.

  • The device sends link statistics, such as RSSI, portion of packets received recently, transmitter nominal power level etc. Note on a general solution applies here as well.

  • The device sends metadata, including an immediate message if the link is lost. (Note: This could also be handled by the receiver, but I think a backup from the RF node itself would be nice) It may also send a periodic heartbeat containing system status.

I'm unclear on the exact capabilities of DroneCAN and Cyphal (especially the latter), and use cases that may arise. Below are two starting example implementations, that represent different ends of a flexibility spectrum. They would both be sufficient for the canonical use case described above, but different in applications beyond it:

#1: A simple, partially hard-coded standard, analogous to the CRSF protocol. I imagine this will integrate in a straightforward way with DroneCAN. I’ve put this together by following examples on the DroneCAN List of standard data types. Of note, it sends all control channel data in the same packet, without distinguishing priority.

Example packet, using the DroneCAN List of standard data types:

uint16 [<=10] channel_high_precision     # High precision channel data. For example, throttle or pitch

uint8 [<=10] channel_low_precision        # Low precision channel data. For example, arm status or flight mode

Of note, I’m not sure how to make precision flexible using the example standard data types; in this example, I’ve hard-coded 2 precision levels. Compared to existing standards that use 11-13 bits of data for control channel data, this is higher precision, so uses more bandwidth/larger packet size than required. How would you handle this, using the DroneCAN spec?

Example link stats packet, sent at a slower rate, hard-coded values and precision; this is what CRSF uses. I am not proposing it specifically, but it’s an example of hard-coding, using a current standard. Of note, it is inflexible:

uint32 timestamp
uint8 uplink_rssi_1
uint8 uplink_rssi_2
uint7 uplink_link_quality
int8 uplink_snr
uint8 active_antenna
int8 rf_mode
int4 uplink_tx_power
uint8 download rssi
uint8 downlink_link_quality
int8 downlink_snr
  • If the link is lost at any point, the node immediately broadcasts a terse message of high priority.

#2: An ideal, flexible standard. I would prefer something like this, but am not sure if it fits the model of DroneCAN and/or Cyphal:

By default, the node is silent. The entity receiving data (eg flight controller) submits a discovery request. The Rx responds with a list of information it can supply, including channel indices, available resolutions, and available data rates for each channel. Given this info, the FC can choose which info it wants to receive based on the Rx’s capabilities, which it knows due to the response to discovery. The subscribe request will always succeed, since the flight controller has the information it needs to make it.

Example of available information: #1: The channel number (to be interpreted by the Rx node). #2: Data rate. #3: resolution. The node responds with a success or error message, per its ability to serve this request. If success, the node broadcasts the data as requested until it receives a cancellation request. Example subscription request:

[
    Subscription index/reference = 1,
    Rate: 100Hz,
    Channel 1, 12 bits,
    Channel 2, 12 bits
]

[
    Subscription index/reference = 2,
    Rate: 50Hz,
    Channel 5, 2 bits,
]

[
    Subscription index/reference = 3,
    Rate: 10Hz,
    Channel 6, 2 bits,
    Channel 17, 1 bit,
    Channel 18, 1 bit,
]

Example responses here. E.g.

[
  Subscription index/reference = 1,
  <12 bits of data for channel 1>,
  <12 bits of data for channel 2>,
]

[
  Subscription index/reference = 2,
  <2 bits of data for channel 5>,
]


[
  Subscription index/reference = 3,
  <2 bits of data for channel 6>,
  <1 bits of data for channel 17>,
  <1 bits of data for channel 18>,
]

The sequence of packets will be:
1,1,1,1…,2,1,1,1…,2,1,1,1… eventually 3,1,1,1…, 2,1,1,1…

The flexible approach would be robust to changing requirements for different use cases, and allow the subscriber (eg flight controller) to only receive the data it needs, at the rate it's capable of receiving. It would minimize the amount of data sent, saving bandwidth. Of note, the FC could make multiple subscriptions, each with a reference that is included in the subscribe request; the same reference is returned when the Rx sends data, so the FC knows what data, and the format of it for decoding purposes.

I think some combination of the approaches may be viable. For example, a flexible subscription setup, but restricting the number of data rates to 2.

Of note, I think for many cases of channel data, 2+ frames may be required on FDCAN. If this addition is made available for basic CAN, multi-frame packets would be required in all cases. This begs the question: Should this be backwards compatible with basic CAN, or should it be FDCAN only? Suggested approach: A discovery agreement between the Rx and FC, allowing either to be used. The subscribe can choose the frame format (CAN/FDCAN) too.

Relevant discussion on the TBS github; about improving the CRSF spec, but is immediately applicable here: tbs-fpv/freedomtx#26 (comment)

Would appreciate any and all input on establishing a standard that’s simple and flexible. Of note, I already have a working CAN receiver, using an ExpressLRS circuit integrated with an STM32 MCU that acts as the FDCAN node, and a CAN transceiver. Using this for specific hardware where both Rx and flight controller are cooperative is easy; my intent here is establishing a common API that will allow CAN Rxes to be swapped arbitrarily, with no change to flight-controller code.

Variable-length array fields: Make length a single-byte

Currently, variable-arrange arrays are difficult to implement and debug. This is due to them having bit-level alignment, and being skipped in some cases per the DSDL spec, eg when a combination of tail array optimization requirements are met per this: https://dronecan.github.io/Specification/3._Data_structure_description_language/. This can change the alignment of the rest of the message, to save between 1 and 7 bits of data. IMO not worth it. Of note, it appears that in some cases like GetNodeInfo responses, tail array optimization is used in legacy CAN packets, but not FD packets, but reasons I'm not clear about.

Recommended fix: Either to be applied to new message types, or with a deprecation to the existing format; I recognize that the former is more realistic.
All variable length arrays start with a single-byte length field.

Example of how, in an FD frame, PyDroneCAN (and presumably the spec as is) implements this name length, printed from PyDroneCAN:

name=ArrayValue(type=saturated uint8[<=80], items=[111, 114, 103, 46, 97, 110, 121, 108, 101, 97, 102, 46, 103, 110, 115, 115]))

This is what that section of the message looks like over the wire in FD mode, due to the present alignment handling. Note that every word is bit-shifted by one.

[32, 222, 228, 206, 92, 194, 220, 242, 216, 202, 194, 204, 92, 206, 220, 230, 230]

In legacy mode, the data is passed byte for byte over the wire, ie 111, 114, 103 etc.

In this case, 32 is the name length of 16, bit shifted left by 1. 222 is the first name byte, shifted left by one; etc.

Telemetry

How would you like to handle telemetry? One option is the tunnel messages here: https://github.com/dronecan/DSDL/tree/master/uavcan/tunnel. @peterbarker would prefer something fixed instead from chats on Discord.

I strongly prefer something byte-aligned. The tunnel Broadcast DSDL message currently offsets the array by 2 bits, which has consequences for implementing/testing/debugging.

I'm currently doing CAN telemetry using an arbitrary CAN ID, and passing through the payload directly in the frame with no metadata.

Feature Request: Measurement Range

I would like to add messages to define measurement ranges for DroneCAN sensor nodes. For example, one great use of DroneCAN would be to stack air data sensors, i.e. one with a range of 0 - 20 m/s, one with a range of 0 - 40 m/s, etc. This way you can get better accuracy at low speeds and be able to switch to the higher speed sensor when the low speed sensor saturates. You can imagine similar situations with the IMU / INS (i.e. an accel with a +/-4g range and a second sensor with a +/- 40g range).

To effectively use sensors with multiple measurement ranges, subscribers would need to know the measurement ranges of the publishers. I think this could be accomplished by either:

  1. The subscriber requesting this message from the publisher, or
  2. The publisher broadcasting this message at a low rate (i.e. 1 Hz)

I also think the measurement variance could be included with this message, enabling the high rate messages to be smaller in size and more efficient, especially for the limited bandwidth in CAN 2.0. I'm happy to contribute, but would like to gauge community interest before heading down this path.

Move 20300.CBAT to `dronecan` section

Hi! The cuav/equipment/power/20300.CBAT.uavcan power supply data seems more practical than the ones in uavcan/equipment/power. I'm designing a CAN-based power supply, and it's the best match to the data I'd like to output.

Thoughts on moving this to dronecan/equipment/power or similar? It was presumably designed with a specific device in mind, but it seems like a better general option than the ones in uavcan.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.