]> git.mxchange.org Git - flightgear.git/blobdiff - src/AIModel/AIAircraft.cxx
Changes to the AIModel code, to prepare for the new traffic manager code:
[flightgear.git] / src / AIModel / AIAircraft.cxx
index 2228f83d9214ab857e89d7ec0f02d211dcac7d05..d66eaa3ea3c449d3eae62348c2e14e908c4e1dab 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.
 //
@@ -29,6 +29,7 @@
 #include <Main/viewer.hxx>
 #include <Scenery/scenery.hxx>
 #include <Scenery/tilemgr.hxx>
+#include <Airports/dynamics.hxx>
 
 #include <string>
 #include <math.h>
@@ -40,7 +41,7 @@
 #  include <ieeefp.h>
 #endif
 
-SG_USING_STD(string);
+using std::string;
 
 #include "AIAircraft.hxx"
 #include "performancedata.hxx"
@@ -150,7 +151,8 @@ void FGAIAircraft::setPerformance(const std::string& acclass) {
          return;
      }
      catch (FP_Inactive) {
-         return;
+         //return;
+         groundTargetSpeed = 0;
      }
 
      handleATCRequests(); // ATC also has a word to say
@@ -266,7 +268,10 @@ void FGAIAircraft::ProcessFlightPlan( double dt, time_t now ) {
         //TODO let the fp handle this (loading of next leg)
         fp->IncrementWaypoint((bool) trafficRef);
         if (!(fp->getNextWaypoint()) && trafficRef)
-            loadNextLeg();
+            if (!loadNextLeg()) {
+                setDie(true);
+                return;
+            }
 
         prev = fp->getPreviousWaypoint();
         curr = fp->getCurrentWaypoint();
@@ -290,7 +295,7 @@ void FGAIAircraft::ProcessFlightPlan( double dt, time_t now ) {
         }
 
         if (next) {
-            fp->setLeadDistance(speed, tgt_heading, curr, next);
+            fp->setLeadDistance(tgt_speed, tgt_heading, curr, next);
         }
 
         if (!(prev->on_ground))  // only update the tgt altitude from flightplan if not on the ground
@@ -321,11 +326,13 @@ bool FGAIAircraft::_getGearDown() const {
 }
 
 
-void FGAIAircraft::loadNextLeg() {
+bool FGAIAircraft::loadNextLeg() {
 
     int leg;
     if ((leg = fp->getLeg())  == 10) {
-        trafficRef->next();
+        if (!trafficRef->next()) {
+            return false;
+        }
         setCallSign(trafficRef->getCallSign());
        //props->setStringValue("callsign", callsign.c_str());
         leg = 1;
@@ -352,7 +359,9 @@ void FGAIAircraft::loadNextLeg() {
                     trafficRef->getFlightType(),
                     acType,
                     company);
+       //cerr << "created  leg " << leg << " for " << trafficRef->getCallSign() << endl;
     }
+    return true;
 }
 
 
@@ -365,7 +374,7 @@ void FGAIAircraft::getGroundElev(double dt) {
     dt_elev_count += dt;
 
     // Update minimally every three secs, but add some randomness
-    // to prevent all IA objects doing this in synchrony
+    // to prevent all AI objects doing this in synchrony
     if (dt_elev_count < (3.0) + (rand() % 10))
         return;
 
@@ -413,10 +422,14 @@ void FGAIAircraft::announcePositionToController() {
     if (trafficRef) {
         int leg = fp->getLeg();
 
-        // Note that leg was been incremented after creating the current leg, so we should use
+        // Note that leg has been incremented after creating the current leg, so we should use
         // leg numbers here that are one higher than the number that is used to create the leg
         //
         switch (leg) {
+          case 2:              // Startup and Push back
+            if (trafficRef->getDepartureAirport()->getDynamics())
+                controller = trafficRef->getDepartureAirport()->getDynamics()->getStartupController();
+            break;
         case 3:              // Taxiing to runway
             if (trafficRef->getDepartureAirport()->getDynamics()->getGroundNetwork()->exists())
                 controller = trafficRef->getDepartureAirport()->getDynamics()->getGroundNetwork();
@@ -425,12 +438,14 @@ void FGAIAircraft::announcePositionToController() {
             if (trafficRef->getDepartureAirport()->getDynamics()) {
                 controller = trafficRef->getDepartureAirport()->getDynamics()->getTowerController();
                 //if (trafficRef->getDepartureAirport()->getId() == "EHAM") {
-                //cerr << trafficRef->getCallSign() << " at runway " << fp->getRunway() << "Ready for departure "
-                //   << trafficRef->getFlightType() << " to " << trafficRef->getArrivalAirport()->getId() << endl;
+                //string trns = trafficRef->getCallSign() + " at runway " + fp->getRunway() + 
+                //              ". Ready for departure. " + trafficRef->getFlightType() + " to " +
+                //              trafficRef->getArrivalAirport()->getId();
+                //fgSetString("/sim/messages/atc", trns.c_str());
                 //  if (controller == 0) {
                 //cerr << "Error in assigning controller at " << trafficRef->getDepartureAirport()->getId() << endl;
                 //}
-
+                //}
             } else {
                 cerr << "Error: Could not find Dynamics at airport : " << trafficRef->getDepartureAirport()->getId() << endl;
             }
@@ -446,29 +461,17 @@ void FGAIAircraft::announcePositionToController() {
 
         if ((controller != prevController) && (prevController != 0)) {
             prevController->signOff(getID());
-            string callsign =  trafficRef->getCallSign();
-            if ( trafficRef->getHeavy())
-                callsign += "Heavy";
-            switch (leg) {
-            case 3:
-                //cerr << callsign << " ready to taxi to runway " << fp->getRunway() << endl;
-                break;
-            case 4:
-                //cerr << callsign << " at runway " << fp->getRunway() << "Ready for take-off. "
-                //     << trafficRef->getFlightRules() << " to " << trafficRef->getArrivalAirport()->getId()
-                //     << "(" << trafficRef->getArrivalAirport()->getName() << ")."<< endl;
-                break;
-            }
         }
         prevController = controller;
         if (controller) {
             controller->announcePosition(getID(), fp, fp->getCurrentWaypoint()->routeIndex,
                                          _getLatitude(), _getLongitude(), hdg, speed, altitude_ft,
-                                         trafficRef->getRadius(), leg, trafficRef->getCallSign());
+                                         trafficRef->getRadius(), leg, this);
         }
     }
 }
 
+// Process ATC instructions and report back
 
 void FGAIAircraft::processATC(FGATCInstruction instruction) {
     if (instruction.getCheckForCircularWait()) {
@@ -494,7 +497,7 @@ void FGAIAircraft::processATC(FGATCInstruction instruction) {
     } else {
         if (holdPos) {
             //if (trafficRef)
-            // cerr << trafficRef->getCallSign() << " Resuming Taxi " << endl;
+            // cerr << trafficRef->getCallSign() << " Resuming Taxi." << endl;
             holdPos = false;
         }
         // Change speed Instruction. This can only be excecuted when there is no
@@ -522,6 +525,7 @@ void FGAIAircraft::processATC(FGATCInstruction instruction) {
 
 void FGAIAircraft::handleFirstWaypoint() {
     bool eraseWaypoints;         //TODO YAGNI
+    headingError = 0;
     if (trafficRef) {
         eraseWaypoints = true;
     } else {
@@ -538,7 +542,10 @@ void FGAIAircraft::handleFirstWaypoint() {
     //TODO fp should handle this
     fp->IncrementWaypoint(eraseWaypoints);
     if (!(fp->getNextWaypoint()) && trafficRef)
-        loadNextLeg();
+        if (!loadNextLeg()) {
+            setDie(true);
+            return;
+        }
 
     prev = fp->getPreviousWaypoint();   //first waypoint
     curr = fp->getCurrentWaypoint();    //second waypoint
@@ -609,7 +616,6 @@ bool FGAIAircraft::leadPointReached(FGAIFlightPlan::waypoint* curr) {
 
     //cerr << "2" << endl;
     double lead_dist = fp->getLeadDistance();
-    //cerr << " Distance : " << dist_to_go << ": Lead distance " << lead_dist << endl;
     // experimental: Use fabs, because speed can be negative (I hope) during push_back.
 
     if (lead_dist < fabs(2*speed)) {
@@ -619,6 +625,12 @@ bool FGAIAircraft::leadPointReached(FGAIFlightPlan::waypoint* curr) {
     }
 
     //prev_dist_to_go = dist_to_go;
+    //if (dist_to_go < lead_dist)
+    //     cerr << trafficRef->getCallSign() << " Distance : " 
+    //          << dist_to_go << ": Lead distance " 
+    //          << lead_dist << " " << curr->name 
+    //          << " Ground target speed " << groundTargetSpeed << endl;
+         
     return dist_to_go < lead_dist;
 }
 
@@ -633,7 +645,7 @@ bool FGAIAircraft::aiTrafficVisible() {
 
     user.CourseAndDistance(current, &course, &distance);
 
-    return ((distance * SG_METER_TO_NM) <= TRAFFICTOAIDIST);
+    return ((distance * SG_METER_TO_NM) <= TRAFFICTOAIDISTTODIE);
 }
 
 
@@ -656,6 +668,7 @@ bool FGAIAircraft::handleAirportEndPoints(FGAIFlightPlan::waypoint* prev, time_t
 
     // This waypoint marks the fact that the aircraft has passed the initial taxi
     // departure waypoint, so it can release the parking.
+    //cerr << trafficRef->getCallSign() << " has passed waypoint " << prev->name << " at speed " << speed << endl;
     if (prev->name == "PushBackPoint") {
         dep->getDynamics()->releaseParking(fp->getGate());
         time_t holdUntil = now + 120;
@@ -758,6 +771,7 @@ void FGAIAircraft::updatePrimaryTargetValues() {
                 throw AI_OutOfSight();
             }
         }
+        timeElapsed = now - fp->getStartTime();
         if (! fp->isActive(now)) { 
             throw FP_Inactive();
         }
@@ -819,30 +833,63 @@ void FGAIAircraft::updateHeading() {
         // If on ground, calculate heading change directly
         if (onGround()) {
             double headingDiff = fabs(hdg-tgt_heading);
+            double bank_sense = 0.0;
+        /*
+        double diff = fabs(hdg - tgt_heading);
+        if (diff > 180)
+            diff = fabs(diff - 360);
 
+        double sum = hdg + diff;
+        if (sum > 360.0)
+            sum -= 360.0;
+        if (fabs(sum - tgt_heading) < 1.0) {
+            bank_sense = 1.0;    // right turn
+        } else {
+            bank_sense = -1.0;   // left turn
+        }*/
             if (headingDiff > 180)
                 headingDiff = fabs(headingDiff - 360);
-
-            groundTargetSpeed = tgt_speed - (tgt_speed * (headingDiff/45));
+            double sum = hdg + headingDiff;
+            if (sum > 360.0) 
+                sum -= 360.0;
+            if (fabs(sum - tgt_heading) > 0.0001) {
+                bank_sense = -1.0;
+            } else {
+                bank_sense = 1.0;
+            }
+            //if (trafficRef)
+               //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);
+            //} else {
+            //    groundTargetSpeed = tgt_speed;
+            //}
             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 += dt * sign(roll);
-
-                if (headingChangeRate > 30)
-                    headingChangeRate = 30;
-                else if (headingChangeRate < -30)
-                    headingChangeRate = -30;
-
+                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 (fabs(headingChangeRate) > headingDiff)
-                    headingChangeRate = headingDiff*sign(roll);
-                else
-                    headingChangeRate += dt * sign(roll);
+                   if (fabs(headingChangeRate) > headingDiff)
+                       headingChangeRate = headingDiff*sign(roll);
+                   else
+                       headingChangeRate += dt * sign(roll);
             }
-            hdg += headingChangeRate * dt;
+
+           hdg += headingChangeRate * dt * (fabs(speed) / 15);
+            headingError = headingDiff;
         } else {
             if (fabs(speed) > 1.0) {
                 turn_radius_ft = 0.088362 * speed * speed
@@ -945,6 +992,20 @@ void FGAIAircraft::updatePitchAngleTarget() {
     }
 }
 
+string FGAIAircraft::atGate() {
+     string tmp("");
+     if (fp->getLeg() < 3) {
+         if (trafficRef) {
+             if (fp->getGate() > 0) {
+                 FGParking *park =
+                     trafficRef->getDepartureAirport()->getDynamics()->getParking(fp->getGate());
+                 tmp = park->getName();
+             }
+         }
+     }
+     return tmp;
+}
+
 void FGAIAircraft::handleATCRequests() {
     //TODO implement NullController for having no ATC to save the conditionals
     if (controller) {