#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" #include "mcc_mount_concepts.h" namespace mcc { // mount configuration template struct MccMountConfig { static constexpr MccMountType mountType = MOUNT_TYPE; virtual ~MccMountConfig() = default; }; 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 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; typedef typename mount_telemetry_t::mount_telemetry_data_t mount_telemetry_data_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; } mount_telemetry_data_t mountTelemetry() const { return _mountTelemetry.data(); } /* prohibited zone related public methods */ // add zones to mount control system template size_t pzAddZone(ZT zone, ZTs... zones) { static constexpr auto pi2 = std::numbers::pi / 2.0; auto zone_ptr = std::make_shared(std::move(zone)); // typename ZT::coord_t x, y; if constexpr (ZT::preferedCoordKind == MccCoordPairKind::COORDS_KIND_AZALT) { // azimuth and altitude _pzFuncs.emplace_back({.coordPairKind = ZT::preferedCoordKind, .inZoneFunc = [zone_ptr, this]() { auto tmry_data = _mountTelemetry.data(); return zone_ptr->inZone(tmry_data.mntAZ, tmry_data.mntALT, tmry_data.utc); }, .timeToFunc = [zone_ptr, this]() { auto tmry_data = _mountTelemetry.data(); return zone_ptr->timeTo(tmry_data.mntAZ, tmry_data.mntALT, tmry_data.utc); }, .timeFromFunc = [zone_ptr, this]() { auto tmry_data = _mountTelemetry.data(); return zone_ptr->timeFrom(tmry_data.mntAZ, tmry_data.mntALT, tmry_data.utc); }}); } else if constexpr (ZT::preferedCoordKind == MccCoordPairKind::COORDS_KIND_AZZD) { // azimuth and zenithal distance _pzFuncs.emplace_back( {.coordPairKind = ZT::preferedCoordKind, .inZoneFunc = [zone_ptr, this]() { auto tmry_data = _mountTelemetry.data(); return zone_ptr->inZone(tmry_data.mntAZ, pi2 - tmry_data.mntALT, tmry_data.utc); }, .timeToFunc = [zone_ptr, this]() { auto tmry_data = _mountTelemetry.data(); return zone_ptr->timeTo(tmry_data.mntAZ, pi2 - tmry_data.mntALT, tmry_data.utc); }, .timeFromFunc = [zone_ptr, this]() { auto tmry_data = _mountTelemetry.data(); return zone_ptr->timeFrom(tmry_data.mntAZ, pi2 - tmry_data.mntALT, tmry_data.utc); }}); } else if constexpr (ZT::preferedCoordKind == MccCoordPairKind::COORDS_KIND_RADEC_APP) { } else if constexpr (ZT::preferedCoordKind == MccCoordPairKind::COORDS_KIND_HADEC_APP) { } else if constexpr (ZT::preferedCoordKind == MccCoordPairKind::COORDS_KIND_RADEC_ICRS) { } else if constexpr (ZT::preferedCoordKind == MccCoordPairKind::COORDS_KIND_XY) { } else { static_assert(false, "UNKNOWN COORDINATE SYSTEM!!!"); } if constexpr (sizeof...(ZTs)) { pzAddZone(std::move(zones)...); } return _pzFuncs.size(); } // delete all zones from mount control system void pzClearZone() { _pzFuncs.clear(); } template XT, std::derived_from YT> auto pzInZone(const XT& x, const YT& y, traits::mcc_time_duration_c auto const& utc) { } protected: mount_config_t _mountConfig; mount_telemetry_t _mountTelemetry; // a type to which the result of calling prohibited zone class methods 'timeTo' and 'timeFrom' will be converted typedef std::chrono::duration pz_duration_t; // seconds as floating-point number typedef std::function pz_inzone_func_t; typedef std::function pz_timeto_func_t; typedef std::function pz_timefrom_func_t; struct pz_funcs_t { MccCoordPairKind coordPairKind; pz_inzone_func_t inZoneFunc; pz_timeto_func_t timeToFunc; pz_timefrom_func_t timeFromFunc; }; std::vector _pzFuncs{}; }; // 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