]> git.mxchange.org Git - flightgear.git/blob - src/AIModel/AIManager.cxx
52d8e3da96d7879d967019bf8d173707b1ae397a
[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
40 SG_USING_STD(list);
41
42
43 FGAIManager::FGAIManager() {
44   initDone = false;
45   for (int i=0; i < FGAIBase::MAX_OBJECTS; i++)
46      numObjects[i] = 0;
47   _dt = 0.0;
48   dt_count = 9;
49   scenario_filename = "";
50   ai_list.clear();
51 }
52
53 FGAIManager::~FGAIManager() {
54   ai_list_itr = ai_list.begin();
55   while(ai_list_itr != ai_list.end()) {
56       (*ai_list_itr)->unbind();
57       delete (*ai_list_itr);
58       ++ai_list_itr;
59     }
60   ai_list.clear();
61   ModelVecIterator i = loadedModels.begin();
62   while (i != loadedModels.end())
63     {
64       i->getModelId()->deRef();
65     }
66 }
67
68
69 void FGAIManager::init() {
70   root = fgGetNode("sim/ai", true);
71
72   enabled = root->getNode("enabled", true)->getBoolValue();
73   if (!enabled)
74       return;
75
76   wind_from_down_node = fgGetNode("/environment/wind-from-down-fps", true);
77  
78   scenario_filename = root->getNode("scenario", true)->getStringValue();
79   if (scenario_filename != "") processScenario( scenario_filename );
80
81   initDone = true;
82 }
83
84
85 void FGAIManager::bind() {
86    root = globals->get_props()->getNode("ai/models", true);
87    root->tie("count", SGRawValuePointer<int>(&numObjects[0]));
88 }
89
90
91 void FGAIManager::unbind() {
92     root->untie("count");
93 }
94
95
96 void FGAIManager::update(double dt) {
97
98         // initialize these for finding nearest thermals
99         range_nearest = 10000.0;
100         strength = 0.0;
101         FGTrafficManager *tmgr = (FGTrafficManager*) globals->get_subsystem("Traffic Manager");
102
103         if (!enabled)
104             return;
105
106         _dt = dt;
107
108         ai_list_itr = ai_list.begin();
109         while(ai_list_itr != ai_list.end()) {
110                 if ((*ai_list_itr)->getDie()) {      
111                   tmgr->release((*ai_list_itr)->getID());
112                    --numObjects[(*ai_list_itr)->getType()];
113                    --numObjects[0];
114                    (*ai_list_itr)->unbind();
115                    delete (*ai_list_itr);
116                    if ( ai_list_itr == ai_list.begin() ) {
117                        ai_list.erase(ai_list_itr);
118                        ai_list_itr = ai_list.begin();
119                        continue;
120                    } else {
121                        ai_list.erase(ai_list_itr--);
122                    }
123                 } else {
124                    fetchUserState();
125                    if ((*ai_list_itr)->isa(FGAIBase::otThermal)) {
126                        processThermal((FGAIThermal*)*ai_list_itr); 
127                    } else { 
128                       (*ai_list_itr)->update(_dt);
129                    }
130                 }
131                 ++ai_list_itr;
132         }
133         wind_from_down_node->setDoubleValue( strength );
134
135 }
136
137
138 void*
139 FGAIManager::createAircraft( FGAIModelEntity *entity,   FGAISchedule *ref) {
140      
141         FGAIAircraft* ai_plane = new FGAIAircraft(this, ref);
142         ai_list.push_back(ai_plane);
143         ++numObjects[0];
144         ++numObjects[FGAIBase::otAircraft];
145         if (entity->m_class == "light") {
146           ai_plane->SetPerformance(&FGAIAircraft::settings[FGAIAircraft::LIGHT]);
147         } else if (entity->m_class == "ww2_fighter") {
148           ai_plane->SetPerformance(&FGAIAircraft::settings[FGAIAircraft::WW2_FIGHTER]);
149         } else if (entity->m_class ==  "jet_transport") {
150           ai_plane->SetPerformance(&FGAIAircraft::settings[FGAIAircraft::JET_TRANSPORT]);
151         } else if (entity->m_class == "jet_fighter") {
152           ai_plane->SetPerformance(&FGAIAircraft::settings[FGAIAircraft::JET_FIGHTER]);
153         } else if (entity->m_class ==  "tanker") {
154           ai_plane->SetPerformance(&FGAIAircraft::settings[FGAIAircraft::JET_TRANSPORT]);
155           ai_plane->SetTanker(true);
156         } else {
157           ai_plane->SetPerformance(&FGAIAircraft::settings[FGAIAircraft::JET_TRANSPORT]);
158         }
159         ai_plane->setAcType(entity->acType);
160         ai_plane->setCompany(entity->company);
161         ai_plane->setHeading(entity->heading);
162         ai_plane->setSpeed(entity->speed);
163         ai_plane->setPath(entity->path.c_str());
164         ai_plane->setAltitude(entity->altitude);
165         ai_plane->setLongitude(entity->longitude);
166         ai_plane->setLatitude(entity->latitude);
167         ai_plane->setBank(entity->roll);
168
169         if ( entity->fp ) {
170           ai_plane->SetFlightPlan(entity->fp);
171         }
172
173         ai_plane->init();
174         ai_plane->bind();
175         return ai_plane;
176 }
177
178 void*
179 FGAIManager::createShip( FGAIModelEntity *entity ) {
180     
181      // cout << "creating ship" << endl;    
182
183         FGAIShip* ai_ship = new FGAIShip(this);
184         ai_list.push_back(ai_ship);
185         ++numObjects[0];
186         ++numObjects[FGAIBase::otShip];
187         ai_ship->setHeading(entity->heading);
188         ai_ship->setSpeed(entity->speed);
189         ai_ship->setPath(entity->path.c_str());
190         ai_ship->setAltitude(entity->altitude);
191         ai_ship->setLongitude(entity->longitude);
192         ai_ship->setLatitude(entity->latitude);
193         ai_ship->setBank(entity->rudder);
194
195         if ( entity->fp ) {
196            ai_ship->setFlightPlan(entity->fp);
197         }
198
199         ai_ship->init();
200         ai_ship->bind();
201         return ai_ship;
202 }
203
204 void*
205 FGAIManager::createCarrier( FGAIModelEntity *entity ) {
206     
207     // cout << "creating carrier" << endl;
208
209         FGAICarrier* ai_carrier = new FGAICarrier(this);
210         ai_list.push_back(ai_carrier);
211         ++numObjects[0];
212         ++numObjects[FGAIBase::otShip];
213         ai_carrier->setHeading(entity->heading);
214         ai_carrier->setSpeed(entity->speed);
215         ai_carrier->setPath(entity->path.c_str());
216         ai_carrier->setAltitude(entity->altitude);
217         ai_carrier->setLongitude(entity->longitude);
218         ai_carrier->setLatitude(entity->latitude);
219         ai_carrier->setBank(entity->rudder);
220         ai_carrier->setSolidObjects(entity->solid_objects);
221         ai_carrier->setWireObjects(entity->wire_objects);
222         ai_carrier->setCatapultObjects(entity->catapult_objects);
223         ai_carrier->setRadius(entity->radius);
224         ai_carrier->setXoffset(entity->x_offset);
225         ai_carrier->setYoffset(entity->y_offset);
226         ai_carrier->setZoffset(entity->z_offset);
227
228         if ( entity->fp ) {
229            ai_carrier->setFlightPlan(entity->fp);
230         }
231
232         ai_carrier->init();
233         ai_carrier->bind();
234         return ai_carrier;
235 }
236
237 void*
238 FGAIManager::createBallistic( FGAIModelEntity *entity ) {
239
240         FGAIBallistic* ai_ballistic = new FGAIBallistic(this);
241         ai_list.push_back(ai_ballistic);
242         ++numObjects[0];
243         ++numObjects[FGAIBase::otBallistic];
244         ai_ballistic->setAzimuth(entity->azimuth);
245         ai_ballistic->setElevation(entity->elevation);
246         ai_ballistic->setSpeed(entity->speed);
247         ai_ballistic->setPath(entity->path.c_str());
248         ai_ballistic->setAltitude(entity->altitude);
249         ai_ballistic->setLongitude(entity->longitude);
250         ai_ballistic->setLatitude(entity->latitude);
251         ai_ballistic->setDragArea(entity->eda);
252         ai_ballistic->setLife(entity->life);
253         ai_ballistic->setBuoyancy(entity->buoyancy);
254         ai_ballistic->setWind_from_east(entity->wind_from_east);
255         ai_ballistic->setWind_from_north(entity->wind_from_north);
256         ai_ballistic->setWind(entity->wind);
257         ai_ballistic->setRoll(entity->roll);
258         ai_ballistic->setCd(entity->cd);
259         ai_ballistic->setMass(entity->mass);
260         ai_ballistic->setStabilisation(entity->aero_stabilised);
261         ai_ballistic->init();
262         ai_ballistic->bind();
263         return ai_ballistic;
264 }
265
266 void*
267 FGAIManager::createStorm( FGAIModelEntity *entity ) {
268
269         FGAIStorm* ai_storm = new FGAIStorm(this);
270         ++numObjects[0];
271         ++numObjects[FGAIBase::otStorm];
272         ai_storm->setHeading(entity->heading);
273         ai_storm->setSpeed(entity->speed);
274         ai_storm->setPath(entity->path.c_str());
275         ai_storm->setAltitude(entity->altitude);
276         ai_storm->setLongitude(entity->longitude);
277         ai_storm->setLatitude(entity->latitude);
278         ai_storm->init();
279         ai_storm->bind();
280         ai_list.push_back(ai_storm);
281         return ai_storm;
282 }
283
284 void*
285 FGAIManager::createThermal( FGAIModelEntity *entity ) {
286
287         FGAIThermal* ai_thermal = new FGAIThermal(this);
288         ++numObjects[0];
289         ++numObjects[FGAIBase::otThermal];
290         ai_thermal->setLongitude(entity->longitude);
291         ai_thermal->setLatitude(entity->latitude);
292         ai_thermal->setMaxStrength(entity->strength);
293         ai_thermal->setDiameter(entity->diameter / 6076.11549);
294         ai_thermal->init();
295         ai_thermal->bind();
296         ai_list.push_back(ai_thermal);
297         return ai_thermal;
298 }
299
300 void FGAIManager::destroyObject( void* ID ) {
301         ai_list_itr = ai_list.begin();
302         while(ai_list_itr != ai_list.end()) {
303             if ((*ai_list_itr)->getID() == ID) {
304               --numObjects[0];
305               --numObjects[(*ai_list_itr)->getType()];
306               (*ai_list_itr)->unbind();
307               delete (*ai_list_itr);
308               ai_list.erase(ai_list_itr);
309
310               break;
311             }
312             ++ai_list_itr;
313         }
314 }
315
316 // fetch the user's state every 10 sim cycles
317 void FGAIManager::fetchUserState( void ) {
318    ++dt_count;
319    if (dt_count == 10) {
320      user_latitude  = fgGetDouble("/position/latitude-deg");
321      user_longitude = fgGetDouble("/position/longitude-deg");
322      user_altitude  = fgGetDouble("/position/altitude-ft");
323      user_heading   = fgGetDouble("/orientation/heading-deg");
324      user_pitch     = fgGetDouble("/orientation/pitch-deg");
325      user_yaw       = fgGetDouble("/orientation/side-slip-deg");
326      user_speed     = fgGetDouble("/velocities/uBody-fps") * 0.592484;
327      dt_count = 0;
328    }
329 }
330
331
332 // only keep the results from the nearest thermal
333 void FGAIManager::processThermal( FGAIThermal* thermal ) {
334   thermal->update(_dt);
335   if ( thermal->_getRange() < range_nearest ) {
336      range_nearest = thermal->_getRange();
337      strength = thermal->getStrength();
338   }
339 }
340
341
342 void FGAIManager::processScenario( string &filename ) {
343   FGAIScenario* s = new FGAIScenario( filename );
344   for (int i=0;i<s->nEntries();i++) {
345     FGAIModelEntity* en = s->getNextEntry();
346
347     if (en) {
348       if ( en->m_type == "aircraft") {
349         createAircraft( en );
350
351       } else if ( en->m_type == "ship") {
352         createShip( en );
353
354       } else if ( en->m_type == "carrier") {
355         createCarrier( en );
356
357       } else if ( en->m_type == "thunderstorm") {
358         createStorm( en );
359
360       } else if ( en->m_type == "thermal") {
361         createThermal( en );
362
363       } else if ( en->m_type == "ballistic") {
364         createBallistic( en );
365       }      
366     }
367   }
368
369   delete s;
370 }
371
372 // This code keeps track of models that have already been loaded
373 // Eventually we'd prbably need to find a way to keep track of models
374 // that are unloaded again
375 ssgBranch * FGAIManager::getModel(const string& path)
376 {
377   ModelVecIterator i = loadedModels.begin();
378   while (i != loadedModels.end())
379     {
380       if (i->getPath() == path)
381         return i->getModelId();
382       i++;
383     }
384   return 0;
385 }
386
387 void FGAIManager::setModel(const string& path, ssgBranch *model)
388 {
389   loadedModels.push_back(FGModelID(path,model));
390 }
391
392
393 //end AIManager.cxx