From: Mathias Froehlich Date: Sat, 24 Nov 2012 09:34:08 +0000 (+0100) Subject: fgai: Add an initial sketch of an external ai module. X-Git-Url: https://git.mxchange.org/?a=commitdiff_plain;h=d79b2385b4f4a64a2460c32e6123ea399bfa83d6;p=flightgear.git fgai: Add an initial sketch of an external ai module. --- diff --git a/utils/CMakeLists.txt b/utils/CMakeLists.txt index 70d89a487..f176e749f 100644 --- a/utils/CMakeLists.txt +++ b/utils/CMakeLists.txt @@ -14,3 +14,8 @@ endif (FLTK_FOUND) if (WITH_FGPANEL) add_subdirectory(fgpanel) endif (WITH_FGPANEL) + +# win32 is just excluded because of not having argument parsing there ... +if(RTI_FOUND AND NOT WIN32) + add_subdirectory(fgai) +endif(RTI_FOUND AND NOT WIN32) diff --git a/utils/fgai/AIBVHPager.cxx b/utils/fgai/AIBVHPager.cxx new file mode 100644 index 000000000..a5cc13960 --- /dev/null +++ b/utils/fgai/AIBVHPager.cxx @@ -0,0 +1,152 @@ +// Copyright (C) 2009 - 2012 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "AIBVHPager.hxx" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace fgai { + +// Short circuit reading image files. +class AIBVHPager::ReadFileCallback : public simgear::OptionsReadFileCallback { +public: + virtual ~ReadFileCallback() + { } + + virtual osgDB::ReaderWriter::ReadResult readImage(const std::string& name, const osgDB::Options*) + { return new osg::Image; } +}; + +// A sub tree collector that pages in the nodes that it needs +class AIBVHPager::SubTreeCollector : public simgear::BVHSubTreeCollector { +public: + SubTreeCollector(simgear::BVHPager& pager, const SGSphered& sphere) : + BVHSubTreeCollector(sphere), + _pager(pager), + _complete(true) + { } + virtual ~SubTreeCollector() + { } + + virtual void apply(simgear::BVHPageNode& pageNode) + { + _pager.use(pageNode); + BVHSubTreeCollector::apply(pageNode); + _complete = _complete && 0 != pageNode.getNumChildren(); + } + bool complete() const + { return _complete; } + +private: + simgear::BVHPager& _pager; + bool _complete; +}; + +AIBVHPager::AIBVHPager() +{ +} + +AIBVHPager::~AIBVHPager() +{ +} + +void +AIBVHPager::setScenery(const std::string& fg_root, const std::string& fg_scenery) +{ + SGSharedPtr props = new SGPropertyNode; + try { + SGPath preferencesFile = fg_root; + preferencesFile.append("preferences.xml"); + readProperties(preferencesFile.str(), props); + } catch (...) { + // In case of an error, at least make summer :) + props->getNode("sim/startup/season", true)->setStringValue("summer"); + + SG_LOG(SG_GENERAL, SG_ALERT, "Problems loading FlightGear preferences.\n" + << "Probably FG_ROOT is not properly set."); + } + + /// now set up the simgears required model stuff + + simgear::ResourceManager::instance()->addBasePath(fg_root, simgear::ResourceManager::PRIORITY_DEFAULT); + // Just reference simgears reader writer stuff so that the globals get + // pulled in by the linker ... + simgear::ModelRegistry::instance(); + + sgUserDataInit(props.get()); + SGMaterialLib* ml = new SGMaterialLib; + SGPath mpath(fg_root); + mpath.append("Materials/default/materials.xml"); + try { + ml->load(fg_root, mpath.str(), props); + } catch (...) { + SG_LOG(SG_GENERAL, SG_ALERT, "Problems loading FlightGear materials.\n" + << "Probably FG_ROOT is not properly set."); + } + simgear::SGModelLib::init(fg_root, props); + + // Set up the reader/writer options + osg::ref_ptr options; + if (osgDB::Options* ropt = osgDB::Registry::instance()->getOptions()) + options = new simgear::SGReaderWriterOptions(*ropt); + else + options = new simgear::SGReaderWriterOptions; + osgDB::convertStringPathIntoFilePathList(fg_scenery, + options->getDatabasePathList()); + options->setMaterialLib(ml); + options->setPropertyNode(props); + options->setReadFileCallback(new ReadFileCallback); + options->setPluginStringData("SimGear::FG_ROOT", fg_root); + // we do not need the builtin boundingvolumes + options->setPluginStringData("SimGear::BOUNDINGVOLUMES", "OFF"); + // And we only want terrain, no objects on top. + options->setPluginStringData("SimGear::FG_ONLY_TERRAIN", "ON"); + // Hmm, ??!! + options->setPluginStringData("SimGear::FG_ONLY_AIRPORTS", "ON"); + props->getNode("sim/rendering/random-objects", true)->setBoolValue(false); + props->getNode("sim/rendering/random-vegetation", true)->setBoolValue(false); + + // Get the whole world bvh tree + _node = simgear::BVHPageNodeOSG::load("w180s90-360x180.spt", options); +} + +SGSharedPtr +AIBVHPager::getBoundingVolumes(const SGSphered& sphere) +{ + if (!_node.valid()) + return SGSharedPtr(); + SubTreeCollector subTreeCollector(*this, sphere); + _node->accept(subTreeCollector); + return subTreeCollector.getNode(); +} + +} // namespace fgai diff --git a/utils/fgai/AIBVHPager.hxx b/utils/fgai/AIBVHPager.hxx new file mode 100644 index 000000000..2da3e2239 --- /dev/null +++ b/utils/fgai/AIBVHPager.hxx @@ -0,0 +1,49 @@ +// Copyright (C) 2009 - 2012 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#ifndef _AIBVHPAGER_HXX +#define _AIBVHPAGER_HXX + +#include +#include +#include + +namespace fgai { + +class AIBVHPager : public simgear::BVHPager { +public: + AIBVHPager(); + ~AIBVHPager(); + + /// Load the flightgear scenery into the pager + void setScenery(const std::string& fg_root, const std::string& fg_scenery); + + /// Get a bounding volume subtree contained in sphere. + /// This is similar to the not so well known ground cache. + SGSharedPtr getBoundingVolumes(const SGSphered& sphere); + +private: + class ReadFileCallback; + class SubTreeCollector; + + /// The possibly paged root node + SGSharedPtr _node; +}; + +} // namespace fgai + +#endif diff --git a/utils/fgai/AIEnvironment.cxx b/utils/fgai/AIEnvironment.cxx new file mode 100644 index 000000000..e74ebbc4f --- /dev/null +++ b/utils/fgai/AIEnvironment.cxx @@ -0,0 +1,37 @@ +// Copyright (C) 2009 - 2012 Mathias Froehlich +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "AIEnvironment.hxx" + +#include "AIObject.hxx" +#include "AIManager.hxx" + +namespace fgai { + +AIEnvironment::~AIEnvironment() +{ +} + +void +AIEnvironment::update(AIObject& object, const SGTimeStamp& dt) +{ +} + +} // namespace fgai diff --git a/utils/fgai/AIEnvironment.hxx b/utils/fgai/AIEnvironment.hxx new file mode 100644 index 000000000..3e482ff57 --- /dev/null +++ b/utils/fgai/AIEnvironment.hxx @@ -0,0 +1,48 @@ +// Copyright (C) 2009 - 2012 Mathias Froehlich +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +#ifndef AIEnvironment_hxx +#define AIEnvironment_hxx + +#include +#include +#include "AISubsystem.hxx" + +namespace fgai { + +class AIPhysics; +class AIBVHPager; + +class AIEnvironment : public AISubsystem { +public: + virtual ~AIEnvironment(); + + virtual void update(AIObject& object, const SGTimeStamp& dt); + + // Get these at some point from a weather module and an apropriate + // hla attribute + double getDensity() const + { return 1.29; } + double getTemperature() const + { return 15 + 273.15; } + /// The wind speed in cartesian coorindates in the earth centered frame + SGVec3d getWindVelocity() const + { return SGVec3d::zeros(); } +}; + +} // namespace fgai + +#endif diff --git a/utils/fgai/AIManager.cxx b/utils/fgai/AIManager.cxx new file mode 100644 index 000000000..c1ee6efbd --- /dev/null +++ b/utils/fgai/AIManager.cxx @@ -0,0 +1,228 @@ +// Copyright (C) 2009 - 2012 Mathias Froehlich +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "AIManager.hxx" + +#include + +#include "HLAAirVehicleClass.hxx" +#include "HLAAircraftClass.hxx" +#include "HLABaloonClass.hxx" +#include "HLAMPAircraftClass.hxx" + +#include "AIObject.hxx" + +namespace fgai { + +AIManager::AIManager() : + _maxStep(SGTimeStamp::fromSecMSec(0, 200)) +{ + // Set sensible defaults + setFederationExecutionName("rti:///FlightGear"); + setFederateType("AIFederate"); + /// The hla ai module is running ahead of the simulation time of the federation. + /// This way we are sure that all required data has arrived at the client when it is needed. + /// This is the amount of simulation time the ai module leads the federations simulation time. + setLeadTime(SGTimeStamp::fromSec(10)); + setTimeConstrainedByLocalClock(true); +} + +AIManager::~AIManager() +{ +} + +simgear::HLAObjectClass* +AIManager::createObjectClass(const std::string& name) +{ + // Just there for demonstration. + if (name == "MPAircraft") + return new HLAMPAircraftClass(name, this); + + // These should be the future objects + // The air vehicle should be the one an atc looks at + if (name == "AirVehicle") + return new HLAAirVehicleClass(name, this); + // An aircraft with wings and that + if (name == "Aircraft") + return new HLAAircraftClass(name, this); + // A hot air baloon ... + if (name == "Baloon") + return new HLABaloonClass(name, this); + + return 0; +} + +bool +AIManager::init() +{ + if (!simgear::HLAFederate::init()) + return false; + + SGTimeStamp federateTime; + queryFederateTime(federateTime); + _simTime = federateTime + getLeadTime(); + + _pager.start(); + + return true; +} + +bool +AIManager::update() +{ + // Mark newly requested paged nodes with the current simulation time. + _pager.setUseStamp((unsigned)_simTime.toSecs()); + + while (!_initObjectList.empty()) { + assert(_currentObject.empty()); + _currentObject.splice(_currentObject.end(), _initObjectList, _initObjectList.begin()); + _currentObject.front()->init(*this); + // If it did not reschedule itself, immediately delete it + if (_currentObject.empty()) + continue; + _currentObject.front()->shutdown(*this); + _currentObject.clear(); + } + + // Find the first time slot we have anything scheduled for + TimeStampObjectListIteratorMap::iterator i; + i = _timeStampObjectListIteratorMap.begin(); + + if (i == _timeStampObjectListIteratorMap.end() || _simTime + _maxStep < i->first) { + // If the time slot is too far away, do a _maxStep time advance. + + _simTime += _maxStep; + + } else { + // Process the list object updates scheduled for this time slot + + _simTime = i->first; + + // Call the updates + while (_objectList.begin() != i->second) { + assert(_currentObject.empty()); + _currentObject.splice(_currentObject.end(), _objectList, _objectList.begin()); + _currentObject.front()->update(*this, _simTime); + // If it did not reschedule itself, immediately delete it + if (_currentObject.empty()) + continue; + _currentObject.front()->shutdown(*this); + _currentObject.clear(); + } + + // get rid of the null element + assert(!_objectList.front().valid()); + _objectList.pop_front(); + + // The timestep has passed now + _timeStampObjectListIteratorMap.erase(i); + } + + if (!timeAdvance(_simTime - getLeadTime())) + return false; + + // Expire bounding volume nodes older than 120 seconds + _pager.update(120); + + return true; +} + +bool +AIManager::shutdown() +{ + // don't care anmore + _timeStampObjectListIteratorMap.clear(); + // Nothing has ever happened with these, just get rid of them + _initObjectList.clear(); + // Call shutdown on them + while (!_objectList.empty()) { + SGSharedPtr object; + object.swap(_objectList.front()); + _objectList.pop_front(); + if (!object.valid()) + continue; + object->shutdown(*this); + } + + // Then do the hla shutdown part + if (!simgear::HLAFederate::shutdown()) + return false; + + // Expire bounding volume nodes + _pager.update(0); + _pager.stop(); + + return true; +} + +void +AIManager::insert(const SGSharedPtr& object) +{ + if (!object.valid()) + return; + /// Note that this iterator is consistently spliced through the various lists, + /// This must stay stable. + object->_objectListIterator = _initObjectList.insert(_initObjectList.end(), object); +} + +void +AIManager::schedule(AIObject& object, const SGTimeStamp& simTime) +{ + if (simTime <= _simTime) + return; + if (_currentObject.empty()) + return; + + TimeStampObjectListIteratorMap::iterator i; + i = _timeStampObjectListIteratorMap.lower_bound(simTime); + if (i == _timeStampObjectListIteratorMap.end()) { + ObjectList::iterator j = _objectList.insert(_objectList.end(), 0); + typedef TimeStampObjectListIteratorMap::value_type value_type; + i = _timeStampObjectListIteratorMap.insert(value_type(simTime, j)).first; + } else if (i->first != simTime) { + if (i == _timeStampObjectListIteratorMap.begin()) { + ObjectList::iterator j = _objectList.insert(_objectList.begin(), 0); + typedef TimeStampObjectListIteratorMap::value_type value_type; + i = _timeStampObjectListIteratorMap.insert(value_type(simTime, j)).first; + } else { + --i; + ObjectList::iterator k = i->second; + ObjectList::iterator j = _objectList.insert(++k, 0); + typedef TimeStampObjectListIteratorMap::value_type value_type; + i = _timeStampObjectListIteratorMap.insert(value_type(simTime, j)).first; + } + } + // Note that the iterator stays stable + _objectList.splice(i->second, _currentObject, _currentObject.begin()); +} + +const AIBVHPager& +AIManager::getPager() const +{ + return _pager; +} + +AIBVHPager& +AIManager::getPager() +{ + return _pager; +} + +} // namespace fgai diff --git a/utils/fgai/AIManager.hxx b/utils/fgai/AIManager.hxx new file mode 100644 index 000000000..a9c19739f --- /dev/null +++ b/utils/fgai/AIManager.hxx @@ -0,0 +1,77 @@ +// Copyright (C) 2009 - 2012 Mathias Froehlich +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +#ifndef AIManager_hxx +#define AIManager_hxx + +#include +#include "AIBVHPager.hxx" + +namespace fgai { + +class AIObject; + +class AIManager : public simgear::HLAFederate { +public: + AIManager(); + virtual ~AIManager(); + + virtual simgear::HLAObjectClass* createObjectClass(const std::string& name); + + virtual bool init(); + virtual bool update(); + virtual bool shutdown(); + + void insert(const SGSharedPtr& aiObject); + void schedule(AIObject& object, const SGTimeStamp& simTime); + + const SGTimeStamp& getSimTime() const + { return _simTime; } + + const AIBVHPager& getPager() const; + AIBVHPager& getPager(); + + /// For the list of ai object that are active + typedef std::list > ObjectList; + /// For the schedule of the next update of an ai object + typedef std::map TimeStampObjectListMap; + + typedef std::map TimeStampObjectListIteratorMap; + +private: + /// The current simulation time + SGTimeStamp _simTime; + /// The maximum time advance step size that is taken + SGTimeStamp _maxStep; + + /// Single element list that is used to store the currently worked on + /// ai object. This is a helper for any work method in the object. + ObjectList _currentObject; + + /// List of objects that are inserted and need to be initialized + ObjectList _initObjectList; + /// List of running and ready to use objects, is in execution order + ObjectList _objectList; + /// Map of insert points for specific simulation times + TimeStampObjectListIteratorMap _timeStampObjectListIteratorMap; + + /// for paging bounding volume trees + AIBVHPager _pager; +}; + +} // namespace fgai + +#endif diff --git a/utils/fgai/AIObject.cxx b/utils/fgai/AIObject.cxx new file mode 100644 index 000000000..06d42c272 --- /dev/null +++ b/utils/fgai/AIObject.cxx @@ -0,0 +1,103 @@ +// Copyright (C) 2009 - 2012 Mathias Froehlich +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "AIObject.hxx" + +#include +#include +#include + +#include "AIManager.hxx" + +namespace fgai { + +AIObject::AIObject() : + _environment(new AIEnvironment), + _subsystemGroup(new AISubsystemGroup) +{ +} + +AIObject::~AIObject() +{ +} + +void +AIObject::init(AIManager& manager) +{ + _simTime = manager.getSimTime(); +} + +void +AIObject::update(AIManager& manager, const SGTimeStamp& simTime) +{ + _simTime = simTime; +} + +void +AIObject::shutdown(AIManager& manager) +{ + _simTime = SGTimeStamp(); +} + +void +AIObject::setGroundCache(const AIPhysics& physics, AIBVHPager& pager, const SGTimeStamp& dt) +{ + SGVec3d point = physics.getLocation().getPosition(); + double linearVelocity = norm(physics.getLinearBodyVelocity()); + // The 2 is a security factor for accelerations, but at least 100 meters + double radius = std::max(100.0, 2*dt.toSecs()*linearVelocity); + SGSphered requiredSphere(point, radius); + /// Are we already good enough? + if (requiredSphere.inside(_querySphere)) + return; + // Now query something somehow bigger to avoid querying again in the next frame + SGSphered sphere(point, 4*radius); + _node = pager.getBoundingVolumes(sphere); + if (!_node.valid()) + return; + _querySphere = sphere; +} + +bool +AIObject::getGroundIntersection(SGVec3d& point, SGVec3d& normal, const SGLineSegmentd& lineSegment) const +{ + if (!_node.valid()) + return false; + simgear::BVHLineSegmentVisitor lineSegmentVisitor(lineSegment); + _node->accept(lineSegmentVisitor); + if (lineSegmentVisitor.empty()) + return false; + normal = lineSegmentVisitor.getNormal(); + point = lineSegmentVisitor.getPoint(); + return true; +} + +bool +AIObject::getGroundIntersection(SGPlaned& plane, const SGLineSegmentd& lineSegment) const +{ + SGVec3d point; + SGVec3d normal; + if (!getGroundIntersection(point, normal, lineSegment)) + return false; + plane = SGPlaned(normal, point); + return true; +} + +} // namespace fgai diff --git a/utils/fgai/AIObject.hxx b/utils/fgai/AIObject.hxx new file mode 100644 index 000000000..f5f68a444 --- /dev/null +++ b/utils/fgai/AIObject.hxx @@ -0,0 +1,92 @@ +// Copyright (C) 2009 - 2012 Mathias Froehlich +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +#ifndef AIObject_hxx +#define AIObject_hxx + +#include +#include +#include +#include +#include + +#include "AIEnvironment.hxx" +#include "AIManager.hxx" +#include "AIPhysics.hxx" + +namespace fgai { + +class AIBVHPager; + +class AIObject : public SGWeakReferenced { +public: + AIObject(); + virtual ~AIObject(); + + // also register the required hla objects here + virtual void init(AIManager& manager); + virtual void update(AIManager& manager, const SGTimeStamp& simTime); + virtual void shutdown(AIManager& manager); + + void setGroundCache(const AIPhysics& physics, AIBVHPager& pager, const SGTimeStamp& dt); + bool getGroundIntersection(SGVec3d& point, SGVec3d& normal, const SGLineSegmentd& lineSegment) const; + bool getGroundIntersection(SGPlaned& plane, const SGLineSegmentd& lineSegment) const; + + const SGTimeStamp& getSimTime() const + { return _simTime; } + + const AIEnvironment& getEnvironment() const + { return *_environment; } + AIEnvironment& getEnvironment() + { return *_environment; } + + const AISubsystemGroup& getSubsystemGroup() const + { return *_subsystemGroup; } + AISubsystemGroup& getSubsystemGroup() + { return *_subsystemGroup; } + + const AIPhysics& getPhysics() const + { return *_physics; } + AIPhysics& getPhysics() + { return *_physics; } + +protected: + void setPhysics(AIPhysics* physics) + { _physics = physics; } + +private: + friend class AIManager; + + // The simulation time + SGTimeStamp _simTime; + + // The iterator to our own list entry in the manager class + AIManager::ObjectList::iterator _objectListIterator; + + // The components we have for an ai object + SGSharedPtr _environment; + SGSharedPtr _subsystemGroup; + SGSharedPtr _physics; + + /// The equivalent of the ground cache for FGInterface. + SGSharedPtr _node; + /// The sphere we really queried for the ground cache + SGSphered _querySphere; +}; + +} // namespace fgai + +#endif diff --git a/utils/fgai/AIPhysics.cxx b/utils/fgai/AIPhysics.cxx new file mode 100644 index 000000000..c60e79e83 --- /dev/null +++ b/utils/fgai/AIPhysics.cxx @@ -0,0 +1,104 @@ +// Copyright (C) 2009 - 2012 Mathias Froehlich +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "AIPhysics.hxx" + +#include +#include "AIEnvironment.hxx" + +namespace fgai { + +AIPhysics::AIPhysics(const AIPhysics& physics) : + _location(physics._location), + _linearBodyVelocity(physics._linearBodyVelocity), + _angularBodyVelocity(physics._angularBodyVelocity), + _geodPosition(physics._geodPosition), + _horizontalLocalOrientation(physics._horizontalLocalOrientation) +{ +} + +AIPhysics::AIPhysics(const SGLocationd& location, const SGVec3d& linearBodyVelocity, + const SGVec3d& angularBodyVelocity) : + _location(location), + _linearBodyVelocity(linearBodyVelocity), + _angularBodyVelocity(angularBodyVelocity) +{ + _geodPosition = SGGeod::fromCart(_location.getPosition()); + _horizontalLocalOrientation = SGQuatd::fromLonLat(_geodPosition); +} + +AIPhysics::~AIPhysics() +{ +} + +void +AIPhysics::update(AIObject& object, const SGTimeStamp& dt) +{ + advanceByBodyVelocity(dt.toSecs(), _linearBodyVelocity, _angularBodyVelocity); +} + +void +AIPhysics::advanceByBodyAcceleration(const double& dt, + const SGVec3d& linearAcceleration, + const SGVec3d& angularAcceleration) +{ + // The current linear and angular velocity + SGVec3d linearVelocity = getLinearBodyVelocity(); + SGVec3d angularVelocity = getAngularBodyVelocity(); + + // an euler step for the velocities, the positions get upgraded below + linearVelocity += dt*linearAcceleration; + angularVelocity += dt*angularAcceleration; + + advanceByBodyVelocity(dt, linearVelocity, angularVelocity); +} + +void +AIPhysics::advanceByBodyVelocity(const double& dt, + const SGVec3d& linearVelocity, + const SGVec3d& angularVelocity) +{ + // Do an euler step with the derivatives at mSimTime + _location.eulerStepBodyVelocities(dt, _linearBodyVelocity, _angularBodyVelocity); + _geodPosition = SGGeod::fromCart(_location.getPosition()); + _horizontalLocalOrientation = SGQuatd::fromLonLat(_geodPosition); + + // Store the new velocities for the next interval at mSimTim + dt + _linearBodyVelocity = linearVelocity; + _angularBodyVelocity = angularVelocity; +} + +void +AIPhysics::advanceToLocation(const double& dt, const SGLocationd& location) +{ + // At first we need to move along with the announced velocities, so: + // Do an euler step with the derivatives at mSimTime. + _location.eulerStepBodyVelocities(dt, _linearBodyVelocity, _angularBodyVelocity); + _geodPosition = SGGeod::fromCart(_location.getPosition()); + _horizontalLocalOrientation = SGQuatd::fromLonLat(_geodPosition); + + // Now compute velocities that will move to the desired position, orientation if the next + // advance method is called with the same dt value + SGVec3d positionDifference = location.getPosition() - _location.getPosition(); + _linearBodyVelocity = (1/dt)*_location.getOrientation().transform(positionDifference); + _angularBodyVelocity = SGQuatd::forwardDifferenceVelocity(_location.getOrientation(), location.getOrientation(), dt); +} + +} // namespace fgai diff --git a/utils/fgai/AIPhysics.hxx b/utils/fgai/AIPhysics.hxx new file mode 100644 index 000000000..57497a1fd --- /dev/null +++ b/utils/fgai/AIPhysics.hxx @@ -0,0 +1,108 @@ +// Copyright (C) 2009 - 2012 Mathias Froehlich +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +#ifndef AIPhysics_hxx +#define AIPhysics_hxx + +#include +#include "AISubsystem.hxx" + +namespace fgai { + +class AIPhysics : public AISubsystem { +public: + /// Initial conditions need to be set at creation time. + /// Just setting the position underway will result in unphysical motion. + AIPhysics(const AIPhysics& physics); + AIPhysics(const SGLocationd& location, const SGVec3d& linearBodyVelocity = SGVec3d::zeros(), + const SGVec3d& angularBodyVelocity = SGVec3d::zeros()); + virtual ~AIPhysics(); + + /// The default is unaccelerated movement + virtual void update(AIObject& object, const SGTimeStamp& dt); + + /// The current state + const SGLocationd& getLocation() const + { return _location; } + const SGVec3d& getPosition() const + { return _location.getPosition(); } + const SGQuatd& getOrientation() const + { return _location.getOrientation(); } + const SGGeod& getGeodPosition() const + { return _geodPosition; } + const SGQuatd& getHorizontalLocalOrientation() const + { return _horizontalLocalOrientation; } + /// The orientation of the body wrt the geodetic ned coordinate system + SGQuatd getGeodOrientation() const + { return inverse(_horizontalLocalOrientation)*_location.getOrientation(); } + const SGVec3d& getLinearBodyVelocity() const + { return _linearBodyVelocity; } + const SGVec3d& getAngularBodyVelocity() const + { return _angularBodyVelocity; } + /// The velocity in global cartesian coordinates + SGVec3d getLinearVelocity() const + { return _location.getOrientation().backTransform(_linearBodyVelocity); } + /// The velocity in the north east down coordinate system + /// Note that this gets undefined at the poles. + SGVec3d getGeodVelocity() const + { return getGeodOrientation().backTransform(getLinearBodyVelocity()); } + double getDownVelocity() const + { return getGeodVelocity()[2]; } + SGVec2d getHorizontalVelocity() const + { SGVec3d v = getGeodVelocity(); return SGVec2d(v[0], v[1]); } + +protected: + /// The below methods change the position and velocity of the vehicle + /// in a way that is consistent in that it matches position, velocity + /// values to keep the velocity a numerical derivative of the position. + + /// Given the accelerations at the current simulation time mSimTime, + /// update the position and velocity to mSimTime + dt. + /// This is the primary advance mode for physically simulated motion. + /// Compute the forces on the single body, compute the accelerations + /// from the forces by newtons law and accelerate by this amount. + void advanceByBodyAcceleration(const double& dt, + const SGVec3d& linearAcceleration, + const SGVec3d& angularAcceleration); + + /// Given the velocities at the next simulation time mSimTime, + /// update the position and velocity to mSimTime + dt. + void advanceByBodyVelocity(const double& dt, + const SGVec3d& linearVelocity, + const SGVec3d& angularVelocity); + + /// Given the desired position and orientation, a pair of velocities + /// is computed to reach that position and orientation in the + /// next advance step. This one advance step latency is important + /// for other participants to correctly extrapolate the position + /// and orientation based on the velocities. + /// Note that this only works when the next update is called with + /// the same time increment. + void advanceToLocation(const double& dt, const SGLocationd& location); + +private: + AIPhysics& operator=(const AIPhysics& physics); + + SGLocationd _location; + SGVec3d _linearBodyVelocity; + SGVec3d _angularBodyVelocity; + SGGeod _geodPosition; + SGQuatd _horizontalLocalOrientation; +}; + +} // namespace fgai + +#endif diff --git a/utils/fgai/AISubsystem.hxx b/utils/fgai/AISubsystem.hxx new file mode 100644 index 000000000..a643bc1f4 --- /dev/null +++ b/utils/fgai/AISubsystem.hxx @@ -0,0 +1,60 @@ +// Copyright (C) 2009 - 2012 Mathias Froehlich +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +#ifndef AISubsystem_hxx +#define AISubsystem_hxx + +#include +#include +#include + +namespace fgai { + +class AIObject; + +class AISubsystem : public SGWeakReferenced { +public: + AISubsystem() + { } + virtual ~AISubsystem() + { } + + virtual void update(AIObject& object, const SGTimeStamp& dt) = 0; +}; + +class AISubsystemGroup : public AISubsystem { +public: + AISubsystemGroup() + { } + virtual ~AISubsystemGroup() + { } + + virtual void update(AIObject& object, const SGTimeStamp& dt) + { + for (SubsystemList::iterator i = _subsystemList.begin(); + i != _subsystemList.end(); ++i) { + (*i)->update(object, dt); + } + } + +private: + typedef std::list > SubsystemList; + SubsystemList _subsystemList; +}; + +} // namespace fgai + +#endif diff --git a/utils/fgai/CMakeLists.txt b/utils/fgai/CMakeLists.txt new file mode 100644 index 000000000..3b234a4c3 --- /dev/null +++ b/utils/fgai/CMakeLists.txt @@ -0,0 +1,28 @@ +add_executable(fgai + fgai.cxx + HLAAircraft.cxx + HLAAircraftClass.cxx + HLAAirVehicle.cxx + HLAAirVehicleClass.cxx + AIBVHPager.cxx + AIEnvironment.cxx + AIManager.cxx + AIObject.cxx + AIPhysics.cxx + HLABaloon.cxx + HLABaloonClass.cxx + HLAMPAircraft.cxx + HLAMPAircraftClass.cxx + HLASceneObject.cxx + HLASceneObjectClass.cxx +) + +target_link_libraries(fgai + ${SIMGEAR_LIBRARIES} + ${OPENSCENEGRAPH_LIBRARIES} + ${OPENGL_LIBRARIES} + ${RTI_LIBRARIES} + ${SIMGEAR_CORE_LIBRARY_DEPENDENCIES} +) + +install(TARGETS fgai RUNTIME DESTINATION bin) diff --git a/utils/fgai/HLAAirVehicle.cxx b/utils/fgai/HLAAirVehicle.cxx new file mode 100644 index 000000000..3ebea910c --- /dev/null +++ b/utils/fgai/HLAAirVehicle.cxx @@ -0,0 +1,49 @@ +// Copyright (C) 2009 - 2012 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "HLAAirVehicle.hxx" + +#include "HLAAirVehicleClass.hxx" + +namespace fgai { + +HLAAirVehicle::HLAAirVehicle(HLAAirVehicleClass* objectClass) : + HLASceneObject(objectClass) +{ +} + +HLAAirVehicle::~HLAAirVehicle() +{ +} + +void +HLAAirVehicle::createAttributeDataElements() +{ + HLASceneObject::createAttributeDataElements(); + + assert(dynamic_cast(getObjectClass().get())); + HLAAirVehicleClass& objectClass = static_cast(*getObjectClass()); + + setAttributeDataElement(objectClass.getCallSignIndex(), _callSign.getDataElement()); + // setAttributeDataElement(objectClass.getSquawkIndex(), _squawk.getDataElement()); +} + +} // namespace fgai diff --git a/utils/fgai/HLAAirVehicle.hxx b/utils/fgai/HLAAirVehicle.hxx new file mode 100644 index 000000000..956ad8520 --- /dev/null +++ b/utils/fgai/HLAAirVehicle.hxx @@ -0,0 +1,54 @@ +// Copyright (C) 2009 - 2012 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#ifndef HLAAirVehicle_hxx +#define HLAAirVehicle_hxx + +#include +#include +#include "HLASceneObject.hxx" + +namespace fgai { + +class HLAAirVehicleClass; + +class HLAAirVehicle : public HLASceneObject { +public: + HLAAirVehicle(HLAAirVehicleClass* objectClass = 0); + virtual ~HLAAirVehicle(); + + virtual void createAttributeDataElements(); + + void setCallSign(const std::string& callSign) + { _callSign.setValue(callSign); } + const std::string& getCallSign() const + { return _callSign.getValue(); } + + /// FIXME encode Mode a/b/c/whatever into a variant and make this backward compatible for all time!!! + // void setTransponder(unsigned short transponder) + // { _transponder.setValue(transponder); } + // unsigned short getTransponder() const + // { return _transponder.getValue(); } + +private: + simgear::HLAStringData _callSign; + // simgear::HLAUShortData _transponder; +}; + +} // namespace fgai + +#endif diff --git a/utils/fgai/HLAAirVehicleClass.cxx b/utils/fgai/HLAAirVehicleClass.cxx new file mode 100644 index 000000000..b3e6b7f9f --- /dev/null +++ b/utils/fgai/HLAAirVehicleClass.cxx @@ -0,0 +1,54 @@ +// Copyright (C) 2009 - 2012 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "HLAAirVehicleClass.hxx" + +#include "HLAAirVehicle.hxx" + +namespace fgai { + +HLAAirVehicleClass::HLAAirVehicleClass(const std::string& name, simgear::HLAFederate* federate) : + HLASceneObjectClass(name, federate) +{ +} + +HLAAirVehicleClass::~HLAAirVehicleClass() +{ +} + +simgear::HLAObjectInstance* +HLAAirVehicleClass::createObjectInstance(const std::string& name) +{ + return new HLAAirVehicle(this); +} + +void +HLAAirVehicleClass::createAttributeDataElements(simgear::HLAObjectInstance& objectInstance) +{ + /// FIXME resolve these indices somewhere else! + if (_callSignIndex.empty()) + _callSignIndex = getDataElementIndex("callSign"); + if (_transponderIndex.empty()) + _transponderIndex = getDataElementIndex("transponder"); + HLASceneObjectClass::createAttributeDataElements(objectInstance); +} + +} // namespace fgai diff --git a/utils/fgai/HLAAirVehicleClass.hxx b/utils/fgai/HLAAirVehicleClass.hxx new file mode 100644 index 000000000..520bb6ead --- /dev/null +++ b/utils/fgai/HLAAirVehicleClass.hxx @@ -0,0 +1,52 @@ +// Copyright (C) 2009 - 2012 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#ifndef HLAAirVehicleClass_hxx +#define HLAAirVehicleClass_hxx + +#include "HLASceneObjectClass.hxx" + +namespace fgai { + +class HLAAirVehicleClass : public HLASceneObjectClass { +public: + HLAAirVehicleClass(const std::string& name, simgear::HLAFederate* federate); + virtual ~HLAAirVehicleClass(); + + /// Create a new instance of this class. + virtual simgear::HLAObjectInstance* createObjectInstance(const std::string& name); + + virtual void createAttributeDataElements(simgear::HLAObjectInstance& objectInstance); + + bool setCallSignIndex(const std::string& path) + { return getDataElementIndex(_callSignIndex, path); } + const simgear::HLADataElementIndex& getCallSignIndex() const + { return _callSignIndex; } + + bool setTransponderIndex(const std::string& path) + { return getDataElementIndex(_transponderIndex, path); } + const simgear::HLADataElementIndex& getTransponderIndex() const + { return _transponderIndex; } + +private: + simgear::HLADataElementIndex _callSignIndex; + simgear::HLADataElementIndex _transponderIndex; +}; + +} // namespace fgai + +#endif diff --git a/utils/fgai/HLAAircraft.cxx b/utils/fgai/HLAAircraft.cxx new file mode 100644 index 000000000..ff6b9ec3c --- /dev/null +++ b/utils/fgai/HLAAircraft.cxx @@ -0,0 +1,50 @@ +// Copyright (C) 2009 - 2012 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "HLAAircraft.hxx" + +#include "HLAAircraftClass.hxx" + +namespace fgai { + +HLAAircraft::HLAAircraft(HLAAircraftClass* objectClass) : + HLAAirVehicle(objectClass) +{ +} + +HLAAircraft::~HLAAircraft() +{ +} + +void +HLAAircraft::createAttributeDataElements() +{ + HLAAirVehicle::createAttributeDataElements(); + + assert(dynamic_cast(getObjectClass().get())); + HLAAircraftClass& objectClass = static_cast(*getObjectClass()); + + // setAttributeDataElement(objectClass.getModelPathIndex(), _modelPath.getDataElement()); + // setAttributeDataElement(objectClass.getModelLiveryIndex(), _modelLivery.getDataElement()); + // setAttributeDataElement(objectClass.getSimTimeIndex(), _simTime.getDataElement()); +} + +} // namespace fgai diff --git a/utils/fgai/HLAAircraft.hxx b/utils/fgai/HLAAircraft.hxx new file mode 100644 index 000000000..0671ed335 --- /dev/null +++ b/utils/fgai/HLAAircraft.hxx @@ -0,0 +1,46 @@ +// Copyright (C) 2009 - 2012 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#ifndef HLAAircraft_hxx +#define HLAAircraft_hxx + +#include +#include "HLAAirVehicle.hxx" + +namespace fgai { + +class HLAAircraftClass; + +class HLAAircraft : public HLAAirVehicle { +public: + HLAAircraft(HLAAircraftClass* objectClass = 0); + virtual ~HLAAircraft(); + + virtual void createAttributeDataElements(); + +private: + // // The model stuff + // simgear::HLAStringData _modelPath; + // simgear::HLAStringData _modelLivery; + + // // The current simTime + // simgear::HLADoubleData _simTime; +}; + +} // namespace fgai + +#endif diff --git a/utils/fgai/HLAAircraftClass.cxx b/utils/fgai/HLAAircraftClass.cxx new file mode 100644 index 000000000..57f9257c5 --- /dev/null +++ b/utils/fgai/HLAAircraftClass.cxx @@ -0,0 +1,52 @@ +// Copyright (C) 2009 - 2012 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "HLAAircraftClass.hxx" + +#include "HLAAircraft.hxx" + +namespace fgai { + +HLAAircraftClass::HLAAircraftClass(const std::string& name, simgear::HLAFederate* federate) : + HLAAirVehicleClass(name, federate) +{ +} + +HLAAircraftClass::~HLAAircraftClass() +{ +} + +simgear::HLAObjectInstance* +HLAAircraftClass::createObjectInstance(const std::string& name) +{ + return new HLAAircraft(this); +} + +void +HLAAircraftClass::createAttributeDataElements(simgear::HLAObjectInstance& objectInstance) +{ + /// FIXME resolve these indices somewhere else! + // if (_simTimeIndex.empty()) + // _simTimeIndex = getDataElementIndex("simTime"); + HLAAirVehicleClass::createAttributeDataElements(objectInstance); +} + +} // namespace fgai diff --git a/utils/fgai/HLAAircraftClass.hxx b/utils/fgai/HLAAircraftClass.hxx new file mode 100644 index 000000000..259221825 --- /dev/null +++ b/utils/fgai/HLAAircraftClass.hxx @@ -0,0 +1,46 @@ +// Copyright (C) 2009 - 2012 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#ifndef HLAAircraftClass_hxx +#define HLAAircraftClass_hxx + +#include "HLAAirVehicleClass.hxx" + +namespace fgai { + +class HLAAircraftClass : public HLAAirVehicleClass { +public: + HLAAircraftClass(const std::string& name, simgear::HLAFederate* federate); + virtual ~HLAAircraftClass(); + + /// Create a new instance of this class. + virtual simgear::HLAObjectInstance* createObjectInstance(const std::string& name); + + virtual void createAttributeDataElements(simgear::HLAObjectInstance& objectInstance); + + // bool setSimTimeIndex(const std::string& path) + // { return getDataElementIndex(_simTimeIndex, path); } + // const simgear::HLADataElementIndex& getSimTimeIndex() const + // { return _simTimeIndex; } + +private: + // simgear::HLADataElementIndex _simTimeIndex; +}; + +} // namespace fgai + +#endif diff --git a/utils/fgai/HLABaloon.cxx b/utils/fgai/HLABaloon.cxx new file mode 100644 index 000000000..698c8e808 --- /dev/null +++ b/utils/fgai/HLABaloon.cxx @@ -0,0 +1,50 @@ +// Copyright (C) 2009 - 2012 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "HLABaloon.hxx" + +#include "HLABaloonClass.hxx" + +namespace fgai { + +HLABaloon::HLABaloon(HLABaloonClass* objectClass) : + HLAAirVehicle(objectClass) +{ +} + +HLABaloon::~HLABaloon() +{ +} + +void +HLABaloon::createAttributeDataElements() +{ + HLAAirVehicle::createAttributeDataElements(); + + assert(dynamic_cast(getObjectClass().get())); + HLABaloonClass& objectClass = static_cast(*getObjectClass()); + + // setAttributeDataElement(objectClass.getModelPathIndex(), _modelPath.getDataElement()); + // setAttributeDataElement(objectClass.getModelLiveryIndex(), _modelLivery.getDataElement()); + // setAttributeDataElement(objectClass.getSimTimeIndex(), _simTime.getDataElement()); +} + +} // namespace fgai diff --git a/utils/fgai/HLABaloon.hxx b/utils/fgai/HLABaloon.hxx new file mode 100644 index 000000000..2f33b6173 --- /dev/null +++ b/utils/fgai/HLABaloon.hxx @@ -0,0 +1,41 @@ +// Copyright (C) 2009 - 2012 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#ifndef HLABaloon_hxx +#define HLABaloon_hxx + +#include "HLAAirVehicle.hxx" + +namespace fgai { + +class HLABaloonClass; + +class HLABaloon : public HLAAirVehicle { +public: + HLABaloon(HLABaloonClass* objectClass = 0); + virtual ~HLABaloon(); + + virtual void createAttributeDataElements(); + +private: + // // The current simTime + // simgear::HLADoubleData _simTime; +}; + +} // namespace fgai + +#endif diff --git a/utils/fgai/HLABaloonClass.cxx b/utils/fgai/HLABaloonClass.cxx new file mode 100644 index 000000000..1fb2975dc --- /dev/null +++ b/utils/fgai/HLABaloonClass.cxx @@ -0,0 +1,52 @@ +// Copyright (C) 2009 - 2012 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "HLABaloonClass.hxx" + +#include "HLABaloon.hxx" + +namespace fgai { + +HLABaloonClass::HLABaloonClass(const std::string& name, simgear::HLAFederate* federate) : + HLAAirVehicleClass(name, federate) +{ +} + +HLABaloonClass::~HLABaloonClass() +{ +} + +simgear::HLAObjectInstance* +HLABaloonClass::createObjectInstance(const std::string& name) +{ + return new HLABaloon(this); +} + +void +HLABaloonClass::createAttributeDataElements(simgear::HLAObjectInstance& objectInstance) +{ + /// FIXME resolve these indices somewhere else! + // if (_simTimeIndex.empty()) + // _simTimeIndex = getDataElementIndex("simTime"); + HLAAirVehicleClass::createAttributeDataElements(objectInstance); +} + +} // namespace fgai diff --git a/utils/fgai/HLABaloonClass.hxx b/utils/fgai/HLABaloonClass.hxx new file mode 100644 index 000000000..67a30f66c --- /dev/null +++ b/utils/fgai/HLABaloonClass.hxx @@ -0,0 +1,46 @@ +// Copyright (C) 2009 - 2012 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#ifndef HLABaloonClass_hxx +#define HLABaloonClass_hxx + +#include "HLAAirVehicleClass.hxx" + +namespace fgai { + +class HLABaloonClass : public HLAAirVehicleClass { +public: + HLABaloonClass(const std::string& name, simgear::HLAFederate* federate); + virtual ~HLABaloonClass(); + + /// Create a new instance of this class. + virtual simgear::HLAObjectInstance* createObjectInstance(const std::string& name); + + virtual void createAttributeDataElements(simgear::HLAObjectInstance& objectInstance); + + // bool setSimTimeIndex(const std::string& path) + // { return getDataElementIndex(_simTimeIndex, path); } + // const simgear::HLADataElementIndex& getSimTimeIndex() const + // { return _simTimeIndex; } + +private: + // simgear::HLADataElementIndex _simTimeIndex; +}; + +} // namespace fgai + +#endif diff --git a/utils/fgai/HLAMPAircraft.cxx b/utils/fgai/HLAMPAircraft.cxx new file mode 100644 index 000000000..377283eed --- /dev/null +++ b/utils/fgai/HLAMPAircraft.cxx @@ -0,0 +1,50 @@ +// Copyright (C) 2009 - 2012 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "HLAMPAircraft.hxx" + +#include "HLAMPAircraftClass.hxx" + +namespace fgai { + +HLAMPAircraft::HLAMPAircraft(HLAMPAircraftClass* objectClass) : + HLASceneObject(objectClass) +{ +} + +HLAMPAircraft::~HLAMPAircraft() +{ +} + +void +HLAMPAircraft::createAttributeDataElements() +{ + HLASceneObject::createAttributeDataElements(); + + assert(dynamic_cast(getObjectClass().get())); + HLAMPAircraftClass& objectClass = static_cast(*getObjectClass()); + + setAttributeDataElement(objectClass.getModelPathIndex(), _modelPath.getDataElement()); + setAttributeDataElement(objectClass.getModelLiveryIndex(), _modelLivery.getDataElement()); + setAttributeDataElement(objectClass.getSimTimeIndex(), _simTime.getDataElement()); +} + +} // namespace fgai diff --git a/utils/fgai/HLAMPAircraft.hxx b/utils/fgai/HLAMPAircraft.hxx new file mode 100644 index 000000000..11adc231b --- /dev/null +++ b/utils/fgai/HLAMPAircraft.hxx @@ -0,0 +1,62 @@ +// Copyright (C) 2009 - 2012 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#ifndef HLAMPAircraft_hxx +#define HLAMPAircraft_hxx + +#include +#include "HLASceneObject.hxx" + +namespace fgai { + +class HLAMPAircraftClass; + +class HLAMPAircraft : public HLASceneObject { +public: + HLAMPAircraft(HLAMPAircraftClass* objectClass = 0); + virtual ~HLAMPAircraft(); + + virtual void createAttributeDataElements(); + + void setModelPath(const std::string& modelPath) + { _modelPath.setValue(modelPath); } + const std::string& getModelPath() const + { return _modelPath.getValue(); } + + void setModelLivery(const std::string& modelLivery) + { _modelLivery.setValue(modelLivery); } + const std::string& getModelLivery() const + { return _modelLivery.getValue(); } + + /// FIXME feed this by the simtime of the positon?! + void setSimTime(double simTime) + { _simTime.setValue(simTime); } + double getSimTime() const + { return _simTime.getValue(); } + +private: + // The model stuff + simgear::HLAStringData _modelPath; + simgear::HLAStringData _modelLivery; + + // The current simTime + simgear::HLADoubleData _simTime; +}; + +} // namespace fgai + +#endif diff --git a/utils/fgai/HLAMPAircraftClass.cxx b/utils/fgai/HLAMPAircraftClass.cxx new file mode 100644 index 000000000..106024d61 --- /dev/null +++ b/utils/fgai/HLAMPAircraftClass.cxx @@ -0,0 +1,56 @@ +// Copyright (C) 2009 - 2012 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "HLAMPAircraftClass.hxx" + +#include "HLAMPAircraft.hxx" + +namespace fgai { + +HLAMPAircraftClass::HLAMPAircraftClass(const std::string& name, simgear::HLAFederate* federate) : + HLASceneObjectClass(name, federate) +{ +} + +HLAMPAircraftClass::~HLAMPAircraftClass() +{ +} + +simgear::HLAObjectInstance* +HLAMPAircraftClass::createObjectInstance(const std::string&) +{ + return new HLAMPAircraft(this); +} + +void +HLAMPAircraftClass::createAttributeDataElements(simgear::HLAObjectInstance& objectInstance) +{ + /// FIXME resolve these indices somewhere else! + if (_modelPathIndex.empty()) + _modelPathIndex = getDataElementIndex("model.path"); + if (_modelLiveryIndex.empty()) + _modelLiveryIndex = getDataElementIndex("model.livery"); + if (_simTimeIndex.empty()) + _simTimeIndex = getDataElementIndex("simTime"); + HLASceneObjectClass::createAttributeDataElements(objectInstance); +} + +} // namespace fgai diff --git a/utils/fgai/HLAMPAircraftClass.hxx b/utils/fgai/HLAMPAircraftClass.hxx new file mode 100644 index 000000000..769806590 --- /dev/null +++ b/utils/fgai/HLAMPAircraftClass.hxx @@ -0,0 +1,59 @@ +// Copyright (C) 2009 - 2012 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#ifndef HLAMPAircraftClass_hxx +#define HLAMPAircraftClass_hxx + +#include "HLASceneObjectClass.hxx" + +namespace fgai { + +/// For compatibility with the old mp stuff??!! +class HLAMPAircraftClass : public HLASceneObjectClass { +public: + HLAMPAircraftClass(const std::string& name, simgear::HLAFederate* federate); + virtual ~HLAMPAircraftClass(); + + /// Create a new instance of this class. + virtual simgear::HLAObjectInstance* createObjectInstance(const std::string& name); + + virtual void createAttributeDataElements(simgear::HLAObjectInstance& objectInstance); + + bool setModelPathIndex(const std::string& path) + { return getDataElementIndex(_modelPathIndex, path); } + const simgear::HLADataElementIndex& getModelPathIndex() const + { return _modelPathIndex; } + + bool setModelLiveryIndex(const std::string& path) + { return getDataElementIndex(_modelLiveryIndex, path); } + const simgear::HLADataElementIndex& getModelLiveryIndex() const + { return _modelLiveryIndex; } + + bool setSimTimeIndex(const std::string& path) + { return getDataElementIndex(_simTimeIndex, path); } + const simgear::HLADataElementIndex& getSimTimeIndex() const + { return _simTimeIndex; } + +private: + simgear::HLADataElementIndex _modelPathIndex; + simgear::HLADataElementIndex _modelLiveryIndex; + simgear::HLADataElementIndex _simTimeIndex; +}; + +} // namespace fgai + +#endif diff --git a/utils/fgai/HLASceneObject.cxx b/utils/fgai/HLASceneObject.cxx new file mode 100644 index 000000000..83cd793f1 --- /dev/null +++ b/utils/fgai/HLASceneObject.cxx @@ -0,0 +1,126 @@ +// Copyright (C) 2009 - 2012 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "HLASceneObject.hxx" + +#include +#include "HLASceneObjectClass.hxx" +#include "AIPhysics.hxx" + +namespace fgai { + +class HLASceneObject::Location : public simgear::HLAAbstractLocation { +public: + Location() : + _position(SGVec3d::zeros()), + _imag(SGVec3d::zeros()), + _angularVelocity(SGVec3d::zeros()), + _linearVelocity(SGVec3d::zeros()) + { } + + virtual SGLocationd getLocation() const + { return SGLocationd(_position, SGQuatd::fromPositiveRealImag(_imag)); } + virtual void setLocation(const SGLocationd& location) + { + _position = location.getPosition(); + _imag = location.getOrientation().getPositiveRealImag(); + } + + virtual SGVec3d getCartPosition() const + { return _position; } + virtual void setCartPosition(const SGVec3d& position) + { _position = position; } + + virtual SGQuatd getCartOrientation() const + { return SGQuatd::fromPositiveRealImag(_imag); } + virtual void setCartOrientation(const SGQuatd& orientation) + { _imag = orientation.getPositiveRealImag(); } + + virtual SGVec3d getAngularBodyVelocity() const + { return _angularVelocity; } + virtual void setAngularBodyVelocity(const SGVec3d& angularVelocity) + { _angularVelocity = angularVelocity; } + + virtual SGVec3d getLinearBodyVelocity() const + { return _linearVelocity; } + virtual void setLinearBodyVelocity(const SGVec3d& linearVelocity) + { _linearVelocity = linearVelocity; } + + virtual double getTimeDifference(const SGTimeStamp& timeStamp) const + { return _position.getDataElement()->getTimeDifference(timeStamp); } + + simgear::HLADataElement* getPositionDataElement() + { return _position.getDataElement(); } + simgear::HLADataElement* getOrientationDataElement() + { return _imag.getDataElement(); } + + simgear::HLADataElement* getAngularVelocityDataElement() + { return _angularVelocity.getDataElement(); } + simgear::HLADataElement* getLinearVelocityDataElement() + { return _linearVelocity.getDataElement(); } + +private: + simgear::HLAVec3dData _position; + simgear::HLAVec3dData _imag; + + simgear::HLAVec3dData _angularVelocity; + simgear::HLAVec3dData _linearVelocity; +}; + + +HLASceneObject::HLASceneObject(HLASceneObjectClass* objectClass) : + HLAObjectInstance(objectClass) +{ +} + +HLASceneObject::~HLASceneObject() +{ +} + +void +HLASceneObject::createAttributeDataElements() +{ + /// FIXME at some point we should not need that anymore + HLAObjectInstance::createAttributeDataElements(); + + assert(dynamic_cast(getObjectClass().get())); + HLASceneObjectClass& objectClass = static_cast(*getObjectClass()); + + Location* location = new Location; + setAttributeDataElement(objectClass.getPositionIndex(), location->getPositionDataElement()); + setAttributeDataElement(objectClass.getOrientationIndex(), location->getOrientationDataElement()); + setAttributeDataElement(objectClass.getAngularVelocityIndex(), location->getAngularVelocityDataElement()); + setAttributeDataElement(objectClass.getLinearVelocityIndex(), location->getLinearVelocityDataElement()); + _location = location; +} + +void +HLASceneObject::setLocation(const AIPhysics& physics) +{ + if (!_location.valid()) + return; + /// In the long term do not just copy, but also decide how long to skip updates to the hla attributes ... + _location->setLocation(physics.getLocation()); + _location->setAngularBodyVelocity(physics.getAngularBodyVelocity()); + _location->setLinearBodyVelocity(physics.getLinearBodyVelocity()); +} + +} // namespace fgai diff --git a/utils/fgai/HLASceneObject.hxx b/utils/fgai/HLASceneObject.hxx new file mode 100644 index 000000000..aed2c1066 --- /dev/null +++ b/utils/fgai/HLASceneObject.hxx @@ -0,0 +1,47 @@ +// Copyright (C) 2009 - 2012 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#ifndef HLASceneObject_hxx +#define HLASceneObject_hxx + +#include +#include + +namespace fgai { + +class AIPhysics; +class HLASceneObjectClass; + +class HLASceneObject : public simgear::HLAObjectInstance { +public: + HLASceneObject(HLASceneObjectClass* objectClass = 0); + virtual ~HLASceneObject(); + + virtual void createAttributeDataElements(); + + void setLocation(const AIPhysics& physics); + +private: + /// Currently we have our own location. FIXME Extend Cartesian location at some point. + class Location; + // The location of this object + SGSharedPtr _location; +}; + +} // namespace fgai + +#endif diff --git a/utils/fgai/HLASceneObjectClass.cxx b/utils/fgai/HLASceneObjectClass.cxx new file mode 100644 index 000000000..333083b40 --- /dev/null +++ b/utils/fgai/HLASceneObjectClass.cxx @@ -0,0 +1,58 @@ +// Copyright (C) 2009 - 2012 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "HLASceneObjectClass.hxx" + +#include "HLASceneObject.hxx" + +namespace fgai { + +HLASceneObjectClass::HLASceneObjectClass(const std::string& name, simgear::HLAFederate* federate) : + HLAObjectClass(name, federate) +{ +} + +HLASceneObjectClass::~HLASceneObjectClass() +{ +} + +simgear::HLAObjectInstance* +HLASceneObjectClass::createObjectInstance(const std::string& name) +{ + return new HLASceneObject(this); +} + +void +HLASceneObjectClass::createAttributeDataElements(simgear::HLAObjectInstance& objectInstance) +{ + /// FIXME resolve these indices somewhere else! + if (_positionIndex.empty()) + _positionIndex = getDataElementIndex("location.position"); + if (_orientationIndex.empty()) + _orientationIndex = getDataElementIndex("location.orientation"); + if (_angularVelocityIndex.empty()) + _angularVelocityIndex = getDataElementIndex("velocity.angular"); + if (_linearVelocityIndex.empty()) + _linearVelocityIndex = getDataElementIndex("velocity.linear"); + HLAObjectClass::createAttributeDataElements(objectInstance); +} + +} // namespace fgai diff --git a/utils/fgai/HLASceneObjectClass.hxx b/utils/fgai/HLASceneObjectClass.hxx new file mode 100644 index 000000000..ef220d2d0 --- /dev/null +++ b/utils/fgai/HLASceneObjectClass.hxx @@ -0,0 +1,67 @@ +// Copyright (C) 2009 - 2012 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#ifndef HLASceneObjectClass_hxx +#define HLASceneObjectClass_hxx + +#include +#include + +namespace fgai { + +class HLASceneObjectClass : public simgear::HLAObjectClass { +public: + HLASceneObjectClass(const std::string& name, simgear::HLAFederate* federate); + virtual ~HLASceneObjectClass(); + + /// Create a new instance of this class. + virtual simgear::HLAObjectInstance* createObjectInstance(const std::string& name); + + virtual void createAttributeDataElements(simgear::HLAObjectInstance& objectInstance); + + bool setPositionIndex(const std::string& path) + { return getDataElementIndex(_positionIndex, path); } + const simgear::HLADataElementIndex& getPositionIndex() const + { return _positionIndex; } + + bool setOrientationIndex(const std::string& path) + { return getDataElementIndex(_orientationIndex, path); } + const simgear::HLADataElementIndex& getOrientationIndex() const + { return _orientationIndex; } + + bool setAngularVelocityIndex(const std::string& path) + { return getDataElementIndex(_angularVelocityIndex, path); } + const simgear::HLADataElementIndex& getAngularVelocityIndex() const + { return _angularVelocityIndex; } + + bool setLinearVelocityIndex(const std::string& path) + { return getDataElementIndex(_linearVelocityIndex, path); } + const simgear::HLADataElementIndex& getLinearVelocityIndex() const + { return _linearVelocityIndex; } + +private: + /// FIXME use a location factory for that?! + simgear::HLADataElementIndex _positionIndex; + simgear::HLADataElementIndex _orientationIndex; + + simgear::HLADataElementIndex _angularVelocityIndex; + simgear::HLADataElementIndex _linearVelocityIndex; +}; + +} // namespace fgai + +#endif diff --git a/utils/fgai/fgai.cxx b/utils/fgai/fgai.cxx new file mode 100644 index 000000000..f720b5dc3 --- /dev/null +++ b/utils/fgai/fgai.cxx @@ -0,0 +1,605 @@ +// Copyright (C) 2009 - 2012 Mathias Froehlich +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include "AIObject.hxx" +#include "AIManager.hxx" + +#include "HLAMPAircraft.hxx" +#include "HLAMPAircraftClass.hxx" +#include "AIPhysics.hxx" + +namespace fgai { + +#if 0 +class AIVehiclePhysics : public AIPhysics { +public: + AIVehiclePhysics(const SGLocationd& location, const SGVec3d& linearBodyVelocity = SGVec3d::zeros(), + const SGVec3d& angularBodyVelocity = SGVec3d::zeros()) : + AIPhysics(location, linearBodyVelocity, angularBodyVelocity) + { + setMass(1); + setInertia(1, 1, 1); + } + virtual ~AIVehiclePhysics() + { } + + double getMass() const + { return _mass; } + void setMass(double mass) + { _mass = mass; } + + void setInertia(double ixx, double iyy, double izz, double ixy = 0, double ixz = 0, double iyz = 0) + { + _inertia = SGMatrixd(ixx, ixy, ixz, 0, + ixy, iyy, iyz, 0, + ixz, iyz, izz, 0, + 0, 0, 0, 1); + invert(_inertiaInverse, _inertia); + } + +protected: + void advanceByBodyForce(const double& dt, + const SGVec3d& force, + const SGVec3d& torque) + { + SGVec3d linearVelocity = getLinearBodyVelocity(); + SGVec3d angularVelocity = getAngularBodyVelocity(); + + SGVec3d linearAcceleration = (1/_mass)*(force - cross(angularVelocity, linearVelocity)); + SGVec3d angularAcceleration = _inertiaInverse.xformVec(torque - cross(angularVelocity, _inertia.xformVec(angularVelocity))); + + advanceByBodyAcceleration(dt, linearAcceleration, angularAcceleration); + } + + SGVec3d getGravityAcceleration() const + { + return SGQuatd::fromLonLat(getGeodPosition()).backTransform(SGVec3d(0, 0, 9.81)); + } + +private: + // unsimulated motion, hide this for this kind of class here + using AIPhysics::advanceByBodyAcceleration; + using AIPhysics::advanceByBodyVelocity; + using AIPhysics::advanceToCartPosition; + + double _mass; + // FIXME this is a symmetric 3x3 matrix ... + SGMatrixd _inertia; + SGMatrixd _inertiaInverse; +}; + +// FIXME Totally unfinished simple aerodynamics model for an ai aircraft +// also just here for a sketch of an idea +class AIAircraftPhysics : public AIVehiclePhysics { +public: + AIAircraftPhysics(const SGLocationd& location, const SGVec3d& linearBodyVelocity = SGVec3d::zeros(), + const SGVec3d& angularBodyVelocity = SGVec3d::zeros()) : + AIVehiclePhysics(location, linearBodyVelocity, angularBodyVelocity) + { } + virtual ~AIAircraftPhysics() + { } + + double getElevatorPosition() const + { return _elevatorPosition; } + void setElevatorPosition(double elevatorPosition) + { _elevatorPosition = elevatorPosition; } + + double getAileronPosition() const + { return _aileronPosition; } + void setAileronPosition(double aileronPosition) + { _aileronPosition = aileronPosition; } + + double getRudderPosition() const + { return _rudderPosition; } + void setRudderPosition(double rudderPosition) + { _rudderPosition = rudderPosition; } + + // double getFlapsPosition() const + // { return _flapsPosition; } + // void setFlapsPosition(double flapsPosition) + // { _flapsPosition = flapsPosition; } + + double getThrust() const + { return _thrust; } + void setThrust(double thrust) + { _thrust = thrust; } + + virtual void update(AIObject& object, const SGTimeStamp& dt) + { + // const AIEnvironment& environment = object.getEnvironment(); + const AIEnvironment environment; + + /// Compute the forces on the aircraft. This is a very simple fdm. + + // The velocity of the aircraft wrt the surrounding fluid + SGVec3d windVelocity = getLinearBodyVelocity(); + windVelocity -= getOrientation().transform(environment.getWindVelocity()); + + // The true airspeed of the bird + double airSpeed = norm(windVelocity); + // simple density with(out FIXME) altitude + double density = environment.getDensity(); + // The dynaimc pressure - most important value in aerodynamics + double dynamicPressure = 0.5*density*airSpeed*airSpeed; + + // The angle of attack and sideslip angle + double alpha = 0, beta = 0; + if (1e-3 < SGMiscd::max(fabs(windVelocity[0]), fabs(windVelocity[2]))) + alpha = atan2(windVelocity[2], windVelocity[0]); + double uw = sqrt(windVelocity[0]*windVelocity[0] + windVelocity[2]*windVelocity[2]); + if (1e-3 < SGMiscd::max(fabs(windVelocity[1]), fabs(uw))) + beta = atan2(windVelocity[1], uw); + // Transform from the stability axis to body axis + SGQuatd stabilityToBody = SGQuatd::fromEulerRad(beta, alpha, 0); + + // We assume a simple angular dependency for the + // lift, drag and side force coefficients. + + // lift for alpha = 0 + double _Cl0 = 0.5; + // lift at stall angle of attack + double _ClStall = 2; + // stall angle of attack + double _alphaStall = 18; + // Drag for alpha = 0 + double _Cd0 = 0.05; + // Drag for alpha = 90 + double _Cd90 = 1.05; + // Side force coefficient for maximum side angle + double _Cs90 = 1.05; + + /// FIXME + double _area = 1; + SGVec3d _aerodynamicReferencePoint(0, 0, 0); + SGVec3d _centerOfGravity(0, 0, 0); + + // So compute the lift drag and side force coefficient for the + // current stream conditions. + double Cl = _Cl0 + (_ClStall - _Cl0)*sin(SGMiscd::clip(90/_alphaStall*alpha, -0.5*SGMiscd::pi(), SGMiscd::pi())); + double Cd = _Cd0 + (_Cd90 - _Cd0)*(0.5 - 0.5*cos(2*alpha)); + double Cs = _Cs90*sin(beta); + + // Forces in the stability axes + double lift = Cl*dynamicPressure*_area; + double drag = Cd*dynamicPressure*_area; + double side = Cs*dynamicPressure*_area; + + // Torque in body axes + double p = 0; + double q = 0; + double r = 0; + + // Compute the force in stability coordinates ... + SGVec3d stabilityForce(-drag, side, -lift); + // ... and torque in body coordinates + SGVec3d torque(p, q, r); + + SGVec3d force = stabilityToBody.transform(stabilityForce); + torque += cross(force, _aerodynamicReferencePoint); + + std::pair velocity; + for (_GearVector::iterator i = _gearVector.begin(); i != _gearVector.end(); ++i) { + std::pair torqueForce; + torqueForce = i->force(getLocation(), velocity, object); + torque += torqueForce.first; + force += torqueForce.second; + } + + // Transform the torque back to the center of gravity + torque -= cross(force, _centerOfGravity); + + // Advance the equations of motion. + advanceByBodyForce(dt.toSecs(), force, torque); + } + + /// The normalized elevator position + double _elevatorPosition; + /// The normalized aileron position + double _aileronPosition; + /// The normalized rudder position + double _rudderPosition; + // /// The normalized flaps position + // double _flapsPosition; + /// Normalized thrust + double _thrust; + + struct _Gear { + SGVec3d _position; + SGVec3d _direction; + double _spring; + double _damping; + + std::pair + force(const SGLocationd& location, const std::pair& velocity, AIObject& object) + { + SGVec3d start = location.getAbsolutePosition(_position - _direction); + SGVec3d end = location.getAbsolutePosition(_position); + SGLineSegmentd lineSegment(start, end); + + SGVec3d point; + SGVec3d normal; + // if (!object.getGroundIntersection(point, normal, lineSegment)) + // return std::pair(SGVec3d(0, 0, 0), SGVec3d(0, 0, 0)); + + // FIXME just now only the spring force ... + + // The compression length + double compressLength = norm(point - start); + SGVec3d springForce = -_spring*compressLength*_direction; + + SGVec3d dampingForce(0, 0, 0); + + SGVec3d force = springForce + dampingForce; + SGVec3d torque(0, 0, 0); + + return std::pair(torque, force); + } + }; + + typedef std::vector<_Gear> _GearVector; + _GearVector _gearVector; + + /// The total mass of the bird in kg. No fluel is burned. + /// Some sensible inertia values are derived from the mass. + // double _mass; + /// The thrust to mass ratio which tells us someting about + /// the possible accelerations. + // double _thrustMassRatio; + + /// The stall speed + // double _stallSpeed; + // double _maximumSpeed; + // // double _approachSpeed; + // // double _takeoffSpeed; + // // double _cruiseSpeed; + /// The maximum density altitude this aircraft can fly + // double _densityAltitudeLimit; + + /// statistical evaluation shows: + /// wingarea = C*wingspan^2, C in [0.1, 0.4], say 0.2 + /// ixx = C*wingarea*mass, C in [1e-3, 1e-2] + /// iyy = C*wingarea*mass, C in [1e-2, 0.02] + /// izz = C*wingarea*mass, C in [1e-2, 0.02] + /// Hmm, let's say, weight relates to wingarea? + /// probably, since lift is linear dependent on wingarea + + /// So, define a 'size' in meters. + /// the derive + /// wingspan = size + /// wingarea = 0.2*size*size + /// mass = C*wingarea + /// ixx = 0.005*wingarea*mass + /// iyy = 0.05*wingarea*mass + /// izz = 0.05*wingarea*mass + + + /// an other idea: + /// define a bird of some weight class. That means mass given. + /// Then derive + /// i* ??? must be mass^2 accodring to the thoughts above + /// Then do Cl, Cd, Cs. + /// according to approach speed at sea level with 5 deg aoa and 2,5 deg glideslope and 25 % thrust. + /// according to cruise altitude and cruise speed at 75% thrust compute this at altitude + /// interpolate between these two sets of C*'s based on altitude. +}; +#endif + +/// An automated lego aircraft, constant linear and angular speed +class AIOgel : public AIObject { +public: + AIOgel(const SGGeod& geod) : + _geod(geod), + _radius(500), + _turnaroundTime(3*60), + _velocity(10) + { } + virtual ~AIOgel() + { } + + virtual void init(AIManager& manager) + { + AIObject::init(manager); + + SGLocationd location(SGVec3d::fromGeod(_geod), SGQuatd::fromLonLat(_geod)); + SGVec3d linearVelocity(_velocity, 0, 0); + SGVec3d angularVelocity(0, 0, SGMiscd::twopi()/_turnaroundTime); + setPhysics(new AIPhysics(location, linearVelocity, angularVelocity)); + + HLAMPAircraftClass* objectClass = dynamic_cast(manager.getObjectClass("MPAircraft")); + if (!objectClass) + return; + _objectInstance = new HLAMPAircraft(objectClass); + if (!_objectInstance.valid()) + return; + _objectInstance->registerInstance(); + _objectInstance->setModelPath("Aircraft/ogel/Models/SinglePiston.xml"); + + manager.schedule(*this, getSimTime() + SGTimeStamp::fromSecMSec(0, 1)); + } + + virtual void update(AIManager& manager, const SGTimeStamp& simTime) + { + SGTimeStamp dt = simTime - getSimTime(); + + setGroundCache(getPhysics(), manager.getPager(), dt); + getEnvironment().update(*this, dt); + getSubsystemGroup().update(*this, dt); + getPhysics().update(*this, dt); + + AIObject::update(manager, simTime); + + if (!_objectInstance.valid()) + return; + + _objectInstance->setLocation(getPhysics()); + _objectInstance->setSimTime(getSimTime().toSecs()); + _objectInstance->updateAttributeValues(getSimTime(), simgear::RTIData("update")); + + manager.schedule(*this, getSimTime() + SGTimeStamp::fromSecMSec(0, 100)); + } + + virtual void shutdown(AIManager& manager) + { + if (_objectInstance.valid()) + _objectInstance->removeInstance(simgear::RTIData("shutdown")); + _objectInstance = 0; + AIObject::shutdown(manager); + } + +private: + SGGeod _geod; + double _radius; + double _turnaroundTime; + double _velocity; + SGSharedPtr _objectInstance; +}; + +/// an ogle in a traffic circuit at lowi +class AIOgelInTrafficCircuit : public AIObject { +public: + /// Also nothing to really use for a long time, but to demonstrate how it basically works + class Physics : public AIPhysics { + public: + Physics(const SGLocationd& location, const SGVec3d& linearBodyVelocity = SGVec3d::zeros(), + const SGVec3d& angularBodyVelocity = SGVec3d::zeros()) : + AIPhysics(location, linearBodyVelocity, angularBodyVelocity), + _targetVelocity(30), + _gearOffset(2.5) + { } + virtual ~Physics() + { } + + virtual void update(AIObject& object, const SGTimeStamp& dt) + { + SGVec3d down = getHorizontalLocalOrientation().backTransform(SGVec3d(0, 0, 1)); + SGVec3d distToAimingPoint = getAimingPoint() - getPosition(); + if (norm(distToAimingPoint - down*dot(down, distToAimingPoint)) <= 10*dt.toSecs()*norm(getLinearVelocity())) + rotateAimingPoint(); + + SGVec3d aimingVector = normalize(getAimingPoint() - getPosition()); + SGVec3d bodyAimingVector = getLocation().getOrientation().transform(aimingVector); + + SGVec3d angularVelocity = 0.2*cross(SGVec3d(1, 0, 0), bodyAimingVector); + SGVec3d bodyDownVector = getLocation().getOrientation().transform(down); + // keep an upward orientation + angularVelocity += cross(SGVec3d(0, 0, 1), SGVec3d(0, bodyDownVector[1], bodyDownVector[2])); + + SGVec3d linearVelocity(_targetVelocity, 0, 0); + + SGVec3d gearPosition = getPosition() + _gearOffset*down; + SGLineSegmentd lineSegment(gearPosition - 10*down, gearPosition + 10*down); + SGVec3d point, normal; + if (object.getGroundIntersection(point, normal, lineSegment)) { + double agl = dot(down, point - gearPosition); + if (agl < 0) + linearVelocity -= down*(0.5*agl/dt.toSecs()); + } + + advanceByBodyVelocity(dt.toSecs(), linearVelocity, angularVelocity); + } + + const SGVec3d& getAimingPoint() const + { return _waypoints.front(); } + void rotateAimingPoint() + { _waypoints.splice(_waypoints.end(), _waypoints, _waypoints.begin()); } + + std::list _waypoints; + double _targetVelocity; + double _gearOffset; + }; + + AIOgelInTrafficCircuit() + { } + virtual ~AIOgelInTrafficCircuit() + { } + + virtual void init(AIManager& manager) + { + AIObject::init(manager); + + /// Put together somw waypoints + /// This needs to be replaced by something generic + SGGeod rwyStart = SGGeod::fromDegM(11.35203755, 47.26109606, 574); + SGGeod rwyEnd = SGGeod::fromDegM(11.33741688, 47.25951967, 576); + SGQuatd hl = SGQuatd::fromLonLat(rwyStart); + SGVec3d down = hl.backTransform(SGVec3d(0, 0, 1)); + + SGVec3d cartRwyStart = SGVec3d::fromGeod(rwyStart); + SGVec3d cartRwyEnd = SGVec3d::fromGeod(rwyEnd); + + SGVec3d centerline = normalize(cartRwyEnd - cartRwyStart); + SGVec3d left = normalize(cross(centerline, down)); + + SGGeod endClimb = SGGeod::fromGeodM(SGGeod::fromCart(cartRwyEnd + 500*centerline), 700); + SGGeod startDescend = SGGeod::fromGeodM(SGGeod::fromCart(cartRwyStart - 500*centerline + 150*left), 650); + + SGGeod startDownwind = SGGeod::fromGeodM(SGGeod::fromCart(cartRwyEnd + 500*centerline + 800*left), 750); + SGGeod endDownwind = SGGeod::fromGeodM(SGGeod::fromCart(cartRwyStart - 500*centerline + 800*left), 750); + + SGLocationd location(SGVec3d::fromGeod(rwyStart), SGQuatd::fromLonLat(rwyStart)*SGQuatd::fromEulerDeg(-100, 0, 0)); + Physics* physics = new Physics(location, SGVec3d(0, 0, 0), SGVec3d(0, 0, 0)); + physics->_waypoints.push_back(SGVec3d::fromGeod(rwyStart)); + physics->_waypoints.push_back(SGVec3d::fromGeod(rwyEnd)); + physics->_waypoints.push_back(SGVec3d::fromGeod(endClimb)); + physics->_waypoints.push_back(SGVec3d::fromGeod(startDownwind)); + physics->_waypoints.push_back(SGVec3d::fromGeod(endDownwind)); + physics->_waypoints.push_back(SGVec3d::fromGeod(startDescend)); + setPhysics(physics); + + /// Ok, this is part of the official sketch + HLAMPAircraftClass* objectClass = dynamic_cast(manager.getObjectClass("MPAircraft")); + if (!objectClass) + return; + _objectInstance = new HLAMPAircraft(objectClass); + if (!_objectInstance.valid()) + return; + _objectInstance->registerInstance(); + _objectInstance->setModelPath("Aircraft/ogel/Models/SinglePiston.xml"); + + /// Need to schedule something else we get deleted + manager.schedule(*this, getSimTime() + SGTimeStamp::fromSecMSec(0, 100)); + } + + virtual void update(AIManager& manager, const SGTimeStamp& simTime) + { + SGTimeStamp dt = simTime - getSimTime(); + + setGroundCache(getPhysics(), manager.getPager(), dt); + getEnvironment().update(*this, dt); + getSubsystemGroup().update(*this, dt); + getPhysics().update(*this, dt); + + AIObject::update(manager, simTime); + + if (!_objectInstance.valid()) + return; + + _objectInstance->setLocation(getPhysics()); + _objectInstance->setSimTime(getSimTime().toSecs()); + _objectInstance->updateAttributeValues(getSimTime(), simgear::RTIData("update")); + + /// Need to schedule something else we get deleted + manager.schedule(*this, getSimTime() + SGTimeStamp::fromSecMSec(0, 100)); + } + + virtual void shutdown(AIManager& manager) + { + if (_objectInstance.valid()) + _objectInstance->removeInstance(simgear::RTIData("shutdown")); + _objectInstance = 0; + + AIObject::shutdown(manager); + } + +private: + SGSharedPtr _objectInstance; +}; + +} // namespace fgai + +// getopt +#include + +int +main(int argc, char* argv[]) +{ + SGSharedPtr manager = new fgai::AIManager; + + /// FIXME include some argument parsing stuff + std::string fg_root; + std::string fg_scenery; + + int c; + while ((c = getopt(argc, argv, "cCf:F:n:O:p:RsS")) != EOF) { + switch (c) { + case 'c': + manager->setCreateFederationExecution(true); + break; + case 'C': + manager->setTimeConstrained(true); + break; + case 'f': + manager->setFederateType(optarg); + break; + case 'F': + manager->setFederationExecutionName(optarg); + break; + case 'O': + manager->setFederationObjectModel(optarg); + break; + case 'p': + logbuf::set_log_classes(SG_ALL); + logbuf::set_log_priority(sgDebugPriority(atoi(optarg))); + break; + case 'R': + manager->setTimeRegulating(true); + break; + case 's': + manager->setTimeConstrainedByLocalClock(false); + break; + case 'S': + manager->setTimeConstrainedByLocalClock(true); + break; + case 'r': + fg_root = optarg; + break; + case 'y': + fg_scenery = optarg; + break; + } + } + + if (fg_root.empty()) { + if (const char *fg_root_env = std::getenv("FG_ROOT")) { + fg_root = fg_root_env; + } else { + fg_root = PKGLIBDIR; + } + } + if (fg_scenery.empty()) { + if (const char *fg_scenery_env = std::getenv("FG_SCENERY")) { + fg_scenery = fg_scenery_env; + } else if (!fg_root.empty()) { + SGPath path(fg_root); + path.append("Scenery"); + fg_scenery = path.str(); + } + } + + manager->getPager().setScenery(fg_root, fg_scenery); + + if (manager->getFederationObjectModel().empty()) { + SGPath path(fg_root); + path.append("HLA"); + path.append("fg-local-fom.xml"); + manager->setFederationObjectModel(path.str()); + } + + /// EDDS + manager->insert(new fgai::AIOgel(SGGeod::fromDegFt(9.19298, 48.6895, 2000))); + /// LOWI + manager->insert(new fgai::AIOgel(SGGeod::fromDegFt(11.344, 47.260, 2500))); + /// LOWI traffic circuit + manager->insert(new fgai::AIOgelInTrafficCircuit); + + return manager->exec(); +}