# include <dirent.h> // for directory reading
#endif
-#ifdef FG_WEATHERCM
-# include <WeatherCM/FGLocalWeatherDatabase.h>
-#else
-# include <Environment/environment_mgr.hxx>
-# include <Environment/environment.hxx>
-#endif
+#include <Environment/environment_mgr.hxx>
+#include <Environment/environment.hxx>
#include "AIMgr.hxx"
#include "AILocalTraffic.hxx"
// TODO - use the proper user callsign when it becomes user settable.
removalList.clear();
activated.clear();
+ _havePiperModel = true;
}
FGAIMgr::~FGAIMgr() {
+ ssgDeRefDelete(_defaultModel);
+ if(_havePiperModel) ssgDeRefDelete(_piperModel);
}
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/");
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);
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);
}
}
}
- closedir(d);
+ ulCloseDir(d);
}
-#endif
-
+
// See if are in range at startup and activate if necessary
SearchByPos(15.0);
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;
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;
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;
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 :-(