30
29
* dynamically create a flight plan for AI traffic, based on data provided by the
31
30
* Traffic Manager, when reading a filed flightplan failes. (DT, 2004/07/10)
33
* This is the top-level function, and the only one that publicly available.
32
* This is the top-level function, and the only one that is publicly available.
38
37
// 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)
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)
43
44
int currWpt = wpt_iterator - waypoints.begin();
47
//cerr << "Creating Push_Back" << endl;
48
createPushBack(firstFlight,dep, latitude, longitude, radius, fltType, aircraftType, airline);
49
//cerr << "Done" << endl;
48
createPushBack(firstFlight,dep, latitude, longitude,
49
radius, fltType, aircraftType, airline);
52
//cerr << "Creating Taxi" << endl;
53
createTaxi(firstFlight, 1, dep, latitude, longitude, radius, fltType, aircraftType, airline);
52
createTaxi(firstFlight, 1, dep, latitude, longitude,
53
radius, fltType, aircraftType, airline);
56
//cerr << "Creating TAkeoff" << endl;
57
56
createTakeOff(firstFlight, dep, speed);
60
//cerr << "Creating Climb" << endl;
61
59
createClimb(firstFlight, dep, speed, alt);
64
//cerr << "Creating Cruise" << endl;
65
62
createCruise(firstFlight, dep,arr, latitude, longitude, speed, alt);
68
//cerr << "Creating Decent" << endl;
72
//cerr << "Creating Landing" << endl;
73
68
createLanding(arr);
76
//cerr << "Creating Taxi 2" << endl;
77
createTaxi(false, 2, arr, latitude, longitude, radius, fltType, aircraftType, airline);
71
createTaxi(false, 2, arr, latitude, longitude, radius,
72
fltType, aircraftType, airline);
80
//cerr << "Creating Parking" << endl;
75
createParking(arr, radius);
85
cerr << "Unknown case: " << legNr << endl;
79
SG_LOG(SG_INPUT, SG_ALERT, "AIFlightPlan::create() attempting to create unknown leg"
80
" this is probably an internal program error");
87
82
wpt_iterator = waypoints.begin()+currWpt;
115
110
// Otherwise use the current aircraft position.
118
if (!(dep->getAvailableParking(&lat, &lon, &heading, &gateId, radius, fltType, aircraftType, airline)))
120
cerr << "Could not find parking " << endl;
113
if (!(dep->getDynamics()->getAvailableParking(&lat, &lon,
116
aircraftType, airline)))
118
SG_LOG(SG_INPUT, SG_WARN, "Could not find parking for a " <<
120
" of flight type " << fltType <<
121
" of airline " << airline <<
122
" at airport " << dep->getId());
125
dep->getParking(gateId, &lat, &lon, &heading);
128
//heading = getHeading();
127
dep->getDynamics()->getParking(gateId, &lat, &lon, &heading);
130
129
heading += 180.0;
131
130
if (heading > 360)
174
173
wpt->flaps_down= true;
175
174
wpt->finished = false;
176
175
wpt->on_ground = true;
177
waypoints.push_back(wpt);
176
waypoints.push_back(wpt);
182
179
/*******************************************************************
183
180
* createCreate Taxi.
184
181
* initialize the Aircraft at the parking location
185
182
******************************************************************/
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)
183
void FGAIFlightPlan::createTaxi(bool firstFlight, int direction,
184
FGAirport *apt, double latitude, double longitude,
185
double radius, const string& fltType,
186
const string& acType, const string& airline)
188
188
double wind_speed;
189
189
double wind_heading;
192
191
double lat, lon, az;
193
192
double lat2, lon2, az2;
197
// Erase all existing waypoints.
198
// wpt_vector_iterator i= waypoints.begin();
200
//int currWpt = wpt_iterator - waypoints.begin();
197
// If this function is called during initialization,
198
// make sure we obtain a valid gate ID first
199
// and place the model at the location of the gate.
202
if (!(apt->getDynamics()->getAvailableParking(&lat, &lon,
207
SG_LOG(SG_INPUT, SG_WARN, "Could not find parking for a " <<
209
" of flight type " << fltType <<
210
" of airline " << airline <<
211
" at airport " << apt->getId());
213
//waypoint *wpt = new waypoint;
214
//wpt->name = "park";
215
//wpt->latitude = lat;
216
//wpt->longitude = lon;
217
//wpt->altitude = apt->getElevation();
219
//wpt->crossat = -10000;
220
//wpt->gear_down = true;
221
//wpt->flaps_down= true;
222
//wpt->finished = false;
223
//wpt->on_ground = true;
224
//waypoints.push_back(wpt);
204
226
// "NOTE: this is currently fixed to "com" for commercial traffic
205
227
// Should be changed to be used dynamically to allow "gen" and "mil"
207
apt->getActiveRunway("com", 1, activeRunway);
229
apt->getDynamics()->getActiveRunway("com", 1, activeRunway);
208
230
if (!(globals->get_runways()->search(apt->getId(),
212
cout << "Failed to find runway for " << apt->getId() << endl;
213
// Hmm, how do we handle a potential error like this?
217
//apt->getActiveRunway(string("com"), 1, test);
234
SG_LOG(SG_INPUT, SG_ALERT, "Failed to find runway " <<
236
" at airport " << apt->getId());
240
// Determine the beginning of he runway
220
241
heading = rwy._heading;
221
242
double azimuth = heading + 180.0;
222
243
while ( azimuth >= 360.0 ) { azimuth -= 360.0; }
223
244
geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, azimuth,
224
245
rwy._length * SG_FEET_TO_METER * 0.5 - 5.0,
225
246
&lat2, &lon2, &az2 );
226
if (apt->getGroundNetwork()->exists())
248
if (apt->getDynamics()->getGroundNetwork()->exists())
229
int runwayId = apt->getGroundNetwork()->findNearestNode(lat2, lon2);
230
//int currId = apt->getGroundNetwork()->findNearestNode(latitude,longitude);
251
int runwayId = apt->getDynamics()->getGroundNetwork()->findNearestNode(lat2,
233
255
// A negative gateId indicates an overflow parking, use a
234
256
// fallback mechanism for this.
235
// Starting from gate 0 is a bit of a hack...
257
// Starting from gate 0 in this case is a bit of a hack
258
// which requires a more proper solution later on.
236
259
FGTaxiRoute route;
238
route = apt->getGroundNetwork()->findShortestRoute(gateId, runwayId);
261
route = apt->getDynamics()->getGroundNetwork()->findShortestRoute(gateId,
240
route = apt->getGroundNetwork()->findShortestRoute(0, runwayId);
264
route = apt->getDynamics()->getGroundNetwork()->findShortestRoute(0, runwayId);
241
265
intVecIterator i;
242
//cerr << "creating route : ";
243
// No route found: go from gate directly to runway
244
267
if (route.empty()) {
245
268
//Add the runway startpoint;
246
269
wpt = new waypoint;
298
bool isPushBackPoint = false;
300
// If this is called during initialization, randomly
301
// skip a number of waypoints to get a more realistic
303
isPushBackPoint = true;
304
int nrWaypoints = route.size();
305
int nrWaypointsToSkip = rand() % nrWaypoints;
306
// but make sure we always keep two active waypoints
307
// to prevent a segmentation fault
308
for (int i = 0; i < nrWaypointsToSkip-2; i++) {
309
isPushBackPoint = false;
314
//chop off the first two waypoints, because
315
// those have already been created
316
// by create pushback
317
int size = route.size();
275
323
while(route.next(&node))
278
//cerr << "Creating Node: " << node << endl;
279
FGTaxiNode *tn = apt->getGroundNetwork()->findNode(node);
325
FGTaxiNode *tn = apt->getDynamics()->getGroundNetwork()->findNode(node);
280
326
//ids.pop_back();
281
327
wpt = new waypoint;
282
328
wpt->name = "taxiway"; // fixme: should be the name of the taxiway
283
329
wpt->latitude = tn->getLatitude();
284
330
wpt->longitude = tn->getLongitude();
285
wpt->altitude = apt->getElevation(); // should maybe be tn->elev too
331
// Elevation is currently disregarded when on_ground is true
332
// because the AIModel obtains a periodic ground elevation estimate.
333
wpt->altitude = apt->getElevation();
334
if (isPushBackPoint) {
336
isPushBackPoint = false;
287
341
wpt->crossat = -10000;
288
342
wpt->gear_down = true;
289
343
wpt->flaps_down= true;
324
378
wpt->finished = false;
325
379
wpt->on_ground = true;
326
380
waypoints.push_back(wpt);
327
//wpt = new waypoint;
328
//wpt->finished = false;
329
//waypoints.push_back(wpt); // add one more to prevent a segfault.
332
383
else // Landing taxi
335
// "NOTE: this is currently fixed to "com" for commercial traffic
336
// Should be changed to be used dynamically to allow "gen" and "mil"
338
//apt->getActiveRunway("com", 1, name);
339
//if (!(globals->get_runways()->search(apt->getId(),
343
//cout << "Failed to find runway for " << apt->getId() << endl;
344
// Hmm, how do we handle a potential error like this?
348
//apt->getActiveRunway(string("com"), 1, test);
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);
361
geo_direct_wgs_84 ( 0, lat, lon, heading,
363
&lat2, &lon2, &az2 );
385
apt->getDynamics()->getAvailableParking(&lat, &lon, &heading,
386
&gateId, radius, fltType,
364
389
double lat3 = (*(waypoints.end()-1))->latitude;
365
390
double lon3 = (*(waypoints.end()-1))->longitude;
366
cerr << (*(waypoints.end()-1))->name << endl;
367
if (apt->getGroundNetwork()->exists())
391
//cerr << (*(waypoints.end()-1))->name << endl;
393
// Find a route from runway end to parking/gate.
394
if (apt->getDynamics()->getGroundNetwork()->exists())
370
int runwayId = apt->getGroundNetwork()->findNearestNode(lat3, lon3);
371
//int currId = apt->getGroundNetwork()->findNearestNode(latitude,longitude);
397
int runwayId = apt->getDynamics()->getGroundNetwork()->findNearestNode(lat3,
374
399
// A negative gateId indicates an overflow parking, use a
375
400
// fallback mechanism for this.
376
401
// Starting from gate 0 is a bit of a hack...
377
402
FGTaxiRoute route;
379
route = apt->getGroundNetwork()->findShortestRoute(runwayId, gateId);
404
route = apt->getDynamics()->getGroundNetwork()->findShortestRoute(runwayId,
381
route = apt->getGroundNetwork()->findShortestRoute(runwayId, 0);
407
route = apt->getDynamics()->getGroundNetwork()->findShortestRoute(runwayId, 0);
382
408
intVecIterator i;
383
//cerr << "creating route : ";
384
410
// No route found: go from gate directly to runway
385
411
if (route.empty()) {
386
412
//Add the runway startpoint;
451
483
wpt->finished = false;
452
484
wpt->on_ground = true;
453
485
waypoints.push_back(wpt);
488
wpt->name = "Begin Parking"; //apt->getId(); //wpt_node->getStringValue("name", "END");
489
wpt->latitude = lat2;
490
wpt->longitude = lon2;
491
wpt->altitude = apt->getElevation();
493
wpt->crossat = -10000;
494
wpt->gear_down = true;
495
wpt->flaps_down= true;
496
wpt->finished = false;
497
wpt->on_ground = true;
498
waypoints.push_back(wpt);
504
apt->getDynamics()->getParking(gateId, &lat, &lon, &heading);
510
wpt->name = "END"; //wpt_node->getStringValue("name", "END");
512
wpt->longitude = lon;
515
wpt->crossat = -10000;
516
wpt->gear_down = true;
517
wpt->flaps_down= true;
518
wpt->finished = false;
519
wpt->on_ground = true;
520
waypoints.push_back(wpt);
460
// Add the final destination 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();
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);
476
// wpt_iterator = waypoints.begin();
479
//wpt_iterator = waypoints.begin()+currWpt;
482
526
/*******************************************************************
514
545
// "NOTE: this is currently fixed to "com" for commercial traffic
515
546
// Should be changed to be used dynamically to allow "gen" and "mil"
517
apt->getActiveRunway("com", 1, activeRunway);
548
apt->getDynamics()->getActiveRunway("com", 1, activeRunway);
518
549
if (!(globals->get_runways()->search(apt->getId(),
522
cout << "Failed to find runway for " << apt->getId() << endl;
523
// Hmm, how do we handle a potential error like this?
553
SG_LOG(SG_INPUT, SG_ALERT, "Failed to find runway " <<
555
" at airport " << apt->getId());
527
//apt->getActiveRunway(string("com"), 1, test);
531
559
heading = rwy._heading;
532
560
double azimuth = heading + 180.0;
533
561
while ( azimuth >= 360.0 ) { azimuth -= 360.0; }
593
// Erase all existing waypoints.
594
// wpt_vector_iterator i= waypoints.begin();
595
//while(waypoints.begin() != waypoints.end())
598
// waypoints.erase(i);
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
609
620
// "NOTE: this is currently fixed to "com" for commercial traffic
610
621
// Should be changed to be used dynamically to allow "gen" and "mil"
612
apt->getActiveRunway("com", 1, activeRunway);
623
apt->getDynamics()->getActiveRunway("com", 1, activeRunway);
613
624
if (!(globals->get_runways()->search(apt->getId(),
617
cout << "Failed to find runway for " << apt->getId() << endl;
618
// Hmm, how do we handle a potential error like this?
628
SG_LOG(SG_INPUT, SG_ALERT, "Failed to find runway " <<
630
" at airport " << apt->getId());
622
//apt->getActiveRunway(string("com"), 1, test);
672
676
* initialize the Aircraft at the parking location
673
677
******************************************************************/
674
void FGAIFlightPlan::createCruise(bool firstFlight, FGAirport *dep, FGAirport *arr, double latitude, double longitude, double speed, double alt)
678
void FGAIFlightPlan::createCruise(bool firstFlight, FGAirport *dep,
679
FGAirport *arr, double latitude,
680
double longitude, double speed,
676
683
double wind_speed;
677
684
double wind_heading;
680
686
double lat, lon, az;
681
687
double lat2, lon2, az2;
686
// Erase all existing waypoints.
687
// wpt_vector_iterator i= waypoints.begin();
688
//while(waypoints.begin() != waypoints.end())
691
// waypoints.erase(i);
695
691
wpt = new waypoint;
696
692
wpt->name = "Cruise"; //wpt_node->getStringValue("name", "END");
697
693
wpt->latitude = latitude;
704
700
wpt->finished = false;
705
701
wpt->on_ground = false;
706
702
waypoints.push_back(wpt);
707
//Beginning of Decent
710
705
// should be changed dynamically to allow "gen" and "mil"
711
arr->getActiveRunway("com", 2, activeRunway);
706
arr->getDynamics()->getActiveRunway("com", 2, activeRunway);
712
707
if (!(globals->get_runways()->search(arr->getId(),
716
cout << "Failed to find runway for " << arr->getId() << endl;
717
// Hmm, how do we handle a potential error like this?
711
SG_LOG(SG_INPUT, SG_ALERT, "Failed to find runway " <<
713
" at airport " << arr->getId());
721
//arr->getActiveRunway(string("com"), 1, test);
724
//cerr << "Altitude = " << alt << endl;
725
//cerr << "Done" << endl;
726
//if (arr->getId() == "EHAM")
728
// cerr << "Creating cruise to EHAM " << latitude << " " << longitude << endl;
730
716
heading = rwy._heading;
731
717
azimuth = heading + 180.0;
732
718
while ( azimuth >= 360.0 ) { azimuth -= 360.0; }
735
// Note: This places us at the location of the active
736
// runway during initial cruise. This needs to be
738
721
geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, azimuth,
740
723
&lat2, &lon2, &az2 );
741
724
wpt = new waypoint;
742
wpt->name = "BOD"; //wpt_node->getStringValue("name", "END");
743
726
wpt->latitude = lat2;
744
727
wpt->longitude = lon2;
745
728
wpt->altitude = alt;
778
//// Erase all existing waypoints.
779
// wpt_vector_iterator i= waypoints.begin();
780
//while(waypoints.begin() != waypoints.end())
783
// waypoints.erase(i);
787
756
//Beginning of Decent
789
758
// allow "mil" and "gen" as well
790
apt->getActiveRunway("com", 2, activeRunway);
791
if (!(globals->get_runways()->search(apt->getId(),
795
cout << "Failed to find runway for " << apt->getId() << endl;
796
// Hmm, how do we handle a potential error like this?
800
//apt->getActiveRunway(string("com"), 1, test);
803
//cerr << "Done" << endl;
759
apt->getDynamics()->getActiveRunway("com", 2, activeRunway);
760
if (!(globals->get_runways()->search(apt->getId(),
764
SG_LOG(SG_INPUT, SG_ALERT, "Failed to find runway " <<
766
" at airport " << apt->getId());
804
770
heading = rwy._heading;
805
771
azimuth = heading + 180.0;
806
772
while ( azimuth >= 360.0 ) { azimuth -= 360.0; }
810
773
geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, azimuth,
812
775
&lat2, &lon2, &az2 );
921
875
wpt->finished = false;
922
876
wpt->on_ground = true;
923
877
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();
929
//if (apt->getId() == "EHAM")
931
// cerr << "Created Landing to EHAM " << lat2 << " " << lon2 << ": Runway = " << rwy._rwy_no
932
// << "heading " << heading << endl;
936
880
/*******************************************************************
938
882
* initialize the Aircraft at the parking location
939
883
******************************************************************/
940
void FGAIFlightPlan::createParking(FGAirport *apt)
884
void FGAIFlightPlan::createParking(FGAirport *apt, double radius)
946
apt->getParking(gateId, &lat, &lon, &heading);
891
apt->getDynamics()->getParking(gateId, &lat, &lon, &heading);
947
892
heading += 180.0;
948
893
if (heading > 360)
895
geo_direct_wgs_84 ( 0, lat, lon, heading,
897
&lat2, &lon2, &az2 );
899
wpt->name = "taxiStart";
900
wpt->latitude = lat2;
901
wpt->longitude = lon2;
902
wpt->altitude = apt->getElevation();
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
geo_direct_wgs_84 ( 0, lat, lon, heading,
912
&lat2, &lon2, &az2 );
914
wpt->name = "taxiStart";
915
wpt->latitude = lat2;
916
wpt->longitude = lon2;
917
wpt->altitude = apt->getElevation();
919
wpt->crossat = -10000;
920
wpt->gear_down = true;
921
wpt->flaps_down= true;
922
wpt->finished = false;
923
wpt->on_ground = true;
924
waypoints.push_back(wpt);
951
// Erase all existing waypoints.
952
// wpt_vector_iterator i= waypoints.begin();
953
//while(waypoints.begin() != waypoints.end())
956
// waypoints.erase(i);
959
// And finally one more named "END"
960
926
wpt = new waypoint;
961
927
wpt->name = "END"; //wpt_node->getStringValue("name", "END");
962
928
wpt->latitude = lat;
963
929
wpt->longitude = lon;
930
wpt->altitude = apt->getElevation();
966
932
wpt->crossat = -10000;
967
933
wpt->gear_down = true;