* Some tweaks to the traffic scheduling algorithm.
* Misc cleanup.
}
if (trafficRef) {
//cerr << "Tracking callsign : \"" << fgGetString("/ai/track-callsign") << "\"" << endl;
-/* if (trafficRef->getCallSign() == fgGetString("/ai/track-callsign")) {
+ if (trafficRef->getCallSign() == fgGetString("/ai/track-callsign")) {
cerr << trafficRef->getCallSign() << " " << tgt_altitude_ft << " " << _getSpeed() << " "
- << _getAltitude() << " "<< _getLatitude() << " " << _getLongitude() << " " << dist_to_go << " " << lead_dist << " " << curr->name << " " << vs << " " << tgt_vs << " " << bearing << " " << minBearing << " " << speedFraction << endl;
- }*/
+ << _getAltitude() << " "<< _getLatitude() << " " << _getLongitude() << " " << dist_to_go << " " << lead_dist << " " << curr->getName() << " " << vs << " " << tgt_vs << " " << bearing << " " << minBearing << " " << speedFraction << " " << invisible << endl;
+ }
}
if ((dist_to_go < lead_dist) || (bearing > (minBearing * 1.1))) {
minBearing = 360;
double distanceCovered = descentSpeed * descentTimeNeeded;
//cerr << "Tracking : " << fgGetString("/ai/track-callsign");
- if (trafficRef->getCallSign() == fgGetString("/ai/track-callsign")) {
- cerr << "Checking for end of cruise stage for :" << trafficRef->getCallSign() << endl;
- cerr << "Descent rate : " << descentRate << endl;
- cerr << "Descent speed : " << descentSpeed << endl;
- cerr << "VerticalDistance : " << verticalDistance << ". Altitude : " << altitude_ft << ". Elevation " << trafficRef->getArrivalAirport()->getElevation() << endl;
- cerr << "DecentTimeNeeded : " << descentTimeNeeded << endl;
- cerr << "DistanceCovered : " << distanceCovered << endl;
- }
+// if (trafficRef->getCallSign() == fgGetString("/ai/track-callsign")) {
+// cerr << "Checking for end of cruise stage for :" << trafficRef->getCallSign() << endl;
+// cerr << "Descent rate : " << descentRate << endl;
+// cerr << "Descent speed : " << descentSpeed << endl;
+// cerr << "VerticalDistance : " << verticalDistance << ". Altitude : " << altitude_ft << ". Elevation " << trafficRef->getArrivalAirport()->getElevation() << endl;
+// cerr << "DecentTimeNeeded : " << descentTimeNeeded << endl;
+// cerr << "DistanceCovered : " << distanceCovered << endl;
+// }
//cerr << "Distance = " << distance << endl;
distance = distanceCovered;
if (dist < distanceCovered) {
- if (trafficRef->getCallSign() == fgGetString("/ai/track-callsign")) {
- //exit(1);
- }
+// if (trafficRef->getCallSign() == fgGetString("/ai/track-callsign")) {
+// //exit(1);
+// }
return true;
} else {
return false;
time_t ete = tracklength / ((speed * SG_NM_TO_METER) / 3600.0);
time_t secondsToGo = arrivalTime - now;
- if (trafficRef->getCallSign() == fgGetString("/ai/track-callsign")) {
- cerr << "Checking arrival time: ete " << ete << ". Time to go : " << secondsToGo << ". Track length = " << tracklength << endl;
- }
+// if (trafficRef->getCallSign() == fgGetString("/ai/track-callsign")) {
+// cerr << "Checking arrival time: ete " << ete << ". Time to go : " << secondsToGo << ". Track length = " << tracklength << endl;
+// }
return (ete - secondsToGo); // Positive when we're too slow...
}
case 1:
retVal = createPushBack(ac, firstFlight, dep, latitude, longitude,
radius, fltType, aircraftType, airline);
+ // Pregenerate the
+ if (retVal) {
+ waypoints.back()->setName( waypoints.back()->getName() + string("legend"));
+ retVal = createTakeoffTaxi(ac, false, dep, radius, fltType, aircraftType, airline);
+ }
break;
case 2:
retVal = createTakeoffTaxi(ac, firstFlight, dep, radius, fltType,
//cerr << "Adding groundnetWork to the scenegraph::update" << endl;
prevController = controller;
}
- //globals->get_scenery()->get_scene_graph()->addChild(node);
+ for (AtcVecIterator atc = activeStations.begin(); atc != activeStations.end(); atc++) {
+ (*atc)->update(time);
+ }
}
TimeVectorIterator i = estimatedArrivalTimes.begin();
//cerr << "Checking eta slots " << eta << ": " << endl;
for (i = estimatedArrivalTimes.begin();
- i != estimatedArrivalTimes.end(); i++) {
+ i != estimatedArrivalTimes.end(); i++) {
//cerr << "Stored time : " << (*i) << endl;
}
i = estimatedArrivalTimes.begin();
* FGTrafficRecord
**************************************************************************/
FGTrafficRecord::FGTrafficRecord():
-id(0), waitsForId(0),
-currentPos(0),
-leg(0),
-frequencyId(0),
-state(0),
-allowTransmission(true),
-latitude(0), longitude(0), heading(0), speed(0), altitude(0), radius(0)
+ id(0), waitsForId(0),
+ currentPos(0),
+ leg(0),
+ frequencyId(0),
+ state(0),
+ allowTransmission(true),
+ allowPushback(true),
+ priority(0),
+ latitude(0), longitude(0), heading(0), speed(0), altitude(0), radius(0)
{
}
void FGTrafficRecord::setPositionAndIntentions(int pos,
- FGAIFlightPlan * route)
+ FGAIFlightPlan * route)
{
currentPos = pos;
"Error in FGTrafficRecord::setPositionAndIntentions");
//cerr << "Pos : " << pos << " Curr " << *(intentions.begin()) << endl;
for (intVecIterator i = intentions.begin();
- i != intentions.end(); i++) {
+ i != intentions.end(); i++) {
//cerr << (*i) << " ";
}
//cerr << endl;
//exit(1);
}
/**
- * Check if another aircraft is ahead of the current one, and on the same
+ * Check if another aircraft is ahead of the current one, and on the same
* return true / false is the is/isn't the case.
*
****************************************************************************/
//cerr << callsign << ": Check Position and intentions: we are on the same taxiway" << other.callsign << "Index = " << currentPos << endl;
result = true;
}
- // else if (other.intentions.size())
+ // else if (other.intentions.size())
// {
// cerr << "Start check 2" << endl;
- // intVecIterator i = other.intentions.begin();
+ // intVecIterator i = other.intentions.begin();
// while (!((i == other.intentions.end()) || ((*i) == currentPos)))
// i++;
// if (i != other.intentions.end()) {
}
void FGTrafficRecord::setPositionAndHeading(double lat, double lon,
- double hdg, double spd,
- double alt)
+ double hdg, double spd,
+ double alt)
{
latitude = lat;
longitude = lon;
FGTrafficRecord & other)
{
if (checkPositionAndIntentions(other)
- || (other.checkPositionAndIntentions(*this)))
+ || (other.checkPositionAndIntentions(*this)))
return -1;
intVecIterator i, j;
int currentTargetNode = 0, otherTargetNode = 0;
if (currentPos > 0)
- currentTargetNode = net->findSegment(currentPos)->getEnd()->getIndex(); // OKAY,...
+ currentTargetNode = net->findSegment(currentPos)->getEnd()->getIndex(); // OKAY,...
if (other.currentPos > 0)
otherTargetNode = net->findSegment(other.currentPos)->getEnd()->getIndex(); // OKAY,...
if ((currentTargetNode == otherTargetNode) && currentTargetNode > 0)
for (i = intentions.begin(); i != intentions.end(); i++) {
if ((*i) > 0) {
if ((currentTargetNode ==
- net->findSegment(*i)->getEnd()->getIndex())) {
+ net->findSegment(*i)->getEnd()->getIndex())) {
//cerr << "Current crosses at " << currentTargetNode <<endl;
return currentTargetNode;
}
}
if (other.intentions.size()) {
for (i = other.intentions.begin(); i != other.intentions.end();
- i++) {
+ i++) {
if ((*i) > 0) {
if (otherTargetNode ==
- net->findSegment(*i)->getEnd()->getIndex()) {
+ net->findSegment(*i)->getEnd()->getIndex()) {
//cerr << "Other crosses at " << currentTargetNode <<endl;
return otherTargetNode;
}
if (intentions.size() && other.intentions.size()) {
for (i = intentions.begin(); i != intentions.end(); i++) {
for (j = other.intentions.begin(); j != other.intentions.end();
- j++) {
+ j++) {
//cerr << "finding segment " << *i << " and " << *j << endl;
if (((*i) > 0) && ((*j) > 0)) {
currentTargetNode =
return true;
if (other.intentions.size()) {
for (intVecIterator i = other.intentions.begin();
- i != other.intentions.end(); i++) {
+ i != other.intentions.end(); i++) {
if (*i > 0) {
othernode = net->findSegment(*i)->getEnd()->getIndex();
if ((node == othernode) && (node > -1))
// {
// for (intVecIterator i = intentions.begin(); i != intentions.end(); i++)
// {
- // if (*i > 0)
+ // if (*i > 0)
// {
// node = net->findSegment(*i)->getEnd()->getIndex();
// if ((node == othernode) && (node > -1))
}
for (intVecIterator i = intentions.begin(); i != intentions.end();
- i++) {
+ i++) {
if ((opp = net->findSegment(other.currentPos)->opposite())) {
if ((*i) > 0)
if (opp->getIndex() ==
- net->findSegment(*i)->getIndex()) {
+ net->findSegment(*i)->getIndex()) {
if (net->findSegment(*i)->getStart()->getIndex() ==
- node) {
+ node) {
{
//cerr << "Found the node " << node << endl;
return true;
}
if (other.intentions.size()) {
for (intVecIterator j = other.intentions.begin();
- j != other.intentions.end(); j++) {
+ j != other.intentions.end(); j++) {
// cerr << "Current segment 1 " << (*i) << endl;
if ((*i) > 0) {
if ((opp = net->findSegment(*i)->opposite())) {
if (opp->getIndex() ==
- net->findSegment(*j)->getIndex()) {
+ net->findSegment(*j)->getIndex()) {
//cerr << "Nodes " << net->findSegment(*i)->getIndex()
// << " and " << net->findSegment(*j)->getIndex()
// << " are opposites " << endl;
if (net->findSegment(*i)->getStart()->
- getIndex() == node) {
+ getIndex() == node) {
{
//cerr << "Found the node " << node << endl;
return true;
return false;
}
+bool FGTrafficRecord::isActive(int margin)
+{
+ time_t now = time(NULL) + fgGetLong("/sim/time/warp");
+ time_t deptime = aircraft->getTrafficRef()->getDepartureTime();
+ return ((now + margin) > deptime);
+}
+
+
void FGTrafficRecord::setSpeedAdjustment(double spd)
{
instruction.setChangeSpeed(true);
bool FGTrafficRecord::pushBackAllowed()
{
- // With the user ATC / AI integration, checking whether the user's aircraft is near no longer works, because
- // this will effectively block the user's aircraft itself from receiving pushback clearance.
- // So, what can we do?
- /*
- double course, az2, dist;
- SGGeod curr(SGGeod::fromDegM(getLongitude(),
- getLatitude(), getAltitude()));
-
- double userLatitude = fgGetDouble("/position/latitude-deg");
- double userLongitude = fgGetDouble("/position/longitude-deg");
- SGGeod user(SGGeod::fromDeg(userLongitude, userLatitude));
- SGGeodesy::inverse(curr, user, course, az2, dist);
- //cerr << "Distance to user : " << dist << endl;
- return (dist > 250);
- */
-
-
- // In essence, we should check whether the pusbback route itself, as well as the associcated
- // taxiways near the pushback point are free of traffic.
- // To do so, we need to
- return true;
+ return allowPushback;
}
+
/***************************************************************************
* FGATCInstruction
*
FGATCController::~FGATCController()
{
- //cerr << "running FGATController destructor" << endl;
+ //cerr << "running FGATController destructor" << endl;
}
string FGATCController::getGateName(FGAIAircraft * ref)
return ref->atGate();
}
-bool FGATCController::isUserAircraft(FGAIAircraft* ac)
-{
- return (ac->getCallSign() == fgGetString("/sim/multiplay/callsign")) ? true : false;
+bool FGATCController::isUserAircraft(FGAIAircraft* ac)
+{
+ return (ac->getCallSign() == fgGetString("/sim/multiplay/callsign")) ? true : false;
};
void FGATCController::transmit(FGTrafficRecord * rec, AtcMsgId msgId,
taxiFreq =
rec->getAircraft()->getTrafficRef()->getDepartureAirport()->
getDynamics()->getGroundFrequency(2);
- towerFreq =
+ towerFreq =
rec->getAircraft()->getTrafficRef()->getDepartureAirport()->
getDynamics()->getTowerFrequency(2);
receiver =
getRunwayClassFromTrafficType(fltType);
rec->getAircraft()->getTrafficRef()->getDepartureAirport()->
- getDynamics()->getActiveRunway(rwyClass, 1, activeRunway,
- heading);
+ getDynamics()->getActiveRunway(rwyClass, 1, activeRunway,
+ heading);
rec->getAircraft()->GetFlightPlan()->setRunway(activeRunway);
fp = rec->getAircraft()->getTrafficRef()->getDepartureAirport()->
- getDynamics()->getSID(activeRunway, heading);
+ getDynamics()->getSID(activeRunway, heading);
rec->getAircraft()->GetFlightPlan()->setSID(fp);
if (fp) {
SID = fp->getName() + " departure";
case MSG_REPORT_RUNWAY_HOLD_SHORT:
activeRunway = rec->getAircraft()->GetFlightPlan()->getRunway();
//activeRunway = "test";
- text = receiver + ". Holding short runway "
- + activeRunway
- + ". " + sender;
+ text = receiver + ". Holding short runway "
+ + activeRunway
+ + ". " + sender;
//text = "test1";
//cerr << "1 Currently at leg " << rec->getLeg() << endl;
break;
case MSG_ACKNOWLEDGE_REPORT_RUNWAY_HOLD_SHORT:
activeRunway = rec->getAircraft()->GetFlightPlan()->getRunway();
- text = receiver + "Roger. Holding short runway "
- // + activeRunway
- + ". " + sender;
+ text = receiver + "Roger. Holding short runway "
+ // + activeRunway
+ + ". " + sender;
//text = "test2";
//cerr << "2 Currently at leg " << rec->getLeg() << endl;
break;
// the relevant frequency.
// Note that distance attenuation is currently not yet implemented
if ((onBoardRadioFreqI0 == stationFreq)
- || (onBoardRadioFreqI1 == stationFreq)) {
+ || (onBoardRadioFreqI1 == stationFreq)) {
if (rec->allowTransmissions()) {
fgSetString("/sim/messages/atc", text.c_str());
}
}
// TODO: Set transponder codes according to real-world routes.
-// The current version just returns a random string of four octal numbers.
+// The current version just returns a random string of four octal numbers.
string FGATCController::genTransponderCode(string fltRules)
{
if (fltRules == "VFR") {
}
}
-void FGATCController::init()
+void FGATCController::init()
{
- if (!initialized) {
- FGATCManager *mgr = (FGATCManager*) globals->get_subsystem("ATC");
- mgr->addController(this);
- initialized = true;
+ if (!initialized) {
+ FGATCManager *mgr = (FGATCManager*) globals->get_subsystem("ATC");
+ mgr->addController(this);
+ initialized = true;
}
}
*
**************************************************************************/
FGTowerController::FGTowerController(FGAirportDynamics *par) :
-FGATCController()
+ FGATCController()
{
parent = par;
}
-//
+//
void FGTowerController::announcePosition(int id,
- FGAIFlightPlan * intendedRoute,
- int currentPosition, double lat,
- double lon, double heading,
- double speed, double alt,
- double radius, int leg,
- FGAIAircraft * ref)
+ FGAIFlightPlan * intendedRoute,
+ int currentPosition, double lat,
+ double lon, double heading,
+ double speed, double alt,
+ double radius, int leg,
+ FGAIAircraft * ref)
{
init();
TrafficVectorIterator i = activeTraffic.begin();
rec.setRadius(radius);
rec.setAircraft(ref);
activeTraffic.push_back(rec);
- // Don't just schedule the aircraft for the tower controller, also assign if to the correct active runway.
+ // Don't just schedule the aircraft for the tower controller, also assign if to the correct active runway.
ActiveRunwayVecIterator rwy = activeRunways.begin();
if (activeRunways.size()) {
while (rwy != activeRunways.end()) {
}
void FGTowerController::updateAircraftInformation(int id, double lat, double lon,
- double heading, double speed, double alt,
- double dt)
+ double heading, double speed, double alt,
+ double dt)
{
TrafficVectorIterator i = activeTraffic.begin();
// Search whether the current id has an entry
// see if we already have a clearance record for the currently active runway
// NOTE: dd. 2011-08-07: Because the active runway has been constructed in the announcePosition function, we may safely assume that is
- // already exists here. So, we can simplify the current code.
+ // already exists here. So, we can simplify the current code.
ActiveRunwayVecIterator rwy = activeRunways.begin();
while (rwy != activeRunways.end()) {
if (rwy->getRunwayName() == current->getRunway()) {
rwy->setCleared(id);
}
}
+ } else {
+
}
}
// NOTE:
// IF WE MAKE TRAFFICRECORD A MEMBER OF THE BASE CLASS
-// THE FOLLOWING THREE FUNCTIONS: SIGNOFF, HAS INSTRUCTION AND GETINSTRUCTION CAN
+// THE FOLLOWING THREE FUNCTIONS: SIGNOFF, HAS INSTRUCTION AND GETINSTRUCTION CAN
// BECOME DEVIRTUALIZED AND BE A MEMBER OF THE BASE ATCCONTROLLER CLASS
// WHICH WOULD SIMPLIFY CODE MAINTENANCE.
// Note that this function is probably obsolete
return string(parent->getId() + "-tower");
}
+void FGTowerController::update(double dt)
+{
+
+}
+
/***************************************************************************
*
**************************************************************************/
FGStartupController::FGStartupController(FGAirportDynamics *par):
- FGATCController()
+ FGATCController()
{
parent = par;
}
void FGStartupController::announcePosition(int id,
- FGAIFlightPlan * intendedRoute,
- int currentPosition, double lat,
- double lon, double heading,
- double speed, double alt,
- double radius, int leg,
- FGAIAircraft * ref)
+ FGAIFlightPlan * intendedRoute,
+ int currentPosition, double lat,
+ double lon, double heading,
+ double speed, double alt,
+ double radius, int leg,
+ FGAIAircraft * ref)
{
init();
TrafficVectorIterator i = activeTraffic.begin();
// NOTE:
// IF WE MAKE TRAFFICRECORD A MEMBER OF THE BASE CLASS
-// THE FOLLOWING THREE FUNCTIONS: SIGNOFF, HAS INSTRUCTION AND GETINSTRUCTION CAN
+// THE FOLLOWING THREE FUNCTIONS: SIGNOFF, HAS INSTRUCTION AND GETINSTRUCTION CAN
// BECOME DEVIRTUALIZED AND BE A MEMBER OF THE BASE ATCCONTROLLER CLASS
// WHICH WOULD SIMPLIFY CODE MAINTENANCE.
// Note that this function is probably obsolete
}
bool FGStartupController::checkTransmissionState(int st, time_t now, time_t startTime, TrafficVectorIterator i, AtcMsgId msgId,
- AtcMsgDir msgDir)
+ AtcMsgDir msgDir)
{
int state = i->getState();
if ((state == st) && available) {
if ((msgDir == ATC_AIR_TO_GROUND) && isUserAircraft(i->getAircraft())) {
-
+
//cerr << "Checking state " << st << " for " << i->getAircraft()->getCallSign() << endl;
static 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);
- //cerr << "Selected transmission message " << n << endl;
- FGATCDialogNew::instance()->removeEntry(1);
+ // PopupCallback(n);
+ //cerr << "Selected transmission message " << n << endl;
+ FGATCDialogNew::instance()->removeEntry(1);
} else {
//cerr << "creading message for " << i->getAircraft()->getCallSign() << endl;
transmit(&(*i), msgId, msgDir, false);
}
void FGStartupController::updateAircraftInformation(int id, double lat, double lon,
- double heading, double speed, double alt,
- double dt)
+ double heading, double speed, double alt,
+ double dt)
{
TrafficVectorIterator i = activeTraffic.begin();
// Search search if the current id has an entry
int state = i->getState();
- // The user controlled aircraft should have crased here, because it doesn't have a traffic reference.
+ // The user controlled aircraft should have crased here, because it doesn't have a traffic reference.
// NOTE: if we create a traffic schedule for the user aircraft, we can use this to plan a flight.
time_t startTime = i->getAircraft()->getTrafficRef()->getDepartureTime();
time_t now = time(NULL) + fgGetLong("/sim/time/warp");
- //cerr << i->getAircraft()->getTrafficRef()->getCallSign()
+ //cerr << i->getAircraft()->getTrafficRef()->getCallSign()
// << " is scheduled to depart in " << startTime-now << " seconds. Available = " << available
// << " at parking " << getGateName(i->getAircraft()) << endl;
checkTransmissionState(7, now, (startTime + 180), i, MSG_REQUEST_PUSHBACK_CLEARANCE, ATC_AIR_TO_GROUND);
-
+
if ((state == 8) && available) {
if (now > startTime + 200) {
if (i->pushBackAllowed()) {
//while (group->getNumChildren()) {
// cerr << "Number of children: " << group->getNumChildren() << endl;
//simgear::EffectGeode* geode = (simgear::EffectGeode*) group->getChild(0);
- //osg::MatrixTransform *obj_trans = (osg::MatrixTransform*) group->getChild(0);
- //geode->releaseGLObjects();
- //group->removeChild(geode);
- //delete geode;
+ //osg::MatrixTransform *obj_trans = (osg::MatrixTransform*) group->getChild(0);
+ //geode->releaseGLObjects();
+ //group->removeChild(geode);
+ //delete geode;
group = 0;
}
if (visible) {
//for ( FGTaxiSegmentVectorIterator i = segments.begin(); i != segments.end(); i++) {
double dx = 0;
for (TrafficVectorIterator i = activeTraffic.begin(); i != activeTraffic.end(); i++) {
- // Handle start point
- int pos = i->getCurrentPosition();
- //cerr << "rendering for " << i->getAircraft()->getCallSign() << "pos = " << pos << endl;
- if (pos > 0) {
- FGTaxiSegment *segment = parent->getGroundNetwork()->findSegment(pos);
- SGGeod start(SGGeod::fromDeg((i->getLongitude()), (i->getLatitude())));
- SGGeod end (SGGeod::fromDeg(segment->getEnd()->getLongitude(), segment->getEnd()->getLatitude()));
-
- double length = SGGeodesy::distanceM(start, end);
- //heading = SGGeodesy::headingDeg(start->getGeod(), end->getGeod());
-
- double az2, heading; //, distanceM;
- SGGeodesy::inverse(start, end, heading, az2, length);
- double coveredDistance = length * 0.5;
- SGGeod center;
- SGGeodesy::direct(start, heading, coveredDistance, center, az2);
- //cerr << "Active Aircraft : Centerpoint = (" << center.getLatitudeDeg() << ", " << center.getLongitudeDeg() << "). Heading = " << heading << endl;
- ///////////////////////////////////////////////////////////////////////////////
- // Make a helper function out of this
- osg::Matrix obj_pos;
- osg::MatrixTransform *obj_trans = new osg::MatrixTransform;
- obj_trans->setDataVariance(osg::Object::STATIC);
- // Experimental: Calculate slope here, based on length, and the individual elevations
- double elevationStart;
- if (isUserAircraft((i)->getAircraft())) {
- elevationStart = fgGetDouble("/position/ground-elev-m");
- } else {
- elevationStart = ((i)->getAircraft()->_getAltitude());
- }
- double elevationEnd = segment->getEnd()->getElevation();
- if ((elevationEnd == 0) || (elevationEnd == parent->getElevation())) {
- SGGeod center2 = end;
- center2.setElevationM(SG_MAX_ELEVATION_M);
- if (local_scenery->get_elevation_m( center2, elevationEnd, NULL )) {
- elevation_feet = elevationEnd * SG_METER_TO_FEET + 0.5;
- //elevation_meters += 0.5;
- }
- else {
- elevationEnd = parent->getElevation();
- }
- segment->getEnd()->setElevation(elevationEnd);
- }
-
- double elevationMean = (elevationStart + elevationEnd) / 2.0;
- double elevDiff = elevationEnd - elevationStart;
-
- double slope = atan2(elevDiff, length) * SGD_RADIANS_TO_DEGREES;
-
- //cerr << "1. Using mean elevation : " << elevationMean << " and " << slope << endl;
-
- WorldCoordinate( obj_pos, center.getLatitudeDeg(), center.getLongitudeDeg(), elevationMean + 0.5, -(heading), slope );
-;
-
- obj_trans->setMatrix( obj_pos );
- //osg::Vec3 center(0, 0, 0)
-
- float width = length /2.0;
- osg::Vec3 corner(-width, 0, 0.25f);
- osg::Vec3 widthVec(2*width + 1, 0, 0);
- osg::Vec3 heightVec(0, 1, 0);
- osg::Geometry* geometry;
- geometry = osg::createTexturedQuadGeometry(corner, widthVec, heightVec);
- simgear::EffectGeode* geode = new simgear::EffectGeode;
- geode->setName("test");
- geode->addDrawable(geometry);
- //osg::Node *custom_obj;
- SGMaterial *mat = matlib->find("UnidirectionalTaper");
- if (mat)
- geode->setEffect(mat->get_effect());
- obj_trans->addChild(geode);
- // wire as much of the scene graph together as we can
- //->addChild( obj_trans );
- group->addChild( obj_trans );
- /////////////////////////////////////////////////////////////////////
- } else {
- //cerr << "BIG FAT WARNING: current position is here : " << pos << endl;
- }
- for(intVecIterator j = (i)->getIntentions().begin(); j != (i)->getIntentions().end(); j++) {
- osg::Matrix obj_pos;
- int k = (*j);
- if (k > 0) {
- //cerr << "rendering for " << i->getAircraft()->getCallSign() << "intention = " << k << endl;
+ if (i->isActive(300)) {
+ // Handle start point
+ int pos = i->getCurrentPosition();
+ //cerr << "rendering for " << i->getAircraft()->getCallSign() << "pos = " << pos << endl;
+ if (pos > 0) {
+ FGTaxiSegment *segment = parent->getGroundNetwork()->findSegment(pos);
+ SGGeod start(SGGeod::fromDeg((i->getLongitude()), (i->getLatitude())));
+ SGGeod end (SGGeod::fromDeg(segment->getEnd()->getLongitude(), segment->getEnd()->getLatitude()));
+
+ double length = SGGeodesy::distanceM(start, end);
+ //heading = SGGeodesy::headingDeg(start->getGeod(), end->getGeod());
+
+ double az2, heading; //, distanceM;
+ SGGeodesy::inverse(start, end, heading, az2, length);
+ double coveredDistance = length * 0.5;
+ SGGeod center;
+ SGGeodesy::direct(start, heading, coveredDistance, center, az2);
+ //cerr << "Active Aircraft : Centerpoint = (" << center.getLatitudeDeg() << ", " << center.getLongitudeDeg() << "). Heading = " << heading << endl;
+ ///////////////////////////////////////////////////////////////////////////////
+ // Make a helper function out of this
+ osg::Matrix obj_pos;
osg::MatrixTransform *obj_trans = new osg::MatrixTransform;
obj_trans->setDataVariance(osg::Object::STATIC);
- FGTaxiSegment *segment = parent->getGroundNetwork()->findSegment(k);
-
- double elevationStart = segment->getStart()->getElevation();
- double elevationEnd = segment->getEnd ()->getElevation();
- if ((elevationStart == 0) || (elevationStart == parent->getElevation())) {
- SGGeod center2 = segment->getStart()->getGeod();
- center2.setElevationM(SG_MAX_ELEVATION_M);
- if (local_scenery->get_elevation_m( center2, elevationStart, NULL )) {
- elevation_feet = elevationStart * SG_METER_TO_FEET + 0.5;
- //elevation_meters += 0.5;
- }
- else {
- elevationStart = parent->getElevation();
- }
- segment->getStart()->setElevation(elevationStart);
+ // Experimental: Calculate slope here, based on length, and the individual elevations
+ double elevationStart;
+ if (isUserAircraft((i)->getAircraft())) {
+ elevationStart = fgGetDouble("/position/ground-elev-m");
+ } else {
+ elevationStart = ((i)->getAircraft()->_getAltitude() * SG_FEET_TO_METER);
}
+ double elevationEnd = segment->getEnd()->getElevation();
if ((elevationEnd == 0) || (elevationEnd == parent->getElevation())) {
- SGGeod center2 = segment->getEnd()->getGeod();
+ SGGeod center2 = end;
center2.setElevationM(SG_MAX_ELEVATION_M);
if (local_scenery->get_elevation_m( center2, elevationEnd, NULL )) {
elevation_feet = elevationEnd * SG_METER_TO_FEET + 0.5;
//elevation_meters += 0.5;
}
- else {
+ else {
elevationEnd = parent->getElevation();
}
segment->getEnd()->setElevation(elevationEnd);
}
-
+
double elevationMean = (elevationStart + elevationEnd) / 2.0;
double elevDiff = elevationEnd - elevationStart;
- double length = segment->getLength();
- double slope = atan2(elevDiff, length) * SGD_RADIANS_TO_DEGREES;
-
- //cerr << "2. Using mean elevation : " << elevationMean << " and " << slope << endl;
+ double slope = atan2(elevDiff, length) * SGD_RADIANS_TO_DEGREES;
- WorldCoordinate( obj_pos, segment->getLatitude(), segment->getLongitude(), elevationMean + 0.5, -(segment->getHeading()), slope );
+ //cerr << "1. Using mean elevation : " << elevationMean << " and " << slope << endl;
- //WorldCoordinate( obj_pos, segment->getLatitude(), segment->getLongitude(), parent->getElevation()+8+dx, -(segment->getHeading()) );
+ WorldCoordinate( obj_pos, center.getLatitudeDeg(), center.getLongitudeDeg(), elevationMean + 0.5 + dx, -(heading), slope );
+ ;
obj_trans->setMatrix( obj_pos );
//osg::Vec3 center(0, 0, 0)
- float width = segment->getLength() /2.0;
+ float width = length /2.0;
osg::Vec3 corner(-width, 0, 0.25f);
osg::Vec3 widthVec(2*width + 1, 0, 0);
osg::Vec3 heightVec(0, 1, 0);
geode->setName("test");
geode->addDrawable(geometry);
//osg::Node *custom_obj;
- SGMaterial *mat = matlib->find("UnidirectionalTaper");
+ SGMaterial *mat;
+ if (segment->hasBlock()) {
+ mat = matlib->find("UnidirectionalTaperRed");
+ } else {
+ mat = matlib->find("UnidirectionalTaperGreen");
+ }
if (mat)
geode->setEffect(mat->get_effect());
obj_trans->addChild(geode);
// wire as much of the scene graph together as we can
//->addChild( obj_trans );
group->addChild( obj_trans );
+ /////////////////////////////////////////////////////////////////////
} else {
- //cerr << "BIG FAT WARNING: k is here : " << pos << endl;
+ //cerr << "BIG FAT WARNING: current position is here : " << pos << endl;
}
+ for (intVecIterator j = (i)->getIntentions().begin(); j != (i)->getIntentions().end(); j++) {
+ osg::Matrix obj_pos;
+ int k = (*j);
+ if (k > 0) {
+ //cerr << "rendering for " << i->getAircraft()->getCallSign() << "intention = " << k << endl;
+ osg::MatrixTransform *obj_trans = new osg::MatrixTransform;
+ obj_trans->setDataVariance(osg::Object::STATIC);
+ FGTaxiSegment *segment = parent->getGroundNetwork()->findSegment(k);
+
+ double elevationStart = segment->getStart()->getElevation();
+ double elevationEnd = segment->getEnd ()->getElevation();
+ if ((elevationStart == 0) || (elevationStart == parent->getElevation())) {
+ SGGeod center2 = segment->getStart()->getGeod();
+ center2.setElevationM(SG_MAX_ELEVATION_M);
+ if (local_scenery->get_elevation_m( center2, elevationStart, NULL )) {
+ elevation_feet = elevationStart * SG_METER_TO_FEET + 0.5;
+ //elevation_meters += 0.5;
+ }
+ else {
+ elevationStart = parent->getElevation();
+ }
+ segment->getStart()->setElevation(elevationStart);
+ }
+ if ((elevationEnd == 0) || (elevationEnd == parent->getElevation())) {
+ SGGeod center2 = segment->getEnd()->getGeod();
+ center2.setElevationM(SG_MAX_ELEVATION_M);
+ if (local_scenery->get_elevation_m( center2, elevationEnd, NULL )) {
+ elevation_feet = elevationEnd * SG_METER_TO_FEET + 0.5;
+ //elevation_meters += 0.5;
+ }
+ else {
+ elevationEnd = parent->getElevation();
+ }
+ segment->getEnd()->setElevation(elevationEnd);
+ }
+
+ double elevationMean = (elevationStart + elevationEnd) / 2.0;
+ double elevDiff = elevationEnd - elevationStart;
+ double length = segment->getLength();
+ double slope = atan2(elevDiff, length) * SGD_RADIANS_TO_DEGREES;
+
+ //cerr << "2. Using mean elevation : " << elevationMean << " and " << slope << endl;
+
+
+ WorldCoordinate( obj_pos, segment->getLatitude(), segment->getLongitude(), elevationMean + 0.5 + dx, -(segment->getHeading()), slope );
+
+ //WorldCoordinate( obj_pos, segment->getLatitude(), segment->getLongitude(), parent->getElevation()+8+dx, -(segment->getHeading()) );
+
+ obj_trans->setMatrix( obj_pos );
+ //osg::Vec3 center(0, 0, 0)
+
+ float width = segment->getLength() /2.0;
+ osg::Vec3 corner(-width, 0, 0.25f);
+ osg::Vec3 widthVec(2*width + 1, 0, 0);
+ osg::Vec3 heightVec(0, 1, 0);
+ osg::Geometry* geometry;
+ geometry = osg::createTexturedQuadGeometry(corner, widthVec, heightVec);
+ simgear::EffectGeode* geode = new simgear::EffectGeode;
+ geode->setName("test");
+ geode->addDrawable(geometry);
+ //osg::Node *custom_obj;
+ SGMaterial *mat;
+ if (segment->hasBlock()) {
+ mat = matlib->find("UnidirectionalTaperRed");
+ } else {
+ mat = matlib->find("UnidirectionalTaperGreen");
+ }
+ if (mat)
+ geode->setEffect(mat->get_effect());
+ obj_trans->addChild(geode);
+ // wire as much of the scene graph together as we can
+ //->addChild( obj_trans );
+ group->addChild( obj_trans );
+ } else {
+ //cerr << "BIG FAT WARNING: k is here : " << pos << endl;
+ }
+ }
+ dx += 0.2;
}
- //dx += 0.1;
}
globals->get_scenery()->get_scene_graph()->addChild(group);
}
return string(parent->getId() + "-startup");
}
+void FGStartupController::update(double dt)
+{
+
+}
+
+
/***************************************************************************
* class FGApproachController
*
**************************************************************************/
FGApproachController::FGApproachController(FGAirportDynamics *par):
-FGATCController()
+ FGATCController()
{
parent = par;
}
-//
+//
void FGApproachController::announcePosition(int id,
- FGAIFlightPlan * intendedRoute,
- int currentPosition,
- double lat, double lon,
- double heading, double speed,
- double alt, double radius,
- int leg, FGAIAircraft * ref)
+ FGAIFlightPlan * intendedRoute,
+ int currentPosition,
+ double lat, double lon,
+ double heading, double speed,
+ double alt, double radius,
+ int leg, FGAIAircraft * ref)
{
init();
TrafficVectorIterator i = activeTraffic.begin();
}
void FGApproachController::updateAircraftInformation(int id, double lat, double lon,
- double heading, double speed, double alt,
- double dt)
+ double heading, double speed, double alt,
+ double dt)
{
TrafficVectorIterator i = activeTraffic.begin();
// Search search if the current id has an entry
}
}
+void FGApproachController::update(double dt)
+{
+
+}
#include <simgear/structure/SGReferenced.hxx>
#include <simgear/structure/SGSharedPtr.hxx>
+
#include <string>
#include <vector>
+#include <list>
using std::string;
using std::vector;
+using std::list;
typedef vector<int> intVec;
class FGATCInstruction
{
private:
- bool holdPattern;
- bool holdPosition;
- bool changeSpeed;
- bool changeHeading;
- bool changeAltitude;
- bool resolveCircularWait;
-
- double speed;
- double heading;
- double alt;
+ bool holdPattern;
+ bool holdPosition;
+ bool changeSpeed;
+ bool changeHeading;
+ bool changeAltitude;
+ bool resolveCircularWait;
+
+ double speed;
+ double heading;
+ double alt;
public:
- FGATCInstruction();
- bool hasInstruction ();
- bool getHoldPattern () { return holdPattern; };
- bool getHoldPosition () { return holdPosition; };
- bool getChangeSpeed () { return changeSpeed; };
- bool getChangeHeading () { return changeHeading; };
- bool getChangeAltitude() { return changeAltitude; };
-
- double getSpeed () { return speed; };
- double getHeading () { return heading; };
- double getAlt () { return alt; };
-
- bool getCheckForCircularWait() { return resolveCircularWait; };
-
- void setHoldPattern (bool val) { holdPattern = val; };
- void setHoldPosition (bool val) { holdPosition = val; };
- void setChangeSpeed (bool val) { changeSpeed = val; };
- void setChangeHeading (bool val) { changeHeading = val; };
- void setChangeAltitude(bool val) { changeAltitude = val; };
-
- void setResolveCircularWait (bool val) { resolveCircularWait = val; };
-
- void setSpeed (double val) { speed = val; };
- void setHeading (double val) { heading = val; };
- void setAlt (double val) { alt = val; };
+ FGATCInstruction();
+ bool hasInstruction ();
+ bool getHoldPattern () {
+ return holdPattern;
+ };
+ bool getHoldPosition () {
+ return holdPosition;
+ };
+ bool getChangeSpeed () {
+ return changeSpeed;
+ };
+ bool getChangeHeading () {
+ return changeHeading;
+ };
+ bool getChangeAltitude() {
+ return changeAltitude;
+ };
+
+ double getSpeed () {
+ return speed;
+ };
+ double getHeading () {
+ return heading;
+ };
+ double getAlt () {
+ return alt;
+ };
+
+ bool getCheckForCircularWait() {
+ return resolveCircularWait;
+ };
+
+ void setHoldPattern (bool val) {
+ holdPattern = val;
+ };
+ void setHoldPosition (bool val) {
+ holdPosition = val;
+ };
+ void setChangeSpeed (bool val) {
+ changeSpeed = val;
+ };
+ void setChangeHeading (bool val) {
+ changeHeading = val;
+ };
+ void setChangeAltitude(bool val) {
+ changeAltitude = val;
+ };
+
+ void setResolveCircularWait (bool val) {
+ resolveCircularWait = val;
+ };
+
+ void setSpeed (double val) {
+ speed = val;
+ };
+ void setHeading (double val) {
+ heading = val;
+ };
+ void setAlt (double val) {
+ alt = val;
+ };
};
class FGTrafficRecord
{
private:
- int id, waitsForId;
- int currentPos;
- int leg;
- int frequencyId;
- int state;
- bool allowTransmission;
- time_t timer;
- intVec intentions;
- FGATCInstruction instruction;
- double latitude, longitude, heading, speed, altitude, radius;
- string runway;
- //FGAISchedule *trafficRef;
- FGAIAircraft *aircraft;
-
-
+ int id, waitsForId;
+ int currentPos;
+ int leg;
+ int frequencyId;
+ int state;
+ bool allowTransmission;
+ bool allowPushback;
+ int priority;
+ time_t timer;
+ intVec intentions;
+ FGATCInstruction instruction;
+ double latitude, longitude, heading, speed, altitude, radius;
+ string runway;
+ //FGAISchedule *trafficRef;
+ FGAIAircraft *aircraft;
+
+
public:
- FGTrafficRecord();
-
- void setId(int val) { id = val; };
- void setRadius(double rad) { radius = rad;};
- void setPositionAndIntentions(int pos, FGAIFlightPlan *route);
- void setRunway(string rwy) { runway = rwy;};
- void setLeg(int lg) { leg = lg;};
- int getId() { return id;};
- int getState() { return state;};
- void setState(int s) { state = s;}
- FGATCInstruction getInstruction() { return instruction;};
- bool hasInstruction() { return instruction.hasInstruction(); };
- void setPositionAndHeading(double lat, double lon, double hdg, double spd, double alt);
- bool checkPositionAndIntentions(FGTrafficRecord &other);
- int crosses (FGGroundNetwork *, FGTrafficRecord &other);
- bool isOpposing (FGGroundNetwork *, FGTrafficRecord &other, int node);
-
- bool onRoute(FGGroundNetwork *, FGTrafficRecord &other);
-
- bool getSpeedAdjustment() { return instruction.getChangeSpeed(); };
-
- double getLatitude () { return latitude ; };
- double getLongitude() { return longitude; };
- double getHeading () { return heading ; };
- double getSpeed () { return speed ; };
- double getAltitude () { return altitude ; };
- double getRadius () { return radius ; };
-
- int getWaitsForId () { return waitsForId; };
-
- void setSpeedAdjustment(double spd);
- void setHeadingAdjustment(double heading);
- void clearSpeedAdjustment () { instruction.setChangeSpeed (false); };
- void clearHeadingAdjustment() { instruction.setChangeHeading(false); };
-
- bool hasHeadingAdjustment() { return instruction.getChangeHeading(); };
- bool hasHoldPosition() { return instruction.getHoldPosition(); };
- void setHoldPosition (bool inst) { instruction.setHoldPosition(inst); };
-
- void setWaitsForId(int id) { waitsForId = id; };
-
- void setResolveCircularWait() { instruction.setResolveCircularWait(true); };
- void clearResolveCircularWait() { instruction.setResolveCircularWait(false); };
-
- string getRunway() { return runway; };
- //void setCallSign(string clsgn) { callsign = clsgn; };
- void setAircraft(FGAIAircraft *ref) { aircraft = ref;};
- void updateState() { state++; allowTransmission=true; };
- //string getCallSign() { return callsign; };
- FGAIAircraft *getAircraft() { return aircraft;};
- int getTime() { return timer; };
- int getLeg() { return leg; };
- void setTime(time_t time) { timer = time; };
-
- bool pushBackAllowed();
- bool allowTransmissions() { return allowTransmission; };
- void suppressRepeatedTransmissions () { allowTransmission=false; };
- void allowRepeatedTransmissions () { allowTransmission=true; };
- void nextFrequency() { frequencyId++; };
- int getNextFrequency() { return frequencyId; };
- intVec& getIntentions() { return intentions; };
- int getCurrentPosition() { return currentPos; };
+ FGTrafficRecord();
+
+ void setId(int val) {
+ id = val;
+ };
+ void setRadius(double rad) {
+ radius = rad;
+ };
+ void setPositionAndIntentions(int pos, FGAIFlightPlan *route);
+ void setRunway(string rwy) {
+ runway = rwy;
+ };
+ void setLeg(int lg) {
+ leg = lg;
+ };
+ int getId() {
+ return id;
+ };
+ int getState() {
+ return state;
+ };
+ void setState(int s) {
+ state = s;
+ }
+ FGATCInstruction getInstruction() {
+ return instruction;
+ };
+ bool hasInstruction() {
+ return instruction.hasInstruction();
+ };
+ void setPositionAndHeading(double lat, double lon, double hdg, double spd, double alt);
+ bool checkPositionAndIntentions(FGTrafficRecord &other);
+ int crosses (FGGroundNetwork *, FGTrafficRecord &other);
+ bool isOpposing (FGGroundNetwork *, FGTrafficRecord &other, int node);
+
+ bool isActive(int margin);
+
+ bool onRoute(FGGroundNetwork *, FGTrafficRecord &other);
+
+ bool getSpeedAdjustment() {
+ return instruction.getChangeSpeed();
+ };
+
+ double getLatitude () {
+ return latitude ;
+ };
+ double getLongitude() {
+ return longitude;
+ };
+ double getHeading () {
+ return heading ;
+ };
+ double getSpeed () {
+ return speed ;
+ };
+ double getAltitude () {
+ return altitude ;
+ };
+ double getRadius () {
+ return radius ;
+ };
+
+ int getWaitsForId () {
+ return waitsForId;
+ };
+
+ void setSpeedAdjustment(double spd);
+ void setHeadingAdjustment(double heading);
+ void clearSpeedAdjustment () {
+ instruction.setChangeSpeed (false);
+ };
+ void clearHeadingAdjustment() {
+ instruction.setChangeHeading(false);
+ };
+
+ bool hasHeadingAdjustment() {
+ return instruction.getChangeHeading();
+ };
+ bool hasHoldPosition() {
+ return instruction.getHoldPosition();
+ };
+ void setHoldPosition (bool inst) {
+ instruction.setHoldPosition(inst);
+ };
+
+ void setWaitsForId(int id) {
+ waitsForId = id;
+ };
+
+ void setResolveCircularWait() {
+ instruction.setResolveCircularWait(true);
+ };
+ void clearResolveCircularWait() {
+ instruction.setResolveCircularWait(false);
+ };
+
+ string getRunway() {
+ return runway;
+ };
+ //void setCallSign(string clsgn) { callsign = clsgn; };
+ void setAircraft(FGAIAircraft *ref) {
+ aircraft = ref;
+ };
+ void updateState() {
+ state++;
+ allowTransmission=true;
+ };
+ //string getCallSign() { return callsign; };
+ FGAIAircraft *getAircraft() {
+ return aircraft;
+ };
+ int getTime() {
+ return timer;
+ };
+ int getLeg() {
+ return leg;
+ };
+ void setTime(time_t time) {
+ timer = time;
+ };
+
+ bool pushBackAllowed();
+ bool allowTransmissions() {
+ return allowTransmission;
+ };
+ void allowPushBack() { allowPushback =true;};
+ void denyPushBack () { allowPushback = false;};
+ void suppressRepeatedTransmissions () {
+ allowTransmission=false;
+ };
+ void allowRepeatedTransmissions () {
+ allowTransmission=true;
+ };
+ void nextFrequency() {
+ frequencyId++;
+ };
+ int getNextFrequency() {
+ return frequencyId;
+ };
+ intVec& getIntentions() {
+ return intentions;
+ };
+ int getCurrentPosition() {
+ return currentPos;
+ };
+ void setPriority(int p) { priority = p; };
+ int getPriority() { return priority; };
};
-typedef vector<FGTrafficRecord> TrafficVector;
-typedef vector<FGTrafficRecord>::iterator TrafficVectorIterator;
+typedef list<FGTrafficRecord> TrafficVector;
+typedef list<FGTrafficRecord>::iterator TrafficVectorIterator;
typedef vector<time_t> TimeVector;
typedef vector<time_t>::iterator TimeVectorIterator;
class ActiveRunway
{
private:
- string rwy;
- int currentlyCleared;
- double distanceToFinal;
- TimeVector estimatedArrivalTimes;
- AircraftVec departureCue;
+ string rwy;
+ int currentlyCleared;
+ double distanceToFinal;
+ TimeVector estimatedArrivalTimes;
+ AircraftVec departureCue;
public:
- ActiveRunway(string r, int cc) { rwy = r; currentlyCleared = cc; distanceToFinal = 6.0 * SG_NM_TO_METER; };
-
- string getRunwayName() { return rwy; };
- int getCleared () { return currentlyCleared; };
- double getApproachDistance() { return distanceToFinal; };
- //time_t getEstApproachTime() { return estimatedArrival; };
-
- //void setEstApproachTime(time_t time) { estimatedArrival = time; };
- void addToDepartureCue(FGAIAircraft *ac) { departureCue.push_back(ac); };
- void setCleared(int number) { currentlyCleared = number; };
- time_t requestTimeSlot(time_t eta);
-
- int getDepartureCueSize() { return departureCue.size(); };
- FGAIAircraft* getFirstAircraftInDepartureCue() { return departureCue.size() ? *(departureCue.begin()) : NULL; };
- void updateDepartureCue() { departureCue.erase(departureCue.begin()); }
+ ActiveRunway(string r, int cc) {
+ rwy = r;
+ currentlyCleared = cc;
+ distanceToFinal = 6.0 * SG_NM_TO_METER;
+ };
+
+ string getRunwayName() {
+ return rwy;
+ };
+ int getCleared () {
+ return currentlyCleared;
+ };
+ double getApproachDistance() {
+ return distanceToFinal;
+ };
+ //time_t getEstApproachTime() { return estimatedArrival; };
+
+ //void setEstApproachTime(time_t time) { estimatedArrival = time; };
+ void addToDepartureCue(FGAIAircraft *ac) {
+ departureCue.push_back(ac);
+ };
+ void setCleared(int number) {
+ currentlyCleared = number;
+ };
+ time_t requestTimeSlot(time_t eta);
+
+ int getDepartureCueSize() {
+ return departureCue.size();
+ };
+ FGAIAircraft* getFirstAircraftInDepartureCue() {
+ return departureCue.size() ? *(departureCue.begin()) : NULL;
+ };
+ void updateDepartureCue() {
+ departureCue.erase(departureCue.begin());
+ }
};
typedef vector<ActiveRunway> ActiveRunwayVec;
/**
* class FGATCController
- * NOTE: this class serves as an abstraction layer for all sorts of ATC controllers.
+ * NOTE: this class serves as an abstraction layer for all sorts of ATC controllers.
*************************************************************************************/
class FGATCController
{
private:
-
+
protected:
- bool initialized;
- bool available;
- time_t lastTransmission;
+ bool initialized;
+ bool available;
+ time_t lastTransmission;
- double dt_count;
- osg::Group* group;
+ double dt_count;
+ osg::Group* group;
- string formatATCFrequency3_2(int );
- string genTransponderCode(string fltRules);
- bool isUserAircraft(FGAIAircraft*);
+ string formatATCFrequency3_2(int );
+ string genTransponderCode(string fltRules);
+ bool isUserAircraft(FGAIAircraft*);
public:
- typedef enum {
- MSG_ANNOUNCE_ENGINE_START,
- MSG_REQUEST_ENGINE_START,
- MSG_PERMIT_ENGINE_START,
- MSG_DENY_ENGINE_START,
- MSG_ACKNOWLEDGE_ENGINE_START,
- MSG_REQUEST_PUSHBACK_CLEARANCE,
- MSG_PERMIT_PUSHBACK_CLEARANCE,
- MSG_HOLD_PUSHBACK_CLEARANCE,
- MSG_ACKNOWLEDGE_SWITCH_GROUND_FREQUENCY,
- MSG_INITIATE_CONTACT,
- MSG_ACKNOWLEDGE_INITIATE_CONTACT,
- MSG_REQUEST_TAXI_CLEARANCE,
- MSG_ISSUE_TAXI_CLEARANCE,
- MSG_ACKNOWLEDGE_TAXI_CLEARANCE,
- MSG_HOLD_POSITION,
- MSG_ACKNOWLEDGE_HOLD_POSITION,
- MSG_RESUME_TAXI,
- MSG_ACKNOWLEDGE_RESUME_TAXI,
- MSG_REPORT_RUNWAY_HOLD_SHORT,
- MSG_ACKNOWLEDGE_REPORT_RUNWAY_HOLD_SHORT,
- MSG_SWITCH_TOWER_FREQUENCY,
- MSG_ACKNOWLEDGE_SWITCH_TOWER_FREQUENCY
- } AtcMsgId;
-
- typedef enum {
- ATC_AIR_TO_GROUND,
- ATC_GROUND_TO_AIR } AtcMsgDir;
- FGATCController();
- virtual ~FGATCController();
- void init();
-
- virtual void announcePosition(int id, FGAIFlightPlan *intendedRoute, int currentRoute,
- double lat, double lon,
- double hdg, double spd, double alt, double radius, int leg,
- FGAIAircraft *aircraft) = 0;
- virtual void signOff(int id) = 0;
- virtual void updateAircraftInformation(int id, double lat, double lon,
- double heading, double speed, double alt, double dt) = 0;
- virtual bool hasInstruction(int id) = 0;
- virtual FGATCInstruction getInstruction(int id) = 0;
-
- double getDt() { return dt_count; };
- void setDt(double dt) { dt_count = dt;};
- void transmit(FGTrafficRecord *rec, AtcMsgId msgId, AtcMsgDir msgDir, bool audible);
- string getGateName(FGAIAircraft *aircraft);
- virtual void render(bool) = 0;
- virtual string getName() = 0;
+ typedef enum {
+ MSG_ANNOUNCE_ENGINE_START,
+ MSG_REQUEST_ENGINE_START,
+ MSG_PERMIT_ENGINE_START,
+ MSG_DENY_ENGINE_START,
+ MSG_ACKNOWLEDGE_ENGINE_START,
+ MSG_REQUEST_PUSHBACK_CLEARANCE,
+ MSG_PERMIT_PUSHBACK_CLEARANCE,
+ MSG_HOLD_PUSHBACK_CLEARANCE,
+ MSG_ACKNOWLEDGE_SWITCH_GROUND_FREQUENCY,
+ MSG_INITIATE_CONTACT,
+ MSG_ACKNOWLEDGE_INITIATE_CONTACT,
+ MSG_REQUEST_TAXI_CLEARANCE,
+ MSG_ISSUE_TAXI_CLEARANCE,
+ MSG_ACKNOWLEDGE_TAXI_CLEARANCE,
+ MSG_HOLD_POSITION,
+ MSG_ACKNOWLEDGE_HOLD_POSITION,
+ MSG_RESUME_TAXI,
+ MSG_ACKNOWLEDGE_RESUME_TAXI,
+ MSG_REPORT_RUNWAY_HOLD_SHORT,
+ MSG_ACKNOWLEDGE_REPORT_RUNWAY_HOLD_SHORT,
+ MSG_SWITCH_TOWER_FREQUENCY,
+ MSG_ACKNOWLEDGE_SWITCH_TOWER_FREQUENCY
+ } AtcMsgId;
+
+ typedef enum {
+ ATC_AIR_TO_GROUND,
+ ATC_GROUND_TO_AIR
+ } AtcMsgDir;
+ FGATCController();
+ virtual ~FGATCController();
+ void init();
+
+ virtual void announcePosition(int id, FGAIFlightPlan *intendedRoute, int currentRoute,
+ double lat, double lon,
+ double hdg, double spd, double alt, double radius, int leg,
+ FGAIAircraft *aircraft) = 0;
+ virtual void signOff(int id) = 0;
+ virtual void updateAircraftInformation(int id, double lat, double lon,
+ double heading, double speed, double alt, double dt) = 0;
+ virtual bool hasInstruction(int id) = 0;
+ virtual FGATCInstruction getInstruction(int id) = 0;
+
+ double getDt() {
+ return dt_count;
+ };
+ void setDt(double dt) {
+ dt_count = dt;
+ };
+ void transmit(FGTrafficRecord *rec, AtcMsgId msgId, AtcMsgDir msgDir, bool audible);
+ string getGateName(FGAIAircraft *aircraft);
+ virtual void render(bool) = 0;
+ virtual string getName() = 0;
+
+ virtual void update(double) = 0;
private:
- AtcMsgDir lastTransmissionDirection;
+ AtcMsgDir lastTransmissionDirection;
};
/******************************************************************************
class FGTowerController : public FGATCController
{
private:
- TrafficVector activeTraffic;
- ActiveRunwayVec activeRunways;
- FGAirportDynamics *parent;
-
+ TrafficVector activeTraffic;
+ ActiveRunwayVec activeRunways;
+ FGAirportDynamics *parent;
+
public:
- FGTowerController(FGAirportDynamics *parent);
- virtual ~FGTowerController() {};
- virtual void announcePosition(int id, FGAIFlightPlan *intendedRoute, int currentRoute,
- double lat, double lon,
- double hdg, double spd, double alt, double radius, int leg,
- FGAIAircraft *aircraft);
- virtual void signOff(int id);
- virtual void updateAircraftInformation(int id, double lat, double lon,
- double heading, double speed, double alt, double dt);
- virtual bool hasInstruction(int id);
- virtual FGATCInstruction getInstruction(int id);
-
- virtual void render(bool);
- virtual string getName();
- bool hasActiveTraffic() { return activeTraffic.size() != 0; };
- TrafficVector &getActiveTraffic() { return activeTraffic; };
+ FGTowerController(FGAirportDynamics *parent);
+ virtual ~FGTowerController() {};
+ virtual void announcePosition(int id, FGAIFlightPlan *intendedRoute, int currentRoute,
+ double lat, double lon,
+ double hdg, double spd, double alt, double radius, int leg,
+ FGAIAircraft *aircraft);
+ virtual void signOff(int id);
+ virtual void updateAircraftInformation(int id, double lat, double lon,
+ double heading, double speed, double alt, double dt);
+ virtual bool hasInstruction(int id);
+ virtual FGATCInstruction getInstruction(int id);
+
+ virtual void render(bool);
+ virtual string getName();
+ virtual void update(double dt);
+ bool hasActiveTraffic() {
+ return activeTraffic.size() != 0;
+ };
+ TrafficVector &getActiveTraffic() {
+ return activeTraffic;
+ };
};
/******************************************************************************
* class FGStartupController
- * handle
+ * handle
*****************************************************************************/
class FGStartupController : public FGATCController
{
private:
- TrafficVector activeTraffic;
- //ActiveRunwayVec activeRunways;
- FGAirportDynamics *parent;
-
+ TrafficVector activeTraffic;
+ //ActiveRunwayVec activeRunways;
+ FGAirportDynamics *parent;
+
public:
- FGStartupController(FGAirportDynamics *parent);
- virtual ~FGStartupController() {};
- virtual void announcePosition(int id, FGAIFlightPlan *intendedRoute, int currentRoute,
- double lat, double lon,
- double hdg, double spd, double alt, double radius, int leg,
- FGAIAircraft *aircraft);
- virtual void signOff(int id);
- virtual void updateAircraftInformation(int id, double lat, double lon,
- double heading, double speed, double alt, double dt);
- virtual bool hasInstruction(int id);
- virtual FGATCInstruction getInstruction(int id);
-
- virtual void render(bool);
- virtual string getName();
-
- bool hasActiveTraffic() { return activeTraffic.size() != 0; };
- TrafficVector &getActiveTraffic() { return activeTraffic; };
-
- // 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);
-
-};
+ FGStartupController(FGAirportDynamics *parent);
+ virtual ~FGStartupController() {};
+ virtual void announcePosition(int id, FGAIFlightPlan *intendedRoute, int currentRoute,
+ double lat, double lon,
+ double hdg, double spd, double alt, double radius, int leg,
+ FGAIAircraft *aircraft);
+ virtual void signOff(int id);
+ virtual void updateAircraftInformation(int id, double lat, double lon,
+ double heading, double speed, double alt, double dt);
+ virtual bool hasInstruction(int id);
+ virtual FGATCInstruction getInstruction(int id);
+
+ virtual void render(bool);
+ virtual string getName();
+ virtual void update(double dt);
+
+ bool hasActiveTraffic() {
+ return activeTraffic.size() != 0;
+ };
+ TrafficVector &getActiveTraffic() {
+ return activeTraffic;
+ };
+
+ // 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);
+
+};
/******************************************************************************
* class FGTowerControl
class FGApproachController : public FGATCController
{
private:
- TrafficVector activeTraffic;
- ActiveRunwayVec activeRunways;
- FGAirportDynamics *parent;
-
+ TrafficVector activeTraffic;
+ ActiveRunwayVec activeRunways;
+ FGAirportDynamics *parent;
+
public:
- FGApproachController(FGAirportDynamics * parent);
- virtual ~FGApproachController() { };
- virtual void announcePosition(int id, FGAIFlightPlan *intendedRoute, int currentRoute,
- double lat, double lon,
- double hdg, double spd, double alt, double radius, int leg,
- FGAIAircraft *aircraft);
- virtual void signOff(int id);
- virtual void updateAircraftInformation(int id, double lat, double lon,
- double heading, double speed, double alt, double dt);
- virtual bool hasInstruction(int id);
- virtual FGATCInstruction getInstruction(int id);
-
- virtual void render(bool);
- virtual string getName();
-
- ActiveRunway* getRunway(string name);
-
- bool hasActiveTraffic() { return activeTraffic.size() != 0; };
- TrafficVector &getActiveTraffic() { return activeTraffic; };
+ FGApproachController(FGAirportDynamics * parent);
+ virtual ~FGApproachController() { };
+ virtual void announcePosition(int id, FGAIFlightPlan *intendedRoute, int currentRoute,
+ double lat, double lon,
+ double hdg, double spd, double alt, double radius, int leg,
+ FGAIAircraft *aircraft);
+ virtual void signOff(int id);
+ virtual void updateAircraftInformation(int id, double lat, double lon,
+ double heading, double speed, double alt, double dt);
+ virtual bool hasInstruction(int id);
+ virtual FGATCInstruction getInstruction(int id);
+
+ virtual void render(bool);
+ virtual string getName();
+ virtual void update(double dt);
+
+ ActiveRunway* getRunway(string name);
+
+ bool hasActiveTraffic() {
+ return activeTraffic.size() != 0;
+ };
+ TrafficVector &getActiveTraffic() {
+ return activeTraffic;
+ };
};
class FGAirportDynamics {
private:
- FGAirport* _ap;
-
- FGParkingVec parkings;
- FGRunwayPreference rwyPrefs;
- FGSidStar SIDs;
- FGStartupController startupController;
- FGGroundNetwork groundNetwork;
- FGTowerController towerController;
- FGApproachController approachController;
-
- time_t lastUpdate;
- std::string prevTrafficType;
- stringVec landing;
- stringVec takeoff;
- stringVec milActive, comActive, genActive, ulActive;
- stringVec *currentlyActive;
- intVec freqAwos; // </AWOS>
- intVec freqUnicom; // </UNICOM>
- intVec freqClearance;// </CLEARANCE>
- intVec freqGround; // </GROUND>
- intVec freqTower; // </TOWER>
- intVec freqApproach; // </APPROACH>
-
- int atisSequenceIndex;
- double atisSequenceTimeStamp;
-
- std::string chooseRunwayFallback();
- bool innerGetActiveRunway(const std::string &trafficType, int action, std::string &runway, double heading);
- std::string chooseRwyByHeading(stringVec rwys, double heading);
-
- double elevation;
+ FGAirport* _ap;
+
+ FGParkingVec parkings;
+ FGRunwayPreference rwyPrefs;
+ FGSidStar SIDs;
+ FGStartupController startupController;
+ FGGroundNetwork groundNetwork;
+ FGTowerController towerController;
+ FGApproachController approachController;
+
+ time_t lastUpdate;
+ std::string prevTrafficType;
+ stringVec landing;
+ stringVec takeoff;
+ stringVec milActive, comActive, genActive, ulActive;
+ stringVec *currentlyActive;
+ intVec freqAwos; // </AWOS>
+ intVec freqUnicom; // </UNICOM>
+ intVec freqClearance;// </CLEARANCE>
+ intVec freqGround; // </GROUND>
+ intVec freqTower; // </TOWER>
+ intVec freqApproach; // </APPROACH>
+
+ int atisSequenceIndex;
+ double atisSequenceTimeStamp;
+
+ std::string chooseRunwayFallback();
+ bool innerGetActiveRunway(const std::string &trafficType, int action, std::string &runway, double heading);
+ std::string chooseRwyByHeading(stringVec rwys, double heading);
+
+ double elevation;
public:
- FGAirportDynamics(FGAirport* ap);
- ~FGAirportDynamics();
-
- void addAwosFreq (int val) { freqAwos.push_back(val); };
- void addUnicomFreq (int val) { freqUnicom.push_back(val); };
- void addClearanceFreq(int val) { freqClearance.push_back(val); };
- void addGroundFreq (int val) { freqGround.push_back(val); };
- void addTowerFreq (int val) { freqTower.push_back(val); };
- void addApproachFreq (int val) { freqApproach.push_back(val); };
-
- void init();
- double getLongitude() const;
- // Returns degrees
- double getLatitude() const;
- // Returns ft
- double getElevation() const;
- const string& getId() const;
-
- void getActiveRunway(const string& trafficType, int action, string& runway, double heading);
-
- void addParking(FGParking& park);
- bool getAvailableParking(double *lat, double *lon,
- double *heading, int *gate, double rad, const string& fltype,
- const string& acType, const string& airline);
- void getParking (int id, double *lat, double* lon, double *heading);
- FGParking *getParking(int i);
- void releaseParking(int id);
- string getParkingName(int i);
- int getNrOfParkings() { return parkings.size(); };
- //FGAirport *getAddress() { return this; };
- //const string &getName() const { return _name;};
- // Returns degrees
-
- // Departure / Arrival procedures
- FGSidStar * getSIDs() { return &SIDs; };
- FGAIFlightPlan * getSID(string activeRunway, double heading);
-
-
- // ATC related functions.
- FGStartupController *getStartupController() { return &startupController; };
- FGGroundNetwork *getGroundNetwork() { return &groundNetwork; };
- FGTowerController *getTowerController() { return &towerController; };
- FGApproachController *getApproachController() { return &approachController; };
-
- int getGroundFrequency(unsigned leg);
- int getTowerFrequency (unsigned nr);
-
- /// get current ATIS sequence letter
- const std::string getAtisSequence();
-
- /// get the current ATIS sequence number, updating it if necessary
- int updateAtisSequence(int interval, bool forceUpdate);
-
- void setRwyUse(const FGRunwayPreference& ref);
+ FGAirportDynamics(FGAirport* ap);
+ ~FGAirportDynamics();
+
+ void addAwosFreq (int val) {
+ freqAwos.push_back(val);
+ };
+ void addUnicomFreq (int val) {
+ freqUnicom.push_back(val);
+ };
+ void addClearanceFreq(int val) {
+ freqClearance.push_back(val);
+ };
+ void addGroundFreq (int val) {
+ freqGround.push_back(val);
+ };
+ void addTowerFreq (int val) {
+ freqTower.push_back(val);
+ };
+ void addApproachFreq (int val) {
+ freqApproach.push_back(val);
+ };
+
+ void init();
+ double getLongitude() const;
+ // Returns degrees
+ double getLatitude() const;
+ // Returns ft
+ double getElevation() const;
+ const string& getId() const;
+
+ void getActiveRunway(const string& trafficType, int action, string& runway, double heading);
+
+ void addParking(FGParking& park);
+ bool getAvailableParking(double *lat, double *lon,
+ double *heading, int *gate, double rad, const string& fltype,
+ const string& acType, const string& airline);
+ void getParking (int id, double *lat, double* lon, double *heading);
+ FGParking *getParking(int i);
+ void releaseParking(int id);
+ string getParkingName(int i);
+ int getNrOfParkings() {
+ return parkings.size();
+ };
+ //FGAirport *getAddress() { return this; };
+ //const string &getName() const { return _name;};
+ // Returns degrees
+
+ // Departure / Arrival procedures
+ FGSidStar * getSIDs() {
+ return &SIDs;
+ };
+ FGAIFlightPlan * getSID(string activeRunway, double heading);
+
+
+ // ATC related functions.
+ FGStartupController *getStartupController() {
+ return &startupController;
+ };
+ FGGroundNetwork *getGroundNetwork() {
+ return &groundNetwork;
+ };
+ FGTowerController *getTowerController() {
+ return &towerController;
+ };
+ FGApproachController *getApproachController() {
+ return &approachController;
+ };
+
+ int getGroundFrequency(unsigned leg);
+ int getTowerFrequency (unsigned nr);
+
+ /// get current ATIS sequence letter
+ const std::string getAtisSequence();
+
+ /// get the current ATIS sequence number, updating it if necessary
+ int updateAtisSequence(int interval, bool forceUpdate);
+
+ void setRwyUse(const FGRunwayPreference& ref);
};
-// There is probably a computationally cheaper way of
+// There is probably a computationally cheaper way of
// doing this.
void FGTaxiSegment::setDimensions(double elevation)
{
} else {
// If currNode points to the first node, this means the aircraft is not on the taxi node
// yet. Make sure to return a unique identifyer in this situation though, because otherwise
- // the speed adjust AI code may be unable to resolve whether two aircraft are on the same
- // taxi route or not. the negative of the preceding route seems a logical choice, as it is
- // unique for any starting location.
+ // the speed adjust AI code may be unable to resolve whether two aircraft are on the same
+ // taxi route or not. the negative of the preceding route seems a logical choice, as it is
+ // unique for any starting location.
// Note that this is probably just a temporary fix until I get Parking / tower control working.
*rte = -1 * *(currRoute);
}
return (*a) < (*b);
}
+bool compare_trafficrecords(FGTrafficRecord a, FGTrafficRecord b)
+{
+ return (a.getIntentions().size() < b.getIntentions().size());
+}
+
FGGroundNetwork::FGGroundNetwork()
{
hasNetwork = false;
}
cachefile << "[GroundNetcachedata:ref:2011:09:04]" << endl;
for (FGTaxiNodeVectorIterator node = nodes.begin();
- node != nodes.end(); node++) {
- if (saveData) {
+ node != nodes.end(); node++) {
+ if (saveData) {
cachefile << (*node)->getIndex () << " "
- << (*node)->getElevation () << " "
- << endl;
- }
+ << (*node)->getElevation () << " "
+ << endl;
+ }
delete(*node);
}
nodes.clear();
pushBackNodes.clear();
for (FGTaxiSegmentVectorIterator seg = segments.begin();
- seg != segments.end(); seg++) {
+ seg != segments.end(); seg++) {
delete(*seg);
}
segments.clear();
}
cachefile << "[GroundNetcachedata:ref:2011:09:04]" << endl;
for (FGTaxiNodeVectorIterator node = nodes.begin();
- node != nodes.end(); node++) {
- if (saveData) {
+ node != nodes.end(); node++) {
+ if (saveData) {
cachefile << (*node)->getIndex () << " "
- << (*node)->getElevation () << " "
- << endl;
- }
+ << (*node)->getElevation () << " "
+ << endl;
+ }
}
if (saveData) {
cachefile.close();
string revisionStr;
data >> revisionStr;
if (revisionStr != "[GroundNetcachedata:ref:2011:09:04]") {
- SG_LOG(SG_GENERAL, SG_ALERT,"GroundNetwork Warning: discarding outdated cachefile " <<
- cacheData.c_str() << " for Airport " << airport);
+ SG_LOG(SG_GENERAL, SG_ALERT,"GroundNetwork Warning: discarding outdated cachefile " <<
+ cacheData.c_str() << " for Airport " << airport);
} else {
for (FGTaxiNodeVectorIterator i = nodes.begin();
- i != nodes.end();
- i++) {
+ i != nodes.end();
+ i++) {
(*i)->setElevation(parent->getElevation() * SG_FEET_TO_METER);
data >> index >> elev;
if (data.eof())
int index = -1;
for (FGTaxiNodeVectorIterator itr = nodes.begin(); itr != nodes.end();
- itr++) {
+ itr++) {
double d = SGGeodesy::distanceM(aGeod, (*itr)->getGeod());
if (d < minDist) {
minDist = d;
FGTaxiNode *FGGroundNetwork::findNode(unsigned idx)
{ /*
- for (FGTaxiNodeVectorIterator
+ for (FGTaxiNodeVectorIterator
itr = nodes.begin();
itr != nodes.end(); itr++)
{
FGTaxiSegment *FGGroundNetwork::findSegment(unsigned idx)
{ /*
- for (FGTaxiSegmentVectorIterator
+ for (FGTaxiSegmentVectorIterator
itr = segments.begin();
itr != segments.end(); itr++)
{
if (itr->getIndex() == idx)
return itr->getAddress();
- }
+ }
*/
if ((idx > 0) && (idx <= segments.size()))
return segments[idx - 1]->getAddress();
FGTaxiRoute FGGroundNetwork::findShortestRoute(int start, int end,
- bool fullSearch)
+ bool fullSearch)
{
//implements Dijkstra's algorithm to find shortest distance route from start to end
//taken from http://en.wikipedia.org/wiki/Dijkstra's_algorithm
}
for (FGTaxiNodeVectorIterator
- itr = currNodesSet->begin(); itr != currNodesSet->end(); itr++) {
+ itr = currNodesSet->begin(); itr != currNodesSet->end(); itr++) {
(*itr)->setPathScore(HUGE_VAL); //infinity by all practical means
(*itr)->setPreviousNode(0); //
(*itr)->setPreviousSeg(0); //
while (!unvisited.empty()) {
FGTaxiNode *best = *(unvisited.begin());
for (FGTaxiNodeVectorIterator
- itr = unvisited.begin(); itr != unvisited.end(); itr++) {
+ itr = unvisited.begin(); itr != unvisited.end(); itr++) {
if ((*itr)->getPathScore() < best->getPathScore())
best = (*itr);
}
break;
} else {
for (FGTaxiSegmentVectorIterator
- seg = best->getBeginRoute();
- seg != best->getEndRoute(); seg++) {
+ seg = best->getBeginRoute();
+ seg != best->getEndRoute(); seg++) {
if (fullSearch || (*seg)->isPushBack()) {
FGTaxiNode *tgt = (*seg)->getEnd();
double alt =
rec.setPositionAndHeading(lat, lon, heading, speed, alt);
rec.setRadius(radius); // only need to do this when creating the record.
rec.setAircraft(aircraft);
- activeTraffic.push_back(rec);
+ activeTraffic.push_front(rec);
+
} else {
i->setPositionAndIntentions(currentPosition, intendedRoute);
i->setPositionAndHeading(lat, lon, heading, speed, alt);
* 9 = Acknowledge switch tower frequency
*************************************************************************************************************************/
bool FGGroundNetwork::checkTransmissionState(int minState, int maxState, TrafficVectorIterator i, time_t now, AtcMsgId msgId,
- AtcMsgDir msgDir)
+ AtcMsgDir msgDir)
{
int state = i->getState();
if ((state >= minState) && (state <= maxState) && available) {
int n = trans_num->getIntValue();
if (n == 0) {
trans_num->setIntValue(-1);
- // PopupCallback(n);
- //cerr << "Selected transmission message " << n << endl;
- FGATCManager *atc = (FGATCManager*) globals->get_subsystem("atc");
- FGATCDialogNew::instance()->removeEntry(1);
+ // PopupCallback(n);
+ //cerr << "Selected transmission message " << n << endl;
+ FGATCManager *atc = (FGATCManager*) globals->get_subsystem("atc");
+ FGATCDialogNew::instance()->removeEntry(1);
} else {
//cerr << "creating message for " << i->getAircraft()->getCallSign() << endl;
transmit(&(*i), msgId, msgDir, false);
}
void FGGroundNetwork::updateAircraftInformation(int id, double lat, double lon,
- double heading, double speed, double alt,
- double dt)
+ double heading, double speed, double alt,
+ double dt)
{
time_t currentTime = time(NULL);
if (nextSave < currentTime) {
saveElevationCache();
nextSave = currentTime + 100 + rand() % 200;
}
- // Check whether aircraft are on hold due to a preceding pushback. If so, make sure to
+ // Check whether aircraft are on hold due to a preceding pushback. If so, make sure to
// Transmit air-to-ground "Ready to taxi request:
// Transmit ground to air approval / hold
- // Transmit confirmation ...
+ // Transmit confirmation ...
// Probably use a status mechanism similar to the Engine start procedure in the startup controller.
bool needsTaxiClearance = current->getAircraft()->getTaxiClearanceRequest();
if (!needsTaxiClearance) {
checkHoldPosition(id, lat, lon, heading, speed, alt);
- if (checkForCircularWaits(id)) {
- i->setResolveCircularWait();
- }
+ //if (checkForCircularWaits(id)) {
+ // i->setResolveCircularWait();
+ //}
} else {
current->setHoldPosition(true);
int state = current->getState();
aircraft. For traffic that is on other routes we need to issue a "HOLD Position"
instruction. See below for the hold position instruction.
- Note that there currently still is one flaw in the logic that needs to be addressed.
+ Note that there currently still is one flaw in the logic that needs to be addressed.
There can be situations where one aircraft is in front of the current aircraft, on a separate
route, but really close after an intersection coming off the current route. This
aircraft is still close enough to block the current aircraft. This situation is currently
*/
void FGGroundNetwork::checkSpeedAdjustment(int id, double lat,
- double lon, double heading,
- double speed, double alt)
+ double lon, double heading,
+ double speed, double alt)
{
- TrafficVectorIterator current, closest;
+ TrafficVectorIterator current, closest, closestOnNetwork;
TrafficVectorIterator i = activeTraffic.begin();
bool otherReasonToSlowDown = false;
bool previousInstruction;
//TrafficVector iterator closest;
closest = current;
for (TrafficVectorIterator i = activeTraffic.begin();
- i != activeTraffic.end(); i++) {
+ i != activeTraffic.end(); i++) {
if (i == current) {
continue;
}
if ((dist < mindist) && (bearing < 60.0)) {
mindist = dist;
closest = i;
+ closestOnNetwork = i;
minbearing = bearing;
+
}
}
//Check traffic at the tower controller
if (towerController->hasActiveTraffic()) {
for (TrafficVectorIterator i =
- towerController->getActiveTraffic().begin();
- i != towerController->getActiveTraffic().end(); i++) {
+ towerController->getActiveTraffic().begin();
+ i != towerController->getActiveTraffic().end(); i++) {
//cerr << "Comparing " << current->getId() << " and " << i->getId() << endl;
SGGeod other(SGGeod::fromDegM(i->getLongitude(),
i->getLatitude(),
bearing = 360 - bearing;
if ((dist < mindist) && (bearing < 60.0)) {
//cerr << "Current aircraft " << current->getAircraft()->getTrafficRef()->getCallSign()
- // << " is closest to " << i->getAircraft()->getTrafficRef()->getCallSign()
- // << ", which has status " << i->getAircraft()->isScheduledForTakeoff()
+ // << " is closest to " << i->getAircraft()->getTrafficRef()->getCallSign()
+ // << ", which has status " << i->getAircraft()->isScheduledForTakeoff()
// << endl;
mindist = dist;
closest = i;
}
*/
current->clearSpeedAdjustment();
-
+ bool needBraking = false;
if (current->checkPositionAndIntentions(*closest)
- || otherReasonToSlowDown) {
+ || otherReasonToSlowDown) {
double maxAllowableDistance =
(1.1 * current->getRadius()) +
(1.1 * closest->getRadius());
if (closest->getId() != current->getId()) {
current->setSpeedAdjustment(closest->getSpeed() *
(mindist / 100));
- if (
- closest->getAircraft()->getTakeOffStatus() &&
+ needBraking = true;
+ if (
+ closest->getAircraft()->getTakeOffStatus() &&
(current->getAircraft()->getTrafficRef()->getDepartureAirport() == closest->getAircraft()->getTrafficRef()->getDepartureAirport()) &&
(current->getAircraft()->GetFlightPlan()->getRunway() == closest->getAircraft()->GetFlightPlan()->getRunway())
- )
- current->getAircraft()->scheduleForATCTowerDepartureControl(1);
+ )
+ current->getAircraft()->scheduleForATCTowerDepartureControl(1);
} else {
current->setSpeedAdjustment(0); // This can only happen when the user aircraft is the one closest
}
}
}
}
+ if ((closest == closestOnNetwork) && (current->getPriority() < closest->getPriority()) && needBraking) {
+ swap(current, closest);
+ }
}
}
TrafficVectorIterator current;
TrafficVectorIterator i = activeTraffic.begin();
if (activeTraffic.size()) {
- //while ((i->getId() != id) && i != activeTraffic.end())
+ //while ((i->getId() != id) && i != activeTraffic.end())
while (i != activeTraffic.end()) {
if (i->getId() == id) {
break;
bool origStatus = current->hasHoldPosition();
current->setHoldPosition(false);
SGGeod curr(SGGeod::fromDegM(lon, lat, alt));
+ int currentRoute = i->getCurrentPosition();
+ int nextRoute;
+ if (i->getIntentions().size()) {
+ nextRoute = (*(i->getIntentions().begin()));
+ } else {
+ nextRoute = 0;
+ }
+ if (currentRoute > 0) {
+ FGTaxiSegment *tx = findSegment(currentRoute);
+ FGTaxiSegment *nx;
+ if (nextRoute) {
+ nx = findSegment(nextRoute);
+ } else {
+ nx = tx;
+ }
+ if (tx->hasBlock() || nx->hasBlock() ) {
+ current->setHoldPosition(true);
+ }
+ }
- for (i = activeTraffic.begin(); i != activeTraffic.end(); i++) {
- if (i->getId() != current->getId()) {
- int node = current->crosses(this, *i);
- if (node != -1) {
- FGTaxiNode *taxiNode = findNode(node);
-
- // Determine whether it's save to continue or not.
- // If we have a crossing route, there are two possibilities:
- // 1) This is an interestion
- // 2) This is oncoming two-way traffic, using the same taxiway.
- //cerr << "Hold check 1 : " << id << " has common node " << node << endl;
-
- SGGeod other(SGGeod::
- fromDegM(i->getLongitude(), i->getLatitude(),
- i->getAltitude()));
- bool needsToWait;
- bool opposing;
- if (current->isOpposing(this, *i, node)) {
- needsToWait = true;
- opposing = true;
- //cerr << "Hold check 2 : " << node << " has opposing segment " << endl;
- // issue a "Hold Position" as soon as we're close to the offending node
- // For now, I'm doing this as long as the other aircraft doesn't
- // have a hold instruction as soon as we're within a reasonable
- // distance from the offending node.
- // This may be a bit of a conservative estimate though, as it may
- // be well possible that both aircraft can both continue to taxi
- // without crashing into each other.
- } else {
- opposing = false;
- if (SGGeodesy::distanceM(other, taxiNode->getGeod()) > 200) // 2.0*i->getRadius())
- {
- needsToWait = false;
- //cerr << "Hold check 3 : " << id <<" Other aircraft approaching node is still far away. (" << dist << " nm). Can safely continue "
- // << endl;
- } else {
+
+ /* for (i = activeTraffic.begin(); i != activeTraffic.end(); i++) {
+ if (i->getId() != current->getId()) {
+ int node = current->crosses(this, *i);
+ if (node != -1) {
+ FGTaxiNode *taxiNode = findNode(node);
+
+ // Determine whether it's save to continue or not.
+ // If we have a crossing route, there are two possibilities:
+ // 1) This is an interestion
+ // 2) This is oncoming two-way traffic, using the same taxiway.
+ //cerr << "Hold check 1 : " << id << " has common node " << node << endl;
+
+ SGGeod other(SGGeod::
+ fromDegM(i->getLongitude(), i->getLatitude(),
+ i->getAltitude()));
+ bool needsToWait;
+ bool opposing;
+ if (current->isOpposing(this, *i, node)) {
needsToWait = true;
- //cerr << "Hold check 4: " << id << " Would need to wait for other aircraft : distance = " << dist << " meters" << endl;
+ opposing = true;
+ //cerr << "Hold check 2 : " << node << " has opposing segment " << endl;
+ // issue a "Hold Position" as soon as we're close to the offending node
+ // For now, I'm doing this as long as the other aircraft doesn't
+ // have a hold instruction as soon as we're within a reasonable
+ // distance from the offending node.
+ // This may be a bit of a conservative estimate though, as it may
+ // be well possible that both aircraft can both continue to taxi
+ // without crashing into each other.
+ } else {
+ opposing = false;
+ if (SGGeodesy::distanceM(other, taxiNode->getGeod()) > 200) // 2.0*i->getRadius())
+ {
+ needsToWait = false;
+ //cerr << "Hold check 3 : " << id <<" Other aircraft approaching node is still far away. (" << dist << " nm). Can safely continue "
+ // << endl;
+ } else {
+ needsToWait = true;
+ //cerr << "Hold check 4: " << id << " Would need to wait for other aircraft : distance = " << dist << " meters" << endl;
+ }
}
- }
- double dist =
- SGGeodesy::distanceM(curr, taxiNode->getGeod());
- if (!(i->hasHoldPosition())) {
-
- if ((dist < 200) && //2.5*current->getRadius()) &&
- (needsToWait) && (i->onRoute(this, *current)) &&
- //((i->onRoute(this, *current)) || ((!(i->getSpeedAdjustment())))) &&
- (!(current->getId() == i->getWaitsForId())))
- //(!(i->getSpeedAdjustment()))) // &&
- //(!(current->getSpeedAdjustment())))
-
- {
- if (!(isUserAircraft(i->getAircraft()))) { // test code. Don't wait for the user, let the user wait for you.
- current->setHoldPosition(true);
- current->setWaitsForId(i->getId());
+ double dist =
+ SGGeodesy::distanceM(curr, taxiNode->getGeod());
+ if (!(i->hasHoldPosition())) {
+
+ if ((dist < 200) && //2.5*current->getRadius()) &&
+ (needsToWait) && (i->onRoute(this, *current)) &&
+ //((i->onRoute(this, *current)) || ((!(i->getSpeedAdjustment())))) &&
+ (!(current->getId() == i->getWaitsForId())))
+ //(!(i->getSpeedAdjustment()))) // &&
+ //(!(current->getSpeedAdjustment())))
+
+ {
+ if (!(isUserAircraft(i->getAircraft()))) { // test code. Don't wait for the user, let the user wait for you.
+ current->setHoldPosition(true);
+ current->setWaitsForId(i->getId());
+ }
+ //cerr << "Hold check 5: " << current->getCallSign() <<" Setting Hold Position: distance to node (" << node << ") "
+ // << dist << " meters. Waiting for " << i->getCallSign();
+ //if (opposing)
+ //cerr <<" [opposing] " << endl;
+ //else
+ // cerr << "[non-opposing] " << endl;
+ //if (i->hasSpeefAdjustment())
+ // {
+ // cerr << " (which in turn waits for ) " << i->
+ } else {
+ //cerr << "Hold check 6: " << id << " No need to hold yet: Distance to node : " << dist << " nm"<< endl;
}
- //cerr << "Hold check 5: " << current->getCallSign() <<" Setting Hold Position: distance to node (" << node << ") "
- // << dist << " meters. Waiting for " << i->getCallSign();
- //if (opposing)
- //cerr <<" [opposing] " << endl;
- //else
- // cerr << "[non-opposing] " << endl;
- //if (i->hasSpeefAdjustment())
- // {
- // cerr << " (which in turn waits for ) " << i->
- } else {
- //cerr << "Hold check 6: " << id << " No need to hold yet: Distance to node : " << dist << " nm"<< endl;
}
}
}
- }
- }
+ } */
bool currStatus = current->hasHoldPosition();
current->setHoldPosition(origStatus);
// Either a Hold Position or a resume taxi transmission has been issued
//int state = current->getState();
if (checkTransmissionState(1,1, current, now, MSG_ACKNOWLEDGE_HOLD_POSITION, ATC_AIR_TO_GROUND)) {
- current->setState(0);
- current->setHoldPosition(true);
+ current->setState(0);
+ current->setHoldPosition(true);
}
if (checkTransmissionState(2,2, current, now, MSG_ACKNOWLEDGE_RESUME_TAXI, ATC_AIR_TO_GROUND)) {
- current->setState(0);
- current->setHoldPosition(false);
+ current->setState(0);
+ current->setHoldPosition(false);
}
if (current->getAircraft()->getTakeOffStatus() && (current->getState() == 0)) {
- //cerr << "Scheduling " << current->getAircraft()->getCallSign() << " for hold short" << endl;
- current->setState(6);
- }
+ //cerr << "Scheduling " << current->getAircraft()->getCallSign() << " for hold short" << endl;
+ current->setState(6);
+ }
if (checkTransmissionState(6,6, 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)) {
- //current->setState(0);
-}
+ //current->setState(0);
+}
/**
* Check whether situations occur where the current aircraft is waiting for itself
- * due to higher order interactions.
+ * due to higher order interactions.
* A 'circular' wait is a situation where a waits for b, b waits for c, and c waits
- * for a. Ideally each aircraft only waits for one other aircraft, so by tracing
- * through this list of waiting aircraft, we can check if we'd eventually end back
+ * for a. Ideally each aircraft only waits for one other aircraft, so by tracing
+ * through this list of waiting aircraft, we can check if we'd eventually end back
* at the current aircraft.
*
* Note that we should consider the situation where we are actually checking aircraft
//printed = true;
TrafficVectorIterator i = activeTraffic.begin();
if (trafficSize) {
- //while ((i->getId() != id) && i != activeTraffic.end())
+ //while ((i->getId() != id) && i != activeTraffic.end())
while (i != activeTraffic.end()) {
if (i->getId() == target) {
break;
// actually this trap isn't as impossible as it first seemed:
// the setWaitsForID(id) is set to current when the aircraft
- // is waiting for the user controlled aircraft.
+ // is waiting for the user controlled aircraft.
//if (current->getId() == other->getId()) {
// cerr << "Caught the impossible trap" << endl;
// cerr << "Current = " << current->getId() << endl;
if (current->getId() == other->getId())
return false;
//}
- //cerr << current->getCallSign() << " (" << current->getId() << ") " << " -> " << other->getCallSign()
+ //cerr << current->getCallSign() << " (" << current->getId() << ") " << " -> " << other->getCallSign()
// << " (" << other->getId() << "); " << endl;;
//current = other;
}
//while (group->getNumChildren()) {
// cerr << "Number of children: " << group->getNumChildren() << endl;
//simgear::EffectGeode* geode = (simgear::EffectGeode*) group->getChild(0);
- //osg::MatrixTransform *obj_trans = (osg::MatrixTransform*) group->getChild(0);
- //geode->releaseGLObjects();
- //group->removeChild(geode);
- //delete geode;
+ //osg::MatrixTransform *obj_trans = (osg::MatrixTransform*) group->getChild(0);
+ //geode->releaseGLObjects();
+ //group->removeChild(geode);
+ //delete geode;
group = 0;
}
if (visible) {
// Handle start point
int pos = i->getCurrentPosition() - 1;
if (pos >= 0) {
-
+
SGGeod start(SGGeod::fromDeg((i->getLongitude()), (i->getLatitude())));
SGGeod end (SGGeod::fromDeg(segments[pos]->getEnd()->getLongitude(), segments[pos]->getEnd()->getLatitude()));
SGGeod center;
SGGeodesy::direct(start, heading, coveredDistance, center, az2);
//cerr << "Active Aircraft : Centerpoint = (" << center.getLatitudeDeg() << ", " << center.getLongitudeDeg() << "). Heading = " << heading << endl;
- ///////////////////////////////////////////////////////////////////////////////
+ ///////////////////////////////////////////////////////////////////////////////
// Make a helper function out of this
osg::Matrix obj_pos;
osg::MatrixTransform *obj_trans = new osg::MatrixTransform;
if (isUserAircraft((i)->getAircraft())) {
elevationStart = fgGetDouble("/position/ground-elev-m");
} else {
- elevationStart = ((i)->getAircraft()->_getAltitude());
+ elevationStart = ((i)->getAircraft()->_getAltitude());
}
double elevationEnd = segments[pos]->getEnd()->getElevation();
//cerr << "Using elevation " << elevationEnd << endl;
center2.setElevationM(SG_MAX_ELEVATION_M);
if (local_scenery->get_elevation_m( center2, elevationEnd, NULL )) {
elevation_feet = elevationEnd * SG_METER_TO_FEET + 0.5;
- //elevation_meters += 0.5;
+ //elevation_meters += 0.5;
}
- else {
+ else {
elevationEnd = parent->getElevation();
}
segments[pos]->getEnd()->setElevation(elevationEnd);
}
double elevationMean = (elevationStart + elevationEnd) / 2.0;
double elevDiff = elevationEnd - elevationStart;
-
- double slope = atan2(elevDiff, length) * SGD_RADIANS_TO_DEGREES;
-
- //cerr << "1. Using mean elevation : " << elevationMean << " and " << slope << endl;
+
+ double slope = atan2(elevDiff, length) * SGD_RADIANS_TO_DEGREES;
+
+ //cerr << "1. Using mean elevation : " << elevationMean << " and " << slope << endl;
WorldCoordinate( obj_pos, center.getLatitudeDeg(), center.getLongitudeDeg(), elevationMean+ 0.5, -(heading), slope );
geode->setName("test");
geode->addDrawable(geometry);
//osg::Node *custom_obj;
- SGMaterial *mat = matlib->find("UnidirectionalTaper");
+ SGMaterial *mat;
+ if (segments[pos]->hasBlock()) {
+ mat = matlib->find("UnidirectionalTaperRed");
+ } else {
+ mat = matlib->find("UnidirectionalTaperGreen");
+ }
if (mat)
geode->setEffect(mat->get_effect());
obj_trans->addChild(geode);
// wire as much of the scene graph together as we can
//->addChild( obj_trans );
group->addChild( obj_trans );
- /////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////
} else {
//cerr << "BIG FAT WARNING: current position is here : " << pos << endl;
}
- for(intVecIterator j = (i)->getIntentions().begin(); j != (i)->getIntentions().end(); j++) {
+ for (intVecIterator j = (i)->getIntentions().begin(); j != (i)->getIntentions().end(); j++) {
osg::Matrix obj_pos;
int k = (*j)-1;
if (k >= 0) {
elevation_feet = elevationStart * SG_METER_TO_FEET + 0.5;
//elevation_meters += 0.5;
}
- else {
+ else {
elevationStart = parent->getElevation();
}
segments[k]->getStart()->setElevation(elevationStart);
elevation_feet = elevationEnd * SG_METER_TO_FEET + 0.5;
//elevation_meters += 0.5;
}
- else {
+ else {
elevationEnd = parent->getElevation();
}
segments[k]->getEnd()->setElevation(elevationEnd);
double elevDiff = elevationEnd - elevationStart;
double length = segments[k]->getLength();
double slope = atan2(elevDiff, length) * SGD_RADIANS_TO_DEGREES;
-
- // cerr << "2. Using mean elevation : " << elevationMean << " and " << slope << endl;
+
+ // cerr << "2. Using mean elevation : " << elevationMean << " and " << slope << endl;
WorldCoordinate( obj_pos, segments[k]->getLatitude(), segments[k]->getLongitude(), elevationMean+ 0.5, -(segments[k]->getHeading()), slope );
geode->setName("test");
geode->addDrawable(geometry);
//osg::Node *custom_obj;
- SGMaterial *mat = matlib->find("UnidirectionalTaper");
+ SGMaterial *mat;
+ if (segments[k]->hasBlock()) {
+ mat = matlib->find("UnidirectionalTaperRed");
+ } else {
+ mat = matlib->find("UnidirectionalTaperGreen");
+ }
if (mat)
geode->setEffect(mat->get_effect());
obj_trans->addChild(geode);
string FGGroundNetwork::getName() {
return string(parent->getId() + "-ground");
}
+
+void FGGroundNetwork::update(double dt)
+{
+ for (FGTaxiSegmentVectorIterator tsi = segments.begin(); tsi != segments.end(); tsi++) {
+ (*tsi)->unblock();
+ }
+ int priority = 1;
+ //sort(activeTraffic.begin(), activeTraffic.end(), compare_trafficrecords);
+ // Handle traffic that is under ground control first; this way we'll prevent clutter at the gate areas.
+ // Don't allow an aircraft to pushback when a taxiing aircraft is currently using part of the intended route.
+ for (TrafficVectorIterator i = parent->getDynamics()->getStartupController()->getActiveTraffic().begin();
+ i != parent->getDynamics()->getStartupController()->getActiveTraffic().end(); i++) {
+ i->allowPushBack();
+ i->setPriority(priority++);
+ if (i->isActive(60)) {
+
+ // Check for all active aircraft whether it's current pos segment is
+ // an opposite of one of the departing aircraft's intentions
+ for (TrafficVectorIterator j = activeTraffic.begin(); j != activeTraffic.end(); j++) {
+ int pos = j->getCurrentPosition();
+ if (pos > 0) {
+ FGTaxiSegment *seg = segments[pos-1]->opposite();
+ if (seg) {
+ int posReverse = seg->getIndex();
+ for (intVecIterator k = i->getIntentions().begin(); k != i->getIntentions().end(); k++) {
+ if ((*k) == posReverse) {
+ i->denyPushBack();
+ segments[posReverse-1]->block();
+ }
+ }
+ }
+ }
+ }
+ // if the current aircraft is still allowed to pushback, we can start reserving a route for if by blocking all the entry taxiways.
+ if (i->pushBackAllowed()) {
+ int pos = i->getCurrentPosition();
+ if (pos > 0) {
+ FGTaxiSegment *seg = segments[pos-1];
+ FGTaxiNode *node = seg->getEnd();
+ for (FGTaxiSegmentVectorIterator tsi = segments.begin(); tsi != segments.end(); tsi++) {
+ if (((*tsi)->getEnd() == node) && ((*tsi) != seg)) {
+ (*tsi)->block();
+ }
+ }
+ }
+ for (intVecIterator j = i->getIntentions().begin(); j != i->getIntentions().end(); j++) {
+ int pos = (*j);
+ if (pos > 0) {
+ FGTaxiSegment *seg = segments[pos-1];
+ FGTaxiNode *node = seg->getEnd();
+ for (FGTaxiSegmentVectorIterator tsi = segments.begin(); tsi != segments.end(); tsi++) {
+ if (((*tsi)->getEnd() == node) && ((*tsi) != seg)) {
+ (*tsi)->block();
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ for (TrafficVectorIterator i = activeTraffic.begin(); i != activeTraffic.end(); i++) {
+ i->setPriority(priority++);
+ int pos = i->getCurrentPosition();
+ if (pos > 0) {
+ if (segments[pos-1]->hasBlock()) {
+ SG_LOG(SG_GENERAL, SG_ALERT, "Taxiway incursion for AI aircraft" << i->getAircraft()->getCallSign());
+ }
+
+ }
+ intVecIterator ivi;
+ for (ivi = i->getIntentions().begin(); ivi != i->getIntentions().end(); ivi++) {
+ int segIndex = (*ivi);
+ if (segIndex > 0) {
+ if (segments[segIndex-1]->hasBlock())
+ break;
+ }
+ }
+ //after this, ivi points just behind the last valid unblocked taxi segment.
+ for (intVecIterator j = i->getIntentions().begin(); j != ivi; j++) {
+ int pos = (*j);
+ if (pos > 0) {
+ FGTaxiSegment *seg = segments[pos-1];
+ FGTaxiNode *node = seg->getEnd();
+ for (FGTaxiSegmentVectorIterator tsi = segments.begin(); tsi != segments.end(); tsi++) {
+ if (((*tsi)->getEnd() == node) && ((*tsi) != seg)) {
+ (*tsi)->block();
+ }
+ }
+ }
+ }
+ }
+}
+
class FGTaxiSegment
{
private:
- int startNode;
- int endNode;
- double length;
- double heading;
- SGGeod center;
- bool isActive;
- bool isPushBackRoute;
- FGTaxiNode *start;
- FGTaxiNode *end;
- int index;
- FGTaxiSegment *oppositeDirection;
-
-
+ int startNode;
+ int endNode;
+ double length;
+ double heading;
+ SGGeod center;
+ bool isActive;
+ bool isPushBackRoute;
+ bool isBlocked;
+ FGTaxiNode *start;
+ FGTaxiNode *end;
+ int index;
+ FGTaxiSegment *oppositeDirection;
+
+
public:
- FGTaxiSegment() :
- startNode(0),
- endNode(0),
- length(0),
- heading(0),
- isActive(0),
- isPushBackRoute(0),
- start(0),
- end(0),
- index(0),
- oppositeDirection(0)
- {
- };
-
- FGTaxiSegment (const FGTaxiSegment &other) :
- startNode (other.startNode),
- endNode (other.endNode),
- length (other.length),
- heading (other.heading),
- center (other.center),
- isActive (other.isActive),
- isPushBackRoute (other.isPushBackRoute),
- start (other.start),
- end (other.end),
- index (other.index),
- oppositeDirection (other.oppositeDirection)
- {
- };
-
- FGTaxiSegment& operator=(const FGTaxiSegment &other)
- {
- startNode = other.startNode;
- endNode = other.endNode;
- length = other.length;
- heading = other.heading;
- center = other.center;
- isActive = other.isActive;
- isPushBackRoute = other.isPushBackRoute;
- start = other.start;
- end = other.end;
- index = other.index;
- oppositeDirection = other.oppositeDirection;
- return *this;
- };
-
- void setIndex (int val) { index = val; };
- void setStartNodeRef (int val) { startNode = val; };
- void setEndNodeRef (int val) { endNode = val; };
-
- void setOpposite(FGTaxiSegment *opp) { oppositeDirection = opp; };
-
- void setStart(FGTaxiNodeVector *nodes);
- void setEnd (FGTaxiNodeVector *nodes);
- void setPushBackType(bool val) { isPushBackRoute = val; };
- void setDimensions(double elevation);
-
- FGTaxiNode * getEnd() { return end;};
- FGTaxiNode * getStart() { return start; };
- double getLength() { return length; };
- int getIndex() { return index; };
- double getLatitude() { return center.getLatitudeDeg(); };
- double getLongitude() { return center.getLongitudeDeg(); };
- double getHeading() { return heading; };
- bool isPushBack() { return isPushBackRoute; };
-
- int getPenalty(int nGates);
-
- FGTaxiSegment *getAddress() { return this;};
-
- bool operator<(const FGTaxiSegment &other) const { return index < other.index; };
- //bool hasSmallerHeadingDiff (const FGTaxiSegment &other) const { return headingDiff < other.headingDiff; };
- FGTaxiSegment *opposite() { return oppositeDirection; };
- void setCourseDiff(double crse);
-
-
-
-
+ FGTaxiSegment() :
+ startNode(0),
+ endNode(0),
+ length(0),
+ heading(0),
+ isActive(0),
+ isPushBackRoute(0),
+ isBlocked(0),
+ start(0),
+ end(0),
+ index(0),
+ oppositeDirection(0)
+ {
+ };
+
+ FGTaxiSegment (const FGTaxiSegment &other) :
+ startNode (other.startNode),
+ endNode (other.endNode),
+ length (other.length),
+ heading (other.heading),
+ center (other.center),
+ isActive (other.isActive),
+ isPushBackRoute (other.isPushBackRoute),
+ isBlocked (other.isBlocked),
+ start (other.start),
+ end (other.end),
+ index (other.index),
+ oppositeDirection (other.oppositeDirection)
+ {
+ };
+
+ FGTaxiSegment& operator=(const FGTaxiSegment &other)
+ {
+ startNode = other.startNode;
+ endNode = other.endNode;
+ length = other.length;
+ heading = other.heading;
+ center = other.center;
+ isActive = other.isActive;
+ isPushBackRoute = other.isPushBackRoute;
+ isBlocked = other.isBlocked;
+ start = other.start;
+ end = other.end;
+ index = other.index;
+ oppositeDirection = other.oppositeDirection;
+ return *this;
+ };
+
+ void setIndex (int val) {
+ index = val;
+ };
+ void setStartNodeRef (int val) {
+ startNode = val;
+ };
+ void setEndNodeRef (int val) {
+ endNode = val;
+ };
+
+ void setOpposite(FGTaxiSegment *opp) {
+ oppositeDirection = opp;
+ };
+
+ void setStart(FGTaxiNodeVector *nodes);
+ void setEnd (FGTaxiNodeVector *nodes);
+ void setPushBackType(bool val) {
+ isPushBackRoute = val;
+ };
+ void setDimensions(double elevation);
+ void block() {
+ isBlocked = true;
+ }
+ void unblock() {
+ isBlocked = false;
+ };
+ bool hasBlock() {
+ return isBlocked;
+ };
+
+ FGTaxiNode * getEnd() {
+ return end;
+ };
+ FGTaxiNode * getStart() {
+ return start;
+ };
+ double getLength() {
+ return length;
+ };
+ int getIndex() {
+ return index;
+ };
+ double getLatitude() {
+ return center.getLatitudeDeg();
+ };
+ double getLongitude() {
+ return center.getLongitudeDeg();
+ };
+ double getHeading() {
+ return heading;
+ };
+ bool isPushBack() {
+ return isPushBackRoute;
+ };
+
+ int getPenalty(int nGates);
+
+ FGTaxiSegment *getAddress() {
+ return this;
+ };
+
+ bool operator<(const FGTaxiSegment &other) const {
+ return index < other.index;
+ };
+ //bool hasSmallerHeadingDiff (const FGTaxiSegment &other) const { return headingDiff < other.headingDiff; };
+ FGTaxiSegment *opposite() {
+ return oppositeDirection;
+ };
+ void setCourseDiff(double crse);
+
+
+
+
};
class FGTaxiRoute
{
private:
- intVec nodes;
- intVec routes;
- double distance;
+ intVec nodes;
+ intVec routes;
+ double distance;
// int depth;
- intVecIterator currNode;
- intVecIterator currRoute;
+ intVecIterator currNode;
+ intVecIterator currRoute;
public:
- FGTaxiRoute() { distance = 0; currNode = nodes.begin(); currRoute = routes.begin();};
- FGTaxiRoute(intVec nds, intVec rts, double dist, int dpth) {
- nodes = nds;
- routes = rts;
- distance = dist;
- currNode = nodes.begin();
- currRoute = routes.begin();
+ FGTaxiRoute() {
+ distance = 0;
+ currNode = nodes.begin();
+ currRoute = routes.begin();
+ };
+ FGTaxiRoute(intVec nds, intVec rts, double dist, int dpth) {
+ nodes = nds;
+ routes = rts;
+ distance = dist;
+ currNode = nodes.begin();
+ currRoute = routes.begin();
// depth = dpth;
- };
+ };
- FGTaxiRoute& operator= (const FGTaxiRoute &other) {
- nodes = other.nodes;
- routes = other.routes;
- distance = other.distance;
+ FGTaxiRoute& operator= (const FGTaxiRoute &other) {
+ nodes = other.nodes;
+ routes = other.routes;
+ distance = other.distance;
// depth = other.depth;
- currNode = nodes.begin();
- currRoute = routes.begin();
- return *this;
- };
-
- FGTaxiRoute(const FGTaxiRoute& copy) :
- nodes(copy.nodes),
- routes(copy.routes),
- distance(copy.distance),
+ currNode = nodes.begin();
+ currRoute = routes.begin();
+ return *this;
+ };
+
+ FGTaxiRoute(const FGTaxiRoute& copy) :
+ nodes(copy.nodes),
+ routes(copy.routes),
+ distance(copy.distance),
// depth(copy.depth),
- currNode(nodes.begin()),
- currRoute(routes.begin())
- {};
-
- bool operator< (const FGTaxiRoute &other) const {return distance < other.distance; };
- bool empty () { return nodes.begin() == nodes.end(); };
- bool next(int *nde);
- bool next(int *nde, int *rte);
- void rewind(int legNr);
-
- void first() { currNode = nodes.begin(); currRoute = routes.begin(); };
- int size() { return nodes.size(); };
- int nodesLeft() { return nodes.end() - currNode; };
+ currNode(nodes.begin()),
+ currRoute(routes.begin())
+ {};
+
+ bool operator< (const FGTaxiRoute &other) const {
+ return distance < other.distance;
+ };
+ bool empty () {
+ return nodes.begin() == nodes.end();
+ };
+ bool next(int *nde);
+ bool next(int *nde, int *rte);
+ void rewind(int legNr);
+
+ void first() {
+ currNode = nodes.begin();
+ currRoute = routes.begin();
+ };
+ int size() {
+ return nodes.size();
+ };
+ int nodesLeft() {
+ return nodes.end() - currNode;
+ };
// int getDepth() { return depth; };
};
class FGGroundNetwork : public FGATCController
{
private:
- bool hasNetwork;
- bool networkInitialized;
- time_t nextSave;
- //int maxDepth;
- int count;
- FGTaxiNodeVector nodes;
- FGTaxiNodeVector pushBackNodes;
- FGTaxiSegmentVector segments;
- //intVec route;
- //intVec nodesStack;
- //intVec routesStack;
- TaxiRouteVector routes;
- TrafficVector activeTraffic;
- TrafficVectorIterator currTraffic;
+ bool hasNetwork;
+ bool networkInitialized;
+ time_t nextSave;
+ //int maxDepth;
+ int count;
+ FGTaxiNodeVector nodes;
+ FGTaxiNodeVector pushBackNodes;
+ FGTaxiSegmentVector segments;
+ //intVec route;
+ //intVec nodesStack;
+ //intVec routesStack;
+ TaxiRouteVector routes;
+ TrafficVector activeTraffic;
+ TrafficVectorIterator currTraffic;
- bool foundRoute;
- double totalDistance, maxDistance;
- FGTowerController *towerController;
- FGAirport *parent;
+ bool foundRoute;
+ double totalDistance, maxDistance;
+ FGTowerController *towerController;
+ FGAirport *parent;
- //void printRoutingError(string);
+ //void printRoutingError(string);
- void checkSpeedAdjustment(int id, double lat, double lon,
- double heading, double speed, double alt);
- void checkHoldPosition(int id, double lat, double lon,
- double heading, double speed, double alt);
+ void checkSpeedAdjustment(int id, double lat, double lon,
+ double heading, double speed, double alt);
+ void checkHoldPosition(int id, double lat, double lon,
+ double heading, double speed, double alt);
public:
- FGGroundNetwork();
- ~FGGroundNetwork();
-
- void addNode (const FGTaxiNode& node);
- void addNodes (FGParkingVec *parkings);
- void addSegment(const FGTaxiSegment& seg);
-
- void init();
- bool exists() { return hasNetwork; };
- void setTowerController(FGTowerController *twrCtrlr) { towerController = twrCtrlr; };
-
- int findNearestNode(double lat, double lon);
- int findNearestNode(const SGGeod& aGeod);
-
- FGTaxiNode *findNode(unsigned idx);
- FGTaxiSegment *findSegment(unsigned idx);
- FGTaxiRoute findShortestRoute(int start, int end, bool fullSearch=true);
- //void trace(FGTaxiNode *, int, int, double dist);
-
- int getNrOfNodes() { return nodes.size(); };
-
- void setParent(FGAirport *par) { parent = par; };
-
- virtual void announcePosition(int id, FGAIFlightPlan *intendedRoute, int currentRoute,
- double lat, double lon, double hdg, double spd, double alt,
- double radius, int leg, FGAIAircraft *aircraft);
- virtual void signOff(int id);
- virtual void updateAircraftInformation(int id, double lat, double lon, double heading, double speed, double alt, double dt);
- virtual bool hasInstruction(int id);
- virtual FGATCInstruction getInstruction(int id);
-
- bool checkTransmissionState(int minState, int MaxState, TrafficVectorIterator i, time_t now, AtcMsgId msgId,
- AtcMsgDir msgDir);
- bool checkForCircularWaits(int id);
- virtual void render(bool);
- virtual string getName();
-
- void saveElevationCache();
+ FGGroundNetwork();
+ ~FGGroundNetwork();
+
+ void addNode (const FGTaxiNode& node);
+ void addNodes (FGParkingVec *parkings);
+ void addSegment(const FGTaxiSegment& seg);
+
+ void init();
+ bool exists() {
+ return hasNetwork;
+ };
+ void setTowerController(FGTowerController *twrCtrlr) {
+ towerController = twrCtrlr;
+ };
+
+ int findNearestNode(double lat, double lon);
+ int findNearestNode(const SGGeod& aGeod);
+
+ FGTaxiNode *findNode(unsigned idx);
+ FGTaxiSegment *findSegment(unsigned idx);
+ FGTaxiRoute findShortestRoute(int start, int end, bool fullSearch=true);
+ //void trace(FGTaxiNode *, int, int, double dist);
+
+ int getNrOfNodes() {
+ return nodes.size();
+ };
+
+ void setParent(FGAirport *par) {
+ parent = par;
+ };
+
+ virtual void announcePosition(int id, FGAIFlightPlan *intendedRoute, int currentRoute,
+ double lat, double lon, double hdg, double spd, double alt,
+ double radius, int leg, FGAIAircraft *aircraft);
+ virtual void signOff(int id);
+ virtual void updateAircraftInformation(int id, double lat, double lon, double heading, double speed, double alt, double dt);
+ virtual bool hasInstruction(int id);
+ virtual FGATCInstruction getInstruction(int id);
+
+ bool checkTransmissionState(int minState, int MaxState, TrafficVectorIterator i, time_t now, AtcMsgId msgId,
+ AtcMsgDir msgDir);
+ bool checkForCircularWaits(int id);
+ virtual void render(bool);
+ virtual string getName();
+ virtual void update(double dt);
+
+ void saveElevationCache();
};
FGScheduledFlight *flight = NULL;
do {
if (currentDestination.empty()) {
- flight = findAvailableFlight(userPort, flightIdentifier, now, (now+6400));
+ //flight = findAvailableFlight(userPort, flightIdentifier, now, (now+1800));
if (!flight)
flight = findAvailableFlight(currentDestination, flightIdentifier);
} else {
<< " " << arrT << ":");
flights.push_back(flight);
- } while (currentDestination != startingPort);
+ } while (1); //(currentDestination != startingPort);
SG_LOG(SG_GENERAL, SG_BULK, " Done ");
}