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)
--- /dev/null
+// 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
--- /dev/null
+// 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
--- /dev/null
+// 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
--- /dev/null
+// 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
--- /dev/null
+// 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
--- /dev/null
+// 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
--- /dev/null
+// 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
--- /dev/null
+// 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
--- /dev/null
+// 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
--- /dev/null
+// 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
--- /dev/null
+// 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
--- /dev/null
+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)
--- /dev/null
+// 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
--- /dev/null
+// 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
--- /dev/null
+// 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
--- /dev/null
+// 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
--- /dev/null
+// 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
--- /dev/null
+// 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
--- /dev/null
+// 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
--- /dev/null
+// 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
--- /dev/null
+// 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
--- /dev/null
+// 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
--- /dev/null
+// 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
--- /dev/null
+// 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
--- /dev/null
+// 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
--- /dev/null
+// 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
--- /dev/null
+// 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
--- /dev/null
+// 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
--- /dev/null
+// 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
--- /dev/null
+// 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
--- /dev/null
+// 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
--- /dev/null
+// 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
--- /dev/null
+// 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();
+}