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