Metadata-Version: 2.4
Name: kalbee
Version: 0.5.0
Summary: A clean, modular Python implementation of Kalman Filters and estimation algorithms.
Author-email: Le Duc Minh <minh.leduc.0210@gmail.com>
Maintainer-email: Le Duc Minh <minh.leduc.0210@gmail.com>
Project-URL: Homepage, https://github.com/MinLee0210/kalbee
Project-URL: Repository, https://github.com/MinLee0210/kalbee
Project-URL: Documentation, https://minlee0210.github.io/kalbee
Keywords: kalman-filter,extended-kalman-filter,ekf,unscented-kalman-filter,ukf,particle-filter,ensemble-kalman-filter,information-filter,state-estimation,sensor-fusion,tracking,alpha-beta-gamma,rts-smoother,adaptive-filter,robotics,signal-processing,python
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: numpy>=1.24.4
Requires-Dist: scipy>=1.10.0
Provides-Extra: yolo
Requires-Dist: ultralytics>=8.0.0; extra == "yolo"
Requires-Dist: opencv-python>=4.8.0; extra == "yolo"
Provides-Extra: viz
Requires-Dist: matplotlib>=3.7.0; extra == "viz"
Provides-Extra: docs
Requires-Dist: mkdocs-material>=9.7.2; extra == "docs"
Dynamic: license-file

# kalbee

<div align="center">
  <img src="https://raw.githubusercontent.com/MinLee0210/kalbee/main/docs/kalbee.png" alt="kalbee logo" width="300"/>
</div>

<br>

`kalbee` is a clean, modular Python implementation of Kalman Filters and related estimation algorithms. Designed for simplicity and performance, it provides a standard interface for state estimation in various applications.

## Features

- **10 Filters**: KF, EKF, UKF, Particle Filter, Ensemble KF, Information Filter, Alpha-Beta-Gamma, Adaptive KF, Square-Root KF (SRKF), and Vectorized KF (VKF)
- **Estimators**: Interacting Multiple Model (IMM) filter blending/switching estimator
- **Motion Models**: Ready-made constant-velocity, constant-acceleration, and coordinated-turn `(F, Q)` builders plus position measurement models
- **Multi-Object Tracking**: SORT-style `MultiObjectTracker` with Hungarian association, Mahalanobis/IoU gating, and track lifecycle management — built on top of any filter
- **Parameter Learning**: Offline EM (`em_kalman`) that fits `Q`/`R` from data by maximum likelihood, complementing the online Adaptive KF
- **RTS Smoother**: Rauch-Tung-Striebel backward smoother for post-processing
- **Metrics**: RMSE, NEES, NIS, Log-Likelihood for filter diagnostics
- **Experiment Runner**: Compare filters on synthetic signals with one line
- **AutoFilter Factory**: Switch between filters by name
- **Numerical Stability**: Joseph form covariance updates, Cholesky factor stabilization, and symmetry enforcement
- **NumPy/SciPy Integration**: Optimized for numerical computations

## Installation

```bash
pip install kalbee
```

Or from source:

```bash
git clone https://github.com/MinLee0210/kalbee.git
cd kalbee
pip install -e .
```

Optional extras: `pip install "kalbee[yolo]"` (object-tracking examples), `"kalbee[viz]"` (plotting), or `"kalbee[docs]"` (documentation site).

## Quick Start

### 1. Standard Kalman Filter

```python
import numpy as np
from kalbee import KalmanFilter

state = np.zeros((2, 1))  # [position, velocity]
cov = np.eye(2)
F = np.array([[1, 1], [0, 1]])  # Constant velocity model
Q = np.eye(2) * 0.01
H = np.array([[1, 0]])
R = np.array([[0.1]])

kf = KalmanFilter(state, cov, F, Q, H, R)
kf.predict()
kf.update(np.array([[1.2]]))
print(f"Estimated State:\n{kf.x}")
```

### 2. Interacting Multiple Model (IMM) Filter

```python
import numpy as np
from kalbee import KalmanFilter, InteractingMultipleModel

# Define CV and CA filters with shared state size (6D)
# CV model setup
kf_cv = KalmanFilter(state_init, cov_init, F_cv, Q_cv, H, R)
# CA model setup
kf_ca = KalmanFilter(state_init, cov_init, F_ca, Q_ca, H, R)

model_transition = np.array([[0.95, 0.05], [0.05, 0.95]])
model_probabilities = np.array([0.8, 0.2])

imm = InteractingMultipleModel([kf_cv, kf_ca], model_transition, model_probabilities)
imm.predict()
imm.update(measurement)
```

### 3. Vectorized Kalman Filter (Batched Tracking)

```python
import numpy as np
from kalbee import VectorizedKalmanFilter

batch_size = 1000
state = np.zeros((batch_size, 2, 1))
covariance = np.repeat(np.eye(2)[np.newaxis, :, :], batch_size, axis=0)

# Load batched models and predict
vkf = VectorizedKalmanFilter(state, covariance, F_batch, Q_batch, H_batch, R_batch)
vkf.predict()
vkf.update(batched_measurements)
```

### 4. Compare Filters with Experiments

```python
from kalbee import run_experiment

report = run_experiment(
    signal="sine",
    filters=["kf", "ekf", "ukf", "pf"],
    noise_std=0.5,
)
print(report.summary())
```

### 5. AutoFilter Factory

```python
from kalbee import AutoFilter

kf = AutoFilter.from_filter(state, cov, F, Q, H, R, mode="kf")
# Available modes: kf, ekf, ukf, abg, pf, enkf, if, akf, srkf, vkf
```

### 6. Multi-Object Tracking

```python
import numpy as np
from kalbee import KalmanFilter, MultiObjectTracker
from kalbee.models import constant_velocity, position_measurement_model

# Ready-made 2D constant-velocity model: state = [x, vx, y, vy]
F, Q = constant_velocity(dt=1.0, process_var=0.1, n_dims=2)
H, R = position_measurement_model(order=1, n_dims=2, measurement_var=0.25)

def new_track(z):  # build a filter seeded on a fresh detection
    x0 = np.array([[z[0]], [0.0], [z[1]], [0.0]])
    return KalmanFilter(x0, np.eye(4) * 10.0, F, Q, H, R)

tracker = MultiObjectTracker(new_track, n_init=3, max_age=5)

# Feed detections (D x 2 positions) frame by frame, e.g. from YOLO
for detections in detection_stream:
    confirmed = tracker.update(detections)
    for t in confirmed:
        print(t.id, t.state[0, 0], t.state[2, 0])
```

See [`examples/multi_object_tracking.py`](examples/multi_object_tracking.py) for a full runnable demo.

### 7. Learn Noise Covariances from Data (EM)

```python
from kalbee import em_kalman
from kalbee.models import constant_velocity, position_measurement_model

F, _ = constant_velocity(dt=1.0, n_dims=1)
H, _ = position_measurement_model(order=1, n_dims=1)

# measurements: array of shape (T, m) — learn Q and R by maximum likelihood
result = em_kalman(measurements, F, H, n_iter=50)
print("Learned Q:\n", result.Q)
print("Learned R:\n", result.R)
print("Log-likelihood history:", result.loglik_history[-1])
```

## Documentation

Full documentation with theory, code examples, and experiments for each filter:

```bash
pip install mkdocs-material
mkdocs serve
```

- [Getting Started](docs/getting_started.md)
- **Filters**: [KF](docs/filters/kalman_filter.md) · [EKF](docs/filters/extended_kalman_filter.md) · [UKF](docs/filters/unscented_kalman_filter.md) · [PF](docs/filters/particle_filter.md) · [EnKF](docs/filters/ensemble_kalman_filter.md) · [IF](docs/filters/information_filter.md) · [ABG](docs/filters/alpha_beta_gamma_filter.md) · [AKF](docs/filters/adaptive_kalman_filter.md) · [SRKF](docs/filters/square_root_kalman_filter.md) · [Vectorized KF](docs/filters/vectorized_kalman_filter.md) · [IMM](docs/filters/interacting_multiple_model.md)
- **Features**: [RTS Smoother](docs/features/rts_smoother.md) · [Metrics](docs/features/metrics.md) · [Experiments](docs/features/experiments.md) · [Maneuvering Target Tracking](docs/features/maneuvering_target.md) · [YOLO Object Tracking](docs/features/yolo_tracking.md)
- [Architecture](docs/architecture.md)

## Testing

```bash
uv run pytest tests/                                  # run the suite
uv run pytest tests/ --cov=kalbee --cov-report=term   # with coverage
```

## License

This project is licensed under the Apache License 2.0.
