Skip to content

Commit d0f14cf

Browse files
authored
Merge branch 'sdf12' into ahcorde/usd_to_sdf/fix_world_errors
2 parents cc4bdc0 + 0eea69f commit d0f14cf

14 files changed

+98
-34
lines changed

include/sdf/Model.hh

+5-2
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include <ignition/math/Pose3.hh>
2525
#include <ignition/utils/ImplPtr.hh>
2626
#include "sdf/Element.hh"
27+
#include "sdf/ParserConfig.hh"
2728
#include "sdf/Plugin.hh"
2829
#include "sdf/SemanticPose.hh"
2930
#include "sdf/Types.hh"
@@ -420,7 +421,8 @@ namespace sdf
420421
/// model.
421422
/// Note that parameter passing functionality is not captured with this
422423
/// function.
423-
/// \param[in] _useIncludeTag When true, the model's URI is used to create
424+
/// \param[in] _config Parser configuration. When the ToElementUseIncludeTag
425+
/// policy is true, the model's URI is used to create
424426
/// an SDF `<include>` rather than a `<model>`. The model's URI must be
425427
/// first set using the `Model::SetUri` function. If the model's URI is
426428
/// empty, then a `<model>` element will be generated. The default is true
@@ -429,7 +431,8 @@ namespace sdf
429431
/// is loaded from an `<include>` tag since the parser will
430432
/// automatically expand an `<include>` element to a `<model>` element.
431433
/// \return SDF element pointer with updated model values.
432-
public: sdf::ElementPtr ToElement(bool _useIncludeTag = true) const;
434+
public: sdf::ElementPtr ToElement(
435+
const ParserConfig &_config = ParserConfig::GlobalConfig()) const;
433436

434437
/// \brief Check if a given name exists in the FrameAttachedTo graph at the
435438
/// scope of the model.

include/sdf/ParserConfig.hh

+22
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,28 @@ class SDFORMAT_VISIBLE ParserConfig
174174
/// \brief Get the preserveFixedJoint flag value.
175175
public: bool URDFPreserveFixedJoint() const;
176176

177+
/// \brief Several DOM classes have ToElement() methods that return an
178+
/// XML Element populated from the contents of the DOM object. When
179+
/// populating the details of a model that was included using the
180+
/// <include> tag, one may wish to retain the exact include tag and
181+
/// URI instead of copying the full details of the included model.
182+
/// This method lets you set this behavior.
183+
/// \param[in] _useIncludeTag When true, the model's URI is used to create
184+
/// an SDF `<include>` rather than a `<model>`. The model's URI must be
185+
/// first set using the `Model::SetUri` function. If the model's URI is
186+
/// empty, then a `<model>` element will be generated. The default is true
187+
/// so that URI values are used when ToElement is called from a
188+
/// World object. Make sure to use `Model::SetUri` even when the model
189+
/// is loaded from an `<include>` tag since the parser will
190+
/// automatically expand an `<include>` element to a `<model>` element.
191+
public: void SetToElementUseIncludeTag(bool _useIncludeTag);
192+
193+
/// \brief Get the policy value about whether <include> tags are
194+
/// reconstituted in ToElement() invocations.
195+
/// \return True if include tags are reconstituted, or false
196+
/// if the fully populated model is returned instead.
197+
public: bool ToElementUseIncludeTag() const;
198+
177199
/// \brief Private data pointer.
178200
IGN_UTILS_IMPL_PTR(dataPtr)
179201
};

include/sdf/Root.hh

+4-3
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include <string>
2121
#include <ignition/utils/ImplPtr.hh>
2222

23+
#include "sdf/ParserConfig.hh"
2324
#include "sdf/SDFImpl.hh"
2425
#include "sdf/Types.hh"
2526
#include "sdf/sdf_config.h"
@@ -202,10 +203,10 @@ namespace sdf
202203
/// root.
203204
/// Note that parameter passing functionality is not captured with this
204205
/// function.
205-
/// \param[in] _useIncludeTag This will pass the _useIncludeTag to
206-
/// sdf::Model::ToElement.
206+
/// \param[in] _config Custom parser configuration
207207
/// \return SDF element pointer with updated root values.
208-
public: sdf::ElementPtr ToElement(bool _useIncludeTag = true) const;
208+
public: sdf::ElementPtr ToElement(
209+
const ParserConfig &_config = ParserConfig::GlobalConfig()) const;
209210

210211
/// \brief Private data pointer
211212
IGN_UTILS_UNIQUE_IMPL_PTR(dataPtr)

include/sdf/World.hh

+4-3
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "sdf/Atmosphere.hh"
2828
#include "sdf/Element.hh"
2929
#include "sdf/Gui.hh"
30+
#include "sdf/ParserConfig.hh"
3031
#include "sdf/Plugin.hh"
3132
#include "sdf/Scene.hh"
3233
#include "sdf/Types.hh"
@@ -431,10 +432,10 @@ namespace sdf
431432
/// world.
432433
/// Note that parameter passing functionality is not captured with this
433434
/// function.
434-
/// \param[in] _useIncludeTag This parameter is passed through to the
435-
/// Model::ToElement function.
435+
/// \param[in] _config Custom parser configuration
436436
/// \return SDF element pointer with updated world values.
437-
public: sdf::ElementPtr ToElement(bool _useIncludeTag = true) const;
437+
public: sdf::ElementPtr ToElement(
438+
const ParserConfig &_config = ParserConfig::GlobalConfig()) const;
438439

439440
/// \brief Get the plugins attached to this object.
440441
/// \return A vector of Plugin, which will be empty if there are no

include/sdf/parser.hh

+7
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,13 @@ namespace sdf
4646
SDFORMAT_VISIBLE
4747
bool init(SDFPtr _sdf);
4848

49+
/// \brief Initialize the SDF interface from the embedded root spec file
50+
/// \param[out] _sdf Pointer to an SDF object.
51+
/// \param[in] _config Custom parser configuration
52+
/// \return True if successful.
53+
SDFORMAT_VISIBLE
54+
bool init(SDFPtr _sdf, const ParserConfig &_config);
55+
4956
/// \brief Initialize the SDF interface using a file
5057
/// \param[in] _filename Name of the SDF file
5158
/// \param[out] _sdf Pointer to an SDF object.

src/Model.cc

+7-7
Original file line numberDiff line numberDiff line change
@@ -123,8 +123,8 @@ class sdf::Model::Implementation
123123
/// </world>
124124
///
125125
/// and the included model could also have a plugin. We want the
126-
/// ToElement(true) function to output only the plugin specified in the
127-
/// <include> tag.
126+
/// ToElement() function to output only the plugin specified in the
127+
/// <include> tag when the ToElementUseIncludeTag policy is true..
128128
public: std::vector<Plugin> includePlugins;
129129
};
130130

@@ -974,12 +974,12 @@ void Model::SetUri(const std::string &_uri)
974974
}
975975

976976
/////////////////////////////////////////////////
977-
sdf::ElementPtr Model::ToElement(bool _useIncludeTag) const
977+
sdf::ElementPtr Model::ToElement(const ParserConfig &_config) const
978978
{
979-
if (_useIncludeTag && !this->dataPtr->uri.empty())
979+
if (_config.ToElementUseIncludeTag() && !this->dataPtr->uri.empty())
980980
{
981981
sdf::ElementPtr worldElem(new sdf::Element);
982-
sdf::initFile("world.sdf", worldElem);
982+
sdf::initFile("world.sdf", _config, worldElem);
983983

984984
sdf::ElementPtr includeElem = worldElem->AddElement("include");
985985
includeElem->GetElement("uri")->Set(this->Uri());
@@ -1005,7 +1005,7 @@ sdf::ElementPtr Model::ToElement(bool _useIncludeTag) const
10051005
}
10061006

10071007
sdf::ElementPtr elem(new sdf::Element);
1008-
sdf::initFile("model.sdf", elem);
1008+
sdf::initFile("model.sdf", _config, elem);
10091009
elem->GetAttribute("name")->Set(this->Name());
10101010

10111011
if (!this->dataPtr->canonicalLink.empty())
@@ -1043,7 +1043,7 @@ sdf::ElementPtr Model::ToElement(bool _useIncludeTag) const
10431043

10441044
// Model
10451045
for (const sdf::Model &model : this->dataPtr->models)
1046-
elem->InsertElement(model.ToElement(_useIncludeTag), true);
1046+
elem->InsertElement(model.ToElement(_config), true);
10471047

10481048
// Add in the plugins
10491049
for (const Plugin &plugin : this->dataPtr->plugins)

src/Model_TEST.cc

+3-1
Original file line numberDiff line numberDiff line change
@@ -455,7 +455,9 @@ TEST(DOMModel, Uri)
455455

456456
// ToElement NOT using the URI, which should result in a <model>
457457
{
458-
sdf::ElementPtr elem = model.ToElement(false);
458+
sdf::ParserConfig config = sdf::ParserConfig::GlobalConfig();
459+
config.SetToElementUseIncludeTag(false);
460+
sdf::ElementPtr elem = model.ToElement(config);
459461
elem->PrintValues(" ");
460462

461463
// Should be a <model>

src/ParamPassing.cc

+6-4
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,8 @@ void updateParams(const ParserConfig &_config,
184184
}
185185
else if (actionStr == "replace")
186186
{
187-
ElementPtr newElem = initElementDescription(childElemXml, _errors);
187+
ElementPtr newElem =
188+
initElementDescription(childElemXml, _config, _errors);
188189
if (!newElem)
189190
continue;
190191

@@ -334,12 +335,13 @@ ElementPtr getElementByName(const ElementPtr _elem,
334335

335336
//////////////////////////////////////////////////
336337
ElementPtr initElementDescription(const tinyxml2::XMLElement *_xml,
338+
const ParserConfig &_config,
337339
Errors &_errors)
338340
{
339341
ElementPtr elemDesc = std::make_shared<Element>();
340342
std::string filename = std::string(_xml->Name()) + ".sdf";
341343

342-
if (!initFile(filename, elemDesc))
344+
if (!initFile(filename, _config, elemDesc))
343345
{
344346
// TODO(jenn) not sure if we should load the element anyway
345347
// (e.g., user created their own element), maybe future implementation
@@ -360,7 +362,7 @@ void handleIndividualChildActions(const ParserConfig &_config,
360362
ElementPtr _elem,
361363
Errors &_errors)
362364
{
363-
ElementPtr elemDesc = initElementDescription(_childrenXml, _errors);
365+
ElementPtr elemDesc = initElementDescription(_childrenXml, _config, _errors);
364366
if (!elemDesc)
365367
return;
366368

@@ -504,7 +506,7 @@ void handleIndividualChildActions(const ParserConfig &_config,
504506
void add(const ParserConfig &_config, const std::string &_source,
505507
tinyxml2::XMLElement *_childXml, ElementPtr _elem, Errors &_errors)
506508
{
507-
ElementPtr newElem = initElementDescription(_childXml, _errors);
509+
ElementPtr newElem = initElementDescription(_childXml, _config, _errors);
508510
if (!newElem)
509511
return;
510512

src/ParamPassing.hh

+2
Original file line numberDiff line numberDiff line change
@@ -96,10 +96,12 @@ namespace sdf
9696

9797
/// \brief Initialize an sdf element description from the xml element
9898
/// \param[in] _xml Pointer to xml element
99+
/// \param[in] _config Custom parser configuration
99100
/// \param[out] _errors Captures errors found during parsing
100101
/// \return ElementPtr to the initialized element description,
101102
/// nullptr if undefined/unknown sdf element
102103
ElementPtr initElementDescription(const tinyxml2::XMLElement *_xml,
104+
const ParserConfig &_config,
103105
Errors &_errors);
104106

105107
/// \brief Handles individual actions of children in _childrenXml

src/ParserConfig.cc

+16
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,10 @@ class sdf::ParserConfig::Implementation
4949
/// \brief Flag to explicitly preserve fixed joints when
5050
/// reading the SDF/URDF file.
5151
public: bool preserveFixedJoint = false;
52+
53+
/// \brief Flag to use <include> tags within ToElement methods instead of
54+
/// the fully included model.
55+
public: bool toElementUseIncludeTag = true;
5256
};
5357

5458

@@ -169,3 +173,15 @@ bool ParserConfig::URDFPreserveFixedJoint() const
169173
{
170174
return this->dataPtr->preserveFixedJoint;
171175
}
176+
177+
/////////////////////////////////////////////////
178+
void ParserConfig::SetToElementUseIncludeTag(bool _useIncludeTag)
179+
{
180+
this->dataPtr->toElementUseIncludeTag = _useIncludeTag;
181+
}
182+
183+
/////////////////////////////////////////////////
184+
bool ParserConfig::ToElementUseIncludeTag() const
185+
{
186+
return this->dataPtr->toElementUseIncludeTag;
187+
}

src/Root.cc

+5-5
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ Errors Root::LoadSdfString(const std::string &_sdf, const ParserConfig &_config)
179179
{
180180
Errors errors;
181181
SDFPtr sdfParsed(new SDF());
182-
init(sdfParsed);
182+
init(sdfParsed, _config);
183183

184184
// Read an SDF string, and store the result in sdfParsed.
185185
if (!readString(_sdf, _config, sdfParsed, errors))
@@ -525,16 +525,16 @@ void Root::Implementation::UpdateGraphs(sdf::Model &_model,
525525
}
526526

527527
/////////////////////////////////////////////////
528-
sdf::ElementPtr Root::ToElement(bool _useIncludeTag) const
528+
sdf::ElementPtr Root::ToElement(const ParserConfig &_config) const
529529
{
530530
sdf::ElementPtr elem(new sdf::Element);
531-
sdf::initFile("root.sdf", elem);
531+
sdf::initFile("root.sdf", _config, elem);
532532

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

535535
if (this->Model() != nullptr)
536536
{
537-
elem->InsertElement(this->Model()->ToElement(_useIncludeTag), true);
537+
elem->InsertElement(this->Model()->ToElement(_config), true);
538538
}
539539
else if (this->Light() != nullptr)
540540
{
@@ -548,7 +548,7 @@ sdf::ElementPtr Root::ToElement(bool _useIncludeTag) const
548548
{
549549
// Worlds
550550
for (const sdf::World &world : this->dataPtr->worlds)
551-
elem->InsertElement(world.ToElement(_useIncludeTag), true);
551+
elem->InsertElement(world.ToElement(_config), true);
552552
}
553553

554554
return elem;

src/World.cc

+3-3
Original file line numberDiff line numberDiff line change
@@ -856,10 +856,10 @@ Errors World::Implementation::LoadSphericalCoordinates(
856856
}
857857

858858
/////////////////////////////////////////////////
859-
sdf::ElementPtr World::ToElement(bool _useIncludeTag) const
859+
sdf::ElementPtr World::ToElement(const ParserConfig &_config) const
860860
{
861861
sdf::ElementPtr elem(new sdf::Element);
862-
sdf::initFile("world.sdf", elem);
862+
sdf::initFile("world.sdf", _config, elem);
863863

864864
elem->GetAttribute("name")->Set(this->Name());
865865
elem->GetElement("gravity")->Set(this->Gravity());
@@ -874,7 +874,7 @@ sdf::ElementPtr World::ToElement(bool _useIncludeTag) const
874874

875875
// Models
876876
for (const sdf::Model &model : this->dataPtr->models)
877-
elem->InsertElement(model.ToElement(_useIncludeTag), true);
877+
elem->InsertElement(model.ToElement(_config), true);
878878

879879
// Actors
880880
for (const sdf::Actor &actor : this->dataPtr->actors)

src/parser.cc

+10-4
Original file line numberDiff line numberDiff line change
@@ -369,11 +369,17 @@ static void insertIncludedElement(sdf::SDFPtr _includeSDF,
369369

370370
//////////////////////////////////////////////////
371371
bool init(SDFPtr _sdf)
372+
{
373+
return init(_sdf, ParserConfig::GlobalConfig());
374+
}
375+
376+
//////////////////////////////////////////////////
377+
bool init(SDFPtr _sdf, const ParserConfig &_config)
372378
{
373379
std::string xmldata = SDF::EmbeddedSpec("root.sdf", false);
374380
auto xmlDoc = makeSdfDoc();
375381
xmlDoc.Parse(xmldata.c_str());
376-
return initDoc(&xmlDoc, ParserConfig::GlobalConfig(), _sdf);
382+
return initDoc(&xmlDoc, _config, _sdf);
377383
}
378384

379385
//////////////////////////////////////////////////
@@ -646,7 +652,7 @@ SDFPtr readFile(
646652
{
647653
// Create and initialize the data structure that will hold the parsed SDF data
648654
sdf::SDFPtr sdfParsed(new sdf::SDF());
649-
sdf::init(sdfParsed);
655+
sdf::init(sdfParsed, _config);
650656

651657
// Read an SDF file, and store the result in sdfParsed.
652658
if (!sdf::readFile(_filename, _config, sdfParsed, _errors))
@@ -1587,12 +1593,12 @@ bool readXml(tinyxml2::XMLElement *_xml, ElementPtr _sdf,
15871593
// a new sdf pointer is created here by cloning a fresh sdf template
15881594
// pointer instead of calling init every iteration.
15891595
// SDFPtr includeSDF(new SDF);
1590-
// init(includeSDF);
1596+
// init(includeSDF, _config);
15911597
static SDFPtr includeSDFTemplate;
15921598
if (!includeSDFTemplate)
15931599
{
15941600
includeSDFTemplate.reset(new SDF);
1595-
init(includeSDFTemplate);
1601+
init(includeSDFTemplate, _config);
15961602
}
15971603
SDFPtr includeSDF(new SDF);
15981604
includeSDF->Root(includeSDFTemplate->Root()->Clone());

test/integration/model_dom.cc

+4-2
Original file line numberDiff line numberDiff line change
@@ -700,7 +700,8 @@ TEST(DOMModel, IncludeModelWithPlugin)
700700

701701
// Test ToElement with useInclude == true
702702
{
703-
sdf::ElementPtr elem = model->ToElement(true);
703+
config.SetToElementUseIncludeTag(true);
704+
sdf::ElementPtr elem = model->ToElement(config);
704705

705706
// There should be a uri
706707
ASSERT_TRUE(elem->HasElement("uri"));
@@ -723,7 +724,8 @@ TEST(DOMModel, IncludeModelWithPlugin)
723724
// model SDF which would have two plugins, one from the <include> tag and
724725
// one from the included model
725726
{
726-
sdf::ElementPtr elem = model->ToElement(false);
727+
config.SetToElementUseIncludeTag(false);
728+
sdf::ElementPtr elem = model->ToElement(config);
727729

728730
// There should NOT be a uri
729731
ASSERT_FALSE(elem->HasElement("uri"));

0 commit comments

Comments
 (0)