]> git.mxchange.org Git - flightgear.git/blob - src/AIModel/AIManager.cxx
Boris Koenig:
[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 <list>
26
27 #include "AIManager.hxx"
28 #include "AIAircraft.hxx"
29 #include "AIShip.hxx"
30 #include "AIBallistic.hxx"
31 #include "AIStorm.hxx"
32 #include "AIThermal.hxx"
33
34 SG_USING_STD(list);
35
36
37 FGAIManager::FGAIManager() {
38   initDone = false;
39   for (int i=0; i < FGAIBase::MAX_OBJECTS; i++)
40      numObjects[i] = 0;
41   _dt = 0.0;
42   dt_count = 9;
43   scenario_filename = "";
44   ai_list.clear();
45 }
46
47 FGAIManager::~FGAIManager() {
48   ai_list_itr = ai_list.begin();
49   while(ai_list_itr != ai_list.end()) {
50       (*ai_list_itr)->unbind();
51       delete (*ai_list_itr);
52       ++ai_list_itr;
53     }
54   ai_list.clear();
55 }
56
57
58 void FGAIManager::init() {
59   root = fgGetNode("sim/ai", true);
60
61   enabled = root->getNode("enabled", true)->getBoolValue();
62   if (!enabled)
63       return;
64
65   wind_from_down_node = fgGetNode("/environment/wind-from-down-fps", true);
66  
67   scenario_filename = root->getNode("scenario", true)->getStringValue();
68   if (scenario_filename != "") processScenario( scenario_filename );
69
70   initDone = true;
71 }
72
73
74 void FGAIManager::bind() {
75    root = globals->get_props()->getNode("ai/models", true);
76    root->tie("count", SGRawValuePointer<int>(&numObjects[0]));
77 }
78
79
80 void FGAIManager::unbind() {
81     root->untie("count");
82 }
83
84
85 void FGAIManager::update(double dt) {
86
87         // initialize these for finding nearest thermals
88         range_nearest = 10000.0;
89         strength = 0.0;
90
91         if (!enabled)
92             return;
93
94         _dt = dt;
95
96         ai_list_itr = ai_list.begin();
97         while(ai_list_itr != ai_list.end()) {
98                 if ((*ai_list_itr)->getDie()) {      
99                    --numObjects[(*ai_list_itr)->getType()];
100                    --numObjects[0];
101                    (*ai_list_itr)->unbind();
102                    delete (*ai_list_itr);
103                    if ( ai_list_itr == ai_list.begin() ) {
104                        ai_list.erase(ai_list_itr);
105                        ai_list_itr = ai_list.begin();
106                        continue;
107                    } else {
108                        ai_list.erase(ai_list_itr--);
109                    }
110                 } else {
111                    fetchUserState();
112                    if ((*ai_list_itr)->isa(FGAIBase::otThermal)) {
113                        processThermal((FGAIThermal*)*ai_list_itr); 
114                    } else { 
115                       (*ai_list_itr)->update(_dt);
116                    }
117                 }
118                 ++ai_list_itr;
119         }
120         wind_from_down_node->setDoubleValue( strength );
121
122 }
123
124
125 void*
126 FGAIManager::createAircraft( FGAIModelEntity *entity ) {
127      
128         FGAIAircraft* ai_plane = new FGAIAircraft(this);
129         ai_list.push_back(ai_plane);
130         ++numObjects[0];
131         ++numObjects[FGAIBase::otAircraft];
132         if (entity->m_class == "light") {
133           ai_plane->SetPerformance(&FGAIAircraft::settings[FGAIAircraft::LIGHT]);
134         } else if (entity->m_class == "ww2_fighter") {
135           ai_plane->SetPerformance(&FGAIAircraft::settings[FGAIAircraft::WW2_FIGHTER]);
136         } else if (entity->m_class ==  "jet_transport") {
137           ai_plane->SetPerformance(&FGAIAircraft::settings[FGAIAircraft::JET_TRANSPORT]);
138         } else if (entity->m_class == "jet_fighter") {
139           ai_plane->SetPerformance(&FGAIAircraft::settings[FGAIAircraft::JET_FIGHTER]);
140         } else if (entity->m_class ==  "tanker") {
141           ai_plane->SetPerformance(&FGAIAircraft::settings[FGAIAircraft::JET_TRANSPORT]);
142           ai_plane->SetTanker(true);
143         } else {
144           ai_plane->SetPerformance(&FGAIAircraft::settings[FGAIAircraft::JET_TRANSPORT]);
145         }
146         ai_plane->setHeading(entity->heading);
147         ai_plane->setSpeed(entity->speed);
148         ai_plane->setPath(entity->path.c_str());
149         ai_plane->setAltitude(entity->altitude);
150         ai_plane->setLongitude(entity->longitude);
151         ai_plane->setLatitude(entity->latitude);
152         ai_plane->setBank(entity->roll);
153
154         if ( entity->fp ) {
155           ai_plane->SetFlightPlan(entity->fp);
156         }
157
158         ai_plane->init();
159         ai_plane->bind();
160         return ai_plane;
161 }
162
163 void*
164 FGAIManager::createShip( FGAIModelEntity *entity ) {
165
166         FGAIShip* ai_ship = new FGAIShip(this);
167         ai_list.push_back(ai_ship);
168         ++numObjects[0];
169         ++numObjects[FGAIBase::otShip];
170         ai_ship->setHeading(entity->heading);
171         ai_ship->setSpeed(entity->speed);
172         ai_ship->setPath(entity->path.c_str());
173         ai_ship->setAltitude(entity->altitude);
174         ai_ship->setLongitude(entity->longitude);
175         ai_ship->setLatitude(entity->latitude);
176         ai_ship->setBank(entity->rudder);
177
178         if ( entity->fp ) {
179            ai_ship->setFlightPlan(entity->fp);
180         }
181
182         ai_ship->init();
183         ai_ship->bind();
184         return ai_ship;
185 }
186
187 void*
188 FGAIManager::createBallistic( FGAIModelEntity *entity ) {
189
190         FGAIBallistic* ai_ballistic = new FGAIBallistic(this);
191         ai_list.push_back(ai_ballistic);
192         ++numObjects[0];
193         ++numObjects[FGAIBase::otBallistic];
194         ai_ballistic->setAzimuth(entity->azimuth);
195         ai_ballistic->setElevation(entity->elevation);
196         ai_ballistic->setSpeed(entity->speed);
197         ai_ballistic->setPath(entity->path.c_str());
198         ai_ballistic->setAltitude(entity->altitude);
199         ai_ballistic->setLongitude(entity->longitude);
200         ai_ballistic->setLatitude(entity->latitude);
201         ai_ballistic->setDragArea(entity->eda);
202         ai_ballistic->setLife(entity->life);
203         ai_ballistic->setBuoyancy(entity->buoyancy);
204         ai_ballistic->setWind_from_east(entity->wind_from_east);
205         ai_ballistic->setWind_from_north(entity->wind_from_north);
206         ai_ballistic->setWind(entity->wind);
207         ai_ballistic->setRoll(entity->roll);
208         ai_ballistic->setCd(entity->cd);
209         ai_ballistic->setMass(entity->mass);
210         ai_ballistic->init();
211         ai_ballistic->bind();
212         return ai_ballistic;
213 }
214
215 void*
216 FGAIManager::createStorm( FGAIModelEntity *entity ) {
217
218         FGAIStorm* ai_storm = new FGAIStorm(this);
219         ++numObjects[0];
220         ++numObjects[FGAIBase::otStorm];
221         ai_storm->setHeading(entity->heading);
222         ai_storm->setSpeed(entity->speed);
223         ai_storm->setPath(entity->path.c_str());
224         ai_storm->setAltitude(entity->altitude);
225         ai_storm->setLongitude(entity->longitude);
226         ai_storm->setLatitude(entity->latitude);
227         ai_storm->init();
228         ai_storm->bind();
229         ai_list.push_back(ai_storm);
230         return ai_storm;
231 }
232
233 void*
234 FGAIManager::createThermal( FGAIModelEntity *entity ) {
235
236         FGAIThermal* ai_thermal = new FGAIThermal(this);
237         ++numObjects[0];
238         ++numObjects[FGAIBase::otThermal];
239         ai_thermal->setLongitude(entity->longitude);
240         ai_thermal->setLatitude(entity->latitude);
241         ai_thermal->setMaxStrength(entity->strength);
242         ai_thermal->setDiameter(entity->diameter / 6076.11549);
243         ai_thermal->init();
244         ai_thermal->bind();
245         ai_list.push_back(ai_thermal);
246         return ai_thermal;
247 }
248
249 void FGAIManager::destroyObject( void* ID ) {
250         ai_list_itr = ai_list.begin();
251         while(ai_list_itr != ai_list.end()) {
252             if ((*ai_list_itr)->getID() == ID) {
253               --numObjects[0];
254               --numObjects[(*ai_list_itr)->getType()];
255               (*ai_list_itr)->unbind();
256               delete (*ai_list_itr);
257               ai_list.erase(ai_list_itr);
258
259               break;
260             }
261             ++ai_list_itr;
262         }
263 }
264
265 // fetch the user's state every 10 sim cycles
266 void FGAIManager::fetchUserState( void ) {
267    ++dt_count;
268    if (dt_count == 10) {
269      user_latitude  = fgGetDouble("/position/latitude-deg");
270      user_longitude = fgGetDouble("/position/longitude-deg");
271      user_altitude  = fgGetDouble("/position/altitude-ft");
272      user_heading   = fgGetDouble("/orientation/heading-deg");
273      user_pitch     = fgGetDouble("/orientation/pitch-deg");
274      user_yaw       = fgGetDouble("/orientation/side-slip-deg");
275      user_speed     = fgGetDouble("/velocities/uBody-fps") * 0.592484;
276      dt_count = 0;
277    }
278 }
279
280
281 // only keep the results from the nearest thermal
282 void FGAIManager::processThermal( FGAIThermal* thermal ) {
283   thermal->update(_dt);
284   if ( thermal->_getRange() < range_nearest ) {
285      range_nearest = thermal->_getRange();
286      strength = thermal->getStrength();
287   }
288 }
289
290
291 void FGAIManager::processScenario( string &filename ) {
292   FGAIScenario* s = new FGAIScenario( filename );
293   for (int i=0;i<s->nEntries();i++) {
294     FGAIModelEntity* en = s->getNextEntry();
295
296     if (en) {
297       if ( en->m_type == "aircraft") {
298         createAircraft( en );
299
300       } else if ( en->m_type == "ship") {
301         createShip( en );
302
303       } else if ( en->m_type == "thunderstorm") {
304         createStorm( en );
305
306       } else if ( en->m_type == "thermal") {
307         createThermal( en );
308
309       } else if ( en->m_type == "ballistic") {
310         createBallistic( en );
311       }      
312     }
313   }
314
315   delete s;
316 }
317
318 //end AIManager.cxx