#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_coord.h" #include "mcc_finite_state_machine.h" #include "mcc_spdlog.h" #include "mcc_traits.h" #include "mount_astrom.h" #include "mount_pz.h" namespace mcc { /* BASIC DATA DEFINITIONS */ // coordinate system related constants enum class MccCoordKind : uint8_t { COORDS_KIND_RA_IRCS, // IRCS right ascension COORDS_KIND_RA_APP, // apparent right ascension COORDS_KIND_HA, // hour angle COORDS_KIND_AZ, // azimuth COORDS_KIND_X, // co-longitude coordinate COORDS_KIND_DEC_IRCS, // IRCS declination COORDS_KIND_DEC_APP, // apparent declination COORDS_KIND_ALT, // altitude COORDS_KIND_ZD, // zenithal distance COORDS_KIND_Y // co-latitude coordinate }; enum class MccCoordPairKind : uint16_t { // catalog's COORDS_KIND_RADEC_IRCS = (int)MccCoordKind::COORDS_KIND_RA_IRCS + ((int)MccCoordKind::COORDS_KIND_DEC_IRCS << 8), // apparent RA and DEC COORDS_KIND_RADEC_APP = (int)MccCoordKind::COORDS_KIND_RA_APP + ((int)MccCoordKind::COORDS_KIND_DEC_APP << 8), // apparent HA (hour angle) and DEC COORDS_KIND_HADEC_APP = (int)MccCoordKind::COORDS_KIND_HA + ((int)MccCoordKind::COORDS_KIND_DEC_APP << 8), // Azimuth and Altitude COORDS_KIND_AZALT = (int)MccCoordKind::COORDS_KIND_AZ + ((int)MccCoordKind::COORDS_KIND_ALT << 8), // Azimuth and Zenithal distance COORDS_KIND_AZZD = (int)MccCoordKind::COORDS_KIND_AZ + ((int)MccCoordKind::COORDS_KIND_ZD << 8), // co-longitude and co-latitude (e.g. mount hardware drive/axis encoders) COORDS_KIND_XY = (int)MccCoordKind::COORDS_KIND_X + ((int)MccCoordKind::COORDS_KIND_Y << 8), }; template static constexpr std::string_view MccCoordPairKindStr = KIND == MccCoordPairKind::COORDS_KIND_RADEC_IRCS ? "RADEC-IRCS" : KIND == MccCoordPairKind::COORDS_KIND_RADEC_APP ? "RADEC-APP" : KIND == MccCoordPairKind::COORDS_KIND_HADEC_APP ? "HADEC-APP" : KIND == MccCoordPairKind::COORDS_KIND_AZALT ? "Azimuth-Altitude" : KIND == MccCoordPairKind::COORDS_KIND_AZZD ? "AzimuthZendist" : KIND == MccCoordPairKind::COORDS_KIND_XY ? "XY" : "UNKNOWN"; // 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, traits::mcc_input_char_range auto const& logger_mark = "[MOUNT]", std::shared_ptr logger = spdlog::null_logger_mt("NULL")) : fsm::MccFiniteStateMachine(InitStateT{}), utils::MccSpdlogLogger(logger) { addMarkToPatternIdx(logger_mark); logDebug("Create MccMount class instance: thread = {}", getThreadId()); } virtual ~MccMount() { logDebug("Delete MccMount class instance: thread = {}", getThreadId()); } /* public methods */ void initMount() {} void stopMount() {} void shutdownMount() {} void slewMount(slew_param_t params) {} void startGuiding() {} mount_config_t mountConfig() const { return _mountConfig.load(); } mount_telemetry_t mountTelemetry() const { return _mountTelemetry.load(); } /* prohibited zone related public methods */ template size_t pzAddZone(ZT zone, ZTs... zones) { _pzInZoneFunc.emplace_back([zone = std::move(zone)](const MccAngle& x, const MccAngle& y, void* ctx) mutable { auto context = *static_cast(ctx); return zone.inZone(x, y, context); }); if constexpr (sizeof...(ZTs)) { psAddZone(std::move(zones)...); } return _pzInZoneFunc.size(); } void pzClearZone() { _pzInZoneFunc.clear(); } protected: std::atomic _mountConfig; std::atomic _mountTelemetry; typedef std::chrono::duration pz_duration_t; std::vector> _pzInZoneFunc; std::vector> _pzTimeToZoneFunc; std::vector> _pzTimeFromZoneFunc; }; // 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