Skip to content

Commit 992ab59

Browse files
committed
Merge branch 'ahcorde/sdf_to_usd_links' into adlarkin/sdf_to_usd_joints
2 parents bc74c28 + f816dd4 commit 992ab59

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+2098
-212
lines changed

include/sdf/Error.hh

+1-1
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ namespace sdf
145145
VERSION_DEPRECATED,
146146

147147
/// \brief Merge include is unspported for the type of entity being
148-
/// included.
148+
/// included, or the custom parser does not support merge includes.
149149
MERGE_INCLUDE_UNSUPPORTED,
150150
};
151151

include/sdf/InterfaceElements.hh

+11
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,17 @@ class SDFORMAT_VISIBLE NestedInclude
154154
/// \param[in] _includeElement The include element
155155
public: void SetIncludeElement(sdf::ElementPtr _includeElement);
156156

157+
158+
/// \brief Set whether the interface model is to be merge-included (i.e
159+
/// set the value of `//include/[@merge]`)
160+
/// \param[in] _isMerge True if the interface model is to be merge included
161+
public: void SetIsMerge(bool _isMerge);
162+
163+
/// \brief Whether the interface model is to be merge-included
164+
/// \return If `//include/[@merge]` is set, this returns the value of the
165+
/// attribute, otherwise, nullopt.
166+
public: const std::optional<bool> &IsMerge() const;
167+
157168
/// \brief Provides the URI as specified in `//include/uri`. This may or may
158169
/// not end with a file extension (it will not end with an extension if it
159170
/// refers to a model package).

include/sdf/InterfaceModel.hh

+12-2
Original file line numberDiff line numberDiff line change
@@ -124,10 +124,20 @@ class SDFORMAT_VISIBLE InterfaceModel
124124
/// \brief Gets registered links.
125125
public: const std::vector<sdf::InterfaceLink> &Links() const;
126126

127+
/// \brief Whether the custom parser supports merge-include.
128+
/// \return True if the custom parser supports merge-include
129+
public: bool ParserSupportsMergeInclude() const;
130+
131+
/// \brief Set whether the custom parser supports merge-include.
132+
/// \brief[in] _val True if the custom parser supports merge-include.
133+
public: void SetParserSupportsMergeInclude(bool _val);
134+
127135
/// \brief Recursively invoke the reposture callback if a the callback is set.
128136
/// \param[in] _poseGraph Object used for resolving poses.
129-
private: void InvokeRespostureFunction(
130-
sdf::ScopedGraph<PoseRelativeToGraph> _graph) const;
137+
/// \param[in] _name Override name of graph scope.
138+
private: void InvokeRepostureFunction(
139+
sdf::ScopedGraph<PoseRelativeToGraph> _graph,
140+
const std::optional<std::string> &_name) const;
131141

132142
friend World;
133143
friend Model;

include/sdf/Link.hh

+65
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,13 @@ namespace sdf
7676
/// \sa uint64_t VisualCount() const
7777
public: const Visual *VisualByIndex(const uint64_t _index) const;
7878

79+
/// \brief Get a mutable visual based on an index.
80+
/// \param[in] _index Index of the visual. The index should be in the
81+
/// range [0..VisualCount()).
82+
/// \return Pointer to the visual. Nullptr if the index does not exist.
83+
/// \sa uint64_t VisualCount() const
84+
public: Visual *VisualByIndex(uint64_t _index);
85+
7986
/// \brief Get whether a visual name exists.
8087
/// \param[in] _name Name of the visual to check.
8188
/// \return True if there exists a visual with the given name.
@@ -86,6 +93,11 @@ namespace sdf
8693
/// \return Pointer to the visual. Nullptr if the name does not exist.
8794
public: const Visual *VisualByName(const std::string &_name) const;
8895

96+
/// \brief Get a mutable visual based on a name.
97+
/// \param[in] _name Name of the visual.
98+
/// \return Pointer to the visual. Nullptr if the name does not exist.
99+
public: Visual *VisualByName(const std::string &_name);
100+
89101
/// \brief Get the number of collisions.
90102
/// \return Number of collisions contained in this Link object.
91103
public: uint64_t CollisionCount() const;
@@ -97,6 +109,13 @@ namespace sdf
97109
/// \sa uint64_t CollisionCount() const
98110
public: const Collision *CollisionByIndex(const uint64_t _index) const;
99111

112+
/// \brief Get a mutable collision based on an index.
113+
/// \param[in] _index Index of the collision. The index should be in the
114+
/// range [0..CollisionCount()).
115+
/// \return Pointer to the collision. Nullptr if the index does not exist.
116+
/// \sa uint64_t CollisionCount() const
117+
public: Collision *CollisionByIndex(uint64_t _index);
118+
100119
/// \brief Get whether a collision name exists.
101120
/// \param[in] _name Name of the collision to check.
102121
/// \return True if there exists a collision with the given name.
@@ -107,6 +126,11 @@ namespace sdf
107126
/// \return Pointer to the collision. Nullptr if the name does not exist.
108127
public: const Collision *CollisionByName(const std::string &_name) const;
109128

129+
/// \brief Get a mutable collision based on a name.
130+
/// \param[in] _name Name of the collision.
131+
/// \return Pointer to the collision. Nullptr if the name does not exist.
132+
public: Collision *CollisionByName(const std::string &_name);
133+
110134
/// \brief Get the number of lights.
111135
/// \return Number of lights contained in this Link object.
112136
public: uint64_t LightCount() const;
@@ -118,6 +142,13 @@ namespace sdf
118142
/// \sa uint64_t LightCount() const
119143
public: const Light *LightByIndex(const uint64_t _index) const;
120144

145+
/// \brief Get a mutable light based on an index.
146+
/// \param[in] _index Index of the light. The index should be in the
147+
/// range [0..LightCount()).
148+
/// \return Pointer to the light. Nullptr if the index does not exist.
149+
/// \sa uint64_t LightCount() const
150+
public: Light *LightByIndex(uint64_t _index);
151+
121152
/// \brief Get whether a light name exists.
122153
/// \param[in] _name Name of the light to check.
123154
/// \return True if there exists a light with the given name.
@@ -128,6 +159,11 @@ namespace sdf
128159
/// \return Pointer to the light. Nullptr if the name does not exist.
129160
public: const Light *LightByName(const std::string &_name) const;
130161

162+
/// \brief Get a mutable light based on a name.
163+
/// \param[in] _name Name of the light.
164+
/// \return Pointer to the light. Nullptr if the name does not exist.
165+
public: Light *LightByName(const std::string &_name);
166+
131167
/// \brief Get the number of sensors.
132168
/// \return Number of sensors contained in this Link object.
133169
public: uint64_t SensorCount() const;
@@ -139,6 +175,13 @@ namespace sdf
139175
/// \sa uint64_t SensorCount() const
140176
public: const Sensor *SensorByIndex(const uint64_t _index) const;
141177

178+
/// \brief Get a mutable sensor based on an index.
179+
/// \param[in] _index Index of the sensor. The index should be in the
180+
/// range [0..SensorCount()).
181+
/// \return Pointer to the sensor. Nullptr if the index does not exist.
182+
/// \sa uint64_t SensorCount() const
183+
public: Sensor *SensorByIndex(uint64_t _index);
184+
142185
/// \brief Get whether a sensor name exists.
143186
/// \param[in] _name Name of the sensor to check.
144187
/// \return True if there exists a sensor with the given name.
@@ -151,6 +194,13 @@ namespace sdf
151194
/// \sa bool SensorNameExists(const std::string &_name) const
152195
public: const Sensor *SensorByName(const std::string &_name) const;
153196

197+
/// \brief Get a mutable sensor based on a name.
198+
/// \param[in] _name Name of the sensor.
199+
/// \return Pointer to the sensor. Nullptr if a sensor with the given name
200+
/// does not exist.
201+
/// \sa bool SensorNameExists(const std::string &_name) const
202+
public: Sensor *SensorByName(const std::string &_name);
203+
154204
/// \brief Get the number of particle emitters.
155205
/// \return Number of particle emitters contained in this Link object.
156206
public: uint64_t ParticleEmitterCount() const;
@@ -164,6 +214,14 @@ namespace sdf
164214
public: const ParticleEmitter *ParticleEmitterByIndex(
165215
const uint64_t _index) const;
166216

217+
/// \brief Get a mutable particle emitter based on an index.
218+
/// \param[in] _index Index of the particle emitter.
219+
/// The index should be in the range [0..ParticleEmitterCount()).
220+
/// \return Pointer to the particle emitter. Nullptr if the index does
221+
/// not exist.
222+
/// \sa uint64_t ParticleEmitterCount() const
223+
public: ParticleEmitter *ParticleEmitterByIndex(uint64_t _index);
224+
167225
/// \brief Get whether a particle emitter name exists.
168226
/// \param[in] _name Name of the particle emitter to check.
169227
/// \return True if there exists a particle emitter with the given name.
@@ -177,6 +235,13 @@ namespace sdf
177235
public: const ParticleEmitter *ParticleEmitterByName(
178236
const std::string &_name) const;
179237

238+
/// \brief Get a mutable particle emitter based on a name.
239+
/// \param[in] _name Name of the particle emitter.
240+
/// \return Pointer to the particle emitter. Nullptr if a particle emitter
241+
/// with the given name does not exist.
242+
/// \sa bool ParticleEmitterNameExists(const std::string &_name) const
243+
public: ParticleEmitter *ParticleEmitterByName(const std::string &_name);
244+
180245
/// \brief Get the inertial value for this link. The inertial object
181246
/// consists of the link's mass, a 3x3 rotational inertia matrix, and
182247
/// a pose for the inertial reference frame. The units for mass is

include/sdf/Model.hh

+11
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include <memory>
2121
#include <string>
2222
#include <utility>
23+
#include <vector>
2324
#include <ignition/math/Pose3.hh>
2425
#include <ignition/utils/ImplPtr.hh>
2526
#include "sdf/Element.hh"
@@ -44,6 +45,8 @@ namespace sdf
4445
struct PoseRelativeToGraph;
4546
struct FrameAttachedToGraph;
4647
template <typename T> class ScopedGraph;
48+
using InterfaceModelConstPtr = std::shared_ptr<const InterfaceModel>;
49+
4750

4851
class SDFORMAT_VISIBLE Model
4952
{
@@ -410,12 +413,20 @@ namespace sdf
410413
private: void SetFrameAttachedToGraph(
411414
sdf::ScopedGraph<FrameAttachedToGraph> _graph);
412415

416+
/// \brief Get the list of merged interface models.
417+
/// \return The list of merged interface models.
418+
private: const std::vector<std::pair<std::optional<sdf::NestedInclude>,
419+
sdf::InterfaceModelConstPtr>> &MergedInterfaceModels() const;
420+
413421
/// \brief Allow Root::Load, World::SetPoseRelativeToGraph, or
414422
/// World::SetFrameAttachedToGraph to call SetPoseRelativeToGraph and
415423
/// SetFrameAttachedToGraph
416424
friend class Root;
417425
friend class World;
418426

427+
// Allow ModelWrapper from FrameSemantics.cc to call MergedInterfaceModels
428+
friend struct ModelWrapper;
429+
419430
/// \brief Private data pointer.
420431
IGN_UTILS_IMPL_PTR(dataPtr)
421432
};

src/CMakeLists.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ if (BUILD_TESTING)
6868
endif()
6969

7070
if (TARGET UNIT_FrameSemantics_TEST)
71-
target_sources(UNIT_FrameSemantics_TEST PRIVATE FrameSemantics.cc)
71+
target_sources(UNIT_FrameSemantics_TEST PRIVATE FrameSemantics.cc Utils.cc)
7272
endif()
7373

7474
if (TARGET UNIT_ParamPassing_TEST)

src/FrameSemantics.cc

+109
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636

3737
#include "FrameSemantics.hh"
3838
#include "ScopedGraph.hh"
39+
#include "Utils.hh"
3940

4041
namespace sdf
4142
{
@@ -306,6 +307,17 @@ struct LinkWrapper : public WrapperBase
306307
{
307308
}
308309

310+
/// \brief Constructor from name and pose data (without sdf::Link or
311+
/// sdf::InterfaceLink)
312+
LinkWrapper(const std::string &_name, const ignition::math::Pose3d &_rawPose,
313+
const std::string &_relativeTo)
314+
: WrapperBase{_name, "Link", FrameType::LINK},
315+
rawPose(_rawPose),
316+
rawRelativeTo(_relativeTo),
317+
relativeTo(rawRelativeTo)
318+
{
319+
}
320+
309321
/// \brief Raw pose of the entity.
310322
const ignition::math::Pose3d rawPose;
311323
/// \brief The //pose/@relative_to attribute.
@@ -339,6 +351,18 @@ struct FrameWrapper : public WrapperBase
339351
{
340352
}
341353

354+
/// \brief Constructor from name, pose, and attachement data (without
355+
/// sdf::Frame or sdf::InterfaceFrame)
356+
FrameWrapper(const std::string &_name, const ignition::math::Pose3d &_rawPose,
357+
const std::string &_relativeTo, const std::string &_attachedTo)
358+
: WrapperBase{_name, "Frame", FrameType::FRAME},
359+
rawPose(_rawPose),
360+
rawRelativeTo(_relativeTo),
361+
attachedTo(_attachedTo),
362+
relativeTo(rawRelativeTo.empty() ? attachedTo : rawRelativeTo)
363+
{
364+
}
365+
342366
/// \brief Raw pose of the entity.
343367
const ignition::math::Pose3d rawPose;
344368
/// \brief The //pose/@relative_to attribute.
@@ -386,6 +410,15 @@ struct JointWrapper : public WrapperBase
386410
const std::string relativeTo;
387411
};
388412

413+
/// \brief Placement frame information
414+
struct PlacementFrameInfo
415+
{
416+
/// \brief Computed name of the proxy model frame
417+
std::string proxyName;
418+
/// \brief The name of placement frame from //include/placement_frame.
419+
std::string placementFrameName;
420+
};
421+
389422
/// \brief Wrapper for sdf::Model and sdf::InterfaceModel
390423
struct ModelWrapper : public WrapperBase
391424
{
@@ -422,6 +455,56 @@ struct ModelWrapper : public WrapperBase
422455
this->models.emplace_back(*_model.InterfaceModelNestedIncludeByIndex(i),
423456
*_model.InterfaceModelByIndex(i));
424457
}
458+
for (const auto &[nestedInclude, model] : _model.MergedInterfaceModels())
459+
{
460+
const std::string proxyModelFrameName = computeMergedModelProxyFrameName(
461+
nestedInclude->LocalModelName().value_or(model->Name()));
462+
463+
std::string poseRelativeTo =
464+
nestedInclude->IncludePoseRelativeTo().value_or("");
465+
if (poseRelativeTo.empty())
466+
{
467+
poseRelativeTo = "__model__";
468+
}
469+
this->frames.emplace_back(proxyModelFrameName,
470+
nestedInclude->IncludeRawPose().value_or(
471+
model->ModelFramePoseInParentFrame()),
472+
poseRelativeTo, model->CanonicalLinkName());
473+
474+
for (const auto &item : model->Links())
475+
{
476+
this->links.emplace_back(item.Name(), item.PoseInModelFrame(),
477+
proxyModelFrameName);
478+
}
479+
for (const auto &item : model->Frames())
480+
{
481+
std::string attachedTo = item.AttachedTo();
482+
if (item.AttachedTo() == "__model__")
483+
{
484+
attachedTo = proxyModelFrameName;
485+
}
486+
this->frames.emplace_back(item.Name(), item.PoseInAttachedToFrame(),
487+
attachedTo, attachedTo);
488+
}
489+
for (const auto &item : model->Joints())
490+
{
491+
std::string childName = item.ChildName();
492+
if (item.ChildName() == "__model__")
493+
{
494+
childName = proxyModelFrameName;
495+
}
496+
this->joints.emplace_back(sdf::InterfaceJoint(item.Name(), childName,
497+
item.PoseInChildFrame()));
498+
}
499+
if (nestedInclude->PlacementFrame().has_value())
500+
{
501+
this->mergedModelPlacements.push_back(
502+
{proxyModelFrameName, *nestedInclude->PlacementFrame()});
503+
}
504+
505+
// Skip adding nested interface models because they are already included
506+
// in the parent model's list of nested models.
507+
}
425508
}
426509

427510
/// \brief Constructor that takes an sdf::NestedInclude and
@@ -479,6 +562,8 @@ struct ModelWrapper : public WrapperBase
479562
std::vector<JointWrapper> joints;
480563
/// \brief Children nested models and interface models.
481564
std::vector<ModelWrapper> models;
565+
/// \brief Placement frame information for each merged model.
566+
std::vector<PlacementFrameInfo> mergedModelPlacements;
482567

483568
/// \brief Helper function to add children of interface models.
484569
private: void AddInterfaceChildren(const sdf::InterfaceModel &_ifaceModel)
@@ -1014,6 +1099,30 @@ Errors wrapperBuildPoseRelativeToGraph(ScopedGraph<PoseRelativeToGraph> &_out,
10141099

10151100
outModel.UpdateEdge(rootToModel, resolvedModelPose);
10161101
}
1102+
1103+
// For each merge model, update the edge between the parent model and the
1104+
// proxy model frame to take into account the placement frame used when
1105+
// nesting the merged model via //include.
1106+
for (const auto &[proxyName, placementFrameName] :
1107+
_model.mergedModelPlacements)
1108+
{
1109+
auto proxyId = outModel.VertexIdByName(proxyName);
1110+
auto modelToProxy =
1111+
outModel.Graph().EdgeFromVertices(modelFrameId, proxyId);
1112+
const auto rawPose = modelToProxy.Data();
1113+
1114+
// We have to first set the edge data to an identity pose to be able to call
1115+
// resolveModelPoseWithPlacementFrame, which in turn calls
1116+
// sdf::resolvePoseRelativeToRoot. We will later update the edge after the
1117+
// pose is calculated.
1118+
outModel.UpdateEdge(modelToProxy, ignition::math::Pose3d::Zero);
1119+
ignition::math::Pose3d resolvedModelPose;
1120+
sdf::Errors resolveErrors =
1121+
resolveModelPoseWithPlacementFrame(rawPose,
1122+
placementFrameName, outModel, resolvedModelPose);
1123+
errors.insert(errors.end(), resolveErrors.begin(), resolveErrors.end());
1124+
outModel.UpdateEdge(modelToProxy, resolvedModelPose);
1125+
}
10171126
return errors;
10181127
}
10191128
/////////////////////////////////////////////////

0 commit comments

Comments
 (0)