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

Unify RotationalInertia validity tests and exception messages. #22278

Open
wants to merge 7 commits into
base: master
Choose a base branch
from

Conversation

mitiguy
Copy link
Contributor

@mitiguy mitiguy commented Dec 6, 2024

This PR is work towards a unified and logical sequence for inertia validity checks.
This PR is specifically for RotationalInertia().
A subsequent one will follow for SpatialInertia() and its cousin in the Geometry class.

All of the testing for validity is delegated to one function, namely GetInvalidityReport().
It reports an empty string if all seems well, otherwise it returns a string with why the inertia is invalid.
This process will be repeated for each of three classes and provide a better mechanism for error handling and for ensuring that inertia validity checks provide consistently sensible messages.


This change is Reviewable

@mitiguy mitiguy force-pushed the unifyValidityTestAndMessagesRotationalInertia branch from a30eb7a to 5f32ba1 Compare December 18, 2024 01:47
@mitiguy mitiguy changed the title [WIP] Unify RotationalInertia validity tests and exception messages. Unify RotationalInertia validity tests and exception messages. Dec 19, 2024
Copy link
Contributor Author

@mitiguy mitiguy left a comment

Choose a reason for hiding this comment

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

Feature review +@sherm1

Reviewable status: LGTM missing from assignee sherm1(platform), needs at least two assigned reviewers, commits need curation (https://drake.mit.edu/reviewable.html#curated-commits), missing label for release notes (waiting on @mitiguy)

Copy link
Member

@sherm1 sherm1 left a comment

Choose a reason for hiding this comment

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

Feature :lgtm: pending some minor comments
+@SeanCurtis-TRI for platform review per rotation, please

Reviewed 3 of 3 files at r1, all commit messages.
Reviewable status: 2 unresolved discussions, LGTM missing from assignee SeanCurtis-TRI(platform), commits need curation (https://drake.mit.edu/reviewable.html#curated-commits), missing label for release notes (waiting on @mitiguy)


multibody/tree/rotational_inertia.h line 986 at r1 (raw file):

  // inequality. For symbolic type T, tests are rudimentary (e.g., test for NaN
  // moments or products of inertia).
  std::string GetInvalidityReport() const;

minor: should use more straightforward std::optional<std::string> rather than using an empty string as a bespoke signal.


multibody/tree/rotational_inertia.h line 986 at r1 (raw file):

  // inequality. For symbolic type T, tests are rudimentary (e.g., test for NaN
  // moments or products of inertia).
  std::string GetInvalidityReport() const;

minor: this name needs an upgrade. As I understand it, it is actually investigating this RotationalInertia for potential invalidity. The current name sounds like it is passively returning an existing report. Consider something that reflects the work being done better, .e.g. CheckValidity() or CheckValidityAndReportIfInvalid() or some such.

Copy link
Contributor

@SeanCurtis-TRI SeanCurtis-TRI left a comment

Choose a reason for hiding this comment

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

It's not quite complete. See below.

Reviewed 3 of 3 files at r1, all commit messages.
Reviewable status: 4 unresolved discussions, LGTM missing from assignee SeanCurtis-TRI(platform), commits need curation (https://drake.mit.edu/reviewable.html#curated-commits), missing label for release notes (waiting on @mitiguy)


multibody/tree/rotational_inertia.h line 986 at r1 (raw file):

Previously, sherm1 (Michael Sherman) wrote…

minor: this name needs an upgrade. As I understand it, it is actually investigating this RotationalInertia for potential invalidity. The current name sounds like it is passively returning an existing report. Consider something that reflects the work being done better, .e.g. CheckValidity() or CheckValidityAndReportIfInvalid() or some such.

How about, simply MakeValidityReport()? CreateValidityReport()?


multibody/tree/rotational_inertia.h line 1000 at r1 (raw file):

  template <typename T1 = T>
  typename std::enable_if_t<scalar_predicate<T1>::is_bool>
  ThrowIfNotPhysicallyValid(const char* func_name) {

BTW As long as you're here, you might consider the following:

Take all of this:

  // SFINAE for numeric types. See ThrowIfNotPhysicallyValidImpl().
  template <typename T1 = T>
  typename std::enable_if_t<scalar_predicate<T1>::is_bool>
  ThrowIfNotPhysicallyValid(const char* func_name) {
    ThrowIfNotPhysicallyValidImpl(func_name);
  }

  // SFINAE for non-numeric types -- does nothing;
  template <typename T1 = T>
  typename std::enable_if_t<!scalar_predicate<T1>::is_bool>
  ThrowIfNotPhysicallyValid(const char*) {}

and simply replace it with:

  // We don't attempt validation for T = Symbolic.
  void ThrowIfNotPhysicallyValid(const char* func_name) {
    if constexpr (scalar_predicate<T>::is_bool) {
      ThrowIfNotPhysicallyValidImpl(func_name);
    }
  }

The primary argument for not doing this in this PR is that you still have a number of old-school SFINAE stuff on other functions in the file, so rolling all of those into their own PR would be perfectly reasonable. But it seems that while you're messing around in these files, we can modernize and compact this code.


multibody/tree/rotational_inertia.cc line 225 at r1 (raw file):

    error_message = fmt::format("\nNaN detected in RotationalInertia.");
  } else if constexpr (scalar_predicate<T>::is_bool) {
    if (!AreMomentsOfInertiaNearPositiveAndSatisfyTriangleInequality()) {

One thing we talked about on the whiteboard was that this function would get digested into this function.

The reasoning is as follows:

  1. This test currently has information about invalidity -- i.e., non-positive values, non-triangle inequality.
  2. In the future, you were recommending a cascading sequence of tests starting as close to the actual values in memory before operating on a transformed value.

None of that information is available to the caller. We'd discussed moving three functions in to the one report and this was one of them.

That need not be the only solution. This could likewise return a std::optional<string> (nullopt for valid, non-null with information if there was a problem). And the caller could make use of that. Furthermore, the caller wouldn't have to blindly recompute the principle moments again, because if they were relevant, the AreMomentsOfInertia....() function would have already included them in the error message.

So, this PR is a step in the right direction, but it didn't take all the steps yet.

@mitiguy mitiguy force-pushed the unifyValidityTestAndMessagesRotationalInertia branch from 537320c to 6fcffe6 Compare December 20, 2024 02:22
Copy link
Contributor

@SeanCurtis-TRI SeanCurtis-TRI left a comment

Choose a reason for hiding this comment

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

Reviewable status: 4 unresolved discussions, LGTM missing from assignee SeanCurtis-TRI(platform), commits need curation (https://drake.mit.edu/reviewable.html#curated-commits), missing label for release notes (waiting on @mitiguy)


multibody/tree/rotational_inertia.cc line 225 at r1 (raw file):

Previously, SeanCurtis-TRI (Sean Curtis) wrote…

One thing we talked about on the whiteboard was that this function would get digested into this function.

The reasoning is as follows:

  1. This test currently has information about invalidity -- i.e., non-positive values, non-triangle inequality.
  2. In the future, you were recommending a cascading sequence of tests starting as close to the actual values in memory before operating on a transformed value.

None of that information is available to the caller. We'd discussed moving three functions in to the one report and this was one of them.

That need not be the only solution. This could likewise return a std::optional<string> (nullopt for valid, non-null with information if there was a problem). And the caller could make use of that. Furthermore, the caller wouldn't have to blindly recompute the principle moments again, because if they were relevant, the AreMomentsOfInertia....() function would have already included them in the error message.

So, this PR is a step in the right direction, but it didn't take all the steps yet.

The phrase "this function would get digested into this function" is horrible. I'll try again.

The function AreMomentsOfInertia....() would disappear and its contents would become part of this.

(And with that correction, all the rest of the previous content might make more sense.)

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.

3 participants