3 ########################################################################
4 # Convert DAFIFT ARPT/ILS.TXT to FlightGear format.
5 ########################################################################
9 my($faa_ils_file) = shift(@ARGV);
10 my($dafift_arpt_file) = shift(@ARGV);
11 my($dafift_ils_file) = shift(@ARGV);
12 my($fgfs_ils_file) = shift(@ARGV);
15 "<faa_ils_file> <dafift_arpt_file> <dafift_ils_file> <fgfs_ils_file>\n"
16 if !defined($faa_ils_file) || !defined($dafift_arpt_file)
17 || !defined($dafift_ils_file) || !defined($fgfs_ils_file);
23 &load_dafift( $dafift_arpt_file, $dafift_ils_file );
24 &load_faa( $faa_ils_file );
25 &load_fgfs( $faa_ils_file );
31 ########################################################################
33 ########################################################################
38 open( FAA_ILS, "<$file" ) || die "Cannot open FAA data: $file\n";
40 <FAA_ILS>; # skip header line
45 my ( $rec_type, $faa_id, $rwy, $type, $faa_date,
46 $faa_apt_name, $faa_city, $faa_st, $faa_state,
47 $faa_region, $id, $faa_len, $faa_wid, $faa_cat,
48 $faa_owner, $faa_operator, $faa_bearing, $faa_magvar,
49 $loc_type, $loc_id, $loc_freq, $faa_loc_latd,
50 $faa_loc_lats, $faa_loc_lond, $faa_loc_lons, $loc_width,
51 $faa_stop_dist, $faa_app_dist, $faa_gs_type, $gs_angle,
52 $faa_gs_freq, $faa_gs_latd, $faa_gs_lats, $faa_gs_lond,
53 $faa_gs_lons, $faa_gs_dist, $gs_elev, $faa_im_type,
54 $faa_im_latd, $faa_im_lats, $faa_im_lond, $faa_im_lons,
55 $faa_im_dist, $faa_mm_type, $faa_mm_id, $faa_mm_name,
56 $faa_mm_freq, $faa_mm_latd, $faa_mm_lats, $faa_mm_lond,
57 $faa_mm_lons, $faa_mm_dist, $faa_om_type, $faa_om_id,
58 $faa_om_name, $faa_om_freq, $faa_om_latd, $faa_om_lats,
59 $faa_om_lond, $faa_om_lons, $faa_om_dist,
60 $faa_om_backcourse, $faa_dme_channel, $faa_dme_latd,
61 $faa_dme_lats, $faa_dme_lond, $faa_dme_lons, $faa_dme_app_dist,
62 $faa_dme_stop_dist, $blank)
64 m/^(.{4})(.{11})(.{3})(.{10})(.{10})(.{42})(.{26})(.{2})(.{20})(.{3})(.{4})(.{5})(.{4})(.{9})(.{50})(.{50})(.{3})(.{3})(.{15})(.{5})(.{6})(.{14})(.{11})(.{14})(.{11})(.{5})(.{5})(.{6})(.{15})(.{4})(.{6})(.{14})(.{11})(.{14})(.{11})(.{6})(.{7})(.{15})(.{14})(.{11})(.{14})(.{11})(.{6})(.{15})(.{2})(.{5})(.{3})(.{14})(.{11})(.{14})(.{11})(.{6})(.{15})(.{2})(.{5})(.{3})(.{14})(.{11})(.{14})(.{11})(.{6})(.{9})(.{4})(.{14})(.{11})(.{14})(.{11})(.{6})(.{5})(.{34})/;
67 my( $loc_hdg ) = $faa_bearing + make_dmagvar($faa_magvar);
68 my( $loc_lat ) = make_dcoord($faa_loc_lats) / 3600.0;
69 my( $loc_lon ) = make_dcoord($faa_loc_lons) / 3600.0;
70 my( $gs_lat ) = make_dcoord($faa_gs_lats) / 3600.0;
71 my( $gs_lon ) = make_dcoord($faa_gs_lons) / 3600.0;
72 my( $im_lat ) = make_dcoord($faa_im_lats) / 3600.0;
73 my( $im_lon ) = make_dcoord($faa_im_lons) / 3600.0;
74 my( $mm_lat ) = make_dcoord($faa_mm_lats) / 3600.0;
75 my( $mm_lon ) = make_dcoord($faa_mm_lons) / 3600.0;
76 my( $om_lat ) = make_dcoord($faa_om_lats) / 3600.0;
77 my( $om_lon ) = make_dcoord($faa_om_lons) / 3600.0;
78 my( $dme_lat ) = make_dcoord($faa_dme_lats) / 3600.0;
79 my( $dme_lon ) = make_dcoord($faa_dme_lons) / 3600.0;
81 if ( $rec_type eq "ILS1" ) {
82 if ( $ILS{$id . $rwy} eq "" ) {
83 print "FAA adding: $id - $rwy\n";
84 add_record( $id, $rwy, $loc_freq, $loc_id, $loc_hdg, $loc_lat,
85 $loc_lon, $gs_elev, $gs_angle, $gs_lat, $gs_lon,
86 $dme_lat, $dme_lon, $om_lat, $om_lon, $mm_lat,
87 $mm_lon, $im_lat, $im_lon );
94 ########################################################################
96 ########################################################################
99 my( $arpt_file ) = shift;
100 my( $ils_file ) = shift;
104 my( $id, $rwy, $type );
105 my( $has_dme, $has_gs, $has_loc, $has_im, $has_mm, $has_om );
106 my( $dme_lon, $dme_lat, $dme_elev, $dme_bias );
107 my( $gs_lon, $gs_lat, $gs_elev, $gs_angle );
108 my( $loc_type, $loc_lon, $loc_lat, $loc_elev, $loc_freq, $loc_hdg,
109 $loc_width, $loc_id );
110 my( $im_lon, $im_lat, $mm_lon, $mm_lat, $om_lon, $om_lat );
112 # load airport file so we can lookup ICAO from internal ID
114 open( ARPT, "<$arpt_file" ) || die "Cannot open DAFIFT: $arpt_file\n";
116 <ARPT>; # skip header line
120 my(@F) = split(/\t/);
122 if ( length($icao) < 3 ) {
123 if ( length( $F[4] ) >= 3 ) {
129 $Airports{$F[0]} = $icao;
130 # print "$F[0] - $icao\n";
133 # Load the DAFIFT ils file
135 my( $last_id, $last_rwy ) = ("", "");
137 open( DAFIFT_ILS, "<$ils_file" ) || die "Cannot open DAFIFT: $ils_file\n";
139 <DAFIFT_ILS>; # skip header line
141 while ( <DAFIFT_ILS> ) {
147 if ( $last_id ne "" && ($last_id ne $id || $last_rwy ne $rwy) ) {
148 # just hist the start of the next record, dump the current data
151 ( $gs_elev, $gs_angle, $gs_lat, $gs_lon ) = ( 0, 0, 0, 0 );
154 ( $dme_lat, $dme_lon ) = ( 0, 0 );
157 ( $om_lat, $om_lon ) = ( 0, 0 );
160 ( $mm_lat, $mm_lon ) = ( 0, 0 );
163 ( $im_lat, $im_lon ) = ( 0, 0 );
165 if ( $ILS{$Airports{$last_id} . $last_rwy} eq "" ) {
166 print "DAFIFT adding: $Airports{$last_id} - $last_rwy\n";
167 add_record( $Airports{$last_id}, $last_rwy, $loc_freq,
168 $loc_id, $loc_hdg, $loc_lat, $loc_lon,
169 $gs_elev, $gs_angle, $gs_lat, $gs_lon,
170 $dme_lat, $dme_lon, $om_lat, $om_lon, $mm_lat,
171 $mm_lon, $im_lat, $im_lon );
183 if ( $type eq "D" ) {
186 $dme_lon = make_dcoord( $F[16] );
187 $dme_lat = make_dcoord( $F[14] );
189 if ( $dme_elev !~ m/\d/ ) {
195 # print "$id DME $dme_lon $dme_lat $dme_elev $dme_bias\n";
196 } elsif ( $type eq "G" ) {
199 $gs_lon = make_dcoord( $F[16] );
200 $gs_lat = make_dcoord( $F[14] );
202 if ( $gs_elev !~ m/\d/ ) {
208 # print "$id GS $gs_lon $gs_lat $gs_elev $gs_angle\n";
209 } elsif ( $type eq "Z" ) {
212 $loc_lon = make_dcoord( $F[16] );
213 $loc_lat = make_dcoord( $F[14] );
215 if ( $loc_elev !~ m/\d/ ) {
220 ($loc_freq) = $F[5] =~ m/(\d\d\d\d\d\d)/;
222 my( $magvar ) = make_dmagvar( $F[22] );
223 # print "mag var = $F[22] (" . $magvar . ")\n";
224 $loc_hdg = $F[24] + make_dmagvar( $F[22] );
227 # print "$id LOC $loc_lon $loc_lat $loc_elev $loc_freq $loc_hdg $loc_width\n";
228 } elsif ( $type eq "I" ) {
231 $im_lon = make_dcoord( $F[16] );
232 $im_lat = make_dcoord( $F[14] );
233 # print "$id IM $im_lon $im_lat\n";
234 } elsif ( $type eq "M" ) {
235 # Middle marker entry
237 $mm_lon = make_dcoord( $F[16] );
238 $mm_lat = make_dcoord( $F[14] );
239 # print "$id MM $mm_lon $mm_lat\n";
240 } elsif ( $type eq "O" ) {
243 $om_lon = make_dcoord( $F[16] );
244 $om_lat = make_dcoord( $F[14] );
245 # print "$id OM $om_lon $om_lat\n";
250 # printf("%-5s %10.6f %11.6f\n", $F[0], $F[14], $F[16]);
254 ( $gs_elev, $gs_angle, $gs_lat, $gs_lon ) = ( 0, 0, 0, 0 );
257 ( $dme_lat, $dme_lon ) = ( 0, 0 );
260 ( $om_lat, $om_lon ) = ( 0, 0 );
263 ( $mm_lat, $mm_lon ) = ( 0, 0 );
266 ( $im_lat, $im_lon ) = ( 0, 0 );
268 if ( $ILS{$Airports{$last_id} . $last_rwy} eq "" ) {
269 print "DAFIFT adding (last): $Airports{$last_id} - $last_rwy\n";
270 add_record( $Airports{$last_id}, $last_rwy, $loc_freq,
271 $loc_id, $loc_hdg, $loc_lat, $loc_lon,
272 $gs_elev, $gs_angle, $gs_lat, $gs_lon,
273 $dme_lat, $dme_lon, $om_lat, $om_lon, $mm_lat,
274 $mm_lon, $im_lat, $im_lon );
279 ########################################################################
280 # Process FlightGear ILS data
281 ########################################################################
284 my( $ils_file ) = shift;
287 open( FGILS, "zcat $ils_file|" ) || die "Cannot open FGFS: $ils_file\n";
289 <FGILS>; # skip header line
293 if ( ! m/\[End\]/ && length($_) > 1 ) {
295 my( $type_code, $type_name, $icao, $rwy, $loc_freq, $loc_id,
296 $loc_hdg, $loc_lat, $loc_lon, $gs_elev, $gs_angle, $gs_lat,
297 $gs_lon, $dme_lat, $dme_lon, $om_lat, $om_lon, $mm_lat, $mm_lon,
298 $im_lat, $im_lon ) = split(/\s+/);
299 if ( $ILS{$icao . $rwy} eq "" ) {
300 print "FGFS adding: $icao $rwy\n";
301 $ILS{$icao . $rwy} = $_;
308 ########################################################################
309 # Write out the accumulated combined result
310 ########################################################################
313 # dump out the final results
314 print "// FlightGear ILS data, generated from DAFIFT ARPT/ILS.TXT\n";
316 foreach $key ( sort (keys %ILS) ) {
317 print "$ILS{$key}\n";
323 ########################################################################
325 ########################################################################
328 # add a record to the master list
331 my( $apt_id ) = shift;
333 my( $loc_freq ) = shift;
334 my( $loc_id ) = shift;
335 my( $loc_hdg ) = shift;
336 my( $loc_lat ) = shift;
337 my( $loc_lon ) = shift;
338 my( $gs_elev ) = shift;
339 my( $gs_angle ) = shift;
340 my( $gs_lat ) = shift;
341 my( $gs_lon ) = shift;
342 my( $dme_lat ) = shift;
343 my( $dme_lon ) = shift;
344 my( $om_lat ) = shift;
345 my( $om_lon ) = shift;
346 my( $mm_lat ) = shift;
347 my( $mm_lon ) = shift;
348 my( $im_lat ) = shift;
349 my( $im_lon ) = shift;
352 $record = sprintf( "I ILS %-4s %-3s %06.2f %-4s %06.2f %10.6f %11.6f ",
354 $loc_freq, $loc_id, $loc_hdg, $loc_lat, $loc_lon );
355 $record .= sprintf( "%5d %5.2f %10.6f %11.6f ",
356 $gs_elev, $gs_angle, $gs_lat, $gs_lon );
357 $record .= sprintf( "%10.6f %11.6f ", $dme_lat, $dme_lon );
358 $record .= sprintf( "%10.6f %11.6f ", $om_lat, $om_lon );
359 $record .= sprintf( "%10.6f %11.6f ", $mm_lat, $mm_lon );
360 $record .= sprintf( "%10.6f %11.6f ", $im_lat, $im_lon );
362 if ( $ILS{$apt_id . $rwy} eq "" ) {
363 print "Adding (common): $apt_id - $rwy\n";
364 $ILS{$apt_id . $rwy} = $record;
369 # convert a lon/lat coordinate in various formats to signed decimal
373 my( $dir, $deg, $min, $sec );
375 if ( $coord =~ m/^[WE]/ ) {
376 ( $dir, $deg, $min, $sec )
377 = $coord =~ m/^([EW])(\d\d\d)(\d\d)(\d\d\d\d)/;
378 $value = $deg + $min/60.0 + ($sec/100)/3600.0;
382 } elsif ( $coord =~ m/^[NS]/ ) {
383 ( $dir, $deg, $min, $sec )
384 = $coord =~ m/^([NS])(\d\d)(\d\d)(\d\d\d\d)/;
385 $value = $deg + $min/60.0 + ($sec/100)/3600.0;
389 } elsif ( $coord =~ m/[EW]$/ ) {
390 ($value, $dir) = $coord =~ m/(\d{6}\.\d{3})(.)/;
391 if ( $value eq "W" ) {
394 } elsif ( $coord =~ m/[NS]$/ ) {
395 ($value, $dir) = $coord =~ m/(\d{6}\.\d{3})(.)/;
396 if ( $value eq "S" ) {
400 # print "$dir $deg:$min:$sec = $value\n";
404 # convert a magnetic variation in various formats to signed decimal
407 my( $coord ) = shift;
409 if ( $coord =~ m/^[EW]/ ) {
410 my( $dir, $deg, $min, $date )
411 = $coord =~ m/^([EW])(\d\d\d)(\d\d\d) (\d\d\d\d)/;
412 $value = $deg + ($min/10)/60.0;
416 } elsif ( $coord =~ m/[EW]$/ ) {
418 = $coord =~ m/^(\d\d)([EW])/;
424 # print "$dir $deg:$min = $value\n";