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.
This commit is contained in:
parent
ef12314346
commit
85a1e5cc98
10 changed files with 392 additions and 77 deletions
|
@ -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;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -27,7 +27,8 @@
|
|||
#include "AIBallistic.hxx"
|
||||
|
||||
|
||||
FGAIBallistic::FGAIBallistic() {
|
||||
FGAIBallistic::FGAIBallistic(FGAIManager* mgr) {
|
||||
manager = mgr;
|
||||
_type_str = "ballistic";
|
||||
}
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ class FGAIBallistic : public FGAIBase {
|
|||
|
||||
public:
|
||||
|
||||
FGAIBallistic();
|
||||
FGAIBallistic(FGAIManager* mgr);
|
||||
~FGAIBallistic();
|
||||
|
||||
bool init();
|
||||
|
|
|
@ -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<double>(&speed));
|
||||
props->tie("id", SGRawValuePointer<int>(&id));
|
||||
props->tie("velocities/true-airspeed-kt", SGRawValuePointer<double>(&speed));
|
||||
props->tie("velocities/vertical-speed-fps",
|
||||
SGRawValueFunctions<double>(FGAIBase::_getVS_fps,
|
||||
FGAIBase::_setVS_fps));
|
||||
|
@ -108,7 +112,17 @@ void FGAIBase::bind() {
|
|||
|
||||
props->tie("orientation/pitch-deg", SGRawValuePointer<double>(&pitch));
|
||||
props->tie("orientation/roll-deg", SGRawValuePointer<double>(&roll));
|
||||
props->tie("orientation/heading-deg", SGRawValuePointer<double>(&hdg));
|
||||
props->tie("orientation/true-heading-deg", SGRawValuePointer<double>(&hdg));
|
||||
|
||||
props->tie("radar/bearing-deg", SGRawValueFunctions<double>(FGAIBase::_getBearing));
|
||||
props->tie("radar/elevation-deg", SGRawValueFunctions<double>(FGAIBase::_getElevation));
|
||||
props->tie("radar/range-nm", SGRawValueFunctions<double>(FGAIBase::_getRange));
|
||||
// props->tie("radar/rdot-kts", SGRawValueFunctions<double>(FGAIBase::_getRdot));
|
||||
props->tie("radar/h-offset", SGRawValueFunctions<double>(FGAIBase::_getH_offset));
|
||||
props->tie("radar/v-offset", SGRawValueFunctions<double>(FGAIBase::_getV_offset));
|
||||
props->tie("radar/x-shift", SGRawValueFunctions<double>(FGAIBase::_getX_shift));
|
||||
props->tie("radar/y-shift", SGRawValueFunctions<double>(FGAIBase::_getY_shift));
|
||||
props->tie("radar/rotation", SGRawValueFunctions<double>(FGAIBase::_getRotation));
|
||||
|
||||
props->tie("controls/lighting/nav-lights",
|
||||
SGRawValueFunctions<bool>(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");
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
for (int i = 0; i < node->nChildren(); i++) {
|
||||
const SGPropertyNode * entry = node->getChild(i);
|
||||
void FGAIManager::init() {
|
||||
int rval;
|
||||
root = fgGetNode("sim/ai", true);
|
||||
|
||||
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]);
|
||||
|
||||
} 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(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();
|
||||
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 (!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 = createShip( entry->getStringValue("path"),
|
||||
entry->getDoubleValue("latitude"),
|
||||
entry->getDoubleValue("longitude"),
|
||||
entry->getDoubleValue("altitude-ft"),
|
||||
entry->getDoubleValue("heading"),
|
||||
entry->getDoubleValue("speed-KTAS"),
|
||||
entry->getDoubleValue("rudder") );
|
||||
|
||||
} 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();
|
||||
|
||||
rval = createBallistic( entry->getStringValue("path"),
|
||||
entry->getDoubleValue("latitude"),
|
||||
entry->getDoubleValue("longitude"),
|
||||
entry->getDoubleValue("altitude-ft"),
|
||||
entry->getDoubleValue("azimuth"),
|
||||
entry->getDoubleValue("elevation"),
|
||||
entry->getDoubleValue("speed") );
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -109,33 +98,166 @@ void FGAIManager::init() {
|
|||
|
||||
|
||||
void FGAIManager::bind() {
|
||||
root = globals->get_props()->getNode("ai/models", true);
|
||||
root->tie("count", SGRawValuePointer<int>(&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; x<maxint; x++) {
|
||||
used = false;
|
||||
id_itr = ids.begin();
|
||||
while( id_itr != ids.end() ) {
|
||||
if ((*id_itr) == x) used = true;
|
||||
++id_itr;
|
||||
}
|
||||
if (!used) {
|
||||
ids.push_back(x);
|
||||
return x;
|
||||
}
|
||||
}
|
||||
return -1; // no available ID's
|
||||
}
|
||||
|
||||
|
||||
// This function removes an ID from the ID array, making it
|
||||
// available for assignment to another AI object
|
||||
void FGAIManager::freeID( int ID ) {
|
||||
id_itr = ids.begin();
|
||||
while( id_itr != ids.end() ) {
|
||||
if (*id_itr == ID) {
|
||||
ids.erase( id_itr );
|
||||
return;
|
||||
}
|
||||
++id_itr;
|
||||
}
|
||||
}
|
||||
|
||||
int FGAIManager::createAircraft( string model_class, string path,
|
||||
double latitude, double longitude, double altitude,
|
||||
double heading, double speed, double pitch, double roll ) {
|
||||
|
||||
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]);
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,6 +47,11 @@ private:
|
|||
ai_list_type ai_list;
|
||||
ai_list_iterator ai_list_itr;
|
||||
|
||||
// array of already-assigned ID's
|
||||
typedef vector <int> 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 );
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -27,7 +27,8 @@
|
|||
#include "AIShip.hxx"
|
||||
|
||||
|
||||
FGAIShip::FGAIShip() {
|
||||
FGAIShip::FGAIShip(FGAIManager* mgr) {
|
||||
manager = mgr;
|
||||
hdg_lock = false;
|
||||
rudder = 0.0;
|
||||
_type_str = "ship";
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Add table
Reference in a new issue