]> git.mxchange.org Git - flightgear.git/commitdiff
Ground network distance tracking code. AIAircraft taxiing at airports
authordurk <durk>
Sat, 26 Aug 2006 07:22:20 +0000 (07:22 +0000)
committerdurk <durk>
Sat, 26 Aug 2006 07:22:20 +0000 (07:22 +0000)
maintain a resonable distance from each other while taxiing on the same
route. The current code does not yet take crossing routes or aircraft
taxiing into opposite directions into account.

12 files changed:
src/AIModel/AIAircraft.cxx
src/AIModel/AIAircraft.hxx
src/AIModel/AIFlightPlan.cxx
src/AIModel/AIFlightPlan.hxx
src/AIModel/AIFlightPlanCreate.cxx
src/AIModel/AIFlightPlanCreateCruise.cxx
src/Airports/groundnetwork.cxx
src/Airports/groundnetwork.hxx
src/Airports/simple.hxx
src/Traffic/SchedFlight.cxx
src/Traffic/Schedule.cxx
src/Traffic/Schedule.hxx

index 62edd27616e76aa0de8692424f29682a727b6054..93f6f96be597ea8c1bd55152fed6b00703303c29 100644 (file)
@@ -74,6 +74,8 @@ FGAIAircraft::FGAIAircraft(FGAISchedule *ref) :
         groundOffset = 0;
 
     fp = 0;
+    controller = 0;
+    prevController = 0;
     dt_count = 0;
     dt_elev_count = 0;
     use_perf_vs = true;
@@ -217,6 +219,19 @@ void FGAIAircraft::Run(double dt) {
 
         AccelTo( props->getDoubleValue("controls/flight/target-spd" ) );
     }
+    if (controller)
+      {
+       controller->update(getID(), 
+                          pos.getLatitudeDeg(), 
+                          pos.getLongitudeDeg(),
+                          hdg,
+                          speed,
+                          altitude_ft);
+       //if (controller->hasInstruction(getID()))
+       //  {
+           processATC(controller->getInstruction(getID()));
+           //  }
+      }
       
     double turn_radius_ft;
     double turn_circum_ft;
@@ -553,22 +568,11 @@ void FGAIAircraft::SetFlightPlan(FGAIFlightPlan *f) {
 void FGAIAircraft::ProcessFlightPlan( double dt, time_t now ) {
     bool eraseWaypoints;
     if (trafficRef) {
-//      FGAirport *arr;
-//      FGAirport *dep;
         eraseWaypoints = true;
-//      cerr << trafficRef->getRegistration();
-//      cerr << "Departure airport " << endl;
-//      dep = trafficRef->getDepartureAirport();
-//      if (dep)
-//          cerr << dep->getId() << endl;
-//      cerr << "Arrival   airport " << endl;
-//      arr = trafficRef->getArrivalAirport();
-//      if (arr)
-//          cerr << arr->getId() <<endl << endl;;
     } else
         eraseWaypoints = false;
 
-    //cerr << "Processing Flightplan" << endl;
     FGAIFlightPlan::waypoint* prev = 0; // the one behind you
     FGAIFlightPlan::waypoint* curr = 0; // the one ahead
     FGAIFlightPlan::waypoint* next = 0; // the next plus 1
@@ -577,75 +581,68 @@ void FGAIAircraft::ProcessFlightPlan( double dt, time_t now ) {
     next = fp->getNextWaypoint();
     dt_count += dt;
 
-    if (!prev) {  //beginning of flightplan, do this initialization once
-        //setBank(0.0);
-        spinCounter = 0;
-        tempReg = "";
-        //prev_dist_to_go = HUGE;
-        //cerr << "Before increment " << curr-> name << endl;
-        fp->IncrementWaypoint(eraseWaypoints);
-        //prev = fp->getPreviousWaypoint(); //first waypoint
-        //curr = fp->getCurrentWaypoint();  //second waypoint
-        //next = fp->getNextWaypoint();     //third waypoint (might not exist!)
-        //cerr << "After increment " << prev-> name << endl;
-        if (!(fp->getNextWaypoint()) && trafficRef)
-            loadNextLeg();
+    ///////////////////////////////////////////////////////////////////////////
+    // Initialize the flightplan
+    //////////////////////////////////////////////////////////////////////////
+    if (!prev) {
 
-        //cerr << "After load " << prev-> name << endl;
-        prev = fp->getPreviousWaypoint(); //first waypoint
-        curr = fp->getCurrentWaypoint();  //second waypoint
-        next = fp->getNextWaypoint();     //third waypoint (might not exist!)
-        //cerr << "After load " << prev-> name << endl;
-        setLatitude(prev->latitude);
-        setLongitude(prev->longitude);
-        setSpeed(prev->speed);
-        setAltitude(prev->altitude);
-
-        if (prev->speed > 0.0)
-            setHeading(fp->getBearing(prev->latitude, prev->longitude, curr));
-        else
-            setHeading(fp->getBearing(curr->latitude, curr->longitude, prev));
-
-        // If next doesn't exist, as in incrementally created flightplans for
-        // AI/Trafficmanager created plans,
-        // Make sure lead distance is initialized otherwise
-        if (next)
-            fp->setLeadDistance(speed, hdg, curr, next);
-
-        if (curr->crossat > -1000.0) { //use a calculated descent/climb rate
-            use_perf_vs = false;
-            tgt_vs = (curr->crossat - prev->altitude)
-                    / (fp->getDistanceToGo(pos.getLatitudeDeg(), pos.getLongitudeDeg(), curr)
-                    / 6076.0 / prev->speed*60.0);
-            tgt_altitude_ft = curr->crossat;
-        } else {
-            use_perf_vs = true;
-            tgt_altitude_ft = prev->altitude;
-        }
-        alt_lock = hdg_lock = true;
-        no_roll = prev->on_ground;
-        if (no_roll) {
-            Transform();         // make sure aip is initialized.
-            getGroundElev(60.1); // make sure it's exectuted first time around, so force a large dt value
-            //getGroundElev(60.1); // Need to do this twice.
-            //cerr << trafficRef->getRegistration() << " Setting altitude to " << tgt_altitude << endl;
-            doGroundAltitude(); //(tgt_altitude);
-        }
-        prevSpeed = 0;
-        //cout << "First waypoint:  " << prev->name << endl;
-        //cout << "  Target speed:    " << tgt_speed << endl;
-        //cout << "  Target altitude: " << tgt_altitude << endl;
-        //cout << "  Target heading:  " << tgt_heading << endl << endl;
-        //cerr << "Done Flightplan init" << endl;
-        return;
+      spinCounter = 0;
+      tempReg = "";
+      fp->IncrementWaypoint(eraseWaypoints);
+      if (!(fp->getNextWaypoint()) && trafficRef)
+       loadNextLeg();
+      
+      prev = fp->getPreviousWaypoint(); //first waypoint
+      curr = fp->getCurrentWaypoint();  //second waypoint
+      next = fp->getNextWaypoint();     //third waypoint (might not exist!)
+      
+      setLatitude(prev->latitude);
+      setLongitude(prev->longitude);
+      setSpeed(prev->speed);
+      setAltitude(prev->altitude);
+      
+      if (prev->speed > 0.0)
+       setHeading(fp->getBearing(prev->latitude, prev->longitude, curr));
+      else
+       setHeading(fp->getBearing(curr->latitude, curr->longitude, prev));
+      
+      // If next doesn't exist, as in incrementally created flightplans for
+      // AI/Trafficmanager created plans,
+      // Make sure lead distance is initialized otherwise
+      if (next)
+       fp->setLeadDistance(speed, hdg, curr, next);
+      
+      if (curr->crossat > -1000.0) { //use a calculated descent/climb rate
+       use_perf_vs = false;
+       tgt_vs = (curr->crossat - prev->altitude)
+         / (fp->getDistanceToGo(pos.getLatitudeDeg(), pos.getLongitudeDeg(), curr)
+            / 6076.0 / prev->speed*60.0);
+       tgt_altitude_ft = curr->crossat;
+      } else {
+       use_perf_vs = true;
+       tgt_altitude_ft = prev->altitude;
+      }
+      alt_lock = hdg_lock = true;
+      no_roll = prev->on_ground;
+      if (no_roll) {
+       Transform();         // make sure aip is initialized.
+       getGroundElev(60.1); // make sure it's exectuted first time around, so force a large dt value
+       doGroundAltitude(); 
+      }
+      // Make sure to announce the aircraft's position 
+      announcePositionToController();
+      prevSpeed = 0;
+      return;
     } // end of initialization
-
-    // let's only process the flight plan every 100 ms.
+    
+    ///////////////////////////////////////////////////////////////////////////
+    // Check Execution time (currently once every 100 ms
+    ///////////////////////////////////////////////////////////////////////////
     if ((dt_count < 0.1) || (now < fp->getStartTime())) {
-        //cerr  << "done fp dt" << endl;
-        return;
+      //cerr  << "done fp dt" << endl;
+      return;
     } else {
-        dt_count = 0;
+      dt_count = 0;
     }
     // check to see if we've reached the lead point for our next turn
     double dist_to_go = fp->getDistanceToGo(pos.getLatitudeDeg(), pos.getLongitudeDeg(), curr);
@@ -659,45 +656,18 @@ void FGAIAircraft::ProcessFlightPlan( double dt, time_t now ) {
         lead_dist = fabs(2*speed);  //don't skip over the waypoint
         //cerr << "Extending lead distance to " << lead_dist << endl;
     }
-//  FGAirport * apt = trafficRef->getDepartureAirport();
-//  if ((dist_to_go > prev_dist_to_go) && trafficRef && apt) {
-//      if (apt->getId() == string("EHAM"))
-//          cerr << "Alert: " << trafficRef->getRegistration() << " is moving away from waypoint " << curr->name  << endl
-//               << "Target heading : " << tgt_heading << "act heading " << hdg << " Tgt speed : " << tgt_speed << endl
-//               << "Lead distance : " << lead_dist  << endl
-//               << "Distance to go: " << dist_to_go << endl;
-//  }
-
-    prev_dist_to_go = dist_to_go;
-    //cerr << "2" << endl;
-    //if (no_roll)
-    //  lead_dist = 10.0;
-    //cout << "Leg : " << (fp->getLeg()-1) << ". dist_to_go: " << dist_to_go << ",  lead_dist: "
-    //     << lead_dist << ", tgt_speed " << tgt_speed << ", tgt_heading " << tgt_heading
-    //     << " speed " << speed << " hdg " << hdg << ". Altitude "  << altitude << " TAget alt :"
-    //     << tgt_altitude << endl;
+
+    //prev_dist_to_go = dist_to_go;
 
     if ( dist_to_go < lead_dist ) {
-        //prev_dist_to_go = HUGE;
-        // For traffic manager generated aircraft:
-        // check if the aircraft flies of of user range. And adjust the
-        // Current waypoint's elevation according to Terrain Elevation
         if (curr->finished) {  //end of the flight plan
             if (fp->getRepeat())
                 fp->restart();
             else
                 setDie(true);
-
-            //cerr << "Done die end of fp" << endl;
             return;
         }
 
-        // we've reached the lead-point for the waypoint ahead
-        //cerr << "4" << endl;
-        //cerr << "Situation after lead point" << endl;
-        //cerr << "Prviious: " << prev->name << endl;
-        //cerr << "Current : " << curr->name << endl;
-        //cerr << "Next    : " << next->name << endl;
         if (next) {
             tgt_heading = fp->getBearing(curr, next);
             spinCounter = 0;
@@ -712,7 +682,6 @@ void FGAIAircraft::ProcessFlightPlan( double dt, time_t now ) {
         next = fp->getNextWaypoint();
 
         // Now that we have incremented the waypoints, excute some traffic manager specific code
-        // based on the name of the waypoint we just passed.
         if (trafficRef) {
             double userLatitude  = fgGetDouble("/position/latitude-deg");
             double userLongitude = fgGetDouble("/position/longitude-deg");
@@ -722,57 +691,32 @@ void FGAIAircraft::ProcessFlightPlan( double dt, time_t now ) {
             user.CourseAndDistance(current, &course, &distance);
             if ((distance * SG_METER_TO_NM) > TRAFFICTOAIDIST) {
                 setDie(true);
-                //cerr << "done fp die out of range" << endl;
                 return;
             }
 
             FGAirport * dep = trafficRef->getDepartureAirport();
             FGAirport * arr = trafficRef->getArrivalAirport();
-            // At parking the beginning of the airport
             if (!( dep && arr)) {
                 setDie(true);
                 return;
             }
-
-            //if ((dep->getId() == string("EHAM") || (arr->getId() == string("EHAM")))) {
-            //    cerr << trafficRef->getRegistration()
-            //         << " Enroute from " << dep->getId()
-            //         << " to "           << arr->getId()
-            //         << " just crossed " << prev->name
-            //         << " Assigned rwy     " << fp->getRunwayId()
-            //         << " " << fp->getRunway() << endl;
-            // }
-            //if ((dep->getId() == string("EHAM")) && (prev->name == "park2")) {
-            //    cerr << "Schiphol ground "
-            //         << trafficRef->getCallSign();
-            //    if (trafficRef->getHeavy())
-            //        cerr << "Heavy";
-            //    cerr << ", is type "
-            //         << trafficRef->getAircraft()
-            //         << " ready to go. IFR to "
-            //         << arr->getId() <<endl;
-            // }
-
+           // This waypoint marks the fact that the aircraft has passed the initial taxi
+           // departure waypoint, so it can release the parking.
             if (prev->name == "park2")
                 dep->getDynamics()->releaseParking(fp->getGate());
-
-            // Some debug messages, specific to testing the Logical networks.
-            // if ((arr->getId() == string("EHAM")) && (prev->name  == "Center")) {
-            //     cerr << "Schiphol ground "
-            //          << trafficRef->getRegistration() << " "
-            //          << trafficRef->getCallSign();
-            //     if (trafficRef->getHeavy())
-            //         cerr << "Heavy";
-            //     cerr << ", arriving from " << dep->getName() ;
-            //     cerr << " landed runway "
-            //          << fp->getRunway()
-            //          << " request taxi to gate "
-            //          << arr->getDynamics()->getParkingName(fp->getGate())
-            //          << endl;
-            // }
-            if (prev->name == "END")
-                fp->setTime(trafficRef->getDepartureTime());
-            //cerr << "5" << endl;
+           // This is the last taxi waypoint, and marks the the end of the flight plan
+           // so, the schedule should update and wait for the next departure time. 
+            if (prev->name == "END") {
+             // make sure to wait at least 20 minutes at parking to prevent "nervous" taxi behavior
+             // delayed aircraft. 
+             time_t nextDeparture = trafficRef->getDepartureTime();
+             if (nextDeparture < (now+1200)) {
+               nextDeparture = now + 1200; 
+             }
+             fp->setTime(trafficRef->getDepartureTime());
+           }
+           announcePositionToController();
+            
         }
 
         if (next) {
@@ -843,6 +787,11 @@ void FGAIAircraft::ProcessFlightPlan( double dt, time_t now ) {
     }
 }
 
+void FGAIAircraft::initializeFlightPlan() 
+{
+
+}
+
 
 bool FGAIAircraft::_getGearDown() const {
     return ((props->getFloatValue("position/altitude-agl-ft") < 900.0)
@@ -1013,3 +962,82 @@ void FGAIAircraft::doGroundAltitude() {
       altitude_ft += 0.1 * ((tgt_altitude_ft+groundOffset) - altitude_ft);
 }
 
+
+void FGAIAircraft::announcePositionToController() 
+{
+  if (trafficRef) {
+    //FGTaxiRoute *taxiRoute = fp->getTaxiRoute();
+    
+    int leg = fp->getLeg();
+    
+    // For starters, I'll only do this for departure and arrival taxi. The mechanism
+    // could be extended to include any controller however. 
+    //int node, currentTaxiSegment;
+    //if (taxiRoute->next(&node, &currentTaxiSegment)) {
+    if (fp->getCurrentWaypoint()->routeIndex != 0) {
+      //char buffer[10];
+      //snprintf (buffer, 10, "%d", node);
+      switch (leg) {
+      case 3:
+       cerr << trafficRef->getRegistration() 
+            << " taxiing to runway at segment " 
+            << fp->getCurrentWaypoint()->routeIndex
+            << endl;
+       //cerr << "Match check between taxisegment and taxiroute : " << node << " " 
+       //     << fp->getCurrentWaypoint()->name << endl;
+       if (trafficRef->getDepartureAirport()->getDynamics()->getGroundNetwork()->exists())
+         controller = trafficRef->getDepartureAirport()->getDynamics()->getGroundNetwork();
+       break;
+      case 9:
+       cerr << trafficRef->getRegistration() 
+            << " taxiing to parking at segment " 
+            << fp->getCurrentWaypoint()->routeIndex
+            << endl;
+       if (trafficRef->getArrivalAirport()->getDynamics()->getGroundNetwork()->exists())
+         controller = trafficRef->getArrivalAirport()->getDynamics()->getGroundNetwork();
+       break;
+      default: 
+       controller = 0;
+       break;
+      }
+    } else {
+      //fp->deleteTaxiRoute();
+      controller = 0;
+    }
+    if ((controller != prevController) && (prevController != 0)) {
+      prevController->signOff(getID());
+      cerr << trafficRef->getRegistration() 
+          << " signing off " << endl;
+    }
+    prevController = controller;
+    if (controller) {
+      controller->announcePosition(getID(), fp, fp->getCurrentWaypoint()->routeIndex,
+                                  _getLatitude(), _getLongitude(), hdg, speed, altitude_ft, 
+                                  trafficRef->getRadius());
+    }
+  }
+}
+
+
+void FGAIAircraft::processATC(FGATCInstruction instruction)
+{
+  //cerr << "Processing ATC instruction (not Implimented yet)" << endl;
+  if (instruction.getHoldPattern   ()) {
+  }
+  if (instruction.getHoldPosition  ()) {
+  }
+  if (instruction.getChangeSpeed   ()) {
+    AccelTo(instruction.getSpeed());
+  }else {
+    if (fp) AccelTo(fp->getPreviousWaypoint()->speed);
+  }
+  if (instruction.getChangeHeading ()) { 
+    hdg_lock = false;
+    TurnTo(instruction.getHeading());
+  } else {
+    if (fp) {hdg_lock = true;}
+  }
+  if (instruction.getChangeAltitude()) { 
+  }
+
+}
index b50ea691f80914daff6937752f50ea251e23dbf2..095b21b3797ff14ca897ae670fdd94461c5da646 100644 (file)
@@ -71,6 +71,7 @@ public:
     void SetPerformance(const PERF_STRUCT *ps);
     void setFlightPlan(const std::string& fp, bool repat = false);
     void SetFlightPlan(FGAIFlightPlan *f);
+    void initializeFlightPlan();
     FGAIFlightPlan* GetFlightPlan() const { return fp; };
     void AccelTo(double speed);
     void PitchTo(double angle);
@@ -89,11 +90,15 @@ public:
     void setAcType(const string& ac) { acType = ac; };
     void setCompany(const string& comp) { company = comp;};
 
+    void announcePositionToController();
+    void processATC(FGATCInstruction instruction);
+
     inline void SetTanker(bool setting) { isTanker = setting; };
     virtual const char* getTypeString(void) const { return "aircraft"; }
 
 private:
     FGAISchedule *trafficRef;
+    FGATCController *controller, *prevController; 
 
     bool hdg_lock;
     bool alt_lock;
index 1ffc4328383dac203d0e49b247cee182802da06c..8f03b93a7d4e58037af1ba7e6f664a8b0f861e4b 100644 (file)
@@ -296,12 +296,6 @@ FGAIFlightPlan::FGAIFlightPlan(const std::string& p,
 FGAIFlightPlan::~FGAIFlightPlan()
 {
   deleteWaypoints();
-  //waypoints.clear();
-  //while (waypoints.begin() != waypoints.end())
-  //  {
-  //    delete *(waypoints.begin());
-  //    waypoints.erase (waypoints.begin());
-  //  }
   if (taxiRoute)
     delete taxiRoute;
 }
@@ -491,3 +485,20 @@ void FGAIFlightPlan::restart()
 {
   wpt_iterator = waypoints.begin();
 }
+
+
+void FGAIFlightPlan::deleteTaxiRoute() 
+{
+  if (taxiRoute)
+    delete taxiRoute;
+  taxiRoute = 0;
+}
+
+
+int FGAIFlightPlan::getRouteIndex(int i) {
+  if ((i > 0) && (i < waypoints.size())) {
+    return waypoints[i]->routeIndex;
+  }
+  else
+    return 0;
+}
index 023ad85a093f2b97e905377e8677e03ef3e13490..28f285b171bd77ee44e7d4ebcb43a3e8dd83797e 100644 (file)
@@ -48,6 +48,7 @@ public:
    bool gear_down;
    bool flaps_down;
    bool on_ground;
+    int routeIndex;  // For AI/ATC purposes;
   } waypoint;
 
    FGAIFlightPlan(const string& filename);
@@ -93,8 +94,11 @@ public:
   void setRepeat(bool r) { repeat = r; };
   bool getRepeat(void) const { return repeat; };
   void restart(void);
+  int getNrOfWayPoints() { return waypoints.size(); };
+  int getRouteIndex(int i); // returns the AI related index of this current routes. 
+  FGTaxiRoute *getTaxiRoute() { return taxiRoute; };
+  void deleteTaxiRoute();
   
-  int getNrOfWayPoints() { return waypoints.end() - waypoints.begin(); };
 
 private:
   FGRunway rwy;
index 2c6646d85a2cc84a54f733146fcb387a6b6f16d4..adeb775f9913166705a83b4e37d914849290a502 100644 (file)
@@ -44,7 +44,7 @@ void FGAIFlightPlan::create(FGAirport *dep, FGAirport *arr, int legNr,
   int currWpt = wpt_iterator - waypoints.begin();
   switch(legNr)
     {
-    case 1:
+      case 1:
       createPushBack(firstFlight,dep, latitude, longitude, 
                     radius, fltType, aircraftType, airline);
       break;
@@ -140,10 +140,9 @@ void FGAIFlightPlan::createPushBack(bool firstFlight, FGAirport *dep,
   wpt->flaps_down= true;
   wpt->finished  = false;
   wpt->on_ground = true;
+
   waypoints.push_back(wpt); 
   
-  // Add park twice, because it uses park once for initialization and once
-  // to trigger the departure ATC message 
   geo_direct_wgs_84 ( 0, lat, lon, heading, 
                      10, 
                      &lat2, &lon2, &az2 );
@@ -158,6 +157,7 @@ void FGAIFlightPlan::createPushBack(bool firstFlight, FGAirport *dep,
   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,           
@@ -173,6 +173,7 @@ void FGAIFlightPlan::createPushBack(bool firstFlight, FGAirport *dep,
   wpt->flaps_down= true;
   wpt->finished  = false;
   wpt->on_ground = true;
+  wpt->routeIndex = 0;
   waypoints.push_back(wpt);  
 }
 
@@ -280,6 +281,7 @@ void FGAIFlightPlan::createTaxi(bool firstFlight, int direction,
            wpt->flaps_down= true;
            wpt->finished  = false;
            wpt->on_ground = true;
+           wpt->routeIndex = 0;
            waypoints.push_back(wpt);
            
            //Add the runway startpoint;
@@ -294,6 +296,7 @@ void FGAIFlightPlan::createTaxi(bool firstFlight, int direction,
            wpt->flaps_down= true;
            wpt->finished  = false;
            wpt->on_ground = true;
+           wpt->routeIndex = 0;
            waypoints.push_back(wpt);   
          } else {
            int node;
@@ -312,8 +315,7 @@ void FGAIFlightPlan::createTaxi(bool firstFlight, int direction,
                isPushBackPoint = false;
                taxiRoute->next(&node);
              }
-           }
-           else {
+           } else {
              //chop off the first two waypoints, because
              // those have already been created
              // by create pushback
@@ -323,13 +325,16 @@ void FGAIFlightPlan::createTaxi(bool firstFlight, int direction,
                taxiRoute->next(&node);
              }
            }
-           while(taxiRoute->next(&node))
+           int route;
+           while(taxiRoute->next(&node, &route))
              {
                //FGTaxiNode *tn = apt->getDynamics()->getGroundNetwork()->findSegment(node)->getEnd();
+               char buffer[10];
+               snprintf (buffer, 10, "%d", node);
                FGTaxiNode *tn = apt->getDynamics()->getGroundNetwork()->findNode(node);
                //ids.pop_back();  
                wpt = new waypoint;
-               wpt->name      = "taxiway"; // fixme: should be the name of the taxiway
+               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
@@ -347,23 +352,27 @@ void FGAIFlightPlan::createTaxi(bool firstFlight, int direction,
                wpt->flaps_down= true;
                wpt->finished  = false;
                wpt->on_ground = true;
+               wpt->routeIndex = route;
                waypoints.push_back(wpt);
              }
            //cerr << endl;
            // finally, rewind the taxiRoute object to the point where we started
+           // generating the Flightplan, for AI use.
+           // This is a bit tricky, because the 
            taxiRoute->first();
            if (firstFlight) { 
-             for (int i = 0; i < nrWaypointsToSkip-2; i++) {
+             for (int i = 0; i < nrWaypointsToSkip-1; i++) {
                taxiRoute->next(&node);
              }
            } else {
              int size = taxiRoute->size();
              if (size > 2) {
-               taxiRoute->next(&node);
-               taxiRoute->next(&node);
+               //taxiRoute->next(&node);
+               //taxiRoute->next(&node);       
+               //taxiRoute->next(&node);
              }
            }
-         }
+         } // taxiRoute not empty
        }
       else 
        {
@@ -380,6 +389,7 @@ void FGAIFlightPlan::createTaxi(bool firstFlight, int direction,
          wpt->flaps_down= true;
          wpt->finished  = false;
          wpt->on_ground = true;
+         wpt->routeIndex = 0;
          waypoints.push_back(wpt);
          
          //Add the runway startpoint;
@@ -394,6 +404,7 @@ void FGAIFlightPlan::createTaxi(bool firstFlight, int direction,
          wpt->flaps_down= true;
          wpt->finished  = false;
          wpt->on_ground = true;
+         wpt->routeIndex = 0;
          waypoints.push_back(wpt);
        }
     }
@@ -441,6 +452,7 @@ void FGAIFlightPlan::createTaxi(bool firstFlight, int direction,
            wpt->flaps_down= true;
            wpt->finished  = false;
            wpt->on_ground = true;
+           wpt->routeIndex = 0;
            waypoints.push_back(wpt);
            
            //Add the runway startpoint;
@@ -455,6 +467,7 @@ void FGAIFlightPlan::createTaxi(bool firstFlight, int direction,
            wpt->flaps_down= true;
            wpt->finished  = false;
            wpt->on_ground = true;
+           wpt->routeIndex = 0;
            waypoints.push_back(wpt);   
          } else {
            int node;
@@ -462,13 +475,17 @@ void FGAIFlightPlan::createTaxi(bool firstFlight, int direction,
            int size = taxiRoute->size();
            // Omit the last two waypoints, as 
            // those are created by createParking()
+           int route;
            for (int i = 0; i < size-2; i++)
              {
-               taxiRoute->next(&node);
+               taxiRoute->next(&node, &route);
+               char buffer[10];
+               snprintf (buffer, 10, "%d", node);
                //FGTaxiNode *tn = apt->getDynamics()->getGroundNetwork()->findNode(node);
                FGTaxiNode *tn = apt->getDynamics()->getGroundNetwork()->findNode(node);
                wpt = new waypoint;
-               wpt->name      = "taxiway"; // fixme: should be the name of the taxiway
+               //wpt->name      = "taxiway"; // fixme: should be the name of the taxiway
+               wpt->name      = string(buffer);// fixme: should be the name of the taxiway
                wpt->latitude  = tn->getLatitude();
                wpt->longitude = tn->getLongitude();
                wpt->altitude  = apt->getElevation();
@@ -478,8 +495,11 @@ void FGAIFlightPlan::createTaxi(bool firstFlight, int direction,
                wpt->flaps_down= true;
                wpt->finished  = false;
                wpt->on_ground = true;
+               wpt->routeIndex = route;
                waypoints.push_back(wpt);
              }
+           //taxiRoute->first();
+           //taxiRoute->next(&node);
          }
        }
       else
@@ -503,6 +523,7 @@ void FGAIFlightPlan::createTaxi(bool firstFlight, int direction,
          wpt->flaps_down= true;
          wpt->finished  = false;
          wpt->on_ground = true;
+         wpt->routeIndex = 0;
          waypoints.push_back(wpt);
         
          wpt = new waypoint;
@@ -516,6 +537,7 @@ void FGAIFlightPlan::createTaxi(bool firstFlight, int direction,
          wpt->flaps_down= true;
          wpt->finished  = false;
          wpt->on_ground = true;
+         wpt->routeIndex = 0;
          waypoints.push_back(wpt); 
 
          //waypoint* wpt;
@@ -538,6 +560,7 @@ void FGAIFlightPlan::createTaxi(bool firstFlight, int direction,
          wpt->flaps_down= true;
          wpt->finished  = false;
          wpt->on_ground = true;
+         wpt->routeIndex = 0;
          waypoints.push_back(wpt);
        }
       
@@ -592,6 +615,7 @@ void FGAIFlightPlan::createTakeOff(bool firstFlight, FGAirport *apt, double spee
   wpt->flaps_down= true;
   wpt->finished  = false;
   wpt->on_ground = true;
+  wpt->routeIndex = 0;
   waypoints.push_back(wpt); 
   
   lat = lat2;
@@ -614,6 +638,7 @@ void FGAIFlightPlan::createTakeOff(bool firstFlight, FGAirport *apt, double spee
   wpt->flaps_down= true;
   wpt->finished  = false;
   wpt->on_ground = false;
+  wpt->routeIndex = 0;
   waypoints.push_back(wpt);
 }
  
@@ -667,6 +692,7 @@ void FGAIFlightPlan::createClimb(bool firstFlight, FGAirport *apt, double speed,
   wpt->flaps_down= true;
   wpt->finished  = false;
   wpt->on_ground = false;
+  wpt->routeIndex = 0;
   waypoints.push_back(wpt); 
   
 
@@ -684,6 +710,7 @@ void FGAIFlightPlan::createClimb(bool firstFlight, FGAirport *apt, double speed,
   wpt->flaps_down= true;
   wpt->finished  = false;
   wpt->on_ground = false;
+  wpt->routeIndex = 0;
   waypoints.push_back(wpt); 
 }
 
@@ -799,6 +826,7 @@ void FGAIFlightPlan::createDecent(FGAirport *apt)
   wpt->flaps_down= false;
   wpt->finished  = false;
   wpt->on_ground = false;
+  wpt->routeIndex = 0;
   waypoints.push_back(wpt);  
   
   // Three thousand ft. Slowing down to 160 kts
@@ -816,6 +844,7 @@ void FGAIFlightPlan::createDecent(FGAirport *apt)
   wpt->flaps_down= true;
   wpt->finished  = false;
   wpt->on_ground = false;
+  wpt->routeIndex = 0;
   waypoints.push_back(wpt);
 }
 /*******************************************************************
@@ -852,6 +881,7 @@ void FGAIFlightPlan::createLanding(FGAirport *apt)
   wpt->flaps_down= true;
   wpt->finished  = false;
   wpt->on_ground = true;
+  wpt->routeIndex = 0;
   waypoints.push_back(wpt); 
 
  //Full stop at the runway centerpoint
@@ -869,6 +899,7 @@ void FGAIFlightPlan::createLanding(FGAirport *apt)
   wpt->flaps_down= true;
   wpt->finished  = false;
   wpt->on_ground = true;
+  wpt->routeIndex = 0;
   waypoints.push_back(wpt);
 
  geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, heading, 
@@ -885,6 +916,7 @@ void FGAIFlightPlan::createLanding(FGAirport *apt)
   wpt->flaps_down= true;
   wpt->finished  = false;
   wpt->on_ground = true;
+  wpt->routeIndex = 0;
   waypoints.push_back(wpt); 
 }
 
@@ -917,6 +949,7 @@ void FGAIFlightPlan::createParking(FGAirport *apt, double radius)
   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, 
                      0.1 *radius,           
@@ -932,6 +965,7 @@ void FGAIFlightPlan::createParking(FGAirport *apt, double radius)
   wpt->flaps_down= true;
   wpt->finished  = false;
   wpt->on_ground = true;
+  wpt->routeIndex = 0;
   waypoints.push_back(wpt);   
 
   wpt = new waypoint;
@@ -945,5 +979,6 @@ void FGAIFlightPlan::createParking(FGAirport *apt, double radius)
   wpt->flaps_down= true;
   wpt->finished  = false;
   wpt->on_ground = true;
+  wpt->routeIndex = 0;
   waypoints.push_back(wpt);
 }
index c60e40bb207d3bddb370100b37a9b1ae53b94b38..fc81c4dbd088700858beb4d46a86c842cd0cf947 100755 (executable)
@@ -340,6 +340,7 @@ void FGAIFlightPlan::createCruise(bool firstFlight, FGAirport *dep,
   wpt->flaps_down= false;
   wpt->finished  = false;
   wpt->on_ground = false;
+  wpt->routeIndex = 0;
   waypoints.push_back(wpt); 
   
  
@@ -373,5 +374,6 @@ void FGAIFlightPlan::createCruise(bool firstFlight, FGAirport *dep,
   wpt->flaps_down= false;
   wpt->finished  = false;
   wpt->on_ground = false;
+  wpt->routeIndex = 0;
   waypoints.push_back(wpt); 
 }
index 862c359df79a483d95429610257c371a50210778..835fbb52bf5675c67e4f993dcc16dc73314d747c 100644 (file)
@@ -41,6 +41,8 @@
 //#include <Main/fg_props.hxx>
 //#include <Airports/runways.hxx>
 
+#include <AIModel/AIFlightPlan.hxx>
+
 //#include STL_STRING
 
 #include "groundnetwork.hxx"
@@ -103,7 +105,9 @@ void FGTaxiSegment::setTrackDistance()
                     0);
   first.CourseAndDistance(second, &course, &length);
 }
-
+/***************************************************************************
+ * FGTaxiRoute
+ **************************************************************************/
 bool FGTaxiRoute::next(int *nde) 
 { 
   //for (intVecIterator i = nodes.begin(); i != nodes.end(); i++)
@@ -119,8 +123,9 @@ bool FGTaxiRoute::next(int *nde)
   if (currNode == nodes.end())
     return false;
   *nde = *(currNode); 
+  if (currNode != nodes.begin()) // make sure route corresponds to the end node
+    currRoute++;
   currNode++;
-  currRoute++;
   return true;
 };
 
@@ -140,11 +145,123 @@ bool FGTaxiRoute::next(int *nde, int *rte)
   if (currNode == nodes.end())
     return false;
   *nde = *(currNode); 
-  *rte = *(currRoute);
+  //*rte = *(currRoute);
+  if (currNode != nodes.begin()) // Make sure route corresponds to the end node
+    {
+      *rte = *(currRoute);
+      currRoute++;
+    }
+  else
+    {
+      // If currNode points to the first node, this means the aircraft is not on the taxi node
+      // yet. Make sure to return a unique identifyer in this situation though, because otherwise
+      // the speed adjust AI code may be unable to resolve whether two aircraft are on the same 
+      // taxi route or not. the negative of the preceding route seems a logical choice, as it is 
+      // unique for any starting location. 
+      // Note that this is probably just a temporary fix until I get Parking / tower control working.
+      *rte = -1 * *(currRoute); 
+    }
   currNode++;
-  currRoute++;
   return true;
 };
+
+void FGTaxiRoute::rewind(int route)
+{
+  int currPoint;
+  int currRoute;
+  first();
+  do {
+    if (!(next(&currPoint, &currRoute))) { 
+      SG_LOG(SG_GENERAL,SG_ALERT, "Error in rewinding TaxiRoute: current" << currRoute 
+            << " goal " << route);
+    }
+  } while (currRoute != route);
+}
+
+/***************************************************************************
+ * FGTrafficRecord
+ **************************************************************************/
+void FGTrafficRecord::setPositionAndIntentions(int pos, FGAIFlightPlan *route)
+{
+  currentPos = pos;
+  if (intentions.size()) {
+    if (*intentions.begin() != pos) {
+      SG_LOG(SG_GENERAL, SG_ALERT, "Error in FGTrafficRecord::setPositionAndIntentions");
+      cerr << "Pos : " << pos << " Curr " << *(intentions.begin())  << endl;
+      for (intVecIterator i = intentions.begin(); i != intentions.end() ; i++) {
+       cerr << (*i) << " ";
+      }
+      cerr << endl;
+    }
+    intentions.erase(intentions.begin());
+  } else {
+    //int legNr, routeNr;
+    //FGAIFlightPlan::waypoint* const wpt= route->getCurrentWaypoint();
+    int size = route->getNrOfWayPoints();
+    cerr << "Setting pos" << pos << " ";
+    cerr << "setting intentions ";
+    for (int i = 0; i < size; i++) {
+      int val = route->getRouteIndex(i);
+     
+      if ((val) && (val != pos))
+       {
+         intentions.push_back(val); 
+         cerr << val<< " ";
+       }
+    }
+    cerr << endl;
+    //while (route->next(&legNr, &routeNr)) {
+    //intentions.push_back(routeNr);
+    //}
+    //route->rewind(currentPos);
+  }
+  //exit(1);
+}
+
+bool FGTrafficRecord::checkPositionAndIntentions(FGTrafficRecord &other)
+{
+  bool result = false;
+  //cerr << "Start check 1" << endl;
+  if (currentPos == other.currentPos) 
+    {
+      //cerr << "Check Position and intentions: current matches" << endl;
+      result = true;
+    }
+ //  else if (other.intentions.size()) 
+//     {
+//       cerr << "Start check 2" << endl;
+//       intVecIterator i = other.intentions.begin(); 
+//       while (!((i == other.intentions.end()) || ((*i) == currentPos)))
+//     i++;
+//       if (i != other.intentions.end()) {
+//     cerr << "Check Position and intentions: current matches other.intentions" << endl;
+//     result = true;
+//       }
+  else if (intentions.size()) {
+    //cerr << "Start check 3" << endl;
+    intVecIterator i = intentions.begin(); 
+    while (!((i == intentions.end()) || ((*i) == other.currentPos)))
+      i++;
+    if (i != intentions.end()) {
+      //cerr << "Check Position and intentions: .other.current matches" << endl;
+      result = true;
+    }
+  }
+  //cerr << "Done !!" << endl;
+  return result;
+}
+
+void FGTrafficRecord::setPositionAndHeading(double lat, double lon, double hdg, 
+                                           double spd, double alt)
+{
+  latitude = lat;
+  longitude = lon;
+  heading = hdg;
+  speed = spd;
+  altitude = alt;
+}
+
 /***************************************************************************
  * FGGroundNetwork()
  **************************************************************************/
@@ -155,6 +272,7 @@ FGGroundNetwork::FGGroundNetwork()
   foundRoute = false;
   totalDistance = 0;
   maxDistance = 0;
+  currTraffic = activeTraffic.begin();
 }
 
 void FGGroundNetwork::addSegment(const FGTaxiSegment &seg)
@@ -187,7 +305,7 @@ void FGGroundNetwork::addNodes(FGParkingVec *parkings)
 void FGGroundNetwork::init()
 {
   hasNetwork = true;
-  int index = 0;
+  int index = 1;
   FGTaxiSegmentVectorIterator i = segments.begin();
   while(i != segments.end()) {
     //cerr << "initializing node " << i->getIndex() << endl;
@@ -421,3 +539,250 @@ void FGGroundNetwork::printRoutingError(string mess)
     }
   //exit(1);
 }
+
+
+void FGGroundNetwork::announcePosition(int id, FGAIFlightPlan *intendedRoute, int currentPosition,
+                                      double lat, double lon, double heading, 
+                                      double speed, double alt, double radius)
+{
+  TrafficVectorIterator i = activeTraffic.begin();
+  // Search search if the current id alread has an entry
+  // This might be faster using a map instead of a vector, but let's start by taking a safe route
+  if (activeTraffic.size()) {
+    while ((i->getId() != id) && i != activeTraffic.end()) {
+      i++;
+    }
+  }
+  // Add a new TrafficRecord if no one exsists for this aircraft.
+  if (i == activeTraffic.end() || (activeTraffic.size() == 0)) {
+    FGTrafficRecord rec;
+    rec.setId(id);
+    rec.setPositionAndIntentions(currentPosition, intendedRoute);
+    rec.setPositionAndHeading(lat, lon, heading, speed, alt);
+    rec.setRadius(radius); // only need to do this when creating the record.
+    activeTraffic.push_back(rec);
+  } else {
+    i->setPositionAndIntentions(currentPosition, intendedRoute); 
+    i->setPositionAndHeading(lat, lon, heading, speed, alt);
+  }
+}
+
+void FGGroundNetwork::signOff(int id) {
+ TrafficVectorIterator i = activeTraffic.begin();
+  // Search search if the current id alread has an entry
+  // This might be faster using a map instead of a vector, but let's start by taking a safe route
+  if (activeTraffic.size()) {
+    while ((i->getId() != id) && i != activeTraffic.end()) {
+      i++;
+    }
+  }
+  if (i == activeTraffic.end() || (activeTraffic.size() == 0)) {
+    SG_LOG(SG_GENERAL, SG_ALERT, "AI error: Aircraft without traffic record is signing off");
+  } else {
+      i = activeTraffic.erase(i);
+  }
+}
+
+void FGGroundNetwork::update(int id, double lat, double lon, double heading, double speed, double alt) {
+  TrafficVectorIterator i = activeTraffic.begin();
+  // Search search if the current id has an entry
+  // This might be faster using a map instead of a vector, but let's start by taking a safe route
+  TrafficVectorIterator current, closest;
+  if (activeTraffic.size()) {
+    while ((i->getId() != id) && i != activeTraffic.end()) {
+      i++;
+    }
+  }
+  // update position of the current aircraft
+  if (i == activeTraffic.end() || (activeTraffic.size() == 0)) {
+    SG_LOG(SG_GENERAL, SG_ALERT, "AI error: updating aircraft without traffic record");
+  } else {
+    i->setPositionAndHeading(lat, lon, heading, speed, alt);
+    current = i;
+  }
+
+  // Scan for a speed adjustment change. Find the nearest aircraft that is in front
+  // and adjust speed when we get too close. Only do this when current position and/or
+  // intentions of the current aircraft match current taxiroute position of the proximate
+  // aircraft. 
+  double mindist = HUGE;
+  if (activeTraffic.size()) 
+    {
+      double course, dist, bearing, minbearing;
+     
+      //TrafficVector iterator closest;
+      for (TrafficVectorIterator i = activeTraffic.begin(); 
+          i != activeTraffic.end(); i++)
+       {
+         if (i != current) {
+           SGWayPoint curr  (lon,
+                             lat,
+                             alt);
+           SGWayPoint other    (i->getLongitude  (),
+                                i->getLatitude (),
+                                i->getAltitude  ());
+           other.CourseAndDistance(curr, &course, &dist);
+            bearing = fabs(heading-course);
+         if (bearing > 180)
+           bearing = 360-bearing;
+         if ((dist < mindist) && (bearing < 60.0))
+           {
+             mindist = dist;
+             closest = i;
+             minbearing = bearing;
+           }
+         }
+       }
+         //cerr << "Distance : " << dist << " bearing : " << bearing << " heading : " << heading 
+         //   << " course : " << course << endl;
+      current->clearSpeedAdjustment();
+      // Only clear the heading adjustment at positive speeds, otherwise the waypoint following
+      // code wreaks havoc
+      if (speed > 0.2)
+       current->clearHeadingAdjustment();
+      // All clear
+      if (mindist > 100)
+       {
+         //current->clearSpeedAdjustment();
+         //current->clearHeadingAdjustment();
+       } 
+      else
+       {
+         if (current->getId() == closest->getWaitsForId())
+           return;
+         else 
+           current->setWaitsForId(closest->getId());
+         
+         // Getting close: Slow down to a bit less than the other aircraft
+         double maxAllowableDistance = (1.1*current->getRadius()) + (1.1*closest->getRadius());
+           if (mindist > maxAllowableDistance)
+           {
+             if (current->checkPositionAndIntentions(*closest)) 
+               {
+                 // Adjust speed, but don't let it drop to below 1 knots
+                 //if (fabs(speed) > 1)
+                 if (!(current->hasHeadingAdjustment())) 
+                   {
+                     current->setSpeedAdjustment(closest->getSpeed()* (mindist/100));
+                     //cerr << "Adjusting speed to " << closest->getSpeed() * (mindist / 100) << " " 
+                     //         << "Bearing = " << minbearing << " Distance = " << mindist
+                     //         << " Latitude = " <<lat << " longitude = " << lon << endl;
+                     //<< " Latitude = " <<closest->getLatitude() 
+                     //<< " longitude = " << closest->getLongitude() 
+                     //  << endl;
+                   }
+                 else
+                   {
+                      double newSpeed = (maxAllowableDistance-mindist);
+                      current->setSpeedAdjustment(newSpeed);
+                   } 
+               }
+           }
+         else
+           { 
+             if (!(current->hasHeadingAdjustment())) 
+               {
+                 double newSpeed;
+                 if (mindist > 10) {
+                   newSpeed = 0.01;
+                     current->setSpeedAdjustment(newSpeed);
+                 } else {
+                   newSpeed = -1 * (maxAllowableDistance-mindist);
+                   current->setSpeedAdjustment(newSpeed);
+                   current->setHeadingAdjustment(heading);
+                   //        if (mindist < 5) {
+                   //          double bank_sense = 0;
+                   //          current->setSpeedAdjustment(-0.1);
+                   //          // Do a heading adjustment
+                   //          double diff = fabs(heading - bearing);
+                   //          if (diff > 180)
+                   //            diff = fabs(diff - 360);
+                   
+                   //          double sum = heading + diff;
+                   //          if (sum > 360.0)
+                   //            sum -= 360.0;
+                   //          if (fabs(sum - bearing) < 1.0) {
+                   //            bank_sense = -1.0;   // turn left for evasive action
+                   //          } else {
+                   //            bank_sense = 1.0;  // turn right for evasive action
+                   //          }
+                   //          double newHeading = heading + bank_sense;
+                   //          if (newHeading < 0) newHeading   += 360;
+                   //          if (newHeading > 360) newHeading -= 360;
+                   //          current->setHeadingAdjustment(newHeading);
+                   //          //cerr << "Yikes: TOOOO close. backing up and turning to heading " << newHeading 
+                   //          //  << endl;
+                   //          cerr << "Troubleshooting: " << current->getId() << " Closest : " << closest->getId() 
+                   //               << endl;
+                   //       }
+                 }
+               }
+           }
+       }
+    }
+}
+
+bool FGGroundNetwork::hasInstruction(int id)
+{
+   TrafficVectorIterator i = activeTraffic.begin();
+  // Search search if the current id has an entry
+  // This might be faster using a map instead of a vector, but let's start by taking a safe route
+  if (activeTraffic.size()) {
+    while ((i->getId() != id) && i != activeTraffic.end()) {
+      i++;
+    }
+  }
+  if (i == activeTraffic.end() || (activeTraffic.size() == 0)) {
+    SG_LOG(SG_GENERAL, SG_ALERT, "AI error: checking ATC instruction for aircraft without traffic record");
+  } else {
+    return i->hasInstruction();
+  }
+}
+
+FGATCInstruction FGGroundNetwork::getInstruction(int id)
+{
+  TrafficVectorIterator i = activeTraffic.begin();
+  // Search search if the current id has an entry
+  // This might be faster using a map instead of a vector, but let's start by taking a safe route
+  if (activeTraffic.size()) {
+    while ((i->getId() != id) && i != activeTraffic.end()) {
+      i++;
+    }
+  }
+  if (i == activeTraffic.end() || (activeTraffic.size() == 0)) {
+    SG_LOG(SG_GENERAL, SG_ALERT, "AI error: requesting ATC instruction for aircraft without traffic record");
+  } else {
+    return i->getInstruction();
+  }
+}
+
+
+
+
+/***************************************************************************
+ * FGATCInstruction
+ *
+ * This class is really out of place here, and should be combined with
+ * FGATC controller and go into it's own file / directory
+ * I'm leaving it for now though, because I'm testing this stuff quite
+ * heavily.
+ **************************************************************************/
+FGATCInstruction::FGATCInstruction()
+{
+  holdPattern    = false; 
+  holdPosition   = false;
+  changeSpeed    = false;
+  changeHeading  = false;
+  changeAltitude = false;
+
+  double speed   = 0;
+  double heading = 0;
+  double alt     = 0;
+}
+
+bool FGATCInstruction::hasInstruction()
+{
+  return (holdPattern || holdPosition || changeSpeed || changeHeading || changeAltitude);
+}
+
+
index 4c8bdb2eb6d1a504fd4d53e5e872b7009fb9c1ae..f4a8dd41fd583cb554fb5fa35474b155b2ee9078 100644 (file)
 
 #include <simgear/compiler.h>
 
+
 #include STL_STRING
 #include <vector>
 
 SG_USING_STD(string);
 SG_USING_STD(vector);
 
+
 #include "parking.hxx"
+//#include <AIModel/AIBase.hxx>
+
+
 
 class FGTaxiSegment; // forward reference
+class FGAIFlightPlan; // forward reference
 
 typedef vector<FGTaxiSegment>  FGTaxiSegmentVector;
 typedef vector<FGTaxiSegment*> FGTaxiSegmentPointerVector;
@@ -137,6 +143,7 @@ public:
   bool empty () { return nodes.begin() == nodes.end(); };
   bool next(int *nde); 
   bool next(int *nde, int *rte);
+  void rewind(int legNr);
   
   void first() { currNode = nodes.begin(); currRoute = routes.begin(); };
   int size() { return nodes.size(); };
@@ -145,10 +152,133 @@ public:
 typedef vector<FGTaxiRoute> TaxiRouteVector;
 typedef vector<FGTaxiRoute>::iterator TaxiRouteVectorIterator;
 
+/**************************************************************************************
+ * class FGATCInstruction
+ * like class FGATC Controller, this class definition should go into its own file
+ * and or directory... For now, just testing this stuff out though...
+ *************************************************************************************/
+class FGATCInstruction
+{
+private:
+  bool holdPattern;
+  bool holdPosition;
+  bool changeSpeed;
+  bool changeHeading;
+  bool changeAltitude;
+
+  double speed;
+  double heading;
+  double alt;
+public:
+
+  FGATCInstruction();
+  bool hasInstruction   ();
+  bool getHoldPattern   () { return holdPattern;    };
+  bool getHoldPosition  () { return holdPosition;   };
+  bool getChangeSpeed   () { return changeSpeed;    };
+  bool getChangeHeading () { return changeHeading;  };
+  bool getChangeAltitude() { return changeAltitude; };
+
+  double getSpeed       () { return speed; };
+  double getHeading     () { return heading; };
+  double getAlt         () { return alt; };
+
+  void setHoldPattern   (bool val) { holdPattern    = val; };
+  void setHoldPosition  (bool val) { holdPosition   = val; };
+  void setChangeSpeed   (bool val) { changeSpeed    = val; };
+  void setChangeHeading (bool val) { changeHeading  = val; };
+  void setChangeAltitude(bool val) { changeAltitude = val; };
+
+  void setSpeed       (double val) { speed   = val; };
+  void setHeading     (double val) { heading = val; };
+  void setAlt         (double val) { alt     = val; };
+};
+
+
+/**************************************************************************************
+ * class FGTrafficRecord
+ *************************************************************************************/
+class FGTrafficRecord
+{
+private:
+  int id, waitsForId;
+  int currentPos;
+  intVec intentions;
+  FGATCInstruction instruction;
+  double latitude, longitude, heading, speed, altitude, radius;
+  
+  
+public:
+  FGTrafficRecord() {};
+  
+  void setId(int val)  { id = val; };
+  void setRadius(double rad) { radius = rad;};
+  void setPositionAndIntentions(int pos, FGAIFlightPlan *route);
+  int getId() { return id;};
+  FGATCInstruction getInstruction() { return instruction;};
+  bool hasInstruction() { return instruction.hasInstruction(); };
+  void setPositionAndHeading(double lat, double lon, double hdg, double spd, double alt);
+  bool checkPositionAndIntentions(FGTrafficRecord &other);
+  
+  double getLatitude () { return latitude ; };
+  double getLongitude() { return longitude; };
+  double getHeading  () { return heading  ; };
+  double getSpeed    () { return speed    ; };
+  double getAltitude () { return altitude ; };
+  double getRadius   () { return radius   ; };
+
+  int getWaitsForId  () { return waitsForId; };
+
+  void setSpeedAdjustment(double spd) { instruction.setChangeSpeed(true); 
+                                        instruction.setSpeed(spd); };
+  void setHeadingAdjustment(double heading) { instruction.setChangeHeading(true);
+                                              instruction.setHeading(heading); };
+  void clearSpeedAdjustment  () { instruction.setChangeSpeed  (false); };
+  void clearHeadingAdjustment() { instruction.setChangeHeading(false); };
+
+  bool hasHeadingAdjustment() { return instruction.getChangeHeading(); };
+
+  void setWaitsForId(int id) { waitsForId = id; };
+
+};
+
+typedef vector<FGTrafficRecord> TrafficVector;
+typedef vector<FGTrafficRecord>::iterator TrafficVectorIterator;
+
+
+
+
+/**************************************************************************************
+ * class FGATCController
+ * NOTE: this class serves as an abstraction layer for all sorts of ATC controller,
+ * Ground and air, so eventually it should move to its own file / directory. 
+ *************************************************************************************/
+class FGATCController
+{
+private:
+  double dt_count;
+public:
+  FGATCController() { dt_count = 0;};
+  virtual ~FGATCController() {};
+  virtual void announcePosition(int id, FGAIFlightPlan *intendedRoute, int currentRoute,
+                               double lat, double lon,
+                               double hdg, double spd, double alt, double radius) = 0;
+  virtual void             signOff(int id) = 0;
+  virtual void             update(int id, double lat, double lon, 
+                                 double heading, double speed, double alt) = 0;
+  virtual bool             hasInstruction(int id) = 0;
+  virtual FGATCInstruction getInstruction(int id) = 0;
+
+  double getDt() { return dt_count; };
+  void   setDt(double dt) { dt_count = dt;};
+};
+
+
+
 /**************************************************************************************
  * class FGGroundNetWork
  *************************************************************************************/
-class FGGroundNetwork
+class FGGroundNetwork : public FGATCController
 {
 private:
   bool hasNetwork;
@@ -158,6 +288,8 @@ private:
   intVec nodesStack;
   intVec routesStack;
   TaxiRouteVector routes;
+  TrafficVector activeTraffic;
+  TrafficVectorIterator currTraffic;
   
   bool foundRoute;
   double totalDistance, maxDistance;
@@ -178,7 +310,14 @@ public:
   FGTaxiSegment *findSegment(int idx);
   FGTaxiRoute findShortestRoute(int start, int end);
   void trace(FGTaxiNode *, int, int, double dist);
+
+  virtual void announcePosition(int id, FGAIFlightPlan *intendedRoute, int currentRoute, 
+                               double lat, double lon, double hdg, double spd, double alt, double radius);
+  virtual void signOff(int id);
+  virtual void update(int id, double lat, double lon, double heading, double speed, double alt);
+  virtual bool hasInstruction(int id);
+  virtual FGATCInstruction getInstruction(int id);
 };
 
+
 #endif
index 39521fc1530fff8b290e58d069421abb80cdd576..72256bf5f56098da67b1e27228d4438c3d334556 100644 (file)
@@ -50,6 +50,7 @@
 #include "groundnetwork.hxx"
 #include "dynamics.hxx"
 
+
 SG_USING_STD(string);
 SG_USING_STD(map);
 SG_USING_STD(set);
index 1e45921cd47c5a06e36b37af29ac593def98b13a..0247b70640ddf9ac5b0881c9c2a1b34cba61dc9c 100644 (file)
@@ -271,7 +271,7 @@ bool FGScheduledFlight::initializeAirports()
   arrivalPort = globals->get_airports()->search(arrId);
   if(arrivalPort == NULL)
     {
-      SG_LOG( SG_GENERAL, SG_WARN, "Traffic manager could not find arrival airort   : " << arrId);
+      SG_LOG( SG_GENERAL, SG_WARN, "Traffic manager could not find arrival airport   : " << arrId);
       return false;
     }
 
index f80667687c434cca0c91ff871659817cc5007d25..d1e181e6ef488738457f84eb5f269f1d58dd7759 100644 (file)
@@ -185,7 +185,7 @@ bool FGAISchedule::update(time_t now)
   time_t 
     totalTimeEnroute, 
     elapsedTimeEnroute,
-    remainingTimeEnroute;
+    remainingTimeEnroute, deptime = 0;
   double
     userLatitude,
     userLongitude;
@@ -218,6 +218,8 @@ bool FGAISchedule::update(time_t now)
        {
          i->adjustTime(now);
        }
+      if (fgGetBool("/sim/traffic-manager/instantaneous-action") == true)
+       deptime = now;
       firstRun = false;
     }
   
@@ -225,6 +227,8 @@ bool FGAISchedule::update(time_t now)
   // Because this is done at every update, we only need to check the status
   // of the first listed flight. 
   sort(flights.begin(), flights.end());
+  if (!deptime)
+    deptime = flights.begin()->getDepartureTime();
   FGScheduledFlightVecIterator i = flights.begin();
   if (AIManagerRef)
     {
@@ -391,8 +395,11 @@ bool FGAISchedule::update(time_t now)
                  aircraft->setAltitude(i->getCruiseAlt()*100); // convert from FL to feet
                  aircraft->setSpeed(speed);
                  aircraft->setBank(0);
-                 aircraft->SetFlightPlan(new FGAIFlightPlan(flightPlanName, courseToDest, i->getDepartureTime(), dep, 
-                                                            arr,true, radius, i->getCruiseAlt()*100, lat, lon, speed, flightType, acType, airline));
+                 aircraft->SetFlightPlan(new FGAIFlightPlan(flightPlanName, courseToDest, deptime, 
+                                                            dep, arr,true, radius, 
+                                                            i->getCruiseAlt()*100, 
+                                                            lat, lon, speed, flightType, acType, 
+                                                            airline));
                  aimgr->attach(aircraft);
                  
                  
index a79585e0bf12ddc2a81fa1482a089deb371504d8..e29329ab959ac832a813573af688361b176d9242 100644 (file)
@@ -60,6 +60,8 @@ class FGAISchedule
               int, FGScheduledFlightVec);                  // construct & init
   FGAISchedule(const FGAISchedule &other);                  // copy constructor
 
+
+
   ~FGAISchedule(); //destructor
 
   bool update(time_t now);