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