26 DBG_SIMULATOR(
INDI::
Logger::getInstance().addDebugLevel(
"Simulator Verbose",
"SIMULATOR"))
54 AxisStatusRA = AxisStatusDEC = STOPPED;
82 return (
const char *)
"Simple Telescope Simulator";
87 DEBUGF(DBG_SIMULATOR,
"Goto - Celestial reference frame target right ascension %lf(%lf) declination %lf",
92 char RAStr[32], DecStr[32];
97 DEBUG(DBG_SIMULATOR,
"Goto - tracking requested");
139 if ((
AltAz.altitude > 90.0) || (
AltAz.altitude < -90.0))
141 DEBUG(DBG_SIMULATOR,
"Goto - Altitude out of range");
147 if ((
AltAz.azimuth > 360.0) || (
AltAz.azimuth < -360.0))
149 DEBUG(DBG_SIMULATOR,
"Goto - Azimuth out of range");
154 if (
AltAz.azimuth < 0.0)
156 DEBUG(DBG_SIMULATOR,
"Goto - Azimuth negative");
160 DEBUGF(DBG_SIMULATOR,
"Goto - Scope reference frame target altitude %lf azimuth %lf",
AltAz.altitude,
163 GotoTargetMicrostepsDEC = int(
AltAz.altitude * MICROSTEPS_PER_DEGREE);
164 if (GotoTargetMicrostepsDEC == CurrentEncoderMicrostepsDEC)
165 AxisStatusDEC = STOPPED;
168 if (GotoTargetMicrostepsDEC > CurrentEncoderMicrostepsDEC)
169 AxisDirectionDEC = FORWARD;
171 AxisDirectionDEC = REVERSE;
172 AxisStatusDEC = SLEWING_TO;
174 GotoTargetMicrostepsRA = int(
AltAz.azimuth * MICROSTEPS_PER_DEGREE);
175 if (GotoTargetMicrostepsRA == CurrentEncoderMicrostepsRA)
176 AxisStatusRA = STOPPED;
179 if (GotoTargetMicrostepsRA > CurrentEncoderMicrostepsRA)
180 AxisDirectionRA = (GotoTargetMicrostepsRA - CurrentEncoderMicrostepsRA) < MICROSTEPS_PER_REVOLUTION / 2.0 ?
184 AxisDirectionRA = (CurrentEncoderMicrostepsRA - GotoTargetMicrostepsRA) < MICROSTEPS_PER_REVOLUTION / 2.0 ?
187 AxisStatusRA = SLEWING_TO;
212 char *formats[],
char *names[],
int n)
250bool ScopeSim::ISNewText(
const char *dev,
const char *name,
char *texts[],
char *names[],
int n)
264 AxisStatus axisStat = (command ==
MOTION_START) ? SLEWING : STOPPED;
266 AxisSlewRateDEC = DEFAULT_SLEW_RATE;
267 AxisDirectionDEC = axisDir;
268 AxisStatusDEC = axisStat;
275 AxisDirection axisDir = (dir ==
DIRECTION_WEST) ? FORWARD : REVERSE;
276 AxisStatus axisStat = (command ==
MOTION_START) ? SLEWING : STOPPED;
278 AxisSlewRateRA = DEFAULT_SLEW_RATE;
279 AxisDirectionRA = axisDir;
280 AxisStatusRA = axisStat;
289 double RightAscension, Declination;
293 DEBUG(DBG_SIMULATOR,
"ReadScopeStatus - TransformTelescopeToCelestial failed");
301 DEBUG(DBG_SIMULATOR,
"ReadScopeStatus - ApproximateMountAlignment ZENITH");
306 DEBUG(DBG_SIMULATOR,
"ReadScopeStatus - ApproximateMountAlignment NORTH_CELESTIAL_POLE");
315 DEBUG(DBG_SIMULATOR,
"ReadScopeStatus - ApproximateMountAlignment SOUTH_CELESTIAL_POLE");
331 DEBUGF(DBG_SIMULATOR,
"ReadScopeStatus - RA %lf hours DEC %lf degrees", RightAscension, Declination);
333 NewRaDec(RightAscension, Declination);
343 AltAz.altitude = double(CurrentEncoderMicrostepsDEC) / MICROSTEPS_PER_DEGREE;
344 AltAz.azimuth = double(CurrentEncoderMicrostepsRA) / MICROSTEPS_PER_DEGREE;
369 TraceThisTickCount++;
370 if (60 == TraceThisTickCount)
372 TraceThisTick =
true;
373 TraceThisTickCount = 0;
377 static struct timeval ltv
387 gettimeofday(&tv,
nullptr);
389 if (ltv.tv_sec == 0 && ltv.tv_usec == 0)
392 dt = tv.tv_sec - ltv.tv_sec + (tv.tv_usec - ltv.tv_usec) / 1e6;
396 long SlewSteps = dt * AxisSlewRateRA;
397 bool CompleteRevolution = SlewSteps >= MICROSTEPS_PER_REVOLUTION;
398 SlewSteps = SlewSteps % MICROSTEPS_PER_REVOLUTION;
400 switch (AxisStatusRA)
409 "TimerHit Slewing - RA Current Encoder %ld SlewSteps %ld Direction %d Target %ld Status %d",
410 CurrentEncoderMicrostepsRA, SlewSteps, AxisDirectionRA, GotoTargetMicrostepsRA, AxisStatusRA);
413 if (FORWARD == AxisDirectionRA)
414 CurrentEncoderMicrostepsRA += SlewSteps;
416 CurrentEncoderMicrostepsRA -= SlewSteps;
417 if (CurrentEncoderMicrostepsRA < 0)
418 CurrentEncoderMicrostepsRA += MICROSTEPS_PER_REVOLUTION;
419 else if (CurrentEncoderMicrostepsRA >= MICROSTEPS_PER_REVOLUTION)
420 CurrentEncoderMicrostepsRA -= MICROSTEPS_PER_REVOLUTION;
422 DEBUGF(DBG_SIMULATOR,
"TimerHit Slewing - RA New Encoder %d New Status %d", CurrentEncoderMicrostepsRA,
430 "TimerHit SlewingTo - RA Current Encoder %ld SlewSteps %ld Direction %d Target %ld Status %d",
431 CurrentEncoderMicrostepsRA, SlewSteps, AxisDirectionRA, GotoTargetMicrostepsRA, AxisStatusRA);
433 long OldEncoder = CurrentEncoderMicrostepsRA;
435 if (FORWARD == AxisDirectionRA)
436 CurrentEncoderMicrostepsRA += SlewSteps;
438 CurrentEncoderMicrostepsRA -= SlewSteps;
439 if (CurrentEncoderMicrostepsRA < 0)
440 CurrentEncoderMicrostepsRA += MICROSTEPS_PER_REVOLUTION;
441 else if (CurrentEncoderMicrostepsRA >= MICROSTEPS_PER_REVOLUTION)
442 CurrentEncoderMicrostepsRA -= MICROSTEPS_PER_REVOLUTION;
444 if (CompleteRevolution)
447 AxisStatusRA = STOPPED;
448 CurrentEncoderMicrostepsRA = GotoTargetMicrostepsRA;
452 bool FoundTarget =
false;
453 if (FORWARD == AxisDirectionRA)
455 if (CurrentEncoderMicrostepsRA < OldEncoder)
458 if ((GotoTargetMicrostepsRA >= OldEncoder) &&
459 (GotoTargetMicrostepsRA <= MICROSTEPS_PER_REVOLUTION))
461 else if ((GotoTargetMicrostepsRA >= 0) &&
462 (GotoTargetMicrostepsRA <= CurrentEncoderMicrostepsRA))
465 else if ((GotoTargetMicrostepsRA >= OldEncoder) &&
466 (GotoTargetMicrostepsRA <= CurrentEncoderMicrostepsRA))
471 if (CurrentEncoderMicrostepsRA > OldEncoder)
474 if ((GotoTargetMicrostepsRA >= 0) && (GotoTargetMicrostepsRA <= OldEncoder))
476 else if ((GotoTargetMicrostepsRA >= CurrentEncoderMicrostepsRA) &&
477 (GotoTargetMicrostepsRA <= MICROSTEPS_PER_REVOLUTION))
480 else if ((GotoTargetMicrostepsRA >= CurrentEncoderMicrostepsRA) &&
481 (GotoTargetMicrostepsRA <= OldEncoder))
486 AxisStatusRA = STOPPED;
487 CurrentEncoderMicrostepsRA = GotoTargetMicrostepsRA;
490 DEBUGF(DBG_SIMULATOR,
"TimerHit SlewingTo - RA New Encoder %d New Status %d", CurrentEncoderMicrostepsRA,
497 SlewSteps = dt * AxisSlewRateDEC;
499 switch (AxisStatusDEC)
508 "TimerHit Slewing - DEC Current Encoder %ld SlewSteps %d Direction %ld Target %ld Status %d",
509 CurrentEncoderMicrostepsDEC, SlewSteps, AxisDirectionDEC, GotoTargetMicrostepsDEC, AxisStatusDEC);
512 SlewSteps = SlewSteps % MICROSTEPS_PER_REVOLUTION;
513 if (FORWARD == AxisDirectionDEC)
514 CurrentEncoderMicrostepsDEC += SlewSteps;
516 CurrentEncoderMicrostepsDEC -= SlewSteps;
517 if (CurrentEncoderMicrostepsDEC > MAX_DEC)
519 CurrentEncoderMicrostepsDEC = MAX_DEC;
520 AxisStatusDEC = STOPPED;
521 DEBUG(DBG_SIMULATOR,
"TimerHit - DEC axis hit the buffers at MAX_DEC");
523 else if (CurrentEncoderMicrostepsDEC < MIN_DEC)
525 CurrentEncoderMicrostepsDEC = MIN_DEC;
526 AxisStatusDEC = STOPPED;
527 DEBUG(DBG_SIMULATOR,
"TimerHit - DEC axis hit the buffers at MIN_DEC");
530 DEBUGF(DBG_SIMULATOR,
"TimerHit Slewing - DEC New Encoder %d New Status %d", CurrentEncoderMicrostepsDEC,
538 "TimerHit SlewingTo - DEC Current Encoder %ld SlewSteps %d Direction %ld Target %ld Status %d",
539 CurrentEncoderMicrostepsDEC, SlewSteps, AxisDirectionDEC, GotoTargetMicrostepsDEC, AxisStatusDEC);
543 if (FORWARD == AxisDirectionDEC)
545 if (CurrentEncoderMicrostepsDEC <= GotoTargetMicrostepsDEC)
546 StepsToTarget = GotoTargetMicrostepsDEC - CurrentEncoderMicrostepsDEC;
548 StepsToTarget = CurrentEncoderMicrostepsDEC - GotoTargetMicrostepsDEC;
553 if (CurrentEncoderMicrostepsDEC >= GotoTargetMicrostepsDEC)
554 StepsToTarget = CurrentEncoderMicrostepsDEC - GotoTargetMicrostepsDEC;
556 StepsToTarget = GotoTargetMicrostepsDEC - CurrentEncoderMicrostepsDEC;
558 if (StepsToTarget <= SlewSteps)
561 AxisStatusDEC = STOPPED;
562 CurrentEncoderMicrostepsDEC = GotoTargetMicrostepsDEC;
566 if (FORWARD == AxisDirectionDEC)
567 CurrentEncoderMicrostepsDEC += SlewSteps;
569 CurrentEncoderMicrostepsDEC -= SlewSteps;
570 if (CurrentEncoderMicrostepsDEC < 0)
571 CurrentEncoderMicrostepsDEC += MICROSTEPS_PER_REVOLUTION;
572 else if (CurrentEncoderMicrostepsDEC >= MICROSTEPS_PER_REVOLUTION)
573 CurrentEncoderMicrostepsDEC -= MICROSTEPS_PER_REVOLUTION;
576 DEBUGF(DBG_SIMULATOR,
"TimerHit SlewingTo - DEC New Encoder %d New Status %d", CurrentEncoderMicrostepsDEC,
589 if ((STOPPED == AxisStatusRA) && (STOPPED == AxisStatusDEC))
594 DEBUG(DBG_SIMULATOR,
"TimerHit - Goto finished start tracking");
612 double JulianOffset = 1.0 / (24.0 * 60 * 60);
618 ln_get_julian_from_sys() + JulianOffset, TDV))
633 if ((AltAz.altitude > 90.0) || (AltAz.altitude < -90.0))
635 DEBUG(DBG_SIMULATOR,
"TimerHit tracking - Altitude out of range");
641 if ((AltAz.azimuth > 360.0) || (AltAz.azimuth < -360.0))
643 DEBUG(DBG_SIMULATOR,
"TimerHit tracking - Azimuth out of range");
648 if (AltAz.azimuth < 0.0)
650 DEBUG(DBG_SIMULATOR,
"TimerHit tracking - Azimuth negative");
651 AltAz.azimuth = 360.0 + AltAz.azimuth;
654 long AltitudeOffsetMicrosteps = int(AltAz.altitude * MICROSTEPS_PER_DEGREE - CurrentEncoderMicrostepsDEC);
655 long AzimuthOffsetMicrosteps = int(AltAz.azimuth * MICROSTEPS_PER_DEGREE - CurrentEncoderMicrostepsRA);
657 DEBUGF(DBG_SIMULATOR,
"TimerHit - Tracking AltitudeOffsetMicrosteps %d AzimuthOffsetMicrosteps %d",
658 AltitudeOffsetMicrosteps, AzimuthOffsetMicrosteps);
660 if (0 != AzimuthOffsetMicrosteps)
664 if (AzimuthOffsetMicrosteps > 0)
666 if (AzimuthOffsetMicrosteps < MICROSTEPS_PER_REVOLUTION / 2.0)
669 AxisDirectionRA = FORWARD;
670 AxisSlewRateRA = AzimuthOffsetMicrosteps;
675 AxisDirectionRA = REVERSE;
676 AxisSlewRateRA = MICROSTEPS_PER_REVOLUTION - AzimuthOffsetMicrosteps;
681 AzimuthOffsetMicrosteps = std::abs(AzimuthOffsetMicrosteps);
682 if (AzimuthOffsetMicrosteps < MICROSTEPS_PER_REVOLUTION / 2.0)
685 AxisDirectionRA = REVERSE;
686 AxisSlewRateRA = AzimuthOffsetMicrosteps;
691 AxisDirectionRA = FORWARD;
692 AxisSlewRateRA = MICROSTEPS_PER_REVOLUTION - AzimuthOffsetMicrosteps;
695 AxisSlewRateRA = std::abs(AzimuthOffsetMicrosteps);
696 AxisDirectionRA = AzimuthOffsetMicrosteps > 0 ? FORWARD : REVERSE;
697 AxisStatusRA = SLEWING;
698 DEBUGF(DBG_SIMULATOR,
"TimerHit - Tracking AxisSlewRateRA %lf AxisDirectionRA %d", AxisSlewRateRA,
704 AxisStatusRA = STOPPED;
705 DEBUG(DBG_SIMULATOR,
"TimerHit - Tracking nothing to do stopping RA axis");
708 if (0 != AltitudeOffsetMicrosteps)
712 AxisSlewRateDEC = std::abs(AltitudeOffsetMicrosteps);
713 AxisDirectionDEC = AltitudeOffsetMicrosteps > 0 ? FORWARD : REVERSE;
714 AxisStatusDEC = SLEWING;
715 DEBUGF(DBG_SIMULATOR,
"TimerHit - Tracking AxisSlewRateDEC %lf AxisDirectionDEC %d", AxisSlewRateDEC,
721 AxisStatusDEC = STOPPED;
722 DEBUG(DBG_SIMULATOR,
"TimerHit - Tracking nothing to do stopping DEC axis");
732 TraceThisTick =
false;
void ProcessAlignmentNumberProperties(Telescope *pTelescope, const char *name, double values[], char *names[], int n)
Call this function from within the ISNewNumber processing path. The function will handle any alignmen...
void ProcessAlignmentSwitchProperties(Telescope *pTelescope, const char *name, ISState *states, char *names[], int n)
Call this function from within the ISNewSwitch processing path. The function will handle any alignmen...
void InitAlignmentProperties(Telescope *pTelescope)
Initialize alignment subsystem properties. It is recommended to call this function within initPropert...
void ProcessAlignmentBLOBProperties(Telescope *pTelescope, const char *name, int sizes[], int blobsizes[], char *blobs[], char *formats[], char *names[], int n)
Call this function from within the ISNewBlob processing path. The function will handle any alignment ...
void ProcessAlignmentTextProperties(Telescope *pTelescope, const char *name, char *texts[], char *names[], int n)
Call this function from within the ISNewText processing path. The function will handle any alignment ...
bool CheckForDuplicateSyncPoint(const AlignmentDatabaseEntry &CandidateEntry, double Tolerance=0.1) const
Check if a entry already exists in the database.
AlignmentDatabaseType & GetAlignmentDatabase()
Get a reference to the in memory database.
void UpdateLocation(double latitude, double longitude, double elevation)
Call this function from within the updateLocation processing path.
void UpdateSize()
Call this function when the number of entries in the database changes.
bool TransformTelescopeToCelestialJD(const TelescopeDirectionVector &ApparentTelescopeDirectionVector, double &RightAscension, double &Declination, double JulianDate)
TransformTelescopeToCelestialJD Transforms Mount Coords to Celestial (Sky) Coordinates.
bool TransformCelestialToTelescopeJD(double RightAscension, double Declination, double JulianDate, TelescopeDirectionVector &ApparentTelescopeDirectionVector)
TransformCelestialToTelescopeJD Transforms Celestial (Sky) Coords to Mount Coordinates.
bool Initialise(InMemoryDatabase *pInMemoryDatabase)
Initialise or re-initialise the math plugin. Re-reading the in memory database as necessary.
MountAlignment_t GetApproximateMountAlignment()
Get the approximate alignment of the mount.
const TelescopeDirectionVector TelescopeDirectionVectorFromAltitudeAzimuth(INDI::IHorizontalCoordinates HorizontalCoordinates)
Calculates a normalised direction vector from the supplied altitude and azimuth.
void AltitudeAzimuthFromTelescopeDirectionVector(const TelescopeDirectionVector TelescopeDirectionVector, INDI::IHorizontalCoordinates &HorizontalCoordinates)
Calculates an altitude and azimuth from the supplied normalised direction vector and declination.
uint32_t getCurrentPollingPeriod() const
getCurrentPollingPeriod Return the current polling period.
virtual bool ISNewBLOB(const char *dev, const char *name, int sizes[], int blobsizes[], char *blobs[], char *formats[], char *names[], int n)
Process the client newBLOB command.
int SetTimer(uint32_t ms)
Set a timer to call the function TimerHit after ms milliseconds.
void addDebugControl()
Add Debug control to the driver.
void setState(IPState state)
void apply(const char *format,...) const ATTRIBUTE_FORMAT_PRINTF(2
bool isSwitchOn(const std::string &name) const
TelescopeStatus TrackState
virtual bool initProperties() override
Called to initialize basic properties required all the time.
virtual void TimerHit() override
Called when setTimer() time is up.
virtual bool ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n) override
Process the client newSwitch command.
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Process the client newNumber command.
IGeographicCoordinates m_Location
void NewRaDec(double ra, double dec)
The child class calls this function when it has updates.
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Process the client newSwitch command.
The ScopeSim class provides a simple mount simulator of an equatorial mount.
virtual bool ReadScopeStatus() override
Read telescope status.
virtual bool Abort() override
Abort any telescope motion including tracking if possible.
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Process the client newSwitch command.
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Process the client newNumber command.
virtual const char * getDefaultName() override
virtual bool Disconnect() override
Disconnect from device.
virtual bool Sync(double ra, double dec) override
Set the telescope current RA and DEC coordinates to the supplied RA and DEC coordinates.
virtual bool Goto(double, double) override
Move the scope to the supplied RA and DEC coordinates.
virtual bool ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n) override
Process the client newSwitch command.
virtual bool Connect() override
Connect to the device. INDI::DefaultDevice implementation connects to appropriate connection interfac...
void TimerHit() override
Called when setTimer() time is up.
virtual bool MoveWE(INDI_DIR_WE dir, TelescopeMotionCommand command) override
Move the telescope in the direction dir.
virtual bool updateLocation(double latitude, double longitude, double elevation) override
Update telescope location settings.
virtual bool MoveNS(INDI_DIR_NS dir, TelescopeMotionCommand command) override
Start or Stop the telescope motion in the direction dir.
virtual bool initProperties() override
Called to initialize basic properties required all the time.
bool ISNewBLOB(const char *dev, const char *name, int sizes[], int blobsizes[], char *blobs[], char *formats[], char *names[], int n) override
Process the client newBLOB command.
INDI::PropertySwitch AbortSP
INDI::PropertySwitch MovementNSSP
INDI::PropertyNumber EqNP
INDI::PropertySwitch MovementWESP
INDI::PropertySwitch CoordSP
int fs_sexa(char *out, double a, int w, int fracbase)
Converts a sexagesimal number to a string. sprint the variable a in sexagesimal format into out[].
Implementations for common driver routines.
#define DEBUG(priority, msg)
Macro to print log messages. Example of usage of the Logger: DEBUG(DBG_DEBUG, "hello " << "world");.
#define DEBUGF(priority, msg,...)
Namespace to encapsulate the INDI Alignment Subsystem classes. For more information see "INDI Alignme...
Namespace to encapsulate INDI client, drivers, and mediator classes.
void EquatorialToHorizontal(IEquatorialCoordinates *object, IGeographicCoordinates *observer, double JD, IHorizontalCoordinates *position)
EquatorialToHorizontal Calculate horizontal coordinates from equatorial coordinates.
void HorizontalToEquatorial(IHorizontalCoordinates *object, IGeographicCoordinates *observer, double JD, IEquatorialCoordinates *position)
HorizontalToEquatorial Calculate Equatorial EOD Coordinates from horizontal coordinates.
std::unique_ptr< ScopeSim > telescope_sim(new ScopeSim())
Entry in the in memory alignment database.
double RightAscension
Right ascension in decimal hours. N.B. libnova works in decimal degrees so conversion is always neede...
double ObservationJulianDate
TelescopeDirectionVector TelescopeDirection
Normalised vector giving telescope pointing direction. This is referred to elsewhere as the "apparent...
double Declination
Declination in decimal degrees.
int PrivateDataSize
This size in bytes of any private data.
Holds a normalised direction vector (direction cosines)
void RotateAroundY(double Angle)
Rotate the reference frame around the Y axis. This has the affect of rotating the vector itself in th...
The Logger class is a simple logger to log messages to file and INDI clients. This is the implementat...