Propagate A SmallBody And Evaluate Dense Trajectories¶
This guide shows how to propagate a SmallBody over a chosen interval and query position and velocity from the dense trajectory inside the solved interval.
Use Configure Force Models And Dynamic Systems first when you need a custom force model; the propagation path here uses the standard built-in force model.
Prerequisites¶
- Activate the project environment described in Installation.
- You need a local planetary SPK kernel. Replace the placeholder path in the snippet with a local file such as
de441.bsp. - The initial orbit below is already a canonical
BCRSstate.
For the model-level background, read Numerical Integrators And Dense Trajectories.
1. Build the initial SmallBody¶
Start from a canonical BCRS state.
from difforb.body import SmallBody
from difforb.core import BCRS, State, Time
t0 = Time.from_tdb_date(2025, 1, 2)
state0 = State(
tdb=t0.tdb(),
pos=[1.685775738339898, -1.336388854313325, -0.2144927004440800],
vel=[0.008995712853117517, 0.006985684417802803, 0.004020851173846060],
frame=BCRS,
)
body = SmallBody.create(state0)
print(body)
<SmallBody shape=() epoch_jd=2460677.500000000 frame=BCRS mag_model=none trajectory=uninitialized>
The orbit is ready. The trajectory is not ready yet.
2. Build model and integrator¶
Load the planetary kernel. Then build the standard force model and one integrator.
from difforb.dynamics import DynamicSystem
from difforb.spk import set_default_ephemeris
from difforb.integrator import NumericalIntegrator
planetary_kernel = "/path/to/your/de441.bsp"
set_default_ephemeris(planetary_kernel)
force_model = DynamicSystem.from_standard_system().build_force_model()
integrator = NumericalIntegrator(method="IAS15", tol=1e-12)
print(force_model)
print(integrator)
This path uses the standard major-body background and the IAS15 integrator. If you want another integrator, change
method to "DOPRI8" or "DOPRI5".
3. Propagate the orbit¶
Choose the end epoch and call propagate(...).
from difforb.core import Time
t_end = Time.from_tdb_date(2025, 2, 15)
body = body.propagate(t0.tdb(), t_end.tdb(), force_model, integrator)
print(body)
print(body.trajectory is not None)
<SmallBody shape=() epoch_jd=2460677.500000000 frame=BCRS mag_model=none trajectory=ready>
True
After this call, the dense trajectory is stored in body.trajectory.
4. Check whether one epoch is covered¶
Use is_covered(...) before you query.
inside = Time.from_tdb_date(2025, 1, 20)
outside = Time.from_tdb_date(2025, 3, 1)
print(bool(body.trajectory.is_covered(inside.tdb().jd1, inside.tdb().jd2)))
print(bool(body.trajectory.is_covered(outside.tdb().jd1, outside.tdb().jd2)))
True
False
The first epoch is inside the solved interval. The second is outside.
5. Query the dense trajectory directly¶
Use body.trajectory.evaluate(...) when you want canonical BCRS position and velocity.
pos_i, vel_i = body.trajectory.evaluate(inside.tdb().jd1, inside.tdb().jd2)
print(pos_i)
print(vel_i)
[ 1.8396007 -1.20465751 -0.14124085]
[0.00809158 0.00763366 0.00411113]
These are the interpolated Cartesian position and velocity at 2025-01-20 TDB.
6. Query through SmallBody¶
Use body.state(...) when you want a full State object.
state_i = body.state(inside.tdb(), frame=BCRS)
print(state_i.frame.name)
print(state_i.pos)
print(state_i.vel)
BCRS
[ 1.8396007 -1.20465751 -0.14124085]
[0.00809158 0.00763366 0.00411113]
The values match the direct trajectory interpolation. The difference is that body.state(...) returns a State object.
Common Mistakes¶
body.trajectoryisNoneuntil you callpropagate(...).body.state(...)fails if the query epoch is outside the solved interval.trajectory.evaluate(...)takes split Julian date parts, not aTimeobject.tolis a shorthand tolerance. ForIAS15, it fillsatolwhenatolis not given. ForDOPRI8andDOPRI5, it fills missingrtolandatol. Use explicitrtolandatolwhen you need separate relative and absolute tolerances.
Next Steps¶
- Continue to Configure Force Models And Dynamic Systems if you want a custom force model.
- Continue to Ephemeris Products Workflow if you want observer products from the propagated orbit.
- Use the Body API, Dynamics API, and Integrator API for details on propagation objects.