#pragma once /* MOUNT CONTROL COMPONENTS LIBRARY */ #include #include #include #include #include #include #include #include "spdlog/sinks/null_sink.h" #include "mcc_spdlog.h" #include "mount_astrom.h" #include "mount_astrom_default.h" // low-level functions namespace lowlevel { #include "../LibSidServo/sidservo.h" } // namespace lowlevel namespace mcc { namespace traits { // mount state type concept template concept mcc_mount_state_c = requires(T t, const T t_const) { { t_const.ident() } -> std::same_as; { t.enter() } -> std::same_as; { t.exit() } -> std::same_as; }; } // namespace traits /* SOME BASIC DATA STRUCTURES 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 % press_t pressure; // atmospheric presure in hPa=mB }; // mount current position and related quantities struct MccMountPosition { 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; // encoder-measured current mount coordinates (in radians) mnt_coord_t mntRA, mntDEC; mnt_coord_t mntHA; mnt_coord_t mntAZ, mntZD; // encoder-measured current mount moving speed (in radians/s) mnt_speed_t mntSpeedX, mntSpeedY; // X - HA, Y - DEC for equatorial-type mount; X - AZ, Y - ZD for horizontal-type one // current refraction coefficient mnt_coord_t currRefr; // PCS (pointing correction system) corrections mnt_coord_t pcsX, pcsY; // X - HA, Y - DEC for equatorial-type mount; X - AZ, Y - ZD for horizontal-type one }; /* MOUNT BASE TEMPLATED CLASS WITH BASIC FUNCTIONALITY */ enum class MccMountType : uint8_t { GERMAN_TYPE, FORK_TYPE, CROSSAXIS_TYPE, ALTAZ_TYPE }; // implements a Finite State Machine Pattern template class MccMount : public utils::MccSpdlogLogger { typedef double mnt_coord_t; typedef double mnt_speed_t; typedef double time_point_t; public: static constexpr MccMountType mountType = MOUNT_TYPE; /* mount main-cycle variable quantities (mount orientation) */ struct mount_orient_t { // time-related std::chrono::system_clock::time_point utc; time_point_t mjd; // modified Julian date 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; // encoder-measured current mount coordinates (in radians) mnt_coord_t mntRA, mntDEC; mnt_coord_t mntHA; mnt_coord_t mntAZ, mntZD; // encoder-measured current mount moving speed (in radians/s) mnt_speed_t mntSpeedX, mntSpeedY; // X - HA, Y - DEC for equatorial-type mount; X - AZ, Y - ZD for horizontal-type one // current refraction coefficient mnt_coord_t currRefr; // PCS (pointing correction system) corrections mnt_coord_t pcsX, pcsY; // X - HA, Y - DEC for equatorial-type mount; X - AZ, Y - ZD for horizontal-type one // mount current state }; struct mount_config_t { std::string leap_seconds_filename{}; // empty to use hardcoded default value! std::string earth_orient_filename{}; // empty to use hardcoded default value! }; /* Constructors and destructor */ MccMount(traits::mcc_input_char_range auto const& logger_mark = "[MOUNT]", std::shared_ptr logger = spdlog::null_logger_mt("NULL")) : utils::MccSpdlogLogger(logger), _exitCurrentState([]() {}) { std::istringstream strst; addMarkToPatternIdx(logger_mark); logDebug("Create MccMount class instance: thread = {}", getThreadId()); logInfo("Load leap seconds and Earth orientation databases ..."); auto time_db_loader = [this](const std::string& filename, std::string_view type, auto& db) { if (filename.empty()) { logWarn("An empty {} filename! Skip and keep default values!", type); return; } bool ok = db.load(filename); if (!ok) { logError("CANNOT parse {} file '{}' or it is not accessable!", type, filename); logWarn("Keep {} database in default state!", type); } else { logInfo("{} database was successfully loaded from '{}' file", type, filename); } }; time_db_loader(_mountCurrentConfig.leap_seconds_filename, "leap seconds", _leapSecondsDB); time_db_loader(_mountCurrentConfig.earth_orient_filename, "Earth orientation", _earthOrientDB); } virtual ~MccMount() { logDebug("Delete MccMount class instance: thread = {}", getThreadId()); } /* Public methods */ template void setMountState(StateT& state) { _exitCurrentState(); // exit from current state _exitCurrentState = [&state]() { state.exit(); }; state.enter(); } mount_orient_t getMountData() const noexcept { return _currentMountOrient.load(); } void setMeteo(std::derived_from auto const& meteo) { _currentMeteo.store(meteo); } protected: mount_config_t _mountCurrentConfig; // std::shared_ptr _mountLogger; std::function _exitCurrentState; // time scales related databases astrom::MccLeapSeconds _leapSecondsDB; astrom::MccIersBulletinA _earthOrientDB; std::atomic _currentMountOrient; std::atomic _currentMeteo; }; } // namespace mcc