This commit is contained in:
Timur A. Fatkhullin 2025-07-21 00:33:06 +03:00
parent 9cd52267d6
commit 6d65efd0af
6 changed files with 323 additions and 181 deletions

View File

@ -10,40 +10,13 @@
#include "mcc_astrom_iers.h"
#include "mcc_mount_concepts.h"
#include "mcc_mount_coord.h"
// #include "mcc_mount_astrom.h"
#include "mcc_mount_concepts.h"
namespace mcc::astrom::erfa
{
#include <erfa.h>
#include <erfam.h>
/* A concept for ERFA-library compatible type to represent anglular quantities */
template <typename T>
concept mcc_erfa_angle_t = std::constructible_from<T, double> && std::convertible_to<T, double>;
template <mcc_erfa_angle_t AngleT = MccAngle>
class MccMountAstromEngineERFA
{
protected:
static constexpr std::array engineErrorString = {"OK",
"invalid argument",
"invalid year",
"invalid month",
"time point is out of range",
"time point is out of range",
"dubious year",
"unacceptable year",
"leap seconds update error",
"bulletin A update error"};
public:
static constexpr double DEFAULT_WAVELENGTH = 0.55; // default observed wavelength in mkm
enum error_t : size_t {
enum class MccMountAstromEngineERFAErrorCode : int {
ERROR_OK = 0,
ERROR_INVALID_INPUT_ARG,
ERROR_JULDATE_INVALID_YEAR,
@ -54,7 +27,97 @@ public:
ERROR_UNACCEPTABLE_DATE,
ERROR_UPDATE_LEAPSECONDS,
ERROR_UPDATE_BULLETINA,
};
};
}
namespace std
{
template <>
class is_error_code_enum<mcc::astrom::erfa::MccMountAstromEngineERFAErrorCode> : public true_type
{
};
} // namespace std
namespace mcc::astrom::erfa
{
#include <erfa.h>
#include <erfam.h>
/* error category definition */
// error category
struct MccMountAstromEngineERFACategory : public std::error_category {
MccMountAstromEngineERFACategory() : std::error_category() {}
const char* name() const noexcept
{
return "ADC_GENERIC_DEVICE";
}
std::string message(int ec) const
{
MccMountAstromEngineERFAErrorCode err = static_cast<MccMountAstromEngineERFAErrorCode>(ec);
switch (err) {
case MccMountAstromEngineERFAErrorCode::ERROR_OK:
return "OK";
case MccMountAstromEngineERFAErrorCode::ERROR_INVALID_INPUT_ARG:
return "invalid argument";
case MccMountAstromEngineERFAErrorCode::ERROR_JULDATE_INVALID_YEAR:
return "invalid year number";
case MccMountAstromEngineERFAErrorCode::ERROR_JULDATE_INVALID_MONTH:
return "invalid month number";
case MccMountAstromEngineERFAErrorCode::ERROR_BULLETINA_OUT_OF_RANGE:
return "time point is out of range";
case MccMountAstromEngineERFAErrorCode::ERROR_LEAPSECONDS_OUT_OF_RANGE:
return "time point is out of range";
case MccMountAstromEngineERFAErrorCode::ERROR_DUBIOUS_YEAR:
return "dubious year";
case MccMountAstromEngineERFAErrorCode::ERROR_UNACCEPTABLE_DATE:
return "unacceptable date";
case MccMountAstromEngineERFAErrorCode::ERROR_UPDATE_LEAPSECONDS:
return "leap seconds update error";
case MccMountAstromEngineERFAErrorCode::ERROR_UPDATE_BULLETINA:
return "bulletin A update error";
default:
return "UNKNOWN";
}
}
static const MccMountAstromEngineERFACategory& get()
{
static const MccMountAstromEngineERFACategory constInst;
return constInst;
}
};
inline std::error_code make_error_code(MccMountAstromEngineERFAErrorCode ec)
{
return std::error_code(static_cast<int>(ec), MccMountAstromEngineERFACategory::get());
}
/* A concept for ERFA-library compatible type to represent anglular quantities */
template <typename T>
concept mcc_erfa_angle_t = std::constructible_from<T, double> && std::convertible_to<T, double>;
template <mcc_erfa_angle_t AngleT = MccAngle>
class MccMountAstromEngineERFA
{
public:
static constexpr double DEFAULT_WAVELENGTH = 0.55; // default observed wavelength in mkm
typedef std::error_code error_t;
// meteo parameters (to compute refraction)
@ -140,10 +203,10 @@ public:
std::lock_guard lock{_stateMutex};
if (!_currentState._leapSeconds.load(stream, comment_sym)) {
return ERROR_UPDATE_LEAPSECONDS;
return MccMountAstromEngineERFAErrorCode::ERROR_UPDATE_LEAPSECONDS;
}
return ERROR_OK;
return MccMountAstromEngineERFAErrorCode::ERROR_OK;
}
@ -152,10 +215,10 @@ public:
std::lock_guard lock{_stateMutex};
if (!_currentState._leapSeconds.load(filename, comment_sym)) {
return ERROR_UPDATE_LEAPSECONDS;
return MccMountAstromEngineERFAErrorCode::ERROR_UPDATE_LEAPSECONDS;
}
return ERROR_OK;
return MccMountAstromEngineERFAErrorCode::ERROR_OK;
}
@ -164,10 +227,10 @@ public:
std::lock_guard lock{_stateMutex};
if (!_currentState._bulletinA.load(stream, comment_sym)) {
return ERROR_UPDATE_BULLETINA;
return MccMountAstromEngineERFAErrorCode::ERROR_UPDATE_BULLETINA;
}
return ERROR_OK;
return MccMountAstromEngineERFAErrorCode::ERROR_OK;
}
@ -176,19 +239,13 @@ public:
std::lock_guard lock{_stateMutex};
if (!_currentState._bulletinA.load(filename, comment_sym)) {
return ERROR_UPDATE_BULLETINA;
return MccMountAstromEngineERFAErrorCode::ERROR_UPDATE_BULLETINA;
}
return ERROR_OK;
return MccMountAstromEngineERFAErrorCode::ERROR_OK;
}
std::string errorString(error_t err) const
{
return engineErrorString[err];
}
/* time-related methods */
// templated generic version
@ -203,10 +260,10 @@ public:
static constexpr std::chrono::year MIN_YEAR = -4799y;
if (ymd.year() < MIN_YEAR) {
return ERROR_JULDATE_INVALID_YEAR;
return MccMountAstromEngineERFAErrorCode::ERROR_JULDATE_INVALID_YEAR;
}
if (!ymd.month().ok()) {
return ERROR_JULDATE_INVALID_MONTH;
return MccMountAstromEngineERFAErrorCode::ERROR_JULDATE_INVALID_MONTH;
}
int64_t im = (unsigned)ymd.month();
@ -223,7 +280,7 @@ public:
using fd_t = std::chrono::duration<double, std::ratio<86400>>; // fraction of day
juldate.mjd = static_cast<double>(mjd_int) + std::chrono::duration_cast<fd_t>(time_point - dd).count();
return ERROR_OK;
return MccMountAstromEngineERFAErrorCode::ERROR_OK;
}
error_t greg2jul(time_point_t time_point, juldate_t& juldate)
@ -242,14 +299,14 @@ public:
if (tai_utc.has_value()) {
tt.mjd += std::chrono::duration_cast<real_days_t>(tai_utc.value()).count();
} else {
return ERROR_LEAPSECONDS_OUT_OF_RANGE;
return MccMountAstromEngineERFAErrorCode::ERROR_LEAPSECONDS_OUT_OF_RANGE;
}
auto tt_tai = _currentState._bulletinA.TT_TAI();
tt.mjd = juldate.mjd + std::chrono::duration_cast<real_days_t>(tt_tai).count();
return ERROR_OK;
return MccMountAstromEngineERFAErrorCode::ERROR_OK;
}
@ -270,7 +327,7 @@ public:
if (dut1.has_value()) {
ut1 += std::chrono::duration_cast<real_days_t>(dut1.value()).count();
} else { // out of range
return ERROR_BULLETINA_OUT_OF_RANGE;
return MccMountAstromEngineERFAErrorCode::ERROR_BULLETINA_OUT_OF_RANGE;
}
}
@ -288,7 +345,7 @@ public:
juldate_t tt;
auto err = terrestrialTime(juldate, tt);
if (err != ERROR_OK) {
if (err != MccMountAstromEngineERFAErrorCode::ERROR_OK) {
return err;
}
@ -297,7 +354,7 @@ public:
gst += _currentState.lon;
}
return ERROR_OK;
return MccMountAstromEngineERFAErrorCode::ERROR_OK;
}
@ -306,13 +363,13 @@ public:
juldate_t tt;
auto err = terrestrialTime(juldate, tt);
if (err != ERROR_OK) {
if (err != MccMountAstromEngineERFAErrorCode::ERROR_OK) {
return err;
}
eo = eraEo06a(tt.MJD0, tt.mjd);
return ERROR_OK;
return MccMountAstromEngineERFAErrorCode::ERROR_OK;
}
/* atmospheric refraction-related methods */
@ -324,7 +381,7 @@ public:
eraRefco(_currentState.meteo.pressure, _currentState.meteo.temperature, _currentState.meteo.humidity,
_currentState.wavelength, &refr.refa, &refr.refb);
return ERROR_OK;
return MccMountAstromEngineERFAErrorCode::ERROR_OK;
}
@ -337,7 +394,7 @@ public:
corr = ref_params.refa / tanALT + ref_params.refb / tanALT / tanALT / tanALT;
}
return ERROR_OK;
return MccMountAstromEngineERFAErrorCode::ERROR_OK;
}
/* coordinates conversional methods */
@ -357,12 +414,12 @@ public:
auto dut1 = _currentState._bulletinA.DUT1(juldate.mjd);
if (!dut1.has_value()) {
return ERROR_BULLETINA_OUT_OF_RANGE;
return MccMountAstromEngineERFAErrorCode::ERROR_BULLETINA_OUT_OF_RANGE;
}
auto pol_pos = _currentState._bulletinA.polarCoords(juldate.mjd);
if (!pol_pos.has_value()) {
return ERROR_BULLETINA_OUT_OF_RANGE;
return MccMountAstromEngineERFAErrorCode::ERROR_BULLETINA_OUT_OF_RANGE;
}
const auto arcsec2rad = std::numbers::pi / 180 / 3600;
pol_pos->x *= arcsec2rad;
@ -376,9 +433,9 @@ public:
&oaz, &ozd, &oha, &odec, &ora, &eo_);
if (ret == 1) {
return ERROR_DUBIOUS_YEAR;
return MccMountAstromEngineERFAErrorCode::ERROR_DUBIOUS_YEAR;
} else if (ret == -1) {
return ERROR_UNACCEPTABLE_DATE;
return MccMountAstromEngineERFAErrorCode::ERROR_UNACCEPTABLE_DATE;
}
ra_app = ora;
@ -388,7 +445,7 @@ public:
ha = oha;
eo = eo_;
return ERROR_OK;
return MccMountAstromEngineERFAErrorCode::ERROR_OK;
}
@ -402,7 +459,7 @@ public:
az = r_az;
alt = r_alt;
return ERROR_OK;
return MccMountAstromEngineERFAErrorCode::ERROR_OK;
}
error_t azalt2hadec(coord_t az, coord_t alt, coord_t& ha, coord_t& dec)
@ -416,7 +473,7 @@ public:
ha = r_ha;
dec = r_dec;
return ERROR_OK;
return MccMountAstromEngineERFAErrorCode::ERROR_OK;
}
@ -426,7 +483,7 @@ public:
pa = eraHd2pa(ha, dec, _currentState.lat);
return ERROR_OK;
return MccMountAstromEngineERFAErrorCode::ERROR_OK;
}

View File

@ -97,12 +97,6 @@ concept mcc_astrom_engine_c = requires(T t, const T t_const) {
typename T::refract_result_t;
// { t.setState(std::declval<typename T::engine_state_t>()) };
// { t_const.getState() } -> std::same_as<typename T::engine_state_t>;
{ t_const.errorString(std::declval<typename T::error_t>()) } -> mcc_formattable;
/* coordinates conversional methods */
// ICRS RA and DEC to observed place: icrs2obs(ra, dec, jd, ra_app, dec_app, ha, az, alt, eo)
@ -249,7 +243,7 @@ concept mcc_mount_telemetry_data_c = requires(T telemetry) {
template <typename T>
concept mcc_mount_telemetry_c = requires(T t, const T t_const) {
typename T::error_t;
requires mcc_error_c<typename T::error_t>;
// // a class that at least contains celestial (equatorial and horizontal) coordinates
// requires requires(typename T::mount_telemetry_data_t telemetry) {

View File

@ -12,6 +12,65 @@
#include "mcc_mount_concepts.h"
#include "mcc_mount_coord.h"
namespace mcc
{
enum class MccMountDefaultPECErrorCode : int { ERROR_OK, ERROR_INVALID_INPUTS_BISPLEV, ERROR_EXCEED_MAX_ITERS };
/* error category definition */
// error category
struct MccMountDefaultPECCategory : public std::error_category {
MccMountDefaultPECCategory() : std::error_category() {}
const char* name() const noexcept
{
return "ADC_GENERIC_DEVICE";
}
std::string message(int ec) const
{
MccMountDefaultPECErrorCode err = static_cast<MccMountDefaultPECErrorCode>(ec);
switch (err) {
case MccMountDefaultPECErrorCode::ERROR_OK:
return "OK";
case MccMountDefaultPECErrorCode::ERROR_INVALID_INPUTS_BISPLEV:
return "invalid input arguments for bispev";
case MccMountDefaultPECErrorCode::ERROR_EXCEED_MAX_ITERS:
return "exceed maximum of iterations number";
default:
return "UNKNOWN";
}
}
static const MccMountDefaultPECCategory& get()
{
static const MccMountDefaultPECCategory constInst;
return constInst;
}
};
inline std::error_code make_error_code(MccMountDefaultPECErrorCode ec)
{
return std::error_code(static_cast<int>(ec), MccMountDefaultPECCategory::get());
}
} // namespace mcc
namespace std
{
template <>
class is_error_code_enum<mcc::MccMountDefaultPECErrorCode> : public true_type
{
};
} // namespace std
namespace mcc
{
@ -165,7 +224,7 @@ public:
if (ret) {
res.dx = std::numeric_limits<double>::quiet_NaN();
res.dy = std::numeric_limits<double>::quiet_NaN();
return std::error_code(); // !!!!!!!!!!!!!!
return MccMountDefaultPECErrorCode::ERROR_INVALID_INPUTS_BISPLEV;
}
@ -175,7 +234,7 @@ public:
if (ret) {
res.dx = std::numeric_limits<double>::quiet_NaN();
res.dy = std::numeric_limits<double>::quiet_NaN();
return std::error_code(); // !!!!!!!!!!!!!!
return MccMountDefaultPECErrorCode::ERROR_INVALID_INPUTS_BISPLEV;
}
@ -187,7 +246,7 @@ public:
static_assert(false, "UNSUPPORTED");
}
return std::error_code();
return MccMountDefaultPECErrorCode::ERROR_OK;
}
// from celestial to encoder (use of iterative scheme)
@ -196,35 +255,59 @@ public:
coord_t e2 = eps * eps;
coord_t xi = x, yi = y;
coord_t xp, yp;
coord_t xe, ye;
size_t iter = 1;
// the first iteration
auto err = compute(x, y, res);
if (!err) {
xp = x - res.dx;
yp = y - res.dy;
// 'encoder' cocordinates
xe = x - res.dx;
ye = y - res.dy;
bool ok = ((xp - x) * (xp - x) + (yp - y) * (yp - y)) <= e2;
err = compute(xe, ye, res); // to celestial
if (err) {
return MccMountDefaultPECErrorCode::ERROR_INVALID_INPUTS_BISPLEV;
}
xi = xe + res.dx; // celestial
yi = ye + res.dy;
auto rx = (x - xi);
auto ry = (y - yi);
auto d = rx * rx + ry * ry;
bool ok = d <= e2;
if (ok) {
return std::error_code();
return MccMountDefaultPECErrorCode::ERROR_OK;
}
while (iter < max_iter) {
xi = xp;
yi = xp;
err = compute(xi, yi, res);
xp -= res.dx;
yp -= res.dy;
err = compute(xi, yi, res); // to encoder
if (err) {
return MccMountDefaultPECErrorCode::ERROR_INVALID_INPUTS_BISPLEV;
}
xe = x - res.dx;
ye = y - res.dy;
ok = ((xp - xi) * (xp - xi) + (yp - yi) * (yp - yi)) <= e2;
err = compute(xe, ye, res); // to celestial
if (err) {
return MccMountDefaultPECErrorCode::ERROR_INVALID_INPUTS_BISPLEV;
}
xi = xe + res.dx; // celestial
yi = ye + res.dy;
ok = ((x - xi) * (x - xi) + (y - yi) * (y - yi)) <= e2;
if (ok) {
return std::error_code();
}
return MccMountDefaultPECErrorCode::ERROR_OK;
}
// err = "exceed max iterations";!!!
++iter;
}
err = MccMountDefaultPECErrorCode::ERROR_EXCEED_MAX_ITERS;
}
return err;

View File

@ -139,42 +139,6 @@ public:
typedef DATA_T mount_telemetry_data_t;
// mount current telemetry data: time, position and related quantities
// struct mount_telemetry_data_t {
// typedef typename astrom_engine_t::coord_t coord_t;
// // time-related
// typename astrom_engine_t::time_point_t utc; // time point of measurements, UTC
// typename astrom_engine_t::juldate_t jd; // Julian date
// typename astrom_engine_t::sideral_time_t siderTime; // local apperant sideral time
// // typename astrom_engine_t::time_point_t ut1; // Universal time
// // typename astrom_engine_t::time_point_t tt; // Terrestial time
// // apparent target (user-input) current coordinates (in radians)
// coord_t tagRA, tagDEC;
// coord_t tagHA;
// coord_t tagAZ, tagALT;
// coord_t tagPA; // paralactic angle
// // encoder-measured current mount coordinates (in radians)
// coord_t mntRA, mntDEC;
// coord_t mntHA;
// coord_t mntAZ, mntALT;
// typename astrom_engine_t::pa_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 - ALT for horizontal-type one
// coord_t mntPosX, mntPosY;
// // current refraction coefficients
// typename pec_t::pec_result_t currRefrCoeffs;
// // current refraction correction (for mntALT)
// coord_t currRefr;
// // PEC (pointing error correction):
// // X - HA, Y - DEC for equatorial-type mount; X - AZ, Y - ALT for horizontal-type one
// coord_t pecX, pecY;
// };
MccMountTelemetry(astrom_engine_t& astrom_engine, pec_t& pec, hardware_t& hardware)
: _astromEngine(astrom_engine), _pec(pec), _hardware(hardware)

View File

@ -19,7 +19,6 @@ namespace mcc
* [azimuth, zenithal distance] (see sources code below)
*/
template <traits::mcc_mount_telemetry_c TELEMETRY_T>
class MccSimpleSlewModel
{
public:
@ -37,26 +36,47 @@ public:
};
template <traits::mcc_mount_hardware_c HARDWARE_T,
traits::mcc_astrom_engine_c ASTROM_T,
traits::mcc_mount_pec_c PEC_T>
MccSimpleSlewModel(HARDWARE_T& hardware, ASTROM_T& astrom_engine, PEC_T& pec)
template <traits::mcc_mount_controls_c MOUNT_CONTROLS_T>
MccSimpleSlewModel(MOUNT_CONTROLS_T& mount_controls)
{
const auto p_hardware = &hardware;
const auto p_astrom_engine = &astrom_engine;
const auto p_pec = &pec;
// deduce controls types
using astrom_engine_t = decltype(mount_controls.astrometryEngine);
using hardware_t = decltype(mount_controls.hardware);
using pec_t = decltype(mount_controls.PEC);
using telemetry_t = decltype(mount_controls.telemetry);
using tpl_pz_t = decltype(mount_controls.prohibitedZones);
static constexpr size_t Nzones = std::tuple_size_v<tpl_pz_t>;
const auto p_mount_controls = &mount_controls;
// prohibited zones related lambdas
auto check_zones = [p_mount_controls]<size_t... Is>(std::array<bool, sizeof...(Is)>& result,
std::index_sequence<Is...>) {
((result[Is] = std::get<Is>(p_mount_controls->prohibitedZones).inZone(p_mount_controls->telemetry.data())),
...);
bool flag = false;
((flag |= result[Is]), ...);
return flag;
};
_slewFunc = [p_mount_controls](this auto&& self, const slew_params_t& slew_pars) {
auto& astrom_engine = p_mount_controls->astrometryEngine;
auto& hardware = p_mount_controls->hardware;
auto& pec = p_mount_controls->PEC;
auto& telemetry = p_mount_controls->telemetry;
_slewFunc = [p_hardware, p_astrom_engine, p_pec](this auto&& self, const slew_params_t& slew_pars,
TELEMETRY_T& telemetry) {
using coord_t = typename ASTROM_T::coord_t;
using jd_t = typename ASTROM_T::juldate_t;
using coord_t = typename astrom_engine_t::coord_t;
using jd_t = typename astrom_engine_t::juldate_t;
typename HARDWARE_T::axes_pos_t ax_pos;
typename hardware_t::axes_pos_t ax_pos;
error_t res_err;
typename ASTROM_T::error_t ast_err;
typename astrom_engine_t::error_t ast_err;
typename pec_t::error_t pec_err;
if (slew_pars.coordPairKind == mcc::MccCoordPairKind::COORDS_KIND_XY) {
// trivial case (the pair is interpretated as raw encoder coordinates)
@ -66,26 +86,24 @@ public:
mcc::MccCoordPairKind::COORDS_KIND_RADEC_ICRS) { // catalog coordinates
jd_t jd;
coord_t ra_app, dec_app, ha, az, alt;
typename ASTROM_T::eo_t eo;
typename astrom_engine_t::eo_t eo;
ast_err = p_astrom_engine->greg2jul(std::chrono::system_clock::now(), jd);
ast_err = astrom_engine->greg2jul(std::chrono::system_clock::now(), jd);
if (!ast_err) {
ast_err = p_astrom_engine->icrs2obs(slew_pars.x, slew_pars.y, jd, ra_app, dec_app, ha, az, alt, eo);
ast_err = astrom_engine->icrs2obs(slew_pars.x, slew_pars.y, jd, ra_app, dec_app, ha, az, alt, eo);
if (!ast_err) {
if constexpr (mccIsEquatorialMount(PEC_T::mountType)) {
if constexpr (mccIsEquatorialMount(pec_t::mountType)) {
res_err = self({.coordPairKind = mcc::MccCoordPairKind::COORDS_KIND_HADEC_APP,
.x = ha,
.y = dec_app,
.stop = slew_pars.stop},
telemetry);
} else if constexpr (mccIsAltAzMount(PEC_T::mountType)) {
.stop = slew_pars.stop});
} else if constexpr (mccIsAltAzMount(pec_t::mountType)) {
res_err = self({.coordPairKind = mcc::MccCoordPairKind::COORDS_KIND_AZALT,
.x = az,
.y = alt,
.stop = slew_pars.stop},
telemetry);
.stop = slew_pars.stop});
} else {
static_assert(false, "UNKNOWN MOUNT TYPE!");
}
@ -94,78 +112,73 @@ public:
} else if (slew_pars.coordPairKind == mcc::MccCoordPairKind::COORDS_KIND_RADEC_APP) { // apparent
jd_t jd;
typename ASTROM_T::eo_t eo;
typename astrom_engine_t::eo_t eo;
ast_err = p_astrom_engine->greg2jul(std::chrono::system_clock::now(), jd);
ast_err = astrom_engine->greg2jul(std::chrono::system_clock::now(), jd);
if (!ast_err) {
typename ASTROM_T::sideral_time_t lst;
ast_err = p_astrom_engine->apparentSiderTime(jd, lst, true);
typename astrom_engine_t::sideral_time_t lst;
ast_err = astrom_engine->apparentSiderTime(jd, lst, true);
if (!ast_err) {
ast_err = p_astrom_engine->eqOrigins(jd, eo);
ast_err = astrom_engine->eqOrigins(jd, eo);
if (!ast_err) {
res_err = self({.coordPairKind = mcc::MccCoordPairKind::COORDS_KIND_HADEC_APP,
.x = lst - slew_pars.x + eo, // HA = LST - RA_APP + EO
.y = slew_pars.y,
.stop = slew_pars.stop},
telemetry);
.stop = slew_pars.stop});
}
}
}
} else if (slew_pars.coordPairKind == mcc::MccCoordPairKind::COORDS_KIND_HADEC_APP) { // apparent
if constexpr (mccIsEquatorialMount(PEC_T::mountType)) { // compute encoder coordinates
if constexpr (mccIsEquatorialMount(pec_t::mountType)) { // compute encoder coordinates
coord_t eps = 1.0 / 3600.0 * std::numbers::pi / 180.0;
typename PEC_T::pec_result_t pec_res;
typename pec_t::pec_result_t pec_res;
auto err = p_pec->reverseCompute(slew_pars.x, slew_pars.y, pec_res, eps, 10);
if (!err) {
pec_err = pec->reverseCompute(slew_pars.x, slew_pars.y, pec_res, eps, 10);
if (!pec_err) {
res_err = self({.coordPairKind = mcc::MccCoordPairKind::COORDS_KIND_XY,
.x = slew_pars.x - pec_res.dx,
.y = slew_pars.y - pec_res.dy,
.stop = slew_pars.stop},
telemetry);
.stop = slew_pars.stop});
}
} else if constexpr (mccIsAltAzMount(PEC_T::mountType)) {
} else if constexpr (mccIsAltAzMount(pec_t::mountType)) {
coord_t az, alt;
ast_err = p_astrom_engine->hadec2azalt(slew_pars.x, slew_pars.y, az, alt);
ast_err = astrom_engine->hadec2azalt(slew_pars.x, slew_pars.y, az, alt);
if (!ast_err) {
res_err = self({.coordPairKind = mcc::MccCoordPairKind::COORDS_KIND_AZALT,
.x = az,
.y = alt,
.stop = slew_pars.stop},
telemetry);
.stop = slew_pars.stop});
}
} else {
static_assert(false, "UNKNOWN MOUNT TYPE!");
}
} else if (slew_pars.coordPairKind == mcc::MccCoordPairKind::COORDS_KIND_AZALT) {
if constexpr (mccIsEquatorialMount(PEC_T::mountType)) {
if constexpr (mccIsEquatorialMount(pec_t::mountType)) {
coord_t ha, dec;
ast_err = p_astrom_engine->azalt2hadec(slew_pars.x, slew_pars.y, ha, dec);
ast_err = astrom_engine->azalt2hadec(slew_pars.x, slew_pars.y, ha, dec);
if (!ast_err) {
res_err = self({.coordPairKind = mcc::MccCoordPairKind::COORDS_KIND_HADEC_APP,
.x = ha,
.y = dec,
.stop = slew_pars.stop},
telemetry);
.stop = slew_pars.stop});
}
} else if constexpr (mccIsAltAzMount(PEC_T::mountType)) { // compute encoder coordinates
} else if constexpr (mccIsAltAzMount(pec_t::mountType)) { // compute encoder coordinates
coord_t eps = 1.0 / 3600.0 * std::numbers::pi / 180.0;
typename PEC_T::pec_result_t pec_res;
typename pec_t::pec_result_t pec_res;
auto err = p_pec->reverseCompute(slew_pars.x, slew_pars.y, pec_res, eps, 10);
if (!err) {
pec_err = pec->reverseCompute(slew_pars.x, slew_pars.y, pec_res, eps, 10);
if (!pec_err) {
res_err = self({.coordPairKind = mcc::MccCoordPairKind::COORDS_KIND_XY,
.x = slew_pars.x - pec_res.dx,
.y = slew_pars.y - pec_res.dy,
.stop = slew_pars.stop},
telemetry);
.stop = slew_pars.stop});
}
} else {
@ -178,32 +191,57 @@ public:
res_err = self({.coordPairKind = mcc::MccCoordPairKind::COORDS_KIND_AZALT,
.x = slew_pars.x,
.y = std::numbers::pi / 2.0 - slew_pars.y,
.stop = slew_pars.stop},
telemetry);
.stop = slew_pars.stop});
}
if (res_err) {
return res_err;
}
if (!ast_err) {
auto err = p_hardware->setPos(std::move(ax_pos));
if (pec_err) {
// ???????????
return std::error_code(); // !!!!!!!!!!!!!!!
}
if (!ast_err) {
typename telemetry_t::error_t t_err;
typename telemetry_t::mount_telemetry_data_t t_data;
// move mount (it is assumed this is asynchronous operation!!!)
typename hardware_t::error_t err = hardware->setPos(std::move(ax_pos));
std::array<bool, Nzones> pz_result;
if (!err) {
//
// what is the condition for mount reaches given position?!!
//
while (true) {
t_err = telemetry.data(t_data);
if (t_err) {
// ?????????!!!!!!!!!!
}
// check prohibited zones
if (check_zones(pz_result, std::make_index_sequence<Nzones>{})) {
// stop mount ?!!!!!!!!!!!!!!!!!!!!!
// return in-zone-error-code
}
}
}
}
};
}
error_t slew(const slew_params_t& pars, TELEMETRY_T& telemetry)
error_t slew(const slew_params_t& pars)
{
error_t res_err = _slewFunc(pars, telemetry);
error_t res_err = _slewFunc(pars);
return res_err;
}
protected:
std::function<error_t(const slew_params_t&, TELEMETRY_T&)> _slewFunc{};
std::function<error_t(const slew_params_t&)> _slewFunc{};
};

View File

@ -10,6 +10,7 @@
struct tel_data_t {
typedef mcc::MccAngle coord_t;
typedef std::chrono::system_clock::time_point time_point_t;
coord_t mntRA, mntDEC, mntHA;
coord_t mntAZ, mntALT;
@ -187,7 +188,7 @@ int main(int argc, char* argv[])
auto res = erfa.icrs2obs(ra1, dec1, jd, ra_o, dec_o, ha1, az1, alt1, eor);
std::cout << "eq of origins (from icrs2obs) = " << eor.sexagesimal(true) << "\n";
std::cout << "ret code (icrs2obs) = " << erfa.errorString(res) << "\n";
std::cout << "ret code (icrs2obs) = " << res.message() << "\n";
std::cout << "alt = " << alt1.sexagesimal() << "\n";
std::cout << "az = " << az1.sexagesimal() << "\n";
@ -232,7 +233,7 @@ int main(int argc, char* argv[])
ra1 = "17:00:00"_hms;
dec1 = "40:25:10.43"_dms;
res = erfa.icrs2obs(ra1, dec1, jd, ra_o, dec_o, ha1, az1, alt1, eor);
std::cout << "ret code (icrs2obs) = " << erfa.errorString(res) << "\n";
std::cout << "ret code (icrs2obs) = " << res.message() << "\n";
std::cout << "alt = " << alt1.sexagesimal() << "\n";
std::cout << "az = " << az1.sexagesimal() << "\n";
@ -265,5 +266,10 @@ int main(int argc, char* argv[])
std::cout << "(MAXALT) time from zone: " << std::chrono::hh_mm_ss(tm) << " (" << now1 << ")\n";
}
ra_o = 1.0;
dec_o = 2.0;
ha1 = ra_o * dec_o;
std::cout << "mult: " << ha1.degrees() << "\n";
return ecode;
}