Skip to content

Verify DH.Panda inertial parameters #688

Open

Description

@petercorke

The doubt

DH/Panda.py's inertial parameters (m, r, I per link) were added in PR #294 (Antun Škurić / askuric, merged 2022-04-07, closing #278). Per the PR's own description, the values were "just a quick transfer" from the MATLAB Robotics Toolbox's mdl_panda.m into the Python DH model.

That's a reasonable thing to do for m (mass is a scalar, frame-independent), but r (CoM offset) and I (inertia tensor) are only meaningful relative to a specific link frame -- and DH link frames have their own specific axis-placement convention (origin/axis choice determined by the a/d/alpha parameters and the standard vs. modified DH rules). There's no stated verification in the PR that RTB-MATLAB's DH link frame for each Panda joint is placed identically to RTB-Python's for the same a/d/alpha/mdh values -- the two toolboxes could in principle place a link frame's origin or axis orientation differently for the same nominal DH parameters, which would make a directly-copied r/I silently wrong despite being real, plausible-looking numbers. This is exactly the same class of bug flagged in #686 (the risk of copying DH-frame data into a URDF model without accounting for the frame difference) -- raised here reflexively about whether the original DH port itself was ever actually checked, since apparently it wasn't at the time.

Cross-check against an independent source

robot_descriptions' Panda (loaded today via Frankie(), see #686/#687) has its own, independently-sourced inertial data -- not derived from MATLAB at all, and expressed in the URDF's own (differently-conventioned) link frames. If DH.Panda()'s ported values are frame-correct, DH.Panda() and Frankie() should predict essentially the same dynamics for the same physical robot at the same joint angles, despite being two structurally different models built from two independent sources.

Gravity-load torque (rne(q, 0, 0), default gravity) at four configurations (zero, qr, and two random poses):

qz:      DH  [ 0.     -3.4344  0.     -3.2572  0.      1.6942  0.    ]
         RD  [ 0.     -3.4344  0.     -3.2572  0.      1.6942  0.    ]   diff: 0

qr:      DH  [ 0.    -16.72   -0.2691  19.3268  0.5998  1.7526 -0.0032]
         RD  [ 0.    -16.72   -0.2691  19.3268  0.5998  1.7526 -0.0032]  diff: 0

random1: DH  [ 0.     -7.2826 -2.9838  16.6589  0.7844  1.7237 -0.0263]
         RD  [-0.     -7.2826 -2.9838  16.6589  0.7844  1.7237 -0.0263]  diff: 0

random2: DH  [ 0.    -24.9307 -1.137   13.1356  0.3285  1.2961 -0.021 ]
         RD  [-0.    -24.9307 -1.137   13.1356  0.3285  1.2961 -0.021 ]  diff: 0

Agreement to displayed precision (4 dp) at every configuration tried, including two arbitrary ones -- not just the "nice" poses. This stresses m/r heavily (gravity torque is fundamentally a mass-times-moment-arm quantity) but only weakly exercises I (the inertia tensor only shows up under velocity/acceleration, not static gravity load).

Full inertia matrix M(q) (which does stress I) at q = [0.3, -0.5, 0.2, -1.8, 0.4, 1.5, 0.6]:

  • Every off-diagonal term matches to the displayed precision (3 dp).
  • Diagonal terms match to within ~1% (largest: M[0,0] = 0.530 (DH) vs. 0.535 (RD), a 0.9% difference) -- small enough to plausibly be rounding/minor-revision differences between the MATLAB-era source data and robot_descriptions' source, not the signature of a structural frame-convention error (which would typically show up as a much larger discrepancy, a sign flip, or a non-symmetric/non-matching structure).

Conclusion so far, and what's not yet covered

This is fairly strong evidence DH.Panda()'s ported parameters are correctly expressed in RTB-Python's own DH frame convention, despite the port never having been explicitly checked for that at the time. Not yet covered:

  • Velocity-dependent (Coriolis/centrifugal) terms specifically, in isolation -- M(q) exercises I but not \dot{q}-dependent behavior.
  • A true third, independent reference (e.g. Pinocchio or MuJoCo loading the same URDF robot_descriptions uses) rather than only cross-checking two RTB-internal models against each other -- if both happened to share some RTB-specific convention quirk, this check wouldn't catch it. (The #636 comment thread has a precedent for this kind of MuJoCo cross-check, worth reusing here.)
  • Extreme/near-singular configurations.

xref #686 (the related URDF-Panda inertial-data gap, and where this doubt was first raised in the context of not porting DH data into URDF).

Activity

  1. added
    tech-debtKnown technical debt / deferred cleanup, not a live bug
    on Sep 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    tech-debtKnown technical debt / deferred cleanup, not a live bug

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions