diff --git a/cxx/mcc_mount_pec.h b/cxx/mcc_mount_pec.h index 2dcb442..94548b9 100644 --- a/cxx/mcc_mount_pec.h +++ b/cxx/mcc_mount_pec.h @@ -5,21 +5,92 @@ namespace mcc { +enum class MccMountPECType { PEC_TYPE_GEOMETRY, PEC_TYPE_GEOMETRY_BSPLINE, PEC_TYPE_BSPLINE }; + +template class MccMountPEC { public: + static constexpr MccMountPECType pecType = TYPE; + struct pec_result_t { MccAngle dx, dy; }; + // "classic" geometric PEC coefficients + struct pec_geom_coeffs_t { + typedef double coeff_t; + + coeff_t zeroPointX; + coeff_t zeroPointY; + coeff_t collimationErr; // tube collimation error + coeff_t nonperpendErr; // X-Y axes nonperpendicularity + coeff_t misalignErr1; // misalignment of hour-angle/azimuth axis: left-right for equatorial, East-West for + // alt-azimuthal + coeff_t misalignErr2; // misalignment of hour-angle/azimuth axis: vertical for equatorial, North-South for + // alt-azimuthal + + coeff_t tubeFlexure; + coeff_t forkFlexure; + coeff_t DECaxisFlexure; // declination axis flexure + }; + + // B-splines coefficients + struct pec_bspline_coeffs_t { + typedef double knot_t; + typedef double coeff_t; + + std::vector knots; + std::vector coeffs; + }; + + + MccMountPEC(pec_geom_coeffs_t geom_coeffs, pec_bspline_coeffs_t bspline_coeffs) + requires(TYPE == MccMountPECType::PEC_TYPE_GEOMETRY_BSPLINE) + : _geomCoeffs(std::move(geom_coeffs)), _bspleCoeffs(std::move(bspline_coeffs)) + { + } + + MccMountPEC(pec_geom_coeffs_t geom_coeffs) + requires(TYPE == MccMountPECType::PEC_TYPE_GEOMETRY) + : _geomCoeffs(std::move(geom_coeffs)), _bspleCoeffs() + { + } + + + MccMountPEC(pec_bspline_coeffs_t bspline_coeffs) + requires(TYPE == MccMountPECType::PEC_TYPE_BSPLINE) + : _geomCoeffs(), _bspleCoeffs(std::move(bspline_coeffs)) + { + } + + + // X and Y axis encoder coordinates template XT, std::derived_from YT> pec_result_t compute(const XT& x, const YT& y) { static constexpr MccCoordPairKind coord_kind = traits::mcc_type_pair_hash(); - pec_result_t res; + pec_result_t res{0.0, 0.0}; if constexpr (coord_kind == MccCoordPairKind::COORDS_KIND_HADEC_APP) { + if constexpr (TYPE == MccMountPECType::PEC_TYPE_GEOMETRY) { + const auto tanY = std::tan(y); + const auto sinX = std::sin(x); + const auto cosX = std::cos(x); + + res.dx = _geomCoeffs.zeroPointX + _geomCoeffs.collimationErr / std::cos(y) + + _geomCoeffs.nonperpendErr * tanY - _geomCoeffs.misalignErr1 * cosX * tanY + + _geomCoeffs.misalignErr2 * sinX * tanY; + + res.dy = _geomCoeffs.zeroPointY + _geomCoeffs.misalignErr1 * sinX + _geomCoeffs.misalignErr2 * cosX; + } + + if constexpr (TYPE == MccMountPECType::PEC_TYPE_BSPLINE || + TYPE == MccMountPECType::PEC_TYPE_GEOMETRY_BSPLINE) { + res.dx += 0.0; + res.dy += 0.0; + } } else if constexpr (coord_kind == MccCoordPairKind::COORDS_KIND_AZALT) { } else { static_assert(false, "UNSUPPORTED"); @@ -27,6 +98,10 @@ public: return res; } + +private: + pec_geom_coeffs_t _geomCoeffs; + pec_bspline_coeffs_t _bspleCoeffs; }; } // namespace mcc