~ubuntu-branches/ubuntu/precise/flightgear/precise

« back to all changes in this revision

Viewing changes to src/AIModel/AIFlightPlanCreate.cxx

  • Committer: Bazaar Package Importer
  • Author(s): Ove Kaaven
  • Date: 2011-01-30 15:46:35 UTC
  • mfrom: (3.1.7 sid)
  • Revision ID: james.westby@ubuntu.com-20110130154635-rlynmg9n5hzxq5xe
Tags: 2.0.0-3
* Recommend fgfs-aircraft-base and fgfs-models-base.
  Closes. #610276.
* Added note about scenery SharedModels.tgz to README.Debian.

Show diffs side-by-side

added added

removed removed

Lines of Context:
24
24
 
25
25
#include "AIFlightPlan.hxx"
26
26
#include <simgear/math/sg_geodesy.hxx>
 
27
#include <simgear/props/props.hxx>
 
28
#include <simgear/props/props_io.hxx>
 
29
 
27
30
#include <Airports/runways.hxx>
28
31
#include <Airports/dynamics.hxx>
 
32
#include "AIAircraft.hxx"
 
33
#include "performancedata.hxx"
29
34
 
30
35
#include <Environment/environment_mgr.hxx>
31
36
#include <Environment/environment.hxx>
41
46
 
42
47
 
43
48
// Check lat/lon values during initialization;
44
 
void FGAIFlightPlan::create(FGAirport *dep, FGAirport *arr, int legNr, 
 
49
void FGAIFlightPlan::create(FGAIAircraft *ac, FGAirport *dep, FGAirport *arr, int legNr, 
45
50
                            double alt, double speed, double latitude, 
46
51
                            double longitude, bool firstFlight,double radius, 
47
52
                            const string& fltType, const string& aircraftType, 
51
56
  switch(legNr)
52
57
    {
53
58
      case 1:
54
 
      createPushBack(firstFlight,dep, latitude, longitude, 
 
59
      createPushBack(ac, firstFlight,dep, latitude, longitude, 
55
60
                     radius, fltType, aircraftType, airline);
56
61
      break;
57
62
    case 2: 
58
 
      createTaxi(firstFlight, 1, dep, latitude, longitude, 
59
 
                 radius, fltType, aircraftType, airline);
 
63
      createTakeoffTaxi(ac, firstFlight, dep, radius, fltType, aircraftType, airline);
60
64
      break;
61
65
    case 3: 
62
 
      createTakeOff(firstFlight, dep, speed, fltType);
 
66
      createTakeOff(ac, firstFlight, dep, speed, fltType);
63
67
      break;
64
68
    case 4: 
65
 
      createClimb(firstFlight, dep, speed, alt, fltType);
 
69
      createClimb(ac, firstFlight, dep, speed, alt, fltType);
66
70
      break;
67
71
    case 5: 
68
 
      createCruise(firstFlight, dep,arr, latitude, longitude, speed, alt, fltType);
 
72
      createCruise(ac, firstFlight, dep,arr, latitude, longitude, speed, alt, fltType);
69
73
      break;
70
74
    case 6: 
71
 
      createDecent(arr, fltType);
 
75
      createDecent(ac, arr, fltType);
72
76
      break;
73
77
    case 7: 
74
 
      createLanding(arr);
 
78
      createLanding(ac, arr);
75
79
      break;
76
80
    case 8: 
77
 
      createTaxi(false, 2, arr, latitude, longitude, radius, 
78
 
                 fltType, aircraftType, airline);
 
81
      createLandingTaxi(ac, arr, radius, fltType, aircraftType, airline);
79
82
      break;
80
83
      case 9: 
81
 
        createParking(arr, radius);
 
84
        createParking(ac, arr, radius);
82
85
      break;
83
86
    default:
84
87
      //exit(1);
89
92
  leg++;
90
93
}
91
94
 
92
 
 
93
 
 
94
 
 
95
 
 
96
 
 
97
 
/*******************************************************************
98
 
 * createCreate Taxi. 
99
 
 * initialize the Aircraft at the parking location
100
 
 ******************************************************************/
101
 
void FGAIFlightPlan::createTaxi(bool firstFlight, int direction, 
102
 
                                FGAirport *apt, double latitude, double longitude, 
103
 
                                double radius, const string& fltType, 
104
 
                                const string& acType, const string& airline)
105
 
{
106
 
  double heading;
107
 
  double lat, lon;
108
 
  double lat2, lon2, az2;
109
 
  waypoint *wpt;
110
 
 
111
 
  int nrWaypointsToSkip;
112
 
 
113
 
   if (direction == 1)
114
 
    {
115
 
      // If this function is called during initialization,
116
 
      // make sure we obtain a valid gate ID first
117
 
      // and place the model at the location of the gate.
118
 
      if (firstFlight)
119
 
        {
120
 
          if (!(apt->getDynamics()->getAvailableParking(&lat, &lon, 
121
 
                                                        &heading, &gateId, 
122
 
                                                        radius, fltType, 
123
 
                                                        acType, airline)))
124
 
            {
125
 
              SG_LOG(SG_INPUT, SG_WARN, "Could not find parking for a " << 
126
 
                     acType <<
127
 
                     " of flight type " << fltType <<
128
 
                     " of airline     " << airline <<
129
 
                     " at airport     " << apt->getId());
130
 
            }
131
 
          //waypoint *wpt = new waypoint;
132
 
          //wpt->name      = "park";
133
 
          //wpt->latitude  = lat;
134
 
          //wpt->longitude = lon;
135
 
          //wpt->altitude  = apt->getElevation();
136
 
          //wpt->speed     = -10; 
137
 
          //wpt->crossat   = -10000;
138
 
          //wpt->gear_down = true;
139
 
          //wpt->flaps_down= true;
140
 
          //wpt->finished  = false;
141
 
          //wpt->on_ground = true;
142
 
          //waypoints.push_back(wpt);  
143
 
        }
144
 
      string rwyClass = getRunwayClassFromTrafficType(fltType);
145
 
      apt->getDynamics()->getActiveRunway(rwyClass, 1, activeRunway);
146
 
      rwy = apt->getRunwayByIdent(activeRunway);
147
 
      
148
 
      // Determine the beginning of he runway
149
 
      heading = rwy->headingDeg();
150
 
      double azimuth = heading + 180.0;
151
 
      while ( azimuth >= 360.0 ) { azimuth -= 360.0; }
152
 
      geo_direct_wgs_84 ( 0, rwy->latitude(), rwy->longitude(), azimuth, 
153
 
                          rwy->lengthM() * 0.5 - 5.0,
154
 
                          &lat2, &lon2, &az2 );
155
 
 
156
 
      if (apt->getDynamics()->getGroundNetwork()->exists())
157
 
        {
158
 
          intVec ids;
159
 
          int runwayId = apt->getDynamics()->getGroundNetwork()->findNearestNode(lat2, 
160
 
                                                                                 lon2);
161
 
 
162
 
          
163
 
          // A negative gateId indicates an overflow parking, use a
164
 
          // fallback mechanism for this. 
165
 
          // Starting from gate 0 in this case is a bit of a hack
166
 
          // which requires a more proper solution later on.
167
 
          //FGTaxiRoute route;
168
 
          delete taxiRoute;
169
 
          taxiRoute = new FGTaxiRoute;
170
 
 
171
 
          // Determine which node to start from.
172
 
          int node;
173
 
          // Find out which node to start from
174
 
          FGParking *park = apt->getDynamics()->getParking(gateId);
175
 
          if (park)
176
 
                node = park->getPushBackPoint();
177
 
          else
178
 
                node = 0;
179
 
          if (node == -1)
180
 
             node = gateId;
181
 
 
182
 
          // HAndle case where parking doens't have a node
183
 
          if ((node == 0) && park) {
184
 
                if (firstFlight) {
185
 
                    node = gateId;
186
 
                } else {
187
 
                    node = lastNodeVisited;
188
 
                }
189
 
          }
190
 
 
191
 
          //cerr << "Using node " << node << endl;
192
 
            *taxiRoute = apt->getDynamics()->getGroundNetwork()->findShortestRoute(node, runwayId);
193
 
          intVecIterator i;
194
 
         
195
 
          if (taxiRoute->empty()) {
196
 
            //Add the runway startpoint;
197
 
            wpt = new waypoint;
198
 
            wpt->name      = "Airport Center";
199
 
            wpt->latitude  = latitude;
200
 
            wpt->longitude = longitude;
201
 
            wpt->altitude  = apt->getElevation();
202
 
            wpt->speed     = 15; 
203
 
            wpt->crossat   = -10000;
204
 
            wpt->gear_down = true;
205
 
            wpt->flaps_down= true;
206
 
            wpt->finished  = false;
207
 
            wpt->on_ground = true;
208
 
            wpt->routeIndex = 0;
209
 
            waypoints.push_back(wpt);
210
 
            
211
 
            //Add the runway startpoint;
212
 
            wpt = new waypoint;
213
 
            wpt->name      = "Runway Takeoff";
214
 
            wpt->latitude  = lat2;
215
 
            wpt->longitude = lon2;
216
 
            wpt->altitude  = apt->getElevation();
217
 
            wpt->speed     = 15; 
218
 
            wpt->crossat   = -10000;
219
 
            wpt->gear_down = true;
220
 
            wpt->flaps_down= true;
221
 
            wpt->finished  = false;
222
 
            wpt->on_ground = true;
223
 
            wpt->routeIndex = 0;
224
 
            waypoints.push_back(wpt);   
225
 
          } else {
226
 
            int node;
227
 
            taxiRoute->first();
228
 
            //bool isPushBackPoint = false;
229
 
            if (firstFlight) {
230
 
 
231
 
              // If this is called during initialization, randomly
232
 
              // skip a number of waypoints to get a more realistic
233
 
              // taxi situation.
234
 
              //isPushBackPoint = true;
235
 
              int nrWaypoints = taxiRoute->size();
236
 
              nrWaypointsToSkip = rand() % nrWaypoints;
237
 
              // but make sure we always keep two active waypoints
238
 
              // to prevent a segmentation fault
239
 
              for (int i = 0; i < nrWaypointsToSkip-2; i++) {
240
 
                //isPushBackPoint = false;
241
 
                taxiRoute->next(&node);
242
 
              }
243
 
              apt->getDynamics()->releaseParking(gateId);
244
 
            } else {
245
 
               if (taxiRoute->size() > 1) {
246
 
                   taxiRoute->next(&node); // chop off the first waypoint, because that is already the last of the pushback route
247
 
               }
248
 
            }
249
 
            int route;
250
 
            while(taxiRoute->next(&node, &route))
251
 
              {
252
 
                //FGTaxiNode *tn = apt->getDynamics()->getGroundNetwork()->findSegment(node)->getEnd();
253
 
                char buffer[10];
254
 
                snprintf (buffer, 10, "%d", node);
255
 
                FGTaxiNode *tn = apt->getDynamics()->getGroundNetwork()->findNode(node);
256
 
                //ids.pop_back();  
257
 
                wpt = new waypoint;
258
 
                wpt->name      = string(buffer); // fixme: should be the name of the taxiway
259
 
                wpt->latitude  = tn->getLatitude();
260
 
                wpt->longitude = tn->getLongitude();
261
 
                // Elevation is currently disregarded when on_ground is true
262
 
                // because the AIModel obtains a periodic ground elevation estimate.
263
 
                wpt->altitude  = apt->getElevation();
264
 
                wpt->speed     = 15; 
265
 
                wpt->crossat   = -10000;
266
 
                wpt->gear_down = true;
267
 
                wpt->flaps_down= true;
268
 
                wpt->finished  = false;
269
 
                wpt->on_ground = true;
270
 
                wpt->routeIndex = route;
271
 
                waypoints.push_back(wpt);
272
 
              }
273
 
             /*
274
 
            //cerr << endl;
275
 
            // finally, rewind the taxiRoute object to the point where we started
276
 
            // generating the Flightplan, for AI use.
277
 
            // This is a bit tricky, because the 
278
 
            taxiRoute->first();
279
 
            if (firstFlight) { 
280
 
              for (int i = 0; i < nrWaypointsToSkip-1; i++) {
281
 
                taxiRoute->next(&node);
282
 
              }
283
 
            } else {
284
 
              int size = taxiRoute->size();
285
 
              if (size > 2) {
286
 
                //taxiRoute->next(&node);
287
 
                //taxiRoute->next(&node);       
288
 
                //taxiRoute->next(&node);
289
 
              }
290
 
            }*/
291
 
          } // taxiRoute not empty
292
 
        }
293
 
      else 
294
 
        {
295
 
          // This is the fallback mechanism, in case no ground network is available
296
 
          //Add the runway startpoint;
297
 
          wpt = new waypoint;
298
 
          wpt->name      = "Airport Center";
299
 
          wpt->latitude  = apt->getLatitude();
300
 
          wpt->longitude = apt->getLongitude();
301
 
          wpt->altitude  = apt->getElevation();
302
 
          wpt->speed     = 15; 
303
 
          wpt->crossat   = -10000;
304
 
          wpt->gear_down = true;
305
 
          wpt->flaps_down= true;
306
 
          wpt->finished  = false;
307
 
          wpt->on_ground = true;
308
 
          wpt->routeIndex = 0;
309
 
          waypoints.push_back(wpt);
310
 
          
311
 
          //Add the runway startpoint;
312
 
          wpt = new waypoint;
313
 
          wpt->name      = "Runway Takeoff";
314
 
          wpt->latitude  = lat2;
315
 
          wpt->longitude = lon2;
316
 
          wpt->altitude  = apt->getElevation();
317
 
          wpt->speed     = 15; 
318
 
          wpt->crossat   = -10000;
319
 
          wpt->gear_down = true;
320
 
          wpt->flaps_down= true;
321
 
          wpt->finished  = false;
322
 
          wpt->on_ground = true;
323
 
          wpt->routeIndex = 0;
324
 
          waypoints.push_back(wpt);
325
 
        }
326
 
    }
327
 
  else  // Landing taxi
328
 
    {
329
 
      apt->getDynamics()->getAvailableParking(&lat, &lon, &heading, 
330
 
                                              &gateId, radius, fltType, 
331
 
                                              acType, airline);
332
 
     
333
 
      double lat3 = (*(waypoints.end()-1))->latitude;
334
 
      double lon3 = (*(waypoints.end()-1))->longitude;
335
 
      //cerr << (*(waypoints.end()-1))->name << endl;
336
 
      
337
 
      // Find a route from runway end to parking/gate.
338
 
      if (apt->getDynamics()->getGroundNetwork()->exists())
339
 
        {
340
 
          intVec ids;
341
 
          int runwayId = apt->getDynamics()->getGroundNetwork()->findNearestNode(lat3, 
342
 
                                                                                 lon3);
343
 
          // A negative gateId indicates an overflow parking, use a
344
 
          // fallback mechanism for this. 
345
 
          // Starting from gate 0 is a bit of a hack...
346
 
          //FGTaxiRoute route;
347
 
          delete taxiRoute;
348
 
          taxiRoute = new FGTaxiRoute;
349
 
          if (gateId >= 0)
350
 
            *taxiRoute = apt->getDynamics()->getGroundNetwork()->findShortestRoute(runwayId, 
351
 
                                                                              gateId);
352
 
          else
353
 
            *taxiRoute = apt->getDynamics()->getGroundNetwork()->findShortestRoute(runwayId, 0);
354
 
          intVecIterator i;
355
 
         
356
 
          // No route found: go from gate directly to runway
357
 
          if (taxiRoute->empty()) {
358
 
            //Add the runway startpoint;
359
 
            wpt = new waypoint;
360
 
            wpt->name      = "Airport Center";
361
 
            wpt->latitude  = latitude;
362
 
            wpt->longitude = longitude;
363
 
            wpt->altitude  = apt->getElevation();
364
 
            wpt->speed     = 15; 
365
 
            wpt->crossat   = -10000;
366
 
            wpt->gear_down = true;
367
 
            wpt->flaps_down= true;
368
 
            wpt->finished  = false;
369
 
            wpt->on_ground = true;
370
 
            wpt->routeIndex = 0;
371
 
            waypoints.push_back(wpt);
372
 
            
373
 
            //Add the runway startpoint;
374
 
            wpt = new waypoint;
375
 
            wpt->name      = "Runway Takeoff";
376
 
            wpt->latitude  = lat3;
377
 
            wpt->longitude = lon3;
378
 
            wpt->altitude  = apt->getElevation();
379
 
            wpt->speed     = 15; 
380
 
            wpt->crossat   = -10000;
381
 
            wpt->gear_down = true;
382
 
            wpt->flaps_down= true;
383
 
            wpt->finished  = false;
384
 
            wpt->on_ground = true;
385
 
            wpt->routeIndex = 0;
386
 
            waypoints.push_back(wpt);   
387
 
          } else {
388
 
            int node;
389
 
            taxiRoute->first();
390
 
            int size = taxiRoute->size();
391
 
            // Omit the last two waypoints, as 
392
 
            // those are created by createParking()
393
 
            int route;
394
 
            for (int i = 0; i < size-2; i++)
395
 
              {
396
 
                taxiRoute->next(&node, &route);
397
 
                char buffer[10];
398
 
                snprintf (buffer, 10, "%d", node);
399
 
                //FGTaxiNode *tn = apt->getDynamics()->getGroundNetwork()->findNode(node);
400
 
                FGTaxiNode *tn = apt->getDynamics()->getGroundNetwork()->findNode(node);
401
 
                wpt = new waypoint;
402
 
                //wpt->name      = "taxiway"; // fixme: should be the name of the taxiway
403
 
                wpt->name      = string(buffer);// fixme: should be the name of the taxiway
404
 
                wpt->latitude  = tn->getLatitude();
405
 
                wpt->longitude = tn->getLongitude();
406
 
                wpt->altitude  = apt->getElevation();
407
 
                wpt->speed     = 15; 
408
 
                wpt->crossat   = -10000;
409
 
                wpt->gear_down = true;
410
 
                wpt->flaps_down= true;
411
 
                wpt->finished  = false;
412
 
                wpt->on_ground = true;
413
 
                wpt->routeIndex = route;
414
 
                waypoints.push_back(wpt);
415
 
              }
416
 
            //taxiRoute->first();
417
 
            //taxiRoute->next(&node);
418
 
          }
419
 
        }
420
 
      else
421
 
        {
422
 
          // Use a fallback mechanism in case no ground network is available
423
 
          // obtain the location of the gate entrance point 
424
 
          heading += 180.0;
425
 
          if (heading > 360)
426
 
            heading -= 360;
427
 
          geo_direct_wgs_84 ( 0, lat, lon, heading, 
428
 
                              100,
429
 
                              &lat2, &lon2, &az2 );
430
 
          wpt = new waypoint;
431
 
          wpt->name      = "Airport Center";
432
 
          wpt->latitude  = apt->getLatitude();
433
 
          wpt->longitude = apt->getLongitude();
434
 
          wpt->altitude  = apt->getElevation();
435
 
          wpt->speed     = 15; 
436
 
          wpt->crossat   = -10000;
437
 
          wpt->gear_down = true;
438
 
          wpt->flaps_down= true;
439
 
          wpt->finished  = false;
440
 
          wpt->on_ground = true;
441
 
          wpt->routeIndex = 0;
442
 
          waypoints.push_back(wpt);
443
 
         
444
 
          wpt = new waypoint;
445
 
          wpt->name      = "Begin Parking"; //apt->getId(); //wpt_node->getStringValue("name", "END");
446
 
          wpt->latitude  = lat2;
447
 
          wpt->longitude = lon2;
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
 
          wpt->routeIndex = 0;
456
 
          waypoints.push_back(wpt); 
457
 
 
458
 
          //waypoint* wpt;
459
 
          //double lat;
460
 
          //double lon;
461
 
          //double heading;
462
 
          apt->getDynamics()->getParking(gateId, &lat, &lon, &heading);
463
 
          heading += 180.0;
464
 
          if (heading > 360)
465
 
            heading -= 360; 
466
 
          
467
 
          wpt = new waypoint;
468
 
          wpt->name      = "END"; //wpt_node->getStringValue("name", "END");
469
 
          wpt->latitude  = lat;
470
 
          wpt->longitude = lon;
471
 
          wpt->altitude  = 19;
472
 
          wpt->speed     = 15; 
473
 
          wpt->crossat   = -10000;
474
 
          wpt->gear_down = true;
475
 
          wpt->flaps_down= true;
476
 
          wpt->finished  = false;
477
 
          wpt->on_ground = true;
478
 
          wpt->routeIndex = 0;
479
 
          waypoints.push_back(wpt);
480
 
        }
481
 
      
482
 
    }
 
95
FGAIFlightPlan::waypoint*
 
96
FGAIFlightPlan::createOnGround(FGAIAircraft *ac, const std::string& aName, const SGGeod& aPos, double aElev, double aSpeed)
 
97
{
 
98
  waypoint* wpt = new waypoint;
 
99
  wpt->name = aName;
 
100
  wpt->longitude = aPos.getLongitudeDeg();
 
101
  wpt->latitude = aPos.getLatitudeDeg();
 
102
  wpt->altitude  = aElev;
 
103
  wpt->speed     = aSpeed; 
 
104
  wpt->crossat   = -10000;
 
105
  wpt->gear_down = true;
 
106
  wpt->flaps_down= true;
 
107
  wpt->finished  = false;
 
108
  wpt->on_ground = true;
 
109
  wpt->routeIndex= 0;
 
110
  return wpt;
 
111
}
 
112
 
 
113
FGAIFlightPlan::waypoint*
 
114
FGAIFlightPlan::createInAir(FGAIAircraft *ac, const std::string& aName, const SGGeod& aPos, double aElev, double aSpeed)
 
115
{
 
116
  waypoint* wpt = new waypoint;
 
117
  wpt->name = aName;
 
118
  wpt->longitude = aPos.getLongitudeDeg();
 
119
  wpt->latitude = aPos.getLatitudeDeg();
 
120
  wpt->altitude  = aElev;
 
121
  wpt->speed     = aSpeed; 
 
122
  wpt->crossat   = -10000;
 
123
  wpt->gear_down = false;
 
124
  wpt->flaps_down= false;
 
125
  wpt->finished  = false;
 
126
  wpt->on_ground = false;
 
127
  wpt->routeIndex= 0;
 
128
  return wpt;
 
129
}
 
130
 
 
131
FGAIFlightPlan::waypoint*
 
132
FGAIFlightPlan::cloneWithPos(FGAIAircraft *ac, waypoint* aWpt, const std::string& aName, const SGGeod& aPos)
 
133
{
 
134
  waypoint* wpt = new waypoint;
 
135
  wpt->name = aName;
 
136
  wpt->longitude = aPos.getLongitudeDeg();
 
137
  wpt->latitude = aPos.getLatitudeDeg();
 
138
  
 
139
  wpt->altitude  = aWpt->altitude;
 
140
  wpt->speed     = aWpt->speed; 
 
141
  wpt->crossat   = aWpt->crossat;
 
142
  wpt->gear_down = aWpt->gear_down;
 
143
  wpt->flaps_down= aWpt->flaps_down;
 
144
  wpt->finished  = aWpt->finished;
 
145
  wpt->on_ground = aWpt->on_ground;
 
146
  wpt->routeIndex = 0;
 
147
  
 
148
  return wpt;
 
149
}
 
150
 
 
151
FGAIFlightPlan::waypoint*
 
152
FGAIFlightPlan::clone(waypoint* aWpt)
 
153
{
 
154
  waypoint* wpt  = new waypoint;
 
155
  wpt->name      = aWpt->name;
 
156
  wpt->longitude = aWpt->longitude;
 
157
  wpt->latitude  = aWpt->latitude;
 
158
 
 
159
  wpt->altitude  = aWpt->altitude;
 
160
  wpt->speed     = aWpt->speed; 
 
161
  wpt->crossat   = aWpt->crossat;
 
162
  wpt->gear_down = aWpt->gear_down;
 
163
  wpt->flaps_down= aWpt->flaps_down;
 
164
  wpt->finished  = aWpt->finished;
 
165
  wpt->on_ground = aWpt->on_ground;
 
166
  wpt->routeIndex = 0;
 
167
  
 
168
  return wpt;
 
169
}
 
170
 
 
171
 
 
172
void FGAIFlightPlan::createDefaultTakeoffTaxi(FGAIAircraft *ac, FGAirport* aAirport, FGRunway* aRunway)
 
173
{
 
174
  SGGeod runwayTakeoff = aRunway->pointOnCenterline(5.0);
 
175
  double airportElev = aAirport->getElevation();
 
176
  
 
177
  waypoint* wpt;
 
178
  wpt = createOnGround(ac, "Airport Center", aAirport->geod(), airportElev, ac->getPerformance()->vTaxi());
 
179
  waypoints.push_back(wpt);
 
180
  wpt = createOnGround(ac, "Runway Takeoff", runwayTakeoff, airportElev, ac->getPerformance()->vTaxi());
 
181
  waypoints.push_back(wpt);     
 
182
}
 
183
 
 
184
void FGAIFlightPlan::createTakeoffTaxi(FGAIAircraft *ac, bool firstFlight, 
 
185
                                FGAirport *apt,
 
186
                                double radius, const string& fltType, 
 
187
                                const string& acType, const string& airline)
 
188
{
 
189
  double heading, lat, lon;
 
190
  
 
191
  // If this function is called during initialization,
 
192
  // make sure we obtain a valid gate ID first
 
193
  // and place the model at the location of the gate.
 
194
  if (firstFlight) {
 
195
    if (!(apt->getDynamics()->getAvailableParking(&lat, &lon, 
 
196
              &heading, &gateId, 
 
197
              radius, fltType, 
 
198
              acType, airline)))
 
199
    {
 
200
      SG_LOG(SG_INPUT, SG_WARN, "Could not find parking for a " << 
 
201
       acType <<
 
202
       " of flight type " << fltType <<
 
203
       " of airline     " << airline <<
 
204
       " at airport     " << apt->getId());
 
205
    }
 
206
  }
 
207
  
 
208
  string rwyClass = getRunwayClassFromTrafficType(fltType);
 
209
 
 
210
  // Only set this if it hasn't been set by ATC already.
 
211
  if (activeRunway.empty()) {
 
212
      //cerr << "Getting runway for " << ac->getTrafficRef()->getCallSign() << " at " << apt->getId() << endl;
 
213
      double depHeading = ac->getTrafficRef()->getCourse();
 
214
      apt->getDynamics()->getActiveRunway(rwyClass, 1, activeRunway, depHeading);
 
215
  }
 
216
  rwy = apt->getRunwayByIdent(activeRunway);
 
217
  SGGeod runwayTakeoff = rwy->pointOnCenterline(5.0);
 
218
 
 
219
  FGGroundNetwork* gn = apt->getDynamics()->getGroundNetwork();
 
220
  if (!gn->exists()) {
 
221
    createDefaultTakeoffTaxi(ac, apt, rwy);
 
222
    return;
 
223
  }
 
224
  
 
225
  intVec ids;
 
226
  int runwayId = gn->findNearestNode(runwayTakeoff);
 
227
 
 
228
  // A negative gateId indicates an overflow parking, use a
 
229
  // fallback mechanism for this. 
 
230
  // Starting from gate 0 in this case is a bit of a hack
 
231
  // which requires a more proper solution later on.
 
232
  delete taxiRoute;
 
233
  taxiRoute = new FGTaxiRoute;
 
234
 
 
235
  // Determine which node to start from.
 
236
  int node = 0;
 
237
  // Find out which node to start from
 
238
  FGParking *park = apt->getDynamics()->getParking(gateId);
 
239
  if (park) {
 
240
    node = park->getPushBackPoint();
 
241
  }
 
242
  
 
243
  if (node == -1) {
 
244
    node = gateId;
 
245
  }
 
246
  
 
247
  // HAndle case where parking doens't have a node
 
248
  if ((node == 0) && park) {
 
249
    if (firstFlight) {
 
250
      node = gateId;
 
251
    } else {
 
252
      node = lastNodeVisited;
 
253
    }
 
254
  }
 
255
 
 
256
  *taxiRoute = gn->findShortestRoute(node, runwayId);
 
257
  intVecIterator i;
 
258
         
 
259
  if (taxiRoute->empty()) {
 
260
    createDefaultTakeoffTaxi(ac, apt, rwy);
 
261
    return;
 
262
  }
 
263
  
 
264
  taxiRoute->first();
 
265
  //bool isPushBackPoint = false;
 
266
  if (firstFlight) {
 
267
    // If this is called during initialization, randomly
 
268
    // skip a number of waypoints to get a more realistic
 
269
    // taxi situation.
 
270
    int nrWaypointsToSkip = rand() % taxiRoute->size();
 
271
    // but make sure we always keep two active waypoints
 
272
    // to prevent a segmentation fault
 
273
    for (int i = 0; i < nrWaypointsToSkip-2; i++) {
 
274
      taxiRoute->next(&node);
 
275
    }
 
276
    apt->getDynamics()->releaseParking(gateId);
 
277
  } else {
 
278
    if (taxiRoute->size() > 1) {
 
279
      taxiRoute->next(&node); // chop off the first waypoint, because that is already the last of the pushback route
 
280
    }
 
281
  }
 
282
  
 
283
  // push each node on the taxi route as a waypoint
 
284
  int route;
 
285
  while(taxiRoute->next(&node, &route)) {
 
286
                char buffer[10];
 
287
                snprintf (buffer, 10, "%d", node);
 
288
                FGTaxiNode *tn = apt->getDynamics()->getGroundNetwork()->findNode(node);
 
289
    waypoint* wpt = createOnGround(ac, buffer, tn->getGeod(), apt->getElevation(), ac->getPerformance()->vTaxi());
 
290
    wpt->routeIndex = route;
 
291
                waypoints.push_back(wpt);
 
292
  }
 
293
}
 
294
 
 
295
void FGAIFlightPlan::createDefaultLandingTaxi(FGAIAircraft *ac, FGAirport* aAirport)
 
296
{
 
297
  SGGeod lastWptPos = 
 
298
    SGGeod::fromDeg(waypoints.back()->longitude, waypoints.back()->latitude);
 
299
  double airportElev = aAirport->getElevation();
 
300
  
 
301
  waypoint* wpt;
 
302
  wpt = createOnGround(ac, "Runway Exit", lastWptPos, airportElev, ac->getPerformance()->vTaxi());
 
303
  waypoints.push_back(wpt);     
 
304
  wpt = createOnGround(ac, "Airport Center", aAirport->geod(), airportElev, ac->getPerformance()->vTaxi());
 
305
  waypoints.push_back(wpt);
 
306
  
 
307
  double heading, lat, lon;
 
308
  aAirport->getDynamics()->getParking(gateId, &lat, &lon, &heading);
 
309
  wpt = createOnGround(ac, "END", SGGeod::fromDeg(lon, lat), airportElev, ac->getPerformance()->vTaxi());
 
310
  waypoints.push_back(wpt);
 
311
}
 
312
 
 
313
void FGAIFlightPlan::createLandingTaxi(FGAIAircraft *ac, FGAirport *apt,
 
314
                                double radius, const string& fltType, 
 
315
                                const string& acType, const string& airline)
 
316
{
 
317
  double heading, lat, lon;
 
318
  apt->getDynamics()->getAvailableParking(&lat, &lon, &heading, 
 
319
        &gateId, radius, fltType, acType, airline);
 
320
  
 
321
  SGGeod lastWptPos = 
 
322
    SGGeod::fromDeg(waypoints.back()->longitude, waypoints.back()->latitude);
 
323
  FGGroundNetwork* gn = apt->getDynamics()->getGroundNetwork();
 
324
  
 
325
   // Find a route from runway end to parking/gate.
 
326
  if (!gn->exists()) {
 
327
    createDefaultLandingTaxi(ac, apt);
 
328
    return;
 
329
  }
 
330
  
 
331
        intVec ids;
 
332
  int runwayId = gn->findNearestNode(lastWptPos);
 
333
  // A negative gateId indicates an overflow parking, use a
 
334
  // fallback mechanism for this. 
 
335
  // Starting from gate 0 is a bit of a hack...
 
336
  //FGTaxiRoute route;
 
337
  delete taxiRoute;
 
338
  taxiRoute = new FGTaxiRoute;
 
339
  if (gateId >= 0)
 
340
    *taxiRoute = gn->findShortestRoute(runwayId, gateId);
 
341
  else
 
342
    *taxiRoute = gn->findShortestRoute(runwayId, 0);
 
343
  intVecIterator i;
 
344
  
 
345
  if (taxiRoute->empty()) {
 
346
    createDefaultLandingTaxi(ac, apt);
 
347
    return;
 
348
  }
 
349
  
 
350
  int node;
 
351
  taxiRoute->first();
 
352
  int size = taxiRoute->size();
 
353
  // Omit the last two waypoints, as 
 
354
  // those are created by createParking()
 
355
  int route;
 
356
  for (int i = 0; i < size-2; i++) {
 
357
    taxiRoute->next(&node, &route);
 
358
    char buffer[10];
 
359
    snprintf (buffer, 10, "%d", node);
 
360
    FGTaxiNode *tn = gn->findNode(node);
 
361
    waypoint* wpt = createOnGround(ac, buffer, tn->getGeod(), apt->getElevation(), ac->getPerformance()->vTaxi());
 
362
    wpt->routeIndex = route;
 
363
    waypoints.push_back(wpt);
 
364
  }
483
365
}
484
366
 
485
367
/*******************************************************************
486
368
 * CreateTakeOff 
487
369
 * initialize the Aircraft at the parking location
488
370
 ******************************************************************/
489
 
void FGAIFlightPlan::createTakeOff(bool firstFlight, FGAirport *apt, double speed, const string &fltType)
 
371
void FGAIFlightPlan::createTakeOff(FGAIAircraft *ac, bool firstFlight, FGAirport *apt, double speed, const string &fltType)
490
372
{
491
 
  double heading;
492
 
  double lat, lon, az;
493
 
  double lat2, lon2, az2;
494
 
  waypoint *wpt;
495
 
  
496
 
  // Get the current active runway, based on code from David Luff
497
 
  // This should actually be unified and extended to include 
498
 
  // Preferential runway use schema's 
499
 
  if (firstFlight)
 
373
    double accel    = ac->getPerformance()->acceleration();
 
374
    double vTaxi    = ac->getPerformance()->vTaxi();
 
375
    double vRotate  = ac->getPerformance()->vRotate();
 
376
//    double vTakeoff = ac->getPerformance()->vTakeoff();
 
377
    double vClimb   = ac->getPerformance()->vClimb();
 
378
    // Acceleration = dV / dT
 
379
    // Acceleration X dT = dV
 
380
    // dT = dT / Acceleration
 
381
    //d = (Vf^2 - Vo^2) / (2*a)
 
382
//    double accelTime = (vRotate - vTaxi) / accel;
 
383
    //cerr << "Using " << accelTime << " as total acceleration time" << endl;
 
384
    double accelDistance = (vRotate*vRotate - vTaxi*vTaxi) / (2*accel);
 
385
    //cerr << "Using " << accelDistance << " " << accel << " " << vRotate << endl;
 
386
    waypoint *wpt;
 
387
    // Get the current active runway, based on code from David Luff
 
388
    // This should actually be unified and extended to include 
 
389
    // Preferential runway use schema's 
 
390
    // NOTE: DT (2009-01-18: IIRC, this is currently already the case, 
 
391
    // because the getActive runway function takes care of that.
 
392
    if (firstFlight)
500
393
    {
501
 
      //string name;
502
 
      string rwyClass = getRunwayClassFromTrafficType(fltType);
503
 
      apt->getDynamics()->getActiveRunway(rwyClass, 1, activeRunway);
504
 
      rwy = apt->getRunwayByIdent(activeRunway);
 
394
        string rwyClass = getRunwayClassFromTrafficType(fltType);
 
395
        double heading = ac->getTrafficRef()->getCourse();
 
396
        apt->getDynamics()->getActiveRunway(rwyClass, 1, activeRunway, heading);
 
397
        rwy = apt->getRunwayByIdent(activeRunway);
505
398
    }
506
 
  // Acceleration point, 105 meters into the runway,
507
 
  heading = rwy->headingDeg();
508
 
  double azimuth = heading + 180.0;
509
 
  while ( azimuth >= 360.0 ) { azimuth -= 360.0; }
510
 
  geo_direct_wgs_84 ( 0, rwy->latitude(), rwy->longitude(), azimuth, 
511
 
                      rwy->lengthM() * 0.5 - 105.0,
512
 
                      &lat2, &lon2, &az2 );
513
 
  wpt = new waypoint; 
514
 
  wpt->name      = "accel"; 
515
 
  wpt->latitude  = lat2; 
516
 
  wpt->longitude = lon2; 
517
 
  wpt->altitude  = apt->getElevation();
518
 
  wpt->speed     = speed;  
519
 
  wpt->crossat   = -10000;
520
 
  wpt->gear_down = true;
521
 
  wpt->flaps_down= true;
522
 
  wpt->finished  = false;
523
 
  wpt->on_ground = true;
524
 
  wpt->routeIndex = 0;
525
 
  waypoints.push_back(wpt); 
526
 
  
527
 
  lat = lat2;
528
 
  lon = lon2;
529
 
  az  = az2;
530
 
  
531
 
  //Start Climbing to 3000 ft. Let's do this 
532
 
  // at the center of the runway for now:
533
 
  // 
534
 
  geo_direct_wgs_84 ( 0, lat, lon, heading, 
535
 
  2560 * SG_FEET_TO_METER,
536
 
  &lat2, &lon2, &az2 );
537
 
  
538
 
  wpt = new waypoint;
539
 
  wpt->name      = "SOC";
540
 
  wpt->latitude  = rwy->latitude();
541
 
  wpt->longitude = rwy->longitude();
542
 
  wpt->altitude  = apt->getElevation()+1000;
543
 
  wpt->speed     = speed; 
544
 
  wpt->crossat   = -10000;
545
 
  wpt->gear_down = true;
546
 
  wpt->flaps_down= true;
547
 
  wpt->finished  = false;
548
 
  wpt->on_ground = false;
549
 
  wpt->routeIndex = 0;
550
 
  waypoints.push_back(wpt);
551
 
 
552
 
 
553
 
 geo_direct_wgs_84 ( 0, rwy->latitude(), rwy->longitude(), heading, 
554
 
  rwy->lengthM(),
555
 
  &lat2, &lon2, &az2 );
556
 
 
557
 
  wpt = new waypoint;
558
 
  wpt->name      = "3000 ft";
559
 
  wpt->latitude  = lat2;
560
 
  wpt->longitude = lon2;
561
 
  wpt->altitude  = apt->getElevation()+3000;
562
 
  wpt->speed     = speed; 
563
 
  wpt->crossat   = -10000;
564
 
  wpt->gear_down = true;
565
 
  wpt->flaps_down= true;
566
 
  wpt->finished  = false;
567
 
  wpt->on_ground = false;
568
 
  wpt->routeIndex = 0;
569
 
  waypoints.push_back(wpt);
570
 
 
571
 
// Finally, add two more waypoints, so that aircraft will remain under
572
 
  // Tower control until they have reached the 3000 ft climb point
573
 
 
574
 
 
575
 
 geo_direct_wgs_84 ( 0, rwy->latitude(), rwy->longitude(), heading, 
576
 
  5000,
577
 
  &lat2, &lon2, &az2 );
578
 
 
579
 
 
580
 
  wpt = new waypoint;
581
 
  wpt->name      = "5000 ft";
582
 
  wpt->latitude  = lat2;
583
 
  wpt->longitude = lon2;
584
 
  wpt->altitude  = apt->getElevation()+5000;
585
 
  wpt->speed     = speed;
586
 
  wpt->crossat   = -10000;
587
 
  wpt->gear_down = true;
588
 
  wpt->flaps_down= true;
589
 
  wpt->finished  = false;
590
 
  wpt->on_ground = false;
591
 
  wpt->routeIndex = 0;
592
 
  waypoints.push_back(wpt);  
593
 
  //cerr << "Created takeoff plan : " << endl;
594
 
  //for (wpt_vector_iterator i = waypoints.begin(); i != waypoints.end(); i++) {
595
 
  //     cerr << "Waypoint Name: " << (*i)->name << ". Speed = " << (*i)->speed << endl;
596
 
  //}
597
 
 
598
 
 
599
 
 //  geo_direct_wgs_84 ( 0, rwy->latitude(), rwy->longitude(), heading, 
600
 
//   100000,
601
 
//   &lat2, &lon2, &az2 );
602
 
//   wpt = new waypoint;
603
 
//   wpt->name      = "5100 ft";
604
 
//   wpt->latitude  = lat2;
605
 
//   wpt->longitude = lon2;
606
 
//   wpt->altitude  = apt->getElevation()+5100;
607
 
//   wpt->speed     = speed; 
608
 
//   wpt->crossat   = -10000;
609
 
//   wpt->gear_down = true;
610
 
//   wpt->flaps_down= true;
611
 
//   wpt->finished  = false;
612
 
//   wpt->on_ground = false;
613
 
//   wpt->routeIndex = 0;
614
 
//   waypoints.push_back(wpt);
 
399
 
 
400
    double airportElev = apt->getElevation();
 
401
    // Acceleration point, 105 meters into the runway,
 
402
    SGGeod accelPoint = rwy->pointOnCenterline(105.0);
 
403
    wpt = createOnGround(ac, "accel", accelPoint, airportElev, vClimb);
 
404
    waypoints.push_back(wpt);
 
405
 
 
406
    //Start Climbing to 3000 ft. Let's do this 
 
407
    // at the center of the runway for now:
 
408
    SGGeod rotate = rwy->pointOnCenterline(105.0+accelDistance);
 
409
    wpt = cloneWithPos(ac, wpt, "SOC", rotate);
 
410
    wpt->altitude  = airportElev+1000;
 
411
    wpt->on_ground = false;
 
412
    waypoints.push_back(wpt);
 
413
 
 
414
    wpt = cloneWithPos(ac, wpt, "3000 ft", rwy->end());
 
415
    wpt->altitude  = airportElev+3000;
 
416
    waypoints.push_back(wpt);
 
417
 
 
418
    // Finally, add two more waypoints, so that aircraft will remain under
 
419
    // Tower control until they have reached the 3000 ft climb point
 
420
    SGGeod pt = rwy->pointOnCenterline(5000 + rwy->lengthM() * 0.5);
 
421
    wpt = cloneWithPos(ac, wpt, "5000 ft", pt);
 
422
    wpt->altitude  = airportElev+5000;
 
423
    waypoints.push_back(wpt);
615
424
}
616
 
 
 
425
  
617
426
/*******************************************************************
618
427
 * CreateClimb
619
428
 * initialize the Aircraft at the parking location
620
429
 ******************************************************************/
621
 
void FGAIFlightPlan::createClimb(bool firstFlight, FGAirport *apt, double speed, double alt, const string &fltType)
 
430
void FGAIFlightPlan::createClimb(FGAIAircraft *ac, bool firstFlight, FGAirport *apt, double speed, double alt, const string &fltType)
622
431
{
623
 
  double heading;
624
 
  //FGRunway rwy;
625
 
  double lat2, lon2, az2;
626
 
  //int direction;
627
432
  waypoint *wpt;
 
433
//  bool planLoaded = false;
 
434
  string fPLName;
 
435
  double vClimb   = ac->getPerformance()->vClimb();
628
436
 
629
 
 
630
 
  if (firstFlight)
631
 
    {
632
 
      //string name;
633
 
      string rwyClass = getRunwayClassFromTrafficType(fltType);
634
 
      apt->getDynamics()->getActiveRunway(rwyClass, 1, activeRunway);
635
 
      rwy = apt->getRunwayByIdent(activeRunway);
 
437
  if (firstFlight) {
 
438
    string rwyClass = getRunwayClassFromTrafficType(fltType);
 
439
    double heading = ac->getTrafficRef()->getCourse();
 
440
    apt->getDynamics()->getActiveRunway(rwyClass, 1, activeRunway, heading);
 
441
    rwy = apt->getRunwayByIdent(activeRunway);
 
442
  }
 
443
  if (sid) {
 
444
    for (wpt_vector_iterator i = sid->getFirstWayPoint(); 
 
445
         i != sid->getLastWayPoint(); 
 
446
         i++) {
 
447
            waypoints.push_back(clone(*(i)));
 
448
            //cerr << " Cloning waypoint " << endl;
636
449
    }
637
 
  
638
 
  
639
 
  heading = rwy->headingDeg();
640
 
  double azimuth = heading + 180.0;
641
 
  while ( azimuth >= 360.0 ) { azimuth -= 360.0; }
642
 
  //cerr << "Creating climb at : " << rwy._id << " " << rwy._rwy_no << endl;
643
 
  geo_direct_wgs_84 ( 0, rwy->latitude(), rwy->longitude(), heading, 
644
 
                      10*SG_NM_TO_METER,
645
 
                      &lat2, &lon2, &az2 );
646
 
  wpt = new waypoint;
647
 
  wpt->name      = "10000ft climb";
648
 
  wpt->latitude  = lat2;
649
 
  wpt->longitude = lon2;
650
 
  wpt->altitude  = 10000;
651
 
  wpt->speed     = speed; 
652
 
  wpt->crossat   = -10000;
653
 
  wpt->gear_down = true;
654
 
  wpt->flaps_down= true;
655
 
  wpt->finished  = false;
656
 
  wpt->on_ground = false;
657
 
  wpt->routeIndex = 0;
658
 
  waypoints.push_back(wpt); 
659
 
  
 
450
  } else  {
 
451
      SGGeod climb1 = rwy->pointOnCenterline(10*SG_NM_TO_METER);
 
452
      wpt = createInAir(ac, "10000ft climb", climb1, vClimb, 10000);
 
453
      wpt->gear_down = true;
 
454
      wpt->flaps_down= true;
 
455
      waypoints.push_back(wpt); 
660
456
 
661
 
  geo_direct_wgs_84 ( 0, rwy->latitude(), rwy->longitude(), heading, 
662
 
                      20*SG_NM_TO_METER,
663
 
                      &lat2, &lon2, &az2 );
664
 
  wpt = new waypoint;
665
 
  wpt->name      = "18000ft climb";
666
 
  wpt->latitude  = lat2;
667
 
  wpt->longitude = lon2;
668
 
  wpt->altitude  = 18000;
669
 
  wpt->speed     = speed; 
670
 
  wpt->crossat   = -10000;
671
 
  wpt->gear_down = true;
672
 
  wpt->flaps_down= true;
673
 
  wpt->finished  = false;
674
 
  wpt->on_ground = false;
675
 
  wpt->routeIndex = 0;
676
 
  waypoints.push_back(wpt); 
 
457
      SGGeod climb2 = rwy->pointOnCenterline(20*SG_NM_TO_METER);
 
458
      wpt = cloneWithPos(ac, wpt, "18000ft climb", climb2);
 
459
      wpt->altitude  = 18000;
 
460
      waypoints.push_back(wpt); 
 
461
   }
677
462
}
678
463
 
679
464
 
680
 
// /*******************************************************************
681
 
//  * CreateCruise
682
 
//  * initialize the Aircraft at the parking location
683
 
//  ******************************************************************/
684
 
// void FGAIFlightPlan::createCruise(bool firstFlight, FGAirport *dep, 
685
 
//                                FGAirport *arr, double latitude, 
686
 
//                                double longitude, double speed, 
687
 
//                                double alt)
688
 
// {
689
 
//   double wind_speed;
690
 
//   double wind_heading;
691
 
//   double heading;
692
 
//   double lat, lon, az;
693
 
//   double lat2, lon2, az2;
694
 
//   double azimuth;
695
 
//   waypoint *wpt;
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
 
  
710
 
 
711
 
//   // should be changed dynamically to allow "gen" and "mil"
712
 
//   arr->getDynamics()->getActiveRunway("com", 2, activeRunway);
713
 
//   if (!(globals->get_runways()->search(arr->getId(), 
714
 
//                                     activeRunway, 
715
 
//                                     &rwy)))
716
 
//     {
717
 
//       SG_LOG(SG_INPUT, SG_ALERT, "Failed to find runway " << 
718
 
//           activeRunway << 
719
 
//           " at airport     " << arr->getId());
720
 
//       exit(1);
721
 
//     }
722
 
//   heading = rwy->headingDeg();
723
 
//   azimuth = heading + 180.0;
724
 
//   while ( azimuth >= 360.0 ) { azimuth -= 360.0; }
725
 
  
726
 
  
727
 
//   geo_direct_wgs_84 ( 0, rwy->latitude(), rwy->longitude(), azimuth, 
728
 
//                    110000,
729
 
//                    &lat2, &lon2, &az2 );
730
 
//   wpt = new waypoint;
731
 
//   wpt->name      = "BOD";
732
 
//   wpt->latitude  = lat2;
733
 
//   wpt->longitude = lon2;
734
 
//   wpt->altitude  = alt;
735
 
//   wpt->speed     = speed; 
736
 
//   wpt->crossat   = alt;
737
 
//   wpt->gear_down = false;
738
 
//   wpt->flaps_down= false;
739
 
//   wpt->finished  = false;
740
 
//   wpt->on_ground = false;
741
 
//   waypoints.push_back(wpt); 
742
 
// }
743
465
 
744
466
/*******************************************************************
745
467
 * CreateDecent
746
468
 * initialize the Aircraft at the parking location
747
469
 ******************************************************************/
748
 
void FGAIFlightPlan::createDecent(FGAirport *apt, const string &fltType)
 
470
void FGAIFlightPlan::createDecent(FGAIAircraft *ac, FGAirport *apt, const string &fltType)
749
471
{
750
 
 
751
472
  // Ten thousand ft. Slowing down to 240 kts
752
 
  double heading;
753
 
  //FGRunway rwy;
754
 
  double lat2, lon2, az2;
755
 
  double azimuth;
756
 
  //int direction;
757
473
  waypoint *wpt;
 
474
double vDecent   = ac->getPerformance()->vDescent();
 
475
  double vApproach = ac->getPerformance()->vApproach();
758
476
 
759
477
  //Beginning of Decent
760
478
  //string name;
761
479
  // allow "mil" and "gen" as well
762
480
  string rwyClass = getRunwayClassFromTrafficType(fltType);
763
 
  apt->getDynamics()->getActiveRunway(rwyClass, 2, activeRunway);
 
481
  double heading = ac->getTrafficRef()->getCourse();
 
482
  apt->getDynamics()->getActiveRunway(rwyClass, 2, activeRunway, heading);
764
483
  rwy = apt->getRunwayByIdent(activeRunway);
765
484
     
766
 
  heading = rwy->headingDeg();
767
 
  azimuth = heading + 180.0;
768
 
  while ( azimuth >= 360.0 ) { azimuth -= 360.0; }
769
 
  geo_direct_wgs_84 ( 0, rwy->latitude(), rwy->longitude(), azimuth, 
770
 
                      100000,
771
 
                      &lat2, &lon2, &az2 );
772
 
  
773
 
  wpt = new waypoint;
774
 
  wpt->name      = "Dec 10000ft"; //wpt_node->getStringValue("name", "END");
775
 
  wpt->latitude  = lat2;
776
 
  wpt->longitude = lon2;
777
 
  wpt->altitude  = apt->getElevation();
778
 
  wpt->speed     = 240; 
 
485
  SGGeod descent1 = rwy->pointOnCenterline(-100000); // 100km out
 
486
  wpt = createInAir(ac, "Dec 10000ft", descent1, apt->getElevation(), vDecent);
779
487
  wpt->crossat   = 10000;
780
 
  wpt->gear_down = false;
781
 
  wpt->flaps_down= false;
782
 
  wpt->finished  = false;
783
 
  wpt->on_ground = false;
784
 
  wpt->routeIndex = 0;
785
488
  waypoints.push_back(wpt);  
786
489
  
787
490
  // Three thousand ft. Slowing down to 160 kts
788
 
  geo_direct_wgs_84 ( 0, rwy->latitude(), rwy->longitude(), azimuth, 
789
 
                      8*SG_NM_TO_METER,
790
 
                      &lat2, &lon2, &az2 );
791
 
  wpt = new waypoint;
792
 
  wpt->name      = "DEC 3000ft"; //wpt_node->getStringValue("name", "END");
793
 
  wpt->latitude  = lat2;
794
 
  wpt->longitude = lon2;
795
 
  wpt->altitude  = apt->getElevation();
796
 
  wpt->speed     = 160; 
 
491
  SGGeod descent2 = rwy->pointOnCenterline(-8*SG_NM_TO_METER); // 8nm out
 
492
  wpt = createInAir(ac, "DEC 3000ft", descent2, apt->getElevation(), vApproach);
797
493
  wpt->crossat   = 3000;
798
494
  wpt->gear_down = true;
799
495
  wpt->flaps_down= true;
800
 
  wpt->finished  = false;
801
 
  wpt->on_ground = false;
802
 
  wpt->routeIndex = 0;
803
496
  waypoints.push_back(wpt);
804
497
}
805
498
/*******************************************************************
806
499
 * CreateLanding
807
500
 * initialize the Aircraft at the parking location
808
501
 ******************************************************************/
809
 
void FGAIFlightPlan::createLanding(FGAirport *apt)
 
502
void FGAIFlightPlan::createLanding(FGAIAircraft *ac, FGAirport *apt)
810
503
{
811
 
  // Ten thousand ft. Slowing down to 150 kts
812
 
  double heading;
813
 
  //FGRunway rwy;
814
 
  double lat2, lon2, az2;
815
 
  double azimuth;
816
 
  //int direction;
 
504
  double vTouchdown   = ac->getPerformance()->vTouchdown();
 
505
  double vTaxi        = ac->getPerformance()->vTaxi();
 
506
 
817
507
  waypoint *wpt;
818
 
 
819
 
  
820
 
  heading = rwy->headingDeg();
821
 
  azimuth = heading + 180.0;
822
 
  while ( azimuth >= 360.0 ) { azimuth -= 360.0; }
823
 
 
 
508
  double aptElev = apt->getElevation();
824
509
  //Runway Threshold
825
 
 geo_direct_wgs_84 ( 0, rwy->latitude(), rwy->longitude(), azimuth, 
826
 
                     rwy->lengthM() *0.45,
827
 
                     &lat2, &lon2, &az2 );
828
 
  wpt = new waypoint;
829
 
  wpt->name      = "Threshold"; //wpt_node->getStringValue("name", "END");
830
 
  wpt->latitude  = lat2;
831
 
  wpt->longitude = lon2;
832
 
  wpt->altitude  = apt->getElevation();
833
 
  wpt->speed     = 150; 
834
 
  wpt->crossat   = apt->getElevation();
835
 
  wpt->gear_down = true;
836
 
  wpt->flaps_down= true;
837
 
  wpt->finished  = false;
838
 
  wpt->on_ground = true;
839
 
  wpt->routeIndex = 0;
 
510
  wpt = createOnGround(ac, "Threshold", rwy->threshold(), aptElev, vTouchdown);
 
511
  wpt->crossat = apt->getElevation();
840
512
  waypoints.push_back(wpt); 
841
513
 
842
 
 //Full stop at the runway centerpoint
843
 
 geo_direct_wgs_84 ( 0, rwy->latitude(), rwy->longitude(), azimuth, 
844
 
                     rwy->lengthFt() *0.45,
845
 
                      &lat2, &lon2, &az2 );
846
 
  wpt = new waypoint;
847
 
  wpt->name      = "Center"; //wpt_node->getStringValue("name", "END");
848
 
  wpt->latitude  = rwy->latitude();
849
 
  wpt->longitude = rwy->longitude();
850
 
  wpt->altitude  = apt->getElevation();
851
 
  wpt->speed     = 30; 
852
 
  wpt->crossat   = -10000;
853
 
  wpt->gear_down = true;
854
 
  wpt->flaps_down= true;
855
 
  wpt->finished  = false;
856
 
  wpt->on_ground = true;
857
 
  wpt->routeIndex = 0;
 
514
 // Roll-out
 
515
  wpt = createOnGround(ac, "Center", rwy->geod(), aptElev, vTaxi*2);
858
516
  waypoints.push_back(wpt);
859
517
 
860
 
 geo_direct_wgs_84 ( 0, rwy->latitude(), rwy->longitude(), heading, 
861
 
                     rwy->lengthM() *0.45,
862
 
                     &lat2, &lon2, &az2 );
863
 
  wpt = new waypoint;
864
 
  wpt->name      = "Threshold"; //wpt_node->getStringValue("name", "END");
865
 
  wpt->latitude  = lat2;
866
 
  wpt->longitude = lon2;
867
 
  wpt->altitude  = apt->getElevation();
868
 
  wpt->speed     = 15; 
 
518
  SGGeod rollOut = rwy->pointOnCenterline(rwy->lengthM() * 0.9);
 
519
  wpt = createOnGround(ac, "Roll Out", rollOut, aptElev, vTaxi);
869
520
  wpt->crossat   = apt->getElevation();
870
 
  wpt->gear_down = true;
871
 
  wpt->flaps_down= true;
872
 
  wpt->finished  = false;
873
 
  wpt->on_ground = true;
874
 
  wpt->routeIndex = 0;
875
521
  waypoints.push_back(wpt); 
876
522
}
877
523
 
879
525
 * CreateParking
880
526
 * initialize the Aircraft at the parking location
881
527
 ******************************************************************/
882
 
void FGAIFlightPlan::createParking(FGAirport *apt, double radius)
 
528
void FGAIFlightPlan::createParking(FGAIAircraft *ac, FGAirport *apt, double radius)
883
529
{
884
530
  waypoint* wpt;
885
 
  double lat, lat2;
886
 
  double lon, lon2;
887
 
  double az2;
888
 
  double heading;
 
531
  double aptElev = apt->getElevation();
 
532
  double lat = 0.0, lat2 = 0.0;
 
533
  double lon = 0.0, lon2 = 0.0;
 
534
  double az2 = 0.0;
 
535
  double heading = 0.0;
 
536
 
 
537
  double vTaxi        = ac->getPerformance()->vTaxi();
 
538
  double vTaxiReduced = vTaxi * (2.0/3.0);
889
539
  apt->getDynamics()->getParking(gateId, &lat, &lon, &heading);
890
540
  heading += 180.0;
891
541
  if (heading > 360)
893
543
  geo_direct_wgs_84 ( 0, lat, lon, heading, 
894
544
                      2.2*radius,           
895
545
                      &lat2, &lon2, &az2 );
896
 
  wpt = new waypoint;
897
 
  wpt->name      = "taxiStart";
898
 
  wpt->latitude  = lat2;
899
 
  wpt->longitude = lon2;
900
 
  wpt->altitude  = apt->getElevation();
901
 
  wpt->speed     = 10; 
902
 
  wpt->crossat   = -10000;
903
 
  wpt->gear_down = true;
904
 
  wpt->flaps_down= true;
905
 
  wpt->finished  = false;
906
 
  wpt->on_ground = true;
907
 
  wpt->routeIndex = 0;
908
 
  waypoints.push_back(wpt); 
 
546
  wpt = createOnGround(ac, "taxiStart", SGGeod::fromDeg(lon2, lat2), aptElev, vTaxiReduced);
 
547
  waypoints.push_back(wpt);
 
548
  
909
549
  geo_direct_wgs_84 ( 0, lat, lon, heading, 
910
550
                      0.1 *radius,           
911
551
                      &lat2, &lon2, &az2 );
912
 
  wpt = new waypoint;
913
 
  wpt->name      = "taxiStart";
914
 
  wpt->latitude  = lat2;
915
 
  wpt->longitude = lon2;
916
 
  wpt->altitude  = apt->getElevation();
917
 
  wpt->speed     = 10; 
918
 
  wpt->crossat   = -10000;
919
 
  wpt->gear_down = true;
920
 
  wpt->flaps_down= true;
921
 
  wpt->finished  = false;
922
 
  wpt->on_ground = true;
923
 
  wpt->routeIndex = 0;
 
552
          
 
553
  wpt = createOnGround(ac, "taxiStart2", SGGeod::fromDeg(lon2, lat2), aptElev, vTaxiReduced);
924
554
  waypoints.push_back(wpt);   
925
555
 
926
 
  wpt = new waypoint;
927
 
  wpt->name      = "END"; //wpt_node->getStringValue("name", "END");
928
 
  wpt->latitude  = lat;
929
 
  wpt->longitude = lon;
930
 
  wpt->altitude  = apt->getElevation();
931
 
  wpt->speed     = 15; 
932
 
  wpt->crossat   = -10000;
933
 
  wpt->gear_down = true;
934
 
  wpt->flaps_down= true;
935
 
  wpt->finished  = false;
936
 
  wpt->on_ground = true;
937
 
  wpt->routeIndex = 0;
 
556
  wpt = createOnGround(ac, "END", SGGeod::fromDeg(lon, lat), aptElev, vTaxiReduced);
938
557
  waypoints.push_back(wpt);
939
558
}
940
559