astrox-python 1.0.0__py3-none-any.whl → 1.2.0__py3-none-any.whl
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.
- astrox/celestial.py +60 -4
- astrox/orbits.py +38 -6
- astrox/propagator.py +31 -0
- {astrox_python-1.0.0.dist-info → astrox_python-1.2.0.dist-info}/METADATA +1 -1
- {astrox_python-1.0.0.dist-info → astrox_python-1.2.0.dist-info}/RECORD +7 -7
- {astrox_python-1.0.0.dist-info → astrox_python-1.2.0.dist-info}/WHEEL +0 -0
- {astrox_python-1.0.0.dist-info → astrox_python-1.2.0.dist-info}/licenses/LICENSE +0 -0
astrox/celestial.py
CHANGED
|
@@ -74,6 +74,9 @@ class MpcOrbitalElements:
|
|
|
74
74
|
raan_deg: float | None = None
|
|
75
75
|
argument_of_periapsis_deg: float | None = None
|
|
76
76
|
mean_anomaly_deg: float | None = None
|
|
77
|
+
reference_frame: str | None = None
|
|
78
|
+
"""Heliocentric mean-ecliptic variant: ``MeanEclpJ2000`` (JPL) or
|
|
79
|
+
``EclpJ2000ICRF`` (MPC, server default)."""
|
|
77
80
|
|
|
78
81
|
def __post_init__(self) -> None:
|
|
79
82
|
for field_name in (
|
|
@@ -95,9 +98,14 @@ class MpcOrbitalElements:
|
|
|
95
98
|
parameter=field_name,
|
|
96
99
|
),
|
|
97
100
|
)
|
|
101
|
+
object.__setattr__(
|
|
102
|
+
self,
|
|
103
|
+
"reference_frame",
|
|
104
|
+
_optional_string(self.reference_frame, parameter="reference_frame"),
|
|
105
|
+
)
|
|
98
106
|
|
|
99
|
-
def to_wire(self) -> dict[str,
|
|
100
|
-
payload: dict[str,
|
|
107
|
+
def to_wire(self) -> dict[str, Any]:
|
|
108
|
+
payload: dict[str, Any] = {}
|
|
101
109
|
_include_if_supplied(payload, "EpochMjdTdt", self.epoch_mjd_tdt)
|
|
102
110
|
_include_if_supplied(payload, "PeriTimeMjdTdt", self.periapsis_time_mjd_tdt)
|
|
103
111
|
_include_if_supplied(payload, "Q", self.periapsis_distance_au)
|
|
@@ -111,6 +119,7 @@ class MpcOrbitalElements:
|
|
|
111
119
|
self.argument_of_periapsis_deg,
|
|
112
120
|
)
|
|
113
121
|
_include_if_supplied(payload, "MeanAnomaly", self.mean_anomaly_deg)
|
|
122
|
+
_include_if_supplied(payload, "ReferenceFrame", self.reference_frame)
|
|
114
123
|
return payload
|
|
115
124
|
|
|
116
125
|
|
|
@@ -125,6 +134,7 @@ def mpc_orbital_elements(
|
|
|
125
134
|
raan_deg: float | None = None,
|
|
126
135
|
argument_of_periapsis_deg: float | None = None,
|
|
127
136
|
mean_anomaly_deg: float | None = None,
|
|
137
|
+
reference_frame: str | None = None,
|
|
128
138
|
) -> MpcOrbitalElements:
|
|
129
139
|
"""Build an MPC orbital-element fragment without adding physics policy."""
|
|
130
140
|
return MpcOrbitalElements(
|
|
@@ -137,6 +147,7 @@ def mpc_orbital_elements(
|
|
|
137
147
|
raan_deg=raan_deg,
|
|
138
148
|
argument_of_periapsis_deg=argument_of_periapsis_deg,
|
|
139
149
|
mean_anomaly_deg=mean_anomaly_deg,
|
|
150
|
+
reference_frame=reference_frame,
|
|
140
151
|
)
|
|
141
152
|
|
|
142
153
|
|
|
@@ -153,7 +164,7 @@ def _elements_to_wire(
|
|
|
153
164
|
value: MpcOrbitalElements | None,
|
|
154
165
|
*,
|
|
155
166
|
parameter: str,
|
|
156
|
-
) -> dict[str,
|
|
167
|
+
) -> dict[str, Any] | None:
|
|
157
168
|
if value is None:
|
|
158
169
|
return None
|
|
159
170
|
if not isinstance(value, MpcOrbitalElements):
|
|
@@ -175,6 +186,9 @@ def lambert_transfer_window(
|
|
|
175
186
|
arrival_step_days: float | None = None,
|
|
176
187
|
departure_elements: MpcOrbitalElements | None = None,
|
|
177
188
|
arrival_elements: MpcOrbitalElements | None = None,
|
|
189
|
+
max_departure_delta_v_m_s: int | None = None,
|
|
190
|
+
max_arrival_delta_v_m_s: int | None = None,
|
|
191
|
+
max_time_of_flight_days: int | None = None,
|
|
178
192
|
) -> dict[str, Any]:
|
|
179
193
|
"""Return a Lambert transfer-window scan from ASTROX.
|
|
180
194
|
|
|
@@ -236,6 +250,30 @@ def lambert_transfer_window(
|
|
|
236
250
|
"ArrivalElements",
|
|
237
251
|
_elements_to_wire(arrival_elements, parameter="arrival_elements"),
|
|
238
252
|
)
|
|
253
|
+
_include_if_supplied(
|
|
254
|
+
payload,
|
|
255
|
+
"MaxDepartureDV",
|
|
256
|
+
_optional_integer(
|
|
257
|
+
max_departure_delta_v_m_s,
|
|
258
|
+
parameter="max_departure_delta_v_m_s",
|
|
259
|
+
),
|
|
260
|
+
)
|
|
261
|
+
_include_if_supplied(
|
|
262
|
+
payload,
|
|
263
|
+
"MaxArrivalDV",
|
|
264
|
+
_optional_integer(
|
|
265
|
+
max_arrival_delta_v_m_s,
|
|
266
|
+
parameter="max_arrival_delta_v_m_s",
|
|
267
|
+
),
|
|
268
|
+
)
|
|
269
|
+
_include_if_supplied(
|
|
270
|
+
payload,
|
|
271
|
+
"MaxTofDays",
|
|
272
|
+
_optional_integer(
|
|
273
|
+
max_time_of_flight_days,
|
|
274
|
+
parameter="max_time_of_flight_days",
|
|
275
|
+
),
|
|
276
|
+
)
|
|
239
277
|
return _without_status_fields(
|
|
240
278
|
raw.post("/celestial/transfer", json=payload),
|
|
241
279
|
endpoint="/celestial/transfer",
|
|
@@ -331,8 +369,16 @@ def mpc_ephemeris(
|
|
|
331
369
|
observer_frame: str | None = None,
|
|
332
370
|
start: str | None = None,
|
|
333
371
|
stop: str | None = None,
|
|
372
|
+
step_s: float | None = None,
|
|
373
|
+
target_elements: MpcOrbitalElements | None = None,
|
|
334
374
|
) -> dict[str, Any]:
|
|
335
|
-
"""Return ASTROX minor-planet ephemeris output from its MPC-backed route.
|
|
375
|
+
"""Return ASTROX minor-planet ephemeris output from its MPC-backed route.
|
|
376
|
+
|
|
377
|
+
When ``target_elements`` is supplied, the server integrates those MPC
|
|
378
|
+
orbital elements directly instead of resolving ``target_name`` through the
|
|
379
|
+
MPC network query. ``step_s`` controls the output sampling cadence; zero
|
|
380
|
+
requests the server's internal integration grid.
|
|
381
|
+
"""
|
|
336
382
|
payload: dict[str, Any] = {
|
|
337
383
|
"TargetName": _string(target_name, parameter="target_name"),
|
|
338
384
|
}
|
|
@@ -351,6 +397,16 @@ def mpc_ephemeris(
|
|
|
351
397
|
"Stop",
|
|
352
398
|
_optional_string(stop, parameter="stop"),
|
|
353
399
|
)
|
|
400
|
+
_include_if_supplied(
|
|
401
|
+
payload,
|
|
402
|
+
"Step",
|
|
403
|
+
_optional_number(step_s, parameter="step_s"),
|
|
404
|
+
)
|
|
405
|
+
_include_if_supplied(
|
|
406
|
+
payload,
|
|
407
|
+
"TargetElements",
|
|
408
|
+
_elements_to_wire(target_elements, parameter="target_elements"),
|
|
409
|
+
)
|
|
354
410
|
return _without_status_fields(
|
|
355
411
|
raw.post("/celestial/mpc", json=payload),
|
|
356
412
|
endpoint="/celestial/mpc",
|
astrox/orbits.py
CHANGED
|
@@ -11,6 +11,7 @@ from astrox._http import raw
|
|
|
11
11
|
__all__ = [
|
|
12
12
|
"CartesianState",
|
|
13
13
|
"KeplerianElements",
|
|
14
|
+
"LambertResult",
|
|
14
15
|
"MeanKeplerianElements",
|
|
15
16
|
"Tle",
|
|
16
17
|
"cartesian_state",
|
|
@@ -517,14 +518,37 @@ def geo_ym_lambert_delta_v(
|
|
|
517
518
|
)
|
|
518
519
|
|
|
519
520
|
|
|
521
|
+
@dataclass(frozen=True, kw_only=True)
|
|
522
|
+
class LambertResult:
|
|
523
|
+
"""Single-case Lambert solution with the sampled transfer positions."""
|
|
524
|
+
|
|
525
|
+
departure_delta_v_m_s: tuple[float, float, float]
|
|
526
|
+
arrival_delta_v_m_s: tuple[float, float, float]
|
|
527
|
+
positions: tuple[float, ...]
|
|
528
|
+
"""Flat ``(x, y, z, ...)`` transfer position sequence in meters.
|
|
529
|
+
|
|
530
|
+
The server samples ``path_point_count`` points including the departure and
|
|
531
|
+
arrival positions, so the sequence length is ``path_point_count * 3``.
|
|
532
|
+
"""
|
|
533
|
+
|
|
534
|
+
|
|
520
535
|
def lambert_delta_v(
|
|
521
536
|
*,
|
|
522
537
|
departure_state: CartesianState,
|
|
523
538
|
arrival_state: CartesianState,
|
|
524
539
|
time_of_flight_s: float,
|
|
525
540
|
gravitational_parameter_m3_s2: float | None = None,
|
|
526
|
-
|
|
527
|
-
|
|
541
|
+
get_path_points: bool = False,
|
|
542
|
+
path_point_count: int | None = None,
|
|
543
|
+
) -> tuple[tuple[float, float, float], tuple[float, float, float]] | LambertResult:
|
|
544
|
+
"""Return single-revolution Lambert delta-v between two Cartesian states.
|
|
545
|
+
|
|
546
|
+
By default returns ``(departure_delta_v_m_s, arrival_delta_v_m_s)``. When
|
|
547
|
+
``get_path_points`` is true, the server also samples the transfer orbit and
|
|
548
|
+
the return is a :class:`LambertResult` carrying the delta-v pair plus the
|
|
549
|
+
flat position sequence; ``path_point_count`` sets the sample count
|
|
550
|
+
(server default 100, including both endpoints).
|
|
551
|
+
"""
|
|
528
552
|
if not isinstance(departure_state, CartesianState):
|
|
529
553
|
raise TypeError("departure_state must be a CartesianState instance")
|
|
530
554
|
if not isinstance(arrival_state, CartesianState):
|
|
@@ -536,12 +560,20 @@ def lambert_delta_v(
|
|
|
536
560
|
"TOF": [time_of_flight_s],
|
|
537
561
|
}
|
|
538
562
|
_include_if_supplied(payload, "Gm", gravitational_parameter_m3_s2)
|
|
563
|
+
if get_path_points:
|
|
564
|
+
payload["GetPathPoints"] = True
|
|
565
|
+
_include_if_supplied(payload, "NumberOfPathPoints", path_point_count)
|
|
539
566
|
|
|
540
567
|
result = raw.post("/orbit/lambert", json=payload)
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
568
|
+
departure_delta_v = (result["DV1"][0], result["DV1"][1], result["DV1"][2])
|
|
569
|
+
arrival_delta_v = (result["DV2"][0], result["DV2"][1], result["DV2"][2])
|
|
570
|
+
if get_path_points:
|
|
571
|
+
return LambertResult(
|
|
572
|
+
departure_delta_v_m_s=departure_delta_v,
|
|
573
|
+
arrival_delta_v_m_s=arrival_delta_v,
|
|
574
|
+
positions=tuple(result["Positions"]),
|
|
575
|
+
)
|
|
576
|
+
return departure_delta_v, arrival_delta_v
|
|
545
577
|
|
|
546
578
|
|
|
547
579
|
def convert_czml_position(
|
astrox/propagator.py
CHANGED
|
@@ -42,6 +42,7 @@ __all__ = [
|
|
|
42
42
|
"sgp4",
|
|
43
43
|
"simple_ascent",
|
|
44
44
|
"two_body",
|
|
45
|
+
"two_body_rv",
|
|
45
46
|
]
|
|
46
47
|
|
|
47
48
|
|
|
@@ -672,6 +673,36 @@ def two_body(
|
|
|
672
673
|
return _success_path(result)
|
|
673
674
|
|
|
674
675
|
|
|
676
|
+
def two_body_rv(
|
|
677
|
+
*,
|
|
678
|
+
state: CartesianState,
|
|
679
|
+
time_of_flight_s: float,
|
|
680
|
+
gravitational_parameter_m3_s2: float | None = None,
|
|
681
|
+
step_s: float | None = None,
|
|
682
|
+
) -> tuple[float, ...]:
|
|
683
|
+
"""Propagate a Cartesian state with two-body dynamics and return the sampled ephemeris.
|
|
684
|
+
|
|
685
|
+
Returns the flat ``[t, x, y, z, vx, vy, vz, ...]`` sequence, where ``t`` is
|
|
686
|
+
seconds relative to the initial epoch, positions are in meters, and
|
|
687
|
+
velocities are in m/s. The sequence includes the start and stop samples;
|
|
688
|
+
intermediate samples follow ``step_s`` (server default 60 s).
|
|
689
|
+
"""
|
|
690
|
+
if not isinstance(state, CartesianState):
|
|
691
|
+
raise TypeError("state must be a CartesianState instance")
|
|
692
|
+
|
|
693
|
+
payload: dict[str, Any] = {
|
|
694
|
+
"RV0": state.to_wire(),
|
|
695
|
+
"TimeOfFlight": time_of_flight_s,
|
|
696
|
+
}
|
|
697
|
+
if gravitational_parameter_m3_s2 is not None:
|
|
698
|
+
payload["Gm"] = gravitational_parameter_m3_s2
|
|
699
|
+
if step_s is not None:
|
|
700
|
+
payload["Step"] = step_s
|
|
701
|
+
|
|
702
|
+
result = raw.post("/Propagator/TwoBodyRV", json=payload)
|
|
703
|
+
return tuple(result["Positions"])
|
|
704
|
+
|
|
705
|
+
|
|
675
706
|
def j2(
|
|
676
707
|
*,
|
|
677
708
|
start: str,
|
|
@@ -3,13 +3,13 @@ astrox/_http.py,sha256=ZZDkJ6qPG4VbMDRZO7xonIib88aYS6PPTVRxRYwXU3A,15606
|
|
|
3
3
|
astrox/access.py,sha256=pjyCher_yQNmkoojf2sWpG1HRDnLLK9gI90jM1iEoTo,5817
|
|
4
4
|
astrox/cat.py,sha256=doZqy6lGDtgrVe9QlU57l1lccmzirc14RDSR41tyGUU,15057
|
|
5
5
|
astrox/catalog.py,sha256=WDb3adiDO41YY6IdivjN3ri1vIQMHi6DPI3dBa8W1Gc,5255
|
|
6
|
-
astrox/celestial.py,sha256=
|
|
6
|
+
astrox/celestial.py,sha256=EFuKRyZ2uMsjqdRCDTdwDsA3QuzstIU98DwWj8t-Btk,12703
|
|
7
7
|
astrox/conjunction.py,sha256=sXhTNAlMai27ejuJekksaAw-850nHPimo21YdFpuzQo,9108
|
|
8
8
|
astrox/exceptions.py,sha256=apClRT1r-N3XY1ibXxkW3oxpsJgiHos4tC0cMJ8eBRk,2592
|
|
9
9
|
astrox/libration.py,sha256=YBgcZi2pTAjL5VUlE8y6jLhVbYnwRxv-PIUxJQmFBSg,13454
|
|
10
10
|
astrox/lighting.py,sha256=aWMty64rU3wv1H1Q5q-yXG5mINbIY31omyd-pjdNaVs,3876
|
|
11
|
-
astrox/orbits.py,sha256=
|
|
12
|
-
astrox/propagator.py,sha256=
|
|
11
|
+
astrox/orbits.py,sha256=SdRE7f9W9zO4N6Xxjg5quHK--gsVh1E5qdvJigpwxLA,19223
|
|
12
|
+
astrox/propagator.py,sha256=GPcg5fpra_jsof4ipxgtaeJNof2PrWBvUTnDG1aH940,38434
|
|
13
13
|
astrox/rocket.py,sha256=tb6wXc4bZ0EMAd9bVzva_7k3I9S2lsYA7Q2RD6byqfk,2755
|
|
14
14
|
astrox/terrain.py,sha256=2v_Ca5OnXjmMtIKNFQJ_Kbdsh42ZuIc4ZDe-0aWnpdg,6146
|
|
15
15
|
astrox/astrogator/__init__.py,sha256=rgIHos9rHjQ3i-qkpLeLRwZL6zsVthc2bOVbAdwHWHU,267
|
|
@@ -33,7 +33,7 @@ astrox/coverage/number_of_assets.py,sha256=Bf1OQRu1r9lunyARyQoV4x7KetkgY_7OMNcEc
|
|
|
33
33
|
astrox/coverage/response_time.py,sha256=yLnv8eEDL6CS0PJHC1JIKBCoOachOwo3m8dNoHH3HfQ,5164
|
|
34
34
|
astrox/coverage/revisit_time.py,sha256=R5vF2egixCF9elvsGYXzpgWbD5lfcQW8uZqi1ifIDX8,5155
|
|
35
35
|
astrox/coverage/simple_coverage.py,sha256=ZPj3HrP3M59rG47pz4eHt1rq-vTlk-oZ7c2ZBmFsz1U,4992
|
|
36
|
-
astrox_python-1.
|
|
37
|
-
astrox_python-1.
|
|
38
|
-
astrox_python-1.
|
|
39
|
-
astrox_python-1.
|
|
36
|
+
astrox_python-1.2.0.dist-info/METADATA,sha256=wh8FRFOydoqxg-BeW5pnZZj1Pz5i_zaC_TxamnoA5mw,2520
|
|
37
|
+
astrox_python-1.2.0.dist-info/WHEEL,sha256=zOwg4jB6zX2kU910N-cMawjivD6tO8NEWvE12je1bVk,87
|
|
38
|
+
astrox_python-1.2.0.dist-info/licenses/LICENSE,sha256=Fbt55lCQnv_n5yGhbG_VDlowjaV_FPHBQWsJIyuBpDk,1062
|
|
39
|
+
astrox_python-1.2.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|