Skip to content

Commit bb398eb

Browse files
committed
[#144] Correct noncircular orbit generation
1 parent 6237646 commit bb398eb

6 files changed

Lines changed: 66 additions & 22 deletions

File tree

docs/source/release_notes.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ Development - |version|
3838
* Allow for per-episode randomization of :class:`ResourceReward` weights and observation
3939
of those weights with :class:`ResourceRewardWeight`.
4040
* Add :class:`ImpulsiveThrustHill` for impulsive thrust in the Hill frame.
41+
* Separate :class:`random_circular_orbit` and :class:`random_orbit` to avoid misleading
42+
altitude argument.
43+
4144

4245
Version 1.1.0
4346
-------------

src/bsk_rl/utils/orbital.py

Lines changed: 50 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,33 +21,48 @@
2121

2222

2323
def random_orbit(
24-
i: Optional[float] = 45.0,
25-
alt: float = 500,
26-
r_body: float = 6371,
24+
i: Optional[float] = None,
25+
a: Optional[float] = 6371 + 500,
2726
e: float = 0,
2827
Omega: Optional[float] = None,
29-
omega: Optional[float] = 0,
28+
omega: Optional[float] = None,
3029
f: Optional[float] = None,
30+
alt: float = None,
31+
r_body: float = 6371,
3132
) -> ClassicElements:
3233
"""Create a set of orbit elements.
3334
3435
Parameters are fixed if specified and randomized if ``None``. Defaults to a random
35-
circular orbit at 500 km altitude and 45 deg inclination.
36+
circular orbit at 500 km altitude.
3637
3738
Args:
3839
i: [deg] Inclination, randomized in ``[-pi, pi]``.
39-
alt: [km] Altitude above r_body.
40-
r_body: [km] Body radius.
40+
a: [km] Semi-major axis.
4141
e: Eccentricity.
4242
Omega: [deg] LAN, randomized in ``[0, 2pi]``.
4343
omega: [deg] Argument of periapsis, randomized in ``[0, 2pi]``.
4444
f: [deg] True anomaly, randomized in ``[0, 2pi]``.
45+
alt: [km] (deprecated) Altitude above r_body.
46+
r_body: [km] (deprecated) Body radius.
4547
4648
Returns:
4749
ClassicElements: orbital elements
4850
"""
51+
if alt is not None:
52+
logger.warning(
53+
"Ignoring a, e, and omega and using alt and r_body to generate a circular orbit."
54+
"random_circular_orbit is preferred for this use case."
55+
)
56+
return random_circular_orbit(
57+
i=i,
58+
alt=alt,
59+
r_body=r_body,
60+
Omega=Omega,
61+
f=f,
62+
)
63+
4964
oe = ClassicElements()
50-
oe.a = (r_body + alt) * 1e3
65+
oe.a = a * 1e3
5166
oe.e = e
5267
oe.i = np.radians(i) if i is not None else np.random.uniform(-np.pi, np.pi)
5368
oe.Omega = (
@@ -60,6 +75,32 @@ def random_orbit(
6075
return oe
6176

6277

78+
def random_circular_orbit(
79+
i: Optional[float] = None,
80+
alt: float = 500,
81+
r_body: float = 6371,
82+
Omega: Optional[float] = None,
83+
f: Optional[float] = None,
84+
):
85+
"""Create a set of orbit elements for a circular orbit.
86+
87+
Parameters are fixed if specified and randomized if ``None``.
88+
89+
Args:
90+
i: [deg] Inclination, randomized in ``[-pi, pi]``.
91+
alt: [km] Altitude above r_body.
92+
r_body: [km] Body radius, defaults to Earth's radius.
93+
Omega: [deg] LAN, randomized in ``[0, 2pi]``.
94+
f: [deg] True anomaly, randomized in ``[0, 2pi]``.
95+
96+
"""
97+
omega = 0
98+
e = 0
99+
a = r_body + alt
100+
101+
return random_orbit(i=i, a=a, e=e, Omega=Omega, omega=omega, f=f)
102+
103+
63104
def random_epoch(start: int = 2000, end: int = 2022):
64105
"""Generate a random epoch in a year range.
65106
@@ -616,6 +657,7 @@ def hill2cd(
616657
__doc_title__ = "Orbital"
617658
__all__ = [
618659
"random_orbit",
660+
"random_circular_orbit",
619661
"random_epoch",
620662
"lla2ecef",
621663
"elevation",

tests/integration/act/test_int_actions_discrete.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ class ChargeSat(sats.Satellite):
8686
"Charger",
8787
sat_args=ChargeSat.default_sat_args(
8888
# High, inclined orbit makes eclipse unlikely
89-
oe=random_orbit(alt=50000, i=90),
89+
oe=random_orbit(a=50000, i=90),
9090
batteryStorageCapacity=500_000,
9191
storedCharge_Init=250_000,
9292
),

tests/integration/obs/test_int_observations.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,7 @@ class SatPropertiesSat(sats.Satellite):
7171
"SatelliteTasking-v1",
7272
satellite=SatPropertiesSat(
7373
"Sputnik",
74-
sat_args=SatPropertiesSat.default_sat_args(
75-
oe=random_orbit(r_body=7000, alt=0, i=45)
76-
),
74+
sat_args=SatPropertiesSat.default_sat_args(oe=random_orbit(a=7000, i=45)),
7775
),
7876
scenario=UniformTargets(n_targets=0),
7977
rewarder=data.NoReward(),

tests/integration/obs/test_int_relative_observations.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,17 +28,13 @@ class RelPropertiesSat(sats.Satellite):
2828
RelPropertiesSat(
2929
"Deputy",
3030
sat_args=dict(
31-
oe=random_orbit(
32-
i=1.0, alt=1000.0, e=0.0, Omega=0.0, omega=0.0, f=0.0
33-
)
31+
oe=random_orbit(i=1.0, a=7000.0, e=0.0, Omega=0.0, omega=0.0, f=0.0)
3432
),
3533
),
3634
BasicSat(
3735
"Chief",
3836
sat_args=dict(
39-
oe=random_orbit(
40-
i=1.0, alt=1100.0, e=0.0, Omega=0.0, omega=0.0, f=0.0
41-
)
37+
oe=random_orbit(i=1.0, a=7100.0, e=0.0, Omega=0.0, omega=0.0, f=0.0)
4238
),
4339
),
4440
],

tests/unittest/utils/test_orbital.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,13 @@ def test_random_orbit(self):
1717
assert 0 <= oe.omega <= 2 * np.pi
1818
assert 0 <= oe.f <= 2 * np.pi
1919

20+
@pytest.mark.repeat(10)
21+
def test_random_circular_orbit(self):
22+
oe = orbital.random_circular_orbit(i=None, Omega=None, f=None)
23+
assert -np.pi <= oe.i <= np.pi
24+
assert 0 <= oe.Omega <= 2 * np.pi
25+
assert 0 <= oe.f <= 2 * np.pi
26+
2027
def test_repeatable(self):
2128
np.random.seed(0)
2229
oe1 = orbital.random_orbit()
@@ -25,9 +32,7 @@ def test_repeatable(self):
2532
assert oe1.f == oe2.f
2633

2734
def test_units(self):
28-
oe = orbital.random_orbit(
29-
i=90.0, alt=500, r_body=1000, e=0.1, Omega=90.0, omega=90.0, f=90.0
30-
)
35+
oe = orbital.random_orbit(i=90.0, a=1500, e=0.1, Omega=90.0, omega=90.0, f=90.0)
3136
assert oe.a == 1500000
3237
assert oe.e == 0.1
3338
assert np.pi / 2 == oe.i == oe.Omega == oe.omega == oe.f
@@ -198,7 +203,7 @@ def test_eclipse(self):
198203
def test_no_eclipse(self):
199204
ts = orbital.TrajectorySimulator(
200205
self.epoch,
201-
oe=orbital.random_orbit(alt=50000, i=90.0, omega=0, Omega=0, f=45.0),
206+
oe=orbital.random_orbit(a=50000, i=90.0, omega=0, Omega=0, f=45.0),
202207
mu=self.mu,
203208
)
204209
assert ts.next_eclipse(0, max_tries=3) == (1.0, 1.0)

0 commit comments

Comments
 (0)