robotology / idyntree

Multibody Dynamics Library designed for Free Floating Robots
BSD 3-Clause "New" or "Revised" License
177 stars 67 forks source link

ModelExporter: exporting a frame attached to the base link, make that fake link the base link #1201

Open Nicogene opened 2 months ago

Nicogene commented 2 months ago

@mfussi66 @kaidegast and I noticed this strange behaviour when trying to export frames attached to the link that is passed as baseLink to the ModelExporterOptions. Basically what happens is that the frame exported become the new baseLink and the fixed joint between the base link and the frame is reversed (the frame is the parent, the base link is the child).

Here is the python snipped I used for testing this strange behaviour:

import idyntree.swig as idyn

model = idyn.Model()
# Let's add the base link
model.addLink("root_link",idyn.Link())
# Let's add a frame to the base link
model.addAdditionalFrameToLink("root_link", "root_link_frame", idyn.Transform.Identity())
export_options = idyn.ModelExporterOptions()
export_options.robotExportedName = "foo"
export_options.baseLink = "root_link"
model_exporter= idyn.ModelExporter()
model_exporter.init(model)
model_exporter.setExportingOptions(export_options)
model_exporter.exportModelToFile("model.urdf")

And here is the resulting URDF:

<?xml version="1.0"?>
<robot name="foo">
  <link name="root_link_frame"/>
  <joint name="root_link_frame_fixed_joint" type="fixed">
    <origin xyz="0 0 0" rpy="0 -0 0"/>
    <parent link="root_link_frame"/>
    <child link="root_link"/>
  </joint>
  <link name="root_link">
    <inertial>
      <mass value="0"/>
      <origin xyz="0 0 0" rpy="0 -0 0"/>
      <inertia ixx="5.981524883892869e-154" ixy="6.013469529641847e-154" ixz="1.7174754640937156e-259" iyy="9.635107555939643e+140" iyz="1.9608652923211385e+243" izz="-4.538015473251081e+279"/>
    </inertial>
  </link>
</robot>

cc @traversaro

traversaro commented 2 months ago

The exportFirstBaseLinkAdditionalFrameAsFakeURDFBase option of ModelExporterOptions (https://robotology.github.io/idyntree/structiDynTree_1_1ModelExporterOptions.html#a776c8f98ae5c58e038e3a1962f9fd318) controls this behavior. The history behind it is a bit convoluted, but the basic reason is that one of the URDF parser used by ROS has a bug that basically ignores the mass/inertia of the root link (see https://github.com/ros/kdl_parser/issues/27 and https://github.com/ros/robot_model/issues/6), so having exportFirstBaseLinkAdditionalFrameAsFakeURDFBase set to true by default make sures that if a the model has a fake link in the base, when loaded in kdl the root link is not ignored.

However, if you need to avoid this behaviour, you can set it to False:

export_options.exportFirstBaseLinkAdditionalFrameAsFakeURDFBase = False
traversaro commented 2 months ago

fyi @kaidegast @mfussi66 @Nicogene

Nicogene commented 2 months ago

The exportFirstBaseLinkAdditionalFrameAsFakeURDFBase option of ModelExporterOptions (robotology.github.io/idyntree/structiDynTree_1_1ModelExporterOptions.html#a776c8f98ae5c58e038e3a1962f9fd318) controls this behavior. The history behind it is a bit convoluted, but the basic reason is that one of the URDF parser used by ROS has a bug that basically ignores the mass/inertia of the root link (see ros/kdl_parser#27 and ros/robot_model#6), so having exportFirstBaseLinkAdditionalFrameAsFakeURDFBase set to true by default make sures that if a the model has a fake link in the base, when loaded in kdl the root link is not ignored.

However, if you need to avoid this behaviour, you can set it to False:

export_options.exportFirstBaseLinkAdditionalFrameAsFakeURDFBase = False

Thanks @traversaro! Do you think it is safe to set it to false in creo2urdf?

traversaro commented 2 months ago

Thanks @traversaro! Do you think it is safe to set it to false in creo2urdf?

Sure. The only downside is that users loading the created by creo2urdf will get a warning:

The root link has an inertia specified in the URDF, but KDL does not support a root link with an inertia. As a workaround, you can add an extra dummy link to your URDF.

from https://github.com/ros/kdl_parser/blob/74d4ee3bc6938de8ae40a700997baef06114ea1b/kdl_parser/src/kdl_parser.cpp#L240-L242 when they will load the URDF in ROS's robot-state-publisher. As the robot-state-publisher does not use dynamics, this is not a big problem, just a minor annoyance.