Skip to content

feat(dynamics): payload_capacity() replaces pay() and paycap() - #881

Merged
petercorke merged 4 commits into
mainfrom
feat/payload-capacity-v2
Oct 22, 2026
Merged

petercorke merged 4 commits into
mainfrom
feat/payload-capacity-v2

Conversation

@petercorke

Copy link
Copy Markdown
Owner

Adds payload_capacity() and removes pay() and paycap(), which it replaces.

payload_capacity(q, tau_m, w, frame="base"): for each configuration (row of q), the multiple of the wrench w that each joint can support without exceeding its torque limit, a matrix of shape (m, n). Each entry is a positive number, inf if the joint has no part in it, or nan if gravity alone is beyond the limit; the minimum over the joints is the capacity and its argmin is the limiting joint. If w is the weight of a 1 kg mass the answer is in kg.

  • tau_m is (n,) or (1,n) of maxima (the minimum is the negative), or (2,n) of minima then maxima.
  • w is a 6-vector in the base frame (frame="base", default) or the end-effector frame, including the tool (frame="ee"). The Jacobian function is chosen once before the loop. Any other value raises ValueError.
  • The motor torque that holds the robot and a payload s·w is gravload − s·Jᵀw, since w is the wrench the payload applies to the robot. This sign is checked against physics that does not use the method (below), and it matters for asymmetric limits.
  • Derived from the MATLAB pay and paycap by Bryan Moutrie (@au-phiware), credited in the docstring. The docstring has an example, as code and a .. plot::, of the Puma 560 along a line.

Removed: pay() (it was -J.T @ w, a poor name) and paycap() (its docstring did not match what it returned, Issue #728, and its test was skipped). These are public methods, so this is a breaking change; the replacement is payload_capacity, and the limits layout differs from paycap's (n, 2) with the maximum first. No ! in the title, as agreed for this repository.

Tests (tests/test_payload_capacity.py, 20): the reference is a real mass on the last link, whose gravity load comes from the recursive Newton-Euler dynamics and does not use the method, for the Puma 560 and the Panda with symmetric and asymmetric limits: at 0.999 of the capacity every joint is within its limit, and at 1.01 of it one is not. Also that a mass adds −Jᵀw to the gravity load, the inf and nan cases, a trajectory, a single q, the limit forms, bad shapes and a bad frame, and that a wrench in the end-effector frame equals the same wrench rotated into the base frame.

Changes numerical results or public behaviour: yes, new method; pay and paycap are removed.

Ran: the payload, DHRobot, ERobot, BaseRobot and hasdynamics tests (228 passed, 1 skipped) and mypy (clean, 165 files). Not run: the docs build; the docs/notebooks/payload.ipynb notebook is not part of this PR.

Written by Peter Corke with Claude Code, which fixed a sign error in the first version (the gravity term had the wrong sign relative to the payload term), added frame, and wrote the tests.

🤖 Generated with Claude Code

payload_capacity(q, tau_m, w, frame="base") is the multiple of a wrench w that each joint
can support, for each configuration in q, for joint torque limits tau_m: a positive
number, inf if the joint has no part in it, and nan if gravity alone is beyond the limit.
The wrench is in the base frame, or "ee" for the end-effector frame.  Limits are (n,) or
(1,n) maxima, or (2,n) minima then maxima.

pay() is removed, it is -J.T @ w and was a poor name, and paycap() is removed, which
returned a tuple when its docstring said otherwise and was skipped in its test.  Both
were ported from the MATLAB functions of Bryan Moutrie, credited in the docstring.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@codacy-production

codacy-production Bot commented Oct 21, 2026 •

Copy link
Copy Markdown

Not up to standards ⛔

🔴 Issues 12 high

Alerts:
⚠ 12 issues (≤ 0 issues of at least minor severity)

Results:
12 new issues

Category Results
ErrorProne 1 high
Security 11 high

View in Codacy

🟢 Metrics 15 complexity · 0 duplication

Metric Results
Complexity 15
Duplication 0

View in Codacy

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

@petercorke
petercorke enabled auto-merge (squash) October 21, 2026 23:36
@petercorke
petercorke merged commit f7d5548 into main Oct 22, 2026
22 of 23 checks passed
@github-actions github-actions Bot mentioned this pull request Oct 22, 2026
@codecov

codecov Bot commented Oct 22, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 0% with 25 lines in your changes missing coverage. Please review.
✅ Project coverage is 0.00%. Comparing base (aaf0902) to head (7adf729).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
src/roboticstoolbox/robot/Dynamics.py 0.00% 25 Missing ⚠️
Additional details and impacted files
@@          Coverage Diff          @@
##            main    #881   +/-   ##
=====================================
  Coverage   0.00%   0.00%           
=====================================
  Files        146     146           
  Lines      17200   17164   -36     
=====================================
+ Misses     17200   17164   -36     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@petercorke
petercorke deleted the feat/payload-capacity-v2 branch October 22, 2026 04:37
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.

1 participant