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

Add support for exporting additional frames in ModelExporter #557

Merged

Conversation

traversaro
Copy link
Member

@traversaro traversaro commented Aug 19, 2019

This PR builds on the top of #554, so it will not be ready to be merged until that PR is merged before.

Relevant commits:

  • 5fab702 : Add Model::getLinkAdditionalFrames method
  • b77faa5 : Add support for exporting additional frames in ModelExporter

All addition come with the respective unit tests and documentation.

@traversaro traversaro force-pushed the feature/URDFexportAdditionalFrames branch 2 times, most recently from 2173398 to 726c917 Compare August 23, 2019 12:52
@traversaro
Copy link
Member Author

@prashanthr05 this PR is now ready for review, thanks!

}

frameIndices.resize(0);
for (FrameIndex frameIndex=this->getNrOfLinks(); frameIndex < this->getNrOfFrames(); frameIndex++) {
Copy link
Contributor

@prashanthr05 prashanthr05 Aug 24, 2019

Choose a reason for hiding this comment

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

For quicker understanding and readabilityof code, it would be great to document the relationship between the link serialization and the additional frames serialization, also here.

Copy link
Contributor

Choose a reason for hiding this comment

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

I see it is documented here,

* The frame indices between 0 and getNrOfLinks()-1 are always assigned to the

In that case, we can give a pointer to this documentation here.

Copy link
Member Author

Choose a reason for hiding this comment

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

Fixed in 81e7f7a .

* @param[out] frames a vector of FrameIndex of the frame indeces attached to the specified link index,
* @return true if the specified link is a valid link, false otherwise.
*/
bool getLinkAdditionalFrames(const LinkIndex lnkIndex, std::vector<FrameIndex>& frameIndeces) const;
Copy link
Contributor

@prashanthr05 prashanthr05 Aug 24, 2019

Choose a reason for hiding this comment

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

Does it also make sense to have an overload with linkName as input argument?

Not specifically for this scenario. but in general nice-to-have feature in the Model API.

Copy link
Contributor

Choose a reason for hiding this comment

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

Similar overload for frameNames as output?

Copy link
Member Author

Choose a reason for hiding this comment

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

It could make sense, but I would leave this to a separate PR. Probably we can have a guideline to have for all methods in iDynTree::Model both the index and the names one, and then have a PR for add names-variant for all methods missing them. Can you open a new issue on this?

@@ -63,11 +63,30 @@ class ModelExporterOptions
*
* Furthermore, currently the model exporter only exports a subset of the features
* supported in iDynTree::Model. In particular, the following features are not exported:
* * Additional frames
*
Copy link
Contributor

@prashanthr05 prashanthr05 Aug 24, 2019

Choose a reason for hiding this comment

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

I like the way how Additional Frames disappeared ;D

* due to workaround a bug in official %KDL parser used in ROS (see https://github.com/ros/kdl_parser/issues/27 for more info). For this reason,
* if the selected base_link has at least one additional frame, the first additional frame of the base link is added as a **parent** fake URDF link,
* instead as a **child** fake URDF link as done with the rest of %iDynTree's additional frames. If no additional frame is available for the base link,
* the base link of the URDF will have a mass, and will generate a warning then used with the ROS's [`kdl_parser`](https://github.com/ros/kdl_parser) .
Copy link
Contributor

Choose a reason for hiding this comment

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

Wow, is this the reason why Travis is failing in this pull request robotology/icub-models-generator#113 related to icub-model-generator?

Copy link
Member Author

Choose a reason for hiding this comment

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

I do not think so, I think that is an error is always there even if non-failing PRs.

Copy link
Contributor

@prashanthr05 prashanthr05 Aug 27, 2019

Choose a reason for hiding this comment

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

What I thought was, due to the parent-child direction inverting workaround, the root_tlink-base_link gets inverted parent reference and the base link might have a mass throwing an error?

Because, the segfaults was due to the fact that root_link has a described and the exact words from the failure read...

The root link 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.
No link found with name base_link

Would that be possible?

Copy link
Member Author

Choose a reason for hiding this comment

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

Because, the segfaults was due to the fact that root_link has a described and the exact words from the failure read...

Are you sure that the same error were not present in the successful builds?

Copy link
Contributor

Choose a reason for hiding this comment

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

Are you sure that the same error were not present in the successful builds?

Uhmm.. of this, I am not sure.

* <parent_element>
* <link name="<frame_name>"/>
* <joint name="<frame_name>_fixed_joint" type="fixed">
* <origin xyz="0.1 0.2 0.3" rpy="0 0 3.1416"/>
Copy link
Contributor

@prashanthr05 prashanthr05 Aug 24, 2019

Choose a reason for hiding this comment

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

The numbers here are misleading. Can we change them to placeholders?

UPDATE: Ok, given that this is just an example of it might look on the generated URDF, please ignore my comment.


// Export fake link
xmlNodePtr link_xml = xmlNewChild(parent_element, NULL, BAD_CAST "link", NULL);
xmlNewProp(link_xml, BAD_CAST "name", BAD_CAST frame_name.c_str());
Copy link
Contributor

Choose a reason for hiding this comment

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

If any future developer asks why there is BAD_CAST all across the code, we could possibly document this https://stackoverflow.com/questions/45058878/why-libxml2-uses-bad-cast-everywhere-in-a-c-c-code somewhere in the code ?

Copy link
Member Author

Choose a reason for hiding this comment

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

Fixed in ee923f4 .

// child
xmlNodePtr child_xml = xmlNewChild(joint_xml, NULL, BAD_CAST "child", NULL);
xmlNewProp(child_xml, BAD_CAST "link", BAD_CAST child_of_fake_joint.c_str());

Copy link
Contributor

Choose a reason for hiding this comment

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

I see a common trend of using the method xmlNewChild and xmlNewProp sequentially. Can we not make a function that does the composition of these two steps?

Copy link
Contributor

@prashanthr05 prashanthr05 Aug 24, 2019

Choose a reason for hiding this comment

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

I see this also depends on how many properties we add in sequence. So the complexity of having a single function to handle all properties might be big. But can still be handled by a vector of key-value pairs.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, this could make sense, but at least initially I preferred to avoid start writing a C++ wrapper on the top of the libxml2 API, without having a clear idea about our need from the libxml2's API. Furthermore, I am a bit afraid that adding a layer between the libxml2's API and the parser could impact readability. However, a C++ wrapper could make sense, but I would prefer to complete the URDF exporter implementation to understand our needs, and eventually do an libxml2 abstraction as a refactoring. What do you think?

Copy link
Contributor

Choose a reason for hiding this comment

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

Agreed.

@traversaro
Copy link
Member Author

I should have addressed all your comments @prashanthr05 .


// TODO(traversaro) : uncomment the following line when frames are correctly handled by the exporter
// ASSERT_EQUAL_DOUBLE(model.getNrOfFrames(), modelReloaded.getNrOfLinks());

Copy link
Contributor

Choose a reason for hiding this comment

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

Thank you for remembering to remove this. Sorry I missed this in the review!

@traversaro traversaro force-pushed the feature/URDFexportAdditionalFrames branch from 805d1fe to 358beda Compare August 27, 2019 09:05
@traversaro
Copy link
Member Author

Thanks @prashanthr05 !

@traversaro traversaro merged commit af0effb into robotology:devel Aug 27, 2019
@traversaro traversaro mentioned this pull request Sep 2, 2019
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.

2 participants