From 732cd33947f596eff4ace38596a49100e1a54fe3 Mon Sep 17 00:00:00 2001 From: "Timur A. Fatkhullin" Date: Tue, 16 Sep 2025 18:35:39 +0300 Subject: [PATCH] ... --- asibfm700/asibfm700_mount.cpp | 24 ++ asibfm700/asibfm700_mount.h | 43 ++++ mcc/mcc_generic_mount.h | 121 +++++----- mcc/mcc_generics.h | 11 + mcc/mcc_generics_new.h | 409 ++++++++++++++++++++++++---------- 5 files changed, 433 insertions(+), 175 deletions(-) diff --git a/asibfm700/asibfm700_mount.cpp b/asibfm700/asibfm700_mount.cpp index 92b9f62..8b6abe9 100644 --- a/asibfm700/asibfm700_mount.cpp +++ b/asibfm700/asibfm700_mount.cpp @@ -29,4 +29,28 @@ Asibfm700Mount::~Asibfm700Mount() logDebug("Delete Asibfm700Mount class instance ({})", this->getThreadId()); } + + +Asibfm700Mount1::Asibfm700Mount1(Asibfm700MountConfig const& config, + std::shared_ptr logger, + const auto& pattern_range) + : mcc::ccte::erfa::MccCCTE_ERFA({.meteo{.temperature = 10.0, .humidity = 0.5, .pressure = 1010.0}, + .wavelength = config.refractWavelength, + .lat = config.siteLatitude, + .lon = config.siteLongitude, + .elev = config.siteElevation}), + Asibfm700PCM(config.pcmData), + base_gm_class_t(gm_class_t{AsibFM700ServoController{config.servoControllerConfig}, mcc::MccTelemetry{this}, + Asibfm700PZoneContainer{}, mcc::MccSimpleSlewingModel{this}, + mcc::MccSimpleTrackingModel{this}, Asibfm700Logger{std::move(logger), pattern_range}}, + Asibfm700StartState{}) +{ + logDebug("Create Asibfm700Mount class instance ({})", this->getThreadId()); +} + +Asibfm700Mount1::~Asibfm700Mount1() +{ + logDebug("Delete Asibfm700Mount class instance ({})", this->getThreadId()); +} + } // namespace asibfm700 diff --git a/asibfm700/asibfm700_mount.h b/asibfm700/asibfm700_mount.h index 39476af..06b6dcd 100644 --- a/asibfm700/asibfm700_mount.h +++ b/asibfm700/asibfm700_mount.h @@ -64,6 +64,14 @@ class Asibfm700Mount1 : public mcc::ccte::erfa::MccCCTE_ERFA, mcc::MccSimpleTrackingModel, Asibfm700Logger>> { + typedef mcc::MccGenericMount + gm_class_t; + typedef mcc::MccGenericFsmMount> base_gm_class_t; +protected: + struct Asibfm700ErrorState : base_gm_class_t::MccGenericFsmMountBaseState { + static constexpr std::string_view ID{"ASIBFM700-MOUNT-ERROR-STATE"}; + + void exit(MccGenericFsmMountErrorEvent& event) + { + event.mount()->logWarn("The mount already in error state!"); + } + + void enter(MccGenericFsmMountErrorEvent& event) + { + event.mount()->logWarn("The mount already in error state!"); + } + + void exit(mcc::fsm::traits::fsm_event_c auto& event) + { + exitLog(event); + } + + void enter(mcc::fsm::traits::fsm_event_c auto& event) + { + enterLog(event); + + // ... + } + + using transition_t = mcc::fsm::fsm_transition_table_t< + std::pair, + std::pair>, + std::pair>>; + }; + + + typedef base_gm_class_t::MccGenericFsmMountStartState Asibfm700StartState; + public: using base_gm_class_t::error_t; diff --git a/mcc/mcc_generic_mount.h b/mcc/mcc_generic_mount.h index 5435d0b..88a3af9 100644 --- a/mcc/mcc_generic_mount.h +++ b/mcc/mcc_generic_mount.h @@ -99,7 +99,7 @@ public: auto hw_err = this->hardwareStop(); if (hw_err) { - return mcc_deduce_error(hw_err, MccGenericMountErrorCode::ERROR_HW_STOP); + return mcc_deduce_error_code(hw_err, MccGenericMountErrorCode::ERROR_HW_STOP); } logInfo("Stop command was sent"); @@ -113,7 +113,7 @@ public: auto hw_err = this->hardwareInit(); if (hw_err) { - return mcc_deduce_error(hw_err, MccGenericMountErrorCode::ERROR_HW_STOP); + return mcc_deduce_error_code(hw_err, MccGenericMountErrorCode::ERROR_HW_STOP); } logInfo("Mount initialization was performed"); @@ -140,6 +140,8 @@ public: using typename MOUNT_T::tracking_params_t; protected: + error_t _lastError; + /* default events implementation */ struct MccGenericFsmMountBaseEvent { @@ -236,7 +238,8 @@ protected: struct MccGenericFsmMountErrorState; // default error-state class implementation (forward declaration) - template + // template + template struct MccGenericFsmMountInitState; template @@ -260,7 +263,8 @@ protected: std::pair>>; }; - template + // template + template struct MccGenericFsmMountIdleState : MccGenericFsmMountBaseState // IDLE state: mount is stopped, wait for client commands { @@ -285,8 +289,11 @@ protected: } }; - template + // template + template struct MccGenericFsmMountInitState : MccGenericFsmMountBaseState { + // static_assert(fsm::traits::fsm_state_c); + static constexpr std::string_view ID{"GENERIC-MOUNT-INIT-STATE"}; using transition_t = fsm::fsm_transition_table_t< @@ -512,6 +519,9 @@ protected: void exit(fsm::traits::fsm_event_c auto& event) { + // just reset error + event.mount()->_lastError = MccGenericFsmMountErrorCode::ERROR_OK; + exitLog(event); if constexpr (mcc_generic_log_mount_c) { @@ -524,6 +534,8 @@ protected: void enter(fsm::traits::fsm_event_c auto& event) { + event.mount()->_lastError = event.eventData(); + enterLog(event); if constexpr (mcc_generic_log_mount_c) { @@ -546,15 +558,21 @@ public: // reimplementation of base-class methods to adapt it to FSM-behavior - auto initMount() + error_t initMount() { try { this->dispatchEvent(MccGenericFsmMountInitEvent{this}); } catch (std::system_error const& exc) { - return exc.code(); + if (exc.code().category() == fsm::MccFiniteStateMachineCategory::get()) { + _lastError = MccGenericFsmMountErrorCode::ERROR_INVALID_OPERATION; + } else { + // return exc.code(); + _lastError = exc.code(); + } } - return MccGenericFsmMountErrorCode::ERROR_OK; + // return MccGenericFsmMountErrorCode::ERROR_OK; + return _lastError; } auto stopMount() @@ -562,10 +580,16 @@ public: try { this->dispatchEvent(MccGenericFsmMountStopEvent{this}); } catch (std::system_error const& exc) { - return exc.code(); + if (exc.code().category() == fsm::MccFiniteStateMachineCategory::get()) { + _lastError = MccGenericFsmMountErrorCode::ERROR_INVALID_OPERATION; + } else { + // return exc.code(); + _lastError = exc.code(); + } } - return MccGenericFsmMountErrorCode::ERROR_OK; + // return MccGenericFsmMountErrorCode::ERROR_OK; + return _lastError; } auto slewToTarget() @@ -573,10 +597,16 @@ public: try { this->dispatchEvent(MccGenericFsmMountSlewEvent{this}); } catch (std::system_error const& exc) { - return exc.code(); + if (exc.code().category() == fsm::MccFiniteStateMachineCategory::get()) { + _lastError = MccGenericFsmMountErrorCode::ERROR_INVALID_OPERATION; + } else { + // return exc.code(); + _lastError = exc.code(); + } } - return MccGenericFsmMountErrorCode::ERROR_OK; + // return MccGenericFsmMountErrorCode::ERROR_OK; + return _lastError; } auto stopSlewing() @@ -584,10 +614,16 @@ public: try { this->dispatchEvent(MccGenericFsmMountStopEvent{this}); } catch (std::system_error const& exc) { - return exc.code(); + if (exc.code().category() == fsm::MccFiniteStateMachineCategory::get()) { + _lastError = MccGenericFsmMountErrorCode::ERROR_INVALID_OPERATION; + } else { + // return exc.code(); + _lastError = exc.code(); + } } - return MccGenericFsmMountErrorCode::ERROR_OK; + // return MccGenericFsmMountErrorCode::ERROR_OK; + return _lastError; } auto trackTarget() @@ -595,10 +631,16 @@ public: try { this->dispatchEvent(MccGenericFsmMountTrackEvent{this}); } catch (std::system_error const& exc) { - return exc.code(); + if (exc.code().category() == fsm::MccFiniteStateMachineCategory::get()) { + _lastError = MccGenericFsmMountErrorCode::ERROR_INVALID_OPERATION; + } else { + // return exc.code(); + _lastError = exc.code(); + } } - return MccGenericFsmMountErrorCode::ERROR_OK; + // return MccGenericFsmMountErrorCode::ERROR_OK; + return _lastError; } @@ -607,47 +649,16 @@ public: try { this->dispatchEvent(MccGenericFsmMountStopEvent{this}); } catch (std::system_error const& exc) { - return exc.code(); + if (exc.code().category() == fsm::MccFiniteStateMachineCategory::get()) { + _lastError = MccGenericFsmMountErrorCode::ERROR_INVALID_OPERATION; + } else { + // return exc.code(); + _lastError = exc.code(); + } } - return MccGenericFsmMountErrorCode::ERROR_OK; - } - - -protected: - // wrappers - - auto _initMount() - { - return MOUNT_T::initMount(); - } - - - auto _stopMount() - { - return MOUNT_T::stopMount(); - } - - auto _slewToTarget() - { - return MOUNT_T::slewToTarget(); - } - - - auto _trackTarget() - { - return MOUNT_T::trackTarget(); - } - - - auto _startGuidingTarget() - { - return MOUNT_T::startGuidingTarget(); - } - - auto _stopGuidingTarget() - { - return MOUNT_T::stopGuidingTarget(); + // return MccGenericFsmMountErrorCode::ERROR_OK; + return _lastError; } }; diff --git a/mcc/mcc_generics.h b/mcc/mcc_generics.h index 65e4a04..810398e 100644 --- a/mcc/mcc_generics.h +++ b/mcc/mcc_generics.h @@ -167,6 +167,17 @@ static constexpr ErrT mcc_deduce_error(const DErrT& err, const ErrT& default_err } } +template +static constexpr std::error_code mcc_deduce_error_code(const DErrT& err, const ErrT& default_err) + requires(std::is_error_code_enum_v || std::derived_from) +{ + if constexpr (std::is_error_code_enum_v) { + return err; + } else { + return default_err; + } +} + /* ATMOSPHERIC REFRACTION MODEL CLASS CONCEPT */ diff --git a/mcc/mcc_generics_new.h b/mcc/mcc_generics_new.h index dd6eb7e..503fc39 100644 --- a/mcc/mcc_generics_new.h +++ b/mcc/mcc_generics_new.h @@ -306,14 +306,6 @@ struct MccGenericEqtHrzCoords : MccGenericCelestialPoint { typedef MccGenericEqtHrzCoords MccEqtHrzCoords; -template -struct MccGenericPointingTarget : MccGenericEqtHrzCoords { - using typename MccGenericEqtHrzCoords::coord_t; - - coord_t RA_ICRS{}, DEC_ICRS{}; -}; - -typedef MccGenericPointingTarget MccPointingTarget; static constexpr void mcc_copy_eqt_hrz_coord(mcc_eqt_hrz_coord_c auto const& from_pt, mcc_eqt_hrz_coord_c auto* to_pt) { @@ -349,64 +341,84 @@ static constexpr void mcc_copy_eqt_hrz_coord(mcc_eqt_hrz_coord_c auto const& fro template concept mcc_ccte_c = requires(const T t_const, T t) { - { t_const.nameCCTE() } -> std::formattable; + { t_const.nameCCTE() } -> std::formattable; // just a name requires mcc_refract_model_c; { t.refractionModel(std::declval()) } -> mcc_error_c; + /* there is no way to declare a concept for a class templated method, so mandatory implementation is only required + for default MCC library types */ - [](T tt) -> mcc_error_c auto { - MccTimePoint tp{}; - double jd, st, pa, dZ; + // timepointToJulday(mcc_time_point_c auto tp, mcc_julday_c auto* julday) + { t.timepointToJulday(std::declval(), std::declval()) } -> mcc_error_c; + { t.timepointToJulday(std::declval(), std::declval()) } -> mcc_error_c; - MccJulianDay jd_class; + // timepointToAppSideral(mcc_time_point_c auto tp, mcc_angle_c auto* st, bool islocal) + { + t.timepointToAppSideral(std::declval(), std::declval(), std::declval()) + } -> mcc_error_c; + { + t.timepointToAppSideral(std::declval(), std::declval(), std::declval()) + } -> mcc_error_c; - MccAngle st_class, pa_class, dZ_class; - - MccCelestialPoint cp; - MccGenericCelestialPoint cp_class; - - MccEqtHrzCoords eqhr; - MccGenericEqtHrzCoords eqhr_class; + // juldayToAppSideral(mcc_julday_c auto jd, mcc_angle_c auto* st, bool islocal) + { t.juldayToAppSideral(std::declval(), std::declval(), std::declval()) } -> mcc_error_c; + { t.juldayToAppSideral(std::declval(), std::declval(), std::declval()) } -> mcc_error_c; + { + t.juldayToAppSideral(std::declval(), std::declval(), std::declval()) + } -> mcc_error_c; + { + t.juldayToAppSideral(std::declval(), std::declval(), std::declval()) + } -> mcc_error_c; - auto ret = tt.timepointToJulday(tp, &jd); - ret = tt.timepointToJulday(tp, &jd_class); + // NOTE: ASSUMING THE AZIMUTH IS COUNTED FROM THE SOUTH THROUGH THE WEST!!! + + // transformCoordinates(mcc_celestial_point_c auto from_pt, mcc_celestial_point_c auto* to_pt) + { t.transformCoordinates(std::declval(), std::declval()) } -> mcc_error_c; + { + t.transformCoordinates(std::declval(), std::declval*>()) + } -> mcc_error_c; + { + t.transformCoordinates(std::declval>(), std::declval()) + } -> mcc_error_c; + { + t.transformCoordinates(std::declval>(), + std::declval*>()) + } -> mcc_error_c; + + { t.transformCoordinates(std::declval(), std::declval()) } -> mcc_error_c; + { + t.transformCoordinates(std::declval(), std::declval*>()) + } -> mcc_error_c; + { + t.transformCoordinates(std::declval>(), std::declval()) + } -> mcc_error_c; + { + t.transformCoordinates(std::declval>(), + std::declval*>()) + } -> mcc_error_c; - ret = tt.timepointToAppSideral(tp, &st, true); - ret = tt.timepointToAppSideral(tp, &st_class, true); + // parallacticAngle(mcc_celestial_point_c auto pt, mcc_angle_c auto* pa) + { t.parallacticAngle(std::declval(), std::declval()) } -> mcc_error_c; + { t.parallacticAngle(std::declval(), std::declval()) } -> mcc_error_c; + { t.parallacticAngle(std::declval>(), std::declval()) } -> mcc_error_c; + { + t.parallacticAngle(std::declval>(), std::declval()) + } -> mcc_error_c; - ret = tt.timepointToAppSideral(jd, &st, true); - ret = tt.timepointToAppSideral(jd, &st_class, true); - ret = tt.timepointToAppSideral(jd_class, &st, true); - ret = tt.timepointToAppSideral(jd_class, &st_class, true); - // NOTE: ASSUMING THE AZIMUTH IS COUNTED FROM THE SOUTH THROUGH THE WEST!!! - - ret = tt.transformCoordinates(cp, &cp); - ret = tt.transformCoordinates(cp, &cp_class); - ret = tt.transformCoordinates(cp_class, &cp); - ret = tt.transformCoordinates(cp_class, &cp_class); - - ret = tt.transformCoordinates(cp, &eqhr); - ret = tt.transformCoordinates(cp, &eqhr_class); - ret = tt.transformCoordinates(cp_class, &eqhr); - ret = tt.transformCoordinates(cp_class, &eqhr_class); - - ret = tt.parallacticAngle(cp, &pa); - ret = tt.parallacticAngle(cp, &pa_class); - ret = tt.parallacticAngle(cp_class, &pa); - ret = tt.parallacticAngle(cp_class, &pa_class); - - ret = tt.refractionCorrection(cp, &dZ); - ret = tt.refractionCorrection(cp, &dZ_class); - ret = tt.refractionCorrection(cp_class, &dZ); - ret = tt.refractionCorrection(cp_class, &dZ_class); - - return ret; - }(t); + // refractionCorrection(mcc_celestial_point_c auto pt, mcc_angle_c auto* dZ) + { t.refractionCorrection(std::declval(), std::declval()) } -> mcc_error_c; + { t.refractionCorrection(std::declval(), std::declval()) } -> mcc_error_c; + { + t.refractionCorrection(std::declval>(), std::declval()) + } -> mcc_error_c; + { + t.refractionCorrection(std::declval>(), std::declval()) + } -> mcc_error_c; }; @@ -436,83 +448,181 @@ concept mcc_PCM_c = requires(T t) { return val; }(); // to ensure 'mountType' can be used in compile-time context - [](T tt) -> mcc_error_c auto { - MccPCMResult res; - MccGenericPCMResult res_class; + /* there is no way to declare a concept for a class templated method, so mandatory implementation is only required + for default MCC library types */ - MccCelestialPoint cp; - MccGenericCelestialPoint cp_class; - MccEqtHrzCoords eqhr; - MccGenericEqtHrzCoords eqhr_class; + // the templated method signature: + // computePCM(mcc_celestial_point_c auto pt, mcc_PCM_result_c auto* result, mcc_celestial_point_c auto* app_pt) + // pt - hardware (encoder) coordinates for which PCM needs to be calculated (pt.pair_kind is ignored!), + // app_pt: app_pt->X = pt.X + result->pcmX + // app_pt->Y = pt.Y + result->pcmY + { + t.computePCM(std::declval(), std::declval(), + std::declval()) + } -> mcc_error_c; + { + t.computePCM(std::declval(), std::declval*>(), + std::declval()) + } -> mcc_error_c; + { + t.computePCM(std::declval>(), std::declval(), + std::declval()) + } -> mcc_error_c; + { + t.computePCM(std::declval>(), std::declval*>(), + std::declval()) + } -> mcc_error_c; - // computePCM(mcc_celestial_point_c auto pt, mcc_PCM_result_c auto* result, mcc_celestial_point_c auto* app_pt) + { + t.computePCM(std::declval(), std::declval(), + std::declval*>()) + } -> mcc_error_c; + { + t.computePCM(std::declval(), std::declval*>(), + std::declval*>()) + } -> mcc_error_c; + { + t.computePCM(std::declval>(), std::declval(), + std::declval*>()) + } -> mcc_error_c; + { + t.computePCM(std::declval>(), std::declval*>(), + std::declval*>()) + } -> mcc_error_c; - auto ret = tt.computePCM(cp, &res, &cp); - ret = tt.computePCM(cp, &res_class, &cp); - ret = tt.computePCM(cp_class, &res, &cp); - ret = tt.computePCM(cp_class, &res_class, &cp); - ret = tt.computePCM(cp, &res, &cp_class); - ret = tt.computePCM(cp, &res_class, &cp_class); - ret = tt.computePCM(cp_class, &res, &cp_class); - ret = tt.computePCM(cp_class, &res_class, &cp_class); + // the templated method signature: + // computePCM(mcc_celestial_point_c auto pt, mcc_PCM_result_c auto* result, mcc_eqt_hrz_coord_c auto* app_pt) + // + // for equatorial mounts the method must compute (if app_pt is not nullptr): + // app_pt->HA = pt.X + result->pcmX + // app_pt->DEC_APP = pt.Y + result->pcmY + // for alt-azimuthal: + // app_pt->AZ = pt.X + result->pcmX + // app_pt->ZD = pt.Y + result->pcmY + { + t.computePCM(std::declval(), std::declval(), std::declval()) + } -> mcc_error_c; + { + t.computePCM(std::declval(), std::declval*>(), + std::declval()) + } -> mcc_error_c; + { + t.computePCM(std::declval>(), std::declval(), + std::declval()) + } -> mcc_error_c; + { + t.computePCM(std::declval>(), std::declval*>(), + std::declval()) + } -> mcc_error_c; - // computePCM(mcc_celestial_point_c auto pt, mcc_PCM_result_c auto* result, mcc_eqt_hrz_coord_c auto* app_pt) - // - // for equatorial mounts the method must compute: - // app_pt->HA = pt.X + result->pcmX - // app_pt->DEC_APP = pt.Y + result->pcmY - // for alt-azimuthal: - // app_pt->AZ = pt.X + result->pcmX - // app_pt->ZD = pt.Y + result->pcmY ret = tt.computePCM(cp, &res, &eqhr); - ret = tt.computePCM(cp, &res_class, &eqhr); - ret = tt.computePCM(cp_class, &res, &eqhr); - ret = tt.computePCM(cp_class, &res_class, &eqhr); + { + t.computePCM(std::declval(), std::declval(), + std::declval*>()) + } -> mcc_error_c; + { + t.computePCM(std::declval(), std::declval*>(), + std::declval*>()) + } -> mcc_error_c; + { + t.computePCM(std::declval>(), std::declval(), + std::declval*>()) + } -> mcc_error_c; + { + t.computePCM(std::declval>(), std::declval*>(), + std::declval*>()) + } -> mcc_error_c; - ret = tt.computePCM(cp, &res, &eqhr_class); - ret = tt.computePCM(cp, &res_class, &eqhr_class); - ret = tt.computePCM(cp_class, &res, &eqhr_class); - ret = tt.computePCM(cp_class, &res_class, &eqhr_class); - // computeInversePCM(mcc_celestial_point_c auto pt, mcc_PCM_result_c auto* result, mcc_celestial_point_c auto* - // app_pt) + // the templated method signature: + // computeInversePCM(mcc_celestial_point_c auto app_pt, mcc_PCM_result_c auto* result, mcc_celestial_point_c auto* + // hw_pt) + // + // app_pt - apparent celestial coordinates for which inverted PCM needs to be calculated. + // app_pt.X and app_pt.Y are assumed to be HA and DEC for equatorial mounts; AZ and ZD for alt-azimuthal + // ones (app_pt.pair_kind is ignored!) + // hw_pt - computed hardware (encoder) coordinates + { + t.computeInversePCM(std::declval(), std::declval(), + std::declval()) + } -> mcc_error_c; + { + t.computeInversePCM(std::declval(), std::declval*>(), + std::declval()) + } -> mcc_error_c; + { + t.computeInversePCM(std::declval>(), std::declval(), + std::declval()) + } -> mcc_error_c; + { + t.computeInversePCM(std::declval>(), + std::declval*>(), std::declval()) + } -> mcc_error_c; - ret = tt.computeInversePCM(cp, &res, &cp); - ret = tt.computeInversePCM(cp, &res_class, &cp); - ret = tt.computeInversePCM(cp_class, &res, &cp); - ret = tt.computeInversePCM(cp_class, &res_class, &cp); + { + t.computeInversePCM(std::declval(), std::declval(), + std::declval*>()) + } -> mcc_error_c; + { + t.computeInversePCM(std::declval(), std::declval*>(), + std::declval*>()) + } -> mcc_error_c; + { + t.computeInversePCM(std::declval>(), std::declval(), + std::declval*>()) + } -> mcc_error_c; + { + t.computeInversePCM(std::declval>(), + std::declval*>(), + std::declval*>()) + } -> mcc_error_c; - ret = tt.computeInversePCM(cp, &res, &cp_class); - ret = tt.computeInversePCM(cp, &res_class, &cp_class); - ret = tt.computeInversePCM(cp_class, &res, &cp_class); - ret = tt.computeInversePCM(cp_class, &res_class, &cp_class); - // computeInversePCM(mcc_eqt_hrz_coord_c auto pt, mcc_PCM_result_c auto* result, mcc_celestial_point_c auto* - // app_pt) - // - // NOTE: for computation of the corrections the method must use of app_pt.X and app_pt.Y - // - // for equatorial mounts the method must compute: - // hw_pt->X = app_pt.HA + inv_result.pcmX - // hw_pt->Y = app_pt.DEC_APP + inv_result.pcmY - // and inputs for the corrections computing are app_pt.HA and app_pt.DEC_APP - // for alt-azimuthal: - // hw_pt->X = app_pt.AZ + inv_result.pcmX - // hw_pt->Y = app_pt.ZD + inv_result.pcmY - // and inputs for the corrections computing are app_pt.ZA and app_pt.ZD ret = - // tt.computeInversePCM(eqhr, &res, &cp); - ret = tt.computeInversePCM(eqhr, &res_class, &cp); - ret = tt.computeInversePCM(eqhr_class, &res, &cp); - ret = tt.computeInversePCM(eqhr_class, &res_class, &cp); + // the templated method signature: + // computeInversePCM(mcc_eqt_hrz_coord_c auto app_pt, mcc_PCM_result_c auto* result, mcc_celestial_point_c auto* + // hw_pt) + // + // for equatorial mounts the method must compute: + // hw_pt->X = app_pt.HA + inv_result.pcmX + // hw_pt->Y = app_pt.DEC_APP + inv_result.pcmY + // for alt-azimuthal: + // hw_pt->X = app_pt.AZ + inv_result.pcmX + // hw_pt->Y = app_pt.ZD + inv_result.pcmY + { + t.computeInversePCM(std::declval(), std::declval(), + std::declval()) + } -> mcc_error_c; + { + t.computeInversePCM(std::declval(), std::declval*>(), + std::declval()) + } -> mcc_error_c; + { + t.computeInversePCM(std::declval>(), std::declval(), + std::declval()) + } -> mcc_error_c; + { + t.computeInversePCM(std::declval>(), + std::declval*>(), std::declval()) + } -> mcc_error_c; - ret = tt.computeInversePCM(eqhr, &res, &cp_class); - ret = tt.computeInversePCM(eqhr, &res_class, &cp_class); - ret = tt.computeInversePCM(eqhr_class, &res, &cp_class); - ret = tt.computeInversePCM(eqhr_class, &res_class, &cp_class); - - return ret; - }(t); + { + t.computeInversePCM(std::declval(), std::declval(), + std::declval*>()) + } -> mcc_error_c; + { + t.computeInversePCM(std::declval(), std::declval*>(), + std::declval*>()) + } -> mcc_error_c; + { + t.computeInversePCM(std::declval>(), std::declval(), + std::declval*>()) + } -> mcc_error_c; + { + t.computeInversePCM(std::declval>(), + std::declval*>(), + std::declval*>()) + } -> mcc_error_c; }; /* MOUNT HARDWARE ABSTRACTION CLASS CONCEPT */ @@ -602,8 +712,9 @@ concept mcc_hardware_c = requires(T t, const T t_const) { -/* MOUNT TELEMETRY DATA CLASS CONCEPT */ +/* MOUNT TELEMETRY DATA CLASS CONCEPT */ +// target coordinates class concept template concept mcc_pointing_target_coord_c = mcc_eqt_hrz_coord_c && requires(T t) { requires mcc_angle_c; // ICRS right ascention @@ -611,6 +722,16 @@ concept mcc_pointing_target_coord_c = mcc_eqt_hrz_coord_c && requires(T t) { }; +template +struct MccGenericPointingTarget : MccGenericEqtHrzCoords { + using typename MccGenericEqtHrzCoords::coord_t; + + coord_t RA_ICRS{}, DEC_ICRS{}; +}; + +typedef MccGenericPointingTarget MccPointingTarget; + + static constexpr void mcc_copy_pointing_target_coord(mcc_pointing_target_coord_c auto const& from_pt, mcc_pointing_target_coord_c auto* to_pt) { @@ -665,6 +786,28 @@ concept mcc_telemetry_data_c = mcc_eqt_hrz_coord_c && std::default_initializa }; +/* DEFAULT TELEMETRY DATA CLASS */ + +template +struct MccGenericTelemetryData : MccGenericEqtHrzCoords { + using typename MccGenericEqtHrzCoords::coord_t; + + MccJulianDay JD; + coord_t LST; // local apparent sideral time + + MccGenericPointingTarget target{}; + + coord_t speedX, speedY; + + coord_t pcmX, pcmY; + + coord_t refCorr; +}; + + +typedef MccGenericTelemetryData MccTelemetryData; + + static constexpr void mcc_copy_telemetry_data(mcc_telemetry_data_c auto const& from_pt, mcc_telemetry_data_c auto* to_pt) { @@ -707,7 +850,7 @@ static constexpr void mcc_copy_telemetry_data(mcc_telemetry_data_c auto const& f -/* MOUNT TELEMETRY MANAGER CLASS CONCEPT */ +/* MOUNT TELEMETRY MANAGER CLASS CONCEPT */ template struct mcc_telemetry_interface_t { @@ -774,8 +917,34 @@ protected: mcc_telemetry_interface_t() = default; }; +// template +// concept mcc_telemetry_c = std::derived_from>; + template -concept mcc_telemetry_c = std::derived_from>; +concept mcc_telemetry_c = requires(T t) { + // update telemetry data right now + { t.updateTelemetryData() } -> mcc_error_c; + + // get current data + // an implementation is expected to return current, possibly already expired, telemetry data + // one should call consistently both 'updateTelemetryData' + 'telemetryData' methods + // to ensure that the data is up-to-date + // + // templated method signature + // telemetryData(mcc_telemetry_data_c auto* data) + { t.telemetryData(std::declval()) } -> mcc_error_c; + { t.telemetryData(std::declval*>()) } -> mcc_error_c; + + + // waiting for updated data + // an implementation is expected to block the current thread waiting for + // telemetry data to be updated (internal synchronization) + // + // templated method signature + // waitForTelemetryData(mcc_telemetry_data_c auto* data) + { t.waitForTelemetryData(std::declval()) } -> mcc_error_c; + { t.waitForTelemetryData(std::declval*>()) } -> mcc_error_c; +};