...
This commit is contained in:
@@ -19,7 +19,10 @@ enum class MccSimpleGuidingModelErrorCode : int {
|
||||
ERROR_ASTROM_COMP,
|
||||
ERROR_TELEMETRY_DATA,
|
||||
ERROR_PEC_COMP,
|
||||
ERROR_HARDWARE_SETPOS,
|
||||
ERROR_INVALID_CONTEXT_PARAM,
|
||||
ERROR_INVALID_THRESH,
|
||||
ERROR_INVALID_CORR_RANGE,
|
||||
};
|
||||
|
||||
} // namespace mcc
|
||||
@@ -56,12 +59,22 @@ struct MccSimpleGuidingModelCategory : public std::error_category {
|
||||
switch (err) {
|
||||
case MccSimpleGuidingModelErrorCode::ERROR_OK:
|
||||
return "OK";
|
||||
case MccSimpleGuidingModelErrorCode::ERROR_UNSUPPORTED_COORD_PAIR:
|
||||
return "slew model: unsupported coordinate pair";
|
||||
case MccSimpleGuidingModelErrorCode::ERROR_ASTROM_COMP:
|
||||
return "guiding model: cannot perform astrometrical computations";
|
||||
case MccSimpleGuidingModelErrorCode::ERROR_TELEMETRY_DATA:
|
||||
return "guiding model: cannot get telemetry data";
|
||||
case MccSimpleGuidingModelErrorCode::ERROR_PEC_COMP:
|
||||
return "guiding model: cannot compute PEC corrections";
|
||||
case MccSimpleGuidingModelErrorCode::ERROR_HARDWARE_SETPOS:
|
||||
return "guiding model: cannot set position";
|
||||
case MccSimpleGuidingModelErrorCode::ERROR_INVALID_CONTEXT_PARAM:
|
||||
return "guiding model: invalid context parameter";
|
||||
case MccSimpleGuidingModelErrorCode::ERROR_INVALID_THRESH:
|
||||
return "guiding model: invalid guiding residual threshold";
|
||||
case MccSimpleGuidingModelErrorCode::ERROR_INVALID_CORR_RANGE:
|
||||
return "guiding model: invalid guiding correction range";
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
}
|
||||
@@ -123,34 +136,38 @@ public:
|
||||
typedef std::error_code error_t;
|
||||
|
||||
struct guiding_context_t {
|
||||
double corrThresh{MccAngle("00:00:00.2"_dms)}; // correction threshold
|
||||
double corrThresh{MccAngle("00:00:00.2"_dms)}; // correction threshold
|
||||
double correctionRange[2]{MccAngle("00:00:00.5"_dms), MccAngle("00:00:05"_dms)};
|
||||
|
||||
std::chrono::duration<double> predictedTrackDuration{10.0}; // 10 seconds
|
||||
std::chrono::duration<double> predictedTrackResolution{0.1}; // 0.1 seconds
|
||||
};
|
||||
|
||||
struct guiding_point_t {
|
||||
typedef double coord_t;
|
||||
typedef MccCelestialPoint guiding_point_t;
|
||||
|
||||
mcc::MccCoordPairKind coordPairKind{mcc::MccCoordPairKind::COORDS_KIND_RADEC_ICRS};
|
||||
// struct guiding_point_t {
|
||||
// typedef double coord_t;
|
||||
|
||||
coord_t x, y;
|
||||
};
|
||||
// mcc::MccCoordPairKind coordPairKind{mcc::MccCoordPairKind::COORDS_KIND_RADEC_ICRS};
|
||||
|
||||
// coord_t x, y;
|
||||
// };
|
||||
|
||||
template <traits::mcc_mount_controls_c MOUNT_CONTROLS_T, typename... LoggerCtorArgTs>
|
||||
MccSimpleGuidingModel(MOUNT_CONTROLS_T& mount_controls, LoggerCtorArgTs&&... ctor_args)
|
||||
MccSimpleGuidingModel(MOUNT_CONTROLS_T& mount_controls, guiding_context_t context, LoggerCtorArgTs&&... ctor_args)
|
||||
requires(!std::same_as<LoggerT, MccNullLogger>)
|
||||
: LoggerT(std::forward<LoggerCtorArgTs>(ctor_args)...)
|
||||
{
|
||||
logDebug(std::format("Create 'MccSimpleGuidingModel' class instance ({})", (void*)this));
|
||||
|
||||
init(mount_controls);
|
||||
init(mount_controls, std::move(context));
|
||||
}
|
||||
|
||||
template <traits::mcc_mount_controls_c MOUNT_CONTROLS_T>
|
||||
MccSimpleGuidingModel(MOUNT_CONTROLS_T& mount_controls)
|
||||
MccSimpleGuidingModel(MOUNT_CONTROLS_T& mount_controls, guiding_context_t context)
|
||||
requires(std::same_as<LoggerT, MccNullLogger>)
|
||||
{
|
||||
init(mount_controls);
|
||||
init(mount_controls, std::move(context));
|
||||
}
|
||||
|
||||
virtual ~MccSimpleGuidingModel()
|
||||
@@ -159,7 +176,20 @@ public:
|
||||
}
|
||||
|
||||
|
||||
error_t guiding(guiding_point_t guiding_point) {}
|
||||
error_t guiding(guiding_point_t guiding_point)
|
||||
{
|
||||
return _guidingFunc(std::move(guiding_point));
|
||||
}
|
||||
|
||||
error_t stopGuiding(bool off)
|
||||
{
|
||||
_doCorrection = off;
|
||||
}
|
||||
|
||||
bool inGuiding()
|
||||
{
|
||||
return _doCorrection;
|
||||
}
|
||||
|
||||
protected:
|
||||
std::function<error_t()> _guidingFunc{};
|
||||
@@ -182,10 +212,63 @@ protected:
|
||||
return MccSimpleGuidingModelErrorCode::ERROR_INVALID_CONTEXT_PARAM;
|
||||
}
|
||||
|
||||
auto resi_thresh2 = context.corrThresh * context.corrThresh;
|
||||
|
||||
if (utils::isEqual(resi_thresh2, 0.0)) {
|
||||
return MccSimpleGuidingModelErrorCode::ERROR_INVALID_THRESH;
|
||||
}
|
||||
|
||||
const auto p_mount_controls = &mount_controls;
|
||||
|
||||
_guidingFunc = [p_mount_controls, context = std::move(context), predicted_Npoints](
|
||||
auto check_zones = [p_mount_controls, this]() {
|
||||
return [this]<size_t... Is>(std::index_sequence<Is...>) {
|
||||
error_t ret;
|
||||
|
||||
(
|
||||
[&ret]() {
|
||||
if constexpr (Is > 0) {
|
||||
if (ret) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
typename telemetry_t::mount_telemetry_data_t tdata;
|
||||
|
||||
auto tel_err = p_mount_controls->telemetry.data(tdata);
|
||||
if (tel_err) {
|
||||
if constexpr (std::same_as<decltype(tel_err), error_t>) {
|
||||
ret = tel_err;
|
||||
} else {
|
||||
ret = MccSimpleGuidingModelErrorCode::ERROR_TELEMETRY_DATA;
|
||||
}
|
||||
} else {
|
||||
ret = std::get<Is>(p_mount_controls->prohibitedZones).inZone(tdata)
|
||||
? MccSimpleGuidingModelErrorCode::ERROR_IN_PROHIBITED_ZONE
|
||||
: MccSimpleGuidingModelErrorCode::ERROR_OK;
|
||||
if (ret) {
|
||||
auto log_str = std::format("given coordinates are in prohibited zone '{}'",
|
||||
std::get<Is>(p_mount_controls->prohibitedZones).name());
|
||||
logError(log_str);
|
||||
}
|
||||
}
|
||||
}(),
|
||||
...);
|
||||
|
||||
|
||||
return ret;
|
||||
}(std::make_index_sequence<Nzones>{});
|
||||
};
|
||||
|
||||
|
||||
_guidingFunc = [p_mount_controls, context = std::move(context), predicted_Npoints, this](
|
||||
this auto&& self, guiding_point_t guiding_point) {
|
||||
if (context.correctionRange[0] >= context.correctionRange[1]) {
|
||||
return MccSimpleGuidingModelErrorCode::ERROR_INVALID_THRESH;
|
||||
}
|
||||
|
||||
auto low_corr_limit = context.correctionRange[0] * context.correctionRange[0];
|
||||
auto high_corr_limit = context.correctionRange[1] * context.correctionRange[1];
|
||||
|
||||
auto& astrom_engine = p_mount_controls->astrometryEngine;
|
||||
auto& hardware = p_mount_controls->hardware;
|
||||
auto& pec = p_mount_controls->PEC;
|
||||
@@ -196,8 +279,6 @@ protected:
|
||||
jd_t jd;
|
||||
|
||||
|
||||
typename hardware_t::axes_pos_t ax_pos;
|
||||
|
||||
error_t res_err;
|
||||
typename astrom_engine_t::error_t ast_err;
|
||||
typename pec_t::error_t pec_err;
|
||||
@@ -297,7 +378,7 @@ protected:
|
||||
}
|
||||
|
||||
if (guiding_point.coordPairKind != mcc::MccCoordPairKind::COORDS_KIND_RADEC_ICRS) {
|
||||
ast_err = astrom_engine.greg2jul(std::chrono::system_clock::now(), jd);
|
||||
ast_err = astrom_engine.greg2jul(astrom_engine_t::timePointNow(), jd);
|
||||
if (!ast_err) {
|
||||
ast_err = astrom_engine.obs2icrs(guiding_point.coordPairKind, guiding_point.x, guiding_point.y, jd,
|
||||
ra_icrs, dec_icrs);
|
||||
@@ -321,11 +402,33 @@ protected:
|
||||
|
||||
|
||||
coord_t ha, ra_app, dec_app, az, alt, eo;
|
||||
coord_t xr, yr, coord_diff;
|
||||
typename hardware_t::axes_pos_t ax_pos;
|
||||
|
||||
while (true) {
|
||||
// check prohibited zones ...
|
||||
ast_err = astrom_engine.greg2jul(std::chrono::system_clock::now(), jd);
|
||||
ast_err = astrom_engine.icrs2obs(ra_icrs, dec_icrs, jd, ra_app, dec_app, ha, az, alt, eo);
|
||||
if ((res_err = check_zones())) {
|
||||
return res_err;
|
||||
}
|
||||
|
||||
ast_err = astrom_engine.greg2jul(astrom_engine_t::timePointNow(), jd);
|
||||
if (!ast_err) {
|
||||
ast_err = astrom_engine.icrs2obs(ra_icrs, dec_icrs, jd, ra_app, dec_app, ha, az, alt, eo);
|
||||
}
|
||||
if (ast_err) {
|
||||
if constexpr (std::same_as<decltype(ast_err), error_t>) {
|
||||
logError(
|
||||
std::format("An error occured while performing astrometry computations: code = {} ({})",
|
||||
ast_err.value(), ast_err.message()));
|
||||
return ast_err;
|
||||
} else {
|
||||
if constexpr (traits::mcc_formattable<decltype(ast_err)>) {
|
||||
logError(std::format("An error occured while performing astrometry computations: code = {}",
|
||||
ast_err));
|
||||
}
|
||||
return MccSimpleGuidingModelErrorCode::ERROR_ASTROM_COMP;
|
||||
}
|
||||
}
|
||||
|
||||
t_err = telemetry.data(t_data);
|
||||
if (t_err) {
|
||||
@@ -342,6 +445,50 @@ protected:
|
||||
}
|
||||
|
||||
// compare t_data with computed coordinates ...
|
||||
if (_doCorrection) {
|
||||
if constexpr (mccIsEquatorialMount(pec_t::mountType)) {
|
||||
xr = t_data.mntHA - ha;
|
||||
yr = t_data.mntDEC - dec_app;
|
||||
} else if constexpr (mccIsAltAzMount(pec_t::mountType)) {
|
||||
xr = t_data.mntAZ - az;
|
||||
yr = t_data.mntALT - alt;
|
||||
} else {
|
||||
static_assert(false, "UNSUPPORTED MOUNT TYPE!");
|
||||
}
|
||||
|
||||
coord_diff = xr * xr + yr * yr;
|
||||
|
||||
if (coord_diff < low_corr_limit) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (coord_diff > high_corr_limit) {
|
||||
logWarn(std::format(
|
||||
"guiding model: the 'mount-target' difference exceeds the limit (diff = {}; lim = {})",
|
||||
(double)coord_diff, (double)high_corr_limit));
|
||||
continue;
|
||||
}
|
||||
|
||||
// do correction
|
||||
ax_pos.state = hardware_t::hw_state_t::HW_STATE_TRACK;
|
||||
ax_pos.x = t_data.mntPosX;
|
||||
ax_pos.y = t_data.mntPosY;
|
||||
|
||||
// asynchronous operation!
|
||||
auto err = hardware.setPos(std::move(ax_pos));
|
||||
if (err) {
|
||||
if constexpr (std::same_as<decltype(err), error_t>) {
|
||||
logError(
|
||||
std::format("An hardware error occured: code = {} ({})", err.value(), err.message()));
|
||||
return err;
|
||||
} else {
|
||||
if constexpr (traits::mcc_formattable<decltype(err)>) {
|
||||
logError(std::format("An hardware error occured: code = {}", err));
|
||||
}
|
||||
return MccSimpleGuidingModelErrorCode::ERROR_HARDWARE_SETPOS;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return MccSimpleGuidingModelErrorCode::ERROR_OK;
|
||||
|
||||
Reference in New Issue
Block a user