]> git.mxchange.org Git - flightgear.git/blob - src/AIModel/AIManager.cxx
6fc225e37997db58bf3fc43c56d9d2ecf058b97b
[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_iterator 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_iterator 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         ai_ship->setName(entity->name);
195
196         if ( entity->fp ) {
197            ai_ship->setFlightPlan(entity->fp);
198         }
199
200         ai_ship->init();
201         ai_ship->bind();
202         return ai_ship;
203 }
204
205 void*
206 FGAIManager::createCarrier( FGAIModelEntity *entity ) {
207     
208     // cout << "creating carrier" << endl;
209
210         FGAICarrier* ai_carrier = new FGAICarrier(this);
211         ai_list.push_back(ai_carrier);
212         ++numObjects[0];
213         ++numObjects[FGAIBase::otCarrier];
214         ai_carrier->setHeading(entity->heading);
215         ai_carrier->setSpeed(entity->speed);
216         ai_carrier->setPath(entity->path.c_str());
217         ai_carrier->setAltitude(entity->altitude);
218         ai_carrier->setLongitude(entity->longitude);
219         ai_carrier->setLatitude(entity->latitude);
220         ai_carrier->setBank(entity->rudder);
221         ai_carrier->setSolidObjects(entity->solid_objects);
222         ai_carrier->setWireObjects(entity->wire_objects);
223         ai_carrier->setCatapultObjects(entity->catapult_objects);
224         ai_carrier->setParkingPositions(entity->ppositions);
225         ai_carrier->setRadius(entity->radius);
226         ai_carrier->setSign(entity->pennant_number);
227         ai_carrier->setName(entity->name);
228         ai_carrier->setFlolsOffset(entity->flols_offset);
229
230         if ( entity->fp ) {
231            ai_carrier->setFlightPlan(entity->fp);
232         }
233
234         ai_carrier->init();
235         ai_carrier->bind();
236         return ai_carrier;
237 }
238
239 void*
240 FGAIManager::createBallistic( FGAIModelEntity *entity ) {
241
242         FGAIBallistic* ai_ballistic = new FGAIBallistic(this);
243         ai_list.push_back(ai_ballistic);
244         ++numObjects[0];
245         ++numObjects[FGAIBase::otBallistic];
246         ai_ballistic->setAzimuth(entity->azimuth);
247         ai_ballistic->setElevation(entity->elevation);
248         ai_ballistic->setSpeed(entity->speed);
249         ai_ballistic->setPath(entity->path.c_str());
250         ai_ballistic->setAltitude(entity->altitude);
251         ai_ballistic->setLongitude(entity->longitude);
252         ai_ballistic->setLatitude(entity->latitude);
253         ai_ballistic->setDragArea(entity->eda);
254         ai_ballistic->setLife(entity->life);
255         ai_ballistic->setBuoyancy(entity->buoyancy);
256         ai_ballistic->setWind_from_east(entity->wind_from_east);
257         ai_ballistic->setWind_from_north(entity->wind_from_north);
258         ai_ballistic->setWind(entity->wind);
259         ai_ballistic->setRoll(entity->roll);
260         ai_ballistic->setCd(entity->cd);
261         ai_ballistic->setMass(entity->mass);
262         ai_ballistic->setStabilisation(entity->aero_stabilised);
263         ai_ballistic->init();
264         ai_ballistic->bind();
265         return ai_ballistic;
266 }
267
268 void*
269 FGAIManager::createStorm( FGAIModelEntity *entity ) {
270
271         FGAIStorm* ai_storm = new FGAIStorm(this);
272         ++numObjects[0];
273         ++numObjects[FGAIBase::otStorm];
274         ai_storm->setHeading(entity->heading);
275         ai_storm->setSpeed(entity->speed);
276         ai_storm->setPath(entity->path.c_str());
277         ai_storm->setAltitude(entity->altitude);
278         ai_storm->setLongitude(entity->longitude);
279         ai_storm->setLatitude(entity->latitude);
280         ai_storm->init();
281         ai_storm->bind();
282         ai_list.push_back(ai_storm);
283         return ai_storm;
284 }
285
286 void*
287 FGAIManager::createThermal( FGAIModelEntity *entity ) {
288
289         FGAIThermal* ai_thermal = new FGAIThermal(this);
290         ++numObjects[0];
291         ++numObjects[FGAIBase::otThermal];
292         ai_thermal->setLongitude(entity->longitude);
293         ai_thermal->setLatitude(entity->latitude);
294         ai_thermal->setMaxStrength(entity->strength);
295         ai_thermal->setDiameter(entity->diameter / 6076.11549);
296         ai_thermal->init();
297         ai_thermal->bind();
298         ai_list.push_back(ai_thermal);
299         return ai_thermal;
300 }
301
302 void FGAIManager::destroyObject( void* ID ) {
303         ai_list_iterator ai_list_itr = ai_list.begin();
304         while(ai_list_itr != ai_list.end()) {
305             if ((*ai_list_itr)->getID() == ID) {
306               --numObjects[0];
307               --numObjects[(*ai_list_itr)->getType()];
308               (*ai_list_itr)->unbind();
309               delete (*ai_list_itr);
310               ai_list.erase(ai_list_itr);
311
312               break;
313             }
314             ++ai_list_itr;
315         }
316 }
317
318 // fetch the user's state every 10 sim cycles
319 void FGAIManager::fetchUserState( void ) {
320    ++dt_count;
321    if (dt_count == 10) {
322      user_latitude  = fgGetDouble("/position/latitude-deg");
323      user_longitude = fgGetDouble("/position/longitude-deg");
324      user_altitude  = fgGetDouble("/position/altitude-ft");
325      user_heading   = fgGetDouble("/orientation/heading-deg");
326      user_pitch     = fgGetDouble("/orientation/pitch-deg");
327      user_yaw       = fgGetDouble("/orientation/side-slip-deg");
328      user_speed     = fgGetDouble("/velocities/uBody-fps") * 0.592484;
329      dt_count = 0;
330    }
331 }
332
333
334 // only keep the results from the nearest thermal
335 void FGAIManager::processThermal( FGAIThermal* thermal ) {
336   thermal->update(_dt);
337   if ( thermal->_getRange() < range_nearest ) {
338      range_nearest = thermal->_getRange();
339      strength = thermal->getStrength();
340   }
341 }
342
343
344 void FGAIManager::processScenario( string &filename ) {
345   FGAIScenario* s = new FGAIScenario( filename );
346   for (int i=0;i<s->nEntries();i++) {
347     FGAIModelEntity* en = s->getNextEntry();
348
349     if (en) {
350       if ( en->m_type == "aircraft") {
351         createAircraft( en );
352
353       } else if ( en->m_type == "ship") {
354         createShip( en );
355
356       } else if ( en->m_type == "carrier") {
357         createCarrier( en );
358
359       } else if ( en->m_type == "thunderstorm") {
360         createStorm( en );
361
362       } else if ( en->m_type == "thermal") {
363         createThermal( en );
364
365       } else if ( en->m_type == "ballistic") {
366         createBallistic( en );
367       }      
368     }
369   }
370
371   delete s;
372 }
373
374 // This code keeps track of models that have already been loaded
375 // Eventually we'd prbably need to find a way to keep track of models
376 // that are unloaded again
377 ssgBranch * FGAIManager::getModel(const string& path)
378 {
379   ModelVecIterator i = loadedModels.begin();
380   while (i != loadedModels.end())
381     {
382       if (i->getPath() == path)
383         return i->getModelId();
384       i++;
385     }
386   return 0;
387 }
388
389 void FGAIManager::setModel(const string& path, ssgBranch *model)
390 {
391   loadedModels.push_back(FGModelID(path,model));
392 }
393
394
395 //end AIManager.cxx