Repository navigation
Commit 59f3a3c
authored
fix: SO3.RotatedVector returned identity for antipodal vectors (#201)
## Summary
`SO3.RotatedVector(v1, v2)` computes the rotation axis as `v1 x v2`.
That
cross product is zero whenever `v1` and `v2` are (anti)parallel, and the
existing singularity check (`abs(s) < tol * eps`) treats both cases
identically -- returning identity regardless:
```python
>>> from spatialmath import SO3
>>> SO3.RotatedVector([0, 0, 1], [0, 0, -1]) # should flip, not be identity
1 0 0
0 1 0
0 0 1
```
That's correct when `v1` and `v2` point the same way, but wrong when
they're antipodal (`v2 == -v1`) -- the correct answer there is a 180°
rotation about any axis perpendicular to `v1`, not identity.
- [x] Distinguish the two cases via the sign of `v1 . v2` at the
singularity.
- [x] The antipodal case uses the closed form for a 180° rotation about
a
unit axis `u` (`R = 2*u*u^T - I`), with `u` found by crossing `v1`
against whichever world axis it's least aligned with (so the cross
product used to find `u` is never itself degenerate).
- [x] Existing test coverage
(`tests/test_pose3d.py::test_rotatedvector`)
only covered the general and exact-same-direction cases -- added the
antipodal case there, parametrised over several different `v1` values.
Found this while building a `FromTo(start, end)` constructor for an
`Arrow` shape in a downstream package, which needs exactly this "rotate
a
reference axis to point along an arbitrary direction" operation and hit
the bug immediately for a direction pointing straight backward relative
to the reference axis.
## Test plan
- [x] Full suite: `pytest tests/` -- 342 passed
- [x] New antipodal-case test passes; confirmed it fails against the old
code (returns identity instead of a real rotation)
- [x] Confirmed the general-rotation and exact-same-direction cases are
unaffected (existing test assertions unchanged)1 parent c20408d commit 59f3a3c
2 files changed
Lines changed: 31 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
769 | 769 | | |
770 | 770 | | |
771 | 771 | | |
772 | | - | |
| 772 | + | |
| 773 | + | |
| 774 | + | |
| 775 | + | |
| 776 | + | |
| 777 | + | |
| 778 | + | |
| 779 | + | |
| 780 | + | |
| 781 | + | |
| 782 | + | |
| 783 | + | |
| 784 | + | |
| 785 | + | |
| 786 | + | |
| 787 | + | |
| 788 | + | |
| 789 | + | |
773 | 790 | | |
774 | 791 | | |
775 | 792 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
731 | 731 | | |
732 | 732 | | |
733 | 733 | | |
| 734 | + | |
| 735 | + | |
| 736 | + | |
| 737 | + | |
| 738 | + | |
| 739 | + | |
| 740 | + | |
| 741 | + | |
| 742 | + | |
| 743 | + | |
| 744 | + | |
| 745 | + | |
| 746 | + | |
734 | 747 | | |
735 | 748 | | |
736 | 749 | | |
| |||
0 commit comments