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