Skip to main content

Crate ados_positioning

Crate ados_positioning 

Source
Expand description

§ados-positioning

crates.io docs.rs license MSRV

Split a mixed UBX, NMEA and RTCM3 byte stream with resync, build u-blox VALSET commands and run an RTK base survey-in state machine.

A GNSS receiver interleaves several protocols on one serial or USB port, and a read can end in the middle of any of them. This crate buffers the bytes, hands back whole frames whose checksums hold, and skips garbage one byte at a time until it finds the next valid frame. On top of the splitter it decodes the common u-blox navigation messages and NMEA GGA/RMC, builds CFG-VALSET configuration commands, and drives an RTK base receiver through survey-in or a fixed position.

use ados_positioning::stream::{crc24q, ubx_frame, Frame, Splitter};

// A UBX NAV-DOP message with an 18-byte payload.
let ubx = ubx_frame(0x01, 0x04, &[0u8; 18]);

// An NMEA sentence: `$body*hh` where hh is the XOR of the body bytes.
let body = "GNGGA,123519,4807.038,N,01131.000,E,1,08,0.9,545.4,M,46.9,M,,";
let ck = body.bytes().fold(0u8, |a, c| a ^ c);
let nmea = format!("${body}*{ck:02X}\r\n");

// An RTCM3 frame: preamble, 10-bit length, payload, CRC-24Q. The payload
// starts with the 12-bit message number (1005 = 0x3ED).
let mut rtcm = vec![0xD3, 0x00, 0x02, 0x3E, 0xD0];
let crc = crc24q(&rtcm);
rtcm.extend_from_slice(&[(crc >> 16) as u8, (crc >> 8) as u8, crc as u8]);

// Interleave them with line noise, then feed the stream in small reads.
let mut bytes = vec![0x00, 0xFF, b'x'];
bytes.extend_from_slice(&ubx);
bytes.extend_from_slice(nmea.as_bytes());
bytes.extend_from_slice(&[0x13, 0x37]);
bytes.extend_from_slice(&rtcm);

let mut splitter = Splitter::new();
let frames: Vec<Frame> = bytes.chunks(5).flat_map(|c| splitter.push(c)).collect();

assert!(matches!(frames[0], Frame::Ubx { class: 0x01, id: 0x04, .. }));
assert!(matches!(&frames[1], Frame::Nmea(s) if s.starts_with("$GNGGA")));
assert_eq!(frames[2], Frame::Rtcm(rtcm));
assert!(splitter.garbage() > 0);

§Highlights

  • One splitter for UBX, NMEA 0183 and RTCM3: every frame is accepted only when its UBX Fletcher checksum, NMEA XOR checksum or RTCM3 CRC-24Q holds.
  • Bounded memory: the buffer is capped at 64 KiB, UBX payloads at 8 KiB and NMEA sentences at 120 bytes, so a stream that never forms a frame cannot grow without limit.
  • Pure state machines: the RTK base machine returns the bytes to write and takes the receiver’s reports as input, with no I/O of its own.
  • Unit tests cover chunked input at every split size, resync after corrupt frames, the VALSET key encoding and every base transition.
  • Two dependencies: serde for the serializable state types and tracing for the base failure event.

§How it works

The crate has six modules.

  • stream splits one receiver byte stream into Frames. Receivers interleave protocols on one port, and a read can end anywhere, so Splitter buffers across pushes. A frame is accepted only when its checksum holds; on a mismatch, or on bytes that start no known frame, one byte is dropped and the scan resumes. The dropped byte count is available as a garbage counter. It also exposes ubx_frame, ubx_checksum, crc24q and rtcm_msg_type for building and inspecting frames.
  • ubx decodes NAV-PVT, NAV-DOP, NAV-SVIN, NAV-RELPOSNED, TIM-TP, MON-VER and ACK payloads. Offsets follow the u-blox F9 interface description; every decoder checks the payload length first and returns None for a short or foreign payload.
  • nmea decodes GGA and RMC, the fallback when a receiver sends no UBX.
  • receiver keeps per-receiver navigation state fed by decoded frames and reports a solution (fix type, RTK state, position, accuracy) that goes stale after a fixed timeout.
  • valset builds UBX-CFG-VALSET commands. A key id carries its value size in bits 28..30 (1 = one bit stored in a byte, 2 = one byte, 3 = two, 4 = four, 5 = eight), and each item writes exactly that many little-endian bytes. Helpers enable the navigation outputs per port, start a survey-in, set a fixed base position and enable the RTCM3 base messages 1005, 1074, 1084, 1094, 1124 and 1230.
  • base is the RTK base state machine: off, then surveying, then fixed or failed. The machine returns the bytes to write to the receiver, and receiver reports (NAV-SVIN, ACK, MON-VER) advance it. Nothing is reported as progress until the receiver itself reports it, and a command the receiver does not confirm within a timeout fails the machine.

§Cargo features

FeatureDefaultWhat it enables
fixturesnoThe fixtures module: byte-exact receiver frames with correct checksums, for tests in downstream crates.

§Part of ADOS

Used in production by the ADOS Drone Agent, the onboard software of the ADOS software-defined drone platform. All ADOS crates · Docs · Discord

§Other ADOS crates

Platform (versioned with the ADOS Drone Agent)

CrateWhat it doesDocs
ados-protocolWire contracts of the ADOS Drone Agent: IPC framing, plugin RPC envelope, capability tokens and the vision frame bus.docs.rs
ados-sdkWrite Rust plugins for the ADOS Drone Agent: IPC client, plugin context, driver traits and lifecycle runner.docs.rs
ados-visionSingle-object visual tracker: Kalman motion model, appearance re-identification and YOLOv8 head decoding.docs.rs
ados-gpioDrive status buzzers and LEDs on Linux GPIO lines, with bounded software-PWM beep patterns.docs.rs
ados-hal-probeFind out what a board’s hardware can really do by probing it, plus bundled board profiles.docs.rs

Standalone

CrateWhat it doesDocs
ados-sensorhubSensor hub wire protocol: COBS framing, CRC-16 and fixed-layout IMU, baro, mag and GNSS packets. no_std.docs.rs
ados-offloadChoose where perception runs (onboard, offloaded or hybrid) and hold the vehicle when results go stale.docs.rs
ados-macpinStable MAC addresses for Linux network adapters that randomize theirs every boot.docs.rs
ados-loraLoRa transmit governor with cited regional band plans, duty cycle, dwell time and airtime accounting.docs.rs
ados-crsf-codecno_std CRSF / ExpressLRS codec for RC channels, telemetry and parameter frames.docs.rs
ados-rtcmRTCM3 framing, CRC-24Q and MAVLink GPS_RTCM_DATA fragmentation for RTK corrections.docs.rs
ados-clockMap remote clocks onto the host clock: least-squares and envelope fits, TIMESYNC and a chrony sink.docs.rs
ados-swarmSwarm control laws: separation, flocking, formations, CBBA task allocation and a point-mass simulator.docs.rs
ados-mavlink-tunnelSend large messages over MAVLink TUNNEL frames with chunking and bounded reassembly.docs.rs
ados-display-driverSmall-display output on Linux: SSD1306/SH1106 OLED over I2C, pixel packers and a framebuffer writer.docs.rs
ados-hmiFront-panel input: touchscreen calibration and gestures, button presses and rotary encoders.docs.rs

§ADOS repositories

RepoRuns onWhat it doesLink
ADOS Mission ControlBrowser, desktop (Electron)Ground control station: FC setup, mission planning, flight, 3D simulation, fleetADOSMissionControl
ADOS Drone AgentCompanion computer on the drone, or a ground nodeOnboard agent: MAVLink routing, HD video, long-range radio link, plugins, remote controlADOSDroneAgent
ADOS Android GCSAndroid phones and tabletsNative ground control app for agents on the LAN, direct flight controllers and the cloudADOSAndroidGCS
ADOS ExtensionsDrone Agent and Mission ControlFirst-party signed plugins, each with an agent half and a GCS halfADOSExtensions
ADOS MCPYour machineModel Context Protocol server that lets AI clients operate ADOS drones under scopes and a safety gateADOS-MCP
Documentationdocs.altnautica.comPublic docs for every ADOS productDocumentation

§License

Licensed under either of Apache License, Version 2.0 or MIT license at your option.

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this crate by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

Modules§

base
RTK base state machine: off → surveying → fixed | failed.
fixtures
Test fixtures: byte-exact receiver frames with correct checksums.
nmea
NMEA GGA / RMC decode, the fallback when a receiver sends no UBX.
receiver
Per-receiver navigation state, fed by decoded frames.
stream
Splits one receiver byte stream into UBX, NMEA and RTCM3 frames.
ubx
UBX message decode for the navigation, timing, acknowledgement and version messages a host typically consumes. Offsets follow the u-blox F9 interface description; every decoder checks the payload length first and returns None for a short or foreign payload.
valset
UBX-CFG-VALSET builders for the RTK base (u-blox F9 configuration keys).