diff --git a/cxx/CMakeLists.txt b/cxx/CMakeLists.txt index 276899d..1341366 100644 --- a/cxx/CMakeLists.txt +++ b/cxx/CMakeLists.txt @@ -123,13 +123,19 @@ set(CNTR_PROTO_LIB comm_proto) add_library(${CNTR_PROTO_LIB} STATIC ${CNTR_PROTO_LIB_SRC}) -set(MCC_LIBRARY_SRC mcc_mount_concepts.h mcc_mount.h mcc_mount_coord.h mcc_mount_events_states.h mcc_finite_state_machine.h - mcc_mount_pec.h mcc_mount_pz.h mcc_traits.h mcc_mount_telemetry.h mcc_mount_config.h mcc_mount_astro_erfa.h mcc_astrom_iers.h mcc_astrom_iers_default.h mcc_utils.h) +set(MCC_LIBRARY_SRC mcc_mount_concepts.h mcc_fsm_mount.h mcc_mount_coord.h mcc_mount_events_states.h mcc_finite_state_machine.h + mcc_mount_pec.h mcc_mount_pz.h mcc_traits.h mcc_mount_telemetry.h mcc_mount_config.h mcc_mount_astro_erfa.h mcc_astrom_iers.h mcc_astrom_iers_default.h + mcc_utils.h mcc_spdlog.h) set(MCC_LIBRARY mcc) add_library(${MCC_LIBRARY} INTERFACE ${MCC_LIBRARY_SRC}) target_compile_features(${MCC_LIBRARY} INTERFACE cxx_std_23) target_include_directories(${MCC_LIBRARY} INTERFACE ${FITPACK_INCLUDE_DIR}) + +set(ASIBFM700_LIB_SRC asibfm700_hardware.h asibfm700_hardware.cpp) +set(ASIBFM700_LIB asibfm700) +add_library(${ASIBFM700_LIB} STATIC ${ASIBFM700_LIB_SRC}) + # set(MOUNT_SERVER_APP_SRC mount.h mount_state.h mount_server.cpp comm_server.h comm_server_endpoint.h comm_server_configfile.h mount_astrom.h # mount_astrom_default.h mcc_coord.h mount_pz.h mcc_fsm.h mcc_fsm_utils.h mcc_finite_state_machine.h mcc_mount_events_states.h) # set(MOUNT_SERVER_APP mount_server) diff --git a/cxx/asibfm700_hardware.cpp b/cxx/asibfm700_hardware.cpp new file mode 100644 index 0000000..0d1492e --- /dev/null +++ b/cxx/asibfm700_hardware.cpp @@ -0,0 +1,138 @@ +#include "asibfm700_hardware.h" + +using namespace asibfm700; + + +/* error category implementation */ + +const char* AsibFM700HardwareErrorCategory::name() const noexcept +{ + return "ASTROSIB FM700 MOUNT HARDWARE ERROR CATEGORY"; +} + +std::string AsibFM700HardwareErrorCategory::message(int ec) const +{ + AsibFM700HardwareErrorCode code = static_cast(ec); + + std::string msg; + + switch (code) { + case AsibFM700HardwareErrorCode::ERROR_OK: + msg = "OK"; + case asibfm700::AsibFM700HardwareErrorCode::ERROR_FATAL: + msg = "fatal hardware error"; + case AsibFM700HardwareErrorCode::ERROR_BADFORMAT: + msg = "wrong arguments of function"; + case AsibFM700HardwareErrorCode::ERROR_ENCODERDEV: + msg = "encoder device error or can't open"; + case AsibFM700HardwareErrorCode::ERROR_MOUNTDEV: + msg = "mount device error or can't open"; + case AsibFM700HardwareErrorCode::ERROR_FAILED: + msg = "failed to run command - protocol error"; + default: + msg = "UNKNOWN ERROR"; + } + + return msg; +} + +const AsibFM700HardwareErrorCategory& AsibFM700HardwareErrorCategory::get() +{ + static const AsibFM700HardwareErrorCategory constInst; + return constInst; +} + + + +/* AsibFM700Hardware CLASS IMPLEMENTATION */ + + +/* static methods */ + +// void AsibFM700Hardware::moveInst(AsibFM700Hardware* from, AsibFM700Hardware* to) +// { +// to->_hwConfig = std::move(from->_hwConfig); +// to->_deviceConfig = std::move(from->_deviceConfig); + +// from->_deviceConfig.MountDevPath = nullptr; +// from->_deviceConfig.EncoderDevPath = nullptr; +// from->_deviceConfig.EncoderXDevPath = nullptr; +// from->_deviceConfig.EncoderYDevPath = nullptr; +// } + +/* constructors and destructor */ + +AsibFM700Hardware::AsibFM700Hardware(const hardware_config_t& conf) : _hardwareConfig(conf) +{ + _hardwareConfig.devConfig.MountDevPath = const_cast(_hardwareConfig.MountDevPath.c_str()); + _hardwareConfig.devConfig.EncoderDevPath = const_cast(_hardwareConfig.EncoderDevPath.c_str()); + _hardwareConfig.devConfig.EncoderXDevPath = const_cast(_hardwareConfig.EncoderXDevPath.c_str()); + _hardwareConfig.devConfig.EncoderYDevPath = const_cast(_hardwareConfig.EncoderYDevPath.c_str()); +} + +// AsibFM700Hardware::AsibFM700Hardware(AsibFM700Hardware&& other) +// { +// moveInst(&other, this); +// } + +// AsibFM700Hardware& AsibFM700Hardware::operator=(AsibFM700Hardware&& other) +// { +// moveInst(&other, this); + +// return *this; +// } + +AsibFM700Hardware::~AsibFM700Hardware() {} + +std::string_view AsibFM700Hardware::id() const +{ + return "Sidereal Technology Servo II controller"; +} + + + +AsibFM700Hardware::error_t AsibFM700Hardware::setPos(AsibFM700Hardware::axes_pos_t pos) +{ + double X = pos.x, Y = pos.y; + auto err = static_cast(Mount.moveTo(&X, &Y)); + + return err; +} + + + +AsibFM700Hardware::error_t AsibFM700Hardware::getPos(AsibFM700Hardware::axes_pos_t& pos) +{ + mountdata_t data; + auto err = static_cast(Mount.getMountData(&data)); + + if (err == AsibFM700HardwareErrorCode::ERROR_OK) { + // time point from sidservo library is 'struct timeval', i.e., seconds and + // microseconds ellapsed from UNIX time epoch + + using secs_t = std::chrono::duration; + secs_t secs = secs_t{1.0 * data.encposition.msrtime.tv_sec + 1.0E-6 * data.encposition.msrtime.tv_usec}; + + pos.time_point = time_point_t{std::chrono::duration_cast(secs)}; + + pos.x = data.encposition.X; + pos.y = data.encposition.Y; + } + + return err; +} + + +AsibFM700Hardware::error_t AsibFM700Hardware::stop() +{ + auto err = static_cast(Mount.stop()); + + return err; +} + +AsibFM700Hardware::error_t AsibFM700Hardware::init() +{ + auto err = static_cast(Mount.init(&_hardwareConfig.devConfig)); + + return err; +} diff --git a/cxx/asibfm700_hardware.h b/cxx/asibfm700_hardware.h new file mode 100644 index 0000000..2188cb1 --- /dev/null +++ b/cxx/asibfm700_hardware.h @@ -0,0 +1,128 @@ +#pragma once + +/* AstroSIB-FM700 FORK MOUNT CONTROL LIBRARY */ + +/* HARDWARE WRAPPER IMPLEMENTATION */ + +#include "../LibSidServo/sidservo.h" + +#include "mcc_mount_concepts.h" +#include "mcc_mount_coord.h" + + +namespace asibfm700 +{ + +/* error codes enum definition */ + +enum class AsibFM700HardwareErrorCode : int { + // error codes from sidservo library + ERROR_OK = MCC_E_OK, + ERROR_FATAL = MCC_E_FATAL, + ERROR_BADFORMAT = MCC_E_BADFORMAT, + ERROR_ENCODERDEV = MCC_E_ENCODERDEV, + ERROR_MOUNTDEV = MCC_E_MOUNTDEV, + ERROR_FAILED = MCC_E_FAILED, + // my codes ... +}; + +// error category +struct AsibFM700HardwareErrorCategory : public std::error_category { + const char* name() const noexcept; + std::string message(int ec) const; + + static const AsibFM700HardwareErrorCategory& get(); +}; + + +inline std::error_code make_error_code(AsibFM700HardwareErrorCode ec) +{ + return std::error_code(static_cast(ec), AsibFM700HardwareErrorCategory::get()); +} + +} // namespace asibfm700 + + +namespace std +{ + +template <> +class is_error_code_enum : public true_type +{ +}; + +} // namespace std + + + +namespace asibfm700 +{ + +class AsibFM700Hardware final +{ +public: + // definitions from concept + typedef std::error_code error_t; + typedef mcc::MccAngle coord_t; + typedef std::chrono::system_clock::time_point time_point_t; // UTC time + + struct axes_pos_t { + time_point_t time_point; + coord_t x, y; + }; + + // c++ish wrapper to 'conf_t' struct + + struct device_config_t { + std::string MountDevPath; // path to mount device + int MountDevSpeed; // serial speed + std::string EncoderDevPath; // path to encoder device + int EncoderDevSpeed; // serial speed + int SepEncoder; // ==1 if encoder works as separate serial device, ==2 if there's new version with two devices + std::string EncoderXDevPath; // paths to new controller devices + std::string EncoderYDevPath; + double MountReqInterval; // interval between subsequent mount requests (seconds) + double EncoderReqInterval; // interval between subsequent encoder requests (seconds) + }; + + + struct hardware_config_t { + // the 'char*' fields from conf_t: + // wrap it to std::string + std::string MountDevPath; + std::string EncoderDevPath; + std::string EncoderXDevPath; + std::string EncoderYDevPath; + + conf_t devConfig; + hardware_configuration_t hwConfig; + }; + + AsibFM700Hardware(const hardware_config_t& conf); + + ~AsibFM700Hardware(); + + AsibFM700Hardware(const AsibFM700Hardware&) = delete; + AsibFM700Hardware& operator=(const AsibFM700Hardware&) = delete; + + AsibFM700Hardware(AsibFM700Hardware&&) = default; + AsibFM700Hardware& operator=(AsibFM700Hardware&&) = default; + + + std::string_view id() const; + + error_t setPos(axes_pos_t); + error_t getPos(axes_pos_t&); + error_t stop(); + error_t init(); + +private: + hardware_config_t _hardwareConfig; + + // static void moveInst(AsibFM700Hardware* from, AsibFM700Hardware* to); +}; + +static_assert(mcc::traits::mcc_mount_hardware_c, "AsibFM700Hardware!!!"); + + +} // namespace asibfm700 diff --git a/cxx/mcc_finite_state_machine.h b/cxx/mcc_finite_state_machine.h index caa6717..2473076 100644 --- a/cxx/mcc_finite_state_machine.h +++ b/cxx/mcc_finite_state_machine.h @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -318,7 +319,7 @@ protected: std::vector _eventID{}; std::recursive_mutex _transitionMutex{}; - + std::future _currentStateThreadFuture; static MccFiniteStateMachine& copyInstance(const MccFiniteStateMachine* from, MccFiniteStateMachine* to) { @@ -400,7 +401,6 @@ public: if constexpr (requires(curr_state_t inst) { { inst.exit(std::declval()) }; }) { - // std::get(*states).exit(event); std::get(*states).exit(*p_event); } else if constexpr (requires(curr_state_t inst) { { inst.exit() }; @@ -412,7 +412,6 @@ public: if constexpr (requires(EvT inst) { { inst.onTransit() }; }) { - // event.onTransit(); p_event->onTransit(); } @@ -423,7 +422,6 @@ public: if constexpr (requires(to_state_t inst) { { inst.enter(std::declval()) }; }) { - // std::get(*states).enter(event); std::get(*states).enter(*p_event); } else if constexpr (requires(to_state_t inst) { { inst.enter() }; diff --git a/cxx/mcc_mount.h b/cxx/mcc_fsm_mount.h similarity index 73% rename from cxx/mcc_mount.h rename to cxx/mcc_fsm_mount.h index 4194db3..0f7e129 100644 --- a/cxx/mcc_mount.h +++ b/cxx/mcc_fsm_mount.h @@ -1,42 +1,45 @@ #pragma once -/* MOUNT CONTROL COMPONENTS LIBRARY */ +/* MOUNT CONTROL COMPONENTS LIBRARY */ -/* AN GENERIC MOUNT CLASS IMPLEMENTATION */ -// #include + +/* AN GENERIC MOUNT CLASS IMPLEMENTATION BASED ON FINITE STATE MACHINE */ + #include -// #include -// #include #include #include #include "spdlog/sinks/null_sink.h" -#include "mcc_finite_state_machine.h" +#include "mcc_mount_concepts.h" #include "mcc_mount_coord.h" #include "mcc_spdlog.h" #include "mcc_traits.h" -// #include "mount_astrom.h" -// #include "mcc_mount_pz.h" -#include "mcc_mount_concepts.h" + + +#include "mcc_finite_state_machine.h" +#include "mcc_mount_events_states.h" namespace mcc { - -template -class MccMount : public fsm::MccFiniteStateMachine, public utils::MccSpdlogLogger +template +class MccMount : public fsm::MccFiniteStateMachine, public utils::MccSpdlogLogger, protected MOUNT_CONTROLS { + // declare these classes as friends to allow them access protected members 'slewModel' and 'guidingModel' + friend class MccMountStateSlew; + friend class MccMountStateGuiding; + public: - typedef MOUNT_CONFIG mount_config_t; - typedef decltype(mount_config_t::telemetry) mount_telemetry_t; + typedef MOUNT_CONTROLS mount_controls_t; + typedef decltype(mount_controls_t::telemetry) mount_telemetry_t; typedef typename mount_telemetry_t::mount_telemetry_data_t mount_telemetry_data_t; - typedef decltype(mount_config_t::astrometryEngine) astrom_engine_t; - typedef decltype(mount_config_t::PEC) pec_t; - typedef decltype(mount_config_t::hardware) hardware_t; - typedef decltype(mount_config_t::slewModel) slew_model_t; - typedef decltype(mount_config_t::guidingModel) guiding_model_t; + typedef decltype(mount_controls_t::astrometryEngine) astrom_engine_t; + typedef decltype(mount_controls_t::PEC) pec_t; + typedef decltype(mount_controls_t::hardware) hardware_t; + typedef decltype(mount_controls_t::slewModel) slew_model_t; + typedef decltype(mount_controls_t::guidingModel) guiding_model_t; typedef typename slew_model_t::slew_params_t slew_params_t; @@ -44,16 +47,13 @@ public: /* constructors and destructor */ template - MccMount(mount_config_t mount_config, + MccMount(mount_controls_t mount_controls, InitStateT, std::shared_ptr logger = spdlog::null_logger_mt("NULL"), const LogMarkT& logger_mark = "[MOUNT]") : fsm::MccFiniteStateMachine(InitStateT{}), utils::MccSpdlogLogger(logger), - _mountConfig(std::move(mount_config)), - _mountTelemetry(_mountConfig.telemetry), - _slewModel(_mountConfig.slewModel), - _guidingModel(_mountConfig.guidingModel) + mount_controls_t(std::move(mount_controls)) { addMarkToPatternIdx(logger_mark); @@ -87,24 +87,11 @@ public: void startGuiding() {} - // mount_config_t mountConfig() const - // { - // return _mountConfig; - // } - - // returns "mount_config_t&" or "mount_config_t const&" - decltype(auto) mountConfig(this auto&& self) - { - auto& config_ref = std::forward(self)._mountConfig; - - return config_ref; - } - mount_telemetry_data_t mountTelemetryData() const { mount_telemetry_data_t mnt_data; - auto err = _mountTelemetry.data(mnt_data); + auto err = this->telemetry.data(); if (err) { // log .... } @@ -149,11 +136,6 @@ public: protected: - mount_config_t _mountConfig; - mount_telemetry_t& _mountTelemetry; - slew_model_t& _slewModel; - guiding_model_t& _guidingModel; - // a type to which the result of calling prohibited zone class methods 'timeTo' and 'timeFrom' will be converted typedef std::chrono::duration pz_duration_t; // seconds as floating-point number @@ -191,13 +173,14 @@ protected: }; // end of MccMount class -namespace traits -{ -// given mount class must be a descendant of MccMount -template -concept mcc_mount_c = requires(T t) { [](MccMount*) {}(&t); }; +// namespace traits +// { -} // namespace traits +// // given mount class must be a descendant of MccMount +// template +// concept mcc_mount_c = requires(T t) { [](MccMount*) {}(&t); }; + +// } // namespace traits } // namespace mcc diff --git a/cxx/mcc_mount_concepts.h b/cxx/mcc_mount_concepts.h index f5ca3ec..2d43117 100644 --- a/cxx/mcc_mount_concepts.h +++ b/cxx/mcc_mount_concepts.h @@ -4,10 +4,10 @@ #include +#include "mcc_finite_state_machine.h" #include "mcc_mount_coord.h" #include "mcc_traits.h" - /* SOME LIBRARY-WIDE DECLARATIONS */ namespace mcc @@ -63,6 +63,22 @@ namespace mcc::traits { +/* GENERIC LOGGER */ + +template +concept mcc_logger_c = requires(T t, const T t_const) { + typename T::loglevel_t; + { t.setLogLevel(std::declval()) }; + { t_const.getLogLevel() } -> std::same_as; + + { t.logMessage(std::declval(), std::declval()) }; + + { t.logError(std::declval()) }; + { t.logDebug(std::declval()) }; + { t.logWarn(std::declval()) }; + { t.logInfo(std::declval()) }; +}; + /* ASTROMETRY-RELATED COMPUTATION ENGINE */ template @@ -171,6 +187,7 @@ concept mcc_mount_hardware_c = !std::copyable && std::movable && requires( { t.setPos(std::declval()) } -> std::same_as; { t.getPos(std::declval()) } -> std::same_as; { t.stop() } -> std::same_as; + { t.init() } -> std::same_as; }; @@ -235,12 +252,14 @@ concept mcc_mount_telemetry_c = requires(T t, const T t_const) { // // a class that at least contains celestial (equatorial and horizontal) coordinates // requires requires(typename T::mount_telemetry_data_t telemetry) { // typename T::mount_telemetry_data_t::coord_t; - // requires std::same_as; // apparent - // RA requires std::same_as; // - // apparent DEC requires std::same_as; - // // hour angle requires std::same_as; - // // azimuth requires std::same_as; // - // altitude + // requires std::same_as; // + // apparent RA requires std::same_as; // apparent DEC requires std::same_as; + // // hour angle requires std::same_as; + // // azimuth requires std::same_as; // altitude // }; requires mcc_mount_telemetry_data_c; @@ -336,8 +355,8 @@ concept mcc_prohibited_zone_c = // for given coordinates and time the method computes a time to reach the zone. - // implementation of the method must assume that input coordinates are apparent RA and DEC at given time point, - // while the time point is one from which computation should be performed (e.g. current time moment) + // implementation of the method must assume that input coordinates are apparent RA and DEC at given time + // point, while the time point is one from which computation should be performed (e.g. current time moment) { t.timeTo(std::declval(), std::declval(), std::declval()) @@ -369,11 +388,11 @@ concept mcc_prohibited_zone_c = -/* MOUNT GENERIC CONFIGURATION */ +/* MOUNT GENERIC CONTROLS */ template -concept mcc_mount_config_c = std::movable && requires(T t) { +concept mcc_mount_controls_c = std::move_constructible && std::movable && requires(T t) { requires mcc_astrom_engine_c; requires mcc_mount_pec_c; requires mcc_mount_hardware_c; @@ -388,5 +407,37 @@ concept mcc_mount_config_c = std::movable && requires(T t) { }; +/* GENERIC MOUNT CONCEPTS */ + +template +concept mcc_mount_c = requires(T t) { + // the class must define typename 'mount_controls_t' and it must be its base class + requires mcc_mount_controls_c; + requires std::derived_from; + + + // deduced from 'mount_controls_t' typenames + requires mcc_mount_telemetry_c; + requires std::same_as; + requires mcc_astrom_engine_c; + requires mcc_mount_pec_c; + requires mcc_mount_hardware_c; + requires mcc_slew_model_c; + requires mcc_guiding_model_c; + + requires std::same_as; + + // public method + { t.mountTelemetryData() } -> std::same_as; +}; + +// generic with logging methods +template +concept mcc_log_mount_c = mcc_mount_c && mcc_logger_c; + + +// a generic Finite State Machine mount with logging methods +template +concept mcc_fsm_log_mount_c = std::derived_from && mcc_log_mount_c; } // namespace mcc::traits diff --git a/cxx/mcc_mount_coord.h b/cxx/mcc_mount_coord.h index ac22131..6d7e65b 100644 --- a/cxx/mcc_mount_coord.h +++ b/cxx/mcc_mount_coord.h @@ -349,11 +349,18 @@ public: } + // unary '-' and '+' template - SelfT& operator-(this SelfT& self) + SelfT operator-(this SelfT& self) { - self._angleInRads = -self._angleInRads; + SelfT res = -self._angleInRads; + return res; + } + + template + SelfT operator+(this SelfT& self) + { return self; } }; diff --git a/cxx/mcc_mount_events_states.h b/cxx/mcc_mount_events_states.h index b7a0c84..e5ecbf4 100644 --- a/cxx/mcc_mount_events_states.h +++ b/cxx/mcc_mount_events_states.h @@ -3,12 +3,13 @@ /* MOUNT CONTROL COMPONENTS LIBRARY */ /* - * BASIC EVENTS AND MOUNT STATES DEFINITIONS (REFERENCE IMPLEMENTATION) + * BASIC EVENTS AND MOUNT STATES DEFINITIONS (POSSIBLE IMPLEMENTATION) * */ +#include -#include "mcc_mount.h" +#include "mcc_mount_concepts.h" namespace mcc { @@ -19,7 +20,7 @@ namespace mcc // a base class for mount state machine events -template +template class MccMountEventBase { public: @@ -41,7 +42,7 @@ protected: // transit to IDLE state -template +template struct MccMountEventIDLE : public MccMountEventBase { typedef MccMountEventBase base_t; @@ -55,7 +56,7 @@ struct MccMountEventIDLE : public MccMountEventBase { // transit to initialization state -template +template struct MccMountEventInit : public MccMountEventBase { typedef MccMountEventBase base_t; @@ -69,7 +70,7 @@ struct MccMountEventInit : public MccMountEventBase { // transit to error state -template +template struct MccMountEventError : public MccMountEventBase { typedef MccMountEventBase base_t; @@ -91,7 +92,7 @@ protected: // transit to slew state -template +template struct MccMountEventSlew : public MccMountEventBase { typedef MccMountEventBase base_t; @@ -113,7 +114,7 @@ protected: // transit to guiding state -template +template struct MccMountEventGuiding : public MccMountEventBase { typedef MccMountEventBase base_t; @@ -127,7 +128,7 @@ struct MccMountEventGuiding : public MccMountEventBase { // transit to stop state -template +template struct MccMountEventStop : public MccMountEventBase { typedef MccMountEventBase base_t; @@ -159,7 +160,7 @@ protected: // transit to shutdown state -template +template struct MccMountEventShutdown : public MccMountEventBase { typedef MccMountEventBase base_t; @@ -173,7 +174,7 @@ struct MccMountEventShutdown : public MccMountEventBase { /* MOUNT STATE MACHINE STATES */ -template +template struct MccMountStateBase { // template > EvT> // void exit(this auto&& self, EvT& event) @@ -214,45 +215,46 @@ protected: void exitLog(this auto&& self, EvT& event) { using self_t = std::remove_cvref_t; - event.mount().logDebug("Exit from '{}' state due to '{}' event ...", self_t::ID, EvT::ID); + + event.mount().logDebug(std::format("Exit from '{}' state due to '{}' event ...", self_t::ID, EvT::ID)); } template > EvT> void enterLog(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); + event.mount().logDebug(std::format("Enter to '{}' state due to '{}' event ...", self_t::ID, EvT::ID)); } }; // just forward declarations -template +template struct MccMountStateIDLE; -template +template struct MccMountStateInit; -template +template struct MccMountStateError; -template +template struct MccMountStateSlew; -template > +template > struct MccMountStateStop; -template +template struct MccMountStateGuiding; -template +template struct MccMountStateShutdown; // stop state -template +template struct MccMountStateStop : MccMountStateBase { static constexpr std::string_view ID = "MCC-MOUNT-STOP-STATE"; @@ -287,7 +289,7 @@ struct MccMountStateStop : MccMountStateBase { mount.stopMount(); if constexpr (std::same_as>) { - mount.logInfo("Stop reason: {}", event.reason()); + mount.logInfo(std::format("Stop reason: {}", event.reason())); // normal behavior (transit to IDLE state after stopping) mount.template dispatchEvent>({mount}); @@ -300,7 +302,7 @@ struct MccMountStateStop : MccMountStateBase { // initialization state -template +template struct MccMountStateInit : MccMountStateBase { static constexpr std::string_view ID = "MCC-MOUNT-INIT-STATE"; @@ -329,7 +331,7 @@ struct MccMountStateInit : MccMountStateBase { // error state -template +template struct MccMountStateError : MccMountStateBase { static constexpr std::string_view ID = "MCC-MOUNT-ERROR-STATE"; @@ -348,9 +350,9 @@ struct MccMountStateError : MccMountStateBase { { this->exitLog(event); - event.mount().logWarn( + event.mount().logWarn(std::format( "The mount is in the error state!!! One must correct it before transit to any states! Event type is '{}'", - EvT::ID); + EvT::ID)); } void exit(MccMountEventIDLE& event) @@ -372,8 +374,8 @@ struct MccMountStateError : MccMountStateBase { auto err = event.eventData(); - event.mount().logError("The mount is in the error state: code = {}, category = {}, message = '{}'", err.value(), - err.category().name(), err.message()); + event.mount().logError(std::format("The mount is in the error state: code = {}, category = {}, message = '{}'", + err.value(), err.category().name(), err.message())); } // template > EvT> // void enter(EvT& event) @@ -391,7 +393,7 @@ struct MccMountStateError : MccMountStateBase { // IDLE state -template +template struct MccMountStateIDLE : MccMountStateBase { static constexpr std::string_view ID = "MCC-MOUNT-IDLE-STATE"; @@ -419,7 +421,7 @@ struct MccMountStateIDLE : MccMountStateBase { // shutdown state -template +template struct MccMountStateShutdown : MccMountStateBase { static constexpr std::string_view ID = "MCC-MOUNT-SHUTDOWN-STATE"; @@ -445,7 +447,7 @@ struct MccMountStateShutdown : MccMountStateBase { // slew state -template +template struct MccMountStateSlew : MccMountStateBase { static constexpr std::string_view ID = "MCC-MOUNT-SLEW-STATE"; @@ -478,7 +480,7 @@ struct MccMountStateSlew : MccMountStateBase { // guiding state -template +template struct MccMountStateGuiding : MccMountStateBase { static constexpr std::string_view ID = "MCC-MOUNT-GUIDING-STATE"; diff --git a/cxx/mcc_mount_pz.h b/cxx/mcc_mount_pz.h index 5d1dde0..ae8f351 100644 --- a/cxx/mcc_mount_pz.h +++ b/cxx/mcc_mount_pz.h @@ -53,6 +53,7 @@ public: // : "ALTLIMIT-UNKNOWN"), : _altLimit(alt_limit), _latitude(lat), _abs_lat(std::abs(_latitude)), _lat_lim(pi2 - _abs_lat) { + _lat_lim = pi2 - _abs_lat; _altLimit.normalize(); } diff --git a/cxx/mcc_mount_telemetry.h b/cxx/mcc_mount_telemetry.h index 28a6fb6..76cba6b 100644 --- a/cxx/mcc_mount_telemetry.h +++ b/cxx/mcc_mount_telemetry.h @@ -3,7 +3,7 @@ /* MOUNT CONTROL COMPONENTS LIBRARY */ -/* MOUNT TELEMETRY OBJECT POSSIBLE IMPLEMENTATION */ +/* MOUNT TELEMETRY OBJECT POSSIBLE GENERIC IMPLEMENTATION */ #include diff --git a/cxx/mcc_traits.h b/cxx/mcc_traits.h index d675875..183bcf7 100644 --- a/cxx/mcc_traits.h +++ b/cxx/mcc_traits.h @@ -164,8 +164,9 @@ concept mcc_nonconst_lvref = std::is_lvalue_reference_v && !std::is_const_v -concept mcc_error_c = std::convertible_to; -// concept mcc_error_c = std::convertible_to && mcc_formattable; +concept mcc_error_c = std::convertible_to || requires(const T t) { + { t.operator bool() }; +}; namespace details { diff --git a/cxx/mount_astrom.h b/cxx/mount_astrom.h index 7af590a..2657315 100644 --- a/cxx/mount_astrom.h +++ b/cxx/mount_astrom.h @@ -16,8 +16,8 @@ #endif #include "mcc_traits.h" +#include "mcc_utils.h" #include "mount_astrom_default.h" -#include "utils.h" namespace erfa {