KrakenEffectorComponent.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526
  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 "KrakenEffectorComponent.h"
  9. #include "ApplePickingNotifications.h"
  10. #include "Manipulator/ManipulatorRequestBus.h"
  11. #include "PickingStructs.h"
  12. #include "ROS2/VehicleDynamics/VehicleInputControlBus.h"
  13. #include <AzCore/Component/Entity.h>
  14. #include <AzCore/Component/ComponentApplicationBus.h>
  15. #include <AzCore/Component/TransformBus.h>
  16. #include <AzCore/Serialization/EditContext.h>
  17. #include <AzCore/Serialization/EditContextConstants.inl>
  18. #include <AzCore/Serialization/SerializeContext.h>
  19. #include <AzFramework/Physics/Common/PhysicsSimulatedBody.h>
  20. #include <AzFramework/Physics/RigidBodyBus.h>
  21. #include <LmbrCentral/Shape/BoxShapeComponentBus.h>
  22. namespace AppleKraken
  23. {
  24. namespace DebugStateTransit
  25. {
  26. static const AZStd::unordered_map<EffectorState, const char*> kMapToString{ { EffectorState::INVALID, "INVALID" },
  27. { EffectorState::IDLE, "IDLE" },
  28. { EffectorState::PREPARED, "PREPARED" },
  29. { EffectorState::PICKING, "PICKING" },
  30. { EffectorState::PICKING_STABILIZE, "PICKING_STABILIZE" },
  31. { EffectorState::RETRIEVING, "RETRIEVING" },
  32. { EffectorState::RETRIEVING_NOSE, "RETRIEVING_NOSE" },
  33. { EffectorState::RETRIEVING_STABILIZE,
  34. "RETRIEVING_STABILIZE" } };
  35. // TODO - this is a debug space for a stub implementation. Proper: a state transition machine with lambdas.
  36. AZStd::string StateTransitionString(EffectorState current, EffectorState next)
  37. {
  38. return AZStd::string::format("state transition %s -> %s\n", kMapToString.at(current), kMapToString.at(next));
  39. }
  40. } // namespace DebugStateTransit
  41. KrakenEffectorComponent::KrakenEffectorComponent()
  42. {
  43. InitializeStateProperties();
  44. }
  45. void KrakenEffectorComponent::Activate()
  46. {
  47. ApplePickingRequestBus::Handler::BusConnect(GetEntityId());
  48. AZ::TickBus::Handler::BusConnect();
  49. m_onTriggerHandleBeginHandler = AzPhysics::SimulatedBodyEvents::OnTriggerEnter::Handler(
  50. [&]([[maybe_unused]] AzPhysics::SimulatedBodyHandle bodyHandle, [[maybe_unused]] const AzPhysics::TriggerEvent& event)
  51. {
  52. const AZ::EntityId& e1 = event.m_otherBody->GetEntityId();
  53. const AZ::EntityId& e2 = event.m_triggerBody->GetEntityId();
  54. [[maybe_unused]] const AZ::EntityId& collideToEntityId = m_appleProbe == e1 ? e2 : e1;
  55. // AZStd::string entity_name;
  56. // AZ::ComponentApplicationBus::BroadcastResult(entity_name,
  57. // &AZ::ComponentApplicationRequests::GetEntityName, collideToEntityId);
  58. // AZ_Printf("m_onTriggerHandleBeginHandler", "Collission %s\n", entity_name.c_str());
  59. // AzPhysics::SimulatedBody* collideToEntityId = this->GetEntityId() == e1 ? event.m_triggerBody : event.m_otherBody;}
  60. if (m_currentTask.m_appleEntityId == collideToEntityId)
  61. {
  62. AZ_TracePrintf("m_onTriggerHandleBeginHandler", " %s : m_onTriggerHandle to Apple!====================",
  63. GetEntity()->GetName().c_str());
  64. ApplePickingNotificationBus::Event(this->GetEntityId(),&ApplePickingNotifications::ApplePicked);
  65. if (m_effectorState == EffectorState::PICKING)
  66. {
  67. // start picking the apple
  68. BeginTransitionIfAcceptable(EffectorState::PICKING_STABILIZE);
  69. }
  70. }
  71. if (m_restEntityId == collideToEntityId)
  72. {
  73. AZ_TracePrintf("m_onTriggerHandleBeginHandler", "%s : m_onTriggerHandle to Rest!====================",
  74. GetEntity()->GetName().c_str());
  75. if (m_effectorState == EffectorState::RETRIEVING || m_effectorState == EffectorState::RETRIEVING_NOSE )
  76. {
  77. // start picking the apple
  78. BeginTransitionIfAcceptable(EffectorState::RETRIEVING_STABILIZE);
  79. }
  80. }
  81. });
  82. }
  83. void KrakenEffectorComponent::Deactivate()
  84. {
  85. AZ::TickBus::Handler::BusDisconnect();
  86. ApplePickingRequestBus::Handler::BusDisconnect();
  87. }
  88. void KrakenEffectorComponent::Reflect(AZ::ReflectContext* context)
  89. {
  90. if (AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context))
  91. {
  92. serialize->Class<KrakenEffectorComponent, AZ::Component>()
  93. ->Version(4)
  94. ->Field("ReachEntity", &KrakenEffectorComponent::m_reachEntity)
  95. ->Field("ManipulatorEntity", &KrakenEffectorComponent::m_manipulatorEntity)
  96. ->Field("AppleProbe", &KrakenEffectorComponent::m_appleProbe)
  97. ->Field("RootManipulatorFreeze", &KrakenEffectorComponent::m_rootEntityToFreeze)
  98. ->Field("BaseLinkToKinematic", &KrakenEffectorComponent::m_baseLinkToKinematic)
  99. ->Field("RestEntity", &KrakenEffectorComponent::m_restEntityId)
  100. ->Field("PickStabilizeTime", &KrakenEffectorComponent::m_stabilize_time)
  101. ->Field("MaxPickingTime", &KrakenEffectorComponent::m_maxPickingTime);
  102. if (AZ::EditContext* ec = serialize->GetEditContext())
  103. {
  104. ec->Class<KrakenEffectorComponent>("Kraken Effector", "Manipulator component for picking apples")
  105. ->ClassElement(AZ::Edit::ClassElements::EditorData, "")
  106. ->Attribute(AZ::Edit::Attributes::Category, "AppleKraken")
  107. ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game"))
  108. ->DataElement(
  109. AZ::Edit::UIHandlers::EntityId,
  110. &KrakenEffectorComponent::m_reachEntity,
  111. "Kraken Reach entity",
  112. "Kraken entity with box shape to set reach area")
  113. ->DataElement(
  114. AZ::Edit::UIHandlers::EntityId,
  115. &KrakenEffectorComponent::m_manipulatorEntity,
  116. "Entity with manipulator",
  117. "The entity that has a component handling events from ManipulatorRequestBus")
  118. ->DataElement(
  119. AZ::Edit::UIHandlers::EntityId, &KrakenEffectorComponent::m_appleProbe, "Entity to probe apples", "Sucking collider")
  120. ->DataElement(
  121. AZ::Edit::UIHandlers::EntityId,
  122. &KrakenEffectorComponent::m_rootEntityToFreeze,
  123. "RootManipulatorFreeze",
  124. "RootManipulatorFreeze to freeze during robot movement")
  125. ->DataElement(
  126. AZ::Edit::UIHandlers::EntityId,
  127. &KrakenEffectorComponent::m_baseLinkToKinematic,
  128. "BaseLinkToKinematic",
  129. "BaseLinkToKinematic during manipulator movement")
  130. ->DataElement(
  131. AZ::Edit::UIHandlers::EntityId,
  132. &KrakenEffectorComponent::m_restEntityId,
  133. "ManipulatorRestPoint",
  134. "ManipulatorRestPoint")
  135. ->DataElement(
  136. AZ::Edit::UIHandlers::EntityId,
  137. &KrakenEffectorComponent::m_stabilize_time,
  138. "PickStabilizeTime",
  139. "PickStabilizeTime")
  140. ->DataElement(
  141. AZ::Edit::UIHandlers::EntityId, &KrakenEffectorComponent::m_maxPickingTime, "MaxPickingTime", "MaxPickingTime")
  142. ->Attribute(AZ::Edit::Attributes::AutoExpand, true);
  143. }
  144. }
  145. ManipulatorRequestHandler::Reflect(context);
  146. }
  147. void KrakenEffectorComponent::PrepareForPicking()
  148. {
  149. AZ_TracePrintf("KrakenEffectorComponent", "%s: PrepareForPicking\n", GetEntity()->GetName().c_str());
  150. BeginTransitionIfAcceptable(EffectorState::PREPARED);
  151. }
  152. void KrakenEffectorComponent::PickApple(const PickAppleTask& appleTask)
  153. {
  154. AZ_TracePrintf("KrakenEffectorComponent", "%s: PickApple\n", GetEntity()->GetName().c_str());
  155. // TODO - handle appleTask
  156. m_currentTask = appleTask;
  157. ManipulatorRequestBus::Event(m_manipulatorEntity, &ManipulatorRequest::PickApple, appleTask.m_middle);
  158. BeginTransitionIfAcceptable(EffectorState::PICKING);
  159. }
  160. void KrakenEffectorComponent::FinishPicking()
  161. {
  162. AZ_TracePrintf("KrakenEffectorComponent", "%s : FinishPicking\n", GetEntity()->GetName().c_str());
  163. BeginTransitionIfAcceptable(EffectorState::IDLE);
  164. }
  165. PickingState KrakenEffectorComponent::GetEffectorState()
  166. {
  167. PickingState state;
  168. state.m_effectorState = m_effectorState;
  169. state.m_taskProgress = 0.0f; // TODO
  170. state.m_description = DebugStateTransit::kMapToString.at(m_effectorState);
  171. if (m_currentTask.IsValid())
  172. {
  173. state.m_currentTask = m_currentTask;
  174. }
  175. return state;
  176. }
  177. AZ::Obb KrakenEffectorComponent::GetEffectorReachArea()
  178. {
  179. AZ_TracePrintf("KrakenEffectorComponent", "%s: GetEffectorReachArea\n", GetEntity()->GetName().c_str());
  180. AZ::Obb reachArea;
  181. if (m_reachEntity.IsValid())
  182. {
  183. AZ::Transform targetTM = AZ::Transform::CreateIdentity();
  184. AZ::TransformBus::EventResult(targetTM, m_reachEntity, &AZ::TransformBus::Events::GetWorldTM);
  185. AZ::Vector3 dimensions = AZ::Vector3{ 0.f };
  186. LmbrCentral::BoxShapeComponentRequestsBus::EventResult(
  187. dimensions, m_reachEntity, &LmbrCentral::BoxShapeComponentRequests::GetBoxDimensions);
  188. if (!dimensions.IsZero())
  189. {
  190. AZ_Printf("KrakenEffectorComponent", "OurEffectorReachArea :");
  191. AZ_Printf(
  192. "KrakenEffectorComponent", " local dimensions : %f %f %f", dimensions.GetX(), dimensions.GetY(), dimensions.GetZ());
  193. AZ_Printf(
  194. "KrakenEffectorComponent",
  195. " transform - rot : %f %f %f %f",
  196. targetTM.GetRotation().GetX(),
  197. targetTM.GetRotation().GetY(),
  198. targetTM.GetRotation().GetZ(),
  199. targetTM.GetRotation().GetW());
  200. AZ_Printf(
  201. "KrakenEffectorComponent",
  202. " transform - pos : %f %f %f",
  203. targetTM.GetTranslation().GetX(),
  204. targetTM.GetTranslation().GetY(),
  205. targetTM.GetTranslation().GetZ());
  206. reachArea.SetHalfLengths(dimensions / 2);
  207. reachArea.SetPosition(targetTM.GetTranslation());
  208. reachArea.SetRotation(targetTM.GetRotation());
  209. return reachArea;
  210. }
  211. AZ_Warning(
  212. "KrakenEffectorComponent", true, "Reach entity %s does not have BoxShapeComponent!", m_reachEntity.ToString().c_str());
  213. }
  214. AZ_Warning("KrakenEffectorComponent", true, "GetEffectorReachArea - returning invalid reach");
  215. reachArea.SetHalfLengths(AZ::Vector3{ 0, 0, 0 });
  216. reachArea.SetPosition(AZ::Vector3{ 0, 0, 0 }); /// TODO - get it from entity With box
  217. return reachArea;
  218. }
  219. void KrakenEffectorComponent::OnTick(float deltaTime, [[maybe_unused]] AZ::ScriptTimePoint time)
  220. {
  221. m_currentStateTransitionTime += deltaTime;
  222. GetCurrentStateAction()();
  223. if (m_effectorState == m_effectorTargetState)
  224. { // //TODO - nothing to do in stub version
  225. return;
  226. }
  227. // State transition
  228. AZ_TracePrintf(
  229. "KrakenEffectorComponent", "%s : %s", GetEntity()->GetName().c_str(), DebugStateTransit::StateTransitionString(m_effectorState, m_effectorTargetState).c_str());
  230. m_currentStateTransitionTime = 0.0f;
  231. // Update state
  232. auto transitionAction = GetCurrentTransitionAction();
  233. m_effectorState = m_effectorTargetState;
  234. transitionAction();
  235. if (!m_registeredCallback)
  236. {
  237. auto* physicsSystem = AZ::Interface<AzPhysics::SystemInterface>::Get();
  238. auto* sceneInterface = AZ::Interface<AzPhysics::SceneInterface>::Get();
  239. auto [physicScene, physicBody] = physicsSystem->FindAttachedBodyHandleFromEntityId(m_appleProbe);
  240. if (physicBody != AzPhysics::InvalidSimulatedBodyHandle && physicScene != AzPhysics::InvalidSceneHandle)
  241. {
  242. AzPhysics::SimulatedBody* simulated_body = sceneInterface->GetSimulatedBodyFromHandle(physicScene, physicBody);
  243. simulated_body->RegisterOnTriggerEnterHandler(m_onTriggerHandleBeginHandler);
  244. m_registeredCallback = true;
  245. }
  246. }
  247. }
  248. void KrakenEffectorComponent::LockManipulator(bool locked)
  249. {
  250. AZStd::vector<AZ::EntityId> descendants;
  251. AZ::TransformBus::EventResult(descendants, m_rootEntityToFreeze, &AZ::TransformBus::Events::GetAllDescendants);
  252. descendants.push_back(m_rootEntityToFreeze);
  253. if (is_manipulator_locked != locked)
  254. {
  255. if (locked) {
  256. AZ_Printf("KrakenEffectorComponent", "Locking : %s\n", GetEntity()->GetName().c_str());
  257. }
  258. else{
  259. AZ_Printf("KrakenEffectorComponent", "Unlocking : %s\n", GetEntity()->GetName().c_str());
  260. }
  261. for (auto& descadant : descendants)
  262. {
  263. using VehicleBus = VehicleDynamics::VehicleInputControlRequestBus;
  264. if (locked)
  265. {
  266. // Lock manipulator, make base_link not kinematic anymore
  267. Physics::RigidBodyRequestBus::Event(descadant, &Physics::RigidBodyRequestBus::Events::DisablePhysics);
  268. Physics::RigidBodyRequestBus::Event(m_baseLinkToKinematic, &Physics::RigidBodyRequestBus::Events::SetKinematic, false);
  269. VehicleBus::Event(m_baseLinkToKinematic, &VehicleBus::Events::SetDisableVehicleDynamics, false);
  270. }
  271. else
  272. {
  273. // loose manipulator, make base_link kinematic
  274. Physics::RigidBodyRequestBus::Event(descadant, &Physics::RigidBodyRequestBus::Events::EnablePhysics);
  275. Physics::RigidBodyRequestBus::Event(m_baseLinkToKinematic, &Physics::RigidBodyRequestBus::Events::SetKinematic, true);
  276. VehicleBus::Event(m_baseLinkToKinematic, &VehicleBus::Events::SetDisableVehicleDynamics, true);
  277. }
  278. }
  279. is_manipulator_locked = locked;
  280. }
  281. }
  282. bool KrakenEffectorComponent::IsTransitionValid(EffectorState targetState) const
  283. {
  284. AZ_Assert(m_effectorState != EffectorState::INVALID, "Effector is in an invalid state! Unable to access transition properties.");
  285. return m_stateProperties.m_allowedTransitions.contains(AZStd::make_pair(m_effectorState, targetState));
  286. }
  287. bool KrakenEffectorComponent::IsTransitionAcceptable(EffectorState targetState) const
  288. {
  289. if (m_effectorState == EffectorState::PICKING && m_effectorState == EffectorState::PICKING)
  290. {
  291. // allow this non-existing state transition without error
  292. return true;
  293. }
  294. if (m_effectorState != m_effectorTargetState)
  295. {
  296. AZ_Error(
  297. "KrakenEffectorComponent",
  298. false,
  299. "%s: Unable to accept request: currently realizing %s", GetEntity()->GetName().c_str(),
  300. DebugStateTransit::StateTransitionString(m_effectorState, m_effectorTargetState).c_str());
  301. return false;
  302. }
  303. if (!IsTransitionValid(targetState))
  304. {
  305. AZ_Error(
  306. "KrakenEffectorComponent",
  307. false,
  308. "%s: Invalid state transition %s",GetEntity()->GetName().c_str(),
  309. DebugStateTransit::StateTransitionString(m_effectorState, m_effectorTargetState).c_str());
  310. return false;
  311. }
  312. return true;
  313. }
  314. void KrakenEffectorComponent::BeginTransitionIfAcceptable(EffectorState targetState)
  315. {
  316. if (IsTransitionAcceptable(targetState))
  317. {
  318. m_currentStateTransitionTime = 0.0f;
  319. m_effectorTargetState = targetState;
  320. }
  321. }
  322. void KrakenEffectorComponent::InitializeStateProperties()
  323. {
  324. m_stateProperties.m_stateActions = {
  325. { EffectorState::IDLE,
  326. [this]()
  327. {
  328. LockManipulator(true);
  329. } },
  330. { EffectorState::PREPARED,
  331. []()
  332. {
  333. } },
  334. { EffectorState::PICKING,
  335. [this]()
  336. {
  337. if (m_currentStateTransitionTime > m_maxPickingTime)
  338. {
  339. AZ_Printf("m_onTriggerHandleBeginHandler", "%s : Failed to retrieve apple--------------------\n", GetEntity()->GetName().c_str());
  340. BeginTransitionIfAcceptable(EffectorState::RETRIEVING_FAILED);
  341. }
  342. } },
  343. { EffectorState::PICKING_STABILIZE,
  344. [this]()
  345. {
  346. if (m_currentStateTransitionTime > m_stabilize_time)
  347. {
  348. BeginTransitionIfAcceptable(EffectorState::RETRIEVING_NOSE);
  349. }
  350. } },
  351. { EffectorState::RETRIEVING_NOSE,
  352. [this]()
  353. {
  354. bool result;
  355. EBUS_EVENT_ID_RESULT(result, m_manipulatorEntity, ManipulatorRequestBus, IsNoseRetreived);
  356. if (result)
  357. {
  358. BeginTransitionIfAcceptable(EffectorState::RETRIEVING);
  359. }
  360. } },
  361. { EffectorState::RETRIEVING_FAILED,
  362. [this]()
  363. {
  364. bool result;
  365. EBUS_EVENT_ID_RESULT(result, m_manipulatorEntity, ManipulatorRequestBus, IsNoseRetreived);
  366. if (result)
  367. {
  368. BeginTransitionIfAcceptable(EffectorState::PREPARED);
  369. }
  370. } },
  371. {EffectorState::RETRIEVING,
  372. [this]() {
  373. // Continue if manipulator retraction was blocked
  374. if (m_currentStateTransitionTime > m_maxRetrieveTime) {
  375. BeginTransitionIfAcceptable(EffectorState::RETRIEVING_STABILIZE);
  376. }
  377. } },
  378. { EffectorState::RETRIEVING_STABILIZE,
  379. [this]()
  380. {
  381. if (m_currentStateTransitionTime > m_stabilize_time)
  382. {
  383. BeginTransitionIfAcceptable(EffectorState::PREPARED);
  384. }
  385. } }
  386. };
  387. m_stateProperties.m_allowedTransitions = {
  388. {
  389. { EffectorState::IDLE, EffectorState::PREPARED },
  390. [this]()
  391. {
  392. LockManipulator(false);
  393. ApplePickingNotificationBus::Event(GetEntityId(),&ApplePickingNotifications::EffectorReadyForPicking);
  394. },
  395. },
  396. {
  397. { EffectorState::PREPARED, EffectorState::PICKING },
  398. []()
  399. {
  400. },
  401. },
  402. {
  403. { EffectorState::PICKING, EffectorState::PICKING_STABILIZE },
  404. []()
  405. {
  406. },
  407. },
  408. {
  409. { EffectorState::PICKING_STABILIZE, EffectorState::RETRIEVING_NOSE },
  410. [this]()
  411. {
  412. if (!m_currentTask.IsValid())
  413. {
  414. AZ_Error("KrakenEffectorComponent", true, "%s : No valid task for current picking!",GetEntity()->GetName().c_str());
  415. return;
  416. }
  417. ManipulatorRequestBus::Event(m_manipulatorEntity, &ManipulatorRequest::RetrieveNose);
  418. },
  419. },
  420. {
  421. { EffectorState::RETRIEVING_NOSE, EffectorState::RETRIEVING },
  422. [this]()
  423. {
  424. ManipulatorRequestBus::Event(m_manipulatorEntity, &ManipulatorRequest::Retrieve);
  425. },
  426. },
  427. { // on skip
  428. { EffectorState::RETRIEVING_NOSE, EffectorState::RETRIEVING_STABILIZE },
  429. [this]()
  430. {
  431. ManipulatorRequestBus::Event(m_manipulatorEntity, &ManipulatorRequest::Retrieve);
  432. },
  433. },
  434. {
  435. { EffectorState::RETRIEVING, EffectorState::RETRIEVING_STABILIZE },
  436. []()
  437. {
  438. },
  439. },
  440. {
  441. { EffectorState::RETRIEVING_FAILED, EffectorState::PREPARED },
  442. [this]()
  443. {
  444. ApplePickingNotificationBus::Event(this->GetEntityId(),&ApplePickingNotifications::PickingFailed, "Timeout");
  445. },
  446. },
  447. {
  448. { EffectorState::RETRIEVING_STABILIZE, EffectorState::PREPARED },
  449. [this]()
  450. {
  451. ApplePickingNotificationBus::Event(GetEntityId(),&ApplePickingNotifications::AppleRetrieved);
  452. },
  453. },
  454. {
  455. { EffectorState::PREPARED, EffectorState::IDLE },
  456. []()
  457. {
  458. },
  459. },
  460. {
  461. { EffectorState::PICKING, EffectorState::IDLE },
  462. [this]()
  463. {
  464. // apple picking was finished with timeout
  465. ManipulatorRequestBus::Event(m_manipulatorEntity, &ManipulatorRequest::Retrieve);
  466. },
  467. },
  468. {
  469. { EffectorState::PICKING, EffectorState::RETRIEVING_FAILED },
  470. [this]()
  471. {
  472. ManipulatorRequestBus::Event(m_manipulatorEntity, &ManipulatorRequest::RetrieveNose);
  473. },
  474. },
  475. };
  476. }
  477. const AZStd::function<void()>& KrakenEffectorComponent::GetCurrentStateAction() const
  478. {
  479. AZ_Assert(m_effectorState != EffectorState::INVALID, "%s : Effector is in an invalid state! Unable to access state properties.",GetEntity()->GetName().c_str());
  480. return m_stateProperties.m_stateActions.at(m_effectorState);
  481. }
  482. const AZStd::function<void()>& KrakenEffectorComponent::GetCurrentTransitionAction() const
  483. {
  484. return m_stateProperties.m_allowedTransitions.at(AZStd::make_pair(m_effectorState, m_effectorTargetState));
  485. }
  486. } // namespace AppleKraken