Propagate your first orbit

Install a matching wheel using Installation. The standard package supports this example; the installed runtime needs only the standard library and its bundled binaries/data.

examples/quickstart.py
"""Propagate a circular orbit with point-mass Earth gravity."""

import math

import gmatpy as gmat

epoch = "2020-07-20T12:00:00Z"
mu = 398600.4415  # Earth's GMAT gravitational parameter, km^3/s^2.
radius_km = 7000.0
state = (radius_km, 0.0, 0.0, 0.0, math.sqrt(mu / radius_km), 0.0)
forces = gmat.ForceModel(degree=0, sun=False, moon=False, srp=False)

# These are elapsed seconds from epoch, not incremental step lengths.
samples = gmat.propagate(state, epoch, [0, 300, 600], forces=forces)

assert [sample.time_s for sample in samples] == [0, 300, 600]
assert math.dist(samples[0].state, state) < 1e-9
angle = math.sqrt(mu / radius_km**3) * 600
expected_position = (radius_km * math.cos(angle), radius_km * math.sin(angle), 0.0)
assert math.dist(samples[-1].position_km, expected_position) < 1e-5
assert abs(math.hypot(*samples[-1].position_km) - radius_km) < 1e-5

last = samples[-1]
print(f"t = {last.time_s:.0f} s; radius = {math.hypot(*last.position_km):.6f} km")
print("position (km):", tuple(round(value, 6) for value in last.position_km))

The initial six-state is [x, y, z, vx, vy, vz] in km and km/s, in EarthMJ2000Eq (Earth-centered mean equator/equinox J2000). The example starts at an explicitly UTC epoch and samples elapsed SI seconds. The return value is a list of immutable Sample values; state concatenates the position and velocity tuples.

times=[0, 300, 600] asks for samples at those offsets from the epoch. It does not request successive steps of 0, 300, and 600 seconds. Repeated offsets repeat the same state, and an empty sequence produces an empty result. Each call starts a new orbit; a second call does not continue the first call’s internal state. Negative, non-finite, or decreasing sample times are rejected.

Choose a force model

The default ForceModel uses EGM96 8×8 Earth gravity, Sun and Moon point masses, and spherical solar radiation pressure (SRP). Drag is off. The integrator is adaptive Prince-Dormand 7/8, with accuracy=1e-12 and max_step_s=60.0. Accuracy is an integrator setting, not a bound on physical orbit prediction error. Output spacing and maximum integration step are separate choices.

For a two-body comparison:

two_body = gmat.ForceModel(degree=0, sun=False, moon=False, srp=False)
samples = gmat.propagate(
    [7000, 0, 0, 0, 7.5, 1.0], "2020-07-20T12:00:00Z", [0, 600],
    forces=two_body,
)

For degree/order 70 Earth gravity and constant-flux Jacchia-Roberts drag:

forces = gmat.ForceModel(degree=70, order=70, drag=True,
                        f107=150.0, f107a=150.0, kp=3.0)
spacecraft = gmat.Spacecraft(mass_kg=1000, drag_area_m2=5, srp_area_m2=5)
samples = gmat.propagate(
    [7000, 0, 0, 0, 7.5, 1.0], "2020-07-20T12:00:00Z", range(0, 3601, 60),
    forces=forces, spacecraft=spacecraft,
)

EGM96 supports degree/order through 360; JGM3 supports through 70. The spacecraft has constant mass, areas, Cd and Cr. File-driven space weather is not used by this helper. See Time, frames, units and scientific inputs for model/data limits and Runnable examples for runnable utility and mission examples.

Use copied values outside native calls

Value-based helpers return Python numbers, tuples, lists, or dictionaries that you can safely retain. GMAT itself has process-global state: calls are serialized, and parallel jobs must use spawned processes. Do not load a second GMAT API in the same process. native_session() has stricter native object lifetime rules, explained in Mission workflows and native access.