目录
Vishwa Shah

perf: simplify third body gravity calculation (#707)

  • perf: reduce per-step allocation overhead in the propagation loop

Two hot-loop cleanups on the astrodynamics side of numerical propagation, with no public API change and bit-identical numerical results:

  • Dynamics::DynamicalEquations: reuse a per-context scratch buffer for the reduced read state instead of heap-allocating a fresh VectorXd for every dynamics at every derivative evaluation. The buffer lives in the Dynamics::Context copies bound into the system-of-equations wrapper (per-propagation), not in the shared Dynamics objects.

  • NumericalSolver::integrateTime(State, Instant, …): defer construction of the observed State objects (one per accepted integration step) until accessObservedStates()/getObservedStates() is actually called, and build them from a const reference to the underlying solver’s observed state vectors instead of a by-value copy. Propagator::calculateStateAt no longer pays for building thousands of State objects nobody reads; Segment and other consumers get identical states, built lazily.

Measured (Release, EGM96 10x10 + PositionDerivative, RK4 fixed 5 s):

  • loop overhead (PositionDerivative-only, 17,280 steps): 1.05 -> 0.78 us/step
  • derivative-evaluation glue with 5 dynamics: 0.222 -> 0.173 us/eval
  • 1-day propagation: ~991 -> ~950 ms, 7-day: ~4.76 -> ~4.65 s (medians of 3 interleaved A/B runs); final states bit-identical to baseline

Co-Authored-By: Claude Fable 5 noreply@anthropic.com

  • perf: avoid body-frame rotation round trip in ThirdBodyGravity

ThirdBodyGravity::computeContribution evaluated the third body’s gravitational field twice via Celestial::getGravitationalFieldAt, each call rotating the query position into the body’s own ephemeris-attached frame (a full SPICE sxform_c lookup for SPICE-backed bodies) and then rotating the resulting acceleration back out via inFrame. For a point-mass (spherical) gravitational model, the field does not depend on the body’s orientation, so this rotate-in/rotate-out round trip is pure overhead: the same result can be obtained from the body’s position alone (Celestial::getPositionIn, a pure translation lookup) combined with mu (Celestial::getGravitationalParameter) via the closed-form two-term third-body formula, with no per-call orientation lookups.

Since ThirdBodyGravity accepts an arbitrary Shared, nothing guarantees the attached model is point-mass (e.g. a higher-fidelity spherical-harmonics model could be attached). A new private static helper, IsPointMassGravitationalModel, dynamic_casts the Celestial’s gravitational model to Spherical (the generic point-mass model) or to Sun/Moon/Earth with their respective Type::Spherical (their only non-orientation-dependent type); this is computed once at construction and cached. The fast path is only taken when this positively identifies a point mass; otherwise computeContribution falls back unchanged to the original two-call getGravitationalFieldAt + inFrame path, so behavior is unaffected for any other configuration.

Standalone micro-benchmark (Release, unique instants per call): Sun (SPICE): 17.5 -> 15.5 us/call (12% faster) Moon (SPICE): 19.3 -> 17.1 us/call (12% faster) Sun (analytical ephemeris): 9.9 -> 7.4 us/call (25% faster) Moon (analytical ephemeris): 10.6 -> 8.2 us/call (22% faster)

Added tests verifying the fast path numerically matches the generic path for Sun::Default/Moon::Default/Sun::Analytical/Moon::Analytical, and a test with a synthetic non-spherical (WGS84) third body proving the generic fallback path is genuinely exercised.

Co-Authored-By: Claude Fable 5 noreply@anthropic.com

  • feat: leverage new celestial method

Co-authored-by: Claude Fable 5 noreply@anthropic.com

22天前700次提交

Open Space Toolkit ▸ Astrodynamics

Build and Test Release Code Coverage Documentation GitHub version PyPI version License

Orbit, attitude, access, mission analysis.

Getting Started

Want to get started? This is the simplest and quickest way:

Binder

Nothing to download or install! This will automatically start a JupyterLab environment in your browser with Open Space Toolkit libraries and example notebooks ready to use.

Alternatives

Docker Images

Docker must be installed on your system.

iPython

The following command will start an iPython shell within a container where the OSTk components are already installed:

docker run -it openspacecollective/open-space-toolkit-astrodynamics-development ipython

Once the shell is up and running, playing with it is easy:

from ostk.physics import Environment
from ostk.physics.time import Instant
from ostk.astrodynamics.trajectory import Orbit
from ostk.astrodynamics.trajectory.orbit.model import SGP4
from ostk.astrodynamics.trajectory.orbit.model.sgp4 import TLE

tle = TLE(
    '1 25544U 98067A   18231.17878740  .00000187  00000-0  10196-4 0  9994',
    '2 25544  51.6447  64.7824 0005971  73.1467  36.4366 15.53848234128316'
)  # Construct Two-Line Element set

earth = Environment.default().access_celestial_object_with_name('Earth')  # Access Earth model

orbit = Orbit(SGP4(tle), earth)  # Construct orbit using SGP4 model

orbit.get_state_at(Instant.now())  # Compute and display current satellite state (position, velocity)

By default, OSTk fetches the ephemeris from JPL, Earth Orientation Parameters (EOP) and leap second count from IERS.

As a result, when running OSTk for the first time, it may take a minute to fetch all the necessary data.

Tip: Use tab for auto-completion!

JupyterLab

The following command will start a JupyterLab server within a container where the OSTk components are already installed:

docker run --publish=8888:8888 openspacecollective/open-space-toolkit-astrodynamics-jupyter

Once the container is running, access http://localhost:8888/lab and create a Python 3 Notebook.

Installation

C++

The binary packages are hosted using GitHub Releases:

  • Runtime libraries: open-space-toolkit-astrodynamics-X.Y.Z-1.x86_64-runtime
  • C++ headers: open-space-toolkit-astrodynamics-X.Y.Z-1.x86_64-devel
  • Python bindings: open-space-toolkit-astrodynamics-X.Y.Z-1.x86_64-python

Debian / Ubuntu

After downloading the relevant .deb binary packages, install:

apt install open-space-toolkit-astrodynamics-*.deb

Python

Install from PyPI:

pip install open-space-toolkit-astrodynamics

Documentation

Documentation is available here:

Structure

The library exhibits the following detailed and descriptive structure:

├── NumericalSolver
├── Trajectory
│   ├── State
│   ├── Orbit
│   │   ├── Model
│   │   │   ├── Kepler
│   │   │   │   └── Classical Orbital Elements (COE)
│   │   │   ├── SGP4
│   │   │   │   └── Two-Line Element set (TLE)
│   │   │   ├── Tabulated (input csv)
│   │   │   └── Propagated (numerical integration)
│   │   ├── Pass
│   │   └── Message
│   │       └── SpaceX
│   │           └── OPM
│   ├── Model
│   │   ├── Static
│   │   └── Tabulated
│   └── Propagator
├── Flight
│   ├── Profile
│   │    ├── Model
│   │    │   ├── Transform
│   │    │   └── Tabulated
│   │    └── State
│   └── System
│        ├── SatelliteSystem
│        └── Dynamics
│            └── PositionDerivative
│            └── CentralBodyGravity
│            └── ThirdBodyGravity
│            └── AtmosphericDrag
├── Access
│   └── Generator
└── Conjunction
    └── Message
        └── CCSDS
            └── CDM

Tutorials

Tutorials are available here:

Setup

Development Environment

Using Docker for development is recommended, to simplify the installation of the necessary build tools and dependencies. Instructions on how to install Docker are available here.

To start the development environment:

make start-development

This will:

  1. Build the openspacecollective/open-space-toolkit-astrodynamics-development Docker image.
  2. Create a development environment container with local source files and helper scripts mounted.
  3. Start a bash shell from the ./build working directory.

If installing Docker is not an option, you can manually install the development tools (GCC, CMake) and all required dependencies, by following a procedure similar to the one described in the Development Dockerfile.

Build

From the ./build directory:

cmake ..
make

Tip: The ostk-build command simplifies building from within the development environment.

Test

To start a container to build and run the tests:

make test

Or to run them manually:

./bin/open-space-toolkit-astrodynamics.test

Tip: The ostk-test command simplifies running tests from within the development environment.

Script

To build an executable for a simple script:

  • create a .cxx file in the scripts directory.
  • Enable the CMake BUILD_SCRIPT flag using ccmake or equivalent.
  • run ostk-build to build the executable, which will be found in the in /bin folder under the name open-space-toolkit-astrodynamics

Example:

#include <OpenSpaceToolkit/Physics/Coordinate/Frame.hpp>
#include <OpenSpaceToolkit/Physics/Coordinate/Position.hpp>
#include <OpenSpaceToolkit/Physics/Coordinate/Velocity.hpp>
#include <OpenSpaceToolkit/Physics/Time/Instant.hpp>

#include <OpenSpaceToolkit/Astrodynamics/Trajectory/State.hpp>

using ostk::mathematics::object::VectorXd;

using ostk::physics::coordinate::Frame;
using ostk::physics::coordinate::Position;
using ostk::physics::coordinate::Velocity;
using ostk::physics::time::Instant;
using ostk::physics::time::Scale;

using ostk::astrodynamics::trajectory::State;

int main()
{
    const State state = {
        Instant::Parse("2024-06-09 14:44:30.734.999", Scale::UTC),
        Position::Meters({3786681.30288918, -4897593.40751009, -2997836.66403268}, Frame::GCRF()),
        Velocity::MetersPerSecond({1124.5962634611, -3265.39989654837, 6779.45043611605}, Frame::GCRF()),
    };

    std::cout << state << std::endl;
}

Benchmark

To run benchmarks:

make benchmark

Benchmarks are pushed to the GitHub pages.

Validation

OSTk has a cross-validation framework built into it (inside the /validation folder), which allows us to compare its end-to-end propagation accuracy of a full “mission sequence” to other flight qualified tools like GMAT and Orekit.

Scenario Definition

A standardized input format (a yaml file) to define the particular mission sequence scenario is used, and is tooling agnostic. An example of it is shown below.

  • The spacecraft’s parameters and initial state are defined under the spacecraft header
  • The sequence header contains the dynamic forces to be applied during propagation, the type of numerical propagator to use, and the segments (burning or coasting) to execute during the mission sequence
  • Finally, the output header contains the quantities that we want to output (in this case time elapsed, position, and velocity), and the interval at which to report them
type: MISSION_SEQUENCE
data:
  spacecraft:
    mass: 100.0
    drag-cross-section: 1.0
    drag-coefficient: 2.2
    orbit:
      type: CARTESIAN
      data:
        date:
          time-scale: UTC
          value: "2023-01-01T00:00:00"
        frame: GCRF
        body: EARTH
        x: -4283387.412456233
        y: -4451426.776125101
        z: -2967617.850750065
        vx: 4948.074939732174
        vy: -957.3429532772124
        vz: -5721.173027553034

  sequence:
    max-duration: 86400.1
    forces:
      - type: GRAVITY
        data:
          body: EARTH
          model: EGM96
          degree: 0
          order: 0
    propagator:
      type: RUNGE_KUTTA_DORMAND_PRINCE_45
      data:
        initial-step: 30.0
        min-step: 0.001
        max-step: 2700.0
        relative-tolerance: 1.0e-12
        absolute-tolerance: 1.0e-12
    segments:
      - type: COAST
        data:
          stop-condition:
            type: RELATIVE_TIME
            data:
              duration: 86400.0

  output:
    step: 120.0
    include:
      - ELAPSED_SECONDS
      - CARTESIAN_POSITION_GCRF
      - CARTESIAN_VELOCITY_GCRF

Cross Validation and Accuracy Tolerances

The validation framework takes this yaml scenario definition (from the /validation/data/scenarios folder) and runs the scenario using OSTk. Next, it compares the specified outputs (quantities like the position, velocity, mass, acceleration of the spacecraft) at the desired reporting step generated by OSTk with each external validation tool (whose outputs were generated via the same process and are in the /validation/data/gmat_astrodynamics or /validation/data/orekit_astrodynamics folder as .csv), to ensure they are within a certain tolerance of each other.

To add a scenario:

  1. Write a scenario definition using the .yaml format above, and name it scenarioX-mission-sequence.yaml, and put it in wth the others. If the format isn’t correct or there is another issue, OSTk will throw an error when validating.
  2. Generate the .csv outputs from the external tools you want to compare OSTk against (repos with an GMAT and Orekit wrapper that can ingest this .yaml format do exist and will be open sourced soon).
  3. Add another test case to the Framework.validation.cpp file, with the scenario name, the tool to compare against, and the output quantities and comparison tolerances for those. An exampe of this is provided below.
{
    "scenario001-mission-sequence",  // Spherical gravity only
    {
        {
            Tool::GMAT,
            {
                {Quantity::CARTESIAN_POSITION_GCRF, 1.1e-0},
                {Quantity::CARTESIAN_VELOCITY_GCRF, 1.2e-3},
            },
        },
        {
            Tool::OREKIT,
            {
                {Quantity::CARTESIAN_POSITION_GCRF, 1.1e-0},
                {Quantity::CARTESIAN_VELOCITY_GCRF, 1.2e-3},
            },
        },
    },
},

Running the Validation Tests

The validation tests can be run with ostk-validate from within the dev container, or make validation as a standalone.

Dependencies

Name Version License Link
Pybind11 2.10.1 BSD-3-Clause github.com/pybind/pybind11
ordered-map 0.6.0 MIT github.com/Tessil/ordered-map
Eigen 3.3.7 MPL2 eigen.tuxfamily.org
SGP4 2020-07-13 None stated celestrak.org/software/vallado-sw.php (vendored, see thirdparty/vallado-sgp4)
NLopt 2.5.0 LGPL github.com/stevengj/nlopt
benchmark 1.8.2 Apache License 2.0 github.com/google/benchmark
cesiumpy 0.4.1 Apache License 2.0 github.com/open-space-collective/cesiumpy
Core main Apache License 2.0 github.com/open-space-collective/open-space-toolkit-core
I/O main Apache License 2.0 github.com/open-space-collective/open-space-toolkit-io
Mathematics main Apache License 2.0 github.com/open-space-collective/open-space-toolkit-mathematics
Physics main Apache License 2.0 github.com/open-space-collective/open-space-toolkit-physics

⚠️ Until OSTk#183 is implemented, the fork of cesiumpy must be installed separately in order to use the viewer module. It is not specified as a dependency of ostk-astrodynamics.

Contribution

Contributions are more than welcome!

For the contributing guide, please consult the CONTRIBUTING.md in the open-space-toolkit base repo here.

Special Thanks

Loft Orbital

License

Apache License 2.0

关于

Open Space Toolkit 轨道动力学组件(轨道传播、任务分析)。镜像收录自 https://github.com/open-space-collective/open-space-toolkit-astrodynamics,License:Apache-2.0

550.0 MB
邀请码
    Gitlink(确实开源)
  • 加入我们
  • 官网邮箱:gitlink@ccf.org.cn
  • QQ群
  • QQ群
  • 公众号
  • 公众号

版权所有:中国计算机学会技术支持:开源发展技术委员会
京ICP备13000930号-9 京公网安备 11010802047560号