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;
218 char *formats[],
char *names[],
int n)
270 AxisStatus axisStat = (command ==
MOTION_START) ? SLEWING : STOPPED;
272 AxisSlewRateDEC = DEFAULT_SLEW_RATE;
273 AxisDirectionDEC = axisDir;
274 AxisStatusDEC = axisStat;
281 AxisDirection axisDir = (dir ==
DIRECTION_WEST) ? FORWARD : REVERSE;
282 AxisStatus axisStat = (command ==
MOTION_START) ? SLEWING : STOPPED;
284 AxisSlewRateRA = DEFAULT_SLEW_RATE;
285 AxisDirectionRA = axisDir;
286 AxisStatusRA = axisStat;
295 double RightAscension, Declination;
299 DEBUG(DBG_SIMULATOR,
"ReadScopeStatus - TransformTelescopeToCelestial failed");
307 DEBUG(DBG_SIMULATOR,
"ReadScopeStatus - ApproximateMountAlignment ZENITH");
312 DEBUG(DBG_SIMULATOR,
"ReadScopeStatus - ApproximateMountAlignment NORTH_CELESTIAL_POLE");
321 DEBUG(DBG_SIMULATOR,
"ReadScopeStatus - ApproximateMountAlignment SOUTH_CELESTIAL_POLE");
337 DEBUGF(DBG_SIMULATOR,
"ReadScopeStatus - RA %lf hours DEC %lf degrees", RightAscension, Declination);
339 NewRaDec(RightAscension, Declination);
349 AltAz.altitude = double(CurrentEncoderMicrostepsDEC) / MICROSTEPS_PER_DEGREE;
350 AltAz.azimuth = double(CurrentEncoderMicrostepsRA) / MICROSTEPS_PER_DEGREE;
375 TraceThisTickCount++;
376 if (60 == TraceThisTickCount)
378 TraceThisTick =
true;
379 TraceThisTickCount = 0;
383 static struct timeval ltv
393 gettimeofday(&tv,
nullptr);
395 if (ltv.tv_sec == 0 && ltv.tv_usec == 0)
398 dt = tv.tv_sec - ltv.tv_sec + (tv.tv_usec - ltv.tv_usec) / 1e6;
402 long SlewSteps = dt * AxisSlewRateRA;
403 bool CompleteRevolution = SlewSteps >= MICROSTEPS_PER_REVOLUTION;
404 SlewSteps = SlewSteps % MICROSTEPS_PER_REVOLUTION;
406 switch (AxisStatusRA)
415 "TimerHit Slewing - RA Current Encoder %ld SlewSteps %ld Direction %d Target %ld Status %d",
416 CurrentEncoderMicrostepsRA, SlewSteps, AxisDirectionRA, GotoTargetMicrostepsRA, AxisStatusRA);
419 if (FORWARD == AxisDirectionRA)
420 CurrentEncoderMicrostepsRA += SlewSteps;
422 CurrentEncoderMicrostepsRA -= SlewSteps;
423 if (CurrentEncoderMicrostepsRA < 0)
424 CurrentEncoderMicrostepsRA += MICROSTEPS_PER_REVOLUTION;
425 else if (CurrentEncoderMicrostepsRA >= MICROSTEPS_PER_REVOLUTION)
426 CurrentEncoderMicrostepsRA -= MICROSTEPS_PER_REVOLUTION;
428 DEBUGF(DBG_SIMULATOR,
"TimerHit Slewing - RA New Encoder %d New Status %d", CurrentEncoderMicrostepsRA,
436 "TimerHit SlewingTo - RA Current Encoder %ld SlewSteps %ld Direction %d Target %ld Status %d",
437 CurrentEncoderMicrostepsRA, SlewSteps, AxisDirectionRA, GotoTargetMicrostepsRA, AxisStatusRA);
439 long OldEncoder = CurrentEncoderMicrostepsRA;
441 if (FORWARD == AxisDirectionRA)
442 CurrentEncoderMicrostepsRA += SlewSteps;
444 CurrentEncoderMicrostepsRA -= SlewSteps;
445 if (CurrentEncoderMicrostepsRA < 0)
446 CurrentEncoderMicrostepsRA += MICROSTEPS_PER_REVOLUTION;
447 else if (CurrentEncoderMicrostepsRA >= MICROSTEPS_PER_REVOLUTION)
448 CurrentEncoderMicrostepsRA -= MICROSTEPS_PER_REVOLUTION;
450 if (CompleteRevolution)
453 AxisStatusRA = STOPPED;
454 CurrentEncoderMicrostepsRA = GotoTargetMicrostepsRA;
458 bool FoundTarget =
false;
459 if (FORWARD == AxisDirectionRA)
461 if (CurrentEncoderMicrostepsRA < OldEncoder)
464 if ((GotoTargetMicrostepsRA >= OldEncoder) &&
465 (GotoTargetMicrostepsRA <= MICROSTEPS_PER_REVOLUTION))
467 else if ((GotoTargetMicrostepsRA >= 0) &&
468 (GotoTargetMicrostepsRA <= CurrentEncoderMicrostepsRA))
471 else if ((GotoTargetMicrostepsRA >= OldEncoder) &&
472 (GotoTargetMicrostepsRA <= CurrentEncoderMicrostepsRA))
477 if (CurrentEncoderMicrostepsRA > OldEncoder)
480 if ((GotoTargetMicrostepsRA >= 0) && (GotoTargetMicrostepsRA <= OldEncoder))
482 else if ((GotoTargetMicrostepsRA >= CurrentEncoderMicrostepsRA) &&
483 (GotoTargetMicrostepsRA <= MICROSTEPS_PER_REVOLUTION))
486 else if ((GotoTargetMicrostepsRA >= CurrentEncoderMicrostepsRA) &&
487 (GotoTargetMicrostepsRA <= OldEncoder))
492 AxisStatusRA = STOPPED;
493 CurrentEncoderMicrostepsRA = GotoTargetMicrostepsRA;
496 DEBUGF(DBG_SIMULATOR,
"TimerHit SlewingTo - RA New Encoder %d New Status %d", CurrentEncoderMicrostepsRA,
503 SlewSteps = dt * AxisSlewRateDEC;
505 switch (AxisStatusDEC)
514 "TimerHit Slewing - DEC Current Encoder %ld SlewSteps %d Direction %ld Target %ld Status %d",
515 CurrentEncoderMicrostepsDEC, SlewSteps, AxisDirectionDEC, GotoTargetMicrostepsDEC, AxisStatusDEC);
518 SlewSteps = SlewSteps % MICROSTEPS_PER_REVOLUTION;
519 if (FORWARD == AxisDirectionDEC)
520 CurrentEncoderMicrostepsDEC += SlewSteps;
522 CurrentEncoderMicrostepsDEC -= SlewSteps;
523 if (CurrentEncoderMicrostepsDEC > MAX_DEC)
525 CurrentEncoderMicrostepsDEC = MAX_DEC;
526 AxisStatusDEC = STOPPED;
527 DEBUG(DBG_SIMULATOR,
"TimerHit - DEC axis hit the buffers at MAX_DEC");
529 else if (CurrentEncoderMicrostepsDEC < MIN_DEC)
531 CurrentEncoderMicrostepsDEC = MIN_DEC;
532 AxisStatusDEC = STOPPED;
533 DEBUG(DBG_SIMULATOR,
"TimerHit - DEC axis hit the buffers at MIN_DEC");
536 DEBUGF(DBG_SIMULATOR,
"TimerHit Slewing - DEC New Encoder %d New Status %d", CurrentEncoderMicrostepsDEC,
544 "TimerHit SlewingTo - DEC Current Encoder %ld SlewSteps %d Direction %ld Target %ld Status %d",
545 CurrentEncoderMicrostepsDEC, SlewSteps, AxisDirectionDEC, GotoTargetMicrostepsDEC, AxisStatusDEC);
549 if (FORWARD == AxisDirectionDEC)
551 if (CurrentEncoderMicrostepsDEC <= GotoTargetMicrostepsDEC)
552 StepsToTarget = GotoTargetMicrostepsDEC - CurrentEncoderMicrostepsDEC;
554 StepsToTarget = CurrentEncoderMicrostepsDEC - GotoTargetMicrostepsDEC;
559 if (CurrentEncoderMicrostepsDEC >= GotoTargetMicrostepsDEC)
560 StepsToTarget = CurrentEncoderMicrostepsDEC - GotoTargetMicrostepsDEC;
562 StepsToTarget = GotoTargetMicrostepsDEC - CurrentEncoderMicrostepsDEC;
564 if (StepsToTarget <= SlewSteps)
567 AxisStatusDEC = STOPPED;
568 CurrentEncoderMicrostepsDEC = GotoTargetMicrostepsDEC;
572 if (FORWARD == AxisDirectionDEC)
573 CurrentEncoderMicrostepsDEC += SlewSteps;
575 CurrentEncoderMicrostepsDEC -= SlewSteps;
576 if (CurrentEncoderMicrostepsDEC < 0)
577 CurrentEncoderMicrostepsDEC += MICROSTEPS_PER_REVOLUTION;
578 else if (CurrentEncoderMicrostepsDEC >= MICROSTEPS_PER_REVOLUTION)
579 CurrentEncoderMicrostepsDEC -= MICROSTEPS_PER_REVOLUTION;
582 DEBUGF(DBG_SIMULATOR,
"TimerHit SlewingTo - DEC New Encoder %d New Status %d", CurrentEncoderMicrostepsDEC,
595 if ((STOPPED == AxisStatusRA) && (STOPPED == AxisStatusDEC))
600 DEBUG(DBG_SIMULATOR,
"TimerHit - Goto finished start tracking");
619 double JulianOffset = 1.0 / (24.0 * 60 * 60);
639 if ((
AltAz.altitude > 90.0) || (
AltAz.altitude < -90.0))
641 DEBUG(DBG_SIMULATOR,
"TimerHit tracking - Altitude out of range");
647 if ((
AltAz.azimuth > 360.0) || (
AltAz.azimuth < -360.0))
649 DEBUG(DBG_SIMULATOR,
"TimerHit tracking - Azimuth out of range");
654 if (
AltAz.azimuth < 0.0)
656 DEBUG(DBG_SIMULATOR,
"TimerHit tracking - Azimuth negative");
660 long AltitudeOffsetMicrosteps = int(
AltAz.altitude * MICROSTEPS_PER_DEGREE - CurrentEncoderMicrostepsDEC);
661 long AzimuthOffsetMicrosteps = int(
AltAz.azimuth * MICROSTEPS_PER_DEGREE - CurrentEncoderMicrostepsRA);
663 DEBUGF(DBG_SIMULATOR,
"TimerHit - Tracking AltitudeOffsetMicrosteps %d AzimuthOffsetMicrosteps %d",
664 AltitudeOffsetMicrosteps, AzimuthOffsetMicrosteps);
666 if (0 != AzimuthOffsetMicrosteps)
670 if (AzimuthOffsetMicrosteps > 0)
672 if (AzimuthOffsetMicrosteps < MICROSTEPS_PER_REVOLUTION / 2.0)
675 AxisDirectionRA = FORWARD;
676 AxisSlewRateRA = AzimuthOffsetMicrosteps;
681 AxisDirectionRA = REVERSE;
682 AxisSlewRateRA = MICROSTEPS_PER_REVOLUTION - AzimuthOffsetMicrosteps;
687 AzimuthOffsetMicrosteps = std::abs(AzimuthOffsetMicrosteps);
688 if (AzimuthOffsetMicrosteps < MICROSTEPS_PER_REVOLUTION / 2.0)
691 AxisDirectionRA = REVERSE;
692 AxisSlewRateRA = AzimuthOffsetMicrosteps;
697 AxisDirectionRA = FORWARD;
698 AxisSlewRateRA = MICROSTEPS_PER_REVOLUTION - AzimuthOffsetMicrosteps;
701 AxisSlewRateRA = std::abs(AzimuthOffsetMicrosteps);
702 AxisDirectionRA = AzimuthOffsetMicrosteps > 0 ? FORWARD : REVERSE;
703 AxisStatusRA = SLEWING;
704 DEBUGF(DBG_SIMULATOR,
"TimerHit - Tracking AxisSlewRateRA %lf AxisDirectionRA %d", AxisSlewRateRA,
710 AxisStatusRA = STOPPED;
711 DEBUG(DBG_SIMULATOR,
"TimerHit - Tracking nothing to do stopping RA axis");
714 if (0 != AltitudeOffsetMicrosteps)
718 AxisSlewRateDEC = std::abs(AltitudeOffsetMicrosteps);
719 AxisDirectionDEC = AltitudeOffsetMicrosteps > 0 ? FORWARD : REVERSE;
720 AxisStatusDEC = SLEWING;
721 DEBUGF(DBG_SIMULATOR,
"TimerHit - Tracking AxisSlewRateDEC %lf AxisDirectionDEC %d", AxisSlewRateDEC,
727 AxisStatusDEC = STOPPED;
728 DEBUG(DBG_SIMULATOR,
"TimerHit - Tracking nothing to do stopping DEC axis");
738 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)
Initilize alignment subsystem properties. It is recommended to call this function within initProperti...
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 ...
AlignmentDatabaseType & GetAlignmentDatabase()
Get a reference to the in memory database.
bool CheckForDuplicateSyncPoint(const AlignmentDatabaseEntry &CandidateEntry, double Tolerance=0.1) const
Check if a entry already exists in the 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 TransformTelescopeToCelestial(const TelescopeDirectionVector &ApparentTelescopeDirectionVector, double &RightAscension, double &Declination)
TransformTelescopeToCelestial Transforms Mount Coords to Celestial (Sky) Coordinates.
bool TransformCelestialToTelescope(const double RightAscension, const double Declination, double JulianOffset, TelescopeDirectionVector &ApparentTelescopeDirectionVector)
TransformCelestialToTelescope 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 alognment 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.
const char * getDeviceName() const
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.
TelescopeStatus TrackState
ISwitchVectorProperty MovementNSSP
ISwitchVectorProperty AbortSP
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.
ISwitchVectorProperty CoordSP
INumberVectorProperty EqNP
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Process the client newNumber command.
INumber ScopeParametersN[4]
IGeographicCoordinates m_Location
void NewRaDec(double ra, double dec)
The child class calls this function when it has updates.
ISwitchVectorProperty MovementWESP
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.
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.
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.
void IUResetSwitch(ISwitchVectorProperty *svp)
Reset all switches in a switch vector property to OFF.
ISwitch * IUFindSwitch(const ISwitchVectorProperty *svp, const char *name)
Find an ISwitch member in a vector switch property.
void IDSetNumber(const INumberVectorProperty *nvp, const char *fmt,...)
void IDSetSwitch(const ISwitchVectorProperty *svp, const char *fmt,...)
#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 nomalised 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...