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: " <<rwy._heading << endl; - //cerr << "Wind Speed : " << windSpeed << endl; if (hdgDiff > 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;