Metadata-Version: 2.4
Name: turbo-ckf
Version: 0.8.0
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: Apache Software License
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Rust
Classifier: Topic :: Scientific/Engineering
Requires-Dist: numpy>=1.22
Requires-Dist: numpy ; extra == 'dev'
Requires-Dist: filterpy ; extra == 'dev'
Requires-Dist: pytest ; extra == 'dev'
Requires-Dist: pytest-benchmark ; extra == 'dev'
Requires-Dist: pytest-cov ; extra == 'dev'
Requires-Dist: maturin ; extra == 'dev'
Provides-Extra: dev
License-File: LICENSE-MIT
License-File: LICENSE-APACHE
Summary: Turbo-CKF: High-performance Cubature Kalman Filter
Keywords: kalman-filter,cubature-kalman-filter,sensor-fusion,rust,python
Author: Mohammed Khalid
License-Expression: MIT OR Apache-2.0
Requires-Python: >=3.9
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
Project-URL: Homepage, https://github.com/mokhld/turbo-ckf
Project-URL: Issues, https://github.com/mokhld/turbo-ckf/issues
Project-URL: Repository, https://github.com/mokhld/turbo-ckf

# turbo-ckf

[![PyPI version](https://img.shields.io/pypi/v/turbo-ckf.svg)](https://pypi.org/project/turbo-ckf/)
[![Python versions](https://img.shields.io/pypi/pyversions/turbo-ckf.svg)](https://pypi.org/project/turbo-ckf/)
[![CI](https://github.com/mokhld/turbo-ckf/actions/workflows/ci.yml/badge.svg)](https://github.com/mokhld/turbo-ckf/actions/workflows/ci.yml)
[![License: MIT OR Apache-2.0](https://img.shields.io/badge/license-MIT%20OR%20Apache--2.0-blue.svg)](#license)

`turbo-ckf` is a Rust-backed Cubature Kalman Filter package for high-throughput prediction/update loops. Implemented here purely as an experiment after reading the paper.

## What This Package Optimizes

- Fast prediction with built-in linear models:
  - `predict_standard_model(...)`
  - `predict_standard_model_ckf(...)`
  - `predict_linear_model(F)`
  - `predict_linear_model_ckf(F)`
- Fast AHRS update path:
  - `update_paper_ahrs(...)`

`predict(...)` and `update(...)` also run through Rust, but callback cost in Python can dominate if your models are heavy.

## Square-Root Variant

`TurboSRCKF` is a separate estimator that propagates the lower-triangular Cholesky factor of `P` directly. The filter loop never calls `stable_cholesky` on `P`, so the silent diagonal-jitter accumulation `TurboCKF` surfaces via `jitter_count` is structurally impossible in steady state. Use it when `P` becomes ill-conditioned (e.g., long predict chains with tiny `Q`/`R`, or rank-deficient seed covariances). Mirrors `predict(...)` + `update(...)`; for closed-form linear predicts or the AHRS update use `TurboCKF`.

```python
from turbo_ckf import TurboSRCKF
kf = TurboSRCKF(dim_x=4, dim_z=2, dt=0.1, hx=hx_vectorized, fx=fx_vectorized)
kf.predict()
kf.update(z)
# kf.chol_P is the lower-triangular factor; kf.P = chol_P @ chol_P.T
```

## Callback Contract

Custom `fx` and `hx` must be vectorized:

- Input shape is `(2 * dim_x, dim_x)`.
- `fx` output shape must be `(2 * dim_x, dim_x)`.
- `hx` output shape must be `(2 * dim_x, dim_z)`.

If you pass pointwise callbacks, `TurboCKF` raises immediately.

## Install

```bash
pip install turbo-ckf
```

Wheels are published for CPython 3.9 - 3.13 on Linux, macOS, and Windows.

## Install from source (development)

From `turbo-ckf/`:

```bash
bash turbo_ckf/setup_env.sh
```

## Usage

```python
from turbo_ckf import TurboCKF

kf = TurboCKF(dim_x=2, dim_z=1, dt=0.1, hx=hx_vectorized, fx=fx_vectorized)
kf.predict_standard_model("constant_velocity")
kf.update(z)
```

State assignment is forgiving about spelling: `x` accepts lists, integer
arrays, and column vectors; `P`, `Q`, `R` accept scalars (`kf.R = 0.25` means
`0.25 * I`), 1-D diagonals (`kf.Q = [1e-3, 1e-2]`), or full matrices. Wrong
sizes and non-finite values raise at assignment time with the attribute named
in the error. Changing `kf.dt` after construction takes effect on the next
predict, including the standard/linear-model paths.

A NaN or inf measurement raises instead of corrupting the state. For a missed
measurement pass `z=None`, which runs the predict-only step and clears the
innovation diagnostics.

### Filtering a whole sequence

`run(...)` wraps the predict/update loop, stacks the per-step outputs, and
handles measurement dropouts:

```python
result = kf.run(zs)                # zs: (N, dim_z), or (N,) when dim_z == 1
result.xs, result.Ps               # posterior means / covariances, stacked
result.log_likelihoods, result.nis # per-step diagnostics

# Missed measurements: None entries (or all-NaN rows with
# nan_means_missing=True) skip the update for that step.
kf.run([z0, None, z2])
kf.run(zs, nan_means_missing=True)

# Per-step time steps and measurement noise:
kf.run(zs, dts=dt_array, Rs=r_stack)
```

`run` is available on both `TurboCKF` and `TurboSRCKF`. For linear models
prefer the static `TurboCKF.batch_filter`, which runs the whole loop inside
Rust in a single crossing.

AHRS path:

```python
kf.predict_linear_model(Fk)
kf.update_paper_ahrs(z6, sigma_acc2=1e-2, sigma_mag2=1e-2)
```

## Benchmarks

### Paper-Reported Targets (Shing et al., arXiv:2602.12283)

These are the KCKF-vs-CKF results reported in the paper:

- MacBook Pro 2021 (M1 Pro): KCKF `0.110 ms` vs CKF `0.135 ms` (`18.79%` lower time, about `1.23x` faster).
- Raspberry Pi 4 Model B: KCKF `1.28 ms` vs CKF `1.51 ms` (`15.15%` lower time, about `1.18x` faster).

### Local Results In This Repo

Measured on **February 21, 2026** on Apple M4 Max, Python 3.12.0, NumPy 2.4.2.

From:

```bash
.venv-turbo-ckf/bin/python turbo_ckf_tests/verify_before_after.py --steps 50000 --repeats 7 --warmup 1 --parity-steps 500
```

Median runtime per 50k predict+update steps:

- FilterPy (`filterpy_predict_update`): `2.354375 s` (baseline)
- TurboCKF callback path (`turbo_callback_predict_update`): `0.662003 s` (`3.56x` vs FilterPy)
- TurboCKF standard model KCKF (`turbo_standard_model_predict_update`): `0.539281 s` (`4.37x` vs FilterPy)
- TurboCKF standard model CKF (`turbo_standard_model_ckf_predict_update`): `0.549905 s` (`4.28x` vs FilterPy)
- KCKF-vs-CKF full-step speedup in this setup: `1.02x` (`0.549905 / 0.539281`)

From:

```bash
.venv-turbo-ckf/bin/python turbo_ckf_tests/benchmark_paper.py
```

- KCKF-vs-CKF (prediction only, backend): `1.67x`
- KCKF-vs-CKF (full step, backend): `1.09x`
- KCKF-vs-CKF (full step, wrapper): `1.03x`

Interpretation:

- The largest gains here are from the Rust-backed implementation versus pure-Python FilterPy loops (`~3.5x` to `~4.4x` in these runs).
- The direct KCKF-vs-CKF algorithmic gain is present but smaller on full-step end-to-end runs, and larger when isolating prediction equations.

## Research Basis

- This repo is an implementation of the KCKF AHRS equations described in:
  - Shing, Y. C., et al., "KCKF: A Fast and Stable Quaternion-Based Orientation Estimator", arXiv:2602.12283 (2026), https://arxiv.org/abs/2602.12283.
- Credit for the method belongs to the paper authors.

## License

Dual-licensed under either:
- MIT (`LICENSE-MIT`)
- Apache-2.0 (`LICENSE-APACHE`)

