]> git.mxchange.org Git - flightgear.git/blob - src/AIModel/AIManager.cxx
Mathias Froehlich:
[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 <Main/globals.hxx>
22
23 #include <Airports/simple.hxx>
24 #include <Traffic/TrafficMgr.hxx>
25
26 #include "AIManager.hxx"
27 #include "AIAircraft.hxx"
28 #include "AIShip.hxx"
29 #include "AIBallistic.hxx"
30 #include "AIStorm.hxx"
31 #include "AIThermal.hxx"
32 #include "AICarrier.hxx"
33 #include "AIStatic.hxx"
34 #include "AIMultiplayer.hxx"
35
36 FGAIManager::FGAIManager() {
37   for (int i=0; i < FGAIBase::MAX_OBJECTS; i++)
38      numObjects[i] = 0;
39   _dt = 0.0;
40   scenario_filename = "";
41 }
42
43 FGAIManager::~FGAIManager() {
44   ai_list_iterator ai_list_itr = ai_list.begin();
45   while(ai_list_itr != ai_list.end()) {
46       (*ai_list_itr)->unbind();
47       ++ai_list_itr;
48   }
49 }
50
51
52 void FGAIManager::init() {
53   root = fgGetNode("sim/ai", true);
54
55   enabled = root->getNode("enabled", true)->getBoolValue();
56   if (!enabled)
57       return;
58
59   wind_from_down_node = fgGetNode("/environment/wind-from-down-fps", true);
60   wind_from_east_node  = fgGetNode("/environment/wind-from-east-fps",true);
61   wind_from_north_node = fgGetNode("/environment/wind-from-north-fps",true);
62
63   user_latitude_node  = fgGetNode("/position/latitude-deg", true);
64   user_longitude_node = fgGetNode("/position/longitude-deg", true);
65   user_altitude_node  = fgGetNode("/position/altitude-ft", true);
66   user_heading_node   = fgGetNode("/orientation/heading-deg", true);
67   user_pitch_node     = fgGetNode("/orientation/pitch-deg", true);
68   user_yaw_node       = fgGetNode("/orientation/side-slip-deg", true);
69   user_speed_node     = fgGetNode("/velocities/uBody-fps", true);
70
71
72   /// Move that into the constructor
73   for(int i = 0 ; i < root->nChildren() ; i++) {
74     SGPropertyNode *aiEntry = root->getChild( i );
75     if( !strcmp( aiEntry->getName(), "scenario" ) ) {
76       scenario_filename = aiEntry->getStringValue();
77       if (!scenario_filename.empty())
78         processScenario( scenario_filename );
79     }
80   }
81 }
82
83
84 void FGAIManager::reinit() {
85    update(0.0);
86 }
87
88
89 void FGAIManager::bind() {
90    root = globals->get_props()->getNode("ai/models", true);
91    root->tie("count", SGRawValuePointer<int>(&numObjects[0]));
92 }
93
94
95 void FGAIManager::unbind() {
96     root->untie("count");
97 }
98
99
100 void FGAIManager::update(double dt) {
101
102         // initialize these for finding nearest thermals
103         range_nearest = 10000.0;
104         strength = 0.0;
105         FGTrafficManager *tmgr = (FGTrafficManager*) globals->get_subsystem("Traffic Manager");
106
107         if (!enabled)
108             return;
109
110         _dt = dt;
111
112         ai_list_iterator ai_list_itr = ai_list.begin();
113         while(ai_list_itr != ai_list.end()) {
114                 if ((*ai_list_itr)->getDie()) {      
115                   tmgr->release((*ai_list_itr)->getID());
116                    --numObjects[(*ai_list_itr)->getType()];
117                    --numObjects[0];
118                    (*ai_list_itr)->unbind();
119                    if ( ai_list_itr == ai_list.begin() ) {
120                        ai_list.erase(ai_list_itr);
121                        ai_list_itr = ai_list.begin();
122                        continue;
123                    } else {
124                        ai_list.erase(ai_list_itr--);
125                    }
126                 } else {
127                    fetchUserState();
128                    if ((*ai_list_itr)->isa(FGAIBase::otThermal)) {
129                        FGAIBase *base = *ai_list_itr;
130                        processThermal((FGAIThermal*)base); 
131                    } else { 
132                       (*ai_list_itr)->update(_dt);
133                    }
134                 }
135                 ++ai_list_itr;
136         }
137         wind_from_down_node->setDoubleValue( strength ); // for thermals
138 }
139
140 void
141 FGAIManager::attach(SGSharedPtr<FGAIBase> model)
142 {
143   model->setManager(this);
144   ai_list.push_back(model);
145   ++numObjects[0];
146   ++numObjects[model->getType()];
147   model->init();
148   model->bind();
149 }
150
151
152 void FGAIManager::destroyObject( int ID ) {
153         ai_list_iterator ai_list_itr = ai_list.begin();
154         while(ai_list_itr != ai_list.end()) {
155             if ((*ai_list_itr)->getID() == ID) {
156               --numObjects[0];
157               --numObjects[(*ai_list_itr)->getType()];
158               (*ai_list_itr)->unbind();
159               ai_list.erase(ai_list_itr);
160               break;
161             }
162             ++ai_list_itr;
163         }
164 }
165
166
167 void FGAIManager::fetchUserState( void ) {
168      user_latitude  = user_latitude_node->getDoubleValue();
169      user_longitude = user_longitude_node->getDoubleValue();
170      user_altitude  = user_altitude_node->getDoubleValue();
171      user_heading   = user_heading_node->getDoubleValue();
172      user_pitch     = user_pitch_node->getDoubleValue();
173      user_yaw       = user_yaw_node->getDoubleValue();
174      user_speed     = user_speed_node->getDoubleValue() * 0.592484;
175      wind_from_east = wind_from_east_node->getDoubleValue();
176      wind_from_north = wind_from_north_node->getDoubleValue();
177      
178      
179 }
180
181
182 // only keep the results from the nearest thermal
183 void FGAIManager::processThermal( FGAIThermal* thermal ) {
184   thermal->update(_dt);
185   if ( thermal->_getRange() < range_nearest ) {
186      range_nearest = thermal->_getRange();
187      strength = thermal->getStrength();
188   }
189 }
190
191
192 void FGAIManager::processScenario( const string &filename ) {
193
194   SGPropertyNode_ptr scenarioTop = loadScenarioFile(filename);
195   if (!scenarioTop)
196     return;
197   SGPropertyNode* scenarios = scenarioTop->getChild("scenario");
198   if (!scenarios)
199     return;
200
201   for (int i = 0; i < scenarios->nChildren(); i++) { 
202     SGPropertyNode* scEntry = scenarios->getChild(i);
203     std::string type = scEntry->getStringValue("type", "aircraft");
204
205     if (type == "aircraft") {
206       FGAIAircraft* aircraft = new FGAIAircraft;
207       aircraft->readFromScenario(scEntry);
208       attach(aircraft);
209
210     } else if (type == "ship") {
211       FGAIShip* ship = new FGAIShip;
212       ship->readFromScenario(scEntry);
213       attach(ship);
214       
215     } else if (type == "carrier") {
216       FGAICarrier* carrier = new FGAICarrier;
217       carrier->readFromScenario(scEntry);
218       attach(carrier);
219       
220     } else if (type == "thunderstorm") {
221       FGAIStorm* storm = new FGAIStorm;
222       storm->readFromScenario(scEntry);
223       attach(storm);
224       
225     } else if (type == "thermal") {
226       FGAIThermal* thermal = new FGAIThermal;
227       thermal->readFromScenario(scEntry);
228       attach(thermal);
229       
230     } else if (type == "ballistic") {
231       FGAIBallistic* ballistic = new FGAIBallistic;
232       ballistic->readFromScenario(scEntry);
233       attach(ballistic);
234       
235     } else if (type == "static") {
236       FGAIStatic* aistatic = new FGAIStatic;
237       aistatic->readFromScenario(scEntry);
238       attach(aistatic);
239       
240     }
241   }
242 }
243
244 SGPropertyNode_ptr
245 FGAIManager::loadScenarioFile(const std::string& filename)
246 {
247   SGPath path(globals->get_fg_root());
248   path.append("AI/" + filename + ".xml");
249   try {
250     SGPropertyNode_ptr root = new SGPropertyNode;
251     readProperties(path.str(), root);
252     return root;
253   } catch (const sg_exception &e) {
254     SG_LOG(SG_GENERAL, SG_ALERT, "Incorrect path specified for AI "
255            "scenario: \"" << path.str() << "\"");
256     return 0;
257   }
258 }
259
260 // This code keeps track of models that have already been loaded
261 // Eventually we'd prbably need to find a way to keep track of models
262 // that are unloaded again
263 ssgBranch * FGAIManager::getModel(const string& path) const
264 {
265   ModelVecIterator i = loadedModels.begin();
266   while (i != loadedModels.end())
267     {
268       if (i->getPath() == path)
269         return i->getModelId();
270       i++;
271     }
272   return 0;
273 }
274
275 void FGAIManager::setModel(const string& path, ssgBranch *model)
276 {
277   loadedModels.push_back(FGModelID(path,model));
278 }
279
280 bool FGAIManager::getStartPosition(const string& id, const string& pid,
281                                    Point3D& geodPos, double& heading,
282                                    sgdVec3 uvw)
283 {
284   bool found = false;
285   SGPropertyNode* root = fgGetNode("sim/ai", true);
286   if (!root->getNode("enabled", true)->getBoolValue())
287       return found;
288
289   for(int i = 0 ; (!found) && i < root->nChildren() ; i++) {
290     SGPropertyNode *aiEntry = root->getChild( i );
291     if( !strcmp( aiEntry->getName(), "scenario" ) ) {
292       string filename = aiEntry->getStringValue();
293       SGPropertyNode_ptr scenarioTop = loadScenarioFile(filename);
294       if (scenarioTop) {
295         SGPropertyNode* scenarios = scenarioTop->getChild("scenario");
296         if (scenarios) {
297           for (int i = 0; i < scenarios->nChildren(); i++) { 
298             SGPropertyNode* scEntry = scenarios->getChild(i);
299             std::string type = scEntry->getStringValue("type");
300             std::string pnumber = scEntry->getStringValue("pennant-number");
301             std::string name = scEntry->getStringValue("name");
302             if (type == "carrier" && (pnumber == id || name == id)) {
303               SGSharedPtr<FGAICarrier> carrier = new FGAICarrier;
304               carrier->readFromScenario(scEntry);
305               
306               if (carrier->getParkPosition(pid, geodPos, heading, uvw)) {
307                 found = true;
308                 break;
309               }
310             }
311           }
312         }
313       }
314     }
315   }
316   return found;
317 }
318
319 //end AIManager.cxx