ULS-DeCoNet Blitz Messages Specification
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 ID | Name | Size | Description |
|---|---|---|---|
| 0x0010 | XCG1_RX_RAW_MEASURMENT | 8 bytes | Legacy raw measurement (±30°) |
| 0x0011 | RX_RAW_MEASURMENT | 8 bytes | Raw measurement (±180°) |
| 0x0012 | RX_POS_IN_TX_FRAME | 8 bytes | 3D position in TX frame |
| 0x0013 | RX_MRX | 6 bytes | Multi-receiver info |
| 0x0014 | RX_DACS | 8 bytes | DACS with continuous yaw |
| 0x0020 | GIMU_MEASUREMENT | 8 bytes | Ground IMU data |
| 0x0030 | XX_TXC_IMU_OVERRIDE | 8 bytes | IMU override command |
| 0x0031 | XX_TXC_MAG_OVERRIDE | 8 bytes | Magnetometer 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
| Field | Type | Range | Description |
|---|---|---|---|
| status | uint8_t | 0-255 | Status flags (see section 5) |
| d | uint8_t | 0-255 | Distance in 10 cm steps (0-25.5m) |
| aX | int16_t | -30000 to +30000 | Angle X proportional to ±30° |
| aY | int16_t | -30000 to +30000 | Angle Y proportional to ±30° |
| oF | int8_t | -128 to +127 | Forward offset in cm |
| oR | int8_t | -128 to +127 | Right 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
| Field | Type | Range | Description |
|---|---|---|---|
| status | uint8_t | 0-255 | Status flags |
| counter | uint8_t | 0-255 | Packet counter (wraps at 256) |
| aX | int16_t | -32768 to +32767 | Angle X scaled to ±180° |
| aY | int16_t | -32768 to +32767 | Angle Y scaled to ±180° |
| distance | uint16_t | 0-65535 | Distance 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
| Field | Type | Range | Description |
|---|---|---|---|
| status | uint8_t | 0-255 | Status flags |
| counter | uint8_t | 0-255 | Packet counter |
| posX | int16_t | -32768 to +32767 | X position in cm (±327.68m) |
| posY | int16_t | -32768 to +32767 | Y position in cm (±327.68m) |
| posZ | int16_t | -32768 to +32767 | Z 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
| Field | Type | Range | Description |
|---|---|---|---|
| status | uint8_t | 0-255 | Status flags (bit 5: MRX_OK) |
| counter | uint8_t | 0-255 | Packet counter |
| yaw | int16_t | -32768 to +32767 | Yaw angle scaled to ±180° |
| distance | uint16_t | 0-65535 | Distance 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
| Field | Type | Range | Description |
|---|---|---|---|
| status | uint8_t | 0-255 | Status flags |
| counter | uint8_t | 0-255 | Packet counter |
| yaw | int16_t | -32768 to +32767 | Wrapped yaw ±180° |
| distance | uint16_t | 0-65535 | Distance in cm |
| yawContinuous | int16_t | -32768 to +32767 | Unwrapped 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
| Field | Type | Range | Description |
|---|---|---|---|
| status | uint8_t | 0-255 | Status flags (bit 4: GU_IMU_OK) |
| counter | uint8_t | 0-255 | Packet counter |
| roll | int16_t | -32768 to +32767 | Roll scaled to ±180° |
| pitch | int16_t | -32768 to +32767 | Pitch scaled to ±180° |
| yaw | int16_t | -32768 to +32767 | Yaw 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
| Field | Type | Range | Description |
|---|---|---|---|
| control | uint8_t | 0-255 | Control flags (see below) |
| counter | uint8_t | 0-255 | Packet counter |
| roll | int16_t | -32768 to +32767 | Override roll value |
| pitch | int16_t | -32768 to +32767 | Override pitch value |
| yaw | int16_t | -32768 to +32767 | Override yaw value |
Control Bits
| Bit | Name | Description |
|---|---|---|
| 0 | SET_ROLL | Enable roll override |
| 1 | SET_PITCH | Enable pitch override |
| 2 | SET_YAW | Enable yaw override |
| 3-7 | Reserved | Must 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
| Field | Type | Range | Description |
|---|---|---|---|
| control | uint8_t | 0-255 | Control flags (see below) |
| counter | uint8_t | 0-255 | Packet counter |
| mx | int16_t | -32768 to +32767 | X magnetic field component |
| my | int16_t | -32768 to +32767 | Y magnetic field component |
| mz | int16_t | -32768 to +32767 | Z magnetic field component |
Control Bits
| Bit | Name | Description |
|---|---|---|
| 0 | SET_OVERRIDE | Enable magnetometer override |
| 1-7 | Reserved | Must 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:
| Bit | Flag Name | Description |
|---|---|---|
| 0 | CARRIER_OK | IR carrier signal detected |
| 1 | SQ_OK | Signal quality acceptable |
| 2 | POS_OK | Position successfully estimated |
| 3 | VEL_OK | Velocity successfully estimated |
| 4 | GU_IMU_OK | Ground Unit IMU operational |
| 5 | MRX_OK | MRX message received from secondary receiver |
| 6 | MRXDATA_OK | MRX yaw and distance calculated successfully |
| 7 | Reserved | Reserved 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+