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