Skip to Content
ReferenceHTTP APIOrbit determination

Orbit determination

POST/od/tracking
POST/od/bls
POST/od/ekf

Purpose

POST /od/tracking generates synthetic observations from a known truth orbit. POST /od/bls fits one epoch state to a whole arc. POST /od/ekf processes the same observations sequentially.

They form a workflow rather than three unrelated endpoints: the tracking simulator is what makes the estimators testable, because it starts from an answer you already know.

Observations travel inline

Unlike the CLI, which reads a tracking CSV from disk, these endpoints take measurements inline as JSON. That is what makes them usable from another host, and it means a real arc produces a large request body: 220 observations is roughly 27 kB.

The station list is also inline, and it must describe every station appearing in the measurements. Without it a measurement cannot be related to a state.

POST /od/bls

Request

ParameterTypeUnitDefaultRequiredDescription
epochstringRFC 3339 UTC—YesSolution epoch. Observations must not precede it.
measurementsarrayn/a—YesObservations, each with epoch, station_id, kind, value, and sigma.
stationsarrayn/a—YesGround stations. Must cover every station_id in the measurements.
initial_orbitobjectn/a—YesKeplerian elements as the initial guess. Note: `initial_orbit`, where the CLI flag is `--initial`.
forcestringn/aj2NoReference force model: `two_body`, `j2`, or `j4`.
edit_sigmanumbersigma4NoResidual editing threshold. Zero disables editing.
max_iterationsintegercount10NoIteration cap. Reaching it without convergence is a failure, not an answer.

Example response

Fitting 220 synthetic observations from two Deep Space Network stations:

{ "epoch": "2026-01-01T00:00:00Z", "position_eci_km": [3209.861533717679, 5499.371867195568, 2711.997942122806], "velocity_eci_km_s": [-5.533572605774019, 0.6885441582931939, 5.15319070740035], "covariance": [[3.5789720154651683e-7, "..."]], "position_sigma_km": ["..."], "velocity_sigma_km_s": ["..."], "rms_history": ["..."], "iterations": 3, "converged": true, "measurements_used": 220, "measurements_edited": 0, "residuals": ["..."] }

Elided: covariance is a full 6-by-6 matrix and residuals carries one entry per observation.

The response gives you more than the CLI

FieldWhy it matters
position_eci_km, velocity_eci_km_sThe estimated state itself, which the CLI summary does not print
covarianceThe full 6-by-6 matrix, not just the diagonal sigmas
rms_historyRMS at each iteration, which shows whether convergence was clean or struggled
residualsPer-observation residuals, for spotting a bad station or an epoch tagged wrongly
convergedExplicit. Check it before reading anything else

converged: false with iterations at the cap means the solver did not find a solution. The state and covariance are still populated, and they are the last iterate rather than an answer.

Always check converged first. Nothing else in the response indicates failure.

Covariance is formal, not truth

The reported sigmas are what the estimator believes given its own model and the stated measurement noise. They are optimistic whenever the force model is incomplete, because unmodeled acceleration is absorbed as signal.

An RMS near 1.0 is the target: residuals are weighted by each observation’s sigma, so an RMS of 1 means the fit disagrees with the data by about as much as the stated noise. Much above 1 means the model cannot explain the data; much below means the sigmas are pessimistic.

POST /od/ekf

Processes observations sequentially, maintaining a running state and covariance. It takes the same measurement and station arrays plus process-noise and initial uncertainty parameters.

The filter’s reported uncertainty is typically one to two orders of magnitude larger than batch on the same data, and that is correct: different epochs, time since the last observation, and deliberate process noise all contribute. See the od ekf page for the comparison in detail.

POST /od/tracking

Generates synthetic observations from a truth orbit, which is the only way to validate an estimator against an answer you already know.

Run many seeds, compare actual error against reported sigma, and confirm the errors fall within one sigma about 68 percent of the time. A filter that reports 0.03 km while actually erring by 0.3 km is worse than one that honestly reports 0.3 km, because downstream decisions trust the number.

See also

Question? Give us feedbackDocuments Varaha Constellation Designer main (pre-release)
Last updated on