]> git.mxchange.org Git - flightgear.git/commitdiff
Initial stab at making the AI plane take the user into account when flying a circuit...
authordaveluff <daveluff>
Wed, 11 Jun 2003 21:49:46 +0000 (21:49 +0000)
committerdaveluff <daveluff>
Wed, 11 Jun 2003 21:49:46 +0000 (21:49 +0000)
src/ATC/AILocalTraffic.cxx
src/ATC/tower.cxx
src/ATC/tower.hxx

index 4a7b0da31f059221118f0b7c2dd976cede87fcbc..65557cdf9bbdca73758424ace8cf219f5398c667 100644 (file)
@@ -605,6 +605,8 @@ void FGAILocalTraffic::FlyTrafficPattern(double dt) {
        double wind_from = wind_from_hdg->getDoubleValue();
        double wind_speed = wind_speed_knots->getDoubleValue();
 
+       double dveldt;
+       
        switch(leg) {
        case TAKEOFF_ROLL:
                //inAir = false;
@@ -627,9 +629,26 @@ void FGAILocalTraffic::FlyTrafficPattern(double dt) {
                break;
        case CLIMBOUT:
                track = rwy.hdg;
+               // Turn to crosswind if above 600ft AND if other traffic allows
+               // (decided in FGTower and accessed through GetCrosswindConstraint(...)).
                if((pos.elev() - rwy.threshold_pos.elev()) * SG_METER_TO_FEET > 600) {
-                       cout << "Turning to crosswind, distance from threshold = " << orthopos.y() << '\n'; 
-                       leg = TURN1;
+                       double cc = 0.0;
+                       if(tower->GetCrosswindConstraint(cc)) {
+                               if(orthopos.y() > cc) {
+                                       cout << "Turning to crosswind, distance from threshold = " << orthopos.y() << '\n'; 
+                                       leg = TURN1;
+                               }
+                       } else {
+                               cout << "Turning to crosswind, distance from threshold = " << orthopos.y() << '\n'; 
+                               leg = TURN1;
+                       }
+               }
+               // Need to check for levelling off in case we can't turn crosswind as soon
+               // as we would like due to other traffic.
+               if((pos.elev() - rwy.threshold_pos.elev()) * SG_METER_TO_FEET > 1000) {
+                       slope = 0.0;
+                       pitch = 0.0;
+                       IAS = 80.0;             // FIXME - use smooth transistion to new speed and attitude.
                }
                break;
        case TURN1:
@@ -647,9 +666,18 @@ void FGAILocalTraffic::FlyTrafficPattern(double dt) {
                        pitch = 0.0;
                        IAS = 80.0;             // FIXME - use smooth transistion to new speed
                }
-               // turn 1000m out for now
+               // turn 1000m out for now, taking other traffic into accout
                if(fabs(orthopos.x()) > 980) {
-                       leg = TURN2;
+                       double dd = 0.0;
+                       if(tower->GetDownwindConstraint(dd)) {
+                               if(fabs(orthopos.x()) > fabs(dd)) {
+                                       cout << "Turning to downwind, distance from centerline = " << fabs(orthopos.x()) << '\n'; 
+                                       leg = TURN2;
+                               }
+                       } else {
+                               cout << "Turning to downwind, distance from centerline = " << fabs(orthopos.x()) << '\n'; 
+                               leg = TURN2;
+                       }
                }
                break;
        case TURN2:
@@ -681,15 +709,26 @@ void FGAILocalTraffic::FlyTrafficPattern(double dt) {
                        transmitted = true;
                }
                if(orthopos.y() < -480) {
+                       // FIXME - TODO - take tower baseleg constraint ie. other traffic, into account when calculating start of descent
                        slope = -4.0;   // FIXME - calculate to descent at 500fpm and hit the threshold (taking wind into account as well!!)
                        pitch = -3.0;
                        IAS = 85.0;
                }
                if(orthopos.y() < -980) {
-                       //roll = -20;
-                       leg = TURN3;
-                       transmitted = false;
-                       IAS = 80.0;
+                       double bb = 0.0;
+                       if(tower->GetDownwindConstraint(bb)) {
+                               if(fabs(orthopos.y()) > fabs(bb)) {
+                                       cout << "Turning to base, distance from threshold = " << fabs(orthopos.y()) << '\n'; 
+                                       leg = TURN3;
+                                       transmitted = false;
+                                       IAS = 80.0;
+                               }
+                       } else {
+                               cout << "Turning to base, distance from threshold = " << fabs(orthopos.y()) << '\n'; 
+                               leg = TURN3;
+                               transmitted = false;
+                               IAS = 80.0;
+                       }
                }
                break;
        case TURN3:
@@ -759,7 +798,7 @@ void FGAILocalTraffic::FlyTrafficPattern(double dt) {
                        pos.setelev(aip.getSGLocation()->get_cur_elev_m() + wheelOffset);
                }
                track = rwy.hdg;
-               double dveldt = -5.0;
+               dveldt = -5.0;
                vel += dveldt * dt;
                // FIXME - differentiate between touch and go and full stops
                if(vel <= 15.0) {
@@ -775,6 +814,8 @@ void FGAILocalTraffic::FlyTrafficPattern(double dt) {
                        }
                }
                break;
+       case LEG_UNKNOWN:
+               break;
     }
 
        if(inAir) {
index db95044a56f23004f1a5c8c1b1c741b50f722829..62aade7161b79f9e778a3a0e7e736422395fa466 100644 (file)
@@ -44,6 +44,7 @@ longFinalAcknowledged(false),
 finalReported(false),
 finalAcknowledged(false),
 opType(TTT_UNKNOWN),
+leg(LEG_UNKNOWN),
 isUser(false)
 {
        plane.callsign = "UNKNOWN";
@@ -59,6 +60,7 @@ longFinalAcknowledged(false),
 finalReported(false),
 finalAcknowledged(false),
 opType(TTT_UNKNOWN),
+leg(LEG_UNKNOWN),
 isUser(false)
 {
        plane = p;
@@ -74,6 +76,7 @@ longFinalAcknowledged(false),
 finalReported(false),
 finalAcknowledged(false),
 opType(TTT_UNKNOWN),
+leg(LEG_UNKNOWN),
 isUser(false)
 {
        plane.callsign = "UNKNOWN";
@@ -90,6 +93,7 @@ longFinalAcknowledged(false),
 finalReported(false),
 finalAcknowledged(false),
 opType(TTT_UNKNOWN),
+leg(LEG_UNKNOWN),
 isUser(false)
 {
        plane = p;
@@ -230,7 +234,6 @@ void FGTower::Update(double dt) {
        // Do one plane from the hold list
        if(ii == 4) {
                if(holdList.size()) {
-                       //cout << "A" << endl;
                        //cout << "*holdListItr = " << *holdListItr << endl;
                        if(holdListItr == holdList.end()) {
                                holdListItr = holdList.begin();
@@ -240,14 +243,10 @@ void FGTower::Update(double dt) {
                        TowerPlaneRec* t = *holdListItr;
                        //cout << "t = " << t << endl;
                        if(t->holdShortReported) {
-                               //cout << "B" << endl;
                                double responseTime = 10.0;             // seconds - this should get more sophisticated at some point
                                if(t->clearanceCounter > responseTime) {
-                                       //cout << "C" << endl;
                                        if(t->nextOnRwy) {
-                                               //cout << "D" << endl;
                                                if(rwyOccupied) {
-                                                       //cout << "E" << endl;
                                                        // Do nothing for now - consider acknowloging hold short eventually
                                                } else {
                                                        // Lets Roll !!!!
@@ -337,20 +336,49 @@ void FGTower::Update(double dt) {
                if(circuitList.size()) {
                        circuitListItr = circuitList.begin();   // TODO - at the moment we're constraining plane 2 based on plane 1 - this won't work for 3 planes in the circuit!!
                        TowerPlaneRec* t = *circuitListItr;
+                       if(t->isUser) {
+                               t->pos.setlon(user_lon_node->getDoubleValue());
+                               t->pos.setlat(user_lat_node->getDoubleValue());
+                               t->pos.setelev(user_elev_node->getDoubleValue());
+                       } else {
+                               // TODO - set/update the position if it's an AI plane
+                       }
                        Point3D tortho = ortho.ConvertToLocal(t->pos);
                        if(t->isUser) {
                                // Need to figure out which leg he's on
+                               //cout << "rwy.hdg = " << rwy.hdg << " user hdg = " << user_hdg_node->getDoubleValue();
                                double ho = GetAngleDiff_deg(user_hdg_node->getDoubleValue(), rwy.hdg);
+                               //cout << " ho = " << ho << '\n';
                                // TODO FIXME - get the wind and convert this to track, or otherwise use track somehow!!!
                                // If it's gusty might need to filter the value, although we are leaving 30 degrees each way leeway!
                                if(abs(ho) < 30) {
                                        // could be either takeoff, climbout or landing - check orthopos.y
-                                       if((tortho.y() < 0) || (t->leg == TURN4) || (t->leg == LANDING_ROLL)) {
-                                               t->leg = LANDING_ROLL;
-                                               //cout << "Landing_roll\n";
+                                       //cout << "tortho.y = " << tortho.y() << '\n';
+                                       if((tortho.y() < 0) || (t->leg == TURN4) || (t->leg == FINAL)) {
+                                               t->leg = FINAL;
+                                               //cout << "Final\n";
                                        } else {
                                                t->leg = CLIMBOUT;      // TODO - check elev wrt. apt elev to differentiate takeoff roll and climbout
                                                //cout << "Climbout\n";
+                                               // If it's the user we may be unsure of his/her intentions.
+                                               // (Hopefully the AI planes won't try confusing the sim!!!)
+                                               if(t->opType == TTT_UNKNOWN) {
+                                                       if(tortho.y() > 5000) {
+                                                               // 5 km out from threshold - assume it's a departure
+                                                               t->opType = OUTBOUND;
+                                                               // Since we are unknown operation we should be in depList already.
+                                                               circuitList.erase(circuitListItr);
+                                                               circuitListItr = circuitList.begin();
+                                                       }
+                                               } else if(t->opType == CIRCUIT) {
+                                                       if(tortho.y() > 10000) {
+                                                               // 10 km out - assume the user has abandoned the circuit!!
+                                                               t->opType = OUTBOUND;
+                                                               depList.push_back(t);
+                                                               circuitList.erase(circuitListItr);
+                                                               circuitListItr = circuitList.begin();
+                                                       }
+                                               }
                                        }
                                } else if(abs(ho) < 60) {
                                        // turn1 or turn 4
@@ -394,29 +422,35 @@ void FGTower::Update(double dt) {
                        case FINAL:
                                // Base leg must be at least as far out as the plane is - actually possibly not necessary for separation, but we'll use that for now.
                                base_leg_pos = tortho.y();
+                               //cout << "base_leg_pos = " << base_leg_pos << '\n';
                                break;
                        case TURN4:
                                // Fall through to base
                        case BASE:
                                base_leg_pos = tortho.y();
+                               //cout << "base_leg_pos = " << base_leg_pos << '\n';
                                break;
                        case TURN3:
                                // Fall through to downwind
                        case DOWNWIND:
                                // Only have the downwind leg pos as turn-to-base constraint if more negative than we already have.
                                base_leg_pos = (tortho.y() < base_leg_pos ? tortho.y() : base_leg_pos);
+                               //cout << "base_leg_pos = " << base_leg_pos;
                                downwind_leg_pos = tortho.x();          // Assume that a following plane can simply be constrained by the immediately in front downwind plane
+                               //cout << " downwind_leg_pos = " << downwind_leg_pos << '\n';
                                break;
                        case TURN2:
                                // Fall through to crosswind
                        case CROSSWIND:
                                crosswind_leg_pos = tortho.y();
+                               //cout << "crosswind_leg_pos = " << crosswind_leg_pos << '\n';
                                break;
                        case TURN1:
                                // Fall through to climbout
                        case CLIMBOUT:
                                // Only use current by constraint as largest
-                               crosswind_leg_pos = (tortho.y() > crosswind_leg_pos ? tortho.x() : crosswind_leg_pos);
+                               crosswind_leg_pos = (tortho.y() > crosswind_leg_pos ? tortho.y() : crosswind_leg_pos);
+                               //cout << "crosswind_leg_pos = " << crosswind_leg_pos << '\n';
                                break;
                        case TAKEOFF_ROLL:
                                break;
@@ -452,6 +486,37 @@ void FGTower::Update(double dt) {
 }
 
 
+// Returns true if positions of crosswind/downwind/base leg turns should be constrained by previous traffic
+// plus the constraint position as a rwy orientated orthopos (meters)
+bool FGTower::GetCrosswindConstraint(double& cpos) {
+       if(crosswind_leg_pos != 0.0) {
+               cpos = crosswind_leg_pos;
+               return(true);
+       } else {
+               cpos = 0.0;
+               return(false);
+       }
+}
+bool FGTower::GetDownwindConstraint(double& dpos) {
+       if(downwind_leg_pos != 0.0) {
+               dpos = downwind_leg_pos;
+               return(true);
+       } else {
+               dpos = 0.0;
+               return(false);
+       }
+}
+bool FGTower::GetBaseConstraint(double& bpos) {
+       if(base_leg_pos != 0.0) {
+               bpos = base_leg_pos;
+               return(true);
+       } else {
+               bpos = 0.0;
+               return(false);
+       }
+}
+
+
 // Figure out which runways are active.
 // For now we'll just be simple and do one active runway - eventually this will get much more complex
 // This is a private function - public interface to the results of this is through GetActiveRunway
index 13a0b6833af3dde33233101364fafd4e99e590aa..dee2d5e5ea8cdbd473e113b3a78350de5e37a3c3 100644 (file)
@@ -135,6 +135,12 @@ public:
        inline atc_type GetType() { return TOWER; }
        
        inline FGGround* GetGroundPtr() { return ground; }
+       
+       // Returns true if positions of crosswind/downwind/base leg turns should be constrained by previous traffic
+       // plus the constraint position as a rwy orientated orthopos (meters)
+       bool GetCrosswindConstraint(double& cpos);
+       bool GetDownwindConstraint(double& dpos);
+       bool GetBaseConstraint(double& bpos);
 
 private:
        FGATCMgr* ATCmgr;       
@@ -224,7 +230,7 @@ private:
     SGPropertyNode* user_lon_node;
     SGPropertyNode* user_lat_node;
     SGPropertyNode* user_elev_node;
-       SGPropertyNode* user_hdg_node;
+    SGPropertyNode* user_hdg_node;
        
        // Details of the general traffic flow etc in the circuit
        double crosswind_leg_pos;       // Distance from threshold crosswind leg is being turned to in meters (actual operation - *not* ideal circuit)