Observation Model Setup

Having defined the link ends, you can now define and create the observation models. Below the general workflow for this is discussed. The observation models can play two roles in Tudat:

  • To generate simulated data inside Tudat, instead of loading real data.

  • For use in a (least-squares) estimation loop, to create the observation models used to fit input data (real or simulated) to observations provided

Before providing any specifics, we need to distinguish several different types of settings/models/data structures in Tudat, which will be elaborated upon in the following pages:

  • Observation Model Settings, which are presented below containing settings for the types of observations that are to be used. These objects do not perform any calculation, but defined the properties of the observation simulators that are created

  • Observation Simulators, which are discussed below. These objects compute the actual observations from the current properties of the environment. As input, these objects require observation times (and possibly additional metadata).

  • Observation Simulation Settings, which are discussed on the following page. These objects define how to use the observationaccessing_observations simulators by providing the required settings for observation times, etc.

  • Observation Collection, which are discussed on the following page. These objects store the full set of observations and associated data used in a single estimation/covariance analysis in Tudat

Defining observation settings

Tudat supports a diverse set of observation types. The creation of an observation model is done in a similar manner as models used for the numerical propagation: an object defining the settings of each observation model is created (of type ObservationModelSettings), which is then processed to create the actual observation model. The full list of available observation models is discussed here, including links to the API documentation

A basic observation model is defined by:

  • The type of the observation

  • The link ends involved in the observation (e.g. transmitter, receiver)

Below is a basic example of creating settings for two observation models. Note that the below code snippet defines a o ne-way range and one-way Doppler (open-loop) observable, each with the New Norcia ESTRACK station/Mars Express as transmitter/receiver (see Link Ends Setup). These settings are put into the observation_settings_list list. Note that this list of observation model settings can be extended with any number of entries, with any number of link ends. The only limitation is that you may not have duplicate entries of link ends and observable type (as this would essentially define an identical type of observation).

# Define link ends
one_way_nno_mex_link_ends = dict( );
one_way_nno_mex_link_ends[ transmitter ] = estimation_setup.observation.body_reference_point_link_end_id( "Earth", "NNO" );
one_way_nno_mex_link_ends[ receiver ] = estimation_setup.observation.body_origin_link_end_id( "MeX" );
one_way_nno_mex_link_definition = estimation_setup.link_definition( one_way_nno_mex_link_ends )

# Create list of observation settings
observation_settings_list = list()
observation_settings_list.append( observation_setup.one_way_range( one_way_nno_mex_link_ends ) )
observation_settings_list.append( observation_setup.one_way_open_loop_doppler( one_way_nno_mex_link_ends ) )

When defining observation models, you can for most types of models define settings for:

  • Biases: A bias in Tudat is applied to the observable after its ‘ideal’ value computed from the environment is computed. You can find a list of settings for observation biases in our API documentation

  • Light-time corrections: When using an observable that involves the observation of one point/body in space by another (including any observable that involves the exchange of elecromagnetic signals), it is automatically assumed that the signal travels at the speed of light, and the associated light-time is determined when calculating the observable. Deviations from the signal’s ideal trajectory (straight line at speed of light) may be defind by adding light-time correction settings, as listed in our API documentation

  • Light-time convergence settings: Calculating the light time between two link ends requires the iterative solution of the light-time equation. Default settings for convergence criteria for this solution are implemented, but a user may modify these settings if so desired. The associated settings object can be created using the light_time_convergence_settings() function.

Observation biases are used to add any systematic deviations from the ‘physical’ value of the computed obseravation (due to unmodelled electronic delays, or unmodelled propagation effects of the electromagnectic signals). A list of available biases can be found TODO. In short, for a bias \(\Delta h\) (which may be a function of time, or properties of the environment), an ‘ideal’ computed observation \(\bar{h}\), the actual computed observation becomes:

\[h(t)=\bar{h}(t)+\Delta h(t)\]

Note that the random noise is not yet considered here, as this is typically not modelled as part of the observation itself during the estimation.

The light-time correction and light-time convergence settings influence how the light time in one ‘leg’ (e.g. between two link ends, here with indices 0 and 1) is calculated. To compute the light time, the following implicit equation has to be solved:

\[\frac{||\mathbf{r}_{1}(t_{1}) - \mathbf{r}_{0}(t_{0})||}{c}=\left(t_{1}-t_{0}\right)+\Delta t(t_{0},t_{1};\mathbf{r}_{1}(t_{1}),\mathbf{r}_{0}(t_{0}))\]

where, depending on the reference link end, the time \(t_{0}\) at link end 0 is kept fixed, or the time \(t_{1}\) at link end 1 is kept fixed. The \(\mathbf{r}_{0}\) and \(\mathbf{r}_{1}\) functions define the positions of link end 0 and 1 as a funtion of time. The function \(\Delta t\) collects all effects that cause the propagation of the signal to deviate from propagation in a straight line at the speed of light.


The light time equation is always solved when using an observable that involved the transmission/reception of a signal. The “light time corrections” only refer to deviations from the straight-line speed of light propagation of the signal.

The above options are added to the calls of the observation model settings factory functions. Below is an example

# Define link ends
one_way_nno_mex_link_ends = dict( );
one_way_nno_mex_link_ends[ transmitter ] = estimation_setup.observation.body_reference_point_link_end_id( "Earth", "NNO" );
one_way_nno_mex_link_ends[ receiver ] = estimation_setup.observation.body_origin_link_end_id( "MeX" );
one_way_nno_mex_link_definition = estimation_setup.link_definition( one_way_nno_mex_link_ends )

# Define settings for light-time calculations
light_time_correction_settings = [ observation_setup.first_order_relativistic_correction( [ 'Sun' ] )]

# Define settings for range bias
range_bias_settings = observation_setup.absolute_bias( 0.01 )

# Create list of observation settings
observation_settings_list = list()
observation_settings_list.append( observation_setup.one_way_range(
    light_time_correction_settings = light_time_correction_settings,
    bias_settings = range_bias_settings ) )
observation_settings_list.append( observation_setup.one_way_open_loop_doppler(
    light_time_correction_settings = light_time_correction_settings ) )

where we have defined that, for both observation models for which settings are created, the light-time calculation will take into account the first-order relativistic correction of the Sun, by using the first_order_relativistic_correction() function. For the range observable, we have defined an absolute bias of 1 cm (0.01 m) using the absolute_bias(), while leaving the Doppler observable unbiased.

Creating the observation models

The observation_settings_list in the above examples (a list[ObservationModelSettings]) is used to create the observation simulators, which compute the actual values of the observables in Tudat. Depending on the your use case, a user may or may not interact with the observation simulators directly:

  • Simulated observations In this case, the user must interact with the observation simulators created from the observation_settings_list (which can be done in several ways), as discussed in mroe detail below

  • Real observations In this case, the observation_settings_list is used inside the estimation to create the obsevation simulators and generated the ‘computed observations’ from which the residuals are computed

Therefore, the rest of this section is only relevant for the first part: using simulated observations in Tudat.


This section only discusses the creation of the observation simulators. The use of these simulators to generate observations is discussed on the next page

In what follows, we distinguish two different kinds of observation models:

  • The truth model, which is the one used to simulate the observations which we use as input to the estimation. When using real observations, the ‘truth model’ is our physical reality

  • The estimatiom model, which is the model used inside the estimator to fit the real or simulated observations (which are generated from the truth model)

In other words, when computing the residuals from ‘observed minus computed’ (or ‘O-C’) data, the truth model is the source of the ‘observed* data, and the estimation model is the source of the computed data.

When using simulated observations, one can therefore choose between two different approaches

  • The truth model and estimation model are identical to one another, so that the observation model(s) used to fit the observations is mathematically identical to the one used to generate them

  • The truth model and estimation model are different from one another, so that there are physical effects present in the mathematical model used to simulate the osbervations which are not present in the model used to do the estimation

Same truth and estimation model

The first case (equal truth and estimation model) is obviously a simplification of reality: when processing real data there are always effects present in our physical reality that are not incorporated into our models However, the first case can be very useful for a number of cases. Firstly, when only performing a covariance analysis, the estimation model is never used, so we can dispense with its definition altogether (greatlt simplifying the setup!) Secondly, doing a full estimation with the truth and estimation model equal to one another allows one to study the influence that different data types, their noise levels, etc. have on the final estimation, with some more flexibility than what is the case in the covariance anlaysus. More specifically, in a covariance analysis one is limited to Gaussian uncorrelated noise, which in a full estimation you can add any noise you like to the observations.

When taking this approach, one makes use of the fact that observation simulators for the estimation are created anyway when creating an Estimator object (discussed further here). You can extract these observation_simulators as follows, and use them to simulate observations as follows:

# Create physical environment (as set of physical bodies)
estimator = Estimator(

# Extract observation simulators
observation_simulators = estimator.observation_simulators

Different truth and estimation model

The second case above, where the truth and estimation model are different from one another, opens up a broad range of options. In principle, any and all settings of the bodies, the propagation model, and the observation models can be made different between the two. A challenge is often in choosing the difference that one wants to implement to study the case at hand. In this case, the observation simulators are created directly, using the create_observation_simulators() function:

# Create physical environment (a set of physical bodies)
bodies = ...

# Create settings for observation models
observation_settings_list = list( )

# Create observation simulators
observation_simulators = create_observation_simulators( observation_settings_list, bodies )

When subsequently creating the Estimator object (discussed further here) to perform the estimation, one can then provide a different observation_settings_list to ensure a difference between the truth and estimation models. One can also choose to provide different bodies, so that the physical environment from which the observations are simulated, and the one to which they are fit, are different. Finally, even when using the same bodies, one can choose a different model for the states of the estimated bodies to ensure a difference in truth and estimation model.

The observation simulators

In either case, the observation_simulators variable is a list of objects derived from ObservationSimulator, with a single object responsible for the simulation of a single type of observable (e.g. one-way range, one-way Doppler, etc.). The observation_simulators is then used for simulating the actual observations to be used in the analysis, as described in Observation Creation. Note that the ObservationSimulator is responsible for all observations of a given kind (e.g. each set of link ends), the ObservationModel simulates observations of a single kind, for a single set of link ends (e.g. one-way range observations between a given ground station and a single spacecraft). Details on the associated options can be found in the API documentation.

For ‘manual’ simulation of observations, you can extract an ObservationModel object from the ObservationSimulator (TODO example).