# 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:

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:

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.

Note

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(
one_way_nno_mex_link_ends
light_time_correction_settings = light_time_correction_settings,
bias_settings = range_bias_settings ) )
observation_settings_list.append( observation_setup.one_way_open_loop_doppler(
one_way_nno_mex_link_ends,
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.

Note

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 realityThe

**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 themThe

*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( bodies, parameters_to_estimate, observation_settings_list, propagator_settings) # 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).