Pelorus Python Bindings
Python bindings for Pelorus, a resource-aware Lidar-Inertial Odometry.
Installation
From source (requires Rust toolchain)
cd pelorus_py
pip install maturin
maturin develop --release
Select at most one GPU backend when building:
maturin develop --release --features cuda
maturin develop --release --features vulkan
maturin develop --release --features metal
Metal is available on macOS. CUDA requires a supported NVIDIA CUDA
installation. Vulkan requires a compatible device and driver. The default
features enable Rayon CPU parallelism and include processing_time_ns in
odometry results. Additional features are no-imu-sync and
large-processing-queue. The legacy downsample feature is retained for
compatibility but does not control the current configuration-based downsampling.
Or build a wheel:
maturin build --release --out dist
pip install dist/pelorus-*.whl
Usage
Basic API
import pelorus
import numpy as np
# Create Pelorus instance
lio = pelorus.Handle() # Uses embedded default config
# Or with custom config:
# lio = pelorus.Handle("path/to/config.rl")
#
# If you want to control PointCloud2 parsing (like `pelorus_create_with_options` in C):
# - device_specific_pointcloud2=True (default)
# - device_specific_pointcloud2=False (generic parsing path)
# lio = pelorus.Handle("path/to/config.rl", device_specific_pointcloud2=False)
# Add IMU data
lio.add_imu(
timestamp_sec=1000,
timestamp_nanosec=0,
orientation=[1.0, 0.0, 0.0, 0.0], # w, x, y, z
orientation_covariance=[0.01] + [0.0]*8,
angular_velocity=[0.0, 0.0, 0.0],
angular_velocity_covariance=[0.001] + [0.0]*8,
linear_acceleration=[0.0, 0.0, 9.81],
linear_acceleration_covariance=[0.01] + [0.0]*8,
)
# Add point cloud (recommended):
# - If you already have ROS2 messages, pass them directly:
# lio.add_pointcloud2_ros(cloud_msg)
#
# - For non-ROS point sources, use NumPy/sequence inputs:
# - Nx3: [x,y,z] (no per-point timing)
# - Nx4: [x,y,z,t] where t is uint32 nanosecond offset
# - Nx5: [x,y,z,intensity,t]
# NumPy arrays may use float32 or float64. Inputs must be non-empty. The t value
# must be finite and in the uint32 range; fractional values are rounded to the
# nearest nanosecond. The scan header timestamp is required:
points = np.array([[1.0, 2.0, 3.0, 0.0]], dtype=np.float32)
scan_id = lio.add_pointcloud(
points,
timestamp_sec=1000,
timestamp_nanosec=0,
)
# After feeding enough synchronized IMU and Lidar data, receive odometry:
odom = lio.try_recv()
if odom:
print(f"Position: {odom['position']}")
print(f"Orientation: {odom['orientation']}")
print(f"Linear velocity: {odom['linear_velocity']}")
print(f"Accelerometer bias: {odom['accel_bias']}")
print(f"Gyroscope bias: {odom['gyro_bias']}")
print(f"Points: {len(odom['points'])}")
# Or block until the next odometry result is available. Do this only while
# another producer is feeding data or when an output is expected.
# odom = lio.recv()
# Or receive odometry asynchronously via callback (like pelorus_c)
def on_odom(odom: dict) -> None:
print("Odom:", odom["timestamp_sec"], odom["timestamp_nanosec"], odom["position"])
lio.set_callback(on_odom)
# ... feed IMU / pointclouds ...
lio.clear_callback() # equivalent to lio.set_callback(None)
Using with MCAP Bagfiles
See examples/bagfile_example.py for a complete example using real sensor data from an MCAP bagfile.
python -m pip install mcap mcap-ros2-support
API Reference
Handle
Main interface to the Pelorus system.
Constructor
-
Handle(config_path: str | None = None, device_specific_pointcloud2: bool = True): Create a new Pelorus instancedevice_specific_pointcloud2=Falseselects the generic parsing path for PointCloud2 inputs.
Methods
add_imu(...): Add an IMU measurementadd_imu_ros(imu_msg): Add a ROS2sensor_msgs/msg/Imuobject directlyadd_odom(...): Add an odometry measurementadd_odom_ros(odom_msg): Add a ROS2nav_msgs/msg/Odometryobject directlyadd_pointcloud(cloud_dict): Add a point cloud (PointCloud2 format)add_pointcloud(cloud_np, timestamp_sec=..., timestamp_nanosec=...): Add a point cloud from a non-empty float32/float64 NumPy arrayadd_pointcloud(cloud_sequence, timestamp_sec=..., timestamp_nanosec=...): Add a point cloud from lists, tuples, or other Python sequencesadd_pointcloud2_ros(cloud_msg): Add a ROS2sensor_msgs/msg/PointCloud2message directlytry_recv(): Try to receive odometry (non-blocking), returnsNoneif no datarecv(): Receive odometry (blocks until available)set_callback(callback): Deliver odometry via callback from a background thread. Disablestry_recv()/recv()queuing while enabledclear_callback(): Disable callback delivery (equivalent toset_callback(None))version(): Get library version (static method)
Timestamp semantics
Pelorus uses two timestamp levels:
-
IMU/Odom timestamps (
timestamp_sec+timestamp_nanosec)- Absolute timestamps (typically epoch / ROS time) used for synchronization.
-
Lidar timestamps
- Scan header timestamp: absolute (sec/nanosec)
- Per-point
tfield (if provided):uint32nanoseconds offset, non-negative and forward in time relative to the scan header time.
The effective point time is:
point_time_abs = header_time_abs + (t * 1e-9)
Odometry outputs include timestamp_sec/timestamp_nanosec (and timestamp
as float for convenience), scan_id, pose/twist data and covariances,
accel_bias and gyro_bias in the IMU frame, a points NumPy array, and
frame_id. Builds using the default processing-time-export feature also
include processing_time_ns.
Development
# Install development dependencies
pip install maturin pytest black ruff
# Build and test
maturin develop
pytest
# Format code
black .
ruff check .
License
Dual-licensed under MIT or Apache-2.0, consistent with the Pelorus project.
Metadata
Release files for pelorus 0.0.8
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Built distributions (wheels)
Total release size: 13.7 MB
Release files / pelorus-0.0.8-cp38-abi3-musllinux_1_2_x86_64.whl
| Download URL | pelorus-0.0.8-cp38-abi3-musllinux_1_2_x86_64.whl |
|---|---|
| Size | 2.4 MB |
| Tags | CPython 3.8 Linux musl 1.2+ x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
48f589e3ce6232c598939b6bf049cca436e7d5f936b973a0b86250ea22fa3a45
|
|
BLAKE2b-256 checksum How to use checksums |
bd0b51dc25b589d155b1a0422bfcecb5135486c2a2c32e793f5a040b84229113
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.4
|
Release files / pelorus-0.0.8-cp38-abi3-musllinux_1_2_armv7l.whl
| Download URL | pelorus-0.0.8-cp38-abi3-musllinux_1_2_armv7l.whl |
|---|---|
| Size | 1.7 MB |
| Tags | CPython 3.8 Linux musl 1.2+ ARMv7l abi3 |
|
SHA-256 checksum How to use checksums |
0590a7b544ddb1648fc1dd4a374b831ff8d73220c42b91f63075af2fa00638a6
|
|
BLAKE2b-256 checksum How to use checksums |
071701c0f10f9d37bf883e36328a6429a7555203b66bd5ca2a69fdfddba3908d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.4
|
Release files / pelorus-0.0.8-cp38-abi3-musllinux_1_2_aarch64.whl
| Download URL | pelorus-0.0.8-cp38-abi3-musllinux_1_2_aarch64.whl |
|---|---|
| Size | 1.9 MB |
| Tags | CPython 3.8 Linux musl 1.2+ ARM64 abi3 |
|
SHA-256 checksum How to use checksums |
c7684234065a44fdf35b02904196c65a6985659b40d58f50b048df4808bd8b74
|
|
BLAKE2b-256 checksum How to use checksums |
aeb495e0e4c7ce85cb0b6a8013150b41134a54b95495cb0d227c08ece8cf4a47
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.4
|
Release files / pelorus-0.0.8-cp38-abi3-manylinux_2_34_aarch64.whl
| Download URL | pelorus-0.0.8-cp38-abi3-manylinux_2_34_aarch64.whl |
|---|---|
| Size | 1.8 MB |
| Tags | CPython 3.8 Linux glibc 2.34+ ARM64 abi3 |
|
SHA-256 checksum How to use checksums |
ee17a86f6915b5837e2cfb0d11148cdb68aa1965e2cebcccaf4375979f5720e8
|
|
BLAKE2b-256 checksum How to use checksums |
e87033d088b818ed378419dc43785f18f16a91019dda38e8d2dc36c0ee9bfa84
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.4
|
Release files / pelorus-0.0.8-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | pelorus-0.0.8-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
|---|---|
| Size | 2.3 MB |
| Tags | CPython 3.8 Linux glibc 2.17+ x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
7d86d5d55766de453109d1a67f88353b0f4aa0472a919df38805e3a13aff9ef9
|
|
BLAKE2b-256 checksum How to use checksums |
fbd71650a069510689603e0736095c045c36c7d1aa326ca357368c4990ecc493
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.4
|
Release files / pelorus-0.0.8-cp38-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl
| Download URL | pelorus-0.0.8-cp38-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl |
|---|---|
| Size | 1.7 MB |
| Tags | CPython 3.8 Linux glibc 2.17+ ARMv7l abi3 |
|
SHA-256 checksum How to use checksums |
a8719cc9764610a231a56ed99a50c21b6de54a4225d34b2c116fe07d5adeeb5b
|
|
BLAKE2b-256 checksum How to use checksums |
20bafac9b52e938545d302cd2d8fe27827ed5033b8df813057d8a663ed394075
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.4
|
Release files / pelorus-0.0.8-cp38-abi3-macosx_11_0_arm64.whl
| Download URL | pelorus-0.0.8-cp38-abi3-macosx_11_0_arm64.whl |
|---|---|
| Size | 1.8 MB |
| Tags | CPython 3.8 abi3 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
acc17cf5ac2603be67029530fc464b186fc5d22c17538e847a005889176071e2
|
|
BLAKE2b-256 checksum How to use checksums |
1c0c6041283bc2618b0d05bf444e8da2500c9168c900e8b1f0aad2d1333c45f0
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.4
|
Security for pelorus 0.0.8
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.