C++ / Python 3.10+

quak
filter

Modular state estimation building blocks — UKF, IMM, and multi-sensor fusion in C++ with Python bindings. Quaternion-native, real-time tracking.

Install:

pip install quakfilter

Requires Python ≥ 3.10 and NumPy ≥ 2.0. Built with Eigen 5 and optional OpenMP for parallel tracking.

API Reference GitHub

Core Capabilities

Unscented Kalman Filter

Sigma-point UKF on a 16-dimensional quaternion state vector (position, velocity, orientation, angular velocity). Handles non-linear dynamics without Jacobians.

ukf = quak.UKF(model, process_noise, measurement_noise, initial_covariance, x0)

Manifold-Aware Estimation

Sigma points respect SO(3) quaternion geometry — no linearization artifacts on rotations. Pluggable manifold abstraction with built-in Euclidean and Quaternion types for correct retraction and lifting on non-Euclidean state spaces.

quak.Quaternion() # SO(3) manifold for UKF sigma-point generation

Interacting Multiple Model

IMM estimator that blends multiple motion models (constant velocity, constant turn-rate, Singer jerk, helical) — automatically adapts to maneuvering targets.

imm = quak.IMMEstimator(models, transition_matrix, mode_probabilities)

Multi-Object Track Pool

Manages hundreds of concurrent tracks with automatic birth, death, and data association. OpenMP-accelerated parallel predict and update across all tracks.

pool = quak.TrackPool(models, config); pool.step(detections, timestamp)

Projective Bounding Box Sensor

Fuse 2D image detections with 3D state via calibrated camera projection. Supports pinhole, fisheye, and arbitrary distortion models.

sensor = quak.ProjectiveBBoxSensor(camera_params, noise_model)

Quick Start

Single-Object UKF Tracking

Create a filter, predict forward, and update with measurements.

import numpy as np
import quak

# Constant-velocity rigid body model
model = quak.RigidBodyCVModel()

# Initial state: position + velocity + quaternion + angular velocity
x0 = np.zeros(16)
x0[9] = 1.0  # quaternion w-component

ukf = quak.UKF(
    model=model,
    process_noise=np.eye(15) * 0.01,
    measurement_noise=np.eye(6) * 0.001,
    initial_covariance=np.eye(15) * 0.1,
    initial_state=x0,
)

# Predict → Update loop
ukf.predict(dt=0.1)
ukf.update(measurement)

Multi-Object Tracking

TrackPool handles birth, death, and association for many targets simultaneously.

import quak

pool = quak.TrackPool(
    models=[quak.RigidBodyCVModel(), quak.RigidBodyCTRVModel()],
    transition_matrix=np.array([[0.95, 0.05], [0.05, 0.95]]),
)

for timestamp, detections in sensor_stream:
    pool.step(detections, timestamp)
    for track in pool.active_tracks:
        print(f"Track {track.id}: {track.position}")