From 6646ef6acabd12342c1cca2f244accd15456c6b0 Mon Sep 17 00:00:00 2001 From: "Timur A. Fatkhullin" Date: Wed, 9 Jul 2025 18:47:13 +0300 Subject: [PATCH] ... --- cxx/mcc_mount_astro_erfa.h | 89 ++++++++++++++++--- cxx/mcc_mount_astrom.h | 4 + cxx/mcc_mount_concepts.h | 171 ++++++++++++++++++++++--------------- cxx/mcc_mount_pec.h | 53 +++++------- cxx/mcc_mount_telemetry.h | 151 +++++++++++++++++++++++++------- cxx/mcc_traits.h | 5 +- cxx/tests/astrom_test.cpp | 14 ++- 7 files changed, 339 insertions(+), 148 deletions(-) diff --git a/cxx/mcc_mount_astro_erfa.h b/cxx/mcc_mount_astro_erfa.h index c49f03c..cda7082 100644 --- a/cxx/mcc_mount_astro_erfa.h +++ b/cxx/mcc_mount_astro_erfa.h @@ -80,7 +80,9 @@ public: typedef MccAngle coord_t; typedef MccAngle sideral_time_t; + // typedef juldate_t terr_time_t; typedef MccAngle pa_t; + typedef MccAngle eo_t; struct refract_result_t { double refa, refb; @@ -156,34 +158,67 @@ public: } - engine_err_t apparentSiderTime(juldate_t juldate, sideral_time_t& gst, bool islocal = false) + engine_err_t terrestialTime(juldate_t juldate, juldate_t& tt) { std::lock_guard lock{_stateMutex}; using real_days_t = std::chrono::duration>; - double ut1 = juldate.mjd, tt = juldate.mjd; - - auto dut1 = _currentState._bulletinA.DUT1(juldate.mjd); - - if (dut1.has_value()) { - ut1 += std::chrono::duration_cast(dut1.value()).count(); - } else { // out of range - return ERROR_BULLETINA_OUT_OF_RANGE; - } - auto tai_utc = _currentState._leapSeconds[juldate.mjd]; if (tai_utc.has_value()) { - tt += std::chrono::duration_cast(tai_utc.value()).count(); + tt.mjd += std::chrono::duration_cast(tai_utc.value()).count(); } else { return ERROR_LEAPSECONDS_OUT_OF_RANGE; } auto tt_tai = _currentState._bulletinA.TT_TAI(); - tt += std::chrono::duration_cast(tt_tai).count(); + tt.mjd = juldate.mjd + std::chrono::duration_cast(tt_tai).count(); - gst = eraGst06a(juldate.MJD0, ut1, juldate.MJD0, tt); + return ERROR_OK; + } + + + engine_err_t apparentSiderTime(juldate_t juldate, sideral_time_t& gst, bool islocal = false) + { + // std::lock_guard lock{_stateMutex}; + + using real_days_t = std::chrono::duration>; + + double ut1 = juldate.mjd; + // double tt = juldate.mjd; + + { + std::lock_guard lock{_stateMutex}; + + auto dut1 = _currentState._bulletinA.DUT1(juldate.mjd); + + if (dut1.has_value()) { + ut1 += std::chrono::duration_cast(dut1.value()).count(); + } else { // out of range + return ERROR_BULLETINA_OUT_OF_RANGE; + } + } + + // auto tai_utc = _currentState._leapSeconds[juldate.mjd]; + // if (tai_utc.has_value()) { + // tt += std::chrono::duration_cast(tai_utc.value()).count(); + // } else { + // return ERROR_LEAPSECONDS_OUT_OF_RANGE; + // } + + + // auto tt_tai = _currentState._bulletinA.TT_TAI(); + // tt += std::chrono::duration_cast(tt_tai).count(); + // gst = eraGst06a(juldate.MJD0, ut1, juldate.MJD0, tt); + + juldate_t tt; + auto err = terrestialTime(juldate, tt); + if (err != ERROR_OK) { + return err; + } + + gst = eraGst06a(juldate.MJD0, ut1, juldate.MJD0, tt.mjd); if (islocal) { gst += _currentState.lon; } @@ -192,6 +227,20 @@ public: } + engine_err_t eqOrigins(juldate_t juldate, eo_t& eo) + { + juldate_t tt; + + auto err = terrestialTime(juldate, tt); + if (err != ERROR_OK) { + return err; + } + + eo = eraEo06a(tt.MJD0, tt.mjd); + + return ERROR_OK; + } + /* atmospheric refraction-related methods */ engine_err_t refraction(refract_result_t& refr) @@ -205,6 +254,18 @@ public: } + engine_err_t refractCorrection(const coord_t& alt, const refract_result_t& ref_params, coord_t& corr) + { + if (alt <= 0.0) { + corr = 35.4 / 60.0 * std::numbers::pi / 180.0; // 35.4 arcminutes + } else { + auto tanALT = std::tan(alt); + corr = ref_params.refa / tanALT + ref_params.refb / tanALT / tanALT / tanALT; + } + + return ERROR_OK; + } + /* coordinates conversional methods */ engine_err_t icrs2obs(coord_t ra, diff --git a/cxx/mcc_mount_astrom.h b/cxx/mcc_mount_astrom.h index eaebcac..9eec573 100644 --- a/cxx/mcc_mount_astrom.h +++ b/cxx/mcc_mount_astrom.h @@ -83,6 +83,10 @@ concept mcc_astrom_engine_c = requires(T t, const T t_const) { std::declval()) } -> std::same_as; + // equation of origins + { + t.eqOrigins(std::declval(), std::declval()) + } -> std::same_as; /* atmospheric refraction-related methods */ diff --git a/cxx/mcc_mount_concepts.h b/cxx/mcc_mount_concepts.h index 9a9ff64..fd510a1 100644 --- a/cxx/mcc_mount_concepts.h +++ b/cxx/mcc_mount_concepts.h @@ -21,6 +21,36 @@ static constexpr std::string_view MccMountTypeStr = TYPE == MccMountType::GERMAN : TYPE == MccMountType::ALTAZ_TYPE ? "ALTAZ" : "UNKNOWN"; +template +static constexpr bool mcc_is_equatorial_mount = TYPE == MccMountType::GERMAN_TYPE ? true + : TYPE == MccMountType::FORK_TYPE ? true + : TYPE == MccMountType::CROSSAXIS_TYPE ? true + : TYPE == MccMountType::ALTAZ_TYPE ? false + : false; +template +static constexpr bool mcc_is_altaz_mount = TYPE == MccMountType::GERMAN_TYPE ? false + : TYPE == MccMountType::FORK_TYPE ? false + : TYPE == MccMountType::CROSSAXIS_TYPE ? false + : TYPE == MccMountType::ALTAZ_TYPE ? true + : false; + +static consteval bool mccIsEquatorialMount(const MccMountType type) +{ + return type == MccMountType::GERMAN_TYPE ? true + : type == MccMountType::FORK_TYPE ? true + : type == MccMountType::CROSSAXIS_TYPE ? true + : type == MccMountType::ALTAZ_TYPE ? false + : false; +}; + +static consteval bool mccIsAltAzMount(const MccMountType type) +{ + return type == MccMountType::GERMAN_TYPE ? false + : type == MccMountType::FORK_TYPE ? false + : type == MccMountType::CROSSAXIS_TYPE ? false + : type == MccMountType::ALTAZ_TYPE ? true + : false; +}; } // namespace mcc @@ -99,108 +129,114 @@ concept mcc_astrom_engine_c = requires(T t, const T t_const) { /* atmospheric refraction-related methods */ + // compute refraction-related quantities: refraction(refr_params) { t.refraction(std::declval()) } -> std::same_as; + + // compute refraction correction for given altitude: refractCorrection(alt, refr_params, refr_corr) + { + t.refractCorrection(std::declval(), std::declval(), + std::declval()) + } -> std::same_as; }; /* MOUNT AXES AND MOTORS HARDWARE GENERIC ABSTRACTION */ -// encoder basic concept (e.g. mount axis encoder or motor shaft one) -template -concept mcc_hw_encoder_c = requires(T t, const T t_const) { - typename T::error_t; +// // encoder basic concept (e.g. mount axis encoder or motor shaft one) +// template +// concept mcc_hw_encoder_c = requires(T t, const T t_const) { +// requires mcc_error_c; - typename T::time_point_t; - typename T::coord_t; - typename T::speed_t; - typename T::accel_t; +// typename T::time_point_t; +// typename T::coord_t; +// typename T::speed_t; +// typename T::accel_t; - requires requires(typename T::state_t st) { - requires std::same_as; - requires std::same_as; - requires std::same_as; - requires std::same_as; - }; +// requires requires(typename T::state_t st) { +// requires std::same_as; +// requires std::same_as; +// requires std::same_as; +// requires std::same_as; +// }; - { t_const.errorString(std::declval()) } -> mcc_formattable; +// { t_const.errorString(std::declval()) } -> mcc_formattable; - { t_const.id() } -> mcc_formattable; +// { t_const.id() } -> mcc_formattable; - { t.getState(std::declval()) } -> std::same_as; -}; +// { t.getState(std::declval()) } -> std::same_as; +// }; -template -concept mcc_hw_motor_c = requires(T t, const T t_const) { - typename T::error_t; +// template +// concept mcc_hw_motor_c = requires(T t, const T t_const) { +// requires mcc_error_c; - typename T::coord_t; - typename T::speed_t; - typename T::accel_t; +// typename T::coord_t; +// typename T::speed_t; +// typename T::accel_t; - requires requires(typename T::pos_t st) { - requires std::same_as; - requires std::same_as; // means maximal allowed speed - requires std::same_as; // means a maximal allowed acceleration (jerk) - }; +// requires requires(typename T::pos_t st) { +// requires std::same_as; +// requires std::same_as; // means maximal allowed speed +// requires std::same_as; // means a maximal allowed acceleration +// (jerk) +// }; - { t_const.errorString(std::declval()) } -> mcc_formattable; +// { t_const.errorString(std::declval()) } -> mcc_formattable; - { t_const.id() } -> mcc_formattable; +// { t_const.id() } -> mcc_formattable; - { t.toPos(std::declval()) } -> std::same_as; +// { t.toPos(std::declval()) } -> std::same_as; - { t.stop() } -> std::same_as; -}; +// { t.stop() } -> std::same_as; +// }; -namespace details -{ -template -concept mcc_tuple_enc_ref_c = mcc_tuple_c && requires(T t) { - []