Skip to main content

lieplusplus_py

Swarm Systems Lab Python lieplusplus library

⚠️ Warning: This project is a work in progress.

Installation

pip install lieplusplus_py

Python Lie++ API Documentation

SO(3) - 3D Rotations

import numpy as np
from lieplusplus import SO3

# --- Constructors ---
R = SO3()                               # Identity rotation
R = SO3([1, 0, 0, 0])                   # Quaternion [w, x, y, z]
R = SO3(np.eye(3))                      # Rotation matrix (3×3)
R = SO3([0.1, 0.2, 0.3])                # Rotation vector (exp map)
R = SO3([1, 0, 0], [0, 1, 0])           # Rotation sending u -> v
R = SO3.random()                        # Random rotation

# --- Group operations ---
R3 = R1 * R2         # Compose rotations
v_rot = R * v        # Rotate a 3-vector
M_rot = R * M        # Rotate a 3×3 matrix

# --- Lie-theoretic operations (static) ---
u  = SO3.log(R)          # R^3 log-coordinate
R2 = SO3.exp(u)          # Exponential map
U  = SO3.wedge(u)        # 3×3 skew-symmetric matrix
u2 = SO3.vee(U)          # Vector from skew matrix
u0 = SO3.tangent_zero()  # Zero element of so(3)

# --- Jacobians ---
J    = SO3.leftJacobian(u)
Jinv = SO3.invLeftJacobian(u)

# --- Accessors ---
R.asMatrix()      # 3×3 rotation matrix
R.Adjoint()       # 3×3 Adjoint matrix
R.inv()           # Inverse rotation
R.q()             # Quaternion [w, x, y, z]

SE(3) - Poses

import numpy as np
from lieplusplus import SE3, SO3

# --- Constructors ---
T = SE3()                                 # Identity pose
T = SE3(R, t)                             # SO(3) + translation vector
T = SE3(np.eye(4))                        # Full 4×4 pose matrix
T = SE3([0.1, 0.2, 0.3], [1, 2, 3])       # Rotation vector + translation
T = SE3.random()                          # Random pose

# --- Group operations ---
T3 = T1 * T2       # Compose poses
p_world = T * p    # Transform a 3D point

# --- Lie-theoretic operations (static) ---
u  = SE3.log(T)        # R^6 tangent vector
T2 = SE3.exp(u)
U  = SE3.wedge(u)
u2 = SE3.vee(U)
u0 = SE3.tangent_zero()

# --- Accessors ---
T.asMatrix()       # 4×4 transformation matrix
T.Adjoint()        # 6×6 Adjoint matrix
T.inv()            # Inverse pose
T.R()              # Rotation (SO3)
T.q()              # Quaternion
T.translation()    # 3D translation vector

SE_2(3) - Extended Poses

import numpy as np
from lieplusplus import SE3_2, SO3

# --- Constructors ---
X = SE3_2()                               # Identity extended pose
X = SE3_2(R, [v, p])                      # Rotation + [velocity, position]
X = SE3_2(R, [np.zeros(3), np.ones(3)])   # Example
X = SE3_2.random()                        # Random extended pose

# --- Group operations ---
X3 = X1 * X2

# --- Lie-theoretic operations (static) ---
u  = SE3_2.log(X)       # R^9 tangent vector
X2 = SE3_2.exp(u)
U  = SE3_2.wedge(u)
u2 = SE3_2.vee(U)
u0 = SE3_2.tangent_zero()

# --- Accessors ---
X.asMatrix()    # 5×5 extended matrix
X.Adjoint()     # 9×9 Adjoint matrix
X.inv()         # Inverse extended pose
X.R()           # Rotation (SO3)
X.v()           # Velocity vector
X.p()           # Position vector

Array operators

The group classes above are object-oriented and single-element by design: the algebra of one robot rarely needs vectorization. Calling them from Python in a loop is dominated not by the arithmetic (tens of nanoseconds) but by the pybind boundary crossing (~1-1.5 us per call), which a loop over N entities pays N times.

So the same maths is also exposed as plain functions on numpy arrays, crossing into C++ once per call:

import numpy as np
import lieplusplus as lpp

xi = np.random.normal(size=(1000, 3)) * 0.01
R = lpp.so3_exp(xi)                 # (1000, 3, 3)
R = lpp.so3_retract(R, xi)          # R * exp(xi), the integration primitive

Measured on SO(3) retraction: ~3 us/entity for a Python loop vs ~0.04 us/entity (~68x at N=1000), and faster than an equivalent vectorized NumPy implementation, since the C++ loop materializes no temporaries.

One function, any input

There is no separate batch API to choose. Each operator is shape-polymorphic, and takes whatever array you happen to have:

lpp.so3_exp(v)                          # (3,)     -> (3, 3)      one element
lpp.so3_exp(v_stack)                    # (N, 3)   -> (N, 3, 3)   or a stack

lpp.so3_retract(one_R, tangents)        # (3,3) x (N,3) -> (N,3,3)   leading axis broadcasts N vs 1
lpp.so3_retract(R, tangents, out=R)     # writes in place, allocating nothing

lpp.so3_exp(fortran_or_float32_or_list) # any layout/dtype converts - no ascontiguousarray needed
lpp.so3_log(SO3.random())               # group objects work too (via __array__)

out= accepts any writable array of the right shape. A C-contiguous float64 buffer is written directly (zero copy - the fast path an integrator wants); anything else (an F-ordered array, a slice, a float32 buffer) goes through a temporary and is copied back, so the result always lands in your array. It is never silently discarded.

Shape errors name the operator and the argument:

so3_exp: argument 'x' must have shape (3) or (N, 3), got (4, 5)
so3_retract: leading dimensions do not broadcast, got 4 and 3

Available operators

SO(3) shapes (one element, or N of them)
so3_exp / so3_log (3,) -> (3,3) / (3,3) -> (3,)
so3_inv (3,3) -> (3,3)
so3_compose (3,3) x (3,3) -> (3,3)
so3_retract (3,3) x (3,) -> (3,3)
so3_rotate (3,3) x (3,) -> (3,)
so3_right_jacobian / so3_inv_right_jacobian (3,) -> (3,3)
SE(3) shapes (one element, or N of them)
se3_exp / se3_log (6,) -> (4,4) / (4,4) -> (6,)
se3_inv (4,4) -> (4,4)
se3_compose (4,4) x (4,4) -> (4,4)
se3_retract (4,4) x (6,) -> (4,4)
se3_transform (4,4) x (3,) -> (3,)

Adding an operator

The machinery lives in src/pybind_batch.hpp and is library-agnostic - it only assumes fixed-size Eigen types in and out, so it can be dropped into any pybind11 project. Adding an operator is one line; shape checking, broadcasting, out=, layout conversion and error messages come for free:

namespace pb = pybind_batch;

pb::def_unary<Vec3d, Matrix3d>(m, "so3_exp",
    [](const Vec3d& u) { return SO3d::exp(u).asMatrix(); }, "Exponential map.");

pb::def_binary<Matrix3d, Vec3d, Matrix3d>(m, "so3_retract",
    [](const Matrix3d& R, const Vec3d& u) { return (SO3d(R) * SO3d::exp(u)).asMatrix(); },
    "Right retraction R*exp(u).");

The element types determine the array shapes: Vec3d means (3,) or (N, 3), Matrix4d means (4, 4) or (N, 4, 4).

Note. The array operators are free functions (lpp.so3_exp) rather than methods on the classes (SO3.exp) because the two have different contracts. SO3.exp accepts a (3,) vector and a (3,1) column - convenient for one element, but (3,1) would be ambiguous with a stack of 3 under batching. The free functions are strict about rank instead, which is what lets a single name serve one element and a million.

License

MIT

Metadata

Release files for lieplusplus-py 0.7.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for lieplusplus-py 0.7.0
File Size Uploaded
lieplusplus_py-0.7.0.tar.gz 88.6 kB Details

Built distributions (wheels)

Table of built distributions (wheels) for lieplusplus-py 0.7.0
File Interpreter ABI Platform
lieplusplus_py-0.7.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl CPython 3.14 CPython 3.14 Linux glibc 2.28+ x86-64, Linux glibc 2.27+ x86-64 Details
lieplusplus_py-0.7.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl CPython 3.13 CPython 3.13 Linux glibc 2.27+ x86-64, Linux glibc 2.28+ x86-64 Details
lieplusplus_py-0.7.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl CPython 3.12 CPython 3.12 Linux glibc 2.28+ x86-64, Linux glibc 2.27+ x86-64 Details

Total release size: 6.3 MB

Release files / lieplusplus_py-0.7.0.tar.gz

Download URL lieplusplus_py-0.7.0.tar.gz
Size 88.6 kB
Tags Source
SHA-256 checksum
How to use checksums
7821c7d40cc81dcff979bdc83d16fbf934ddea207844d11a10a169e6e3d835aa
BLAKE2b-256 checksum
How to use checksums
adc963141b0e045dec31acef0fc7943cba75591c5d059ba75b7d37fb33d9aad0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.6

Release files / lieplusplus_py-0.7.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl

Download URL lieplusplus_py-0.7.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Size 2.1 MB
Tags CPython 3.14 Linux glibc 2.27+ x86-64 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
ea7241a72fb292f3deabcaca10f8fc194e1ada25ebed73ad0701726dd1db87ac
BLAKE2b-256 checksum
How to use checksums
39f70940d4f0384e421b114e534fd7102186d395b58a3cbc4f8a0bcdf371e15b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.6

Release files / lieplusplus_py-0.7.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl

Download URL lieplusplus_py-0.7.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Size 2.1 MB
Tags CPython 3.13 Linux glibc 2.27+ x86-64 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
ad589eb94474fe85d897f384c87b98fc22d354a68a5652470ca8d8ebbfaea2a9
BLAKE2b-256 checksum
How to use checksums
13977c0e484d268b58d2837070fe0d1eaac1ca676d0936727f09429186f74710
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.6

Release files / lieplusplus_py-0.7.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl

Download URL lieplusplus_py-0.7.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Size 2.1 MB
Tags CPython 3.12 Linux glibc 2.27+ x86-64 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
32197e1a8b3b4989ec0d426c4c88bbd7e099210b3bc3fa656fdbf1f7aadc47a7
BLAKE2b-256 checksum
How to use checksums
12e0742b9ab544889fc080813ced2ec18a442e7ef9f9720dddbb13b013fae18c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.6

Release history Release notifications | RSS feed

This release

0.7.0 This release

4 release files

0.6.1

4 release files

0.6.0

4 release files

0.5.1

4 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page