From 3d769d79eb5aa01b17b137408ac6a4d1182bf9a2 Mon Sep 17 00:00:00 2001 From: "Timur A. Fatkhullin" Date: Wed, 1 Oct 2025 06:26:50 +0300 Subject: [PATCH] ... --- asibfm700/CMakeLists.txt | 12 +- asibfm700/asibfm700_common.h | 2 +- asibfm700/asibfm700_configfile.h | 488 +++++++++++++++++++++++++- asibfm700/asibfm700_mount.cpp | 2 + asibfm700/asibfm700_mount.h | 2 +- {mcc => asibfm700}/tests/cfg_test.cpp | 15 +- mcc/CMakeLists.txt | 6 +- mcc/mcc_moving_model_common.h | 4 +- 8 files changed, 505 insertions(+), 26 deletions(-) rename {mcc => asibfm700}/tests/cfg_test.cpp (77%) diff --git a/asibfm700/CMakeLists.txt b/asibfm700/CMakeLists.txt index 1890fe6..18e7837 100644 --- a/asibfm700/CMakeLists.txt +++ b/asibfm700/CMakeLists.txt @@ -40,4 +40,14 @@ set(ASIBFM700_LIB asibfm700mount) add_library(${ASIBFM700_LIB} STATIC ${ASIBFM700_LIB_SRC} asibfm700_mount.h asibfm700_mount.cpp asibfm700_configfile.h) -target_link_libraries(${ASIBFM700_LIB} PRIVATE mcc) +target_link_libraries(${ASIBFM700_LIB} PRIVATE mcc spdlog) + +option(WITH_TESTS "Build tests" ON) + +if (WITH_TESTS) + set(CFG_TEST_APP cfg_test) + add_executable(${CFG_TEST_APP} tests/cfg_test.cpp) + target_link_libraries(${CFG_TEST_APP} PRIVATE mcc) + + enable_testing() + endif() diff --git a/asibfm700/asibfm700_common.h b/asibfm700/asibfm700_common.h index e05657f..efd3283 100644 --- a/asibfm700/asibfm700_common.h +++ b/asibfm700/asibfm700_common.h @@ -26,7 +26,7 @@ typedef mcc::utils::MccSpdlogLogger Asibfm700Logger; /* MOUNT CONFIGURATION CLASS */ -struct Asibfm700MountConfig { +struct Asibfm700MountConfig1 { std::chrono::milliseconds hardwarePollingPeriod{100}; // main cycle period // CCTE-related configuration diff --git a/asibfm700/asibfm700_configfile.h b/asibfm700/asibfm700_configfile.h index 0559dbe..9fec087 100644 --- a/asibfm700/asibfm700_configfile.h +++ b/asibfm700/asibfm700_configfile.h @@ -8,9 +8,13 @@ #include #include +#include #include #include +#include "asibfm700_common.h" +#include "asibfm700_servocontroller.h" + namespace asibfm700 { @@ -306,11 +310,15 @@ static auto Asibfm700MountConfigDefaults = std::make_tuple( simple_config_record_t{"pcmBsplineDegree", std::vector{3, 3}}, // PCM B-spline knots along X-axis (HA-angle or azimuth). By default from 0 to 2*PI radians + // NOTE: The first and last values are interpretated as border knots!!! + // Thus the array length must be equal to or greater than 2! simple_config_record_t{"pcmBsplineXknots", std::vector{0.0, 0.6981317, 1.3962634, 2.0943951, 2.7925268, 3.4906585, 4.1887902, 4.88692191, 5.58505361, 6.28318531}}, // PCM B-spline knots along Y-axis (declination or zenithal distance). By default from -PI/6 to PI/2 radians + // NOTE: The first and last values are interpretated as border knots!!! + // Thus the array length must be equal to or greater than 2! simple_config_record_t{"pcmBsplineYknots", std::vector{-0.52359878, -0.29088821, -0.05817764, 0.17453293, 0.40724349, 0.63995406, 0.87266463, 1.10537519, 1.33808576, 1.57079633}}, @@ -324,8 +332,8 @@ static auto Asibfm700MountConfigDefaults = std::make_tuple( /* slewing and tracking parameters */ - // arcseconds per second - simple_config_record_t{"sideralRate", 15.0410686}, + // // arcseconds per second + // simple_config_record_t{"sideralRate", 15.0410686}, // timeout for telemetry updating in milliseconds simple_config_record_t{"telemetryTimeout", std::chrono::milliseconds(3000)}, @@ -375,11 +383,59 @@ static auto Asibfm700MountConfigDefaults = std::make_tuple( /* hardware-related */ + // hardware mode: 1 - model mode, otherwise real mode + simple_config_record_t{"RunModel", 0}, + + // mount serial device paths + simple_config_record_t{"MountDevPath", std::string("/dev/ttyUSB0")}, + + // mount serial device speed + simple_config_record_t{"MountDevSpeed", 19200}, + + // motor encoders serial device path + simple_config_record_t{"EncoderDevPath", std::string("")}, + + // X-axis encoder serial device path + simple_config_record_t{"EncoderXDevPath", std::string("/dev/encoderX0")}, + + // Y-axis encoder serial device path + simple_config_record_t{"EncoderYDevPath", std::string("/dev/encoderY0")}, + + // encoders serial device speed + simple_config_record_t{"EncoderDevSpeed", 153000}, + + // ==1 if encoder works as separate serial device, ==2 if there's new version with two devices + simple_config_record_t{"SepEncoder", 2}, + + + // mount polling interval in millisecs + simple_config_record_t{"MountReqInterval", std::chrono::milliseconds(100)}, + + // encoders polling interval in millisecs + simple_config_record_t{"EncoderReqInterval", std::chrono::milliseconds(50)}, + + // mount axes rate calculation interval in millisecs + simple_config_record_t{"EncoderSpeedInterval", std::chrono::milliseconds(100)}, + + // X-axis coordinate PID P,I,D-params + simple_config_record_t{"XPIDC", std::vector{0.8, 0.1, 0.3}}, + + // X-axis rate PID P,I,D-params + simple_config_record_t{"XPIDV", std::vector{1.0, 0.01, 0.2}}, + + // Y-axis coordinate PID P, I, D-params + simple_config_record_t{"YPIDC", std::vector{0.8, 0.1, 0.3}}, + + // Y-axis rate PID P,I,D-params + simple_config_record_t{"YPIDV", std::vector{0.5, 0.2, 0.5}}, + + // maximal moving rate (degrees per second) along HA-axis (Y-axis of Sidereal servo microcontroller) - simple_config_record_t{"hwMaxRateHA", mcc::MccAngle(5.0_degs)}, + simple_config_record_t{"hwMaxRateHA", mcc::MccAngle(8.0_degs)}, // maximal moving rate (degrees per second) along DEC-axis (X-axis of Sidereal servo microcontroller) - simple_config_record_t{"hwMaxRateDEC", mcc::MccAngle(5.0_degs)} + simple_config_record_t{"hwMaxRateDEC", mcc::MccAngle(10.0_degs)} + ); @@ -392,7 +448,10 @@ class Asibfm700MountConfig : protected ConfigHolder(this->_configDB["hardwarePollingPeriod"]); + + // CCTE + + siteLatitude = std::get(this->_configDB["siteLatitude"]); + siteLongitude = std::get(this->_configDB["siteLongitude"]); + siteElevation = std::get(this->_configDB["siteElevation"]); + refractWavelength = std::get(this->_configDB["refractWavelength"]); + + leapSecondFilename = std::get(this->_configDB["leapSecondFilename"]); + bulletinAFilename = std::get(this->_configDB["bulletinAFilename"]); + + // prohibited zones + + pzMinAltitude = std::get(this->_configDB["pzMinAltitude"]); + pzLimitSwitchHAMin = std::get(this->_configDB["pzLimitSwitchHAMin"]); + pzLimitSwitchHAMax = std::get(this->_configDB["pzLimitSwitchHAMax"]); + + + // hardware config + + servoControllerConfig.hwConfig = {}; + + servoControllerConfig.MountDevPath = std::get(this->_configDB["MountDevPath"]); + servoControllerConfig.EncoderDevPath = std::get(this->_configDB["EncoderDevPath"]); + servoControllerConfig.EncoderXDevPath = std::get(this->_configDB["EncoderXDevPath"]); + servoControllerConfig.EncoderYDevPath = std::get(this->_configDB["EncoderYDevPath"]); + + servoControllerConfig.devConfig.MountDevPath = servoControllerConfig.MountDevPath.data(); + servoControllerConfig.devConfig.EncoderDevPath = servoControllerConfig.EncoderDevPath.data(); + servoControllerConfig.devConfig.EncoderXDevPath = servoControllerConfig.EncoderXDevPath.data(); + servoControllerConfig.devConfig.EncoderYDevPath = servoControllerConfig.EncoderYDevPath.data(); + + servoControllerConfig.devConfig.RunModel = std::get(this->_configDB["RunModel"]); + servoControllerConfig.devConfig.MountDevSpeed = std::get(this->_configDB["MountDevSpeed"]); + servoControllerConfig.devConfig.EncoderDevSpeed = std::get(this->_configDB["EncoderDevSpeed"]); + servoControllerConfig.devConfig.SepEncoder = std::get(this->_configDB["SepEncoder"]); + + std::chrono::duration secs; // seconds as floating-point + + secs = std::get(this->_configDB["MountReqInterval"]); + servoControllerConfig.devConfig.MountReqInterval = secs.count(); + + secs = std::get(this->_configDB["EncoderReqInterval"]); + servoControllerConfig.devConfig.EncoderReqInterval = secs.count(); + + secs = std::get(this->_configDB["EncoderSpeedInterval"]); + servoControllerConfig.devConfig.EncoderSpeedInterval = secs.count(); + + std::vector pid = std::get>(this->_configDB["XPIDC"]); + if (pid.size() > 2) { + servoControllerConfig.devConfig.XPIDC.P = pid[0]; + servoControllerConfig.devConfig.XPIDC.I = pid[1]; + servoControllerConfig.devConfig.XPIDC.D = pid[2]; + } + + pid = std::get>(this->_configDB["XPIDV"]); + if (pid.size() > 2) { + servoControllerConfig.devConfig.XPIDV.P = pid[0]; + servoControllerConfig.devConfig.XPIDV.I = pid[1]; + servoControllerConfig.devConfig.XPIDV.D = pid[2]; + } + + pid = std::get>(this->_configDB["YPIDC"]); + if (pid.size() > 2) { + servoControllerConfig.devConfig.YPIDC.P = pid[0]; + servoControllerConfig.devConfig.YPIDC.I = pid[1]; + servoControllerConfig.devConfig.YPIDC.D = pid[2]; + } + + pid = std::get>(this->_configDB["YPIDV"]); + if (pid.size() > 2) { + servoControllerConfig.devConfig.YPIDV.P = pid[0]; + servoControllerConfig.devConfig.YPIDV.I = pid[1]; + servoControllerConfig.devConfig.YPIDV.D = pid[2]; + } + + + // slew and track parameters + + movingModelParams.telemetryTimeout = + std::get(this->_configDB["telemetryTimeout"]); + + movingModelParams.minTimeToPZone = + std::get(this->_configDB["minTimeToPZone"]); + + movingModelParams.updatingPZoneInterval = + std::get(this->_configDB["updatingPZoneInterval"]); + + movingModelParams.slewToleranceRadius = + std::get(this->_configDB["slewToleranceRadius"]); + + movingModelParams.adjustCoordDiff = + std::get(this->_configDB["adjustCoordDiff"]); + + movingModelParams.adjustCycleInterval = + std::get(this->_configDB["adjustCycleInterval"]); + + movingModelParams.slewTimeout = + std::get(this->_configDB["slewTimeout"]); + + movingModelParams.timeShiftToTargetPoint = + std::get(this->_configDB["timeShiftToTargetPoint"]); + + movingModelParams.trackingCycleInterval = + std::get(this->_configDB["trackingCycleInterval"]); + + + // PCM data + + pcmData.type = std::get(this->_configDB["pcmType"]); + + pcmData.siteLatitude = std::get(this->_configDB["siteLatitude"]); + + pid = std::get>(this->_configDB["pcmGeomCoeffs"]); + if (pid.size() >= 9) { // must be 9 coefficients + pcmData.geomCoefficients = {.zeroPointX = pid[0], + .zeroPointY = pid[1], + .collimationErr = pid[2], + .nonperpendErr = pid[3], + .misalignErr1 = pid[4], + .misalignErr2 = pid[5], + .tubeFlexure = pid[6], + .forkFlexure = pid[7], + .DECaxisFlexure = pid[8]}; + } + + std::vector dd = std::get(this->_configDB["pcmBsplineDegree"]); + if (dd.size() >= 2) { + pcmData.bspline.bsplDegreeX = dd[0] > 0 ? dd[0] : 3; + pcmData.bspline.bsplDegreeY = dd[1] > 0 ? dd[1] : 3; + } + + pid = std::get>(this->_configDB["pcmBsplineXknots"]); + // pid must contains interior and border (single point for each border) knots so minimal length must be 2 + if (pid.size() >= 2) { + // generate full knots array (with border knots) + size_t Nknots = pid.size() + pcmData.bspline.bsplDegreeX * 2 - 2; + pcmData.bspline.knotsX.resize(Nknots); + + for (size_t i = 0; i <= pcmData.bspline.bsplDegreeX; ++i) { // border knots + pcmData.bspline.knotsX[i] = pid[0]; + pcmData.bspline.knotsX[Nknots - i - 1] = pid.back(); + } + for (size_t i = 0; i < (pid.size() - 2); ++i) { // interior knots + pcmData.bspline.knotsX[i + pcmData.bspline.bsplDegreeX] = pid[1 + i]; + } + } + + pid = std::get>(this->_configDB["pcmBsplineYknots"]); + // pid must contains interior and border (single point for each border) knots so minimal length must be 2 + if (pid.size() >= 2) { + // generate full knots array (with border knots) + size_t Nknots = pid.size() + pcmData.bspline.bsplDegreeY * 2 - 2; + pcmData.bspline.knotsY.resize(Nknots); + + for (size_t i = 0; i <= pcmData.bspline.bsplDegreeY; ++i) { // border knots + pcmData.bspline.knotsY[i] = pid[0]; + pcmData.bspline.knotsY[Nknots - i - 1] = pid.back(); + } + for (size_t i = 0; i < (pid.size() - 2); ++i) { // interior knots + pcmData.bspline.knotsY[i + pcmData.bspline.bsplDegreeY] = pid[1 + i]; + } + } + + // minimal allowed number of B-spline coefficients + size_t Ncoeffs = pcmData.type == mcc::MccDefaultPCMType::PCM_TYPE_GEOMETRY + ? 0 + : (pcmData.bspline.knotsX.size() - pcmData.bspline.bsplDegreeX - 1) * + (pcmData.bspline.knotsY.size() - pcmData.bspline.bsplDegreeY - 1); + + pid = std::get>(this->_configDB["pcmBsplineXcoeffs"]); + + if (pid.size() >= Ncoeffs) { + pcmData.bspline.coeffsX.resize(Ncoeffs); + for (size_t i = 0; i < Ncoeffs; ++i) { + pcmData.bspline.coeffsX[i] = pid[i]; + } + } + + pid = std::get>(this->_configDB["pcmBsplineYcoeffs"]); + + if (pid.size() >= Ncoeffs) { + pcmData.bspline.coeffsY.resize(Ncoeffs); + for (size_t i = 0; i < Ncoeffs; ++i) { + pcmData.bspline.coeffsY[i] = pid[i]; + } + } + } + inline static auto deserializer = [](std::string_view str, auto& value) { using value_t = std::decay_t; - bool ok; + bool ok = true; if constexpr (std::is_arithmetic_v || std::ranges::output_range || std::ranges::range) { @@ -446,6 +723,22 @@ protected: if (ok) { value = mcc::MccAngle(vd, mcc::MccDegreeTag{}); } + } else if constexpr (std::same_as) { + std::string vstr; + ok = base_t::defaultDeserializeFunc(str, vstr); + auto s = mcc::utils::trimSpaces(vstr); + + if (ok) { + if (s == mcc::MccDefaultPCMTypeString) { + value = mcc::MccDefaultPCMType::PCM_TYPE_GEOMETRY; + } else if (s == mcc::MccDefaultPCMTypeString) { + value = mcc::MccDefaultPCMType::PCM_TYPE_GEOMETRY; + } else if (s == mcc::MccDefaultPCMTypeString) { + value = mcc::MccDefaultPCMType::PCM_TYPE_BSPLINE; + } else { + return false; + } + } } else { return false; } @@ -454,4 +747,169 @@ protected: }; }; + +static constexpr std::string_view Asibfm700MountConfigString = + R"--( +# +# ASTROSIB FM-700 MOUNT DEFAULT CONFIGURATION +# +# (created 2025-10-01T03:00:00.0) +# + +# main cycle period +hardwarePollingPeriod = 100 + +# geographic coordinates of the observation site + +# site latitude in degrees +siteLatitude = 43.646711 + +# site longitude in degrees +siteLongitude = 41.440732 + +# site elevation in meters +siteElevation = 2070.0 + +# celestial coordinate transformation + +# wavelength at which refraction is calculated (in mkm) +refractWavelength = 0.55 + +# an empty filename means default precompiled string +leapSecondFilename = + +# an empty filename means default precompiled string +bulletinAFilename = + +# pointing correction model + +# PCM default type +pcmType = GEOMETRY + +# PCM geometrical coefficients +pcmGeomCoeffs = 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 + +# PCM B-spline degrees +pcmBsplineDegree = 3, 3 + +# PCM B-spline knots along X-axis (HA-angle or azimuth). By default from 0 to 2*PI radians +pcmBsplineXknots = 0.0, 0.6981317, 1.3962634, 2.0943951, 2.7925268, 3.4906585, 4.1887902, 4.88692191, 5.58505361, 6.28318531 + +# PCM B-spline knots along Y-axis (declination or zenithal distance). By default from -PI/6 to PI/2 radians +pcmBsplineYknots = -0.52359878, -0.29088821, -0.05817764, 0.17453293, 0.40724349, 0.63995406, 0.87266463, 1.10537519, 1.33808576, 1.57079633 + +# PCM B-spline coeffs for along X-axis (HA-angle or azimuth) +pcmBsplineXcoeffs = + +# PCM B-spline coeffs for along Y-axis (declination or zenithal distance) +pcmBsplineYcoeffs = + + +# slewing and tracking parameters + +# arcseconds per second +#sideralRate = 15.0410686 + +# timeout for telemetry updating in milliseconds +telemetryTimeout = 3000 + +# minimal allowed time in seconds to prohibited zone +minTimeToPZone = 10 + +# a time interval to update prohibited zones related quantities (millisecs) +updatingPZoneInterval = 5000 + +# coordinates difference in arcsecs to stop slewing +slewToleranceRadius = 5.0 + +# target-mount coordinate difference in arcsecs to start adjusting of slewing +adjustCoordDiff = 50.0 + +# minimum time in millisecs between two successive adjustments +adjustCycleInterval = 300 + +# slew process timeout in seconds +slewTimeout = 3600 + +# a time shift into future to compute target position in future (UT1-scale time duration, millisecs) +timeShiftToTargetPoint = 10000 + +# minimum time in millisecs between two successive tracking corrections +trackingCycleInterval = 300 + + +# prohibited zones + +# minimal altitude in degrees +pzMinAltitude = 10.0 + +# HA-axis limit switch minimal value in degrees +pzLimitSwitchHAMin = -170.0 + +# HA-axis limit switch maximal value in degrees +pzLimitSwitchHAMax = 170.0 + +# DEC-axis limit switch minimal value in degrees +pzLimitSwitchDecMin = -90.0 + +# DEC-axis limit switch maximal value in degrees +pzLimitSwitchDecMax = 90.0 + + +# hardware-related + +# hardware mode: 1 - model mode, otherwise real mode +RunModel = 0 + +# mount serial device paths +MountDevPath = /dev/ttyUSB0 + +# mount serial device speed +MountDevSpeed = 19200 + +# motor encoders serial device path +EncoderDevPath = + +# X-axis encoder serial device path +EncoderXDevPath = /dev/encoderX0 + +# Y-axis encoder serial device path +EncoderYDevPath = /dev/encoderY0 + +# encoders serial device speed +EncoderDevSpeed = 153000 + +# ==1 if encoder works as separate serial device, ==2 if there's new version with two devices +SepEncoder = 2 + +# mount polling interval in millisecs +MountReqInterval = 100 + +# encoders polling interval in millisecs +EncoderReqInterval = 50 + +# mount axes rate calculation interval in millisecs +EncoderSpeedInterval = 100 + +# X-axis coordinate PID P,I,D-params +XPIDC = 0.8, 0.1, 0.3 + +# X-axis rate PID P,I,D-params +XPIDV = 1.0, 0.01, 0.2 + +# Y-axis coordinate PID P,I,D-params +YPIDC = 0.8, 0.1, 0.3 + +# Y-axis rate PID P,I,D-params +YPIDV = 0.5, 0.2, 0.5 + + +# maximal moving rate (degrees per second) along HA-axis (Y-axis of Sidereal servo microcontroller) +hwMaxRateHA = 8.0 + +# maximal moving rate (degrees per second) along DEC-axis (X-axis of Sidereal servo microcontroller) +hwMaxRateDEC = 10.0 + +)--"; + } // namespace asibfm700 diff --git a/asibfm700/asibfm700_mount.cpp b/asibfm700/asibfm700_mount.cpp index 2056976..15f33af 100644 --- a/asibfm700/asibfm700_mount.cpp +++ b/asibfm700/asibfm700_mount.cpp @@ -125,6 +125,8 @@ Asibfm700Mount::error_t Asibfm700Mount::updateMountConfig(const Asibfm700MountCo { std::lock_guard lock{*_mountConfigMutex}; + _mountConfig = cfg; + hardwareUpdateConfig(_mountConfig.servoControllerConfig.devConfig); hardwareUpdateConfig(_mountConfig.servoControllerConfig.hwConfig); diff --git a/asibfm700/asibfm700_mount.h b/asibfm700/asibfm700_mount.h index 665a23e..9b8bdb7 100644 --- a/asibfm700/asibfm700_mount.h +++ b/asibfm700/asibfm700_mount.h @@ -11,7 +11,7 @@ #include #include "asibfm700_common.h" - +#include "asibfm700_configfile.h" namespace asibfm700 diff --git a/mcc/tests/cfg_test.cpp b/asibfm700/tests/cfg_test.cpp similarity index 77% rename from mcc/tests/cfg_test.cpp rename to asibfm700/tests/cfg_test.cpp index 5f4bd8b..af0b41d 100644 --- a/mcc/tests/cfg_test.cpp +++ b/asibfm700/tests/cfg_test.cpp @@ -1,6 +1,6 @@ #include -#include "../../asibfm700/asibfm700_configfile.h" +#include "../asibfm700_configfile.h" template struct rec_t { @@ -50,5 +50,18 @@ int main() } std::cout << "]\n"; + + std::ofstream fst("/tmp/cfg.cfg"); + fst << asibfm700::Asibfm700MountConfigString; + fst.close(); + + asibfm700::Asibfm700MountConfig acfg; + + auto ec = acfg.load("/tmp/cfg.cfg"); + std::cout << "EC (load) = " << ec.message() << "\n"; + + std::cout << "refr w: " << acfg.refractWavelength << "\n"; + + return 0; } diff --git a/mcc/CMakeLists.txt b/mcc/CMakeLists.txt index 5d12810..2013049 100644 --- a/mcc/CMakeLists.txt +++ b/mcc/CMakeLists.txt @@ -92,9 +92,5 @@ if (WITH_TESTS) target_include_directories(${CTTE_TEST_APP} PRIVATE ${ERFA_INCLUDE_DIR}) target_link_libraries(${CTTE_TEST_APP} ERFA_LIB bsplines) - set(CFG_TEST_APP cfg_test) - add_executable(${CFG_TEST_APP} tests/cfg_test.cpp) - target_link_libraries(${CFG_TEST_APP} PRIVATE mcc) - enable_testing() - endif() +endif() diff --git a/mcc/mcc_moving_model_common.h b/mcc/mcc_moving_model_common.h index ad540ed..fa7b7c5 100644 --- a/mcc/mcc_moving_model_common.h +++ b/mcc/mcc_moving_model_common.h @@ -21,7 +21,7 @@ struct MccSimpleMovingModelParams { static constexpr double sideralRate = 15.0410686_arcsecs; // in radians per second // timeout to telemetry updating - std::chrono::seconds telemetryTimeout{3}; + 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}; @@ -60,7 +60,7 @@ struct MccSimpleMovingModelParams { 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::duration timeShiftToTargetPoint{10.0}; + std::chrono::milliseconds timeShiftToTargetPoint{10000}; // ******* guiding mode *******