#!/usr/bin/env perl
use
5.006002;
use
POSIX
qw{ strftime }
;
our
$VERSION
=
'0.168'
;
my
%opt
;
GetOptions( \
%opt
,
qw{ username=s password=s }
,
help
=>
sub
{ pod2usage( {
-verbose
=> 2 } ) },
) or pod2usage( {
-verbose
=> 0 } );
my
%desc
;
my
$cgi
= CGI->new();
$cgi
->charset(
'utf-8'
);
my
$json
= JSON->new()->utf8();
my
$st
= Astro::SpaceTrack->new();
foreach
my
$attr
(
qw{ password username }
) {
defined
$opt
{
$attr
}
and
$st
->set(
$attr
=>
$opt
{
$attr
} );
}
defined
$opt
{username}
or
defined
$opt
{password}
or
$st
->set(
identity
=> 1 );
my
$title
=
'Space Track Model Definitions'
;
print
$cgi
->start_html(
-title
=>
$title
,
-style
=> {
src
=>
'trw.css'
} ),
$cgi
->h1(
$title
),
$cgi
->p(
<<"EOD" );
This is an expansion on the model definitions provided by version 2 of
the Space Track interface. It is generated by
@{[ Cwd::abs_path( $0 ) ]}
EOD
foreach
my
$class
(
qw{ boxscore launch_site satcat tle tle_latest }
) {
my
$resp
=
$st
->spacetrack_query_v2(
basicspacedata
=>
'modeldef'
,
class
=>
$class
,
format
=>
'json'
,
);
$resp
->is_success()
or
die
$resp
->status_line();
print
$cgi
->h2(
"Class $class"
),
$cgi
->start_dl();
foreach
my
$field
(
sort
{
$a
->{Field} cmp
$b
->{Field} }
@{
$json
->decode(
$resp
->content() )->{data} }
) {
my
$name
=
$field
->{Field};
print
$cgi
->dt(
$name
);
my
$blurb
=
defined
$desc
{
$class
}{
$name
} ?
$desc
{
$class
}{
$name
} :
defined
$desc
{_}{
$name
} ?
$desc
{_}{
$name
} :
'Unknown.'
;
$blurb
=~ s/ \s* \n / /smxg;
print
$cgi
->dd(
$blurb
, interpret_type(
$field
) );
}
print
$cgi
->end_dl();
}
print
$cgi
->p(
<<'EOD' );
The descriptions of the data types should be pretty much
self-explanatory. However:
EOD
print
$cgi
->ul(
map
{
$cgi
->li(
$_
) }
<<'EOD',
<code>date</code> by itself means a calendar date (GMT), without a time
of day. The date is expressed as a numeric <code>year-month-day</code>
with the year being a four-digit Gregorian year, and the month and day
being two digits.
EOD
<<'EOD',
<code>date and time</code> means both calendar date (GMT) and optional
time of day. The time of day is expressed as
<code>hour:minute:second</code>, with each field having two digits, and
separated from the date by a single space.
EOD
);
print
$cgi
->table(
{
class
=>
'nopadding'
,
summary
=>
'revision information'
,
},
$cgi
->Tr(
$cgi
->td( {
class
=>
'right'
},
'Last revision:'
),
$cgi
->td( strftime(
'%d-%b-%Y'
,
localtime
) ),
),
);
print
$cgi
->end_html();
{
my
%interp
;
BEGIN {
%interp
= (
bigint
=>
sub
{
return
'integer of 8 bytes'
;
},
char
=>
sub
{
my
(
$type
,
$width
) =
@_
;
return
"string of $width characters"
;
},
date
=>
sub
{
return
'date'
;
},
datetime
=>
sub
{
return
'date and time'
;
},
decimal
=>
sub
{
my
(
$type
,
$width
) =
@_
;
(
$width
,
my
$decimal
) =
split
qr{ , }
smx,
$width
;
return
"decimal number of $width digits with $decimal after the decimal"
;
},
double
=>
sub
{
return
'double-precision number'
;
},
enum
=>
sub
{
my
(
$type
,
$width
) =
@_
;
return
"enumeration of $width"
;
},
float
=>
sub
{
return
'floating-point number'
;
},
int
=>
sub
{
return
'integer of 4 bytes'
;
},
mediumint
=>
sub
{
return
'integer of 3 bytes'
;
},
smallint
=>
sub
{
return
'integer of 2 bytes'
;
},
tinyint
=>
sub
{
return
'integer of 1 byte'
;
},
varchar
=>
sub
{
my
(
$type
,
$width
) =
@_
;
return
"string of up to $width characters"
;
},
);
}
sub
interpret_type {
my
(
$field
) =
@_
;
my
$type
=
$field
->{Type};
my
@desc
= (
'It is'
);
$type
=~ s/ \s* unsigned //smx
and
push
@desc
,
'unsigned'
;
$type
=~ m/ \A ( \w+ ) (?: [(] ( [^(]+ ) [)] )? \s* /smx
or
return
;
my
(
$kind
,
$width
) = ( $1, $2 );
push
@desc
,
$interp
{
$kind
} ?
$interp
{
$kind
}->(
$kind
,
$width
) :
defined
$width
?
"$kind($width)"
:
$kind
;
splice
@desc
, 1, 0,
$desc
[1] =~ m/ \A [aeihou] /smx ?
'an'
:
'a'
;
$desc
[-1] .=
'.'
;
if
(
exists
$field
->{Null} ) {
push
@desc
,
$field
->{Null} =~ m/ \A yes \z /smxi ?
'It can be null.'
:
'It can not be null.'
;
}
if
(
exists
$field
->{Default} ) {
push
@desc
,
'The default is'
;
if
(
defined
$field
->{Default} ) {
if
(
''
eq
$field
->{Default} ) {
push
@desc
,
'the empty string'
;
}
else
{
(
my
$dflt
=
$field
->{Default} ) =~ s/
" /"
"/smxg;
push
@desc
,
qq<"$dflt">
;
}
}
else
{
push
@desc
,
'null'
;
}
$desc
[-1] .=
'.'
;
}
return
join
' '
,
@desc
;
}
}
BEGIN {
%desc
= (
_
=> {
APOGEE
=>
<<'EOD',
This is the apogee of the body's orbit in kilometers above the Earth's
surface.
EOD
ARG_OF_PERICENTER
=>
<<'EOD',
This is the argument of perigee of the body's orbit, in degrees.
EOD
BSTAR
=>
<<'EOD',
This is the B* drag term in the model of the body's motion, in inverse
Earth radii.
EOD
CLASSIFICATION_TYPE
=>
<<'EOD',
This is the classification status of the orbital data. In theory it is
either 'C' for 'Classified' or 'U' for 'Unclassified.' In practice you
will only see 'U'.
EOD
COUNTRY
=>
<<'EOD',
This is an abbreviation for the country or other agency to which the
body belongs. It corresponds to SPADOC_CD in class boxscore.
EOD
CURRENT
=>
<<'EOD',
This is 'Y' for the current record when the query is made, or 'N'
otherwise.
EOD
DECAY
=>
<<'EOD',
This is the date the body deorbited. If the body is still in orbit it is
null.
EOD
ECCENTRICITY
=>
<<'EOD',
This is the eccentricity of the body's orbit.
EOD
ELEMENT_SET_NO
=>
<<'EOD',
This is the orbital element sets for a given body are numbered
sequentially. This is this element set's number in the sequence.
EOD
EPHEMERIS_TYPE
=>
<<'EOD',
In theory, this is a number encoding the model that the data are
intended for. In practice, it is always 0.
EOD
EPOCH
=>
<<'EOD',
This is the date and time of the epoch of the orbital data. Because of
the desire to be able to query the data, the fractional-second portion
of the epoch is in EPOCH_MICROSECONDS.
EOD
EPOCH_MICROSECONDS
=>
<<'EOD',
This is the fractional-second portion of the epoch. To get the true
epoch of the data, divide this by one million and add it to the EPOCH.
EOD
FILE
=>
<<'EOD',
This is, more or less, the transaction number of the most recent Space
Track update that contained this data. It can be used for incremental
updates by saving the FILE from the last download and then selecting
only data with a greater FILE.
EOD
INCLINATION
=>
<<'EOD',
This is the inclination of the body's orbit in degrees.
EOD
INTLDES
=>
<<'EOD',
This is the international launch designator. It is made up of the last
two digits of the Gregorian year (with leading zeroes), a three-digit
launch number in the year (with leading zeroes), and a launch piece
which consists of one or more upper-case alphabetic characters, with the
payload being 'A'. For example, the Zarya module of the International
Space Station is 98067A. This is different from the INTLDES in class
satcat.
EOD
LAUNCH
=>
<<'EOD',
This is the date the body was launched.
EOD
LAUNCH_NUM
=>
<<'EOD',
This is the launch number in the year.
EOD
LAUNCH_PIECE
=>
<<'EOD',
This is the launch piece.
EOD
LAUNCH_SITE
=>
<<'EOD',
This is the name of a launch site.
EOD
LAUNCH_YEAR
=>
<<'EOD',
This is the Gregorian year the body was launched.
EOD
MEAN_ANOMALY
=>
<<'EOD',
This is the mean anomaly of the body's orbit, in degrees.
EOD
MEAN_MOTION
=>
<<'EOD',
This is the mean motion of the body, in revolutions per day.
EOD
MEAN_MOTION_DOT
=>
<<'EOD',
This is the first time derivative of the mean motion (i.e. the
acceleration), in revolutions per day squared. Also known as the
Ballistic Coefficient.
EOD
MEAN_MOTION_DDOT
=>
<<'EOD',
This is the second time derivative of the mean motion, in revolutions
per day cubed.
EOD
NORAD_CAT_ID
=>
<<'EOD',
This is the OID, or NORAD catalog ID. Note that there are no leading
zeroes.
EOD
OBJECT_ID
=>
<<'EOD',
This is the international launch designator. It is made up of a numeric
four-digit Gregorian year, a dash, a three-digit launch number in the
year (with leading zeroes), and a launch piece which consists of one or
more upper-case alphabetic characters, with the payload being 'A'. For
example, the Zarya module of the International Space Station is
1998-067A.
EOD
OBJECT_NAME
=>
<<'EOD',
This is the common name of the object.
EOD
OBJECT_NUMBER
=>
<<'EOD',
This is the OID, or NORAD catalog ID. Note that there are no leading
zeroes.
EOD
OBJECT_TYPE
=>
<<'EOD',
This is a computed value representing the general type of the body. It
can be 'DEBRIS', 'PAYLOAD', 'ROCKET BODY', 'TBA', 'UNKNOWN', or 'OTHER'.
EOD
ORBITAL_TBA
=>
<<'EOD', # boxscore
At a guess, number of objects on-orbit which are not yet classified.
EOD
PERIGEE
=>
<<'EOD',
This is the perigee of the body's orbit in kilometers above the Earth's
surface.
EOD
PERIOD
=>
<<'EOD',
This is the period of the body's orbit, in minutes.
EOD
RA_OF_ASC_NODE
=>
<<'EOD',
This is the right ascension of the ascending node of the body's orbit,
in degrees (not hours).
EOD
RCSSOURCE
=>
<<'EOD',
This is an abbreviation of the source for the radar cross-section data.
EOD
RCSVALUE
=>
<<'EOD',
This is the radar cross-section of the body, in square meters. This is
now always carried as 0.
EOD
RCS_SIZE
=>
<<'EOD',
This is a qualitative statement of the size of the RCS. Observed values
are 'SMALL', 'MEDIUM', 'LARGE', and null.
EOD
REV_AT_EPOCH
=>
<<'EOD',
This is the number of revolutions the body has made at the epoch time.
In practice, this seems to be a whole-number value.
EOD
SEMIMAJOR_AXIS
=>
<<'EOD',
This is the semimajor axis of the orbit, in kilometers.
EOD
SITE
=>
<<'EOD',
This is an abbreviation for the site from which the body was launched.
EOD
SITE_CODE
=>
<<'EOD',
This is an abbreviation for the site from which the body was launched.
EOD
TLE_LINE0
=>
<<'EOD',
This is the common name of the object, with a '0 ' prefixed, since it is
the zeroth line of the TLE.
EOD
TLE_LINE1
=>
<<'EOD',
This is the first line of the TLE data for this body's orbit, as
represented in a traditional TLE data set.
EOD
TLE_LINE2
=>
<<'EOD',
This is the second line of the TLE data for this body's orbit, as
represented in a traditional TLE data set.
EOD
},
boxscore
=> {
COUNTRY
=>
<<'EOD',
Owning country or agency.
EOD
COUNTRY_TOTAL
=>
<<'EOD',
Number of bodies launched.
EOD
DECAYED_DEBRIS_COUNT
=>
<<'EOD',
Number of debris bodies decayed.
EOD
DECAYED_PAYLOAD_COUNT
=>
<<'EOD',
Number of payloads decayed.
EOD
DECAYED_ROCKET_BODY_COUNT
=>
<<'EOD',
Number of rocket bodies decayed.
EOD
DECAYED_TOTAL_COUNT
=>
<<'EOD',
Number of bodies of all types decayed.
EOD
ORBITAL_DEBRIS_COUNT
=>
<<'EOD',
Number of debris bodies in orbit.
EOD
ORBITAL_PAYLOAD_COUNT
=>
<<'EOD',
Number of payloads in orbit.
EOD
ORBITAL_ROCKET_BODY_COUNT
=>
<<'EOD',
Number of rocket bodies in orbit.
EOD
ORBITAL_TOTAL_COUNT
=>
<<'EOD',
Number of bodies of all types in orbit.
EOD
SPADOC_CD
=>
<<'EOD',
Abbreviation of owning country or agency.
EOD
},
satcat
=> {
INTLDES
=>
<<'EOD',
This is the international launch designator. It is made up of a numeric
four-digit Gregorian year, a dash, a three-digit launch number in the
year (with leading zeroes), and a launch piece which consists of one or
more upper-case alphabetic characters, with the payload being 'A'. For
example, the Zarya module of the International Space Station is
1998-067A. The individual parts of the international launch designator
are available in the LAUNCH_YEAR, LAUNCH_NUM, and LAUNCH_PIECE fields.
EOD
SATNAME
=>
<<'EOD',
This is the common name of the satellite.
EOD
},
tle
=> {
DECAYED
=>
<<'EOD',
This is a flag which is set if the body has decaued. It is documented as
being 0 if not.
EOD
},
tle_latest
=> {
DECAYED
=>
<<'EOD',
This is a flag which is set if the body has decaued. It is documented as
being 0 if not.
EOD
ORDINAL
=>
<<'EOD',
This is the ordinal number of this data set for this OID. The number
increases with decreasing EPOCH, with the most-recent epoch being 1.
EOD
},
);
}