Instrument Neutral Distributed Interface INDI 2.2.5
scopesim_helper.h
Go to the documentation of this file.
1/*
2 * scopesim_helper.h
3 *
4 * Copyright 2020 Chris Rowland <[email protected]>
5 *
6 * helper classes for the telescope simulator
7 *
8 * The Angle structure defines an angle class that manages the wrap round
9 * 0 to 360 and handles arithmetic and logic across this boundary.
10 *
11 * The Axis class manages a simulated mount axis and handles moving, tracking, and guiding.
12 *
13 * The Alignment class handles the alignment, converting between the observed and instrument
14 * places, and allowing for the axis positions needed for a GEM mount.
15 *
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
29 * MA 02110-1301, USA.
30 *
31 *
32 */
33
35
36#pragma once
37
38#include <stdint.h>
39#include <sys/time.h>
40#include <cmath>
41
42#include <indicom.h>
43
44extern char device_str[64];
45
52class Angle
53{
54 private:
55 double angle; // position in degrees, range -180 to 0 to 180
56
62 static double range(double deg)
63 {
64 while (deg > 180.0) deg -= 360.0;
65 while (deg <= -180.0) deg += 360.0;
66 return deg;
67 }
68
69 static double hrstoDeg(double hrs)
70 {
71 return range(hrs * 15.0);
72 }
73
74 public:
76
78 {
79 angle = 0;
80 }
81
82 Angle(double value, ANGLE_UNITS type);
83
84 Angle(double degrees)
85 {
86 angle = range(degrees);
87 }
88
89 //virtual ~Angle() = default;
90
95 double Degrees()
96 {
97 return angle;
98 }
99
104 double Degrees360()
105 {
106 return (angle >= 0) ? angle : 360.0 + angle;
107 }
108
113 double Hours()
114 {
115 double h = angle / 15.0;
116 if (h < 0.0)
117 h = 24 + h;
118 return h;
119 }
124 double HoursHa()
125 {
126 return angle / 15.0;
127 }
128
133 double radians();
134
140 void setDegrees(double deg)
141 {
142 angle = range(deg);
143 }
144
149 void setHours(double hrs)
150 {
151 angle = hrstoDeg(hrs);
152 }
153
155 {
156 double total = a.Degrees() + this->Degrees();
157 return Angle(total);
158 }
159
161 {
162 return Angle(this->Degrees() - a.Degrees());
163 }
164
166 {
167 return range(this->angle - a.angle);
168 }
169
171 {
172 return Angle(-this->angle);
173 }
174
176 {
177 angle = range(angle + a.angle);
178 return *this;
179 }
180
181 Angle &operator += (const double d)
182 {
183 angle = range(angle + d);
184 return *this;
185 }
186
188 {
189 angle = range(angle - a.angle);
190 return *this;
191 }
192
193 Angle &operator-= (const double d)
194 {
195 angle = range(angle - d);
196 return *this;
197 }
198
200 {
201 return Angle(this->angle + a.angle);
202 }
203
204 Angle operator+ (const double &d)
205 {
206 return Angle(this->angle + d);
207 }
208
210 {
211 return Angle(this->angle - rhs.angle);
212 }
213
214 Angle operator- (const double &rhs)
215 {
216 return Angle(this->angle - rhs);
217 }
218
226 Angle operator * (const double duration)
227 {
228 return Angle(this->angle * duration);
229 }
230
231 bool operator== (const Angle &a);
232
233 bool operator!= (const Angle &a);
234
235 bool operator > (const Angle &a)
236 {
237 return difference(a) > 0;
238 }
239
240 bool operator < (const Angle &a)
241 {
242 return difference(a) < 0;
243 }
244 bool operator >= (const Angle &a)
245 {
246 return difference(a) >= 0;
247 }
248 bool operator <= (const Angle &a)
249 {
250 return difference(a) <= 0;
251 }
252};
253
255
266class Axis
267{
268 public:
273
274 Axis(const char * name)
275 {
276 axisName = name;
277 }
278
279 const char * axisName;
280
281 // sets position and target so does not cause a slew.
282 void setDegrees(double degrees);
283 void setHours(double hours);
284
285 Angle position; // current angle of the telescope position about axis
286
287 void StartSlew(Angle angle);
288
289 void Abort()
290 {
291 target = position;
292 mcRate = 0;
293 guideDuration = 0;
294 }
295
296 bool isSlewing = false;
297
299 {
300 return tracking;
301 }
302
303 void Tracking(bool enabled);
304
311 void TrackRate(AXIS_TRACK_RATE rate);
312
318
319 double getTrackingRateDegSec();
320
325
331 void StartGuide(double rate, uint32_t durationMs);
332
334 {
335 return guideDuration > 0;
336 }
337
338 int mcRate = 0; // int -4 to 4 sets move rate, zero is stopped
339
340 void update(); // called about once a second to update the position and mode
341
342 // needed for debug MACROS
343 const char *getDeviceName()
344 {
345 return device_str;
346 }
347
348 private:
349 Angle target; // target axis position
350
351 struct timeval lastTime
352 {
353 0, 0
354 };
355
356 bool tracking = false; // this allows the tracking state and rate to be set independently
357
358 AXIS_TRACK_RATE trackingRate { AXIS_TRACK_RATE::OFF };
359
360 Angle rotateCentre { 90.0 };
361
362 double guideDuration = 0;
363 Angle guideRateDegSec;
364
365 // rates are angles in degrees per second derived from the values in indicom.h
366 // which are in arcsec per second.
367
368 const Angle solarRate { TRACKRATE_SOLAR / 3600.0 };
369 const Angle siderealRate { TRACKRATE_SIDEREAL / 3600.0 };
370 const Angle lunarRate { TRACKRATE_LUNAR / 3600.0 };
371
372 Angle mcRates[5]
373 {
374 0,
375 siderealRate, // guide rate
376 0.5, // fine rate
377 2.5, // center rate
378 6.0, // goto rate
379 };
380};
381
410{
411 public:
413
415
418
420
428 void mountToApparentRaDec(Angle primary, Angle secondary, Angle * apparentRa, Angle* apparentDec);
429
430
431 void apparentRaDecToMount(Angle apparentRa, Angle apparentDec, Angle *primary, Angle *secondary);
432
433
443 void setCorrections(double ih, double id, double ch, double np, double ma, double me);
444 void setCorrections(double *coeffs)
445 {
446 setCorrections(coeffs[0], coeffs[1], coeffs[2], coeffs[3], coeffs[4], coeffs[5]);
447 }
448
449 void setFlipHourAngle(double deg)
450 {
451 flipHourAngle = deg;
452 }
453
454 // needed for debug MACROS
455 const char *getDeviceName()
456 {
457 return device_str;
458 }
459
460 double ih()
461 {
462 return IH;
463 }
464 double id()
465 {
466 return ID;
467 }
468 double np()
469 {
470 return NP;
471 }
472 double ch()
473 {
474 return CH;
475 }
476 double ma()
477 {
478 return MA;
479 }
480 double me()
481 {
482 return ME;
483 }
484
485 void instrumentToObserved(Angle instrumentHa, Angle instrumentDec, Angle *observedHa, Angle *observedDec);
486
487 void observedToInstrument(Angle observedHa, Angle observedDec, Angle * instrumentHa, Angle * instrumentDec);
488
489
497 void mountToApparentHaDec(Angle primary, Angle secondary, Angle *apparentHa, Angle *apparentDec);
498
503 void mountToInstrumentHaDec(Angle primary, Angle secondary, Angle *instrumentHa, Angle *instrumentDec);
504
505 // Inverse of mountToInstrumentHaDec: converts raw instrument HA/Dec (no Wallace) to
506 // axis positions. Uses the same flipHourAngle condition as apparentHaDecToMount so
507 // it selects the correct pier side for a Goto without applying pointing corrections.
508 void instrumentHaDecToMount(Angle instrumentHa, Angle instrumentDec, Angle *primary, Angle *secondary);
509
517 void apparentHaDecToMount(Angle apparentHa, Angle apparentDec, Angle *primary, Angle *secondary);
518
519 Angle lst(); // returns the current LST as an angle
520 private:
521
522
523
524
525 Angle flipHourAngle = 0;
526
544 void correction(Angle instrumentHa, Angle instrumentDec, Angle *correctionHa, Angle *correctionDec);
545
546 // mount model, these angles are in degrees
547 // the angles are small so use double to avoid
548 // loads of conversions
552 double IH = 0;
556 double ID = 0;
560 double CH = 0;
564 double NP = 0;
568 double MA = 0;
572 double ME = 0;
573
574
575 // corrections done using direction cosines and rotations after Taki
576 //apparentHaDecToMount(Vector HaDec, Vector * mount);
577};
578
588{
589 public:
595 {
596 L = M = N = 0;
597 }
598
605 Vector(double l, double m, double n);
606
613
615 {
616 return L * L + M * M + N * N;
617 }
618
619 double length()
620 {
621 return std::sqrt(lengthSquared());
622 }
623
624 void normalise();
625
630 Angle primary();
631
637
642 Vector rotateX(Angle angle);
643
648 Vector rotateY(Angle angle);
649
654 Vector rotateZ(Angle angle);
655
656 double l()
657 {
658 return L;
659 }
660 double m()
661 {
662 return M;
663 }
664 double n()
665 {
666 return N;
667 }
668
669 protected:
670 double L; // in the Ha 0 direction, pointing at Ha 0, Dec 0, X direction
671 double M; // in the Ha 6 direction, pointing at Ha 6h, Dec 0, Y direction
672 double N; // toward the pole, Dec 0, Z direction
673};
The Alignment class This converts between the mount axis angles and the sky hour angle and declinatio...
void setCorrections(double ih, double id, double ch, double np, double ma, double me)
setCorrections set the values of the six corrections
void instrumentHaDecToMount(Angle instrumentHa, Angle instrumentDec, Angle *primary, Angle *secondary)
void apparentRaDecToMount(Angle apparentRa, Angle apparentDec, Angle *primary, Angle *secondary)
void mountToApparentHaDec(Angle primary, Angle secondary, Angle *apparentHa, Angle *apparentDec)
mountToApparentHaDec: convert mount position to apparent Ha, Dec
const char * getDeviceName()
void apparentHaDecToMount(Angle apparentHa, Angle apparentDec, Angle *primary, Angle *secondary)
apparentHaDecToMount
void observedToInstrument(Angle observedHa, Angle observedDec, Angle *instrumentHa, Angle *instrumentDec)
void mountToApparentRaDec(Angle primary, Angle secondary, Angle *apparentRa, Angle *apparentDec)
mountToApparentRaDec: convert mount position to apparent Ra, Dec
void instrumentToObserved(Angle instrumentHa, Angle instrumentDec, Angle *observedHa, Angle *observedDec)
void setFlipHourAngle(double deg)
void setCorrections(double *coeffs)
MOUNT_TYPE mountType
void mountToInstrumentHaDec(Angle primary, Angle secondary, Angle *instrumentHa, Angle *instrumentDec)
mountToInstrumentHaDec: convert mount axis positions to instrument (encoder) HA/Dec without applying ...
The Angle class This class implements an angle type. This holds an angle that is always in the range ...
double Degrees360()
Degrees360.
bool operator<=(const Angle &a)
double difference(Angle a)
Angle(double degrees)
double radians()
radians
Angle add(Angle a)
bool operator==(const Angle &a)
void setHours(double hrs)
setHours set the angle
double Hours()
Hours.
Angle & operator+=(const Angle &a)
void setDegrees(double deg)
setDegrees set the angle in degrees
bool operator>(const Angle &a)
bool operator!=(const Angle &a)
Angle & operator-=(const Angle &a)
Angle subtract(Angle a)
double HoursHa()
HoursHa.
bool operator>=(const Angle &a)
bool operator<(const Angle &a)
double Degrees()
Degrees.
Angle operator-()
Angle operator*(const double duration)
operator * multiplies the angle by a double, used to manage tracking and slewing
Angle operator+(const Angle &a)
The Axis class Implements a generic Axis which can be used for equatorial or AltAz mounts for both ax...
Angle TrackingRateDegSec
TrackingRateDegSec.
bool isSlewing
const char * axisName
void setDegrees(double degrees)
const char * getDeviceName()
void StartGuide(double rate, uint32_t durationMs)
StartGuide start guiding.
void Abort()
void Tracking(bool enabled)
AXIS_TRACK_RATE TrackRate()
TrackRate returns the AXIS_TRACK_RATE property.
void StartSlew(Angle angle)
void update()
Angle position
double getTrackingRateDegSec()
bool isTracking()
bool IsGuiding()
AXIS_TRACK_RATE
The AXIS_TRACK_RATE enum defines the common track rates.
void setHours(double hours)
Axis(const char *name)
The Vector class This implements the Directional Cosine used by Taki in his Matrix method....
double n()
Vector rotateY(Angle angle)
rotateY rotates this vector through angle about the Y axis
Vector rotateX(Angle angle)
rotateX rotates this vector through angle about the X axis
double lengthSquared()
double length()
Vector()
Vector creates an empty vector.
Vector rotateZ(Angle angle)
rotateZ rotates this vector through angle about the Z axis
void normalise()
Angle secondary()
secondary returns the secondary angle (dec, altitude) from this vector
double l()
Angle primary()
primary returns the primary angle (Ra, Ha, Azimuth) from this vector
double m()
Implementations for common driver routines.
#define TRACKRATE_SOLAR
Definition indimacros.h:45
#define TRACKRATE_SIDEREAL
Definition indimacros.h:39
#define TRACKRATE_LUNAR
Definition indimacros.h:48
uint16_t type
Definition pwc-ioctl.h:0
char device_str[64]
The transformations are based on the paper "Matrix Method for Coordinates Transformation" written by ...