Metadata-Version: 2.5
Name: blackwell
Version: 0.0.3
Summary: JAX-native probabilistic robotics
Project-URL: Documentation, https://unswei.github.io/blackwell/
Project-URL: Issues, https://github.com/unswei/blackwell/issues
Project-URL: Source, https://github.com/unswei/blackwell
Project-URL: Changelog, https://github.com/unswei/blackwell/blob/main/CHANGELOG.md
Author: Blackwell contributors
License-Expression: Apache-2.0
License-File: LICENSE
Keywords: jax,probabilistic-robotics,robotics,state-estimation
Classifier: Development Status :: 2 - Pre-Alpha
Classifier: Intended Audience :: Science/Research
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
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: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Typing :: Typed
Requires-Python: >=3.10
Requires-Dist: jax>=0.6
Provides-Extra: dev
Requires-Dist: build>=1.2; extra == 'dev'
Requires-Dist: matplotlib>=3.8; extra == 'dev'
Requires-Dist: mkdocs-material>=9.6; extra == 'dev'
Requires-Dist: mkdocs>=1.6; extra == 'dev'
Requires-Dist: mkdocstrings[python]>=0.27; extra == 'dev'
Requires-Dist: pytest>=8.3; extra == 'dev'
Requires-Dist: ruff>=0.8; extra == 'dev'
Provides-Extra: docs
Requires-Dist: mkdocs-material>=9.6; extra == 'docs'
Requires-Dist: mkdocs>=1.6; extra == 'docs'
Requires-Dist: mkdocstrings[python]>=0.27; extra == 'docs'
Provides-Extra: plot
Requires-Dist: matplotlib>=3.8; extra == 'plot'
Description-Content-Type: text/markdown

# Blackwell

[![Test](https://github.com/unswei/blackwell/actions/workflows/test.yml/badge.svg)](https://github.com/unswei/blackwell/actions/workflows/test.yml)
[![Documentation](https://github.com/unswei/blackwell/actions/workflows/docs.yml/badge.svg)](https://github.com/unswei/blackwell/actions/workflows/docs.yml)
[![PyPI](https://img.shields.io/pypi/v/blackwell.svg)](https://pypi.org/project/blackwell/)
[![Python 3.10+](https://img.shields.io/badge/python-3.10%2B-3776AB)](https://www.python.org/)
[![Apache-2.0](https://img.shields.io/badge/licence-Apache--2.0-blue)](LICENSE)

Blackwell is a compact, JAX-native probabilistic-robotics library. It provides
manifold-aware Gaussian beliefs, weighted particles, Euclidean, SE(2) and SE(3) state
spaces, an extended Kalman filter, a bootstrap particle filter, reproducible
simulation and uncertainty metrics.

It is useful today for planar localisation, 3D transform uncertainty, linear state
estimation and estimator research, while remaining deliberately pre-alpha:
expect API changes before version 1.0.

**[Documentation](https://unswei.github.io/blackwell/)** ·
**[Five-minute localisation](https://unswei.github.io/blackwell/getting-started/quickstart/)** ·
**[Examples](https://unswei.github.io/blackwell/examples/)** ·
**[API reference](https://unswei.github.io/blackwell/api/)**

Explore the documentation for installation guidance, practical tutorials,
runnable examples and the complete API reference.

## Install

Blackwell requires Python 3.10 or newer. Install the latest release from PyPI:

```console
python -m pip install blackwell
```

Blackwell requires `jax>=0.6`. Python 3.10 selects JAX 0.6.2; newer Python
versions select newer compatible JAX releases. The installer uses the Python
interpreter running the command. To use Python 3.11 explicitly, run
`python3.11 -m pip install --upgrade blackwell jax`.

Accelerator-specific JAX packages are intentionally not pinned. See the
[installation guide](https://unswei.github.io/blackwell/getting-started/installation/)
for GPU/TPU and development setups.

## A first SE(2) estimate

```python
import jax
import jax.numpy as jnp

from blackwell import GaussianBelief
from blackwell.filters.ekf import ExtendedKalmanFilter
from blackwell.models import range_bearing
from blackwell.models import se2 as se2_models
from blackwell.spaces import se2

filter_ = ExtendedKalmanFilter(se2, se2_models, range_bearing)
dynamics = se2_models.BodyMotion(
    process_covariance=jnp.diag(jnp.array([0.01, 0.01, 0.0025]))
)
observation = range_bearing.KnownLandmarksRangeBearing(
    landmarks=jnp.array([[5.0, 0.0], [0.0, 5.0]]),
    measurement_covariance=jnp.diag(jnp.array([0.08, 0.02])),
)
belief = GaussianBelief(
    mean=jnp.array([0.0, 0.0, 0.0]),
    covariance=jnp.diag(jnp.array([0.5, 0.5, 0.1])),
)

belief = jax.jit(filter_.step)(
    belief,
    dynamics,
    observation,
    jnp.array([0.3, 0.0, 0.04]),
    range_bearing.observe(jnp.array([0.35, 0.08, 0.05]), observation),
)
print(belief.mean)
```

SE(2) states are `[x, y, heading]`; controls and covariance use local
body-frame tangent coordinates `[forward, lateral, turn]`.

SE(3) states are `[x, y, z, qx, qy, qz, qw]`, with a scalar-last Hamilton
quaternion. Their covariance uses six body-frame coordinates: translation
`rho` followed by rotation vector `phi`. See the
[SE(3) uncertainty example](https://unswei.github.io/blackwell/examples/se3-uncertainty/) for composition,
inversion and point transformation with correlated inputs.

## What is included?

- Euclidean and right-retraction SE(2)/SE(3) state spaces
- Linear dynamics and observations
- SE(2) body-motion and known-landmark range-bearing models
- Manifold-aware extended Kalman filtering
- Bootstrap particle filtering with explicit ESS and systematic resampling
- Reproducible trajectory simulation
- RMSE, planar position RMSE and NEES metrics
- Runnable linear, SE(2) EKF, particle-localisation and correlated SE(3) examples

Blackwell does not yet include built-in IMU models, smoothing, SLAM state
augmentation, data association, sensor drivers or production persistence. See
[Choose an estimator](https://unswei.github.io/blackwell/getting-started/choose-an-estimator/)
for the current fit and limits.

## Design commitments

- JAX is the sole numerical backend.
- Mathematical kernels are pure and beliefs are immutable PyTrees.
- Manifold uncertainty lives in local tangent coordinates.
- Geometry, stochastic models and inference remain separate.
- Random keys, JIT compilation and resampling policy stay explicit.
- Simulation and consistency metrics are part of the public API.

## Run the examples

```console
git clone https://github.com/unswei/blackwell.git
cd blackwell
uv sync --all-extras
uv run python examples/quickstart.py
uv run python examples/linear_kalman_filter.py
uv run python examples/se3_uncertainty.py
uv run python examples/se2_localisation.py --plot localisation.png
uv run python examples/particle_localisation.py --plot particles.png
```

## Contribute

Set up the reproducible development environment and run all local checks:

```console
uv sync --all-extras
uv run ruff check .
uv run pytest
uv run python -m build
uv run mkdocs build --strict
```

See [CONTRIBUTING.md](CONTRIBUTING.md) for workflow, test and documentation
expectations.

## Licence

Blackwell is licensed under the [Apache License 2.0](LICENSE).
