...
This commit is contained in:
parent
a35e72d166
commit
4d13c86e3d
@ -21,6 +21,12 @@ namespace mcc::astrom::erfa
|
|||||||
#include <erfa.h>
|
#include <erfa.h>
|
||||||
#include <erfam.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
|
class MccMountAstromEngineERFA
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
@ -34,7 +40,7 @@ protected:
|
|||||||
"unacceptable year"};
|
"unacceptable year"};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum engine_err_t : size_t {
|
enum error_t : size_t {
|
||||||
ERROR_OK = 0,
|
ERROR_OK = 0,
|
||||||
ERROR_INVALID_INPUT_ARG,
|
ERROR_INVALID_INPUT_ARG,
|
||||||
ERROR_JULDATE_INVALID_YEAR,
|
ERROR_JULDATE_INVALID_YEAR,
|
||||||
@ -62,8 +68,10 @@ public:
|
|||||||
|
|
||||||
double wavelength = 0.55; // observed wavelength in mkm
|
double wavelength = 0.55; // observed wavelength in mkm
|
||||||
|
|
||||||
MccAngle lat = "00:00:00"_dms; // site latitude
|
AngleT lat = "00:00:00"_dms; // site latitude
|
||||||
MccAngle lon = "00:00:00"_dms; // site longitude
|
AngleT lon = "00:00:00"_dms; // site longitude
|
||||||
|
// MccAngle lat = "00:00:00"_dms; // site latitude
|
||||||
|
// MccAngle lon = "00:00:00"_dms; // site longitude
|
||||||
double elev = 0.0; // site elevation (in meters)
|
double elev = 0.0; // site elevation (in meters)
|
||||||
|
|
||||||
mcc::astrom::iers::MccLeapSeconds _leapSeconds{};
|
mcc::astrom::iers::MccLeapSeconds _leapSeconds{};
|
||||||
@ -77,12 +85,20 @@ public:
|
|||||||
double mjd{51544.5}; // J2000.0
|
double mjd{51544.5}; // J2000.0
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef MccAngle coord_t;
|
// typedef MccAngle coord_t;
|
||||||
|
|
||||||
typedef MccAngle sideral_time_t;
|
// typedef MccAngle sideral_time_t;
|
||||||
// typedef juldate_t terr_time_t;
|
// typedef MccAngle pa_t;
|
||||||
typedef MccAngle pa_t;
|
// typedef MccAngle eo_t;
|
||||||
typedef MccAngle eo_t;
|
|
||||||
|
|
||||||
|
/* use of the same type fro representation of celestial and geodetic coordinates, celestial angles (e.g. P.A.),
|
||||||
|
* sideral time */
|
||||||
|
typedef AngleT coord_t;
|
||||||
|
|
||||||
|
typedef AngleT sideral_time_t;
|
||||||
|
typedef AngleT pa_t;
|
||||||
|
typedef AngleT eo_t;
|
||||||
|
|
||||||
struct refract_result_t {
|
struct refract_result_t {
|
||||||
double refa, refb;
|
double refa, refb;
|
||||||
@ -110,7 +126,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::string errorString(engine_err_t err) const
|
std::string errorString(error_t err) const
|
||||||
{
|
{
|
||||||
return engineErrorString[err];
|
return engineErrorString[err];
|
||||||
}
|
}
|
||||||
@ -119,7 +135,7 @@ public:
|
|||||||
|
|
||||||
// templated generic version
|
// templated generic version
|
||||||
template <mcc::traits::mcc_systime_c TpT>
|
template <mcc::traits::mcc_systime_c TpT>
|
||||||
engine_err_t greg2jul(TpT time_point, juldate_t& juldate)
|
error_t greg2jul(TpT time_point, juldate_t& juldate)
|
||||||
{
|
{
|
||||||
using namespace std::literals::chrono_literals;
|
using namespace std::literals::chrono_literals;
|
||||||
|
|
||||||
@ -152,13 +168,13 @@ public:
|
|||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
engine_err_t greg2jul(time_point_t time_point, juldate_t& juldate)
|
error_t greg2jul(time_point_t time_point, juldate_t& juldate)
|
||||||
{
|
{
|
||||||
return greg2jul<time_point_t>(time_point, juldate);
|
return greg2jul<time_point_t>(time_point, juldate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
engine_err_t terrestrialTime(juldate_t juldate, juldate_t& tt)
|
error_t terrestrialTime(juldate_t juldate, juldate_t& tt)
|
||||||
{
|
{
|
||||||
std::lock_guard lock{_stateMutex};
|
std::lock_guard lock{_stateMutex};
|
||||||
|
|
||||||
@ -179,7 +195,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
engine_err_t apparentSiderTime(juldate_t juldate, sideral_time_t& gst, bool islocal = false)
|
error_t apparentSiderTime(juldate_t juldate, sideral_time_t& gst, bool islocal = false)
|
||||||
{
|
{
|
||||||
// std::lock_guard lock{_stateMutex};
|
// std::lock_guard lock{_stateMutex};
|
||||||
|
|
||||||
@ -227,7 +243,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
engine_err_t eqOrigins(juldate_t juldate, eo_t& eo)
|
error_t eqOrigins(juldate_t juldate, eo_t& eo)
|
||||||
{
|
{
|
||||||
juldate_t tt;
|
juldate_t tt;
|
||||||
|
|
||||||
@ -243,7 +259,7 @@ public:
|
|||||||
|
|
||||||
/* atmospheric refraction-related methods */
|
/* atmospheric refraction-related methods */
|
||||||
|
|
||||||
engine_err_t refraction(refract_result_t& refr)
|
error_t refraction(refract_result_t& refr)
|
||||||
{
|
{
|
||||||
std::lock_guard lock{_stateMutex};
|
std::lock_guard lock{_stateMutex};
|
||||||
|
|
||||||
@ -254,7 +270,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
engine_err_t refractCorrection(const coord_t& alt, const refract_result_t& ref_params, coord_t& corr)
|
error_t refractCorrection(const coord_t& alt, const refract_result_t& ref_params, coord_t& corr)
|
||||||
{
|
{
|
||||||
if (alt <= 0.0) {
|
if (alt <= 0.0) {
|
||||||
corr = 35.4 / 60.0 * std::numbers::pi / 180.0; // 35.4 arcminutes
|
corr = 35.4 / 60.0 * std::numbers::pi / 180.0; // 35.4 arcminutes
|
||||||
@ -268,7 +284,7 @@ public:
|
|||||||
|
|
||||||
/* coordinates conversional methods */
|
/* coordinates conversional methods */
|
||||||
|
|
||||||
engine_err_t icrs2obs(coord_t ra,
|
error_t icrs2obs(coord_t ra,
|
||||||
coord_t dec,
|
coord_t dec,
|
||||||
juldate_t juldate,
|
juldate_t juldate,
|
||||||
coord_t& ra_app,
|
coord_t& ra_app,
|
||||||
@ -316,7 +332,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
engine_err_t hadec2azalt(coord_t ha, coord_t dec, coord_t& az, coord_t& alt)
|
error_t hadec2azalt(coord_t ha, coord_t dec, coord_t& az, coord_t& alt)
|
||||||
{
|
{
|
||||||
std::lock_guard lock{_stateMutex};
|
std::lock_guard lock{_stateMutex};
|
||||||
|
|
||||||
@ -329,7 +345,7 @@ public:
|
|||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
engine_err_t azalt2hadec(coord_t az, coord_t alt, coord_t& ha, coord_t& dec)
|
error_t azalt2hadec(coord_t az, coord_t alt, coord_t& ha, coord_t& dec)
|
||||||
{
|
{
|
||||||
std::lock_guard lock{_stateMutex};
|
std::lock_guard lock{_stateMutex};
|
||||||
|
|
||||||
@ -344,7 +360,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
engine_err_t hadec2pa(coord_t ha, coord_t dec, pa_t& pa)
|
error_t hadec2pa(coord_t ha, coord_t dec, pa_t& pa)
|
||||||
{
|
{
|
||||||
std::lock_guard lock{_stateMutex};
|
std::lock_guard lock{_stateMutex};
|
||||||
|
|
||||||
@ -386,4 +402,4 @@ protected:
|
|||||||
} // namespace mcc::astrom::erfa
|
} // namespace mcc::astrom::erfa
|
||||||
|
|
||||||
|
|
||||||
static_assert(mcc::traits::mcc_astrom_engine_c<mcc::astrom::erfa::MccMountAstromEngineERFA>, "");
|
static_assert(mcc::traits::mcc_astrom_engine_c<mcc::astrom::erfa::MccMountAstromEngineERFA<>>, "");
|
||||||
|
|||||||
@ -64,7 +64,7 @@ namespace mcc::traits
|
|||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
concept mcc_astrom_engine_c = requires(T t, const T t_const) {
|
concept mcc_astrom_engine_c = requires(T t, const T t_const) {
|
||||||
typename T::engine_err_t;
|
requires mcc_error_c<typename T::error_t>;
|
||||||
typename T::engine_state_t;
|
typename T::engine_state_t;
|
||||||
requires std::movable<typename T::engine_state_t>;
|
requires std::movable<typename T::engine_state_t>;
|
||||||
|
|
||||||
@ -81,7 +81,7 @@ concept mcc_astrom_engine_c = requires(T t, const T t_const) {
|
|||||||
|
|
||||||
{ t_const.getState() } -> std::same_as<typename T::engine_state_t>;
|
{ t_const.getState() } -> std::same_as<typename T::engine_state_t>;
|
||||||
|
|
||||||
{ t_const.errorString(std::declval<typename T::engine_err_t>()) } -> mcc_formattable;
|
{ t_const.errorString(std::declval<typename T::error_t>()) } -> mcc_formattable;
|
||||||
|
|
||||||
/* coordinates conversional methods */
|
/* coordinates conversional methods */
|
||||||
|
|
||||||
@ -91,25 +91,30 @@ concept mcc_astrom_engine_c = requires(T t, const T t_const) {
|
|||||||
std::declval<typename T::juldate_t>(), std::declval<typename T::coord_t&>(),
|
std::declval<typename T::juldate_t>(), std::declval<typename T::coord_t&>(),
|
||||||
std::declval<typename T::coord_t&>(), std::declval<typename T::coord_t&>(),
|
std::declval<typename T::coord_t&>(), std::declval<typename T::coord_t&>(),
|
||||||
std::declval<typename T::coord_t&>(), std::declval<typename T::coord_t&>())
|
std::declval<typename T::coord_t&>(), std::declval<typename T::coord_t&>())
|
||||||
} -> std::same_as<typename T::engine_err_t>;
|
} -> std::same_as<typename T::error_t>;
|
||||||
|
|
||||||
// compute hour angle and declination from azimuth and altitude: hadec2azalt(ha, dec, az, alt)
|
// compute hour angle and declination from azimuth and altitude: hadec2azalt(ha, dec, az, alt)
|
||||||
{
|
{
|
||||||
t.hadec2azalt(std::declval<typename T::coord_t>(), std::declval<typename T::coord_t>(),
|
t.hadec2azalt(std::declval<typename T::coord_t>(), std::declval<typename T::coord_t>(),
|
||||||
std::declval<typename T::coord_t&>(), std::declval<typename T::coord_t&>())
|
std::declval<typename T::coord_t&>(), std::declval<typename T::coord_t&>())
|
||||||
} -> std::same_as<typename T::engine_err_t>;
|
} -> std::same_as<typename T::error_t>;
|
||||||
|
|
||||||
// compute azimuth and altitude from hour angle and declination: azalt2hadec(az, alt, ha, dec)
|
// compute azimuth and altitude from hour angle and declination: azalt2hadec(az, alt, ha, dec)
|
||||||
{
|
{
|
||||||
t.azalt2hadec(std::declval<typename T::coord_t>(), std::declval<typename T::coord_t>(),
|
t.azalt2hadec(std::declval<typename T::coord_t>(), std::declval<typename T::coord_t>(),
|
||||||
std::declval<typename T::coord_t&>(), std::declval<typename T::coord_t&>())
|
std::declval<typename T::coord_t&>(), std::declval<typename T::coord_t&>())
|
||||||
} -> std::same_as<typename T::engine_err_t>;
|
} -> std::same_as<typename T::error_t>;
|
||||||
|
|
||||||
// compute parallactic angle: hadec2pa(ha, dec, pa)
|
// compute parallactic angle: hadec2pa(ha, dec, pa)
|
||||||
{
|
{
|
||||||
t.hadec2pa(std::declval<typename T::coord_t>(), std::declval<typename T::coord_t>(),
|
t.hadec2pa(std::declval<typename T::coord_t>(), std::declval<typename T::coord_t>(),
|
||||||
std::declval<typename T::pa_t&>())
|
std::declval<typename T::pa_t&>())
|
||||||
} -> std::same_as<typename T::engine_err_t>;
|
} -> std::same_as<typename T::error_t>;
|
||||||
|
|
||||||
|
// compute equation of origins
|
||||||
|
{
|
||||||
|
t.eqOrigins(std::declval<typename T::juldate_t>(), std::declval<typename T::eo_t&>())
|
||||||
|
} -> std::same_as<typename T::error_t>;
|
||||||
|
|
||||||
|
|
||||||
/* time-related methods */
|
/* time-related methods */
|
||||||
@ -117,95 +122,31 @@ concept mcc_astrom_engine_c = requires(T t, const T t_const) {
|
|||||||
// Gregorian Calendar time point to Julian Date: greg2jul(time_point, jd)
|
// Gregorian Calendar time point to Julian Date: greg2jul(time_point, jd)
|
||||||
{
|
{
|
||||||
t.greg2jul(std::declval<typename T::time_point_t>(), std::declval<typename T::juldate_t&>())
|
t.greg2jul(std::declval<typename T::time_point_t>(), std::declval<typename T::juldate_t&>())
|
||||||
} -> std::same_as<typename T::engine_err_t>;
|
} -> std::same_as<typename T::error_t>;
|
||||||
|
|
||||||
// apparent sideral time: apparentSiderTime(jd, gst, islocal)
|
// apparent sideral time: apparentSiderTime(jd, gst, islocal)
|
||||||
// if islocal == false then the method must return the Greenwich apparent sideral time, otherwise - local one
|
// if islocal == false then the method must return the Greenwich apparent sideral time, otherwise - local one
|
||||||
{
|
{
|
||||||
t.apparentSiderTime(std::declval<typename T::juldate_t>(), std::declval<typename T::sideral_time_t&>(),
|
t.apparentSiderTime(std::declval<typename T::juldate_t>(), std::declval<typename T::sideral_time_t&>(),
|
||||||
std::declval<bool>())
|
std::declval<bool>())
|
||||||
} -> std::same_as<typename T::engine_err_t>;
|
} -> std::same_as<typename T::error_t>;
|
||||||
|
|
||||||
|
|
||||||
/* atmospheric refraction-related methods */
|
/* atmospheric refraction-related methods */
|
||||||
|
|
||||||
// compute refraction-related quantities: refraction(refr_params)
|
// compute refraction-related quantities: refraction(refr_params)
|
||||||
{ t.refraction(std::declval<typename T::refract_result_t&>()) } -> std::same_as<typename T::engine_err_t>;
|
{ t.refraction(std::declval<typename T::refract_result_t&>()) } -> std::same_as<typename T::error_t>;
|
||||||
|
|
||||||
// compute refraction correction for given altitude: refractCorrection(alt, refr_params, refr_corr)
|
// compute refraction correction for given altitude: refractCorrection(alt, refr_params, refr_corr)
|
||||||
{
|
{
|
||||||
t.refractCorrection(std::declval<typename T::coord_t>(), std::declval<typename T::refract_result_t>(),
|
t.refractCorrection(std::declval<typename T::coord_t>(), std::declval<typename T::refract_result_t>(),
|
||||||
std::declval<typename T::coord_t&>())
|
std::declval<typename T::coord_t&>())
|
||||||
} -> std::same_as<typename T::engine_err_t>;
|
} -> std::same_as<typename T::error_t>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/* MOUNT AXES AND MOTORS HARDWARE GENERIC ABSTRACTION */
|
/* A VERY GENERIC MOUNT HARDWARE CONCEPT */
|
||||||
|
|
||||||
// // encoder basic concept (e.g. mount axis encoder or motor shaft one)
|
|
||||||
// template <typename T>
|
|
||||||
// concept mcc_hw_encoder_c = requires(T t, const T t_const) {
|
|
||||||
// requires mcc_error_c<typename T::error_t>;
|
|
||||||
|
|
||||||
// typename T::time_point_t;
|
|
||||||
// typename T::coord_t;
|
|
||||||
// typename T::speed_t;
|
|
||||||
// typename T::accel_t;
|
|
||||||
|
|
||||||
// requires requires(typename T::state_t st) {
|
|
||||||
// requires std::same_as<decltype(st.time), typename T::time_point_t>;
|
|
||||||
// requires std::same_as<decltype(st.pos), typename T::coord_t>;
|
|
||||||
// requires std::same_as<decltype(st.speed), typename T::speed_t>;
|
|
||||||
// requires std::same_as<decltype(st.accel), typename T::accel_t>;
|
|
||||||
// };
|
|
||||||
|
|
||||||
// { t_const.errorString(std::declval<typename T::error_t>()) } -> mcc_formattable;
|
|
||||||
|
|
||||||
// { t_const.id() } -> mcc_formattable;
|
|
||||||
|
|
||||||
// { t.getState(std::declval<typename T::state_t&>()) } -> std::same_as<typename T::error_t>;
|
|
||||||
// };
|
|
||||||
|
|
||||||
|
|
||||||
// template <typename T>
|
|
||||||
// concept mcc_hw_motor_c = requires(T t, const T t_const) {
|
|
||||||
// requires mcc_error_c<typename T::error_t>;
|
|
||||||
|
|
||||||
// typename T::coord_t;
|
|
||||||
// typename T::speed_t;
|
|
||||||
// typename T::accel_t;
|
|
||||||
|
|
||||||
// requires requires(typename T::pos_t st) {
|
|
||||||
// requires std::same_as<decltype(st.pos), typename T::coord_t>;
|
|
||||||
// requires std::same_as<decltype(st.speed), typename T::speed_t>; // means maximal allowed speed
|
|
||||||
// requires std::same_as<decltype(st.accel), typename T::accel_t>; // means a maximal allowed acceleration
|
|
||||||
// (jerk)
|
|
||||||
// };
|
|
||||||
|
|
||||||
|
|
||||||
// { t_const.errorString(std::declval<typename T::error_t>()) } -> mcc_formattable;
|
|
||||||
|
|
||||||
// { t_const.id() } -> mcc_formattable;
|
|
||||||
|
|
||||||
// { t.toPos(std::declval<typename T::pos_t>()) } -> std::same_as<typename T::error_t>;
|
|
||||||
|
|
||||||
// { t.stop() } -> std::same_as<typename T::error_t>;
|
|
||||||
// };
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// namespace details
|
|
||||||
// {
|
|
||||||
// template <typename T>
|
|
||||||
// concept mcc_hw_enc_lvref_c = mcc_nonconst_lvref<T> && mcc_hw_encoder_c<std::remove_reference_t<T>>;
|
|
||||||
|
|
||||||
// template <typename T>
|
|
||||||
// concept mcc_hw_motor_lvref_c = mcc_nonconst_lvref<T> && mcc_hw_motor_c<std::remove_reference_t<T>>;
|
|
||||||
|
|
||||||
// } // namespace details
|
|
||||||
|
|
||||||
|
|
||||||
// a very generic mount hardware concept
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
concept mcc_mount_hardware_c = requires(T t, const T t_const) {
|
concept mcc_mount_hardware_c = requires(T t, const T t_const) {
|
||||||
requires mcc_error_c<typename T::error_t>;
|
requires mcc_error_c<typename T::error_t>;
|
||||||
@ -229,14 +170,6 @@ concept mcc_mount_hardware_c = requires(T t, const T t_const) {
|
|||||||
|
|
||||||
{ t.setPos(std::declval<typename T::axes_pos_t>()) } -> std::same_as<typename T::error_t>;
|
{ t.setPos(std::declval<typename T::axes_pos_t>()) } -> std::same_as<typename T::error_t>;
|
||||||
{ t.getPos(std::declval<typename T::axes_pos_t&>()) } -> std::same_as<typename T::error_t>;
|
{ t.getPos(std::declval<typename T::axes_pos_t&>()) } -> std::same_as<typename T::error_t>;
|
||||||
|
|
||||||
// // access to encoders
|
|
||||||
// { t.encoderPosX() } -> details::mcc_hw_enc_lvref_c;
|
|
||||||
// { t.encoderPosY() } -> details::mcc_hw_enc_lvref_c;
|
|
||||||
|
|
||||||
// // access to motors
|
|
||||||
// { t.motorX() } -> details::mcc_hw_motor_lvref_c;
|
|
||||||
// { t.motorY() } -> details::mcc_hw_motor_lvref_c;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -244,16 +177,23 @@ concept mcc_mount_hardware_c = requires(T t, const T t_const) {
|
|||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
concept mcc_mount_pec_c = requires(T t, const T t_const) {
|
concept mcc_mount_pec_c = requires(T t, const T t_const) {
|
||||||
|
requires mcc_error_c<typename T::error_t>;
|
||||||
typename T::coord_t;
|
typename T::coord_t;
|
||||||
typename T::pec_data_t;
|
typename T::pec_data_t;
|
||||||
typename T::pec_result_t;
|
|
||||||
|
|
||||||
{ t.setData(std::declval<typename T::pec_data_t>()) };
|
// at least contains .dx and .dy fields
|
||||||
{ t_const.getData() } -> std::same_as<typename T::pec_data_t>;
|
requires requires(typename T::pec_result_t res) {
|
||||||
|
requires std::same_as<decltype(res.dx), typename T::coord_t>;
|
||||||
|
requires std::same_as<decltype(res.dy), typename T::coord_t>;
|
||||||
|
};
|
||||||
|
|
||||||
|
{ t.setData(std::declval<typename T::pec_data_t>()) } -> std::same_as<typename T::error_t>;
|
||||||
|
{ t_const.getData(std::declval<typename T::pec_data_t&>()) } -> std::same_as<typename T::error_t>;
|
||||||
|
|
||||||
{
|
{
|
||||||
t.compute(std::declval<const typename T::coord_t&>(), std::declval<const typename T::coord_t&>())
|
t.compute(std::declval<const typename T::coord_t&>(), std::declval<const typename T::coord_t&>(),
|
||||||
} -> std::same_as<typename T::pec_result_t>;
|
std::declval<typename T::pec_result_t>())
|
||||||
|
} -> std::same_as<typename T::error_t>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -5,33 +5,14 @@
|
|||||||
|
|
||||||
/* MOUNT TELEMETRY OBJECT CONCEPT AND POSSIBLE IMPLEMENTATION */
|
/* MOUNT TELEMETRY OBJECT CONCEPT AND POSSIBLE IMPLEMENTATION */
|
||||||
|
|
||||||
#include <functional>
|
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
// #include "mcc_mount_config.h"
|
|
||||||
#include "mcc_mount_concepts.h"
|
#include "mcc_mount_concepts.h"
|
||||||
|
|
||||||
namespace mcc
|
namespace mcc
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
// namespace traits
|
|
||||||
// {
|
|
||||||
|
|
||||||
// template <typename T>
|
|
||||||
// concept mcc_mount_telemetry_c = requires(T t, const T t_const) {
|
|
||||||
// typename T::error_t;
|
|
||||||
// typename T::mount_telemetry_data_t;
|
|
||||||
|
|
||||||
// { t_const.errorString(std::declval<typename T::error_t>()) } -> mcc_formattable;
|
|
||||||
|
|
||||||
// { t.update() } -> std::same_as<typename T::error_t>;
|
|
||||||
|
|
||||||
// { t_const.data() } -> std::same_as<typename T::mount_telemetry_data_t>;
|
|
||||||
// };
|
|
||||||
|
|
||||||
// } // namespace traits
|
|
||||||
|
|
||||||
template <traits::mcc_astrom_engine_c ASTROM_ENGINE_T,
|
template <traits::mcc_astrom_engine_c ASTROM_ENGINE_T,
|
||||||
traits::mcc_mount_pec_c PEC_T,
|
traits::mcc_mount_pec_c PEC_T,
|
||||||
traits::mcc_mount_hardware_c HARDWARE_T>
|
traits::mcc_mount_hardware_c HARDWARE_T>
|
||||||
@ -42,29 +23,44 @@ public:
|
|||||||
typedef PEC_T pec_t;
|
typedef PEC_T pec_t;
|
||||||
typedef HARDWARE_T hardware_t;
|
typedef HARDWARE_T hardware_t;
|
||||||
|
|
||||||
enum error_t : int { TEL_ERROR_OK = 0, TEL_ERROR_HARDWARE, TEL_ERROR_ASTROMETRY_COMP };
|
enum error_t : int { TEL_ERROR_OK = 0, TEL_ERROR_HARDWARE, TEL_ERROR_ASTROMETRY_COMP, TEL_ERROR_PEC };
|
||||||
|
|
||||||
// check for coordinate types consistency
|
// check for coordinate types consistency
|
||||||
static_assert(std::convertible_to<typename hardware_t::coord_t, typename astrom_engine_t::coord_t>,
|
static_assert(std::convertible_to<typename hardware_t::coord_t, typename astrom_engine_t::coord_t>,
|
||||||
"HARDWARE COORDINATE TYPE MUST BE CONVERTIBLE TO ASTROMETRY ENGINE ONE!");
|
"HARDWARE COORDINATE TYPE MUST BE CONVERTIBLE TO ASTROMETRY ENGINE ONE!");
|
||||||
|
|
||||||
static_assert(std::convertible_to<typename astrom_engine_t::coord_t, typename pec_t::coord_t>,
|
static_assert(std::convertible_to<typename hardware_t::coord_t, typename pec_t::coord_t>,
|
||||||
"ASTROMETRY ENGINE COORDINATE TYPE MUST BE CONVERTIBLE TO PEC ONE!");
|
"HARDWARE COORDINATE TYPE MUST BE CONVERTIBLE TO PEC ONE!");
|
||||||
|
|
||||||
static_assert(std::same_as<typename astrom_engine_t::time_point_t, typename hardware_t::time_point_t>,
|
// static_assert(std::convertible_to<typename pec_t::coord_t, typename astrom_engine_t::coord_t>,
|
||||||
"TIME-POINT TYPE IN ASTROMETRY ENGINE AND HARDWARE MUST BE THE SAME!");
|
// "ASTROMETRY ENGINE COORDINATE TYPE MUST BE CONVERTIBLE TO PEC ONE!");
|
||||||
|
|
||||||
|
// mandatory arithmetic operations
|
||||||
|
static_assert( // for CIO-based apparent RA computation and PEC correction addition (see below)
|
||||||
|
requires(typename astrom_engine_t::coord_t v1,
|
||||||
|
typename astrom_engine_t::coord_t v2,
|
||||||
|
typename pec_t::coord_t v3) {
|
||||||
|
{ v1 + v2 } -> std::convertible_to<typename astrom_engine_t::coord_t>;
|
||||||
|
{ v1 - v2 } -> std::convertible_to<typename astrom_engine_t::coord_t>;
|
||||||
|
v1 += v3;
|
||||||
|
},
|
||||||
|
"ASTROMETRY ENGINE COORDINATE TYPE MUST DEFINE '+', '+=' AND '-' ARITHMETIC OPERATIONS!");
|
||||||
|
|
||||||
|
|
||||||
|
// check for time point types consistency
|
||||||
|
static_assert(std::convertible_to<typename hardware_t::time_point_t, typename astrom_engine_t::time_point_t>,
|
||||||
|
"HARDWARE TIME-POINT TYPE MUST BE CONVERTIBLE TO ASTROMETRY ENGINE ONE!");
|
||||||
|
|
||||||
// mount current telemetry data: time, position and related quantities
|
// mount current telemetry data: time, position and related quantities
|
||||||
struct mount_telemetry_data_t {
|
struct mount_telemetry_data_t {
|
||||||
typedef astrom_engine_t::coord_t mnt_coord_t;
|
typedef astrom_engine_t::coord_t mnt_coord_t;
|
||||||
// typedef astrom_engine_t::coord_t mnt_speed_t;
|
|
||||||
|
|
||||||
// time-related
|
// time-related
|
||||||
typename astrom_engine_t::time_point_t utc; // time point of measurements, UTC
|
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::juldate_t jd; // Julian date
|
||||||
typename astrom_engine_t::sideral_time_t siderTime; // local apperant sideral time
|
typename astrom_engine_t::sideral_time_t siderTime; // local apperant sideral time
|
||||||
// astrom_engine_t::time_point_t ut1; // Universal time
|
// typename astrom_engine_t::time_point_t ut1; // Universal time
|
||||||
// astrom_engine_t::time_point_t tt; // Terrestial time
|
// typename astrom_engine_t::time_point_t tt; // Terrestial time
|
||||||
|
|
||||||
// apparent target (user-input) current coordinates (in radians)
|
// apparent target (user-input) current coordinates (in radians)
|
||||||
mnt_coord_t tagRA, tagDEC;
|
mnt_coord_t tagRA, tagDEC;
|
||||||
@ -81,7 +77,6 @@ public:
|
|||||||
// encoder-measured (non-corrected for PCS) current mount position and moving speed (in radians, radians/s)
|
// 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
|
// X - HA, Y - DEC for equatorial-type mount; X - AZ, Y - ALT for horizontal-type one
|
||||||
mnt_coord_t mntPosX, mntPosY;
|
mnt_coord_t mntPosX, mntPosY;
|
||||||
// mnt_speed_t mntSpeedX, mntSpeedY;
|
|
||||||
|
|
||||||
// current refraction coefficients
|
// current refraction coefficients
|
||||||
typename pec_t::pec_result_t currRefrCoeffs;
|
typename pec_t::pec_result_t currRefrCoeffs;
|
||||||
@ -94,44 +89,44 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
MccMountTelemetry(astrom_engine_t& astrom_engine, pec_t& pec, hardware_t& hardware)
|
MccMountTelemetry(astrom_engine_t& astrom_engine, pec_t& pec, hardware_t& hardware)
|
||||||
|
: _astromEngine(astrom_engine), _pec(pec), _hardware(hardware)
|
||||||
{
|
{
|
||||||
// to be sure that arguments are captured by reference
|
}
|
||||||
const auto astrom_engine_ptr = &astrom_engine;
|
|
||||||
const auto pec_ptr = &pec;
|
|
||||||
const auto hardware_ptr = &hardware;
|
|
||||||
|
|
||||||
_updateImpl = [astrom_engine_ptr, pec_ptr, hardware_ptr, this]() {
|
virtual ~MccMountTelemetry() = default;
|
||||||
|
|
||||||
|
// update current data method
|
||||||
|
error_t update()
|
||||||
|
{
|
||||||
mount_telemetry_data_t current_data;
|
mount_telemetry_data_t current_data;
|
||||||
|
|
||||||
// computing ...
|
|
||||||
|
|
||||||
typename hardware_t::axes_pos_t ax_pos;
|
typename hardware_t::axes_pos_t ax_pos;
|
||||||
|
|
||||||
auto err = hardware_ptr->getPos(ax_pos);
|
auto err = _hardware.getPos(ax_pos);
|
||||||
if (err) {
|
if (err) {
|
||||||
// logging?!!!
|
// logging?!!!
|
||||||
return TEL_ERROR_HARDWARE;
|
return TEL_ERROR_HARDWARE;
|
||||||
}
|
}
|
||||||
|
|
||||||
_data.utc = ax_pos.time_point;
|
_data.utc = ax_pos.time_point;
|
||||||
_data.mntPosX = ax_pos.x;
|
_data.mntPosX = static_cast<typename astrom_engine_t::coord_t>(ax_pos.x);
|
||||||
_data.mntPosY = ax_pos.y;
|
_data.mntPosY = static_cast<typename astrom_engine_t::coord_t>(ax_pos.y);
|
||||||
|
|
||||||
// compute Julian date
|
// compute Julian date
|
||||||
auto ast_err = astrom_engine_ptr->greg2jul(_data.utc, _data.jd);
|
auto ast_err = _astromEngine.greg2jul(_data.utc, _data.jd);
|
||||||
if (ast_err) {
|
if (ast_err) {
|
||||||
return TEL_ERROR_ASTROMETRY_COMP;
|
return TEL_ERROR_ASTROMETRY_COMP;
|
||||||
}
|
}
|
||||||
|
|
||||||
// compute local apparent sideral time
|
// compute local apparent sideral time
|
||||||
ast_err = astrom_engine_ptr->apparentSiderTime(_data.jd, _data.siderTime, true);
|
ast_err = _astromEngine.apparentSiderTime(_data.jd, _data.siderTime, true);
|
||||||
if (ast_err) {
|
if (ast_err) {
|
||||||
return TEL_ERROR_ASTROMETRY_COMP;
|
return TEL_ERROR_ASTROMETRY_COMP;
|
||||||
}
|
}
|
||||||
|
|
||||||
// compute equation of origins
|
// compute equation of origins
|
||||||
typename astrom_engine_t::eo_t eo;
|
typename astrom_engine_t::eo_t eo;
|
||||||
ast_err = astrom_engine_ptr->eqOrigins(_data.jd, eo);
|
ast_err = _astromEngine.eqOrigins(_data.jd, eo);
|
||||||
if (ast_err) {
|
if (ast_err) {
|
||||||
return TEL_ERROR_ASTROMETRY_COMP;
|
return TEL_ERROR_ASTROMETRY_COMP;
|
||||||
}
|
}
|
||||||
@ -139,21 +134,28 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
typename pec_t::pec_result_t pec_res;
|
typename pec_t::pec_result_t pec_res;
|
||||||
pec_res = pec_ptr->compute(ax_pos.x, ax_pos.y);
|
auto pec_err = _pec.compute(ax_pos.x, ax_pos.y, pec_res);
|
||||||
|
if (pec_err) {
|
||||||
|
return TEL_ERROR_PEC;
|
||||||
|
}
|
||||||
|
|
||||||
if constexpr (mccIsEquatorialMount(pec_t::mountType)) {
|
if constexpr (mccIsEquatorialMount(pec_t::mountType)) {
|
||||||
_data.mntHA = pec_res.x + ax_pos.x;
|
_data.mntHA = _data.mntPosX;
|
||||||
_data.mntDEC = pec_res.y + ax_pos.y;
|
_data.mntDEC = _data.mntPosY;
|
||||||
|
_data.mntHA += pec_res.dx;
|
||||||
|
_data.mntDEC += pec_res.dy;
|
||||||
|
|
||||||
ast_err = astrom_engine_ptr->hadec2azalt(_data.mntHA, _data.mntDEC, _data.mntAZ, _data.mntALT);
|
ast_err = _astromEngine.hadec2azalt(_data.mntHA, _data.mntDEC, _data.mntAZ, _data.mntALT);
|
||||||
if (ast_err) {
|
if (ast_err) {
|
||||||
return TEL_ERROR_ASTROMETRY_COMP;
|
return TEL_ERROR_ASTROMETRY_COMP;
|
||||||
}
|
}
|
||||||
} else if constexpr (mccIsAltAzMount(pec_t::mountType)) {
|
} else if constexpr (mccIsAltAzMount(pec_t::mountType)) {
|
||||||
_data.mntAZ = pec_res.x + ax_pos.x;
|
_data.mntAZ = _data.mntPosX;
|
||||||
_data.mntALT = pec_res.y + ax_pos.x;
|
_data.mntALT = _data.mntPosY;
|
||||||
|
_data.mntAZ += pec_res.dx;
|
||||||
|
_data.mntALT += pec_res.dy;
|
||||||
|
|
||||||
ast_err = astrom_engine_ptr->azalt2hadec(_data.mntAZ, _data.mntALT, _data.mntHA, _data.mntDEC);
|
ast_err = _astromEngine.azalt2hadec(_data.mntAZ, _data.mntALT, _data.mntHA, _data.mntDEC);
|
||||||
if (ast_err) {
|
if (ast_err) {
|
||||||
return TEL_ERROR_ASTROMETRY_COMP;
|
return TEL_ERROR_ASTROMETRY_COMP;
|
||||||
}
|
}
|
||||||
@ -165,35 +167,24 @@ public:
|
|||||||
_data.mntRA = _data.siderTime - _data.mntHA + eo;
|
_data.mntRA = _data.siderTime - _data.mntHA + eo;
|
||||||
|
|
||||||
// compute PA
|
// compute PA
|
||||||
ast_err = astrom_engine_ptr->hadec2pa(_data.mntHA, _data.mntDEC, _data.mntPA);
|
ast_err = _astromEngine.hadec2pa(_data.mntHA, _data.mntDEC, _data.mntPA);
|
||||||
if (ast_err) {
|
if (ast_err) {
|
||||||
return TEL_ERROR_ASTROMETRY_COMP;
|
return TEL_ERROR_ASTROMETRY_COMP;
|
||||||
}
|
}
|
||||||
|
|
||||||
ast_err = astrom_engine_ptr->refraction(_data.currRefrCoeffs);
|
ast_err = _astromEngine.refraction(_data.currRefrCoeffs);
|
||||||
if (ast_err) {
|
if (ast_err) {
|
||||||
return TEL_ERROR_ASTROMETRY_COMP;
|
return TEL_ERROR_ASTROMETRY_COMP;
|
||||||
}
|
}
|
||||||
|
|
||||||
ast_err = astrom_engine_ptr->refractCorrection(_data.mntALT, _data.currRefrCoeffs, _data.currRefr);
|
ast_err = _astromEngine.refractCorrection(_data.mntALT, _data.currRefrCoeffs, _data.currRefr);
|
||||||
if (ast_err) {
|
if (ast_err) {
|
||||||
return TEL_ERROR_ASTROMETRY_COMP;
|
return TEL_ERROR_ASTROMETRY_COMP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
std::lock_guard lock{_updateMutex};
|
std::lock_guard lock{_updateMutex};
|
||||||
|
|
||||||
_data = std::move(current_data);
|
_data = std::move(current_data);
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual ~MccMountTelemetry() = default;
|
|
||||||
|
|
||||||
// update current data method
|
|
||||||
error_t update()
|
|
||||||
{
|
|
||||||
_updateImpl();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mount_telemetry_data_t data(this auto&& self)
|
mount_telemetry_data_t data(this auto&& self)
|
||||||
@ -206,12 +197,29 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::string_view errorString(error_t err) const
|
||||||
|
{
|
||||||
|
if (err == TEL_ERROR_OK) {
|
||||||
|
return "OK";
|
||||||
|
} else if (err == TEL_ERROR_ASTROMETRY_COMP) {
|
||||||
|
return "astrometry computation error";
|
||||||
|
} else if (err == TEL_ERROR_PEC) {
|
||||||
|
return "PEC computation error";
|
||||||
|
} else if (err == TEL_ERROR_HARDWARE) {
|
||||||
|
return "hardware request error";
|
||||||
|
} else {
|
||||||
|
return "unknown error";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
mount_telemetry_data_t _data{};
|
mount_telemetry_data_t _data{};
|
||||||
|
astrom_engine_t& _astromEngine;
|
||||||
std::function<error_t()> _updateImpl{};
|
pec_t& _pec;
|
||||||
|
hardware_t& _hardware;
|
||||||
|
|
||||||
std::mutex _updateMutex;
|
std::mutex _updateMutex;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
} // namespace mcc
|
} // namespace mcc
|
||||||
|
|||||||
@ -164,7 +164,8 @@ concept mcc_nonconst_lvref = std::is_lvalue_reference_v<T> && !std::is_const_v<s
|
|||||||
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
concept mcc_error_c = std::convertible_to<T, bool> && mcc_formattable<T>;
|
concept mcc_error_c = std::convertible_to<T, bool>;
|
||||||
|
// concept mcc_error_c = std::convertible_to<T, bool> && mcc_formattable<T>;
|
||||||
|
|
||||||
namespace details
|
namespace details
|
||||||
{
|
{
|
||||||
|
|||||||
@ -146,7 +146,8 @@ int main(int argc, char* argv[])
|
|||||||
|
|
||||||
std::cout << "\n\n\n\n";
|
std::cout << "\n\n\n\n";
|
||||||
|
|
||||||
mcc::astrom::erfa::MccMountAstromEngineERFA::engine_state_t state;
|
using engine_t = mcc::astrom::erfa::MccMountAstromEngineERFA<>;
|
||||||
|
engine_t::engine_state_t state;
|
||||||
state.lon = 41.440732_degs;
|
state.lon = 41.440732_degs;
|
||||||
state.lat = 43.646711_degs;
|
state.lat = 43.646711_degs;
|
||||||
state.elev = 2100.0;
|
state.elev = 2100.0;
|
||||||
@ -156,8 +157,8 @@ int main(int argc, char* argv[])
|
|||||||
std::cout << "LON = " << state.lon.sexagesimal() << "\n";
|
std::cout << "LON = " << state.lon.sexagesimal() << "\n";
|
||||||
std::cout << "LAT = " << state.lat.sexagesimal() << "\n\n";
|
std::cout << "LAT = " << state.lat.sexagesimal() << "\n\n";
|
||||||
|
|
||||||
mcc::astrom::erfa::MccMountAstromEngineERFA erfa(state);
|
engine_t erfa(state);
|
||||||
mcc::astrom::erfa::MccMountAstromEngineERFA::juldate_t jd{60861.72};
|
engine_t::juldate_t jd{60861.72};
|
||||||
|
|
||||||
now = std::chrono::system_clock::now();
|
now = std::chrono::system_clock::now();
|
||||||
erfa.greg2jul(now, jd);
|
erfa.greg2jul(now, jd);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user