1 /******************************************************************************
2 * AIFlightPlanCreate.cxx
3 * Written by Durk Talsma, started May, 2004.
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.
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.
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.
19 **************************************************************************/
20 #include "AIFlightPlan.hxx"
21 #include <simgear/math/sg_geodesy.hxx>
22 #include <Airports/runways.hxx>
24 #include <Environment/environment_mgr.hxx>
25 #include <Environment/environment.hxx>
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)
32 * This is the top-level function, and the only one that is publicly available.
37 // Check lat/lon values during initialization;
38 void FGAIFlightPlan::create(FGAirport *dep, FGAirport *arr, int legNr,
39 double alt, double speed, double latitude,
40 double longitude, bool firstFlight,double radius,
41 const string& fltType, const string& aircraftType,
42 const string& airline)
44 int currWpt = wpt_iterator - waypoints.begin();
48 createPushBack(firstFlight,dep, latitude, longitude,
49 radius, fltType, aircraftType, airline);
52 createTaxi(firstFlight, 1, dep, latitude, longitude,
53 radius, fltType, aircraftType, airline);
56 createTakeOff(firstFlight, dep, speed, fltType);
59 createClimb(firstFlight, dep, speed, alt, fltType);
62 createCruise(firstFlight, dep,arr, latitude, longitude, speed, alt, fltType);
65 createDecent(arr, fltType);
71 createTaxi(false, 2, arr, latitude, longitude, radius,
72 fltType, aircraftType, airline);
75 createParking(arr, radius);
79 SG_LOG(SG_INPUT, SG_ALERT, "AIFlightPlan::create() attempting to create unknown leg"
80 " this is probably an internal program error");
82 wpt_iterator = waypoints.begin()+currWpt;
86 /*******************************************************************
88 * initialize the Aircraft at the parking location
89 ******************************************************************/
90 void FGAIFlightPlan::createPushBack(bool firstFlight, FGAirport *dep,
94 const string& fltType,
95 const string& aircraftType,
96 const string& airline)
105 //int currWpt = wpt_iterator - waypoints.begin();
106 // Erase all existing waypoints.
109 // We only need to get a valid parking if this is the first leg.
110 // Otherwise use the current aircraft position.
113 if (!(dep->getDynamics()->getAvailableParking(&lat, &lon,
116 aircraftType, airline)))
118 SG_LOG(SG_INPUT, SG_ALERT, "Could not find parking for a " <<
120 " of flight type " << fltType <<
121 " of airline " << airline <<
122 " at airport " << dep->getId());
128 dep->getDynamics()->getParking(gateId, &lat, &lon, &heading);
133 waypoint *wpt = new waypoint;
136 wpt->longitude = lon;
137 wpt->altitude = dep->getElevation();
139 wpt->crossat = -10000;
140 wpt->gear_down = true;
141 wpt->flaps_down= true;
142 wpt->finished = false;
143 wpt->on_ground = true;
145 waypoints.push_back(wpt);
147 geo_direct_wgs_84 ( 0, lat, lon, heading,
149 &lat2, &lon2, &az2 );
152 wpt->latitude = lat2;
153 wpt->longitude = lon2;
154 wpt->altitude = dep->getElevation();
156 wpt->crossat = -10000;
157 wpt->gear_down = true;
158 wpt->flaps_down= true;
159 wpt->finished = false;
160 wpt->on_ground = true;
162 waypoints.push_back(wpt);
163 geo_direct_wgs_84 ( 0, lat, lon, heading,
165 &lat2, &lon2, &az2 );
167 wpt->name = "taxiStart";
168 wpt->latitude = lat2;
169 wpt->longitude = lon2;
170 wpt->altitude = dep->getElevation();
172 wpt->crossat = -10000;
173 wpt->gear_down = true;
174 wpt->flaps_down= true;
175 wpt->finished = false;
176 wpt->on_ground = true;
178 waypoints.push_back(wpt);
181 /*******************************************************************
183 * initialize the Aircraft at the parking location
184 ******************************************************************/
185 void FGAIFlightPlan::createTaxi(bool firstFlight, int direction,
186 FGAirport *apt, double latitude, double longitude,
187 double radius, const string& fltType,
188 const string& acType, const string& airline)
192 double lat2, lon2, az2;
195 int nrWaypointsToSkip;
199 // If this function is called during initialization,
200 // make sure we obtain a valid gate ID first
201 // and place the model at the location of the gate.
204 if (!(apt->getDynamics()->getAvailableParking(&lat, &lon,
209 SG_LOG(SG_INPUT, SG_WARN, "Could not find parking for a " <<
211 " of flight type " << fltType <<
212 " of airline " << airline <<
213 " at airport " << apt->getId());
215 //waypoint *wpt = new waypoint;
216 //wpt->name = "park";
217 //wpt->latitude = lat;
218 //wpt->longitude = lon;
219 //wpt->altitude = apt->getElevation();
221 //wpt->crossat = -10000;
222 //wpt->gear_down = true;
223 //wpt->flaps_down= true;
224 //wpt->finished = false;
225 //wpt->on_ground = true;
226 //waypoints.push_back(wpt);
228 string rwyClass = getRunwayClassFromTrafficType(fltType);
229 apt->getDynamics()->getActiveRunway(rwyClass, 1, activeRunway);
230 if (!(globals->get_runways()->search(apt->getId(),
234 SG_LOG(SG_INPUT, SG_ALERT, "Failed to find runway " <<
236 " at airport " << apt->getId() << " of class " << rwyClass << " (1)");
240 // Determine the beginning of he runway
241 heading = rwy._heading;
242 double azimuth = heading + 180.0;
243 while ( azimuth >= 360.0 ) { azimuth -= 360.0; }
244 geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, azimuth,
245 rwy._length * SG_FEET_TO_METER * 0.5 - 5.0,
246 &lat2, &lon2, &az2 );
248 if (apt->getDynamics()->getGroundNetwork()->exists())
251 int runwayId = apt->getDynamics()->getGroundNetwork()->findNearestNode(lat2,
255 // A negative gateId indicates an overflow parking, use a
256 // fallback mechanism for this.
257 // Starting from gate 0 in this case is a bit of a hack
258 // which requires a more proper solution later on.
261 taxiRoute = new FGTaxiRoute;
263 *taxiRoute = apt->getDynamics()->getGroundNetwork()->findShortestRoute(gateId,
266 *taxiRoute = apt->getDynamics()->getGroundNetwork()->findShortestRoute(0, runwayId);
269 if (taxiRoute->empty()) {
270 //Add the runway startpoint;
272 wpt->name = "Airport Center";
273 wpt->latitude = latitude;
274 wpt->longitude = longitude;
275 wpt->altitude = apt->getElevation();
277 wpt->crossat = -10000;
278 wpt->gear_down = true;
279 wpt->flaps_down= true;
280 wpt->finished = false;
281 wpt->on_ground = true;
283 waypoints.push_back(wpt);
285 //Add the runway startpoint;
287 wpt->name = "Runway Takeoff";
288 wpt->latitude = lat2;
289 wpt->longitude = lon2;
290 wpt->altitude = apt->getElevation();
292 wpt->crossat = -10000;
293 wpt->gear_down = true;
294 wpt->flaps_down= true;
295 wpt->finished = false;
296 wpt->on_ground = true;
298 waypoints.push_back(wpt);
302 bool isPushBackPoint = false;
304 // If this is called during initialization, randomly
305 // skip a number of waypoints to get a more realistic
307 isPushBackPoint = true;
308 int nrWaypoints = taxiRoute->size();
309 nrWaypointsToSkip = rand() % nrWaypoints;
310 // but make sure we always keep two active waypoints
311 // to prevent a segmentation fault
312 for (int i = 0; i < nrWaypointsToSkip-2; i++) {
313 isPushBackPoint = false;
314 taxiRoute->next(&node);
317 //chop off the first two waypoints, because
318 // those have already been created
319 // by create pushback
320 int size = taxiRoute->size();
322 taxiRoute->next(&node);
323 taxiRoute->next(&node);
327 while(taxiRoute->next(&node, &route))
329 //FGTaxiNode *tn = apt->getDynamics()->getGroundNetwork()->findSegment(node)->getEnd();
331 snprintf (buffer, 10, "%d", node);
332 FGTaxiNode *tn = apt->getDynamics()->getGroundNetwork()->findNode(node);
335 wpt->name = string(buffer); // fixme: should be the name of the taxiway
336 wpt->latitude = tn->getLatitude();
337 wpt->longitude = tn->getLongitude();
338 // Elevation is currently disregarded when on_ground is true
339 // because the AIModel obtains a periodic ground elevation estimate.
340 wpt->altitude = apt->getElevation();
341 if (isPushBackPoint) {
343 isPushBackPoint = false;
348 wpt->crossat = -10000;
349 wpt->gear_down = true;
350 wpt->flaps_down= true;
351 wpt->finished = false;
352 wpt->on_ground = true;
353 wpt->routeIndex = route;
354 waypoints.push_back(wpt);
357 // finally, rewind the taxiRoute object to the point where we started
358 // generating the Flightplan, for AI use.
359 // This is a bit tricky, because the
362 for (int i = 0; i < nrWaypointsToSkip-1; i++) {
363 taxiRoute->next(&node);
366 int size = taxiRoute->size();
368 //taxiRoute->next(&node);
369 //taxiRoute->next(&node);
370 //taxiRoute->next(&node);
373 } // taxiRoute not empty
377 // This is the fallback mechanism, in case no ground network is available
378 //Add the runway startpoint;
380 wpt->name = "Airport Center";
381 wpt->latitude = apt->getLatitude();
382 wpt->longitude = apt->getLongitude();
383 wpt->altitude = apt->getElevation();
385 wpt->crossat = -10000;
386 wpt->gear_down = true;
387 wpt->flaps_down= true;
388 wpt->finished = false;
389 wpt->on_ground = true;
391 waypoints.push_back(wpt);
393 //Add the runway startpoint;
395 wpt->name = "Runway Takeoff";
396 wpt->latitude = lat2;
397 wpt->longitude = lon2;
398 wpt->altitude = apt->getElevation();
400 wpt->crossat = -10000;
401 wpt->gear_down = true;
402 wpt->flaps_down= true;
403 wpt->finished = false;
404 wpt->on_ground = true;
406 waypoints.push_back(wpt);
411 apt->getDynamics()->getAvailableParking(&lat, &lon, &heading,
412 &gateId, radius, fltType,
415 double lat3 = (*(waypoints.end()-1))->latitude;
416 double lon3 = (*(waypoints.end()-1))->longitude;
417 //cerr << (*(waypoints.end()-1))->name << endl;
419 // Find a route from runway end to parking/gate.
420 if (apt->getDynamics()->getGroundNetwork()->exists())
423 int runwayId = apt->getDynamics()->getGroundNetwork()->findNearestNode(lat3,
425 // A negative gateId indicates an overflow parking, use a
426 // fallback mechanism for this.
427 // Starting from gate 0 is a bit of a hack...
430 taxiRoute = new FGTaxiRoute;
432 *taxiRoute = apt->getDynamics()->getGroundNetwork()->findShortestRoute(runwayId,
435 *taxiRoute = apt->getDynamics()->getGroundNetwork()->findShortestRoute(runwayId, 0);
438 // No route found: go from gate directly to runway
439 if (taxiRoute->empty()) {
440 //Add the runway startpoint;
442 wpt->name = "Airport Center";
443 wpt->latitude = latitude;
444 wpt->longitude = longitude;
445 wpt->altitude = apt->getElevation();
447 wpt->crossat = -10000;
448 wpt->gear_down = true;
449 wpt->flaps_down= true;
450 wpt->finished = false;
451 wpt->on_ground = true;
453 waypoints.push_back(wpt);
455 //Add the runway startpoint;
457 wpt->name = "Runway Takeoff";
458 wpt->latitude = lat3;
459 wpt->longitude = lon3;
460 wpt->altitude = apt->getElevation();
462 wpt->crossat = -10000;
463 wpt->gear_down = true;
464 wpt->flaps_down= true;
465 wpt->finished = false;
466 wpt->on_ground = true;
468 waypoints.push_back(wpt);
472 int size = taxiRoute->size();
473 // Omit the last two waypoints, as
474 // those are created by createParking()
476 for (int i = 0; i < size-2; i++)
478 taxiRoute->next(&node, &route);
480 snprintf (buffer, 10, "%d", node);
481 //FGTaxiNode *tn = apt->getDynamics()->getGroundNetwork()->findNode(node);
482 FGTaxiNode *tn = apt->getDynamics()->getGroundNetwork()->findNode(node);
484 //wpt->name = "taxiway"; // fixme: should be the name of the taxiway
485 wpt->name = string(buffer);// fixme: should be the name of the taxiway
486 wpt->latitude = tn->getLatitude();
487 wpt->longitude = tn->getLongitude();
488 wpt->altitude = apt->getElevation();
490 wpt->crossat = -10000;
491 wpt->gear_down = true;
492 wpt->flaps_down= true;
493 wpt->finished = false;
494 wpt->on_ground = true;
495 wpt->routeIndex = route;
496 waypoints.push_back(wpt);
498 //taxiRoute->first();
499 //taxiRoute->next(&node);
504 // Use a fallback mechanism in case no ground network is available
505 // obtain the location of the gate entrance point
509 geo_direct_wgs_84 ( 0, lat, lon, heading,
511 &lat2, &lon2, &az2 );
513 wpt->name = "Airport Center";
514 wpt->latitude = apt->getLatitude();
515 wpt->longitude = apt->getLongitude();
516 wpt->altitude = apt->getElevation();
518 wpt->crossat = -10000;
519 wpt->gear_down = true;
520 wpt->flaps_down= true;
521 wpt->finished = false;
522 wpt->on_ground = true;
524 waypoints.push_back(wpt);
527 wpt->name = "Begin Parking"; //apt->getId(); //wpt_node->getStringValue("name", "END");
528 wpt->latitude = lat2;
529 wpt->longitude = lon2;
530 wpt->altitude = apt->getElevation();
532 wpt->crossat = -10000;
533 wpt->gear_down = true;
534 wpt->flaps_down= true;
535 wpt->finished = false;
536 wpt->on_ground = true;
538 waypoints.push_back(wpt);
544 apt->getDynamics()->getParking(gateId, &lat, &lon, &heading);
550 wpt->name = "END"; //wpt_node->getStringValue("name", "END");
552 wpt->longitude = lon;
555 wpt->crossat = -10000;
556 wpt->gear_down = true;
557 wpt->flaps_down= true;
558 wpt->finished = false;
559 wpt->on_ground = true;
561 waypoints.push_back(wpt);
567 /*******************************************************************
569 * initialize the Aircraft at the parking location
570 ******************************************************************/
571 void FGAIFlightPlan::createTakeOff(bool firstFlight, FGAirport *apt, double speed, const string &fltType)
575 double lat2, lon2, az2;
578 // Get the current active runway, based on code from David Luff
579 // This should actually be unified and extended to include
580 // Preferential runway use schema's
584 string rwyClass = getRunwayClassFromTrafficType(fltType);
585 apt->getDynamics()->getActiveRunway(rwyClass, 1, activeRunway);
586 if (!(globals->get_runways()->search(apt->getId(),
590 SG_LOG(SG_INPUT, SG_ALERT, "Failed to find runway " <<
592 " at airport " << apt->getId()<< " of class " << rwyClass << " (2)");
596 // Acceleration point, 105 meters into the runway,
597 heading = rwy._heading;
598 double azimuth = heading + 180.0;
599 while ( azimuth >= 360.0 ) { azimuth -= 360.0; }
600 geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, azimuth,
601 rwy._length * SG_FEET_TO_METER * 0.5 - 105.0,
602 &lat2, &lon2, &az2 );
605 wpt->latitude = lat2;
606 wpt->longitude = lon2;
607 wpt->altitude = apt->getElevation();
609 wpt->crossat = -10000;
610 wpt->gear_down = true;
611 wpt->flaps_down= true;
612 wpt->finished = false;
613 wpt->on_ground = true;
615 waypoints.push_back(wpt);
621 //Start Climbing to 3000 ft. Let's do this
622 // at the center of the runway for now:
624 geo_direct_wgs_84 ( 0, lat, lon, heading,
625 2560 * SG_FEET_TO_METER,
626 &lat2, &lon2, &az2 );
630 wpt->latitude = rwy._lat;
631 wpt->longitude = rwy._lon;
632 wpt->altitude = apt->getElevation()+1000;
634 wpt->crossat = -10000;
635 wpt->gear_down = true;
636 wpt->flaps_down= true;
637 wpt->finished = false;
638 wpt->on_ground = false;
640 waypoints.push_back(wpt);
643 geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, heading,
644 rwy._length * SG_FEET_TO_METER,
645 &lat2, &lon2, &az2 );
648 wpt->name = "3000 ft";
649 wpt->latitude = lat2;
650 wpt->longitude = lon2;
651 wpt->altitude = apt->getElevation()+3000;
653 wpt->crossat = -10000;
654 wpt->gear_down = true;
655 wpt->flaps_down= true;
656 wpt->finished = false;
657 wpt->on_ground = false;
659 waypoints.push_back(wpt);
661 // Finally, add two more waypoints, so that aircraft will remain under
662 // Tower control until they have reached the 3000 ft climb point
665 geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, heading,
667 &lat2, &lon2, &az2 );
671 wpt->name = "5000 ft";
672 wpt->latitude = lat2;
673 wpt->longitude = lon2;
674 wpt->altitude = apt->getElevation()+5000;
676 wpt->crossat = -10000;
677 wpt->gear_down = true;
678 wpt->flaps_down= true;
679 wpt->finished = false;
680 wpt->on_ground = false;
682 waypoints.push_back(wpt);
684 // geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, heading,
686 // &lat2, &lon2, &az2 );
687 // wpt = new waypoint;
688 // wpt->name = "5100 ft";
689 // wpt->latitude = lat2;
690 // wpt->longitude = lon2;
691 // wpt->altitude = apt->getElevation()+5100;
692 // wpt->speed = speed;
693 // wpt->crossat = -10000;
694 // wpt->gear_down = true;
695 // wpt->flaps_down= true;
696 // wpt->finished = false;
697 // wpt->on_ground = false;
698 // wpt->routeIndex = 0;
699 // waypoints.push_back(wpt);
702 /*******************************************************************
704 * initialize the Aircraft at the parking location
705 ******************************************************************/
706 void FGAIFlightPlan::createClimb(bool firstFlight, FGAirport *apt, double speed, double alt, const string &fltType)
710 double lat2, lon2, az2;
718 string rwyClass = getRunwayClassFromTrafficType(fltType);
719 apt->getDynamics()->getActiveRunway(rwyClass, 1, activeRunway);
720 if (!(globals->get_runways()->search(apt->getId(),
724 SG_LOG(SG_INPUT, SG_ALERT, "Failed to find runway " <<
726 " at airport " << apt->getId()<< " of class " << rwyClass << " (3)");
732 heading = rwy._heading;
733 double azimuth = heading + 180.0;
734 while ( azimuth >= 360.0 ) { azimuth -= 360.0; }
735 //cerr << "Creating climb at : " << rwy._id << " " << rwy._rwy_no << endl;
736 geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, heading,
738 &lat2, &lon2, &az2 );
740 wpt->name = "10000ft climb";
741 wpt->latitude = lat2;
742 wpt->longitude = lon2;
743 wpt->altitude = 10000;
745 wpt->crossat = -10000;
746 wpt->gear_down = true;
747 wpt->flaps_down= true;
748 wpt->finished = false;
749 wpt->on_ground = false;
751 waypoints.push_back(wpt);
754 geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, heading,
756 &lat2, &lon2, &az2 );
758 wpt->name = "18000ft climb";
759 wpt->latitude = lat2;
760 wpt->longitude = lon2;
761 wpt->altitude = 18000;
763 wpt->crossat = -10000;
764 wpt->gear_down = true;
765 wpt->flaps_down= true;
766 wpt->finished = false;
767 wpt->on_ground = false;
769 waypoints.push_back(wpt);
773 // /*******************************************************************
775 // * initialize the Aircraft at the parking location
776 // ******************************************************************/
777 // void FGAIFlightPlan::createCruise(bool firstFlight, FGAirport *dep,
778 // FGAirport *arr, double latitude,
779 // double longitude, double speed,
782 // double wind_speed;
783 // double wind_heading;
785 // double lat, lon, az;
786 // double lat2, lon2, az2;
790 // wpt = new waypoint;
791 // wpt->name = "Cruise"; //wpt_node->getStringValue("name", "END");
792 // wpt->latitude = latitude;
793 // wpt->longitude = longitude;
794 // wpt->altitude = alt;
795 // wpt->speed = speed;
796 // wpt->crossat = -10000;
797 // wpt->gear_down = false;
798 // wpt->flaps_down= false;
799 // wpt->finished = false;
800 // wpt->on_ground = false;
801 // waypoints.push_back(wpt);
804 // // should be changed dynamically to allow "gen" and "mil"
805 // arr->getDynamics()->getActiveRunway("com", 2, activeRunway);
806 // if (!(globals->get_runways()->search(arr->getId(),
810 // SG_LOG(SG_INPUT, SG_ALERT, "Failed to find runway " <<
812 // " at airport " << arr->getId());
815 // heading = rwy._heading;
816 // azimuth = heading + 180.0;
817 // while ( azimuth >= 360.0 ) { azimuth -= 360.0; }
820 // geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, azimuth,
822 // &lat2, &lon2, &az2 );
823 // wpt = new waypoint;
824 // wpt->name = "BOD";
825 // wpt->latitude = lat2;
826 // wpt->longitude = lon2;
827 // wpt->altitude = alt;
828 // wpt->speed = speed;
829 // wpt->crossat = alt;
830 // wpt->gear_down = false;
831 // wpt->flaps_down= false;
832 // wpt->finished = false;
833 // wpt->on_ground = false;
834 // waypoints.push_back(wpt);
837 /*******************************************************************
839 * initialize the Aircraft at the parking location
840 ******************************************************************/
841 void FGAIFlightPlan::createDecent(FGAirport *apt, const string &fltType)
844 // Ten thousand ft. Slowing down to 240 kts
847 double lat2, lon2, az2;
852 //Beginning of Decent
854 // allow "mil" and "gen" as well
855 string rwyClass = getRunwayClassFromTrafficType(fltType);
856 apt->getDynamics()->getActiveRunway(rwyClass, 2, activeRunway);
857 if (!(globals->get_runways()->search(apt->getId(),
861 SG_LOG(SG_INPUT, SG_ALERT, "Failed to find runway " <<
863 " at airport " << apt->getId()<< " of class " << rwyClass << " (4)");
867 heading = rwy._heading;
868 azimuth = heading + 180.0;
869 while ( azimuth >= 360.0 ) { azimuth -= 360.0; }
870 geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, azimuth,
872 &lat2, &lon2, &az2 );
875 wpt->name = "Dec 10000ft"; //wpt_node->getStringValue("name", "END");
876 wpt->latitude = lat2;
877 wpt->longitude = lon2;
878 wpt->altitude = apt->getElevation();
880 wpt->crossat = 10000;
881 wpt->gear_down = false;
882 wpt->flaps_down= false;
883 wpt->finished = false;
884 wpt->on_ground = false;
886 waypoints.push_back(wpt);
888 // Three thousand ft. Slowing down to 160 kts
889 geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, azimuth,
891 &lat2, &lon2, &az2 );
893 wpt->name = "DEC 3000ft"; //wpt_node->getStringValue("name", "END");
894 wpt->latitude = lat2;
895 wpt->longitude = lon2;
896 wpt->altitude = apt->getElevation();
899 wpt->gear_down = true;
900 wpt->flaps_down= true;
901 wpt->finished = false;
902 wpt->on_ground = false;
904 waypoints.push_back(wpt);
906 /*******************************************************************
908 * initialize the Aircraft at the parking location
909 ******************************************************************/
910 void FGAIFlightPlan::createLanding(FGAirport *apt)
912 // Ten thousand ft. Slowing down to 150 kts
915 double lat2, lon2, az2;
921 heading = rwy._heading;
922 azimuth = heading + 180.0;
923 while ( azimuth >= 360.0 ) { azimuth -= 360.0; }
926 geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, azimuth,
927 rwy._length*0.45 * SG_FEET_TO_METER,
928 &lat2, &lon2, &az2 );
930 wpt->name = "Threshold"; //wpt_node->getStringValue("name", "END");
931 wpt->latitude = lat2;
932 wpt->longitude = lon2;
933 wpt->altitude = apt->getElevation();
935 wpt->crossat = apt->getElevation();
936 wpt->gear_down = true;
937 wpt->flaps_down= true;
938 wpt->finished = false;
939 wpt->on_ground = true;
941 waypoints.push_back(wpt);
943 //Full stop at the runway centerpoint
944 geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, azimuth,
946 &lat2, &lon2, &az2 );
948 wpt->name = "Center"; //wpt_node->getStringValue("name", "END");
949 wpt->latitude = rwy._lat;
950 wpt->longitude = rwy._lon;
951 wpt->altitude = apt->getElevation();
953 wpt->crossat = -10000;
954 wpt->gear_down = true;
955 wpt->flaps_down= true;
956 wpt->finished = false;
957 wpt->on_ground = true;
959 waypoints.push_back(wpt);
961 geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, heading,
962 rwy._length*0.45 * SG_FEET_TO_METER,
963 &lat2, &lon2, &az2 );
965 wpt->name = "Threshold"; //wpt_node->getStringValue("name", "END");
966 wpt->latitude = lat2;
967 wpt->longitude = lon2;
968 wpt->altitude = apt->getElevation();
970 wpt->crossat = apt->getElevation();
971 wpt->gear_down = true;
972 wpt->flaps_down= true;
973 wpt->finished = false;
974 wpt->on_ground = true;
976 waypoints.push_back(wpt);
979 /*******************************************************************
981 * initialize the Aircraft at the parking location
982 ******************************************************************/
983 void FGAIFlightPlan::createParking(FGAirport *apt, double radius)
990 apt->getDynamics()->getParking(gateId, &lat, &lon, &heading);
994 geo_direct_wgs_84 ( 0, lat, lon, heading,
996 &lat2, &lon2, &az2 );
998 wpt->name = "taxiStart";
999 wpt->latitude = lat2;
1000 wpt->longitude = lon2;
1001 wpt->altitude = apt->getElevation();
1003 wpt->crossat = -10000;
1004 wpt->gear_down = true;
1005 wpt->flaps_down= true;
1006 wpt->finished = false;
1007 wpt->on_ground = true;
1008 wpt->routeIndex = 0;
1009 waypoints.push_back(wpt);
1010 geo_direct_wgs_84 ( 0, lat, lon, heading,
1012 &lat2, &lon2, &az2 );
1014 wpt->name = "taxiStart";
1015 wpt->latitude = lat2;
1016 wpt->longitude = lon2;
1017 wpt->altitude = apt->getElevation();
1019 wpt->crossat = -10000;
1020 wpt->gear_down = true;
1021 wpt->flaps_down= true;
1022 wpt->finished = false;
1023 wpt->on_ground = true;
1024 wpt->routeIndex = 0;
1025 waypoints.push_back(wpt);
1028 wpt->name = "END"; //wpt_node->getStringValue("name", "END");
1029 wpt->latitude = lat;
1030 wpt->longitude = lon;
1031 wpt->altitude = apt->getElevation();
1033 wpt->crossat = -10000;
1034 wpt->gear_down = true;
1035 wpt->flaps_down= true;
1036 wpt->finished = false;
1037 wpt->on_ground = true;
1038 wpt->routeIndex = 0;
1039 waypoints.push_back(wpt);
1044 * @param fltType a string describing the type of
1045 * traffic, normally used for gate assignments
1046 * @return a converted string that gives the runway
1047 * preference schedule to be used at aircraft having
1048 * a preferential runway schedule implemented (i.e.
1049 * having a rwyprefs.xml file
1051 * Currently valid traffic types for gate assignment:
1052 * - gate (commercial gate)
1053 * - cargo (commercial gargo),
1054 * - ga (general aviation) ,
1055 * - ul (ultralight),
1056 * - mil-fighter (military - fighter),
1057 * - mil-transport (military - transport)
1059 * Valid runway classes:
1060 * - com (commercial traffic: jetliners, passenger and cargo)
1061 * - gen (general aviation)
1062 * - ul (ultralight: I can imagine that these may share a runway with ga on some airports)
1063 * - mil (all military traffic)
1065 string FGAIFlightPlan::getRunwayClassFromTrafficType(string fltType)
1067 if ((fltType == "gate") || (fltType == "cargo")) {
1068 return string("com");
1070 if (fltType == "ga") {
1071 return string ("gen");
1073 if (fltType == "ul") {
1074 return string("ul");
1076 if ((fltType == "mil-fighter") || (fltType == "mil-transport")) {
1077 return string("mil");