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;
|
groundOffset = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
fp = 0;
|
fp = nullptr;
|
||||||
controller = 0;
|
controller = nullptr;
|
||||||
prevController = 0;
|
prevController = nullptr;
|
||||||
towerController = 0;
|
towerController = nullptr;
|
||||||
dt_count = 0;
|
dt_count = 0;
|
||||||
dt_elev_count = 0;
|
dt_elev_count = 0;
|
||||||
use_perf_vs = true;
|
use_perf_vs = true;
|
||||||
|
@ -604,11 +604,13 @@ bool FGAIAircraft::loadNextLeg(double distance) {
|
||||||
} else {
|
} else {
|
||||||
double cruiseAlt = trafficRef->getCruiseAlt() * 100;
|
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,
|
bool ok = fp->create (this,
|
||||||
dep,
|
dep,
|
||||||
arr,
|
arr,
|
||||||
leg+1,
|
nextLeg,
|
||||||
cruiseAlt,
|
cruiseAlt,
|
||||||
trafficRef->getSpeed(),
|
trafficRef->getSpeed(),
|
||||||
_getLatitude(),
|
_getLatitude(),
|
||||||
|
@ -721,10 +723,10 @@ void FGAIAircraft::announcePositionToController() {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case AILeg::APPROACH:
|
case AILeg::APPROACH:
|
||||||
if (trafficRef->getArrivalAirport()->getDynamics()) {
|
if (trafficRef->getArrivalAirport()->getDynamics()) {
|
||||||
controller = trafficRef->getArrivalAirport()->getDynamics()->getApproachController();
|
controller = trafficRef->getArrivalAirport()->getDynamics()->getApproachController();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case AILeg::PARKING_TAXI: // Taxiing for parking
|
case AILeg::PARKING_TAXI: // Taxiing for parking
|
||||||
if (trafficRef->getArrivalAirport()->getDynamics()->getGroundController()->exists())
|
if (trafficRef->getArrivalAirport()->getDynamics()->getGroundController()->exists())
|
||||||
controller = trafficRef->getArrivalAirport()->getDynamics()->getGroundController();
|
controller = trafficRef->getArrivalAirport()->getDynamics()->getGroundController();
|
||||||
|
@ -749,7 +751,7 @@ void FGAIAircraft::announcePositionToController() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FGAIAircraft::scheduleForATCTowerDepartureControl(int state) {
|
void FGAIAircraft::scheduleForATCTowerDepartureControl() {
|
||||||
if (!takeOffStatus) {
|
if (!takeOffStatus) {
|
||||||
int leg = fp->getLeg();
|
int leg = fp->getLeg();
|
||||||
if (trafficRef) {
|
if (trafficRef) {
|
||||||
|
@ -765,7 +767,7 @@ void FGAIAircraft::scheduleForATCTowerDepartureControl(int state) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
takeOffStatus = state;
|
takeOffStatus = AITakeOffStatus::QUEUED;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process ATC instructions and report back
|
// Process ATC instructions and report back
|
||||||
|
@ -782,7 +784,17 @@ void FGAIAircraft::processATC(const FGATCInstruction& instruction) {
|
||||||
// let an offending aircraft take an evasive action
|
// let an offending aircraft take an evasive action
|
||||||
// for instance taxi back a little bit.
|
// 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
|
// Hold Position
|
||||||
if (instruction.getHoldPosition ()) {
|
if (instruction.getHoldPosition ()) {
|
||||||
|
@ -1048,11 +1060,14 @@ bool FGAIAircraft::handleAirportEndPoints(FGAIWaypoint* prev, time_t now) {
|
||||||
AccelTo(0.0);
|
AccelTo(0.0);
|
||||||
}
|
}
|
||||||
if (prev->contains("legend")) {
|
if (prev->contains("legend")) {
|
||||||
fp->incrementLeg();
|
int nextLeg = determineNextLeg(fp->getLeg());
|
||||||
|
while (nextLeg!=fp->getLeg()) {
|
||||||
|
fp->incrementLeg();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (prev->contains(string("DepartureHold"))) {
|
if (prev->contains(string("DepartureHold"))) {
|
||||||
//cerr << "Passing point DepartureHold" << endl;
|
//cerr << "Passing point DepartureHold" << endl;
|
||||||
scheduleForATCTowerDepartureControl(1);
|
scheduleForATCTowerDepartureControl();
|
||||||
}
|
}
|
||||||
if (prev->contains(string("Accel"))) {
|
if (prev->contains(string("Accel"))) {
|
||||||
takeOffStatus = AITakeOffStatus::CLEARED_FOR_TAKEOFF;
|
takeOffStatus = AITakeOffStatus::CLEARED_FOR_TAKEOFF;
|
||||||
|
@ -1387,6 +1402,20 @@ const string& FGAIAircraft::atGate()
|
||||||
return empty;
|
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)
|
void FGAIAircraft::handleATCRequests(double dt)
|
||||||
{
|
{
|
||||||
if (!this->getTrafficRef()) {
|
if (!this->getTrafficRef()) {
|
||||||
|
|
|
@ -44,9 +44,10 @@ namespace AILeg
|
||||||
CLIMB = 4,
|
CLIMB = 4,
|
||||||
CRUISE = 5,
|
CRUISE = 5,
|
||||||
APPROACH = 6,
|
APPROACH = 6,
|
||||||
LANDING = 7,
|
HOLD = 7,
|
||||||
PARKING_TAXI = 8,
|
LANDING = 8,
|
||||||
PARKING = 9
|
PARKING_TAXI = 9,
|
||||||
|
PARKING = 10
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,7 +123,7 @@ public:
|
||||||
int getTakeOffStatus() { return takeOffStatus; };
|
int getTakeOffStatus() { return takeOffStatus; };
|
||||||
void setTakeOffSlot(time_t timeSlot) { takeOffTimeSlot = timeSlot;};
|
void setTakeOffSlot(time_t timeSlot) { takeOffTimeSlot = timeSlot;};
|
||||||
time_t getTakeOffSlot(){return takeOffTimeSlot;};
|
time_t getTakeOffSlot(){return takeOffTimeSlot;};
|
||||||
void scheduleForATCTowerDepartureControl(int state);
|
void scheduleForATCTowerDepartureControl();
|
||||||
|
|
||||||
const std::string& GetTransponderCode() { return transponderCode; };
|
const std::string& GetTransponderCode() { return transponderCode; };
|
||||||
void SetTransponderCode(const std::string& tc) { transponderCode = tc;};
|
void SetTransponderCode(const std::string& tc) { transponderCode = tc;};
|
||||||
|
@ -200,6 +201,8 @@ private:
|
||||||
/**Handle special cases for the User AI shadow*/
|
/**Handle special cases for the User AI shadow*/
|
||||||
void updateUserFlightPlan(double dt);
|
void updateUserFlightPlan(double dt);
|
||||||
|
|
||||||
|
/**Calculate the next leg (hold or not)*/
|
||||||
|
int determineNextLeg(int leg);
|
||||||
void handleATCRequests(double dt);
|
void handleATCRequests(double dt);
|
||||||
|
|
||||||
inline bool isStationary() {
|
inline bool isStationary() {
|
||||||
|
|
|
@ -185,7 +185,7 @@ public:
|
||||||
|
|
||||||
double checkTrackLength(const std::string& wptName) const;
|
double checkTrackLength(const std::string& wptName) const;
|
||||||
time_t getStartTime() const { return start_time; }
|
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 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);
|
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 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 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 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 createLanding(FGAIAircraft *, FGAirport *, const std::string&);
|
||||||
bool createParking(FGAIAircraft *, FGAirport *, double radius);
|
bool createParking(FGAIAircraft *, FGAirport *, double radius);
|
||||||
void deleteWaypoints();
|
void deleteWaypoints();
|
||||||
|
|
|
@ -101,6 +101,10 @@ bool FGAIFlightPlan::create(FGAIAircraft * ac, FGAirport * dep,
|
||||||
retVal = createDescent(ac, arr, SGGeod::fromDeg(longitude, latitude), speed, alt, fltType,
|
retVal = createDescent(ac, arr, SGGeod::fromDeg(longitude, latitude), speed, alt, fltType,
|
||||||
distance);
|
distance);
|
||||||
break;
|
break;
|
||||||
|
case AILeg::HOLD:
|
||||||
|
retVal = createHold(ac, arr, SGGeod::fromDeg(longitude, latitude), speed, alt, fltType,
|
||||||
|
distance);
|
||||||
|
break;
|
||||||
case AILeg::LANDING:
|
case AILeg::LANDING:
|
||||||
retVal = createLanding(ac, arr, fltType);
|
retVal = createLanding(ac, arr, fltType);
|
||||||
break;
|
break;
|
||||||
|
@ -775,7 +779,7 @@ bool FGAIFlightPlan::createDescent(FGAIAircraft * ac,
|
||||||
heading);
|
heading);
|
||||||
if (!apt->hasRunwayWithIdent(activeRunway)) {
|
if (!apt->hasRunwayWithIdent(activeRunway)) {
|
||||||
SG_LOG(SG_AI, SG_WARN, ac->getCallSign() <<
|
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;
|
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");
|
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();
|
time_t now = globals->get_time_params()->get_cur_time();
|
||||||
|
|
||||||
//if (ac->getTrafficRef()->getCallSign() == fgGetString("/ai/track-callsign")) {
|
arrivalTime = now;
|
||||||
// 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;
|
|
||||||
//choose a distance to the runway such that it will take at least 60 seconds more
|
//choose a distance to the runway such that it will take at least 60 seconds more
|
||||||
// time to get there than the previous aircraft.
|
// time to get there than the previous aircraft.
|
||||||
// Don't bother when aircraft need to be repositioned, because that marks the initialization phased...
|
// 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;
|
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
|
* compute the distance along the centerline, to the ILS glideslope
|
||||||
* transmitter. Return -1 if there's no GS for the runway
|
* 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;
|
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,
|
void FGATCController::transmit(FGTrafficRecord * rec, FGAirportDynamics *parent, AtcMsgId msgId,
|
||||||
AtcMsgDir msgDir, bool audible)
|
AtcMsgDir msgDir, bool audible)
|
||||||
{
|
{
|
||||||
|
@ -109,7 +139,6 @@ void FGATCController::transmit(FGTrafficRecord * rec, FGAirportDynamics *parent,
|
||||||
int stationFreq = 0;
|
int stationFreq = 0;
|
||||||
int taxiFreq = 0;
|
int taxiFreq = 0;
|
||||||
int towerFreq = 0;
|
int towerFreq = 0;
|
||||||
int freqId = 0;
|
|
||||||
string atisInformation;
|
string atisInformation;
|
||||||
string text;
|
string text;
|
||||||
string taxiFreqStr;
|
string taxiFreqStr;
|
||||||
|
@ -133,14 +162,20 @@ void FGATCController::transmit(FGTrafficRecord * rec, FGAirportDynamics *parent,
|
||||||
instructionText = "taxi";
|
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 depApt = rec->getAircraft()->getTrafficRef()->getDepartureAirport();
|
||||||
|
auto arrApt = rec->getAircraft()->getTrafficRef()->getArrivalAirport();
|
||||||
|
|
||||||
if (!depApt) {
|
if (!depApt) {
|
||||||
SG_LOG(SG_ATC, SG_DEV_ALERT, "TrafficRec has empty departure airport, can't transmit");
|
SG_LOG(SG_ATC, SG_DEV_ALERT, "TrafficRec has empty departure airport, can't transmit");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (!arrApt) {
|
||||||
|
SG_LOG(SG_ATC, SG_DEV_ALERT, "TrafficRec has empty arrival airport, can't transmit");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
stationFreq = getFrequency();
|
stationFreq = getFrequency();
|
||||||
taxiFreq = depApt->getDynamics()->getGroundFrequency(2);
|
taxiFreq = depApt->getDynamics()->getGroundFrequency(2);
|
||||||
|
@ -281,16 +316,12 @@ void FGATCController::transmit(FGTrafficRecord * rec, FGAirportDynamics *parent,
|
||||||
text = receiver + ". Holding short runway "
|
text = receiver + ". Holding short runway "
|
||||||
+ activeRunway
|
+ activeRunway
|
||||||
+ ". " + sender + ".";
|
+ ". " + sender + ".";
|
||||||
//text = "test1";
|
|
||||||
SG_LOG(SG_ATC, SG_DEBUG, "1 Currently at leg " << rec->getLeg());
|
|
||||||
break;
|
break;
|
||||||
case MSG_ACKNOWLEDGE_REPORT_RUNWAY_HOLD_SHORT:
|
case MSG_ACKNOWLEDGE_REPORT_RUNWAY_HOLD_SHORT:
|
||||||
activeRunway = rec->getAircraft()->GetFlightPlan()->getRunway();
|
activeRunway = rec->getAircraft()->GetFlightPlan()->getRunway();
|
||||||
text = receiver + " Roger. Holding short runway "
|
text = receiver + " Roger. Holding short runway "
|
||||||
// + activeRunway
|
// + activeRunway
|
||||||
+ ". " + sender + ".";
|
+ ". " + sender + ".";
|
||||||
//text = "test2";
|
|
||||||
SG_LOG(SG_ATC, SG_DEBUG, "2 Currently at leg " << rec->getLeg());
|
|
||||||
break;
|
break;
|
||||||
case MSG_CLEARED_FOR_TAKEOFF:
|
case MSG_CLEARED_FOR_TAKEOFF:
|
||||||
activeRunway = rec->getAircraft()->GetFlightPlan()->getRunway();
|
activeRunway = rec->getAircraft()->GetFlightPlan()->getRunway();
|
||||||
|
@ -300,23 +331,40 @@ void FGATCController::transmit(FGTrafficRecord * rec, FGAirportDynamics *parent,
|
||||||
case MSG_ACKNOWLEDGE_CLEARED_FOR_TAKEOFF:
|
case MSG_ACKNOWLEDGE_CLEARED_FOR_TAKEOFF:
|
||||||
activeRunway = rec->getAircraft()->GetFlightPlan()->getRunway();
|
activeRunway = rec->getAircraft()->GetFlightPlan()->getRunway();
|
||||||
text = receiver + " Roger. Cleared for takeoff runway " + activeRunway + ". " + sender + ".";
|
text = receiver + " Roger. Cleared for takeoff runway " + activeRunway + ". " + sender + ".";
|
||||||
//text = "test2";
|
|
||||||
break;
|
break;
|
||||||
case MSG_SWITCH_TOWER_FREQUENCY:
|
case MSG_SWITCH_TOWER_FREQUENCY:
|
||||||
towerFreqStr = formatATCFrequency3_2(towerFreq);
|
towerFreqStr = formatATCFrequency3_2(towerFreq);
|
||||||
text = receiver + " Contact Tower at " + towerFreqStr + ". " + sender + ".";
|
text = receiver + " Contact Tower at " + towerFreqStr + ". " + sender + ".";
|
||||||
//text = "test3";
|
|
||||||
SG_LOG(SG_ATC, SG_DEBUG, "3 Currently at leg " << rec->getLeg());
|
|
||||||
break;
|
break;
|
||||||
case MSG_ACKNOWLEDGE_SWITCH_TOWER_FREQUENCY:
|
case MSG_ACKNOWLEDGE_SWITCH_TOWER_FREQUENCY:
|
||||||
towerFreqStr = formatATCFrequency3_2(towerFreq);
|
towerFreqStr = formatATCFrequency3_2(towerFreq);
|
||||||
text = receiver + " Roger, switching to tower at " + towerFreqStr + ". " + sender + ".";
|
text = receiver + " Roger, switching to tower at " + towerFreqStr + ". " + sender + ".";
|
||||||
//text = "test4";
|
break;
|
||||||
SG_LOG(SG_ATC, SG_DEBUG, "4 Currently at leg " << rec->getLeg());
|
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;
|
break;
|
||||||
default:
|
default:
|
||||||
//text = "test3";
|
//text = "test3";
|
||||||
text = text + sender + ". Transmitting unknown Message.";
|
text = text + sender + ". Transmitting unknown Message. MsgId " + std::to_string(msgId);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -341,12 +389,10 @@ void FGATCController::transmit(FGTrafficRecord * rec, FGAirportDynamics *parent,
|
||||||
((onBoardRadioFreqI0 == stationFreq)||
|
((onBoardRadioFreqI0 == stationFreq)||
|
||||||
(onBoardRadioFreqI1 == stationFreq))) {
|
(onBoardRadioFreqI1 == stationFreq))) {
|
||||||
if (rec->allowTransmissions()) {
|
if (rec->allowTransmissions()) {
|
||||||
|
|
||||||
if( fgGetBool( "/sim/radio/use-itm-attenuation", false ) ) {
|
if( fgGetBool( "/sim/radio/use-itm-attenuation", false ) ) {
|
||||||
SG_LOG(SG_ATC, SG_DEBUG, "Using ITM radio propagation");
|
SG_LOG(SG_ATC, SG_DEBUG, "Using ITM radio propagation");
|
||||||
FGRadioTransmission* radio = new FGRadioTransmission();
|
FGRadioTransmission* radio = new FGRadioTransmission();
|
||||||
SGGeod sender_pos;
|
SGGeod sender_pos;
|
||||||
double sender_alt_ft, sender_alt;
|
|
||||||
if(ground_to_air) {
|
if(ground_to_air) {
|
||||||
sender_pos = parent->parent()->geod();
|
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)
|
void FGATCController::signOff(int id)
|
||||||
{
|
{
|
||||||
TrafficVectorIterator i = searchActiveTraffic(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());
|
"AI error: Aircraft without traffic record is signing off from " << getName() << " at " << SG_ORIGIN << " list " << activeTraffic.empty());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
SG_LOG(SG_ATC, SG_DEBUG, i->getCallsign() << " (" << i->getId() << ") signing off from " << getName() << "(" << getFrequency() << ")");
|
||||||
|
int oldSize = activeTraffic.size();
|
||||||
activeTraffic.erase(i);
|
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)
|
bool FGATCController::hasInstruction(int id)
|
||||||
|
|
|
@ -39,28 +39,35 @@ namespace ATCMessageState
|
||||||
{
|
{
|
||||||
enum Type
|
enum Type
|
||||||
{
|
{
|
||||||
// 0 = Normal; no action required
|
// 0 = Normal; no action required
|
||||||
NORMAL = 0,
|
NORMAL,
|
||||||
// 1 = "Acknowledge "Hold position
|
// 1 = "Acknowledge "Hold position
|
||||||
ACK_HOLD = 1,
|
ACK_HOLD,
|
||||||
// 2 = "Acknowledge "Resume taxi".
|
// 2 = "Acknowledge "Resume taxi".
|
||||||
ACK_RESUME_TAXI = 2,
|
ACK_RESUME_TAXI,
|
||||||
// 3 = "Issue TaxiClearance"
|
// 3 = "Issue TaxiClearance"
|
||||||
TAXI_CLEARED = 3,
|
TAXI_CLEARED = 3,
|
||||||
// 4 = Acknowledge Taxi Clearance"
|
// 4 = Acknowledge Taxi Clearance"
|
||||||
ACK_TAXI_CLEARED = 4,
|
ACK_TAXI_CLEARED = 4,
|
||||||
// 5 = Post acknowlegde taxiclearance: Start taxiing
|
// 5 = Post acknowlegde taxiclearance: Start taxiing
|
||||||
START_TAXI = 5,
|
START_TAXI = 5,
|
||||||
// 6 = Report runway
|
// 6 = Report runway
|
||||||
REPORT_RUNWAY = 6,
|
REPORT_RUNWAY = 6,
|
||||||
// 7 = Acknowledge report runway
|
// 7 = Acknowledge report runway
|
||||||
ACK_REPORT_RUNWAY = 7,
|
ACK_REPORT_RUNWAY = 7,
|
||||||
// 8 = Switch tower frequency
|
// 8 = Switch tower frequency
|
||||||
SWITCH_TOWER = 8,
|
SWITCH_GROUND_TOWER = 8,
|
||||||
// 9 = Acknowledge switch tower frequency
|
// 9 = Acknowledge switch tower frequency
|
||||||
ACK_SWITCH_TOWER = 9,
|
ACK_SWITCH_GROUND_TOWER = 9,
|
||||||
// 10 = Cleared for takeoff
|
// 10 = Cleared for takeoff
|
||||||
CLEARED_TAKEOFF = 10,
|
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_CLEARED_FOR_TAKEOFF,
|
||||||
MSG_ACKNOWLEDGE_CLEARED_FOR_TAKEOFF,
|
MSG_ACKNOWLEDGE_CLEARED_FOR_TAKEOFF,
|
||||||
MSG_SWITCH_TOWER_FREQUENCY,
|
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;
|
} AtcMsgId;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
@ -135,6 +148,8 @@ public:
|
||||||
FGAIAircraft *aircraft) = 0;
|
FGAIAircraft *aircraft) = 0;
|
||||||
virtual void updateAircraftInformation(int id, SGGeod geod,
|
virtual void updateAircraftInformation(int id, SGGeod geod,
|
||||||
double heading, double speed, double alt, double dt) = 0;
|
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);
|
virtual void signOff(int id);
|
||||||
bool hasInstruction(int id);
|
bool hasInstruction(int id);
|
||||||
|
|
|
@ -98,9 +98,11 @@ void FGApproachController::announcePosition(int id,
|
||||||
rec.setLeg(leg);
|
rec.setLeg(leg);
|
||||||
rec.setCallsign(ref->getCallSign());
|
rec.setCallsign(ref->getCallSign());
|
||||||
rec.setAircraft(ref);
|
rec.setAircraft(ref);
|
||||||
|
rec.setPlannedArrivalTime(intendedRoute->getArrivalTime());
|
||||||
activeTraffic.push_back(rec);
|
activeTraffic.push_back(rec);
|
||||||
} else {
|
} else {
|
||||||
i->setPositionAndHeading(lat, lon, heading, speed, alt);
|
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 heading, double speed, double alt,
|
||||||
double dt)
|
double dt)
|
||||||
{
|
{
|
||||||
|
time_t now = globals->get_time_params()->get_cur_time();
|
||||||
// Search activeTraffic for a record matching our id
|
// Search activeTraffic for a record matching our id
|
||||||
TrafficVectorIterator i = FGATCController::searchActiveTraffic(id);
|
TrafficVectorIterator i = FGATCController::searchActiveTraffic(id);
|
||||||
TrafficVectorIterator current;
|
TrafficVectorIterator current;
|
||||||
|
@ -115,7 +118,7 @@ void FGApproachController::updateAircraftInformation(int id, SGGeod geod,
|
||||||
// update position of the current aircraft
|
// update position of the current aircraft
|
||||||
if (i == activeTraffic.end() || activeTraffic.empty()) {
|
if (i == activeTraffic.end() || activeTraffic.empty()) {
|
||||||
SG_LOG(SG_ATC, SG_ALERT,
|
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 {
|
} else {
|
||||||
i->setPositionAndHeading(geod.getLatitudeDeg(), geod.getLongitudeDeg(), heading, speed, alt);
|
i->setPositionAndHeading(geod.getLatitudeDeg(), geod.getLongitudeDeg(), heading, speed, alt);
|
||||||
current = i;
|
current = i;
|
||||||
|
@ -146,13 +149,42 @@ void FGApproachController::updateAircraftInformation(int id, SGGeod geod,
|
||||||
} else {
|
} else {
|
||||||
current->clearSpeedAdjustment();
|
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);
|
//current->setSpeedAdjustment(current->getAircraft()->getPerformance()->vDescent() + time_diff);
|
||||||
}
|
}
|
||||||
setDt(getDt() + dt);
|
setDt(getDt() + dt);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Periodically check for and remove dead traffic records */
|
/** Periodically check for and remove dead traffic records */
|
||||||
void FGApproachController::update(double dt)
|
void FGApproachController::update(double dt)
|
||||||
{
|
{
|
||||||
FGATCController::eraseDeadTraffic();
|
FGATCController::eraseDeadTraffic();
|
||||||
|
|
|
@ -130,7 +130,7 @@ void FGGroundController::announcePosition(int id,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* The ground network can deal with the following states:
|
* The ground network can deal with the following states:
|
||||||
* 0 = Normal; no action required
|
* 0 = Normal; no action required
|
||||||
* 1 = "Acknowledge "Hold position
|
* 1 = "Acknowledge "Hold position
|
||||||
|
@ -143,35 +143,6 @@ void FGGroundController::announcePosition(int id,
|
||||||
* 8 = Switch tower frequency
|
* 8 = Switch tower frequency
|
||||||
* 9 = Acknowledge 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,
|
void FGGroundController::updateAircraftInformation(int id, SGGeod geod,
|
||||||
double heading, double speed, double alt,
|
double heading, double speed, double alt,
|
||||||
|
@ -221,26 +192,25 @@ void FGGroundController::updateAircraftInformation(int id, SGGeod geod,
|
||||||
if ((now - lastTransmission) > 15) {
|
if ((now - lastTransmission) > 15) {
|
||||||
available = true;
|
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);
|
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);
|
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);
|
current->setState(ATCMessageState::START_TAXI);
|
||||||
}
|
}
|
||||||
if ((state == 5) && available) {
|
if ((state == ATCMessageState::START_TAXI) && available) {
|
||||||
current->setState(ATCMessageState::NORMAL);
|
current->setState(ATCMessageState::NORMAL);
|
||||||
current->getAircraft()->setTaxiClearanceRequest(false);
|
current->getAircraft()->setTaxiClearanceRequest(false);
|
||||||
current->setHoldPosition(false);
|
current->setHoldPosition(false);
|
||||||
available = false;
|
available = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* Scan for a speed adjustment change. Find the nearest aircraft that is in front
|
* 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
|
* 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
|
* 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()) {
|
if( current->getId() == i->getId()) {
|
||||||
continue;
|
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();
|
SGGeod other = i->getPos();
|
||||||
SGGeodesy::inverse(curr, other, course, az2, dist);
|
SGGeodesy::inverse(curr, other, course, az2, dist);
|
||||||
bearing = fabs(heading - course);
|
bearing = fabs(heading - course);
|
||||||
|
@ -394,7 +364,7 @@ void FGGroundController::checkSpeedAdjustment(int id, double lat,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* Check for "Hold position instruction".
|
* Check for "Hold position instruction".
|
||||||
* The hold position should be issued under the following conditions:
|
* 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
|
* 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);
|
"AI error: Trying to access non-existing aircraft in FGGroundNetwork::checkHoldPosition at " << SG_ORIGIN);
|
||||||
}
|
}
|
||||||
current = i;
|
current = i;
|
||||||
if (current->getAircraft()->getTakeOffStatus() == 1) {
|
if (current->getAircraft()->getTakeOffStatus() == AITakeOffStatus::QUEUED) {
|
||||||
current->setHoldPosition(true);
|
current->setHoldPosition(true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (current->getAircraft()->getTakeOffStatus() == 2) {
|
if ((now - lastTransmission) > 15) {
|
||||||
SG_LOG(SG_ATC, SG_DEBUG, current->getAircraft()->getCallSign() << ". Taxi in position and hold");
|
available = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (current->getAircraft()->getTakeOffStatus() == AITakeOffStatus::CLEARED_FOR_TAKEOFF) {
|
||||||
current->setHoldPosition(false);
|
current->setHoldPosition(false);
|
||||||
current->clearSpeedAdjustment();
|
current->clearSpeedAdjustment();
|
||||||
return;
|
return;
|
||||||
|
@ -485,7 +458,7 @@ void FGGroundController::checkHoldPosition(int id, double lat,
|
||||||
if ((now - lastTransmission) > 2) {
|
if ((now - lastTransmission) > 2) {
|
||||||
available = true;
|
available = true;
|
||||||
}
|
}
|
||||||
if (current->getState() == 0) {
|
if (current->getState() == ATCMessageState::NORMAL) {
|
||||||
if ((origStatus != currStatus) && available) {
|
if ((origStatus != currStatus) && available) {
|
||||||
SG_LOG(SG_ATC, SG_DEBUG, "Issuing hold short instruction " << currStatus << " " << available);
|
SG_LOG(SG_ATC, SG_DEBUG, "Issuing hold short instruction " << currStatus << " " << available);
|
||||||
if (currStatus == true) { // No has a hold short instruction
|
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
|
//9 = Acknowledge switch tower frequency
|
||||||
|
|
||||||
//int state = current->getState();
|
//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->setState(ATCMessageState::NORMAL);
|
||||||
current->setHoldPosition(true);
|
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->setState(ATCMessageState::NORMAL);
|
||||||
current->setHoldPosition(false);
|
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");
|
SG_LOG(SG_ATC, SG_DEBUG, "Scheduling " << current->getAircraft()->getCallSign() << " for hold short");
|
||||||
current->setState(ATCMessageState::REPORT_RUNWAY);
|
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;
|
int counter = 0;
|
||||||
|
|
||||||
if (id == target) {
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -641,7 +614,7 @@ static void WorldCoordinate(osg::Matrix& obj_pos, double lat,
|
||||||
0.0, 1.0, 0.0));
|
0.0, 1.0, 0.0));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Draw visible taxi routes */
|
/** Draw visible taxi routes */
|
||||||
void FGGroundController::render(bool visible)
|
void FGGroundController::render(bool visible)
|
||||||
{
|
{
|
||||||
SGMaterialLib *matlib = globals->get_matlib();
|
SGMaterialLib *matlib = globals->get_matlib();
|
||||||
|
|
|
@ -76,9 +76,7 @@ public:
|
||||||
double radius, int leg, FGAIAircraft *aircraft);
|
double radius, int leg, FGAIAircraft *aircraft);
|
||||||
virtual void updateAircraftInformation(int id, SGGeod geod, double heading, double speed, double alt, double dt);
|
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,
|
bool checkForCircularWaits(int id);
|
||||||
AtcMsgDir msgDir);
|
|
||||||
bool checkForCircularWaits(int id);
|
|
||||||
virtual void render(bool);
|
virtual void render(bool);
|
||||||
virtual std::string getName();
|
virtual std::string getName();
|
||||||
virtual void update(double dt);
|
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,
|
void FGStartupController::updateAircraftInformation(int id, SGGeod geod, double heading, double speed, double alt,
|
||||||
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,
|
|
||||||
double dt)
|
double dt)
|
||||||
{
|
{
|
||||||
// Search activeTraffic for a record matching our id
|
// 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();
|
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()));
|
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;
|
available = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
checkTransmissionState(0, now, (startTime + 0 ), i, MSG_ANNOUNCE_ENGINE_START, ATC_AIR_TO_GROUND);
|
if (now >(startTime + 0)) {
|
||||||
checkTransmissionState(1, now, (startTime + 60 ), i, MSG_REQUEST_ENGINE_START, ATC_AIR_TO_GROUND);
|
checkTransmissionState(ATCMessageState::NORMAL, ATCMessageState::NORMAL, i, now, MSG_ANNOUNCE_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();
|
|
||||||
}
|
}
|
||||||
checkTransmissionState(5, now, (startTime + 140), i, MSG_INITIATE_CONTACT, ATC_AIR_TO_GROUND);
|
if (now >(startTime + 60)) {
|
||||||
checkTransmissionState(6, now, (startTime + 150), i, MSG_ACKNOWLEDGE_INITIATE_CONTACT, ATC_GROUND_TO_AIR);
|
checkTransmissionState(ATCMessageState::ACK_HOLD, ATCMessageState::ACK_HOLD, i, now, MSG_REQUEST_ENGINE_START, ATC_AIR_TO_GROUND);
|
||||||
checkTransmissionState(7, now, (startTime + 180), i, MSG_REQUEST_PUSHBACK_CLEARANCE, 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 ((state == 8) && available) {
|
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 (now > startTime + 200) {
|
||||||
if (i->pushBackAllowed()) {
|
if (i->pushBackAllowed()) {
|
||||||
i->allowRepeatedTransmissions();
|
i->allowRepeatedTransmissions();
|
||||||
|
@ -208,7 +186,7 @@ void FGStartupController::updateAircraftInformation(int id, SGGeod geod,
|
||||||
available = false;
|
available = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((state == 9) && available) {
|
if ((state == ATCMessageState::ACK_SWITCH_GROUND_TOWER) && available) {
|
||||||
i->setHoldPosition(false);
|
i->setHoldPosition(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -230,7 +208,6 @@ static void WorldCoordinate(osg::Matrix& obj_pos, double lat,
|
||||||
|
|
||||||
void FGStartupController::render(bool visible)
|
void FGStartupController::render(bool visible)
|
||||||
{
|
{
|
||||||
SG_LOG(SG_ATC, SG_DEBUG, "Rendering startup controller");
|
|
||||||
SGMaterialLib *matlib = globals->get_matlib();
|
SGMaterialLib *matlib = globals->get_matlib();
|
||||||
if (group) {
|
if (group) {
|
||||||
//int nr = ;
|
//int nr = ;
|
||||||
|
@ -245,6 +222,7 @@ void FGStartupController::render(bool visible)
|
||||||
group = 0;
|
group = 0;
|
||||||
}
|
}
|
||||||
if (visible) {
|
if (visible) {
|
||||||
|
SG_LOG(SG_ATC, SG_BULK, "Rendering startup controller");
|
||||||
group = new osg::Group;
|
group = new osg::Group;
|
||||||
FGScenery * local_scenery = globals->get_scenery();
|
FGScenery * local_scenery = globals->get_scenery();
|
||||||
//double elevation_meters = 0.0;
|
//double elevation_meters = 0.0;
|
||||||
|
|
|
@ -61,11 +61,6 @@ public:
|
||||||
virtual void render(bool);
|
virtual void render(bool);
|
||||||
virtual std::string getName();
|
virtual std::string getName();
|
||||||
virtual void update(double dt);
|
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
|
#endif
|
|
@ -96,7 +96,7 @@ void FGTowerController::announcePosition(int id,
|
||||||
rec.setPositionAndHeading(lat, lon, heading, speed, alt);
|
rec.setPositionAndHeading(lat, lon, heading, speed, alt);
|
||||||
rec.setRunway(intendedRoute->getRunway());
|
rec.setRunway(intendedRoute->getRunway());
|
||||||
rec.setLeg(leg);
|
rec.setLeg(leg);
|
||||||
//rec.setCallSign(callsign);
|
rec.setCallsign(ref->getCallSign());
|
||||||
rec.setRadius(radius);
|
rec.setRadius(radius);
|
||||||
rec.setAircraft(ref);
|
rec.setAircraft(ref);
|
||||||
activeTraffic.push_back(rec);
|
activeTraffic.push_back(rec);
|
||||||
|
@ -113,13 +113,19 @@ void FGTowerController::announcePosition(int id,
|
||||||
if (rwy == activeRunways.end()) {
|
if (rwy == activeRunways.end()) {
|
||||||
ActiveRunway aRwy(intendedRoute->getRunway(), id);
|
ActiveRunway aRwy(intendedRoute->getRunway(), id);
|
||||||
aRwy.addToDepartureQueue(ref);
|
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);
|
activeRunways.push_back(aRwy);
|
||||||
rwy = (activeRunways.end()-1);
|
rwy = (activeRunways.end()-1);
|
||||||
} else {
|
} else {
|
||||||
|
time_t now = globals->get_time_params()->get_cur_time();
|
||||||
|
rec.setPlannedArrivalTime(now);
|
||||||
|
rec.setRunwaySlot(rwy->requestTimeSlot(now));
|
||||||
rwy->addToDepartureQueue(ref);
|
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 {
|
} else {
|
||||||
i->setPositionAndHeading(lat, lon, heading, speed, alt);
|
i->setPositionAndHeading(lat, lon, heading, speed, alt);
|
||||||
}
|
}
|
||||||
|
@ -134,6 +140,7 @@ void FGTowerController::updateAircraftInformation(int id, SGGeod geod,
|
||||||
|
|
||||||
setDt(getDt() + dt);
|
setDt(getDt() + dt);
|
||||||
|
|
||||||
|
time_t now = globals->get_time_params()->get_cur_time();
|
||||||
if (i == activeTraffic.end() || (activeTraffic.empty())) {
|
if (i == activeTraffic.end() || (activeTraffic.empty())) {
|
||||||
SG_LOG(SG_ATC, SG_ALERT,
|
SG_LOG(SG_ATC, SG_ALERT,
|
||||||
"AI error: updating aircraft without traffic record at " <<
|
"AI error: updating aircraft without traffic record at " <<
|
||||||
|
@ -184,30 +191,43 @@ void FGTowerController::updateAircraftInformation(int id, SGGeod geod,
|
||||||
if (ac->getTakeOffStatus() == AITakeOffStatus::QUEUED) {
|
if (ac->getTakeOffStatus() == AITakeOffStatus::QUEUED) {
|
||||||
// transmit takeoff clearance
|
// transmit takeoff clearance
|
||||||
ac->setTakeOffStatus(AITakeOffStatus::CLEARED_FOR_TAKEOFF);
|
ac->setTakeOffStatus(AITakeOffStatus::CLEARED_FOR_TAKEOFF);
|
||||||
transmit(&(*i), &(*parent), MSG_CLEARED_FOR_TAKEOFF, ATC_GROUND_TO_AIR, true);
|
TrafficVectorIterator first = searchActiveTraffic(ac->getID());
|
||||||
i->setState(ATCMessageState::CLEARED_TAKEOFF);
|
//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
|
//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);
|
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 {
|
} else {
|
||||||
current.setHoldPosition(true);
|
current.setHoldPosition(true);
|
||||||
|
SG_LOG(SG_ATC, SG_BULK,
|
||||||
|
current.getCallsign() << "| Waiting for " << (current.getRunwaySlot() - now) << " seconds");
|
||||||
}
|
}
|
||||||
int clearanceId = rwy->getCleared();
|
int clearanceId = rwy->getCleared();
|
||||||
if (clearanceId) {
|
if (clearanceId) {
|
||||||
if (id == 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);
|
current.setHoldPosition(false);
|
||||||
} else {
|
} 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 {
|
} else {
|
||||||
if (current.getAircraft() == rwy->getFirstAircraftInDepartureQueue()) {
|
if (current.getAircraft() == rwy->getFirstAircraftInDepartureQueue()) {
|
||||||
SG_LOG(SG_ATC, SG_BULK,
|
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);
|
rwy->setCleared(id);
|
||||||
auto ac = rwy->getFirstOfStatus(1);
|
auto ac = rwy->getFirstOfStatus(AITakeOffStatus::QUEUED);
|
||||||
if (ac) {
|
if (ac) {
|
||||||
ac->setTakeOffStatus(AITakeOffStatus::QUEUED);
|
ac->setTakeOffStatus(AITakeOffStatus::QUEUED);
|
||||||
// transmit takeoff clearacne? But why twice?
|
// transmit takeoff clearacne? But why twice?
|
||||||
|
@ -241,9 +261,8 @@ void FGTowerController::signOff(int id)
|
||||||
});
|
});
|
||||||
|
|
||||||
if (runwayIt != activeRunways.end()) {
|
if (runwayIt != activeRunways.end()) {
|
||||||
SG_LOG(SG_ATC, SG_BULK, "Cleared " << id << " from " << runwayIt->getRunwayName() );
|
SG_LOG(SG_ATC, SG_BULK, i->getCallsign() << "|Cleared " << id << " from " << runwayIt->getRunwayName() << " cleared " << runwayIt->getCleared() );
|
||||||
runwayIt->setCleared(0);
|
runwayIt->removeFromDepartureQueue(id);
|
||||||
runwayIt->updateDepartureQueue();
|
|
||||||
} else {
|
} else {
|
||||||
SG_LOG(SG_ATC, SG_ALERT,
|
SG_LOG(SG_ATC, SG_ALERT,
|
||||||
"AI error: Attempting to erase non-existing runway clearance record in FGTowerController::signoff at " << SG_ORIGIN);
|
"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() {
|
string FGTowerController::getName() {
|
||||||
return string(parent->getId() + "-tower");
|
return string(parent->parent()->getName() + "-tower");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FGTowerController::update(double dt)
|
void FGTowerController::update(double dt)
|
||||||
{
|
{
|
||||||
FGATCController::eraseDeadTraffic();
|
FGATCController::eraseDeadTraffic();
|
||||||
|
|
|
@ -59,9 +59,9 @@ FGATCManager::~FGATCManager() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Sets up ATC subsystem parts depending on other subsystems
|
* Sets up ATC subsystem parts depending on other subsystems
|
||||||
Override of SGSubsystem::postinit()
|
* Override of SGSubsystem::postinit()
|
||||||
Will set private boolean flag "initSucceeded" to true upon conclusion
|
* Will set private boolean flag "initSucceeded" to true upon conclusion
|
||||||
*/
|
*/
|
||||||
void FGATCManager::postinit()
|
void FGATCManager::postinit()
|
||||||
{
|
{
|
||||||
|
|
|
@ -67,12 +67,23 @@ ActiveRunway::ActiveRunway(const std::string& r, int cc) :
|
||||||
distanceToFinal = 6.0 * SG_NM_TO_METER;
|
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()
|
void ActiveRunway::updateDepartureQueue()
|
||||||
{
|
{
|
||||||
departureQueue.erase(departureQueue.begin());
|
departureQueue.erase(departureQueue.begin());
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* Fetch next slot for the active runway
|
* Fetch next slot for the active runway
|
||||||
* @param eta time of slot requested
|
* @param eta time of slot requested
|
||||||
* @return newEta: next slot available; starts at eta paramater
|
* @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 the aircraft is the first arrival, add to the vector and return eta directly
|
||||||
if (estimatedArrivalTimes.empty()) {
|
if (estimatedArrivalTimes.empty()) {
|
||||||
estimatedArrivalTimes.push_back(eta);
|
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;
|
return eta;
|
||||||
} else {
|
} else {
|
||||||
// First check the already assigned slots to see where we need to fit the flight in
|
// First check the already assigned slots to see where we need to fit the flight in
|
||||||
TimeVectorIterator i = estimatedArrivalTimes.begin();
|
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?
|
// is this needed - just a debug output?
|
||||||
for (i = estimatedArrivalTimes.begin();
|
for (i = estimatedArrivalTimes.begin();
|
||||||
|
@ -110,7 +121,7 @@ time_t ActiveRunway::requestTimeSlot(time_t eta)
|
||||||
if ((eta + separation) < (*i)) {
|
if ((eta + separation) < (*i)) {
|
||||||
newEta = eta;
|
newEta = eta;
|
||||||
SG_LOG(SG_ATC, SG_BULK, "Storing at beginning");
|
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);
|
slotHousekeeping(newEta);
|
||||||
return newEta;
|
return newEta;
|
||||||
}
|
}
|
||||||
|
@ -128,7 +139,7 @@ time_t ActiveRunway::requestTimeSlot(time_t eta)
|
||||||
newEta = (*i) + separation;
|
newEta = (*i) + separation;
|
||||||
SG_LOG(SG_ATC, SG_BULK, "Storing at end + 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);
|
slotHousekeeping(newEta);
|
||||||
return newEta;
|
return newEta;
|
||||||
} else {
|
} 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()
|
void ActiveRunway::printDepartureQueue()
|
||||||
{
|
{
|
||||||
SG_LOG(SG_ATC, SG_DEBUG, "Departure queue for " << rwy << ": ");
|
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
|
SGSharedPtr<FGAIAircraft>ActiveRunway::getFirstOfStatus(int stat) const
|
||||||
{
|
{
|
||||||
auto it = std::find_if(departureQueue.begin(), departureQueue.end(), [stat](const SGSharedPtr<FGAIAircraft>& acft) {
|
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 FGTrafficRecord::checkPositionAndIntentions(FGTrafficRecord & other)
|
||||||
{
|
{
|
||||||
bool result = false;
|
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() ) {
|
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);
|
SG_LOG(SG_ATC, SG_BULK, getCallsign() << "| Check Position and intentions: " << other.getCallsign() << " we are on the same taxiway; Index = " << currentPos);
|
||||||
result = true;
|
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())
|
// 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");
|
// SG_LOG(SG_ATC, SG_BULK, "Check Position and intentions: current matches other.intentions");
|
||||||
// result = true;
|
// result = true;
|
||||||
// }
|
// }
|
||||||
else if (! intentions.empty()) {
|
else if (!intentions.empty()) {
|
||||||
SG_LOG(SG_ATC, SG_BULK, getCallsign() << "|Itentions " << intentions.size());
|
SG_LOG(SG_ATC, SG_BULK, getCallsign() << "| Itentions Size " << intentions.size());
|
||||||
intVecIterator i = intentions.begin();
|
intVecIterator i = intentions.begin();
|
||||||
//while (!((i == intentions.end()) || ((*i) == other.currentPos)))
|
//while (!((i == intentions.end()) || ((*i) == other.currentPos)))
|
||||||
while (i != intentions.end()) {
|
while (i != intentions.end()) {
|
||||||
|
@ -343,7 +358,13 @@ bool FGTrafficRecord::checkPositionAndIntentions(FGTrafficRecord & other)
|
||||||
}
|
}
|
||||||
if (i != intentions.end()) {
|
if (i != intentions.end()) {
|
||||||
SG_LOG(SG_ATC, SG_BULK, getCallsign() << "| Check Position and intentions: " << other.getCallsign()<< " matches Index = " << (*i));
|
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;
|
return result;
|
||||||
|
|
|
@ -64,6 +64,7 @@ class FGATCInstruction
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
bool holdPattern;
|
bool holdPattern;
|
||||||
|
int requestedArrivalTime;
|
||||||
bool holdPosition;
|
bool holdPosition;
|
||||||
bool changeSpeed;
|
bool changeSpeed;
|
||||||
bool changeHeading;
|
bool changeHeading;
|
||||||
|
@ -80,6 +81,12 @@ public:
|
||||||
bool getHoldPattern () const {
|
bool getHoldPattern () const {
|
||||||
return holdPattern;
|
return holdPattern;
|
||||||
};
|
};
|
||||||
|
void setRunwaySlot (int val) {
|
||||||
|
requestedArrivalTime = val;
|
||||||
|
};
|
||||||
|
int getRunwaySlot () const {
|
||||||
|
return requestedArrivalTime;
|
||||||
|
};
|
||||||
bool getHoldPosition () const {
|
bool getHoldPosition () const {
|
||||||
return holdPosition;
|
return holdPosition;
|
||||||
};
|
};
|
||||||
|
@ -156,6 +163,7 @@ private:
|
||||||
bool allowTransmission;
|
bool allowTransmission;
|
||||||
bool allowPushback;
|
bool allowPushback;
|
||||||
int priority;
|
int priority;
|
||||||
|
int plannedArrivalTime;
|
||||||
time_t timer;
|
time_t timer;
|
||||||
intVec intentions;
|
intVec intentions;
|
||||||
FGATCInstruction instruction;
|
FGATCInstruction instruction;
|
||||||
|
@ -186,9 +194,15 @@ public:
|
||||||
int getId() const {
|
int getId() const {
|
||||||
return id;
|
return id;
|
||||||
};
|
};
|
||||||
|
/**
|
||||||
|
* Return the current ATC State of type @see ATCMessageState
|
||||||
|
*/
|
||||||
int getState() const {
|
int getState() const {
|
||||||
return state;
|
return state;
|
||||||
};
|
};
|
||||||
|
/**
|
||||||
|
* Set the current ATC State of type @see ATCMessageState
|
||||||
|
*/
|
||||||
void setState(int s) {
|
void setState(int s) {
|
||||||
state = s;
|
state = s;
|
||||||
}
|
}
|
||||||
|
@ -212,7 +226,23 @@ public:
|
||||||
bool getSpeedAdjustment() const {
|
bool getSpeedAdjustment() const {
|
||||||
return instruction.getChangeSpeed();
|
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() {
|
SGGeod getPos() {
|
||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
|
@ -251,7 +281,6 @@ public:
|
||||||
void setHoldPosition (bool inst) {
|
void setHoldPosition (bool inst) {
|
||||||
instruction.setHoldPosition(inst);
|
instruction.setHoldPosition(inst);
|
||||||
};
|
};
|
||||||
|
|
||||||
void setWaitsForId(int id) {
|
void setWaitsForId(int id) {
|
||||||
waitsForId = id;
|
waitsForId = id;
|
||||||
};
|
};
|
||||||
|
@ -368,6 +397,8 @@ public:
|
||||||
|
|
||||||
SGSharedPtr<FGAIAircraft> getFirstOfStatus(int stat) const;
|
SGSharedPtr<FGAIAircraft> getFirstOfStatus(int stat) const;
|
||||||
|
|
||||||
|
void removeFromDepartureQueue(int id);
|
||||||
|
|
||||||
void updateDepartureQueue();
|
void updateDepartureQueue();
|
||||||
|
|
||||||
void printDepartureQueue();
|
void printDepartureQueue();
|
||||||
|
|
|
@ -1031,7 +1031,7 @@ FGAIAircraft * TrafficTests::flyAI(SGSharedPtr<FGAIAircraft> aiAircraft, std::st
|
||||||
int startSpeed = aiAircraft->GetFlightPlan()->getCurrentWaypoint()->getSpeed();
|
int startSpeed = aiAircraft->GetFlightPlan()->getCurrentWaypoint()->getSpeed();
|
||||||
aiAircraft->AccelTo(startSpeed);
|
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);
|
CPPUNIT_ASSERT_EQUAL(aiAircraft->GetFlightPlan()->isValidPlan(), true);
|
||||||
if (!aiAircraft->getDie()) {
|
if (!aiAircraft->getDie()) {
|
||||||
// collect position
|
// collect position
|
||||||
|
@ -1072,7 +1072,7 @@ FGAIAircraft * TrafficTests::flyAI(SGSharedPtr<FGAIAircraft> aiAircraft, std::st
|
||||||
aiAircraft->dumpCSV(csvFile, lineIndex++);
|
aiAircraft->dumpCSV(csvFile, lineIndex++);
|
||||||
// A flight without loops should never reach 400°
|
// A flight without loops should never reach 400°
|
||||||
CPPUNIT_ASSERT_LESSEQUAL(400.0, headingSum);
|
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);
|
CPPUNIT_ASSERT_MESSAGE( "Aircraft has not completed test in time.", i < 3000000);
|
||||||
// Arrived at a parking
|
// Arrived at a parking
|
||||||
int beforeNextDepTime = aiAircraft->getTrafficRef()->getDepartureTime() - 30;
|
int beforeNextDepTime = aiAircraft->getTrafficRef()->getDepartureTime() - 30;
|
||||||
|
|
Loading…
Reference in a new issue