mountcontrol/cxx/mcc_mount_telemetry_astrom.h
2025-07-24 18:55:59 +03:00

297 lines
11 KiB
C++

#pragma once
/* MOUNT CONTROL COMPONENTS LIBRARY */
/* VARIUOS ASTROMETRIC TRANSFORMATIONS FOR TELEMETRY */
#include "mcc_mount_concepts.h"
namespace mcc
{
template <traits::mcc_astrom_engine_c ASTROM_ENGINE_T, traits::mcc_mount_pec_c PEC_T>
class MccMountTelemetryAstromTransform
{
static typename ASTROM_ENGINE_T::coord_t dummyCoord{};
public:
// deduce mount type
static constexpr bool equatorialMount = mccIsEquatorialMount(PEC_T::mountType);
static constexpr bool altAzMount = mccIsAltAzMount(PEC_T::mountType);
typedef ASTROM_ENGINE_T astrom_engine_t;
typedef PEC_T pec_t;
typedef typename astrom_engine_t::coord_t coord_t;
typedef std::error_code error_t;
MccMountTelemetryAstromTransform(astrom_engine_t& astrom_engine, pec_t& pec)
: _astromEngine(astrom_engine), _pec(pec)
{
}
virtual ~MccMountTelemetryAstromTransform() = default;
template <traits::mcc_celestial_point_c CT>
error_t toApparent(CT coord,
astrom_engine_t::time_point_t time_point,
coord_t& X_app,
coord_t& Y_app,
coord_t& XX_app = dummyCoord)
{
typedef typename astrom_engine_t::jd_t jd_t;
jd_t jd;
typedef typename astrom_engine_t::eo_t eo_t;
eo_t eo;
typedef typename astrom_engine_t::sideral_time_t sideral_time_t;
sideral_time_t lst;
typename astrom_engine_t::error_t ast_err;
typename pec_t::error_t pec_err;
auto get_jd_lst_eo = [&time_point, this](jd_t& jd, sideral_time_t& lst, eo_t& eo) {
auto ast_err = _astromEngine.greg2jul(time_point, jd);
if (!ast_err) {
ast_err = _astromEngine.apparentSiderTime(jd, lst, true);
if (!ast_err) {
ast_err = _astromEngine->eqOrigins(jd, eo);
}
}
return ast_err;
};
if (coord.coordPairKind == MccCoordPairKind::COORDS_KIND_XY) { // from encoder's
typename pec_t::pec_result_t pec_res;
pec_err = _pec.compute(coord.x, coord.y, pec_res);
if (!pec_err) {
X_app = coord.x + pec_res.dx;
Y_app = coord.y + pec_res.dy;
}
} else if (coord.coordPairKind == MccCoordPairKind::COORDS_KIND_RADEC_APP) { // from app RA-DEC
coord_t HA;
// logDebug("Input slew coordinates are apparent RA-DEC: convert it to apparent HA-DEC ...");
ast_err = get_jd_lst_eo(jd, lst, eo);
if (!ast_err) {
HA = lst - coord.x + eo; // HA = LST - RA_APP + EO
if constexpr (equatorialMount) { // compute HA (as XX_app)
X_app = coord.x;
Y_app = coord.y;
XX_app = HA;
} else if constexpr (altAzMount) {
ast_err = _astromEngine.hadec2azalt(HA, coord.y, X_app, Y_app);
} else {
static_assert(false, "UNSUPPORTED MOUNT TYPE!");
}
}
} else if (coord.coordPairKind == MccCoordPairKind::COORDS_KIND_HADEC_APP) { // from app HA-DEC
ast_err = get_jd_lst_eo(jd, lst, eo);
if (!ast_err) {
if constexpr (equatorialMount) { // compute CIO RA (as XX_app)
X_app = coord.x;
Y_app = coord.y;
XX_app = lst - coord.x + eo;
} else if constexpr (altAzMount) {
ast_err = _astromEngine.hadec2azalt(coord.x, coord.y, X_app, Y_app);
} else {
static_assert(false, "UNSUPPORTED MOUNT TYPE!");
}
}
} else if (coord.coordPairKind == MccCoordPairKind::COORDS_KIND_AZALT) { // from app AZ-ALT
if constexpr (equatorialMount) {
ast_err = azalt2hadec(coord.x, coord.y, X_app, Y_app); // compute HA-DEC
if (!ast_err) { // compute CIO RA (as XX_app)
ast_err = toApparent(X_app, Y_app, X_app, Y_app, XX_app);
}
} else if (altAzMount) {
X_app = coord.x;
Y_app = coord.y;
} else {
static_assert(false, "UNSUPPORTED MOUNT TYPE!");
}
} else if (coord.coordPairKind == MccCoordPairKind::COORDS_KIND_AZZD) { // from app AZ-ZD
coord.coordPairKind == MccCoordPairKind::COORDS_KIND_AZALT;
coord.y = std::numbers::pi / 2.0 - coord.y;
ast_err = toApparent(std::move(coord), std::move(time_point), X_app, Y_app, XX_app);
} else if (coord.coordPairKind == MccCoordPairKind::COORDS_KIND_RADEC_ICRS) { // from ICRS RA-DEC
coord_t az, alt;
eo_t eo;
// for equatorial mount:
// X_app = RA_app, Y_app = DEC_app, XX_app = HA_app
// for alt-azimuthal mount:
// X_app = AZ, Y_app = ALT
ast_err = _astromEngine.greg2jul(time_point, jd);
if (!ast_err) {
ast_err = _astromEngine.icrs2obs(coord.x, coord.y, jd, X_app, Y_app, XX_app, az, alt, eo);
if (!ast_err) {
if constexpr (equatorialMount) {
// nothing to do
} else if (altAzMount) {
X_app = az;
Y_app = alt;
} else {
static_assert(false, "UNSUPPORTED MOUNT TYPE!");
}
}
}
} else {
return std::make_error_code(std::errc::operation_canceled);
}
if (pec_err) {
if constexpr (std::same_as<decltype(pec_err), error_t>) {
return pec_err;
} else {
return std::make_error_code(std::errc::operation_canceled);
}
}
if (ast_err) {
if constexpr (std::same_as<decltype(ast_err), error_t>) {
return ast_err;
} else {
return std::make_error_code(std::errc::operation_canceled);
}
}
return {};
}
template <traits::mcc_celestial_point_c CT>
error_t toICRS(CT coord, astrom_engine_t::time_point_t time_point, coord_t& RA, coord_t& DEC)
{
typename astrom_engine_t::error_t ast_err;
typename pec_t::error_t pec_err;
if (coord.coordPairKind == MccCoordPairKind::COORDS_KIND_XY) { // from encoder's
typename pec_t::pec_result_t pec_res;
pec_err = _pec.compute(coord.x, coord.y, pec_res);
if (!pec_err) {
coord.x += pec_res.dx;
coord.y += pec_res.dy;
if constexpr (equatorialMount) {
coord.coordPairKind = MccCoordPairKind::COORDS_KIND_HADEC_APP;
} else if constexpr (altAzMount) {
coord.coordPairKind = MccCoordPairKind::COORDS_KIND_AZALT;
} else {
static_assert(false, "UNSUPPORTED MOUNT TYPE!");
}
ast_err = toICRS(std::move(coord), std::move(time_point), RA, DEC);
}
} else if (coord.coordPairKind == MccCoordPairKind::COORDS_KIND_RADEC_APP) { // from app RA-DEC
} else if (coord.coordPairKind == MccCoordPairKind::COORDS_KIND_HADEC_APP) { // from app HA-DEC
} else if (coord.coordPairKind == MccCoordPairKind::COORDS_KIND_AZALT) { // from app AZ-ALT
} else if (coord.coordPairKind == MccCoordPairKind::COORDS_KIND_AZZD) { // from app AZ-ZD
coord.coordPairKind == MccCoordPairKind::COORDS_KIND_AZALT;
coord.y = std::numbers::pi / 2.0 - coord.y;
ast_err = toICRS(std::move(coord), std::move(time_point), RA, DEC);
} else if (coord.coordPairKind == MccCoordPairKind::COORDS_KIND_RADEC_ICRS) { // from ICRS RA-DEC
RA = coord.x;
DEC = coord.y;
return {};
} else {
return std::make_error_code(std::errc::operation_canceled);
}
if (coord.coordPairKind != MccCoordPairKind::COORDS_KIND_RADEC_ICRS) {
typename astrom_engine_t::jd_t jd;
ast_err = _astromEngine.greg2jul(astrom_engine_t::timePointNow(), jd);
if (!ast_err) {
ast_err = _astromEngine.obs2icrs(coord.coordPairKind, coord.x, coord.y, jd, RA, DEC);
}
}
if (pec_err) {
if constexpr (std::same_as<decltype(pec_err), error_t>) {
return pec_err;
} else {
return std::make_error_code(std::errc::operation_canceled);
}
}
if (ast_err) {
if constexpr (std::same_as<decltype(ast_err), error_t>) {
return ast_err;
} else {
return std::make_error_code(std::errc::operation_canceled);
}
}
return {};
}
template <traits::mcc_celestial_point_c CT>
error_t toHardware(CT coord, astrom_engine_t::time_point_t time_point, coord_t& X, coord_t& Y)
{
typename astrom_engine_t::error_t ast_err;
typename pec_t::error_t pec_err;
if (coord.coordPairKind == MccCoordPairKind::COORDS_KIND_XY) { // from encoder's
X = coord.x;
Y = coord.y;
return {};
} else if (coord.coordPairKind == MccCoordPairKind::COORDS_KIND_RADEC_APP) { // from app RA-DEC
} else if (coord.coordPairKind == MccCoordPairKind::COORDS_KIND_HADEC_APP) { // from app HA-DEC
} else if (coord.coordPairKind == MccCoordPairKind::COORDS_KIND_AZALT) { // from app AZ-ALT
} else if (coord.coordPairKind == MccCoordPairKind::COORDS_KIND_AZZD) { // from app AZ-ZD
coord.coordPairKind == MccCoordPairKind::COORDS_KIND_AZALT;
coord.y = std::numbers::pi / 2.0 - coord.y;
ast_err = toICRS(std::move(coord), std::move(time_point), X, Y);
} else if (coord.coordPairKind == MccCoordPairKind::COORDS_KIND_RADEC_ICRS) { // from ICRS RA-DEC
} else {
return std::make_error_code(std::errc::operation_canceled);
}
if (pec_err) {
if constexpr (std::same_as<decltype(pec_err), error_t>) {
return pec_err;
} else {
return std::make_error_code(std::errc::operation_canceled);
}
}
if (ast_err) {
if constexpr (std::same_as<decltype(ast_err), error_t>) {
return ast_err;
} else {
return std::make_error_code(std::errc::operation_canceled);
}
}
return {};
}
protected:
astrom_engine_t& _astromEngine;
pec_t& _pec;
};
} // namespace mcc