Commands to control scenarios / AI-objects.
New commands allow runtime scenario loading and unloading, and AI object creation and removal at runtime.
This commit is contained in:
parent
4a84ea0bc4
commit
96a40fe70c
2 changed files with 145 additions and 85 deletions
src/AIModel
|
@ -25,6 +25,8 @@
|
||||||
#include <simgear/math/sg_geodesy.hxx>
|
#include <simgear/math/sg_geodesy.hxx>
|
||||||
#include <simgear/props/props_io.hxx>
|
#include <simgear/props/props_io.hxx>
|
||||||
#include <simgear/structure/exception.hxx>
|
#include <simgear/structure/exception.hxx>
|
||||||
|
#include <simgear/structure/commands.hxx>
|
||||||
|
|
||||||
#include <boost/mem_fn.hpp>
|
#include <boost/mem_fn.hpp>
|
||||||
#include <boost/foreach.hpp>
|
#include <boost/foreach.hpp>
|
||||||
|
|
||||||
|
@ -45,6 +47,33 @@
|
||||||
#include "AIGroundVehicle.hxx"
|
#include "AIGroundVehicle.hxx"
|
||||||
#include "AIEscort.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() :
|
FGAIManager::FGAIManager() :
|
||||||
cb_ai_bare(SGPropertyChangeCallback<FGAIManager>(this,&FGAIManager::updateLOD,
|
cb_ai_bare(SGPropertyChangeCallback<FGAIManager>(this,&FGAIManager::updateLOD,
|
||||||
fgGetNode("/sim/rendering/static-lod/ai-bare", true))),
|
fgGetNode("/sim/rendering/static-lod/ai-bare", true))),
|
||||||
|
@ -72,6 +101,9 @@ FGAIManager::init() {
|
||||||
user_altitude_agl_node = fgGetNode("/position/altitude-agl-ft", true);
|
user_altitude_agl_node = fgGetNode("/position/altitude-agl-ft", true);
|
||||||
user_yaw_node = fgGetNode("/orientation/side-slip-deg", true);
|
user_yaw_node = fgGetNode("/orientation/side-slip-deg", true);
|
||||||
user_speed_node = fgGetNode("/velocities/uBody-fps", 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
|
void
|
||||||
|
@ -86,20 +118,18 @@ FGAIManager::postinit() {
|
||||||
enabled->setBoolValue(true);
|
enabled->setBoolValue(true);
|
||||||
|
|
||||||
// process all scenarios
|
// process all scenarios
|
||||||
std::set<std::string> loadedScenarios;
|
|
||||||
BOOST_FOREACH(SGPropertyNode* n, root->getChildren("scenario")) {
|
BOOST_FOREACH(SGPropertyNode* n, root->getChildren("scenario")) {
|
||||||
const string& name = n->getStringValue();
|
const string& name = n->getStringValue();
|
||||||
if (name.empty())
|
if (name.empty())
|
||||||
continue;
|
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");
|
SG_LOG(SG_AI, SG_WARN, "won't load scenario '" << name << "' twice");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
SG_LOG(SG_AI, SG_INFO, "loading scenario '" << name << '\'');
|
SG_LOG(SG_AI, SG_INFO, "loading scenario '" << name << '\'');
|
||||||
loadScenario(name);
|
loadScenario(name);
|
||||||
loadedScenarios.insert(name);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -242,81 +272,101 @@ FGAIManager::processThermal( double dt, FGAIThermal* thermal ) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FGAIManager::addObjectCommand(const SGPropertyNode* definition)
|
||||||
|
{
|
||||||
|
addObject(definition);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
ai->readFromScenario(const_cast<SGPropertyNode*>(definition));
|
||||||
|
attach(ai);
|
||||||
|
return ai;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
FGAIManager::loadScenario( const string &filename ) {
|
FGAIManager::unloadScenario( const string &filename)
|
||||||
|
{
|
||||||
SGPropertyNode_ptr scenarioTop = loadScenarioFile(filename);
|
ScenarioDict::iterator it = _scenarios.find(filename);
|
||||||
|
if (it == _scenarios.end()) {
|
||||||
if (!scenarioTop)
|
SG_LOG(SG_AI, SG_WARN, "unload scenario: not found:" << filename);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
SGPropertyNode* scenarios = scenarioTop->getChild("scenario");
|
|
||||||
|
delete it->second;
|
||||||
if (!scenarios)
|
_scenarios.erase(it);
|
||||||
return;
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SGPropertyNode_ptr
|
SGPropertyNode_ptr
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#define _FG_AIMANAGER_HXX
|
#define _FG_AIMANAGER_HXX
|
||||||
|
|
||||||
#include <list>
|
#include <list>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
#include <simgear/structure/subsystem_mgr.hxx>
|
#include <simgear/structure/subsystem_mgr.hxx>
|
||||||
#include <simgear/structure/SGSharedPtr.hxx>
|
#include <simgear/structure/SGSharedPtr.hxx>
|
||||||
|
@ -37,24 +38,21 @@
|
||||||
#include <Traffic/SchedFlight.hxx>
|
#include <Traffic/SchedFlight.hxx>
|
||||||
#include <Traffic/Schedule.hxx>
|
#include <Traffic/Schedule.hxx>
|
||||||
|
|
||||||
using std::list;
|
|
||||||
|
|
||||||
class FGAIThermal;
|
class FGAIThermal;
|
||||||
|
|
||||||
|
typedef SGSharedPtr<FGAIBase> FGAIBasePtr;
|
||||||
|
|
||||||
class FGAIManager : public SGSubsystem
|
class FGAIManager : public SGSubsystem
|
||||||
{
|
{
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
// A list of pointers to AI objects
|
// 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::iterator ai_list_iterator;
|
||||||
typedef ai_list_type::const_iterator ai_list_const_iterator;
|
typedef ai_list_type::const_iterator ai_list_const_iterator;
|
||||||
|
|
||||||
ai_list_type ai_list;
|
const ai_list_type& get_ai_list() const {
|
||||||
|
|
||||||
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());
|
|
||||||
return ai_list;
|
return ai_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,9 +70,6 @@ public:
|
||||||
|
|
||||||
const FGAIBase *calcCollision(double alt, double lat, double lon, double fuse_range);
|
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_heading() const { return user_heading; }
|
||||||
inline double get_user_pitch() const { return user_pitch; }
|
inline double get_user_pitch() const { return user_pitch; }
|
||||||
inline double get_user_yaw() const { return user_yaw; }
|
inline double get_user_yaw() const { return user_yaw; }
|
||||||
|
@ -86,18 +81,27 @@ public:
|
||||||
|
|
||||||
int getNumAiObjects(void) const;
|
int getNumAiObjects(void) const;
|
||||||
|
|
||||||
void loadScenario( const string &filename );
|
bool loadScenario( const string &filename );
|
||||||
|
|
||||||
static SGPropertyNode_ptr loadScenarioFile(const std::string& filename);
|
static SGPropertyNode_ptr loadScenarioFile(const std::string& filename);
|
||||||
|
|
||||||
static bool getStartPosition(const string& id, const string& pid,
|
static bool getStartPosition(const string& id, const string& pid,
|
||||||
SGGeod& geodPos, double& hdng, SGVec3d& uvw);
|
SGGeod& geodPos, double& hdng, SGVec3d& uvw);
|
||||||
|
|
||||||
|
FGAIBasePtr addObject(const SGPropertyNode* definition);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void removeDeadItem(FGAIBase* base);
|
void removeDeadItem(FGAIBase* base);
|
||||||
|
|
||||||
double calcRange(const SGVec3d& aCartPos, FGAIBase* aObject) const;
|
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 root;
|
||||||
SGPropertyNode_ptr enabled;
|
SGPropertyNode_ptr enabled;
|
||||||
SGPropertyNode_ptr thermal_lift_node;
|
SGPropertyNode_ptr thermal_lift_node;
|
||||||
|
@ -108,6 +112,8 @@ private:
|
||||||
SGPropertyNode_ptr wind_from_north_node;
|
SGPropertyNode_ptr wind_from_north_node;
|
||||||
|
|
||||||
|
|
||||||
|
ai_list_type ai_list;
|
||||||
|
|
||||||
double user_altitude_agl;
|
double user_altitude_agl;
|
||||||
double user_heading;
|
double user_heading;
|
||||||
double user_pitch;
|
double user_pitch;
|
||||||
|
@ -127,6 +133,10 @@ private:
|
||||||
|
|
||||||
SGPropertyChangeCallback<FGAIManager> cb_ai_bare;
|
SGPropertyChangeCallback<FGAIManager> cb_ai_bare;
|
||||||
SGPropertyChangeCallback<FGAIManager> cb_ai_detailed;
|
SGPropertyChangeCallback<FGAIManager> cb_ai_detailed;
|
||||||
|
|
||||||
|
class Scenario;
|
||||||
|
typedef std::map<std::string, Scenario*> ScenarioDict;
|
||||||
|
ScenarioDict _scenarios;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // _FG_AIMANAGER_HXX
|
#endif // _FG_AIMANAGER_HXX
|
||||||
|
|
Loading…
Add table
Reference in a new issue