MAVLab by Ascend Labs

Drone simulation, made approachable.

MAVLab is an Android-first drone systems simulation and digital-twin platform for learners who want to understand drones without first fighting ROS, Gazebo, ArduPilot/PX4 SITL, Docker, MAVProxy, Linux networking, and multi-window simulator setup.

Android-first Offline Digital Twin MAVLink v2 QGroundControl v1.5
Kotlin + Jetpack Compose SceneView 3D PID autopilot Flight logging
Flight Cockpit
1. Overview & Purpose

MAVLab exists to make drone simulation approachable. A learner who wants to understand drones is usually pushed straight into a hard professional stack — ROS/ROS 2, Gazebo/Webots/JSBSim, ArduPilot SITL / PX4 SITL, Docker, Python bridges, MAVProxy, UDP routing, and QGroundControl / Mission Planner configuration — long before they have understood the drone itself.

Product statement. MAVLab is a user-friendly phone-based drone simulation and digital-twin platform that helps students, operators, and builders learn drone systems without first mastering ROS, Gazebo, ArduPilot/PX4 SITL, Docker, MAVProxy, Linux networking, or simulator infrastructure. The active implementation lives in mavlab-android/.

Learning-order thesis

MAVLab does not compete with professional tools. It changes the learning order:

MAVLab first
  -> understand sensors, attitude, telemetry, flight modes, missions,
     failures, GCS workflows, and simulation state
  -> then graduate into ArduPilot SITL, PX4 SITL, Gazebo, ROS 2,
     Webots, JSBSim, hardware-in-the-loop, and real aircraft

What MAVLab abstracts away at the beginning

  • Installing ROS/Gazebo/SITL stacks and building ArduPilot/PX4 locally.
  • Running multiple terminals and bridges; debugging UDP endpoints before understanding MAVLink.
  • Needing a physical Pixhawk, frame, batteries, RC transmitter, GPS module, telemetry radio, or a safe test field for the first learning loop.

What MAVLab should still teach

  • Arm/disarm and flight modes; roll, pitch, yaw, altitude, velocity, GPS, and heading.
  • Sensor quality and failures; MAVLink telemetry and command flow.
  • QGroundControl connection and mission workflows; manual vs GCS mission control authority.
  • Autonomous mission upload/execution; wind, battery, payload, motor, GPS, compass, barometer, and link-loss failures.
  • 3D state visualization through the SIM tab; logs, reports, replay, and debrief.
MAVLab is not a replacement for ROS, Gazebo, ArduPilot, PX4, QGroundControl, or Mission Planner. MAVLab is the friendly simulation and learning layer before them.
2. Features (v1.5)
High-fidelity physics & autopilot
Fixed-rate quadcopter physics model with realistic PID attitude/altitude control.
Cockpit diagnostics
Live telemetry panels and rolling real-time graphs for altitude, roll, pitch, and yaw.
Multi-mode control
Interactive dual joysticks or phone accelerometer tilt control.
3D digital twin (SIM)
Live 3D rendering of position, attitude, and propeller speeds using a bundled GLB model.
Waypoint missions
Autonomous mission upload, track plotting, active-waypoint navigation, and Guided offsets.
MAVLink UDP server
Interoperable with QGroundControl: heartbeats, position/attitude streams, parameters, mission sync.
Failure labs
GPS loss/drift, compass loss, barometer offset, wind/gusts, motor failure, battery drain, payload mass, and link loss.
Flight logging
Session-based CSV telemetry and JSONL event timelines.
Markdown reports
Human-readable report.md debriefs: max altitude, battery use, failure timeline, safety notes.
Sharesheet export
Share/export flight files via standard Android Sharesheet intents.
First-launch onboarding
Educational walkthrough of features and digital-twin concepts; replayable from Ops.

Failure Labs scenarios

  • GPS Loss, GPS Drift, Compass Loss, and Barometer offset failures.
  • Wind speed, direction, and gust simulation.
  • Individual motor failure.
  • Unsafe battery drain and heavy payload masses.
  • Signal / link loss scenarios.
3. Build & Quick Start

Project facts

Application ID
com.ascend.mavlab
Version
1.5.0 (code 15)
SDK
minSdk 26 (Android 8.0) · compile/target 35
Toolchain
Kotlin · JDK 17 · Jetpack Compose · SceneView
APK output
MAVlab.apk · < 50 MB
Targets
Offline-first · Android 8.0+

Build, test & assemble the debug package

cd mavlab-android
GRADLE_USER_HOME="$PWD/.gradle" ./gradlew lintDebug testDebugUnitTest assembleDebug

Install to a connected device

adb install -r app/build/outputs/apk/debug/app-debug.apk

CI verifies lint, unit tests, and the debug build. Keep the debug APK under 50 MB.

4. QGroundControl Integration

Connecting QGC

  1. Split-screen (on-device): open MAVLab and QGC side-by-side. QGC discovers the vehicle on 127.0.0.1:14550.
  2. Local Wi-Fi (cross-device): put the phone and computer on the same Wi-Fi. MAVLab's UDP broadcast auto-links the vehicle to desktop QGC.
  3. Ensure the GCS System ID is 255 (default) and MAVLab is 1 to prevent system conflicts.

Test environments

Environment A — split-screen Android
  1. Enable developer options and split-screen/multi-window for all apps.
  2. Open MAVLab in the top half, QGroundControl in the bottom half.
  3. QGC listens on localhost port 14550 and discovers the MAVLab broadcast.
Environment B — cross-device local Wi-Fi
  1. Connect the Android device and a desktop running QGC to the same Wi-Fi router/hotspot.
  2. Ensure no firewall blocks UDP port 14550.
  3. Launch both; the UDP broadcast auto-registers the drone on desktop QGC.

Acceptance checklist

ItemActionVerification
DiscoveryOpen both appsQGC discovers MAVLab within 5 s; audio "Armed"/"Disarmed"; heartbeats turn green.
Arm/DisarmClick Arm/Disarm in QGCState updates immediately; SIM propellers start/stop.
Command ACKTakeoff / Land in QGCQGC receives ACK; drone moves vertically.
Mission uploadCreate waypoints, tap UploadAll items accepted; MISSION RESTORED printed; waypoints shown in Mission tab.
AUTO flightStart AUTO missionDrone navigates waypoints; MAVLab transmits current WP indices; QGC active line moves.
Link reconnectWi-Fi off 10 s, then onQGC reports link loss, reconnects, resumes telemetry.
StabilityRun 10 minutesTelemetry stable; memory constant; no ANRs or crashes.

Mission upload protocol flow

QGC MISSION_COUNT          -> MAVLab validates count, clears upload state
MAVLab MISSION_REQUEST_INT -> QGC MISSION_ITEM_INT (per sequence)
... repeat until all items received ...
MAVLab loads mission into MissionEngine / PhysicsSimulationEngine
MAVLab MISSION_ACK(ACCEPTED) -> Mission screen shows uploaded mission

Supported mission messages: MISSION_COUNT, MISSION_ITEM_INT, legacy MISSION_ITEM, MISSION_REQUEST_LIST, MISSION_REQUEST_INT, legacy MISSION_REQUEST, MISSION_CLEAR_ALL, MISSION_SET_CURRENT, MISSION_ACK, MISSION_CURRENT, and MISSION_ITEM_REACHED. Outbound telemetry also includes HEARTBEAT, ATTITUDE, GLOBAL_POSITION_INT, GPS_RAW_INT, VFR_HUD, SYS_STATUS, BATTERY_STATUS, COMMAND_ACK, and PARAM_VALUE. Inbound command handling covers SET_MODE, PARAM_REQUEST_LIST, PARAM_SET, COMMAND_LONG (arm/disarm, takeoff, land), and SET_MESSAGE_INTERVAL.

5. MAVLink & System IDs

MAVLab mimics ArduPilot by default and must not auto-renumber its vehicle system ID during a live link. A MAVLink system ID is part of vehicle identity; silently changing it while a GCS is connected leaves QGC with stale vehicle state (heartbeat visible, but mission upload behaves as if nothing is connected).

Recommended defaults

RoleSystem IDComponent IDNotes
MAVLab vehicle (autopilot)11Stable for the whole session; not derived from Android ID.
QGroundControl (GCS)255190QGC default GCS system ID.
Second MAVLab simulator2, 3For multiple simulated vehicles on one network.
Second GCS / companion254 / 190Companion must not pretend to be the vehicle.

Port mapping

EndpointPort
MAVLab local bind (receive from GCS)14551 (same-device) / 14556 legacy
QGC UDP listen (telemetry target)14550

On the first GCS heartbeat MAVLab records the sender IP/port and switches from broadcast to targeted unicast to reduce congestion. 0.0.0.0 is a bind address only — never a send target.

Guardrails & invariants

  • Self-heartbeat guard: inbound packets whose sender System ID equals the local vehicle System ID are ignored (prevents parsing looped-back broadcasts as GCS commands).
  • Heartbeat rate: HEARTBEAT (#0) broadcast at 1 Hz.
  • Connection warmup: gcsConnected = true only after ≥ 3 s of continuous GCS heartbeats.
  • Connection timeout: > 15 s without GCS heartbeats marks the link disconnected.
  • Failsafe reversion: losing the GCS link during AUTO reverts authority from GCS_MISSION to safety defaults (hold/RTL) to prevent flyaways.

Conflict handling — diagnose, do not self-change

If a colliding heartbeat arrives, MAVLab keeps its vehicle ID stable and surfaces a diagnostic warning instead of renumbering:

MAVLink identity conflict
MAVLab vehicle SYSID is 1.
QGC heartbeat is also using SYSID 1.
Set QGC MAVLink System ID to 255 and reconnect.
Do not change MAVLab vehicle SYSID unless running multiple simulated vehicles.

Inbound commands/mission messages are target-filtered: act only when target_system == vehicleSystemId or target_system == 0 (broadcast where semantics allow). PARAM downloads advertise a stable identity (SYSID_THISMAV=1, MAV_SYSID=1, SYSID_MYGCS=255, MAV_GCS_SYSID=255). Mission upload is blocked with a clear reason (MAV_MISSION_DENIED) while an identity conflict exists.

Recommended QGC setup for the user

1. Open QGroundControl settings -> MAVLink.
2. Set QGC MAVLink System ID to 255.
3. Keep MAVLab Vehicle System ID at 1.
4. Same-phone: QGC UDP 14550, MAVLab bind 14551.
5. Restart/reconnect the UDP link after changing the System ID.
6. Architecture

Runtime

  • SimulationService starts the shared simulation runtime (foreground service boundary).
  • AppRuntime exposes state, failures, missions, MAVLink status, and control commands to Compose screens.
  • PhysicsSimulationEngine runs the fixed-rate physics loop and owns autopilot, failures, mission progress, and battery state.

Single source of truth — state flow

Controller input or QGC command
  -> PhysicsSimulationEngine / MissionEngine / Autopilot / FailureInjector
  -> DroneState  (Kotlin StateFlow)
  -> Cockpit + Controller + Mission + SIM + Ops + FlightRecorder

State changes write directly to StateFlow structures inside the engine; AppRuntime exposes them as read-only streams; Compose screens observe them as read-only state, ensuring atomic, unidirectional data flow. The SIM is never animated directly from UI controls.

Control authority model

A priority-based single-writer authority model arbitrates between local input and remote GCS commands.

AuthorityMeaningCockpit UI
IDLENo active authority; drone disarmed or waiting.Control: Idle
CONTROLLERBuilt-in phone/manual controls drive the drone.Control: Controller
GCS_DIRECTQGC commands mode/arm/takeoff/land, no mission active.Control: GCS Direct
GCS_MISSIONUploaded QGC mission / AUTO drives the drone.Control: GCS Mission

Manual override: local inputs (disarm, manual land, guided offsets, joysticks) instantly preempt an active GCS_MISSION and shift back to CONTROLLER. Autopilot state writes must verify the active authority before writing to the state flow.

Core modules

core/mavlink
MAVLink endpoint, socket config, message builder/packets, mission upload session.
core/sensors
Phone sensor abstraction.
core/settings
Default settings structures.
simulation/engine
Engine + DroneState shape (attitude, motors, authority, MAVLink labels).
simulation/physics
6-DOF physics step.
simulation/autopilot
Flight controller + MissionEngine.
simulation/recording
FlightRecorder / FlightSession / FlightEvent.
feature/* & service
Compose surfaces and the foreground service.

Phase order

Phase 0 skeleton & guardrails → Phase 1 QGC/MAVLink proof → Phase 2 physics → Phase 3 controller & telemetry → Phase 4 3D visualization → Phase 5 failures & missions → Phase 6 polish & release.

7. Product Surfaces

MAVLab is organized into five primary tabs. Every tab answers one clean question. (Systems is deferred from MVP navigation; its failure/health capability is surfaced as a lightweight subset inside Controller.)

TabQuestion it answersPrimary mode
CockpitWhat is the drone doing now, and who is controlling it?Observe / command essentials
ControllerHow do I manually control or perturb the drone from the phone?Manual/local control
MissionWhat mission did QGC/demo load, and how is it progressing?GCS/autonomous operation
SIMHow is the drone reacting visually to the current simulation state?Visual digital twin
OpsIs MAVLink/QGC/app infrastructure healthy?Diagnostics / configuration

Cockpit

Live flight instrument and authority/status surface: control authority, flight mode, armed state, altitude AGL, ground/vertical speed, heading, battery percent/voltage, GPS fix & satellites, roll/pitch/yaw, throttle, attitude/altitude charts, MAVLink/GCS indicator, mission summary, last inbound message and last ACK, plus essential arm/takeoff/land buttons. It stays glanceable and does not own tuning, failure sliders, or 3D internals.

Controller

Local manual-control surface with an input-source selector (Phone sensors vs Custom input), calibration, tilt visualizer, throttle/roll/pitch/yaw controls, and an Advanced test inputs section (motor failure, GPS loss, wind preset, reset). Every Controller input routes through the simulation engine — never animating the model directly. It also hosts the Drone Sound Lab (see §9).

Mission

Inspect, start, clear, and monitor uploaded or demo missions: source, waypoint list, active waypoint, progress count, AUTO start, clear, load demo, re-upload replacement, and mission-protocol status (upload in progress/accepted/rejected, last sequence). GCS missions drive the same simulation state as manual flight.

SIM

The visual digital twin. Loads drone.glb, maps east/north/altitude to position and pitch/yaw/roll to rotation, animates propellers from motor state, and overlays a HUD (authority, mode, arm state, altitude, speed, battery, GPS, motor RPM bars, active waypoint, failure warnings). Default is a chase/inspection view: the drone stays readable near center while the world/path/camera communicate movement. Bench and world/map views are future modes.

Altitude instrument (SIM HUD spec)

A bottom-center circular aviation-style indicator drawn in Compose Canvas: dark bezel and tick ring, blue-sky/brown-ground artificial horizon with white horizon line, a fixed orange drone reference marker, an altitude scale, and readouts for ALT AGL, altitude (1 dp), and vertical speed (signed, 2 dp). It binds to DroneState only — never to 3D model transforms — and reacts to roll/pitch with a low-altitude warning band.

Ops

Technical operations & diagnostics: MAVLink UDP status, bind port, QGC destination, system/component IDs, last inbound message, last ACK, identity health, flight-log history/sharing, QGC troubleshooting, replay onboarding, and the release QA checklist.

3D model node contract

The app is model-agnostic as long as the GLB follows a stable node-name and pivot contract (e.g. Prop_FL/FR/RL/RR, Motor_FL/FR/RL/RR, optional PropBlur_*, Battery, GPSModule, PayloadMount, CameraGimbal). Missing optional nodes degrade gracefully and are reported in diagnostics rather than crashing. Performance targets: GLB < 5 MB where possible, < ~50k triangles.

8. Flight Logging & Reports

Arming creates a new session; disarming closes it, computes flight-envelope stats, and writes the report. Sessions are stored in app-private storage (no storage permission needed, works offline):

filesDir/mavlab/flights/{session_id}/
  manifest.json   # session start/end, duration, app/schema version, max alt/speed, battery used, event counts
  telemetry.csv   # ~5 Hz time-series telemetry
  events.jsonl    # one JSON object per line: timeline events
  mission.json    # snapshot of the uploaded/demo mission
  report.md       # human-readable markdown flight summary + safety review

Telemetry CSV (v1.5 schema highlights)

Includes session_id, control authority, armed state, flight mode, lat/lon, north/east position, altitude AGL, ground/vertical speed, headingDegrees, roll/pitch/yaw, throttle, battery percent/voltage, gpsFixType, satellite count, motor RPM (when available), activeWaypoint, and failureFlags.

Events (JSONL)

Sparse, human-readable: recording start/stop, arm/disarm, takeoff/land, mode changes, authority changes, mission upload lifecycle, waypoint reached, mission completion, failure injection/restoration, GCS connection, and battery/failsafe warnings.

Markdown report

Each session auto-generates report.md summarizing dates/durations and control authorities, mission parameters and waypoint success ratios, calculated flight envelopes (e.g. max altitude), chronological event timelines, and safety observations (e.g. "GPS was lost during flight — practice altitude-hold recovery..."). Reviewable in-app via the report viewer dialog.

Sharing

Android FileProvider packages session files and exposes them through standard Sharesheet intents — share the complete flight folder (CSV, manifest, events, mission, report) to email, drive, or chat.

MVP boundaries. No heavy cloud logging; no 100+ Hz UI-readable logs by default; structured telemetry/events over screenshots; logging never depends on QGC — built-in Controller sessions log too. Future: ZIP export, document-picker save, replay/debrief, dataset generation.
9. Audio / Sound System

MAVLab sound should evolve from a demo feature into a digital-twin training signal: make the drone feel alive, make RPM/throttle understandable by ear, make failures/payload audible, make the sound physically explainable, and eventually connect sound, telemetry, and AI debrief.

Architecture (kept replaceable)

DroneState + FailureState
  -> DroneSoundModel
  -> DroneSoundController
  -> Android audio backend
  -> Controller / SIM / Ops surfaces
Guardrail. Audio controls must never bypass the simulator unless explicitly in Sound test mode. Default path: Controller/QGC input → PhysicsSimulationEngine → DroneState.motors → DroneSoundModel → DroneSoundController. AppRuntime owns lifecycle, not a Compose screen.

Current target: V2 — Controller-tunable per-motor adaptive sound

Four SoundPool motor streams, each following its motor's RPM; per-motor mix and roughness sliders; sound test mode (audio-only while disarmed); low/critical battery cues. Controls live in Controller → Drone Sound Lab: sound enabled, master volume, per-motor mix, roughness, alerts, test mode, test RPM, reset. Optional assets: drone_motor_loop.wav, drone_motor_rough_loop.wav, drone_warning_beep.wav, drone_motor_sputter.wav.

Version roadmap

VersionMain techniqueMain valuePriority
V1One SoundPool loopBasic life/feedbackSkip/reference
V2Four SoundPool motor streamsPer-motor adaptive training soundBuild now
V3Hybrid SoundPool + AudioTrackProcedural RPM/BPF realismNext after V2
V4Spatial/environment modelDistance/flyby realismLater
V5Profiles + drillsOperator training productLater
V6Oboe + AI debriefProduction digital-twin audioLong-term

V3 acoustic model (blade-pass frequency)

BPF = blade_count * RPM / 60
2-blade prop @ 6000 RPM -> BPF = 200 Hz
harmonics: 200, 400, 600, 800 Hz ...

V3 keeps V2 loops but adds procedural layers (blade-pass harmonics, filtered prop-wash noise, motor/ESC whine, maneuver roughness, descent turbulence), with AudioTrack streaming for the procedural layer alongside SoundPool cues. Later versions add spatial audio (distance attenuation, panning, Doppler), drone acoustic profiles and training drills, and finally a native Oboe engine feeding AI debrief features.

10. Setup Guide

MAVLab's core learning loop runs from one Android-first app. You do not need ROS, Gazebo, ArduPilot SITL, PX4 SITL, Docker, Python bridges, cloud servers, or Linux networking knowledge to start.

Install

  1. Install MAVLab on an Android 8.0+ phone.
  2. Install QGroundControl if you want ground-station integration.
  3. Open MAVLab and complete onboarding.
  4. Use the guided surfaces: Cockpit, Controller, Mission, SIM, and Ops.

QGroundControl

For same-device use, run MAVLab and QGC in split-screen — MAVLab broadcasts MAVLink telemetry over UDP and QGC should discover it automatically. For desktop QGC, put phone and desktop on the same Wi-Fi; MAVLab broadcasts to common LAN destinations and UDP port 14550.

Build from source

cd mavlab-android
GRADLE_USER_HOME="$PWD/.gradle" ./gradlew lintDebug testDebugUnitTest assembleDebug
adb install -r app/build/outputs/apk/debug/app-debug.apk

Troubleshooting

  • If QGC does not connect, restart QGC and MAVLab, then confirm both are on the same network.
  • If the phone controller is unavailable, use the manual fallback sliders in the Controller tab.
  • If the 3D model does not render smoothly, keep using Cockpit/Mission — the simulator keeps running.
11. Teacher Guide

MAVLab is designed for classroom drone-systems lessons without physical aircraft and without making students begin with the hardest simulation stack. Learners understand drone behaviour first, then later graduate into ROS, Gazebo, ArduPilot/PX4 SITL, Webots, JSBSim, hardware-in-the-loop, and real aircraft.

Teaching philosophy

  1. Show the concept in MAVLab.
  2. Let students operate it from a phone.
  3. Connect the concept to QGroundControl/MAVLink.
  4. Only then explain how it appears in ArduPilot SITL, PX4 SITL, ROS, Gazebo, or real aircraft.

Recommended lesson order

1. Your First Flight · 2. Understanding MAVLink · 3. Phone as Controller · 4. Flight Modes Explained · 5. PID Control · 6. Sensors · 7. Failsafes.

Classroom format

  • Students run MAVLab on their phones; QGC in split-screen or on an instructor desktop.
  • Open each session with the problem MAVLab solves: the concepts can be learned first in one friendly app.
  • Use Failure Lab only after students understand normal flight.

Assessment ideas

  • Explain the difference between Stabilize, Alt Hold, Guided, Loiter, Auto, and RTL.
  • Identify which telemetry messages QGC uses for attitude, position, GPS, and battery.
  • Demonstrate GPS loss and explain why Auto/Loiter degrade.
  • Load a demo mission and describe waypoint progression.
  • Compare behavior with and without wind.
Safety framing. MAVLab is a simulator, but its lessons reinforce real-world safety: never arm near people, validate GPS before autonomous flight, and understand failsafes before relying on them.
12. Test Matrix & QA

v1.5 functional test matrix

IDScenarioExpected resultStatus
ONB-001First launchOnboarding explains Cockpit, Controller, SIM, Mission, Labs, and Ops.Passed
ONB-003Onboarding replay (Ops)Overlay re-opens, navigable/dismissible.Passed
DASH-001Idle telemetryDisconnected/disarmed; 0.0 m AGL; battery ~85%; flat charts.Passed
DASH-002Active telemetryPanels update at 5 Hz; charts plot real-time curves.Passed
CTRL-001Phone sensor toggleTilting shifts roll/pitch indicators; yaw trim slider works.Passed
CTRL-002Manual fallbackJoystick sliders control roll/pitch/yaw/throttle.Passed
SIM-001Drone animationGLB model pitches/rolls and spins props in sync with telemetry.Passed
SIM-002Overlay panelAltitude, vertical speed, battery match simulation values.Passed
MIS-001Demo mission load4-waypoint path loads; pins and trajectory shown.Passed
MIS-002QGC discoveryQGC detects MAVLab at 127.0.0.1:14550 or local IP; green heartbeats.Passed
MIS-003GCS mission uploadMission acknowledged; items sync to Mission tab.Passed
MIS-004AUTO executionDrone flies waypoints; current/reached updates sync to QGC.Passed
FAIL-002In-flight GPS LossGPS indicator red; Ops badge "1 scenario"; chip shows ● ACTIVE.Passed
FAIL-003Failure resetAll failures clear; badges hide; GPS healthy.Passed
LOG-001Log generationSession folder under mavlab/flights/ with all files.Passed
LOG-002View reportDialog shows markdown report (dates, duration, max alt, battery, timeline, safety).Passed
LOG-003Share sessionSharesheet contains all 5 flight files.Passed

Device coverage

Android 8 / 11 / 13 / 15 (devices or emulators), a low-end phone for sensor-fallback testing, and a Pixel-class phone for the performance baseline.

Protocol & lifecycle tests

  • Same-phone split-screen QGC; desktop QGC on the same Wi-Fi; Wi-Fi off/on; explicit QGC IP; subnet broadcast.
  • App background/restore; screen rotation; screen off/on; QGC restart while MAVLab runs; MAVLab restart while QGC runs; two MAVLab devices on one network.
  • 3D performance: Twin/SIM does not stutter on a low-cost phone; props don't cause excessive recomposition; SceneView samples latest state rather than collecting 100 Hz UI updates.

Release QA

Clean install + onboarding, demo mission + AUTO, inject GPS loss + verify Alt-Hold failsafe, confirm QGC telemetry, run one hour with no crash/ANR, and confirm the debug APK is under 50 MB.

13. Demo Script (7–10 min)

1 · Setup & onboarding (1 min)

Launch MAVLab. Open with the problem statement (beginners get pushed into ROS/Gazebo/SITL/Docker/ MAVProxy/networking; MAVLab is the friendly first layer). Walk the tabs — Cockpit, Controller, SIM, Mission, Ops — then tap Get Started.

2 · Pre-flight & local manual control (2 min)

Controller → Arm Vehicle → throttle up or Takeoff (alt hold at 10 m). Switch to SIM to watch takeoff/hover. Back in Controller, enable Phone Sensor Control and tilt the phone; show the SIM mimicking tilt; toggle sensors off to return to joysticks.

3 · QGC connection & AUTO mission (3 min)

Connect QGC (split-screen or desktop on the same Wi-Fi). Plan a short 3-waypoint mission in QGC and Upload; verify it appears in MAVLab's Mission tab. Trigger AUTO; watch the SIM fly, noting active-waypoint rings and the Mission index updating.

4 · In-flight failures & recovery (2 min)

Ops → Failure scenario catalog → GPS Loss (Jamming). Point out the ● ACTIVE badge; in Cockpit the GPS lock drops from 3D Fix to No Fix (red); observe QGC's GPS warning; execute a safe Land to recover.

5 · Post-flight review & export (2 min)

Disarm. In Ops, open the completed session → View Report; point out the timeline (armed → GPS failure → land) and the safety warning. Tap Share to show the Sharesheet ready to export the CSV and markdown files.

14. Release Notes & Checklist

What's new in v1.5

Flight logging & reporting
  • Rich telemetry CSV with session_id, gpsFixType, headingDegrees, activeWaypoint, failureFlags.
  • Auto-generated report.md: dates/durations, authorities, mission & waypoint ratios, flight envelopes, event timelines, and safety observations.
  • In-app report viewer dialog and Sharesheet export of the full flight folder.
Failure Lab upgrades
  • Collapsible scenario catalog; real-time active-failure count badges; per-chip ● ACTIVE tags.
Onboarding & diagnostics UI
  • Replayable first-launch onboarding; color-coded MAVLink/QGC link-state indicators.
Upgrade
./gradlew installDebug
# then open the app, follow onboarding, and use the Ops tab
# for flight logs, sharing, and the failure catalog

v1.5 phase acceptance (snapshot)

PhaseStatus
0 · Baseline audit & release definitionDone
1 · Navigation, product surface, copy polishDone
2 · Onboarding upgradeDone
3 · Cockpit UI polishDone
4 · SIM / 3D visualization upgradeDone
5 · Mission & QGC workflow polishPending real same-phone & desktop-Wi-Fi acceptance
6 · Failure-lab explanation polishDone
7 · Flight logging, export & reviewIn progress
8 · QA, demo, docs & packagingIn progress
Release gates. Real QGC same-phone and desktop-Wi-Fi acceptance, instructor-ready export/report, fresh passing build, and a phone-installable APK under 50 MB remain gates before v1.5 is fully signed off.
15. Contributing

MAVLab is an Android-first drone education simulator. Keep changes focused, testable, and useful for students learning flight systems.

Local setup

  1. Install Android Studio or the Android SDK command-line tools.
  2. Install Android SDK 35 and Java 17.
  3. Open mavlab-android/ as the Android project.
  4. Build & test:
    cd mavlab-android
    GRADLE_USER_HOME="$PWD/.gradle" ./gradlew lintDebug testDebugUnitTest assembleDebug

Guidelines

  • Keep simulator behavior deterministic where possible.
  • Add JVM tests for physics, controller mapping, mission, and failure logic.
  • Avoid network-dependent runtime features unless there is an offline fallback.
  • Keep the APK under 50 MB.
  • Do not commit local SDK paths, build outputs, or device-specific files.

Existing test anchors include MavlinkMessageBuilderTest, MissionUploadSessionTest, MissionEngineTest, ControlAuthorityTest, DroneModelControllerTest, MissionSnapshotCodecTest, MissionUploadStatusTest, and FlightRecorderTest. Licensed under MIT.

16. Asset Inventory

The repository ships three tracked binary assets. All are referenced here as local paths only.

PathTypeRole
drone.glbGLB 3D modelRuntime digital-twin model loaded by the SIM screen (node-name/pivot contract in §7).
assets/Mav logo.pngPNG imageMAVLab / Ascend Labs brand mark (shown in this document's header).
assets/Screenshot_20260620_184419.jpgJPEG imageApp interface screenshot (shown in the overview hero).
Mav logo.png MAVLab logo
Screenshot_20260620_184419.jpg App screenshot
drone.glb
[binary 3D model — not previewed]
drone.glb
This document loads no remote resources. Images are local with text-path fallbacks; the GLB model is referenced by path only and is not loaded here.