mountcontrol/cxx/mount.h
2025-03-11 18:30:23 +03:00

146 lines
3.7 KiB
C++

#pragma once
/* MOUNT CONTROL COMPONENTS LIBRARY */
#include <atomic>
#include <chrono>
#include <concepts>
#include <cstdint>
#include <functional>
#include <string_view>
#include "spdlog/sinks/null_sink.h"
// low-level functions
namespace lowlevel
{
#include "../LibSidServo/sidservo.h"
} // namespace lowlevel
namespace mcc
{
enum class MccMountType : uint8_t { GERMAN_TYPE, FORK_TYPE, CROSSAXIS_TYPE, ALTAZ_TYPE };
// mount state type concept
template <typename T>
concept mcc_mount_state_c = requires(T t, const T t_const) {
{ t_const.ident() } -> std::same_as<std::string_view>;
{ t.enter() } -> std::same_as<void>;
{ t.exit() } -> std::same_as<void>;
};
// implements a Finite State Machine Pattern
template <MccMountType MOUNT_TYPE>
class MccMount
{
typedef double mnt_coord_t;
typedef double mnt_speed_t;
typedef double time_point_t;
public:
static constexpr MccMountType mountType = MOUNT_TYPE;
/* low-level hardware related constants */
// number of attempts to get low-level hardware data before emit an error
static constexpr uint8_t LOWLEVEL_HW_POLL_ATTEMPTS = 10;
/* mount main-cycle variable quantities (mount orientation) */
struct mount_orient_t {
// time-related
std::chrono::system_clock::time_point utc;
time_point_t mjd; // modified Julian date
time_point_t siderTime; // sideral time (in radians)
// apparent target (user-input) current coordinates (in radians)
mnt_coord_t tagRA, tagDEC;
mnt_coord_t tagHA;
mnt_coord_t tagAZ, tagZD;
// encoder-measured current mount coordinates (in radians)
mnt_coord_t mntRA, mntDEC;
mnt_coord_t mntHA;
mnt_coord_t mntAZ, mntZD;
// encoder-measured current mount moving speed (in radians/s)
mnt_speed_t mntSpeedX,
mntSpeedY; // X - HA, Y - DEC for equatorial-type mount; X - AZ, Y - ZD for horizontal-type one
// current refraction coefficient
mnt_coord_t currRefr;
// PCS (pointing correction system) corrections
mnt_coord_t pcsX, pcsY; // X - HA, Y - DEC for equatorial-type mount; X - AZ, Y - ZD for horizontal-type one
// mount current state
};
struct mount_config_t {
uint8_t hw_poll_attempts = LOWLEVEL_HW_POLL_ATTEMPTS;
};
MccMount(std::shared_ptr<spdlog::logger> logger = spdlog::null_logger_mt("NULL"))
: _mountLogger(logger), _exitCurrentState([]() {})
{
}
virtual ~MccMount() {}
template <mcc_mount_state_c StateT>
void setMountState(StateT& state)
{
_exitCurrentState(); // exit from current state
_exitCurrentState = [&state]() { state.exit(); };
state.enter();
}
mount_orient_t getMountData() const noexcept
{
return _currentMountOrient.load();
}
protected:
mount_config_t _mountCurrentConfig;
std::shared_ptr<spdlog::logger> _mountLogger;
std::function<void()> _exitCurrentState;
std::atomic<mount_orient_t> _currentMountOrient;
void updateMountState()
{
mount_orient_t orient;
lowlevel::mountdata_t hw_mdata;
// get data from encoders
decltype(mount_config_t::hw_poll_attempts) n_attempts = 0;
do {
auto ret_code = lowlevel::Mount.getMountData(&hw_mdata);
if (ret_code != lowlevel::MCC_E_OK) {
++n_attempts;
}
} while (n_attempts < _mountCurrentConfig.hw_poll_attempts);
if (n_attempts >= _mountCurrentConfig.hw_poll_attempts) {
// log error heres
return;
}
_currentMountOrient.store(orient);
}
};
} // namespace mcc