-
Notifications
You must be signed in to change notification settings - Fork 33
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
Implement Invariant EKF Floating Base Estimator #85
Implement Invariant EKF Floating Base Estimator #85
Conversation
Fails because CI was not updated to add To avoid any merge conflicts, maybe we can wait for this to be merged. |
I added manif to CI in a way that merge conflicts will be avoided. |
cc @S-Dafarra @GiulioRomualdi, this PR is ready to be reviewed. |
CI is failing due to YCM version. See robotology/whole-body-estimators#83. |
Can you please try to rebase? In this way, the modification relative to the adding of |
5239eb9
to
d10adf2
Compare
Done!! Please note that, this PR also contains a few changes in the parent class |
The macOS CI is failing in the InvariantEKF Test, looks like the estimation results are bad (surprising). This needs to be investigated on a macOS machine. Instead of the windows, CI is failing due to linking the problem of YarpUtilitiesTest with |
On Windows, it's actually failing because of
Here a related issue: robotology/community#81 This patch should solve your problem diff --git a/cmake/AddBipedalLocomotionUnitTest.cmake b/cmake/AddBipedalLocomotionUnitTest.cmake
index 82430fd..4449f25 100644
--- a/cmake/AddBipedalLocomotionUnitTest.cmake
+++ b/cmake/AddBipedalLocomotionUnitTest.cmake
@@ -69,6 +69,7 @@ function(add_bipedal_test)
target_link_libraries(${targetname} PRIVATE CatchTestMain ${${prefix}_LINKS})
target_compile_definitions(${targetname} PRIVATE CATCH_CONFIG_FAST_COMPILE CATCH_CONFIG_DISABLE_MATCHERS)
target_compile_features(${targetname} PUBLIC cxx_std_17)
+ target_compile_definitions(${targetname} PRIVATE -D_USE_MATH_DEFINES)
add_test(NAME ${targetname} COMMAND ${targetname}) On my laptop, the test (in debug) is still failing. Normalizing the diff --git a/src/Estimators/tests/InvariantEKFBaseEstimatorTest.cpp b/src/Estimators/tests/InvariantEKFBaseEstimatorTest.cpp
index 9b51ff0..c86684d 100644
--- a/src/Estimators/tests/InvariantEKFBaseEstimatorTest.cpp
+++ b/src/Estimators/tests/InvariantEKFBaseEstimatorTest.cpp
@@ -135,6 +135,7 @@ TEST_CASE("Invariant EKF Base Estimator")
// ground truth
Eigen::Vector3d simIMUPos;
Eigen::Quaterniond simImuQuat = Eigen::Quaterniond(0.3218, -0.6304, -0.6292, 0.3212);
+ simImuQuat.normalize();
simIMUPos << 0.0296, -0.1439, 0.4915;
// IMU measures
@@ -222,4 +223,3 @@ TEST_CASE("Invariant EKF Base Estimator")
REQUIRE( std::abs(newOut.stateStdDev.imuPosition(0) - resetStateStdDev.imuPosition(0)) < 2e-2);
}
- |
Yes, yet again I had failed to run the tests in Debug. I will keep this in mind. I will make relevant changes. Let's see if that fixes the macOS tests as well.
I shall open a separate PR for that. |
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.
Some initial comments
src/Estimators/include/BipedalLocomotion/FloatingBaseEstimators/FloatingBaseEstimator.h
Show resolved
Hide resolved
iDynTree::Transform& basePose, | ||
iDynTree::Twist& baseTwist); |
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 should be changed to manif
and Eigen
objects.
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 opened an issue for this. #107.
This will be dealt with later in a new PR.
d10adf2
to
280f2a6
Compare
Ciao @kouroshD !! May I ask you a favor of testing this PR by running the You might have to install the dependency "manif" on your computer for testing this PR. |
Ciao @kouroshD .. do not worry about this. We managed to procure a Mac workstation in the lab. I shall do the necessary testing myself :) |
280f2a6
to
2694a0b
Compare
Strangely, running the I am installing valgrind according to https://stackoverflow.com/questions/58360093/how-to-install-valgrind-on-macos-catalina-10-15-with-homebrew by tapping into |
Looks like using I changed this in 3020229 and the tests seem to pass both on Debug and Release on the local workstation. |
Take home message, never use |
Changed |
virtual bool resetEstimator(const Eigen::Quaterniond& newBaseOrientation, | ||
const Eigen::Vector3d& newBasePosition) final; |
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.
here you can use:
virtual bool resetEstimator(const Eigen::Quaterniond& newBaseOrientation, | |
const Eigen::Vector3d& newBasePosition) final; | |
virtual bool resetEstimator(Eigen::Ref<const Eigen::Quaterniond> newBaseOrientation, | |
Eigen::Ref<const Eigen::Vector3d> newBasePosition) final; |
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.
Eigen::Ref
doesn't seem to work on Quaternions.
Following compilation error is thrown,
error: ‘IsVectorAtCompileTime’ is not a member of ‘const Eigen::Quaternion<double>’
Eigen::MatrixXd I = Eigen::MatrixXd::Identity(dims, dims); | ||
|
||
Eigen::MatrixXd Fk = I + (Fc*dt); | ||
Eigen::MatrixXd Qk = (Fk*Lc*Qc*(Lc.transpose())*(Fk.transpose()))*dt; |
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.
Do you think we may avoid continuous memory allocation if I
,Fk
and Qk
are class members?
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.
Actually, here the catch is that these matrices do not have a fixed dimension throughout the run time. The dimensions vary if bias estimation is toggled during run time.
In this case, storing the matrices as class members means that we need to modify the mechanics of current implementation in a way that these matrix dimensions are updated at every step. It is not difficult to implement, however, in any case, we need to be reallocating the memory during the resize. That's why I chose this way instead.
Correct me if my rationale is not good enough.
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 think that some resizing from time to time are better than allocating memory all the time. Can you provide some more insights on why a continuous resize may be necessary?
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.
Continuous resize won't be necessary. Just at events of bias estimation toggle. I can make the relevant changes.
Here, we do not even consider arbitrary number of contacts, we consider only 2. (so we don't need to continuously resize the matrices.)
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.
Done in 6abd678
Eigen::MatrixXd PHT = P*measModelJacobian.transpose(); | ||
Eigen::MatrixXd S = measModelJacobian*PHT + measNoiseVar; | ||
Eigen::MatrixXd K = PHT*(S.inverse()); |
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.
As before, probably we may avoid having this continuous memory allocation.
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'd prefer to keep this part as it is since this also depends on the number of feet in contact with the ground which seems to be changing "almost continuously". This means anyways we might have to do an almost continuous resizing of these matrices. Instead for the above comment, I made the matrices Fc
, Qc
and Lc
as class members to avoid continuous memory allocation, since their dimensions would only change at very rare events of toggling the bias estimation.
What do you think @GiulioRomualdi?
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.
To be honest, I am with @GiulioRomualdi on this. It is always better to avoid memory allocations, especially in pieces of code that are called at every control iteration. In principle, these should have no memory allocation at all.
It is acceptable to have some resize from time to time, also considering that the container may have some capacity (hence memory may not be allocated also in case of resizes).
If the number of members blows up, then we can discuss alternative solutions.
Also, I have noticed that in the code below there are several temporary matrices (X
, BigX
, innovation
, delta
, dX
, IminusKH
). Also this should be avoided as much as possible.
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've partially done this in 6abd678. Let me know if this is in line with what is suggested. However, about the resizing of the matrices related to the measurement model/updates, it would require a bit more time to do it in a cleaner way.
I also completely agree with what is suggested. In fact, I had an earlier design in the element repo which considered these things. But not sure why I changed my mind to do things in a different way here.
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.
Eigen
automatically resizes the matrix when using the assignment operator. So you don't need to deal with the explicit resize for a first iteration I think. Then, later on, we can understand if it should be better to resize these matrices beforehand in a specific place.
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.
Fixed in f456476
// X = |R v p pr pl| | ||
// | 1 | | ||
// | 1 | | ||
// | 1 | | ||
// | 1| | ||
X.resize(7, 7); | ||
X.block<3, 3>(0, 0) = state.imuOrientation.toRotationMatrix(); | ||
X.block<3, 1>(0, 3) = state.imuLinearVelocity; | ||
X.block<3, 1>(0, 4) = state.imuPosition; | ||
X.block<3, 1>(0, 5) = state.rContactFramePosition; | ||
X.block<3, 1>(0, 6) = state.lContactFramePosition; | ||
X.bottomLeftCorner<4, 3>().setZero(); | ||
X.bottomRightCorner<4, 4>() = Eigen::Matrix4d::Identity(); |
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.
Probably it makes sense to store X as sparse matrix
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.
Given it's only a 7x7 matrix, do you think we can achieve higher gain margins using a sparse matrix?
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.
In our use cases, sparse matrices are useful only if need in some calculations involving inversions (e.g solving linear systems or when interfacing to solvers). Another possible application is to reduce the occupation in memory, but this is not an issue for basically all our applications. Hence, if we are not in the first case, I would avoid using sparse matrices.
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 most we do with this matrix is matrix multiplication. For inversions, we exploit with Lie group properties of direct product/semi-direct-product to only involve submatrix operations.
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.
Ok, I would vote for keeping it dense then.
d311aa2
to
f456476
Compare
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 PR is very complex for me to delve into every detail, it is above my head 😁 But on the software side, I did not spot anything worth changing. In addition, the implementation can change easily later if needed. Hence, it looks good to me
src/Estimators/include/BipedalLocomotion/FloatingBaseEstimators/FloatingBaseEstimator.h
Outdated
Show resolved
Hide resolved
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 did not checked everithing in detail, but overall it seems fine!
0756894
to
c5b51a1
Compare
cc @GiulioRomualdi do you think we can merge this? |
c5b51a1
to
f7a3f93
Compare
@GiulioRomualdi I've squashed the commits. You could merge it once the CI passes, thank you! :) |
Merging |
This PR,
InvariantEKFBaseEstimator
(the Contact Aided Invariant EKF algorithm) by inheriting from theFloatingBaseEstimator
class. Reference to the original paper is Contact-Aided Invariant Extended Kalman Filtering for Robot State Estimation. This implementation does not contain a full EKF SLAM algorithm using also visual factors. Instead, it's limited to estimating the foot positions of a bipedal robot only along with the base pose and IMU biases. For the original (and full) version, please see https://github.com/RossHartley/invariant-ekf.InvariantEKFBaseEstimatorTest
that tests the estimator algorithm for a simple static configuration of iCubGenova04 robot.Additionally, this PR also
Estimators
algorithms andFloatingBaseEstimators
algorithmFloatingBaseEstimator
class slightly to add some required features with respect to the model computations.Pending from the PR,