...
This commit is contained in:
parent
4696daa2ee
commit
c2627ecd89
@ -85,7 +85,7 @@ if (WITH_TESTS)
|
|||||||
set(CTTE_TEST_APP ccte_test)
|
set(CTTE_TEST_APP ccte_test)
|
||||||
add_executable(${CTTE_TEST_APP} tests/ccte_test.cpp)
|
add_executable(${CTTE_TEST_APP} tests/ccte_test.cpp)
|
||||||
target_include_directories(${CTTE_TEST_APP} PRIVATE ${ERFA_INCLUDE_DIR})
|
target_include_directories(${CTTE_TEST_APP} PRIVATE ${ERFA_INCLUDE_DIR})
|
||||||
target_link_libraries(${CTTE_TEST_APP} ERFA_LIB)
|
target_link_libraries(${CTTE_TEST_APP} ERFA_LIB bsplines)
|
||||||
|
|
||||||
enable_testing()
|
enable_testing()
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
@ -399,7 +399,7 @@ public:
|
|||||||
{
|
{
|
||||||
error_t ret = MccCCTE_ERFAErrorCode::ERROR_OK;
|
error_t ret = MccCCTE_ERFAErrorCode::ERROR_OK;
|
||||||
|
|
||||||
MccJulianDay jd;
|
// MccJulianDay jd;
|
||||||
|
|
||||||
if (to_pt == nullptr) {
|
if (to_pt == nullptr) {
|
||||||
return ret;
|
return ret;
|
||||||
@ -476,7 +476,8 @@ public:
|
|||||||
return transformCoordinates(pt, to_pt);
|
return transformCoordinates(pt, to_pt);
|
||||||
}
|
}
|
||||||
} else { // the same time points
|
} else { // the same time points
|
||||||
double eo, lst, ha, dec, az, alt;
|
double eo, lst, ha;
|
||||||
|
// , dec, az, alt;
|
||||||
|
|
||||||
auto lst_eo = [&]() {
|
auto lst_eo = [&]() {
|
||||||
// ret = eqOrigins(from_pt.time_point, &eo);
|
// ret = eqOrigins(from_pt.time_point, &eo);
|
||||||
@ -517,7 +518,7 @@ public:
|
|||||||
} else if (to_pt->pair_kind == MccCoordPairKind::COORDS_KIND_RADEC_APP) {
|
} else if (to_pt->pair_kind == MccCoordPairKind::COORDS_KIND_RADEC_APP) {
|
||||||
lst_eo();
|
lst_eo();
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
to_pt->X = lst - from_pt.X + eo;
|
to_pt->X = MccAngle(lst - from_pt.X + eo).normalize<MccAngle::NORM_KIND_0_360>();
|
||||||
to_pt->Y = from_pt.Y;
|
to_pt->Y = from_pt.Y;
|
||||||
} else {
|
} else {
|
||||||
return ret;
|
return ret;
|
||||||
@ -541,7 +542,7 @@ public:
|
|||||||
azalt2hadec(from_pt, to_pt);
|
azalt2hadec(from_pt, to_pt);
|
||||||
lst_eo();
|
lst_eo();
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
to_pt->X = lst - to_pt->X + eo;
|
to_pt->X = MccAngle(lst - to_pt->X + eo).normalize<MccAngle::NORM_KIND_0_360>();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ret = MccCCTE_ERFAErrorCode::ERROR_UNSUPPORTED_COORD_PAIR;
|
ret = MccCCTE_ERFAErrorCode::ERROR_UNSUPPORTED_COORD_PAIR;
|
||||||
@ -560,7 +561,7 @@ public:
|
|||||||
{
|
{
|
||||||
error_t ret = MccCCTE_ERFAErrorCode::ERROR_OK;
|
error_t ret = MccCCTE_ERFAErrorCode::ERROR_OK;
|
||||||
|
|
||||||
MccJulianDay jd;
|
// MccJulianDay jd;
|
||||||
|
|
||||||
if (to_pt == nullptr) {
|
if (to_pt == nullptr) {
|
||||||
return ret;
|
return ret;
|
||||||
|
|||||||
@ -104,6 +104,16 @@ struct MccGenericPointingTarget : MccGenericEqtHrzCoords<CoordT> {
|
|||||||
typedef MccGenericPointingTarget<MccCelestialPoint::coord_t> MccPointingTarget;
|
typedef MccGenericPointingTarget<MccCelestialPoint::coord_t> MccPointingTarget;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
template <mcc_angle_c CoordT>
|
||||||
|
struct MccGenericPCMResult {
|
||||||
|
CoordT pcmX, pcmY;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
typedef MccGenericPCMResult<double> MccPCMResult;
|
||||||
|
|
||||||
|
|
||||||
/* DEFAULT TELEMETRY DATA CLASS */
|
/* DEFAULT TELEMETRY DATA CLASS */
|
||||||
|
|
||||||
template <mcc_angle_c CoordT>
|
template <mcc_angle_c CoordT>
|
||||||
|
|||||||
@ -136,6 +136,13 @@ concept mcc_time_point_c = traits::mcc_systime_c<T>;
|
|||||||
// concept mcc_time_point_c = requires(T t) { []<typename CT, typename DT>(std::chrono::time_point<CT, DT>) {}(t); };
|
// concept mcc_time_point_c = requires(T t) { []<typename CT, typename DT>(std::chrono::time_point<CT, DT>) {}(t); };
|
||||||
|
|
||||||
|
|
||||||
|
template <mcc_time_point_c T1, mcc_time_point_c T2>
|
||||||
|
static constexpr void mcc_tp2tp(const T1& from_tp1, T2& to_tp)
|
||||||
|
{
|
||||||
|
to_tp = std::chrono::time_point_cast<typename T2::duration>(from_tp1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* JULIAN DAY CLASS CONCEPT */
|
/* JULIAN DAY CLASS CONCEPT */
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@ -327,18 +334,66 @@ concept mcc_ccte_c = std::derived_from<T, mcc_CCTE_interface_t<typename T::error
|
|||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
concept mcc_PCM_result_c = requires(T t) {
|
concept mcc_PCM_result_c = requires(T t) {
|
||||||
requires mcc_angle_c<decltype(t.dx)>;
|
requires mcc_angle_c<decltype(t.pcmX)>;
|
||||||
requires mcc_angle_c<decltype(t.dy)>;
|
requires mcc_angle_c<decltype(t.pcmY)>;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <mcc_error_c RetT, mcc_PCM_result_c ResT>
|
template <mcc_error_c RetT>
|
||||||
struct mcc_PCM_interface_t {
|
struct mcc_PCM_interface_t {
|
||||||
virtual ~mcc_PCM_interface_t() = default;
|
virtual ~mcc_PCM_interface_t() = default;
|
||||||
|
|
||||||
|
// ignore app_pt->pair_kind and time points!!!
|
||||||
template <std::derived_from<mcc_PCM_interface_t> SelfT>
|
template <std::derived_from<mcc_PCM_interface_t> SelfT>
|
||||||
RetT computePCM(this SelfT&& self, mcc_celestial_point_c auto pt, ResT* result)
|
RetT computePCM(this SelfT&& self,
|
||||||
|
mcc_celestial_point_c auto pt,
|
||||||
|
mcc_PCM_result_c auto* result,
|
||||||
|
mcc_celestial_point_c auto* app_pt)
|
||||||
{
|
{
|
||||||
return std::forward<SelfT>(self).computePCM(std::move(pt), result);
|
return std::forward<SelfT>(self).computePCM(std::move(pt), result, app_pt);
|
||||||
|
}
|
||||||
|
|
||||||
|
// for equatorial mounts the method must compute:
|
||||||
|
// app_pt->HA = pt.X + result->pcmX
|
||||||
|
// app_pt->DEC_APP = pt.Y + result->pcmY
|
||||||
|
// for alt-azimuthal:
|
||||||
|
// app_pt->AZ = pt.X + result->pcmX
|
||||||
|
// app_pt->ZD = pt.Y + result->pcmY
|
||||||
|
template <std::derived_from<mcc_PCM_interface_t> SelfT>
|
||||||
|
RetT computePCM(this SelfT&& self,
|
||||||
|
mcc_celestial_point_c auto pt,
|
||||||
|
mcc_PCM_result_c auto* result,
|
||||||
|
mcc_eqt_hrz_coord_c auto* app_pt)
|
||||||
|
{
|
||||||
|
return std::forward<SelfT>(self).computePCM(std::move(pt), result, app_pt);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <std::derived_from<mcc_PCM_interface_t> SelfT>
|
||||||
|
RetT computeInversePCM(this SelfT&& self,
|
||||||
|
mcc_celestial_point_c auto app_pt,
|
||||||
|
mcc_PCM_result_c auto* inv_result,
|
||||||
|
mcc_celestial_point_c auto* hw_pt)
|
||||||
|
{
|
||||||
|
return std::forward<SelfT>(self).computePCM(std::move(app_pt), inv_result, hw_pt);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// NOTE: for computation of the corrections the method must use of app_pt.X and app_pt.Y
|
||||||
|
//
|
||||||
|
// for equatorial mounts the method must compute:
|
||||||
|
// hw_pt->X = app_pt.HA + inv_result.pcmX
|
||||||
|
// hw_pt->Y = app_pt.DEC_APP + inv_result.pcmY
|
||||||
|
// and inputs for the corrections computing are app_pt.HA and app_pt.DEC_APP
|
||||||
|
// for alt-azimuthal:
|
||||||
|
// hw_pt->X = app_pt.AZ + inv_result.pcmX
|
||||||
|
// hw_pt->Y = app_pt.ZD + inv_result.pcmY
|
||||||
|
// and inputs for the corrections computing are app_pt.ZA and app_pt.ZD
|
||||||
|
template <std::derived_from<mcc_PCM_interface_t> SelfT>
|
||||||
|
RetT computeInversePCM(this SelfT&& self,
|
||||||
|
mcc_eqt_hrz_coord_c auto app_pt,
|
||||||
|
mcc_PCM_result_c auto* inv_result,
|
||||||
|
mcc_celestial_point_c auto* hw_pt)
|
||||||
|
{
|
||||||
|
return std::forward<SelfT>(self).computePCM(std::move(app_pt), inv_result, hw_pt);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@ -346,15 +401,14 @@ protected:
|
|||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
concept mcc_PCM_c =
|
concept mcc_PCM_c = std::derived_from<T, mcc_PCM_interface_t<typename T::error_t>> && requires {
|
||||||
std::derived_from<T, mcc_PCM_interface_t<typename T::error_t, typename T::pcm_result_t>> && requires {
|
// the 'T' class must contain static constexpr member of 'MccMountType' type
|
||||||
// the 'T' class must contain static constexpr member of 'MccMountType' type
|
requires std::same_as<decltype(T::mountType), const MccMountType>;
|
||||||
requires std::same_as<decltype(T::mountType), const MccMountType>;
|
[]() {
|
||||||
[]() {
|
static constexpr MccMountType val = T::mountType;
|
||||||
static constexpr MccMountType val = T::mountType;
|
return val;
|
||||||
return val;
|
}(); // to ensure 'mountType' can be used in compile-time context
|
||||||
}(); // to ensure 'mountType' can be used in compile-time context
|
};
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -404,13 +458,13 @@ concept mcc_hardware_c = requires(T t, const T t_const) {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
// a class that contains at least time point of measurement, coordinates for x,y axes, its moving rates and moving
|
// a class that contains at least time point of measurement, coordinates for x,y axes,
|
||||||
// type
|
// its moving rates and moving type
|
||||||
requires requires(typename T::hardware_state_t state) {
|
requires mcc_celestial_point_c<typename T::hardware_state_t> && requires(typename T::hardware_state_t state) {
|
||||||
requires mcc_time_point_c<decltype(state.time_point)>; // time point
|
// requires mcc_time_point_c<decltype(state.time_point)>; // time point
|
||||||
|
|
||||||
requires mcc_angle_c<decltype(state.X)>; // target or current co-longitude coordinate
|
// requires mcc_angle_c<decltype(state.X)>; // target or current co-longitude coordinate
|
||||||
requires mcc_angle_c<decltype(state.Y)>; // target or current co-latitude coordinate
|
// requires mcc_angle_c<decltype(state.Y)>; // target or current co-latitude coordinate
|
||||||
|
|
||||||
requires mcc_angle_c<decltype(state.speedX)>; // moving speed along co-longitude coordinate
|
requires mcc_angle_c<decltype(state.speedX)>; // moving speed along co-longitude coordinate
|
||||||
requires mcc_angle_c<decltype(state.speedY)>; // moving speed along co-latitude coordinate
|
requires mcc_angle_c<decltype(state.speedY)>; // moving speed along co-latitude coordinate
|
||||||
|
|||||||
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 mcc
|
||||||
{
|
{
|
||||||
|
|
||||||
namespace details
|
|
||||||
{
|
|
||||||
|
|
||||||
template <mcc::mcc_angle_c CT>
|
|
||||||
struct _pcm_result_t {
|
|
||||||
CT dx, dy;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace details
|
|
||||||
|
|
||||||
// type of PCM corrections (algorithm used):
|
// type of PCM corrections (algorithm used):
|
||||||
// PCM_TYPE_GEOMETRY - "classic" geometry-based correction coefficients
|
// 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 };
|
enum class MccDefaultPCMType { PCM_TYPE_GEOMETRY, PCM_TYPE_GEOMETRY_BSPLINE, PCM_TYPE_BSPLINE };
|
||||||
|
|
||||||
template <MccMountType MOUNT_TYPE>
|
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:
|
public:
|
||||||
static constexpr MccMountType mountType = MOUNT_TYPE;
|
static constexpr MccMountType mountType = MOUNT_TYPE;
|
||||||
@ -99,7 +89,6 @@ public:
|
|||||||
typedef std::error_code error_t;
|
typedef std::error_code error_t;
|
||||||
typedef double coord_t;
|
typedef double coord_t;
|
||||||
|
|
||||||
typedef details::_pcm_result_t<coord_t> pcm_result_t;
|
|
||||||
|
|
||||||
// "classic" geometric PEC coefficients
|
// "classic" geometric PEC coefficients
|
||||||
struct pcm_geom_coeffs_t {
|
struct pcm_geom_coeffs_t {
|
||||||
@ -143,7 +132,11 @@ public:
|
|||||||
|
|
||||||
// constructors
|
// 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(MccDefaultPCM&& other) = default;
|
||||||
MccDefaultPCM& operator=(MccDefaultPCM&& other) = default;
|
MccDefaultPCM& operator=(MccDefaultPCM&& other) = default;
|
||||||
@ -153,47 +146,49 @@ public:
|
|||||||
|
|
||||||
virtual ~MccDefaultPCM() = default;
|
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:
|
// The computed PCM quantities must be interpretated as:
|
||||||
// apparent_X = encoder_X + pcm_result_t.dx
|
// apparent_X = encoder_X + res.pcmX
|
||||||
// apparent_Y = encoder_Y + pcm_result_t.dy
|
// apparent_Y = encoder_Y + res.pcmY
|
||||||
// so, input x and y are assumed to be mount axis encoder coordinates
|
// 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 constexpr (mcc_is_equatorial_mount<MOUNT_TYPE>) { // equatorial
|
||||||
if (_pecData.type == MccDefaultPCMType::PCM_TYPE_GEOMETRY) {
|
if (_pcmData.type == MccDefaultPCMType::PCM_TYPE_GEOMETRY) {
|
||||||
const auto cosPhi = std::cos(_pecData.siteLatitude);
|
const auto cosPhi = std::cos(_pcmData.siteLatitude);
|
||||||
const auto sinPhi = std::sin(_pecData.siteLatitude);
|
const auto sinPhi = std::sin(_pcmData.siteLatitude);
|
||||||
const auto tanY = std::tan(pt.Y);
|
const auto tanY = std::tan(pt.Y);
|
||||||
const auto sinX = std::sin(pt.X);
|
const auto sinX = std::sin(pt.X);
|
||||||
const auto cosX = std::cos(pt.X);
|
const auto cosX = std::cos(pt.X);
|
||||||
@ -201,55 +196,55 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
if (utils::isEqual(cosY, 0.0)) {
|
if (utils::isEqual(cosY, 0.0)) {
|
||||||
res.dx = _pecData.geomCoefficients.zeroPointX;
|
res->pcmX = _pcmData.geomCoefficients.zeroPointX;
|
||||||
} else {
|
} else {
|
||||||
res.dx = _pecData.geomCoefficients.zeroPointX + _pecData.geomCoefficients.collimationErr / cosY +
|
res->pcmX = _pcmData.geomCoefficients.zeroPointX + _pcmData.geomCoefficients.collimationErr / cosY +
|
||||||
_pecData.geomCoefficients.nonperpendErr * tanY -
|
_pcmData.geomCoefficients.nonperpendErr * tanY -
|
||||||
_pecData.geomCoefficients.misalignErr1 * cosX * tanY +
|
_pcmData.geomCoefficients.misalignErr1 * cosX * tanY +
|
||||||
_pecData.geomCoefficients.misalignErr2 * sinX * tanY +
|
_pcmData.geomCoefficients.misalignErr2 * sinX * tanY +
|
||||||
_pecData.geomCoefficients.tubeFlexure * cosPhi * sinX / cosY -
|
_pcmData.geomCoefficients.tubeFlexure * cosPhi * sinX / cosY -
|
||||||
_pecData.geomCoefficients.DECaxisFlexure * (cosPhi * cosX + sinPhi * tanY);
|
_pcmData.geomCoefficients.DECaxisFlexure * (cosPhi * cosX + sinPhi * tanY);
|
||||||
}
|
}
|
||||||
|
|
||||||
res.dy = _pecData.geomCoefficients.zeroPointY + _pecData.geomCoefficients.misalignErr1 * sinX +
|
res->pcmY = _pcmData.geomCoefficients.zeroPointY + _pcmData.geomCoefficients.misalignErr1 * sinX +
|
||||||
_pecData.geomCoefficients.misalignErr2 * cosX +
|
_pcmData.geomCoefficients.misalignErr2 * cosX +
|
||||||
_pecData.geomCoefficients.tubeFlexure * (cosPhi * cosX * std::sin(pt.Y) - sinPhi * cosY);
|
_pcmData.geomCoefficients.tubeFlexure * (cosPhi * cosX * std::sin(pt.Y) - sinPhi * cosY);
|
||||||
|
|
||||||
if constexpr (mountType == MccMountType::FORK_TYPE) {
|
if constexpr (mountType == MccMountType::FORK_TYPE) {
|
||||||
if (!utils::isEqual(cosX, 0.0)) {
|
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 ||
|
if (_pcmData.type == MccDefaultPCMType::PCM_TYPE_BSPLINE ||
|
||||||
_pecData.type == MccDefaultPCMType::PCM_TYPE_GEOMETRY_BSPLINE) {
|
_pcmData.type == MccDefaultPCMType::PCM_TYPE_GEOMETRY_BSPLINE) {
|
||||||
double spl_valX, spl_valY;
|
double spl_valX, spl_valY;
|
||||||
|
|
||||||
int ret = bsplines::fitpack_eval_spl2d(_pecData.bspline.knotsX, _pecData.bspline.knotsY,
|
int ret = bsplines::fitpack_eval_spl2d(_pcmData.bspline.knotsX, _pcmData.bspline.knotsY,
|
||||||
_pecData.bspline.coeffsX, pt.X, pt.Y, spl_valX,
|
_pcmData.bspline.coeffsX, pt.X, pt.Y, spl_valX,
|
||||||
_pecData.bspline.bsplDegreeX, _pecData.bspline.bsplDegreeY);
|
_pcmData.bspline.bsplDegreeX, _pcmData.bspline.bsplDegreeY);
|
||||||
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
res.dx = std::numeric_limits<double>::quiet_NaN();
|
res->pcmX = std::numeric_limits<double>::quiet_NaN();
|
||||||
res.dy = std::numeric_limits<double>::quiet_NaN();
|
res->pcmY = std::numeric_limits<double>::quiet_NaN();
|
||||||
return MccDefaultPCMErrorCode::ERROR_INVALID_INPUTS_BISPLEV;
|
return MccDefaultPCMErrorCode::ERROR_INVALID_INPUTS_BISPLEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ret = bsplines::fitpack_eval_spl2d(_pecData.bspline.knotsX, _pecData.bspline.knotsY,
|
ret = bsplines::fitpack_eval_spl2d(_pcmData.bspline.knotsX, _pcmData.bspline.knotsY,
|
||||||
_pecData.bspline.coeffsY, pt.X, pt.Y, spl_valY,
|
_pcmData.bspline.coeffsY, pt.X, pt.Y, spl_valY,
|
||||||
_pecData.bspline.bsplDegreeX, _pecData.bspline.bsplDegreeY);
|
_pcmData.bspline.bsplDegreeX, _pcmData.bspline.bsplDegreeY);
|
||||||
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
res.dx = std::numeric_limits<double>::quiet_NaN();
|
res->pcmX = std::numeric_limits<double>::quiet_NaN();
|
||||||
res.dy = std::numeric_limits<double>::quiet_NaN();
|
res->pcmY = std::numeric_limits<double>::quiet_NaN();
|
||||||
return MccDefaultPCMErrorCode::ERROR_INVALID_INPUTS_BISPLEV;
|
return MccDefaultPCMErrorCode::ERROR_INVALID_INPUTS_BISPLEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
res.dx += spl_valX;
|
res->pcmX += spl_valX;
|
||||||
res.dy += spl_valY;
|
res->pcmY += spl_valY;
|
||||||
}
|
}
|
||||||
} else if constexpr (mcc_is_altaz_mount<MOUNT_TYPE>) {
|
} else if constexpr (mcc_is_altaz_mount<MOUNT_TYPE>) {
|
||||||
static_assert(false, "NOT IMPLEMENTED!");
|
static_assert(false, "NOT IMPLEMENTED!");
|
||||||
@ -257,14 +252,65 @@ public:
|
|||||||
static_assert(false, "UNSUPPORTED");
|
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;
|
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:
|
private:
|
||||||
pcm_data_t _pecData;
|
pcm_data_t _pcmData;
|
||||||
|
|
||||||
std::unique_ptr<std::mutex> _pecDataMutex;
|
std::unique_ptr<std::mutex> _pcmDataMutex;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -294,8 +294,9 @@ public:
|
|||||||
ha = coords.HA;
|
ha = coords.HA;
|
||||||
dec = coords.DEC_APP;
|
dec = coords.DEC_APP;
|
||||||
} else {
|
} else {
|
||||||
MccCelestialPoint to_pt{.pair_kind = MccCoordPairKind::COORDS_KIND_HADEC_APP,
|
MccCelestialPoint to_pt{.pair_kind = MccCoordPairKind::COORDS_KIND_HADEC_APP};
|
||||||
.time_point = coords.time_point};
|
mcc_tp2tp(coords.time_point, to_pt.time_point);
|
||||||
|
|
||||||
ret = getCoord(coords, &to_pt);
|
ret = getCoord(coords, &to_pt);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
return ret;
|
return ret;
|
||||||
@ -310,7 +311,7 @@ public:
|
|||||||
auto cos_ha = (_sinAlim - sinDec * _sinLat) / cosDec / _cosLat;
|
auto cos_ha = (_sinAlim - sinDec * _sinLat) / cosDec / _cosLat;
|
||||||
|
|
||||||
if (cos_ha > 1.0) { // no intersection
|
if (cos_ha > 1.0) { // no intersection
|
||||||
point->pair_kind = MccCoordPairKind::COORDS_KIND_GENERIC;
|
// point->pair_kind = MccCoordPairKind::COORDS_KIND_GENERIC;
|
||||||
point->X = std::numeric_limits<double>::quiet_NaN();
|
point->X = std::numeric_limits<double>::quiet_NaN();
|
||||||
point->Y = std::numeric_limits<double>::quiet_NaN();
|
point->Y = std::numeric_limits<double>::quiet_NaN();
|
||||||
|
|
||||||
@ -328,14 +329,16 @@ public:
|
|||||||
az = -std::acos(cosA);
|
az = -std::acos(cosA);
|
||||||
}
|
}
|
||||||
|
|
||||||
MccCelestialPoint pt{
|
MccCelestialPoint pt{.pair_kind = MccCoordPairKind::COORDS_KIND_AZALT, .X = az, .Y = _altLimit};
|
||||||
.pair_kind = MccCoordPairKind::COORDS_KIND_AZALT, .time_point = coords.time_point, .X = az, .Y = _altLimit},
|
mcc_tp2tp(coords.time_point, pt.time_point);
|
||||||
to_pt{.pair_kind = point->pair_kind, .time_point = point->time_point};
|
|
||||||
|
MccCelestialPoint to_pt{.pair_kind = point->pair_kind};
|
||||||
|
mcc_tp2tp(point->time_point, to_pt.time_point);
|
||||||
|
|
||||||
ret = _transformCoordinates(pt, &to_pt);
|
ret = _transformCoordinates(pt, &to_pt);
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
point->X = to_pt.X;
|
point->X = MccAngle(to_pt.X).normalize<MccAngle::NORM_KIND_0_360>();
|
||||||
point->Y = to_pt.Y;
|
point->Y = MccAngle(to_pt.Y).normalize<MccAngle::NORM_KIND_90_90>();
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|||||||
@ -320,14 +320,18 @@ public:
|
|||||||
MccCelestialPoint pt;
|
MccCelestialPoint pt;
|
||||||
|
|
||||||
auto apply_func = [&](auto& func, auto& pt_arg, size_t i) {
|
auto apply_func = [&](auto& func, auto& pt_arg, size_t i) {
|
||||||
|
auto ptr = result->begin();
|
||||||
|
std::ranges::advance(ptr, i);
|
||||||
|
|
||||||
|
pt.pair_kind = ptr->pair_kind;
|
||||||
|
pt.time_point = ptr->time_point;
|
||||||
|
|
||||||
error_t ret = func(pt_arg, &pt);
|
error_t ret = func(pt_arg, &pt);
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
// if (traits::mcc_range_size(*result) == i) {
|
// if (traits::mcc_range_size(*result) == i) {
|
||||||
// std::back_inserter(*result) = CPT();
|
// std::back_inserter(*result) = CPT();
|
||||||
// }
|
// }
|
||||||
|
|
||||||
auto ptr = result->begin();
|
|
||||||
std::ranges::advance(ptr, i);
|
|
||||||
mcc_copy_celestial_point(pt, &(*ptr));
|
mcc_copy_celestial_point(pt, &(*ptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -191,41 +191,39 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// compute hardware coordinates
|
|
||||||
// WARNING: It is assumed here that PCM corrections have small (arcseconds-arcminutes) values
|
|
||||||
// since ususaly there is no reverse transformation for "hardware-to-apparent" relation!
|
|
||||||
typename pcm_t::error_t pcm_err;
|
typename pcm_t::error_t pcm_err;
|
||||||
|
|
||||||
struct {
|
MccPCMResult pcm_res;
|
||||||
double dx, dy;
|
|
||||||
} pcm_res;
|
|
||||||
|
|
||||||
|
// MccCelestialPoint pt;
|
||||||
|
// pt.time_point =
|
||||||
|
// std::chrono::time_point_cast<typename decltype(pt.time_point)::duration>(_data.target.time_point);
|
||||||
|
|
||||||
MccCelestialPoint pt;
|
pcm_err = pcm->computeInversePCM(_data, &pcm_res, &_data);
|
||||||
pt.time_point =
|
|
||||||
std::chrono::time_point_cast<typename decltype(pt.time_point)::duration>(_data.target.time_point);
|
|
||||||
|
|
||||||
if constexpr (mccIsEquatorialMount(pcm_t::mountType)) {
|
// if constexpr (mccIsEquatorialMount(pcm_t::mountType)) {
|
||||||
pt.pair_kind = MccCoordPairKind::COORDS_KIND_HADEC_APP;
|
// pcm_err = pcm->computeInversePCM(_data, &pcm_res, &_data);
|
||||||
pt.X = _data.target.HA;
|
|
||||||
pt.Y = _data.target.DEC_APP;
|
// pt.pair_kind = MccCoordPairKind::COORDS_KIND_HADEC_APP;
|
||||||
pcm_err = pcm->compute(std::move(pt), &pcm_res);
|
// pt.X = _data.target.HA;
|
||||||
if (!pcm_err) {
|
// pt.Y = _data.target.DEC_APP;
|
||||||
_data.target.X = _data.target.HA - pcm_res.dx;
|
// pcm_err = pcm->computeInversePCM(std::move(pt), &pcm_res);
|
||||||
_data.target.Y = _data.target.DEC_APP - pcm_res.dy;
|
// if (!pcm_err) {
|
||||||
}
|
// _data.target.X = _data.target.HA - pcm_res.pcmX;
|
||||||
} else if constexpr (mccIsAltAzMount(pcm_t::mountType)) {
|
// _data.target.Y = _data.target.DEC_APP - pcm_res.pcmY;
|
||||||
pt.pair_kind = MccCoordPairKind::COORDS_KIND_AZALT;
|
// }
|
||||||
pt.X = _data.target.AZ;
|
// } else if constexpr (mccIsAltAzMount(pcm_t::mountType)) {
|
||||||
pt.Y = _data.target.ALT;
|
// pt.pair_kind = MccCoordPairKind::COORDS_KIND_AZALT;
|
||||||
pcm_err = pcm->compute(std::move(pt), &pcm_res);
|
// pt.X = _data.target.AZ;
|
||||||
if (!pcm_err) {
|
// pt.Y = _data.target.ALT;
|
||||||
_data.target.X = _data.target.AZ - pcm_res.dx;
|
// pcm_err = pcm->computeInversePCM(std::move(pt), &pcm_res);
|
||||||
_data.target.Y = _data.target.ALT - pcm_res.dy;
|
// if (!pcm_err) {
|
||||||
}
|
// _data.target.X = _data.target.AZ - pcm_res.pcmX;
|
||||||
} else {
|
// _data.target.Y = _data.target.ALT - pcm_res.pcmY;
|
||||||
static_assert(false, "UNKNOWN MOUNT TYPE!");
|
// }
|
||||||
}
|
// } else {
|
||||||
|
// static_assert(false, "UNKNOWN MOUNT TYPE!");
|
||||||
|
// }
|
||||||
|
|
||||||
if (pcm_err) {
|
if (pcm_err) {
|
||||||
return mcc_deduce_error<error_t>(pcm_err, MccTelemetryErrorCode::ERROR_PCM_COMP);
|
return mcc_deduce_error<error_t>(pcm_err, MccTelemetryErrorCode::ERROR_PCM_COMP);
|
||||||
@ -281,18 +279,12 @@ public:
|
|||||||
_data.speedX = (double)hw_pos.speedX;
|
_data.speedX = (double)hw_pos.speedX;
|
||||||
_data.speedY = (double)hw_pos.speedY;
|
_data.speedY = (double)hw_pos.speedY;
|
||||||
|
|
||||||
struct {
|
// fill _data.pcmX, _data.pcmY and corresponded apparent coordinates
|
||||||
double dx, dy;
|
auto pcm_err = pcm->computePCM(_data, &_data, &_data);
|
||||||
} pcm_res;
|
|
||||||
|
|
||||||
auto pcm_err = pcm->computePCM(_data, &pcm_res);
|
|
||||||
if (pcm_err) {
|
if (pcm_err) {
|
||||||
return mcc_deduce_error(pcm_err, MccTelemetryErrorCode::ERROR_PCM_COMP);
|
return mcc_deduce_error(pcm_err, MccTelemetryErrorCode::ERROR_PCM_COMP);
|
||||||
}
|
}
|
||||||
|
|
||||||
_data.pcmX = pcm_res.dx;
|
|
||||||
_data.pcmY = pcm_res.dy;
|
|
||||||
|
|
||||||
if (stop_token.stop_requested()) {
|
if (stop_token.stop_requested()) {
|
||||||
return MccTelemetryErrorCode::ERROR_UPDATE_STOPPED;
|
return MccTelemetryErrorCode::ERROR_UPDATE_STOPPED;
|
||||||
}
|
}
|
||||||
@ -300,8 +292,6 @@ public:
|
|||||||
MccCelestialPoint pt{.pair_kind = MccCoordPairKind::COORDS_KIND_AZALT, .time_point = _data.time_point};
|
MccCelestialPoint pt{.pair_kind = MccCoordPairKind::COORDS_KIND_AZALT, .time_point = _data.time_point};
|
||||||
|
|
||||||
if constexpr (mccIsEquatorialMount(pcm_t::mountType)) {
|
if constexpr (mccIsEquatorialMount(pcm_t::mountType)) {
|
||||||
_data.HA = (double)hw_pos.X + pcm_res.dx;
|
|
||||||
_data.DEC_APP = (double)hw_pos.Y + pcm_res.dy;
|
|
||||||
_data.RA_APP = (double)_data.LST - (double)_data.HA + eo;
|
_data.RA_APP = (double)_data.LST - (double)_data.HA + eo;
|
||||||
|
|
||||||
_data.X = _data.HA;
|
_data.X = _data.HA;
|
||||||
@ -316,14 +306,12 @@ public:
|
|||||||
_data.ZD = std::numbers::pi / 2.0 - _data.ALT;
|
_data.ZD = std::numbers::pi / 2.0 - _data.ALT;
|
||||||
}
|
}
|
||||||
} else if constexpr (mccIsAltAzMount(pcm_t::mountType)) {
|
} else if constexpr (mccIsAltAzMount(pcm_t::mountType)) {
|
||||||
_data.AZ = (double)hw_pos.X + pcm_res.dx;
|
_data.ALT = std::numbers::pi / 2.0 - _data.ZD;
|
||||||
_data.ALT = (double)hw_pos.Y + pcm_res.dy;
|
|
||||||
_data.ZD = std::numbers::pi / 2.0 - _data.ALT;
|
|
||||||
|
|
||||||
_data.X = _data.AZ;
|
_data.X = _data.AZ;
|
||||||
_data.Y = _data.ALT;
|
_data.Y = _data.ZD;
|
||||||
|
|
||||||
_data.pair_kind = MccCoordPairKind::COORDS_KIND_AZALT;
|
_data.pair_kind = MccCoordPairKind::COORDS_KIND_AZZD;
|
||||||
|
|
||||||
pt.pair_kind = MccCoordPairKind::COORDS_KIND_HADEC_APP;
|
pt.pair_kind = MccCoordPairKind::COORDS_KIND_HADEC_APP;
|
||||||
ccte_err = ccte->transformCoordinates(_data, &pt);
|
ccte_err = ccte->transformCoordinates(_data, &pt);
|
||||||
|
|||||||
@ -18,7 +18,7 @@ enum class MccSimpleTrackingModelErrorCode : int {
|
|||||||
ERROR_HW_GETSTATE,
|
ERROR_HW_GETSTATE,
|
||||||
ERROR_HW_SETSTATE,
|
ERROR_HW_SETSTATE,
|
||||||
ERROR_PCM_COMP,
|
ERROR_PCM_COMP,
|
||||||
ERROR_TELEMETRY_TIMEOUT,
|
ERROR_GET_TELEMETRY,
|
||||||
ERROR_PZONE_CONTAINER_COMP,
|
ERROR_PZONE_CONTAINER_COMP,
|
||||||
ERROR_IN_PZONE,
|
ERROR_IN_PZONE,
|
||||||
ERROR_NEAR_PZONE,
|
ERROR_NEAR_PZONE,
|
||||||
@ -80,11 +80,9 @@ public:
|
|||||||
// compute position in future
|
// compute position in future
|
||||||
auto err = hardware->hardwareGetState(&hw_state);
|
auto err = hardware->hardwareGetState(&hw_state);
|
||||||
if (err) {
|
if (err) {
|
||||||
return mcc_deduce_error(err, MccSimpleTrackingModelErrorCode::ERROR_HW_GETSTATE);
|
return mcc_deduce_error<error_t>(err, MccSimpleTrackingModelErrorCode::ERROR_HW_GETSTATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
cpt.time_point = std::chrono::time_point_cast<decltype(cpt.time_point)>(hw_state.time_point);
|
|
||||||
|
|
||||||
if constexpr (mccIsEquatorialMount(PcmT::mountType)) {
|
if constexpr (mccIsEquatorialMount(PcmT::mountType)) {
|
||||||
cpt.pair_kind = MccCoordPairKind::COORDS_KIND_HADEC_APP;
|
cpt.pair_kind = MccCoordPairKind::COORDS_KIND_HADEC_APP;
|
||||||
} else if constexpr (mccIsAltAzMount(PcmT::mountType)) {
|
} else if constexpr (mccIsAltAzMount(PcmT::mountType)) {
|
||||||
@ -94,62 +92,94 @@ public:
|
|||||||
static_assert(false, "UNKNOW MOUNT TYPE!");
|
static_assert(false, "UNKNOW MOUNT TYPE!");
|
||||||
}
|
}
|
||||||
|
|
||||||
cpt.X = hw_state.X;
|
|
||||||
cpt.Y = hw_state.Y;
|
|
||||||
|
|
||||||
struct {
|
MccTelemetryData tdata;
|
||||||
double dx, dy;
|
auto t_err = telemetry->waitForTelemetryData(&tdata, _currentTrackParams.telemetryTimeout);
|
||||||
} pcm_res;
|
if (t_err) {
|
||||||
|
return mcc_deduce_error<error_t>(t_err, MccSimpleTrackingModelErrorCode::ERROR_GET_TELEMETRY);
|
||||||
auto pcm_err = pcm->computePCM(cpt, &pcm_res);
|
|
||||||
if (pcm_err) {
|
|
||||||
return mcc_deduce_error(pcm_err, MccSimpleTrackingModelErrorCode::ERROR_PCM_COMP);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// to celestial coordinates
|
mcc_tp2tp(tdata.time_point, cpt.time_point);
|
||||||
cpt.X += pcm_res.dx;
|
|
||||||
cpt.Y += pcm_res.dy;
|
|
||||||
|
|
||||||
|
|
||||||
|
std::vector<std::chrono::duration<double>> pz_timeto; // in seconds
|
||||||
|
std::chrono::duration<double> min_time{0.0};
|
||||||
|
std::vector<MccCelestialPoint> intsc_pt(pz_cont->sizePZones(), cpt);
|
||||||
|
|
||||||
|
// compute intersection points with the prohibited zones
|
||||||
|
auto pz_err = pz_cont->intersectPZone(tdata, &intsc_pt);
|
||||||
|
if (pz_err) {
|
||||||
|
return mcc_deduce_error<error_t>(pz_err, MccSimpleTrackingModelErrorCode::ERROR_PZONE_CONTAINER_COMP);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if constexpr (mccIsEquatorialMount(PcmT::mountType)) {
|
if constexpr (mccIsEquatorialMount(PcmT::mountType)) {
|
||||||
cpt.pair_kind = MccCoordPairKind::COORDS_KIND_HADEC_APP;
|
double dha_min = 0.0, dha;
|
||||||
|
|
||||||
|
// find the closest pzone
|
||||||
|
|
||||||
|
for (auto& ipt : intsc_pt) {
|
||||||
|
if (std::isfinite(ipt.X) && std::isfinite(ipt.Y)) {
|
||||||
|
dha = ipt.X - tdata.HA;
|
||||||
|
if (dha < 0.0) {
|
||||||
|
dha += std::numbers::pi * 2.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dha < dha_min) {
|
||||||
|
dha_min = dha;
|
||||||
|
cpt.X = ipt.X;
|
||||||
|
cpt.Y = ipt.Y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (utils::isEqual(dha_min, 0.0)) { // no intersections
|
||||||
|
cpt.X = tdata.HA - 1.0_mins;
|
||||||
|
cpt.Y = tdata.DEC_APP;
|
||||||
|
}
|
||||||
|
|
||||||
|
MccPCMResult pcm_inv_res;
|
||||||
|
|
||||||
|
// endpoint of the mount moving
|
||||||
|
auto pcm_err = pcm->computeInversePCM(cpt, &pcm_inv_res, &hw_state);
|
||||||
|
if (pcm_err) {
|
||||||
|
return mcc_deduce_error<error_t>(pcm_err, MccSimpleTrackingModelErrorCode::ERROR_PCM_COMP);
|
||||||
|
}
|
||||||
|
|
||||||
// just set sideral rate once
|
// just set sideral rate once
|
||||||
// hw_state.time_point;
|
mcc_tp2tp(cpt.time_point, hw_state.time_point);
|
||||||
hw_state.speedX = _currentTrackParams.trackSpeedX;
|
hw_state.speedX = _currentTrackParams.trackSpeedX;
|
||||||
hw_state.speedY = _currentTrackParams.trackSpeedY;
|
hw_state.speedY = _currentTrackParams.trackSpeedY;
|
||||||
hw_state.moving_type = HardwareT::hardware_moving_state_t::HW_MOVE_TRACKING;
|
hw_state.moving_type = HardwareT::hardware_moving_state_t::HW_MOVE_TRACKING;
|
||||||
|
|
||||||
|
// start tracking
|
||||||
err = hardware->hardwareSetState(std::move(hw_state));
|
err = hardware->hardwareSetState(std::move(hw_state));
|
||||||
if (err) {
|
if (err) {
|
||||||
return mcc_deduce_error(err, MccSimpleTrackingModelErrorCode::ERROR_HW_SETSTATE);
|
return mcc_deduce_error<error_t>(err, MccSimpleTrackingModelErrorCode::ERROR_HW_SETSTATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// control prohibited zones
|
|
||||||
MccTelemetryData tdata;
|
|
||||||
std::vector<std::chrono::duration<double>> pz_timeto; // in seconds
|
|
||||||
|
|
||||||
// std::vector<bool> pz_flags;
|
|
||||||
// bool inzone_flag;
|
|
||||||
|
|
||||||
while (!*_stopTracking) {
|
while (!*_stopTracking) {
|
||||||
auto pz_err = pz_cont->timeToPZone(tdata, &pz_timeto);
|
// control prohibited zones
|
||||||
|
pz_err = pz_cont->timeToPZone(tdata, &pz_timeto);
|
||||||
if (pz_err) {
|
if (pz_err) {
|
||||||
return mcc_deduce_error(pz_err, MccSimpleTrackingModelErrorCode::ERROR_PZONE_CONTAINER_COMP);
|
return mcc_deduce_error<error_t>(pz_err,
|
||||||
|
MccSimpleTrackingModelErrorCode::ERROR_PZONE_CONTAINER_COMP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
min_time = std::chrono::duration<double>{0};
|
||||||
for (size_t i = 0; i < pz_cont->sizePZones(); ++i) {
|
for (size_t i = 0; i < pz_cont->sizePZones(); ++i) {
|
||||||
if (pz_timeto[i] <= _currentTrackParams.minTimeToPZone) {
|
if (pz_timeto[i] <= _currentTrackParams.minTimeToPZone) {
|
||||||
return MccSimpleTrackingModelErrorCode::ERROR_NEAR_PZONE;
|
return MccSimpleTrackingModelErrorCode::ERROR_NEAR_PZONE;
|
||||||
}
|
}
|
||||||
|
if (pz_timeto[i] < min_time) {
|
||||||
|
min_time = pz_timeto[i];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto t_err = telemetry->waitForTelemetryData(&tdata, _currentTrackParams.telemetryTimeout);
|
t_err = telemetry->waitForTelemetryData(&tdata, _currentTrackParams.telemetryTimeout);
|
||||||
if (t_err) {
|
if (t_err) {
|
||||||
return mcc_deduce_error(t_err, MccSimpleTrackingModelErrorCode::ERROR_TELEMETRY_TIMEOUT);
|
return mcc_deduce_error<error_t>(t_err, MccSimpleTrackingModelErrorCode::ERROR_GET_TELEMETRY);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*_stopTracking) {
|
if (*_stopTracking) {
|
||||||
@ -161,16 +191,6 @@ public:
|
|||||||
// unhandled stop state?!!!
|
// unhandled stop state?!!!
|
||||||
return MccSimpleTrackingModelErrorCode::ERROR_UNEXPECTED_AXIS_RATES;
|
return MccSimpleTrackingModelErrorCode::ERROR_UNEXPECTED_AXIS_RATES;
|
||||||
}
|
}
|
||||||
|
|
||||||
// auto pz_err = mount->inPZone(tdata, &inzone_flag, &pz_flags);
|
|
||||||
// if (pz_err) {
|
|
||||||
// return mcc_deduce_error(t_err, MccSimpleTrackingModelErrorCode::ERROR_PZONE_CONTAINER_COMP);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (inzone_flag) {
|
|
||||||
// // logging
|
|
||||||
// return MccSimpleTrackingModelErrorCode::ERROR_IN_PZONE;
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return MccSimpleTrackingModelErrorCode::ERROR_OK;
|
return MccSimpleTrackingModelErrorCode::ERROR_OK;
|
||||||
|
|||||||
@ -223,6 +223,11 @@ static R rad2sxg(double ang, bool hms = false, int prec = 2)
|
|||||||
{
|
{
|
||||||
R res;
|
R res;
|
||||||
|
|
||||||
|
if (!std::isfinite(ang)) {
|
||||||
|
std::vformat_to(std::back_inserter(res), "{}", std::make_format_args(ang));
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
std::string fmt = "{:02.0f}:{:02.0f}:{:0" + std::to_string(prec + 3) + "." + std::to_string(prec) + "f}";
|
std::string fmt = "{:02.0f}:{:02.0f}:{:0" + std::to_string(prec + 3) + "." + std::to_string(prec) + "f}";
|
||||||
// std::string fmt = "{:02.0f}:{:02.0f}:{:02." + std::to_string(prec) + "f}";
|
// std::string fmt = "{:02.0f}:{:02.0f}:{:02." + std::to_string(prec) + "f}";
|
||||||
|
|
||||||
|
|||||||
@ -105,6 +105,19 @@ int main()
|
|||||||
std::cout << "TIME TO ZONE 2: " << vm[1] << "\n";
|
std::cout << "TIME TO ZONE 2: " << vm[1] << "\n";
|
||||||
|
|
||||||
|
|
||||||
|
std::vector<mcc::MccCelestialPoint> vpt(
|
||||||
|
2, {.pair_kind = mcc::MccCoordPairKind::COORDS_KIND_AZZD, .time_point = eqhrz.time_point});
|
||||||
|
|
||||||
|
ret = pzcont.intersectPZone(eqhrz, &vpt);
|
||||||
|
std::cout << "ret = " << ret.message() << "\n";
|
||||||
|
if (!ret) {
|
||||||
|
std::cout << "INTERSC POINT 1: AZ = " << mcc::MccAngle(vpt[0].X).sexagesimal()
|
||||||
|
<< ", ZD = " << mcc::MccAngle(vpt[0].Y).sexagesimal() << "\n";
|
||||||
|
std::cout << "INTERSC POINT 2: AZ = " << mcc::MccAngle(vpt[1].X).sexagesimal()
|
||||||
|
<< ", ZD = " << mcc::MccAngle(vpt[1].Y).sexagesimal() << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
std::cout << "\n\n";
|
std::cout << "\n\n";
|
||||||
|
|
||||||
MccCCTE_ERFA::meteo_t meteo{.temperature = 10.0, .humidity = 0.7, .pressure = 1010.0};
|
MccCCTE_ERFA::meteo_t meteo{.temperature = 10.0, .humidity = 0.7, .pressure = 1010.0};
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user