Telescope Control Library
EquatorialMount.h
- Committer:
- caoyu@caoyuan9642-desktop.MIT.EDU
- Date:
- 2018-09-24
- Revision:
- 19:fd854309cb4c
- Parent:
- 18:3ea58b079adc
File content as of revision 19:fd854309cb4c:
#ifndef EQUATORIALMOUNT_H_ #define EQUATORIALMOUNT_H_ #include "Axis.h" #include "Mount.h" #include "UTCClock.h" #include "LocationProvider.h" #include "CelestialMath.h" #include "PEC.h" #define MAX_AS_N 10 // Max number of alignment stars class Axis; class PEC; /** * Direction of nudge */ typedef enum { NUDGE_NONE = 0, NUDGE_EAST = 1, NUDGE_WEST = 2, NUDGE_NORTH = 4, NUDGE_SOUTH = 8, NUDGE_NORTHWEST = NUDGE_NORTH | NUDGE_WEST, NUDGE_SOUTHWEST = NUDGE_SOUTH | NUDGE_WEST, NUDGE_NORTHEAST = NUDGE_NORTH | NUDGE_EAST, NUDGE_SOUTHEAST = NUDGE_SOUTH | NUDGE_EAST, } nudgedir_t; /** * Direction of guide */ typedef enum { GUIDE_EAST = 1, GUIDE_WEST = 2, GUIDE_NORTH = 3, GUIDE_SOUTH = 4, } guidedir_t; /** * Object that represents an equatorial mount with two perpendicular axis called RA and Dec. */ class EquatorialMount: public Mount { protected: Axis &ra; /// RA Axis Axis &dec; /// DEC Axis UTCClock &clock; /// Clock Mutex mutex_update; /// Mutex to lock position updating Mutex mutex_execution; /// Mutex to lock motion related functions LocationProvider loc; /// Current location (GPS coordinates) bool south; /// If we are in south semisphere MountCoordinates curr_pos; /// Current Position in mount coordinates (offset from the index positions) EquatorialCoordinates curr_pos_eq; /// Current Position in the equatorial coordinates (absolute pointing direction in the sky) nudgedir_t curr_nudge_dir; double nudgeSpeed; pierside_t pier_side; /// Side of pier. 1: East EqCalibration calibration; AlignmentStar alignment_stars[MAX_AS_N]; int num_alignment_stars; PEC pec; /// PEC function public: /** * Create an EquatorialMount object which controls two axis * @param ra RA Axis * @param dec DEC Axis * @note cone_value, ma_alt, ma_azi,off_ra, off_dec will be init to zero, i.e. assuming a perfectly aligned mount pointing at RA=DEC=0 * @note This class assumes that the rotating direction of both axis are correct. * This should be done using the invert option when initializing the RotationAxis objects * @sa RotationAxis */ EquatorialMount(Axis &ra, Axis &dec, UTCClock &clk, LocationProvider &loc); virtual ~EquatorialMount() { } /** * Perform a Go-To to specified equatorial coordinates in the sky * @param ra_dest RA coordinate in degree. * @return osOK if no error */ osStatus goTo(double ra_dest, double dec_dest); osStatus goTo(EquatorialCoordinates dest); osStatus goToMount(MountCoordinates mc, bool withCorrection = true); osStatus goToIndex() { return goToMount(MountCoordinates(0, 0)); } osStatus startNudge(nudgedir_t); osStatus stopNudge(); osStatus startTracking(); osStatus stopTracking(); mountstatus_t getStatus(); /** * Guide on specified direction for specified time */ osStatus guide(guidedir_t dir, int ms); /*Calibration related functions*/ /** * Clear calibration, use current latitude for the polar axis */ void clearCalibration() { num_alignment_stars = 0; calibration = EqCalibration(); calibration.pa.alt = loc.getLatitude(); } /** * Clear calibration except axis offsets, use current latitude for the polar axis */ void clearCalibrationExceptOffsets() { num_alignment_stars = 0; calibration.cone = 0; calibration.pa.alt = loc.getLatitude(); calibration.pa.azi = 0; } /** * Get calibration * @return Current calibration */ const EqCalibration &getCalibration() const { return calibration; } /** * Set calibration * @param calib New Calibration */ void setCalibration(const EqCalibration &calib) { calibration = calib; } /** @return number of alignment stars */ int getNumAlignmentStar() { return num_alignment_stars; } /** Add an alignment star * @return osStatus error if no more star can be added */ osStatus addAlignmentStar(const AlignmentStar &as) { if (num_alignment_stars < MAX_AS_N) { alignment_stars[num_alignment_stars++] = as; return recalibrate(); } else return osErrorResource; } /** Remove an alignment star * @param index # of star to remove, starting from 0 * @return osStatus error if no more star can be deleted */ osStatus removeAlignmentStar(int index) { if (index < 0 || index >= num_alignment_stars) { return osErrorParameter; } for (; index < num_alignment_stars - 1; index++) { alignment_stars[index] = alignment_stars[index + 1]; } num_alignment_stars--; return recalibrate(); } /** Get alignment star * @param index # of star to get * @return pointer to that alignment star if found, NULL if doesn't exist */ AlignmentStar *getAlignmentStar(int index) { if (index < 0 || index >= num_alignment_stars) { return NULL; } return &alignment_stars[index]; } /** Replace an alignment star with another * @param index # of star to replace * @param as new star to add. Will be copied by value * @return error if star not found */ osStatus replaceAlignmentStar(int index, const AlignmentStar &as) { if (index < 0 || index >= num_alignment_stars) { return osErrorParameter; } alignment_stars[index] = as; return recalibrate(); } /** Force all alignment stars to be perfected aligned according to the current calibration * Useful during a polar alignment procedure * @note This will throw off all the alignment stars if the error is too big or calibration is wrong */ void forceAlignment(); /** * Convert EQ coordinates to mount coodinates using current calibration. Utility function * @param eq EQ coordinate to convert * @return mount coordinates */ MountCoordinates convertToMountCoordinates( const EquatorialCoordinates &eq) { LocalEquatorialCoordinates leq = CelestialMath::equatorialToLocalEquatorial(eq, clock.getTimeHighResolution(), loc.getLocation()); // Apply PA misalignment leq = CelestialMath::applyMisalignment(leq, calibration.pa, loc.getLocation()); // Apply Cone error leq = CelestialMath::applyConeError(leq, calibration.cone); // Convert to Mount coordinates. Automatically determine the pier side, then apply offset return CelestialMath::localEquatorialToMount(leq, PIER_SIDE_AUTO) + calibration.offset; } /** * Convert mount coordinates to EQ coodinates using current calibration. Utility function * @param mc Mount coordinate to convert * @return EQ coordinates */ EquatorialCoordinates convertToEqCoordinates(const MountCoordinates &mc) { LocalEquatorialCoordinates leq = CelestialMath::mountToLocalEquatorial( mc - calibration.offset); leq = CelestialMath::deapplyConeError(leq, calibration.cone); leq = CelestialMath::deapplyMisalignment(leq, calibration.pa, loc.getLocation()); return CelestialMath::localEquatorialToEquatorial(leq, clock.getTimeHighResolution(), loc.getLocation()); } /** * Use alignment stars to recalculate the calibration. * @return osStatus */ osStatus recalibrate(); /** * Call emergency stop of the Axis objects * @note This function can be called from any context (including ISR) to perform a hard stop of the mount */ void emergencyStop(); /** * Call stop of the Axis objects * @note This function can be called from any context (including ISR) to perform a soft stop of the mount */ void stopAsync(); /** BLOCKING. Cannot be called in ISR. * Call stop of the Axis objects and wait until they are stopped. * @note This function can be called from any context (including ISR) to perform a soft stop of the mount */ void stopSync(); /** * Get current equatorial coordinates * @return current equatorial coordinates */ const EquatorialCoordinates &getEquatorialCoordinates() { updatePosition(); return curr_pos_eq; } /** * Get current mount coordinates * @return current mount coordinates */ const MountCoordinates &getMountCoordinates() { updatePosition(); return curr_pos; } /** * Make an alignment star object using the provided reference star, current mount position, and current time * @param star_ref Reference star position * @return AlignmentStar object representing the alignment star */ AlignmentStar makeAlignmentStar(const EquatorialCoordinates star_ref) { updatePosition(); return AlignmentStar(star_ref, curr_pos, clock.getTimeHighResolution()); } /** * Align the current mount using an array of alignment stars. Support up to 10 stars. * @note If n=1, will only correct for Index offset * If n=2, will correct for index offset and polar misalignment * If n>=3, will correct for index offset, pa misalignment and cone error * @param n # of alignment stars to use * @param as Array of alignment stars * @return osOK if successfully converged and updated the values */ osStatus align(int n, const AlignmentStar as[]); /** * Set slew rate of both axis * @param rate new speed */ void setSlewSpeed(double rate); /** @return current slew speed */ double getSlewSpeed(); /** * Set tracking speed of RA axis * @param rate new speed in sidereal rate */ void setTrackSpeedSidereal(double rate); /** @return current track speed in sidereal units */ double getTrackSpeedSidereal(); /** * Set guiding speed of RA axis * @param rate new speed in sidereal rate */ void setGuideSpeedSidereal(double rate); /** @return current guide speed in sidereal units */ double getGuideSpeedSidereal(); /** * Print current position to stream. */ void printPosition(FILE *stream = stdout) { fprintf(stream, "Mount: RA=%7.2f, DEC=%7.2f %c\n", curr_pos.ra_delta, curr_pos.dec_delta, (curr_pos.side == PIER_SIDE_WEST) ? 'W' : 'E'); fprintf(stream, "EQ: RA=%7.2f, DEC=%7.2f\n", curr_pos_eq.ra, curr_pos_eq.dec); } /** * Update current pointing direction from low-level encoders/counters. * @note should be called before printing the position using printPosition */ void updatePosition(); /** Get current time source */ UTCClock& getClock() const { return clock; } /** @return get current location coodinates. */ LocationCoordinates getLocation() const { return loc.getLocation(); } }; #endif /*EQUATORIALMOUNT_H_*/