This commit is contained in:
Timur A. Fatkhullin 2025-08-08 23:50:55 +03:00
parent c45d17b236
commit b99263a014
11 changed files with 709 additions and 197 deletions

View File

@ -18,7 +18,7 @@
namespace asibfm700
{
typedef mcc::astrom::erfa::MccMountAstromEngineERFA<mcc::MccAngle> AsibFM700AstromEngine;
typedef mcc::astrom::erfa::MccMountAstromEngineERFA AsibFM700AstromEngine;
typedef mcc::MccMountDefaultPEC<mcc::MccMountType::FORK_TYPE> AsibFM700PointingErrorCorrection;

View File

@ -10,9 +10,9 @@ AsibFM700Mount::AsibFM700Mount(AsibFM700Config config, std::shared_ptr<spdlog::l
base_gm_t({_currentConfig.astromEngineState},
{_currentConfig.hardwareConfig},
{_currentConfig.pecData},
AsibFM700Telemetry{_astromEngine, _pec, _hardware},
slew_model_t{_telemetry, _hardware, _pzFuncs},
guiding_model_t{_telemetry, _hardware, _pzFuncs})
AsibFM700Telemetry{&_astromEngine, &_pec, &_hardware},
slew_model_t{&_telemetry, &_hardware, &_pzFuncs},
guiding_model_t{&_telemetry, &_hardware, &_pzFuncs})
{
}

View File

@ -119,9 +119,9 @@ public:
traits::mcc_irange_of_pzones_c<typename TELEMETRY_T::mount_telemetry_data_t> PZ_T,
// traits::mcc_tuple_c PZ_T,
typename... LoggerCtorArgTs>
MccSimpleGuidingModel(TELEMETRY_T& telemetry,
HARDWARE_T& hardware,
PZ_T& prohibited_zone,
MccSimpleGuidingModel(TELEMETRY_T* telemetry,
HARDWARE_T* hardware,
PZ_T* prohibited_zone,
LoggerCtorArgTs&&... ctor_args)
requires(!std::same_as<LoggerT, MccNullLogger>)
: LoggerT(std::forward<LoggerCtorArgTs>(ctor_args)...)
@ -131,16 +131,16 @@ public:
init(telemetry, hardware, prohibited_zone);
}
template <traits::mcc_mount_telemetry_c TELEMETRY_T,
traits::mcc_mount_hardware_c HARDWARE_T,
traits::mcc_irange_of_pzones_c<typename TELEMETRY_T::mount_telemetry_data_t> PZ_T
// traits::mcc_tuple_c PZ_T
>
MccSimpleGuidingModel(TELEMETRY_T& telemetry, HARDWARE_T& hardware, PZ_T& prohibited_zone)
requires(std::same_as<LoggerT, MccNullLogger>)
{
init(telemetry, hardware, prohibited_zone);
}
// template <traits::mcc_mount_telemetry_c TELEMETRY_T,
// traits::mcc_mount_hardware_c HARDWARE_T,
// traits::mcc_irange_of_pzones_c<typename TELEMETRY_T::mount_telemetry_data_t> PZ_T
// // traits::mcc_tuple_c PZ_T
// >
// MccSimpleGuidingModel(TELEMETRY_T& telemetry, HARDWARE_T& hardware, PZ_T& prohibited_zone)
// requires(std::same_as<LoggerT, MccNullLogger>)
// {
// init(telemetry, hardware, prohibited_zone);
// }
MccSimpleGuidingModel(MccSimpleGuidingModel&& other)
@ -184,22 +184,22 @@ protected:
error_t init(auto& telemetry, auto& hardware, auto& prohibited_zones)
error_t init(auto* p_telemetry, auto* p_hardware, auto* p_prohibited_zones)
{
// deduce controls types
// deduce controls types
using hardware_t = decltype(hardware);
using telemetry_t = decltype(telemetry);
using hardware_t = decltype(*p_hardware);
using telemetry_t = decltype(*p_telemetry);
static_assert(traits::mcc_mount_default_telemetry_c<telemetry_t>,
"TELEMETRY CLASS MUST BE A DESCENDANT OF 'MccMountTelemetry'!");
using astrom_engine_t = typename telemetry_t::astrom_engine_t;
static constexpr size_t Nzones = std::tuple_size_v<decltype(prohibited_zones)>;
static constexpr size_t Nzones = std::tuple_size_v<decltype(*p_prohibited_zones)>;
const auto p_telemetry = &telemetry;
const auto p_hardware = &hardware;
const auto p_prohibited_zones = &prohibited_zones;
// const auto p_telemetry = &telemetry;
// const auto p_hardware = &hardware;
// const auto p_prohibited_zones = &prohibited_zones;
_guidingFunc = [p_telemetry, p_hardware, p_prohibited_zones, this](guiding_point_t guiding_point) {
_stopRequested = false;

View File

@ -107,11 +107,6 @@ inline std::error_code make_error_code(MccMountAstromEngineERFAErrorCode ec)
/* A concept for ERFA-library compatible type to represent anglular quantities */
template <typename T>
concept mcc_erfa_angle_t = std::constructible_from<T, double> && std::convertible_to<T, double>;
template <mcc_erfa_angle_t AngleT = MccAngle>
class MccMountAstromEngineERFA
{
public:
@ -119,6 +114,9 @@ public:
typedef std::error_code error_t;
/* use of the same type for representation of celestial and geodetic coordinates, celestial angles (e.g. P.A.),
* and sideral time */
typedef double coord_t;
// meteo parameters (to compute refraction)
struct meteo_t {
@ -136,9 +134,9 @@ public:
double wavelength = DEFAULT_WAVELENGTH; // observed wavelength in mkm
AngleT lat = "00:00:00"_dms; // site latitude
AngleT lon = "00:00:00"_dms; // site longitude
double elev = 0.0; // site elevation (in meters)
coord_t lat = "00:00:00"_dms; // site latitude
coord_t lon = "00:00:00"_dms; // site longitude
double elev = 0.0; // site elevation (in meters)
mcc::astrom::iers::MccLeapSeconds _leapSeconds{};
mcc::astrom::iers::MccIersBulletinA _bulletinA{};
@ -152,13 +150,10 @@ public:
};
/* use of the same type for representation of celestial and geodetic coordinates, celestial angles (e.g. P.A.),
* and sideral time */
typedef AngleT coord_t;
typedef AngleT sideral_time_t;
typedef AngleT pa_t;
typedef AngleT eo_t;
typedef coord_t sideral_time_t;
typedef coord_t pa_t;
typedef coord_t eo_t;
struct refract_result_t {
double refa, refb;
@ -556,6 +551,170 @@ public:
return MccMountAstromEngineERFAErrorCode::ERROR_OK;
}
error_t coord2coord(MccCoordPairKind coord_from_kind,
coord_t x_from,
coord_t y_from,
time_point_t time_point_from,
MccCoordPairKind coord_to_kind,
coord_t& x_to,
coord_t& y_to,
time_point_t time_point_to)
{
error_t ret = MccMountAstromEngineERFAErrorCode::ERROR_OK;
// no convertion
if (time_point_from == time_point_to && coord_from_kind == coord_to_kind) {
x_to = x_from;
y_to = y_from;
return ret;
}
juldate_t jd;
eo_t eo;
coord_t ra, dec, ha, az, alt;
sideral_time_t lst;
auto lst_eo = [&]() {
ret = greg2jul(time_point_from, jd);
if (!ret) {
ret = apparentSiderTime(jd, lst, true);
if (!ret) {
ret = eqOrigins(jd, eo);
}
}
};
// special case: to ICRS from apparent
if (coord_to_kind == MccCoordPairKind::COORDS_KIND_RADEC_ICRS) {
if (coord_to_kind == MccCoordPairKind::COORDS_KIND_AZALT ||
coord_to_kind == MccCoordPairKind::COORDS_KIND_AZZD ||
coord_to_kind == MccCoordPairKind::COORDS_KIND_RADEC_APP ||
coord_to_kind == MccCoordPairKind::COORDS_KIND_HADEC_APP) {
//
ret = greg2jul(time_point_from, jd);
if (!ret) {
ret = obs2icrs(coord_from_kind, x_from, y_from, jd, x_to, y_to);
}
} else {
ret = MccMountAstromEngineERFAErrorCode::ERROR_UNSUPPORTED_COORD_PAIR;
}
return ret;
}
// special case: from ICRS to apparent
if (coord_from_kind == MccCoordPairKind::COORDS_KIND_RADEC_ICRS) {
if (coord_to_kind == MccCoordPairKind::COORDS_KIND_AZALT ||
coord_to_kind == MccCoordPairKind::COORDS_KIND_AZZD ||
coord_to_kind == MccCoordPairKind::COORDS_KIND_RADEC_APP ||
coord_to_kind == MccCoordPairKind::COORDS_KIND_HADEC_APP) {
//
ret = greg2jul(time_point_to, jd);
if (!ret) {
ret = icrs2obs(x_from, y_from, jd, ra, dec, ha, az, alt, eo);
if (!ret) {
if (coord_to_kind == MccCoordPairKind::COORDS_KIND_AZALT) {
x_to = az;
y_to = alt;
} else if (coord_to_kind == MccCoordPairKind::COORDS_KIND_AZZD) {
x_to = az;
y_to = std::numbers::pi / 2.0 - alt;
} else if (coord_to_kind == MccCoordPairKind::COORDS_KIND_RADEC_APP) {
x_to = ra;
y_to = dec;
} else if (coord_to_kind == MccCoordPairKind::COORDS_KIND_HADEC_APP) {
x_to = ha;
y_to = dec;
}
}
}
} else {
ret = MccMountAstromEngineERFAErrorCode::ERROR_UNSUPPORTED_COORD_PAIR;
}
return ret;
}
// from apparent to apparent
if (time_point_from != time_point_to) { // first, convert 'from' coordinates to ICRS
ret = greg2jul(time_point_from, jd);
if (!ret) {
ret = obs2icrs(coord_from_kind, x_from, y_from, jd, ra, dec);
if (!ret) { // from ICRS to required
return coord2coord(MccCoordPairKind::COORDS_KIND_RADEC_ICRS, ra, dec, time_point_from,
coord_to_kind, x_to, y_to, time_point_to);
}
}
} else { // same time points
if (coord_from_kind == MccCoordPairKind::COORDS_KIND_RADEC_APP) {
// first, compute HA from CIO-based RA!!!
lst_eo();
if (!ret) {
ha = lst - x_from + eo;
} else {
return ret;
}
if (coord_to_kind == MccCoordPairKind::COORDS_KIND_AZALT) {
ret = hadec2azalt(ha, y_from, x_to, y_to);
} else if (coord_to_kind == MccCoordPairKind::COORDS_KIND_AZZD) {
ret = hadec2azalt(ha, y_from, x_to, y_to);
if (!ret) {
y_to = std::numbers::pi / 2.0 - y_to;
}
} else if (coord_to_kind == MccCoordPairKind::COORDS_KIND_HADEC_APP) {
x_to = ha;
y_to = y_from;
} else {
ret = MccMountAstromEngineERFAErrorCode::ERROR_UNSUPPORTED_COORD_PAIR;
}
} else if (coord_from_kind == MccCoordPairKind::COORDS_KIND_HADEC_APP) {
if (coord_to_kind == MccCoordPairKind::COORDS_KIND_AZALT) {
ret = hadec2azalt(x_from, y_from, x_to, y_to);
} else if (coord_to_kind == MccCoordPairKind::COORDS_KIND_AZZD) {
ret = hadec2azalt(x_from, y_from, x_to, y_to);
if (!ret) {
y_to = std::numbers::pi / 2.0 - y_to;
}
} else if (coord_to_kind == MccCoordPairKind::COORDS_KIND_RADEC_APP) {
lst_eo();
if (!ret) {
x_to = lst - x_from + eo;
y_to = y_from;
}
} else {
ret = MccMountAstromEngineERFAErrorCode::ERROR_UNSUPPORTED_COORD_PAIR;
}
} else if (coord_from_kind == MccCoordPairKind::COORDS_KIND_AZALT) {
if (coord_to_kind == MccCoordPairKind::COORDS_KIND_RADEC_APP) {
ret = azalt2hadec(x_from, y_from, x_to, y_to);
if (!ret) {
lst_eo();
if (!ret) {
x_to = lst - x_to + eo;
}
}
} else if (coord_to_kind == MccCoordPairKind::COORDS_KIND_AZZD) {
x_to = x_from;
y_to = std::numbers::pi / 2.0 - y_from;
} else if (coord_to_kind == MccCoordPairKind::COORDS_KIND_HADEC_APP) {
ret = azalt2hadec(x_from, y_from, x_to, y_to);
} else {
ret = MccMountAstromEngineERFAErrorCode::ERROR_UNSUPPORTED_COORD_PAIR;
}
} else if (coord_from_kind == MccCoordPairKind::COORDS_KIND_AZZD) {
return coord2coord(MccCoordPairKind::COORDS_KIND_AZALT, std::move(x_from),
std::numbers::pi / 2.0 - y_to, time_point_from, coord_to_kind, x_to, y_to,
time_point_to);
} else {
ret = MccMountAstromEngineERFAErrorCode::ERROR_UNSUPPORTED_COORD_PAIR;
}
}
return ret;
}
/* helper mathods */
@ -577,4 +736,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

@ -98,6 +98,43 @@ concept mcc_logger_c = requires(T t, const T t_const) {
};
/* A CONCEPT FOR COORDINATE REPRESENTATION */
// it is a fundametal floating-point type or
// a class that can be constructed from or converted to the double fundametal type
template <typename T>
concept mcc_coord_t = std::floating_point<T> || (std::convertible_to<T, double> && std::constructible_from<T, double>);
/* A CONCEPT FOR UTC TIME POINT REPRESENTATION */
// it is a std::chrono::sys_time<Duration> or
// fundamental arithmetic type that represent number of seconds after the 00:00:00 of 1 January 1970 (UNIX time)
template <typename T>
concept mcc_utc_time_point_c = mcc_systime_c<T> || std::is_arithmetic_v<T>;
/* A CONCEPT FOR CLASS TO REPRESENT CELESTIAL POINT */
template <typename T>
concept mcc_celestial_point_c = requires(T t) {
// a type to represent UTC time point of coordinates
// it's clear that this makes sense for apparent coordinates
typename T::time_point_t;
// coordinates pair type (e.g. IRCS RA,DEC, Az,Alt and so on)
requires std::same_as<decltype(t.coordPairKind), MccCoordPairKind>;
typename T::coord_t;
// co-longitude (e.g. RA or Az)
requires std::same_as<decltype(t.x), typename T::coord_t>;
// co-latitude (e.g. DEC or ZD)
requires std::same_as<decltype(t.y), typename T::coord_t>;
};
/* ASTROMETRY-RELATED COMPUTATION ENGINE */
template <typename T>
@ -128,10 +165,10 @@ concept mcc_astrom_engine_c = requires(T t, const T t_const) {
} -> std::same_as<typename T::error_t>;
// observed place to ICRS RA and DEC: obs2icrs(type, x, y, jd, ra_icrs, dec_icrs)
// (x,y) = (AZ, ZD) if type = MccCoordPairKind::COORDS_KIND_AZZD
// (x,y) = (AZ, ALT) if type = MccCoordPairKind::COORDS_KIND_AZALT
// (x,y) = (HA, DEC) if type = MccCoordPairKind::COORDS_KIND_HADEC_APP
// (x,y) = (RA, DEC) if type = MccCoordPairKind::COORDS_KIND_RADEC_APP
// (x, y) = (AZ, ZD) if type == MccCoordPairKind::COORDS_KIND_AZZD
// (x, y) = (AZ, ALT) if type == MccCoordPairKind::COORDS_KIND_AZALT
// (x, y) = (HA, DEC) if type == MccCoordPairKind::COORDS_KIND_HADEC_APP
// (x, y) = (RA, DEC) if type == MccCoordPairKind::COORDS_KIND_RADEC_APP
{
t.obs2icrs(std::declval<MccCoordPairKind>(), std::declval<typename T::coord_t>(),
std::declval<typename T::coord_t>(), std::declval<typename T::juldate_t>(),
@ -157,6 +194,26 @@ concept mcc_astrom_engine_c = requires(T t, const T t_const) {
std::declval<typename T::pa_t&>())
} -> std::same_as<typename T::error_t>;
// transform coordinates according to its pair types and time points (a high-level wrapper):
//
// coord2coord(coord_pair_kind_from, x_from, y_from, time_point_from, coord_pair_kind_to, x_to, y_to, time_point_to)
//
// (x_*, y_*) = (AZ, ZD) if coord_pair_kind_* == MccCoordPairKind::COORDS_KIND_AZZD
// (x_*, y_*) = (AZ, ALT) if coord_pair_kind_* == MccCoordPairKind::COORDS_KIND_AZALT
// (x_*, y_*) = (HA, DEC) if coord_pair_kind_* == MccCoordPairKind::COORDS_KIND_HADEC_APP (apparent)
// (x_*, y_*) = (RA, DEC) if coord_pair_kind_* == MccCoordPairKind::COORDS_KIND_RADEC_APP (apparent)
// (x_*, y_*) = (RA, DEC) if coord_pair_kind_* == MccCoordPairKind::COORDS_KIND_RADEC_ICRS (ICRS)
//
// if coord_pair_kind_* and time_point_* are equal then x_to = x_from, y_to = y_from
{
t.coord2coord(std::declval<MccCoordPairKind>(), std::declval<typename T::coord_t>(),
std::declval<typename T::coord_t>(), std::declval<typename T::time_point_t>(),
std::declval<MccCoordPairKind>(), std::declval<typename T::coord_t&>(),
std::declval<typename T::coord_t&>(), std::declval<typename T::time_point_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&>())
@ -355,23 +412,6 @@ concept mcc_mount_telemetry_c = requires(T t, const T t_const) {
};
/* A CONCEPT FOR CLASS TO REPRESENT CELESTIAL POINT */
template <typename T>
concept mcc_celestial_point_c = requires(T t) {
// input coordinates pair type (e.g. IRCS RA,DEC, Az,Alt and so on)
requires std::same_as<decltype(t.coordPairKind), MccCoordPairKind>;
typename T::coord_t;
// co-longitude (e.g. RA or Az)
requires std::same_as<decltype(t.x), typename T::coord_t>;
// co-latitude (e.g. DEC or ZD)
requires std::same_as<decltype(t.y), typename T::coord_t>;
};
// /* SLEW PARAMETERS */
@ -420,14 +460,85 @@ concept mcc_guiding_model_c = requires(T t) {
/* MOUNT PROHIBITED ZONE */
struct MccPzoneAbstractInterface {
bool inZone(this auto&& self, mcc_mount_telemetry_data_c auto const& telemetry_data)
{
using self_t = decltype(self);
if constexpr (std::same_as<std::remove_cvref_t<self_t>, MccPzoneAbstractInterface>) {
static_assert(false, "Call an empty MccPzoneAbstractInterface::inZone method");
} else {
return std::forward<self_t>(self).inZone(telemetry_data);
}
}
bool inZone(this auto&& self, mcc_celestial_point_c auto const& sky_point)
{
using self_t = decltype(self);
if constexpr (std::same_as<std::remove_cvref_t<self_t>, MccPzoneAbstractInterface>) {
static_assert(false, "Call an empty MccPzoneAbstractInterface::inZone method");
} else {
return std::forward<self_t>(self).inZone(sky_point);
}
}
// returns a time to reach the zone
auto timeTo(this auto&& self, mcc_mount_telemetry_data_c auto const& telemetry_data)
{
using self_t = decltype(self);
if constexpr (std::same_as<std::remove_cvref_t<self_t>, MccPzoneAbstractInterface>) {
static_assert(false, "Call an empty MccPzoneAbstractInterface::timeTo method");
} else {
return std::forward<self_t>(self).timeTo(telemetry_data);
}
}
auto timeTo(this auto&& self, mcc_celestial_point_c auto const& sky_point)
{
using self_t = decltype(self);
if constexpr (std::same_as<std::remove_cvref_t<self_t>, MccPzoneAbstractInterface>) {
static_assert(false, "Call an empty MccPzoneAbstractInterface::timeTo method");
} else {
return std::forward<self_t>(self).timeTo(sky_point);
}
}
// returns a time to exit from the zone
auto timeFrom(this auto&& self, mcc_mount_telemetry_data_c auto const& telemetry_data)
{
using self_t = decltype(self);
if constexpr (std::same_as<std::remove_cvref_t<self_t>, MccPzoneAbstractInterface>) {
static_assert(false, "Call an empty MccPzoneAbstractInterface::timeFrom method");
} else {
return std::forward<self_t>(self).timeFrom(telemetry_data);
}
}
auto timeFrom(this auto&& self, mcc_celestial_point_c auto const& sky_point)
{
using self_t = decltype(self);
if constexpr (std::same_as<std::remove_cvref_t<self_t>, MccPzoneAbstractInterface>) {
static_assert(false, "Call an empty MccPzoneAbstractInterface::timeFrom method");
} else {
return std::forward<self_t>(self).timeFrom(sky_point);
}
}
};
template <typename T, typename TelemetryDataT>
concept mcc_prohibited_zone_c =
mcc_mount_telemetry_data_c<TelemetryDataT> && std::movable<T> && requires(T t, const T t_const) {
// typename T::coord_t;
typename T::coord_t;
// typename T::time_point_t;
requires mcc_time_duration_c<typename T::duration_t>;
// static constexpr member to represent inifite duration
// static constexpr member to represent infinite duration
requires requires {
requires std::same_as<decltype(T::infiniteDuration), typename T::duration_t const>;
[]() {
@ -446,46 +557,11 @@ concept mcc_prohibited_zone_c =
};
// the type 'T' must define a static constexpr member of type MccCoordPairKind
// to declarate type of coordinate pair used to describe the zone.
// This coordinate pair must be used as input in the 'inZone' class method.
// requires requires {
// requires std::same_as<decltype(T::zoneCoordPairKind), const MccCoordPairKind>;
// []() {
// constexpr MccCoordPairKind val = T::zoneCoordPairKind;
// return val;
// }(); // to ensure that 'zoneCoordPairKind' can be used at compile-time context
// };
// return a name of the zone
{ t_const.name() } -> mcc_formattable;
// check if given coordinates are into the zone.
// input coordinates interpretation is in according to 'zoneCoordPairKind' static constexpr member
// {
// t.inZone(std::declval<typename T::coord_t>(), std::declval<typename T::coord_t>())
// } -> std::convertible_to<bool>;
// // for given coordinates and time the method computes a time to reach the zone.
// // implementation of the method must assume that input coordinates are apparent RA and DEC at given time
// // point, while the time point is one from which computation should be performed (e.g. current time moment)
// {
// t.timeTo(std::declval<typename T::coord_t>(), std::declval<typename T::coord_t>(),
// std::declval<typename T::time_point_t>())
// } -> mcc_time_duration_c;
// // for given coordinates and time the method computes a time to exit from the zone
// {
// t.timeFrom(std::declval<typename T::coord_t>(), std::declval<typename T::coord_t>(),
// std::declval<typename T::time_point_t>())
// } -> mcc_time_duration_c;
// requires for the methods above with the first argument of type
// 'const mcc_mount_telemetry_data_c&' (const lvalue reference)
{ t.inZone(std::declval<const TelemetryDataT&>()) } -> std::convertible_to<bool>;
// a time duration to reach the zone.
@ -500,12 +576,129 @@ concept mcc_prohibited_zone_c =
{ t.timeFrom(std::declval<const TelemetryDataT&>()) } -> std::same_as<typename T::duration_t>;
};
// an input range of prohibited zones
template <typename T, typename TelemetryDataT>
concept mcc_irange_of_pzones_c = mcc_mount_telemetry_data_c<TelemetryDataT> && std::ranges::input_range<T> &&
mcc_prohibited_zone_c<std::ranges::range_value_t<T>, TelemetryDataT>;
// // an input range of prohibited zones
// template <typename T, typename TelemetryDataT>
// concept mcc_irange_of_pzones_c = mcc_mount_telemetry_data_c<TelemetryDataT> && std::ranges::input_range<T> &&
// mcc_prohibited_zone_c<std::ranges::range_value_t<T>, TelemetryDataT>;
// // a concept for a callable with the first argument of type satisfied to 'mcc_prohibited_zone_c'
// template <typename T, typename TelemetryDataT>
// concept mcc_pzone_foreach_func_c = mcc_is_callable<T> && mcc_mount_telemetry_data_c<TelemetryDataT> &&
// mcc_prohibited_zone_c<mcc_func_arg1_t<T>, TelemetryDataT>;
// There is no way to declare a concept of class with templated method so one needs to define
// a generic interface of prohibited zones holder/container explicitly
template <mcc_mount_telemetry_data_c TelemetryDataT>
struct MccPZoneAbstractContainer {
virtual ~MccPZoneAbstractContainer() = default;
// must return a size of the container after the addition of the given zone
template <mcc_prohibited_zone_c<TelemetryDataT> ZT>
size_t pzAddZone(this auto&& self, ZT zone)
{
using self_t = decltype(self);
if constexpr (std::same_as<std::remove_cvref_t<self_t>, MccPZoneAbstractContainer>) {
static_assert(false, "Call an empty MccPZoneAbstractContainer::pzAddZone method");
} else {
return std::forward<self_t>(self).pzAddZone(std::move(zone));
}
}
// clear the container
auto pzClearZones(this auto&& self)
{
using self_t = decltype(self);
if constexpr (std::same_as<std::remove_cvref_t<self_t>, MccPZoneAbstractContainer>) {
static_assert(false, "Call an empty MccPZoneAbstractContainer::pzClearZones method");
} else {
return std::forward<self_t>(self).pzClearZones();
}
}
// must return the size of the container (number of zones)
size_t pzSize(this auto&& self)
{
using self_t = decltype(self);
if constexpr (std::same_as<std::remove_cvref_t<self_t>, MccPZoneAbstractContainer>) {
static_assert(false, "Call an empty MccPZoneAbstractContainer::pzSize method");
} else {
return std::forward<self_t>(self).pzSize();
}
}
// must return true if the given telemetry coordinates are in any of zones in the containe and
// false otherwise
template <typename RT>
bool pzInZone(this auto&& self, const TelemetryDataT& tdata, RT& result)
{
using self_t = decltype(self);
if constexpr (std::same_as<std::remove_cvref_t<self_t>, MccPZoneAbstractContainer>) {
static_assert(false, "Call an empty MccPZoneAbstractContainer::pzInZone method");
} else {
return std::forward<self_t>(self).pzInZone(tdata, result);
}
}
template <typename RT>
auto pzTimeTo(this auto&& self, const TelemetryDataT& tdata, RT& result)
{
using self_t = decltype(self);
if constexpr (std::same_as<std::remove_cvref_t<self_t>, MccPZoneAbstractContainer>) {
static_assert(false, "Call an empty MccPZoneAbstractContainer::pzInZone method");
} else {
return std::forward<self_t>(self).pzTimeTo(tdata, result);
}
}
template <typename RT>
auto pzTimeFrom(this auto&& self, const TelemetryDataT& tdata, RT& result)
{
using self_t = decltype(self);
if constexpr (std::same_as<std::remove_cvref_t<self_t>, MccPZoneAbstractContainer>) {
static_assert(false, "Call an empty MccPZoneAbstractContainer::pzInZone method");
} else {
return std::forward<self_t>(self).pzTimeFrom(tdata, result);
}
}
protected:
MccPZoneAbstractContainer() = default;
};
// a full concept for prohibited zones container
template <typename T, typename TelemetryDataT>
concept mcc_mount_pzones_container_c = std::derived_from<T, MccPZoneAbstractContainer<TelemetryDataT>> && requires {
// common time duration type for zones 'timeTo' and 'timeFrom' methods
requires mcc_time_duration_c<typename T::duration_t>;
// static constexpr member to represent infinite duration
requires requires {
requires std::same_as<decltype(T::infiniteDuration), typename T::duration_t const>;
[]() {
constexpr auto val = T::infiniteDuration;
return val;
};
};
// static constexpr member to represent zero duration
requires requires {
requires std::same_as<decltype(T::zeroDuration), typename T::duration_t const>;
[]() {
constexpr auto val = T::zeroDuration;
return val;
};
};
};
/* MOUNT GENERIC CONTROLS */

View File

@ -29,6 +29,7 @@ template <MccAltLimitKind KIND = MccAltLimitKind::MIN_ALT_LIMIT>
class MccAltLimitPZ
// class MccAltLimitPZ : public MccProhibitedZone
{
protected:
static constexpr auto pi2 = std::numbers::pi * 2.0;
public:
@ -36,16 +37,16 @@ public:
static constexpr MccAltLimitKind altLimitKind = KIND;
typedef MccAngle coord_t;
// floating-point time duration (seconds)
typedef std::chrono::duration<double> duration_t;
typedef MccAngle coord_t;
typedef std::chrono::system_clock::time_point time_point_t;
static constexpr duration_t infiniteDuration{std::numeric_limits<double>::infinity()};
static constexpr duration_t zeroDuration{0.0};
MccAltLimitPZ(const MccAngle& alt_limit, const MccAngle& lat)
MccAltLimitPZ(const coord_t& alt_limit, const coord_t& lat, traits::mcc_astrom_engine_c auto* astrom_engine)
// : MccProhibitedZone(KIND == MccAltLimitKind::MIN_ALT_LIMIT ? "MINALT-ZONE"
// : KIND == MccAltLimitKind::MAX_ALT_LIMIT ? "MAXALT-ZONE"
// : "ALTLIMIT-UNKNOWN"),
@ -53,6 +54,21 @@ public:
{
_lat_lim = pi2 - _abs_lat;
_altLimit.normalize<MccAngle::NORM_KIND_90_90>();
using astrom_engine_t = decltype(*astrom_engine);
using astrom_coord_t = typename astrom_engine_t::coord_t;
static_assert(std::convertible_to<coord_t, astrom_coord_t>,
"ASTROMETRY ENGINE AND THE ZONE COORDINATE TYPE ARE NOT COMPATIBLE!");
static_assert(std::convertible_to<astrom_coord_t, coord_t>,
"ASTROMETRY ENGINE AND THE ZONE COORDINATE TYPE ARE NOT COMPATIBLE!");
_coord2coord = [astrom_engine, this](MccCoordPairKind kind_from, coord_t x_from, coord_t y_from,
time_point_t tpoint, MccCoordPairKind kind_to, coord_t& x_to,
coord_t& y_to) {
auto err = astrom_engine->coord2coord(kind_from, std::move(x_from), std::move(y_from), tpoint, kind_to,
x_to, y_to, tpoint);
};
}
@ -118,59 +134,84 @@ public:
}
}
template <std::derived_from<MccAngle> XT, std::derived_from<MccAngle> YT>
// bool inZone(const XT& x, const YT& y, traits::mcc_systime_c auto const& utc = std::chrono::system_clock::now())
bool inZone(const XT& x, const YT& y)
bool inZone(traits::mcc_celestial_point_c auto const& target)
{
static constexpr MccCoordPairKind coord_kind = traits::mcc_type_pair_hash<XT, YT>();
coord_t alt, az;
if constexpr (coord_kind == MccCoordPairKind::COORDS_KIND_AZALT) { // trivial case
if constexpr (KIND == MccAltLimitKind::MIN_ALT_LIMIT) {
return y <= _altLimit;
} else if constexpr (KIND == MccAltLimitKind::MAX_ALT_LIMIT) {
return y >= _altLimit;
}
} else if constexpr (coord_kind == MccCoordPairKind::COORDS_KIND_AZZD) { // trivial case
// return inZone(x, MccAngleALT(std::numbers::pi / 2 - (double)y), utc);
return inZone(x, MccAngleALT(std::numbers::pi / 2 - (double)y));
} else if constexpr (coord_kind == MccCoordPairKind::COORDS_KIND_HADEC_APP) {
// implementation ...
return false;
} else if constexpr (coord_kind == MccCoordPairKind::COORDS_KIND_RADEC_APP) {
// implementation ...
return false;
} else {
throw std::system_error(std::make_error_code(std::errc::operation_not_supported));
_coord2coord(target.coordPairKind, target.x, target.y, target.time_point, MccCoordPairKind::COORDS_KIND_AZALT,
az, alt);
if constexpr (KIND == MccAltLimitKind::MIN_ALT_LIMIT) {
return alt <= _altLimit;
} else if constexpr (KIND == MccAltLimitKind::MAX_ALT_LIMIT) {
return alt >= _altLimit;
}
}
duration_t timeTo(traits::mcc_celestial_point_c auto const& target)
{
coord_t ha, dec;
if (inZone(target)) {
return zeroDuration;
}
return false;
_coord2coord(target.coordPairKind, target.x, target.y, target.time_point,
MccCoordPairKind::COORDS_KIND_HADEC_APP, ha, dec);
if (!doesObjectReachZone(ha)) {
return infiniteDuration;
}
if constexpr (KIND ==
MccAltLimitKind::MIN_ALT_LIMIT) { // the closest time point is one after upper culmination
return compute(ha, dec, false);
} else if constexpr (KIND == MccAltLimitKind::MAX_ALT_LIMIT) { // the closest time point is one before upper
// culmination
return compute(ha, dec, true);
}
}
template <std::derived_from<MccAngle> XT, std::derived_from<MccAngle> YT>
duration_t timeTo(const XT& x,
const YT& y,
traits::mcc_systime_c auto const& utc = std::chrono::system_clock::now())
duration_t timeFrom(traits::mcc_celestial_point_c auto const& target)
{
return duration_t{std::numeric_limits<double>::infinity()};
coord_t ha, dec;
if (!inZone(target)) {
return zeroDuration;
}
_coord2coord(target.coordPairKind, target.x, target.y, target.time_point,
MccCoordPairKind::COORDS_KIND_HADEC_APP, ha, dec);
if (!doesObjectExitFromZone(ha)) {
return infiniteDuration;
}
if (!doesObjectReachZone(ha)) {
return zeroDuration;
}
if constexpr (KIND ==
MccAltLimitKind::MIN_ALT_LIMIT) { // the closest time point is one before upper culmination
return compute(ha, dec, true);
} else if constexpr (KIND == MccAltLimitKind::MAX_ALT_LIMIT) { // the closest time point is one after upper
// culmination
return compute(ha, dec, false);
}
}
template <std::derived_from<MccAngle> XT, std::derived_from<MccAngle> YT>
duration_t timeFrom(const XT& x,
const YT& y,
traits::mcc_systime_c auto const& utc = std::chrono::system_clock::now())
{
return duration_t{0.0};
}
private:
MccAngle _altLimit, _latitude, _abs_lat, _lat_lim;
coord_t _altLimit, _latitude, _abs_lat, _lat_lim;
bool doesObjectReachZone(traits::mcc_mount_telemetry_data_c auto const& telemetry_data)
// wrapper function
std::function<coord_t(MccCoordPairKind, coord_t, coord_t, time_point_t, MccCoordPairKind, coord_t&, coord_t&)>
_coord2coord{};
bool doesObjectReachZone(const coord_t& dec_app)
{
// check for limit conditions
auto dd = std::abs(telemetry_data.mntDEC);
auto dd = std::abs(dec_app);
if constexpr (KIND == MccAltLimitKind::MIN_ALT_LIMIT) {
dd += _altLimit;
@ -189,11 +230,16 @@ private:
return true;
}
bool doesObjectReachZone(traits::mcc_mount_telemetry_data_c auto const& telemetry_data)
{
return doesObjectReachZone(telemetry_data.mntDEC);
}
bool doesObjectExitFromZone(traits::mcc_mount_telemetry_data_c auto const& telemetry_data)
bool doesObjectExitFromZone(const coord_t& dec_app)
{
// check for limit conditions
auto dd = std::abs(telemetry_data.mntDEC);
auto dd = std::abs(dec_app);
if constexpr (KIND == MccAltLimitKind::MIN_ALT_LIMIT) {
dd -= _altLimit;
@ -212,10 +258,16 @@ private:
return true;
}
duration_t compute(traits::mcc_mount_telemetry_data_c auto const& telemetry_data, bool before_upper_culm)
bool doesObjectExitFromZone(traits::mcc_mount_telemetry_data_c auto const& telemetry_data)
{
double cos_ha = (std::sin(_altLimit) - std::sin(telemetry_data.mntDEC) * std::sin(_latitude)) /
std::cos(telemetry_data.mntDEC) / std::cos(_latitude);
return doesObjectExitFromZone(telemetry_data.mntDEC);
}
duration_t compute(const coord_t& ha_app, const coord_t& dec_app, bool before_upper_culm)
{
double cos_ha =
(std::sin(_altLimit) - std::sin(dec_app) * std::sin(_latitude)) / std::cos(dec_app) / std::cos(_latitude);
if (cos_ha > 1.0) { // should not be!
return infiniteDuration;
@ -228,7 +280,7 @@ private:
ha = std::acos(cos_ha); // HA after upper culmination!!
}
MccAngle time_ang = ha - telemetry_data.mntHA; // in sideral time scale
MccAngle time_ang = ha - ha_app; // in sideral time scale
if (time_ang < 0.0) { // next day
time_ang += pi2;
@ -238,6 +290,11 @@ private:
return duration_t{time_ang.seconds()};
}
duration_t compute(traits::mcc_mount_telemetry_data_c auto const& telemetry_data, bool before_upper_culm)
{
return compute(telemetry_data.mntHA, telemetry_data.mntDEC, before_upper_culm);
}
};
typedef MccAltLimitPZ<MccAltLimitKind::MIN_ALT_LIMIT> MccMinAltPZ;

View File

@ -3,7 +3,7 @@
/* MOUNT CONTROL COMPONENTS LIBRARY */
/* AN DEFAULT IMPLEMENTATION OF PROHIBITED ZONES HOLDER */
/* A DEFAULT IMPLEMENTATION OF PROHIBITED ZONES HOLDER */
#include "mcc_mount_concepts.h"
@ -11,7 +11,7 @@ namespace mcc
{
template <traits::mcc_mount_telemetry_data_c TelemetryDataT>
class MccPZoneHolder
class MccPZoneContainer : public traits::MccPZoneAbstractContainer<TelemetryDataT>
{
public:
typedef TelemetryDataT telemetry_data_t;
@ -21,7 +21,7 @@ public:
// adaptor class for prohibited zones
struct MccPZoneWrapper {
using duration_t = MccPZoneHolder::duration_t;
using duration_t = MccPZoneContainer::duration_t;
static constexpr duration_t infiniteDuration{std::numeric_limits<double>::infinity()};
static constexpr duration_t zeroDuration{0.0};
@ -53,7 +53,11 @@ public:
MccPZoneWrapper() = default;
};
size_t pzNumberOfZones() const { return _pzWrapperVec.size(); }
MccPZoneContainer() = default;
virtual ~MccPZoneContainer() = default;
size_t pzSize() const { return _pzWrapperVec.size(); }
// add zone/zones
template <traits::mcc_prohibited_zone_c<telemetry_data_t> ZT,
@ -156,10 +160,108 @@ public:
return in_zone;
}
template <std::ranges::output_range<bool> RT>
bool pzInZone(traits::mcc_celestial_point_c auto const& target, RT& result)
{
bool in_zone = false;
auto const p_target = &target;
result = pzForeachZone<RT>([&in_zone, p_target](auto& wr) {
bool r = wr.inZone(*p_target);
in_zone |= r;
return r;
});
return in_zone;
}
protected:
std::vector<MccPZoneWrapper> _pzWrapperVec{};
};
class PZC
{
protected:
struct point_t {
typedef std::chrono::system_clock::time_point time_point_t;
typedef double coord_t;
time_point_t time_point;
MccCoordPairKind coordPairKind;
coord_t x, y;
};
static_assert(traits::mcc_celestial_point_c<point_t>);
template <typename ZT>
static inline std::unordered_map<const PZC*, std::vector<std::shared_ptr<ZT>>> _zones{};
std::vector<std::function<void()>> _clearFunc{};
// template <typename ZT, typename CPT>
// static inline std::unordered_map<const PZC*, std::function<std::vector<bool>(const CPT&)>> _inZoneFunc = [](){
// };
// template <typename ZT, typename CPT>
// static inline std::function<std::vector<bool>(const PZC*, const CPT&)> _inZoneFunc =
// [](const PZC* cont, const CPT& cp) {
// std::vector<bool> res;
// for (ZT& zone : _zones<ZT>[cont]) {
// res.emplace_back(zone.inZone(cp));
// }
// return res;
// };
std::vector<std::function<bool(const point_t&)>> _inZoneFunc;
public:
template <typename ZT>
size_t addZone(ZT zone)
{
auto sptr = std::make_shared<ZT>(std::move(zone));
_zones<ZT>[this].emplace_back(sptr);
if (_zones<ZT>[this].size() == 1) {
_clearFunc.emplace_back([this]() { _zones<ZT>[this].clear(); });
_inZoneFunc.emplace_back([sptr](const point_t& cp) { return sptr->inZone(cp); });
}
}
template <typename CPT, std::ranges::output_range<bool> RT>
bool inZone(const CPT& cp, RT& res)
{
using tp_t = typename point_t::time_point_t;
using cp_tp_t = typename CPT::time_point_t;
bool in_zone = false, r;
point_t pt{.coordPairKind = cp.coordPairKind, .x = cp.x, .y = cp.y};
if constexpr (traits::mcc_systime_c<cp_tp_t>) {
pt.time_point = std::chrono::time_point_cast<tp_t>(cp.time_point);
} else if constexpr (std::is_arithmetic_v<cp_tp_t>) {
pt.time_point = tp_t{std::chrono::duration<tp_t::rep>(static_cast<tp_t::rep>(cp.time_point))};
} else {
static_assert(false, "INVALID TYPE!");
}
res = RT();
for (auto& func : _inZoneFunc) {
r = func(pt);
in_zone |= r;
std::back_inserter(res) = r;
}
return in_zone;
}
};
} // namespace mcc

View File

@ -143,7 +143,7 @@ public:
typename ASTROM_ENGINE_T::coord_t xdiff, ydiff, r2;
};
MccMountTelemetry(astrom_engine_t& astrom_engine, pec_t& pec, hardware_t& hardware)
MccMountTelemetry(astrom_engine_t* astrom_engine, pec_t* pec, hardware_t* hardware)
: base_t(astrom_engine, pec), _hardware(hardware)
{
}
@ -221,7 +221,7 @@ public:
typename hardware_t::axes_pos_t ax_pos;
auto err = _hardware.getPos(ax_pos);
auto err = _hardware->getPos(ax_pos);
if (err) {
if constexpr (std::same_as<error_t, decltype(err)>) {
return err;
@ -357,7 +357,7 @@ public:
protected:
mount_telemetry_data_t _data{};
hardware_t& _hardware;
hardware_t* _hardware;
std::unique_ptr<std::mutex> _updateMutex;
std::unique_ptr<std::condition_variable> _updateCondVar;

View File

@ -104,7 +104,7 @@ public:
typedef std::error_code error_t;
MccMountTelemetryAstromTransform(astrom_engine_t& astrom_engine, pec_t& pec)
MccMountTelemetryAstromTransform(astrom_engine_t* astrom_engine, pec_t* pec)
: _astromEngine(astrom_engine), _pec(pec)
{
}
@ -166,9 +166,9 @@ public:
typename pec_t::error_t pec_err;
auto get_jd_lst_eo = [&time_point, this](jd_t& jd, sideral_time_t& lst, eo_t& eo) {
auto ast_err = _astromEngine.greg2jul(time_point, jd);
auto ast_err = _astromEngine->greg2jul(time_point, jd);
if (!ast_err) {
ast_err = _astromEngine.apparentSiderTime(jd, lst, true);
ast_err = _astromEngine->apparentSiderTime(jd, lst, true);
if (!ast_err) {
ast_err = _astromEngine->eqOrigins(jd, eo);
@ -180,7 +180,7 @@ public:
if (coord.coordPairKind == MccCoordPairKind::COORDS_KIND_XY) { // from encoder's
typename pec_t::pec_result_t pec_res;
pec_err = _pec.compute(coord.x, coord.y, pec_res);
pec_err = _pec->compute(coord.x, coord.y, pec_res);
if (!pec_err) {
X_app = coord.x + pec_res.dx;
Y_app = coord.y + pec_res.dy;
@ -202,7 +202,7 @@ public:
Y_app = coord.y;
XX_app = HA;
} else if constexpr (altAzMount) {
ast_err = _astromEngine.hadec2azalt(HA, coord.y, X_app, Y_app);
ast_err = _astromEngine->hadec2azalt(HA, coord.y, X_app, Y_app);
} else {
static_assert(false, "UNSUPPORTED MOUNT TYPE!");
}
@ -217,15 +217,15 @@ public:
Y_app = coord.y;
XX_app = lst - coord.x + eo;
} else if constexpr (altAzMount) {
ast_err = _astromEngine.hadec2azalt(coord.x, coord.y, X_app, Y_app);
ast_err = _astromEngine->hadec2azalt(coord.x, coord.y, X_app, Y_app);
} else {
static_assert(false, "UNSUPPORTED MOUNT TYPE!");
}
}
} else if (coord.coordPairKind == MccCoordPairKind::COORDS_KIND_AZALT) { // from app AZ-ALT
if constexpr (equatorialMount) {
ast_err = _astromEngine.azalt2hadec(coord.x, coord.y, X_app, Y_app); // compute HA-DEC
if (!ast_err) { // compute CIO RA (as XX_app)
ast_err = _astromEngine->azalt2hadec(coord.x, coord.y, X_app, Y_app); // compute HA-DEC
if (!ast_err) { // compute CIO RA (as XX_app)
coord.coordPairKind == MccCoordPairKind::COORDS_KIND_HADEC_APP;
coord.x = X_app;
coord.y = Y_app;
@ -250,9 +250,9 @@ public:
// for alt-azimuthal mount:
// X_app = AZ, Y_app = ALT
ast_err = _astromEngine.greg2jul(time_point, jd);
ast_err = _astromEngine->greg2jul(time_point, jd);
if (!ast_err) {
ast_err = _astromEngine.icrs2obs(coord.x, coord.y, jd, X_app, Y_app, XX_app, az, alt, eo);
ast_err = _astromEngine->icrs2obs(coord.x, coord.y, jd, X_app, Y_app, XX_app, az, alt, eo);
if (!ast_err) {
if constexpr (equatorialMount) {
@ -297,7 +297,7 @@ public:
if (coord.coordPairKind == MccCoordPairKind::COORDS_KIND_XY) { // from encoder's
typename pec_t::pec_result_t pec_res;
pec_err = _pec.compute(coord.x, coord.y, pec_res);
pec_err = _pec->compute(coord.x, coord.y, pec_res);
if (!pec_err) {
coord.x += pec_res.dx;
coord.y += pec_res.dy;
@ -332,9 +332,9 @@ public:
if (coord.coordPairKind != MccCoordPairKind::COORDS_KIND_RADEC_ICRS) {
typename astrom_engine_t::jd_t jd;
ast_err = _astromEngine.greg2jul(astrom_engine_t::timePointNow(), jd);
ast_err = _astromEngine->greg2jul(astrom_engine_t::timePointNow(), jd);
if (!ast_err) {
ast_err = _astromEngine.obs2icrs(coord.coordPairKind, coord.x, coord.y, jd, RA, DEC);
ast_err = _astromEngine->obs2icrs(coord.coordPairKind, coord.x, coord.y, jd, RA, DEC);
}
}
@ -371,9 +371,9 @@ public:
sideral_time_t lst;
auto get_jd_lst_eo = [&time_point, this](jd_t& jd, sideral_time_t& lst, eo_t& eo) {
auto ast_err = _astromEngine.greg2jul(time_point, jd);
auto ast_err = _astromEngine->greg2jul(time_point, jd);
if (!ast_err) {
ast_err = _astromEngine.apparentSiderTime(jd, lst, true);
ast_err = _astromEngine->apparentSiderTime(jd, lst, true);
if (!ast_err) {
ast_err = _astromEngine->eqOrigins(jd, eo);
@ -404,7 +404,7 @@ public:
if constexpr (equatorialMount) {
typename pec_t::pec_result_t pec_res;
pec_err = _pec.compute(coord.x, coord.y, pec_res);
pec_err = _pec->compute(coord.x, coord.y, pec_res);
if (!pec_err) {
X = coord.x - pec_res.dx;
Y = coord.y - pec_res.dy;
@ -413,7 +413,7 @@ public:
}
} else if constexpr (altAzMount) {
coord_t az, alt;
ast_err = _astromEngine.hadec2azalt(coord.x, coord.y, az, alt);
ast_err = _astromEngine->hadec2azalt(coord.x, coord.y, az, alt);
if (!ast_err) {
coord.coordPairKind == MccCoordPairKind::COORDS_KIND_AZALT;
coord.x = az;
@ -427,7 +427,7 @@ public:
} else if (coord.coordPairKind == MccCoordPairKind::COORDS_KIND_AZALT) { // from app AZ-ALT
if constexpr (equatorialMount) {
coord_t ha, dec;
ast_err = _astromEngine.azalt2hadec(coord.x, coord.y, ha, dec);
ast_err = _astromEngine->azalt2hadec(coord.x, coord.y, ha, dec);
if (!ast_err) {
coord.coordPairKind == MccCoordPairKind::COORDS_KIND_HADEC_APP;
coord.x = ha;
@ -438,7 +438,7 @@ public:
} else if constexpr (altAzMount) {
typename pec_t::pec_result_t pec_res;
pec_err = _pec.compute(coord.x, coord.y, pec_res);
pec_err = _pec->compute(coord.x, coord.y, pec_res);
if (!pec_err) {
X = coord.x - pec_res.dx;
Y = coord.y - pec_res.dy;
@ -456,7 +456,7 @@ public:
coord_t ra, dec, ha, az, alt;
eo_t eo;
ast_err = _astromEngine.greg2jul(time_point, jd);
ast_err = _astromEngine->greg2jul(time_point, jd);
if (!ast_err) {
ast_err = icrs2obs(coord.x, coord.y, jd, ra, dec, ha, az, alt, eo);
if (!ast_err) {
@ -499,8 +499,8 @@ public:
}
protected:
astrom_engine_t& _astromEngine;
pec_t& _pec;
astrom_engine_t* _astromEngine;
pec_t* _pec;
};

View File

@ -16,6 +16,7 @@ namespace mcc
struct MccCelestialPoint {
typedef double coord_t;
typedef std::chrono::system_clock::time_point time_point_t;
MccCoordPairKind coordPairKind{MccCoordPairKind::COORDS_KIND_RADEC_ICRS};
coord_t x{0.0}, y{0.0};

View File

@ -129,9 +129,9 @@ public:
traits::mcc_irange_of_pzones_c<typename TELEMETRY_T::mount_telemetry_data_t> PZ_T,
// traits::mcc_tuple_c PZ_T, // std::tuple of prohibited zones
typename... LoggerCtorArgTs>
MccSimpleSlewModel(TELEMETRY_T& telemetry,
HARDWARE_T& hardware,
PZ_T& prohibited_zone,
MccSimpleSlewModel(TELEMETRY_T* telemetry,
HARDWARE_T* hardware,
PZ_T* prohibited_zone,
LoggerCtorArgTs&&... ctor_args)
requires(!std::same_as<LoggerT, MccNullLogger>)
: LoggerT(std::forward<LoggerCtorArgTs>(ctor_args)...)
@ -141,16 +141,16 @@ public:
init(telemetry, hardware, prohibited_zone);
}
template <traits::mcc_mount_telemetry_c TELEMETRY_T,
traits::mcc_mount_hardware_c HARDWARE_T,
traits::mcc_irange_of_pzones_c<typename TELEMETRY_T::mount_telemetry_data_t> PZ_T
// traits::mcc_tuple_c PZ_T // std::tuple of prohibited zones
>
MccSimpleSlewModel(TELEMETRY_T& telemetry, HARDWARE_T& hardware, PZ_T& prohibited_zone)
requires(std::same_as<LoggerT, MccNullLogger>)
{
init(telemetry, hardware, prohibited_zone);
}
// template <traits::mcc_mount_telemetry_c TELEMETRY_T,
// traits::mcc_mount_hardware_c HARDWARE_T,
// traits::mcc_irange_of_pzones_c<typename TELEMETRY_T::mount_telemetry_data_t> PZ_T
// // traits::mcc_tuple_c PZ_T // std::tuple of prohibited zones
// >
// MccSimpleSlewModel(TELEMETRY_T& telemetry, HARDWARE_T& hardware, PZ_T& prohibited_zone)
// requires(std::same_as<LoggerT, MccNullLogger>)
// {
// init(telemetry, hardware, prohibited_zone);
// }
MccSimpleSlewModel(MccSimpleSlewModel&& other)
: _stopRequested(other._stopRequested.load()), _slewFunc(std::move(other._slewFunc))
@ -195,21 +195,21 @@ protected:
std::atomic_bool _stopRequested{false};
std::function<error_t(const slew_point_t&)> _slewFunc{};
void init(auto& telemetry, auto& hardware, auto& prohibited_zones)
void init(auto* p_telemetry, auto* p_hardware, auto* p_prohibited_zones)
{
// deduce controls types
using hardware_t = decltype(hardware);
using telemetry_t = decltype(telemetry);
using hardware_t = decltype(*p_hardware);
using telemetry_t = decltype(*p_telemetry);
static_assert(traits::mcc_mount_default_telemetry_c<telemetry_t>,
"TELEMETRY CLASS MUST BE A DESCENDANT OF 'MccMountTelemetry'!");
using astrom_engine_t = typename telemetry_t::astrom_engine_t;
static constexpr size_t Nzones = std::tuple_size_v<decltype(prohibited_zones)>;
static constexpr size_t Nzones = std::tuple_size_v<decltype(*p_prohibited_zones)>;
const auto p_telemetry = &telemetry;
const auto p_hardware = &hardware;
const auto p_prohibited_zones = &prohibited_zones;
// const auto p_telemetry = &telemetry;
// const auto p_hardware = &hardware;
// const auto p_prohibited_zones = &prohibited_zones;
_slewFunc = [p_telemetry, p_hardware, p_prohibited_zones, this](slew_point_t slew_point) {
_stopRequested = false;