#!/usr/bin/perl # 2019-08-20 - Review # 08/04/2016 - For short, less than 100 km, need a set of wpts to follow # 12/11/2014 - Like the xg output, add refueling legs to the # 20141003 - Load ALL airports - for a light plane vfr, need to also supply re-fueling airport # 20141001 - Add a log file # 20140930 from : http://seb.marque.free.fr/fichiers/scripts/perl/plandevol # l'option -w a été enlevée pour éviter l'affichage des warnings inutiles décrits ci-dessous: # Use of implicit split to @_ is deprecated at fgfs/plandevol-dev line ... # main::construction_route() called too early to check prototype at fgfs/plandevol-dev line ... ####################################################################################################################################################### ## *********************************************** ## ***** TRES IMPORTANT ***** VERY IMPORTANT ***** ## *********************************************** ## ## CE SCRIPT NE PROPOSE PAS UNE SOLUTION DE VOL FIABLE POUR LA CONSTRUCTION D'UN PLAN DE VOL RÉEL!!!!!!!! ## IL N'EST QU'UNE SOLUTION POUR PROPOSER UN TRAJET DE _LOISIR_ AVEC FLIGHTGEAR FS ET NE GARANTIT EN AUCUN CAS LA FIABILITÉ DES INFORMATIONS ## QU'IL DÉLIVRE ## ####################################################################################################################################################### ###################################################################################################################################################### ## ## script écrit par seb marque, paris, france ## ## plandevol, version 0.5.9 qui s'approche dangereusement de la version 0.6.0 ## --help pour une aide sur l'utilisation du script ## ## script placé sous licence GPL par Sébastien MARQUE ## texte complet disponible sur http://www.gnu.org/licenses/gpl.txt ## # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ####################################################################################################################################################### ## ## les fonctions fg_connect, set_prop, get_prop et send proviennent du script telnet.pl trouvé dans le code source de fgfs 0.98 (de Curtis L. Olson, ## avec "courtesy" pour Melchior Franz. ## ## les fonctions round, ll2xyz, xyz2ll, llll2dir (dont provient llll2dir_), distance (dont provient distance_) et coord_dist_sqr proviennent du script ## de Melchior Franz "freq" trouvé sur http://members.aon.at/mfranz/freq, en attente de leur remplacement éventuel par les fonctions de Math::Trig ## ###################################################################################################################################################### ## ## bugs connus: si une balise est situé dans l'enceinte du point d'arrivée elle n'est pas détectée... c'est dommage ## fixé la compatibilité avec les différentes versions de nav.dat.gz ## ## version 0.6 -> réglage auto des instruments de vol ## -> intégration des fix dans le plan de vol si nécessaire ## -> gestion des sid/star ## -> nettoyage du code ## ###################################################################################################################################################### use strict; use POSIX qw(ceil floor); use Getopt::Long; # pour récupérer les options en ligne de commande use IO::Socket; # pour la connexion telnet avec FlightGear use File::Basename; # split path ($name,$dir,$ext) = fileparse($file [, qr/\.[^.]*/] ) use Time::HiRes qw( gettimeofday tv_interval ); use Data::Dumper; use Env qw(HOME FG_ROOT FG_HOME); # pour lire HOME FG_HOME et FG_ROOT my $os = $^O; my $perl_dir = '/home/geoff/bin'; my $PATH_SEP = '/'; my $temp_dir = '/tmp'; if ($os =~ /win/i) { $perl_dir = 'C:\GTools\perl'; $temp_dir = $perl_dir; $PATH_SEP = "\\"; } unshift(@INC, $perl_dir); require 'lib_utils.pl' or die "Unable to load 'lib_utils.pl' Check paths in \@INC...\n"; require 'fg_wsg84.pl' or die "Unable to load fg_wsg84.pl ...\n"; # log file stuff our ($LF); my $pgmname = $0; if ($pgmname =~ /(\\|\/)/) { my @tmpsp = split(/(\\|\/)/,$pgmname); $pgmname = $tmpsp[-1]; } my $outfile = $temp_dir.$PATH_SEP."temp.$pgmname.txt"; my $out_xg = $temp_dir.$PATH_SEP."tempout.xg"; my $out_csv = $temp_dir.$PATH_SEP."tempout.csv"; open_log($outfile); my $def_dep = ""; my $def_arr = ""; my $debug_on = 0; if ($debug_on) { ##$def_dep = "YCBA"; ##$def_arr = "YGIL"; ##$def_dep = "YGIL"; ##$def_arr = "YPAG"; # "YBHI"; # "YCBA"; ##$def_dep = "KSFO"; # "ESSA"; # "LFPG"; ##$def_arr = "KLAX"; # "LFPG"; # "LFBD"; ##$def_dep = "LFPO"; # Orly ##$def_arr = "LFBD"; # Bordeaux Merignac ##$def_dep = "LFPV"; # Velizy ##$def_arr = "LFCZ"; # Mimizan ##$def_dep = "YPPH"; # Perth ##$def_arr = "YSSY"; # Sydney $def_dep = "KCLT"; # USA - 749 KCLT Charlotte Douglas Intl 35.223512110,-80.944231280 $def_arr = "LIRF"; # Italy - 15 LIRF Roma Fiumicino Leonardo 41.793517,12.251605 } # c172p #my $aircraft = "c172p"; #my $max_range = 696; # nm #my $cruise_speed = 150; # 122; # kts (kn) = 87 km/h #my $def_altitude = 2000; # feet AGL (or AMSL) # Cruise speed: 122 kn (140 mph; 226 km/h) # Stall speed: 47 kn (54 mph; 87 km/h) (power off, flaps down)[73] # Never exceed speed: 163 kn (188 mph; 302 km/h) (IAS)[8] # Range: 696 nmi (801 mi; 1,289 km) with 45 minute reserve, 55% Power, at 12,000 ft # Service ceiling: 13,500 ft (4,100 m) # Rate of climb: 721 ft/min (3.66 m/s) # Wing loading: 14.1 lb/sq ft (68.6 kg/m2) # Beech 99 #my $aircraft = "beech99"; # "beech99-yasim"; #my $max_range = 910; # nm #my $cruise_speed = 205; # kts (kn) = 87 km/h # Cruise speed: 205 knots (380 km/h) at 10,000 ft (3,050 m) # Range: 910 nm (1,048 mi, 1,686 km) at 216 mph (347 km/h) at 8,000 ft (2,440 m) # Service ceiling: 26,200 ft (7,988 m) # Rate of climb: 1,700 ft/min (8.63 m/s) #my $def_altitude = 5000; # feet AGL (or AMSL) # A330 my $aircraft = "A330"; # A330-300 my $max_range = 7500; # nm 13,450 km my $cruise_speed = 470; # kts (kn) = 871 km/h my $def_altitude = 10000; # feet AGL (or AMSL) # Cub #my $aircraft = 'Cub'; #my $cruise_speed = 62; # kn #my $max_range = 191; # NM with fuel adjustment to Cub_FDM.xml #my $def_altitude = 3000; # feet AGL (or AMSL) ## DECLARATION DES VARIABLES GLOBALES ##################################### # sid icao lat lon apt-array # 0 1 2 3 4 my @depart = (undef, $def_dep, undef, undef, undef); # tableau contenant des infos sur l'aéroport de départ (sid, ICAO, lat, lon, nom complet de l'aéroport) my @arrivee = (undef, $def_arr, undef, undef, undef, undef); # tableau contenant des infos sur l'aéroport d'arrivée (star, ICAO, lat, lon, nom complet de l'aéroport) # 0 1 2 3 4 5 6 7 8 # push(@g_navaids, [$typ, $nlat, $nlon, $nalt, $nfrq, $nrng, $nfrq2, $nid, $name, 0, 0, 0, 0] ); my @g_navaids = (); my $fgfs; # socket de connexion à fgfs my @route; # contient la route à suivre my @flt_plan = (); # similar to the above my @flt_hops = (); # above processed to find refueling airports my %apt_icao = (); # set with a reference of each airport found. key=ICAO my ($navaid, $fix); # pointent sur les tableaux contenant les aides à la navigation my $erreur; # contient les messages d'erreur éventuels my $version; # pour la compatibilité avec différentes version de nav.dat.gz my $sous_fonction; # pointe vers des sous fonctions anonymes définies localement my @all_airports = (); # load ALL airports my $done_all = 0; # only done once # actually seems little difference on these mostly small distances my $use_sg_math = 1; # use fg_geo_inverse_wgs_84($lat1, $lon1, $lat2, $lon2, \$az1, \$az2, \$s); my $VERS = "0.8.0 2014-11-13"; # my $VERS = "0.7.0 2014-10-03"; # my $VERS = "0.6.0"; my $load_log = 0; my $verbosity = 1; # default verbosity (range 0,1,2,5,9) my $add_xg_bbox = 0; my $def_root = "F:\\fgdata"; $def_root = "X:\\fgdata" if (-d "X:\\fgdata"); # VARIABLES DES OPTIONS DU SCRIPT ################################# my $FGROOT = (exists $ENV{FG_ROOT})? $FG_ROOT : $def_root; my $FGHOME = (exists $ENV{FG_HOME})? $FG_HOME : "$HOME/.fgfs"; my $vor_a_vor; # exclusivement du vor my $vor_preferes; # si on veut du vor, mais sinon du ndb my $deviation_max = 30; # virage maximal my $dist_min = 74; # = 40 # was 10; # distance minimale entre deux waypoints (km?) my $km; # affichage des distances en kilomètres my $help; # demande d'aide my $csv_conf=':,'; # les séparateurs pour les fichiers .csv my $no_stdout; # pas de sortie sur le terminal my ($sidx, $starx); # protocole sid/star demandé sans spécifier de piste my ($sid, $star); # protocole sid/star demandé en spécifiant une piste my $add_couleur; # applique des couleurs à la sortie standard my ($com_dep, $com_app, $com); # pour afficher les fréqences de communication my $wpt; #enregistrer la route my $WPFILE; # le fichier dans lequel on enregistre les points de passage my $CSVFILE; # le fichier dans lequel on enregistre les points de passage my $XGFILE; # le fichier dans lequel on enregistre les points de passage my $add_altitude = 1; # add altitdude to waypoints my $xml_base = ''; my $incl_refuel_ap = 1; # not used or documented # my $INSTRFILE; # création d'un fichier .xml # "instr" => \$INSTRFILE, my $options = GetOptions ( "v|vor-a-vor" => \$vor_a_vor, "preferer-vor"=> \$vor_preferes, "km" => \$km, "dev-max=i" => \$deviation_max, "dist-min=i" => \$dist_min, "max-range=i" => \$max_range, "fg-root=s" => \$FGROOT, "aircraft=s" => \$aircraft, "wpt" => \$wpt, "csv=s" => \$CSVFILE, "xg=s" => \$XGFILE, "csv-conf=s" => \$csv_conf, "d|dep=s" => \$depart[1], "a|arr=s" => \$arrivee[1], "no-stdout" => \$no_stdout, "help" => \$help, "sidx" => \$sidx, "starx" => \$starx, "sid=s" => \$sid, "star=s" => \$star, "com-dep" => \$com_dep, "com-app" => \$com_app, "com" => \$com, "def-alt=i" => \$def_altitude, "def-spd=i" => \$cruise_speed, "ansi" => \$add_couleur); ## FICHIERS UTILISÉS PAR LE SCRIPT ## à modifier selon sa propre configuration ## accepte les fichiers en clair, ou gzipés ########################################### my $NAVFILE = "$FGROOT/Navaids/nav.dat.gz"; # le fichier contenant les aides à la navigation my $FIXFILE = "$FGROOT/Navaids/fix.dat.gz"; # le fichier contenant les fix my $SIDFILE = "$FGROOT/NavAids/sid.dat"; # le fichier contenant les procédures SID my $STARFILE = "$FGROOT/NavAids/star.dat"; # le fichier contenant les procédure STAR my $APTFILE = "$FGROOT/Airports/apt.dat.gz"; # le fichier contenant les aéroports my $AWYFILE = "$FGROOT/Navaids/awy.dat.gz"; # hi and low airways ## DÉCLARÉ COMME VARIABLE MAIS UTILISÉ COMME CONSTANTE ###################################################### my $texte_aide = <) (-a | --arr ) options: [-v | --vor-a-vor] [--preferer-vor] [--km] [--fg-root ] [--wpt] [--csv ] [--csv-conf ] [--xg ] [--dev-max ] [--dist-min ] [--max-range ] [--aircraft ] [--sid ][--star ] [--sidx][--starx] [--com-dep][--com-app][--com] [--ansi] [--def-alt [--def-spd [--help] Essential: -d|--dep=icao : point de départ. il est possible de spécifier: - soit le code oaci de l'aéroport (ex: --dep=LFQQ), - soit la position actuelle de l'avion dans fgfs (ex: --dep=telnet:5401) - soit une position exprimée en lat, long (ex: --dep=[45.564,-2.066]) Options: -a|--arr=icao : point d'arrivée. même possibilités que l'option --dep --aircraft : Short name of aircraft. Used to name the xml output file. (default $aircraft) -v | --vor-a-vor : ne sélectionne que les balises VOR et VOR-DME (pas de TACAN) --preferer-vor : route construite avec NDB et VOR, avec une préférence pour les balises VOR --km : affiche la distance en km (défaut: affichage en nm) --fg-root=path : chemin contenant les fichiers de FlightGear défaut: $FGROOT --wpt : enregistre la route dans $FGROOT/Routes (nommage auto) directory must exist. It will not be created. --csv=file : fichier CSV ( séparateur = : , virgule décimale = , ) pour affichage du trajet en graphique (via oocalc par exemple) --xg=file : fichier XG. Can be viewed by polyView2D. See https://sites.google.com/site/polyview2d/ --csv-conf=ab : paramètre les séparateurs de colonne et de décimale pour la fabrication du fichier csv. format = séparateurdécimale (ex: --csv-conf=?ù) pour des colonnes séparées par le caractère '?', et la virgule représentée par le caractère 'ù'. par défaut --csv-conf=$csv_conf --dev-max=degs : déviation maximale d'une balise à une autre par rapport au trajet en cours (défaut: $deviation_max°) --dist-min=km : distance minimale entre deux balises (défaut: $dist_min km) --max-range=nm : maximum distance before refueling (defaut: $max_range nm) --sid --star=rw : cherche le trajet en tenant compte de la procédure sid (ou star) de la piste codé sur deux ou trois caractères (ex: --sid 09 --star 23, ou --sid 09R --star 23) si aucun indicatif de piste (R, C ou L) n'est fourni ils seront tous les trois inclus dans la recherche de procédure --sidx, --starx : idem que --sid et --star, mais avec une piste choisie par le programme: - pour le moment, le choix se porte sur la piste dont la procédure rapproche du point de départ/arrivée - dans le futur, il est prévu une implémentation avec les METAR (décollage/atterrissage face au vent) - selon l'évolution du fichier apt.dat, on peut imaginer un choix en fonction des pistes réellement usitées --com-dep, --com-app : affichent respectivement les fréquences COM pour le départ (dep) ou l'approche (app) --com : affichent les fréquences COM pour le départ (dep) and l'approche (app) --def-alt=feet : default AGL in feet --def-spd=kn : default cruise speed in kn --ansi : affiche les étapes en couleurs, pour les terminaux qui ne supportent pas la norme ANSI, ou pour redirection du résultat --help : affiche ce message d'aide et quitte (même si d'autres options ont été spécifiées) CE SCRIPT NE PROPOSE PAS UNE SOLUTION DE VOL FIABLE POUR LA CONSTRUCTION D'UN PLAN DE VOL RÉEL!!!!!!!! IL N'EST QU'UNE SOLUTION POUR PROPOSER UN TRAJET DE _LOISIR_ AVEC FLIGHTGEAR FS ET NE GARANTIT EN AUCUN CAS LA FIABILITÉ DES INFORMATIONS QU'IL DÉLIVRE EOH my $PI = 3.1415926535897932384626433832795029; my $D2R = $PI / 180; my $R2D = 180 / $PI; my $ERAD = 6378138.12; #my $ERAD = 6378; my $NDB = 2; my $VOR = 3; my $KM2FEET = 3280.84; my $NM2KM = 1.852; my $KM2NM = 0.539957; sub VERB1() { return $verbosity >= 1; } sub VERB2() { return $verbosity >= 2; } sub VERB5() { return $verbosity >= 5; } sub VERB9() { return $verbosity >= 9; } sub pgm_exit($$) { my ($val,$msg) = @_; if (length($msg)) { $msg .= "\n" if (!($msg =~ /\n$/)); prt($msg); } # show_warnings($val); close_log($outfile,$load_log); exit($val); } # FONCTIONS DE CONNEXION AVEC FGFS PAR TELNET ############################################# sub get_prop($$) { my( $handle ) = shift; &fg_send( $handle, "get " . shift ); eof $handle and die "\nconnection closed by host"; $_ = <$handle>; s/\015?\012$//; /^-ERR (.*)/ and die "\nfgfs error: $1\n"; return $_; } sub set_prop($$$) { my( $handle ) = shift; my( $prop ) = shift; my( $value ) = shift; &fg_send( $handle, "set $prop $value"); # eof $handle and die "\nconnection closed by host"; } sub fg_send($$) { my( $handle ) = shift; print $handle shift, "\015\012"; } sub fg_connect($$$) { my( $host ) = shift; my( $port ) = shift; my( $timeout ) = (shift || 120); my( $socket ); STDOUT->autoflush(1); while ($timeout--) { if ($socket = IO::Socket::INET->new( Proto => 'tcp', PeerAddr => $host, PeerPort => $port) ) { $socket->autoflush(1); return $socket; } prt( "Attempting to connect to $host ... " . $timeout . "\n" ); sleep(1); } return 0; } # FONCTIONS DE CALCULS GEOGRAPHIQUES # par Frank Melchior #################################### sub round($) { my $i = shift; my $m = (shift or 1); $i /= $m; $i = $i - &floor($i) >= 0.5 ? &ceil($i) : &floor($i); $i *= $m; return $i; } sub coord_dist_sq($$$$$$) { my ($xa, $ya, $za, $xb, $yb, $zb) = @_; my $x = $xb - $xa; my $y = $yb - $ya; my $z = $zb - $za; return $x * $x + $y * $y + $z * $z; } sub ll2xyz($$) { my $lat = (shift) * $D2R; my $lon = (shift) * $D2R; my $cosphi = cos $lat; my $di = $cosphi * cos $lon; my $dj = $cosphi * sin $lon; my $dk = sin $lat; return ($di, $dj, $dk); } # return km distance sub distance_($) { my $t = shift; my @ll1 = ll2xyz($t->[0], $t->[1]); my @ll2 = ll2xyz($t->[2], $t->[3]); return $ERAD * sqrt(coord_dist_sq($ll1[0], $ll1[1], $ll1[2], $ll2[0], $ll2[1], $ll2[2])) / 1000; } sub llll2dir_($) { my $t = shift; my $latA = ($t->[0]) * $D2R; my $lonA = ($t->[1]) * $D2R; my $latB = ($t->[2]) * $D2R; my $lonB = ($t->[3]) * $D2R; my $xdist = sin($lonB - $lonA) * $ERAD * cos(($latA + $latB) / 2); my $ydist = sin($latB - $latA) * $ERAD; my $dir = atan2($xdist, $ydist) * $R2D; $dir += 360 if $dir < 0; return $dir; } # Airport Line. eg '1 5355 1 0 KABQ Albuquerque Intl Sunport' # 0 1 - this as an airport header line. 16 is a seaplane/floatplane base, 17 a heliport. # 1 5355 - Airport elevation (in feet above MSL). # 2 1 - Airport has a control tower (1=yes, 0=no). # 3 0 - Display X-Plane’s default airport buildings (1=yes, 0=no). # 4 KABQ - Identifying code for the airport (the ICAO code, if one exists). # 5+Albuquerque Intl Sunport - Airport name. sub load_airports() { my ($ver,$line,$type,$autre_bout); my $t1 = [gettimeofday]; if ( -e $APTFILE ) { open (APT, "gzip -d -c $APTFILE|") or die "je ne peux pas ouvrir $APTFILE\n" ; while () { if (/^(\d+)\s+Version\s+/) { $ver = $1; last; } } } else { prt("fichier $APTFILE introuvable\n"); prt("veuillez vérifier \$FGROOT\n"); prt("ou utilisez l'option --fg-root=répertoire\n"); prt("ou encore modifiez le script ver ligne 80\n"); exit 1; } if ($ver) { prt("Loading file $APTFILE, version $ver... moment...\n") if (VERB1()); } else { close APT; prt("Failed to find version in $APTFILE!\n"); exit 1; } my $aptcnt = 0; while ($line = ) { chomp $line; next if ($line =~ /^\s*$/); my @header = split(/\s+/, $line); $type = $header[0]; last if ($type == 99); if ($type == 1) { # 0 1 2 3 4 5+ # # elev_ft twr bld icao name push(@all_airports, \@header); $aptcnt++; } elsif ($type == 10) { if ($header[3] ne 'xxx') { # 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 # 10 36.962213 127.031071 14x 131.52 8208 1595.0620 0000.0000 150 321321 1 0 3 0.25 0 0300.0300 # 10 36.969145 127.020106 xxx 221.51 329 0.0 0.0 75 161161 1 0 0 0.25 0 $header[3] =~ /(..)(.)/; $autre_bout = ($1 > 18)? $1 - 18 : $1 + 18; $autre_bout = '0'.$autre_bout if ($autre_bout < 10); $autre_bout .= 'L' if ($2 eq 'R'); $autre_bout .= 'R' if ($2 eq 'L'); $autre_bout .= 'C' if ($2 eq 'C'); if ($2 eq 'x') { $header[3] = $1.' '; $autre_bout .= ' '; } $header[3] = $header[3].'/'.$autre_bout; push(@all_airports,\@header); } } elsif ($type == 100) { # See version 1000 specs # 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 # 100 29.87 3 0 0.00 1 2 1 16 43.91080605 004.90321905 0.00 0.00 2 0 0 0 34 43.90662331 004.90428974 0.00 0.00 2 0 0 0 my $rwy = $header[8]; my $rwynm = $rwy; $rwynm =~ /(..)(.)/; $autre_bout = ($1 > 18) ? $1 - 18 : $1 + 18; $autre_bout = '0'.$autre_bout if ($autre_bout < 10); $autre_bout .= 'L' if ($2 eq 'R'); $autre_bout .= 'R' if ($2 eq 'L'); $autre_bout .= 'C' if ($2 eq 'C'); if ($2 eq 'x') { $rwy = $1.' '; $autre_bout .= ' '; } $rwynm = $rwy.'/'.$autre_bout; my $rlat1 = $header[9]; # $of_lat1 my $rlon1 = $header[10]; # $of_lon1 my $rlat2 = $header[18]; # $of_lat2 my $rlon2 = $header[19]; # $of_lon2 my $rlat = ($rlat1 + $rlat2) / 2; my $rlon = ($rlon1 + $rlon2) / 2; my ($dist,$az1,$az2,$res,$s); if ($use_sg_math) { $res = fg_geo_inverse_wgs_84($rlat1, $rlon1, $rlat2, $rlon2, \$az1, \$az2, \$s); $dist = int(($s / 1000) * $KM2FEET ); # runway length, in feet } else { $dist = distance_( [$rlat1, $rlon1, $rlat2, $rlon2] ); $dist = int( $dist * $KM2FEET ); # runway length, in feet $az1 = llll2dir_( [$rlat1, $rlon1, $rlat2, $rlon2] ); } $az1 = round($az1); my @a = (); #push(@a,[10, $rlat, $rlon, $rwynm, $az1, $dist, 0.0, 0.0, 75, 161161, 1, 0, 0, 0.25, 0, 0]); @a = (10, $rlat, $rlon, $rwynm, $az1, $dist, 0.0, 0.0, 75, 161161, 1, 0, 0, 0.25, 0, 0); push(@all_airports, \@a); } elsif (($type >= 50)&&($type <= 59)) { # on garde aussi les fréquences COM... push(@all_airports,\@header); } } $done_all = scalar @all_airports; my $elap = secs_HHMMSS( tv_interval( $t1, [gettimeofday] ) ); prt("Loaded $aptcnt airports, total $done_all lines...in $elap...\n") if (VERB1()); $done_all = 1; } sub get_airport_by_icao($$) { my ($icao,$ara) = @_; my $max = scalar @all_airports; my ($i,$type,$ra); my $fnd = 0; for ($i = 0; $i < $max; $i++) { $ra = $all_airports[$i]; $type = ${$ra}[0]; if (($type == 1) && (${$ra}[4] eq $icao)) { push(@{$ara},$ra); $i++; $fnd = 1; for (; $i < $max; $i++) { $ra = $all_airports[$i]; $type = ${$ra}[0]; last if ($type == 1); # stop at next airport header push(@{$ara},$ra); } } last if ($fnd); } return $fnd; } # FONCTIONS DE CALCUL DU TRAJET # passed reference to # my @depart = (undef, "LFPG", undef, undef,undef); # or @arrivee ... ############################### sub configure_extremite ($$$) { my ($extremite, $proc, $procx) = @_; my $extremite_ok; # positionné à 1 si l'extrémité a pu être configuré, # sera la valeur de retour de la fonction # to UPPER case $extremite->[1] =~ tr/a-z/A-Z/; my $icao = $extremite->[1]; # extract icao sub getPositionParTelnet ($) { # si on est pas déjà connecté, alors on se connecte if (!$fgfs) { if ( !($fgfs = &fg_connect("localhost", $_[0], 5)) ) { prt("Impossible de se connecter\n"); } } # on récupère la position actuelle de l'appareil my $lat = get_prop ($fgfs,"/position/latitude-deg[0]"); my $lon = get_prop ($fgfs, "/position/longitude-deg[0]"); # si la postion est trouvée (limitation: ~ est différente de 0°00'00''N 0°00'00''E) if ($lat && $lon) { $extremite_ok = 1; return $lat, $lon; } else { $erreur = "Impossible de déterminer la position actuelle de l'appareil\n"; } } $sous_fonction = sub { my $t1 = [gettimeofday]; my ($type,@donnees_aeroport); get_airport_by_icao($icao,\@donnees_aeroport); # on récupère ses coordonnées de la première piste listée... pour l'instant my $lcnt = scalar @donnees_aeroport; if ($lcnt > 0) { my ($i,$ra,$alat,$alon); for ($i = 0; $i < $lcnt; $i++) { $ra = $donnees_aeroport[$i]; $type = ${$ra}[0]; ### prt("$i: rtype $rtype\n"); if ($type == 10) { $alat = ${$ra}[1]; $alon = ${$ra}[2]; $extremite_ok = 1; last; } } if ($extremite_ok) { my $elap = secs_HHMMSS( tv_interval( $t1, [gettimeofday] ) ); prt("Success: $icao lat/lon $alat,$alon, $lcnt records... in $elap\n") if (VERB1()); # return @{$donnees_aeroport[1]}[1], @{$donnees_aeroport[1]}[2], \@donnees_aeroport; return $alat,$alon,\@donnees_aeroport; } $erreur = "Error: No runways found for $icao..."; } else { # ces lignes ne atteintes que si aucun aéroport a été trouvé dans la base $erreur = "Error: $icao n'a pas été trouvé dans la base de données aéroports..."; } }; if ($extremite->[1] =~ /^TELNET:(\d+)/) { # position actuelle de l'appareil, connue par telnet $extremite->[1] = "ici"; ($extremite->[2], $extremite->[3]) = getPositionParTelnet ($1); $extremite->[4] = [[0, undef, undef, undef, undef, "position au ".`date`]]; ($extremite->[0], $$proc, $$procx) = (undef, undef, undef); } elsif ($extremite->[1] =~ /^\[(.+),(.+)\]$/) { # position exprimée en coordonnées cartésiennes $extremite->[1] = "pos"; ($extremite->[2], $extremite->[3]) = ($1, $2); $extremite->[4] = [[0, undef, undef, undef,undef, $1.", ".$2]]; if (abs($extremite->[2])<=90 && abs($extremite->[3])<=180) { $extremite_ok = 1; } else { $erreur = "format de coordonnées inconnu...: ".$extremite->[2]." ".$extremite->[3]; } ($extremite->[0], $$proc, $$procx) = (undef, undef, undef); } else { # position par nom de l'aéroport # set positions and runway array ($extremite->[2], $extremite->[3], $extremite->[4]) = &$sous_fonction ($extremite); } # on ferme la connexion avec fgfs close ($fgfs) if $fgfs; # on retourne le résultat de nos recherches return $extremite_ok; } sub load_nav_data() { my $t1 = [gettimeofday]; prt("\n[v5] Loading $NAVFILE file ...\n") if (VERB5()); die "ERROR: Can NOT stat '$NAVFILE'!\n" if ( !( -f $NAVFILE) ); open NIF, "gzip -d -c $NAVFILE|" or die "ERROR: CAN NOT OPEN $NAVFILE...$!...\n"; my @nav_lines = ; close NIF; my $elap = secs_HHMMSS( tv_interval( $t1, [gettimeofday] ) ); prt("[v5] Got ".scalar @nav_lines." lines in $elap...\n") if (VERB5()); my ($line,@arr,$nc,$i,$len); my ($typ,$nlat,$nlon,$nalt,$nfrq,$nrng,$nfrq2,$nid,$name); foreach $line (@nav_lines) { chomp $line; $line = trim_all($line); $len = length($line); next if ($line =~ /\s+Version\s+/i); next if ($line =~ /^I/); next if ($len == 0); # 0 1 (lat) 2 (lon) 3(alt) 4(feq) 5(rng) 6 7 8++ # 2 38.087769 -077.324919 284 396 25 0.000 APH A P Hill NDB # 3 57.103719 009.995578 57 11670 100 1.000 AAL Aalborg VORTAC # 4 39.980911 -075.877814 660 10850 18 281.662 IMQS 40N 29 ILS-cat-I # 4 -09.458922 147.231225 128 11010 18 148.650 IWG AYPY 14L ILS-cat-I # 5 40.034606 -079.023281 2272 10870 18 236.086 ISOZ 2G9 24 LOC # 5 67.018506 -050.682072 165 10955 18 61.600 ISF BGSF 10 LOC # 6 39.977294 -075.860275 655 10850 10 300281.205 --- 40N 29 GS # 6 -09.432703 147.216444 128 11010 10 302148.785 --- AYPY 14L GS # 7 39.960719 -075.750778 660 0 0 281.205 --- 40N 29 OM # 7 -09.376150 147.176867 146 0 0 148.785 JSN AYPY 14L OM # 8 -09.421875 147.208331 91 0 0 148.785 MM AYPY 14L MM # 8 -09.461050 147.232544 146 0 0 328.777 PY AYPY 32R MM # 9 65.609444 -018.052222 32 0 0 22.093 --- BIAR 01 IM # 9 08.425319 004.475597 1126 0 0 49.252 IL DNIL 05 IM # 12 -09.432703 147.216444 11 11010 18 0.000 IWG AYPY 14L DME-ILS # 12 -09.449222 147.226589 11 10950 18 0.000 IBB AYPY 32R DME-ILS @arr = split(/\s+/,$line); $nc = scalar @arr; $typ = $arr[0]; last if ($typ == 99); if ($nc < 8) { prt("Type: [$typ] - Handle this line [$line] - count = $nc...\n"); pgm_exit(1,"ERROR: FIX ME FIRST!\n"); } $nlat = $arr[1]; $nlon = $arr[2]; $nalt = $arr[3]; $nfrq = $arr[4]; $nrng = $arr[5]; $nfrq2 = $arr[6]; $nid = $arr[7]; $name = ''; for ($i = 8; $i < $nc; $i++) { $name .= ' ' if length($name); $name .= $arr[$i]; } push(@g_navaids, [$typ, $nlat, $nlon, $nalt, $nfrq, $nrng, $nfrq2, $nid, $name, 0, 0, 0, 0] ); } $elap = secs_HHMMSS( tv_interval( $t1, [gettimeofday] ) ); prt("[v5] Got ".scalar @g_navaids." navaids in $elap...\n") if (VERB5()); } # NAV_TO_RAM ############ # 0 1 (lat) 2 (lon) 3(alt) 4(feq) 5(rng) 6 7 8++ # 2 38.087769 -077.324919 284 396 25 0.000 APH A P Hill NDB # 3 57.103719 009.995578 57 11670 100 1.000 AAL Aalborg VORTAC sub nav_to_ram ($$$) { my ($fichier, $phrase, $decale) = @_; prt("Loading file ${$fichier}, p=$phrase d=$decale\n") if (VERB2()); my @selection; # tableau qui va contenir les aides à la navigation utiles my $marge = 2; my $lat_sup = (($depart[2] >= $arrivee[2])? $depart[2]:$arrivee[2]) + $marge; my $lat_inf = (($depart[2] <= $arrivee[2])? $depart[2]:$arrivee[2]) - $marge; my $long_sup = (($depart[3] >= $arrivee[3])? $depart[3]:$arrivee[3]) + $marge; my $long_inf = (($depart[3] <= $arrivee[3])? $depart[3]:$arrivee[3]) - $marge; prt("For lat/lon $lat_sup,$long_sup $lat_inf,$long_inf...\n") if (VERB5()); if ( -e $$fichier ) { $$fichier =~ /.+\.(.+)$/; my $fichier_traite = ($1 eq 'gz')? 'gzip -d -c '.$$fichier.'|' : $$fichier; open (NAV, $fichier_traite) or die "je ne peux pas ouvrir $$fichier\n" ; } else { die "fichier $$fichier introuvable\n"; } # on détermine la version du fichier nav.dat if ($$fichier eq $NAVFILE) { while (