...
This commit is contained in:
@@ -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{};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user