52
53
readProperties(path.str(), &root);
53
54
} catch (const sg_exception &e) {
54
55
SG_LOG(SG_GENERAL, SG_ALERT,
55
"Error reading AI flight plan: ");
56
cout << path.str() << endl;
56
"Error reading AI flight plan: " << path.str());
57
// cout << path.str() << endl;
90
91
// as setting speeds and altitude computed by the
91
92
// traffic manager.
92
93
FGAIFlightPlan::FGAIFlightPlan(FGAIModelEntity *entity,
97
100
bool useInitialWayPoint = true;
98
101
bool useCurrentWayPoint = false;
99
102
SGPath path( globals->get_fg_root() );
100
103
path.append( "/Data/AI/FlightPlans" );
101
104
path.append( entity->path );
102
105
SGPropertyNode root;
107
// This is a bit of a hack:
108
// Normally the value of course will be used to evaluate whether
109
// or not a waypoint will be used for midair initialization of
110
// an AI aircraft. However, if a course value of 999 will be passed
111
// when an update request is received, which will by definition always be
112
// on the ground and should include all waypoints.
115
useInitialWayPoint = false;
116
useCurrentWayPoint = true;
105
120
readProperties(path.str(), &root);
182
197
// so once is the useWpt flag is set to true, we cannot reset it to false.
183
198
//cerr << "Discarding waypoint: " << (*i)->name
184
199
// << ": Course difference = " << crsDiff
185
// << "Course = " << course
186
// << "crse = " << crse << endl;
200
// << "Course = " << course
201
// << "crse = " << crse << endl;
189
204
useCurrentWayPoint = true;
193
208
if ((dist > 100.0) && (useInitialWayPoint))
195
//waypoints.push_back(init_waypoint);
210
//waypoints.push_back(init_waypoint);;
196
211
waypoints.insert(i, init_waypoint);
197
212
//cerr << "Using waypoint : " << init_waypoint->name << endl;
214
//if (useInitialWayPoint)
216
// (*i)->speed = dist; // A hack
199
218
//waypoints.push_back( wpt );
200
219
//cerr << "Using waypoint : " << (*i)->name
201
220
// << ": course diff : " << crsDiff
343
362
void FGAIFlightPlan::create(FGAirport *dep, FGAirport *arr, double alt, double speed)
346
365
double wind_heading;
368
double lat2, lon2, az2;
349
371
//waypoints.push_back(wpt);
350
372
// Create the outbound taxi leg, for now simplified as a
351
373
// Direct route from the airport center point to the start
352
374
// of the runway.
353
375
///////////////////////////////////////////////////////////
354
//cerr << "Cruise Alt << " << alt << endl;
376
//cerr << "Cruise Alt << " << alt << endl;
377
// Temporary code to add some small random variation to aircraft parking positions;
378
direction = (rand() % 360);
379
geo_direct_wgs_84 ( 0, dep->_latitude, dep->_longitude, direction,
381
&lat2, &lon2, &az2 );
355
382
waypoint *wpt = new waypoint;
356
wpt->name = dep->id; //wpt_node->getStringValue("name", "END");
357
wpt->latitude = dep->latitude;
358
wpt->longitude = dep->longitude;
359
wpt->altitude = dep->elevation + 19; // probably need to add some model height to it
383
wpt->name = dep->_id; //wpt_node->getStringValue("name", "END");
384
wpt->latitude = lat2;
385
wpt->longitude = lon2;
386
wpt->altitude = dep->_elevation + 19; // probably need to add some model height to it
361
388
wpt->crossat = -10000;
362
389
wpt->gear_down = true;
363
390
wpt->flaps_down= true;
364
391
wpt->finished = false;
392
wpt->on_ground = true;
365
393
waypoints.push_back(wpt);
367
395
// Get the current active runway, based on code from David Luff
369
397
stationweather = ((FGEnvironmentMgr *) globals->get_subsystem("environment"))
370
->getEnvironment(dep->latitude, dep->longitude, dep->elevation);
398
->getEnvironment(dep->_latitude, dep->_longitude, dep->_elevation);
372
400
wind_speed = stationweather.get_wind_speed_kt();
373
401
wind_heading = stationweather.get_wind_from_heading_deg();
376
404
// which is consistent with Flightgear's initial setup.
379
string rwy_no = globals->get_runways()->search(dep->id, int(wind_heading));
380
if (!(globals->get_runways()->search(dep->id, (int) wind_heading, &rwy )))
407
string rwy_no = globals->get_runways()->search(dep->_id, int(wind_heading));
408
if (!(globals->get_runways()->search(dep->_id, (int) wind_heading, &rwy )))
382
cout << "Failed to find runway for " << dep->id << endl;
410
cout << "Failed to find runway for " << dep->_id << endl;
383
411
// Hmm, how do we handle a potential error like this?
388
double lat2, lon2, az2;
389
double heading = rwy.heading;
416
double heading = rwy._heading;
390
417
double azimuth = heading + 180.0;
391
418
while ( azimuth >= 360.0 ) { azimuth -= 360.0; }
392
geo_direct_wgs_84 ( 0, rwy.lat, rwy.lon, azimuth,
393
rwy.length * SG_FEET_TO_METER * 0.5 - 5.0,
419
geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, azimuth,
420
rwy._length * SG_FEET_TO_METER * 0.5 - 5.0,
394
421
&lat2, &lon2, &az2 );
396
423
//Add the runway startpoint;
397
424
wpt = new waypoint;
399
426
wpt->latitude = lat2;
400
427
wpt->longitude = lon2;
401
wpt->altitude = dep->elevation + 19;
428
wpt->altitude = dep->_elevation + 19;
403
430
wpt->crossat = -10000;
404
431
wpt->gear_down = true;
410
437
//Next: The point on the runway where we begin to accelerate to take-off speed
411
438
//100 meters down the runway seems to work. Shorter distances cause problems with
412
439
// the turn with larger aircraft
413
geo_direct_wgs_84 ( 0, rwy.lat, rwy.lon, azimuth,
414
rwy.length * SG_FEET_TO_METER * 0.5 - 105.0,
440
geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, azimuth,
441
rwy._length * SG_FEET_TO_METER * 0.5 - 105.0,
415
442
&lat2, &lon2, &az2 );
416
443
wpt = new waypoint;
417
444
wpt->name = "accel";
418
445
wpt->latitude = lat2;
419
446
wpt->longitude = lon2;
420
wpt->altitude = dep->elevation + 19;
447
wpt->altitude = dep->_elevation + 19;
421
448
wpt->speed = speed;
422
449
wpt->crossat = -10000;
423
450
wpt->gear_down = true;
470
497
//Beginning of Decent
471
498
stationweather = ((FGEnvironmentMgr *)globals->get_subsystem("environment"))
472
->getEnvironment(arr->latitude, arr->longitude, arr->elevation);
499
->getEnvironment(arr->_latitude, arr->_longitude, arr->_elevation);
474
501
wind_speed = stationweather.get_wind_speed_kt();
475
502
wind_heading = stationweather.get_wind_from_heading_deg();
479
506
// which is consistent with Flightgear's initial setup.
482
rwy_no = globals->get_runways()->search(arr->id, int(wind_heading));
483
//cout << "Using runway # " << rwy_no << " for departure at " << dep->id << endl;
509
rwy_no = globals->get_runways()->search(arr->_id, int(wind_heading));
510
//cout << "Using runway # " << rwy_no << " for departure at " << dep->_id << endl;
485
if (!(globals->get_runways()->search(arr->id, (int) wind_heading, &rwy )))
512
if (!(globals->get_runways()->search(arr->_id, (int) wind_heading, &rwy )))
487
cout << "Failed to find runway for " << arr->id << endl;
514
cout << "Failed to find runway for " << arr->_id << endl;
488
515
// Hmm, how do we handle a potential error like this?
491
518
//cerr << "Done" << endl;
492
heading = rwy.heading;
519
heading = rwy._heading;
493
520
azimuth = heading + 180.0;
494
521
while ( azimuth >= 360.0 ) { azimuth -= 360.0; }
498
geo_direct_wgs_84 ( 0, rwy.lat, rwy.lon, azimuth,
525
geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, azimuth,
500
527
&lat2, &lon2, &az2 );
501
528
wpt = new waypoint;
512
539
waypoints.push_back(wpt);
514
541
// Ten thousand ft. Slowing down to 240 kts
515
geo_direct_wgs_84 ( 0, rwy.lat, rwy.lon, azimuth,
542
geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, azimuth,
516
543
20*SG_NM_TO_METER,
517
544
&lat2, &lon2, &az2 );
518
545
wpt = new waypoint;
519
546
wpt->name = "Dec 10000ft"; //wpt_node->getStringValue("name", "END");
520
547
wpt->latitude = lat2;
521
548
wpt->longitude = lon2;
522
wpt->altitude = arr->elevation + 19;
549
wpt->altitude = arr->_elevation + 19;
523
550
wpt->speed = 240;
524
551
wpt->crossat = 10000;
525
552
wpt->gear_down = false;
529
556
waypoints.push_back(wpt);
531
558
// Three thousand ft. Slowing down to 160 kts
532
geo_direct_wgs_84 ( 0, rwy.lat, rwy.lon, azimuth,
559
geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, azimuth,
533
560
8*SG_NM_TO_METER,
534
561
&lat2, &lon2, &az2 );
535
562
wpt = new waypoint;
536
563
wpt->name = "DEC 3000ft"; //wpt_node->getStringValue("name", "END");
537
564
wpt->latitude = lat2;
538
565
wpt->longitude = lon2;
539
wpt->altitude = arr->elevation + 19;
566
wpt->altitude = arr->_elevation + 19;
540
567
wpt->speed = 160;
541
568
wpt->crossat = 3000;
542
569
wpt->gear_down = true;
545
572
wpt->on_ground = false;
546
573
waypoints.push_back(wpt);
547
574
//Runway Threshold
548
geo_direct_wgs_84 ( 0, rwy.lat, rwy.lon, azimuth,
575
geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, azimuth,
576
rwy._length*0.45 * SG_FEET_TO_METER,
550
577
&lat2, &lon2, &az2 );
551
578
wpt = new waypoint;
552
579
wpt->name = "Threshold"; //wpt_node->getStringValue("name", "END");
553
580
wpt->latitude = lat2;
554
581
wpt->longitude = lon2;
555
wpt->altitude = arr->elevation + 19;
582
wpt->altitude = arr->_elevation + 19;
557
wpt->crossat = arr->elevation + 19;
584
wpt->crossat = arr->_elevation + 19;
558
585
wpt->gear_down = true;
559
586
wpt->flaps_down= true;
560
587
wpt->finished = false;
562
589
waypoints.push_back(wpt);
564
591
//Full stop at the runway centerpoint
565
geo_direct_wgs_84 ( 0, rwy.lat, rwy.lon, azimuth,
592
geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, azimuth,
567
594
&lat2, &lon2, &az2 );
568
595
wpt = new waypoint;
569
596
wpt->name = "Center"; //wpt_node->getStringValue("name", "END");
570
wpt->latitude = rwy.lat;
571
wpt->longitude = rwy.lon;
572
wpt->altitude = arr->elevation + 19;
597
wpt->latitude = rwy._lat;
598
wpt->longitude = rwy._lon;
599
wpt->altitude = arr->_elevation + 19;
574
601
wpt->crossat = -10000;
575
602
wpt->gear_down = true;
576
603
wpt->flaps_down= true;
577
604
wpt->finished = false;
578
wpt->on_ground = false;
605
wpt->on_ground = true;
579
606
waypoints.push_back(wpt);
608
direction = (rand() % 360);
609
geo_direct_wgs_84 ( 0, arr->_latitude, arr->_longitude, direction,
611
&lat2, &lon2, &az2 );
581
613
// Add the final destination waypoint
582
614
wpt = new waypoint;
583
wpt->name = arr->id; //wpt_node->getStringValue("name", "END");
584
wpt->latitude = arr->latitude;
585
wpt->longitude = arr->longitude;
586
wpt->altitude = arr->elevation+19;
615
wpt->name = arr->_id; //wpt_node->getStringValue("name", "END");
616
wpt->latitude = lat2;
617
wpt->longitude = lon2;
618
wpt->altitude = arr->_elevation+19;
588
620
wpt->crossat = -10000;
589
621
wpt->gear_down = true;
590
622
wpt->flaps_down= true;
591
623
wpt->finished = false;
592
wpt->on_ground = false;
624
wpt->on_ground = true;
593
625
waypoints.push_back(wpt);
595
627
// And finally one more named "END"
596
628
wpt = new waypoint;
597
629
wpt->name = "END"; //wpt_node->getStringValue("name", "END");
598
wpt->latitude = arr->latitude;
599
wpt->longitude = arr->longitude;
630
wpt->latitude = lat2;
631
wpt->longitude = lon2;
600
632
wpt->altitude = 19;
602
634
wpt->crossat = -10000;
609
641
// And finally one more named "EOF"
610
642
wpt = new waypoint;
611
643
wpt->name = "EOF"; //wpt_node->getStringValue("name", "END");
612
wpt->latitude = arr->latitude;
613
wpt->longitude = arr->longitude;
644
wpt->latitude = lat2;
645
wpt->longitude = lon2;
614
646
wpt->altitude = 19;
616
648
wpt->crossat = -10000;
617
649
wpt->gear_down = true;
618
650
wpt->flaps_down= true;
619
651
wpt->finished = true;
620
wpt->finished = true;
652
wpt->on_ground = true;
621
653
waypoints.push_back(wpt);