orbitforge od simulate-tracking
Synopsis
orbitforge od simulate-tracking --orbit <PATH> [OPTIONS]Description
Generates realistic tracking observations from a known truth orbit: propagate the orbit, work out when each station can see it, and emit noisy measurements at a fixed cadence.
Its purpose is testing. Orbit determination is hard to validate against real data because the true answer is unknown. Here the truth orbit is an input, so the solution can be compared against it directly, and the estimated uncertainty can be checked against the actual error.
The dotted line is the point of the whole exercise: the truth orbit is available for comparison in a way it never is operationally.
Options
| Parameter | Type | Unit | Default | Required | Description |
|---|---|---|---|---|---|
--orbit | path | n/a | — | Yes | Keplerian-elements JSON for the truth orbit. See the schema below. |
--stations | path | n/a | — | No | Tracking-stations JSON, with per-station noise specifications. |
--station | string | n/a | — | No | Catalog station shorthand, repeatable, for example `--station dsn:goldstone`. Uses default range and range-rate noise. |
--start | string | RFC 3339 UTC | 2026-01-01T00:00:00Z | No | Window start epoch. |
--duration-hours | float | h | 24 | No | Window length. |
--cadence-seconds | float | s | 60 | No | Observation interval while a station has visibility. |
--seed | integer | n/a | 7 | No | Noise seed. The same seed reproduces the same observations exactly. |
--force | enum | n/a | j2 | No | Truth force model: `two-body`, `j2`, or `j4`. |
--light-time | flag | n/a | — | No | Apply the one-way light-time correction. |
--csv | path | n/a | — | No | Write observations as tracking CSV, the input format for `od bls` and `od ekf`. |
--tdm | path | n/a | — | No | Write observations as a CCSDS TDM (KVN) file. |
--satellite-id | string | n/a | sat-1 | No | Satellite identifier stamped into the TDM. |
Truth orbit schema
{
"semi_major_axis_km": 6928.0,
"eccentricity": 0.001,
"inclination_deg": 51.6,
"raan_deg": 40.0,
"argument_of_perigee_deg": 30.0,
"true_anomaly_deg": 0.0
}Every field is required. A missing field is reported by name:
Error: failed to parse orbit file `orbit.json`
Caused by:
missing field `argument_of_perigee_deg` at line 8 column 1Worked example
Two Deep Space Network stations tracking a station-like orbit for a day:
orbitforge od simulate-tracking \
--orbit orbit.json \
--station dsn:goldstone --station dsn:madrid \
--duration-hours 24 --cadence-seconds 60 \
--csv obs.csvSimulated 220 observations from 2 stations over 24.0 h (seed 7).
Wrote tracking CSV -> obs.csvThe observation file
epoch,station_id,kind,value,sigma
2026-01-01T00:06:00Z,dsn:madrid,range,1775.655885312,0.010000000
2026-01-01T00:06:00Z,dsn:madrid,range_rate,-5.887454298,0.000010000| Column | Meaning |
|---|---|
epoch | Observation time, RFC 3339 UTC |
station_id | Which station produced it |
kind | range in km, range_rate in km/s, azimuth or elevation in degrees |
value | The noisy measurement |
sigma | One-sigma uncertainty, in the measurement’s own units |
Each visible epoch produces one row per measurement kind, so 110 epochs each carrying a range and a range-rate measurement give 220 observations.
220 observations over 24 hours at a 60-second cadence is sparse, and correctly so. Two stations at fixed sites see a low Earth orbit only during passes, typically a few minutes several times a day. Most of the window has no visibility from either site, which is exactly the condition that makes orbit determination interesting.
Stations file
The --station shorthand uses catalog defaults. For explicit control over noise,
supply a stations file:
[
{
"station": {
"id": "dsn:goldstone",
"name": "NASA DSN Goldstone",
"latitude_deg": 35.4267,
"longitude_deg": -116.89,
"altitude_km": 1.0,
"min_elevation_deg": 6.0
},
"range": { "sigma": 0.01 },
"range_rate": { "sigma": 0.00001 }
}
]A measurement kind is produced only if it is present. Omitting range_rate
yields range-only tracking, which is a materially harder estimation problem.
NoiseSpec also accepts a bias term, defaulting to zero, for modeling
systematic station errors.
The same stations file must be supplied to od bls and od ekf. The solvers need
each station’s position to relate a measurement to a state, and its sigma to weight
the residual. Passing a different file than the one used to simulate makes the
solution inconsistent with the data in a way that shows up as inflated residuals
rather than as an error.
Reproducibility
The noise is seeded. Re-running with the same --seed reproduces the same
observations exactly, which is what makes a regression test possible. Change the
seed to test the estimator against a different noise realization, and vary it
across many runs to check that the estimated covariance is statistically
consistent with the actual error.
See also
od blsto fit an epoch state to these observations.od ekfto process them sequentially.stations listfor catalog identifiers.
main (pre-release)