Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Capsule class with inertia calculation method #163

Merged
merged 18 commits into from
Nov 7, 2020

Conversation

scpeters
Copy link
Member

@scpeters scpeters commented Oct 13, 2020

This package has classes for several shapes (Box, Cylinder, Sphere) as well as methods in MassMatrix3 for computing inertial properties of these shapes assuming uniform density. This pull request adds a new Capsule shape class that is like a Cylinder with hemispheres capping each end. Methods for computing the inertial properties of a Capsule are added to MassMatrix3 and validated in unit tests by comparing to the formulae used by Open Dynamics Engine.

Update: I've removed the MassMatrix3 methods and removed the Quaternion parameter from the Capsule class.

Copy the Cylinder class and unit test to create Capsule,
which is similar to the Cylinder but with hemispheres
capping either end of the cylinder.

Signed-off-by: Steve Peters <[email protected]>
Signed-off-by: Steve Peters <[email protected]>
@chapulina chapulina added enhancement New feature or request 🏢 edifice Ignition Edifice 🏰 citadel Ignition Citadel 📜 blueprint Ignition Blueprint 🔮 dome Ignition Dome labels Oct 13, 2020
Copy link

@EricCousineau-TRI EricCousineau-TRI left a comment

Choose a reason for hiding this comment

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

Looks good at a high-level. The API here seems to be highly redundant and coupled (e.g. shapes + offsets, inertia computations, etc.), but understandably it'd be hard to refactor any time soon.

Made some picky comments, but nothing blocking.

Is there also a high-level issue that this is aiming towards?
e.g. gazebosim/sdformat#176 gazebosim/sdformat#376

include/ignition/math/Capsule.hh Outdated Show resolved Hide resolved
include/ignition/math/Capsule.hh Outdated Show resolved Hide resolved
/// equivalent to a cylinder with capped with hemispheres. Radius and
/// length are in meters. See Material for more on material properties.
/// By default, a capsule's length is aligned with the Z axis. The
/// rotational offset encodes a rotation from the z axis.

Choose a reason for hiding this comment

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

It would be good to also state that the radius defines the circle when the capsule intersects with G's XY-plane.

include/ignition/math/MassMatrix3.hh Outdated Show resolved Hide resolved
include/ignition/math/MassMatrix3.hh Outdated Show resolved Hide resolved
@EricCousineau-TRI
Copy link

Also, the shapes defined in ign-math seem like they have a shared contract, but there doesn't seem to be any form of contract enforcement (e.g. dynamic inheritance, static inheritance / mixins with CRTP, etc.).

Am I missing something there?

@scpeters
Copy link
Member Author

Is there also a high-level issue that this is aiming towards?
e.g. osrf/sdformat#176 osrf/sdformat#376

it's in support of gazebosim/sdformat#376, along with gazebosim/sdformat#389

@scpeters
Copy link
Member Author

The API here seems to be highly redundant and coupled (e.g. shapes + offsets, inertia computations, etc.), but understandably it'd be hard to refactor any time soon.

It took me a little while to remember, but I remembered a bit of the original intent behind this design. We added the MassMatrix3 class (started in 2.3.0 and a bit more in 2.4.0) before adding the shape classes like Sphere and Cylinder (5.0.0). The MassMatrix3 class is intended to represent a scalar mass and a 3x3 moment of inertia matrix. If you diagonalize the inertia matrix to get the principal moments of inertia and the orientation of its principal axes, then you can use these values along with its mass to compute the dimensions and orientation of a box of uniform density that has equivalent inertial properties (see MassMatrix3::EquivalentBox from 2.4.0 for reference).

That EquivalentBox is used to visualize the moment of inertia in Gazebo. After adding EquivalentBox, we added its inverse SetFromBox as well as SetFromSphere and SetFromCylinderZ for good measure (we also use these in gazebo). The quaternion parameter was added to SetFromBox for symmetry with EquivalentBox and to SetFromCylinderZ to accommodate cylinders with different axis alignments.

When the shape functions were added in 5.0.0, they included a Quaternion parameter in the constructor, and in retrospect, I think they might be confusing things more than helping. I'll remove them from the Capsule constructors; they'll still be in the other shape classes, but we'll need a major version bump to get rid of those

I'll think further on whether we need MassMatrix3::SetFromCapsuleZ functions or not; if not I'll just put the math in the Capsule class

This is more elegant than the MassMatrix3::SetFromCapsuleZ
helper functions.

Signed-off-by: Steve Peters <[email protected]>
@scpeters
Copy link
Member Author

I'll think further on whether we need MassMatrix3::SetFromCapsuleZ functions or not; if not I'll just put the math in the Capsule class

I thought about it, and we can use the Inertial class directly from Capsule, which we can't do from MassMatrix3, so I've done it in 0ac1488, and it's a bit more elegant

I've removed the MassMatrix3::SetFromCapsuleZ helper functions in d9c8d73

@scpeters scpeters changed the title Add Capsule class and MassMatrix3 methods Add Capsule class with inertia calculation method Oct 19, 2020
@chapulina chapulina self-requested a review October 26, 2020 18:40
Copy link
Contributor

@chapulina chapulina left a comment

Choose a reason for hiding this comment

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

Looks good to me, I just have a question about the hemispheres, but I'm trusting the test that the math checks out.

include/ignition/math/Capsule.hh Outdated Show resolved Hide resolved
include/ignition/math/detail/Capsule.hh Outdated Show resolved Hide resolved
include/ignition/math/detail/Capsule.hh Show resolved Hide resolved
@scpeters
Copy link
Member Author

Also, the shapes defined in ign-math seem like they have a shared contract, but there doesn't seem to be any form of contract enforcement (e.g. dynamic inheritance, static inheritance / mixins with CRTP, etc.).

Am I missing something there?

no I don't think you're missing anything. I think the shape objects have similar API's but it's not enforced

@EricCousineau-TRI
Copy link

Aye, sounds good. Minor concern is that the Capsule API may now deviates from others (given that it computes its own inertia, rather than kinda doing some psuedo static-double-dispatch things).

include/ignition/math/Capsule.hh Show resolved Hide resolved
include/ignition/math/Capsule.hh Outdated Show resolved Hide resolved
include/ignition/math/Capsule.hh Outdated Show resolved Hide resolved
include/ignition/math/Capsule.hh Outdated Show resolved Hide resolved
include/ignition/math/Capsule.hh Outdated Show resolved Hide resolved
include/ignition/math/detail/Capsule.hh Show resolved Hide resolved
include/ignition/math/detail/Capsule.hh Outdated Show resolved Hide resolved
{
/// \brief Default constructor. The default radius and length are both
/// zero.
public: Capsule() = default;
Copy link
Contributor

Choose a reason for hiding this comment

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

What do you think about not providing a default constructor? That way the only time we would have invalid Capsule objects would be if the input length and radius values are invalid.

Copy link
Member Author

Choose a reason for hiding this comment

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

I like having the default constructor. If you want to create a shape without remembering the order of the arguments in the constructor:

Capsuled capsule;
capsule.SetLength(length);
capsule.SetRadius(radius);

if other people don't like it, we can remove it, but I'm inclined to keep it

Copy link
Contributor

Choose a reason for hiding this comment

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

If I put on my pedantry hat, the "right" way to do what @scpeters is suggesting would be to have something like a Capsule::Builder class that lets you fill in the information necessary to build a Capsule object, and then you could call build() on it (or something similar) and it constructs a capsule for you, perhaps throwing an exception if the parameters are invalid (e.g. radius <= 0, length <= 0).

Some would (fairly) argue that's overkill for this use case, but the more I've had to deal with writing production-quality code, the more I've been feeling it's worth the effort to make every assumption explicit inside the code itself.

src/Capsule_TEST.cc Show resolved Hide resolved
* Remove destructor
* Remove duplicate SetLength method
* Add tparam doc-string
* Fix comment about parameter that has been removed

Signed-off-by: Steve Peters <[email protected]>
With the prior API that passes a reference to a MassMatrix3,
it is unclear whether the object is mutated when the parameters
are invalid. Using std::optional removes the ambiguity and
ensures that invalid values are not returned.

Signed-off-by: Steve Peters <[email protected]>
@scpeters scpeters merged commit b084f66 into gazebosim:ign-math6 Nov 7, 2020
@scpeters scpeters deleted the capsule branch November 7, 2020 01:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
📜 blueprint Ignition Blueprint 🏰 citadel Ignition Citadel 🔮 dome Ignition Dome 🏢 edifice Ignition Edifice enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants