@@ -73,8 +73,8 @@ namespace ROS2
73
73
struct JointToAttachedModel
74
74
{
75
75
AZStd::string m_fullyQualifiedName;
76
- const sdf::Joint* m_joint;
77
- const sdf::Model* m_attachedModel;
76
+ const sdf::Joint* m_joint{} ;
77
+ const sdf::Model* m_attachedModel{} ;
78
78
};
79
79
// this is a unique ordered vector
80
80
AZStd::vector<JointToAttachedModel> m_joints;
@@ -121,41 +121,120 @@ namespace ROS2
121
121
struct LinkToAttachedModel
122
122
{
123
123
AZStd::string m_fullyQualifiedName;
124
- const sdf::Link* m_link;
125
- const sdf::Model* m_attachedModel;
124
+ const sdf::Link* m_link{} ;
125
+ const sdf::Model* m_attachedModel{} ;
126
126
};
127
127
// this is a unique ordered vector
128
128
AZStd::vector<LinkToAttachedModel> m_links;
129
129
};
130
130
LinksMapper linksMapper;
131
131
132
- auto GetAllLinksFromModel = [&linksMapper](const sdf::Model& model, const Utils::ModelStack&) -> Utils::VisitModelResponse
132
+ struct ModelMapper
133
+ {
134
+ struct NestedModelToAttachedModel
135
+ {
136
+ AZStd::string m_fullyQualifiedName;
137
+ const sdf::Model* m_nestedModel{};
138
+ const sdf::Model* m_attachedModel{};
139
+ };
140
+ // this is a unique ordered vector
141
+ AZStd::vector<NestedModelToAttachedModel> m_models;
142
+ };
143
+ ModelMapper modelMapper;
144
+
145
+ auto GetAllLinksAndSetModelHierarchy = [&linksMapper, &modelMapper](const sdf::Model& model, const Utils::ModelStack& modelStack) -> Utils::VisitModelResponse
133
146
{
134
147
// As the VisitModels function visits nested models by default, gatherNestedModelLinks is set to false
135
148
constexpr bool gatherNestedModelLinks = false ;
136
149
auto linksForModel = Utils::GetAllLinks (model, gatherNestedModelLinks);
137
150
for (const auto & [fullyQualifiedName, link] : linksForModel)
138
151
{
139
152
// Push back the mapping of link to attached model into the ordered vector
140
- LinksMapper::LinkToAttachedModel linkToAttachedModel{ AZStd::string (fullyQualifiedName.c_str (), fullyQualifiedName.size ()),
141
- link,
142
- &model };
153
+ AZStd::string fullLinkName (fullyQualifiedName.c_str (), fullyQualifiedName.size ());
154
+ LinksMapper::LinkToAttachedModel linkToAttachedModel{ AZStd::move (fullLinkName), link, &model };
143
155
linksMapper.m_links .push_back (AZStd::move (linkToAttachedModel));
144
156
}
157
+
158
+ // Use the model stack to create a mapping from the current model
159
+ // to the parent model it is attached to.
160
+ // If the current model has no parent model the attached model is set to nullptr
161
+ std::string stdFullModelName;
162
+ for (const sdf::Model& ancestorModel : modelStack)
163
+ {
164
+ stdFullModelName = sdf::JoinName (stdFullModelName, ancestorModel.Name ());
165
+ }
166
+ stdFullModelName = sdf::JoinName (stdFullModelName, model.Name ());
167
+ AZStd::string fullModelName (stdFullModelName.c_str (), stdFullModelName.size ());
168
+ ModelMapper::NestedModelToAttachedModel nestedModelToAttachedModel;
169
+ nestedModelToAttachedModel.m_fullyQualifiedName = AZStd::move (fullModelName);
170
+ nestedModelToAttachedModel.m_nestedModel = &model;
171
+ nestedModelToAttachedModel.m_attachedModel = !modelStack.empty () ? &modelStack.back ().get () : nullptr ;
172
+ modelMapper.m_models .push_back (AZStd::move (nestedModelToAttachedModel));
173
+
145
174
return Utils::VisitModelResponse::VisitNestedAndSiblings;
146
175
};
147
176
148
- // Gather all links from all the models in the SDF
149
- Utils::VisitModels (*m_root, GetAllLinksFromModel , visitNestedModels);
177
+ // Gather all links and add a mapping of nested model -> parent model for each model in the SDF
178
+ Utils::VisitModels (*m_root, GetAllLinksAndSetModelHierarchy , visitNestedModels);
150
179
151
180
// Build up a list of all entities created as a part of processing the file.
152
181
AZStd::vector<AZ::EntityId> createdEntities;
153
- AZStd::unordered_map<const sdf::Link*, AzToolsFramework::Prefab::PrefabEntityResult> createdLinks;
154
182
AZStd::unordered_map<const sdf::Model*, AzToolsFramework::Prefab::PrefabEntityResult> createdModels;
183
+
184
+ AZStd::unordered_map<const sdf::Link*, AzToolsFramework::Prefab::PrefabEntityResult> createdLinks;
155
185
AZStd::unordered_map<AZStd::string, const sdf::Link*> links;
156
- for ([[maybe_unused]] const auto & [fullLinkName, linkPtr, attachedModel] : linksMapper.m_links )
186
+
187
+ // Create an entity for each model
188
+ for ([[maybe_unused]] const auto & [fullModelName, modelPtr, _] : modelMapper.m_models )
189
+ {
190
+ // Create entities for each model in the SDF
191
+ if (AzToolsFramework::Prefab::PrefabEntityResult createModelEntityResult = CreateEntityForModel (*modelPtr);
192
+ createModelEntityResult)
193
+ {
194
+ AZ::EntityId createdModelEntityId = createModelEntityResult.GetValue ();
195
+ // Add the model entity to the created entity list so that it gets added to the prefab
196
+ createdEntities.emplace_back (createdModelEntityId);
197
+
198
+ std::string modelName = modelPtr->Name ();
199
+ AZStd::string azModelName (modelName.c_str (), modelName.size ());
200
+ AZStd::lock_guard<AZStd::mutex> lck (m_statusLock);
201
+ m_status.emplace (azModelName, AZStd::string::format (" [model] created as: %s" , createdModelEntityId.ToString ().c_str ()));
202
+ createdModels.emplace (modelPtr, createModelEntityResult);
203
+ }
204
+ }
205
+
206
+ // ! Setup the parent hierarchy for the nested models
207
+ for ([[maybe_unused]] const auto & [_, modelPtr, parentModelPtr] : modelMapper.m_models )
208
+ {
209
+ // If there is no parent model, then the model would be at the top level of the hiearachy
210
+ if (parentModelPtr == nullptr || modelPtr == nullptr )
211
+ {
212
+ continue ;
213
+ }
214
+ // Create entities for each model in the SDF
215
+ AZ::EntityId modelEntityId;
216
+ if (auto modelIt = createdModels.find (modelPtr); modelIt != createdModels.end () && modelIt->second )
217
+ {
218
+ modelEntityId = modelIt->second .GetValue ();
219
+ }
220
+
221
+ AZ::EntityId parentModelEntityId;
222
+ if (auto parentModelIt = createdModels.find (parentModelPtr); parentModelIt != createdModels.end () && parentModelIt->second )
223
+ {
224
+ parentModelEntityId = parentModelIt->second .GetValue ();
225
+ }
226
+
227
+ // If the both the parent model and current model entity exist
228
+ // set the current model transform component parent to the parent model
229
+ if (parentModelEntityId.IsValid () && modelEntityId.IsValid ())
230
+ {
231
+ PrefabMakerUtils::SetEntityParent (modelEntityId, parentModelEntityId);
232
+ }
233
+ }
234
+
235
+ // Create an entity for each link and set the parent to be the model entity where the link is attached
236
+ for ([[maybe_unused]] const auto & [_, linkPtr, attachedModel] : linksMapper.m_links )
157
237
{
158
- // Create entities for the model containing the link
159
238
AZ::EntityId modelEntityId;
160
239
if (attachedModel != nullptr )
161
240
{
@@ -166,26 +245,7 @@ namespace ROS2
166
245
modelEntityId = modelIt->second .GetValue ();
167
246
}
168
247
}
169
- else
170
- {
171
- if (AzToolsFramework::Prefab::PrefabEntityResult createModelEntityResult = CreateEntityForModel (*attachedModel);
172
- createModelEntityResult)
173
- {
174
- modelEntityId = createModelEntityResult.GetValue ();
175
- // Add the model entity to the created entity list
176
- // so that it gets added to the prefab
177
- createdEntities.emplace_back (modelEntityId);
178
-
179
- std::string modelName = attachedModel->Name ();
180
- AZStd::string azModelName (modelName.c_str (), modelName.size ());
181
- AZStd::lock_guard<AZStd::mutex> lck (m_statusLock);
182
- m_status.emplace (azModelName, AZStd::string::format (" created as: %s" , modelEntityId.ToString ().c_str ()));
183
- createdModels.emplace (attachedModel, createModelEntityResult);
184
- }
185
- }
186
-
187
248
}
188
-
189
249
// Add all link as children of their attached model entity by default
190
250
createdLinks[linkPtr] = AddEntitiesForLink (*linkPtr, attachedModel, modelEntityId, createdEntities);
191
251
}
@@ -202,11 +262,11 @@ namespace ROS2
202
262
AZStd::lock_guard<AZStd::mutex> lck (m_statusLock);
203
263
if (result.IsSuccess ())
204
264
{
205
- m_status.emplace (azLinkName, AZStd::string::format (" created as: %s" , result.GetValue ().ToString ().c_str ()));
265
+ m_status.emplace (azLinkName, AZStd::string::format (" [link] created as: %s" , result.GetValue ().ToString ().c_str ()));
206
266
}
207
267
else
208
268
{
209
- m_status.emplace (azLinkName, AZStd::string::format (" failed : %s" , result.GetError ().c_str ()));
269
+ m_status.emplace (azLinkName, AZStd::string::format (" [link] failed : %s" , result.GetError ().c_str ()));
210
270
}
211
271
}
212
272
@@ -390,7 +450,7 @@ namespace ROS2
390
450
AZStd::lock_guard<AZStd::mutex> lck (m_statusLock);
391
451
auto result = m_jointsMaker.AddJointComponent (jointPtr, childEntity.GetValue (), leadEntity.GetValue ());
392
452
m_status.emplace (
393
- azJointName, AZStd::string::format (" %s: %llu" , result.IsSuccess () ? " created as" : " failed" , result.GetValue ()));
453
+ azJointName, AZStd::string::format (" [joint] %s: %llu" , result.IsSuccess () ? " created as" : " failed" , result.GetValue ()));
394
454
}
395
455
else
396
456
{
@@ -508,64 +568,11 @@ namespace ROS2
508
568
if (auto * transformComponent = entity->FindComponent <AzToolsFramework::Components::TransformComponent>();
509
569
transformComponent != nullptr )
510
570
{
511
- gz::math::Pose3d modelPose;
512
- if (sdf::Errors poseResolveErrors = model.SemanticPose ().Resolve (modelPose); !poseResolveErrors.empty ())
513
- {
514
- AZStd::string poseErrorMessages = Utils::JoinSdfErrorsToString (poseResolveErrors);
515
-
516
- auto poseErrorsForModel = AZStd::string::format (
517
- R"( Unable to resolve semantic pose for model %s. Creation of Model entity has failed. Errors: "%s")" ,
518
- model.Name ().c_str (),
519
- poseErrorMessages.c_str ());
520
-
521
- return AZ::Failure (poseErrorsForModel);
522
- }
523
-
571
+ gz::math::Pose3d modelPose = model.RawPose ();
524
572
AZ::Transform modelTransform = URDF::TypeConversions::ConvertPose (modelPose);
525
-
526
- // If the model is nested below another model, check if it has a placement frame
527
- if (const sdf::Model* parentModel = Utils::GetModelContainingModel (*m_root, model); parentModel != nullptr )
528
- {
529
- if (const sdf::Frame* modelPlacementFrame = parentModel->FrameByName (model.PlacementFrameName ()); modelPlacementFrame != nullptr )
530
- {
531
- gz::math::Pose3d placementFramePose;
532
- if (sdf::Errors poseResolveErrors = modelPlacementFrame->SemanticPose ().Resolve (placementFramePose);
533
- !poseResolveErrors.empty ())
534
- {
535
- AZStd::string poseErrorMessages = Utils::JoinSdfErrorsToString (poseResolveErrors);
536
-
537
- auto poseErrorsForModel = AZStd::string::format (
538
- R"( Unable to resolve semantic pose for model %s parent model %s. Creation of Model entity has failed. Errors: "%s")" ,
539
- model.Name ().c_str (),
540
- parentModel->Name ().c_str (),
541
- poseErrorMessages.c_str ());
542
-
543
- return AZ::Failure (poseErrorsForModel);
544
- }
545
-
546
- modelTransform = modelTransform * URDF::TypeConversions::ConvertPose (placementFramePose);
547
- }
548
- }
549
-
550
- if (const sdf::Frame* implicitFrame = model.FrameByName (" __model__" ); implicitFrame != nullptr )
551
- {
552
- gz::math::Pose3d implicitFramePose;
553
- if (sdf::Errors poseResolveErrors = implicitFrame->SemanticPose ().Resolve (implicitFramePose); !poseResolveErrors.empty ())
554
- {
555
- AZStd::string poseErrorMessages = Utils::JoinSdfErrorsToString (poseResolveErrors);
556
-
557
- auto poseErrorsForModel = AZStd::string::format (
558
- R"( Unable to resolve semantic pose for model's implicit frame %s. Creation of Model entity has failed. Errors: "%s")" ,
559
- implicitFrame->Name ().c_str (),
560
- poseErrorMessages.c_str ());
561
-
562
- return AZ::Failure (poseErrorsForModel);
563
- }
564
-
565
- modelTransform = modelTransform * URDF::TypeConversions::ConvertPose (implicitFramePose);
566
- }
567
-
568
- transformComponent->SetWorldTM (AZStd::move (modelTransform));
573
+ // Set the local transform for each model to have it be translated in relation
574
+ // to its parent
575
+ transformComponent->SetLocalTM (AZStd::move (modelTransform));
569
576
}
570
577
571
578
// Allow the created model entity to persist if there are no errors at ths point
0 commit comments