-
Notifications
You must be signed in to change notification settings - Fork 342
Link::AddForceInInertialFrame APIs added #2816
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
Conversation
|
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. |
include/gz/sim/Link.hh
Outdated
| /// 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, |
There was a problem hiding this comment.
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?.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
- The function which applies force directly at the COM, can be named either AddForce or AddRelativeForce
- 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.
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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
0cbdd0f to
4e44110
Compare
Signed-off-by: Vedant87 <Vedantsr3@gmail.com>
Signed-off-by: Vedant87 <Vedantsr3@gmail.com>
Signed-off-by: Vedant87 <Vedantsr3@gmail.com>
… to 80 characters Signed-off-by: Vedant87 <Vedantsr3@gmail.com>
… to 80 characters Signed-off-by: Vedant87 <Vedantsr3@gmail.com>
4e44110 to
9660d0c
Compare
src/Link.cc
Outdated
| } | ||
|
|
||
| ////////////////////////////////////////////////// | ||
| void Link::AddLinkForce(EntityComponentManager &_ecm, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add a unit test for this?
You can find other tests for the link class here: https://github.com/gazebosim/gz-sim/blob/gz-sim9/src/Link_TEST.cc
|
Once you decide on the naming, it'll also be good to update the python API. |
Signed-off-by: Vedant87 <Vedantsr3@gmail.com>
Signed-off-by: Vedant87 <Vedantsr3@gmail.com>
Signed-off-by: Vedant87 <Vedantsr3@gmail.com>
Signed-off-by: Vedant87 <Vedantsr3@gmail.com>
Sorry for the delay; this is complicated and it took me a while to collect my thoughts.
Some references for naming these quantities:
The gz::sim::Link class already has two overloads of the
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:
Having said all that, here are some guidelines:
I'll follow up with concrete suggestions inline |
include/gz/sim/Link.hh
Outdated
| /// 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, |
There was a problem hiding this comment.
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
include/gz/sim/Link.hh
Outdated
| /// \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. |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
consider defining
_positionin the same coordinates as_forcefor consistency
The documentation is conflicting:
- According to Link.hh:330-331 ,
_positionis defined in link-fixed coordinates. - According to Link.cc:457-459 ,
_positionis 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.
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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 ,_positionis directly added toinertial, if_positionis expressed in terms of Link's center of mass there should be a calculation to convert_positionfrom in terms of Link's center of mass to_positionin 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
_forceand_positionare both expressed in link-fixed coordinates. -
I'll work on fixing all these issues in the next commit.
include/gz/sim/Link.hh
Outdated
| /// \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. |
There was a problem hiding this comment.
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
Signed-off-by: Vedant87 <Vedantsr3@gmail.com>
Signed-off-by: Vedant87 <Vedantsr3@gmail.com>
|
sorry I missed the notification that you updated this PR; I'll take a look |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks for documenting your test! I just have some minor suggestions about formatting, and one comment that you don't need to act on since you've already put in a lot of work here
test/integration/link.cc
Outdated
| wrenchMsg.torque().x(), wrenchMsg.torque().y(), wrenchMsg.torque().z())); | ||
|
|
||
| // Add force in Inertial Frame at an offset | ||
| math::Vector3d offset{0.0, 1.0, 0.0}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
since the inertial frame pose only has a rotation about the Y axis, this offset won't be rotated. I think you've put in enough work here, so I won't ask you to do more, but I think it would be a stronger test if the offset was 1, 0, 0, since this offset would pass through a rotation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
since the inertial frame pose only has a rotation about the Y axis, this offset won't be rotated. I think you've put in enough work here, so I won't ask you to do more, but I think it would be a stronger test if the offset was
1, 0, 0, since this offset would pass through a rotation
I can work on this, just need to do a few matrix multiplications and edit a few lines of code.
Co-authored-by: Steve Peters <computersthatmove@gmail.com> Signed-off-by: Vedant Randive <vedantsr3@gmail.com>
Co-authored-by: Steve Peters <computersthatmove@gmail.com> Signed-off-by: Vedant Randive <vedantsr3@gmail.com>
Co-authored-by: Steve Peters <computersthatmove@gmail.com> Signed-off-by: Vedant Randive <vedantsr3@gmail.com>
Co-authored-by: Steve Peters <computersthatmove@gmail.com> Signed-off-by: Vedant Randive <vedantsr3@gmail.com>
Co-authored-by: Steve Peters <computersthatmove@gmail.com> Signed-off-by: Vedant Randive <vedantsr3@gmail.com>
Co-authored-by: Steve Peters <computersthatmove@gmail.com> Signed-off-by: Vedant Randive <vedantsr3@gmail.com>
Co-authored-by: Steve Peters <computersthatmove@gmail.com> Signed-off-by: Vedant Randive <vedantsr3@gmail.com>
Co-authored-by: Steve Peters <computersthatmove@gmail.com> Signed-off-by: Vedant Randive <vedantsr3@gmail.com>
Co-authored-by: Steve Peters <computersthatmove@gmail.com> Signed-off-by: Vedant Randive <vedantsr3@gmail.com>
Signed-off-by: Vedant87 <Vedantsr3@gmail.com>
test/integration/link.cc
Outdated
| // [-1 0 0 | 3] [0] | ||
| // [0 0 0 | 1] [1] | ||
| // = [1, 2, 2] | ||
| // offsetInLInkFrame = [1, 2, 2] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this looks right to me
test/integration/link.cc
Outdated
| // First, calculate the effective position vector in the world frame. | ||
| // offsetInLinkFrame = [1, 2, 2] | ||
| // inertiaPose.Pos() = [1, 2, 3] | ||
| // effectivePosition = offsetInLinkFrame + inertiaPose.Pos() = [2, 4, 5] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know why this step is needed. I would think the torque could be computed by rotating offsetInLinkFrame to the world frame and then computing the cross product with worldForceWithOffset.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know why this step is needed. I would think the torque could be computed by rotating
offsetInLinkFrameto the world frame and then computing the cross product withworldForceWithOffset.
- This is consistent with the torque calculations done for AddWorldForce's offset test (see: Link.cc:657-658 ).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the offsetInLinkFrame variable has already been computed by multiplication with the homogeneous transformation matrix H_inertial, which has the inertiaPose.Pos() embedded within it. So I think it should not be added again
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the
offsetInLinkFramevariable has already been computed by multiplication with the homogeneous transformation matrixH_inertial, which has theinertiaPose.Pos()embedded within it. So I think it should not be added again
Understood, will change the H_inertial to a pure rotational, this will be more consistent with the following changes.
src/Link.cc
Outdated
| math::Quaterniond::Identity); | ||
| math::Vector3d positionInLinkFrame = | ||
| (inertial->Data().Pose() * | ||
| forceApplicationRelativeToInertialFrame).Pos(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the AddWorldForce API is a bit confusing
- the force is expressed in world coordinates
- the force is applied at an offset from the link center of mass / inertial frame
- the offset is expressed in link-frame coordinates
so I think we just need to rotate _position here, to express it in link-frame coordinates, since it is already relative to the center-of-mass / inertial frame
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the AddWorldForce API is a bit confusing
- the force is expressed in world coordinates
- the force is applied at an offset from the link center of mass / inertial frame
- the offset is expressed in link-frame coordinates
so I think we just need to rotate
_positionhere, to express it in link-frame coordinates, since it is already relative to the center-of-mass / inertial frame
Understood, changing this to
math::Vector3d positionInLinkFrame = inertial->Data().Pose().Rot().RotateVector(_position);
Signed-off-by: Vedant87 <Vedantsr3@gmail.com>
Signed-off-by: Vedant87 <Vedantsr3@gmail.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks, that fix looks correct. we are almost there! just one more comment to be fixed
src/Link.cc
Outdated
| // ApplyWorldForce applies the force at a position expressed in terms | ||
| // Rotate offset from inertial frame to link frame. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| // ApplyWorldForce applies the force at a position expressed in terms | |
| // Rotate offset from inertial frame to link frame. | |
| // ApplyWorldForce applies the force at a position relative to the | |
| // center of mass and expressed in coordinates of the link frame. | |
| // Since _position is relative to the center of mass in coordinates | |
| // of the inertial frame, it just needs to be rotated to be expressed | |
| // in coordiantes of the link frame. |
Signed-off-by: Vedant87 <Vedantsr3@gmail.com>
|
thanks for your contribution! |
🎉 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
codecheckpassed (See contributing)Note to maintainers: Remember to use Squash-Merge and edit the commit message to match the pull request summary while retaining
Signed-off-bymessages.