// calculations for moon rise/set times are based on http://www.stargazing.net/kepler/moonrise.html article public moonRiseSet getMoonTimes(long date, double lat, double lng, bool inUTC) { long t = date; // if (inUTC) t.setUTCHours(0, 0, 0, 0); // else t.setHours(0, 0, 0, 0); double hc = 0.133 * rad; AltAz gmp = getMoonPosition(t, lat, lng); double h0 = gmp.Alt - hc, h1, h2, rise = 0.0, set = 0.0, a, b, xe, ye = 0.0, d, roots, x1 = 0.0, x2 = 0.0, dx; // go in 2-hour chunks, each time seeing if a 3-point quadratic curve crosses zero (which means rise or set) for (var i = 1; i <= 24; i += 2) { AltAz gmp1 = getMoonPosition(hoursLater(t, i), lat, lng); AltAz gmp2 = getMoonPosition(hoursLater(t, i + 1), lat, lng); h1 = gmp1.Alt - hc; h2 = gmp2.Alt - hc; a = (h0 + h2) / 2 - h1; b = (h2 - h0) / 2; xe = -b / (2 * a); ye = (a * xe + b) * xe + h1; d = b * b - 4 * a * h1; roots = 0; x1 = 0.0; x2 = 0.0; if (d >= 0) { dx = Math.Sqrt(d) / (Math.Abs(a) * 2); x1 = xe - dx; x2 = xe + dx; if (Math.Abs(x1) <= 1) { roots++; } if (Math.Abs(x2) <= 1) { roots++; } if (x1 < -1) { x1 = x2; } } if (roots == 1) { if (h0 < 0) { rise = (double)i + x1; } else { set = i + x1; } } else if (roots == 2) { rise = i + (ye < 0 ? x2 : x1); set = i + (ye < 0 ? x1 : x2); } if (rise != 0.0 && set != 0.0) { break; } h0 = h2; } var result = new moonRiseSet(); if (rise != 0.0) { result.riseTime = hoursLater(t, (int)rise); } if (set != 0) { result.settime = hoursLater(t, (int)set); } if (rise == 0.0 && set == 0.0) { result.state = ye > 0 ? "alwaysUp" : "alwaysDown"; } return(result); }
//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(); } } }