SE(3)-LIO Python bindings
Python bindings for the ROS-agnostic SE(3) LiDAR-Inertial Odometry C++ core.
Install
Linux x86_64 wheels are on PyPI (the C++ core is bundled in):
pip install se3-lio # add [viz] for the live Polyscope viewer
Build from source
The bindings link the C++ core, which needs OpenMP (libgomp); Eigen and Sophus
are fetched and compiled in. Build inside the project's ROS2 Docker image
(docker/ros2/), where OpenMP is available.
# inside the container, from the repo root
pip install --no-build-isolation -ve ./python/ # requires: pip install pybind11 scikit-build-core
# or, with build isolation (pulls build deps automatically):
pip install -ve ./python/
Usage (high-level API)
import numpy as np
from se3_lio import SE3LIO, SE3LIOConfig, load_node_params
config = SE3LIOConfig(downsample_resolution=0.5, max_iter=4, verbose=False)
odom = SE3LIO(config, lidar_extrinsic=np.eye(4))
# or load the ROS2 node's params.yaml (same mapping as lio_node.cpp):
params = load_node_params("config/ntu.yaml")
odom = SE3LIO(params["config"], params["extrinsic"])
# points: (N, 3) float xyz in the LiDAR frame
# point_times: (N,) float per-point time offset from frame start [s]
# imu: (M, 7) float rows of [t, ax, ay, az, gx, gy, gz]
state, cloud = odom.register_frame(points, point_times, imu, frame_stamp)
print(state.pose, state.vel, state.covariance) # cloud: (N,3) deskewed, body frame
register_frame mirrors the per-frame data path of the ROS2 node: it builds a
synced measurement, applies the LiDAR extrinsic, sorts points by relative
timestamp, and runs one estimatePose step. Set verbose=True to enable the
core's per-frame stdout logging (off by default).
CLI pipeline
se3_lio_pipeline runs odometry over a rosbag and writes a TUM trajectory — the
Python equivalent of the node, offline. The input format is auto-detected:
| input | format | LiDAR | reader |
|---|---|---|---|
| rosbag2 directory | ROS2 | Livox CustomMsg |
rosbag2_py |
*.bag file |
ROS1 | Ouster PointCloud2 |
rosbags |
# ROS2 / Livox (rosbag2 directory)
se3_lio_pipeline <rosbag_dir> --config my_rig.yaml --imu-topic /livox/imu --lidar-topic /livox/lidar \
--max-frames 300 --output results/
# ROS1 / Ouster (e.g. NTU VIRAL .bag)
se3_lio_pipeline eee_01.bag --config config/ntu.yaml \
--max-frames 1500 --output results/
# -> results/<bag>_se3lio.tum + a summary (frames, path length, final pose)
--config is a small YAML giving the LiDAR→IMU extrinsic (and, optionally,
topics + algorithm overrides); keys you omit fall back to the
SE3LIOConfig code defaults. The repo's config/*.yaml
cover our datasets — for your own rig, write just the extrinsic and pass the
topics on the CLI:
# my_rig.yaml -> sensors: { t_exts: [x,y,z], q_exts: [w,x,y,z] }
se3_lio_pipeline my.bag --config my_rig.yaml \
--imu-topic /my/imu --lidar-topic /my/points
Use --input-type ros2-livox|ros1-ouster to override auto-detection. It reads
the bag, reproduces the node's conversion + synchronization
(rosbag.py / ros1bag.py),
and runs OdometryPipeline over the frames. Use the same
pieces programmatically:
from se3_lio import load_node_params
from se3_lio.datasets import RosbagDataset
from se3_lio.pipeline import OdometryPipeline
p = load_node_params("config/ntu.yaml")
dataset = RosbagDataset(bag_dir, p["imu_topic"], p["lidar_topic"], p["min_range"])
pipeline = OdometryPipeline(dataset, p["config"], p["extrinsic"]).run()
pipeline.save_tum("traj.tum")
print(pipeline.summary())
Visualization (Polyscope)
se3_lio_pipeline --visualize opens a live Polyscope
viewer: the current scan (gravity-aligned world frame) and the trajectory, with
play/pause [space], step [N], center [C], and screenshot [S].
pip install se3-lio[viz] # adds polyscope
se3_lio_pipeline eee_01.bag --config config/ntu.yaml \
--max-frames 1500 --visualize
The viewer lives in se3_lio/viz/polyscope_viz.py
(PolyscopeVisualizer, lazily importing polyscope). It implements the pipeline
logger interface (log_frame), following KISS-ICP / GenZ-ICP's Polyscope viewers.
Visualization (Rerun)
--rerun-save writes a Rerun .rrd (open it in the viewer,
below): a 3D view (sliding submap, trajectory, sensor pose with TF axes,
camera-follow) plus scalar plots (linear/angular speed, compute time, CPU, RAM).
Logger: se3_lio/viz/rerun_logger.py.
pip install se3-lio[rerun] # adds rerun-sdk (pinned, see below)
se3_lio_pipeline eee_01.bag --config config/ntu.yaml --rerun-save out.rrd
Version: the [rerun] extra pins rerun-sdk==0.33.1, because .rrd
files are only guaranteed to open in a matching viewer version and the
logger uses version-specific APIs. Keep the viewer in lockstep — since the host
Python may be too old for a recent SDK, use a dedicated env:
conda create -n rerun033 python=3.11 -y
conda run -n rerun033 pip install rerun-sdk==0.33.1
conda run -n rerun033 rerun out.rrd # native viewer (matches the .rrd)
Alternatively serve the web viewer from the same SDK (rr.serve_web_viewer) so
no local install has to match. When upgrading rerun, bump the pin, fix any
logger API breaks, rebuild, and regenerate the .rrd (or rerun rrd migrate).
Raw binding
The _-prefixed names (se3_lio_pybind._SE3LIO, _SE3LIOConfig, _State) are
the raw binding the high-level API is built on.
import numpy as np
from se3_lio import se3_lio_pybind as lio
config = lio._SE3LIOConfig()
config.downsample_resolution = 0.5
config.max_iter = 4
odom = lio._SE3LIO(config, np.eye(4)) # second arg: 4x4 LiDAR->body extrinsic
# points: (N, 3) float64 xyz in the LiDAR frame
# point_times: (N,) float64 per-point time offset from frame start [s]
# imu: (M, 7) float64 rows of [t, ax, ay, az, gx, gy, gz]
state, cloud = odom._register_frame(points, point_times, imu, frame_stamp)
print(state.pose) # 4x4 SE(3) pose; cloud: (N,3) deskewed body-frame points
print(state.vel, state.bg, state.ba, state.grav)
print(state.covariance) # 18x18
Metadata
Release files for se3-lio 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| se3_lio-0.2.0.tar.gz | 23.7 kB | With provenance | Details for se3_lio-0.2.0.tar.gz |
Built distributions (wheels)
Total release size: 2.3 MB
Release files / se3_lio-0.2.0.tar.gz
| Download URL | se3_lio-0.2.0.tar.gz |
|---|---|
| Size | 23.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
d51c473f78ea42afeacb14a1d0404d84eb8d82d100f84b2c968ceef4d6392a94
|
|
BLAKE2b-256 checksum How to use checksums |
6b025e57d42cf55bd00695f801f74251655ae27181ec3e2d3a895b673b126200
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 4, 2026.
Transparency logRelease files / se3_lio-0.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | se3_lio-0.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
|---|---|
| Size | 459.7 kB |
| Tags | CPython 3.12 Linux glibc 2.17+ x86-64 |
|
SHA-256 checksum How to use checksums |
e3e3eb64b26377771072cfdb9ecb8120b1e110ee0a40c53fe473d13fb0d12b5e
|
|
BLAKE2b-256 checksum How to use checksums |
55c1248f577b76fda1e7bac3f95bebf4fee4f8e8a4a736348da3b6728d0711fa
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 4, 2026.
Transparency logRelease files / se3_lio-0.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | se3_lio-0.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
|---|---|
| Size | 458.7 kB |
| Tags | CPython 3.11 Linux glibc 2.17+ x86-64 |
|
SHA-256 checksum How to use checksums |
6f23b952dd71d9738b64a193e647f236f31d15356d41af34730463df424022e6
|
|
BLAKE2b-256 checksum How to use checksums |
aec9441fdb22acd22220ce95927126d45d4256a191609e84c61d832597cc81f7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 4, 2026.
Transparency logRelease files / se3_lio-0.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | se3_lio-0.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
|---|---|
| Size | 457.7 kB |
| Tags | CPython 3.10 Linux glibc 2.17+ x86-64 |
|
SHA-256 checksum How to use checksums |
7ca102cf748aa8993cd5c04b9c7b09dd251be897f069bd6b0bbeb557eb59d835
|
|
BLAKE2b-256 checksum How to use checksums |
56cf0afe6e380db20280c7e7a0e9f5bff97f70ee58c104740a99e4835d8e83af
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 4, 2026.
Transparency logRelease files / se3_lio-0.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | se3_lio-0.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
|---|---|
| Size | 458.2 kB |
| Tags | CPython 3.9 Linux glibc 2.17+ x86-64 |
|
SHA-256 checksum How to use checksums |
f0936498050c61a3145cf494bf88cf748ed23ffad2a13e27e68b4627b33263c3
|
|
BLAKE2b-256 checksum How to use checksums |
c7b12c41bae5881271d16a708750c20b1390b7efaca77780a4f4e68f7966ba58
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 4, 2026.
Transparency logRelease files / se3_lio-0.2.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | se3_lio-0.2.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
|---|---|
| Size | 458.5 kB |
| Tags | CPython 3.8 Linux glibc 2.17+ x86-64 |
|
SHA-256 checksum How to use checksums |
1346d225fa943f7c36d108c3db9d437febf3442bdb0c32eb49fac4fecb99ba4f
|
|
BLAKE2b-256 checksum How to use checksums |
40bbf599bb49c3f7dcf6e35a8dc4ce2e6b2acd7d0437e47e345b4e60e073b167
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 4, 2026.
Transparency logSecurity for se3-lio 0.2.0
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.
Full provenance
All 6 files in this release have been uploaded with provenance metadata.
Attestation for se3_lio-0.2.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 4, 2026.
Transparency logA 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.