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

Fix velocity and position integration for FreeJoint #1437

Merged
merged 11 commits into from
Dec 16, 2021

Conversation

azeey
Copy link
Contributor

@azeey azeey commented Feb 28, 2020

This resolves issue #1433 and possibly the other issues mentioned in there. The two changes made in this PR are:

  1. When integrating a FreeJoint's velocity, an additional term is added to account for changing linear velocity in the inertial frame.

  2. The joint velocities of FreeJoint are in se3 and since they are expressed in the body frame, they have to be updated after the joint's positions (SE3) are updated. The same is true for accelerations after velocities are integrated.

This PR breaks a test in test_Dynamics.cpp because integration of the joint positions of FreeJoint updates joint velocities unlike other joint types. I left this as WIP to get some feedback on what to do about this test failure.


Before creating a pull request

  • Document new methods and classes
  • Format new code files using clang-format

Before merging a pull request

  • Set version target by selecting a milestone on the right side
  • Summarize this change in CHANGELOG.md
  • Add unit test(s) for this change

The main fix is in the expression used to integrate velocities. The
secondary fix is to update spatial accelerations after
integrating velocities and to update both spatial velocities and
accelerations after integrating positions.
@azeey azeey mentioned this pull request Mar 7, 2020
@jslee02 jslee02 self-requested a review March 12, 2020 19:48
@scpeters
Copy link
Collaborator

@jslee02 let us know if you need any explanation of these changes

cc @mxgrey

Copy link
Member

@jslee02 jslee02 left a comment

Choose a reason for hiding this comment

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

I think the correct fix for the numerical inaccuracy of FreeJoint is to change the dynamics equation to use the global frame. Currently, DART uses local frame (or body attached frame) that leads to that the linear acceleration depends on the angular velocity, which doesn't exist in the global frame version.

This PR is resolving the issue by reverting the velocity and acceleration that are computed by the forward dynamics (represented in body frame). It may fix the issue but not the root cause.

Let me rework on the dynamics equations switching the reference frame to global frame, but this could take some time. In the meantime, I might be okay to accept this PR as long as it doesn't break the current behavior but resolving the issue.

Sorry for taking too long in response.

dart/dynamics/FreeJoint.cpp Outdated Show resolved Hide resolved
@scpeters
Copy link
Collaborator

This PR is resolving the issue by reverting the velocity and acceleration that are computed by the forward dynamics (represented in body frame). It may fix the issue but not the root cause.

Let me rework on the dynamics equations switching the reference frame to global frame, but this could take some time. In the meantime, I might be okay to accept this PR as long as it doesn't break the current behavior but resolving the issue.

Sounds good to me.

@azeey
Copy link
Contributor Author

azeey commented Mar 19, 2020

Yes, I think doing the dynamics in the global frame would probably be a better fix.

This PR is resolving the issue by reverting the velocity and acceleration that are computed by the forward dynamics (represented in body frame).

Is it reverting? My understanding was that it was updating the velocity and acceleration to be in the updated (after integration) body frame.

@jslee02
Copy link
Member

jslee02 commented Mar 19, 2020

Is it reverting? My understanding was that it was updating the velocity and acceleration to be in the updated (after integration) body frame.

Sorry, "overwriting" would be a better word. I intended to say that the function additionally updates the velocity and acceleration that are already computed by other functions.

@scpeters
Copy link
Collaborator

@jslee02 wrote: In the meantime, I might be okay to accept this PR as long as it doesn't break the current behavior but resolving the issue.

If you have a better fix ready, we can use that one, but if we are going to merge a short-term fix, would it be acceptable to modify test_Dynamics.cpp to match the new behavior?

@jslee02
Copy link
Member

jslee02 commented Mar 25, 2020

If you have a better fix ready, we can use that one, but if we are going to merge a short-term fix, would it be acceptable to modify test_Dynamics.cpp to match the new behavior?

Yes, it would work.

azeey added a commit to gazebo-forks/dart that referenced this pull request Apr 3, 2020
* Fix issue dartsim#1433

The main fix is in the expression used to integrate velocities. The
secondary fix is to update spatial accelerations after
integrating velocities and to update both spatial velocities and
accelerations after integrating positions.

* Add regression test for issue dartsim#1193

* Remove main in test, fix style
Signed-off-by: Addisu Z. Taddese <addisu@openrobotics.org>
@azeey
Copy link
Contributor Author

azeey commented Oct 6, 2020

While working on #1505 (a copy of gazebo-forks#9) , I found that getLinearAcceleration did not return the correct value. Investigating that further, I found that the integration fix I have so far did not apply when constraint impulses are involved. Furthermore, I found problems with the integration of position in FreeJoint::integratePosition when the COM of a body is not at the origin. f34aa32 fixes both issues and adds a test for the COM offset issue.

The linear acceleration issue is fixed by a Coriolis term from the acceleration before integrating it to obtain a new velocity. My intuition for this is that the FreeJoint::integratePosition updates the spatial velocity based on the newly integrated position. This update to spatial velocity is in itself an acceleration and it does what the Coriolis term would have done had we FreeJoint::integratePosition not updated the spatial velocity.

The COM offset issue is fixed by transforming all quantities into the COM frame before integration. After integration, the values are transformed back into the body's origin frame.

@costashatz
Copy link
Contributor

@jslee02 any updates on this one and when it will be fixed in DART main repo?

@jslee02
Copy link
Member

jslee02 commented Sep 20, 2021

Let me take a look this PR this weekend

@azeey azeey changed the title [WIP] Fix velocity and position integration for FreeJoint Fix velocity and position integration for FreeJoint Sep 24, 2021
@azeey
Copy link
Contributor Author

azeey commented Sep 24, 2021

I've updated the PR with the changes we've made on our fork. I've relaxed the tolerances in test_Dynamics to make tests pass. IMO, a proper way to fix those tests would be to compute the finite differences for 6DOF joints differently than simple vector subtraction because the velocities in the two time steps are in two different reference frames (the body has undergone a rotation).

@costashatz
Copy link
Contributor

@azeey thanks! @jslee02 any updates?

@jslee02
Copy link
Member

jslee02 commented Dec 15, 2021

My apologies for the supre late response. Left a few comments, one build related one and mostly style fixes.

As pointed out in gazebo-forks#28 (comment), changing the reference frame would require lots of work and need throught tests to make sure it doesn't introduce unforeseen side effects. Let me merge this change as it's currently the best solution. Thank you for the fix with the decent tests!


setVelocitiesStatic(math::AdR(Qdiff.inverse(), getVelocitiesStatic()));
Copy link
Member

Choose a reason for hiding this comment

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

Could we cache math::AdR(Qdiff.inverse()) to compute it only once?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I cached Qdiff.inverse() in the variable QdiffInv in 5091a56. I hope that's what you meant.

dart/dynamics/FreeJoint.cpp Outdated Show resolved Hide resolved
unittests/regression/CMakeLists.txt Outdated Show resolved Hide resolved
unittests/regression/test_Issue1193.cpp Outdated Show resolved Hide resolved
unittests/regression/test_Issue1193.cpp Outdated Show resolved Hide resolved
unittests/regression/test_Issue1193.cpp Outdated Show resolved Hide resolved
auto comLinearVel = rootBn->getCOMLinearVelocity();
// TODO (addisu) Improve FreeJoint integration so that a higher tolerance is
// not necessary here.
EXPECT_NEAR(0.01, comLinearVel.x(), tol * 1e2);
Copy link
Member

Choose a reason for hiding this comment

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

Nit: Would it be better to change 0.01 to 10 * dt to give hint on where the expected value come from?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, I added a variable extForce and then used the x component of that in the expectation. 5091a56

Signed-off-by: Addisu Z. Taddese <addisu@openrobotics.org>
Signed-off-by: Addisu Z. Taddese <addisu@openrobotics.org>
Copy link
Member

@jslee02 jslee02 left a comment

Choose a reason for hiding this comment

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

Thank you for being patient with me! LGTM

This pull request was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants