Astro-satpass
view release on metacpan or search on metacpan
qw{ latitude=f longitude=f height=f horizon=f twilight=f more+
time_zone|time-zone|zone=s pretty! },
help => sub { pod2usage( { -verbose => 2 } ) },
) or pod2usage( { -verbose => 0 } );
my $now = time; # The time the script was run.
my $start_time; # The start time for the prediction
if ( my $time = shift @ARGV ) {
require Date::Manip;
$start_time = Date::Manip::UnixDate( $time, '%s' )
or die "Invalid start time $time\n";
} else {
$start_time = $now;
}
my $days = shift @ARGV || 7; # Number of days to predict
# Retrieve the TLE data from Celestrak.
my $getter = Astro::SpaceTrack->new( direct => 1, with_name => 1 );
my $resp = $getter->celestrak( 'stations' );
$resp->is_success()
or die 'Failed to retrieve TLE data: ', $resp->status_line();
# Parse the TLE data, eliminating any Progress or Soyuz modules, or
# whatever else may be in the same data set.
my ( $iss ) = grep { 25544 == $_->get( 'id' ) }
Astro::Coord::ECI::TLE->parse( $resp->content() );
# Set up our location
my $sta = Astro::Coord::ECI->new(
)->geodetic(
deg2rad( $opt{latitude} ),
deg2rad( $opt{longitude} ),
$opt{height} / 1000,
);
# Configure the TLE object as desired for the pass prediction, based on
# the option values.
$iss->set(
horizon => deg2rad( $opt{horizon} ),
pass_variant => ( $opt{more} ?
PASS_VARIANT_NONE :
PASS_VARIANT_VISIBLE_EVENTS | PASS_VARIANT_FAKE_MAX |
PASS_VARIANT_START_END
),
station => $sta,
twilight => deg2rad( $opt{twilight} ),
visible => $opt{more} < 2,
);
# Compute the passes.
my @passes = $iss->pass( $start_time, $start_time + $days * 86400 );
# Put the output into UTF-8 mode, since that is what we intend to use.
# This gets eval'ed to hide it if we're using Perl 5.6.
$] ge '5.008'
and eval "binmode STDOUT, ':encoding(utf-8)'";
# Now fire up the XML generator.
my $xw = XML::Writer->new(
DATA_MODE => $opt{pretty},
DATA_INDENT => 4,
ENCODING => 'utf-8',
);
# Start the XML.
$xw->xmlDecl(); # The declaration
$xw->startTag( 'transits', # The document tag
latitude => $opt{latitude},
longitude => $opt{longitude},
altitude => $opt{height},
timezone => $opt{time_zone},
days => $days,
gmtnow => DateTime->from_epoch(
epoch => $now,
time_zone => 'GMT',
)->strftime( '%Y-%m-%dT%H:%M:%S' ),
object => $iss->get( 'name' ),
oid => $iss->get( 'id' ),
);
# For each pass,
my $pass_number = 1;
foreach my $pass ( @passes ) {
# Emit the start tag for the pass
$xw->startTag( 'pass',
number => $pass_number++,
date => DateTime->from_epoch(
epoch => $pass->{events}[0]{time},
time_zone => $opt{time_zone},
)->strftime( '%Y-%m-%d' ),
);
# For each event in the pass
foreach my $event ( @{ $pass->{events} } ) {
# Emit a tag representing the event itself
$xw->startTag( $event->{event} );
# Emit the time of the event
$xw->dataElement( time => DateTime->from_epoch(
epoch => $event->{time},
time_zone => $opt{time_zone},
)->strftime( '%H:%M:%S' ),
);
# Emit the elevation of the event
( run in 1.867 second using v1.01-cache-2.11-cpan-b16cb0d3907 )