KrakenManipulatorController.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  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 "KrakenManipulatorController.h"
  9. #include <AzCore/Serialization/EditContext.h>
  10. #include <AzFramework/Components/TransformComponent.h>
  11. #include <AzToolsFramework/UI/PropertyEditor/PropertyEditorAPI.h>
  12. namespace AppleKraken
  13. {
  14. ROS2::MotorizedJoint* ManipulatorController::getMotorizedJoint(const AZ::EntityId& entityWithMotJoint)
  15. {
  16. AZ_Assert(entityWithMotJoint.IsValid(), "Entity Invalid");
  17. AZ::Entity* e_ptr{ nullptr };
  18. AZ::ComponentApplicationBus::BroadcastResult(e_ptr, &AZ::ComponentApplicationRequests::FindEntity, entityWithMotJoint);
  19. AZ_Assert(e_ptr, "No such entity");
  20. ROS2::MotorizedJoint* component = e_ptr->FindComponent<ROS2::MotorizedJoint>();
  21. // AZ_Assert(component, "No ROS2::MotorizedJoint in %s", e_ptr->GetName().c_str());
  22. return component;
  23. }
  24. void ManipulatorController::Activate()
  25. {
  26. ManipulatorRequestBus::Handler::BusConnect(GetEntityId());
  27. AZ::TickBus::Handler::BusConnect();
  28. ImGui::ImGuiUpdateListenerBus::Handler::BusConnect();
  29. initialized = false;
  30. }
  31. void ManipulatorController::Deactivate()
  32. {
  33. ManipulatorRequestBus::Handler::BusDisconnect(GetEntityId());
  34. AZ::TickBus::Handler::BusDisconnect();
  35. ImGui::ImGuiUpdateListenerBus::Handler::BusDisconnect();
  36. }
  37. void ManipulatorController::Reflect(AZ::ReflectContext* context)
  38. {
  39. if (AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context))
  40. {
  41. serialize->Class<ManipulatorController, AZ::Component>()
  42. ->Version(2)
  43. ->Field("ManipulatorEntityX", &ManipulatorController::m_entityX)
  44. ->Field("ManipulatorEntityY", &ManipulatorController::m_entityY)
  45. ->Field("ManipulatorEntityZ", &ManipulatorController::m_entityZ)
  46. ->Field("ManipulatorVecX", &ManipulatorController::m_vectorX)
  47. ->Field("ManipulatorVecY", &ManipulatorController::m_vectorY)
  48. ->Field("ManipulatorVecZ", &ManipulatorController::m_vectorZ)
  49. ->Field("RestEntity", &ManipulatorController::m_restEntity)
  50. ->Field("m_effector", &ManipulatorController::m_effector)
  51. ->Field("max_errorXZ", &ManipulatorController::max_errorXZ)
  52. ->Field("max_errorY", &ManipulatorController::max_errorY);
  53. if (AZ::EditContext* ec = serialize->GetEditContext())
  54. {
  55. ec->Class<ManipulatorController>("ManipulatorController", "ManipulatorController")
  56. ->ClassElement(AZ::Edit::ClassElements::EditorData, "ManipulatorController")
  57. ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game"))
  58. ->Attribute(AZ::Edit::Attributes::Category, "AppleKraken")
  59. ->DataElement(AZ::Edit::UIHandlers::EntityId, &ManipulatorController::m_entityX, "m_entityX", "m_entityX")
  60. ->DataElement(AZ::Edit::UIHandlers::EntityId, &ManipulatorController::m_entityY, "m_entityY", "m_entityY")
  61. ->DataElement(AZ::Edit::UIHandlers::EntityId, &ManipulatorController::m_entityZ, "m_entity_z1", "m_entityZ")
  62. ->DataElement(AZ::Edit::UIHandlers::EntityId, &ManipulatorController::m_vectorX, "vx", "vx")
  63. ->DataElement(AZ::Edit::UIHandlers::EntityId, &ManipulatorController::m_vectorY, "vy", "vy")
  64. ->DataElement(AZ::Edit::UIHandlers::EntityId, &ManipulatorController::m_vectorZ, "vz", "vz")
  65. ->DataElement(AZ::Edit::UIHandlers::EntityId, &ManipulatorController::m_effector, "Effector", "Effector")
  66. ->DataElement(AZ::Edit::UIHandlers::EntityId, &ManipulatorController::m_restEntity, "Rest entity", "Rest Entity")
  67. ->DataElement(AZ::Edit::UIHandlers::EntityId, &ManipulatorController::max_errorXZ, "max_errorXZ", "max error XZ to retract nose")
  68. ->DataElement(AZ::Edit::UIHandlers::EntityId, &ManipulatorController::max_errorY, "max_errorY", "max error Y to retract nose");
  69. }
  70. }
  71. }
  72. void ManipulatorController::OnTick([[maybe_unused]] float deltaTime, [[maybe_unused]] AZ::ScriptTimePoint time)
  73. {
  74. if (!initialized)
  75. {
  76. // get offset to effector
  77. AZ::Transform transformBaseLink;
  78. AZ::TransformBus::EventResult(transformBaseLink, GetEntityId(), &AZ::TransformBus::Events::GetWorldTM);
  79. AZ::Transform transformEffector;
  80. AZ::TransformBus::EventResult(transformEffector, m_effector, &AZ::TransformBus::Events::GetWorldTM);
  81. m_transform_base_link_to_effector = transformBaseLink.GetInverse() * transformEffector;
  82. initialized = true;
  83. return;
  84. }
  85. if (m_desiredApple)
  86. {
  87. m_desiredPosition = *m_desiredApple;
  88. }
  89. else
  90. {
  91. AZ::TransformBus::EventResult(m_desiredPosition, m_restEntity, &AZ::TransformBus::Events::GetWorldTranslation);
  92. }
  93. // apple is given in the World's coordinate system
  94. AZ::Transform current_base_link;
  95. AZ::TransformBus::EventResult(current_base_link, GetEntityId(), &AZ::TransformBus::Events::GetWorldTM);
  96. AZ::Vector3 position_in_baselink_tf = current_base_link.GetInverse().TransformPoint(m_desiredPosition);
  97. AZ::Vector3 position_in_effector_tf = m_transform_base_link_to_effector.GetInverse().TransformPoint(position_in_baselink_tf);
  98. m_setPointX = position_in_effector_tf.Dot(m_vectorX);
  99. m_setPointZ = position_in_effector_tf.Dot(m_vectorZ);
  100. float error_x = std::numeric_limits<float>::max();
  101. float error_z = std::numeric_limits<float>::max();
  102. if (m_entityX.IsValid())
  103. {
  104. auto component_x = getMotorizedJoint(m_entityX);
  105. if (component_x)
  106. {
  107. component_x->SetSetpoint(m_setPointX);
  108. error_x = component_x->GetError();
  109. }
  110. }
  111. if (m_entityZ.IsValid())
  112. {
  113. auto component_z = getMotorizedJoint(m_entityZ);
  114. if (component_z)
  115. {
  116. component_z->SetSetpoint(m_setPointZ);
  117. error_z = component_z->GetError();
  118. }
  119. }
  120. // auto - disable nose retrieve only if we reached small error.
  121. if (m_noseRetrieveRequest == true)
  122. {
  123. m_time_XZ_ok += deltaTime;
  124. if (m_time_XZ_ok > m_timeSetpointReach)
  125. {
  126. if (error_x < max_errorXZ && error_x > -max_errorXZ && error_z < max_errorXZ && error_z > -max_errorXZ)
  127. {
  128. AZ_Printf("ManipulatorController", "Nose is sliding out \n");
  129. m_noseRetrieveRequest = false;
  130. m_time_XZ_ok = 0;
  131. }
  132. }
  133. }
  134. m_setPointY = position_in_effector_tf.Dot(m_vectorY);
  135. if (m_entityY.IsValid())
  136. {
  137. auto component_y = getMotorizedJoint(m_entityY);
  138. if (component_y)
  139. {
  140. if (m_noseRetrieveRequest)
  141. {
  142. m_setPointY = 0;
  143. m_time_Y_ok += deltaTime;
  144. if (m_time_Y_ok > m_timeSetpointReach)
  145. {
  146. auto error_y = getMotorizedJoint(m_entityY)->GetError();
  147. if (error_y < max_errorY && error_y > -max_errorY)
  148. {
  149. m_noseRetrievingSuccess = true;
  150. m_time_Y_ok = 0.0;
  151. }
  152. }
  153. }
  154. else
  155. {
  156. m_noseRetrievingSuccess = false;
  157. }
  158. component_y->SetSetpoint(m_setPointY);
  159. }
  160. }
  161. }
  162. void ManipulatorController::PickApple(const AZ::Vector3 position)
  163. {
  164. m_noseRetrieveRequest = true;
  165. m_time_XZ_ok = 0;
  166. AZ_Printf("ManipulatorController", "PickApple\n");
  167. ResetTimer();
  168. m_desiredApple = position;
  169. };
  170. AZ::Vector3 ManipulatorController::GetPosition()
  171. {
  172. auto currentPosition = AZ::Vector3(
  173. getMotorizedJoint(m_entityX)->GetCurrentPosition(),
  174. getMotorizedJoint(m_entityY)->GetCurrentPosition(),
  175. getMotorizedJoint(m_entityZ)->GetCurrentPosition()
  176. );
  177. return currentPosition;
  178. };
  179. void ManipulatorController::Retrieve()
  180. {
  181. AZ_Printf("ManipulatorController", "Retrieve\n");
  182. m_time_XZ_ok = std::numeric_limits<float>::lowest();
  183. m_noseRetrieveRequest = true;
  184. m_desiredApple.reset();
  185. };
  186. void ManipulatorController::RetrieveNose()
  187. {
  188. AZ_Printf("ManipulatorController", "RetrieveNose\n");
  189. m_time_XZ_ok = std::numeric_limits<float>::lowest();
  190. m_noseRetrieveRequest = true;
  191. }
  192. int ManipulatorController::GetStatus()
  193. {
  194. return 0;
  195. };
  196. void ManipulatorController::ResetTimer()
  197. {
  198. m_time_XZ_ok = 0;
  199. }
  200. bool ManipulatorController::IsNoseRetreived()
  201. {
  202. return m_noseRetrievingSuccess;
  203. }
  204. AZ::EntityId ManipulatorController::GetEffectorEntity()
  205. {
  206. return m_effector;
  207. }
  208. AZ::EntityId ManipulatorController::GetRestEntity()
  209. {
  210. return m_restEntity;
  211. }
  212. void ManipulatorController::OnImGuiUpdate()
  213. {
  214. AZStd::string window_name = AZStd::string::format("ManipulatorController%s", GetEntityId().ToString().c_str());
  215. ImGui::Begin(window_name.c_str());
  216. auto pos = GetPosition();
  217. if (m_desiredApple){
  218. ImGui::Text("Desired Apple : %.1f %.1f %.1f", m_desiredApple->GetX(),m_desiredApple->GetY(),m_desiredApple->GetZ());
  219. }else{
  220. ImGui::Text("No Desired Apple");
  221. }
  222. if (ImGui::CollapsingHeader("Gantry"))
  223. {
  224. ImGui::Text("Positions : %.1f %.1f", pos.GetX(), pos.GetZ() );
  225. ImGui::Text("SetPoint : %.1f %.1f", m_setPointX, m_setPointZ );
  226. }
  227. if (ImGui::CollapsingHeader("Nose"))
  228. {
  229. ImGui::Text("Positions : %.1f", pos.GetY());
  230. ImGui::Text("SetPoint : %.1f", m_setPointY);
  231. ImGui::Checkbox("noseRetrieveRequest", &m_noseRetrieveRequest);
  232. ImGui::Checkbox("noseRetrievingSuccess", &m_noseRetrievingSuccess);
  233. }
  234. ImGui::End();
  235. }
  236. } // namespace AppleKraken