Merge branch 'next' of git://gitorious.org/fg/flightgear into next
This commit is contained in:
commit
a2ffbba23e
16 changed files with 2482 additions and 1982 deletions
|
@ -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;
|
||||||
|
@ -89,8 +90,8 @@ void FGAIBallistic::readFromScenario(SGPropertyNode* scFileNode) {
|
||||||
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));
|
||||||
|
@ -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) {
|
||||||
|
@ -143,8 +144,13 @@ 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());
|
||||||
|
|
||||||
|
if (_slave_to_ac){
|
||||||
props->setStringValue("force/path", _force_path.c_str());
|
props->setStringValue("force/path", _force_path.c_str());
|
||||||
|
props->setStringValue("contents/path", _contents_path.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
//props->setStringValue("vector/path", _vector_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
|
||||||
|
@ -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,11 +172,10 @@ 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",
|
||||||
|
@ -179,7 +186,7 @@ void FGAIBallistic::bind() {
|
||||||
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",
|
||||||
|
@ -195,7 +202,7 @@ 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",
|
||||||
|
@ -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,18 +271,16 @@ 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();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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,8 +484,9 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -553,19 +610,39 @@ 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();
|
||||||
|
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());
|
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) {
|
||||||
|
@ -574,7 +651,7 @@ void FGAIBallistic::Run(double 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
|
||||||
|
@ -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,
|
||||||
|
@ -661,6 +739,7 @@ void FGAIBallistic::Run(double dt) {
|
||||||
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();
|
||||||
|
@ -673,7 +752,7 @@ void FGAIBallistic::Run(double dt) {
|
||||||
|
|
||||||
//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){
|
||||||
|
@ -754,18 +833,22 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -779,6 +862,8 @@ void FGAIBallistic::Run(double 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;
|
||||||
|
@ -795,8 +880,6 @@ 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;
|
||||||
|
@ -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) {
|
||||||
|
@ -865,10 +950,11 @@ void FGAIBallistic::handle_expiry() {
|
||||||
report_impact(pos.getElevationM());
|
report_impact(pos.getElevationM());
|
||||||
_expiry_reported = true;
|
_expiry_reported = true;
|
||||||
|
|
||||||
//if (life == -1){
|
if (life == -1){
|
||||||
// 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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -878,7 +964,6 @@ void FGAIBallistic::handle_collision()
|
||||||
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
|
||||||
|
@ -953,11 +1038,16 @@ 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 {
|
||||||
|
@ -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,7 +1082,7 @@ 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;
|
||||||
}
|
}
|
||||||
|
@ -1036,7 +1091,7 @@ 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,8 +1137,11 @@ 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
|
||||||
|
@ -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
|
||||||
|
|
|
@ -74,25 +74,26 @@ public:
|
||||||
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;
|
||||||
|
|
||||||
|
@ -163,6 +164,7 @@ 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
|
||||||
|
@ -170,17 +172,27 @@ private:
|
||||||
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;
|
||||||
|
|
||||||
|
@ -191,13 +203,17 @@ private:
|
||||||
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;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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),
|
||||||
|
|
|
@ -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()) {
|
||||||
|
|
|
@ -70,7 +70,7 @@ void FGAIMultiplayer::bind() {
|
||||||
FGAIBase::bind();
|
FGAIBase::bind();
|
||||||
|
|
||||||
props->tie("refuel/contact", SGRawValuePointer<bool>(&contact));
|
props->tie("refuel/contact", SGRawValuePointer<bool>(&contact));
|
||||||
props->setBoolValue("tanker",isTanker);
|
props->tie("tanker", SGRawValuePointer<bool>(&isTanker));
|
||||||
|
|
||||||
props->tie("controls/invisible",
|
props->tie("controls/invisible",
|
||||||
SGRawValuePointer<bool>(&invisible));
|
SGRawValuePointer<bool>(&invisible));
|
||||||
|
@ -460,16 +460,20 @@ void FGAIMultiplayer::update(double dt)
|
||||||
|
|
||||||
|
|
||||||
if ( isTanker) {
|
if ( isTanker) {
|
||||||
|
//cout << "IS tanker ";
|
||||||
if ( (range_ft2 < 250.0 * 250.0) &&
|
if ( (range_ft2 < 250.0 * 250.0) &&
|
||||||
(y_shift > 0.0) &&
|
(y_shift > 0.0) &&
|
||||||
(elevation > 0.0) ){
|
(elevation > 0.0) ){
|
||||||
// refuel_node->setBoolValue(true);
|
// refuel_node->setBoolValue(true);
|
||||||
|
//cout << "in contact" << endl;
|
||||||
contact = true;
|
contact = true;
|
||||||
} else {
|
} else {
|
||||||
// refuel_node->setBoolValue(false);
|
// refuel_node->setBoolValue(false);
|
||||||
|
//cout << "not in contact" << endl;
|
||||||
contact = false;
|
contact = false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
//cout << "NOT tanker " << endl;
|
||||||
contact = false;
|
contact = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -28,12 +28,11 @@ 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;
|
||||||
|
@ -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();
|
loadAI();
|
||||||
|
|
||||||
while (_found_sub)
|
while (_found_sub)
|
||||||
loadSubmodels();
|
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()
|
||||||
|
@ -117,16 +124,28 @@ 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
|
||||||
|
@ -149,8 +168,10 @@ void FGSubmodelMgr::update(double dt)
|
||||||
(*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,27 +183,26 @@ 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) {
|
||||||
|
@ -190,11 +210,12 @@ void FGSubmodelMgr::update(double dt)
|
||||||
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
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -237,6 +265,7 @@ 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->setSlaved(sm->slaved);
|
||||||
ballist->setRandom(sm->random);
|
ballist->setRandom(sm->random);
|
||||||
ballist->setRandomness(sm->randomness);
|
ballist->setRandomness(sm->randomness);
|
||||||
ballist->setLatitude(offsetpos.getLatitudeDeg());
|
ballist->setLatitude(offsetpos.getLatitudeDeg());
|
||||||
|
@ -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,14 +340,14 @@ 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;
|
||||||
|
|
||||||
|
@ -318,6 +355,7 @@ void FGSubmodelMgr::transform(submodel *sm)
|
||||||
|
|
||||||
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,44 +385,28 @@ 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;
|
//cout << "Submodel: setting IC "<< name << endl;
|
||||||
IC.lat = (*sm_list_itr)->_getLatitude();
|
//cout << "heading " << IC.azimuth << endl ;
|
||||||
IC.lon = (*sm_list_itr)->_getLongitude();
|
//cout << "speed down " << IC.speed_down_fps << endl ;
|
||||||
IC.alt = (*sm_list_itr)->_getAltitude();
|
//cout << "speed east " << IC.speed_east_fps << endl ;
|
||||||
IC.roll = (*sm_list_itr)->_getRoll();
|
//cout << "speed north " << IC.speed_north_fps << endl ;
|
||||||
IC.elevation = (*sm_list_itr)->_getPitch();
|
//cout << "parent speed fps in " << IC.speed << "sm speed in " << sm->speed << endl ;
|
||||||
IC.azimuth = (*sm_list_itr)->_getHeading();
|
//cout << "lat " << IC.lat;
|
||||||
IC.alt = (*sm_list_itr)->_getAltitude();
|
//cout << "alt " << IC.alt << endl ;
|
||||||
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 << "speed down " << IC.speed_down_fps << endl ;
|
|
||||||
cout << "speed east " << IC.speed_east_fps << endl ;
|
|
||||||
cout << "speed north " << IC.speed_north_fps << endl ;
|
|
||||||
cout << "parent speed fps in" << IC.speed << "sm speed in " << sm->speed << 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();
|
||||||
|
|
||||||
|
//cout << "wind e " << IC.wind_from_east << " n " << IC.wind_from_north << endl;
|
||||||
|
|
||||||
userpos.setLatitudeDeg(IC.lat);
|
userpos.setLatitudeDeg(IC.lat);
|
||||||
userpos.setLongitudeDeg(IC.lon);
|
userpos.setLongitudeDeg(IC.lon);
|
||||||
userpos.setElevationFt(IC.alt);
|
userpos.setElevationFt(IC.alt);
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -535,7 +562,7 @@ void FGSubmodelMgr::setData(int id, string& path, bool serviceable)
|
||||||
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);
|
||||||
|
@ -543,8 +570,6 @@ void FGSubmodelMgr::setData(int id, string& path, bool serviceable)
|
||||||
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();
|
||||||
|
|
||||||
|
@ -573,12 +598,12 @@ void FGSubmodelMgr::setData(int id, string& path, bool serviceable)
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
@ -645,7 +670,7 @@ void FGSubmodelMgr::setSubData(int id, string& path, bool serviceable)
|
||||||
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);
|
||||||
|
@ -653,7 +678,6 @@ void FGSubmodelMgr::setSubData(int id, string& path, bool serviceable)
|
||||||
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();
|
||||||
|
|
||||||
|
@ -681,11 +705,13 @@ void FGSubmodelMgr::setSubData(int id, string& path, bool serviceable)
|
||||||
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;
|
||||||
|
@ -713,10 +739,10 @@ void FGSubmodelMgr::loadSubmodels()
|
||||||
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;
|
||||||
|
@ -731,6 +757,7 @@ void FGSubmodelMgr::loadSubmodels()
|
||||||
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
|
||||||
|
@ -739,14 +766,19 @@ void FGSubmodelMgr::loadSubmodels()
|
||||||
|
|
||||||
//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,7 +786,6 @@ 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
|
||||||
|
@ -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
|
||||||
|
|
|
@ -25,7 +25,7 @@ using std::list;
|
||||||
|
|
||||||
class FGAIBase;
|
class FGAIBase;
|
||||||
|
|
||||||
class FGSubmodelMgr : public SGSubsystem
|
class FGSubmodelMgr : public SGSubsystem, public SGPropertyChangeListener
|
||||||
{
|
{
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -58,6 +58,7 @@ public:
|
||||||
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;
|
||||||
|
@ -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,6 +146,8 @@ private:
|
||||||
double _parent_pitch;
|
double _parent_pitch;
|
||||||
double _parent_roll;
|
double _parent_roll;
|
||||||
double _parent_speed;
|
double _parent_speed;
|
||||||
|
double _parent_ID;
|
||||||
|
|
||||||
double _x_offset;
|
double _x_offset;
|
||||||
double _y_offset;
|
double _y_offset;
|
||||||
double _z_offset;
|
double _z_offset;
|
||||||
|
@ -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,6 +204,7 @@ 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);
|
||||||
|
|
||||||
|
|
|
@ -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_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() );
|
// _environment->get_wind_speed_kt() );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FGEnvironment
|
FGEnvironment
|
||||||
|
|
|
@ -160,6 +160,8 @@ FGMultiplayMgr::sIdPropertyList[] = {
|
||||||
|
|
||||||
{1200, "environment/wildfire/data", simgear::props::STRING},
|
{1200, "environment/wildfire/data", simgear::props::STRING},
|
||||||
|
|
||||||
|
{1300, "tanker", simgear::props::INT},
|
||||||
|
|
||||||
{10001, "sim/multiplay/transmission-freq-hz", simgear::props::STRING},
|
{10001, "sim/multiplay/transmission-freq-hz", simgear::props::STRING},
|
||||||
{10002, "sim/multiplay/chat", simgear::props::STRING},
|
{10002, "sim/multiplay/chat", simgear::props::STRING},
|
||||||
|
|
||||||
|
|
|
@ -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()
|
||||||
// {
|
// {
|
||||||
|
|
|
@ -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 ¤tDestination, const string &req);
|
FGScheduledFlight*findAvailableFlight (const string ¤tDestination, 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;};
|
||||||
|
|
||||||
|
|
|
@ -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,8 +128,10 @@ 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
|
||||||
|
|
|
@ -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
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue