This commit is contained in:
2026-03-20 17:20:46 +03:00
parent 9ad5bfb09b
commit 48d1bf37f7

View File

@@ -21,6 +21,7 @@ namespace mcc::impl
enum class MccDefaultPCMConstructorErrorCode : int { enum class MccDefaultPCMConstructorErrorCode : int {
ERROR_OK, ERROR_OK,
ERROR_NOT_ENOUGH_DATA, ERROR_NOT_ENOUGH_DATA,
ERROR_INVALID_INDEX,
#ifdef USE_BSPLINE_PCM #ifdef USE_BSPLINE_PCM
ERROR_INVALID_KNOTS_NUMBER, ERROR_INVALID_KNOTS_NUMBER,
ERROR_BSPLINE_FIT ERROR_BSPLINE_FIT
@@ -46,7 +47,8 @@ struct MccDefaultPCMConstructorErrorCategory : std::error_category {
return "OK"; return "OK";
case MccDefaultPCMConstructorErrorCode::ERROR_NOT_ENOUGH_DATA: case MccDefaultPCMConstructorErrorCode::ERROR_NOT_ENOUGH_DATA:
return "not enough data point"; return "not enough data point";
case MccDefaultPCMConstructorErrorCode::ERROR_INVALID_INDEX:
return "invalid index of data point";
#ifdef USE_BSPLINE_PCM #ifdef USE_BSPLINE_PCM
case MccDefaultPCMConstructorErrorCode::ERROR_INVALID_KNOTS_NUMBER: case MccDefaultPCMConstructorErrorCode::ERROR_INVALID_KNOTS_NUMBER:
return "invalid number of B-spline knots"; return "invalid number of B-spline knots";
@@ -106,16 +108,16 @@ public:
struct table_t { struct table_t {
std::vector<double> target_colon, target_colat; std::vector<double> target_colon{}, target_colat{};
std::vector<double> hw_colon, hw_colat; std::vector<double> hw_colon{}, hw_colat{};
std::vector<double> colon_res, colat_res; // target - hw std::vector<double> colon_res{}, colat_res{}; // target - hw
}; };
struct compute_result_t { struct compute_result_t {
MccDefaultPCMType pcm_type; MccDefaultPCMType pcm_type;
MccError error{}; // final model computation error MccError error{}; // final model computation error
std::vector<double> model_colon, model_colat; // fitted model values std::vector<double> model_colon, model_colat; // fitting model values
std::vector<double> colon_res, colat_res; // target - model std::vector<double> colon_res, colat_res; // target - model
#ifdef USE_BSPLINE_PCM #ifdef USE_BSPLINE_PCM
@@ -127,12 +129,10 @@ public:
#endif #endif
}; };
MccError addPoint(mcc_skypoint_c auto target_coords, MccError addPoint(mcc_skypoint_c auto target_coords, mcc_coord_pair_c auto const& hw_counts)
mcc_coord_pair_c auto const& hw_counts,
mcc_coord_epoch_c auto const& ref_epoch)
requires(decltype(hw_counts)::pairKind == MccCoordPairKind::COORDS_KIND_XY) requires(decltype(hw_counts)::pairKind == MccCoordPairKind::COORDS_KIND_XY)
{ {
auto err = target_coords.to(ref_coordpair_t::pairKind, ref_epoch); auto err = target_coords.to(ref_coordpair_t::pairKind, hw_counts.epoch());
if (err) { if (err) {
return mcc_deduced_err(err, MccDefaultPCMErrorCode::ERROR_CCTE); return mcc_deduced_err(err, MccDefaultPCMErrorCode::ERROR_CCTE);
} }
@@ -140,6 +140,8 @@ public:
// _table.push_back({target_coords.co_lon(), target_coords.co_lat(), hw_counts.x(), hw_counts.y(), // _table.push_back({target_coords.co_lon(), target_coords.co_lat(), hw_counts.x(), hw_counts.y(),
// target_coords.co_lon() - hw_counts.x(), target_coords.co_lat() - hw_counts.y()}); // target_coords.co_lon() - hw_counts.x(), target_coords.co_lat() - hw_counts.y()});
_tableEpoch.emplace_back(hw_counts.epoch());
_table.target_colon.emplace_back(target_coords.co_lon()); _table.target_colon.emplace_back(target_coords.co_lon());
_table.target_colat.emplace_back(target_coords.co_lon()); _table.target_colat.emplace_back(target_coords.co_lon());
@@ -153,11 +155,25 @@ public:
} }
MccError addPoint(mcc_skypoint_c auto target_coords, mcc_coord_pair_c auto const& hw_counts) template <mcc_coord_pair_c TAG_T, mcc_coord_pair_c HW_T>
MccError getPoint(size_t idx, std::tuple<TAG_T, HW_T>& point)
requires(std::same_as<typename TAG_T::x_t, typename ref_coordpair_t::x_t> &&
std::same_as<typename TAG_T::y_t, typename ref_coordpair_t::y_t> &&
HW_T::pairKind == MccCoordPairKind::COORDS_KIND_XY)
{ {
auto ref_epoch = hw_counts.epoch(); if (idx > _table.target_colon.size()) {
return MccDefaultPCMConstructorErrorCode::ERROR_INVALID_INDEX;
}
return addPoint(std::move(target_coords), hw_counts, ref_epoch); std::get<0>(point).setX(_table.target_colon[idx]);
std::get<0>(point).setY(_table.target_colat[idx]);
std::get<0>(point).setEpoch(_tableEpoch[idx]);
std::get<1>(point).setX(_table.hw_colon[idx]);
std::get<1>(point).setY(_table.hw_colat[idx]);
std::get<1>(point).setEpoch(_tableEpoch[idx]);
return MccDefaultPCMConstructorErrorCode::ERROR_OK;
} }
@@ -168,6 +184,8 @@ public:
void deletePoints() void deletePoints()
{ {
_tableEpoch.clear();
_table.target_colon.clear(); _table.target_colon.clear();
_table.target_colat.clear(); _table.target_colat.clear();
@@ -285,13 +303,13 @@ public:
// the fitting for geometrical coefficients is already done above so // the fitting for geometrical coefficients is already done above so
// one must fit residuals by bivariate B-splines // one must fit residuals by bivariate B-splines
std::vector<double> xres(_table.size()), yres(_table.size()); std::vector<double> xres(numberOfPoints()), yres(numberOfPoints());
// for (size_t i = 0; i < _table.size(); ++i) { // for (size_t i = 0; i < _table.size(); ++i) {
// xres = _table[i].target_colon; // xres = _table[i].target_colon;
// yres = _table[i].target_colat; // yres = _table[i].target_colat;
// } // }
for (size_t i = 0; i < _table.size(); ++i) { for (size_t i = 0; i < numberOfPoints(); ++i) {
xres = _table.target_colon[i]; xres = _table.target_colon[i] - result.;
yres = _table.target_colat[i]; yres = _table.target_colat[i];
} }
} }
@@ -301,7 +319,8 @@ public:
protected: protected:
// std::vector<table_elem_t> _table; // std::vector<table_elem_t> _table;
table_t _table; table_t _table{};
std::vector<MccCelestialCoordEpoch> _tableEpoch{};
compute_result_t bsplineFitting(MccDefaultPCM<MOUNT_TYPE>::pcm_data_t& pcm_data) compute_result_t bsplineFitting(MccDefaultPCM<MOUNT_TYPE>::pcm_data_t& pcm_data)
{ {
@@ -320,22 +339,24 @@ protected:
pcm_data.bspline.coeffsX.resize(Ncoeffs); pcm_data.bspline.coeffsX.resize(Ncoeffs);
pcm_data.bspline.coeffsY.resize(Ncoeffs); pcm_data.bspline.coeffsY.resize(Ncoeffs);
if (pcm_data.type == MccDefaultPCMType::PCM_TYPE_BSPLINE) { /*
// here both direct and inverse coefficients will be calculated WARNING:
pcm_data.inverseBspline.coeffsX.resize(Ncoeffs); FITPACK B-spline on sphere: in the fitting routines the first angle argument is THETA - co-latitude
pcm_data.inverseBspline.coeffsY.resize(Ncoeffs); coordinate and the second one is PHI - co-longitude
*/
// direct (celestial = encoder + pcm) // direct (celestial = encoder + pcm)
result.bspline_fit_err = bsplines::fitpack_sphere_fit(_table.hw_colat, _table.hw_colon, _table.colon_res, result.bspline_fit_err = bsplines::fitpack_sphere_fit(_table.hw_colat, _table.hw_colon, _table.colon_res, 1.0,
1.0, pcm_data.bspline.knotsY, pcm_data.bspline.knotsX, pcm_data.bspline.knotsY, pcm_data.bspline.knotsX,
pcm_data.bspline.coeffsX, resi2x); pcm_data.bspline.coeffsX, resi2x);
if (result.bspline_fit_err > 0) { if (result.bspline_fit_err > 0) {
result.error = MccDefaultPCMConstructorErrorCode::ERROR_BSPLINE_FIT; result.error = MccDefaultPCMConstructorErrorCode::ERROR_BSPLINE_FIT;
return result; return result;
} }
result.bspline_fit_err = bsplines::fitpack_sphere_fit(_table.hw_colat, _table.hw_colon, _table.colat_res, result.bspline_fit_err = bsplines::fitpack_sphere_fit(_table.hw_colat, _table.hw_colon, _table.colat_res, 1.0,
1.0, pcm_data.bspline.knotsY, pcm_data.bspline.knotsX, pcm_data.bspline.knotsY, pcm_data.bspline.knotsX,
pcm_data.bspline.coeffsY, resi2y); pcm_data.bspline.coeffsY, resi2y);
if (result.bspline_fit_err > 0) { if (result.bspline_fit_err > 0) {
result.error = MccDefaultPCMConstructorErrorCode::ERROR_BSPLINE_FIT; result.error = MccDefaultPCMConstructorErrorCode::ERROR_BSPLINE_FIT;
@@ -343,7 +364,29 @@ protected:
} }
bsplines::fitpack_eval_spl2d(pcm_data.bspline.knotsY, pcm_data.bspline.knotsX, pcm_data.bspline.coeffsX,
_table.hw_colat, _table.hw_colon, result.model_colon); // get fitted residuals!!!
bsplines::fitpack_eval_spl2d(pcm_data.bspline.knotsY, pcm_data.bspline.knotsX, pcm_data.bspline.coeffsY,
_table.hw_colat, _table.hw_colon, result.model_colat); // get fitted residuals!!!
result.colon_res.resize(numberOfPoints());
result.colat_res.resize(numberOfPoints());
for (size_t i = 0; i < numberOfPoints(); ++i) {
result.colon_res[i] = _table.colon_res[i] - result.model_colon[i]; // = target - model
result.colat_res[i] = _table.colat_res[i] - result.model_colat[i]; // = target - model
result.model_colon[i] += _table.hw_colon[i]; // == hw + fitted_pcmX
result.model_colat[i] += _table.hw_colat[i]; // == hw + fitted_pcmY
}
if (pcm_data.type == MccDefaultPCMType::PCM_TYPE_BSPLINE) {
// here both direct and inverse coefficients will be calculated
pcm_data.inverseBspline.coeffsX.resize(Ncoeffs);
pcm_data.inverseBspline.coeffsY.resize(Ncoeffs);
// inverse (encoder = celestial + pcm) // inverse (encoder = celestial + pcm)
std::vector<double> colon_res = _table.colon_res; std::vector<double> colon_res = _table.colon_res;
std::vector<double> colat_res = _table.colat_res; std::vector<double> colat_res = _table.colat_res;
for (size_t i = 0; i < colat_res.size(); ++i) { for (size_t i = 0; i < colat_res.size(); ++i) {
@@ -366,8 +409,30 @@ protected:
result.error = MccDefaultPCMConstructorErrorCode::ERROR_BSPLINE_FIT; result.error = MccDefaultPCMConstructorErrorCode::ERROR_BSPLINE_FIT;
return result; return result;
} }
bsplines::fitpack_eval_spl2d(pcm_data.bspline.knotsY, pcm_data.bspline.knotsX,
pcm_data.bspline.inverseCoeffsX, _table.hw_colat, _table.hw_colon,
result.inv_model_colon); // get fitted residuals!!!
bsplines::fitpack_eval_spl2d(pcm_data.bspline.knotsY, pcm_data.bspline.knotsX,
pcm_data.bspline.inverseCoeffsY, _table.hw_colat, _table.hw_colon,
result.inv_model_colat); // get fitted residuals!!!
result.inv_colon_res.resize(numberOfPoints());
result.inv_colat_res.resize(numberOfPoints());
for (size_t i = 0; i < numberOfPoints(); ++i) {
result.inv_colon_res[i] = _table.colon_res[i] - result.inv_model_colon[i]; // = hw - model
result.inv_colat_res[i] = _table.colat_res[i] - result.inv_model_colat[i]; // = hw - model
result.inv_model_colon[i] += _table.target_colon[i]; // == target + fitted_pcmX
result.inv_model_colat[i] += _table.target_colat[i]; // == target + fitted_pcmY
} }
} }
return result;
}
void robustLinearRegress() {}
}; };
} // namespace mcc::impl } // namespace mcc::impl