...
This commit is contained in:
@@ -215,6 +215,7 @@ set(MCC_SRC
|
|||||||
include/mcc/mcc_pcm.h
|
include/mcc/mcc_pcm.h
|
||||||
include/mcc/mcc_telemetry.h
|
include/mcc/mcc_telemetry.h
|
||||||
include/mcc/mcc_movement_controls.h
|
include/mcc/mcc_movement_controls.h
|
||||||
|
include/mcc/mcc_generic_movecontrols.h
|
||||||
include/mcc/mcc_serialization_common.h
|
include/mcc/mcc_serialization_common.h
|
||||||
include/mcc/mcc_deserializer.h
|
include/mcc/mcc_deserializer.h
|
||||||
include/mcc/mcc_serializer.h
|
include/mcc/mcc_serializer.h
|
||||||
@@ -265,7 +266,10 @@ endif()
|
|||||||
if(USE_BSPLINE_PCM)
|
if(USE_BSPLINE_PCM)
|
||||||
target_compile_definitions(${PROJECT_NAME} INTERFACE USE_BSPLINE_PCM)
|
target_compile_definitions(${PROJECT_NAME} INTERFACE USE_BSPLINE_PCM)
|
||||||
target_link_libraries(${PROJECT_NAME} INTERFACE fitpack)
|
target_link_libraries(${PROJECT_NAME} INTERFACE fitpack)
|
||||||
target_link_directories(${PROJECT_NAME} INTERFACE "$<BUILD_INTERFACE:${CMAKE_BINARY_DIR}/fitpack>")
|
target_link_directories(
|
||||||
|
${PROJECT_NAME}
|
||||||
|
INTERFACE "$<BUILD_INTERFACE:${CMAKE_BINARY_DIR}/fitpack>"
|
||||||
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(USE_ASIO)
|
if(USE_ASIO)
|
||||||
@@ -275,7 +279,10 @@ endif()
|
|||||||
if(USE_SPDLOG)
|
if(USE_SPDLOG)
|
||||||
target_link_libraries(${PROJECT_NAME} INTERFACE spdlog::spdlog_header_only)
|
target_link_libraries(${PROJECT_NAME} INTERFACE spdlog::spdlog_header_only)
|
||||||
# target_compile_definitions(${PROJECT_NAME} INTERFACE SPDLOG_USE_STD_FORMAT=1 SPDLOG_FMT_EXTERNAL=0)
|
# target_compile_definitions(${PROJECT_NAME} INTERFACE SPDLOG_USE_STD_FORMAT=1 SPDLOG_FMT_EXTERNAL=0)
|
||||||
target_compile_definitions(${PROJECT_NAME} INTERFACE SPDLOG_USE_STD_FORMAT=1)
|
target_compile_definitions(
|
||||||
|
${PROJECT_NAME}
|
||||||
|
INTERFACE SPDLOG_USE_STD_FORMAT=1
|
||||||
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(BUILD_TESTS)
|
if(BUILD_TESTS)
|
||||||
|
|||||||
@@ -499,21 +499,55 @@ struct mcc_skypoint_interface_t {
|
|||||||
{
|
{
|
||||||
return std::forward<SelfT>(self).EO(eo);
|
return std::forward<SelfT>(self).EO(eo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// template <std::derived_from<mcc_skypoint_interface_t> SelfT>
|
||||||
|
// typename std::remove_cvref_t<SelfT>::dist_result_t distance(this SelfT&& self, auto const& sp)
|
||||||
|
// {
|
||||||
|
// return std::forward<SelfT>(self).distance(sp);
|
||||||
|
// }
|
||||||
|
// template <std::derived_from<mcc_skypoint_interface_t> SelfT>
|
||||||
|
// SelfT& operator+=(this SelfT& self, mcc_coord_pair_c auto const& dxy)
|
||||||
|
// {
|
||||||
|
// return self.operator+=(dxy);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// template <std::derived_from<mcc_skypoint_interface_t> SelfT>
|
||||||
|
// SelfT& operator-=(this SelfT& self, mcc_coord_pair_c auto const& dxy)
|
||||||
|
// {
|
||||||
|
// return self.operator-=(dxy);
|
||||||
|
// }
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
concept mcc_skypoint_c = std::derived_from<T, mcc_skypoint_interface_t> && requires(const T t_const) {
|
concept mcc_skypoint_c =
|
||||||
{ t_const.epoch() } -> mcc_coord_epoch_c;
|
std::derived_from<T, mcc_skypoint_interface_t> && requires(const T t_const, const T t_other_const, T t) {
|
||||||
|
{ t_const.epoch() } -> mcc_coord_epoch_c;
|
||||||
|
|
||||||
// currently stored coordinates pair kind
|
// 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
|
// currently stored co-longitude coordinate
|
||||||
{ t_const.co_lon() } -> std::convertible_to<double>;
|
{ t_const.co_lon() } -> std::convertible_to<double>;
|
||||||
|
|
||||||
// currently stored co-latitude coordinate
|
// currently stored co-latitude coordinate
|
||||||
{ t_const.co_lat() } -> std::convertible_to<double>;
|
{ t_const.co_lat() } -> std::convertible_to<double>;
|
||||||
};
|
|
||||||
|
requires requires(typename T::dist_result_t res) {
|
||||||
|
requires mcc_angle_c<decltype(res.dist)>; // distance on sphere
|
||||||
|
requires mcc_angle_c<decltype(res.dx)>; // defference on co-longitude coordinates
|
||||||
|
requires mcc_angle_c<decltype(res.dy)>; // defference on co-latitude coordinates
|
||||||
|
requires mcc_angle_c<decltype(res.x2)>; // co-longitude coordinates of target sky point (in the same
|
||||||
|
// coordinate system as 'this')
|
||||||
|
requires mcc_angle_c<decltype(res.y2)>; // co-latitude coordinates of target sky point (in the same
|
||||||
|
// coordinate system as 'this')
|
||||||
|
};
|
||||||
|
|
||||||
|
// distance on sphere between two sky points
|
||||||
|
{ t_const.distance(std::declval<const T&>()) } -> std::same_as<typename T::dist_result_t>;
|
||||||
|
|
||||||
|
// { t_const - t_other_const } -> mcc_coord_pair_c;
|
||||||
|
// { t_const + t_other_const } -> mcc_coord_pair_c;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -380,6 +380,14 @@ public:
|
|||||||
|
|
||||||
using error_t = typename CCTE_T::error_t;
|
using error_t = typename CCTE_T::error_t;
|
||||||
|
|
||||||
|
struct dist_result_t {
|
||||||
|
MccAngle dist{};
|
||||||
|
MccAngle dx{};
|
||||||
|
MccAngle dy{};
|
||||||
|
MccAngle x2{};
|
||||||
|
MccAngle y2{};
|
||||||
|
};
|
||||||
|
|
||||||
MccGenericSkyPoint() {}
|
MccGenericSkyPoint() {}
|
||||||
|
|
||||||
template <mcc_coord_pair_c PT>
|
template <mcc_coord_pair_c PT>
|
||||||
@@ -685,11 +693,34 @@ public:
|
|||||||
return cctEngine.equationOrigins(_epoch, eo);
|
return cctEngine.equationOrigins(_epoch, eo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
dist_result_t distance(MccGenericSkyPoint const& sp) const
|
||||||
|
// dist_result_t distance(mcc_skypoint_c auto const& sp)
|
||||||
|
{
|
||||||
|
double x, y;
|
||||||
|
|
||||||
|
if (_pairKind == sp.pairKind() && utils::isEqual(_epoch.MJD(), sp.epoch().MJD())) {
|
||||||
|
x = sp.co_lon();
|
||||||
|
y = sp.co_lat();
|
||||||
|
} else { // convert to the same coordinates kind
|
||||||
|
MccGenericSkyPoint p{sp};
|
||||||
|
p.to(_pairKind, _epoch);
|
||||||
|
|
||||||
|
x = p.co_lon();
|
||||||
|
y = p.co_lat();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto d = utils::distanceOnSphere(_x, _y, x, y);
|
||||||
|
|
||||||
|
return {.dist = std::get<2>(d), .dx = std::get<0>(d), .dx = std::get<1>(d), .x2 = x, .y2 = y};
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
double _x{0.0}, _y{0.0};
|
double _x{0.0}, _y{0.0};
|
||||||
MccCoordPairKind _pairKind{MccCoordPairKind::COORDS_KIND_RADEC_ICRS};
|
MccCoordPairKind _pairKind{MccCoordPairKind::COORDS_KIND_RADEC_ICRS};
|
||||||
MccCelestialCoordEpoch _epoch{}; // J2000.0
|
MccCelestialCoordEpoch _epoch{}; // J2000.0
|
||||||
|
|
||||||
|
|
||||||
template <mcc_skypoint_c T>
|
template <mcc_skypoint_c T>
|
||||||
void fromOtherSkyPoint(T&& other)
|
void fromOtherSkyPoint(T&& other)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,5 +1,21 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
/****************************************************************************************
|
||||||
|
* *
|
||||||
|
* MOUNT CONTROL COMPONENTS LIBRARY *
|
||||||
|
* *
|
||||||
|
* *
|
||||||
|
* GENERIC IMPLEMENTATION OF MOUNT MOVEMENT CONTROLS *
|
||||||
|
* *
|
||||||
|
****************************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
|
#include <fstream>
|
||||||
|
#include <future>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
#include "mcc_error.h"
|
#include "mcc_error.h"
|
||||||
|
|
||||||
|
|
||||||
@@ -26,7 +42,10 @@ namespace mcc::impl
|
|||||||
|
|
||||||
// error category
|
// error category
|
||||||
struct MccGenericMovementControlsErrorCategory : std::error_category {
|
struct MccGenericMovementControlsErrorCategory : std::error_category {
|
||||||
const char* name() const noexcept { return "MCC-GENERIC-MOVECONTRL"; }
|
const char* name() const noexcept
|
||||||
|
{
|
||||||
|
return "MCC-GENERIC-MOVECONTRL";
|
||||||
|
}
|
||||||
|
|
||||||
std::string message(int ec) const
|
std::string message(int ec) const
|
||||||
{
|
{
|
||||||
@@ -44,12 +63,12 @@ struct MccGenericMovementControlsErrorCategory : std::error_category {
|
|||||||
default:
|
default:
|
||||||
return "unknown";
|
return "unknown";
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static const MccGenericMovementControlsErrorCategory& get()
|
static const MccGenericMovementControlsErrorCategory& get()
|
||||||
{
|
{
|
||||||
static const MccGenericMovementControlsErrorCategory constInst;
|
static const MccGenericMovementControlsErrorCategory constInst;
|
||||||
return constInst;
|
return constInst;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -89,28 +108,280 @@ struct MccGenericMovementControlsParams {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
template <std::default_constructible PARAMS_T>
|
/* UTILITY CLASS TO HOLD AND SAVE MOUNT MOVING TRAJECTORY */
|
||||||
|
|
||||||
|
struct MccMovementPathFile {
|
||||||
|
static constexpr std::string_view commentSeq{"# "};
|
||||||
|
static constexpr std::string_view lineDelim{"\n"};
|
||||||
|
|
||||||
|
void setCommentSeq(traits::mcc_input_char_range auto const& s)
|
||||||
|
{
|
||||||
|
_commentSeq.clear();
|
||||||
|
std::ranges::copy(s, std::back_inserter(_commentSeq));
|
||||||
|
}
|
||||||
|
|
||||||
|
void setLineDelim(traits::mcc_input_char_range auto const& s)
|
||||||
|
{
|
||||||
|
_lineDelim.clear();
|
||||||
|
std::ranges::copy(s, std::back_inserter(_lineDelim));
|
||||||
|
}
|
||||||
|
|
||||||
|
// add comment string/strings
|
||||||
|
template <traits::mcc_input_char_range RT, traits::mcc_input_char_range... RTs>
|
||||||
|
void addComment(RT const& r, RTs const&... rs)
|
||||||
|
{
|
||||||
|
std::ranges::copy(_commentSeq, std::back_inserter(_buffer));
|
||||||
|
std::ranges::copy(r, std::back_inserter(_buffer));
|
||||||
|
std::ranges::copy(lineDelim, std::back_inserter(_buffer));
|
||||||
|
|
||||||
|
if constexpr (sizeof...(RTs)) {
|
||||||
|
addComment(rs...);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// general purpose method
|
||||||
|
template <std::formattable<char>... ArgTs>
|
||||||
|
void addToPath(std::format_string<ArgTs...> fmt, ArgTs&&... args)
|
||||||
|
{
|
||||||
|
std::format_to(std::back_inserter(_buffer), fmt, std::forward<ArgTs>(args)...);
|
||||||
|
std::ranges::copy(lineDelim, std::back_inserter(_buffer));
|
||||||
|
}
|
||||||
|
|
||||||
|
// general purpose method
|
||||||
|
template <std::formattable<char>... ArgTs>
|
||||||
|
void addToPath(std::string_view fmt, ArgTs&&... args)
|
||||||
|
{
|
||||||
|
std::vformat_to(std::back_inserter(_buffer), fmt, std::make_format_args(std::forward<ArgTs>(args)...));
|
||||||
|
std::ranges::copy(lineDelim, std::back_inserter(_buffer));
|
||||||
|
}
|
||||||
|
|
||||||
|
// default-implemented method
|
||||||
|
void addToPath(mcc_telemetry_data_c auto const& tdata)
|
||||||
|
{
|
||||||
|
// UNIX-time millisecs, mount X, mount Y, target X, target Y, dX(mount-target), dY(mount-target), dist, state
|
||||||
|
auto dist = tdata.mountPos.distance(tdata.targetPos);
|
||||||
|
|
||||||
|
using d_t = std::chrono::milliseconds;
|
||||||
|
|
||||||
|
auto tp = std::chrono::duration_cast<d_t>(tdata.mountPos.epoch().UTC().time_since_epoch());
|
||||||
|
|
||||||
|
const std::string_view d_fmt = "{:f14.8}";
|
||||||
|
const auto v = std::views::repeat(d_fmt, 7) | std::views::join_with(' ');
|
||||||
|
std::string fmt = "{} " + std::string(v.begin(), v.end()) + " {}";
|
||||||
|
|
||||||
|
addToPath(fmt, tp.count(), (double)tdata.mountPos.co_lon() * MCC_RADS_TO_DEGRESS,
|
||||||
|
(double)tdata.mountPos.co_lat() * MCC_RADS_TO_DEGRESS, (double)dist.x2 * MCC_RADS_TO_DEGRESS,
|
||||||
|
(double)dist.y2 * MCC_RADS_TO_DEGRESS, (double)dist.dx * MCC_RADS_TO_DEGRESS,
|
||||||
|
(double)dist.dy * MCC_RADS_TO_DEGRESS, (double)dist.dist * MCC_RADS_TO_DEGRESS,
|
||||||
|
(int)tdata.hwState.movementState);
|
||||||
|
}
|
||||||
|
|
||||||
|
void clearPath()
|
||||||
|
{
|
||||||
|
_buffer.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool saveToFile(std::string const& filename, std::ios_base::openmode mode = std::ios_base::trunc)
|
||||||
|
{
|
||||||
|
std::ofstream fst(filename, mode);
|
||||||
|
|
||||||
|
if (fst.is_open()) {
|
||||||
|
fst << _buffer;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::string _buffer{};
|
||||||
|
|
||||||
|
std::string _commentSeq{commentSeq};
|
||||||
|
std::string _lineDelim{lineDelim};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
enum class MccGenericMovementControlsPolicy : int { POLICY_ASYNC, POLICY_BLOCKING };
|
||||||
|
|
||||||
|
template <std::default_initializable PARAMS_T,
|
||||||
|
MccGenericMovementControlsPolicy EXEC_POLICY = MccGenericMovementControlsPolicy::POLICY_ASYNC>
|
||||||
class MccGenericMovementControls
|
class MccGenericMovementControls
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
static constexpr MccGenericMovementControlsPolicy executePolicy = EXEC_POLICY;
|
||||||
|
|
||||||
|
static constexpr std::chrono::seconds defaultWaitTimeout{3};
|
||||||
|
|
||||||
typedef MccError error_t;
|
typedef MccError error_t;
|
||||||
|
|
||||||
typedef PARAMS_T movement_params_t;
|
typedef PARAMS_T movement_params_t;
|
||||||
|
|
||||||
error_t slewToTarget(bool slew_and_stop) {}
|
~MccGenericMovementControls()
|
||||||
|
{
|
||||||
|
stopMount();
|
||||||
|
|
||||||
error_t trackTarget() {}
|
if constexpr (executePolicy == MccGenericMovementControlsPolicy::POLICY_ASYNC) {
|
||||||
|
if (_slewFuncFuture.valid()) {
|
||||||
|
auto status = _slewFuncFuture.wait_for(_waitTimeout->load());
|
||||||
|
}
|
||||||
|
|
||||||
error_t stopMount() {}
|
if (_trackFuncFuture.valid()) {
|
||||||
|
auto status = _trackFuncFuture.wait_for(_waitTimeout->load());
|
||||||
|
}
|
||||||
|
|
||||||
error_t setMovementParams(movement_params_t const& pars) { _currentParams->store(pars); }
|
if (_stopFuncFuture.valid()) {
|
||||||
|
auto status = _stopFuncFuture.wait_for(_waitTimeout->load());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
movement_params_t getMovementParams() const { return _currentParams->load(); }
|
error_t slewToTarget(bool slew_and_stop)
|
||||||
|
{
|
||||||
|
_stopMovementRequest = false;
|
||||||
|
|
||||||
|
if constexpr (executePolicy == MccGenericMovementControlsPolicy::POLICY_ASYNC) {
|
||||||
|
_slewFuncFuture = std::async(std::launch::async, _slewFunc, slew_and_stop);
|
||||||
|
|
||||||
|
return MccGenericMovementControlsErrorCode::ERROR_OK;
|
||||||
|
} else if constexpr (executePolicy == MccGenericMovementControlsPolicy::POLICY_BLOCKING) {
|
||||||
|
return _slewFunc(slew_and_stop);
|
||||||
|
} else {
|
||||||
|
static_assert(false, "UNKNOWN EXECUTION POLICY!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
error_t trackTarget()
|
||||||
|
{
|
||||||
|
_stopMovementRequest = false;
|
||||||
|
|
||||||
|
if constexpr (executePolicy == MccGenericMovementControlsPolicy::POLICY_ASYNC) {
|
||||||
|
_trackFuncFuture = std::async(std::launch::async, _trackFunc);
|
||||||
|
|
||||||
|
return MccGenericMovementControlsErrorCode::ERROR_OK;
|
||||||
|
} else if constexpr (executePolicy == MccGenericMovementControlsPolicy::POLICY_BLOCKING) {
|
||||||
|
return _trackFunc();
|
||||||
|
} else {
|
||||||
|
static_assert(false, "UNKNOWN EXECUTION POLICY!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
error_t stopMount()
|
||||||
|
{
|
||||||
|
_stopMovementRequest = true;
|
||||||
|
|
||||||
|
if constexpr (executePolicy == MccGenericMovementControlsPolicy::POLICY_ASYNC) {
|
||||||
|
_stopFuncFuture = std::async(std::launch::async, _stopFunc);
|
||||||
|
|
||||||
|
return MccGenericMovementControlsErrorCode::ERROR_OK;
|
||||||
|
} else if constexpr (executePolicy == MccGenericMovementControlsPolicy::POLICY_BLOCKING) {
|
||||||
|
return _stopFunc();
|
||||||
|
} else {
|
||||||
|
static_assert(false, "UNKNOWN EXECUTION POLICY!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
error_t setMovementParams(movement_params_t const& pars)
|
||||||
|
{
|
||||||
|
_currentParams->store(pars);
|
||||||
|
|
||||||
|
return MccGenericMovementControlsErrorCode::ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
movement_params_t getMovementParams() const
|
||||||
|
{
|
||||||
|
return _currentParams->load();
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
MccGenericMovementControls() = default;
|
template <std::invocable<bool> SLEW_FUNC_T, std::invocable<> TRACK_FUNC_T, std::invocable<> STOP_FUNC_T>
|
||||||
|
MccGenericMovementControls(SLEW_FUNC_T&& slew_func, TRACK_FUNC_T&& track_func, STOP_FUNC_T&& stop_func)
|
||||||
|
: _slewFunc(std::forward<SLEW_FUNC_T>(slew_func)),
|
||||||
|
_trackFunc(std::forward<TRACK_FUNC_T>(track_func)),
|
||||||
|
_stopFunc(std::forward<STOP_FUNC_T>(stop_func)){};
|
||||||
|
|
||||||
std::unique_ptr<std::atomic<PARAMS_T>> _currentParams{new std::atomic<PARAMS_T>{}};
|
std::unique_ptr<std::atomic<PARAMS_T>> _currentParams{new std::atomic<PARAMS_T>{}};
|
||||||
|
|
||||||
|
std::atomic_bool _stopMovementRequest{false};
|
||||||
|
|
||||||
|
std::function<error_t(bool)> _slewFunc{};
|
||||||
|
std::function<error_t()> _trackFunc;
|
||||||
|
std::function<error_t()> _stopFunc;
|
||||||
|
|
||||||
|
std::conditional_t<executePolicy == MccGenericMovementControlsPolicy::POLICY_ASYNC,
|
||||||
|
std::future<error_t>,
|
||||||
|
std::nullptr_t>
|
||||||
|
_slewFuncFuture{};
|
||||||
|
|
||||||
|
std::conditional_t<executePolicy == MccGenericMovementControlsPolicy::POLICY_ASYNC,
|
||||||
|
std::future<error_t>,
|
||||||
|
std::nullptr_t>
|
||||||
|
_trackFuncFuture{};
|
||||||
|
|
||||||
|
std::conditional_t<executePolicy == MccGenericMovementControlsPolicy::POLICY_ASYNC,
|
||||||
|
std::future<error_t>,
|
||||||
|
std::nullptr_t>
|
||||||
|
_stopFuncFuture{};
|
||||||
|
|
||||||
|
|
||||||
|
std::unique_ptr<std::atomic<std::chrono::nanoseconds>> _waitTimeout{
|
||||||
|
new std::atomic<std::chrono::nanoseconds>{defaultWaitTimeout}};
|
||||||
|
|
||||||
|
|
||||||
|
// utility methods
|
||||||
|
|
||||||
|
// the method calculates the change in coordinates of a point over a given time given the current speed and braking
|
||||||
|
// acceleration. a position after given 'time' interval is returned
|
||||||
|
auto coordsAfterTime(mcc_coord_pair_c auto& cp,
|
||||||
|
mcc_coord_pair_c auto const& speedXY, // in radians per seconds
|
||||||
|
mcc_coord_pair_c auto const& braking_accelXY, // in radians per seconds in square
|
||||||
|
traits::mcc_time_duration_c auto const& time,
|
||||||
|
mcc_coord_pair_c auto* dxy = nullptr)
|
||||||
|
{
|
||||||
|
// time to stop mount with given current speed and constant braking acceleration
|
||||||
|
double tx_stop = std::abs(speedXY.x()) / braking_accelXY.x();
|
||||||
|
double ty_stop = std::abs(speedXY.y()) / braking_accelXY.y();
|
||||||
|
|
||||||
|
using secs_t = std::chrono::duration<double>; // seconds as double
|
||||||
|
|
||||||
|
double tx = std::chrono::duration_cast<secs_t>(time).count();
|
||||||
|
double ty = std::chrono::duration_cast<secs_t>(time).count();
|
||||||
|
|
||||||
|
if (std::isfinite(tx_stop) && (tx > tx_stop)) {
|
||||||
|
tx = tx_stop;
|
||||||
|
}
|
||||||
|
if (std::isfinite(ty_stop) && (ty > ty_stop)) {
|
||||||
|
ty = ty_stop;
|
||||||
|
}
|
||||||
|
|
||||||
|
// the distance:
|
||||||
|
// here, one must take into account the sign of the speed!!!
|
||||||
|
double dx = speedXY.x() * tx - std::copysign(braking_accelXY.x(), speedXY.x()) * tx * tx / 2.0;
|
||||||
|
double dy = speedXY.y() * ty - std::copysign(braking_accelXY.y(), speedXY.y()) * ty * ty / 2.0;
|
||||||
|
|
||||||
|
std::remove_cvref_t<decltype(cp)> cp_res{};
|
||||||
|
cp_res.setEpoch(cp.epoch().UTC() + time);
|
||||||
|
|
||||||
|
cp_res.setX((double)cp.x() + dx);
|
||||||
|
cp_res.setY((double)cp.y() + dy);
|
||||||
|
|
||||||
|
if (dxy) {
|
||||||
|
dxy->setX(dx);
|
||||||
|
dxy->setY(dy);
|
||||||
|
dxy->setEpoch(cp_res.epoch());
|
||||||
|
}
|
||||||
|
|
||||||
|
return cp_res;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template <std::default_initializable PARAMS_T>
|
||||||
|
using MccGenericBlockingMovementControls =
|
||||||
|
MccGenericMovementControls<PARAMS_T, MccGenericMovementControlsPolicy::POLICY_BLOCKING>;
|
||||||
|
|
||||||
|
template <std::default_initializable PARAMS_T>
|
||||||
|
using MccGenericAsyncMovementControls =
|
||||||
|
MccGenericMovementControls<PARAMS_T, MccGenericMovementControlsPolicy::POLICY_ASYNC>;
|
||||||
|
|
||||||
} // namespace mcc::impl
|
} // namespace mcc::impl
|
||||||
|
|||||||
Reference in New Issue
Block a user