This commit is contained in:
Timur A. Fatkhullin 2025-09-16 18:35:39 +03:00
parent bb41710645
commit 732cd33947
5 changed files with 433 additions and 175 deletions

View File

@ -29,4 +29,28 @@ Asibfm700Mount::~Asibfm700Mount()
logDebug("Delete Asibfm700Mount class instance ({})", this->getThreadId());
}
Asibfm700Mount1::Asibfm700Mount1(Asibfm700MountConfig const& config,
std::shared_ptr<spdlog::logger> logger,
const auto& pattern_range)
: mcc::ccte::erfa::MccCCTE_ERFA({.meteo{.temperature = 10.0, .humidity = 0.5, .pressure = 1010.0},
.wavelength = config.refractWavelength,
.lat = config.siteLatitude,
.lon = config.siteLongitude,
.elev = config.siteElevation}),
Asibfm700PCM(config.pcmData),
base_gm_class_t(gm_class_t{AsibFM700ServoController{config.servoControllerConfig}, mcc::MccTelemetry{this},
Asibfm700PZoneContainer{}, mcc::MccSimpleSlewingModel{this},
mcc::MccSimpleTrackingModel{this}, Asibfm700Logger{std::move(logger), pattern_range}},
Asibfm700StartState{})
{
logDebug("Create Asibfm700Mount class instance ({})", this->getThreadId());
}
Asibfm700Mount1::~Asibfm700Mount1()
{
logDebug("Delete Asibfm700Mount class instance ({})", this->getThreadId());
}
} // namespace asibfm700

View File

@ -64,6 +64,14 @@ class Asibfm700Mount1 : public mcc::ccte::erfa::MccCCTE_ERFA,
mcc::MccSimpleTrackingModel,
Asibfm700Logger>>
{
typedef mcc::MccGenericMount<AsibFM700ServoController,
mcc::MccTelemetry,
Asibfm700PZoneContainer,
mcc::MccSimpleSlewingModel,
mcc::MccSimpleTrackingModel,
Asibfm700Logger>
gm_class_t;
typedef mcc::MccGenericFsmMount<mcc::MccGenericMount<AsibFM700ServoController,
mcc::MccTelemetry,
Asibfm700PZoneContainer,
@ -72,6 +80,41 @@ class Asibfm700Mount1 : public mcc::ccte::erfa::MccCCTE_ERFA,
Asibfm700Logger>>
base_gm_class_t;
protected:
struct Asibfm700ErrorState : base_gm_class_t::MccGenericFsmMountBaseState {
static constexpr std::string_view ID{"ASIBFM700-MOUNT-ERROR-STATE"};
void exit(MccGenericFsmMountErrorEvent& event)
{
event.mount()->logWarn("The mount already in error state!");
}
void enter(MccGenericFsmMountErrorEvent& event)
{
event.mount()->logWarn("The mount already in error state!");
}
void exit(mcc::fsm::traits::fsm_event_c auto& event)
{
exitLog(event);
}
void enter(mcc::fsm::traits::fsm_event_c auto& event)
{
enterLog(event);
// ...
}
using transition_t = mcc::fsm::fsm_transition_table_t<
std::pair<MccGenericFsmMountErrorEvent, Asibfm700ErrorState>,
std::pair<MccGenericFsmMountInitEvent, MccGenericFsmMountInitState<Asibfm700ErrorState>>,
std::pair<MccGenericFsmMountIdleEvent, MccGenericFsmMountIdleState<Asibfm700ErrorState>>>;
};
typedef base_gm_class_t::MccGenericFsmMountStartState<Asibfm700ErrorState> Asibfm700StartState;
public:
using base_gm_class_t::error_t;

View File

@ -99,7 +99,7 @@ public:
auto hw_err = this->hardwareStop();
if (hw_err) {
return mcc_deduce_error(hw_err, MccGenericMountErrorCode::ERROR_HW_STOP);
return mcc_deduce_error_code(hw_err, MccGenericMountErrorCode::ERROR_HW_STOP);
}
logInfo("Stop command was sent");
@ -113,7 +113,7 @@ public:
auto hw_err = this->hardwareInit();
if (hw_err) {
return mcc_deduce_error(hw_err, MccGenericMountErrorCode::ERROR_HW_STOP);
return mcc_deduce_error_code(hw_err, MccGenericMountErrorCode::ERROR_HW_STOP);
}
logInfo("Mount initialization was performed");
@ -140,6 +140,8 @@ public:
using typename MOUNT_T::tracking_params_t;
protected:
error_t _lastError;
/* default events implementation */
struct MccGenericFsmMountBaseEvent {
@ -236,7 +238,8 @@ protected:
struct MccGenericFsmMountErrorState; // default error-state class implementation (forward declaration)
template <fsm::traits::fsm_state_c ERROR_STATE_T>
// template <fsm::traits::fsm_state_c ERROR_STATE_T>
template <typename ERROR_STATE_T>
struct MccGenericFsmMountInitState;
template <fsm::traits::fsm_state_c ERROR_STATE_T>
@ -260,7 +263,8 @@ protected:
std::pair<MccGenericFsmMountInitEvent, MccGenericFsmMountInitState<ERROR_STATE_T>>>;
};
template <fsm::traits::fsm_state_c ERROR_STATE_T>
// template <fsm::traits::fsm_state_c ERROR_STATE_T>
template <typename ERROR_STATE_T>
struct MccGenericFsmMountIdleState
: MccGenericFsmMountBaseState // IDLE state: mount is stopped, wait for client commands
{
@ -285,8 +289,11 @@ protected:
}
};
template <fsm::traits::fsm_state_c ERROR_STATE_T>
// template <fsm::traits::fsm_state_c ERROR_STATE_T>
template <typename ERROR_STATE_T>
struct MccGenericFsmMountInitState : MccGenericFsmMountBaseState {
// static_assert(fsm::traits::fsm_state_c<ERROR_STATE_T>);
static constexpr std::string_view ID{"GENERIC-MOUNT-INIT-STATE"};
using transition_t = fsm::fsm_transition_table_t<
@ -512,6 +519,9 @@ protected:
void exit(fsm::traits::fsm_event_c auto& event)
{
// just reset error
event.mount()->_lastError = MccGenericFsmMountErrorCode::ERROR_OK;
exitLog(event);
if constexpr (mcc_generic_log_mount_c<MOUNT_T>) {
@ -524,6 +534,8 @@ protected:
void enter(fsm::traits::fsm_event_c auto& event)
{
event.mount()->_lastError = event.eventData();
enterLog(event);
if constexpr (mcc_generic_log_mount_c<MOUNT_T>) {
@ -546,15 +558,21 @@ public:
// reimplementation of base-class methods to adapt it to FSM-behavior
auto initMount()
error_t initMount()
{
try {
this->dispatchEvent(MccGenericFsmMountInitEvent{this});
} catch (std::system_error const& exc) {
return exc.code();
if (exc.code().category() == fsm::MccFiniteStateMachineCategory::get()) {
_lastError = MccGenericFsmMountErrorCode::ERROR_INVALID_OPERATION;
} else {
// return exc.code();
_lastError = exc.code();
}
}
return MccGenericFsmMountErrorCode::ERROR_OK;
// return MccGenericFsmMountErrorCode::ERROR_OK;
return _lastError;
}
auto stopMount()
@ -562,10 +580,16 @@ public:
try {
this->dispatchEvent(MccGenericFsmMountStopEvent{this});
} catch (std::system_error const& exc) {
return exc.code();
if (exc.code().category() == fsm::MccFiniteStateMachineCategory::get()) {
_lastError = MccGenericFsmMountErrorCode::ERROR_INVALID_OPERATION;
} else {
// return exc.code();
_lastError = exc.code();
}
}
return MccGenericFsmMountErrorCode::ERROR_OK;
// return MccGenericFsmMountErrorCode::ERROR_OK;
return _lastError;
}
auto slewToTarget()
@ -573,10 +597,16 @@ public:
try {
this->dispatchEvent(MccGenericFsmMountSlewEvent{this});
} catch (std::system_error const& exc) {
return exc.code();
if (exc.code().category() == fsm::MccFiniteStateMachineCategory::get()) {
_lastError = MccGenericFsmMountErrorCode::ERROR_INVALID_OPERATION;
} else {
// return exc.code();
_lastError = exc.code();
}
}
return MccGenericFsmMountErrorCode::ERROR_OK;
// return MccGenericFsmMountErrorCode::ERROR_OK;
return _lastError;
}
auto stopSlewing()
@ -584,10 +614,16 @@ public:
try {
this->dispatchEvent(MccGenericFsmMountStopEvent{this});
} catch (std::system_error const& exc) {
return exc.code();
if (exc.code().category() == fsm::MccFiniteStateMachineCategory::get()) {
_lastError = MccGenericFsmMountErrorCode::ERROR_INVALID_OPERATION;
} else {
// return exc.code();
_lastError = exc.code();
}
}
return MccGenericFsmMountErrorCode::ERROR_OK;
// return MccGenericFsmMountErrorCode::ERROR_OK;
return _lastError;
}
auto trackTarget()
@ -595,10 +631,16 @@ public:
try {
this->dispatchEvent(MccGenericFsmMountTrackEvent{this});
} catch (std::system_error const& exc) {
return exc.code();
if (exc.code().category() == fsm::MccFiniteStateMachineCategory::get()) {
_lastError = MccGenericFsmMountErrorCode::ERROR_INVALID_OPERATION;
} else {
// return exc.code();
_lastError = exc.code();
}
}
return MccGenericFsmMountErrorCode::ERROR_OK;
// return MccGenericFsmMountErrorCode::ERROR_OK;
return _lastError;
}
@ -607,47 +649,16 @@ public:
try {
this->dispatchEvent(MccGenericFsmMountStopEvent{this});
} catch (std::system_error const& exc) {
return exc.code();
if (exc.code().category() == fsm::MccFiniteStateMachineCategory::get()) {
_lastError = MccGenericFsmMountErrorCode::ERROR_INVALID_OPERATION;
} else {
// return exc.code();
_lastError = exc.code();
}
}
return MccGenericFsmMountErrorCode::ERROR_OK;
}
protected:
// wrappers
auto _initMount()
{
return MOUNT_T::initMount();
}
auto _stopMount()
{
return MOUNT_T::stopMount();
}
auto _slewToTarget()
{
return MOUNT_T::slewToTarget();
}
auto _trackTarget()
{
return MOUNT_T::trackTarget();
}
auto _startGuidingTarget()
{
return MOUNT_T::startGuidingTarget();
}
auto _stopGuidingTarget()
{
return MOUNT_T::stopGuidingTarget();
// return MccGenericFsmMountErrorCode::ERROR_OK;
return _lastError;
}
};

View File

@ -167,6 +167,17 @@ static constexpr ErrT mcc_deduce_error(const DErrT& err, const ErrT& default_err
}
}
template <mcc_error_c ErrT, mcc_error_c DErrT>
static constexpr std::error_code mcc_deduce_error_code(const DErrT& err, const ErrT& default_err)
requires(std::is_error_code_enum_v<ErrT> || std::derived_from<ErrT, std::error_code>)
{
if constexpr (std::is_error_code_enum_v<DErrT>) {
return err;
} else {
return default_err;
}
}
/* ATMOSPHERIC REFRACTION MODEL CLASS CONCEPT */

View File

@ -306,14 +306,6 @@ struct MccGenericEqtHrzCoords : MccGenericCelestialPoint<CoordT> {
typedef MccGenericEqtHrzCoords<MccCelestialPoint::coord_t> MccEqtHrzCoords;
template <mcc_angle_c CoordT>
struct MccGenericPointingTarget : MccGenericEqtHrzCoords<CoordT> {
using typename MccGenericEqtHrzCoords<CoordT>::coord_t;
coord_t RA_ICRS{}, DEC_ICRS{};
};
typedef MccGenericPointingTarget<MccCelestialPoint::coord_t> MccPointingTarget;
static constexpr void mcc_copy_eqt_hrz_coord(mcc_eqt_hrz_coord_c auto const& from_pt, mcc_eqt_hrz_coord_c auto* to_pt)
{
@ -349,64 +341,84 @@ static constexpr void mcc_copy_eqt_hrz_coord(mcc_eqt_hrz_coord_c auto const& fro
template <typename T>
concept mcc_ccte_c = requires(const T t_const, T t) {
{ t_const.nameCCTE() } -> std::formattable<char>;
{ t_const.nameCCTE() } -> std::formattable<char>; // just a name
requires mcc_refract_model_c<typename T::refract_model_t>;
{ t.refractionModel(std::declval<typename T::refract_model_t*>()) } -> mcc_error_c;
/* there is no way to declare a concept for a class templated method, so mandatory implementation is only required
for default MCC library types */
[](T tt) -> mcc_error_c auto {
MccTimePoint tp{};
double jd, st, pa, dZ;
// timepointToJulday(mcc_time_point_c auto tp, mcc_julday_c auto* julday)
{ t.timepointToJulday(std::declval<MccTimePoint>(), std::declval<double*>()) } -> mcc_error_c;
{ t.timepointToJulday(std::declval<MccTimePoint>(), std::declval<MccJulianDay*>()) } -> mcc_error_c;
MccJulianDay jd_class;
// timepointToAppSideral(mcc_time_point_c auto tp, mcc_angle_c auto* st, bool islocal)
{
t.timepointToAppSideral(std::declval<MccTimePoint>(), std::declval<double*>(), std::declval<bool>())
} -> mcc_error_c;
{
t.timepointToAppSideral(std::declval<MccTimePoint>(), std::declval<MccAngle*>(), std::declval<bool>())
} -> mcc_error_c;
MccAngle st_class, pa_class, dZ_class;
MccCelestialPoint cp;
MccGenericCelestialPoint<MccAngle> cp_class;
MccEqtHrzCoords eqhr;
MccGenericEqtHrzCoords<MccAngle> eqhr_class;
// juldayToAppSideral(mcc_julday_c auto jd, mcc_angle_c auto* st, bool islocal)
{ t.juldayToAppSideral(std::declval<double>(), std::declval<double*>(), std::declval<bool>()) } -> mcc_error_c;
{ t.juldayToAppSideral(std::declval<double>(), std::declval<MccAngle*>(), std::declval<bool>()) } -> mcc_error_c;
{
t.juldayToAppSideral(std::declval<MccJulianDay>(), std::declval<double*>(), std::declval<bool>())
} -> mcc_error_c;
{
t.juldayToAppSideral(std::declval<MccJulianDay>(), std::declval<MccAngle*>(), std::declval<bool>())
} -> mcc_error_c;
auto ret = tt.timepointToJulday(tp, &jd);
ret = tt.timepointToJulday(tp, &jd_class);
// NOTE: ASSUMING THE AZIMUTH IS COUNTED FROM THE SOUTH THROUGH THE WEST!!!
// transformCoordinates(mcc_celestial_point_c auto from_pt, mcc_celestial_point_c auto* to_pt)
{ t.transformCoordinates(std::declval<MccCelestialPoint>(), std::declval<MccCelestialPoint*>()) } -> mcc_error_c;
{
t.transformCoordinates(std::declval<MccCelestialPoint>(), std::declval<MccGenericCelestialPoint<MccAngle>*>())
} -> mcc_error_c;
{
t.transformCoordinates(std::declval<MccGenericCelestialPoint<MccAngle>>(), std::declval<MccCelestialPoint*>())
} -> mcc_error_c;
{
t.transformCoordinates(std::declval<MccGenericCelestialPoint<MccAngle>>(),
std::declval<MccGenericCelestialPoint<MccAngle>*>())
} -> mcc_error_c;
{ t.transformCoordinates(std::declval<MccCelestialPoint>(), std::declval<MccEqtHrzCoords*>()) } -> mcc_error_c;
{
t.transformCoordinates(std::declval<MccCelestialPoint>(), std::declval<MccGenericEqtHrzCoords<MccAngle>*>())
} -> mcc_error_c;
{
t.transformCoordinates(std::declval<MccGenericCelestialPoint<MccAngle>>(), std::declval<MccEqtHrzCoords*>())
} -> mcc_error_c;
{
t.transformCoordinates(std::declval<MccGenericCelestialPoint<MccAngle>>(),
std::declval<MccGenericEqtHrzCoords<MccAngle>*>())
} -> mcc_error_c;
ret = tt.timepointToAppSideral(tp, &st, true);
ret = tt.timepointToAppSideral(tp, &st_class, true);
// parallacticAngle(mcc_celestial_point_c auto pt, mcc_angle_c auto* pa)
{ t.parallacticAngle(std::declval<MccCelestialPoint>(), std::declval<double*>()) } -> mcc_error_c;
{ t.parallacticAngle(std::declval<MccCelestialPoint>(), std::declval<MccAngle*>()) } -> mcc_error_c;
{ t.parallacticAngle(std::declval<MccGenericCelestialPoint<MccAngle>>(), std::declval<double*>()) } -> mcc_error_c;
{
t.parallacticAngle(std::declval<MccGenericCelestialPoint<MccAngle>>(), std::declval<MccAngle*>())
} -> mcc_error_c;
ret = tt.timepointToAppSideral(jd, &st, true);
ret = tt.timepointToAppSideral(jd, &st_class, true);
ret = tt.timepointToAppSideral(jd_class, &st, true);
ret = tt.timepointToAppSideral(jd_class, &st_class, true);
// NOTE: ASSUMING THE AZIMUTH IS COUNTED FROM THE SOUTH THROUGH THE WEST!!!
ret = tt.transformCoordinates(cp, &cp);
ret = tt.transformCoordinates(cp, &cp_class);
ret = tt.transformCoordinates(cp_class, &cp);
ret = tt.transformCoordinates(cp_class, &cp_class);
ret = tt.transformCoordinates(cp, &eqhr);
ret = tt.transformCoordinates(cp, &eqhr_class);
ret = tt.transformCoordinates(cp_class, &eqhr);
ret = tt.transformCoordinates(cp_class, &eqhr_class);
ret = tt.parallacticAngle(cp, &pa);
ret = tt.parallacticAngle(cp, &pa_class);
ret = tt.parallacticAngle(cp_class, &pa);
ret = tt.parallacticAngle(cp_class, &pa_class);
ret = tt.refractionCorrection(cp, &dZ);
ret = tt.refractionCorrection(cp, &dZ_class);
ret = tt.refractionCorrection(cp_class, &dZ);
ret = tt.refractionCorrection(cp_class, &dZ_class);
return ret;
}(t);
// refractionCorrection(mcc_celestial_point_c auto pt, mcc_angle_c auto* dZ)
{ t.refractionCorrection(std::declval<MccCelestialPoint>(), std::declval<double*>()) } -> mcc_error_c;
{ t.refractionCorrection(std::declval<MccCelestialPoint>(), std::declval<MccAngle*>()) } -> mcc_error_c;
{
t.refractionCorrection(std::declval<MccGenericCelestialPoint<MccAngle>>(), std::declval<double*>())
} -> mcc_error_c;
{
t.refractionCorrection(std::declval<MccGenericCelestialPoint<MccAngle>>(), std::declval<MccAngle*>())
} -> mcc_error_c;
};
@ -436,83 +448,181 @@ concept mcc_PCM_c = requires(T t) {
return val;
}(); // to ensure 'mountType' can be used in compile-time context
[](T tt) -> mcc_error_c auto {
MccPCMResult res;
MccGenericPCMResult<MccAngle> res_class;
/* there is no way to declare a concept for a class templated method, so mandatory implementation is only required
for default MCC library types */
MccCelestialPoint cp;
MccGenericCelestialPoint<MccAngle> cp_class;
MccEqtHrzCoords eqhr;
MccGenericEqtHrzCoords<MccAngle> eqhr_class;
// the templated method signature:
// computePCM(mcc_celestial_point_c auto pt, mcc_PCM_result_c auto* result, mcc_celestial_point_c auto* app_pt)
// pt - hardware (encoder) coordinates for which PCM needs to be calculated (pt.pair_kind is ignored!),
// app_pt: app_pt->X = pt.X + result->pcmX
// app_pt->Y = pt.Y + result->pcmY
{
t.computePCM(std::declval<MccCelestialPoint>(), std::declval<MccPCMResult*>(),
std::declval<MccCelestialPoint*>())
} -> mcc_error_c;
{
t.computePCM(std::declval<MccCelestialPoint>(), std::declval<MccGenericPCMResult<MccAngle>*>(),
std::declval<MccCelestialPoint*>())
} -> mcc_error_c;
{
t.computePCM(std::declval<MccGenericCelestialPoint<MccAngle>>(), std::declval<MccPCMResult*>(),
std::declval<MccCelestialPoint*>())
} -> mcc_error_c;
{
t.computePCM(std::declval<MccGenericCelestialPoint<MccAngle>>(), std::declval<MccGenericPCMResult<MccAngle>*>(),
std::declval<MccCelestialPoint*>())
} -> mcc_error_c;
// computePCM(mcc_celestial_point_c auto pt, mcc_PCM_result_c auto* result, mcc_celestial_point_c auto* app_pt)
{
t.computePCM(std::declval<MccCelestialPoint>(), std::declval<MccPCMResult*>(),
std::declval<MccGenericCelestialPoint<MccAngle>*>())
} -> mcc_error_c;
{
t.computePCM(std::declval<MccCelestialPoint>(), std::declval<MccGenericPCMResult<MccAngle>*>(),
std::declval<MccGenericCelestialPoint<MccAngle>*>())
} -> mcc_error_c;
{
t.computePCM(std::declval<MccGenericCelestialPoint<MccAngle>>(), std::declval<MccPCMResult*>(),
std::declval<MccGenericCelestialPoint<MccAngle>*>())
} -> mcc_error_c;
{
t.computePCM(std::declval<MccGenericCelestialPoint<MccAngle>>(), std::declval<MccGenericPCMResult<MccAngle>*>(),
std::declval<MccGenericCelestialPoint<MccAngle>*>())
} -> mcc_error_c;
auto ret = tt.computePCM(cp, &res, &cp);
ret = tt.computePCM(cp, &res_class, &cp);
ret = tt.computePCM(cp_class, &res, &cp);
ret = tt.computePCM(cp_class, &res_class, &cp);
ret = tt.computePCM(cp, &res, &cp_class);
ret = tt.computePCM(cp, &res_class, &cp_class);
ret = tt.computePCM(cp_class, &res, &cp_class);
ret = tt.computePCM(cp_class, &res_class, &cp_class);
// the templated method signature:
// computePCM(mcc_celestial_point_c auto pt, mcc_PCM_result_c auto* result, mcc_eqt_hrz_coord_c auto* app_pt)
//
// for equatorial mounts the method must compute (if app_pt is not nullptr):
// app_pt->HA = pt.X + result->pcmX
// app_pt->DEC_APP = pt.Y + result->pcmY
// for alt-azimuthal:
// app_pt->AZ = pt.X + result->pcmX
// app_pt->ZD = pt.Y + result->pcmY
{
t.computePCM(std::declval<MccCelestialPoint>(), std::declval<MccPCMResult*>(), std::declval<MccEqtHrzCoords*>())
} -> mcc_error_c;
{
t.computePCM(std::declval<MccCelestialPoint>(), std::declval<MccGenericPCMResult<MccAngle>*>(),
std::declval<MccEqtHrzCoords*>())
} -> mcc_error_c;
{
t.computePCM(std::declval<MccGenericCelestialPoint<MccAngle>>(), std::declval<MccPCMResult*>(),
std::declval<MccEqtHrzCoords*>())
} -> mcc_error_c;
{
t.computePCM(std::declval<MccGenericCelestialPoint<MccAngle>>(), std::declval<MccGenericPCMResult<MccAngle>*>(),
std::declval<MccEqtHrzCoords*>())
} -> mcc_error_c;
// computePCM(mcc_celestial_point_c auto pt, mcc_PCM_result_c auto* result, mcc_eqt_hrz_coord_c auto* app_pt)
//
// for equatorial mounts the method must compute:
// app_pt->HA = pt.X + result->pcmX
// app_pt->DEC_APP = pt.Y + result->pcmY
// for alt-azimuthal:
// app_pt->AZ = pt.X + result->pcmX
// app_pt->ZD = pt.Y + result->pcmY ret = tt.computePCM(cp, &res, &eqhr);
ret = tt.computePCM(cp, &res_class, &eqhr);
ret = tt.computePCM(cp_class, &res, &eqhr);
ret = tt.computePCM(cp_class, &res_class, &eqhr);
{
t.computePCM(std::declval<MccCelestialPoint>(), std::declval<MccPCMResult*>(),
std::declval<MccGenericEqtHrzCoords<MccAngle>*>())
} -> mcc_error_c;
{
t.computePCM(std::declval<MccCelestialPoint>(), std::declval<MccGenericPCMResult<MccAngle>*>(),
std::declval<MccGenericEqtHrzCoords<MccAngle>*>())
} -> mcc_error_c;
{
t.computePCM(std::declval<MccGenericCelestialPoint<MccAngle>>(), std::declval<MccPCMResult*>(),
std::declval<MccGenericEqtHrzCoords<MccAngle>*>())
} -> mcc_error_c;
{
t.computePCM(std::declval<MccGenericCelestialPoint<MccAngle>>(), std::declval<MccGenericPCMResult<MccAngle>*>(),
std::declval<MccGenericEqtHrzCoords<MccAngle>*>())
} -> mcc_error_c;
ret = tt.computePCM(cp, &res, &eqhr_class);
ret = tt.computePCM(cp, &res_class, &eqhr_class);
ret = tt.computePCM(cp_class, &res, &eqhr_class);
ret = tt.computePCM(cp_class, &res_class, &eqhr_class);
// computeInversePCM(mcc_celestial_point_c auto pt, mcc_PCM_result_c auto* result, mcc_celestial_point_c auto*
// app_pt)
// the templated method signature:
// computeInversePCM(mcc_celestial_point_c auto app_pt, mcc_PCM_result_c auto* result, mcc_celestial_point_c auto*
// hw_pt)
//
// app_pt - apparent celestial coordinates for which inverted PCM needs to be calculated.
// app_pt.X and app_pt.Y are assumed to be HA and DEC for equatorial mounts; AZ and ZD for alt-azimuthal
// ones (app_pt.pair_kind is ignored!)
// hw_pt - computed hardware (encoder) coordinates
{
t.computeInversePCM(std::declval<MccCelestialPoint>(), std::declval<MccPCMResult*>(),
std::declval<MccCelestialPoint*>())
} -> mcc_error_c;
{
t.computeInversePCM(std::declval<MccCelestialPoint>(), std::declval<MccGenericPCMResult<MccAngle>*>(),
std::declval<MccCelestialPoint*>())
} -> mcc_error_c;
{
t.computeInversePCM(std::declval<MccGenericCelestialPoint<MccAngle>>(), std::declval<MccPCMResult*>(),
std::declval<MccCelestialPoint*>())
} -> mcc_error_c;
{
t.computeInversePCM(std::declval<MccGenericCelestialPoint<MccAngle>>(),
std::declval<MccGenericPCMResult<MccAngle>*>(), std::declval<MccCelestialPoint*>())
} -> mcc_error_c;
ret = tt.computeInversePCM(cp, &res, &cp);
ret = tt.computeInversePCM(cp, &res_class, &cp);
ret = tt.computeInversePCM(cp_class, &res, &cp);
ret = tt.computeInversePCM(cp_class, &res_class, &cp);
{
t.computeInversePCM(std::declval<MccCelestialPoint>(), std::declval<MccPCMResult*>(),
std::declval<MccGenericCelestialPoint<MccAngle>*>())
} -> mcc_error_c;
{
t.computeInversePCM(std::declval<MccCelestialPoint>(), std::declval<MccGenericPCMResult<MccAngle>*>(),
std::declval<MccGenericCelestialPoint<MccAngle>*>())
} -> mcc_error_c;
{
t.computeInversePCM(std::declval<MccGenericCelestialPoint<MccAngle>>(), std::declval<MccPCMResult*>(),
std::declval<MccGenericCelestialPoint<MccAngle>*>())
} -> mcc_error_c;
{
t.computeInversePCM(std::declval<MccGenericCelestialPoint<MccAngle>>(),
std::declval<MccGenericPCMResult<MccAngle>*>(),
std::declval<MccGenericCelestialPoint<MccAngle>*>())
} -> mcc_error_c;
ret = tt.computeInversePCM(cp, &res, &cp_class);
ret = tt.computeInversePCM(cp, &res_class, &cp_class);
ret = tt.computeInversePCM(cp_class, &res, &cp_class);
ret = tt.computeInversePCM(cp_class, &res_class, &cp_class);
// computeInversePCM(mcc_eqt_hrz_coord_c auto pt, mcc_PCM_result_c auto* result, mcc_celestial_point_c auto*
// app_pt)
//
// NOTE: for computation of the corrections the method must use of app_pt.X and app_pt.Y
//
// for equatorial mounts the method must compute:
// hw_pt->X = app_pt.HA + inv_result.pcmX
// hw_pt->Y = app_pt.DEC_APP + inv_result.pcmY
// and inputs for the corrections computing are app_pt.HA and app_pt.DEC_APP
// for alt-azimuthal:
// hw_pt->X = app_pt.AZ + inv_result.pcmX
// hw_pt->Y = app_pt.ZD + inv_result.pcmY
// and inputs for the corrections computing are app_pt.ZA and app_pt.ZD ret =
// tt.computeInversePCM(eqhr, &res, &cp);
ret = tt.computeInversePCM(eqhr, &res_class, &cp);
ret = tt.computeInversePCM(eqhr_class, &res, &cp);
ret = tt.computeInversePCM(eqhr_class, &res_class, &cp);
// the templated method signature:
// computeInversePCM(mcc_eqt_hrz_coord_c auto app_pt, mcc_PCM_result_c auto* result, mcc_celestial_point_c auto*
// hw_pt)
//
// for equatorial mounts the method must compute:
// hw_pt->X = app_pt.HA + inv_result.pcmX
// hw_pt->Y = app_pt.DEC_APP + inv_result.pcmY
// for alt-azimuthal:
// hw_pt->X = app_pt.AZ + inv_result.pcmX
// hw_pt->Y = app_pt.ZD + inv_result.pcmY
{
t.computeInversePCM(std::declval<MccEqtHrzCoords>(), std::declval<MccPCMResult*>(),
std::declval<MccCelestialPoint*>())
} -> mcc_error_c;
{
t.computeInversePCM(std::declval<MccEqtHrzCoords>(), std::declval<MccGenericPCMResult<MccAngle>*>(),
std::declval<MccCelestialPoint*>())
} -> mcc_error_c;
{
t.computeInversePCM(std::declval<MccGenericEqtHrzCoords<MccAngle>>(), std::declval<MccPCMResult*>(),
std::declval<MccCelestialPoint*>())
} -> mcc_error_c;
{
t.computeInversePCM(std::declval<MccGenericEqtHrzCoords<MccAngle>>(),
std::declval<MccGenericPCMResult<MccAngle>*>(), std::declval<MccCelestialPoint*>())
} -> mcc_error_c;
ret = tt.computeInversePCM(eqhr, &res, &cp_class);
ret = tt.computeInversePCM(eqhr, &res_class, &cp_class);
ret = tt.computeInversePCM(eqhr_class, &res, &cp_class);
ret = tt.computeInversePCM(eqhr_class, &res_class, &cp_class);
return ret;
}(t);
{
t.computeInversePCM(std::declval<MccEqtHrzCoords>(), std::declval<MccPCMResult*>(),
std::declval<MccGenericCelestialPoint<MccAngle>*>())
} -> mcc_error_c;
{
t.computeInversePCM(std::declval<MccEqtHrzCoords>(), std::declval<MccGenericPCMResult<MccAngle>*>(),
std::declval<MccGenericCelestialPoint<MccAngle>*>())
} -> mcc_error_c;
{
t.computeInversePCM(std::declval<MccGenericEqtHrzCoords<MccAngle>>(), std::declval<MccPCMResult*>(),
std::declval<MccGenericCelestialPoint<MccAngle>*>())
} -> mcc_error_c;
{
t.computeInversePCM(std::declval<MccGenericEqtHrzCoords<MccAngle>>(),
std::declval<MccGenericPCMResult<MccAngle>*>(),
std::declval<MccGenericCelestialPoint<MccAngle>*>())
} -> mcc_error_c;
};
/* MOUNT HARDWARE ABSTRACTION CLASS CONCEPT */
@ -602,8 +712,9 @@ concept mcc_hardware_c = requires(T t, const T t_const) {
/* MOUNT TELEMETRY DATA CLASS CONCEPT */
/* MOUNT TELEMETRY DATA CLASS CONCEPT */
// target coordinates class concept
template <typename T>
concept mcc_pointing_target_coord_c = mcc_eqt_hrz_coord_c<T> && requires(T t) {
requires mcc_angle_c<decltype(t.RA_ICRS)>; // ICRS right ascention
@ -611,6 +722,16 @@ concept mcc_pointing_target_coord_c = mcc_eqt_hrz_coord_c<T> && requires(T t) {
};
template <mcc_angle_c CoordT>
struct MccGenericPointingTarget : MccGenericEqtHrzCoords<CoordT> {
using typename MccGenericEqtHrzCoords<CoordT>::coord_t;
coord_t RA_ICRS{}, DEC_ICRS{};
};
typedef MccGenericPointingTarget<MccCelestialPoint::coord_t> MccPointingTarget;
static constexpr void mcc_copy_pointing_target_coord(mcc_pointing_target_coord_c auto const& from_pt,
mcc_pointing_target_coord_c auto* to_pt)
{
@ -665,6 +786,28 @@ concept mcc_telemetry_data_c = mcc_eqt_hrz_coord_c<T> && std::default_initializa
};
/* DEFAULT TELEMETRY DATA CLASS */
template <mcc_angle_c CoordT>
struct MccGenericTelemetryData : MccGenericEqtHrzCoords<CoordT> {
using typename MccGenericEqtHrzCoords<CoordT>::coord_t;
MccJulianDay JD;
coord_t LST; // local apparent sideral time
MccGenericPointingTarget<coord_t> target{};
coord_t speedX, speedY;
coord_t pcmX, pcmY;
coord_t refCorr;
};
typedef MccGenericTelemetryData<MccCelestialPoint::coord_t> MccTelemetryData;
static constexpr void mcc_copy_telemetry_data(mcc_telemetry_data_c auto const& from_pt,
mcc_telemetry_data_c auto* to_pt)
{
@ -707,7 +850,7 @@ static constexpr void mcc_copy_telemetry_data(mcc_telemetry_data_c auto const& f
/* MOUNT TELEMETRY MANAGER CLASS CONCEPT */
/* MOUNT TELEMETRY MANAGER CLASS CONCEPT */
template <mcc_error_c RetT>
struct mcc_telemetry_interface_t {
@ -774,8 +917,34 @@ protected:
mcc_telemetry_interface_t() = default;
};
// template <typename T>
// concept mcc_telemetry_c = std::derived_from<T, mcc_telemetry_interface_t<typename T::error_t>>;
template <typename T>
concept mcc_telemetry_c = std::derived_from<T, mcc_telemetry_interface_t<typename T::error_t>>;
concept mcc_telemetry_c = requires(T t) {
// update telemetry data right now
{ t.updateTelemetryData() } -> mcc_error_c;
// get current data
// an implementation is expected to return current, possibly already expired, telemetry data
// one should call consistently both 'updateTelemetryData' + 'telemetryData' methods
// to ensure that the data is up-to-date
//
// templated method signature
// telemetryData(mcc_telemetry_data_c auto* data)
{ t.telemetryData(std::declval<MccTelemetryData*>()) } -> mcc_error_c;
{ t.telemetryData(std::declval<MccGenericTelemetryData<MccAngle>*>()) } -> mcc_error_c;
// waiting for updated data
// an implementation is expected to block the current thread waiting for
// telemetry data to be updated (internal synchronization)
//
// templated method signature
// waitForTelemetryData(mcc_telemetry_data_c auto* data)
{ t.waitForTelemetryData(std::declval<MccTelemetryData*>()) } -> mcc_error_c;
{ t.waitForTelemetryData(std::declval<MccGenericTelemetryData<MccAngle>*>()) } -> mcc_error_c;
};