]> git.mxchange.org Git - flightgear.git/commitdiff
David Culp:
authorehofman <ehofman>
Sat, 15 May 2004 09:07:55 +0000 (09:07 +0000)
committerehofman <ehofman>
Sat, 15 May 2004 09:07:55 +0000 (09:07 +0000)
Here's the newest AI stuff.

The AIManager at init() creates a new scenario.  Right now the
default_scenario is hard coded in, but eventually the AIManager should get
the scenario filename from preferences.xml.

The scenario defines which AI objects will be created.  Right now it only
creates AIAircraft, but this is easily extended.  The scenario also defines
which flightplan will be assigned to the airplane.  Scenario config files go
in data/Data/AI.

The Airplane gets a pointer to a FlightPlan object.  Each airplane should get
its own flightplan object, even if two airplanes have the same flight plan.
This is because  the flightplan maintains the iterator pointing to the
current waypoint, and two airplanes might be at different locations (for
instance if they were created at different times).  The flight plan files go
in data/Data/AI/FlightPlans.

When the airplane gets to the waypoint named "END" it vanishes.  The
AIAircraft destructor deletes its flight plan (if it has one).

The last waypoint is a place holder only.  I called mine
<WPT><NAME>"EOF"</NAME></WPT>.

src/AIModel/AIAircraft.cxx
src/AIModel/AIAircraft.hxx
src/AIModel/AIBase.cxx
src/AIModel/AIFlightPlan.cxx [new file with mode: 0644]
src/AIModel/AIFlightPlan.hxx [new file with mode: 0644]
src/AIModel/AIManager.cxx
src/AIModel/AIManager.hxx
src/AIModel/AIScenario.cxx [new file with mode: 0644]
src/AIModel/AIScenario.hxx [new file with mode: 0644]
src/AIModel/Makefile.am

index 717f9a1e7db9ee9ccb9e524314fce2da565f7452..bbed46642da14e0baa2e52c60d0df2523139dc66 100644 (file)
@@ -56,6 +56,9 @@ FGAIAircraft::FGAIAircraft(FGAIManager* mgr) {
    _self = this;
    _type_str = "aircraft";
    _otype = otAircraft;
+   fp = 0;
+   fp_count = 0;
+   use_perf_vs = true;
 
    // set heading and altitude locks
    hdg_lock = false;
@@ -64,6 +67,7 @@ FGAIAircraft::FGAIAircraft(FGAIManager* mgr) {
 
 
 FGAIAircraft::~FGAIAircraft() {
+    if (fp) delete fp;
     _self = NULL;
 }
 
@@ -108,6 +112,8 @@ void FGAIAircraft::SetPerformance(const PERF_STRUCT *ps) {
 void FGAIAircraft::Run(double dt) {
 
    FGAIAircraft::dt = dt;
+
+   if (fp) ProcessFlightPlan();
        
    double turn_radius_ft;
    double turn_circum_ft;
@@ -159,26 +165,31 @@ void FGAIAircraft::Run(double dt) {
      double sum = hdg + diff;
      if (sum > 360.0) sum -= 360.0;
      if (fabs(sum - tgt_heading) < 1.0) { 
-       bank_sense = 1.0;
+       bank_sense = 1.0;   // right turn
      } else {
-       bank_sense = -1.0;
+       bank_sense = -1.0;  // left turn
      } 
-     if (diff < 30) tgt_roll = diff * bank_sense; 
+     if (diff < 30) {
+         tgt_roll = diff * bank_sense; 
+     } else {
+         tgt_roll = 30.0 * bank_sense;
+     }
    }
 
-   // adjust bank angle
+   // adjust bank angle, use 9 degrees per second
    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;
+     if (bank_diff > 0.0) roll += 9.0 * dt;
+     if (bank_diff < 0.0) roll -= 9.0 * dt;
    }
 
    // adjust altitude (meters) based on current vertical speed (fpm)
-   altitude += vs * 0.0166667 * dt * SG_FEET_TO_METER;  
-   double altitude_ft = altitude * SG_METER_TO_FEET;
+   altitude += vs / 60.0 * dt;
+   pos.setelev(altitude * SG_FEET_TO_METER);  
+   double altitude_ft = altitude;
 
    // find target vertical speed if altitude lock engaged
-   if (alt_lock) {
+   if (alt_lock && use_perf_vs) {
      if (altitude_ft < tgt_altitude) {
        tgt_vs = tgt_altitude - altitude_ft;
        if (tgt_vs > performance->climb_rate)
@@ -190,9 +201,15 @@ void FGAIAircraft::Run(double dt) {
      }
    }
 
+   if (alt_lock && !use_perf_vs) {
+     double max_vs = 2*(tgt_altitude - altitude);
+     if ((fabs(tgt_altitude - altitude) < 1500.0) && 
+         (fabs(max_vs) < fabs(tgt_vs))) tgt_vs = max_vs;
+   }   
+
    // adjust vertical speed
    double vs_diff = tgt_vs - vs;
-   if (fabs(vs_diff) > 1.0) {
+   if (fabs(vs_diff) > 10.0) {
      if (vs_diff > 0.0) {
        vs += 400.0 * dt;
        if (vs > tgt_vs) vs = tgt_vs;
@@ -216,7 +233,7 @@ void FGAIAircraft::Run(double dt) {
    double user_heading   = manager->get_user_heading();
    double user_pitch     = manager->get_user_pitch();
    double user_yaw       = manager->get_user_yaw();
-   // double user_speed     = manager->get_user_speed();
+   double user_speed     = manager->get_user_speed();
 
    // calculate range to target in feet and nautical miles
    double lat_range = fabs(pos.lat() - user_latitude) * ft_per_deg_lat;
@@ -253,7 +270,7 @@ void FGAIAircraft::Run(double dt) {
    // calculate look up/down to target
    vert_offset = elevation + user_pitch;
 
-/* this calculation needs to be fixed
+/* this calculation needs to be fixed, but it isn't important anyway
    // calculate range rate
    double recip_bearing = bearing + 180.0;
    if (recip_bearing > 360.0) recip_bearing -= 360.0;
@@ -311,7 +328,102 @@ void FGAIAircraft::TurnTo(double heading) {
 
 
 double FGAIAircraft::sign(double x) {
-
   if ( x < 0.0 ) { return -1.0; }
   else { return 1.0; }
 }
+
+void FGAIAircraft::SetFlightPlan(FGAIFlightPlan *f) {
+  fp = f;
+}
+
+void FGAIAircraft::ProcessFlightPlan( void ) {
+  FGAIFlightPlan::waypoint* prev = 0; // the one behind you
+  FGAIFlightPlan::waypoint* curr = 0; // the one ahead
+  FGAIFlightPlan::waypoint* next = 0; // the next plus 1
+  prev = fp->getPreviousWaypoint();
+  curr = fp->getCurrentWaypoint();
+  next = fp->getNextWaypoint();
+  ++fp_count;
+
+  if (!prev) {  //beginning of flightplan, do this initialization once
+    fp->IncrementWaypoint();
+    prev = fp->getPreviousWaypoint(); //first waypoint
+    curr = fp->getCurrentWaypoint();  //second waypoint
+    next = fp->getNextWaypoint();     //third waypoint (might not exist!) 
+    setLatitude(prev->latitude);
+    setLongitude(prev->longitude);
+    setSpeed(prev->speed);
+    setAltitude(prev->altitude);
+    setHeading(fp->getBearing(prev->latitude, prev->longitude, curr));
+    if (next) fp->setLeadDistance(speed, hdg, curr, next);
+    
+    if (curr->crossat > -1000.0) { //start descent/climb now
+        use_perf_vs = false;
+        tgt_vs = (curr->crossat - prev->altitude)/
+                 (fp->getDistanceToGo(pos.lat(), pos.lon(), curr)/
+                                      6076.0/prev->speed*60.0);
+        tgt_altitude = curr->crossat;
+    } else {
+        use_perf_vs = true;
+        tgt_altitude = prev->altitude;
+    }
+    alt_lock = hdg_lock = true;
+    //cout << "First waypoint:  " << prev->name << endl;
+    //cout << "  Target speed:    " << tgt_speed << endl;
+    //cout << "  Target altitude: " << tgt_altitude << endl;
+    //cout << "  Target heading:  " << tgt_heading << endl << endl;       
+    return;  
+  } // end of initialization
+
+  // let's only process the flight plan every 11 time steps
+  if (fp_count < 11) { 
+    return;
+  } else {
+    fp_count = 0;
+
+    // check to see if we've reached the lead point for our next turn
+    double dist_to_go = fp->getDistanceToGo(pos.lat(), pos.lon(), curr); 
+    double lead_dist = fp->getLeadDistance();
+    if (lead_dist < (2*speed)) lead_dist = 2*speed;  //don't skip over the waypoint
+    //cout << "dist_to_go: " << dist_to_go << ",  lead_dist: " << lead_dist << endl;
+
+    if ( dist_to_go < lead_dist ) {
+      if (curr->name == "END") {  //end of the flight plan, so terminate
+        setDie(true);
+        return;
+      }
+      // we've reached the lead-point for the waypoint ahead 
+      if (next) tgt_heading = fp->getBearing(curr, next);  
+      fp->IncrementWaypoint();
+      prev = fp->getPreviousWaypoint();
+      curr = fp->getCurrentWaypoint();
+      next = fp->getNextWaypoint();
+      if (next) fp->setLeadDistance(speed, tgt_heading, curr, next);
+      if (curr->crossat > -1000.0) {
+        use_perf_vs = false;
+        tgt_vs = (curr->crossat - altitude)/
+                 (fp->getDistanceToGo(pos.lat(), pos.lon(), curr)/6076.0/speed*60.0);
+        tgt_altitude = curr->crossat;
+      } else {
+        use_perf_vs = true;
+        tgt_altitude = prev->altitude;
+      }
+      tgt_speed = prev->speed;
+      hdg_lock = alt_lock = true;
+      //cout << "Crossing waypoint: " << prev->name << endl;
+      //cout << "  Target speed:    " << tgt_speed << endl;
+      //cout << "  Target altitude: " << tgt_altitude << endl;
+      //cout << "  Target heading:  " << tgt_heading << endl << endl;       
+    } else {
+        double calc_bearing = fp->getBearing(pos.lat(), pos.lon(), curr);
+        double hdg_error = calc_bearing - tgt_heading;
+        if (fabs(hdg_error) > 1.0) {
+          TurnTo( calc_bearing ); 
+        }
+    }
+     
+  }
+
+}
+
+
index 6ea34c092fbfbe51d7440b3235d73125dd63f504..fb62588e23ae1a6e560ee3c71d1b2516b0a4082f 100644 (file)
@@ -23,6 +23,7 @@
 
 #include "AIManager.hxx"
 #include "AIBase.hxx"
+#include "AIFlightPlan.hxx"
 
 #include <string>
 SG_USING_STD(string);
@@ -58,12 +59,15 @@ public:
        void update(double dt);
 
         void SetPerformance(const PERF_STRUCT *ps);
+        void SetFlightPlan(FGAIFlightPlan *f);
         void AccelTo(double speed);
         void PitchTo(double angle);
         void RollTo(double angle);
         void YawTo(double angle);
         void ClimbTo(double altitude);
         void TurnTo(double heading);
+        void ProcessFlightPlan( void );
+        //double getHeading(double lat1, double lon1, double lat2, double lon2);
 
 protected:
         static FGAIAircraft *_self;
@@ -72,10 +76,12 @@ private:
 
         bool hdg_lock;
         bool alt_lock;
-
+        FGAIFlightPlan *fp;
+        int fp_count;  
         double dt; 
 
         const PERF_STRUCT *performance;
+        bool use_perf_vs;
 
        void Run(double dt);
         double sign(double x); 
index bb1af2279ad82017c5e666fcafdbee922ac6944b..18af4a9aaea0c024de42b0a3fa941a51952162c5 100644 (file)
@@ -56,6 +56,7 @@ FGAIBase::FGAIBase() {
 }
 
 FGAIBase::~FGAIBase() {
+    globals->get_scenery()->get_scene_graph()->removeKid(aip.getSceneGraph());
     unbind();
     _self = NULL;
 }
diff --git a/src/AIModel/AIFlightPlan.cxx b/src/AIModel/AIFlightPlan.cxx
new file mode 100644 (file)
index 0000000..16ddb3d
--- /dev/null
@@ -0,0 +1,171 @@
+// FGAIFlightPlan - class for loading and storing  AI flight plans
+// Written by David Culp, started May 2004
+// - 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 "AIFlightPlan.hxx"
+#include <simgear/misc/sg_path.hxx>
+#include <simgear/debug/logstream.hxx>
+#include <simgear/structure/exception.hxx>
+#include <simgear/constants.h>
+#ifdef __BORLANDC__
+#  define exception c_exception
+#endif
+#include <simgear/props/props.hxx>
+#include <Main/globals.hxx>
+#include <Main/fg_props.hxx>
+
+
+FGAIFlightPlan::FGAIFlightPlan(string filename)
+{
+  int i;
+  SGPath path( globals->get_fg_root() );
+  path.append( ("/Data/AI/FlightPlans/" + filename).c_str() );
+  SGPropertyNode root;
+
+  try {
+      readProperties(path.str(), &root);
+  } catch (const sg_exception &e) {
+      SG_LOG(SG_GENERAL, SG_ALERT,
+       "Error reading AI flight plan: ");
+       cout << path.str() << endl;
+      return;
+  }
+
+  SGPropertyNode * node = root.getNode("FLIGHTPLAN");
+  for (i = 0; i < node->nChildren(); i++) { 
+     //cout << "Reading waypoint " << i << endl;        
+     waypoint* wpt = new waypoint;
+     waypoints.push_back( wpt );
+     SGPropertyNode * wpt_node = node->getChild(i);
+     wpt->name      = wpt_node->getStringValue("NAME", "END");
+     wpt->latitude  = wpt_node->getDoubleValue("LAT", 0);
+     wpt->longitude = wpt_node->getDoubleValue("LON", 0);
+     wpt->altitude  = wpt_node->getDoubleValue("ALT", 0);
+     wpt->speed     = wpt_node->getDoubleValue("KTAS", 0);
+     wpt->crossat   = wpt_node->getDoubleValue("CROSSAT", -10000);
+     wpt->gear_down = wpt_node->getBoolValue("GEAR-DOWN", false);
+     wpt->flaps_down= wpt_node->getBoolValue("FLAPS-DOWN", false);
+   }
+
+  wpt_iterator = waypoints.begin();
+  //cout << waypoints.size() << " waypoints read." << endl;
+}
+
+
+FGAIFlightPlan::~FGAIFlightPlan()
+{
+  waypoints.clear();
+}
+
+
+FGAIFlightPlan::waypoint*
+FGAIFlightPlan::getPreviousWaypoint( void )
+{
+  if (wpt_iterator == waypoints.begin()) {
+    return 0;
+  } else {
+    wpt_vector_iterator prev = wpt_iterator;
+    return *(--prev);
+  }
+}
+
+FGAIFlightPlan::waypoint*
+FGAIFlightPlan::getCurrentWaypoint( void )
+{
+  return *wpt_iterator;
+}
+
+FGAIFlightPlan::waypoint*
+FGAIFlightPlan::getNextWaypoint( void )
+{
+  if (wpt_iterator == waypoints.end()) {
+    return 0;
+  } else {
+    wpt_vector_iterator next = wpt_iterator;
+    return *(++next);
+  }
+}
+
+void FGAIFlightPlan::IncrementWaypoint( void )
+{
+  wpt_iterator++;
+}
+
+// gives distance in feet from a position to a waypoint
+double FGAIFlightPlan::getDistanceToGo(double lat, double lon, waypoint* wp){
+   // get size of a degree at the present latitude
+   // this won't work over large distances
+   double ft_per_deg_lat = 366468.96 - 3717.12 * cos(lat / SG_RADIANS_TO_DEGREES);
+   double ft_per_deg_lon = 365228.16 * cos(lat / SG_RADIANS_TO_DEGREES);
+   double lat_diff_ft = fabs(wp->latitude - lat) * ft_per_deg_lat;
+   double lon_diff_ft = fabs(wp->longitude - lon) * ft_per_deg_lon;
+   return sqrt((lat_diff_ft * lat_diff_ft) + (lon_diff_ft * lon_diff_ft));
+}
+
+// sets distance in feet from a lead point to the current waypoint
+void FGAIFlightPlan::setLeadDistance(double speed, double bearing, 
+                                     waypoint* current, waypoint* next){
+  double turn_radius = 0.1911 * speed * speed; // an estimate for 25 degrees bank
+  double inbound = bearing;
+  double outbound = getBearing(current, next);
+  double diff = fabs(inbound - outbound);
+  if (diff > 180.0) diff = 360.0 - diff;
+  lead_distance = turn_radius * sin(diff * SG_DEGREES_TO_RADIANS); 
+}
+
+void FGAIFlightPlan::setLeadDistance(double distance_ft){
+  lead_distance = distance_ft;
+}
+
+
+double FGAIFlightPlan::getBearing(waypoint* first, waypoint* second){
+  return getBearing(first->latitude, first->longitude, second);
+}
+
+
+double FGAIFlightPlan::getBearing(double lat, double lon, waypoint* wp){
+  double latd = lat;
+  double lond = lon;
+  double latt = wp->latitude;
+  double lont = wp->longitude;
+  double ft_per_deg_lat = 366468.96 - 3717.12 * cos(lat/SG_RADIANS_TO_DEGREES);
+  double ft_per_deg_lon = 365228.16 * cos(lat/SG_RADIANS_TO_DEGREES);
+
+  if (lond < 0.0) lond+=360.0;
+  if (lont < 0.0) lont+=360.0;
+  latd+=90.0;
+  latt+=90.0;
+
+  double lat_diff = (latt - latd) * ft_per_deg_lat;
+  double lon_diff = (lont - lond) * ft_per_deg_lon;
+  double angle = atan(fabs(lat_diff / lon_diff)) * SG_RADIANS_TO_DEGREES;
+
+  bool southerly = true;
+  if (latt > latd) southerly = false;
+  bool easterly = false;
+  if (lont > lond) easterly = true;
+  if (southerly && easterly) return 90.0 + angle;
+  if (!southerly && easterly) return 90.0 - angle;
+  if (southerly && !easterly) return 270.0 - angle;
+  if (!southerly && !easterly) return 270.0 + angle; 
+
+  /* prevent a compiler warning */
+  return 0.0;
+}
+
+
diff --git a/src/AIModel/AIFlightPlan.hxx b/src/AIModel/AIFlightPlan.hxx
new file mode 100644 (file)
index 0000000..e511c2c
--- /dev/null
@@ -0,0 +1,75 @@
+// FGAIFlightPlan - class for loading and storing  AI flight plans
+// Written by David Culp, started May 2004
+// - 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_AIFLIGHTPLAN_HXX
+#define _FG_AIFLIGHTPLAN_HXX
+
+#include <simgear/compiler.h>
+#include <vector>
+#include <string>
+SG_USING_STD(vector);
+SG_USING_STD(string);
+
+
+class FGAIFlightPlan {
+
+public:
+
+  typedef struct {
+   string name;
+   double latitude;
+   double longitude;
+   double altitude;
+   double speed;
+   double crossat;
+   bool gear_down;
+   bool flaps_down;
+  } waypoint;
+
+   FGAIFlightPlan(string filename);
+   ~FGAIFlightPlan();
+
+   waypoint* getPreviousWaypoint( void );
+   waypoint* getCurrentWaypoint( void );
+   waypoint* getNextWaypoint( void );
+   void IncrementWaypoint( void );
+
+   double getDistanceToGo(double lat, double lon, waypoint* wp);
+   void setLeadDistance(double speed, double bearing, waypoint* current, waypoint* next);
+   void setLeadDistance(double distance_ft);
+   double getLeadDistance( void ) const {return lead_distance;}
+   double getBearing(waypoint* previous, waypoint* next);
+   double getBearing(double lat, double lon, waypoint* next);
+
+private:
+
+    typedef vector <waypoint*> wpt_vector_type;
+    typedef wpt_vector_type::iterator wpt_vector_iterator;
+
+    wpt_vector_type       waypoints;
+    wpt_vector_iterator   wpt_iterator;
+
+    double distance_to_go;
+    double lead_distance;
+
+};    
+
+
+
+#endif  // _FG_AIFLIGHTPLAN_HXX
+
index ceffc4c4a8c8b2d1f2e0a87f2bf3cea1fa96c8b1..9e5e7fb3c9641d0f41415c90106f0443adc47984 100644 (file)
@@ -113,6 +113,10 @@ void FGAIManager::init() {
     }
   }
 
+  //**********  Flight Plan test code !!!! ****************
+  processScenario( "default_scenario" );
+  //******************************************************* 
+
   initDone = true;
 }
 
@@ -208,6 +212,8 @@ int FGAIManager::createAircraft( string model_class, string path,
           ai_plane->SetPerformance(&FGAIAircraft::settings[FGAIAircraft::JET_TRANSPORT]);
         } else if (model_class == "jet_fighter") {
           ai_plane->SetPerformance(&FGAIAircraft::settings[FGAIAircraft::JET_FIGHTER]);
+        } else {
+          ai_plane->SetPerformance(&FGAIAircraft::settings[FGAIAircraft::JET_TRANSPORT]);
         }
         ai_plane->setHeading(heading);
         ai_plane->setSpeed(speed);
@@ -222,6 +228,32 @@ int FGAIManager::createAircraft( string model_class, string path,
 }
 
 
+int FGAIManager::createAircraft( string model_class, string path,
+              FGAIFlightPlan* flightplan ) {
+     
+        FGAIAircraft* ai_plane = new FGAIAircraft(this);
+        ai_list.push_back(ai_plane);
+        ai_plane->setID( assignID() );
+        ++numObjects;
+        if (model_class == "light") {
+          ai_plane->SetPerformance(&FGAIAircraft::settings[FGAIAircraft::LIGHT]);
+        } else if (model_class == "ww2_fighter") {
+          ai_plane->SetPerformance(&FGAIAircraft::settings[FGAIAircraft::WW2_FIGHTER]);
+        } else if (model_class ==  "jet_transport") {
+          ai_plane->SetPerformance(&FGAIAircraft::settings[FGAIAircraft::JET_TRANSPORT]);
+        } else if (model_class == "jet_fighter") {
+          ai_plane->SetPerformance(&FGAIAircraft::settings[FGAIAircraft::JET_FIGHTER]);
+        } else {
+          ai_plane->SetPerformance(&FGAIAircraft::settings[FGAIAircraft::JET_TRANSPORT]);
+        }
+        ai_plane->setPath(path.c_str());
+        ai_plane->SetFlightPlan(flightplan);
+        ai_plane->init();
+        ai_plane->bind();
+        return ai_plane->getID();
+}
+
+
 int FGAIManager::createShip( string path, double latitude, double longitude,
                              double altitude, double heading, double speed,
                              double rudder ) {
@@ -336,3 +368,16 @@ void FGAIManager::processThermal( FGAIThermal* thermal ) {
      strength = thermal->getStrength();
   }
 }
+
+
+void FGAIManager::processScenario( string filename ) {
+  //cout << "AIManager: creating a scenario." << endl;
+  FGAIScenario* s = new FGAIScenario( filename );
+  FGAIScenario::entry* en = s->getNextEntry();
+  if (en) {
+    FGAIFlightPlan* f = new FGAIFlightPlan( en->flightplan );
+    createAircraft("jet_transport", "Aircraft/737/Models/boeing733.xml", f);
+  }
+  delete s;
+}
+
index 537d5145eeee77db767ca5b4d00ee76bb704b05e..106d0abb33cf9703e3d38682a19c5830307b5cc6 100644 (file)
@@ -27,6 +27,8 @@
 #include <Main/fg_props.hxx>
 #include <list>
 #include "AIBase.hxx"
+#include "AIScenario.hxx"
+#include "AIFlightPlan.hxx"
 
 SG_USING_STD(list);
 class FGAIThermal;
@@ -75,6 +77,10 @@ public:
                         double pitch = 0,   // in degrees
                         double roll = 0 );  // in degrees
 
+    int createAircraft( string model_class, // see FGAIAircraft.hxx for possible classes
+                        string path,        // path to exterior model
+                        FGAIFlightPlan *flightplan );
+
     int createShip(     string path,        // path to exterior model
                         double latitude,    // in degrees -90 to 90
                         double longitude,   // in degrees -180 to 180
@@ -114,6 +120,8 @@ public:
     inline double get_user_yaw() { return user_yaw; }
     inline double get_user_speed() {return user_speed; }
 
+    void processScenario( string filename );
+
 private:
 
     bool initDone;
diff --git a/src/AIModel/AIScenario.cxx b/src/AIModel/AIScenario.cxx
new file mode 100644 (file)
index 0000000..c714f98
--- /dev/null
@@ -0,0 +1,83 @@
+// FGAIScenario - class for loading an AI scenario
+// Written by David Culp, started May 2004
+// - 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 "AIScenario.hxx"
+#include <simgear/misc/sg_path.hxx>
+#include <simgear/debug/logstream.hxx>
+#include <simgear/structure/exception.hxx>
+#include <simgear/constants.h>
+#ifdef __BORLANDC__
+#  define exception c_exception
+#endif
+#include <simgear/props/props.hxx>
+#include <Main/globals.hxx>
+#include <Main/fg_props.hxx>
+
+
+FGAIScenario::FGAIScenario(string filename)
+{
+  int i;
+  SGPath path( globals->get_fg_root() );
+  path.append( ("/Data/AI/" + filename + ".xml").c_str() );
+  SGPropertyNode root;
+
+  try {
+      readProperties(path.str(), &root);
+  } catch (const sg_exception &e) {
+      SG_LOG(SG_GENERAL, SG_ALERT,
+       "Incorrect path specified for AI scenario: ");
+       cout << path.str() << endl;
+      return;
+  }
+
+  SGPropertyNode * node = root.getNode("SCENARIO");
+  for (i = 0; i < node->nChildren(); i++) { 
+     //cout << "Reading entry " << i << endl;        
+     entry* en = new entry;
+     entries.push_back( en );
+     SGPropertyNode * entry_node = node->getChild(i);
+     en->callsign       = entry_node->getStringValue("CALLSIGN", "none");
+     en->aircraft_class = entry_node->getStringValue("CLASS", "jet_transport");
+     en->model_path     = entry_node->getStringValue("MODEL", "Models/Geometry/glider.ac");
+     en->flightplan     = entry_node->getStringValue("FLIGHTPLAN", "");
+   }
+
+  entry_iterator = entries.begin();
+  //cout << entries.size() << " entries read." << endl;
+}
+
+
+FGAIScenario::~FGAIScenario()
+{
+  entries.clear();
+}
+
+
+FGAIScenario::entry*
+FGAIScenario::getNextEntry( void )
+{
+  return *entry_iterator;
+}
+
+int FGAIScenario::nEntries( void )
+{
+  return entries.size();
+}
+
+
diff --git a/src/AIModel/AIScenario.hxx b/src/AIModel/AIScenario.hxx
new file mode 100644 (file)
index 0000000..2e35d91
--- /dev/null
@@ -0,0 +1,59 @@
+// FGAIScenario - class for loading an AI scenario
+// Written by David Culp, started May 2004
+// - 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_AISCENARIO_HXX
+#define _FG_AISCENARIO_HXX
+
+#include <simgear/compiler.h>
+#include <vector>
+#include <string>
+SG_USING_STD(vector);
+SG_USING_STD(string);
+
+
+class FGAIScenario {
+
+public:
+
+  typedef struct {
+   string callsign;
+   string aircraft_class;
+   string model_path;
+   string flightplan;
+  } entry;
+
+   FGAIScenario(string filename);
+   ~FGAIScenario();
+
+   entry* getNextEntry( void );
+   int nEntries( void );
+
+private:
+
+    typedef vector <entry*> entry_vector_type;
+    typedef entry_vector_type::iterator entry_vector_iterator;
+
+    entry_vector_type       entries;
+    entry_vector_iterator   entry_iterator;
+
+
+};    
+
+
+#endif  // _FG_AISCENARIO_HXX
+
index 71bf3c5292bcd8cf0a738fb8217325ff1b2b3cd2..54bff8b5e4a674a59c0dab5f97352ddb6d124213 100644 (file)
@@ -4,9 +4,11 @@ libAIModel_a_SOURCES = \
        AIManager.hxx AIManager.cxx \
        AIBase.hxx AIBase.cxx \
        AIAircraft.hxx AIAircraft.cxx \
-        AIShip.hxx AIShip.cxx \
-        AIBallistic.hxx AIBallistic.cxx \
+       AIShip.hxx AIShip.cxx \
+       AIBallistic.hxx AIBallistic.cxx \
        AIStorm.hxx AIStorm.cxx \
-       AIThermal.hxx AIThermal.cxx
+       AIThermal.hxx AIThermal.cxx \
+       AIFlightPlan.hxx AIFlightPlan.cxx \
+       AIScenario.hxx AIScenario.cxx
 
 INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/src