552 lines
23 KiB
C++
552 lines
23 KiB
C++
#pragma once
|
|
|
|
/* MOUNT CONTROL COMPONENTS LIBRARY */
|
|
|
|
|
|
/* SIMPLE Tracking MODEL IMPLEMENTATION */
|
|
|
|
|
|
#include <fstream>
|
|
|
|
#include "mcc_defaults.h"
|
|
#include "mcc_moving_model_common.h"
|
|
|
|
namespace mcc
|
|
{
|
|
|
|
enum class MccSimpleTrackingModelErrorCode : int {
|
|
ERROR_OK,
|
|
ERROR_CCTE,
|
|
ERROR_HW_GETSTATE,
|
|
ERROR_HW_SETSTATE,
|
|
ERROR_PCM_COMP,
|
|
ERROR_GET_TELEMETRY,
|
|
ERROR_DIST_TELEMETRY,
|
|
ERROR_PZONE_CONTAINER_COMP,
|
|
ERROR_NEAR_PZONE,
|
|
ERROR_IN_PZONE,
|
|
ERROR_ALREADY_TRACK,
|
|
ERROR_ALREADY_STOPPED,
|
|
ERROR_STOPPED
|
|
};
|
|
|
|
} // namespace mcc
|
|
|
|
|
|
namespace std
|
|
{
|
|
|
|
template <>
|
|
class is_error_code_enum<mcc::MccSimpleTrackingModelErrorCode> : public true_type
|
|
{
|
|
};
|
|
|
|
} // namespace std
|
|
|
|
|
|
|
|
namespace mcc
|
|
{
|
|
|
|
|
|
// error category
|
|
struct MccSimpleTrackingModelCategory : public std::error_category {
|
|
MccSimpleTrackingModelCategory() : std::error_category() {}
|
|
|
|
const char* name() const noexcept
|
|
{
|
|
return "SIMPLE-TRACKING-MODEL";
|
|
}
|
|
|
|
std::string message(int ec) const
|
|
{
|
|
MccSimpleTrackingModelErrorCode err = static_cast<MccSimpleTrackingModelErrorCode>(ec);
|
|
|
|
switch (err) {
|
|
case MccSimpleTrackingModelErrorCode::ERROR_OK:
|
|
return "OK";
|
|
case MccSimpleTrackingModelErrorCode::ERROR_CCTE:
|
|
return "coordinate transformation error";
|
|
case MccSimpleTrackingModelErrorCode::ERROR_HW_GETSTATE:
|
|
return "cannot get hardware state";
|
|
case MccSimpleTrackingModelErrorCode::ERROR_HW_SETSTATE:
|
|
return "cannot set hardware state";
|
|
case MccSimpleTrackingModelErrorCode::ERROR_PCM_COMP:
|
|
return "PCM computation error";
|
|
case MccSimpleTrackingModelErrorCode::ERROR_GET_TELEMETRY:
|
|
return "cannot get telemetry";
|
|
case MccSimpleTrackingModelErrorCode::ERROR_DIST_TELEMETRY:
|
|
return "cannot get target-to-mount-position distance";
|
|
case MccSimpleTrackingModelErrorCode::ERROR_PZONE_CONTAINER_COMP:
|
|
return "pzone container computation error";
|
|
case MccSimpleTrackingModelErrorCode::ERROR_NEAR_PZONE:
|
|
return "near prohibited zone";
|
|
case MccSimpleTrackingModelErrorCode::ERROR_IN_PZONE:
|
|
return "in prohibited zone";
|
|
case MccSimpleTrackingModelErrorCode::ERROR_ALREADY_TRACK:
|
|
return "already tracking";
|
|
case MccSimpleTrackingModelErrorCode::ERROR_ALREADY_STOPPED:
|
|
return "tracking is already stopped";
|
|
default:
|
|
return "UNKNOWN";
|
|
}
|
|
}
|
|
|
|
static const MccSimpleTrackingModelCategory& get()
|
|
{
|
|
static const MccSimpleTrackingModelCategory constInst;
|
|
return constInst;
|
|
}
|
|
};
|
|
|
|
|
|
inline std::error_code make_error_code(MccSimpleTrackingModelErrorCode ec)
|
|
{
|
|
return std::error_code(static_cast<int>(ec), MccSimpleTrackingModelCategory::get());
|
|
}
|
|
|
|
|
|
|
|
class MccSimpleTrackingModel
|
|
{
|
|
public:
|
|
typedef std::error_code error_t;
|
|
|
|
typedef MccSimpleMovingModelParams tracking_params_t;
|
|
|
|
|
|
template <mcc_all_controls_c CONTROLS_T, mcc_logger_c LoggerT = MccNullLogger>
|
|
MccSimpleTrackingModel(CONTROLS_T* controls, LoggerT logger)
|
|
: _stopTracking(new std::atomic_bool()),
|
|
_currentParamsMutex(new std::mutex()),
|
|
_lastError(MccSimpleTrackingModelErrorCode::ERROR_OK)
|
|
{
|
|
std::ostringstream os;
|
|
os << std::this_thread::get_id();
|
|
|
|
logger.logDebug(std::format("Create MccSimpleTrackingModel class instance (thread: {})", os.str()));
|
|
|
|
*_stopTracking = true;
|
|
|
|
_trackingFunc = [logger = std::move(logger), controls, this]() mutable -> error_t {
|
|
typename CONTROLS_T::hardware_state_t hw_state;
|
|
|
|
MccTelemetryData tdata;
|
|
MccEqtHrzCoords intsc_coords;
|
|
MccCelestialPoint target_in_future_pt;
|
|
|
|
bool store_path = false;
|
|
std::ofstream fst;
|
|
using path_tp_t = std::chrono::duration<double>; // seconds represented as double
|
|
|
|
if constexpr (mccIsEquatorialMount(CONTROLS_T::mountType)) {
|
|
target_in_future_pt.pair_kind = MccCoordPairKind::COORDS_KIND_HADEC_APP;
|
|
} else if constexpr (mccIsAltAzMount(CONTROLS_T::mountType)) {
|
|
target_in_future_pt.pair_kind = MccCoordPairKind::COORDS_KIND_AZZD;
|
|
} else {
|
|
static_assert(false, "UNKNOWN MOUNT TYPE!");
|
|
}
|
|
|
|
// double dist, dx, dy;
|
|
|
|
logger.logInfo("Start tracking:");
|
|
logger.logInfo(" timesift: {} millisecs", _currentParams.timeShiftToTargetPoint.count());
|
|
logger.logInfo(" min time to pzone: {} secs", _currentParams.minTimeToPZone.count());
|
|
|
|
|
|
auto t_err = controls->telemetryData(&tdata);
|
|
if (t_err) {
|
|
*_stopTracking = true;
|
|
return mcc_deduce_error_code(t_err, MccSimpleTrackingModelErrorCode::ERROR_GET_TELEMETRY);
|
|
}
|
|
|
|
auto start_point = tdata.time_point; // needed for trajectory file
|
|
|
|
bool in_zone;
|
|
auto pz_err = controls->inPZone(tdata, &in_zone);
|
|
if (pz_err) {
|
|
return mcc_deduce_error_code(pz_err, MccSimpleTrackingModelErrorCode::ERROR_PZONE_CONTAINER_COMP);
|
|
}
|
|
|
|
if (in_zone) {
|
|
logger.logError("mount current coordinates are in prohibited zone:");
|
|
logger.logError(std::format(
|
|
" RA-APP, DEC-APP, HA, LST: {}, {}, {}, {}", mcc::MccAngle{tdata.RA_APP}.sexagesimal(true),
|
|
mcc::MccAngle{tdata.DEC_APP}.sexagesimal(), mcc::MccAngle{tdata.HA}.sexagesimal(true),
|
|
mcc::MccAngle{tdata.LST}.sexagesimal(true)));
|
|
logger.logError(std::format(" AZ, ZD, ALT: {}, {}, {}", mcc::MccAngle{tdata.target.AZ}.sexagesimal(),
|
|
mcc::MccAngle{tdata.ZD}.sexagesimal(),
|
|
mcc::MccAngle{tdata.ALT}.sexagesimal()));
|
|
|
|
logger.logError(std::format(" hardware X, Y: {}, {}", mcc::MccAngle{tdata.X}.sexagesimal(),
|
|
mcc::MccAngle{tdata.Y}.sexagesimal()));
|
|
|
|
return MccSimpleTrackingModelErrorCode::ERROR_IN_PZONE;
|
|
}
|
|
|
|
|
|
bool no_intersects = false;
|
|
|
|
// function to update the closest prohibited zone intersect point
|
|
auto update_pzones_ipoint = [controls, &tdata, &intsc_coords, &no_intersects, &hw_state,
|
|
this]() -> error_t {
|
|
// compute intersection points with the prohibited zones
|
|
auto pz_err = mcc_find_closest_pzone(controls, tdata, &intsc_coords);
|
|
if (pz_err) {
|
|
return mcc_deduce_error_code(pz_err, MccSimpleTrackingModelErrorCode::ERROR_PZONE_CONTAINER_COMP);
|
|
}
|
|
|
|
if constexpr (mccIsEquatorialMount(CONTROLS_T::mountType)) {
|
|
if (std::isfinite(intsc_coords.HA)) {
|
|
intsc_coords.X = intsc_coords.HA;
|
|
intsc_coords.Y = intsc_coords.DEC_APP;
|
|
} else {
|
|
no_intersects = true;
|
|
// intsc_coords.X = tdata.HA + 710.0_mins; // 12h - 10min
|
|
// intsc_coords.Y = tdata.DEC_APP;
|
|
}
|
|
} else if constexpr (mccIsAltAzMount(CONTROLS_T::mountType)) {
|
|
if (std::isfinite(intsc_coords.AZ)) {
|
|
intsc_coords.X = intsc_coords.AZ;
|
|
intsc_coords.Y = intsc_coords.ZD;
|
|
} else {
|
|
no_intersects = true;
|
|
}
|
|
} else {
|
|
static_assert(false, "UNKNOWN MOUNT TYPE!");
|
|
}
|
|
|
|
return MccSimpleTrackingModelErrorCode::ERROR_OK;
|
|
};
|
|
|
|
|
|
auto target_point = [&, this](MccCelestialPoint* point) -> std::error_code {
|
|
double dha =
|
|
std::chrono::duration<double>(_currentParams.timeShiftToTargetPoint * mcc_sideral_to_UT1_ratio)
|
|
.count(); // sideral hour seconds
|
|
dha *= std::numbers::pi / 43200.0; // radians
|
|
|
|
auto target_ha = tdata.target.HA + dha;
|
|
|
|
// auto dt = std::chrono::duration<double>{tdata.HA} +
|
|
// _currentParams.timeShiftToTargetPoint * mcc_sideral_to_UT1_ratio; // hour seconds
|
|
|
|
auto tp_dt = std::chrono::duration_cast<typename decltype(tdata.time_point)::duration>(
|
|
_currentParams.timeShiftToTargetPoint);
|
|
|
|
// point in +time_dist future
|
|
MccCelestialPoint pt{.pair_kind = MccCoordPairKind::COORDS_KIND_HADEC_APP,
|
|
.X = MccAngle(target_ha).normalize<MccAngle::NORM_KIND_180_180>(),
|
|
.Y = tdata.target.DEC_APP};
|
|
mcc_tp2tp(tdata.time_point + tp_dt, pt.time_point);
|
|
|
|
point->time_point = pt.time_point;
|
|
|
|
// check for prohibited zone
|
|
if (std::isfinite(intsc_coords.HA)) {
|
|
bool through_pzone =
|
|
(intsc_coords.HA - pt.X) <= 0; // must be <= 0 if point in future will be in the zone
|
|
through_pzone &=
|
|
(intsc_coords.HA - tdata.HA) > 0; // must be > 0 if point in future was out of the zone
|
|
|
|
if (through_pzone) {
|
|
pt.X = intsc_coords.HA;
|
|
}
|
|
}
|
|
|
|
auto ret = controls->transformCoordinates(std::move(pt), point);
|
|
if (ret) {
|
|
return mcc_deduce_error_code(ret, MccSimpleTrackingModelErrorCode::ERROR_CCTE);
|
|
} else {
|
|
MccPCMResult pcm_inv_res;
|
|
|
|
// endpoint of the mount moving
|
|
auto pcm_err = controls->computeInversePCM(target_in_future_pt, &pcm_inv_res, &hw_state);
|
|
if (pcm_err) {
|
|
return mcc_deduce_error_code(pcm_err, MccSimpleTrackingModelErrorCode::ERROR_PCM_COMP);
|
|
}
|
|
|
|
mcc_tp2tp(tdata.time_point + tp_dt, hw_state.time_point);
|
|
}
|
|
|
|
return MccSimpleTrackingModelErrorCode::ERROR_OK;
|
|
};
|
|
|
|
|
|
pz_err = update_pzones_ipoint();
|
|
if (pz_err) {
|
|
*_stopTracking = true;
|
|
return mcc_deduce_error_code(pz_err, MccSimpleTrackingModelErrorCode::ERROR_PZONE_CONTAINER_COMP);
|
|
}
|
|
|
|
hw_state.moving_state = CONTROLS_T::hardware_moving_state_t::HW_MOVE_TRACKING;
|
|
|
|
{
|
|
std::lock_guard lock{*_currentParamsMutex};
|
|
|
|
mcc_copy_eqt_hrz_coord(tdata, &tdata.target);
|
|
|
|
auto ccte_err = target_point(&target_in_future_pt);
|
|
if (ccte_err) {
|
|
*_stopTracking = true;
|
|
return mcc_deduce_error_code(ccte_err, MccSimpleTrackingModelErrorCode::ERROR_CCTE);
|
|
}
|
|
|
|
if constexpr (mccIsEquatorialMount(CONTROLS_T::mountType)) {
|
|
hw_state.speedX = _currentParams.trackSpeedX;
|
|
hw_state.speedY = _currentParams.trackSpeedY;
|
|
}
|
|
|
|
logger.logTrace("The updated target point:");
|
|
if constexpr (mccIsEquatorialMount(CONTROLS_T::mountType)) {
|
|
logger.logTrace(" HA, DEC: {} {}", MccAngle(target_in_future_pt.X).sexagesimal(true),
|
|
MccAngle(target_in_future_pt.Y).sexagesimal());
|
|
} else if constexpr (mccIsAltAzMount(CONTROLS_T::mountType)) {
|
|
logger.logTrace(" AZ, ZD: {} {}", MccAngle(target_in_future_pt.X).sexagesimal(),
|
|
MccAngle(target_in_future_pt.Y).sexagesimal());
|
|
} else {
|
|
static_assert(false, "UNKNOWN MOUNT TYPE!");
|
|
}
|
|
|
|
if (!_currentParams.trackingPathFilename.empty()) { // open tracking trajectory file
|
|
fst.open(_currentParams.trackingPathFilename);
|
|
if (fst.is_open()) {
|
|
store_path = true;
|
|
logger.logInfo(" timesift: {} millisecs", _currentParams.timeShiftToTargetPoint.count());
|
|
logger.logInfo(" min time to pzone: {} secs", _currentParams.minTimeToPZone.count());
|
|
|
|
fst << "# \n";
|
|
fst << "# Tracking trajectory, " << std::chrono::system_clock::now() << "\n";
|
|
fst << "# Config:\n";
|
|
fst << "# timeshift: " << _currentParams.timeShiftToTargetPoint.count() << " millisecs\n";
|
|
fst << "# min time to pzone: " << _currentParams.minTimeToPZone.count() << " secs\n";
|
|
fst << "# \n";
|
|
fst << "# Format (time is in seconds, coordinates are in radians): \n";
|
|
fst << "# <time-since-start> <target X> <target Y> <mount X> <mount Y> <dX_{target-mount}> "
|
|
"<dY_{target-mount}> <moving state>\n";
|
|
|
|
} else {
|
|
logger.logError(std::format("Cannot open tracking path file: {}! Do not save it!",
|
|
_currentParams.trackingPathFilename));
|
|
}
|
|
}
|
|
}
|
|
|
|
// move mount
|
|
logger.logDebug(std::format("Send to hardware: X = {} degs, Y = {} degs",
|
|
mcc::MccAngle{hw_state.X}.degrees(), mcc::MccAngle{hw_state.Y}.degrees()));
|
|
|
|
auto hw_err = controls->hardwareSetState(hw_state);
|
|
if (hw_err) {
|
|
*_stopTracking = true;
|
|
return mcc_deduce_error_code(hw_err, MccSimpleTrackingModelErrorCode::ERROR_HW_SETSTATE);
|
|
}
|
|
|
|
logger.logDebug(" the 'hardwareSetState' method performed successfully!");
|
|
|
|
|
|
std::chrono::steady_clock::time_point last_corr_tp, last_ipzone_update_tp;
|
|
last_corr_tp = std::chrono::steady_clock::now();
|
|
last_ipzone_update_tp = last_corr_tp;
|
|
|
|
while (!*_stopTracking) {
|
|
// wait for updated telemetry data
|
|
{
|
|
std::lock_guard lock{*_currentParamsMutex};
|
|
|
|
t_err = controls->waitForTelemetryData(&tdata, _currentParams.telemetryTimeout);
|
|
|
|
if (t_err) {
|
|
*_stopTracking = true;
|
|
return mcc_deduce_error_code(t_err, MccSimpleTrackingModelErrorCode::ERROR_GET_TELEMETRY);
|
|
}
|
|
}
|
|
|
|
if (store_path) {
|
|
fst << std::chrono::duration_cast<path_tp_t>(tdata.time_point - start_point).count() << " "
|
|
<< tdata.target.HA << " " << tdata.target.DEC_APP << " " << tdata.HA << " " << tdata.DEC_APP
|
|
<< " " << (tdata.target.HA - tdata.HA) << " " << (tdata.target.DEC_APP - tdata.DEC_APP) << " "
|
|
<< (int)hw_state.moving_state << "\n";
|
|
}
|
|
|
|
|
|
if constexpr (mccIsEquatorialMount(CONTROLS_T::mountType)) {
|
|
logger.logTrace(std::format(" current target: HA = {}, DEC = {}",
|
|
mcc::MccAngle(tdata.target.HA).sexagesimal(true),
|
|
mcc::MccAngle(tdata.target.DEC_APP).sexagesimal()));
|
|
logger.logTrace(std::format(" current mount: HA = {}, DEC = {}",
|
|
mcc::MccAngle(tdata.HA).sexagesimal(true),
|
|
mcc::MccAngle(tdata.DEC_APP).sexagesimal()));
|
|
} else if constexpr (mccIsAltAzMount(CONTROLS_T::mountType)) {
|
|
logger.logTrace(std::format(" target: AZ = {}, ZD = {}",
|
|
mcc::MccAngle(tdata.target.AZ).sexagesimal(),
|
|
mcc::MccAngle(tdata.target.ZD).sexagesimal()));
|
|
logger.logTrace(std::format(" mount: AZ = {}, ZD = {}", mcc::MccAngle(tdata.AZ).sexagesimal(),
|
|
mcc::MccAngle(tdata.ZD).sexagesimal()));
|
|
}
|
|
|
|
logger.logTrace(std::format(" mount: speedX = {}/s, speedY = {}/s",
|
|
mcc::MccAngleFancyString(tdata.speedX),
|
|
mcc::MccAngleFancyString(tdata.speedY)));
|
|
|
|
|
|
if (*_stopTracking) {
|
|
break;
|
|
}
|
|
|
|
// control prohibited zones
|
|
// if (mcc_is_near_pzones(controls, tdata, _currentParams.minTimeToPZone, pz_err)) {
|
|
// logger.logError("Mount is near zone!");
|
|
// *_stopTracking = true;
|
|
// return MccSimpleTrackingModelErrorCode::ERROR_NEAR_PZONE;
|
|
// }
|
|
// if (pz_err) {
|
|
// *_stopTracking = true;
|
|
// return mcc_deduce_error_code(pz_err,
|
|
// MccSimpleTrackingModelErrorCode::ERROR_PZONE_CONTAINER_COMP);
|
|
// }
|
|
|
|
if (*_stopTracking) {
|
|
break;
|
|
}
|
|
|
|
// {
|
|
// std::lock_guard lock{*_currentParamsMutex};
|
|
// auto now = std::chrono::steady_clock::now();
|
|
|
|
// if ((now - last_corr_tp) > _currentParams.trackingCycleInterval) {
|
|
// // update prohibited zones intersection point
|
|
// if ((now - last_ipzone_update_tp) < _currentParams.updatingPZoneInterval) {
|
|
// pz_err = update_pzones_ipoint();
|
|
// if (pz_err) {
|
|
// *_stopTracking = true;
|
|
// return mcc_deduce_error_code(
|
|
// pz_err, MccSimpleTrackingModelErrorCode::ERROR_PZONE_CONTAINER_COMP);
|
|
// }
|
|
// }
|
|
|
|
// // compute new target-in-future point
|
|
// auto ccte_err = target_point(&target_in_future_pt);
|
|
// if (ccte_err) {
|
|
// *_stopTracking = true;
|
|
// return mcc_deduce_error_code(ccte_err, MccSimpleTrackingModelErrorCode::ERROR_CCTE);
|
|
// }
|
|
|
|
// logger.logTrace("The updated target point:");
|
|
// if constexpr (mccIsEquatorialMount(CONTROLS_T::mountType)) {
|
|
// logger.logTrace(" HA, DEC: {} {}", MccAngle(target_in_future_pt.X).sexagesimal(true),
|
|
// MccAngle(target_in_future_pt.Y).sexagesimal());
|
|
// } else if constexpr (mccIsAltAzMount(CONTROLS_T::mountType)) {
|
|
// logger.logTrace(" AZ, ZD: {} {}", MccAngle(target_in_future_pt.X).sexagesimal(),
|
|
// MccAngle(target_in_future_pt.Y).sexagesimal());
|
|
// } else {
|
|
// static_assert(false, "UNKNOWN MOUNT TYPE!");
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// compute new target-in-future point
|
|
auto ccte_err = target_point(&target_in_future_pt);
|
|
if (ccte_err) {
|
|
*_stopTracking = true;
|
|
return mcc_deduce_error_code(ccte_err, MccSimpleTrackingModelErrorCode::ERROR_CCTE);
|
|
}
|
|
|
|
logger.logTrace("The updated target point:");
|
|
if constexpr (mccIsEquatorialMount(CONTROLS_T::mountType)) {
|
|
logger.logTrace(" HA, DEC: {} {}", MccAngle(target_in_future_pt.X).sexagesimal(true),
|
|
MccAngle(target_in_future_pt.Y).sexagesimal());
|
|
} else if constexpr (mccIsAltAzMount(CONTROLS_T::mountType)) {
|
|
logger.logTrace(" AZ, ZD: {} {}", MccAngle(target_in_future_pt.X).sexagesimal(),
|
|
MccAngle(target_in_future_pt.Y).sexagesimal());
|
|
} else {
|
|
static_assert(false, "UNKNOWN MOUNT TYPE!");
|
|
}
|
|
|
|
// send corrections
|
|
logger.logDebug(std::format("Send to hardware: X = {} degs, Y = {} degs",
|
|
mcc::MccAngle{hw_state.X}.degrees(), mcc::MccAngle{hw_state.Y}.degrees()));
|
|
|
|
hw_state.moving_state = CONTROLS_T::hardware_moving_state_t::HW_MOVE_TRACKING;
|
|
hw_err = controls->hardwareSetState(hw_state);
|
|
if (hw_err) {
|
|
*_stopTracking = true;
|
|
return mcc_deduce_error_code(hw_err, MccSimpleTrackingModelErrorCode::ERROR_HW_SETSTATE);
|
|
}
|
|
|
|
logger.logDebug(" the 'hardwareSetState' method performed successfully!");
|
|
|
|
|
|
// sleep here
|
|
{
|
|
std::lock_guard lock{*_currentParamsMutex};
|
|
std::this_thread::sleep_for(_currentParams.trackingTelemetryInterval);
|
|
}
|
|
}
|
|
|
|
return MccSimpleTrackingModelErrorCode::ERROR_OK;
|
|
};
|
|
}
|
|
|
|
MccSimpleTrackingModel(MccSimpleTrackingModel&&) = default;
|
|
MccSimpleTrackingModel& operator=(MccSimpleTrackingModel&&) = default;
|
|
|
|
MccSimpleTrackingModel(const MccSimpleTrackingModel&) = delete;
|
|
MccSimpleTrackingModel& operator=(const MccSimpleTrackingModel&) = delete;
|
|
|
|
error_t trackTarget()
|
|
{
|
|
if (!(*_stopTracking)) { // already tracking
|
|
return MccSimpleTrackingModelErrorCode::ERROR_ALREADY_TRACK;
|
|
}
|
|
|
|
*_stopTracking = false;
|
|
|
|
return _trackingFunc();
|
|
}
|
|
|
|
error_t stopTracking()
|
|
{
|
|
if (*_stopTracking) { // already stopped
|
|
return MccSimpleTrackingModelErrorCode::ERROR_ALREADY_STOPPED;
|
|
}
|
|
|
|
*_stopTracking = true;
|
|
|
|
return MccSimpleTrackingModelErrorCode::ERROR_OK;
|
|
}
|
|
|
|
error_t setTrackingParams(tracking_params_t params)
|
|
{
|
|
std::lock_guard lock{*_currentParamsMutex};
|
|
|
|
_currentParams = std::move(params);
|
|
|
|
return MccSimpleTrackingModelErrorCode::ERROR_OK;
|
|
}
|
|
|
|
|
|
tracking_params_t getTrackingParams() const
|
|
{
|
|
std::lock_guard lock{*_currentParamsMutex};
|
|
|
|
return _currentParams;
|
|
}
|
|
|
|
error_t trackinLastError() const
|
|
{
|
|
return _lastError;
|
|
}
|
|
|
|
protected:
|
|
std::function<error_t()> _trackingFunc{};
|
|
std::unique_ptr<std::atomic_bool> _stopTracking;
|
|
|
|
tracking_params_t _currentParams{};
|
|
std::unique_ptr<std::mutex> _currentParamsMutex{};
|
|
|
|
error_t _lastError;
|
|
};
|
|
|
|
} // namespace mcc
|