|
Astro::Coord::ECI::TLE - Compute satellite locations using NORAD orbit propagation models |
Astro::Coord::ECI::TLE - Compute satellite locations using NORAD orbit propagation models
my @sats = Astro::Coord::ECI::TLE->parse ($tle_data);
my $now = time ();
foreach my $tle (@sats) {
my @latlon = $tle->universal ($now)->geodetic ();
my @xyz = $tle->eci (); # For same time.
print $tle->get ('id'), "\t@latlon\t@xyx\n";
}
The acquisition of the orbital elements represented by $tle_data in the above example is left as an exercise for the student.
Hint: see http://www.space-track.org/, http://celestrak.com/, or the Astro::SpaceTrack manpage.
This module implements the NORAD orbital propagation models described
in their ``SPACETRACK REPORT NO. 3, Models for Propagation of NORAD
Element Sets.'' In other words, it turns the two- or three-line
element sets available from such places as http://www.space-track.org/
or http://celestrak.com/ into predictions of where the relevant
orbiting bodies will be. Additionally, the pass() method implements an
actual visibility prediction system.
The models implemented are:
SGP - fairly simple, only useful for near-earth bodies; SGP4 - more complex, only useful for near-earth bodies; SDP4 - corresponds to SGP4, but for deep-space bodies; SGP8 - more complex still, only for near-earth bodies; SDP8 - corresponds to SGP8, but for deep-space bodies.
There are also some meta-models, with the smarts to run either a near-earth model or the corresponding deep-space model depending on the body the object represents:
model - uses the preferred model (sgp4 or sdp4); model4 - runs sgp4 or sdp4; model8 = runs sgp8 or sdp8.
In addition, I have on at least one occasion wanted to turn off the automatic calculation of position when the time was set. That is accomplished with this model:
null - does nothing.
The models do not return the coordinates directly, they simply set the coordinates represented by the object (by virtue of being a subclass of Astro::Coord::ECI) and return the object itself. You can then call the appropriate inherited method to get the coordinates of the body in whatever coordinate system is convenient. For example, to find the latitude, longitude, and altitude of a body at a given time, you do
my ($lat, $long, $alt) = $body->model ($time)->geodetic;
Or, assuming the model attribute is set the way you want it, by
my ($lat, $long, $alt) = $body->geodetic ($time);
It is also possible to run the desired model (as specified by the model attribute) simply by setting the time represented by the object.
At the moment, the recommended model to use is either SGP4 or SDP4, depending on whether the orbital elements are for a near-earth or deep-space body. For the purpose of these models, any body with a period of at least 225 minutes is considered to be a deep-space body.
The NORAD report claims accuracy of 5 or 6 places a day after the epoch of an element set for the original FORTRAN IV, which used (mostly) 8 place single-precision calculations. Perl typically uses many more places, but it does not follow that the models are correspondingly more accurate when implemented in Perl. My understanding is that in general (i.e. disregarding the characteristics of a particular implementation of the models involved) the total error of the predictions (including error in measuring the position of the satellite) runs from a few hundred meters to as much as a kilometer.
This module is a computer-assisted translation of the FORTRAN reference implementation in ``SPACETRACK REPORT NO. 3.'' That means, basically, that I ran the FORTRAN through a Perl script that handled the translation of the assignment statements into Perl, and then fixed up the logic by hand. Dominik Borkowski's SGP C-lib was used as a reference implementation for testing purposes, because I didn't have a Pascal compiler, and I have yet to get any model but SGP to run correctly under g77.
The following methods should be considered public:
new()Any arguments get passed to the set() method.
It is both anticipated and recommended that you use the parse()
method instead of this method to create an object, since the models
currently have no code to guard against incomplete data.
rebless() and should not be called by the user.
At this level it does nothing.
status() method and 'illum' attributes, and ultimately of
the rebless() method. It is intended to be used by subclasses to
register short names for themselves upon initialization, though of
course you can call it yourself as well.
For example, this class calls
__PACKAGE__->alias (tle => __PACKAGE__);
You can register more than one alias in a single call. Aliases can be deleted by assigning them a false value (e.g. '' or undef).
If called without arguments, it returns the current aliases.
You can actually call this as a normal method, but it still behaves like a static method.
At this level it does nothing.
ds50($time)It can also be called as a ``static'' method, i.e. as Astro::Coord::ECI::TLE->ds50 ($time), but in this case the time may not be defaulted, and no attempt has been made to make this a pretty error.
get('attribute')set() method should handle the attribute.
Actually, in the spirit of UNIVERSAL::can, it returns a reference to the code if the model exists, and undef otherwise.
This is really for the benefit of Astro::Coord::ECI::TLE::Set, so it can select the correct member object before running the model.
model($time)The intent is that this method will use whatever model is currently preferred. If the preferred model changes, this method will use the new preferred model as soon as I:
- Find out about the change; - Can get the specifications for the new model; - Can find the time to code up the new model.
You need to call one of the Astro::Coord::ECI methods (e.g. geodetic () or equatorial ()) to retrieve the position you just calculated.
You need to call one of the Astro::Coord::ECI methods (e.g. geodetic () or equatorial ()) to retrieve the position you just calculated.
You need to call one of the Astro::Coord::ECI methods (e.g. geodetic () or equatorial ()) to retrieve the position you just calculated.
The input will be split into individual lines, and all blank lines and lines beginning with '#' will be eliminated. The remaining lines are assumed to represent two- or three-line element sets, in so-called external format. Internal format (denoted by a 'G' in column 79 of line 1 of the set, not counting the common name if any) is not supported, and the presence of such data will result in an exception being thrown.
All arguments except $station are optional, the defaults being
$start = time() $end = $start + 7 days \@sky = []
The return is a list of passes, which may be empty. Each pass is represented by an anonymous hash containing the following keys:
{body} => Reference to body making pass;
{time} => Time of pass (culmination);
{events} => [the individual events of the pass].
The individual events are also anonymous hashes, with each hash containing the following keys:
{azimuth} => Azimuth of event in radians;
{body} => Reference to body making pass;
{appulse} => { # This is present only for PASS_EVENT_APPULSE;
{angle} => minimum separation in radians;
{body} => other body involved in appulse;
}
{elevation} => Elevation of event in radians;
{event} => Event code (PASS_EVENT_xxxx);
{illumination} => Illumination at time of event (PASS_EVENT_xxxx);
{range} => Distance to event in kilometers;
{station} => Reference to observing station;
{time} => Time of event;
Note that the time set in the various {body} and {station} objects is not guaranteed to be anything in particular. Specifically, it is almost certainly not the time of the event.
The events are coded by the following manifest constants:
PASS_EVENT_NONE => dualvar (0, ''); PASS_EVENT_SHADOWED => dualvar (1, 'shdw'); PASS_EVENT_LIT => dualvar (2, 'lit'); PASS_EVENT_DAY => dualvar (3, 'day'); PASS_EVENT_RISE => dualvar (4, 'rise'); PASS_EVENT_MAX => dualvar (5, 'max'); PASS_EVENT_SET => dualvar (6, 'set'); PASS_EVENT_APPULSE => dualvar (7, 'apls');
The dualvar function comes from Scalar::Util, and generates values which are numeric in numeric context and strings in string context. If Scalar::Util cannot be loaded the numeric values are returned.
These manifest constants can be imported using the individual names, or the tags ':constant' or ':all'. They can also be accessed as methods using (e.g.) $tle->PASS_EVENT_LIT, or as static methods using (e.g.) Astro::Coord::ECI::TLE->PASS_EVENT_LIT.
Illumination is represented by one of PASS_EVENT_SHADOWED, PASS_EVENT_LIT, or PASS_EVENT_DAY. The first two are calculated based on whether the illuminating body (i.e. the body specified by the 'illum' attribute) is above the horizon; the third is based on whether the Sun is higher than specified by the 'twilight' attribute, and trumps the other two (i.e. if it's day it doesn't matter whether the satellite is illuminated).
Time resolution of the events is typically to the nearest second, except for appulses, which need to be calculated more closely to detect transits. The time reported for the event is the time after the event occurred. For example, the time reported for rise is the earliest time the body is found above the horizon, and the time reported for set is the earliest time the body is found below the horizon.
The operation of this method is affected by the following attributes, in addition to its arguments and the orbital elements associated with the object:
* appulse # Maximum appulse to report * geometric # Use geometric horizon for pass rise/set * horizon # Effective horizon * interval # Interval for pass() positions, if positive * illum # Source of illumination. * limb # Whether lit when upper limb above horizon * twilight # Distance of illuminator below horizon * visible # Pass() reports only illuminated passes
before_reblessing() method is called.
After reblessing, the after_reblessing() method is called with the
\%possible_attributes hash reference as argument.
It is possible to omit the $class argument if the \%possible_attributes argument contains the keys {class} or {type}, taken in that order. If the $class argument is omitted and the \%possible_attributes hash does not have the requisite keys, the $tle object is unmodified.
It is also possible to omit both arguments, in which case the object will be reblessed according to the content of the internal status table.
For convenience, you can pass an alias instead of the full class name. The following aliases are recognized:
iridium => 'Astro::Coord::ECI::TLE::Iridium' tle => 'Astro::Coord::ECI::TLE'
Other aliases may be defined with the alias() static method.
Note that this method returns the original object (possibly reblessed). It does not under any circumstances manufacture another object.
Because this is a subclass of Astro::Coord::ECI, any attributes of that class can also be set.
parse() method to determine which subclass (if any) to bless the
created object into. The first argument determines what is done to the
status table; subsequent arguments depend on the first argument. Valid
commands and arguments are:
status (add => $id, $type => $status, $name, $comment) adds an item to the status table or modifies an existing item. The $id is the NORAD ID of the body. The only currently-supported $type is 'Astro::Coord::ECI::TLE::Iridium', but any alias to this will also work (see alias(); 'iridium' is defined by default). The $status is 0, 1, or 2, representing in-service, spare, or failed respectively. The strings '+' or '' will be interpreted as 0, 'S', 's', or '?' as 1, and any other non-numeric string as 2. The $name and $comment arguments default to empty.
status ('clear') clears the status table.
status (clear => 'type') clears all entries of the given type in the status table. For supported types, see the discussion of 'add', above.
status (drop => $id) removes the given NORAD ID from the status table.
status ('show') returns a list of list references, representing the 'add' commands which would be used to regenerate the status table.
sgp($time)The result is the original object reference. You need to call one of the Astro::Coord::ECI methods (e.g. geodetic () or equatorial ()) to retrieve the position you just calculated.
``Spacetrack Report Number 3'' (see ``Acknowledgments'') says that this model can be used for either near-earth or deep-space orbits, but the reference implementation they provide dies on an attempt to use this model for a deep-space object, and I have followed the reference implementation.
sgp4($time)The result is the original object reference. See the DESCRIPTION heading above for how to retrieve the coordinates you just calculated.
``Spacetrack Report Number 3'' (see ``Acknowledgments'') says that this model can be used only for near-earth orbits.
sdp4($time)The result is the original object reference. You need to call one of the Astro::Coord::ECI methods (e.g. geodetic () or equatorial ()) to retrieve the position you just calculated.
``Spacetrack Report Number 3'' (see ``Acknowledgments'') says that this model can be used only for deep-space orbits.
sgp8($time)The result is the original object reference. You need to call one of the Astro::Coord::ECI methods (e.g. geodetic () or equatorial ()) to retrieve the position you just calculated.
``Spacetrack Report Number 3'' (see ``Acknowledgments'') says that this model can be used only for near-earth orbits.
sdp8($time)The result is the original object reference. You need to call one of the Astro::Coord::ECI methods (e.g. geodetic () or equatorial ()) to retrieve the position you just calculated.
``Spacetrack Report Number 3'' (see ``Acknowledgments'') says that this model can be used only for near-earth orbits.
Although there is no reason this method can not be called directly, it exists to take advantage of the hook in the Astro::Coord::ECI object, to allow the position of the body to be computed when the time of the object is set.
This class has the following additional public attributes. The description gives the data type. It may also give one of the following if applicable:
parse - if the attribute is set by the parse() method;
read-only - if the attribute is read-only;
static - if the attribute may be set on the class as well as an object.
Note that the orbital elements provided by NORAD are tweaked for use by the models implemented by this class. If you plug them in to the same-named parameters of other models, your mileage may vary significantly.
pass() method, in radians.
The default is equivalent to 10 degrees.
pass() method will go back before
the epoch of the data. If false, the pass() method will silently adjust
its start time forward -- or not so silently if this puts the start time
after the end time.
The default is 1 (i.e. true).
pass() method whether to calculate rise and set relative
to the geometric horizon (if true) or the horizon attribute (if
false)
The default is 0 (i.e. false).
alias()
thereof, or you may specify an object of the appropriate class. When you
access this attribute, you get an object.
In addition to the full class names, 'sun' and 'moon' are set up as
aliases for Astro::Coord::ECI::Sun and Astro::Coord::ECI::Moon
respectively. Other aliases can be set up using the alias() mechanism.
The value 'sun' (or something equivalent) is probably the only useful
value, but I know people have looked into Iridium 'Moon flares', so I
exposed the attribute.
The default is 'sun'.
pass() method return
positions at this interval (in seconds) across the sky. The associated
event code of these will be PASS_EVENT_NONE. If zero or negative, pass()
will only return times when some event of interest occurs.
The default is 0.
payload(s) getting the
first letters, and spent boosters, debris, etc getting the rest.
pass() method how to compute illumination
of the body. If true, it is computed based on the upper limb of the
source of illumination; if false, it is based on the center.
The default is 1 (i.e. true).
time_set() method is called, or a
false value if no model is to be run. Legal model names are: model,
model4, model8, null, sgp, sgp4, sgp8, sdp4, and sdp8.
The default is 'model'. Setting the value on the class changes the default.
rebless() method is allowed to rebless
this object. If false, the object will not be reblessed when its
id changes.
Note that if this attribute is false, setting it true will cause the object to be reblessed.
The default is true (i.e. 1).
parse() method to
generate this object. If the object was not created by the parse()
method, this attribute will be empty.
pass() method whether to report only passes
which are illuminated (if true) or all passes (if false).
The default is 1 (i.e. true).
The author wishes to acknowledge the following individuals.
Dominik Brodowski (http://www.brodo.de/), whose SGP C-lib (available at http://www.brodo.de/space/sgp/) provided a reference implementation that I could easily run, and pick apart to help get my own code working. Dominik based his work on Dr. Kelso's Pascal implementation.
Felix R. Hoots and Ronald L. Roehric, the authors of ``SPACETRACK REPORT NO. 3 - Models for Propagation of NORAD Element Sets,'' which provided the basis for the Astro::Coord::ECI::TLE module.
Dr. T. S. Kelso, who compiled this report and made it available at http://celestrak.com/NORAD/documentation/spacetrk.pdf. Dr. Kelso's Two-Line Element Set Format FAQ (http://celestrak.com/columns/v04n03/) was also extremely helpful, as was his discussion of the coordinate system used (http://celestrak.com/columns/v02n01/) and (indirectly) his Pascal implementation of these models.
I am aware of no other modules that perform calculations with NORAD orbital element sets. The Astro-Coords package by Tim Jenness provides calculations using orbital elements, but the NORAD elements are tweaked for use by the models implemented in this package.
Thomas R. Wyant, III (wyant at cpan dot org)
Copyright 2005, 2006, 2007 by Thomas R. Wyant, III (wyant at cpan dot org). All rights reserved.
This module is free software; you can use it, redistribute it and/or modify it under the same terms as Perl itself. Please see http://perldoc.perl.org/index-licence.html for the current licenses.
This software is provided without any warranty of any kind, express or implied. The author will not be liable for any damages of any sort relating in any way to this software.
|
Astro::Coord::ECI::TLE - Compute satellite locations using NORAD orbit propagation models |