]> git.mxchange.org Git - flightgear.git/blob - src/AIModel/AIManager.cxx
Don't use the this pointer for referencing the AIModels anymore, this
[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   ModelVecIterator i = loadedModels.begin();
63   while (i != loadedModels.end())
64     {
65       i->getModelId()->deRef();
66     }
67 }
68
69
70 void FGAIManager::init() {
71   root = fgGetNode("sim/ai", true);
72
73   enabled = root->getNode("enabled", true)->getBoolValue();
74   if (!enabled)
75       return;
76
77   wind_from_down_node = fgGetNode("/environment/wind-from-down-fps", true);
78   wind_from_east_node  = fgGetNode("/environment/wind-from-east-fps",true);
79   wind_from_north_node = fgGetNode("/environment/wind-from-north-fps",true);
80
81   user_latitude_node  = fgGetNode("/position/latitude-deg", true);
82   user_longitude_node = fgGetNode("/position/longitude-deg", true);
83   user_altitude_node  = fgGetNode("/position/altitude-ft", true);
84   user_heading_node   = fgGetNode("/orientation/heading-deg", true);
85   user_pitch_node     = fgGetNode("/orientation/pitch-deg", true);
86   user_yaw_node       = fgGetNode("/orientation/side-slip-deg", true);
87   user_speed_node     = fgGetNode("/velocities/uBody-fps", true);
88
89   for(int i = 0 ; i < root->nChildren() ; i++) {
90     SGPropertyNode *aiEntry = root->getChild( i );
91         if( !strcmp( aiEntry->getName(), "scenario" ) ) {
92       scenario_filename = aiEntry->getStringValue();
93       if (scenario_filename != "") processScenario( scenario_filename );
94         }
95   }
96   initDone = true;
97 }
98
99
100 void FGAIManager::reinit() {
101    update(0.0);
102 }
103
104
105 void FGAIManager::bind() {
106    root = globals->get_props()->getNode("ai/models", true);
107    root->tie("count", SGRawValuePointer<int>(&numObjects[0]));
108 }
109
110
111 void FGAIManager::unbind() {
112     root->untie("count");
113 }
114
115
116 void FGAIManager::update(double dt) {
117
118         // initialize these for finding nearest thermals
119         range_nearest = 10000.0;
120         strength = 0.0;
121         FGTrafficManager *tmgr = (FGTrafficManager*) globals->get_subsystem("Traffic Manager");
122
123         if (!enabled)
124             return;
125
126         _dt = dt;
127
128         ai_list_iterator ai_list_itr = ai_list.begin();
129         while(ai_list_itr != ai_list.end()) {
130                 if ((*ai_list_itr)->getDie()) {      
131                   tmgr->release((*ai_list_itr)->getID());
132                    --numObjects[(*ai_list_itr)->getType()];
133                    --numObjects[0];
134                    (*ai_list_itr)->unbind();
135                    delete (*ai_list_itr);
136                    if ( ai_list_itr == ai_list.begin() ) {
137                        ai_list.erase(ai_list_itr);
138                        ai_list_itr = ai_list.begin();
139                        continue;
140                    } else {
141                        ai_list.erase(ai_list_itr--);
142                    }
143                 } else {
144                    fetchUserState();
145                    if ((*ai_list_itr)->isa(FGAIBase::otThermal)) {
146                        processThermal((FGAIThermal*)*ai_list_itr); 
147                    } else { 
148                       (*ai_list_itr)->update(_dt);
149                    }
150                 }
151                 ++ai_list_itr;
152         }
153         wind_from_down_node->setDoubleValue( strength ); // for thermals
154
155 }
156
157
158 void*
159 FGAIManager::createAircraft( FGAIModelEntity *entity,   FGAISchedule *ref) {
160      
161         FGAIAircraft* ai_plane = new FGAIAircraft(this, ref);
162         ai_list.push_back(ai_plane);
163         ++numObjects[0];
164         ++numObjects[FGAIBase::otAircraft];
165         if (entity->m_class == "light") {
166           ai_plane->SetPerformance(&FGAIAircraft::settings[FGAIAircraft::LIGHT]);
167         } else if (entity->m_class == "ww2_fighter") {
168           ai_plane->SetPerformance(&FGAIAircraft::settings[FGAIAircraft::WW2_FIGHTER]);
169         } else if (entity->m_class ==  "jet_transport") {
170           ai_plane->SetPerformance(&FGAIAircraft::settings[FGAIAircraft::JET_TRANSPORT]);
171         } else if (entity->m_class == "jet_fighter") {
172           ai_plane->SetPerformance(&FGAIAircraft::settings[FGAIAircraft::JET_FIGHTER]);
173         } else if (entity->m_class ==  "tanker") {
174           ai_plane->SetPerformance(&FGAIAircraft::settings[FGAIAircraft::JET_TRANSPORT]);
175           ai_plane->SetTanker(true);
176         } else {
177           ai_plane->SetPerformance(&FGAIAircraft::settings[FGAIAircraft::JET_TRANSPORT]);
178         }
179         ai_plane->setAcType(entity->acType);
180         ai_plane->setCompany(entity->company);
181         ai_plane->setHeading(entity->heading);
182         ai_plane->setSpeed(entity->speed);
183         ai_plane->setPath(entity->path.c_str());
184         ai_plane->setAltitude(entity->altitude);
185         ai_plane->setLongitude(entity->longitude);
186         ai_plane->setLatitude(entity->latitude);
187         ai_plane->setBank(entity->roll);
188
189         if ( entity->fp ) {
190           ai_plane->SetFlightPlan(entity->fp);
191         }
192         if (entity->repeat) {
193           ai_plane->GetFlightPlan()->setRepeat(true);
194         }
195         ai_plane->init();
196         ai_plane->bind();
197         return ai_plane;
198 }
199
200 void*
201 FGAIManager::createShip( FGAIModelEntity *entity ) {
202     
203      // cout << "creating ship" << endl;    
204
205         FGAIShip* ai_ship = new FGAIShip(this);
206         ai_list.push_back(ai_ship);
207         ++numObjects[0];
208         ++numObjects[FGAIBase::otShip];
209         ai_ship->setHeading(entity->heading);
210         ai_ship->setSpeed(entity->speed);
211         ai_ship->setPath(entity->path.c_str());
212         ai_ship->setAltitude(entity->altitude);
213         ai_ship->setLongitude(entity->longitude);
214         ai_ship->setLatitude(entity->latitude);
215         ai_ship->setRudder(entity->rudder);
216         ai_ship->setName(entity->name);
217
218         if ( entity->fp ) {
219            ai_ship->setFlightPlan(entity->fp);
220         }
221
222         ai_ship->init();
223         ai_ship->bind();
224         return ai_ship;
225 }
226
227 void*
228 FGAIManager::createCarrier( FGAIModelEntity *entity ) {
229     
230     // cout << "creating carrier" << endl;
231
232         FGAICarrier* ai_carrier = new FGAICarrier(this);
233         ai_list.push_back(ai_carrier);
234         ++numObjects[0];
235         ++numObjects[FGAIBase::otCarrier];
236         ai_carrier->setHeading(entity->heading);
237         ai_carrier->setSpeed(entity->speed);
238         ai_carrier->setPath(entity->path.c_str());
239         ai_carrier->setAltitude(entity->altitude);
240         ai_carrier->setLongitude(entity->longitude);
241         ai_carrier->setLatitude(entity->latitude);
242         ai_carrier->setRudder(entity->rudder);
243         ai_carrier->setSolidObjects(entity->solid_objects);
244         ai_carrier->setWireObjects(entity->wire_objects);
245         ai_carrier->setCatapultObjects(entity->catapult_objects);
246         ai_carrier->setParkingPositions(entity->ppositions);
247         ai_carrier->setRadius(entity->radius);
248         ai_carrier->setSign(entity->pennant_number);
249         ai_carrier->setName(entity->name);
250         ai_carrier->setFlolsOffset(entity->flols_offset);
251         ai_carrier->setWind_from_east(entity->wind_from_east);
252         ai_carrier->setWind_from_north(entity->wind_from_north);
253         ai_carrier->setTACANChannelID(entity->TACAN_channel_ID);
254         ai_carrier->setMaxLat(entity->max_lat);
255         ai_carrier->setMinLat(entity->min_lat);
256         ai_carrier->setMaxLong(entity->max_long);
257         ai_carrier->setMinLong(entity->min_long);
258         
259
260         if ( entity->fp ) {
261            ai_carrier->setFlightPlan(entity->fp);
262         }
263
264         ai_carrier->init();
265         ai_carrier->bind();
266         return ai_carrier;
267 }
268
269 void*
270 FGAIManager::createBallistic( FGAIModelEntity *entity ) {
271
272         FGAIBallistic* ai_ballistic = new FGAIBallistic(this);
273         ai_list.push_back(ai_ballistic);
274         ++numObjects[0];
275         ++numObjects[FGAIBase::otBallistic];
276         ai_ballistic->setAzimuth(entity->azimuth);
277         ai_ballistic->setElevation(entity->elevation);
278         ai_ballistic->setSpeed(entity->speed);
279         ai_ballistic->setPath(entity->path.c_str());
280         ai_ballistic->setAltitude(entity->altitude);
281         ai_ballistic->setLongitude(entity->longitude);
282         ai_ballistic->setLatitude(entity->latitude);
283         ai_ballistic->setDragArea(entity->eda);
284         ai_ballistic->setLife(entity->life);
285         ai_ballistic->setBuoyancy(entity->buoyancy);
286         ai_ballistic->setWind_from_east(entity->wind_from_east);
287         ai_ballistic->setWind_from_north(entity->wind_from_north);
288         ai_ballistic->setWind(entity->wind);
289         ai_ballistic->setRoll(entity->roll);
290         ai_ballistic->setCd(entity->cd);
291         ai_ballistic->setMass(entity->mass);
292         ai_ballistic->setStabilisation(entity->aero_stabilised);
293         ai_ballistic->init();
294         ai_ballistic->bind();
295         return ai_ballistic;
296 }
297
298 void*
299 FGAIManager::createStorm( FGAIModelEntity *entity ) {
300
301         FGAIStorm* ai_storm = new FGAIStorm(this);
302         ++numObjects[0];
303         ++numObjects[FGAIBase::otStorm];
304         ai_storm->setHeading(entity->heading);
305         ai_storm->setSpeed(entity->speed);
306         ai_storm->setPath(entity->path.c_str());
307         ai_storm->setAltitude(entity->altitude); 
308         ai_storm->setDiameter(entity->diameter / 6076.11549); 
309         ai_storm->setHeight(entity->height_msl); 
310         ai_storm->setStrengthNorm(entity->strength); 
311         ai_storm->setLongitude(entity->longitude);
312         ai_storm->setLatitude(entity->latitude);
313         ai_storm->init();
314         ai_storm->bind();
315         ai_list.push_back(ai_storm);
316         return ai_storm;
317 }
318
319 void*
320 FGAIManager::createThermal( FGAIModelEntity *entity ) {
321
322         FGAIThermal* ai_thermal = new FGAIThermal(this);
323         ++numObjects[0];
324         ++numObjects[FGAIBase::otThermal];
325         ai_thermal->setLongitude(entity->longitude);
326         ai_thermal->setLatitude(entity->latitude);
327         ai_thermal->setMaxStrength(entity->strength);
328         ai_thermal->setDiameter(entity->diameter / 6076.11549);
329         ai_thermal->setHeight(entity->height_msl);
330         ai_thermal->init();
331         ai_thermal->bind();
332         ai_list.push_back(ai_thermal);
333         return ai_thermal;
334 }
335
336 void*
337 FGAIManager::createStatic( FGAIModelEntity *entity ) {
338      
339      // cout << "creating static object" << endl;    
340
341         FGAIStatic* ai_static = new FGAIStatic(this);
342         ai_list.push_back(ai_static);
343         ++numObjects[0];
344         ++numObjects[FGAIBase::otStatic];
345         ai_static->setHeading(entity->heading);
346         ai_static->setPath(entity->path.c_str());
347         ai_static->setAltitude(entity->altitude);
348         ai_static->setLongitude(entity->longitude);
349         ai_static->setLatitude(entity->latitude);
350         ai_static->init();
351         ai_static->bind();
352         return ai_static;
353 }
354
355 void FGAIManager::destroyObject( int ID ) {
356         ai_list_iterator ai_list_itr = ai_list.begin();
357         while(ai_list_itr != ai_list.end()) {
358             if ((*ai_list_itr)->getID() == ID) {
359               --numObjects[0];
360               --numObjects[(*ai_list_itr)->getType()];
361               (*ai_list_itr)->unbind();
362               delete (*ai_list_itr);
363               ai_list.erase(ai_list_itr);
364
365               break;
366             }
367             ++ai_list_itr;
368         }
369 }
370
371
372 void FGAIManager::fetchUserState( void ) {
373      user_latitude  = user_latitude_node->getDoubleValue();
374      user_longitude = user_longitude_node->getDoubleValue();
375      user_altitude  = user_altitude_node->getDoubleValue();
376      user_heading   = user_heading_node->getDoubleValue();
377      user_pitch     = user_pitch_node->getDoubleValue();
378      user_yaw       = user_yaw_node->getDoubleValue();
379      user_speed     = user_speed_node->getDoubleValue() * 0.592484;
380      wind_from_east = wind_from_east_node->getDoubleValue();
381      wind_from_north = wind_from_north_node->getDoubleValue();
382      
383      
384 }
385
386
387 // only keep the results from the nearest thermal
388 void FGAIManager::processThermal( FGAIThermal* thermal ) {
389   thermal->update(_dt);
390   if ( thermal->_getRange() < range_nearest ) {
391      range_nearest = thermal->_getRange();
392      strength = thermal->getStrength();
393   }
394 }
395
396
397 void FGAIManager::processScenario( const string &filename ) {
398   FGAIScenario* s = new FGAIScenario( filename );
399   for (int i=0;i<s->nEntries();i++) {
400     FGAIModelEntity* en = s->getNextEntry();
401
402     if (en) {
403       if ( en->m_type == "aircraft") {
404         createAircraft( en );
405
406       } else if ( en->m_type == "ship") {
407         createShip( en );
408
409       } else if ( en->m_type == "carrier") {
410         createCarrier( en );
411
412       } else if ( en->m_type == "thunderstorm") {
413         createStorm( en );
414
415       } else if ( en->m_type == "thermal") {
416         createThermal( en );
417
418       } else if ( en->m_type == "ballistic") {
419         createBallistic( en );
420
421       } else if ( en->m_type == "static") {
422         createStatic( en );
423       }            
424     }
425   }
426
427   delete s;
428 }
429
430 // This code keeps track of models that have already been loaded
431 // Eventually we'd prbably need to find a way to keep track of models
432 // that are unloaded again
433 ssgBranch * FGAIManager::getModel(const string& path)
434 {
435   ModelVecIterator i = loadedModels.begin();
436   while (i != loadedModels.end())
437     {
438       if (i->getPath() == path)
439         return i->getModelId();
440       i++;
441     }
442   return 0;
443 }
444
445 void FGAIManager::setModel(const string& path, ssgBranch *model)
446 {
447   loadedModels.push_back(FGModelID(path,model));
448 }
449
450 bool FGAIManager::getStartPosition(const string& id, const string& pid,
451                                    Point3D& geodPos, double& heading,
452                                    sgdVec3 uvw)
453 {
454   SGPropertyNode* root = fgGetNode("sim/ai", true);
455   if (!root->getNode("enabled", true)->getBoolValue())
456       return 0;
457
458   bool found = false;
459   for(int i = 0 ; (!found) && i < root->nChildren() ; i++) {
460     SGPropertyNode *aiEntry = root->getChild( i );
461         if( !strcmp( aiEntry->getName(), "scenario" ) ) {
462         string filename = aiEntry->getStringValue();
463         FGAIScenario* s = new FGAIScenario( filename );
464         for (int i=0; i<s->nEntries(); i++) {
465             FGAIModelEntity* en = s->getNextEntry();
466             if (en && en->m_type == "carrier" &&
467                 (en->pennant_number == id || en->name == id)) {
468             FGAICarrier* ai_carrier = new FGAICarrier(0);
469             ai_carrier->setHeading(en->heading);
470             ai_carrier->setSpeed(en->speed);
471             ai_carrier->setAltitude(en->altitude);
472             ai_carrier->setLongitude(en->longitude);
473             ai_carrier->setLatitude(en->latitude);
474             ai_carrier->setBank(en->rudder);
475             ai_carrier->setParkingPositions(en->ppositions);
476       ai_carrier->setWind_from_east(en->wind_from_east);
477       ai_carrier->setWind_from_north(en->wind_from_north);
478       //ai_carrier->setTACANFreq(en->TACAN_freq);
479
480             if (ai_carrier->getParkPosition(pid, geodPos, heading, uvw)) {
481                 delete ai_carrier;
482                 found = true;
483                 break;
484             }
485
486             delete ai_carrier;
487         }
488       }
489       delete s;
490     }
491   }
492   return found;
493 }
494
495 //end AIManager.cxx