C++ OpenGL Project for visualising satellite orbits around earth based on their orbital elements.
The Project uses GLFW, GLEW, OpenGL and FreeImage, all in 64-bit. This is a Visual Studio Project (2017 Enterprise). Trying to get the project running with other IDEs is not guaranteed to work.
Numerical instability may occur if the application is not limited to 60fps. It might work, it might not.
Author: Bernhard Matthias Luedtke 2020-06-04
The Project is loosely based on original work by Prof. Dr.-Ing. Philipp Lensing. It is uploaded here with his approval.
Anyone is free to download this project and modify it. There is no guaranteed maintenance or support. If you use code from the project, please give a link to the repository.
To understand the aspect of orbital mechanics, I mainly studied this book: http://cmp.felk.cvut.cz/~kukelova/pajdla/Bate,%20Mueller,%20and%20White%20-%20Fundamentals%20of%20Astrodynamics.pdf
"OpenGLOrbiter/classes"
Good question. This text will walk you through the most important classes and the way things are currently done. This is, of course, subject to change. (Note: Running the code in Debug mode will take a really long time with many sats).
Where do we start? With main, of course. Main.cpp implements int main(){...} and therefore serves as the starting point. Here, a glfwWindow is opened. For every frame, the Manager (called 'App') is updated (.update) and drawn.
The Manager class is the heart of the management of the application. Things like adding satellites with different orbits can be done in here. If a model is being displayed in the window, the object of class manager likely holds a unique_ptr to the model/object. In the update-Method, the objects having update-methods should be updated from here (e.g. the satellites). The draw methods call 'draw' for all objects known to the Manager that can be drawn. If you add any new models that are not held in the standard std::vector for satellites or models (uModels), don't forget to add them here - otherwise they wont be drawn.
In this application, a satellite represents an entity that orbits around earth. It has Orbital parameters (capsuled in a class), which determine it's orbit. Note that no 'collision' between satellites (or with the earth) are possible. Implementing this is not the specific target of this application. Also, satellites have zero mass (as of 2020-06-04). These simplifications are needed, as more realistic phenomena become harder and harder to implement. Over time, more 'realistic' behaviour may be added. There is no set timeplan however. The progression along the orbit of a satellite is calculated per frame. This leads to a problem: If the application is not limited to e.g. 60 fps (60fps is my recommendation), the time delta every frame might be tiny. This can cause numerical instability, since the angle the satellite progresses also becomes increasingly small, making it harder to accurately calculate. If the angle is extremely small, the progression along the orbit might not be calculatable for the frame. There might be similar effects for very large angles. The current method may have numerical instabilities for angles right around π, but they rarely appear.
A satellite's orbit may be represented by an OrbitLineModel. This class holds a vector of points and builds a linestring out of the points to visualize the orbit. The points can be generated by calling a satellites calcOrbitVis() method. Be aware that some specific orbits can cause issues, more robust orbit visualization techniques are being thought of. These issues mainly appear in the mentioned method for calculating the points along the orbit. The orbit visualization has one experimental feature: dashed/dotted orbit lines. Note that this can cause severe problems with some specific orbits. The underlying issue is being worked on. It's not a trivial problem, so I'm not sure if I can fix it anytime soon.
The class OrbitEphemeris is used for holding values for the six orbital elements (based on Kepler). I highly suggest reading up on what these are online. It's too complicated to explain it here in detail. Basically, these are some scalar values and some angles, which are used to infer a satellite's orbit.
The application uses an earth-centric coordinate system, with the earth being at the origin (0,0,0). The scale is 1/6378 to reality. This means that one unit in this coordinate system equals approximately to the earths radius (slightly lower than at the equator), 6378 km. The timescale can be influenced by modifying the code. The Manager object managing the satellites has a method speedUpSats(float speedUp) for this purpose. SpeedUp can be called, as an example, at the end of the constructor of the Manager class.