diff --git a/src/AIModel/AIBallistic.cxx b/src/AIModel/AIBallistic.cxx index 2ed0b6913..4cd14b43a 100644 --- a/src/AIModel/AIBallistic.cxx +++ b/src/AIModel/AIBallistic.cxx @@ -25,86 +25,133 @@ #include #include +#include #include +#include + +#include #include "AIBallistic.hxx" +SG_USING_STD(vector); + +const double FGAIBallistic::slugs_to_kgs = 14.5939029372; FGAIBallistic::FGAIBallistic() : FGAIBase(otBallistic) { drag_area = 0.007; life_timer = 0.0; gravity = 32; -// buoyancy = 64; + // buoyancy = 64; no_roll = false; aero_stabilised = false; + ht_agl_ft = 0; + impact_data = false; + impact_energy = 0; + impact_speed = 0; + impact_lat = 0; + impact_lon = 0; + impact_elev = 0; + load_resistance = 0; + solid = false; + mat_name = ""; } FGAIBallistic::~FGAIBallistic() { } void FGAIBallistic::readFromScenario(SGPropertyNode* scFileNode) { - if (!scFileNode) - return; + if (!scFileNode) + return; - FGAIBase::readFromScenario(scFileNode); + FGAIBase::readFromScenario(scFileNode); - setAzimuth(scFileNode->getDoubleValue("azimuth", 0.0)); - setElevation(scFileNode->getDoubleValue("elevation", 0.0)); - setDragArea(scFileNode->getDoubleValue("eda", 0.007)); - setLife(scFileNode->getDoubleValue("life", 900.0)); - setBuoyancy(scFileNode->getDoubleValue("buoyancy", 0)); - setWind_from_east(scFileNode->getDoubleValue("wind_from_east", 0)); - setWind_from_north(scFileNode->getDoubleValue("wind_from_north", 0)); - setWind(scFileNode->getBoolValue("wind", false)); - setRoll(scFileNode->getDoubleValue("roll", 0.0)); - setCd(scFileNode->getDoubleValue("cd", 0.029)); - setMass(scFileNode->getDoubleValue("mass", 0.007)); - setStabilisation(scFileNode->getBoolValue("aero_stabilized", false)); - setNoRoll(scFileNode->getBoolValue("no-roll", false)); - setRandom(scFileNode->getBoolValue("random", false)); + setAzimuth(scFileNode->getDoubleValue("azimuth", 0.0)); + setElevation(scFileNode->getDoubleValue("elevation", 0.0)); + setDragArea(scFileNode->getDoubleValue("eda", 0.007)); + setLife(scFileNode->getDoubleValue("life", 900.0)); + setBuoyancy(scFileNode->getDoubleValue("buoyancy", 0)); + setWind_from_east(scFileNode->getDoubleValue("wind_from_east", 0)); + setWind_from_north(scFileNode->getDoubleValue("wind_from_north", 0)); + setWind(scFileNode->getBoolValue("wind", false)); + setRoll(scFileNode->getDoubleValue("roll", 0.0)); + setCd(scFileNode->getDoubleValue("cd", 0.029)); + setMass(scFileNode->getDoubleValue("mass", 0.007)); + setStabilisation(scFileNode->getBoolValue("aero_stabilized", false)); + setNoRoll(scFileNode->getBoolValue("no-roll", false)); + setRandom(scFileNode->getBoolValue("random", false)); + setImpact(scFileNode->getBoolValue("impact", false)); + setName(scFileNode->getStringValue("name", "Bomb")); } bool FGAIBallistic::init(bool search_in_AI_path) { - FGAIBase::init(search_in_AI_path); - hdg = azimuth; - pitch = elevation; - roll = rotation; - Transform(); - return true; + FGAIBase::init(search_in_AI_path); + + props->setStringValue("material/name", mat_name.c_str()); + props->setStringValue("name", name.c_str()); + + hdg = azimuth; + pitch = elevation; + roll = rotation; + Transform(); + return true; } void FGAIBallistic::bind() { -// FGAIBase::bind(); - props->tie("sim/time/elapsed-sec", - SGRawValueMethods(*this, - &FGAIBallistic::_getTime)); + // FGAIBase::bind(); + props->tie("sim/time/elapsed-sec", + SGRawValueMethods(*this, + &FGAIBallistic::_getTime)); + props->tie("material/load-resistance", + SGRawValuePointer(&load_resistance)); + props->tie("material/solid", + SGRawValuePointer(&solid)); + props->tie("altitude-agl-ft", + SGRawValuePointer(&ht_agl_ft)); + props->tie("impact/latitude-deg", + SGRawValuePointer(&impact_lat)); + props->tie("impact/longitude-deg", + SGRawValuePointer(&impact_lon)); + props->tie("impact/elevation-m", + SGRawValuePointer(&impact_elev)); + props->tie("impact/speed-mps", + SGRawValuePointer(&impact_speed)); + props->tie("impact/energy-kJ", + SGRawValuePointer(&impact_energy)); } void FGAIBallistic::unbind() { -// FGAIBase::unbind(); - props->untie("sim/time/elapsed-sec"); + // FGAIBase::unbind(); + props->untie("sim/time/elapsed-sec"); + props->untie("material/load-resistance"); + props->untie("material/solid"); + props->untie("altitude-agl-ft"); + props->untie("impact/latitude-deg"); + props->untie("impact/longitude-deg"); + props->untie("impact/elevation-m"); + props->untie("impact/speed-mps"); + props->untie("impact/energy-kJ"); } void FGAIBallistic::update(double dt) { - FGAIBase::update(dt); - Run(dt); - Transform(); + FGAIBase::update(dt); + Run(dt); + Transform(); } void FGAIBallistic::setAzimuth(double az) { - hdg = azimuth = az; + hdg = azimuth = az; } void FGAIBallistic::setElevation(double el) { - pitch = elevation = el; + pitch = elevation = el; } void FGAIBallistic::setRoll(double rl) { - rotation = rl; + rotation = rl; } void FGAIBallistic::setStabilisation(bool val) { - aero_stabilised = val; + aero_stabilised = val; } void FGAIBallistic::setNoRoll(bool nr) { @@ -112,62 +159,66 @@ void FGAIBallistic::setNoRoll(bool nr) { } void FGAIBallistic::setDragArea(double a) { - drag_area = a; + drag_area = a; } void FGAIBallistic::setLife(double seconds) { - life = seconds; + life = seconds; } void FGAIBallistic::setBuoyancy(double fpss) { - buoyancy = fpss; + buoyancy = fpss; } void FGAIBallistic::setWind_from_east(double fps) { - wind_from_east = fps; + wind_from_east = fps; } void FGAIBallistic::setWind_from_north(double fps) { - wind_from_north = fps; + wind_from_north = fps; } void FGAIBallistic::setWind(bool val) { - wind = val; + wind = val; } void FGAIBallistic::setCd(double c) { - Cd = c; + Cd = c; } void FGAIBallistic::setMass(double m) { - mass = m; + mass = m; } void FGAIBallistic::setRandom(bool r) { random = r; } +void FGAIBallistic::setImpact(bool i) { + impact = i; +} + void FGAIBallistic::setName(const string& n) { name = n; } void FGAIBallistic::Run(double dt) { - life_timer += dt; -// cout << "life timer 1" << life_timer << dt << endl; - if (life_timer > life) setDie(true); + life_timer += dt; + // cout << "life timer 1" << life_timer << dt << endl; + if (life_timer > life) setDie(true); + + double speed_north_deg_sec; + double speed_east_deg_sec; + double wind_speed_from_north_deg_sec; + double wind_speed_from_east_deg_sec; + double Cdm; // Cd adjusted by Mach Number - double speed_north_deg_sec; - double speed_east_deg_sec; - double wind_speed_from_north_deg_sec; - double wind_speed_from_east_deg_sec; - double Cdm; // Cd adjusted by Mach Number - //randomise Cd by +- 5% if (random) Cd = Cd * 0.95 + (0.05 * sg_random()); - // Adjust Cd by Mach number. The equations are based on curves - // for a conventional shell/bullet (no boat-tail). + // Adjust Cd by Mach number. The equations are based on curves + // for a conventional shell/bullet (no boat-tail). if ( Mach < 0.7 ) Cdm = 0.0125 * Mach + Cd; else if ( 0.7 < Mach && Mach < 1.2 ) @@ -176,69 +227,111 @@ void FGAIBallistic::Run(double dt) { Cdm = 0.2965 * pow ( Mach, -1.1506 ) + Cd; //cout << " Mach , " << Mach << " , Cdm , " << Cdm << " ballistic speed kts //"<< speed << endl; - - // drag = Cd * 0.5 * rho * speed * speed * drag_area; - // rho is adjusted for altitude in void FGAIBase::update, - // using Standard Atmosphere (sealevel temperature 15C) - // acceleration = drag/mass; - // adjust speed by drag - speed -= (Cdm * 0.5 * rho * speed * speed * drag_area/mass) * dt; - // don't let speed become negative + // drag = Cd * 0.5 * rho * speed * speed * drag_area; + // rho is adjusted for altitude in void FGAIBase::update, + // using Standard Atmosphere (sealevel temperature 15C) + // acceleration = drag/mass; + // adjust speed by drag + speed -= (Cdm * 0.5 * rho * speed * speed * drag_area/mass) * dt; + + // don't let speed become negative if ( speed < 0.0 ) speed = 0.0; double speed_fps = speed * SG_KT_TO_FPS; - - // calculate vertical and horizontal speed components + + // calculate vertical and horizontal speed components vs = sin( pitch * SG_DEGREES_TO_RADIANS ) * speed_fps; double hs = cos( pitch * SG_DEGREES_TO_RADIANS ) * speed_fps; - // convert horizontal speed (fps) to degrees per second - speed_north_deg_sec = cos(hdg / SG_RADIANS_TO_DEGREES) * hs / ft_per_deg_lat; - speed_east_deg_sec = sin(hdg / SG_RADIANS_TO_DEGREES) * hs / ft_per_deg_lon; - - // if wind not required, set to zero - if (!wind) { - wind_from_north = 0; - wind_from_east = 0; - } - - // convert wind speed (fps) to degrees per second - wind_speed_from_north_deg_sec = wind_from_north / ft_per_deg_lat; - wind_speed_from_east_deg_sec = wind_from_east / ft_per_deg_lon; - - // set new position + // convert horizontal speed (fps) to degrees per second + speed_north_deg_sec = cos(hdg / SG_RADIANS_TO_DEGREES) * hs / ft_per_deg_lat; + speed_east_deg_sec = sin(hdg / SG_RADIANS_TO_DEGREES) * hs / ft_per_deg_lon; + + // if wind not required, set to zero + if (!wind) { + wind_from_north = 0; + wind_from_east = 0; + } + + // convert wind speed (fps) to degrees per second + wind_speed_from_north_deg_sec = wind_from_north / ft_per_deg_lat; + wind_speed_from_east_deg_sec = wind_from_east / ft_per_deg_lon; + + // set new position pos.setLatitudeDeg( pos.getLatitudeDeg() + (speed_north_deg_sec - wind_speed_from_north_deg_sec) * dt ); pos.setLongitudeDeg( pos.getLongitudeDeg() + (speed_east_deg_sec - wind_speed_from_east_deg_sec) * dt ); - // adjust vertical speed for acceleration of gravity and buoyancy - vs -= (gravity - buoyancy) * dt; - - // adjust altitude (feet) - altitude_ft += vs * dt; - pos.setElevationFt(altitude_ft); + // adjust vertical speed for acceleration of gravity and buoyancy + vs -= (gravity - buoyancy) * dt; - // recalculate pitch (velocity vector) if aerostabilized + // adjust altitude (feet) + altitude_ft += vs * dt; + pos.setElevationFt(altitude_ft); + + // recalculate pitch (velocity vector) if aerostabilized /*cout << name << ": " << "aero_stabilised " << aero_stabilised << " pitch " << pitch <<" vs " << vs <get_scenery()->get_elevation_m(pos.getLatitudeDeg(), pos.getLongitudeDeg(), + 10000.0, elevation_m, &material)) + return; + + if (material) { + const vector names = material->get_names(); + + if (!names.empty()) + mat_name = names[0].c_str(); + + solid = material->get_solid(); + load_resistance = material->get_load_resistance(); + props->setStringValue("material/name", mat_name.c_str()); + //cout << "material " << mat_name << " solid " << solid << " load " << load_resistance << endl; + } + + ht_agl_ft = pos.getElevationFt() - elevation_m * SG_METER_TO_FEET; + + // report impact by setting tied variables + if (ht_agl_ft <= 0) { + impact_lat = pos.getLatitudeDeg(); + impact_lon = pos.getLongitudeDeg(); + impact_elev = elevation_m; + impact_speed = speed * SG_KT_TO_MPS; + impact_energy = (mass * slugs_to_kgs) * impact_speed + * impact_speed / (2 * 1000); + + props->setBoolValue("impact/signal", true); // for listeners + impact_data = true; + } } // end AIBallistic + diff --git a/src/AIModel/AIBallistic.hxx b/src/AIModel/AIBallistic.hxx index 6e3e5fbd7..176dd1d16 100644 --- a/src/AIModel/AIBallistic.hxx +++ b/src/AIModel/AIBallistic.hxx @@ -54,10 +54,12 @@ public: void setNoRoll( bool nr ); void setRandom( bool r ); void setName(const string&); + void setImpact(bool i); double _getTime() const; virtual const char* getTypeString(void) const { return "ballistic"; } + static const double slugs_to_kgs; //conversion factor private: @@ -71,13 +73,29 @@ private: double buoyancy; // fps2 double wind_from_east; // fps double wind_from_north; // fps - bool wind; // if true, local wind will be applied to object + bool wind; // if true, local wind will be applied to object double Cd; // drag coefficient double mass; // slugs - bool random; // modifier for Cd + bool random; // modifier for Cd + double ht_agl_ft; // height above ground level + double load_resistance; // ground load resistanc N/m^2 + bool solid; // if true ground is solid for FDMs + bool impact; // if true an impact point on the terrain is calculated + bool impact_data; // if true impact data have been set + + double impact_energy; + double impact_speed; + double impact_lat; + double impact_lon; + double impact_elev; + + string mat_name; string name; void Run(double dt); + void handle_impact(); + + FGAIBase* ai; }; #endif // _FG_AIBALLISTIC_HXX diff --git a/src/AIModel/submodel.cxx b/src/AIModel/submodel.cxx index 2cf28b147..a0b681a80 100644 --- a/src/AIModel/submodel.cxx +++ b/src/AIModel/submodel.cxx @@ -210,6 +210,7 @@ bool FGSubmodelMgr::release(submodel* sm, double dt) ballist->setStabilisation(sm->aero_stabilised); ballist->setNoRoll(sm->no_roll); ballist->setName(sm->name); + ballist->setImpact(sm->impact); ai->attach(ballist); if (sm->count > 0) @@ -487,6 +488,7 @@ void FGSubmodelMgr::setData(int id, string& path, bool serviceable) sm->weight = entry_node->getDoubleValue("weight", 0.25); sm->aero_stabilised = entry_node->getBoolValue("aero-stabilised", true); sm->no_roll = entry_node->getBoolValue("no-roll", false); + sm->impact = entry_node->getBoolValue("impact", false); sm->contents_node = fgGetNode(entry_node->getStringValue("contents", "none"), false); sm->speed_node = fgGetNode(entry_node->getStringValue("speed-node", "none"), false); diff --git a/src/AIModel/submodel.hxx b/src/AIModel/submodel.hxx index 495b0d44d..1f0bf1b47 100644 --- a/src/AIModel/submodel.hxx +++ b/src/AIModel/submodel.hxx @@ -59,6 +59,7 @@ public: int id; bool no_roll; bool serviceable; + bool impact; } submodel; @@ -82,6 +83,7 @@ public: double mass; int id; bool no_roll; + bool impact; } IC_struct;