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