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

Fixed application of <sensor><pose> tags in lumped links during URDF conversion #525

Merged
merged 4 commits into from
Apr 6, 2021

Conversation

peci1
Copy link
Contributor

@peci1 peci1 commented Mar 30, 2021

🦟 Bug fix

Fixes #67 and #378.

Summary

There is a TODO in

https://github.com/osrf/sdformat/blob/8496164cac259e13083023efb06b76a04b1f8d3e/src/parser_urdf.cc#L3374-L3375

which states that <sensor><pose> tags are being silently ignored. This is the culprit of bugs #67 and #378. And of many headaches people spend converting their sensors, finding out after hours that they have to attach them to non-lumped links without any offset for the conversion to work.

This PR fixes the behavior and adds correct processing of <sensor><pose> and <projector><pose> for lumped links.

In addition to ignoring the <sensor><pose> values, there is also weird behavior. First,

https://github.com/osrf/sdformat/blob/8496164cac259e13083023efb06b76a04b1f8d3e/src/parser_urdf.cc#L3378

thinks it deletes the user-specified <sensor><pose> tag.

Second,

https://github.com/osrf/sdformat/blob/8496164cac259e13083023efb06b76a04b1f8d3e/src/parser_urdf.cc#L3406

thinks it adds the computed transform to <sensor><pose>.

The problem is that both of these lines of code work one level higher than they should. (*_blobIt) is a XML snippet containing the <sensor> tag, so there is no direct child <pose> of (*_blobIt). The second line then adds a new element <pose>, but again, as a sibling of <sensor>, not as a child. This is interesting and might have had unforseen consequences (as multiple pose tags are allowed, at least syntactically). Fortunately, there is a guard at

https://github.com/osrf/sdformat/blob/8496164cac259e13083023efb06b76a04b1f8d3e/src/parser_urdf.cc#L2128

that only allows the first child of (*_blobIt) to be passed further. This might look like another bug, but I actually utilized this behavior sealing it for the future (it has been this way for a decade, so...).

Currently, when there is no <sensor><pose> specified, the conversion process doesn't emit any <sensor><pose> in the end, even though it should accumulate something and I see it adding and removing the XML fragments. That is because of the fact it adds the <pose> at wrong level, and in the next level, it deletes/re-adds this sibling of <sensor>. With <sensor><pose> manually specified, it makes it appear in the result (but without the accumulated transform). That's because the DeleteChild function has no effect on <sensor><pose> but deletes the sibling <pose> instead (TinyXML2 doesn't fail when deleting a wrong child).

The fix I propose in this PR is somewhat complicated to grasp on. First idea of just storing _reductionTransform * sensorPose in the <sensor><pose> field does not work as all but the first lump transforms get doubled. What I do is I take the <sensor><pose> when first encountering it and store the <pose> as a sibling of <sensor>. As said earlier, this sibling will not bubble up anywhere, but it is the scratchpad that is needed. <sensor><pose> is then used for storing the actual _reductionTransform * sensorPose. What is important is that the original <sensor><pose> is not updated and we always have access to it in the original form, so that we can take the recursively computed reduction transform and add the sensor pose exactly once.

I was also looking for a nicer way to parse the 6-tuple transform string, but haven't found any usable part of the library. If you know how e.g. sdf::Param could be used to simplify and reuse-ify the code, let me know.

I also added a comprehensive test suite based on both mentioned issues and my experiments. I also verified the change running ign sdf -p on https://github.com/osrf/subt/tree/master/submitted_models/ctu_cras_norlab_absolem_sensor_config_1 model which might go as deep as 10 levels of joints/links (or maybe even more) with sensors at the very tips. I tried exchanging the last link transform for a sensor pose and the result was the same.


As a workaround until this PR is merged, this is what can be done.

  1. Attach the sensor to a non-lumped link and make the origins of the link and the sensor identical. Non-lumped links are set by <preserveFixedJoint>true</preserveFixedJoint>
  2. If you want to have the sensor on a lumped link, you have to manually compute the transformation of the sensor to its nearest non-lumped link. Once you have this transformation, add it in <sensor><pose>. Even though it seems you're duplicating the tree-induced transform by the <pose> tag, you are not because of the reported bugs.

Interestingly, the part of code I fixed was mostly untouched for 8 years. However, it seems that gz sdf -p from Gazebo 9 behaves differently.

Checklist

  • Signed all commits for DCO
  • Added tests
  • Updated documentation (as needed)
  • Updated migration guide (as needed) (how should I do it before submitting the PR when there is need to write down the PR number I don't yet have?)
  • Code check passed (In source directory, run sh tools/code_check.sh)
  • All tests passed (See
    test coverage)
  • While waiting for a review on your PR, please help review
    another open pull request
    to support the maintainers

Note to maintainers: Remember to use Squash-Merge

… conversion.

Fixed <projector>, too.

Signed-off-by: Martin Pecka <[email protected]>
Signed-off-by: Martin Pecka <[email protected]>
@github-actions github-actions bot added the 🔮 dome Ignition Dome label Mar 30, 2021
peci1 added a commit to ctu-vras/subt that referenced this pull request Mar 30, 2021
After this commit, the model.sdf can be exactly recreated by the update_robot_sdf script.

Until gazebosim/sdformat#525 gets merged, `ign sdf -p` does not account for the reduced joint transform when outputting sensors attached to lumped frames. But it copies `<sensor><pose>` verbatim, so I took the old values from SDF and put them temporarily in `<sensor><pose>` where they specify relative position of the sensor to base_link where they get lumped.

Printing of the resulting SDF memory model results in flipping one Euler notation, but it's a 100% equivalent transform. Here's a proof by Ignition Math:

Quaterniond initialized by (-2.19645, -1.5707963267948966, 0) has:
 - coefs: -0.629608 -0.321859 -0.629608 0.321859
 - Euler: -2.19645 -1.5708 0

Quaterniond initialized by (3.1415926535897931, -1.5707963267948966, 0.945143) has:
 - coefs: 0.629608 0.321859 0.629608 -0.321859
 - Euler: -2.19645 -1.5708 0

This proves that the one changed line in model.sdf means no practical change.
@codecov-io
Copy link

Codecov Report

Merging #525 (8496164) into sdf10 (436b28d) will decrease coverage by 0.09%.
The diff coverage is 86.57%.

❗ Current head 8496164 differs from pull request most recent head d8f92de. Consider uploading reports for the commit d8f92de to get more accurate results
Impacted file tree graph

@@            Coverage Diff             @@
##            sdf10     #525      +/-   ##
==========================================
- Coverage   87.75%   87.65%   -0.10%     
==========================================
  Files          62       71       +9     
  Lines        9594    10104     +510     
==========================================
+ Hits         8419     8857     +438     
- Misses       1175     1247      +72     
Impacted Files Coverage Δ
include/sdf/Element.hh 100.00% <ø> (ø)
include/sdf/Filesystem.hh 100.00% <ø> (ø)
include/sdf/Types.hh 100.00% <ø> (ø)
src/SDF.cc 93.33% <ø> (+0.98%) ⬆️
src/Scene.cc 100.00% <ø> (ø)
src/ScopedGraph.hh 98.86% <ø> (ø)
src/SemanticPose.cc 100.00% <ø> (ø)
src/Sensor.cc 80.18% <ø> (-1.90%) ⬇️
src/Sky.cc 100.00% <ø> (ø)
src/Sphere.cc 90.00% <ø> (-3.62%) ⬇️
... and 86 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 436b28d...d8f92de. Read the comment docs.

nkoenig pushed a commit to osrf/subt that referenced this pull request Apr 1, 2021
* Absolem: Sync Xacro: Trivial numeric representation changes.

* Absolem: Sync Xacro: Whitespace only changes.

* Absolem: Sync Xacro: 1e-5 changes.

* Absolem: Sync Xacro: Rotation switched to the opposite direction, but it doesn't matter as it only rotates a symmetrical cube visual.

* Absolem: Sync Xacro: Switch to SDF 1.7 <pose relative_to="">.

No geometrical change (verified visually).

* Absolem: Sync Xacro: Move joint SDF above link.

* Absolem: Sync Xacro: Swap <parent> and <child> tag order.

* Absolem: Sync Xacro: Move joint SDF above link.

* Absolem: Sync Xacro: Move joint SDF above link.

* Absolem: Sync Xacro: Move joint SDF above link.

* Absolem: Sync Xacro: Move joint SDF above link.

* Absolem: Sync Xacro: Move joint SDF above link.

* Absolem: Sync Xacro: Move joint SDF above link.

* Absolem: Sync Xacro: Move joint SDF above link.

* Absolem: Sync Xacro: Move joint SDF above link.

* Absolem: Sync Xacro: Move joint SDF above link.

* Absolem: Sync Xacro: Move joint SDF above link.

* Absolem: Sync Xacro: Move joint SDF above link.

* Absolem: Sync Xacro: Move joint SDF above link.

* Absolem: Sync Xacro: Move joint SDF above link.

* Absolem: Sync Xacro: Move joint SDF above link.

* Absolem: Sync Xacro: Move joint SDF above link.

* Absolem: Sync Xacro: Move joint SDF above link.

* Absolem: Sync Xacro: Move joint SDF above link.

* Absolem: Sync Xacro: Move joint SDF above link.

* Absolem: Sync Xacro: Move joint SDF above link.

* Absolem: Sync Xacro: Move joint SDF above link.

* Absolem: Sync Xacro: Move joint SDF above link.

* Absolem: Sync Xacro: Move joint SDF above link.

* Absolem: Sync Xacro: Move joint SDF above link.

* Absolem: Sync Xacro: Move joint SDF above link.

* Absolem: Sync Xacro: Move joint SDF above link.

* Absolem: Sync Xacro: Move joint SDF above link.

* Absolem: Sync Xacro: Move joint SDF above link.

* Absolem: Sync Xacro: Move joint SDF above link.

* Absolem: Sync Xacro: Move joint SDF above link.

* Absolem: Sync Xacro: Move joint SDF above link.

* Absolem: Sync Xacro: Move joint SDF above link.

* Absolem: Sync Xacro: Move joint SDF above link.

* Absolem: Sync Xacro: Move joint SDF above link.

* Absolem: Sync Xacro: Move joint SDF above link.

* Absolem: Sync Xacro: Move joint SDF above link.

* Absolem: Sync Xacro: Move joint SDF above link.

* Absolem: Sync Xacro: Move joint SDF above link.

* Absolem: Sync Xacro: Move joint SDF above link.

* Absolem: Sync Xacro: Move joint SDF above link.

* Absolem: Sync Xacro: Move joint SDF above link.

* Absolem: Sync Xacro: Move joint SDF above link.

* Absolem: Sync Xacro: Move joint SDF above link.

* Absolem: Sync Xacro: Change IMU and friction parameters in Xacro to correspond to the desired values in SDF.

* Absolem: Sync Xacro: Fixed SDF 1.7 <sensor><pose> wrong lumping.

After this commit, the model.sdf can be exactly recreated by the update_robot_sdf script.

Until gazebosim/sdformat#525 gets merged, `ign sdf -p` does not account for the reduced joint transform when outputting sensors attached to lumped frames. But it copies `<sensor><pose>` verbatim, so I took the old values from SDF and put them temporarily in `<sensor><pose>` where they specify relative position of the sensor to base_link where they get lumped.

Printing of the resulting SDF memory model results in flipping one Euler notation, but it's a 100% equivalent transform. Here's a proof by Ignition Math:

Quaterniond initialized by (-2.19645, -1.5707963267948966, 0) has:
 - coefs: -0.629608 -0.321859 -0.629608 0.321859
 - Euler: -2.19645 -1.5708 0

Quaterniond initialized by (3.1415926535897931, -1.5707963267948966, 0.945143) has:
 - coefs: 0.629608 0.321859 0.629608 -0.321859
 - Euler: -2.19645 -1.5708 0

This proves that the one changed line in model.sdf means no practical change.

* Absolem: Removed empty link visuals as they obstructed the omnicam and were not good for anything else.
Copy link
Contributor

@nkoenig nkoenig left a comment

Choose a reason for hiding this comment

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

Looks good to me. Thanks for the tests.

Copy link
Contributor

@nkoenig nkoenig left a comment

Choose a reason for hiding this comment

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

Minor CI fix needed.

test/integration/urdf_gazebo_extensions.cc Outdated Show resolved Hide resolved
Signed-off-by: Martin Pecka <[email protected]>
@doisyg
Copy link
Contributor

doisyg commented Apr 10, 2021

Is it possible to merge also in edifice/sdf11 ? (as it should fix gazebosim/ros_gz#147)

@chapulina
Copy link
Contributor

Is it possible to merge also in edifice/sdf11 ?

Being forward-ported on #539

@peci1 peci1 changed the title Fixed application of <sensor><pose> tags in lumped linkes during URDF conversion Fixed application of <sensor><pose> tags in lumped links during URDF conversion Apr 15, 2021
scpeters added a commit that referenced this pull request Aug 22, 2022
Backported from #525.

Signed-off-by: Steve Peters <[email protected]>
scpeters added a commit that referenced this pull request Aug 24, 2022
When converting a fixed joint in a URDF file to SDFormat,
by default the contents of the child link are merged into
the parent link, but poses in gazebo extensions such as
//gazebo/sensor/pose are not properly transformed (#378).
This issue has already been fixed in newer branches by #525,
so the test and that fix have been backported and refactored to
reduce code duplication (about 30 lines removed from parser_urdf.cc)
and also fix the treatment of //gazebo/light/pose.

Fixes #378.

Signed-off-by: Steve Peters <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🔮 dome Ignition Dome
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants