This commit is contained in:
Timur A. Fatkhullin 2025-08-01 17:55:55 +03:00
parent 750d29ceb9
commit 9bfe1c3ad5
9 changed files with 125 additions and 265 deletions

View File

@ -132,11 +132,9 @@ target_compile_features(${MCC_LIBRARY} INTERFACE cxx_std_23)
target_include_directories(${MCC_LIBRARY} INTERFACE ${FITPACK_INCLUDE_DIR})
set(ASIBFM700_LIB_SRC asibfm700_hardware.h asibfm700_hardware.cpp)
set(ASIBFM700_LIB_SRC asibfm700_common.h asibfm700_hardware.h asibfm700_hardware.cpp)
set(ASIBFM700_LIB asibfm700)
add_library(${ASIBFM700_LIB} STATIC ${ASIBFM700_LIB_SRC}
asibfm700_slew_model.h asibfm700_slew_model.cpp
asibfm700_common.h)
add_library(${ASIBFM700_LIB} STATIC ${ASIBFM700_LIB_SRC})
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

View File

@ -5,11 +5,12 @@
/* COMMON DEFINITIONS */
#include "asibfm700_hardware.h"
#include "mcc_guiding_model.h"
#include "mcc_mount_astro_erfa.h"
#include "mcc_mount_pec.h"
#include "mcc_mount_telemetry.h"
#include "asibfm700_hardware.h"
#include "mcc_slew_model.h"
namespace asibfm700
{
@ -27,6 +28,21 @@ typedef mcc::MccMountTelemetry<AsibFM700AstromEngine,
AsibFM700Telemetry;
typedef mcc::MccSimpleSlewModel<> AsibFM700SlewModel;
typedef mcc::MccSimpleGuidingModel<> AsibFM700GuidingModel;
struct AsibMountControls {
AsibMountControls() : telemetry(astrometryEngine, PEC, hardware) {}
AsibFM700AstromEngine astrometryEngine;
AsibFM700PointingErrorCorrection PEC;
AsibFM700Hardware hardware;
AsibFM700Telemetry telemetry;
AsibFM700SlewModel slewModel;
AsibFM700GuidingModel guidingModel;
};
// global mount configuration
struct AsibFM700Config {

View File

@ -1,110 +0,0 @@
#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

View File

@ -1,75 +0,0 @@
#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

View File

@ -137,13 +137,7 @@ public:
typedef std::error_code error_t;
struct guiding_point_t : MccCelestialPoint {
coord_t corrThresh{(double)MccAngle("00:00:00.2"_dms)}; // correction threshold
coord_t correctionRange[2]{(double)MccAngle(0.5_arcsecs), (double)MccAngle(5.0_arcsecs)};
// timeout to wait telemetry update (in seconds, as floating-point)
std::chrono::duration<double> telemetryUpdateTimeout{1.0};
};
using guiding_point_t = MccSlewAndGuidingPoint;
template <traits::mcc_mount_controls_c MOUNT_CONTROLS_T, typename... LoggerCtorArgTs>
MccSimpleGuidingModel(MOUNT_CONTROLS_T& mount_controls, LoggerCtorArgTs&&... ctor_args)
@ -248,18 +242,21 @@ protected:
while (true) {
if (_stopRequested) {
res_err = MccSimpleGuidingModelErrorCode::ERROR_GUIDING_STOPPED;
// return MccSimpleGuidingModelErrorCode::ERROR_GUIDING_STOPPED;
// interpetate stoping as 'no error' exit
return MccSimpleGuidingModelErrorCode::ERROR_OK;
}
// suspend the thread here until telemetry data is updated
t_err = telemetry.waitForUpdatedData(t_data, guiding_point.telemetryUpdateTimeout);
// check prohibited zones ...
if (mccCheckInZonePZTuple(t_data, p_mount_controls->prohibitedZones, in_zone_flag)) {
return MccSimpleGuidingModelErrorCode::ERROR_IN_PROHIBITED_ZONE;
};
// suspend the thread here until telemetry data is updated
t_err = telemetry.waitForUpdatedData(t_data, guiding_point.telemetryUpdateTimeout);
if (t_err) {
std::string err_str = "An error occured while waiting for updated telemetry";
if constexpr (std::same_as<decltype(t_err), error_t>) {
@ -276,7 +273,8 @@ protected:
}
if (_stopRequested) {
res_err = MccSimpleGuidingModelErrorCode::ERROR_GUIDING_STOPPED;
// interpetate stoping as 'no error' exit
return MccSimpleGuidingModelErrorCode::ERROR_OK;
}
// compare t_data with computed coordinates ...

View File

@ -28,10 +28,7 @@ public:
virtual ~MccMountEventBase() = default;
mount_t& mount() const
{
return _mount;
}
mount_t& mount() const { return _mount; }
protected:
MccMountEventBase(mount_t& mount) : _mount(mount) {}
@ -78,10 +75,7 @@ struct MccMountEventError : public MccMountEventBase<MountT> {
using event_data_t = std::error_code;
event_data_t eventData() const
{
return _error;
}
event_data_t eventData() const { return _error; }
MccMountEventError(MountT& mount, const event_data_t& error) : base_t(mount), _error(error) {}
@ -98,12 +92,9 @@ struct MccMountEventSlew : public MccMountEventBase<MountT> {
static constexpr std::string_view ID = "MCC-MOUNT-SLEW-EVENT";
using event_data_t = typename MountT::slew_params_t;
using event_data_t = typename MountT::slew_model_t::slew_point_t;
event_data_t eventData() const
{
return _eventData;
}
event_data_t eventData() const { return _eventData; }
MccMountEventSlew(MountT& mount, const event_data_t& ev_data) : base_t(mount), _eventData(ev_data) {}
@ -120,9 +111,14 @@ struct MccMountEventGuiding : public MccMountEventBase<MountT> {
static constexpr std::string_view ID = "MCC-MOUNT-GUIDING-EVENT";
// CTAD does not work for clang++ (at least till v. 20 and -std=c++23)!
// so, one must explicitly define constructor here
MccMountEventGuiding(MountT& mount) : base_t(mount) {}
using event_data_t = typename MountT::guiding_model_t::guiding_point_t;
event_data_t eventData() const { return _eventData; }
MccMountEventGuiding(MountT& mount, const event_data_t& ev_data) : base_t(mount), _eventData(ev_data) {}
protected:
event_data_t _eventData;
};
@ -139,10 +135,7 @@ struct MccMountEventStop : public MccMountEventBase<MountT> {
EVENT_STOP_BUTTON // hardware button
};
event_data_t eventData() const
{
return _reason;
}
event_data_t eventData() const { return _reason; }
std::string_view reason() const
{
@ -286,7 +279,10 @@ struct MccMountStateStop : MccMountStateBase<MountT> {
auto mount = event.mount();
mount.stopMount();
// should one check current state (slewing, guiding)?
mount.slewModel.stop();
mount.guidingModel.stop();
mount.hardware.stop();
if constexpr (std::same_as<EvT, MccMountEventStop<MountT>>) {
mount.logInfo(std::format("Stop reason: {}", event.reason()));
@ -446,7 +442,8 @@ struct MccMountStateShutdown : MccMountStateBase<MountT> {
// slew state
// WARNING: It must be a friend to 'MountT' class if it inherits it base class mount_controls_t
// as protected or private!!!
template <traits::mcc_fsm_log_mount_c MountT>
struct MccMountStateSlew : MccMountStateBase<MountT> {
static constexpr std::string_view ID = "MCC-MOUNT-SLEW-STATE";
@ -472,7 +469,18 @@ struct MccMountStateSlew : MccMountStateBase<MountT> {
{
this->enterLog(event);
event.mount().slewMount(event.eventData());
auto slew_err = event.mount().slewModel.slew(event.eventData());
if (slew_err) {
if constexpr (std::same_as<decltype(slew_err), std::error_code>) {
event.mount().dispatchEvent(MccMountEventError<MountT>{event.mount(), slew_err});
} else {
// ...
}
return;
}
// switch to IDLE state
event.mount().template dispatchEvent<MccMountEventIDLE<MountT>>({event.mount()});
}
};
@ -505,7 +513,17 @@ struct MccMountStateGuiding : MccMountStateBase<MountT> {
{
this->enterLog(event);
event.mount().startGuiding();
auto err = event.mount().guidingModel.guiding(event.eventData());
if (err) {
if constexpr (std::same_as<decltype(err), std::error_code>) {
event.mount().dispatchEvent(MccMountEventError<MountT>{event.mount(), err});
} else {
// ...
}
}
// switch to IDLE state
event.mount().template dispatchEvent<MccMountEventIDLE<MountT>>({event.mount()});
}
};

View File

@ -5,7 +5,6 @@
/* MOUNT TELEMETRY OBJECT POSSIBLE GENERIC IMPLEMENTATION */
#include <list>
#include <mutex>
#include "mcc_mount_telemetry_astrom.h"

View File

@ -25,6 +25,55 @@ static_assert(traits::mcc_celestial_point_c<MccCelestialPoint>, "MccCelestialPoi
/* COMMON SLEW-AND-GUIDING POINT CLASS DEFINITION */
struct MccSlewAndGuidingPoint : MccCelestialPoint {
// ******* default constants *******
static constexpr size_t defaultWithinToleranceCycleNumber = 10;
static constexpr size_t defaultMaxAdjustingCycleNumber = 100;
// common parameters
// timeout to wait telemetry update (in seconds, as floating-point)
std::chrono::duration<double> telemetryUpdateTimeout{1.0};
// ******* slewing-related parameters *******
// target-mount coordinate difference to start adjusting of slewing (in radians)
coord_t adjustCoordDiff{(double)MccAngle{10.0_degs}};
// coordinates difference to stop slewing (in radians)
coord_t slewToleranceRadius{(double)MccAngle{5.0_arcsecs}};
// slew process timeout
std::chrono::seconds slewTimeout{3600};
std::chrono::duration<double> telemetryPollingInterval{0.1};
// if true - stop mount after the slewing
bool stopAfterSlew{false};
coord_t slewXRate{0.0}; // maximal slewing rate (0 means move with maximal allowed rate)
coord_t slewYRate{0.0}; // maximal slewing rate (0 means move with maximal allowed rate)
coord_t adjustXRate{(double)MccAngle{5.0_arcmins}}; // maximal adjusting rate (a rate at the final slewing stage)
coord_t adjustYRate{(double)MccAngle{5.0_arcmins}}; // maximal adjusting rate (a rate at the final slewing stage)
// number of consecutive measurements within slewToleranceRadius radius to stop adjusting of slewing
size_t withinToleranceCycleNumber{defaultWithinToleranceCycleNumber};
// maximal allowed number of adjusting cycles
size_t maxAdjustingCycleNumber{defaultMaxAdjustingCycleNumber};
// ******* guiding-related parameters *******
coord_t correctionRange[2]{(double)MccAngle(0.3_arcsecs), (double)MccAngle(5.0_arcsecs)};
};
/* CHECK FOR CURRENT MOUNT POSITION IN PROHIBITED ZONES */
template <traits::mcc_mount_telemetry_data_c TelemetryDataT, traits::mcc_prohibited_zone_c<TelemetryDataT>... ZTs>

View File

@ -121,35 +121,7 @@ public:
static constexpr size_t defaultAdjustSuccessCycles = 5;
struct slew_point_t : MccCelestialPoint {
// target-mount coordinate difference to start adjusting of slewing (in radians)
coord_t adjustCoordDiff{(double)MccAngle{10.0_degs}};
// coordinates difference to stop slewing (in radians)
coord_t slewToleranceRadius{(double)MccAngle{5.0_arcsecs}};
// slew process timeout
std::chrono::seconds slewTimeout{3600};
std::chrono::duration<double> telemetryPollingInterval{0.1};
// if true - stop mount after the slewing
bool stopAfterSlew{false};
coord_t slewXRate{0.0}; // maximal slewing rate (0 means move with maximal allowed rate)
coord_t slewYRate{0.0}; // maximal slewing rate (0 means move with maximal allowed rate)
coord_t adjustXRate{
(double)MccAngle{5.0_arcmins}}; // maximal adjusting rate (a rate at the final slewing stage)
coord_t adjustYRate{
(double)MccAngle{5.0_arcmins}}; // maximal adjusting rate (a rate at the final slewing stage)
// number of consecutive measurements within slewToleranceRadius radius to stop adjusting of slewing
size_t withinToleranceCycleNumber{10};
// maximal allowed number of adjusting cycles
size_t maxAdjustingCycleNumber{100};
};
using slew_point_t = MccSlewAndGuidingPoint;
template <traits::mcc_mount_controls_c MOUNT_CONTROLS_T, typename... LoggerCtorArgTs>
@ -233,8 +205,8 @@ protected:
coord_t ra_icrs, dec_icrs;
if (slew_point.adjustSuccessCycles == 0) {
slew_point.adjustSuccessCycles = 5;
if (slew_point.withinToleranceCycleNumber == 0) {
slew_point.withinToleranceCycleNumber = MccSlewAndGuidingPoint::defaultWithinToleranceCycleNumber;
}
// first, compute encoder coordinates
@ -392,16 +364,11 @@ protected:
auto start_poll_tm = std::chrono::steady_clock::now();
// auto timeout_point = std::chrono::steady_clock::now() + slew_point.slewTimeout;
auto wait_timeout = slew_point.slewTimeout / 5;
if (wait_timeout < std::chrono::seconds(1)) {
wait_timeout = std::chrono::seconds(1);
}
// NOTE: TARGET COORDINATES WILL BE UPDATED FOR CURRENT TIME-POINT IN TELEMETRY-CLASS!!!
while (true) {
t_err = telemetry.waitForUpdatedData(t_data, wait_timeout);
t_err = telemetry.waitForUpdatedData(t_data, slew_point.telemetryUpdateTimeout);
if (t_err) {
std::string err_str = "An error occured while waiting for updated telemetry";