AI/ATC
* Added Messages for Takeoff * Added Messages for Hold & Holdpatterns * More enums instead of Magic Numbers
This commit is contained in:
parent
11eca7825d
commit
3667e5de3c
16 changed files with 400 additions and 252 deletions
|
@ -69,10 +69,10 @@ FGAIAircraft::FGAIAircraft(FGAISchedule* ref) : /* HOT must be disabled for AI A
|
|||
groundOffset = 0;
|
||||
}
|
||||
|
||||
fp = 0;
|
||||
controller = 0;
|
||||
prevController = 0;
|
||||
towerController = 0;
|
||||
fp = nullptr;
|
||||
controller = nullptr;
|
||||
prevController = nullptr;
|
||||
towerController = nullptr;
|
||||
dt_count = 0;
|
||||
dt_elev_count = 0;
|
||||
use_perf_vs = true;
|
||||
|
@ -604,11 +604,13 @@ bool FGAIAircraft::loadNextLeg(double distance) {
|
|||
} else {
|
||||
double cruiseAlt = trafficRef->getCruiseAlt() * 100;
|
||||
|
||||
SG_LOG(SG_AI, SG_BULK, getCallSign() << "|Loading Leg " << leg+1);
|
||||
int nextLeg = determineNextLeg(leg);
|
||||
|
||||
SG_LOG(SG_AI, SG_BULK, getCallSign() << "|Loading Leg " << nextLeg);
|
||||
bool ok = fp->create (this,
|
||||
dep,
|
||||
arr,
|
||||
leg+1,
|
||||
nextLeg,
|
||||
cruiseAlt,
|
||||
trafficRef->getSpeed(),
|
||||
_getLatitude(),
|
||||
|
@ -721,10 +723,10 @@ void FGAIAircraft::announcePositionToController() {
|
|||
}
|
||||
break;
|
||||
case AILeg::APPROACH:
|
||||
if (trafficRef->getArrivalAirport()->getDynamics()) {
|
||||
controller = trafficRef->getArrivalAirport()->getDynamics()->getApproachController();
|
||||
}
|
||||
break;
|
||||
if (trafficRef->getArrivalAirport()->getDynamics()) {
|
||||
controller = trafficRef->getArrivalAirport()->getDynamics()->getApproachController();
|
||||
}
|
||||
break;
|
||||
case AILeg::PARKING_TAXI: // Taxiing for parking
|
||||
if (trafficRef->getArrivalAirport()->getDynamics()->getGroundController()->exists())
|
||||
controller = trafficRef->getArrivalAirport()->getDynamics()->getGroundController();
|
||||
|
@ -749,7 +751,7 @@ void FGAIAircraft::announcePositionToController() {
|
|||
}
|
||||
}
|
||||
|
||||
void FGAIAircraft::scheduleForATCTowerDepartureControl(int state) {
|
||||
void FGAIAircraft::scheduleForATCTowerDepartureControl() {
|
||||
if (!takeOffStatus) {
|
||||
int leg = fp->getLeg();
|
||||
if (trafficRef) {
|
||||
|
@ -765,7 +767,7 @@ void FGAIAircraft::scheduleForATCTowerDepartureControl(int state) {
|
|||
}
|
||||
}
|
||||
}
|
||||
takeOffStatus = state;
|
||||
takeOffStatus = AITakeOffStatus::QUEUED;
|
||||
}
|
||||
|
||||
// Process ATC instructions and report back
|
||||
|
@ -782,7 +784,17 @@ void FGAIAircraft::processATC(const FGATCInstruction& instruction) {
|
|||
// let an offending aircraft take an evasive action
|
||||
// for instance taxi back a little bit.
|
||||
}
|
||||
if (instruction.getHoldPattern ()) {}
|
||||
switch (fp->getLeg())
|
||||
{
|
||||
case AILeg::STARTUP_PUSHBACK:
|
||||
case AILeg::APPROACH:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (instruction.getHoldPattern ()) {
|
||||
//holdtime = instruction.getHoldTime();
|
||||
}
|
||||
|
||||
// Hold Position
|
||||
if (instruction.getHoldPosition ()) {
|
||||
|
@ -1048,11 +1060,14 @@ bool FGAIAircraft::handleAirportEndPoints(FGAIWaypoint* prev, time_t now) {
|
|||
AccelTo(0.0);
|
||||
}
|
||||
if (prev->contains("legend")) {
|
||||
fp->incrementLeg();
|
||||
int nextLeg = determineNextLeg(fp->getLeg());
|
||||
while (nextLeg!=fp->getLeg()) {
|
||||
fp->incrementLeg();
|
||||
}
|
||||
}
|
||||
if (prev->contains(string("DepartureHold"))) {
|
||||
//cerr << "Passing point DepartureHold" << endl;
|
||||
scheduleForATCTowerDepartureControl(1);
|
||||
scheduleForATCTowerDepartureControl();
|
||||
}
|
||||
if (prev->contains(string("Accel"))) {
|
||||
takeOffStatus = AITakeOffStatus::CLEARED_FOR_TAKEOFF;
|
||||
|
@ -1387,6 +1402,20 @@ const string& FGAIAircraft::atGate()
|
|||
return empty;
|
||||
}
|
||||
|
||||
int FGAIAircraft::determineNextLeg(int leg) {
|
||||
if (leg==AILeg::APPROACH) {
|
||||
time_t now = globals->get_time_params()->get_cur_time();
|
||||
if (controller->getInstruction(getID()).getRunwaySlot()
|
||||
> now) {
|
||||
return AILeg::HOLD;
|
||||
} else {
|
||||
return AILeg::LANDING;
|
||||
}
|
||||
} else {
|
||||
return leg+1;
|
||||
}
|
||||
}
|
||||
|
||||
void FGAIAircraft::handleATCRequests(double dt)
|
||||
{
|
||||
if (!this->getTrafficRef()) {
|
||||
|
|
|
@ -44,9 +44,10 @@ namespace AILeg
|
|||
CLIMB = 4,
|
||||
CRUISE = 5,
|
||||
APPROACH = 6,
|
||||
LANDING = 7,
|
||||
PARKING_TAXI = 8,
|
||||
PARKING = 9
|
||||
HOLD = 7,
|
||||
LANDING = 8,
|
||||
PARKING_TAXI = 9,
|
||||
PARKING = 10
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -122,7 +123,7 @@ public:
|
|||
int getTakeOffStatus() { return takeOffStatus; };
|
||||
void setTakeOffSlot(time_t timeSlot) { takeOffTimeSlot = timeSlot;};
|
||||
time_t getTakeOffSlot(){return takeOffTimeSlot;};
|
||||
void scheduleForATCTowerDepartureControl(int state);
|
||||
void scheduleForATCTowerDepartureControl();
|
||||
|
||||
const std::string& GetTransponderCode() { return transponderCode; };
|
||||
void SetTransponderCode(const std::string& tc) { transponderCode = tc;};
|
||||
|
@ -200,6 +201,8 @@ private:
|
|||
/**Handle special cases for the User AI shadow*/
|
||||
void updateUserFlightPlan(double dt);
|
||||
|
||||
/**Calculate the next leg (hold or not)*/
|
||||
int determineNextLeg(int leg);
|
||||
void handleATCRequests(double dt);
|
||||
|
||||
inline bool isStationary() {
|
||||
|
|
|
@ -185,7 +185,7 @@ public:
|
|||
|
||||
double checkTrackLength(const std::string& wptName) const;
|
||||
time_t getStartTime() const { return start_time; }
|
||||
time_t getArrivalTime() const { return arrivalTime; }
|
||||
time_t getArrivalTime() const { return arrivalTime; }
|
||||
|
||||
bool create(FGAIAircraft *, FGAirport *dep, FGAirport *arr, int leg, double alt, double speed, double lat, double lon,
|
||||
bool firstLeg, double radius, const std::string& fltType, const std::string& aircraftType, const std::string& airline, double distance);
|
||||
|
@ -268,6 +268,7 @@ private:
|
|||
bool createClimb(FGAIAircraft *, bool, FGAirport *, FGAirport* arrival, double, double, const std::string&);
|
||||
bool createCruise(FGAIAircraft *, bool, FGAirport*, FGAirport*, const SGGeod& current, double, double, const std::string&);
|
||||
bool createDescent(FGAIAircraft *, FGAirport *, const SGGeod& current, double speed, double alt,const std::string&, double distance);
|
||||
bool createHold(FGAIAircraft *, FGAirport *, const SGGeod& current, double speed, double alt,const std::string&, double distance);
|
||||
bool createLanding(FGAIAircraft *, FGAirport *, const std::string&);
|
||||
bool createParking(FGAIAircraft *, FGAirport *, double radius);
|
||||
void deleteWaypoints();
|
||||
|
|
|
@ -101,6 +101,10 @@ bool FGAIFlightPlan::create(FGAIAircraft * ac, FGAirport * dep,
|
|||
retVal = createDescent(ac, arr, SGGeod::fromDeg(longitude, latitude), speed, alt, fltType,
|
||||
distance);
|
||||
break;
|
||||
case AILeg::HOLD:
|
||||
retVal = createHold(ac, arr, SGGeod::fromDeg(longitude, latitude), speed, alt, fltType,
|
||||
distance);
|
||||
break;
|
||||
case AILeg::LANDING:
|
||||
retVal = createLanding(ac, arr, fltType);
|
||||
break;
|
||||
|
@ -775,7 +779,7 @@ bool FGAIFlightPlan::createDescent(FGAIAircraft * ac,
|
|||
heading);
|
||||
if (!apt->hasRunwayWithIdent(activeRunway)) {
|
||||
SG_LOG(SG_AI, SG_WARN, ac->getCallSign() <<
|
||||
"| FGAIFlightPlan::createLanding: No such runway " << activeRunway << " at " << apt->ident());
|
||||
"| FGAIFlightPlan::createDescent: No such runway " << activeRunway << " at " << apt->ident());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1018,63 +1022,56 @@ bool FGAIFlightPlan::createDescent(FGAIAircraft * ac,
|
|||
createArc(ac, secondaryTarget, ac->_getHeading()+rightAngle, heading+rightAngle, firstTurnIncrement, initialTurnRadius, ac->getAltitude(), altDiff/3, vDescent, "straight_turn_%03d");
|
||||
}
|
||||
|
||||
// To prevent absurdly steep approaches, compute the origin from where the approach should have started
|
||||
SGGeod origin;
|
||||
|
||||
if (distance < requiredDistance * 0.8) {
|
||||
reposition = true;
|
||||
SGGeodesy::direct(waypoints.back()->getPos(), azimuth,
|
||||
requiredDistance, origin, dummyAz2);
|
||||
|
||||
double addDD = SGGeodesy::courseDeg(refPoint, initialTarget);
|
||||
distance = SGGeodesy::distanceM(current, initialTarget);
|
||||
azimuth = SGGeodesy::courseDeg(current, initialTarget);
|
||||
} else {
|
||||
// We project a new point out of line so the aircraft has room to turn to new heading.
|
||||
origin = SGGeodesy::direct(current, ac->getTrueHeadingDeg(), initialTurnRadius);
|
||||
distance = SGGeodesy::distanceM(origin, initialTarget);
|
||||
azimuth = SGGeodesy::courseDeg(origin, initialTarget);
|
||||
}
|
||||
|
||||
// Calculate the ETA at final, based on remaining distance, and approach speed.
|
||||
// distance should really consist of flying time to terniary target, plus circle
|
||||
// but the distance to secondary target should work as a reasonable approximation
|
||||
// aditionally add the amount of distance covered by making a turn of "side"
|
||||
time_t remaining =
|
||||
(initialTurnRadius + distance) / ((vDescent * SG_NM_TO_METER) / 3600.0);
|
||||
time_t now = globals->get_time_params()->get_cur_time();
|
||||
|
||||
//if (ac->getTrafficRef()->getCallSign() == fgGetString("/ai/track-callsign")) {
|
||||
// cerr << " Arrival time estimation: turn angle " << side << ". Turn distance " << turnDistance << ". Linear distance " << distance << ". Time to go " << remaining << endl;
|
||||
// //exit(1);
|
||||
//}
|
||||
|
||||
time_t eta = now + remaining;
|
||||
arrivalTime = now;
|
||||
//choose a distance to the runway such that it will take at least 60 seconds more
|
||||
// time to get there than the previous aircraft.
|
||||
// Don't bother when aircraft need to be repositioned, because that marks the initialization phased...
|
||||
|
||||
time_t newEta;
|
||||
|
||||
if (reposition == false) {
|
||||
newEta =
|
||||
apt->getDynamics()->getApproachController()->getRunway(rwy->name())->requestTimeSlot(eta);
|
||||
} else {
|
||||
newEta = eta;
|
||||
}
|
||||
|
||||
arrivalTime = newEta;
|
||||
time_t additionalTimeNeeded = newEta - eta;
|
||||
SG_LOG(SG_AI, SG_BULK, "Additional time required " << additionalTimeNeeded << " ");
|
||||
|
||||
//Number of holds
|
||||
double holdsPatterns = (additionalTimeNeeded-additionalTimeNeeded%240)/240;
|
||||
|
||||
additionalTimeNeeded -= holdsPatterns*240;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
* CreateHold
|
||||
* Generate a hold flight path from the permission to land point
|
||||
* Exactly one hold pattern
|
||||
******************************************************************/
|
||||
bool FGAIFlightPlan::createHold(FGAIAircraft * ac,
|
||||
FGAirport * apt,
|
||||
const SGGeod& current,
|
||||
double speed,
|
||||
double alt,
|
||||
const string & fltType,
|
||||
double requiredDistance)
|
||||
{
|
||||
//Beginning of Descent
|
||||
const string& rwyClass = getRunwayClassFromTrafficType(fltType);
|
||||
double vDescent = ac->getPerformance()->vDescent();
|
||||
double vApproach = ac->getPerformance()->vApproach();
|
||||
double initialTurnRadius = getTurnRadius(vDescent, true);
|
||||
double heading = ac->getTrueHeadingDeg();
|
||||
apt->getDynamics()->getActiveRunway(rwyClass, 2, activeRunway,
|
||||
heading);
|
||||
if (!apt->hasRunwayWithIdent(activeRunway)) {
|
||||
SG_LOG(SG_AI, SG_WARN, ac->getCallSign() <<
|
||||
"| FGAIFlightPlan::createHold: No such runway " << activeRunway << " at " << apt->ident());
|
||||
return false;
|
||||
}
|
||||
FGRunwayRef rwy = apt->getRunwayByIdent(activeRunway);
|
||||
double currentAltitude = waypoints.back()->getAltitude();
|
||||
double distanceOut = apt->getDynamics()->getApproachController()->getRunway(rwy->name())->getApproachDistance(); //12 * SG_NM_TO_METER;
|
||||
double lateralOffset = initialTurnRadius;
|
||||
|
||||
SGGeod secondaryTarget = rwy->pointOffCenterline(-2 * distanceOut, lateralOffset);
|
||||
SGGeod secondHoldCenter = rwy->pointOffCenterline(-4 * distanceOut, lateralOffset);
|
||||
|
||||
createArc(ac, secondaryTarget, rwy->headingDeg()-90, rwy->headingDeg()+90, 5, initialTurnRadius,
|
||||
currentAltitude, 0, vDescent, "hold_1_%03d");
|
||||
createArc(ac, secondHoldCenter, rwy->headingDeg()+90, rwy->headingDeg()-90, 5, initialTurnRadius,
|
||||
currentAltitude, 0, vDescent, "hold_2_%03d");
|
||||
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* compute the distance along the centerline, to the ILS glideslope
|
||||
* transmitter. Return -1 if there's no GS for the runway
|
||||
|
|
|
@ -102,6 +102,36 @@ bool FGATCController::isUserAircraft(FGAIAircraft* ac)
|
|||
return (ac->getCallSign() == fgGetString("/sim/multiplay/callsign")) ? true : false;
|
||||
};
|
||||
|
||||
bool FGATCController::checkTransmissionState(int minState, int maxState, TrafficVectorIterator i, time_t now, AtcMsgId msgId,
|
||||
AtcMsgDir msgDir)
|
||||
{
|
||||
int state = i->getState();
|
||||
if ((state >= minState) && (state <= maxState) && available) {
|
||||
if ((msgDir == ATC_AIR_TO_GROUND) && isUserAircraft(i->getAircraft())) {
|
||||
SG_LOG(SG_ATC, SG_BULK, "Checking state " << state << " for " << i->getAircraft()->getCallSign());
|
||||
SGPropertyNode_ptr trans_num = globals->get_props()->getNode("/sim/atc/transmission-num", true);
|
||||
int n = trans_num->getIntValue();
|
||||
if (n == 0) {
|
||||
trans_num->setIntValue(-1);
|
||||
// PopupCallback(n);
|
||||
SG_LOG(SG_ATC, SG_DEBUG, "Selected transmission message " << n);
|
||||
//auto atc = globals->get_subsystem<FGATCManager>();
|
||||
//FGATCDialogNew::instance()->removeEntry(1);
|
||||
} else {
|
||||
SG_LOG(SG_ATC, SG_BULK, "Sending message for " << i->getAircraft()->getCallSign());
|
||||
transmit(&(*i), parent, msgId, msgDir, false);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
transmit(&(*i), parent, msgId, msgDir, true);
|
||||
i->updateState();
|
||||
lastTransmission = now;
|
||||
available = false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void FGATCController::transmit(FGTrafficRecord * rec, FGAirportDynamics *parent, AtcMsgId msgId,
|
||||
AtcMsgDir msgDir, bool audible)
|
||||
{
|
||||
|
@ -109,7 +139,6 @@ void FGATCController::transmit(FGTrafficRecord * rec, FGAirportDynamics *parent,
|
|||
int stationFreq = 0;
|
||||
int taxiFreq = 0;
|
||||
int towerFreq = 0;
|
||||
int freqId = 0;
|
||||
string atisInformation;
|
||||
string text;
|
||||
string taxiFreqStr;
|
||||
|
@ -133,14 +162,20 @@ void FGATCController::transmit(FGTrafficRecord * rec, FGAirportDynamics *parent,
|
|||
instructionText = "taxi";
|
||||
}
|
||||
|
||||
SG_LOG(SG_ATC, SG_DEBUG, "transmitting for: " << sender << "Leg = " << rec->getLeg());
|
||||
SG_LOG(SG_ATC, SG_BULK, "transmitting for: " << sender << " at Leg " << rec->getLeg());
|
||||
|
||||
//FIXME move departure and arrival to rec
|
||||
auto depApt = rec->getAircraft()->getTrafficRef()->getDepartureAirport();
|
||||
auto arrApt = rec->getAircraft()->getTrafficRef()->getArrivalAirport();
|
||||
|
||||
if (!depApt) {
|
||||
SG_LOG(SG_ATC, SG_DEV_ALERT, "TrafficRec has empty departure airport, can't transmit");
|
||||
return;
|
||||
}
|
||||
if (!arrApt) {
|
||||
SG_LOG(SG_ATC, SG_DEV_ALERT, "TrafficRec has empty arrival airport, can't transmit");
|
||||
return;
|
||||
}
|
||||
|
||||
stationFreq = getFrequency();
|
||||
taxiFreq = depApt->getDynamics()->getGroundFrequency(2);
|
||||
|
@ -281,16 +316,12 @@ void FGATCController::transmit(FGTrafficRecord * rec, FGAirportDynamics *parent,
|
|||
text = receiver + ". Holding short runway "
|
||||
+ activeRunway
|
||||
+ ". " + sender + ".";
|
||||
//text = "test1";
|
||||
SG_LOG(SG_ATC, SG_DEBUG, "1 Currently at leg " << rec->getLeg());
|
||||
break;
|
||||
case MSG_ACKNOWLEDGE_REPORT_RUNWAY_HOLD_SHORT:
|
||||
activeRunway = rec->getAircraft()->GetFlightPlan()->getRunway();
|
||||
text = receiver + " Roger. Holding short runway "
|
||||
// + activeRunway
|
||||
+ ". " + sender + ".";
|
||||
//text = "test2";
|
||||
SG_LOG(SG_ATC, SG_DEBUG, "2 Currently at leg " << rec->getLeg());
|
||||
break;
|
||||
case MSG_CLEARED_FOR_TAKEOFF:
|
||||
activeRunway = rec->getAircraft()->GetFlightPlan()->getRunway();
|
||||
|
@ -300,23 +331,40 @@ void FGATCController::transmit(FGTrafficRecord * rec, FGAirportDynamics *parent,
|
|||
case MSG_ACKNOWLEDGE_CLEARED_FOR_TAKEOFF:
|
||||
activeRunway = rec->getAircraft()->GetFlightPlan()->getRunway();
|
||||
text = receiver + " Roger. Cleared for takeoff runway " + activeRunway + ". " + sender + ".";
|
||||
//text = "test2";
|
||||
break;
|
||||
case MSG_SWITCH_TOWER_FREQUENCY:
|
||||
towerFreqStr = formatATCFrequency3_2(towerFreq);
|
||||
text = receiver + " Contact Tower at " + towerFreqStr + ". " + sender + ".";
|
||||
//text = "test3";
|
||||
SG_LOG(SG_ATC, SG_DEBUG, "3 Currently at leg " << rec->getLeg());
|
||||
break;
|
||||
case MSG_ACKNOWLEDGE_SWITCH_TOWER_FREQUENCY:
|
||||
towerFreqStr = formatATCFrequency3_2(towerFreq);
|
||||
text = receiver + " Roger, switching to tower at " + towerFreqStr + ". " + sender + ".";
|
||||
//text = "test4";
|
||||
SG_LOG(SG_ATC, SG_DEBUG, "4 Currently at leg " << rec->getLeg());
|
||||
break;
|
||||
case MSG_ARRIVAL:
|
||||
text = receiver + ". " + sender + " Information delta.";
|
||||
break;
|
||||
case MSG_ACKNOWLEDGE_ARRIVAL:
|
||||
activeRunway = rec->getRunway();
|
||||
text = receiver + " expect ILS approach " + activeRunway + ". " + sender;
|
||||
break;
|
||||
case MSG_CLEARED_TO_LAND:
|
||||
activeRunway = rec->getRunway();
|
||||
//TODO Weather
|
||||
text = receiver + " runway " + activeRunway + " cleared to land. " + sender;
|
||||
break;
|
||||
case MSG_ACKNOWLEDGE_CLEARED_TO_LAND:
|
||||
activeRunway = rec->getAircraft()->GetFlightPlan()->getRunway();
|
||||
text = receiver + " runway " + activeRunway + " cleared to land. " + sender;
|
||||
break;
|
||||
case MSG_HOLD:
|
||||
text = receiver + " hold as published . " + sender;
|
||||
break;
|
||||
case MSG_ACKNOWLEDGE_HOLD:
|
||||
text = receiver + " holding as published . " + sender;
|
||||
break;
|
||||
default:
|
||||
//text = "test3";
|
||||
text = text + sender + ". Transmitting unknown Message.";
|
||||
text = text + sender + ". Transmitting unknown Message. MsgId " + std::to_string(msgId);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -341,12 +389,10 @@ void FGATCController::transmit(FGTrafficRecord * rec, FGAirportDynamics *parent,
|
|||
((onBoardRadioFreqI0 == stationFreq)||
|
||||
(onBoardRadioFreqI1 == stationFreq))) {
|
||||
if (rec->allowTransmissions()) {
|
||||
|
||||
if( fgGetBool( "/sim/radio/use-itm-attenuation", false ) ) {
|
||||
SG_LOG(SG_ATC, SG_DEBUG, "Using ITM radio propagation");
|
||||
FGRadioTransmission* radio = new FGRadioTransmission();
|
||||
SGGeod sender_pos;
|
||||
double sender_alt_ft, sender_alt;
|
||||
if(ground_to_air) {
|
||||
sender_pos = parent->parent()->geod();
|
||||
}
|
||||
|
@ -368,6 +414,11 @@ void FGATCController::transmit(FGTrafficRecord * rec, FGAirportDynamics *parent,
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sign off the aircraft with the id from this controller.
|
||||
* @param id the id of the aircraft
|
||||
*/
|
||||
|
||||
void FGATCController::signOff(int id)
|
||||
{
|
||||
TrafficVectorIterator i = searchActiveTraffic(id);
|
||||
|
@ -377,8 +428,12 @@ void FGATCController::signOff(int id)
|
|||
"AI error: Aircraft without traffic record is signing off from " << getName() << " at " << SG_ORIGIN << " list " << activeTraffic.empty());
|
||||
return;
|
||||
}
|
||||
SG_LOG(SG_ATC, SG_DEBUG, i->getCallsign() << " (" << i->getId() << ") signing off from " << getName() << "(" << getFrequency() << ")");
|
||||
int oldSize = activeTraffic.size();
|
||||
activeTraffic.erase(i);
|
||||
SG_LOG(SG_ATC, SG_DEBUG, i->getCallsign() << " signing off from " << getName() );
|
||||
if ((oldSize-activeTraffic.size()) != 1) {
|
||||
SG_LOG(SG_ATC, SG_WARN, i->getCallsign() << " not removed ");
|
||||
}
|
||||
}
|
||||
|
||||
bool FGATCController::hasInstruction(int id)
|
||||
|
|
|
@ -39,28 +39,35 @@ namespace ATCMessageState
|
|||
{
|
||||
enum Type
|
||||
{
|
||||
// 0 = Normal; no action required
|
||||
NORMAL = 0,
|
||||
// 1 = "Acknowledge "Hold position
|
||||
ACK_HOLD = 1,
|
||||
// 2 = "Acknowledge "Resume taxi".
|
||||
ACK_RESUME_TAXI = 2,
|
||||
// 3 = "Issue TaxiClearance"
|
||||
TAXI_CLEARED = 3,
|
||||
// 4 = Acknowledge Taxi Clearance"
|
||||
ACK_TAXI_CLEARED = 4,
|
||||
// 5 = Post acknowlegde taxiclearance: Start taxiing
|
||||
START_TAXI = 5,
|
||||
// 6 = Report runway
|
||||
REPORT_RUNWAY = 6,
|
||||
// 7 = Acknowledge report runway
|
||||
ACK_REPORT_RUNWAY = 7,
|
||||
// 8 = Switch tower frequency
|
||||
SWITCH_TOWER = 8,
|
||||
// 9 = Acknowledge switch tower frequency
|
||||
ACK_SWITCH_TOWER = 9,
|
||||
// 10 = Cleared for takeoff
|
||||
CLEARED_TAKEOFF = 10,
|
||||
// 0 = Normal; no action required
|
||||
NORMAL,
|
||||
// 1 = "Acknowledge "Hold position
|
||||
ACK_HOLD,
|
||||
// 2 = "Acknowledge "Resume taxi".
|
||||
ACK_RESUME_TAXI,
|
||||
// 3 = "Issue TaxiClearance"
|
||||
TAXI_CLEARED = 3,
|
||||
// 4 = Acknowledge Taxi Clearance"
|
||||
ACK_TAXI_CLEARED = 4,
|
||||
// 5 = Post acknowlegde taxiclearance: Start taxiing
|
||||
START_TAXI = 5,
|
||||
// 6 = Report runway
|
||||
REPORT_RUNWAY = 6,
|
||||
// 7 = Acknowledge report runway
|
||||
ACK_REPORT_RUNWAY = 7,
|
||||
// 8 = Switch tower frequency
|
||||
SWITCH_GROUND_TOWER = 8,
|
||||
// 9 = Acknowledge switch tower frequency
|
||||
ACK_SWITCH_GROUND_TOWER = 9,
|
||||
// 10 = Cleared for takeoff
|
||||
CLEARED_TAKEOFF,
|
||||
ACK_CLEARED_TAKEOFF,
|
||||
ANNOUNCE_ARRIVAL,
|
||||
ACK_ARRIVAL,
|
||||
HOLD,
|
||||
CLEARED_TO_LAND,
|
||||
ACK_CLEARED_TO_LAND,
|
||||
LANDING_TAXI
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -118,7 +125,13 @@ public:
|
|||
MSG_CLEARED_FOR_TAKEOFF,
|
||||
MSG_ACKNOWLEDGE_CLEARED_FOR_TAKEOFF,
|
||||
MSG_SWITCH_TOWER_FREQUENCY,
|
||||
MSG_ACKNOWLEDGE_SWITCH_TOWER_FREQUENCY
|
||||
MSG_ACKNOWLEDGE_SWITCH_TOWER_FREQUENCY,
|
||||
MSG_ARRIVAL,
|
||||
MSG_ACKNOWLEDGE_ARRIVAL,
|
||||
MSG_HOLD,
|
||||
MSG_ACKNOWLEDGE_HOLD,
|
||||
MSG_CLEARED_TO_LAND,
|
||||
MSG_ACKNOWLEDGE_CLEARED_TO_LAND
|
||||
} AtcMsgId;
|
||||
|
||||
typedef enum {
|
||||
|
@ -135,6 +148,8 @@ public:
|
|||
FGAIAircraft *aircraft) = 0;
|
||||
virtual void updateAircraftInformation(int id, SGGeod geod,
|
||||
double heading, double speed, double alt, double dt) = 0;
|
||||
bool checkTransmissionState(int minState, int MaxState, TrafficVectorIterator i, time_t now, AtcMsgId msgId,
|
||||
AtcMsgDir msgDir);
|
||||
|
||||
virtual void signOff(int id);
|
||||
bool hasInstruction(int id);
|
||||
|
|
|
@ -98,9 +98,11 @@ void FGApproachController::announcePosition(int id,
|
|||
rec.setLeg(leg);
|
||||
rec.setCallsign(ref->getCallSign());
|
||||
rec.setAircraft(ref);
|
||||
rec.setPlannedArrivalTime(intendedRoute->getArrivalTime());
|
||||
activeTraffic.push_back(rec);
|
||||
} else {
|
||||
i->setPositionAndHeading(lat, lon, heading, speed, alt);
|
||||
i->setPlannedArrivalTime(intendedRoute->getArrivalTime());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -108,6 +110,7 @@ void FGApproachController::updateAircraftInformation(int id, SGGeod geod,
|
|||
double heading, double speed, double alt,
|
||||
double dt)
|
||||
{
|
||||
time_t now = globals->get_time_params()->get_cur_time();
|
||||
// Search activeTraffic for a record matching our id
|
||||
TrafficVectorIterator i = FGATCController::searchActiveTraffic(id);
|
||||
TrafficVectorIterator current;
|
||||
|
@ -115,7 +118,7 @@ void FGApproachController::updateAircraftInformation(int id, SGGeod geod,
|
|||
// update position of the current aircraft
|
||||
if (i == activeTraffic.end() || activeTraffic.empty()) {
|
||||
SG_LOG(SG_ATC, SG_ALERT,
|
||||
"AI error: updating aircraft without traffic record at " << SG_ORIGIN);
|
||||
"FGApproachController updating aircraft without traffic record at " << SG_ORIGIN);
|
||||
} else {
|
||||
i->setPositionAndHeading(geod.getLatitudeDeg(), geod.getLongitudeDeg(), heading, speed, alt);
|
||||
current = i;
|
||||
|
@ -146,13 +149,42 @@ void FGApproachController::updateAircraftInformation(int id, SGGeod geod,
|
|||
} else {
|
||||
current->clearSpeedAdjustment();
|
||||
}
|
||||
if ((now - lastTransmission) > 15) {
|
||||
available = true;
|
||||
}
|
||||
//Start of our status runimplicit "announce arrival"
|
||||
if (checkTransmissionState(ATCMessageState::NORMAL, ATCMessageState::NORMAL, current, now, MSG_ARRIVAL, ATC_AIR_TO_GROUND)) {
|
||||
current->setRunwaySlot(getRunway(current->getRunway())->requestTimeSlot(current->getPlannedArrivalTime()));
|
||||
current->setState(ATCMessageState::ACK_ARRIVAL);
|
||||
}
|
||||
if (checkTransmissionState(ATCMessageState::ACK_ARRIVAL, ATCMessageState::ACK_ARRIVAL, current, now, MSG_ACKNOWLEDGE_ARRIVAL, ATC_GROUND_TO_AIR)) {
|
||||
if (current->getRunwaySlot() > current->getPlannedArrivalTime()) {
|
||||
current->setState(ATCMessageState::HOLD);
|
||||
} else {
|
||||
current->setState(ATCMessageState::CLEARED_TO_LAND);
|
||||
}
|
||||
}
|
||||
if (checkTransmissionState(ATCMessageState::HOLD, ATCMessageState::HOLD, current, now, MSG_ACKNOWLEDGE_HOLD, ATC_AIR_TO_GROUND)) {
|
||||
current->setState(ATCMessageState::ACK_HOLD);
|
||||
}
|
||||
if (checkTransmissionState(ATCMessageState::CLEARED_TO_LAND, ATCMessageState::CLEARED_TO_LAND, current, now, MSG_CLEARED_TO_LAND, ATC_GROUND_TO_AIR)) {
|
||||
current->setState(ATCMessageState::ACK_CLEARED_TO_LAND);
|
||||
}
|
||||
if (checkTransmissionState(ATCMessageState::ACK_CLEARED_TO_LAND, ATCMessageState::ACK_CLEARED_TO_LAND, current, now, MSG_ACKNOWLEDGE_CLEARED_TO_LAND, ATC_AIR_TO_GROUND)) {
|
||||
current->setState(ATCMessageState::SWITCH_GROUND_TOWER);
|
||||
}
|
||||
if (checkTransmissionState(ATCMessageState::SWITCH_GROUND_TOWER, ATCMessageState::SWITCH_GROUND_TOWER, current, now, MSG_SWITCH_TOWER_FREQUENCY, ATC_GROUND_TO_AIR)) {
|
||||
}
|
||||
if (checkTransmissionState(ATCMessageState::ACK_SWITCH_GROUND_TOWER, ATCMessageState::ACK_SWITCH_GROUND_TOWER, current, now, MSG_ACKNOWLEDGE_SWITCH_TOWER_FREQUENCY, ATC_AIR_TO_GROUND)) {
|
||||
current->setState(ATCMessageState::LANDING_TAXI);
|
||||
}
|
||||
}
|
||||
//current->setSpeedAdjustment(current->getAircraft()->getPerformance()->vDescent() + time_diff);
|
||||
}
|
||||
setDt(getDt() + dt);
|
||||
}
|
||||
|
||||
/* Periodically check for and remove dead traffic records */
|
||||
/** Periodically check for and remove dead traffic records */
|
||||
void FGApproachController::update(double dt)
|
||||
{
|
||||
FGATCController::eraseDeadTraffic();
|
||||
|
|
|
@ -130,7 +130,7 @@ void FGGroundController::announcePosition(int id,
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* The ground network can deal with the following states:
|
||||
* 0 = Normal; no action required
|
||||
* 1 = "Acknowledge "Hold position
|
||||
|
@ -143,35 +143,6 @@ void FGGroundController::announcePosition(int id,
|
|||
* 8 = Switch tower frequency
|
||||
* 9 = Acknowledge switch tower frequency
|
||||
*/
|
||||
bool FGGroundController::checkTransmissionState(int minState, int maxState, TrafficVectorIterator i, time_t now, AtcMsgId msgId,
|
||||
AtcMsgDir msgDir)
|
||||
{
|
||||
int state = i->getState();
|
||||
if ((state >= minState) && (state <= maxState) && available) {
|
||||
if ((msgDir == ATC_AIR_TO_GROUND) && isUserAircraft(i->getAircraft())) {
|
||||
SG_LOG(SG_ATC, SG_DEBUG, "Checking state " << state << " for " << i->getAircraft()->getCallSign());
|
||||
SGPropertyNode_ptr trans_num = globals->get_props()->getNode("/sim/atc/transmission-num", true);
|
||||
int n = trans_num->getIntValue();
|
||||
if (n == 0) {
|
||||
trans_num->setIntValue(-1);
|
||||
// PopupCallback(n);
|
||||
SG_LOG(SG_ATC, SG_DEBUG, "Selected transmission message " << n);
|
||||
//auto atc = globals->get_subsystem<FGATCManager>();
|
||||
//FGATCDialogNew::instance()->removeEntry(1);
|
||||
} else {
|
||||
SG_LOG(SG_ATC, SG_DEBUG, "creating message for " << i->getAircraft()->getCallSign());
|
||||
transmit(&(*i), parent, msgId, msgDir, false);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
transmit(&(*i), parent, msgId, msgDir, true);
|
||||
i->updateState();
|
||||
lastTransmission = now;
|
||||
available = false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void FGGroundController::updateAircraftInformation(int id, SGGeod geod,
|
||||
double heading, double speed, double alt,
|
||||
|
@ -221,26 +192,25 @@ void FGGroundController::updateAircraftInformation(int id, SGGeod geod,
|
|||
if ((now - lastTransmission) > 15) {
|
||||
available = true;
|
||||
}
|
||||
if (checkTransmissionState(0,2, current, now, MSG_REQUEST_TAXI_CLEARANCE, ATC_AIR_TO_GROUND)) {
|
||||
if (checkTransmissionState(ATCMessageState::NORMAL,ATCMessageState::ACK_RESUME_TAXI, current, now, MSG_REQUEST_TAXI_CLEARANCE, ATC_AIR_TO_GROUND)) {
|
||||
current->setState(ATCMessageState::TAXI_CLEARED);
|
||||
}
|
||||
if (checkTransmissionState(3,3, current, now, MSG_ISSUE_TAXI_CLEARANCE, ATC_GROUND_TO_AIR)) {
|
||||
if (checkTransmissionState(ATCMessageState::TAXI_CLEARED,ATCMessageState::TAXI_CLEARED, current, now, MSG_ISSUE_TAXI_CLEARANCE, ATC_GROUND_TO_AIR)) {
|
||||
current->setState(ATCMessageState::ACK_TAXI_CLEARED);
|
||||
}
|
||||
if (checkTransmissionState(4,4, current, now, MSG_ACKNOWLEDGE_TAXI_CLEARANCE, ATC_AIR_TO_GROUND)) {
|
||||
if (checkTransmissionState(ATCMessageState::ACK_TAXI_CLEARED,ATCMessageState::ACK_TAXI_CLEARED, current, now, MSG_ACKNOWLEDGE_TAXI_CLEARANCE, ATC_AIR_TO_GROUND)) {
|
||||
current->setState(ATCMessageState::START_TAXI);
|
||||
}
|
||||
if ((state == 5) && available) {
|
||||
if ((state == ATCMessageState::START_TAXI) && available) {
|
||||
current->setState(ATCMessageState::NORMAL);
|
||||
current->getAircraft()->setTaxiClearanceRequest(false);
|
||||
current->setHoldPosition(false);
|
||||
available = false;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* Scan for a speed adjustment change. Find the nearest aircraft that is in front
|
||||
* and adjust speed when we get too close. Only do this when current position and/or
|
||||
* intentions of the current aircraft match current taxiroute position of the proximate
|
||||
|
@ -310,7 +280,7 @@ void FGGroundController::checkSpeedAdjustment(int id, double lat,
|
|||
if( current->getId() == i->getId()) {
|
||||
continue;
|
||||
}
|
||||
SG_LOG(SG_ATC, SG_BULK, "Comparing " << current->getCallsign() << " and " << i->getCallsign());
|
||||
SG_LOG(SG_ATC, SG_BULK, current->getCallsign() << "| Comparing with " << i->getCallsign() << " Id: " << i->getId());
|
||||
SGGeod other = i->getPos();
|
||||
SGGeodesy::inverse(curr, other, course, az2, dist);
|
||||
bearing = fabs(heading - course);
|
||||
|
@ -394,7 +364,7 @@ void FGGroundController::checkSpeedAdjustment(int id, double lat,
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* Check for "Hold position instruction".
|
||||
* The hold position should be issued under the following conditions:
|
||||
* 1) For aircraft entering or crossing a runway with active traffic on it, or landing aircraft near it
|
||||
|
@ -427,12 +397,15 @@ void FGGroundController::checkHoldPosition(int id, double lat,
|
|||
"AI error: Trying to access non-existing aircraft in FGGroundNetwork::checkHoldPosition at " << SG_ORIGIN);
|
||||
}
|
||||
current = i;
|
||||
if (current->getAircraft()->getTakeOffStatus() == 1) {
|
||||
if (current->getAircraft()->getTakeOffStatus() == AITakeOffStatus::QUEUED) {
|
||||
current->setHoldPosition(true);
|
||||
return;
|
||||
}
|
||||
if (current->getAircraft()->getTakeOffStatus() == 2) {
|
||||
SG_LOG(SG_ATC, SG_DEBUG, current->getAircraft()->getCallSign() << ". Taxi in position and hold");
|
||||
if ((now - lastTransmission) > 15) {
|
||||
available = true;
|
||||
}
|
||||
|
||||
if (current->getAircraft()->getTakeOffStatus() == AITakeOffStatus::CLEARED_FOR_TAKEOFF) {
|
||||
current->setHoldPosition(false);
|
||||
current->clearSpeedAdjustment();
|
||||
return;
|
||||
|
@ -485,7 +458,7 @@ void FGGroundController::checkHoldPosition(int id, double lat,
|
|||
if ((now - lastTransmission) > 2) {
|
||||
available = true;
|
||||
}
|
||||
if (current->getState() == 0) {
|
||||
if (current->getState() == ATCMessageState::NORMAL) {
|
||||
if ((origStatus != currStatus) && available) {
|
||||
SG_LOG(SG_ATC, SG_DEBUG, "Issuing hold short instruction " << currStatus << " " << available);
|
||||
if (currStatus == true) { // No has a hold short instruction
|
||||
|
@ -511,11 +484,11 @@ void FGGroundController::checkHoldPosition(int id, double lat,
|
|||
//9 = Acknowledge switch tower frequency
|
||||
|
||||
//int state = current->getState();
|
||||
if (checkTransmissionState(1,1, current, now, MSG_ACKNOWLEDGE_HOLD_POSITION, ATC_AIR_TO_GROUND)) {
|
||||
if (checkTransmissionState(ATCMessageState::ACK_HOLD, ATCMessageState::ACK_HOLD, current, now, MSG_ACKNOWLEDGE_HOLD_POSITION, ATC_AIR_TO_GROUND)) {
|
||||
current->setState(ATCMessageState::NORMAL);
|
||||
current->setHoldPosition(true);
|
||||
}
|
||||
if (checkTransmissionState(2,2, current, now, MSG_ACKNOWLEDGE_RESUME_TAXI, ATC_AIR_TO_GROUND)) {
|
||||
if (checkTransmissionState(ATCMessageState::ACK_RESUME_TAXI, ATCMessageState::ACK_RESUME_TAXI, current, now, MSG_ACKNOWLEDGE_RESUME_TAXI, ATC_AIR_TO_GROUND)) {
|
||||
current->setState(ATCMessageState::NORMAL);
|
||||
current->setHoldPosition(false);
|
||||
}
|
||||
|
@ -523,13 +496,13 @@ void FGGroundController::checkHoldPosition(int id, double lat,
|
|||
SG_LOG(SG_ATC, SG_DEBUG, "Scheduling " << current->getAircraft()->getCallSign() << " for hold short");
|
||||
current->setState(ATCMessageState::REPORT_RUNWAY);
|
||||
}
|
||||
if (checkTransmissionState(6,6, current, now, MSG_REPORT_RUNWAY_HOLD_SHORT, ATC_AIR_TO_GROUND)) {
|
||||
if (checkTransmissionState(ATCMessageState::REPORT_RUNWAY ,ATCMessageState::REPORT_RUNWAY , current, now, MSG_REPORT_RUNWAY_HOLD_SHORT, ATC_AIR_TO_GROUND)) {
|
||||
}
|
||||
if (checkTransmissionState(7,7, current, now, MSG_ACKNOWLEDGE_REPORT_RUNWAY_HOLD_SHORT, ATC_GROUND_TO_AIR)) {
|
||||
if (checkTransmissionState(ATCMessageState::ACK_REPORT_RUNWAY, ATCMessageState::ACK_REPORT_RUNWAY, current, now, MSG_ACKNOWLEDGE_REPORT_RUNWAY_HOLD_SHORT, ATC_GROUND_TO_AIR)) {
|
||||
}
|
||||
if (checkTransmissionState(8,8, current, now, MSG_SWITCH_TOWER_FREQUENCY, ATC_GROUND_TO_AIR)) {
|
||||
if (checkTransmissionState(ATCMessageState::SWITCH_GROUND_TOWER, ATCMessageState::SWITCH_GROUND_TOWER, current, now, MSG_SWITCH_TOWER_FREQUENCY, ATC_GROUND_TO_AIR)) {
|
||||
}
|
||||
if (checkTransmissionState(9,9, current, now, MSG_ACKNOWLEDGE_SWITCH_TOWER_FREQUENCY, ATC_AIR_TO_GROUND)) {
|
||||
if (checkTransmissionState(ATCMessageState::ACK_SWITCH_GROUND_TOWER, ATCMessageState::ACK_SWITCH_GROUND_TOWER, current, now, MSG_ACKNOWLEDGE_SWITCH_TOWER_FREQUENCY, ATC_AIR_TO_GROUND)) {
|
||||
}
|
||||
|
||||
|
||||
|
@ -580,7 +553,7 @@ bool FGGroundController::checkForCircularWaits(int id)
|
|||
int counter = 0;
|
||||
|
||||
if (id == target) {
|
||||
SG_LOG(SG_ATC, SG_DEBUG, "aircraft waits for user");
|
||||
SG_LOG(SG_ATC, SG_DEBUG, "aircraft is waiting for user");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -641,7 +614,7 @@ static void WorldCoordinate(osg::Matrix& obj_pos, double lat,
|
|||
0.0, 1.0, 0.0));
|
||||
}
|
||||
|
||||
/* Draw visible taxi routes */
|
||||
/** Draw visible taxi routes */
|
||||
void FGGroundController::render(bool visible)
|
||||
{
|
||||
SGMaterialLib *matlib = globals->get_matlib();
|
||||
|
|
|
@ -76,9 +76,7 @@ public:
|
|||
double radius, int leg, FGAIAircraft *aircraft);
|
||||
virtual void updateAircraftInformation(int id, SGGeod geod, double heading, double speed, double alt, double dt);
|
||||
|
||||
bool checkTransmissionState(int minState, int MaxState, TrafficVectorIterator i, time_t now, AtcMsgId msgId,
|
||||
AtcMsgDir msgDir);
|
||||
bool checkForCircularWaits(int id);
|
||||
bool checkForCircularWaits(int id);
|
||||
virtual void render(bool);
|
||||
virtual std::string getName();
|
||||
virtual void update(double dt);
|
||||
|
|
|
@ -105,41 +105,7 @@ void FGStartupController::announcePosition(int id,
|
|||
}
|
||||
}
|
||||
|
||||
bool FGStartupController::checkTransmissionState(int st, time_t now, time_t startTime, TrafficVectorIterator i, AtcMsgId msgId,
|
||||
AtcMsgDir msgDir)
|
||||
{
|
||||
int state = i->getState();
|
||||
if ((state == st) && available) {
|
||||
if ((msgDir == ATC_AIR_TO_GROUND) && isUserAircraft(i->getAircraft())) {
|
||||
|
||||
SG_LOG(SG_ATC, SG_BULK, "Checking state " << st << " for " << i->getAircraft()->getCallSign());
|
||||
SGPropertyNode_ptr trans_num = globals->get_props()->getNode("/sim/atc/transmission-num", true);
|
||||
int n = trans_num->getIntValue();
|
||||
if (n == 0) {
|
||||
trans_num->setIntValue(-1);
|
||||
// PopupCallback(n);
|
||||
SG_LOG(SG_ATC, SG_BULK, "Selected transmission message " << n);
|
||||
//FGATCDialogNew::instance()->removeEntry(1);
|
||||
} else {
|
||||
SG_LOG(SG_ATC, SG_BULK, "Creating message for " << i->getAircraft()->getCallSign());
|
||||
transmit(&(*i), &(*parent), msgId, msgDir, false);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (now > startTime) {
|
||||
SG_LOG(SG_ATC, SG_BULK, "Transmitting startup msg");
|
||||
transmit(&(*i), &(*parent), msgId, msgDir, true);
|
||||
i->updateState();
|
||||
lastTransmission = now;
|
||||
available = false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void FGStartupController::updateAircraftInformation(int id, SGGeod geod,
|
||||
double heading, double speed, double alt,
|
||||
void FGStartupController::updateAircraftInformation(int id, SGGeod geod, double heading, double speed, double alt,
|
||||
double dt)
|
||||
{
|
||||
// Search activeTraffic for a record matching our id
|
||||
|
@ -171,7 +137,8 @@ void FGStartupController::updateAircraftInformation(int id, SGGeod geod,
|
|||
time_t now = globals->get_time_params()->get_cur_time();
|
||||
|
||||
|
||||
if ((startTime - now) > 0) {
|
||||
if (((startTime - now) > 60 && (startTime - now)%60 == 0) ||
|
||||
((startTime - now) < 60 && (startTime - now) > 0)) {
|
||||
SG_LOG(SG_ATC, SG_BULK, i->getAircraft()->getTrafficRef()->getCallSign() << " is scheduled to depart in " << startTime - now << " seconds. Available = " << available << " at parking " << getGateName(i->getAircraft()));
|
||||
}
|
||||
|
||||
|
@ -179,20 +146,31 @@ void FGStartupController::updateAircraftInformation(int id, SGGeod geod,
|
|||
available = true;
|
||||
}
|
||||
|
||||
checkTransmissionState(0, now, (startTime + 0 ), i, MSG_ANNOUNCE_ENGINE_START, ATC_AIR_TO_GROUND);
|
||||
checkTransmissionState(1, now, (startTime + 60 ), i, MSG_REQUEST_ENGINE_START, ATC_AIR_TO_GROUND);
|
||||
checkTransmissionState(2, now, (startTime + 80 ), i, MSG_PERMIT_ENGINE_START, ATC_GROUND_TO_AIR);
|
||||
checkTransmissionState(3, now, (startTime + 100), i, MSG_ACKNOWLEDGE_ENGINE_START, ATC_AIR_TO_GROUND);
|
||||
if (checkTransmissionState(4, now, (startTime + 130), i, MSG_ACKNOWLEDGE_SWITCH_GROUND_FREQUENCY, ATC_AIR_TO_GROUND)) {
|
||||
i->nextFrequency();
|
||||
if (now >(startTime + 0)) {
|
||||
checkTransmissionState(ATCMessageState::NORMAL, ATCMessageState::NORMAL, i, now, MSG_ANNOUNCE_ENGINE_START, ATC_AIR_TO_GROUND);
|
||||
}
|
||||
checkTransmissionState(5, now, (startTime + 140), i, MSG_INITIATE_CONTACT, ATC_AIR_TO_GROUND);
|
||||
checkTransmissionState(6, now, (startTime + 150), i, MSG_ACKNOWLEDGE_INITIATE_CONTACT, ATC_GROUND_TO_AIR);
|
||||
checkTransmissionState(7, now, (startTime + 180), i, MSG_REQUEST_PUSHBACK_CLEARANCE, ATC_AIR_TO_GROUND);
|
||||
|
||||
|
||||
|
||||
if ((state == 8) && available) {
|
||||
if (now >(startTime + 60)) {
|
||||
checkTransmissionState(ATCMessageState::ACK_HOLD, ATCMessageState::ACK_HOLD, i, now, MSG_REQUEST_ENGINE_START, ATC_AIR_TO_GROUND);
|
||||
}
|
||||
if (now >(startTime + 80)) {
|
||||
checkTransmissionState(ATCMessageState::ACK_RESUME_TAXI, ATCMessageState::ACK_RESUME_TAXI, i, now, MSG_PERMIT_ENGINE_START, ATC_GROUND_TO_AIR);
|
||||
}
|
||||
if (now >(startTime + 100)) {
|
||||
checkTransmissionState(ATCMessageState::TAXI_CLEARED, ATCMessageState::TAXI_CLEARED, i, now, MSG_ACKNOWLEDGE_ENGINE_START, ATC_AIR_TO_GROUND);
|
||||
}
|
||||
if (now >(startTime + 130)) {
|
||||
checkTransmissionState(ATCMessageState::ACK_TAXI_CLEARED, ATCMessageState::ACK_TAXI_CLEARED, i, now, MSG_ACKNOWLEDGE_SWITCH_GROUND_FREQUENCY, ATC_AIR_TO_GROUND);
|
||||
}
|
||||
if (now >(startTime + 140)) {
|
||||
checkTransmissionState(ATCMessageState::START_TAXI, ATCMessageState::START_TAXI, i, now, MSG_INITIATE_CONTACT, ATC_AIR_TO_GROUND);
|
||||
}
|
||||
if (now >(startTime + 150)) {
|
||||
checkTransmissionState(ATCMessageState::REPORT_RUNWAY, ATCMessageState::REPORT_RUNWAY, i, now, MSG_ACKNOWLEDGE_INITIATE_CONTACT, ATC_GROUND_TO_AIR);
|
||||
}
|
||||
if (now >(startTime + 180)) {
|
||||
checkTransmissionState(ATCMessageState::ACK_REPORT_RUNWAY, ATCMessageState::ACK_REPORT_RUNWAY, i, now, MSG_REQUEST_PUSHBACK_CLEARANCE, ATC_AIR_TO_GROUND);
|
||||
}
|
||||
if ((state == ATCMessageState::SWITCH_GROUND_TOWER) && available) {
|
||||
if (now > startTime + 200) {
|
||||
if (i->pushBackAllowed()) {
|
||||
i->allowRepeatedTransmissions();
|
||||
|
@ -208,7 +186,7 @@ void FGStartupController::updateAircraftInformation(int id, SGGeod geod,
|
|||
available = false;
|
||||
}
|
||||
}
|
||||
if ((state == 9) && available) {
|
||||
if ((state == ATCMessageState::ACK_SWITCH_GROUND_TOWER) && available) {
|
||||
i->setHoldPosition(false);
|
||||
}
|
||||
}
|
||||
|
@ -230,7 +208,6 @@ static void WorldCoordinate(osg::Matrix& obj_pos, double lat,
|
|||
|
||||
void FGStartupController::render(bool visible)
|
||||
{
|
||||
SG_LOG(SG_ATC, SG_DEBUG, "Rendering startup controller");
|
||||
SGMaterialLib *matlib = globals->get_matlib();
|
||||
if (group) {
|
||||
//int nr = ;
|
||||
|
@ -245,6 +222,7 @@ void FGStartupController::render(bool visible)
|
|||
group = 0;
|
||||
}
|
||||
if (visible) {
|
||||
SG_LOG(SG_ATC, SG_BULK, "Rendering startup controller");
|
||||
group = new osg::Group;
|
||||
FGScenery * local_scenery = globals->get_scenery();
|
||||
//double elevation_meters = 0.0;
|
||||
|
|
|
@ -61,11 +61,6 @@ public:
|
|||
virtual void render(bool);
|
||||
virtual std::string getName();
|
||||
virtual void update(double dt);
|
||||
|
||||
// Hpoefully, we can move this function to the base class, but I need to verify what is needed for the other controllers before doing so.
|
||||
bool checkTransmissionState(int st, time_t now, time_t startTime, TrafficVectorIterator i, AtcMsgId msgId,
|
||||
AtcMsgDir msgDir);
|
||||
|
||||
};
|
||||
|
||||
#endif
|
|
@ -96,7 +96,7 @@ void FGTowerController::announcePosition(int id,
|
|||
rec.setPositionAndHeading(lat, lon, heading, speed, alt);
|
||||
rec.setRunway(intendedRoute->getRunway());
|
||||
rec.setLeg(leg);
|
||||
//rec.setCallSign(callsign);
|
||||
rec.setCallsign(ref->getCallSign());
|
||||
rec.setRadius(radius);
|
||||
rec.setAircraft(ref);
|
||||
activeTraffic.push_back(rec);
|
||||
|
@ -113,13 +113,19 @@ void FGTowerController::announcePosition(int id,
|
|||
if (rwy == activeRunways.end()) {
|
||||
ActiveRunway aRwy(intendedRoute->getRunway(), id);
|
||||
aRwy.addToDepartureQueue(ref);
|
||||
time_t now = globals->get_time_params()->get_cur_time();
|
||||
rec.setPlannedArrivalTime(now);
|
||||
rec.setRunwaySlot(aRwy.requestTimeSlot(now));
|
||||
activeRunways.push_back(aRwy);
|
||||
rwy = (activeRunways.end()-1);
|
||||
} else {
|
||||
time_t now = globals->get_time_params()->get_cur_time();
|
||||
rec.setPlannedArrivalTime(now);
|
||||
rec.setRunwaySlot(rwy->requestTimeSlot(now));
|
||||
rwy->addToDepartureQueue(ref);
|
||||
}
|
||||
|
||||
SG_LOG(SG_ATC, SG_DEBUG, ref->getTrafficRef()->getCallSign() << " You are number " << rwy->getdepartureQueueSize() << " for takeoff ");
|
||||
SG_LOG(SG_ATC, SG_DEBUG, ref->getTrafficRef()->getCallSign() << " You are number " << rwy->getdepartureQueueSize() << " for takeoff from " << rwy->getRunwayName());
|
||||
} else {
|
||||
i->setPositionAndHeading(lat, lon, heading, speed, alt);
|
||||
}
|
||||
|
@ -134,6 +140,7 @@ void FGTowerController::updateAircraftInformation(int id, SGGeod geod,
|
|||
|
||||
setDt(getDt() + dt);
|
||||
|
||||
time_t now = globals->get_time_params()->get_cur_time();
|
||||
if (i == activeTraffic.end() || (activeTraffic.empty())) {
|
||||
SG_LOG(SG_ATC, SG_ALERT,
|
||||
"AI error: updating aircraft without traffic record at " <<
|
||||
|
@ -184,30 +191,43 @@ void FGTowerController::updateAircraftInformation(int id, SGGeod geod,
|
|||
if (ac->getTakeOffStatus() == AITakeOffStatus::QUEUED) {
|
||||
// transmit takeoff clearance
|
||||
ac->setTakeOffStatus(AITakeOffStatus::CLEARED_FOR_TAKEOFF);
|
||||
transmit(&(*i), &(*parent), MSG_CLEARED_FOR_TAKEOFF, ATC_GROUND_TO_AIR, true);
|
||||
i->setState(ATCMessageState::CLEARED_TAKEOFF);
|
||||
TrafficVectorIterator first = searchActiveTraffic(ac->getID());
|
||||
//FIXME use checkTransmissionState
|
||||
if (first == activeTraffic.end() || activeTraffic.empty()) {
|
||||
SG_LOG(SG_ATC, SG_ALERT,
|
||||
"FGApproachController updating aircraft without traffic record at " << SG_ORIGIN);
|
||||
} else {
|
||||
first->setState(ATCMessageState::CLEARED_TAKEOFF);
|
||||
transmit(&(*first), &(*parent), MSG_CLEARED_FOR_TAKEOFF, ATC_GROUND_TO_AIR, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
//FIXME Make it an member of traffic record
|
||||
if (current.getAircraft()->getTakeOffStatus() == AITakeOffStatus::CLEARED_FOR_TAKEOFF) {
|
||||
if (current.getAircraft()->getTakeOffStatus() == AITakeOffStatus::CLEARED_FOR_TAKEOFF &&
|
||||
current.getRunwaySlot() < now) {
|
||||
current.setHoldPosition(false);
|
||||
if (checkTransmissionState(ATCMessageState::CLEARED_TAKEOFF, ATCMessageState::CLEARED_TAKEOFF, i, now, MSG_ACKNOWLEDGE_CLEARED_FOR_TAKEOFF, ATC_AIR_TO_GROUND)) {
|
||||
current.setState(ATCMessageState::ANNOUNCE_ARRIVAL);
|
||||
}
|
||||
} else {
|
||||
current.setHoldPosition(true);
|
||||
SG_LOG(SG_ATC, SG_BULK,
|
||||
current.getCallsign() << "| Waiting for " << (current.getRunwaySlot() - now) << " seconds");
|
||||
}
|
||||
int clearanceId = rwy->getCleared();
|
||||
if (clearanceId) {
|
||||
if (id == clearanceId) {
|
||||
SG_LOG(SG_ATC, SG_BULK, "Unset Hold " << clearanceId << " for " << rwy->getRunwayName());
|
||||
SG_LOG(SG_ATC, SG_BULK, current.getCallsign() << "| Unset Hold " << clearanceId << " for rwy " << rwy->getRunwayName());
|
||||
current.setHoldPosition(false);
|
||||
} else {
|
||||
SG_LOG(SG_ATC, SG_WARN, "Not cleared " << id << " Currently cleared " << clearanceId);
|
||||
SG_LOG(SG_ATC, SG_BULK, current.getCallsign() << "| Not cleared " << id << " Currently cleared " << clearanceId);
|
||||
}
|
||||
} else {
|
||||
if (current.getAircraft() == rwy->getFirstAircraftInDepartureQueue()) {
|
||||
SG_LOG(SG_ATC, SG_BULK,
|
||||
"Cleared " << current.getAircraft()->getCallSign() << " for " << rwy->getRunwayName() << " Id " << id);
|
||||
current.getCallsign() << "| Cleared for runway " << getName() << " " << rwy->getRunwayName() << " Id " << id);
|
||||
rwy->setCleared(id);
|
||||
auto ac = rwy->getFirstOfStatus(1);
|
||||
auto ac = rwy->getFirstOfStatus(AITakeOffStatus::QUEUED);
|
||||
if (ac) {
|
||||
ac->setTakeOffStatus(AITakeOffStatus::QUEUED);
|
||||
// transmit takeoff clearacne? But why twice?
|
||||
|
@ -241,9 +261,8 @@ void FGTowerController::signOff(int id)
|
|||
});
|
||||
|
||||
if (runwayIt != activeRunways.end()) {
|
||||
SG_LOG(SG_ATC, SG_BULK, "Cleared " << id << " from " << runwayIt->getRunwayName() );
|
||||
runwayIt->setCleared(0);
|
||||
runwayIt->updateDepartureQueue();
|
||||
SG_LOG(SG_ATC, SG_BULK, i->getCallsign() << "|Cleared " << id << " from " << runwayIt->getRunwayName() << " cleared " << runwayIt->getCleared() );
|
||||
runwayIt->removeFromDepartureQueue(id);
|
||||
} else {
|
||||
SG_LOG(SG_ATC, SG_ALERT,
|
||||
"AI error: Attempting to erase non-existing runway clearance record in FGTowerController::signoff at " << SG_ORIGIN);
|
||||
|
@ -294,9 +313,10 @@ void FGTowerController::render(bool visible) {
|
|||
}
|
||||
|
||||
string FGTowerController::getName() {
|
||||
return string(parent->getId() + "-tower");
|
||||
return string(parent->parent()->getName() + "-tower");
|
||||
}
|
||||
|
||||
|
||||
void FGTowerController::update(double dt)
|
||||
{
|
||||
FGATCController::eraseDeadTraffic();
|
||||
|
|
|
@ -59,9 +59,9 @@ FGATCManager::~FGATCManager() {
|
|||
}
|
||||
|
||||
/**
|
||||
Sets up ATC subsystem parts depending on other subsystems
|
||||
Override of SGSubsystem::postinit()
|
||||
Will set private boolean flag "initSucceeded" to true upon conclusion
|
||||
* Sets up ATC subsystem parts depending on other subsystems
|
||||
* Override of SGSubsystem::postinit()
|
||||
* Will set private boolean flag "initSucceeded" to true upon conclusion
|
||||
*/
|
||||
void FGATCManager::postinit()
|
||||
{
|
||||
|
|
|
@ -67,12 +67,23 @@ ActiveRunway::ActiveRunway(const std::string& r, int cc) :
|
|||
distanceToFinal = 6.0 * SG_NM_TO_METER;
|
||||
};
|
||||
|
||||
void ActiveRunway::removeFromDepartureQueue(int id) {
|
||||
if (id!=currentlyCleared) {
|
||||
printDepartureQueue();
|
||||
SG_LOG(SG_ATC, SG_WARN, "Not cleared id being removed from DepartureQueue " << id << " currently cleared " << currentlyCleared);
|
||||
} else {
|
||||
setCleared(0);
|
||||
updateDepartureQueue();
|
||||
printDepartureQueue();
|
||||
}
|
||||
}
|
||||
|
||||
void ActiveRunway::updateDepartureQueue()
|
||||
{
|
||||
departureQueue.erase(departureQueue.begin());
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* Fetch next slot for the active runway
|
||||
* @param eta time of slot requested
|
||||
* @return newEta: next slot available; starts at eta paramater
|
||||
|
@ -92,12 +103,12 @@ time_t ActiveRunway::requestTimeSlot(time_t eta)
|
|||
// if the aircraft is the first arrival, add to the vector and return eta directly
|
||||
if (estimatedArrivalTimes.empty()) {
|
||||
estimatedArrivalTimes.push_back(eta);
|
||||
SG_LOG(SG_ATC, SG_DEBUG, getRunwayName() << "Checked eta slots, using " << eta);
|
||||
SG_LOG(SG_ATC, SG_BULK, getRunwayName() << " Checked eta slots, using " << eta);
|
||||
return eta;
|
||||
} else {
|
||||
// First check the already assigned slots to see where we need to fit the flight in
|
||||
TimeVectorIterator i = estimatedArrivalTimes.begin();
|
||||
SG_LOG(SG_ATC, SG_DEBUG, getRunwayName() << " Checking eta slots " << eta << " : " << estimatedArrivalTimes.size() << " Timediff " << (eta - globals->get_time_params()->get_cur_time()));
|
||||
SG_LOG(SG_ATC, SG_BULK, getRunwayName() << " Checking eta slots " << eta << " : " << estimatedArrivalTimes.size() << " Timediff : " << (eta - globals->get_time_params()->get_cur_time()));
|
||||
|
||||
// is this needed - just a debug output?
|
||||
for (i = estimatedArrivalTimes.begin();
|
||||
|
@ -110,7 +121,7 @@ time_t ActiveRunway::requestTimeSlot(time_t eta)
|
|||
if ((eta + separation) < (*i)) {
|
||||
newEta = eta;
|
||||
SG_LOG(SG_ATC, SG_BULK, "Storing at beginning");
|
||||
SG_LOG(SG_ATC, SG_DEBUG, "Done. New ETA : " << newEta);
|
||||
SG_LOG(SG_ATC, SG_DEBUG, "Done. New ETA : " << newEta );
|
||||
slotHousekeeping(newEta);
|
||||
return newEta;
|
||||
}
|
||||
|
@ -128,7 +139,7 @@ time_t ActiveRunway::requestTimeSlot(time_t eta)
|
|||
newEta = (*i) + separation;
|
||||
SG_LOG(SG_ATC, SG_BULK, "Storing at end + separation");
|
||||
}
|
||||
SG_LOG(SG_ATC, SG_DEBUG, "Done. New ETA : " << newEta);
|
||||
SG_LOG(SG_ATC, SG_DEBUG, "Done. New ETA : " << newEta << " Timediff : " << (newEta-eta));
|
||||
slotHousekeeping(newEta);
|
||||
return newEta;
|
||||
} else {
|
||||
|
@ -197,7 +208,7 @@ void ActiveRunway::slotHousekeeping(time_t newEta)
|
|||
}
|
||||
}
|
||||
|
||||
/* Output the contents of the departure queue vector nicely formatted*/
|
||||
/** Output the contents of the departure queue vector nicely formatted*/
|
||||
void ActiveRunway::printDepartureQueue()
|
||||
{
|
||||
SG_LOG(SG_ATC, SG_DEBUG, "Departure queue for " << rwy << ": ");
|
||||
|
@ -208,7 +219,7 @@ void ActiveRunway::printDepartureQueue()
|
|||
|
||||
}
|
||||
|
||||
/* Fetch the first aircraft in the departure queue with a certain status */
|
||||
/** Fetch the first aircraft in the departure queue with a certain status */
|
||||
SGSharedPtr<FGAIAircraft>ActiveRunway::getFirstOfStatus(int stat) const
|
||||
{
|
||||
auto it = std::find_if(departureQueue.begin(), departureQueue.end(), [stat](const SGSharedPtr<FGAIAircraft>& acft) {
|
||||
|
@ -316,10 +327,14 @@ bool FGTrafficRecord::isDead() const {
|
|||
bool FGTrafficRecord::checkPositionAndIntentions(FGTrafficRecord & other)
|
||||
{
|
||||
bool result = false;
|
||||
SG_LOG(SG_ATC, SG_BULK, getCallsign() << "|checkPositionAndIntentions");
|
||||
SG_LOG(SG_ATC, SG_BULK, getCallsign() << "| checkPositionAndIntentions CurrentPos : " << currentPos << " Other : " << other.currentPos << " Leg : " << leg << " Other Leg : " << other.leg );
|
||||
if (currentPos == other.currentPos && getId() != other.getId() ) {
|
||||
SG_LOG(SG_ATC, SG_BULK, getCallsign() << "|Check Position and intentions: " << other.getCallsign() << " we are on the same taxiway; Index = " << currentPos);
|
||||
result = true;
|
||||
SG_LOG(SG_ATC, SG_BULK, getCallsign() << "| Check Position and intentions: " << other.getCallsign() << " we are on the same taxiway; Index = " << currentPos);
|
||||
int headingTowards = SGGeodesy::courseDeg( other.getPos(), getPos() );
|
||||
int headingDiff = SGMiscd::normalizePeriodic(-180, 180, headingTowards - getHeading() );
|
||||
SG_LOG(SG_ATC, SG_BULK, getCallsign() << "| " << heading << "\t" << headingTowards << "\t" << headingDiff);
|
||||
// getHeading()
|
||||
result = abs(headingDiff) < 89;
|
||||
}
|
||||
// else if (! other.intentions.empty())
|
||||
// {
|
||||
|
@ -331,8 +346,8 @@ bool FGTrafficRecord::checkPositionAndIntentions(FGTrafficRecord & other)
|
|||
// SG_LOG(SG_ATC, SG_BULK, "Check Position and intentions: current matches other.intentions");
|
||||
// result = true;
|
||||
// }
|
||||
else if (! intentions.empty()) {
|
||||
SG_LOG(SG_ATC, SG_BULK, getCallsign() << "|Itentions " << intentions.size());
|
||||
else if (!intentions.empty()) {
|
||||
SG_LOG(SG_ATC, SG_BULK, getCallsign() << "| Itentions Size " << intentions.size());
|
||||
intVecIterator i = intentions.begin();
|
||||
//while (!((i == intentions.end()) || ((*i) == other.currentPos)))
|
||||
while (i != intentions.end()) {
|
||||
|
@ -343,7 +358,13 @@ bool FGTrafficRecord::checkPositionAndIntentions(FGTrafficRecord & other)
|
|||
}
|
||||
if (i != intentions.end()) {
|
||||
SG_LOG(SG_ATC, SG_BULK, getCallsign() << "| Check Position and intentions: " << other.getCallsign()<< " matches Index = " << (*i));
|
||||
result = true;
|
||||
int headingTowards = SGGeodesy::courseDeg( other.getPos(), getPos() );
|
||||
int distanceM = SGGeodesy::distanceM( other.getPos(), getPos() );
|
||||
int headingDiff = SGMiscd::normalizePeriodic(-180, 180, headingTowards - getHeading() );
|
||||
SG_LOG(SG_ATC, SG_BULK, getCallsign() << "| Heading : " << heading << "\t Heading Other->Current" << headingTowards << "\t Heading Diff :" << headingDiff << "\t Distance : " << distanceM);
|
||||
// difference of heading is small and it's actually near
|
||||
result = abs(headingDiff) < 89 && distanceM < 400;
|
||||
// result = true;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
|
|
@ -64,6 +64,7 @@ class FGATCInstruction
|
|||
{
|
||||
private:
|
||||
bool holdPattern;
|
||||
int requestedArrivalTime;
|
||||
bool holdPosition;
|
||||
bool changeSpeed;
|
||||
bool changeHeading;
|
||||
|
@ -80,6 +81,12 @@ public:
|
|||
bool getHoldPattern () const {
|
||||
return holdPattern;
|
||||
};
|
||||
void setRunwaySlot (int val) {
|
||||
requestedArrivalTime = val;
|
||||
};
|
||||
int getRunwaySlot () const {
|
||||
return requestedArrivalTime;
|
||||
};
|
||||
bool getHoldPosition () const {
|
||||
return holdPosition;
|
||||
};
|
||||
|
@ -156,6 +163,7 @@ private:
|
|||
bool allowTransmission;
|
||||
bool allowPushback;
|
||||
int priority;
|
||||
int plannedArrivalTime;
|
||||
time_t timer;
|
||||
intVec intentions;
|
||||
FGATCInstruction instruction;
|
||||
|
@ -186,9 +194,15 @@ public:
|
|||
int getId() const {
|
||||
return id;
|
||||
};
|
||||
/**
|
||||
* Return the current ATC State of type @see ATCMessageState
|
||||
*/
|
||||
int getState() const {
|
||||
return state;
|
||||
};
|
||||
/**
|
||||
* Set the current ATC State of type @see ATCMessageState
|
||||
*/
|
||||
void setState(int s) {
|
||||
state = s;
|
||||
}
|
||||
|
@ -212,7 +226,23 @@ public:
|
|||
bool getSpeedAdjustment() const {
|
||||
return instruction.getChangeSpeed();
|
||||
};
|
||||
|
||||
void setPlannedArrivalTime (int val) {
|
||||
plannedArrivalTime = val;
|
||||
};
|
||||
/**Arrival time planned by aircraft.*/
|
||||
int getPlannedArrivalTime () const {
|
||||
return plannedArrivalTime;
|
||||
};
|
||||
void setRunwaySlot( int val ) {
|
||||
if (plannedArrivalTime) {
|
||||
SG_LOG(SG_ATC, SG_BULK, callsign << "| Runwayslot " << (val-plannedArrivalTime));
|
||||
}
|
||||
instruction.setRunwaySlot(val);
|
||||
};
|
||||
/**Arrival time requested by ATC.*/
|
||||
int getRunwaySlot() {
|
||||
return instruction.getRunwaySlot();
|
||||
};
|
||||
SGGeod getPos() {
|
||||
return pos;
|
||||
}
|
||||
|
@ -251,7 +281,6 @@ public:
|
|||
void setHoldPosition (bool inst) {
|
||||
instruction.setHoldPosition(inst);
|
||||
};
|
||||
|
||||
void setWaitsForId(int id) {
|
||||
waitsForId = id;
|
||||
};
|
||||
|
@ -368,6 +397,8 @@ public:
|
|||
|
||||
SGSharedPtr<FGAIAircraft> getFirstOfStatus(int stat) const;
|
||||
|
||||
void removeFromDepartureQueue(int id);
|
||||
|
||||
void updateDepartureQueue();
|
||||
|
||||
void printDepartureQueue();
|
||||
|
|
|
@ -1031,7 +1031,7 @@ FGAIAircraft * TrafficTests::flyAI(SGSharedPtr<FGAIAircraft> aiAircraft, std::st
|
|||
int startSpeed = aiAircraft->GetFlightPlan()->getCurrentWaypoint()->getSpeed();
|
||||
aiAircraft->AccelTo(startSpeed);
|
||||
|
||||
for (size_t i = 0; i < 12000000 && !(aiAircraft->getDie()) && aiAircraft->GetFlightPlan()->getLeg() < 10; i++) {
|
||||
for (size_t i = 0; i < 12000000 && !(aiAircraft->getDie()) && aiAircraft->GetFlightPlan()->getLeg() <= AILeg::PARKING; i++) {
|
||||
CPPUNIT_ASSERT_EQUAL(aiAircraft->GetFlightPlan()->isValidPlan(), true);
|
||||
if (!aiAircraft->getDie()) {
|
||||
// collect position
|
||||
|
@ -1072,7 +1072,7 @@ FGAIAircraft * TrafficTests::flyAI(SGSharedPtr<FGAIAircraft> aiAircraft, std::st
|
|||
aiAircraft->dumpCSV(csvFile, lineIndex++);
|
||||
// A flight without loops should never reach 400°
|
||||
CPPUNIT_ASSERT_LESSEQUAL(400.0, headingSum);
|
||||
CPPUNIT_ASSERT_LESSEQUAL(10, aiAircraft->GetFlightPlan()->getLeg());
|
||||
CPPUNIT_ASSERT_LESSEQUAL( 10, aiAircraft->GetFlightPlan()->getLeg());
|
||||
CPPUNIT_ASSERT_MESSAGE( "Aircraft has not completed test in time.", i < 3000000);
|
||||
// Arrived at a parking
|
||||
int beforeNextDepTime = aiAircraft->getTrafficRef()->getDepartureTime() - 30;
|
||||
|
|
Loading…
Reference in a new issue