Kstars

gmath.cpp
1 /*
2  SPDX-FileCopyrightText: 2012 Andrew Stepanenko
3 
4  Modified by Jasem Mutlaq <[email protected]> for KStars:
5  SPDX-FileCopyrightText: 2012 Jasem Mutlaq <[email protected]>
6 
7  SPDX-License-Identifier: GPL-2.0-or-later
8 */
9 
10 #include "gmath.h"
11 
12 #include "Options.h"
13 #include "fitsviewer/fitsdata.h"
14 #include "fitsviewer/fitsview.h"
15 #include "auxiliary/kspaths.h"
16 #include "ekos_guide_debug.h"
17 #include "ekos/auxiliary/stellarsolverprofileeditor.h"
18 #include "guidealgorithms.h"
19 
20 #include <QVector3D>
21 #include <cmath>
22 #include <set>
23 
24 // Qt version calming
25 #include <qtendl.h>
26 
27 GuiderUtils::Vector cgmath::findLocalStarPosition(QSharedPointer<FITSData> &imageData,
28  QSharedPointer<GuideView> &guideView, bool firstFrame)
29 {
30  GuiderUtils::Vector position;
31  if (usingSEPMultiStar())
32  {
33  QRect trackingBox = guideView->getTrackingBox();
34  position = guideStars.findGuideStar(imageData, trackingBox, guideView, firstFrame);
35 
36  }
37  else
38  position = GuideAlgorithms::findLocalStarPosition(
39  imageData, algorithm, video_width, video_height,
40  guideView->getTrackingBox());
41 
42  if (position.x == -1 || position.y == -1)
43  setLostStar(true);
44  return position;
45 }
46 
47 
48 cgmath::cgmath() : QObject()
49 {
50  // sky coord. system vars.
51  starPosition = GuiderUtils::Vector(0);
52  targetPosition = GuiderUtils::Vector(0);
53 
54  // processing
55  in_params.reset();
56  out_params.reset();
57  driftUpto[GUIDE_RA] = driftUpto[GUIDE_DEC] = 0;
58  drift[GUIDE_RA] = new double[CIRCULAR_BUFFER_SIZE];
59  drift[GUIDE_DEC] = new double[CIRCULAR_BUFFER_SIZE];
60  memset(drift[GUIDE_RA], 0, sizeof(double) * CIRCULAR_BUFFER_SIZE);
61  memset(drift[GUIDE_DEC], 0, sizeof(double) * CIRCULAR_BUFFER_SIZE);
62  drift_integral[GUIDE_RA] = drift_integral[GUIDE_DEC] = 0;
63 
64  logFile.setFileName(QDir(KSPaths::writableLocation(QStandardPaths::AppLocalDataLocation)).filePath("guide_log.txt"));
65  gpg.reset(new GPG());
66 }
67 
68 cgmath::~cgmath()
69 {
70  delete[] drift[GUIDE_RA];
71  delete[] drift[GUIDE_DEC];
72 }
73 
74 bool cgmath::setVideoParameters(int vid_wd, int vid_ht, int binX, int binY)
75 {
76  if (vid_wd <= 0 || vid_ht <= 0)
77  return false;
78 
79  video_width = vid_wd / binX;
80  video_height = vid_ht / binY;
81 
82  calibration.setBinningUsed(binX, binY);
83  guideStars.setCalibration(calibration);
84 
85  return true;
86 }
87 
88 bool cgmath::setGuiderParameters(double ccd_pix_wd, double ccd_pix_ht, double guider_aperture, double guider_focal)
89 {
90  if (ccd_pix_wd < 0)
91  ccd_pix_wd = 0;
92  if (ccd_pix_ht < 0)
93  ccd_pix_ht = 0;
94  if (guider_focal <= 0)
95  guider_focal = 1;
96 
97  aperture = guider_aperture;
98  guideStars.setCalibration(calibration);
99 
100  return true;
101 }
102 
103 // This logging will be removed in favor of guidelog.h.
104 void cgmath::createGuideLog()
105 {
106  logFile.close();
107  logFile.open(QIODevice::WriteOnly | QIODevice::Text);
108  QTextStream out(&logFile);
109 
110  out << "Guiding rate,x15 arcsec/sec: " << Qt::endl;
111  out << "Focal,mm: " << calibration.getFocalLength() << Qt::endl;
112  out << "Aperture,mm: " << aperture << Qt::endl;
113  out << "F/D: " << calibration.getFocalLength() / aperture << Qt::endl;
114  out << "Frame #, Time Elapsed (ms), RA Error (arcsec), RA Correction (ms), RA Correction Direction, DEC Error "
115  "(arcsec), DEC Correction (ms), DEC Correction Direction"
116  << Qt::endl;
117 
118  logTime.restart();
119 }
120 
121 bool cgmath::setTargetPosition(double x, double y)
122 {
123  // check frame ranges
124  if (x < 0)
125  x = 0;
126  if (y < 0)
127  y = 0;
128  if (x >= (double)video_width - 1)
129  x = (double)video_width - 1;
130  if (y >= (double)video_height - 1)
131  y = (double)video_height - 1;
132 
133  targetPosition = GuiderUtils::Vector(x, y, 0);
134 
135  guideStars.setCalibration(calibration);
136 
137  return true;
138 }
139 
140 bool cgmath::getTargetPosition(double *x, double *y) const
141 {
142  *x = targetPosition.x;
143  *y = targetPosition.y;
144  return true;
145 }
146 
147 int cgmath::getAlgorithmIndex(void) const
148 {
149  return algorithm;
150 }
151 
152 void cgmath::getStarScreenPosition(double *dx, double *dy) const
153 {
154  *dx = starPosition.x;
155  *dy = starPosition.y;
156 }
157 
158 bool cgmath::reset()
159 {
160  iterationCounter = 0;
161  driftUpto[GUIDE_RA] = driftUpto[GUIDE_DEC] = 0;
162  drift_integral[GUIDE_RA] = drift_integral[GUIDE_DEC] = 0;
163  out_params.reset();
164 
165  memset(drift[GUIDE_RA], 0, sizeof(double) * CIRCULAR_BUFFER_SIZE);
166  memset(drift[GUIDE_DEC], 0, sizeof(double) * CIRCULAR_BUFFER_SIZE);
167 
168  return true;
169 }
170 
171 void cgmath::setAlgorithmIndex(int algorithmIndex)
172 {
173  if (algorithmIndex < 0 || algorithmIndex > SEP_MULTISTAR)
174  return;
175 
176  algorithm = algorithmIndex;
177 }
178 
179 bool cgmath::usingSEPMultiStar() const
180 {
181  return algorithm == SEP_MULTISTAR;
182 }
183 
184 void cgmath::updateCircularBuffers(void)
185 {
186  iterationCounter++;
187 
188  driftUpto[GUIDE_RA]++;
189  driftUpto[GUIDE_DEC]++;
190  if (driftUpto[GUIDE_RA] >= CIRCULAR_BUFFER_SIZE)
191  driftUpto[GUIDE_RA] = 0;
192  if (driftUpto[GUIDE_DEC] >= CIRCULAR_BUFFER_SIZE)
193  driftUpto[GUIDE_DEC] = 0;
194 }
195 
196 //-------------------- Processing ---------------------------
197 void cgmath::start()
198 {
199  iterationCounter = 0;
200  driftUpto[GUIDE_RA] = driftUpto[GUIDE_DEC] = 0;
201  drift_integral[GUIDE_RA] = drift_integral[GUIDE_DEC] = 0;
202  out_params.reset();
203 
204  memset(drift[GUIDE_RA], 0, sizeof(double) * CIRCULAR_BUFFER_SIZE);
205  memset(drift[GUIDE_DEC], 0, sizeof(double) * CIRCULAR_BUFFER_SIZE);
206 
207  if (calibration.getFocalLength() > 0 && aperture > 0)
208  createGuideLog();
209 
210  gpg->reset();
211 }
212 
213 void cgmath::abort()
214 {
215  guideStars.reset();
216 }
217 
218 void cgmath::suspend(bool mode)
219 {
220  suspended = mode;
221 }
222 
223 bool cgmath::isSuspended() const
224 {
225  return suspended;
226 }
227 
228 bool cgmath::isStarLost() const
229 {
230  return lost_star;
231 }
232 
233 void cgmath::setLostStar(bool is_lost)
234 {
235  lost_star = is_lost;
236 }
237 
238 namespace
239 {
240 QString axisStr(int raDEC)
241 {
242  if (raDEC == GUIDE_RA)
243  return "RA";
244  else if (raDEC == GUIDE_DEC)
245  return "DEC";
246  else
247  return "???";
248 }
249 
250 const QString directionStr(GuideDirection dir)
251 {
252  switch (dir)
253  {
254  case RA_DEC_DIR:
255  return "Decrease RA";
256  case RA_INC_DIR:
257  return "Increase RA";
258  case DEC_DEC_DIR:
259  return "Decrease DEC";
260  case DEC_INC_DIR:
261  return "Increase DEC";
262  default:
263  return "NO DIR";
264  }
265 }
266 } // namespace
267 
268 void cgmath::calculatePulses(Ekos::GuideState state)
269 {
270  qCDebug(KSTARS_EKOS_GUIDE) << "Processing Axes";
271 
272  const bool dithering = state == Ekos::GuideState::GUIDE_DITHERING;
273 
274  if (!dithering)
275  {
276  in_params.proportional_gain[0] = Options::rAProportionalGain();
277  in_params.proportional_gain[1] = Options::dECProportionalGain();
278 
279  in_params.integral_gain[0] = Options::rAIntegralGain();
280  in_params.integral_gain[1] = Options::dECIntegralGain();
281 
282  // Always pulse if were dithering.
283  in_params.enabled[0] = Options::rAGuideEnabled();
284  in_params.enabled[1] = Options::dECGuideEnabled();
285 
286  in_params.min_pulse_arcsec[0] = Options::rAMinimumPulseArcSec();
287  in_params.min_pulse_arcsec[1] = Options::dECMinimumPulseArcSec();
288 
289  in_params.max_pulse_arcsec[0] = Options::rAMaximumPulseArcSec();
290  in_params.max_pulse_arcsec[1] = Options::dECMaximumPulseArcSec();
291 
292  // RA W/E enable (but always pulse if dithering).
293  // East RA+ enabled?
294  in_params.enabled_axis1[0] = Options::eastRAGuideEnabled();
295  // West RA- enabled?
296  in_params.enabled_axis2[0] = Options::westRAGuideEnabled();
297 
298  // DEC N/S enable (but always pulse if dithering).
299  // North DEC+ enabled?
300  in_params.enabled_axis1[1] = Options::northDECGuideEnabled();
301  // South DEC- enabled?
302  in_params.enabled_axis2[1] = Options::southDECGuideEnabled();
303  }
304  else
305  {
306  // If we're dithering, enable all axes and use full pulses.
307  in_params.proportional_gain[0] = 1.0;
308  in_params.proportional_gain[1] = 1.0;
309  in_params.integral_gain[0] = 0.0;
310  in_params.integral_gain[1] = 0.0;
311  in_params.min_pulse_arcsec[0] = 0.0;
312  in_params.min_pulse_arcsec[1] = 0.0;
313  in_params.max_pulse_arcsec[0] = Options::rAMaximumPulseArcSec();
314  in_params.max_pulse_arcsec[1] = Options::dECMaximumPulseArcSec();
315  in_params.enabled[0] = true;
316  in_params.enabled[1] = true;
317  in_params.enabled_axis1[0] = true;
318  in_params.enabled_axis2[0] = true;
319  in_params.enabled_axis1[1] = true;
320  in_params.enabled_axis2[1] = true;
321  }
322 
323 
324  // process axes...
325  for (int k = GUIDE_RA; k <= GUIDE_DEC; k++)
326  {
327  // zero all out commands
328  GuideDirection pulseDirection = NO_DIR;
329  int pulseLength = 0; // milliseconds
330  GuideDirection dir;
331 
332  // Get the drift for this axis
333  const int idx = driftUpto[k];
334  const double arcsecDrift = drift[k][idx];
335 
336  const double pulseConverter = (k == GUIDE_RA) ?
337  calibration.raPulseMillisecondsPerArcsecond() :
338  calibration.decPulseMillisecondsPerArcsecond();
339  const double maxPulseMilliseconds = in_params.max_pulse_arcsec[k] * pulseConverter;
340 
341  // Compute the average drift in the recent past for the integral control term.
342  drift_integral[k] = 0;
343  for (int i = 0; i < CIRCULAR_BUFFER_SIZE; ++i)
344  drift_integral[k] += drift[k][i];
345  drift_integral[k] /= (double)CIRCULAR_BUFFER_SIZE;
346 
347  qCDebug(KSTARS_EKOS_GUIDE) << "drift[" << axisStr(k) << "] = " << arcsecDrift
348  << " integral[" << axisStr(k) << "] = " << drift_integral[k];
349 
350  // GPG pulse computation
351  bool useGPG = !dithering && Options::gPGEnabled() && (k == GUIDE_RA) && in_params.enabled[k];
352  if (useGPG && gpg->computePulse(arcsecDrift,
353  usingSEPMultiStar() ? &guideStars : nullptr, &pulseLength, &dir, calibration))
354  {
355  pulseDirection = dir;
356  pulseLength = std::min(pulseLength, static_cast<int>(maxPulseMilliseconds + 0.5));
357  }
358  else
359  {
360  // This is the main non-GPG guide-pulse computation.
361  // Traditionally it was hardwired so that proportional_gain=133 was about a control gain of 1.0
362  // This is now in the 0.0 - 1.0 range, and multiplies the calibrated mount performance.
363 
364  const double arcsecPerMsPulse = k == GUIDE_RA ? calibration.raPulseMillisecondsPerArcsecond() :
365  calibration.decPulseMillisecondsPerArcsecond();
366  const double proportionalResponse = arcsecDrift * in_params.proportional_gain[k] * arcsecPerMsPulse;
367  const double integralResponse = drift_integral[k] * in_params.integral_gain[k] * arcsecPerMsPulse;
368  pulseLength = std::min(fabs(proportionalResponse + integralResponse), maxPulseMilliseconds);
369 
370  // calc direction
371  // We do not send pulse if direction is disabled completely, or if direction in a specific axis (e.g. N or S) is disabled
372  if (!in_params.enabled[k] || // This axis not enabled
373  // Positive direction of this axis not enabled.
374  (arcsecDrift > 0 && !in_params.enabled_axis1[k]) ||
375  // Negative direction of this axis not enabled.
376  (arcsecDrift < 0 && !in_params.enabled_axis2[k]))
377  {
378  pulseDirection = NO_DIR;
379  pulseLength = 0;
380  }
381  else
382  {
383  // Check the min pulse value, and assign the direction.
384  const double pulseArcSec = pulseConverter > 0 ? pulseLength / pulseConverter : 0;
385  if (pulseArcSec >= in_params.min_pulse_arcsec[k])
386  {
387  if (k == GUIDE_RA)
388  pulseDirection = arcsecDrift > 0 ? RA_DEC_DIR : RA_INC_DIR;
389  else
390  pulseDirection = arcsecDrift > 0 ? DEC_INC_DIR : DEC_DEC_DIR; // GUIDE_DEC.
391  }
392  else
393  pulseDirection = NO_DIR;
394  }
395 
396  }
397  qCDebug(KSTARS_EKOS_GUIDE) << "pulse_length[" << axisStr(k) << "] = " << pulseLength
398  << "ms, Direction = " << directionStr(pulseDirection);
399 
400  out_params.pulse_dir[k] = pulseDirection;
401  out_params.pulse_length[k] = pulseLength;
402  out_params.delta[k] = arcsecDrift;
403  }
404 
405  if (Options::guideLogging())
406  {
407  QTextStream out(&logFile);
408  out << iterationCounter << "," << logTime.elapsed() << "," << out_params.delta[0] << "," << out_params.pulse_length[0] <<
409  ","
410  << directionStr(out_params.pulse_dir[0]) << "," << out_params.delta[1] << ","
411  << out_params.pulse_length[1] << "," << directionStr(out_params.pulse_dir[1]) << Qt::endl;
412  }
413 }
414 
415 void cgmath::performProcessing(Ekos::GuideState state, QSharedPointer<FITSData> &imageData,
416  QSharedPointer<GuideView> &guideView, GuideLog *logger)
417 {
418  if (suspended)
419  {
420  if (Options::gPGEnabled())
421  {
422  GuiderUtils::Vector guideStarPosition = findLocalStarPosition(imageData, guideView, false);
423  if (guideStarPosition.x != -1 && !std::isnan(guideStarPosition.x))
424  {
425  gpg->suspended(guideStarPosition, targetPosition,
426  usingSEPMultiStar() ? &guideStars : nullptr, calibration);
427  }
428  }
429  // do nothing if suspended
430  return;
431  }
432 
433  GuiderUtils::Vector starPositionArcSec, targetPositionArcSec;
434 
435  // find guiding star location in the image
436  starPosition = findLocalStarPosition(imageData, guideView, false);
437 
438  // If no star found, mark as lost star.
439  if (starPosition.x == -1 || std::isnan(starPosition.x))
440  {
441  setLostStar(true);
442  if (logger != nullptr && state == Ekos::GUIDE_GUIDING)
443  {
444  GuideLog::GuideData data;
445  data.code = GuideLog::GuideData::NO_STAR_FOUND;
446  data.type = GuideLog::GuideData::DROP;
447  logger->addGuideData(data);
448  }
449  return;
450  }
451  else
452  setLostStar(false);
453 
454  // Emit the detected star center
455  QVector3D starCenter(starPosition.x, starPosition.y, 0);
456  emit newStarPosition(starCenter, true);
457 
458  // If we're only calibrating, then we're done.
459  if (state == Ekos::GUIDE_CALIBRATING)
460  return;
461 
462  if (state == Ekos::GUIDE_GUIDING && (targetPosition.x <= 0.0 || targetPosition.y <= 0.0))
463  {
464  qCDebug(KSTARS_EKOS_GUIDE) << "Guiding with target 0.0 -- something's wrong!!!!!!!!!!!";
465  for (int k = GUIDE_RA; k <= GUIDE_DEC; k++)
466  {
467  out_params.pulse_dir[k] = NO_DIR;
468  out_params.pulse_length[k] = 0;
469  out_params.delta[k] = 0;
470  setLostStar(true);
471  }
472  return;
473  }
474  qCDebug(KSTARS_EKOS_GUIDE) << "################## BEGIN PROCESSING ##################";
475 
476  // translate star coords into sky coord. system
477 
478  // convert from pixels into arcsecs
479  starPositionArcSec = calibration.convertToArcseconds(starPosition);
480  targetPositionArcSec = calibration.convertToArcseconds(targetPosition);
481 
482  qCDebug(KSTARS_EKOS_GUIDE) << "Star X:" << starPosition.x << "Y:" << starPosition.y << "arcsecs: " <<
483  starPositionArcSec.x << starPositionArcSec.y;
484  qCDebug(KSTARS_EKOS_GUIDE) << "Reticle X:" << targetPosition.x << "Y:" << targetPosition.y << "arcsecs: " <<
485  targetPositionArcSec.x << targetPositionArcSec.y;
486 
487 
488  // Compute RA & DEC drift in arcseconds.
489  const GuiderUtils::Vector star_xy_arcsec_drift = starPositionArcSec - targetPositionArcSec;
490  const GuiderUtils::Vector star_drift = calibration.rotateToRaDec(star_xy_arcsec_drift);
491 
492  // both coords are ready for math processing
493  // put coord to drift list
494  // Note: if we're not guiding, these will be overwritten,
495  // as driftUpto is only incremented when guiding.
496  drift[GUIDE_RA][driftUpto[GUIDE_RA]] = star_drift.x;
497  drift[GUIDE_DEC][driftUpto[GUIDE_DEC]] = star_drift.y;
498 
499  qCDebug(KSTARS_EKOS_GUIDE) << "-------> AFTER ROTATION Diff RA: " << star_drift.x << " DEC: " << star_drift.y;
500 
501  if (state == Ekos::GUIDE_GUIDING && usingSEPMultiStar())
502  {
503  double multiStarRADrift, multiStarDECDrift;
504  if (guideStars.getDrift(sqrt(star_drift.x * star_drift.x + star_drift.y * star_drift.y),
505  targetPosition.x, targetPosition.y,
506  &multiStarRADrift, &multiStarDECDrift))
507  {
508  qCDebug(KSTARS_EKOS_GUIDE) << "-------> MultiStar: Diff RA: " << multiStarRADrift << " DEC: " << multiStarDECDrift;
509  drift[GUIDE_RA][driftUpto[GUIDE_RA]] = multiStarRADrift;
510  drift[GUIDE_DEC][driftUpto[GUIDE_DEC]] = multiStarDECDrift;
511  }
512  else
513  {
514  qCDebug(KSTARS_EKOS_GUIDE) << "-------> MultiStar: failed, fell back to guide star";
515  }
516  }
517 
518  // driftUpto will change when the circular buffer is updated,
519  // so save the values for logging.
520  const double raDrift = drift[GUIDE_RA][driftUpto[GUIDE_RA]];
521  const double decDrift = drift[GUIDE_DEC][driftUpto[GUIDE_DEC]];
522 
523  // make decision by axes
524  calculatePulses(state);
525 
526  if (state == Ekos::GUIDE_GUIDING)
527  {
528  calculateRmsError();
529  emitStats();
530  updateCircularBuffers();
531  }
532 
533  if (logger != nullptr)
534  {
535  GuideLog::GuideData data;
536  data.type = GuideLog::GuideData::MOUNT;
537  // These are distances in pixels.
538  // Note--these don't include the multistar algorithm, but the below ra/dec ones do.
539  data.dx = starPosition.x - targetPosition.x;
540  data.dy = starPosition.y - targetPosition.y;
541  // Above computes position - reticle. Should the reticle-position, so negate.
542  calibration.convertToPixels(-raDrift, -decDrift, &data.raDistance, &data.decDistance);
543 
544  const double raGuideFactor = out_params.pulse_dir[GUIDE_RA] == NO_DIR ?
545  0 : (out_params.pulse_dir[GUIDE_RA] == RA_DEC_DIR ? -1.0 : 1.0);
546  const double decGuideFactor = out_params.pulse_dir[GUIDE_DEC] == NO_DIR ?
547  0 : (out_params.pulse_dir[GUIDE_DEC] == DEC_INC_DIR ? -1.0 : 1.0);
548 
549  // Phd2LogViewer wants these in pixels instead of arcseconds, so normalizing them, but
550  // that will be wrong for non-square pixels. They should really accept arcsecond units.
551  data.raGuideDistance = calibration.xPixelsPerArcsecond() * raGuideFactor * out_params.pulse_length[GUIDE_RA] /
552  calibration.raPulseMillisecondsPerArcsecond();
553  data.decGuideDistance = calibration.yPixelsPerArcsecond() * decGuideFactor * out_params.pulse_length[GUIDE_DEC] /
554  calibration.decPulseMillisecondsPerArcsecond();
555 
556  data.raDuration = out_params.pulse_dir[GUIDE_RA] == NO_DIR ? 0 : out_params.pulse_length[GUIDE_RA];
557  data.raDirection = out_params.pulse_dir[GUIDE_RA];
558  data.decDuration = out_params.pulse_dir[GUIDE_DEC] == NO_DIR ? 0 : out_params.pulse_length[GUIDE_DEC];
559  data.decDirection = out_params.pulse_dir[GUIDE_DEC];
560  data.code = GuideLog::GuideData::NO_ERRORS;
561  data.snr = guideStars.getGuideStarSNR();
562  data.mass = guideStars.getGuideStarMass();
563  // Add SNR and MASS from SEP stars.
564  logger->addGuideData(data);
565  }
566  qCDebug(KSTARS_EKOS_GUIDE) << "################## FINISH PROCESSING ##################";
567 }
568 
569 void cgmath::emitStats()
570 {
571  double pulseRA = 0;
572  if (out_params.pulse_dir[GUIDE_RA] == RA_DEC_DIR)
573  pulseRA = out_params.pulse_length[GUIDE_RA];
574  else if (out_params.pulse_dir[GUIDE_RA] == RA_INC_DIR)
575  pulseRA = -out_params.pulse_length[GUIDE_RA];
576  double pulseDEC = 0;
577  if (out_params.pulse_dir[GUIDE_DEC] == DEC_DEC_DIR)
578  pulseDEC = -out_params.pulse_length[GUIDE_DEC];
579  else if (out_params.pulse_dir[GUIDE_DEC] == DEC_INC_DIR)
580  pulseDEC = out_params.pulse_length[GUIDE_DEC];
581 
582  const bool hasGuidestars = usingSEPMultiStar();
583  const double snr = hasGuidestars ? guideStars.getGuideStarSNR() : 0;
584  const double skyBG = hasGuidestars ? guideStars.skybackground().mean : 0;
585  const int numStars = hasGuidestars ? guideStars.skybackground().starsDetected : 0; // wait for rob's release
586 
587  emit guideStats(-out_params.delta[GUIDE_RA], -out_params.delta[GUIDE_DEC],
588  pulseRA, pulseDEC, snr, skyBG, numStars);
589 }
590 
591 void cgmath::calculateRmsError(void)
592 {
593  if (!do_statistics)
594  return;
595 
596  if (iterationCounter == 0)
597  return;
598 
599  int count = std::min(iterationCounter, static_cast<unsigned int>(CIRCULAR_BUFFER_SIZE));
600  for (int k = GUIDE_RA; k <= GUIDE_DEC; k++)
601  {
602  double sqr_avg = 0;
603  for (int i = 0; i < count; ++i)
604  sqr_avg += drift[k][i] * drift[k][i];
605 
606  out_params.sigma[k] = sqrt(sqr_avg / (double)count);
607  }
608 }
609 
610 
611 QVector3D cgmath::selectGuideStar(const QSharedPointer<FITSData> &imageData)
612 {
613  return guideStars.selectGuideStar(imageData);
614 }
615 
616 double cgmath::getGuideStarSNR()
617 {
618  return guideStars.getGuideStarSNR();
619 }
620 
621 //---------------------------------------------------------------------------------------
622 cproc_in_params::cproc_in_params()
623 {
624  reset();
625 }
626 
627 void cproc_in_params::reset(void)
628 {
629  average = true;
630 
631  for (int k = GUIDE_RA; k <= GUIDE_DEC; k++)
632  {
633  enabled[k] = true;
634  integral_gain[k] = 0;
635  max_pulse_arcsec[k] = 5000;
636  min_pulse_arcsec[k] = 0;
637  }
638 }
639 
640 cproc_out_params::cproc_out_params()
641 {
642  reset();
643 }
644 
645 void cproc_out_params::reset(void)
646 {
647  for (int k = GUIDE_RA; k <= GUIDE_DEC; k++)
648  {
649  delta[k] = 0;
650  pulse_dir[k] = NO_DIR;
651  pulse_length[k] = 0;
652  sigma[k] = 0;
653  }
654 }
655 
QTextStream & endl(QTextStream &stream)
QCA_EXPORT Logger * logger()
KIOFILEWIDGETS_EXPORT QString dir(const QString &fileClass)
KGuiItem reset()
This file is part of the KDE documentation.
Documentation copyright © 1996-2022 The KDE developers.
Generated on Mon Aug 8 2022 04:13:21 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.