remove guiding model
now it are only slewing and tracking states
This commit is contained in:
parent
460fc360c6
commit
2478c1e8d2
@ -14,3 +14,4 @@ set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH})
|
|||||||
|
|
||||||
add_subdirectory(cxx)
|
add_subdirectory(cxx)
|
||||||
add_subdirectory(mcc)
|
add_subdirectory(mcc)
|
||||||
|
add_subdirectory(asibfm700)
|
||||||
|
|||||||
15
asibfm700/CMakeLists.txt
Normal file
15
asibfm700/CMakeLists.txt
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.14)
|
||||||
|
|
||||||
|
# set(CMAKE_BUILD_TYPE Release)
|
||||||
|
|
||||||
|
set(CMAKE_CXX_STANDARD 23)
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
|
||||||
|
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake")
|
||||||
|
|
||||||
|
|
||||||
|
set(ASIBFM700_LIB_SRC asibfm700_common.h asibfm700_servocontroller.h asibfm700_servocontroller.cpp)
|
||||||
|
|
||||||
|
set(ASIBFM700_LIB asibfm700mount)
|
||||||
|
add_library(${ASIBFM700_LIB} STATIC ${ASIBFM700_LIB_SRC})
|
||||||
|
target_link_libraries(${ASIBFM700_LIB} PRIVATE mcc1)
|
||||||
11
asibfm700/asibfm700_common.h
Normal file
11
asibfm700/asibfm700_common.h
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
/* AstroSib FORK MOUNT FM-700 CONTROL LIBRARY */
|
||||||
|
|
||||||
|
|
||||||
|
/* COMMON LIBRARY DEFINITIONS */
|
||||||
|
|
||||||
|
namespace asibfm700
|
||||||
|
{
|
||||||
|
|
||||||
|
} // namespace asibfm700
|
||||||
84
asibfm700/asibfm700_servocontroller.cpp
Normal file
84
asibfm700/asibfm700_servocontroller.cpp
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
#include "asibfm700_servocontroller.h"
|
||||||
|
|
||||||
|
namespace asibfm700
|
||||||
|
{
|
||||||
|
|
||||||
|
AsibFM700ServoController::AsibFM700ServoController() : _hardwareConfig(), _setStateMutex(new std::mutex) {}
|
||||||
|
|
||||||
|
AsibFM700ServoController::AsibFM700ServoController(hardware_config_t config) : AsibFM700ServoController()
|
||||||
|
{
|
||||||
|
_hardwareConfig = std::move(config);
|
||||||
|
|
||||||
|
_hardwareConfig.devConfig.MountDevPath = const_cast<char*>(_hardwareConfig.MountDevPath.c_str());
|
||||||
|
_hardwareConfig.devConfig.EncoderDevPath = const_cast<char*>(_hardwareConfig.EncoderDevPath.c_str());
|
||||||
|
_hardwareConfig.devConfig.EncoderXDevPath = const_cast<char*>(_hardwareConfig.EncoderXDevPath.c_str());
|
||||||
|
_hardwareConfig.devConfig.EncoderYDevPath = const_cast<char*>(_hardwareConfig.EncoderYDevPath.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
constexpr std::string_view AsibFM700ServoController::hardwareName() const
|
||||||
|
{
|
||||||
|
return "Sidereal-ServoControllerII";
|
||||||
|
}
|
||||||
|
|
||||||
|
AsibFM700ServoController::error_t AsibFM700ServoController::hardwareStop()
|
||||||
|
{
|
||||||
|
return static_cast<AsibFM700ServoControllerErrorCode>(Mount.stop());
|
||||||
|
}
|
||||||
|
|
||||||
|
AsibFM700ServoController::error_t AsibFM700ServoController::hardwareInit()
|
||||||
|
{
|
||||||
|
return static_cast<AsibFM700ServoControllerErrorCode>(Mount.init(&_hardwareConfig.devConfig));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
AsibFM700ServoController::error_t AsibFM700ServoController::hardwareSetState(hardware_state_t state)
|
||||||
|
{
|
||||||
|
// time point from sidservo library is 'double' number represented UNIXTIME with
|
||||||
|
// microseconds/nanoseconds precision
|
||||||
|
double tp = std::chrono::duration<double>(state.time_point.time_since_epoch()).count();
|
||||||
|
|
||||||
|
std::lock_guard lock{*_setStateMutex};
|
||||||
|
|
||||||
|
// according to"SiTech protocol notes" X is DEC-axis and Y is HA-axis
|
||||||
|
coordval_pair_t cvalpair{.X{.val = state.Y, .t = tp}, .Y{.val = state.X, .t = tp}};
|
||||||
|
coordpair_t cpair{.X = state.Y, .Y = state.X};
|
||||||
|
|
||||||
|
// correctTo is asynchronous function!!!
|
||||||
|
//
|
||||||
|
// according to the Eddy's implementation of the LibSidServo library it is safe
|
||||||
|
// to pass the addresses of 'cvalpair' and 'cpair' automatic variables
|
||||||
|
auto err = static_cast<AsibFM700ServoControllerErrorCode>(Mount.correctTo(&cvalpair, &cpair));
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
AsibFM700ServoController::error_t AsibFM700ServoController::hardwareGetState(hardware_state_t* state)
|
||||||
|
{
|
||||||
|
using tp_t = decltype(hardware_state_t::time_point);
|
||||||
|
|
||||||
|
mountdata_t mdata;
|
||||||
|
|
||||||
|
error_t err = static_cast<AsibFM700ServoControllerErrorCode>(Mount.getMountData(&mdata));
|
||||||
|
if (!err) {
|
||||||
|
// time point from sidservo library is 'double' number represented UNIXTIME with
|
||||||
|
// microseconds/nanoseconds precision (must be equal for encXposition and encYposition)
|
||||||
|
|
||||||
|
using secs_t = std::chrono::duration<double>;
|
||||||
|
|
||||||
|
secs_t secs = secs_t{mdata.encXposition.t};
|
||||||
|
state->time_point = tp_t{std::chrono::duration_cast<tp_t::duration>(secs)};
|
||||||
|
|
||||||
|
// according to "SiTech protocol notes" X is DEC-axis and Y is HA-axis
|
||||||
|
state->X = mdata.encYposition.val;
|
||||||
|
state->Y = mdata.encXposition.val;
|
||||||
|
|
||||||
|
state->speedX = mdata.encYspeed.val;
|
||||||
|
state->speedY = mdata.encXspeed.val;
|
||||||
|
}
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace asibfm700
|
||||||
124
asibfm700/asibfm700_servocontroller.h
Normal file
124
asibfm700/asibfm700_servocontroller.h
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <mcc_defaults.h>
|
||||||
|
#include <mcc_generics.h>
|
||||||
|
|
||||||
|
#include "../LibSidServo/sidservo.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace asibfm700
|
||||||
|
{
|
||||||
|
|
||||||
|
/* error codes enum definition */
|
||||||
|
|
||||||
|
enum class AsibFM700ServoControllerErrorCode : int {
|
||||||
|
// error codes from sidservo library
|
||||||
|
ERROR_OK = MCC_E_OK,
|
||||||
|
ERROR_FATAL = MCC_E_FATAL,
|
||||||
|
ERROR_BADFORMAT = MCC_E_BADFORMAT,
|
||||||
|
ERROR_ENCODERDEV = MCC_E_ENCODERDEV,
|
||||||
|
ERROR_MOUNTDEV = MCC_E_MOUNTDEV,
|
||||||
|
ERROR_FAILED = MCC_E_FAILED,
|
||||||
|
// my codes ...
|
||||||
|
};
|
||||||
|
|
||||||
|
// error category
|
||||||
|
struct AsibFM700HardwareErrorCategory : public std::error_category {
|
||||||
|
const char* name() const noexcept;
|
||||||
|
std::string message(int ec) const;
|
||||||
|
|
||||||
|
static const AsibFM700HardwareErrorCategory& get();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static inline std::error_code make_error_code(AsibFM700ServoControllerErrorCode ec)
|
||||||
|
{
|
||||||
|
return std::error_code(static_cast<int>(ec), AsibFM700HardwareErrorCategory::get());
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace asibfm700
|
||||||
|
|
||||||
|
|
||||||
|
namespace std
|
||||||
|
{
|
||||||
|
|
||||||
|
template <>
|
||||||
|
class is_error_code_enum<asibfm700::AsibFM700ServoControllerErrorCode> : public true_type
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace std
|
||||||
|
|
||||||
|
|
||||||
|
namespace asibfm700
|
||||||
|
{
|
||||||
|
|
||||||
|
class AsibFM700ServoController final
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef std::error_code error_t;
|
||||||
|
|
||||||
|
enum class hardware_moving_state_t : int {
|
||||||
|
HW_MOVE_STOPPED,
|
||||||
|
HW_MOVE_SLEWING,
|
||||||
|
HW_MOVE_ADJUSTING,
|
||||||
|
HW_MOVE_TRACKING,
|
||||||
|
HW_MOVE_GUIDING
|
||||||
|
};
|
||||||
|
|
||||||
|
struct hardware_state_t {
|
||||||
|
static constexpr mcc::MccCoordPairKind pair_kind = mcc::MccCoordPairKind::COORDS_KIND_HADEC_APP;
|
||||||
|
mcc::MccTimePoint time_point;
|
||||||
|
|
||||||
|
double X, Y, speedX, speedY;
|
||||||
|
|
||||||
|
hardware_moving_state_t moving_state;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct hardware_config_t {
|
||||||
|
// the 'char*' fields from conf_t:
|
||||||
|
// wrap it to std::string
|
||||||
|
std::string MountDevPath;
|
||||||
|
std::string EncoderDevPath;
|
||||||
|
std::string EncoderXDevPath;
|
||||||
|
std::string EncoderYDevPath;
|
||||||
|
|
||||||
|
conf_t devConfig;
|
||||||
|
hardware_configuration_t hwConfig;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* constructors and destructor */
|
||||||
|
|
||||||
|
AsibFM700ServoController();
|
||||||
|
|
||||||
|
AsibFM700ServoController(hardware_config_t config);
|
||||||
|
|
||||||
|
AsibFM700ServoController(const AsibFM700ServoController&) = delete;
|
||||||
|
AsibFM700ServoController& operator=(const AsibFM700ServoController&) = delete;
|
||||||
|
|
||||||
|
AsibFM700ServoController(AsibFM700ServoController&&);
|
||||||
|
AsibFM700ServoController& operator=(AsibFM700ServoController&&);
|
||||||
|
|
||||||
|
~AsibFM700ServoController();
|
||||||
|
|
||||||
|
/* public methods */
|
||||||
|
|
||||||
|
constexpr std::string_view hardwareName() const;
|
||||||
|
|
||||||
|
error_t hardwareSetState(hardware_state_t state);
|
||||||
|
error_t hardwareGetState(hardware_state_t* state);
|
||||||
|
|
||||||
|
error_t hardwareStop();
|
||||||
|
error_t hardwareInit();
|
||||||
|
|
||||||
|
void hardwareUpdateConfig(conf_t cfg);
|
||||||
|
void hardwareUpdateConfig(hardware_configuration_t cfg);
|
||||||
|
|
||||||
|
private:
|
||||||
|
hardware_config_t _hardwareConfig;
|
||||||
|
|
||||||
|
std::unique_ptr<std::mutex> _setStateMutex;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace asibfm700
|
||||||
@ -70,8 +70,7 @@ include_directories(${BSPLINES_INCLUDE_DIR})
|
|||||||
set(MCC_LIBRARY_SRC1 mcc_generics.h mcc_defaults.h mcc_traits.h mcc_utils.h
|
set(MCC_LIBRARY_SRC1 mcc_generics.h mcc_defaults.h mcc_traits.h mcc_utils.h
|
||||||
mcc_ccte_iers.h mcc_ccte_iers_default.h mcc_ccte_erfa.h mcc_pcm.h mcc_telemetry.h
|
mcc_ccte_iers.h mcc_ccte_iers_default.h mcc_ccte_erfa.h mcc_pcm.h mcc_telemetry.h
|
||||||
mcc_angle.h mcc_pzone.h mcc_pzone_container.h mcc_finite_state_machine.h
|
mcc_angle.h mcc_pzone.h mcc_pzone_container.h mcc_finite_state_machine.h
|
||||||
mcc_generic_mount.h mcc_tracking_model.h mcc_slewing_model.h mcc_guiding_model.h
|
mcc_generic_mount.h mcc_tracking_model.h mcc_slewing_model.h mcc_moving_model_common.h)
|
||||||
mcc_moving_model_common.h)
|
|
||||||
|
|
||||||
list(APPEND MCC_LIBRARY_SRC1 mcc_spdlog.h)
|
list(APPEND MCC_LIBRARY_SRC1 mcc_spdlog.h)
|
||||||
|
|
||||||
@ -79,6 +78,11 @@ set(MCC_LIBRARY1 mcc1)
|
|||||||
add_library(${MCC_LIBRARY1} INTERFACE ${MCC_LIBRARY_SRC1})
|
add_library(${MCC_LIBRARY1} INTERFACE ${MCC_LIBRARY_SRC1})
|
||||||
target_compile_features(${MCC_LIBRARY1} INTERFACE cxx_std_23)
|
target_compile_features(${MCC_LIBRARY1} INTERFACE cxx_std_23)
|
||||||
target_include_directories(${MCC_LIBRARY1} INTERFACE ${ERFA_INCLUDE_DIR} ${BSPLINES_INCLUDE_DIR})
|
target_include_directories(${MCC_LIBRARY1} INTERFACE ${ERFA_INCLUDE_DIR} ${BSPLINES_INCLUDE_DIR})
|
||||||
|
target_include_directories(${MCC_LIBRARY1} INTERFACE
|
||||||
|
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
|
||||||
|
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/mcc>
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
option(WITH_TESTS "Build tests" ON)
|
option(WITH_TESTS "Build tests" ON)
|
||||||
|
|
||||||
|
|||||||
@ -37,14 +37,14 @@ template <mcc_hardware_c HardwareT,
|
|||||||
mcc_pzone_container_c PZoneContT,
|
mcc_pzone_container_c PZoneContT,
|
||||||
mcc_slewing_model_c SlewModelT,
|
mcc_slewing_model_c SlewModelT,
|
||||||
mcc_tracking_model_c TrackModelT,
|
mcc_tracking_model_c TrackModelT,
|
||||||
mcc_guiding_model_c GuidingModelT,
|
// mcc_guiding_model_c GuidingModelT,
|
||||||
mcc_logger_c LoggerT = MccNullLogger>
|
mcc_logger_c LoggerT = MccNullLogger>
|
||||||
class MccGenericMount : public HardwareT,
|
class MccGenericMount : public HardwareT,
|
||||||
public TelemetryT,
|
public TelemetryT,
|
||||||
public PZoneContT,
|
public PZoneContT,
|
||||||
public SlewModelT,
|
public SlewModelT,
|
||||||
public TrackModelT,
|
public TrackModelT,
|
||||||
public GuidingModelT,
|
// public GuidingModelT,
|
||||||
public LoggerT
|
public LoggerT
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -56,7 +56,7 @@ public:
|
|||||||
using LoggerT::logWarn;
|
using LoggerT::logWarn;
|
||||||
|
|
||||||
|
|
||||||
using typename GuidingModelT::guiding_params_t;
|
// using typename GuidingModelT::guiding_params_t;
|
||||||
using typename SlewModelT::slewing_params_t;
|
using typename SlewModelT::slewing_params_t;
|
||||||
using typename TrackModelT::tracking_params_t;
|
using typename TrackModelT::tracking_params_t;
|
||||||
|
|
||||||
@ -65,14 +65,14 @@ public:
|
|||||||
PZoneContT pzone_cont,
|
PZoneContT pzone_cont,
|
||||||
SlewModelT slew_model,
|
SlewModelT slew_model,
|
||||||
TrackModelT track_model,
|
TrackModelT track_model,
|
||||||
GuidingModelT guiding_model,
|
// GuidingModelT guiding_model,
|
||||||
LoggerT logger = MccNullLogger{})
|
LoggerT logger = MccNullLogger{})
|
||||||
: HardwareT(std::move(hardware)),
|
: HardwareT(std::move(hardware)),
|
||||||
TelemetryT(std::move(telemetry)),
|
TelemetryT(std::move(telemetry)),
|
||||||
PZoneContT(std::move(pzone_cont)),
|
PZoneContT(std::move(pzone_cont)),
|
||||||
SlewModelT(std::move(slew_model)),
|
SlewModelT(std::move(slew_model)),
|
||||||
TrackModelT(std::move(track_model)),
|
TrackModelT(std::move(track_model)),
|
||||||
GuidingModelT(std::move(guiding_model)),
|
// GuidingModelT(std::move(guiding_model)),
|
||||||
LoggerT(std::move(logger))
|
LoggerT(std::move(logger))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -83,7 +83,7 @@ public:
|
|||||||
{
|
{
|
||||||
logInfo("stop any movements ...");
|
logInfo("stop any movements ...");
|
||||||
|
|
||||||
this->stopGuidingTarget();
|
// this->stopGuidingTarget();
|
||||||
this->stopTracking();
|
this->stopTracking();
|
||||||
this->stopSlewing();
|
this->stopSlewing();
|
||||||
|
|
||||||
@ -119,15 +119,16 @@ template <mcc_hardware_c HardwareT,
|
|||||||
mcc_pzone_container_c PZoneContT,
|
mcc_pzone_container_c PZoneContT,
|
||||||
mcc_slewing_model_c SlewModelT,
|
mcc_slewing_model_c SlewModelT,
|
||||||
mcc_tracking_model_c TrackModelT,
|
mcc_tracking_model_c TrackModelT,
|
||||||
mcc_guiding_model_c GuidingModelT,
|
// mcc_guiding_model_c GuidingModelT,
|
||||||
mcc_logger_c LoggerT = MccNullLogger>
|
mcc_logger_c LoggerT = MccNullLogger>
|
||||||
class MccGenericMountFSM
|
class MccGenericMountFSM
|
||||||
: public fsm::MccFiniteStateMachine,
|
: public fsm::MccFiniteStateMachine,
|
||||||
public MccGenericMount<HardwareT, TelemetryT, PZoneContT, SlewModelT, TrackModelT, GuidingModelT, LoggerT>
|
// public MccGenericMount<HardwareT, TelemetryT, PZoneContT, SlewModelT, TrackModelT, GuidingModelT, LoggerT>
|
||||||
|
public MccGenericMount<HardwareT, TelemetryT, PZoneContT, SlewModelT, TrackModelT, LoggerT>
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
typedef MccGenericMount<HardwareT, TelemetryT, PZoneContT, SlewModelT, TrackModelT, GuidingModelT, LoggerT>
|
// typedef MccGenericMount<HardwareT, TelemetryT, PZoneContT, SlewModelT, TrackModelT, GuidingModelT, LoggerT>
|
||||||
base_gmount_t;
|
typedef MccGenericMount<HardwareT, TelemetryT, PZoneContT, SlewModelT, TrackModelT, LoggerT> base_gmount_t;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef typename base_gmount_t::error_t error_t;
|
typedef typename base_gmount_t::error_t error_t;
|
||||||
@ -206,11 +207,11 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
// to guiding state
|
// to guiding state
|
||||||
struct MccGenericMountEventGuiding : MccGenericMountBaseEvent {
|
// struct MccGenericMountEventGuiding : MccGenericMountBaseEvent {
|
||||||
static constexpr std::string_view ID = "MCC-MOUNT-GUIDING-EVENT";
|
// static constexpr std::string_view ID = "MCC-MOUNT-GUIDING-EVENT";
|
||||||
|
|
||||||
MccGenericMountEventGuiding(MccGenericMountFSM& mount) : MccGenericMountBaseEvent(mount) {}
|
// MccGenericMountEventGuiding(MccGenericMountFSM& mount) : MccGenericMountBaseEvent(mount) {}
|
||||||
};
|
// };
|
||||||
|
|
||||||
|
|
||||||
// to stoping state
|
// to stoping state
|
||||||
@ -252,7 +253,7 @@ public:
|
|||||||
struct MccGenericMountStateError;
|
struct MccGenericMountStateError;
|
||||||
struct MccGenericMountStateSlew;
|
struct MccGenericMountStateSlew;
|
||||||
struct MccGenericMountStateTrack;
|
struct MccGenericMountStateTrack;
|
||||||
struct MccGenericMountStateGuiding;
|
// struct MccGenericMountStateGuiding;
|
||||||
struct MccGenericMountStateStopping;
|
struct MccGenericMountStateStopping;
|
||||||
|
|
||||||
struct MccGenericMountStateUninit : MccGenericMountBaseState {
|
struct MccGenericMountStateUninit : MccGenericMountBaseState {
|
||||||
@ -394,8 +395,7 @@ public:
|
|||||||
struct MccGenericMountStateTrack : MccGenericMountBaseState {
|
struct MccGenericMountStateTrack : MccGenericMountBaseState {
|
||||||
using transition_t =
|
using transition_t =
|
||||||
fsm::fsm_transition_table_t<std::pair<MccGenericMountEventStop, MccGenericMountStateStopping>,
|
fsm::fsm_transition_table_t<std::pair<MccGenericMountEventStop, MccGenericMountStateStopping>,
|
||||||
std::pair<MccGenericMountEventError, MccGenericMountStateError>,
|
std::pair<MccGenericMountEventError, MccGenericMountStateError>>;
|
||||||
std::pair<MccGenericMountEventGuiding, MccGenericMountStateGuiding>>;
|
|
||||||
|
|
||||||
template <std::derived_from<MccGenericMountBaseEvent> EvT>
|
template <std::derived_from<MccGenericMountBaseEvent> EvT>
|
||||||
void exit(EvT& event)
|
void exit(EvT& event)
|
||||||
@ -421,34 +421,34 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct MccGenericMountStateGuiding : MccGenericMountBaseState {
|
// struct MccGenericMountStateGuiding : MccGenericMountBaseState {
|
||||||
using transition_t =
|
// using transition_t =
|
||||||
fsm::fsm_transition_table_t<std::pair<MccGenericMountEventStop, MccGenericMountStateStopping>,
|
// fsm::fsm_transition_table_t<std::pair<MccGenericMountEventStop, MccGenericMountStateStopping>,
|
||||||
std::pair<MccGenericMountEventError, MccGenericMountStateError>,
|
// std::pair<MccGenericMountEventError, MccGenericMountStateError>,
|
||||||
std::pair<MccGenericMountEventTrack, MccGenericMountStateTrack>>;
|
// std::pair<MccGenericMountEventTrack, MccGenericMountStateTrack>>;
|
||||||
|
|
||||||
template <std::derived_from<MccGenericMountBaseEvent> EvT>
|
// template <std::derived_from<MccGenericMountBaseEvent> EvT>
|
||||||
void exit(EvT& event)
|
// void exit(EvT& event)
|
||||||
{
|
// {
|
||||||
error_t err = event.mount()._stopGuidingMount();
|
// error_t err = event.mount()._stopGuidingMount();
|
||||||
if (err) {
|
// if (err) {
|
||||||
event.mount().dispatchEvent(MccGenericMountEventError{event.mount(), err});
|
// event.mount().dispatchEvent(MccGenericMountEventError{event.mount(), err});
|
||||||
}
|
// }
|
||||||
|
|
||||||
this->exitLog(event);
|
// this->exitLog(event);
|
||||||
}
|
// }
|
||||||
|
|
||||||
template <std::derived_from<MccGenericMountBaseEvent> EvT>
|
// template <std::derived_from<MccGenericMountBaseEvent> EvT>
|
||||||
void enter(EvT& event)
|
// void enter(EvT& event)
|
||||||
{
|
// {
|
||||||
this->enterLog(event);
|
// this->enterLog(event);
|
||||||
|
|
||||||
error_t err = event.mount()._startGuidingMount();
|
// error_t err = event.mount()._startGuidingMount();
|
||||||
if (err) {
|
// if (err) {
|
||||||
event.mount().dispatchEvent(MccGenericMountEventError{event.mount(), err});
|
// event.mount().dispatchEvent(MccGenericMountEventError{event.mount(), err});
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
};
|
// };
|
||||||
|
|
||||||
|
|
||||||
/* CONSTRUCTORS AND DESTRUCTOR */
|
/* CONSTRUCTORS AND DESTRUCTOR */
|
||||||
@ -458,7 +458,7 @@ public:
|
|||||||
PZoneContT pzone_cont,
|
PZoneContT pzone_cont,
|
||||||
SlewModelT slew_model,
|
SlewModelT slew_model,
|
||||||
TrackModelT track_model,
|
TrackModelT track_model,
|
||||||
GuidingModelT guiding_model,
|
// GuidingModelT guiding_model,
|
||||||
LoggerT logger = MccNullLogger{})
|
LoggerT logger = MccNullLogger{})
|
||||||
: fsm::MccFiniteStateMachine(MccGenericMountStateUninit{}),
|
: fsm::MccFiniteStateMachine(MccGenericMountStateUninit{}),
|
||||||
base_gmount_t(std::move(hardware),
|
base_gmount_t(std::move(hardware),
|
||||||
@ -466,7 +466,7 @@ public:
|
|||||||
std::move(pzone_cont),
|
std::move(pzone_cont),
|
||||||
std::move(slew_model),
|
std::move(slew_model),
|
||||||
std::move(track_model),
|
std::move(track_model),
|
||||||
std::move(guiding_model),
|
// std::move(guiding_model),
|
||||||
std::move(logger))
|
std::move(logger))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -506,15 +506,15 @@ public:
|
|||||||
this->dispatchEvent(MccGenericMountEventIDLE{*this});
|
this->dispatchEvent(MccGenericMountEventIDLE{*this});
|
||||||
}
|
}
|
||||||
|
|
||||||
auto startGuidingTarget()
|
// auto startGuidingTarget()
|
||||||
{
|
// {
|
||||||
this->dispatchEvent(MccGenericMountEventGuiding{*this});
|
// this->dispatchEvent(MccGenericMountEventGuiding{*this});
|
||||||
}
|
// }
|
||||||
|
|
||||||
auto stopGuidingTarget()
|
// auto stopGuidingTarget()
|
||||||
{
|
// {
|
||||||
this->dispatchEvent(MccGenericMountEventTrack{*this});
|
// this->dispatchEvent(MccGenericMountEventTrack{*this});
|
||||||
}
|
// }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// wrappers
|
// wrappers
|
||||||
|
|||||||
@ -64,18 +64,10 @@ static consteval bool mccIsAltAzMount(const MccMountType type)
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
enum class MccProhibitedZonePolicy : int {
|
||||||
// enum MccCoordPairKind : size_t {
|
PZ_POLICY_STOP, // stop mount near the zone
|
||||||
// COORDS_KIND_GENERIC,
|
PZ_POLICY_FLIP // flip mount, e.g., near the meridian, near HA-axis encoder limit switch
|
||||||
// COORDS_KIND_RADEC_ICRS,
|
};
|
||||||
// COORDS_KIND_RADEC_APP,
|
|
||||||
// COORDS_KIND_HADEC_APP,
|
|
||||||
// COORDS_KIND_AZZD,
|
|
||||||
// COORDS_KIND_AZALT,
|
|
||||||
// COORDS_KIND_XY,
|
|
||||||
// COORDS_KIND_LATLON
|
|
||||||
// };
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* GENERIC LOGGER CLASS CONCEPT */
|
/* GENERIC LOGGER CLASS CONCEPT */
|
||||||
@ -480,7 +472,7 @@ concept mcc_hardware_c = requires(T t, const T t_const) {
|
|||||||
requires mcc_angle_c<decltype(state.speedX)>; // moving speed along co-longitude coordinate
|
requires mcc_angle_c<decltype(state.speedX)>; // moving speed along co-longitude coordinate
|
||||||
requires mcc_angle_c<decltype(state.speedY)>; // moving speed along co-latitude coordinate
|
requires mcc_angle_c<decltype(state.speedY)>; // moving speed along co-latitude coordinate
|
||||||
|
|
||||||
requires std::same_as<typename T::hardware_moving_state_t, decltype(state.moving_type)>;
|
requires std::same_as<typename T::hardware_moving_state_t, decltype(state.moving_state)>;
|
||||||
};
|
};
|
||||||
|
|
||||||
// set hardware state:
|
// set hardware state:
|
||||||
@ -745,12 +737,12 @@ concept mcc_prohibited_zone_c =
|
|||||||
std::derived_from<T, mcc_pzone_interface_t<typename T::error_t>> && requires(const T t_const) {
|
std::derived_from<T, mcc_pzone_interface_t<typename T::error_t>> && requires(const T t_const) {
|
||||||
{ t_const.name() } -> std::formattable<char>;
|
{ t_const.name() } -> std::formattable<char>;
|
||||||
|
|
||||||
requires requires(typename T::pzone_policy_t pp) {
|
// the 'T' class must contain static constexpr member of 'MccMountType' type
|
||||||
[]() {
|
requires std::same_as<decltype(T::pzPolicy), const MccProhibitedZonePolicy>;
|
||||||
static constexpr auto v1 = T::pzone_policy_t::STOP_POLICY;
|
[]() {
|
||||||
static constexpr auto v2 = T::pzone_policy_t::FLIP_POLICY;
|
static constexpr MccProhibitedZonePolicy val = T::pzPolicy;
|
||||||
}();
|
return val;
|
||||||
};
|
}(); // to ensure 'pzPolicy' can be used in compile-time context
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -867,22 +859,22 @@ concept mcc_tracking_model_c = requires(T t) {
|
|||||||
{ t.getTrackingParams() } -> std::same_as<typename T::tracking_params_t>;
|
{ t.getTrackingParams() } -> std::same_as<typename T::tracking_params_t>;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
// template <typename T>
|
||||||
concept mcc_guiding_model_c = requires(T t) {
|
// concept mcc_guiding_model_c = requires(T t) {
|
||||||
requires mcc_error_c<typename T::error_t>;
|
// requires mcc_error_c<typename T::error_t>;
|
||||||
|
|
||||||
// a class of guiding process parameters
|
// // a class of guiding process parameters
|
||||||
requires requires(typename T::guiding_params_t pars) {
|
// requires requires(typename T::guiding_params_t pars) {
|
||||||
// guide along both mount axis
|
// // guide along both mount axis
|
||||||
requires std::convertible_to<decltype(pars.dualAxisGuiding), bool>;
|
// requires std::convertible_to<decltype(pars.dualAxisGuiding), bool>;
|
||||||
};
|
// };
|
||||||
|
|
||||||
{ t.startGuidingTarget() } -> std::same_as<typename T::error_t>;
|
// { t.startGuidingTarget() } -> std::same_as<typename T::error_t>;
|
||||||
{ t.stopGuidingTarget() } -> std::same_as<typename T::error_t>;
|
// { t.stopGuidingTarget() } -> std::same_as<typename T::error_t>;
|
||||||
|
|
||||||
{ t.setGuidingParams(std::declval<typename T::guiding_params_t>()) } -> std::same_as<typename T::error_t>;
|
// { t.setGuidingParams(std::declval<typename T::guiding_params_t>()) } -> std::same_as<typename T::error_t>;
|
||||||
{ t.getGuidingParams() } -> std::same_as<typename T::guiding_params_t>;
|
// { t.getGuidingParams() } -> std::same_as<typename T::guiding_params_t>;
|
||||||
};
|
// };
|
||||||
|
|
||||||
|
|
||||||
/* GENERIC MOUNT CLASS CONCEPT */
|
/* GENERIC MOUNT CLASS CONCEPT */
|
||||||
@ -897,7 +889,10 @@ template <typename T>
|
|||||||
concept mcc_all_controls_c = mcc_position_controls_c<T> && mcc_telemetry_c<T> && mcc_pzone_container_c<T>;
|
concept mcc_all_controls_c = mcc_position_controls_c<T> && mcc_telemetry_c<T> && mcc_pzone_container_c<T>;
|
||||||
|
|
||||||
|
|
||||||
|
// generic mount:
|
||||||
|
// 1) telemetry-related methods
|
||||||
|
// 2) prohibited zones related methods
|
||||||
|
// 3) slewing and tracking, stop and init mount methods
|
||||||
template <typename T>
|
template <typename T>
|
||||||
concept mcc_generic_mount_c = mcc_telemetry_c<T> && mcc_pzone_container_c<T> && requires(T t) {
|
concept mcc_generic_mount_c = mcc_telemetry_c<T> && mcc_pzone_container_c<T> && requires(T t) {
|
||||||
requires mcc_error_c<typename T::error_t>;
|
requires mcc_error_c<typename T::error_t>;
|
||||||
@ -909,8 +904,8 @@ concept mcc_generic_mount_c = mcc_telemetry_c<T> && mcc_pzone_container_c<T> &&
|
|||||||
{ t.trackTarget() } -> std::same_as<typename T::error_t>;
|
{ t.trackTarget() } -> std::same_as<typename T::error_t>;
|
||||||
|
|
||||||
|
|
||||||
{ t.startGuidingTarget() } -> std::same_as<typename T::error_t>;
|
// { t.startGuidingTarget() } -> std::same_as<typename T::error_t>;
|
||||||
{ t.stopGuidingTarget() } -> std::same_as<typename T::error_t>;
|
// { t.stopGuidingTarget() } -> std::same_as<typename T::error_t>;
|
||||||
|
|
||||||
// stop any movement
|
// stop any movement
|
||||||
{ t.stopMount() } -> std::same_as<typename T::error_t>;
|
{ t.stopMount() } -> std::same_as<typename T::error_t>;
|
||||||
|
|||||||
@ -1,302 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
/* MOUNT CONTROL COMPONENTS LIBRARY */
|
|
||||||
|
|
||||||
|
|
||||||
/* SIMPLE GUIDING MODEL IMPLEMENTATION */
|
|
||||||
|
|
||||||
|
|
||||||
#include "mcc_defaults.h"
|
|
||||||
#include "mcc_moving_model_common.h"
|
|
||||||
|
|
||||||
namespace mcc
|
|
||||||
{
|
|
||||||
|
|
||||||
enum class MccSimpleGuidingModelErrorCode : int {
|
|
||||||
ERROR_OK,
|
|
||||||
ERROR_CCTE,
|
|
||||||
ERROR_HW_GETSTATE,
|
|
||||||
ERROR_HW_SETSTATE,
|
|
||||||
ERROR_PCM_COMP,
|
|
||||||
ERROR_GET_TELEMETRY,
|
|
||||||
ERROR_DIST_TELEMETRY,
|
|
||||||
ERROR_DIFF_TELEMETRY,
|
|
||||||
ERROR_PZONE_CONTAINER_COMP,
|
|
||||||
ERROR_IN_PZONE,
|
|
||||||
ERROR_NEAR_PZONE,
|
|
||||||
ERROR_TIMEOUT,
|
|
||||||
ERROR_UNEXPECTED_AXIS_RATES,
|
|
||||||
ERROR_STOPPED
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace mcc
|
|
||||||
|
|
||||||
|
|
||||||
namespace std
|
|
||||||
{
|
|
||||||
|
|
||||||
template <>
|
|
||||||
class is_error_code_enum<mcc::MccSimpleGuidingModelErrorCode> : public true_type
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace std
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
namespace mcc
|
|
||||||
{
|
|
||||||
|
|
||||||
class MccSimpleGuidingModel
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
typedef std::error_code error_t;
|
|
||||||
|
|
||||||
typedef MccSimpleMovingModelParams guiding_params_t;
|
|
||||||
|
|
||||||
|
|
||||||
template <mcc_all_controls_c CONTROLS_T>
|
|
||||||
MccSimpleGuidingModel(CONTROLS_T* controls)
|
|
||||||
: _stopGuiding(new std::atomic_bool()), _currentParamsMutex(new std::mutex())
|
|
||||||
{
|
|
||||||
_guidingFunc = [controls, this]() -> error_t {
|
|
||||||
typename CONTROLS_T::hardware_state_t hw_state;
|
|
||||||
|
|
||||||
MccTelemetryData tdata;
|
|
||||||
MccEqtHrzCoords intsc_coords;
|
|
||||||
MccCelestialPoint target_in_future_pt;
|
|
||||||
|
|
||||||
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, "UNKNOW MOUNT TYPE!");
|
|
||||||
}
|
|
||||||
|
|
||||||
// double dist, dx, dy;
|
|
||||||
|
|
||||||
auto t_err = controls->telemetryData(&tdata);
|
|
||||||
if (t_err) {
|
|
||||||
return mcc_deduce_error<error_t>(t_err, MccSimpleGuidingModelErrorCode::ERROR_GET_TELEMETRY);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
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<error_t>(pz_err,
|
|
||||||
MccSimpleGuidingModelErrorCode::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, "UNKNOW MOUNT TYPE!");
|
|
||||||
}
|
|
||||||
|
|
||||||
// MccPCMResult pcm_inv_res;
|
|
||||||
|
|
||||||
// // endpoint of the mount moving
|
|
||||||
// auto pcm_err = controls->computeInversePCM(intsc_coords, &pcm_inv_res, &hw_state);
|
|
||||||
// if (pcm_err) {
|
|
||||||
// return mcc_deduce_error<error_t>(pcm_err, MccSimpleGuidingModelErrorCode::ERROR_PCM_COMP);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if constexpr (mccIsEquatorialMount(CONTROLS_T::mountType)) {
|
|
||||||
// hw_state.speedX = _currentParams.trackSpeedX;
|
|
||||||
// hw_state.speedY = _currentParams.trackSpeedY;
|
|
||||||
// }
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
auto target_point = [&, this](MccCelestialPoint* point) {
|
|
||||||
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(dt.count() * std::numbers::pi / 3600.0 / 15.0).normalize<MccAngle::NORM_KIND_0_360>(),
|
|
||||||
.Y = tdata.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<error_t>(ret, MccSimpleGuidingModelErrorCode::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<error_t>(pcm_err, MccSimpleGuidingModelErrorCode::ERROR_PCM_COMP);
|
|
||||||
}
|
|
||||||
|
|
||||||
mcc_tp2tp(tdata.time_point, hw_state.time_point);
|
|
||||||
}
|
|
||||||
|
|
||||||
return MccSimpleGuidingModelErrorCode::ERROR_OK;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
auto pz_err = update_pzones_ipoint();
|
|
||||||
if (pz_err) {
|
|
||||||
return mcc_deduce_error<error_t>(pz_err, MccSimpleGuidingModelErrorCode::ERROR_PZONE_CONTAINER_COMP);
|
|
||||||
}
|
|
||||||
|
|
||||||
hw_state.moving_type = CONTROLS_T::hardware_moving_state_t::HW_MOVE_GUIDING;
|
|
||||||
|
|
||||||
{
|
|
||||||
std::lock_guard lock{*_currentParamsMutex};
|
|
||||||
|
|
||||||
auto ccte_err = target_point(&target_in_future_pt);
|
|
||||||
if (ccte_err) {
|
|
||||||
return mcc_deduce_error(ccte_err, MccSimpleGuidingModelErrorCode::ERROR_CCTE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if constexpr (mccIsEquatorialMount(CONTROLS_T::mountType)) {
|
|
||||||
hw_state.speedX = _currentParams.trackSpeedX;
|
|
||||||
hw_state.speedY = _currentParams.trackSpeedY;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// move mount
|
|
||||||
auto hw_err = controls->hardwareSetState(hw_state);
|
|
||||||
if (hw_err) {
|
|
||||||
return mcc_deduce_error<error_t>(hw_err, MccSimpleGuidingModelErrorCode::ERROR_HW_SETSTATE);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
std::chrono::steady_clock::time_point last_corr_tp, last_ipzone_update_tp;
|
|
||||||
|
|
||||||
while (*_stopGuiding) {
|
|
||||||
// wait for updated telemetry data
|
|
||||||
{
|
|
||||||
std::lock_guard lock{*_currentParamsMutex};
|
|
||||||
|
|
||||||
t_err = controls->waitForTelemetryData(&tdata, _currentParams.telemetryTimeout);
|
|
||||||
|
|
||||||
if (t_err) {
|
|
||||||
return mcc_deduce_error<error_t>(t_err, MccSimpleGuidingModelErrorCode::ERROR_GET_TELEMETRY);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*_stopGuiding) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// control prohibited zones
|
|
||||||
if (mcc_is_near_pzones(controls, tdata, _currentParams.minTimeToPZone, pz_err)) {
|
|
||||||
return MccSimpleGuidingModelErrorCode::ERROR_NEAR_PZONE;
|
|
||||||
}
|
|
||||||
if (pz_err) {
|
|
||||||
return mcc_deduce_error<error_t>(pz_err,
|
|
||||||
MccSimpleGuidingModelErrorCode::ERROR_PZONE_CONTAINER_COMP);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*_stopGuiding) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
std::lock_guard lock{*_currentParamsMutex};
|
|
||||||
auto now = std::chrono::steady_clock::now();
|
|
||||||
|
|
||||||
if ((now - last_corr_tp) < _currentParams.guidingMinInterval) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// update prohibited zones intersection point
|
|
||||||
if ((now - last_ipzone_update_tp) < _currentParams.updatingPZoneInterval) {
|
|
||||||
pz_err = update_pzones_ipoint();
|
|
||||||
if (pz_err) {
|
|
||||||
return mcc_deduce_error<error_t>(
|
|
||||||
pz_err, MccSimpleGuidingModelErrorCode::ERROR_PZONE_CONTAINER_COMP);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// compute new target-in-future point
|
|
||||||
auto ccte_err = target_point(&target_in_future_pt);
|
|
||||||
if (ccte_err) {
|
|
||||||
return mcc_deduce_error(ccte_err, MccSimpleGuidingModelErrorCode::ERROR_CCTE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// send corrections
|
|
||||||
hw_state.moving_type = CONTROLS_T::hardware_moving_state_t::HW_MOVE_GUIDING;
|
|
||||||
hw_err = controls->hardwareSetState(hw_state);
|
|
||||||
if (hw_err) {
|
|
||||||
return mcc_deduce_error<error_t>(hw_err, MccSimpleGuidingModelErrorCode::ERROR_HW_SETSTATE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return MccSimpleGuidingModelErrorCode::ERROR_OK;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
MccSimpleGuidingModel(MccSimpleGuidingModel&&) = default;
|
|
||||||
MccSimpleGuidingModel& operator=(MccSimpleGuidingModel&&) = default;
|
|
||||||
|
|
||||||
MccSimpleGuidingModel(const MccSimpleGuidingModel&) = delete;
|
|
||||||
MccSimpleGuidingModel& operator=(const MccSimpleGuidingModel&) = delete;
|
|
||||||
|
|
||||||
error_t startGuidingTarget()
|
|
||||||
{
|
|
||||||
*_stopGuiding = false;
|
|
||||||
|
|
||||||
return _guidingFunc();
|
|
||||||
}
|
|
||||||
|
|
||||||
error_t stoptGuidingTarget()
|
|
||||||
{
|
|
||||||
*_stopGuiding = true;
|
|
||||||
|
|
||||||
return MccSimpleGuidingModelErrorCode::ERROR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
std::function<error_t()> _guidingFunc{};
|
|
||||||
std::unique_ptr<std::atomic_bool> _stopGuiding;
|
|
||||||
|
|
||||||
guiding_params_t _currentParams{};
|
|
||||||
std::unique_ptr<std::mutex> _currentParamsMutex{};
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace mcc
|
|
||||||
@ -43,19 +43,21 @@ struct MccSimpleMovingModelParams {
|
|||||||
// slew process timeout
|
// slew process timeout
|
||||||
std::chrono::seconds slewTimeout{3600};
|
std::chrono::seconds slewTimeout{3600};
|
||||||
|
|
||||||
double slewXRate{0.0}; // maximal slewing rate (0 means move with maximal allowed rate)
|
double slewRateX{0.0}; // maximal slewing rate (0 means move with maximal allowed rate)
|
||||||
double slewYRate{0.0}; // maximal slewing rate (0 means move with maximal allowed rate)
|
double slewRateY{0.0}; // maximal slewing rate (0 means move with maximal allowed rate)
|
||||||
|
|
||||||
std::chrono::milliseconds adjustCycleInterval{500}; // minimum time between two successive adjustments
|
std::chrono::milliseconds adjustCycleInterval{500}; // minimum time between two successive adjustments
|
||||||
|
|
||||||
double adjustXRate{5.0_arcmins}; // maximal adjusting rate (a rate at the final slewing stage)
|
double adjustRateX{5.0_arcmins}; // maximal adjusting rate (a rate at the final slewing stage)
|
||||||
double adjustYRate{5.0_arcmins}; // maximal adjusting rate (a rate at the final slewing stage)
|
double adjustRateY{5.0_arcmins}; // maximal adjusting rate (a rate at the final slewing stage)
|
||||||
|
|
||||||
|
|
||||||
// ******* tracking mode *******
|
// ******* tracking mode *******
|
||||||
|
|
||||||
double trackSpeedX{};
|
double trackSpeedX{};
|
||||||
double trackSpeedY{};
|
double trackSpeedY{};
|
||||||
|
std::chrono::milliseconds trackingCycleInterval{500}; // minimum time between two successive tracking corrections
|
||||||
|
bool dualAxisTracking{true}; // mount must be of an equatorial type: false means guiding along only HA-axis
|
||||||
|
|
||||||
// time shift into future to compute target position in future (UT1-scale time duration)
|
// time shift into future to compute target position in future (UT1-scale time duration)
|
||||||
std::chrono::duration<double> timeShiftToTargetPoint{10.0};
|
std::chrono::duration<double> timeShiftToTargetPoint{10.0};
|
||||||
|
|||||||
189
mcc/mcc_pzone.h
189
mcc/mcc_pzone.h
@ -12,7 +12,7 @@ namespace mcc
|
|||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
enum MccAltLimitPZErrorCode : int { ERROR_OK, ERROR_NULLPTR, ERROR_COORD_TRANSFROM };
|
enum MccAltLimitPZErrorCode : int { ERROR_OK, ERROR_NULLPTR, ERROR_COORD_TRANSFROM, ERROR_PCM_COMP };
|
||||||
|
|
||||||
} // namespace mcc
|
} // namespace mcc
|
||||||
|
|
||||||
@ -56,6 +56,8 @@ struct MccAltLimitPZCategory : public std::error_category {
|
|||||||
return "input argument os nullptr";
|
return "input argument os nullptr";
|
||||||
case MccAltLimitPZErrorCode::ERROR_COORD_TRANSFROM:
|
case MccAltLimitPZErrorCode::ERROR_COORD_TRANSFROM:
|
||||||
return "coordinate transformation error";
|
return "coordinate transformation error";
|
||||||
|
case MccAltLimitPZErrorCode::ERROR_PCM_COMP:
|
||||||
|
return "PCM computation error";
|
||||||
default:
|
default:
|
||||||
return "UNKNOWN";
|
return "UNKNOWN";
|
||||||
}
|
}
|
||||||
@ -85,6 +87,8 @@ protected:
|
|||||||
static constexpr auto pi2 = std::numbers::pi * 2.0;
|
static constexpr auto pi2 = std::numbers::pi * 2.0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
static constexpr MccProhibitedZonePolicy pzPolicy = MccProhibitedZonePolicy::PZ_POLICY_STOP;
|
||||||
|
|
||||||
typedef std::error_code error_t;
|
typedef std::error_code error_t;
|
||||||
|
|
||||||
MccAltLimitPZ(mcc_angle_c auto const& alt_limit, mcc_angle_c auto const& latitude, mcc_ccte_c auto* ccte_engine)
|
MccAltLimitPZ(mcc_angle_c auto const& alt_limit, mcc_angle_c auto const& latitude, mcc_ccte_c auto* ccte_engine)
|
||||||
@ -551,4 +555,187 @@ protected:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* co-longitude axis (HA or AZ) limit switch prohibited zone */
|
||||||
|
|
||||||
|
template <MccCoordKind AXIS_KIND>
|
||||||
|
class MccAxisLimitSwitchPZ : public mcc_pzone_interface_t<std::error_code>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static_assert(AXIS_KIND == MccCoordKind::COORDS_KIND_AZ || AXIS_KIND == MccCoordKind::COORDS_KIND_HA,
|
||||||
|
"UNSUPPORTED AXIS TYPE!");
|
||||||
|
|
||||||
|
typedef std::error_code error_t;
|
||||||
|
|
||||||
|
static constexpr MccCoordKind axisKind = AXIS_KIND;
|
||||||
|
|
||||||
|
static constexpr MccProhibitedZonePolicy pzPolicy = MccProhibitedZonePolicy::PZ_POLICY_FLIP;
|
||||||
|
|
||||||
|
//
|
||||||
|
// min_limit_val and max_limit_val are hardware encoder angles in radians!
|
||||||
|
//
|
||||||
|
MccAxisLimitSwitchPZ(mcc_angle_c auto const& min_limit_val,
|
||||||
|
mcc_angle_c auto const& max_limit_val,
|
||||||
|
mcc_position_controls_c auto* controls)
|
||||||
|
: _minLimit(min_limit_val), _maxLimit(max_limit_val)
|
||||||
|
{
|
||||||
|
_transformCoordinates = [controls](MccCelestialPoint from_pt, MccCelestialPoint* to_pt) -> error_t {
|
||||||
|
if (to_pt == nullptr) {
|
||||||
|
return MccAltLimitPZErrorCode::ERROR_NULLPTR;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto err = controls->transformCoordinates(from_pt, to_pt);
|
||||||
|
if (!err) {
|
||||||
|
return MccAltLimitPZErrorCode::ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (std::same_as<decltype(err), error_t>) {
|
||||||
|
return err;
|
||||||
|
} else {
|
||||||
|
return MccAltLimitPZErrorCode::ERROR_COORD_TRANSFROM;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
_transformCoordinatesEqtHrzCoords = [controls](MccCelestialPoint from_pt, MccEqtHrzCoords* to_pt) -> error_t {
|
||||||
|
if (to_pt == nullptr) {
|
||||||
|
return MccAltLimitPZErrorCode::ERROR_NULLPTR;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto err = controls->transformCoordinates(from_pt, to_pt);
|
||||||
|
if (!err) {
|
||||||
|
return MccAltLimitPZErrorCode::ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (std::same_as<decltype(err), error_t>) {
|
||||||
|
return err;
|
||||||
|
} else {
|
||||||
|
return MccAltLimitPZErrorCode::ERROR_COORD_TRANSFROM;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
_computePCM = [controls](MccCelestialPoint from_pt, MccCelestialPoint* to_pt) -> error_t {
|
||||||
|
MccPCMResult inv_res;
|
||||||
|
auto err = controls->computeInversePCM(std::move(from_pt), &inv_res, to_pt);
|
||||||
|
if (err) {
|
||||||
|
return mcc_deduce_error<error_t>(err, MccAltLimitPZErrorCode::ERROR_PCM_COMP);
|
||||||
|
}
|
||||||
|
|
||||||
|
return MccAltLimitPZErrorCode::ERROR_OK;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
consteval std::string_view name()
|
||||||
|
{
|
||||||
|
return axisKind == MccCoordKind::COORDS_KIND_AZ ? "AZ_AXIS-LIMITSWITCH_ZONE"
|
||||||
|
: axisKind == MccCoordKind::COORDS_KIND_HA ? "HA_AXIS-LIMITSWITCH_ZONE"
|
||||||
|
: "UKNOWN";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <typename InputT>
|
||||||
|
error_t inPZone(InputT coords, bool* result)
|
||||||
|
requires(mcc_eqt_hrz_coord_c<InputT> || mcc_celestial_point_c<InputT>)
|
||||||
|
{
|
||||||
|
if (result == nullptr) {
|
||||||
|
return MccAltLimitPZErrorCode::ERROR_NULLPTR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if constexpr (mcc_eqt_hrz_coord_c<InputT>) {
|
||||||
|
// assume here .X and are hardware encoder coordinate of corresponding axis
|
||||||
|
*result = (coords.X < _maxLimit) && (coords.X > _minLimit);
|
||||||
|
} else { // mcc_celestial_point_c
|
||||||
|
if (coords.pair_kind == MccCoordPairKind::COORDS_KIND_XY) { // hardware
|
||||||
|
*result = (coords.X < _maxLimit) && (coords.X > _minLimit);
|
||||||
|
} else { // here one needs transform input coordinates to hardware encoder ones
|
||||||
|
MccCelestialPoint pt;
|
||||||
|
|
||||||
|
auto ret = getHWCoords(std::move(coords), &pt);
|
||||||
|
if (ret) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
*result = (pt.X < _maxLimit) && (pt.X > _minLimit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return MccAltLimitPZErrorCode::ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename InputT>
|
||||||
|
error_t timeToPZone(InputT coords, traits::mcc_time_duration_c auto* res_time)
|
||||||
|
requires(mcc_eqt_hrz_coord_c<InputT> || mcc_celestial_point_c<InputT>)
|
||||||
|
{
|
||||||
|
using res_t = std::remove_cvref_t<decltype(*res_time)>;
|
||||||
|
using period_t = typename res_t::period;
|
||||||
|
|
||||||
|
double time_ang;
|
||||||
|
|
||||||
|
if (res_time == nullptr) {
|
||||||
|
return MccAltLimitPZErrorCode::ERROR_NULLPTR;
|
||||||
|
}
|
||||||
|
if constexpr (mcc_eqt_hrz_coord_c<InputT>) {
|
||||||
|
// assume here .X and are hardware encoder coordinate of corresponding axis
|
||||||
|
if constexpr (AXIS_KIND == MccCoordKind::COORDS_KIND_HA) {
|
||||||
|
time_ang = (_maxLimit - coords.X) / mcc_sideral_to_UT1_ratio; // to UT1 scale
|
||||||
|
} else if constexpr (AXIS_KIND == MccCoordKind::COORDS_KIND_AZ) {
|
||||||
|
}
|
||||||
|
} else { // mcc_celestial_point_c
|
||||||
|
}
|
||||||
|
|
||||||
|
std::chrono::nanoseconds ns{
|
||||||
|
static_cast<std::chrono::nanoseconds::rep>(time_ang * 43200.0 / std::numbers::pi * 1.0E9)};
|
||||||
|
|
||||||
|
period_t rat;
|
||||||
|
*res_time = res_t{static_cast<typename res_t::rep>(time_ang * 43200.0 / std::numbers::pi * rat.den / rat.num)};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename InputT>
|
||||||
|
error_t timeFromPZone(InputT coords, traits::mcc_time_duration_c auto* res_time)
|
||||||
|
requires(mcc_eqt_hrz_coord_c<InputT> || mcc_celestial_point_c<InputT>)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename InputT, typename ResultT>
|
||||||
|
error_t intersectPZone(InputT coords, ResultT* point)
|
||||||
|
requires((mcc_eqt_hrz_coord_c<InputT> || mcc_celestial_point_c<InputT>) &&
|
||||||
|
(mcc_eqt_hrz_coord_c<ResultT> || mcc_celestial_point_c<ResultT>))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
double _minLimit, _maxLimit;
|
||||||
|
|
||||||
|
std::function<error_t(MccCelestialPoint, MccCelestialPoint*)> _transformCoordinates{};
|
||||||
|
std::function<error_t(MccCelestialPoint, MccEqtHrzCoords*)> _transformCoordinatesEqtHrzCoords{};
|
||||||
|
|
||||||
|
std::function<error_t(MccCelestialPoint, MccCelestialPoint*)> _computePCM{};
|
||||||
|
|
||||||
|
error_t getHWCoords(MccCelestialPoint from_pt, MccCelestialPoint* to_pt)
|
||||||
|
{
|
||||||
|
error_t ret = MccAltLimitPZErrorCode::ERROR_OK;
|
||||||
|
|
||||||
|
if (from_pt.pair_kind == MccCoordPairKind::COORDS_KIND_XY) { // hardware
|
||||||
|
to_pt->X = from_pt.X;
|
||||||
|
to_pt->Y = from_pt.Y;
|
||||||
|
} else { // here one needs transform input coordinates to hardware encoder ones
|
||||||
|
if constexpr (AXIS_KIND == MccCoordKind::COORDS_KIND_AZ) {
|
||||||
|
to_pt->pair_kind = MccCoordPairKind::COORDS_KIND_AZZD;
|
||||||
|
|
||||||
|
} else if constexpr (AXIS_KIND == MccCoordKind::COORDS_KIND_HA) {
|
||||||
|
to_pt->pair_kind = MccCoordPairKind::COORDS_KIND_HADEC_APP;
|
||||||
|
}
|
||||||
|
|
||||||
|
mcc_tp2tp(from_pt.time_point, to_pt->time_point);
|
||||||
|
|
||||||
|
ret = _transformCoordinates(std::move(from_pt), to_pt);
|
||||||
|
if (!ret) {
|
||||||
|
ret = _computePCM(*to_pt, to_pt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace mcc
|
} // namespace mcc
|
||||||
|
|||||||
@ -22,6 +22,7 @@ enum class MccSimpleSlewingModelErrorCode : int {
|
|||||||
ERROR_DIST_TELEMETRY,
|
ERROR_DIST_TELEMETRY,
|
||||||
ERROR_DIFF_TELEMETRY,
|
ERROR_DIFF_TELEMETRY,
|
||||||
ERROR_PZONE_CONTAINER_COMP,
|
ERROR_PZONE_CONTAINER_COMP,
|
||||||
|
ERROR_TARGET_IN_PZONE,
|
||||||
ERROR_IN_PZONE,
|
ERROR_IN_PZONE,
|
||||||
ERROR_NEAR_PZONE,
|
ERROR_NEAR_PZONE,
|
||||||
ERROR_TIMEOUT,
|
ERROR_TIMEOUT,
|
||||||
@ -58,42 +59,18 @@ public:
|
|||||||
|
|
||||||
typedef MccSimpleMovingModelParams slewing_params_t;
|
typedef MccSimpleMovingModelParams slewing_params_t;
|
||||||
|
|
||||||
// struct slewing_params_t {
|
template <mcc_all_controls_c CONTROLS_T>
|
||||||
// bool slewAndStop{false}; // slew to target and stop mount
|
MccSimpleSlewingModel(CONTROLS_T* controls)
|
||||||
|
|
||||||
// std::chrono::seconds telemetryTimeout{3};
|
|
||||||
|
|
||||||
// // minimal time to prohibited zone at current speed. if it is lesser then exit with error
|
|
||||||
// std::chrono::seconds minTimeToPZone{10};
|
|
||||||
|
|
||||||
// // target-mount coordinate difference to start adjusting of slewing (in radians)
|
|
||||||
// double adjustCoordDiff{10.0_degs};
|
|
||||||
|
|
||||||
// // coordinates difference to stop slewing (in radians)
|
|
||||||
// double slewToleranceRadius{5.0_arcsecs};
|
|
||||||
|
|
||||||
// // slew process timeout
|
|
||||||
// std::chrono::seconds slewTimeout{3600};
|
|
||||||
|
|
||||||
// double slewXRate{0.0}; // maximal slewing rate (0 means move with maximal allowed rate)
|
|
||||||
// double slewYRate{0.0}; // maximal slewing rate (0 means move with maximal allowed rate)
|
|
||||||
|
|
||||||
// double adjustXRate{5.0_arcmins}; // maximal adjusting rate (a rate at the final slewing stage)
|
|
||||||
// double adjustYRate{5.0_arcmins}; // maximal adjusting rate (a rate at the final slewing stage)
|
|
||||||
// };
|
|
||||||
|
|
||||||
template <mcc_telemetry_data_c TelemetryT, mcc_hardware_c HardwareT, mcc_pzone_container_c PZoneContT>
|
|
||||||
MccSimpleSlewingModel(TelemetryT* telemetry, HardwareT* hardware, PZoneContT* pz_cont)
|
|
||||||
: _stopSlewing(new std::atomic_bool()), _currentParamsMutex(new std::mutex)
|
: _stopSlewing(new std::atomic_bool()), _currentParamsMutex(new std::mutex)
|
||||||
{
|
{
|
||||||
_slewingFunc = [telemetry, hardware, pz_cont, this]() -> error_t {
|
_slewingFunc = [controls, this]() -> error_t {
|
||||||
// first, check target coordinates
|
// first, check target coordinates
|
||||||
typename TelemetryT::error_t t_err;
|
typename CONTROLS_T::error_t t_err;
|
||||||
MccTelemetryData tdata;
|
MccTelemetryData tdata;
|
||||||
|
|
||||||
{
|
{
|
||||||
std::lock_guard lock{*_currentParamsMutex};
|
std::lock_guard lock{*_currentParamsMutex};
|
||||||
t_err = telemetry->telemetryData(&tdata);
|
t_err = controls->telemetryData(&tdata);
|
||||||
|
|
||||||
if (t_err) {
|
if (t_err) {
|
||||||
return mcc_deduce_error<error_t>(t_err, MccSimpleSlewingModelErrorCode::ERROR_GET_TELEMETRY);
|
return mcc_deduce_error<error_t>(t_err, MccSimpleSlewingModelErrorCode::ERROR_GET_TELEMETRY);
|
||||||
@ -101,13 +78,13 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool in_zone;
|
bool in_zone;
|
||||||
auto pz_err = pz_cont->inPZone(tdata.target, &in_zone);
|
auto pz_err = controls->inPZone(tdata.target, &in_zone);
|
||||||
if (pz_err) {
|
if (pz_err) {
|
||||||
return mcc_deduce_error<error_t>(pz_err, MccSimpleSlewingModelErrorCode::ERROR_PZONE_CONTAINER_COMP);
|
return mcc_deduce_error<error_t>(pz_err, MccSimpleSlewingModelErrorCode::ERROR_PZONE_CONTAINER_COMP);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (in_zone) {
|
if (in_zone) {
|
||||||
return MccSimpleSlewingModelErrorCode::ERROR_IN_PZONE;
|
return MccSimpleSlewingModelErrorCode::ERROR_TARGET_IN_PZONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*_stopSlewing) {
|
if (*_stopSlewing) {
|
||||||
@ -115,29 +92,23 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
MccCelestialPoint cpt;
|
MccCelestialPoint cpt;
|
||||||
mcc_tp2tp(tdata.time_point, cpt.time_point);
|
double min_time_to_pzone_in_secs;
|
||||||
|
|
||||||
if constexpr (mccIsEquatorialMount(HardwareT::mountType)) {
|
if constexpr (mccIsEquatorialMount(CONTROLS_T::mountType)) {
|
||||||
cpt.pair_kind = MccCoordPairKind::COORDS_KIND_HADEC_APP;
|
cpt.pair_kind = MccCoordPairKind::COORDS_KIND_HADEC_APP;
|
||||||
} else if constexpr (mccIsAltAzMount(HardwareT::mountType)) {
|
} else if constexpr (mccIsAltAzMount(CONTROLS_T::mountType)) {
|
||||||
cpt.pair_kind = MccCoordPairKind::COORDS_KIND_AZZD;
|
cpt.pair_kind = MccCoordPairKind::COORDS_KIND_AZZD;
|
||||||
} else {
|
} else {
|
||||||
static_assert(false, "UNKNOWN MOUNT TYPE!");
|
static_assert(false, "UNKNOWN MOUNT TYPE!");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<MccCelestialPoint> isct_pt(pz_cont->sizePZones, cpt);
|
|
||||||
pz_err = pz_cont->intersectPZone(tdata.target, &isct_pt);
|
|
||||||
if (pz_err) {
|
|
||||||
return mcc_deduce_error<error_t>(pz_err, MccSimpleSlewingModelErrorCode::ERROR_PZONE_CONTAINER_COMP);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*_stopSlewing) {
|
if (*_stopSlewing) {
|
||||||
return MccSimpleSlewingModelErrorCode::ERROR_STOPPED;
|
return MccSimpleSlewingModelErrorCode::ERROR_STOPPED;
|
||||||
}
|
}
|
||||||
|
|
||||||
typename HardwareT::hardware_state_t hw_state;
|
typename CONTROLS_T::hardware_state_t hw_state;
|
||||||
|
|
||||||
auto hw_err = hardware->hardwareGetState(&hw_state);
|
auto hw_err = controls->hardwareGetState(&hw_state);
|
||||||
if (hw_err) {
|
if (hw_err) {
|
||||||
return mcc_deduce_error<error_t>(hw_err, MccSimpleSlewingModelErrorCode::ERROR_HW_GETSTATE);
|
return mcc_deduce_error<error_t>(hw_err, MccSimpleSlewingModelErrorCode::ERROR_HW_GETSTATE);
|
||||||
}
|
}
|
||||||
@ -147,17 +118,20 @@ public:
|
|||||||
{
|
{
|
||||||
std::lock_guard lock{*_currentParamsMutex};
|
std::lock_guard lock{*_currentParamsMutex};
|
||||||
|
|
||||||
hw_state.speedX = _currentParams.slewXRate;
|
hw_state.speedX = _currentParams.slewRateX;
|
||||||
hw_state.speedY = _currentParams.slewYRate;
|
hw_state.speedY = _currentParams.slewRateY;
|
||||||
|
|
||||||
|
min_time_to_pzone_in_secs =
|
||||||
|
std::chrono::duration_cast<std::chrono::duration<double>>(_currentParams.minTimeToPZone).count();
|
||||||
}
|
}
|
||||||
hw_state.moving_type = HardwareT::hardware_moving_state_t::HW_MOVE_SLEWING;
|
hw_state.moving_state = CONTROLS_T::hardware_moving_state_t::HW_MOVE_SLEWING;
|
||||||
|
|
||||||
if (*_stopSlewing) {
|
if (*_stopSlewing) {
|
||||||
return MccSimpleSlewingModelErrorCode::ERROR_STOPPED;
|
return MccSimpleSlewingModelErrorCode::ERROR_STOPPED;
|
||||||
}
|
}
|
||||||
|
|
||||||
// start slewing
|
// start slewing
|
||||||
hw_err = hardware->hardwareSetState(hw_state);
|
hw_err = controls->hardwareSetState(hw_state);
|
||||||
if (hw_err) {
|
if (hw_err) {
|
||||||
return mcc_deduce_error<error_t>(hw_err, MccSimpleSlewingModelErrorCode::ERROR_HW_SETSTATE);
|
return mcc_deduce_error<error_t>(hw_err, MccSimpleSlewingModelErrorCode::ERROR_HW_SETSTATE);
|
||||||
}
|
}
|
||||||
@ -165,8 +139,10 @@ public:
|
|||||||
std::chrono::steady_clock::time_point start_slewing_tp, last_adjust_tp;
|
std::chrono::steady_clock::time_point start_slewing_tp, last_adjust_tp;
|
||||||
mcc_tp2tp(hw_state.time_point, start_slewing_tp);
|
mcc_tp2tp(hw_state.time_point, start_slewing_tp);
|
||||||
|
|
||||||
double dist, dx, dy, sinY, rate2, xrate;
|
// double dist, dx, dy, sinY, rate2, xrate;
|
||||||
std::chrono::duration<double> dtx, dty; // seconds in double
|
// std::chrono::duration<double> dtx, dty; // seconds in double
|
||||||
|
|
||||||
|
double dist;
|
||||||
|
|
||||||
bool adjust_mode = false;
|
bool adjust_mode = false;
|
||||||
static constexpr auto sideral_rate2 = slewing_params_t::sideralRate * slewing_params_t::sideralRate;
|
static constexpr auto sideral_rate2 = slewing_params_t::sideralRate * slewing_params_t::sideralRate;
|
||||||
@ -176,7 +152,7 @@ public:
|
|||||||
{
|
{
|
||||||
std::lock_guard lock{*_currentParamsMutex};
|
std::lock_guard lock{*_currentParamsMutex};
|
||||||
|
|
||||||
t_err = telemetry->waitForTelemetryData(&tdata, _currentParams.telemetryTimeout);
|
t_err = controls->waitForTelemetryData(&tdata, _currentParams.telemetryTimeout);
|
||||||
|
|
||||||
if (t_err) {
|
if (t_err) {
|
||||||
return mcc_deduce_error<error_t>(t_err, MccSimpleSlewingModelErrorCode::ERROR_GET_TELEMETRY);
|
return mcc_deduce_error<error_t>(t_err, MccSimpleSlewingModelErrorCode::ERROR_GET_TELEMETRY);
|
||||||
@ -187,42 +163,27 @@ public:
|
|||||||
return MccSimpleSlewingModelErrorCode::ERROR_STOPPED;
|
return MccSimpleSlewingModelErrorCode::ERROR_STOPPED;
|
||||||
}
|
}
|
||||||
|
|
||||||
// compute time to prohibited zones at current speed
|
// calculate coordinates at current speed '_currentParams.minTimeToPZone' seconds ahead
|
||||||
for (auto const& pt : isct_pt) {
|
// and check them for getting into the prohibited zones
|
||||||
if (std::isfinite(pt.X) && std::isfinite(pt.Y)) {
|
if constexpr (mccIsEquatorialMount(CONTROLS_T::mountType)) {
|
||||||
if constexpr (mccIsEquatorialMount(HardwareT::mountType)) {
|
cpt.X = tdata.HA + tdata.speedX * min_time_to_pzone_in_secs;
|
||||||
// sinY = sin(std::numbers::pi / 2.0 - tdata.DEC_APP);
|
cpt.X = tdata.DEC_APP + tdata.speedY * min_time_to_pzone_in_secs;
|
||||||
dx = pt.X - tdata.HA;
|
} else if constexpr (mccIsAltAzMount(CONTROLS_T::mountType)) {
|
||||||
dy = pt.Y - tdata.DEC_APP;
|
cpt.X = tdata.AZ + tdata.speedX * min_time_to_pzone_in_secs;
|
||||||
} else if constexpr (mccIsAltAzMount(HardwareT::mountType)) {
|
cpt.X = tdata.ZD + tdata.speedY * min_time_to_pzone_in_secs;
|
||||||
// sinY = sin(tdata.ZD);
|
|
||||||
dx = pt.X - tdata.AZ;
|
|
||||||
dy = pt.Y - tdata.ZD;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if (utils::isEqual(sinY, 0.0)) {
|
|
||||||
// dtx = decltype(dtx){std::numeric_limits<double>::infinity()};
|
|
||||||
// rate2 = std::numeric_limits<double>::infinity();
|
|
||||||
// } else {
|
|
||||||
// xrate = tdata.speedX * sinY;
|
|
||||||
// dtx = decltype(dtx){std::abs(dx / xrate)};
|
|
||||||
// }
|
|
||||||
dtx = decltype(dtx){std::abs(dx / tdata.speedX)};
|
|
||||||
dty = decltype(dty){std::abs(dy / tdata.speedY)};
|
|
||||||
|
|
||||||
{
|
|
||||||
std::lock_guard lock{*_currentParamsMutex};
|
|
||||||
|
|
||||||
if (dtx < _currentParams.minTimeToPZone || dty < _currentParams.minTimeToPZone) {
|
|
||||||
return MccSimpleSlewingModelErrorCode::ERROR_NEAR_PZONE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*_stopSlewing) {
|
|
||||||
return MccSimpleSlewingModelErrorCode::ERROR_STOPPED;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
mcc_tp2tp(tdata.time_point, cpt.time_point);
|
||||||
|
|
||||||
|
pz_err = controls->inPZone(cpt, &in_zone);
|
||||||
|
if (pz_err) {
|
||||||
|
return mcc_deduce_error<error_t>(pz_err,
|
||||||
|
MccSimpleSlewingModelErrorCode::ERROR_PZONE_CONTAINER_COMP);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (in_zone) {
|
||||||
|
return MccSimpleSlewingModelErrorCode::ERROR_NEAR_PZONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -233,12 +194,12 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
hw_err = hardware->hardwareGetState(&hw_state);
|
hw_err = controls->hardwareGetState(&hw_state);
|
||||||
if (hw_err) {
|
if (hw_err) {
|
||||||
return mcc_deduce_error<error_t>(hw_err, MccSimpleSlewingModelErrorCode::ERROR_HW_GETSTATE);
|
return mcc_deduce_error<error_t>(hw_err, MccSimpleSlewingModelErrorCode::ERROR_HW_GETSTATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
t_err = telemetry->targetToMountDist(&dist);
|
t_err = controls->targetToMountDist(&dist);
|
||||||
if (t_err) {
|
if (t_err) {
|
||||||
return mcc_deduce_error<error_t>(t_err, MccSimpleSlewingModelErrorCode::ERROR_DIST_TELEMETRY);
|
return mcc_deduce_error<error_t>(t_err, MccSimpleSlewingModelErrorCode::ERROR_DIST_TELEMETRY);
|
||||||
}
|
}
|
||||||
@ -252,7 +213,7 @@ public:
|
|||||||
|
|
||||||
if (adjust_mode && !_currentParams.slewAndStop) {
|
if (adjust_mode && !_currentParams.slewAndStop) {
|
||||||
// do not allow mount speed fall below sideral
|
// do not allow mount speed fall below sideral
|
||||||
if constexpr (mccIsEquatorialMount(HardwareT::mountType)) {
|
if constexpr (mccIsEquatorialMount(CONTROLS_T::mountType)) {
|
||||||
// turn on sideral rate only if the current position point catches up with the target
|
// turn on sideral rate only if the current position point catches up with the target
|
||||||
if ((tdata.target.HA - tdata.HA) <= 0.0 && tdata.speedX < slewing_params_t::sideralRate) {
|
if ((tdata.target.HA - tdata.HA) <= 0.0 && tdata.speedX < slewing_params_t::sideralRate) {
|
||||||
hw_state.X = (double)tdata.target.X;
|
hw_state.X = (double)tdata.target.X;
|
||||||
@ -260,23 +221,23 @@ public:
|
|||||||
|
|
||||||
hw_state.speedX = slewing_params_t::sideralRate;
|
hw_state.speedX = slewing_params_t::sideralRate;
|
||||||
|
|
||||||
hw_state.moving_type = HardwareT::hardware_moving_state_t::HW_MOVE_TRACKING;
|
hw_state.moving_state = CONTROLS_T::hardware_moving_state_t::HW_MOVE_TRACKING;
|
||||||
|
|
||||||
hw_err = hardware->hardwareSetState(hw_state);
|
hw_err = controls->hardwareSetState(hw_state);
|
||||||
if (hw_err) {
|
if (hw_err) {
|
||||||
return mcc_deduce_error<error_t>(hw_err,
|
return mcc_deduce_error<error_t>(hw_err,
|
||||||
MccSimpleSlewingModelErrorCode::ERROR_HW_SETSTATE);
|
MccSimpleSlewingModelErrorCode::ERROR_HW_SETSTATE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if constexpr (mccIsAltAzMount(HardwareT::mountType)) {
|
} else if constexpr (mccIsAltAzMount(CONTROLS_T::mountType)) {
|
||||||
} else {
|
} else {
|
||||||
static_assert(false, "UNKNOWN MOUNT TYPE!!");
|
static_assert(false, "UNKNOWN MOUNT TYPE!!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dist <= _currentParams.slewToleranceRadius) { // stop slewing and exit from cycle
|
if (dist <= _currentParams.slewToleranceRadius) { // stop slewing and exit from cycle
|
||||||
if (hw_state.moving_type ==
|
if (hw_state.moving_state ==
|
||||||
HardwareT::hardware_moving_state_t::HW_MOVE_STOPPED) { // mount was stopped
|
CONTROLS_T::hardware_moving_state_t::HW_MOVE_STOPPED) { // mount was stopped
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -290,12 +251,12 @@ public:
|
|||||||
hw_state.X = (double)tdata.target.X;
|
hw_state.X = (double)tdata.target.X;
|
||||||
hw_state.Y = (double)tdata.target.Y;
|
hw_state.Y = (double)tdata.target.Y;
|
||||||
|
|
||||||
hw_state.speedX = _currentParams.adjustXRate;
|
hw_state.speedX = _currentParams.adjustRateX;
|
||||||
hw_state.speedY = _currentParams.adjustYRate;
|
hw_state.speedY = _currentParams.adjustRateY;
|
||||||
|
|
||||||
hw_state.moving_type = HardwareT::hardware_moving_state_t::HW_MOVE_ADJUSTING;
|
hw_state.moving_state = CONTROLS_T::hardware_moving_state_t::HW_MOVE_ADJUSTING;
|
||||||
|
|
||||||
hw_err = hardware->hardwareSetState(hw_state);
|
hw_err = controls->hardwareSetState(hw_state);
|
||||||
if (hw_err) {
|
if (hw_err) {
|
||||||
return mcc_deduce_error<error_t>(hw_err, MccSimpleSlewingModelErrorCode::ERROR_HW_SETSTATE);
|
return mcc_deduce_error<error_t>(hw_err, MccSimpleSlewingModelErrorCode::ERROR_HW_SETSTATE);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -125,43 +125,6 @@ public:
|
|||||||
using pcm_t = std::remove_cvref_t<decltype(*pcm)>;
|
using pcm_t = std::remove_cvref_t<decltype(*pcm)>;
|
||||||
using hardware_t = std::remove_cvref_t<decltype(*hardware)>;
|
using hardware_t = std::remove_cvref_t<decltype(*hardware)>;
|
||||||
|
|
||||||
|
|
||||||
_toHardwareFunc = [ccte, pcm](const MccCelestialPoint& from_pt, MccCelestialPoint* to_pt) -> error_t {
|
|
||||||
if (to_pt == nullptr) {
|
|
||||||
return MccTelemetryErrorCode::ERROR_NULLPTR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if constexpr (mccIsEquatorialMount(pcm_t::mountType)) {
|
|
||||||
to_pt->pair_kind = MccCoordPairKind::COORDS_KIND_HADEC_APP;
|
|
||||||
} else if constexpr (mccIsAltAzMount(pcm_t::mountType)) {
|
|
||||||
to_pt->pair_kind = MccCoordPairKind::COORDS_KIND_AZALT;
|
|
||||||
} else {
|
|
||||||
static_assert(false, "UNKNOWN MOUNT TYPE!");
|
|
||||||
}
|
|
||||||
|
|
||||||
auto err = ccte->transformCoordinates(from_pt, to_pt);
|
|
||||||
if (err) {
|
|
||||||
return mcc_deduce_error(err, MccTelemetryErrorCode::ERROR_COORD_TRANSFORM);
|
|
||||||
}
|
|
||||||
|
|
||||||
// compute hardware coordinates
|
|
||||||
// WARNING: It is assumed here that PCM corrections have small (arcseconds-arcminutes) values
|
|
||||||
// since ususaly there is no reverse transformation for "hardware-to-apparent" relation!
|
|
||||||
struct {
|
|
||||||
double dx, dy;
|
|
||||||
} pcm_res;
|
|
||||||
|
|
||||||
auto pcm_err = pcm->compute(from_pt, &pcm_res);
|
|
||||||
if (pcm_err) {
|
|
||||||
return mcc_deduce_error<error_t>(pcm_err, MccTelemetryErrorCode::ERROR_PCM_COMP);
|
|
||||||
}
|
|
||||||
|
|
||||||
to_pt->X -= pcm_res.dx;
|
|
||||||
to_pt->Y -= pcm_res.dy;
|
|
||||||
|
|
||||||
return MccTelemetryErrorCode::ERROR_OK;
|
|
||||||
};
|
|
||||||
|
|
||||||
_updateTargetFunc = [ccte, pcm, this](bool only_hw, std::stop_token stop_token) -> error_t {
|
_updateTargetFunc = [ccte, pcm, this](bool only_hw, std::stop_token stop_token) -> error_t {
|
||||||
if (!only_hw) {
|
if (!only_hw) {
|
||||||
//
|
//
|
||||||
@ -584,22 +547,6 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
error_t transformToHardwareCoords(mcc_celestial_point_c auto pt, mcc_celestial_point_c auto* res)
|
|
||||||
{
|
|
||||||
MccCelestialPoint cpt, rcpt;
|
|
||||||
mcc_copy_celestial_point(pt, &cpt);
|
|
||||||
|
|
||||||
rcpt.time_point = std::chrono::time_point_cast<decltype(rcpt.time_point)>(res->time_point);
|
|
||||||
auto err = _toHardwareFunc(cpt, &rcpt);
|
|
||||||
if (err) {
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
mcc_copy_celestial_point(rcpt, res);
|
|
||||||
|
|
||||||
return MccTelemetryErrorCode::ERROR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
error_t targetToMountDiff(MccCoordPairKind pair_kind, mcc_angle_c auto* dx, mcc_angle_c auto* dy)
|
error_t targetToMountDiff(MccCoordPairKind pair_kind, mcc_angle_c auto* dx, mcc_angle_c auto* dy)
|
||||||
{
|
{
|
||||||
@ -658,7 +605,6 @@ protected:
|
|||||||
std ::function<error_t(bool, std::stop_token)> _updateTargetFunc{};
|
std ::function<error_t(bool, std::stop_token)> _updateTargetFunc{};
|
||||||
std::function<error_t(std::stop_token)> _updateFunc{};
|
std::function<error_t(std::stop_token)> _updateFunc{};
|
||||||
std::function<error_t()> _setTargetFunc{};
|
std::function<error_t()> _setTargetFunc{};
|
||||||
std::function<error_t(const MccCelestialPoint&, MccCelestialPoint*)> _toHardwareFunc{};
|
|
||||||
|
|
||||||
std::unique_ptr<std::mutex> _updateMutex;
|
std::unique_ptr<std::mutex> _updateMutex;
|
||||||
std::unique_ptr<std::condition_variable> _updateCondVar;
|
std::unique_ptr<std::condition_variable> _updateCondVar;
|
||||||
|
|||||||
@ -3,11 +3,10 @@
|
|||||||
/* MOUNT CONTROL COMPONENTS LIBRARY */
|
/* MOUNT CONTROL COMPONENTS LIBRARY */
|
||||||
|
|
||||||
|
|
||||||
/* SIMPLE TRACKING MODEL IMPLEMENTATION */
|
/* SIMPLE Tracking MODEL IMPLEMENTATION */
|
||||||
|
|
||||||
|
|
||||||
#include "mcc_defaults.h"
|
#include "mcc_defaults.h"
|
||||||
#include "mcc_generics.h"
|
|
||||||
#include "mcc_moving_model_common.h"
|
#include "mcc_moving_model_common.h"
|
||||||
|
|
||||||
namespace mcc
|
namespace mcc
|
||||||
@ -15,14 +14,19 @@ namespace mcc
|
|||||||
|
|
||||||
enum class MccSimpleTrackingModelErrorCode : int {
|
enum class MccSimpleTrackingModelErrorCode : int {
|
||||||
ERROR_OK,
|
ERROR_OK,
|
||||||
|
ERROR_CCTE,
|
||||||
ERROR_HW_GETSTATE,
|
ERROR_HW_GETSTATE,
|
||||||
ERROR_HW_SETSTATE,
|
ERROR_HW_SETSTATE,
|
||||||
ERROR_PCM_COMP,
|
ERROR_PCM_COMP,
|
||||||
ERROR_GET_TELEMETRY,
|
ERROR_GET_TELEMETRY,
|
||||||
|
ERROR_DIST_TELEMETRY,
|
||||||
|
ERROR_DIFF_TELEMETRY,
|
||||||
ERROR_PZONE_CONTAINER_COMP,
|
ERROR_PZONE_CONTAINER_COMP,
|
||||||
ERROR_IN_PZONE,
|
ERROR_IN_PZONE,
|
||||||
ERROR_NEAR_PZONE,
|
ERROR_NEAR_PZONE,
|
||||||
ERROR_UNEXPECTED_AXIS_RATES
|
ERROR_TIMEOUT,
|
||||||
|
ERROR_UNEXPECTED_AXIS_RATES,
|
||||||
|
ERROR_STOPPED
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace mcc
|
} // namespace mcc
|
||||||
@ -50,227 +54,254 @@ public:
|
|||||||
|
|
||||||
typedef MccSimpleMovingModelParams tracking_params_t;
|
typedef MccSimpleMovingModelParams tracking_params_t;
|
||||||
|
|
||||||
// struct tracking_params_t {
|
|
||||||
// static constexpr double sideralRate = 15.0410686_arcsecs; // in radians per second
|
|
||||||
|
|
||||||
// double trackSpeedX{};
|
template <mcc_all_controls_c CONTROLS_T>
|
||||||
// double trackSpeedY{};
|
MccSimpleTrackingModel(CONTROLS_T* controls)
|
||||||
|
: _stopTracking(new std::atomic_bool()), _currentParamsMutex(new std::mutex())
|
||||||
// std::chrono::seconds telemetryTimeout{3};
|
|
||||||
// // minimal time to prohibited zone. if it is lesser then exit with error
|
|
||||||
// std::chrono::seconds minTimeToPZone{10};
|
|
||||||
// };
|
|
||||||
|
|
||||||
template <mcc_telemetry_data_c TelemetryT,
|
|
||||||
mcc_hardware_c HardwareT,
|
|
||||||
mcc_PCM_c PcmT,
|
|
||||||
mcc_pzone_container_c PZoneContT>
|
|
||||||
MccSimpleTrackingModel(TelemetryT* telemetry, HardwareT* hardware, PcmT* pcm, PZoneContT* pz_cont)
|
|
||||||
: _stopTracking(new std::atomic_bool()), _currentTrackParamsMutex(new std::mutex)
|
|
||||||
{
|
{
|
||||||
*_stopTracking = false;
|
_trackingFunc = [controls, this]() -> error_t {
|
||||||
|
typename CONTROLS_T::hardware_state_t hw_state;
|
||||||
// set default values
|
|
||||||
if constexpr (mccIsEquatorialMount(PcmT::mountType)) {
|
|
||||||
_currentTrackParams.trackSpeedX = tracking_params_t::sideralRate; // move along HA-axis with sideral rate
|
|
||||||
_currentTrackParams.trackSpeedY = 0.0;
|
|
||||||
|
|
||||||
_currentTrackParams.telemetryTimeout = std::chrono::seconds(3);
|
|
||||||
_currentTrackParams.minTimeToPZone = std::chrono::seconds(10);
|
|
||||||
}
|
|
||||||
|
|
||||||
_trackingFunc = [telemetry, hardware, pcm, pz_cont, this]() -> error_t {
|
|
||||||
typename HardwareT::hardware_state_t hw_state;
|
|
||||||
|
|
||||||
MccEqtHrzCoords intsc_coords;
|
|
||||||
|
|
||||||
MccTelemetryData tdata;
|
MccTelemetryData tdata;
|
||||||
auto t_err = telemetry->waitForTelemetryData(&tdata, _currentTrackParams.telemetryTimeout);
|
MccEqtHrzCoords intsc_coords;
|
||||||
|
MccCelestialPoint target_in_future_pt;
|
||||||
|
|
||||||
|
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, "UNKNOW MOUNT TYPE!");
|
||||||
|
}
|
||||||
|
|
||||||
|
// double dist, dx, dy;
|
||||||
|
|
||||||
|
auto t_err = controls->telemetryData(&tdata);
|
||||||
if (t_err) {
|
if (t_err) {
|
||||||
return mcc_deduce_error<error_t>(t_err, MccSimpleTrackingModelErrorCode::ERROR_GET_TELEMETRY);
|
return mcc_deduce_error<error_t>(t_err, MccSimpleTrackingModelErrorCode::ERROR_GET_TELEMETRY);
|
||||||
}
|
}
|
||||||
|
|
||||||
mcc_tp2tp(tdata.time_point, intsc_coords.time_point);
|
|
||||||
|
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<error_t>(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, "UNKNOW MOUNT TYPE!");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
std::vector<std::chrono::duration<double>> pz_timeto; // in seconds
|
auto target_point = [&, this](MccCelestialPoint* point) {
|
||||||
std::chrono::duration<double> min_time{0.0};
|
auto dt = std::chrono::duration<double>{tdata.HA} +
|
||||||
|
_currentParams.timeShiftToTargetPoint * mcc_sideral_to_UT1_ratio; // hour seconds
|
||||||
|
|
||||||
// compute intersection points with the prohibited zones
|
auto tp_dt = std::chrono::duration_cast<typename decltype(tdata.time_point)::duration>(
|
||||||
auto pz_err = mcc_find_closest_pzone(pz_cont, tdata, &intsc_coords);
|
_currentParams.timeShiftToTargetPoint);
|
||||||
|
|
||||||
|
// point in +time_dist future
|
||||||
|
MccCelestialPoint pt{
|
||||||
|
.pair_kind = MccCoordPairKind::COORDS_KIND_HADEC_APP,
|
||||||
|
.X = MccAngle(dt.count() * std::numbers::pi / 3600.0 / 15.0).normalize<MccAngle::NORM_KIND_0_360>(),
|
||||||
|
.Y = tdata.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<error_t>(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<error_t>(pcm_err, MccSimpleTrackingModelErrorCode::ERROR_PCM_COMP);
|
||||||
|
}
|
||||||
|
|
||||||
|
mcc_tp2tp(tdata.time_point, hw_state.time_point);
|
||||||
|
}
|
||||||
|
|
||||||
|
return MccSimpleTrackingModelErrorCode::ERROR_OK;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
auto pz_err = update_pzones_ipoint();
|
||||||
if (pz_err) {
|
if (pz_err) {
|
||||||
return mcc_deduce_error<error_t>(pz_err, MccSimpleTrackingModelErrorCode::ERROR_PZONE_CONTAINER_COMP);
|
return mcc_deduce_error<error_t>(pz_err, MccSimpleTrackingModelErrorCode::ERROR_PZONE_CONTAINER_COMP);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool no_intersects = false;
|
hw_state.moving_state = CONTROLS_T::hardware_moving_state_t::HW_MOVE_Tracking;
|
||||||
|
|
||||||
if constexpr (mccIsEquatorialMount(HardwareT::mountType)) {
|
{
|
||||||
if (std::isfinite(intsc_coords.HA)) {
|
std::lock_guard lock{*_currentParamsMutex};
|
||||||
intsc_coords.X = intsc_coords.HA;
|
|
||||||
intsc_coords.Y = intsc_coords.DEC_APP;
|
auto ccte_err = target_point(&target_in_future_pt);
|
||||||
} else {
|
if (ccte_err) {
|
||||||
no_intersects = true;
|
return mcc_deduce_error(ccte_err, MccSimpleTrackingModelErrorCode::ERROR_CCTE);
|
||||||
intsc_coords.X = tdata.HA + 710.0_mins; // 12h - 10min
|
|
||||||
intsc_coords.Y = tdata.DEC_APP;
|
|
||||||
}
|
}
|
||||||
} else if constexpr (mccIsAltAzMount(HardwareT::mountType)) {
|
|
||||||
if (std::isfinite(intsc_coords.AZ)) {
|
if constexpr (mccIsEquatorialMount(CONTROLS_T::mountType)) {
|
||||||
intsc_coords.X = intsc_coords.AZ;
|
hw_state.speedX = _currentParams.trackSpeedX;
|
||||||
intsc_coords.Y = intsc_coords.ZD;
|
hw_state.speedY = _currentParams.trackSpeedY;
|
||||||
} else {
|
|
||||||
no_intersects = true;
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
static_assert(false, "UNKNOW MOUNT TYPE!");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// compute position in future
|
// move mount
|
||||||
auto hw_err = hardware->hardwareGetState(&hw_state);
|
auto hw_err = controls->hardwareSetState(hw_state);
|
||||||
if (hw_err) {
|
if (hw_err) {
|
||||||
return mcc_deduce_error<error_t>(hw_err, MccSimpleTrackingModelErrorCode::ERROR_HW_GETSTATE);
|
return mcc_deduce_error<error_t>(hw_err, MccSimpleTrackingModelErrorCode::ERROR_HW_SETSTATE);
|
||||||
}
|
|
||||||
|
|
||||||
MccPCMResult pcm_inv_res;
|
|
||||||
|
|
||||||
// endpoint of the mount moving
|
|
||||||
auto pcm_err = pcm->computeInversePCM(intsc_coords, &pcm_inv_res, &hw_state);
|
|
||||||
if (pcm_err) {
|
|
||||||
return mcc_deduce_error<error_t>(pcm_err, MccSimpleTrackingModelErrorCode::ERROR_PCM_COMP);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::chrono::steady_clock::time_point last_corr_tp, last_ipzone_update_tp;
|
||||||
|
|
||||||
if constexpr (mccIsEquatorialMount(PcmT::mountType)) {
|
while (*_stopTracking) {
|
||||||
// just set sideral rate once
|
// wait for updated telemetry data
|
||||||
mcc_tp2tp(tdata.time_point, hw_state.time_point);
|
|
||||||
{
|
{
|
||||||
std::lock_guard lock{*_currentTrackParamsMutex};
|
std::lock_guard lock{*_currentParamsMutex};
|
||||||
|
|
||||||
hw_state.speedX = _currentTrackParams.trackSpeedX;
|
t_err = controls->waitForTelemetryData(&tdata, _currentParams.telemetryTimeout);
|
||||||
hw_state.speedY = _currentTrackParams.trackSpeedY;
|
|
||||||
}
|
|
||||||
hw_state.moving_type = HardwareT::hardware_moving_state_t::HW_MOVE_TRACKING;
|
|
||||||
|
|
||||||
// start tracking
|
|
||||||
hw_err = hardware->hardwareSetState(std::move(hw_state));
|
|
||||||
if (hw_err) {
|
|
||||||
return mcc_deduce_error<error_t>(hw_err, MccSimpleTrackingModelErrorCode::ERROR_HW_SETSTATE);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
while (!*_stopTracking) {
|
|
||||||
// control prohibited zones
|
|
||||||
pz_err = pz_cont->timeToPZone(tdata, &pz_timeto);
|
|
||||||
if (pz_err) {
|
|
||||||
return mcc_deduce_error<error_t>(pz_err,
|
|
||||||
MccSimpleTrackingModelErrorCode::ERROR_PZONE_CONTAINER_COMP);
|
|
||||||
}
|
|
||||||
|
|
||||||
min_time = std::chrono::duration<double>{0};
|
|
||||||
for (size_t i = 0; i < pz_cont->sizePZones(); ++i) {
|
|
||||||
if (pz_timeto[i] < _currentTrackParams.minTimeToPZone) {
|
|
||||||
return MccSimpleTrackingModelErrorCode::ERROR_NEAR_PZONE;
|
|
||||||
}
|
|
||||||
if (pz_timeto[i] < min_time) {
|
|
||||||
min_time = pz_timeto[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
t_err = telemetry->waitForTelemetryData(&tdata, _currentTrackParams.telemetryTimeout);
|
|
||||||
if (t_err) {
|
if (t_err) {
|
||||||
return mcc_deduce_error<error_t>(t_err, MccSimpleTrackingModelErrorCode::ERROR_GET_TELEMETRY);
|
return mcc_deduce_error<error_t>(t_err, MccSimpleTrackingModelErrorCode::ERROR_GET_TELEMETRY);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (*_stopTracking) {
|
if (*_stopTracking) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// control prohibited zones
|
||||||
|
if (mcc_is_near_pzones(controls, tdata, _currentParams.minTimeToPZone, pz_err)) {
|
||||||
|
return MccSimpleTrackingModelErrorCode::ERROR_NEAR_PZONE;
|
||||||
|
}
|
||||||
|
if (pz_err) {
|
||||||
|
return mcc_deduce_error<error_t>(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) {
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (no_intersects) {
|
// update prohibited zones intersection point
|
||||||
if ((intsc_coords.HA - tdata.HA) < 10.0_mins) { // recompute target point
|
if ((now - last_ipzone_update_tp) < _currentParams.updatingPZoneInterval) {
|
||||||
intsc_coords.X += 11.0_hours;
|
pz_err = update_pzones_ipoint();
|
||||||
|
if (pz_err) {
|
||||||
hw_err = hardware->hardwareGetState(&hw_state);
|
return mcc_deduce_error<error_t>(
|
||||||
if (hw_err) {
|
pz_err, MccSimpleTrackingModelErrorCode::ERROR_PZONE_CONTAINER_COMP);
|
||||||
return mcc_deduce_error<error_t>(hw_err,
|
|
||||||
MccSimpleTrackingModelErrorCode::ERROR_HW_GETSTATE);
|
|
||||||
}
|
|
||||||
|
|
||||||
pcm_err = pcm->computeInversePCM(intsc_coords, &pcm_inv_res, &hw_state);
|
|
||||||
if (pcm_err) {
|
|
||||||
return mcc_deduce_error<error_t>(pcm_err,
|
|
||||||
MccSimpleTrackingModelErrorCode::ERROR_PCM_COMP);
|
|
||||||
}
|
|
||||||
|
|
||||||
// just set sideral rate once
|
|
||||||
mcc_tp2tp(tdata.time_point, hw_state.time_point);
|
|
||||||
{
|
|
||||||
std::lock_guard lock{*_currentTrackParamsMutex};
|
|
||||||
|
|
||||||
hw_state.speedX = _currentTrackParams.trackSpeedX;
|
|
||||||
hw_state.speedY = _currentTrackParams.trackSpeedY;
|
|
||||||
}
|
|
||||||
hw_state.moving_type = HardwareT::hardware_moving_state_t::HW_MOVE_TRACKING;
|
|
||||||
|
|
||||||
// start tracking
|
|
||||||
hw_err = hardware->hardwareSetState(std::move(hw_state));
|
|
||||||
if (hw_err) {
|
|
||||||
return mcc_deduce_error<error_t>(hw_err,
|
|
||||||
MccSimpleTrackingModelErrorCode::ERROR_HW_SETSTATE);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// compute new target-in-future point
|
||||||
|
auto ccte_err = target_point(&target_in_future_pt);
|
||||||
|
if (ccte_err) {
|
||||||
|
return mcc_deduce_error(ccte_err, MccSimpleTrackingModelErrorCode::ERROR_CCTE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return MccSimpleTrackingModelErrorCode::ERROR_OK;
|
// send corrections
|
||||||
|
hw_state.moving_state = CONTROLS_T::hardware_moving_state_t::HW_MOVE_Tracking;
|
||||||
} else if constexpr (mccIsAltAzMount(PcmT::mountType)) {
|
hw_err = controls->hardwareSetState(hw_state);
|
||||||
static_assert(false, "NOT IMPLEMENTED!");
|
if (hw_err) {
|
||||||
} else {
|
return mcc_deduce_error<error_t>(hw_err, MccSimpleTrackingModelErrorCode::ERROR_HW_SETSTATE);
|
||||||
static_assert(false, "UNKNOW MOUNT TYPE!");
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return MccSimpleTrackingModelErrorCode::ERROR_OK;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
MccSimpleTrackingModel(MccSimpleTrackingModel&&) = default;
|
MccSimpleTrackingModel(MccSimpleTrackingModel&&) = default;
|
||||||
MccSimpleTrackingModel& operator=(MccSimpleTrackingModel&&) = default;
|
MccSimpleTrackingModel& operator=(MccSimpleTrackingModel&&) = default;
|
||||||
|
|
||||||
|
MccSimpleTrackingModel(const MccSimpleTrackingModel&) = delete;
|
||||||
|
MccSimpleTrackingModel& operator=(const MccSimpleTrackingModel&) = delete;
|
||||||
|
|
||||||
error_t trackMount()
|
error_t trackTarget()
|
||||||
{
|
{
|
||||||
|
*_stopTracking = false;
|
||||||
|
|
||||||
return _trackingFunc();
|
return _trackingFunc();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
error_t stoptTracking()
|
||||||
error_t stopTracking()
|
|
||||||
{
|
{
|
||||||
*_stopTracking = true;
|
*_stopTracking = true;
|
||||||
|
|
||||||
return MccSimpleTrackingModelErrorCode::ERROR_OK;
|
return MccSimpleTrackingModelErrorCode::ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
error_t setTrackingParams(tracking_params_t params)
|
error_t setTrackingParams(tracking_params_t params)
|
||||||
{
|
{
|
||||||
std::lock_guard lock{*_currentTrackParamsMutex};
|
std::lock_guard lock{*_currentParamsMutex};
|
||||||
|
|
||||||
_currentTrackParams = std::move(params);
|
_currentParams = std::move(params);
|
||||||
|
|
||||||
return MccSimpleTrackingModelErrorCode::ERROR_OK;
|
return MccSimpleTrackingModelErrorCode::ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
tracking_params_t getTrackingParams() const
|
tracking_params_t getTrackingParams() const
|
||||||
{
|
{
|
||||||
std::lock_guard lock{*_currentTrackParamsMutex};
|
std::lock_guard lock{*_currentParamsMutex};
|
||||||
|
|
||||||
return _currentTrackParams;
|
return _currentParams;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::function<error_t()> _trackingFunc{};
|
std::function<error_t()> _trackingFunc{};
|
||||||
std::unique_ptr<std::atomic_bool> _stopTracking{};
|
std::unique_ptr<std::atomic_bool> _stopTracking;
|
||||||
|
|
||||||
tracking_params_t _currentTrackParams;
|
tracking_params_t _currentParams{};
|
||||||
std::unique_ptr<std::mutex> _currentTrackParamsMutex;
|
std::unique_ptr<std::mutex> _currentParamsMutex{};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace mcc
|
} // namespace mcc
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user