271 lines
10 KiB
C++
271 lines
10 KiB
C++
#pragma once
|
|
|
|
/* MOUNT CONTROL COMPONENTS LIBRARY */
|
|
|
|
#include <concepts>
|
|
|
|
#include "mcc_mount_coord.h"
|
|
#include "mcc_traits.h"
|
|
|
|
|
|
/* SOME LIBRARY-WIDE DECLARATIONS */
|
|
|
|
namespace mcc
|
|
{
|
|
// mount construction type (only the most common ones)
|
|
enum class MccMountType : uint8_t { GERMAN_TYPE, FORK_TYPE, CROSSAXIS_TYPE, ALTAZ_TYPE };
|
|
|
|
template <MccMountType TYPE>
|
|
static constexpr std::string_view MccMountTypeStr = TYPE == MccMountType::GERMAN_TYPE ? "GERMAN"
|
|
: TYPE == MccMountType::FORK_TYPE ? "FORK"
|
|
: TYPE == MccMountType::CROSSAXIS_TYPE ? "CROSSAXIS"
|
|
: TYPE == MccMountType::ALTAZ_TYPE ? "ALTAZ"
|
|
: "UNKNOWN";
|
|
|
|
template <MccMountType TYPE>
|
|
static constexpr bool mcc_is_equatorial_mount = TYPE == MccMountType::GERMAN_TYPE ? true
|
|
: TYPE == MccMountType::FORK_TYPE ? true
|
|
: TYPE == MccMountType::CROSSAXIS_TYPE ? true
|
|
: TYPE == MccMountType::ALTAZ_TYPE ? false
|
|
: false;
|
|
template <MccMountType TYPE>
|
|
static constexpr bool mcc_is_altaz_mount = TYPE == MccMountType::GERMAN_TYPE ? false
|
|
: TYPE == MccMountType::FORK_TYPE ? false
|
|
: TYPE == MccMountType::CROSSAXIS_TYPE ? false
|
|
: TYPE == MccMountType::ALTAZ_TYPE ? true
|
|
: false;
|
|
|
|
static consteval bool mccIsEquatorialMount(const MccMountType type)
|
|
{
|
|
return type == MccMountType::GERMAN_TYPE ? true
|
|
: type == MccMountType::FORK_TYPE ? true
|
|
: type == MccMountType::CROSSAXIS_TYPE ? true
|
|
: type == MccMountType::ALTAZ_TYPE ? false
|
|
: false;
|
|
};
|
|
|
|
static consteval bool mccIsAltAzMount(const MccMountType type)
|
|
{
|
|
return type == MccMountType::GERMAN_TYPE ? false
|
|
: type == MccMountType::FORK_TYPE ? false
|
|
: type == MccMountType::CROSSAXIS_TYPE ? false
|
|
: type == MccMountType::ALTAZ_TYPE ? true
|
|
: false;
|
|
};
|
|
|
|
} // namespace mcc
|
|
|
|
|
|
|
|
namespace mcc::traits
|
|
{
|
|
|
|
|
|
/* ASTROMETRY-RELATED COMPUTATION ENGINE */
|
|
|
|
template <typename T>
|
|
concept mcc_astrom_engine_c = requires(T t, const T t_const) {
|
|
requires mcc_error_c<typename T::error_t>;
|
|
typename T::engine_state_t;
|
|
requires std::movable<typename T::engine_state_t>;
|
|
|
|
typename T::coord_t; // type for coordinates representation
|
|
typename T::time_point_t; // type to represent UTC time point
|
|
typename T::juldate_t; // type to represent Julian date
|
|
typename T::sideral_time_t; // type to represent sideral time
|
|
typename T::pa_t; // type to represent parallactic angle
|
|
|
|
typename T::refract_result_t;
|
|
|
|
|
|
{ t.setState(std::declval<typename T::engine_state_t>()) };
|
|
|
|
{ t_const.getState() } -> std::same_as<typename T::engine_state_t>;
|
|
|
|
{ t_const.errorString(std::declval<typename T::error_t>()) } -> mcc_formattable;
|
|
|
|
/* coordinates conversional methods */
|
|
|
|
// ICRS RA and DEC to observed place: icrs2obs(ra, dec, jd, ra_app, dec_app, ha, az, alt)
|
|
{
|
|
t.icrs2obs(std::declval<typename T::coord_t>(), std::declval<typename T::coord_t>(),
|
|
std::declval<typename T::juldate_t>(), std::declval<typename T::coord_t&>(),
|
|
std::declval<typename T::coord_t&>(), std::declval<typename T::coord_t&>(),
|
|
std::declval<typename T::coord_t&>(), std::declval<typename T::coord_t&>())
|
|
} -> std::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::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::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::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 */
|
|
|
|
// 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::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::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::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::error_t>;
|
|
};
|
|
|
|
|
|
/* 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>;
|
|
typename T::config_t;
|
|
|
|
typename T::time_point_t;
|
|
typename T::coord_t;
|
|
|
|
{ t_const.id() } -> mcc_formattable;
|
|
|
|
// hardware configuration
|
|
{ t.setConfig(std::declval<typename T::config_t>()) } -> std::same_as<typename T::error_t>;
|
|
{ t.getConfig(std::declval<typename T::config_t&>()) } -> std::same_as<typename T::error_t>;
|
|
|
|
// at least contains time of measurement and coordinates for x,y axes
|
|
requires requires(typename T::axes_pos_t pos) {
|
|
requires std::same_as<decltype(pos.time_point), typename T::time_point_t>;
|
|
requires std::same_as<decltype(pos.x), typename T::coord_t>;
|
|
requires std::same_as<decltype(pos.y), typename T::coord_t>;
|
|
};
|
|
|
|
{ t.setPos(std::declval<typename T::axes_pos_t>()) } -> std::same_as<typename T::error_t>;
|
|
{ t.getPos(std::declval<typename T::axes_pos_t&>()) } -> std::same_as<typename T::error_t>;
|
|
};
|
|
|
|
|
|
/* POINTING-ERROR CORRECTION */
|
|
|
|
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;
|
|
|
|
// 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::declval<typename T::pec_result_t>())
|
|
} -> std::same_as<typename T::error_t>;
|
|
};
|
|
|
|
|
|
/* MOUNT STATE TELEMETRY */
|
|
|
|
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>;
|
|
};
|
|
|
|
|
|
|
|
/* MOUNT PROHIBITED ZONE */
|
|
template <typename T>
|
|
concept mcc_prohibited_zone_c = std::movable<T> && requires(T t, const T t_const) {
|
|
typename T::coord_t;
|
|
typename T::time_point_t;
|
|
|
|
// the type 'T' must define 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 class methods.
|
|
requires requires {
|
|
requires std::same_as<decltype(T::zoneCoordPairKind), const MccCoordPairKind>;
|
|
[]() {
|
|
constexpr MccCoordPairKind val = T::zoneCoordPairKind;
|
|
}(); // 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 in the zone at given time point
|
|
{
|
|
t.inZone(std::declval<typename T::coord_t>(), std::declval<typename T::coord_t>(),
|
|
std::declval<typename T::time_point_t>())
|
|
} -> std::convertible_to<bool>;
|
|
|
|
|
|
// for given coordinates and time the method computes a time to reach the zone
|
|
{
|
|
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;
|
|
};
|
|
|
|
|
|
/* MOUNT GENERIC CONFIGURATION */
|
|
|
|
template <typename T>
|
|
concept mcc_mount_config_c = requires(T t) {
|
|
{ t.astromEngine() } -> mcc_astrom_engine_c;
|
|
{ t.pec() } -> mcc_mount_pec_c;
|
|
{ t.hardware() } -> mcc_mount_hardware_c;
|
|
};
|
|
|
|
|
|
|
|
} // namespace mcc::traits
|