]> git.mxchange.org Git - flightgear.git/blob - src/AIModel/AIManager.cxx
0047d0199b081895ba55a866e1c03b2b147fa4dc
[flightgear.git] / src / AIModel / AIManager.cxx
1 // AIManager.cxx  Based on David Luff's AIMgr:
2 // - a global management type for AI objects
3 //
4 // Written by David Culp, started October 2003.
5 // - davidculp2@comcast.net
6 //
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License as
9 // published by the Free Software Foundation; either version 2 of the
10 // License, or (at your option) any later version.
11 //
12 // This program is distributed in the hope that it will be useful, but
13 // WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 // General Public License for more details.
16 //
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20
21 #include <simgear/misc/sg_path.hxx>
22 #include <Main/fg_props.hxx>
23 #include <Main/globals.hxx>
24
25 #include <Airports/simple.hxx>
26 #include <Traffic/SchedFlight.hxx>
27 #include <Traffic/Schedule.hxx>
28 #include <Traffic/TrafficMgr.hxx>
29
30 #include <list>
31
32 #include "AIManager.hxx"
33 #include "AIAircraft.hxx"
34 #include "AIShip.hxx"
35 #include "AIBallistic.hxx"
36 #include "AIStorm.hxx"
37 #include "AIThermal.hxx"
38 #include "AICarrier.hxx"
39 #include "AIStatic.hxx"
40
41 SG_USING_STD(list);
42
43
44 FGAIManager::FGAIManager() {
45   initDone = false;
46   for (int i=0; i < FGAIBase::MAX_OBJECTS; i++)
47      numObjects[i] = 0;
48   _dt = 0.0;
49   dt_count = 9;
50   scenario_filename = "";
51   ai_list.clear();
52 }
53
54 FGAIManager::~FGAIManager() {
55   ai_list_iterator ai_list_itr = ai_list.begin();
56   while(ai_list_itr != ai_list.end()) {
57       (*ai_list_itr)->unbind();
58       delete (*ai_list_itr);
59       ++ai_list_itr;
60     }
61   ai_list.clear();
62 }
63
64
65 void FGAIManager::init() {
66   root = fgGetNode("sim/ai", true);
67
68   enabled = root->getNode("enabled", true)->getBoolValue();
69   if (!enabled)
70       return;
71
72   wind_from_down_node = fgGetNode("/environment/wind-from-down-fps", true);
73   wind_from_east_node  = fgGetNode("/environment/wind-from-east-fps",true);
74   wind_from_north_node = fgGetNode("/environment/wind-from-north-fps",true);
75
76   user_latitude_node  = fgGetNode("/position/latitude-deg", true);
77   user_longitude_node = fgGetNode("/position/longitude-deg", true);
78   user_altitude_node  = fgGetNode("/position/altitude-ft", true);
79   user_heading_node   = fgGetNode("/orientation/heading-deg", true);
80   user_pitch_node     = fgGetNode("/orientation/pitch-deg", true);
81   user_yaw_node       = fgGetNode("/orientation/side-slip-deg", true);
82   user_speed_node     = fgGetNode("/velocities/uBody-fps", true);
83
84   for(int i = 0 ; i < root->nChildren() ; i++) {
85     SGPropertyNode *aiEntry = root->getChild( i );
86         if( !strcmp( aiEntry->getName(), "scenario" ) ) {
87       scenario_filename = aiEntry->getStringValue();
88       if (scenario_filename != "") processScenario( scenario_filename );
89         }
90   }
91   initDone = true;
92 }
93
94
95 void FGAIManager::reinit() {
96    update(0.0);
97 }
98
99
100 void FGAIManager::bind() {
101    root = globals->get_props()->getNode("ai/models", true);
102    root->tie("count", SGRawValuePointer<int>(&numObjects[0]));
103 }
104
105
106 void FGAIManager::unbind() {
107     root->untie("count");
108 }
109
110
111 void FGAIManager::update(double dt) {
112
113         // initialize these for finding nearest thermals
114         range_nearest = 10000.0;
115         strength = 0.0;
116         FGTrafficManager *tmgr = (FGTrafficManager*) globals->get_subsystem("Traffic Manager");
117
118         if (!enabled)
119             return;
120
121         _dt = dt;
122
123         ai_list_iterator ai_list_itr = ai_list.begin();
124         while(ai_list_itr != ai_list.end()) {
125                 if ((*ai_list_itr)->getDie()) {      
126                   tmgr->release((*ai_list_itr)->getID());
127                    --numObjects[(*ai_list_itr)->getType()];
128                    --numObjects[0];
129                    (*ai_list_itr)->unbind();
130                    delete (*ai_list_itr);
131                    if ( ai_list_itr == ai_list.begin() ) {
132                        ai_list.erase(ai_list_itr);
133                        ai_list_itr = ai_list.begin();
134                        continue;
135                    } else {
136                        ai_list.erase(ai_list_itr--);
137                    }
138                 } else {
139                    fetchUserState();
140                    if ((*ai_list_itr)->isa(FGAIBase::otThermal)) {
141                        processThermal((FGAIThermal*)*ai_list_itr); 
142                    } else { 
143                       (*ai_list_itr)->update(_dt);
144                    }
145                 }
146                 ++ai_list_itr;
147         }
148         wind_from_down_node->setDoubleValue( strength ); // for thermals
149
150 }
151
152
153 void*
154 FGAIManager::createAircraft( FGAIModelEntity *entity,   FGAISchedule *ref) {
155      
156         FGAIAircraft* ai_plane = new FGAIAircraft(this, ref);
157         ai_list.push_back(ai_plane);
158         ++numObjects[0];
159         ++numObjects[FGAIBase::otAircraft];
160         if (entity->m_class == "light") {
161           ai_plane->SetPerformance(&FGAIAircraft::settings[FGAIAircraft::LIGHT]);
162         } else if (entity->m_class == "ww2_fighter") {
163           ai_plane->SetPerformance(&FGAIAircraft::settings[FGAIAircraft::WW2_FIGHTER]);
164         } else if (entity->m_class ==  "jet_transport") {
165           ai_plane->SetPerformance(&FGAIAircraft::settings[FGAIAircraft::JET_TRANSPORT]);
166         } else if (entity->m_class == "jet_fighter") {
167           ai_plane->SetPerformance(&FGAIAircraft::settings[FGAIAircraft::JET_FIGHTER]);
168         } else if (entity->m_class ==  "tanker") {
169           ai_plane->SetPerformance(&FGAIAircraft::settings[FGAIAircraft::JET_TRANSPORT]);
170           ai_plane->SetTanker(true);
171         } else {
172           ai_plane->SetPerformance(&FGAIAircraft::settings[FGAIAircraft::JET_TRANSPORT]);
173         }
174         ai_plane->setAcType(entity->acType);
175         ai_plane->setCompany(entity->company);
176         ai_plane->setHeading(entity->heading);
177         ai_plane->setSpeed(entity->speed);
178         ai_plane->setPath(entity->path.c_str());
179         ai_plane->setAltitude(entity->altitude);
180         ai_plane->setLongitude(entity->longitude);
181         ai_plane->setLatitude(entity->latitude);
182         ai_plane->setBank(entity->roll);
183
184         if ( entity->fp ) {
185           ai_plane->SetFlightPlan(entity->fp);
186         }
187         if (entity->repeat) {
188           ai_plane->GetFlightPlan()->setRepeat(true);
189         }
190         ai_plane->init();
191         ai_plane->bind();
192         return ai_plane;
193 }
194
195 void*
196 FGAIManager::createShip( FGAIModelEntity *entity ) {
197     
198      // cout << "creating ship" << endl;    
199
200         FGAIShip* ai_ship = new FGAIShip(this);
201         ai_list.push_back(ai_ship);
202         ++numObjects[0];
203         ++numObjects[FGAIBase::otShip];
204         ai_ship->setHeading(entity->heading);
205         ai_ship->setSpeed(entity->speed);
206         ai_ship->setPath(entity->path.c_str());
207         ai_ship->setAltitude(entity->altitude);
208         ai_ship->setLongitude(entity->longitude);
209         ai_ship->setLatitude(entity->latitude);
210         ai_ship->setRudder(entity->rudder);
211         ai_ship->setName(entity->name);
212
213         if ( entity->fp ) {
214            ai_ship->setFlightPlan(entity->fp);
215         }
216
217         ai_ship->init();
218         ai_ship->bind();
219         return ai_ship;
220 }
221
222 void*
223 FGAIManager::createCarrier( FGAIModelEntity *entity ) {
224     
225     // cout << "creating carrier" << endl;
226
227         FGAICarrier* ai_carrier = new FGAICarrier(this);
228         ai_list.push_back(ai_carrier);
229         ++numObjects[0];
230         ++numObjects[FGAIBase::otCarrier];
231         ai_carrier->setHeading(entity->heading);
232         ai_carrier->setSpeed(entity->speed);
233         ai_carrier->setPath(entity->path.c_str());
234         ai_carrier->setAltitude(entity->altitude);
235         ai_carrier->setLongitude(entity->longitude);
236         ai_carrier->setLatitude(entity->latitude);
237         ai_carrier->setRudder(entity->rudder);
238         ai_carrier->setSolidObjects(entity->solid_objects);
239         ai_carrier->setWireObjects(entity->wire_objects);
240         ai_carrier->setCatapultObjects(entity->catapult_objects);
241         ai_carrier->setParkingPositions(entity->ppositions);
242         ai_carrier->setRadius(entity->radius);
243         ai_carrier->setSign(entity->pennant_number);
244         ai_carrier->setName(entity->name);
245         ai_carrier->setFlolsOffset(entity->flols_offset);
246         ai_carrier->setWind_from_east(entity->wind_from_east);
247         ai_carrier->setWind_from_north(entity->wind_from_north);
248         ai_carrier->setTACANChannelID(entity->TACAN_channel_ID);
249         ai_carrier->setMaxLat(entity->max_lat);
250         ai_carrier->setMinLat(entity->min_lat);
251         ai_carrier->setMaxLong(entity->max_long);
252         ai_carrier->setMinLong(entity->min_long);
253         
254
255         if ( entity->fp ) {
256            ai_carrier->setFlightPlan(entity->fp);
257         }
258
259         ai_carrier->init();
260         ai_carrier->bind();
261         return ai_carrier;
262 }
263
264 void*
265 FGAIManager::createBallistic( FGAIModelEntity *entity ) {
266
267         FGAIBallistic* ai_ballistic = new FGAIBallistic(this);
268         ai_list.push_back(ai_ballistic);
269         ++numObjects[0];
270         ++numObjects[FGAIBase::otBallistic];
271         ai_ballistic->setAzimuth(entity->azimuth);
272         ai_ballistic->setElevation(entity->elevation);
273         ai_ballistic->setSpeed(entity->speed);
274         ai_ballistic->setPath(entity->path.c_str());
275         ai_ballistic->setAltitude(entity->altitude);
276         ai_ballistic->setLongitude(entity->longitude);
277         ai_ballistic->setLatitude(entity->latitude);
278         ai_ballistic->setDragArea(entity->eda);
279         ai_ballistic->setLife(entity->life);
280         ai_ballistic->setBuoyancy(entity->buoyancy);
281         ai_ballistic->setWind_from_east(entity->wind_from_east);
282         ai_ballistic->setWind_from_north(entity->wind_from_north);
283         ai_ballistic->setWind(entity->wind);
284         ai_ballistic->setRoll(entity->roll);
285         ai_ballistic->setCd(entity->cd);
286         ai_ballistic->setMass(entity->mass);
287         ai_ballistic->setStabilisation(entity->aero_stabilised);
288         ai_ballistic->init();
289         ai_ballistic->bind();
290         return ai_ballistic;
291 }
292
293 void*
294 FGAIManager::createStorm( FGAIModelEntity *entity ) {
295
296         FGAIStorm* ai_storm = new FGAIStorm(this);
297         ++numObjects[0];
298         ++numObjects[FGAIBase::otStorm];
299         ai_storm->setHeading(entity->heading);
300         ai_storm->setSpeed(entity->speed);
301         ai_storm->setPath(entity->path.c_str());
302         ai_storm->setAltitude(entity->altitude); 
303         ai_storm->setDiameter(entity->diameter / 6076.11549); 
304         ai_storm->setHeight(entity->height_msl); 
305         ai_storm->setStrengthNorm(entity->turb_strength); 
306         ai_storm->setLongitude(entity->longitude);
307         ai_storm->setLatitude(entity->latitude);
308         ai_storm->init();
309         ai_storm->bind();
310         ai_list.push_back(ai_storm);
311         return ai_storm;
312 }
313
314 void*
315 FGAIManager::createThermal( FGAIModelEntity *entity ) {
316
317         FGAIThermal* ai_thermal = new FGAIThermal(this);
318         ++numObjects[0];
319         ++numObjects[FGAIBase::otThermal];
320         ai_thermal->setLongitude(entity->longitude);
321         ai_thermal->setLatitude(entity->latitude);
322         ai_thermal->setMaxStrength(entity->strength);
323         ai_thermal->setDiameter(entity->diameter / 6076.11549);
324         ai_thermal->setHeight(entity->height_msl);
325         ai_thermal->init();
326         ai_thermal->bind();
327         ai_list.push_back(ai_thermal);
328         return ai_thermal;
329 }
330
331 void*
332 FGAIManager::createStatic( FGAIModelEntity *entity ) {
333      
334      // cout << "creating static object" << endl;    
335
336         FGAIStatic* ai_static = new FGAIStatic(this);
337         ai_list.push_back(ai_static);
338         ++numObjects[0];
339         ++numObjects[FGAIBase::otStatic];
340         ai_static->setHeading(entity->heading);
341         ai_static->setPath(entity->path.c_str());
342         ai_static->setAltitude(entity->altitude);
343         ai_static->setLongitude(entity->longitude);
344         ai_static->setLatitude(entity->latitude);
345         ai_static->init();
346         ai_static->bind();
347         return ai_static;
348 }
349
350 void FGAIManager::destroyObject( int ID ) {
351         ai_list_iterator ai_list_itr = ai_list.begin();
352         while(ai_list_itr != ai_list.end()) {
353             if ((*ai_list_itr)->getID() == ID) {
354               --numObjects[0];
355               --numObjects[(*ai_list_itr)->getType()];
356               (*ai_list_itr)->unbind();
357               delete (*ai_list_itr);
358               ai_list.erase(ai_list_itr);
359
360               break;
361             }
362             ++ai_list_itr;
363         }
364 }
365
366
367 void FGAIManager::fetchUserState( void ) {
368      user_latitude  = user_latitude_node->getDoubleValue();
369      user_longitude = user_longitude_node->getDoubleValue();
370      user_altitude  = user_altitude_node->getDoubleValue();
371      user_heading   = user_heading_node->getDoubleValue();
372      user_pitch     = user_pitch_node->getDoubleValue();
373      user_yaw       = user_yaw_node->getDoubleValue();
374      user_speed     = user_speed_node->getDoubleValue() * 0.592484;
375      wind_from_east = wind_from_east_node->getDoubleValue();
376      wind_from_north = wind_from_north_node->getDoubleValue();
377      
378      
379 }
380
381
382 // only keep the results from the nearest thermal
383 void FGAIManager::processThermal( FGAIThermal* thermal ) {
384   thermal->update(_dt);
385   if ( thermal->_getRange() < range_nearest ) {
386      range_nearest = thermal->_getRange();
387      strength = thermal->getStrength();
388   }
389 }
390
391
392 void FGAIManager::processScenario( const string &filename ) {
393   FGAIScenario* s = new FGAIScenario( filename );
394   for (int i=0;i<s->nEntries();i++) {
395    FGAIModelEntity* const en = s->getNextEntry();
396
397     if (en) {
398       if ( en->m_type == "aircraft") {
399         createAircraft( en );
400
401       } else if ( en->m_type == "ship") {
402         createShip( en );
403
404       } else if ( en->m_type == "carrier") {
405         createCarrier( en );
406
407       } else if ( en->m_type == "thunderstorm") {
408         createStorm( en );
409
410       } else if ( en->m_type == "thermal") {
411         createThermal( en );
412
413       } else if ( en->m_type == "ballistic") {
414         createBallistic( en );
415
416       } else if ( en->m_type == "static") {
417         createStatic( en );
418       }            
419     }
420   }
421
422   delete s;
423 }
424
425 // This code keeps track of models that have already been loaded
426 // Eventually we'd prbably need to find a way to keep track of models
427 // that are unloaded again
428 ssgBranch * FGAIManager::getModel(const string& path) const
429 {
430   ModelVecIterator i = loadedModels.begin();
431   while (i != loadedModels.end())
432     {
433       if (i->getPath() == path)
434         return i->getModelId();
435       i++;
436     }
437   return 0;
438 }
439
440 void FGAIManager::setModel(const string& path, ssgBranch *model)
441 {
442   loadedModels.push_back(FGModelID(path,model));
443 }
444
445 bool FGAIManager::getStartPosition(const string& id, const string& pid,
446                                    Point3D& geodPos, double& heading,
447                                    sgdVec3 uvw)
448 {
449   SGPropertyNode* root = fgGetNode("sim/ai", true);
450   if (!root->getNode("enabled", true)->getBoolValue())
451       return 0;
452
453   bool found = false;
454   for(int i = 0 ; (!found) && i < root->nChildren() ; i++) {
455     SGPropertyNode *aiEntry = root->getChild( i );
456         if( !strcmp( aiEntry->getName(), "scenario" ) ) {
457         string filename = aiEntry->getStringValue();
458         FGAIScenario* s = new FGAIScenario( filename );
459         for (int i=0; i<s->nEntries(); i++) {
460             FGAIModelEntity* en = s->getNextEntry();
461             if (en && en->m_type == "carrier" &&
462                 (en->pennant_number == id || en->name == id)) {
463             FGAICarrier* ai_carrier = new FGAICarrier(0);
464             ai_carrier->setHeading(en->heading);
465             ai_carrier->setSpeed(en->speed);
466             ai_carrier->setAltitude(en->altitude);
467             ai_carrier->setLongitude(en->longitude);
468             ai_carrier->setLatitude(en->latitude);
469             ai_carrier->setBank(en->rudder);
470             ai_carrier->setParkingPositions(en->ppositions);
471       ai_carrier->setWind_from_east(en->wind_from_east);
472       ai_carrier->setWind_from_north(en->wind_from_north);
473       //ai_carrier->setTACANFreq(en->TACAN_freq);
474
475             if (ai_carrier->getParkPosition(pid, geodPos, heading, uvw)) {
476                 delete ai_carrier;
477                 found = true;
478                 break;
479             }
480
481             delete ai_carrier;
482         }
483       }
484       delete s;
485     }
486   }
487   return found;
488 }
489
490 //end AIManager.cxx