From 85a1e5cc983169594563763c903436c8f1cfa934 Mon Sep 17 00:00:00 2001 From: ehofman Date: Fri, 27 Feb 2004 10:20:17 +0000 Subject: [PATCH] David Culp: Here's a new batch of AI code which includes a working radar instrument. I put the radar calculations into the existing AIAircraft class. It was easier that way, and it can always be migrated out later if we have to. Every tenth sim cycle the AIManager makes a copy of the current user state information. When the AIAircraft updates it uses this information to calculate the radar numbers. It calculates: 1) bearing from user to target 2) range to target in nautical miles 3) "horizontal offset" to target. This is the angle from the nose to the target, in degrees, from -180 to 180. This will be useful later for a HUD. 4) elevation, in degrees (vertical angle from user's position to target position) 5) vertical offset, in degrees (this is elevation corrected for user's pitch) 6) rdot (range rate in knots, note: not working yet, so I commented it out) and three items used by the radar instrument to place the "blip" 7) y_shift, in nautical miles 8) x_shift, in nautical miles 9) rotation, in degrees The radar instrument uses the above three items, and applies a scale factor to the x-shift and y-shift in order to match the instrument's scale. Changing the display scale can be done entirely in the XML code for the instrument. Right now it's set up only to display a 40 mile scale. The radar is an AWACS view, which is not very realistic, but it is useful and demonstrates the technology. With just a little more work I can get a HUD marker. All I need to do there is make a bank angle adjustment to the current values. --- src/AIModel/AIAircraft.cxx | 73 ++++++++++- src/AIModel/AIAircraft.hxx | 2 +- src/AIModel/AIBallistic.cxx | 3 +- src/AIModel/AIBallistic.hxx | 2 +- src/AIModel/AIBase.cxx | 33 ++++- src/AIModel/AIBase.hxx | 44 ++++++- src/AIModel/AIManager.cxx | 244 +++++++++++++++++++++++++++--------- src/AIModel/AIManager.hxx | 56 +++++++++ src/AIModel/AIShip.cxx | 3 +- src/AIModel/AIShip.hxx | 5 +- 10 files changed, 390 insertions(+), 75 deletions(-) diff --git a/src/AIModel/AIAircraft.cxx b/src/AIModel/AIAircraft.cxx index 66360d8a5..40c790a16 100644 --- a/src/AIModel/AIAircraft.cxx +++ b/src/AIModel/AIAircraft.cxx @@ -51,7 +51,8 @@ const FGAIAircraft::PERF_STRUCT FGAIAircraft::settings[] = { FGAIAircraft *FGAIAircraft::_self = NULL; -FGAIAircraft::FGAIAircraft() { +FGAIAircraft::FGAIAircraft(FGAIManager* mgr) { + manager = mgr; _self = this; // set heading and altitude locks @@ -173,10 +174,10 @@ void FGAIAircraft::Run(double 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; // find target vertical speed if altitude lock engaged if (alt_lock) { - double altitude_ft = altitude * SG_METER_TO_FEET; if (altitude_ft < tgt_altitude) { tgt_vs = tgt_altitude - altitude_ft; if (tgt_vs > performance->climb_rate) @@ -203,6 +204,74 @@ void FGAIAircraft::Run(double dt) { // match pitch angle to vertical speed pitch = vs * 0.005; + //###########################// + // do calculations for radar // + //###########################// + + // copy values from the AIManager + double user_latitude = manager->get_user_latitude(); + double user_longitude = manager->get_user_longitude(); + double user_altitude = manager->get_user_altitude(); + 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(); + + // calculate range to target in feet and nautical miles + double lat_range = fabs(pos.lat() - user_latitude) * ft_per_deg_lat; + double lon_range = fabs(pos.lon() - user_longitude) * ft_per_deg_lon; + double range_ft = sqrt( lat_range*lat_range + lon_range*lon_range ); + range = range_ft / 6076.11549; + + // calculate bearing to target + if (pos.lat() >= user_latitude) { + bearing = atan2(lat_range, lon_range) * SG_RADIANS_TO_DEGREES; + if (pos.lon() >= user_longitude) { + bearing = 90.0 - bearing; + } else { + bearing = 270.0 + bearing; + } + } else { + bearing = atan2(lon_range, lat_range) * SG_RADIANS_TO_DEGREES; + if (pos.lon() >= user_longitude) { + bearing = 180.0 - bearing; + } else { + bearing = 180.0 + bearing; + } + } + + // calculate look left/right to target, without yaw correction + horiz_offset = bearing - user_heading; + if (horiz_offset > 180.0) horiz_offset -= 360.0; + if (horiz_offset < -180.0) horiz_offset += 360.0; + + // calculate elevation to target + elevation = atan2( altitude_ft - user_altitude, range_ft ) + * SG_RADIANS_TO_DEGREES; + + // calculate look up/down to target + vert_offset = elevation + user_pitch; + +/* this calculation needs to be fixed + // calculate range rate + double recip_bearing = bearing + 180.0; + if (recip_bearing > 360.0) recip_bearing -= 360.0; + double my_horiz_offset = recip_bearing - hdg; + if (my_horiz_offset > 180.0) my_horiz_offset -= 360.0; + if (my_horiz_offset < -180.0) my_horiz_offset += 360.0; + rdot = (-user_speed * cos( horiz_offset * SG_DEGREES_TO_RADIANS )) + + (-speed * 1.686 * cos( my_horiz_offset * SG_DEGREES_TO_RADIANS )); +*/ + + // now correct look left/right for yaw + horiz_offset += user_yaw; + + // calculate values for radar display + y_shift = range * cos( horiz_offset * SG_DEGREES_TO_RADIANS); + x_shift = range * sin( horiz_offset * SG_DEGREES_TO_RADIANS); + rotation = hdg - user_heading; + if (rotation < 0.0) rotation += 360.0; + } diff --git a/src/AIModel/AIAircraft.hxx b/src/AIModel/AIAircraft.hxx index 8d16f381e..6ea34c092 100644 --- a/src/AIModel/AIAircraft.hxx +++ b/src/AIModel/AIAircraft.hxx @@ -49,7 +49,7 @@ public: enum aircraft_e {LIGHT=0, WW2_FIGHTER, JET_TRANSPORT, JET_FIGHTER}; static const PERF_STRUCT settings[]; - FGAIAircraft(); + FGAIAircraft(FGAIManager* mgr); ~FGAIAircraft(); bool init(); diff --git a/src/AIModel/AIBallistic.cxx b/src/AIModel/AIBallistic.cxx index 86703da9c..0e7249e4e 100644 --- a/src/AIModel/AIBallistic.cxx +++ b/src/AIModel/AIBallistic.cxx @@ -27,7 +27,8 @@ #include "AIBallistic.hxx" -FGAIBallistic::FGAIBallistic() { +FGAIBallistic::FGAIBallistic(FGAIManager* mgr) { + manager = mgr; _type_str = "ballistic"; } diff --git a/src/AIModel/AIBallistic.hxx b/src/AIModel/AIBallistic.hxx index 3878778b9..479dc44e5 100644 --- a/src/AIModel/AIBallistic.hxx +++ b/src/AIModel/AIBallistic.hxx @@ -28,7 +28,7 @@ class FGAIBallistic : public FGAIBase { public: - FGAIBallistic(); + FGAIBallistic(FGAIManager* mgr); ~FGAIBallistic(); bool init(); diff --git a/src/AIModel/AIBase.cxx b/src/AIModel/AIBase.cxx index 16f956ec6..baa13f865 100644 --- a/src/AIModel/AIBase.cxx +++ b/src/AIModel/AIBase.cxx @@ -48,9 +48,12 @@ FGAIBase::FGAIBase() { _self = this; _type_str = "model"; tgt_roll = roll = tgt_pitch = tgt_yaw = tgt_vs = vs = pitch = 0.0; + bearing = elevation = range = rdot = 0.0; + x_shift = y_shift = rotation = 0.0; } FGAIBase::~FGAIBase() { + unbind(); _self = NULL; } @@ -91,7 +94,8 @@ bool FGAIBase::init() { } void FGAIBase::bind() { - props->tie("velocities/airspeed-kt", SGRawValuePointer(&speed)); + props->tie("id", SGRawValuePointer(&id)); + props->tie("velocities/true-airspeed-kt", SGRawValuePointer(&speed)); props->tie("velocities/vertical-speed-fps", SGRawValueFunctions(FGAIBase::_getVS_fps, FGAIBase::_setVS_fps)); @@ -108,7 +112,17 @@ void FGAIBase::bind() { props->tie("orientation/pitch-deg", SGRawValuePointer(&pitch)); props->tie("orientation/roll-deg", SGRawValuePointer(&roll)); - props->tie("orientation/heading-deg", SGRawValuePointer(&hdg)); + props->tie("orientation/true-heading-deg", SGRawValuePointer(&hdg)); + + props->tie("radar/bearing-deg", SGRawValueFunctions(FGAIBase::_getBearing)); + props->tie("radar/elevation-deg", SGRawValueFunctions(FGAIBase::_getElevation)); + props->tie("radar/range-nm", SGRawValueFunctions(FGAIBase::_getRange)); +// props->tie("radar/rdot-kts", SGRawValueFunctions(FGAIBase::_getRdot)); + props->tie("radar/h-offset", SGRawValueFunctions(FGAIBase::_getH_offset)); + props->tie("radar/v-offset", SGRawValueFunctions(FGAIBase::_getV_offset)); + props->tie("radar/x-shift", SGRawValueFunctions(FGAIBase::_getX_shift)); + props->tie("radar/y-shift", SGRawValueFunctions(FGAIBase::_getY_shift)); + props->tie("radar/rotation", SGRawValueFunctions(FGAIBase::_getRotation)); props->tie("controls/lighting/nav-lights", SGRawValueFunctions(FGAIBase::_isNight)); @@ -117,7 +131,8 @@ void FGAIBase::bind() { } void FGAIBase::unbind() { - props->untie("velocities/airspeed-kt"); + props->untie("id"); + props->untie("velocities/true-airspeed-kt"); props->untie("velocities/vertical-speed-fps"); props->untie("position/altitude-ft"); @@ -126,7 +141,17 @@ void FGAIBase::unbind() { props->untie("orientation/pitch-deg"); props->untie("orientation/roll-deg"); - props->untie("orientation/heading-deg"); + props->untie("orientation/true-heading-deg"); + + props->untie("radar/bearing-deg"); + props->untie("radar/elevation-deg"); + props->untie("radar/range-nm"); +// props->untie("radar/rdot-kts"); + props->untie("radar/h-offset"); + props->untie("radar/v-offset"); + props->untie("radar/x-shift"); + props->untie("radar/y-shift"); + props->untie("radar/rotation"); props->untie("controls/controls/lighting/nav-lights"); } diff --git a/src/AIModel/AIBase.hxx b/src/AIModel/AIBase.hxx index 568469542..63e0128fe 100644 --- a/src/AIModel/AIBase.hxx +++ b/src/AIModel/AIBase.hxx @@ -30,6 +30,8 @@ SG_USING_STD(string); +class FGAIManager; + class FGAIBase { public: @@ -51,21 +53,26 @@ public: void setLongitude( double longitude ); void setBank( double bank ); + void setID( int ID ); + int getID(); void setDie( bool die ); bool getDie(); protected: SGPropertyNode *props; + FGAIManager* manager; + // these describe the model's actual state 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 vs; // vertical speed, feet per minute + // these describe the model's desired state double tgt_heading; // target heading, degrees true double tgt_altitude; // target altitude, *feet* above sea level double tgt_speed; // target speed, KTAS @@ -74,10 +81,22 @@ protected: double tgt_yaw; double tgt_vs; + // these describe radar information for the user + double bearing; // true bearing from user to this model + double elevation; // elevation in degrees from user to this model + double range; // range from user to this model, nm + double rdot; // range rate, in knots + double horiz_offset; // look left/right from user to me, deg + double vert_offset; // look up/down from user to me, deg + double x_shift; // value used by radar display instrument + double y_shift; // value used by radar display instrument + double rotation; // value used by radar display instrument + string model_path; //Path to the 3D model SGModelPlacement aip; bool delete_me; + int id; void Transform(); @@ -98,6 +117,16 @@ public: static double _getLongitude(); static double _getLatitude (); + static double _getBearing(); + static double _getElevation(); + static double _getRange(); + static double _getRdot(); + static double _getH_offset(); + static double _getV_offset(); + static double _getX_shift(); + static double _getY_shift(); + static double _getRotation(); + static bool _isNight(); }; @@ -143,6 +172,16 @@ inline void FGAIBase::_setLatitude ( double latitude ) { inline double FGAIBase::_getLongitude() { return _self->pos.lon(); } inline double FGAIBase::_getLatitude () { return _self->pos.lat(); } +inline double FGAIBase::_getBearing() { return _self->bearing; } +inline double FGAIBase::_getElevation() { return _self->elevation; } +inline double FGAIBase::_getRange() { return _self->range; } +inline double FGAIBase::_getRdot() { return _self->rdot; } +inline double FGAIBase::_getH_offset() { return _self->horiz_offset; } +inline double FGAIBase::_getV_offset() { return _self->vert_offset; } +inline double FGAIBase::_getX_shift() { return _self->x_shift; } +inline double FGAIBase::_getY_shift() { return _self->y_shift; } +inline double FGAIBase::_getRotation() { return _self->rotation; } + inline double FGAIBase::_getVS_fps() { return _self->vs*60.0; } inline void FGAIBase::_setVS_fps( double _vs ) { _self->vs = _vs/60.0; } @@ -157,5 +196,8 @@ inline bool FGAIBase::_isNight() { return (fgGetFloat("/sim/time/sun-angle-rad") > 1.57); } +inline void FGAIBase::setID( int ID ) { id = ID; } +inline int FGAIBase::getID() { return id; } + #endif // _FG_AIBASE_HXX diff --git a/src/AIModel/AIManager.cxx b/src/AIModel/AIManager.cxx index 52a1c0fd1..b3d3060da 100644 --- a/src/AIModel/AIManager.cxx +++ b/src/AIModel/AIManager.cxx @@ -34,72 +34,61 @@ SG_USING_STD(list); FGAIManager::FGAIManager() { initDone = false; + numObjects = 0; + dt_count = 9; } FGAIManager::~FGAIManager() { + ai_list_itr = ai_list.begin(); + while(ai_list_itr != ai_list.end()) { + delete (*ai_list_itr); + ++ai_list_itr; + } ai_list.clear(); + ids.clear(); } + void FGAIManager::init() { - SGPropertyNode * node = fgGetNode("sim/ai", true); + int rval; + root = fgGetNode("sim/ai", true); - for (int i = 0; i < node->nChildren(); i++) { - const SGPropertyNode * entry = node->getChild(i); + for (int i = 0; i < root->nChildren(); i++) { + const SGPropertyNode * entry = root->getChild(i); if (!strcmp(entry->getName(), "entry")) { if (!strcmp(entry->getStringValue("type", ""), "aircraft")) { - FGAIAircraft* ai_plane = new FGAIAircraft; - ai_list.push_back(ai_plane); - string model_class = entry->getStringValue("class", ""); - if (model_class == "light") { - ai_plane->SetPerformance(&FGAIAircraft::settings[FGAIAircraft::LIGHT]); + rval = createAircraft( entry->getStringValue("class", ""), + entry->getStringValue("path"), + entry->getDoubleValue("latitude"), + entry->getDoubleValue("longitude"), + entry->getDoubleValue("altitude-ft"), + entry->getDoubleValue("heading"), + entry->getDoubleValue("speed-KTAS"), + 0.0, + entry->getDoubleValue("bank") ); - } 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 (!strcmp(entry->getStringValue("type", ""), "ship")) { - } else if (model_class == "jet_fighter") { - ai_plane->SetPerformance(&FGAIAircraft::settings[FGAIAircraft::JET_FIGHTER]); - } + rval = createShip( entry->getStringValue("path"), + entry->getDoubleValue("latitude"), + entry->getDoubleValue("longitude"), + entry->getDoubleValue("altitude-ft"), + entry->getDoubleValue("heading"), + entry->getDoubleValue("speed-KTAS"), + entry->getDoubleValue("rudder") ); - 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->setBank(entry->getDoubleValue("bank")); - ai_plane->init(); - ai_plane->bind(); + } else if (!strcmp(entry->getStringValue("type", ""), "ballistic")) { - } 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->setBank(entry->getDoubleValue("rudder")); - ai_ship->init(); - ai_ship->bind(); + rval = createBallistic( entry->getStringValue("path"), + entry->getDoubleValue("latitude"), + entry->getDoubleValue("longitude"), + entry->getDoubleValue("altitude-ft"), + entry->getDoubleValue("azimuth"), + entry->getDoubleValue("elevation"), + entry->getDoubleValue("speed") ); - } 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(); - ai_ballistic->bind(); } } } @@ -109,33 +98,166 @@ void FGAIManager::init() { void FGAIManager::bind() { + root = globals->get_props()->getNode("ai/models", true); + root->tie("count", SGRawValuePointer(&numObjects)); } void FGAIManager::unbind() { - ai_list_itr = ai_list.begin(); - while(ai_list_itr != ai_list.end()) { - (*ai_list_itr)->unbind(); - ++ai_list_itr; - } + root->untie("count"); } 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); + freeID((*ai_list_itr)->getID()); + delete (*ai_list_itr); + ai_list.erase(ai_list_itr); + --ai_list_itr; + --numObjects; } else { + fetchUserState(); (*ai_list_itr)->update(dt); } ++ai_list_itr; } } + + +// This function returns the next available ID +int FGAIManager::assignID() { + int maxint = 30000; + int x; + bool used; + for (x=0; xsetID( 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]); + } + ai_plane->setHeading(heading); + ai_plane->setSpeed(speed); + ai_plane->setPath(path.c_str()); + ai_plane->setAltitude(altitude); + ai_plane->setLongitude(longitude); + ai_plane->setLatitude(latitude); + ai_plane->setBank(roll); + 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 ) { + + FGAIShip* ai_ship = new FGAIShip(this); + ai_list.push_back(ai_ship); + ai_ship->setID( assignID() ); + ++numObjects; + ai_ship->setHeading(heading); + ai_ship->setSpeed(speed); + ai_ship->setPath(path.c_str()); + ai_ship->setAltitude(altitude); + ai_ship->setLongitude(longitude); + ai_ship->setLatitude(latitude); + ai_ship->setBank(rudder); + ai_ship->init(); + ai_ship->bind(); + return ai_ship->getID(); +} + + +int FGAIManager::createBallistic( string path, double latitude, double longitude, + double altitude, double azimuth, double elevation, + double speed ) { + + FGAIBallistic* ai_ballistic = new FGAIBallistic(this); + ai_list.push_back(ai_ballistic); + ai_ballistic->setID( assignID() ); + ++numObjects; + ai_ballistic->setAzimuth(azimuth); + ai_ballistic->setElevation(elevation); + ai_ballistic->setSpeed(speed); + ai_ballistic->setPath(path.c_str()); + ai_ballistic->setAltitude(altitude); + ai_ballistic->setLongitude(longitude); + ai_ballistic->setLatitude(latitude); + ai_ballistic->init(); + ai_ballistic->bind(); + return ai_ballistic->getID(); +} + +void FGAIManager::destroyObject( int ID ) { + ai_list_itr = ai_list.begin(); + while(ai_list_itr != ai_list.end()) { + if ((*ai_list_itr)->getID() == ID) { + freeID( ID ); + delete (*ai_list_itr); + ai_list.erase(ai_list_itr); + --ai_list_itr; + --numObjects; + return; + } + ++ai_list_itr; + } +} + +// fetch the user's state every 10 sim cycles +void FGAIManager::fetchUserState( void ) { + ++dt_count; + if (dt_count == 10) { + user_latitude = fgGetDouble("/position/latitude-deg"); + user_longitude = fgGetDouble("/position/longitude-deg"); + user_altitude = fgGetDouble("/position/altitude-ft"); + user_heading = fgGetDouble("/orientation/heading-deg"); + user_pitch = fgGetDouble("/orientation/pitch-deg"); + user_yaw = fgGetDouble("/orientation/side-slip-deg"); + user_speed = fgGetDouble("/velocities/uBody-fps") * 0.592484; + dt_count = 0; + } +} diff --git a/src/AIModel/AIManager.hxx b/src/AIModel/AIManager.hxx index 32098fcd7..9b668f4cc 100644 --- a/src/AIModel/AIManager.hxx +++ b/src/AIModel/AIManager.hxx @@ -47,6 +47,11 @@ private: ai_list_type ai_list; ai_list_iterator ai_list_itr; + // array of already-assigned ID's + typedef vector id_vector_type; + id_vector_type ids; + id_vector_type::iterator id_itr; + public: enum object_type { otAircraft, otShip, otBallistic, otRocket }; @@ -59,10 +64,61 @@ public: void unbind(); void update(double dt); + int assignID(); + void freeID(int ID); + + int createAircraft( string model_class, // see FGAIAircraft.hxx for possible classes + string path, // path to exterior model + double latitude, // in degrees -90 to 90 + double longitude, // in degrees -180 to 180 + double altitude, // in feet + double heading, // true heading in degrees + double speed, // in knots true airspeed (KTAS) + double pitch = 0, // in degrees + double roll = 0 ); // in degrees + + int createShip( string path, // path to exterior model + double latitude, // in degrees -90 to 90 + double longitude, // in degrees -180 to 180 + double altitude, // in feet (ex. for a lake!) + double heading, // true heading in degrees + double speed, // in knots true + double rudder ); // in degrees (between 0 and 5 works best) + + + int createBallistic( string path, // path to exterior model + double latitude, // in degrees -90 to 90 + double longitude, // in degrees -180 to 180 + double altitude, // in feet + double azimuth, // in degrees (same as heading) + double elevation, // in degrees (same as pitch) + double speed ); // in feet per second + + void destroyObject( int ID ); + + inline double get_user_latitude() { return user_latitude; } + inline double get_user_longitude() { return user_longitude; } + inline double get_user_altitude() { return user_altitude; } + inline double get_user_heading() { return user_heading; } + inline double get_user_pitch() { return user_pitch; } + inline double get_user_yaw() { return user_yaw; } + inline double get_user_speed() {return user_speed; } private: bool initDone; + int numObjects; + SGPropertyNode* root; + + double user_latitude; + double user_longitude; + double user_altitude; + double user_heading; + double user_pitch; + double user_yaw; + double user_speed; + int dt_count; + void fetchUserState( void ); }; diff --git a/src/AIModel/AIShip.cxx b/src/AIModel/AIShip.cxx index bd9ebb09f..d9fc379fe 100644 --- a/src/AIModel/AIShip.cxx +++ b/src/AIModel/AIShip.cxx @@ -27,7 +27,8 @@ #include "AIShip.hxx" -FGAIShip::FGAIShip() { +FGAIShip::FGAIShip(FGAIManager* mgr) { + manager = mgr; hdg_lock = false; rudder = 0.0; _type_str = "ship"; diff --git a/src/AIModel/AIShip.hxx b/src/AIModel/AIShip.hxx index d4d29f022..1fc583ca0 100644 --- a/src/AIModel/AIShip.hxx +++ b/src/AIModel/AIShip.hxx @@ -21,15 +21,14 @@ #ifndef _FG_AISHIP_HXX #define _FG_AISHIP_HXX -#include "AIManager.hxx" #include "AIBase.hxx" - +class FGAIManager; class FGAIShip : public FGAIBase { public: - FGAIShip(); + FGAIShip(FGAIManager* mgr); ~FGAIShip(); bool init(); -- 2.39.5