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 AddLinkForce Function to Apply Forces in Link Frame #2816

Open
wants to merge 16 commits into
base: main
Choose a base branch
from

Conversation

Vedant87
Copy link

@Vedant87 Vedant87 commented Mar 7, 2025

🎉 New feature

Closes #2713

Summary

Function added: to apply force relative to the center of mass of the link frame, the function converts the force to a force with respect to the world coordinates. It uses the AddWorldForce method to apply force either at the center of mass of the link or at an offset from the center of mass, based on user input.

Checklist

  • Signed all commits for DCO
  • Added tests
  • Added example and/or tutorial
  • Updated documentation (as needed)
  • Updated migration guide (as needed)
  • Consider updating Python bindings (if the library has them)
  • codecheck passed (See contributing)
  • All tests passed (See test coverage)
  • While waiting for a review on your PR, please help review another open pull request to support the maintainers

Note to maintainers: Remember to use Squash-Merge and edit the commit message to match the pull request summary while retaining Signed-off-by messages.

@Vedant87 Vedant87 requested a review from mjcarroll as a code owner March 7, 2025 16:12
@github-actions github-actions bot added the 🪵 jetty Gazebo Jetty label Mar 7, 2025
@iche033
Copy link
Contributor

iche033 commented Mar 7, 2025

The CI picked up some lint issues - can you remove trailing whitespace and limit lines to 80 char? I also made some minor comments on removing empty lines.

/// and applied at the center of mass of the link.
/// \param[in] _ecm Mutable Entity-component manager.
/// \param[in] _force Force to be applied expressed in link's center of mass coordinates
public: void AddLinkForce(EntityComponentManager &_ecm,
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe just AddForce, which is more consistent with gazebo-classic's API. Do you have any preference on the API name, @scpeters?.

Copy link
Contributor

Choose a reason for hiding this comment

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

friendly ping @scpeters

given that the other functions in this class do not have the Link string in the name, e.g. SetLinearVelocity (instead of SetLinkLinearVelocity), I think we should rename this to AddForce to be consistent.

Copy link
Author

@Vedant87 Vedant87 Mar 13, 2025

Choose a reason for hiding this comment

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

I was thinking to use the following naming convention

  1. The function which applies force directly at the COM, can be named either AddForce or AddRelativeForce
  2. The function which applies force at an offset from the COM, can be named AddLinkForce.

This naming convention is consistent with gazebo-classic's API.

Copy link
Member

Choose a reason for hiding this comment

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

apologies for the delayed response; this is complicated and I wrote an overly long response, which I will post as a separate comment to this PR

Copy link
Member

Choose a reason for hiding this comment

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

/// \param[in] _force Force to be applied expressed in link's
/// center of mass coordinates

by center of mass coordinates, do you mean the coordinates of the inertial frame defined by the SDFormat //link/inertial/pose offset from the link frame?

If so, you could name this method AddInertialForce or AddForceInInertialFrame or AddForceRelativeToInertialFrame

@Vedant87 Vedant87 requested a review from iche033 March 8, 2025 03:35
@Vedant87 Vedant87 force-pushed the add_link_force_api branch 4 times, most recently from 0cbdd0f to 4e44110 Compare March 8, 2025 09:37
@Vedant87 Vedant87 force-pushed the add_link_force_api branch from 4e44110 to 9660d0c Compare March 8, 2025 09:45
@arjo129
Copy link
Contributor

arjo129 commented Mar 11, 2025

Once you decide on the naming, it'll also be good to update the python API.

Signed-off-by: Vedant87 <[email protected]>
Signed-off-by: Vedant87 <[email protected]>
Signed-off-by: Vedant87 <[email protected]>
@arjo129
Copy link
Contributor

arjo129 commented Mar 13, 2025

@vedant do address @iche033's comment and add python bndngs.

@scpeters
Copy link
Member

Maybe just AddForce, which is more consistent with gazebo-classic's API. Do you have any preference on the API name, @scpeters?.

Sorry for the delay; this is complicated and it took me a while to collect my thoughts.
The Vector3 force parameter requires two pieces of context in order to interpret it:

  • the location on the Link where it acts
  • the coordinates in which the force Vector components are expressed

Some references for naming these quantities:

The gz::sim::Link class already has two overloads of the AddWorldForce() method:

  • Accepting a single Vector3 force parameter (see Link.hh:319-324):
        - the force vector is "expressed-in-coordinates-of" the world frame and applied "relative-to" the link center-of-mass
  • Accepting two Vector3 parameters: force and position (see Link.hh:326-334)
        - the position vector specifies "The point of application of the force expressed in the link-fixed frame." I assume this means that the position vector is "relative-to" the link frame origin and "expressed-in-coordinates-of" the link frame.
        - the force vector is "expressed-in-coordinates-of" the world frame and applied "relative-to" the point specified by the position parameter

I suppose the "World" in the "AddWorldForce" method name refers to the "expressed-in-coordinates-of" frame for the force vector, but it seems inconsistent to me that the position parameter is "expressed-in-coordinates-of" the link frame. It also seems inconsistent that for one overload, the force is applied "relative-to" the link center-of-mass, but in the other overload it is applied "relative-to" an offset from the link-fixed frame.

In gazebo-classic, the gazebo::physics::Link class has the following APIs with varying levels of documented behavior in the header file:

  • AddForce: relative-to and expressed-in-coordinates-of not documented in the header
  • AddRelativeForce: relative-to not documented, expressed-in-coordinates-of "body's own frame of reference"
  • AddForceAtWorldPosition: the force's expressed-in-coordinates-of frame is not documented, but the force is applied relative-to a position specified in the "global coordinate frame" (aka world).
  • AddForceAtRelativePosition: the force is expressed-in-coordinates-of the world reference frame, and relative-to a position vector expressed-in-coordinates-of the link frame and relative-to the link's center of mass
  • AddLinkForce: this is the most consistent, as the force is expressed-in-coordinates-of the link frame and applied relative-to a position vector expressed-in-coordinates of the link frame and relative-to the link frame's origin

Having said all that, here are some guidelines:

  • Mandatory: be clear about how the parameters to these APIs are defined. For force and position parameters, this includes the location relative-to which they are defined and which frame they are "expressed-in-coordinates-of". Be as verbose as needed in the header file documentation.
  • If possible, prefer consistent frame conventions for the parameters of an API. For example, gazebo::physics::AddLinkForce uses the Link frame consistently
  • You can try to fully describe the frame convention in the API name (AddForceAtWorldPosition, AddForceAtRelativePosition) but the name will likely become very long

I'll follow up with concrete suggestions inline

/// and applied at the center of mass of the link.
/// \param[in] _ecm Mutable Entity-component manager.
/// \param[in] _force Force to be applied expressed in link's center of mass coordinates
public: void AddLinkForce(EntityComponentManager &_ecm,
Copy link
Member

Choose a reason for hiding this comment

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

/// \param[in] _force Force to be applied expressed in link's
/// center of mass coordinates

by center of mass coordinates, do you mean the coordinates of the inertial frame defined by the SDFormat //link/inertial/pose offset from the link frame?

If so, you could name this method AddInertialForce or AddForceInInertialFrame or AddForceRelativeToInertialFrame

/// \param[in] _force Force to be applied expressed in link's center
/// of mass coordinates
/// \param[in] _position The point of application of the force expressed
/// in the link-fixed frame.
Copy link
Member

Choose a reason for hiding this comment

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

consider defining _position in the same coordinates as _force for consistency

Copy link
Author

Choose a reason for hiding this comment

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

consider defining _position in the same coordinates as _force for consistency

The documentation is conflicting:

  • According to Link.hh:330-331 , _position is defined in link-fixed coordinates.
  • According to Link.cc:457-459 , _position is defined in Link's center of mass coordinates.

In the current implementation I am assuming _position is defined in Link's center of mass coordinates, which are the same coordinates as _force.

Copy link
Member

Choose a reason for hiding this comment

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

well if the inconsistent use of frames is a documentation error, then let's fix the documentation. We should confirm the actual behavior with the test though

Copy link
Author

Choose a reason for hiding this comment

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

well if the inconsistent use of frames is a documentation error, then let's fix the documentation. We should confirm the actual behavior with the test though

  • _position , is expressed in terms of link fixed frame. In Link.cc:460-461 , _position is directly added to inertial , if _position is expressed in terms of Link's center of mass there should be a calculation to convert _position from in terms of Link's center of mass to _position in terms of link-fixed coordinates.

  • There is a major issue in my code that I overlooked, the calculations in my code consider the force is expressed in coordinates of the link frame, so coincidently _force and _position are both expressed in link-fixed coordinates.

  • I'll work on fixing all these issues in the next commit.

/// \param[in] _force Force to be applied expressed in link's center
/// of mass coordinates
/// \param[in] _position The point of application of the force expressed
/// in the link-fixed frame.
Copy link
Member

Choose a reason for hiding this comment

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

well if the inconsistent use of frames is a documentation error, then let's fix the documentation. We should confirm the actual behavior with the test though

@Vedant87
Copy link
Author

I've made the required changes to the code, I am not sure why the commit is failing the following 2 tests:

  1. gz_sim-ci-pr_any-noble-amd64
  2. gz_sim-pr-clowin

@Vedant87 Vedant87 requested review from scpeters and arjo129 March 14, 2025 17:03
@scpeters
Copy link
Member

  1. gz_sim-ci-pr_any-noble-amd64

this had an unrelated flaky test failure (see #2609)

  1. gz_sim-pr-clowin

this was an infra problem, fixed by gazebo-tooling/release-tools#1281, I retriggered it

@Vedant87 Vedant87 requested a review from scpeters March 19, 2025 03:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🪵 jetty Gazebo Jetty
Projects
Status: In review
Development

Successfully merging this pull request may close these issues.

4 participants