Orbit determination for interplanetary missions


I’m trying to build an application performing orbit determination for interplanetary missions. To my mind, it is better to use AbsolutePVCoordinates instead of Orbits for this type of applications.
However, with the current implementation of Orekit, it is a bit difficult to do it because the orbit determination works a lot with the Orbit class.

As a result, my objective is to generalize the orbit determination to be compatible with AbsolutePVCoordinates. I understand it is a difficult task…

  • Generalizing NumericalPropagatorBuilder (I prefer generalization instead of creating a new builder)
  • Use SpacecraftState instead of Orbit when possible in the BatchLSEstimator and BatchLSModel
  • Having a common interface, extending PVCoordinatesProvider, for Orbits and AbsolutePVCoordinates (purposes: (1) providing the Jacobian wrt parameters and cartesian, (2) providing isOrbitTypeDefined, and (3) providing isCentralAttractionDefined)


  • Orbit determination in non inertial frames
  • Reducing the number of constructors in SpacecraftState

What do you think about that?
Any idea of additional tasks to perform?

I would be please to contribute it if this feature is accepted.

Thank you,

Hi Bryan,

I actually think that SpacecraftState has become a bit of an atrocity since AbsolutePVCoordinates has been introduced within it. Don’t get me wrong, I understand the user need and I appreciate that it didn’t break any APIs. However, the current duality in the class calls for polymorphism. So ideally there should be two classes with a common interface and/or abstraction. But this would require huge efforts to adapt the library (the Field version basically doubles the workload) and I don’t think there is enough time before Orekit 12 for that. So maybe what you propose (with orbit determination in mind) is more suitable in the short term.

A question though: what would be the difference between isOrbitTypeDefined and isCentralAttractionDefined?


That’s just my opinion, but I appreciate the fact of having just one class: SpacecraftState which can be used with different coordinates provider (Orbit and APV). Because it is a widely used Orekit object, I’m afraid that having two objects, even with a common interface, can complexify a lot the code and the use. My idea is just to simplify the instantiation of SpacecraftState by using a common inaterface for both Orbit and APV. This is a first big step tonreduce the atrocity.

Yes, I agree that splitting SpacecraftState cannot be performed for 12.0.
I forget to mention that this contribution will not be performed during my free time. It’s an Airbus idea to contribute it. Unfortunately, because splitting requires API changes (and a lot of devs), we cannot wait a 13.0 and support weeks of devs for that…
I’m trying to find the solution which can satisfy both parties :slightly_smiling_face:

Any, that’s a mistake.

Thank you,


That would be a great addition!!
I too like @Serrof think that the SpacecraftState has become too bloated but I think your solution @bcazabonne may reduce its complexity.

I would pay extra attention to the measurements and the light time correction inside of them.
Since we use "shiftedBy"s to correct for the light time it can lead to big errors, given that the delay of the signal will be of several minutes in interplanetary motion.
Maybe it will be ok for a spacecraft on a heliocentric cruise. But, take for example a radio-relay spacecraft around Mars with a complex force model which is communicating with the Deep Space Network antennas on Earth.
The signal can take up to 20 minutes to arrive/depart from the spacecraft to the antenna, and I’m pretty sure that “shiftedBy” won’t perform well in that case.

Some time ago with @luc we tried to add an OrekitStepInterpolator in the signature of the theoreticalEvaluation method of the measurements to improve the extrapolation of the state used in light-time corrections, but:

  • It was already hard (to my defense I was a beginner in Orekit by that time :slight_smile: )
  • It implied that the OD was performed with an integrated propagator (and now we can do it with analytical propagators too)
    (Edit: I was wrong here, analytical propagators also expose an OrekitStepInterpolator for the step handlers)
  • It supposed that the light-time delay was contained in the time interval of the interpolator. Looking back at the example above, I don’t think we can use 20min steps with a complex gravity model of Mars

Now that I’m putting some thoughts on this again, I think the best course of action would be to propagate on the whole time span first, store the results in a BoundedPropagator, and then compute the estimated measurements using this propagator (or a more generic object like PVCoordinatesProvider). That way we can correct for light-time delays much better.
This will break the logic of the MeasurementsHandler gathering the measurements’ estimations on the fly during propagation.
And probably induce API changes in the measurement classes and the OD classes.
Kalman filters will somehow also need to store the ephemeris of the propagation performed during the prediction step.

Anyway, that was long but I just wanted to warn you about that potential trap beforehand.
I don’t think that it’s impossible to do though.


1 Like

Thank you @MaximeJ
That’s indeed an important remark. Generalizing the API of estimators is the first step. A second step will indeed be to think about the measurement models.
Thanks to Orekit API, users can implement their own measurement model to handle the shiftedBy issue. That’s why we started our design on the generalization of the estimator which is not really recommended to extend :sweat_smile:


For an unrelated issue, I indeed need to change the MeasurementBuilder.build signature from Map<ObservableSatellite, SpacecraftState> states to Map<ObservableSatellite, OrekitStepInterpolator> states.
I have open issue 1220, it is trivial to do for 12.0.