exploring-edge-perf
  1. ModalAI VOXL 2 Mini research notes
  • Research notebooks
  • Theoretical LLM TPS on IQ-9075, Jetson, and NVIDIA GPUs
  • 3D photo reconstruction / indoor navigation research notes
  • Autonomous indoor drone navigation / capture research notes
  • 04_ref_matrials.html
  • NVIDIA Isaac ecosystem research notes
  • ModalAI VOXL 2 Mini research notes
  • Flight compute and competing ecosystems
  • ModalAI module reference
  • The Pixhawk ecosystem
  • ROS, from zero
  • VIO and SLAM
  • Navigation and exploration
  • Drone platforms

On this page

  • Hardware at a glance
    • Mini vs full-size VOXL 2
    • The flight controller is a DSP core, not a chip
  • Cameras and sensors
    • ToF vs lidar
    • Two consequences for capture
  • I/O and connectors
    • Power and motors
    • Offboard sensors
  • The ecosystem around the board
    • Compute boards
    • Image sensors and the flex chain
    • ESCs and the missing PWM
    • Power, radios, breakouts
    • Finished vehicles and kits
    • What it costs to build
    • What the ecosystem implies
  • Software: VOXL SDK
    • Details worth keeping in mind
    • ROS and cross-development
  • What the source tree shows
  • Bridging the board to simulation
    • 1. PX4 HITL — documented, works today
    • 2. Simulated VIO into the real stack — also shipped
    • 3. Simulated imagery into the perception stack — custom
    • Recommended ladder
  • Running the stack on the host (software in the loop)
    • Expectation vs reality
    • The bridge, verified
    • Practical gotchas when reproducing this
    • Bugs worth reporting upstream
  • What the autonomy stack already does
  • Onboard AI compute, realistically
  • What is provided, and what is missing
    • Integration surface
  • Risks and caveats
  • References

ModalAI VOXL 2 Mini research notes

Scope: what the VOXL 2 Mini provides out of the box, what it cannot do, and where an indoor autonomous-capture stack has to attach.

Core take: the Mini is a 42 x 42 mm, 11 g board that is both the companion computer and the flight controller, and it already ships a working indoor autonomy stack:

  • visual-inertial odometry (VIO),
  • stereo and time-of-flight (ToF) depth,
  • truncated / Euclidean signed distance field (TSDF / ESDF) mapping,
  • rapidly-exploring random tree (RRT*) planning with trajectory optimization,
  • PX4 collision prevention.

What it does not ship is any notion of where to go next: no exploration policy, no next-best-view, no coverage or photo-quality metric. That gap is the subject of the GLEAM / Next-Best-Path (NBP) line of work, and it sits off-board.

Prices as of 2026-07:

  • $1,249.99 board only,
  • $1,349.99 with power module,
  • $1,449.99 with VOXL electronic speed controller (ESC) Mini,
  • product page, docs.

Assembled in USA, which is most of why the price looks the way it does — see the bill-of-materials estimate below.

Hardware at a glance

Item VOXL 2 Mini
Size / weight 42 x 42 mm, 11 g, 30.5 mm mount pattern
SoC Qualcomm QRB5165, 8 cores to 3.091 GHz
RAM / flash 8 GB LPDDR5 / 128 GB
GPU Adreno 650, 1024 ALUs
NPU Hexagon, ~15 TOPS
Cameras 4 concurrent MIPI-CSI2 lanes
Video 8K30 h.264/h.265 encode, up to 108 MP stills
IMU / baro 2x TDK ICM-42688-P / ICP-10111
Flight controller PX4 1.14 or ArduPilot 4.6+, on the sensor DSP
Power 3.8 VDC in, 0.5-8 W
Radio none onboard; WiFi / 5G / LTE / Microhard as add-ons

Terms: SoC = system on chip, ALU = arithmetic logic unit, NPU = neural processing unit, TOPS = tera-operations per second, MIPI-CSI2 = camera serial interface, IMU = inertial measurement unit, DSP = digital signal processor.

Mini vs full-size VOXL 2

The QRB5165 is the robotics variant of the Snapdragon 865; Qualcomm’s Robotics RB5 platform is the reference design it comes from. The flight controller runs on one of its DSP subsystems, not on a separate microcontroller — the next section unpacks that.

Differences vs the full-size VOXL 2:

  • 42 x 42 mm / 11 g vs 70 x 36 mm / 16 g.
  • 4 concurrent camera lanes vs 6.
  • 3.8 V input vs 5 V.
  • ArduPilot documented alongside PX4.

Everything else — SoC, RAM, flash, GPU, NPU, encode, IMUs — is identical. The Mini is not cut-down compute; the differences are mechanical and I/O.

The flight controller is a DSP core, not a chip

The QRB5165 is a heterogeneous SoC: eight ARM (Kryo 585) cores running Ubuntu, the Adreno GPU, a compute DSP (cDSP — the “NPU” in the spec table), and the SLPI (sensor low-power island) — a Hexagon DSP subsystem that phones use for always-on sensor fusion. ModalAI runs the entire flight controller there (their docs call it the sensors DSP, SDSP). PX4 executes under QuRT, Qualcomm’s real-time OS for Hexagon, with its own scheduler and memory space; the board’s IMUs and barometer are wired to SLPI-owned SPI/I2C buses, so the control loop never crosses into Linux. PX4 itself is deliberately split: everything flight-critical runs on the DSP, while its support tasks — logging, MAVLink processing — run as a companion process on the ARM cores.

What this buys and costs, versus a separate flight-controller MCU:

  • Real isolation, shared package. The DSP keeps stabilizing through Linux-side CPU load, service crashes, even a userspace lockup — the practical failure containment a separate STM32 gives. What it does not survive is what a separate chip would: whole-SoC events (power, thermal shutdown, kernel-triggered subsystem resets) take the autopilot down with the computer.
  • The bridge is muORB: PX4’s internal uORB pub/sub, extended across the DSP↔︎Linux boundary over Qualcomm’s FastRPC shared-memory transport. Linux-side services (voxl-px4 companion process, voxl-mavlink-server, and through it qVIO and the rest of the SDK) see the autopilot’s topics without a serial link — the same role a UART+MAVLink hop plays on a Pixhawk-style split stack, at shared-memory latency.
  • Toolchain lock-in. Code on the SLPI is built with Qualcomm’s proprietary Hexagon SDK, so voxl-px4 is ModalAI’s fork built in their docker environment — you cannot flash an upstream PX4 release, and the shipped version trails upstream (1.14 in SDK 1.6). ArduPilot took the same path but upstream: its QuRT HAL is mainlined, which is why current ArduPilot is documented on the Mini.
  • I/O follows the SoC. No timer-driven PWM pads — hence UART/serial ESCs only — and no SWD-style debug probe into the DSP: flight-side debugging is logs, the PX4 shell over adb, and muORB topic inspection.
  • History note: this replaced a real two-chip design — VOXL 1 paired with the STM32F7-based Flight Core (“VOXL Flight” when combined on one PCB). VOXL 2 moved the autopilot on-die and dropped the MCU.

Cameras and sensors

Concurrency caps on the Mini: 4 tracking, or 2 ToF, or 2 hires (high-resolution) sensors across the 4 camera ports, mixed via interposer boards M0076 / M0084 / M0135.

Role Sensor Shutter Modules
Tracking (VIO) OV7251, AR0144 global M0014, M0072, M0166, M0149
Stereo OV7251, OV9782 global M0015, M0073, M0113
Hires Sony IMX214/412/678/664 rolling M0024, M0025, M0107, M0161, M0143, M0186
ToF PMD IRS1645, IRS2975C - M0040, M0169, M0178
Thermal FLIR Lepton 3.5 / Boson - I2C + SPI adapter
Rangefinder VL53L1X / VL53L1CX - I2C

Every module above except M0143 has a datasheet page at docs.modalai.com/<part number>/; the interposers and flexes below follow the same pattern. The PCB catalog is the index, though it lags the per-board pages.

What each role is for:

  • Tracking: mono fisheye (~167 deg) — the VIO input.
  • Stereo: mono pairs — depth-from-stereo.
  • Hires: the photogrammetry path.
  • ToF: primary depth input to voxl-mapper.
  • Rangefinder: altitude only.

Buses: I2C = inter-integrated circuit, SPI = serial peripheral interface.

Supported image sensor configurations on the VOXL 2 Mini

ToF vs lidar

Same physics family, different engineering, different data product:

  • The PMD modules are indirect ToF flash cameras. A flood illuminator lights the whole scene and every pixel measures the phase shift of the modulated return, giving a dense but low-resolution depth image. Short range (a few metres indoors), weak in sunlight, poor on dark or specular surfaces, and prone to multipath error in corners.
  • Lidar normally means direct ToF: a pulsed laser timed against a single-photon detector, scanned or flash-illuminated. Sparse returns, but tens to hundreds of metres, sunlight-robust, cm-accurate.
  • The VL53L1X rangefinder is direct ToF as well — effectively a single-pixel lidar.

For indoor mapping the ToF camera is the better data product: dense depth, cheap, small. For large or sunlit spaces it degrades badly, and that is where lidar would be wanted — which the Mini does not natively support.

Two consequences for capture

  • Every high-resolution sensor is rolling shutter. Global shutter exists only on the low-resolution mono computer-vision (CV) cameras. For photogrammetry that means motion blur and rolling-shutter skew unless the vehicle flies slowly or stops to shoot at capture poses. A capture-policy constraint, not a software one.

  • Per camera, QRB5165 can configure only three image outputs at once. HAL3 is Android’s camera hardware abstraction layer: the interface between Qualcomm’s sensor/ISP stack and voxl-camera-server. We use it indirectly whenever a MIPI camera is used, but applications normally consume Modal Pipe Architecture (MPA) pipes rather than call HAL3 themselves. preview, small_video, large_video, and snapshot are ModalAI’s four camera-server profiles, not four stream types defined by HAL3:

    Profile Intended output
    preview Low-latency RAW8/NV12 frames for CV
    small_video Lower-resolution H.264/H.265 for FPV/RTSP
    large_video High-resolution H.264/H.265 for recording
    snapshot On-demand, ISP-processed JPEG

    A hires camera normally spends its three slots on small video, large video, and snapshots; adding an uncompressed CV preview requires disabling one. This is usually acceptable here because qVIO consumes preview frames from a separate tracking camera while the hires camera handles capture. Multiple programs can also subscribe to the same MPA output without consuming another HAL3 slot. The hard limitation is therefore four distinct native outputs from one sensor, not necessarily four downstream uses if an output can be shared or derived.

I/O and connectors

VOXL 2 Mini connector locations, top and bottom

Connector Function
J1 3.8 V DC power in + I2C battery monitoring (6 A inrush)
J2 5 V fan output, PWM controlled
J3 USB3 SuperSpeed, 900 mA VBUS
J4 serial debug console (debug kernel builds only)
J6 / J7 camera group 0 / 1: 2x 4-lane MIPI CSI, CCI, 8 power rails
J9 USB-C: ADB, OTG / host
J10 UART or SPI expansion (2 chip selects), 3.3 V
J19 2x UART + 2x I2C: RC receiver, ESC, GNSS, magnetometer

Terms: PWM = pulse-width modulation, CCI = camera control interface, ADB = Android Debug Bridge, OTG = USB on-the-go, UART = universal asynchronous receiver/transmitter, RC = radio control, GNSS = global navigation satellite system.

Power and motors

Power is the integration gotcha: the Mini wants 3.8 V, not 5 V. Two supported sources:

  • MDK-M0041-4-00 Power Module v3 — 2S-6S LiPo in on XT60, fixed 3.8 V out, two INA231 current monitors on I2C.
  • M0129 VOXL Mini 4-in-1 ESC — use the fixed-3.8 V M0129-63 (current 2S-6S hardware), sold as MDK-M0129-63-00 without accessory cables or -01 with them. It reports battery telemetry over UART on J19 instead.

M0041 is the correct board-family number, not M00041. ModalAI’s Mini guide shortens the required variant to MDK-M0041-4; the full current orderable SKU is MDK-M0041-4-00. The generic Power Module v3 datasheet is stale: its part-number table lists only older 5 V assemblies, while the Mini guide and store listing confirm this 3.8 V variant.

There is also no PWM output for motors: the QRB5165 has none, so ESCs talk UART, or you add the VOXL 2 IO board. See the ecosystem section below.

Offboard sensors

Documented on the Mini:

  • GNSS — UART on J19 (SSC_QUP6).
  • Magnetometer — I2C on J19 (SSC_QUP0).
  • Power monitoring — I2C on J1.
  • Rangefinder — I2C.

Notably no documented UART lidar support. A spinning or solid-state lidar would mean USB3 or a custom UART bring-up, not a supported path.

The ecosystem around the board

The Mini is one stock-keeping unit in a vertically integrated catalogue. ModalAI sells the compute, the sensors, the flexes that connect them, the ESCs, the power modules, the radios, and finished drones — and the software assumes their parts. Buying a bare board is rarely what you actually want.

VOXL 2 Mini board held in a hand

Compute boards

Board What it is
M0054 / M0154 VOXL 2, full size, 6 camera lanes, from $1,299.99
M0104 VOXL 2 Mini, 4 camera lanes, from $1,249.99
M0204 VOXL 2 Mini refresh (no doc page yet)
M0087 Flight Core v2 — standalone STM32 autopilot, no compute
M0006 / M0019 VOXL 1 and VOXL Flight, previous generation

SDK 1.6 also lists MVX-* boards (MM0204-1, M0205-1, M0206-1) and QCS6490 support as supported platforms — the next hardware generation is already in the tree.

Image sensors and the flex chain

ModalAI image sensor module family

A sensor never plugs straight into the board. The chain is sensor module -> flex cable -> interposer -> J6/J7:

  • Interposers: M0076 (DF40C to AXT), M0084 (Y-AXT, two sensors per port), M0135 (dual image sensor adapter), M0195 (Mini / Stinger).
  • Thermal adapters: M0187 (Lepton), M0153 (Boson).
  • ToF adapters: M0172, M0178 (high power), M0189 (Mini-specific).
  • Extension flexes in fixed lengths (M0036, M0074), stereo flexes with fixed baselines (M0010, M0039).

The mechanical layout of a build is largely decided by which flexes exist. Custom baselines or camera placements mean custom flex, not just a config file.

Full part-number lookup with weights and datasheet links: ModalAI module reference.

ESCs and the missing PWM

The QRB5165 has no PWM output. This shapes every build:

  • UART ESCs are the native path: M0129 (Mini 4-in-1, pairs with the Mini over J19), M0049 / M0117 / M0134 (4-in-1, up to 32 A), M0138 (FPV 4-in-1). See the Mini ESC configs.
  • For PWM ESCs you add the VOXL 2 IO board, which speaks the PX4IO protocol — and therefore does not support DShot.
  • The M0129 also feeds the Mini its 3.8 V and reports battery telemetry over the same UART.

VOXL 2 Mini connected to the M0129 Mini 4-in-1 ESC

Power, radios, breakouts

  • Power modules: M0041 family — the Mini needs the 3.8 V MDK-M0041-4-00, not a 5 V -1 / -5 variant.
  • Cellular: M0130 LTE add-on with I/O breakout and USB hub (from $249.99), M0067 / M0090 5G carriers.
  • Mesh/datalink: M0048 / M0059 Microhard ($199.99), Doodle Labs options.
  • WiFi: M0136 modules, M0141 WiFi add-on with I/O.
  • Video transmit: M0185 dual-band VTX; MSP DisplayPort OSD works with third-party HDZero / Walksnail units.
  • Debug and expansion: M0017 / M0078 USB debug, M0125 / M0151 USB3-UART expansion (from $49.99), M0062 and M0144 breakouts, M0022 PWM breakout.

Full part-number lookup — 85 boards, weights, and verified datasheet links, plus which ones the official catalog is missing — is in ModalAI module reference.

Full part list: the PCB catalog and the add-ons store page.

Finished vehicles and kits

Product Notes
Starling 2 220 mm, 280 g, >40 min flight, from $2,949.99
Starling 2 Max 322 mm, 500 g takeoff + 500 g payload, 55+ min, from $3,199.99
Sentinel ModalAI’s reference drone; also sold as flight deck or bare PCB
VOXL 2 Flight Deck pre-assembled, calibrated compute + sensor kit
MDK-M0104-1-C4 / -C6 Mini sensor development kits
D0013 Mini reference architecture

Sensor fits, for reference:

  • Starling 2: 3x AR0144 tracking + 1x IMX412 hires.
  • Starling 2 Max: 2x AR0144 + 2x IMX412, optional FLIR Lepton, up to $5,799.99 fully equipped.
  • MDK-M0104-1-C4: tracking + hires. MDK-M0104-1-C6: ToF + hires + tracking.
  • D0013: Mini + M0129 ESC + IMX664 + 2x AR0144 + Lepton + ELRS receiver.

D0013 reference build wiring diagram

Note the Starlings carry the full VOXL 2, not the Mini. There is no ModalAI turnkey drone built on the Mini, so any Mini-based vehicle is an integration job.

What it costs to build

Nobody publishes QRB5165 pricing, so the following is inference from teardown-era Snapdragon 865 numbers and distributor kit prices — call it +/-40%. Short version: the Mini plausibly costs ~$350-575 to manufacture, so $1,249.99 is roughly 2.5-3.5x cost, 60-70% gross margin. Normal for niche US-assembled robotics hardware, and most of the price is not on the bill of materials.

Bill-of-materials estimate, anchors, and what the margin buys

Estimated unit cost at ModalAI volume (low thousands per year):

Item Est. unit cost
QRB5165 SoC $120-180
8 GB LPDDR5 $45-70
128 GB UFS $25-40
PMICs + power tree $30-50
2x ICM-42688-P + ICP-10111 $15-25
Passives, crystals, inductors $20-35
Connectors (2x DF40C-60, USB-C, 4x JST) $15-25
PCB (42 x 42 mm, ~12-layer HDI, stacked microvias) $25-50
Shields, thermal, mech $5-10
SMT assembly, test, IMU/baro calibration, yield $50-90
Total ~$350-575, midpoint ~$450

At 10k+/year this would fall to roughly $280-350.

Anchors behind the range:

  • Snapdragon 865 was ~$85 die-only and ~$150 packaged at phone volumes in 2020. QRB5165 is the industrial SKU with 10+ year longevity at a fraction of the volume, so a premium over $85 is expected.
  • Thundercomm’s RB5 Core Kit — QRB5165 SOM (8 GB / 128 GB) plus a full carrier board — retails $795 at qty 1, $764 at 100+. A finished product with margin at $795 caps how expensive the silicon can plausibly be.
  • Memory is abnormally expensive in 2026: LPDDR5X contract prices rose ~90% quarter-on-quarter in Q1, so the memory lines are maybe $40 above their 2024 level.

What the margin actually buys:

  • US assembly in small runs, to defense-procurement standards — a trusted supply chain costs real money.
  • The software: VOXL SDK, the PX4-on-DSP port, camera and ISP bring-up. That engineering is amortized over a few thousand boards a year and dwarfs the silicon.
  • Qualcomm licensee access — ModalAI builds the sensor-DSP images. That is the moat, and it is not on the BOM.
  • Long support life, export paperwork, reseller margin.

What the ecosystem implies

  • Buy a configured kit, not a bare board. The catalogue is the real product; a board on its own needs an airframe, ESC, flexes, sensors, and a radio before it does anything.
  • Sensor choice is catalogue-bounded. Anything outside the list means camera driver work against a Qualcomm ISP on a 4.19 kernel — expensive, and exactly the kind of task that consumes a research sprint on its own.
  • The lock-in is real but honest. PX4, ArduPilot, ROS 2, and MAVLink are all upstream open standards, so the autonomy work is portable even if the hardware is not.
  • Volume pricing exists but will not halve it. For a deployment that needs compute under ~$500 per vehicle, this platform is the wrong shape — but the obvious alternative got worse in July 2026: NVIDIA raised Jetson prices by 33-101% (Orin Nano Super devkit $249 -> $399, AGX Orin 32 GB module $899 -> $1,799) on memory cost pressure, so a Jetson plus a separate flight controller no longer undercuts an integrated VOXL by much once the FMU, carrier and wiring are counted.
  • For a demonstration, the cheapest credible path is a Starling 2 — same SDK, flying, no integration — with the Mini reserved for a later size- or weight-driven build.

Software: VOXL SDK

Current release SDK 1.6.3 (2026-02-06), system image 1.8.06, Ubuntu 18.04 / kernel 4.19 (the store page says “Debian Buster” instead — ModalAI’s own materials disagree; the SDK build targets are qrb5165 = Ubuntu 18.04 and qrb5165-2 = Ubuntu 20.04). Services talk over ModalAI’s Modal Pipe Architecture (MPA) — named pipes under /run/mpa/. Source is on GitLab — but see the licensing note below: it is source-available, not open source.

Service Does
voxl-camera-server HAL3 access to the Qualcomm ISP, OpenMAX encode
voxl-qvio-server MPA wrapper around Qualcomm mvVISLAM: fisheye + IMU -> 6-DoF pose
voxl-open-vins-server Open-VINS, the open alternative to qVIO
voxl-dfs-server depth from stereo: disparity + point cloud pipes
voxl-mapper voxblox TSDF -> ESDF, RRT*, loco trajectory, mesh export
voxl-vision-hub VIO -> PX4 bridge, MAVLink, VOA, AprilTag, offboard modes
voxl-tflite-server LiteRT inference on CPU / GPU / NNAPI / NPU delegates
voxl-portal web UI: video, 2D costmap, 3D mesh, planning overlays
voxl-streamer RTSP video out
voxl-logger / voxl-replay record and replay MPA pipes
voxl-mavlink-server MAVLink routing to autopilot and ground station
voxl-tag-detector AprilTag detection
voxl-lepton-server, voxl-rangefinder-server thermal, rangefinder drivers

Terms: ISP = image signal processor, 6-DoF = six degrees of freedom, VOA = visual obstacle avoidance (PX4 collision prevention), LiteRT = formerly TensorFlow Lite, NNAPI = Android neural networks API, RTSP = real-time streaming protocol.

Details worth keeping in mind

  • voxl-qvio-server is an open MPA wrapper; the VIO itself is Qualcomm’s proprietary libmvVISLAM from the MV SDK. How it is fed and read is open to change; how it estimates is not.
  • voxl-mapper is beta; needs qVIO + vision-hub; ToF input by default.
  • voxl-camera-server does NV12/RAW8 preview, h264/h265, JPG snapshot, with either ISP or mean-sample-value (MSV) auto-exposure.
  • voxl-tflite-server ships YOLOv5, MobileNet-SSD, DeepLabV3, MoveNet, FastDepth.
  • voxl-vision-hub opens MAVLink UDP ports for MAVROS/MAVSDK — the entry point for an off-board planner.

ROS and cross-development

ROS (Robot Operating System) support:

  • ROS 2 Foxy as native Debian packages (voxl-ros2-foxy, on disk since SDK 1.1), see the install guide.
  • voxl-mpa-to-ros2 bridges images, IMU, point clouds, VIO pose.
  • Anything newer than Foxy runs in Docker.
  • The bridge only publishes topics that have subscribers.

Cross-development uses the voxl-cross Docker image; targets are qrb5165 (Ubuntu 18.04) and qrb5165-2 (Ubuntu 20.04). CPU, OpenCL GPU, and Hexagon SDK DSP paths are all available.

What the source tree shows

The SDK was cloned locally under voxl/ (40 repos, shallow, 2026-07-31; commit manifest in voxl/README.md). Reading it corrects several things the marketing pages imply.

Licensing is source-available, not open source. 28 of 33 LICENSE files are BSD-3 with a fourth clause: “The Software is used solely in conjunction with devices provided by ModalAI Inc.” Exceptions: libmodal-pipe and libmodal-json are LGPL-3.0, voxl-voxblox keeps ETH-ASL’s BSD, voxl-open-vins-server is an Open-VINS redistribution. Practical effect: the code can be read, patched and extended for a ModalAI-based product, but not lifted onto other hardware.

voxl-qvio-server is a thin wrapper, not the algorithm. Its README: “MPA service for Qualcomm MV SDK VIO (MVVISLAM)”. The estimator is Qualcomm’s libmvVISLAM; the repo is the pipe plumbing, config, and quality reporting. A quirk worth knowing: on the 18.04 image the MV SDK is 32-bit only, so this is the only 32-bit package on the platform — the 20.04 (qrb5165-2) build is 64-bit.

voxl-mapper vendors the ETH-ASL planning stack. Under server/ sit loco_planner, mav_local_planner, mav_path_smoothing, mav_planning_common, mav_trajectory_generation, voxblox_planning_common — i.e. mav_voxblox_planning de-ROSed onto MPA. Familiar research code, which also means its known limits (2.5D-ish assumptions, replanning cost) are inherited wholesale.

voxl-vision-hub has more offboard modes than the docs advertise. Source files include offboard_figure_eight, offboard_follow_tag, offboard_trajectory, offboard_wps (waypoints), offboard_backtrack (retrace the flown path), plus voa_manager, obs_pc_filter, pose_filter, fixed_pose_input, horizon_cal. Waypoint mode is likely a simpler integration target for an external planner than trajectory mode.

Tooling worth knowing about early. voxl-mpa-tools ships voxl-inspect-* for every pipe type (cam, imu, vio, pose, points, tof, gps, mavlink, detections) — that is the debugging surface. voxl-logger records and replays MPA data and includes voxl-logger-to-rosbag, so real flight data can be pulled into ROS-side tooling.

SDK 1.7 is in progress: voxl-suite on dev reads version 1.7.0, ahead of the 1.6.3 release the docs describe.

Bridging the board to simulation

Three separate seams, in increasing order of custom work.

1. PX4 HITL — documented, works today

voxl-px4-hitl is a shipped target (voxl-px4/make_package.sh installs voxl-px4-hitl, voxl-px4-hitl-start, and a HITL parameter config). The host runs Gazebo Classic — in ModalAI’s voxl-gazebo-docker image, since Gazebo Classic has no Ubuntu 22.04 build — sends HIL_SENSOR / HIL_GPS over an FTDI serial link, and PX4 on the sensor DSP returns actuator commands. Real RC still works.

Setup notes from the docs and the community write-up: SDK >= 1.1.2, systemctl disable voxl-px4, disable voxl-qvio-server (real VIO fights the simulated sensors), drop the FTDI latency_timer to 1, start Gazebo before QGroundControl. The docs wire it to J18, which is a VOXL 2 connector — on the Mini that has to move to a J10/J19 UART, so verify before ordering cables.

2. Simulated VIO into the real stack — also shipped

The useful find in the source tree. voxl-hitl-vio-server listens for MAVLink ODOMETRY messages on UDP port 14560, converts them into a vio_data_t, and publishes them on the qvio pipe that voxl-vision-hub already consumes — pose, quaternion, linear and angular velocity, covariances, and a quality field. voxl-hitl-rangefinder-server does the same for height.

The README says “from a gazebo instance”, but nothing in the code is Gazebo-specific: any simulator that can emit MAVLink ODOMETRY over UDP can drive the onboard autonomy stack, and Pegasus already speaks MAVLink. So Isaac Sim can feed pose to the real board with no new protocol — an Isaac-side publisher plus a config file, not a porting project.

3. Simulated imagery into the perception stack — custom

Neither of the above exercises cameras, qVIO, DFS, or voxl-mapper’s depth input. Doing that means publishing frames into MPA ourselves. The camera interface is documented and extensible — camera_image_metadata_t plus raw bytes, a JSON info file for discovery — and voxl-camera-server, voxl-lepton-server, and voxl-uvc-server are all implementations of it, so a “sim camera server” is the intended shape.

Verify before committing: whether qVIO’s IMU arrives over MPA or straight from the DSP; timestamp discipline (metadata wants apps-proc CLOCK_MONOTONIC at exposure start, so sim frames must be stamped in the board’s clock); and matching intrinsics, distortion, and exposure metadata to a real module, otherwise the VIO tuning is meaningless. Bandwidth is a non-issue for tracking cameras (640x480 mono at 30 Hz is about 9 MB/s); 4K hires would need encoding.

Cheaper substitute: voxl-logger records MPA pipes on a real flight and voxl-replay plays them back on the bench, with voxl-logger-to-rosbag feeding ROS-side tooling. Real data, no bridge to write.

Recommended ladder

  • First: Isaac/Pegasus + PX4 SITL, planner on MAVSDK/MAVROS. The interface is identical to the real board, so this already is the bridge that matters.
  • Once hardware is in hand: HITL with Gazebo Classic exactly as documented, to establish that offboard commands drive the real flight stack. Then swap in Isaac as the odometry source through voxl-hitl-vio-server — cheap, and it puts simulated scenes in front of the real voxl-mapper / VOA / PX4 loop.
  • Only if perception-on-hardware becomes a milestone: MPA image injection. Budget a week; verify the qVIO IMU path first, because that single unknown decides feasibility.

One constraint applies throughout: HITL cannot use lockstep, so the simulator must hold real time. Isaac with RTX rendering and several cameras on a laptop GPU may not, and when it slips the flight dynamics are wrong rather than merely slow.

Running the stack on the host (software in the loop)

22 of the 40 cloned repos have a native platform in build.sh — “Build with the native gcc/g++ compilers for testing code locally on a desktop computer”. The chain below was built on Ubuntu 24.04 / gcc 13, without sudo, with /usr and /run read-only. Full log and reproduction steps in voxl/NATIVE_BUILD.md.

Component Result
libmodal-json, libmodal-pipe, librc-math, libmodal-journal, libvoxl-cutils build clean
MPA transport on x86 works — server/client exchanged live data
voxl-hitl-vio-server builds, runs, sim bridge verified end to end
voxl-mapper builds and runs (2 include-path patches, no source changes)
voxl-vision-hub builds and runs with a ~90-line libmodal-cv stub
voxl-mavlink-server builds with patch; upstream native target is broken
voxl-mpa-tools builds, 18 voxl-inspect-* binaries
voxl-logger needs libturbojpeg0-dev, libopencv-dev; source compiles clean

The autonomy layer runs on a desktop. No emulation, no cross-compiler, no board.

Expectation vs reality

Three expectations formed before the build turned out to be wrong, all in a useful direction.

libmodal-cv is a soft blocker, not a hard one. It is 8 functions, 1 struct, 1 macro, used from three files. Six are container plumbing; the only real computer vision is mcv_pc_downsample2, a voxel-grid decimator with depth/FOV/count/confidence filtering. A ~90-line pass-through stub gives a clean build of voxl-vision-hub, and the binary starts, brings up geometry, MAVLink IO, VIO manager, tag manager, VOA manager and IMU manager, and creates its MPA pipes. A faithful version is ~150 lines, half a day. Caveat: the ABI is inferred from call sites, so a stub is source-compatible only — every consumer must then be built from source, never mixed with a real ModalAI .deb.

libmodal-cv was not even the first thing to break. voxl_common_config.h failed earlier, and it is open source, sitting in voxl-mpa-tools/lib/.

The dependency cost, not the code, is what makes this a day of work. Nothing usable came from the system — no Eigen, Ceres, NLopt or OpenCV dev headers — so voxl-mapper required building Eigen 3.4, NLopt, Ceres 2.0 (~7 min) and voxblox first. Worse, ModalAI’s voxl-ceres-solver and voxl-nlopt repos contain no source at all, only submodule pointers to upstream GitHub. An offline host cannot build voxl-mapper.

The bridge, verified

voxl-hitl-vio-server built natively, and a purpose-written probe then sent mavlink_odometry_t{x=1.5, y=2.5, z=-3.5, q=identity, v=(.1,.2,.3), quality=77} to 127.0.0.1:14560 and read back vio_data_t{state=OK, quality=77, T=[1.50 2.50 -3.50], vel=[0.10 0.20 0.30]} on the qvio pipe. Isaac to MPA works today, on a laptop, with no board present.

Wiring facts that matter:

  • Port 14560 is hardcoded (receiver_udp.c:52). The config exposes receiver_port but nothing reads it.
  • It publishes qvio and qvio_extended, deliberately squatting the real qVIO pipe names — which is why mapper and vision-hub accept it transparently.
  • It ignores time_usec and stamps with local CLOCK_MONOTONIC, so sim time and board time have to be reconciled externally.
  • voxl-mapper subscribes to vvhub_body_wrt_fixed (its only hardcoded input) plus tof_pipe_0..3 and depth_pipe_0..3, and publishes plan_msgs whose control pipe accepts plan_home, plan_to, follow_path, stop_following. That control pipe is the attachment point for an external exploration planner. Depth inputs are fully config-driven, but note all four depth_pipe_*_enable default to 0 while tof_0_enable defaults to 1, and extrinsics are stored as a name resolved against extrinsics.conf, not an inline transform.

Practical gotchas when reproducing this

  • voxl-mavlink is a submodule wrapper; a --depth 1 clone leaves c_library_v2 empty and libmodal-pipe fails on mavlink.h.
  • gcc 13 needs -Wno-error= for address-of-packed-member, sign-compare and a stringop-overflow false positive. These work as env CFLAGS because their CMakeLists append ${CMAKE_C_FLAGS} last.
  • make install writes to /usr/include and /usr/bin directly. Copy into a prefix instead.
  • The MPA base dir is a compile-time #define (/run/mpa/) with no env override; either make /run/mpa writable or patch the define.
  • Raise the inotify limit before a multi-service session. libmodal-pipe calls inotify_init() per server pipe and exits on failure. With the default 128 instances mostly eaten by a desktop, services die seemingly at random — voxl-mavlink-server never survived. sudo sysctl -w fs.inotify.max_user_instances=1024.

Bugs worth reporting upstream

Found while getting this to run, all with file:line in voxl/NATIVE_BUILD.md:

  • voxl-hitl-vio-server assigns s.quality after the memcpy, so qvio_extended always publishes quality 0.
  • The same file fills velocity_covariance from pose_covariance and never reads odom.velocity_covariance.
  • Its “reject localhost” guard compares host-order against network-order, so it never fires on little-endian.
  • voxl-mavlink-server’s own build.sh native omits -DPLATFORM, so CMake hard-fails: their native target is broken out of the box.
  • voxl-vision-hub/utils/voxl-inspect-vfc never links -lm and only builds by luck on their toolchain.
  • voxl-mpa-tools uses ${OpenCV_LIBS} with no find_package(OpenCV) anywhere, and its build.sh returns exit 0 even when make fails.

What the autonomy stack already does

Chained together, the shipped stack is a complete indoor GPS-denied loop:

  1. Tracking fisheye + IMU -> voxl-qvio-server -> 6-DoF pose.
  2. ToF and/or stereo -> point clouds.
  3. voxl-mapper integrates them into a TSDF, derives an ESDF collision cost field (0.2 m voxels by default), plans with RRT* (1 s budget by default), and smooths with loco.
  4. voxl-vision-hub transforms the trajectory into the autopilot frame and feeds PX4 in trajectory offboard mode.
  5. VOA fuses stereo/ToF/rangefinder points into a buffer driving PX4 collision prevention, independent of the planner.

So the standing question of whether local navigation is already solved by the hardware vendor has, for indoor, slow, GPS-denied flight, a largely affirmative answer. Research effort is better spent on the exploration and capture layers than on re-deriving local navigation.

The honest caveats:

  • voxl-mapper is labelled beta and authorized for beta use only.
  • qVIO is a closed-source DSP blob that cannot be debugged or extended.
  • Everything is tuned for ModalAI’s own Starling airframes.

Onboard AI compute, realistically

15 TOPS sounds like a lot. The constraint is not throughput, it is the toolchain:

  • No CUDA. Nothing from the Isaac / PyTorch side runs on this board as-is. Anything learned must be exported to LiteRT with a GPU/NNAPI/NPU delegate, or converted for the Qualcomm Neural Processing SDK (SNPE). Invalid delegate choices silently fall back to CPU.
  • Custom models are not drop-in for voxl-tflite-server: each needs a C++ class implementing post_process() and worker().
  • Published VOXL 2 GPU-delegate numbers: MobileNetV1 ~125 fps, YOLOv5 ~36 fps. Comfortable for a detector alongside VIO; not a budget for a large policy network at high rate.

So a learned exploration policy of the GLEAM/NBP kind is portable to this hardware, but porting is real engineering: model conversion, quantization, a serving class, and a latency budget shared with VIO, mapping, and encode. For a research milestone the policy is better kept on a PC, streaming decisions to the drone.

What is provided, and what is missing

Provided out of the box — effectively the entire onboard column of an indoor autonomy system:

  • pose, depth, a volumetric map,
  • obstacle avoidance,
  • a web visualization surface,
  • log/replay and video streaming,
  • a flight controller that already consumes external trajectories.

Missing, and therefore the research surface — goal selection. voxl-mapper plans a path to a goal someone else chose. There is no:

  • frontier selection,
  • information gain,
  • next-best-view,
  • photo-coverage metric,
  • notion of whether the pictures taken were any good.

Integration surface

For a PC-side planner there are two clean options, neither needing a custom protocol:

  • MAVLink/MAVSDK over the UDP ports voxl-vision-hub opens, sending setpoints or trajectories.
  • ROS 2 topics via voxl-mpa-to-ros2 (pose, images, point clouds up; goals down), which matches how the simulation-side tooling is structured.

For the photogrammetry stream:

  • Hires stills go through the ISP as JPG snapshots, stored on the 128 GB onboard.
  • Offload over USB3 or an add-on modem — there is no built-in radio.
  • Rolling shutter plus the 3-stream cap means capture has to be deliberate — pose, stop, shoot — not continuous high-rate video harvesting.

Simulation link: QRB5165 is not an Isaac target. The bridge between Isaac Sim / Pegasus and this hardware is PX4 — software-in-the-loop (SITL) first, MAVLink message compatibility later.

Risks and caveats

  • Stack age. Ubuntu 18.04, kernel 4.19, ROS 2 Foxy (end of life 2023), PX4 1.14. Anything modern lives in Docker. Expect friction with current Python/CV packages.
  • Flight controller shares the SoC. Excellent for SWaP (size, weight and power) and latency, but a Linux-side fault and the autopilot are on the same die. J10/J19 support an external flight controller where that separation is required.
  • Closed components and a field-of-use licence. The VIO algorithm (libmvVISLAM) and the sensor DSP images are Qualcomm builds; if VIO misbehaves in a given environment the available responses are configuration and Open-VINS, not a fix. Separately, most SDK repos are BSD-3 plus a clause restricting use to ModalAI hardware — source-available, not open source, so the code cannot be lifted onto another board.
  • No documented UART lidar path on the Mini. If the sensor plan drifts toward lidar SLAM (simultaneous localization and mapping), bring-up needs verifying before committing.
  • Roadmap risk is the strongest argument against this board. VOXL 3 (QCS8550, 45 TOPS) is SBIR-funded development, not a product — modalai.com/products/voxl-3 404s. Meanwhile the signals point away from QRB5165: SDK 1.6 carries QCS6490 support and new MVX-* boards, the SDK 1.7 betas exist only for a QCS6490 next-gen board rather than voxl2/voxl2-mini, and a ModalAI engineer stated on their forum (17 Jul 2026) that “we are not going to be officially supporting Ubuntu2.0 Kernel on VOXL2, as we are working on enabling next gen hardware”. Forum-sourced, so confirm with sales — but if accurate, the Ubuntu 18.04 userland is where VOXL 2 stops, and a product roadmap should not assume otherwise.
  • Their own support has limits on the closed parts. In a February 2026 forum thread about violently unstable qVIO flight, a ModalAI engineer replied that “the underlying QVIO source code is not available” to them either. That is the practical meaning of the libmvVISLAM dependency.
  • Lead time is the practical killer. The product page states “Expected to ship within 60 business days from San Diego, CA” for the Mini (30 for the full VOXL 2). That is roughly three months. Any schedule that depends on having one of these boards in hand starts with an order placed up front.
  • Cost of hands-on work. $1.25-1.45k for a board that still needs an airframe, ESC, radio, and cameras. The Starling 2 / Starling 2 Max dev drones run the same SDK flying and are the cheaper path to validating the software, though they carry full VOXL 2 rather than the Mini.

References

Product and board:

  • VOXL 2 Mini product page
  • Docs overview
  • Feature matrix
  • Connectors
  • Power
  • Image sensors
  • Offboard sensors
  • D0013 architecture

Software:

  • VOXL SDK overview
  • SDK 1.6 release notes
  • voxl-camera-server
  • voxl-dfs-server
  • voxl-tflite-server
  • voxl-vision-hub
  • voxl-mapper source
  • ROS 2 on VOXL 2

Flight stack and accessories:

  • ArduPilot on VOXL 2
  • PX4 VOXL 2 page
  • Power Module v3 datasheet
  • ModalAI image sensor catalog