]> git.mxchange.org Git - flightgear.git/commitdiff
fgai: Add an initial sketch of an external ai module.
authorMathias Froehlich <Mathias.Froehlich@web.de>
Sat, 24 Nov 2012 09:34:08 +0000 (10:34 +0100)
committerMathias Froehlich <Mathias.Froehlich@web.de>
Sat, 24 Nov 2012 09:34:08 +0000 (10:34 +0100)
34 files changed:
utils/CMakeLists.txt
utils/fgai/AIBVHPager.cxx [new file with mode: 0644]
utils/fgai/AIBVHPager.hxx [new file with mode: 0644]
utils/fgai/AIEnvironment.cxx [new file with mode: 0644]
utils/fgai/AIEnvironment.hxx [new file with mode: 0644]
utils/fgai/AIManager.cxx [new file with mode: 0644]
utils/fgai/AIManager.hxx [new file with mode: 0644]
utils/fgai/AIObject.cxx [new file with mode: 0644]
utils/fgai/AIObject.hxx [new file with mode: 0644]
utils/fgai/AIPhysics.cxx [new file with mode: 0644]
utils/fgai/AIPhysics.hxx [new file with mode: 0644]
utils/fgai/AISubsystem.hxx [new file with mode: 0644]
utils/fgai/CMakeLists.txt [new file with mode: 0644]
utils/fgai/HLAAirVehicle.cxx [new file with mode: 0644]
utils/fgai/HLAAirVehicle.hxx [new file with mode: 0644]
utils/fgai/HLAAirVehicleClass.cxx [new file with mode: 0644]
utils/fgai/HLAAirVehicleClass.hxx [new file with mode: 0644]
utils/fgai/HLAAircraft.cxx [new file with mode: 0644]
utils/fgai/HLAAircraft.hxx [new file with mode: 0644]
utils/fgai/HLAAircraftClass.cxx [new file with mode: 0644]
utils/fgai/HLAAircraftClass.hxx [new file with mode: 0644]
utils/fgai/HLABaloon.cxx [new file with mode: 0644]
utils/fgai/HLABaloon.hxx [new file with mode: 0644]
utils/fgai/HLABaloonClass.cxx [new file with mode: 0644]
utils/fgai/HLABaloonClass.hxx [new file with mode: 0644]
utils/fgai/HLAMPAircraft.cxx [new file with mode: 0644]
utils/fgai/HLAMPAircraft.hxx [new file with mode: 0644]
utils/fgai/HLAMPAircraftClass.cxx [new file with mode: 0644]
utils/fgai/HLAMPAircraftClass.hxx [new file with mode: 0644]
utils/fgai/HLASceneObject.cxx [new file with mode: 0644]
utils/fgai/HLASceneObject.hxx [new file with mode: 0644]
utils/fgai/HLASceneObjectClass.cxx [new file with mode: 0644]
utils/fgai/HLASceneObjectClass.hxx [new file with mode: 0644]
utils/fgai/fgai.cxx [new file with mode: 0644]

index 70d89a487f8fa0bb609da7921e36682647605a06..f176e749f846949492db6d4e2cc50ac3515f05a7 100644 (file)
@@ -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 (file)
index 0000000..a5cc139
--- /dev/null
@@ -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 <config.h>
+#endif
+
+#include "AIBVHPager.hxx"
+
+#include <simgear/bvh/BVHPageNode.hxx>
+#include <simgear/bvh/BVHSubTreeCollector.hxx>
+#include <simgear/misc/sg_path.hxx>
+#include <simgear/misc/ResourceManager.hxx>
+#include <simgear/props/props.hxx>
+#include <simgear/props/props_io.hxx>
+#include <simgear/scene/material/matlib.hxx>
+#include <simgear/scene/model/BVHPageNodeOSG.hxx>
+#include <simgear/scene/model/ModelRegistry.hxx>
+#include <simgear/scene/util/SGReaderWriterOptions.hxx>
+#include <simgear/scene/util/OptionsReadFileCallback.hxx>
+#include <simgear/scene/tgdb/userdata.hxx>
+
+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<SGPropertyNode> 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<simgear::SGReaderWriterOptions> 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<simgear::BVHNode>
+AIBVHPager::getBoundingVolumes(const SGSphered& sphere)
+{
+    if (!_node.valid())
+        return SGSharedPtr<simgear::BVHNode>();
+    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 (file)
index 0000000..2da3e22
--- /dev/null
@@ -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 <string>
+#include <simgear/bvh/BVHNode.hxx>
+#include <simgear/bvh/BVHPager.hxx>
+
+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<simgear::BVHNode> getBoundingVolumes(const SGSphered& sphere);
+
+private:
+    class ReadFileCallback;
+    class SubTreeCollector;
+
+    /// The possibly paged root node
+    SGSharedPtr<simgear::BVHNode> _node;
+};
+
+} // namespace fgai
+
+#endif
diff --git a/utils/fgai/AIEnvironment.cxx b/utils/fgai/AIEnvironment.cxx
new file mode 100644 (file)
index 0000000..e74ebbc
--- /dev/null
@@ -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 <config.h>
+#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 (file)
index 0000000..3e482ff
--- /dev/null
@@ -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 <simgear/bvh/BVHNode.hxx>
+#include <simgear/math/SGGeometry.hxx>
+#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 (file)
index 0000000..c1ee6ef
--- /dev/null
@@ -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 <config.h>
+#endif
+
+#include "AIManager.hxx"
+
+#include <cassert>
+
+#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<AIObject> 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<AIObject>& 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 (file)
index 0000000..a9c1973
--- /dev/null
@@ -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 <simgear/hla/HLAFederate.hxx>
+#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>& 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<SGSharedPtr<AIObject> > ObjectList;
+    /// For the schedule of the next update of an ai object
+    typedef std::map<SGTimeStamp, ObjectList> TimeStampObjectListMap;
+
+    typedef std::map<SGTimeStamp, ObjectList::iterator> 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 (file)
index 0000000..06d42c2
--- /dev/null
@@ -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 <config.h>
+#endif
+
+#include "AIObject.hxx"
+
+#include <simgear/bvh/BVHLineSegmentVisitor.hxx>
+#include <simgear/bvh/BVHNode.hxx>
+#include <simgear/math/SGGeometry.hxx>
+
+#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 (file)
index 0000000..f5f68a4
--- /dev/null
@@ -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 <list>
+#include <string>
+#include <simgear/math/SGGeometry.hxx>
+#include <simgear/structure/SGWeakReferenced.hxx>
+#include <simgear/timing/timestamp.hxx>
+
+#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<AIEnvironment> _environment;
+    SGSharedPtr<AISubsystemGroup> _subsystemGroup;
+    SGSharedPtr<AIPhysics> _physics;
+
+    /// The equivalent of the ground cache for FGInterface.
+    SGSharedPtr<simgear::BVHNode> _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 (file)
index 0000000..c60e79e
--- /dev/null
@@ -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 <config.h>
+#endif
+
+#include "AIPhysics.hxx"
+
+#include <simgear/math/SGGeometry.hxx>
+#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 (file)
index 0000000..57497a1
--- /dev/null
@@ -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 <simgear/math/SGMath.hxx>
+#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 (file)
index 0000000..a643bc1
--- /dev/null
@@ -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 <list>
+#include <simgear/structure/SGWeakReferenced.hxx>
+#include <simgear/timing/timestamp.hxx>
+
+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<SGSharedPtr<AISubsystem> > SubsystemList;
+    SubsystemList _subsystemList;
+};
+
+} // namespace fgai
+
+#endif
diff --git a/utils/fgai/CMakeLists.txt b/utils/fgai/CMakeLists.txt
new file mode 100644 (file)
index 0000000..3b234a4
--- /dev/null
@@ -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 (file)
index 0000000..3ebea91
--- /dev/null
@@ -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 <config.h>
+#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<HLAAirVehicleClass*>(getObjectClass().get()));
+    HLAAirVehicleClass& objectClass = static_cast<HLAAirVehicleClass&>(*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 (file)
index 0000000..956ad85
--- /dev/null
@@ -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 <simgear/hla/HLAArrayDataElement.hxx>
+#include <simgear/hla/HLABasicDataElement.hxx>
+#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 (file)
index 0000000..b3e6b7f
--- /dev/null
@@ -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 <config.h>
+#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 (file)
index 0000000..520bb6e
--- /dev/null
@@ -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 (file)
index 0000000..ff6b9ec
--- /dev/null
@@ -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 <config.h>
+#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<HLAAircraftClass*>(getObjectClass().get()));
+    HLAAircraftClass& objectClass = static_cast<HLAAircraftClass&>(*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 (file)
index 0000000..0671ed3
--- /dev/null
@@ -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 <simgear/hla/HLAArrayDataElement.hxx>
+#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 (file)
index 0000000..57f9257
--- /dev/null
@@ -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 <config.h>
+#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 (file)
index 0000000..2592218
--- /dev/null
@@ -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 (file)
index 0000000..698c8e8
--- /dev/null
@@ -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 <config.h>
+#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<HLABaloonClass*>(getObjectClass().get()));
+    HLABaloonClass& objectClass = static_cast<HLABaloonClass&>(*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 (file)
index 0000000..2f33b61
--- /dev/null
@@ -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 (file)
index 0000000..1fb2975
--- /dev/null
@@ -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 <config.h>
+#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 (file)
index 0000000..67a30f6
--- /dev/null
@@ -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 (file)
index 0000000..377283e
--- /dev/null
@@ -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 <config.h>
+#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<HLAMPAircraftClass*>(getObjectClass().get()));
+    HLAMPAircraftClass& objectClass = static_cast<HLAMPAircraftClass&>(*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 (file)
index 0000000..11adc23
--- /dev/null
@@ -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 <simgear/hla/HLAArrayDataElement.hxx>
+#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 (file)
index 0000000..106024d
--- /dev/null
@@ -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 <config.h>
+#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 (file)
index 0000000..7698065
--- /dev/null
@@ -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 (file)
index 0000000..83cd793
--- /dev/null
@@ -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 <config.h>
+#endif
+
+#include "HLASceneObject.hxx"
+
+#include <simgear/hla/HLAArrayDataElement.hxx>
+#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<HLASceneObjectClass*>(getObjectClass().get()));
+    HLASceneObjectClass& objectClass = static_cast<HLASceneObjectClass&>(*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 (file)
index 0000000..aed2c10
--- /dev/null
@@ -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 <simgear/hla/HLAObjectClass.hxx>
+#include <simgear/hla/HLALocation.hxx>
+
+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<simgear::HLAAbstractLocation> _location;
+};
+
+} // namespace fgai
+
+#endif
diff --git a/utils/fgai/HLASceneObjectClass.cxx b/utils/fgai/HLASceneObjectClass.cxx
new file mode 100644 (file)
index 0000000..333083b
--- /dev/null
@@ -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 <config.h>
+#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 (file)
index 0000000..ef220d2
--- /dev/null
@@ -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 <string>
+#include <simgear/hla/HLAObjectClass.hxx>
+
+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 (file)
index 0000000..f720b5d
--- /dev/null
@@ -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 <config.h>
+#endif
+
+#include <simgear/misc/sg_path.hxx>
+
+#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<SGVec3d, SGVec3d> velocity;
+        for (_GearVector::iterator i = _gearVector.begin(); i != _gearVector.end(); ++i) {
+            std::pair<SGVec3d, SGVec3d> 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<SGVec3d, SGVec3d>
+        force(const SGLocationd& location, const std::pair<SGVec3d, SGVec3d>& 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, SGVec3d>(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<SGVec3d, SGVec3d>(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<HLAMPAircraftClass*>(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<HLAMPAircraft> _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<SGVec3d> _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<HLAMPAircraftClass*>(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<HLAMPAircraft> _objectInstance;
+};
+
+} // namespace fgai
+
+// getopt
+#include <unistd.h>
+
+int
+main(int argc, char* argv[])
+{
+    SGSharedPtr<fgai::AIManager> 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();
+}