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 transform issue in odometry display plugin #1631

Merged
merged 4 commits into from
Aug 19, 2021

Conversation

UniBwTAS
Copy link
Contributor

@UniBwTAS UniBwTAS commented Jun 7, 2021

Description

This pull request fixes a transform issue with odometry plugin for rviz. The previous implementation only shows meaningful Arrows/Axes when the "fixed frame" of rviz is equal to the parent frame of the Odometry message. However, when the fixed frame is different, then the pose of the visuals have to be constantly re-computed because they moved w.r.t. the fixed frame. Currently the transform is calculated just once when the message arrives. We re-compute the transform of the scene node (which corresponds to the parent frame of the Odometry message and contains all the Arrows/Axes) whenever the update (=redraw) callback is triggered.

Additionally we introduced a ref_pose_ which is useful for poses with very large positional values. E.g. the Pose in the UTM frame. Without this ref_pose_ this causes glitches because Ogre only works with single point precision (float). So Ogre has problems to calculate the transform fixed_frame (often base_link or frame close to base_link) -> utm -> base_link. By introducing this ref_pose_ Ogre has to handle much smaller positional values and the offset to the ref_pose_ can be calculated in double point precision.

Image before:

Screenshot from 2021-06-07 18-29-19

Image after:

Screenshot from 2021-06-07 18-56-21

Image for better understanding. In the attached rosbag we compare ground truth odometry against dead-reckoning. It contains the transform utm -> odom -> base_link, one odom message for dead reckoning and odom message for ground truth (gps + imu).

Screenshot from 2021-06-07 17-52-23

Files to reproduce (rosbag & rviz config):
https://www.dropbox.com/sh/mo6zo6akakiap6e/AAAShCSywQxV4sWC5JtjF5TEa?dl=0

Copy link
Contributor

@rhaschke rhaschke left a comment

Choose a reason for hiding this comment

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

I understand that you want to see the past path of your robot/car when using a fixed frame that is attached to the robot.
In principle, I support this PR. However, there are several shortcomings that need to be fixed:
The PR combines several changes, which should be split into individual commits, each providing a concise commit message:

  • Smoothly updating the scene node's position + orientation
  • Introducing ref_pose to be more robust w.r.t. huge positions
  • Cosmetic changes, e.g. renaming length() ➡️ norm()

Renaming and introducing new members breaks ABI, which should be strictly avoided. Can you think of alternative implementations? If not, try to restrict incompatible API/ABI changes to a minimum!

  • Removing last_used_message_ and introducing two new last*message members. Is that really needed? It breaks ABI.
    As far as I can see, you need last_message_ for smoothly updating the scene node's position + orientation.
    Why not moving this update into processMessage()? Then you don't need to remember last_message_?
  • There is a significant drift of the shown trajectory when the fixed transform is set to odom. Could be numerical issues, but could be a conceptual problem as well. Using odom as fixed frame, I expect to see exactly the old behavior.
  • Instead of using the last message's frame as the reference frame, shouldn't you use the same frame_id as reference, e.g. the one from the first seen message? Why happens if odometry messages are expressed w.r.t. a different parent frame in between?

src/rviz/default_plugin/odometry_display.cpp Outdated Show resolved Hide resolved
src/rviz/default_plugin/odometry_display.cpp Outdated Show resolved Hide resolved
src/rviz/default_plugin/odometry_display.h Outdated Show resolved Hide resolved
src/rviz/default_plugin/odometry_display.h Outdated Show resolved Hide resolved
src/rviz/default_plugin/odometry_display.cpp Outdated Show resolved Hide resolved
@UniBwTAS UniBwTAS force-pushed the fix-odometry-plugin branch 2 times, most recently from 7a865e2 to 86067c5 Compare June 22, 2021 10:45
@UniBwTAS
Copy link
Contributor Author

UniBwTAS commented Jun 22, 2021

I split the original commit into 3 distinct ones.

Why not moving this update into processMessage()? Then you don't need to remember last_message_?

The transform has to be calculated continuously when the fixed_frame (e.g. base_link) is moving w.r.t. to the parent frame of the Odometry message (e.g. odom). When the Odometry message comes in not very frequently then the movement of the trajectory does not look very smooth. So I decided to put it into the update() callback. Nevertheless I was able to get rid of last_message_ by simply using the most recent transform available. I think its ok in most scenarios.

There is a significant drift of the shown trajectory when the fixed transform is set to odom. Could be numerical issues, but could be a conceptual problem as well. Using odom as fixed frame, I expect to see exactly the old behavior.

I think the drift you mean only comes from the inaccuracies of 2D (no pitch or roll) dead reckoning (red trajectory) compared to that of inertial navigation system (blue trajectory). For me everything looks fine w.r.t. to visualization. The red trajectory looks the same with and without my commits when setting the fixed_frame to odom. Without my commits it is meaningless to compare red and blue trajectory since the latter has utm as its parent frame and hence for it the fixed frame should be set to utm. (However, UTM origin is quite far away from trajecory)

@UniBwTAS
Copy link
Contributor Author

By the way, using the attached rosbag one can see the importance of ref_pose_ (introduced in the second commit). The blue trajectory looks very ugly due to large positional values in the UTM frame which causes numerical issues:

Screenshot from 2021-06-22 11-28-54

Copy link
Contributor

@rhaschke rhaschke left a comment

Choose a reason for hiding this comment

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

Thanks for cleaning up this PR.

Without my commits it is meaningless to compare red and blue trajectory since the latter has utm as its parent frame and hence for it the fixed frame should be set to utm. (However, UTM origin is quite far away from trajecory)

I don't get this statement. Why shouldn't it be possible use odom as the fixed frame for the blue trajectory? Without your changes (left), the blue trajectory is perfectly displayed on top of the red one, implying that the frame conversion works perfectly fine.
With your changes (right), the blue trajectory drifts over time (i.e. history changes):

comaprison.mp4

It looks like the order of orientation and translation is somehow screwed.

Comment on lines 381 to 382
ROS_ERROR("Error transforming odometry '%s' from frame '%s' to frame '%s'", qPrintable(getName()),
last_used_message_->header.frame_id.c_str(), qPrintable(fixed_frame_));
Copy link
Contributor

Choose a reason for hiding this comment

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

If you are at it: Could you replace this console error output with a display status error (Display::setStatus)?
Remember to reset the status to OK if there is no error.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Even though the left/old one looks better, the right one is correct. Our dead reckoning (red) is really that bad ;) It is only based on wheel turn rates and a yaw gyroscope from the ESP sensor. Therefore it only works in the 2D plane as it cannot detect roll and pitch of the vehicle. The inertial navigation system, on the other hand, is able to measure roll and pitch. Thats why the blue trajectory pitches and rolls w.r.t. to the fixed frame (odom, which is based on our dead reckoning).

That the left one looks meaningful is a coincidence because the trajectories are "similar". New Odometry messages, or more precisely the arrows, are inserted at the right position of the scene but old ones are not updated when the fixed frame moves w.r.t. these arrows.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If you are at it: Could you replace this console error output with a display status error (Display::setStatus)?
Remember to reset the status to OK if there is no error.

I added this in the latest commit. I borrowed the code from grid_display.cpp.

Copy link
Contributor Author

@UniBwTAS UniBwTAS Jun 22, 2021

Choose a reason for hiding this comment

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

I finally removed the setStatus commit again, as this part is already handled by the MessageFilterDisplay Super-Class. Otherwise there would be duplicate Transform items:
Screenshot from 2021-06-22 20-56-12

Copy link
Contributor

Choose a reason for hiding this comment

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

Sure. Sorry for the noise.

@rhaschke
Copy link
Contributor

That the left one looks meaningful is a coincidence because the trajectories are "similar". New Odometry messages, or more precisely the arrows, are inserted at the right position of the scene but old ones are not updated when the fixed frame moves w.r.t. these arrows.

My main concern is that the history of the blue trajectory changes, which shouldn't be the case in my opinion.

@rhaschke
Copy link
Contributor

tf2_eigen package is missing (see buildfarm job)

@UniBwTAS
Copy link
Contributor Author

My main concern is that the history of the blue trajectory changes, which shouldn't be the case in my opinion.

No the history of blue arrows is not changing. Just its parent frame utm moved with respect to fixed_frame odom.

@UniBwTAS UniBwTAS force-pushed the fix-odometry-plugin branch from 86067c5 to dab9066 Compare June 22, 2021 18:38
@UniBwTAS
Copy link
Contributor Author

UniBwTAS commented Jun 22, 2021

tf2_eigen package is missing (see buildfarm job)

I added the tf2_eigen package into the CMakeList.txt and package.xml

Copy link
Contributor

@rhaschke rhaschke left a comment

Choose a reason for hiding this comment

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

My main concern is that the history of the blue trajectory changes, which shouldn't be the case in my opinion.

No the history of blue arrows is not changing. Just its parent frame utm moved with respect to fixed_frame odom.

Sure, but in effect, the past trajectory moves in space, which is wrong in my opinion.

CMakeLists.txt Show resolved Hide resolved
src/rviz/default_plugin/odometry_display.cpp Outdated Show resolved Hide resolved
…ry of arrows/axes

This commit ensures to keep history of arrows/axes even if fixed_frame is different from parent frame_id of Odometry.msg
… message

These large values can occur when transforming GPS to UTM coordinates.
…en current and last position

These large values can occur when transforming GPS to UTM coordinates.
@UniBwTAS UniBwTAS force-pushed the fix-odometry-plugin branch from dab9066 to f880b1e Compare June 22, 2021 19:13
@UniBwTAS
Copy link
Contributor Author

UniBwTAS commented Jun 22, 2021

My main concern is that the history of the blue trajectory changes, which shouldn't be the case in my opinion.

No the history of blue arrows is not changing. Just its parent frame utm moved with respect to fixed_frame odom.

Sure, but in effect, the past trajectory moves in space, which is wrong in my opinion.

In my opinion this is absolutely mandatory since otherwise the visualization makes no sense any more as soon you switch to another fixed_frame than the parent frame of the Odometry message. Compare the first image of this pull request with second one. The first visualization is useless.

@UniBwTAS
Copy link
Contributor Author

I added a video. Maybe you will better see why the history of arrows is important to us and why it should move w.r.t. to the fixed_frame. Here the fixed_frame is set to utm. Now the aerial image and the blue trajectory are fixed. The red trajectory pitches and rolls together with the car (as it is just 2D). Now we can compare how much the origin of the red trajectory drifts over time compared to ground truth blue trajectory:

https://www.dropbox.com/s/p13n2i6f46zsqup/odometry_display_with_utm_as_fixed_frame.mp4?dl=0

@UniBwTAS
Copy link
Contributor Author

The arrows are still fixed as before when fixed_frame is parent frame of odometry messages. In this case the plugin behaves the same as before. However, when the fixed_frame is different from parent frame it now shows meaningful trajectories whereas in previous implementation the visual output was unusable.

@UniBwTAS
Copy link
Contributor Author

UniBwTAS commented Jun 24, 2021

We created a synthetic example which shows the problem with the current implementation:
Current Implementation:

odom-2021-06-24_14.14.12.mp4

New Implementation:

odom-2021-06-24_14.10.51.mp4

The code generating the synthetic example can be found here.

@rhaschke
Copy link
Contributor

Thanks for providing this example. If I now understand correctly, the observed drift comes from slightly different odometries published in the two topics of the rosbag file. Depending on which frame is used as the fixed frame, one or the other curve stays fixed, right?

@AndreasR30
Copy link
Contributor

Thanks for providing this example. If I now understand correctly, the observed drift comes from slightly different odometries published in the two topics of the rosbag file. Depending on which frame is used as the fixed frame, one or the other curve stays fixed, right?

Yes

@rhaschke
Copy link
Contributor

I think this is fine to merge as soon as UniBwTAS#1 is merged into this PR.

@UniBwTAS
Copy link
Contributor Author

I think this is fine to merge as soon as UniBwTAS#1 is merged into this PR.

Done

@UniBwTAS
Copy link
Contributor Author

@rhaschke Is there still a reason not to merge this pull request?

@AndreasR30
Copy link
Contributor

@rhaschke ping

@rhaschke rhaschke merged commit 5b27a0c into ros-visualization:noetic-devel Aug 19, 2021
@rhaschke
Copy link
Contributor

Sorry for the delay merging this.

rhaschke pushed a commit that referenced this pull request Aug 20, 2021
…ry of arrows/axes

This ensures correct history display even if rviz' fixed frame is different from the parent frame_id of Odometry.msg.
Partial backport of #1631.
rhaschke pushed a commit to rhaschke/rviz that referenced this pull request Aug 20, 2021
In order to correctly display the path/history of Odometry messages when the
message's frame_id is moving relative to rviz' fixed frame, we need to update
the pose of the corresponding scene node in each update() cycle.
This is a partial backport of ros-visualization#1631.
@UniBwTAS UniBwTAS deleted the fix-odometry-plugin branch August 20, 2021 16:41
rhaschke added a commit to rhaschke/rviz that referenced this pull request Sep 24, 2021
rhaschke added a commit that referenced this pull request Sep 24, 2021
@rhaschke
Copy link
Contributor

I reverted this PR for the same reason as #1655, namely updating the node's transform doesn't consider the message's timestamp anymore.

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.

3 participants