From 0ece93074f7e29bfe21ac47c66e678711ec2397d Mon Sep 17 00:00:00 2001 From: onox Date: Thu, 21 May 2015 22:45:15 +0200 Subject: [PATCH] submodel: Add random error for azimuth and elevation Signed-off-by: onox --- src/AIModel/AIBallistic.cxx | 44 +++++++++++++++++++++++++++---------- src/AIModel/AIBallistic.hxx | 7 +++++- src/AIModel/submodel.cxx | 39 +++++++++++++++++++++++++++----- src/AIModel/submodel.hxx | 5 ++++- 4 files changed, 76 insertions(+), 19 deletions(-) diff --git a/src/AIModel/AIBallistic.cxx b/src/AIModel/AIBallistic.cxx index d0868bef6..78ed4cdf0 100644 --- a/src/AIModel/AIBallistic.cxx +++ b/src/AIModel/AIBallistic.cxx @@ -48,14 +48,17 @@ _ht_agl_ft(0.0), _azimuth(0.0), _elevation(0.0), _rotation(0.0), +_az_random_error(0.0), +_el_random_error(0.0), hs(0), _elapsed_time(0), _aero_stabilised(false), _drag_area(0.007), _cd(0.029), +_init_cd(0.029), _cd_randomness(0.0), -_life_timer(0.0), _buoyancy(0), +_life_timer(0.0), _wind(true), _mass(0), _random(false), @@ -274,13 +277,24 @@ void FGAIBallistic::update(double dt) void FGAIBallistic::setAzimuth(double az) { if (_random) - hdg = _azimuth = (az - 5 ) + (10 * sg_random()); + hdg = _azimuth = az - _az_random_error + 2 * _az_random_error * sg_random(); else hdg = _azimuth = az; } +void FGAIBallistic::setAzimuthRandomError(double error) { + _az_random_error = error; +} + +void FGAIBallistic::setElevationRandomError(double error) { + _el_random_error = error; +} + void FGAIBallistic::setElevation(double el) { - pitch = _elevation = el; + if (_random) + pitch = _elevation = el - _el_random_error + 2 * _el_random_error * sg_random(); + else + pitch = _elevation = el; } void FGAIBallistic::setRoll(double rl) { @@ -328,6 +342,7 @@ void FGAIBallistic::setWind(bool val) { void FGAIBallistic::setCd(double cd) { _cd = cd; + _init_cd = cd; } void FGAIBallistic::setCdRandomness(double randomness) { @@ -664,23 +679,28 @@ void FGAIBallistic::Run(double dt) { // Set the contents in the appropriate tank or other property in the parent to zero setContents(0); - // Randomize Cd by +- a certain percentage of the ideal Cd - double Cd; - if (_random) - Cd = _cd * (1 - _cd_randomness + 2 * _cd_randomness * sg_random()); - else - Cd = _cd; + if (_random) { + // Keep the new Cd within +- 10% of the current Cd to avoid a fluctuating value + double cd_min = _cd * 0.9; + double cd_max = _cd * 1.1; + + // Randomize Cd by +- a certain percentage of the initial Cd + _cd = _init_cd * (1 - _cd_randomness + 2 * _cd_randomness * sg_random()); + + if (_cd < cd_min) _cd = cd_min; + if (_cd > cd_max) _cd = cd_max; + } // Adjust Cd by Mach number. The equations are based on curves // for a conventional shell/bullet (no boat-tail). double Cdm; if (Mach < 0.7) - Cdm = 0.0125 * Mach + Cd; + Cdm = 0.0125 * Mach + _cd; else if (Mach < 1.2) - Cdm = 0.3742 * pow(Mach, 2) - 0.252 * Mach + 0.0021 + Cd; + Cdm = 0.3742 * pow(Mach, 2) - 0.252 * Mach + 0.0021 + _cd; else - Cdm = 0.2965 * pow(Mach, -1.1506) + Cd; + Cdm = 0.2965 * pow(Mach, -1.1506) + _cd; //cout <<_name << " Mach " << Mach << " Cdm " << Cdm // << " ballistic speed kts "<< speed << endl; diff --git a/src/AIModel/AIBallistic.hxx b/src/AIModel/AIBallistic.hxx index 01f08f87c..5b18a88ea 100644 --- a/src/AIModel/AIBallistic.hxx +++ b/src/AIModel/AIBallistic.hxx @@ -51,6 +51,8 @@ public: void setAzimuth( double az ); void setElevation( double el ); + void setAzimuthRandomError(double error); + void setElevationRandomError(double error); void setRoll( double rl ); void setStabilisation( bool val ); void setDragArea( double a ); @@ -169,11 +171,14 @@ public: private: + double _az_random_error; // maximum azimuth error in degrees + double _el_random_error; // maximum elevation error in degrees bool _aero_stabilised; // if true, object will align with trajectory double _drag_area; // equivalent drag area in ft2 double _buoyancy; // fps^2 bool _wind; // if true, local wind will be applied to object - double _cd; // drag coefficient + double _cd; // current drag coefficient + double _init_cd; // initial drag coefficient double _cd_randomness; // randomness of Cd. 1.0 means +- 100%, 0.0 means no randomness double _life_timer; // seconds double _mass; // slugs diff --git a/src/AIModel/submodel.cxx b/src/AIModel/submodel.cxx index 4e58fcb0c..cb07fd804 100644 --- a/src/AIModel/submodel.cxx +++ b/src/AIModel/submodel.cxx @@ -259,11 +259,13 @@ bool FGSubmodelMgr::release(submodel *sm, double dt) ballist->setName(sm->name); ballist->setSlaved(sm->slaved); ballist->setRandom(sm->random); - ballist->setLifeRandomness(sm->randomness); + ballist->setLifeRandomness(sm->life_randomness->get_value()); ballist->setLatitude(offsetpos.getLatitudeDeg()); ballist->setLongitude(offsetpos.getLongitudeDeg()); ballist->setAltitude(offsetpos.getElevationFt()); + ballist->setAzimuthRandomError(sm->azimuth_error->get_value()); ballist->setAzimuth(IC.azimuth); + ballist->setElevationRandomError(sm->elevation_error->get_value()); ballist->setElevation(IC.elevation); ballist->setRoll(IC.roll); ballist->setSpeed(IC.speed / SG_KT_TO_FPS); @@ -274,6 +276,7 @@ bool FGSubmodelMgr::release(submodel *sm, double dt) ballist->setLife(sm->life); ballist->setBuoyancy(sm->buoyancy); ballist->setWind(sm->wind); + ballist->setCdRandomness(sm->cd_randomness->get_value()); ballist->setCd(sm->cd); ballist->setStabilisation(sm->aero_stabilised); ballist->setNoRoll(sm->no_roll); @@ -415,7 +418,6 @@ void FGSubmodelMgr::transform(submodel *sm) cosRz = cos(IC.azimuth * SG_DEGREES_TO_RADIANS); sinRz = sin(IC.azimuth * SG_DEGREES_TO_RADIANS); - // Get submodel initial velocity vector angles in XZ and XY planes. // This vector should be added to aircraft's vector. IC.elevation += (yaw_offset * sinRx) + (pitch_offset * cosRx); @@ -550,16 +552,43 @@ void FGSubmodelMgr::setData(int id, const string& path, bool serviceable, const sm->ext_force = entry_node->getBoolValue("external-force", false); sm->force_path = entry_node->getStringValue("force-path", ""); sm->random = entry_node->getBoolValue("random", false); - sm->randomness = entry_node->getDoubleValue("randomness", 0.5); SGPropertyNode_ptr prop_root = fgGetNode("/", true); SGPropertyNode n; SGPropertyNode_ptr a = entry_node->getNode("yaw-offset"); - sm->yaw_offset = new FGXMLAutopilot::InputValue(*prop_root, a ? *a : n ); + sm->yaw_offset = new FGXMLAutopilot::InputValue(*prop_root, a ? *a : n); a = entry_node->getNode("pitch-offset"); - sm->pitch_offset = new FGXMLAutopilot::InputValue(*prop_root, a ? *a : n ); + sm->pitch_offset = new FGXMLAutopilot::InputValue(*prop_root, a ? *a : n); + + // Randomness + a = entry_node->getNode("randomness", true); + SGPropertyNode_ptr b; + + // Maximum azimuth randomness error in degrees + b = a->getNode("azimuth"); + sm->azimuth_error = new FGXMLAutopilot::InputValue(*prop_root, b ? *b : n); + + // Maximum elevation randomness error in degrees + b = a->getNode("elevation"); + sm->elevation_error = new FGXMLAutopilot::InputValue(*prop_root, b ? *b : n); + + // Randomness of Cd (plus or minus) + b = a->getNode("cd"); + if (!b) { + b = a->getNode("cd", true); + b->setDoubleValue(0.1); + } + sm->cd_randomness = new FGXMLAutopilot::InputValue(*prop_root, *b); + + // Randomness of life (plus or minus) + b = a->getNode("life"); + if (!b) { + b = a->getNode("life", true); + b->setDoubleValue(0.5); + } + sm->life_randomness = new FGXMLAutopilot::InputValue(*prop_root, *b); if (sm->contents_node != 0) sm->contents = sm->contents_node->getDoubleValue(); diff --git a/src/AIModel/submodel.hxx b/src/AIModel/submodel.hxx index 881e08d0b..4c080526e 100644 --- a/src/AIModel/submodel.hxx +++ b/src/AIModel/submodel.hxx @@ -51,7 +51,10 @@ public: double drag_area; double life; double buoyancy; - double randomness; + FGXMLAutopilot::InputValue_ptr azimuth_error; + FGXMLAutopilot::InputValue_ptr elevation_error; + FGXMLAutopilot::InputValue_ptr cd_randomness; + FGXMLAutopilot::InputValue_ptr life_randomness; bool wind; bool first_time; double cd;