#include "WimaStateMachine.h" #include "QGCLoggingCategory.h" #include const QLoggingCategory &WimaPlanerLog(); namespace wima_planer_detail { template constexpr typename std::underlying_type::type integral(T value) { return static_cast::type>(value); } WimaStateMachine::WimaStateMachine(QObject *parent) : QObject(parent), _state(STATE::NEEDS_INIT) {} STATE WimaStateMachine::state() { return this->_state; } void WimaStateMachine::updateState(EVENT e) { qCDebug(WimaPlanerLog) << "StateMachine::updateState(): event:" << e; switch (this->_state) { case STATE::NEEDS_INIT: switch (e) { case EVENT::INIT_DONE: setState(STATE::NEEDS_J_AREA_UPDATE); break; case EVENT::M_AREA_NOT_READY: case EVENT::M_AREA_READY: case EVENT::M_AREA_PATH_CHANGED: case EVENT::S_AREA_PATH_CHANGED: case EVENT::CORRIDOR_PATH_CHANGED: case EVENT::M_AREA_TILES_CHANGED: case EVENT::M_AREA_PROGRESS_CHANGED: case EVENT::J_AREA_UPDATED: case EVENT::DEPOT_CHANGED: case EVENT::SURVEY_DESTROYED: case EVENT::MISSION_ITEMS_DESTROYED: case EVENT::SURVEY_UPDATE_TRIGGERED: case EVENT::SURVEY_UPDATED: case EVENT::PATH_CHANGED: case EVENT::PATH_UPDATED: break; qCCritical(WimaPlanerLog) << "StateMachine::updateState: Unknown event: " << e; Q_ASSERT(false); } break; // STATE::NEEDS_INIT case STATE::WAITING_FOR_TILE_UPDATE: switch (e) { case EVENT::INIT_DONE: case EVENT::M_AREA_NOT_READY: break; case EVENT::M_AREA_READY: setState(STATE::NEEDS_J_AREA_UPDATE); break; case EVENT::M_AREA_PATH_CHANGED: case EVENT::S_AREA_PATH_CHANGED: case EVENT::CORRIDOR_PATH_CHANGED: case EVENT::M_AREA_TILES_CHANGED: case EVENT::M_AREA_PROGRESS_CHANGED: case EVENT::J_AREA_UPDATED: case EVENT::DEPOT_CHANGED: case EVENT::SURVEY_DESTROYED: case EVENT::MISSION_ITEMS_DESTROYED: case EVENT::SURVEY_UPDATE_TRIGGERED: case EVENT::SURVEY_UPDATED: case EVENT::PATH_CHANGED: case EVENT::PATH_UPDATED: break; qCCritical(WimaPlanerLog) << "StateMachine::updateState: Unknown event: " << e; Q_ASSERT(false); } break; // STATE::NEEDS_INIT case STATE::NEEDS_J_AREA_UPDATE: switch (e) { case EVENT::INIT_DONE: break; case EVENT::M_AREA_NOT_READY: setState(STATE::WAITING_FOR_TILE_UPDATE); break; case EVENT::M_AREA_READY: case EVENT::M_AREA_PATH_CHANGED: case EVENT::S_AREA_PATH_CHANGED: case EVENT::CORRIDOR_PATH_CHANGED: case EVENT::M_AREA_TILES_CHANGED: case EVENT::M_AREA_PROGRESS_CHANGED: break; case EVENT::J_AREA_UPDATED: setState(STATE::NEEDS_SURVEY_UPDATE); case EVENT::DEPOT_CHANGED: case EVENT::SURVEY_DESTROYED: case EVENT::MISSION_ITEMS_DESTROYED: case EVENT::SURVEY_UPDATE_TRIGGERED: case EVENT::SURVEY_UPDATED: case EVENT::PATH_CHANGED: case EVENT::PATH_UPDATED: break; qCCritical(WimaPlanerLog) << "StateMachine::updateState: Unknown event: " << e; Q_ASSERT(false); } break; // STATE::NEEDS_J_AREA_UPDATE case STATE::NEEDS_SURVEY_UPDATE: switch (e) { case EVENT::INIT_DONE: case EVENT::M_AREA_NOT_READY: setState(STATE::WAITING_FOR_TILE_UPDATE); break; case EVENT::M_AREA_READY: case EVENT::M_AREA_PATH_CHANGED: case EVENT::S_AREA_PATH_CHANGED: case EVENT::CORRIDOR_PATH_CHANGED: setState(STATE::NEEDS_J_AREA_UPDATE); break; case EVENT::M_AREA_TILES_CHANGED: case EVENT::M_AREA_PROGRESS_CHANGED: case EVENT::J_AREA_UPDATED: case EVENT::DEPOT_CHANGED: case EVENT::SURVEY_DESTROYED: case EVENT::MISSION_ITEMS_DESTROYED: break; case EVENT::SURVEY_UPDATE_TRIGGERED: setState(STATE::WAITING_FOR_SURVEY_UPDATE); break; case EVENT::SURVEY_UPDATED: case EVENT::PATH_CHANGED: case EVENT::PATH_UPDATED: break; qCCritical(WimaPlanerLog) << "StateMachine::updateState: Unknown event: " << e; Q_ASSERT(false); } break; // STATE::NEEDS_SURVEY_UPDATE case STATE::WAITING_FOR_SURVEY_UPDATE: switch (e) { case EVENT::INIT_DONE: case EVENT::M_AREA_NOT_READY: setState(STATE::WAITING_FOR_TILE_UPDATE); break; case EVENT::M_AREA_READY: case EVENT::M_AREA_PATH_CHANGED: case EVENT::S_AREA_PATH_CHANGED: case EVENT::CORRIDOR_PATH_CHANGED: setState(STATE::NEEDS_J_AREA_UPDATE); break; case EVENT::M_AREA_TILES_CHANGED: case EVENT::M_AREA_PROGRESS_CHANGED: case EVENT::J_AREA_UPDATED: case EVENT::DEPOT_CHANGED: case EVENT::SURVEY_DESTROYED: case EVENT::MISSION_ITEMS_DESTROYED: setState(STATE::NEEDS_SURVEY_UPDATE); break; case EVENT::SURVEY_UPDATE_TRIGGERED: break; case EVENT::SURVEY_UPDATED: setState(STATE::NEEDS_PATH_UPDATE); case EVENT::PATH_CHANGED: case EVENT::PATH_UPDATED: break; qCCritical(WimaPlanerLog) << "StateMachine::updateState: Unknown event: " << e; Q_ASSERT(false); } break; // STATE::WAYTING_FOR_SURVEY_UPDATE case STATE::NEEDS_PATH_UPDATE: switch (e) { case EVENT::INIT_DONE: case EVENT::M_AREA_NOT_READY: setState(STATE::WAITING_FOR_TILE_UPDATE); break; case EVENT::M_AREA_READY: case EVENT::M_AREA_PATH_CHANGED: case EVENT::S_AREA_PATH_CHANGED: case EVENT::CORRIDOR_PATH_CHANGED: setState(STATE::NEEDS_J_AREA_UPDATE); break; case EVENT::M_AREA_TILES_CHANGED: case EVENT::M_AREA_PROGRESS_CHANGED: case EVENT::J_AREA_UPDATED: case EVENT::DEPOT_CHANGED: case EVENT::SURVEY_DESTROYED: case EVENT::MISSION_ITEMS_DESTROYED: setState(STATE::NEEDS_SURVEY_UPDATE); break; case EVENT::SURVEY_UPDATE_TRIGGERED: setState(STATE::WAITING_FOR_SURVEY_UPDATE); break; case EVENT::SURVEY_UPDATED: case EVENT::PATH_CHANGED: break; case EVENT::PATH_UPDATED: setState(STATE::UP_TO_DATE); break; qCCritical(WimaPlanerLog) << "StateMachine::updateState: Unknown event: " << e; Q_ASSERT(false); } break; // STATE::NEEDS_PATH_UPDATE case STATE::UP_TO_DATE: switch (e) { case EVENT::INIT_DONE: case EVENT::M_AREA_NOT_READY: setState(STATE::WAITING_FOR_TILE_UPDATE); break; case EVENT::M_AREA_READY: case EVENT::M_AREA_PATH_CHANGED: case EVENT::S_AREA_PATH_CHANGED: case EVENT::CORRIDOR_PATH_CHANGED: setState(STATE::NEEDS_J_AREA_UPDATE); break; case EVENT::M_AREA_TILES_CHANGED: case EVENT::M_AREA_PROGRESS_CHANGED: case EVENT::J_AREA_UPDATED: case EVENT::DEPOT_CHANGED: case EVENT::SURVEY_DESTROYED: case EVENT::MISSION_ITEMS_DESTROYED: setState(STATE::NEEDS_SURVEY_UPDATE); break; case EVENT::SURVEY_UPDATE_TRIGGERED: setState(STATE::WAITING_FOR_SURVEY_UPDATE); break; case EVENT::SURVEY_UPDATED: case EVENT::PATH_CHANGED: setState(STATE::NEEDS_PATH_UPDATE); break; case EVENT::PATH_UPDATED: break; qCCritical(WimaPlanerLog) << "StateMachine::updateState: Unknown event: " << e; Q_ASSERT(false); } break; // STATE::UP_TO_DATE qCCritical(WimaPlanerLog) << "StateMachine::updateState: Unknown state: " << this->_state; Q_ASSERT(false); } } bool WimaStateMachine::upToDate() { return upToDate(this->_state); } bool WimaStateMachine::surveyReady() { return surveyReady(this->_state); } void WimaStateMachine::setState(STATE s) { if (this->_state != s) { auto oldState = this->_state; this->_state = s; emit stateChanged(); if (upToDate(oldState) != upToDate(s)) { emit upToDateChanged(); } if (surveyReady(oldState) != surveyReady(s)) { emit surveyReadyChanged(); } qCDebug(WimaPlanerLog) << "StateMachine::setState():" << oldState << "->" << s; } } bool WimaStateMachine::surveyReady(STATE s) { // Using a switch to enable compiler checking of used states. bool value = false; switch (s) { case STATE::NEEDS_INIT: case STATE::WAITING_FOR_TILE_UPDATE: case STATE::NEEDS_J_AREA_UPDATE: case STATE::NEEDS_SURVEY_UPDATE: case STATE::WAITING_FOR_SURVEY_UPDATE: break; case STATE::NEEDS_PATH_UPDATE: case STATE::UP_TO_DATE: value = true; break; } return value; } bool WimaStateMachine::upToDate(STATE s) { // Using a switch to enable compiler checking of used states. bool value = false; switch (s) { case STATE::NEEDS_INIT: case STATE::WAITING_FOR_TILE_UPDATE: case STATE::NEEDS_J_AREA_UPDATE: case STATE::NEEDS_SURVEY_UPDATE: case STATE::WAITING_FOR_SURVEY_UPDATE: case STATE::NEEDS_PATH_UPDATE: break; case STATE::UP_TO_DATE: value = true; break; } return value; } QDebug &operator<<(QDebug &ds, STATE s) { switch (s) { case STATE::NEEDS_INIT: ds << "NEEDS_INIT"; break; case STATE::WAITING_FOR_TILE_UPDATE: ds << "WAITING_FOR_TILE_UPDATE"; break; case STATE::NEEDS_J_AREA_UPDATE: ds << "NEEDS_J_AREA_UPDATE"; break; case STATE::NEEDS_SURVEY_UPDATE: ds << "NEEDS_SURVEY_UPDATE"; break; case STATE::WAITING_FOR_SURVEY_UPDATE: ds << "WAITING_FOR_SURVEY_UPDATE"; break; case STATE::NEEDS_PATH_UPDATE: ds << "NEEDS_PATH_UPDATE"; break; case STATE::UP_TO_DATE: ds << "UP_TO_DATE"; break; } return ds; } QDebug &operator<<(QDebug &ds, EVENT s) { switch (s) { case EVENT::INIT_DONE: ds << "INIT_DONE"; break; case EVENT::M_AREA_NOT_READY: ds << "M_AREA_NOT_READY"; break; case EVENT::M_AREA_READY: ds << "M_AREA_READY"; break; case EVENT::M_AREA_PATH_CHANGED: ds << "M_AREA_PATH_CHANGED"; break; case EVENT::S_AREA_PATH_CHANGED: ds << "S_AREA_PATH_CHANGED"; break; case EVENT::CORRIDOR_PATH_CHANGED: ds << "CORRIDOR_PATH_CHANGED"; break; case EVENT::M_AREA_TILES_CHANGED: ds << "M_AREA_TILES_CHANGED"; break; case EVENT::M_AREA_PROGRESS_CHANGED: ds << "M_AREA_PROGRESS_CHANGED"; break; case EVENT::J_AREA_UPDATED: ds << "J_AREA_UPDATED"; break; case EVENT::DEPOT_CHANGED: ds << "DEPOT_CHANGED"; break; case EVENT::SURVEY_DESTROYED: ds << "SURVEY_DESTROYED"; break; case EVENT::MISSION_ITEMS_DESTROYED: ds << "MISSION_ITEMS_DESTROYED"; break; case EVENT::SURVEY_UPDATE_TRIGGERED: ds << "SURVEY_UPDATE_TRIGGERED"; break; case EVENT::SURVEY_UPDATED: ds << "SURVEY_UPDATED"; break; case EVENT::PATH_CHANGED: ds << "PATH_CHANGED"; break; case EVENT::PATH_UPDATED: ds << "PATH_UPDATED"; break; } return ds; } } // namespace wima_planer_detail