_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),
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) {
void FGAIBallistic::setCd(double cd) {
_cd = cd;
+ _init_cd = cd;
}
void FGAIBallistic::setCdRandomness(double randomness) {
// 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;
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 );
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
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);
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);
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);
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();