From fc7e9740c3e34e1725ac28563285b7e6fa41972b Mon Sep 17 00:00:00 2001 From: James Turner Date: Wed, 1 Jun 2011 23:55:04 +0100 Subject: [PATCH 1/5] Improvements to exposing FGPositioned via commands - support frequency searches. --- src/Main/fg_commands.cxx | 63 +++++++++++++++++++++++++++++++ src/Navaids/PositionedBinding.cxx | 25 +++++++++--- src/Navaids/positioned.cxx | 2 +- 3 files changed, 84 insertions(+), 6 deletions(-) diff --git a/src/Main/fg_commands.cxx b/src/Main/fg_commands.cxx index c2058ba19..f9933243d 100644 --- a/src/Main/fg_commands.cxx +++ b/src/Main/fg_commands.cxx @@ -34,6 +34,9 @@ #include #include #include +#include +#include +#include #include "fg_init.hxx" #include "fg_io.hxx" @@ -1349,7 +1352,63 @@ do_release_cockpit_button (const SGPropertyNode *arg) return true; } +static SGGeod commandSearchPos(const SGPropertyNode* arg) +{ + if (arg->hasChild("longitude-deg") && arg->hasChild("latitude-deg")) { + return SGGeod::fromDeg(arg->getDoubleValue("longitude-deg"), + arg->getDoubleValue("latitude-deg")); + } + + // use current viewer/aircraft position + return SGGeod::fromDeg(fgGetDouble("/position/longitude-deg"), + fgGetDouble("/position/latitude-deg")); +} + +static bool +do_comm_search(const SGPropertyNode* arg) +{ + SGGeod pos = commandSearchPos(arg); + int khz = static_cast(arg->getDoubleValue("frequency-mhz") * 100.0 + 0.25); + + flightgear::CommStation* sta = flightgear::CommStation::findByFreq(khz, pos, NULL); + if (!sta) { + return true; + } + + SGPropertyNode* result = fgGetNode(arg->getStringValue("result")); + sta->createBinding(result); + return true; +} +static bool +do_nav_search(const SGPropertyNode* arg) +{ + SGGeod pos = commandSearchPos(arg); + double mhz = arg->getDoubleValue("frequency-mhz"); + + FGNavList* navList = globals->get_navlist(); + string type(arg->getStringValue("type", "vor")); + if (type == "dme") { + navList = globals->get_dmelist(); + } else if (type == "tacan") { + navList = globals->get_tacanlist(); + } + + FGNavRecord* nav = navList->findByFreq(mhz, pos); + if (!nav && (type == "vor")) { + // if we're searching VORs, look for localizers too + nav = globals->get_loclist()->findByFreq(mhz, pos); + } + + if (!nav) { + return true; + } + + SGPropertyNode* result = fgGetNode(arg->getStringValue("result")); + nav->createBinding(result); + return true; +} + //////////////////////////////////////////////////////////////////////// // Command setup. //////////////////////////////////////////////////////////////////////// @@ -1421,6 +1480,10 @@ static struct { { "dump-terrainbranch", do_dump_terrain_branch }, { "print-visible-scene", do_print_visible_scene_info }, { "reload-shaders", do_reload_shaders }, + + { "find-navaid", do_nav_search }, + { "find-comm", do_comm_search }, + { 0, 0 } // zero-terminated }; diff --git a/src/Navaids/PositionedBinding.cxx b/src/Navaids/PositionedBinding.cxx index c1ecdf0aa..8a2f23f6f 100644 --- a/src/Navaids/PositionedBinding.cxx +++ b/src/Navaids/PositionedBinding.cxx @@ -148,12 +148,27 @@ AirportBinding::AirportBinding(const FGAirport* apt, SGPropertyNode* nd) : for (unsigned int c=0; ccommStations().size(); ++c) { flightgear::CommStation* comm = apt->commStations()[c]; std::string tynm = FGPositioned::nameForType(comm->type()); - int count = nd->getChildren(tynm).size(); - SGPropertyNode* commNode = nd->getChild(tynm, count, true); - commNode->setStringValue("ident", comm->ident()); - commNode->setDoubleValue("frequency-mhz", comm->freqMHz()); - } + // for some standard frequence types, we don't care about the ident, + // so just list the frequencies under one group. + if ((comm->type() == FGPositioned::FREQ_ATIS) || + (comm->type() == FGPositioned::FREQ_AWOS) || + (comm->type() == FGPositioned::FREQ_TOWER) || + (comm->type() == FGPositioned::FREQ_GROUND)) + { + SGPropertyNode* commNode = nd->getChild(tynm, 0, true); + int count = nd->getChildren("frequency-mhz").size(); + SGPropertyNode* freqNode = commNode->getChild("frequency-mhz", count, true); + freqNode->setDoubleValue(comm->freqMHz()); + } else { + // for other kinds of frequency, there's more variation, so list the ID too + int count = nd->getChildren(tynm).size(); + SGPropertyNode* commNode = nd->getChild(tynm, count, true); + commNode->setStringValue("ident", comm->ident()); + commNode->setDoubleValue("frequency-mhz", comm->freqMHz()); + + } + } // of airprot comm stations iteration } CommStationBinding::CommStationBinding(const CommStation* sta, SGPropertyNode* node) : diff --git a/src/Navaids/positioned.cxx b/src/Navaids/positioned.cxx index b67e9c75d..88613881b 100644 --- a/src/Navaids/positioned.cxx +++ b/src/Navaids/positioned.cxx @@ -861,7 +861,7 @@ FGPositioned::Filter* createSearchFilter(const SGPropertyNode* arg) return NULL; } -SGGeod commandSearchPos(const SGPropertyNode* arg) +static SGGeod commandSearchPos(const SGPropertyNode* arg) { if (arg->hasChild("longitude-deg") && arg->hasChild("latitude-deg")) { return SGGeod::fromDeg(arg->getDoubleValue("longitude-deg"), From 5572c53a7ebf2b3a0b683f1e2baedeaf9cac7d3d Mon Sep 17 00:00:00 2001 From: James Turner Date: Thu, 2 Jun 2011 00:33:47 +0100 Subject: [PATCH 2/5] Minor tweaks to positioned find commands. --- src/Navaids/positioned.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Navaids/positioned.cxx b/src/Navaids/positioned.cxx index 88613881b..7aa183eba 100644 --- a/src/Navaids/positioned.cxx +++ b/src/Navaids/positioned.cxx @@ -841,7 +841,7 @@ FGPositioned::sortByRange(List& aResult, const SGGeod& aPos) FGPositioned::Filter* createSearchFilter(const SGPropertyNode* arg) { - string sty(arg->getStringValue("type", 0)); + string sty(arg->getStringValue("type", "any")); FGPositioned::Type ty = FGPositioned::typeFromName(sty); double minRunwayLenFt = arg->getDoubleValue("min-runway-length-ft", -1.0); @@ -932,7 +932,7 @@ bool commandFindByIdent(const SGPropertyNode* arg) if (arg->hasChild("name")) { results = FGPositioned::findAllWithName(arg->getStringValue("name"), filt.get(), exact); } else if (arg->hasChild("ident")) { - results = FGPositioned::findAllWithName(arg->getStringValue("ident"), filt.get(), exact); + results = FGPositioned::findAllWithIdent(arg->getStringValue("ident"), filt.get(), exact); } else { SG_LOG(SG_GENERAL, SG_WARN, "commandFindByIdent: no search term defined"); return false; From 370645e5937d2cf7a51d9a56dc7dfb110b385f24 Mon Sep 17 00:00:00 2001 From: ThorstenB Date: Thu, 2 Jun 2011 23:53:42 +0200 Subject: [PATCH 3/5] Olaf Flebbe: #332, Improve Nasal's "systime" method Use gettimeofday for determine time, rather than time() and gettimeofday() --- src/Scripting/NasalSys.cxx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Scripting/NasalSys.cxx b/src/Scripting/NasalSys.cxx index 2690bda6d..af67ae368 100644 --- a/src/Scripting/NasalSys.cxx +++ b/src/Scripting/NasalSys.cxx @@ -476,10 +476,9 @@ static naRef f_systime(naContext c, naRef me, int argc, naRef* args) // Converts from 100ns units in 1601 epoch to unix epoch in sec return naNum((t * 1e-7) - 11644473600.0); #else - time_t t; struct timeval td; - do { t = time(0); gettimeofday(&td, 0); } while(t != time(0)); - return naNum(t + 1e-6 * td.tv_usec); + gettimeofday(&td, 0); + return naNum(td.tv_sec + 1e-6 * td.tv_usec); #endif } From b0985c6b022e67b5875b33cbbf809392b8c21745 Mon Sep 17 00:00:00 2001 From: James Turner Date: Thu, 2 Jun 2011 23:01:17 +0100 Subject: [PATCH 4/5] Fix for bug 331, cmake was missing mkfifo() check. Thanks to Olaf Flebbe for the catch! --- CMakeLists.txt | 2 ++ src/Include/config_cmake.h.in | 1 + 2 files changed, 3 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1ec1f627e..06f3517b3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -224,6 +224,8 @@ include_directories(${PROJECT_BINARY_DIR}/src/Include) add_definitions(-DHAVE_CONFIG_H) +check_function_exists(mkfifo HAVE_MKFIFO) + # configure a header file to pass some of the CMake settings # to the source code configure_file ( diff --git a/src/Include/config_cmake.h.in b/src/Include/config_cmake.h.in index 047717038..721253db8 100644 --- a/src/Include/config_cmake.h.in +++ b/src/Include/config_cmake.h.in @@ -19,6 +19,7 @@ #cmakedefine HAVE_SYS_TIME_H #cmakedefine HAVE_WINDOWS_H #cmakedefine HAVE_CULLSETTINGS_CLEAR_MASK +#cmakedefine HAVE_MKFIFO #define VERSION "@FLIGHTGEAR_VERSION@" From d5f81f0eacfb8ab5f7a7767716454a12e687ce6d Mon Sep 17 00:00:00 2001 From: James Turner Date: Thu, 2 Jun 2011 23:28:40 +0100 Subject: [PATCH 5/5] Push some of the ATIS logic into AirportDynamics, in preparation for ATIS being owned by the airport --- src/ATC/trafficcontrol.cxx | 2 +- src/ATCDCL/atis.cxx | 48 +++---------------------------- src/ATCDCL/atis.hxx | 4 +-- src/Airports/dynamics.cxx | 59 ++++++++++++++++++++++---------------- src/Airports/dynamics.hxx | 36 +++++++++++------------ src/Airports/simple.cxx | 22 +++++++------- 6 files changed, 66 insertions(+), 105 deletions(-) diff --git a/src/ATC/trafficcontrol.cxx b/src/ATC/trafficcontrol.cxx index 8079933b1..f2ccd33ee 100644 --- a/src/ATC/trafficcontrol.cxx +++ b/src/ATC/trafficcontrol.cxx @@ -494,7 +494,7 @@ void FGATCController::transmit(FGTrafficRecord * rec, AtcMsgId msgId, getName() + "-Ground"; atisInformation = rec->getAircraft()->getTrafficRef()->getDepartureAirport()-> - getDynamics()->getAtisInformation(); + getDynamics()->getAtisSequence(); break; case 4: receiver = diff --git a/src/ATCDCL/atis.cxx b/src/ATCDCL/atis.cxx index b2f358620..460cc31a8 100644 --- a/src/ATCDCL/atis.cxx +++ b/src/ATCDCL/atis.cxx @@ -53,6 +53,7 @@ #include
#include
#include +#include #include "ATCutils.hxx" @@ -228,47 +229,6 @@ int Apt_US_CA(const string id) { return 0; } -// Add structure and map for storing a log of atis transmissions -// made in this session of FlightGear. This allows the callsign -// to be allocated correctly wrt time. -typedef struct { - double tstamp; - int sequence; -} atis_transmission_type; - -typedef std::map < std::string, atis_transmission_type > atis_log_type; -typedef atis_log_type::iterator atis_log_iterator; -typedef atis_log_type::const_iterator atis_log_const_iterator; - -static atis_log_type atislog; - -int FGATIS::GetAtisSequence( const string& apt_id, - const double tstamp, const int interval, const int special) -{ - atis_transmission_type tran; - - if(atislog.find(apt_id) == atislog.end()) { // New station - tran.tstamp = tstamp - interval; -// Random number between 0 and 25 inclusive, i.e. 26 equiprobable outcomes: - tran.sequence = int(sg_random() * LTRS); - atislog[apt_id] = tran; - //cout << "New ATIS station: " << apt_id << " seq-1: " - // << tran.sequence << endl; - } - -// calculate the appropriate identifier and update the log - tran = atislog[apt_id]; - - int delta = int((tstamp - tran.tstamp) / interval); - tran.tstamp += delta * interval; - if (special && !delta) delta++; // a "special" ATIS update is required - tran.sequence = (tran.sequence + delta) % LTRS; - atislog[apt_id] = tran; - //if (delta) cout << "New ATIS sequence: " << tran.sequence - // << " Delta: " << delta << endl; - return(tran.sequence + (delta ? 0 : LTRS*1000)); -} - // Generate the actual broadcast ATIS transmission. // Regen means regenerate the /current/ transmission. // Special means generate a new transmission, with a new sequence. @@ -280,12 +240,12 @@ int FGATIS::GenTransmission(const int regen, const int special) { string BRK = ".\n"; string PAUSE = " / "; - double tstamp = atof(fgGetString("sim/time/elapsed-sec")); int interval = _type == ATIS ? ATIS_interval // ATIS updated hourly : 2*minute; // AWOS updated more frequently - - int sequence = GetAtisSequence(ident, tstamp, interval, special); + + FGAirport* apt = FGAirport::findByIdent(ident); + int sequence = apt->getDynamics()->updateAtisSequence(interval, special); if (!regen && sequence > LTRS) { //xx if (msg_OK) cout << "ATIS: no change: " << sequence << endl; //xx msg_time = cur_time; diff --git a/src/ATCDCL/atis.hxx b/src/ATCDCL/atis.hxx index 189b11106..0c6124b8d 100644 --- a/src/ATCDCL/atis.hxx +++ b/src/ATCDCL/atis.hxx @@ -95,9 +95,7 @@ class FGATIS : public FGATC { void TreeOut(int msgOK); friend std::istream& operator>> ( std::istream&, FGATIS& ); - - int GetAtisSequence( const std::string& apt_id, - const double tstamp, const int interval, const int special); + }; typedef int (FGATIS::*int_getter)() const; diff --git a/src/Airports/dynamics.cxx b/src/Airports/dynamics.cxx index 11cb454b9..69f8c051d 100644 --- a/src/Airports/dynamics.cxx +++ b/src/Airports/dynamics.cxx @@ -36,6 +36,7 @@ #include
#include
#include +#include #include #include @@ -49,33 +50,11 @@ using std::random_shuffle; #include "dynamics.hxx" FGAirportDynamics::FGAirportDynamics(FGAirport * ap): -_ap(ap), rwyPrefs(ap), SIDs(ap) +_ap(ap), rwyPrefs(ap), SIDs(ap), + atisSequenceIndex(-1), + atisSequenceTimeStamp(0.0) { lastUpdate = 0; - - // For testing only. This needs to be refined when we move ATIS functionality over. - atisInformation = "Sierra"; -} - -// Note that the ground network should also be copied -FGAirportDynamics:: -FGAirportDynamics(const FGAirportDynamics & other):rwyPrefs(other. - rwyPrefs), -SIDs(other.SIDs) -{ - for (FGParkingVecConstIterator ip = other.parkings.begin(); - ip != other.parkings.end(); ip++) - parkings.push_back(*(ip)); - // rwyPrefs = other.rwyPrefs; - lastUpdate = other.lastUpdate; - - stringVecConstIterator il; - for (il = other.landing.begin(); il != other.landing.end(); il++) - landing.push_back(*il); - for (il = other.takeoff.begin(); il != other.takeoff.end(); il++) - takeoff.push_back(*il); - lastUpdate = other.lastUpdate; - atisInformation = other.atisInformation; } // Destructor @@ -540,3 +519,33 @@ FGAIFlightPlan *FGAirportDynamics::getSID(string activeRunway, { return SIDs.getBest(activeRunway, heading); } + +const std::string FGAirportDynamics::getAtisSequence() +{ + if (atisSequenceIndex == -1) { + updateAtisSequence(1, false); + } + + return GetPhoneticLetter(atisSequenceIndex); +} + +int FGAirportDynamics::updateAtisSequence(int interval, bool forceUpdate) +{ + double now = globals->get_sim_time_sec(); + if (atisSequenceIndex == -1) { + // first computation + atisSequenceTimeStamp = now; + atisSequenceIndex = rand() % LTRS; // random initial sequence letters + return atisSequenceIndex; + } + + int steps = static_cast((now - atisSequenceTimeStamp) / interval); + atisSequenceTimeStamp += (interval * steps); + if (forceUpdate && (steps == 0)) { + ++steps; // a "special" ATIS update is required + } + + atisSequenceIndex = (atisSequenceIndex + steps) % LTRS; + // return a huge value if no update occurred + return (atisSequenceIndex + (steps ? 0 : LTRS*1000)); +} diff --git a/src/Airports/dynamics.hxx b/src/Airports/dynamics.hxx index 609218218..cf862054e 100644 --- a/src/Airports/dynamics.hxx +++ b/src/Airports/dynamics.hxx @@ -22,24 +22,15 @@ #ifndef _AIRPORT_DYNAMICS_HXX_ #define _AIRPORT_DYNAMICS_HXX_ - -#ifndef __cplusplus -# error This library requires C++ -#endif - -#include - #include #include "parking.hxx" #include "groundnetwork.hxx" #include "runwayprefs.hxx" #include "sidstar.hxx" -//typedef vector DoubleVec; -//typedef vector::iterator DoubleVecIterator; - +// forward decls class FGAirport; - +class FGEnvironment; class FGAirportDynamics { @@ -55,7 +46,7 @@ private: FGApproachController approachController; time_t lastUpdate; - string prevTrafficType; + std::string prevTrafficType; stringVec landing; stringVec takeoff; stringVec milActive, comActive, genActive, ulActive; @@ -67,14 +58,14 @@ private: intVec freqTower; // intVec freqApproach; // - string atisInformation; - - string chooseRunwayFallback(); - bool innerGetActiveRunway(const string &trafficType, int action, string &runway, double heading); - string chooseRwyByHeading(stringVec rwys, double heading); + 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); public: FGAirportDynamics(FGAirport* ap); - FGAirportDynamics(const FGAirportDynamics &other); ~FGAirportDynamics(); void addAwosFreq (int val) { freqAwos.push_back(val); }; @@ -118,8 +109,13 @@ public: FGTowerController *getTowerController() { return &towerController; }; FGApproachController *getApproachController() { return &approachController; }; - const string& getAtisInformation() { return atisInformation; }; - int getGroundFrequency(unsigned leg); //{ return freqGround.size() ? freqGround[0] : 0; }; + int getGroundFrequency(unsigned leg); + + /// 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); }; diff --git a/src/Airports/simple.cxx b/src/Airports/simple.cxx index f4f3d1adb..9df1cb254 100644 --- a/src/Airports/simple.cxx +++ b/src/Airports/simple.cxx @@ -96,20 +96,18 @@ bool FGAirport::isHeliport() const FGAirportDynamics * FGAirport::getDynamics() { - if (_dynamics != 0) { + if (_dynamics) { return _dynamics; - } else { - //cerr << "Trying to load dynamics for " << _id << endl; - _dynamics = new FGAirportDynamics(this); - XMLLoader::load(_dynamics); + } + + _dynamics = new FGAirportDynamics(this); + XMLLoader::load(_dynamics); - FGRunwayPreference rwyPrefs(this); - XMLLoader::load(&rwyPrefs); - _dynamics->setRwyUse(rwyPrefs); - - //FGSidStar SIDs(this); - XMLLoader::load(_dynamics->getSIDs()); - } + FGRunwayPreference rwyPrefs(this); + XMLLoader::load(&rwyPrefs); + _dynamics->setRwyUse(rwyPrefs); + XMLLoader::load(_dynamics->getSIDs()); + return _dynamics; }