#pragma once /* MOUNT CONTROL COMPONENTS LIBRARY */ /* AN GENERIC MOUNT CLASS IMPLEMENTATION */ // #include #include #include #include #include #include #include "spdlog/sinks/null_sink.h" #include "mcc_finite_state_machine.h" #include "mcc_mount_coord.h" #include "mcc_spdlog.h" #include "mcc_traits.h" // #include "mount_astrom.h" #include "mcc_mount_pz.h" namespace mcc { /* BASIC DATA DEFINITIONS */ // meteo parameters (e.g. to compute refraction) struct MccMountMeteo { typedef double temp_t; typedef double humid_t; typedef double press_t; temp_t temperature; // Temperature in C humid_t humidity; // humidity in % ([0.0, 1.0]) press_t pressure; // atmospheric presure in hPa=mB }; // mount site geographical location struct MccMountSiteInfo { typedef MccAngle mnt_site_coord_t; typedef MccAngle mnt_site_elev_t; mnt_site_coord_t latitude{"00:00:00.0"_dms}; // mnt_site_coord_t longitude{0.0}; // positive to the East mnt_site_elev_t elevation{0.0}; // in meters std::string_view name{"ALL-ZERO"}; // just a human-readable name }; // mount current telemetry: time, position and related quantities struct MccMountTelemetry { typedef double mnt_coord_t; typedef double mnt_speed_t; typedef double time_point_t; // time-related std::chrono::system_clock::time_point utc; time_point_t mjd; // modified Julian date time_point_t ut1; time_point_t tt; time_point_t siderTime; // sideral time (in radians) // apparent target (user-input) current coordinates (in radians) mnt_coord_t tagRA, tagDEC; mnt_coord_t tagHA; mnt_coord_t tagAZ, tagZD; mnt_coord_t tagPA; // paralactic angle // encoder-measured current mount coordinates (in radians) mnt_coord_t mntRA, mntDEC; mnt_coord_t mntHA; mnt_coord_t mntAZ, mntZD; mnt_coord_t mntPA; // encoder-measured (non-corrected for PCS) current mount position and moving speed (in radians, radians/s) // X - HA, Y - DEC for equatorial-type mount; X - AZ, Y - ZD for horizontal-type one mnt_coord_t mntPosX, mntPosY; mnt_speed_t mntSpeedX, mntSpeedY; // current refraction coefficient (for tagZD) mnt_coord_t currRefr; // PCS (pointing correction system) corrections // X - HA, Y - DEC for equatorial-type mount; X - AZ, Y - ZD for horizontal-type one mnt_coord_t pcsX, pcsY; }; // mount construction type (only the most common ones) enum class MccMountType : uint8_t { GERMAN_TYPE, FORK_TYPE, CROSSAXIS_TYPE, ALTAZ_TYPE }; template static constexpr std::string_view MccMountTypeStr = TYPE == MccMountType::GERMAN_TYPE ? "GERMAN" : TYPE == MccMountType::FORK_TYPE ? "FORK" : TYPE == MccMountType::CROSSAXIS_TYPE ? "CROSSAXIS" : TYPE == MccMountType::ALTAZ_TYPE ? "ALTAZ" : "UNKNOWN"; // mount configuration template struct MccMountConfig { static constexpr MccMountType mountType = MOUNT_TYPE; virtual ~MccMountConfig() = default; // astrom::MccLeapSeconds leapSeconds; // astrom::MccIersBulletinA iersBulletinA; MccMountSiteInfo siteInfo{.latitude = 0.0, .longitude = 0.0, .elevation = 0.0, .name{"ALL-ZERO"}}; // template // auto update(this auto&& self, CompCtorArgTs... comp_ctor_args) // { // return std::forward(self).updateImpl(std::forward(comp_ctor_args)...); // } }; namespace traits { // given mount configuration class must be a descendant of MccMountConfig template concept mcc_mountconfig_c = requires(T t) { [](MccMountConfig*) {}(&t); }; } // namespace traits template MOUNT_TELEMETRY> class MccMount : public fsm::MccFiniteStateMachine, public utils::MccSpdlogLogger { public: static constexpr auto mountType = MOUNT_CONFIG::mountType; typedef MOUNT_CONFIG mount_config_t; typedef MOUNT_TELEMETRY mount_telemetry_t; struct slew_param_t { MccCoordPairKind kind; // input coordinates type MccAngle x; // co-longitude (e.g. RA or Az) MccAngle y; // co-latitude (e.g. DEC or ZD) bool stop; // stop after slewing }; /* constructors and destructor */ template MccMount(InitStateT, std::shared_ptr logger = spdlog::null_logger_mt("NULL"), const LogMarkT& logger_mark = "[MOUNT]") : fsm::MccFiniteStateMachine(InitStateT{}), utils::MccSpdlogLogger(logger) { addMarkToPatternIdx(logger_mark); logDebug("Create MccMount class instance: thread = {}", getThreadId()); auto ids = this->stateIDs(); auto r = ids | std::views::join_with(','); logDebug("{}", std::string(r.begin(), r.end())); } virtual ~MccMount() { logDebug("Delete MccMount class instance: thread = {}", getThreadId()); } /* public methods */ void initMount() { this->logInfo("STATE: {}", this->currentStateID()); } void stopMount() {} void shutdownMount() {} void slewMount(slew_param_t params) {} void startGuiding() {} mount_config_t mountConfig() const { return _mountConfig; // return _mountConfig.load(); } mount_telemetry_t mountTelemetry() const { return _mountTelemetry; // return _mountTelemetry.load(); } /* prohibited zone related public methods */ template ZT, std::derived_from... ZTs> size_t pzAddZone(ZT zone, ZTs... zones) { static constexpr auto pi2 = std::numbers::pi / 2.0; _pzRequestFunc.emplace_back([zone = std::move(zone), this]() { mount_telemetry_t data = _mountTelemetry.load(); if constexpr (ZT::preferedCoordKind == MccCoordPairKind::COORDS_KIND_AZALT) { return zone.request(MccAngleAZ(data.tagAZ), MccAngleALT(pi2 - data.tagZD)); } else if constexpr (ZT::preferedCoordKind == MccCoordPairKind::COORDS_KIND_AZZD) { return zone.request(MccAngleAZ(data.tagAZ), MccAngleZD(data.tagZD)); } else if constexpr (ZT::preferedCoordKind == MccCoordPairKind::COORDS_KIND_RADEC_APP) { return zone.request(MccAngleRA_APP(data.tagRA), MccAngleDEC_APP(data.tagDEC)); } else if constexpr (ZT::preferedCoordKind == MccCoordPairKind::COORDS_KIND_HADEC_APP) { return zone.request(MccAngleHA_APP(data.tagHA), MccAngleDEC_APP(data.tagDEC)); } else if constexpr (ZT::preferedCoordKind == MccCoordPairKind::COORDS_KIND_RADEC_ICRS) { return zone.request(MccAngleRA_APP(data.tagRA), MccAngleDEC_APP(data.tagDEC)); } else if constexpr (ZT::preferedCoordKind == MccCoordPairKind::COORDS_KIND_XY) { return zone.request(MccAngleX(data.mntPosX), MccAngleY(data.mntPosY)); } else { static_assert(false, "UNKNOWN COORDINATE SYSTEM!!!"); } }); if constexpr (sizeof...(ZTs)) { psAddZone(std::move(zones)...); } return _pzRequestFunc.size(); } void pzClearZone() { _pzRequestFunc.clear(); } protected: // std::atomic _mountConfig; // std::atomic _mountTelemetry; mount_config_t _mountConfig; mount_telemetry_t _mountTelemetry; typedef std::chrono::duration pz_duration_t; std::vector> _pzRequestFunc{}; }; // 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 mcc