Compare commits

...

10 Commits

Author SHA1 Message Date
1a8e1bbed0 ... 2026-02-17 18:27:57 +03:00
578339fd8b ... 2026-02-17 16:24:33 +03:00
775dedd835 ... 2026-02-17 15:59:14 +03:00
1841664b63 ... 2026-02-17 15:01:16 +03:00
5cfa67d6a1 ... 2026-02-17 15:00:45 +03:00
8dd5e4751c ... 2026-02-17 14:42:48 +03:00
b1c5b64879 ... 2026-02-17 14:41:42 +03:00
c5299d06bb ... 2026-02-17 14:23:10 +03:00
5202f8dc84 ... 2026-02-17 14:13:42 +03:00
ec7b7d8506 ... 2026-02-17 14:08:46 +03:00
6 changed files with 102 additions and 38 deletions

View File

@@ -505,8 +505,14 @@ template <typename T>
concept mcc_skypoint_c = std::derived_from<T, mcc_skypoint_interface_t> && requires(const T t_const) { concept mcc_skypoint_c = std::derived_from<T, mcc_skypoint_interface_t> && requires(const T t_const) {
{ t_const.epoch() } -> mcc_coord_epoch_c; { t_const.epoch() } -> mcc_coord_epoch_c;
// currently stored coordinates pair // currently stored coordinates pair kind
{ t_const.pairKind() } -> std::same_as<impl::MccCoordPairKind>; { t_const.pairKind() } -> std::same_as<impl::MccCoordPairKind>;
// currently stored co-longitude coordinate
{ t_const.co_lon() } -> std::convertible_to<double>;
// currently stored co-latitude coordinate
{ t_const.co_lat() } -> std::convertible_to<double>;
}; };
@@ -656,6 +662,14 @@ concept mcc_hardware_c = requires(T t) {
// static const variable with name of hardware // static const variable with name of hardware
requires std::formattable<decltype(T::hardwareName), char> && std::is_const_v<decltype(T::hardwareName)>; requires std::formattable<decltype(T::hardwareName), char> && std::is_const_v<decltype(T::hardwareName)>;
// the 'T' class must contain static constexpr member of 'MccMountType' type
requires std::same_as<decltype(T::mountType), const MccMountType>;
[]() {
[[maybe_unused]] static constexpr MccMountType val = T::mountType;
}(); // to ensure 'mountType' can be used in compile-time context
// a type that defines at least HW_MOVE_ERROR, HW_MOVE_STOPPING, HW_MOVE_STOPPED, HW_MOVE_SLEWING, // a type that defines at least HW_MOVE_ERROR, HW_MOVE_STOPPING, HW_MOVE_STOPPED, HW_MOVE_SLEWING,
// HW_MOVE_ADJUSTING, HW_MOVE_TRACKING and HW_MOVE_GUIDING compile-time constants. The main purpose of this type is // HW_MOVE_ADJUSTING, HW_MOVE_TRACKING and HW_MOVE_GUIDING compile-time constants. The main purpose of this type is
// a possible tunning of hardware hardwareSetState-related commands and detect the stop and error states from // a possible tunning of hardware hardwareSetState-related commands and detect the stop and error states from
@@ -804,14 +818,14 @@ struct mcc_telemetry_interface_t {
// set target position // set target position
template <std::derived_from<mcc_telemetry_interface_t> SelfT> template <std::derived_from<mcc_telemetry_interface_t> SelfT>
RetT setTarget(this SelfT&& self, mcc_skypoint_c auto const& pt) RetT setPointingTarget(this SelfT&& self, mcc_skypoint_c auto const& pt)
{ {
return std::forward<SelfT>(self).setTarget(pt); return std::forward<SelfT>(self).setTarget(pt);
} }
// get entered target position // get entered target position
template <std::derived_from<mcc_telemetry_interface_t> SelfT> template <std::derived_from<mcc_telemetry_interface_t> SelfT>
RetT getTarget(this SelfT&& self, mcc_skypoint_c auto* pt) RetT getPointingTarget(this SelfT&& self, mcc_skypoint_c auto* pt)
{ {
return std::forward<SelfT>(self).getTarget(pt); return std::forward<SelfT>(self).getTarget(pt);
} }

View File

@@ -234,7 +234,7 @@ struct MccSkyRADEC_ICRS : MccCoordPair<MccAngleRA_ICRS, MccAngleDEC_ICRS> {
// ignore epoch setting (it is always J2000.0) // ignore epoch setting (it is always J2000.0)
void setEpoch(mcc_coord_epoch_c auto const&) void setEpoch(mcc_coord_epoch_c auto const&)
{ {
static_assert(false, "CANNOT SET EPOCH FOR ICRS-KIND COORDINATE PAIR!!!"); // static_assert(false, "CANNOT SET EPOCH FOR ICRS-KIND COORDINATE PAIR!!!");
} }
}; };
@@ -344,14 +344,24 @@ struct MccSkyAZALT : MccCoordPair<MccAngleAZ, MccAngleALT> {
} }
}; };
using MccGenXY = MccCoordPair<MccAngleX, MccAngleY>; using MccGenXY = MccCoordPair<MccAngleX, MccAngleY>;
using MccGeoLONLAT = MccCoordPair<MccAngleLON, MccAngleLAT>; using MccGeoLONLAT = MccCoordPair<MccAngleLON, MccAngleLAT>;
// utility type definition: deduce a coordinate pair kind according to mount type
// mcc_deduced_coord_pair_t = MccSkyHADEC_OBS for equathorial mounts,
// mcc_deduced_coord_pair_t = MccSkyAZZD for altazimuthal ones and
// mcc_deduced_coord_pair_t = std::nullptr_t otherwise
template <MccMountType MOUNT_TYPE>
using mcc_deduced_coord_pair_t =
std::conditional_t<mccIsEquatorialMount(MOUNT_TYPE),
MccSkyHADEC_OBS,
std::conditional_t<mccIsAltAzMount(MOUNT_TYPE), MccSkyAZZD, std::nullptr_t>>;
static MccSkyHADEC_APP hadec = MccGenXY{};
static MccSkyAZALT azalt{MccSkyAZZD{1.0, 1.1}};
// static MccSkyHADEC_APP hadec = MccGenXY{};
// static MccSkyAZALT azalt{MccSkyAZZD{1.0, 1.1}};
/* MCC-LIBRARY DEFAULT GENERIC SKY POINT CLASS IMPLEMENTATION */ /* MCC-LIBRARY DEFAULT GENERIC SKY POINT CLASS IMPLEMENTATION */
@@ -423,6 +433,17 @@ public:
return _epoch; return _epoch;
} }
double co_lon() const
{
return _x;
}
double co_lat() const
{
return _y;
}
template <mcc_coord_pair_c PT> template <mcc_coord_pair_c PT>
MccGenericSkyPoint& from(const PT& coord_pair) MccGenericSkyPoint& from(const PT& coord_pair)
{ {

View File

@@ -53,7 +53,7 @@ struct std::formatter<mcc::impl::MccError, char> {
// _currFmt.push_back(*(++it)); // _currFmt.push_back(*(++it));
// } // }
if (it++ != ctx.end() || it++ != '}') { if (it++ != ctx.end() || *(it++) != '}') {
_delim = *(++it); _delim = *(++it);
} }
case '}': case '}':

View File

@@ -271,7 +271,7 @@ protected:
private: private:
std::string _filename; std::string _filename;
std::istringstream _st; std::ostringstream _st;
}; };
@@ -283,29 +283,33 @@ public:
template <mcc_hardware_c HARDWARE_T, template <mcc_hardware_c HARDWARE_T,
mcc_generic_mount_c MOUNT_T, // MOUNT_T is mcc_telemetry_c, mcc_pzone_container_c and mcc_logger_c mcc_generic_mount_c MOUNT_T, // MOUNT_T is mcc_telemetry_c, mcc_pzone_container_c and mcc_logger_c
// (see mcc_concepts.h) // (see mcc_concepts.h)
mcc_mount_status_c STATUS_T, std::invocable<typename MOUNT_T::mount_status_t const&> CallbackFuncT =
std::invocable<STATUS_T const&> CallbackFuncT = decltype([](STATUS_T const&) {})> decltype([](typename MOUNT_T::mount_status_t const&) {})>
MccSimpleMovementControls( MccSimpleMovementControls(
HARDWARE_T* hardware, HARDWARE_T* hardware,
MOUNT_T* mount, MOUNT_T* mount,
CallbackFuncT&& mode_switch_callback = [](STATUS_T const&) {}) CallbackFuncT&& mode_switch_callback = [](typename MOUNT_T::mount_status_t const&) {})
: MccSimpleMovementControls(hardware, mount, mount, mode_switch_callback, *mount) : MccSimpleMovementControls(hardware, mount, mount, std::forward<CallbackFuncT>(mode_switch_callback), mount)
{ {
} }
template <mcc_hardware_c HARDWARE_T, template <mcc_hardware_c HARDWARE_T,
mcc_telemetry_c TELEMETRY_T, mcc_telemetry_c TELEMETRY_T,
mcc_pzone_container_c PZONE_CONT_T, mcc_pzone_container_c PZONE_CONT_T,
mcc_mount_status_c STATUS_T, typename CallbackFuncT,
std::invocable<STATUS_T const&> CallbackFuncT = decltype([](STATUS_T const&) {}),
mcc_logger_c LOGGER_T = MccNullLogger> mcc_logger_c LOGGER_T = MccNullLogger>
MccSimpleMovementControls( MccSimpleMovementControls(HARDWARE_T* hardware,
HARDWARE_T* hardware,
TELEMETRY_T* telemetry, TELEMETRY_T* telemetry,
PZONE_CONT_T* pzone_cont, PZONE_CONT_T* pzone_cont,
CallbackFuncT&& mode_switch_callback = [](STATUS_T const&) {}, CallbackFuncT&& mode_switch_callback,
LOGGER_T* logger = &details::NullLogger) LOGGER_T* logger = &details::NullLogger)
{ {
static_assert(traits::mcc_func_traits<CallbackFuncT>::arity == 1 &&
mcc_mount_status_c<std::decay_t<traits::mcc_func_arg1_t<CallbackFuncT>>>,
"INVALID 'CallbackFuncT' CALLABLE SIGNATURE!");
using STATUS_T = std::decay_t<traits::mcc_func_arg1_t<CallbackFuncT>>;
auto send_to_hardware = [hardware, logger](typename HARDWARE_T::hardware_state_t const& hw_state) -> error_t { auto send_to_hardware = [hardware, logger](typename HARDWARE_T::hardware_state_t const& hw_state) -> error_t {
if constexpr (std::derived_from<decltype(hw_state.XY), MccCoordPair<MccAngleX, MccAngleY>>) { if constexpr (std::derived_from<decltype(hw_state.XY), MccCoordPair<MccAngleX, MccAngleY>>) {
logger->logDebug(std::format("Send to hardware: X = {} degs, Y = {} degs", hw_state.XY.x().degrees(), logger->logDebug(std::format("Send to hardware: X = {} degs, Y = {} degs", hw_state.XY.x().degrees(),
@@ -372,14 +376,14 @@ public:
static_assert(!std::is_null_pointer_v<decltype(mount_pos)>, "UNKNOWn MOUNT TYPE"); static_assert(!std::is_null_pointer_v<decltype(mount_pos)>, "UNKNOWn MOUNT TYPE");
mount_pos.setX(tdata.hwState.XY.x() + tdata.pcmCorrection.x + dx); mount_pos.setX((double)tdata.hwState.XY.x() + tdata.pcmCorrection.pcmX + dx);
mount_pos.setY(tdata.hwState.XY.y() + tdata.pcmCorrection.y + dy); mount_pos.setY((double)tdata.hwState.XY.y() + tdata.pcmCorrection.pcmY + dy);
mount_pos.setEpoch(tdata.hwState.XY.epoch()); mount_pos.setEpoch(tdata.hwState.XY.epoch());
logger->logTrace(std::format(" mount: speedX = {}/s, speedY = {}/s", MccAngleFancyString(speedX), logger->logTrace(std::format(" mount: speedX = {}/s, speedY = {}/s", MccAngleFancyString(speedX),
MccAngleFancyString(speedY))); MccAngleFancyString(speedY)));
auto pz_err = pzone_cont->inPZone(mount_pos, &in_zone, &in_zone_vec); auto pz_err = pzone_cont->inPZone(MccSkyPoint(mount_pos), &in_zone, &in_zone_vec);
if (pz_err) { if (pz_err) {
return mcc_deduced_err(pz_err, MccSimpleMovementControlsErrorCode::ERROR_PZONE_CONTAINER_COMP); return mcc_deduced_err(pz_err, MccSimpleMovementControlsErrorCode::ERROR_PZONE_CONTAINER_COMP);
} }
@@ -433,7 +437,7 @@ public:
}; };
auto log_pos = [logger, this](typename TELEMETRY_T::telemetry_data_t const& tdata) { auto log_pos = [logger, this](typename TELEMETRY_T::telemetry_data_t const& tdata) -> error_t {
double x_mnt, y_mnt, x_tag, y_tag; double x_mnt, y_mnt, x_tag, y_tag;
std::conditional_t<mccIsEquatorialMount(HARDWARE_T::mountType), MccSkyHADEC_OBS, std::conditional_t<mccIsEquatorialMount(HARDWARE_T::mountType), MccSkyHADEC_OBS,
@@ -470,9 +474,11 @@ public:
logger->logTrace(std::format(" current mount: {} = {}, {} = {}", x_str, coord_pair.x().sexagesimal(true), logger->logTrace(std::format(" current mount: {} = {}, {} = {}", x_str, coord_pair.x().sexagesimal(true),
y_str, coord_pair.y().sexagesimal())); y_str, coord_pair.y().sexagesimal()));
_pathFile << tdata.mountPos.epoch().UTC.time_since_epoch().count() << " " << x_tag << " " << y_tag << " " _pathFile << tdata.mountPos.epoch().UTC().time_since_epoch().count() << " " << x_tag << " " << y_tag << " "
<< x_mnt << " " << y_mnt << " " << (x_tag - x_mnt) << " " << (y_tag - y_mnt) << " " << x_mnt << " " << y_mnt << " " << (x_tag - x_mnt) << " " << (y_tag - y_mnt) << " "
<< (int)tdata.hwState.movementState << "\n"; << (int)tdata.hwState.movementState << "\n";
return MccSimpleMovementControlsErrorCode::ERROR_OK;
}; };
auto cb_sptr = auto cb_sptr =
@@ -593,8 +599,10 @@ public:
(*cb_sptr)(STATUS_T::MOUNT_STATUS_SLEWING); (*cb_sptr)(STATUS_T::MOUNT_STATUS_SLEWING);
auto start_point = tdata.hwState.XY.epoch().UTC(); // needed for trajectory file auto start_point = std::chrono::steady_clock::now();
auto last_hw_time = start_point; auto last_hw_time = tdata.hwState.XY.epoch().UTC();
mcc_deduced_coord_pair_t<HARDWARE_T::mountType> tag_cp, mnt_cp;
while (!*_stopMoving) { while (!*_stopMoving) {
t_err = telemetry->telemetryData(&tdata); t_err = telemetry->telemetryData(&tdata);
@@ -641,8 +649,16 @@ public:
last_hw_time = tdata.hwState.XY.epoch().UTC(); last_hw_time = tdata.hwState.XY.epoch().UTC();
auto dist = utils::distanceOnSphere(tdata.targetPos.x(), tdata.targetPos.y(), tdata.mountPos.x(), auto ccte_err = tdata.targetPos.to(tag_cp);
tdata.mountPos.y()); if (ccte_err) {
*_lastError = mcc_deduced_err(ccte_err, MccSimpleMovementControlsErrorCode::ERROR_CCTE_COMP);
}
ccte_err = tdata.mountPos.to(mnt_cp);
if (ccte_err) {
*_lastError = mcc_deduced_err(ccte_err, MccSimpleMovementControlsErrorCode::ERROR_CCTE_COMP);
}
auto dist = utils::distanceOnSphere(tag_cp.x(), tag_cp.y(), mnt_cp.x(), mnt_cp.y());
logger->logTrace(std::format(" target-to-mount distance: {} (dx = {}, dy = {})", logger->logTrace(std::format(" target-to-mount distance: {} (dx = {}, dy = {})",
MccAngleFancyString(std::get<2>(dist)), std::get<0>(dist), MccAngleFancyString(std::get<2>(dist)), std::get<0>(dist),
@@ -650,7 +666,7 @@ public:
// stop slewing and exit from the cycle? // stop slewing and exit from the cycle?
if (dist <= _currentParams.slewToleranceRadius) { if (std::get<2>(dist) <= _currentParams.slewToleranceRadius) {
if (tdata.hwState.movementState == HARDWARE_T::hardware_movement_state_t::HW_MOVE_STOPPED || if (tdata.hwState.movementState == HARDWARE_T::hardware_movement_state_t::HW_MOVE_STOPPED ||
tdata.hwState.movementState == HARDWARE_T::hardware_movement_state_t::HW_MOVE_GUIDING) { tdata.hwState.movementState == HARDWARE_T::hardware_movement_state_t::HW_MOVE_GUIDING) {
logger->logInfo("target-to-mount distance is lesser than slew acceptable radius - exit!"); logger->logInfo("target-to-mount distance is lesser than slew acceptable radius - exit!");
@@ -701,8 +717,18 @@ public:
return; return;
} }
auto dist = utils::distanceOnSphere(tdata.targetPos.x(), tdata.targetPos.y(), tdata.mountPos.x(), auto ccte_err = tdata.targetPos.to(tag_cp);
tdata.mountPos.y()); if (ccte_err) {
*_lastError = mcc_deduced_err(ccte_err, MccSimpleMovementControlsErrorCode::ERROR_CCTE_COMP);
return;
}
ccte_err = tdata.mountPos.to(mnt_cp);
if (ccte_err) {
*_lastError = mcc_deduced_err(ccte_err, MccSimpleMovementControlsErrorCode::ERROR_CCTE_COMP);
return;
}
auto dist = utils::distanceOnSphere(tag_cp.x(), tag_cp.y(), mnt_cp.x(), mnt_cp.y());
log_pos(tdata); log_pos(tdata);

View File

@@ -38,6 +38,7 @@
#include "mcc_concepts.h" #include "mcc_concepts.h"
#include "mcc_coordinate.h"
#include "mcc_netserver_endpoint.h" #include "mcc_netserver_endpoint.h"
#include "mcc_netserver_proto.h" #include "mcc_netserver_proto.h"
#include "mcc_traits.h" #include "mcc_traits.h"
@@ -90,6 +91,8 @@ struct MccGenericMountNetworkServerErrorCategory : std::error_category {
defaut: defaut:
return "unknown"; return "unknown";
}; };
return "unknown";
} }
static const MccGenericMountNetworkServerErrorCategory& get() static const MccGenericMountNetworkServerErrorCategory& get()
@@ -1088,7 +1091,7 @@ protected:
if (vc) { // set operation if (vc) { // set operation
auto m_err = mount_ptr->setPointingTarget(vc.value()); auto m_err = mount_ptr->setPointingTarget(vc.value());
if (m_err) { if (m_err) {
err = mcc_deduce_err(m_err, MccGenericMountNetworkServerErrorCode::ERROR_MOUNT_SET_TARGET); err = mcc_deduced_err(m_err, MccGenericMountNetworkServerErrorCode::ERROR_MOUNT_SET_TARGET);
} else { } else {
output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, input_msg.byteRepr()); output_msg.construct(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, input_msg.byteRepr());
} }
@@ -1182,10 +1185,10 @@ protected:
auto t_err = mount->telemetryData(&tdata); auto t_err = mount->telemetryData(&tdata);
if (t_err) { if (t_err) {
return mcc_deduce_err(t_err, MccGenericMountNetworkServerErrorCode::ERROR_MOUNT_GET_TELEMETRY); return mcc_deduced_err(t_err, MccGenericMountNetworkServerErrorCode::ERROR_MOUNT_GET_TELEMETRY);
} }
auto get_coords = [&]<mcc_coord_pair_c T>(T& cp) { auto get_coords = [&]<mcc_coord_pair_c T>(T& cp) -> std::error_code {
cp.setEpoch(tdata.mountPos.epoch()); cp.setEpoch(tdata.mountPos.epoch());
if (target) { if (target) {

View File

@@ -315,7 +315,7 @@ public:
} }
} }
error_t setTarget(mcc_skypoint_c auto const& sp) error_t setPointingTarget(mcc_skypoint_c auto const& sp)
{ {
_enteredTargetPos = sp; _enteredTargetPos = sp;
@@ -323,7 +323,7 @@ public:
} }
error_t getTarget(mcc_skypoint_c auto* sp) error_t getPointingTarget(mcc_skypoint_c auto* sp)
{ {
sp = _enteredTargetPos; sp = _enteredTargetPos;