1
0
Fork 0

Merge branch 'next' of git://gitorious.org/fg/flightgear into next

This commit is contained in:
Frederic Bouvier 2010-09-01 19:24:44 +02:00
commit a2ffbba23e
16 changed files with 2482 additions and 1982 deletions

View file

@ -39,34 +39,35 @@ const double FGAIBallistic::slugs_to_kgs = 14.5939029372;
const double FGAIBallistic::slugs_to_lbs = 32.1740485564; const double FGAIBallistic::slugs_to_lbs = 32.1740485564;
FGAIBallistic::FGAIBallistic(object_type ot) : FGAIBallistic::FGAIBallistic(object_type ot) :
FGAIBase(ot), FGAIBase(ot),
_height(0.0), _height(0.0),
_ht_agl_ft(0.0), _ht_agl_ft(0.0),
_azimuth(0.0), _azimuth(0.0),
_elevation(0.0), _elevation(0.0),
_rotation(0.0), _rotation(0.0),
_formate_to_ac(false), _formate_to_ac(false),
_aero_stabilised(false), _aero_stabilised(false),
_drag_area(0.007), _drag_area(0.007),
_life_timer(0.0), _life_timer(0.0),
_gravity(32.1740485564), _gravity(32.1740485564),
_buoyancy(0), _buoyancy(0),
_wind(true), _wind(true),
_mass(0), _mass(0),
_random(false), _random(false),
_load_resistance(0), _load_resistance(0),
_solid(false), _solid(false),
_force_stabilised(false), _force_stabilised(false),
_slave_to_ac(false), _slave_to_ac(false),
_slave_load_to_ac(false), _slave_load_to_ac(false),
_contents_lb(0), _contents_lb(0),
_report_collision(false), _report_collision(false),
_report_expiry(false), _report_expiry(false),
_report_impact(false), _report_impact(false),
_external_force(false), _external_force(false),
_impact_report_node(fgGetNode("/ai/models/model-impact", true)), _impact_report_node(fgGetNode("/ai/models/model-impact", true)),
_old_height(0), _old_height(0),
_elapsed_time(0) _elapsed_time(0),
hs(0)
{ {
no_roll = false; no_roll = false;
@ -83,14 +84,14 @@ void FGAIBallistic::readFromScenario(SGPropertyNode* scFileNode) {
FGAIBase::readFromScenario(scFileNode); FGAIBase::readFromScenario(scFileNode);
//setPath(scFileNode->getStringValue("model", "Models/Geometry/rocket.ac")); //setPath(scFileNode->getStringValue("model", "Models/Geometry/rocket.ac"));
setRandom(scFileNode->getBoolValue("random", false)); setRandom(scFileNode->getBoolValue("random", false));
setAzimuth(scFileNode->getDoubleValue("azimuth", 0.0)); setAzimuth(scFileNode->getDoubleValue("azimuth", 0.0));
setElevation(scFileNode->getDoubleValue("elevation", 0)); setElevation(scFileNode->getDoubleValue("elevation", 0));
setDragArea(scFileNode->getDoubleValue("eda", 0.007)); setDragArea(scFileNode->getDoubleValue("eda", 0.007));
setLife(scFileNode->getDoubleValue("life", 900.0)); setLife(scFileNode->getDoubleValue("life", 900.0));
setBuoyancy(scFileNode->getDoubleValue("buoyancy", 0)); setBuoyancy(scFileNode->getDoubleValue("buoyancy", 0));
setWind_from_east(scFileNode->getDoubleValue("wind_from_east", 0)); //setWind_from_east(scFileNode->getDoubleValue("wind_from_east", 0));
setWind_from_north(scFileNode->getDoubleValue("wind_from_north", 0)); //setWind_from_north(scFileNode->getDoubleValue("wind_from_north", 0));
setWind(scFileNode->getBoolValue("wind", false)); setWind(scFileNode->getBoolValue("wind", false));
setRoll(scFileNode->getDoubleValue("roll", 0.0)); setRoll(scFileNode->getDoubleValue("roll", 0.0));
setCd(scFileNode->getDoubleValue("cd", 0.029)); setCd(scFileNode->getDoubleValue("cd", 0.029));
@ -99,8 +100,8 @@ void FGAIBallistic::readFromScenario(SGPropertyNode* scFileNode) {
setStabilisation(scFileNode->getBoolValue("aero-stabilised", false)); setStabilisation(scFileNode->getBoolValue("aero-stabilised", false));
setNoRoll(scFileNode->getBoolValue("no-roll", false)); setNoRoll(scFileNode->getBoolValue("no-roll", false));
setImpact(scFileNode->getBoolValue("impact", false)); setImpact(scFileNode->getBoolValue("impact", false));
setExpiry(scFileNode->getBoolValue("expiry", false)); setExpiry(scFileNode->getBoolValue("expiry", false));
setCollision(scFileNode->getBoolValue("collision", false)); setCollision(scFileNode->getBoolValue("collision", false));
setImpactReportNode(scFileNode->getStringValue("impact-reports")); setImpactReportNode(scFileNode->getStringValue("impact-reports"));
setName(scFileNode->getStringValue("name", "Rocket")); setName(scFileNode->getStringValue("name", "Rocket"));
setFuseRange(scFileNode->getDoubleValue("fuse-range", 0.0)); setFuseRange(scFileNode->getDoubleValue("fuse-range", 0.0));
@ -119,7 +120,7 @@ void FGAIBallistic::readFromScenario(SGPropertyNode* scFileNode) {
setLoadOffset(scFileNode->getDoubleValue("load-offset", 0.0)); setLoadOffset(scFileNode->getDoubleValue("load-offset", 0.0));
setSlaved(scFileNode->getBoolValue("slaved", false)); setSlaved(scFileNode->getBoolValue("slaved", false));
setSlavedLoad(scFileNode->getBoolValue("slaved-load", false)); setSlavedLoad(scFileNode->getBoolValue("slaved-load", false));
setContentsNode(scFileNode->getStringValue("contents")); setContentsPath(scFileNode->getStringValue("contents"));
} }
bool FGAIBallistic::init(bool search_in_AI_path) { bool FGAIBallistic::init(bool search_in_AI_path) {
@ -127,9 +128,9 @@ bool FGAIBallistic::init(bool search_in_AI_path) {
_impact_reported = false; _impact_reported = false;
_collision_reported = false; _collision_reported = false;
_expiry_reported = false; _expiry_reported = false;
_impact_lat = 0; _impact_lat = 0;
_impact_lon = 0; _impact_lon = 0;
_impact_elev = 0; _impact_elev = 0;
_impact_hdg = 0; _impact_hdg = 0;
@ -143,9 +144,14 @@ bool FGAIBallistic::init(bool search_in_AI_path) {
props->setStringValue("material/name", ""); props->setStringValue("material/name", "");
props->setStringValue("name", _name.c_str()); props->setStringValue("name", _name.c_str());
props->setStringValue("submodels/path", _submodel.c_str()); props->setStringValue("submodels/path", _path.c_str());
props->setStringValue("force/path", _force_path.c_str());
//props->setStringValue("vector/path", _vector_path.c_str()); if (_slave_to_ac){
props->setStringValue("force/path", _force_path.c_str());
props->setStringValue("contents/path", _contents_path.c_str());
}
//props->setStringValue("vector/path", _vector_path.c_str());
// start with high value so that animations don't trigger yet // start with high value so that animations don't trigger yet
_ht_agl_ft = 1e10; _ht_agl_ft = 1e10;
@ -155,6 +161,8 @@ bool FGAIBallistic::init(bool search_in_AI_path) {
Transform(); Transform();
//cout << _name << " speed init: " << speed << endl;
return true; return true;
} }
@ -164,25 +172,24 @@ void FGAIBallistic::bind() {
props->tie("sim/time/elapsed-sec", props->tie("sim/time/elapsed-sec",
SGRawValueMethods<FGAIBallistic,double>(*this, SGRawValueMethods<FGAIBallistic,double>(*this,
&FGAIBallistic::_getTime)); &FGAIBallistic::_getTime));
props->tie("mass-slug", //props->tie("mass-slug",
SGRawValueMethods<FGAIBallistic,double>(*this, // SGRawValueMethods<FGAIBallistic,double>(*this,
&FGAIBallistic::getMass)); // &FGAIBallistic::getMass));
props->tie("material/load-resistance",
SGRawValuePointer<double>(&_load_resistance));
props->tie("material/solid", props->tie("material/solid",
SGRawValuePointer<bool>(&_solid)); SGRawValuePointer<bool>(&_solid));
props->tie("altitude-agl-ft", props->tie("altitude-agl-ft",
SGRawValuePointer<double>(&_ht_agl_ft)); SGRawValuePointer<double>(&_ht_agl_ft));
props->tie("controls/slave-to-ac", props->tie("controls/slave-to-ac",
SGRawValueMethods<FGAIBallistic,bool> SGRawValueMethods<FGAIBallistic,bool>
(*this, &FGAIBallistic::getSlaved, &FGAIBallistic::setSlaved)); (*this, &FGAIBallistic::getSlaved, &FGAIBallistic::setSlaved));
props->tie("controls/invisible", props->tie("controls/invisible",
SGRawValuePointer<bool>(&invisible)); SGRawValuePointer<bool>(&invisible));
if(_external_force){ if(_external_force || _slave_to_ac){
props->tie("controls/force_stabilized", props->tie("controls/force_stabilized",
SGRawValuePointer<bool>(&_force_stabilised)); SGRawValuePointer<bool>(&_force_stabilised));
props->tie("position/global-x", props->tie("position/global-x",
SGRawValueMethods<FGAIBase,double>(*this, &FGAIBase::_getCartPosX, 0)); SGRawValueMethods<FGAIBase,double>(*this, &FGAIBase::_getCartPosX, 0));
props->tie("position/global-y", props->tie("position/global-y",
SGRawValueMethods<FGAIBase,double>(*this, &FGAIBase::_getCartPosY, 0)); SGRawValueMethods<FGAIBase,double>(*this, &FGAIBase::_getCartPosY, 0));
@ -195,8 +202,8 @@ void FGAIBallistic::bind() {
props->tie("velocities/horizontal-speed-fps", props->tie("velocities/horizontal-speed-fps",
SGRawValuePointer<double>(&hs)); SGRawValuePointer<double>(&hs));
props->tie("position/altitude-ft", props->tie("position/altitude-ft",
SGRawValueMethods<FGAIBase,double>(*this, &FGAIBase::_getAltitude, &FGAIBase::_setAltitude)); SGRawValueMethods<FGAIBase,double>(*this, &FGAIBase::_getElevationFt, &FGAIBase::_setAltitude));
props->tie("position/latitude-deg", props->tie("position/latitude-deg",
SGRawValueMethods<FGAIBase,double>(*this, &FGAIBase::_getLatitude, &FGAIBase::_setLatitude)); SGRawValueMethods<FGAIBase,double>(*this, &FGAIBase::_getLatitude, &FGAIBase::_setLatitude));
props->tie("position/longitude-deg", props->tie("position/longitude-deg",
SGRawValueMethods<FGAIBase,double>(*this, &FGAIBase::_getLongitude, &FGAIBase::_setLongitude)); SGRawValueMethods<FGAIBase,double>(*this, &FGAIBase::_getLongitude, &FGAIBase::_setLongitude));
@ -221,22 +228,23 @@ void FGAIBallistic::bind() {
props->tie("load/bearing-to-hitch-deg", props->tie("load/bearing-to-hitch-deg",
SGRawValueMethods<FGAIBallistic,double> SGRawValueMethods<FGAIBallistic,double>
(*this, &FGAIBallistic::getBearingLoadToHitch)); (*this, &FGAIBallistic::getBearingLoadToHitch));
props->tie("material/load-resistance",
SGRawValuePointer<double>(&_load_resistance));
} }
} }
void FGAIBallistic::unbind() { void FGAIBallistic::unbind() {
// FGAIBase::unbind(); // FGAIBase::unbind();
props->untie("sim/time/elapsed-sec"); props->untie("sim/time/elapsed-sec");
props->untie("mass-slug"); props->untie("mass-slug");
props->untie("material/load-resistance");
props->untie("material/solid"); props->untie("material/solid");
props->untie("altitude-agl-ft"); props->untie("altitude-agl-ft");
props->untie("controls/slave-to-ac"); props->untie("controls/slave-to-ac");
props->untie("controls/invisible"); props->untie("controls/invisible");
if(_external_force){ if(_external_force || _slave_to_ac){
props->untie("position/global-y"); props->untie("position/global-y");
props->untie("position/global-x"); props->untie("position/global-x");
props->untie("position/global-z"); props->untie("position/global-z");
@ -255,6 +263,7 @@ void FGAIBallistic::unbind() {
props->untie("load/distance-to-hitch-ft"); props->untie("load/distance-to-hitch-ft");
props->untie("load/elevation-to-hitch-deg"); props->untie("load/elevation-to-hitch-deg");
props->untie("load/bearing-to-hitch-deg"); props->untie("load/bearing-to-hitch-deg");
props->untie("material/load-resistance");
} }
} }
@ -262,29 +271,27 @@ void FGAIBallistic::update(double dt) {
FGAIBase::update(dt); FGAIBase::update(dt);
_setUserPos(); _setUserPos();
if (_slave_to_ac){ if (_formate_to_ac){
slaveToAC(dt);
Transform();
setHitchVelocity(dt);
} else if (_formate_to_ac){
formateToAC(dt); formateToAC(dt);
Transform(); Transform();
setHitchVelocity(dt); } else if (_slave_to_ac){
slaveToAC(dt);
Transform();
} else if (!invisible){ } else if (!invisible){
Run(dt); Run(dt);
Transform(); Transform();
} }
} }
void FGAIBallistic::setAzimuth(double az) { void FGAIBallistic::setAzimuth(double az) {
if (_random)
hdg = _azimuth = (az - 5 ) + (10 * sg_random());
else
hdg = _azimuth = az;
//cout << _name << " init hdg " << hdg << " random " << _random << endl; if (_random)
hdg = _azimuth = (az - 5 ) + (10 * sg_random());
else
hdg = _azimuth = az;
//cout << _name << " init hdg " << hdg << " random " << _random << endl;
} }
void FGAIBallistic::setElevation(double el) { void FGAIBallistic::setElevation(double el) {
@ -313,11 +320,11 @@ void FGAIBallistic::setDragArea(double a) {
void FGAIBallistic::setLife(double seconds) { void FGAIBallistic::setLife(double seconds) {
if (_random){ if (_random){
life = seconds * _randomness + (seconds * (1 -_randomness) * sg_random()); life = seconds * _randomness + (seconds * (1 -_randomness) * sg_random());
//cout << "life " << life << endl; //cout << "life " << life << endl;
} else } else
life = seconds; life = seconds;
} }
void FGAIBallistic::setBuoyancy(double fpss) { void FGAIBallistic::setBuoyancy(double fpss) {
@ -366,7 +373,6 @@ void FGAIBallistic::setCollision(bool c) {
void FGAIBallistic::setExpiry(bool e) { void FGAIBallistic::setExpiry(bool e) {
_report_expiry = e; _report_expiry = e;
//cout << "_report_expiry " << _report_expiry << endl;
} }
void FGAIBallistic::setExternalForce(bool f) { void FGAIBallistic::setExternalForce(bool f) {
@ -384,7 +390,8 @@ void FGAIBallistic::setName(const string& n) {
} }
void FGAIBallistic::setSMPath(const string& s) { void FGAIBallistic::setSMPath(const string& s) {
_submodel = s; _path = s;
//cout << "submodel path " << _path << endl;
} }
void FGAIBallistic::setFuseRange(double f) { void FGAIBallistic::setFuseRange(double f) {
@ -419,12 +426,55 @@ void FGAIBallistic::setFormate(bool f) {
_formate_to_ac = f; _formate_to_ac = f;
} }
void FGAIBallistic::setContentsNode(const string& path) { void FGAIBallistic::setContentsPath(const string& path) {
_contents_path = path;
if (!path.empty()) { if (!path.empty()) {
_contents_node = fgGetNode(path.c_str(), true); _contents_node = fgGetNode(path.c_str(), true);
} }
} }
void FGAIBallistic::setContentsNode(SGPropertyNode_ptr node) {
if (node != 0) {
_contents_node = node;
_contents_path = _contents_node->getDisplayName();
}
}
void FGAIBallistic::setParentNode(SGPropertyNode_ptr node) {
if (node != 0) {
_pnode = node;
_p_pos_node = _pnode->getChild("position", 0, true);
_p_lat_node = _p_pos_node->getChild("latitude-deg", 0, true);
_p_lon_node = _p_pos_node->getChild("longitude-deg", 0, true);
_p_alt_node = _p_pos_node->getChild("altitude-ft", 0, true);
_p_ori_node = _pnode->getChild("orientation", 0, true);
_p_pch_node = _p_ori_node->getChild("pitch-deg", 0, true);
_p_rll_node = _p_ori_node->getChild("roll-deg", 0, true);
_p_hdg_node = _p_ori_node->getChild("true-heading-deg",0, true);
_p_vel_node = _pnode->getChild("velocities", 0, true);
_p_spd_node = _p_vel_node->getChild("true-airspeed-kt", 0, true);
}
}
void FGAIBallistic::setParentPos() {
if (_pnode != 0) {
double lat = _p_lat_node->getDoubleValue();
double lon = _p_lon_node->getDoubleValue();
double alt = _p_alt_node->getDoubleValue();
_parentpos.setLongitudeDeg(lon);
_parentpos.setLatitudeDeg(lat);
_parentpos.setElevationFt(alt);
}
}
bool FGAIBallistic::getSlaved() const { bool FGAIBallistic::getSlaved() const {
return _slave_to_ac; return _slave_to_ac;
} }
@ -434,13 +484,14 @@ double FGAIBallistic::getMass() const {
} }
double FGAIBallistic::getContents() { double FGAIBallistic::getContents() {
if(_contents_node) if(_contents_node){
_contents_lb = _contents_node->getChild("level-lbs",0,1)->getDoubleValue(); _contents_lb = _contents_node->getChild("level-lbs",0,1)->getDoubleValue();
}
return _contents_lb; return _contents_lb;
} }
void FGAIBallistic::setContents(double c) { void FGAIBallistic::setContents(double c) {
if(_contents_node) if(_contents_node)
_contents_lb = _contents_node->getChild("level-gal_us",0,1)->setDoubleValue(c); _contents_lb = _contents_node->getChild("level-gal_us",0,1)->setDoubleValue(c);
} }
@ -462,27 +513,33 @@ void FGAIBallistic::setForcePath(const string& p) {
} }
} }
bool FGAIBallistic::getHtAGL(){ bool FGAIBallistic::getHtAGL(double start){
if (getGroundElevationM(SGGeod::fromGeodM(pos, 10000), if (getGroundElevationM(SGGeod::fromGeodM(pos, start),
_elevation_m, &_material)) { _elevation_m, &_material)) {
_ht_agl_ft = pos.getElevationFt() - _elevation_m * SG_METER_TO_FEET; _ht_agl_ft = pos.getElevationFt() - _elevation_m * SG_METER_TO_FEET;
if (_material) { if (_material) {
const vector<string>& names = _material->get_names(); const vector<string>& names = _material->get_names();
_solid = _material->get_solid(); _solid = _material->get_solid();
_load_resistance = _material->get_load_resistance(); _load_resistance = _material->get_load_resistance();
_frictionFactor =_material->get_friction_factor(); _frictionFactor =_material->get_friction_factor();
if (!names.empty()) if (!names.empty())
props->setStringValue("material/name", names[0].c_str()); props->setStringValue("material/name", names[0].c_str());
else else
props->setStringValue("material/name", ""); props->setStringValue("material/name", "");
/*cout << "material " << mat_name
<< " solid " << _solid _mat_name = names[0];
<< " load " << _load_resistance
<< " frictionFactor " << frictionFactor //cout << "material " << _mat_name
<< endl;*/ //<< " solid " << _solid
//<< " load " << _load_resistance
//<< " frictionFactor " << _frictionFactor
//<< endl;
} }
return true; return true;
} else { } else {
return false; return false;
@ -491,11 +548,11 @@ bool FGAIBallistic::getHtAGL(){
} }
double FGAIBallistic::getRecip(double az){ double FGAIBallistic::getRecip(double az){
// calculate the reciprocal of the input azimuth // calculate the reciprocal of the input azimuth
if(az - 180 < 0){ if(az - 180 < 0){
return az + 180; return az + 180;
} else { } else {
return az - 180; return az - 180;
} }
} }
@ -515,16 +572,16 @@ void FGAIBallistic::setHt(double h, double dt, double coeff){
} }
void FGAIBallistic::setHdg(double az, double dt, double coeff){ void FGAIBallistic::setHdg(double az, double dt, double coeff){
double recip = getRecip(hdg); double recip = getRecip(hdg);
double c = dt / (coeff + dt); double c = dt / (coeff + dt);
//we need to ensure that we turn the short way to the new hdg //we need to ensure that we turn the short way to the new hdg
if (az < recip && az < hdg && hdg > 180) { if (az < recip && az < hdg && hdg > 180) {
hdg = ((az + 360) * c) + (hdg * (1 - c)); hdg = ((az + 360) * c) + (hdg * (1 - c));
} else if (az > recip && az > hdg && hdg <= 180){ } else if (az > recip && az > hdg && hdg <= 180){
hdg = ((az - 360) * c) + (hdg * (1 - c)); hdg = ((az - 360) * c) + (hdg * (1 - c));
} else { } else {
hdg = (az * c) + (hdg * (1 - c)); hdg = (az * c) + (hdg * (1 - c));
} }
} }
double FGAIBallistic::getTgtXOffset() const { double FGAIBallistic::getTgtXOffset() const {
@ -533,7 +590,7 @@ double FGAIBallistic::getTgtXOffset() const {
double FGAIBallistic::getTgtYOffset() const { double FGAIBallistic::getTgtYOffset() const {
return _tgt_y_offset; return _tgt_y_offset;
} }
double FGAIBallistic::getTgtZOffset() const { double FGAIBallistic::getTgtZOffset() const {
return _tgt_z_offset; return _tgt_z_offset;
@ -553,34 +610,54 @@ void FGAIBallistic::setTgtZOffset(double z){
void FGAIBallistic::slaveToAC(double dt){ void FGAIBallistic::slaveToAC(double dt){
setHitchPos(); double hdg, pch, rll = 0;
pos.setLatitudeDeg(hitchpos.getLatitudeDeg());
pos.setLongitudeDeg(hitchpos.getLongitudeDeg()); if (_pnode != 0) {
pos.setElevationFt(hitchpos.getElevationFt()); setParentPos();
setHeading(manager->get_user_heading()); hdg = _p_hdg_node->getDoubleValue();
setPitch(manager->get_user_pitch() + _pitch_offset); pch = _p_pch_node->getDoubleValue();
setBank(manager->get_user_roll() + _roll_offset); rll = _p_rll_node->getDoubleValue();
setSpeed(manager->get_user_speed()); setOffsetPos(_parentpos, hdg, pch, rll);
setSpeed(_p_spd_node->getDoubleValue());
}else {
hdg = manager->get_user_heading();
pch = manager->get_user_pitch();
rll = manager->get_user_roll();
setOffsetPos(userpos, hdg, pch, rll);
setSpeed(manager->get_user_speed());
}
pos.setLatitudeDeg(_offsetpos.getLatitudeDeg());
pos.setLongitudeDeg(_offsetpos.getLongitudeDeg());
pos.setElevationFt(_offsetpos.getElevationFt());
setHeading(hdg);
setPitch(pch + _pitch_offset);
setBank(rll + _roll_offset);
setOffsetVelocity(dt, pos);
//update the mass (slugs) //update the mass (slugs)
_mass = (_weight_lb + getContents()) / slugs_to_lbs; _mass = (_weight_lb + getContents()) / slugs_to_lbs;
/*cout <<"_mass "<<_mass <<" " << getContents() _impact_reported = false;
<<" " << getContents() / slugs_to_lbs << endl;*/
//cout << _name << " _mass "<<_mass <<" " << getContents()
//<< " " << getContents() / slugs_to_lbs << " weight " << _weight_lb << endl;
// cout << _name << " update hs " << hs << " vs " << vs << endl;
} }
void FGAIBallistic::Run(double dt) { void FGAIBallistic::Run(double dt) {
_life_timer += dt; _life_timer += dt;
// if life = -1 the object does not die // if life = -1 the object does not die
if (_life_timer > life && life != -1){ if (_life_timer > life && life != -1){
if (_report_expiry && !_expiry_reported){ if (_report_expiry && !_expiry_reported && !_impact_reported && !_collision_reported){
//cout<<"AIBallistic: expiry"<< endl; //cout<<"AIBallistic: expiry"<< endl;
handle_expiry(); handle_expiry();
} else } else
setDie(true); setDie(true);
} }
//set the contents in the appropriate tank or other property in the parent to zero //set the contents in the appropriate tank or other property in the parent to zero
setContents(0); setContents(0);
@ -600,7 +677,8 @@ void FGAIBallistic::Run(double dt) {
else else
Cdm = 0.2965 * pow(Mach, -1.1506) + _Cd; Cdm = 0.2965 * pow(Mach, -1.1506) + _Cd;
//cout << "Mach " << Mach << " Cdm " << Cdm << "// ballistic speed kts "<< speed << endl; //cout <<_name << " Mach " << Mach << " Cdm " << Cdm
// << " ballistic speed kts "<< speed << endl;
// drag = Cd * 0.5 * rho * speed * speed * drag_area; // drag = Cd * 0.5 * rho * speed * speed * drag_area;
// rho is adjusted for altitude in void FGAIBase::update, // rho is adjusted for altitude in void FGAIBase::update,
@ -660,20 +738,21 @@ void FGAIBallistic::Run(double dt) {
double friction_force_speed_east_deg_sec = 0; double friction_force_speed_east_deg_sec = 0;
double force_elevation_deg = 0; double force_elevation_deg = 0;
if (_external_force) { if (_external_force) {
//cout << _name << " external force" << endl;
SGPropertyNode *n = fgGetNode(_force_path.c_str(), true); SGPropertyNode *n = fgGetNode(_force_path.c_str(), true);
double force_lbs = n->getChild("force-lb", 0, true)->getDoubleValue(); double force_lbs = n->getChild("force-lb", 0, true)->getDoubleValue();
force_elevation_deg = n->getChild("force-elevation-deg", 0, true)->getDoubleValue(); force_elevation_deg = n->getChild("force-elevation-deg", 0, true)->getDoubleValue();
double force_azimuth_deg = n->getChild("force-azimuth-deg", 0, true)->getDoubleValue(); double force_azimuth_deg = n->getChild("force-azimuth-deg", 0, true)->getDoubleValue();
//resolve force into vertical and horizontal components: //resolve force into vertical and horizontal components:
double v_force_lbs = force_lbs * sin( force_elevation_deg * SG_DEGREES_TO_RADIANS ); double v_force_lbs = force_lbs * sin( force_elevation_deg * SG_DEGREES_TO_RADIANS );
h_force_lbs = force_lbs * cos( force_elevation_deg * SG_DEGREES_TO_RADIANS ); h_force_lbs = force_lbs * cos( force_elevation_deg * SG_DEGREES_TO_RADIANS );
//ground interaction //ground interaction
if (getHtAGL()){ if (getHtAGL(10000)){
double deadzone = 0.1; double deadzone = 0.1;
if (_ht_agl_ft <= (0 + _ground_offset + deadzone) && _solid){ if (_ht_agl_ft <= (0 + _ground_offset + deadzone) && _solid){
@ -683,7 +762,7 @@ void FGAIBallistic::Run(double dt) {
normal_force_lbs = 0; normal_force_lbs = 0;
pos.setElevationFt(0 + _ground_offset); pos.setElevationFt(0 + _ground_offset);
if (vs < 0) if (vs < 0)
vs = -vs * 0.5; vs = -vs * 0.5;
// calculate friction // calculate friction
@ -692,7 +771,7 @@ void FGAIBallistic::Run(double dt) {
static_friction_force_lbs = mu * normal_force_lbs * _frictionFactor; static_friction_force_lbs = mu * normal_force_lbs * _frictionFactor;
//adjust horizontal force. We assume that a speed of <= 5 fps is static //adjust horizontal force. We assume that a speed of <= 5 fps is static
if (h_force_lbs <= static_friction_force_lbs && hs <= 5){ if (h_force_lbs <= static_friction_force_lbs && hs <= 5){
h_force_lbs = hs = 0; h_force_lbs = hs = 0;
speed_north_fps = speed_east_fps = 0; speed_north_fps = speed_east_fps = 0;
@ -738,9 +817,9 @@ void FGAIBallistic::Run(double dt) {
double wind_speed_from_east_deg_sec = _wind_from_east / ft_per_deg_lon; double wind_speed_from_east_deg_sec = _wind_from_east / ft_per_deg_lon;
//recombine the horizontal velocity components //recombine the horizontal velocity components
hs = sqrt(((speed_north_fps + force_speed_north_fps + friction_force_speed_north_fps) hs = sqrt(((speed_north_fps + force_speed_north_fps + friction_force_speed_north_fps)
* (speed_north_fps + force_speed_north_fps + friction_force_speed_north_fps)) * (speed_north_fps + force_speed_north_fps + friction_force_speed_north_fps))
+ ((speed_east_fps + force_speed_east_fps + friction_force_speed_east_fps) + ((speed_east_fps + force_speed_east_fps + friction_force_speed_east_fps)
* (speed_east_fps + force_speed_east_fps + friction_force_speed_east_fps))); * (speed_east_fps + force_speed_east_fps + friction_force_speed_east_fps)));
if (hs <= 0.00001) if (hs <= 0.00001)
@ -754,31 +833,37 @@ void FGAIBallistic::Run(double dt) {
// set new position // set new position
if(_slave_load_to_ac) { if(_slave_load_to_ac) {
setHitchPos(); setOffsetPos(pos,
pos.setLatitudeDeg(hitchpos.getLatitudeDeg()); manager->get_user_heading(),
pos.setLongitudeDeg(hitchpos.getLongitudeDeg()); manager->get_user_pitch(),
pos.setElevationFt(hitchpos.getElevationFt()); manager->get_user_roll()
);
pos.setLatitudeDeg(_offsetpos.getLatitudeDeg());
pos.setLongitudeDeg(_offsetpos.getLongitudeDeg());
pos.setElevationFt(_offsetpos.getElevationFt());
if (getHtAGL()){ if (getHtAGL(10000)){
double deadzone = 0.1; double deadzone = 0.1;
if (_ht_agl_ft <= (0 + _ground_offset + deadzone) && _solid){ if (_ht_agl_ft <= (0 + _ground_offset + deadzone) && _solid){
pos.setElevationFt(0 + _ground_offset); pos.setElevationFt(0 + _ground_offset);
} else { } else {
pos.setElevationFt(hitchpos.getElevationFt() + _load_offset); pos.setElevationFt(_offsetpos.getElevationFt() + _load_offset);
} }
} }
} else { } else {
pos.setLatitudeDeg( pos.getLatitudeDeg() pos.setLatitudeDeg( pos.getLatitudeDeg()
+ (speed_north_deg_sec - wind_speed_from_north_deg_sec + (speed_north_deg_sec - wind_speed_from_north_deg_sec
+ force_speed_north_deg_sec + friction_force_speed_north_deg_sec) * dt ); + force_speed_north_deg_sec + friction_force_speed_north_deg_sec) * dt );
pos.setLongitudeDeg( pos.getLongitudeDeg() pos.setLongitudeDeg( pos.getLongitudeDeg()
+ (speed_east_deg_sec - wind_speed_from_east_deg_sec + (speed_east_deg_sec - wind_speed_from_east_deg_sec
+ force_speed_east_deg_sec + friction_force_speed_east_deg_sec) * dt ); + force_speed_east_deg_sec + friction_force_speed_east_deg_sec) * dt );
pos.setElevationFt(pos.getElevationFt() + vs * dt); pos.setElevationFt(pos.getElevationFt() + vs * dt);
} }
// cout << _name << " run hs " << hs << " vs " << vs << endl;
// recalculate total speed // recalculate total speed
if ( vs == 0 && hs == 0) if ( vs == 0 && hs == 0)
speed = 0; speed = 0;
@ -787,7 +872,7 @@ void FGAIBallistic::Run(double dt) {
// recalculate elevation and azimuth (velocity vectors) // recalculate elevation and azimuth (velocity vectors)
_elevation = atan2( vs, hs ) * SG_RADIANS_TO_DEGREES; _elevation = atan2( vs, hs ) * SG_RADIANS_TO_DEGREES;
_azimuth = atan2((speed_east_fps + force_speed_east_fps + friction_force_speed_east_fps), _azimuth = atan2((speed_east_fps + force_speed_east_fps + friction_force_speed_east_fps),
(speed_north_fps + force_speed_north_fps + friction_force_speed_north_fps)) (speed_north_fps + force_speed_north_fps + friction_force_speed_north_fps))
* SG_RADIANS_TO_DEGREES; * SG_RADIANS_TO_DEGREES;
@ -795,10 +880,8 @@ void FGAIBallistic::Run(double dt) {
if (_azimuth < 0) if (_azimuth < 0)
_azimuth += 360; _azimuth += 360;
//cout << "_azimuth " << _azimuth << " hdg "<< hdg << endl;
if (_aero_stabilised) { // we simulate rotational moment of inertia by using a filter if (_aero_stabilised) { // we simulate rotational moment of inertia by using a filter
//cout<< "_aero_stabilised "<< endl; //cout<< "_aero_stabilised "<< endl;
const double coeff = 0.9; const double coeff = 0.9;
// we assume a symetrical MI about the pitch and yaw axis // we assume a symetrical MI about the pitch and yaw axis
@ -806,8 +889,8 @@ void FGAIBallistic::Run(double dt) {
setHdg(_azimuth, dt, coeff); setHdg(_azimuth, dt, coeff);
} else if (_force_stabilised) { // we simulate rotational moment of inertia by using a filter } else if (_force_stabilised) { // we simulate rotational moment of inertia by using a filter
//cout<< "_force_stabilised "<< endl; //cout<< "_force_stabilised "<< endl;
const double coeff = 0.9; const double coeff = 0.9;
double ratio = h_force_lbs/(_mass * slugs_to_lbs); double ratio = h_force_lbs/(_mass * slugs_to_lbs);
if (ratio > 1) ratio = 1; if (ratio > 1) ratio = 1;
@ -843,7 +926,9 @@ double FGAIBallistic::_getTime() const {
void FGAIBallistic::handle_impact() { void FGAIBallistic::handle_impact() {
// try terrain intersection // try terrain intersection
if(!getHtAGL()) double start = pos.getElevationM() + 10;
if(!getHtAGL(start))
return; return;
if (_ht_agl_ft <= 0) { if (_ht_agl_ft <= 0) {
@ -855,30 +940,30 @@ void FGAIBallistic::handle_impact() {
invisible = true; invisible = true;
} else if (_subID == 0) // kill the AIObject if there is no subsubmodel } else if (_subID == 0) // kill the AIObject if there is no subsubmodel
setDie(true); setDie(true);
} }
} }
void FGAIBallistic::handle_expiry() { void FGAIBallistic::handle_expiry() {
SG_LOG(SG_GENERAL, SG_DEBUG, "AIBallistic: handle_expiry " << pos.getElevationM());
report_impact(pos.getElevationM()); SG_LOG(SG_GENERAL, SG_DEBUG, "AIBallistic: handle_expiry " << pos.getElevationM());
_expiry_reported = true;
report_impact(pos.getElevationM());
_expiry_reported = true;
if (life == -1){
invisible = true;
} else if (_subID == 0){ // kill the AIObject if there is no subsubmodel
setDie(true);
}
//if (life == -1){
// invisible = true;
//} else if (_subID == 0) // kill the AIObject if there is no subsubmodel
// setDie(true);
} }
void FGAIBallistic::handle_collision() void FGAIBallistic::handle_collision()
{ {
const FGAIBase *object = manager->calcCollision(pos.getElevationFt(), const FGAIBase *object = manager->calcCollision(pos.getElevationFt(),
pos.getLatitudeDeg(),pos.getLongitudeDeg(), _fuse_range); pos.getLatitudeDeg(),pos.getLongitudeDeg(), _fuse_range);
if (object) { if (object) {
SG_LOG(SG_GENERAL, SG_DEBUG, "AIBallistic: object hit");
report_impact(pos.getElevationM(), object); report_impact(pos.getElevationM(), object);
_collision_reported = true; _collision_reported = true;
} }
@ -895,13 +980,13 @@ void FGAIBallistic::report_impact(double elevation, const FGAIBase *object)
_impact_roll = roll; _impact_roll = roll;
SGPropertyNode *n = props->getNode("impact", true); SGPropertyNode *n = props->getNode("impact", true);
if (object) {
if (object)
n->setStringValue("type", object->getTypeString()); n->setStringValue("type", object->getTypeString());
n->setStringValue("callsign", object->_callsign); else
} else {
n->setStringValue("type", "terrain"); n->setStringValue("type", "terrain");
n->setStringValue("callsign", "");
} SG_LOG(SG_GENERAL, SG_DEBUG, "AIBallistic: object impact" << _name << " lon " <<_impact_lon);
n->setDoubleValue("longitude-deg", _impact_lon); n->setDoubleValue("longitude-deg", _impact_lon);
n->setDoubleValue("latitude-deg", _impact_lat); n->setDoubleValue("latitude-deg", _impact_lat);
@ -922,7 +1007,7 @@ SGVec3d FGAIBallistic::getCartUserPos() const {
SGVec3d FGAIBallistic::getCartHitchPos() const{ SGVec3d FGAIBallistic::getCartHitchPos() const{
// convert geodetic positions to geocentered // convert geodetic positions to geocentered
SGVec3d cartuserPos = getCartUserPos(); SGVec3d cartuserPos = SGVec3d::fromGeod(userpos);
//SGVec3d cartPos = getCartPos(); //SGVec3d cartPos = getCartPos();
// Transform to the right coordinate frame, configuration is done in // Transform to the right coordinate frame, configuration is done in
@ -930,8 +1015,8 @@ SGVec3d FGAIBallistic::getCartHitchPos() const{
// in the simulation usual body x-forward, y-right, z-down coordinates // in the simulation usual body x-forward, y-right, z-down coordinates
// (meters) ) // (meters) )
SGVec3d _off(_x_offset * SG_FEET_TO_METER, SGVec3d _off(_x_offset * SG_FEET_TO_METER,
_y_offset * SG_FEET_TO_METER, _y_offset * SG_FEET_TO_METER,
-_z_offset * SG_FEET_TO_METER); -_z_offset * SG_FEET_TO_METER);
// Transform the user position to the horizontal local coordinate system. // Transform the user position to the horizontal local coordinate system.
SGQuatd hlTrans = SGQuatd::fromLonLat(userpos); SGQuatd hlTrans = SGQuatd::fromLonLat(userpos);
@ -953,15 +1038,20 @@ SGVec3d FGAIBallistic::getCartHitchPos() const{
return offsetPos; return offsetPos;
} }
void FGAIBallistic::setHitchPos(){ void FGAIBallistic::setOffsetPos(SGGeod inpos, double heading, double pitch, double roll){
// convert the hitch geocentered position to geodetic // convert the hitch geocentered position to geodetic
SGVec3d carthitchPos = getCartHitchPos();
SGGeodesy::SGCartToGeod(carthitchPos, hitchpos); SGVec3d cartoffsetPos = getCartOffsetPos(inpos, heading, pitch, roll);
//SGVec3d cartoffsetPos = getCartHitchPos();
//SGGeodesy::SGCartToGeod(cartoffsetPos, hitchpos);
SGGeodesy::SGCartToGeod(cartoffsetPos, _offsetpos);
} }
double FGAIBallistic::getDistanceLoadToHitch() const { double FGAIBallistic::getDistanceLoadToHitch() const {
//calculate the distance load to hitch //calculate the distance load to hitch
SGVec3d carthitchPos = getCartHitchPos(); SGVec3d carthitchPos = getCartHitchPos();
SGVec3d cartPos = getCartPos(); SGVec3d cartPos = getCartPos();
@ -970,47 +1060,12 @@ double FGAIBallistic::getDistanceLoadToHitch() const {
return distance * SG_METER_TO_FEET; return distance * SG_METER_TO_FEET;
} }
void FGAIBallistic::setHitchVelocity(double dt) {
//calculate the distance from the previous hitch position
SGVec3d carthitchPos = getCartHitchPos();
SGVec3d diff = carthitchPos - _oldcarthitchPos;
double distance = norm(diff);
//calculate speed knots
speed = (distance/dt) * SG_MPS_TO_KT;
//now calulate the angle between the old and current hitch positions (degrees)
double angle = 0;
double daltM = hitchpos.getElevationM() - oldhitchpos.getElevationM();
if (fabs(distance) < SGLimits<float>::min()) {
angle = 0;
} else {
double sAngle = daltM/distance;
sAngle = SGMiscd::min(1, SGMiscd::max(-1, sAngle));
angle = SGMiscd::rad2deg(asin(sAngle));
}
_elevation = angle;
//calculate the bearing of the new hitch position from the old
double az1, az2, dist;
geo_inverse_wgs_84(oldhitchpos, hitchpos, &az1, &az2, &dist);
_azimuth = az1;
// and finally store the new values
_oldcarthitchPos = carthitchPos;
oldhitchpos = hitchpos;
}
double FGAIBallistic::getElevLoadToHitch() const { double FGAIBallistic::getElevLoadToHitch() const {
// now the angle, positive angles are upwards // now the angle, positive angles are upwards
double distance = getDistanceLoadToHitch() * SG_FEET_TO_METER; double distance = getDistanceLoadToHitch() * SG_FEET_TO_METER;
double angle = 0; double angle = 0;
double daltM = hitchpos.getElevationM() - pos.getElevationM(); double daltM = _offsetpos.getElevationM() - pos.getElevationM();
if (fabs(distance) < SGLimits<float>::min()) { if (fabs(distance) < SGLimits<float>::min()) {
angle = 0; angle = 0;
@ -1027,16 +1082,16 @@ double FGAIBallistic::getBearingLoadToHitch() const {
//calculate the bearing and range of the second pos from the first //calculate the bearing and range of the second pos from the first
double az1, az2, distance; double az1, az2, distance;
geo_inverse_wgs_84(pos, hitchpos, &az1, &az2, &distance); geo_inverse_wgs_84(pos, _offsetpos, &az1, &az2, &distance);
return az1; return az1;
} }
double FGAIBallistic::getRelBrgHitchToUser() const { double FGAIBallistic::getRelBrgHitchToUser() const {
//calculate the relative bearing //calculate the relative bearing
double az1, az2, distance; double az1, az2, distance;
geo_inverse_wgs_84(hitchpos, userpos, &az1, &az2, &distance); geo_inverse_wgs_84(_offsetpos, userpos, &az1, &az2, &distance);
double rel_brg = az1 - hdg; double rel_brg = az1 - hdg;
@ -1057,7 +1112,7 @@ double FGAIBallistic::getElevHitchToUser() const {
double distance = norm(diff); double distance = norm(diff);
double angle = 0; double angle = 0;
double daltM = userpos.getElevationM() - hitchpos.getElevationM(); double daltM = userpos.getElevationM() - _offsetpos.getElevationM();
// now the angle, positive angles are upwards // now the angle, positive angles are upwards
if (fabs(distance) < SGLimits<float>::min()) { if (fabs(distance) < SGLimits<float>::min()) {
@ -1082,14 +1137,17 @@ void FGAIBallistic::setTgtOffsets(double dt, double coeff){
void FGAIBallistic::formateToAC(double dt){ void FGAIBallistic::formateToAC(double dt){
setTgtOffsets(dt, 25); setTgtOffsets(dt, 25);
setHitchPos(); setOffsetPos(userpos,
setHitchVelocity(dt); manager->get_user_heading(),
manager->get_user_pitch(),
manager->get_user_roll()
);
// elapsed time has a random initialisation so that each // elapsed time has a random initialisation so that each
// wingman moves differently // wingman moves differently
_elapsed_time += dt; _elapsed_time += dt;
// we derive a sine based factor to give us smoothly // we derive a sine based factor to give us smoothly
// varying error between -1 and 1 // varying error between -1 and 1
double factor = sin(SGMiscd::deg2rad(_elapsed_time * 10)); double factor = sin(SGMiscd::deg2rad(_elapsed_time * 10));
double r_angle = 5 * factor; double r_angle = 5 * factor;
@ -1097,19 +1155,19 @@ void FGAIBallistic::formateToAC(double dt){
double h_angle = 5 * factor; double h_angle = 5 * factor;
double h_feet = 3 * factor; double h_feet = 3 * factor;
pos.setLatitudeDeg(hitchpos.getLatitudeDeg()); pos.setLatitudeDeg(_offsetpos.getLatitudeDeg());
pos.setLongitudeDeg(hitchpos.getLongitudeDeg()); pos.setLongitudeDeg(_offsetpos.getLongitudeDeg());
if (getHtAGL()){ if (getHtAGL(10000)){
if(_ht_agl_ft <= 10) { if(_ht_agl_ft <= 10) {
_height = userpos.getElevationFt(); _height = userpos.getElevationFt();
} else if (_ht_agl_ft > 10 && _ht_agl_ft <= 150 ) { } else if (_ht_agl_ft > 10 && _ht_agl_ft <= 150 ) {
setHt(userpos.getElevationFt(), dt, 1.0); setHt(userpos.getElevationFt(), dt, 1.0);
} else if (_ht_agl_ft > 150 && _ht_agl_ft <= 250) { } else if (_ht_agl_ft > 150 && _ht_agl_ft <= 250) {
setHt(hitchpos.getElevationFt()+ h_feet, dt, 0.75); setHt(_offsetpos.getElevationFt()+ h_feet, dt, 0.75);
} else } else
setHt(hitchpos.getElevationFt()+ h_feet, dt, 0.5); setHt(_offsetpos.getElevationFt()+ h_feet, dt, 0.5);
pos.setElevationFt(_height); pos.setElevationFt(_height);
} }
@ -1130,6 +1188,105 @@ void FGAIBallistic::formateToAC(double dt){
setBnk(manager->get_user_roll() + _roll_offset, dt, 0.9); setBnk(manager->get_user_roll() + _roll_offset, dt, 0.9);
} }
setSpeed(speed); setOffsetVelocity(dt, pos);
} }
void FGAIBallistic::calcVSHS(){
// calculate vertical and horizontal speed components
double speed_fps = speed * SG_KT_TO_FPS;
if (speed == 0.0) {
hs = vs = 0.0;
} else {
vs = sin( _elevation * SG_DEGREES_TO_RADIANS ) * speed_fps;
hs = cos( _elevation * SG_DEGREES_TO_RADIANS ) * speed_fps;
}
}
void FGAIBallistic::calcNE(){
//resolve horizontal speed into north and east components:
_speed_north_fps = cos(_azimuth / SG_RADIANS_TO_DEGREES) * hs;
_speed_east_fps = sin(_azimuth / SG_RADIANS_TO_DEGREES) * hs;
// convert horizontal speed (fps) to degrees per second
speed_north_deg_sec = _speed_north_fps / ft_per_deg_lat;
speed_east_deg_sec = _speed_east_fps / ft_per_deg_lon;
}
SGVec3d FGAIBallistic::getCartOffsetPos(SGGeod inpos, double user_heading,
double user_pitch, double user_roll
) const{
// convert geodetic positions to geocentered
SGVec3d cartuserPos = SGVec3d::fromGeod(inpos);
//SGVec3d cartuserPos = getCartUserPos();
//SGVec3d cartPos = getCartPos();
// Transform to the right coordinate frame, configuration is done in
// the x-forward, y-right, z-up coordinates (feet), computation
// in the simulation usual body x-forward, y-right, z-down coordinates
// (meters) )
SGVec3d _off(_x_offset * SG_FEET_TO_METER,
_y_offset * SG_FEET_TO_METER,
-_z_offset * SG_FEET_TO_METER);
// Transform the user position to the horizontal local coordinate system.
SGQuatd hlTrans = SGQuatd::fromLonLat(userpos);
// and postrotate the orientation of the user model wrt the horizontal
// local frame
hlTrans *= SGQuatd::fromYawPitchRollDeg(
user_heading,
user_pitch,
user_roll);
// The offset converted to the usual body fixed coordinate system
// rotated to the earth-fixed coordinates axis
SGVec3d off = hlTrans.backTransform(_off);
// Add the position offset of the user model to get the geocentered position
SGVec3d offsetPos = cartuserPos + off;
return offsetPos;
}
void FGAIBallistic::setOffsetVelocity(double dt, SGGeod offsetpos) {
//calculate the distance from the previous offset position
SGVec3d cartoffsetPos = SGVec3d::fromGeod(offsetpos);
SGVec3d diff = cartoffsetPos - _oldcartoffsetPos;
double distance = norm(diff);
//calculate speed knots
speed = (distance/dt) * SG_MPS_TO_KT;
//now calulate the angle between the old and current postion positions (degrees)
double angle = 0;
double daltM = offsetpos.getElevationM() - _oldoffsetpos.getElevationM();
if (fabs(distance) < SGLimits<float>::min()) {
angle = 0;
} else {
double sAngle = daltM/distance;
sAngle = SGMiscd::min(1, SGMiscd::max(-1, sAngle));
angle = SGMiscd::rad2deg(asin(sAngle));
}
_elevation = angle;
//calculate vertical and horizontal speed components
calcVSHS();
//calculate the bearing of the new offset position from the old
double az1, az2, dist;
geo_inverse_wgs_84(_oldoffsetpos, offsetpos, &az1, &az2, &dist);
_azimuth = az1;
//resolve horizontal speed into north and east components:
calcNE();
// and finally store the new values
_oldcartoffsetPos = cartoffsetPos;
_oldoffsetpos = offsetpos;
}
// end AIBallistic // end AIBallistic

View file

@ -15,7 +15,7 @@
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details. // General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software // along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
@ -68,31 +68,32 @@ public:
void setWeight( double w ); void setWeight( double w );
void setNoRoll( bool nr ); void setNoRoll( bool nr );
void setRandom( bool r ); void setRandom( bool r );
void setRandomness( double r ); void setRandomness( double r );
void setName(const string&); void setName(const string&);
void setCollision(bool c); void setCollision(bool c);
void setExpiry(bool e); void setExpiry(bool e);
void setImpact(bool i); void setImpact(bool i);
void setImpactReportNode(const string&); void setImpactReportNode(const string&);
void setContentsNode(const string&); void setContentsNode(const SGPropertyNode_ptr);
void setFuseRange(double f); void setFuseRange(double f);
void setSMPath(const string&); void setSMPath(const string&);
void setSubID(int i); void setSubID(int i);
void setSubmodel(const string&); void setSubmodel(const string&);
void setExternalForce( bool f ); void setExternalForce( bool f );
void setForcePath(const string&); void setForcePath(const string&);
void setContentsPath(const string&);
void setForceStabilisation( bool val ); void setForceStabilisation( bool val );
void setGroundOffset(double g); void setGroundOffset(double g);
void setLoadOffset(double l); void setLoadOffset(double l);
void setSlaved(bool s); void setSlaved(bool s);
void setSlavedLoad(bool s); void setSlavedLoad(bool s);
void setHitchPos();
void setPch (double e, double dt, double c); void setPch (double e, double dt, double c);
void setHdg (double az, double dt, double c); void setHdg (double az, double dt, double c);
void setBnk(double r, double dt, double c); void setBnk(double r, double dt, double c);
void setHt(double h, double dt, double c); void setHt(double h, double dt, double c);
void setHitchVelocity(double dt);
void setFormate(bool f); void setFormate(bool f);
void setParentNode(const SGPropertyNode_ptr);
void setParentPos();
double _getTime() const; double _getTime() const;
double getRelBrgHitchToUser() const; double getRelBrgHitchToUser() const;
@ -102,7 +103,7 @@ public:
SGVec3d getCartHitchPos() const; SGVec3d getCartHitchPos() const;
bool getHtAGL(); bool getHtAGL(double start);
bool getSlaved() const; bool getSlaved() const;
bool getSlavedLoad() const; bool getSlavedLoad() const;
@ -114,13 +115,13 @@ public:
SGPropertyNode_ptr _force_azimuth_node; SGPropertyNode_ptr _force_azimuth_node;
SGPropertyNode_ptr _force_elevation_node; SGPropertyNode_ptr _force_elevation_node;
SGGeod hitchpos;
double _height; double _height;
double _ht_agl_ft; // height above ground level double _ht_agl_ft; // height above ground level
double _azimuth; // degrees true double _azimuth; // degrees true
double _elevation; // degrees double _elevation; // degrees
double _rotation; // degrees double _rotation; // degrees
double _speed_north_fps;
double _speed_east_fps;
bool _formate_to_ac; bool _formate_to_ac;
@ -153,7 +154,7 @@ private:
double _Cd; // drag coefficient double _Cd; // drag coefficient
double _mass; // slugs double _mass; // slugs
bool _random; // modifier for Cd, life, az bool _random; // modifier for Cd, life, az
double _randomness; // dimension for _random, only applies to life at present double _randomness; // dimension for _random, only applies to life at present
double _load_resistance; // ground load resistanc N/m^2 double _load_resistance; // ground load resistanc N/m^2
double _frictionFactor; // dimensionless modifier for Coefficient of Friction double _frictionFactor; // dimensionless modifier for Coefficient of Friction
bool _solid; // if true ground is solid for FDMs bool _solid; // if true ground is solid for FDMs
@ -163,41 +164,56 @@ private:
bool _slave_load_to_ac;// if true, object will be slaved to the parent ac pos bool _slave_load_to_ac;// if true, object will be slaved to the parent ac pos
double _contents_lb; // contents of the object double _contents_lb; // contents of the object
double _weight_lb; // weight of the object (no contents if appropriate) (lbs) double _weight_lb; // weight of the object (no contents if appropriate) (lbs)
string _mat_name;
bool _report_collision; // if true a collision point with AI Objects is calculated bool _report_collision; // if true a collision point with AI Objects is calculated
bool _report_impact; // if true an impact point on the terrain is calculated bool _report_impact; // if true an impact point on the terrain is calculated
bool _external_force; // if true then apply external force bool _external_force; // if true then apply external force
bool _report_expiry; bool _report_expiry;
SGPropertyNode_ptr _impact_report_node; // report node for impact and collision SGPropertyNode_ptr _impact_report_node; // report node for impact and collision
SGPropertyNode_ptr _contents_node; // report node for impact and collision SGPropertyNode_ptr _contents_node; // node for droptank etc. contents
SGPropertyNode_ptr _pnode; // node for parent model
SGPropertyNode_ptr _p_pos_node; // nodes for parent parameters
SGPropertyNode_ptr _p_lat_node;
SGPropertyNode_ptr _p_lon_node;
SGPropertyNode_ptr _p_alt_node;
SGPropertyNode_ptr _p_ori_node;
SGPropertyNode_ptr _p_pch_node;
SGPropertyNode_ptr _p_rll_node;
SGPropertyNode_ptr _p_hdg_node;
SGPropertyNode_ptr _p_vel_node;
SGPropertyNode_ptr _p_spd_node;
double _fuse_range; double _fuse_range;
double _distance; double _distance;
double _dt_count; double _dt_count;
double _next_run; double _next_run;
string _name;
string _path;
string _submodel; string _submodel;
string _force_path; string _force_path;
string _contents_path;
const SGMaterial* _material; const SGMaterial* _material;
void handle_collision(); void handle_collision();
void handle_expiry(); void handle_expiry();
void handle_impact(); void handle_impact();
void report_impact(double elevation, const FGAIBase *target = 0); void report_impact(double elevation, const FGAIBase *target = 0);
void slaveToAC(double dt); void slaveToAC(double dt);
void setContents(double c); void setContents(double c);
void formateToAC(double dt); void formateToAC(double dt);
void calcVSHS();
void calcNE();
void setOffsetPos(SGGeod pos, double heading, double pitch, double roll);
void setOffsetVelocity(double dt, SGGeod pos);
SGVec3d getCartUserPos() const; SGVec3d getCartUserPos() const;
SGVec3d getCartOffsetPos(SGGeod pos, double heading, double pitch, double roll) const;
double getDistanceLoadToHitch() const; double getDistanceLoadToHitch() const;
double getElevLoadToHitch() const; double getElevLoadToHitch() const;
double getBearingLoadToHitch() const; double getBearingLoadToHitch() const;
double getRecip(double az); double getRecip(double az);
double getMass() const; double getMass() const;
@ -206,9 +222,13 @@ private:
double _load_offset; double _load_offset;
double _old_height; double _old_height;
SGVec3d _oldcarthitchPos; SGVec3d _oldcartoffsetPos;
SGVec3d _oldcartPos;
SGGeod oldhitchpos; SGGeod _parentpos;
SGGeod _oldpos;
SGGeod _offsetpos;
SGGeod _oldoffsetpos;
}; };

View file

@ -81,7 +81,7 @@ FGAIBase::FGAIBase(object_type ot) :
delete_me = false; delete_me = false;
_impact_reported = false; _impact_reported = false;
_collision_reported = false; _collision_reported = false;
_expiry_reported = false; _expiry_reported = false;
_subID = 0; _subID = 0;
@ -227,14 +227,16 @@ bool FGAIBase::init(bool search_in_AI_path) {
void FGAIBase::initModel(osg::Node *node) void FGAIBase::initModel(osg::Node *node)
{ {
if (model.valid()) { if (model.valid()) {
if( _path != ""){
props->setStringValue("submodels/path", _path.c_str());
SG_LOG(SG_INPUT, SG_DEBUG, "AIBase: submodels/path " << _path);
}
fgSetString("/ai/models/model-added", props->getPath().c_str()); fgSetString("/ai/models/model-added", props->getPath().c_str());
} else if (!model_path.empty()) { } else if (!model_path.empty()) {
SG_LOG(SG_INPUT, SG_WARN, "AIBase: Could not load model " << model_path); SG_LOG(SG_INPUT, SG_WARN, "AIBase: Could not load model " << model_path);
} }
props->setStringValue("submodels/path", _path.c_str()); //props->setStringValue("submodels/path", _path.c_str());
setDie(false); setDie(false);
} }
@ -472,7 +474,7 @@ SGVec3d FGAIBase::getCartPosAt(const SGVec3d& _off) const {
hlTrans *= SGQuatd::fromYawPitchRollDeg(hdg, pitch, roll); hlTrans *= SGQuatd::fromYawPitchRollDeg(hdg, pitch, roll);
// The offset converted to the usual body fixed coordinate system // The offset converted to the usual body fixed coordinate system
// rotated to the earth fiexed coordinates axis // rotated to the earth fixed coordinates axis
SGVec3d off = hlTrans.backTransform(_off); SGVec3d off = hlTrans.backTransform(_off);
// Add the position offset of the AIModel to gain the earth centered position // Add the position offset of the AIModel to gain the earth centered position
@ -533,7 +535,7 @@ double FGAIBase::_getLatitude() const {
return pos.getLatitudeDeg(); return pos.getLatitudeDeg();
} }
double FGAIBase::_getElevationFt () const { double FGAIBase::_getElevationFt() const {
return pos.getElevationFt(); return pos.getElevationFt();
} }

View file

@ -1,7 +1,7 @@
// FGAIBase.hxx - abstract base class for AI objects // FGAIBase.hxx - abstract base class for AI objects
// Written by David Culp, started Nov 2003, based on // Written by David Culp, started Nov 2003, based on
// David Luff's FGAIEntity class. // David Luff's FGAIEntity class.
// - davidculp2@comcast.net // - davidculp2@comcast.net
// //
// This program is free software; you can redistribute it and/or // This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as // modify it under the terms of the GNU General Public License as
@ -44,9 +44,9 @@ class FGAIBase : public SGReferenced {
public: public:
enum object_type { otNull = 0, otAircraft, otShip, otCarrier, otBallistic, enum object_type { otNull = 0, otAircraft, otShip, otCarrier, otBallistic,
otRocket, otStorm, otThermal, otStatic, otWingman, otGroundVehicle, otRocket, otStorm, otThermal, otStatic, otWingman, otGroundVehicle,
otEscort, otMultiplayer, otEscort, otMultiplayer,
MAX_OBJECTS }; // Needs to be last!!! MAX_OBJECTS }; // Needs to be last!!!
FGAIBase(object_type ot); FGAIBase(object_type ot);
virtual ~FGAIBase(); virtual ~FGAIBase();
@ -95,7 +95,7 @@ public:
SGVec3d getCartPos() const; SGVec3d getCartPos() const;
bool getGroundElevationM(const SGGeod& pos, double& elev, bool getGroundElevationM(const SGGeod& pos, double& elev,
const SGMaterial** material) const; const SGMaterial** material) const;
double _getCartPosX() const; double _getCartPosX() const;
double _getCartPosY() const; double _getCartPosY() const;
@ -177,7 +177,7 @@ protected:
bool _impact_reported; bool _impact_reported;
bool _collision_reported; bool _collision_reported;
bool _expiry_reported; bool _expiry_reported;
double _impact_lat; double _impact_lat;
double _impact_lon; double _impact_lon;
@ -247,7 +247,7 @@ public:
bool _getImpact(); bool _getImpact();
bool _getImpactData(); bool _getImpactData();
bool _getCollisionData(); bool _getCollisionData();
bool _getExpiryData(); bool _getExpiryData();
SGPropertyNode* _getProps() const; SGPropertyNode* _getProps() const;
@ -274,8 +274,8 @@ public:
inline double _getBearing() { return bearing; }; inline double _getBearing() { return bearing; };
virtual osg::Node* load3DModel(const string &path, virtual osg::Node* load3DModel(const string &path,
SGPropertyNode *prop_root); SGPropertyNode *prop_root);
static bool _isNight(); static bool _isNight();
}; };

View file

@ -316,7 +316,7 @@ bool FGAIGroundVehicle::getPitch() {
//cout << "new waypoint, calculating pitch " << endl; //cout << "new waypoint, calculating pitch " << endl;
curr_alt = curr->altitude; curr_alt = curr->altitude;
prev_alt = prev->altitude; prev_alt = prev->altitude;
cout << "prev_alt" <<prev_alt << endl; //cout << "prev_alt" <<prev_alt << endl;
d_alt = (curr_alt - prev_alt) * SG_METER_TO_FEET; d_alt = (curr_alt - prev_alt) * SG_METER_TO_FEET;
//_elevation = prev->altitude; //_elevation = prev->altitude;
distance = SGGeodesy::distanceM(SGGeod::fromDeg(prev->longitude, prev->latitude), distance = SGGeodesy::distanceM(SGGeod::fromDeg(prev->longitude, prev->latitude),

View file

@ -2,7 +2,7 @@
// - a global management type for AI objects // - a global management type for AI objects
// //
// Written by David Culp, started October 2003. // Written by David Culp, started October 2003.
// - davidculp2@comcast.net // - davidculp2@comcast.net
// //
// This program is free software; you can redistribute it and/or // This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as // modify it under the terms of the GNU General Public License as
@ -97,7 +97,7 @@ FGAIManager::postinit() {
continue; continue;
if (scenarios.find(name) != scenarios.end()) { if (scenarios.find(name) != scenarios.end()) {
SG_LOG(SG_GENERAL, SG_WARN, "won't load scenario '" << name << "' twice"); SG_LOG(SG_GENERAL, SG_DEBUG, "won't load scenario '" << name << "' twice");
continue; continue;
} }
@ -110,6 +110,7 @@ FGAIManager::postinit() {
void void
FGAIManager::reinit() { FGAIManager::reinit() {
update(0.0); update(0.0);
ai_list_iterator ai_list_itr = ai_list.begin(); ai_list_iterator ai_list_itr = ai_list.begin();
while(ai_list_itr != ai_list.end()) { while(ai_list_itr != ai_list.end()) {

File diff suppressed because it is too large Load diff

View file

@ -1,7 +1,7 @@
// FGAIWingman - FGAIBllistic-derived class creates an AI Wingman // FGAIWingman - FGAIBllistic-derived class creates an AI Wingman
// //
// Written by Vivian Meazza, started February 2008. // Written by Vivian Meazza, started February 2008.
// - vivian.meazza at lineone.net // - vivian.meazza at lineone.net
// //
// This program is free software; you can redistribute it and/or // This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as // modify it under the terms of the GNU General Public License as
@ -27,6 +27,7 @@ FGAIWingman::FGAIWingman() : FGAIBallistic(otWingman)
{ {
invisible = false; invisible = false;
_formate_to_ac = true; _formate_to_ac = true;
} }
FGAIWingman::~FGAIWingman() {} FGAIWingman::~FGAIWingman() {}
@ -42,7 +43,7 @@ void FGAIWingman::readFromScenario(SGPropertyNode* scFileNode) {
setLife(scFileNode->getDoubleValue("life", -1)); setLife(scFileNode->getDoubleValue("life", -1));
setNoRoll(scFileNode->getBoolValue("no-roll", false)); setNoRoll(scFileNode->getBoolValue("no-roll", false));
setName(scFileNode->getStringValue("name", "Wingman")); setName(scFileNode->getStringValue("name", "Wingman"));
setSMPath(scFileNode->getStringValue("submodel-path", "")); //setSMPath(scFileNode->getStringValue("submodel-path", ""));
setSubID(scFileNode->getIntValue("SubID", 0)); setSubID(scFileNode->getIntValue("SubID", 0));
setXoffset(scFileNode->getDoubleValue("x-offset", 0.0)); setXoffset(scFileNode->getDoubleValue("x-offset", 0.0));
setYoffset(scFileNode->getDoubleValue("y-offset", 0.0)); setYoffset(scFileNode->getDoubleValue("y-offset", 0.0));
@ -57,14 +58,46 @@ void FGAIWingman::readFromScenario(SGPropertyNode* scFileNode) {
void FGAIWingman::bind() { void FGAIWingman::bind() {
FGAIBallistic::bind(); FGAIBallistic::bind();
props->tie("id", SGRawValueMethods<FGAIBase,int>(*this,
&FGAIBase::getID));
props->tie("subID", SGRawValueMethods<FGAIBase,int>(*this,
&FGAIBase::_getSubID));
props->tie("position/altitude-ft",
SGRawValueMethods<FGAIBase,double>(*this,
&FGAIBase::_getElevationFt,
&FGAIBase::_setAltitude));
props->tie("position/latitude-deg",
SGRawValueMethods<FGAIBase,double>(*this,
&FGAIBase::_getLatitude,
&FGAIBase::_setLatitude));
props->tie("position/longitude-deg",
SGRawValueMethods<FGAIBase,double>(*this,
&FGAIBase::_getLongitude,
&FGAIBase::_setLongitude));
props->tie("orientation/pitch-deg", SGRawValuePointer<double>(&pitch));
props->tie("orientation/roll-deg", SGRawValuePointer<double>(&roll));
props->tie("orientation/true-heading-deg", SGRawValuePointer<double>(&hdg));
props->tie("submodels/serviceable", SGRawValuePointer<bool>(&serviceable));
props->tie("load/rel-brg-to-user-deg", props->tie("load/rel-brg-to-user-deg",
SGRawValueMethods<FGAIBallistic,double> SGRawValueMethods<FGAIBallistic,double>
(*this, &FGAIBallistic::getRelBrgHitchToUser)); (*this, &FGAIBallistic::getRelBrgHitchToUser));
props->tie("load/elev-to-user-deg", props->tie("load/elev-to-user-deg",
SGRawValueMethods<FGAIBallistic,double> SGRawValueMethods<FGAIBallistic,double>
(*this, &FGAIBallistic::getElevHitchToUser)); (*this, &FGAIBallistic::getElevHitchToUser));
props->tie("velocities/vertical-speed-fps", props->tie("velocities/vertical-speed-fps",
SGRawValuePointer<double>(&vs)); SGRawValuePointer<double>(&vs));
props->tie("velocities/true-airspeed-kt",
SGRawValuePointer<double>(&speed));
props->tie("velocities/speed-east-fps",
SGRawValuePointer<double>(&_speed_east_fps));
props->tie("velocities/speed-north-fps",
SGRawValuePointer<double>(&_speed_north_fps));
props->tie("position/x-offset", props->tie("position/x-offset",
SGRawValueMethods<FGAIBase,double>(*this, &FGAIBase::_getXOffset, &FGAIBase::setXoffset)); SGRawValueMethods<FGAIBase,double>(*this, &FGAIBase::_getXOffset, &FGAIBase::setXoffset));
props->tie("position/y-offset", props->tie("position/y-offset",
@ -72,19 +105,36 @@ void FGAIWingman::bind() {
props->tie("position/z-offset", props->tie("position/z-offset",
SGRawValueMethods<FGAIBase,double>(*this, &FGAIBase::_getZOffset, &FGAIBase::setZoffset)); SGRawValueMethods<FGAIBase,double>(*this, &FGAIBase::_getZOffset, &FGAIBase::setZoffset));
props->tie("position/tgt-x-offset", props->tie("position/tgt-x-offset",
SGRawValueMethods<FGAIWingman,double>(*this, &FGAIWingman::getTgtXOffset, &FGAIWingman::setTgtXOffset)); SGRawValueMethods<FGAIBallistic,double>(*this, &FGAIBallistic::getTgtXOffset, &FGAIBallistic::setTgtXOffset));
props->tie("position/tgt-y-offset", props->tie("position/tgt-y-offset",
SGRawValueMethods<FGAIWingman,double>(*this, &FGAIWingman::getTgtYOffset, &FGAIWingman::setTgtYOffset)); SGRawValueMethods<FGAIBallistic,double>(*this, &FGAIBallistic::getTgtYOffset, &FGAIBallistic::setTgtYOffset));
props->tie("position/tgt-z-offset", props->tie("position/tgt-z-offset",
SGRawValueMethods<FGAIWingman,double>(*this, &FGAIWingman::getTgtZOffset, &FGAIWingman::setTgtZOffset)); SGRawValueMethods<FGAIBallistic,double>(*this, &FGAIBallistic::getTgtZOffset, &FGAIBallistic::setTgtZOffset));
} }
void FGAIWingman::unbind() { void FGAIWingman::unbind() {
FGAIBallistic::unbind(); FGAIBallistic::unbind();
props->untie("id");
props->untie("SubID");
props->untie("orientation/pitch-deg");
props->untie("orientation/roll-deg");
props->untie("orientation/true-heading-deg");
props->untie("submodels/serviceable");
props->untie("velocities/true-airspeed-kt");
props->untie("velocities/vertical-speed-fps");
props->untie("velocities/speed_east_fps");
props->untie("velocities/speed_north_fps");
props->untie("load/rel-brg-to-user-deg"); props->untie("load/rel-brg-to-user-deg");
props->untie("load/elev-to-user-deg"); props->untie("load/elev-to-user-deg");
props->untie("velocities/vertical-speed-fps");
props->untie("position/altitude-ft");
props->untie("position/latitude-deg");
props->untie("position/longitude-deg");
props->untie("position/x-offset"); props->untie("position/x-offset");
props->untie("position/y-offset"); props->untie("position/y-offset");
props->untie("position/z-offset"); props->untie("position/z-offset");
@ -108,11 +158,13 @@ bool FGAIWingman::init(bool search_in_AI_path) {
roll = _rotation; roll = _rotation;
_ht_agl_ft = 1e10; _ht_agl_ft = 1e10;
props->setStringValue("submodels/path", _path.c_str());
return true; return true;
} }
void FGAIWingman::update(double dt) { void FGAIWingman::update(double dt) {
FGAIBallistic::update(dt); FGAIBallistic::update(dt);
// cout << FGAIBase::_getName() << " update speed " << FGAIBase::_getSpeed() << endl;
} }
// end AIWingman // end AIWingman

View file

@ -28,16 +28,15 @@ const double FGSubmodelMgr::lbs_to_slugs = 0.031080950172;
FGSubmodelMgr::FGSubmodelMgr() FGSubmodelMgr::FGSubmodelMgr()
{ {
x_offset = y_offset = 0.0; x_offset = y_offset = z_offset = 0.0;
z_offset = -4.0; pitch_offset = 0.0;
pitch_offset = 2.0;
yaw_offset = 0.0; yaw_offset = 0.0;
out[0] = out[1] = out[2] = 0; //out[0] = out[1] = out[2] = 0;
string contents_node; string contents_node;
contrail_altitude = 30000; contrail_altitude = 30000;
_count = 0; _count = 0;
_found_sub = true; _found_sub = true;
} }
FGSubmodelMgr::~FGSubmodelMgr() FGSubmodelMgr::~FGSubmodelMgr()
@ -78,16 +77,24 @@ void FGSubmodelMgr::init()
ai = (FGAIManager*)globals->get_subsystem("ai_model"); ai = (FGAIManager*)globals->get_subsystem("ai_model");
load(); load();
//_model_added_node = fgGetNode("ai/models/model-added", true);
//_model_added_node->addChangeListener(this, false);
} }
void FGSubmodelMgr::postinit() { void FGSubmodelMgr::postinit() {
// postinit, so that the AI list is populated // postinit, so that the AI list is populated
loadAI();
while (_found_sub) loadAI();
loadSubmodels();
while (_found_sub)
loadSubmodels();
//TODO reload submodels if an MP ac joins //TODO reload submodels if an MP ac joins
//_model_added_node = fgGetNode("ai/models/model-added", true);
//_model_added_node->addChangeListener(this, false);
} }
void FGSubmodelMgr::bind() void FGSubmodelMgr::bind()
@ -109,7 +116,7 @@ void FGSubmodelMgr::update(double dt)
_impact = false; _impact = false;
_hit = false; _hit = false;
_expiry = false; _expiry = false;
// check if the submodel hit an object or terrain // check if the submodel hit an object or terrain
sm_list = ai->get_ai_list(); sm_list = ai->get_ai_list();
@ -117,20 +124,32 @@ void FGSubmodelMgr::update(double dt)
sm_list_iterator end = sm_list.end(); sm_list_iterator end = sm_list.end();
for (; sm_list_itr != end; ++sm_list_itr) { for (; sm_list_itr != end; ++sm_list_itr) {
_impact = (*sm_list_itr)->_getImpactData(); FGAIBase::object_type object_type =(*sm_list_itr)->getType();
_hit = (*sm_list_itr)->_getCollisionData();
_expiry = (*sm_list_itr)->_getExpiryData(); if (object_type != FGAIBase::otBallistic){// only work on ballistic objects
continue; // so continue
}
int parent_subID = (*sm_list_itr)->_getSubID(); int parent_subID = (*sm_list_itr)->_getSubID();
int id = (*sm_list_itr)->getID();
if ( parent_subID == 0 || id == -1) // this entry in the list has no associated submodel
continue; // or is invalid so we can continue
//SG_LOG(SG_GENERAL, SG_DEBUG, "Submodel: Impact " << _impact << " hit! " //SG_LOG(SG_GENERAL, SG_DEBUG, "Submodel: Impact " << _impact << " hit! "
// << _hit <<" parent_subID " << parent_subID); // << _hit <<" parent_subID " << parent_subID);
if ( parent_subID == 0) // this entry in the list has no associated submodel _hit = (*sm_list_itr)->_getCollisionData();
continue; // so we can continue _impact = (*sm_list_itr)->_getImpactData();
_expiry = (*sm_list_itr)->_getExpiryData();
//SG_LOG(SG_GENERAL, SG_ALERT, "Submodel: " << (*sm_list_itr)->_getName()
// << " Impact " << _impact << " hit! " << _hit
// << " exipiry :-( " << _expiry );
if (_impact || _hit || _expiry) { if (_impact || _hit || _expiry) {
// SG_LOG(SG_GENERAL, SG_ALERT, "Submodel: Impact " << _impact << " hit! " << _hit // SG_LOG(SG_GENERAL, SG_ALERT, "Submodel: Impact " << _impact << " hit! " << _hit
//<< " exipiry :-( " << _expiry ); //<< " exipiry :-( " << _expiry );
submodel_iterator = submodels.begin(); submodel_iterator = submodels.begin();
@ -147,10 +166,12 @@ void FGSubmodelMgr::update(double dt)
_parent_roll = (*sm_list_itr)->_getImpactRoll(); _parent_roll = (*sm_list_itr)->_getImpactRoll();
_parent_speed = (*sm_list_itr)->_getImpactSpeed(); _parent_speed = (*sm_list_itr)->_getImpactSpeed();
(*submodel_iterator)->first_time = true; (*submodel_iterator)->first_time = true;
//cout << "Impact: parent SubID = child_ID elev " << _parent_elev << endl; //cout << "Impact: parent SubID = child_ID elev " << _parent_elev << endl;
if (release(*submodel_iterator, dt)) if (release(*submodel_iterator, dt)){
(*sm_list_itr)->setDie(true); (*sm_list_itr)->setDie(true);
//cout << "Impact: set die" << (*sm_list_itr)->_getName() << endl;
}
} }
@ -162,43 +183,43 @@ void FGSubmodelMgr::update(double dt)
_contrail_trigger->setBoolValue(_user_alt_node->getDoubleValue() > contrail_altitude); _contrail_trigger->setBoolValue(_user_alt_node->getDoubleValue() > contrail_altitude);
bool in_range = true; // bool in_range = true;
bool trigger = false; bool trigger = false;
int i = -1; int i = -1;
submodel_iterator = submodels.begin(); submodel_iterator = submodels.begin();
while (submodel_iterator != submodels.end()) { while (submodel_iterator != submodels.end()) {
i++; i++;
in_range = true;
/*SG_LOG(SG_GENERAL, SG_DEBUG, /*SG_LOG(SG_GENERAL, SG_DEBUG,
"Submodels: " << (*submodel_iterator)->id "Submodels: " << (*submodel_iterator)->id
<< " name " << (*submodel_iterator)->name << " name " << (*submodel_iterator)->name
<< " in range " << in_range);*/ );*/
if ((*submodel_iterator)->trigger_node != 0) { if ((*submodel_iterator)->trigger_node != 0) {
_trigger_node = (*submodel_iterator)->trigger_node; _trigger_node = (*submodel_iterator)->trigger_node;
trigger = _trigger_node->getBoolValue(); trigger = _trigger_node->getBoolValue();
//cout << (*submodel_iterator)->name << "trigger node found " << trigger << endl; //cout << (*submodel_iterator)->name << "trigger node found " << trigger << endl;
} else { } else {
trigger = true; trigger = false;
//cout << (*submodel_iterator)->name << "trigger node not found " << trigger << endl; //cout << (*submodel_iterator)->name << " trigger node not found " << trigger << endl;
} }
if (trigger && (*submodel_iterator)->count != 0) { if (trigger && (*submodel_iterator)->count != 0) {
int id = (*submodel_iterator)->id; int id = (*submodel_iterator)->id;
string name = (*submodel_iterator)->name; string name = (*submodel_iterator)->name;
/*SG_LOG(SG_GENERAL, SG_DEBUG, SG_LOG(SG_GENERAL, SG_DEBUG,
"Submodels end: " << (*submodel_iterator)->id "Submodels release: " << (*submodel_iterator)->id
<< " name " << (*submodel_iterator)->name << " name " << (*submodel_iterator)->name
<< " count " << (*submodel_iterator)->count << " count " << (*submodel_iterator)->count
<< " in range " << in_range);*/ << " slaved " << (*submodel_iterator)->slaved
);
release(*submodel_iterator, dt); release(*submodel_iterator, dt);
} else } else
(*submodel_iterator)->first_time = true; (*submodel_iterator)->first_time = true;
++submodel_iterator; ++submodel_iterator;
} // end while } // end while
@ -206,13 +227,20 @@ void FGSubmodelMgr::update(double dt)
bool FGSubmodelMgr::release(submodel *sm, double dt) bool FGSubmodelMgr::release(submodel *sm, double dt)
{ {
//cout << "release id " << sm->id << " name " << sm->name //cout << "release id " << sm->id
//<< " first time " << sm->first_time << " repeat " << sm->repeat << // << " name " << sm->name
// endl; // << " first time " << sm->first_time
// << " repeat " << sm->repeat
// << " slaved " << sm->slaved
// << endl;
// only run if first time or repeat is set to true // only run if first time or repeat is set to true
if (!sm->first_time && !sm->repeat) { if (!sm->first_time && !sm->repeat) {
//cout<< "not first time " << sm->first_time<< " repeat " << sm->repeat <<endl; //cout<< "returning: "<< sm->name
// << " not first time " << sm->first_time
// << " repeat " << sm->repeat
// << " slaved " << sm->slaved
// << endl;
return false; return false;
} }
@ -222,8 +250,8 @@ bool FGSubmodelMgr::release(submodel *sm, double dt)
//cout << "not yet: timer " << sm->timer << " delay " << sm->delay << endl; //cout << "not yet: timer " << sm->timer << " delay " << sm->delay << endl;
return false; return false;
} }
//cout << "released timer: " << sm->timer << " delay " << sm->delay << endl; //cout << "released timer: " << sm->timer << " delay " << sm->delay << endl;
sm->timer = 0.0; sm->timer = 0.0;
@ -237,11 +265,12 @@ bool FGSubmodelMgr::release(submodel *sm, double dt)
FGAIBallistic* ballist = new FGAIBallistic; FGAIBallistic* ballist = new FGAIBallistic;
ballist->setPath(sm->model.c_str()); ballist->setPath(sm->model.c_str());
ballist->setName(sm->name); ballist->setName(sm->name);
ballist->setRandom(sm->random); ballist->setSlaved(sm->slaved);
ballist->setRandomness(sm->randomness); ballist->setRandom(sm->random);
ballist->setLatitude(offsetpos.getLatitudeDeg()); ballist->setRandomness(sm->randomness);
ballist->setLongitude(offsetpos.getLongitudeDeg()); ballist->setLatitude(offsetpos.getLatitudeDeg());
ballist->setAltitude(offsetpos.getElevationFt()); ballist->setLongitude(offsetpos.getLongitudeDeg());
ballist->setAltitude(offsetpos.getElevationFt());
ballist->setAzimuth(IC.azimuth); ballist->setAzimuth(IC.azimuth);
ballist->setElevation(IC.elevation); ballist->setElevation(IC.elevation);
ballist->setRoll(IC.roll); ballist->setRoll(IC.roll);
@ -257,7 +286,7 @@ bool FGSubmodelMgr::release(submodel *sm, double dt)
ballist->setStabilisation(sm->aero_stabilised); ballist->setStabilisation(sm->aero_stabilised);
ballist->setNoRoll(sm->no_roll); ballist->setNoRoll(sm->no_roll);
ballist->setCollision(sm->collision); ballist->setCollision(sm->collision);
ballist->setExpiry(sm->expiry); ballist->setExpiry(sm->expiry);
ballist->setImpact(sm->impact); ballist->setImpact(sm->impact);
ballist->setImpactReportNode(sm->impact_report); ballist->setImpactReportNode(sm->impact_report);
ballist->setFuseRange(sm->fuse_range); ballist->setFuseRange(sm->fuse_range);
@ -266,6 +295,14 @@ bool FGSubmodelMgr::release(submodel *sm, double dt)
ballist->setForceStabilisation(sm->force_stabilised); ballist->setForceStabilisation(sm->force_stabilised);
ballist->setExternalForce(sm->ext_force); ballist->setExternalForce(sm->ext_force);
ballist->setForcePath(sm->force_path.c_str()); ballist->setForcePath(sm->force_path.c_str());
ballist->setXoffset(sm->x_offset);
ballist->setYoffset(sm->y_offset);
ballist->setZoffset(sm->z_offset);
ballist->setPitchoffset(sm->pitch_offset);
ballist->setYawoffset(sm->yaw_offset);
ballist->setParentNode(_selected_ac);
ballist->setContentsNode(sm->contents_node);
ballist->setWeight(sm->weight);
ai->attach(ballist); ai->attach(ballist);
if (sm->count > 0) if (sm->count > 0)
@ -288,7 +325,7 @@ void FGSubmodelMgr::load()
void FGSubmodelMgr::transform(submodel *sm) void FGSubmodelMgr::transform(submodel *sm)
{ {
// set initial conditions // set initial conditions
if (sm->contents_node != 0) { if (sm->contents_node != 0 && !sm->slaved) {
// get the weight of the contents (lbs) and convert to mass (slugs) // get the weight of the contents (lbs) and convert to mass (slugs)
sm->contents = sm->contents_node->getChild("level-lbs",0,1)->getDoubleValue(); sm->contents = sm->contents_node->getChild("level-lbs",0,1)->getDoubleValue();
//cout << "transform: contents " << sm->contents << endl; //cout << "transform: contents " << sm->contents << endl;
@ -303,21 +340,22 @@ void FGSubmodelMgr::transform(submodel *sm)
} else } else
IC.mass = sm->weight * lbs_to_slugs; IC.mass = sm->weight * lbs_to_slugs;
// cout << "mass " << IC.mass << endl; int id = sm->id;
int sub_id = sm->sub_id;
string name = sm->name;
if (sm->speed_node != 0) if (sm->speed_node != 0)
sm->speed = sm->speed_node->getDoubleValue(); sm->speed = sm->speed_node->getDoubleValue();
int id = sm->id;
//int sub_id = (*submodel)->sub_id;
string name = sm->name;
//cout << " name " << name << " id " << id << " sub id" << sub_id << endl; //cout << " name " << name << " id " << id << " sub id" << sub_id << endl;
// set the Initial Conditions for the types of submodel parent // set the Initial Conditions for the types of submodel parent
if (_impact || _hit || _expiry) { if (_impact || _hit || _expiry) {
// set the data for a submodel tied to a submodel // set the data for a submodel tied to a submodel
_count++; _count++;
IC.lat = _parent_lat; IC.lat = _parent_lat;
@ -347,56 +385,40 @@ void FGSubmodelMgr::transform(submodel *sm)
} else { } else {
// set the data for a submodel tied to an AI Object // set the data for a submodel tied to an AI Object
//cout << " set the data for a submodel tied to an AI Object " << id << endl;
sm_list_iterator sm_list_itr = sm_list.begin(); sm_list_iterator sm_list_itr = sm_list.begin();
sm_list_iterator end = sm_list.end(); sm_list_iterator end = sm_list.end();
setParentNode(id);
while (sm_list_itr != end) {
int parent_id = (*sm_list_itr)->getID();
if (id != parent_id) {
++sm_list_itr;
continue;
}
//cout << "found id " << id << endl;
IC.lat = (*sm_list_itr)->_getLatitude();
IC.lon = (*sm_list_itr)->_getLongitude();
IC.alt = (*sm_list_itr)->_getAltitude();
IC.roll = (*sm_list_itr)->_getRoll();
IC.elevation = (*sm_list_itr)->_getPitch();
IC.azimuth = (*sm_list_itr)->_getHeading();
IC.alt = (*sm_list_itr)->_getAltitude();
IC.speed = (*sm_list_itr)->_getSpeed() * SG_KT_TO_FPS;
IC.speed_down_fps = -(*sm_list_itr)->_getVS_fps();
IC.speed_east_fps = (*sm_list_itr)->_get_speed_east_fps();
IC.speed_north_fps = (*sm_list_itr)->_get_speed_north_fps();
++sm_list_itr;
}
} }
/*cout << "heading " << IC.azimuth << endl ; //cout << "Submodel: setting IC "<< name << endl;
cout << "speed down " << IC.speed_down_fps << endl ; //cout << "heading " << IC.azimuth << endl ;
cout << "speed east " << IC.speed_east_fps << endl ; //cout << "speed down " << IC.speed_down_fps << endl ;
cout << "speed north " << IC.speed_north_fps << endl ; //cout << "speed east " << IC.speed_east_fps << endl ;
cout << "parent speed fps in" << IC.speed << "sm speed in " << sm->speed << endl ;*/ //cout << "speed north " << IC.speed_north_fps << endl ;
//cout << "parent speed fps in " << IC.speed << "sm speed in " << sm->speed << endl ;
//cout << "lat " << IC.lat;
//cout << "alt " << IC.alt << endl ;
// Set the Initial Conditions that are common to all types of parent
// Set the Initial Conditions that are common to all types of parent
IC.wind_from_east = _user_wind_from_east_node->getDoubleValue(); IC.wind_from_east = _user_wind_from_east_node->getDoubleValue();
IC.wind_from_north = _user_wind_from_north_node->getDoubleValue(); IC.wind_from_north = _user_wind_from_north_node->getDoubleValue();
userpos.setLatitudeDeg(IC.lat); //cout << "wind e " << IC.wind_from_east << " n " << IC.wind_from_north << endl;
userpos.setLongitudeDeg(IC.lon);
userpos.setElevationFt(IC.alt); userpos.setLatitudeDeg(IC.lat);
userpos.setLongitudeDeg(IC.lon);
userpos.setElevationFt(IC.alt);
_x_offset = sm->x_offset; _x_offset = sm->x_offset;
_y_offset = sm->y_offset; _y_offset = sm->y_offset;
_z_offset = sm->z_offset; _z_offset = sm->z_offset;
setOffsetPos(); setOffsetPos();
//IC.elevation += sm->pitch_offset; //IC.elevation += sm->pitch_offset;
//IC.azimuth += sm->yaw_offset ; //IC.azimuth += sm->yaw_offset ;
// pre-process the trig functions // pre-process the trig functions
cosRx = cos(-IC.roll * SG_DEGREES_TO_RADIANS); cosRx = cos(-IC.roll * SG_DEGREES_TO_RADIANS);
@ -431,7 +453,7 @@ void FGSubmodelMgr::transform(submodel *sm)
// if speeds are low this calculation can become unreliable // if speeds are low this calculation can become unreliable
if (IC.speed > 1) { if (IC.speed > 1) {
//IC.azimuth = atan2(IC.total_speed_east, IC.total_speed_north) * SG_RADIANS_TO_DEGREES; IC.azimuth = atan2(IC.total_speed_east, IC.total_speed_north) * SG_RADIANS_TO_DEGREES;
// cout << "azimuth1 " << IC.azimuth<<endl; // cout << "azimuth1 " << IC.azimuth<<endl;
// rationalise the output // rationalise the output
@ -445,6 +467,7 @@ void FGSubmodelMgr::transform(submodel *sm)
* IC.total_speed_north + IC.total_speed_east * IC.total_speed_east)) * IC.total_speed_north + IC.total_speed_east * IC.total_speed_east))
* SG_RADIANS_TO_DEGREES; * SG_RADIANS_TO_DEGREES;
} }
//cout << "IC.speed " << IC.speed / SG_KT_TO_FPS << endl;
} }
void FGSubmodelMgr::updatelat(double lat) void FGSubmodelMgr::updatelat(double lat)
@ -460,7 +483,7 @@ void FGSubmodelMgr::loadAI()
sm_list = ai->get_ai_list(); sm_list = ai->get_ai_list();
if (sm_list.empty()) { if (sm_list.empty()) {
SG_LOG(SG_GENERAL, SG_DEBUG, "Submodels: Unable to read AI submodel list"); SG_LOG(SG_GENERAL, SG_ALERT, "Submodels: Unable to read AI submodel list");
return; return;
} }
@ -476,7 +499,11 @@ void FGSubmodelMgr::loadAI()
} }
int id = (*sm_list_itr)->getID(); int id = (*sm_list_itr)->getID();
string type = (*sm_list_itr)->getTypeString();
bool serviceable = (*sm_list_itr)->_getServiceable(); bool serviceable = (*sm_list_itr)->_getServiceable();
//cout << "loadAI: type " << type << " path "<< path << " serviceable " << serviceable << endl;
setData(id, path, serviceable); setData(id, path, serviceable);
++sm_list_itr; ++sm_list_itr;
} }
@ -490,13 +517,13 @@ void FGSubmodelMgr::setData(int id, string& path, bool serviceable)
SGPath config(globals->get_fg_root()); SGPath config(globals->get_fg_root());
config.append(path); config.append(path);
SG_LOG(SG_GENERAL, SG_DEBUG, "Submodels: path " << path); SG_LOG(SG_GENERAL, SG_DEBUG, "setData: path " << path);
try { try {
SG_LOG(SG_GENERAL, SG_DEBUG, SG_LOG(SG_GENERAL, SG_DEBUG,
"Submodels: Trying to read AI submodels file: " << config.str()); "Submodels: Trying to read AI submodels file: " << config.str());
readProperties(config.str(), &root); readProperties(config.str(), &root);
} catch (const sg_exception &) { } catch (const sg_exception &) {
SG_LOG(SG_GENERAL, SG_DEBUG, SG_LOG(SG_GENERAL, SG_ALERT,
"Submodels: Unable to read AI submodels file: " << config.str()); "Submodels: Unable to read AI submodels file: " << config.str());
return; return;
} }
@ -530,21 +557,19 @@ void FGSubmodelMgr::setData(int id, string& path, bool serviceable)
sm->aero_stabilised = entry_node->getBoolValue("aero-stabilised", true); sm->aero_stabilised = entry_node->getBoolValue("aero-stabilised", true);
sm->no_roll = entry_node->getBoolValue("no-roll", false); sm->no_roll = entry_node->getBoolValue("no-roll", false);
sm->collision = entry_node->getBoolValue("collision", false); sm->collision = entry_node->getBoolValue("collision", false);
sm->expiry = entry_node->getBoolValue("expiry", false); sm->expiry = entry_node->getBoolValue("expiry", false);
sm->impact = entry_node->getBoolValue("impact", false); sm->impact = entry_node->getBoolValue("impact", false);
sm->impact_report = entry_node->getStringValue("impact-reports"); sm->impact_report = entry_node->getStringValue("impact-reports");
sm->fuse_range = entry_node->getDoubleValue("fuse-range", 0.0); sm->fuse_range = entry_node->getDoubleValue("fuse-range", 0.0);
sm->contents_node = fgGetNode(entry_node->getStringValue("contents", "none"), false); sm->contents_node = fgGetNode(entry_node->getStringValue("contents", "none"), false);
sm->speed_node = fgGetNode(entry_node->getStringValue("speed-node", "none"), false); sm->speed_node = fgGetNode(entry_node->getStringValue("speed-prop", "none"), false);
sm->submodel = entry_node->getStringValue("submodel-path", ""); sm->submodel = entry_node->getStringValue("submodel-path", "");
sm->force_stabilised= entry_node->getBoolValue("force-stabilised", false); sm->force_stabilised= entry_node->getBoolValue("force-stabilised", false);
sm->ext_force = entry_node->getBoolValue("external-force", false); sm->ext_force = entry_node->getBoolValue("external-force", false);
sm->force_path = entry_node->getStringValue("force-path", ""); sm->force_path = entry_node->getStringValue("force-path", "");
sm->random = entry_node->getBoolValue("random", false); sm->random = entry_node->getBoolValue("random", false);
sm->randomness = entry_node->getDoubleValue("randomness", 0.5); sm->randomness = entry_node->getDoubleValue("randomness", 0.5);
//cout << "sm->contents_node " << sm->contents_node << endl;
if (sm->contents_node != 0) if (sm->contents_node != 0)
sm->contents = sm->contents_node->getDoubleValue(); sm->contents = sm->contents_node->getDoubleValue();
@ -566,19 +591,19 @@ void FGSubmodelMgr::setData(int id, string& path, bool serviceable)
sm->sub_id = 0; sm->sub_id = 0;
sm->prop = fgGetNode("/ai/submodels/submodel", index, true); sm->prop = fgGetNode("/ai/submodels/submodel", index, true);
sm->prop->tie("delay", SGRawValuePointer<double>(&(sm->delay))); sm->prop->tie("delay", SGRawValuePointer<double>(&(sm->delay)));
sm->prop->tie("count", SGRawValuePointer<int>(&(sm->count))); sm->prop->tie("count", SGRawValuePointer<int>(&(sm->count)));
sm->prop->tie("repeat", SGRawValuePointer<bool>(&(sm->repeat))); sm->prop->tie("repeat", SGRawValuePointer<bool>(&(sm->repeat)));
sm->prop->tie("id", SGRawValuePointer<int>(&(sm->id))); sm->prop->tie("id", SGRawValuePointer<int>(&(sm->id)));
sm->prop->tie("sub-id", SGRawValuePointer<int>(&(sm->sub_id))); sm->prop->tie("sub-id", SGRawValuePointer<int>(&(sm->sub_id)));
sm->prop->tie("serviceable", SGRawValuePointer<bool>(&(sm->serviceable))); sm->prop->tie("serviceable", SGRawValuePointer<bool>(&(sm->serviceable)));
sm->prop->tie("random", SGRawValuePointer<bool>(&(sm->random))); sm->prop->tie("random", SGRawValuePointer<bool>(&(sm->random)));
sm->prop->tie("slaved", SGRawValuePointer<bool>(&(sm->slaved)));
string name = sm->name; string name = sm->name;
sm->prop->setStringValue("name", name.c_str()); sm->prop->setStringValue("name", name.c_str());
string submodel = sm->submodel; string submodel = sm->submodel;
sm->prop->setStringValue("submodel", submodel.c_str()); sm->prop->setStringValue("submodel", submodel.c_str());
//cout << " set submodel path " << submodel << endl;
string force_path = sm->force_path; string force_path = sm->force_path;
sm->prop->setStringValue("force_path", force_path.c_str()); sm->prop->setStringValue("force_path", force_path.c_str());
@ -598,15 +623,15 @@ void FGSubmodelMgr::setSubData(int id, string& path, bool serviceable)
SGPath config(globals->get_fg_root()); SGPath config(globals->get_fg_root());
config.append(path); config.append(path);
SG_LOG(SG_GENERAL, SG_DEBUG, SG_LOG(SG_GENERAL, SG_DEBUG, "setSubData: path " << path);
"Submodels: path " << path);
try { try {
SG_LOG(SG_GENERAL, SG_DEBUG, SG_LOG(SG_GENERAL, SG_DEBUG,
"Submodels: Trying to read AI submodels file: " << config.str()); "Submodels: Trying to read AI submodels file: " << config.str());
readProperties(config.str(), &root); readProperties(config.str(), &root);
} catch (const sg_exception &) { } catch (const sg_exception &) {
SG_LOG(SG_GENERAL, SG_DEBUG, SG_LOG(SG_GENERAL, SG_ALERT,
"Submodels: Unable to read AI submodels file: " << config.str()); "Submodels: Unable to read AI submodels file: " << config.str());
return; return;
} }
@ -640,20 +665,19 @@ void FGSubmodelMgr::setSubData(int id, string& path, bool serviceable)
sm->aero_stabilised = entry_node->getBoolValue("aero-stabilised", true); sm->aero_stabilised = entry_node->getBoolValue("aero-stabilised", true);
sm->no_roll = entry_node->getBoolValue("no-roll", false); sm->no_roll = entry_node->getBoolValue("no-roll", false);
sm->collision = entry_node->getBoolValue("collision", false); sm->collision = entry_node->getBoolValue("collision", false);
sm->expiry = entry_node->getBoolValue("expiry", false); sm->expiry = entry_node->getBoolValue("expiry", false);
sm->impact = entry_node->getBoolValue("impact", false); sm->impact = entry_node->getBoolValue("impact", false);
sm->impact_report = entry_node->getStringValue("impact-reports"); sm->impact_report = entry_node->getStringValue("impact-reports");
sm->fuse_range = entry_node->getDoubleValue("fuse-range", 0.0); sm->fuse_range = entry_node->getDoubleValue("fuse-range", 0.0);
sm->contents_node = fgGetNode(entry_node->getStringValue("contents", "none"), false); sm->contents_node = fgGetNode(entry_node->getStringValue("contents", "none"), false);
sm->speed_node = fgGetNode(entry_node->getStringValue("speed-node", "none"), false); sm->speed_node = fgGetNode(entry_node->getStringValue("speed-prop", "none"), false);
sm->submodel = entry_node->getStringValue("submodel-path", ""); sm->submodel = entry_node->getStringValue("submodel-path", "");
sm->force_stabilised= entry_node->getBoolValue("force-stabilised", false); sm->force_stabilised= entry_node->getBoolValue("force-stabilised", false);
sm->ext_force = entry_node->getBoolValue("external-force", false); sm->ext_force = entry_node->getBoolValue("external-force", false);
sm->force_path = entry_node->getStringValue("force-path", ""); sm->force_path = entry_node->getStringValue("force-path", "");
sm->random = entry_node->getBoolValue("random", false); sm->random = entry_node->getBoolValue("random", false);
sm->randomness = entry_node->getDoubleValue("randomness", 0.5); sm->randomness = entry_node->getDoubleValue("randomness", 0.5);
//cout << "sm->contents_node " << sm->contents_node << endl;
if (sm->contents_node != 0) if (sm->contents_node != 0)
sm->contents = sm->contents_node->getDoubleValue(); sm->contents = sm->contents_node->getDoubleValue();
@ -680,12 +704,14 @@ void FGSubmodelMgr::setSubData(int id, string& path, bool serviceable)
sm->prop->tie("id", SGRawValuePointer<int>(&(sm->id))); sm->prop->tie("id", SGRawValuePointer<int>(&(sm->id)));
sm->prop->tie("sub-id", SGRawValuePointer<int>(&(sm->sub_id))); sm->prop->tie("sub-id", SGRawValuePointer<int>(&(sm->sub_id)));
sm->prop->tie("serviceable", SGRawValuePointer<bool>(&(sm->serviceable))); sm->prop->tie("serviceable", SGRawValuePointer<bool>(&(sm->serviceable)));
sm->prop->tie("random", SGRawValuePointer<bool>(&(sm->random))); sm->prop->tie("random", SGRawValuePointer<bool>(&(sm->random)));
sm->prop->tie("slaved", SGRawValuePointer<bool>(&(sm->slaved)));
string name = sm->name; string name = sm->name;
sm->prop->setStringValue("name", name.c_str()); sm->prop->setStringValue("name", name.c_str());
string submodel = sm->submodel; string submodel = sm->submodel;
sm->prop->setStringValue("submodel", submodel.c_str()); sm->prop->setStringValue("submodel-path", submodel.c_str());
// cout << " set submodel path AI" << submodel<< endl; // cout << " set submodel path AI" << submodel<< endl;
string force_path = sm->force_path; string force_path = sm->force_path;
@ -704,49 +730,55 @@ void FGSubmodelMgr::loadSubmodels()
{ {
SG_LOG(SG_GENERAL, SG_DEBUG, "Submodels: Loading sub submodels"); SG_LOG(SG_GENERAL, SG_DEBUG, "Submodels: Loading sub submodels");
_found_sub = false; _found_sub = false;
submodel_iterator = submodels.begin(); submodel_iterator = submodels.begin();
while (submodel_iterator != submodels.end()) { while (submodel_iterator != submodels.end()) {
string submodel = (*submodel_iterator)->submodel; string submodel = (*submodel_iterator)->submodel;
if (!submodel.empty()) { if (!submodel.empty()) {
//int id = (*submodel_iterator)->id; //int id = (*submodel_iterator)->id;
bool serviceable = true; bool serviceable = true;
//SG_LOG(SG_GENERAL, SG_DEBUG, "found path sub sub " SG_LOG(SG_GENERAL, SG_DEBUG, "found path sub sub "
// << submodel << submodel
// << " index " << index << " index " << index
// << "name " << (*submodel_iterator)->name); << " name " << (*submodel_iterator)->name);
if ((*submodel_iterator)->sub_id == 0){ if ((*submodel_iterator)->sub_id == 0){
(*submodel_iterator)->sub_id = index; (*submodel_iterator)->sub_id = index;
_found_sub = true; _found_sub = true;
setSubData(index, submodel, serviceable); setSubData(index, submodel, serviceable);
} }
} }
++submodel_iterator; ++submodel_iterator;
} // end while } // end while
subsubmodel_iterator = subsubmodels.begin(); subsubmodel_iterator = subsubmodels.begin();
while (subsubmodel_iterator != subsubmodels.end()) { while (subsubmodel_iterator != subsubmodels.end()) {
submodels.push_back(*subsubmodel_iterator); submodels.push_back(*subsubmodel_iterator);
++subsubmodel_iterator; ++subsubmodel_iterator;
} // end while } // end while
subsubmodels.clear(); subsubmodels.clear();
//submodel_iterator = submodels.begin(); //submodel_iterator = submodels.begin();
//while (submodel_iterator != submodels.end()) { //int subcount = 0;
//int id = (*submodel_iterator)->id;
//SG_LOG(SG_GENERAL, SG_DEBUG,"after pushback "
// << " id " << id
// << " name " << (*submodel_iterator)->name
// << " sub id " << (*submodel_iterator)->sub_id);
//++submodel_iterator; //while (submodel_iterator != submodels.end()) {
// int id = (*submodel_iterator)->id;
// subcount++;
// SG_LOG(SG_GENERAL, SG_ALERT,"after pushback "
// << " parent id " << id
// << " name " << (*submodel_iterator)->name
// << " sub id " << (*submodel_iterator)->sub_id
// << " subcount "<< subcount);
// ++submodel_iterator;
//} //}
} }
@ -754,13 +786,12 @@ SGVec3d FGSubmodelMgr::getCartOffsetPos() const{
// convert geodetic positions to geocentered // convert geodetic positions to geocentered
SGVec3d cartuserPos = SGVec3d::fromGeod(userpos); SGVec3d cartuserPos = SGVec3d::fromGeod(userpos);
// Transform to the right coordinate frame, configuration is done in // Transform to the right coordinate frame, configuration is done in
// the x-forward, y-right, z-up coordinates (feet), computation // the x-forward, y-right, z-up coordinates (feet), computation
// in the simulation usual body x-forward, y-right, z-down coordinates // in the simulation usual body x-forward, y-right, z-down coordinates
// (meters) ) // (meters) )
SGVec3d _off(_x_offset * SG_FEET_TO_METER, SGVec3d _off(_x_offset * SG_FEET_TO_METER,
_y_offset * SG_FEET_TO_METER, _y_offset * SG_FEET_TO_METER,
-_z_offset * SG_FEET_TO_METER); -_z_offset * SG_FEET_TO_METER);
@ -780,7 +811,6 @@ SGVec3d FGSubmodelMgr::getCartOffsetPos() const{
// Add the position offset of the user model to get the geocentered position // Add the position offset of the user model to get the geocentered position
SGVec3d offsetPos = cartuserPos + off; SGVec3d offsetPos = cartuserPos + off;
return offsetPos; return offsetPos;
} }
@ -789,5 +819,106 @@ void FGSubmodelMgr::setOffsetPos(){
SGVec3d cartoffsetPos = getCartOffsetPos(); SGVec3d cartoffsetPos = getCartOffsetPos();
SGGeodesy::SGCartToGeod(cartoffsetPos, offsetpos); SGGeodesy::SGCartToGeod(cartoffsetPos, offsetpos);
//cout << "OFFSET POS" << offsetpos.getElevationFt();
}
void FGSubmodelMgr::valueChanged(SGPropertyNode *prop)
{
// cout << "LISTENER: " << endl;
const char* _model_added = _model_added_node->getStringValue();
basic_string <char>::size_type indexCh2b;
string str2 = _model_added;
const char *cstr2b = "ballistic";
indexCh2b = str2.find( cstr2b, 0 );
// cout << "model added - " << str2 <<" now do something "<< endl;
if (indexCh2b != string::npos ){ // we will ignore Ballistic Objects - there are potentially too many
return;
} else {
SGPropertyNode *a_node = fgGetNode(_model_added, true );
SGPropertyNode *sub_node = a_node->getChild("submodels", 0, true);
SGPropertyNode_ptr path_node = sub_node->getChild("path", 0, true);
string path = path_node->getStringValue();
if (path.empty()){
// nothing to do - return
//cout << "subpath empty - return" << endl << endl;
return;
} else {
//cout << "subpath found - loading" << endl << endl;
SGPropertyNode_ptr ident_node = a_node->getChild("id", 0, true);
int id = ident_node->getIntValue();
setData(id, path, true);
_found_sub = true;
while (_found_sub)
loadSubmodels();
}
}
}
void FGSubmodelMgr::setParentNode(int id) {
const SGPropertyNode_ptr ai = fgGetNode("/ai/models", true);
for (int i = ai->nChildren() - 1; i >= -1; i--) {
SGPropertyNode_ptr model;
if (i < 0) { // last iteration: selected model
model = _selected_ac;
} else {
model = ai->getChild(i);
string path = ai->getPath();
const string name = model->getStringValue("name");
int parent_id = model->getIntValue("id");
if (!model->nChildren()){
continue;
}
if (parent_id == id) {
_selected_ac = model; // save selected model for last iteration
break;
}
}
if (!model)
continue;
}// end for loop
if (_selected_ac != 0){
//cout << " parent node found"<< endl;
const string name = _selected_ac->getStringValue("name");
IC.lat = _selected_ac->getDoubleValue("position/latitude-deg");
IC.lon = _selected_ac->getDoubleValue("position/longitude-deg");
IC.alt = _selected_ac->getDoubleValue("position/altitude-ft");
IC.roll = _selected_ac->getDoubleValue("orientation/roll-deg");
IC.elevation = _selected_ac->getDoubleValue("orientation/pitch-deg");
IC.azimuth = _selected_ac->getDoubleValue("orientation/true-heading-deg");
IC.speed = _selected_ac->getDoubleValue("velocities/true-airspeed-kt") * SG_KT_TO_FPS;
IC.speed_down_fps = -_selected_ac->getDoubleValue("velocities/vertical-speed-fps");
IC.speed_east_fps = _selected_ac->getDoubleValue("velocities/speed-east-fps");
IC.speed_north_fps = _selected_ac->getDoubleValue("velocities/speed-north-fps");
//cout << name << " IC.speed " << IC.speed << endl;
} else {
SG_LOG(SG_GENERAL, SG_ALERT, "AISubmodel: parent node not found ");
}
} }
// end of submodel.cxx // end of submodel.cxx

View file

@ -20,12 +20,12 @@
#include <Main/fg_props.hxx> #include <Main/fg_props.hxx>
using std::vector; using std::vector;
using std::string; using std::string;
using std::list; using std::list;
class FGAIBase; class FGAIBase;
class FGSubmodelMgr : public SGSubsystem class FGSubmodelMgr : public SGSubsystem, public SGPropertyChangeListener
{ {
public: public:
@ -53,19 +53,20 @@ public:
double drag_area; double drag_area;
double life; double life;
double buoyancy; double buoyancy;
double randomness; double randomness;
bool wind; bool wind;
bool first_time; bool first_time;
double cd; double cd;
double weight; double weight;
double mass;
double contents; double contents;
bool aero_stabilised; bool aero_stabilised;
int id; int id;
bool no_roll; bool no_roll;
bool serviceable; bool serviceable;
bool random; bool random;
bool collision; bool collision;
bool expiry; bool expiry;
bool impact; bool impact;
string impact_report; string impact_report;
double fuse_range; double fuse_range;
@ -95,6 +96,7 @@ public:
double mass; double mass;
int id; int id;
bool no_roll; bool no_roll;
int parent_id;
} IC_struct; } IC_struct;
FGSubmodelMgr(); FGSubmodelMgr();
@ -144,7 +146,9 @@ private:
double _parent_pitch; double _parent_pitch;
double _parent_roll; double _parent_roll;
double _parent_speed; double _parent_speed;
double _x_offset; double _parent_ID;
double _x_offset;
double _y_offset; double _y_offset;
double _z_offset; double _z_offset;
@ -155,8 +159,8 @@ private:
bool _impact; bool _impact;
bool _hit; bool _hit;
bool _expiry; bool _expiry;
bool _found_sub; bool _found_sub;
SGPropertyNode_ptr _serviceable_node; SGPropertyNode_ptr _serviceable_node;
SGPropertyNode_ptr _user_lat_node; SGPropertyNode_ptr _user_lat_node;
@ -178,6 +182,10 @@ private:
SGPropertyNode_ptr _count_node; SGPropertyNode_ptr _count_node;
SGPropertyNode_ptr _trigger_node; SGPropertyNode_ptr _trigger_node;
SGPropertyNode_ptr props; SGPropertyNode_ptr props;
SGPropertyNode_ptr _model_added_node;
SGPropertyNode_ptr _path_node;
SGPropertyNode_ptr _selected_ac;
FGAIManager* ai; FGAIManager* ai;
IC_struct IC; IC_struct IC;
@ -196,16 +204,17 @@ private:
void setSubData(int id, string& path, bool serviceable); void setSubData(int id, string& path, bool serviceable);
void valueChanged (SGPropertyNode *); void valueChanged (SGPropertyNode *);
void transform(submodel *); void transform(submodel *);
void setParentNode(int parent_id);
bool release(submodel *, double dt); bool release(submodel *, double dt);
int _count; int _count;
SGGeod userpos; SGGeod userpos;
SGGeod offsetpos; SGGeod offsetpos;
SGVec3d getCartOffsetPos() const; SGVec3d getCartOffsetPos() const;
void setOffsetPos(); void setOffsetPos();
}; };

View file

@ -306,19 +306,9 @@ FGEnvironmentMgr::update (double dt)
osg::Vec3 windVec(_environment->get_wind_from_north_fps(), osg::Vec3 windVec(_environment->get_wind_from_north_fps(),
-_environment->get_wind_from_east_fps(), -_environment->get_wind_from_east_fps(),
0); 0);
// SG_LOG(SG_GENERAL, SG_ALERT, "-_environment->get_wind_from_north_mps() " << simgear::Particles::setWindVector(windVec * SG_FEET_TO_METER);
//_environment->get_wind_from_north_fps() * SG_FEET_TO_METER //simgear::Particles::setWindFrom( _environment->get_wind_from_heading_deg(),
//<< " -_environment->get_wind_from_east_mps() " // _environment->get_wind_speed_kt() );
//<< -_environment->get_wind_from_east_fps() * SG_FEET_TO_METER
//);
// simgear::Particles::setWindVector(windVec * SG_FEET_TO_METER);
simgear::Particles::setWindFrom( _environment->get_wind_from_heading_deg(),
_environment->get_wind_speed_kt() );
//double wind_true_deg = _environment->get_wind_from_heading_deg();
//simgear::Particles::setWindFrom( wind_true_deg,
// _environment->get_wind_speed_kt() );
} }
FGEnvironment FGEnvironment

File diff suppressed because it is too large Load diff

View file

@ -115,8 +115,11 @@ FGAISchedule::FGAISchedule(string model,
i++) i++)
flights.push_back(new FGScheduledFlight((*(*i))));*/ flights.push_back(new FGScheduledFlight((*(*i))));*/
AIManagerRef = 0; AIManagerRef = 0;
//score = scre; score = 0;
firstRun = true; firstRun = true;
runCount = 0;
hits = 0;
initialized = false;
} }
FGAISchedule::FGAISchedule(const FGAISchedule &other) FGAISchedule::FGAISchedule(const FGAISchedule &other)
@ -136,13 +139,17 @@ FGAISchedule::FGAISchedule(const FGAISchedule &other)
radius = other.radius; radius = other.radius;
groundOffset = other.groundOffset; groundOffset = other.groundOffset;
flightType = other.flightType; flightType = other.flightType;
//score = other.score; score = other.score;
distanceToUser = other.distanceToUser; distanceToUser = other.distanceToUser;
currentDestination = other.currentDestination; currentDestination = other.currentDestination;
firstRun = other.firstRun; firstRun = other.firstRun;
runCount = other.runCount;
hits = other.hits;
initialized = other.initialized;
} }
FGAISchedule::~FGAISchedule() FGAISchedule::~FGAISchedule()
{ {
/* for (FGScheduledFlightVecIterator flt = flights.begin(); flt != flights.end(); flt++) /* for (FGScheduledFlightVecIterator flt = flights.begin(); flt != flights.end(); flt++)
@ -355,6 +362,14 @@ void FGAISchedule::scheduleFlights()
} }
currentDestination = flight->getArrivalAirport()->getId(); currentDestination = flight->getArrivalAirport()->getId();
if (!initialized) {
string departurePort = flight->getDepartureAirport()->getId();
if (fgGetString("/sim/presets/airport-id") == departurePort) {
hits++;
}
runCount++;
initialized = true;
}
time_t arr, dep; time_t arr, dep;
dep = flight->getDepartureTime(); dep = flight->getDepartureTime();
@ -481,12 +496,25 @@ double FGAISchedule::getSpeed()
SG_CLAMP_RANGE(speed, 300.0, 500.0); SG_CLAMP_RANGE(speed, 300.0, 500.0);
return speed; return speed;
} }
/*
void FGAISchedule::setScore ()
{
if (runCount) {
score = ((double) hits / (double) runCount);
} else {
if (homePort == fgGetString("/sim/presets/airport-id")) {
score = 0.1;
} else {
score = 0.0;
}
}
}
bool compareSchedules(FGAISchedule*a, FGAISchedule*b) bool compareSchedules(FGAISchedule*a, FGAISchedule*b)
{ {
//return (*a) < (*b); return (*a) < (*b);
} }
*/
// void FGAISchedule::setClosestDistanceToUser() // void FGAISchedule::setClosestDistanceToUser()
// { // {

View file

@ -53,9 +53,12 @@ class FGAISchedule
double groundOffset; double groundOffset;
double distanceToUser; double distanceToUser;
int AIManagerRef; int AIManagerRef;
//int score; double score;
unsigned int runCount;
unsigned int hits;
bool firstRun; bool firstRun;
double courseToDest; double courseToDest;
bool initialized;
void scheduleFlights(); void scheduleFlights();
@ -107,10 +110,17 @@ class FGAISchedule
const string& getFlightRules () { return (*flights.begin())->getFlightRules (); }; const string& getFlightRules () { return (*flights.begin())->getFlightRules (); };
bool getHeavy () { return heavy; }; bool getHeavy () { return heavy; };
double getCourse () { return courseToDest; }; double getCourse () { return courseToDest; };
unsigned int getRunCount () { return runCount; };
unsigned int getHits () { return hits; };
void setrunCount(unsigned int count) { runCount = count; };
void setHits (unsigned int count) { hits = count; };
void setScore ();
double getScore () { return score; };
FGScheduledFlight*findAvailableFlight (const string &currentDestination, const string &req); FGScheduledFlight*findAvailableFlight (const string &currentDestination, const string &req);
// used to sort in decending order of score: I've probably found a better way to // used to sort in decending order of score: I've probably found a better way to
// decending order sorting, but still need to test that. // decending order sorting, but still need to test that.
//bool operator< (const FGAISchedule &other) const { return (score > other.score); }; bool operator< (const FGAISchedule &other) const { return (score > other.score); };
//void * getAiRef () { return AIManagerRef; }; //void * getAiRef () { return AIManagerRef; };
//FGAISchedule* getAddress () { return this;}; //FGAISchedule* getAddress () { return this;};

View file

@ -85,10 +85,39 @@ FGTrafficManager::FGTrafficManager()
FGTrafficManager:: ~FGTrafficManager() FGTrafficManager:: ~FGTrafficManager()
{ {
for (ScheduleVectorIterator sched = scheduledAircraft.begin(); sched != scheduledAircraft.end(); sched++) // Save the heuristics data
{ bool saveData = false;
ofstream cachefile;
if (fgGetBool("/sim/traffic-manager/heuristics")) {
SGPath cacheData(fgGetString("/sim/fg-home"));
cacheData.append("ai");
string airport = fgGetString("/sim/presets/airport-id");
if ((airport) != "") {
char buffer[128];
::snprintf(buffer, 128, "%c/%c/%c/",
airport[0], airport[1], airport[2]);
cacheData.append(buffer);
if (!cacheData.exists()) {
cacheData.create_dir(0777);
}
cacheData.append(airport + "-cache.txt");
//cerr << "Saving AI traffic heuristics" << endl;
saveData = true;
cachefile.open(cacheData.str().c_str());
}
}
for (ScheduleVectorIterator sched = scheduledAircraft.begin(); sched != scheduledAircraft.end(); sched++) {
if (saveData) {
cachefile << (*sched)->getRegistration() << " "
<< (*sched)-> getRunCount() << " "
<< (*sched)->getHits() << endl;
}
delete (*sched); delete (*sched);
} }
if (saveData) {
cachefile.close();
}
scheduledAircraft.clear(); scheduledAircraft.clear();
flights.clear(); flights.clear();
} }
@ -99,9 +128,11 @@ void FGTrafficManager::init()
ulDir* d, *d2; ulDir* d, *d2;
ulDirEnt* dent, *dent2; ulDirEnt* dent, *dent2;
SGPath aircraftDir = globals->get_fg_root(); SGPath aircraftDir = globals->get_fg_root();
SGPath path = aircraftDir; SGPath path = aircraftDir;
heuristicsVector heuristics;
HeuristicMap heurMap;
aircraftDir.append("AI/Traffic"); aircraftDir.append("AI/Traffic");
if ((d = ulOpenDir(aircraftDir.c_str())) != NULL) if ((d = ulOpenDir(aircraftDir.c_str())) != NULL)
{ {
@ -130,7 +161,53 @@ void FGTrafficManager::init()
} }
ulCloseDir(d); ulCloseDir(d);
} }
if (fgGetBool("/sim/traffic-manager/heuristics")) {
//cerr << "Processing Heuristics" << endl;
// Load the heuristics data
SGPath cacheData(fgGetString("/sim/fg-home"));
cacheData.append("ai");
string airport = fgGetString("/sim/presets/airport-id");
if ((airport) != "") {
char buffer[128];
::snprintf(buffer, 128, "%c/%c/%c/",
airport[0], airport[1], airport[2]);
cacheData.append(buffer);
cacheData.append(airport + "-cache.txt");
if (cacheData.exists()) {
ifstream data(cacheData.c_str());
while (1) {
Heuristic *h = new Heuristic;
data >> h->registration >> h->runCount >> h->hits;
if (data.eof())
break;
heurMap[h->registration] = h;
heuristics.push_back(h);
}
}
}
for (currAircraft = scheduledAircraft.begin();
currAircraft != scheduledAircraft.end();
currAircraft++) {
string registration = (*currAircraft)->getRegistration();
HeuristicMapIterator itr = heurMap.find(registration);
//cerr << "Processing heuristics for" << (*currAircraft)->getRegistration() << endl;
if (itr == heurMap.end()) {
//cerr << "No heuristics found for " << registration << endl;
} else {
(*currAircraft)->setrunCount(itr->second->runCount);
(*currAircraft)->setHits (itr->second->hits);
(*currAircraft)->setScore();
//cerr <<"Runcount " << itr->second->runCount << ".Hits " << itr->second->hits << endl;
}
}
//cerr << "Done" << endl;
for (heuristicsVectorIterator hvi = heuristics.begin();
hvi != heuristics.end();
hvi++) {
delete (*hvi);
}
sort (scheduledAircraft.begin(), scheduledAircraft.end(), compareSchedules);
}
currAircraft = scheduledAircraft.begin(); currAircraft = scheduledAircraft.begin();
currAircraftClosest = scheduledAircraft.begin(); currAircraftClosest = scheduledAircraft.begin();
} }
@ -153,6 +230,7 @@ void FGTrafficManager::update(double /*dt*/)
{ {
currAircraft = scheduledAircraft.begin(); currAircraft = scheduledAircraft.begin();
} }
//cerr << "Processing << " << (*currAircraft)->getRegistration() << " with score " << (*currAircraft)->getScore() << endl;
if (!((*currAircraft)->update(now, userCart))) if (!((*currAircraft)->update(now, userCart)))
{ {
// NOTE: With traffic manager II, this statement below is no longer true // NOTE: With traffic manager II, this statement below is no longer true

View file

@ -57,6 +57,22 @@
typedef vector<int> IdList; typedef vector<int> IdList;
typedef vector<int>::iterator IdListIterator; typedef vector<int>::iterator IdListIterator;
class Heuristic
{
public:
string registration;
unsigned int runCount;
unsigned int hits;
};
typedef vector<Heuristic*> heuristicsVector;
typedef vector<Heuristic*>::iterator heuristicsVectorIterator;
typedef std::map < std::string, Heuristic *> HeuristicMap;
typedef HeuristicMap::iterator HeuristicMapIterator;
class FGTrafficManager : public SGSubsystem, public XMLVisitor class FGTrafficManager : public SGSubsystem, public XMLVisitor
{ {