Skip to content

Commit

Permalink
World: handle name collisions like Model (#1311)
Browse files Browse the repository at this point in the history
* Add 1.6 world file for existing test
* Add failing 1.7 test
* Update Migration guide

Signed-off-by: Steve Peters <scpeters@openrobotics.org>
  • Loading branch information
scpeters authored Aug 22, 2023
1 parent af88891 commit 88e343b
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 15 deletions.
18 changes: 18 additions & 0 deletions Migration.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,20 @@ forward programmatically.
This document aims to contain similar information to those files
but with improved human-readability..

## libsdformat 13.x to 14.x

### Additions

1. **New SDFormat specification version 1.11**
+ Details about the 1.10 to 1.11 transition are explained below in this same
document

### Modifications

1. World class only renames frames with name collisions if original file version
is 1.6 or earlier. Name collisions in newer files will cause DUPLICATE_NAME
errors, which now matches the behavior of the Model class.

## libsdformat 12.x to 13.x

### Additions
Expand Down Expand Up @@ -554,6 +568,10 @@ ABI was broken for `sdf::Element`, and restored on version 11.2.1.
+ Changed to `_fixed_joint_lump__` to avoid confusion with scoped names
+ [BitBucket pull request 245](https://osrf-migration.github.io/sdformat-gh-pages/#!/osrf/sdformat/pull-requests/245)

## SDFormat specification 1.10 to 1.11

### Additions

## SDFormat specification 1.9 to 1.10

### Additions
Expand Down
42 changes: 29 additions & 13 deletions src/World.cc
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include <unordered_set>
#include <vector>
#include <optional>
#include <gz/math/SemanticVersion.hh>
#include <gz/math/Vector3.hh>

#include "sdf/Actor.hh"
Expand Down Expand Up @@ -134,6 +135,7 @@ Errors World::Load(sdf::ElementPtr _sdf, const ParserConfig &_config)
Errors errors;

this->dataPtr->sdf = _sdf;
gz::math::SemanticVersion sdfVersion(_sdf->OriginalVersion());

// Check that the provided SDF element is a <world>
// This is an error that cannot be recovered, so return an error.
Expand Down Expand Up @@ -284,21 +286,35 @@ Errors World::Load(sdf::ElementPtr _sdf, const ParserConfig &_config)
std::string frameName = frame.Name();
if (frameNames.count(frameName) > 0)
{
frameName += "_frame";
int i = 0;
while (frameNames.count(frameName) > 0)
// This frame has a name collision
if (sdfVersion < gz::math::SemanticVersion(1, 7))
{
frameName = frame.Name() + "_frame" + std::to_string(i++);
// This came from an old file, so try to workaround by renaming frame
frameName += "_frame";
int i = 0;
while (frameNames.count(frameName) > 0)
{
frameName = frame.Name() + "_frame" + std::to_string(i++);
}
std::stringstream ss;
ss << "Frame with name [" << frame.Name() << "] "
<< "in world with name [" << this->Name() << "] "
<< "has a name collision, changing frame name to ["
<< frameName << "].";
Error err(ErrorCode::WARNING, ss.str());
enforceConfigurablePolicyCondition(
_config.WarningsPolicy(), err, errors);

frame.SetName(frameName);
}
else
{
std::stringstream ss;
ss << "Frame with name [" << frame.Name() << "] "
<< "in world with name [" << this->Name() << "] "
<< "has a name collision. Please rename this frame.";
errors.push_back({ErrorCode::DUPLICATE_NAME, ss.str()});
}
std::stringstream ss;
ss << "Frame with name [" << frame.Name() << "] "
<< "in world with name [" << this->Name() << "] "
<< "has a name collision, changing frame name to ["
<< frameName << "].\n";
Error err(ErrorCode::WARNING, ss.str());
enforceConfigurablePolicyCondition(
_config.WarningsPolicy(), err, errors);
frame.SetName(frameName);
}
frameNames.insert(frameName);
}
Expand Down
2 changes: 1 addition & 1 deletion test/integration/error_output.cc
Original file line number Diff line number Diff line change
Expand Up @@ -359,7 +359,7 @@ TEST(ErrorOutput, WorldErrorOutput)
"model with name[common_name] already exists."));
EXPECT_NE(std::string::npos, errors[2].Message().find(
"Frame with name [common_name] in world with name [test_world] has a name"
" collision, changing frame name to [common_name_frame]."));
" collision. Please rename this frame."));
// Check nothing has been printed
EXPECT_TRUE(buffer.str().empty()) << buffer.str();
}
Expand Down
18 changes: 17 additions & 1 deletion test/integration/world_dom.cc
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ TEST(DOMWorld, Load)
TEST(DOMWorld, LoadModelFrameSameName)
{
const std::string testFile =
sdf::testing::TestFile("sdf", "world_model_frame_same_name.sdf");
sdf::testing::TestFile("sdf", "world_model_frame_same_name_1_6.sdf");

// Load the SDF file
sdf::Root root;
Expand Down Expand Up @@ -227,6 +227,22 @@ TEST(DOMWorld, LoadModelFrameSameName)
EXPECT_EQ(Pose(0, -2, 3, 0, 0, 0), pose);
}

/////////////////////////////////////////////////
TEST(DOMWorld, LoadModelFrameSameName_1_7)
{
const std::string testFile =
sdf::testing::TestFile("sdf", "world_model_frame_same_name.sdf");

// Load the SDF file
sdf::Root root;
auto errors = root.Load(testFile);
for (auto e : errors)
std::cout << e << std::endl;
EXPECT_FALSE(errors.empty());
EXPECT_EQ(10u, errors.size());
EXPECT_EQ(errors[0].Code(), sdf::ErrorCode::DUPLICATE_NAME);
}

/////////////////////////////////////////////////
TEST(DOMWorld, NestedModels)
{
Expand Down
20 changes: 20 additions & 0 deletions test/sdf/world_model_frame_same_name_1_6.sdf
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?xml version="1.0" ?>
<sdf version='1.6'>
<world name="world_model_frame_same_name">

<model name="base">
<pose>1 0 0 0 0 0</pose>
<link name="L"/>
</model>

<model name="ground">
<pose>0 2 0 0 0 0</pose>
<link name="L"/>
</model>

<frame name="ground">
<pose>0 0 3 0 0 0</pose>
</frame>

</world>
</sdf>

0 comments on commit 88e343b

Please sign in to comment.