A terminal-based ground station for MAVLink-speaking autonomous vehicles.
Connect to a real or simulated drone over UDP, watch live telemetry, send commands, and record flight logs, all from a single, keyboard-driven TUI. Mission upload and serial links are on the roadmap. Grabbing inspo from QGroundControl or Mission Planner, but stripped down, TUI-first, and hackable.
Ground stations like QGroundControl are powerful but heavy. mavlink-gs is the opposite, as
it's a fast, keyboard-driven cockpit that lives in your terminal, starts instantly, and is
small enough to still read and modify.
Full milestone breakdown in ROADMAP.md. The short version:
- v0.1 — It talks: connect to PX4 SITL over UDP, decode and print core telemetry.
- v0.5 — It shows: live FTXUI TUI with telemetry panels updating at ≥10 Hz.
- v0.8 — It commands: arm / disarm / takeoff / land / RTL / goto-waypoint from a
command palette, with
COMMAND_ACKhandling. - v1.0 — It flies missions: YAML mission upload/download, flight-log recording, and one differentiator feature (multi-vehicle, log playback, or an ASCII map view).
| Layer | Choice |
|---|---|
| Language | C++20 (targeting C++23 features where available) |
| Build | CMake (target-based, ≥3.25) + vcpkg manifest mode |
| MAVLink | mavlink/c_library_v2 (header-only, v2 only) |
| Async / I/O | standalone ASIO (coroutines) |
| TUI | FTXUI |
| CLI / config / logging | CLI11, yaml-cpp, spdlog |
| Testing / quality | Catch2 v3, clang-tidy, clang-format, ASan + UBSan |
The whole stack is developed against PX4 SITL (software-in-the-loop) — no hardware
required. The fastest way to get a simulated drone talking MAVLink on UDP 14550:
# One-time pull (~2 GB)
docker pull jonasvautherin/px4-gazebo-headless:latest
# Run — exposes MAVLink over UDP 14550
docker run --rm -it \
-p 14550:14550/udp \
-p 14556:14556/udp \
jonasvautherin/px4-gazebo-headless:latestYou'll see PX4 boot logs ending in INFO [commander] Ready for takeoff!. To sanity-check
the connection, point QGroundControl at it (auto-connects to
udp://127.0.0.1:14550) — a vehicle should appear near PX4's default home (Zurich), and
you should be able to arm → takeoff → land.
Note: PX4's boot log prints
MAVLink only on localhost (set MAV_0_BROADCAST=1 ...). This is harmless with the Docker command above — the-p 14550:14550/udpport forward lets a ground station on the host connect fine. No parameter change needed.
Validated against PX4 v1.18.0 (git-hash aed118e), Gazebo 8.14.0, x500 quadcopter.
Prerequisites (host tools):
- A C++20 compiler (Apple Clang ≥17, upstream Clang ≥17, or GCC ≥13)
- CMake ≥ 3.25 and Ninja
pkg-config— some vcpkg ports (e.g.asio) invoke it while building
On macOS (Homebrew):
brew install cmake ninja pkg-configvcpkg itself is vendored as a submodule, so no system-wide vcpkg install is needed.
One-time setup:
# Clone with submodules (vcpkg + the MAVLink headers)
git clone --recurse-submodules https://github.com/tjsook/mavlink-gs.git
cd mavlink-gs
# Already cloned without --recurse-submodules? Pull the submodules now:
git submodule update --init --recursive
# Bootstrap vcpkg — compiles the vcpkg tool from the vendored source, once
./external/vcpkg/bootstrap-vcpkg.sh -disableMetricsBuild, test, run:
cmake --preset dev # first run builds all deps from source (slow; cached after)
cmake --build --preset dev
ctest --preset dev # run the unit tests
./build/dev/mavlink-gs --connect udp://127.0.0.1:14550Licensed under the MIT License.