...
This commit is contained in:
parent
0b7261a431
commit
3d769d79eb
@ -40,4 +40,14 @@ set(ASIBFM700_LIB asibfm700mount)
|
|||||||
add_library(${ASIBFM700_LIB} STATIC ${ASIBFM700_LIB_SRC}
|
add_library(${ASIBFM700_LIB} STATIC ${ASIBFM700_LIB_SRC}
|
||||||
asibfm700_mount.h asibfm700_mount.cpp
|
asibfm700_mount.h asibfm700_mount.cpp
|
||||||
asibfm700_configfile.h)
|
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()
|
||||||
|
|||||||
@ -26,7 +26,7 @@ typedef mcc::utils::MccSpdlogLogger Asibfm700Logger;
|
|||||||
|
|
||||||
/* MOUNT CONFIGURATION CLASS */
|
/* MOUNT CONFIGURATION CLASS */
|
||||||
|
|
||||||
struct Asibfm700MountConfig {
|
struct Asibfm700MountConfig1 {
|
||||||
std::chrono::milliseconds hardwarePollingPeriod{100}; // main cycle period
|
std::chrono::milliseconds hardwarePollingPeriod{100}; // main cycle period
|
||||||
|
|
||||||
// CCTE-related configuration
|
// CCTE-related configuration
|
||||||
|
|||||||
@ -8,9 +8,13 @@
|
|||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
#include <mcc_angle.h>
|
#include <mcc_angle.h>
|
||||||
|
#include <mcc_moving_model_common.h>
|
||||||
#include <mcc_pcm.h>
|
#include <mcc_pcm.h>
|
||||||
#include <mcc_utils.h>
|
#include <mcc_utils.h>
|
||||||
|
|
||||||
|
#include "asibfm700_common.h"
|
||||||
|
#include "asibfm700_servocontroller.h"
|
||||||
|
|
||||||
namespace asibfm700
|
namespace asibfm700
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -306,11 +310,15 @@ static auto Asibfm700MountConfigDefaults = std::make_tuple(
|
|||||||
simple_config_record_t{"pcmBsplineDegree", std::vector<size_t>{3, 3}},
|
simple_config_record_t{"pcmBsplineDegree", std::vector<size_t>{3, 3}},
|
||||||
|
|
||||||
// PCM B-spline knots along X-axis (HA-angle or azimuth). By default from 0 to 2*PI radians
|
// 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",
|
simple_config_record_t{"pcmBsplineXknots",
|
||||||
std::vector<double>{0.0, 0.6981317, 1.3962634, 2.0943951, 2.7925268, 3.4906585, 4.1887902,
|
std::vector<double>{0.0, 0.6981317, 1.3962634, 2.0943951, 2.7925268, 3.4906585, 4.1887902,
|
||||||
4.88692191, 5.58505361, 6.28318531}},
|
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
|
// 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",
|
simple_config_record_t{"pcmBsplineYknots",
|
||||||
std::vector<double>{-0.52359878, -0.29088821, -0.05817764, 0.17453293, 0.40724349,
|
std::vector<double>{-0.52359878, -0.29088821, -0.05817764, 0.17453293, 0.40724349,
|
||||||
0.63995406, 0.87266463, 1.10537519, 1.33808576, 1.57079633}},
|
0.63995406, 0.87266463, 1.10537519, 1.33808576, 1.57079633}},
|
||||||
@ -324,8 +332,8 @@ static auto Asibfm700MountConfigDefaults = std::make_tuple(
|
|||||||
|
|
||||||
/* slewing and tracking parameters */
|
/* slewing and tracking parameters */
|
||||||
|
|
||||||
// arcseconds per second
|
// // arcseconds per second
|
||||||
simple_config_record_t{"sideralRate", 15.0410686},
|
// simple_config_record_t{"sideralRate", 15.0410686},
|
||||||
|
|
||||||
// timeout for telemetry updating in milliseconds
|
// timeout for telemetry updating in milliseconds
|
||||||
simple_config_record_t{"telemetryTimeout", std::chrono::milliseconds(3000)},
|
simple_config_record_t{"telemetryTimeout", std::chrono::milliseconds(3000)},
|
||||||
@ -375,11 +383,59 @@ static auto Asibfm700MountConfigDefaults = std::make_tuple(
|
|||||||
|
|
||||||
/* hardware-related */
|
/* 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<double>{0.8, 0.1, 0.3}},
|
||||||
|
|
||||||
|
// X-axis rate PID P,I,D-params
|
||||||
|
simple_config_record_t{"XPIDV", std::vector<double>{1.0, 0.01, 0.2}},
|
||||||
|
|
||||||
|
// Y-axis coordinate PID P, I, D-params
|
||||||
|
simple_config_record_t{"YPIDC", std::vector<double>{0.8, 0.1, 0.3}},
|
||||||
|
|
||||||
|
// Y-axis rate PID P,I,D-params
|
||||||
|
simple_config_record_t{"YPIDV", std::vector<double>{0.5, 0.2, 0.5}},
|
||||||
|
|
||||||
|
|
||||||
// maximal moving rate (degrees per second) along HA-axis (Y-axis of Sidereal servo microcontroller)
|
// 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)
|
// 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<decltype(Asibfm700MountConfi
|
|||||||
public:
|
public:
|
||||||
using base_t::value;
|
using base_t::value;
|
||||||
|
|
||||||
Asibfm700MountConfig() : base_t(Asibfm700MountConfigDefaults) {}
|
Asibfm700MountConfig() : base_t(Asibfm700MountConfigDefaults)
|
||||||
|
{
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
~Asibfm700MountConfig() = default;
|
~Asibfm700MountConfig() = default;
|
||||||
|
|
||||||
@ -410,25 +469,243 @@ public:
|
|||||||
buffer.resize(sz);
|
buffer.resize(sz);
|
||||||
|
|
||||||
fst.read(buffer.data(), sz);
|
fst.read(buffer.data(), sz);
|
||||||
} catch (std::ios_base::failure const& ex) {
|
|
||||||
return ex.code();
|
|
||||||
} catch (...) {
|
|
||||||
return std::make_error_code(std::errc::not_enough_memory);
|
|
||||||
}
|
|
||||||
|
|
||||||
fst.close();
|
fst.close();
|
||||||
} else {
|
|
||||||
return ec;
|
ec = base_t::parse(buffer, deserializer);
|
||||||
|
if (!ec) {
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
} catch (std::ios_base::failure const& ex) {
|
||||||
|
ec = ex.code();
|
||||||
|
} catch (std::length_error const& ex) {
|
||||||
|
ec = std::make_error_code(std::errc::no_buffer_space);
|
||||||
|
} catch (std::bad_alloc const& ex) {
|
||||||
|
ec = std::make_error_code(std::errc::not_enough_memory);
|
||||||
|
} catch (...) {
|
||||||
|
ec = std::make_error_code(std::errc::operation_canceled);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return base_t::parse(buffer, deserializer);
|
return ec;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::chrono::milliseconds hardwarePollingPeriod{};
|
||||||
|
|
||||||
|
mcc::MccAngle siteLatitude{};
|
||||||
|
mcc::MccAngle siteLongitude{};
|
||||||
|
double siteElevation{};
|
||||||
|
double refractWavelength{};
|
||||||
|
|
||||||
|
std::string leapSecondFilename{};
|
||||||
|
std::string bulletinAFilename{};
|
||||||
|
|
||||||
|
mcc::MccAngle pzMinAltitude{};
|
||||||
|
mcc::MccAngle pzLimitSwitchHAMin{};
|
||||||
|
mcc::MccAngle pzLimitSwitchHAMax{};
|
||||||
|
|
||||||
|
|
||||||
|
AsibFM700ServoController::hardware_config_t servoControllerConfig{};
|
||||||
|
mcc::MccSimpleMovingModelParams movingModelParams{};
|
||||||
|
Asibfm700PCM::pcm_data_t pcmData{};
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
void update()
|
||||||
|
{
|
||||||
|
hardwarePollingPeriod = std::get<decltype(hardwarePollingPeriod)>(this->_configDB["hardwarePollingPeriod"]);
|
||||||
|
|
||||||
|
// CCTE
|
||||||
|
|
||||||
|
siteLatitude = std::get<mcc::MccAngle>(this->_configDB["siteLatitude"]);
|
||||||
|
siteLongitude = std::get<mcc::MccAngle>(this->_configDB["siteLongitude"]);
|
||||||
|
siteElevation = std::get<double>(this->_configDB["siteElevation"]);
|
||||||
|
refractWavelength = std::get<double>(this->_configDB["refractWavelength"]);
|
||||||
|
|
||||||
|
leapSecondFilename = std::get<std::string>(this->_configDB["leapSecondFilename"]);
|
||||||
|
bulletinAFilename = std::get<std::string>(this->_configDB["bulletinAFilename"]);
|
||||||
|
|
||||||
|
// prohibited zones
|
||||||
|
|
||||||
|
pzMinAltitude = std::get<mcc::MccAngle>(this->_configDB["pzMinAltitude"]);
|
||||||
|
pzLimitSwitchHAMin = std::get<mcc::MccAngle>(this->_configDB["pzLimitSwitchHAMin"]);
|
||||||
|
pzLimitSwitchHAMax = std::get<mcc::MccAngle>(this->_configDB["pzLimitSwitchHAMax"]);
|
||||||
|
|
||||||
|
|
||||||
|
// hardware config
|
||||||
|
|
||||||
|
servoControllerConfig.hwConfig = {};
|
||||||
|
|
||||||
|
servoControllerConfig.MountDevPath = std::get<std::string>(this->_configDB["MountDevPath"]);
|
||||||
|
servoControllerConfig.EncoderDevPath = std::get<std::string>(this->_configDB["EncoderDevPath"]);
|
||||||
|
servoControllerConfig.EncoderXDevPath = std::get<std::string>(this->_configDB["EncoderXDevPath"]);
|
||||||
|
servoControllerConfig.EncoderYDevPath = std::get<std::string>(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<int>(this->_configDB["RunModel"]);
|
||||||
|
servoControllerConfig.devConfig.MountDevSpeed = std::get<int>(this->_configDB["MountDevSpeed"]);
|
||||||
|
servoControllerConfig.devConfig.EncoderDevSpeed = std::get<int>(this->_configDB["EncoderDevSpeed"]);
|
||||||
|
servoControllerConfig.devConfig.SepEncoder = std::get<int>(this->_configDB["SepEncoder"]);
|
||||||
|
|
||||||
|
std::chrono::duration<double> secs; // seconds as floating-point
|
||||||
|
|
||||||
|
secs = std::get<std::chrono::milliseconds>(this->_configDB["MountReqInterval"]);
|
||||||
|
servoControllerConfig.devConfig.MountReqInterval = secs.count();
|
||||||
|
|
||||||
|
secs = std::get<std::chrono::milliseconds>(this->_configDB["EncoderReqInterval"]);
|
||||||
|
servoControllerConfig.devConfig.EncoderReqInterval = secs.count();
|
||||||
|
|
||||||
|
secs = std::get<std::chrono::milliseconds>(this->_configDB["EncoderSpeedInterval"]);
|
||||||
|
servoControllerConfig.devConfig.EncoderSpeedInterval = secs.count();
|
||||||
|
|
||||||
|
std::vector<double> pid = std::get<std::vector<double>>(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<std::vector<double>>(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<std::vector<double>>(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<std::vector<double>>(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<decltype(movingModelParams.telemetryTimeout)>(this->_configDB["telemetryTimeout"]);
|
||||||
|
|
||||||
|
movingModelParams.minTimeToPZone =
|
||||||
|
std::get<decltype(movingModelParams.minTimeToPZone)>(this->_configDB["minTimeToPZone"]);
|
||||||
|
|
||||||
|
movingModelParams.updatingPZoneInterval =
|
||||||
|
std::get<decltype(movingModelParams.updatingPZoneInterval)>(this->_configDB["updatingPZoneInterval"]);
|
||||||
|
|
||||||
|
movingModelParams.slewToleranceRadius =
|
||||||
|
std::get<decltype(movingModelParams.slewToleranceRadius)>(this->_configDB["slewToleranceRadius"]);
|
||||||
|
|
||||||
|
movingModelParams.adjustCoordDiff =
|
||||||
|
std::get<decltype(movingModelParams.adjustCoordDiff)>(this->_configDB["adjustCoordDiff"]);
|
||||||
|
|
||||||
|
movingModelParams.adjustCycleInterval =
|
||||||
|
std::get<decltype(movingModelParams.adjustCycleInterval)>(this->_configDB["adjustCycleInterval"]);
|
||||||
|
|
||||||
|
movingModelParams.slewTimeout =
|
||||||
|
std::get<decltype(movingModelParams.slewTimeout)>(this->_configDB["slewTimeout"]);
|
||||||
|
|
||||||
|
movingModelParams.timeShiftToTargetPoint =
|
||||||
|
std::get<decltype(movingModelParams.timeShiftToTargetPoint)>(this->_configDB["timeShiftToTargetPoint"]);
|
||||||
|
|
||||||
|
movingModelParams.trackingCycleInterval =
|
||||||
|
std::get<decltype(movingModelParams.trackingCycleInterval)>(this->_configDB["trackingCycleInterval"]);
|
||||||
|
|
||||||
|
|
||||||
|
// PCM data
|
||||||
|
|
||||||
|
pcmData.type = std::get<decltype(pcmData.type)>(this->_configDB["pcmType"]);
|
||||||
|
|
||||||
|
pcmData.siteLatitude = std::get<mcc::MccAngle>(this->_configDB["siteLatitude"]);
|
||||||
|
|
||||||
|
pid = std::get<std::vector<double>>(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<size_t> dd = std::get<decltype(dd)>(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<std::vector<double>>(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<std::vector<double>>(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<std::vector<double>>(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<std::vector<double>>(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) {
|
inline static auto deserializer = [](std::string_view str, auto& value) {
|
||||||
using value_t = std::decay_t<decltype(value)>;
|
using value_t = std::decay_t<decltype(value)>;
|
||||||
|
|
||||||
bool ok;
|
bool ok = true;
|
||||||
|
|
||||||
if constexpr (std::is_arithmetic_v<value_t> || std::ranges::output_range<value_t, char> ||
|
if constexpr (std::is_arithmetic_v<value_t> || std::ranges::output_range<value_t, char> ||
|
||||||
std::ranges::range<value_t>) {
|
std::ranges::range<value_t>) {
|
||||||
@ -446,6 +723,22 @@ protected:
|
|||||||
if (ok) {
|
if (ok) {
|
||||||
value = mcc::MccAngle(vd, mcc::MccDegreeTag{});
|
value = mcc::MccAngle(vd, mcc::MccDegreeTag{});
|
||||||
}
|
}
|
||||||
|
} else if constexpr (std::same_as<value_t, mcc::MccDefaultPCMType>) {
|
||||||
|
std::string vstr;
|
||||||
|
ok = base_t::defaultDeserializeFunc(str, vstr);
|
||||||
|
auto s = mcc::utils::trimSpaces(vstr);
|
||||||
|
|
||||||
|
if (ok) {
|
||||||
|
if (s == mcc::MccDefaultPCMTypeString<mcc::MccDefaultPCMType::PCM_TYPE_GEOMETRY>) {
|
||||||
|
value = mcc::MccDefaultPCMType::PCM_TYPE_GEOMETRY;
|
||||||
|
} else if (s == mcc::MccDefaultPCMTypeString<mcc::MccDefaultPCMType::PCM_TYPE_GEOMETRY_BSPLINE>) {
|
||||||
|
value = mcc::MccDefaultPCMType::PCM_TYPE_GEOMETRY;
|
||||||
|
} else if (s == mcc::MccDefaultPCMTypeString<mcc::MccDefaultPCMType::PCM_TYPE_BSPLINE>) {
|
||||||
|
value = mcc::MccDefaultPCMType::PCM_TYPE_BSPLINE;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return false;
|
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
|
} // namespace asibfm700
|
||||||
|
|||||||
@ -125,6 +125,8 @@ Asibfm700Mount::error_t Asibfm700Mount::updateMountConfig(const Asibfm700MountCo
|
|||||||
{
|
{
|
||||||
std::lock_guard lock{*_mountConfigMutex};
|
std::lock_guard lock{*_mountConfigMutex};
|
||||||
|
|
||||||
|
_mountConfig = cfg;
|
||||||
|
|
||||||
hardwareUpdateConfig(_mountConfig.servoControllerConfig.devConfig);
|
hardwareUpdateConfig(_mountConfig.servoControllerConfig.devConfig);
|
||||||
hardwareUpdateConfig(_mountConfig.servoControllerConfig.hwConfig);
|
hardwareUpdateConfig(_mountConfig.servoControllerConfig.hwConfig);
|
||||||
|
|
||||||
|
|||||||
@ -11,7 +11,7 @@
|
|||||||
#include <mcc_tracking_model.h>
|
#include <mcc_tracking_model.h>
|
||||||
|
|
||||||
#include "asibfm700_common.h"
|
#include "asibfm700_common.h"
|
||||||
|
#include "asibfm700_configfile.h"
|
||||||
|
|
||||||
|
|
||||||
namespace asibfm700
|
namespace asibfm700
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#include "../../asibfm700/asibfm700_configfile.h"
|
#include "../asibfm700_configfile.h"
|
||||||
|
|
||||||
template <typename VT>
|
template <typename VT>
|
||||||
struct rec_t {
|
struct rec_t {
|
||||||
@ -50,5 +50,18 @@ int main()
|
|||||||
}
|
}
|
||||||
std::cout << "]\n";
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -92,9 +92,5 @@ if (WITH_TESTS)
|
|||||||
target_include_directories(${CTTE_TEST_APP} PRIVATE ${ERFA_INCLUDE_DIR})
|
target_include_directories(${CTTE_TEST_APP} PRIVATE ${ERFA_INCLUDE_DIR})
|
||||||
target_link_libraries(${CTTE_TEST_APP} ERFA_LIB bsplines)
|
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()
|
enable_testing()
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
@ -21,7 +21,7 @@ struct MccSimpleMovingModelParams {
|
|||||||
static constexpr double sideralRate = 15.0410686_arcsecs; // in radians per second
|
static constexpr double sideralRate = 15.0410686_arcsecs; // in radians per second
|
||||||
|
|
||||||
// timeout to telemetry updating
|
// 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
|
// minimal time to prohibited zone (at current speed in slewing mode). if it is lesser then exit with error
|
||||||
std::chrono::seconds minTimeToPZone{10};
|
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
|
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)
|
// time shift into future to compute target position in future (UT1-scale time duration)
|
||||||
std::chrono::duration<double> timeShiftToTargetPoint{10.0};
|
std::chrono::milliseconds timeShiftToTargetPoint{10000};
|
||||||
|
|
||||||
// ******* guiding mode *******
|
// ******* guiding mode *******
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user