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