astrox-python 1.0.0__tar.gz → 1.2.0__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.
- {astrox_python-1.0.0 → astrox_python-1.2.0}/.gitignore +4 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/PKG-INFO +1 -1
- {astrox_python-1.0.0 → astrox_python-1.2.0}/astrox/celestial.py +60 -4
- {astrox_python-1.0.0 → astrox_python-1.2.0}/astrox/orbits.py +38 -6
- {astrox_python-1.0.0 → astrox_python-1.2.0}/astrox/propagator.py +31 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/docs/how_to/compute_lambert_transfer.md +10 -3
- {astrox_python-1.0.0 → astrox_python-1.2.0}/docs/how_to/propagate_an_orbit.md +3 -1
- {astrox_python-1.0.0 → astrox_python-1.2.0}/docs/i18n/en/how_to/compute_lambert_transfer.md +11 -3
- {astrox_python-1.0.0 → astrox_python-1.2.0}/docs/i18n/en/how_to/propagate_an_orbit.md +3 -1
- {astrox_python-1.0.0 → astrox_python-1.2.0}/docs/i18n/en/manual/celestial/README.md +36 -15
- {astrox_python-1.0.0 → astrox_python-1.2.0}/docs/i18n/en/manual/orbits/README.md +18 -2
- {astrox_python-1.0.0 → astrox_python-1.2.0}/docs/i18n/en/manual/propagator/README.md +40 -1
- {astrox_python-1.0.0 → astrox_python-1.2.0}/docs/manual/celestial/README.md +36 -15
- {astrox_python-1.0.0 → astrox_python-1.2.0}/docs/manual/orbits/README.md +18 -2
- {astrox_python-1.0.0 → astrox_python-1.2.0}/docs/manual/propagator/README.md +40 -1
- {astrox_python-1.0.0 → astrox_python-1.2.0}/docs/test-principles.md +2 -0
- astrox_python-1.2.0/docs/validation/celestial.md +70 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/docs/validation/libration.md +1 -1
- {astrox_python-1.0.0 → astrox_python-1.2.0}/docs/validation/orbits.md +5 -3
- {astrox_python-1.0.0 → astrox_python-1.2.0}/docs/validation/propagator.md +26 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/examples/01_propagation/README.md +3 -1
- astrox_python-1.2.0/examples/01_propagation/two_body_rv.py +38 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/examples/02_orbits/lambert_delta_v.py +14 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/examples/11_celestial/celestial_queries.py +9 -3
- {astrox_python-1.0.0 → astrox_python-1.2.0}/pyproject.toml +2 -2
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/sdk/celestial/test_celestial.py +144 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/sdk/orbits/test_conversions.py +95 -4
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/sdk/propagator/test_public_contract.py +1 -0
- astrox_python-1.2.0/tests/sdk/propagator/test_two_body_rv.py +138 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/README.md +15 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/cross_validation/celestial/test_cb_axes_rotation_invariants.py +54 -2
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/cross_validation/celestial/test_ephemeris_skyfield.py +59 -6
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/cross_validation/celestial/test_lambert_transfer_lamberthub.py +262 -14
- astrox_python-1.2.0/tests/validation/cross_validation/celestial/test_mpc_target_elements.py +307 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/cross_validation/libration/test_e2m2e_qualification.py +2 -14
- astrox_python-1.2.0/tests/validation/cross_validation/orbits/test_lambert_path_points.py +172 -0
- astrox_python-1.2.0/tests/validation/cross_validation/propagator/test_two_body_rv_brahe.py +228 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/live_snapshot/astrogator/test_run_mcs.py +4 -1
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/live_snapshot/celestial/celestial.snap.json +18 -3
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/live_snapshot/celestial/test_celestial.py +11 -3
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/live_snapshot/orbits/conversions.snap.json +28 -1
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/live_snapshot/orbits/test_conversions.py +16 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/live_snapshot/propagator/test_two_body.py +22 -1
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/live_snapshot/propagator/two_body.snap.json +32 -1
- {astrox_python-1.0.0 → astrox_python-1.2.0}/uv.lock +35 -24
- astrox_python-1.0.0/docs/validation/celestial.md +0 -59
- {astrox_python-1.0.0 → astrox_python-1.2.0}/LICENSE +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/README.md +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/astrox/__init__.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/astrox/_http.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/astrox/access.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/astrox/astrogator/__init__.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/astrox/astrogator/_api.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/astrox/astrogator/_models.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/astrox/astrogator/_results.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/astrox/cat.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/astrox/catalog.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/astrox/components/__init__.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/astrox/components/_axes.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/astrox/components/_common.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/astrox/components/_constraints.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/astrox/components/_objects.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/astrox/components/_positions.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/astrox/components/_rotations.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/astrox/components/_sensors.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/astrox/components/_vgt.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/astrox/conjunction.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/astrox/coverage/__init__.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/astrox/coverage/_core.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/astrox/coverage/_fom.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/astrox/coverage/coverage_time.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/astrox/coverage/number_of_assets.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/astrox/coverage/response_time.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/astrox/coverage/revisit_time.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/astrox/coverage/simple_coverage.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/astrox/exceptions.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/astrox/libration.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/astrox/lighting.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/astrox/rocket.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/astrox/terrain.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/docs/CONTRIBUTING.md +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/docs/README.md +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/docs/automated-workflows.md +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/docs/docs-principles.md +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/docs/getting_started.md +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/docs/how_to/README.md +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/docs/how_to/build_an_hpop_configuration.md +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/docs/how_to/compute_access_intervals.md +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/docs/how_to/compute_lighting_conditions.md +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/docs/how_to/convert_between_orbit_representations.md +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/docs/how_to/generate_a_crtbp_periodic_orbit.md +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/docs/how_to/run_an_astrogator_mcs.md +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/docs/how_to/screen_close_approaches.md +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/docs/i18n/en/README.md +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/docs/i18n/en/getting_started.md +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/docs/i18n/en/how_to/README.md +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/docs/i18n/en/how_to/build_an_hpop_configuration.md +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/docs/i18n/en/how_to/compute_access_intervals.md +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/docs/i18n/en/how_to/compute_lighting_conditions.md +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/docs/i18n/en/how_to/convert_between_orbit_representations.md +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/docs/i18n/en/how_to/generate_a_crtbp_periodic_orbit.md +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/docs/i18n/en/how_to/run_an_astrogator_mcs.md +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/docs/i18n/en/how_to/screen_close_approaches.md +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/docs/i18n/en/manual/README.md +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/docs/i18n/en/manual/access/README.md +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/docs/i18n/en/manual/astrogator/README.md +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/docs/i18n/en/manual/cat/README.md +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/docs/i18n/en/manual/catalog/README.md +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/docs/i18n/en/manual/components/README.md +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/docs/i18n/en/manual/conjunction/README.md +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/docs/i18n/en/manual/coverage/README.md +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/docs/i18n/en/manual/libration/README.md +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/docs/i18n/en/manual/lighting/README.md +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/docs/i18n/en/manual/rocket/README.md +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/docs/i18n/en/manual/terrain/README.md +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/docs/manual/README.md +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/docs/manual/access/README.md +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/docs/manual/astrogator/README.md +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/docs/manual/cat/README.md +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/docs/manual/catalog/README.md +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/docs/manual/components/README.md +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/docs/manual/conjunction/README.md +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/docs/manual/coverage/README.md +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/docs/manual/libration/README.md +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/docs/manual/lighting/README.md +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/docs/manual/rocket/README.md +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/docs/manual/terrain/README.md +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/docs/sdk-principles.md +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/docs/validation/README.md +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/docs/validation/access.md +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/docs/validation/astrogator.md +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/docs/validation/cat.md +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/docs/validation/catalog.md +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/docs/validation/conjunction.md +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/docs/validation/coverage.md +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/docs/validation/lighting.md +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/docs/validation/rocket.md +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/docs/validation/terrain.md +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/examples/01_propagation/ballistic_apogee_alt.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/examples/01_propagation/ballistic_delta_v.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/examples/01_propagation/ballistic_min_ecc.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/examples/01_propagation/ballistic_time_of_flight.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/examples/01_propagation/batch_propagators.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/examples/01_propagation/hpop.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/examples/01_propagation/j2_classical.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/examples/01_propagation/propagator_reference.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/examples/01_propagation/sgp4_tle.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/examples/01_propagation/simple_ascent.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/examples/01_propagation/two_body_classical.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/examples/02_orbits/README.md +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/examples/02_orbits/conversions.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/examples/02_orbits/orbit_system.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/examples/02_orbits/wizards.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/examples/03_lighting/README.md +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/examples/03_lighting/lighting.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/examples/04_access/README.md +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/examples/04_access/chain.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/examples/04_access/compute.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/examples/04_access/constraints.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/examples/04_access/custom_axes.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/examples/04_access/sensor_pointing.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/examples/05_rocket/README.md +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/examples/05_rocket/landing_zone.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/examples/06_coverage/README.md +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/examples/06_coverage/compute.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/examples/06_coverage/fom.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/examples/06_coverage/grid_points.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/examples/06_coverage/reports.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/examples/07_astrogator/run_mcs.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/examples/08_conjunction/README.md +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/examples/08_conjunction/close_approaches.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/examples/09_cat/README.md +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/examples/09_cat/cat_workflows.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/examples/10_catalog/README.md +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/examples/10_catalog/catalog_queries.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/examples/11_celestial/README.md +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/examples/12_terrain/README.md +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/examples/12_terrain/terrain_masks.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/examples/13_libration/README.md +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/examples/13_libration/libration_dynamics.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/examples/manifest.toml +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/README.md +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/conftest.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/sdk/access/helpers.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/sdk/access/test_chain.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/sdk/access/test_compute.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/sdk/access/test_values.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/sdk/astrogator/test_api.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/sdk/astrogator/test_models.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/sdk/astrogator/test_results.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/sdk/cat/test_cat.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/sdk/catalog/test_catalog.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/sdk/client/test_client.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/sdk/components/test_components.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/sdk/conjunction/test_conjunction.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/sdk/coverage/test_coverage.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/sdk/coverage/test_coverage_fom.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/sdk/helpers.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/sdk/libration/test_libration.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/sdk/lighting/test_lighting.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/sdk/orbits/helpers.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/sdk/orbits/test_keplerian.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/sdk/orbits/test_orbit_system.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/sdk/orbits/test_tle.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/sdk/orbits/test_wizards.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/sdk/propagator/helpers.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/sdk/propagator/test_ballistic.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/sdk/propagator/test_hpop.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/sdk/propagator/test_j2_two_body.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/sdk/propagator/test_multi.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/sdk/propagator/test_sgp4_simple_ascent.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/sdk/rocket/__init__.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/sdk/rocket/test_rocket.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/sdk/terrain/test_terrain.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/_external/gmat/README.md +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/_external/gmat/hpop_driver.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/_external/gmat/test_hpop_driver.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/_support/__init__.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/_support/contracts.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/_support/external_tools.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/_support/gmat.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/_support/orekit.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/_support/skyfield.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/_support/test_contracts.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/_support/test_external_tools.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/_support/test_gmat.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/_support/test_skyfield.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/cross_validation/__init__.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/cross_validation/access/README.md +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/cross_validation/access/__init__.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/cross_validation/access/_aer.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/cross_validation/access/_cases.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/cross_validation/access/_constraints.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/cross_validation/access/_exclusion.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/cross_validation/access/_geometry.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/cross_validation/access/_mixed_model.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/cross_validation/access/_orientation.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/cross_validation/access/test_axes_orientation_geometry.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/cross_validation/access/test_chain_sgp4_skyfield.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/cross_validation/access/test_composite_czml_axes_geometry.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/cross_validation/access/test_compute_constraints_skyfield.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/cross_validation/access/test_compute_exclusion_constraints_invariants.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/cross_validation/access/test_compute_ground_sgp4_skyfield.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/cross_validation/access/test_compute_j2_two_body_geometry.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/cross_validation/access/test_compute_sgp4_j2_geometry.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/cross_validation/access/test_compute_site_hpop_geometry.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/cross_validation/access/test_compute_site_j2_geometry.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/cross_validation/access/test_compute_site_two_body_geometry.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/cross_validation/access/test_sensor_pointing_geometry.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/cross_validation/access/test_vgt_orientation_resolution.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/cross_validation/astrogator/__init__.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/cross_validation/astrogator/test_branch_semantics.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/cross_validation/astrogator/test_initial_state_conversions.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/cross_validation/astrogator/test_maneuver_invariants.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/cross_validation/astrogator/test_run_mcs_two_body_brahe.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/cross_validation/astrogator/test_scalar_invariants.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/cross_validation/astrogator/test_sequence_czml_brahe.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/cross_validation/astrogator/test_target_sequence_local.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/cross_validation/cat/test_cat_skyfield.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/cross_validation/conjunction/test_close_approaches_skyfield.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/cross_validation/coverage/_fom_helpers.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/cross_validation/coverage/test_exclusion_grid_constraints_skyfield.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/cross_validation/coverage/test_fom_at_time_boundaries_invariants.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/cross_validation/coverage/test_fom_edge_cases_invariants.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/cross_validation/coverage/test_fom_grid_options_invariants.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/cross_validation/coverage/test_fom_interval_invariants.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/cross_validation/coverage/test_fom_resource_options_invariants.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/cross_validation/coverage/test_fom_response_shapes_invariants.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/cross_validation/coverage/test_fom_response_time_dynamic_invariants.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/cross_validation/coverage/test_grid_generation_local.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/cross_validation/coverage/test_grid_point_modifiers_invariants.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/cross_validation/coverage/test_resource_reports_invariants.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/cross_validation/coverage/test_sgp4_grid_membership_skyfield.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/cross_validation/libration/_support.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/cross_validation/libration/test_cross_endpoint_consistency.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/cross_validation/libration/test_crtbp_trajectory.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/cross_validation/libration/test_fixed_x_correction.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/cross_validation/libration/test_orekit_qualification.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/cross_validation/libration/test_periodic_families.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/cross_validation/libration/test_positions_and_units.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/cross_validation/lighting/__init__.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/cross_validation/lighting/test_site_sun_skyfield.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/cross_validation/lighting/test_spacecraft_solar_intensity_orekit.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/cross_validation/lighting/test_spacecraft_sun_skyfield.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/cross_validation/orbit_system/__init__.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/cross_validation/orbit_system/_support.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/cross_validation/orbit_system/test_convert_czml_position.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/cross_validation/orbit_system/test_earth_moon_libration.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/cross_validation/orbits/__init__.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/cross_validation/orbits/test_kozai_izsak_mean_elements_invariants.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/cross_validation/orbits/test_lambert_lamberthub.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/cross_validation/orbits/test_walker_constellation_equations.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/cross_validation/orbits/test_wizards_local_derivation.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/cross_validation/propagator/test_ballistic_geodetic.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/cross_validation/propagator/test_hpop_gmat.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/cross_validation/propagator/test_j2_analytical.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/cross_validation/propagator/test_multi_sgp4_skyfield.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/cross_validation/propagator/test_sgp4_skyfield.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/cross_validation/propagator/test_simple_ascent_geodetic.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/cross_validation/propagator/test_two_body_brahe.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/cross_validation/rocket/__init__.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/cross_validation/rocket/test_landing_zone_geographiclib.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/cross_validation/terrain/test_terrain_mask_invariants.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/live_snapshot/__init__.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/live_snapshot/access/__init__.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/live_snapshot/access/access.snap.json +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/live_snapshot/access/test_access.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/live_snapshot/access/test_chain_topology.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/live_snapshot/access/test_compute_model_pairs.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/live_snapshot/access/test_compute_options.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/live_snapshot/astrogator/__init__.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/live_snapshot/astrogator/run_mcs.snap.json +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/live_snapshot/cat/cat.snap.json +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/live_snapshot/cat/test_cat.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/live_snapshot/catalog/catalog.snap.json +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/live_snapshot/catalog/test_catalog.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/live_snapshot/conjunction/close_approaches.snap.json +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/live_snapshot/conjunction/test_close_approaches.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/live_snapshot/coverage/coverage.snap.json +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/live_snapshot/coverage/test_coverage.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/live_snapshot/libration/libration.snap.json +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/live_snapshot/libration/test_libration.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/live_snapshot/lighting/__init__.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/live_snapshot/lighting/lighting.snap.json +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/live_snapshot/lighting/test_lighting.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/live_snapshot/orbits/__init__.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/live_snapshot/orbits/orbit_system.snap.json +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/live_snapshot/orbits/test_conversion_roundtrip.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/live_snapshot/orbits/test_orbit_system.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/live_snapshot/orbits/test_wizards.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/live_snapshot/orbits/wizards.snap.json +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/live_snapshot/propagator/__init__.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/live_snapshot/propagator/ballistic.snap.json +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/live_snapshot/propagator/hpop.snap.json +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/live_snapshot/propagator/j2.snap.json +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/live_snapshot/propagator/multi_j2.snap.json +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/live_snapshot/propagator/multi_sgp4.snap.json +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/live_snapshot/propagator/multi_two_body.snap.json +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/live_snapshot/propagator/sgp4.snap.json +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/live_snapshot/propagator/simple_ascent.snap.json +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/live_snapshot/propagator/test_ballistic.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/live_snapshot/propagator/test_hpop.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/live_snapshot/propagator/test_j2.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/live_snapshot/propagator/test_multi_j2.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/live_snapshot/propagator/test_multi_sgp4.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/live_snapshot/propagator/test_multi_two_body.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/live_snapshot/propagator/test_sgp4.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/live_snapshot/propagator/test_simple_ascent.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/live_snapshot/rocket/__init__.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/live_snapshot/rocket/landing_zone.snap.json +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/live_snapshot/rocket/test_landing_zone.py +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/live_snapshot/terrain/terrain.snap.json +0 -0
- {astrox_python-1.0.0 → astrox_python-1.2.0}/tests/validation/live_snapshot/terrain/test_terrain.py +0 -0
|
@@ -11,9 +11,13 @@ wheels/
|
|
|
11
11
|
# Virtual environments
|
|
12
12
|
.venv
|
|
13
13
|
|
|
14
|
+
# Local-only server runtime for validation triage (never commit)
|
|
15
|
+
.local-runtime/
|
|
16
|
+
|
|
14
17
|
# Internal & intermediate docs
|
|
15
18
|
*.md
|
|
16
19
|
!README.md
|
|
20
|
+
!AGENTS.md
|
|
17
21
|
!docs/**/*.md
|
|
18
22
|
docs/MAINTAINER_QUESTIONS.md
|
|
19
23
|
!openapi/**/*.md
|
|
@@ -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",
|
|
@@ -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(
|
|
@@ -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,
|
|
@@ -23,6 +23,9 @@ transfer = celestial.lambert_transfer_window(
|
|
|
23
23
|
min_time_of_flight_days=10,
|
|
24
24
|
departure_step_days=2.0,
|
|
25
25
|
arrival_step_days=1.0,
|
|
26
|
+
# 该窗口出发双曲超速约 15 km/s,超出服务端 MaxDepartureDV 缺省值
|
|
27
|
+
# (10000 m/s),需要显式放宽上限才能保留结果
|
|
28
|
+
max_departure_delta_v_m_s=20000,
|
|
26
29
|
)
|
|
27
30
|
|
|
28
31
|
results = transfer["TransferResults"]
|
|
@@ -32,7 +35,8 @@ for result in results:
|
|
|
32
35
|
print(
|
|
33
36
|
f"出发 {result['DepartureTime']} → 到达 {result['ArrivalTime']}: "
|
|
34
37
|
f"|DeltaV1|={result['DV1_Mag']:.1f} m/s, "
|
|
35
|
-
f"|DeltaV2|={result['DV2_Mag']:.1f} m/s"
|
|
38
|
+
f"|DeltaV2|={result['DV2_Mag']:.1f} m/s, "
|
|
39
|
+
f"TOF={result['TimeOfFlightDays']:.0f} d"
|
|
36
40
|
)
|
|
37
41
|
```
|
|
38
42
|
|
|
@@ -47,14 +51,17 @@ python compute_lambert_transfer.py
|
|
|
47
51
|
1. **选出发与到达天体**:`departure_body`/`arrival_body` 接受服务端支持的天体名称(如 `Earth`、`Mars`、`Ceres`)以及 MPC 编号或名称(如 `2015 XF261`)。小行星省略对应的 `*_elements` 参数时,服务端通过网络查询 MPC 根数。
|
|
48
52
|
2. **定两个时间窗口**:`departure_start`/`departure_stop` 与 `arrival_start`/`arrival_stop` 各定义一个 UTC 时间窗口,SDK 分别组合为 `DepartureInterval`/`ArrivalInterval` 的 `"开始/结束"` 字符串。`departure_step_days` 与 `arrival_step_days`(单位 d)控制窗口内的采样步长,结果个数约等于两个窗口采样点数的乘积;示例中的 2 个出发日 × 3 个到达日产生 6 条结果。`min_time_of_flight_days`(单位 d,整数)过滤掉转移时间太短的组合,服务端缺省 10。
|
|
49
53
|
3. **选输出参考系**:`sun_frame` 服务端缺省 `MeanEclpJ2000`;`ICRF` 分支的转移速度已与独立零圈顺行 Lambert 解一致,端点位置方向也已识别为 ICRF 轴方向,而 `MeanEclpJ2000` 与 ICRF 的精确关系尚未独立确认,需要参考系明确的数值时建议显式传 `sun_frame="ICRF"`。
|
|
54
|
+
4. **按需调整过滤上限**:2026-08-20 起服务端按 `max_departure_delta_v_m_s`/`max_arrival_delta_v_m_s`(缺省各 10000 m/s,分别对应出发/到达双曲超速大小)与 `max_time_of_flight_days`(缺省 500 d)过滤算例,全部超界时返回空列表;扫描大 ΔV 或超长转移窗口时需显式放宽,示例中的 Earth→Mars 窗口就属于这种情况。
|
|
50
55
|
|
|
51
56
|
## 读懂结果
|
|
52
57
|
|
|
53
58
|
每个结果对象包含:
|
|
54
59
|
|
|
55
60
|
- `DepartureTime`/`ArrivalTime`:出发/到达时刻(UTC 字符串)。
|
|
56
|
-
- `DeltaV1`/`DeltaV2
|
|
61
|
+
- `DeltaV1`/`DeltaV2`:出发/到达速度增量向量(出发/到达双曲超速矢量,m/s);`DV1_Mag`/`DV2_Mag` 是它们的欧几里得范数(m/s)。`DeltaV` 相对端点天体速度的物理含义尚未独立确认,需要严格物理解释时请先核对。
|
|
57
62
|
- `RV1`/`RV2`:出发/到达时的日心位置速度 `[x, y, z, vx, vy, vz]`(位置 m、速度 m/s);ICRF 分支下转移速度与独立 Lambert 解一致,端点位置方向与 ICRF 轴方向一致。
|
|
63
|
+
- `TimeOfFlightDays`:飞行时间(d),已验证为到达与出发时刻的精确天数差。
|
|
64
|
+
- `ArrivalLightAngle`:到达时刻太阳光照角(deg),已验证为 `DeltaV2` 与 `RV2` 位置矢量的夹角。
|
|
58
65
|
|
|
59
66
|
## 小行星与显式 MPC 根数
|
|
60
67
|
|
|
@@ -84,7 +91,7 @@ transfer = celestial.lambert_transfer_window(
|
|
|
84
91
|
)
|
|
85
92
|
```
|
|
86
93
|
|
|
87
|
-
注意:显式 MPC
|
|
94
|
+
注意:显式 MPC 根数在转移路由中的独立开普勒递推尚未验证,元素系与时间约定未确认(`reference_frame` 选项不改变该路由的到达状态);这个分支可调用、响应结构已由 live 快照记录,但数值语义请自行核对。`mpc_ephemeris` 的 `target_elements` 分支已验证(见天体手册)。
|
|
88
95
|
|
|
89
96
|
## 了解更多
|
|
90
97
|
|
|
@@ -6,9 +6,10 @@
|
|
|
6
6
|
|
|
7
7
|
1. **输入决定传播器**:
|
|
8
8
|
- 有开普勒根数 → 用 `propagator.j2` 或 `propagator.two_body`。
|
|
9
|
+
- 有笛卡尔位置速度状态 → 用 `propagator.two_body_rv`(纯二体,返回扁平星历序列,不返回 `(period_s, position)`)。
|
|
9
10
|
- 有两行根数(TLE) → 用 `propagator.sgp4`。
|
|
10
11
|
- 有力模型配置 → 用 `propagator.hpop`。
|
|
11
|
-
2.
|
|
12
|
+
2. **读取采样**:除 `two_body_rv` 外,所有单轨传播函数都返回 `(period_s, position)`,其中 `position.cartesian_velocity` 是 CZML 风格的扁平序列 `[t, x, y, z, vx, vy, vz, ...]`。
|
|
12
13
|
|
|
13
14
|
## 完整示例
|
|
14
15
|
|
|
@@ -139,6 +140,7 @@ HPOP 传播
|
|
|
139
140
|
| --- | --- | --- |
|
|
140
141
|
| 开普勒根数 | `propagator.j2` | 考虑 J2 摄动,适合大多数低轨任务。 |
|
|
141
142
|
| 开普勒根数,纯二体 | `propagator.two_body` | 只考虑中心天体引力,计算最快。 |
|
|
143
|
+
| 笛卡尔位置速度状态 | `propagator.two_body_rv` | 定步长数值二体积分,返回扁平星历序列 `[t, x, y, z, vx, vy, vz, ...]`。 |
|
|
142
144
|
| 两行根数(TLE) | `propagator.sgp4` | 直接从 TLE 传播,无需手动构造根数。 |
|
|
143
145
|
| 需要配置力模型 | `propagator.hpop` | 支持重力场、大气、太阳辐射压、第三方天体摄动等配置。 |
|
|
144
146
|
|
|
@@ -23,6 +23,10 @@ transfer = celestial.lambert_transfer_window(
|
|
|
23
23
|
min_time_of_flight_days=10,
|
|
24
24
|
departure_step_days=2.0,
|
|
25
25
|
arrival_step_days=1.0,
|
|
26
|
+
# this window's departure hyperbolic excess speed is about 15 km/s, above
|
|
27
|
+
# the server MaxDepartureDV default (10000 m/s); widen the bound explicitly
|
|
28
|
+
# to keep the results
|
|
29
|
+
max_departure_delta_v_m_s=20000,
|
|
26
30
|
)
|
|
27
31
|
|
|
28
32
|
results = transfer["TransferResults"]
|
|
@@ -32,7 +36,8 @@ for result in results:
|
|
|
32
36
|
print(
|
|
33
37
|
f"Departure {result['DepartureTime']} → arrival {result['ArrivalTime']}: "
|
|
34
38
|
f"|DeltaV1|={result['DV1_Mag']:.1f} m/s, "
|
|
35
|
-
f"|DeltaV2|={result['DV2_Mag']:.1f} m/s"
|
|
39
|
+
f"|DeltaV2|={result['DV2_Mag']:.1f} m/s, "
|
|
40
|
+
f"TOF={result['TimeOfFlightDays']:.0f} d"
|
|
36
41
|
)
|
|
37
42
|
```
|
|
38
43
|
|
|
@@ -47,14 +52,17 @@ python compute_lambert_transfer.py
|
|
|
47
52
|
1. **Choose the departure and arrival bodies**: `departure_body`/`arrival_body` accept server-supported body names (e.g. `Earth`, `Mars`, `Ceres`) and MPC numbers or names (e.g. `2015 XF261`). When the matching `*_elements` argument is omitted for an asteroid, the server queries the MPC elements over the network.
|
|
48
53
|
2. **Set the two time windows**: `departure_start`/`departure_stop` and `arrival_start`/`arrival_stop` each define a UTC time window, which the SDK combines into the `"start/stop"` string of `DepartureInterval`/`ArrivalInterval` respectively. `departure_step_days` and `arrival_step_days` (unit d) control the sample step within each window; the number of results is roughly the product of the two windows' sample counts — the 2 departure days × 3 arrival days in the example produce 6 results. `min_time_of_flight_days` (unit d, integer) filters out combinations whose transfer time is too short; the server default is 10.
|
|
49
54
|
3. **Choose the output reference frame**: the server default for `sun_frame` is `MeanEclpJ2000`; the transfer velocities of the `ICRF` branch agree with an independent zero-revolution prograde Lambert solution, and the endpoint position directions have also been identified as ICRF axes, while the exact relationship between `MeanEclpJ2000` and ICRF is not yet independently confirmed, so pass `sun_frame="ICRF"` explicitly when you need numbers with an identified frame.
|
|
55
|
+
4. **Adjust the filter bounds as needed**: since 2026-08-20 the server filters cases by `max_departure_delta_v_m_s`/`max_arrival_delta_v_m_s` (defaults 10000 m/s each, the departure/arrival hyperbolic excess speed magnitudes) and `max_time_of_flight_days` (default 500 d), returning an empty list when everything is out of bounds; widen the bounds explicitly when scanning large-ΔV or very long transfer windows — the Earth→Mars window in the example is such a case.
|
|
50
56
|
|
|
51
57
|
## Reading the results
|
|
52
58
|
|
|
53
59
|
Each result object contains:
|
|
54
60
|
|
|
55
61
|
- `DepartureTime`/`ArrivalTime`: departure/arrival times (UTC strings).
|
|
56
|
-
- `DeltaV1`/`DeltaV2`: departure/arrival velocity-increment vectors (m/s); `DV1_Mag`/`DV2_Mag` are their Euclidean norms (m/s). The physical meaning of `DeltaV` relative to the endpoint bodies' velocities is not yet independently confirmed, so verify it yourself when you need a strict physical interpretation.
|
|
62
|
+
- `DeltaV1`/`DeltaV2`: departure/arrival velocity-increment vectors (departure/arrival hyperbolic excess velocity vectors, m/s); `DV1_Mag`/`DV2_Mag` are their Euclidean norms (m/s). The physical meaning of `DeltaV` relative to the endpoint bodies' velocities is not yet independently confirmed, so verify it yourself when you need a strict physical interpretation.
|
|
57
63
|
- `RV1`/`RV2`: heliocentric position and velocity at departure/arrival `[x, y, z, vx, vy, vz]` (positions m, velocities m/s); under the ICRF branch the transfer velocities agree with the independent Lambert solution, and the endpoint position directions match the ICRF axes.
|
|
64
|
+
- `TimeOfFlightDays`: time of flight (d), verified to be the exact day difference between the arrival and departure times.
|
|
65
|
+
- `ArrivalLightAngle`: Sun lighting angle at arrival (deg), verified to be the angle between `DeltaV2` and the `RV2` position vector.
|
|
58
66
|
|
|
59
67
|
## Asteroids and explicit MPC elements
|
|
60
68
|
|
|
@@ -84,7 +92,7 @@ transfer = celestial.lambert_transfer_window(
|
|
|
84
92
|
)
|
|
85
93
|
```
|
|
86
94
|
|
|
87
|
-
Note: independent Kepler propagation of explicit MPC elements is not yet verified, and the element system
|
|
95
|
+
Note: independent Kepler propagation of explicit MPC elements in the transfer route is not yet verified, and the element system and time convention are unconfirmed (the `reference_frame` option does not change the arrival states of that route); this branch is callable and its response structure is recorded by live snapshots, but verify the numeric semantics yourself. The `target_elements` branch of `mpc_ephemeris` is verified (see the celestial manual).
|
|
88
96
|
|
|
89
97
|
## Learn more
|
|
90
98
|
|
|
@@ -6,9 +6,10 @@ This page solves a specific task: choose the right propagator from the orbit des
|
|
|
6
6
|
|
|
7
7
|
1. **Input determines the propagator**:
|
|
8
8
|
- You have Keplerian elements → use `propagator.j2` or `propagator.two_body`.
|
|
9
|
+
- You have a Cartesian position/velocity state → use `propagator.two_body_rv` (pure two-body; returns a flat ephemeris sequence, not `(period_s, position)`).
|
|
9
10
|
- You have a two-line element set (TLE) → use `propagator.sgp4`.
|
|
10
11
|
- You have a force model config → use `propagator.hpop`.
|
|
11
|
-
2. **Reading the samples**: all single-orbit propagation functions return `(period_s, position)`, where `position.cartesian_velocity` is a CZML-style flat sequence `[t, x, y, z, vx, vy, vz, ...]`.
|
|
12
|
+
2. **Reading the samples**: except for `two_body_rv`, all single-orbit propagation functions return `(period_s, position)`, where `position.cartesian_velocity` is a CZML-style flat sequence `[t, x, y, z, vx, vy, vz, ...]`.
|
|
12
13
|
|
|
13
14
|
## Complete example
|
|
14
15
|
|
|
@@ -139,6 +140,7 @@ Every 7 numbers in `cartesian_velocity` form one frame: time offset (seconds), p
|
|
|
139
140
|
| --- | --- | --- |
|
|
140
141
|
| Keplerian elements | `propagator.j2` | Includes J2 perturbation; suitable for most LEO missions. |
|
|
141
142
|
| Keplerian elements, pure two-body | `propagator.two_body` | Only central-body gravity; fastest computation. |
|
|
143
|
+
| Cartesian position/velocity state | `propagator.two_body_rv` | Fixed-step numerical two-body integration; returns a flat ephemeris sequence `[t, x, y, z, vx, vy, vz, ...]`. |
|
|
142
144
|
| Two-line element set (TLE) | `propagator.sgp4` | Propagates directly from TLE; no need to build elements manually. |
|
|
143
145
|
| Need to configure a force model | `propagator.hpop` | Supports gravity field, atmosphere, solar radiation pressure, third-body perturbations, and more. |
|
|
144
146
|
|
|
@@ -32,7 +32,7 @@ Computes an ephemeris for a target body over a time window and returns a raw JSO
|
|
|
32
32
|
| `start` | `Start` | Analysis start time (UTC, `yyyy-MM-ddTHH:mm:ssZ`). Optional; the server default is January 1 of the current year |
|
|
33
33
|
| `stop` | `Stop` | Analysis stop time (UTC). Optional; the server default is December 31 of the current year |
|
|
34
34
|
| `observer_name` | `ObserverName` | Observer name, e.g. `Earth`; the server default is `Sun` |
|
|
35
|
-
| `observer_frame` | `ObserverFrame` | Observer frame
|
|
35
|
+
| `observer_frame` | `ObserverFrame` | Observer frame; the server currently accepts `FIXED`, `INERTIAL`, `MeanEclpJ2000`, `EclpJ2000ICRF`, `J2000`, and `ICRF`; default `MeanEclpJ2000` |
|
|
36
36
|
| `step_s` | `Step` | Sample step, in s, server default 86400 s |
|
|
37
37
|
|
|
38
38
|
`target_name` is the only required request field of this function; `start` and `stop` are optional — when omitted they are not sent to ASTROX and the server selects January 1 to December 31 of the current year as the window. Other optional fields that are not supplied are likewise not sent to ASTROX, and the server retains its default values.
|
|
@@ -43,7 +43,7 @@ from astrox import celestial
|
|
|
43
43
|
start = "2026-01-01T00:00:00.000Z"
|
|
44
44
|
stop = "2026-01-02T00:00:00.000Z"
|
|
45
45
|
|
|
46
|
-
for frame in ("J2000", "MeanEclpJ2000"):
|
|
46
|
+
for frame in ("J2000", "MeanEclpJ2000", "EclpJ2000ICRF"):
|
|
47
47
|
ephemeris = celestial.ephemeris(
|
|
48
48
|
target_name="Moon",
|
|
49
49
|
start=start,
|
|
@@ -81,11 +81,11 @@ Computes the rotation from the coordinate axes of the source central body to tho
|
|
|
81
81
|
| `from_central_body` | `FromCbName` | Source central body name, e.g. `Earth` |
|
|
82
82
|
| `to_central_body` | `ToCbName` | Target central body name, e.g. `Moon` |
|
|
83
83
|
| `epoch` | `Epoch` | Epoch time (UTC) |
|
|
84
|
-
| `from_frame` | `FromCbFrame` | Source frame, server options `FIXED`, `INERTIAL`, `J2000`, `ICRF`, `MeanEclpJ2000`, default `INERTIAL` |
|
|
84
|
+
| `from_frame` | `FromCbFrame` | Source frame, server options `FIXED`, `INERTIAL`, `J2000`, `ICRF`, `MeanEclpJ2000`, `EclpJ2000ICRF`, default `INERTIAL` |
|
|
85
85
|
| `to_frame` | `ToCbFrame` | Target frame, same options, default `FIXED` |
|
|
86
86
|
| `order` | `Order` | Rotation motion order: `0` returns the quaternion only, `1` returns the quaternion and angular velocity; passed through as an integer |
|
|
87
87
|
|
|
88
|
-
`order` is preserved as an integer and lowered to the server as-is; the SDK does not rewrite the branch. The `Rotation` field of the response is a numeric array: with `order=0` it has length 4 (quaternion `[qx, qy, qz, qw]`), and with `order=1` it has length 7 (quaternion plus angular-velocity components, unit rad/s per the server documentation). Verified numeric semantics include: for the same central body on both sides with `INERTIAL` frames on both sides, the server returns the identity quaternion with zero angular velocity at `order=1`; the Earth `INERTIAL`→`FIXED` quaternion and angular velocity; and the Earth→Moon `INERTIAL`→`FIXED` angular velocity at `order=1`. The Earth→Moon `INERTIAL`→`FIXED` quaternion is unresolved, and other combinations are unverified, so verify their meaning yourself before use.
|
|
88
|
+
`order` is preserved as an integer and lowered to the server as-is; the SDK does not rewrite the branch. The `Rotation` field of the response is a numeric array: with `order=0` it has length 4 (quaternion `[qx, qy, qz, qw]`), and with `order=1` it has length 7 (quaternion plus angular-velocity components, unit rad/s per the server documentation). Verified numeric semantics include: for the same central body on both sides with `INERTIAL` frames on both sides, the server returns the identity quaternion with zero angular velocity at `order=1`; Earth→Earth `EclpJ2000ICRF`→`ICRF` follows the fixed J2000 mean-obliquity rotation with zero angular velocity at the two maintained epochs and `order=0/1`; the Earth `INERTIAL`→`FIXED` quaternion and angular velocity; and the Earth→Moon `INERTIAL`→`FIXED` angular velocity at `order=1`. The Earth→Moon `INERTIAL`→`FIXED` quaternion is unresolved, and other combinations are unverified, so verify their meaning yourself before use.
|
|
89
89
|
|
|
90
90
|
```python
|
|
91
91
|
rotation = celestial.cb_axes_rotation(
|
|
@@ -113,22 +113,28 @@ celestial.mpc_ephemeris(
|
|
|
113
113
|
observer_frame: str | None = None,
|
|
114
114
|
start: str | None = None,
|
|
115
115
|
stop: str | None = None,
|
|
116
|
+
step_s: float | None = None,
|
|
117
|
+
target_elements: MpcOrbitalElements | None = None,
|
|
116
118
|
) -> dict[str, Any]
|
|
117
119
|
```
|
|
118
120
|
|
|
119
|
-
Queries an MPC minor-planet ephemeris by asteroid name or number and returns a raw JSON response dictionary.
|
|
121
|
+
Queries an MPC minor-planet ephemeris by asteroid name or number and returns a raw JSON response dictionary. When `target_elements` is provided, the server integrates the given MPC orbital elements directly instead of querying MPC over the network.
|
|
120
122
|
|
|
121
123
|
| Parameter | Wire parameter | Description |
|
|
122
124
|
| --- | --- | --- |
|
|
123
125
|
| `target_name` | `TargetName` | Asteroid name or number, e.g. `Ceres`, `99942` |
|
|
124
|
-
| `observer_frame` | `ObserverFrame` | Heliocentric frame, server options `FIXED`, `INERTIAL`, `MeanEclpJ2000`, `
|
|
126
|
+
| `observer_frame` | `ObserverFrame` | Heliocentric frame, server options `FIXED`, `INERTIAL`, `J2000`, `ICRF`, `MeanEclpJ2000`, `EclpJ2000ICRF`, default `MeanEclpJ2000` |
|
|
125
127
|
| `start` | `Start` | Start time (UTC); defaults to the orbital epoch and cannot be earlier than the orbital epoch (server rule) |
|
|
126
128
|
| `stop` | `Stop` | Stop time (UTC); defaults to 1 year after `Start` |
|
|
129
|
+
| `step_s` | `Step` | Output sample step, in s, server default 86400 s; pass `0` to output at the internal integration steps |
|
|
130
|
+
| `target_elements` | `TargetElements` | Explicit MPC orbital elements (built with `mpc_orbital_elements`); when omitted, the server queries MPC over the network |
|
|
131
|
+
|
|
132
|
+
This route fetches orbital elements from the external MPC data source (element epoch in MJD TDT). The server contract declares adaptive heliocentric integration followed by Hermite interpolation onto the fixed output grid selected by `step_s`; `step_s=0` requests output at the server-declared internal integration steps. The response is a heliocentric CZML Position structure containing `OrbitElements` (orbital elements with keys `EpochMjdTdt`, `PeriTimeMjdTdt`, `Q`, `SemimajorAxis`, `Eccentricity`, `Inclination`, `Raan`, `ArgOfPeriapsis`, `MeanAnomaly`, `ReferenceFrame`) and `Position` (CZML structure, same as `ephemeris`). The orbital-element values come from external MPC data, are owned by that external data source, and may change with MPC updates. When `start`/`stop` are omitted, the server uses the orbital-epoch default window (`start` is the orbital epoch and `stop` is one year after it); an explicit fixed window depends on the orbital epoch at query time, and once the external MPC orbital epoch updates, a previously fixed window may fall before the new epoch and be rejected by the server, so prefer omitting the window parameters or following the current epoch.
|
|
127
133
|
|
|
128
|
-
|
|
134
|
+
Verified (within-route invariants): passing the `OrbitElements` returned by a name query back as `target_elements` reproduces the name-query ephemeris exactly; omitting `step_s` exactly matches explicit `86400`, `172800` produces an exact subset of the daily grid, and `0` returns the same endpoints on a nonuniform internal integration grid; the `reference_frame` values `EclpJ2000ICRF` (MPC convention, server default) and `MeanEclpJ2000` (JPL convention) are two distinguishable branches. This evidence verifies request branches and output-sampling semantics, not absolute orbit accuracy. See the [celestial validation page](../../../../validation/celestial.md) for details.
|
|
129
135
|
|
|
130
136
|
```python
|
|
131
|
-
mpc = celestial.mpc_ephemeris(target_name="Ceres")
|
|
137
|
+
mpc = celestial.mpc_ephemeris(target_name="Ceres", step_s=172800.0)
|
|
132
138
|
|
|
133
139
|
print(f"Ceres MPC ephemeris: {len(mpc['Position']['cartesianVelocity']) // 7} state samples")
|
|
134
140
|
```
|
|
@@ -149,6 +155,7 @@ celestial.mpc_orbital_elements(
|
|
|
149
155
|
raan_deg: float | None = None,
|
|
150
156
|
argument_of_periapsis_deg: float | None = None,
|
|
151
157
|
mean_anomaly_deg: float | None = None,
|
|
158
|
+
reference_frame: str | None = None,
|
|
152
159
|
) -> MpcOrbitalElements
|
|
153
160
|
```
|
|
154
161
|
|
|
@@ -165,6 +172,7 @@ Builds a heliocentric MPC orbital-element fragment. When either the departure or
|
|
|
165
172
|
| `raan_deg` | `Raan` | deg |
|
|
166
173
|
| `argument_of_periapsis_deg` | `ArgOfPeriapsis` | deg |
|
|
167
174
|
| `mean_anomaly_deg` | `MeanAnomaly` | deg |
|
|
175
|
+
| `reference_frame` | `ReferenceFrame` | Heliocentric ecliptic frame variant: `MeanEclpJ2000` (JPL) or `EclpJ2000ICRF` (MPC, server default) |
|
|
168
176
|
|
|
169
177
|
```python
|
|
170
178
|
from astrox import celestial
|
|
@@ -184,7 +192,7 @@ elements = celestial.mpc_orbital_elements(
|
|
|
184
192
|
print(elements.to_wire())
|
|
185
193
|
```
|
|
186
194
|
|
|
187
|
-
`to_wire()` returns the ASTROX `MpcOrbElements` request fragment; the example above prints `{'EpochMjdTdt': 61000.0, 'PeriTimeMjdTdt': 60900.0, 'Q': 0.6740515, 'SemimajorAxis': 0.9898367, 'Eccentricity': 0.3190276, 'Inclination': 0.79379, 'Raan': 209.81829, 'ArgOfPeriapsis': 100.88187, 'MeanAnomaly': 120.0}`. When passed to `lambert_transfer_window`, the server propagates heliocentrically directly with these elements and no longer queries MPC over the network. The independent Kepler propagation of explicit elements is unverified: the element system
|
|
195
|
+
`to_wire()` returns the ASTROX `MpcOrbElements` request fragment; the example above prints `{'EpochMjdTdt': 61000.0, 'PeriTimeMjdTdt': 60900.0, 'Q': 0.6740515, 'SemimajorAxis': 0.9898367, 'Eccentricity': 0.3190276, 'Inclination': 0.79379, 'Raan': 209.81829, 'ArgOfPeriapsis': 100.88187, 'MeanAnomaly': 120.0}`. When passed to `lambert_transfer_window`, the server propagates heliocentrically directly with these elements and no longer queries MPC over the network. The independent Kepler propagation of explicit elements in that route is unverified: the element system and time convention are not confirmed (the `reference_frame` option does not change the arrival states of that route); the `target_elements` branch of `mpc_ephemeris` is verified (see above), so verify the meaning yourself before use.
|
|
188
196
|
|
|
189
197
|
## Lambert transfer windows
|
|
190
198
|
|
|
@@ -205,10 +213,13 @@ celestial.lambert_transfer_window(
|
|
|
205
213
|
arrival_step_days: float | None = None,
|
|
206
214
|
departure_elements: MpcOrbitalElements | None = None,
|
|
207
215
|
arrival_elements: MpcOrbitalElements | None = None,
|
|
216
|
+
max_departure_delta_v_m_s: int | None = None,
|
|
217
|
+
max_arrival_delta_v_m_s: int | None = None,
|
|
218
|
+
max_time_of_flight_days: int | None = None,
|
|
208
219
|
) -> dict[str, Any]
|
|
209
220
|
```
|
|
210
221
|
|
|
211
|
-
Samples over the departure time window and the arrival time window, computes Lambert transfers between bodies, and returns a raw JSON response dictionary. It is not the single-case `orbits.lambert_delta_v` interface: that function takes two `CartesianState` values and a `time_of_flight_s`, calls `/orbit/lambert`, and returns the two triples `(DV1, DV2)`; this function scans the whole grid of departure/arrival time pairs and returns a `TransferResults` list.
|
|
222
|
+
Samples over the departure time window and the arrival time window, computes Lambert transfers between bodies, and returns a raw JSON response dictionary. It is not the single-case `orbits.lambert_delta_v` interface: that function takes two `CartesianState` values and a `time_of_flight_s`, calls `/orbit/lambert`, and by default returns the two triples `(DV1, DV2)`; this function scans the whole grid of departure/arrival time pairs and returns a `TransferResults` list.
|
|
212
223
|
|
|
213
224
|
| Parameter | Wire parameter | Description |
|
|
214
225
|
| --- | --- | --- |
|
|
@@ -218,12 +229,15 @@ Samples over the departure time window and the arrival time window, computes Lam
|
|
|
218
229
|
| `departure_stop` | `DepartureInterval` | Departure time window end (UTC) |
|
|
219
230
|
| `arrival_start` | `ArrivalInterval` | Arrival time window start (UTC); combined with `arrival_stop` into `"start/stop"` |
|
|
220
231
|
| `arrival_stop` | `ArrivalInterval` | Arrival time window end (UTC) |
|
|
221
|
-
| `sun_frame` | `SunFrameName` | Heliocentric frame
|
|
232
|
+
| `sun_frame` | `SunFrameName` | Heliocentric output frame; the server currently accepts `MeanEclpJ2000`, `EclpJ2000ICRF`, and `ICRF`; default `EclpJ2000ICRF` |
|
|
222
233
|
| `min_time_of_flight_days` | `MinTofDays` | Minimum transfer time, in d, integer; server default 10 |
|
|
223
234
|
| `departure_step_days` | `DepartureStepDay` | Departure time sample step, in d; server default 1 |
|
|
224
235
|
| `arrival_step_days` | `ArrivalStepDay` | Arrival time sample step, in d; server default 1 |
|
|
225
236
|
| `departure_elements` | `DepartureElements` | MPC orbital elements of the departure asteroid (built with `mpc_orbital_elements`); when omitted, the server queries MPC over the network |
|
|
226
237
|
| `arrival_elements` | `ArrivalElements` | MPC orbital elements of the arrival asteroid; when omitted, the server queries MPC over the network |
|
|
238
|
+
| `max_departure_delta_v_m_s` | `MaxDepartureDV` | Maximum departure velocity increment (departure hyperbolic excess speed magnitude), in m/s, integer; server default 10000, cases above it are filtered out |
|
|
239
|
+
| `max_arrival_delta_v_m_s` | `MaxArrivalDV` | Maximum arrival velocity increment (arrival hyperbolic excess speed magnitude), in m/s, integer; server default 10000, cases above it are filtered out |
|
|
240
|
+
| `max_time_of_flight_days` | `MaxTofDays` | Maximum transfer time, in d, integer; server default 500, cases above it are filtered out |
|
|
227
241
|
|
|
228
242
|
`departure_body`, `arrival_body`, and the four time strings are the required request fields of this function; `DepartureInterval`/`ArrivalInterval` is a single `"start/stop"` string, e.g. `"2028-06-01T00:00:00Z/2028-06-03T00:00:00Z"`. Other optional parameters that are not supplied are not sent to ASTROX, and the server retains its default values.
|
|
229
243
|
|
|
@@ -241,6 +255,9 @@ transfer = celestial.lambert_transfer_window(
|
|
|
241
255
|
min_time_of_flight_days=10,
|
|
242
256
|
departure_step_days=2.0,
|
|
243
257
|
arrival_step_days=1.0,
|
|
258
|
+
# this window's departure hyperbolic excess speed is about 15 km/s, above
|
|
259
|
+
# the server MaxDepartureDV default (10000 m/s); widen the bound explicitly
|
|
260
|
+
max_departure_delta_v_m_s=20000,
|
|
244
261
|
)
|
|
245
262
|
|
|
246
263
|
results = transfer["TransferResults"]
|
|
@@ -248,20 +265,23 @@ first = results[0]
|
|
|
248
265
|
print(f"{len(results)} transfer results")
|
|
249
266
|
print(
|
|
250
267
|
f"First: {first['DepartureTime']} → {first['ArrivalTime']}, "
|
|
251
|
-
f"|DeltaV1|={first['DV1_Mag']:.1f} m/s, |DeltaV2|={first['DV2_Mag']:.1f} m/s"
|
|
268
|
+
f"|DeltaV1|={first['DV1_Mag']:.1f} m/s, |DeltaV2|={first['DV2_Mag']:.1f} m/s, "
|
|
269
|
+
f"TOF={first['TimeOfFlightDays']:.0f} d"
|
|
252
270
|
)
|
|
253
271
|
```
|
|
254
272
|
|
|
255
|
-
The response contains `TransferResults` (an array of transfer results; each element corresponds to one sampled departure/arrival time pair, and the number of results is determined jointly by the two time windows and the sample steps). Each result has the following keys:
|
|
273
|
+
The response contains `TransferResults` (an array of transfer results; each element corresponds to one sampled departure/arrival time pair, and the number of results is determined jointly by the two time windows and the sample steps, and is also affected by `min_time_of_flight_days` and the `max_departure_delta_v_m_s`/`max_arrival_delta_v_m_s`/`max_time_of_flight_days` filter bounds — when every case is out of bounds the list is empty). Each result has the following keys:
|
|
256
274
|
|
|
257
275
|
| Key | Type | Unit / description |
|
|
258
276
|
| --- | --- | --- |
|
|
259
277
|
| `DepartureTime` / `ArrivalTime` | string | Departure/arrival time (UTC string) |
|
|
260
|
-
| `DeltaV1` / `DeltaV2` | number[3] | Departure/arrival velocity-increment vector, m/s |
|
|
278
|
+
| `DeltaV1` / `DeltaV2` | number[3] | Departure/arrival velocity-increment vector (departure/arrival hyperbolic excess velocity vector), m/s |
|
|
261
279
|
| `DV1_Mag` / `DV2_Mag` | number | Departure/arrival velocity-increment magnitude, m/s; verified to be the Euclidean norm of the corresponding `DeltaV` vector |
|
|
262
280
|
| `RV1` / `RV2` | number[6] | Position and velocity at departure/arrival (heliocentric) `[x, y, z, vx, vy, vz]`, positions m, velocities m/s |
|
|
281
|
+
| `TimeOfFlightDays` | number | Time of flight, in d; verified to be the exact day difference between `ArrivalTime` and `DepartureTime` |
|
|
282
|
+
| `ArrivalLightAngle` | number | Sun lighting angle at arrival, in deg; verified to be the angle between `DeltaV2` and the `RV2` position vector |
|
|
263
283
|
|
|
264
|
-
Verified (supported by independent cross-validation): with `sun_frame="ICRF"`, the transfer velocities in `RV1`/`RV2` follow the zero-revolution prograde Lambert relationship, and the endpoint position directions use the ICRF axes. Unresolved: the exact coordinate relationship between `MeanEclpJ2000` and ICRF, the physical meaning of `DeltaV` relative to the endpoint-body velocities, and independent Kepler propagation of explicit MPC elements.
|
|
284
|
+
Verified (supported by independent cross-validation): omitting `sun_frame` produces exactly the same `TransferResults` as explicit `EclpJ2000ICRF`; `EclpJ2000ICRF` output is the `ICRF` output rotated by the fixed 23.43929111111111° J2000 mean obliquity; with `sun_frame="ICRF"`, the transfer velocities in `RV1`/`RV2` follow the zero-revolution prograde Lambert relationship, and the endpoint position directions use the ICRF axes; `max_departure_delta_v_m_s`/`max_arrival_delta_v_m_s`/`max_time_of_flight_days` filter the sampled grid by the `DV1_Mag`/`DV2_Mag`/time-of-flight upper bounds respectively. Note that since 2026-08-20 the server defaults (10000 m/s each for departure/arrival, 500 d) filter out cases beyond the defaults, so scans over large-ΔV windows need explicitly widened bounds. Unresolved: the exact coordinate relationship between explicit `MeanEclpJ2000` and ICRF, the physical meaning of `DeltaV` relative to the endpoint-body velocities, and independent Kepler propagation of explicit MPC elements (the `reference_frame` option does not change the arrival states of that route; the element convention is still unconfirmed). The numeric semantics of those branches remain unverified, so check them before use.
|
|
265
285
|
|
|
266
286
|
## Convention notes
|
|
267
287
|
|
|
@@ -269,6 +289,7 @@ Verified (supported by independent cross-validation): with `sun_frame="ICRF"`, t
|
|
|
269
289
|
- Each `cartesianVelocity` sample is `[Time, X, Y, Z, dX, dY, dZ]`, with `Time` in seconds from the reference epoch, positions in m, and velocities in m/s.
|
|
270
290
|
- `cb_axes_rotation` passes the integer `order` through as-is; the `Rotation` length corresponds to `order` (`0` → 4, `1` → 7).
|
|
271
291
|
- `mpc_ephemeris` relies on the server's orbital-epoch default window when `start`/`stop` are omitted; an explicit fixed window may expire when the external MPC orbital epoch updates.
|
|
292
|
+
- `mpc_ephemeris` `step_s` controls the output sampling grid; when omitted the server default is 86400 s, while `0` outputs at the internal integration steps.
|
|
272
293
|
- The returns of all four functions on this page have the transport-level `IsSuccess` and `Message` removed, and the remaining server fields are preserved; errors are still raised by the HTTP layer (see error handling).
|
|
273
294
|
- `lambert_transfer_window` combines `departure_start`/`departure_stop` and `arrival_start`/`arrival_stop` into the `"start/stop"` strings of `DepartureInterval`/`ArrivalInterval` respectively.
|
|
274
295
|
- `mpc_orbital_elements` only performs the type checks required for lowering and does not perform physical-validity validation; fields that are not supplied do not appear in the `to_wire()` fragment.
|