...
This commit is contained in:
parent
c7693b7fea
commit
646b0bde50
@ -3,7 +3,7 @@
|
||||
/* MOUNT CONTROL COMPONENTS LIBRARY */
|
||||
|
||||
|
||||
/* ASTROMETRY ENGINE BASED ON ERFA-LIBRARY */
|
||||
/* ASTROMETRY ENGINE BASED ON ERFA-LIBRARY (THREAD-SAFE FOR ENGINE STATE MANIPULATIONS) */
|
||||
|
||||
#include <chrono>
|
||||
#include <mutex>
|
||||
@ -298,6 +298,30 @@ public:
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
|
||||
/* helper mathods */
|
||||
|
||||
auto leapSecondsExpireDate() const
|
||||
{
|
||||
return _currentState._leapSeconds.expireDate();
|
||||
}
|
||||
|
||||
auto leapSecondsExpireMJD() const
|
||||
{
|
||||
return _currentState._leapSeconds.expireMJD();
|
||||
}
|
||||
|
||||
|
||||
auto bulletinADateRange() const
|
||||
{
|
||||
return _currentState._bulletinA.dateRange();
|
||||
}
|
||||
|
||||
auto bulletinADateRangeMJD() const
|
||||
{
|
||||
return _currentState._bulletinA.dateRangeMJD();
|
||||
}
|
||||
|
||||
protected:
|
||||
engine_state_t _currentState{};
|
||||
|
||||
|
||||
@ -7,9 +7,8 @@
|
||||
|
||||
|
||||
#include <concepts>
|
||||
#include <string>
|
||||
|
||||
// #include "mcc_traits.h"
|
||||
#include "mcc_traits.h"
|
||||
|
||||
namespace mcc::traits
|
||||
{
|
||||
@ -36,7 +35,7 @@ concept mcc_astrom_engine_c = requires(T t, const T t_const) {
|
||||
|
||||
{ t_const.getState() } -> std::same_as<typename T::engine_state_t>;
|
||||
|
||||
{ t_const.errorString(std::declval<typename T::engine_err_t>()) } -> std::convertible_to<std::string>;
|
||||
{ t_const.errorString(std::declval<typename T::engine_err_t>()) } -> mcc_formattable;
|
||||
|
||||
/* coordinates conversional methods */
|
||||
|
||||
|
||||
257
cxx/mcc_mount_concepts.h
Normal file
257
cxx/mcc_mount_concepts.h
Normal file
@ -0,0 +1,257 @@
|
||||
#pragma once
|
||||
|
||||
/* MOUNT CONTROL COMPONENTS LIBRARY */
|
||||
|
||||
#include <concepts>
|
||||
|
||||
#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";
|
||||
|
||||
|
||||
} // namespace mcc
|
||||
|
||||
|
||||
|
||||
namespace mcc::traits
|
||||
{
|
||||
|
||||
|
||||
/* ASTROMETRY-RELATED COMPUTATION ENGINE */
|
||||
|
||||
template <typename T>
|
||||
concept mcc_astrom_engine_c = requires(T t, const T t_const) {
|
||||
typename T::engine_err_t;
|
||||
typename T::engine_state_t;
|
||||
requires std::movable<typename T::engine_state_t>;
|
||||
|
||||
typename T::coord_t;
|
||||
typename T::prop_motion_t;
|
||||
typename T::parallax_t;
|
||||
typename T::time_point_t;
|
||||
typename T::juldate_t;
|
||||
typename T::gst_t;
|
||||
typename T::pa_t;
|
||||
typename T::eo_t;
|
||||
|
||||
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::engine_err_t>()) } -> mcc_formattable;
|
||||
|
||||
/* coordinates conversional methods */
|
||||
|
||||
// ICRS RA and DEC to observed place: icrs2obs(ra, dec, pra, pdec, plx, jd, ra_app, dec_app, ha, az, alt, eo)
|
||||
{
|
||||
t.icrs2obs(std::declval<typename T::coord_t>(), std::declval<typename T::coord_t>(),
|
||||
std::declval<typename T::prop_motion_t>(), std::declval<typename T::prop_motion_t>(),
|
||||
std::declval<typename T::parallax_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::declval<typename T::eo_t&>())
|
||||
} -> std::same_as<typename T::engine_err_t>;
|
||||
|
||||
// compute hour angle and declination from azimuth and altitude: hadec2azalt(ha, dec, az, alt)
|
||||
{
|
||||
t.hadec2azalt(std::declval<typename T::coord_t>(), std::declval<typename T::coord_t>(),
|
||||
std::declval<typename T::coord_t&>(), std::declval<typename T::coord_t&>())
|
||||
} -> std::same_as<typename T::engine_err_t>;
|
||||
|
||||
// compute azimuth and altitude from hour angle and declination: azalt2hadec(az, alt, ha, dec)
|
||||
{
|
||||
t.azalt2hadec(std::declval<typename T::coord_t>(), std::declval<typename T::coord_t>(),
|
||||
std::declval<typename T::coord_t&>(), std::declval<typename T::coord_t&>())
|
||||
} -> std::same_as<typename T::engine_err_t>;
|
||||
|
||||
// compute paralactic angle: hadec2pa(ha, dec, pa)
|
||||
{
|
||||
t.hadec2pa(std::declval<typename T::coord_t>(), std::declval<typename T::coord_t>(),
|
||||
std::declval<typename T::pa_t&>())
|
||||
} -> std::same_as<typename T::engine_err_t>;
|
||||
|
||||
|
||||
/* 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::engine_err_t>;
|
||||
// requires mcc_systime_c<mcc_func_arg1_t<decltype(&T::greg2jul)>>;
|
||||
// requires mcc_output_arg_c<mcc_func_argN_t<decltype(&T::greg2jul), 2>, typename T::juldate_t>;
|
||||
|
||||
// apparent sideral time: apparentSiderTime(jd, gst, islocal)
|
||||
{
|
||||
t.apparentSiderTime(std::declval<typename T::juldate_t>(), std::declval<typename T::gst_t&>(),
|
||||
std::declval<bool>())
|
||||
} -> std::same_as<typename T::engine_err_t>;
|
||||
|
||||
|
||||
/* atmospheric refraction-related methods */
|
||||
|
||||
{ t.refraction(std::declval<typename T::refract_result_t&>()) } -> std::same_as<typename T::engine_err_t>;
|
||||
};
|
||||
|
||||
|
||||
/* MOUNT AXES AND MOTORS HARDWARE GENERIC ABSTRACTION */
|
||||
|
||||
// encoder basic concept (e.g. mount axis encoder or motor shaft one)
|
||||
template <typename T>
|
||||
concept mcc_hw_encoder_c = requires(T t, const T t_const) {
|
||||
typename T::error_t;
|
||||
|
||||
typename T::time_point_t;
|
||||
typename T::coord_t;
|
||||
typename T::speed_t;
|
||||
typename T::accel_t;
|
||||
// typename T::high_order_deriv_t;
|
||||
|
||||
requires requires(typename T::state_t st) {
|
||||
std::same_as<decltype(st.time), typename T::time_point_t>;
|
||||
std::same_as<decltype(st.pos), typename T::coord_t>;
|
||||
std::same_as<decltype(st.speed), typename T::speed_t>;
|
||||
std::same_as<decltype(st.accel), typename T::accel_t>;
|
||||
// std::same_as<decltype(st.high_order), typename T::high_order_deriv_t>;
|
||||
};
|
||||
|
||||
{ t_const.errorString(std::declval<typename T::error_t>()) } -> mcc_formattable;
|
||||
|
||||
{ t_const.id() } -> mcc_formattable;
|
||||
|
||||
{ t.getState(std::declval<typename T::state_t&>()) } -> std::same_as<typename T::error_t>;
|
||||
};
|
||||
|
||||
|
||||
template <typename T>
|
||||
concept mcc_hw_motor_c = requires(T t, const T t_const) {
|
||||
typename T::error_t;
|
||||
|
||||
typename T::coord_t;
|
||||
typename T::speed_t;
|
||||
typename T::accel_t;
|
||||
|
||||
requires requires(typename T::pos_t st) {
|
||||
std::same_as<decltype(st.pos), typename T::coord_t>;
|
||||
std::same_as<decltype(st.speed), typename T::speed_t>; // means maximal allowed speed
|
||||
std::same_as<decltype(st.accel), typename T::accel_t>; // means a maximal allowed acceleration (jerk)
|
||||
};
|
||||
|
||||
|
||||
{ t_const.errorString(std::declval<typename T::error_t>()) } -> mcc_formattable;
|
||||
|
||||
{ t_const.id() } -> mcc_formattable;
|
||||
|
||||
{ t.rotate(std::declval<typename T::pos_t>()) } -> std::same_as<typename T::error_t>;
|
||||
|
||||
{ t.stop() } -> std::same_as<typename T::error_t>;
|
||||
};
|
||||
|
||||
|
||||
|
||||
namespace details
|
||||
{
|
||||
template <typename T>
|
||||
concept mcc_tuple_enc_ref_c = mcc_tuple_c<T> && requires(T t) {
|
||||
[]<template <typename...> typename TT, mcc_hw_encoder_c... Ts>(TT<Ts & ...>) {}(t);
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
concept mcc_tuple_enc_cref_c = mcc_tuple_c<T> && requires(T t) {
|
||||
[]<template <typename...> typename TT, mcc_hw_encoder_c... Ts>(TT<const Ts & ...>) {}(t);
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
concept mcc_tuple_motor_ref_c = mcc_tuple_c<T> && requires(T t) {
|
||||
[]<template <typename...> typename TT, mcc_hw_motor_c... Ts>(TT<Ts & ...>) {}(t);
|
||||
};
|
||||
|
||||
|
||||
template <typename T>
|
||||
concept mcc_hw_enc_lref_c = std::is_lvalue_reference_v<T> && mcc_hw_encoder_c<std::remove_reference_t<T>>;
|
||||
|
||||
|
||||
template <typename T>
|
||||
concept mcc_hw_motor_lref_c = std::is_lvalue_reference_v<T> && mcc_hw_motor_c<std::remove_reference_t<T>>;
|
||||
|
||||
} // namespace details
|
||||
|
||||
|
||||
// a very generic mount hardware concept
|
||||
template <typename T>
|
||||
concept mcc_mount_hardware_c = requires(T t, const T t_const) {
|
||||
{ t_const.id() } -> mcc_formattable;
|
||||
|
||||
// access to encoders
|
||||
{ t_const.encoders() } -> details::mcc_tuple_enc_cref_c;
|
||||
{ t.encoders() } -> details::mcc_tuple_enc_ref_c;
|
||||
|
||||
{ t.encoderPosX() } -> details::mcc_hw_enc_lref_c;
|
||||
{ t.encoderPosY() } -> details::mcc_hw_enc_lref_c;
|
||||
|
||||
// access to motors
|
||||
{ t.motors() } -> details::mcc_tuple_motor_ref_c;
|
||||
|
||||
{ t.motorX() } -> details::mcc_hw_motor_lref_c;
|
||||
{ t.motorY() } -> details::mcc_hw_motor_lref_c;
|
||||
};
|
||||
|
||||
|
||||
/* POINTING-ERROR CORRECTION */
|
||||
|
||||
template <typename T>
|
||||
concept mcc_mount_pec_c = requires(T t, const T t_const) {
|
||||
typename T::coord_t;
|
||||
typename T::pec_data_t;
|
||||
typename T::pec_result_t;
|
||||
|
||||
{ t.setData(std::declval<typename T::pec_data_t>()) };
|
||||
{ t_const.getData() } -> std::same_as<typename T::pec_data_t>;
|
||||
|
||||
{
|
||||
t.compute(std::declval<const typename T::coord_t&>(), std::declval<const typename T::coord_t&>())
|
||||
} -> std::same_as<typename T::pec_result_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 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
|
||||
@ -15,8 +15,8 @@ namespace traits
|
||||
|
||||
template <typename T>
|
||||
concept mcc_mount_config_c = requires(T t) {
|
||||
{ t.astromEngine() } -> traits::mcc_astrom_engine_c;
|
||||
{ t.hardware() } -> traits::mcc_mount_hardware_c;
|
||||
{ t.astromEngine() } -> mcc_astrom_engine_c;
|
||||
{ t.hardware() } -> mcc_mount_hardware_c;
|
||||
};
|
||||
|
||||
} // namespace traits
|
||||
|
||||
@ -80,21 +80,29 @@ public:
|
||||
// }
|
||||
|
||||
// by default angle is in radians
|
||||
template <typename T>
|
||||
MccAngle(const T& val, const MccRadianTag = MccRadianTag{})
|
||||
requires std::is_arithmetic_v<T>
|
||||
: _angleInRads(val)
|
||||
{
|
||||
}
|
||||
// template <typename T>
|
||||
// MccAngle(const T& val, const MccRadianTag = MccRadianTag{})
|
||||
// requires std::is_arithmetic_v<T>
|
||||
// : _angleInRads(val)
|
||||
// {
|
||||
// }
|
||||
|
||||
// // construct angle in degrees, e.g.:
|
||||
// // auto ang = MccAngle{180.0, mcc_degrees};
|
||||
// template <typename T>
|
||||
// MccAngle(const T& val, const MccDegreeTag)
|
||||
// requires std::is_arithmetic_v<T>
|
||||
// : _angleInRads(val * utils::deg2radCoeff)
|
||||
// {
|
||||
// }
|
||||
|
||||
|
||||
// by default angle is in radians
|
||||
MccAngle(const double& val, const MccRadianTag = MccRadianTag{}) : _angleInRads(val) {}
|
||||
|
||||
// construct angle in degrees, e.g.:
|
||||
// auto ang = MccAngle{180.0, mcc_degrees};
|
||||
template <typename T>
|
||||
MccAngle(const T& val, const MccDegreeTag)
|
||||
requires std::is_arithmetic_v<T>
|
||||
: _angleInRads(val * utils::deg2radCoeff)
|
||||
{
|
||||
}
|
||||
MccAngle(const double& val, const MccDegreeTag) : _angleInRads(val * utils::deg2radCoeff) {}
|
||||
|
||||
|
||||
|
||||
@ -126,6 +134,31 @@ public:
|
||||
|
||||
virtual ~MccAngle() = default;
|
||||
|
||||
template <std::derived_from<MccAngle> T>
|
||||
auto& operator=(this T&& self, const T& other)
|
||||
{
|
||||
std::forward<decltype(self)>(self)._angleInRads = other._angleInRads;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
template <std::derived_from<MccAngle> T>
|
||||
auto& operator=(this T&& self, T&& other)
|
||||
{
|
||||
std::forward<decltype(self)>(self)._angleInRads = std::move(other._angleInRads);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
auto& operator=(this auto&& self, const T& val)
|
||||
requires std::is_arithmetic_v<T>
|
||||
{
|
||||
std::forward<decltype(self)>(self)._angleInRads = val;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
// normalize coordinate
|
||||
template <norm_kind_t KIND>
|
||||
MccAngle& normalize()
|
||||
|
||||
@ -41,6 +41,8 @@ concept mcc_hw_encoder_c = requires(T t, const T t_const) {
|
||||
|
||||
template <typename T>
|
||||
concept mcc_hw_motor_c = requires(T t, const T t_const) {
|
||||
typename T::error_t;
|
||||
|
||||
typename T::coord_t;
|
||||
typename T::speed_t;
|
||||
typename T::accel_t;
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
/* AN REFERENCE "PERIODIC-ERROR-CORRECTION" CLASS IMPLEMENTATION */
|
||||
|
||||
|
||||
|
||||
#include <mutex>
|
||||
#include "fitpack/fitpack.h"
|
||||
#include "mcc_mount_coord.h"
|
||||
|
||||
@ -19,9 +19,13 @@ namespace traits
|
||||
{
|
||||
|
||||
template <typename T, typename XT, typename YT>
|
||||
concept mcc_mount_pec_c = requires(T t, XT x, YT y) {
|
||||
concept mcc_mount_pec_c = requires(T t, const T t_const, XT x, YT y) {
|
||||
typename T::pec_data_t;
|
||||
typename T::pec_result_t;
|
||||
|
||||
{ t.setData(std::declval<typename T::pec_data_t>()) };
|
||||
{ t_const.getData() } -> std::same_as<typename T::pec_data_t>;
|
||||
|
||||
{ t.compute(std::declval<const XT&>(), std::declval<const YT&>()) } -> std::same_as<typename T::pec_result_t>;
|
||||
};
|
||||
|
||||
@ -31,14 +35,11 @@ concept mcc_mount_pec_c = requires(T t, XT x, YT y) {
|
||||
// PEC_TYPE_GEOMETRY - "classic" geometry-based correction coefficients
|
||||
// PEC_TYPE_GEOMETRY_BSPLINE - previous one and additional 2D B-spline corrections
|
||||
// PEC_TYPE_BSPLINE - pure 2D B-spline corrections
|
||||
enum class MccMountPECType { PEC_TYPE_GEOMETRY, PEC_TYPE_GEOMETRY_BSPLINE, PEC_TYPE_BSPLINE };
|
||||
enum class MccMountDefaultPECType { PEC_TYPE_GEOMETRY, PEC_TYPE_GEOMETRY_BSPLINE, PEC_TYPE_BSPLINE };
|
||||
|
||||
template <MccMountPECType TYPE = MccMountPECType::PEC_TYPE_GEOMETRY>
|
||||
class MccMountPEC
|
||||
class MccMountDefaultPEC
|
||||
{
|
||||
public:
|
||||
static constexpr MccMountPECType pecType = TYPE;
|
||||
|
||||
struct pec_result_t {
|
||||
MccAngle dx, dy;
|
||||
};
|
||||
@ -76,31 +77,56 @@ public:
|
||||
std::vector<coeff_t> coeffsY{};
|
||||
};
|
||||
|
||||
struct pec_data_t {
|
||||
MccMountDefaultPECType type{MccMountDefaultPECType::PEC_TYPE_GEOMETRY};
|
||||
double siteLatitude{0.0}; // in radians
|
||||
pec_geom_coeffs_t geomCoefficients{};
|
||||
pec_bspline_coeffs_t bsplineCoefficients{};
|
||||
};
|
||||
|
||||
// constructors
|
||||
|
||||
template <std::derived_from<MccAngle> PhiT>
|
||||
MccMountPEC(const PhiT& phi, pec_geom_coeffs_t geom_coeffs, pec_bspline_coeffs_t bspline_coeffs)
|
||||
requires(TYPE == MccMountPECType::PEC_TYPE_GEOMETRY_BSPLINE)
|
||||
: _phi(phi), _geomCoeffs(std::move(geom_coeffs)), _bspleCoeffs(std::move(bspline_coeffs))
|
||||
{
|
||||
}
|
||||
|
||||
template <std::derived_from<MccAngle> PhiT>
|
||||
MccMountPEC(const PhiT& phi, pec_geom_coeffs_t geom_coeffs)
|
||||
requires(TYPE == MccMountPECType::PEC_TYPE_GEOMETRY)
|
||||
: _phi(phi), _geomCoeffs(std::move(geom_coeffs)), _bspleCoeffs()
|
||||
MccMountDefaultPEC(pec_data_t pdata)
|
||||
: _pecData(std::move(pdata)),
|
||||
_phi(_pecData.siteLatitude),
|
||||
_geomCoeffs(_pecData.geomCoefficients),
|
||||
_bsplCoeffs(_pecData.bsplineCoefficients)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
MccMountPEC(pec_bspline_coeffs_t bspline_coeffs)
|
||||
requires(TYPE == MccMountPECType::PEC_TYPE_BSPLINE)
|
||||
: _geomCoeffs(), _bspleCoeffs(std::move(bspline_coeffs))
|
||||
void setData(pec_data_t pdata)
|
||||
{
|
||||
std::lock_guard lock(_pecDataMutex);
|
||||
|
||||
_pecData = std::move(pdata);
|
||||
_phi = _pecData.siteLatitude;
|
||||
_geomCoeffs = _pecData.geomCoefficients;
|
||||
_bsplCoeffs = _pecData.bsplineCoefficients;
|
||||
}
|
||||
|
||||
|
||||
pec_data_t getData() const
|
||||
{
|
||||
std::lock_guard lock(_pecDataMutex);
|
||||
|
||||
return _pecData;
|
||||
}
|
||||
|
||||
void setType(MccMountDefaultPECType type)
|
||||
{
|
||||
std::lock_guard lock(_pecDataMutex);
|
||||
|
||||
_pecData.type = type;
|
||||
}
|
||||
|
||||
MccMountDefaultPECType getType() const
|
||||
{
|
||||
std::lock_guard lock(_pecDataMutex);
|
||||
|
||||
return _pecData.type;
|
||||
}
|
||||
|
||||
// X and Y axis encoder coordinates
|
||||
template <std::derived_from<MccAngle> XT, std::derived_from<MccAngle> YT>
|
||||
pec_result_t compute(const XT& x, const YT& y)
|
||||
@ -109,8 +135,10 @@ public:
|
||||
|
||||
pec_result_t res{0.0, 0.0};
|
||||
|
||||
std::lock_guard lock(_pecDataMutex);
|
||||
|
||||
if constexpr (coord_kind == MccCoordPairKind::COORDS_KIND_HADEC_APP) {
|
||||
if constexpr (TYPE == MccMountPECType::PEC_TYPE_GEOMETRY) {
|
||||
if (_pecData.type == MccMountDefaultPECType::PEC_TYPE_GEOMETRY) {
|
||||
const auto cosPhi = std::cos(_phi);
|
||||
const auto sinPhi = std::sin(_phi);
|
||||
const auto tanY = std::tan(y);
|
||||
@ -119,22 +147,28 @@ public:
|
||||
const auto cosY = std::cos(y);
|
||||
|
||||
|
||||
res.dx = _geomCoeffs.zeroPointX + _geomCoeffs.collimationErr / cosY + _geomCoeffs.nonperpendErr * tanY -
|
||||
_geomCoeffs.misalignErr1 * cosX * tanY + _geomCoeffs.misalignErr2 * sinX * tanY +
|
||||
_geomCoeffs.tubeFlexure * cosPhi * sinX / cosY -
|
||||
_geomCoeffs.DECaxisFlexure * (cosPhi * cosX + sinPhi * tanY);
|
||||
if (utils::isEqual(cosY, 0.0)) {
|
||||
res.dx = _geomCoeffs.zeroPointX;
|
||||
} else {
|
||||
res.dx = _geomCoeffs.zeroPointX + _geomCoeffs.collimationErr / cosY +
|
||||
_geomCoeffs.nonperpendErr * tanY - _geomCoeffs.misalignErr1 * cosX * tanY +
|
||||
_geomCoeffs.misalignErr2 * sinX * tanY + _geomCoeffs.tubeFlexure * cosPhi * sinX / cosY -
|
||||
_geomCoeffs.DECaxisFlexure * (cosPhi * cosX + sinPhi * tanY);
|
||||
}
|
||||
|
||||
res.dy = _geomCoeffs.zeroPointY + _geomCoeffs.misalignErr1 * sinX + _geomCoeffs.misalignErr2 * cosX +
|
||||
_geomCoeffs.tubeFlexure * (cosPhi * cosX * std::sin(y) - sinPhi * cosY) +
|
||||
_geomCoeffs.forkFlexure / cosX;
|
||||
_geomCoeffs.tubeFlexure * (cosPhi * cosX * std::sin(y) - sinPhi * cosY);
|
||||
if (!utils::isEqual(cosX, 0.0)) {
|
||||
res.dy += _geomCoeffs.forkFlexure / cosX;
|
||||
}
|
||||
}
|
||||
|
||||
if constexpr (TYPE == MccMountPECType::PEC_TYPE_BSPLINE ||
|
||||
TYPE == MccMountPECType::PEC_TYPE_GEOMETRY_BSPLINE) {
|
||||
if (_pecData.type == MccMountDefaultPECType::PEC_TYPE_BSPLINE ||
|
||||
_pecData.type == MccMountDefaultPECType::PEC_TYPE_GEOMETRY_BSPLINE) {
|
||||
double spl_valX, spl_valY;
|
||||
|
||||
int ret = fitpack::fitpack_eval_spl2d(_bspleCoeffs.knotsX, _bspleCoeffs.knotsY, _bspleCoeffs.coeffsX, x,
|
||||
y, spl_valX, _bspleCoeffs.bsplDegreeX, _bspleCoeffs.bsplDegreeY);
|
||||
int ret = fitpack::fitpack_eval_spl2d(_bsplCoeffs.knotsX, _bsplCoeffs.knotsY, _bsplCoeffs.coeffsX, x, y,
|
||||
spl_valX, _bsplCoeffs.bsplDegreeX, _bsplCoeffs.bsplDegreeY);
|
||||
|
||||
if (ret) {
|
||||
res.dx = std::numeric_limits<double>::quiet_NaN();
|
||||
@ -143,8 +177,8 @@ public:
|
||||
}
|
||||
|
||||
|
||||
ret = fitpack::fitpack_eval_spl2d(_bspleCoeffs.knotsX, _bspleCoeffs.knotsY, _bspleCoeffs.coeffsY, x, y,
|
||||
spl_valY, _bspleCoeffs.bsplDegreeX, _bspleCoeffs.bsplDegreeY);
|
||||
ret = fitpack::fitpack_eval_spl2d(_bsplCoeffs.knotsX, _bsplCoeffs.knotsY, _bsplCoeffs.coeffsY, x, y,
|
||||
spl_valY, _bsplCoeffs.bsplDegreeX, _bsplCoeffs.bsplDegreeY);
|
||||
|
||||
if (ret) {
|
||||
res.dx = std::numeric_limits<double>::quiet_NaN();
|
||||
@ -183,9 +217,12 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
double _phi;
|
||||
pec_geom_coeffs_t _geomCoeffs;
|
||||
pec_bspline_coeffs_t _bspleCoeffs;
|
||||
pec_data_t _pecData;
|
||||
double& _phi;
|
||||
pec_geom_coeffs_t& _geomCoeffs;
|
||||
pec_bspline_coeffs_t& _bsplCoeffs;
|
||||
|
||||
mutable std::mutex _pecDataMutex;
|
||||
};
|
||||
|
||||
} // namespace mcc
|
||||
|
||||
@ -19,8 +19,12 @@ namespace traits
|
||||
|
||||
template <typename T>
|
||||
concept mcc_mount_telemetry_c = requires(T t, const T t_const) {
|
||||
typename T::error_t;
|
||||
typename T::mount_telemetry_data_t;
|
||||
{ t.update() };
|
||||
|
||||
{ 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>;
|
||||
};
|
||||
|
||||
@ -162,6 +162,7 @@ concept mcc_tuple_c = requires {
|
||||
template <typename T>
|
||||
concept mcc_nonconst_ref = std::is_lvalue_reference_v<T> && !std::is_const_v<std::remove_reference_t<T>>;
|
||||
|
||||
|
||||
namespace details
|
||||
{
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user