From 1dfe93d5509247b537f606ea2b3554ec8b4752ef Mon Sep 17 00:00:00 2001 From: ehofman Date: Sat, 15 May 2004 09:07:55 +0000 Subject: [PATCH] David Culp: 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 "EOF". --- src/AIModel/AIAircraft.cxx | 138 +++++++++++++++++++++++++--- src/AIModel/AIAircraft.hxx | 8 +- src/AIModel/AIBase.cxx | 1 + src/AIModel/AIFlightPlan.cxx | 171 +++++++++++++++++++++++++++++++++++ src/AIModel/AIFlightPlan.hxx | 75 +++++++++++++++ src/AIModel/AIManager.cxx | 45 +++++++++ src/AIModel/AIManager.hxx | 8 ++ src/AIModel/AIScenario.cxx | 83 +++++++++++++++++ src/AIModel/AIScenario.hxx | 59 ++++++++++++ src/AIModel/Makefile.am | 8 +- 10 files changed, 579 insertions(+), 17 deletions(-) create mode 100644 src/AIModel/AIFlightPlan.cxx create mode 100644 src/AIModel/AIFlightPlan.hxx create mode 100644 src/AIModel/AIScenario.cxx create mode 100644 src/AIModel/AIScenario.hxx diff --git a/src/AIModel/AIAircraft.cxx b/src/AIModel/AIAircraft.cxx index 717f9a1e7..bbed46642 100644 --- a/src/AIModel/AIAircraft.cxx +++ b/src/AIModel/AIAircraft.cxx @@ -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 ); + } + } + + } + +} + + diff --git a/src/AIModel/AIAircraft.hxx b/src/AIModel/AIAircraft.hxx index 6ea34c092..fb62588e2 100644 --- a/src/AIModel/AIAircraft.hxx +++ b/src/AIModel/AIAircraft.hxx @@ -23,6 +23,7 @@ #include "AIManager.hxx" #include "AIBase.hxx" +#include "AIFlightPlan.hxx" #include 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); diff --git a/src/AIModel/AIBase.cxx b/src/AIModel/AIBase.cxx index bb1af2279..18af4a9aa 100644 --- a/src/AIModel/AIBase.cxx +++ b/src/AIModel/AIBase.cxx @@ -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 index 000000000..16ddb3daa --- /dev/null +++ b/src/AIModel/AIFlightPlan.cxx @@ -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 +#include +#include +#include +#ifdef __BORLANDC__ +# define exception c_exception +#endif +#include +#include
+#include
+ + +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 index 000000000..e511c2c16 --- /dev/null +++ b/src/AIModel/AIFlightPlan.hxx @@ -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 +#include +#include +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 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 + diff --git a/src/AIModel/AIManager.cxx b/src/AIModel/AIManager.cxx index ceffc4c4a..9e5e7fb3c 100644 --- a/src/AIModel/AIManager.cxx +++ b/src/AIModel/AIManager.cxx @@ -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; +} + diff --git a/src/AIModel/AIManager.hxx b/src/AIModel/AIManager.hxx index 537d5145e..106d0abb3 100644 --- a/src/AIModel/AIManager.hxx +++ b/src/AIModel/AIManager.hxx @@ -27,6 +27,8 @@ #include
#include #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 index 000000000..c714f9847 --- /dev/null +++ b/src/AIModel/AIScenario.cxx @@ -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 +#include +#include +#include +#ifdef __BORLANDC__ +# define exception c_exception +#endif +#include +#include
+#include
+ + +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 index 000000000..2e35d91b7 --- /dev/null +++ b/src/AIModel/AIScenario.hxx @@ -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 +#include +#include +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_vector_type; + typedef entry_vector_type::iterator entry_vector_iterator; + + entry_vector_type entries; + entry_vector_iterator entry_iterator; + + +}; + + +#endif // _FG_AISCENARIO_HXX + diff --git a/src/AIModel/Makefile.am b/src/AIModel/Makefile.am index 71bf3c529..54bff8b5e 100644 --- a/src/AIModel/Makefile.am +++ b/src/AIModel/Makefile.am @@ -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 -- 2.39.5