#pragma once /* MOUNT CONTROL COMPONENTS LIBRARY */ /* COMMON DEFINITIONS FOR SIMPLE SLEWING, TRACKING AND GUIDING MODEL IMPLEMENTATIONS */ #include #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}; // telemetry request interval std::chrono::milliseconds slewingTelemetryInterval{100}; // 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 ******* // telemetry request interval std::chrono::milliseconds trackingTelemetryInterval{100}; 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 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 res; // first, check if the mount stops before time_in_secs // // the time to stop mount: (V_ini - a*t) = 0 => t = V_ini/a // // the traveled path: s = V_ini*t - a*t*t/2, V_ini - initial speed, a - braking accel, t - the time // // time to stop mount with given current speed and braking acceleration double tx_stop = std::abs(tdata.speedX) / braking_accelX; double ty_stop = std::abs(tdata.speedY) / braking_accelY; double tx = time_in_secs; double ty = time_in_secs; if (std::isfinite(tx_stop) && (time_in_secs > tx_stop)) { tx = tx_stop; } if (std::isfinite(ty_stop) && (time_in_secs > ty_stop)) { ty = ty_stop; } // 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 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; std::vector 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 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; 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::quiet_NaN(); closest_coords->Y = std::numeric_limits::quiet_NaN(); closest_coords->RA_APP = std::numeric_limits::quiet_NaN(); closest_coords->DEC_APP = std::numeric_limits::quiet_NaN(); closest_coords->HA = std::numeric_limits::quiet_NaN(); closest_coords->AZ = std::numeric_limits::quiet_NaN(); closest_coords->ZD = std::numeric_limits::quiet_NaN(); closest_coords->ALT = std::numeric_limits::quiet_NaN(); std::vector pz_coords(pz_cont->sizePZones(), c); double dha, dha_min = std::numeric_limits::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