This commit is contained in:
Timur A. Fatkhullin
2026-05-25 21:34:25 +03:00
parent a304f330fb
commit 03e98d0032

View File

@@ -7,6 +7,9 @@
#include <mcc/mcc_pcm.h> #include <mcc/mcc_pcm.h>
#include "mcc/mcc_pzone.h" #include "mcc/mcc_pzone.h"
#include "asibfm700_common.h"
#include "asibfm700_servocontroller.h"
namespace asibfm700 namespace asibfm700
{ {
@@ -29,7 +32,7 @@ static config_record_t<T> make_config_record(
std::string_view icomm = {}, std::string_view icomm = {},
mcc::impl::mcc_serialization_params_t const& spars = mcc::impl::mcc_serialization_params_t{}) mcc::impl::mcc_serialization_params_t const& spars = mcc::impl::mcc_serialization_params_t{})
{ {
return config_record_t<T>{key, value, value, spars, hcomm, icomm}; return config_record_t<T>{{key, value, value, spars}, hcomm, icomm};
} }
@@ -463,6 +466,296 @@ public:
return _lastConfigPath; return _lastConfigPath;
} }
/* some most often used quantities */
template <mcc::mcc_angle_c T>
T siteLatitude() const
{
return static_cast<double>(getValue<mcc::impl::MccAngle>("siteLatitude").value_or(mcc::impl::MccAngle{}));
};
mcc::impl::MccAngle siteLatitude() const
{
return siteLatitude<mcc::impl::MccAngle>();
};
template <mcc::mcc_angle_c T>
T siteLongitude() const
{
return static_cast<double>(getValue<mcc::impl::MccAngle>("siteLongitude").value_or(mcc::impl::MccAngle{}));
};
mcc::impl::MccAngle siteLongitude() const
{
return siteLongitude<mcc::impl::MccAngle>();
};
template <typename T>
T siteElevation() const
requires std::is_arithmetic_v<T>
{
return getValue<double>("siteElevation").value_or(0.0);
}
double siteElevation() const
{
return getValue<double>("siteElevation").value_or(0.0);
};
template <typename T>
T refractWavelength() const
requires std::is_arithmetic_v<T>
{
return getValue<double>("refractWavelength").value_or(0.0);
}
double refractWavelength() const
{
return getValue<double>("refractWavelength").value_or(0.0);
};
template <mcc::traits::mcc_output_char_range R>
R leapSecondFilename() const
{
R r;
std::string val = getValue<std::string>("leapSecondFilename").value_or("");
std::ranges::copy(val, std::back_inserter(r));
return r;
}
std::string leapSecondFilename() const
{
return leapSecondFilename<std::string>();
};
template <mcc::traits::mcc_output_char_range R>
R bulletinAFilename() const
{
R r;
std::string val = getValue<std::string>("bulletinAFilename").value_or("");
std::ranges::copy(val, std::back_inserter(r));
return r;
}
std::string bulletinAFilename() const
{
return bulletinAFilename<std::string>();
};
AsibFM700ServoController::hardware_config_t servoControllerConfig() const
{
AsibFM700ServoController::hardware_config_t hw_cfg;
hw_cfg.hwConfig = {};
hw_cfg.MountDevPath = getValue<std::string>("MountDevPath").value_or(std::string{});
hw_cfg.EncoderDevPath = getValue<std::string>("EncoderDevPath").value_or(std::string{});
hw_cfg.EncoderXDevPath = getValue<std::string>("EncoderXDevPath").value_or(std::string{});
hw_cfg.EncoderYDevPath = getValue<std::string>("EncoderYDevPath").value_or(std::string{});
hw_cfg.devConfig.MountDevPath = hw_cfg.MountDevPath.data();
hw_cfg.devConfig.EncoderDevPath = hw_cfg.EncoderDevPath.data();
hw_cfg.devConfig.EncoderXDevPath = hw_cfg.EncoderXDevPath.data();
hw_cfg.devConfig.EncoderYDevPath = hw_cfg.EncoderYDevPath.data();
hw_cfg.devConfig.RunModel = getValue<int>("RunModel").value_or(int{});
hw_cfg.devConfig.MountDevSpeed = getValue<int>("MountDevSpeed").value_or(int{});
hw_cfg.devConfig.EncoderDevSpeed = getValue<int>("EncoderDevSpeed").value_or(int{});
hw_cfg.devConfig.SepEncoder = getValue<int>("SepEncoder").value_or(int{});
std::chrono::duration<double> secs; // seconds as floating-point
secs = getValue<std::chrono::milliseconds>("MountReqInterval").value_or(std::chrono::milliseconds{});
hw_cfg.devConfig.MountReqInterval = secs.count();
secs = getValue<std::chrono::milliseconds>("EncoderReqInterval").value_or(std::chrono::milliseconds{});
hw_cfg.devConfig.EncoderReqInterval = secs.count();
secs = getValue<std::chrono::milliseconds>("EncoderSpeedInterval").value_or(std::chrono::milliseconds{});
hw_cfg.devConfig.EncoderSpeedInterval = secs.count();
secs = getValue<std::chrono::milliseconds>("PIDMaxDt").value_or(std::chrono::milliseconds{1000});
hw_cfg.devConfig.PIDMaxDt = secs.count();
secs = getValue<std::chrono::milliseconds>("PIDRefreshDt").value_or(std::chrono::milliseconds{100});
hw_cfg.devConfig.PIDRefreshDt = secs.count();
secs = getValue<std::chrono::milliseconds>("PIDCycleDt").value_or(std::chrono::milliseconds{5000});
hw_cfg.devConfig.PIDCycleDt = secs.count();
std::vector<double> pid = getValue<std::vector<double>>("XPIDV").value_or(std::vector<double>{});
if (pid.size() > 2) {
hw_cfg.devConfig.XPIDV.P = pid[0];
hw_cfg.devConfig.XPIDV.I = pid[1];
hw_cfg.devConfig.XPIDV.D = pid[2];
}
pid = getValue<std::vector<double>>("YPIDV").value_or(std::vector<double>{});
if (pid.size() > 2) {
hw_cfg.devConfig.YPIDV.P = pid[0];
hw_cfg.devConfig.YPIDV.I = pid[1];
hw_cfg.devConfig.YPIDV.D = pid[2];
}
double ang = getValue<mcc::impl::MccAngle>("MaxPointingErr").value_or(mcc::impl::MccAngle(8.0_degs));
hw_cfg.devConfig.MaxPointingErr = ang;
ang = getValue<mcc::impl::MccAngle>("MaxFinePointingErr").value_or(mcc::impl::MccAngle(1.5_degs));
hw_cfg.devConfig.MaxFinePointingErr = ang;
ang = getValue<mcc::impl::MccAngle>("MaxGuidingErr").value_or(mcc::impl::MccAngle(0.5_arcsecs));
hw_cfg.devConfig.MaxGuidingErr = ang;
ang = getValue<int64_t>("XEncZero").value_or(0);
hw_cfg.devConfig.XEncZero = ang;
ang = getValue<int64_t>("YEncZero").value_or(0);
hw_cfg.devConfig.YEncZero = ang;
return hw_cfg;
}
Asibfm700PCM::pcm_data_t pcmData() const
{
Asibfm700PCM::pcm_data_t pcm_data;
std::vector<double> empty_vec;
pcm_data.type = getValue<decltype(pcm_data.type)>("pcmType").value_or(pcm_data.type);
pcm_data.siteLatitude = getValue<mcc::impl::MccAngle>("siteLatitude").value_or(pcm_data.siteLatitude);
std::vector<double> vec = getValue<std::vector<double>>("pcmGeomCoeffs").value_or(empty_vec);
if (vec.size() >= 9) { // must be 9 coefficients
pcm_data.geomCoefficients = {.zeroPointX = vec[0],
.zeroPointY = vec[1],
.collimationErr = vec[2],
.nonperpendErr = vec[3],
.misalignErr1 = vec[4],
.misalignErr2 = vec[5],
.tubeFlexure = vec[6],
.DECaxisFlexure = vec[7],
.forkFlexure = vec[8]};
}
#ifdef USE_BSPLINE_PCM
// std::vector<size_t> dd = getValue<decltype(dd)>("pcmBsplineDegree").value_or(dd);
// if (dd.size() >= 2) {
// pcm_data.bspline.bsplDegreeX = dd[0] > 0 ? dd[0] : 3;
// pcm_data.bspline.bsplDegreeY = dd[1] > 0 ? dd[1] : 3;
// }
vec = getValue<std::vector<double>>("pcmBsplineXknots").value_or(empty_vec);
// pid must contains interior and border (single point for each border) knots so minimal length must be 2
if (vec.size() >= 2) {
// generate full knots array (with border knots)
size_t Nknots = vec.size() + pcm_data.bspline.bsplDegreeX * 2 - 2;
pcm_data.bspline.knotsX.resize(Nknots);
for (size_t i = 0; i <= pcm_data.bspline.bsplDegreeX; ++i) { // border knots
pcm_data.bspline.knotsX[i] = vec[0];
pcm_data.bspline.knotsX[Nknots - i - 1] = vec.back();
}
for (size_t i = 0; i < (vec.size() - 2); ++i) { // interior knots
pcm_data.bspline.knotsX[i + pcm_data.bspline.bsplDegreeX] = vec[1 + i];
}
}
vec = getValue<std::vector<double>>("pcmBsplineYknots").value_or(empty_vec);
// pid must contains interior and border (single point for each border) knots so minimal length must be 2
if (vec.size() >= 2) {
// generate full knots array (with border knots)
size_t Nknots = vec.size() + pcm_data.bspline.bsplDegreeY * 2 - 2;
pcm_data.bspline.knotsY.resize(Nknots);
for (size_t i = 0; i <= pcm_data.bspline.bsplDegreeY; ++i) { // border knots
pcm_data.bspline.knotsY[i] = vec[0];
pcm_data.bspline.knotsY[Nknots - i - 1] = vec.back();
}
for (size_t i = 0; i < (vec.size() - 2); ++i) { // interior knots
pcm_data.bspline.knotsY[i + pcm_data.bspline.bsplDegreeY] = vec[1 + i];
}
}
// minimal allowed number of B-spline coefficients
size_t Ncoeffs = pcm_data.type == mcc::impl::MccDefaultPCMType::PCM_TYPE_GEOMETRY
? 0
: (pcm_data.bspline.knotsX.size() - pcm_data.bspline.bsplDegreeX - 1) *
(pcm_data.bspline.knotsY.size() - pcm_data.bspline.bsplDegreeY - 1);
vec = getValue<std::vector<double>>("pcmBsplineXcoeffs").value_or(empty_vec);
if (vec.size() >= Ncoeffs) {
pcm_data.bspline.coeffsX.clear();
std::ranges::copy_n(vec.begin(), Ncoeffs, std::back_inserter(pcm_data.bspline.coeffsX));
// pcm_data.bspline.coeffsX.resize(Ncoeffs);
// for (size_t i = 0; i < Ncoeffs; ++i) {
// pcm_data.bspline.coeffsX[i] = vec[i];
// }
}
vec = getValue<std::vector<double>>("pcmBsplineYcoeffs").value_or(empty_vec);
if (vec.size() >= Ncoeffs) {
pcm_data.bspline.coeffsY.clear();
std::ranges::copy_n(vec.begin(), Ncoeffs, std::back_inserter(pcm_data.bspline.coeffsY));
// pcm_data.bspline.coeffsY.resize(Ncoeffs);
// for (size_t i = 0; i < Ncoeffs; ++i) {
// pcm_data.bspline.coeffsY[i] = vec[i];
// }
}
vec = getValue<std::vector<double>>("pcmInverseBsplineXcoeffs").value_or(empty_vec);
if (vec.size() >= Ncoeffs) {
pcm_data.bspline.inverseCoeffsX.clear();
std::ranges::copy_n(vec.begin(), Ncoeffs, std::back_inserter(pcm_data.bspline.inverseCoeffsX));
}
vec = getValue<std::vector<double>>("pcmInverseBsplineYcoeffs").value_or(empty_vec);
if (vec.size() >= Ncoeffs) {
pcm_data.bspline.inverseCoeffsY.clear();
std::ranges::copy_n(vec.begin(), Ncoeffs, std::back_inserter(pcm_data.bspline.inverseCoeffsY));
}
#endif
return pcm_data;
}
mcc::impl::MccAltLimitPZ<mcc::impl::MccAltLimitKind::MIN_ALT_LIMIT> minAltPZone()
{
return getValue<mcc::impl::MccAltLimitPZ<mcc::impl::MccAltLimitKind::MIN_ALT_LIMIT>>("altLimPZ")
.value_or(mcc::impl::MccAltLimitPZ<mcc::impl::MccAltLimitKind::MIN_ALT_LIMIT>{10.0, SAORAS_LATITUDE});
}
mcc::impl::MccAxisLimitSwitchPZ<mcc::impl::MccCoordKind::COORDS_KIND_HA_OBS> axisLimitSwitchHA()
{
return getValue<mcc::impl::MccAxisLimitSwitchPZ<mcc::impl::MccCoordKind::COORDS_KIND_HA_OBS>>(
"axisLimitSwitchHA")
.value_or(mcc::impl::MccAxisLimitSwitchPZ<mcc::impl::MccCoordKind::COORDS_KIND_HA_OBS>{
-170.0_degs, 170.0_degs, nullptr});
}
mcc::impl::MccAxisLimitSwitchPZ<mcc::impl::MccCoordKind::COORDS_KIND_DEC_OBS> axisLimitSwitchDEC()
{
return getValue<mcc::impl::MccAxisLimitSwitchPZ<mcc::impl::MccCoordKind::COORDS_KIND_DEC_OBS>>(
"axisLimitSwitchDEC")
.value_or(mcc::impl::MccAxisLimitSwitchPZ<mcc::impl::MccCoordKind::COORDS_KIND_DEC_OBS>{
-90.0_degs, 90.0_degs, nullptr});
}
private: private:
std::filesystem::path _lastConfigPath{}; std::filesystem::path _lastConfigPath{};