]> git.mxchange.org Git - flightgear.git/blobdiff - src/AIModel/AIFlightPlanCreatePushBack.cxx
Interim windows build fix
[flightgear.git] / src / AIModel / AIFlightPlanCreatePushBack.cxx
index e83e0dcbd85aa3dd2ebc12e7cb4cac5701d8e9b1..923596d04c6c73bab1e632d849e891b35db1ce3b 100644 (file)
-/******************************************************************************
- * AIFlightPlanCreatePushBack.cxx
- * Written by Durk Talsma, started August 1, 2007.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- *
- **************************************************************************/
-#include "AIFlightPlan.hxx"
+/****************************************************************************
+* AIFlightPlanCreatePushBack.cxx
+* Written by Durk Talsma, started August 1, 2007.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License as
+* published by the Free Software Foundation; either version 2 of the
+* License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful, but
+* WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+*
+**************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <cstdlib>
+#include <cstdio>
+
 #include <simgear/math/sg_geodesy.hxx>
+
+#include <Airports/airport.hxx>
 #include <Airports/runways.hxx>
+#include <Airports/dynamics.hxx>
+#include <Airports/groundnetwork.hxx>
 
 #include <Environment/environment_mgr.hxx>
 #include <Environment/environment.hxx>
 
-
-void FGAIFlightPlan::createPushBack(bool firstFlight, FGAirport *dep, 
-                                   double latitude,
-                                   double longitude,
-                                   double radius,
-                                   const string& fltType,
-                                   const string& aircraftType,
-                                   const string& airline)
+#include "AIFlightPlan.hxx"
+#include "AIAircraft.hxx"
+#include "performancedata.hxx"
+
+using std::string;
+
+// TODO: Use James Turner's createOnGround functions.
+bool FGAIFlightPlan::createPushBack(FGAIAircraft *ac,
+                                    bool firstFlight, FGAirport *dep,
+                                    double radius,
+                                    const string& fltType,
+                                    const string& aircraftType,
+                                    const string& airline)
 {
-    double lat, lon, heading;
-    FGTaxiRoute *pushBackRoute;
-    if (!(dep->getDynamics()->getGroundNetwork()->exists())) {
-       //cerr << "Push Back fallback" << endl;
-        createPushBackFallBack(firstFlight, dep, latitude, longitude,
+    double vTaxi = ac->getPerformance()->vTaxi();
+    double vTaxiBackward = vTaxi * (-2.0/3.0);
+    double vTaxiReduced  = vTaxi * (2.0/3.0);
+    
+    // Active runway can be conditionally set by ATC, so at the start of a new flight, this
+    // must be reset.
+    activeRunway.clear();
+
+    if (!(dep->getDynamics()->getGroundController()->exists())) {
+        //cerr << "Push Back fallback" << endl;
+        createPushBackFallBack(ac, firstFlight, dep,
                                radius, fltType, aircraftType, airline);
-    } else {
-        if (firstFlight) {
-             if (!(dep->getDynamics()->getAvailableParking(&lat, &lon, 
-                                                           &heading, &gateId, 
-                                                           radius, fltType, 
-                                                           aircraftType, airline))) {
-                   SG_LOG(SG_INPUT, SG_WARN, "Warning: Could not find parking for a " << 
-                                              aircraftType <<
-                                              " of flight type " << fltType << 
-                                              " of airline     " << airline <<
-                                              " at airport     " << dep->getId());
-                    char buffer[10];
-                    snprintf (buffer, 10, "%d", gateId);
-                    //FGTaxiNode *tn = dep->getDynamics()->getGroundNetwork()->findNode(node);
-                    waypoint *wpt;
-                    wpt = new waypoint;
-                    wpt->name      = string(buffer); // fixme: should be the name of the taxiway
-                    wpt->latitude  = lat;
-                    wpt->longitude = lon;
-                    // Elevation is currently disregarded when on_ground is true
-                    // because the AIModel obtains a periodic ground elevation estimate.
-                   wpt->altitude  = dep->getElevation();
-                   wpt->speed = -10;
-                   wpt->crossat   = -10000;
-                   wpt->gear_down = true;
-                   wpt->flaps_down= true;
-                   wpt->finished  = false;
-                   wpt->on_ground = true;
-                   wpt->routeIndex = -1;
-                   waypoints.push_back(wpt);
-            }
-        } else {
-           //cerr << "Push Back follow-up Flight" << endl;
-            dep->getDynamics()->getParking(gateId, &lat, &lon, &heading);
-        }
-        if (gateId < 0) {
-             createPushBackFallBack(firstFlight, dep, latitude, longitude,
-                                    radius, fltType, aircraftType, airline);
-             return;
-
-        }
-       //cerr << "getting parking " << gateId;
-        //cerr << " for a " << 
-        //                                      aircraftType <<
-        //                                      " of flight type " << fltType << 
-        //                                      " of airline     " << airline <<
-        //                                      " at airport     " << dep->getId() << endl;
-       FGParking *parking = dep->getDynamics()->getParking(gateId);
-        int pushBackNode = parking->getPushBackPoint();
-
-       // initialize the pushback route. Note that parts
-       // of this procedure should probably be done inside
-        // taxidraw. This code is likely to change once this
-        // this is fully implemented in taxidraw. Until that time,
-        // however, the full initialization procedure looks like this:
-        // 1) Build a list of all the nodes that are classified as 
-        //    pushBack hold points
-        // 2) For each hold point, use the dykstra algorithm to find a route
-        //    between the gate and the pushBack hold nodes, however use only
-        //    segments that are classified as "pushback" routes.
-        // 3) return the TaxiRoute class that is non empty. 
-        // 4) store refer this route in the parking object, for future use
-
-       if (pushBackNode < 0) {
-            //cerr << "Initializing PushBackRoute " << endl;
-            intVec pushBackNodes;
-           int nAINodes = dep->getDynamics()->getGroundNetwork()->getNrOfNodes();
-            int hits = 0;
-           parking->setPushBackPoint(0); // default in case no network was found.
-
-            // Collect all the nodes that are classified as having pushBack hold status
-            for (int i = 0; i < nAINodes; i++) {
-                if (dep->getDynamics()->getGroundNetwork()->findNode(i)->getHoldPointType() == 3) {
-                    pushBackNodes.push_back(i);
-                }
-           }
+      return true;
+    }
+  
+  // establish the parking position / gate if required
+    if (firstFlight) {
+      gate = dep->getDynamics()->getAvailableParking(radius, fltType,
+                                                       aircraftType, airline);
+      if (!gate.isValid()) {
+        SG_LOG(SG_AI, SG_WARN, "Warning: Could not find parking for a " <<
+               aircraftType <<
+               " of flight type " << fltType <<
+               " of airline     " << airline <<
+               " at airport     " << dep->getId());
+        return false;
+      }
+    }
+  
+    if (!gate.isValid()) {
+        createPushBackFallBack(ac, firstFlight, dep,
+                               radius, fltType, aircraftType, airline);
+        return true;
 
-            // For each node found in step 1, check if it can be reached
-            FGTaxiRoute route;
-            for (intVecIterator nodes = pushBackNodes.begin();
-                                 nodes != pushBackNodes.end();
-                                 nodes++) {
-               route = dep->getDynamics()->getGroundNetwork()->findShortestRoute(gateId, *nodes, false);
-                if (!(route.empty())) {
-                   //cerr << "Found Pushback route of size " << route.size() << endl;
-                    hits++;
-                    parking->setPushBackRoute(new FGTaxiRoute(route));
-                    parking->setPushBackPoint(*nodes);
-                   pushBackNode = *nodes;
-                }
-             }
-             if (hits == 0) {
-                 SG_LOG(SG_GENERAL, SG_INFO, "No pushback route found for gate " << gateId << " at " << dep->getId());
-             }
-             if (hits > 1) {
-                 SG_LOG(SG_GENERAL, SG_WARN, hits << " pushback routes found for gate " << gateId << " at " << dep->getId());
-             }
+    }
+  
+    FGGroundNetwork* groundNet = dep->getDynamics()->getGroundNetwork();
+    FGParking *parking = gate.parking();
+    if (parking && parking->getPushBackPoint() > 0) {
+        FGTaxiRoute route = groundNet->findShortestRoute(parking, parking->getPushBackPoint(), false);
+      
+        int size = route.size();
+        if (size < 2) {
+            SG_LOG(SG_AI, SG_ALERT, "Push back route from gate " << parking->ident() << " has only " << size << " nodes.");
+            SG_LOG(SG_AI, SG_ALERT, "Using  " << parking->getPushBackPoint());
         }
-        if (pushBackNode > 0) {
-            int node, rte;
-            //cerr << "Found valid pusback node " << pushBackNode << "for gate " << gateId << endl;
-            pushBackRoute = parking->getPushBackRoute();
-            int size = pushBackRoute->size();
-            if (size < 2) {
-               SG_LOG(SG_GENERAL, SG_WARN, "Push back route from gate " << gateId << " has only " << size << " nodes.");
-            }
-            pushBackRoute->first();
-            waypoint *wpt;
-           while(pushBackRoute->next(&node, &rte))
-             {
-               //FGTaxiNode *tn = apt->getDynamics()->getGroundNetwork()->findSegment(node)->getEnd();
-               char buffer[10];
-               snprintf (buffer, 10, "%d", node);
-               FGTaxiNode *tn = dep->getDynamics()->getGroundNetwork()->findNode(node);
-               //ids.pop_back();  
-               wpt = new waypoint;
-               wpt->name      = string(buffer); // fixme: should be the name of the taxiway
-               wpt->latitude  = tn->getLatitude();
-               wpt->longitude = tn->getLongitude();
-               // Elevation is currently disregarded when on_ground is true
-               // because the AIModel obtains a periodic ground elevation estimate.
-               wpt->altitude  = dep->getElevation();
-               wpt->speed = -10;
-               wpt->crossat   = -10000;
-               wpt->gear_down = true;
-               wpt->flaps_down= true;
-               wpt->finished  = false;
-               wpt->on_ground = true;
-               wpt->routeIndex = rte;
-               waypoints.push_back(wpt);
-             }
-              // some special considerations for the last point:
-              wpt->name = string("PushBackPoint");
-              wpt->speed = 15;
-        } else {
-           //cerr << "Creating direct forward departure route fragment" << endl;
-           double lat2, lon2, az2;
-           waypoint *wpt;
-           geo_direct_wgs_84 ( 0, lat, lon, heading, 
-                               2, &lat2, &lon2, &az2 );
-           wpt = new waypoint;
-           wpt->name      = "park2";
-           wpt->latitude  = lat2;
-           wpt->longitude = lon2;
-           wpt->altitude  = dep->getElevation();
-           wpt->speed     = 10; 
-           wpt->crossat   = -10000;
-           wpt->gear_down = true;
-           wpt->flaps_down= true;
-           wpt->finished  = false;
-           wpt->on_ground = true;
-           wpt->routeIndex = 0;
-           waypoints.push_back(wpt); 
-
-           geo_direct_wgs_84 ( 0, lat, lon, heading, 
-                               4, &lat2, &lon2, &az2 );
-           wpt = new waypoint;
-           wpt->name      = "name";
-           wpt->latitude  = lat2;
-           wpt->longitude = lon2;
-           wpt->altitude  = dep->getElevation();
-           wpt->speed     = 10; 
-           wpt->crossat   = -10000;
-           wpt->gear_down = true;
-           wpt->flaps_down= true;
-           wpt->finished  = false;
-           wpt->on_ground = true;
-           wpt->routeIndex = 0;
-           waypoints.push_back(wpt);
-
-           //cerr << "Creating final push forward point for gate " << gateId << endl;
-          FGTaxiNode *tn = dep->getDynamics()->getGroundNetwork()->findNode(gateId);
-          FGTaxiSegmentVectorIterator ts = tn->getBeginRoute();
-          FGTaxiSegmentVectorIterator te = tn->getEndRoute();
-          if (ts == te) {
-               SG_LOG(SG_GENERAL, SG_ALERT, "Gate " << gateId << "doesn't seem to have routes associated with it.");
-               //exit(1);
-          }
-           tn = (*ts)->getEnd();
-           lastNodeVisited = tn->getIndex();
-          if (tn == NULL) {
-               SG_LOG(SG_GENERAL, SG_ALERT, "No valid taxinode found");
-               exit(1);
-           }
-           wpt = new waypoint;
-           wpt->name      = "PushBackPoint";
-           wpt->latitude  = tn->getLatitude();
-           wpt->longitude = tn->getLongitude();
-           wpt->altitude  = dep->getElevation();
-           wpt->speed     = 10; 
-           wpt->crossat   = -10000;
-           wpt->gear_down = true;
-           wpt->flaps_down= true;
-           wpt->finished  = false;
-           wpt->on_ground = true;
-           wpt->routeIndex = (*ts)->getIndex();
-           waypoints.push_back(wpt);
-
-
+        
+        route.first();
+        FGTaxiNodeRef node;
+        int rte;
+      
+        while (route.next(node, &rte))
+        {
+            char buffer[10];
+            snprintf (buffer, 10, "%d",  node->getIndex());
+            FGAIWaypoint *wpt = createOnGround(ac, string(buffer), node->geod(), dep->getElevation(), vTaxiBackward);
+            
+            /*
+            if (previous) {
+              FGTaxiSegment* segment = groundNet->findSegment(previous, node);
+              wpt->setRouteIndex(segment->getIndex());
+            } else {
+              // not on the route yet, make up a unique segment ID
+              int x = (int) tn->guid();
+              wpt->setRouteIndex(x);
+            }*/
+            
+            wpt->setRouteIndex(rte);          
+            pushBackWaypoint(wpt);
+            //previous = node;
         }
-
+        // some special considerations for the last point:
+        waypoints.back()->setName(string("PushBackPoint"));
+        waypoints.back()->setSpeed(vTaxi);
+        ac->setTaxiClearanceRequest(true);
+    } else {  // In case of a push forward departure...
+        ac->setTaxiClearanceRequest(false);
+        double az2 = 0.0;
+
+      FGTaxiSegment* pushForwardSegment = dep->getDynamics()->getGroundNetwork()->findSegment(parking, 0);
+      // there aren't any routes for this parking.
+      if (!pushForwardSegment) {
+          SG_LOG(SG_AI, SG_ALERT, "Gate " << parking->ident() << "doesn't seem to have routes associated with it.");
+          return false;
+      }
+
+      lastNodeVisited = pushForwardSegment->getEnd();
+      double distance = pushForwardSegment->getLength();
+
+      double parkingHeading = parking->getHeading();
+    
+      for (int i = 1; i < 10; i++) {
+          SGGeod pushForwardPt;
+          SGGeodesy::direct(parking->geod(), parkingHeading,
+                            ((i / 10.0) * distance), pushForwardPt, az2);
+          char buffer[16];
+          snprintf(buffer, 16, "pushback-%02d", i);
+          FGAIWaypoint *wpt = createOnGround(ac, string(buffer), pushForwardPt, dep->getElevation(), vTaxiReduced);
+
+          wpt->setRouteIndex(pushForwardSegment->getIndex());
+          pushBackWaypoint(wpt);
+      }
+
+      waypoints.back()->setName(string("PushBackPoint"));
+      // cerr << "Done assinging new name" << endl;
     }
+
+    return true;
 }
 /*******************************************************************
- * createPushBackFallBack
- * This is the backup function for airports that don't have a 
- * network yet. 
- ******************************************************************/
-void FGAIFlightPlan::createPushBackFallBack(bool firstFlight, FGAirport *dep, 
-                                   double latitude,
-                                   double longitude,
-                                   double radius,
-                                   const string& fltType,
-                                   const string& aircraftType,
-                                   const string& airline)
+* createPushBackFallBack
+* This is the backup function for airports that don't have a
+* network yet.
+******************************************************************/
+void FGAIFlightPlan::createPushBackFallBack(FGAIAircraft *ac, bool firstFlight, FGAirport *dep,
+        double radius,
+        const string& fltType,
+        const string& aircraftType,
+        const string& airline)
 {
-  double heading;
-  double lat;
-  double lon;
-  double lat2;
-  double lon2;
-  double az2;
+    double az2 = 0.0;
 
+    double vTaxi = ac->getPerformance()->vTaxi();
+    double vTaxiBackward = vTaxi * (-2.0/3.0);
+    double vTaxiReduced  = vTaxi * (2.0/3.0);
 
+    double heading = 180.0; // this is a completely arbitrary heading!
+    FGAIWaypoint *wpt = createOnGround(ac, string("park"), dep->geod(), dep->getElevation(), vTaxiBackward);
 
-  dep->getDynamics()->getParking(-1, &lat, &lon, &heading);
+    pushBackWaypoint(wpt);
 
-  heading += 180.0;
-  if (heading > 360)
-    heading -= 360;
-  waypoint *wpt = new waypoint;
-  wpt->name      = "park";
-  wpt->latitude  = lat;
-  wpt->longitude = lon;
-  wpt->altitude  = dep->getElevation();
-  wpt->speed     = -10; 
-  wpt->crossat   = -10000;
-  wpt->gear_down = true;
-  wpt->flaps_down= true;
-  wpt->finished  = false;
-  wpt->on_ground = true;
+    SGGeod coord;
+    SGGeodesy::direct(dep->geod(), heading, 10, coord, az2);
+    wpt = createOnGround(ac, string("park2"), coord, dep->getElevation(), vTaxiBackward);
 
-  waypoints.push_back(wpt); 
+    pushBackWaypoint(wpt);
+  
+    SGGeodesy::direct(dep->geod(), heading, 2.2 * radius, coord, az2);
+    wpt = createOnGround(ac, string("taxiStart"), coord, dep->getElevation(), vTaxiReduced);
+    pushBackWaypoint(wpt);
 
-  geo_direct_wgs_84 ( 0, lat, lon, heading, 
-                     10, 
-                     &lat2, &lon2, &az2 );
-  wpt = new waypoint;
-  wpt->name      = "park2";
-  wpt->latitude  = lat2;
-  wpt->longitude = lon2;
-  wpt->altitude  = dep->getElevation();
-  wpt->speed     = -10; 
-  wpt->crossat   = -10000;
-  wpt->gear_down = true;
-  wpt->flaps_down= true;
-  wpt->finished  = false;
-  wpt->on_ground = true;
-  wpt->routeIndex = 0;
-  waypoints.push_back(wpt); 
-  geo_direct_wgs_84 ( 0, lat, lon, heading, 
-                     2.2*radius,           
-                     &lat2, &lon2, &az2 );
-  wpt = new waypoint;
-  wpt->name      = "taxiStart";
-  wpt->latitude  = lat2;
-  wpt->longitude = lon2;
-  wpt->altitude  = dep->getElevation();
-  wpt->speed     = 10; 
-  wpt->crossat   = -10000;
-  wpt->gear_down = true;
-  wpt->flaps_down= true;
-  wpt->finished  = false;
-  wpt->on_ground = true;
-  wpt->routeIndex = 0;
-  waypoints.push_back(wpt);
 }