Simon1994PlanetaryPositions.js 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530
  1. import Cartesian3 from './Cartesian3.js';
  2. import defined from './defined.js';
  3. import DeveloperError from './DeveloperError.js';
  4. import JulianDate from './JulianDate.js';
  5. import CesiumMath from './Math.js';
  6. import Matrix3 from './Matrix3.js';
  7. import TimeConstants from './TimeConstants.js';
  8. import TimeStandard from './TimeStandard.js';
  9. /**
  10. * Contains functions for finding the Cartesian coordinates of the sun and the moon in the
  11. * Earth-centered inertial frame.
  12. *
  13. * @exports Simon1994PlanetaryPositions
  14. */
  15. var Simon1994PlanetaryPositions = {};
  16. function computeTdbMinusTtSpice(daysSinceJ2000InTerrestrialTime) {
  17. /* STK Comments ------------------------------------------------------
  18. * This function uses constants designed to be consistent with
  19. * the SPICE Toolkit from JPL version N0051 (unitim.c)
  20. * M0 = 6.239996
  21. * M0Dot = 1.99096871e-7 rad/s = 0.01720197 rad/d
  22. * EARTH_ECC = 1.671e-2
  23. * TDB_AMPL = 1.657e-3 secs
  24. *--------------------------------------------------------------------*/
  25. //* Values taken as specified in STK Comments except: 0.01720197 rad/day = 1.99096871e-7 rad/sec
  26. //* Here we use the more precise value taken from the SPICE value 1.99096871e-7 rad/sec converted to rad/day
  27. //* All other constants are consistent with the SPICE implementation of the TDB conversion
  28. //* except where we treat the independent time parameter to be in TT instead of TDB.
  29. //* This is an approximation made to facilitate performance due to the higher prevalance of
  30. //* the TT2TDB conversion over TDB2TT in order to avoid having to iterate when converting to TDB for the JPL ephemeris.
  31. //* Days are used instead of seconds to provide a slight improvement in numerical precision.
  32. //* For more information see:
  33. //* http://www.cv.nrao.edu/~rfisher/Ephemerides/times.html#TDB
  34. //* ftp://ssd.jpl.nasa.gov/pub/eph/planets/ioms/ExplSupplChap8.pdf
  35. var g = 6.239996 + (0.0172019696544) * daysSinceJ2000InTerrestrialTime;
  36. return 1.657e-3 * Math.sin(g + 1.671e-2 * Math.sin(g));
  37. }
  38. var TdtMinusTai = 32.184;
  39. var J2000d = 2451545;
  40. function taiToTdb(date, result) {
  41. //Converts TAI to TT
  42. result = JulianDate.addSeconds(date, TdtMinusTai, result);
  43. //Converts TT to TDB
  44. var days = JulianDate.totalDays(result) - J2000d;
  45. result = JulianDate.addSeconds(result, computeTdbMinusTtSpice(days), result);
  46. return result;
  47. }
  48. var epoch = new JulianDate(2451545, 0, TimeStandard.TAI); //Actually TDB (not TAI)
  49. var MetersPerKilometer = 1000.0;
  50. var RadiansPerDegree = CesiumMath.RADIANS_PER_DEGREE;
  51. var RadiansPerArcSecond = CesiumMath.RADIANS_PER_ARCSECOND;
  52. var MetersPerAstronomicalUnit = 1.49597870e+11; // IAU 1976 value
  53. var perifocalToEquatorial = new Matrix3();
  54. function elementsToCartesian(semimajorAxis, eccentricity, inclination, longitudeOfPerigee, longitudeOfNode, meanLongitude, result) {
  55. if (inclination < 0.0) {
  56. inclination = -inclination;
  57. longitudeOfNode += CesiumMath.PI;
  58. }
  59. //>>includeStart('debug', pragmas.debug);
  60. if (inclination < 0 || inclination > CesiumMath.PI) {
  61. throw new DeveloperError('The inclination is out of range. Inclination must be greater than or equal to zero and less than or equal to Pi radians.');
  62. }
  63. //>>includeEnd('debug')
  64. var radiusOfPeriapsis = semimajorAxis * (1.0 - eccentricity);
  65. var argumentOfPeriapsis = longitudeOfPerigee - longitudeOfNode;
  66. var rightAscensionOfAscendingNode = longitudeOfNode;
  67. var trueAnomaly = meanAnomalyToTrueAnomaly(meanLongitude - longitudeOfPerigee, eccentricity);
  68. var type = chooseOrbit(eccentricity, 0.0);
  69. //>>includeStart('debug', pragmas.debug);
  70. if (type === 'Hyperbolic' && Math.abs(CesiumMath.negativePiToPi(trueAnomaly)) >= Math.acos(- 1.0 / eccentricity)) {
  71. throw new DeveloperError('The true anomaly of the hyperbolic orbit lies outside of the bounds of the hyperbola.');
  72. }
  73. //>>includeEnd('debug')
  74. perifocalToCartesianMatrix(argumentOfPeriapsis, inclination, rightAscensionOfAscendingNode, perifocalToEquatorial);
  75. var semilatus = radiusOfPeriapsis * (1.0 + eccentricity);
  76. var costheta = Math.cos(trueAnomaly);
  77. var sintheta = Math.sin(trueAnomaly);
  78. var denom = (1.0 + eccentricity * costheta);
  79. //>>includeStart('debug', pragmas.debug);
  80. if (denom <= CesiumMath.Epsilon10) {
  81. throw new DeveloperError('elements cannot be converted to cartesian');
  82. }
  83. //>>includeEnd('debug')
  84. var radius = semilatus / denom;
  85. if (!defined(result)) {
  86. result = new Cartesian3(radius * costheta, radius * sintheta, 0.0);
  87. } else {
  88. result.x = radius * costheta;
  89. result.y = radius * sintheta;
  90. result.z = 0.0;
  91. }
  92. return Matrix3.multiplyByVector(perifocalToEquatorial, result, result);
  93. }
  94. function chooseOrbit(eccentricity, tolerance) {
  95. //>>includeStart('debug', pragmas.debug);
  96. if (eccentricity < 0) {
  97. throw new DeveloperError('eccentricity cannot be negative.');
  98. }
  99. //>>includeEnd('debug')
  100. if (eccentricity <= tolerance) {
  101. return 'Circular';
  102. } else if (eccentricity < 1.0 - tolerance) {
  103. return 'Elliptical';
  104. } else if (eccentricity <= 1.0 + tolerance) {
  105. return 'Parabolic';
  106. }
  107. return 'Hyperbolic';
  108. }
  109. // Calculates the true anomaly given the mean anomaly and the eccentricity.
  110. function meanAnomalyToTrueAnomaly(meanAnomaly, eccentricity) {
  111. //>>includeStart('debug', pragmas.debug);
  112. if (eccentricity < 0.0 || eccentricity >= 1.0) {
  113. throw new DeveloperError('eccentricity out of range.');
  114. }
  115. //>>includeEnd('debug')
  116. var eccentricAnomaly = meanAnomalyToEccentricAnomaly(meanAnomaly, eccentricity);
  117. return eccentricAnomalyToTrueAnomaly(eccentricAnomaly, eccentricity);
  118. }
  119. var maxIterationCount = 50;
  120. var keplerEqConvergence = CesiumMath.EPSILON8;
  121. // Calculates the eccentric anomaly given the mean anomaly and the eccentricity.
  122. function meanAnomalyToEccentricAnomaly(meanAnomaly, eccentricity) {
  123. //>>includeStart('debug', pragmas.debug);
  124. if (eccentricity < 0.0 || eccentricity >= 1.0) {
  125. throw new DeveloperError('eccentricity out of range.');
  126. }
  127. //>>includeEnd('debug')
  128. var revs = Math.floor(meanAnomaly / CesiumMath.TWO_PI);
  129. // Find angle in current revolution
  130. meanAnomaly -= revs * CesiumMath.TWO_PI;
  131. // calculate starting value for iteration sequence
  132. var iterationValue = meanAnomaly + (eccentricity * Math.sin(meanAnomaly)) /
  133. (1.0 - Math.sin(meanAnomaly + eccentricity) + Math.sin(meanAnomaly));
  134. // Perform Newton-Raphson iteration on Kepler's equation
  135. var eccentricAnomaly = Number.MAX_VALUE;
  136. var count;
  137. for (count = 0;
  138. count < maxIterationCount && Math.abs(eccentricAnomaly - iterationValue) > keplerEqConvergence;
  139. ++count)
  140. {
  141. eccentricAnomaly = iterationValue;
  142. var NRfunction = eccentricAnomaly - eccentricity * Math.sin(eccentricAnomaly) - meanAnomaly;
  143. var dNRfunction = 1 - eccentricity * Math.cos(eccentricAnomaly);
  144. iterationValue = eccentricAnomaly - NRfunction / dNRfunction;
  145. }
  146. //>>includeStart('debug', pragmas.debug);
  147. if (count >= maxIterationCount) {
  148. throw new DeveloperError('Kepler equation did not converge');
  149. // STK Components uses a numerical method to find the eccentric anomaly in the case that Kepler's
  150. // equation does not converge. We don't expect that to ever be necessary for the reasonable orbits used here.
  151. }
  152. //>>includeEnd('debug')
  153. eccentricAnomaly = iterationValue + revs * CesiumMath.TWO_PI;
  154. return eccentricAnomaly;
  155. }
  156. // Calculates the true anomaly given the eccentric anomaly and the eccentricity.
  157. function eccentricAnomalyToTrueAnomaly(eccentricAnomaly, eccentricity) {
  158. //>>includeStart('debug', pragmas.debug);
  159. if (eccentricity < 0.0 || eccentricity >= 1.0) {
  160. throw new DeveloperError('eccentricity out of range.');
  161. }
  162. //>>includeEnd('debug')
  163. // Calculate the number of previous revolutions
  164. var revs = Math.floor(eccentricAnomaly / CesiumMath.TWO_PI);
  165. // Find angle in current revolution
  166. eccentricAnomaly -= revs * CesiumMath.TWO_PI;
  167. // Calculate true anomaly from eccentric anomaly
  168. var trueAnomalyX = Math.cos(eccentricAnomaly) - eccentricity;
  169. var trueAnomalyY = Math.sin(eccentricAnomaly) * Math.sqrt(1 - eccentricity * eccentricity);
  170. var trueAnomaly = Math.atan2(trueAnomalyY, trueAnomalyX);
  171. // Ensure the correct quadrant
  172. trueAnomaly = CesiumMath.zeroToTwoPi(trueAnomaly);
  173. if (eccentricAnomaly < 0)
  174. {
  175. trueAnomaly -= CesiumMath.TWO_PI;
  176. }
  177. // Add on previous revolutions
  178. trueAnomaly += revs * CesiumMath.TWO_PI;
  179. return trueAnomaly;
  180. }
  181. // Calculates the transformation matrix to convert from the perifocal (PQW) coordinate
  182. // system to inertial cartesian coordinates.
  183. function perifocalToCartesianMatrix(argumentOfPeriapsis, inclination, rightAscension, result) {
  184. //>>includeStart('debug', pragmas.debug);
  185. if (inclination < 0 || inclination > CesiumMath.PI) {
  186. throw new DeveloperError('inclination out of range');
  187. }
  188. //>>includeEnd('debug')
  189. var cosap = Math.cos(argumentOfPeriapsis);
  190. var sinap = Math.sin(argumentOfPeriapsis);
  191. var cosi = Math.cos(inclination);
  192. var sini = Math.sin(inclination);
  193. var cosraan = Math.cos(rightAscension);
  194. var sinraan = Math.sin(rightAscension);
  195. if (!defined(result)) {
  196. result = new Matrix3(
  197. cosraan * cosap - sinraan * sinap * cosi,
  198. -cosraan * sinap - sinraan * cosap * cosi,
  199. sinraan * sini,
  200. sinraan * cosap + cosraan * sinap * cosi,
  201. -sinraan * sinap + cosraan * cosap * cosi,
  202. -cosraan * sini,
  203. sinap * sini,
  204. cosap * sini,
  205. cosi);
  206. } else {
  207. result[0] = cosraan * cosap - sinraan * sinap * cosi;
  208. result[1] = sinraan * cosap + cosraan * sinap * cosi;
  209. result[2] = sinap * sini;
  210. result[3] = -cosraan * sinap - sinraan * cosap * cosi;
  211. result[4] = -sinraan * sinap + cosraan * cosap * cosi;
  212. result[5] = cosap * sini;
  213. result[6] = sinraan * sini;
  214. result[7] = -cosraan * sini;
  215. result[8] = cosi;
  216. }
  217. return result;
  218. }
  219. // From section 5.8
  220. var semiMajorAxis0 = 1.0000010178 * MetersPerAstronomicalUnit;
  221. var meanLongitude0 = 100.46645683 * RadiansPerDegree;
  222. var meanLongitude1 = 1295977422.83429 * RadiansPerArcSecond;
  223. // From table 6
  224. var p1u = 16002;
  225. var p2u = 21863;
  226. var p3u = 32004;
  227. var p4u = 10931;
  228. var p5u = 14529;
  229. var p6u = 16368;
  230. var p7u = 15318;
  231. var p8u = 32794;
  232. var Ca1 = 64 * 1e-7 * MetersPerAstronomicalUnit;
  233. var Ca2 = -152 * 1e-7 * MetersPerAstronomicalUnit;
  234. var Ca3 = 62 * 1e-7 * MetersPerAstronomicalUnit;
  235. var Ca4 = -8 * 1e-7 * MetersPerAstronomicalUnit;
  236. var Ca5 = 32 * 1e-7 * MetersPerAstronomicalUnit;
  237. var Ca6 = -41 * 1e-7 * MetersPerAstronomicalUnit;
  238. var Ca7 = 19 * 1e-7 * MetersPerAstronomicalUnit;
  239. var Ca8 = -11 * 1e-7 * MetersPerAstronomicalUnit;
  240. var Sa1 = -150 * 1e-7 * MetersPerAstronomicalUnit;
  241. var Sa2 = -46 * 1e-7 * MetersPerAstronomicalUnit;
  242. var Sa3 = 68 * 1e-7 * MetersPerAstronomicalUnit;
  243. var Sa4 = 54 * 1e-7 * MetersPerAstronomicalUnit;
  244. var Sa5 = 14 * 1e-7 * MetersPerAstronomicalUnit;
  245. var Sa6 = 24 * 1e-7 * MetersPerAstronomicalUnit;
  246. var Sa7 = -28 * 1e-7 * MetersPerAstronomicalUnit;
  247. var Sa8 = 22 * 1e-7 * MetersPerAstronomicalUnit;
  248. var q1u = 10;
  249. var q2u = 16002;
  250. var q3u = 21863;
  251. var q4u = 10931;
  252. var q5u = 1473;
  253. var q6u = 32004;
  254. var q7u = 4387;
  255. var q8u = 73;
  256. var Cl1 = -325 * 1e-7;
  257. var Cl2 = -322 * 1e-7;
  258. var Cl3 = -79 * 1e-7;
  259. var Cl4 = 232 * 1e-7;
  260. var Cl5 = -52 * 1e-7;
  261. var Cl6 = 97 * 1e-7;
  262. var Cl7 = 55 * 1e-7;
  263. var Cl8 = -41 * 1e-7;
  264. var Sl1 = -105 * 1e-7;
  265. var Sl2 = -137 * 1e-7;
  266. var Sl3 = 258 * 1e-7;
  267. var Sl4 = 35 * 1e-7;
  268. var Sl5 = -116 * 1e-7;
  269. var Sl6 = -88 * 1e-7;
  270. var Sl7 = -112 * 1e-7;
  271. var Sl8 = -80 * 1e-7;
  272. var scratchDate = new JulianDate(0, 0.0, TimeStandard.TAI);
  273. // Gets a point describing the motion of the Earth-Moon barycenter according to the equations described in section 6.
  274. function computeSimonEarthMoonBarycenter(date, result) {
  275. // t is thousands of years from J2000 TDB
  276. taiToTdb(date, scratchDate);
  277. var x = (scratchDate.dayNumber - epoch.dayNumber) + ((scratchDate.secondsOfDay - epoch.secondsOfDay)/TimeConstants.SECONDS_PER_DAY);
  278. var t = x / (TimeConstants.DAYS_PER_JULIAN_CENTURY * 10.0);
  279. var u = 0.35953620 * t;
  280. var semimajorAxis = semiMajorAxis0 +
  281. Ca1 * Math.cos(p1u * u) + Sa1 * Math.sin(p1u * u) +
  282. Ca2 * Math.cos(p2u * u) + Sa2 * Math.sin(p2u * u) +
  283. Ca3 * Math.cos(p3u * u) + Sa3 * Math.sin(p3u * u) +
  284. Ca4 * Math.cos(p4u * u) + Sa4 * Math.sin(p4u * u) +
  285. Ca5 * Math.cos(p5u * u) + Sa5 * Math.sin(p5u * u) +
  286. Ca6 * Math.cos(p6u * u) + Sa6 * Math.sin(p6u * u) +
  287. Ca7 * Math.cos(p7u * u) + Sa7 * Math.sin(p7u * u) +
  288. Ca8 * Math.cos(p8u * u) + Sa8 * Math.sin(p8u * u);
  289. var meanLongitude = meanLongitude0 + meanLongitude1 * t +
  290. Cl1 * Math.cos(q1u * u) + Sl1 * Math.sin(q1u * u) +
  291. Cl2 * Math.cos(q2u * u) + Sl2 * Math.sin(q2u * u) +
  292. Cl3 * Math.cos(q3u * u) + Sl3 * Math.sin(q3u * u) +
  293. Cl4 * Math.cos(q4u * u) + Sl4 * Math.sin(q4u * u) +
  294. Cl5 * Math.cos(q5u * u) + Sl5 * Math.sin(q5u * u) +
  295. Cl6 * Math.cos(q6u * u) + Sl6 * Math.sin(q6u * u) +
  296. Cl7 * Math.cos(q7u * u) + Sl7 * Math.sin(q7u * u) +
  297. Cl8 * Math.cos(q8u * u) + Sl8 * Math.sin(q8u * u);
  298. // All constants in this part are from section 5.8
  299. var eccentricity = 0.0167086342 - 0.0004203654 * t;
  300. var longitudeOfPerigee = 102.93734808 * RadiansPerDegree + 11612.35290 * RadiansPerArcSecond * t;
  301. var inclination = 469.97289 * RadiansPerArcSecond * t;
  302. var longitudeOfNode = 174.87317577 * RadiansPerDegree - 8679.27034 * RadiansPerArcSecond * t;
  303. return elementsToCartesian(semimajorAxis, eccentricity, inclination, longitudeOfPerigee,
  304. longitudeOfNode, meanLongitude, result);
  305. }
  306. // Gets a point describing the position of the moon according to the equations described in section 4.
  307. function computeSimonMoon(date, result) {
  308. taiToTdb(date, scratchDate);
  309. var x = (scratchDate.dayNumber - epoch.dayNumber) + ((scratchDate.secondsOfDay - epoch.secondsOfDay)/TimeConstants.SECONDS_PER_DAY);
  310. var t = x / (TimeConstants.DAYS_PER_JULIAN_CENTURY);
  311. var t2 = t * t;
  312. var t3 = t2 * t;
  313. var t4 = t3 * t;
  314. // Terms from section 3.4 (b.1)
  315. var semimajorAxis = 383397.7725 + 0.0040 * t;
  316. var eccentricity = 0.055545526 - 0.000000016 * t;
  317. var inclinationConstant = 5.15668983 * RadiansPerDegree;
  318. var inclinationSecPart = -0.00008 * t + 0.02966 * t2 -
  319. 0.000042 * t3 - 0.00000013 * t4;
  320. var longitudeOfPerigeeConstant = 83.35324312 * RadiansPerDegree;
  321. var longitudeOfPerigeeSecPart = 14643420.2669 * t - 38.2702 * t2 -
  322. 0.045047 * t3 + 0.00021301 * t4;
  323. var longitudeOfNodeConstant = 125.04455501 * RadiansPerDegree;
  324. var longitudeOfNodeSecPart = -6967919.3631 * t + 6.3602 * t2 +
  325. 0.007625 * t3 - 0.00003586 * t4;
  326. var meanLongitudeConstant = 218.31664563 * RadiansPerDegree;
  327. var meanLongitudeSecPart = 1732559343.48470 * t - 6.3910 * t2 +
  328. 0.006588 * t3 - 0.00003169 * t4;
  329. // Delaunay arguments from section 3.5 b
  330. var D = 297.85019547 * RadiansPerDegree + RadiansPerArcSecond *
  331. (1602961601.2090 * t - 6.3706 * t2 + 0.006593 * t3 - 0.00003169 * t4);
  332. var F = 93.27209062 * RadiansPerDegree + RadiansPerArcSecond *
  333. (1739527262.8478 * t - 12.7512 * t2 - 0.001037 * t3 + 0.00000417 * t4);
  334. var l = 134.96340251 * RadiansPerDegree + RadiansPerArcSecond *
  335. (1717915923.2178 * t + 31.8792 * t2 + 0.051635 * t3 - 0.00024470 * t4);
  336. var lprime = 357.52910918 * RadiansPerDegree + RadiansPerArcSecond *
  337. (129596581.0481 * t - 0.5532 * t2 + 0.000136 * t3 - 0.00001149 * t4);
  338. var psi = 310.17137918 * RadiansPerDegree - RadiansPerArcSecond *
  339. (6967051.4360 * t + 6.2068 * t2 + 0.007618 * t3 - 0.00003219 * t4);
  340. // Add terms from Table 4
  341. var twoD = 2.0 * D;
  342. var fourD = 4.0 * D;
  343. var sixD = 6.0 * D;
  344. var twol = 2.0 * l;
  345. var threel = 3.0 * l;
  346. var fourl = 4.0 * l;
  347. var twoF = 2.0 * F;
  348. semimajorAxis += 3400.4 * Math.cos(twoD) - 635.6 * Math.cos(twoD - l) -
  349. 235.6 * Math.cos(l) + 218.1 * Math.cos(twoD - lprime) +
  350. 181.0 * Math.cos(twoD + l);
  351. eccentricity += 0.014216 * Math.cos(twoD - l) + 0.008551 * Math.cos(twoD - twol) -
  352. 0.001383 * Math.cos(l) + 0.001356 * Math.cos(twoD + l) -
  353. 0.001147 * Math.cos(fourD - threel) - 0.000914 * Math.cos(fourD - twol) +
  354. 0.000869 * Math.cos(twoD - lprime - l) - 0.000627 * Math.cos(twoD) -
  355. 0.000394 * Math.cos(fourD - fourl) + 0.000282 * Math.cos(twoD - lprime - twol) -
  356. 0.000279 * Math.cos(D - l) - 0.000236 * Math.cos(twol) +
  357. 0.000231 * Math.cos(fourD) + 0.000229 * Math.cos(sixD - fourl) -
  358. 0.000201 * Math.cos(twol - twoF);
  359. inclinationSecPart += 486.26 * Math.cos(twoD - twoF) - 40.13 * Math.cos(twoD) +
  360. 37.51 * Math.cos(twoF) + 25.73 * Math.cos(twol - twoF) +
  361. 19.97 * Math.cos(twoD - lprime - twoF);
  362. longitudeOfPerigeeSecPart += -55609 * Math.sin(twoD - l) - 34711 * Math.sin(twoD - twol) -
  363. 9792 * Math.sin(l) + 9385 * Math.sin(fourD - threel) +
  364. 7505 * Math.sin(fourD - twol) + 5318 * Math.sin(twoD + l) +
  365. 3484 * Math.sin(fourD - fourl) - 3417 * Math.sin(twoD - lprime - l) -
  366. 2530 * Math.sin(sixD - fourl) - 2376 * Math.sin(twoD) -
  367. 2075 * Math.sin(twoD - threel) - 1883 * Math.sin(twol) -
  368. 1736 * Math.sin(sixD - 5.0 * l) + 1626 * Math.sin(lprime) -
  369. 1370 * Math.sin(sixD - threel);
  370. longitudeOfNodeSecPart += -5392 * Math.sin(twoD - twoF) - 540 * Math.sin(lprime) -
  371. 441 * Math.sin(twoD) + 423 * Math.sin(twoF) -
  372. 288 * Math.sin(twol - twoF);
  373. meanLongitudeSecPart += -3332.9 * Math.sin(twoD) + 1197.4 * Math.sin(twoD - l) -
  374. 662.5 * Math.sin(lprime) + 396.3 * Math.sin(l) -
  375. 218.0 * Math.sin(twoD - lprime);
  376. // Add terms from Table 5
  377. var twoPsi = 2.0 * psi;
  378. var threePsi = 3.0 * psi;
  379. inclinationSecPart += 46.997 * Math.cos(psi) * t - 0.614 * Math.cos(twoD - twoF + psi) * t +
  380. 0.614 * Math.cos(twoD - twoF - psi) * t - 0.0297 * Math.cos(twoPsi) * t2 -
  381. 0.0335 * Math.cos(psi) * t2 + 0.0012 * Math.cos(twoD - twoF + twoPsi) * t2 -
  382. 0.00016 * Math.cos(psi) * t3 + 0.00004 * Math.cos(threePsi) * t3 +
  383. 0.00004 * Math.cos(twoPsi) * t3;
  384. var perigeeAndMean = 2.116 * Math.sin(psi) * t - 0.111 * Math.sin(twoD - twoF - psi) * t -
  385. 0.0015 * Math.sin(psi) * t2;
  386. longitudeOfPerigeeSecPart += perigeeAndMean;
  387. meanLongitudeSecPart += perigeeAndMean;
  388. longitudeOfNodeSecPart += -520.77 * Math.sin(psi) * t + 13.66 * Math.sin(twoD - twoF + psi) * t +
  389. 1.12 * Math.sin(twoD - psi) * t - 1.06 * Math.sin(twoF - psi) * t +
  390. 0.660 * Math.sin(twoPsi) * t2 + 0.371 * Math.sin(psi) * t2 -
  391. 0.035 * Math.sin(twoD - twoF + twoPsi) * t2 - 0.015 * Math.sin(twoD - twoF + psi) * t2 +
  392. 0.0014 * Math.sin(psi) * t3 - 0.0011 * Math.sin(threePsi) * t3 -
  393. 0.0009 * Math.sin(twoPsi) * t3;
  394. // Add constants and convert units
  395. semimajorAxis *= MetersPerKilometer;
  396. var inclination = inclinationConstant + inclinationSecPart * RadiansPerArcSecond;
  397. var longitudeOfPerigee = longitudeOfPerigeeConstant + longitudeOfPerigeeSecPart * RadiansPerArcSecond;
  398. var meanLongitude = meanLongitudeConstant + meanLongitudeSecPart * RadiansPerArcSecond;
  399. var longitudeOfNode = longitudeOfNodeConstant + longitudeOfNodeSecPart * RadiansPerArcSecond;
  400. return elementsToCartesian(semimajorAxis, eccentricity, inclination, longitudeOfPerigee,
  401. longitudeOfNode, meanLongitude, result);
  402. }
  403. // Gets a point describing the motion of the Earth. This point uses the Moon point and
  404. // the 1992 mu value (ratio between Moon and Earth masses) in Table 2 of the paper in order
  405. // to determine the position of the Earth relative to the Earth-Moon barycenter.
  406. var moonEarthMassRatio = 0.012300034; // From 1992 mu value in Table 2
  407. var factor = moonEarthMassRatio / (moonEarthMassRatio + 1.0) * -1;
  408. function computeSimonEarth(date, result) {
  409. result = computeSimonMoon(date, result);
  410. return Cartesian3.multiplyByScalar(result, factor, result);
  411. }
  412. // Values for the <code>axesTransformation</code> needed for the rotation were found using the STK Components
  413. // GreographicTransformer on the position of the sun center of mass point and the earth J2000 frame.
  414. var axesTransformation = new Matrix3(1.0000000000000002, 5.619723173785822e-16, 4.690511510146299e-19,
  415. -5.154129427414611e-16, 0.9174820620691819, -0.39777715593191376,
  416. -2.23970096136568e-16, 0.39777715593191376, 0.9174820620691819);
  417. var translation = new Cartesian3();
  418. /**
  419. * Computes the position of the Sun in the Earth-centered inertial frame
  420. *
  421. * @param {JulianDate} [julianDate] The time at which to compute the Sun's position, if not provided the current system time is used.
  422. * @param {Cartesian3} [result] The object onto which to store the result.
  423. * @returns {Cartesian3} Calculated sun position
  424. */
  425. Simon1994PlanetaryPositions.computeSunPositionInEarthInertialFrame= function(julianDate, result){
  426. if (!defined(julianDate)) {
  427. julianDate = JulianDate.now();
  428. }
  429. if (!defined(result)) {
  430. result = new Cartesian3();
  431. }
  432. //first forward transformation
  433. translation = computeSimonEarthMoonBarycenter(julianDate, translation);
  434. result = Cartesian3.negate(translation, result);
  435. //second forward transformation
  436. computeSimonEarth(julianDate, translation);
  437. Cartesian3.subtract(result, translation, result);
  438. Matrix3.multiplyByVector(axesTransformation, result, result);
  439. return result;
  440. };
  441. /**
  442. * Computes the position of the Moon in the Earth-centered inertial frame
  443. *
  444. * @param {JulianDate} [julianDate] The time at which to compute the Sun's position, if not provided the current system time is used.
  445. * @param {Cartesian3} [result] The object onto which to store the result.
  446. * @returns {Cartesian3} Calculated moon position
  447. */
  448. Simon1994PlanetaryPositions.computeMoonPositionInEarthInertialFrame = function(julianDate, result){
  449. if (!defined(julianDate)) {
  450. julianDate = JulianDate.now();
  451. }
  452. result = computeSimonMoon(julianDate, result);
  453. Matrix3.multiplyByVector(axesTransformation, result, result);
  454. return result;
  455. };
  456. export default Simon1994PlanetaryPositions;