From: daveluff Date: Tue, 2 Mar 2004 10:43:16 +0000 (+0000) Subject: Move the mechanics of turning out of the derived classes into AIPlane. The user... X-Git-Url: https://git.mxchange.org/?a=commitdiff_plain;h=9773ba55426fea9597046cceacc05926d03966d4;p=flightgear.git Move the mechanics of turning out of the derived classes into AIPlane. The user-visible effect is that AI planes no longer suddenly change direction without turning properly. --- diff --git a/src/ATC/AIGAVFRTraffic.cxx b/src/ATC/AIGAVFRTraffic.cxx index 2078ef6dc..8449f236c 100644 --- a/src/ATC/AIGAVFRTraffic.cxx +++ b/src/ATC/AIGAVFRTraffic.cxx @@ -84,7 +84,8 @@ bool FGAIGAVFRTraffic::Init(Point3D pt, string destID, const string& callsign) { _pos.setelev(_cruise_alt); // initially set waypoint as airport location _wp = _destPos; - _hdg = GetHeadingFromTo(_pos, _wp); + //_hdg = GetHeadingFromTo(_pos, _wp); + SetTrack(GetHeadingFromTo(_pos, _wp)); _roll = 0.0; _pitch = 0.0; slope = 0.0; @@ -201,7 +202,8 @@ void FGAIGAVFRTraffic::FlyPlane(double dt) { _straightIn = true; _incoming = true; _wp = GetPatternApproachPos(); - _hdg = GetHeadingFromTo(_pos, _wp); // TODO - turn properly! + //_hdg = GetHeadingFromTo(_pos, _wp); // TODO - turn properly! + SetTrack(GetHeadingFromTo(_pos, _wp)); slope = atan((_wp.elev() - _pos.elev()) / dclGetHorizontalSeparation(_wp, _pos)) * DCL_RADIANS_TO_DEGREES; double thesh_offset = 0.0; Point3D opos = ortho.ConvertToLocal(_pos); @@ -221,7 +223,7 @@ void FGAIGAVFRTraffic::FlyPlane(double dt) { _downwindEntry = true; _incoming = true; _wp = GetPatternApproachPos(); - _hdg = GetHeadingFromTo(_pos, _wp); // TODO - turn properly! + SetTrack(GetHeadingFromTo(_pos, _wp)); slope = atan((_wp.elev() - _pos.elev()) / dclGetHorizontalSeparation(_wp, _pos)) * DCL_RADIANS_TO_DEGREES; //cout << "slope = " << slope << '\n'; pending_transmission = "Report "; @@ -247,7 +249,7 @@ void FGAIGAVFRTraffic::FlyPlane(double dt) { if(_straightIn) { //cout << "A " << flush; if(fabs(orthopos.x()) < 10.0 && !_established) { - _hdg = rwy.hdg; // MEGA MEGA HACK - FIXME!!!!!!! + SetTrack(rwy.hdg); _established = true; //cout << "Established at " << orthopos << '\n'; } @@ -279,15 +281,8 @@ void FGAIGAVFRTraffic::FlyPlane(double dt) { if(_entering) { //cout << "C" << flush; if(_turning) { - double tgt_hdg = rwy.hdg + 180.0; - while((tgt_hdg - _hdg) > 180.0) _hdg += 360.0; - while((_hdg - tgt_hdg) > 180.0) _hdg -= 360.0; - double turn_time = 60.0; - _hdg += (360.0 / turn_time) * dt * (tgt_hdg > _hdg ? 1.0 : -1.0); - Bank(25.0 * (tgt_hdg > _hdg ? 1.0 : -1.0)); - if(fabs(_hdg - tgt_hdg) < 2.0) { + if(fabs(_hdg - (rwy.hdg + 180)) < 2.0) { // TODO - use track instead of _hdg? //cout << "Going Local...\n"; - _hdg = rwy.hdg + 180.0; // TODO - FIX THIS UGLY HACK!!!!!!! leg = DOWNWIND; _local = true; _aip.setVisible(true); // HACK @@ -300,6 +295,7 @@ void FGAIGAVFRTraffic::FlyPlane(double dt) { if(fabs(orthopos.x() - (patternDirection == 1 ? 1000 : -1000)) < (_e45 ? 175 : 550)) { // Caution - hardwired turn clearances. //cout << "_turning...\n"; _turning = true; + SetTrack(rwy.hdg + 180.0); } // TODO - need to check for other traffic in the pattern and enter much more integilently than that!!! } else { //cout << "D" << flush; @@ -318,12 +314,14 @@ void FGAIGAVFRTraffic::FlyPlane(double dt) { slope = 0.0; ConditionalTransmit(30); if(_e45) { - _hdg = (patternDirection == 1 ? rwy.hdg - 135.0 : rwy.hdg + 135.0); + SetTrack(patternDirection == 1 ? rwy.hdg - 135.0 : rwy.hdg + 135.0); } else { - _hdg = (patternDirection == 1 ? rwy.hdg + 90.0 : rwy.hdg - 90.0); + SetTrack(patternDirection == 1 ? rwy.hdg + 90.0 : rwy.hdg - 90.0); } - if(_hdg < 0.0) _hdg += 360.0; + //if(_hdg < 0.0) _hdg += 360.0; _entering = true; + } else { + SetTrack(GetHeadingFromTo(_pos, _wp)); } } } @@ -332,8 +330,8 @@ void FGAIGAVFRTraffic::FlyPlane(double dt) { slope = 0.0; } // FIXME - lots of hackery in the next six lines!!!! - double track = _hdg; - double crab = 0.0; + //double track = _hdg; + double crab = 0.0; // This is a placeholder for when we take wind into account. _hdg = track + crab; double vel = _cruise_ias; double dist = vel * 0.514444 * dt; @@ -410,7 +408,6 @@ int FGAIGAVFRTraffic::GetQuadrangleAltitude(int dir, int des_alt) { // 3/ At and appropriate point on non-circuit side of rwy at take-off end for perpendicular entry to circuit overflying end-of-rwy. Point3D FGAIGAVFRTraffic::GetPatternApproachPos() { //cout << "\n\n"; - //cout << "PPPPPPPPPPPPPPPPPPPPPPPppppppppppppppp\n"; //cout << "Calculating pattern approach pos for " << plane.callsign << '\n'; Point3D orthopos = ortho.ConvertToLocal(_pos); Point3D tmp; diff --git a/src/ATC/AILocalTraffic.cxx b/src/ATC/AILocalTraffic.cxx index 0f71a8369..99a8aae8f 100644 --- a/src/ATC/AILocalTraffic.cxx +++ b/src/ATC/AILocalTraffic.cxx @@ -164,6 +164,10 @@ void FGAILocalTraffic::GetRwyDetails(string id) { //cout << "GetRwyDetails called" << endl; rwy.rwyID = tower->GetActiveRunway(); + //cout << "id = " << id << '\n'; + //cout << "Returned id is " << tower->get_ident() << '\n'; + //cout << "Returned name is " << tower->get_name() << '\n'; + //cout << "rwy.rwyID = " << rwy.rwyID << '\n'; // Now we need to get the threshold position and rwy heading @@ -201,7 +205,7 @@ void FGAILocalTraffic::GetRwyDetails(string id) { rwy.end1ortho = ortho.ConvertToLocal(rwy.threshold_pos); // should come out as zero rwy.end2ortho = ortho.ConvertToLocal(takeoff_end); } else { - SG_LOG(SG_ATC, SG_ALERT, "Help - can't get good runway in FGAILocalTraffic!!\n"); + SG_LOG(SG_ATC, SG_ALERT, "Help - can't get good runway at airport " << id << " in FGAILocalTraffic!!"); } } @@ -328,7 +332,7 @@ bool FGAILocalTraffic::Init(const string& callsign, string ICAO, OperatingState leg = DOWNWIND; elevInitGood = false; inAir = true; - track = rwy.hdg - (180 * patternDirection); //should tend to bring track back into the 0->360 range + SetTrack(rwy.hdg - (180 * patternDirection)); slope = 0.0; _pitch = 0.0; _roll = 0.0; @@ -383,7 +387,7 @@ void FGAILocalTraffic::DownwindEntry() { leg = DOWNWIND; elevInitGood = false; inAir = true; - track = rwy.hdg - (180 * patternDirection); //should tend to bring track back into the 0->360 range + SetTrack(rwy.hdg - (180 * patternDirection)); slope = 0.0; _pitch = 0.0; _roll = 0.0; @@ -399,7 +403,7 @@ void FGAILocalTraffic::StraightInEntry(bool des) { leg = FINAL; elevInitGood = false; inAir = true; - track = rwy.hdg; + SetTrack(rwy.hdg); transmitted = true; // TODO - fix this hack. // TODO - set up the next 5 properly for a descent! slope = -5.5; @@ -702,7 +706,7 @@ void FGAILocalTraffic::Update(double dt) { //fgSetDouble("/AI/Local1/ortho-y", (ortho.ConvertToLocal(_pos)).y()); //fgSetDouble("/AI/Local1/elev", _pos.elev() * SG_METER_TO_FEET); - // And finally, call parent for transmission rendering + // And finally, call parent. FGAIPlane::Update(dt); } @@ -800,6 +804,7 @@ void FGAILocalTraffic::FlyTrafficPattern(double dt) { IAS = vel + (cos((_hdg - wind_from) * DCL_DEGREES_TO_RADIANS) * wind_speed); if(IAS >= 70) { leg = CLIMBOUT; + SetTrack(rwy.hdg); // Hands over control of turning to AIPlane _pitch = 10.0; IAS = best_rate_of_climb_speed; //slope = 7.0; @@ -808,7 +813,6 @@ void FGAILocalTraffic::FlyTrafficPattern(double dt) { } break; case CLIMBOUT: - track = rwy.hdg; // Turn to crosswind if above 700ft AND if other traffic allows // (decided in FGTower and accessed through GetCrosswindConstraint(...)). // According to AIM, traffic should climb to within 300ft of pattern altitude before commencing crosswind turn. @@ -843,16 +847,13 @@ void FGAILocalTraffic::FlyTrafficPattern(double dt) { } break; case TURN1: - track += (360.0 / turn_time) * dt * patternDirection; - Bank(25.0 * patternDirection); + SetTrack(rwy.hdg + (90.0 * patternDirection)); if((track < (rwy.hdg - 89.0)) || (track > (rwy.hdg + 89.0))) { leg = CROSSWIND; } break; case CROSSWIND: goAround = false; - LevelWings(); - track = rwy.hdg + (90.0 * patternDirection); if((_pos.elev() - rwy.threshold_pos.elev()) * SG_METER_TO_FEET > 1000) { slope = 0.0; _pitch = 0.0; @@ -873,8 +874,7 @@ void FGAILocalTraffic::FlyTrafficPattern(double dt) { } break; case TURN2: - track += (360.0 / turn_time) * dt * patternDirection; - Bank(25.0 * patternDirection); + SetTrack(rwy.hdg - (180 * patternDirection)); // just in case we didn't make height on crosswind if((_pos.elev() - rwy.threshold_pos.elev()) * SG_METER_TO_FEET > 1000) { slope = 0.0; @@ -884,12 +884,9 @@ void FGAILocalTraffic::FlyTrafficPattern(double dt) { if((track < (rwy.hdg - 179.0)) || (track > (rwy.hdg + 179.0))) { leg = DOWNWIND; transmitted = false; - //roll = 0.0; } break; case DOWNWIND: - LevelWings(); - track = rwy.hdg - (180 * patternDirection); //should tend to bring track back into the 0->360 range // just in case we didn't make height on crosswind if(((_pos.elev() - rwy.threshold_pos.elev()) * SG_METER_TO_FEET > 995) && ((_pos.elev() - rwy.threshold_pos.elev()) * SG_METER_TO_FEET < 1015)) { slope = 0.0; @@ -947,14 +944,12 @@ void FGAILocalTraffic::FlyTrafficPattern(double dt) { } break; case TURN3: - track += (360.0 / turn_time) * dt * patternDirection; - Bank(25.0 * patternDirection); + SetTrack(rwy.hdg - (90 * patternDirection)); if(fabs(rwy.hdg - track) < 91.0) { leg = BASE; } break; case BASE: - LevelWings(); if(!transmitted) { // Base report should only be transmitted at uncontrolled airport - not towered. if(!_controlled) TransmitPatternPositionReport(); @@ -977,8 +972,6 @@ void FGAILocalTraffic::FlyTrafficPattern(double dt) { IAS = 70.0; } - track = rwy.hdg - (90 * patternDirection); - // Try and arrange to turn nicely onto final turn_circumference = IAS * 0.514444 * turn_time; //Hmmm - this is an interesting one - ground vs airspeed in relation to turn radius @@ -991,8 +984,7 @@ void FGAILocalTraffic::FlyTrafficPattern(double dt) { } break; case TURN4: - track += (360.0 / turn_time) * dt * patternDirection; - Bank(25.0 * patternDirection); + SetTrack(rwy.hdg); if(fabs(track - rwy.hdg) < 0.6) { leg = FINAL; vel = nominal_final_speed; @@ -1062,7 +1054,7 @@ void FGAILocalTraffic::FlyTrafficPattern(double dt) { } } // Try and track the extended centreline - track = rwy.hdg - (0.2 * orthopos.x()); + SetTrack(rwy.hdg - (0.2 * orthopos.x())); //cout << "orthopos.x() = " << orthopos.x() << " hdg = " << hdg << '\n'; if(_pos.elev() < (rwy.threshold_pos.elev()+20.0+wheelOffset)) { DoGroundElev(); // Need to call it here expicitly on final since it's only called @@ -1077,6 +1069,8 @@ void FGAILocalTraffic::FlyTrafficPattern(double dt) { _pitch = 0.0; leg = LANDING_ROLL; inAir = false; + LevelWings(); + ClearTrack(); // Take over explicit track handling since AIPlane currently always banks when changing course } } // else need a fallback position based on arpt elev in case ground elev determination fails? } else { diff --git a/src/ATC/AIPlane.cxx b/src/ATC/AIPlane.cxx index 23ebeda2e..91434828d 100644 --- a/src/ATC/AIPlane.cxx +++ b/src/ATC/AIPlane.cxx @@ -44,6 +44,10 @@ FGAIPlane::FGAIPlane() { playing = false; voiceOK = false; vPtr = NULL; + _tgtTrack = 0.0; + _trackSet = false; + _tgtRoll = 0.0; + _rollSuspended = false; } FGAIPlane::~FGAIPlane() { @@ -113,20 +117,27 @@ void FGAIPlane::Update(double dt) { } _counter += dt; } -} - -void FGAIPlane::Bank(double angle) { - // This *should* bank us smoothly to any angle - if(fabs(_roll - angle) > 0.6) { - _roll -= ((_roll - angle)/fabs(_roll - angle)); + + // Fly the plane if necessary + if(_trackSet) { + while((_tgtTrack - track) > 180.0) track += 360.0; + while((track - _tgtTrack) > 180.0) track -= 360.0; + double turn_time = 60.0; + track += (360.0 / turn_time) * dt * (_tgtTrack > track ? 1.0 : -1.0); + Bank(25.0 * (_tgtTrack > track ? 1.0 : -1.0)); + if(fabs(track - _tgtTrack) < 2.0) { // TODO - might need to optimise the delta there - it's on the large (safe) side atm. + track = _tgtTrack; + LevelWings(); + } } -} - -// Duplication of Bank(0.0) really - should I cut this? -void FGAIPlane::LevelWings(void) { - // bring the plane back to level smoothly (this should work to come out of either bank) - if(fabs(_roll) > 0.6) { - _roll -= (_roll/fabs(_roll)); + + if(!_rollSuspended) { + if(fabs(_roll - _tgtRoll) > 0.6) { + // This *should* bank us smoothly to any angle + _roll -= ((_roll - _tgtRoll)/fabs(_roll - _tgtRoll)); + } else { + _roll = _tgtRoll; + } } } diff --git a/src/ATC/AIPlane.hxx b/src/ATC/AIPlane.hxx index e6da8ded4..466807ba4 100644 --- a/src/ATC/AIPlane.hxx +++ b/src/ATC/AIPlane.hxx @@ -120,9 +120,12 @@ protected: // Transmit regardless of other dialog on the channel eg emergency void ImmediateTransmit(int callback_code = 0); + + inline void SetTrack(double t) { _tgtTrack = t; _trackSet = true; } + inline void ClearTrack() { _trackSet = false; } - void Bank(double angle); - void LevelWings(void); + inline void Bank(double r) { _tgtRoll = r; } + inline void LevelWings(void) { _tgtRoll = 0.0; } virtual void ProcessCallback(int code); @@ -153,6 +156,12 @@ private: bool playing; // Indicates a message in progress bool voiceOK; // Flag - true if at least one voice has loaded OK FGATCVoice* vPtr; + + // Navigation + double _tgtTrack; // Track to be following if _trackSet is true + bool _trackSet; // Set true if tgtTrack is to be followed + double _tgtRoll; + bool _rollSuspended; // Set true when a derived class has suspended AIPlane's roll control }; #endif // _FG_AI_PLANE_HXX