From: durk Date: Sat, 4 Mar 2006 08:49:36 +0000 (+0000) Subject: Improved selection of active runway (currently AI traffic only). X-Git-Url: https://git.mxchange.org/?a=commitdiff_plain;h=b9752635a9360e577f43d978702adf2656199ea6;p=flightgear.git Improved selection of active runway (currently AI traffic only). The original code selected the most preferable runway combination, regardless of which combination was currently active. This patch builds in some additional resistance against change, by keeping track of which runways are already in use, and forces a change in active runways only when new (wheather/time of day) conditions force it to do so, resulting in much more consistent runway assignment. behavior. --- diff --git a/src/Airports/dynamics.cxx b/src/Airports/dynamics.cxx index 517e25bea..4e3384e64 100644 --- a/src/Airports/dynamics.cxx +++ b/src/Airports/dynamics.cxx @@ -486,60 +486,61 @@ void FGAirportDynamics::getActiveRunway(const string &trafficType, int action, s windSpeed = stationweather.get_wind_speed_kt(); windHeading = stationweather.get_wind_from_heading_deg(); - double averageWindSpeed = 0; - double averageWindHeading = 0; - double cosHeading = 0; - double sinHeading = 0; - // Initialize at the beginning of the next day or startup - if ((lastUpdate == 0) || (dayStart < lastUpdate)) - { - for (int i = 0; i < 10; i++) - { - avWindHeading [i] = windHeading; - avWindSpeed [i] = windSpeed; - } - } - else - { - if (windSpeed != avWindSpeed[9]) // update if new metar data - { - // shift the running average - for (int i = 0; i < 9 ; i++) - { - avWindHeading[i] = avWindHeading[i+1]; - avWindSpeed [i] = avWindSpeed [i+1]; - } - } - avWindHeading[9] = windHeading; - avWindSpeed [9] = windSpeed; - } + // double averageWindSpeed = 0; +// double averageWindHeading = 0; +// double cosHeading = 0; +// double sinHeading = 0; +// // Initialize at the beginning of the next day or startup +// if ((lastUpdate == 0) || (dayStart < lastUpdate)) +// { +// for (int i = 0; i < 10; i++) +// { +// avWindHeading [i] = windHeading; +// avWindSpeed [i] = windSpeed; +// } +// } +// else +// { +// if (windSpeed != avWindSpeed[9]) // update if new metar data +// { +// // shift the running average +// for (int i = 0; i < 9 ; i++) +// { +// avWindHeading[i] = avWindHeading[i+1]; +// avWindSpeed [i] = avWindSpeed [i+1]; +// } +// } +// avWindHeading[9] = windHeading; +// avWindSpeed [9] = windSpeed; +// } - for (int i = 0; i < 10; i++) - { - averageWindSpeed += avWindSpeed [i]; - //averageWindHeading += avWindHeading [i]; - cosHeading += cos(avWindHeading[i] * SG_DEGREES_TO_RADIANS); - sinHeading += sin(avWindHeading[i] * SG_DEGREES_TO_RADIANS); - } - averageWindSpeed /= 10; - //averageWindHeading /= 10; - cosHeading /= 10; - sinHeading /= 10; - averageWindHeading = atan2(sinHeading, cosHeading) *SG_RADIANS_TO_DEGREES; - if (averageWindHeading < 0) - averageWindHeading += 360.0; - //cerr << "Wind Heading " << windHeading << " average " << averageWindHeading << endl; - //cerr << "Wind Speed " << windSpeed << " average " << averageWindSpeed << endl; - lastUpdate = dayStart; - //if (wind_speed == 0) { - // wind_heading = 270; This forces West-facing rwys to be used in no-wind situations - // which is consistent with Flightgear's initial setup. - //} +// for (int i = 0; i < 10; i++) +// { +// averageWindSpeed += avWindSpeed [i]; +// //averageWindHeading += avWindHeading [i]; +// cosHeading += cos(avWindHeading[i] * SG_DEGREES_TO_RADIANS); +// sinHeading += sin(avWindHeading[i] * SG_DEGREES_TO_RADIANS); +// } +// averageWindSpeed /= 10; +// //averageWindHeading /= 10; +// cosHeading /= 10; +// sinHeading /= 10; +// averageWindHeading = atan2(sinHeading, cosHeading) *SG_RADIANS_TO_DEGREES; +// if (averageWindHeading < 0) +// averageWindHeading += 360.0; +// //cerr << "Wind Heading " << windHeading << " average " << averageWindHeading << endl; +// //cerr << "Wind Speed " << windSpeed << " average " << averageWindSpeed << endl; +// lastUpdate = dayStart; +// //if (wind_speed == 0) { +// // wind_heading = 270; This forces West-facing rwys to be used in no-wind situations +// // which is consistent with Flightgear's initial setup. +// //} //string rwy_no = globals->get_runways()->search(apt->getId(), int(wind_heading)); string scheduleName; //cerr << "finding active Runway for" << _id << endl; //cerr << "Nr of seconds since day start << " << dayStart << endl; + ScheduleTime *currSched; //cerr << "A"<< endl; currSched = rwyPrefs.getSchedule(trafficType.c_str()); @@ -559,7 +560,19 @@ void FGAirportDynamics::getActiveRunway(const string &trafficType, int action, s return; nrActiveRunways = currRunwayGroup->getNrActiveRunways(); //cerr << "Nr of Active Runways = " << nrActiveRunways << endl; - currRunwayGroup->setActive(_id, averageWindSpeed, averageWindHeading, maxTail, maxCross); + + // + currRunwayGroup->setActive(_id, + windSpeed, + windHeading, + maxTail, + maxCross, + ¤tlyActive); + + // Note that I SHOULD keep three lists in memory, one for + // general aviation, one for commercial and one for military + // traffic. + currentlyActive.clear(); nrActiveRunways = currRunwayGroup->getNrActiveRunways(); for (int i = 0; i < nrActiveRunways; i++) { @@ -568,11 +581,13 @@ void FGAirportDynamics::getActiveRunway(const string &trafficType, int action, s if (type == "landing") { landing.push_back(name); + currentlyActive.push_back(name); //cerr << "Landing " << name << endl; } if (type == "takeoff") { takeoff.push_back(name); + currentlyActive.push_back(name); //cerr << "takeoff " << name << endl; } } @@ -582,6 +597,9 @@ void FGAirportDynamics::getActiveRunway(const string &trafficType, int action, s int nr = takeoff.size(); if (nr) { + // Note that the randomization below, is just a placeholder to choose between + // multiple active runways for this action. This should be + // under ATC control. runway = takeoff[(rand() % nr)]; } else diff --git a/src/Airports/dynamics.hxx b/src/Airports/dynamics.hxx index 30b4bf7f9..4eb8b4bc1 100644 --- a/src/Airports/dynamics.hxx +++ b/src/Airports/dynamics.hxx @@ -45,6 +45,7 @@ private: string prevTrafficType; stringVec landing; stringVec takeoff; + stringVec currentlyActive; // Experimental keep a running average of wind dir and speed to prevent // Erratic runway changes. diff --git a/src/Airports/runwayprefs.cxx b/src/Airports/runwayprefs.cxx index d549cac5a..e829c8dd0 100644 --- a/src/Airports/runwayprefs.cxx +++ b/src/Airports/runwayprefs.cxx @@ -197,7 +197,8 @@ void RunwayGroup::setActive(const string &aptId, double windSpeed, double windHeading, double maxTail, - double maxCross) + double maxCross, + stringVec *currentlyActive) { FGRunway rwy; @@ -209,16 +210,31 @@ void RunwayGroup::setActive(const string &aptId, double crossWind; double tailWind; string name; + //stringVec names; + int bestMatch = 0, bestChoice = 0; if (activeRwys > 0) - { + { + // Now downward iterate across all the possible preferences + // starting by the least preferred choice working toward the most preferred choice + nrOfPreferences = rwyList[0].getRwyList()->size(); - for (int i = 0; i < nrOfPreferences; i++) + bool validSelection = true; + bool foundValidSelection = false; + for (int i = nrOfPreferences-1; i >= 0; i--) { - bool validSelection = true; + int match = 0; + + + // Test each runway listed in the preference to see if it's possible to use + // If one runway of the selection isn't allowed, we need to exclude this + // preference, however, we don't want to stop right there, because we also + // don't want to randomly swap runway preferences, unless there is a need to. + // + for (int j = 0; j < activeRwys; j++) { - //cerr << "I J " << i << " " << j << endl; + validSelection = true; name = rwyList[j].getRwyList(i); //cerr << "Name of Runway: " << name << endl; if (globals->get_runways()->search( aptId, @@ -238,20 +254,42 @@ void RunwayGroup::setActive(const string &aptId, //cerr << "Tailwind : " << tailWind << endl; //cerr << "Crosswnd : " << crossWind << endl; if ((tailWind > maxTail) || (crossWind > maxCross)) - validSelection = false; + { + //cerr << "Invalid : "; + validSelection = false; + } + else + { + //cerr << "Valid : "; + } }else { - SG_LOG( SG_GENERAL, SG_INFO, "Failed to find runway " << name << " at " << aptId ); - exit(1); - } - + SG_LOG( SG_GENERAL, SG_INFO, "Failed to find runway " << name << " at " << aptId ); + exit(1); + } } - if (validSelection) + if (validSelection) { - //cerr << "Valid runay selection : " << i << endl; - nrActive = activeRwys; - active = i; - return; - } + //cerr << "Valid : "; + foundValidSelection = true; + for (stringVecIterator it = currentlyActive->begin(); + it != currentlyActive->end(); it++) + { + if ((*it) == name) + match++; + if (match >= bestMatch) { + bestMatch = match; + bestChoice = i; + } + } + } + //cerr << "Preference " << i << " bestMatch " << bestMatch << " choice " << bestChoice << endl; + } + if (foundValidSelection) + { + //cerr << "Valid runay selection : " << bestChoice << endl; + nrActive = activeRwys; + active = bestChoice; + return; } // If this didn't work, due to heavy winds, try again // but select only one landing and one takeoff runway. @@ -280,16 +318,11 @@ void RunwayGroup::setActive(const string &aptId, { //cerr << "Succes" << endl; hdgDiff = fabs(windHeading - rwy._heading); - //cerr << "Wind Heading: " << windHeading << "Runway Heading: " < 180) hdgDiff = 360 - hdgDiff; - //cerr << "Heading diff: " << hdgDiff << endl; hdgDiff *= ((2*M_PI)/360.0); // convert to radians crossWind = windSpeed * sin(hdgDiff); tailWind = -windSpeed * cos(hdgDiff); - //cerr << "Tailwind : " << tailWind << endl; - //cerr << "Crosswnd : " << crossWind << endl; if ((tailWind > maxTail) || (crossWind > maxCross)) validSelection = false; }else { @@ -308,19 +341,7 @@ void RunwayGroup::setActive(const string &aptId, } } active = -1; - //RunwayListVectorIterator i; // = rwlist.begin(); - //stringVecIterator j; - //for (i = rwyList.begin(); i != rwyList.end(); i++) - // { - // cerr << i->getType(); - // for (j = i->getRwyList()->begin(); j != i->getRwyList()->end(); j++) - // { - // cerr << (*j); - // } - // cerr << endl; - // } - //for (int - + nrActive = 0; } void RunwayGroup::getActive(int i, string &name, string &type) diff --git a/src/Airports/runwayprefs.hxx b/src/Airports/runwayprefs.hxx index e45a057ea..c52312c89 100644 --- a/src/Airports/runwayprefs.hxx +++ b/src/Airports/runwayprefs.hxx @@ -96,6 +96,7 @@ private: //stringVec runwayNames; int choice[2]; int nrActive; + public: RunwayGroup() {}; RunwayGroup(const RunwayGroup &other); @@ -103,7 +104,7 @@ public: void setName(const string& nm) { name = nm; }; void add(const RunwayList& list) { rwyList.push_back(list);}; - void setActive(const string& aptId, double windSpeed, double windHeading, double maxTail, double maxCross); + void setActive(const string& aptId, double windSpeed, double windHeading, double maxTail, double maxCross, stringVec *curr); int getNrActiveRunways() { return nrActive;}; void getActive(int i, string& name, string& type); @@ -132,6 +133,7 @@ private: RunwayList rwyList; RunwayGroup rwyGroup; PreferenceList preferences; + time_t processTime(const string&); bool initialized;