Skip to content

Commit

Permalink
Merge 093e6a8 into 9641718
Browse files Browse the repository at this point in the history
  • Loading branch information
nkoenig authored Mar 4, 2022
2 parents 9641718 + 093e6a8 commit 9309982
Show file tree
Hide file tree
Showing 10 changed files with 414 additions and 9 deletions.
22 changes: 22 additions & 0 deletions include/sdf/Root.hh
Original file line number Diff line number Diff line change
Expand Up @@ -142,16 +142,31 @@ namespace sdf
/// \return A pointer to the model, nullptr if it doesn't exist
public: const sdf::Model *Model() const;

/// \brief Set the model object. This will override any existing model,
/// actor, and light object.
/// \param[in] _model The model to use.
public: void SetModel(const sdf::Model &_model);

/// \brief Get a pointer to the light object if it exists.
///
/// \return A pointer to the light, nullptr if it doesn't exist
public: const sdf::Light *Light() const;

/// \brief Set the light object. This will override any existing model,
/// actor, and light object.
/// \param[in] _light The light to use.
public: void SetLight(const sdf::Light &_light);

/// \brief Get a pointer to the actor object if it exists.
///
/// \return A pointer to the actor, nullptr if it doesn't exist
public: const sdf::Actor *Actor() const;

/// \brief Set the actor object. This will override any existing model,
/// actor, and light object.
/// \param[in] _actor The actor to use.
public: void SetActor(const sdf::Actor &_actor);

/// \brief Get a pointer to the SDF element that was generated during
/// load.
/// \return SDF element pointer. The value will be nullptr if Load has
Expand Down Expand Up @@ -183,6 +198,13 @@ namespace sdf
/// an error code and message. An empty vector indicates no error.
public: Errors UpdateGraphs();

/// \brief Create and return an SDF element filled with data from this
/// root.
/// \param[in] _useIncludeTag This will pass the _useIncludeTag to
/// sdf::Model::ToElement.
/// \return SDF element pointer with updated root values.
public: sdf::ElementPtr ToElement(bool _useIncludeTag = true) const;

/// \brief Private data pointer
IGN_UTILS_UNIQUE_IMPL_PTR(dataPtr)
};
Expand Down
4 changes: 3 additions & 1 deletion include/sdf/World.hh
Original file line number Diff line number Diff line change
Expand Up @@ -429,8 +429,10 @@ namespace sdf

/// \brief Create and return an SDF element filled with data from this
/// world.
/// \param[in] _useIncludeTag This parameter is passed through to the
/// Model::ToElement function.
/// \return SDF element pointer with updated world values.
public: sdf::ElementPtr ToElement() const;
public: sdf::ElementPtr ToElement(bool _useIncludeTag = true) const;

/// \brief Get the plugins attached to this object.
/// \return A vector of Plugin, which will be empty if there are no
Expand Down
42 changes: 40 additions & 2 deletions src/Model.cc
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,25 @@ class sdf::Model::Implementation
/// can be loaded from.
public: std::string uri = "";

/// \brief Model plugins.
/// \brief All of the model plugins.
public: std::vector<Plugin> plugins;

/// \brief The model plugins that were specified only in an <include> tag.
/// This data structure is used by the ToElement() function to accurately
/// reproduce the <include> tag.
///
/// For example, a world could be:
/// <world name="default">
/// <include>
/// <uri>test_model_with_plugin</uri>
/// <plugin name="plugin_name" filename="plugin_filename"/>
/// </include>
/// </world>
///
/// and the included model could also have a plugin. We want the
/// ToElement(true) function to output only the plugin specified in the
/// <include> tag.
public: std::vector<Plugin> includePlugins;
};

/////////////////////////////////////////////////
Expand Down Expand Up @@ -387,6 +404,19 @@ Errors Model::Load(sdf::ElementPtr _sdf, const ParserConfig &_config)
this->dataPtr->plugins);
errors.insert(errors.end(), pluginErrors.begin(), pluginErrors.end());

// Check whether the model was loaded from an <include> tag. If so, set
// the URI and capture the plugins.
if (_sdf->GetIncludeElement() && _sdf->GetIncludeElement()->HasElement("uri"))
{
sdf::ElementPtr includeElem = _sdf->GetIncludeElement();
this->SetUri(includeElem->Get<std::string>("uri"));

Errors includePluginErrors = loadRepeated<Plugin>(includeElem, "plugin",
this->dataPtr->includePlugins);
errors.insert(errors.end(), includePluginErrors.begin(),
includePluginErrors.end());
}

return errors;
}

Expand Down Expand Up @@ -961,7 +991,15 @@ sdf::ElementPtr Model::ToElement(bool _useIncludeTag) const
"relative_to")->Set<std::string>(this->dataPtr->poseRelativeTo);
}
includeElem->GetElement("static")->Set(this->Static());
includeElem->GetElement("placement_frame")->Set(this->PlacementFrameName());
if (!this->dataPtr->placementFrameName.empty())
{
includeElem->GetElement("placement_frame")->Set(
this->PlacementFrameName());
}

// Output the plugins
for (const Plugin &plugin : this->dataPtr->includePlugins)
includeElem->InsertElement(plugin.ToElement(), true);

return includeElem;
}
Expand Down
53 changes: 51 additions & 2 deletions src/Root.cc
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ class sdf::Root::Implementation
public: void UpdateGraphs(sdf::Model &_model, sdf::Errors &_errors);

/// \brief Version string
public: std::string version = "";
public: std::string version = SDF_VERSION;

/// \brief The worlds specified under the root SDF element
public: std::vector<World> worlds;
Expand Down Expand Up @@ -210,7 +210,7 @@ Errors Root::Load(SDFPtr _sdf, const ParserConfig &_config)

// Get the SDF version.
std::pair<std::string, bool> versionPair =
this->dataPtr->sdf->Get<std::string>("version", SDF_VERSION);
this->dataPtr->sdf->Get<std::string>("version", this->dataPtr->version);

// Check that the version exists. Exit if the version is missing.
// readFile will fail if the version is missing, so this
Expand Down Expand Up @@ -402,18 +402,37 @@ const Model *Root::Model() const
return std::get_if<sdf::Model>(&this->dataPtr->modelLightOrActor);
}

/////////////////////////////////////////////////
void Root::SetModel(const sdf::Model &_model)
{
this->dataPtr->modelLightOrActor = _model;
}

/////////////////////////////////////////////////
const Light *Root::Light() const
{
return std::get_if<sdf::Light>(&this->dataPtr->modelLightOrActor);
}


/////////////////////////////////////////////////
void Root::SetLight(const sdf::Light &_light)
{
this->dataPtr->modelLightOrActor = _light;
}

/////////////////////////////////////////////////
const Actor *Root::Actor() const
{
return std::get_if<sdf::Actor>(&this->dataPtr->modelLightOrActor);
}

/////////////////////////////////////////////////
void Root::SetActor(const sdf::Actor &_actor)
{
this->dataPtr->modelLightOrActor = _actor;
}

/////////////////////////////////////////////////
sdf::ElementPtr Root::Element() const
{
Expand Down Expand Up @@ -504,3 +523,33 @@ void Root::Implementation::UpdateGraphs(sdf::Model &_model,
this->modelPoseRelativeToGraph = createPoseRelativeToGraph(_model, _errors);
_model.SetPoseRelativeToGraph(this->modelPoseRelativeToGraph);
}

/////////////////////////////////////////////////
sdf::ElementPtr Root::ToElement(bool _useIncludeTag) const
{
sdf::ElementPtr elem(new sdf::Element);
sdf::initFile("root.sdf", elem);

elem->GetAttribute("version")->Set(this->Version());

if (this->Model() != nullptr)
{
elem->InsertElement(this->Model()->ToElement(_useIncludeTag), true);
}
else if (this->Light() != nullptr)
{
elem->InsertElement(this->Light()->ToElement(), true);
}
else if (this->Actor() != nullptr)
{
elem->InsertElement(this->Actor()->ToElement(), true);
}
else
{
// Worlds
for (const sdf::World &world : this->dataPtr->worlds)
elem->InsertElement(world.ToElement(_useIncludeTag), true);
}

return elem;
}
167 changes: 165 additions & 2 deletions src/Root_TEST.cc
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ TEST(DOMRoot, Construction)
{
sdf::Root root;
EXPECT_EQ(nullptr, root.Element());
EXPECT_EQ("", root.Version());
EXPECT_EQ(SDF_VERSION, root.Version());
EXPECT_FALSE(root.WorldNameExists("default"));
EXPECT_FALSE(root.WorldNameExists(""));
EXPECT_EQ(0u, root.WorldCount());
Expand Down Expand Up @@ -203,7 +203,7 @@ TEST(DOMRoot, StringActorSdfParse)
TEST(DOMRoot, Set)
{
sdf::Root root;
EXPECT_STREQ("", root.Version().c_str());
EXPECT_STREQ(SDF_VERSION, root.Version().c_str());
root.SetVersion(SDF_PROTOCOL_VERSION);
EXPECT_STREQ(SDF_PROTOCOL_VERSION, root.Version().c_str());
}
Expand Down Expand Up @@ -339,3 +339,166 @@ TEST(DOMRoot, MutableByIndex)
w->SetName("world2");
EXPECT_EQ("world2", root.WorldByIndex(0)->Name());
}

/////////////////////////////////////////////////
TEST(DOMRoot, ToElementEmpty)
{
sdf::Root root;

sdf::ElementPtr elem = root.ToElement();
ASSERT_NE(nullptr, elem);

sdf::Root root2;
root2.LoadSdfString(elem->ToString(""));

EXPECT_EQ(SDF_VERSION, root2.Version());
}

/////////////////////////////////////////////////
TEST(DOMRoot, ToElementModel)
{
sdf::Root root;

sdf::Actor actor1;
actor1.SetName("actor1");
root.SetActor(actor1);

sdf::Light light1;
light1.SetName("light1");
root.SetLight(light1);

sdf::Model model1;
model1.SetName("model1");
root.SetModel(model1);

ASSERT_NE(nullptr, root.Model());
ASSERT_EQ(nullptr, root.Light());
ASSERT_EQ(nullptr, root.Actor());
EXPECT_EQ(0u, root.WorldCount());

// Convert to sdf::ElementPtr
sdf::ElementPtr elem = root.ToElement();
ASSERT_NE(nullptr, elem);

sdf::Root root2;
root2.LoadSdfString(elem->ToString(""));

EXPECT_EQ(SDF_VERSION, root2.Version());

ASSERT_NE(nullptr, root2.Model());
EXPECT_EQ("model1", root2.Model()->Name());

ASSERT_EQ(nullptr, root2.Actor());
ASSERT_EQ(nullptr, root2.Light());
EXPECT_EQ(0u, root2.WorldCount());
}

/////////////////////////////////////////////////
TEST(DOMRoot, ToElementLight)
{
sdf::Root root;

sdf::Model model1;
model1.SetName("model1");
root.SetModel(model1);

sdf::Actor actor1;
actor1.SetName("actor1");
root.SetActor(actor1);

sdf::Light light1;
light1.SetName("light1");
root.SetLight(light1);

ASSERT_NE(nullptr, root.Light());
ASSERT_EQ(nullptr, root.Model());
ASSERT_EQ(nullptr, root.Actor());
EXPECT_EQ(0u, root.WorldCount());

// Convert to sdf::ElementPtr
sdf::ElementPtr elem = root.ToElement();
ASSERT_NE(nullptr, elem);

sdf::Root root2;
root2.LoadSdfString(elem->ToString(""));

EXPECT_EQ(SDF_VERSION, root2.Version());

ASSERT_NE(nullptr, root2.Light());
EXPECT_EQ("light1", root2.Light()->Name());

ASSERT_EQ(nullptr, root2.Model());
ASSERT_EQ(nullptr, root2.Actor());
EXPECT_EQ(0u, root2.WorldCount());
}

/////////////////////////////////////////////////
TEST(DOMRoot, ToElementActor)
{
sdf::Root root;

sdf::Model model1;
model1.SetName("model1");
root.SetModel(model1);

sdf::Light light1;
light1.SetName("light1");
root.SetLight(light1);

sdf::Actor actor1;
actor1.SetName("actor1");
root.SetActor(actor1);

ASSERT_NE(nullptr, root.Actor());
ASSERT_EQ(nullptr, root.Light());
ASSERT_EQ(nullptr, root.Model());
EXPECT_EQ(0u, root.WorldCount());

// Convert to sdf::ElementPtr
sdf::ElementPtr elem = root.ToElement();
ASSERT_NE(nullptr, elem);

sdf::Root root2;
root2.LoadSdfString(elem->ToString(""));

EXPECT_EQ(SDF_VERSION, root2.Version());

ASSERT_NE(nullptr, root2.Actor());
EXPECT_EQ("actor1", root2.Actor()->Name());

ASSERT_EQ(nullptr, root2.Model());
ASSERT_EQ(nullptr, root2.Light());
EXPECT_EQ(0u, root2.WorldCount());
}

/////////////////////////////////////////////////
TEST(DOMRoot, ToElementWorld)
{
sdf::Root root;

sdf::World world1;
world1.SetName("world1");
root.AddWorld(world1);

sdf::World world2;
world2.SetName("world2");
root.AddWorld(world2);

EXPECT_EQ(2u, root.WorldCount());

// Convert to sdf::ElementPtr
sdf::ElementPtr elem = root.ToElement();
ASSERT_NE(nullptr, elem);

sdf::Root root2;
root2.LoadSdfString(elem->ToString(""));

EXPECT_EQ(SDF_VERSION, root2.Version());
EXPECT_EQ(2u, root2.WorldCount());

ASSERT_NE(nullptr, root2.WorldByIndex(0));
EXPECT_EQ("world1", root2.WorldByIndex(0)->Name());

ASSERT_NE(nullptr, root2.WorldByIndex(1));
EXPECT_EQ("world2", root2.WorldByIndex(1)->Name());
}
Loading

0 comments on commit 9309982

Please sign in to comment.