2
0

ROS2FrameSystemComponent.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include "ROS2FrameSystemComponent.h"
  9. #include "AzCore/std/containers/vector.h"
  10. #include "ROS2FrameSystemBus.h"
  11. #include <AzCore/Component/ComponentApplicationBus.h>
  12. #include <AzCore/Component/ComponentBus.h>
  13. #include <AzCore/Component/Entity.h>
  14. #include <AzCore/Component/EntityId.h>
  15. #include <AzCore/std/containers/set.h>
  16. #include <AzCore/std/string/string.h>
  17. #include <AzToolsFramework/ToolsComponents/TransformComponent.h>
  18. #include <ROS2/Frame/ROS2FrameComponent.h>
  19. #include <ROS2/Frame/ROS2FrameEditorComponentBus.h>
  20. namespace ROS2
  21. {
  22. void ROS2FrameSystemTransformHandler::OnParentChanged(AZ::EntityId oldParent, AZ::EntityId newParent)
  23. {
  24. for (auto frameEntityId : m_frameEntities)
  25. {
  26. ROS2FrameSystemInterface::Get()->MoveFrame(frameEntityId, newParent);
  27. }
  28. }
  29. void ROS2FrameSystemTransformHandler::AddFrameEntity(AZ::EntityId frameEntityId)
  30. {
  31. if (!m_frameEntities.contains(frameEntityId))
  32. {
  33. m_frameEntities.insert(frameEntityId);
  34. }
  35. }
  36. void ROS2FrameSystemTransformHandler::RemoveFrameEntity(AZ::EntityId frameEntityId)
  37. {
  38. if (m_frameEntities.contains(frameEntityId))
  39. {
  40. m_frameEntities.erase(frameEntityId);
  41. }
  42. }
  43. unsigned int ROS2FrameSystemTransformHandler::GetFrameCount()
  44. {
  45. return m_frameEntities.size();
  46. }
  47. ROS2FrameSystemComponent::ROS2FrameSystemComponent()
  48. {
  49. if (ROS2FrameSystemInterface::Get() == nullptr)
  50. {
  51. ROS2FrameSystemInterface::Register(this);
  52. }
  53. }
  54. ROS2FrameSystemComponent::~ROS2FrameSystemComponent()
  55. {
  56. if (ROS2FrameSystemInterface::Get() == this)
  57. {
  58. ROS2FrameSystemInterface::Unregister(this);
  59. }
  60. }
  61. void ROS2FrameSystemComponent::Reflect(AZ::ReflectContext* context)
  62. {
  63. if (AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context))
  64. {
  65. serialize->Class<ROS2FrameSystemComponent, AZ::Component>()->Version(1)->Attribute(
  66. AZ::Edit::Attributes::SystemComponentTags, AZStd::vector<AZ::Crc32>({ AZ_CRC_CE("AssetBuilder") }));
  67. }
  68. }
  69. void ROS2FrameSystemComponent::Activate()
  70. {
  71. }
  72. void ROS2FrameSystemComponent::Deactivate()
  73. {
  74. }
  75. AZ::TransformInterface* ROS2FrameSystemComponent::GetEntityTransformInterface(const AZ::Entity* entity)
  76. {
  77. if (!entity)
  78. {
  79. AZ_Error("GetEntityTransformInterface", false, "Invalid entity!");
  80. return nullptr;
  81. }
  82. auto* interface = entity->FindComponent<AzToolsFramework::Components::TransformComponent>();
  83. return interface;
  84. }
  85. bool ROS2FrameSystemComponent::IsTopLevel(const AZ::EntityId& frameEntityId) const
  86. {
  87. if (m_frameParent.contains(frameEntityId))
  88. {
  89. const AZ::EntityId& parent = m_frameParent.find(frameEntityId)->second;
  90. return m_frameParent.find(parent)->second == parent;
  91. }
  92. return false;
  93. }
  94. AZ::EntityId ROS2FrameSystemComponent::GetParentEntityId(const AZ::EntityId& frameEntityId) const
  95. {
  96. if (m_frameParent.contains(frameEntityId))
  97. {
  98. return m_frameParent.find(frameEntityId)->second;
  99. }
  100. return AZ::EntityId();
  101. }
  102. AZStd::vector<AZ::EntityId> ROS2FrameSystemComponent::FindFrameParentPath(AZ::EntityId frameEntityId)
  103. {
  104. AZStd::vector<AZ::EntityId> path;
  105. path.push_back(frameEntityId);
  106. AZ::Entity* currentEntity = nullptr;
  107. AZ::ComponentApplicationBus::BroadcastResult(currentEntity, &AZ::ComponentApplicationRequests::FindEntity, frameEntityId);
  108. auto* currentTransform = GetEntityTransformInterface(currentEntity);
  109. if (!currentTransform)
  110. {
  111. return path;
  112. }
  113. while (currentEntity->GetId().IsValid())
  114. {
  115. AZ::EntityId nextEntityId;
  116. if (!currentTransform)
  117. {
  118. return path;
  119. }
  120. nextEntityId = currentTransform->GetParentId();
  121. AZ::Entity* parent = nullptr;
  122. if (!nextEntityId.IsValid())
  123. { // Found top of the level
  124. path.push_back(nextEntityId);
  125. return path;
  126. }
  127. else
  128. {
  129. AZ::ComponentApplicationBus::BroadcastResult(parent, &AZ::ComponentApplicationRequests::FindEntity, nextEntityId);
  130. if (parent == nullptr)
  131. {
  132. path.push_back(nextEntityId);
  133. return path;
  134. }
  135. }
  136. if (ROS2FrameEditorComponentBus::HasHandlers(nextEntityId))
  137. {
  138. path.push_back(nextEntityId);
  139. break;
  140. }
  141. path.push_back(nextEntityId);
  142. currentEntity = parent;
  143. currentTransform = GetEntityTransformInterface(currentEntity);
  144. }
  145. return path;
  146. }
  147. void ROS2FrameSystemComponent::RegisterFrame(const AZ::EntityId& frameToRegister)
  148. {
  149. // Check if the frame is valid and if it's already registered;
  150. if (!frameToRegister.IsValid() || m_frameParent.contains(frameToRegister))
  151. {
  152. return;
  153. }
  154. // Get path from itself to its parent (both included)
  155. AZStd::vector<AZ::EntityId> entityPath = FindFrameParentPath(frameToRegister);
  156. const AZ::EntityId& frameParent = entityPath[entityPath.size() - 1];
  157. // Initialize all maps
  158. AZStd::set<AZ::EntityId>& frameToRegisterChildren = m_frameChildren.insert({ frameToRegister, {} }).first->second;
  159. AZStd::set<AZ::EntityId>& frameToRegisterWatchedEntities = m_watchedEntities.insert({ frameToRegister, {} }).first->second;
  160. m_frameParent.insert({ frameToRegister, frameParent });
  161. bool laysOnPath = false;
  162. if (auto frameChildrenIt = m_frameChildren.find(frameParent); frameChildrenIt != m_frameChildren.end())
  163. {
  164. AZStd::set<AZ::EntityId>& parentsChildren = frameChildrenIt->second;
  165. // Check if a frameToRegister lays on one or more childrens paths
  166. AZStd::vector<AZ::EntityId> childrenToErase;
  167. for (const AZ::EntityId& parentsChild : parentsChildren)
  168. {
  169. AZStd::set<AZ::EntityId>& childsPathToParent = m_watchedEntities.find(parentsChild)->second;
  170. if (childsPathToParent.contains(frameToRegister))
  171. {
  172. laysOnPath = true;
  173. // As the new frame lays on the path it is needed to update all entities on the path.
  174. for (AZ::EntityId& entityOnPath : entityPath)
  175. {
  176. if (entityOnPath == frameParent)
  177. {
  178. // Skip updating its parent
  179. continue;
  180. }
  181. // Update the handler to notify the newly registered frame
  182. ROS2FrameSystemTransformHandler& handler = m_watchedEntitiesHandlers.find(entityOnPath)->second;
  183. handler.RemoveFrameEntity(parentsChild);
  184. handler.AddFrameEntity(frameToRegister);
  185. // The child no longer watches the entity
  186. childsPathToParent.erase(entityOnPath);
  187. frameToRegisterWatchedEntities.insert(entityOnPath);
  188. }
  189. // Change the parenthood
  190. childrenToErase.push_back(parentsChild);
  191. frameToRegisterChildren.insert(parentsChild);
  192. m_frameParent.find(parentsChild)->second = frameToRegister;
  193. }
  194. }
  195. for (const AZ::EntityId& child : childrenToErase)
  196. {
  197. parentsChildren.erase(child);
  198. }
  199. // Add itself as a parents child
  200. parentsChildren.insert(frameToRegister);
  201. }
  202. else
  203. {
  204. // As its the first frame, add it as a levels child
  205. m_frameChildren.insert({ frameParent, { frameToRegister } });
  206. // Add the parent of the level to be the level
  207. m_frameParent.insert({ frameParent, frameParent });
  208. }
  209. if (!laysOnPath)
  210. {
  211. // Create new handlers
  212. for (AZ::EntityId& entityOnPath : entityPath)
  213. {
  214. if (entityOnPath == frameParent)
  215. {
  216. // Skip updating its parent
  217. continue;
  218. }
  219. frameToRegisterWatchedEntities.insert(entityOnPath);
  220. ROS2FrameSystemTransformHandler& handler =
  221. m_watchedEntitiesHandlers.insert({ entityOnPath, ROS2FrameSystemTransformHandler() }).first->second;
  222. // Add which entity should be notified
  223. handler.AddFrameEntity(frameToRegister);
  224. // Connect the handler
  225. handler.BusConnect(entityOnPath);
  226. }
  227. }
  228. // Update namespaces
  229. UpdateNamespaces(frameToRegister, frameParent);
  230. auto predecessors = GetAllPredecessors(frameToRegister);
  231. for (const auto& predecessor : predecessors)
  232. {
  233. ROS2FrameEditorComponentNotificationBus::Event(
  234. predecessor, &ROS2FrameEditorComponentNotificationBus::Events::OnChildAdded, frameToRegister);
  235. }
  236. }
  237. void ROS2FrameSystemComponent::UnregisterFrame(const AZ::EntityId& frameToUnregister)
  238. {
  239. // Check if the frame is already unregistered and valid
  240. if (!frameToUnregister.IsValid() || !m_frameParent.contains(frameToUnregister))
  241. {
  242. return;
  243. }
  244. auto predecessors = GetAllPredecessors(frameToUnregister);
  245. AZStd::set<AZ::EntityId>& frameToUnregisterChildren = m_frameChildren.find(frameToUnregister)->second;
  246. AZStd::set<AZ::EntityId>& frameToUnregisterWatchedEntities = m_watchedEntities.find(frameToUnregister)->second;
  247. const AZ::EntityId& frameToUnregisterParent = m_frameParent.find(frameToUnregister)->second;
  248. AZStd::set<AZ::EntityId>& parentsChildren = m_frameChildren.find(frameToUnregisterParent)->second;
  249. if (frameToUnregisterChildren.empty())
  250. {
  251. for (const AZ::EntityId& watchedEntity : frameToUnregisterWatchedEntities)
  252. {
  253. ROS2FrameSystemTransformHandler& handler = m_watchedEntitiesHandlers.find(watchedEntity)->second;
  254. handler.RemoveFrameEntity(frameToUnregister);
  255. if (handler.GetFrameCount() == 0)
  256. {
  257. handler.BusDisconnect();
  258. m_watchedEntitiesHandlers.erase(watchedEntity);
  259. }
  260. }
  261. }
  262. else
  263. {
  264. for (const AZ::EntityId child : frameToUnregisterChildren)
  265. {
  266. // Change the handlers and watched entities
  267. AZStd::set<AZ::EntityId>& childsWatchedEntities = m_watchedEntities.find(child)->second;
  268. for (const AZ::EntityId& watchedEntity : frameToUnregisterWatchedEntities)
  269. {
  270. childsWatchedEntities.insert(watchedEntity);
  271. ROS2FrameSystemTransformHandler& handler = m_watchedEntitiesHandlers.find(watchedEntity)->second;
  272. handler.RemoveFrameEntity(frameToUnregister);
  273. handler.AddFrameEntity(child);
  274. }
  275. // Change the parenthood
  276. parentsChildren.insert(child);
  277. m_frameParent.find(child)->second = frameToUnregisterParent;
  278. }
  279. }
  280. // Update namespaces before removal of children
  281. UpdateNamespaces(frameToUnregister, frameToUnregisterParent, false);
  282. // Remove all references to the unregisteredEntity
  283. m_frameChildren.erase(frameToUnregister);
  284. m_frameParent.erase(frameToUnregister);
  285. m_watchedEntities.erase(frameToUnregister);
  286. // Remove itself form the parents children
  287. parentsChildren.erase(frameToUnregister);
  288. // Check if the parents children are empty to ensure that the level parent will be deleted
  289. if (parentsChildren.size() == 0)
  290. {
  291. if (m_frameParent.find(frameToUnregisterParent)->second == frameToUnregisterParent)
  292. { // Remove the level entity from the registry
  293. m_frameChildren.erase(frameToUnregisterParent);
  294. m_frameParent.erase(frameToUnregisterParent);
  295. }
  296. }
  297. for (const auto& predecessor : predecessors)
  298. {
  299. ROS2FrameEditorComponentNotificationBus::Event(
  300. predecessor, &ROS2FrameEditorComponentNotificationBus::Events::OnChildRemoved, frameToUnregister);
  301. }
  302. }
  303. void ROS2FrameSystemComponent::MoveFrameDetach(
  304. const AZ::EntityId& frameEntityId, const AZStd::set<AZ::EntityId>& newPathToParentFrameSet)
  305. {
  306. // Remove all handlers
  307. AZStd::set<AZ::EntityId>& oldWatchedEntities = m_watchedEntities.find(frameEntityId)->second;
  308. AZStd::vector<AZ::EntityId> watchedEntitiesToRemove;
  309. for (const AZ::EntityId& oldWatchedEntity : oldWatchedEntities)
  310. {
  311. if (newPathToParentFrameSet.contains(oldWatchedEntity))
  312. {
  313. continue;
  314. }
  315. ROS2FrameSystemTransformHandler& handler = m_watchedEntitiesHandlers.find(oldWatchedEntity)->second;
  316. handler.RemoveFrameEntity(frameEntityId);
  317. watchedEntitiesToRemove.push_back(oldWatchedEntity);
  318. if (handler.GetFrameCount() == 0)
  319. {
  320. handler.BusDisconnect();
  321. m_watchedEntitiesHandlers.erase(oldWatchedEntity);
  322. }
  323. }
  324. for (const auto& entityIdToRemove : watchedEntitiesToRemove)
  325. {
  326. oldWatchedEntities.erase(entityIdToRemove);
  327. }
  328. // Remove itself from parents children
  329. m_frameChildren.find(m_frameParent.find(frameEntityId)->second)->second.erase(frameEntityId);
  330. }
  331. void ROS2FrameSystemComponent::MoveFrameAttach(
  332. const AZ::EntityId& frameEntityId, const AZ::EntityId& newFrameParent, const AZStd::vector<AZ::EntityId>& newPathToParentFrame)
  333. {
  334. AZStd::set<AZ::EntityId>& oldWatchedEntities = m_watchedEntities.find(frameEntityId)->second;
  335. // Add itself as a new child
  336. m_frameChildren.find(newFrameParent)->second.insert(frameEntityId);
  337. // Create or add the frame to handlers
  338. for (const AZ::EntityId& entityIdOnPath : newPathToParentFrame)
  339. {
  340. if (entityIdOnPath == newFrameParent || oldWatchedEntities.contains(entityIdOnPath))
  341. {
  342. continue;
  343. }
  344. if (m_watchedEntitiesHandlers.contains(entityIdOnPath))
  345. {
  346. m_watchedEntitiesHandlers.find(entityIdOnPath)->second.AddFrameEntity(frameEntityId);
  347. }
  348. else
  349. {
  350. ROS2FrameSystemTransformHandler& handler =
  351. m_watchedEntitiesHandlers.insert({ entityIdOnPath, ROS2FrameSystemTransformHandler() }).first->second;
  352. // Add which entity should be notified
  353. handler.AddFrameEntity(frameEntityId);
  354. handler.BusConnect(entityIdOnPath);
  355. }
  356. oldWatchedEntities.insert(entityIdOnPath);
  357. }
  358. }
  359. void ROS2FrameSystemComponent::MoveFrame(const AZ::EntityId& frameEntityId, const AZ::EntityId& newParent)
  360. {
  361. // Check if the frame is already registered and valid
  362. if (!frameEntityId.IsValid() || !m_frameParent.contains(frameEntityId))
  363. {
  364. return;
  365. }
  366. AZStd::vector<AZ::EntityId> newPathToParentFrame = FindFrameParentPath(frameEntityId);
  367. const AZ::EntityId& newFrameParent = newPathToParentFrame[newPathToParentFrame.size() - 1];
  368. AZStd::set<AZ::EntityId> newPathToParentFrameSet;
  369. for (const auto& entityOnPath : newPathToParentFrame)
  370. {
  371. newPathToParentFrameSet.insert(entityOnPath);
  372. }
  373. auto oldPredecessors = GetAllPredecessors(frameEntityId);
  374. auto successors = GetAllSuccessors(frameEntityId);
  375. successors.push_back(frameEntityId);
  376. MoveFrameDetach(frameEntityId, newPathToParentFrameSet);
  377. for (const auto& successor : successors)
  378. {
  379. for (const auto& oldPredecessor : oldPredecessors)
  380. {
  381. ROS2FrameEditorComponentNotificationBus::Event(
  382. oldPredecessor, &ROS2FrameEditorComponentNotificationBus::Events::OnChildRemoved, successor);
  383. }
  384. }
  385. // Replace the parent
  386. m_frameParent.find(frameEntityId)->second = newFrameParent;
  387. MoveFrameAttach(frameEntityId, newFrameParent, newPathToParentFrame);
  388. auto newPredecessors = GetAllPredecessors(frameEntityId);
  389. for (const auto& successor : successors)
  390. {
  391. for (const auto& newPredecessor : newPredecessors)
  392. {
  393. ROS2FrameEditorComponentNotificationBus::Event(
  394. newPredecessor, &ROS2FrameEditorComponentNotificationBus::Events::OnChildAdded, successor);
  395. }
  396. }
  397. // Notify about namespace changes
  398. UpdateNamespaces(frameEntityId, newFrameParent);
  399. }
  400. void ROS2FrameSystemComponent::UpdateNamespaces(AZ::EntityId frameEntity, AZ::EntityId frameParentEntity, bool isActive)
  401. {
  402. AZStd::string ros2Namespace;
  403. ROS2FrameEditorComponentBus::EventResult(ros2Namespace, frameParentEntity, &ROS2FrameEditorComponentBus::Events::GetNamespace);
  404. UpdateNamespaces(frameEntity, ros2Namespace, isActive);
  405. }
  406. void ROS2FrameSystemComponent::UpdateNamespaces(AZ::EntityId frameEntity, AZStd::string parentNamespace, bool isActive)
  407. {
  408. ROS2FrameEditorComponentBus::Event(frameEntity, &ROS2FrameEditorComponentBus::Events::UpdateNamespace, parentNamespace);
  409. const AZStd::set<AZ::EntityId>& children = m_frameChildren.find(frameEntity)->second;
  410. AZStd::string ros2Namespace;
  411. if (isActive)
  412. {
  413. ROS2FrameEditorComponentBus::EventResult(ros2Namespace, frameEntity, &ROS2FrameEditorComponentBus::Events::GetNamespace);
  414. }
  415. else
  416. {
  417. ros2Namespace = parentNamespace;
  418. }
  419. for (const AZ::EntityId& child : children)
  420. {
  421. UpdateNamespaces(child, ros2Namespace);
  422. }
  423. }
  424. void ROS2FrameSystemComponent::NotifyChange(const AZ::EntityId& frameEntityId)
  425. {
  426. if (frameEntityId.IsValid() && m_frameParent.contains(frameEntityId))
  427. {
  428. // Notify about namespace changes
  429. UpdateNamespaces(frameEntityId, m_frameParent.find(frameEntityId)->second);
  430. }
  431. }
  432. AZStd::set<AZ::EntityId> ROS2FrameSystemComponent::GetChildrenEntityId(const AZ::EntityId& frameEntityId) const
  433. {
  434. if (!frameEntityId.IsValid() || !m_frameChildren.contains(frameEntityId))
  435. {
  436. return AZStd::set<AZ::EntityId>();
  437. }
  438. return m_frameChildren.find(frameEntityId)->second;
  439. }
  440. AZStd::vector<AZ::EntityId> ROS2FrameSystemComponent::GetAllPredecessors(const AZ::EntityId& frameEntityId) const
  441. {
  442. AZStd::vector<AZ::EntityId> predecessors;
  443. auto childrenIt = m_frameParent.find(frameEntityId);
  444. if (childrenIt == m_frameParent.end())
  445. {
  446. return predecessors;
  447. }
  448. AZ::EntityId currentEntityId = childrenIt->second;
  449. while (m_frameParent.find(currentEntityId) != m_frameParent.end() && m_frameParent.find(currentEntityId)->second != currentEntityId)
  450. {
  451. predecessors.push_back(currentEntityId);
  452. currentEntityId = m_frameParent.find(currentEntityId)->second;
  453. }
  454. return predecessors;
  455. }
  456. AZStd::vector<AZ::EntityId> ROS2FrameSystemComponent::GetAllSuccessors(const AZ::EntityId& frameEntityId) const
  457. {
  458. AZStd::vector<AZ::EntityId> successors;
  459. AZStd::set<AZ::EntityId> children = GetChildrenEntityId(frameEntityId);
  460. for (const AZ::EntityId& child : children)
  461. {
  462. successors.push_back(child);
  463. AZStd::vector<AZ::EntityId> childSuccessors = GetAllSuccessors(child);
  464. successors.insert(successors.end(), childSuccessors.begin(), childSuccessors.end());
  465. }
  466. return successors;
  467. }
  468. } // namespace ROS2