UWB
UWB multilateration and EKF position filter.
- class omnitiles.uwb.UwbEkf(anchors=((0.0, 0.0), (1.778, 0.0), (-0.508, 1.7018), (3.0861, 1.7018)), range_std_m=0.07)[source]
Bases:
objectExtended Kalman Filter fusing UWB ranges with IMU motion detection.
State vector:
[px, py, vx, vy]— 2D position and velocity in meters.Predict uses a constant-velocity model. Process noise Q is modulated by the IMU: when the accelerometer/gyroscope indicate the tile is stationary, Q is very small so the filter aggressively smooths UWB noise. When motion is detected, Q grows so the filter tracks the new position.
Update ingests one or more UWB range observations. Each range is individually gated (Mahalanobis chi² test) to reject multipath outliers before the state is updated.
- Parameters:
anchors (
Sequence[tuple[float,float]])range_std_m (
float|Sequence[float])
- GRAVITY = 9.81
- ACCEL_MOTION_THRESH = 1.0
- GYRO_YAW_MOTION_THRESH = 0.1
- SIGMA_A_STATIONARY = 0.01
- SIGMA_A_MOVING = 5.0
- GATE_CHI2 = 9.0
- property initialized: bool
- property position: tuple[float, float] | None
- property velocity: tuple[float, float] | None
- step(distances_mm, timestamp, imu=None, z_offset_m=0.0)[source]
Run one predict + update cycle.
Returns the filtered
(x, y)in meters, orNoneif the filter has not yet been initialised (needs at least one trilateration fix).- Parameters:
distances_mm (
Sequence[int|None])timestamp (
float)imu (
ImuSample|None)z_offset_m (
float)
- Return type:
tuple[float,float] |None
- omnitiles.uwb.trilaterate(distances_mm, anchors=((0.0, 0.0), (1.778, 0.0), (-0.508, 1.7018), (3.0861, 1.7018)), z_offset_m=0.0)[source]
Compute a 2D position from anchor distances using least-squares.
Works with 3 or more anchors. When more than 3 valid distances are available the overdetermined system is solved via least-squares, averaging out per-anchor ranging noise.
- Parameters:
distances_mm (
Sequence[int|None]) – Distances from each anchor, in millimeters.Noneentries are skipped; at least 3 valid distances are required.anchors (
Sequence[tuple[float,float]]) – Anchor(x, y)positions in meters. Must have the same length as distances_mm.z_offset_m (
float) – Vertical distance between the tag and the (shared) anchor plane, in meters. Measured 3D ranges are projected onto the floor plane viar = sqrt(d**2 - z**2)before solving.
- Return type:
tuple[float,float] |None- Returns:
(x, y)in meters, orNoneif fewer than 3 valid ranges or any valid range is shorter than z_offset_m.