IMUD(8) System Manager's Manual IMUD(8)

Name

imud — a general-purpose IMU daemon

Think of it as gpsd for IMUs.

Synopsis

# install and run
sudo apt install imud imud-wmm-data
sudo systemctl enable --now imud

# or invoke it directly
imud [--config PATH] [--replay FILE] [--skip-bias-cal]
     [--no-nmea] [--no-highrate] [--foreground] [--version] [--help]

Description

imud owns the inertial sensor and does the hard real-time work exactly once: interrupt-driven sampling, calibration, sensor fusion, and precise hardware timestamps. It then publishes a clean attitude, heading, and motion estimate on standard interfaces that any number of programs can read at the same time.

Instead of every application re-implementing I²C drivers and a Kalman filter, you run one small daemon and consume its output. Like gpsd, it is meant to be boring, always-on infrastructure: start it, forget it, and point your software at the stream.

   IMU + magnetometer (I²C/SPI)                  consumers
            │                          ┌────────────────────────────┐
            ▼                          │  chartplotter / autopilot   │
   ┌─────────────────┐   NMEA 0183 ───▶│  ROS2 node                  │
   │      imud       │   binary UDP ──▶│  vision / stabilization     │
   │  drivers·MEKF·  │   AF_UNIX    ──▶│  gimbal / dish pointing     │
   │  timestamps     │                 │  loggers, dashboards, …     │
   └─────────────────┘                 └────────────────────────────┘

It is written in C and depends on the C standard library and, for the interrupt lines, libgpiod — nothing else, and it builds without libgpiod where that is absent. Linux is the packaged target; it also builds and runs on macOS. The license is MIT.

Features

Owns the sensor, once.
Drains the IMU FIFO on a hardware interrupt, applies calibration, and runs a quaternion MEKF at the full sample rate — so consumers get a fused estimate, not raw samples to process themselves.
Publishes to many consumers at once.
NMEA 0183 (UDP broadcast or a TCP listener that plotters simply connect to), a high-rate binary packet over UDP, and a loss-free stream of framed packets over a local AF_UNIX socket or TCP — so several programs share one IMU without contention.
Clean, well-defined outputs.
Quaternion, Euler angles, magnetic and true heading, rate of turn, heave, sea-state statistics (significant wave height and period, roll and pitch periods and amplitudes), compass-health diagnostics, and the attitude covariance — each carrying wall-clock, TAI, and per-sample hardware timestamps for correlation with cameras and other sensors.
Pluggable hardware.
A thin driver layer hides chip differences behind one interface, so swapping sensors is a config change rather than a rewrite. A sim driver runs the entire pipeline with no hardware at all.
A flight recorder built in.
The capture black box records every raw sensor sample to rotating files. imud --replay plays a capture back through the full pipeline and exits when it ends, and imud-cal measures your unit's actual noise (Allan variance) and gyro temperature drift from those same files.
An ABI-stable client library.
libimud decodes the binary stream for C programs and keeps working across daemon upgrades without recompiling. A single-file Python client ships too, and there is an Arduino/ESP32 client in its own repository.
Built to run unattended.
A hardened systemd unit with a watchdog, calibration tools, level-gated logging, and a status socket for health queries.

Use cases

imud is output-agnostic — the same daemon serves very different consumers.

Marine navigation
NMEA 0183 to chartplotters, autopilots, and Signal K, with true heading from the World Magnetic Model, heave, and live sea-state statistics. This is the most exercised use case today, and several fusion options are tuned for it. The imud-signalk bridge feeds Signal K natively over UDP or TCP where NMEA parsing falls short.
Robotics and ROS2
Attitude and rate of turn over the binary stream, at the sensor's full rate rather than a decimated NMEA cadence.
Drones and autopilots
The imud-mavlink bridge feeds MAVLink ATTITUDE messages to ArduPilot, PX4, or QGroundControl over UDP, serial, or TCP.
IoT, home automation, and dashboards
imud-mqtt publishes heading, attitude, and heave to an MQTT broker with Home Assistant auto-discovery; imud-influxdb writes line-protocol points to InfluxDB for Grafana; imud-prometheus serves a /metrics endpoint for Prometheus scraping and alerting.
Machine vision and camera stabilization
High-rate quaternion with hardware timestamps, for frame-accurate correlation between motion and imagery.
Gimbals, pan/tilt rigs, and antenna pointing
Low-latency attitude over the local stream socket or binary UDP.

Installation

Prebuilt, signed packages for Raspberry Pi OS and Debian — arm64 and armhf, suites bookworm and trixie — are in the imud apt repository. The armhf packages are built at the ARMv6 baseline, so they run on every Raspberry Pi that boots a 32-bit userland, the Pi 1 and Pi Zero/Zero W included. The suite is read from your machine, so these are the same four commands on either release:

# 1. Trust the signing key
curl -fsSL https://richcreations.github.io/imud/apt/KEY.gpg \
  | sudo gpg --dearmor -o /usr/share/keyrings/imud.gpg

# 2. Add the repository (suite detected from /etc/os-release)
sudo tee /etc/apt/sources.list.d/imud.sources >/dev/null <<EOF
Types: deb
URIs: https://richcreations.github.io/imud/apt
Suites: $(. /etc/os-release && echo "$VERSION_CODENAME")
Components: main
Signed-By: /usr/share/keyrings/imud.gpg
EOF

# 3. Install the daemon + World Magnetic Model data
sudo apt update && sudo apt install imud imud-wmm-data

# 4. Edit for your hardware, then start on boot
sudo nano /etc/imud/imud.conf
sudo systemctl enable --now imud

The optional bridges and the network monitor are separate packages — imud-signalk, imud-mqtt, imud-influxdb, imud-mavlink, imud-prometheus, imud-utils. See the apt repository page for the full package list.

On macOS, or on a Linux host with Homebrew, the tap carries one formula per package:

brew tap richcreations/imud
brew install richcreations/imud/imud richcreations/imud/imud-wmm-data
brew services start richcreations/imud/imud

On any other Linux host with I²C or SPI, build from source:

sudo apt update && sudo apt install -y build-essential libgpiod-dev
make
sudo make install
sudo make install-wmm-data   # World Magnetic Model (for true heading)
sudo nano /etc/imud/imud.conf
sudo systemctl enable --now imud

On macOS the build is ./configure && make — configure is required there, since it is what picks the backends a Mac has. There is no header bus, so the sensor arrives over an FT232H USB dongle, or run the sim driver with no hardware. There is no .deb — install with Homebrew above, or from source; CI builds and runs the whole test suite on Intel and Apple silicon.

Once it is running, imud-status reports daemon health, attitude, declination, and heave; imud-mon gives a live view of the output streams from any host on the network.

No hardware yet? Run the whole pipeline in simulation, or replay a capture recorded on a real vessel:

imud --config config/sim.conf              # synthetic scenario
imud --replay session.imucap               # recorded raw sensor data

Before first real use, calibrate: imud-cal gyro, imud-cal accel, and an in-situ imud-cal mag.

Output formats

OutputTransportFor
NMEA 0183 UDP broadcast, or TCP :10110 Chartplotters, autopilots, Signal K
Binary packet UDP :10111 High-rate quaternion for vision and control
Framed stream AF_UNIX socket, or TCP :10112 Loss-free local consumers, bridges, libimud

A stock install emits on the local AF_UNIX socket and nothing else; each network output has to be switched on deliberately in /etc/imud/imud.conf. If you just need heading, pitch, and roll for a chartplotter, turn on the NMEA TCP listener and point your app at tcp://<host>:10110.

Hardware

Reference
SparkFun 9DoF IMU Breakout — ST ISM330DHCX (gyro + accelerometer) with a MEMSIC MMC5983MA magnetometer. This is the best-tested combination. The TDK InvenSense MPU-9255 with its AKM AK8963 compass is validated on hardware too, as is the six-axis MPU-6500.
Experimental drivers
ST LSM6DSO and LSM6DSOX, TDK InvenSense ICM-20948, ICM-42688-P and MPU-9250; magnetometers ST LIS2MDL and LIS3MDL, AKM AK09916, and PNI RM3100. imud-imutest is how one of these gets promoted: run it against the part and attach the report.
No hardware
The sim driver runs the full pipeline from a synthetic scenario or a recorded capture file, on any host imud builds on.

Host side, imud targets the Raspberry Pi — it drives the sensor over I²C or SPI and takes the data-ready interrupt on a GPIO line via libgpiod — but nothing in it is Pi-specific beyond that. A host with no bus on a header reaches the parts through an FT232H USB bridge instead, which needs no library and no root and is how a Mac, or a laptop, runs the same drivers.

Bridges and clients

Protocol bridges
Five optional daemons read the local stream socket and re-publish it: imud-signalk (Signal K deltas), imud-mqtt (MQTT + Home Assistant discovery), imud-influxdb (line protocol for Grafana), imud-mavlink (MAVLink v1/v2 to autopilots), and imud-prometheus (a /metrics endpoint). Each is self-contained, with its own config file and man page.
Client libraries
libimud is the ABI-stable C library for the binary stream. A single-file Python client ships with the daemon, and ImudClient provides an Arduino/ESP32 client over TCP or UDP — header-only, no heap, for cockpit displays and telemetry heads.
Tools
imud-cal for gyro, accelerometer, and magnetometer calibration; imud-status to query a running daemon; imud-mon for a live network view of the streams; imud-imutest to validate a sensor driver against real hardware and write a report worth attaching to an issue.

Reporting bugs and contributing

Report a bug or request a feature
Open an issue at github.com/richcreations/imud/issues. For a driver problem, attach an imud-imutest --all report — it captures the hardware, the timing, and every check the daemon relies on, which is most of what a diagnosis needs.
Search past reports
Every report and the replies to it stay public and searchable: all issues, open and closed. Worth checking before filing — and worth reading afterwards, since the reasoning behind a fix usually lives in the thread rather than the commit.
Report a security vulnerability
Please do not open a public issue. Use GitHub's private vulnerability reporting, as described in SECURITY.md, which also states the supported versions and the response timeline.
Contribute code or documentation
CONTRIBUTING.md covers the build, the test suite (make test), the coding conventions, and the doc-sync rules — this project keeps the same facts in several places on purpose, so a change is not finished until its manual, man page and spec entries agree. Pull requests are welcome; CI runs the full suite on amd64, arm64 and armhf, under sanitizers, and against the fuzzers.
Clearing an experimental driver flag
Nine of the fourteen sensor drivers have never run on physical silicon. If you have one of those parts, an imud-imutest report attached to an issue is what clears its flag — see the roadmap.
Code of conduct
Contributor Covenant.

See also

Installed man pages: imud(8), imud-cal(8), imud.conf(5), imud-status(1), libimud(3), and one per bridge.

Author

Written by Richard Simpson. Released under the MIT license.

imud 1.11.0 2026-09-11 IMUD(8)