From 45f655dc90e333f962f65f2204510f9a8fb275af Mon Sep 17 00:00:00 2001 From: "Timur A. Fatkhullin" Date: Wed, 27 Aug 2025 17:55:57 +0300 Subject: [PATCH] ... --- mcc/mcc_angle.h | 15 ++++ mcc/mcc_ccte_erfa.h | 1 + mcc/mcc_generics.h | 8 +- mcc/mcc_pzone.h | 24 +++++- mcc/mcc_tracking_model.h | 163 +++++++++++++++++++++++++++++++++++++++ mcc/tests/ccte_test.cpp | 23 ++++++ 6 files changed, 229 insertions(+), 5 deletions(-) create mode 100644 mcc/mcc_tracking_model.h diff --git a/mcc/mcc_angle.h b/mcc/mcc_angle.h index 2bc3764..8b7fa28 100644 --- a/mcc/mcc_angle.h +++ b/mcc/mcc_angle.h @@ -23,6 +23,21 @@ constexpr double operator""_arcsecs(long double val) // angle in arc seconds return val * std::numbers::pi / 180.0 / 3600.0; } +constexpr double operator""_hours(long double val) // angle in hours +{ + return val * std::numbers::pi / 12.0; +} + +constexpr double operator""_mins(long double val) // angle in hour minutes +{ + return val * std::numbers::pi / 12.0 / 60.0; +} + +constexpr double operator""_secs(long double val) // angle in hour seconds +{ + return val * std::numbers::pi / 12.0 / 3600.0; +} + constexpr double operator""_dms(const char* s, size_t size) // as a string "DEGREES:MINUTES:SECONDS" { auto res = mcc::utils::parsAngleString(std::span{s, size}); diff --git a/mcc/mcc_ccte_erfa.h b/mcc/mcc_ccte_erfa.h index a40293f..8ab9696 100644 --- a/mcc/mcc_ccte_erfa.h +++ b/mcc/mcc_ccte_erfa.h @@ -739,6 +739,7 @@ public: } else { auto tanZ = tan(pt.Y); *dZ = rmodel.refa * tanZ + rmodel.refb * tanZ * tanZ * tanZ; + // *dZ = rmodel.refa / tanZ + rmodel.refb / (tanZ * tanZ * tanZ); } } else { MccCelestialPoint tr_pt{.pair_kind = MccCoordPairKind::COORDS_KIND_AZZD, .time_point = pt.time_point}; diff --git a/mcc/mcc_generics.h b/mcc/mcc_generics.h index 70360a8..0ee9a47 100644 --- a/mcc/mcc_generics.h +++ b/mcc/mcc_generics.h @@ -585,7 +585,7 @@ concept mcc_hardware_c = requires(T t, const T t_const) { requires mcc_angle_c; // moving speed along co-longitude coordinate requires mcc_angle_c; // moving speed along co-latitude coordinate - std::same_as; + requires std::same_as; }; // set hardware state: @@ -735,7 +735,7 @@ concept mcc_slewing_model_c = requires(T t) { // a class of slewing process parameters requires requires(typename T::slewing_params_t pars) { // slew mount to target and stop - std::convertible_to; + requires std::convertible_to; }; { t.slewToTarget() } -> std::same_as; @@ -770,7 +770,7 @@ concept mcc_guiding_model_c = requires(T t) { // a class of guiding process parameters requires requires(typename T::guiding_params_t pars) { // guide along both mount axis - std::convertible_to; + requires std::convertible_to; }; { t.startGuidingTarget() } -> std::same_as; @@ -832,7 +832,7 @@ concept mcc_guiding_model_c = requires(T t) { // && mcc_telemetry_c && mcc_pzone_container_c; template -concept mcc_generic_mount_c = mcc_telemetry_c && mcc_pzone_container_c && requires(T t) { +concept mcc_generic_mount_c = mcc_hardware_c && mcc_telemetry_c && mcc_pzone_container_c && requires(T t) { requires mcc_error_c; // slew mount to target (target coordinates were defined in telemetry data) diff --git a/mcc/mcc_pzone.h b/mcc/mcc_pzone.h index a23e9d4..0359d89 100644 --- a/mcc/mcc_pzone.h +++ b/mcc/mcc_pzone.h @@ -14,7 +14,7 @@ namespace mcc static constexpr double mcc_sideral_to_UT1_ratio = 1.002737909350795; // sideral/UT1 -enum MccAltLimitPZErrorCode : int { ERROR_OK, ERROR_COORD_TRANSFROM }; +enum MccAltLimitPZErrorCode : int { ERROR_OK, ERROR_NULLPTR, ERROR_COORD_TRANSFROM }; } // namespace mcc @@ -54,6 +54,8 @@ struct MccAltLimitPZCategory : public std::error_category { switch (err) { case MccAltLimitPZErrorCode::ERROR_OK: return "OK"; + case MccAltLimitPZErrorCode::ERROR_NULLPTR: + return "input argument os nullptr"; case MccAltLimitPZErrorCode::ERROR_COORD_TRANSFROM: return "coordinate transformation error"; default: @@ -97,6 +99,10 @@ public: _latLim(MccAltLimitPZ::pi2 - _altLimit) { _transformCoordinates = [ccte_engine](MccCelestialPoint from_pt, MccCelestialPoint* to_pt) -> error_t { + if (to_pt == nullptr) { + return MccAltLimitPZErrorCode::ERROR_NULLPTR; + } + auto err = ccte_engine->transformCoordinates(from_pt, to_pt); if (!err) { return MccAltLimitPZErrorCode::ERROR_OK; @@ -128,6 +134,10 @@ public: { double alt; + if (result == nullptr) { + return MccAltLimitPZErrorCode::ERROR_NULLPTR; + } + error_t ret = MccAltLimitPZErrorCode::ERROR_OK; if constexpr (mcc_eqt_hrz_coord_c) { @@ -157,6 +167,10 @@ public: { using res_t = std::remove_cvref_t; + if (res_time == nullptr) { + return MccAltLimitPZErrorCode::ERROR_NULLPTR; + } + double ha, dec; error_t ret = MccAltLimitPZErrorCode::ERROR_OK; @@ -209,6 +223,10 @@ public: { using res_t = std::remove_cvref_t; + if (res_time == nullptr) { + return MccAltLimitPZErrorCode::ERROR_NULLPTR; + } + double ha, dec; error_t ret = MccAltLimitPZErrorCode::ERROR_OK; @@ -266,6 +284,10 @@ public: { double ha, dec, az; + if (point == nullptr) { + return MccAltLimitPZErrorCode::ERROR_NULLPTR; + } + error_t ret = MccAltLimitPZErrorCode::ERROR_OK; if constexpr (mcc_eqt_hrz_coord_c) { diff --git a/mcc/mcc_tracking_model.h b/mcc/mcc_tracking_model.h new file mode 100644 index 0000000..e6b5a36 --- /dev/null +++ b/mcc/mcc_tracking_model.h @@ -0,0 +1,163 @@ +#pragma once + +/* MOUNT CONTROL COMPONENTS LIBRARY */ + + +/* SIMPLE TRACKING MODEL IMPLEMENTATION */ + + +#include "mcc_defaults.h" +#include "mcc_generics.h" + + +namespace mcc +{ + +enum class MccSimpleTrackingModelErrorCode : int { + ERROR_OK, + ERROR_HW_GETSTATE, + ERROR_HW_SETSTATE, + ERROR_TELEMETRY_TIMEOUT, + ERROR_PZONE_CONTAINER_COMP, + ERROR_IN_PZONE, + ERROR_UNEXPECTED_AXIS_RATES +}; + +} // namespace mcc + + +namespace std +{ + +template <> +class is_error_code_enum : public true_type +{ +}; + +} // namespace std + + + +namespace mcc +{ + +template +class MccSimpleTrackingModel +{ +public: + static constexpr MccMountType mountType = MOUNT_TYPE; + + typedef std::error_code error_t; + + struct tracking_params_t { + static constexpr double sideralRate = 15.0410686_arcsecs; // in radians per second + + double trackSpeedX{}; + double trackSpeedY{}; + + std::chrono::seconds telemetryTimeout{3}; + }; + + template + MccSimpleTrackingModel(MountT* mount) : _stopTracking(new std::atomic_bool()) + { + *_stopTracking = false; + + if constexpr (mccIsEquatorialMount(mountType)) { + _currentTrackParams.trackSpeedX = tracking_params_t::sideralRate; // move along HA-axis with sideral rate + _currentTrackParams.trackSpeedY = 0.0; + } + + _trackingFunc = [mount, this]() -> error_t { + typename MountT::hardware_state_t hw_state; + + if constexpr (mccIsEquatorialMount(mountType)) { + // just set sideral rate once + auto err = mount->hardwareGetState(&hw_state); + if (err) { + return mcc_deduce_error(err, MccSimpleTrackingModelErrorCode::ERROR_HW_GETSTATE); + } + + // hw_state.time_point; + hw_state.speedX = _currentTrackParams.trackSpeedX; + hw_state.speedY = _currentTrackParams.trackSpeedY; + hw_state.moving_type = MountT::hardware_moving_state_t::HW_MOVE_TRACKING; + + err = mount->hardwareSetState(std::move(hw_state)); + if (err) { + return mcc_deduce_error(err, MccSimpleTrackingModelErrorCode::ERROR_HW_SETSTATE); + } + + // control prohibited zones + MccTelemetryData tdata; + std::vector pz_flags; + bool inzone_flag; + + while (!*_stopTracking) { + auto t_err = mount->waitForTelemetryData(&tdata, _currentTrackParams.telemetryTimeout); + if (t_err) { + return mcc_deduce_error(t_err, MccSimpleTrackingModelErrorCode::ERROR_TELEMETRY_TIMEOUT); + } + + // check for current axis speed + if (utils::isEqual(tdata.speedX, 0.0) && utils::isEqual(tdata.speedY, 0.0)) { + // unhandled stop state?!!! + return MccSimpleTrackingModelErrorCode::ERROR_UNEXPECTED_AXIS_RATES; + } + + auto pz_err = mount->inPZone(tdata, &inzone_flag, &pz_flags); + if (pz_err) { + return mcc_deduce_error(t_err, MccSimpleTrackingModelErrorCode::ERROR_PZONE_CONTAINER_COMP); + } + + if (inzone_flag) { + // logging + return MccSimpleTrackingModelErrorCode::ERROR_IN_PZONE; + } + } + + return MccSimpleTrackingModelErrorCode::ERROR_OK; + } else if constexpr (mccIsAltAzMount(mountType)) { + static_assert(false, "NOT IMPLEMENTED!"); + } else { + static_assert(false, "UNKNOW MOUNT TYPE!"); + } + }; + } + + MccSimpleTrackingModel(MccSimpleTrackingModel&&) = default; + MccSimpleTrackingModel& operator=(MccSimpleTrackingModel&&) = default; + + + error_t trackMount() + { + return _trackingFunc(); + } + + + error_t stopTracking() + { + *_stopTracking = true; + + return MccSimpleTrackingModelErrorCode::ERROR_OK; + } + + + error_t setTrackingParams(tracking_params_t params) + { + _currentTrackParams = std::move(params); + } + + tracking_params_t getTrackingParams() + { + return _currentTrackParams; + } + +protected: + std::function _trackingFunc{}; + std::unique_ptr _stopTracking{}; + + tracking_params_t _currentTrackParams; +}; + +} // namespace mcc diff --git a/mcc/tests/ccte_test.cpp b/mcc/tests/ccte_test.cpp index 083741a..d05d522 100644 --- a/mcc/tests/ccte_test.cpp +++ b/mcc/tests/ccte_test.cpp @@ -104,5 +104,28 @@ int main() std::cout << "TIME TO ZONE 1: " << vm[0] << "\n"; std::cout << "TIME TO ZONE 2: " << vm[1] << "\n"; + + std::cout << "\n\n"; + + MccCCTE_ERFA::meteo_t meteo{.temperature = 10.0, .humidity = 0.7, .pressure = 1010.0}; + erfa.updateMeteoERFA(meteo); + + MccCCTE_ERFA::refract_model_t rm; + + erfa.refractionModel(&rm); + std::cout << "REFMODEL: A = " << rm.refa << ", B = " << rm.refb << "\n"; + + cp.pair_kind = mcc::MccCoordPairKind::COORDS_KIND_AZZD; + cp.X = 100.0_degs; + cp.Y = 45.0_degs; + + double dZ; + erfa.refractionCorrection(cp, &dZ); + std::cout << "dZ(" << mcc::MccAngle(cp.Y).degrees() << ") = " << mcc::MccAngle(dZ).arcsecs() << "\n"; + + cp.Y = 50.0_degs; + erfa.refractionCorrection(cp, &dZ); + std::cout << "dZ(" << mcc::MccAngle(cp.Y).degrees() << ") = " << mcc::MccAngle(dZ).arcsecs() << "\n"; + return 0; }