1 // AIMgr.cxx - implementation of FGAIMgr
2 // - a global management class for FlightGear generated AI traffic
4 // Written by David Luff, started March 2002.
6 // Copyright (C) 2002 David C Luff - david.luff@nottingham.ac.uk
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.
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.
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.
22 #include <Main/fgfs.hxx>
23 #include <Main/fg_props.hxx>
24 #include <Main/globals.hxx>
25 #include <simgear/misc/sg_path.hxx>
32 # include <sys/types.h> // for directory reading
33 # include <dirent.h> // for directory reading
37 #include "AILocalTraffic.hxx"
38 #include "ATCutils.hxx"
44 ATC = globals->get_ATC_mgr();
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);
57 lon = lon_node->getDoubleValue();
58 lat = lat_node->getDoubleValue();
59 elev = elev_node->getDoubleValue();
61 // go through the $FG_ROOT/ATC directory and find all *.taxi files
62 SGPath path(globals->get_fg_root());
64 string dir = path.dir();
69 // WARNING - I (DCL) haven't tested this on MSVC - this is simply cribbed from TerraGear
72 struct _finddata_t de;
75 path_str = dir + "\\*.*";
77 if ( ( hfile = _findfirst( path.c_str(), &de ) ) == -1 ) {
78 cout << "cannot open directory " << dir << "\n";
80 // load all .taxi files
84 ext = file.substr(pos + 1);
86 cout << "TAXI FILE FOUND!!!\n";
87 f_ident = file.substr(0, pos);
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);
95 aptID_list_type* apts = new aptID_list_type;
96 apts->push_back(f_ident);
99 cout << "Mapping " << f_ident << " to bucket " << idx << '\n';
102 } while ( _findnext( hfile, &de ) == 0 );
109 if ( (d = opendir( dir.c_str() )) == NULL ) {
110 cout << "cannot open directory " << dir << "\n";
112 cout << "Opened directory " << dir << " OK :-)\n";
113 cout << "Contents are:\n";
114 // load all .taxi files
115 while ( (de = readdir(d)) != NULL ) {
117 pos = file.find(".");
118 cout << file << '\n';
120 ext = file.substr(pos + 1);
122 cout << "TAXI FILE FOUND!!!\n";
123 f_ident = file.substr(0, pos);
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);
131 aptID_list_type* apts = new aptID_list_type;
132 apts->push_back(f_ident);
133 airports[idx] = apts;
135 cout << "Mapping " << f_ident << " to bucket " << idx << '\n';
143 // See if are in range at startup and activate if necessary
149 void FGAIMgr::bind() {
152 void FGAIMgr::unbind() {
155 void FGAIMgr::update(double dt) {
158 SG_LOG(SG_ATC, SG_WARN, "Warning - AIMgr::update(...) called before AIMgr::init()");
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?
178 // TODO - need to add a check of if any activated airports have gone out of range
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);
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;
205 // Search for valid airports in the vicinity of the user and activate them if necessary
206 void FGAIMgr::SearchByPos(double range)
208 //cout << "In SearchByPos(...)" << endl;
210 // get bucket number for plane position
211 lon = lon_node->getDoubleValue();
212 lat = lat_node->getDoubleValue();
213 SGBucket buck(lon, lat);
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;
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();
234 //cout << "Size of apts is " << apts->size() << endl;
236 //double rlon = lon * SGD_DEGREES_TO_RADIANS;
237 //double rlat = lat * SGD_DEGREES_TO_RADIANS;
238 //Point3D aircraft = sgGeodToCart( Point3D(rlon, rlat, elev) );
240 for(; current != last; ++current) {
241 //cout << "Found " << *current << endl;;
242 if(activated.find(*current) == activated.end()) {
243 //cout << "Activating " << *current << endl;
245 //if(dclFindAirportID(*current, &a)) {
246 // // We can do something here based on distance from the user if we wish.
248 ActivateAirport(*current);
249 //cout << "Activation done" << endl;
251 //cout << *current << " already activated" << endl;