511 lines
15 KiB
C++
511 lines
15 KiB
C++
#pragma once
|
|
|
|
/* MOUNT CONTROL COMPONENTS LIBRARY */
|
|
|
|
/*
|
|
* BASIC EVENTS AND MOUNT STATES DEFINITIONS (REFERENCE IMPLEMENTATION)
|
|
*
|
|
*/
|
|
|
|
|
|
#include "mcc_mount.h"
|
|
|
|
namespace mcc
|
|
{
|
|
|
|
|
|
/* MOUNT STATE MACHINE STATES */
|
|
|
|
|
|
// a base class for mount state machine events
|
|
|
|
template <traits::mcc_mount_c MountT>
|
|
class MccMountEventBase
|
|
{
|
|
public:
|
|
typedef MountT mount_t;
|
|
|
|
virtual ~MccMountEventBase() = default;
|
|
|
|
mount_t& mount() const
|
|
{
|
|
return _mount;
|
|
}
|
|
|
|
protected:
|
|
MccMountEventBase(mount_t& mount) : _mount(mount) {}
|
|
|
|
mount_t& _mount;
|
|
};
|
|
|
|
|
|
// transit to IDLE state
|
|
|
|
template <traits::mcc_mount_c MountT>
|
|
struct MccMountEventIDLE : public MccMountEventBase<MountT> {
|
|
typedef MccMountEventBase<MountT> 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 <traits::mcc_mount_c MountT>
|
|
struct MccMountEventInit : public MccMountEventBase<MountT> {
|
|
typedef MccMountEventBase<MountT> base_t;
|
|
|
|
static constexpr std::string_view ID = "MCC-MOUNT-INIT-EVENT";
|
|
|
|
// 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) {}
|
|
};
|
|
|
|
|
|
// transit to error state
|
|
|
|
template <traits::mcc_mount_c MountT>
|
|
struct MccMountEventError : public MccMountEventBase<MountT> {
|
|
typedef MccMountEventBase<MountT> 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 <traits::mcc_mount_c MountT>
|
|
struct MccMountEventSlew : public MccMountEventBase<MountT> {
|
|
typedef MccMountEventBase<MountT> base_t;
|
|
|
|
static constexpr std::string_view ID = "MCC-MOUNT-SLEW-EVENT";
|
|
|
|
using event_data_t = typename MountT::slew_param_t;
|
|
|
|
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 <traits::mcc_mount_c MountT>
|
|
struct MccMountEventGuiding : public MccMountEventBase<MountT> {
|
|
typedef MccMountEventBase<MountT> 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 <traits::mcc_mount_c MountT>
|
|
struct MccMountEventStop : public MccMountEventBase<MountT> {
|
|
typedef MccMountEventBase<MountT> 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;
|
|
}
|
|
|
|
std::string_view reason() const
|
|
{
|
|
return _reason == EVENT_STOP_BUTTON ? "Hardware stop-button"
|
|
: _reason == EVENT_STOP_CLIENT ? "Stop from client"
|
|
: "UNKNOWN";
|
|
}
|
|
|
|
MccMountEventStop(MountT& mount, event_data_t reason) : base_t(mount), _reason(reason) {}
|
|
|
|
protected:
|
|
event_data_t _reason;
|
|
};
|
|
|
|
|
|
// transit to shutdown state
|
|
|
|
template <traits::mcc_mount_c MountT>
|
|
struct MccMountEventShutdown : public MccMountEventBase<MountT> {
|
|
typedef MccMountEventBase<MountT> 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 <traits::mcc_mount_c MountT>
|
|
struct MccMountStateBase {
|
|
// template <std::derived_from<MccMountEventBase<MountT>> EvT>
|
|
// void exit(this auto&& self, EvT& event)
|
|
// {
|
|
// using self_t = std::remove_cvref_t<decltype(self)>;
|
|
|
|
// std::forward<decltype(self)>(self).exitImpl(event);
|
|
|
|
// event.mount().logDebug("Exit from '{}' state due to '{}' event ...", self_t::ID, EvT::ID);
|
|
// }
|
|
|
|
// template <std::derived_from<MccMountEventBase<MountT>> EvT>
|
|
// void enter(this auto&& self, EvT& event)
|
|
// {
|
|
// using self_t = std::remove_cvref_t<decltype(self)>;
|
|
|
|
// event.mount().logDebug("Enter to '{}' state due to '{}' event ...", self_t::ID, EvT::ID);
|
|
|
|
// std::forward<decltype(self)>(self).enterImpl(event);
|
|
// }
|
|
|
|
protected:
|
|
// template <std::derived_from<MccMountEventBase<MountT>> EvT>
|
|
// void exitImpl(EvT& event)
|
|
// {
|
|
// event.mount().logWarn("Call an empty MccMountStateBase::exitImpl method!!! Event type is '{}'", EvT::ID);
|
|
// }
|
|
|
|
// template <std::derived_from<MccMountEventBase<MountT>> EvT>
|
|
// void enterImpl(EvT& event)
|
|
// {
|
|
// event.mount().logWarn("Call an empty MccMountStateBase::enterImpl method!!! Event type is '{}'", EvT::ID);
|
|
// }
|
|
|
|
// MccMountStateBase() = default;
|
|
|
|
template <std::derived_from<MccMountEventBase<MountT>> EvT>
|
|
void exitLog(this auto&& self, EvT& event)
|
|
{
|
|
using self_t = std::remove_cvref_t<decltype(self)>;
|
|
event.mount().logDebug("Exit from '{}' state due to '{}' event ...", self_t::ID, EvT::ID);
|
|
}
|
|
|
|
template <std::derived_from<MccMountEventBase<MountT>> EvT>
|
|
void enterLog(this auto&& self, EvT& event)
|
|
{
|
|
using self_t = std::remove_cvref_t<decltype(self)>;
|
|
event.mount().logDebug("Enter to '{}' state due to '{}' event ...", self_t::ID, EvT::ID);
|
|
}
|
|
};
|
|
|
|
|
|
|
|
// just forward declarations
|
|
template <traits::mcc_mount_c MountT>
|
|
struct MccMountStateIDLE;
|
|
|
|
template <traits::mcc_mount_c MountT>
|
|
struct MccMountStateInit;
|
|
|
|
template <traits::mcc_mount_c MountT>
|
|
struct MccMountStateError;
|
|
|
|
template <traits::mcc_mount_c MountT>
|
|
struct MccMountStateSlew;
|
|
|
|
template <traits::mcc_mount_c MountT, fsm::traits::fsm_event_c TrEvT = MccMountEventStop<MountT>>
|
|
struct MccMountStateStop;
|
|
|
|
template <traits::mcc_mount_c MountT>
|
|
struct MccMountStateGuiding;
|
|
|
|
template <traits::mcc_mount_c MountT>
|
|
struct MccMountStateShutdown;
|
|
|
|
|
|
// stop state
|
|
|
|
template <traits::mcc_mount_c MountT, fsm::traits::fsm_event_c TrEvT>
|
|
struct MccMountStateStop : MccMountStateBase<MountT> {
|
|
static constexpr std::string_view ID = "MCC-MOUNT-STOP-STATE";
|
|
|
|
using transition_t = fsm::fsm_transition_table_t<std::pair<MccMountEventIDLE<MountT>, MccMountStateIDLE<MountT>>>;
|
|
|
|
// protected:
|
|
void exit(MccMountEventIDLE<MountT>& event)
|
|
{
|
|
// normal exit from the state
|
|
this->exitLog(event);
|
|
}
|
|
|
|
// normal behavior (transit to IDLE state after stopping)
|
|
// void enter(MccMountEventStop<MountT>& event)
|
|
// {
|
|
// this->enterLog(event);
|
|
|
|
// auto mount = event.mount();
|
|
// mount.stopMount();
|
|
|
|
// // switch to IDLE state
|
|
// mount.template dispatchEvent<MccMountEventIDLE<MountT>>({mount});
|
|
// }
|
|
|
|
template <std::derived_from<MccMountEventBase<MountT>> EvT>
|
|
void enter(EvT& event)
|
|
{
|
|
this->enterLog(event);
|
|
|
|
auto mount = event.mount();
|
|
|
|
mount.stopMount();
|
|
|
|
if constexpr (std::same_as<EvT, MccMountEventStop<MountT>>) {
|
|
mount.logInfo("Stop reason: {}", event.reason());
|
|
|
|
// normal behavior (transit to IDLE state after stopping)
|
|
mount.template dispatchEvent<MccMountEventIDLE<MountT>>({mount});
|
|
} else {
|
|
mount.logInfo("Stop reason: special state");
|
|
mount.dispatchEvent(event);
|
|
}
|
|
}
|
|
};
|
|
|
|
// initialization state
|
|
|
|
template <traits::mcc_mount_c MountT>
|
|
struct MccMountStateInit : MccMountStateBase<MountT> {
|
|
static constexpr std::string_view ID = "MCC-MOUNT-INIT-STATE";
|
|
|
|
using transition_t = fsm::fsm_transition_table_t<std::pair<MccMountEventIDLE<MountT>, MccMountStateIDLE<MountT>>>;
|
|
|
|
// protected:
|
|
void exit(MccMountEventIDLE<MountT>& event)
|
|
{
|
|
// normal exit from the state
|
|
this->exitLog(event);
|
|
}
|
|
|
|
template <std::derived_from<MccMountEventBase<MountT>> EvT>
|
|
void enter(EvT& event)
|
|
{
|
|
this->enterLog(event);
|
|
|
|
MountT& mount = event.mount();
|
|
mount.initMount();
|
|
|
|
// switch to IDLE state
|
|
mount.template dispatchEvent<MccMountEventIDLE<MountT>>({mount});
|
|
}
|
|
};
|
|
|
|
|
|
// error state
|
|
|
|
template <traits::mcc_mount_c MountT>
|
|
struct MccMountStateError : MccMountStateBase<MountT> {
|
|
static constexpr std::string_view ID = "MCC-MOUNT-ERROR-STATE";
|
|
|
|
using transition_t = fsm::fsm_transition_table_t<
|
|
std::pair<MccMountEventIDLE<MountT>, MccMountStateIDLE<MountT>>, // ???? after error correction?
|
|
std::pair<MccMountEventInit<MountT>, MccMountStateInit<MountT>>,
|
|
std::pair<MccMountEventError<MountT>, MccMountStateError<MountT>>,
|
|
std::pair<MccMountEventSlew<MountT>, MccMountStateError<MountT>>,
|
|
std::pair<MccMountEventGuiding<MountT>, MccMountStateError<MountT>>,
|
|
std::pair<MccMountEventStop<MountT>, MccMountStateError<MountT>>,
|
|
std::pair<MccMountEventShutdown<MountT>, MccMountStateShutdown<MountT>>>;
|
|
|
|
// protected:
|
|
template <std::derived_from<MccMountEventBase<MountT>> EvT>
|
|
void exit(EvT& event)
|
|
{
|
|
this->exitLog(event);
|
|
|
|
event.mount().logWarn(
|
|
"The mount is in the error state!!! One must correct it before transit to any states! Event type is '{}'",
|
|
EvT::ID);
|
|
}
|
|
|
|
void exit(MccMountEventIDLE<MountT>& event)
|
|
{
|
|
this->exitLog(event);
|
|
|
|
event.mount().logWarn("Suppose the error was corrected!");
|
|
}
|
|
|
|
void exit(MccMountEventInit<MountT>& event)
|
|
{
|
|
// normal exit from the state
|
|
this->exitLog(event);
|
|
}
|
|
|
|
void enter(MccMountEventError<MountT>& event)
|
|
{
|
|
this->enterLog(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 <std::derived_from<MccMountEventBase<MountT>> EvT>
|
|
// void enter(EvT& event)
|
|
// {
|
|
// this->enterLog(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());
|
|
// }
|
|
};
|
|
|
|
|
|
// IDLE state
|
|
|
|
template <traits::mcc_mount_c MountT>
|
|
struct MccMountStateIDLE : MccMountStateBase<MountT> {
|
|
static constexpr std::string_view ID = "MCC-MOUNT-IDLE-STATE";
|
|
|
|
using transition_t =
|
|
fsm::fsm_transition_table_t<std::pair<MccMountEventInit<MountT>, MccMountStateInit<MountT>>,
|
|
std::pair<MccMountEventError<MountT>, MccMountStateError<MountT>>,
|
|
std::pair<MccMountEventSlew<MountT>, MccMountStateSlew<MountT>>,
|
|
std::pair<MccMountEventGuiding<MountT>, MccMountStateGuiding<MountT>>,
|
|
std::pair<MccMountEventStop<MountT>, MccMountStateIDLE<MountT>>,
|
|
std::pair<MccMountEventShutdown<MountT>, MccMountStateShutdown<MountT>>>;
|
|
|
|
template <std::derived_from<MccMountEventBase<MountT>> EvT>
|
|
void exit(EvT& event)
|
|
{
|
|
this->exitLog(event);
|
|
}
|
|
|
|
template <std::derived_from<MccMountEventBase<MountT>> EvT>
|
|
void enter(EvT& event)
|
|
{
|
|
this->enterLog(event);
|
|
}
|
|
};
|
|
|
|
|
|
// shutdown state
|
|
|
|
template <traits::mcc_mount_c MountT>
|
|
struct MccMountStateShutdown : MccMountStateBase<MountT> {
|
|
static constexpr std::string_view ID = "MCC-MOUNT-SHUTDOWN-STATE";
|
|
|
|
// only initialization
|
|
using transition_t = fsm::fsm_transition_table_t<std::pair<MccMountEventInit<MountT>, MccMountStateInit<MountT>>>;
|
|
|
|
// protected:
|
|
void exit(MccMountEventInit<MountT>& event)
|
|
{
|
|
// normal exit from the state
|
|
this->exitLog(event);
|
|
}
|
|
|
|
template <std::derived_from<MccMountEventBase<MountT>> EvT>
|
|
void enter(EvT& event)
|
|
{
|
|
this->enterLog(event);
|
|
|
|
event.mount().shutdownMount();
|
|
}
|
|
};
|
|
|
|
|
|
// slew state
|
|
|
|
template <traits::mcc_mount_c MountT>
|
|
struct MccMountStateSlew : MccMountStateBase<MountT> {
|
|
static constexpr std::string_view ID = "MCC-MOUNT-SLEW-STATE";
|
|
|
|
// only initialization
|
|
using transition_t =
|
|
fsm::fsm_transition_table_t<std::pair<MccMountEventInit<MountT>, MccMountStateInit<MountT>>,
|
|
std::pair<MccMountEventError<MountT>, MccMountStateStop<MountT>>,
|
|
// std::pair<MccMountEventSlew<MountT>, MccMountStateSlew<MountT>>,
|
|
std::pair<MccMountEventGuiding<MountT>, MccMountStateStop<MountT>>,
|
|
std::pair<MccMountEventStop<MountT>, MccMountStateStop<MountT>>,
|
|
std::pair<MccMountEventShutdown<MountT>, MccMountStateStop<MountT>>>;
|
|
|
|
// protected:
|
|
template <std::derived_from<MccMountEventBase<MountT>> EvT>
|
|
void exit(EvT& event)
|
|
{
|
|
this->exitLog(event);
|
|
}
|
|
|
|
template <std::derived_from<MccMountEventSlew<MountT>> EvT>
|
|
void enter(EvT& event)
|
|
{
|
|
this->enterLog(event);
|
|
|
|
event.mount().slewMount(event.eventData());
|
|
}
|
|
};
|
|
|
|
|
|
|
|
// guiding state
|
|
|
|
template <traits::mcc_mount_c MountT>
|
|
struct MccMountStateGuiding : MccMountStateBase<MountT> {
|
|
static constexpr std::string_view ID = "MCC-MOUNT-GUIDING-STATE";
|
|
|
|
// only initialization
|
|
using transition_t =
|
|
fsm::fsm_transition_table_t<std::pair<MccMountEventInit<MountT>, MccMountStateInit<MountT>>,
|
|
std::pair<MccMountEventError<MountT>, MccMountStateStop<MountT>>,
|
|
// std::pair<MccMountEventSlew<MountT>, MccMountStateSlew<MountT>>,
|
|
std::pair<MccMountEventGuiding<MountT>, MccMountStateStop<MountT>>,
|
|
std::pair<MccMountEventStop<MountT>, MccMountStateStop<MountT>>,
|
|
std::pair<MccMountEventShutdown<MountT>, MccMountStateStop<MountT>>>;
|
|
|
|
// protected:
|
|
template <std::derived_from<MccMountEventBase<MountT>> EvT>
|
|
void exit(EvT& event)
|
|
{
|
|
this->exitLog(event);
|
|
}
|
|
|
|
template <std::derived_from<MccMountEventSlew<MountT>> EvT>
|
|
void enter(EvT& event)
|
|
{
|
|
this->enterLog(event);
|
|
|
|
event.mount().startGuiding();
|
|
}
|
|
};
|
|
|
|
} // namespace mcc
|