Synchronize trajectories based on their path length.
Project description
sensor-sync
sensor-sync is a Python module for estimating the relative time offset between two position-producing sensors.
It is designed for streams where both sensors observe the same motion but do not agree perfectly on timestamp alignment. The module combines timestamp calibration, path-length tracking, interpolation, and a Kalman filter to estimate a stable temporal shift.
What it provides
The public surface is centered around two main types:
Position: one timestamped 3D sample with a scalar velocitySynchronizer: consumes primary and secondary sensor samples and maintains the current estimate
The Kalman state is maintained internally by Synchronizer.
The estimated state contains:
delta_t: estimated time shift between the sensor streamsbias: estimated path-length biassigma_delta_t: uncertainty of the time-shift estimatesigma_bias: uncertainty of the bias estimate
Estimation model
The synchronizer works in two phases.
During calibration, it computes a rough per-sensor wall-clock offset from incoming timestamps. After calibration, it shifts each sensor stream by its average offset and begins trajectory-based matching.
For each incoming sample, the module accumulates traveled path length. Secondary samples are matched against neighboring primary samples, and the primary trajectory is linearly interpolated to the secondary timestamp. The difference in path length becomes the measurement used by the Kalman filter.
The filter estimates two quantities:
- a time offset term
- a bias term that absorbs residual path-length drift
Conceptually, the measurement model is:
$$ \Delta s \approx v \cdot \Delta t + b $$
where $\Delta s$ is the observed path-length difference, $v$ is interpolated velocity, $\Delta t$ is the time shift, and $b$ is a slowly varying bias.
Installation
Requirements:
- Python 3.9 or newer
Using uv:
uv sync
To activate the virtual environment on Windows PowerShell:
.\.venv\Scripts\Activate.ps1
The project depends on:
numpymatplotlibtrajectopy
Usage
Create a synchronizer and feed it timestamped position samples from both streams.
from sensor_sync import Position, Synchronizer
synchronizer = Synchronizer(calibration_samples=20)
primary_sample = Position(
timestamp=1000.0,
x=0.0,
y=0.0,
z=0.0,
v=2.5,
)
secondary_sample = Position(
timestamp=1000.1,
x=0.2,
y=0.0,
z=0.0,
v=2.4,
)
synchronizer.on_new_position_sensor_primary(primary_sample)
synchronizer.on_new_position_sensor_secondary(secondary_sample)
state = synchronizer.state
print(state["delta_t"], state["bias"])
In a real integration, keep feeding both sensors as samples arrive. Once calibration has completed and enough primary samples are available for interpolation, the estimate will be updated automatically.
Integration notes
- The synchronizer is thread-safe at the input boundary and guards updates with a lock.
- Incoming samples are expected to include velocity magnitude in
Position.v. - Matching assumes that the primary stream can provide surrounding samples for interpolation.
- Calibration currently depends on
time.time()and incoming sample timestamps being comparable in the same clock domain. - The implementation mutates
position.timestampin place after applying the sensor-specific average offset.
Tuning
Synchronizer exposes three filter-tuning parameters at construction time:
delta_t_var: process noise for time-shift stabilitybias_var: process noise for bias driftdelta_path_length_var: measurement noise for path-length observations
These can be passed directly to the constructor alongside calibration_samples and initial_dt.
synchronizer = Synchronizer(
calibration_samples=20,
initial_dt=0.0,
delta_t_var=1e-12,
bias_var=1e-3,
delta_path_length_var=0.1,
)
Smaller process noise makes the estimate more stable but less responsive. Larger measurement noise makes the filter trust its prior more than new path-length observations.
Module layout
sensor_sync.py: core implementation of the estimator and synchronizerpyproject.toml: package metadata and dependencies
Status
This repository currently exposes a single-module implementation intended for experimentation and integration work. It is not yet packaged as a multi-file library with a formal test suite or stable public API guarantees.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file trajectory_sync-0.1.0.tar.gz.
File metadata
- Download URL: trajectory_sync-0.1.0.tar.gz
- Upload date:
- Size: 29.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.6 {"installer":{"name":"uv","version":"0.11.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e8a87f47143040bfe11a2884d3af06fe6cdbdad5af96e153fc19c245ebbf4a04
|
|
| MD5 |
b7b945ee7a6cdbb274dfa68ed110879b
|
|
| BLAKE2b-256 |
8f4e0cc00a34b9653d24ff32d0dcf77fd76d80b4444a2fee3a96ebc4d06f4930
|
File details
Details for the file trajectory_sync-0.1.0-py3-none-any.whl.
File metadata
- Download URL: trajectory_sync-0.1.0-py3-none-any.whl
- Upload date:
- Size: 6.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.6 {"installer":{"name":"uv","version":"0.11.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
210e111604ec9d906d14bb6990c822cad10699bc84c43298cc7d0485c3d49f57
|
|
| MD5 |
3ddb781079cfefd8bda9947d4c9e5420
|
|
| BLAKE2b-256 |
4541dfb02a0bc0c73ebf87d69f932aaff0edd5ae11233dbe183cd2f8db045928
|