diff --git a/lib/state_machine/message.hpp b/lib/state_machine/message.hpp deleted file mode 100644 index 79d0eb13..00000000 --- a/lib/state_machine/message.hpp +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once - -namespace hyped::state_machine { - -// Message class containing messages that prompt transitions -enum class Message { - kNone, - kCalibrating, - kReady, - kAccelerating, - kCruising, - kMotorBrake, - kPreFrictionBrake, - kFrictionBrake, - kStopped, - kFailureBrake, - kPreFrictionBrakeFail, - kFrictionBrakeFail, - kOff, - kFailureStopped, - kFailureOff, -}; - -} // namespace hyped::state_machine \ No newline at end of file diff --git a/lib/state_machine/state.hpp b/lib/state_machine/state.hpp index c84bd42c..3e117bb6 100644 --- a/lib/state_machine/state.hpp +++ b/lib/state_machine/state.hpp @@ -4,19 +4,21 @@ namespace hyped::state_machine { enum class State { kIdle, - kCalibrating, + kCalibrate, + kPrecharge, + kReadyForLevitation, + kBeginLevitation, kReady, - kAccelerating, - kCruising, - kMotorBraking, - kPreFrictionBraking, - kFrictionBraking, - kPreFrictionBrakingFail, - kFrictionBrakingFail, - kFailureBraking, + kAccelerate, + kLimBrake, + kFrictionBrake, + kStopLevitation, kStopped, - kFailureStopped, - kOff, + kBatteryRecharge, + kCapacitorDischarge, + kFailureBrake, + kFailure, + kSafe, }; } // namespace hyped::state_machine \ No newline at end of file diff --git a/lib/state_machine/state_machine.cpp b/lib/state_machine/state_machine.cpp index 4a931889..f510b624 100644 --- a/lib/state_machine/state_machine.cpp +++ b/lib/state_machine/state_machine.cpp @@ -8,14 +8,14 @@ StateMachine::StateMachine() : current_state_{State::kIdle} { } -Message StateMachine::stringToMessage(const std::string &message_name) +State StateMachine::stringToState(const std::string &state_name) { - return string_to_message_.at(message_name); + return string_to_state_.at(state_name); } -std::string StateMachine::messageToString(const Message &message) +std::string StateMachine::stateToString(const State &state) { - return message_to_string_.at(message); + return state_to_string_.at(state); } State StateMachine::getCurrentState() @@ -23,4 +23,14 @@ State StateMachine::getCurrentState() return current_state_; } +core::Result StateMachine::handleTransition(const State &state) +{ + const auto next_state = transition_to_state_.find({current_state_, state}); + if (next_state != transition_to_state_.end()) { + current_state_ = next_state->second; + return core::Result::kSuccess; + } + return core::Result::kFailure; +} + } // namespace hyped::state_machine \ No newline at end of file diff --git a/lib/state_machine/state_machine.hpp b/lib/state_machine/state_machine.hpp index 5152c773..3abf0172 100644 --- a/lib/state_machine/state_machine.hpp +++ b/lib/state_machine/state_machine.hpp @@ -8,68 +8,75 @@ #include #include +#include namespace hyped::state_machine { class StateMachine { public: StateMachine(); - Message stringToMessage(const std::string &message_name); - std::string messageToString(const Message &message); + State stringToState(const std::string &state_name); + std::string stateToString(const State &state); State getCurrentState(); + core::Result handleTransition(const State &state); private: - const std::unordered_map string_to_message_ - = {{"kCalibrating", Message::kCalibrating}, - {"kReady", Message::kReady}, - {"kAccelerating", Message::kAccelerating}, - {"kCruising", Message::kCruising}, - {"kMotorBrake", Message::kMotorBrake}, - {"kPreFrictionBrake", Message::kPreFrictionBrake}, - {"kFrictionBrake", Message::kFrictionBrake}, - {"kStopped", Message::kStopped}, - {"kFailureBrake", Message::kFailureBrake}, - {"kPreFrictionBrakeFail", Message::kPreFrictionBrakeFail}, - {"kFrictionBrakeFail", Message::kFrictionBrakeFail}, - {"kOff", Message::kOff}, - {"kFailureStopped", Message::kFailureStopped}, - {"kFailureOff", Message::kFailureOff}}; - const std::unordered_map message_to_string_ - = {{Message::kCalibrating, "kCalibrating"}, - {Message::kReady, "kReady"}, - {Message::kAccelerating, "kAccelerating"}, - {Message::kCruising, "kCruising"}, - {Message::kMotorBrake, "kMotorBrake"}, - {Message::kPreFrictionBrake, "kPreFrictionBrake"}, - {Message::kFrictionBrake, "kFrictionBrake"}, - {Message::kStopped, "kStopped"}, - {Message::kFailureBrake, "kFailureBrake"}, - {Message::kPreFrictionBrakeFail, "kPreFrictionBrakeFail"}, - {Message::kFrictionBrakeFail, "kFrictionBrakeFail"}, - {Message::kOff, "kOff"}, - {Message::kFailureStopped, "kFailureStopped"}, - {Message::kFailureOff, "kFailureOff"}}; - const boost::unordered_map transition_to_state_ - = {{{State::kIdle, Message::kCalibrating}, State::kCalibrating}, - {{State::kCalibrating, Message::kReady}, State::kReady}, - {{State::kReady, Message::kAccelerating}, State::kAccelerating}, - {{State::kAccelerating, Message::kCruising}, State::kCruising}, - {{State::kCruising, Message::kMotorBrake}, State::kMotorBraking}, - {{State::kMotorBraking, Message::kPreFrictionBrake}, State::kPreFrictionBraking}, - {{State::kPreFrictionBraking, Message::kFrictionBrake}, State::kFrictionBraking}, - {{State::kFrictionBraking, Message::kStopped}, State::kStopped}, - {{State::kStopped, Message::kOff}, State::kOff}, - {{State::kAccelerating, Message::kFailureBrake}, State::kFailureBraking}, - {{State::kAccelerating, Message::kPreFrictionBrakeFail}, State::kPreFrictionBrakingFail}, - {{State::kPreFrictionBrakingFail, Message::kFrictionBrakeFail}, State::kFrictionBrakingFail}, - {{State::kCruising, Message::kFailureBrake}, State::kFailureBraking}, - {{State::kCruising, Message::kPreFrictionBrakeFail}, State::kPreFrictionBrakingFail}, - {{State::kMotorBraking, Message::kFailureBrake}, State::kFailureBraking}, - {{State::kMotorBraking, Message::kPreFrictionBrakeFail}, State::kPreFrictionBrakingFail}, - {{State::kFrictionBrakingFail, Message::kFailureBrake}, State::kFailureBraking}, - {{State::kFrictionBrakingFail, Message::kFailureStopped}, State::kFailureStopped}, - {{State::kFailureBraking, Message::kFailureStopped}, State::kFailureStopped}, - {{State::kFailureStopped, Message::kFailureOff}, State::kOff}}; + const std::unordered_map string_to_state_ + = {{"kCalibrate", State::kCalibrate}, + {"kPrecharge", State::kPrecharge}, + {"kReadyForLeviation", State::kReadyForLevitation}, + {"kBeginLevitation", State::kBeginLevitation}, + {"kReady", State::kReady}, + {"kAccelerate", State::kAccelerate}, + {"kLimBrake", State::kLimBrake}, + {"kFrictionBrake", State::kFrictionBrake}, + {"kStopLevitation", State::kStopLevitation}, + {"kStopped", State::kStopped}, + {"kBatteryRecharge", State::kBatteryRecharge}, + {"kCapacitorDischarge", State::kCapacitorDischarge}, + {"kFailureBrake", State::kFailureBrake}, + {"kFailure", State::kFailure}, + {"kSafe", State::kSafe}}; + const std::unordered_map state_to_string_ + = {{State::kCalibrate, "kCalibrate"}, + {State::kPrecharge, "kPrecharge"}, + {State::kReadyForLevitation, "kReadyForLevitation"}, + {State::kBeginLevitation, "kBeginLevitation"}, + {State::kReady, "kReady"}, + {State::kAccelerate, "kAccelerate"}, + {State::kLimBrake, "kLimBrake"}, + {State::kFrictionBrake, "kFrictionBrake"}, + {State::kStopLevitation, "kStopLevitation"}, + {State::kStopped, "kStopped"}, + {State::kBatteryRecharge, "kBatteryRecharge"}, + {State::kCapacitorDischarge, "kCapacitorDischarge"}, + {State::kFailureBrake, "kFailureBrake"}, + {State::kFailure, "kFailure"}, + {State::kSafe, "kSafe"}}; + const boost::unordered_map transition_to_state_ + = {{{State::kIdle, State::kCalibrate}, State::kCalibrate}, + {{State::kIdle, State::kFailure}, State::kFailure}, + {{State::kCalibrate, State::kPrecharge}, State::kPrecharge}, + {{State::kCalibrate, State::kFailure}, State::kFailure}, + {{State::kPrecharge, State::kReadyForLevitation}, State::kReadyForLevitation}, + {{State::kPrecharge, State::kFailure}, State::kFailure}, + {{State::kReadyForLevitation, State::kBeginLevitation}, State::kBeginLevitation}, + {{State::kReadyForLevitation, State::kFailure}, State::kFailure}, + {{State::kBeginLevitation, State::kReady}, State::kReady}, + {{State::kBeginLevitation, State::kFailure}, State::kFailure}, + {{State::kReady, State::kAccelerate}, State::kAccelerate}, + {{State::kAccelerate, State::kLimBrake}, State::kLimBrake}, + {{State::kAccelerate, State::kFailureBrake}, State::kFailureBrake}, + {{State::kLimBrake, State::kFrictionBrake}, State::kFrictionBrake}, + {{State::kLimBrake, State::kFailureBrake}, State::kFailureBrake}, + {{State::kFrictionBrake, State::kStopLevitation}, State::kStopLevitation}, + {{State::kFrictionBrake, State::kFailureBrake}, State::kFailureBrake}, + {{State::kStopLevitation, State::kStopped}, State::kStopped}, + {{State::kStopped, State::kBatteryRecharge}, State::kBatteryRecharge}, + {{State::kBatteryRecharge, State::kCapacitorDischarge}, State::kCapacitorDischarge}, + {{State::kFailureBrake, State::kCapacitorDischarge}, State::kCapacitorDischarge}, + {{State::kFailure, State::kCapacitorDischarge}, State::kCapacitorDischarge}, + {{State::kCapacitorDischarge, State::kSafe}, State::kSafe}}; State current_state_; }; diff --git a/lib/state_machine/types.hpp b/lib/state_machine/types.hpp index 00280229..347e9007 100644 --- a/lib/state_machine/types.hpp +++ b/lib/state_machine/types.hpp @@ -1,6 +1,5 @@ #pragma once -#include "message.hpp" #include "state.hpp" #include @@ -8,22 +7,22 @@ #include namespace hyped::state_machine { -struct SourceAndMessage { +struct SourceAndTarget { State source; - Message message; + State target; - bool operator==(const SourceAndMessage &key) const + bool operator==(const SourceAndTarget &key) const { - return key.source == source && key.message == message; + return key.source == source && key.target == target; } }; -struct source_and_message_hash { - std::size_t operator()(SourceAndMessage const &key) const +struct source_and_target_hash { + std::size_t operator()(SourceAndTarget const &key) const { std::size_t seed = 0; boost::hash_combine(seed, key.source); - boost::hash_combine(seed, key.message); + boost::hash_combine(seed, key.target); return seed; } }; diff --git a/test/state_machine/stm_tests.cpp b/test/state_machine/stm_tests.cpp index d9eaa23c..2a72f791 100644 --- a/test/state_machine/stm_tests.cpp +++ b/test/state_machine/stm_tests.cpp @@ -4,9 +4,175 @@ namespace hyped::test { -TEST(StateMachine, initalize) +void testTransition(std::shared_ptr stm, + state_machine::State transition_state, + state_machine::State expected_state) { - std::unique_ptr stm = std::make_unique(); + stm->handleTransition(transition_state); + ASSERT_TRUE(stm->getCurrentState() == expected_state); } +TEST(StateMachine, cleanRun) +{ + auto stm = std::make_shared(); + testTransition(stm, state_machine::State::kFailureBrake, state_machine::State::kIdle); + testTransition(stm, state_machine::State::kCalibrate, state_machine::State::kCalibrate); + testTransition(stm, state_machine::State::kPrecharge, state_machine::State::kPrecharge); + testTransition( + stm, state_machine::State::kReadyForLevitation, state_machine::State::kReadyForLevitation); + testTransition( + stm, state_machine::State::kBeginLevitation, state_machine::State::kBeginLevitation); + testTransition(stm, state_machine::State::kReady, state_machine::State::kReady); + testTransition(stm, state_machine::State::kAccelerate, state_machine::State::kAccelerate); + testTransition(stm, state_machine::State::kLimBrake, state_machine::State::kLimBrake); + testTransition(stm, state_machine::State::kFrictionBrake, state_machine::State::kFrictionBrake); + testTransition(stm, state_machine::State::kStopLevitation, state_machine::State::kStopLevitation); + testTransition(stm, state_machine::State::kStopped, state_machine::State::kStopped); + testTransition( + stm, state_machine::State::kBatteryRecharge, state_machine::State::kBatteryRecharge); + testTransition( + stm, state_machine::State::kCapacitorDischarge, state_machine::State::kCapacitorDischarge); + testTransition(stm, state_machine::State::kSafe, state_machine::State::kSafe); +} + +TEST(StateMachine, cleanRunDuplicatedMessages) +{ + auto stm = std::make_shared(); + testTransition(stm, state_machine::State::kFailureBrake, state_machine::State::kIdle); + testTransition(stm, state_machine::State::kFailureBrake, state_machine::State::kIdle); + testTransition(stm, state_machine::State::kCalibrate, state_machine::State::kCalibrate); + testTransition(stm, state_machine::State::kCalibrate, state_machine::State::kCalibrate); + testTransition(stm, state_machine::State::kPrecharge, state_machine::State::kPrecharge); + testTransition(stm, state_machine::State::kPrecharge, state_machine::State::kPrecharge); + testTransition( + stm, state_machine::State::kReadyForLevitation, state_machine::State::kReadyForLevitation); + testTransition( + stm, state_machine::State::kReadyForLevitation, state_machine::State::kReadyForLevitation); + testTransition( + stm, state_machine::State::kBeginLevitation, state_machine::State::kBeginLevitation); + testTransition( + stm, state_machine::State::kBeginLevitation, state_machine::State::kBeginLevitation); + testTransition(stm, state_machine::State::kReady, state_machine::State::kReady); + testTransition(stm, state_machine::State::kReady, state_machine::State::kReady); + testTransition(stm, state_machine::State::kAccelerate, state_machine::State::kAccelerate); + testTransition(stm, state_machine::State::kAccelerate, state_machine::State::kAccelerate); + testTransition(stm, state_machine::State::kLimBrake, state_machine::State::kLimBrake); + testTransition(stm, state_machine::State::kLimBrake, state_machine::State::kLimBrake); + testTransition(stm, state_machine::State::kFrictionBrake, state_machine::State::kFrictionBrake); + testTransition(stm, state_machine::State::kFrictionBrake, state_machine::State::kFrictionBrake); + testTransition(stm, state_machine::State::kStopLevitation, state_machine::State::kStopLevitation); + testTransition(stm, state_machine::State::kStopLevitation, state_machine::State::kStopLevitation); + testTransition(stm, state_machine::State::kStopped, state_machine::State::kStopped); + testTransition(stm, state_machine::State::kStopped, state_machine::State::kStopped); + testTransition( + stm, state_machine::State::kBatteryRecharge, state_machine::State::kBatteryRecharge); + testTransition( + stm, state_machine::State::kBatteryRecharge, state_machine::State::kBatteryRecharge); + testTransition( + stm, state_machine::State::kCapacitorDischarge, state_machine::State::kCapacitorDischarge); + testTransition( + stm, state_machine::State::kCapacitorDischarge, state_machine::State::kCapacitorDischarge); + testTransition(stm, state_machine::State::kSafe, state_machine::State::kSafe); + testTransition(stm, state_machine::State::kSafe, state_machine::State::kSafe); +} + +TEST(StateMachine, failureBrakeFromAccelerating) +{ + auto stm = std::make_shared(); + testTransition(stm, state_machine::State::kFailureBrake, state_machine::State::kIdle); + testTransition(stm, state_machine::State::kCalibrate, state_machine::State::kCalibrate); + testTransition(stm, state_machine::State::kPrecharge, state_machine::State::kPrecharge); + testTransition( + stm, state_machine::State::kReadyForLevitation, state_machine::State::kReadyForLevitation); + testTransition( + stm, state_machine::State::kBeginLevitation, state_machine::State::kBeginLevitation); + testTransition(stm, state_machine::State::kReady, state_machine::State::kReady); + testTransition(stm, state_machine::State::kAccelerate, state_machine::State::kAccelerate); + testTransition(stm, state_machine::State::kFailureBrake, state_machine::State::kFailureBrake); + testTransition( + stm, state_machine::State::kCapacitorDischarge, state_machine::State::kCapacitorDischarge); + testTransition(stm, state_machine::State::kSafe, state_machine::State::kSafe); +} + +TEST(StateMachine, failureBrakeFromLIMBrake) +{ + auto stm = std::make_shared(); + testTransition(stm, state_machine::State::kFailureBrake, state_machine::State::kIdle); + testTransition(stm, state_machine::State::kCalibrate, state_machine::State::kCalibrate); + testTransition(stm, state_machine::State::kPrecharge, state_machine::State::kPrecharge); + testTransition( + stm, state_machine::State::kReadyForLevitation, state_machine::State::kReadyForLevitation); + testTransition( + stm, state_machine::State::kBeginLevitation, state_machine::State::kBeginLevitation); + testTransition(stm, state_machine::State::kReady, state_machine::State::kReady); + testTransition(stm, state_machine::State::kAccelerate, state_machine::State::kAccelerate); + testTransition(stm, state_machine::State::kLimBrake, state_machine::State::kLimBrake); + testTransition(stm, state_machine::State::kFailureBrake, state_machine::State::kFailureBrake); + testTransition( + stm, state_machine::State::kCapacitorDischarge, state_machine::State::kCapacitorDischarge); + testTransition(stm, state_machine::State::kSafe, state_machine::State::kSafe); +} + +TEST(StateMachine, failureBrakeFrictionBrake) +{ + auto stm = std::make_shared(); + testTransition(stm, state_machine::State::kFailureBrake, state_machine::State::kIdle); + testTransition(stm, state_machine::State::kCalibrate, state_machine::State::kCalibrate); + testTransition(stm, state_machine::State::kPrecharge, state_machine::State::kPrecharge); + testTransition( + stm, state_machine::State::kReadyForLevitation, state_machine::State::kReadyForLevitation); + testTransition( + stm, state_machine::State::kBeginLevitation, state_machine::State::kBeginLevitation); + testTransition(stm, state_machine::State::kReady, state_machine::State::kReady); + testTransition(stm, state_machine::State::kAccelerate, state_machine::State::kAccelerate); + testTransition(stm, state_machine::State::kLimBrake, state_machine::State::kLimBrake); + testTransition(stm, state_machine::State::kFrictionBrake, state_machine::State::kFrictionBrake); + testTransition(stm, state_machine::State::kFailureBrake, state_machine::State::kFailureBrake); + testTransition( + stm, state_machine::State::kCapacitorDischarge, state_machine::State::kCapacitorDischarge); + testTransition(stm, state_machine::State::kSafe, state_machine::State::kSafe); +} + +TEST(StateMachine, duplicatedMessagesFailureStates) +{ + auto stm = std::make_shared(); + testTransition(stm, state_machine::State::kFailureBrake, state_machine::State::kIdle); + testTransition(stm, state_machine::State::kFailureBrake, state_machine::State::kIdle); + testTransition(stm, state_machine::State::kCalibrate, state_machine::State::kCalibrate); + testTransition(stm, state_machine::State::kCalibrate, state_machine::State::kCalibrate); + testTransition(stm, state_machine::State::kPrecharge, state_machine::State::kPrecharge); + testTransition(stm, state_machine::State::kPrecharge, state_machine::State::kPrecharge); + testTransition( + stm, state_machine::State::kReadyForLevitation, state_machine::State::kReadyForLevitation); + testTransition( + stm, state_machine::State::kReadyForLevitation, state_machine::State::kReadyForLevitation); + testTransition( + stm, state_machine::State::kBeginLevitation, state_machine::State::kBeginLevitation); + testTransition( + stm, state_machine::State::kBeginLevitation, state_machine::State::kBeginLevitation); + testTransition(stm, state_machine::State::kReady, state_machine::State::kReady); + testTransition(stm, state_machine::State::kReady, state_machine::State::kReady); + testTransition(stm, state_machine::State::kAccelerate, state_machine::State::kAccelerate); + testTransition(stm, state_machine::State::kAccelerate, state_machine::State::kAccelerate); + testTransition(stm, state_machine::State::kLimBrake, state_machine::State::kLimBrake); + testTransition(stm, state_machine::State::kLimBrake, state_machine::State::kLimBrake); + testTransition(stm, state_machine::State::kFailureBrake, state_machine::State::kFailureBrake); + testTransition(stm, state_machine::State::kFailureBrake, state_machine::State::kFailureBrake); + testTransition( + stm, state_machine::State::kCapacitorDischarge, state_machine::State::kCapacitorDischarge); + testTransition( + stm, state_machine::State::kCapacitorDischarge, state_machine::State::kCapacitorDischarge); + testTransition(stm, state_machine::State::kSafe, state_machine::State::kSafe); + testTransition(stm, state_machine::State::kSafe, state_machine::State::kSafe); +} + +TEST(StateMachine, duplicatedMessageAfterStateChange) +{ + auto stm = std::make_shared(); + testTransition(stm, state_machine::State::kCalibrate, state_machine::State::kCalibrate); + testTransition(stm, state_machine::State::kPrecharge, state_machine::State::kPrecharge); + testTransition(stm, state_machine::State::kCalibrate, state_machine::State::kPrecharge); + testTransition( + stm, state_machine::State::kReadyForLevitation, state_machine::State::kReadyForLevitation); +} } // namespace hyped::test \ No newline at end of file