From 3c4045e6206d8927c07fc0cae5c61ab35cbb0afd Mon Sep 17 00:00:00 2001 From: "Timur A. Fatkhullin" Date: Tue, 10 Jun 2025 18:19:11 +0300 Subject: [PATCH] ... --- cxx/mcc_mount_events_states.h | 333 +++++++++++++++++++++++++++++++++- cxx/mount.h | 31 +++- 2 files changed, 348 insertions(+), 16 deletions(-) diff --git a/cxx/mcc_mount_events_states.h b/cxx/mcc_mount_events_states.h index ddab3a6..60f7375 100644 --- a/cxx/mcc_mount_events_states.h +++ b/cxx/mcc_mount_events_states.h @@ -3,7 +3,8 @@ /* MOUNT CONTROL COMPONENTS LIBRARY */ /* - * BASIC EVENTS AND MOUNT STATES DEFINITIONS + * BASIC EVENTS AND MOUNT STATES DEFINITIONS (REFERENCE IMPLEMENTATION) + * */ @@ -12,18 +13,332 @@ namespace mcc { -template CONFIG_TYPE, - std::derived_from> MountT> -struct MccMountInitEvent { +namespace traits +{ + +template +concept mcc_mount_c = requires { + requires std::same_as; + + typename T::mount_config_t; + + requires std::derived_from>; +}; + +} // namespace traits + + + +/* MOUNT STATE MACHINE STATES */ + + +// a base class for mount state machine events + +template +class MccMountEventBase +{ +protected: + typedef MountT mount_t; + + MccMountEventBase(mount_t& mount) : _mount(mount) {} + + virtual ~MccMountEventBase() = default; + + mount_t& mount() const + { + return _mount; + } + + mount_t& _mount; +}; + + +// transit to IDLE state + +template +struct MccMountEventIDLE : public MccMountEventBase { + typedef MccMountEventBase base_t; + + static constexpr std::string_view ID = "MCC-MOUNT-IDLE-EVENT"; + + // CTAD does not work for clang++ (at least till v. 20 and -std=c++23)! + // so, one must explicitly define constructor here + MccMountEventIDLE(MountT& mount) : base_t(mount) {} +}; + + +// transit to initialization state + +template +struct MccMountEventInit : public MccMountEventBase { + typedef MccMountEventBase base_t; + static constexpr std::string_view ID = "MCC-MOUNT-INIT-EVENT"; - MccMountInitEvent(MountT& mount) : _mount(mount) {} + // CTAD does not work for clang++ (at least till v. 20 and -std=c++23)! + // so, one must explicitly define constructor here + MccMountEventInit(MountT& mount) : base_t(mount) {} +}; - MountT mount() const { return _mount; } -private: - MountT& _mount; +// transit to error state + +template +struct MccMountEventError : public MccMountEventBase { + typedef MccMountEventBase base_t; + + static constexpr std::string_view ID = "MCC-MOUNT-ERROR-EVENT"; + + using event_data_t = std::error_code; + + event_data_t eventData() const + { + return _error; + } + + MccMountEventError(MountT& mount, const event_data_t& error) : base_t(mount), _error(error) {} + +protected: + event_data_t _error; +}; + + +// transit to slew state + +template +struct MccMountEventSlew : public MccMountEventBase { + typedef MccMountEventBase base_t; + + static constexpr std::string_view ID = "MCC-MOUNT-SLEW-EVENT"; + + struct event_data_t { + MccCoordPairKind kind{MccCoordPairKind::COORDS_KIND_RADEC_IRCS}; + MccAngle x{0.0}, y{0.0}; + + bool stop{false}; // stop after slewing: if false - start guiding + }; + + event_data_t eventData() const + { + return _eventData; + } + + MccMountEventSlew(MountT& mount, const event_data_t& ev_data) : base_t(mount), _eventData(ev_data) {} + +protected: + event_data_t _eventData; +}; + + +// transit to guiding state + +template +struct MccMountEventGuiding : public MccMountEventBase { + typedef MccMountEventBase base_t; + + static constexpr std::string_view ID = "MCC-MOUNT-GUIDING-EVENT"; + + // CTAD does not work for clang++ (at least till v. 20 and -std=c++23)! + // so, one must explicitly define constructor here + MccMountEventGuiding(MountT& mount) : base_t(mount) {} +}; + + +// transit to stop state + +template +struct MccMountEventStop : public MccMountEventBase { + typedef MccMountEventBase base_t; + + static constexpr std::string_view ID = "MCC-MOUNT-STOP-EVENT"; + + enum event_data_t { + EVENT_STOP_CLIENT, // software stop (mount client) + EVENT_STOP_BUTTON // hardware button + }; + + event_data_t eventData() const + { + return _reason; + } + + MccMountEventStop(MountT& mount, event_data_t reason) : base_t(mount), _reason(reason) {} + +protected: + event_data_t _reason; +}; + + +// transit to shutdown state + +template +struct MccMountEventShutdown : public MccMountEventBase { + typedef MccMountEventBase base_t; + + static constexpr std::string_view ID = "MCC-MOUNT-SHUTDOWN-EVENT"; + + // CTAD does not work for clang++ (at least till v. 20 and -std=c++23)! + // so, one must explicitly define constructor here + MccMountEventShutdown(MountT& mount) : base_t(mount) {} +}; + + +/* MOUNT STATE MACHINE STATES */ + +template +struct MccMountStateBase { + template > EvT> + void exit(this auto&& self, EvT& event) + { + using self_t = std::remove_cvref_t; + + std::forward(self).exitImpl(event); + + event.mount().logDebug("Exit from '{}' state due to '{}' event ...", self_t::ID, EvT::ID); + } + + template > EvT> + void enter(this auto&& self, EvT& event) + { + using self_t = std::remove_cvref_t; + + event.mount().logDebug("Enter to '{}' state due to '{}' event ...", self_t::ID, EvT::ID); + + std::forward(self).enterImpl(event); + } + +protected: + template > EvT> + void exitImpl(EvT& event) + { + event.mount().logWarning("Call an empty MccMountStateBase::exitImpl method!!! Event type is '{}'", EvT::ID); + } + + template > EvT> + void enterImpl(EvT& event) + { + event.mount().logWarning("Call an empty MccMountStateBase::enterImpl method!!! Event type is '{}'", EvT::ID); + } +}; + + + +// just forward declarations +template +struct MccMountStateIDLE; + +template +struct MccMountStateInit; + +template +struct MccMountStateError; + +template +struct MccMountStateSlew; + +template +struct MccMountStateStop; + +template +struct MccMountStateGuiding; + +template +struct MccMountStateShutdown; + + +// initialization state + +template +struct MccMountStateInit : MccMountStateBase { + static constexpr std::string_view ID = "MCC-MOUNT-INIT-STATE"; + + using transition_t = fsm::fsm_transition_table_t, MccMountStateIDLE>>; + +protected: + void exitImpl(MccMountEventIDLE& event) + { + // normal exit from the state + } + + template > EvT> + void enterImpl(EvT& event) + { + event.mount().initMount(); + + // switch to IDLE state + event.mount().template dispatchEvent>(); + } +}; + + +template +struct MccMountStateError : MccMountStateBase { + static constexpr std::string_view ID = "MCC-MOUNT-ERROR-STATE"; + + using transition_t = fsm::fsm_transition_table_t< + std::pair, MccMountStateIDLE>, // ???? after error correction? + std::pair, MccMountStateInit>, + std::pair, MccMountStateError>, + std::pair, MccMountStateError>, + std::pair, MccMountStateError>, + std::pair, MccMountStateError>, + std::pair, MccMountStateShutdown>>; + +protected: + template > EvT> + void exitImpl(EvT& event) + { + event.mount().logWarning( + "The mount is in the error state!!! One must correct it before transit to any states! Event type is '{}'", + EvT::ID); + } + + void exitImpl(MccMountEventIDLE& event) + { + event.mount().logWarning("Suppose the error was corrected!"); + } + + void exitImpl(MccMountEventInit& event) + { + // normal exit from the state + } + + template > EvT> + void enterImpl(EvT& event) + { + auto err = event.eventData(); + + event.mount().logError("The mount is in the error state: code = {}, category = {}, message = '{}'", err.value(), + err.category().name(), err.message()); + } +}; + + +template +struct MccMountStateIDLE : MccMountStateBase { + static constexpr std::string_view ID = "MCC-MOUNT-IDLE-STATE"; + + using transition_t = + fsm::fsm_transition_table_t, MccMountStateInit>, + std::pair, MccMountStateError>, + std::pair, MccMountStateSlew>, + std::pair, MccMountStateGuiding>, + std::pair, MccMountStateIDLE>, + std::pair, MccMountStateShutdown>>; +}; + + +template +struct MccMountStateShutdown : MccMountStateBase { + static constexpr std::string_view ID = "MCC-MOUNT-SHUTDOWN-STATE"; + + using transition_t = + fsm::fsm_transition_table_t, MccMountStateInit>, + std::pair, MccMountStateError>, + std::pair, MccMountStateSlew>, + std::pair, MccMountStateGuiding>, + std::pair, MccMountStateIDLE>, + std::pair, MccMountStateShutdown>>; }; } // namespace mcc diff --git a/cxx/mount.h b/cxx/mount.h index 2f000aa..082eda4 100644 --- a/cxx/mount.h +++ b/cxx/mount.h @@ -222,7 +222,6 @@ public: }; - /* Constructors and destructor */ template @@ -244,17 +243,26 @@ public: updateIERSDatabase(IERS_DB_EARTH_ORIENT); } - virtual ~MccMount() { logDebug("Delete MccMount class instance: thread = {}", getThreadId()); } + virtual ~MccMount() + { + logDebug("Delete MccMount class instance: thread = {}", getThreadId()); + } /* Public methods */ - MccMountPosition getMountData() const noexcept { return _currentMountOrient.load(); } + MccMountPosition getMountData() const noexcept + { + return _currentMountOrient.load(); + } // geo location setters/getters - void setGeoLocation(const MccMountSiteInfo& geoloc) { _geoLocation.store(geoloc); } + void setGeoLocation(const MccMountSiteInfo& geoloc) + { + _geoLocation.store(geoloc); + } void setSiteLatitude(const MccAngle& lat) { @@ -282,14 +290,23 @@ public: } - MccMountSiteInfo getGeoLocation() const { return _geoLocation.load(); } + MccMountSiteInfo getGeoLocation() const + { + return _geoLocation.load(); + } // current meteo setters/getters - void setMeteo(const MccMountMeteo& meteo) { _currentMeteo.store(meteo); } + void setMeteo(const MccMountMeteo& meteo) + { + _currentMeteo.store(meteo); + } - MccMountMeteo getMeteo() const { return _currentMeteo.load(); } + MccMountMeteo getMeteo() const + { + return _currentMeteo.load(); + } /* prohibited zone related methods */