]> git.mxchange.org Git - flightgear.git/blob - src/ATC/AIMgr.cxx
Fix a nasty problem in the FGAIMgr search code that could cause a stackdump with...
[flightgear.git] / src / ATC / AIMgr.cxx
1 // AIMgr.cxx - implementation of FGAIMgr 
2 // - a global management class for FlightGear generated AI traffic
3 //
4 // Written by David Luff, started March 2002.
5 //
6 // Copyright (C) 2002  David C Luff - david.luff@nottingham.ac.uk
7 //
8 // This program is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU General Public License as
10 // published by the Free Software Foundation; either version 2 of the
11 // License, or (at your option) any later version.
12 //
13 // This program is distributed in the hope that it will be useful, but
14 // WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 // General Public License for more details.
17 //
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the Free Software
20 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21
22 #include <Airports/simple.hxx>
23 #include <Main/fgfs.hxx>
24 #include <Main/fg_props.hxx>
25 #include <Main/globals.hxx>
26 #include <simgear/misc/sg_path.hxx>
27 #include <simgear/bucket/newbucket.hxx>
28
29 #include <list>
30
31 #ifdef _MSC_VER
32 #  include <io.h>
33 #else
34 #  include <sys/types.h>        // for directory reading
35 #  include <dirent.h>           // for directory reading
36 #endif
37
38 #include "AIMgr.hxx"
39 #include "AILocalTraffic.hxx"
40 #include "ATCutils.hxx"
41
42 SG_USING_STD(list);
43 SG_USING_STD(cout);
44
45 FGAIMgr::FGAIMgr() {
46         ATC = globals->get_ATC_mgr();
47 }
48
49 FGAIMgr::~FGAIMgr() {
50 }
51
52 void FGAIMgr::init() {
53         // Pointers to user's position
54         lon_node = fgGetNode("/position/longitude-deg", true);
55         lat_node = fgGetNode("/position/latitude-deg", true);
56         elev_node = fgGetNode("/position/altitude-ft", true);
57         
58         // go through the $FG_ROOT/ATC directory and find all *.taxi files
59         SGPath path(globals->get_fg_root());
60         path.append("ATC/");
61         string dir = path.dir();
62     string ext;
63     string file, f_ident;
64         int pos;
65         
66         // WARNING - I (DCL) haven't tested this on MSVC - this is simply cribbed from TerraGear
67 #ifdef _MSC_VER 
68         long hfile;
69         struct _finddata_t de;
70         string path_str;
71         
72         path_str = dir + "\\*.*";
73         
74         if ( ( hfile = _findfirst( path.c_str(), &de ) ) == -1 ) {
75                 cout << "cannot open directory " << dir << "\n";
76         } else {                
77                 // load all .taxi files
78                 do {
79                         file = de.name;
80                         pos = file.find(".");
81                         ext = file.substr(pos + 1);
82                         if(ext == "taxi") {
83                                 cout << "TAXI FILE FOUND!!!\n";
84                                 f_ident = file.substr(0, pos);
85                                 FGAirport a;
86                                 if(dclFindAirportID(f_ident, &a)) {
87                                         SGBucket sgb(a.longitude, a.latitude);
88                                         int idx = sgb.gen_index();
89                                         if(airports.find(idx) != airports.end()) {
90                                                 airports[idx]->push_back(f_ident);
91                                         } else {
92                                                 aptID_list_type* apts = new aptID_list_type;
93                                                 apts->push_back(f_ident);
94                                                 airports[idx] = apts;
95                                         }
96                                         cout << "Mapping " << f_ident << " to bucket " << idx << '\n'; 
97                                 }
98                         }
99                 } while ( _findnext( hfile, &de ) == 0 );
100         }
101 #else
102
103     DIR *d;
104     struct dirent *de;
105
106     if ( (d = opendir( dir.c_str() )) == NULL ) {
107                 cout << "cannot open directory " << dir << "\n";
108         } else {
109                 cout << "Opened directory " << dir << " OK :-)\n";
110                 cout << "Contents are:\n";
111                 // load all .taxi files
112                 while ( (de = readdir(d)) != NULL ) {
113                         file = de->d_name;
114                         pos = file.find(".");
115                         cout << file << '\n';
116
117                         ext = file.substr(pos + 1);
118                         if(ext == "taxi") {
119                                 cout << "TAXI FILE FOUND!!!\n";
120                                 f_ident = file.substr(0, pos);
121                                 FGAirport a;
122                                 if(dclFindAirportID(f_ident, &a)) {
123                                         SGBucket sgb(a.longitude, a.latitude);
124                                         int idx = sgb.gen_index();
125                                         if(airports.find(idx) != airports.end()) {
126                                                 airports[idx]->push_back(f_ident);
127                                         } else {
128                                                 aptID_list_type* apts = new aptID_list_type;
129                                                 apts->push_back(f_ident);
130                                                 airports[idx] = apts;
131                                         }
132                                         cout << "Mapping " << f_ident << " to bucket " << idx << '\n'; 
133                                 }
134                         }
135                 }               
136                 closedir(d);
137         }
138 #endif
139         
140         // See if are in range at startup and activate if necessary
141         SearchByPos(10.0);
142 }
143
144 void FGAIMgr::bind() {
145 }
146
147 void FGAIMgr::unbind() {
148 }
149
150 void FGAIMgr::update(double dt) {
151         static int i = 0;
152         static int j = 0;
153
154         // Don't update any planes for first 50 runs through - this avoids some possible initialisation anomalies
155         // Might not need it now we have fade-in though?
156         if(i < 50) {
157                 ++i;
158                 return;
159         }
160         
161         if(j == 215) {
162                 SearchByPos(15.0);
163                 j = 0;
164         }
165         
166         ++j;
167         
168         // TODO - need to add a check of if any activated airports have gone out of range
169         
170         // Traverse the list of active planes and run all their update methods
171         // TODO - spread the load - not all planes should need updating every frame.
172         // Note that this will require dt to be calculated for each plane though
173         // since they rely on it to calculate distance travelled.
174         ai_list_itr = ai_list.begin();
175         while(ai_list_itr != ai_list.end()) {
176                 (*ai_list_itr)->Update(dt);
177                 ++ai_list_itr;
178         }
179 }
180
181
182 // Activate AI traffic at an airport
183 void FGAIMgr::ActivateAirport(string ident) {
184         ATC->AIRegisterAirport(ident);
185         // TODO - need to start the traffic more randomly
186         FGAILocalTraffic* local_traffic = new FGAILocalTraffic;
187         //local_traffic->Init(ident, IN_PATTERN, TAKEOFF_ROLL);
188         local_traffic->Init(ident);
189         local_traffic->FlyCircuits(1, true);    // Fly 2 circuits with touch & go in between
190         ai_list.push_back(local_traffic);
191         activated[ident] = 1;
192 }       
193
194
195 // Search for valid airports in the vicinity of the user and activate them if necessary
196 void FGAIMgr::SearchByPos(double range)
197 {
198         //cout << "In SearchByPos(...)" << endl;
199         
200         // get bucket number for plane position
201         lon = lon_node->getDoubleValue();
202         lat = lat_node->getDoubleValue();
203         SGBucket buck(lon, lat);
204
205         // get neigboring buckets
206         int bx = (int)( range*SG_NM_TO_METER / buck.get_width_m() / 2);
207         //cout << "bx = " << bx << endl;
208         int by = (int)( range*SG_NM_TO_METER / buck.get_height_m() / 2 );
209         //cout << "by = " << by << endl;
210         
211         // loop over bucket range 
212         for ( int i=-bx; i<=bx; i++) {
213                 //cout << "i loop\n";
214                 for ( int j=-by; j<=by; j++) {
215                         //cout << "j loop\n";
216                         buck = sgBucketOffset(lon, lat, i, j);
217                         long int bucket = buck.gen_index();
218                         //cout << "bucket is " << bucket << endl;
219                         if(airports.find(bucket) != airports.end()) {
220                                 aptID_list_type* apts = airports[bucket];
221                                 aptID_list_iterator current = apts->begin();
222                                 aptID_list_iterator last = apts->end();
223                                 
224                                 //cout << "Size of apts is " << apts->size() << endl;
225                                 
226                                 //double rlon = lon * SGD_DEGREES_TO_RADIANS;
227                                 //double rlat = lat * SGD_DEGREES_TO_RADIANS;
228                                 //Point3D aircraft = sgGeodToCart( Point3D(rlon, rlat, elev) );
229                                 //Point3D airport;
230                                 for(; current != last; ++current) {
231                                         //cout << "Found " << *current << endl;;
232                                         if(activated.find(*current) == activated.end()) {
233                                                 //cout << "Activating " << *current << endl;
234                                                 //FGAirport a;
235                                                 //if(dclFindAirportID(*current, &a)) {
236                                                         //      // We can do something here based on distance from the user if we wish.
237                                                 //}
238                                                 ActivateAirport(*current);
239                                                 //cout << "Activation done" << endl;
240                                         } else {
241                                                 //cout << *current << " already activated" << endl;
242                                         }
243                                 }
244                         }
245                 }
246         }
247 }