-
Notifications
You must be signed in to change notification settings - Fork 767
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 / Move Rot3::quaternion
to deprecated block
#1219
Conversation
We verified this fix by adding a group of unit tests in // Check accessing the quaternion components via Rot3::quaternion
EXPECT(assert_equal(q1.w(), R1.quaternion().w()));
EXPECT(assert_equal(q1.x(), R1.quaternion().x()));
EXPECT(assert_equal(q1.y(), R1.quaternion().y()));
EXPECT(assert_equal(q1.z(), R1.quaternion().z()));
EXPECT(assert_equal(q2.w(), R2.quaternion().w()));
EXPECT(assert_equal(q2.x(), R2.quaternion().x()));
EXPECT(assert_equal(q2.y(), R2.quaternion().y()));
EXPECT(assert_equal(q2.z(), R2.quaternion().z())); The original gtsam (at least before commit 9a1eb02 on 2022-06-08) would not pass these tests and give the following error log:
While the fix can pass the tests:
|
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.
Sorry, no - we can deprecate methods (as I alluded to in the group) but definitely not change their behavior/meaning. I'd simply deprecate this method and make sure we use toQuaternion everywhere else.
OK, in that case I will create another PR, try to move |
Note you could just re-use this PR. |
Rot3::quaternion
to deprecated block
Move |
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.
Awesome, thanks ! Please respond to my comment and then I will merge after CI passes.
Seems all Python CI failed with the same error:
It's because in the CI configuration Currently, I have 2 possible solutions for this, and may need some advice from the project maintainers:
|
Something to keep note of, |
I'm sorry but I am not seeing the argument for this. I just updated some code to use Previously I could do q = wTc.rotation().quaternion() but now we have to do q = wTb.rotation().toQuaternion()
q = np.asarray([q.w(), q.x(), q.y(), q.z()]) which isn't functional since we can't chain methods together anymore e.g.: do_something(wTb.rotation().quaternion()) Moreover, the impression that the current API is confusing doesn't have much evidence other than the single data point. |
Just as a heads up, we also rely on the prior functionality in GTSFM. Although this change might make the coefficients more explicit in our particular use case, instead of having to go back and check the documentation for ordering. See: https://github.com/borglab/gtsfm/blob/master/gtsfm/utils/io.py#L374-L377 |
As you suggest, for the python/matlab users, the However, things are different in C++, because the Suppose the following use case: the users want to extract the pose estimation from gtsam and feed it to a ROS odometry message. Without checking the documentation, their IDE gives a coding completion that says: there is a // pose estimation from previous step
gtsam::Point3 wtc;
gtsam::Rot3 wRc;
nav_msgs::Odometry odom;
// wrong quaternion component order!
odom.pose.orientation.w = wRc.quaternion().w();
odom.pose.orientation.x = wRc.quaternion().x();
odom.pose.orientation.y = wRc.quaternion().y();
odom.pose.orientation.z = wRc.quaternion().z(); Everything seems correct, but the ordering of the quaternion doesn't match. And for the debugging process, it will be a nightmare... |
@HViktorTsoi I see your argument, but the docstring for
Moreover, a user should be familiar that a Matrix/Vector is not semantically the same as a quaternion since a vector doesn't enforce the structure of a quaternion. Thus they should already be wary of calling On the other hand, |
This is the gist of the issue here. The object is not a Rot3 but an Eigen vector so one cannot assume the getters for the vector are the same as the getters for a Rot3/Quaternion object. |
Maybe one can still chain methods without do_something(wTb.rotation().toQuaternion().coeffs()[[3,0,1,2]]) It looks a little bit tricky though. |
Yeah I thought about that but because Eigen uses [x, y, z, w], that is also error prone, exactly like the original issue you faced. I am terribly sorry you are having difficulties with debugging and other issues, but hopefully we can figure something out that works for everyone! |
The previous behavior is definitely problematic. Eigen (for better or worse) provides x/y/z/w on vectors, and they conflict with the order in the quaternion method. Just bad. I think the solution in this PR is good. @johnwlambert , let's just fix GTSFM to not use the deprecated method. |
@varunagrawal are we ok to merge? |
I'm not so sure. @HViktorTsoi has done a brilliant job with this PR but @johnwlambert, myself and others would like to see some way to just get the quaternion vector directly without the 2 step process. :( |
Okay if you feel this is the correct approach then let's go for it. We should probably decide on a fixed convention and make that the de facto (aka update constructors and other methods). Thanks for the brilliant PR @HViktorTsoi. You've made our lives so much easier! 😊 |
This PR fixes #1209. More details about this issue can be found in the group discussion https://groups.google.com/g/gtsam-users/c/AxbAAEgMHTA.
Basically, this issue is because
Rot3::quaternion()
returns aVector
as[qw, qx, qy, qz]
, not a quaternion.Vector
is a typedef forEigen::VectorXd
, for which.x()
returns the first element (instead of qw),.y()
the second (so here qx), etc... Therefore thisRot3::quaternion()
API is very non-intuitive and it could lead to a bug in user code if they don't pay attention enough.This fix modifies the
Rot3::quaternion()
API and makes sure the ordering of the returned[qw,qx,qy,qz]
are consistent withgtsam::Quaternion
.