This commit is contained in:
2025-07-08 16:21:03 +03:00
parent c7693b7fea
commit 646b0bde50
9 changed files with 413 additions and 56 deletions

View File

@@ -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