1
0
Fork 0

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.

This commit is contained in:
daveluff 2004-03-02 10:43:16 +00:00
parent cb8db7725a
commit 9773ba5542
4 changed files with 67 additions and 56 deletions

View file

@ -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;

View file

@ -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 {

View file

@ -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;
}
}
}

View file

@ -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