]> git.mxchange.org Git - flightgear.git/commitdiff
More stuff to make the AI/ATC system less hardwired and more generic. Most of the...
authordaveluff <daveluff>
Fri, 7 Mar 2003 13:58:33 +0000 (13:58 +0000)
committerdaveluff <daveluff>
Fri, 7 Mar 2003 13:58:33 +0000 (13:58 +0000)
src/ATC/AILocalTraffic.cxx
src/ATC/AILocalTraffic.hxx
src/ATC/AIMgr.cxx
src/ATC/AIMgr.hxx
src/ATC/ATCmgr.cxx
src/ATC/ATCmgr.hxx
src/ATC/commlist.cxx
src/ATC/ground.cxx
src/ATC/ground.hxx

index f4dc8dbeae79d01d0be2073b1bf5b7683f1dc8bf..8404f32373f529c11553e539fd7e1fda334f3956 100644 (file)
@@ -41,6 +41,8 @@ SG_USING_STD(string);
 #include "ATCutils.hxx"
 
 FGAILocalTraffic::FGAILocalTraffic() {
+       ATC = globals->get_ATC_mgr();
+       
        roll = 0.0;
        pitch = 0.0;
        hdg = 270.0;
@@ -159,24 +161,38 @@ bool FGAILocalTraffic::Init(string ICAO, OperatingState initialState, PatternLeg
        // Find the tower frequency - this is dependent on the ATC system being initialised before the AI system
        airportID = ICAO;
        AirportATC a;
-       if(globals->get_ATC_mgr()->GetAirportATCDetails(airportID, &a)) {
+       if(ATC->GetAirportATCDetails(airportID, &a)) {
                if(a.tower_freq) {      // Has a tower
-                       tower = (FGTower*)globals->get_ATC_mgr()->GetATCPointer((string)airportID, TOWER);      // Maybe need some error checking here
+                       tower = (FGTower*)ATC->GetATCPointer((string)airportID, TOWER); // Maybe need some error checking here
+                       if(tower == NULL) {
+                               // Something has gone wrong - abort or carry on with un-towered operation?
+                               return(false);
+                       }
                        freq = (double)tower->get_freq() / 100.0;
-                       //cout << "***********************************AILocalTraffic freq = " << freq << '\n';
                } else {
                        // Check CTAF, unicom etc
                }
+               if(a.ground_freq) {             // Ground control
+                       ground = (FGGround*)ATC->GetATCPointer((string)airportID, GROUND);      // Maybe need some error checking here
+                       if(ground == NULL) {
+                               // Something has gone wrong :-(
+                               cout << "ERROR - ground has frequency but can't get ground pointer :-(\n";
+                               return(false);
+                       }
+                       freq = (double)tower->get_freq() / 100.0;
+               } else {
+                       // Initialise ground anyway to do the shortest path stuff!
+                       // This is a bit of a hack - might need to be altered sometime, but
+                       // in theory AILocalTraffic doesn't get called unless we have a logical
+                       // network for ground to use so it should work for now!
+                       ground = new FGGround(airportID);       // TODO - ought to set a flag saying that we're responsible
+                                                                                       // for deleting ground in this instance, since normally we're not.
+                       ground->Init();
+               }
        } else {
                //cout << "Unable to find airport details in FGAILocalTraffic::Init()\n";
        }
 
-       // Initialise the relevant FGGround
-       // This needs a complete overhaul soon - what happens if we have 2 AI planes at same airport - they don't both need a structure
-       // This needs to be handled by the ATC manager or similar so only one set of physical data per airport is instantiated
-       // ie. TODO TODO FIXME FIXME
-       airport.Init();
-       
        // Get the airport elevation
        aptElev = dclGetAirportElev(airportID.c_str()) * SG_FEET_TO_METER;
        //cout << "Airport elev in AILocalTraffic = " << aptElev << '\n';
@@ -187,7 +203,7 @@ bool FGAILocalTraffic::Init(string ICAO, OperatingState initialState, PatternLeg
        operatingState = initialState;
        switch(operatingState) {
        case PARKED:
-               ourGate = airport.GetGateNode();
+               ourGate = ground->GetGateNode();
                if(ourGate == NULL) {
                        // Implies no available gates - what shall we do?
                        // For now just vanish the plane - possibly we can make this more elegant in the future
@@ -282,7 +298,7 @@ void FGAILocalTraffic::FlyCircuits(int numCircuits, bool tag) {
                GetRwyDetails();
                
                // Get the takeoff node for the active runway, get a path to it and start taxiing
-               path = airport.GetPath(ourGate, rwy.rwyID);
+               path = ground->GetPath(ourGate, rwy.rwyID);
                if(path.size() < 2) {
                        // something has gone wrong
                        SG_LOG(SG_GENERAL, SG_ALERT, "Invalid path from gate to theshold in FGAILocalTraffic::FlyCircuits\n");
@@ -694,7 +710,7 @@ void FGAILocalTraffic::TransmitPatternPositionReport(void) {
 void FGAILocalTraffic::ExitRunway(Point3D orthopos) {
        //cout << "In ExitRunway" << endl;
        //cout << "Runway ID is " << rwy.ID << endl;
-       node_array_type exitNodes = airport.GetExits(rwy.ID);   //I suppose we ought to have some fallback for rwy with no defined exits?
+       node_array_type exitNodes = ground->GetExits(rwy.ID);   //I suppose we ought to have some fallback for rwy with no defined exits?
        /*
        cout << "Node ID's of exits are ";
        for(unsigned int i=0; i<exitNodes.size(); ++i) {
@@ -725,7 +741,7 @@ void FGAILocalTraffic::ExitRunway(Point3D orthopos) {
                        }
                        ++nItr;
                }
-               ourGate = airport.GetGateNode();
+               ourGate = ground->GetGateNode();
                if(ourGate == NULL) {
                        // Implies no available gates - what shall we do?
                        // For now just vanish the plane - possibly we can make this more elegant in the future
@@ -734,7 +750,7 @@ void FGAILocalTraffic::ExitRunway(Point3D orthopos) {
                        operatingState = PARKED;
                        return;
                }
-               path = airport.GetPath(rwyExit, ourGate);
+               path = ground->GetPath(rwyExit, ourGate);
                /*
                cout << "path returned was:" << endl;
                for(unsigned int i=0; i<path.size(); ++i) {
index e7b00d2694494ac9ed368ec00525255845a5c037..0d97a2e677db69e2f229e9dc6d225f7170855023 100644 (file)
@@ -105,6 +105,9 @@ protected:
        void ReturnToBase(double dt);
        
 private:
+       FGATCMgr* ATC;  
+       // This is purely for synactic convienience to avoid writing globals->get_ATC_mgr()-> all through the code!
+
        // High-level stuff
        OperatingState operatingState;
        int circuitsToFly;      //Number of circuits still to do in this session NOT INCLUDING THE CURRENT ONE
@@ -117,7 +120,7 @@ private:
        // Airport/runway/pattern details
        string airportID;       // The ICAO code of the airport that we're operating around
        double aptElev;         // Airport elevation
-       FGGround airport;       // FIXME FIXME FIXME This is a complete hardwired cop-out at the moment - we need to connect to the correct ground in the same way we do to the tower.
+       FGGround* ground;       // A pointer to the ground control.
        FGTower* tower; // A pointer to the tower control.
        RunwayDetails rwy;
        double patternDirection;        // 1 for right, -1 for left (This is double because we multiply/divide turn rates
index 85ec947839a5a1289b6ef6caeee6b1a94d0f3ffa..d2cff20f0ccf0069e5bdd8e5b9d022b86e3584c2 100644 (file)
 // along with this program; if not, write to the Free Software
 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
+#include <Airports/simple.hxx>
 #include <Main/fgfs.hxx>
 #include <Main/fg_props.hxx>
+#include <Main/globals.hxx>
+#include <Simgear/misc/sg_path.hxx>
+#include <Simgear/bucket/newbucket.hxx>
 
 #include <list>
 
+#ifdef _MSC_VER
+#  include <io.h>
+#else
+#  include <sys/types.h>       // for directory reading
+#  include <dirent.h>          // for directory reading
+#endif
+
 #include "AIMgr.hxx"
 #include "AILocalTraffic.hxx"
+#include "ATCutils.hxx"
 
 SG_USING_STD(list);
 
 
 FGAIMgr::FGAIMgr() {
+       ATC = globals->get_ATC_mgr();
 }
 
 FGAIMgr::~FGAIMgr() {
 }
 
 void FGAIMgr::init() {
+       // go through the $FG_ROOT/ATC directory and find all *.taxi files
+       SGPath path(globals->get_fg_root());
+       path.append("ATC/");
+       string dir = path.dir();
+    string ext;
+    string file, f_ident;
+       int pos;
+       
+       // WARNING - I (DCL) haven't tested this on MSVC - this is simply cribbed from TerraGear
+#ifdef _MSC_VER        
+       long hfile;
+       struct _finddata_t de;
+       string path_str;
+       
+       path_str = dir + "\\*.*";
+       
+       if ( ( hfile = _findfirst( path.c_str(), &de ) ) == -1 ) {
+               cout << "cannot open directory " << dir << "\n";
+       } else {                
+               // load all .taxi files
+               do {
+                       file = de.name;
+                       pos = file.find(".");
+                       ext = file.substr(pos + 1);
+                       if(ext == "taxi") {
+                               cout << "TAXI FILE FOUND!!!\n";
+                               f_ident = file.substr(0, pos);
+                               FGAirport a;
+                               if(dclFindAirportID(f_ident, &a)) {
+                                       SGBucket sgb(a.longitude, a.latitude);
+                                       int idx = sgb.gen_index();
+                                       airports[idx] = f_ident;
+                                       cout << "Mapping " << f_ident << " to bucket " << idx << '\n'; 
+                               }
+                       }
+               } while ( _findnext( hfile, &de ) == 0 );
+       }
+#else
+
+    DIR *d;
+    struct dirent *de;
+
+    if ( (d = opendir( dir.c_str() )) == NULL ) {
+               cout << "cannot open directory " << dir << "\n";
+       } else {
+               cout << "Opened directory " << dir << " OK :-)\n";
+               cout << "Contents are:\n";
+               // load all .taxi files
+               while ( (de = readdir(d)) != NULL ) {
+                       file = de->d_name;
+                       pos = file.find(".");
+                       cout << file << '\n';
+
+                       ext = file.substr(pos + 1);
+                       if(ext == "taxi") {
+                               cout << "TAXI FILE FOUND!!!\n";
+                               f_ident = file.substr(0, pos);
+                               FGAirport a;
+                               if(dclFindAirportID(f_ident, &a)) {
+                                       SGBucket sgb(a.longitude, a.latitude);
+                                       int idx = sgb.gen_index();
+                                       airports[idx] = f_ident;
+                                       cout << "Mapping " << f_ident << " to bucket " << idx << '\n'; 
+                               }
+                       }
+               }               
+               closedir(d);
+       }
+#endif
+       
        // Hard wire some local traffic for now.
        // This is regardless of location and hence *very* ugly but it is a start.
+       ATC->AIRegisterAirport("KEMT");
        FGAILocalTraffic* local_traffic = new FGAILocalTraffic;
        //local_traffic->Init("KEMT", IN_PATTERN, TAKEOFF_ROLL);
        local_traffic->Init("KEMT");
index ec4c4e40ca06fee2a9fdaf0458ffc2ff5bd04e53..8b002744fc4c023318a6b399b907d60ad77669cb 100644 (file)
 
 #include <list>
 
+#include "ATCMgr.hxx"
 #include "AIEntity.hxx"
 
 SG_USING_STD(list);
 
+
 class FGAIMgr : public FGSubsystem
 {
 
 private:
+       FGATCMgr* ATC;  
+       // This is purely for synactic convienience to avoid writing globals->get_ATC_mgr()-> all through the code!
 
     // A list of pointers to all currently active AI stuff
     typedef list <FGAIEntity*> ai_list_type;
@@ -48,6 +52,11 @@ private:
     // Any member function of FGATCMgr is permitted to leave this iterator pointing
     // at any point in or at the end of the list.
     // Hence any new access must explicitly first check for atc_list.end() before dereferencing.
+       
+       // A map of airport-IDs that have taxiway network files against bucket number
+       typedef map < int, string > ai_apt_map_type;
+       typedef ai_apt_map_type::iterator ai_apt_map_iterator;
+       ai_apt_map_type airports;
 
     // Position of the Users Aircraft
     // (This may be needed to calculate the distance from the user when deciding which 3D model to render)
index f2de05d2343024ee049c1ab5026a9b4ae147f738..b2532db33a3d1cc0f7ab9ef1ad9a5530e7539696 100644 (file)
@@ -22,6 +22,7 @@
 
 #include <simgear/misc/sg_path.hxx>
 #include <simgear/debug/logstream.hxx>
+#include <Airports/simple.hxx>
 
 #include "ATCmgr.hxx"
 #include "commlist.hxx"
@@ -31,6 +32,7 @@
 //#include "approachlist.hxx"
 #include "ATCdisplay.hxx"
 #include "ATCDialog.hxx"
+#include "ATCutils.hxx"
 
 /*
 // periodic radio station search wrapper
@@ -50,6 +52,7 @@ AirportATC::AirportATC() :
     ground_freq(0.0),
     ground_active(false),
     set_by_AI(false),
+       numAI(0),
     set_by_comm_search(false) {
 }
 
@@ -83,6 +86,7 @@ void FGATCMgr::init() {
        lat_node = fgGetNode("/position/latitude-deg", true);
        elev_node = fgGetNode("/position/altitude-ft", true);
        atc_list_itr = atc_list.begin();
+       
        // Search for connected ATC stations once per 0.8 seconds or so
        // global_events.Register( "fgATCSearch()", fgATCSearch,
        //                  fgEVENT::FG_EVENT_READY, 800);
@@ -92,23 +96,6 @@ void FGATCMgr::init() {
     current_commlist = new FGCommList;
     SGPath p_comm( globals->get_fg_root() );
     current_commlist->init( p_comm );
-       
-       // Initialise the airport_atc_map - we'll cheat for now and just hardcode KEMT and any others that may be needed for development
-       AirportATC *a = new AirportATC;
-       a->lon = -118.034719;
-       a->lat = 34.086114;
-       a->elev = 296.0;
-       a->atis_freq = 118.75;
-       a->atis_active = false;
-       a->tower_freq = 121.2;
-       a->tower_active = false;
-       a->ground_freq = 125.9;
-       a->ground_active = false;
-       
-       //a->set_by_AI = true;
-       //a->set_by_comm_search = false;
-       
-       airport_atc_map[(string)"KEMT"] = a;
 
 #ifdef ENABLE_AUDIO_SUPPORT    
        // Load all available voices.
@@ -191,6 +178,53 @@ void FGATCMgr::update(double dt) {
        //cout << "comm1 type = " << comm_type[0] << '\n';
 }
 
+
+// Returns frequency in KHz - should I alter this to return in MHz?
+unsigned short int FGATCMgr::GetFrequency(string ident, atc_type tp) {
+       ATCData test;
+       bool ok = current_commlist->FindByCode(ident, test, tp);
+       return(ok ? test.freq : 0);
+}      
+
+
+// Register the fact that the AI system wants to activate an airport
+// Might need more sophistication in this in the future - eg registration by aircraft call-sign.
+bool FGATCMgr::AIRegisterAirport(string ident) {
+       if(airport_atc_map.find(ident) != airport_atc_map.end()) {
+               airport_atc_map[ident]->set_by_AI = true;
+               return(true);
+       } else {
+               FGAirport ap;
+               if(dclFindAirportID(ident, &ap)) {
+                       AirportATC *a = new AirportATC;
+                       // I'm not entirely sure that this AirportATC structure business is actually needed - it just duplicates what we can find out anyway!
+                       a->lon = ap.longitude;
+                       a->lat = ap.latitude;
+                       a->elev = ap.elevation;
+                       a->atis_freq = GetFrequency(ident, ATIS);
+                       a->atis_active = false;
+                       a->tower_freq = GetFrequency(ident, TOWER);
+                       a->tower_active = false;
+                       a->ground_freq = GetFrequency(ident, GROUND);
+                       a->ground_active = false;
+                       // TODO - some airports will have a tower/ground frequency but be inactive overnight.
+                       a->set_by_AI = true;
+                       a->numAI++;
+                       airport_atc_map[ident] = a;
+                       return(true);
+               }
+       }
+       return(false);
+}
+
+
+// Register the fact that the comm radio is tuned to an airport
+bool FGATCMgr::CommRegisterAirport(string ident) {     // Later we'll differentiate between comm 1 and comm2
+       // TODO - implement me!
+       return(false);
+}
+
+
 // Remove from list only if not needed by the AI system or the other comm channel
 // TODO - implement me!!
 void FGATCMgr::CommRemoveFromList(const char* id, atc_type tp, int chan) {
@@ -263,10 +297,11 @@ bool FGATCMgr::GetAirportATCDetails(string icao, AirportATC* a) {
 
 
 // Return a pointer to a given sort of ATC at a given airport and activate if necessary
-// ONLY CALL THIS FUNCTION AFTER FIRST CHECKING THE SERVICE EXISTS BY CALLING GetAirportATCDetails
-// FIXME - we really ought to take out the necessity for two function calls by simply returning
-// a NULL pointer if the service doesn't exist and requiring the caller to check for it (NULL).
+// Returns NULL if service doesn't exist - calling function should check for this.
 FGATC* FGATCMgr::GetATCPointer(string icao, atc_type type) {
+       if(airport_atc_map.find(icao) == airport_atc_map.end()) {
+               return NULL;
+       }
        AirportATC *a = airport_atc_map[icao];
        //cout << "a->lon = " << a->lon << '\n';
        //cout << "a->elev = " << a->elev << '\n';
@@ -275,28 +310,45 @@ FGATC* FGATCMgr::GetATCPointer(string icao, atc_type type) {
                case TOWER:
                if(a->tower_active) {
                        // Get the pointer from the list
-                       return(FindInList(icao.c_str(), type)); // DCL - this untested so far.
+                       return(FindInList(icao.c_str(), type));
                } else {
-                       FGTower* t = new FGTower;
                        ATCData data;
                        if(current_commlist->FindByFreq(a->lon, a->lat, a->elev, a->tower_freq, &data, TOWER)) {
+                               FGTower* t = new FGTower;
                                t->SetData(&data);
                                atc_list.push_back(t);
                                a->tower_active = true;
                                airport_atc_map[icao] = a;
+                               t->Init();
                                return(t);
                        } else {
                                cout << "ERROR - tower that should exist in FGATCMgr::GetATCPointer for airport " << icao << " not found\n";
                        }
                }
                break;
-               // Lets add the rest to get rid of the compiler warnings even though we don't need them yet.
                case APPROACH:
                break;
                case ATIS:
                SG_LOG(SG_GENERAL, SG_ALERT, "ERROR - ATIS station should not be requested from FGATCMgr::GetATCPointer");
                break;
                case GROUND:
+               if(a->ground_active) {
+                       // Get the pointer from the list
+                       return(FindInList(icao.c_str(), type));
+               } else {
+                       ATCData data;
+                       if(current_commlist->FindByFreq(a->lon, a->lat, a->elev, a->ground_freq, &data, GROUND)) {
+                               FGGround* g = new FGGround;
+                               g->SetData(&data);
+                               atc_list.push_back(g);
+                               a->ground_active = true;
+                               airport_atc_map[icao] = a;
+                               g->Init();
+                               return(g);
+                       } else {
+                               cout << "ERROR - ground control that should exist in FGATCMgr::GetATCPointer for airport " << icao << " not found\n";
+                       }
+               }
                break;
                case INVALID:
                break;
index 483568f3a814b8f267118c2d90f0f93e54e70529..be9032128daa1271c6e766357ad0c10cef499857 100644 (file)
@@ -62,10 +62,13 @@ struct AirportATC {
     //bool approach_active;
     //float departure_freq;
     //bool departure_active;
+       
+       // NOTE - the *_active flags determine whether the service is active in atc_list,
+       // *NOT* whether the tower etc is closed or not!!!!
 
     // Flags to ensure the stations don't get wrongly deactivated
     bool set_by_AI;    // true when the AI manager has activated this station
-       // Do we need to ref-count the number of AI planes setting this?
+       unsigned int numAI;     // Ref count of the number of AI planes registered
     bool set_by_comm_search;   // true when the comm_search has activated this station
        // Do we need to distingiush comm1 and comm2?
 };
@@ -159,6 +162,7 @@ public:
     bool GetAirportATCDetails(string icao, AirportATC* a);
 
     // Return a pointer to a given sort of ATC at a given airport and activate if necessary
+       // Returns NULL if service doesn't exist - calling function should check for this.
     FGATC* GetATCPointer(string icao, atc_type type);
        
        // Display a dialog box with options relevant to the currently tuned ATC service.
@@ -178,6 +182,16 @@ public:
        atc_type GetComm2ATCType() { return(comm_type[1]); }
        FGATC* GetComm2ATCPointer() { return(comm_atc_ptr[1]); }
        
+       // Get the frequency of a given service at a given airport
+       // Returns zero if not found
+       unsigned short int GetFrequency(string ident, atc_type tp);
+       
+       // Register the fact that the AI system wants to activate an airport
+       bool AIRegisterAirport(string ident);
+       
+       // Register the fact that the comm radio is tuned to an airport
+       bool CommRegisterAirport(string ident); // Later we'll differentiate between comm 1 and comm2
+       
 private:
 
     // Remove a class from the atc_list and delete it from memory
index 509b095c3771fc6da322c61c66be3c02bcb095b2..eb0201e9213a7ecade8eefc5ba6c06152931e9d6 100644 (file)
@@ -120,7 +120,14 @@ bool FGCommList::FindByFreq( double lon, double lat, double elev, double freq,
        lon *= SGD_DEGREES_TO_RADIANS;
        lat *= SGD_DEGREES_TO_RADIANS;
        
-       comm_list_type stations = commlist_freq[(int)(freq*100.0 + 0.5)];
+       // HACK - if freq > 1000 assume it's in KHz, otherwise assume MHz.
+       // A bit ugly but it works for now!!!!
+       comm_list_type stations;
+       if(freq > 1000.0) {
+               stations = commlist_freq[(int)freq];
+       } else {
+               stations = commlist_freq[(int)(freq*100.0 + 0.5)];
+       }
        comm_list_iterator current = stations.begin();
        comm_list_iterator last = stations.end();
        
index 89a9665ff21a3d76327d792cd06547befd2ee2f0..6734b8be3485a166d3ddf8d1a4af85b330014cf6 100644 (file)
@@ -53,6 +53,12 @@ FGGround::FGGround() {
        networkLoadOK = false;
 }
 
+FGGround::FGGround(string id) {
+       display = false;
+       networkLoadOK = false;
+       ident = id;
+}
+
 FGGround::~FGGround() {
 }
 
index 5770d2d7bc3fb63c9e76d9fc27bde18e2492b1fa..fdc2dd0eafab1a2385d546520e22329feb90dc49 100644 (file)
@@ -208,6 +208,7 @@ class FGGround : public FGATC {
 
 public:
        FGGround();
+       FGGround(string id);
        ~FGGround();
     void Init();