#include <simgear/math/sg_geodesy.hxx>
#include <simgear/props/props_io.hxx>
#include <simgear/structure/exception.hxx>
+#include <simgear/structure/commands.hxx>
+
#include <boost/mem_fn.hpp>
#include <boost/foreach.hpp>
#include "AIGroundVehicle.hxx"
#include "AIEscort.hxx"
+class FGAIManager::Scenario
+{
+public:
+ Scenario(FGAIManager* man, SGPropertyNode* scenarios) :
+ _manager(man)
+ {
+ BOOST_FOREACH(SGPropertyNode* scEntry, scenarios->getChildren("entry")) {
+ FGAIBasePtr ai = man->addObject(scEntry);
+ if (ai) {
+ _objects.push_back(ai);
+ }
+ } // of scenario entry iteration
+ }
+
+ ~Scenario()
+ {
+ BOOST_FOREACH(FGAIBasePtr ai, _objects) {
+ ai->setDie(true);
+ }
+ }
+private:
+ FGAIManager* _manager;
+ std::vector<FGAIBasePtr> _objects;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
FGAIManager::FGAIManager() :
cb_ai_bare(SGPropertyChangeCallback<FGAIManager>(this,&FGAIManager::updateLOD,
fgGetNode("/sim/rendering/static-lod/ai-bare", true))),
user_altitude_agl_node = fgGetNode("/position/altitude-agl-ft", true);
user_yaw_node = fgGetNode("/orientation/side-slip-deg", true);
user_speed_node = fgGetNode("/velocities/uBody-fps", true);
+
+ globals->get_commands()->addCommand("load-scenario", this, &FGAIManager::loadScenarioCommand);
+ globals->get_commands()->addCommand("unload-scenario", this, &FGAIManager::unloadScenarioCommand);
}
void
enabled->setBoolValue(true);
// process all scenarios
- std::set<std::string> loadedScenarios;
BOOST_FOREACH(SGPropertyNode* n, root->getChildren("scenario")) {
const string& name = n->getStringValue();
if (name.empty())
continue;
- if (loadedScenarios.find(name) != loadedScenarios.end()) {
+ if (_scenarios.find(name) != _scenarios.end()) {
SG_LOG(SG_AI, SG_WARN, "won't load scenario '" << name << "' twice");
continue;
}
SG_LOG(SG_AI, SG_INFO, "loading scenario '" << name << '\'');
loadScenario(name);
- loadedScenarios.insert(name);
}
}
}
+bool FGAIManager::loadScenarioCommand(const SGPropertyNode* args)
+{
+ std::string name = args->getStringValue("name");
+ return loadScenario(name);
+}
+bool FGAIManager::unloadScenarioCommand(const SGPropertyNode* args)
+{
+ std::string name = args->getStringValue("name");
+ unloadScenario(name);
+ return true;
+}
-void
-FGAIManager::loadScenario( const string &filename ) {
+bool FGAIManager::addObjectCommand(const SGPropertyNode* definition)
+{
+ addObject(definition);
+ return true;
+}
- SGPropertyNode_ptr scenarioTop = loadScenarioFile(filename);
+FGAIBasePtr FGAIManager::addObject(const SGPropertyNode* definition)
+{
+ const std::string& type = definition->getStringValue("type", "aircraft");
+
+ FGAIBase* ai = NULL;
+ if (type == "tanker") { // refueling scenarios
+ ai = new FGAITanker;
+ } else if (type == "wingman") {
+ ai = new FGAIWingman;
+ } else if (type == "aircraft") {
+ ai = new FGAIAircraft;
+ } else if (type == "ship") {
+ ai = new FGAIShip;
+ } else if (type == "carrier") {
+ ai = new FGAICarrier;
+ } else if (type == "groundvehicle") {
+ ai = new FGAIGroundVehicle;
+ } else if (type == "escort") {
+ ai = new FGAIEscort;
+ } else if (type == "thunderstorm") {
+ ai = new FGAIStorm;
+ } else if (type == "thermal") {
+ ai = new FGAIThermal;
+ } else if (type == "ballistic") {
+ ai = new FGAIBallistic;
+ } else if (type == "static") {
+ ai = new FGAIStatic;
+ }
- if (!scenarioTop)
- return;
+ ai->readFromScenario(const_cast<SGPropertyNode*>(definition));
+ attach(ai);
+ return ai;
+}
- SGPropertyNode* scenarios = scenarioTop->getChild("scenario");
+bool FGAIManager::removeObject(const SGPropertyNode* args)
+{
+ int id = args->getIntValue("id");
+ BOOST_FOREACH(FGAIBase* ai, get_ai_list()) {
+ if (ai->getID() == id) {
+ ai->setDie(true);
+ break;
+ }
+ }
+
+ return false;
+}
- if (!scenarios)
- return;
+bool
+FGAIManager::loadScenario( const string &filename )
+{
+ SGPropertyNode_ptr file = loadScenarioFile(filename);
+ if (!file) {
+ return false;
+ }
+
+ SGPropertyNode_ptr scNode = file->getChild("scenario");
+ if (!scNode) {
+ return false;
+ }
+
+ _scenarios[filename] = new Scenario(this, scNode);
+ return true;
+}
- BOOST_FOREACH(SGPropertyNode* scEntry, scenarios->getChildren("entry")) {
- const std::string& type = scEntry->getStringValue("type", "aircraft");
-
- if (type == "tanker") { // refueling scenarios
- FGAITanker* tanker = new FGAITanker;
- tanker->readFromScenario(scEntry);
- attach(tanker);
-
- } else if (type == "wingman") {
- FGAIWingman* wingman = new FGAIWingman;
- wingman->readFromScenario(scEntry);
- attach(wingman);
-
- } else if (type == "aircraft") {
- FGAIAircraft* aircraft = new FGAIAircraft;
- aircraft->readFromScenario(scEntry);
- attach(aircraft);
-
- } else if (type == "ship") {
- FGAIShip* ship = new FGAIShip;
- ship->readFromScenario(scEntry);
- attach(ship);
-
- } else if (type == "carrier") {
- FGAICarrier* carrier = new FGAICarrier;
- carrier->readFromScenario(scEntry);
- attach(carrier);
-
- } else if (type == "groundvehicle") {
- FGAIGroundVehicle* groundvehicle = new FGAIGroundVehicle;
- groundvehicle->readFromScenario(scEntry);
- attach(groundvehicle);
-
- } else if (type == "escort") {
- FGAIEscort* escort = new FGAIEscort;
- escort->readFromScenario(scEntry);
- attach(escort);
-
- } else if (type == "thunderstorm") {
- FGAIStorm* storm = new FGAIStorm;
- storm->readFromScenario(scEntry);
- attach(storm);
-
- } else if (type == "thermal") {
- FGAIThermal* thermal = new FGAIThermal;
- thermal->readFromScenario(scEntry);
- attach(thermal);
-
- } else if (type == "ballistic") {
- FGAIBallistic* ballistic = new FGAIBallistic;
- ballistic->readFromScenario(scEntry);
- attach(ballistic);
-
- } else if (type == "static") {
- FGAIStatic* aistatic = new FGAIStatic;
- aistatic->readFromScenario(scEntry);
- attach(aistatic);
- }
- } // of scenario entry iteration
+void
+FGAIManager::unloadScenario( const string &filename)
+{
+ ScenarioDict::iterator it = _scenarios.find(filename);
+ if (it == _scenarios.end()) {
+ SG_LOG(SG_AI, SG_WARN, "unload scenario: not found:" << filename);
+ return;
+ }
+
+ delete it->second;
+ _scenarios.erase(it);
}
SGPropertyNode_ptr
#define _FG_AIMANAGER_HXX
#include <list>
+#include <map>
#include <simgear/structure/subsystem_mgr.hxx>
#include <simgear/structure/SGSharedPtr.hxx>
#include <Traffic/SchedFlight.hxx>
#include <Traffic/Schedule.hxx>
-using std::list;
-
class FGAIThermal;
+typedef SGSharedPtr<FGAIBase> FGAIBasePtr;
+
class FGAIManager : public SGSubsystem
{
public:
// A list of pointers to AI objects
- typedef list <SGSharedPtr<FGAIBase> > ai_list_type;
+ typedef std::list <FGAIBasePtr> ai_list_type;
typedef ai_list_type::iterator ai_list_iterator;
typedef ai_list_type::const_iterator ai_list_const_iterator;
- ai_list_type ai_list;
-
- inline const ai_list_type& get_ai_list() const {
- SG_LOG(SG_AI, SG_DEBUG, "AI Manager: AI model return list size " << ai_list.size());
+ const ai_list_type& get_ai_list() const {
return ai_list;
}
const FGAIBase *calcCollision(double alt, double lat, double lon, double fuse_range);
- // inline double get_user_latitude() const { return user_latitude; }
- // inline double get_user_longitude() const { return user_longitude; }
- // inline double get_user_altitude() const { return user_altitude; }
inline double get_user_heading() const { return user_heading; }
inline double get_user_pitch() const { return user_pitch; }
inline double get_user_yaw() const { return user_yaw; }
int getNumAiObjects(void) const;
- void loadScenario( const string &filename );
+ bool loadScenario( const string &filename );
static SGPropertyNode_ptr loadScenarioFile(const std::string& filename);
static bool getStartPosition(const string& id, const string& pid,
SGGeod& geodPos, double& hdng, SGVec3d& uvw);
+ FGAIBasePtr addObject(const SGPropertyNode* definition);
+
private:
void removeDeadItem(FGAIBase* base);
double calcRange(const SGVec3d& aCartPos, FGAIBase* aObject) const;
+ bool loadScenarioCommand(const SGPropertyNode* args);
+ bool unloadScenarioCommand(const SGPropertyNode* args);
+ bool addObjectCommand(const SGPropertyNode* definition);
+
+ bool removeObject(const SGPropertyNode* args);
+ void unloadScenario( const string &filename );
+
SGPropertyNode_ptr root;
SGPropertyNode_ptr enabled;
SGPropertyNode_ptr thermal_lift_node;
SGPropertyNode_ptr wind_from_north_node;
+ ai_list_type ai_list;
+
double user_altitude_agl;
double user_heading;
double user_pitch;
SGPropertyChangeCallback<FGAIManager> cb_ai_bare;
SGPropertyChangeCallback<FGAIManager> cb_ai_detailed;
+
+ class Scenario;
+ typedef std::map<std::string, Scenario*> ScenarioDict;
+ ScenarioDict _scenarios;
};
#endif // _FG_AIMANAGER_HXX