In the following post, I outline some of the challenges I faced when building jsOrrery. I won't give code examples here, as the project's code is entirely available on github at https://github.com/mgvez/jsorrery. The live project can be seen at http://mgvez.github.io/jsorrery. If you'd like a more detailed description of this or that feature, feel free to contact me and I will be glad to provide the details.
The first step in building an orrery is finding the numbers that will describe your system : planets masses, positions and velocities. With these input numbers, you can calculate the gravity forces that are acting between each of the bodies, and thus the changes in velocities over a given lapse of time. From there you can calculate the new positions after that time, and repeat the process indefinitely to have a nice animation of the movements of planets. Simple, isn't it?
The numbers I got from my sources (you can always trust Wikipedia) were scalar. I knew for example that the Earth has a mass of 5.97219×10^24 kg, an average speed of 107,200 km/h and was about 149,598,261 km from the Sun. Thing is, I did not know exactly where to put the Earth at the start of the simulation. The simulation being in 2D, I figured that I could put the Sun at the origin, and all planets lying on the x-axis at their proper distance, with their velocities perpendicular to the position of the Sun.
That setup works great in that you can look at the planets move around the Sun in what seems like an accurate representation of their orbit. But as you can imagine, the Solar System is a bit more complicated than that. In fact, I was at that point when I dropped the Flash project. You see, one gets tired quite soon of looking at meaningless dots revolving around one another. Even if each of the dots represents a planet, the positions are so grossly approximated in such a simulation that it does not teach you much about the real thing.
I was determined to input accurate positions in the system. Maybe I could hardcode numbers that would represent the state of the system at a specific date, if I could find these numbers.
I began to search for raw data, and quickly found sites like this or this, which give you a view of the Solar System as it is right now. These guys certainly did not have raw data for each day, but were calculating the position in some way. I always thought that only Nasa and maybe a few crackpot geniuses could calculate planets positions, but then I began to think that I could too.
An orbit is a trajectory that is determined by physics, but whose geometry can be described precisely. This description, in its classical form, is a set of 6 numbers called orbital elements, which can be used to calculate the position of a planet relative to the body around which it orbits. Two of these numbers describe the shape and size of the orbit and three describe its orientation. The last one indicates where on its orbit the planet could be found at a given time called the epoch.
In fact, even the 5 first elements describe the orbit at the epoch. Orbits are not only influenced by the gravity of the central body, but also by the other bodies that move in the system (among other things). Therefore, orbit shapes and orientation are not fixed and can change over time. Thankfully, these rates of change are pretty much regular, at least in a human life's scale, so we can describe them simply with a second set of 6 numbers. This set merely describe how much the first set's numbers change over a given interval, typically a century when we are talking about planets.
Since we know how much the numbers vary over time and we know what they were at the epoch, we can calculate their actual value at any time. We just have to calculate how much time has passed since the epoch, multiply it with each element's variation rate (second set) and add the result to the epoch's values (first set). When we have the exact numbers for the time at which we want to know the planet's position, the only thing that's left to do is to translate these numbers back to cartesian coordinates.
The goal of the project was to simulate the Solar System by calculating the gravitational forces, so the results given by the orbital elements were just the original state of the system at the start of simulation. Now that I had the right positions for the planets, I had to find what their velocities were at that position. The gravitational forces constantly influence the velocity vector of each planet, which makes them have a curved trajectory instead of going straight, so in order to start an animation, I had to know what was the velocity vector to act upon.
My first instinct was to calculate velocity by differentiating positions at different times. After all, velocity is exactly that : the difference between the positions of an object at the start and end of a time interval. If the calculations of orbital elements gave an accurate position, there is no reason why I couldnt get an accurate difference between two positions, even with a small time increment. I figured that a single one second interval would get me a reasonably accurate velocity reading, no need to perform a complex integration. One second at that scale is small enough to be considered instantaneous.
The result was satisfactory, except for one thing. In my Solar Sytem, I included the orbit of Halley's comet. As you may know, its orbit is in the shape of an elongated ellipse : it is highly eccentric. Eccentricity is the parameter that describes the shape of the orbit, with 0 being circular and augmenting towards 1 for flatter ellipses. One of the effects of having an eccentric orbit is that the calculations of the orbital elements become less accurate. It's not a big problem when you want an approximate position, but velocities cannot be inferred from inacurrate positions. So Halley's comet was'nt giving a damn about its trajectory, getting the hell out away in the universe.
Fortunately, there is a principle of physics that was on my side, and permits the calculation of the speed of an orbiting body from its position only : the vis-viva equation. But speed is a scalar, whereas velocity is a vector, so with vis-viva I had the length of the velocity, not its orientation. Further calculations were needed to get the orientation as well, and I ended up with a pretty good system for calculating all the initial parameters to launch the simulation.
Up to that point, I had displayed the simulation only in 2d, with the canvas through Create.js. Doing it 2d was my original intention when starting the project. I did not want a complex visualisation, just the basics to observe the orbits. Due to the nature of the calculations of the orbital elements, I did not have the choice but to use 3d vectors to compute the positions. I chose to use Three.js's Vector3 for the calculations, as I did not want to reinvent the wheel, but did not think further than that. I did my calculations, and used the x and y component to display the system from above, occasionnaly switching to x and z to see it from the side. I was so absorbed in getting the numbers right that it did not even occur to me that I could do better with the visualisation.
Then one day, like a friggin genius, I realized that I had everything I need to display the simulation in 3d. I had all the numbers in 3d, why not use the 3 compontents all at once? Instead of creating the scene in Create.js, I'd just create the scene in Three, add a camera and some lightning, and voilà! You can't imagine how the geek in me was thrilled when, in 2 hours, he passed from having no idea that he was going to do his visualisation in 3d to having it before his eyes. All the work was already done, and I had'nt realized it. I mean, I could see the Solar System in my browser in 3d, what's not exciting about that? I almost had tears of joy in my eyes.
I had some fun next positionning cameras at different places in the system. I could place a camera on the Earth, so see where the planets were in the sky relative to each other. I also textured the different planets with image maps from around the net, I played with light a little bit. I chose, though, to keep the planets to their real scale in regards to the size of their orbits, and to the Solar System as a whole. I wanted to keep a feeling of the vastness of the Solar System. Most visualisations that we see always have the planets heavily scaled up, otherwise we couldn't see them, but I thought that it gave a false impression of what the real thing is like. I eventually added the possibility to scale the planets at will in the simulation, still I prefer it to be 1:1 scale.
The moon phases
One of the things that 3d brought was the phases of the bodies, that is, the way they are lit by the Sun at any given time as seen from the Earth. The Moon has a phase that everybody is aware of, and so I thought that it would be interesting to observe it in the simulator. I just had to place the main light of the scene at the Sun's position, place a camera at the Earth's position and make it look at the Moon's.
With that setup, I could see the Moon's phase all right : going from full, waning, waxing, etc. But when comparing the simulated phases to almanachs, it was clear that the simulation was far from accurate. I was'nt able to get the accurate phase of the Moon at a given time. The reason is that the Moon's orbit around the Earth is so heavily pertubed by the Sun that it is not regular, thus it cannot be calculated from 6 elements. I had to find another way.
With these complex calculations, I was able to get the accurate phases of the Moon in the simulation.
To make the model a little bit more attractive, I thought of adding a backdrop of stars. You know those magnificient photos of the Milky Way? I even found texture maps for that, so that I could put my whole model inside a sphere with inverted normals to simulate the stars. But it did not feel right. It was so strong that you lost the planets.
I then tried to map stars from a catalog in my own texture, with the help of ImageMagick. For each star in the catalog, I'd calculate a position in the texture image, along with an alpha derived from the star's apparent magnitude and a width depending on the star's right ascension, as it was to be mapped onto a sphere. It was working quite well, but I was not satisfied with the quality when zooming. To keep a good quality, I would have had to load an unreasonably large texture file.
I finally opted to create a particle system for the stars. In it, the particles are not disseminated in a volume, but rather all positionned on the edge of a sphere big enough to contain the model. Each particle represents a star, and is calculated from data found in a star catalog. Its brighness is simulated by its size and alpha that, as in the image map solution, are calculated from the star's magnitude. The algorithm that determines those parameters is nothing scientific, but is based on what I subjectively found more pleasant to the eye. I wanted to have a lot of background stars, with the brightest standing out so you could see the constellations.
With the help of Wikipedia and topastronomer.com (whose logo is, sadly, in Comic Sans) I identified the stars in the database that make the Zodiac constellations, and I joined them with lines so you can easily spot them. I then positionned the sphere so that the star positions are mostly accurate. So for example if you place the camera on the Earth and look at Mars on a particular date, you should see it against the constellations that you would see if you were to look at it for real in the sky. To convince yourself, you can use an application such as Google Sky Map and compare.
One thing strange that I found out is that constellations are drawn from different stars, depending on which source you consult. For example, Libra (Scales) is not drawn the same way if you look at wikipedia compared to topastronomer. I don't know which one's right, I chose that is also used by Google Sky Map.
In the end, the stars that you see in the background of the simulation are made from more than 100,000 particles in WebGL. It is amazing to see how easily you can move around the camera, and WebGL does not even flinch. I have a source with more than 460,000 stars, and I can't see a degradation in performance (I still get 60fps) but I chose not to include it in the final version to save download time.
I talked a lot about setting up the simulator to visualize the Solar System, but it can in fact simulate any orbital system, provided that you have the parameters. After all, the physics that makes the Space Shuttle orbit the Earth is the exact same physics that make Jupiter orbit the Sun. When I started working on the project, my intention was to simulate spacecraft orbits around the Earth. I just started from the Solar System and diverged mostly because I was having fun exploring what I could do.
I still wanted to visualize the orbits of artificial satellites, but unfortunately, I never found complete orbital elements for any of them. For many it is possible to find partial numbers : those that describe the shape and size of the orbits, plus the inclination (which is the angle between the object's orbit and the Earth's equator). But I was never able to find the numbers that describe the orientation of the orbits.
Still, I plugged the numbers in the simulator just to have an idea of how far spacecraft and satellites orbit the Earth, which is interesting to see. For example, you can see how far GPS satellites are from the Earth, and how close manned missions are. I would like though to have the orientation as well... for now, all the satellites orbit in the same plane, which does not represent the reality.
Thank you, Internet!
I make it sound like all of this is simple stuff, but I would lie to you if I told you that I came up with it by myself like a child prodigy. The truth is that I merely plugged together concepts and numbers I found here and there on the internetz. I can't get any credit for all the clever things that happen in the simulation, as I did not invent them and never could have as I'm not an expert in any of those fields.
But that in itself is amazing : these concepts all existed separately on remote parts of the web, waiting for a guy like me to help them get together. In 1996, they would not have come together. I freaking love the internet, as it gives the possibility for people like me to access information that would otherwise be impossible to get. Most of the answers I found have never been published in books and never would have even if there were no internet.
I started the project as a way to free myself of the online world, and in the end it made me rediscover the beauty of the internet because it made me look at different parts of it. Not that I did'nt know they existed, I just never took the time to explore them a little deeper.
There are many other smaller challenges that I faced when doing the project, but these are the major ones that I can think of. I'm sure that there are ways to make this or that feature better, but in the end I am quite content with what it looks like.
I built the simulator in the best of my knowledge and understanding of the many things involved. My goal was to build a visualization of the Solar System as best as I could, but only as a hobby. I don't pretend that this project will revolutionize the way professionals look at orbital mechanics, but I sincerely hope that it will change the way you look at the night sky.
Interesting phenomenons to observe
Watching planets go around the Sun becomes boring surpizingly fast, when you consider all the work I put in it. Fortunately, that's not what's most interesting in jsOrrery. The main feature of jsOrrery is that the planets positions are accurate in regards to the date you set, and it has the consequence that you can observe things that happen in the real Solar System.
Keep in mind that I did not cheat the numbers to have the planets in these positions in the following examples, I always used the same calculations without any correction to get an expected behaviour.
The calculations for the orbit of the Moon were the most difficult to find, because the perturbations from the Sun prevented me from using the standard calculations. But they are now precise enough to observe the right lunar phases on any given date. This is the moon as it is right now as seen from the Earth: The Moon as seen from the Earth
Libration of the moon
Position of the planets relative to constellations
I have drawn the zodiac constellations in jsOrrery, so you can check at any particular date where in the sky are the planets. Just put the camera looking from the Earth, like in this scenario . Be aware that the result is not precise enough to adjust your telecope, but it gives a very good idea of the state of the sky. You can compare with other sources, for example Google Sky Map on Android devices.
This is the limit for the accuracy of the simulation. Given the size of the Sun and Moon in the sky, a great amount of precision is needed to have them both aligned perfectly to the Earth to get an eclipse. By clicking the following links, you will see the state of jsOrrery at different eclipse dates, taken from Nasa's eclipse page.
Apparent retrograde motion
An interesting thing to observe is the apparent retrograde motion of the planets. Since the Earth is in motion, when we observe other planets we sometimes have the impression that they go backwards in the sky when we pass them by on our faster orbit.
In the image above, compare the path of Mars in jsOrrery (right) to what's expected, from Wikipedia's example of the same observation (left). Also compare at the position of the path relative to the background stars.
Click and hit play to see the apparent retrograde motion of Mars in the last half of 2003 in jsOrrery
Apollo Free return trajectory
This is the most interesting thing that is possible to observe in jsOrrery. Since jsOrrery simulates gravity, it can simulate any orbital motion, not just that of the planets around the Sun. I tried to input the numbers from the Apollo mission's trajectories, and you can see the result here: Apollo free return trajectory
If you'd like to read more about how I programmed the free return trajectory, I wrote a description here.
Halley's comet orbit
I included Halley's comet in the Solar System simulation, even if its orbital elements are not precise. Halley's orbit has many perturbations, and it was not easy to find accurate elements to describe it. I have included it nonetheless as it is an interesting object.
Moon orbit is heavily perturbed
The Moon's orbit is also heavily perturbed. If the Sun and planets are not included in the scenario, its orbit is not accurate at all.
Decay of precision over time
The algorithm I use to calculate the motion of the bodies is not 100% accurate. It is good enough to view the motion of the planets over a short period of time, but if the scenario is kept playing for a long time, the positions become less and less accurate.
Further reading and resources
- Planets orbital elements from Nasa's Jet Propulsion Laboratory : http://ssd.jpl.nasa.gov/?planet_pos
- Orbit calculation from the elements by Keith Burnett : http://www.stargazing.net/kepler/ellipse.html
- Orbit calculation from the elements by Paul Schlyter : http://www.stjarnhimlen.se/comp/tutorial.html
- Orbit calculation from the elements by E M Standish (JPL) : http://ssd.jpl.nasa.gov/txt/aprx_pos_planets.pdf
- Planet texture maps are a courtesy of James Hastings-Trew : http://planetpixelemporium.com/planets.html
- Stars coordinates from AstroNexus : http://astronexus.com
- Stars coordinates from Nasa : http://heasarc.gsfc.nasa.gov/docs/archive.html
- David Eagle's orbital calculations of the moon, based on "Lunar Tables and Programs From 4000 B.C. TO A.D. 8000" by Michelle Chapront-Touze and Jean Chapront. : http://www.mathworks.com/matlabcentral/fileexchange/39130-orbital-elements-of-the-moon
- Calculations of Apollo missions trans lunar injection trajectories by Bob Braeunig : http://www.braeunig.us/apollo/
- Calculation of velocity orientation by Hop David : http://orbiter-forum.com/showthread.php?t=24457
- Three.js : http://threejs.org/