-
Notifications
You must be signed in to change notification settings - Fork 1.8k
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 Swapped TFs Axes #2684
Fix Swapped TFs Axes #2684
Changes from 1 commit
81b49ee
1e08819
d171559
3c35930
daba7e5
ebacd30
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -865,9 +865,13 @@ void BaseRealSenseNode::publish_static_tf(const rclcpp::Time& t, | |
msg.header.stamp = t; | ||
msg.header.frame_id = from; | ||
msg.child_frame_id = to; | ||
|
||
// Convert x,y,z (taken from camera extrinsics) | ||
// from optical cooridnates to ros coordinates | ||
msg.transform.translation.x = trans.z; | ||
msg.transform.translation.y = -trans.x; | ||
msg.transform.translation.z = -trans.y; | ||
|
||
msg.transform.rotation.x = q.getX(); | ||
msg.transform.rotation.y = q.getY(); | ||
msg.transform.rotation.z = q.getZ(); | ||
|
@@ -917,7 +921,10 @@ void BaseRealSenseNode::calcAndPublishStaticTransform(const rs2::stream_profile& | |
auto Q = rotationMatrixToQuaternion(ex.rotation); | ||
Q = quaternion_optical * Q * quaternion_optical.inverse(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what are you trying to achieve with this line ? qpq-1 is meant for transformation a vector from CS A to CS B but you have Q in the middle, which is a rotation quaternion. I don't understand the math here. You have relative rotation from tf_ex already, why you need to rotate it again with the quaternion_optical ? Isn't that the tf_ex already assume optical frame ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Actually I did not add this line, it was there for a couple of years. and it was working all the time. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @guoqingzh This added by PR #383 , please review it Could be that Q here is acctually P from the original equation There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @Nir-Az As your screenshot told, the expression rotates vector quaternion (not rotation quaternion). I read the original PR#383, I think the original author is trying to do a rotation combination here. In our code, Q is optical to optical , which can't be used directly in ros tf so he has to rotate first from ros to optical (quaternion_optical inverse), then apply Q, after that apply quaternion_optical again to rotate from optical back to ros, i think it is ok |
||
|
||
float3 trans{ex.translation[0], ex.translation[1], ex.translation[2]}; | ||
// Invert x,y,z of extrinsic translation before sending this as TF translation | ||
// because extrinsic from A to B is the position of A relative to B | ||
// while TF from A to B is the transformation to be done on A to get to B | ||
float3 trans{-ex.translation[0], -ex.translation[1], -ex.translation[2]}; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What about the rotation? In fact, I see it was that way before a PR from september 2022: 61406af Maybe that PR was a mistake or did it solve a real issue? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. After discussing this offline, I understood why the change was introduced in the first place. Samer will check if the "get_extrinsics_to()" function call is "heavy" and if not, we might have one for publishing to the extrinsic topic and another one with opposite order of frames to publish to the tf topic. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We will have to explain it well in the code, hard to understand why extrinsic msg and static_tf should behave differently. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A quick example on D435i why we needed the change of #2477: Before the fix of PR #2477:
After the fix of PR #2477:
To make sure which result is the right one, all we need is to compare it to
And that makes sense with the new result after the fix. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Now, the next explanation is to elaborate more why we need in addition to calculate extrinsic in the opposite way as @Gilaadb suggest. The first extrinsic we calculated above, was used to publish the depth_to_color topic. To calculate TF from depth to color, we need the something opposite: how to go from Depth To Color ? ex1 = base_profile.get_extrinsics_to(profile); // will be used for depth_to_color topic There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @Gilaadb , After a deeper investigation and testing, I would prefer calculating the extrinsic only once, publish it to the extrinsic topic, and then to manipulate it (invert Matrix and Translation-Vector) for TF topics. I tested with ex1 and ex2, and it looks like it add some time to fetch the extrinsic in both ways, as it goes and enumerate on all extrinsic of the camera (twice). so for example, we get today:
but it should be:
so, we have to invert X,Y,Z also in the Rotation, and I'm on it to find the best way for doing that. |
||
publish_static_tf(transform_ts_, trans, Q, _base_frame_id, FRAME_ID(sip)); | ||
|
||
// Transform stream frame to stream optical 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.
Let's verify if IMU coordinates need to change to match this (like in PR #2680 )
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.
After a deeper check, and after review with @Gilaadb, no need for the PR #2680, since all IMU frames and IMU optical frames are looking good.