This commit is contained in:
Timur A. Fatkhullin 2025-07-10 12:03:50 +03:00
parent a35e72d166
commit 4d13c86e3d
5 changed files with 209 additions and 243 deletions

View File

@ -21,6 +21,12 @@ 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:
@ -34,7 +40,7 @@ protected:
"unacceptable year"};
public:
enum engine_err_t : size_t {
enum error_t : size_t {
ERROR_OK = 0,
ERROR_INVALID_INPUT_ARG,
ERROR_JULDATE_INVALID_YEAR,
@ -62,8 +68,10 @@ public:
double wavelength = 0.55; // observed wavelength in mkm
MccAngle lat = "00:00:00"_dms; // site latitude
MccAngle lon = "00:00:00"_dms; // site longitude
AngleT lat = "00:00:00"_dms; // site latitude
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)
mcc::astrom::iers::MccLeapSeconds _leapSeconds{};
@ -77,12 +85,20 @@ public:
double mjd{51544.5}; // J2000.0
};
typedef MccAngle coord_t;
// typedef MccAngle coord_t;
typedef MccAngle sideral_time_t;
// typedef juldate_t terr_time_t;
typedef MccAngle pa_t;
typedef MccAngle eo_t;
// typedef MccAngle sideral_time_t;
// typedef MccAngle pa_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 {
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];
}
@ -119,7 +135,7 @@ public:
// templated generic version
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;
@ -152,13 +168,13 @@ public:
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);
}
engine_err_t terrestrialTime(juldate_t juldate, juldate_t& tt)
error_t terrestrialTime(juldate_t juldate, juldate_t& tt)
{
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};
@ -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;
@ -243,7 +259,7 @@ public:
/* atmospheric refraction-related methods */
engine_err_t refraction(refract_result_t& refr)
error_t refraction(refract_result_t& refr)
{
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) {
corr = 35.4 / 60.0 * std::numbers::pi / 180.0; // 35.4 arcminutes
@ -268,7 +284,7 @@ public:
/* coordinates conversional methods */
engine_err_t icrs2obs(coord_t ra,
error_t icrs2obs(coord_t ra,
coord_t dec,
juldate_t juldate,
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};
@ -329,7 +345,7 @@ public:
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};
@ -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};
@ -386,4 +402,4 @@ protected:
} // 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<>>, "");

View File

@ -64,7 +64,7 @@ namespace mcc::traits
template <typename T>
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;
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.errorString(std::declval<typename T::engine_err_t>()) } -> mcc_formattable;
{ t_const.errorString(std::declval<typename T::error_t>()) } -> mcc_formattable;
/* 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::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)
{
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::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)
{
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::same_as<typename T::engine_err_t>;
} -> std::same_as<typename T::error_t>;
// compute parallactic angle: hadec2pa(ha, dec, pa)
{
t.hadec2pa(std::declval<typename T::coord_t>(), std::declval<typename T::coord_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 */
@ -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)
{
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)
// 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&>(),
std::declval<bool>())
} -> std::same_as<typename T::engine_err_t>;
} -> std::same_as<typename T::error_t>;
/* atmospheric refraction-related methods */
// 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)
{
t.refractCorrection(std::declval<typename T::coord_t>(), std::declval<typename T::refract_result_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>
concept mcc_mount_hardware_c = requires(T t, const T t_const) {
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.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>
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::pec_data_t;
typename T::pec_result_t;
{ t.setData(std::declval<typename T::pec_data_t>()) };
{ t_const.getData() } -> std::same_as<typename T::pec_data_t>;
// at least contains .dx and .dy fields
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&>())
} -> std::same_as<typename T::pec_result_t>;
t.compute(std::declval<const typename T::coord_t&>(), std::declval<const typename T::coord_t&>(),
std::declval<typename T::pec_result_t>())
} -> std::same_as<typename T::error_t>;
};

View File

@ -5,33 +5,14 @@
/* MOUNT TELEMETRY OBJECT CONCEPT AND POSSIBLE IMPLEMENTATION */
#include <functional>
#include <mutex>
// #include "mcc_mount_config.h"
#include "mcc_mount_concepts.h"
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,
traits::mcc_mount_pec_c PEC_T,
traits::mcc_mount_hardware_c HARDWARE_T>
@ -42,29 +23,44 @@ public:
typedef PEC_T pec_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
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!");
static_assert(std::convertible_to<typename astrom_engine_t::coord_t, typename pec_t::coord_t>,
"ASTROMETRY ENGINE COORDINATE TYPE MUST BE CONVERTIBLE TO PEC ONE!");
static_assert(std::convertible_to<typename hardware_t::coord_t, typename pec_t::coord_t>,
"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>,
"TIME-POINT TYPE IN ASTROMETRY ENGINE AND HARDWARE MUST BE THE SAME!");
// static_assert(std::convertible_to<typename pec_t::coord_t, typename astrom_engine_t::coord_t>,
// "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
struct mount_telemetry_data_t {
typedef astrom_engine_t::coord_t mnt_coord_t;
// typedef astrom_engine_t::coord_t mnt_speed_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
// 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 ut1; // Universal time
// typename astrom_engine_t::time_point_t tt; // Terrestial time
// apparent target (user-input) current coordinates (in radians)
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)
// X - HA, Y - DEC for equatorial-type mount; X - AZ, Y - ALT for horizontal-type one
mnt_coord_t mntPosX, mntPosY;
// mnt_speed_t mntSpeedX, mntSpeedY;
// current refraction coefficients
typename pec_t::pec_result_t currRefrCoeffs;
@ -94,44 +89,44 @@ public:
};
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;
// computing ...
typename hardware_t::axes_pos_t ax_pos;
auto err = hardware_ptr->getPos(ax_pos);
auto err = _hardware.getPos(ax_pos);
if (err) {
// logging?!!!
return TEL_ERROR_HARDWARE;
}
_data.utc = ax_pos.time_point;
_data.mntPosX = ax_pos.x;
_data.mntPosY = ax_pos.y;
_data.mntPosX = static_cast<typename astrom_engine_t::coord_t>(ax_pos.x);
_data.mntPosY = static_cast<typename astrom_engine_t::coord_t>(ax_pos.y);
// 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) {
return TEL_ERROR_ASTROMETRY_COMP;
}
// 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) {
return TEL_ERROR_ASTROMETRY_COMP;
}
// compute equation of origins
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) {
return TEL_ERROR_ASTROMETRY_COMP;
}
@ -139,21 +134,28 @@ public:
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)) {
_data.mntHA = pec_res.x + ax_pos.x;
_data.mntDEC = pec_res.y + ax_pos.y;
_data.mntHA = _data.mntPosX;
_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) {
return TEL_ERROR_ASTROMETRY_COMP;
}
} else if constexpr (mccIsAltAzMount(pec_t::mountType)) {
_data.mntAZ = pec_res.x + ax_pos.x;
_data.mntALT = pec_res.y + ax_pos.x;
_data.mntAZ = _data.mntPosX;
_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) {
return TEL_ERROR_ASTROMETRY_COMP;
}
@ -165,35 +167,24 @@ public:
_data.mntRA = _data.siderTime - _data.mntHA + eo;
// 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) {
return TEL_ERROR_ASTROMETRY_COMP;
}
ast_err = astrom_engine_ptr->refraction(_data.currRefrCoeffs);
ast_err = _astromEngine.refraction(_data.currRefrCoeffs);
if (ast_err) {
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) {
return TEL_ERROR_ASTROMETRY_COMP;
}
std::lock_guard lock{_updateMutex};
_data = std::move(current_data);
};
}
virtual ~MccMountTelemetry() = default;
// update current data method
error_t update()
{
_updateImpl();
}
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:
mount_telemetry_data_t _data{};
std::function<error_t()> _updateImpl{};
astrom_engine_t& _astromEngine;
pec_t& _pec;
hardware_t& _hardware;
std::mutex _updateMutex;
};
} // namespace mcc

View File

@ -164,7 +164,8 @@ concept mcc_nonconst_lvref = std::is_lvalue_reference_v<T> && !std::is_const_v<s
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
{

View File

@ -146,7 +146,8 @@ int main(int argc, char* argv[])
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.lat = 43.646711_degs;
state.elev = 2100.0;
@ -156,8 +157,8 @@ int main(int argc, char* argv[])
std::cout << "LON = " << state.lon.sexagesimal() << "\n";
std::cout << "LAT = " << state.lat.sexagesimal() << "\n\n";
mcc::astrom::erfa::MccMountAstromEngineERFA erfa(state);
mcc::astrom::erfa::MccMountAstromEngineERFA::juldate_t jd{60861.72};
engine_t erfa(state);
engine_t::juldate_t jd{60861.72};
now = std::chrono::system_clock::now();
erfa.greg2jul(now, jd);