@@ -129,33 +129,111 @@ namespace ROS2
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 any model it is attached or nullptr if the model is at the top level SDF Root
160
+ std::string stdFullModelName;
161
+ for (const sdf::Model& ancestorModel : modelStack)
162
+ {
163
+ stdFullModelName = sdf::JoinName (stdFullModelName, ancestorModel.Name ());
164
+ }
165
+ stdFullModelName = sdf::JoinName (stdFullModelName, model.Name ());
166
+ AZStd::string fullModelName (stdFullModelName.c_str (), stdFullModelName.size ());
167
+ ModelMapper::NestedModelToAttachedModel nestedModelToAttachedModel;
168
+ nestedModelToAttachedModel.m_fullyQualifiedName = AZStd::move (fullModelName);
169
+ nestedModelToAttachedModel.m_nestedModel = &model;
170
+ nestedModelToAttachedModel.m_attachedModel = !modelStack.empty () ? &modelStack.back ().get () : nullptr ;
171
+ modelMapper.m_models .push_back (AZStd::move (nestedModelToAttachedModel));
172
+
145
173
return Utils::VisitModelResponse::VisitNestedAndSiblings;
146
174
};
147
175
148
- // Gather all links from all the models in the SDF
149
- Utils::VisitModels (*m_root, GetAllLinksFromModel , visitNestedModels);
176
+ // Gather all links and direct nested from all the models in the SDF
177
+ Utils::VisitModels (*m_root, GetAllLinksAndSetModelHierarchy , visitNestedModels);
150
178
151
179
// Build up a list of all entities created as a part of processing the file.
152
180
AZStd::vector<AZ::EntityId> createdEntities;
153
- AZStd::unordered_map<const sdf::Link*, AzToolsFramework::Prefab::PrefabEntityResult> createdLinks;
154
181
AZStd::unordered_map<const sdf::Model*, AzToolsFramework::Prefab::PrefabEntityResult> createdModels;
182
+
183
+ AZStd::unordered_map<const sdf::Link*, AzToolsFramework::Prefab::PrefabEntityResult> createdLinks;
155
184
AZStd::unordered_map<AZStd::string, const sdf::Link*> links;
156
- for ([[maybe_unused]] const auto & [fullLinkName, linkPtr, attachedModel] : linksMapper.m_links )
185
+
186
+ // Create an entity for each model
187
+ for ([[maybe_unused]] const auto & [fullModelName, modelPtr, _] : modelMapper.m_models )
188
+ {
189
+ // Create entities for each model in the SDF
190
+ if (AzToolsFramework::Prefab::PrefabEntityResult createModelEntityResult = CreateEntityForModel (*modelPtr);
191
+ createModelEntityResult)
192
+ {
193
+ AZ::EntityId createdModelEntityId = createModelEntityResult.GetValue ();
194
+ // Add the model entity to the created entity list so that it gets added to the prefab
195
+ createdEntities.emplace_back (createdModelEntityId);
196
+
197
+ std::string modelName = modelPtr->Name ();
198
+ AZStd::string azModelName (modelName.c_str (), modelName.size ());
199
+ AZStd::lock_guard<AZStd::mutex> lck (m_statusLock);
200
+ m_status.emplace (azModelName, AZStd::string::format (" [model] created as: %s" , createdModelEntityId.ToString ().c_str ()));
201
+ createdModels.emplace (modelPtr, createModelEntityResult);
202
+ }
203
+ }
204
+
205
+ // ! Setup the parent hierarchy for the nested models
206
+ for ([[maybe_unused]] const auto & [_, modelPtr, parentModelPtr] : modelMapper.m_models )
207
+ {
208
+ // If there is no parent model, then the model would be at the top level of the hiearachy
209
+ if (parentModelPtr == nullptr || modelPtr == nullptr )
210
+ {
211
+ continue ;
212
+ }
213
+ // Create entities for each model in the SDF
214
+ AZ::EntityId modelEntityId;
215
+ if (auto modelIt = createdModels.find (modelPtr); modelIt != createdModels.end () && modelIt->second )
216
+ {
217
+ modelEntityId = modelIt->second .GetValue ();
218
+ }
219
+
220
+ AZ::EntityId parentModelEntityId;
221
+ if (auto parentModelIt = createdModels.find (parentModelPtr); parentModelIt != createdModels.end () && parentModelIt->second )
222
+ {
223
+ parentModelEntityId = parentModelIt->second .GetValue ();
224
+ }
225
+
226
+ // If the both the parent model and current model entity exist
227
+ // set the current model transform component parent to the parent model
228
+ if (parentModelEntityId.IsValid () && modelEntityId.IsValid ())
229
+ {
230
+ PrefabMakerUtils::SetEntityParent (modelEntityId, parentModelEntityId);
231
+ }
232
+ }
233
+
234
+ // Create an entity for each link and set the parent to be the model entity where the link is attached
235
+ for ([[maybe_unused]] const auto & [_, linkPtr, attachedModel] : linksMapper.m_links )
157
236
{
158
- // Create entities for the model containing the link
159
237
AZ::EntityId modelEntityId;
160
238
if (attachedModel != nullptr )
161
239
{
@@ -166,26 +244,7 @@ namespace ROS2
166
244
modelEntityId = modelIt->second .GetValue ();
167
245
}
168
246
}
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
247
}
188
-
189
248
// Add all link as children of their attached model entity by default
190
249
createdLinks[linkPtr] = AddEntitiesForLink (*linkPtr, attachedModel, modelEntityId, createdEntities);
191
250
}
@@ -202,11 +261,11 @@ namespace ROS2
202
261
AZStd::lock_guard<AZStd::mutex> lck (m_statusLock);
203
262
if (result.IsSuccess ())
204
263
{
205
- m_status.emplace (azLinkName, AZStd::string::format (" created as: %s" , result.GetValue ().ToString ().c_str ()));
264
+ m_status.emplace (azLinkName, AZStd::string::format (" [link] created as: %s" , result.GetValue ().ToString ().c_str ()));
206
265
}
207
266
else
208
267
{
209
- m_status.emplace (azLinkName, AZStd::string::format (" failed : %s" , result.GetError ().c_str ()));
268
+ m_status.emplace (azLinkName, AZStd::string::format (" [link] failed : %s" , result.GetError ().c_str ()));
210
269
}
211
270
}
212
271
@@ -390,7 +449,7 @@ namespace ROS2
390
449
AZStd::lock_guard<AZStd::mutex> lck (m_statusLock);
391
450
auto result = m_jointsMaker.AddJointComponent (jointPtr, childEntity.GetValue (), leadEntity.GetValue ());
392
451
m_status.emplace (
393
- azJointName, AZStd::string::format (" %s: %llu" , result.IsSuccess () ? " created as" : " failed" , result.GetValue ()));
452
+ azJointName, AZStd::string::format (" [joint] %s: %llu" , result.IsSuccess () ? " created as" : " failed" , result.GetValue ()));
394
453
}
395
454
else
396
455
{
@@ -508,63 +567,9 @@ namespace ROS2
508
567
if (auto * transformComponent = entity->FindComponent <AzToolsFramework::Components::TransformComponent>();
509
568
transformComponent != nullptr )
510
569
{
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
-
570
+ gz::math::Pose3d modelPose = model.RawPose ();
524
571
AZ::Transform modelTransform = URDF::TypeConversions::ConvertPose (modelPose);
525
572
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
573
transformComponent->SetWorldTM (AZStd::move (modelTransform));
569
574
}
570
575
0 commit comments