ASAT Code Tutorial 1: Read SatCat data with cURL
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 (presumably) very smart analysts.
We’ll get debris object data from the REST API of the SatCat mentioned above, Space-Track.org, which is operated by the U.S. Strategic Command.
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.
REST API, Http, and cURL
The Space-Track.org service exposes its database to queries via a REST API. If REST APIs are new to you, that’s fine, you don’t really need to know much about REST to query the server.
In this post we’re going to:
- Learn how to issue http requests using the cURL utility
- Transform a server’s JSON responses into a pretty human-readable form
- Save the server’s response to a file
- Authenticate a user-name and password with Space-Track.org and get query results in a single request
- Alternatively, authenticate with the service in advance and store the result in a cookie file that subsequent queries can use
- Use cURL to submit a
gp
query to get orbital data for a group of debris objects associated with an anti-satellite weapons test - Use cURL to submit a
cdm_public
query to receive ‘conjunction’ messages (e.g… collision near-miss alerts)
And, we’ll observe some data and make a few inferences about past Anti-Satellite weapons tests along the way.
As mentioned, we’re going to use a tool called ‘cURL’. cURL allows the user to make http calls from a command prompt, which is exactly what we need. Go ahead and try this curl command:
curl https://stupidrockettricks.com/post/asat-curl/curl-hello-world.txt
If everything goes well, you should see the contents of the text file.
Let’s try a JSON file, since that’s the format the Space-Track.org server will reply with.
curl https://stupidrockettricks.com/post/asat-curl/boxscore.json
And, the result:
curl https://stupidrockettricks.com/post/asat-curl/boxscore.json
[{"COUNTRY":"ALGERIA","SPADOC_CD":"ALG","ORBITAL_TBA":"0","ORBITAL_PAYLOAD_COUNT":"6","ORBITAL_ROCKET_BODY_COUNT":"0","ORBITAL_DEBRIS_COUNT":"0","ORBITAL_TOTAL_COUNT":"6","DECAYED_PAYLOAD_COUNT":"0","DECAYED_ROCKET_BODY_COUNT":"0","DECAYED_DEBRIS_COUNT":"0","DECAYED_TOTAL_COUNT":"0","COUNTRY_TOTAL":"6"},{"COUNTRY":"ALL","SPADOC_CD":"ALL","ORBITAL_TBA":"271","ORBITAL_PAYLOAD_COUNT":"8689","ORBITAL_ROCKET_BODY_COUNT":"2285","ORBITAL_DEBRIS_COUNT":"14295","ORBITAL_TOTAL_COUNT":"25540","DECAYED_PAYLOAD_COUNT":"3884","DECAYED_ROCKET_BODY_COUNT":"4043","DECAYED_DEBRIS_COUNT":"19033","DECAYED_TOTAL_COUNT":"26960","COUNTRY_TOTAL":"52500"},{"COUNTRY":"ARAB SATELLITE COMMUNICATIONS ORGANIZATION","SPADOC_CD":"AB","ORBITAL_TBA":"0","ORBITAL_PAYLOAD_COUNT":"14","ORBITAL_ROCKET_BODY_COUNT":"0","ORBITAL_DEBRIS_COUNT":"0","ORBITAL_TOTAL_COUNT":"14","DECAYED_PAYLOAD_COUNT":"1","DECAYED_ROCKET_BODY_COUNT":"0","DECAYED_DEBRIS_COUNT":"0","DECAYED_TOTAL_COUNT":"1","COUNTRY_TOTAL":"15"},{"COUNTRY":"ARGENTINA","SPADOC_CD":"ARGN","ORBITAL_TBA":"0","ORBITAL_PAYLOAD_COUNT":"44","ORBITAL_ROCKET_BODY_COUNT":"0","ORBITAL_DEBRIS_COUNT":"1","ORBITAL_TOTAL_COUNT":"45","DECAYED_PAYLOAD_COUNT":"2","DECAYED_ROCKET_BODY_COUNT":"0","DECAYED_DEBRIS_COUNT":"0","DECAYED_TOTAL_COUNT":"2","COUNTRY_TOTAL":"47"},{"COUNTRY":"ASIASAT CORP","SPADOC_CD":"AC","ORBITAL_TBA":"0","ORBITAL_PAYLOAD_COUNT":"8","ORBITAL_ROCKET_BODY_COUNT":"0","ORBITAL_DEBRIS_COUNT":"0","ORBITAL_TOTAL_COUNT":"8","DECAYED_PAYLOAD_COUNT":"0","DECAYED_ROCKET_BODY_COUNT":"0","DECAYED_DEBRIS_COUNT":"0","DECAYED_TOTAL_COUNT":"0","COUNTRY_TOTAL":"8"},{"COUNTRY":"AUSTRALIA","SPADOC_CD":"AUS","ORBITAL_TBA":"0","ORBITAL_PAYLOAD_COUNT":"30","ORBITAL_ROCKET_BODY_COUNT":
...
Argh. That’s nearly unpossible to read! Okay, this is what we do… Make yourself a working directory, say c:\rockettricks
and change to that directory.
mkdir c:\rockettricks
cd /D c:\rockettricks
Transform “ugly” JSON responses to “pretty”, with jq
We’re going to download a little utility program that can print “pretty” JSON, which we can actually read - ‘jq’.
jq can mangle the data format that you have into the one that you want with very little effort, and the program to do so is often shorter and simpler than you’d expect.
./jq
To download this utility into our directory, you guessed it, just use cURL:
curl --remote-name --location https://github.com/stedolan/jq/releases/download/jq-1.6/jq-win64.exe
ren jq-win64.exe jq.exe
The two lines above download jq, then rename it to jq.exe
to save ourselves from typing jq-win64
each time.
Let’s try downloading the JSON file again, and this time view a “pretty” version transformed by jq:
curl https://stupidrockettricks.com/post/asat-curl/boxscore.json | jq
This time we get:
curl https://stupidrockettricks.com/post/asat-curl/boxscore.json | jq
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 35408 100 35408 0 0 99970 0 --:--:-- --:--:-- --:--:-- 99k
[
{
"COUNTRY": "ALGERIA",
"SPADOC_CD": "ALG",
"ORBITAL_TBA": "0",
"ORBITAL_PAYLOAD_COUNT": "6",
"ORBITAL_ROCKET_BODY_COUNT": "0",
"ORBITAL_DEBRIS_COUNT": "0",
"ORBITAL_TOTAL_COUNT": "6",
"DECAYED_PAYLOAD_COUNT": "0",
"DECAYED_ROCKET_BODY_COUNT": "0",
"DECAYED_DEBRIS_COUNT": "0",
"DECAYED_TOTAL_COUNT": "0",
"COUNTRY_TOTAL": "6"
},
{
"COUNTRY": "ALL",
"SPADOC_CD": "ALL",
"ORBITAL_TBA": "271",
...
MUCH NICER!
You’re now ready to access the Space-Track.org server using cURL :)
Call the Space-Track.org REST API from cURL
Here’s what we do:
- Go to space-track.org and register
- Open a Windows command prompt, and run this command:
curl https://www.space-track.org/ajaxauth/login -d "identity=MY_USERNAME&password=MY_PASSWORD&query=https://www.space-track.org/basicspacedata/query/class/boxscore" | jq > boxscore.json
…but change MY_USERNAME
and MY_PASSWORD
to the values you registered in step 1…
Prior to this, we were just downloading a lame cached json file from the stupidRocketTricks.com web server. Now, we’re calling the actual Space-Track.org REST API, via cURL, on the command line, authenticating request with valid credentials. And, we’re saving the response as “pretty” JSON to a file, named boxscore.json
. If you open up that file you’ll hopefully see the server’s response as pretty JSON, and not an error message of some sort.
Saving authentication to a cookie file
In this case, we authenticated our credentials AND issued a single request, all in one Http request. We can instead, though, authenticate our credentials in a single http request and save the authentication data into a cookie file. To do this, we’ll need the cURL -c
and -b
options, and give it the name of a file to store/load cookie data from.
We do this like so:
curl -c cookies.txt -b cookies.txt https://www.space-track.org/ajaxauth/login -d "identity=MY_USERNAME&password=MY_PASSWORD"
Of course, once again change MY_USERNAME
and MY_PASSWORD
appropriately again.
If all went well, your authentication credentials are now cached in a local file named cookies.txt
. Feel free to open it and inspect the contents.
Why did we bother doing this? Well, for the time being now we can query the server without supplying a username and password each time.
Try a request, using the credentials in the cookie file:
curl --limit-rate 100K --cookie cookies.txt "https://www.space-track.org/basicspacedata/query/class/gp/OBJECT_ID/~~1963-014/orderby/DECAY_DATE%20desc/" | jq > west-ford-needles.json
If all went well, you’ll have a JSON file that downloaded orbital data for debris left over from Project West Ford. It should look like this:
[
{
...
"OBJECT_NAME": "WESTFORD NEEDLES",
"OBJECT_ID": "1963-014EZ",
...
"OBJECT_TYPE": "DEBRIS",
"COUNTRY_CODE": "US",
"LAUNCH_DATE": "1963-05-09",
...
"DECAY_DATE": "2020-11-08",
},
You’re not seeing things… This thing went up in May 1963, and didn’t down until November 2020.
If you’d rather not hit the Space-Track.org server but would still like to see what the response looks like, here is a cached version from stupidRocketTricks.com:
Westford Needles JSON response.
You’ll notice there’s a lot of debris entries for these needles. What the heck were they???
Project West Ford
Congrats, if you completed the above exercise you now have telemetry data (and more) for the Project West Ford needles launched on May 9, 1963.
Project West Ford sounds so crazy it’s hard to believe it’s true. Can you believe in the early 60’s the U.S. intentionally planted over 350 million bits of space debris?
A secondary objective was to eject 350 million copper needles into earth orbit (Project West Ford)
MIDAS 6
What the…
Now, these were tiny needles, less than an inch long and around 20 micrometers in diameter. However, one of the 3 attempts did not go well and the needles did not fully disperse - over 60 years later they’re still contributing to debris hazards.
Project West Ford:
https://en.wikipedia.org/wiki/Project_West_Ford
Current Remnants:
http://stuffin.space/?search=1963-014
Remember that thing you learned in Physics (or Kerbal Space Program) that for any given point in an orbit, the orbiter will always pass through the same point again?
Can you tell where the needles were released?
Since this was just a dry run, we haven’t pulled data from an actual ASAT test yet, but West Ford is interesting, so… There’s 150 entries in the data we pulled, which is probably an arbitrary cutoff.
The needles that have not reentered yet do not list a decay date. For instance, the very last entry:
{
"CCSDS_OMM_VERS": "2.0",
"COMMENT": "GENERATED VIA SPACE-TRACK.ORG API",
"CREATION_DATE": "2022-05-01T17:24:19",
"ORIGINATOR": "18 SPCS",
"OBJECT_NAME": "WESTFORD NEEDLES *",
"OBJECT_ID": "1963-014CF",
...,
"DECAY_DATE": null,
The records list 49 debris items as having fallen from orbit, and 101 that are still circling. The last portions of the record are the “Two-Line Element” sets that describe the object’s orbit in the near term:
"TLE_LINE0": "0 WESTFORD NEEDLES",
"TLE_LINE1": "1 03253U 63014 BT 68149.86953749 .00004779 +00000-0 +00000-0 0 9993",
"TLE_LINE2": "2 03253 084.9499 328.4708 2732312 019.1959 349.4277 08.86589828003386"
Destructive Anti-Satellite Tests
We’ll look at ASAT Data (briefly) from 4 different ASAT tests - one each by China, India, USA, and USSR.
China: Fengyun-1C (11 January 2007)
In Jan 2007, China destroyed a weather satellite as a test of their SC-19 Anti-Ballistic Missile.
More info:
https://en.wikipedia.org/wiki/2007_Chinese_anti-satellite_missile_test#Space_debris_tracking
curl --limit-rate 100K --cookie cookies.txt "https://www.space-track.org/basicspacedata/query/class/gp/OBJECT_ID/~~1999-025E/orderby/DECAY_DATE%20desc/" | jq > fengyun-1c-cataloged.json
The above returns 601 debris items, which is probably an arbitrary cutoff. Of the results 88 have decayed, while the rest remain circling.
If you’d prefer to avoid calling the Space-Track.org server, a cached response:
Fengyun-1C JSON response
Check out this mess:
http://stuffin.space/?search=1999-025e
India: Mission Shakti (Microsat-R, 27 March 2019)
India tested an ASAT weapon, a modified anti-ballistic missile, in March 2019.
https://en.wikipedia.org/wiki/Mission_Shakti#Space_debris
You may need to log in again (see above), but here’s s curl request for the debris from this test:
curl --limit-rate 100K --cookie cookies.txt "https://www.space-track.org/basicspacedata/query/class/gp/OBJECT_ID/~~2019-006D/orderby/DECAY_DATE%20desc/" | jq > microsat-r-cataloged.json
Cached response:
Microsat-R JSON response
The most recent piece of debris from this test to decay:
"DECAY_DATE": "2021-03-22",
And, scanning through the data there is only one piece of debris that has yet to decay.
USA: USA-193 (21 February 2008)
Prior to calling for a halt to ASAT testing, the USA tested ASATs, successfully destroying several satellites.
The first US test, on 13 September 1985, an ASM-135 ASAT missile launched from a USAF F-15 destroyed P78-1 (Aka Solwnd), a solar physics research satellite. This test created at least 285 identified debris objects. (All debris from this test has since de-orbited.)
The following destructive test, VSE (Delta-180, DM-43) on 5 September 1986, was a SDI (ABM-system) test that involved steering a satellite into the path of the launch vehicle’s second stage (not an ASAT missile). The goal was to test interception guidance and navigation algorithms.
And finally, a satellite known as USA-193 was decommissioned by explosive disassembly via a US SM-3 in Feb 2008.
More info:
https://en.wikipedia.org/wiki/USA-193
curl --limit-rate 100K --cookie cookies.txt "https://www.space-track.org/basicspacedata/query/class/gp/OBJECT_ID/~~2006-057/orderby/NORAD_CAT_ID%20asc/" | jq > usa-193-cataloged.json
Cached response:
USA-193 JSON response
Russia: KOSMOS-1408 (15 November 2021)
Early in the morning of November 15, Moscow time, a Russian missile blasted a Russian satellite to smithereens. The destroyed satellite, Kosmos-1408, had been in orbit for nearly four decades. With at least 1,500 trackable pieces, and countless more too small for detection, the remains of Kosmos-1408 pose a threat to other objects in orbit. The destruction itself caused astronauts and cosmonauts aboard the International Space Station to shelter in space. It also risked harm to China’s taikonauts aboard the Tiangong space station.
This week’s destroyed Russian satellite created even more dangerous space debris
BY KELSEY D. ATHERTON, Popular Science
More info:
https://en.wikipedia.org/wiki/Kosmos_1408
curl --limit-rate 100K --cookie cookies.txt "https://www.space-track.org/basicspacedata/query/class/gp/OBJECT_ID/~~1982-092A/orderby/NORAD_CAT_ID%20asc/" | jq > cosmos-1408-cataloged.json
Cached response:
KOSMOS-1408 JSON response
Collision Near-Miss Alerts
So, how big of a problem is this? Is this all theoretical, or is it real?
Luckily there’s people tasked with monitoring all the junk that’s already floating around and issuing alerts in time for collision avoidance maneuvering.
Let’s see how many near-miss alarms were generated in the last month, shall we?
curl --limit-rate 100K --cookie cookies.txt "https://www.space-track.org/basicspacedata/query/class/cdm_public/orderby/PC%20desc/" | jq > near-miss-alarms.json
Cached response:
Debris Near-Miss Alerts
The results look something like this…:
[
{
"CDM_ID": "280352437",
"CREATED": "2022-04-29 00:45:12.000000",
"EMERGENCY_REPORTABLE": "Y",
"TCA": "2022-04-29T22:03:26.595000",
"MIN_RNG": "4",
"PC": "0.1663616",
"SAT_1_ID": "22487",
"SAT_1_NAME": "COSMOS 2233",
"SAT1_OBJECT_TYPE": "PAYLOAD",
"SAT1_RCS": "LARGE",
"SAT_1_EXCL_VOL": "5.00",
"SAT_2_ID": "5758",
"SAT_2_NAME": "THORAD AGENA D DEB",
"SAT2_OBJECT_TYPE": "DEBRIS",
"SAT2_RCS": "SMALL",
"SAT_2_EXCL_VOL": "5.00"
},
The possibility of this event resulting in a collision is estimated as 16.6% (“PC”, above). Note, though, that the command above asked for the results to be sorted in descending order. Thus, the most likely event to result in a collision over the last month is between COSMOS 2233, and THORAD AGENA D Debris.
But, there’s many more alarms than this one. At present, the database says there were 24,265 alarms last month, almost 1,000 per day. (Unless I’ve badly miscounted - anything is possible). Many of these alerts are duplicates, though. In cases where there’s two satellite operators that need to be warned, two alerts are issued - one alert is issued for each operator. Per our data, there’s about 30 near-miss alarms per hour. One every other minute!
Most of the misses appear unlikely. How many of them are judged more than 10% likely to occur? Try this:
curl --limit-rate 100K --cookie cookies.txt "https://www.space-track.org/basicspacedata/query/class/cdm_public/PC/%3E0.1/orderby/TCA%20asc/" | jq > very-near-miss-alarms.json
Cached response:
Debris Very-Near-Miss Alerts
We get 7 records covering 4 possible collisions estimated above 10% chance in likelihood. Note though, I did not see a description of the “PC” field here, where I would expect it to be described:
https://public.ccsds.org/Pubs/508x0b1e2c2.pdf
I’m just assuming PC=1.0000 means a 100% chance of a collision but you know what happens when people assume things.
Back Link:
Defense: We need clean Anti-Satellite Weapons! Part 2: Intro to Asat Code Tutorials