FingerGripperComponent.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  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
  4. * of this distribution.
  5. *
  6. * SPDX-License-Identifier: Apache-2.0 OR MIT
  7. *
  8. */
  9. #include "FingerGripperComponent.h"
  10. #include "Utils.h"
  11. #include <AzCore/Serialization/EditContext.h>
  12. #include <AzCore/Serialization/SerializeContext.h>
  13. #include <AzFramework/Physics/PhysicsSystem.h>
  14. #include <ROS2/Frame/ROS2FrameComponent.h>
  15. #include <ROS2Controllers/Manipulation/JointsManipulationRequests.h>
  16. #include <imgui/imgui.h>
  17. namespace ROS2Controllers
  18. {
  19. void FingerGripperComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)
  20. {
  21. provided.push_back(AZ_CRC_CE("GripperService"));
  22. }
  23. void FingerGripperComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible)
  24. {
  25. incompatible.push_back(AZ_CRC_CE("GripperService"));
  26. }
  27. void FingerGripperComponent::Activate()
  28. {
  29. m_grippingInProgress = false;
  30. m_initialised = false;
  31. m_cancelled = false;
  32. m_ImGuiPosition = 0.0f;
  33. m_stallingFor = 0.0f;
  34. AZ::TickBus::Handler::BusConnect();
  35. ImGui::ImGuiUpdateListenerBus::Handler::BusConnect();
  36. GripperRequestBus::Handler::BusConnect(GetEntityId());
  37. }
  38. void FingerGripperComponent::Deactivate()
  39. {
  40. AZ::TickBus::Handler::BusDisconnect();
  41. ImGui::ImGuiUpdateListenerBus::Handler::BusDisconnect();
  42. GripperRequestBus::Handler::BusDisconnect(GetEntityId());
  43. }
  44. void FingerGripperComponent::Reflect(AZ::ReflectContext* context)
  45. {
  46. if (AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context))
  47. {
  48. serialize->Class<FingerGripperComponent, AZ::Component>()
  49. ->Field("VelocityEpsilon", &FingerGripperComponent::m_velocityEpsilon)
  50. ->Field("DistanceEpsilon", &FingerGripperComponent::m_goalTolerance)
  51. ->Field("StallTime", &FingerGripperComponent::m_stallTime)
  52. ->Field("InitialPosition", &FingerGripperComponent::m_initialPosition)
  53. ->Version(2);
  54. if (AZ::EditContext* ec = serialize->GetEditContext())
  55. {
  56. ec->Class<FingerGripperComponent>("FingerGripperComponent", "Component controlling a finger gripper.")
  57. ->ClassElement(AZ::Edit::ClassElements::EditorData, "FingerGripperComponent")
  58. ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game"))
  59. ->Attribute(AZ::Edit::Attributes::Category, "ROS2")
  60. ->Attribute(AZ::Edit::Attributes::Icon, "Editor/Icons/Components/FingerGripperComponent.svg")
  61. ->Attribute(AZ::Edit::Attributes::ViewportIcon, "Editor/Icons/Components/Viewport/FingerGripperComponent.svg")
  62. ->DataElement(
  63. AZ::Edit::UIHandlers::Default,
  64. &FingerGripperComponent::m_velocityEpsilon,
  65. "Velocity Epsilon",
  66. "The maximum velocity to consider the gripper as stalled.")
  67. ->DataElement(
  68. AZ::Edit::UIHandlers::Default,
  69. &FingerGripperComponent::m_goalTolerance,
  70. "Goal tolerance",
  71. "Goal is considered reached if the gripper is at this distance or closer")
  72. ->DataElement(
  73. AZ::Edit::UIHandlers::Default,
  74. &FingerGripperComponent::m_stallTime,
  75. "Stall Time",
  76. "The time to wait before considering the gripper as stalled.")
  77. ->DataElement(
  78. AZ::Edit::UIHandlers::Default,
  79. &FingerGripperComponent::m_initialPosition,
  80. "Initial Position",
  81. "The initial position of the gripper in units of the gripper's joints (meters if prismatic, radians if revolute).");
  82. }
  83. }
  84. }
  85. ManipulationJoints& FingerGripperComponent::GetFingerJoints()
  86. {
  87. m_fingerJoints.clear();
  88. m_rootOfArticulation = Utils::GetRootOfArticulation(GetEntityId());
  89. AZ_Warning(
  90. "FingerGripperComponent",
  91. m_rootOfArticulation.IsValid(),
  92. "Entity %s is not part of an articulation.",
  93. GetEntity()->GetName().c_str());
  94. ManipulationJoints allJoints;
  95. if (m_rootOfArticulation.IsValid())
  96. {
  97. JointsManipulationRequestBus::EventResult(allJoints, m_rootOfArticulation, &JointsManipulationRequests::GetJoints);
  98. }
  99. AZStd::vector<AZ::EntityId> descendantIds;
  100. AZ::TransformBus::EventResult(descendantIds, GetEntityId(), &AZ::TransformBus::Events::GetAllDescendants);
  101. for (const auto& descendantId : descendantIds)
  102. {
  103. AZ::Entity* entity{ nullptr };
  104. AZ::ComponentApplicationBus::BroadcastResult(entity, &AZ::ComponentApplicationRequests::FindEntity, descendantId);
  105. AZ_Assert(entity, "Entity %s not found.", descendantId.ToString().c_str());
  106. ROS2::ROS2FrameComponent* component = entity->FindComponent<ROS2::ROS2FrameComponent>();
  107. if (!component)
  108. {
  109. break;
  110. }
  111. const auto jointName = component->GetNamespacedJointName().GetStringView();
  112. if (!jointName.empty())
  113. {
  114. m_fingerJoints[jointName] = allJoints[jointName];
  115. }
  116. }
  117. return m_fingerJoints;
  118. }
  119. void FingerGripperComponent::SetPosition(float position, float maxEffort)
  120. {
  121. if (m_fingerJoints.empty())
  122. {
  123. return;
  124. }
  125. float targetPosition = position;
  126. for (auto& [jointName, jointInfo] : m_fingerJoints)
  127. {
  128. AZ::Outcome<void, AZStd::string> result;
  129. JointsManipulationRequestBus::EventResult(
  130. result, m_rootOfArticulation, &JointsManipulationRequests::MoveJointToPosition, jointName, targetPosition);
  131. if (!result.IsSuccess())
  132. {
  133. AZ_Warning(
  134. "FingerGripperComponent",
  135. result,
  136. "Joint move cannot be realized: %s for %s ",
  137. result.GetError().c_str(),
  138. jointName.c_str());
  139. }
  140. }
  141. float oneMaxEffort = maxEffort / m_fingerJoints.size();
  142. for (auto& [jointName, jointInfo] : m_fingerJoints)
  143. {
  144. AZ::Outcome<void, AZStd::string> result;
  145. JointsManipulationRequestBus::EventResult(
  146. result, m_rootOfArticulation, &JointsManipulationRequests::SetMaxJointEffort, jointName, oneMaxEffort);
  147. if (!result.IsSuccess())
  148. {
  149. AZ_Warning(
  150. "FingerGripperComponent",
  151. result,
  152. "Setting a max force for a joint cannot be realized: %s for %s ",
  153. result.GetError().c_str(),
  154. jointName.c_str());
  155. }
  156. }
  157. }
  158. AZ::Outcome<void, AZStd::string> FingerGripperComponent::GripperCommand(float position, float maxEffort)
  159. {
  160. if (maxEffort == 0.0f)
  161. { // The moveit panda demo fills the max effort fields with 0s, but we want to exert effort
  162. maxEffort = AZStd::numeric_limits<float>::infinity();
  163. }
  164. m_grippingInProgress = true;
  165. m_desiredPosition = position;
  166. m_stallingFor = 0.0f;
  167. m_cancelled = false;
  168. SetPosition(position, maxEffort);
  169. return AZ::Success();
  170. }
  171. AZ::Outcome<void, AZStd::string> FingerGripperComponent::CancelGripperCommand()
  172. {
  173. m_grippingInProgress = false;
  174. m_cancelled = true;
  175. SetPosition(m_initialPosition, AZStd::numeric_limits<float>::infinity());
  176. return AZ::Success();
  177. }
  178. bool FingerGripperComponent::HasGripperCommandBeenCancelled() const
  179. {
  180. return m_cancelled;
  181. }
  182. float FingerGripperComponent::GetGripperPosition() const
  183. {
  184. float gripperPosition = 0.0f;
  185. if (m_fingerJoints.empty())
  186. {
  187. return gripperPosition;
  188. }
  189. for (const auto& [jointName, _] : m_fingerJoints)
  190. {
  191. AZ::Outcome<JointPosition, AZStd::string> result;
  192. JointsManipulationRequestBus::EventResult(
  193. result, m_rootOfArticulation, &JointsManipulationRequests::GetJointPosition, jointName);
  194. gripperPosition += result.GetValueOr(0.f);
  195. }
  196. return gripperPosition / m_fingerJoints.size();
  197. }
  198. float FingerGripperComponent::GetGripperEffort() const
  199. {
  200. float gripperEffort = 0.0f;
  201. for (const auto& [jointName, _] : m_fingerJoints)
  202. {
  203. AZ::Outcome<JointEffort, AZStd::string> result;
  204. JointsManipulationRequestBus::EventResult(result, m_rootOfArticulation, &JointsManipulationRequests::GetJointEffort, jointName);
  205. if (result)
  206. {
  207. gripperEffort += result.GetValue();
  208. }
  209. }
  210. return gripperEffort;
  211. }
  212. bool FingerGripperComponent::IsGripperVelocity0() const
  213. {
  214. for (const auto& [jointName, _] : m_fingerJoints)
  215. {
  216. AZ::Outcome<JointEffort, AZStd::string> velocityResult;
  217. JointsManipulationRequestBus::EventResult(
  218. velocityResult, m_rootOfArticulation, &JointsManipulationRequests::GetJointVelocity, jointName);
  219. if (velocityResult && AZStd::abs(velocityResult.GetValue()) > m_velocityEpsilon)
  220. {
  221. return false;
  222. }
  223. }
  224. return true;
  225. }
  226. bool FingerGripperComponent::IsGripperNotMoving() const
  227. {
  228. return m_stallingFor > m_stallTime;
  229. }
  230. bool FingerGripperComponent::HasGripperReachedGoal() const
  231. {
  232. return !m_grippingInProgress || AZStd::abs(GetGripperPosition() - m_desiredPosition) < m_goalTolerance;
  233. }
  234. void FingerGripperComponent::OnImGuiUpdate()
  235. {
  236. ImGui::Begin("FingerGripperDebugger");
  237. ImGui::SliderFloat("Target Position", &m_ImGuiPosition, 0.0f, 0.1f);
  238. if (ImGui::Button("Execute Command"))
  239. {
  240. GripperCommand(m_ImGuiPosition, AZStd::numeric_limits<float>::infinity());
  241. }
  242. ImGui::End();
  243. }
  244. void FingerGripperComponent::OnTick([[maybe_unused]] float delta, [[maybe_unused]] AZ::ScriptTimePoint timePoint)
  245. {
  246. if (!m_initialised)
  247. {
  248. m_initialised = true;
  249. GetFingerJoints();
  250. SetPosition(m_initialPosition, AZStd::numeric_limits<float>::infinity());
  251. }
  252. if (IsGripperVelocity0())
  253. {
  254. m_stallingFor += delta;
  255. }
  256. else
  257. {
  258. m_stallingFor = 0.0f;
  259. }
  260. }
  261. } // namespace ROS2Controllers