ROS2FrameSystemComponent.cpp 20 KB

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