...
This commit is contained in:
parent
138e4bf84d
commit
6315d5e18e
@ -123,9 +123,12 @@ set(CNTR_PROTO_LIB comm_proto)
|
||||
add_library(${CNTR_PROTO_LIB} STATIC ${CNTR_PROTO_LIB_SRC})
|
||||
|
||||
|
||||
set(MCC_LIBRARY_SRC mcc_mount_concepts.h mcc_fsm_mount.h mcc_mount_coord.h mcc_mount_events_states.h mcc_finite_state_machine.h
|
||||
include_directories(${FITPACK_INCLUDE_DIR})
|
||||
|
||||
|
||||
set(MCC_LIBRARY_SRC mcc_mount_concepts.h mcc_fsm_mount.h mcc_generic_mount.h mcc_mount_coord.h mcc_mount_events_states.h mcc_finite_state_machine.h
|
||||
mcc_mount_pec.h mcc_mount_pz.h mcc_traits.h mcc_mount_telemetry_astrom.h mcc_mount_telemetry.h mcc_mount_config.h mcc_mount_astro_erfa.h
|
||||
mcc_astrom_iers.h mcc_astrom_iers_default.h mcc_slew_model.h mcc_guiding_model.h mcc_utils.h mcc_spdlog.h)
|
||||
mcc_astrom_iers.h mcc_astrom_iers_default.h mcc_slew_model.h mcc_guiding_model.h mcc_slew_guiding_model_common.h mcc_utils.h mcc_spdlog.h)
|
||||
set(MCC_LIBRARY mcc)
|
||||
add_library(${MCC_LIBRARY} INTERFACE ${MCC_LIBRARY_SRC})
|
||||
target_compile_features(${MCC_LIBRARY} INTERFACE cxx_std_23)
|
||||
|
||||
@ -29,6 +29,9 @@ typedef mcc::MccMountTelemetry<AsibFM700AstromEngine,
|
||||
AsibFM700TelemetryData>
|
||||
AsibFM700Telemetry;
|
||||
|
||||
static_assert(std::movable<AsibFM700Telemetry>);
|
||||
static_assert(std::movable<AsibFM700AstromEngine>);
|
||||
static_assert(std::movable<mcc::MccAltLimitPZ<>>);
|
||||
|
||||
// typedef mcc::MccSimpleSlewModel<> AsibFM700SlewModel;
|
||||
// typedef mcc::MccSimpleGuidingModel<> AsibFM700GuidingModel;
|
||||
@ -63,7 +66,7 @@ static_assert(mcc::traits::mcc_mount_controls_c<AsibFM700MountControls<mcc::util
|
||||
// global mount configuration
|
||||
|
||||
struct AsibFM700Config {
|
||||
std::chrono::milliseconds hardwareAskingPeriod{100}; // main cycle period
|
||||
std::chrono::milliseconds hardwarePollingPeriod{100}; // main cycle period
|
||||
|
||||
// mount hardware config
|
||||
AsibFM700Hardware::hardware_config_t hardwareConfig;
|
||||
@ -72,6 +75,10 @@ struct AsibFM700Config {
|
||||
|
||||
class AsibFM700Mount : public mcc::MccMount<AsibFM700MountControls<mcc::utils::MccSpdlogLogger>>
|
||||
{
|
||||
class InitState : public AsibFM700Mount::MccMountEventBase
|
||||
{
|
||||
};
|
||||
|
||||
public:
|
||||
};
|
||||
|
||||
|
||||
@ -100,19 +100,26 @@ AsibFM700Hardware::error_t AsibFM700Hardware::setPos(AsibFM700Hardware::axes_pos
|
||||
double tp = std::chrono::duration<double>(pos.time_point.time_since_epoch()).count();
|
||||
coordval_pair_t hw_posval{.X{.val = pos.x, .t = tp}, .Y{.val = pos.y, .t = tp}};
|
||||
|
||||
//
|
||||
// WARNING: The LibSidservo API was chagned! hw_pos is endpoint where mount must
|
||||
// go "after" slewing
|
||||
//
|
||||
|
||||
switch (pos.moving_type) {
|
||||
case hw_moving_type_t::HW_MOVE_SLEWING: // slew mount
|
||||
if (pos.moveAndStop) {
|
||||
err = static_cast<AsibFM700HardwareErrorCode>(Mount.moveTo(&hw_pos));
|
||||
// err = static_cast<AsibFM700HardwareErrorCode>(Mount.moveTo(&hw_pos));
|
||||
err = static_cast<AsibFM700HardwareErrorCode>(Mount.correctTo(&hw_posval, &hw_pos));
|
||||
} else {
|
||||
err = static_cast<AsibFM700HardwareErrorCode>(Mount.slewTo(&hw_pos, pos.flags));
|
||||
// err = static_cast<AsibFM700HardwareErrorCode>(Mount.slewTo(&hw_pos, pos.flags));
|
||||
err = static_cast<AsibFM700HardwareErrorCode>(Mount.correctTo(&hw_posval, &hw_pos));
|
||||
}
|
||||
break;
|
||||
case hw_moving_type_t::HW_MOVE_ADJUSTING: // corrections at the end of slewing
|
||||
err = static_cast<AsibFM700HardwareErrorCode>(Mount.correctTo(&hw_posval));
|
||||
err = static_cast<AsibFM700HardwareErrorCode>(Mount.correctTo(&hw_posval, &hw_pos));
|
||||
break;
|
||||
case hw_moving_type_t::HW_MOVE_GUIDING: // interpretate as guiding correction
|
||||
err = static_cast<AsibFM700HardwareErrorCode>(Mount.correctTo(&hw_posval));
|
||||
err = static_cast<AsibFM700HardwareErrorCode>(Mount.correctTo(&hw_posval, &hw_pos));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
@ -79,7 +79,7 @@ public:
|
||||
coord_t xrate, yrate;
|
||||
|
||||
hw_moving_type_t moving_type{hw_moving_type_t::HW_MOVE_TRACKING};
|
||||
slewflags_t flags;
|
||||
// slewflags_t flags;
|
||||
bool moveAndStop{false};
|
||||
};
|
||||
|
||||
|
||||
@ -23,12 +23,33 @@
|
||||
namespace mcc
|
||||
{
|
||||
|
||||
// adaptor class for prohibited zones
|
||||
template <traits::mcc_mount_telemetry_data_c TelemetryDataT>
|
||||
struct MccPZoneWrapper {
|
||||
// a type to which the result of calling prohibited zone class methods 'timeTo' and 'timeFrom' will be converted
|
||||
typedef std::chrono::duration<double> pz_duration_t; // seconds as floating-point number
|
||||
|
||||
static constexpr pz_duration_t infiniteDuration{std::numeric_limits<double>::infinity()};
|
||||
static constexpr pz_duration_t zeroDuration{0.0};
|
||||
|
||||
typedef std::function<bool(const TelemetryDataT&)> pz_inzone_func_t;
|
||||
typedef std::function<pz_duration_t(const TelemetryDataT&)> pz_timeto_func_t;
|
||||
typedef std::function<pz_duration_t(const TelemetryDataT&)> pz_timefrom_func_t;
|
||||
|
||||
MccCoordPairKind coordPairKind;
|
||||
const std::function<std::string()> name;
|
||||
pz_inzone_func_t inZone;
|
||||
pz_timeto_func_t timeTo;
|
||||
pz_timefrom_func_t timeFrom;
|
||||
};
|
||||
|
||||
|
||||
template <traits::mcc_mount_controls_c MOUNT_CONTROLS>
|
||||
class MccMount : public fsm::MccFiniteStateMachine, public utils::MccSpdlogLogger, protected MOUNT_CONTROLS
|
||||
{
|
||||
// declare these classes as friends to allow them access protected members 'slewModel' and 'guidingModel'
|
||||
friend class MccMountStateSlew<MccMount<MOUNT_CONTROLS>>;
|
||||
friend class MccMountStateGuiding<MccMount<MOUNT_CONTROLS>>;
|
||||
// friend class MccMountStateSlew<MccMount<MOUNT_CONTROLS>>;
|
||||
// friend class MccMountStateGuiding<MccMount<MOUNT_CONTROLS>>;
|
||||
|
||||
public:
|
||||
typedef MOUNT_CONTROLS mount_controls_t;
|
||||
@ -43,6 +64,47 @@ public:
|
||||
|
||||
// typedef typename slew_model_t::slew_params_t slew_params_t;
|
||||
|
||||
/* base classes for event and state */
|
||||
|
||||
class MccMountEventBase
|
||||
{
|
||||
protected:
|
||||
MccMount& _mount;
|
||||
|
||||
public:
|
||||
MccMountEventBase(MccMount& mount) : _mount(mount) {}
|
||||
virtual ~MccMountEventBase() = default;
|
||||
|
||||
MccMount& mount() { return _mount; }
|
||||
};
|
||||
|
||||
// The implementation of FSM (see mcc_finite_state_machine.h) requires
|
||||
// state to be a default constructible class, so one needs to hold
|
||||
// a pointer to mount class to guarantee access to its private or protected
|
||||
// members and methods
|
||||
class MccMountStateBase
|
||||
{
|
||||
protected:
|
||||
// a pointer to mount class to allow access to private/protected
|
||||
// members/methods of MccMount class from descendent state-classes.
|
||||
// the memory address can be obtained from a call of
|
||||
// MccMountEventBase::mount method (see above)
|
||||
MccMount* _mount;
|
||||
|
||||
public:
|
||||
MccMountStateBase() = default;
|
||||
|
||||
MccMountStateBase(const MccMountStateBase&) = delete;
|
||||
MccMountStateBase& operator=(const MccMountStateBase&) = delete;
|
||||
|
||||
// just as an example (ugly but I still cannot find a solution)
|
||||
// template <std::derived_from<MccMountEventBase> EvT>
|
||||
// void enter(EvT& event)
|
||||
// {
|
||||
// _mount = &event.mount();
|
||||
// _mount->forEachPZone(...);
|
||||
// }
|
||||
};
|
||||
|
||||
/* constructors and destructor */
|
||||
|
||||
@ -64,6 +126,8 @@ public:
|
||||
logDebug("{}", std::string(r.begin(), r.end()));
|
||||
}
|
||||
|
||||
MccMount(const MccMount&) = delete;
|
||||
MccMount& operator=(const MccMount&) = delete;
|
||||
|
||||
virtual ~MccMount() { logDebug("Delete MccMount class instance: thread = {}", getThreadId()); }
|
||||
|
||||
@ -103,15 +167,34 @@ public:
|
||||
{
|
||||
auto zone_ptr = std::make_shared<ZT>(std::move(zone));
|
||||
|
||||
using d_t = typename MccPZoneWrapper<mount_telemetry_data_t>::pz_duration_t;
|
||||
|
||||
_pzFuncs.emplace_back(
|
||||
{.coordPairKind = ZT::zoneCoordPairKind,
|
||||
.name = std::format("{}", zone_ptr->name()),
|
||||
.inZoneFunc = [zone_ptr,
|
||||
this](const mount_telemetry_data_t& tmry_data) { return zone_ptr->inZone(tmry_data); },
|
||||
.timeToFunc = [zone_ptr,
|
||||
this](const mount_telemetry_data_t& tmry_data) { return zone_ptr->timeTo(tmry_data); },
|
||||
.timeFromFunc =
|
||||
[zone_ptr, this](const mount_telemetry_data_t& tmry_data) { return zone_ptr->timeFrom(tmry_data); }});
|
||||
.name = [zone_ptr]() { return std::format("{}", zone_ptr->name()); },
|
||||
.inZone = [zone_ptr](const mount_telemetry_data_t& tmry_data) { return zone_ptr->inZone(tmry_data); },
|
||||
.timeTo =
|
||||
[zone_ptr](const mount_telemetry_data_t& tmry_data) {
|
||||
auto d = zone_ptr->timeTo(tmry_data);
|
||||
|
||||
if (d == ZT::infiniteDuration) {
|
||||
return MccPZoneWrapper<mount_telemetry_data_t>::infiniteDuration;
|
||||
} else if (d == ZT::zeroDuration) {
|
||||
return MccPZoneWrapper<mount_telemetry_data_t>::zeroDuration;
|
||||
}
|
||||
return std::chrono::duration_cast<d_t>(d);
|
||||
},
|
||||
.timeFrom =
|
||||
[zone_ptr](const mount_telemetry_data_t& tmry_data) {
|
||||
auto d = zone_ptr->timeFrom(tmry_data);
|
||||
|
||||
if (d == ZT::infiniteDuration) {
|
||||
return MccPZoneWrapper<mount_telemetry_data_t>::infiniteDuration;
|
||||
} else if (d == ZT::zeroDuration) {
|
||||
return MccPZoneWrapper<mount_telemetry_data_t>::zeroDuration;
|
||||
}
|
||||
return std::chrono::duration_cast<d_t>(d);
|
||||
}});
|
||||
|
||||
|
||||
if constexpr (sizeof...(ZTs)) {
|
||||
@ -144,8 +227,8 @@ protected:
|
||||
pz_timefrom_func_t timeFromFunc;
|
||||
};
|
||||
|
||||
std::vector<pz_funcs_t> _pzFuncs{};
|
||||
|
||||
// std::vector<pz_funcs_t> _pzFuncs{};
|
||||
std::vector<MccPZoneWrapper<mount_telemetry_data_t>> _pzFuncs{};
|
||||
|
||||
template <typename FuncT, traits::mcc_prohibited_zone_c<mount_telemetry_data_t>... ZTs>
|
||||
auto forEachPZone(FuncT&& func, std::tuple<ZTs...>& zones)
|
||||
|
||||
258
cxx/mcc_generic_mount.h
Normal file
258
cxx/mcc_generic_mount.h
Normal file
@ -0,0 +1,258 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
/* MOUNT CONTROL COMPONENTS LIBRARY */
|
||||
|
||||
|
||||
|
||||
/* A GENERIC MOUNT CLASS IMPLEMENTATION */
|
||||
|
||||
|
||||
#include <algorithm>
|
||||
#include "mcc_mount_concepts.h"
|
||||
|
||||
namespace mcc
|
||||
{
|
||||
|
||||
// adaptor class for prohibited zones
|
||||
template <traits::mcc_mount_telemetry_data_c TelemetryDataT>
|
||||
struct MccPZoneWrapper {
|
||||
// a type to which the result of calling prohibited zone class methods 'timeTo' and 'timeFrom' will be converted
|
||||
typedef std::chrono::duration<double> duration_t; // seconds as floating-point number
|
||||
|
||||
static constexpr duration_t infiniteDuration{std::numeric_limits<double>::infinity()};
|
||||
static constexpr duration_t zeroDuration{0.0};
|
||||
|
||||
typedef std::function<bool(const TelemetryDataT&)> pz_inzone_func_t;
|
||||
typedef std::function<duration_t(const TelemetryDataT&)> pz_timeto_func_t;
|
||||
typedef std::function<duration_t(const TelemetryDataT&)> pz_timefrom_func_t;
|
||||
|
||||
MccCoordPairKind coordPairKind;
|
||||
const std::function<std::string()> name;
|
||||
pz_inzone_func_t inZone;
|
||||
pz_timeto_func_t timeTo;
|
||||
pz_timefrom_func_t timeFrom;
|
||||
};
|
||||
|
||||
|
||||
template <traits::mcc_astrom_engine_c ASTROM_ENGINE_T,
|
||||
traits::mcc_mount_hardware_c HARDWARE_T,
|
||||
traits::mcc_mount_pec_c PEC_T,
|
||||
traits::mcc_mount_telemetry_c TELEMETRY_T,
|
||||
traits::mcc_slew_model_c SLEWMODEL_T,
|
||||
traits::mcc_guiding_model_c GUIDEMODEL_T,
|
||||
traits::mcc_logger_c LOGGER_T>
|
||||
class MccGenericMount : public LOGGER_T
|
||||
{
|
||||
typedef LOGGER_T logger_t;
|
||||
|
||||
using logger_t::logDebug;
|
||||
using logger_t::logError;
|
||||
using logger_t::logInfo;
|
||||
using logger_t::logWarn;
|
||||
|
||||
typedef ASTROM_ENGINE_T astrom_engine_t;
|
||||
typedef HARDWARE_T hardware_t;
|
||||
typedef PEC_T pec_t;
|
||||
typedef TELEMETRY_T telemetry_t;
|
||||
typedef typename TELEMETRY_T::telemetry_data_t telemetry_data_t;
|
||||
typedef SLEWMODEL_T slew_model_t;
|
||||
typedef GUIDEMODEL_T guiding_model_t;
|
||||
|
||||
typedef typename MccPZoneWrapper<telemetry_data_t>::duration_t pz_duration_t;
|
||||
|
||||
static constexpr MccMountType mountType = pec_t::mountType;
|
||||
|
||||
virtual ~MccGenericMount() = default;
|
||||
|
||||
// get telemetry data
|
||||
auto mountTelemetryData(telemetry_data_t& data) { return _telemetry.data(data); }
|
||||
|
||||
|
||||
/* prohibited zone related public methods */
|
||||
|
||||
// add zones to mount control system
|
||||
template <traits::mcc_prohibited_zone_c<telemetry_data_t> ZT,
|
||||
traits::mcc_prohibited_zone_c<telemetry_data_t>... ZTs>
|
||||
size_t pzAddZone(ZT zone, ZTs... zones)
|
||||
{
|
||||
auto zone_ptr = std::make_shared<ZT>(std::move(zone));
|
||||
|
||||
using d_t = typename MccPZoneWrapper<telemetry_data_t>::duration_t;
|
||||
|
||||
_pzFuncs.emplace_back(
|
||||
{.coordPairKind = ZT::zoneCoordPairKind,
|
||||
.name = [zone_ptr]() { return std::format("{}", zone_ptr->name()); },
|
||||
.inZone = [zone_ptr](const telemetry_data_t& tmry_data) { return zone_ptr->inZone(tmry_data); },
|
||||
.timeTo =
|
||||
[zone_ptr](const telemetry_data_t& tmry_data) {
|
||||
auto d = zone_ptr->timeTo(tmry_data);
|
||||
|
||||
if constexpr (std::same_as<typename ZT::duration_t, d_t>) {
|
||||
return d;
|
||||
} else {
|
||||
if (d == ZT::infiniteDuration) {
|
||||
return MccPZoneWrapper<telemetry_data_t>::infiniteDuration;
|
||||
} else if (d == ZT::zeroDuration) {
|
||||
return MccPZoneWrapper<telemetry_data_t>::zeroDuration;
|
||||
}
|
||||
return std::chrono::duration_cast<d_t>(d);
|
||||
}
|
||||
},
|
||||
.timeFrom =
|
||||
[zone_ptr](const telemetry_data_t& tmry_data) {
|
||||
auto d = zone_ptr->timeFrom(tmry_data);
|
||||
|
||||
if constexpr (std::same_as<typename ZT::duration_t, d_t>) {
|
||||
return d;
|
||||
} else {
|
||||
if (d == ZT::infiniteDuration) {
|
||||
return MccPZoneWrapper<telemetry_data_t>::infiniteDuration;
|
||||
} else if (d == ZT::zeroDuration) {
|
||||
return MccPZoneWrapper<telemetry_data_t>::zeroDuration;
|
||||
}
|
||||
return std::chrono::duration_cast<d_t>(d);
|
||||
}
|
||||
}});
|
||||
|
||||
|
||||
if constexpr (sizeof...(ZTs)) {
|
||||
pzAddZone(std::move(zones)...);
|
||||
}
|
||||
|
||||
return _pzFuncs.size();
|
||||
}
|
||||
|
||||
// delete all zones from mount control system
|
||||
void pzClearZone()
|
||||
{
|
||||
// stop mount here?!!
|
||||
_pzFuncs.clear();
|
||||
}
|
||||
|
||||
// prohibited zones timeTo from given time point
|
||||
template <std::ranges::output_range<pz_duration_t> RT, traits::mcc_celestial_point_c CT, traits::mcc_systime_c TPT>
|
||||
RT pzTimeTo(CT coord, const TPT& time_point)
|
||||
requires std::convertible_to<TPT, typename astrom_engine_t::time_point_t>
|
||||
{
|
||||
RT res;
|
||||
|
||||
telemetry_data_t tdata;
|
||||
typename astrom_engine_t::juldate_t jd;
|
||||
|
||||
_astromEngine.greg2jul(time_point, jd);
|
||||
|
||||
if (coord.coordPairKind == MccCoordPairKind::COORDS_KIND_XY) { // from encoder's
|
||||
typename pec_t::pec_result_t pec_res;
|
||||
auto pec_err = _pec.compute(coord.x, coord.y, pec_res);
|
||||
if (!pec_err) {
|
||||
if constexpr (mccIsEquatorialMount(mountType)) {
|
||||
tdata.mntHA = coord.x + pec_res.dx;
|
||||
tdata.mntDEC = coord.y + pec_res.dy;
|
||||
_astromEngine.hadec2azalt(tdata.mntHA, tdata.mntDEC, tdata.mntAZ, tdata.mntALT);
|
||||
} else if constexpr (mccIsAltAzMount(mountType)) {
|
||||
tdata.mntAZ = coord.x + pec_res.dx;
|
||||
tdata.mntALT = coord.y + pec_res.dy;
|
||||
_astromEngine.azalt2hadec(tdata.mntAZ, tdata.mntALT, tdata.mntHA, tdata.mntDEC);
|
||||
}
|
||||
} else {
|
||||
return res;
|
||||
}
|
||||
} else if (coord.coordPairKind == MccCoordPairKind::COORDS_KIND_RADEC_APP) { // from app RA-DEC
|
||||
typename astrom_engine_t::eo_t eo;
|
||||
typename astrom_engine_t::sideral_time_t lst;
|
||||
|
||||
_astromEngine.apparentSiderTime(jd, lst, true);
|
||||
_astromEngine.eqOrigins(jd, eo);
|
||||
|
||||
} else if (coord.coordPairKind == MccCoordPairKind::COORDS_KIND_HADEC_APP) { // from app HA-DEC
|
||||
tdata.mntHA = coord.x;
|
||||
tdata.mntDEC = coord.y;
|
||||
_astromEngine.hadec2azalt(tdata.mntHA, tdata.mntDEC, tdata.mntAZ, tdata.mntALT);
|
||||
} else if (coord.coordPairKind == MccCoordPairKind::COORDS_KIND_AZALT) { // from app AZ-ALT
|
||||
tdata.mntAZ = coord.x;
|
||||
tdata.mntALT = coord.y;
|
||||
_astromEngine.azalt2hadec(tdata.mntAZ, tdata.mntALT, tdata.mntHA, tdata.mntDEC);
|
||||
} else if (coord.coordPairKind == MccCoordPairKind::COORDS_KIND_AZZD) { // from app AZ-ZD
|
||||
tdata.mntAZ = coord.x;
|
||||
tdata.mntALT = std::numbers::pi / 2.0 - coord.y;
|
||||
_astromEngine.azalt2hadec(tdata.mntAZ, tdata.mntALT, tdata.mntHA, tdata.mntDEC);
|
||||
} else if (coord.coordPairKind == MccCoordPairKind::COORDS_KIND_RADEC_ICRS) { // from ICRS RA-DEC
|
||||
typename astrom_engine_t::coord_t az, alt;
|
||||
typename astrom_engine_t::eo_t eo;
|
||||
typename astrom_engine_t::juldate_t jd;
|
||||
|
||||
_astromEngine.greg2jul(time_point, jd);
|
||||
_astromEngine.icrs2obs(coord.x, coord.y, jd, tdata.mntRA, tdata.mntDEC, tdata.mntHA, tdata.mntAZ,
|
||||
tdata.mntALT, eo);
|
||||
} else {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
template <traits::mcc_celestial_point_c CT, traits::mcc_systime_c TPT>
|
||||
auto pzTimeTo(CT point, const TPT& time_point)
|
||||
{
|
||||
return pzTimeTo<std::vector<pz_duration_t>>(std::move(point), time_point);
|
||||
}
|
||||
|
||||
// prohibited zones timeTo from current mount position
|
||||
template <std::ranges::output_range<pz_duration_t> RT, traits::mcc_celestial_point_c CT>
|
||||
RT pzTimeTo(CT point)
|
||||
{
|
||||
RT result;
|
||||
|
||||
telemetry_data_t data;
|
||||
auto err = _telemetry.data(data);
|
||||
if (err) {
|
||||
// log...
|
||||
return result;
|
||||
}
|
||||
|
||||
std::ranges::for_each(_pzFuncs,
|
||||
[&result, &data](auto& funcs) { std::back_inserter(result) = funcs.timeTo(data); });
|
||||
}
|
||||
|
||||
template <traits::mcc_celestial_point_c CT>
|
||||
auto pzTimeTo(CT point)
|
||||
{
|
||||
return pzTimeTo<std::vector<pz_duration_t>>(std::move(point));
|
||||
}
|
||||
|
||||
// prohibited zone timeFrom
|
||||
|
||||
protected:
|
||||
ASTROM_ENGINE_T _astromEngine;
|
||||
HARDWARE_T _hardware;
|
||||
PEC_T _pec;
|
||||
TELEMETRY_T _telemetry;
|
||||
SLEWMODEL_T _slewModel;
|
||||
GUIDEMODEL_T _gudingModel;
|
||||
|
||||
std::vector<MccPZoneWrapper<telemetry_data_t>> _pzFuncs{};
|
||||
};
|
||||
|
||||
|
||||
namespace traits
|
||||
{
|
||||
|
||||
template <typename T>
|
||||
concept mcc_generic_mount_c = requires(T t) {
|
||||
// derived from MccGenericMount
|
||||
[]<typename... Ts>(MccGenericMount<Ts...>*) {}(&t);
|
||||
|
||||
{ t.slewMount(std::declval<typename T::slew_model_t::slew_point_t>()) };
|
||||
{ t.startGuiding(std::declval<typename T::guiding_model_t::guiding_point_t>()) };
|
||||
|
||||
{ t.stop() };
|
||||
};
|
||||
|
||||
|
||||
template <typename T>
|
||||
concept mcc_generic_fsm_mount_c = mcc_generic_mount_c<T> && std::derived_from<T, fsm::MccFiniteStateMachine>;
|
||||
|
||||
|
||||
} // namespace traits
|
||||
|
||||
|
||||
} // namespace mcc
|
||||
@ -164,6 +164,27 @@ public:
|
||||
init(telemetry, hardware, prohibited_zone);
|
||||
}
|
||||
|
||||
|
||||
MccSimpleGuidingModel(MccSimpleGuidingModel&& other)
|
||||
: _guidingFunc(std::move(other._guidingFunc)),
|
||||
_doCorrection(other._doCorrection.load()),
|
||||
_stopRequested(other._stopRequested.load())
|
||||
{
|
||||
}
|
||||
|
||||
MccSimpleGuidingModel& operator=(MccSimpleGuidingModel&& other)
|
||||
{
|
||||
if (this == &other) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
_guidingFunc = std::move(other._guidingFunc);
|
||||
_doCorrection = other._doCorrection.load();
|
||||
_stopRequested = other._stopRequested.load();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
virtual ~MccSimpleGuidingModel()
|
||||
{
|
||||
logDebug(std::format("Delete 'MccSimpleGuidingModel' class instance ({})", (void*)this));
|
||||
@ -333,4 +354,6 @@ protected:
|
||||
}
|
||||
};
|
||||
|
||||
// static_assert(std::movable<MccSimpleGuidingModel<>>);
|
||||
|
||||
} // namespace mcc
|
||||
|
||||
@ -151,15 +151,9 @@ public:
|
||||
double mjd{51544.5}; // J2000.0
|
||||
};
|
||||
|
||||
// typedef MccAngle coord_t;
|
||||
|
||||
// typedef MccAngle sideral_time_t;
|
||||
// typedef MccAngle pa_t;
|
||||
// typedef MccAngle eo_t;
|
||||
|
||||
|
||||
/* use of the same type fro representation of celestial and geodetic coordinates, celestial angles (e.g. P.A.),
|
||||
* sideral time */
|
||||
/* use of the same type for representation of celestial and geodetic coordinates, celestial angles (e.g. P.A.),
|
||||
* and sideral time */
|
||||
typedef AngleT coord_t;
|
||||
|
||||
typedef AngleT sideral_time_t;
|
||||
@ -173,40 +167,51 @@ public:
|
||||
|
||||
MccMountAstromEngineERFA() = default;
|
||||
|
||||
MccMountAstromEngineERFA(engine_state_t state) : _currentState(std::move(state)) {}
|
||||
|
||||
MccMountAstromEngineERFA(MccMountAstromEngineERFA&&) = default;
|
||||
MccMountAstromEngineERFA& operator=(MccMountAstromEngineERFA&&) = default;
|
||||
MccMountAstromEngineERFA(engine_state_t state) : _currentState(std::move(state)), _stateMutex(new std::mutex) {}
|
||||
|
||||
MccMountAstromEngineERFA(const MccMountAstromEngineERFA&) = delete;
|
||||
MccMountAstromEngineERFA& operator=(const MccMountAstromEngineERFA&) = delete;
|
||||
|
||||
MccMountAstromEngineERFA(MccMountAstromEngineERFA&& other)
|
||||
: _currentState(std::move(other._currentState)), _stateMutex(std::move(other._stateMutex)) {};
|
||||
|
||||
MccMountAstromEngineERFA& operator=(MccMountAstromEngineERFA&& other)
|
||||
{
|
||||
if (this != &other) {
|
||||
_currentState = std::move(other._currentState);
|
||||
_stateMutex = std::move(other._stateMutex);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
virtual ~MccMountAstromEngineERFA() = default;
|
||||
|
||||
void setState(engine_state_t state)
|
||||
{
|
||||
std::lock_guard lock{_stateMutex};
|
||||
std::lock_guard lock{*_stateMutex};
|
||||
|
||||
_currentState = std::move(state);
|
||||
}
|
||||
|
||||
engine_state_t getState() const
|
||||
{
|
||||
std::lock_guard lock{_stateMutex};
|
||||
std::lock_guard lock{*_stateMutex};
|
||||
|
||||
return _currentState;
|
||||
}
|
||||
|
||||
void updateMeteo(meteo_t meteo)
|
||||
{
|
||||
std::lock_guard lock{_stateMutex};
|
||||
std::lock_guard lock{*_stateMutex};
|
||||
|
||||
_currentState.meteo = std::move(meteo);
|
||||
}
|
||||
|
||||
error_t updateLeapSeconds(std::derived_from<std::basic_istream<char>> auto& stream, char comment_sym = '#')
|
||||
{
|
||||
std::lock_guard lock{_stateMutex};
|
||||
std::lock_guard lock{*_stateMutex};
|
||||
|
||||
if (!_currentState._leapSeconds.load(stream, comment_sym)) {
|
||||
return MccMountAstromEngineERFAErrorCode::ERROR_UPDATE_LEAPSECONDS;
|
||||
@ -218,7 +223,7 @@ public:
|
||||
|
||||
error_t updateLeapSeconds(traits::mcc_input_char_range auto const& filename, char comment_sym = '#')
|
||||
{
|
||||
std::lock_guard lock{_stateMutex};
|
||||
std::lock_guard lock{*_stateMutex};
|
||||
|
||||
if (!_currentState._leapSeconds.load(filename, comment_sym)) {
|
||||
return MccMountAstromEngineERFAErrorCode::ERROR_UPDATE_LEAPSECONDS;
|
||||
@ -230,7 +235,7 @@ public:
|
||||
|
||||
error_t updateBulletinA(std::derived_from<std::basic_istream<char>> auto& stream, char comment_sym = '*')
|
||||
{
|
||||
std::lock_guard lock{_stateMutex};
|
||||
std::lock_guard lock{*_stateMutex};
|
||||
|
||||
if (!_currentState._bulletinA.load(stream, comment_sym)) {
|
||||
return MccMountAstromEngineERFAErrorCode::ERROR_UPDATE_BULLETINA;
|
||||
@ -242,7 +247,7 @@ public:
|
||||
|
||||
error_t updateBulletinA(traits::mcc_input_char_range auto const& filename, char comment_sym = '*')
|
||||
{
|
||||
std::lock_guard lock{_stateMutex};
|
||||
std::lock_guard lock{*_stateMutex};
|
||||
|
||||
if (!_currentState._bulletinA.load(filename, comment_sym)) {
|
||||
return MccMountAstromEngineERFAErrorCode::ERROR_UPDATE_BULLETINA;
|
||||
@ -299,7 +304,7 @@ public:
|
||||
|
||||
error_t terrestrialTime(juldate_t juldate, juldate_t& tt)
|
||||
{
|
||||
std::lock_guard lock{_stateMutex};
|
||||
std::lock_guard lock{*_stateMutex};
|
||||
|
||||
using real_days_t = std::chrono::duration<double, std::ratio<86400>>;
|
||||
|
||||
@ -320,7 +325,7 @@ public:
|
||||
|
||||
error_t apparentSiderTime(juldate_t juldate, sideral_time_t& gst, bool islocal = false)
|
||||
{
|
||||
// std::lock_guard lock{_stateMutex};
|
||||
// std::lock_guard lock{*_stateMutex};
|
||||
|
||||
using real_days_t = std::chrono::duration<double, std::ratio<86400>>;
|
||||
|
||||
@ -328,7 +333,7 @@ public:
|
||||
// double tt = juldate.mjd;
|
||||
|
||||
{
|
||||
std::lock_guard lock{_stateMutex};
|
||||
std::lock_guard lock{*_stateMutex};
|
||||
|
||||
auto dut1 = _currentState._bulletinA.DUT1(juldate.mjd);
|
||||
|
||||
@ -384,7 +389,7 @@ public:
|
||||
|
||||
error_t refraction(refract_result_t& refr)
|
||||
{
|
||||
std::lock_guard lock{_stateMutex};
|
||||
std::lock_guard lock{*_stateMutex};
|
||||
|
||||
eraRefco(_currentState.meteo.pressure, _currentState.meteo.temperature, _currentState.meteo.humidity,
|
||||
_currentState.wavelength, &refr.refa, &refr.refb);
|
||||
@ -417,7 +422,7 @@ public:
|
||||
coord_t& alt,
|
||||
eo_t& eo)
|
||||
{
|
||||
std::lock_guard lock{_stateMutex};
|
||||
std::lock_guard lock{*_stateMutex};
|
||||
|
||||
auto dut1 = _currentState._bulletinA.DUT1(juldate.mjd);
|
||||
|
||||
@ -459,7 +464,7 @@ public:
|
||||
|
||||
error_t obs2icrs(MccCoordPairKind coord_kind, coord_t x, coord_t y, juldate_t juldate, coord_t ra, coord_t dec)
|
||||
{
|
||||
std::lock_guard lock{_stateMutex};
|
||||
std::lock_guard lock{*_stateMutex};
|
||||
|
||||
auto dut1 = _currentState._bulletinA.DUT1(juldate.mjd);
|
||||
|
||||
@ -516,7 +521,7 @@ public:
|
||||
|
||||
error_t hadec2azalt(coord_t ha, coord_t dec, coord_t& az, coord_t& alt)
|
||||
{
|
||||
std::lock_guard lock{_stateMutex};
|
||||
std::lock_guard lock{*_stateMutex};
|
||||
|
||||
double r_az, r_alt;
|
||||
eraHd2ae(ha, dec, _currentState.lat, &r_az, &r_alt);
|
||||
@ -529,7 +534,7 @@ public:
|
||||
|
||||
error_t azalt2hadec(coord_t az, coord_t alt, coord_t& ha, coord_t& dec)
|
||||
{
|
||||
std::lock_guard lock{_stateMutex};
|
||||
std::lock_guard lock{*_stateMutex};
|
||||
|
||||
double r_ha, r_dec;
|
||||
|
||||
@ -544,7 +549,7 @@ public:
|
||||
|
||||
error_t hadec2pa(coord_t ha, coord_t dec, pa_t& pa)
|
||||
{
|
||||
std::lock_guard lock{_stateMutex};
|
||||
std::lock_guard lock{*_stateMutex};
|
||||
|
||||
pa = eraHd2pa(ha, dec, _currentState.lat);
|
||||
|
||||
@ -566,7 +571,7 @@ public:
|
||||
protected:
|
||||
engine_state_t _currentState{};
|
||||
|
||||
mutable std::mutex _stateMutex;
|
||||
std::unique_ptr<std::mutex> _stateMutex;
|
||||
};
|
||||
|
||||
} // namespace mcc::astrom::erfa
|
||||
|
||||
@ -297,7 +297,7 @@ concept mcc_mount_pec_c = requires(T t) {
|
||||
|
||||
// a class that contains at least celestial (equatorial and horizontal) and harware coordinates
|
||||
template <typename T>
|
||||
concept mcc_mount_telemetry_data_c = requires(T telemetry) {
|
||||
concept mcc_mount_telemetry_data_c = std::movable<T> && requires(T telemetry) {
|
||||
typename T::coord_t;
|
||||
typename T::time_point_t;
|
||||
|
||||
@ -423,8 +423,8 @@ concept mcc_guiding_model_c = requires(T t) {
|
||||
template <typename T, typename TelemetryDataT>
|
||||
concept mcc_prohibited_zone_c =
|
||||
mcc_mount_telemetry_data_c<TelemetryDataT> && std::movable<T> && requires(T t, const T t_const) {
|
||||
typename T::coord_t;
|
||||
typename T::time_point_t;
|
||||
// typename T::coord_t;
|
||||
// typename T::time_point_t;
|
||||
requires mcc_time_duration_c<typename T::duration_t>;
|
||||
|
||||
// static constexpr member to represent inifite duration
|
||||
@ -436,6 +436,15 @@ concept mcc_prohibited_zone_c =
|
||||
};
|
||||
};
|
||||
|
||||
// static constexpr member to represent zero duration
|
||||
requires requires {
|
||||
requires std::same_as<decltype(T::zeroDuration), typename T::duration_t>;
|
||||
[]() {
|
||||
constexpr auto val = T::zeroDuration;
|
||||
return val;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
// the type 'T' must define a static constexpr member of type MccCoordPairKind
|
||||
// to declarate type of coordinate pair used to describe the zone.
|
||||
@ -491,6 +500,11 @@ concept mcc_prohibited_zone_c =
|
||||
{ t.timeFrom(std::declval<const TelemetryDataT&>()) } -> std::same_as<typename T::duration_t>;
|
||||
};
|
||||
|
||||
// an input range of prohibited zones
|
||||
template <typename T, typename TelemetryDataT>
|
||||
concept mcc_irange_of_pzones_c = mcc_mount_telemetry_data_c<TelemetryDataT> && std::ranges::input_range<T> &&
|
||||
mcc_prohibited_zone_c<std::ranges::range_value_t<T>, TelemetryDataT>;
|
||||
|
||||
|
||||
|
||||
/* MOUNT GENERIC CONTROLS */
|
||||
@ -511,7 +525,9 @@ concept mcc_mount_controls_c = requires(T t) {
|
||||
// []<mcc_prohibited_zone_c<typename decltype(t.telemetry)::mount_telemetry_data_t>... Ts>(std::tuple<Ts...>) {
|
||||
// }(t.prohibitedZones);
|
||||
|
||||
requires mcc_tuple_c<decltype(t.prohibitedZones)>;
|
||||
// requires mcc_tuple_c<decltype(t.prohibitedZones)>;
|
||||
requires mcc_irange_of_pzones_c<decltype(t.prohibitedZones),
|
||||
typename decltype(t.telemetry)::mount_telemetry_data_t>;
|
||||
};
|
||||
|
||||
|
||||
@ -530,18 +546,24 @@ concept mcc_mount_c = requires(T t) {
|
||||
requires mcc_astrom_engine_c<typename T::astrom_engine_t>;
|
||||
requires mcc_mount_pec_c<typename T::pec_t>;
|
||||
requires mcc_mount_hardware_c<typename T::hardware_t>;
|
||||
// requires mcc_slew_model_c<typename T::slew_model_t, typename T::mount_telemetry_t>;
|
||||
requires mcc_slew_model_c<typename T::slew_model_t>;
|
||||
// requires mcc_guiding_model_c<typename T::guiding_model_t, typename T::mount_telemetry_t>;
|
||||
requires mcc_guiding_model_c<typename T::guiding_model_t>;
|
||||
|
||||
// requires std::same_as<typename T::slew_params_t, typename T::slew_model_t::slew_params_t>;
|
||||
// public methods
|
||||
{
|
||||
t.mountTelemetryData(std::declval<typename T::mount_telemetry_data_t&>())
|
||||
} -> std::same_as<typename T::mount_telemetry_t::error_t>;
|
||||
|
||||
// public method
|
||||
{ t.mountTelemetryData() } -> std::same_as<typename T::mount_telemetry_data_t>;
|
||||
{
|
||||
t.slewMount(std::declval<typename T::slew_model_t::slew_point_t>())
|
||||
} -> std::same_as<typename T::slew_model_t::error_t>;
|
||||
|
||||
{
|
||||
t.guidingTarget(std::declval<typename T::guiding_model_t::guiding_point_t>())
|
||||
} -> std::same_as<typename T::guiding_model_t::error_t>;
|
||||
};
|
||||
|
||||
// generic with logging methods
|
||||
// generic with public logging methods
|
||||
template <typename T>
|
||||
concept mcc_log_mount_c = mcc_mount_c<T> && mcc_logger_c<T>;
|
||||
|
||||
|
||||
@ -23,10 +23,7 @@ enum class MccMountDefaultPECErrorCode : int { ERROR_OK, ERROR_INVALID_INPUTS_BI
|
||||
struct MccMountDefaultPECCategory : public std::error_category {
|
||||
MccMountDefaultPECCategory() : std::error_category() {}
|
||||
|
||||
const char* name() const noexcept
|
||||
{
|
||||
return "ADC_GENERIC_DEVICE";
|
||||
}
|
||||
const char* name() const noexcept { return "ADC_GENERIC_DEVICE"; }
|
||||
|
||||
std::string message(int ec) const
|
||||
{
|
||||
@ -140,14 +137,41 @@ public:
|
||||
: _pecData(std::move(pdata)),
|
||||
_phi(_pecData.siteLatitude),
|
||||
_geomCoeffs(_pecData.geomCoefficients),
|
||||
_bsplCoeffs(_pecData.bsplineCoefficients)
|
||||
_bsplCoeffs(_pecData.bsplineCoefficients),
|
||||
_pecDataMutex(new std::mutex)
|
||||
{
|
||||
}
|
||||
|
||||
MccMountDefaultPEC(const MccMountDefaultPEC&) = delete;
|
||||
MccMountDefaultPEC& operator=(const MccMountDefaultPEC&) = delete;
|
||||
|
||||
MccMountDefaultPEC(MccMountDefaultPEC&& other)
|
||||
: _pecData(std::move(other._pecData)),
|
||||
_phi(_pecData.siteLatitude),
|
||||
_geomCoeffs(_pecData.geomCoefficients),
|
||||
_bsplCoeffs(_pecData.bsplineCoefficients),
|
||||
_pecDataMutex(std::move(other._pecDataMutex))
|
||||
{
|
||||
}
|
||||
|
||||
MccMountDefaultPEC& operator=(MccMountDefaultPEC&& other)
|
||||
{
|
||||
if (this == &other) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
_pecData = std::move(other._pecData);
|
||||
_phi = _pecData.siteLatitude;
|
||||
_geomCoeffs = _pecData.geomCoefficients;
|
||||
_bsplCoeffs = _pecData.bsplineCoefficients;
|
||||
_pecDataMutex = std::move(other._pecDataMutex);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
void setData(pec_data_t pdata)
|
||||
{
|
||||
std::lock_guard lock(_pecDataMutex);
|
||||
std::lock_guard lock(*_pecDataMutex);
|
||||
|
||||
_pecData = std::move(pdata);
|
||||
_phi = _pecData.siteLatitude;
|
||||
@ -158,21 +182,21 @@ public:
|
||||
|
||||
pec_data_t getData() const
|
||||
{
|
||||
std::lock_guard lock(_pecDataMutex);
|
||||
std::lock_guard lock(*_pecDataMutex);
|
||||
|
||||
return _pecData;
|
||||
}
|
||||
|
||||
void setType(MccMountDefaultPECType type)
|
||||
{
|
||||
std::lock_guard lock(_pecDataMutex);
|
||||
std::lock_guard lock(*_pecDataMutex);
|
||||
|
||||
_pecData.type = type;
|
||||
}
|
||||
|
||||
MccMountDefaultPECType getType() const
|
||||
{
|
||||
std::lock_guard lock(_pecDataMutex);
|
||||
std::lock_guard lock(*_pecDataMutex);
|
||||
|
||||
return _pecData.type;
|
||||
}
|
||||
@ -183,7 +207,7 @@ public:
|
||||
// so, input x and y are assumed to be mount axis encoder coordinates
|
||||
error_t compute(const coord_t& x, const coord_t& y, pec_result_t& res)
|
||||
{
|
||||
std::lock_guard lock(_pecDataMutex);
|
||||
std::lock_guard lock(*_pecDataMutex);
|
||||
|
||||
if constexpr (mcc_is_equatorial_mount<MOUNT_TYPE>) { // equatorial
|
||||
if (_pecData.type == MccMountDefaultPECType::PEC_TYPE_GEOMETRY) {
|
||||
@ -249,70 +273,6 @@ public:
|
||||
return MccMountDefaultPECErrorCode::ERROR_OK;
|
||||
}
|
||||
|
||||
// from celestial to encoder (use of iterative scheme)
|
||||
error_t reverseCompute(const coord_t& x, const coord_t& y, pec_result_t& res, coord_t eps, size_t max_iter = 5)
|
||||
{
|
||||
coord_t e2 = eps * eps;
|
||||
|
||||
coord_t xi = x, yi = y;
|
||||
coord_t xe, ye;
|
||||
size_t iter = 1;
|
||||
|
||||
// the first iteration
|
||||
auto err = compute(x, y, res);
|
||||
|
||||
if (!err) {
|
||||
// 'encoder' cocordinates
|
||||
xe = x - res.dx;
|
||||
ye = y - res.dy;
|
||||
|
||||
err = compute(xe, ye, res); // to celestial
|
||||
if (err) {
|
||||
return MccMountDefaultPECErrorCode::ERROR_INVALID_INPUTS_BISPLEV;
|
||||
}
|
||||
|
||||
xi = xe + res.dx; // celestial
|
||||
yi = ye + res.dy;
|
||||
|
||||
auto rx = (x - xi);
|
||||
auto ry = (y - yi);
|
||||
auto d = rx * rx + ry * ry;
|
||||
|
||||
bool ok = d <= e2;
|
||||
if (ok) {
|
||||
return MccMountDefaultPECErrorCode::ERROR_OK;
|
||||
}
|
||||
|
||||
while (iter < max_iter) {
|
||||
err = compute(xi, yi, res); // to encoder
|
||||
if (err) {
|
||||
return MccMountDefaultPECErrorCode::ERROR_INVALID_INPUTS_BISPLEV;
|
||||
}
|
||||
xe = x - res.dx;
|
||||
ye = y - res.dy;
|
||||
|
||||
err = compute(xe, ye, res); // to celestial
|
||||
if (err) {
|
||||
return MccMountDefaultPECErrorCode::ERROR_INVALID_INPUTS_BISPLEV;
|
||||
}
|
||||
|
||||
xi = xe + res.dx; // celestial
|
||||
yi = ye + res.dy;
|
||||
|
||||
ok = ((x - xi) * (x - xi) + (y - yi) * (y - yi)) <= e2;
|
||||
if (ok) {
|
||||
return MccMountDefaultPECErrorCode::ERROR_OK;
|
||||
}
|
||||
|
||||
++iter;
|
||||
}
|
||||
|
||||
err = MccMountDefaultPECErrorCode::ERROR_EXCEED_MAX_ITERS;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
pec_data_t _pecData;
|
||||
@ -320,7 +280,7 @@ private:
|
||||
pec_geom_coeffs_t& _geomCoeffs;
|
||||
pec_bspline_coeffs_t& _bsplCoeffs;
|
||||
|
||||
mutable std::mutex _pecDataMutex;
|
||||
std::unique_ptr<std::mutex> _pecDataMutex;
|
||||
};
|
||||
|
||||
|
||||
@ -328,6 +288,7 @@ typedef MccMountDefaultPEC<MccMountType::ALTAZ_TYPE> MccMountDefaultAltAzPec;
|
||||
typedef MccMountDefaultPEC<MccMountType::FORK_TYPE> MccMountDefaultForkPec;
|
||||
|
||||
static_assert(traits::mcc_mount_pec_c<MccMountDefaultForkPec>, "");
|
||||
static_assert(std::movable<MccMountDefaultForkPec>);
|
||||
|
||||
|
||||
} // namespace mcc
|
||||
|
||||
@ -45,8 +45,6 @@ public:
|
||||
static constexpr duration_t infiniteDuration{std::numeric_limits<double>::infinity()};
|
||||
static constexpr duration_t zeroDuration{0.0};
|
||||
|
||||
//
|
||||
// TODO: add context (e.g. TT-TAI, UT1-UTC, geo location and so on)!!!
|
||||
MccAltLimitPZ(const MccAngle& alt_limit, const MccAngle& lat)
|
||||
// : MccProhibitedZone(KIND == MccAltLimitKind::MIN_ALT_LIMIT ? "MINALT-ZONE"
|
||||
// : KIND == MccAltLimitKind::MAX_ALT_LIMIT ? "MAXALT-ZONE"
|
||||
|
||||
@ -148,6 +148,32 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
MccMountTelemetry(MccMountTelemetry&& other)
|
||||
: base_t(std::move(other)),
|
||||
_data(std::move(other._data)),
|
||||
_hardware(other._hardware),
|
||||
_updateMutex(std::move(other._updateMutex)),
|
||||
_updateCondVar(std::move(other._updateCondVar))
|
||||
{
|
||||
}
|
||||
|
||||
MccMountTelemetry& operator=(MccMountTelemetry&& other)
|
||||
{
|
||||
if (this == &other) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
base_t::operator=(std::move(other));
|
||||
|
||||
_data = std::move(other._data);
|
||||
_hardware = other._hardware;
|
||||
_updateMutex = std::move(other._updateMutex);
|
||||
_updateCondVar = std::move(other._updateCondVar);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
virtual ~MccMountTelemetry() = default;
|
||||
|
||||
|
||||
@ -155,7 +181,7 @@ public:
|
||||
template <traits::mcc_celestial_point_c PointT>
|
||||
error_t setTarget(PointT tag_point)
|
||||
{
|
||||
std::lock_guard lock{_updateMutex};
|
||||
std::lock_guard lock{*_updateMutex};
|
||||
|
||||
auto err = this->toICRS(tag_point, _data.utc, _data.tagRA_ICRS, _data.tagDEC_ICRS);
|
||||
if (!err) {
|
||||
@ -168,7 +194,7 @@ public:
|
||||
// target - mount coordinate difference
|
||||
auto targetToMountDiff()
|
||||
{
|
||||
std::lock_guard lk(_updateMutex);
|
||||
std::lock_guard lk(*_updateMutex);
|
||||
|
||||
coord_diff_t result;
|
||||
|
||||
@ -232,13 +258,16 @@ public:
|
||||
|
||||
|
||||
|
||||
// correction for PEC
|
||||
// compute corrections for PEC and celestial apparent coordinates
|
||||
if constexpr (base_t::equatorialMount) {
|
||||
res_err = this->toApparent(point_t{.coordPairKind = MccCoordPairKind::COORDS_KIND_XY,
|
||||
.x = current_data.mntPosX,
|
||||
.y = current_data.mntPosY},
|
||||
current_data.utc, current_data.mntHA, current_data.mntDEC);
|
||||
if (!res_err) {
|
||||
current_data.pecX = current_data.mntHA - current_data.mntPosX;
|
||||
current_data.pecY = current_data.mntDEC - current_data.mntPosY;
|
||||
|
||||
ast_err = this->_astromEngine.hadec2azalt(current_data.mntHA, current_data.mntDEC, current_data.mntAZ,
|
||||
current_data.mntALT);
|
||||
}
|
||||
@ -248,6 +277,9 @@ public:
|
||||
.y = current_data.mntPosY},
|
||||
current_data.utc, current_data.mntAZ, current_data.mntALT);
|
||||
if (!res_err) {
|
||||
current_data.pecX = current_data.mntAZ - current_data.mntPosX;
|
||||
current_data.pecY = current_data.mntALT - current_data.mntPosY;
|
||||
|
||||
ast_err = this->_astromEngine.azalt2hadec(current_data.mntAZ, current_data.mntALT, current_data.mntHA,
|
||||
current_data.mntDEC);
|
||||
}
|
||||
@ -284,12 +316,12 @@ public:
|
||||
return MccMountTelemetryAstromTransformErrorCode::ERROR_ASTROMETRY_COMP;
|
||||
}
|
||||
|
||||
std::lock_guard lock{_updateMutex};
|
||||
std::lock_guard lock{*_updateMutex};
|
||||
|
||||
_data = std::move(current_data);
|
||||
|
||||
// notify all threads for new telemetry data
|
||||
_updateCondVar.notify_all();
|
||||
_updateCondVar->notify_all();
|
||||
|
||||
return MccMountTelemetryErrorCode::ERROR_OK;
|
||||
}
|
||||
@ -297,7 +329,7 @@ public:
|
||||
|
||||
error_t data(mount_telemetry_data_t& data)
|
||||
{
|
||||
std::lock_guard lock{_updateMutex};
|
||||
std::lock_guard lock{*_updateMutex};
|
||||
|
||||
data = _data;
|
||||
|
||||
@ -310,9 +342,9 @@ public:
|
||||
{
|
||||
auto timeout_tp = std::chrono::steady_clock::now() + timeout;
|
||||
|
||||
std::unique_lock lk(_updateMutex);
|
||||
std::unique_lock lk(*_updateMutex);
|
||||
|
||||
auto res = _updateCondVar.wait_until(
|
||||
auto res = _updateCondVar->wait_until(
|
||||
lk, timeout_tp, [last_time_point = _data.time_point, this]() { return last_time_point < _data.timepoint; });
|
||||
if (res == std::cv_status::timeout) {
|
||||
return MccMountTelemetryErrorCode::ERROR_DATA_TIMEOUT;
|
||||
@ -327,8 +359,8 @@ protected:
|
||||
mount_telemetry_data_t _data{};
|
||||
hardware_t& _hardware;
|
||||
|
||||
std::mutex _updateMutex;
|
||||
std::condition_variable _updateCondVar;
|
||||
std::unique_ptr<std::mutex> _updateMutex;
|
||||
std::unique_ptr<std::condition_variable> _updateCondVar;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -109,6 +109,41 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
MccMountTelemetryAstromTransform(MccMountTelemetryAstromTransform&& other)
|
||||
: _pec(other._pec), _astromEngine(other._astromEngine)
|
||||
{
|
||||
}
|
||||
|
||||
MccMountTelemetryAstromTransform& operator=(MccMountTelemetryAstromTransform&& other)
|
||||
{
|
||||
if (this == &other) {
|
||||
return;
|
||||
}
|
||||
|
||||
_pec = other._pec;
|
||||
_astromEngine = other._astromEngine;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
MccMountTelemetryAstromTransform(const MccMountTelemetryAstromTransform& other)
|
||||
: _pec(other._pec), _astromEngine(other._astromEngine)
|
||||
{
|
||||
}
|
||||
|
||||
MccMountTelemetryAstromTransform& operator=(const MccMountTelemetryAstromTransform& other)
|
||||
{
|
||||
if (this == &other) {
|
||||
return;
|
||||
}
|
||||
|
||||
_pec = other._pec;
|
||||
_astromEngine = other._astromEngine;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
virtual ~MccMountTelemetryAstromTransform() = default;
|
||||
|
||||
template <traits::mcc_celestial_point_c CT>
|
||||
@ -189,9 +224,12 @@ public:
|
||||
}
|
||||
} else if (coord.coordPairKind == MccCoordPairKind::COORDS_KIND_AZALT) { // from app AZ-ALT
|
||||
if constexpr (equatorialMount) {
|
||||
ast_err = azalt2hadec(coord.x, coord.y, X_app, Y_app); // compute HA-DEC
|
||||
ast_err = _astromEngine.azalt2hadec(coord.x, coord.y, X_app, Y_app); // compute HA-DEC
|
||||
if (!ast_err) { // compute CIO RA (as XX_app)
|
||||
ast_err = toApparent(X_app, Y_app, X_app, Y_app, XX_app);
|
||||
coord.coordPairKind == MccCoordPairKind::COORDS_KIND_HADEC_APP;
|
||||
coord.x = X_app;
|
||||
coord.y = Y_app;
|
||||
ast_err = toApparent(std::move(coord), std::move(time_point), X_app, Y_app, XX_app);
|
||||
}
|
||||
} else if (altAzMount) {
|
||||
X_app = coord.x;
|
||||
@ -465,4 +503,5 @@ protected:
|
||||
pec_t& _pec;
|
||||
};
|
||||
|
||||
|
||||
} // namespace mcc
|
||||
|
||||
@ -95,5 +95,29 @@ auto mccCheckInZonePZTuple(const TelemetryDataT& telemetry_data,
|
||||
}(std::make_index_sequence<sizeof...(ZTs)>{});
|
||||
}
|
||||
|
||||
template <traits::mcc_mount_telemetry_data_c TelemetryDataT,
|
||||
traits::mcc_irange_of_pzones_c<TelemetryDataT> RT,
|
||||
std::ranges::output_range<bool> ResT>
|
||||
auto mccCheckInZonePZRange(const TelemetryDataT& telemetry_data, const RT& pzones, ResT& result)
|
||||
{
|
||||
auto Npz = std::ranges::distance(pzones);
|
||||
if (!Npz) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto res_sz = std::ranges::distance(result);
|
||||
|
||||
size_t i = 1;
|
||||
auto res_iter = result.begin();
|
||||
for (auto& el : pzones) {
|
||||
if (i > res_sz) {
|
||||
std::back_inserter(result) = el.inZone(telemetry_data);
|
||||
} else {
|
||||
std::ranges::advance(res_iter, 1);
|
||||
*res_iter = el.inZone(telemetry_data);
|
||||
}
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace mcc
|
||||
|
||||
@ -150,10 +150,25 @@ public:
|
||||
init(telemetry, hardware, prohibited_zone);
|
||||
}
|
||||
|
||||
MccSimpleSlewModel(MccSimpleSlewModel&&) = default;
|
||||
MccSimpleSlewModel& operator=(MccSimpleSlewModel&&) = default;
|
||||
MccSimpleSlewModel(const MccSimpleSlewModel&) = default;
|
||||
MccSimpleSlewModel& operator=(const MccSimpleSlewModel&) = default;
|
||||
MccSimpleSlewModel(MccSimpleSlewModel&& other)
|
||||
: _stopRequested(other._stopRequested.load()), _slewFunc(std::move(other._slewFunc))
|
||||
{
|
||||
}
|
||||
|
||||
MccSimpleSlewModel& operator=(MccSimpleSlewModel&& other)
|
||||
{
|
||||
if (this == &other) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
_stopRequested = other._stopRequested.load();
|
||||
_slewFunc = std::move(_slewFunc);
|
||||
|
||||
return *this;
|
||||
};
|
||||
|
||||
MccSimpleSlewModel(const MccSimpleSlewModel&) = delete;
|
||||
MccSimpleSlewModel& operator=(const MccSimpleSlewModel&) = delete;
|
||||
|
||||
virtual ~MccSimpleSlewModel()
|
||||
{
|
||||
@ -422,5 +437,6 @@ protected:
|
||||
}
|
||||
};
|
||||
|
||||
static_assert(std::movable<MccSimpleSlewModel<>>);
|
||||
|
||||
} // namespace mcc
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user