AI plane should go around instead of landing on user if user dawdles on runway now
This commit is contained in:
parent
cd08f83aa5
commit
0adae696aa
4 changed files with 177 additions and 40 deletions
|
@ -85,6 +85,8 @@ FGAILocalTraffic::FGAILocalTraffic() {
|
||||||
|
|
||||||
descending = false;
|
descending = false;
|
||||||
targetDescentRate = 0.0;
|
targetDescentRate = 0.0;
|
||||||
|
goAround = false;
|
||||||
|
goAroundCalled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
FGAILocalTraffic::~FGAILocalTraffic() {
|
FGAILocalTraffic::~FGAILocalTraffic() {
|
||||||
|
@ -189,6 +191,9 @@ bool FGAILocalTraffic::Init(string ICAO, OperatingState initialState, PatternLeg
|
||||||
} else {
|
} else {
|
||||||
//cout << "Unable to find airport details in FGAILocalTraffic::Init()\n";
|
//cout << "Unable to find airport details in FGAILocalTraffic::Init()\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get the active runway details (and copy them into rwy)
|
||||||
|
GetRwyDetails();
|
||||||
|
|
||||||
// Get the airport elevation
|
// Get the airport elevation
|
||||||
aptElev = dclGetAirportElev(airportID.c_str()) * SG_FEET_TO_METER;
|
aptElev = dclGetAirportElev(airportID.c_str()) * SG_FEET_TO_METER;
|
||||||
|
@ -233,29 +238,12 @@ bool FGAILocalTraffic::Init(string ICAO, OperatingState initialState, PatternLeg
|
||||||
// since we've got the implementation for this case already.
|
// since we've got the implementation for this case already.
|
||||||
// TODO - implement proper generic in_pattern startup.
|
// TODO - implement proper generic in_pattern startup.
|
||||||
|
|
||||||
|
// 18/10/03 - adding the ability to start on downwind (mainly to speed testing of the go-around code!!)
|
||||||
|
|
||||||
|
//cout << "Starting in pattern...\n";
|
||||||
|
|
||||||
tuned_station = tower;
|
tuned_station = tower;
|
||||||
|
|
||||||
// Get the active runway details (and copy them into rwy)
|
|
||||||
GetRwyDetails();
|
|
||||||
|
|
||||||
// Initial position on threshold for now
|
|
||||||
pos.setlat(rwy.threshold_pos.lat());
|
|
||||||
pos.setlon(rwy.threshold_pos.lon());
|
|
||||||
pos.setelev(rwy.threshold_pos.elev());
|
|
||||||
hdg = rwy.hdg;
|
|
||||||
|
|
||||||
// Now we've set the position we can do the ground elev
|
|
||||||
// This might not always be necessary if we implement in-air start
|
|
||||||
elevInitGood = false;
|
|
||||||
inAir = false;
|
|
||||||
DoGroundElev();
|
|
||||||
|
|
||||||
pitch = 0.0;
|
|
||||||
roll = 0.0;
|
|
||||||
leg = TAKEOFF_ROLL;
|
|
||||||
vel = 0.0;
|
|
||||||
slope = 0.0;
|
|
||||||
|
|
||||||
circuitsToFly = 0; // ie just fly this circuit and then stop
|
circuitsToFly = 0; // ie just fly this circuit and then stop
|
||||||
touchAndGo = false;
|
touchAndGo = false;
|
||||||
// FIXME TODO - pattern direction is still hardwired
|
// FIXME TODO - pattern direction is still hardwired
|
||||||
|
@ -264,7 +252,42 @@ bool FGAILocalTraffic::Init(string ICAO, OperatingState initialState, PatternLeg
|
||||||
if(rwy.rwyID.size() == 3) {
|
if(rwy.rwyID.size() == 3) {
|
||||||
patternDirection = (rwy.rwyID.substr(2,1) == "R" ? 1 : -1);
|
patternDirection = (rwy.rwyID.substr(2,1) == "R" ? 1 : -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(initialLeg == DOWNWIND) {
|
||||||
|
pos = ortho.ConvertFromLocal(Point3D(1000*patternDirection, 800, 0.0));
|
||||||
|
pos.setelev(rwy.threshold_pos.elev() + 1000 * SG_FEET_TO_METER);
|
||||||
|
hdg = rwy.hdg + 180.0;
|
||||||
|
leg = DOWNWIND;
|
||||||
|
elevInitGood = false;
|
||||||
|
inAir = true;
|
||||||
|
track = rwy.hdg - (180 * patternDirection); //should tend to bring track back into the 0->360 range
|
||||||
|
slope = 0.0;
|
||||||
|
pitch = 0.0;
|
||||||
|
roll = 0.0;
|
||||||
|
IAS = 90.0;
|
||||||
|
descending = false;
|
||||||
|
aip.setVisible(true);
|
||||||
|
tower->RegisterAIPlane(plane, this, CIRCUIT, DOWNWIND);
|
||||||
|
} else {
|
||||||
|
// Default to initial position on threshold for now
|
||||||
|
pos.setlat(rwy.threshold_pos.lat());
|
||||||
|
pos.setlon(rwy.threshold_pos.lon());
|
||||||
|
pos.setelev(rwy.threshold_pos.elev());
|
||||||
|
hdg = rwy.hdg;
|
||||||
|
|
||||||
|
// Now we've set the position we can do the ground elev
|
||||||
|
// This might not always be necessary if we implement in-air start
|
||||||
|
elevInitGood = false;
|
||||||
|
inAir = false;
|
||||||
|
DoGroundElev();
|
||||||
|
|
||||||
|
pitch = 0.0;
|
||||||
|
roll = 0.0;
|
||||||
|
leg = TAKEOFF_ROLL;
|
||||||
|
vel = 0.0;
|
||||||
|
slope = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
operatingState = IN_PATTERN;
|
operatingState = IN_PATTERN;
|
||||||
|
|
||||||
Transform();
|
Transform();
|
||||||
|
@ -370,15 +393,17 @@ void FGAILocalTraffic::Update(double dt) {
|
||||||
switch(operatingState) {
|
switch(operatingState) {
|
||||||
case IN_PATTERN:
|
case IN_PATTERN:
|
||||||
//cout << "In IN_PATTERN\n";
|
//cout << "In IN_PATTERN\n";
|
||||||
if(!inAir) DoGroundElev();
|
if(!inAir) {
|
||||||
if(!elevInitGood) {
|
DoGroundElev();
|
||||||
if(aip.getSGLocation()->get_cur_elev_m() > -9990.0) {
|
if(!elevInitGood) {
|
||||||
pos.setelev(aip.getSGLocation()->get_cur_elev_m() + wheelOffset);
|
if(aip.getSGLocation()->get_cur_elev_m() > -9990.0) {
|
||||||
//cout << "TAKEOFF_ROLL, POS = " << pos.lon() << ", " << pos.lat() << ", " << pos.elev() << '\n';
|
pos.setelev(aip.getSGLocation()->get_cur_elev_m() + wheelOffset);
|
||||||
//Transform();
|
//cout << "TAKEOFF_ROLL, POS = " << pos.lon() << ", " << pos.lat() << ", " << pos.elev() << '\n';
|
||||||
aip.setVisible(true);
|
//Transform();
|
||||||
//cout << "Making plane visible!\n";
|
aip.setVisible(true);
|
||||||
elevInitGood = true;
|
//cout << "Making plane visible!\n";
|
||||||
|
elevInitGood = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FlyTrafficPattern(dt);
|
FlyTrafficPattern(dt);
|
||||||
|
@ -451,7 +476,7 @@ void FGAILocalTraffic::Update(double dt) {
|
||||||
if(circuitsToFly) {
|
if(circuitsToFly) {
|
||||||
if((taxiRequestPending) && (taxiRequestCleared)) {
|
if((taxiRequestPending) && (taxiRequestCleared)) {
|
||||||
//cout << "&" << flush;
|
//cout << "&" << flush;
|
||||||
// Get the active runway details (and copy them into rwy)
|
// Get the active runway details (in case they've changed since init)
|
||||||
GetRwyDetails();
|
GetRwyDetails();
|
||||||
|
|
||||||
// Get the takeoff node for the active runway, get a path to it and start taxiing
|
// Get the takeoff node for the active runway, get a path to it and start taxiing
|
||||||
|
@ -544,11 +569,11 @@ void FGAILocalTraffic::RegisterTransmission(int code) {
|
||||||
clearedToTakeOff = true;
|
clearedToTakeOff = true;
|
||||||
SG_LOG(SG_ATC, SG_INFO, "AI local traffic " << plane.callsign << " cleared to take-off...");
|
SG_LOG(SG_ATC, SG_INFO, "AI local traffic " << plane.callsign << " cleared to take-off...");
|
||||||
break;
|
break;
|
||||||
// case 13: // Go around!
|
case 13: // Go around!
|
||||||
// responseCounter = 0;
|
responseCounter = 0;
|
||||||
// goAround = true;
|
goAround = true;
|
||||||
// SG_LOG(SG_ATC, SG_INFO, "AI local traffic " << plane.callsign << " told to go-around!!");
|
SG_LOG(SG_ATC, SG_INFO, "AI local traffic " << plane.callsign << " told to go-around!!");
|
||||||
// break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -612,9 +637,11 @@ void FGAILocalTraffic::FlyTrafficPattern(double dt) {
|
||||||
break;
|
break;
|
||||||
case CLIMBOUT:
|
case CLIMBOUT:
|
||||||
track = rwy.hdg;
|
track = rwy.hdg;
|
||||||
// Turn to crosswind if above 600ft AND if other traffic allows
|
// Turn to crosswind if above 700ft AND if other traffic allows
|
||||||
// (decided in FGTower and accessed through GetCrosswindConstraint(...)).
|
// (decided in FGTower and accessed through GetCrosswindConstraint(...)).
|
||||||
if((pos.elev() - rwy.threshold_pos.elev()) * SG_METER_TO_FEET > 600) {
|
// According to AIM, traffic should climb to within 300ft of pattern altitude before commencing crosswind turn.
|
||||||
|
// TODO - At hot 'n high airports this may be 500ft AGL though - need to make this a variable.
|
||||||
|
if((pos.elev() - rwy.threshold_pos.elev()) * SG_METER_TO_FEET > 700) {
|
||||||
double cc = 0.0;
|
double cc = 0.0;
|
||||||
if(tower->GetCrosswindConstraint(cc)) {
|
if(tower->GetCrosswindConstraint(cc)) {
|
||||||
if(orthopos.y() > cc) {
|
if(orthopos.y() > cc) {
|
||||||
|
@ -622,6 +649,7 @@ void FGAILocalTraffic::FlyTrafficPattern(double dt) {
|
||||||
leg = TURN1;
|
leg = TURN1;
|
||||||
}
|
}
|
||||||
} else if(orthopos.y() > 1500.0) { // Added this constraint as a hack to prevent turning too early when going around.
|
} else if(orthopos.y() > 1500.0) { // Added this constraint as a hack to prevent turning too early when going around.
|
||||||
|
// TODO - We should be doing it as a distance from takeoff end, not theshold end though.
|
||||||
cout << "Turning to crosswind, distance from threshold = " << orthopos.y() << '\n';
|
cout << "Turning to crosswind, distance from threshold = " << orthopos.y() << '\n';
|
||||||
leg = TURN1;
|
leg = TURN1;
|
||||||
}
|
}
|
||||||
|
@ -633,6 +661,14 @@ void FGAILocalTraffic::FlyTrafficPattern(double dt) {
|
||||||
pitch = 0.0;
|
pitch = 0.0;
|
||||||
IAS = 80.0; // FIXME - use smooth transistion to new speed and attitude.
|
IAS = 80.0; // FIXME - use smooth transistion to new speed and attitude.
|
||||||
}
|
}
|
||||||
|
if(goAround && !goAroundCalled) {
|
||||||
|
if(responseCounter > 5.5) {
|
||||||
|
pending_transmission = plane.callsign;
|
||||||
|
pending_transmission += " going around";
|
||||||
|
Transmit();
|
||||||
|
goAroundCalled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case TURN1:
|
case TURN1:
|
||||||
track += (360.0 / turn_time) * dt * patternDirection;
|
track += (360.0 / turn_time) * dt * patternDirection;
|
||||||
|
@ -642,6 +678,7 @@ void FGAILocalTraffic::FlyTrafficPattern(double dt) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CROSSWIND:
|
case CROSSWIND:
|
||||||
|
goAround = false;
|
||||||
LevelWings();
|
LevelWings();
|
||||||
track = rwy.hdg + (90.0 * patternDirection);
|
track = rwy.hdg + (90.0 * patternDirection);
|
||||||
if((pos.elev() - rwy.threshold_pos.elev()) * SG_METER_TO_FEET > 1000) {
|
if((pos.elev() - rwy.threshold_pos.elev()) * SG_METER_TO_FEET > 1000) {
|
||||||
|
@ -783,6 +820,15 @@ void FGAILocalTraffic::FlyTrafficPattern(double dt) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case FINAL:
|
case FINAL:
|
||||||
|
if(goAround && responseCounter > 2.0) {
|
||||||
|
leg = CLIMBOUT;
|
||||||
|
pitch = 8.0;
|
||||||
|
IAS = best_rate_of_climb_speed;
|
||||||
|
slope = 5.0; // A bit less steep than the initial climbout.
|
||||||
|
inAir = true;
|
||||||
|
goAroundCalled = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
LevelWings();
|
LevelWings();
|
||||||
if(!transmitted) {
|
if(!transmitted) {
|
||||||
TransmitPatternPositionReport();
|
TransmitPatternPositionReport();
|
||||||
|
|
|
@ -176,6 +176,8 @@ private:
|
||||||
bool clearedToLineUp;
|
bool clearedToLineUp;
|
||||||
bool clearedToTakeOff;
|
bool clearedToTakeOff;
|
||||||
bool liningUp; // Set true when the turn onto the runway heading is commenced when taxiing out
|
bool liningUp; // Set true when the turn onto the runway heading is commenced when taxiing out
|
||||||
|
bool goAround; // Set true if need to go-around
|
||||||
|
bool goAroundCalled; // Set true during go-around only after we have called our go-around on the radio
|
||||||
bool contactTower; // we have been told to contact tower
|
bool contactTower; // we have been told to contact tower
|
||||||
bool contactGround; // we have been told to contact ground
|
bool contactGround; // we have been told to contact ground
|
||||||
bool changeFreq; // true when we need to change frequency
|
bool changeFreq; // true when we need to change frequency
|
||||||
|
|
|
@ -44,6 +44,7 @@ longFinalReported(false),
|
||||||
longFinalAcknowledged(false),
|
longFinalAcknowledged(false),
|
||||||
finalReported(false),
|
finalReported(false),
|
||||||
finalAcknowledged(false),
|
finalAcknowledged(false),
|
||||||
|
instructedToGoAround(false),
|
||||||
onRwy(false),
|
onRwy(false),
|
||||||
nextOnRwy(false),
|
nextOnRwy(false),
|
||||||
opType(TTT_UNKNOWN),
|
opType(TTT_UNKNOWN),
|
||||||
|
@ -64,6 +65,7 @@ longFinalReported(false),
|
||||||
longFinalAcknowledged(false),
|
longFinalAcknowledged(false),
|
||||||
finalReported(false),
|
finalReported(false),
|
||||||
finalAcknowledged(false),
|
finalAcknowledged(false),
|
||||||
|
instructedToGoAround(false),
|
||||||
onRwy(false),
|
onRwy(false),
|
||||||
nextOnRwy(false),
|
nextOnRwy(false),
|
||||||
opType(TTT_UNKNOWN),
|
opType(TTT_UNKNOWN),
|
||||||
|
@ -84,6 +86,7 @@ longFinalReported(false),
|
||||||
longFinalAcknowledged(false),
|
longFinalAcknowledged(false),
|
||||||
finalReported(false),
|
finalReported(false),
|
||||||
finalAcknowledged(false),
|
finalAcknowledged(false),
|
||||||
|
instructedToGoAround(false),
|
||||||
onRwy(false),
|
onRwy(false),
|
||||||
nextOnRwy(false),
|
nextOnRwy(false),
|
||||||
opType(TTT_UNKNOWN),
|
opType(TTT_UNKNOWN),
|
||||||
|
@ -105,6 +108,7 @@ longFinalReported(false),
|
||||||
longFinalAcknowledged(false),
|
longFinalAcknowledged(false),
|
||||||
finalReported(false),
|
finalReported(false),
|
||||||
finalAcknowledged(false),
|
finalAcknowledged(false),
|
||||||
|
instructedToGoAround(false),
|
||||||
onRwy(false),
|
onRwy(false),
|
||||||
nextOnRwy(false),
|
nextOnRwy(false),
|
||||||
opType(TTT_UNKNOWN),
|
opType(TTT_UNKNOWN),
|
||||||
|
@ -273,6 +277,7 @@ void FGTower::Update(double dt) {
|
||||||
// cout << " dt = " << dt << " timeSinceLastDeparture = " << timeSinceLastDeparture << '\n';
|
// cout << " dt = " << dt << " timeSinceLastDeparture = " << timeSinceLastDeparture << '\n';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//cout << ident << " respond = " << respond << " responseReqd = " << responseReqd << '\n';
|
||||||
if(respond) {
|
if(respond) {
|
||||||
if(!responseReqd) SG_LOG(SG_ATC, SG_ALERT, "ERROR - respond is true and responseReqd is false in FGTower::Update(...)");
|
if(!responseReqd) SG_LOG(SG_ATC, SG_ALERT, "ERROR - respond is true and responseReqd is false in FGTower::Update(...)");
|
||||||
Respond();
|
Respond();
|
||||||
|
@ -411,6 +416,7 @@ void FGTower::Respond() {
|
||||||
}
|
}
|
||||||
t->holdShortReported = false;
|
t->holdShortReported = false;
|
||||||
} else if(t->finalReported && !(t->finalAcknowledged)) {
|
} else if(t->finalReported && !(t->finalAcknowledged)) {
|
||||||
|
bool disp = true;
|
||||||
string trns = t->plane.callsign;
|
string trns = t->plane.callsign;
|
||||||
if(t->nextOnRwy && !rwyOccupied) {
|
if(t->nextOnRwy && !rwyOccupied) {
|
||||||
if(t->landingType == FULL_STOP) {
|
if(t->landingType == FULL_STOP) {
|
||||||
|
@ -420,11 +426,15 @@ void FGTower::Respond() {
|
||||||
}
|
}
|
||||||
// TODO - add winds
|
// TODO - add winds
|
||||||
t->clearedToLand = true;
|
t->clearedToLand = true;
|
||||||
|
} else if(t->eta < 20) {
|
||||||
|
// Do nothing - we'll be telling it to go around in less than 10 seconds if the
|
||||||
|
// runway doesn't clear so no point in calling "continue approach".
|
||||||
|
disp = false;
|
||||||
} else {
|
} else {
|
||||||
trns += " continue approach";
|
trns += " continue approach";
|
||||||
t->clearedToLand = false;
|
t->clearedToLand = false;
|
||||||
}
|
}
|
||||||
if(display) {
|
if(display && disp) {
|
||||||
globals->get_ATC_display()->RegisterSingleMessage(trns, 0);
|
globals->get_ATC_display()->RegisterSingleMessage(trns, 0);
|
||||||
}
|
}
|
||||||
t->finalAcknowledged = true;
|
t->finalAcknowledged = true;
|
||||||
|
@ -714,6 +724,7 @@ void FGTower::CheckCircuitList(double dt) {
|
||||||
case CROSSWIND:
|
case CROSSWIND:
|
||||||
crosswind_leg_pos = tortho.y();
|
crosswind_leg_pos = tortho.y();
|
||||||
//cout << "crosswind_leg_pos = " << crosswind_leg_pos << '\n';
|
//cout << "crosswind_leg_pos = " << crosswind_leg_pos << '\n';
|
||||||
|
t->instructedToGoAround = false;
|
||||||
break;
|
break;
|
||||||
case TURN1:
|
case TURN1:
|
||||||
// Fall through to climbout
|
// Fall through to climbout
|
||||||
|
@ -735,6 +746,22 @@ void FGTower::CheckCircuitList(double dt) {
|
||||||
|
|
||||||
if(t->leg == FINAL) {
|
if(t->leg == FINAL) {
|
||||||
if(t->landingType == FULL_STOP) t->opType = INBOUND;
|
if(t->landingType == FULL_STOP) t->opType = INBOUND;
|
||||||
|
if(t->eta < 12 && rwyList.size() && !(t->instructedToGoAround)) {
|
||||||
|
// TODO - need to make this more sophisticated
|
||||||
|
// eg. is the plane accelerating down the runway taking off [OK],
|
||||||
|
// or stationary near the start [V. BAD!!].
|
||||||
|
// For now this should stop the AI plane landing on top of the user.
|
||||||
|
string trns = t->plane.callsign;
|
||||||
|
trns += " GO AROUND TRAFFIC ON RUNWAY I REPEAT GO AROUND";
|
||||||
|
if(display) {
|
||||||
|
globals->get_ATC_display()->RegisterSingleMessage(trns, 0);
|
||||||
|
}
|
||||||
|
t->instructedToGoAround = true;
|
||||||
|
if(t->planePtr) {
|
||||||
|
cout << "Registering Go-around transmission with AI plane\n";
|
||||||
|
t->planePtr->RegisterTransmission(13);
|
||||||
|
}
|
||||||
|
}
|
||||||
} else if(t->leg == LANDING_ROLL) {
|
} else if(t->leg == LANDING_ROLL) {
|
||||||
rwyList.push_front(t);
|
rwyList.push_front(t);
|
||||||
// TODO - if(!clearedToLand) shout something!!
|
// TODO - if(!clearedToLand) shout something!!
|
||||||
|
@ -1053,6 +1080,37 @@ bool FGTower::AddToTrafficList(TowerPlaneRec* t, bool holding) {
|
||||||
return(holding ? firstTime : conflict);
|
return(holding ? firstTime : conflict);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add a tower plane rec with ETA to the circuit list in the correct position ETA-wise
|
||||||
|
// Returns true if this might cause a separation conflict (based on ETA) with other traffic, false otherwise.
|
||||||
|
bool FGTower::AddToCircuitList(TowerPlaneRec* t) {
|
||||||
|
//cout << "ADD: " << circuitList.size();
|
||||||
|
//cout << "AddToCircuitList called, currently size = " << circuitList.size() << endl;
|
||||||
|
double separation_time = 60.0; // seconds - this is currently a guess for light plane separation, and includes a few seconds for a holding plane to taxi onto the rwy.
|
||||||
|
bool conflict = false;
|
||||||
|
tower_plane_rec_list_iterator twrItr;
|
||||||
|
for(twrItr = circuitList.begin(); twrItr != circuitList.end(); twrItr++) {
|
||||||
|
TowerPlaneRec* tpr = *twrItr;
|
||||||
|
|
||||||
|
if(t->eta < tpr->eta) {
|
||||||
|
// Ugg - this one's tricky.
|
||||||
|
// It depends on what the two planes are doing and whether there's a conflict what we do.
|
||||||
|
if(tpr->eta - t->eta > separation_time) { // No probs, plane 2 can squeeze in before plane 1 with no apparent conflict
|
||||||
|
circuitList.insert(twrItr, t);
|
||||||
|
} else { // Ooops - this ones tricky - we have a potential conflict!
|
||||||
|
conflict = true;
|
||||||
|
// HACK - just add anyway for now and flag conflict.
|
||||||
|
circuitList.insert(twrItr, t);
|
||||||
|
}
|
||||||
|
//cout << "\tC\t" << circuitList.size() << '\n';
|
||||||
|
return(conflict);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// If we get here we must be at the end of the list, or maybe the list is empty.
|
||||||
|
circuitList.push_back(t); // TODO - check the separation with the preceding plane for the conflict flag.
|
||||||
|
//cout << "\tE\t" << circuitList.size() << endl;
|
||||||
|
return(conflict);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Calculate the eta of a plane to the threshold.
|
// Calculate the eta of a plane to the threshold.
|
||||||
// For ground traffic this is the fastest they can get there.
|
// For ground traffic this is the fastest they can get there.
|
||||||
|
@ -1267,8 +1325,10 @@ void FGTower::ContactAtHoldShort(PlaneRec plane, FGAIPlane* requestee, tower_tra
|
||||||
t->clearedToLineUp = false;
|
t->clearedToLineUp = false;
|
||||||
t->clearedToTakeOff = false;
|
t->clearedToTakeOff = false;
|
||||||
t->opType = operation;
|
t->opType = operation;
|
||||||
|
t->pos = requestee->GetPos();
|
||||||
|
|
||||||
//cout << "Hold Short reported by " << plane.callsign << '\n';
|
//cout << "Hold Short reported by " << plane.callsign << '\n';
|
||||||
|
SG_LOG(SG_ATC, SG_BULK, "Hold Short reported by " << plane.callsign);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
bool next = AddToTrafficList(t, true);
|
bool next = AddToTrafficList(t, true);
|
||||||
|
@ -1288,6 +1348,28 @@ void FGTower::ContactAtHoldShort(PlaneRec plane, FGAIPlane* requestee, tower_tra
|
||||||
responseReqd = true;
|
responseReqd = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Register the presence of an AI plane at a point where contact would already have been made in real life
|
||||||
|
// CAUTION - currently it is assumed that this plane's callsign is unique - it is up to AIMgr to generate unique callsigns.
|
||||||
|
void FGTower::RegisterAIPlane(PlaneRec plane, FGAIPlane* ai, tower_traffic_type op, PatternLeg lg) {
|
||||||
|
// At the moment this is only going to be tested with inserting an AI plane on downwind
|
||||||
|
TowerPlaneRec* t = new TowerPlaneRec;
|
||||||
|
t->plane = plane;
|
||||||
|
t->planePtr = ai;
|
||||||
|
t->opType = op;
|
||||||
|
t->leg = lg;
|
||||||
|
t->pos = ai->GetPos();
|
||||||
|
|
||||||
|
CalcETA(t);
|
||||||
|
|
||||||
|
if(op == CIRCUIT && lg != LEG_UNKNOWN) {
|
||||||
|
AddToCircuitList(t);
|
||||||
|
} else {
|
||||||
|
// FLAG A WARNING
|
||||||
|
}
|
||||||
|
|
||||||
|
doThresholdUseOrder();
|
||||||
|
}
|
||||||
|
|
||||||
void FGTower::RequestLandingClearance(string ID) {
|
void FGTower::RequestLandingClearance(string ID) {
|
||||||
//cout << "Request Landing Clearance called...\n";
|
//cout << "Request Landing Clearance called...\n";
|
||||||
|
|
||||||
|
|
|
@ -82,6 +82,7 @@ public:
|
||||||
bool longFinalAcknowledged;
|
bool longFinalAcknowledged;
|
||||||
bool finalReported;
|
bool finalReported;
|
||||||
bool finalAcknowledged;
|
bool finalAcknowledged;
|
||||||
|
bool instructedToGoAround; // set true if told by tower to go around
|
||||||
bool onRwy; // is physically on the runway
|
bool onRwy; // is physically on the runway
|
||||||
bool nextOnRwy; // currently projected by tower to be the next on the runway
|
bool nextOnRwy; // currently projected by tower to be the next on the runway
|
||||||
|
|
||||||
|
@ -128,6 +129,10 @@ public:
|
||||||
// Contact tower when at a hold short for departure - for now we'll assume plane - maybe vehicles might want to cross runway eventually?
|
// Contact tower when at a hold short for departure - for now we'll assume plane - maybe vehicles might want to cross runway eventually?
|
||||||
void ContactAtHoldShort(PlaneRec plane, FGAIPlane* requestee, tower_traffic_type operation);
|
void ContactAtHoldShort(PlaneRec plane, FGAIPlane* requestee, tower_traffic_type operation);
|
||||||
|
|
||||||
|
// Register the presence of an AI plane at a point where contact would already have been made in real life
|
||||||
|
// CAUTION - currently it is assumed that this plane's callsign is unique - it is up to AIMgr to generate unique callsigns.
|
||||||
|
void RegisterAIPlane(PlaneRec plane, FGAIPlane* ai, tower_traffic_type op, PatternLeg lg = LEG_UNKNOWN);
|
||||||
|
|
||||||
// Public interface to the active runway - this will get more complex
|
// Public interface to the active runway - this will get more complex
|
||||||
// in the future and consider multi-runway use, airplane weight etc.
|
// in the future and consider multi-runway use, airplane weight etc.
|
||||||
inline string GetActiveRunway() { return activeRwy; }
|
inline string GetActiveRunway() { return activeRwy; }
|
||||||
|
@ -272,6 +277,8 @@ private:
|
||||||
// Add a tower plane rec with ETA to the traffic list in the correct position ETA-wise.
|
// Add a tower plane rec with ETA to the traffic list in the correct position ETA-wise.
|
||||||
// Returns true if this could cause a threshold ETA conflict with other traffic, false otherwise.
|
// Returns true if this could cause a threshold ETA conflict with other traffic, false otherwise.
|
||||||
bool AddToTrafficList(TowerPlaneRec* t, bool holding = false);
|
bool AddToTrafficList(TowerPlaneRec* t, bool holding = false);
|
||||||
|
|
||||||
|
bool AddToCircuitList(TowerPlaneRec* t);
|
||||||
|
|
||||||
// Ground can be separate or handled by tower in real life.
|
// Ground can be separate or handled by tower in real life.
|
||||||
// In the program we will always use a separate FGGround class, but we need to know
|
// In the program we will always use a separate FGGround class, but we need to know
|
||||||
|
|
Loading…
Add table
Reference in a new issue