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

### List of scripts I created

- kep_determination/ellipse_fit.py
- propagation/cowell.py
- propagation/simulator.py
- propagation/dgsn_simulator.py
- propagation/kalman_filter.py
- propagation/sgp4_prop.py
- propagation/sgp4_prop_string.py
- tests/test_ellipse_fit.py
- util/anom_conv.py
- util/new_tle_kep_state.py
- util/teme_to_ecef.py
- orbitdeterminator-webapp/app.py

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