#include "AIBallistic.hxx"
#include <Main/util.hxx>
+#include <Environment/gravity.hxx>
using namespace simgear;
const double FGAIBallistic::slugs_to_lbs = 32.1740485564;
FGAIBallistic::FGAIBallistic(object_type ot) :
-FGAIBase(ot),
+FGAIBase(ot, false),
_height(0.0),
+_speed(0),
_ht_agl_ft(0.0),
_azimuth(0.0),
_elevation(0.0),
_rotation(0.0),
+hs(0),
_elapsed_time(0),
_aero_stabilised(false),
_drag_area(0.007),
_life_timer(0.0),
-_gravity(32.1740485564),
_buoyancy(0),
_wind(true),
_mass(0),
_external_force(false),
_report_expiry(false),
_impact_report_node(fgGetNode("/ai/models/model-impact", true)),
-hs(0),
-_old_height(0),
-_speed(0)
+_old_height(0)
{
no_roll = false;
bool FGAIBallistic::init(bool search_in_AI_path) {
FGAIBase::init(search_in_AI_path);
+ reinit();
+ return true;
+}
+void FGAIBallistic::reinit() {
_impact_reported = false;
_collision_reported = false;
_expiry_reported = false;
_elapsed_time += (sg_random() * 100);
+ _life_timer = 0;
+
props->setStringValue("material/name", "");
props->setStringValue("name", _name.c_str());
props->setStringValue("submodels/path", _path.c_str());
props->setStringValue("contents/path", _contents_path.c_str());
}
- if(_parent != ""){
- setParentNode();
- }
+ //cout << "init: name " << _name.c_str() << " _life_timer " << _life_timer
+ // << endl;
- setParentNodes(_selected_ac);
+ //if(_parent != ""){
+ // setParentNode();
+ //}
+
+ //setParentNodes(_selected_ac);
//props->setStringValue("vector/path", _vector_path.c_str());
Transform();
- //cout << _name << " speed init: " << speed << endl;
+ if(_parent != ""){
+ setParentNode();
+ }
- return true;
+ setParentNodes(_selected_ac);
+
+ FGAIBase::reinit();
}
void FGAIBallistic::bind() {
// FGAIBase::bind();
- props->tie("sim/time/elapsed-sec",
+ _tiedProperties.setRoot(props);
+ tie("sim/time/elapsed-sec",
SGRawValueMethods<FGAIBallistic,double>(*this,
- &FGAIBallistic::_getTime));
- //props->tie("mass-slug",
+ &FGAIBallistic::_getTime, &FGAIBallistic::setTime));
+ //tie("mass-slug",
// SGRawValueMethods<FGAIBallistic,double>(*this,
// &FGAIBallistic::getMass));
- props->tie("material/solid",
+ tie("material/solid",
SGRawValuePointer<bool>(&_solid));
- props->tie("altitude-agl-ft",
+ tie("altitude-agl-ft",
SGRawValuePointer<double>(&_ht_agl_ft));
- props->tie("controls/slave-to-ac",
+ tie("controls/slave-to-ac",
SGRawValueMethods<FGAIBallistic,bool>
(*this, &FGAIBallistic::getSlaved, &FGAIBallistic::setSlaved));
- props->tie("controls/invisible",
+ tie("controls/invisible",
SGRawValuePointer<bool>(&invisible));
if(_external_force || _slave_to_ac){
- props->tie("controls/force_stabilized",
+ tie("controls/force_stabilized",
SGRawValuePointer<bool>(&_force_stabilised));
- props->tie("position/global-x",
+ tie("position/global-x",
SGRawValueMethods<FGAIBase,double>(*this, &FGAIBase::_getCartPosX, 0));
- props->tie("position/global-y",
+ tie("position/global-y",
SGRawValueMethods<FGAIBase,double>(*this, &FGAIBase::_getCartPosY, 0));
- props->tie("position/global-z",
+ tie("position/global-z",
SGRawValueMethods<FGAIBase,double>(*this, &FGAIBase::_getCartPosZ, 0));
- props->tie("velocities/vertical-speed-fps",
+ tie("velocities/vertical-speed-fps",
SGRawValuePointer<double>(&vs));
- props->tie("velocities/true-airspeed-kt",
+ tie("velocities/true-airspeed-kt",
SGRawValuePointer<double>(&speed));
- props->tie("velocities/horizontal-speed-fps",
+ tie("velocities/horizontal-speed-fps",
SGRawValuePointer<double>(&hs));
- props->tie("position/altitude-ft",
+ tie("position/altitude-ft",
SGRawValueMethods<FGAIBase,double>(*this, &FGAIBase::_getElevationFt, &FGAIBase::_setAltitude));
- props->tie("position/latitude-deg",
+ tie("position/latitude-deg",
SGRawValueMethods<FGAIBase,double>(*this, &FGAIBase::_getLatitude, &FGAIBase::_setLatitude));
- props->tie("position/longitude-deg",
+ tie("position/longitude-deg",
SGRawValueMethods<FGAIBase,double>(*this, &FGAIBase::_getLongitude, &FGAIBase::_setLongitude));
- props->tie("orientation/hdg-deg",
+ tie("orientation/hdg-deg",
SGRawValuePointer<double>(&hdg));
- props->tie("orientation/pitch-deg",
+ tie("orientation/pitch-deg",
SGRawValuePointer<double>(&pitch));
- props->tie("orientation/roll-deg",
+ tie("orientation/roll-deg",
SGRawValuePointer<double>(&roll));
- props->tie("controls/slave-load-to-ac",
+ tie("controls/slave-load-to-ac",
SGRawValueMethods<FGAIBallistic,bool>
(*this, &FGAIBallistic::getSlavedLoad, &FGAIBallistic::setSlavedLoad));
- props->tie("position/load-offset",
+ tie("position/load-offset",
SGRawValueMethods<FGAIBallistic,double>
(*this, &FGAIBallistic::getLoadOffset, &FGAIBallistic::setLoadOffset));
- props->tie("load/distance-to-hitch-ft",
+ tie("load/distance-to-hitch-ft",
SGRawValueMethods<FGAIBallistic,double>
(*this, &FGAIBallistic::getDistanceToHitch));
- props->tie("load/elevation-to-hitch-deg",
+ tie("load/elevation-to-hitch-deg",
SGRawValueMethods<FGAIBallistic,double>
(*this, &FGAIBallistic::getElevToHitch));
- props->tie("load/bearing-to-hitch-deg",
+ tie("load/bearing-to-hitch-deg",
SGRawValueMethods<FGAIBallistic,double>
(*this, &FGAIBallistic::getBearingToHitch));
- props->tie("material/load-resistance",
+ tie("material/load-resistance",
SGRawValuePointer<double>(&_load_resistance));
}
}
-void FGAIBallistic::unbind() {
-// FGAIBase::unbind();
-
- props->untie("sim/time/elapsed-sec");
- props->untie("mass-slug");
- props->untie("material/solid");
- props->untie("altitude-agl-ft");
- props->untie("controls/slave-to-ac");
- props->untie("controls/invisible");
-
- if(_external_force || _slave_to_ac){
- props->untie("position/global-y");
- props->untie("position/global-x");
- props->untie("position/global-z");
- props->untie("velocities/vertical-speed-fps");
- props->untie("velocities/true-airspeed-kt");
- props->untie("velocities/horizontal-speed-fps");
- props->untie("position/altitude-ft");
- props->untie("position/latitude-deg");
- props->untie("position/longitude-deg");
- props->untie("position/ht-agl-ft");
- props->untie("orientation/hdg-deg");
- props->untie("orientation/pitch-deg");
- props->untie("orientation/roll-deg");
- props->untie("controls/force_stabilized");
- props->untie("position/load-offset");
- props->untie("load/distance-to-hitch-ft");
- props->untie("load/elevation-to-hitch-deg");
- props->untie("load/bearing-to-hitch-deg");
- props->untie("material/load-resistance");
- }
-}
-
void FGAIBallistic::update(double dt) {
FGAIBase::update(dt);
_setUserPos();
if (_random){
life = seconds * _randomness + (seconds * (1 -_randomness) * sg_random());
- //cout << "life " << life << endl;
+ //cout << " set life " << life << endl;
} else
life = seconds;
}
int FGAIBallistic::setHdg(double tgt_hdg, double dt, double coeff){
double recip = getRecip(hdg);
double c = dt / (coeff + dt);
+ //cout << "set heading " << tgt_hdg << endl;
//we need to ensure that we turn the short way to the new hdg
if (tgt_hdg < recip && tgt_hdg < hdg && hdg > 180) {
hdg = ((tgt_hdg + 360) * c) + (hdg * (1 - c));
void FGAIBallistic::slaveToAC(double dt){
- double hdg, pch, rll, agl = 0;
+ if (invisible)
+ return;
+
+ double hdg, pch, rll;//, agl = 0;
if (_pnode != 0) {
setParentPos();
hdg = _p_hdg_node->getDoubleValue();
pch = _p_pch_node->getDoubleValue();
rll = _p_rll_node->getDoubleValue();
- agl = _p_agl_node->getDoubleValue();
+// agl = _p_agl_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();
- agl = manager->get_user_agl();
+// agl = manager->get_user_agl();
setOffsetPos(userpos, hdg, pch, rll);
setSpeed(manager->get_user_speed());
}
setPitch(pch + _pitch_offset);
setBank(rll + _roll_offset);
setOffsetVelocity(dt, pos);
+ setTime(0);
//update the mass (slugs)
_mass = (_weight_lb + getContents()) / slugs_to_lbs;
void FGAIBallistic::Run(double dt) {
_life_timer += dt;
+
+ //_pass += 1;
+ //cout<<"AIBallistic run: name " << _name.c_str()
+ // << " dt " << dt << " _life_timer " << _life_timer << " pass " << _pass << endl;
// if life = -1 the object does not die
if (_life_timer > life && life != -1){
if (_report_expiry && !_expiry_reported && !_impact_reported && !_collision_reported){
- //cout<<"AIBallistic: expiry"<< endl;
+ //cout<<"AIBallistic run: name " << _name.c_str() << " expiry "
+ //<< " _life_timer " << _life_timer<< endl;
handle_expiry();
- } else
+ } else{
+ //cout<<"AIBallistic run: name " << _name.c_str()
+ // << " die " << " _life_timer " << _life_timer << endl;
setDie(true);
+ }
+ setTime(0);
}
//set the contents in the appropriate tank or other property in the parent to zero
if ( speed < 0.0 )
speed = 0.0;
- double speed_fps = speed * SG_KT_TO_FPS;
- //double hs;
+// double speed_fps = speed * SG_KT_TO_FPS;
// calculate vertical and horizontal speed components
- 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;
- }
+ calcVSHS();
//resolve horizontal speed into north and east components:
- double speed_north_fps = cos(_azimuth / SG_RADIANS_TO_DEGREES) * hs;
- double speed_east_fps = sin(_azimuth / SG_RADIANS_TO_DEGREES) * hs;
-
- // convert horizontal speed (fps) to degrees per second
- double speed_north_deg_sec = speed_north_fps / ft_per_deg_lat;
- double speed_east_deg_sec = speed_east_fps / ft_per_deg_lon;
+ //and convert horizontal speed (fps) to degrees per second
+ calcNE();
// if wind not required, set to zero
if (!_wind) {
double friction_force_speed_north_deg_sec = 0;
double friction_force_speed_east_deg_sec = 0;
double force_elevation_deg = 0;
+ double force_azimuth_deg = 0;
+ double force_lbs = 0;
if (_external_force) {
- //cout << _name << " external force" << endl;
+ //cout << _name << " external force " << hdg << " az " << _azimuth << endl;
SGPropertyNode *n = fgGetNode(_force_path.c_str(), true);
- double force_lbs = n->getChild("force-lb", 0, true)->getDoubleValue();
- force_elevation_deg = n->getChild("force-elevation-deg", 0, true)->getDoubleValue();
- double force_azimuth_deg = n->getChild("force-azimuth-deg", 0, true)->getDoubleValue();
+ force_lbs = n->getChild("force-lb", 0, true)->getDoubleValue();
+ force_elevation_deg = n->getChild("force-elevation-deg", 0, true)->getDoubleValue();
+ force_azimuth_deg = n->getChild("force-azimuth-deg", 0, true)->getDoubleValue();
//resolve force into vertical and horizontal components:
double v_force_lbs = force_lbs * sin( force_elevation_deg * SG_DEGREES_TO_RADIANS );
h_force_lbs = force_lbs * cos( force_elevation_deg * SG_DEGREES_TO_RADIANS );
//ground interaction
+ //we don't do this if impacts are calculated
+ if(!_report_impact){
- if (getHtAGL(10000)){
- double deadzone = 0.1;
+ if (getHtAGL(10000)){
+ double deadzone = 0.1;
- if (_ht_agl_ft <= (0 + _ground_offset + deadzone) && _solid){
- normal_force_lbs = (_mass * slugs_to_lbs) - v_force_lbs;
+ if (_ht_agl_ft <= (0 + _ground_offset + deadzone) && _solid){
+ normal_force_lbs = (_mass * slugs_to_lbs) - v_force_lbs;
- if ( normal_force_lbs < 0 )
- normal_force_lbs = 0;
+ if ( normal_force_lbs < 0 )
+ normal_force_lbs = 0;
- pos.setElevationFt(0 + _ground_offset);
- if (vs < 0)
- vs = -vs * 0.5;
+ pos.setElevationFt(0 + _ground_offset);
+ if (vs < 0)
+ vs = -vs * 0.5;
+
+ // calculate friction
+ // we assume a static Coefficient of Friction (mu) of 0.62 (wood on concrete)
+ double mu = 0.62;
- // calculate friction
- // we assume a static Coefficient of Friction (mu) of 0.62 (wood on concrete)
- double mu = 0.62;
+ static_friction_force_lbs = mu * normal_force_lbs * _frictionFactor;
- static_friction_force_lbs = mu * normal_force_lbs * _frictionFactor;
+ //adjust horizontal force. We assume that a speed of <= 5 fps is static
+ if (h_force_lbs <= static_friction_force_lbs && hs <= 5){
+ h_force_lbs = hs = 0;
+ _speed_north_fps = _speed_east_fps = 0;
+ } else
+ dynamic_friction_force_lbs = (static_friction_force_lbs * 0.95);
- //adjust horizontal force. We assume that a speed of <= 5 fps is static
- if (h_force_lbs <= static_friction_force_lbs && hs <= 5){
- h_force_lbs = hs = 0;
- speed_north_fps = speed_east_fps = 0;
- } else
- dynamic_friction_force_lbs = (static_friction_force_lbs * 0.95);
+ //ignore wind when on the ground for now
+ //TODO fix this
+ _wind_from_north = 0;
+ _wind_from_east = 0;
- //ignore wind when on the ground for now
- //TODO fix this
- _wind_from_north = 0;
- _wind_from_east = 0;
+ }
}
- }
+ } //endif
//acceleration = (force(lbsf)/mass(slugs))
v_force_acc_fpss = v_force_lbs/_mass;
double wind_speed_from_east_deg_sec = _wind_from_east / ft_per_deg_lon;
//recombine the horizontal velocity components
- hs = sqrt(((speed_north_fps + force_speed_north_fps + friction_force_speed_north_fps)
- * (speed_north_fps + force_speed_north_fps + friction_force_speed_north_fps))
- + ((speed_east_fps + force_speed_east_fps + friction_force_speed_east_fps)
- * (speed_east_fps + force_speed_east_fps + friction_force_speed_east_fps)));
+ hs = sqrt(((_speed_north_fps + force_speed_north_fps + friction_force_speed_north_fps)
+ * (_speed_north_fps + force_speed_north_fps + friction_force_speed_north_fps))
+ + ((_speed_east_fps + force_speed_east_fps + friction_force_speed_east_fps)
+ * (_speed_east_fps + force_speed_east_fps + friction_force_speed_east_fps)));
if (hs <= 0.00001)
hs = 0;
// adjust vertical speed for acceleration of gravity, buoyancy, and vertical force
- vs -= (_gravity - _buoyancy - v_force_acc_fpss - normal_force_fpss) * dt;
+ double gravity = SG_METER_TO_FEET * (Environment::Gravity::instance()->getGravity(pos));
+ vs -= (gravity - _buoyancy - v_force_acc_fpss - normal_force_fpss) * dt;
if (vs <= 0.00001 && vs >= -0.00001)
vs = 0;
// recalculate elevation and azimuth (velocity vectors)
_elevation = atan2( vs, hs ) * SG_RADIANS_TO_DEGREES;
- _azimuth = atan2((speed_east_fps + force_speed_east_fps + friction_force_speed_east_fps),
- (speed_north_fps + force_speed_north_fps + friction_force_speed_north_fps))
+ _azimuth = atan2((_speed_east_fps + force_speed_east_fps + friction_force_speed_east_fps),
+ (_speed_north_fps + force_speed_north_fps + friction_force_speed_north_fps))
* SG_RADIANS_TO_DEGREES;
// rationalise azimuth
_azimuth += 360;
if (_aero_stabilised) { // we simulate rotational moment of inertia by using a filter
- //cout<< "_aero_stabilised "<< endl;
+ //cout<< "_aero_stabilised " << hdg << " az " << _azimuth << endl;
const double coeff = 0.9;
// we assume a symetrical MI about the pitch and yaw axis
return _life_timer;
}
+void FGAIBallistic::setTime(double s){
+ _life_timer = s;
+}
+
void FGAIBallistic::handle_impact() {
// try terrain intersection
- double start = pos.getElevationM() + 10;
+ double start = pos.getElevationM() + 100;
if(!getHtAGL(start))
return;
if (_ht_agl_ft <= 0) {
- SG_LOG(SG_GENERAL, SG_DEBUG, "AIBallistic: terrain impact");
+ SG_LOG(SG_AI, SG_DEBUG, "AIBallistic: terrain impact material" << _mat_name);
report_impact(_elevation_m);
_impact_reported = true;
void FGAIBallistic::handle_expiry() {
- SG_LOG(SG_GENERAL, SG_DEBUG, "AIBallistic: handle_expiry " << pos.getElevationM());
+ //SG_LOG(SG_AI, SG_DEBUG, "AIBallistic: handle_expiry " << pos.getElevationM());
report_impact(pos.getElevationM());
_expiry_reported = true;
else
n->setStringValue("type", "terrain");
- SG_LOG(SG_GENERAL, SG_DEBUG, "AIBallistic: object impact" << _name << " lon " <<_impact_lon);
+ SG_LOG(SG_AI, SG_DEBUG, "AIBallistic: object impact " << _name
+ << " lon " <<_impact_lon << " lat " <<_impact_lat << " sec " << _life_timer);
n->setDoubleValue("longitude-deg", _impact_lon);
n->setDoubleValue("latitude-deg", _impact_lat);
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;
+ //don't do this if speed is low
+ //cout << "speed " << speed << endl;
+ if (speed > 0.1){
+ double az1, az2, dist;
+ geo_inverse_wgs_84(_oldoffsetpos, offsetpos, &az1, &az2, &dist);
+ _azimuth = az1;
+ //cout << "offset az " << _azimuth << endl;
+ } else {
+ _azimuth = hdg;
+ //cout << " slow offset az " << _azimuth << endl;
+ }
//resolve horizontal speed into north and east components:
calcNE();