bool SynscanDriver::Goto(double ra, double dec) { char cmd[SYN_RES] = {0}, res[SYN_RES] = {0}; TargetRA = ra; TargetDE = dec; if (isSimulation()) return true; // INDI is JNow. Synscan Controll uses J2000 Epoch ln_equ_posn epochPos { 0, 0 }, J2000Pos { 0, 0 }; epochPos.ra = ra * 15.0; epochPos.dec = dec; // For Alt/Az mounts, we must issue Goto Alt/Az if (m_isAltAz) { struct ln_lnlat_posn lnobserver; struct ln_hrz_posn lnaltaz; lnobserver.lng = LocationN[LOCATION_LONGITUDE].value; if (lnobserver.lng > 180) lnobserver.lng -= 360; lnobserver.lat = LocationN[LOCATION_LATITUDE].value; ln_get_hrz_from_equ(&epochPos, &lnobserver, ln_get_julian_from_sys(), &lnaltaz); /* libnova measures azimuth from south towards west */ double az = range360(lnaltaz.az + 180); double al = lnaltaz.alt; return GotoAzAlt(az, al); } // Synscan accepts J2000 coordinates so we need to convert from JNow to J2000 ln_get_equ_prec2(&epochPos, ln_get_julian_from_sys(), JD2000, &J2000Pos); // Mount deals in J2000 coords. uint32_t n1 = J2000Pos.ra / 360 * 0x100000000; uint32_t n2 = J2000Pos.dec / 360 * 0x100000000; LOGF_DEBUG("Goto - JNow RA: %g JNow DE: %g J2000 RA: %g J2000 DE: %g", ra, dec, J2000Pos.ra / 15.0, J2000Pos.dec); snprintf(cmd, SYN_RES, "r%08X,%08X", n1, n2); if (sendCommand(cmd, res, 18)) { TrackState = SCOPE_SLEWING; HorizontalCoordsNP.s = IPS_BUSY; IDSetNumber(&HorizontalCoordsNP, nullptr); return true; } return false; }
bool ScopeSim::Goto(double r, double d) { targetRA = r; targetDEC = d; char RAStr[64], DecStr[64]; fs_sexa(RAStr, targetRA, 2, 3600); fs_sexa(DecStr, targetDEC, 2, 3600); ln_equ_posn lnradec { 0, 0 }; lnradec.ra = (currentRA * 360) / 24.0; lnradec.dec = currentDEC; ln_get_hrz_from_equ(&lnradec, &lnobserver, ln_get_julian_from_sys(), &lnaltaz); /* libnova measures azimuth from south towards west */ double current_az = range360(lnaltaz.az + 180); //double current_alt =lnaltaz.alt; if (current_az > MIN_AZ_FLIP && current_az < MAX_AZ_FLIP) { lnradec.ra = (r * 360) / 24.0; lnradec.dec = d; ln_get_hrz_from_equ(&lnradec, &lnobserver, ln_get_julian_from_sys(), &lnaltaz); double target_az = range360(lnaltaz.az + 180); //if (targetAz > currentAz && target_az > MIN_AZ_FLIP && target_az < MAX_AZ_FLIP) if (target_az >= current_az && target_az > MIN_AZ_FLIP) { forceMeridianFlip = true; } } TrackState = SCOPE_SLEWING; EqNP.s = IPS_BUSY; DEBUGF(INDI::Logger::DBG_SESSION, "Slewing to RA: %s - DEC: %s", RAStr, DecStr); return true; }
double ScopeSim::getAzimuth(double r, double d) { ln_equ_posn lnradec { 0, 0 }; ln_hrz_posn altaz { 0, 0 }; lnradec.ra = (r * 360) / 24.0; lnradec.dec = d; ln_get_hrz_from_equ(&lnradec, &lnobserver, ln_get_julian_from_sys(), &altaz); /* libnova measures azimuth from south towards west */ return (range360(altaz.az + 180)); }
bool SynscanDriver::ReadScopeStatus() { if (isSimulation()) { mountSim(); return true; } char res[SYN_RES] = {0}; // Goto in progress? if (sendCommand("L", res)) m_MountInfo[MI_GOTO_STATUS] = res[0]; // Pier side if (m_isAltAz == false && sendCommand("p", res)) { m_MountInfo[MI_POINT_STATUS] = res[0]; // INDI and mount pier sides are opposite to each other setPierSide(res[0] == 'W' ? PIER_EAST : PIER_WEST); } if (readTracking()) { if (TrackState == SCOPE_SLEWING) { if (isSlewComplete()) { TrackState = (m_TrackingFlag == 2) ? SCOPE_TRACKING : SCOPE_IDLE; HorizontalCoordsNP.s = (m_TrackingFlag == 2) ? IPS_OK : IPS_IDLE; IDSetNumber(&HorizontalCoordsNP, nullptr); } } else if (TrackState == SCOPE_PARKING) { if (isSlewComplete()) { HorizontalCoordsNP.s = IPS_IDLE; IDSetNumber(&HorizontalCoordsNP, nullptr); TrackState = SCOPE_PARKED; SetTrackEnabled(false); SetParked(true); } } else if (TrackState == SCOPE_IDLE && m_TrackingFlag > 0) TrackState = SCOPE_TRACKING; else if (TrackState == SCOPE_TRACKING && m_TrackingFlag == 0) TrackState = SCOPE_IDLE; } sendStatus(); // Get Precise RA/DE memset(res, 0, SYN_RES); if (!sendCommand("e", res)) return false; uint32_t n1 = 0, n2 = 0; sscanf(res, "%x,%x#", &n1, &n2); double ra = static_cast<double>(n1) / 0x100000000 * 360.0; double de = static_cast<double>(n2) / 0x100000000 * 360.0; ln_equ_posn epochPos { 0, 0 }, J2000Pos { 0, 0 }; J2000Pos.ra = range360(ra); J2000Pos.dec = rangeDec(de); // Synscan reports J2000 coordinates so we need to convert from J2000 to JNow ln_get_equ_prec2(&J2000Pos, JD2000, ln_get_julian_from_sys(), &epochPos); CurrentRA = epochPos.ra / 15.0; CurrentDE = epochPos.dec; char Axis1Coords[MAXINDINAME] = {0}, Axis2Coords[MAXINDINAME] = {0}; fs_sexa(Axis1Coords, J2000Pos.ra / 15.0, 2, 3600); fs_sexa(Axis2Coords, J2000Pos.dec, 2, 3600); LOGF_DEBUG("J2000 RA <%s> DE <%s>", Axis1Coords, Axis2Coords); memset(Axis1Coords, 0, MAXINDINAME); memset(Axis2Coords, 0, MAXINDINAME); fs_sexa(Axis1Coords, CurrentRA, 2, 3600); fs_sexa(Axis2Coords, CurrentDE, 2, 3600); LOGF_DEBUG("JNOW RA <%s> DE <%s>", Axis1Coords, Axis2Coords); // Now feed the rest of the system with corrected data NewRaDec(CurrentRA, CurrentDE); // Get precise az/alt memset(res, 0, SYN_RES); if (!sendCommand("z", res)) return false; sscanf(res, "%x,%x#", &n1, &n2); double az = static_cast<double>(n1) / 0x100000000 * 360.0; double al = static_cast<double>(n2) / 0x100000000 * 360.0; al = rangeDec(al); HorizontalCoordsN[AXIS_AZ].value = az; HorizontalCoordsN[AXIS_ALT].value = al; memset(Axis1Coords, 0, MAXINDINAME); memset(Axis2Coords, 0, MAXINDINAME); fs_sexa(Axis1Coords, az, 2, 3600); fs_sexa(Axis2Coords, al, 2, 3600); LOGF_DEBUG("AZ <%s> ALT <%s>", Axis1Coords, Axis2Coords); IDSetNumber(&HorizontalCoordsNP, nullptr); return true; }
void DomeScript::TimerHit() { if (!isConnected()) return; char name[1024]={0}; // N.B. INDI_UNUSED to make it compile on MacOS // DO NOT CHANGE char *s = tmpnam(name); INDI_UNUSED(s); bool status = RunScript(SCRIPT_STATUS, name, nullptr); if (status) { int parked = 0, shutter = 0; float az = 0; FILE *file = fopen(name, "r"); int ret = 0; ret = fscanf(file, "%d %d %f", &parked, &shutter, &az); fclose(file); unlink(name); DomeAbsPosN[0].value = az = round(range360(az) * 10) / 10; if (parked != 0) { if (getDomeState() == DOME_PARKING || getDomeState() == DOME_UNPARKED) { SetParked(true); TargetAz = az; LOG_INFO("Park succesfully executed"); } } else { if (getDomeState() == DOME_UNPARKING || getDomeState() == DOME_PARKED) { SetParked(false); TargetAz = az; LOG_INFO("Unpark succesfully executed"); } } if (std::round(az * 10) != std::round(TargetAz * 10)) { LOGF_INFO("Moving %g -> %g %d", std::round(az * 10) / 10, std::round(TargetAz * 10) / 10, getDomeState()); IDSetNumber(&DomeAbsPosNP, nullptr); } else if (getDomeState() == DOME_MOVING) { setDomeState(DOME_SYNCED); IDSetNumber(&DomeAbsPosNP, nullptr); } if (shutterState == SHUTTER_OPENED) { if (shutter == 0) { shutterState = SHUTTER_CLOSED; DomeShutterSP.s = IPS_OK; IDSetSwitch(&DomeShutterSP, nullptr); LOG_INFO("Shutter was succesfully closed"); } } else { if (shutter == 1) { shutterState = SHUTTER_OPENED; DomeShutterSP.s = IPS_OK; IDSetSwitch(&DomeShutterSP, nullptr); LOG_INFO("Shutter was succesfully opened"); } } } else { LOG_ERROR("Failed to read status"); } SetTimer(POLLMS); if (!isParked() && TimeSinceUpdate++ > 4) { TimeSinceUpdate = 0; UpdateMountCoords(); } }
void DomeSim::TimerHit() { int nexttimer=1000; if(isConnected() == false) return; // No need to reset timer if we are not connected anymore if (DomeAbsPosNP.s == IPS_BUSY) { if (targetAz > DomeAbsPosN[0].value) { DomeAbsPosN[0].value += DOME_SPEED; } else if (targetAz < DomeAbsPosN[0].value) { DomeAbsPosN[0].value -= DOME_SPEED; } DomeAbsPosN[0].value = range360(DomeAbsPosN[0].value); if (fabs(targetAz - DomeAbsPosN[0].value) <= DOME_SPEED) { DomeAbsPosN[0].value = targetAz; DEBUG(INDI::Logger::DBG_SESSION, "Dome reached requested azimuth angle."); if (getDomeState() == DOME_PARKING) SetParked(true); else if (getDomeState() == DOME_UNPARKING) SetParked(false); else setDomeState(DOME_SYNCED); } IDSetNumber(&DomeAbsPosNP, NULL); } if (DomeShutterSP.s == IPS_BUSY) { if (shutterTimer-- <= 0) { shutterTimer=0; DomeShutterSP.s = IPS_OK; DEBUGF(INDI::Logger::DBG_SESSION, "Shutter is %s.", (DomeShutterS[0].s == ISS_ON ? "open" : "closed")); IDSetSwitch(&DomeShutterSP, NULL); if (getDomeState() == DOME_UNPARKING) SetParked(false); } } SetTimer(nexttimer); // Not all mounts update ra/dec constantly if tracking co-ordinates // This is to ensure our alt/az gets updated even if ra/dec isn't being updated // Once every 10 seconds is more than sufficient // with this added, dome simulator will now correctly track telescope simulator // which does not emit new ra/dec co-ords if they are not changing if(isParked() == false && TimeSinceUpdate++ > 9) { TimeSinceUpdate=0; UpdateMountCoords(); } return; }