3.1. Unperturbed Earth-orbiting Satellite

This page describes how to set up the propagation of the unperturbed Earth-orbiting satellite described in Unperturbed Earth-orbiting Satellite using the json_interface.

The first step is to define the file tree. Since this is a simple example, there is no need to split the root input file into several files. Thus, we will have just a single file called main.json, as shown at the end of this tutorial.

3.1.1. General Settings

We define the key initialEpoch at root level, which will be used as initial time for the integrator and for interpolation of the Spice ephemeris. We also define the key finalEpoch, which is used for interpolation of the Spice ephemeris and to create a time-based termination condition. In both cases, we need to specify the values in seconds since J2000. In this case, globalFrameOrigin is specified to be "Earth". This is because we are only interested in simulating the orbit of a spacecraft around the Earth, and are not interested in any additional celestial body. Finally, the globalFrameOrientation is set to J2000.

Then, we request using the standard Spice kernels, namely pck00010.tpc, gm_de431.tpc, de430_small.bsp and pck00010.tpc. We do this by defining the key spice to be:

{
   "useStandardKernels": true,
   "preloadEphemeris": false
}

where we disabled preloading of the ephemeris of the celestial bodies from the period initialEpoch to finalEpoch.

3.1.2. Body Settings

The next step is to define the body settings. In this case, only Earth and the orbiting body (named Asterix) are considered. Thus, we set the key bodies to be:

{
   "Earth": {
      "useDefaultSettings": true
   },
   "Asterix": {
      "initialState": {
         "type": "keplerian",
         "semiMajorAxis": 7.5E+6,
         "eccentricity": 0.1,
         "inclination": 1.4888,
         "argumentOfPeriapsis": 4.1137,
         "longitudeOfAscendingNode": 0.4084,
         "trueAnomaly": 2.4412
      }
   }
}

The first body, Earth, has the key useDefaultSettings set to true, which means that its properties (such as gravitational parameter, atmosphere, etc.) will be loaded automatically.

The second body, Asterix, does not specify the key useDefaultSettings, which defaults to false. Thus, no properties will be loaded from Spice. Since no perturbations are considered in this propagation, we need not specify a mass or aerodynamic properties. Thus, we only need to provided an initialState. We can provide directly a vector with the Cartesian components, or an object defining the different keys of a Keplerian state, as shown above.

3.1.3. Propagation Settings

Then, we specify the propagator settings. In this case, we are going to propagate the translational state of Asterix about Earth, so we define the key propagators to be:

[
   {
      "integratedStateType": "translational",
      "centralBodies": [ "Earth" ],
      "bodiesToPropagate": [ "Asterix" ],
      "accelerations": {
         "Asterix": {
            "Earth": [
               {
                  "type": "pointMassGravity"
               }
            ]
         }
      }
   }
]

We specify the key propagators[ 0 ].accelerations, an object containing lists of accelerations. The inner keys (in this case, Earth) are the names of the bodies exerting the accelerations, while the outer keys (in this case, Asterix), are the names of the bodies undergoing the accelerations. Thus, accelerations.Asterix.Earth is read as “accelerations on Asterix caused by Earth”. In this case, the only acceleration is Earth’s point-mass gravity.

In this case, some keys of propagators[ 0 ] have been omitted. For instance, the key type has not been specified, meaning that the default value "cowell" is used.

3.1.4. Integration Settings

The next step is to define the integrator settings. The initial time is retrieved from the key initialEpoch defined at root level, so it is sufficient to define the key integrator to be equal to the following object:

{
   "type": "rungeKutta4",
   "stepSize": 10
}

The key saveFrequency is not specified, so the save frequency is assumed to be 1, which means that all the steps are saved.

3.1.5. Output Settings

Then, we have to define the files to which the results of the integration should be saved. We do this by assigning an array of objects containing export settings to the export key:

[
   {
      "file": "@path(stateHistory.txt)",
      "variables": [
         {
            "type": "state"
         }
      ]
   }
]

Here, each element in the array will result in the generation of a different output file; in this case, only one file (stateHistory.txt in the same directory as the input file) will be created. This file will contain a matrix of results, where each row corresponds to an epoch. The key epochsInFirstColumn defaults to true, which means that the first column of the matrix will contain the epochs, and subsequent columns will contain the values of the variables specified in the key variables. In this case, only the state (of the propagated body).

3.1.6. Running the Simulation

We can now carry out the propagation. However, if we want a file containing all the settings actually used by Tudat to be generated (including all default settings), we must specify the options key to be:

{
   "fullSettingsFile": "@path(fullSettings.json)"
}

The resulting input file, containing all the settings, will be:

main.json
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
{
  "initialEpoch": 0,
  "finalEpoch": 86400,
  "globalFrameOrientation": "Earth",
  "globalFrameOrientation": "J2000",
  "spice": {
    "useStandardKernels": true,
    "preloadEphemeris": false
  },
  "bodies": {
    "Earth": {
      "useDefaultSettings": true
    },
    "Asterix": {
      "initialState": {
        "type": "keplerian",
        "semiMajorAxis": 7.5E+6,
        "eccentricity": 0.1,
        "inclination": 1.4888,
        "argumentOfPeriapsis": 4.1137,
        "longitudeOfAscendingNode": 0.4084,
        "trueAnomaly": 2.4412
      }
    }
  },
  "propagators": [
    {
      "integratedStateType": "translational",
      "centralBodies": [
        "Earth"
      ],
      "bodiesToPropagate": [
        "Asterix"
      ],
      "accelerations": {
        "Asterix": {
          "Earth": [
            {
              "type": "pointMassGravity"
            }
          ]
        }
      }
    }
  ],
  "integrator": {
    "type": "rungeKutta4",
    "stepSize": 10
  },
  "export": [
    {
      "file": "@path(stateHistory.txt)",
      "variables": [
        {
          "type": "state"
        }
      ]
    }
  ],
  "options": {
    "fullSettingsFile": "@path(fullSettings.json)"
  }
}

After running in Terminal the following command:

json_inteface main.json

we will get a stateHistory.txt file containing the results, and a fullSettings.json file containing default settings and with some keys moved to a different place (e.g. bodies.Asterix.initialState to propagators[ 0 ].initialStates):

fullSettings.json
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
{
  "bodies": {
    "Asterix": null,
    "Earth": {
      "atmosphere": {
        "boundaryHandling": [
          "boundaryValue"
        ],
        "dependentVariablesNames": [
          "density",
          "pressure",
          "temperature"
        ],
        "file": {
          "0": "/Users/Michele/GitHub/tudat/tudatBundle/tudat/Tudat/../Tudat/External/AtmosphereTables/USSA1976Until100kmPer100mUntil1000kmPer1000m.dat"
        },
        "independentVariablesNames": [
          "altitude"
        ],
        "ratioOfSpecificHeats": 1.4,
        "specificGasConstant": 287.0,
        "type": "tabulated"
      },
      "ephemeris": {
        "convergeLighTimeAberration": false,
        "correctForLightTimeAberration": false,
        "correctForStellarAberration": false,
        "frameOrientation": "J2000",
        "frameOrigin": "SSB",
        "type": "directSpice"
      },
      "gravityField": {
        "model": "egm96",
        "type": "sphericalHarmonic"
      },
      "rotationModel": {
        "originalFrame": "J2000",
        "targetFrame": "IAU_Earth",
        "type": "spice"
      },
      "shapeModel": {
        "radius": 6371008.36666667,
        "type": "spherical"
      }
    }
  },
  "export": [
    {
      "epochsInFirstColumn": true,
      "file": "stateHistory.txt",
      "numericalPrecision": 15,
      "onlyFinalStep": false,
      "onlyInitialStep": false,
      "variables": [
        {
          "type": "state"
        }
      ]
    }
  ],
  "globalFrameOrientation": "J2000",
  "globalFrameOrigin": "Earth",
  "integrator": {
    "assessPropagationTerminationConditionDuringIntegrationSubsteps": false,
    "initialTime": 0.0,
    "saveFrequency": 1,
    "stepSize": 10.0,
    "type": "rungeKutta4"
  },
  "options": {
    "defaultValueUsedForMissingKey": "continueSilently",
    "fullSettingsFile": "fullSettings.json",
    "notifyOnPropagationStart": false,
    "notifyOnPropagationTermination": false,
    "tagOutputFilesIfPropagationFails": true,
    "unusedKey": "printWarning"
  },
  "propagators": [
    {
      "accelerations": {
        "Asterix": {
          "Earth": [
            {
              "type": "pointMassGravity"
            }
          ]
        }
      },
      "bodiesToPropagate": [
        "Asterix"
      ],
      "centralBodies": [
        "Earth"
      ],
      "initialStates": [
        [
          7037613.72352386
        ],
        [
          3237952.92678759
        ],
        [
          2150476.15106024
        ],
        [
          -1465.37073667488
        ],
        [
          -41.0666336979955
        ],
        [
          6622.85625637087
        ]
      ],
      "integratedStateType": "translational",
      "type": "cowell"
    }
  ],
  "spice": {
    "preloadEphemeris": false,
    "useStandardKernels": true
  },
  "termination": {
    "upperLimit": 86400.0,
    "variable": {
      "type": "independent"
    }
  }
}

3.1.7. Results

Finally, we can plot the results using the following MATLAB script:

plotResults.m
1
2
3
4
5
results = importdata('stateHistory.txt');
plot(results(:,1),results(:,2:4)/1e3); grid on;
xlabel('Time [seconds since J2000]');
ylabel('Position [km]');
legend('x','y','z');
../../../../_images/unperturbedSatellite.png