While trying to convert ecliptic coordinates from mean equinox of date to true equinox of date, I ran into excessive overhead from the IAU2000B nutation model. The fact that it uses 77 trigonometric terms made the calculations a lot slower. https://apps.dtic.mil/sti/pdfs/AD1112517.pdf Page 4 in the above document mentions a shorter series “NOD version 2” that has 13 terms instead of 77 as used in IAU2000B. I had not noticed NOD2 before, because it appears only in the FORTRAN version of NOVAS 3.x, not the C version. After reading the FORTRAN code, I realized NOD2 is the same as IAU2000B, only it keeps the first 13 of 77 terms. The terms are already arranged in descending order of significance, so it is easy to truncate the series. Based on this discovery, I realized I could achieve all of the required accuracy needed for Astronomy Engine by keeping only the first 5 terms of the nutation series. This tremendously speeds up nutation calculations while sacrificing only a couple of arcseconds of accuracy. It also makes the minified JavaScript code smaller: Before: 119500 bytes. After: 116653 bytes. So that's what I did here. Most of the work was updating unit tests for accepting slightly different calculation results. The nutation formula change did trigger detection of a lurking bug in the inverse_terra functions, which convert a geocentric vector into latitude, longitude, and elevation (i.e. an Observer object). The Newton's Method loop in this function was not always converging, resulting in an infinite loop. I fixed that by increasing the convergence threshold and throwing an exception if the loop iterates more than 10 times. I also fixed a couple of bugs in the `demotest` scripts.
Supported Programming Languages
|
C
|
Examples | |
|
C#
|
Examples | |
|
JavaScript
|
Examples
|
|
|
Python
|
Examples | |
|
Kotlin / JVM
|
Examples
|
Overview
Astronomy Engine is a suite of open source libraries for calculating positions of the Sun, Moon, and planets, and for predicting interesting events like oppositions, conjunctions, rise and set times, lunar phases, eclipses, transits, and more.
It supports several popular programming langauges with a consistent API. Function and type names are mostly consistent across all the supported languages.
Astronomy Engine is designed to be small, fast, and accurate to within ±1 arcminute. It is based on the authoritative and well-tested models VSOP87 and NOVAS C 3.1.
These libraries are rigorously unit-tested against NOVAS, JPL Horizons, and other reliable sources of ephemeris data. Calculations are also verified to be identical among all the supported programming languages.
Features
-
Provides calculations for the Sun, Moon, Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune, and Pluto.
-
Calculates all supported objects for any calendar date and time for millennia before or after the present.
-
Provides heliocentric and geocentric Cartesian vectors of all the above bodies.
-
Determines apparent horizon-based positions for an observer anywhere on the Earth, given that observer's latitude, longitude, and elevation in meters. Optionally corrects for atmospheric refraction.
-
Calculates rise, set, and culmination times of Sun, Moon, and planets.
-
Finds civil, nautical, and astronomical twilight times (dusk and dawn).
-
Finds date and time of Moon phases: new, first quarter, full, third quarter (or anywhere in between as expressed in degrees of ecliptic longitude).
-
Predicts lunar and solar eclipses.
-
Predicts transits of Mercury and Venus.
-
Predicts lunar apogee and perigee dates, times, and distances.
-
Predicts date and time of equinoxes and solstices for a given calendar year.
-
Determines apparent visual magnitudes of all the supported celestial bodies.
-
Predicts dates of planetary conjunctions, oppositions, and apsides.
-
Predicts dates of Venus' peak visual magnitude.
-
Predicts dates of maximum elongation for Mercury and Venus.
-
Calculates the positions of Jupiter's four largest moons: Io, Europa, Ganymede, and Callisto.
-
Allows custom simulation of the movements of user-defined small bodies, such as asteroids and comets, through the Solar System.
-
Converts angular and vector coordinates among the following orientations:
- Equatorial J2000
- Equatorial equator-of-date
- Ecliptic J2000
- Topocentric Horizontal
- Galactic (IAU 1958)
-
Determines which constellation contains a given point in the sky.
-
Calculates libration of the Moon.
-
Calculates axis orientation and rotation angles for the Sun, Moon, and planets.
Why I Created This Thing
I have been an amateur astronomer since childhood. I still remember the amazement I felt when I saw Saturn through a backyard telescope for the first time. As a software developer, I naturally became interested in combining my love of astronomy with my computer programming skills.
In 2008, I started to learn about formulas for calculating positions of the Moon and planets. I discovered many wonderful resources, including
- Paul Schlyter's lucid and educational page How to compute planetary positions.
- Practical Astronomy with your Calculator, third edition, by Peter Duffett-Smith, Cambridge University Press. ISBN 0 521 35629 6.
- Astronomy on the Personal Computer by Oliver Montenbruck and Thomas Pfleger. ISBN-13: 978-3540672210.
I implemented algorithms based on these resources. Over time, however, I noticed that they were not quite as accurate as I would like. Their calculated positions differed from those reported by online tools like JPL Horizons and Heavens Above by large fractions of a degree in many cases.
In 2019 I renewed my interest in astronomy calculations, with the goal of creating something more accurate that could be written in JavaScript to run inside a browser. I studied how professional astronomers and space agencies did their calculations. First I looked the United States Naval Observatory's NOVAS C 3.1 library. I quickly realized it could not be ported to the browser environment, because it required very large (hundreds of megabytes) precomputed ephemeris files.
This led in turn to studying the French Bureau des Longitudes model known as VSOP87. It requires more computation but the data is much smaller, consisting of trigonometric power series coefficients. However, it was still too large to fit in a practical web page.
Furthermore, these models were extremely complicated, and far more accurate than what I needed. NOVAS, for example, performs relativistic calculations to correct for the bending of light through the gravitational fields of planets, and time dilation due to different non-intertial frames of reference! My humble needs did not require this herculean level of complexity. So I decided to create Astronomy Engine with the following engineering goals:
- Support JavaScript, C, C#, and Python with the same algorithms, and verify them to produce identical results. (Kotlin support was added in 2022.)
- No external dependencies! The code must not require anything outside the standard library for each language.
- Minified JavaScript code less than 120K. (The current size is 116653 bytes.)
- Accuracy always within 1 arcminute of results from NOVAS.
- It would be well documented, relatively easy to use, and support a wide variety of common use cases.
The solution I settled on was to truncate the VSOP87 series to make it as small as possible without exceeding the 1 arcminute error threshold. I created a code generator that converts the truncated tables into C, C#, JavaScript, and Python source code. Then I built unit tests that compare the calculations against the NOVAS C 3.1 code operating on the DE405 ephemeris and other authoritative sources, including the JPL Horizons tool. Basing on VSOP87 and verifying against independent trusted sources provides extra confidence that everything is correct.
Pluto was a special case, because VSOP87 does not include a model for it. I ended up writing a custom gravitation simulator for the major outer planets to model Pluto's orbit. The results are verified against NOVAS and the model TOP2013.
As far as I know, Astronomy Engine is the only open source solution in existence that combines very compact code for four major programming languages with such rigorous validation and testing at a reasonable accuracy threshold. The 1-arcminute accuracy is not good enough for spacecraft navigation, but it is good enough for most amateur uses, and allows the code to be much simpler, faster, and smaller.
I am committed to maintaining this project for the long term, and I am happy to answer questions about how to solve various astronomy calculation problems using Astronomy Engine. Feel free to reach out on the discussions page or submit a new issue.