satkit 0.2.7__tar.gz → 0.2.8__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {satkit-0.2.7 → satkit-0.2.8}/Cargo.toml +1 -1
- {satkit-0.2.7/python/satkit.egg-info → satkit-0.2.8}/PKG-INFO +3 -2
- {satkit-0.2.7 → satkit-0.2.8}/README.md +2 -1
- {satkit-0.2.7 → satkit-0.2.8}/pyproject.toml +1 -1
- {satkit-0.2.7 → satkit-0.2.8}/python/satkit/__init__.pyi +1 -0
- {satkit-0.2.7 → satkit-0.2.8}/python/satkit/satkit.pyi +47 -0
- {satkit-0.2.7 → satkit-0.2.8/python/satkit.egg-info}/PKG-INFO +3 -2
- {satkit-0.2.7 → satkit-0.2.8}/python/satkit.egg-info/SOURCES.txt +3 -1
- {satkit-0.2.7 → satkit-0.2.8}/python/test/orbitprop_gps_fit.py +46 -11
- {satkit-0.2.7 → satkit-0.2.8}/python/test/test.py +38 -0
- {satkit-0.2.7 → satkit-0.2.8}/src/astrotime.rs +4 -4
- {satkit-0.2.7 → satkit-0.2.8}/src/frametransform/mod.rs +1 -1
- {satkit-0.2.7 → satkit-0.2.8}/src/jplephem.rs +18 -18
- satkit-0.2.8/src/kepler.rs +159 -0
- {satkit-0.2.7 → satkit-0.2.8}/src/lib.rs +2 -0
- satkit-0.2.8/src/lpephem/mod.rs +9 -0
- satkit-0.2.8/src/lpephem/planets.rs +335 -0
- {satkit-0.2.7 → satkit-0.2.8}/src/nrlmsise.rs +5 -1
- {satkit-0.2.7 → satkit-0.2.8}/src/ode/rk_adaptive.rs +1 -1
- {satkit-0.2.7 → satkit-0.2.8}/src/orbitprop/propagator.rs +4 -5
- {satkit-0.2.7 → satkit-0.2.8}/src/pybindings/mod.rs +4 -0
- {satkit-0.2.7 → satkit-0.2.8}/src/pybindings/pyastrotime.rs +4 -4
- satkit-0.2.8/src/pybindings/pykepler.rs +98 -0
- satkit-0.2.8/src/pybindings/pysolarsystem.rs +66 -0
- {satkit-0.2.7 → satkit-0.2.8}/src/solarsystem.rs +10 -10
- {satkit-0.2.7 → satkit-0.2.8}/src/spaceweather.rs +2 -2
- {satkit-0.2.7 → satkit-0.2.8}/src/tle.rs +1 -1
- satkit-0.2.7/python/satkit/py.typed +0 -0
- satkit-0.2.7/src/lpephem/mod.rs +0 -4
- satkit-0.2.7/src/pybindings/pysolarsystem.rs +0 -66
- {satkit-0.2.7 → satkit-0.2.8}/LICENSE +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/MANIFEST.in +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/python/docs/source/conf.py +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/python/satkit/__init__.py +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/python/satkit/density.pyi +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/python/satkit/frametransform.pyi +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/python/satkit/jplephem.pyi +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/python/satkit/moon.pyi +0 -0
- {satkit-0.2.7/python/satkit/astro-data → satkit-0.2.8/python/satkit}/py.typed +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/python/satkit/satprop.pyi +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/python/satkit/sun.pyi +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/python/satkit/utils.pyi +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/python/satkit.egg-info/dependency_links.txt +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/python/satkit.egg-info/requires.txt +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/python/satkit.egg-info/top_level.txt +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/python/test/download_data.py +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/python/test/download_from_json.py +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/python/test/download_testvecs.py +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/python/test/sp3file.py +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/setup.cfg +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/src/consts.rs +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/src/duration.rs +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/src/earth_orientation_params.rs +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/src/earthgravity.rs +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/src/frametransform/ierstable.rs +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/src/frametransform/qcirs2gcrs.rs +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/src/itrfcoord.rs +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/src/lpephem/moon.rs +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/src/lpephem/sun.rs +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/src/ode/harmonic_oscillator.rs +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/src/ode/mod.rs +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/src/ode/nalgebra.rs +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/src/ode/rk_adaptive_settings.rs +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/src/ode/rk_explicit.rs +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/src/ode/rkf45.rs +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/src/ode/rkts54.rs +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/src/ode/rkv65.rs +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/src/ode/rkv65_table.rs +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/src/ode/rkv87.rs +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/src/ode/rkv87_table.rs +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/src/ode/rkv98.rs +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/src/ode/rkv98_nointerp.rs +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/src/ode/rkv98_nointerp_table.rs +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/src/ode/rkv98_table.rs +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/src/ode/types.rs +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/src/orbitprop/drag.rs +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/src/orbitprop/mod.rs +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/src/orbitprop/point_gravity.rs +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/src/orbitprop/satproperties.rs +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/src/orbitprop/satstate.rs +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/src/orbitprop/settings.rs +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/src/pybindings/mod_utils.rs +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/src/pybindings/pyconsts.rs +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/src/pybindings/pydensity.rs +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/src/pybindings/pyduration.rs +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/src/pybindings/pyframetransform.rs +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/src/pybindings/pygravity.rs +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/src/pybindings/pyitrfcoord.rs +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/src/pybindings/pyjplephem.rs +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/src/pybindings/pylpephem_moon.rs +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/src/pybindings/pylpephem_sun.rs +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/src/pybindings/pynrlmsise.rs +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/src/pybindings/pypropagate.rs +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/src/pybindings/pypropsettings.rs +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/src/pybindings/pyquaternion.rs +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/src/pybindings/pysatproperties.rs +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/src/pybindings/pysatstate.rs +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/src/pybindings/pysgp4.rs +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/src/pybindings/pytle.rs +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/src/pybindings/pyutils.rs +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/src/sgp4/dpper.rs +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/src/sgp4/dscom.rs +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/src/sgp4/dsinit.rs +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/src/sgp4/dspace.rs +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/src/sgp4/getgravconst.rs +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/src/sgp4/initl.rs +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/src/sgp4/mod.rs +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/src/sgp4/satrec.rs +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/src/sgp4/sgp4.rs +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/src/sgp4/sgp4_lowlevel.rs +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/src/sgp4/sgp4init.rs +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/src/types.rs +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/src/utils/datadir.rs +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/src/utils/download.rs +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/src/utils/mod.rs +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/src/utils/skerror.rs +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/src/utils/test.rs +0 -0
- {satkit-0.2.7 → satkit-0.2.8}/src/utils/update_data.rs +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: satkit
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.8
|
|
4
4
|
Summary: Satellite Orbital Dynamics Toolkit
|
|
5
5
|
Author-email: Steven Michael <ssmichael@gmail.com>
|
|
6
6
|
Maintainer-email: Steven Michael <ssmichael@gmail.com>
|
|
@@ -21,6 +21,7 @@ Requires-Dist: numpy>=1.20.0
|
|
|
21
21
|
|
|
22
22
|
An accurate, high-performance satellite orbital kinematics toolkit, written in Rust with a sensible interface.
|
|
23
23
|
<br/>
|
|
24
|
+
Also includes python bindings for *all* functions via via [pyo3](https://pyo3.rs/)
|
|
24
25
|
|
|
25
26
|
### Github
|
|
26
27
|
|
|
@@ -48,7 +49,7 @@ An accurate, high-performance satellite orbital kinematics toolkit, written in R
|
|
|
48
49
|
- **Native Rust** bindings
|
|
49
50
|
- **Python bindings** for compiled rust code ... speed of Rust with convenience of Python<br/>
|
|
50
51
|
Install with `pip install satkit`<br/>
|
|
51
|
-
PyPi includes
|
|
52
|
+
PyPi includes binary packages for windows, macos (Intel & ARM), and linux. Python documentation is at: <https://satellite-toolkit.readthedocs.io/latest/>
|
|
52
53
|
|
|
53
54
|
## Features
|
|
54
55
|
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
An accurate, high-performance satellite orbital kinematics toolkit, written in Rust with a sensible interface.
|
|
4
4
|
<br/>
|
|
5
|
+
Also includes python bindings for *all* functions via via [pyo3](https://pyo3.rs/)
|
|
5
6
|
|
|
6
7
|
### Github
|
|
7
8
|
|
|
@@ -29,7 +30,7 @@ An accurate, high-performance satellite orbital kinematics toolkit, written in R
|
|
|
29
30
|
- **Native Rust** bindings
|
|
30
31
|
- **Python bindings** for compiled rust code ... speed of Rust with convenience of Python<br/>
|
|
31
32
|
Install with `pip install satkit`<br/>
|
|
32
|
-
PyPi includes
|
|
33
|
+
PyPi includes binary packages for windows, macos (Intel & ARM), and linux. Python documentation is at: <https://satellite-toolkit.readthedocs.io/latest/>
|
|
33
34
|
|
|
34
35
|
## Features
|
|
35
36
|
|
|
@@ -1050,6 +1050,53 @@ class quaternion:
|
|
|
1050
1050
|
quaternion: Quaternion representing interpolation between self and other
|
|
1051
1051
|
"""
|
|
1052
1052
|
|
|
1053
|
+
class kepler:
|
|
1054
|
+
""" Represent Keplerian element sets and convert between cartesian
|
|
1055
|
+
|
|
1056
|
+
|
|
1057
|
+
Notes:
|
|
1058
|
+
* This class is used to represent Keplerian elements and convert between Cartesian coordinates
|
|
1059
|
+
* The class uses the semi-major axis (a), not the semiparameter
|
|
1060
|
+
* All angle units are radians
|
|
1061
|
+
* All length units are meters
|
|
1062
|
+
* All velocity units are meters / second
|
|
1063
|
+
"""
|
|
1064
|
+
|
|
1065
|
+
def __init__(self, *args):
|
|
1066
|
+
"""Create Keplerian element set object from input elements
|
|
1067
|
+
|
|
1068
|
+
# Args:
|
|
1069
|
+
a (float) : Semi-major axis, meters
|
|
1070
|
+
e (float) : Eccentricity, unitless
|
|
1071
|
+
i (float) : Inclination, radians
|
|
1072
|
+
raan (float) : Right ascension of ascending node, radians
|
|
1073
|
+
argp (float) : Argument of perigee, radians
|
|
1074
|
+
nu (float) : True anomaly, radians
|
|
1075
|
+
|
|
1076
|
+
# Returns:
|
|
1077
|
+
satkit.kepler: Keplerian element set object
|
|
1078
|
+
"""
|
|
1079
|
+
|
|
1080
|
+
def to_pv(self) -> typing.Tuple[npt.ArrayLike[np.float64], npt.ArrayLike[np.float64]]:
|
|
1081
|
+
"""Convert Keplerian element set to position and velocity vectors
|
|
1082
|
+
|
|
1083
|
+
Returns:
|
|
1084
|
+
tuple[npt.ArrayLike[np.float64], npt.ArrayLike[np.float64]]: Tuple with two elements representing the position and velocity vectors
|
|
1085
|
+
"""
|
|
1086
|
+
|
|
1087
|
+
def from_pv(
|
|
1088
|
+
pos: npt.ArrayLike[np.float64], vel: npt.ArrayLike[np.float64]
|
|
1089
|
+
) -> kepler:
|
|
1090
|
+
"""Create Keplerian element set from input position and velocity vectors
|
|
1091
|
+
|
|
1092
|
+
Args:
|
|
1093
|
+
pos (npt.ArrayLike[np.float64]): 3-element array representing position vector
|
|
1094
|
+
vel (npt.ArrayLike[np.float64]): 3-element array representing velocity vector
|
|
1095
|
+
|
|
1096
|
+
Returns:
|
|
1097
|
+
satkit.kepler: Keplerian element set object
|
|
1098
|
+
"""
|
|
1099
|
+
|
|
1053
1100
|
class itrfcoord:
|
|
1054
1101
|
""" Representation of a coordinate in the International Terrestrial Reference Frame (ITRF)
|
|
1055
1102
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: satkit
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.8
|
|
4
4
|
Summary: Satellite Orbital Dynamics Toolkit
|
|
5
5
|
Author-email: Steven Michael <ssmichael@gmail.com>
|
|
6
6
|
Maintainer-email: Steven Michael <ssmichael@gmail.com>
|
|
@@ -21,6 +21,7 @@ Requires-Dist: numpy>=1.20.0
|
|
|
21
21
|
|
|
22
22
|
An accurate, high-performance satellite orbital kinematics toolkit, written in Rust with a sensible interface.
|
|
23
23
|
<br/>
|
|
24
|
+
Also includes python bindings for *all* functions via via [pyo3](https://pyo3.rs/)
|
|
24
25
|
|
|
25
26
|
### Github
|
|
26
27
|
|
|
@@ -48,7 +49,7 @@ An accurate, high-performance satellite orbital kinematics toolkit, written in R
|
|
|
48
49
|
- **Native Rust** bindings
|
|
49
50
|
- **Python bindings** for compiled rust code ... speed of Rust with convenience of Python<br/>
|
|
50
51
|
Install with `pip install satkit`<br/>
|
|
51
|
-
PyPi includes
|
|
52
|
+
PyPi includes binary packages for windows, macos (Intel & ARM), and linux. Python documentation is at: <https://satellite-toolkit.readthedocs.io/latest/>
|
|
52
53
|
|
|
53
54
|
## Features
|
|
54
55
|
|
|
@@ -20,7 +20,6 @@ python/satkit.egg-info/SOURCES.txt
|
|
|
20
20
|
python/satkit.egg-info/dependency_links.txt
|
|
21
21
|
python/satkit.egg-info/requires.txt
|
|
22
22
|
python/satkit.egg-info/top_level.txt
|
|
23
|
-
python/satkit/astro-data/py.typed
|
|
24
23
|
python/test/download_data.py
|
|
25
24
|
python/test/download_from_json.py
|
|
26
25
|
python/test/download_testvecs.py
|
|
@@ -34,6 +33,7 @@ src/earth_orientation_params.rs
|
|
|
34
33
|
src/earthgravity.rs
|
|
35
34
|
src/itrfcoord.rs
|
|
36
35
|
src/jplephem.rs
|
|
36
|
+
src/kepler.rs
|
|
37
37
|
src/lib.rs
|
|
38
38
|
src/nrlmsise.rs
|
|
39
39
|
src/solarsystem.rs
|
|
@@ -45,6 +45,7 @@ src/frametransform/mod.rs
|
|
|
45
45
|
src/frametransform/qcirs2gcrs.rs
|
|
46
46
|
src/lpephem/mod.rs
|
|
47
47
|
src/lpephem/moon.rs
|
|
48
|
+
src/lpephem/planets.rs
|
|
48
49
|
src/lpephem/sun.rs
|
|
49
50
|
src/ode/harmonic_oscillator.rs
|
|
50
51
|
src/ode/mod.rs
|
|
@@ -80,6 +81,7 @@ src/pybindings/pyframetransform.rs
|
|
|
80
81
|
src/pybindings/pygravity.rs
|
|
81
82
|
src/pybindings/pyitrfcoord.rs
|
|
82
83
|
src/pybindings/pyjplephem.rs
|
|
84
|
+
src/pybindings/pykepler.rs
|
|
83
85
|
src/pybindings/pylpephem_moon.rs
|
|
84
86
|
src/pybindings/pylpephem_sun.rs
|
|
85
87
|
src/pybindings/pynrlmsise.rs
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# %%
|
|
1
2
|
"""
|
|
2
3
|
This function reads an SP3 file containing precise GPS locaions in the ITRF frame
|
|
3
4
|
|
|
@@ -24,16 +25,30 @@ import os
|
|
|
24
25
|
basedir = os.getenv(
|
|
25
26
|
"SATKIT_TESTVEC_ROOT", default="../.." + os.path.sep + "satkit-testvecs"
|
|
26
27
|
)
|
|
27
|
-
fname = (
|
|
28
|
-
basedir
|
|
29
|
-
+ os.path.sep
|
|
30
|
-
+ "orbitprop"
|
|
31
|
-
+ os.path.sep
|
|
32
|
-
+ "ESA0OPSFIN_20233640000_01D_05M_ORB.SP3"
|
|
33
|
-
)
|
|
34
28
|
|
|
35
|
-
|
|
36
|
-
|
|
29
|
+
sp3names = ['mid22630.sp3', 'mid22631.sp3', 'mid22632.sp3',
|
|
30
|
+
'mid22633.sp3', 'mid22634.sp3', 'mid22635.sp3',
|
|
31
|
+
'mid22636.sp3']
|
|
32
|
+
|
|
33
|
+
sp3names = ['mid22630.sp3', 'mid22631.sp3', 'mid22632.sp3']
|
|
34
|
+
pitrf = np.zeros((0,3), np.float64)
|
|
35
|
+
timearr = np.array([])
|
|
36
|
+
|
|
37
|
+
for sp3name in sp3names:
|
|
38
|
+
fname = (
|
|
39
|
+
basedir
|
|
40
|
+
+ os.path.sep
|
|
41
|
+
+ "orbitprop"
|
|
42
|
+
+ os.path.sep
|
|
43
|
+
+ sp3name
|
|
44
|
+
)
|
|
45
|
+
[pitrf1, timearray1] = read_sp3file(fname)
|
|
46
|
+
pitrf = np.append(pitrf, pitrf1, axis=0)
|
|
47
|
+
timearr = np.append(timearr, timearray1)
|
|
48
|
+
|
|
49
|
+
print(pitrf.shape)
|
|
50
|
+
print(timearr.shape)
|
|
51
|
+
print(timearr[0], timearr[-1])
|
|
37
52
|
|
|
38
53
|
# Rotate positions to the GCRF frame
|
|
39
54
|
pgcrf = np.stack(
|
|
@@ -42,13 +57,12 @@ pgcrf = np.stack(
|
|
|
42
57
|
),
|
|
43
58
|
axis=0,
|
|
44
59
|
)
|
|
45
|
-
|
|
46
60
|
# Crude estimation of initial velocity
|
|
47
61
|
vgcrf = (pgcrf[1, :] - pgcrf[0, :]) / (timearr[1] - timearr[0]).seconds()
|
|
48
62
|
|
|
49
63
|
# Initial state for non-linear least squares is initial velocity
|
|
50
64
|
# and susceptibility to radiation pressuer : Cr A / m
|
|
51
|
-
v0 = np.array([vgcrf[0], vgcrf[1], vgcrf[2],
|
|
65
|
+
v0 = np.array([vgcrf[0], vgcrf[1], vgcrf[2], 0.01])
|
|
52
66
|
|
|
53
67
|
|
|
54
68
|
def minfunc(v):
|
|
@@ -68,6 +82,7 @@ def minfunc(v):
|
|
|
68
82
|
propsettings=settings,
|
|
69
83
|
satproperties=satprops,
|
|
70
84
|
)
|
|
85
|
+
|
|
71
86
|
return np.sum(np.sum((res["pos"] - pgcrf) ** 2, axis=1), axis=0)
|
|
72
87
|
|
|
73
88
|
|
|
@@ -75,3 +90,23 @@ def minfunc(v):
|
|
|
75
90
|
# by tuning initial velocity and CrAoverM
|
|
76
91
|
r = minimize(minfunc, v0, method="Nelder-Mead")
|
|
77
92
|
print(r)
|
|
93
|
+
|
|
94
|
+
# %%
|
|
95
|
+
import plotly.graph_objects as go
|
|
96
|
+
|
|
97
|
+
settings = sk.satprop.propsettings()
|
|
98
|
+
settings.use_jplephem = False
|
|
99
|
+
satprops = sk.satprop.satproperties_static()
|
|
100
|
+
satprops.craoverm = r.x[3]
|
|
101
|
+
res = sk.satprop.propagate(
|
|
102
|
+
pgcrf[0,:], r.x[0:3], timearr[0],
|
|
103
|
+
stoptime=timearr[-1], dt=sk.duration(minutes=5),
|
|
104
|
+
propsettings=settings, satproperties=satprops
|
|
105
|
+
)
|
|
106
|
+
perr = res['pos'] - pgcrf
|
|
107
|
+
fig = go.Figure()
|
|
108
|
+
fig.add_trace(go.Scatter(x=[t.datetime() for t in timearr], y=perr[:,0], mode='lines', name='X'))
|
|
109
|
+
fig.add_trace(go.Scatter(x=[t.datetime() for t in timearr], y=perr[:,1], mode='lines', name='Y'))
|
|
110
|
+
fig.add_trace(go.Scatter(x=[t.datetime() for t in timearr], y=perr[:,2], mode='lines', name='Z'))
|
|
111
|
+
|
|
112
|
+
# %%
|
|
@@ -121,6 +121,44 @@ class TestTime:
|
|
|
121
121
|
assert minute == 0
|
|
122
122
|
assert sec == 0
|
|
123
123
|
|
|
124
|
+
class TestKepler:
|
|
125
|
+
def test_kepler_from_pv(self):
|
|
126
|
+
"""
|
|
127
|
+
Test creation of Kepler elements from position and velocity
|
|
128
|
+
"""
|
|
129
|
+
|
|
130
|
+
# Test case from Vallado, example 2-6
|
|
131
|
+
r = np.array([6524.834, 6862.875, 6448.296])*1.0e3
|
|
132
|
+
v = np.array([4.901327, 5.533756, -1.976341])*1.0e3
|
|
133
|
+
kep = sk.kepler.from_pv(r, v)
|
|
134
|
+
rad2deg = 180.0/m.pi
|
|
135
|
+
print(kep)
|
|
136
|
+
assert kep.a == pytest.approx(36127343, 1.0e-3)
|
|
137
|
+
assert kep.eccen == pytest.approx(0.83285, 1.0e-5)
|
|
138
|
+
assert kep.inclination*rad2deg == pytest.approx(87.87, 1.0e-3)
|
|
139
|
+
assert kep.raan*rad2deg == pytest.approx(227.89, 1.0e-3)
|
|
140
|
+
assert kep.w*rad2deg == pytest.approx(53.38, 1.0e-3)
|
|
141
|
+
assert kep.nu*rad2deg == pytest.approx(92.335, 1.0e-3)
|
|
142
|
+
|
|
143
|
+
def test_kepler_to_pv(self):
|
|
144
|
+
"""
|
|
145
|
+
Test conversion of Kepler elements to position and velocity
|
|
146
|
+
"""
|
|
147
|
+
p = 11067790
|
|
148
|
+
eccen = 0.83285
|
|
149
|
+
incl = 87.87*m.pi/180
|
|
150
|
+
raan = 227.89*m.pi/180
|
|
151
|
+
w = 53.38*m.pi/180
|
|
152
|
+
nu = 92.335*m.pi/180
|
|
153
|
+
|
|
154
|
+
a = p/(1-eccen**2)
|
|
155
|
+
kep = sk.kepler(a, eccen, incl, raan, w, nu)
|
|
156
|
+
pos, vel = kep.to_pv()
|
|
157
|
+
assert pos == pytest.approx(np.array([6525.368, 6861.532, 6449.119])*1.0e3, 1.0e-3)
|
|
158
|
+
assert vel == pytest.approx(np.array([4.902279, 5.533140, -1.975710])*1.0e3, 1.0e-3)
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
|
|
124
162
|
class TestJPLEphem:
|
|
125
163
|
def test_jplephem_testvecs(self):
|
|
126
164
|
"""
|
|
@@ -423,7 +423,7 @@ impl AstroTime {
|
|
|
423
423
|
/// # Returns
|
|
424
424
|
///
|
|
425
425
|
/// * AstroTime Object
|
|
426
|
-
pub fn from_date(year:
|
|
426
|
+
pub fn from_date(year: i32, month: u32, day: u32) -> AstroTime {
|
|
427
427
|
AstroTime::from_mjd(date2mjd_utc(year, month, day) as f64, Scale::UTC)
|
|
428
428
|
}
|
|
429
429
|
|
|
@@ -500,7 +500,7 @@ impl AstroTime {
|
|
|
500
500
|
/// * AstroTime object
|
|
501
501
|
#[inline]
|
|
502
502
|
pub fn from_datetime(
|
|
503
|
-
year:
|
|
503
|
+
year: i32,
|
|
504
504
|
month: u32,
|
|
505
505
|
day: u32,
|
|
506
506
|
hour: u32,
|
|
@@ -526,7 +526,7 @@ impl AstroTime {
|
|
|
526
526
|
///
|
|
527
527
|
/// * AstroTime object
|
|
528
528
|
pub fn from_datetime_with_scale(
|
|
529
|
-
year:
|
|
529
|
+
year: i32,
|
|
530
530
|
month: u32,
|
|
531
531
|
day: u32,
|
|
532
532
|
hour: u32,
|
|
@@ -649,7 +649,7 @@ fn mjd_utc2date(mjd_utc: f64) -> (u32, u32, u32) {
|
|
|
649
649
|
(year as u32, month as u32, day as u32)
|
|
650
650
|
}
|
|
651
651
|
|
|
652
|
-
fn date2mjd_utc(year:
|
|
652
|
+
fn date2mjd_utc(year: i32, month: u32, day: u32) -> i32 {
|
|
653
653
|
// Chapter 15 "Calendars" section 15.11.3 of the
|
|
654
654
|
// Explanatory Suppliment to the Astronomical Almanac
|
|
655
655
|
// Algorithm 3
|
|
@@ -210,7 +210,7 @@ pub fn qgcrf2itrf_approx(tm: &AstroTime) -> Quat {
|
|
|
210
210
|
// Neglecting polar motion
|
|
211
211
|
let qitrf2tod_approx: Quat = qrot_zcoord(-gast(tm));
|
|
212
212
|
|
|
213
|
-
qmod2gcrf(tm) * qtod2mod_approx(tm) * qitrf2tod_approx
|
|
213
|
+
(qmod2gcrf(tm) * qtod2mod_approx(tm) * qitrf2tod_approx).conjugate()
|
|
214
214
|
}
|
|
215
215
|
|
|
216
216
|
///
|
|
@@ -38,17 +38,17 @@ impl TryFrom<i32> for SolarSystem {
|
|
|
38
38
|
type Error = ();
|
|
39
39
|
fn try_from(v: i32) -> Result<Self, Self::Error> {
|
|
40
40
|
match v {
|
|
41
|
-
x if x == SolarSystem::
|
|
42
|
-
x if x == SolarSystem::
|
|
41
|
+
x if x == SolarSystem::Mercury as i32 => Ok(SolarSystem::Mercury),
|
|
42
|
+
x if x == SolarSystem::Venus as i32 => Ok(SolarSystem::Venus),
|
|
43
43
|
x if x == SolarSystem::EMB as i32 => Ok(SolarSystem::EMB),
|
|
44
|
-
x if x == SolarSystem::
|
|
45
|
-
x if x == SolarSystem::
|
|
46
|
-
x if x == SolarSystem::
|
|
47
|
-
x if x == SolarSystem::
|
|
48
|
-
x if x == SolarSystem::
|
|
49
|
-
x if x == SolarSystem::
|
|
50
|
-
x if x == SolarSystem::
|
|
51
|
-
x if x == SolarSystem::
|
|
44
|
+
x if x == SolarSystem::Mars as i32 => Ok(SolarSystem::Mars),
|
|
45
|
+
x if x == SolarSystem::Jupiter as i32 => Ok(SolarSystem::Jupiter),
|
|
46
|
+
x if x == SolarSystem::Saturn as i32 => Ok(SolarSystem::Saturn),
|
|
47
|
+
x if x == SolarSystem::Uranus as i32 => Ok(SolarSystem::Uranus),
|
|
48
|
+
x if x == SolarSystem::Neptune as i32 => Ok(SolarSystem::Neptune),
|
|
49
|
+
x if x == SolarSystem::Pluto as i32 => Ok(SolarSystem::Pluto),
|
|
50
|
+
x if x == SolarSystem::Moon as i32 => Ok(SolarSystem::Moon),
|
|
51
|
+
x if x == SolarSystem::Sun as i32 => Ok(SolarSystem::Sun),
|
|
52
52
|
_ => Err(()),
|
|
53
53
|
}
|
|
54
54
|
}
|
|
@@ -130,7 +130,7 @@ impl JPLEphem {
|
|
|
130
130
|
/// let t = AstroTime::from_datetime(2021, 3, 1, 12, 0, 0.0);
|
|
131
131
|
///
|
|
132
132
|
/// // Find geocentric moon position at this time in the GCRF frame
|
|
133
|
-
/// let p = jplephem::geocentric_pos(SolarSystem::
|
|
133
|
+
/// let p = jplephem::geocentric_pos(SolarSystem::Moon, &t).unwrap();
|
|
134
134
|
/// println!("p = {}", p);
|
|
135
135
|
/// ```
|
|
136
136
|
///
|
|
@@ -453,11 +453,11 @@ impl JPLEphem {
|
|
|
453
453
|
/// 3-vector of cartesian Geocentric position in meters
|
|
454
454
|
///
|
|
455
455
|
fn geocentric_pos(&self, body: SolarSystem, tm: &AstroTime) -> SKResult<Vec3> {
|
|
456
|
-
if body == SolarSystem::
|
|
456
|
+
if body == SolarSystem::Moon {
|
|
457
457
|
return self.barycentric_pos(body, tm);
|
|
458
458
|
} else {
|
|
459
459
|
let emb: Vec3 = self.barycentric_pos(SolarSystem::EMB, tm)?;
|
|
460
|
-
let moon: Vec3 = self.barycentric_pos(SolarSystem::
|
|
460
|
+
let moon: Vec3 = self.barycentric_pos(SolarSystem::Moon, tm)?;
|
|
461
461
|
let b: Vec3 = self.barycentric_pos(body, tm)?;
|
|
462
462
|
|
|
463
463
|
// Compute the position of the body relative to the Earth-moon
|
|
@@ -483,11 +483,11 @@ impl JPLEphem {
|
|
|
483
483
|
/// Note: velocity is relative to Earth
|
|
484
484
|
///
|
|
485
485
|
fn geocentric_state(&self, body: SolarSystem, tm: &AstroTime) -> SKResult<(Vec3, Vec3)> {
|
|
486
|
-
if body == SolarSystem::
|
|
486
|
+
if body == SolarSystem::Moon {
|
|
487
487
|
return self.barycentric_state(body, tm);
|
|
488
488
|
} else {
|
|
489
489
|
let emb: (Vec3, Vec3) = self.barycentric_state(SolarSystem::EMB, tm)?;
|
|
490
|
-
let moon: (Vec3, Vec3) = self.barycentric_state(SolarSystem::
|
|
490
|
+
let moon: (Vec3, Vec3) = self.barycentric_state(SolarSystem::Moon, tm)?;
|
|
491
491
|
let b: (Vec3, Vec3) = self.barycentric_state(body, tm)?;
|
|
492
492
|
|
|
493
493
|
// Compute the position of the body relative to the Earth-moon
|
|
@@ -613,7 +613,7 @@ mod tests {
|
|
|
613
613
|
|
|
614
614
|
let tm = AstroTime::from_jd(2451545.0, Scale::TT);
|
|
615
615
|
//let tm = &AstroTime::from_jd(2451545.0, Scale::UTC);
|
|
616
|
-
let (_, _): (Vec3, Vec3) = jpl.geocentric_state(SolarSystem::
|
|
616
|
+
let (_, _): (Vec3, Vec3) = jpl.geocentric_state(SolarSystem::Moon, &tm).unwrap();
|
|
617
617
|
println!("au = {:.20}", jpl._au);
|
|
618
618
|
}
|
|
619
619
|
|
|
@@ -672,7 +672,7 @@ mod tests {
|
|
|
672
672
|
let (_mpos, mvel): (Vec3, Vec3) = jplephem_singleton()
|
|
673
673
|
.as_ref()
|
|
674
674
|
.unwrap()
|
|
675
|
-
.geocentric_state(SolarSystem::
|
|
675
|
+
.geocentric_state(SolarSystem::Moon, &tm)
|
|
676
676
|
.unwrap();
|
|
677
677
|
// Scale Earth velocity
|
|
678
678
|
tvel = tvel - mvel / (1.0 + jplephem_singleton().as_ref().unwrap().emrat);
|
|
@@ -682,7 +682,7 @@ mod tests {
|
|
|
682
682
|
let (_mpos, mvel): (Vec3, Vec3) = jplephem_singleton()
|
|
683
683
|
.as_ref()
|
|
684
684
|
.unwrap()
|
|
685
|
-
.geocentric_state(SolarSystem::
|
|
685
|
+
.geocentric_state(SolarSystem::Moon, &tm)
|
|
686
686
|
.unwrap();
|
|
687
687
|
//Scale Earth velocity
|
|
688
688
|
svel = svel - mvel / (1.0 + jplephem_singleton().as_ref().unwrap().emrat);
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
//! Keplerian orbital elements module
|
|
2
|
+
//!
|
|
3
|
+
|
|
4
|
+
// External library imports
|
|
5
|
+
use nalgebra::{Vector3, UnitQuaternion};
|
|
6
|
+
type Vec3 = Vector3<f64>;
|
|
7
|
+
type Quat = UnitQuaternion<f64>;
|
|
8
|
+
|
|
9
|
+
/// Keplerian Orbital Elements
|
|
10
|
+
///
|
|
11
|
+
/// The 6 Keplerian orbital elements are:
|
|
12
|
+
/// a: semi-major axis, meters
|
|
13
|
+
/// eccen: Eccentricity
|
|
14
|
+
/// incl: Inclination, radians
|
|
15
|
+
/// RAAN: Right Ascension of the Ascending Node, radians
|
|
16
|
+
/// w: Argument of Perigee, radians
|
|
17
|
+
/// nu: True Anomaly, radians
|
|
18
|
+
#[derive(Debug, Clone)]
|
|
19
|
+
pub struct Kepler {
|
|
20
|
+
pub a: f64,
|
|
21
|
+
pub eccen: f64,
|
|
22
|
+
pub incl: f64,
|
|
23
|
+
pub raan: f64,
|
|
24
|
+
pub w: f64,
|
|
25
|
+
pub nu: f64, // True anomaly
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
impl Kepler {
|
|
29
|
+
/// Create a new Keplerian orbital element object
|
|
30
|
+
///
|
|
31
|
+
/// # Arguments
|
|
32
|
+
///
|
|
33
|
+
/// * `a` - Semi-major axis, meters
|
|
34
|
+
/// * `e` - Eccentricity
|
|
35
|
+
/// * `i` - Inclination, radians
|
|
36
|
+
/// * `raan` - Right Ascension of the Ascending Node, radians
|
|
37
|
+
/// * `argp` - Argument of Perigee, radians
|
|
38
|
+
/// * `nu` - True Anomaly, radians
|
|
39
|
+
///
|
|
40
|
+
/// # Returns
|
|
41
|
+
///
|
|
42
|
+
/// * `Kepler` - A new Keplerian orbital element object
|
|
43
|
+
pub fn new(a: f64, e: f64, i: f64, raan: f64, argp: f64, nu: f64) -> Kepler {
|
|
44
|
+
Kepler {
|
|
45
|
+
a: a,
|
|
46
|
+
eccen: e,
|
|
47
|
+
incl: i,
|
|
48
|
+
raan: raan,
|
|
49
|
+
w: argp,
|
|
50
|
+
nu: nu,
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/// Convert Cartesian coordinates to Keplerian orbital elements
|
|
55
|
+
///
|
|
56
|
+
/// # Arguments
|
|
57
|
+
///
|
|
58
|
+
/// * `r` - Position vector, meters
|
|
59
|
+
/// * `v` - Velocity vector, meters/second
|
|
60
|
+
///
|
|
61
|
+
/// # Returns
|
|
62
|
+
///
|
|
63
|
+
/// * `Kepler` - A new Keplerian orbital element object
|
|
64
|
+
///
|
|
65
|
+
pub fn from_pv(r: Vec3, v: Vec3) -> Kepler {
|
|
66
|
+
let h = r.cross(&v);
|
|
67
|
+
let n = Vec3::z_axis().cross(&h);
|
|
68
|
+
let e =
|
|
69
|
+
((v.norm_squared() -
|
|
70
|
+
crate::consts::MU_EARTH / r.norm()) * r - r.dot(&v) * v) / crate::consts::MU_EARTH;
|
|
71
|
+
let eccen = e.norm();
|
|
72
|
+
let xi = v.norm().powi(2) / 2.0 - crate::consts::MU_EARTH / r.norm();
|
|
73
|
+
let a = -crate::consts::MU_EARTH / (2.0 * xi);
|
|
74
|
+
let incl = (h.z/h.norm()).acos();
|
|
75
|
+
let mut raan = (n.x/n.norm()).acos();
|
|
76
|
+
if n.y < 0.0 {
|
|
77
|
+
raan = 2.0 * std::f64::consts::PI - raan;
|
|
78
|
+
}
|
|
79
|
+
let mut w = (n.dot(&e)/n.norm()/e.norm()).acos();
|
|
80
|
+
if e.z < 0.0 {
|
|
81
|
+
w = 2.0 * std::f64::consts::PI - w;
|
|
82
|
+
}
|
|
83
|
+
let mut nu = (r.dot(&e)/r.norm()/e.norm()).acos();
|
|
84
|
+
if r.dot(&v) < 0.0 {
|
|
85
|
+
nu = 2.0 * std::f64::consts::PI - nu;
|
|
86
|
+
}
|
|
87
|
+
Kepler::new(a, eccen, incl, raan, w, nu)
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/// Convert Keplerian orbital elements to Cartesian coordinates
|
|
91
|
+
///
|
|
92
|
+
/// # Returns
|
|
93
|
+
///
|
|
94
|
+
/// * `(Vec3, Vec3)` - Position and velocity vectors, meters and meters/second
|
|
95
|
+
///
|
|
96
|
+
pub fn to_pv(&self) -> (Vec3, Vec3) {
|
|
97
|
+
let p = self.a * (1.0 - self.eccen.powi(2));
|
|
98
|
+
let r = p / (1.0 + self.eccen * self.nu.cos());
|
|
99
|
+
let r_pqw = Vec3::new(r * self.nu.cos(), r * self.nu.sin(), 0.0);
|
|
100
|
+
let v_pqw = Vec3::new(
|
|
101
|
+
-self.nu.sin(),
|
|
102
|
+
self.eccen + self.nu.cos(),
|
|
103
|
+
0.0) * (crate::consts::MU_EARTH/p).sqrt();
|
|
104
|
+
let q = Quat::from_axis_angle(&Vec3::z_axis(), self.raan) *
|
|
105
|
+
Quat::from_axis_angle(&Vec3::x_axis(), self.incl) *
|
|
106
|
+
Quat::from_axis_angle(&Vec3::z_axis(), self.w);
|
|
107
|
+
(q * r_pqw, q * v_pqw)
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
impl std::fmt::Display for Kepler {
|
|
112
|
+
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
|
113
|
+
write!(f,
|
|
114
|
+
"Keplerian Elements:\n a = {:.0} m\n e = {:.3}\n i = {:.3} rad\n",
|
|
115
|
+
self.a, self.eccen, self.incl)?;
|
|
116
|
+
write!(f, " Ω = {:.3} rad\n ω = {:.3} rad\n ν = {:.3} rad\n", self.raan, self.w, self.nu)
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
#[cfg(test)]
|
|
121
|
+
mod tests {
|
|
122
|
+
use super::*;
|
|
123
|
+
|
|
124
|
+
#[test]
|
|
125
|
+
fn test_topv() {
|
|
126
|
+
// Example 2-6 from Vallado
|
|
127
|
+
let p = 11067790.0;
|
|
128
|
+
let eccen = 0.83285_f64;
|
|
129
|
+
let incl = 87.87_f64.to_radians();
|
|
130
|
+
let raan = 227.89_f64.to_radians();
|
|
131
|
+
let w = 53.38_f64.to_radians();
|
|
132
|
+
let nu = 92.335_f64.to_radians();
|
|
133
|
+
|
|
134
|
+
let a = p / (1.0 - eccen.powi(2));
|
|
135
|
+
|
|
136
|
+
let k = Kepler::new(a, eccen, incl, raan, w, nu);
|
|
137
|
+
let (r, v) = k.to_pv();
|
|
138
|
+
// Note: values below are not incorrect in the book, but are
|
|
139
|
+
// corrected in the online errata
|
|
140
|
+
// See: https://celestrak.org/software/vallado/ErrataVer4.pdf
|
|
141
|
+
assert!((r*1.0e-3 - Vec3::new(6525.368, 6861.532, 6449.119)).norm() < 1e-3);
|
|
142
|
+
assert!((v*1.0e-3 - Vec3::new(4.902279, 5.533140, -1.975710)).norm() < 1e-3);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
#[test]
|
|
146
|
+
fn test_frompv() {
|
|
147
|
+
// Vallado example 2-5
|
|
148
|
+
let r = Vec3::new(6524.834, 6862.875, 6448.296)*1.0e3;
|
|
149
|
+
let v = Vec3::new(4.901327, 5.533756, -1.976341)*1.0e3;
|
|
150
|
+
let k = Kepler::from_pv(r, v);
|
|
151
|
+
assert!((k.a - 36127343_f64).abs() < 1.0e3);
|
|
152
|
+
assert!((k.eccen - 0.83285).abs() < 1e-3);
|
|
153
|
+
assert!((k.incl - 87.87_f64.to_radians()).abs() < 1e-3);
|
|
154
|
+
assert!((k.raan - 227.89_f64.to_radians()).abs() < 1e-3);
|
|
155
|
+
assert!((k.w - 53.38_f64.to_radians()).abs() < 1e-3);
|
|
156
|
+
assert!((k.nu - 92.335_f64.to_radians()).abs() < 1e-3);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|