Challenge description: Your spacecraft has provided its Cartesian ICRF position (km) and velocity (km/s). What is its orbit (expressed as Keplerian elements)?
>docker run --rm -i -e FLAG=pouet kepler:challenge
KEPLER
CHALLANGE
a e i Ω ω υ
.. ,' ,=, .
, / \ .
. | | .
. \ / .
+ '=' .
. .'..'
'Your spacecraft reports that its Cartesian ICRF position (km) and velocity (km/s) are:
Pos (km): [8449.401305, 9125.794363, -17.461357]Vel (km/s): [-1.419072, 6.780149, 0.002865]Time: 2021-06-26-19:20:00.000-UTC
What is its orbit (expressed as Keplerian elements a, e, i, Ω, ω, and υ)?
Semimajor axis, a (km):
We need to determine the orbital parameters from the given Cartesian position and velocity.
It's important to understand what these orbital elements represent. If you need a refresher, check out this lesson on TLE basics (just here) :)
Below is a diagram illustrating the various parameters (note: the spacecraft’s placement is arbitrary for illustration):
The calculations to extract the orbital elements can be pretty involved. So instead, we’ll use the Python library poliastro to do the heavy lifting.
First, let's convert our lists for position and velocity into objects with proper physical units so we can perform calculations:
from poliastro.twobody.orbit import u
pos =[8449.401305,9125.794363,-17.461357]vel =[-1.419072,6.780149,0.002865]pos_km =[*pos]* u.km
vel_kms =[*vel]* u.km / u.s
Here, u.km and u.km / u.s are units from the astropy library.
By multiplying our lists by these units, each coordinate is converted into a Quantity object, so x, y, and z are now properly treated as being in kilometers and km/s. This allows us to perform physical calculations directly.
Similarly, u.s stands for seconds, so u.km / u.s "transforms" our velocity list into the correct unit (km/s).
Next, and this is where the magic happens, we just call the method Orbit.from_vectors which will do all the calculations for us so we can retrieve everything we need:
from poliastro.bodies import Earth
from poliastro.twobody import Orbit
time ="2021-06-26 19:20:00.000"orb = Orbit.from_vectors(Earth, pos_km, vel_kms, time)
Here, Earth is just an object containing the gravitational and geometric parameters of Earth, which are necessary for the calculation (no need to go into detail).
Don't forget to specify the exact time (time) at which the position and velocity were measured. Orbital parameters can change over time due to various gravitational perturbations, so specifying the time is important.
Once we've called Orbit.from_vectors, we just need to extract our six Keplerian elements:
a = orb.a # Semimajor axis in kme = orb.ecc # Eccentricityi = orb.inc.to_value(u.deg)# Inclination (converted to degrees)Omega = orb.raan.to_value(u.deg)# Right ascension of the ascending node (deg)omega = orb.argp.to_value(u.deg)# Argument of perigee (deg)nu = orb.nu.to_value(u.deg)# True anomaly (deg)
With the to_value(u.deg) method from astropy, we can directly convert a value to the unit of our choice. Since the angles are returned in radians, we use this to convert them to degrees.
Now, just print all the orbital parameters and fill in the challenge:
>docker run --rm -i -e FLAG=pouet kepler:challenge
KEPLER
CHALLANGE
a e i Ω ω υ
.. ,' ,=, .
, / \ .
. | | .
. \ / .
+ '=' .
. .'..'
'Your spacecraft reports that its Cartesian ICRF position (km) and velocity (km/s) are:
Pos (km): [8449.401305, 9125.794363, -17.461357]Vel (km/s): [-1.419072, 6.780149, 0.002865]Time: 2021-06-26-19:20:00.000-UTC
What is its orbit (expressed as Keplerian elements a, e, i, Ω, ω, and υ)?
Semimajor axis, a (km): 24732.885760723184Eccentricity, e: 0.7068070220620631Inclination, i (deg): 0.11790360842507447Right ascension of the ascending node, Ω (deg): 90.22650379956278Argument of perigee, ω (deg): 226.58745900876278True anomaly, υ (deg): 90.389955034578You got it! Here's your flag:
pouet