public AltAz getMoonPosition(long date, double lat, double lng) { double lw = rad * -lng, phi = rad * lat, d = toDays(date); RaDec c = moonCoords(d); double H = siderealTime(d, lw) - c.RA, h = altitude(H, phi, c.Dec), // formula 14.1 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. pa = Math.Atan2(Math.Sin(H), Math.Tan(phi) * Math.Cos(c.Dec) - Math.Sin(c.Dec) * Math.Cos(H)); double refraction = astroRefraction(h); h = h + refraction; // altitude correction for refraction refraction = refraction / rad; ///HACK HACK magic offsets .76 and .985 determined empirically /// return(new AltAz() { Az = azimuth(H, phi, c.Dec) * dar + 180.0 - 0.76, Alt = h * dar - 0.985, distance = c.distance, paralacticAngle = pa }); }
/// <summary> /// </summary> /// <param name="Alt">The Altitude (90-elevation) in decimal degrees</param> /// <param name="Az">The Azimuth in decimal degrees</param> /// <param name="Lat">The latitude in decimal degrees</param> /// <param name="Long">The longitude in decimal value</param> /// <param name="Date">The date(time) in UTC</param> /// <returns>The Right Ascentsion and Decination decimal value</returns> public static RaDec CalcualteRaDec(double Alt, double Az, double Lat, double Long, DateTime Date) { double temp, sin_dec, lat = Lat * (Math.PI / 180); double cos_lat = Math.Cos(lat); double alt, az, dec, ha, ra; alt = Alt * (Math.PI / 180); az = Az * (Math.PI / 180); if (alt > Math.PI / 2.0) { alt = Math.PI - alt; az += Math.PI; } if (alt < -Math.PI / 2.0) { alt = -Math.PI - alt; az -= Math.PI; } sin_dec = Math.Sin(lat) * Math.Sin(alt) + cos_lat * Math.Cos(alt) * Math.Cos(az); dec = Math.Asin(sin_dec); if (cos_lat < .00001) /* polar case */ { ha = az + Math.PI; } else { temp = cos_lat * Math.Cos(dec); temp = (Math.Sin(alt) - Math.Sin(lat) * sin_dec) / temp; if (temp > 1.0) { temp = 1.0; } temp = Math.Acos(-temp); ///THIS WAS BACKWARDS! if (Math.Sin(az) < 0.0) { ha = Math.PI - temp; } else { ha = Math.PI + temp; } } double dayOffset = (Date - new DateTime(2000, 1, 1, 12, 0, 0, DateTimeKind.Utc)).TotalDays; double LST = (100.46 + 0.985647 * dayOffset + Long + 15 * (Date.Hour + Date.Minute / 60d) + 360) % 360; ra = (LST - (ha * 180.0 / Math.PI) + 360) % 360; RaDec rd = new RaDec() { RA = ra * 24 / 360, Dec = dec * 180.0 / Math.PI }; rd.Normalize(); return(rd); }
// calculates sun position for a given date and latitude/longitude public AltAz getPosition(int date, double lat, double lng) { double lw = rad * -lng, phi = rad * lat, d = toDays(date); RaDec c = sunCoords(d); double H = siderealTime(d, lw) - c.RA; return(new AltAz() { Az = azimuth(H, phi, c.Dec) * dar + 180.0, Alt = altitude(H, phi, c.Dec) * dar }); }
// calculations for illumination parameters of the moon, // based on http://idlastro.gsfc.nasa.gov/ftp/pro/astro/mphase.pro formulas and // Chapter 48 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. public illumination getMoonIllumination(long date) { double d = toDays(date); RaDec s = sunCoords(d), m = moonCoords(d); double sdist = 149598000, // distance from Earth to Sun in km phi = Math.Acos(Math.Sin(s.Dec) * Math.Sin(m.Dec) + Math.Cos(s.Dec) * Math.Cos(m.Dec) * Math.Cos(s.RA - m.RA)), inc = Math.Atan2(sdist * Math.Sin(phi), m.distance - sdist * Math.Cos(phi)), angle = Math.Atan2(Math.Cos(s.Dec) * Math.Sin(s.RA - m.RA), Math.Sin(s.Dec) * Math.Cos(m.Dec) - Math.Cos(s.Dec) * Math.Sin(m.Dec) * Math.Cos(s.RA - m.RA)); return(new illumination() { fraction = (1 + Math.Cos(inc)) / 2, phase = 0.5 + 0.5 * inc * (angle < 0 ? -1 : 1) / Math.PI, angle = angle }); }
private void presetSelector_SelectedIndexChanged(object sender, EventArgs e) { int item = presetSelector.SelectedIndex; if (item != 0) { this.azCommand = this.Presets[item].Az; this.elCommand = this.Presets[item].El; GeoAngle mAzAngle = GeoAngle.FromDouble(azCommand, true); GeoAngle mElAngle = GeoAngle.FromDouble(elCommand); this.commandAz.Text = string.Format("{0} : {1}", mAzAngle.Degrees, mAzAngle.Minutes); this.commandEl.Text = string.Format("{0} : {1}", mElAngle.Degrees, mElAngle.Minutes); RaDec astro = celestialConversion.CalcualteRaDec(mElAngle.ToDouble(), mAzAngle.ToDouble(), settings.latitude, settings.longitude); GeoAngle Dec = GeoAngle.FromDouble(astro.Dec); GeoAngle RA = GeoAngle.FromDouble(astro.RA, true); this.commandRA.Text = string.Format("{0:D3} : {1:D2}", RA.Degrees, RA.Minutes); this.commandDec.Text = string.Format("{0:D2} : {1:D2}", Dec.Degrees, Dec.Minutes); } }
private void SouthPark_Click(object sender, EventArgs e) { azCommand = settings.azSouthPark; elCommand = settings.elSouthPark; GeoAngle mAzAngle = GeoAngle.FromDouble(azCommand, true); GeoAngle mElAngle = GeoAngle.FromDouble(elCommand); this.commandAz.Text = string.Format("{0} : {1}", mAzAngle.Degrees, mAzAngle.Minutes); this.commandEl.Text = string.Format("{0} : {1}", mElAngle.Degrees, mElAngle.Minutes); RaDec astro = celestialConversion.CalcualteRaDec(mElAngle.ToDouble(), mAzAngle.ToDouble(), settings.latitude, settings.longitude); GeoAngle Dec = GeoAngle.FromDouble(astro.Dec); GeoAngle RA = GeoAngle.FromDouble(astro.RA, true); this.commandRA.Text = string.Format("{0:D3} : {1:D2}", RA.Degrees, RA.Minutes); this.commandDec.Text = string.Format("{0:D2} : {1:D2}", Dec.Degrees, Dec.Minutes); this.state = DishState.Parking;; azPid.Enable(); elPid.Enable(); }
//update position display private void updatePosition() { if ((DateTime.Now - messageTime).TotalSeconds > 30) { Message.Text = ""; } //read actual form encoders //if (dev.Connected && state == DishState.Stopped) //{ // azPos = azReadPosition(); // elPos = elReadPosition(); //} //set up display variables in deg, min, sec format GeoAngle AzAngle = GeoAngle.FromDouble(azPos, true); GeoAngle ElAngle = GeoAngle.FromDouble(elPos); //convert to RA/DEC RaDec astro = celestialConversion.CalcualteRaDec(elPos, azPos, settings.latitude, settings.longitude); //set up RA DEC as deg,min,sec GeoAngle Dec = GeoAngle.FromDouble(astro.Dec); GeoAngle RA = GeoAngle.FromDouble(astro.RA, true); //log position every tenth time through string posLog = string.Format("RA {0:D3} : {1:D2}\t DEC {2:D3} : {3:D2}", RA.Degrees, RA.Minutes, Dec.Degrees, Dec.Minutes); currentIncrement++; if (currentIncrement % 9 == 0) { RollingLogger.LogMessage(posLog); currentIncrement = 0; } //show AZ, EL on main form this.Azimuth.Text = string.Format("{0:D3} : {1:D2}", AzAngle.Degrees, AzAngle.Minutes); this.Elevation.Text = string.Format("{0:D2} : {1:D2}", ElAngle.Degrees, ElAngle.Minutes); //show RA,DEC on main form this.RA.Text = string.Format("{0:D3} : {1:D2}", RA.Degrees, RA.Minutes); this.DEC.Text = string.Format("{0:D2} : {1:D2}", Dec.Degrees, Dec.Minutes); //if celestial track is set, check to make sure command position is above horizon if so then enable motion //probably have to have a completely seperate velocity track loop here - PID loop may not be satisfactor //-----NEEDS TESTING if (trackCelestial) { AltAz aa = celestialConversion.CalculateAltAz(RAcommand, decCommand, settings.latitude, settings.longitude); if (aa.Alt < 0) { Message.Text = "Requested position is below horizon!"; trackMoon = false; messageTime = DateTime.Now; trackCelestial = false; } GeoAngle cAzAngle = GeoAngle.FromDouble(aa.Az, true); GeoAngle cElAngle = GeoAngle.FromDouble(aa.Alt); azCommand = aa.Az; elCommand = aa.Alt; this.commandAz.Text = string.Format("{0:D3} : {1:D2}", cAzAngle.Degrees, cAzAngle.Minutes); this.commandEl.Text = string.Format("{0:D2} : {1:D2}", cElAngle.Degrees, cElAngle.Minutes); if (state != DishState.Moving && state != DishState.Tracking && aa.Alt > 1.0) { this.Go(); } } //if Lunar track is set, check to make sure Moon position is above horizon if so then enable motion //probably have to have a completely seperate velocity track loop here - PID loop may not be satisfactor //-----NEEDS TESTING if (trackMoon) { SunCalc sc = new SunCalc(); long eDate = sc.epochDate(DateTime.UtcNow); double jdate = sc.toJulian(eDate); AltAz aa = sc.getMoonPosition(eDate, settings.latitude, settings.longitude); if (aa.Alt < 0) { Message.Text = "Moon is below horizon!"; trackMoon = false; messageTime = DateTime.Now; } moonRiseSet mrs = sc.getMoonTimes(eDate, settings.latitude, settings.longitude, true); azCommand = aa.Az; elCommand = aa.Alt; GeoAngle mAzAngle = GeoAngle.FromDouble(aa.Az, true); GeoAngle mElAngle = GeoAngle.FromDouble(aa.Alt); this.commandAz.Text = string.Format("{0} : {1}", mAzAngle.Degrees, mAzAngle.Minutes); this.commandEl.Text = string.Format("{2}{0} : {1}", mElAngle.Degrees, mElAngle.Minutes, mElAngle.IsNegative ? "-" : ""); double Alt = elCommand; if (Alt > 90.0) { Alt = Alt - 90.0; } RaDec mastro = celestialConversion.CalcualteRaDec(Alt, azCommand, settings.latitude, settings.longitude); GeoAngle mDec = GeoAngle.FromDouble(mastro.Dec); GeoAngle mRA = GeoAngle.FromDouble(mastro.RA, true); this.commandRA.Text = string.Format("{0:D3} : {1:D2}", mRA.Degrees, mRA.Minutes); this.commandDec.Text = string.Format("{0:D2} : {1:D2}", mDec.Degrees, mDec.Minutes); if (state != DishState.Moving && state != DishState.Tracking && aa.Alt > 1.0) { this.Go(); } }//trackMoon //send stop command if we have to here if (state != DishState.Stopped && state != DishState.Unknown) { if (azPid.Complete && elPid.Complete) { this.Stop(); } } }