This is a page about »Simulating Solar System Part 1«.
The Setup
As an attempt to get away from the bboring crud development/automations, and to flex the part of brain that has been rusty, the author decided to switch gear to c++ and does some physics simulation. The objective is to deliver a GUI that simulates the solar system (inlcuding Pluto, yes). In order to achieve that, a good start is to first be able to simulate Earth Moon system. The code discussed in this article can be found at repo link.
The Physics
The main interaction that the simulator intends to simulate is the gravitatioal force between the celestial body within solar system. It is described as the following,
$$ F_{12} = G\frac{m_1m_2}{r^2} $$The force of body 1 exerts on body 2, which direction is pointing towards to body 1. The formula can be simply translate into the following c++ code.
1glm::vec2 calculateGForce(const PlanetaryObj& earth, const PlanetaryObj& moon) {
2 // calculates f earth exerts on moon, direction is towards earth
3 glm::vec2 direction = glm::vec2{earth.x, earth.y} - glm::vec2{moon.x, moon.y};
4 float r = glm::length(direction); // sqrt((x^2) + (y^2))
5 glm::vec2 unitDirection = direction / r;
6 float mag = G * earth.mass * moon.mass / (r * r);
7 return mag * unitDirection;
8};
The displacement of the bodies can be then calculated by getting the acceleration of each body and then calculate the actual displacement.
$$ \begin{align} a_1 = -\frac{F_{12}}{m_1} \\ v = u + a_{1}t \\ s_2 = s_1 + vt \end{align} $$And the code.
1glm::vec2 F = calculateGForce(earth, moon);
2glm::vec2 accelEarth = -F / earth.mass; // note the direction
3glm::vec2 accelMoon = F / moon.mass;
4
5void updatePos(glm::vec2 acceleration, bool debug) {
6 sf::CircleShape trailPoint(5.f); // Adjust the size and color as needed
7 trailPoint.setFillColor(sf::Color(color.r, color.g, color.b, 128));
8 trailPoint.setOrigin({5.f, 5.f});
9 trailPoint.setPosition(
10 {ViewportWidth / 2.f + x * m2vp, ViewportHeight / 2.f + y * m2vp}
11 );
12 trail.push_back(trailPoint);
13
14 this->vx += acceleration.x * t;
15 this->vy += acceleration.y * t;
16 this->x += vx * t;
17 this->y += vy * t;
18};
Pretty straightforward. By creating the two celestial bodies and SFML
will
take care the rest … or not.
1PlanetaryObj earth{0., 0., EarthRadius, MassEarth, sf::Color(100, 250, 50)};
2PlanetaryObj moon{3.633e8, 0., MoonRadius, MassMoon, sf::Color(100, 50, 250)};
3
4moon.vy = 1.076e3;
Turns out if the code is ran with earth.vy = 0
one will get the following
trajectory. Both object’s will move in one direction if the conservation of
momentum is not preserved. Newton’s first principal applies.
By adding the following will keep the system stable.
1earth.vy = -(moon.vy * moon.mass) / earth.mass;
Now the Earth Moon system is working.