]> git.mxchange.org Git - flightgear.git/commitdiff
More work on AI/ATC integration:
authorDurk Talsma <durk@localhost.(none)>
Tue, 19 Apr 2011 16:01:24 +0000 (18:01 +0200)
committerDurk Talsma <durk@localhost.(none)>
Tue, 19 Apr 2011 16:01:24 +0000 (18:01 +0200)
- Fixed a bug in AI aircraft ground steering code: When aircraft were not moving, the value of headingchangeRate kept increasing to insane levels. Although this was clamped to a maximum of 30 degrees per second, the initial rate could still push the aircraft in the wrong direction. In practice, this bug would be visible when an AI aicraft would be pushed back, when it tended to veer to the right.
 - Make sure that the aircraft slows down well ahead of the pushback point. This change ensures that the AC will actually reach the pushback point. It also ensures a slightly tighter steering range.
 - AI ground steering rate is tuned to 30 degrees per second at a nominal taxispeed of 15. I now modulate the heading adjustment rate by manipulating the adjustment using a non-linear function (the sqrt). This allows for a slightly tighter turn radius at speeds < 15 and slightly looser turns at speeds > 15.
 - The AI Flightplan generation code can return false. This can be used to determine whether any additional AI aircraft may be created. Currently, the function returns false when no more parkings are available. This should limit the build-up of huge AIAircraft tower stacks.
 - The ground network can now graphically display all aircraft actitivy on the ground network by using a virtual marker system.

14 files changed:
src/AIModel/AIAircraft.cxx
src/AIModel/AIFlightPlan.cxx
src/AIModel/AIFlightPlan.hxx
src/AIModel/AIFlightPlanCreate.cxx
src/AIModel/AIFlightPlanCreateCruise.cxx
src/AIModel/AIFlightPlanCreatePushBack.cxx
src/ATC/atc_mgr.cxx
src/ATC/trafficcontrol.cxx
src/ATC/trafficcontrol.hxx
src/Airports/groundnetwork.cxx
src/Airports/groundnetwork.hxx
src/Traffic/Schedule.cxx
src/Traffic/Schedule.hxx
src/Traffic/TrafficMgr.cxx

index 6a4ce077b0a42bd6cccc0f0115cac7ce8bf33b87..c9b5b72081cf9f94fdefa5fc675184d850900088 100644 (file)
@@ -1,4 +1,4 @@
-// FGAIAircraft - FGAIBase-derived class creates an AI airplane
+// // FGAIAircraft - FGAIBase-derived class creates an AI airplane
 //
 // Written by David Culp, started October 2003.
 //
@@ -276,6 +276,19 @@ void FGAIAircraft::ProcessFlightPlan( double dt, time_t now ) {
     if (! leadPointReached(curr)) {
         controlHeading(curr);
         controlSpeed(curr, next);
+            if (speed < 0) { 
+                cerr << getCallSign() 
+                     << ": verifying lead distance to waypoint : " 
+                     << fp->getCurrentWaypoint()->name << " "
+                     << fp->getLeadDistance() << ". Distance to go " 
+                     << (fp->getDistanceToGo(pos.getLatitudeDeg(), pos.getLongitudeDeg(), curr)) 
+                     << ". Target speed = " 
+                     << tgt_speed
+                     << ". Current speed = "
+                     << speed
+                     << ". Minimum Bearing " << minBearing
+                     << endl;
+            }
     } else {
         if (curr->finished)      //end of the flight plan
         {
@@ -676,7 +689,15 @@ bool FGAIAircraft::leadPointReached(FGAIFlightPlan::waypoint* curr) {
     //cerr << "2" << endl;
     double lead_dist = fp->getLeadDistance();
     // experimental: Use fabs, because speed can be negative (I hope) during push_back.
-
+    if ((dist_to_go < fabs(10.0* speed)) && (speed < 0) && (tgt_speed < 0) && fp->getCurrentWaypoint()->name == string("PushBackPoint")) {
+          tgt_speed = -(dist_to_go / 10.0);
+          if (tgt_speed > -0.5) {
+                tgt_speed = -0.5;
+          }
+          if (fp->getPreviousWaypoint()->speed < tgt_speed) {
+              fp->getPreviousWaypoint()->speed = tgt_speed;
+          }
+    }
     if (lead_dist < fabs(2*speed)) {
       //don't skip over the waypoint
       lead_dist = fabs(2*speed);
@@ -936,8 +957,8 @@ void FGAIAircraft::updateHeading() {
                 bank_sense = 1.0;
             }
             //if (trafficRef)
-               //cerr << trafficRef->getCallSign() << " Heading " 
-                //     << hdg << ". Target " << tgt_heading <<  ". Diff " << fabs(sum - tgt_heading) << ". Speed " << speed << endl;
+            // cerr << trafficRef->getCallSign() << " Heading " 
+            //         << hdg << ". Target " << tgt_heading <<  ". Diff " << fabs(sum - tgt_heading) << ". Speed " << speed << endl;
             //if (headingDiff > 60) {
             groundTargetSpeed = tgt_speed; // * cos(headingDiff * SG_DEGREES_TO_RADIANS);
                 //groundTargetSpeed = tgt_speed - tgt_speed * (headingDiff/180);
@@ -946,27 +967,34 @@ void FGAIAircraft::updateHeading() {
             //}
             if (sign(groundTargetSpeed) != sign(tgt_speed))
                 groundTargetSpeed = 0.21 * sign(tgt_speed); // to prevent speed getting stuck in 'negative' mode
-
-            if (headingDiff > 30.0) {
-                // invert if pushed backward
-                headingChangeRate += 10.0 * dt * sign(roll);
-
-                // Clamp the maximum steering rate to 30 degrees per second,
-                // But only do this when the heading error is decreasing.
-                if ((headingDiff < headingError)) {
-                    if (headingChangeRate > 30)
-                        headingChangeRate = 30;
-                    else if (headingChangeRate < -30)
-                        headingChangeRate = -30;
+            
+            // Only update the target values when we're not moving because otherwise we might introduce an enormous target change rate while waiting a the gate, or holding.
+            if (speed != 0) {
+                if (headingDiff > 30.0) {
+                    // invert if pushed backward
+                    headingChangeRate += 10.0 * dt * sign(roll);
+
+                    // Clamp the maximum steering rate to 30 degrees per second,
+                    // But only do this when the heading error is decreasing.
+                    if ((headingDiff < headingError)) {
+                        if (headingChangeRate > 30)
+                            headingChangeRate = 30;
+                        else if (headingChangeRate < -30)
+                            headingChangeRate = -30;
+                    }
+                } else {
+                    if (speed != 0) {
+                        if (fabs(headingChangeRate) > headingDiff)
+                            headingChangeRate = headingDiff*sign(roll);
+                        else
+                            headingChangeRate += dt * sign(roll);
+                    }
                 }
-            } else {
-                   if (fabs(headingChangeRate) > headingDiff)
-                       headingChangeRate = headingDiff*sign(roll);
-                   else
-                       headingChangeRate += dt * sign(roll);
             }
-
-           hdg += headingChangeRate * dt * (fabs(speed) / 15);
+            if (trafficRef)
+               cerr << trafficRef->getCallSign() << " Heading " 
+                     << hdg << ". Target " << tgt_heading <<  ". Diff " << fabs(sum - tgt_heading) << ". Speed " << speed << "Heading change rate : " << headingChangeRate << " bacnk sence " << bank_sense << endl;
+           hdg += headingChangeRate * dt * sqrt(fabs(speed) / 15);
             headingError = headingDiff;
         } else {
             if (fabs(speed) > 1.0) {
index 914f5442c7e6c0990abed8fc341e24044186c2d9..2fa5c36092badad57ca64d0d90ecc620fd41ff64 100644 (file)
@@ -1,4 +1,4 @@
-// FGAIFlightPlan - class for loading and storing  AI flight plans
+// // FGAIFlightPlan - class for loading and storing  AI flight plans
 // Written by David Culp, started May 2004
 // - davidculp2@comcast.net
 //
@@ -50,6 +50,7 @@ FGAIFlightPlan::FGAIFlightPlan()
 {
    sid = 0;
    wpt_iterator = waypoints.begin();
+   isValid = true;
 }
 
 FGAIFlightPlan::FGAIFlightPlan(const string& filename)
@@ -98,6 +99,7 @@ FGAIFlightPlan::FGAIFlightPlan(const string& filename)
    }
 
   wpt_iterator = waypoints.begin();
+  isValid = true;
   //cout << waypoints.size() << " waypoints read." << endl;
 }
 
@@ -137,7 +139,7 @@ FGAIFlightPlan::FGAIFlightPlan(FGAIAircraft *ac,
   path.append( p );
   
   SGPropertyNode root;
-  
+  isValid = true;
   // This is a bit of a hack:
   // Normally the value of course will be used to evaluate whether
   // or not a waypoint will be used for midair initialization of 
@@ -205,7 +207,7 @@ FGAIFlightPlan::FGAIFlightPlan(FGAIAircraft *ac,
       SG_LOG(SG_GENERAL, SG_INFO, "Route from " << dep->getId() << " to " << arr->getId() << ". Set leg to : " << leg << " " << ac->getTrafficRef()->getCallSign());
       wpt_iterator = waypoints.begin();
       bool dist = 0;
-      create(ac, dep,arr, leg, alt, speed, lat, lon,
+      isValid = create(ac, dep,arr, leg, alt, speed, lat, lon,
             firstLeg, radius, fltType, acType, airline, dist);
       wpt_iterator = waypoints.begin();
       //cerr << "after create: " << (*wpt_iterator)->name << endl;
index e9090ce353db78943c06bba4972b2f0d2a9848cb..44485ae754923be75dc9db25b496c23ab52ba9c8 100644 (file)
@@ -87,10 +87,10 @@ public:
   time_t getStartTime() const { return start_time; }
    time_t getArrivalTime() const { return arrivalTime; }
 
-  void    create(FGAIAircraft *, FGAirport *dep, FGAirport *arr, int leg, double alt, double speed, double lat, double lon,
+  bool    create(FGAIAircraft *, FGAirport *dep, FGAirport *arr, int leg, double alt, double speed, double lat, double lon,
                 bool firstLeg, double radius, const std::string& fltType, const std::string& aircraftType, const std::string& airline, double distance);
-  void createPushBack(FGAIAircraft *, bool, FGAirport*, double, double, double, const std::string&, const std::string&, const std::string&);
-  void createTakeOff(FGAIAircraft *, bool, FGAirport *, double, const std::string&);
+  bool createPushBack(FGAIAircraft *, bool, FGAirport*, double, double, double, const std::string&, const std::string&, const std::string&);
+  bool createTakeOff(FGAIAircraft *, bool, FGAirport *, double, const std::string&);
 
   void setLeg(int val) { leg = val;}
   void setTime(time_t st) { start_time = st; }
@@ -142,20 +142,21 @@ private:
   std::string activeRunway;
   FGTaxiRoute *taxiRoute;
   std::string name;
+  bool isValid;
 
   void createPushBackFallBack(FGAIAircraft *, bool, FGAirport*, double, double, double, const std::string&, const std::string&, const std::string&);
-  void createClimb(FGAIAircraft *, bool, FGAirport *, double, double, const std::string&);
-  void createCruise(FGAIAircraft *, bool, FGAirport*, FGAirport*, double, double, double, double, const std::string&);
-  void createDescent(FGAIAircraft *, FGAirport *,  double latitude, double longitude, double speed, double alt,const std::string&, double distance);
-  void createLanding(FGAIAircraft *, FGAirport *, const std::string&);
-  void createParking(FGAIAircraft *, FGAirport *, double radius);
+  bool createClimb(FGAIAircraft *, bool, FGAirport *, double, double, const std::string&);
+  bool createCruise(FGAIAircraft *, bool, FGAirport*, FGAirport*, double, double, double, double, const std::string&);
+  bool createDescent(FGAIAircraft *, FGAirport *,  double latitude, double longitude, double speed, double alt,const std::string&, double distance);
+  bool createLanding(FGAIAircraft *, FGAirport *, const std::string&);
+  bool createParking(FGAIAircraft *, FGAirport *, double radius);
   void deleteWaypoints(); 
   void resetWaypoints();
 
-  void createLandingTaxi(FGAIAircraft *, FGAirport *apt, double radius, const std::string& fltType, const std::string& acType, const std::string& airline);
+  bool createLandingTaxi(FGAIAircraft *, FGAirport *apt, double radius, const std::string& fltType, const std::string& acType, const std::string& airline);
   void createDefaultLandingTaxi(FGAIAircraft *, FGAirport* aAirport);
   void createDefaultTakeoffTaxi(FGAIAircraft *, FGAirport* aAirport, FGRunway* aRunway);
-  void createTakeoffTaxi(FGAIAircraft *, bool firstFlight, FGAirport *apt, double radius, const std::string& fltType, const std::string& acType, const std::string& airline);
+  bool createTakeoffTaxi(FGAIAircraft *, bool firstFlight, FGAirport *apt, double radius, const std::string& fltType, const std::string& acType, const std::string& airline);
 
   double getTurnRadius(double, bool);
         
@@ -170,7 +171,7 @@ private:
  public:
   wpt_vector_iterator getFirstWayPoint() { return waypoints.begin(); };
   wpt_vector_iterator getLastWayPoint()  { return waypoints.end(); };
-
+    bool isValidPlan() { return isValid; };
 };    
 
 #endif  // _FG_AIFLIGHTPLAN_HXX
index a0a396d8fe02ea0874f77432e78b2d4d41911943..9ba1c4d8b9bf7b18183d7627c58f50d9a4fc250f 100644 (file)
@@ -47,7 +47,7 @@
 
 
 // Check lat/lon values during initialization;
-void FGAIFlightPlan::create(FGAIAircraft * ac, FGAirport * dep,
+bool FGAIFlightPlan::create(FGAIAircraft * ac, FGAirport * dep,
                             FGAirport * arr, int legNr, double alt,
                             double speed, double latitude,
                             double longitude, bool firstFlight,
@@ -55,38 +55,39 @@ void FGAIFlightPlan::create(FGAIAircraft * ac, FGAirport * dep,
                             const string & aircraftType,
                             const string & airline, double distance)
 {
+    bool retVal = true;
     int currWpt = wpt_iterator - waypoints.begin();
     switch (legNr) {
     case 1:
-        createPushBack(ac, firstFlight, dep, latitude, longitude,
-                       radius, fltType, aircraftType, airline);
+        retVal = createPushBack(ac, firstFlight, dep, latitude, longitude,
+                                radius, fltType, aircraftType, airline);
         break;
     case 2:
-        createTakeoffTaxi(ac, firstFlight, dep, radius, fltType,
+        retVal =  createTakeoffTaxi(ac, firstFlight, dep, radius, fltType,
                           aircraftType, airline);
         break;
     case 3:
-        createTakeOff(ac, firstFlight, dep, speed, fltType);
+        retVal = createTakeOff(ac, firstFlight, dep, speed, fltType);
         break;
     case 4:
-        createClimb(ac, firstFlight, dep, speed, alt, fltType);
+        retVal = createClimb(ac, firstFlight, dep, speed, alt, fltType);
         break;
     case 5:
-        createCruise(ac, firstFlight, dep, arr, latitude, longitude, speed,
+        retVal = createCruise(ac, firstFlight, dep, arr, latitude, longitude, speed,
                      alt, fltType);
         break;
     case 6:
-        createDescent(ac, arr, latitude, longitude, speed, alt, fltType,
+        retVal = createDescent(ac, arr, latitude, longitude, speed, alt, fltType,
                       distance);
         break;
     case 7:
-        createLanding(ac, arr, fltType);
+        retVal = createLanding(ac, arr, fltType);
         break;
     case 8:
-        createLandingTaxi(ac, arr, radius, fltType, aircraftType, airline);
+        retVal = createLandingTaxi(ac, arr, radius, fltType, aircraftType, airline);
         break;
     case 9:
-        createParking(ac, arr, radius);
+        retVal = createParking(ac, arr, radius);
         break;
     default:
         //exit(1);
@@ -96,6 +97,7 @@ void FGAIFlightPlan::create(FGAIAircraft * ac, FGAirport * dep,
     }
     wpt_iterator = waypoints.begin() + currWpt;
     leg++;
+    return retVal;
 }
 
 FGAIFlightPlan::waypoint *
@@ -200,7 +202,7 @@ void FGAIFlightPlan::createDefaultTakeoffTaxi(FGAIAircraft * ac,
     waypoints.push_back(wpt);
 }
 
-void FGAIFlightPlan::createTakeoffTaxi(FGAIAircraft * ac, bool firstFlight,
+bool FGAIFlightPlan::createTakeoffTaxi(FGAIAircraft * ac, bool firstFlight,
                                        FGAirport * apt,
                                        double radius,
                                        const string & fltType,
@@ -240,7 +242,7 @@ void FGAIFlightPlan::createTakeoffTaxi(FGAIAircraft * ac, bool firstFlight,
     FGGroundNetwork *gn = apt->getDynamics()->getGroundNetwork();
     if (!gn->exists()) {
         createDefaultTakeoffTaxi(ac, apt, rwy);
-        return;
+        return true;
     }
 
     intVec ids;
@@ -278,7 +280,7 @@ void FGAIFlightPlan::createTakeoffTaxi(FGAIAircraft * ac, bool firstFlight,
 
     if (taxiRoute->empty()) {
         createDefaultTakeoffTaxi(ac, apt, rwy);
-        return;
+        return true;
     }
 
     taxiRoute->first();
@@ -313,6 +315,7 @@ void FGAIFlightPlan::createTakeoffTaxi(FGAIAircraft * ac, bool firstFlight,
         wpt->routeIndex = route;
         waypoints.push_back(wpt);
     }
+    return true;
 }
 
 void FGAIFlightPlan::createDefaultLandingTaxi(FGAIAircraft * ac,
@@ -341,7 +344,7 @@ void FGAIFlightPlan::createDefaultLandingTaxi(FGAIAircraft * ac,
     waypoints.push_back(wpt);
 }
 
-void FGAIFlightPlan::createLandingTaxi(FGAIAircraft * ac, FGAirport * apt,
+bool FGAIFlightPlan::createLandingTaxi(FGAIAircraft * ac, FGAirport * apt,
                                        double radius,
                                        const string & fltType,
                                        const string & acType,
@@ -360,7 +363,7 @@ void FGAIFlightPlan::createLandingTaxi(FGAIAircraft * ac, FGAirport * apt,
     // Find a route from runway end to parking/gate.
     if (!gn->exists()) {
         createDefaultLandingTaxi(ac, apt);
-        return;
+        return true;
     }
 
     intVec ids;
@@ -379,7 +382,7 @@ void FGAIFlightPlan::createLandingTaxi(FGAIAircraft * ac, FGAirport * apt,
 
     if (taxiRoute->empty()) {
         createDefaultLandingTaxi(ac, apt);
-        return;
+        return true;
     }
 
     int node;
@@ -399,6 +402,7 @@ void FGAIFlightPlan::createLandingTaxi(FGAIAircraft * ac, FGAirport * apt,
         wpt->routeIndex = route;
         waypoints.push_back(wpt);
     }
+    return true;
 }
 
 /*******************************************************************
@@ -412,7 +416,7 @@ void FGAIFlightPlan::createLandingTaxi(FGAIAircraft * ac, FGAirport * apt,
  *  more likely however. 
  * 
  ******************************************************************/
-void FGAIFlightPlan::createTakeOff(FGAIAircraft * ac, bool firstFlight,
+bool FGAIFlightPlan::createTakeOff(FGAIAircraft * ac, bool firstFlight,
                                    FGAirport * apt, double speed,
                                    const string & fltType)
 {
@@ -487,13 +491,14 @@ void FGAIFlightPlan::createTakeOff(FGAIAircraft * ac, bool firstFlight,
     wpt = cloneWithPos(ac, wpt, "5000 ft", pt);
     wpt->altitude = airportElev + 5000;
     waypoints.push_back(wpt);
+    return true;
 }
 
 /*******************************************************************
  * CreateClimb
  * initialize the Aircraft at the parking location
  ******************************************************************/
-void FGAIFlightPlan::createClimb(FGAIAircraft * ac, bool firstFlight,
+bool FGAIFlightPlan::createClimb(FGAIAircraft * ac, bool firstFlight,
                                  FGAirport * apt, double speed, double alt,
                                  const string & fltType)
 {
@@ -527,6 +532,7 @@ void FGAIFlightPlan::createClimb(FGAIAircraft * ac, bool firstFlight,
         wpt->altitude = 18000;
         waypoints.push_back(wpt);
     }
+    return true;
 }
 
 
@@ -536,7 +542,7 @@ void FGAIFlightPlan::createClimb(FGAIAircraft * ac, bool firstFlight,
  * Generate a flight path from the last waypoint of the cruise to 
  * the permission to land point
  ******************************************************************/
-void FGAIFlightPlan::createDescent(FGAIAircraft * ac, FGAirport * apt,
+bool FGAIFlightPlan::createDescent(FGAIAircraft * ac, FGAirport * apt,
                                    double latitude, double longitude,
                                    double speed, double alt,
                                    const string & fltType,
@@ -823,8 +829,7 @@ void FGAIFlightPlan::createDescent(FGAIAircraft * ac, FGAirport * apt,
         //cerr << "Repositioning to waypoint " << (*waypoints.begin())->name << endl;
         ac->resetPositionFromFlightPlan();
     }
-
-
+    return true;
 }
 
 /*******************************************************************
@@ -833,7 +838,7 @@ void FGAIFlightPlan::createDescent(FGAIAircraft * ac, FGAirport * apt,
    hardcoded at 5000 meters from the threshold) to the threshold, at
    a standard glide slope angle of 3 degrees. 
  ******************************************************************/
-void FGAIFlightPlan::createLanding(FGAIAircraft * ac, FGAirport * apt,
+bool FGAIFlightPlan::createLanding(FGAIAircraft * ac, FGAirport * apt,
                                    const string & fltType)
 {
     double vTouchdown = ac->getPerformance()->vTouchdown();
@@ -873,13 +878,14 @@ void FGAIFlightPlan::createLanding(FGAIAircraft * ac, FGAirport * apt,
        wpt->crossat   = apt->getElevation();
        waypoints.push_back(wpt); 
      */
+    return true;
 }
 
 /*******************************************************************
  * CreateParking
  * initialize the Aircraft at the parking location
  ******************************************************************/
-void FGAIFlightPlan::createParking(FGAIAircraft * ac, FGAirport * apt,
+bool FGAIFlightPlan::createParking(FGAIAircraft * ac, FGAirport * apt,
                                    double radius)
 {
     waypoint *wpt;
@@ -914,6 +920,7 @@ void FGAIFlightPlan::createParking(FGAIAircraft * ac, FGAirport * apt,
         createOnGround(ac, "END", SGGeod::fromDeg(lon, lat), aptElev,
                        vTaxiReduced);
     waypoints.push_back(wpt);
+    return true;
 }
 
 /**
index 1932de9ce3586c640b4842564e6beb2b3fc95be4..05f80c89a7ff9c4d125b09124d92d7f2b2306c33 100644 (file)
@@ -286,7 +286,7 @@ void FGAIFlightPlan::createCruise(bool firstFlight, FGAirport *dep,
  * Note that this is the original version that does not 
  * do any dynamic route computation.
  ******************************************************************/
-void FGAIFlightPlan::createCruise(FGAIAircraft *ac, bool firstFlight, FGAirport *dep, 
+bool FGAIFlightPlan::createCruise(FGAIAircraft *ac, bool firstFlight, FGAirport *dep, 
                                  FGAirport *arr, double latitude, 
                                  double longitude, double speed, 
                                  double alt, const string& fltType)
index 34f21a1fc196b0faabef515b10a6c18e6b4613fe..191423ff901b925d200323d11bf8c4f4b9e9f4ed 100644 (file)
@@ -37,7 +37,7 @@
 
 
 // TODO: Use James Turner's createOnGround functions.
-void FGAIFlightPlan::createPushBack(FGAIAircraft *ac,
+bool FGAIFlightPlan::createPushBack(FGAIAircraft *ac,
                                     bool firstFlight, FGAirport *dep, 
                                    double latitude,
                                    double longitude,
@@ -71,6 +71,7 @@ void FGAIFlightPlan::createPushBack(FGAIAircraft *ac,
                                               " of flight type " << fltType << 
                                               " of airline     " << airline <<
                                               " at airport     " << dep->getId());
+                    return false;
                     char buffer[10];
                     snprintf (buffer, 10, "%d", gateId);
                     //FGTaxiNode *tn = dep->getDynamics()->getGroundNetwork()->findNode(node);
@@ -104,7 +105,7 @@ void FGAIFlightPlan::createPushBack(FGAIAircraft *ac,
         if (gateId < 0) {
              createPushBackFallBack(ac, firstFlight, dep, latitude, longitude,
                                     radius, fltType, aircraftType, airline);
-             return;
+             return true;
 
         }
        //cerr << "getting parking " << gateId;
@@ -231,6 +232,7 @@ void FGAIFlightPlan::createPushBack(FGAIAircraft *ac,
         }
 
     }
+    return true;
 }
 /*******************************************************************
  * createPushBackFallBack
index dace2d26caa9526572c20e749f0a22bbaca9f95a..a05654cfe52856bc0e914ea73ce27085a1a5acc5 100644 (file)
@@ -157,9 +157,9 @@ void FGATCManager::init() {
 
     //dialog.init();
 
-   osg::Node* node = apt->getDynamics()->getGroundNetwork()->getRenderNode();
-   cerr << "Adding groundnetWork to the scenegraph" << endl;
-   globals->get_scenery()->get_scene_graph()->addChild(node);
+   //osg::Node* node = apt->getDynamics()->getGroundNetwork()->getRenderNode();
+   //cerr << "Adding groundnetWork to the scenegraph::init" << endl;
+   //globals->get_scenery()->get_scene_graph()->addChild(node);
    }
 }
 
@@ -177,7 +177,7 @@ void FGATCManager::update ( double time ) {
         double speed     = fgGetDouble("/velocities/groundspeed-kt");
         double altitude  = fgGetDouble("/position/altitude-ft");
 
-        cerr << "Running FGATCManager::update()" << endl;
+        //cerr << "Running FGATCManager::update()" << endl;
         controller->updateAircraftInformation(ai_ac.getID(),
                                               latitude,
                                               longitude,
@@ -185,10 +185,10 @@ void FGATCManager::update ( double time ) {
                                               speed,
                                               altitude, time);
     }
-   /*string airport = fgGetString("/sim/presets/airport-id");
+   string airport = fgGetString("/sim/presets/airport-id");
    FGAirport *apt = FGAirport::findByIdent(airport); 
    osg::Node* node = apt->getDynamics()->getGroundNetwork()->getRenderNode();
-   cerr << "Adding groundnetWork to the scenegraph" << endl;
+   //cerr << "Adding groundnetWork to the scenegraph::update" << endl;
+   
    globals->get_scenery()->get_scene_graph()->addChild(node);
-*/
 }
index c6b14504c7be977be7958506c238c70d5d8f226d..dc7d8c5f30743e5e150486055a3f8d45299c13d3 100644 (file)
@@ -419,6 +419,7 @@ bool FGTrafficRecord::pushBackAllowed()
     // In essence, we should check whether the pusbback route itself, as well as the associcated
     // taxiways near the pushback point are free of traffic. 
     // To do so, we need to 
+    return true;
 }
 
 
index 66381af52f140e930c307c33a790b13e7546340c..a60ffd4685cec79fd64fa57773652c0c1923becb 100644 (file)
@@ -182,6 +182,8 @@ public:
   void allowRepeatedTransmissions () { allowTransmission=true; };
   void nextFrequency() { frequencyId++; };
   int  getNextFrequency() { return frequencyId; };
+  intVec& getIntentions() { return intentions; };
+  int getCurrentPosition() { return currentPos; };
 };
 
 typedef vector<FGTrafficRecord> TrafficVector;
index a87861fabac16a25f6314b17764cb4a4cbd49542..2c676d2e42df5c070b98695c3389cb26bc1f85f9 100644 (file)
@@ -1,3 +1,4 @@
+
 // groundnet.cxx - Implimentation of the FlightGear airport ground handling code
 //
 // Written by Durk Talsma, started June 2005.
@@ -36,6 +37,8 @@
 #include <simgear/debug/logstream.hxx>
 #include <simgear/route/waypoint.hxx>
 #include <simgear/scene/material/EffectGeode.hxx>
+#include <simgear/scene/material/matlib.hxx>
+#include <simgear/scene/material/mat.hxx>
 
 #include <Airports/simple.hxx>
 #include <Airports/dynamics.hxx>
@@ -43,6 +46,8 @@
 #include <AIModel/AIAircraft.hxx>
 #include <AIModel/AIFlightPlan.hxx>
 
+#include <Scenery/scenery.hxx>
+
 #include "groundnetwork.hxx"
 
 /***************************************************************************
@@ -93,7 +98,7 @@ void FGTaxiSegment::setDimensions(double elevation)
     SGGeodesy::inverse(start->getGeod(), end->getGeod(), heading, az2, length);
     double coveredDistance = length * 0.5;
     SGGeodesy::direct(start->getGeod(), heading, coveredDistance, center, az2);
-    cerr << "Centerpoint = (" << center.getLatitudeDeg() << ", " << center.getLongitudeDeg() << "). Heading = " << heading << endl;
+    //cerr << "Centerpoint = (" << center.getLatitudeDeg() << ", " << center.getLongitudeDeg() << "). Heading = " << heading << endl;
 }
 
 
@@ -205,6 +210,7 @@ FGGroundNetwork::FGGroundNetwork()
     //maxDepth    = 1000;
     count = 0;
     currTraffic = activeTraffic.begin();
+    group = 0;
 
 }
 
@@ -1096,34 +1102,107 @@ static void WorldCoordinate(osg::Matrix& obj_pos, double lat,
 
 
 
+
 osg::Node* FGGroundNetwork::getRenderNode()
 {
-    osg::Group* group = new osg::Group;
 
-    for ( FGTaxiSegmentVectorIterator i = segments.begin(); i != segments.end(); i++) {
-        osg::Matrix obj_pos;
-        osg::MatrixTransform *obj_trans = new osg::MatrixTransform;
-        obj_trans->setDataVariance(osg::Object::STATIC);
-        WorldCoordinate( obj_pos, (*i)->getLatitude(), (*i)->getLongitude(), parent->elevation()+10, -((*i)->getHeading()) );
+    SGMaterialLib *matlib = globals->get_matlib();
+    if (group) {
+        //int nr = ;
+        globals->get_scenery()->get_scene_graph()->removeChild(group);
+        //while (group->getNumChildren()) {
+        //  cerr << "Number of children: " << group->getNumChildren() << endl;
+        simgear::EffectGeode* geode = (simgear::EffectGeode*) group->getChild(0);
+          //osg::MatrixTransform *obj_trans = (osg::MatrixTransform*) group->getChild(0);
+           //geode->releaseGLObjects();
+           //group->removeChild(geode);
+           //delete geode;
+    }
+    group = new osg::Group;
+
+    //for ( FGTaxiSegmentVectorIterator i = segments.begin(); i != segments.end(); i++) {
+    double dx = 0;
+    for   (TrafficVectorIterator i = activeTraffic.begin(); i != activeTraffic.end(); i++) {
+        // Handle start point
+        int pos = i->getCurrentPosition() - 1;
+        if (pos >= 0) {
+            
+            SGGeod start(SGGeod::fromDeg((i->getLongitude()), (i->getLatitude())));
+            SGGeod end  (SGGeod::fromDeg(segments[pos]->getEnd()->getLongitude(), segments[pos]->getEnd()->getLatitude()));
+
+            double length = SGGeodesy::distanceM(start, end);
+            //heading = SGGeodesy::headingDeg(start->getGeod(), end->getGeod());
+
+            double az2, heading; //, distanceM;
+            SGGeodesy::inverse(start, end, heading, az2, length);
+            double coveredDistance = length * 0.5;
+            SGGeod center;
+            SGGeodesy::direct(start, heading, coveredDistance, center, az2);
+            //cerr << "Active Aircraft : Centerpoint = (" << center.getLatitudeDeg() << ", " << center.getLongitudeDeg() << "). Heading = " << heading << endl;
+            ///////////////////////////////////////////////////////////////////////////////
+            // Make a helper function out of this
+            osg::Matrix obj_pos;
+                osg::MatrixTransform *obj_trans = new osg::MatrixTransform;
+                obj_trans->setDataVariance(osg::Object::STATIC);
+
+                WorldCoordinate( obj_pos, center.getLatitudeDeg(), center.getLongitudeDeg(), parent->elevation()+8+dx, -(heading) );
+
+                obj_trans->setMatrix( obj_pos );
+                //osg::Vec3 center(0, 0, 0)
+
+                float width = length /2.0;
+                osg::Vec3 corner(-width, 0, 0.25f);
+                osg::Vec3 widthVec(2*width + 1, 0, 0);
+                osg::Vec3 heightVec(0, 1, 0);
+                osg::Geometry* geometry;
+                geometry = osg::createTexturedQuadGeometry(corner, widthVec, heightVec);
+                simgear::EffectGeode* geode = new simgear::EffectGeode;
+                geode->setName("test");
+                geode->addDrawable(geometry);
+                //osg::Node *custom_obj;
+                SGMaterial *mat = matlib->find("UnidirectionalTaper");
+                if (mat)
+                    geode->setEffect(mat->get_effect());
+                obj_trans->addChild(geode);
+                // wire as much of the scene graph together as we can
+                //->addChild( obj_trans );
+                group->addChild( obj_trans );
+        /////////////////////////////////////////////////////////////////////
+        } else {
+             cerr << "BIG FAT WARNING: current position is here : " << pos << endl;
+        }
+        for(intVecIterator j = (i)->getIntentions().begin(); j != (i)->getIntentions().end(); j++) {
+             osg::Matrix obj_pos;
+            int k = (*j)-1;
+            if (k >= 0) {
+                osg::MatrixTransform *obj_trans = new osg::MatrixTransform;
+                obj_trans->setDataVariance(osg::Object::STATIC);
+
+                WorldCoordinate( obj_pos, segments[k]->getLatitude(), segments[k]->getLongitude(), parent->elevation()+8+dx, -(segments[k]->getHeading()) );
 
                 obj_trans->setMatrix( obj_pos );
-        //osg::Vec3 center(0, 0, 0)
-
-        float width = (*i)->getLength() /2.0;
-        osg::Vec3 corner(-width, 0, 0.25f);
-        osg::Vec3 widthVec(2*width + 1, 0, 0);
-        osg::Vec3 heightVec(0, 0, 1);
-        osg::Geometry* geometry;
-        geometry = osg::createTexturedQuadGeometry(corner, widthVec, heightVec);
-        simgear::EffectGeode* geode = new simgear::EffectGeode;
-        geode->setName("test");
-        geode->addDrawable(geometry);
-        //osg::Node *custom_obj;
-        
-        obj_trans->addChild(geode);
-            // wire as much of the scene graph together as we can
-        //->addChild( obj_trans );
-        group->addChild( obj_trans );
+                //osg::Vec3 center(0, 0, 0)
+
+                float width = segments[k]->getLength() /2.0;
+                osg::Vec3 corner(-width, 0, 0.25f);
+                osg::Vec3 widthVec(2*width + 1, 0, 0);
+                osg::Vec3 heightVec(0, 1, 0);
+                osg::Geometry* geometry;
+                geometry = osg::createTexturedQuadGeometry(corner, widthVec, heightVec);
+                simgear::EffectGeode* geode = new simgear::EffectGeode;
+                geode->setName("test");
+                geode->addDrawable(geometry);
+                //osg::Node *custom_obj;
+                SGMaterial *mat = matlib->find("UnidirectionalTaper");
+                if (mat)
+                    geode->setEffect(mat->get_effect());
+                obj_trans->addChild(geode);
+                // wire as much of the scene graph together as we can
+                //->addChild( obj_trans );
+                group->addChild( obj_trans );
+            }
+        }
+        dx += 0.1;
     }
 
 
index 319d8b2dd540b069b427a94300f4a75585f7cd6e..57295c65ff251b828c9848aea4f484e1e34a58c7 100644 (file)
 #ifndef _GROUNDNETWORK_HXX_
 #define _GROUNDNETWORK_HXX_
 
+#include <osg/Geode>
+#include <osg/Geometry>
+#include <osg/MatrixTransform>
+#include <osg/Shape>
+
+
 #include <simgear/compiler.h>
 #include <simgear/route/waypoint.hxx>
 
@@ -37,6 +43,7 @@ using std::vector;
 #include "parking.hxx"
 #include <ATC/trafficcontrol.hxx>
 
+
 class FGTaxiSegment; // forward reference
 class FGAIFlightPlan; // forward reference
 class FGAirport;      // forward reference
@@ -242,6 +249,8 @@ private:
   void checkHoldPosition(int id, double lat, double lon, 
                         double heading, double speed, double alt);
 
+  osg::Group* group;
+
 public:
   FGGroundNetwork();
   ~FGGroundNetwork();
index 11d8d0abee3055a0fa84d460639c16242e8b080a..3445e0a7a6d9612bf525c977282789e434c08a50 100644 (file)
@@ -68,6 +68,7 @@ FGAISchedule::FGAISchedule()
   radius = 0;
   groundOffset = 0;
   distanceToUser = 0;
+  valid = true;
   //score = 0;
 }
 
@@ -120,6 +121,7 @@ FGAISchedule::FGAISchedule(string model,
   runCount         = 0;
   hits             = 0;
   initialized      = false;
+  valid            = true;
 }
 
 FGAISchedule::FGAISchedule(const FGAISchedule &other)
@@ -146,6 +148,7 @@ FGAISchedule::FGAISchedule(const FGAISchedule &other)
   runCount           = other.runCount;
   hits               = other.hits;
   initialized        = other.initialized;
+  valid              = other.valid;
 }
 
 
@@ -192,9 +195,12 @@ bool FGAISchedule::update(time_t now, const SGVec3d& userCart)
     elapsedTimeEnroute,
     remainingTimeEnroute, 
     deptime = 0;
-  
+  if (!valid) {
+    return false;
+  }
   scheduleFlights();
   if (flights.empty()) { // No flights available for this aircraft
+      valid = false;
       return false;
   }
   
@@ -211,7 +217,7 @@ bool FGAISchedule::update(time_t now, const SGVec3d& userCart)
      firstRun = false;
   }
   
-  FGScheduledFlight* flight = flights.front();
+    FGScheduledFlight* flight = flights.front();
   if (!deptime) {
     deptime = flight->getDepartureTime();
     //cerr << "Settiing departure time " << deptime << endl;
@@ -329,19 +335,29 @@ bool FGAISchedule::createAIAircraft(FGScheduledFlight* flight, double speedKnots
   aircraft->setBank(0);
       
   courseToDest = SGGeodesy::courseDeg(position, arr->geod());
-  aircraft->SetFlightPlan(new FGAIFlightPlan(aircraft, flightPlanName, courseToDest, deptime, 
-                                                            dep, arr, true, radius, 
-                                                            flight->getCruiseAlt()*100, 
-                                                            position.getLatitudeDeg(), 
-                   position.getLongitudeDeg(), 
-                   speedKnots, flightType, acType, 
-                                                            airline));
-                   
-    
-  FGAIManager* aimgr = (FGAIManager *) globals-> get_subsystem("ai_model");
-  aimgr->attach(aircraft);
-  AIManagerRef = aircraft->getID();
-  return true;
+    FGAIFlightPlan *fp = new FGAIFlightPlan(aircraft, flightPlanName, courseToDest, deptime, 
+                                            dep, arr, true, radius, 
+                                            flight->getCruiseAlt()*100, 
+                                            position.getLatitudeDeg(), 
+                                            position.getLongitudeDeg(), 
+                                            speedKnots, flightType, acType, 
+                                            airline);
+  if (fp->isValidPlan()) {
+        aircraft->SetFlightPlan(fp);
+        FGAIManager* aimgr = (FGAIManager *) globals-> get_subsystem("ai_model");
+        aimgr->attach(aircraft);
+        AIManagerRef = aircraft->getID();
+        return true;
+  } else {
+        delete aircraft;
+        delete fp;
+        //hand back the flights that had already been scheduled
+        while (!flights.empty()) {
+            flights.front()->release();
+            flights.erase(flights.begin());
+        }
+        return false;
+  }
 }
 
 // Create an initial heading for user controlled aircraft.
index 92b7e78aa0efb8ea55c4221b612bd653935e99c6..1f508271bb78a5c8ff6f3c13a59da61b7744c704 100644 (file)
@@ -59,6 +59,7 @@ class FGAISchedule
   bool firstRun;
   double courseToDest;
   bool initialized;
+  bool valid;
 
   void scheduleFlights();
   
@@ -124,6 +125,7 @@ class FGAISchedule
   // used to sort in decending order of score: I've probably found a better way to
   // decending order sorting, but still need to test that.
   bool operator< (const FGAISchedule &other) const { return (score > other.score); };
+    void taint() { valid = false; };
   //void * getAiRef                 () { return AIManagerRef; };
   //FGAISchedule* getAddress        () { return this;};
 
index 4abbc1a20a8673618d06d28644c19708f92aef8d..9ebf78c1c7c063e80ba68352d1d4073131d4a3a8 100644 (file)
@@ -258,6 +258,7 @@ void FGTrafficManager::update(double /*dt */ )
     }
     //cerr << "Processing << " << (*currAircraft)->getRegistration() << " with score " << (*currAircraft)->getScore() << endl;
     if (!((*currAircraft)->update(now, userCart))) {
+        (*currAircraft)->taint();
         // NOTE: With traffic manager II, this statement below is no longer true
         // after proper initialization, we shouldnt get here.
         // But let's make sure