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 frame export for multi-root models. #914

Merged
merged 3 commits into from
Sep 1, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]


### Added
- Added support for exporting joint position limits to URDF for 1-DoF joints
(prismatic and revolute).
- Added pybind11 python bindings for adding and reading joint limits.

### Fixed
- In the URDF exporter, export only frames attached to the exported traversal [#914](https://github.com/robotology/idyntree/pull/914).
- Fixed handling of the AMENT_PREFIX_PATH environment variable (https://github.com/robotology/idyntree/pull/915).

## [4.2.0] - 2021-07-23
Expand Down
15 changes: 10 additions & 5 deletions src/model_io/urdf/src/URDFModelExport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@
#include <iDynTree/Core/SpatialInertia.h>
#include <iDynTree/Core/Transform.h>
#include <iDynTree/Core/VectorFixSize.h>
#include <iDynTree/Model/Model.h>
#include <iDynTree/Model/Traversal.h>
#include <iDynTree/Model/FixedJoint.h>
#include <iDynTree/Model/Indices.h>
#include <iDynTree/Model/Model.h>
#include <iDynTree/Model/PrismaticJoint.h>
#include <iDynTree/Model/RevoluteJoint.h>
#include <iDynTree/Model/Traversal.h>

#include "URDFParsingUtils.h"

Expand Down Expand Up @@ -503,7 +504,7 @@ bool URDFStringFromModel(const iDynTree::Model & model,
// options.exportFirstBaseLinkAdditionalFrameAsFakeURDFBase is set to false
// If options.exportFirstBaseLinkAdditionalFrameAsFakeURDFBase is set to false,
// baseFakeLinkFrameIndex remains set to FRAME_INVALID_INDEX, a
// and all the additional frames of the base link get exported as child fake links
// and all the additional frames of the base link get exported as child fake links
// in the loop and the end of this function
FrameIndex baseFakeLinkFrameIndex = FRAME_INVALID_INDEX;
std::vector<FrameIndex> frameIndices;
Expand Down Expand Up @@ -546,10 +547,14 @@ bool URDFStringFromModel(const iDynTree::Model & model,
ok = ok && exportLink(*visitedLink, visitedLinkName, model, robot);
}

// Export all the additional frames that are not parent of the base link
// Export all the additional frames.
for (FrameIndex frameIndex=model.getNrOfLinks(); frameIndex < static_cast<FrameIndex>(model.getNrOfFrames()); frameIndex++)
{
if (frameIndex != baseFakeLinkFrameIndex) {
// Check that the frame is not parent of the base link and that the
// frame link is present in the traversal.
if (frameIndex != baseFakeLinkFrameIndex
&& exportTraversal.getTraversalIndexFromLinkIndex(model.getFrameLink(frameIndex)) != TRAVERSAL_INVALID_INDEX) {

ok = ok && exportAdditionalFrame(model.getFrameName(frameIndex),
model.getFrameTransform(frameIndex),
model.getLinkName(model.getFrameLink(frameIndex)),
Expand Down
57 changes: 57 additions & 0 deletions src/model_io/urdf/tests/ModelExporterUnitTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@


#include <iDynTree/Model/Model.h>
#include <iDynTree/Model/RevoluteJoint.h>
#include <iDynTree/ModelIO/ModelLoader.h>
#include <iDynTree/ModelIO/ModelExporter.h>

Expand All @@ -19,6 +20,7 @@
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <memory>
#include <fstream>

using namespace iDynTree;
Expand Down Expand Up @@ -163,6 +165,59 @@ void checkImportExportURDF(std::string fileName)

}

void testFramesNotInTraversal() {
// Create a model with two different roots and export only one.

Model model;
SpatialInertia zeroInertia;
zeroInertia.zero();

Link link;
link.setInertia(zeroInertia);

// Create a 2 links - one joint model.
model.addLink("link_1_1", link);
model.addLink("link_1_2", link);

auto joint = std::make_unique<RevoluteJoint>();
model.addJoint("link_1_1", "link_1_2", "j1", joint.get());

// Add a frame to the body.
model.addAdditionalFrameToLink("link_1_2", "f1", Transform::Identity());

// Add also another link not connected to the other body.
model.addLink("link_2_1", link);

// Add a frame to this body too.
model.addAdditionalFrameToLink("link_2_1", "f2", Transform::Identity());

// Export the model. We want to export only the first body.
ModelExporter exporter;
// Set the root link to link_1_1.
ModelExporterOptions options;
options.baseLink = "link_1_1";
exporter.setExportingOptions(options);

bool ok = exporter.init(model, SensorsList());
ASSERT_IS_TRUE(ok);
std::string urdfString;
ok = exporter.exportModelToString(urdfString);
ASSERT_IS_TRUE(ok);

// Reload the model.
ModelLoader loader;

ok = loader.loadModelFromString(urdfString);
ASSERT_IS_TRUE(ok);
Model modelReloaded = loader.model();

// Check that the reloaded model contains only the 2 links - 1 joint model.
ASSERT_EQUAL_DOUBLE(modelReloaded.getNrOfLinks(), 2);
ASSERT_EQUAL_DOUBLE(modelReloaded.getNrOfJoints(), 1);
ASSERT_EQUAL_DOUBLE(modelReloaded.getNrOfDOFs(), 1);
ASSERT_EQUAL_DOUBLE(modelReloaded.getNrOfFrames(), 2 + 1);
}


int main()
{
Expand All @@ -179,6 +234,8 @@ int main()
checkImportExportURDF(urdfFileName);
}

testFramesNotInTraversal();


return EXIT_SUCCESS;
}