This commit is contained in:
Timur A. Fatkhullin 2025-12-11 17:40:23 +03:00
parent 3c0c719e37
commit 255c34dbb2
3 changed files with 169 additions and 40 deletions

View File

@ -20,7 +20,11 @@ enum class MccGenericMountErrorCode : int {
ERROR_HW_GETSTATE, ERROR_HW_GETSTATE,
ERROR_SET_TARGET, ERROR_SET_TARGET,
ERROR_MOUNT_SLEW, ERROR_MOUNT_SLEW,
ERROR_MOUNT_TRACK ERROR_MOUNT_TRACK,
ERROR_GET_TELEMETRY,
ERROR_UNSUPPORTED_TARGET_COORDPAIR,
ERROR_PZONE_COMP,
ERROR_TARGET_IN_ZONE
}; };
enum class MccGenericFsmMountErrorCode : int { ERROR_OK, ERROR_INVALID_OPERATION, ERROR_UNKNOWN_EVENT }; enum class MccGenericFsmMountErrorCode : int { ERROR_OK, ERROR_INVALID_OPERATION, ERROR_UNKNOWN_EVENT };
@ -70,6 +74,20 @@ struct MccGenericMountCategory : public std::error_category {
return "an error occured while stopping mount"; return "an error occured while stopping mount";
case MccGenericMountErrorCode::ERROR_HW_GETSTATE: case MccGenericMountErrorCode::ERROR_HW_GETSTATE:
return "cannot get state of hardware"; return "cannot get state of hardware";
case MccGenericMountErrorCode::ERROR_SET_TARGET:
return "cannot set target coordinates";
case MccGenericMountErrorCode::ERROR_MOUNT_SLEW:
return "slewing error";
case MccGenericMountErrorCode::ERROR_MOUNT_TRACK:
return "tracking error";
case MccGenericMountErrorCode::ERROR_GET_TELEMETRY:
return "cannot get telemetry data";
case MccGenericMountErrorCode::ERROR_UNSUPPORTED_TARGET_COORDPAIR:
return "unsupported coordinate pair of target";
case MccGenericMountErrorCode::ERROR_PZONE_COMP:
return "an error occured while computing prohibited zone";
case MccGenericMountErrorCode::ERROR_TARGET_IN_ZONE:
return "target coordinates are in prohibitted zone";
default: default:
return "UNKNOWN"; return "UNKNOWN";
} }
@ -186,7 +204,8 @@ public:
PZoneContT(std::make_from_tuple<PZoneContT>(std::move(pzcont_ctor_args))), PZoneContT(std::make_from_tuple<PZoneContT>(std::move(pzcont_ctor_args))),
SlewModelT(std::make_from_tuple<SlewModelT>(std::move(smodel_ctor_args))), SlewModelT(std::make_from_tuple<SlewModelT>(std::move(smodel_ctor_args))),
TrackModelT(std::make_from_tuple<TrackModelT>(std::move(tmodel_ctor_args))), TrackModelT(std::make_from_tuple<TrackModelT>(std::move(tmodel_ctor_args))),
_mountStatus(new std::atomic<mount_status_t>{}) _mountStatus(new std::atomic<mount_status_t>{}),
_lastMountError(new std::atomic<error_t>{MccGenericMountErrorCode::ERROR_OK})
{ {
*_mountStatus = mount_status_t::IDLE; *_mountStatus = mount_status_t::IDLE;
} }
@ -200,12 +219,18 @@ public:
virtual ~MccGenericMount() virtual ~MccGenericMount()
{ {
stopMount(); stopMount();
if (_slewingFuture.valid()) {
_slewingFuture.wait_for(std::chrono::seconds(3));
}
}; };
error_t stopMount() error_t stopMount()
{ {
logInfo("Stop any movements ..."); logInfo("Stop any movements ...");
*_lastMountError = MccGenericMountErrorCode::ERROR_OK;
this->stopTracking(); this->stopTracking();
this->stopSlewing(); this->stopSlewing();
@ -213,34 +238,36 @@ public:
if (hw_err) { if (hw_err) {
*_mountStatus = mount_status_t::ERROR; *_mountStatus = mount_status_t::ERROR;
return mcc_deduce_error_code(hw_err, MccGenericMountErrorCode::ERROR_HW_STOP); *_lastMountError = mcc_deduce_error_code(hw_err, MccGenericMountErrorCode::ERROR_HW_STOP);
} else {
logInfo("Stop command was sent");
*_mountStatus = mount_status_t::STOPPED;
} }
logInfo("Stop command was sent"); return *_lastMountError;
*_mountStatus = mount_status_t::STOPPED;
return MccGenericMountErrorCode::ERROR_OK;
} }
error_t initMount() error_t initMount()
{ {
logInfo("Start generic mount initialization ..."); logInfo("Start generic mount initialization ...");
*_lastMountError = MccGenericMountErrorCode::ERROR_OK;
*_mountStatus = mount_status_t::INITIALIZATION; *_mountStatus = mount_status_t::INITIALIZATION;
auto hw_err = this->hardwareInit(); auto hw_err = this->hardwareInit();
if (hw_err) { if (hw_err) {
*_mountStatus = mount_status_t::ERROR; *_mountStatus = mount_status_t::ERROR;
return mcc_deduce_error_code(hw_err, MccGenericMountErrorCode::ERROR_HW_STOP); *_lastMountError = mcc_deduce_error_code(hw_err, MccGenericMountErrorCode::ERROR_HW_STOP);
} else {
logInfo("Generic mount initialization was performed");
*_mountStatus = mount_status_t::IDLE;
} }
logInfo("Generic mount initialization was performed"); return *_lastMountError;
*_mountStatus = mount_status_t::IDLE;
return MccGenericMountErrorCode::ERROR_OK;
} }
// re-implements TelemetryT::setPointingTarget to hold target coordinates // re-implements TelemetryT::setPointingTarget to hold target coordinates
@ -268,6 +295,47 @@ public:
// re-implements SlewModelT::slewToTarget to fetch input target coordinates from intermediate buffer // re-implements SlewModelT::slewToTarget to fetch input target coordinates from intermediate buffer
error_t slewToTarget(bool slew_and_stop = false) error_t slewToTarget(bool slew_and_stop = false)
{ {
*_lastMountError = MccGenericMountErrorCode::ERROR_OK;
// save current target
MccTelemetryData tdata;
auto sl_params = this->getSlewingParams();
auto t_err = this->telemetryData(&tdata);
if (t_err) {
return *_lastMountError = mcc_deduce_error_code(t_err, MccGenericMountErrorCode::ERROR_GET_TELEMETRY);
}
MccCelestialPoint curr_target{.pair_kind = tdata.target.pair_kind, .time_point = tdata.target.time_point};
if (curr_target.pair_kind == MccCoordPairKind::COORDS_KIND_RADEC_ICRS) {
curr_target.X = tdata.target.RA_ICRS;
curr_target.Y = tdata.target.DEC_ICRS;
} else if (curr_target.pair_kind == MccCoordPairKind::COORDS_KIND_RADEC_APP) {
curr_target.X = tdata.target.RA_APP;
curr_target.Y = tdata.target.DEC_APP;
} else if (curr_target.pair_kind == MccCoordPairKind::COORDS_KIND_HADEC_APP) {
curr_target.X = tdata.target.HA;
curr_target.Y = tdata.target.DEC_APP;
} else if (curr_target.pair_kind == MccCoordPairKind::COORDS_KIND_AZZD) {
curr_target.X = tdata.target.AZ;
curr_target.Y = tdata.target.ZD;
} else if (curr_target.pair_kind == MccCoordPairKind::COORDS_KIND_AZALT) {
curr_target.X = tdata.target.AZ;
curr_target.Y = tdata.target.ALT;
} else if (curr_target.pair_kind == MccCoordPairKind::COORDS_KIND_XY) {
curr_target.X = tdata.target.X;
curr_target.Y = tdata.target.Y;
} else { // it should not be!
logError(
std::format("Unsupported coordinate pair kind ({}) was read from telemetry data! Is mount "
"initialized?! Cannot start slewing!",
(int)curr_target.pair_kind));
return *_lastMountError = MccGenericMountErrorCode::ERROR_UNSUPPORTED_TARGET_COORDPAIR;
}
// set new target coordinates and check it
_enteredTargetCoordiniates.time_point = std::chrono::system_clock::now(); _enteredTargetCoordiniates.time_point = std::chrono::system_clock::now();
auto err = TelemetryT::setPointingTarget(_enteredTargetCoordiniates); auto err = TelemetryT::setPointingTarget(_enteredTargetCoordiniates);
if (err) { if (err) {
@ -276,23 +344,67 @@ public:
return mcc_deduce_error_code(err, MccGenericMountErrorCode::ERROR_SET_TARGET); return mcc_deduce_error_code(err, MccGenericMountErrorCode::ERROR_SET_TARGET);
} }
*_mountStatus = mount_status_t::SLEWING; t_err = this->waitForTelemetryData(&tdata, sl_params.telemetryTimeout);
if (t_err) {
error_t s_err = return mcc_deduce_error_code(t_err, MccGenericMountErrorCode::ERROR_GET_TELEMETRY);
mcc_deduce_error_code(SlewModelT::slewToTarget(slew_and_stop), MccGenericMountErrorCode::ERROR_MOUNT_SLEW);
if (s_err) {
*_mountStatus = mount_status_t::ERROR;
return s_err;
} }
if (slew_and_stop) { bool in_zone;
*_mountStatus = mount_status_t::IDLE; std::vector<bool> in_zone_vec;
} else { auto pz_err = this->inPZone(tdata.target, &in_zone, &in_zone_vec);
s_err = trackTarget(); if (pz_err) {
return *_lastMountError = mcc_deduce_error_code(pz_err, MccGenericMountErrorCode::ERROR_PZONE_COMP);
} }
return s_err; if (in_zone) {
size_t i = 0;
for (; i < in_zone_vec.size(); ++i) {
if (in_zone_vec[i]) {
break;
}
}
logError("target point is in prohibited zone (zone index: {})! Entered target coordinates:", i);
logError(std::format(
" RA-APP, DEC-APP, HA, LST: {}, {}, {}, {}", mcc::MccAngle{tdata.target.RA_APP}.sexagesimal(true),
mcc::MccAngle{tdata.target.DEC_APP}.sexagesimal(), mcc::MccAngle{tdata.target.HA}.sexagesimal(true),
mcc::MccAngle{tdata.LST}.sexagesimal(true)));
logError(std::format(" AZ, ZD, ALT: {}, {}, {}", mcc::MccAngle{tdata.target.AZ}.sexagesimal(),
mcc::MccAngle{tdata.target.ZD}.sexagesimal(),
mcc::MccAngle{tdata.target.ALT}.sexagesimal()));
logError(std::format(" hardware X, Y: {}, {}", mcc::MccAngle{tdata.target.X}.sexagesimal(),
mcc::MccAngle{tdata.target.Y}.sexagesimal()));
return *_lastMountError = mcc_deduce_error_code(pz_err, MccGenericMountErrorCode::ERROR_TARGET_IN_ZONE);
}
// start slewing (asunchronous operation)
_slewingFuture = std::async(std::launch::async,
[slew_and_stop, this]() {
*_mountStatus = mount_status_t::SLEWING;
auto err = SlewModelT::slewToTarget(slew_and_stop);
if (err) {
*_lastMountError =
mcc_deduce_error_code(err, MccGenericMountErrorCode::ERROR_MOUNT_SLEW);
*_mountStatus = mount_status_t::ERROR;
} else {
if (slew_and_stop) {
*_mountStatus = mount_status_t::IDLE;
} else {
*_lastMountError = trackTarget();
}
}
}
);
return MccGenericMountErrorCode::ERROR_OK;
} }
error_t trackTarget() error_t trackTarget()
@ -321,8 +433,7 @@ public:
error_t stopTracking() error_t stopTracking()
{ {
// *_mountStatus = mount_status_t::IDLE; *_mountStatus = mount_status_t::IDLE;
_mountStatus->store(mount_status_t::IDLE);
TrackModelT::stopTracking(); TrackModelT::stopTracking();
@ -335,10 +446,21 @@ public:
return *_mountStatus; return *_mountStatus;
} }
// returns last mount-action error code
error_t mountLastError() const
{
return *_lastMountError;
}
protected: protected:
MccCelestialPoint _enteredTargetCoordiniates{}; MccCelestialPoint _enteredTargetCoordiniates{};
std::unique_ptr<std::atomic<MccGenericMount::mount_status_t>> _mountStatus; std::unique_ptr<std::atomic<MccGenericMount::mount_status_t>> _mountStatus;
std::future<void> _slewingFuture{};
std::unique_ptr<std::atomic<error_t>> _lastMountError;
}; };

View File

@ -623,6 +623,9 @@ public:
*_stopSlewing = true; *_stopSlewing = true;
logger.logInfo("Slewing finished"); logger.logInfo("Slewing finished");
error_t err = *_lastError;
logger.logInfo(std::format(" exit code: {} {} {}", err.value(), err.category().name(), err.message()));
// get final position // get final position
@ -700,12 +703,12 @@ public:
return *_lastError; return *_lastError;
} }
// asynchronous slewing process // // asynchronous slewing process
_slewFuncFuture = std::async(std::launch::async, _slewingFunc, slew_and_stop); // _slewFuncFuture = std::async(std::launch::async, _slewingFunc, slew_and_stop);
return MccSimpleSlewingModelErrorCode::ERROR_OK; // return MccSimpleSlewingModelErrorCode::ERROR_OK;
// return _slewingFunc(slew_and_stop); return _slewingFunc(slew_and_stop);
} }

View File

@ -212,19 +212,23 @@ public:
auto target_point = [&, this](MccCelestialPoint* point) -> std::error_code { auto target_point = [&, this](MccCelestialPoint* point) -> std::error_code {
auto dt = std::chrono::duration<double>{tdata.HA} + double dha =
_currentParams.timeShiftToTargetPoint * mcc_sideral_to_UT1_ratio; // hour seconds std::chrono::duration<double>(_currentParams.timeShiftToTargetPoint * mcc_sideral_to_UT1_ratio)
.count(); // sideral hour seconds
dha *= std::numbers::pi / 43200.0; // radians
auto target_ha = tdata.target.HA + dha;
// 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>( auto tp_dt = std::chrono::duration_cast<typename decltype(tdata.time_point)::duration>(
_currentParams.timeShiftToTargetPoint); _currentParams.timeShiftToTargetPoint);
// point in +time_dist future // point in +time_dist future
MccCelestialPoint pt{.pair_kind = MccCoordPairKind::COORDS_KIND_HADEC_APP, MccCelestialPoint pt{.pair_kind = MccCoordPairKind::COORDS_KIND_HADEC_APP,
// .X = MccAngle(dt.count() * std::numbers::pi / 3600.0 .X = MccAngle(target_ha).normalize<MccAngle::NORM_KIND_180_180>(),
// / 15.0).normalize<MccAngle::NORM_KIND_0_360>(), .Y = tdata.target.DEC_APP};
.X = MccAngle(dt.count() * std::numbers::pi / 3600.0 / 15.0)
.normalize<MccAngle::NORM_KIND_180_180>(),
.Y = tdata.DEC_APP};
mcc_tp2tp(tdata.time_point + tp_dt, pt.time_point); mcc_tp2tp(tdata.time_point + tp_dt, pt.time_point);
point->time_point = pt.time_point; point->time_point = pt.time_point;