~ubuntu-branches/debian/sid/flightgear/sid

« back to all changes in this revision

Viewing changes to src/AIModel/AIManager.cxx

  • Committer: Package Import Robot
  • Author(s): Markus Wanner, Markus Wanner, Rebecca Palmer
  • Date: 2014-01-21 22:31:02 UTC
  • mfrom: (1.3.1) (15.1.2 experimental)
  • Revision ID: package-import@ubuntu.com-20140121223102-cjw7g9le25acd119
Tags: 3.0.0~git20140204+c99ea4-1
[ Markus Wanner ]
* Upload to unstable.
* Adjust B-D to allow building on kfreebsd-*. Closes: #724686.
* Add a lintian-overrides on autotools; we use cmake.
* Upstream corrected the fgfs manpage. Closes: #556362.
* Drop unnecessary man page for gl-info. Closes: #698308.
* Drop README.Linux: it's outdated to the point of uselessness.
  Closes: #574173.
* Add an upper limit of libsimgear-dev versions that flightgear can be
  built with. Closes: #738436.
* Drop the libsvn-dev dependency, neither flightgear nor simgear depend
  on libsvn, anymore. Closes: #682947.
* List icons in debian/install rather than copying around from rules.
* Update menu entry for flightgear, add one for fgcom; add .xpm icons.
  Closes: #713924.
* flightgear.desktop: add German translation
* Bump Standards-Version to 3.9.5; no changes needed.

[ Rebecca Palmer ]
* New upstream release.
* Install the icons (based on code by Saikrishna Arcot).  (Not a
  complete fix for LP908153 as it only sets the menu/Dash icon, not the
  running window's icon, but better than nothing).
* Disable screensaver while running. Closes: LP#793599. Add required
  libdbus-1-dev dependency.
* Remove outdated README.Debian.
* Terrasync now works after just ticking the box. Closes: #252899.
* Always set Terrasync directory.

Show diffs side-by-side

added added

removed removed

Lines of Context:
25
25
#include <simgear/math/sg_geodesy.hxx>
26
26
#include <simgear/props/props_io.hxx>
27
27
#include <simgear/structure/exception.hxx>
 
28
#include <simgear/structure/commands.hxx>
 
29
#include <simgear/structure/SGBinding.hxx>
 
30
 
28
31
#include <boost/mem_fn.hpp>
29
32
#include <boost/foreach.hpp>
30
33
 
31
34
#include <Main/globals.hxx>
32
 
#include <Airports/simple.hxx>
 
35
#include <Airports/airport.hxx>
 
36
#include <Scripting/NasalSys.hxx>
33
37
 
34
38
#include "AIManager.hxx"
35
39
#include "AIAircraft.hxx"
45
49
#include "AIGroundVehicle.hxx"
46
50
#include "AIEscort.hxx"
47
51
 
 
52
class FGAIManager::Scenario
 
53
{
 
54
public:
 
55
    Scenario(FGAIManager* man, const std::string& nm, SGPropertyNode* scenarios) :
 
56
        _internalName(nm)
 
57
    {
 
58
        BOOST_FOREACH(SGPropertyNode* scEntry, scenarios->getChildren("entry")) {
 
59
            FGAIBasePtr ai = man->addObject(scEntry);
 
60
            if (ai) {
 
61
                _objects.push_back(ai);
 
62
            }
 
63
        } // of scenario entry iteration
 
64
        
 
65
        SGPropertyNode* nasalScripts = scenarios->getChild("nasal");
 
66
        if (!nasalScripts) {
 
67
            return;
 
68
        }
 
69
        
 
70
        _unloadScript = nasalScripts->getStringValue("unload");
 
71
        std::string loadScript = nasalScripts->getStringValue("load");
 
72
        if (!loadScript.empty()) {
 
73
            FGNasalSys* nasalSys = (FGNasalSys*) globals->get_subsystem("nasal");
 
74
            std::string moduleName = "scenario_" + _internalName;
 
75
            nasalSys->createModule(moduleName.c_str(), moduleName.c_str(),
 
76
                                   loadScript.c_str(), loadScript.size(),
 
77
                                   0);
 
78
        }
 
79
    }
 
80
    
 
81
    ~Scenario()
 
82
    {
 
83
        BOOST_FOREACH(FGAIBasePtr ai, _objects) {
 
84
            ai->setDie(true);
 
85
        }
 
86
        
 
87
        FGNasalSys* nasalSys = (FGNasalSys*) globals->get_subsystem("nasal");
 
88
        if (!nasalSys)
 
89
            return;
 
90
        
 
91
        std::string moduleName = "scenario_" + _internalName;
 
92
        if (!_unloadScript.empty()) {
 
93
            nasalSys->createModule(moduleName.c_str(), moduleName.c_str(),
 
94
                                   _unloadScript.c_str(), _unloadScript.size(),
 
95
                                   0);
 
96
        }
 
97
        
 
98
        nasalSys->deleteModule(moduleName.c_str());
 
99
    }
 
100
private:
 
101
    std::vector<FGAIBasePtr> _objects;
 
102
    std::string _internalName;
 
103
    std::string _unloadScript;
 
104
};
 
105
 
 
106
///////////////////////////////////////////////////////////////////////////////
 
107
 
48
108
FGAIManager::FGAIManager() :
49
109
    cb_ai_bare(SGPropertyChangeCallback<FGAIManager>(this,&FGAIManager::updateLOD,
50
110
               fgGetNode("/sim/rendering/static-lod/ai-bare", true))),
69
129
    wind_from_east_node  = fgGetNode("/environment/wind-from-east-fps",true);
70
130
    wind_from_north_node = fgGetNode("/environment/wind-from-north-fps",true);
71
131
 
72
 
    user_latitude_node  = fgGetNode("/position/latitude-deg", true);
73
 
    user_longitude_node = fgGetNode("/position/longitude-deg", true);
74
 
    user_altitude_node  = fgGetNode("/position/altitude-ft", true);
75
132
    user_altitude_agl_node  = fgGetNode("/position/altitude-agl-ft", true);
76
 
    user_heading_node   = fgGetNode("/orientation/heading-deg", true);
77
 
    user_pitch_node     = fgGetNode("/orientation/pitch-deg", true);
78
 
    user_yaw_node       = fgGetNode("/orientation/side-slip-deg", true);
79
 
    user_roll_node      = fgGetNode("/orientation/roll-deg", true);
80
133
    user_speed_node     = fgGetNode("/velocities/uBody-fps", true);
 
134
    
 
135
    globals->get_commands()->addCommand("load-scenario", this, &FGAIManager::loadScenarioCommand);
 
136
    globals->get_commands()->addCommand("unload-scenario", this, &FGAIManager::unloadScenarioCommand);
81
137
}
82
138
 
83
139
void
84
 
FGAIManager::postinit() {
 
140
FGAIManager::postinit()
 
141
{
85
142
    // postinit, so that it can access the Nasal subsystem
86
143
 
87
 
    if (!root->getBoolValue("scenarios-enabled", true))
88
 
        return;
89
 
 
90
144
    // scenarios enabled, AI subsystem required
91
145
    if (!enabled->getBoolValue())
92
146
        enabled->setBoolValue(true);
93
147
 
94
148
    // process all scenarios
95
 
    std::map<string, bool> scenarios;
96
 
    for (int i = 0 ; i < root->nChildren() ; i++) {
97
 
        SGPropertyNode *n = root->getChild(i);
98
 
        if (strcmp(n->getName(), "scenario"))
99
 
            continue;
100
 
 
 
149
    BOOST_FOREACH(SGPropertyNode* n, root->getChildren("scenario")) {
101
150
        const string& name = n->getStringValue();
102
151
        if (name.empty())
103
152
            continue;
104
153
 
105
 
        if (scenarios.find(name) != scenarios.end()) {
106
 
            SG_LOG(SG_AI, SG_DEBUG, "won't load scenario '" << name << "' twice");
 
154
        if (_scenarios.find(name) != _scenarios.end()) {
 
155
            SG_LOG(SG_AI, SG_WARN, "won't load scenario '" << name << "' twice");
107
156
            continue;
108
157
        }
109
158
 
110
 
        SG_LOG(SG_AI, SG_ALERT, "loading scenario '" << name << '\'');
111
 
        processScenario(name);
112
 
        scenarios[name] = true;
 
159
        SG_LOG(SG_AI, SG_INFO, "loading scenario '" << name << '\'');
 
160
        loadScenario(name);
113
161
    }
114
162
}
115
163
 
116
164
void
117
165
FGAIManager::reinit()
118
166
{
 
167
    // shutdown scenarios
 
168
    unloadAllScenarios();
 
169
    
119
170
    update(0.0);
120
171
    std::for_each(ai_list.begin(), ai_list.end(), boost::mem_fn(&FGAIBase::reinit));
 
172
    
 
173
    // (re-)load scenarios
 
174
    postinit();
 
175
}
 
176
 
 
177
void
 
178
FGAIManager::shutdown()
 
179
{
 
180
    unloadAllScenarios();
 
181
    
 
182
    BOOST_FOREACH(FGAIBase* ai, ai_list) {
 
183
        ai->unbind();
 
184
    }
 
185
    
 
186
    ai_list.clear();
 
187
    
 
188
    globals->get_commands()->removeCommand("load-scenario");
 
189
    globals->get_commands()->removeCommand("unload-scenario");
121
190
}
122
191
 
123
192
void
169
238
  
170
239
    ai_list.erase(ai_list.begin(), firstAlive);
171
240
  
172
 
    // every remaining item is alive
 
241
    // every remaining item is alive. update them in turn, but guard for
 
242
    // exceptions, so a single misbehaving AI object doesn't bring down the
 
243
    // entire subsystem.
173
244
    BOOST_FOREACH(FGAIBase* base, ai_list) {
174
 
        if (base->isa(FGAIBase::otThermal)) {
175
 
            processThermal(dt, (FGAIThermal*)base);
176
 
        } else {
177
 
            base->update(dt);
 
245
        try {
 
246
            if (base->isa(FGAIBase::otThermal)) {
 
247
                processThermal(dt, (FGAIThermal*)base);
 
248
            } else {
 
249
                base->update(dt);
 
250
            }
 
251
        } catch (sg_exception& e) {
 
252
            SG_LOG(SG_AI, SG_WARN, "caught exception updating AI model:" << base->_getName()<< ", which will be killed."
 
253
                   "\n\tError:" << e.getFormattedMessage());
 
254
            base->setDie(true);
178
255
        }
179
256
    } // of live AI objects iteration
180
257
 
222
299
}
223
300
 
224
301
int
225
 
FGAIManager::getNumAiObjects(void) const
 
302
FGAIManager::getNumAiObjects() const
226
303
{
227
304
    return ai_list.size();
228
305
}
230
307
void
231
308
FGAIManager::fetchUserState( void ) {
232
309
 
233
 
    user_latitude  = user_latitude_node->getDoubleValue();
234
 
    user_longitude = user_longitude_node->getDoubleValue();
235
 
    user_altitude  = user_altitude_node->getDoubleValue();
236
 
    user_heading   = user_heading_node->getDoubleValue();
237
 
    user_pitch     = user_pitch_node->getDoubleValue();
238
 
    user_yaw       = user_yaw_node->getDoubleValue();
 
310
    globals->get_aircraft_orientation(user_heading, user_pitch, user_roll);
239
311
    user_speed     = user_speed_node->getDoubleValue() * 0.592484;
240
 
    user_roll      = user_roll_node->getDoubleValue();
241
312
    wind_from_east = wind_from_east_node->getDoubleValue();
242
313
    wind_from_north   = wind_from_north_node->getDoubleValue();
243
314
    user_altitude_agl = user_altitude_agl_node->getDoubleValue();
256
327
 
257
328
}
258
329
 
259
 
 
 
330
bool FGAIManager::loadScenarioCommand(const SGPropertyNode* args)
 
331
{
 
332
    std::string name = args->getStringValue("name");
 
333
    if (args->hasChild("load-property")) {
 
334
        // slightly ugly, to simplify life in the dialogs, make load allow
 
335
        // loading or unloading based on a bool property.
 
336
        bool loadIt = fgGetBool(args->getStringValue("load-property"));
 
337
        if (!loadIt) {
 
338
            // user actually wants to unload, fine.
 
339
            return unloadScenario(name);
 
340
        }
 
341
    }
 
342
    
 
343
    if (_scenarios.find(name) != _scenarios.end()) {
 
344
        SG_LOG(SG_AI, SG_WARN, "scenario '" << name << "' already loaded");
 
345
        return false;
 
346
    }
 
347
    
 
348
    bool ok = loadScenario(name);
 
349
    if (ok) {
 
350
        // create /sim/ai node for consistency
 
351
        int index = 0;
 
352
        for (; root->hasChild("scenario", index); ++index) {}
 
353
        
 
354
        SGPropertyNode* scenarioNode = root->getChild("scenario", index, true);
 
355
        scenarioNode->setStringValue(name);
 
356
    }
 
357
    
 
358
    return ok;
 
359
}
 
360
 
 
361
bool FGAIManager::unloadScenarioCommand(const SGPropertyNode* args)
 
362
{
 
363
    std::string name = args->getStringValue("name");
 
364
    return unloadScenario(name);
 
365
}
 
366
 
 
367
bool FGAIManager::addObjectCommand(const SGPropertyNode* definition)
 
368
{
 
369
    addObject(definition);
 
370
    return true;
 
371
}
 
372
 
 
373
FGAIBasePtr FGAIManager::addObject(const SGPropertyNode* definition)
 
374
{
 
375
    const std::string& type = definition->getStringValue("type", "aircraft");
 
376
    
 
377
    FGAIBase* ai = NULL;
 
378
    if (type == "tanker") { // refueling scenarios
 
379
        ai = new FGAITanker; 
 
380
    } else if (type == "wingman") {
 
381
        ai = new FGAIWingman;
 
382
    } else if (type == "aircraft") {
 
383
        ai = new FGAIAircraft;
 
384
    } else if (type == "ship") {
 
385
        ai = new FGAIShip;
 
386
    } else if (type == "carrier") {
 
387
        ai = new FGAICarrier;
 
388
    } else if (type == "groundvehicle") {
 
389
        ai = new FGAIGroundVehicle;
 
390
    } else if (type == "escort") {
 
391
        ai = new FGAIEscort;
 
392
    } else if (type == "thunderstorm") {
 
393
        ai = new FGAIStorm;
 
394
    } else if (type == "thermal") {
 
395
        ai = new FGAIThermal;
 
396
    } else if (type == "ballistic") {
 
397
        ai = new FGAIBallistic;
 
398
    } else if (type == "static") {
 
399
        ai = new FGAIStatic;
 
400
    }
 
401
 
 
402
    ai->readFromScenario(const_cast<SGPropertyNode*>(definition));
 
403
    attach(ai);
 
404
    return ai;
 
405
}
 
406
 
 
407
bool FGAIManager::removeObject(const SGPropertyNode* args)
 
408
{
 
409
    int id = args->getIntValue("id");
 
410
    BOOST_FOREACH(FGAIBase* ai, get_ai_list()) {
 
411
        if (ai->getID() == id) {
 
412
            ai->setDie(true);
 
413
            break;
 
414
        }
 
415
    }
 
416
    
 
417
    return false;
 
418
}
 
419
 
 
420
FGAIBasePtr FGAIManager::getObjectFromProperty(const SGPropertyNode* aProp) const
 
421
{
 
422
    BOOST_FOREACH(FGAIBase* ai, get_ai_list()) {
 
423
        if (ai->_getProps() == aProp) {
 
424
            return ai;
 
425
        }
 
426
    } // of AI objects iteration
 
427
    
 
428
    return NULL;
 
429
}
 
430
 
 
431
bool
 
432
FGAIManager::loadScenario( const string &filename )
 
433
{
 
434
    SGPropertyNode_ptr file = loadScenarioFile(filename);
 
435
    if (!file) {
 
436
        return false;
 
437
    }
 
438
    
 
439
    SGPropertyNode_ptr scNode = file->getChild("scenario");
 
440
    if (!scNode) {
 
441
        return false;
 
442
    }
 
443
    
 
444
    _scenarios[filename] = new Scenario(this, filename, scNode);
 
445
    return true;
 
446
}
 
447
 
 
448
 
 
449
bool
 
450
FGAIManager::unloadScenario( const string &filename)
 
451
{
 
452
    ScenarioDict::iterator it = _scenarios.find(filename);
 
453
    if (it == _scenarios.end()) {
 
454
        SG_LOG(SG_AI, SG_WARN, "unload scenario: not found:" << filename);
 
455
        return false;
 
456
    }
 
457
    
 
458
// remove /sim/ai node
 
459
    unsigned int index = 0;
 
460
    for (SGPropertyNode* n = NULL; (n = root->getChild("scenario", index)) != NULL; ++index) {
 
461
        if (n->getStringValue() == filename) {
 
462
            root->removeChild("scenario", index);
 
463
            break;
 
464
        }
 
465
    }
 
466
    
 
467
    delete it->second;
 
468
    _scenarios.erase(it);
 
469
    return true;
 
470
}
260
471
 
261
472
void
262
 
FGAIManager::processScenario( const string &filename ) {
263
 
 
264
 
    SGPropertyNode_ptr scenarioTop = loadScenarioFile(filename);
265
 
 
266
 
    if (!scenarioTop)
267
 
        return;
268
 
 
269
 
    SGPropertyNode* scenarios = scenarioTop->getChild("scenario");
270
 
 
271
 
    if (!scenarios)
272
 
        return;
273
 
 
274
 
    for (int i = 0; i < scenarios->nChildren(); i++) {
275
 
        SGPropertyNode* scEntry = scenarios->getChild(i);
276
 
 
277
 
        if (strcmp(scEntry->getName(), "entry"))
278
 
            continue;
279
 
        const std::string& type = scEntry->getStringValue("type", "aircraft");
280
 
 
281
 
        if (type == "tanker") { // refueling scenarios
282
 
            FGAITanker* tanker = new FGAITanker;
283
 
            tanker->readFromScenario(scEntry);
284
 
            attach(tanker);
285
 
 
286
 
        } else if (type == "wingman") {
287
 
            FGAIWingman* wingman = new FGAIWingman;
288
 
            wingman->readFromScenario(scEntry);
289
 
            attach(wingman);
290
 
 
291
 
        } else if (type == "aircraft") {
292
 
            FGAIAircraft* aircraft = new FGAIAircraft;
293
 
            aircraft->readFromScenario(scEntry);
294
 
            attach(aircraft);
295
 
 
296
 
        } else if (type == "ship") {
297
 
            FGAIShip* ship = new FGAIShip;
298
 
            ship->readFromScenario(scEntry);
299
 
            attach(ship);
300
 
 
301
 
        } else if (type == "carrier") {
302
 
            FGAICarrier* carrier = new FGAICarrier;
303
 
            carrier->readFromScenario(scEntry);
304
 
            attach(carrier);
305
 
 
306
 
        } else if (type == "groundvehicle") {
307
 
            FGAIGroundVehicle* groundvehicle = new FGAIGroundVehicle;
308
 
            groundvehicle->readFromScenario(scEntry);
309
 
            attach(groundvehicle);
310
 
 
311
 
        } else if (type == "escort") {
312
 
            FGAIEscort* escort = new FGAIEscort;
313
 
            escort->readFromScenario(scEntry);
314
 
            attach(escort);
315
 
 
316
 
        } else if (type == "thunderstorm") {
317
 
            FGAIStorm* storm = new FGAIStorm;
318
 
            storm->readFromScenario(scEntry);
319
 
            attach(storm);
320
 
 
321
 
        } else if (type == "thermal") {
322
 
            FGAIThermal* thermal = new FGAIThermal;
323
 
            thermal->readFromScenario(scEntry);
324
 
            attach(thermal);
325
 
 
326
 
        } else if (type == "ballistic") {
327
 
            FGAIBallistic* ballistic = new FGAIBallistic;
328
 
            ballistic->readFromScenario(scEntry);
329
 
            attach(ballistic);
330
 
 
331
 
        } else if (type == "static") {
332
 
            FGAIStatic* aistatic = new FGAIStatic;
333
 
            aistatic->readFromScenario(scEntry);
334
 
            attach(aistatic);
335
 
        }
336
 
 
337
 
    }
338
 
 
 
473
FGAIManager::unloadAllScenarios()
 
474
{
 
475
    ScenarioDict::iterator it = _scenarios.begin();
 
476
    for (; it != _scenarios.end(); ++it) {
 
477
        delete it->second;
 
478
    } // of scenarios iteration
 
479
    
 
480
    
 
481
    // remove /sim/ai node
 
482
    root->removeChildren("scenario");
 
483
    _scenarios.clear();
339
484
}
340
485
 
 
486
 
341
487
SGPropertyNode_ptr
342
488
FGAIManager::loadScenarioFile(const std::string& filename)
343
489
{
423
569
 
424
570
        int id         = (*ai_list_itr)->getID();
425
571
 
426
 
        double range = calcRange(cartPos, (*ai_list_itr));
 
572
        double range = calcRangeFt(cartPos, (*ai_list_itr));
427
573
 
428
574
        //SG_LOG(SG_AI, SG_DEBUG, "AIManager:  AI list size "
429
575
        //    << ai_list.size()
451
597
}
452
598
 
453
599
double
454
 
FGAIManager::calcRange(const SGVec3d& aCartPos, FGAIBase* aObject) const
 
600
FGAIManager::calcRangeFt(const SGVec3d& aCartPos, FGAIBase* aObject) const
455
601
{
456
602
    double distM = dist(aCartPos, aObject->getCartPos());
457
603
    return distM * SG_METER_TO_FEET;