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