X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FATC%2FAIMgr.cxx;h=629d5d97b09f1d4db7c36233c7c64d5a93d011ec;hb=68f248879cb15562c7b026445f83caf8f2842ae9;hp=c27fb5ce43417c4d5273c75c7b24adb6c9d7c283;hpb=4fb5e61162dafd93b6c5f2dcdf6b805538b21657;p=flightgear.git diff --git a/src/ATC/AIMgr.cxx b/src/ATC/AIMgr.cxx index c27fb5ce4..629d5d97b 100644 --- a/src/ATC/AIMgr.cxx +++ b/src/ATC/AIMgr.cxx @@ -34,12 +34,8 @@ # include // for directory reading #endif -#ifdef FG_WEATHERCM -# include -#else -# include -# include -#endif +#include +#include #include "AIMgr.hxx" #include "AILocalTraffic.hxx" @@ -57,9 +53,12 @@ FGAIMgr::FGAIMgr() { // TODO - use the proper user callsign when it becomes user settable. removalList.clear(); activated.clear(); + _havePiperModel = true; } FGAIMgr::~FGAIMgr() { + _defaultModel->deRef(); + if(_havePiperModel) _piperModel->deRef(); } void FGAIMgr::init() { @@ -76,18 +75,41 @@ void FGAIMgr::init() { // Load up models at the start to avoid pausing later // Hack alert - Hardwired paths!! - string planepath = "Aircraft/c172/Models/c172-dpm.ac"; - _defaultModel = sgLoad3DModel( globals->get_fg_root(), - planepath.c_str(), - globals->get_props(), - globals->get_sim_time_sec() ); - + string planepath = "Aircraft/c172r/Models/c172-dpm.ac"; + bool _loadedDefaultOK = true; + try { + _defaultModel = sgLoad3DModel( globals->get_fg_root(), + planepath.c_str(), + globals->get_props(), + globals->get_sim_time_sec() ); + } catch(sg_exception& e) { + _loadedDefaultOK = false; + } + + if(!_loadedDefaultOK ) { + // Just load the same 3D model as the default user plane - that's *bound* to exist! + // TODO - implement robust determination of availability of GA AI aircraft models + planepath = "Aircraft/c172p/Models/c172p.ac"; + _defaultModel = sgLoad3DModel( globals->get_fg_root(), + planepath.c_str(), + globals->get_props(), + globals->get_sim_time_sec() ); + } + planepath = "Aircraft/pa28-161/Models/pa28-161.ac"; - _piperModel = sgLoad3DModel( globals->get_fg_root(), - planepath.c_str(), - globals->get_props(), - globals->get_sim_time_sec() ); - + try { + _piperModel = sgLoad3DModel( globals->get_fg_root(), + planepath.c_str(), + globals->get_props(), + globals->get_sim_time_sec() ); + } catch(sg_exception& e) { + _havePiperModel = false; + } + + // We need to keep one ref of the models open to stop ssg deleting them behind our back! + _defaultModel->ref(); + if(_havePiperModel) _piperModel->ref(); + // go through the $FG_ROOT/ATC directory and find all *.taxi files SGPath path(globals->get_fg_root()); path.append("ATC/"); @@ -96,50 +118,14 @@ void FGAIMgr::init() { 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 + "\\*.*"; + ulDir *d; + struct ulDirEnt *de; - if ( ( hfile = _findfirst( path.c_str(), &de ) ) == -1 ) { - SG_LOG(SG_ATC, SG_WARN, "cannot open directory " << dir); - } else { - // load all .taxi files - do { - file = de.name; - pos = file.find("."); - ext = file.substr(pos + 1); - if(ext == "taxi") { - f_ident = file.substr(0, pos); - FGAirport a; - if(dclFindAirportID(f_ident, &a)) { - SGBucket sgb(a.longitude, a.latitude); - int idx = sgb.gen_index(); - if(facilities.find(idx) != facilities.end()) { - facilities[idx]->push_back(f_ident); - } else { - ID_list_type* apts = new ID_list_type; - apts->push_back(f_ident); - facilities[idx] = apts; - } - SG_LOG(SG_ATC, SG_BULK, "Mapping " << f_ident << " to bucket " << idx); - } - } - } while ( _findnext( hfile, &de ) == 0 ); - } -#else - - DIR *d; - struct dirent *de; - - if ( (d = opendir( dir.c_str() )) == NULL ) { + if ( (d = ulOpenDir( dir.c_str() )) == NULL ) { SG_LOG(SG_ATC, SG_WARN, "cannot open directory " << dir); } else { // load all .taxi files - while ( (de = readdir(d)) != NULL ) { + while ( (de = ulReadDir(d)) != NULL ) { file = de->d_name; pos = file.find("."); ext = file.substr(pos + 1); @@ -147,7 +133,7 @@ void FGAIMgr::init() { f_ident = file.substr(0, pos); FGAirport a; if(dclFindAirportID(f_ident, &a)) { - SGBucket sgb(a.longitude, a.latitude); + SGBucket sgb(a.getLongitude(), a.getLatitude()); int idx = sgb.gen_index(); if(facilities.find(idx) != facilities.end()) { facilities[idx]->push_back(f_ident); @@ -160,10 +146,9 @@ void FGAIMgr::init() { } } } - closedir(d); + ulCloseDir(d); } -#endif - + // See if are in range at startup and activate if necessary SearchByPos(15.0); @@ -258,7 +243,7 @@ void FGAIMgr::update(double dt) { bool gen = false; //cout << "Size of list is " << (*it).second.size() << " at " << s << '\n'; if((*it).second.size()) { - FGAIEntity* e = *((*it).second.rbegin()); + FGAIEntity* e = *((*it).second.rbegin()); // Get the last airplane currently scheduled to arrive at this airport. cd = dclGetHorizontalSeparation(e->GetPos(), dclGetAirportPos(s)); if(cd < (d < 5000 ? 10000 : d + 5000)) { gen = true; @@ -270,7 +255,8 @@ void FGAIMgr::update(double dt) { if(gen) { //cout << "Generating extra traffic at airport " << s << ", at least " << cd << " meters out\n"; //GenerateSimpleAirportTraffic(s, cd); - GenerateSimpleAirportTraffic(s, cd + 2000.0); // The random seems a bit wierd - traffic could get far too bunched without the +2000. + GenerateSimpleAirportTraffic(s, cd + 3000.0); // The random seems a bit wierd - traffic could get far too bunched without the +3000. + // TODO - make the anti-random constant variable depending on the ai-traffic level. } } ++it; @@ -322,6 +308,7 @@ void FGAIMgr::ActivateAirport(string ident) { ATC->AIRegisterAirport(ident); // TODO - need to start the traffic more randomly FGAILocalTraffic* local_traffic = new FGAILocalTraffic; + local_traffic->SetModel(_defaultModel); // currently hardwired to cessna. //local_traffic->Init(ident, IN_PATTERN, TAKEOFF_ROLL); local_traffic->Init(GenerateShortForm(GenerateUniqueCallsign()), ident); local_traffic->FlyCircuits(1, true); // Fly 2 circuits with touch & go in between @@ -366,31 +353,22 @@ void FGAIMgr::GenerateSimpleAirportTraffic(string ident, double min_dist) { bool cessna = true; // Get the time and only operate VFR in the (approximate) daytime. - //SGTime *t = globals->get_time_params(); - string time_str = fgGetString("sim/time/gmt-string"); - int loc_time = atoi((time_str.substr(0,3)).c_str()); - //cout << "gmt_time = " << loc_time << '\n'; - loc_time += (int)((aptpos.lon() / 360.0) * 24.0); - while(loc_time < 0) loc_time += 24; - while(loc_time > 24) loc_time -= 24; + struct tm *t = globals->get_time_params()->getGmt(); + int loc_time = t->tm_hour + int(aptpos.lon() / (360.0 / 24.0)); + while (loc_time < 0) + loc_time += 24; + while (loc_time >= 24) + loc_time -= 24; + //cout << "loc_time = " << loc_time << '\n'; if(loc_time < 7 || loc_time > 19) return; // Check that the visibility is OK for IFR operation. double visibility; - #ifdef FG_WEATHERCM - //sgVec3 position = { aptpos.lat(), aptpos.lon(), aptpos.elev() }; - //FGPhysicalProperty stationweather = WeatherDatabase->get(position); - #else FGEnvironment stationweather = ((FGEnvironmentMgr *)globals->get_subsystem("environment")) ->getEnvironment(aptpos.lat(), aptpos.lon(), aptpos.elev()); // TODO - check whether this should take ft or m for elev. - #endif - #ifdef FG_WEATHERCM - visibility = fgGetDouble("/environment/visibility-m"); - #else visibility = stationweather.get_visibility_m(); - #endif // Technically we can do VFR down to 1 mile (1600m) but that's pretty murky! //cout << "vis = " << visibility << '\n'; if(visibility < 3000) return; @@ -485,11 +463,12 @@ void FGAIMgr::GenerateSimpleAirportTraffic(string ident, double min_dist) { double dir = int(sg_random() * 36); if(dir == 36) dir--; dir *= 10; + if(sg_random() < 0.3) cessna = false; else cessna = true; string s = GenerateShortForm(GenerateUniqueCallsign(), (cessna ? "Cessna-" : "Piper-")); FGAIGAVFRTraffic* t = new FGAIGAVFRTraffic(); - t->SetModel(cessna ? _defaultModel : _piperModel); + t->SetModel(cessna ? _defaultModel : (_havePiperModel ? _piperModel : _defaultModel)); //cout << "Generating VFR traffic " << s << " inbound to " << ident << " " << ad << " meters out from " << dir << " degrees\n"; Point3D tpos = dclUpdatePosition(aptpos, dir, 6.0, ad); if(tpos.elev() > (aptpos.elev() + 3000.0)) tpos.setelev(aptpos.elev() + 3000.0); // FEET yuk :-(