1
$\begingroup$

It took some effort, but in the end, I successfully calculated the geographical point of the Sun. I assumed that I could do the same for the Moon.

My plan is:

  1. Find RA and declination of the Moon
  2. Find GHA of the Moon, using the same math as for the Sun

However, after following this article almost to the letter (except for precession and perturbations), my calculated answer is much different from this site. I've examined the article and my code many times, but can't see an error.

I use Swift programming language, but here it's merely a way to represent my calculations and results.

my code and results

If anyone would like to try it for yourself, here's my code in text format:

import Foundation

extension Double {
  var radians: Double {
    return self * .pi / 180
  }

  var degrees: Double {
    return self  * 180 / .pi
  }

  var rangedUpTo360: Double {
    let multiples = (self/360).rounded(.down)
    return self - 360*multiples
  }

  var rangedUpTo86400: Double {
    let multiples = (self/86400).rounded(.down)
    return self - 86400*multiples
  }
}

extension Date {
  var greenwich: Date {
    let greenwichDate = self.addingTimeInterval(TimeInterval(-TimeZone.current.secondsFromGMT()))
    return greenwichDate
  }
}

class Astronomy {

  static func julianDays(since: Date) -> Double {
    return since.timeIntervalSince1970 / 86400 + 2_440_587.5
  }

  static func daysSinceJ2000(for date: Date) -> Double {
    return julianDays(since: date) - 2_451_545
  }

  static func sunAxialTilt(for daysSinceJ200: Double) -> Double {
    return 23.4393 - 3.563e-7 * daysSinceJ200
  }

  static func greenwichHourAngle(rightAscension: Double, date: Date) -> Double {
    let greenwichTimeZone = TimeZone(secondsFromGMT: 0)!
    var calendar = Calendar.current
    calendar.timeZone = greenwichTimeZone
    let components = calendar.dateComponents([.hour, .minute, .second], from: date)
    let secondsOfDay = Double(components.hour!)*3600 + Double(components.minute!)*60 + Double(components.second!)

    let centuriesSinceJ200 = daysSinceJ2000(for: date.greenwich) / 36525
    let greenwichSiderealTime = 24110.54841 + 8640184.812866*centuriesSinceJ200 + 0.093104*pow(centuriesSinceJ200, 2) - 0.0000062*pow(centuriesSinceJ200, 3)
    let earthSiderealRotationRate = 1.00273790935 + 5.9e-11*centuriesSinceJ200
    let earthRotation = earthSiderealRotationRate*secondsOfDay
    let gmstSeconds = greenwichSiderealTime + earthRotation
    let gmstSecondsNormalized = gmstSeconds.rangedUpTo86400
    let gmst = gmstSecondsNormalized / 3600 * 15
    return gmst.rangedUpTo360 - rightAscension
  }

  static func moonPosition(on date: Date) -> (declination: Double, RA: Double, distance: Double) {
    date
    // day number
    let d = daysSinceJ2000(for: date)
    // longitude of the ascending node
    var N = 125.1228 - 0.0529538083 * d // have to be normalized
    if N < 0 {
      N += 360
    }
    // inclination to the ecliptic (plane of the Earth's orbit)
    let i = 5.1454
    // argument of perihelion
    var w = 318.0634 + 0.1643573223 * d // have to be normalized
    w = w.rangedUpTo360
    // semi-major axis, or mean distance from Sun
    let a = 60.2666 // (Earth radii)
    // eccentricity (0=circle, 0-1=ellipse, 1=parabola)
    let e = 0.054900
    // mean anomaly (0 at perihelion; increases uniformly with time)
    var M = 115.3654 + 13.0649929509 * d // have to be normalized
    M = M.rangedUpTo360
    // eccentric anomaly
    let E = M + e * sin(M.radians) * (1.0 + e * cos(M.radians))
    let xv = a * (cos(E.radians) - e)
    let yv = a * (sqrt(1.0 - e*e) * sin(E.radians))
    // true anomaly (angle between position and perihelion)
    let v = atan2(yv, xv).degrees
    let r = sqrt(pow(xv, 2) + pow(yv, 2))
    // geocentric ecliptical position
    let xG = r * (cos(N.radians) * cos((v + w).radians) - sin(N.radians) * sin((v + w).radians) * cos(i.radians))
    let yG = r * (sin(N.radians) * cos((v + w).radians) + cos(N.radians) * sin((v + w).radians) * cos(i.radians))
    let zG = r * (sin((v + w).radians) * sin(i.radians))
    // equatorial coordinates
    let ecl = sunAxialTilt(for: d)
    let xE = xG
    let yE = yG * cos(ecl.radians) - zG * sin(ecl.radians)
    let zE = yG * sin(ecl.radians) + zG * cos(ecl.radians)
    //right scension
    var rA = atan2(yE, xE)
    rA = rA.degrees
    // declinatino
    var dec = atan2(zE, sqrt(xE * xE + yE * yE) )
    dec = dec.degrees
    // geocentric distance
    let rG = sqrt(xE * xE + yE * yE + zE * zE)
    return (declination: dec, RA: rA, distance: rG)
  }
}

Astronomy.moonPosition(on: Date().greenwich)
$\endgroup$
  • 1
    $\begingroup$ How big are the errors that you are seeing ? I compared theskylive.com link you gave and the apparent Moon position it gave for Greenwich at 2019-02-09 16:52 UTC was off by (2.8,-37.2) arcminutes in RA,Dec respectively compared to JPL HORIZONS and SLALIB. As noted in the njsas.org article, you need the perturbations included to get the position better than 2 degrees - the Moon is so close and moves relatively quickly that small errors in time etc get magnified. Lunar motion theory is surprisingly complicated $\endgroup$ – astrosnapper Feb 9 at 18:03
  • $\begingroup$ @astrosnapper My code returns these values for Feb 9, 2019 at 8:16 PM: - RA: -0.5199 - Dec: -5.1769 While the website returns: - RA: 15.56 - Dec: 1.073 If it were to the lack of perturbation calculations, shouldn't the difference be in 2 degrees range? Somewhere I read that if atan2 returns a negative number in the calculations, I need to add .pi to it. Is it so? And does it mean I have to add 3.14 or 180? I tried though, but it results in a much bigger error. $\endgroup$ – ethamine Feb 9 at 20:57
  • $\begingroup$ Here's what I get using njsas's formulae for your datetime (assuming it's UTC , for the geocenter and without the perturbations): N=115.460502, i=5.1454, w=25.416300,a=60.2666,e=0.0549, M=240.048858 (N,i,w,M are in degrees, a in Earth radii, e unitless). xg,yg,zg are (60.938805003268435, 9.606098833264198, -5.326251364267174) and obliquity of the ecliptic, ecl=23.436812725124444 degrees. This gives RA=0.17750561458751776, Dec= -0.017218433367563225 (both radians) or 00h40m40.88s -00d 59' 11.56". HORIZONS gives: 01 03 06.19 +01 09 42.9 so ~2deg out in Dec $\endgroup$ – astrosnapper Feb 10 at 19:28
  • $\begingroup$ One thing to be careful is whether your quantities are in the right units. In the njsas formulae many things are done in degrees initially but there seems to be some missing conversions to radians when used in trig functions. For the eccentric anomaly, E, both the sin(M) and cos(M) need conversions. Similarly the use of E in the xv,yv formulae (Sec. 6) need converting as does the use of N and i in the formula for 3D position (Sec. 7) and ecl in the conversion from ecliptic to equatorial (Sec. 12). $\endgroup$ – astrosnapper Feb 10 at 19:36
  • $\begingroup$ Hm, for the same date (Feb 9 20:16) I get these results: d=6979.2194; N=115.5465; i=same; w=25.1492; a=same; e=same; M=218.8182; E=218.7853; xg,yg zg=(62.5865, -2.7821, -4.9766); ecl=23.4368; RA=-0.0091580905076487; declination=-0.09038631707987221; Which is different on more then 2 degrees from yours. Would you mind sharing what was your d, E, xV, yV and v? I believe I've handled the conversions properly, as all the sin/cos inputs in my code get converted to radians. ".degrees" and ".radians" in my code convert the value to from rad to degrees and from degrees to rad respectfully $\endgroup$ – ethamine Feb 11 at 18:27

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Browse other questions tagged or ask your own question.