File Coverage

lib/GPS/SpaceTrack.pm
Criterion Covered Total %
statement 22 24 91.6
branch n/a
condition n/a
subroutine 8 8 100.0
pod n/a
total 30 32 93.7


line stmt bran cond sub pod time code
1             package GPS::SpaceTrack;
2              
3             =head1 NAME
4              
5             GPS::SpaceTrack - Package for calculating the position of GPS satellites
6              
7             =head1 SYNOPSIS
8              
9             use GPS::SpaceTrack;
10             my $obj=GPS::SpaceTrack->new(filename=>"gps.tle");
11             print join("\t", qw{Count PRN ELEV Azim SNR USED}), "\n";
12             foreach ($obj->getsatellitelist({lat=>38.870997, lon=>-77.05596})) {
13             print join("\t", $_->prn, $_->elev, $_->azim, $_->snr, $_->used), "\n";
14             }
15              
16             =head1 DESCRIPTION
17              
18             This package can calculates the location of the GPS satellite constellation given the position of the receiver and a time which can be in the future.
19              
20             =head1 CONVENTIONS
21              
22             Function naming convention is "format of the return" underscore "format of the parameters."
23              
24             =cut
25              
26 1     1   8354 use strict;
  1         2  
  1         44  
27 1     1   5 use vars qw($VERSION);
  1         1  
  1         123  
28             $VERSION = sprintf("%d.%02d", q{Revision: 0.11} =~ /(\d+)\.(\d+)/);
29 1     1   1617 use Astro::Coord::ECI;
  1         73211  
  1         44  
30 1     1   2917 use Astro::Coord::ECI::TLE;
  1         106285  
  1         85  
31 1     1   808 use Net::GPSD::Satellite;
  1         1871  
  1         29  
32 1     1   865 use Geo::Functions qw{deg_rad rad_deg};
  1         2171  
  1         103  
33 1     1   845 use Time::HiRes qw{time};
  1         1777  
  1         5  
34 1     1   1552 use GPS::PRN;
  0            
  0            
35             my $gpsprn=GPS::PRN->new;
36              
37             =head1 CONSTRUCTOR
38              
39             =head2 new
40              
41             The new() constructor passes paramaters to the filename() method.
42              
43             my $obj = GPS::SpaceTrack->new(filename=>$filename);
44              
45             =cut
46              
47             sub new {
48             my $this = shift();
49             my $class = ref($this) || $this;
50             my $self = {};
51             bless $self, $class;
52             $self->initialize(@_);
53             return $self;
54             }
55              
56             =head1 METHODS
57              
58             =cut
59              
60             sub initialize {
61             my $self=shift();
62             my $param={@_};
63             $self->filename($param->{'filename'});
64             }
65              
66             =head2 getsatellitelist
67              
68             The getsatellitelist() method returns a list of Net::GPSD::Satellite objects. The getsatellitelist() method is a wrapper around getsatellitelist_rad() for data formatted in degrees instead of radians.
69              
70             my $list=$obj->getsatellitelist({lat=>$lat, lon=>$lon, alt=>$hae, time=>$time}); #degrees, degrees, meters, seconds from epoch
71             my @list=$obj->getsatellitelist({lat=>$lat, lon=>$lon, alt=>$hae, time=>$time}); #degrees, degrees, meters, seconds from epoch
72              
73             =cut
74              
75             sub getsatellitelist {
76             my $self=shift();
77             my $point=shift(); die() unless ref($point) eq "HASH";
78             $point->{'lat'}=rad_deg($point->{'lat'}) if defined($point->{'lat'});
79             $point->{'lon'}=rad_deg($point->{'lon'}) if defined($point->{'lon'});
80             return $self->getsatellitelist_rad($point);
81             }
82              
83             =head2 getsatellitelist_rad
84              
85             The getsatellitelist_rad() method returns a list of Net::GPSD::Satellite objects. This method is basically a wrapper around Astro::Coord::ECI::TLE.
86              
87             my $list=$obj->getsatellitelist_rad({lat=>$lat, lon=>$lon, alt=>$hae, time=>$time}); #radians, radians, meters, seconds from epoch
88             my @list=$obj->getsatellitelist_rad({lat=>$lat, lon=>$lon, alt=>$hae, time=>$time}); #radians, radians, meters, seconds from epoch
89              
90             =cut
91              
92             sub getsatellitelist_rad {
93             my $self=shift();
94             my $point=shift();
95             my $gnd_lat_rad=defined($point->{'lat'}) ?
96             $point->{'lat'} : die('Error: Required {lat=>$lat}');
97             my $gnd_lon_rad=defined($point->{'lon'}) ?
98             $point->{'lon'} : die('Error: Required {lon=>$lon}');
99             my $gnd_hae_km=($point->{'alt'}||0)/1000;
100             my $time=$point->{'time'}||time();
101              
102             my $tle_data=$self->data;
103             my @satellite=Astro::Coord::ECI::TLE->parse($tle_data);
104             my @list=();
105             foreach my $tle (@satellite) {
106             my($sat_lat, $sat_lon, $sat_hae_km)= $tle->universal($time)->geodetic;
107             #my($x, $y, $z)=$tle->eci();
108             my $id=$tle->get('id');
109             #my $name=$tle->get('name');
110             my $sta=Astro::Coord::ECI->new(refraction=>1,
111             name=>'Station')->geodetic($gnd_lat_rad,
112             $gnd_lon_rad,
113             $gnd_hae_km);
114             my ($azm_rad, $elev_rad, $dist_km)=$sta->azel($tle->universal($time));
115             my $prn=$gpsprn->prn_oid($id);
116             my $elev=deg_rad($elev_rad);
117             my $azim=deg_rad($azm_rad);
118             my $snr=45 * sin($elev_rad > 0 ? $elev_rad : 0)**2; #rough calc
119             my $used=$snr > 10 ? 1 : 0; #rough estimate
120             if ($prn) {
121             push @list, Net::GPSD::Satellite->new($prn, $elev, $azim, $snr, $used);
122             }
123             }
124             @list=sort {$b->elev<=>$a->elev} @list;
125             return wantarray ? @list : \@list;
126             }
127              
128             =head2 filename
129              
130             Method to get or set the filename of the TLE data.
131              
132             my $filename=$obj->filename;
133             my $filename=$obj->filename(filename=>$filename);
134              
135             =cut
136              
137             sub filename {
138             my $self=shift();
139             if (@_) {
140             my $filename=shift();
141             if (-r $filename) {
142             $self->{'filename'} = $filename;
143             } else {
144             if (-e $filename) {
145             die("Error: $filename does not exist");
146             } else {
147             die("Error: $filename is not readable");
148             }
149             }
150             }
151             undef($self->{'data'});
152             return $self->{'filename'};
153             }
154              
155             sub data {
156             my $self=shift();
157             unless (defined($self->{'data'})) {
158             my $filename=$self->filename;
159             open(DATA, $filename) || die("Error: Cannot open $filename");
160             {
161             local $/=undef();
162             $self->{'data'}=;
163             }
164             close(DATA);
165             }
166             return $self->{'data'};
167             }
168              
169             1;
170              
171             __END__