Skip to content

Conversation

@Ipuch
Copy link

@Ipuch Ipuch commented Oct 23, 2025

Thanks for taking the time to make and fill out this pull request! I'll be open to any enhancement. Thanks to @MegMll and @LucasJoseph for helping out on this one !

Description

In this PR, we introduce the new ellipsoid joint to pinocchio. This implementation is based on the paper:

Seth A, Sherman M, Eastman P, Delp S. Minimal formulation of joint motion for biomechanisms. Nonlinear Dyn. 2010 Oct 1;62(1):291-303. doi: 10.1007/s11071-010-9717-3. PMID: 21170173; PMCID: PMC3002261.

available here. It has been adapted to the formalism of Pinocchio. It allows defining an ellipsoid on which a solid can glide and rotate with respect to the "normal" of the ellipsoid. The joint is driven as function of angles XYZ, meaningful for biomechanists and thoraco-scapular joint.

Capture.video.du.2025-11-06.23-35-48.webm

Checklist

  • I have run pre-commit run --all-files or pixi run lint
  • I have performed a self-review of my own code
  • I have commented my code where necessary
  • I have made corresponding changes to the doxygen documentation
  • I have added tests that prove my fix or feature works
  • I have updated the CHANGELOG or added the "no changelog" label if it's a CI-related issue
  • I have updated the README credits section
  • We have run PINNOCHIO_EIGEN_NO_MALLOC

Extra To-dos

  • no reverse mode with ellipsoid joint for model-graph
  • Finite differences for motion subspace derivative Sdot, as we have some non-zero terms in Sdot, we (with @MegMll) feel like it would be a good idea to have a test to check Sdot with finite differences as for S.

We have tested that the ellipsoid joint behave as a ZYX spherical joint when radii are zeros. We have to test the translation part as well with a composite joint.

  • Rotation part - The ellipsoid joint behaves as a ZYX spherical joint when radii are zeros.
  • Translation part - Test the ellipsoid joint with a composite joint to check the translation part.
  • Add doc on how to implement a joint in doc/e-development

Linting

  • pre-commit run --all-files

Question

  • Should we add references in the code for what we have implemented ? Doc added in `joint-ellipsoid.hxx

  • To make it pass I had to modify second Dim and second MaxDim to 1 in this line :

    typedef Eigen::Matrix<Scalar, Dim, Dim, Options, MaxDim, MaxDim> ReturnType;

  • Model-graphs, need to make sure the build of the graph happens the expected way for ellipsoid joint -> we can't reverse the joint ellipsoid because the translations and the motion subspace are tight to the parent frame, and it would necessitate to have a new joint definition to get the transform in the child frame. To say it simply, we can't just modify q to express the spatial transform in the child frame.

Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👋 Hi,
This is a reminder message to assign an extra build label to this Pull Request if needed.
By default, this PR will be build with minimal build options (URDF support and Python bindings)
The possible extra labels are:

  • build_collision (build Pinocchio with coal support)
  • build_casadi (build Pinocchio with CasADi support)
  • build_autodiff (build Pinocchio with CppAD support)
  • build_codegen (build Pinocchio with CppADCodeGen support)
  • build_extra (build Pinocchio with extra algorithms)
  • build_mpfr (build Pinocchio with Boost.Multiprecision support)
  • build_sdf (build Pinocchio with SDF parser)
  • build_accelerate (build Pinocchio with APPLE Accelerate framework support)
  • build_all (build Pinocchio with ALL the options stated above)

Thanks.
The Pinocchio development team.

@Ipuch Ipuch force-pushed the topic-ellipsoid branch 4 times, most recently from bf2867e to 31f949c Compare November 3, 2025 17:25
@Ipuch Ipuch force-pushed the topic-ellipsoid branch 3 times, most recently from 0ea8243 to 4733edb Compare November 13, 2025 16:35
@Ipuch Ipuch marked this pull request as ready for review November 13, 2025 18:02
};
typedef JointDataEllipsoidTpl<Scalar, Options> JointDataDerived;
typedef JointModelEllipsoidTpl<Scalar, Options> JointModelDerived;
// typedef JointMotionSubspaceTpl<3, Scalar, Options, 3> Constraint_t;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// typedef JointMotionSubspaceTpl<3, Scalar, Options, 3> Constraint_t;

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Copy link
Author

@Ipuch Ipuch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One last problem with ConstraintForceSetOp which does not compile.

};
typedef JointDataEllipsoidTpl<Scalar, Options> JointDataDerived;
typedef JointModelEllipsoidTpl<Scalar, Options> JointModelDerived;
// typedef JointMotionSubspaceTpl<3, Scalar, Options, 3> Constraint_t;
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@Ipuch Ipuch force-pushed the topic-ellipsoid branch 2 times, most recently from 0877a59 to 2644cc0 Compare December 8, 2025 14:40
forcing subspace with one column

finite diff for S

Sdot
Comment on lines +123 to +127
"radius_a", &JointEllipsoid::radius_a, "Semi-axis length in the x direction.")
.def_readwrite(
"radius_b", &JointEllipsoid::radius_b, "Semi-axis length in the y direction.")
.def_readwrite(
"radius_c", &JointEllipsoid::radius_c, "Semi-axis length in the z direction.")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would recommend changing the naming here. Something like radius_x or semi_axis_x. a, b, c is a bit meaningless.

{
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(Vector3Like, 3);
// Compute first 6 rows from first 2 columns
Eigen::Matrix<Scalar, 6, 1> result = S.template block<6, 2>(0, 0) * v.template segment<2>(0);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Eigen::Matrix<Scalar, 6, 1> result = S.template block<6, 2>(0, 0) * v.template segment<2>(0);
Eigen::Matrix<Scalar, 6, 1> result = S.template leftCols<2>() * v.template head<2>();

Comment on lines +413 to +419
/// @brief Default constructor. Creates a sphere (0.01, 0.01, 0.01).
JointModelEllipsoidTpl()
: radius_a(Scalar(0.01))
, radius_b(Scalar(0.01))
, radius_c(Scalar(0.01))
{
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The default constructor should not have such values. It is better to set everything to 0 or 1.

Comment on lines +166 to +168
double radius_a = 0.01;
double radius_b = 0.01;
double radius_c = 0.01;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Default values should be changed?

Copy link
Contributor

@jcarpent jcarpent left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @Ipuch @LucasJoseph and @MegMll for making this nice add-on to Pinocchio.
I made some minor remarks about member naming notably.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants