Personal
Solar System Simulation
- Python
- NumPy
- Matplotlib
- PyGame
01
Overview
I built this project during my A-levels. It is designed to be used as a learning tool for A-level and GCSE students. Astrophysics is very difficult for students to run their own experiments on (for obvious reasons). This leads to students struggling to visualise key concepts and poor performance on exam questions. The process of building this project improved my own understanding of physics, leading to my interest in engineering and simulation software.
02
The Physics
The acceleration of each planet is calculated at each frame. This is added to its velocity vector, which is then used to update its position.
Users have the freedom to modify the radius and density of planets to see how this affects the gravitational field of the space. I chose not to model the gravitational force between planets in order to keep their orbits stable (unless they choose to modify the mass of the sun). In order to visualise the gravitational field of the whole system, users can add meteors which follow the resultant gravitational field.
03
The Graphics
Building the 3D graphics engine
PyGame only supports 2D shape drawing, so I studied how 3D graphics actually work so that I could display them on a 2D screen. I used linear algebra techniques to implement: back-face culling, face shading and depth perception. This was fairly simple to apply because all the planets are convex shapes.
calcUnitVector — guards the Sun-at-origin case
def ...Getting the scale right
The solar system is difficult to visualise on a linear scale, so I scaled radius and orbital distance by independent logarithmic sclaes. This improves the user experience by having all planets visible simultaneously.
04
Validation & Testing
Validating against NASA data
To check the physics was actually right and not just plausible-looking, I seeded the simulation with Mercury's real position, velocity and mass from NASA's planetary fact sheet, ran it for three orbits, and compared the measured orbital period and mean distance against the published values. My threshold for a pass was within 5%.
- 96.6%
- orbital period accuracy
- 97.9%
- orbital distance accuracy
- ±0.8%
- spread from float rounding
- 169 orbits
- vs. 168.37 expected
0.233 yr measured vs. 0.241 yr actual, averaged over 3 orbits of Mercury
56.66M km measured mean distance vs. 57.9M km actual
measured by seeding many Mercury-like orbits at random starting angles
after 168.37 virtual years — about 30 real minutes of runtime
The remaining error traces to three places: the initial conditions use averaged rather than instantaneous position and velocity, acceleration is only recalculated 100 times a second rather than continuously, and 64-bit floats round differently depending on a planet's starting angle. I isolated that last one by seeding dozens of Mercury-like orbits at random angles around the Sun and plotting them — if the physics were exact they'd land on exactly the same point on a vs. graph; the small scatter that appears instead is rounding error, not a modelling mistake.
Kepler's third law says for every planet orbiting the same star, with the constant of proportionality . Plotting the simulation's own output for all eight planets is the real end-to-end test: it doesn't just check one planet against one fact sheet, it checks whether the whole system's dynamics are self-consistent. On a linear scale the four inner planets collapse into an unreadable cluster in the corner, so I plotted it again on a log-log scale.
The graph above only proves Kepler's law — it doesn't let a student ask their own question of the data. So every run also writes each planet's live position, velocity and orbital data out to an Excel spreadsheet via Openpyxl, overwriting the previous run rather than leaving a folder of near-duplicate files behind. A student who wants to test something the built-in graph plotter doesn't cover — checking by hand, say — can just open the numbers themselves.