7#include "calibration.h"
9#include "ekos_guide_debug.h"
12#include "indi/indimount.h"
14Calibration::Calibration()
16 ROT_Z = GuiderUtils::Matrix(0);
19void Calibration::setAngle(
double rotationAngle)
21 angle = rotationAngle;
22 ROT_Z = GuiderUtils::RotateZ(-M_PI * angle / 180.0);
38 subBinXused = subBinX;
39 subBinYused = subBinY;
43void Calibration::setBinningUsed(
int x,
int y)
49void Calibration::setRaPulseMsPerArcsecond(
double rate)
51 raPulseMsPerArcsecond = rate;
54void Calibration::setDecPulseMsPerArcsecond(
double rate)
56 decPulseMsPerArcsecond = rate;
59GuiderUtils::Vector Calibration::convertToArcseconds(
const GuiderUtils::Vector &input)
const
62 arcseconds.x = input.x * xArcsecondsPerPixel();
63 arcseconds.y = input.y * yArcsecondsPerPixel();
67GuiderUtils::Vector Calibration::convertToPixels(
const GuiderUtils::Vector &input)
const
70 arcseconds.x = input.x / xArcsecondsPerPixel();
71 arcseconds.y = input.y / yArcsecondsPerPixel();
82GuiderUtils::Vector Calibration::rotateToRaDec(
const GuiderUtils::Vector &input)
const
84 GuiderUtils::Vector in;
90void Calibration::rotateToRaDec(
double dx,
double dy,
91 double *ra,
double *dec)
const
93 GuiderUtils::Vector input;
96 GuiderUtils::Vector
out = rotateToRaDec(input);
101double Calibration::binFactor()
const
103 return static_cast<double>(subBinXused) /
static_cast<double>(subBinX);
106double Calibration::inverseBinFactor()
const
108 return 1.0 / binFactor();
111double Calibration::xArcsecondsPerPixel()
const
114 return binFactor() * (206264.806 * ccd_pixel_width * subBinX) / focalMm;
117double Calibration::yArcsecondsPerPixel()
const
119 return binFactor() * (206264.806 * ccd_pixel_height * subBinY) / focalMm;
122double Calibration::xPixelsPerArcsecond()
const
124 return inverseBinFactor() * (focalMm / (206264.806 * ccd_pixel_width * subBinX));
127double Calibration::yPixelsPerArcsecond()
const
129 return inverseBinFactor() * (focalMm / (206264.806 * ccd_pixel_height * subBinY));
132double Calibration::raPulseMillisecondsPerArcsecond()
const
134 return raPulseMsPerArcsecond;
137double Calibration::decPulseMillisecondsPerArcsecond()
const
139 return decPulseMsPerArcsecond;
142double Calibration::calculateRotation(
double x,
double y)
150 if ((!GuiderUtils::Vector(x, y, 0)) < 1)
156 phi = y > 0 ? 90.0 : 270;
174bool Calibration::calculate1D(
double dx,
double dy,
int RATotalPulse)
176 const double arcSecondsX = dx * xArcsecondsPerPixel();
177 const double arcSecondsY = dy * yArcsecondsPerPixel();
182 <<
QString(
"Bad input to calculate1D: ra %1 %2 total pulse %3")
192 calibrationAngle =
phi;
193 calibrationAngleRA =
phi;
194 calibrationAngleDEC = -1;
195 decSwap = calibrationDecSwap =
false;
200 if (raPulseMillisecondsPerArcsecond() > 10000)
203 <<
"Calibration computed unreasonable pulse-milliseconds-per-arcsecond: "
204 << raPulseMillisecondsPerArcsecond() <<
" & " << decPulseMillisecondsPerArcsecond();
211bool Calibration::calculate2D(
222bool Calibration::calculate2D(
235 <<
QString(
"Bad input to calculate2D: ra %1 %2 dec %3 %4 total pulses %5 %6")
264 calibrationAngleRA =
phi_ra;
294 calibrationAngle =
phi;
299 calibrationDecSwap = decSwap;
308 if (raPulseMillisecondsPerArcsecond() > 10000 || decPulseMillisecondsPerArcsecond() > 10000)
311 <<
"Calibration computed unreasonable pulse-milliseconds-per-arcsecond: "
312 << raPulseMillisecondsPerArcsecond() <<
" & " << decPulseMillisecondsPerArcsecond();
323void Calibration::computeDrift(
const GuiderUtils::Vector &
detection,
const GuiderUtils::Vector &reference,
326 GuiderUtils::Vector drift =
detection - reference;
327 drift = rotateToRaDec(drift);
333void Calibration::setDeclinationSwapEnabled(
bool value)
336 .
arg(value ?
"T" :
"F")
337 .arg(decSwap ?
"T" :
"F")
338 .arg(calibrationDecSwap ?
"T" :
"F");
341QString Calibration::serialize()
const
348 QString(
"Cal v1.0,bx=%1,by=%2,pw=%3,ph=%4,fl=%5,ang=%6,angR=%7,angD=%8,"
349 "ramspas=%9,decmspas=%10,swap=%11,ra=%12,dec=%13,side=%14,when=%15,calEnd")
350 .
arg(subBinX).
arg(subBinY).
arg(ccd_pixel_width).
arg(ccd_pixel_height)
351 .
arg(focalMm).
arg(calibrationAngle).
arg(calibrationAngleRA)
352 .
arg(calibrationAngleDEC).
arg(raPulseMsPerArcsecond)
353 .
arg(decPulseMsPerArcsecond).
arg(calibrationDecSwap ? 1 : 0)
362 if (!ref.startsWith(
id))
return false;
363 *result = ref.mid(
id.size()).toString();
370 if (!ref.startsWith(
id))
return false;
371 *result = ref.mid(
id.size()).toDouble(&ok);
378 if (!ref.startsWith(
id))
return false;
379 *result = ref.mid(
id.size()).
toInt(&ok);
384bool Calibration::restore(
const QString &encoding)
387 if (items.size() != 17)
return false;
389 if (items[i] !=
"Cal v1.0")
return false;
390 if (!
parseInt(items[++i],
"bx=", &subBinX))
return false;
391 if (!
parseInt(items[++i],
"by=", &subBinY))
return false;
392 if (!
parseDouble(items[++i],
"pw=", &ccd_pixel_width))
return false;
393 if (!
parseDouble(items[++i],
"ph=", &ccd_pixel_height))
return false;
394 if (!
parseDouble(items[++i],
"fl=", &focalMm))
return false;
395 if (!
parseDouble(items[++i],
"ang=", &calibrationAngle))
return false;
396 setAngle(calibrationAngle);
397 if (!
parseDouble(items[++i],
"angR=", &calibrationAngleRA))
return false;
398 if (!
parseDouble(items[++i],
"angD=", &calibrationAngleDEC))
return false;
402 if (!
parseDouble(items[++i],
"ramspas=", &raPulseMsPerArcsecond))
413 if (!
parseDouble(items[++i],
"decmspas=", &decPulseMsPerArcsecond))
427 decSwap =
static_cast<bool>(
tempInt);
428 calibrationDecSwap = decSwap;
436 calibrationPierSide =
static_cast<ISD::Mount::PierSide
>(
tempInt);
439 if (items[++i] !=
"calEnd")
return false;
444void Calibration::save()
const
446 QString encoding = serialize();
447 Options::setSerializedCalibration(encoding);
461 constexpr double MAX_DEC = 60.0;
483 qCDebug(
KSTARS_EKOS_GUIDE) <<
QString(
"Corrected calibration RA rate. %1 --> %2. Calibration DEC %3 current DEC %4.")
496 if (!restore(encoding))
503 if (calibrationPierSide == ISD::Mount::PIER_UNKNOWN ||
506 qCDebug(
KSTARS_EKOS_GUIDE) <<
"Could not restore calibration--pier side unknown.";
511 raPulseMsPerArcsecond = correctRA(raPulseMsPerArcsecond, calibrationDEC, *
currentDeclination);
519 qCDebug(
KSTARS_EKOS_GUIDE) <<
"Restored calibration--same pier side. Encoding:" << encoding;
524 angle = angle + 180.0;
525 while (angle >= 360.0)
526 angle = angle - 360.0;
528 angle = angle + 360.0;
537 decSwap = !calibrationDecSwap;
540 <<
QString(
"Restored calibration--flipped angles. Angle %1, swap %2 ms/as: %3 %4. Encoding: %5")
541 .
arg(angle).
arg(decSwap ?
"T" :
"F").arg(raPulseMsPerArcsecond).arg(decPulseMsPerArcsecond).arg(encoding);
An angle, stored as degrees, but expressible in many ways.
static dms fromString(const QString &s, bool deg)
Static function to create a DMS object from a QString.
const QString toDMSString(const bool forceSign=false, const bool machineReadable=false, const bool highPrecision=false) const
const QString toHMSString(const bool machineReadable=false, const bool highPrecision=false) const
const double & Degrees() const
QDateTime currentDateTime()
QString arg(Args &&... args) const const
QString number(double n, char format, int precision)
QTextStream & dec(QTextStream &stream)