]> git.mxchange.org Git - flightgear.git/blob - src/AIModel/AIFlightPlanCreate.cxx
Add a lower-bound type navaid lookup, and the ability to specify navaid type in the...
[flightgear.git] / src / AIModel / AIFlightPlanCreate.cxx
1 /******************************************************************************
2  * AIFlightPlanCreate.cxx
3  * Written by Durk Talsma, started May, 2004.
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License as
7  * published by the Free Software Foundation; either version 2 of the
8  * License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  *
19  *
20  **************************************************************************/
21 #include "AIFlightPlan.hxx"
22 #include <simgear/math/sg_geodesy.hxx>
23 #include <Airports/runways.hxx>
24
25 #include <Environment/environment_mgr.hxx>
26 #include <Environment/environment.hxx>
27
28
29 /* FGAIFlightPlan::create()
30  * dynamically create a flight plan for AI traffic, based on data provided by the
31  * Traffic Manager, when reading a filed flightplan failes. (DT, 2004/07/10) 
32  *
33  * This is the top-level function, and the only one that publicly available.
34  *
35  */ 
36
37
38 // Check lat/lon values during initialization;
39 void FGAIFlightPlan::create(FGAirport *dep, FGAirport *arr, int legNr, double alt, double speed, 
40                             double latitude, double longitude, bool firstFlight,
41                             double radius, const string& fltType, const string& aircraftType, const string& airline)
42
43   int currWpt = wpt_iterator - waypoints.begin();
44   switch(legNr)
45     {
46     case 1:
47       //cerr << "Creating Push_Back" << endl;
48       createPushBack(firstFlight,dep, latitude, longitude, radius, fltType, aircraftType, airline);
49       //cerr << "Done" << endl;
50       break;
51     case 2: 
52       //cerr << "Creating Taxi" << endl;
53       createTaxi(firstFlight, 1, dep, latitude, longitude, radius, fltType, aircraftType, airline);
54       break;
55     case 3: 
56       //cerr << "Creating TAkeoff" << endl;
57       createTakeOff(firstFlight, dep, speed);
58       break;
59     case 4: 
60       //cerr << "Creating Climb" << endl;
61       createClimb(firstFlight, dep, speed, alt);
62       break;
63     case 5: 
64       //cerr << "Creating Cruise" << endl;
65       createCruise(firstFlight, dep,arr, latitude, longitude, speed, alt);
66       break;
67     case 6: 
68       //cerr << "Creating Decent" << endl;
69       createDecent(arr);
70       break;
71     case 7: 
72       //cerr << "Creating Landing" << endl;
73       createLanding(arr);
74       break;
75     case 8: 
76       //cerr << "Creating Taxi 2" << endl;
77       createTaxi(false, 2, arr, latitude, longitude, radius, fltType, aircraftType, airline);
78       break;
79     case 9: 
80       //cerr << "Creating Parking" << endl;
81       createParking(arr);
82       break;
83     default:
84       //exit(1);
85       cerr << "Unknown case: " << legNr << endl;
86     }
87   wpt_iterator = waypoints.begin()+currWpt;
88   leg++;
89 }
90
91 /*******************************************************************
92  * createPushBack
93  * initialize the Aircraft at the parking location
94  ******************************************************************/
95 void FGAIFlightPlan::createPushBack(bool firstFlight, FGAirport *dep, 
96                                     double latitude,
97                                     double longitude,
98                                     double radius,
99                                     const string& fltType,
100                                     const string& aircraftType,
101                                     const string& airline)
102 {
103   double heading;
104   double lat;
105   double lon;
106   double lat2;
107   double lon2;
108   double az2;
109   
110   //int currWpt = wpt_iterator - waypoints.begin();
111   // Erase all existing waypoints.
112   //resetWaypoints();
113   
114   // We only need to get a valid parking if this is the first leg. 
115   // Otherwise use the current aircraft position.
116   if (firstFlight)
117     {
118       if (!(dep->getAvailableParking(&lat, &lon, &heading, &gateId, radius, fltType, aircraftType, airline)))
119         {
120           cerr << "Could not find parking " << endl;
121         }
122     }
123   else
124     {
125       dep->getParking(gateId, &lat, &lon, &heading);
126       //lat     = latitude;
127       //lon     = longitude;
128       //heading = getHeading();
129     }
130   heading += 180.0;
131   if (heading > 360)
132     heading -= 360;
133   waypoint *wpt = new waypoint;
134   wpt->name      = "park";
135   wpt->latitude  = lat;
136   wpt->longitude = lon;
137   wpt->altitude  = dep->getElevation();
138   wpt->speed     = -10; 
139   wpt->crossat   = -10000;
140   wpt->gear_down = true;
141   wpt->flaps_down= true;
142   wpt->finished  = false;
143   wpt->on_ground = true;
144   waypoints.push_back(wpt); 
145   
146   // Add park twice, because it uses park once for initialization and once
147   // to trigger the departure ATC message 
148   geo_direct_wgs_84 ( 0, lat, lon, heading, 
149                       10, 
150                       &lat2, &lon2, &az2 );
151   wpt = new waypoint;
152   wpt->name      = "park2";
153   wpt->latitude  = lat2;
154   wpt->longitude = lon2;
155   wpt->altitude  = dep->getElevation();
156   wpt->speed     = -10; 
157   wpt->crossat   = -10000;
158   wpt->gear_down = true;
159   wpt->flaps_down= true;
160   wpt->finished  = false;
161   wpt->on_ground = true;
162   waypoints.push_back(wpt); 
163   geo_direct_wgs_84 ( 0, lat, lon, heading, 
164                       radius,                 // push back one entire aircraft radius
165                       &lat2, &lon2, &az2 );
166   wpt = new waypoint;
167   wpt->name      = "taxiStart";
168   wpt->latitude  = lat2;
169   wpt->longitude = lon2;
170   wpt->altitude  = dep->getElevation();
171   wpt->speed     = 10; 
172   wpt->crossat   = -10000;
173   wpt->gear_down = true;
174   wpt->flaps_down= true;
175   wpt->finished  = false;
176   wpt->on_ground = true;
177   waypoints.push_back(wpt); 
178
179   
180 }
181
182 /*******************************************************************
183  * createCreate Taxi. 
184  * initialize the Aircraft at the parking location
185  ******************************************************************/
186 void FGAIFlightPlan::createTaxi(bool firstFlight, int direction, FGAirport *apt, double latitude, double longitude, double radius, const string& fltType, const string& acType, const string& airline)
187 {
188   double wind_speed;
189   double wind_heading;
190   double heading;
191   //FGRunway rwy;
192   double lat, lon, az;
193   double lat2, lon2, az2;
194   //int direction;
195   waypoint *wpt;
196
197   // Erase all existing waypoints.
198   //   wpt_vector_iterator i= waypoints.begin();
199   //resetWaypoints();
200   //int currWpt = wpt_iterator - waypoints.begin();
201   if (direction == 1)
202     {
203       //string name;
204       // "NOTE: this is currently fixed to "com" for commercial traffic
205       // Should be changed to be used dynamically to allow "gen" and "mil"
206       // as well
207       apt->getActiveRunway("com", 1, activeRunway);
208       if (!(globals->get_runways()->search(apt->getId(), 
209                                             activeRunway, 
210                                             &rwy)))
211         {
212           cout << "Failed to find runway for " << apt->getId() << endl;
213           // Hmm, how do we handle a potential error like this?
214           exit(1);
215         }
216       //string test;
217       //apt->getActiveRunway(string("com"), 1, test);
218       //exit(1);
219       
220       heading = rwy._heading;
221       double azimuth = heading + 180.0;
222       while ( azimuth >= 360.0 ) { azimuth -= 360.0; }
223       geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, azimuth, 
224                           rwy._length * SG_FEET_TO_METER * 0.5 - 5.0,
225                           &lat2, &lon2, &az2 );
226       if (apt->getGroundNetwork()->exists())
227         {
228           intVec ids;
229           int runwayId = apt->getGroundNetwork()->findNearestNode(lat2, lon2);
230           //int currId   = apt->getGroundNetwork()->findNearestNode(latitude,longitude);
231           //exit(1);
232           
233           // A negative gateId indicates an overflow parking, use a
234           // fallback mechanism for this. 
235           // Starting from gate 0 is a bit of a hack...
236           FGTaxiRoute route;
237           if (gateId >= 0)
238             route = apt->getGroundNetwork()->findShortestRoute(gateId, runwayId);
239           else
240             route = apt->getGroundNetwork()->findShortestRoute(0, runwayId);
241           intVecIterator i;
242           //cerr << "creating route : ";
243           // No route found: go from gate directly to runway
244           if (route.empty()) {
245             //Add the runway startpoint;
246             wpt = new waypoint;
247             wpt->name      = "Airport Center";
248             wpt->latitude  = latitude;
249             wpt->longitude = longitude;
250             wpt->altitude  = apt->getElevation();
251             wpt->speed     = 15; 
252             wpt->crossat   = -10000;
253             wpt->gear_down = true;
254             wpt->flaps_down= true;
255             wpt->finished  = false;
256             wpt->on_ground = true;
257             waypoints.push_back(wpt);
258             
259             //Add the runway startpoint;
260             wpt = new waypoint;
261             wpt->name      = "Runway Takeoff";
262             wpt->latitude  = lat2;
263             wpt->longitude = lon2;
264             wpt->altitude  = apt->getElevation();
265             wpt->speed     = 15; 
266             wpt->crossat   = -10000;
267             wpt->gear_down = true;
268             wpt->flaps_down= true;
269             wpt->finished  = false;
270             wpt->on_ground = true;
271             waypoints.push_back(wpt);   
272           } else {
273             int node;
274             route.first();
275             while(route.next(&node))
276               {
277                 //i = ids.end()-1;
278                 //cerr << "Creating Node: " << node << endl;
279                 FGTaxiNode *tn = apt->getGroundNetwork()->findNode(node);
280                 //ids.pop_back();  
281                 wpt = new waypoint;
282                 wpt->name      = "taxiway"; // fixme: should be the name of the taxiway
283                 wpt->latitude  = tn->getLatitude();
284                 wpt->longitude = tn->getLongitude();
285                 wpt->altitude  = apt->getElevation(); // should maybe be tn->elev too
286                 wpt->speed     = 15; 
287                 wpt->crossat   = -10000;
288                 wpt->gear_down = true;
289                 wpt->flaps_down= true;
290                 wpt->finished  = false;
291                 wpt->on_ground = true;
292                 waypoints.push_back(wpt);
293               }
294             cerr << endl;
295           }
296           //exit(1);
297         }
298       else 
299         {
300           //Add the runway startpoint;
301           wpt = new waypoint;
302           wpt->name      = "Airport Center";
303           wpt->latitude  = apt->getLatitude();
304           wpt->longitude = apt->getLongitude();
305           wpt->altitude  = apt->getElevation();
306           wpt->speed     = 15; 
307           wpt->crossat   = -10000;
308           wpt->gear_down = true;
309           wpt->flaps_down= true;
310           wpt->finished  = false;
311           wpt->on_ground = true;
312           waypoints.push_back(wpt);
313           
314           //Add the runway startpoint;
315           wpt = new waypoint;
316           wpt->name      = "Runway Takeoff";
317           wpt->latitude  = lat2;
318           wpt->longitude = lon2;
319           wpt->altitude  = apt->getElevation();
320           wpt->speed     = 15; 
321           wpt->crossat   = -10000;
322           wpt->gear_down = true;
323           wpt->flaps_down= true;
324           wpt->finished  = false;
325           wpt->on_ground = true;
326           waypoints.push_back(wpt);
327           //wpt = new waypoint;
328           //wpt->finished = false;
329           //waypoints.push_back(wpt);  // add one more to prevent a segfault. 
330         }
331     }
332   else  // Landing taxi
333     {
334       //string name;
335       // "NOTE: this is currently fixed to "com" for commercial traffic
336       // Should be changed to be used dynamically to allow "gen" and "mil"
337       // as well
338       //apt->getActiveRunway("com", 1, name);
339       //if (!(globals->get_runways()->search(apt->getId(), 
340       //                                    name, 
341       //                            &rwy)))
342       //{//
343       //cout << "Failed to find runway for " << apt->getId() << endl;
344       // Hmm, how do we handle a potential error like this?
345       // exit(1);
346       //        }
347       //string test;
348       //apt->getActiveRunway(string("com"), 1, test);
349       //exit(1);
350       
351       //heading = rwy._heading;
352       //double azimuth = heading + 180.0;
353       //while ( azimuth >= 360.0 ) { azimuth -= 360.0; }
354       //geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, azimuth, 
355       //                  rwy._length * SG_FEET_TO_METER * 0.5 - 5.0,
356       //                  &lat2, &lon2, &az2 );
357       apt->getAvailableParking(&lat, &lon, &heading, &gateId, radius, fltType, acType, airline);
358       heading += 180.0;
359       if (heading > 360)
360         heading -= 360;
361       geo_direct_wgs_84 ( 0, lat, lon, heading, 
362                           100,
363                           &lat2, &lon2, &az2 );
364       double lat3 = (*(waypoints.end()-1))->latitude;
365       double lon3 = (*(waypoints.end()-1))->longitude;
366       cerr << (*(waypoints.end()-1))->name << endl;
367       if (apt->getGroundNetwork()->exists())
368         {
369           intVec ids;
370           int runwayId = apt->getGroundNetwork()->findNearestNode(lat3, lon3);
371           //int currId   = apt->getGroundNetwork()->findNearestNode(latitude,longitude);
372           //exit(1);
373           
374           // A negative gateId indicates an overflow parking, use a
375           // fallback mechanism for this. 
376           // Starting from gate 0 is a bit of a hack...
377           FGTaxiRoute route;
378           if (gateId >= 0)
379             route = apt->getGroundNetwork()->findShortestRoute(runwayId, gateId);
380           else
381             route = apt->getGroundNetwork()->findShortestRoute(runwayId, 0);
382           intVecIterator i;
383           //cerr << "creating route : ";
384           // No route found: go from gate directly to runway
385           if (route.empty()) {
386             //Add the runway startpoint;
387             wpt = new waypoint;
388             wpt->name      = "Airport Center";
389             wpt->latitude  = latitude;
390             wpt->longitude = longitude;
391             wpt->altitude  = apt->getElevation();
392             wpt->speed     = 15; 
393             wpt->crossat   = -10000;
394             wpt->gear_down = true;
395             wpt->flaps_down= true;
396             wpt->finished  = false;
397             wpt->on_ground = true;
398             waypoints.push_back(wpt);
399             
400             //Add the runway startpoint;
401             wpt = new waypoint;
402             wpt->name      = "Runway Takeoff";
403             wpt->latitude  = lat2;
404             wpt->longitude = lon2;
405             wpt->altitude  = apt->getElevation();
406             wpt->speed     = 15; 
407             wpt->crossat   = -10000;
408             wpt->gear_down = true;
409             wpt->flaps_down= true;
410             wpt->finished  = false;
411             wpt->on_ground = true;
412             waypoints.push_back(wpt);   
413           } else {
414             int node;
415             route.first();
416             while(route.next(&node))
417               {
418                 //i = ids.end()-1;
419                 //cerr << "Creating Node: " << node << endl;
420                 FGTaxiNode *tn = apt->getGroundNetwork()->findNode(node);
421                 //ids.pop_back();  
422                 wpt = new waypoint;
423                 wpt->name      = "taxiway"; // fixme: should be the name of the taxiway
424                 wpt->latitude  = tn->getLatitude();
425                 wpt->longitude = tn->getLongitude();
426                 wpt->altitude  = apt->getElevation(); // should maybe be tn->elev too
427                 wpt->speed     = 15; 
428                 wpt->crossat   = -10000;
429                 wpt->gear_down = true;
430                 wpt->flaps_down= true;
431                 wpt->finished  = false;
432                 wpt->on_ground = true;
433                 waypoints.push_back(wpt);
434               }
435             cerr << endl;
436           }
437           //exit(1);
438         }
439       else
440         {
441           //Add the runway startpoint;
442           wpt = new waypoint;
443           wpt->name      = "Airport Center";
444           wpt->latitude  = apt->getLatitude();
445           wpt->longitude = apt->getLongitude();
446           wpt->altitude  = apt->getElevation();
447           wpt->speed     = 15; 
448           wpt->crossat   = -10000;
449           wpt->gear_down = true;
450           wpt->flaps_down= true;
451           wpt->finished  = false;
452           wpt->on_ground = true;
453           waypoints.push_back(wpt);
454           
455         }
456
457
458
459
460       // Add the final destination waypoint
461       wpt = new waypoint;
462       wpt->name      = "Begin Parking"; //apt->getId(); //wpt_node->getStringValue("name", "END");
463       wpt->latitude  = lat2;
464       wpt->longitude = lon2;
465       wpt->altitude  = apt->getElevation();
466       wpt->speed     = 15; 
467       wpt->crossat   = -10000;
468       wpt->gear_down = true;
469       wpt->flaps_down= true;
470       wpt->finished  = false;
471       wpt->on_ground = true;
472       waypoints.push_back(wpt); 
473
474      
475     }
476   // wpt_iterator = waypoints.begin();
477   //if (!firstFlight)
478   // wpt_iterator++; 
479   //wpt_iterator = waypoints.begin()+currWpt;
480 }
481
482 /*******************************************************************
483  * CreateTakeOff 
484  * initialize the Aircraft at the parking location
485  ******************************************************************/
486 void FGAIFlightPlan::createTakeOff(bool firstFlight, FGAirport *apt, double speed)
487 {
488   double wind_speed;
489   double wind_heading;
490   double heading;
491   //FGRunway rwy;
492   double lat, lon, az;
493   double lat2, lon2, az2;
494   //int direction;
495   waypoint *wpt;
496   
497   
498   // Erase all existing waypoints.
499   // wpt_vector_iterator i= waypoints.begin();
500   //while(waypoints.begin() != waypoints.end())
501   //  {      
502   //    delete *(i);
503   //    waypoints.erase(i);
504   //  }
505   //resetWaypoints();
506   
507   
508   // Get the current active runway, based on code from David Luff
509   // This should actually be unified and extended to include 
510   // Preferential runway use schema's 
511   if (firstFlight)
512     {
513       //string name;
514        // "NOTE: this is currently fixed to "com" for commercial traffic
515       // Should be changed to be used dynamically to allow "gen" and "mil"
516       // as well
517       apt->getActiveRunway("com", 1, activeRunway);
518         if (!(globals->get_runways()->search(apt->getId(), 
519                                               activeRunway, 
520                                               &rwy)))
521           {
522             cout << "Failed to find runway for " << apt->getId() << endl;
523             // Hmm, how do we handle a potential error like this?
524             exit(1);
525           }
526         //string test;
527       //apt->getActiveRunway(string("com"), 1, test);
528       //exit(1);
529     }
530   
531   heading = rwy._heading;
532   double azimuth = heading + 180.0;
533   while ( azimuth >= 360.0 ) { azimuth -= 360.0; }
534   geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, azimuth, 
535                       rwy._length * SG_FEET_TO_METER * 0.5 - 105.0,
536                       &lat2, &lon2, &az2 );
537   wpt = new waypoint; 
538   wpt->name      = "accel"; 
539   wpt->latitude  = lat2; 
540   wpt->longitude = lon2; 
541   wpt->altitude  = apt->getElevation();
542   wpt->speed     = speed;  
543   wpt->crossat   = -10000;
544   wpt->gear_down = true;
545   wpt->flaps_down= true;
546   wpt->finished  = false;
547   wpt->on_ground = true;
548   waypoints.push_back(wpt); 
549   
550   lat = lat2;
551   lon = lon2;
552   az  = az2;
553   
554   //Next: the Start of Climb
555   geo_direct_wgs_84 ( 0, lat, lon, heading, 
556   2560 * SG_FEET_TO_METER,
557   &lat2, &lon2, &az2 );
558   
559   wpt = new waypoint;
560   wpt->name      = "SOC";
561   wpt->latitude  = lat2;
562   wpt->longitude = lon2;
563   wpt->altitude  = apt->getElevation()+3000;
564   wpt->speed     = speed; 
565   wpt->crossat   = -10000;
566   wpt->gear_down = true;
567   wpt->flaps_down= true;
568   wpt->finished  = false;
569   wpt->on_ground = false;
570   waypoints.push_back(wpt);
571   //  waypoints.push_back(wpt);
572   //waypoints.push_back(wpt);  // add one more to prevent a segfault. 
573   // wpt_iterator = waypoints.begin();
574   //if (!firstFlight)
575   // wpt_iterator++;
576 }
577  
578 /*******************************************************************
579  * CreateClimb
580  * initialize the Aircraft at the parking location
581  ******************************************************************/
582 void FGAIFlightPlan::createClimb(bool firstFlight, FGAirport *apt, double speed, double alt)
583 {
584   double wind_speed;
585   double wind_heading;
586   double heading;
587   //FGRunway rwy;
588   double lat, lon, az;
589   double lat2, lon2, az2;
590   //int direction;
591   waypoint *wpt;
592
593   // Erase all existing waypoints.
594   // wpt_vector_iterator i= waypoints.begin();
595   //while(waypoints.begin() != waypoints.end())
596   //  {      
597   //    delete *(i);
598   //    waypoints.erase(i);
599   //  }
600   //resetWaypoints();
601   
602   
603   // Get the current active runway, based on code from David Luff
604   // This should actually be unified and extended to include 
605   // Preferential runway use schema's 
606   if (firstFlight)
607     {
608       //string name;
609       // "NOTE: this is currently fixed to "com" for commercial traffic
610       // Should be changed to be used dynamically to allow "gen" and "mil"
611       // as well
612       apt->getActiveRunway("com", 1, activeRunway);
613         if (!(globals->get_runways()->search(apt->getId(), 
614                                               activeRunway, 
615                                               &rwy)))
616           {
617             cout << "Failed to find runway for " << apt->getId() << endl;
618             // Hmm, how do we handle a potential error like this?
619             exit(1);
620           }
621         //string test;
622         //apt->getActiveRunway(string("com"), 1, test);
623       //exit(1);
624     }
625   
626   
627   heading = rwy._heading;
628   double azimuth = heading + 180.0;
629   while ( azimuth >= 360.0 ) { azimuth -= 360.0; }
630   geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, heading, 
631                       10*SG_NM_TO_METER,
632                       &lat2, &lon2, &az2 );
633   wpt = new waypoint;
634   wpt->name      = "10000ft climb";
635   wpt->latitude  = lat2;
636   wpt->longitude = lon2;
637   wpt->altitude  = 10000;
638   wpt->speed     = speed; 
639   wpt->crossat   = -10000;
640   wpt->gear_down = true;
641   wpt->flaps_down= true;
642   wpt->finished  = false;
643   wpt->on_ground = false;
644   waypoints.push_back(wpt); 
645   
646
647   geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, heading, 
648                       20*SG_NM_TO_METER,
649                       &lat2, &lon2, &az2 );
650   wpt = new waypoint;
651   wpt->name      = "18000ft climb";
652   wpt->latitude  = lat2;
653   wpt->longitude = lon2;
654   wpt->altitude  = 18000;
655   wpt->speed     = speed; 
656   wpt->crossat   = -10000;
657   wpt->gear_down = true;
658   wpt->flaps_down= true;
659   wpt->finished  = false;
660   wpt->on_ground = false;
661   waypoints.push_back(wpt); 
662   //waypoints.push_back(wpt); 
663   //waypoints.push_back(wpt);  // add one more to prevent a segfault. 
664   // wpt_iterator = waypoints.begin();
665   //if (!firstFlight)
666   // wpt_iterator++;
667 }
668
669
670 /*******************************************************************
671  * CreateCruise
672  * initialize the Aircraft at the parking location
673  ******************************************************************/
674 void FGAIFlightPlan::createCruise(bool firstFlight, FGAirport *dep, FGAirport *arr, double latitude, double longitude, double speed, double alt)
675 {
676   double wind_speed;
677   double wind_heading;
678   double heading;
679   //FGRunway rwy;
680   double lat, lon, az;
681   double lat2, lon2, az2;
682   double azimuth;
683   //int direction;
684   waypoint *wpt;
685
686   // Erase all existing waypoints.
687   // wpt_vector_iterator i= waypoints.begin();
688   //while(waypoints.begin() != waypoints.end())
689   //  {      
690   //    delete *(i);
691   //    waypoints.erase(i);
692   //  }
693   //resetWaypoints();
694
695   wpt = new waypoint;
696   wpt->name      = "Cruise"; //wpt_node->getStringValue("name", "END");
697   wpt->latitude  = latitude;
698   wpt->longitude = longitude;
699   wpt->altitude  = alt;
700   wpt->speed     = speed; 
701   wpt->crossat   = -10000;
702   wpt->gear_down = false;
703   wpt->flaps_down= false;
704   wpt->finished  = false;
705   wpt->on_ground = false;
706   waypoints.push_back(wpt); 
707   //Beginning of Decent
708  
709   //string name;
710   // should be changed dynamically to allow "gen" and "mil"
711   arr->getActiveRunway("com", 2, activeRunway);
712   if (!(globals->get_runways()->search(arr->getId(), 
713                                        activeRunway, 
714                                        &rwy)))
715     {
716       cout << "Failed to find runway for " << arr->getId() << endl;
717       // Hmm, how do we handle a potential error like this?
718       exit(1);
719     }
720   //string test;
721   //arr->getActiveRunway(string("com"), 1, test);
722   //exit(1);
723   
724   //cerr << "Altitude = " << alt << endl;
725   //cerr << "Done" << endl;
726   //if (arr->getId() == "EHAM")
727   //  {
728   //    cerr << "Creating cruise to EHAM " << latitude << " " << longitude << endl;
729   //  }
730   heading = rwy._heading;
731   azimuth = heading + 180.0;
732   while ( azimuth >= 360.0 ) { azimuth -= 360.0; }
733   
734   
735   // Note: This places us at the location of the active 
736   // runway during initial cruise. This needs to be 
737   // fixed later. 
738   geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, azimuth, 
739                       110000,
740                       &lat2, &lon2, &az2 );
741   wpt = new waypoint;
742   wpt->name      = "BOD"; //wpt_node->getStringValue("name", "END");
743   wpt->latitude  = lat2;
744   wpt->longitude = lon2;
745   wpt->altitude  = alt;
746   wpt->speed     = speed; 
747   wpt->crossat   = alt;
748   wpt->gear_down = false;
749   wpt->flaps_down= false;
750   wpt->finished  = false;
751   wpt->on_ground = false;
752   waypoints.push_back(wpt); 
753   //waypoints.push_back(wpt);
754   //waypoints.push_back(wpt);  // add one more to prevent a segfault.  
755   //wpt_iterator = waypoints.begin();
756   //if (!firstFlight)
757   // wpt_iterator++;
758 }
759
760 /*******************************************************************
761  * CreateDecent
762  * initialize the Aircraft at the parking location
763  ******************************************************************/
764 void FGAIFlightPlan::createDecent(FGAirport *apt)
765 {
766
767   // Ten thousand ft. Slowing down to 240 kts
768   double wind_speed;
769   double wind_heading;
770   double heading;
771   //FGRunway rwy;
772   double lat, lon, az;
773   double lat2, lon2, az2;
774   double azimuth;
775   //int direction;
776   waypoint *wpt;
777
778   //// Erase all existing waypoints.
779   // wpt_vector_iterator i= waypoints.begin();
780   //while(waypoints.begin() != waypoints.end())
781   //  {      
782   //    delete *(i);
783   //    waypoints.erase(i);
784   //  }
785   //resetWaypoints();
786
787   //Beginning of Decent
788   //string name;
789   // allow "mil" and "gen" as well
790   apt->getActiveRunway("com", 2, activeRunway);
791     if (!(globals->get_runways()->search(apt->getId(), 
792                                           activeRunway, 
793                                           &rwy)))
794       {
795         cout << "Failed to find runway for " << apt->getId() << endl;
796         // Hmm, how do we handle a potential error like this?
797         exit(1);
798       }
799     //string test;
800     //apt->getActiveRunway(string("com"), 1, test);
801   //exit(1);
802
803   //cerr << "Done" << endl;
804   heading = rwy._heading;
805   azimuth = heading + 180.0;
806   while ( azimuth >= 360.0 ) { azimuth -= 360.0; }
807   
808   
809   
810   geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, azimuth, 
811                       100000,
812                       &lat2, &lon2, &az2 );
813   
814   wpt = new waypoint;
815   wpt->name      = "Dec 10000ft"; //wpt_node->getStringValue("name", "END");
816   wpt->latitude  = lat2;
817   wpt->longitude = lon2;
818   wpt->altitude  = apt->getElevation();
819   wpt->speed     = 240; 
820   wpt->crossat   = 10000;
821   wpt->gear_down = false;
822   wpt->flaps_down= false;
823   wpt->finished  = false;
824   wpt->on_ground = false;
825   waypoints.push_back(wpt);  
826
827   // Three thousand ft. Slowing down to 160 kts
828   geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, azimuth, 
829                      8*SG_NM_TO_METER,
830                      &lat2, &lon2, &az2 );
831   wpt = new waypoint;
832   wpt->name      = "DEC 3000ft"; //wpt_node->getStringValue("name", "END");
833   wpt->latitude  = lat2;
834   wpt->longitude = lon2;
835   wpt->altitude  = apt->getElevation();
836   wpt->speed     = 160; 
837   wpt->crossat   = 3000;
838   wpt->gear_down = true;
839   wpt->flaps_down= true;
840   wpt->finished  = false;
841   wpt->on_ground = false;
842   waypoints.push_back(wpt);
843   //waypoints.push_back(wpt);
844   //waypoints.push_back(wpt);  // add one more to prevent a segfault. 
845   //wpt_iterator = waypoints.begin();
846   //wpt_iterator++;
847   //if (apt->getId() == "EHAM")
848   //  {
849   //    cerr << "Created Decend to EHAM " << lat2 << " " << lon2 << ": Runway = " << rwy._rwy_no 
850   //       << "heading " << heading << endl;
851   //  }
852 }
853 /*******************************************************************
854  * CreateLanding
855  * initialize the Aircraft at the parking location
856  ******************************************************************/
857 void FGAIFlightPlan::createLanding(FGAirport *apt)
858 {
859   // Ten thousand ft. Slowing down to 240 kts
860   double wind_speed;
861   double wind_heading;
862   double heading;
863   //FGRunway rwy;
864   double lat, lon, az;
865   double lat2, lon2, az2;
866   double azimuth;
867   //int direction;
868   waypoint *wpt;
869
870   
871   heading = rwy._heading;
872   azimuth = heading + 180.0;
873   while ( azimuth >= 360.0 ) { azimuth -= 360.0; }
874
875   //Runway Threshold
876  geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, azimuth, 
877                      rwy._length*0.45 * SG_FEET_TO_METER,
878                      &lat2, &lon2, &az2 );
879   wpt = new waypoint;
880   wpt->name      = "Threshold"; //wpt_node->getStringValue("name", "END");
881   wpt->latitude  = lat2;
882   wpt->longitude = lon2;
883   wpt->altitude  = apt->getElevation();
884   wpt->speed     = 150; 
885   wpt->crossat   = apt->getElevation();
886   wpt->gear_down = true;
887   wpt->flaps_down= true;
888   wpt->finished  = false;
889   wpt->on_ground = true;
890   waypoints.push_back(wpt); 
891
892  //Full stop at the runway centerpoint
893  geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, azimuth, 
894                      rwy._length*0.45,
895                       &lat2, &lon2, &az2 );
896   wpt = new waypoint;
897   wpt->name      = "Center"; //wpt_node->getStringValue("name", "END");
898   wpt->latitude  = rwy._lat;
899   wpt->longitude = rwy._lon;
900   wpt->altitude  = apt->getElevation();
901   wpt->speed     = 30; 
902   wpt->crossat   = -10000;
903   wpt->gear_down = true;
904   wpt->flaps_down= true;
905   wpt->finished  = false;
906   wpt->on_ground = true;
907   waypoints.push_back(wpt);
908
909  geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, heading, 
910                      rwy._length*0.45 * SG_FEET_TO_METER,
911                      &lat2, &lon2, &az2 );
912   wpt = new waypoint;
913   wpt->name      = "Threshold"; //wpt_node->getStringValue("name", "END");
914   wpt->latitude  = lat2;
915   wpt->longitude = lon2;
916   wpt->altitude  = apt->getElevation();
917   wpt->speed     = 15; 
918   wpt->crossat   = apt->getElevation();
919   wpt->gear_down = true;
920   wpt->flaps_down= true;
921   wpt->finished  = false;
922   wpt->on_ground = true;
923   waypoints.push_back(wpt); 
924   //waypoints.push_back(wpt); 
925   //waypoints.push_back(wpt);  // add one more to prevent a segfault. 
926   //wpt_iterator = waypoints.begin();
927   //wpt_iterator++;
928
929   //if (apt->getId() == "EHAM")
930   //{
931   //  cerr << "Created Landing to EHAM " << lat2 << " " << lon2 << ": Runway = " << rwy._rwy_no 
932   //     << "heading " << heading << endl;
933   //}
934 }
935
936 /*******************************************************************
937  * CreateParking
938  * initialize the Aircraft at the parking location
939  ******************************************************************/
940 void FGAIFlightPlan::createParking(FGAirport *apt)
941 {
942   waypoint* wpt;
943   double lat;
944   double lon;
945   double heading;
946   apt->getParking(gateId, &lat, &lon, &heading);
947   heading += 180.0;
948   if (heading > 360)
949     heading -= 360; 
950
951   // Erase all existing waypoints.
952   // wpt_vector_iterator i= waypoints.begin();
953   //while(waypoints.begin() != waypoints.end())
954   //  {      
955   //    delete *(i);
956   //    waypoints.erase(i);
957   //  }
958   //resetWaypoints();
959   // And finally one more named "END"
960   wpt = new waypoint;
961   wpt->name      = "END"; //wpt_node->getStringValue("name", "END");
962   wpt->latitude  = lat;
963   wpt->longitude = lon;
964   wpt->altitude  = 19;
965   wpt->speed     = 15; 
966   wpt->crossat   = -10000;
967   wpt->gear_down = true;
968   wpt->flaps_down= true;
969   wpt->finished  = false;
970   wpt->on_ground = true;
971   waypoints.push_back(wpt);
972   //waypoints.push_back(wpt);
973   //waypoints.push_back(wpt);  // add one more to prevent a segfault. 
974   //wpt_iterator = waypoints.begin();
975   //wpt_iterator++;
976 }