...
This commit is contained in:
parent
464c262e08
commit
9cd52267d6
@ -134,7 +134,10 @@ target_include_directories(${MCC_LIBRARY} INTERFACE ${FITPACK_INCLUDE_DIR})
|
||||
|
||||
set(ASIBFM700_LIB_SRC asibfm700_hardware.h asibfm700_hardware.cpp)
|
||||
set(ASIBFM700_LIB asibfm700)
|
||||
add_library(${ASIBFM700_LIB} STATIC ${ASIBFM700_LIB_SRC})
|
||||
add_library(${ASIBFM700_LIB} STATIC ${ASIBFM700_LIB_SRC}
|
||||
asibfm700_slew_model.h asibfm700_slew_model.cpp
|
||||
asibfm700_common.h)
|
||||
target_include_directories(${ASIBFM700_LIB} PRIVATE ${FITPACK_INCLUDE_DIR})
|
||||
|
||||
# set(MOUNT_SERVER_APP_SRC mount.h mount_state.h mount_server.cpp comm_server.h comm_server_endpoint.h comm_server_configfile.h mount_astrom.h
|
||||
# mount_astrom_default.h mcc_coord.h mount_pz.h mcc_fsm.h mcc_fsm_utils.h mcc_finite_state_machine.h mcc_mount_events_states.h)
|
||||
|
||||
45
cxx/asibfm700_common.h
Normal file
45
cxx/asibfm700_common.h
Normal file
@ -0,0 +1,45 @@
|
||||
#pragma once
|
||||
|
||||
/* AstroSIB-FM700 FORK MOUNT CONTROL LIBRARY */
|
||||
|
||||
/* COMMON DEFINITIONS */
|
||||
|
||||
|
||||
#include "mcc_mount_astro_erfa.h"
|
||||
#include "mcc_mount_pec.h"
|
||||
#include "mcc_mount_telemetry.h"
|
||||
|
||||
#include "asibfm700_hardware.h"
|
||||
|
||||
namespace asibfm700
|
||||
{
|
||||
|
||||
typedef mcc::astrom::erfa::MccMountAstromEngineERFA<mcc::MccAngle> AsibFM700AstromEngine;
|
||||
|
||||
typedef mcc::MccMountDefaultPEC<mcc::MccMountType::FORK_TYPE> AsibFM700PointingErrorCorrection;
|
||||
|
||||
struct AsibFM700TelemetryData : mcc::MccMountTelemetryData<AsibFM700AstromEngine, AsibFM700PointingErrorCorrection> {
|
||||
// apparent target (user-input) current coordinates
|
||||
coord_t tagRA, tagDEC;
|
||||
coord_t tagHA;
|
||||
coord_t tagAZ, tagALT;
|
||||
coord_t tagPA;
|
||||
};
|
||||
|
||||
typedef mcc::MccMountTelemetry<AsibFM700AstromEngine,
|
||||
AsibFM700PointingErrorCorrection,
|
||||
AsibFM700Hardware,
|
||||
AsibFM700TelemetryData>
|
||||
AsibFM700Telemetry;
|
||||
|
||||
|
||||
// global mount configuration
|
||||
|
||||
struct AsibFM700Config {
|
||||
std::chrono::milliseconds hardwareAskingPeriod{100}; // main cycle period
|
||||
|
||||
// mount hardware config
|
||||
AsibFM700Hardware::hardware_config_t hardwareConfig;
|
||||
};
|
||||
|
||||
} // namespace asibfm700
|
||||
@ -93,7 +93,8 @@ std::string_view AsibFM700Hardware::id() const
|
||||
|
||||
AsibFM700Hardware::error_t AsibFM700Hardware::setPos(AsibFM700Hardware::axes_pos_t pos)
|
||||
{
|
||||
double X = pos.x, Y = pos.y;
|
||||
// according to hardware configuration (encoders pins (Eddy said)) X is DEC-axis and Y is HA-axis
|
||||
double X = pos.y, Y = pos.x;
|
||||
auto err = static_cast<AsibFM700HardwareErrorCode>(Mount.moveTo(&X, &Y));
|
||||
|
||||
return err;
|
||||
@ -115,8 +116,9 @@ AsibFM700Hardware::error_t AsibFM700Hardware::getPos(AsibFM700Hardware::axes_pos
|
||||
|
||||
pos.time_point = time_point_t{std::chrono::duration_cast<time_point_t::duration>(secs)};
|
||||
|
||||
pos.x = data.encposition.X;
|
||||
pos.y = data.encposition.Y;
|
||||
// according to hardware configuration (encoders pins (Eddy said)) X is DEC-axis and Y is HA-axis
|
||||
pos.x = data.encposition.Y;
|
||||
pos.y = data.encposition.X;
|
||||
}
|
||||
|
||||
return err;
|
||||
|
||||
@ -71,20 +71,6 @@ public:
|
||||
coord_t x, y;
|
||||
};
|
||||
|
||||
// c++ish wrapper to 'conf_t' struct
|
||||
|
||||
struct device_config_t {
|
||||
std::string MountDevPath; // path to mount device
|
||||
int MountDevSpeed; // serial speed
|
||||
std::string EncoderDevPath; // path to encoder device
|
||||
int EncoderDevSpeed; // serial speed
|
||||
int SepEncoder; // ==1 if encoder works as separate serial device, ==2 if there's new version with two devices
|
||||
std::string EncoderXDevPath; // paths to new controller devices
|
||||
std::string EncoderYDevPath;
|
||||
double MountReqInterval; // interval between subsequent mount requests (seconds)
|
||||
double EncoderReqInterval; // interval between subsequent encoder requests (seconds)
|
||||
};
|
||||
|
||||
|
||||
struct hardware_config_t {
|
||||
// the 'char*' fields from conf_t:
|
||||
@ -113,6 +99,7 @@ public:
|
||||
|
||||
error_t setPos(axes_pos_t);
|
||||
error_t getPos(axes_pos_t&);
|
||||
|
||||
error_t stop();
|
||||
error_t init();
|
||||
|
||||
|
||||
110
cxx/asibfm700_slew_model.cpp
Normal file
110
cxx/asibfm700_slew_model.cpp
Normal file
@ -0,0 +1,110 @@
|
||||
#include "asibfm700_slew_model.h"
|
||||
|
||||
|
||||
namespace asibfm700
|
||||
{
|
||||
|
||||
/* error category implementation */
|
||||
|
||||
const char* AsibFM700SlewModelErrorCategory::name() const noexcept
|
||||
{
|
||||
return "ASTROSIB FM700 MOUNT SLEW MODEL ERROR CATEGORY";
|
||||
}
|
||||
|
||||
std::string AsibFM700SlewModelErrorCategory::message(int ec) const
|
||||
{
|
||||
AsibFM700SlewModelErrorCode code = static_cast<AsibFM700SlewModelErrorCode>(ec);
|
||||
|
||||
std::string msg;
|
||||
|
||||
switch (code) {
|
||||
case AsibFM700SlewModelErrorCode::ERROR_OK:
|
||||
msg = "OK";
|
||||
default:
|
||||
msg = "UNKNOWN ERROR";
|
||||
}
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
const AsibFM700SlewModelErrorCategory& AsibFM700SlewModelErrorCategory::get()
|
||||
{
|
||||
static const AsibFM700SlewModelErrorCategory constInst;
|
||||
return constInst;
|
||||
}
|
||||
|
||||
|
||||
AsibFM700SlewModel::AsibFM700SlewModel(AsibFM700Hardware& hw_control, AsibFM700AstromEngine& astrom_engine)
|
||||
: _hwControl(hw_control), _astromEngine(astrom_engine)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
AsibFM700SlewModel::error_t AsibFM700SlewModel::slew(const slew_params_t& slew_pars, AsibFM700Telemetry& telemetry)
|
||||
{
|
||||
using astrom_t = std::remove_reference_t<decltype(_astromEngine)>;
|
||||
using coord_t = typename astrom_t::coord_t;
|
||||
using jd_t = typename astrom_t::juldate_t;
|
||||
|
||||
AsibFM700SlewModel::error_t res_err = AsibFM700SlewModelErrorCode::ERROR_OK;
|
||||
|
||||
AsibFM700Hardware::axes_pos_t ax_pos;
|
||||
|
||||
if (slew_pars.coordPairKind == mcc::MccCoordPairKind::COORDS_KIND_XY) {
|
||||
// trivial case (the pair is interpretated as raw encoder coordinates)
|
||||
ax_pos.x = slew_pars.x;
|
||||
ax_pos.y = slew_pars.y;
|
||||
} else if (slew_pars.coordPairKind == mcc::MccCoordPairKind::COORDS_KIND_RADEC_ICRS) { // catalog coordinates
|
||||
jd_t jd;
|
||||
coord_t ra_app, dec_app, ha, az, alt;
|
||||
typename astrom_t::eo_t eo;
|
||||
|
||||
auto err = _astromEngine.greg2jul(std::chrono::system_clock::now(), jd);
|
||||
|
||||
if (!err) {
|
||||
err = _astromEngine.icrs2obs(slew_pars.x, slew_pars.y, jd, ra_app, dec_app, ha, az, alt, eo);
|
||||
|
||||
if (!err) {
|
||||
res_err = slew({.coordPairKind = mcc::MccCoordPairKind::COORDS_KIND_HADEC_APP,
|
||||
.x = ha,
|
||||
.y = dec_app,
|
||||
.stop = slew_pars.stop},
|
||||
telemetry);
|
||||
}
|
||||
}
|
||||
|
||||
} else if (slew_pars.coordPairKind == mcc::MccCoordPairKind::COORDS_KIND_RADEC_APP) { // apparent
|
||||
jd_t jd;
|
||||
typename astrom_t::eo_t eo;
|
||||
|
||||
auto err = _astromEngine.greg2jul(std::chrono::system_clock::now(), jd);
|
||||
if (!err) {
|
||||
typename astrom_t::sideral_time_t lst;
|
||||
err = _astromEngine.apparentSiderTime(jd, lst, true);
|
||||
|
||||
if (!err) {
|
||||
err = _astromEngine.eqOrigins(jd, eo);
|
||||
if (!err) {
|
||||
res_err = slew({.coordPairKind = mcc::MccCoordPairKind::COORDS_KIND_HADEC_APP,
|
||||
.x = lst - slew_pars.x + eo, // HA = LST - RA_APP + EO
|
||||
.y = slew_pars.y,
|
||||
.stop = slew_pars.stop},
|
||||
telemetry);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (slew_pars.coordPairKind == mcc::MccCoordPairKind::COORDS_KIND_HADEC_APP) { // apparent
|
||||
// compute encoders coordinates
|
||||
} else if (slew_pars.coordPairKind == mcc::MccCoordPairKind::COORDS_KIND_AZALT) {
|
||||
} else if (slew_pars.coordPairKind == mcc::MccCoordPairKind::COORDS_KIND_AZZD) {
|
||||
}
|
||||
|
||||
auto err = _hwControl.setPos(std::move(ax_pos));
|
||||
|
||||
while (true) {
|
||||
}
|
||||
|
||||
return res_err;
|
||||
}
|
||||
|
||||
} // namespace asibfm700
|
||||
75
cxx/asibfm700_slew_model.h
Normal file
75
cxx/asibfm700_slew_model.h
Normal file
@ -0,0 +1,75 @@
|
||||
#pragma once
|
||||
|
||||
/* AstroSIB-FM700 FORK MOUNT CONTROL LIBRARY */
|
||||
|
||||
/* SLEW MODEL IMPLEMENTATION */
|
||||
|
||||
|
||||
#include "asibfm700_common.h"
|
||||
|
||||
namespace asibfm700
|
||||
{
|
||||
|
||||
enum class AsibFM700SlewModelErrorCode : int { ERROR_OK };
|
||||
|
||||
// error category
|
||||
struct AsibFM700SlewModelErrorCategory : public std::error_category {
|
||||
const char* name() const noexcept;
|
||||
std::string message(int ec) const;
|
||||
|
||||
static const AsibFM700SlewModelErrorCategory& get();
|
||||
};
|
||||
|
||||
|
||||
inline std::error_code make_error_code(AsibFM700SlewModelErrorCode ec)
|
||||
{
|
||||
return std::error_code(static_cast<int>(ec), AsibFM700SlewModelErrorCategory::get());
|
||||
}
|
||||
|
||||
} // namespace asibfm700
|
||||
|
||||
|
||||
|
||||
namespace std
|
||||
{
|
||||
|
||||
template <>
|
||||
class is_error_code_enum<asibfm700::AsibFM700SlewModelErrorCode> : public true_type
|
||||
{
|
||||
};
|
||||
|
||||
} // namespace std
|
||||
|
||||
|
||||
|
||||
namespace asibfm700
|
||||
{
|
||||
|
||||
class AsibFM700SlewModel final
|
||||
{
|
||||
public:
|
||||
typedef std::error_code error_t;
|
||||
|
||||
struct slew_params_t {
|
||||
typedef mcc::MccAngle coord_t;
|
||||
|
||||
mcc::MccCoordPairKind coordPairKind{mcc::MccCoordPairKind::COORDS_KIND_HADEC_APP};
|
||||
|
||||
coord_t x{0.0};
|
||||
coord_t y{0.0};
|
||||
|
||||
bool stop{false};
|
||||
};
|
||||
|
||||
AsibFM700SlewModel(AsibFM700Hardware& hw_control, AsibFM700AstromEngine& astrom_engine);
|
||||
|
||||
~AsibFM700SlewModel();
|
||||
|
||||
error_t slew(const slew_params_t&, AsibFM700Telemetry&);
|
||||
|
||||
private:
|
||||
AsibFM700Hardware& _hwControl;
|
||||
AsibFM700AstromEngine& _astromEngine;
|
||||
};
|
||||
|
||||
} // namespace asibfm700
|
||||
@ -186,6 +186,7 @@ concept mcc_mount_hardware_c = !std::copyable<T> && std::movable<T> && requires(
|
||||
|
||||
{ t.setPos(std::declval<typename T::axes_pos_t>()) } -> std::same_as<typename T::error_t>;
|
||||
{ t.getPos(std::declval<typename T::axes_pos_t&>()) } -> std::same_as<typename T::error_t>;
|
||||
|
||||
{ t.stop() } -> std::same_as<typename T::error_t>;
|
||||
{ t.init() } -> std::same_as<typename T::error_t>;
|
||||
};
|
||||
@ -215,7 +216,7 @@ concept mcc_mount_pec_c = requires(T t, const T t_const) {
|
||||
|
||||
{
|
||||
t.compute(std::declval<const typename T::coord_t&>(), std::declval<const typename T::coord_t&>(),
|
||||
std::declval<typename T::pec_result_t>())
|
||||
std::declval<typename T::pec_result_t&>())
|
||||
} -> std::same_as<typename T::error_t>;
|
||||
};
|
||||
|
||||
@ -226,6 +227,7 @@ concept mcc_mount_pec_c = requires(T t, const T t_const) {
|
||||
template <typename T>
|
||||
concept mcc_mount_telemetry_data_c = requires(T telemetry) {
|
||||
typename T::coord_t;
|
||||
typename T::time_point_t;
|
||||
|
||||
// // target current coordinates
|
||||
// requires std::same_as<decltype(telemetry.tagRA), typename T::coord_t>; // apparent RA
|
||||
@ -297,7 +299,7 @@ concept mcc_slew_params_c = std::movable<T> && requires(T t) {
|
||||
|
||||
template <typename T, typename TelemetryT>
|
||||
concept mcc_slew_model_c = mcc_mount_telemetry_c<TelemetryT> && requires(T t) {
|
||||
typename T::error_t;
|
||||
requires mcc_error_c<typename T::error_t>;
|
||||
requires mcc_slew_params_c<typename T::slew_params_t>;
|
||||
|
||||
{
|
||||
|
||||
@ -397,7 +397,9 @@ static auto operator*(const T1& v1, const T2& v2)
|
||||
} else if constexpr (std::is_arithmetic_v<T2>) {
|
||||
return v1 *= v2;
|
||||
} else {
|
||||
static_assert(false, "INCOMPATIBLE TYPES!");
|
||||
using res_t = std::conditional_t<std::convertible_to<T1, T2> && std::derived_from<T1, MccAngle>, T1, T2>;
|
||||
return res_t{(double)v1 * (double)v2};
|
||||
// static_assert(false, "INCOMPATIBLE TYPES!");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -28,6 +28,7 @@ class MccMountDefaultPEC final
|
||||
public:
|
||||
static constexpr MccMountType mountType = MOUNT_TYPE;
|
||||
|
||||
typedef std::error_code error_t;
|
||||
typedef MccAngle coord_t;
|
||||
|
||||
struct pec_result_t {
|
||||
@ -117,11 +118,12 @@ public:
|
||||
return _pecData.type;
|
||||
}
|
||||
|
||||
// X and Y axis encoder coordinates
|
||||
pec_result_t compute(const coord_t& x, const coord_t& y)
|
||||
// The computed PEC quantities must be interpretated as:
|
||||
// apparent_X = encoder_X + pec_result_t.dx
|
||||
// apparent_Y = encoder_Y + pec_result_t.dy
|
||||
// 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)
|
||||
{
|
||||
pec_result_t res{0.0, 0.0};
|
||||
|
||||
std::lock_guard lock(_pecDataMutex);
|
||||
|
||||
if constexpr (mcc_is_equatorial_mount<MOUNT_TYPE>) { // equatorial
|
||||
@ -163,7 +165,7 @@ public:
|
||||
if (ret) {
|
||||
res.dx = std::numeric_limits<double>::quiet_NaN();
|
||||
res.dy = std::numeric_limits<double>::quiet_NaN();
|
||||
return res;
|
||||
return std::error_code(); // !!!!!!!!!!!!!!
|
||||
}
|
||||
|
||||
|
||||
@ -173,7 +175,7 @@ public:
|
||||
if (ret) {
|
||||
res.dx = std::numeric_limits<double>::quiet_NaN();
|
||||
res.dy = std::numeric_limits<double>::quiet_NaN();
|
||||
return res;
|
||||
return std::error_code(); // !!!!!!!!!!!!!!
|
||||
}
|
||||
|
||||
|
||||
@ -185,9 +187,48 @@ public:
|
||||
static_assert(false, "UNSUPPORTED");
|
||||
}
|
||||
|
||||
return res;
|
||||
return std::error_code();
|
||||
}
|
||||
|
||||
// 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 xp, yp;
|
||||
size_t iter = 1;
|
||||
|
||||
// the first iteration
|
||||
auto err = compute(x, y, res);
|
||||
|
||||
if (!err) {
|
||||
xp = x - res.dx;
|
||||
yp = y - res.dy;
|
||||
|
||||
bool ok = ((xp - x) * (xp - x) + (yp - y) * (yp - y)) <= e2;
|
||||
if (ok) {
|
||||
return std::error_code();
|
||||
}
|
||||
|
||||
while (iter < max_iter) {
|
||||
xi = xp;
|
||||
yi = xp;
|
||||
err = compute(xi, yi, res);
|
||||
xp -= res.dx;
|
||||
yp -= res.dy;
|
||||
|
||||
ok = ((xp - xi) * (xp - xi) + (yp - yi) * (yp - yi)) <= e2;
|
||||
if (ok) {
|
||||
return std::error_code();
|
||||
}
|
||||
}
|
||||
|
||||
// err = "exceed max iterations";!!!
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
@ -203,4 +244,7 @@ private:
|
||||
typedef MccMountDefaultPEC<MccMountType::ALTAZ_TYPE> MccMountDefaultAltAzPec;
|
||||
typedef MccMountDefaultPEC<MccMountType::FORK_TYPE> MccMountDefaultForkPec;
|
||||
|
||||
static_assert(traits::mcc_mount_pec_c<MccMountDefaultForkPec>, "");
|
||||
|
||||
|
||||
} // namespace mcc
|
||||
|
||||
@ -13,9 +13,95 @@ namespace mcc
|
||||
{
|
||||
|
||||
|
||||
namespace traits
|
||||
{
|
||||
|
||||
/* enhanced telemetry data concept */
|
||||
/* in general it correspond to definitions used in astrometry engine (see its concept) */
|
||||
|
||||
template <typename T, typename ASTROM_ENGINE_T, typename PEC_T>
|
||||
concept mcc_mount_telemetry_enh_data_c = mcc_mount_telemetry_data_c<T> && requires(T t) {
|
||||
requires traits::mcc_astrom_engine_c<ASTROM_ENGINE_T>;
|
||||
requires traits::mcc_mount_pec_c<PEC_T>;
|
||||
|
||||
// check for types definitions and its consistency
|
||||
requires std::same_as<typename T::coord_t, typename ASTROM_ENGINE_T::coord_t>;
|
||||
|
||||
requires std::same_as<typename T::time_point_t, typename ASTROM_ENGINE_T::time_point_t>;
|
||||
|
||||
requires std::same_as<typename T::juldate_t,
|
||||
typename ASTROM_ENGINE_T::juldate_t>; // a type to represent Julian date
|
||||
|
||||
requires std::same_as<typename T::sideral_time_t,
|
||||
typename ASTROM_ENGINE_T::sideral_time_t>; // a type to represent sideral time
|
||||
|
||||
requires std::same_as<typename T::pa_t,
|
||||
typename ASTROM_ENGINE_T::pa_t>; // a type to represent parallactic angle
|
||||
// typename T::eo_t; // a type to represent equation of origins
|
||||
|
||||
requires std::same_as<decltype(t.jd), typename T::juldate_t>; // Julian date
|
||||
requires std::same_as<decltype(t.siderTime), typename T::sideral_time_t>; // sideral time
|
||||
requires std::same_as<decltype(t.mntRA), typename T::pa_t>; // parallactic angle
|
||||
|
||||
// encoder-measured (non-corrected for PCS) current mount position and moving speed (in radians, radians/s)
|
||||
// X - HA, Y - DEC for equatorial-type mount; X - AZ, Y - ALT for horizontal-type one
|
||||
requires std::same_as<decltype(t.mntPosX), typename T::coord_t>;
|
||||
requires std::same_as<decltype(t.mntPosY), typename T::coord_t>;
|
||||
|
||||
// current refraction coefficients
|
||||
requires std::same_as<decltype(t.currRefrCoeffs), typename PEC_T::pec_result_t>;
|
||||
// current refraction correction (for mntALT)
|
||||
requires std::same_as<decltype(t.currRefr), typename T::coord_t>;
|
||||
|
||||
// PEC (pointing error correction):
|
||||
// X - HA, Y - DEC for equatorial-type mount; X - AZ, Y - ALT for horizontal-type one
|
||||
requires std::same_as<decltype(t.pecX), typename T::coord_t>;
|
||||
requires std::same_as<decltype(t.pecY), typename T::coord_t>;
|
||||
};
|
||||
|
||||
} // namespace traits
|
||||
|
||||
|
||||
// default generic telemetry data definition
|
||||
template <traits::mcc_astrom_engine_c ASTROM_ENGINE_T, traits::mcc_mount_pec_c PEC_T>
|
||||
struct MccMountTelemetryData {
|
||||
typedef typename ASTROM_ENGINE_T::coord_t coord_t;
|
||||
typedef typename ASTROM_ENGINE_T::time_point_t time_point_t;
|
||||
typedef typename ASTROM_ENGINE_T::juldate_t juldate_t;
|
||||
typedef typename ASTROM_ENGINE_T::sideral_time_t sideral_time_t;
|
||||
typedef typename ASTROM_ENGINE_T::pa_t pa_t;
|
||||
|
||||
// time-related
|
||||
time_point_t utc; // time point of measurements, UTC
|
||||
juldate_t jd; // Julian date
|
||||
sideral_time_t siderTime; // local apperant sideral time
|
||||
|
||||
// encoder-measured current mount coordinates
|
||||
coord_t mntRA, mntDEC;
|
||||
coord_t mntHA;
|
||||
coord_t mntAZ, mntALT;
|
||||
pa_t mntPA;
|
||||
|
||||
// encoder-measured (non-corrected for PCS) current mount position
|
||||
// X - HA, Y - DEC for equatorial-type mount; X - AZ, Y - ALT for horizontal-type one
|
||||
coord_t mntPosX, mntPosY;
|
||||
|
||||
// current refraction coefficients
|
||||
typename PEC_T::pec_result_t currRefrCoeffs;
|
||||
|
||||
// current refraction correction (for mntALT)
|
||||
coord_t currRefr;
|
||||
|
||||
// PEC (pointing error correction):
|
||||
// X - HA, Y - DEC for equatorial-type mount; X - AZ, Y - ALT for horizontal-type one
|
||||
coord_t pecX, pecY;
|
||||
};
|
||||
|
||||
template <traits::mcc_astrom_engine_c ASTROM_ENGINE_T,
|
||||
traits::mcc_mount_pec_c PEC_T,
|
||||
traits::mcc_mount_hardware_c HARDWARE_T>
|
||||
traits::mcc_mount_hardware_c HARDWARE_T,
|
||||
traits::mcc_mount_telemetry_enh_data_c<ASTROM_ENGINE_T, PEC_T> DATA_T =
|
||||
MccMountTelemetryData<ASTROM_ENGINE_T, PEC_T>>
|
||||
class MccMountTelemetry
|
||||
{
|
||||
public:
|
||||
@ -51,42 +137,44 @@ public:
|
||||
static_assert(std::convertible_to<typename hardware_t::time_point_t, typename astrom_engine_t::time_point_t>,
|
||||
"HARDWARE TIME-POINT TYPE MUST BE CONVERTIBLE TO ASTROMETRY ENGINE ONE!");
|
||||
|
||||
typedef DATA_T mount_telemetry_data_t;
|
||||
|
||||
// mount current telemetry data: time, position and related quantities
|
||||
struct mount_telemetry_data_t {
|
||||
typedef typename astrom_engine_t::coord_t coord_t;
|
||||
// struct mount_telemetry_data_t {
|
||||
// typedef typename astrom_engine_t::coord_t coord_t;
|
||||
|
||||
// time-related
|
||||
typename astrom_engine_t::time_point_t utc; // time point of measurements, UTC
|
||||
typename astrom_engine_t::juldate_t jd; // Julian date
|
||||
typename astrom_engine_t::sideral_time_t siderTime; // local apperant sideral time
|
||||
// typename astrom_engine_t::time_point_t ut1; // Universal time
|
||||
// typename astrom_engine_t::time_point_t tt; // Terrestial time
|
||||
// // time-related
|
||||
// typename astrom_engine_t::time_point_t utc; // time point of measurements, UTC
|
||||
// typename astrom_engine_t::juldate_t jd; // Julian date
|
||||
// typename astrom_engine_t::sideral_time_t siderTime; // local apperant sideral time
|
||||
// // typename astrom_engine_t::time_point_t ut1; // Universal time
|
||||
// // typename astrom_engine_t::time_point_t tt; // Terrestial time
|
||||
|
||||
// apparent target (user-input) current coordinates (in radians)
|
||||
coord_t tagRA, tagDEC;
|
||||
coord_t tagHA;
|
||||
coord_t tagAZ, tagALT;
|
||||
coord_t tagPA; // paralactic angle
|
||||
// // apparent target (user-input) current coordinates (in radians)
|
||||
// coord_t tagRA, tagDEC;
|
||||
// coord_t tagHA;
|
||||
// coord_t tagAZ, tagALT;
|
||||
// coord_t tagPA; // paralactic angle
|
||||
|
||||
// encoder-measured current mount coordinates (in radians)
|
||||
coord_t mntRA, mntDEC;
|
||||
coord_t mntHA;
|
||||
coord_t mntAZ, mntALT;
|
||||
typename astrom_engine_t::pa_t mntPA;
|
||||
// // encoder-measured current mount coordinates (in radians)
|
||||
// coord_t mntRA, mntDEC;
|
||||
// coord_t mntHA;
|
||||
// coord_t mntAZ, mntALT;
|
||||
// typename astrom_engine_t::pa_t mntPA;
|
||||
|
||||
// encoder-measured (non-corrected for PCS) current mount position and moving speed (in radians, radians/s)
|
||||
// X - HA, Y - DEC for equatorial-type mount; X - AZ, Y - ALT for horizontal-type one
|
||||
coord_t mntPosX, mntPosY;
|
||||
// // encoder-measured (non-corrected for PCS) current mount position and moving speed (in radians, radians/s)
|
||||
// // X - HA, Y - DEC for equatorial-type mount; X - AZ, Y - ALT for horizontal-type one
|
||||
// coord_t mntPosX, mntPosY;
|
||||
|
||||
// current refraction coefficients
|
||||
typename pec_t::pec_result_t currRefrCoeffs;
|
||||
// current refraction correction (for mntALT)
|
||||
coord_t currRefr;
|
||||
// // current refraction coefficients
|
||||
// typename pec_t::pec_result_t currRefrCoeffs;
|
||||
// // current refraction correction (for mntALT)
|
||||
// coord_t currRefr;
|
||||
|
||||
// PEC (pointing error correction):
|
||||
// X - HA, Y - DEC for equatorial-type mount; X - AZ, Y - ALT for horizontal-type one
|
||||
coord_t pecX, pecY;
|
||||
};
|
||||
// // PEC (pointing error correction):
|
||||
// // X - HA, Y - DEC for equatorial-type mount; X - AZ, Y - ALT for horizontal-type one
|
||||
// coord_t pecX, pecY;
|
||||
// };
|
||||
|
||||
MccMountTelemetry(astrom_engine_t& astrom_engine, pec_t& pec, hardware_t& hardware)
|
||||
: _astromEngine(astrom_engine), _pec(pec), _hardware(hardware)
|
||||
|
||||
212
cxx/mcc_slew_model.h
Normal file
212
cxx/mcc_slew_model.h
Normal file
@ -0,0 +1,212 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
/* MOUNT CONTROL COMPONENTS LIBRARY */
|
||||
|
||||
|
||||
/* A VERY SIMPLE SLEW MODEL GENERIC IMPLEMENTATION */
|
||||
|
||||
|
||||
#include "mcc_mount_concepts.h"
|
||||
|
||||
namespace mcc
|
||||
{
|
||||
|
||||
|
||||
/*
|
||||
* WARNING: it is assumed that coordinates are in radians!
|
||||
* but this fact is only used if slew coordinate pair are given as
|
||||
* [azimuth, zenithal distance] (see sources code below)
|
||||
*/
|
||||
|
||||
template <traits::mcc_mount_telemetry_c TELEMETRY_T>
|
||||
class MccSimpleSlewModel
|
||||
{
|
||||
public:
|
||||
typedef std::error_code error_t;
|
||||
|
||||
struct slew_params_t {
|
||||
typedef mcc::MccAngle coord_t;
|
||||
|
||||
mcc::MccCoordPairKind coordPairKind{mcc::MccCoordPairKind::COORDS_KIND_HADEC_APP};
|
||||
|
||||
coord_t x{0.0};
|
||||
coord_t y{0.0};
|
||||
|
||||
bool stop{false};
|
||||
};
|
||||
|
||||
|
||||
template <traits::mcc_mount_hardware_c HARDWARE_T,
|
||||
traits::mcc_astrom_engine_c ASTROM_T,
|
||||
traits::mcc_mount_pec_c PEC_T>
|
||||
MccSimpleSlewModel(HARDWARE_T& hardware, ASTROM_T& astrom_engine, PEC_T& pec)
|
||||
{
|
||||
const auto p_hardware = &hardware;
|
||||
const auto p_astrom_engine = &astrom_engine;
|
||||
const auto p_pec = &pec;
|
||||
|
||||
|
||||
|
||||
_slewFunc = [p_hardware, p_astrom_engine, p_pec](this auto&& self, const slew_params_t& slew_pars,
|
||||
TELEMETRY_T& telemetry) {
|
||||
using coord_t = typename ASTROM_T::coord_t;
|
||||
using jd_t = typename ASTROM_T::juldate_t;
|
||||
|
||||
typename HARDWARE_T::axes_pos_t ax_pos;
|
||||
|
||||
error_t res_err;
|
||||
typename ASTROM_T::error_t ast_err;
|
||||
|
||||
if (slew_pars.coordPairKind == mcc::MccCoordPairKind::COORDS_KIND_XY) {
|
||||
// trivial case (the pair is interpretated as raw encoder coordinates)
|
||||
ax_pos.x = slew_pars.x;
|
||||
ax_pos.y = slew_pars.y;
|
||||
} else if (slew_pars.coordPairKind ==
|
||||
mcc::MccCoordPairKind::COORDS_KIND_RADEC_ICRS) { // catalog coordinates
|
||||
jd_t jd;
|
||||
coord_t ra_app, dec_app, ha, az, alt;
|
||||
typename ASTROM_T::eo_t eo;
|
||||
|
||||
ast_err = p_astrom_engine->greg2jul(std::chrono::system_clock::now(), jd);
|
||||
|
||||
if (!ast_err) {
|
||||
ast_err = p_astrom_engine->icrs2obs(slew_pars.x, slew_pars.y, jd, ra_app, dec_app, ha, az, alt, eo);
|
||||
|
||||
if (!ast_err) {
|
||||
if constexpr (mccIsEquatorialMount(PEC_T::mountType)) {
|
||||
res_err = self({.coordPairKind = mcc::MccCoordPairKind::COORDS_KIND_HADEC_APP,
|
||||
.x = ha,
|
||||
.y = dec_app,
|
||||
.stop = slew_pars.stop},
|
||||
telemetry);
|
||||
} else if constexpr (mccIsAltAzMount(PEC_T::mountType)) {
|
||||
res_err = self({.coordPairKind = mcc::MccCoordPairKind::COORDS_KIND_AZALT,
|
||||
.x = az,
|
||||
.y = alt,
|
||||
.stop = slew_pars.stop},
|
||||
telemetry);
|
||||
} else {
|
||||
static_assert(false, "UNKNOWN MOUNT TYPE!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else if (slew_pars.coordPairKind == mcc::MccCoordPairKind::COORDS_KIND_RADEC_APP) { // apparent
|
||||
jd_t jd;
|
||||
typename ASTROM_T::eo_t eo;
|
||||
|
||||
ast_err = p_astrom_engine->greg2jul(std::chrono::system_clock::now(), jd);
|
||||
if (!ast_err) {
|
||||
typename ASTROM_T::sideral_time_t lst;
|
||||
ast_err = p_astrom_engine->apparentSiderTime(jd, lst, true);
|
||||
|
||||
if (!ast_err) {
|
||||
ast_err = p_astrom_engine->eqOrigins(jd, eo);
|
||||
if (!ast_err) {
|
||||
res_err = self({.coordPairKind = mcc::MccCoordPairKind::COORDS_KIND_HADEC_APP,
|
||||
.x = lst - slew_pars.x + eo, // HA = LST - RA_APP + EO
|
||||
.y = slew_pars.y,
|
||||
.stop = slew_pars.stop},
|
||||
telemetry);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (slew_pars.coordPairKind == mcc::MccCoordPairKind::COORDS_KIND_HADEC_APP) { // apparent
|
||||
if constexpr (mccIsEquatorialMount(PEC_T::mountType)) { // compute encoder coordinates
|
||||
coord_t eps = 1.0 / 3600.0 * std::numbers::pi / 180.0;
|
||||
|
||||
typename PEC_T::pec_result_t pec_res;
|
||||
|
||||
auto err = p_pec->reverseCompute(slew_pars.x, slew_pars.y, pec_res, eps, 10);
|
||||
if (!err) {
|
||||
res_err = self({.coordPairKind = mcc::MccCoordPairKind::COORDS_KIND_XY,
|
||||
.x = slew_pars.x - pec_res.dx,
|
||||
.y = slew_pars.y - pec_res.dy,
|
||||
.stop = slew_pars.stop},
|
||||
telemetry);
|
||||
}
|
||||
} else if constexpr (mccIsAltAzMount(PEC_T::mountType)) {
|
||||
coord_t az, alt;
|
||||
|
||||
ast_err = p_astrom_engine->hadec2azalt(slew_pars.x, slew_pars.y, az, alt);
|
||||
|
||||
if (!ast_err) {
|
||||
res_err = self({.coordPairKind = mcc::MccCoordPairKind::COORDS_KIND_AZALT,
|
||||
.x = az,
|
||||
.y = alt,
|
||||
.stop = slew_pars.stop},
|
||||
telemetry);
|
||||
}
|
||||
} else {
|
||||
static_assert(false, "UNKNOWN MOUNT TYPE!");
|
||||
}
|
||||
} else if (slew_pars.coordPairKind == mcc::MccCoordPairKind::COORDS_KIND_AZALT) {
|
||||
if constexpr (mccIsEquatorialMount(PEC_T::mountType)) {
|
||||
coord_t ha, dec;
|
||||
|
||||
ast_err = p_astrom_engine->azalt2hadec(slew_pars.x, slew_pars.y, ha, dec);
|
||||
|
||||
if (!ast_err) {
|
||||
res_err = self({.coordPairKind = mcc::MccCoordPairKind::COORDS_KIND_HADEC_APP,
|
||||
.x = ha,
|
||||
.y = dec,
|
||||
.stop = slew_pars.stop},
|
||||
telemetry);
|
||||
}
|
||||
} else if constexpr (mccIsAltAzMount(PEC_T::mountType)) { // compute encoder coordinates
|
||||
coord_t eps = 1.0 / 3600.0 * std::numbers::pi / 180.0;
|
||||
|
||||
typename PEC_T::pec_result_t pec_res;
|
||||
|
||||
auto err = p_pec->reverseCompute(slew_pars.x, slew_pars.y, pec_res, eps, 10);
|
||||
if (!err) {
|
||||
res_err = self({.coordPairKind = mcc::MccCoordPairKind::COORDS_KIND_XY,
|
||||
.x = slew_pars.x - pec_res.dx,
|
||||
.y = slew_pars.y - pec_res.dy,
|
||||
.stop = slew_pars.stop},
|
||||
telemetry);
|
||||
}
|
||||
|
||||
} else {
|
||||
static_assert(false, "UNKNOWN MOUNT TYPE!");
|
||||
}
|
||||
} else if (slew_pars.coordPairKind == mcc::MccCoordPairKind::COORDS_KIND_AZZD) {
|
||||
//
|
||||
// WARNING: it is assumed that coordinates are in radians!
|
||||
//
|
||||
res_err = self({.coordPairKind = mcc::MccCoordPairKind::COORDS_KIND_AZALT,
|
||||
.x = slew_pars.x,
|
||||
.y = std::numbers::pi / 2.0 - slew_pars.y,
|
||||
.stop = slew_pars.stop},
|
||||
telemetry);
|
||||
}
|
||||
|
||||
if (res_err) {
|
||||
return res_err;
|
||||
}
|
||||
|
||||
if (!ast_err) {
|
||||
auto err = p_hardware->setPos(std::move(ax_pos));
|
||||
|
||||
while (true) {
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
error_t slew(const slew_params_t& pars, TELEMETRY_T& telemetry)
|
||||
{
|
||||
error_t res_err = _slewFunc(pars, telemetry);
|
||||
|
||||
return res_err;
|
||||
}
|
||||
|
||||
protected:
|
||||
std::function<error_t(const slew_params_t&, TELEMETRY_T&)> _slewFunc{};
|
||||
};
|
||||
|
||||
|
||||
// static_assert(traits::mcc_slew_model_c<>);
|
||||
|
||||
} // namespace mcc
|
||||
Loading…
x
Reference in New Issue
Block a user