MoffKalast / vizanti

A mission planner and visualizer for controlling outdoor ROS robots.
https://wiki.ros.org/vizanti
BSD 3-Clause "New" or "Revised" License
145 stars 30 forks source link

Inverted map rotation? #52

Closed giovanidiniz closed 10 months ago

giovanidiniz commented 10 months ago

Hi, @MoffKalast,

I've playing some more with Vizanti. It's working very well for me! One thing I've been trying to understand, though. It seems to me the satellite tiles rotation is inverted.

I've been digging to see if I had something weird going with my TFs,, but I'm pretty sure they are correct at this point. Can you point me to how I would go about inverting the tile rotation?

Thanks!

MoffKalast commented 10 months ago

Hmm interesting, are you using a nav stack that rotates the satelite fix frame so it matches a lidar map? I've worked with a setup like that once and it can indeed result in the map being in all kinds of weird orientations.

Generally the tile rotations are derived from the navsatfix frame -> fixed_frame transform.

https://github.com/MoffKalast/vizanti/blob/3685c6a6b66421dd1deafb9231888385313ba540/public/templates/satelite/satelite_script.js#L118

There's likely some rotation in your transform chain that's causing it, and it may in fact be completely correct for the way the nav stack works. It would be a good addition to have the option to rotate the entire rendering display at some point, but for now I suppose you could try adding an additional tf_static frame for viewing that nullifies the yaw rotation and use that as the viewing fixed_frame?

Could also be that this line should not be inverting the angle, I'll run some tests later to verify.

https://github.com/MoffKalast/vizanti/blob/3685c6a6b66421dd1deafb9231888385313ba540/public/templates/satelite/satelite_script.js#L123

giovanidiniz commented 10 months ago

Ok, for now, replacing the transformed poses with the following works well enough for me:

const transformed = tf.transformPose(
                map_fix.header.frame_id,
                map_fix.header.frame_id,
                meters,
                new Quaternion()
            );

I did encounter another underlying bug with the tile rendering. When the vehicle is moving, it seems the tiles are not being properly translated. I can see tiles moving relative to static frames (e.g., "map" in my case)

giovanidiniz commented 10 months ago

I replaced lines 96/97 in the code with these:

const offsetX = initial_fix_data.offset.x - i * fix_data.metersSize;
const offsetY = initial_fix_data.offset.y - j * fix_data.metersSize;

And that fixed the issue with the translating icons, except when the robot goes from one tile to another. In which case its position jumps with a distance that looks suspiciously similar to the fix_data offset.

Anyhow, just wanted to contribute my investigation so far

MoffKalast commented 10 months ago

Ah I think I see what you mean.

https://github.com/MoffKalast/vizanti/assets/9977799/70b0a453-28c9-46b8-990f-bf5503e487d2

These are two satelite renderings overlaid one on top of the other for different topics publishing the same data but in different forms (/odom as fixed frame):

Since the raw fix is being published relative to base_link that would mean that the entire transform, rotation included, applies to that data. Navsatfix on the other hand can't provide rotational rata so it doesn't invert and nullify the other rotations as it would need to and is just along for the ride. This is correct in terms of transform calculation, but in practice it's obviously a problem since no receiver publishes fix data with correct global rotation.

Overall this reminds me of the issue that both rviz and vizanti have regarding occupancy grid map timestamps, in that maps actually render wrong when viewed from non-static frames because the last known timestamp transform (which can be seconds in the past) will move them around if they're not being updated at the same rate as the most rapidly updated frame.

Rviz's solution there was to provide a default-on "ignore timestamps" checkbox which prevents this jumping behaviour, which isn't ideal but since I don't have any better ideas yet I've implemented the same here.

So if we're being pragmatic, there could just be a checkbox that ignores rotational transforms (enabled by default, since localization systems do typically publish a zero rotation origin fix anyway which would work fine), so that the map doesn't jump around when viewing raw data.

No guarantee that the base_link rotation would be consistent with the map rotation though, since you do need something that actually provides global rotation for that to make any kind of sense. Another issue is that if the fix is in a frame that is correctly rotated to compensate for some rotational offset, it will be ignored and probably lead to much frustration unless people know to disable that check. I suppose we could automatically notify and disable it if the frame_id has a non-identity quaternion? Wouldn't work for raw data directly in base link though, so idk.

MoffKalast commented 10 months ago

Here's how an implementation of that would work, note that the rotation is only correct in this case because both /odom and /map are already corrected by the localization stack to conform to world rotation.

https://github.com/MoffKalast/vizanti/assets/9977799/4dc195d6-c357-4fd5-87ed-528e6b82692a

I went to check what rviz_satelite does in this situation and it also seems to just ignore the rotations, so that's at least consistent now I suppose:

image

I've pushed the change to noetic-feature and ros2-feature for testing, let me know if it makes sense on your end. The checkbox is disabled by default for now so it should behave the same as before until you check it.

giovanidiniz commented 10 months ago

I tested your changes over the weekend a ton of times and they do the trick for me. I'll close this issue for now. Thanks so much for the help!