Instrument Neutral Distributed Interface INDI  2.0.2
scopesim_helper.h
Go to the documentation of this file.
1 /*
2  * scopesim_helper.h
3  *
4  * Copyright 2020 Chris Rowland <chris.rowland@cherryfield.me.uk>
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 
34 #pragma once
35 
36 #include <stdint.h>
37 #include <sys/time.h>
38 #include <cmath>
39 
40 #include <indicom.h>
41 
42 static char device_str[64] = "Telescope Simulator";
43 
50 class Angle
51 {
52  private:
53  double angle; // position in degrees, range -180 to 0 to 180
54 
60  static double range(double deg)
61  {
62  while (deg > 180.0) deg -= 360.0;
63  while (deg <= -180.0) deg += 360.0;
64  return deg;
65  }
66 
67  static double hrstoDeg(double hrs)
68  {
69  return range(hrs * 15.0);
70  }
71 
72  public:
74 
76  {
77  angle = 0;
78  }
79 
80  Angle(double value, ANGLE_UNITS type);
81 
82  Angle(double degrees)
83  {
84  angle = range(degrees);
85  }
86 
87  //virtual ~Angle() = default;
88 
93  double Degrees()
94  {
95  return angle;
96  }
97 
102  double Degrees360()
103  {
104  return (angle >= 0) ? angle : 360.0 + angle;
105  }
106 
111  double Hours()
112  {
113  double h = angle / 15.0;
114  if (h < 0.0)
115  h = 24 + h;
116  return h;
117  }
122  double HoursHa()
123  {
124  return angle / 15.0;
125  }
126 
131  double radians();
132 
138  void setDegrees(double deg)
139  {
140  angle = range(deg);
141  }
142 
147  void setHours(double hrs)
148  {
149  angle = hrstoDeg(hrs);
150  }
151 
153  {
154  double total = a.Degrees() + this->Degrees();
155  return Angle(total);
156  }
157 
159  {
160  return Angle(this->Degrees() - a.Degrees());
161  }
162 
163  double difference(Angle a)
164  {
165  return range(this->angle - a.angle);
166  }
167 
169  {
170  return Angle(-this->angle);
171  }
172 
174  {
175  angle = range(angle + a.angle);
176  return *this;
177  }
178 
179  Angle &operator += (const double d)
180  {
181  angle = range(angle + d);
182  return *this;
183  }
184 
186  {
187  angle = range(angle - a.angle);
188  return *this;
189  }
190 
191  Angle &operator-= (const double d)
192  {
193  angle = range(angle - d);
194  return *this;
195  }
196 
198  {
199  return Angle(this->angle + a.angle);
200  }
201 
202  Angle operator+ (const double &d)
203  {
204  return Angle(this->angle + d);
205  }
206 
207  Angle operator- (const Angle &rhs)
208  {
209  return Angle(this->angle - rhs.angle);
210  }
211 
212  Angle operator- (const double &rhs)
213  {
214  return Angle(this->angle - rhs);
215  }
216 
224  Angle operator * (const double duration)
225  {
226  return Angle(this->angle * duration);
227  }
228 
229  bool operator== (const Angle &a);
230 
231  bool operator!= (const Angle &a);
232 
233  bool operator > (const Angle &a)
234  {
235  return difference(a) > 0;
236  }
237 
238  bool operator < (const Angle &a)
239  {
240  return difference(a) < 0;
241  }
242  bool operator >= (const Angle &a)
243  {
244  return difference(a) >= 0;
245  }
246  bool operator <= (const Angle &a)
247  {
248  return difference(a) <= 0;
249  }
250 };
251 
253 
261 class Axis
262 {
263  public:
268 
269  Axis(const char * name)
270  {
271  axisName = name;
272  }
273 
274  const char * axisName;
275 
276  // sets position and target so does not cause a slew.
277  void setDegrees(double degrees);
278  void setHours(double hours);
279 
280  Angle position; // current axis position
281 
282  void StartSlew(Angle angle);
283 
284  void Abort()
285  {
286  target = position;
287  mcRate = 0;
288  guideDuration = 0;
289  }
290 
291  bool isSlewing;
292 
293  bool isTracking()
294  {
295  return tracking;
296  }
297 
298  void Tracking(bool enabled);
299 
306  void TrackRate(AXIS_TRACK_RATE rate);
307 
313 
318 
324  void StartGuide(double rate, uint32_t durationMs);
325 
326  bool IsGuiding()
327  {
328  return guideDuration > 0;
329  }
330 
331  int mcRate; // int -4 to 4 sets move rate, zero is stopped
332 
333  void update(); // called about once a second to update the position and mode
334 
335  // needed for debug MACROS
336  const char *getDeviceName()
337  {
338  return device_str;
339  }
340 
341  private:
342  Angle target; // target axis position
343 
344  struct timeval lastTime
345  {
346  0, 0
347  };
348 
349  bool tracking; // this allows the tracking state and rate to be set independently
350 
351  AXIS_TRACK_RATE trackingRate { AXIS_TRACK_RATE::OFF };
352 
353  Angle rotateCentre { 90.0 };
354 
355  double guideDuration;
356  Angle guideRateDegSec;
357 
358  // rates are angles in degrees per second derived from the values in indicom.h
359  // which are in arcsec per second.
360 
361  const Angle solarRate { TRACKRATE_SOLAR / 3600.0 };
362  const Angle siderealRate { TRACKRATE_SIDEREAL / 3600.0 };
363  const Angle lunarRate { TRACKRATE_LUNAR / 3600.0 };
364 
365  Angle mcRates[5]
366  {
367  0,
368  siderealRate, // guide rate
369  0.5, // fine rate
370  2.5, // center rate
371  6.0, // goto rate
372  };
373 };
374 
403 {
404  public:
406 
408 
411 
413 
421  void mountToApparentRaDec(Angle primary, Angle secondary, Angle * apparentRa, Angle* apparentDec);
422 
423 
424  void apparentRaDecToMount(Angle apparentRa, Angle apparentDec, Angle *primary, Angle *secondary);
425 
426 
436  void setCorrections(double ih, double id, double ch, double np, double ma, double me);
437 
438  void setFlipHourAngle(double deg)
439  {
440  flipHourAngle = deg;
441  }
442 
443  // needed for debug MACROS
444  const char *getDeviceName()
445  {
446  return device_str;
447  }
448 
449  double ih()
450  {
451  return IH;
452  }
453  double id()
454  {
455  return ID;
456  }
457  double np()
458  {
459  return NP;
460  }
461  double ch()
462  {
463  return CH;
464  }
465  double ma()
466  {
467  return MA;
468  }
469  double me()
470  {
471  return ME;
472  }
473 
474  void instrumentToObserved(Angle instrumentHa, Angle instrumentDec, Angle *observedHa, Angle *observedDec);
475 
476  void observedToInstrument(Angle observedHa, Angle observedDec, Angle * instrumentHa, Angle * instrumentDec);
477 
478 
486  void mountToApparentHaDec(Angle primary, Angle secondary, Angle *apparentHa, Angle *apparentDec);
487 
495  void apparentHaDecToMount(Angle apparentHa, Angle apparentDec, Angle *primary, Angle *secondary);
496 
497  Angle lst(); // returns the current LST as an angle
498  private:
499 
500 
501 
502 
503  Angle flipHourAngle = 0;
504 
522  void correction(Angle instrumentHa, Angle instrumentDec, Angle *correctionHa, Angle *correctionDec);
523 
524  // mount model, these angles are in degrees
525  // the angles are small so use double to avoid
526  // loads of conversions
530  double IH = 0;
534  double ID = 0;
538  double CH = 0;
542  double NP = 0;
546  double MA = 0;
550  double ME = 0;
551 
552 
553  // corrections done using direction cosines and rotations after Taki
554  //apparentHaDecToMount(Vector HaDec, Vector * mount);
555 };
556 
565 class Vector
566 {
567  public:
573  {
574  L = M = N = 0;
575  }
576 
583  Vector(double l, double m, double n);
584 
591 
592  double lengthSquared()
593  {
594  return L * L + M * M + N * N;
595  }
596 
597  double length()
598  {
599  return std::sqrt(lengthSquared());
600  }
601 
602  void normalise();
603 
608  Angle primary();
609 
614  Angle secondary();
615 
620  Vector rotateX(Angle angle);
621 
626  Vector rotateY(Angle angle);
627 
632  Vector rotateZ(Angle angle);
633 
634  double l()
635  {
636  return L;
637  }
638  double m()
639  {
640  return M;
641  }
642  double n()
643  {
644  return N;
645  }
646 
647  protected:
648  double L; // in the Ha 0 direction, pointing at Ha 0, Dec 0, X direction
649  double M; // in the Ha 6 direction, pointing at Ha 6h, Dec 0, Y direction
650  double N; // toward the pole, Dec 0, Z direction
651 };
The Alignment class This converts between the mount axis angles and the sky hour angle and declinatio...
double ch()
void setCorrections(double ih, double id, double ch, double np, double ma, double me)
setCorrections set the values of the six corrections
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
double ih()
double np()
double id()
void apparentHaDecToMount(Angle apparentHa, Angle apparentDec, Angle *primary, Angle *secondary)
apparentHaDecToMount
double ma()
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)
double me()
const char * getDeviceName()
MOUNT_TYPE mountType
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.
void setDegrees(double deg)
setDegrees set the angle in degrees
bool operator>(const Angle &a)
bool 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 Angle &a)
Angle & operator+=(const Angle &a)
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)
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
const char * getDeviceName()
bool isTracking()
bool IsGuiding()
AXIS_TRACK_RATE
The AXIS_TRACK_RATE enum defines the common track rates.
int mcRate
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
double M
double L
double N
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: indicom.h:61
#define TRACKRATE_SIDEREAL
Definition: indicom.h:55
#define TRACKRATE_LUNAR
Definition: indicom.h:64
const char * OFF
__le16 type
Definition: pwc-ioctl.h:0