297 lines
11 KiB
C++
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
|