<p>The code in question appears to convert from polar to Cartesian form in different ways in different places.
If you want the velocity direction to be pi/2 ahead of the position direction, then make that explicit and use the same function for both position and velocity.</p>
<p>I suggest replacing CelestialBodyProperties's x_pos and y_pos with distance, and renaming its scalar velocity as speed.</p>
<pre><code>def to_cartesian(r: float, theta: float) -&gt; list[float]:
    x = r * np.cos(theta)
    y = r * np.sin(theta)
    return [x, y]

# in CelestialBody.__init__
self.position = np.array(to_cartesian(
        celestial_body_data.distance, celestial_body_data.direction - np.pi/2),
        dtype=np.float64)
self.velocity = np.array(to_cartesian(
        celestial_body_data.speed, celestial_body_data.direction),
        dtype=np.float64)
</code></pre>
<p>If the display y coordinate increases from top to bottom, the result should look like the screenshot in question but with Venus starting in the 1 o'clock position and following a circular orbit.</p>

CC BY-SA 4.0
2023-12-30T22:42:42.643Z
This seemed to do the trick, i believe. I appreciate the help.
Tmpecho
CC BY-SA 4.0
2023-12-30T16:58:45.540Z
2023-12-30T16:58:45.540Z
Mike G
<p>I am working on a 2d solar system model using Python, but I'm unsure if my implementation of planet data is correct. I have the planet data stored in polar form (distance, velocity and angle), and I later convert that data into x, y coordinates. I did this originally for ease of inputting planet position data, but I later discovered that ir maybe wasn't the best move.</p>
<h2>The problem</h2>
<p>My problem is that most angles behave differently that what I would like. What I would like the for the <code>direction</code> param to say <em>where</em> the planet is relative to the sun and not necessarily at what angle from the sun it is moving, if that makes sense. For example, I never want a planet to start moving directly towards the sun, or any other weird angles. What I think I'm doing wrong is that the direction now says in what direction the planet is traveling relative to itself as well. In the image below, I altered the direction of Venus to be 0.6 rad. The planet is initially positioned correctly, however the velocity direction is wrong, as it obviously isn't traveling outwards from the sun.
<a href="https://i.sstatic.net/8Uyqk.jpg" rel="nofollow noreferrer"><img src="https://i.sstatic.net/8Uyqk.jpg" alt="screenshot from simulation" /></a></p>
<p>The code for the project can be found at the GitHub page <a href="https://github.com/Tmpecho/solsystem_modell" rel="nofollow noreferrer">solsystem-modell</a> (<code>README.md</code> is in Norwegian but code should all be in English). I hope that there aren't any problems regarding the model itself, but a quick check that things in general are fine would be much appreciated as well.</p>
<h2>Context</h2>
<p>I here have the relevant code for the project.</p>
<p>Data is stored like this:</p>
<div class="s-table-container">
<table class="s-table">
<thead>
<tr>
<th style="text-align: left;">Name</th>
<th style="text-align: left;">Color (RGB)</th>
<th style="text-align: right;">Radius (km)</th>
<th style="text-align: right;">Mass (kg)</th>
<th style="text-align: right;">Distance (AU)</th>
<th style="text-align: right;">Velocity (m/s)</th>
<th style="text-align: left;">Direction (radians)</th>
<th style="text-align: right;">Max_Trail_Length</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: left;">Sun</td>
<td style="text-align: left;">(255, 255, 0)</td>
<td style="text-align: right;">6963400</td>
<td style="text-align: right;">1.98847e+30</td>
<td style="text-align: right;">0</td>
<td style="text-align: right;">0</td>
<td style="text-align: left;">0</td>
<td style="text-align: right;">100</td>
</tr>
<tr>
<td style="text-align: left;">Mercury</td>
<td style="text-align: left;">(255, 0, 0)</td>
<td style="text-align: right;">2440</td>
<td style="text-align: right;">3.3011e+23</td>
<td style="text-align: right;">0.393</td>
<td style="text-align: right;">47362</td>
<td style="text-align: left;">pi / 2</td>
<td style="text-align: right;">200</td>
</tr>
<tr>
<td style="text-align: left;">Venus</td>
<td style="text-align: left;">(255, 165, 0)</td>
<td style="text-align: right;">6052</td>
<td style="text-align: right;">4.8675e+24</td>
<td style="text-align: right;">0.723</td>
<td style="text-align: right;">35021.4</td>
<td style="text-align: left;">pi / 2</td>
<td style="text-align: right;">600</td>
</tr>
<tr>
<td style="text-align: left;">Earth</td>
<td style="text-align: left;">(0, 0, 255)</td>
<td style="text-align: right;">6371</td>
<td style="text-align: right;">5.9722e+24</td>
<td style="text-align: right;">1</td>
<td style="text-align: right;">29784.8</td>
<td style="text-align: left;">pi / 2</td>
<td style="text-align: right;">800</td>
</tr>
<tr>
<td style="text-align: left;">Mars</td>
<td style="text-align: left;">(255, 0, 0)</td>
<td style="text-align: right;">3390</td>
<td style="text-align: right;">6.4171e+23</td>
<td style="text-align: right;">1.52</td>
<td style="text-align: right;">24130.8</td>
<td style="text-align: left;">pi / 2</td>
<td style="text-align: right;">2000</td>
</tr>
<tr>
<td style="text-align: left;">Jupiter</td>
<td style="text-align: left;">(255, 222, 173)</td>
<td style="text-align: right;">69911</td>
<td style="text-align: right;">1.8982e+27</td>
<td style="text-align: right;">5.203</td>
<td style="text-align: right;">13070</td>
<td style="text-align: left;">pi / 2</td>
<td style="text-align: right;">10000</td>
</tr>
<tr>
<td style="text-align: left;">Saturn</td>
<td style="text-align: left;">(210, 180, 140)</td>
<td style="text-align: right;">58232</td>
<td style="text-align: right;">5.6834e+26</td>
<td style="text-align: right;">9.737</td>
<td style="text-align: right;">9690</td>
<td style="text-align: left;">pi / 2</td>
<td style="text-align: right;">20000</td>
</tr>
<tr>
<td style="text-align: left;">Uranus</td>
<td style="text-align: left;">(0, 0, 128)</td>
<td style="text-align: right;">25362</td>
<td style="text-align: right;">8.681e+25</td>
<td style="text-align: right;">19.61</td>
<td style="text-align: right;">6810</td>
<td style="text-align: left;">pi / 2</td>
<td style="text-align: right;">50000</td>
</tr>
<tr>
<td style="text-align: left;">Neptune</td>
<td style="text-align: left;">(0, 0, 255)</td>
<td style="text-align: right;">24622</td>
<td style="text-align: right;">1.02413e+26</td>
<td style="text-align: right;">29.897</td>
<td style="text-align: right;">5430</td>
<td style="text-align: left;">pi / 2</td>
<td style="text-align: right;">200000</td>
</tr>
</tbody>
</table>
</div>
<p>I then import the data using this method (you can ignore most things that doesn't include the relevant data as distance, velocity and angle):
<em>In <code>utils.py</code></em></p>
<pre><code>def create_celestial_bodies(sun_x: float, sun_y: float, file_name) -&gt; list[CelestialBody]:
    planets = []
    with open(file_name, 'r') as file:
        reader = csv.reader(file)
        next(reader)
        for row in reader:
            name, color, radius, mass, distance, velocity, direction, max_trail_length = row
            color = tuple(map(int, color.strip(&quot;()&quot;).split(&quot;, &quot;)))
            radius = int(radius) * 1000
            mass = float(mass)
            distance = float(distance) * config.AU
            velocity = float(velocity)
            direction = eval(direction.replace('pi', 'np.pi'))
            x_pos = sun_x + distance * np.sin(direction)
            y_pos = sun_y + distance * np.cos(direction)
            max_trail_length = int(max_trail_length)

            # noinspection PyTypeChecker
            celestial_body_appearance = CelestialBodyAppearance(name, color, radius)
            celestial_body_properties = CelestialBodyProperties(mass, x_pos, y_pos,
                                                                velocity, direction, max_trail_length)
            celestial_body = CelestialBody(celestial_body_appearance, celestial_body_properties)
            planets.append(celestial_body)
    return planets
</code></pre>
<p>The data is stored in a <code>CelestialBody</code> class. Here is the initializing method where the data is converted into xy form:</p>
<pre><code>class CelestialBody:
    def __init__(self, appearance: 'CelestialBodyAppearance', celestial_body_data: 'CelestialBodyProperties') -&gt; None:
        self.name = appearance.name
        self.color = appearance.color

        self.mass = celestial_body_data.mass
        if config.TO_SCALE:
            self.size = appearance.radius / config.AU * config.ZOOM * config.SCALE_FACTOR
        else:
            if self.mass &gt; 0:
                self.size = config.DEFAULT_OBJECT_SIZE * np.log(self.mass) / config.SIZE_SCALING_FACTOR * config.ZOOM
            else:
                self.size = 0
        self.position = np.array([celestial_body_data.x_pos, celestial_body_data.y_pos], dtype=np.float64)
        self.velocity = np.array([celestial_body_data.velocity * np.cos(celestial_body_data.direction),
                                  celestial_body_data.velocity * np.sin(celestial_body_data.direction)],
                                 dtype=np.float64)
        self.max_trail_length = celestial_body_data.max_trail_length
        self.is_stationary = appearance.name == &quot;Sun&quot; and config.IS_SUN_STATIONARY

        self.label_surfaces = None
        self.time_since_last_trail_update = 0
        self.trail_update_interval = config.TRAIL_UPDATE_INTERVAL
        self.positions = deque(maxlen=10000)
</code></pre>
<p>I think the problem lays somewhere here. I could've implemented something incorrectly or missed out on some important details.</p>
<p>In short, I'm trying to get the <code>direction</code> of the planets working correctly, placing the planet around the sun in it's correct position.</p>
<p>I apologize for the clunky read. I'm not a native English speaker.</p>

CC BY-SA 4.0
2023-12-30T02:22:01.143Z
Shall I just delete the original question? This isn't asking about the same thing although it's very connected. Here I'm asking for help if something is wrong with my implementation of planet data. I can merge the questions in the morning, since it's 3:20 in the morning for me now.
Tmpecho
CC BY-SA 4.0
2023-12-30T14:38:35.190Z
I see the difference now that I've read it more carefully.
Mike G
<solar-system><coordinate><python><coordinate-systems>
Implementing polar coordinates correctly in solar system model?
Tmpecho
# Implementing polar coordinates correctly in solar system model?

(Asked by: username_0 on 2023-12-30)

I am working on a 2d solar system model using Python, but I'm unsure if my implementation of planet data is correct. I have the planet data stored in polar form (distance, velocity and angle), and I later convert that data into x, y coordinates. I did this originally for ease of inputting planet position data, but I later discovered that ir maybe wasn't the best move.
The problem
My problem is that most angles behave differently that what I would like. What I would like the for the direction param to say where the planet is relative to the sun and not necessarily at what angle from the sun it is moving, if that makes sense. For example, I never want a planet to start moving directly towards the sun, or any other weird angles. What I think I'm doing wrong is that the direction now says in what direction the planet is traveling relative to itself as well. In the image below, I altered the direction of Venus to be 0.6 rad. The planet is initially positioned correctly, however the velocity direction is wrong, as it obviously isn't traveling outwards from the sun.

The code for the project can be found at the GitHub page solsystem-modell (README.md is in Norwegian but code should all be in English). I hope that there aren't any problems regarding the model itself, but a quick check that things in general are fine would be much appreciated as well.
Context
I here have the relevant code for the project.
Data is stored like this:




Name
Color (RGB)
Radius (km)
Mass (kg)
Distance (AU)
Velocity (m/s)
Direction (radians)
Max_Trail_Length




Sun
(255, 255, 0)
6963400
1.98847e+30
0
0
0
100


Mercury
(255, 0, 0)
2440
3.3011e+23
0.393
47362
pi / 2
200


Venus
(255, 165, 0)
6052
4.8675e+24
0.723
35021.4
pi / 2
600


Earth
(0, 0, 255)
6371
5.9722e+24
1
29784.8
pi / 2
800


Mars
(255, 0, 0)
3390
6.4171e+23
1.52
24130.8
pi / 2
2000


Jupiter
(255, 222, 173)
69911
1.8982e+27
5.203
13070
pi / 2
10000


Saturn
(210, 180, 140)
58232
5.6834e+26
9.737
9690
pi / 2
20000


Uranus
(0, 0, 128)
25362
8.681e+25
19.61
6810
pi / 2
50000


Neptune
(0, 0, 255)
24622
1.02413e+26
29.897
5430
pi / 2
200000




I then import the data using this method (you can ignore most things that doesn't include the relevant data as distance, velocity and angle):
In utils.py
def create_celestial_bodies(sun_x: float, sun_y: float, file_name) -> list[CelestialBody]:
    planets = []
    with open(file_name, 'r') as file:
        reader = csv.reader(file)
        next(reader)
        for row in reader:
            name, color, radius, mass, distance, velocity, direction, max_trail_length = row
            color = tuple(map(int, color.strip("()").split(", ")))
            radius = int(radius) * 1000
            mass = float(mass)
            distance = float(distance) * config.AU
            velocity = float(velocity)
            direction = eval(direction.replace('pi', 'np.pi'))
            x_pos = sun_x + distance * np.sin(direction)
            y_pos = sun_y + distance * np.cos(direction)
            max_trail_length = int(max_trail_length)

            # noinspection PyTypeChecker
            celestial_body_appearance = CelestialBodyAppearance(name, color, radius)
            celestial_body_properties = CelestialBodyProperties(mass, x_pos, y_pos,
                                                                velocity, direction, max_trail_length)
            celestial_body = CelestialBody(celestial_body_appearance, celestial_body_properties)
            planets.append(celestial_body)
    return planets

The data is stored in a CelestialBody class. Here is the initializing method where the data is converted into xy form:
class CelestialBody:
    def __init__(self, appearance: 'CelestialBodyAppearance', celestial_body_data: 'CelestialBodyProperties') -> None:
        self.name = appearance.name
        self.color = appearance.color

        self.mass = celestial_body_data.mass
        if config.TO_SCALE:
            self.size = appearance.radius / config.AU * config.ZOOM * config.SCALE_FACTOR
        else:
            if self.mass > 0:
                self.size = config.DEFAULT_OBJECT_SIZE * np.log(self.mass) / config.SIZE_SCALING_FACTOR * config.ZOOM
            else:
                self.size = 0
        self.position = np.array([celestial_body_data.x_pos, celestial_body_data.y_pos], dtype=np.float64)
        self.velocity = np.array([celestial_body_data.velocity * np.cos(celestial_body_data.direction),
                                  celestial_body_data.velocity * np.sin(celestial_body_data.direction)],
                                 dtype=np.float64)
        self.max_trail_length = celestial_body_data.max_trail_length
        self.is_stationary = appearance.name == "Sun" and config.IS_SUN_STATIONARY

        self.label_surfaces = None
        self.time_since_last_trail_update = 0
        self.trail_update_interval = config.TRAIL_UPDATE_INTERVAL
        self.positions = deque(maxlen=10000)

I think the problem lays somewhere here. I could've implemented something incorrectly or missed out on some important details.
In short, I'm trying to get the direction of the planets working correctly, placing the planet around the sun in it's correct position.
I apologize for the clunky read. I'm not a native English speaker.

**Tags:** solar-system, coordinate, python, coordinate-systems
> **Comments:**
> **username_0**: Shall I just delete the original question? This isn't asking about the same thing although it's very connected. Here I'm asking for help if something is wrong with my implementation of planet data. I can merge the questions in the morning, since it's 3:20 in the morning for me now.  
> **username_1**: I see the difference now that I've read it more carefully.  

---

## 1 answers

### Answer by username_1 on 2023-12-30. Score: 1 | Accepted answer

The code in question appears to convert from polar to Cartesian form in different ways in different places.
If you want the velocity direction to be pi/2 ahead of the position direction, then make that explicit and use the same function for both position and velocity.
I suggest replacing CelestialBodyProperties's x_pos and y_pos with distance, and renaming its scalar velocity as speed.
def to_cartesian(r: float, theta: float) -> list[float]:
    x = r * np.cos(theta)
    y = r * np.sin(theta)
    return [x, y]

# in CelestialBody.__init__
self.position = np.array(to_cartesian(
        celestial_body_data.distance, celestial_body_data.direction - np.pi/2),
        dtype=np.float64)
self.velocity = np.array(to_cartesian(
        celestial_body_data.speed, celestial_body_data.direction),
        dtype=np.float64)

If the display y coordinate increases from top to bottom, the result should look like the screenshot in question but with Venus starting in the 1 o'clock position and following a circular orbit.

> **Comments:**
> **username_0**: This seemed to do the trick, i believe. I appreciate the help.  

---

