Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/test-package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: ['3.8', '3.9', '3.10']
python-version: ['3.9', '3.10', '3.11', '3.12', '3.13']
steps:
- uses: actions/checkout@v2
- name: Set up Python ${{matrix.python-version}}
Expand Down
8 changes: 8 additions & 0 deletions pymlg/numpy/se3.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,14 @@ def odot(b):
X[0:3, 0:3] = SO3.odot(b[0:3])
X[0:3, 3:6] = b[3] * np.identity(3)
return X

@staticmethod
def ocircle(b):
b = np.array(b).ravel()
X = np.zeros((6, 4))
X[3:6, -1] = b[0:3]
X[0:3, :3] = SO3.odot(b[0:3])
return X
Comment on lines +168 to +175
Copy link

Copilot AI Apr 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ocircle is added on the NumPy SE3, but the project README states the user API should be the same across implementations (notably NumPy vs JAX). Currently pymlg/jax/se3.py (and torch) has odot but no ocircle, so this introduces an API mismatch. Either add ocircle to the other backends (at least JAX, per README) or update the API parity promise/documentation.

Suggested change
@staticmethod
def ocircle(b):
b = np.array(b).ravel()
X = np.zeros((6, 4))
X[3:6, -1] = b[0:3]
X[0:3, :3] = SO3.odot(b[0:3])
return X

Copilot uses AI. Check for mistakes.

@staticmethod
def adjoint(T):
Expand Down
24 changes: 24 additions & 0 deletions tests/numpy/test_se3.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
"""
Perform any other group-specific tests that are not part of the standard tests.
"""

from pymlg import SE3 as G
Copy link

Copilot AI Apr 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test module lives under tests/numpy/, but it imports SE3 from the top-level pymlg package (the C++ wrapper by default). To ensure this exercises the pure NumPy implementation and matches the pattern used by tests/numpy/test_standard_numpy.py, import SE3 from pymlg.numpy instead (and keep backend-specific tests in their respective folders).

Suggested change
from pymlg import SE3 as G
from pymlg.numpy import SE3 as G

Copilot uses AI. Check for mistakes.
import numpy as np

def test_odot():
p = np.array([0.1, 0.2, 0.3, 0.4])
x = np.array([0.1, 0.2, 0.3, 0.4, 0.5, 0.6])
X = G.odot(p)
assert X.shape == (4, 6)
assert np.allclose(G.wedge(x) @ p, X @ x)

def test_ocircle():
p = np.array([0.1, 0.2, 0.3, 0.4])
x = np.array([0.1, 0.2, 0.3, 0.4, 0.5, 0.6])
X = G.ocircle(p)
assert X.shape == (6, 4)
assert np.allclose(p.T @ G.wedge(x), x.T @ X)

if __name__ == "__main__":
test_odot()
test_ocircle()
Loading