From cd0c447b43bf9f7ea2e11a1e8914efc3b0516158 Mon Sep 17 00:00:00 2001 From: ehofman Date: Fri, 28 Nov 2003 15:48:05 +0000 Subject: [PATCH] Add David Culp's AI model manager code which is derived from David Luff's AI/ATC code. --- configure.ac | 1 + src/AIModel/.cvsignore | 3 + src/AIModel/AIAircraft.cxx | 202 ++++++++++++++++++++++++++++++++++++ src/AIModel/AIAircraft.hxx | 62 +++++++++++ src/AIModel/AIBallistic.cxx | 117 +++++++++++++++++++++ src/AIModel/AIBallistic.hxx | 51 +++++++++ src/AIModel/AIBase.cxx | 97 +++++++++++++++++ src/AIModel/AIBase.hxx | 74 +++++++++++++ src/AIModel/AIManager.cxx | 127 +++++++++++++++++++++++ src/AIModel/AIManager.hxx | 80 ++++++++++++++ src/AIModel/AIShip.cxx | 153 +++++++++++++++++++++++++++ src/AIModel/AIShip.hxx | 54 ++++++++++ src/AIModel/Makefile.am | 10 ++ src/GUI/AirportList.cxx | 2 + src/Main/Makefile.am | 1 + src/Main/fg_init.cxx | 9 ++ src/Makefile.am | 1 + 17 files changed, 1044 insertions(+) create mode 100644 src/AIModel/.cvsignore create mode 100644 src/AIModel/AIAircraft.cxx create mode 100644 src/AIModel/AIAircraft.hxx create mode 100644 src/AIModel/AIBallistic.cxx create mode 100644 src/AIModel/AIBallistic.hxx create mode 100644 src/AIModel/AIBase.cxx create mode 100644 src/AIModel/AIBase.hxx create mode 100644 src/AIModel/AIManager.cxx create mode 100644 src/AIModel/AIManager.hxx create mode 100644 src/AIModel/AIShip.cxx create mode 100644 src/AIModel/AIShip.hxx create mode 100644 src/AIModel/Makefile.am diff --git a/configure.ac b/configure.ac index aa39e3591..21050c09c 100644 --- a/configure.ac +++ b/configure.ac @@ -505,6 +505,7 @@ AC_CONFIG_FILES([ \ src/Main/runfgfs \ src/Main/runfgfs.bat \ src/Model/Makefile \ + src/AIModel/Makefile \ src/MultiPlayer/Makefile \ src/Navaids/Makefile \ src/Network/Makefile \ diff --git a/src/AIModel/.cvsignore b/src/AIModel/.cvsignore new file mode 100644 index 000000000..e99558847 --- /dev/null +++ b/src/AIModel/.cvsignore @@ -0,0 +1,3 @@ +.deps +Makefile +Makefile.in diff --git a/src/AIModel/AIAircraft.cxx b/src/AIModel/AIAircraft.cxx new file mode 100644 index 000000000..010eaffc3 --- /dev/null +++ b/src/AIModel/AIAircraft.cxx @@ -0,0 +1,202 @@ +// FGAIAircraft - FGAIBase-derived class creates an AI airplane +// +// Written by David Culp, started October 2003. +// +// Copyright (C) 2003 David P. Culp - davidculp2@comcast.net +// +// 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include
+#include
+#include +#include +#include + +SG_USING_STD(string); + +#include "AIAircraft.hxx" + +FGAIAircraft::FGAIAircraft() { + + // set heading and altitude locks + hdg_lock = false; + alt_lock = false; +} + + +FGAIAircraft::~FGAIAircraft() { +} + + +bool FGAIAircraft::init() { + return FGAIBase::init(); +} + + +void FGAIAircraft::update(double dt) { + + Run(dt); + Transform(); + FGAIBase::update(dt); +} + +void FGAIAircraft::SetPerformance(PERF_STRUCT ps) { + + performance = ps; +} + + +void FGAIAircraft::Run(double dt) { + + FGAIAircraft::dt = dt; + + double turn_radius_ft; + double turn_circum_ft; + double speed_north_deg_sec; + double speed_east_deg_sec; + double ft_per_deg_lon; + double ft_per_deg_lat; + double dist_covered_ft; + double alpha; + + // get size of a degree at this latitude + ft_per_deg_lat = 366468.96 - 3717.12 * cos(pos.lat() / 57.2958 ); + ft_per_deg_lon = 365228.16 * cos(pos.lat() / 57.2958); + + // adjust speed + double speed_diff = tgt_speed - speed; + if (fabs(speed_diff) > 0.2) { + if (speed_diff > 0.0) speed += performance.accel * dt; + if (speed_diff < 0.0) speed -= performance.decel * dt; + } + + // convert speed to degrees per second + speed_north_deg_sec = cos( hdg / 57.29577951 ) * speed * 1.686 / ft_per_deg_lat; + speed_east_deg_sec = sin( hdg / 57.29577951 ) * speed * 1.686 / ft_per_deg_lon; + + // set new position + pos.setlat( pos.lat() + speed_north_deg_sec * dt); + pos.setlon( pos.lon() + speed_east_deg_sec * dt); + + // adjust heading based on current bank angle + if (roll != 0.0) { + turn_radius_ft = 0.088362 * speed * speed / tan( fabs(roll) / 57.2958 ); + turn_circum_ft = 6.2831853 * turn_radius_ft; + dist_covered_ft = speed * 1.686 * dt; + alpha = dist_covered_ft / turn_circum_ft * 360.0; + hdg += alpha * sign( roll ); + if ( hdg > 360.0 ) hdg -= 360.0; + if ( hdg < 0.0) hdg += 360.0; + } + + // adjust target bank angle if heading lock engaged + if (hdg_lock) { + double bank_sense = 0.0; + double diff = fabs(hdg - tgt_heading); + if (diff > 180) diff = fabs(diff - 360); + double sum = hdg + diff; + if (sum > 360.0) sum -= 360.0; + if (fabs(sum - tgt_heading) < 1.0) { + bank_sense = 1.0; + } else { + bank_sense = -1.0; + } + if (diff < 30) tgt_roll = diff * bank_sense; + } + + // adjust bank angle + double bank_diff = tgt_roll - roll; + if (fabs(bank_diff) > 0.2) { + if (bank_diff > 0.0) roll += 5.0 * dt; + if (bank_diff < 0.0) roll -= 5.0 * dt; + } + + // adjust altitude (meters) based on current vertical speed (fpm) + altitude += vs * 0.0166667 * dt * 0.3048; + + // find target vertical speed if altitude lock engaged + if (alt_lock) { + double altitude_ft = altitude * 3.28084; + if (altitude_ft < tgt_altitude) { + tgt_vs = tgt_altitude - altitude_ft; + if (tgt_vs > performance.climb_rate) tgt_vs = performance.climb_rate; + } else { + tgt_vs = tgt_altitude - altitude_ft; + if (tgt_vs < (-performance.descent_rate)) tgt_vs = -performance.descent_rate; + } + } + + // adjust vertical speed + double vs_diff = tgt_vs - vs; + if (fabs(vs_diff) > 1.0) { + if (vs_diff > 0.0) { + vs += 400.0 * dt; + if (vs > tgt_vs) vs = tgt_vs; + } else { + vs -= 300.0 * dt; + if (vs < tgt_vs) vs = tgt_vs; + } + } + + // match pitch angle to vertical speed + pitch = vs * 0.005; + +} + + +void FGAIAircraft::AccelTo(double speed) { + tgt_speed = speed; +} + + +void FGAIAircraft::PitchTo(double angle) { + tgt_pitch = angle; + alt_lock = false; +} + + +void FGAIAircraft::RollTo(double angle) { + tgt_roll = angle; + hdg_lock = false; +} + + +void FGAIAircraft::YawTo(double angle) { + tgt_yaw = angle; +} + + +void FGAIAircraft::ClimbTo(double altitude) { + tgt_altitude = altitude; + alt_lock = true; +} + + +void FGAIAircraft::TurnTo(double heading) { + tgt_heading = heading; + hdg_lock = true; +} + + +double FGAIAircraft::sign(double x) { + + if ( x < 0.0 ) { return -1.0; } + else { return 1.0; } +} diff --git a/src/AIModel/AIAircraft.hxx b/src/AIModel/AIAircraft.hxx new file mode 100644 index 000000000..759cca93c --- /dev/null +++ b/src/AIModel/AIAircraft.hxx @@ -0,0 +1,62 @@ +// FGAIAircraft - AIBase derived class creates an AI aircraft +// +// Written by David Culp, started October 2003. +// +// Copyright (C) 2003 David P. Culp - davidculp2@comcast.net +// +// 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +#ifndef _FG_AIAircraft_HXX +#define _FG_AIAircraft_HXX + +#include "AIManager.hxx" +#include "AIBase.hxx" + +#include +SG_USING_STD(string); + + +class FGAIAircraft : public FGAIBase { + +public: + + FGAIAircraft(); + ~FGAIAircraft(); + + bool init(); + void update(double dt); + + void SetPerformance(PERF_STRUCT ps); + void AccelTo(double speed); + void PitchTo(double angle); + void RollTo(double angle); + void YawTo(double angle); + void ClimbTo(double altitude); + void TurnTo(double heading); + +private: + + bool hdg_lock; + bool alt_lock; + + double dt; + + PERF_STRUCT performance; + + void Run(double dt); + double sign(double x); +}; + +#endif // _FG_AIAircraft_HXX diff --git a/src/AIModel/AIBallistic.cxx b/src/AIModel/AIBallistic.cxx new file mode 100644 index 000000000..2d96b7c75 --- /dev/null +++ b/src/AIModel/AIBallistic.cxx @@ -0,0 +1,117 @@ +// FGAIBallistic - FGAIBase-derived class creates a ballistic object +// +// Written by David Culp, started November 2003. +// - davidculp2@comcast.net +// +// 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include + +#include "AIBallistic.hxx" + + +FGAIBallistic::FGAIBallistic() { +} + +FGAIBallistic::~FGAIBallistic() { +} + + +bool FGAIBallistic::init() { + FGAIBase::init(); + vs = sin( elevation * 0.017453293 ) * speed; + hs = cos( elevation * 0.017453293 ) * speed; + aero_stabilized = true; + hdg = azimuth; + pitch = elevation; + return true; +} + + +void FGAIBallistic::update(double dt) { + + Run(dt); + Transform(); + FGAIBase::update(dt); +} + + +void FGAIBallistic::setAzimuth(double az) { + azimuth = az; +} + + +void FGAIBallistic::setElevation(double el) { + elevation = el; +} + + +void FGAIBallistic::setStabilization(bool val) { + aero_stabilized = val; +} + + +void FGAIBallistic::Run(double dt) { + + double speed_north_deg_sec; + double speed_east_deg_sec; + double ft_per_deg_lon; + double ft_per_deg_lat; + + // get size of a degree at this latitude + ft_per_deg_lat = 366468.96 - 3717.12 * cos(pos.lat() / 57.2958 ); + ft_per_deg_lon = 365228.16 * cos(pos.lat() / 57.2958); + + // the two drag calculations below assume sea-level density, + // mass of 0.03 slugs, drag coeff of 0.295, frontal area of 0.007 ft2 + // adjust horizontal speed due to drag + hs -= 0.000082 * hs * hs * dt; + if ( hs < 0.0 ) hs = 0.0; + + // adjust vertical speed due to drag + if (vs > 0.0) { + vs -= 0.000082 * vs * vs * dt; + } else { + vs += 0.000082 * vs * vs * dt; + } + + // convert horizontal speed (fps) to degrees per second + speed_north_deg_sec = cos( hdg / 57.29577951 ) * hs / ft_per_deg_lat; + speed_east_deg_sec = sin( hdg / 57.29577951 ) * hs / ft_per_deg_lon; + + // set new position + pos.setlat( pos.lat() + speed_north_deg_sec * dt); + pos.setlon( pos.lon() + speed_east_deg_sec * dt); + + // adjust vertical speed for acceleration of gravity + vs -= 32.17 * dt; + + // adjust altitude (meters) + altitude += vs * dt * 0.3048; + pos.setelev(altitude); + + // adjust pitch if aerostabilized + if (aero_stabilized) pitch = atan2( vs, hs ) * 57.29577951; + + // set destruction flag if altitude less than sea level -1000 + if (altitude < -1000.0) setDie(true); + +} + diff --git a/src/AIModel/AIBallistic.hxx b/src/AIModel/AIBallistic.hxx new file mode 100644 index 000000000..71951d204 --- /dev/null +++ b/src/AIModel/AIBallistic.hxx @@ -0,0 +1,51 @@ +// FGAIBallistic - AIBase derived class creates an AI ballistic object +// +// Written by David Culp, started November 2003. +// - davidculp2@comcast.net +// +// 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +#ifndef _FG_AIBALLISTIC_HXX +#define _FG_AIBALLISTIC_HXX + +#include "AIManager.hxx" +#include "AIBase.hxx" + + +class FGAIBallistic : public FGAIBase { + +public: + + FGAIBallistic(); + ~FGAIBallistic(); + + bool init(); + void update(double dt); + + void setAzimuth( double az ); + void setElevation( double el ); + void setStabilization( bool val ); + +private: + + double azimuth; // degrees true + double elevation; // degrees + double hs; // horizontal speed (fps) + bool aero_stabilized; // if true, object will point where it's going + + void Run(double dt); +}; + +#endif // _FG_AIBALLISTIC_HXX diff --git a/src/AIModel/AIBase.cxx b/src/AIModel/AIBase.cxx new file mode 100644 index 000000000..7c476180f --- /dev/null +++ b/src/AIModel/AIBase.cxx @@ -0,0 +1,97 @@ +// FGAIBase - abstract base class for AI objects +// Written by David Culp, started Nov 2003, based on +// David Luff's FGAIEntity class. +// - davidculp2@comcast.net +// +// 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., 675 Mass Ave, Cambridge, MA 02139, USA. + + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include
+#include +#include +#include +#include +#include +#include +#include + +#include "AIBase.hxx" + +FGAIBase::~FGAIBase() { +} + +void FGAIBase::update(double dt) { +} + + +void FGAIBase::Transform() { + aip.setPosition(pos.lon(), pos.lat(), pos.elev() * SG_METER_TO_FEET); + aip.setOrientation(roll, pitch, hdg); + aip.update( globals->get_scenery()->get_center() ); +} + + +bool FGAIBase::init() { + ssgBranch *model = sgLoad3DModel( globals->get_fg_root(), + model_path.c_str(), + globals->get_props(), + globals->get_sim_time_sec() ); + if (model) { + aip.init( model ); + aip.setVisible(true); + globals->get_scenery()->get_scene_graph()->addKid(aip.getSceneGraph()); + } else { + SG_LOG(SG_INPUT, SG_WARN, "AIBase: Could not load aircraft model."); + } + + tgt_roll = tgt_pitch = tgt_yaw = tgt_vs = vs = roll = pitch = 0.0; +} + + +void FGAIBase::setPath( const char* model ) { + model_path.append(model); +} + +void FGAIBase::setSpeed( double speed_KTAS ) { + speed = tgt_speed = speed_KTAS; +} + +void FGAIBase::setAltitude( double altitude_ft ) { + altitude = tgt_altitude = altitude_ft; + pos.setelev(altitude * 0.3048); +} + +void FGAIBase::setLongitude( double longitude ) { + pos.setlon(longitude); +} + +void FGAIBase::setLatitude( double latitude ) { + pos.setlat(latitude); +} + +void FGAIBase::setHeading( double heading ) { + hdg = tgt_heading = heading; +} + +void FGAIBase::setDie( bool die ) { + delete_me = die; +} + diff --git a/src/AIModel/AIBase.hxx b/src/AIModel/AIBase.hxx new file mode 100644 index 000000000..8e562628f --- /dev/null +++ b/src/AIModel/AIBase.hxx @@ -0,0 +1,74 @@ +// FGAIBase - abstract base class for AI objects +// Written by David Culp, started Nov 2003, based on +// David Luff's FGAIEntity class. +// - davidculp2@comcast.net +// +// 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +#ifndef _FG_AIBASE_HXX +#define _FG_AIBASE_HXX + +#include +#include +#include + +SG_USING_STD(string); + +class FGAIBase { + +public: + + virtual ~FGAIBase(); + virtual void update(double dt); + inline Point3D GetPos() { return(pos); } + virtual bool init(); + + void setPath( const char* model ); + void setSpeed( double speed_KTAS ); + void setAltitude( double altitude_ft ); + void setLongitude( double longitude ); + void setLatitude( double latitude ); + void setHeading( double heading ); + void setDie( bool die ); + inline bool getDie() { return delete_me; } + +protected: + + Point3D pos; // WGS84 lat & lon in degrees, elev above sea-level in meters + double hdg; // True heading in degrees + double roll; // degrees, left is negative + double pitch; // degrees, nose-down is negative + double speed; // knots true airspeed + double altitude; // meters above sea level + double vs; // vertical speed, feet per minute + + double tgt_heading; // target heading, degrees true + double tgt_altitude; // target altitude, *feet* above sea level + double tgt_speed; // target speed, KTAS + double tgt_roll; + double tgt_pitch; + double tgt_yaw; + double tgt_vs; + + + string model_path; //Path to the 3D model + SGModelPlacement aip; + bool delete_me; + + void Transform(); +}; + +#endif // _FG_AIBASE_HXX + diff --git a/src/AIModel/AIManager.cxx b/src/AIModel/AIManager.cxx new file mode 100644 index 000000000..2d68fc3d9 --- /dev/null +++ b/src/AIModel/AIManager.cxx @@ -0,0 +1,127 @@ +// AIManager.cxx Based on David Luff's AIMgr: +// - a global management class for AI objects +// +// Written by David Culp, started October 2003. +// - davidculp2@comcast.net +// +// 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +#include +#include
+#include
+ +#include + +#include "AIManager.hxx" +#include "AIAircraft.hxx" +#include "AIShip.hxx" +#include "AIBallistic.hxx" + +SG_USING_STD(list); + + +FGAIManager::FGAIManager() { + initDone = false; +} + +FGAIManager::~FGAIManager() { + ai_list.clear(); +} + +void FGAIManager::init() { + SGPropertyNode * node = fgGetNode("sim/ai", true); + for (int i = 0; i < node->nChildren(); i++) { + const SGPropertyNode * entry = node->getChild(i); + if (!strcmp(entry->getName(), "entry")) { + if (!strcmp(entry->getStringValue("type", ""), "aircraft")) { + FGAIAircraft* ai_plane = new FGAIAircraft; + ai_list.push_back(ai_plane); + if (!strcmp(entry->getStringValue("class", ""), "light")) { + PERF_STRUCT ps = {2.0, 2.0, 450.0, 1000.0, 70.0, 80.0, 100.0, 80.0, 60.0}; + ai_plane->SetPerformance(ps); + } else if (!strcmp(entry->getStringValue("class", ""), "ww2_fighter")) { + PERF_STRUCT ps = {4.0, 2.0, 3000.0, 1500.0, 110.0, 180.0, 250.0, 200.0, 100.0}; + ai_plane->SetPerformance(ps); + } else if (!strcmp(entry->getStringValue("class", ""), "jet_transport")) { + PERF_STRUCT ps = {5.0, 2.0, 3000.0, 1500.0, 140.0, 300.0, 430.0, 300.0, 130.0}; + ai_plane->SetPerformance(ps); + } else if (!strcmp(entry->getStringValue("class", ""), "jet_fighter")) { + PERF_STRUCT ps = {7.0, 3.0, 4000.0, 2000.0, 150.0, 350.0, 500.0, 350.0, 150.0}; + ai_plane->SetPerformance(ps); + } + ai_plane->setHeading(entry->getDoubleValue("heading")); + ai_plane->setSpeed(entry->getDoubleValue("speed-KTAS")); + ai_plane->setPath(entry->getStringValue("path")); + ai_plane->setAltitude(entry->getDoubleValue("altitude-ft")); + ai_plane->setLongitude(entry->getDoubleValue("longitude")); + ai_plane->setLatitude(entry->getDoubleValue("latitude")); + ai_plane->init(); + + } else if (!strcmp(entry->getStringValue("type", ""), "ship")) { + FGAIShip* ai_ship = new FGAIShip; + ai_list.push_back(ai_ship); + ai_ship->setHeading(entry->getDoubleValue("heading")); + ai_ship->setSpeed(entry->getDoubleValue("speed-KTAS")); + ai_ship->setPath(entry->getStringValue("path")); + ai_ship->setAltitude(entry->getDoubleValue("altitude-ft")); + ai_ship->setLongitude(entry->getDoubleValue("longitude")); + ai_ship->setLatitude(entry->getDoubleValue("latitude")); + ai_ship->init(); + + } else if (!strcmp(entry->getStringValue("type", ""), "ballistic")) { + FGAIBallistic* ai_ballistic = new FGAIBallistic; + ai_list.push_back(ai_ballistic); + ai_ballistic->setAzimuth(entry->getDoubleValue("azimuth")); + ai_ballistic->setElevation(entry->getDoubleValue("elevation")); + ai_ballistic->setSpeed(entry->getDoubleValue("speed-fps")); + ai_ballistic->setPath(entry->getStringValue("path")); + ai_ballistic->setAltitude(entry->getDoubleValue("altitude-ft")); + ai_ballistic->setLongitude(entry->getDoubleValue("longitude")); + ai_ballistic->setLatitude(entry->getDoubleValue("latitude")); + ai_ballistic->init(); + } + } + } + + initDone = true; +} + + +void FGAIManager::bind() { +} + + +void FGAIManager::unbind() { +} + + +void FGAIManager::update(double dt) { +#if 0 + if(!initDone) { + init(); + SG_LOG(SG_ATC, SG_WARN, "Warning - AIManager::update(...) called before AIManager::init()"); + } +#endif + + ai_list_itr = ai_list.begin(); + while(ai_list_itr != ai_list.end()) { + if ((*ai_list_itr)->getDie()) { + ai_list.erase(ai_list_itr, ai_list_itr); + } else { + (*ai_list_itr)->update(dt); + } + ++ai_list_itr; + } +} diff --git a/src/AIModel/AIManager.hxx b/src/AIModel/AIManager.hxx new file mode 100644 index 000000000..032cc0100 --- /dev/null +++ b/src/AIModel/AIManager.hxx @@ -0,0 +1,80 @@ +// AIManager.hxx - experimental! - David Culp - based on: +// AIMgr.hxx - definition of FGAIMgr +// - a global management class for FlightGear generated AI traffic +// +// Written by David Luff, started March 2002. +// +// Copyright (C) 2002 David C Luff - david.luff@nottingham.ac.uk +// +// 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +#ifndef _FG_AIMANAGER_HXX +#define _FG_AIMANAGER_HXX + +#include +#include
+#include +#include "AIBase.hxx" + +SG_USING_STD(list); + + struct PERF_STRUCT { + double accel; + double decel; + double climb_rate; + double descent_rate; + double takeoff_speed; + double climb_speed; + double cruise_speed; + double descent_speed; + double land_speed; + }; + + +class FGAIManager : public SGSubsystem +{ + +private: + + // A list of pointers to AI objects + typedef list ai_list_type; + typedef ai_list_type::iterator ai_list_iterator; + typedef ai_list_type::const_iterator ai_list_const_iterator; + + // Everything put in this list should be created dynamically + // on the heap and ***DELETED WHEN REMOVED!!!!!*** + ai_list_type ai_list; + ai_list_iterator ai_list_itr; + +public: + + enum object_type { otAircraft, otShip, otBallistic, otRocket }; + + FGAIManager(); + ~FGAIManager(); + + void init(); + void bind(); + void unbind(); + void update(double dt); + + +private: + + bool initDone; + +}; + +#endif // _FG_AIMANAGER_HXX diff --git a/src/AIModel/AIShip.cxx b/src/AIModel/AIShip.cxx new file mode 100644 index 000000000..4a81972b6 --- /dev/null +++ b/src/AIModel/AIShip.cxx @@ -0,0 +1,153 @@ +// FGAIShip - FGAIBase-derived class creates an AI ship +// +// Written by David Culp, started October 2003. +// - davidculp2@comcast.net +// +// 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include + +#include "AIShip.hxx" + + +FGAIShip::FGAIShip() { + hdg_lock = false; + rudder = 0.0; +} + +FGAIShip::~FGAIShip() { +} + + +bool FGAIShip::init() { + return FGAIBase::init(); +} + + + +void FGAIShip::update(double dt) { + + Run(dt); + Transform(); + FGAIBase::update(dt); +} + + + +void FGAIShip::Run(double dt) { + + double turn_radius_ft; + double turn_circum_ft; + double speed_north_deg_sec; + double speed_east_deg_sec; + double ft_per_deg_lon; + double ft_per_deg_lat; + double dist_covered_ft; + double alpha; + + // get size of a degree at this latitude + ft_per_deg_lat = 366468.96 - 3717.12 * cos(pos.lat() / 57.2958 ); + ft_per_deg_lon = 365228.16 * cos(pos.lat() / 57.2958); + + // adjust speed + double speed_diff = tgt_speed - speed; + if (fabs(speed_diff) > 0.1) { + if (speed_diff > 0.0) speed += 0.1 * dt; + if (speed_diff < 0.0) speed -= 0.1 * dt; + } + + // convert speed to degrees per second + speed_north_deg_sec = cos( hdg / 57.29577951 ) * speed * 1.686 / ft_per_deg_lat; + speed_east_deg_sec = sin( hdg / 57.29577951 ) * speed * 1.686 / ft_per_deg_lon; + + // set new position + pos.setlat( pos.lat() + speed_north_deg_sec * dt); + pos.setlon( pos.lon() + speed_east_deg_sec * dt); + + // adjust heading based on current rudder angle + if (rudder != 0.0) { + turn_radius_ft = 0.088362 * speed * speed / tan( fabs(rudder) / 57.2958 ); + turn_circum_ft = 6.2831853 * turn_radius_ft; + dist_covered_ft = speed * 1.686 * dt; + alpha = dist_covered_ft / turn_circum_ft * 360.0; + hdg += alpha * sign( rudder ); + if ( hdg > 360.0 ) hdg -= 360.0; + if ( hdg < 0.0) hdg += 360.0; + } + + // adjust target rudder angle if heading lock engaged + if (hdg_lock) { + double rudder_sense = 0.0; + double diff = fabs(hdg - tgt_heading); + if (diff > 180) diff = fabs(diff - 360); + double sum = hdg + diff; + if (sum > 360.0) sum -= 360.0; + if (fabs(sum - tgt_heading) < 1.0) { + rudder_sense = 1.0; + } else { + rudder_sense = -1.0; + } + if (diff < 30) tgt_roll = diff * rudder_sense; + } + + // adjust rudder angle + double rudder_diff = tgt_roll - rudder; + if (fabs(rudder_diff) > 0.1) { + if (rudder_diff > 0.0) rudder += 5.0 * dt; + if (rudder_diff < 0.0) rudder -= 5.0 * dt; + } + +} + + +void FGAIShip::AccelTo(double speed) { + tgt_speed = speed; +} + + +void FGAIShip::PitchTo(double angle) { + tgt_pitch = angle; +} + + +void FGAIShip::RollTo(double angle) { + tgt_roll = angle; +} + + +void FGAIShip::YawTo(double angle) { +} + + +void FGAIShip::ClimbTo(double altitude) { +} + + +void FGAIShip::TurnTo(double heading) { + tgt_heading = heading; + hdg_lock = true; +} + + +double FGAIShip::sign(double x) { + + if ( x < 0.0 ) { return -1.0; } + else { return 1.0; } +} diff --git a/src/AIModel/AIShip.hxx b/src/AIModel/AIShip.hxx new file mode 100644 index 000000000..c36686245 --- /dev/null +++ b/src/AIModel/AIShip.hxx @@ -0,0 +1,54 @@ +// FGAIShip - AIBase derived class creates an AI ship +// +// Written by David Culp, started November 2003. +// +// Copyright (C) 2003 David P. Culp - davidculp2@comcast.net +// +// 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +#ifndef _FG_AISHIP_HXX +#define _FG_AISHIP_HXX + +#include "AIManager.hxx" +#include "AIBase.hxx" + + +class FGAIShip : public FGAIBase { + +public: + + FGAIShip(); + ~FGAIShip(); + + bool init(); + void update(double dt); + + void AccelTo(double speed); + void PitchTo(double angle); + void RollTo(double angle); + void YawTo(double angle); + void ClimbTo(double altitude); + void TurnTo(double heading); + +private: + + bool hdg_lock; + double rudder; + + void Run(double dt); + double sign(double x); +}; + +#endif // _FG_AISHIP_HXX diff --git a/src/AIModel/Makefile.am b/src/AIModel/Makefile.am new file mode 100644 index 000000000..ba103fc13 --- /dev/null +++ b/src/AIModel/Makefile.am @@ -0,0 +1,10 @@ +noinst_LIBRARIES = libAIModel.a + +libAIModel_a_SOURCES = \ + AIManager.hxx AIManager.cxx \ + AIBase.hxx AIBase.cxx \ + AIAircraft.hxx AIAircraft.cxx \ + AIShip.hxx AIShip.cxx \ + AIBallistic.hxx AIBallistic.cxx + +INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/src diff --git a/src/GUI/AirportList.cxx b/src/GUI/AirportList.cxx index 3f97342de..2057e520f 100644 --- a/src/GUI/AirportList.cxx +++ b/src/GUI/AirportList.cxx @@ -1,3 +1,5 @@ +#include // strncpy() + #include
#include diff --git a/src/Main/Makefile.am b/src/Main/Makefile.am index 73986c829..e47142095 100644 --- a/src/Main/Makefile.am +++ b/src/Main/Makefile.am @@ -71,6 +71,7 @@ fgfs_LDADD = \ $(top_builddir)/src/Input/libInput.a \ $(top_builddir)/src/Instrumentation/libInstrumentation.a \ $(top_builddir)/src/Model/libModel.a \ + $(top_builddir)/src/AIModel/libAIModel.a \ $(top_builddir)/src/Network/libNetwork.a \ $(top_builddir)/src/Navaids/libNavaids.a \ $(top_builddir)/src/Scenery/libScenery.a \ diff --git a/src/Main/fg_init.cxx b/src/Main/fg_init.cxx index 5be3d3bce..873e82aac 100644 --- a/src/Main/fg_init.cxx +++ b/src/Main/fg_init.cxx @@ -95,6 +95,7 @@ #include #include #include +#include #include #include #include @@ -1654,6 +1655,14 @@ bool fgInitSubsystems() { globals->get_AI_mgr()->init(); + //////////////////////////////////////////////////////////////////// + // Initialise the AI Model Manager + //////////////////////////////////////////////////////////////////// + + SG_LOG(SG_GENERAL, SG_INFO, " AI Model Manager"); + globals->add_subsystem("ai_model", new FGAIManager); + + #ifdef ENABLE_AUDIO_SUPPORT //////////////////////////////////////////////////////////////////// // Initialize the sound subsystem. diff --git a/src/Makefile.am b/src/Makefile.am index d324d32e1..74a44e7f9 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -23,6 +23,7 @@ SUBDIRS = \ Input \ Instrumentation \ Model \ + AIModel \ Navaids \ Network \ $(MPLAYER_DIRS) \