ROS2FrameComponent.cpp 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  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 "Frame/ROS2FrameComponent.h"
  9. #include "ROS2/ROS2Bus.h"
  10. #include "Utilities/ROS2Names.h"
  11. #include <AzCore/Component/Entity.h>
  12. #include <AzCore/Serialization/EditContext.h>
  13. #include <AzCore/Serialization/EditContextConstants.inl>
  14. #include <AzCore/Serialization/SerializeContext.h>
  15. #include <AzToolsFramework/Entity/EditorEntityHelpers.h>
  16. #include <AzToolsFramework/ToolsComponents/TransformComponent.h>
  17. namespace ROS2
  18. {
  19. void ROS2FrameComponent::Activate()
  20. {
  21. m_namespaceConfiguration.PopulateNamespace(IsTopLevel(), GetEntity()->GetName());
  22. if (m_publishTransform)
  23. {
  24. AZ_TracePrintf(
  25. "ROS2FrameComponent",
  26. "Setting up %s transfrom between parent %s and child %s to be published %s",
  27. IsDynamic() ? "dynamic" : "static",
  28. GetParentFrameID().data(),
  29. GetFrameID().data(),
  30. IsDynamic() ? "continuously to /tf" : "once to /tf_static");
  31. m_ros2Transform = AZStd::make_unique<ROS2Transform>(GetParentFrameID(), GetFrameID(), IsDynamic());
  32. if (IsDynamic())
  33. {
  34. AZ::TickBus::Handler::BusConnect();
  35. }
  36. else
  37. {
  38. m_ros2Transform->Publish(GetFrameTransform());
  39. }
  40. }
  41. }
  42. void ROS2FrameComponent::Deactivate()
  43. {
  44. if (m_publishTransform)
  45. {
  46. if (IsDynamic())
  47. {
  48. AZ::TickBus::Handler::BusDisconnect();
  49. }
  50. m_ros2Transform.reset();
  51. }
  52. }
  53. void ROS2FrameComponent::OnTick([[maybe_unused]] float deltaTime, [[maybe_unused]] AZ::ScriptTimePoint time)
  54. {
  55. m_ros2Transform->Publish(GetFrameTransform());
  56. }
  57. const char* ROS2FrameComponent::GetGlobalFrameName()
  58. {
  59. // TODO - parametrize this (typically: "odom", "world" and sometimes "map")
  60. return "odom";
  61. }
  62. bool ROS2FrameComponent::IsTopLevel() const
  63. {
  64. return GetGlobalFrameName() == GetParentFrameID();
  65. }
  66. bool ROS2FrameComponent::IsDynamic() const
  67. { // TODO - determine by joint type
  68. return IsTopLevel();
  69. }
  70. const ROS2FrameComponent* ROS2FrameComponent::GetParentROS2FrameComponent() const
  71. {
  72. auto* transformInterface = GetEntityTransformInterface();
  73. if (!transformInterface)
  74. {
  75. AZ_Error("GetParentROS2FrameComponent", false, "No transform interface, but it is required!");
  76. return nullptr;
  77. }
  78. if (AZ::EntityId parentEntityId = GetEntityTransformInterface()->GetParentId(); parentEntityId.IsValid())
  79. {
  80. const AZ::Entity* parentEntity = AzToolsFramework::GetEntityById(parentEntityId);
  81. return parentEntity->FindComponent<ROS2FrameComponent>();
  82. }
  83. return nullptr;
  84. }
  85. const AZ::Transform& ROS2FrameComponent::GetFrameTransform() const
  86. {
  87. auto transformInterface = GetEntityTransformInterface();
  88. if (GetParentROS2FrameComponent() != nullptr)
  89. {
  90. return transformInterface->GetLocalTM();
  91. }
  92. return transformInterface->GetWorldTM();
  93. }
  94. AZ::TransformInterface* ROS2FrameComponent::GetEntityTransformInterface() const
  95. {
  96. // TODO - instead, use EditorFrameComponent to handle Editor-context queries and here only use the "Game" version
  97. auto* interface = GetEntity()->FindComponent<AzFramework::TransformComponent>();
  98. if (interface)
  99. {
  100. return interface;
  101. }
  102. return GetEntity()->FindComponent<AzToolsFramework::Components::TransformComponent>();
  103. }
  104. AZStd::string ROS2FrameComponent::GetParentFrameID() const
  105. {
  106. if (auto parentFrame = GetParentROS2FrameComponent(); parentFrame != nullptr)
  107. {
  108. return parentFrame->GetFrameID();
  109. }
  110. return GetGlobalFrameName();
  111. }
  112. AZStd::string ROS2FrameComponent::GetFrameID() const
  113. {
  114. return ROS2Names::GetNamespacedName(GetNamespace(), m_frameName);
  115. }
  116. AZStd::string ROS2FrameComponent::GetNamespace() const
  117. {
  118. auto parentFrame = GetParentROS2FrameComponent();
  119. AZStd::string parentNamespace("");
  120. if (parentFrame != nullptr)
  121. {
  122. parentNamespace = parentFrame->GetNamespace();
  123. }
  124. return m_namespaceConfiguration.GetNamespace(parentNamespace);
  125. }
  126. void ROS2FrameComponent::Reflect(AZ::ReflectContext* context)
  127. {
  128. NamespaceConfiguration::Reflect(context);
  129. if (AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context))
  130. {
  131. serialize->Class<ROS2FrameComponent, AZ::Component>()
  132. ->Version(1)
  133. ->Field("Namespace Configuration", &ROS2FrameComponent::m_namespaceConfiguration)
  134. ->Field("Frame Name", &ROS2FrameComponent::m_frameName)
  135. ->Field("Publish Transform", &ROS2FrameComponent::m_publishTransform);
  136. if (AZ::EditContext* ec = serialize->GetEditContext())
  137. {
  138. ec->Class<ROS2FrameComponent>("ROS2 Frame", "[ROS2 Frame component]")
  139. ->ClassElement(AZ::Edit::ClassElements::EditorData, "")
  140. ->Attribute(AZ::Edit::Attributes::Category, "ROS2")
  141. ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game"))
  142. ->DataElement(
  143. AZ::Edit::UIHandlers::Default,
  144. &ROS2FrameComponent::m_namespaceConfiguration,
  145. "Namespace Configuration",
  146. "Namespace Configuration")
  147. ->DataElement(AZ::Edit::UIHandlers::Default, &ROS2FrameComponent::m_frameName, "Frame Name", "Frame Name")
  148. ->DataElement(
  149. AZ::Edit::UIHandlers::Default, &ROS2FrameComponent::m_publishTransform, "Publish Transform", "Publish Transform");
  150. }
  151. }
  152. }
  153. void ROS2FrameComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)
  154. {
  155. provided.push_back(AZ_CRC_CE("ROS2Frame"));
  156. }
  157. void ROS2FrameComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible)
  158. {
  159. incompatible.push_back(AZ_CRC_CE("ROS2Frame"));
  160. }
  161. void ROS2FrameComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required)
  162. {
  163. required.push_back(AZ_CRC("TransformService"));
  164. }
  165. ROS2FrameComponent::ROS2FrameComponent() = default;
  166. ROS2FrameComponent::ROS2FrameComponent(AZStd::string frameId)
  167. : m_frameName(AZStd::move(frameId))
  168. {
  169. }
  170. } // namespace ROS2