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