1
0
Fork 0
* Added Messages for Takeoff
* Added Messages for Hold & Holdpatterns
* More enums instead of Magic Numbers
This commit is contained in:
portree_kid 2022-12-29 22:21:23 +01:00
parent 11eca7825d
commit 3667e5de3c
16 changed files with 400 additions and 252 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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