Batched PyTorch solvers for group synchronization: recover absolute poses from noisy pairwise relatives.
Given a connected measurement graph and relatives
The solution is unique up to a global left action
SpectralSO3Sync is a torch.nn.Module around the solver. examples/outlier_weights.py trains a tiny MLP to downweight junk edges; the eigenvector step is unchanged. That helps on synthetic outliers. It does not replace the linear algebra, and oracle weights (if you already knew the bad edges) are still much better.
uv sync --extra devimport torch
from group_sync_torch import (
so3,
erdos_renyi_edges,
rotations_from_absolutes,
spectral_sync,
refine_rotations,
mean_geodesic_error,
)
n = 24
R_true = so3.rand_uniform(n)
src, dst = erdos_renyi_edges(n, p=0.35)
graph = rotations_from_absolutes(R_true, src, dst, noise_std=0.2)
R_hat = spectral_sync(graph)
R_hat = refine_rotations(graph, R_hat)
err_deg = mean_geodesic_error(R_hat, R_true).item() * 180 / torch.pi
print(f"mean geodesic error: {err_deg:.2f} deg")uv run examples/synthetic_so3.py
uv run examples/noise_sweep.py
uv run examples/outlier_weights.py
uv run pytestsrc/group_sync_torch/
so3.py / se3.py exp, log, hat/vee, projection
graph.py directed relative measurements
spectral.py connection-Laplacian solver
layers.py nn.Module wrapper (grads into relatives)
refine.py geodesic gradient steps
se3_sync.py two-stage rigid motions
metrics.py left-gauge alignment and error
MIT

