bool ScopeSim::ReadScopeStatus() { static struct timeval ltv { 0, 0 }; struct timeval tv { 0, 0 }; double dt = 0, da_ra = 0, da_dec = 0, dx = 0, dy = 0, ra_guide_dt = 0, dec_guide_dt = 0; static double last_dx = 0, last_dy = 0; int nlocked, ns_guide_dir = -1, we_guide_dir = -1; char RA_DISP[64], DEC_DISP[64], RA_GUIDE[64], DEC_GUIDE[64], RA_PE[64], DEC_PE[64], RA_TARGET[64], DEC_TARGET[64]; /* update elapsed time since last poll, don't presume exactly POLLMS */ gettimeofday(&tv, nullptr); if (ltv.tv_sec == 0 && ltv.tv_usec == 0) ltv = tv; dt = tv.tv_sec - ltv.tv_sec + (tv.tv_usec - ltv.tv_usec) / 1e6; ltv = tv; if (fabs(targetRA - currentRA) * 15. >= GOTO_LIMIT) da_ra = GOTO_RATE * dt; else if (fabs(targetRA - currentRA) * 15. >= SLEW_LIMIT) da_ra = SLEW_RATE * dt; else da_ra = FINE_SLEW_RATE * dt; if (fabs(targetDEC - currentDEC) >= GOTO_LIMIT) da_dec = GOTO_RATE * dt; else if (fabs(targetDEC - currentDEC) >= SLEW_LIMIT) da_dec = SLEW_RATE * dt; else da_dec = FINE_SLEW_RATE * dt; if (MovementNSSP.s == IPS_BUSY || MovementWESP.s == IPS_BUSY) { int rate = IUFindOnSwitchIndex(&SlewRateSP); switch (rate) { case SLEW_GUIDE: da_ra = FINE_SLEW_RATE * dt * 0.05; da_dec = FINE_SLEW_RATE * dt * 0.05; break; case SLEW_CENTERING: da_ra = FINE_SLEW_RATE * dt * .1; da_dec = FINE_SLEW_RATE * dt * .1; break; case SLEW_FIND: da_ra = SLEW_RATE * dt; da_dec = SLEW_RATE * dt; break; default: da_ra = GOTO_RATE * dt; da_dec = GOTO_RATE * dt; break; } switch (MovementNSSP.s) { case IPS_BUSY: if (MovementNSS[DIRECTION_NORTH].s == ISS_ON) currentDEC += da_dec; else if (MovementNSS[DIRECTION_SOUTH].s == ISS_ON) currentDEC -= da_dec; break; default: break; } switch (MovementWESP.s) { case IPS_BUSY: if (MovementWES[DIRECTION_WEST].s == ISS_ON) currentRA += da_ra / 15.; else if (MovementWES[DIRECTION_EAST].s == ISS_ON) currentRA -= da_ra / 15.; break; default: break; } NewRaDec(currentRA, currentDEC); return true; } /* Process per current state. We check the state of EQUATORIAL_EOD_COORDS_REQUEST and act acoordingly */ switch (TrackState) { /*case SCOPE_IDLE: EqNP.s = IPS_IDLE; break;*/ case SCOPE_SLEWING: case SCOPE_PARKING: /* slewing - nail it when both within one pulse @ SLEWRATE */ nlocked = 0; dx = targetRA - currentRA; // Always take the shortcut, don't go all around the globe // If the difference between target and current is more than 12 hours, then we need to take the shortest path if (dx > 12) dx -= 24; else if (dx < -12) dx += 24; // In meridian flip, alway force eastward motion (increasing RA) until target is reached. if (forceMeridianFlip) { dx = fabs(dx); if (dx == 0) { dx = 1; da_ra = GOTO_LIMIT; } } if (fabs(dx) * 15. <= da_ra) { currentRA = targetRA; nlocked++; } else if (dx > 0) currentRA += da_ra / 15.; else currentRA -= da_ra / 15.; currentRA = range24(currentRA); dy = targetDEC - currentDEC; if (fabs(dy) <= da_dec) { currentDEC = targetDEC; nlocked++; } else if (dy > 0) currentDEC += da_dec; else currentDEC -= da_dec; EqNP.s = IPS_BUSY; if (nlocked == 2) { forceMeridianFlip = false; if (TrackState == SCOPE_SLEWING) { // Initially no PE in both axis. EqPEN[0].value = currentRA; EqPEN[1].value = currentDEC; IDSetNumber(&EqPENV, nullptr); TrackState = SCOPE_TRACKING; EqNP.s = IPS_OK; DEBUG(INDI::Logger::DBG_SESSION, "Telescope slew is complete. Tracking..."); } else { SetParked(true); EqNP.s = IPS_IDLE; } } break; case SCOPE_IDLE: //currentRA += (TRACKRATE_SIDEREAL/3600.0 * dt) / 15.0; currentRA += (TrackRateN[AXIS_RA].value/3600.0 * dt) / 15.0; currentRA = range24(currentRA); break; case SCOPE_TRACKING: // In case of custom tracking rate if (TrackModeS[1].s == ISS_ON) { currentRA += ( ((TRACKRATE_SIDEREAL/3600.0) - (TrackRateN[AXIS_RA].value/3600.0)) * dt) / 15.0; currentDEC += ( (TrackRateN[AXIS_DE].value/3600.0) * dt); } dt *= 1000; if (guiderNSTarget[GUIDE_NORTH] > 0) { DEBUGF(INDI::Logger::DBG_DEBUG, "Commanded to GUIDE NORTH for %g ms", guiderNSTarget[GUIDE_NORTH]); ns_guide_dir = GUIDE_NORTH; } else if (guiderNSTarget[GUIDE_SOUTH] > 0) { DEBUGF(INDI::Logger::DBG_DEBUG, "Commanded to GUIDE SOUTH for %g ms", guiderNSTarget[GUIDE_SOUTH]); ns_guide_dir = GUIDE_SOUTH; } // WE Guide Selection if (guiderEWTarget[GUIDE_WEST] > 0) { we_guide_dir = GUIDE_WEST; DEBUGF(INDI::Logger::DBG_DEBUG, "Commanded to GUIDE WEST for %g ms", guiderEWTarget[GUIDE_WEST]); } else if (guiderEWTarget[GUIDE_EAST] > 0) { we_guide_dir = GUIDE_EAST; DEBUGF(INDI::Logger::DBG_DEBUG, "Commanded to GUIDE EAST for %g ms", guiderEWTarget[GUIDE_EAST]); } if (ns_guide_dir != -1) { dec_guide_dt = TrackRateN[AXIS_RA].value/3600.0 * GuideRateN[DEC_AXIS].value * guiderNSTarget[ns_guide_dir] / 1000.0 * (ns_guide_dir == GUIDE_NORTH ? 1 : -1); // If time remaining is more that dt, then decrement and if (guiderNSTarget[ns_guide_dir] >= dt) guiderNSTarget[ns_guide_dir] -= dt; else guiderNSTarget[ns_guide_dir] = 0; if (guiderNSTarget[ns_guide_dir] == 0) { GuideNSNP.s = IPS_IDLE; IDSetNumber(&GuideNSNP, nullptr); } EqPEN[DEC_AXIS].value += dec_guide_dt; } if (we_guide_dir != -1) { ra_guide_dt = (TrackRateN[AXIS_RA].value/3600.0) / 15.0 * GuideRateN[RA_AXIS].value * guiderEWTarget[we_guide_dir] / 1000.0 * (we_guide_dir == GUIDE_WEST ? -1 : 1); if (guiderEWTarget[we_guide_dir] >= dt) guiderEWTarget[we_guide_dir] -= dt; else guiderEWTarget[we_guide_dir] = 0; if (guiderEWTarget[we_guide_dir] == 0) { GuideWENP.s = IPS_IDLE; IDSetNumber(&GuideWENP, nullptr); } EqPEN[RA_AXIS].value += ra_guide_dt; } //Mention the followng: // Current RA displacemet and direction // Current DEC displacement and direction // Amount of RA GUIDING correction and direction // Amount of DEC GUIDING correction and direction dx = EqPEN[RA_AXIS].value - targetRA; dy = EqPEN[DEC_AXIS].value - targetDEC; fs_sexa(RA_DISP, fabs(dx), 2, 3600); fs_sexa(DEC_DISP, fabs(dy), 2, 3600); fs_sexa(RA_GUIDE, fabs(ra_guide_dt), 2, 3600); fs_sexa(DEC_GUIDE, fabs(dec_guide_dt), 2, 3600); fs_sexa(RA_PE, EqPEN[RA_AXIS].value, 2, 3600); fs_sexa(DEC_PE, EqPEN[DEC_AXIS].value, 2, 3600); fs_sexa(RA_TARGET, targetRA, 2, 3600); fs_sexa(DEC_TARGET, targetDEC, 2, 3600); if (dx != last_dx || dy != last_dy || ra_guide_dt != 0.0 || dec_guide_dt != 0.0) { last_dx = dx; last_dy = dy; //DEBUGF(INDI::Logger::DBG_DEBUG, "dt is %g\n", dt); DEBUGF(INDI::Logger::DBG_DEBUG, "RA Displacement (%c%s) %s -- %s of target RA %s", dx >= 0 ? '+' : '-', RA_DISP, RA_PE, (EqPEN[RA_AXIS].value - targetRA) > 0 ? "East" : "West", RA_TARGET); DEBUGF(INDI::Logger::DBG_DEBUG, "DEC Displacement (%c%s) %s -- %s of target RA %s", dy >= 0 ? '+' : '-', DEC_DISP, DEC_PE, (EqPEN[DEC_AXIS].value - targetDEC) > 0 ? "North" : "South", DEC_TARGET); DEBUGF(INDI::Logger::DBG_DEBUG, "RA Guide Correction (%g) %s -- Direction %s", ra_guide_dt, RA_GUIDE, ra_guide_dt > 0 ? "East" : "West"); DEBUGF(INDI::Logger::DBG_DEBUG, "DEC Guide Correction (%g) %s -- Direction %s", dec_guide_dt, DEC_GUIDE, dec_guide_dt > 0 ? "North" : "South"); } if (ns_guide_dir != -1 || we_guide_dir != -1) IDSetNumber(&EqPENV, nullptr); break; default: break; } char RAStr[64], DecStr[64]; fs_sexa(RAStr, currentRA, 2, 3600); fs_sexa(DecStr, currentDEC, 2, 3600); DEBUGF(DBG_SCOPE, "Current RA: %s Current DEC: %s", RAStr, DecStr); NewRaDec(currentRA, currentDEC); return true; }
void SynscanDriver::mountSim() { static struct timeval ltv; struct timeval tv; double dt, da, dx; int nlocked; /* update elapsed time since last poll, don't presume exactly POLLMS */ gettimeofday(&tv, nullptr); if (ltv.tv_sec == 0 && ltv.tv_usec == 0) ltv = tv; dt = tv.tv_sec - ltv.tv_sec + (tv.tv_usec - ltv.tv_usec) / 1e6; ltv = tv; double currentSlewRate = SIM_SLEW_RATE[IUFindOnSwitchIndex(&SlewRateSP)] * TRACKRATE_SIDEREAL / 3600.0; da = currentSlewRate * dt; /* Process per current state. We check the state of EQUATORIAL_COORDS and act acoordingly */ switch (TrackState) { case SCOPE_IDLE: CurrentRA += (TrackRateN[AXIS_RA].value / 3600.0 * dt) / 15.0; CurrentRA = range24(CurrentRA); break; case SCOPE_TRACKING: break; case SCOPE_SLEWING: case SCOPE_PARKING: /* slewing - nail it when both within one pulse @ SLEWRATE */ nlocked = 0; dx = TargetRA - CurrentRA; // Take shortest path if (fabs(dx) > 12) dx *= -1; if (fabs(dx) <= da) { CurrentRA = TargetRA; nlocked++; } else if (dx > 0) CurrentRA += da / 15.; else CurrentRA -= da / 15.; if (CurrentRA < 0) CurrentRA += 24; else if (CurrentRA > 24) CurrentRA -= 24; dx = TargetDE - CurrentDE; if (fabs(dx) <= da) { CurrentDE = TargetDE; nlocked++; } else if (dx > 0) CurrentDE += da; else CurrentDE -= da; if (nlocked == 2) { if (TrackState == SCOPE_SLEWING) TrackState = SCOPE_TRACKING; else TrackState = SCOPE_PARKED; } break; default: break; } NewRaDec(CurrentRA, CurrentDE); }
double get_local_sidereal_time(double longitude) { double SD = ln_get_apparent_sidereal_time(ln_get_julian_from_sys()) - (360.0 - longitude) / 15.0; return range24(SD); }