diff --git a/cxx/CMakeLists.txt b/cxx/CMakeLists.txt index f2642a5..4341ebf 100644 --- a/cxx/CMakeLists.txt +++ b/cxx/CMakeLists.txt @@ -132,11 +132,9 @@ 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_SRC asibfm700_common.h asibfm700_hardware.h asibfm700_hardware.cpp) set(ASIBFM700_LIB asibfm700) -add_library(${ASIBFM700_LIB} STATIC ${ASIBFM700_LIB_SRC} - asibfm700_slew_model.h asibfm700_slew_model.cpp - asibfm700_common.h) +add_library(${ASIBFM700_LIB} STATIC ${ASIBFM700_LIB_SRC}) target_include_directories(${ASIBFM700_LIB} PRIVATE ${FITPACK_INCLUDE_DIR}) # 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 diff --git a/cxx/asibfm700_common.h b/cxx/asibfm700_common.h index 64a4ca6..6490b09 100644 --- a/cxx/asibfm700_common.h +++ b/cxx/asibfm700_common.h @@ -5,11 +5,12 @@ /* COMMON DEFINITIONS */ +#include "asibfm700_hardware.h" +#include "mcc_guiding_model.h" #include "mcc_mount_astro_erfa.h" #include "mcc_mount_pec.h" #include "mcc_mount_telemetry.h" - -#include "asibfm700_hardware.h" +#include "mcc_slew_model.h" namespace asibfm700 { @@ -27,6 +28,21 @@ typedef mcc::MccMountTelemetry AsibFM700SlewModel; +typedef mcc::MccSimpleGuidingModel<> AsibFM700GuidingModel; + + +struct AsibMountControls { + AsibMountControls() : telemetry(astrometryEngine, PEC, hardware) {} + + AsibFM700AstromEngine astrometryEngine; + AsibFM700PointingErrorCorrection PEC; + AsibFM700Hardware hardware; + AsibFM700Telemetry telemetry; + AsibFM700SlewModel slewModel; + AsibFM700GuidingModel guidingModel; +}; + // global mount configuration struct AsibFM700Config { diff --git a/cxx/asibfm700_slew_model.cpp b/cxx/asibfm700_slew_model.cpp deleted file mode 100644 index bd228b4..0000000 --- a/cxx/asibfm700_slew_model.cpp +++ /dev/null @@ -1,110 +0,0 @@ -#include "asibfm700_slew_model.h" - - -namespace asibfm700 -{ - -/* error category implementation */ - -const char* AsibFM700SlewModelErrorCategory::name() const noexcept -{ - return "ASTROSIB FM700 MOUNT SLEW MODEL ERROR CATEGORY"; -} - -std::string AsibFM700SlewModelErrorCategory::message(int ec) const -{ - AsibFM700SlewModelErrorCode code = static_cast(ec); - - std::string msg; - - switch (code) { - case AsibFM700SlewModelErrorCode::ERROR_OK: - msg = "OK"; - default: - msg = "UNKNOWN ERROR"; - } - - return msg; -} - -const AsibFM700SlewModelErrorCategory& AsibFM700SlewModelErrorCategory::get() -{ - static const AsibFM700SlewModelErrorCategory constInst; - return constInst; -} - - -AsibFM700SlewModel::AsibFM700SlewModel(AsibFM700Hardware& hw_control, AsibFM700AstromEngine& astrom_engine) - : _hwControl(hw_control), _astromEngine(astrom_engine) -{ -} - - -AsibFM700SlewModel::error_t AsibFM700SlewModel::slew(const slew_params_t& slew_pars, AsibFM700Telemetry& telemetry) -{ - using astrom_t = std::remove_reference_t; - using coord_t = typename astrom_t::coord_t; - using jd_t = typename astrom_t::juldate_t; - - AsibFM700SlewModel::error_t res_err = AsibFM700SlewModelErrorCode::ERROR_OK; - - AsibFM700Hardware::axes_pos_t ax_pos; - - if (slew_pars.coordPairKind == mcc::MccCoordPairKind::COORDS_KIND_XY) { - // trivial case (the pair is interpretated as raw encoder coordinates) - ax_pos.x = slew_pars.x; - ax_pos.y = slew_pars.y; - } else if (slew_pars.coordPairKind == mcc::MccCoordPairKind::COORDS_KIND_RADEC_ICRS) { // catalog coordinates - jd_t jd; - coord_t ra_app, dec_app, ha, az, alt; - typename astrom_t::eo_t eo; - - auto err = _astromEngine.greg2jul(std::chrono::system_clock::now(), jd); - - if (!err) { - err = _astromEngine.icrs2obs(slew_pars.x, slew_pars.y, jd, ra_app, dec_app, ha, az, alt, eo); - - if (!err) { - res_err = slew({.coordPairKind = mcc::MccCoordPairKind::COORDS_KIND_HADEC_APP, - .x = ha, - .y = dec_app, - .stop = slew_pars.stop}, - telemetry); - } - } - - } else if (slew_pars.coordPairKind == mcc::MccCoordPairKind::COORDS_KIND_RADEC_APP) { // apparent - jd_t jd; - typename astrom_t::eo_t eo; - - auto err = _astromEngine.greg2jul(std::chrono::system_clock::now(), jd); - if (!err) { - typename astrom_t::sideral_time_t lst; - err = _astromEngine.apparentSiderTime(jd, lst, true); - - if (!err) { - err = _astromEngine.eqOrigins(jd, eo); - if (!err) { - res_err = slew({.coordPairKind = mcc::MccCoordPairKind::COORDS_KIND_HADEC_APP, - .x = lst - slew_pars.x + eo, // HA = LST - RA_APP + EO - .y = slew_pars.y, - .stop = slew_pars.stop}, - telemetry); - } - } - } - } else if (slew_pars.coordPairKind == mcc::MccCoordPairKind::COORDS_KIND_HADEC_APP) { // apparent - // compute encoders coordinates - } else if (slew_pars.coordPairKind == mcc::MccCoordPairKind::COORDS_KIND_AZALT) { - } else if (slew_pars.coordPairKind == mcc::MccCoordPairKind::COORDS_KIND_AZZD) { - } - - auto err = _hwControl.setPos(std::move(ax_pos)); - - while (true) { - } - - return res_err; -} - -} // namespace asibfm700 diff --git a/cxx/asibfm700_slew_model.h b/cxx/asibfm700_slew_model.h deleted file mode 100644 index 2f2cb61..0000000 --- a/cxx/asibfm700_slew_model.h +++ /dev/null @@ -1,75 +0,0 @@ -#pragma once - -/* AstroSIB-FM700 FORK MOUNT CONTROL LIBRARY */ - -/* SLEW MODEL IMPLEMENTATION */ - - -#include "asibfm700_common.h" - -namespace asibfm700 -{ - -enum class AsibFM700SlewModelErrorCode : int { ERROR_OK }; - -// error category -struct AsibFM700SlewModelErrorCategory : public std::error_category { - const char* name() const noexcept; - std::string message(int ec) const; - - static const AsibFM700SlewModelErrorCategory& get(); -}; - - -inline std::error_code make_error_code(AsibFM700SlewModelErrorCode ec) -{ - return std::error_code(static_cast(ec), AsibFM700SlewModelErrorCategory::get()); -} - -} // namespace asibfm700 - - - -namespace std -{ - -template <> -class is_error_code_enum : public true_type -{ -}; - -} // namespace std - - - -namespace asibfm700 -{ - -class AsibFM700SlewModel final -{ -public: - typedef std::error_code error_t; - - struct slew_params_t { - typedef mcc::MccAngle coord_t; - - mcc::MccCoordPairKind coordPairKind{mcc::MccCoordPairKind::COORDS_KIND_HADEC_APP}; - - coord_t x{0.0}; - coord_t y{0.0}; - - bool stop{false}; - }; - - AsibFM700SlewModel(AsibFM700Hardware& hw_control, AsibFM700AstromEngine& astrom_engine); - - ~AsibFM700SlewModel(); - - error_t slew(const slew_params_t&, AsibFM700Telemetry&); - -private: - AsibFM700Hardware& _hwControl; - AsibFM700AstromEngine& _astromEngine; -}; - -} // namespace asibfm700 diff --git a/cxx/mcc_guiding_model.h b/cxx/mcc_guiding_model.h index 565c7f3..cfb6b94 100644 --- a/cxx/mcc_guiding_model.h +++ b/cxx/mcc_guiding_model.h @@ -137,13 +137,7 @@ public: typedef std::error_code error_t; - struct guiding_point_t : MccCelestialPoint { - coord_t corrThresh{(double)MccAngle("00:00:00.2"_dms)}; // correction threshold - coord_t correctionRange[2]{(double)MccAngle(0.5_arcsecs), (double)MccAngle(5.0_arcsecs)}; - - // timeout to wait telemetry update (in seconds, as floating-point) - std::chrono::duration telemetryUpdateTimeout{1.0}; - }; + using guiding_point_t = MccSlewAndGuidingPoint; template MccSimpleGuidingModel(MOUNT_CONTROLS_T& mount_controls, LoggerCtorArgTs&&... ctor_args) @@ -248,18 +242,21 @@ protected: while (true) { if (_stopRequested) { - res_err = MccSimpleGuidingModelErrorCode::ERROR_GUIDING_STOPPED; + // return MccSimpleGuidingModelErrorCode::ERROR_GUIDING_STOPPED; + // interpetate stoping as 'no error' exit + return MccSimpleGuidingModelErrorCode::ERROR_OK; } + + // suspend the thread here until telemetry data is updated + t_err = telemetry.waitForUpdatedData(t_data, guiding_point.telemetryUpdateTimeout); + // check prohibited zones ... if (mccCheckInZonePZTuple(t_data, p_mount_controls->prohibitedZones, in_zone_flag)) { return MccSimpleGuidingModelErrorCode::ERROR_IN_PROHIBITED_ZONE; }; - // suspend the thread here until telemetry data is updated - t_err = telemetry.waitForUpdatedData(t_data, guiding_point.telemetryUpdateTimeout); - if (t_err) { std::string err_str = "An error occured while waiting for updated telemetry"; if constexpr (std::same_as) { @@ -276,7 +273,8 @@ protected: } if (_stopRequested) { - res_err = MccSimpleGuidingModelErrorCode::ERROR_GUIDING_STOPPED; + // interpetate stoping as 'no error' exit + return MccSimpleGuidingModelErrorCode::ERROR_OK; } // compare t_data with computed coordinates ... diff --git a/cxx/mcc_mount_events_states.h b/cxx/mcc_mount_events_states.h index e5ecbf4..cde889f 100644 --- a/cxx/mcc_mount_events_states.h +++ b/cxx/mcc_mount_events_states.h @@ -28,10 +28,7 @@ public: virtual ~MccMountEventBase() = default; - mount_t& mount() const - { - return _mount; - } + mount_t& mount() const { return _mount; } protected: MccMountEventBase(mount_t& mount) : _mount(mount) {} @@ -78,10 +75,7 @@ struct MccMountEventError : public MccMountEventBase { using event_data_t = std::error_code; - event_data_t eventData() const - { - return _error; - } + event_data_t eventData() const { return _error; } MccMountEventError(MountT& mount, const event_data_t& error) : base_t(mount), _error(error) {} @@ -98,12 +92,9 @@ struct MccMountEventSlew : public MccMountEventBase { static constexpr std::string_view ID = "MCC-MOUNT-SLEW-EVENT"; - using event_data_t = typename MountT::slew_params_t; + using event_data_t = typename MountT::slew_model_t::slew_point_t; - event_data_t eventData() const - { - return _eventData; - } + event_data_t eventData() const { return _eventData; } MccMountEventSlew(MountT& mount, const event_data_t& ev_data) : base_t(mount), _eventData(ev_data) {} @@ -120,9 +111,14 @@ struct MccMountEventGuiding : public MccMountEventBase { 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) {} + using event_data_t = typename MountT::guiding_model_t::guiding_point_t; + + event_data_t eventData() const { return _eventData; } + + MccMountEventGuiding(MountT& mount, const event_data_t& ev_data) : base_t(mount), _eventData(ev_data) {} + +protected: + event_data_t _eventData; }; @@ -139,10 +135,7 @@ struct MccMountEventStop : public MccMountEventBase { EVENT_STOP_BUTTON // hardware button }; - event_data_t eventData() const - { - return _reason; - } + event_data_t eventData() const { return _reason; } std::string_view reason() const { @@ -286,7 +279,10 @@ struct MccMountStateStop : MccMountStateBase { auto mount = event.mount(); - mount.stopMount(); + // should one check current state (slewing, guiding)? + mount.slewModel.stop(); + mount.guidingModel.stop(); + mount.hardware.stop(); if constexpr (std::same_as>) { mount.logInfo(std::format("Stop reason: {}", event.reason())); @@ -446,7 +442,8 @@ struct MccMountStateShutdown : MccMountStateBase { // slew state - +// WARNING: It must be a friend to 'MountT' class if it inherits it base class mount_controls_t +// as protected or private!!! template struct MccMountStateSlew : MccMountStateBase { static constexpr std::string_view ID = "MCC-MOUNT-SLEW-STATE"; @@ -472,7 +469,18 @@ struct MccMountStateSlew : MccMountStateBase { { this->enterLog(event); - event.mount().slewMount(event.eventData()); + auto slew_err = event.mount().slewModel.slew(event.eventData()); + if (slew_err) { + if constexpr (std::same_as) { + event.mount().dispatchEvent(MccMountEventError{event.mount(), slew_err}); + } else { + // ... + } + return; + } + + // switch to IDLE state + event.mount().template dispatchEvent>({event.mount()}); } }; @@ -505,7 +513,17 @@ struct MccMountStateGuiding : MccMountStateBase { { this->enterLog(event); - event.mount().startGuiding(); + auto err = event.mount().guidingModel.guiding(event.eventData()); + if (err) { + if constexpr (std::same_as) { + event.mount().dispatchEvent(MccMountEventError{event.mount(), err}); + } else { + // ... + } + } + + // switch to IDLE state + event.mount().template dispatchEvent>({event.mount()}); } }; diff --git a/cxx/mcc_mount_telemetry.h b/cxx/mcc_mount_telemetry.h index c072b6c..5446117 100644 --- a/cxx/mcc_mount_telemetry.h +++ b/cxx/mcc_mount_telemetry.h @@ -5,7 +5,6 @@ /* MOUNT TELEMETRY OBJECT POSSIBLE GENERIC IMPLEMENTATION */ -#include #include #include "mcc_mount_telemetry_astrom.h" diff --git a/cxx/mcc_slew_guiding_model_common.h b/cxx/mcc_slew_guiding_model_common.h index d2a934d..484b1d1 100644 --- a/cxx/mcc_slew_guiding_model_common.h +++ b/cxx/mcc_slew_guiding_model_common.h @@ -25,6 +25,55 @@ static_assert(traits::mcc_celestial_point_c, "MccCelestialPoi +/* COMMON SLEW-AND-GUIDING POINT CLASS DEFINITION */ + +struct MccSlewAndGuidingPoint : MccCelestialPoint { + // ******* default constants ******* + + static constexpr size_t defaultWithinToleranceCycleNumber = 10; + static constexpr size_t defaultMaxAdjustingCycleNumber = 100; + + // common parameters + + // timeout to wait telemetry update (in seconds, as floating-point) + std::chrono::duration telemetryUpdateTimeout{1.0}; + + + // ******* slewing-related parameters ******* + + // target-mount coordinate difference to start adjusting of slewing (in radians) + coord_t adjustCoordDiff{(double)MccAngle{10.0_degs}}; + + // coordinates difference to stop slewing (in radians) + coord_t slewToleranceRadius{(double)MccAngle{5.0_arcsecs}}; + + // slew process timeout + std::chrono::seconds slewTimeout{3600}; + + std::chrono::duration telemetryPollingInterval{0.1}; + + // if true - stop mount after the slewing + bool stopAfterSlew{false}; + + coord_t slewXRate{0.0}; // maximal slewing rate (0 means move with maximal allowed rate) + coord_t slewYRate{0.0}; // maximal slewing rate (0 means move with maximal allowed rate) + + coord_t adjustXRate{(double)MccAngle{5.0_arcmins}}; // maximal adjusting rate (a rate at the final slewing stage) + coord_t adjustYRate{(double)MccAngle{5.0_arcmins}}; // maximal adjusting rate (a rate at the final slewing stage) + + // number of consecutive measurements within slewToleranceRadius radius to stop adjusting of slewing + size_t withinToleranceCycleNumber{defaultWithinToleranceCycleNumber}; + + // maximal allowed number of adjusting cycles + size_t maxAdjustingCycleNumber{defaultMaxAdjustingCycleNumber}; + + + // ******* guiding-related parameters ******* + + coord_t correctionRange[2]{(double)MccAngle(0.3_arcsecs), (double)MccAngle(5.0_arcsecs)}; +}; + + /* CHECK FOR CURRENT MOUNT POSITION IN PROHIBITED ZONES */ template ... ZTs> diff --git a/cxx/mcc_slew_model.h b/cxx/mcc_slew_model.h index 9064b40..2093673 100644 --- a/cxx/mcc_slew_model.h +++ b/cxx/mcc_slew_model.h @@ -121,35 +121,7 @@ public: static constexpr size_t defaultAdjustSuccessCycles = 5; - struct slew_point_t : MccCelestialPoint { - // target-mount coordinate difference to start adjusting of slewing (in radians) - coord_t adjustCoordDiff{(double)MccAngle{10.0_degs}}; - - // coordinates difference to stop slewing (in radians) - coord_t slewToleranceRadius{(double)MccAngle{5.0_arcsecs}}; - - // slew process timeout - std::chrono::seconds slewTimeout{3600}; - - std::chrono::duration telemetryPollingInterval{0.1}; - - // if true - stop mount after the slewing - bool stopAfterSlew{false}; - - coord_t slewXRate{0.0}; // maximal slewing rate (0 means move with maximal allowed rate) - coord_t slewYRate{0.0}; // maximal slewing rate (0 means move with maximal allowed rate) - - coord_t adjustXRate{ - (double)MccAngle{5.0_arcmins}}; // maximal adjusting rate (a rate at the final slewing stage) - coord_t adjustYRate{ - (double)MccAngle{5.0_arcmins}}; // maximal adjusting rate (a rate at the final slewing stage) - - // number of consecutive measurements within slewToleranceRadius radius to stop adjusting of slewing - size_t withinToleranceCycleNumber{10}; - - // maximal allowed number of adjusting cycles - size_t maxAdjustingCycleNumber{100}; - }; + using slew_point_t = MccSlewAndGuidingPoint; template @@ -233,8 +205,8 @@ protected: coord_t ra_icrs, dec_icrs; - if (slew_point.adjustSuccessCycles == 0) { - slew_point.adjustSuccessCycles = 5; + if (slew_point.withinToleranceCycleNumber == 0) { + slew_point.withinToleranceCycleNumber = MccSlewAndGuidingPoint::defaultWithinToleranceCycleNumber; } // first, compute encoder coordinates @@ -392,16 +364,11 @@ protected: auto start_poll_tm = std::chrono::steady_clock::now(); - // auto timeout_point = std::chrono::steady_clock::now() + slew_point.slewTimeout; - auto wait_timeout = slew_point.slewTimeout / 5; - if (wait_timeout < std::chrono::seconds(1)) { - wait_timeout = std::chrono::seconds(1); - } // NOTE: TARGET COORDINATES WILL BE UPDATED FOR CURRENT TIME-POINT IN TELEMETRY-CLASS!!! while (true) { - t_err = telemetry.waitForUpdatedData(t_data, wait_timeout); + t_err = telemetry.waitForUpdatedData(t_data, slew_point.telemetryUpdateTimeout); if (t_err) { std::string err_str = "An error occured while waiting for updated telemetry";