2
0

FingerGripperComponent.cpp 10 KB

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