]> git.mxchange.org Git - flightgear.git/blobdiff - src/AIModel/AIAircraft.cxx
Merge branch 'next' of gitorious.org:fg/flightgear into next
[flightgear.git] / src / AIModel / AIAircraft.cxx
index 30b7cf9d3be6f2dbe7781e2f28867b91af66c093..efb346a6b1e83b0e98af5569c4808ae452675117 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.
 //
@@ -47,11 +47,10 @@ using std::string;
 #include "AIAircraft.hxx"
 #include "performancedata.hxx"
 #include "performancedb.hxx"
+#include <signal.h>
 
 //#include <Airports/trafficcontroller.hxx>
 
-static string tempReg;
-
 FGAIAircraft::FGAIAircraft(FGAISchedule *ref) :
      /* HOT must be disabled for AI Aircraft,
       * otherwise traffic detection isn't working as expected.*/
@@ -65,9 +64,10 @@ FGAIAircraft::FGAIAircraft(FGAISchedule *ref) :
     else
         groundOffset = 0;
 
-    fp = 0;
-    controller = 0;
-    prevController = 0;
+    fp              = 0;
+    controller      = 0;
+    prevController  = 0;
+    towerController = 0;
     dt_count = 0;
     dt_elev_count = 0;
     use_perf_vs = true;
@@ -92,6 +92,7 @@ FGAIAircraft::FGAIAircraft(FGAISchedule *ref) :
 
     _performance = 0; //TODO initialize to JET_TRANSPORT from PerformanceDB
     dt = 0;
+    takeOffStatus = 0;
 }
 
 
@@ -189,6 +190,7 @@ void FGAIAircraft::checkVisibility()
 
 void FGAIAircraft::AccelTo(double speed) {
     tgt_speed = speed;
+    assertSpeed(speed);
     if (!isStationary())
         _needsGroundElevation = true;
 }
@@ -285,6 +287,7 @@ void FGAIAircraft::ProcessFlightPlan( double dt, time_t now ) {
     if (! leadPointReached(curr)) {
         controlHeading(curr);
         controlSpeed(curr, next);
+        
             /*
             if (speed < 0) { 
                 cerr << getCallSign() 
@@ -348,13 +351,18 @@ void FGAIAircraft::ProcessFlightPlan( double dt, time_t now ) {
             fp->setLeadDistance(tgt_speed, tgt_heading, curr, next);
         }
 
+
         if (!(prev->getOn_ground()))  // only update the tgt altitude from flightplan if not on the ground
         {
             tgt_altitude_ft = prev->getAltitude();
             if (curr->getCrossat() > -1000.0) {
                 use_perf_vs = false;
-                tgt_vs = (curr->getCrossat() - altitude_ft) / (fp->getDistanceToGo(pos.getLatitudeDeg(), pos.getLongitudeDeg(), curr)
-                         / 6076.0 / speed*60.0);
+                // Distance to go in meters
+                double vert_dist_ft = curr->getCrossat() - altitude_ft;
+                double err_dist     = prev->getCrossat() - altitude_ft;
+                double dist_m       = fp->getDistanceToGo(pos.getLatitudeDeg(), pos.getLongitudeDeg(), curr);
+                tgt_vs = calcVerticalSpeed(vert_dist_ft, dist_m, speed, err_dist);
+                
                 checkTcas();
                 tgt_altitude_ft = curr->getCrossat();
             } else {
@@ -367,6 +375,49 @@ void FGAIAircraft::ProcessFlightPlan( double dt, time_t now ) {
     }
 }
 
+double FGAIAircraft::calcVerticalSpeed(double vert_ft, double dist_m, double speed, double err)
+{
+    // err is negative when we passed too high
+    double vert_m = vert_ft * SG_FEET_TO_METER;
+    double err_m  = err     * SG_FEET_TO_METER;
+    //double angle = atan2(vert_m, dist_m);
+    double speedMs = (speed * SG_NM_TO_METER) / 3600;
+    //double vs = cos(angle) * speedMs; // Now in m/s
+    double vs = 0;
+    //cerr << "Error term = " << err_m << endl;
+    if (dist_m) {
+        vs = ((vert_m) / dist_m) * speedMs;
+    }
+    // Convert to feet per minute
+    vs *= (SG_METER_TO_FEET * 60);
+    //if (getCallSign() == "LUFTHANSA2002")
+    //if (fabs(vs) > 100000) {
+//     if (getCallSign() == "LUFTHANSA2057") {
+//         cerr << getCallSign() << " " << fp->getPreviousWaypoint()->getName() << ". Alt = " << altitude_ft <<  " vertical dist = " << vert_m << " horiz dist = " << dist_m << " << angle  = " << angle * SG_RADIANS_TO_DEGREES << " vs " << vs << " horizontal speed " << speed << "Previous crossAT " << fp->getPreviousWaypoint()->getCrossat() << endl;
+//     //= (curr->getCrossat() - altitude_ft) / (fp->getDistanceToGo(pos.getLatitudeDeg(), pos.getLongitudeDeg(), curr)
+//     //                     / 6076.0 / speed*60.0);
+//         //raise(SIGSEGV);
+//     }
+    return vs;
+}
+
+void FGAIAircraft::assertSpeed(double speed)
+{
+    if ((speed < -50) || (speed > 1000)) {
+        cerr << getCallSign() << " " 
+            << "Previous waypoint " << fp->getPreviousWaypoint()->getName() << " "
+            << "Departure airport " << trafficRef->getDepartureAirport() << " "
+            << "Leg " << fp->getLeg() <<  " "
+            << "target_speed << " << tgt_speed <<  " "
+            << "speedFraction << " << speedFraction << " "
+            << "Currecnt speed << " << speed << " "
+            << endl;
+       raise(SIGSEGV);
+    }
+}
+
+
+
 void FGAIAircraft::checkTcas(void)
 {
     if (props->getIntValue("tcas/threat-level",0)==3)
@@ -495,12 +546,16 @@ void FGAIAircraft::getGroundElev(double dt) {
 
 
 void FGAIAircraft::doGroundAltitude() {
-    if ((fabs(altitude_ft - (tgt_altitude_ft+groundOffset)) > 1000.0)||
-        (isStationary()))
-        altitude_ft = (tgt_altitude_ft + groundOffset);
-    else
-        altitude_ft += 0.1 * ((tgt_altitude_ft+groundOffset) - altitude_ft);
-    tgt_vs = 0;
+    if ((fp->getLeg() == 7) && ((altitude_ft -  tgt_altitude_ft) > 5)) {
+        tgt_vs = -500;
+    } else {
+        if ((fabs(altitude_ft - (tgt_altitude_ft+groundOffset)) > 1000.0)||
+            (isStationary()))
+            altitude_ft = (tgt_altitude_ft + groundOffset);
+        else
+            altitude_ft += 0.1 * ((tgt_altitude_ft+groundOffset) - altitude_ft);
+        tgt_vs = 0;
+    }
 }
 
 
@@ -525,6 +580,7 @@ void FGAIAircraft::announcePositionToController() {
         case 3:              //Take off tower controller
             if (trafficRef->getDepartureAirport()->getDynamics()) {
                 controller = trafficRef->getDepartureAirport()->getDynamics()->getTowerController();
+                towerController = 0;
             } else {
                 cerr << "Error: Could not find Dynamics at airport : " << trafficRef->getDepartureAirport()->getId() << endl;
             }
@@ -555,6 +611,26 @@ void FGAIAircraft::announcePositionToController() {
     }
 }
 
+void FGAIAircraft::scheduleForATCTowerDepartureControl(int state) {
+    if (!takeOffStatus) {
+        int leg = fp->getLeg();
+        if (trafficRef) {
+            if (trafficRef->getDepartureAirport()->getDynamics()) {
+                towerController = trafficRef->getDepartureAirport()->getDynamics()->getTowerController();
+            } else {
+                cerr << "Error: Could not find Dynamics at airport : " << trafficRef->getDepartureAirport()->getId() << endl;
+            }
+            if (towerController) {
+                towerController->announcePosition(getID(), fp, fp->getCurrentWaypoint()->getRouteIndex(),
+                                                   _getLatitude(), _getLongitude(), hdg, speed, altitude_ft,
+                                                    trafficRef->getRadius(), leg, this);
+                //cerr << "Scheduling " << trafficRef->getCallSign() << " for takeoff " << endl;
+            }
+        }
+    }
+    takeOffStatus = state;
+}
+
 // Process ATC instructions and report back
 
 void FGAIAircraft::processATC(FGATCInstruction instruction) {
@@ -621,7 +697,6 @@ void FGAIAircraft::handleFirstWaypoint() {
     FGAIWaypoint* next = 0;// the next plus 1
 
     spinCounter = 0;
-    tempReg = "";
 
     //TODO fp should handle this
     fp->IncrementWaypoint(eraseWaypoints);
@@ -654,9 +729,13 @@ void FGAIAircraft::handleFirstWaypoint() {
     if (curr->getCrossat() > -1000.0) //use a calculated descent/climb rate
     {
         use_perf_vs = false;
-        tgt_vs = (curr->getCrossat() - prev->getAltitude())
-                 / (fp->getDistanceToGo(pos.getLatitudeDeg(), pos.getLongitudeDeg(), curr)
-                    / 6076.0 / prev->getSpeed()*60.0);
+        //tgt_vs = (curr->getCrossat() - prev->getAltitude())
+        //         / (fp->getDistanceToGo(pos.getLatitudeDeg(), pos.getLongitudeDeg(), curr)
+        //            / 6076.0 / prev->getSpeed()*60.0);
+        double vert_dist_ft = curr->getCrossat() - altitude_ft;
+        double err_dist     = prev->getCrossat() - altitude_ft;
+        double dist_m       = fp->getDistanceToGo(pos.getLatitudeDeg(), pos.getLongitudeDeg(), curr);
+        tgt_vs = calcVerticalSpeed(vert_dist_ft, dist_m, speed, err_dist);
         checkTcas();
         tgt_altitude_ft = curr->getCrossat();
     } else {
@@ -708,6 +787,7 @@ bool FGAIAircraft::leadPointReached(FGAIWaypoint* curr) {
           if (tgt_speed > -0.5) {
                 tgt_speed = -0.5;
           }
+          assertSpeed(tgt_speed);
           if (fp->getPreviousWaypoint()->getSpeed() < tgt_speed) {
               fp->getPreviousWaypoint()->setSpeed(tgt_speed);
           }
@@ -733,7 +813,7 @@ bool FGAIAircraft::leadPointReached(FGAIWaypoint* curr) {
                  minBearing = 10;
             }
             if ((minBearing < 360.0) && (minBearing > 10.0)) {
-                speedFraction = cos(minBearing *SG_DEGREES_TO_RADIANS);
+                speedFraction = 0.5 + (cos(minBearing *SG_DEGREES_TO_RADIANS) * 0.5);
             } else {
                 speedFraction = 1.0;
             }
@@ -748,6 +828,7 @@ bool FGAIAircraft::leadPointReached(FGAIWaypoint* curr) {
      }
     if ((dist_to_go < lead_dist) || (bearing > (minBearing * 1.1))) {
         minBearing = 360;
+        speedFraction = 1.0;
         return true;
     } else {
         return false;
@@ -783,15 +864,33 @@ bool FGAIAircraft::handleAirportEndPoints(FGAIWaypoint* prev, time_t now) {
     // 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;
+    //cerr << "Passing waypoint : " << prev->getName() << endl;
     if (prev->contains("PushBackPoint")) {
         dep->getDynamics()->releaseParking(fp->getGate());
         AccelTo(0.0);
-        setTaxiClearanceRequest(true);
+        //setTaxiClearanceRequest(true);
     }
     if (prev->contains("legend")) {
         fp->incrementLeg();
     }
-
+    if (prev->contains(string("DepartureHold"))) {
+        //cerr << "Passing point DepartureHold" << endl;
+        scheduleForATCTowerDepartureControl(1);
+    }
+    if (prev->contains(string("Accel"))) {
+        takeOffStatus = 3;
+    }
+    /*if (prev->contains(string("final"))) {
+        
+         cerr << getCallSign() << " " 
+            << fp->getPreviousWaypoint()->getName() 
+            << ". Alt = " << altitude_ft 
+            << " vs " << vs 
+            << " horizontal speed " << speed 
+            << "Previous crossAT " << fp->getPreviousWaypoint()->getCrossat()
+            << "Airport elevation" << getTrafficRef()->getArrivalAirport()->getElevation() 
+            << "Altitude difference " << (altitude_ft -  fp->getPreviousWaypoint()->getCrossat()) << 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->contains("END")) {
@@ -800,7 +899,7 @@ bool FGAIAircraft::handleAirportEndPoints(FGAIWaypoint* prev, time_t now) {
         if (nextDeparture < (now+1200)) {
             nextDeparture = now + 1200;
         }
-        fp->setTime(nextDeparture); // should be "next departure"
+        fp->setTime(nextDeparture);
     }
 
     return true;
@@ -850,6 +949,7 @@ void FGAIAircraft::controlSpeed(FGAIWaypoint* curr, FGAIWaypoint* next) {
 
     if (fabs(speed_diff) > 10) {
         prevSpeed = speed;
+        assertSpeed(speed);
         if (next) {
             fp->setLeadDistance(speed, tgt_heading, curr, next);
         }
@@ -978,13 +1078,14 @@ void FGAIAircraft::updateHeading() {
             //         << hdg << ". Target " << tgt_heading <<  ". Diff " << fabs(sum - tgt_heading) << ". Speed " << speed << endl;
             //if (headingDiff > 60) {
             groundTargetSpeed = tgt_speed; // * cos(headingDiff * SG_DEGREES_TO_RADIANS);
+            assertSpeed(groundTargetSpeed);
                 //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
-            
+            assertSpeed(groundTargetSpeed);
             // 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) {
@@ -1085,7 +1186,12 @@ void FGAIAircraft::updateVerticalSpeedTarget() {
                     tgt_vs = -_performance->descentRate();
             }
         } else {
-            double max_vs = 4*(tgt_altitude_ft - altitude_ft);
+            double vert_dist_ft = fp->getCurrentWaypoint()->getCrossat() - altitude_ft;
+            double err_dist     = 0; //prev->getCrossat() - altitude_ft;
+            double dist_m       = fp->getDistanceToGo(pos.getLatitudeDeg(), pos.getLongitudeDeg(), fp->getCurrentWaypoint());
+            tgt_vs = calcVerticalSpeed(vert_dist_ft, dist_m, speed, err_dist);
+            //cerr << "Target vs before : " << tgt_vs;
+/*            double max_vs = 10*(tgt_altitude_ft - altitude_ft);
             double min_vs = 100;
             if (tgt_altitude_ft < altitude_ft)
                 min_vs = -100.0;
@@ -1094,7 +1200,8 @@ void FGAIAircraft::updateVerticalSpeedTarget() {
                 tgt_vs = max_vs;
 
             if (fabs(tgt_vs) < fabs(min_vs))
-                tgt_vs = min_vs;
+                tgt_vs = min_vs;*/
+            //cerr << "target vs : after " << tgt_vs << endl;
         }
     } //else 
     //    tgt_vs = 0.0;
@@ -1141,6 +1248,14 @@ void FGAIAircraft::handleATCRequests() {
                                               altitude_ft, dt);
         processATC(controller->getInstruction(getID()));
     }
+    if (towerController) {
+        towerController->updateAircraftInformation(getID(),
+                                              pos.getLatitudeDeg(),
+                                              pos.getLongitudeDeg(),
+                                              hdg,
+                                              speed,
+                                              altitude_ft, dt);
+    }
 }
 
 void FGAIAircraft::updateActualState() {
@@ -1152,7 +1267,7 @@ void FGAIAircraft::updateActualState() {
         speed = _performance->actualSpeed(this, groundTargetSpeed, dt);
     else
         speed = _performance->actualSpeed(this, (tgt_speed *speedFraction), dt);
-
+    assertSpeed(speed);
     updateHeading();
     roll = _performance->actualBankAngle(this, tgt_roll, dt);