#pragma once /* MOUNT CONTROL COMPONENTS LIBRARY */ /* IMPLEMENTATION OF TELEMETRY CLASS */ #include "mcc_defaults.h" namespace mcc { static constexpr double mcc_sideral_to_UT1_ratio = 1.002737909350795; // sideral/UT1 enum MccTelemetryErrorCode : int { ERROR_OK, ERROR_COORD_TRANSFROM, ERROR_PCM_COMP }; } // namespace mcc namespace std { template <> class is_error_code_enum : public true_type { }; } // namespace std namespace mcc { /* error category definition */ // error category struct MccTelemetryCategory : public std::error_category { MccTelemetryCategory() : std::error_category() {} const char* name() const noexcept { return "ALTITUDE-LIMIT-PZ"; } std::string message(int ec) const { MccTelemetryErrorCode err = static_cast(ec); switch (err) { case MccTelemetryErrorCode::ERROR_OK: return "OK"; case MccTelemetryErrorCode::ERROR_COORD_TRANSFROM: return "coordinate transformation error"; case MccTelemetryErrorCode::ERROR_PCM_COMP: return "PCM computation error"; default: return "UNKNOWN"; } } static const MccTelemetryCategory& get() { static const MccTelemetryCategory constInst; return constInst; } }; inline std::error_code make_error_code(MccTelemetryErrorCode ec) { return std::error_code(static_cast(ec), MccTelemetryCategory::get()); } /* TELEMETRY UPDATE POLICY */ enum class MccTelemetryUpdatePolicy : int { TEMETRY_UPDATE_INNER, TEMETRY_UPDATE_EXTERNAL }; template class MccTelemetry : public mcc_telemetry_interface_t { public: static constexpr MccTelemetryUpdatePolicy updatePolicy = UPDATE_POLICY; typedef std::error_code error_t; MccTelemetry(mcc_ccte_c auto* ccte, mcc_PCM_c auto* pcm, mcc_hardware_c auto* hardware) { using ccte_t = std::remove_cvref_t; using pcm_t = std::remove_cvref_t; using hardware_t = std::remove_cvref_t; _updateFunc = [ccte, pcm, hardware, this](MccTelemetryData* data) { typename hardware_t::axes_pos_t hw_pos; auto hw_err = hardware->getPos(&hw_pos); if (!hw_err) { data->time_point = std::chrono::time_point_casttime_point)::duration>(hw_pos.time_point); auto ccte_err = ccte->timepointToJulday(data->time_point, &data->JD); if (!ccte_err) { ccte_err = ccte->timepointToAppSideral(data->time_point, &data->LST, true); if (!ccte_err) { data->speedX = (double)hw_pos.speedX; data->speedY = (double)hw_pos.speedY; struct { double dx, dy; } pcm_res; auto pcm_err = pcm->computePCM(data, &pcm_res); if (pcm_err) { if constexpr (std::same_as) { return pcm_err; } else { return MccTelemetryErrorCode::ERROR_PCM_COMP; } } MccCelestialPoint pt{.pair_kind = MccCoordPairKind::COORDS_KIND_AZALT, .time_point = data->time_point}; if constexpr (mccIsEquatorialMount(pcm_t::mountType)) { data->HA = (double)hw_pos.X + pcm_res.dx; data->DEC_APP = (double)hw_pos.Y + pcm_res.dy; data->X = data->HA; data->Y = data->DEC_APP; data->pair_kind = MccCoordPairKind::COORDS_KIND_HADEC_APP; ccte_err = ccte->transformCoordinates(*data, &pt); if (!ccte_err) { data->AZ = pt.X; data->ALT = pt.Y; data->ZD = std::numbers::pi / 2.0 - data->ALT; } } else if constexpr (mccIsAltAzMount(pcm_t::mountType)) { data->AZ = (double)hw_pos.X + pcm_res.dx; data->ALT = (double)hw_pos.Y + pcm_res.dy; data->ZD = std::numbers::pi / 2.0 - data->ALT; data->X = data->AZ; data->Y = data->ALT; data->pair_kind = MccCoordPairKind::COORDS_KIND_AZALT; pt.pair_kind = MccCoordPairKind::COORDS_KIND_HADEC_APP; ccte_err = ccte->transformCoordinates(*data, &pt); if (!ccte) { data->HA = pt.X; data->DEC_APP = pt.Y; } } else { static_assert(false, "UNKNOWN MOUNT TYPE!"); } } } } }; } error_t telemetryData(mcc_telemetry_data_c auto* data) { error_t ret = MccTelemetryErrorCode::ERROR_OK; // first, update mount coordinates return ret; } error_t setPointingTarget(mcc_celestial_point_c auto pt) {} protected: std::function _updateFunc; }; } // namespace mcc