fix mount initialization (add EEPROM reading, assign correponded mount config items) rewrite computing distance to pzones in slewing mode (add braking aceleration) add more informative errors description for serialization (network protocol)
197 lines
7.0 KiB
C++
197 lines
7.0 KiB
C++
#pragma once
|
|
|
|
/* MOUNT CONTROL COMPONENTS LIBRARY */
|
|
|
|
|
|
/* COMMON DEFINITIONS FOR SIMPLE SLEWING, TRACKING AND GUIDING MODEL IMPLEMENTATIONS */
|
|
|
|
|
|
#include <chrono>
|
|
|
|
#include "mcc_angle.h"
|
|
#include "mcc_generics.h"
|
|
|
|
namespace mcc
|
|
{
|
|
|
|
struct MccSimpleMovingModelParams {
|
|
// ******* common for all modes *******
|
|
|
|
// mean celestial rate
|
|
static constexpr double sideralRate = 15.0410686_arcsecs; // in radians per second
|
|
|
|
// timeout to telemetry updating
|
|
std::chrono::milliseconds telemetryTimeout{3000};
|
|
|
|
// minimal time to prohibited zone (at current speed in slewing mode). if it is lesser then exit with error
|
|
std::chrono::seconds minTimeToPZone{10};
|
|
|
|
// time interval to update prohibited zones related quantities (e.g. intersection points)
|
|
std::chrono::milliseconds updatingPZoneInterval{5000};
|
|
|
|
|
|
// ******* slewing mode *******
|
|
|
|
bool slewAndStop{false}; // slew to target and stop mount
|
|
|
|
// coordinates difference to stop slewing (in radians)
|
|
double slewToleranceRadius{5.0_arcsecs};
|
|
|
|
// target-mount coordinate difference to start adjusting of slewing (in radians)
|
|
double adjustCoordDiff{slewToleranceRadius * 10.0};
|
|
|
|
// slew process timeout
|
|
std::chrono::seconds slewTimeout{3600};
|
|
|
|
double slewRateX{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
|
|
|
|
double adjustRateX{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)
|
|
|
|
// braking acceleration after execution of mount stopping command (in rads/s^2)
|
|
// it must be given as non-negative value!!!
|
|
double brakingAccelX{0.0};
|
|
double brakingAccelY{0.0};
|
|
|
|
|
|
// ******* tracking mode *******
|
|
|
|
double trackSpeedX{};
|
|
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)
|
|
std::chrono::milliseconds timeShiftToTargetPoint{10000};
|
|
// maximal target-to-mount difference for tracking process (in arcsecs)
|
|
// it it is greater then the current mount coordinates are used as target one
|
|
double trackingMaxCoordDiff{20.0};
|
|
|
|
// ******* guiding mode *******
|
|
|
|
double guidingCorrectionRange[2]{0.3_arcsecs, 3.0_arcsecs};
|
|
std::chrono::milliseconds guidingMinInterval{500}; // minimum time between two successive corrections
|
|
bool dualAxisGuiding{true}; // mount must be of an equatorial type: false means guiding along only HA-axis
|
|
};
|
|
|
|
|
|
// calculate the distances along the X and Y axes that the mount will travel at the current speed in a given time,
|
|
// taking into account the braking acceleration
|
|
//
|
|
// WARNING:
|
|
// It is assumed that the given braking accelerations are non-negative,
|
|
// while speeds may have a sign according to motion direction.
|
|
// The latter means that returned distances can be negative!
|
|
std::pair<double, double> mcc_compute_distance(mcc_telemetry_data_c auto const& tdata,
|
|
double time_in_secs,
|
|
mcc_angle_c auto const& braking_accelX,
|
|
mcc_angle_c auto const& braking_accelY)
|
|
{
|
|
std::pair<double, double> res;
|
|
|
|
// first, check if the mount will stop after given time_in_secs to prevent traveled path to be
|
|
// negative
|
|
//
|
|
// the traveled path: s = V_ini*t - a*t*t/2, V_ini - initial speed, a - braking accel, t - the time
|
|
// then, for s>=0, t <= 2*V_ini/a
|
|
//
|
|
|
|
double term_x = 2.0 * std::abs(tdata.speedX) / braking_accelX;
|
|
double term_y = 2.0 * std::abs(tdata.speedY) / braking_accelY;
|
|
double tx = time_in_secs;
|
|
double ty = time_in_secs;
|
|
|
|
if (std::isfinite(term_x) && (time_in_secs > term_x)) {
|
|
tx = term_x;
|
|
}
|
|
if (std::isfinite(term_y) && (time_in_secs > term_y)) {
|
|
ty = term_y;
|
|
}
|
|
|
|
// here, one must take into account the sign of the speed!!!
|
|
res.first = tdata.speedX * tx - std::copysign(braking_accelX, tdata.speedX) * tx * tx / 2.0;
|
|
res.second = tdata.speedY * ty - std::copysign(braking_accelY, tdata.speedY) * ty * ty / 2.0;
|
|
|
|
return res;
|
|
}
|
|
|
|
template <mcc_pzone_container_c PZoneContT>
|
|
bool mcc_is_near_pzones(PZoneContT* pz_cont,
|
|
mcc_telemetry_data_c auto const& tdata,
|
|
traits::mcc_time_duration_c auto const& min_timeto,
|
|
typename PZoneContT::error_t& err)
|
|
{
|
|
using res_t = std::decay_t<decltype(min_timeto)>;
|
|
|
|
std::vector<res_t> pz_timeto; // in seconds
|
|
|
|
err = pz_cont->timeToPZone(tdata, &pz_timeto);
|
|
if (err) {
|
|
return false;
|
|
}
|
|
|
|
for (auto const& t : pz_timeto) {
|
|
if (t <= min_timeto) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
template <mcc_pzone_container_c PZoneContT>
|
|
typename PZoneContT::error_t mcc_find_closest_pzone(PZoneContT* pz_cont,
|
|
mcc_telemetry_data_c auto const& tdata,
|
|
mcc_eqt_hrz_coord_c auto* closest_coords)
|
|
{
|
|
using res_t = std::decay_t<decltype(*closest_coords)>;
|
|
|
|
if (closest_coords == nullptr) {
|
|
return {};
|
|
}
|
|
|
|
res_t c;
|
|
|
|
mcc_tp2tp(tdata.time_point, c.time_point);
|
|
|
|
mcc_tp2tp(tdata.time_point, closest_coords->time_point);
|
|
closest_coords->X = std::numeric_limits<double>::quiet_NaN();
|
|
closest_coords->Y = std::numeric_limits<double>::quiet_NaN();
|
|
closest_coords->RA_APP = std::numeric_limits<double>::quiet_NaN();
|
|
closest_coords->DEC_APP = std::numeric_limits<double>::quiet_NaN();
|
|
closest_coords->HA = std::numeric_limits<double>::quiet_NaN();
|
|
closest_coords->AZ = std::numeric_limits<double>::quiet_NaN();
|
|
closest_coords->ZD = std::numeric_limits<double>::quiet_NaN();
|
|
closest_coords->ALT = std::numeric_limits<double>::quiet_NaN();
|
|
|
|
std::vector<res_t> pz_coords(pz_cont->sizePZones(), c);
|
|
|
|
double dha, dha_min = std::numeric_limits<double>::max();
|
|
|
|
auto err = pz_cont->intersectPZone(tdata, &pz_coords);
|
|
if (!err) {
|
|
for (auto const& rpt : pz_coords) {
|
|
if (std::isfinite(rpt.X) && std::isfinite(rpt.Y)) {
|
|
dha = rpt.HA - tdata.HA;
|
|
if (dha < 0.0) {
|
|
dha += std::numbers::pi * 2.0;
|
|
}
|
|
|
|
if (dha < dha_min) {
|
|
dha_min = dha;
|
|
mcc_copy_eqt_hrz_coord(rpt, closest_coords);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
|
|
} // namespace mcc
|