...
This commit is contained in:
166
mcc/mcc_pcm.h
166
mcc/mcc_pcm.h
@@ -73,16 +73,6 @@ class is_error_code_enum<mcc::MccDefaultPCMErrorCode> : public true_type
|
||||
namespace mcc
|
||||
{
|
||||
|
||||
namespace details
|
||||
{
|
||||
|
||||
template <mcc::mcc_angle_c CT>
|
||||
struct _pcm_result_t {
|
||||
CT dx, dy;
|
||||
};
|
||||
|
||||
|
||||
} // namespace details
|
||||
|
||||
// type of PCM corrections (algorithm used):
|
||||
// PCM_TYPE_GEOMETRY - "classic" geometry-based correction coefficients
|
||||
@@ -91,7 +81,7 @@ struct _pcm_result_t {
|
||||
enum class MccDefaultPCMType { PCM_TYPE_GEOMETRY, PCM_TYPE_GEOMETRY_BSPLINE, PCM_TYPE_BSPLINE };
|
||||
|
||||
template <MccMountType MOUNT_TYPE>
|
||||
class MccDefaultPCM : public mcc_PCM_interface_t<std::error_code, details::_pcm_result_t<double>>
|
||||
class MccDefaultPCM : public mcc_PCM_interface_t<std::error_code>
|
||||
{
|
||||
public:
|
||||
static constexpr MccMountType mountType = MOUNT_TYPE;
|
||||
@@ -99,7 +89,6 @@ public:
|
||||
typedef std::error_code error_t;
|
||||
typedef double coord_t;
|
||||
|
||||
typedef details::_pcm_result_t<coord_t> pcm_result_t;
|
||||
|
||||
// "classic" geometric PEC coefficients
|
||||
struct pcm_geom_coeffs_t {
|
||||
@@ -143,7 +132,11 @@ public:
|
||||
|
||||
// constructors
|
||||
|
||||
MccDefaultPCM(pcm_data_t pdata) : _pecData(std::move(pdata)), _pecDataMutex(new std::mutex) {}
|
||||
MccDefaultPCM() : _pcmDataMutex(new std::mutex) {}
|
||||
MccDefaultPCM(pcm_data_t pdata) : MccDefaultPCM()
|
||||
{
|
||||
_pcmData = std::move(pdata);
|
||||
}
|
||||
|
||||
MccDefaultPCM(MccDefaultPCM&& other) = default;
|
||||
MccDefaultPCM& operator=(MccDefaultPCM&& other) = default;
|
||||
@@ -153,47 +146,49 @@ public:
|
||||
|
||||
virtual ~MccDefaultPCM() = default;
|
||||
|
||||
void setData(pcm_data_t pdata)
|
||||
void setPCMData(pcm_data_t pdata)
|
||||
{
|
||||
std::lock_guard lock(*_pecDataMutex);
|
||||
std::lock_guard lock(*_pcmDataMutex);
|
||||
|
||||
_pecData = std::move(pdata);
|
||||
_pcmData = std::move(pdata);
|
||||
}
|
||||
|
||||
|
||||
pcm_data_t getData() const
|
||||
pcm_data_t getPCMData() const
|
||||
{
|
||||
std::lock_guard lock(*_pecDataMutex);
|
||||
std::lock_guard lock(*_pcmDataMutex);
|
||||
|
||||
return _pecData;
|
||||
return _pcmData;
|
||||
}
|
||||
|
||||
void setType(MccDefaultPCMType type)
|
||||
void setPCMType(MccDefaultPCMType type)
|
||||
{
|
||||
std::lock_guard lock(*_pecDataMutex);
|
||||
std::lock_guard lock(*_pcmDataMutex);
|
||||
|
||||
_pecData.type = type;
|
||||
_pcmData.type = type;
|
||||
}
|
||||
|
||||
MccDefaultPCMType getType() const
|
||||
MccDefaultPCMType getPCMType() const
|
||||
{
|
||||
std::lock_guard lock(*_pecDataMutex);
|
||||
std::lock_guard lock(*_pcmDataMutex);
|
||||
|
||||
return _pecData.type;
|
||||
return _pcmData.type;
|
||||
}
|
||||
|
||||
// The computed PEC quantities must be interpretated as:
|
||||
// apparent_X = encoder_X + pcm_result_t.dx
|
||||
// apparent_Y = encoder_Y + pcm_result_t.dy
|
||||
// The computed PCM quantities must be interpretated as:
|
||||
// apparent_X = encoder_X + res.pcmX
|
||||
// apparent_Y = encoder_Y + res.pcmY
|
||||
// so, input x and y are assumed to be mount axis encoder coordinates
|
||||
error_t compute(mcc_celestial_point_c auto pt, pcm_result_t& res)
|
||||
template <typename T = std::nullptr_t>
|
||||
error_t computePCM(mcc_celestial_point_c auto pt, mcc_PCM_c auto* res, T* app_pt = nullptr)
|
||||
requires(mcc_celestial_point_c<T> || mcc_eqt_hrz_coord_c<T> || std::same_as<T, std::nullptr_t>)
|
||||
{
|
||||
std::lock_guard lock(*_pecDataMutex);
|
||||
std::lock_guard lock(*_pcmDataMutex);
|
||||
|
||||
if constexpr (mcc_is_equatorial_mount<MOUNT_TYPE>) { // equatorial
|
||||
if (_pecData.type == MccDefaultPCMType::PCM_TYPE_GEOMETRY) {
|
||||
const auto cosPhi = std::cos(_pecData.siteLatitude);
|
||||
const auto sinPhi = std::sin(_pecData.siteLatitude);
|
||||
if (_pcmData.type == MccDefaultPCMType::PCM_TYPE_GEOMETRY) {
|
||||
const auto cosPhi = std::cos(_pcmData.siteLatitude);
|
||||
const auto sinPhi = std::sin(_pcmData.siteLatitude);
|
||||
const auto tanY = std::tan(pt.Y);
|
||||
const auto sinX = std::sin(pt.X);
|
||||
const auto cosX = std::cos(pt.X);
|
||||
@@ -201,55 +196,55 @@ public:
|
||||
|
||||
|
||||
if (utils::isEqual(cosY, 0.0)) {
|
||||
res.dx = _pecData.geomCoefficients.zeroPointX;
|
||||
res->pcmX = _pcmData.geomCoefficients.zeroPointX;
|
||||
} else {
|
||||
res.dx = _pecData.geomCoefficients.zeroPointX + _pecData.geomCoefficients.collimationErr / cosY +
|
||||
_pecData.geomCoefficients.nonperpendErr * tanY -
|
||||
_pecData.geomCoefficients.misalignErr1 * cosX * tanY +
|
||||
_pecData.geomCoefficients.misalignErr2 * sinX * tanY +
|
||||
_pecData.geomCoefficients.tubeFlexure * cosPhi * sinX / cosY -
|
||||
_pecData.geomCoefficients.DECaxisFlexure * (cosPhi * cosX + sinPhi * tanY);
|
||||
res->pcmX = _pcmData.geomCoefficients.zeroPointX + _pcmData.geomCoefficients.collimationErr / cosY +
|
||||
_pcmData.geomCoefficients.nonperpendErr * tanY -
|
||||
_pcmData.geomCoefficients.misalignErr1 * cosX * tanY +
|
||||
_pcmData.geomCoefficients.misalignErr2 * sinX * tanY +
|
||||
_pcmData.geomCoefficients.tubeFlexure * cosPhi * sinX / cosY -
|
||||
_pcmData.geomCoefficients.DECaxisFlexure * (cosPhi * cosX + sinPhi * tanY);
|
||||
}
|
||||
|
||||
res.dy = _pecData.geomCoefficients.zeroPointY + _pecData.geomCoefficients.misalignErr1 * sinX +
|
||||
_pecData.geomCoefficients.misalignErr2 * cosX +
|
||||
_pecData.geomCoefficients.tubeFlexure * (cosPhi * cosX * std::sin(pt.Y) - sinPhi * cosY);
|
||||
res->pcmY = _pcmData.geomCoefficients.zeroPointY + _pcmData.geomCoefficients.misalignErr1 * sinX +
|
||||
_pcmData.geomCoefficients.misalignErr2 * cosX +
|
||||
_pcmData.geomCoefficients.tubeFlexure * (cosPhi * cosX * std::sin(pt.Y) - sinPhi * cosY);
|
||||
|
||||
if constexpr (mountType == MccMountType::FORK_TYPE) {
|
||||
if (!utils::isEqual(cosX, 0.0)) {
|
||||
res.dy += _pecData.geomCoefficients.forkFlexure / cosX;
|
||||
res->pcmY += _pcmData.geomCoefficients.forkFlexure / cosX;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_pecData.type == MccDefaultPCMType::PCM_TYPE_BSPLINE ||
|
||||
_pecData.type == MccDefaultPCMType::PCM_TYPE_GEOMETRY_BSPLINE) {
|
||||
if (_pcmData.type == MccDefaultPCMType::PCM_TYPE_BSPLINE ||
|
||||
_pcmData.type == MccDefaultPCMType::PCM_TYPE_GEOMETRY_BSPLINE) {
|
||||
double spl_valX, spl_valY;
|
||||
|
||||
int ret = bsplines::fitpack_eval_spl2d(_pecData.bspline.knotsX, _pecData.bspline.knotsY,
|
||||
_pecData.bspline.coeffsX, pt.X, pt.Y, spl_valX,
|
||||
_pecData.bspline.bsplDegreeX, _pecData.bspline.bsplDegreeY);
|
||||
int ret = bsplines::fitpack_eval_spl2d(_pcmData.bspline.knotsX, _pcmData.bspline.knotsY,
|
||||
_pcmData.bspline.coeffsX, pt.X, pt.Y, spl_valX,
|
||||
_pcmData.bspline.bsplDegreeX, _pcmData.bspline.bsplDegreeY);
|
||||
|
||||
if (ret) {
|
||||
res.dx = std::numeric_limits<double>::quiet_NaN();
|
||||
res.dy = std::numeric_limits<double>::quiet_NaN();
|
||||
res->pcmX = std::numeric_limits<double>::quiet_NaN();
|
||||
res->pcmY = std::numeric_limits<double>::quiet_NaN();
|
||||
return MccDefaultPCMErrorCode::ERROR_INVALID_INPUTS_BISPLEV;
|
||||
}
|
||||
|
||||
|
||||
ret = bsplines::fitpack_eval_spl2d(_pecData.bspline.knotsX, _pecData.bspline.knotsY,
|
||||
_pecData.bspline.coeffsY, pt.X, pt.Y, spl_valY,
|
||||
_pecData.bspline.bsplDegreeX, _pecData.bspline.bsplDegreeY);
|
||||
ret = bsplines::fitpack_eval_spl2d(_pcmData.bspline.knotsX, _pcmData.bspline.knotsY,
|
||||
_pcmData.bspline.coeffsY, pt.X, pt.Y, spl_valY,
|
||||
_pcmData.bspline.bsplDegreeX, _pcmData.bspline.bsplDegreeY);
|
||||
|
||||
if (ret) {
|
||||
res.dx = std::numeric_limits<double>::quiet_NaN();
|
||||
res.dy = std::numeric_limits<double>::quiet_NaN();
|
||||
res->pcmX = std::numeric_limits<double>::quiet_NaN();
|
||||
res->pcmY = std::numeric_limits<double>::quiet_NaN();
|
||||
return MccDefaultPCMErrorCode::ERROR_INVALID_INPUTS_BISPLEV;
|
||||
}
|
||||
|
||||
|
||||
res.dx += spl_valX;
|
||||
res.dy += spl_valY;
|
||||
res->pcmX += spl_valX;
|
||||
res->pcmY += spl_valY;
|
||||
}
|
||||
} else if constexpr (mcc_is_altaz_mount<MOUNT_TYPE>) {
|
||||
static_assert(false, "NOT IMPLEMENTED!");
|
||||
@@ -257,14 +252,65 @@ public:
|
||||
static_assert(false, "UNSUPPORTED");
|
||||
}
|
||||
|
||||
if constexpr (!std::is_null_pointer_v<T>) {
|
||||
if constexpr (mcc_eqt_hrz_coord_c<T>) {
|
||||
if constexpr (mccIsEquatorialMount(mountType)) {
|
||||
app_pt->HA = pt.X + res->pcmX;
|
||||
app_pt->DEC_APP = pt.Y + res->pcmY;
|
||||
} else if constexpr (mccIsAltAzMount(mountType)) {
|
||||
app_pt->AZ = pt.X + res->pcmX;
|
||||
app_pt->ZD = pt.Y + res->pcmY;
|
||||
} else {
|
||||
static_assert(false, "UNKNOW MOUNT TYPE!");
|
||||
}
|
||||
} else {
|
||||
app_pt->X = pt.X + res->pcmX;
|
||||
app_pt->Y = pt.Y + res->pcmY;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return MccDefaultPCMErrorCode::ERROR_OK;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
error_t computeInversePCM(T app_pt, mcc_PCM_result_c auto* result, mcc_celestial_point_c auto* hw_pt = nullptr)
|
||||
requires(mcc_celestial_point_c<T> || mcc_eqt_hrz_coord_c<T>)
|
||||
{
|
||||
// for small corrections only!!!
|
||||
auto ret = computePCM(std::move(app_pt), result);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
result->pcmX = -result->pcmX;
|
||||
result->pcmY = -result->pcmY;
|
||||
|
||||
if (hw_pt != nullptr) {
|
||||
if constexpr (mcc_eqt_hrz_coord_c<T>) {
|
||||
if constexpr (mccIsEquatorialMount(mountType)) {
|
||||
hw_pt->X = app_pt.HA + result->pcmX;
|
||||
hw_pt->Y = app_pt.DEC_APP + result->pcmY;
|
||||
} else if constexpr (mccIsAltAzMount(mountType)) {
|
||||
hw_pt->X = app_pt.AZ + result->pcmX;
|
||||
hw_pt->Y = app_pt.ZD + result->pcmY;
|
||||
} else {
|
||||
static_assert(false, "UNKNOW MOUNT TYPE!");
|
||||
}
|
||||
} else {
|
||||
hw_pt->X = app_pt.X + result->pcmX;
|
||||
hw_pt->Y = app_pt.Y + result->pcmY;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private:
|
||||
pcm_data_t _pecData;
|
||||
pcm_data_t _pcmData;
|
||||
|
||||
std::unique_ptr<std::mutex> _pecDataMutex;
|
||||
std::unique_ptr<std::mutex> _pcmDataMutex;
|
||||
};
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user