SCOUT UAV
Ground control station for a search-and-rescue drone (UAV)
SCOUT is a capstone project sponsored by Lockheed Martin to design a fixed-wing Unmanned Aerial Vehicle (UAV) capable of autonomous search-and-rescue missions. I lead the software team, building the web-based ground control station (GCS) that operators use to plan missions, monitor live telemetry, review thermal video, and confirm person detections. All in one interface.
Problem
Search-and-rescue operators need to monitor flight telemetry, control the UAV's mission, and review thermal-camera detections simultaneously. Existing open-source GCS tools are either too low-level for non-technical operators or too coupled to a specific hardware stack. The goal was a custom operator-first interface designed around the SCOUT mission profile.
Architecture
The GCS is a React + TypeScript SPA, served via Vite, that talks to a FastAPI backend over WebSockets for live telemetry and a REST API for mission data. The backend connects to the autopilot (ArduPilot) over MAVLink using PyMAVLink, translating raw MAVLink messages into structured JSON events the frontend subscribes to. The map layer uses MapLibre GL for real-time vehicle track rendering and mission waypoint editing. Thermal video frames are streamed as MJPEG and overlaid in a secondary panel alongside the detection queue.
Engineering challenges
MAVLink is a binary protocol designed for embedded systems. Bridging it cleanly to a WebSocket API required careful message parsing and state reconciliation when packets arrive out of order or are dropped. The other hard problem was telemetry latency: at 10 Hz from the autopilot, the UI needs to update without blocking the main thread, so telemetry state lives outside React's render cycle and is pushed to components via a lightweight pub/sub layer.
Testing and CI
ArduPilot SITL (software-in-the-loop simulation) runs in CI alongside the backend, so integration tests can exercise the full MAVLink pipeline without physical hardware. The frontend is tested with Vitest and the backend with pytest; GitHub Actions runs both on every PR.