ASAT Code Tutorial 2: Process SatCat data yourself in a C# Application

post-thumb

Note: This is a post is part of a multi-part series.


Preface: Getting Data from Space-Track.org

In case you missed it: Please tread lightly here.

A Satellite Catalog (SatCat) contains information about objects in Earth’s orbit. The data is generated by radar tracking stations, then categorized and cataloged by some (definitely) very smart analysts. We’ll get debris object data from the REST API of a SatCat operated by the U.S. Strategic Command, Space-Track.org.

If it sounds a bit serious, it is.

Air Force Maj. Gen. David D. Thompson, U.S. Strategic Command’s director of plans and policy at Offutt Air Force Base, Nebraska, said the release of new high-quality positional information on space debris of an unknown origin will help owner-operators better protect their satellites from these objects and ultimately create less space debris.
“We run a predictive program that shows where the objects are, where they will be in the future, and the potential for these objects to run into each other,” Thompson said.
Officials Expand Space-tracking Website
U.S. Department of Defense

If you adhere to the User Agreement you can obtain credentials to query the SatCat.

You’ll need a Space-Track.org username and password shortly, so if you haven’t already done so, go to space-track.org and register.


Data Analysis

Querying the SatCat from C#

Sure, it was fun querying the SatCat from cURL, but we can’t do a lot with the data (unless we write an app that parses these downloaded data from files).

The good news is we have even more power when we query the SatCat from an application we author in a programming language, such as C#.

In this post we’re going to:

  • Send http requests to Space-Track.org
  • Authenticate a username/password AND submit a query in the same http request
  • Alternatively, authenticate with the service in advance and store the result in a cookie that subsequent queries can use
  • Submit a cdm_public query to receive ‘conjunction’ messages (e.g… collision near-miss alerts)
  • Submit a gp query to get orbital data for a group of debris objects associated with an anti-satellite weapons test

Here we go! :-D

C# App: “Conjunction” alerts

By “Conjunction” we mean collision near-misses

As before, we can authenticate AND query the server in a single call. From C#:

            string jsonResponse;
            using (var client = new WebClient())
            {
                string uriBase = "https://www.space-track.org";
                string requestController = "/basicspacedata";
                string requestAction = "/query";
                // Here, we prepare a 'cdm_public' query, which returns a list of conjunction alerts.
                // We'll constrain the search to the "Time of Closest Approach" after 'now'...
                // ...And return the list sorted by the time of closest approach.
                string predicateValues = "/class/cdm_public/TCA/%3E" 
                                         + DateTime.UtcNow.ToString("s") 
                                         + "/orderby/TCA%20asc/emptyresult/show";
                string requestUrl = uriBase + requestController + requestAction + predicateValues;

                // Store the user authentication information, as well as a query to execute upon authentication
                var data = new NameValueCollection
                {
                    { "identity", userRef },
                    { "password", passwordRef },
                    { "query", requestUrl },
                };

                byte[] requestResponse;
                try
                {
                    // Submit the Query request to the REST API endpoint and wait for the response
                    requestResponse = client.UploadValues(uriBase + "/ajaxauth/login", data);
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.ToString());
                    return;
                }

                jsonResponse = System.Text.Encoding.Default.GetString(requestResponse);
            }


            Conjunction[] deserializedResponse = null;
            try
            {
                deserializedResponse = JsonConvert.DeserializeObject<Conjunction[]>(jsonResponse);
            }
            catch (Exception e)
            {
                Console.WriteLine("Could not parse response: {0}", e.ToString());
                return;
            }

Assuming all goes well, we’ll have a list of Conjunctions we can process in deserializedResponse.

Parsing JSON in C# is made easy with Json.NET, which the above project uses. See the full source on GitHub for details.

Example Program Output:

Querying SpaceTrack active for Conjunction Alerts...
Found 1351 Records
-------------------------

CDM_ID 291727653 PC 0.0002372735 TCA 5/19/2022 12:08:52 AM EMERGENCY_REPORTABLE Y
   SAT_1_NAME SL-8 R/B (RocketBody) SAT_2_NAME DELTA 1 DEB (Debris)

CDM_ID 291729471 PC 0.0002372735 TCA 5/19/2022 12:08:52 AM EMERGENCY_REPORTABLE Y
   SAT_1_NAME DELTA 1 DEB (Debris) SAT_2_NAME SL-8 R/B (RocketBody)
   ...

Cached Response:
Active Conjunction Alerts

The example program is available on GitHub. See the source code for details on entering your Space-Track.org username & password.
ConjunctionAlerts project on GitHub

And the winner is… … …

Fengyun 1C easily wins the “most debris alerts” award!

In the intro, I mentioned between the Russian and Chinese ASAT tests, one generates significantly more near-miss alerts than the other. So, which one is it?

Kosmos 1408 (Russia): Cited in 18 alerts
Fengyun 1C (China): Cited in 768 alerts

Holy discrepancies, Batperson! Why the difference? Me thinks China needs to get that Space-Debris sweeper in gear (assuming it’s not just an ‘Co-Orbital’ anti-satellite weapon).

Firstly, it’s speculated the Russian satellite broke up into much larger and less numerous pieces than initially expected and feared. So, there’s apparently a lot more pieces of Fengyun 1C floating around threatening to run into other things. The wikipedia entry for the two satellites indicates Fengyun created about 10x the individual debris objects as the Kosmos “test”.

Secondly, Kosmos 1408 was destroyed at a lower altitude than Fengyun 1C, which may make a difference. If you notice the orbital periods of the Kosmos debris it’s generally in the 90’s (minutes), while the Fengyun debris is in the low 100’s. The greater the orbital period, the greater the altitude. Before interception Fengyun had an orbital period of 102 minutes, compared to the Kosmos satellite at 97.8 minutes. This certainly isn’t enough to cover the discrepancy between 18 alerts vs 768 alerts, it’s likely a very minor factor. If anyone has an explanation other than the quantity of debris objects please clue me in :-D. Perhaps I’ve made an error in assumptions analyzing the alerts?

Of note:

China filed a formal complaint to the United Nations (UN) on Dec. 6 about collision risks the SpaceX’s Starlink satellites pose to its manned space station.
China complains to UN about dodging SpaceX Starlink satellites
Financial Post

I was not able to find a single alert (at this time) involving a Starlink satellite.

C# App: Get Debris objects by parent’s OBJECT_ID

Also, just like before, we can authenticate our user credentials with Space-Track.org and save them to a cookie. The first step is to derive our own class from .NET’s WebClient class.

        public class WebClientEx : WebClient
        {
            // Create the container to hold all Cookie objects
            private CookieContainer _cookieContainer = new CookieContainer();

            // Override the WebRequest method so we can store the cookie
            // container as an attribute of the Web Request object
            protected override WebRequest GetWebRequest(Uri address)
            {
                WebRequest request = base.GetWebRequest(address);

                if (request is HttpWebRequest)
                    (request as HttpWebRequest).CookieContainer = _cookieContainer;

                return request;
            }
        }

As you can see from the code, we do this so we can associate a CookieContainer with each Web Request.

Now we can use our super special WebClient to query Space-Track.org. We’ll issue two (synchronous) Web Requests, one to authenticate, and a second that does the actual query:

            string uriBase = "https://www.space-track.org";
            string requestController = "/basicspacedata";
            string requestAction = "/query";
            // Here, we use the `gp` REST API, to get orbital data for a set of objects.
            string predicateValues = "/class/gp/OBJECT_ID/~~" 
                                    + objectId 
                                    + "/orderby/DECAY_DATE%20desc/emptyresult/show";
            string request = uriBase + requestController + requestAction + predicateValues;

            // Create new WebClient object to communicate with the service
            using (var client = new WebClientEx())
            {
                // Store the user authentication information
                var data = new NameValueCollection
                {
                    { "identity", User },
                    { "password", Password },
                };

                byte[] queryResponse;
                try
                {
                    // Generate the URL for the API Query and return the response
                    // Request #1
                    var authenticationResponse = client.UploadValues(uriBase + "/ajaxauth/login", data);
                    // Request #2
                    queryResponse = client.DownloadData(request);
                }
                catch(Exception e)
                {
                    return e.ToString();
                }

                return (System.Text.Encoding.Default.GetString(queryResponse));

We no longer append the query into the Http request data because we’re submitting it as a separate request.

Here, we use Space-Track.org’s ‘gp’ REST API, which returns orbital data for a list of objects. To obtain the set of objects associated with a given ASAT test we use a ‘like’ query for the Object ID. To find Kosmos-1408 debris, we ask the API for data for object ID’s that are ‘like 1982-092A’, which in the query becomes OBJECT_ID/~~1982-092A. This returns a list including objects like ‘1982-092AEN’, ‘1982-092AUR’, ‘1982-092ACT’, etc.

Admittedly we’re not doing a lot of data “processing” here. But, you get the idea - and once you get the data loaded into your app you can process it all you want.

GitHub Project:
ASATDebrisCsExample Project on GitHub


Back Link:
Defense: We need clean Anti-Satellite Weapons! Part 2: Intro to Asat Code Tutorials

Comments are disabled. To share feedback, please send email, or join the discussion on Discord.