ULS-DeCoNet Blitz Messages Specification

Protocol Specification ULSDC-PBDS051125, version 1.0.4

ULSDC-PBDS051125 · version 1.0.4 · issued November 13, 2025
The numbered PDF is the controlled copy: download it from the portal.

Introduction

Purpose

The Blitz protocol is a specialized messaging subsystem within ULS-DeCoNet designed for high-frequency transmission of sensor measurement data from ULS positioning systems.

Key Characteristics

  • Low Overhead: Fixed 11-byte messages (3-byte header + 8-byte payload)
  • High Frequency: Optimized for 100+ Hz update rates
  • Real-time: Minimal latency from sensor to network
  • Type-safe: Strongly typed message definitions
  • Compact: Efficient packing of measurement data

Blitz Protocol Overview

Protocol Stack Position

block-beta
  columns 1
  A["Application Layer\n(Blitz Message Handling)"]
  B["IF Protocol\n(IF_CMD_BLITZ = 0x06)"]
  C["Framing Layer"]

Message Flow

flowchart LR
  Sensor --> Measurement --> BlitzEncode["Blitz Encode"] --> IFLayer["IF Layer"] --> Transport --> Receiver
  BlitzEncode --> MsgId["MSG_ID + Data"] --> BlitzCmd["IF_CMD_BLITZ"] --> Frame["UART/CAN Frame"]

Message Format

IF Layer Packet Structure

packet-beta
title "Blitz IF Layer Packet"
0-7: "CMD 0x06 (1 byte)"
8-15: "SRC_LID (1 byte)"
16-31: "MSG_ID (2 bytes)"
32-95: "DATA (8 bytes)"

Total Size: 11 bytes

Fields:

  • CMD: Always 0x06 (IF_CMD_BLITZ)
  • SRC_LID: Source device ID
  • MSG_ID: Blitz message type identifier (uint16_t, little-endian)
  • DATA: Message-specific payload (8 bytes maximum)

Common Data Structure

typedef struct {
    uint8_t src_lid;         // Source logical ID
    uint16_t msg_id;         // Message type ID
    union {
        uint8_t data[8];     // Raw data access
        // Specific message structures
        __uls_blitz_xcg1_rx_raw_measurmet xcg1_rx_raw_measurmet;
        __uls_blitz_msg_rx_raw_measurmet rx_raw_measurmet;
        __uls_blitz_msg_rx_pos_in_tx_frame rx_pos_in_tx_frame;
        __uls_blitz_msg_rx_mrx rx_mrx;
        __uls_blitz_msg_rx_dacs rx_dacs;
    };
} __blitz_common_data_struct;

Message Types

Message Type Summary

Message IDNameSizeDescription
0x0010XCG1_RX_RAW_MEASURMENT8 bytesLegacy raw measurement (±30°)
0x0011RX_RAW_MEASURMENT8 bytesRaw measurement (±180°)
0x0012RX_POS_IN_TX_FRAME8 bytes3D position in TX frame
0x0013RX_MRX6 bytesMulti-receiver info
0x0014RX_DACS8 bytesDACS with continuous yaw
0x0020GIMU_MEASUREMENT8 bytesGround IMU data
0x0030XX_TXC_IMU_OVERRIDE8 bytesIMU override command
0x0031XX_TXC_MAG_OVERRIDE8 bytesMagnetometer override

XCG1 Raw Measurement (0x0010)

Legacy message for XCopter Generation 1 systems

Structure

typedef struct __attribute__((packed)) {
    uint8_t status;    // Status bits
    uint8_t d;         // Distance in 10 cm increments
    int16_t aX;        // Angle X: [-30000 = -30°, +30000 = +30°]
    int16_t aY;        // Angle Y: [-30000 = -30°, +30000 = +30°]
    int8_t oF;         // Sensor offset Forward (cm)
    int8_t oR;         // Sensor offset Right (cm)
} __uls_blitz_xcg1_rx_raw_measurmet;

Total Size: 8 bytes

Field Descriptions

FieldTypeRangeDescription
statusuint8_t0-255Status flags (see section 5)
duint8_t0-255Distance in 10 cm steps (0-25.5m)
aXint16_t-30000 to +30000Angle X proportional to ±30°
aYint16_t-30000 to +30000Angle Y proportional to ±30°
oFint8_t-128 to +127Forward offset in cm
oRint8_t-128 to +127Right offset in cm

Angular Conversion

float angle_x_deg = (aX * 30.0f) / 30000.0f;
float angle_y_deg = (aY * 30.0f) / 30000.0f;

Distance Conversion

float distance_m = d * 0.1f;  // d in 10 cm steps

Raw Measurement (0x0011)

Standard raw measurement with full angular range

Structure

typedef struct __attribute__((packed)) {
    uint8_t status;      // Status bits
    uint8_t counter;     // Message counter
    int16_t aX;          // Angle X: [-180° to +180°]
    int16_t aY;          // Angle Y: [-180° to +180°]
    uint16_t distance;   // Distance measurement
} __uls_blitz_msg_rx_raw_measurmet;

Total Size: 8 bytes

Field Descriptions

FieldTypeRangeDescription
statusuint8_t0-255Status flags
counteruint8_t0-255Packet counter (wraps at 256)
aXint16_t-32768 to +32767Angle X scaled to ±180°
aYint16_t-32768 to +32767Angle Y scaled to ±180°
distanceuint16_t0-65535Distance in cm (0-655.35m)

Angular Conversion

float angle_x_deg = (aX * 180.0f) / 32767.0f;
float angle_y_deg = (aY * 180.0f) / 32767.0f;

Precision: ~0.0055° per LSB

Distance Conversion

float distance_m = distance * 0.01f;  // distance in cm

Position in TX Frame (0x0012)

3D position vector in transmitter coordinate frame

Structure

typedef struct __attribute__((packed)) {
    uint8_t status;    // Status bits
    uint8_t counter;   // Message counter
    int16_t posX;      // X position (cm)
    int16_t posY;      // Y position (cm)
    int16_t posZ;      // Z position (cm)
} __uls_blitz_msg_rx_pos_in_tx_frame;

Total Size: 8 bytes

Field Descriptions

FieldTypeRangeDescription
statusuint8_t0-255Status flags
counteruint8_t0-255Packet counter
posXint16_t-32768 to +32767X position in cm (±327.68m)
posYint16_t-32768 to +32767Y position in cm (±327.68m)
posZint16_t-32768 to +32767Z position in cm (±327.68m)

Coordinate System

Transmitter Frame:
         +Z (up)
          |
          |
          +------- +X (forward)
         /
        /
      +Y (right)

Position Conversion

float pos_x_m = posX * 0.01f;  // cm to m
float pos_y_m = posY * 0.01f;
float pos_z_m = posZ * 0.01f;

Range: ±327.68 meters
Resolution: 1 cm


MRX Information (0x0013)

Multi-Receiver Extension data

Structure

typedef struct __attribute__((packed)) {
    uint8_t status;      // Status bits
    uint8_t counter;     // Message counter
    int16_t yaw;         // Yaw angle [-180° to +180°]
    uint16_t distance;   // Distance in cm
} __uls_blitz_msg_rx_mrx;

Total Size: 6 bytes (2 bytes unused in 8-byte payload)

Field Descriptions

FieldTypeRangeDescription
statusuint8_t0-255Status flags (bit 5: MRX_OK)
counteruint8_t0-255Packet counter
yawint16_t-32768 to +32767Yaw angle scaled to ±180°
distanceuint16_t0-65535Distance in cm

Angular Conversion

float yaw_deg = (yaw * 180.0f) / 32767.0f;

Usage

MRX data is calculated from measurements of a secondary receiver, providing:

  • Relative yaw orientation
  • Distance between receivers
  • Enhanced positioning accuracy

DACS Information (0x0014)

Directional Angle Calculation System with continuous yaw tracking

Structure

typedef struct __attribute__((packed)) {
    uint8_t status;         // Status bits
    uint8_t counter;        // Message counter
    int16_t yaw;            // Yaw angle [-180° to +180°]
    uint16_t distance;      // Distance in cm
    int16_t yawContinuous;  // Continuous yaw (±32768°)
} __uls_blitz_msg_rx_dacs;

Total Size: 8 bytes

Field Descriptions

FieldTypeRangeDescription
statusuint8_t0-255Status flags
counteruint8_t0-255Packet counter
yawint16_t-32768 to +32767Wrapped yaw ±180°
distanceuint16_t0-65535Distance in cm
yawContinuousint16_t-32768 to +32767Unwrapped yaw ±32768°

Angular Conversion

Wrapped Yaw:

float yaw_deg = (yaw * 180.0f) / 32767.0f;  // -180 to +180°

Continuous Yaw:

float yaw_continuous_deg = yawContinuous;  // Direct degree value

Usage

DACS provides:

  • Standard wrapped yaw for heading
  • Continuous yaw for counting full rotations
  • Useful for applications requiring rotation tracking beyond ±180°

Example:

Rotation: 450° clockwise
yaw = 90° (wrapped to ±180° range)
yawContinuous = 450°

Ground IMU Measurement (0x0020)

Inertial Measurement Unit data from ground transmitter

Structure

typedef struct __attribute__((packed)) {
    uint8_t status;    // Status bits
    uint8_t counter;   // Message counter
    int16_t roll;      // Roll angle [-180° to +180°]
    int16_t pitch;     // Pitch angle [-180° to +180°]
    int16_t yaw;       // Yaw angle [-180° to +180°]
} __uls_blitz_msg_gimu_data;

Total Size: 8 bytes

Field Descriptions

FieldTypeRangeDescription
statusuint8_t0-255Status flags (bit 4: GU_IMU_OK)
counteruint8_t0-255Packet counter
rollint16_t-32768 to +32767Roll scaled to ±180°
pitchint16_t-32768 to +32767Pitch scaled to ±180°
yawint16_t-32768 to +32767Yaw scaled to ±180°

Angular Conversion

float roll_deg = (roll * 180.0f) / 32767.0f;
float pitch_deg = (pitch * 180.0f) / 32767.0f;
float yaw_deg = (yaw * 180.0f) / 32767.0f;

Precision: ~0.0055° per LSB

Orientation Convention

Euler Angles (Tait-Bryan convention):
  Roll:  Rotation about X-axis (forward)
  Pitch: Rotation about Y-axis (right)
  Yaw:   Rotation about Z-axis (up)

IMU Override (0x0030)

Override IMU data on ground transmitter

Structure

typedef struct __attribute__((packed)) {
    uint8_t control;   // Control bits
    uint8_t counter;   // Message counter
    int16_t roll;      // Override roll [-180° to +180°]
    int16_t pitch;     // Override pitch [-180° to +180°]
    int16_t yaw;       // Override yaw [-180° to +180°]
} __uls_blitz_msg_xx_txc_imu_override;

Total Size: 8 bytes

Field Descriptions

FieldTypeRangeDescription
controluint8_t0-255Control flags (see below)
counteruint8_t0-255Packet counter
rollint16_t-32768 to +32767Override roll value
pitchint16_t-32768 to +32767Override pitch value
yawint16_t-32768 to +32767Override yaw value

Control Bits

BitNameDescription
0SET_ROLLEnable roll override
1SET_PITCHEnable pitch override
2SET_YAWEnable yaw override
3-7ReservedMust be 0

Usage

// Override only yaw
msg.control = (1 << 2);  // SET_YAW
msg.yaw = (45.0f * 32767.0f) / 180.0f;  // 45 degrees
msg.roll = 0;    // Ignored (SET_ROLL not set)
msg.pitch = 0;   // Ignored (SET_PITCH not set)

Purpose:

  • External orientation source (e.g., motion capture, GNSS heading)
  • Calibration and testing
  • Compass-less operation

Magnetometer Override (0x0031)

Override magnetometer data on ground transmitter

Structure

typedef struct __attribute__((packed)) {
    uint8_t control;   // Control bits
    uint8_t counter;   // Message counter
    int16_t mx;        // Magnetic field X component
    int16_t my;        // Magnetic field Y component
    int16_t mz;        // Magnetic field Z component
} __uls_blitz_msg_xx_txc_mag_override;

Total Size: 8 bytes

Field Descriptions

FieldTypeRangeDescription
controluint8_t0-255Control flags (see below)
counteruint8_t0-255Packet counter
mxint16_t-32768 to +32767X magnetic field component
myint16_t-32768 to +32767Y magnetic field component
mzint16_t-32768 to +32767Z magnetic field component

Control Bits

BitNameDescription
0SET_OVERRIDEEnable magnetometer override
1-7ReservedMust be 0

Magnetic Field Conversion

float mx_norm = (mx * 1.0f) / 32767.0f;  // Normalized [-1.0, +1.0]
float my_norm = (my * 1.0f) / 32767.0f;
float mz_norm = (mz * 1.0f) / 32767.0f;

Purpose:

  • External magnetometer source
  • Magnetic interference compensation
  • Indoor operation with external compass

Status Bits

Common Status Flags

Most Blitz messages include a status byte with these flags:

BitFlag NameDescription
0CARRIER_OKIR carrier signal detected
1SQ_OKSignal quality acceptable
2POS_OKPosition successfully estimated
3VEL_OKVelocity successfully estimated
4GU_IMU_OKGround Unit IMU operational
5MRX_OKMRX message received from secondary receiver
6MRXDATA_OKMRX yaw and distance calculated successfully
7ReservedReserved for future use

Status Checking

bool check_measurement_valid(uint8_t status) {
    // Check minimum required flags
    if (!(status & (1 << 0))) return false;  // No carrier
    if (!(status & (1 << 1))) return false;  // Poor signal quality
    if (!(status & (1 << 2))) return false;  // No position
    return true;
}

bool has_velocity(uint8_t status) {
    return (status & (1 << 3)) != 0;
}

bool has_mrx_data(uint8_t status) {
    return ((status & (1 << 5)) != 0) && ((status & (1 << 6)) != 0);
}

Data Encoding

Integer Scaling

Angular Data (±180° range):

int16_t_value = (angle_degrees / 180.0) * 32767.0
angle_degrees = (int16_t_value / 32767.0) * 180.0

Position Data (cm):

int16_t_value = position_cm
position_m = int16_t_value * 0.01

Distance Data (cm):

uint16_t_value = distance_cm
distance_m = uint16_t_value * 0.01

Byte Order

All multi-byte fields use little-endian byte order

Example (int16_t = 0x1234):

Memory layout: [0x34, 0x12]
                 LSB   MSB

Packing

All structures use __attribute__((packed)) to ensure:

  • No padding bytes inserted by compiler
  • Exact memory layout as defined
  • Network transmission compatibility

Usage Examples

Sending Blitz Message

// Prepare raw measurement
__uls_blitz_msg_rx_raw_measurmet msg;

msg.status = calculate_status_bits();
msg.counter = packet_counter++;
msg.aX = (int16_t)((angle_x_deg / 180.0f) * 32767.0f);
msg.aY = (int16_t)((angle_y_deg / 180.0f) * 32767.0f);
msg.distance = (uint16_t)(distance_m * 100.0f);  // m to cm

// Send via interface
interface->ifSendBLITZ(
    ULS_BLITZ_MSG_ID_RX_RAW_MEASURMENT,
    (uint8_t*)&msg,
    sizeof(msg)
);

Receiving Blitz Message

// Set callback
interface->ifclbkBlitzReceived = &onBlitzReceived;

void onBlitzReceived(ULSBusInterface *iface) {
    uint16_t msg_id = iface->ifRxPacket->blitz.msg_id;
    uint8_t *data = iface->ifRxPacket->blitz.data;
    
    switch(msg_id) {
        case ULS_BLITZ_MSG_ID_RX_RAW_MEASURMENT: {
            __uls_blitz_msg_rx_raw_measurmet *msg =
                (__uls_blitz_msg_rx_raw_measurmet*)data;
            
            // Check status
            if (!(msg->status & 0x07)) break;  // Check flags 0,1,2
            
            // Extract data
            float ax = (msg->aX / 32767.0f) * 180.0f;
            float ay = (msg->aY / 32767.0f) * 180.0f;
            float dist = msg->distance * 0.01f;
            
            // Process measurement
            process_measurement(ax, ay, dist);
            break;
        }
        
        case ULS_BLITZ_MSG_ID_GIMU_MEASUREMENT: {
            __uls_blitz_msg_gimu_data *msg =
                (__uls_blitz_msg_gimu_data*)data;
            
            float roll = (msg->roll / 32767.0f) * 180.0f;
            float pitch = (msg->pitch / 32767.0f) * 180.0f;
            float yaw = (msg->yaw / 32767.0f) * 180.0f;
            
            update_orientation(roll, pitch, yaw);
            break;
        }
        
        // Handle other message types...
    }
}

IMU Override Example

// Override yaw angle from external source
void send_yaw_override(float yaw_deg) {
    __uls_blitz_msg_xx_txc_imu_override msg;
    
    msg.control = (1 << 2);  // Enable yaw override only
    msg.counter = counter++;
    msg.roll = 0;
    msg.pitch = 0;
    msg.yaw = (int16_t)((yaw_deg / 180.0f) * 32767.0f);
    
    interface->ifSendBLITZ(
        ULS_BLITZ_MSG_ID_XX_TXC_IMU_OVERRIDE,
        (uint8_t*)&msg,
        sizeof(msg)
    );
}

Performance Considerations

Update Rates

Typical Rates:

  • Raw measurements: 100-200 Hz
  • Position data: 100 Hz
  • IMU data: 100-200 Hz
  • MRX data: 50-100 Hz

Bandwidth Usage

Per Message:

  • UART (COBS mode): ~13 bytes (11 data + 2 overhead)
  • CAN: 1 frame (11 bytes in 8-byte frame + header)

Example Load (100 Hz, UART @ 115200 bps):

Bandwidth = 100 Hz × 13 bytes × 8 bits = 10.4 kbps
Utilization = 10.4 / 115.2 = 9%

Latency

End-to-end latency:

  • Sensor → Encoding: <1 ms
  • Transmission: 0.1-1 ms (depends on transport)
  • Reception → Callback: <1 ms
  • Total: 1-3 ms typical

Copyright © 2020-2026 UAVLAS <www.uavlas.com>
License: GNU Lesser General Public License v3.0+