Skip to content

[DO NOT MERGE] Integration: PR backlog - #285

Closed
taughz wants to merge 50 commits into
masterfrom
integration/2026-11
Closed

taughz wants to merge 50 commits into
masterfrom
integration/2026-11

Conversation

@taughz

@taughz taughz commented Nov 5, 2026 •

Copy link
Copy Markdown
Collaborator

Do not merge this PR. It is a hub for integration testing the open PR backlog against internal RAI software. The branch stages the PRs listed below, one --no-ff merge commit per PR in merge order, so they can be tested together. Once that passes, the individual PRs are approved and merged to master in this order (ticking them off here), and this hub is closed.

The branch is rebuilt (force-pushed) whenever a contained PR changes or lands on master. Do not rebase it: that would flatten the per-PR merge commits.

Contained PRs (merge order)

High-priority PRs first, then the rest roughly oldest first, with related PRs kept adjacent. Simulated merges show no textual conflicts in this order.

RoboX2020 and others added 30 commits October 10, 2026 15:49
Added support for stacked numpy arrays in baseposelist.py.
… error

Added support for SE3 constructor with (N, 4, 4) NumPy array.
Add unit test for SE3 constructor with stacked array input.
…ating a second one

axes_logic reuses the current axes when the current figure has axes, but when
the current figure had none, as after a bare plt.figure(), it called
plt.figure() again.  Every "new plot" idiom (plt.figure() followed by a plot_xxx
call) therefore left an empty figure behind, most visible with the ipympl
backend where figures stay open in notebooks.

Put the axes in the empty current figure instead.  new=True still always makes a
new figure, a dimension mismatch still makes a new figure, and a current figure
that has axes is reused as before.

Add direct tests of axes_logic (there were none): the existing behaviour, and the
empty-current-figure cases.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Signed-off-by: 李永祺 <doribelove@gmail.com>
Signed-off-by: 李永祺 <doribelove@gmail.com>
The docstring was indented by an extra four spaces and a stray
'from typing import TYPE_CHECKING' line ended the runblock early,
which would render incorrectly in the docs. Restore the docstring
formatting to match the rest of the module; the lazy SymPy import
is unchanged.
The shape guard added with the stacked-array support rejected every
array whose shape differed from the class's internal value shape when
check=False. That broke accepted equivalent forms: Twist3 from a 4x4
SE(3)/se(3) matrix, Twist2 from a 3x3 SE(2)/se(2) matrix, and
Quaternion from a non-4-vector array, all of which the class _import
methods deliberately accept unchecked.

Only reject when a matrix pose class (SE3, SO3, SE2, SO2) gets a 3D
array whose per-matrix size is wrong: such an array can only be read
as a stack, so the mismatch is never a valid pose, whatever check is.
Single 2D arrays keep their historical check=False behavior.
Signed-off-by: 李永祺 <doribelove@gmail.com>
Every UnitQuaternion has a non-negative scalar part by construction
(qunit()), and interp1 always interpolates from the identity
quaternion, whose dot product with any unit quaternion is just that
quaternion's own scalar part. The negative-dot-product condition
`shortest` checks for to detect "the long way round" can therefore
never occur here -- confirmed empirically (2000 random compositions,
plus explicit UnitQuaternion([-1,0,0,0]) construction, all canonicalize
to non-negative scalar part).

Drops the dead branch, warns on shortest=True, documents why in a
docstring note, and pins the no-op behavior (identical results for
True/False, warns only when True) with a regression test.
Twist3.__mul__ raised a hard ValueError for any right operand it
didn't directly recognize, instead of returning NotImplemented -- so
Python never got the chance to fall back to right.__rmul__(left).
This made Twist3 * SpatialVelocity/Acceleration/Force/Momentum
unconditionally fail, even though SpatialVector.__rmul__ explicitly
documents supporting Twist3 alongside SE3.

Found while independently verifying #207 (SpatialForce/Momentum
coadjoint fix): that PR's Twist3 code path is correct but was
untestable through normal `*` syntax because of this bug.
Add a test to ensure scipy is not loaded when importing spatialmath.
Ad() was self.SE3().Ad() -- constructs a full validated SE3 object
just to immediately extract its array and discard the object. Computes
the same result directly (trexp then tr2adjoint, skipping the SE3
constructor/validation overhead): bit-identical output, ~1.4x faster.

No existing test covered Ad() at all; added one first (hand-verified
pure-rotation and pure-translation cases, plus a cross-check against
SE3.Ad() over 20 random transforms) and confirmed it passes unchanged
against both the old and new implementation.
…trings

Follow-up to the twist-sequence broadcasting change. A search for cut/paste
errors between Twist2 and Twist3 turned up some real bugs as well as text:

- isprismatic/isrevolute raised AttributeError on a sequence because they
  read .w/.v from the raw ndarrays in .data instead of the Twist elements.
- Twist2.__rmul had no trailing underscores so it was never called, and
  ``2 * Twist2`` silently fell through to UserList repetition.
- Twist3.__rmul__ used right.S, which is a list for a sequence, so scalar *
  Twist3 failed for sequences.
- Twist3.Rand used yrange[0] as the lower bound of the z range.

Docstrings: Twist2.SE2 said it returned SE3 and pointed at Twist3.exp (and
its degree-mode message named Twist3.exp); Twist2.__init__ said it built a
prismatic twist and swapped the moment/direction sizes; Twist2.isvalid
described a 6-vector/4x4; UnitRevolute said prismatic; Twist3.Rand described
SE3.Rand; Rx/Ry/Rz called their results SE(3)/SO(3) rotations; the
[omega, v] ordering note contradicted the [v, omega] data layout; exp()
documented a default of None and left a literal unterminated; the
``runblock:`` directives in __str__/__repr__ had a single colon (and their
examples would not have run once fixed). SE2.Rand's example used SE3.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
A twist is used both as the log of a pose (RVC, Modern Robotics) and as a
velocity (ROS Twist). They share the vector, the [v, w] layout and the
algebra, but nothing in the docstrings said so. Say so, point to
SpatialVelocity as the typed counterpart, and note which properties are
invariant to scaling the twist and which are not.

Twist2 had no class docstring, only __init__, so give it one.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…ib block

isnotebook() lived inside graphics.py's matplotlib try-block, so it vanished
when matplotlib was missing, and it reported False for Google Colab and
JupyterLite. RTB, MVTB and bdsim each grew their own copy as a result.

Add environment(), returning "terminal", "ipython", "jupyter", "colab" or
"jupyterlite", in a new matplotlib-free module, and make isnotebook() a thin
wrapper that is True for jupyter, colab and jupyterlite. smb.isnotebook is
still exported. Tests use a faked get_ipython/sys.modules/sys.platform.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Copilot AI added 2 commits November 5, 2026 08:59
Avoids a textual conflict with other PRs that add tests after the line
distance tests, and restores the executable bit on the test file, which
runs as a script.
@taughz taughz self-assigned this Nov 5, 2026
taughz added 18 commits November 5, 2026 10:04
The package is pure Python, so numpy is not needed to build it, and
numpy has deprecated oldest-supported-numpy. Build tools that do not
install arbitrary build requirements (for example rules_py's uv sdist
builder) fail on it.
…copied docstrings; document twist usages (builds on #248)
@taughz
taughz force-pushed the integration/2026-11 branch from 81c99fb to bcbec7b Compare November 5, 2026 15:05
@taughz taughz closed this Nov 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants