## [GSoC2018|OrbitDeterminator|Arya] Orbit determination and propagation

### Introduction

OrbitDeterminator is part of the bigger DGSN project by AerospaceResearch.Net. The Distributed Ground Station Network will be a network of thousands of ground stations across the globe. Together, these ground stations will track satellites cheaper and faster than conventional tracking stations. It will also get ordinary citizens involved in real space missions, so it is a win-win for everybody.

The purpose of OrbitDeterminator is to process the data coming from the DGSN and estimate the orbit of the satellite. It should also be able to predict the satellite’s location at any future time. This is the approximate workflow of the project:

(Note that the project is still under development so this workflow might change in future.)

My mentor was Alexandros Kazantzidis. He alongwith Nilesh Chaturvedi had worked on the preliminary orbit determination part last year. However the results could be improved. So I worked a little on that, but my main contribution was on real time tracking. As a side project I made a web application for one of the modules. I also cleaned the repo by adding a gitignore file and removing all temporary and IDE files.

### Technical Details

The project is hosted on GitHub and made entirely in Python. It includes a requirements.txt and setup.py file. So it can be installed easily using pip. The project directory structure is quite simple and intuitive:

```├── docs
└── orbitdeterminator
├── example_data
├── filters
├── kep_determination
├── propagation
├── test_deploy
├── tests
└── util```

Observation data is stored in the form of csv files in the following format:

```# the data consists of 4 columns separated by spaces:
#
# time, x-coordinate, y-coordinate, z-coordinate
#
# for example:

1526927274 -5234.47464 4126.08971 -1266.52201
1526927284 -5272.8012 4094.65453 -1208.06841
```

Time is stored in unix timestamp format. Unit of distance (unless otherwise specified) is a kilometer. Keplerian orbital elements are stored in the form of a 1×6 numpy array:

```kep[0] = semi-major axis
kep[1] = eccentricity
kep[2] = inclination
kep[3] = argument of perigee
kep[4] = right ascension of ascending node
kep[5] = true anomaly```

Similarly, state vectors are stored in the form of a 1×6 numpy array:

`s = [rx,ry,rz,vx,vy,vz]`

This should be enough to get one started. For more help you can check the documentation.

### Preliminary Orbit Determination (blog post)

Last year two methods of filtering were developed – the Savitzky-Golay filter and the Triple Moving Average filter. Two methods of orbit determination were also developed – the Lambert’s method and an interpolation method. However, they were not giving good results for certain kinds of data.

I made a new algorithm that fits an ellipse to the data, similar to fitting a line to a set of points. It gave better results than the previous algorithms so we decided to continue with it.

### Propagation (blog post)

The real time tracking consists of two parts – propagation of state vector and the Kalman filter. For propagation we decided to use the SGP4 algorithm. It did the propagation excellently but was not stable with the Kalman filter. So I made a simple propagator. It uses numerical integration and takes into account atmospheric drag and the oblateness of the Earth. After making it I spent a lot of time testing it. The only major problem was that the time period did not match with the real time period. A simple fix for this was to manually fiddle with the semi-major axis of the satellite until it gives the correct time period. I tried a lot to fix this problem, but could not do so. Anyway, since it was working well with the Kalman filter, we decided to continue.

### DGSN Simulator (blog post)

Since enough ground stations do not exist yet, we need some sort of artificial data to test the Kalman filter with. So I proposed to make a DGSN simulator module. The basic idea was that it will give the location of the satellite periodically with some noise. In the end the simulator had the following features:

• Noise in spatial coordinates
• Non-uniform interval between observations
• Gaps in observations (to simulate the satellite being out of range)
• Simulation speed control

The simulator in action. It is printing the coordinates every second.

Plotting the data produced by the simulator.

### Kalman Filter (blog post)

After all this the Kalman filter was left. This was quite straight-forward. I directly implemented the equations on Wikipedia and it worked quite well. However if a time varying covariance matrix is used, it will give better results.

### Web Application (blog post)

As a side project I made a web application for the ellipse fit algorithm. We created a new repository for this because it is not a necessary component of orbitdeterminator. It is made using the Dash library. Upload a csv file, it will process and give the orbital elements alongwith beautiful graphs.

The web application

### Future Work

• Integrating Aakash’s SGP4 module with the Kalman filter.
• Fixing the time period problem in the numerical propagator.
• Testing the system with real observations.
• Improving the Kalman filter.
• Deploying the web application on a public server.

## [GSoC2018|USOC|Pedro] Final Evaluations – My 3 month stay at AerospaceResearch

After 3 months of work towards AerospaceResearch, the time has come to write my last devblog related to this year’s edition of GSoC.  This might be a long one, so please bear with me for the next few minutes. At the end of the post, there’s a section with all my work throughout the project.

## Assigning data to UI elements

Since the last post, the AssignData Window has suffered considerable changes. I had to re-design it from scratch due to some limitations related to JavaFX’s TreeView implementation. Moving items from one tree to another causes them to behave incorrectly. I had to stick to another solution that may not look as smooth and intuitive but performs way better and actually works.

This is what it looks like:

## [GSoC’18|VisMa|Shantanu] Week #10-11: Dynamic Simplification and Plotting

This is GSoC’18 log#05. Here I will cover on what I have done in week #10-11. Link to the previous log. The work during this period is mostly done in visma/gui.

## Done so far…

A quick solver (visma/gui/qsolver.py) has been implemented which dynamically simplifies the expression as the user inputs. Instead of implementing the logger which was supposed to report if the input expression is invalid, I have implemented this feature in the qsolver itself. It lets the user know what is missing in the input or if the input syntax is wrong.

## [GSoC2018|OrbitDeterminator|Jorge] Week #7-8 – Refining Gauss method implementation

During these weeks, I worked on coding a high-level interface for two Gauss method applications of orbit determination: Earth satellites and asteroids.
One of the main differences with respect to my previous work, is that we relied heavily on the `astropy` library (www.astropy.org), a Python library for astronomical calculations. One of the main factors which inclined us to use this library, is that it has a lot of useful functions, it is relatively well-tested, gives more consistency to the code, and also avoids typos (e.g., in numerical values of astronomical constants). We also incorporated the `poliastro` library, mainly to use its implementation of the Stumpff functions.

### Changes in implementation

One of the main changes with respect to the previous version of our implementation, was the abstraction of a „core“ computation of the Gauss method and its refinement iterative stage, regardless of the case being handled, whether it is an Earth-orbiting object (satellite, space debris, etc.) or a Sun-orbiting object (main-belt asteroid, Near-Earth asteroid, comet, etc.). This abstraction is implemented in the `gauss_method_core` and `gauss_refinement` function, which are low level functions and may be adapted for user-defined applications.
A new feature of the latest version of the code, is that in case of having multiple solutions to the Gauss polynomial, now the user is able to select distinct roots for each occurrence of the multiple solutions. As we will see in examples below, multiple positive solutions to the Gauss polynomial are common when handling real-world data. In the case of finding more than one feasible solution to the Gauss polynomial, the code spits out all the feasible roots found; this allow the user to select the adequate root to the polynomial.
Also, the execution speed was improved for the Near-Earth asteroids case: when handling multiple observations, instead of reading the MPC-formatted file each time and retrieving the relevant triplet of observations, now the file is read only once. Since the observation files from MPC are typically a few thousand lines long, this improved the execution speeds about 10x.
Another important change, is that now the local mean sidereal time is computed using `astropy` ’s `sidereal_time` method for `SkyCoord` objects instead of using our own implementation. While doing this, we were able to identify a bug in our implementation of the computation of the local sidereal time!
Finally, in the case of Sun-orbiting bodies, the average orbital elements are computed in the heliocentric J2000.0 ecliptic frame; this allows us to directly compare our results, for example, with the orbital elements listed in the JPL’s Horizons online ephemeris service.

## [GSoC’18|OrbitDeterminator|Aakash] Week #7-8 : Propagation Model

`About the Author: Hello guys, I am Aakash Deep. I am an undergraduate student from Indraprastha Institute of Information Technology, Delhi (IIIT-D) in Computer Science and Engineering (CSE). I am a speed-cuber and, my hobby is solving Rubik's Cube. I am also founder of Rubik's Cube Club at IIIT-D.`

The post is in the continuation of the series of posts from the past. To read those blogs use these links for blog1, blog2 and blog3.

## Highlights

• The database module was added earlier to create and maintain/update the database. For the database, we used MySQL.
• The Gibb’s Method was implemented and OOP concepts were used for the ease of use and better maintenance.
• Propagation Model was implemented and the output was making some sense.

## [GSoC2018|Orbitdeterminator|Arya] Week #8-9: Implementing Kalman Filter

After the implementation of the Cowell propagator, it was time for the Kalman Filter. It is an algorithm that uses a series of measurements observed over time, containing statistical noise and other inaccuracies, and produces estimates of unknown variables that tend to be more accurate than those based on a single measurement alone. A Kalman Filter is the ideal filter for a linear process having Gaussian noise. Since our process is not linear, a modified version of the filter must be used. This is called the Extended Kalman Filter. It linearizes about the point in question and applies the regular Kalman Filter to it.

To apply the filter, the following things are required:

• A function f which outputs the next state, given the current state.
• The matrix F which is the jacobian of f .
• The matrix H which converts state into corresponding observations.
• A matrix Q denoting process noise. It consists of the inaccuracies in the model.
• A matrix R denoting measurement noise.

The variables involved during the calculations are:

• x – the state of the system
• z – the observations of the system
• P – covariance matrix of x. It denotes the inaccuracy in the estimate. As the filter runs, P is supposed to decrease.
• K – the Kalman gain. This matrix is between 0 and I and denotes how much the observations can be trusted vs how much the model can be trusted.

The filter consists of two major steps:

• Predict – in this step, we predict the next state (x) and covariance matrix (P) using our model.
• Update – in this step, we update our estimates of x and P using observations (z).

## [GSoC2018|OrbitDeterminator|Arya] Week #7-8: Implementing Cowell propagator

Last time when we tried to use the SGP4 propagator in our Kalman Filter, we ran into problems. This was because you can’t stop the algorithm at a certain stage and continue from there. Suppose you want to propagate from $t_1$ to $t_2$, you can directly propagate from $t_1$ to $t_2$ but you can’t propagate it from $t_1$ to $t_3$ to $t_2$ . So I set out to make our own propagator taking into account two major perturbations – oblateness of Earth and atmospheric drag. Instead of making an analytical propagator like SGP4, I went with a numerical one because that can be stopped and started at any point. So the first challenge was making a numerical integrator.

### Numerical Integration

Numerical integration are used to integrate a differential equation from one point to another point. I studied and tested various integrators and finally settled on Runge-Kutta 4th order integrator (RK4).

Advantages of RK4:

• Good accuracy for small to medium step sizes
• Low computation cost
• Easy to implement

Let the initial value problem be $\dot y = f(t,y)$ and $y(t_0) = y_0$ .

Choose a step size $h > 0$ and define

\begin{align*} y_{n+1} &= y_n + \frac{1}{6}(k_1+2k_2+2k_3+k_4) \\ t_{n+1} &= t_n + h \end{align*}

for  $n = 0,1,2,3,\dots$ where,

\begin{align*} k_1 &= h\,f\left( t_n,y_n \right) \\ k_2 &= h\,f\left( t_n + \frac{h}{2}, y_n + \frac{k_1}{2} \right) \\ k_3 &= h\,f\left( t_n + \frac{h}{2}, y_n + \frac{k_2}{2} \right) \\ k_4 &= h\,f\left( t_n + h, y_n + k_3 \right) \\ \end{align*}

Note that these equations work equally well whether y is a scalar or a vector. In our case, the differential equation is $\mathbf{\ddot r}=-\frac{\mu}{r^3}\vec{\mathbf r} + \vec{\mathbf a}_p$. It is not in a form suitable to be used directly in RK4. To use it in RK4 we have to vectorize the equation. First, let’s define the state of the system $\mathbf s$ as $[x, y, z, \dot x, \dot y, \dot z]^T$ . Let $r = \sqrt{x^2+y^2+z^2}$ . Then,

This form can be directly used in the RK4 integrator.

## [GSoC’18|VisMa|Shantanu] Week #08-09: Develop, Test, Repeat

This is GSoC log#04 (view log#03 here). Here I will cover on what I have done in week #08-09 and a gist of what has been accomplished in Phase II coding period and what is to be done in the final coding period.

## Done so far…

• Added tests using pytest
• Code coverage using coverage.py through pytest
• Added variable substitution methods
• Created an equation solver in multi-variables
• Initialized work on matrices
• Ported source to Python3 and using PyQt5