1
0
Fork 0

submodel: Fix randomness of Cd and life

Signed-off-by: onox <denkpadje@gmail.com>
This commit is contained in:
onox 2015-05-21 00:23:33 +02:00 committed by Erik Hofman
parent e049a9ab03
commit 1b6326e057
3 changed files with 169 additions and 213 deletions

View file

@ -52,11 +52,14 @@ hs(0),
_elapsed_time(0),
_aero_stabilised(false),
_drag_area(0.007),
_cd(0.029),
_cd_randomness(0.0),
_life_timer(0.0),
_buoyancy(0),
_wind(true),
_mass(0),
_random(false),
_life_randomness(0.0),
_load_resistance(0),
_solid(false),
_force_stabilised(false),
@ -252,7 +255,6 @@ void FGAIBallistic::bind() {
tie("material/load-resistance",
SGRawValuePointer<double>(&_load_resistance));
}
}
void FGAIBallistic::update(double dt)
@ -262,7 +264,8 @@ void FGAIBallistic::update(double dt)
if (_slave_to_ac) {
slaveToAC(dt);
Transform();
} else if (!invisible){
}
else if (!invisible) {
Run(dt);
Transform();
}
@ -270,13 +273,10 @@ void FGAIBallistic::update(double dt)
}
void FGAIBallistic::setAzimuth(double az) {
if (_random)
hdg = _azimuth = (az - 5 ) + (10 * sg_random());
else
hdg = _azimuth = az;
//cout << _name << " init hdg " << hdg << " random " << _random << endl;
}
void FGAIBallistic::setElevation(double el) {
@ -304,11 +304,9 @@ void FGAIBallistic::setDragArea(double a) {
}
void FGAIBallistic::setLife(double seconds) {
if (_random){
life = seconds * _randomness + (seconds * (1 -_randomness) * sg_random());
//cout << " set life " << life << endl;
} else
if (_random)
life = seconds * (1 - _life_randomness + 2 * _life_randomness * sg_random());
else
life = seconds;
}
@ -328,8 +326,12 @@ void FGAIBallistic::setWind(bool val) {
_wind = val;
}
void FGAIBallistic::setCd(double c) {
_Cd = c;
void FGAIBallistic::setCd(double cd) {
_cd = cd;
}
void FGAIBallistic::setCdRandomness(double randomness) {
_cd_randomness = randomness;
}
void FGAIBallistic::setMass(double m) {
@ -340,8 +342,8 @@ void FGAIBallistic::setWeight(double w) {
_weight_lb = w;
}
void FGAIBallistic::setRandomness(double r) {
_randomness = r;
void FGAIBallistic::setLifeRandomness(double randomness) {
_life_randomness = randomness;
}
void FGAIBallistic::setRandom(bool r) {
@ -365,7 +367,6 @@ void FGAIBallistic::setExternalForce(bool f) {
}
void FGAIBallistic::setImpactReportNode(const string& path) {
if (!path.empty())
_impact_report_node = fgGetNode(path.c_str(), true);
}
@ -404,7 +405,6 @@ void FGAIBallistic::setSlaved(bool s) {
}
void FGAIBallistic::setContentsPath(const string& path) {
_contents_path = path;
if (!path.empty()) {
@ -413,7 +413,6 @@ void FGAIBallistic::setContentsPath(const string& path) {
}
void FGAIBallistic::setContentsNode(SGPropertyNode_ptr node) {
if (node != 0) {
_contents_node = node;
_contents_path = _contents_node->getDisplayName();
@ -421,7 +420,6 @@ void FGAIBallistic::setContentsNode(SGPropertyNode_ptr node) {
}
void FGAIBallistic::setParentNodes(SGPropertyNode_ptr node) {
if (node != 0) {
_pnode = node;
_p_pos_node = _pnode->getChild("position", 0, true);
@ -439,14 +437,10 @@ void FGAIBallistic::setParentNodes(SGPropertyNode_ptr node) {
_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) {
//cout << "set parent pos" << endl;
double lat = _p_lat_node->getDoubleValue();
double lon = _p_lon_node->getDoubleValue();
double alt = _p_alt_node->getDoubleValue();
@ -454,9 +448,7 @@ void FGAIBallistic::setParentPos() {
_parentpos.setLongitudeDeg(lon);
_parentpos.setLatitudeDeg(lat);
_parentpos.setElevationFt(alt);
}
}
bool FGAIBallistic::getSlaved() const {
@ -522,21 +514,21 @@ bool FGAIBallistic::getHtAGL(double start){
//<< " load " << _load_resistance
//<< " frictionFactor " << _frictionFactor
//<< endl;
}
return true;
} else {
}
else {
return false;
}
}
double FGAIBallistic::getRecip(double az) {
// calculate the reciprocal of the input azimuth
if (az - 180 < 0) {
return az + 180;
} else {
}
else {
return az - 180;
}
}
@ -604,7 +596,6 @@ void FGAIBallistic::setTgtZOffset(double z){
}
void FGAIBallistic::slaveToAC(double dt) {
if (invisible)
return;
@ -618,7 +609,8 @@ void FGAIBallistic::slaveToAC(double dt){
// agl = _p_agl_node->getDoubleValue();
setOffsetPos(_parentpos, hdg, pch, rll);
setSpeed(_p_spd_node->getDoubleValue());
}else {
}
else {
hdg = manager->get_user_heading();
pch = manager->get_user_pitch();
rll = manager->get_user_roll();
@ -655,12 +647,12 @@ void FGAIBallistic::Run(double dt) {
// 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 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);
@ -669,23 +661,26 @@ void FGAIBallistic::Run(double dt) {
setTime(0);
}
//set the contents in the appropriate tank or other property in the parent to zero
// Set the contents in the appropriate tank or other property in the parent to zero
setContents(0);
//randomise Cd by +- 10%
// Randomize Cd by +- a certain percentage of the ideal Cd
double Cd;
if (_random)
_Cd = _Cd * 0.90 + (0.10 * sg_random());
Cd = _cd * (1 - _cd_randomness + 2 * _cd_randomness * sg_random());
else
Cd = _cd;
// 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;
@ -710,19 +705,19 @@ void FGAIBallistic::Run(double dt) {
//and convert horizontal speed (fps) to degrees per second
calcNE();
// if wind not required, set to zero
// If wind not required, set to zero
if (!_wind) {
_wind_from_north = 0;
_wind_from_east = 0;
} else {
}
else {
_wind_from_north = manager->get_wind_from_north();
_wind_from_east = manager->get_wind_from_east();
}
//calculate velocity due to external force
// Calculate velocity due to external force
double force_speed_north_deg_sec = 0;
double force_speed_east_deg_sec = 0;
// double vs_force_fps = 0;
double hs_force_fps = 0;
double v_force_acc_fpss = 0;
double force_speed_north_fps = 0;
@ -748,15 +743,12 @@ void FGAIBallistic::Run(double dt) {
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:
// 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)){
// Perform ground interaction if impacts are not calculated
if (!_report_impact && getHtAGL(10000)) {
double deadzone = 0.1;
if (_ht_agl_ft <= (0 + _ground_offset + deadzone) && _solid) {
@ -769,30 +761,27 @@ void FGAIBallistic::Run(double dt) {
if (vs < 0)
vs = -vs * 0.5;
// calculate friction
// we assume a static Coefficient of Friction (mu) of 0.62 (wood on concrete)
// 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;
//adjust horizontal force. We assume that a speed of <= 5 fps is static
// 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
}
else
dynamic_friction_force_lbs = (static_friction_force_lbs * 0.95);
//ignore wind when on the ground for now
// 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;
normal_force_fpss = normal_force_lbs / _mass;
@ -854,12 +843,13 @@ void FGAIBallistic::Run(double dt) {
if (_ht_agl_ft <= (0 + _ground_offset + deadzone) && _solid) {
pos.setElevationFt(0 + _ground_offset);
} else {
}
else {
pos.setElevationFt(_offsetpos.getElevationFt() + _load_offset);
}
}
} else {
}
else {
pos.setLatitudeDeg( pos.getLatitudeDeg()
+ (speed_north_deg_sec - wind_speed_from_north_deg_sec
+ force_speed_north_deg_sec + friction_force_speed_north_deg_sec) * dt );
@ -894,7 +884,8 @@ void FGAIBallistic::Run(double dt) {
// we assume a symetrical MI about the pitch and yaw axis
setPch(_elevation, dt, coeff);
setHdg(_azimuth, dt, coeff);
} else if (_force_stabilised) { // we simulate rotational moment of inertia by using a filter
}
else if (_force_stabilised) { // we simulate rotational moment of inertia by using a filter
//cout<< "_force_stabilised "<< endl;
const double coeff = 0.9;
@ -913,18 +904,17 @@ void FGAIBallistic::Run(double dt) {
setHdg(_azimuth, dt, coeff);
}
//do impacts and collisions
// Do impacts and collisions
if (_report_impact && !_impact_reported)
handle_impact();
if (_report_collision && !_collision_reported)
handle_collision();
// set destruction flag if altitude less than sea level -1000
// Set destruction flag if altitude less than sea level -1000
if (altitude_ft < -1000.0 && life != -1)
setDie(true);
} // end Run
}
double FGAIBallistic::_getTime() const {
return _life_timer;
@ -934,9 +924,21 @@ void FGAIBallistic::setTime(double s){
_life_timer = s;
}
void FGAIBallistic::handle_impact() {
void FGAIBallistic::handleEndOfLife(double elevation) {
report_impact(elevation);
// try terrain intersection
// Make the submodel invisible if the submodel is immortal, otherwise kill it if it has no subsubmodels
if (life == -1) {
invisible = true;
}
else if (_subID == 0) {
// Kill the AIObject if there is no subsubmodel
setDie(true);
}
}
void FGAIBallistic::handle_impact() {
// Try terrain intersection
double start = pos.getElevationM() + 100;
if (!getHtAGL(start))
@ -944,29 +946,14 @@ void FGAIBallistic::handle_impact() {
if (_ht_agl_ft <= 0) {
SG_LOG(SG_AI, SG_DEBUG, "AIBallistic: terrain impact material" << _mat_name);
report_impact(_elevation_m);
_impact_reported = true;
if (life == -1){
invisible = true;
} else if (_subID == 0) // kill the AIObject if there is no subsubmodel
setDie(true);
handleEndOfLife(_elevation_m);
}
}
void FGAIBallistic::handle_expiry() {
//SG_LOG(SG_AI, SG_DEBUG, "AIBallistic: handle_expiry " << pos.getElevationM());
report_impact(pos.getElevationM());
_expiry_reported = true;
if (life == -1){
invisible = true;
} else if (_subID == 0){ // kill the AIObject if there is no subsubmodel
setDie(true);
}
handleEndOfLife(pos.getElevationM());
}
void FGAIBallistic::handle_collision()
@ -1012,7 +999,6 @@ void FGAIBallistic::report_impact(double elevation, const FGAIBase *object)
}
SGVec3d FGAIBallistic::getCartHitchPos() const {
// convert geodetic positions to geocentered
SGVec3d cartuserPos = globals->get_aircraft_position_cart();
@ -1042,20 +1028,13 @@ SGVec3d FGAIBallistic::getCartHitchPos() const{
// Add the position offset of the user model to get the geocentered position
SGVec3d offsetPos = cartuserPos + off;
return offsetPos;
}
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 cartoffsetPos = getCartOffsetPos(inpos, heading, pitch, roll);
//SGVec3d cartoffsetPos = getCartHitchPos();
//SGGeodesy::SGCartToGeod(cartoffsetPos, hitchpos);
SGGeodesy::SGCartToGeod(cartoffsetPos, _offsetpos);
}
double FGAIBallistic::getDistanceToHitch() const {
@ -1109,8 +1088,7 @@ double FGAIBallistic::getRelBrgHitchToUser() const {
}
double FGAIBallistic::getElevHitchToUser() const {
//calculate the distance from the user position
// Calculate the distance from the user position
SGVec3d carthitchPos = getCartHitchPos();
SGVec3d cartuserPos = globals->get_aircraft_position_cart();
@ -1121,10 +1099,11 @@ double FGAIBallistic::getElevHitchToUser() const {
double daltM = globals->get_aircraft_position().getElevationM() - _offsetpos.getElevationM();
// now the angle, positive angles are upwards
// Now the angle, positive angles are upwards
if (fabs(distance) < SGLimits<float>::min()) {
angle = 0;
} else {
}
else {
double sAngle = daltM/distance;
sAngle = SGMiscd::min(1, SGMiscd::max(-1, sAngle));
angle = SGMiscd::rad2deg(asin(sAngle));
@ -1141,38 +1120,34 @@ void FGAIBallistic::setTgtOffsets(double dt, double coeff){
_z_offset = (_tgt_z_offset * c) + (_z_offset * (1 - c));
}
void FGAIBallistic::calcVSHS() {
// calculate vertical and horizontal speed components
// Calculate vertical and horizontal speed components
double speed_fps = speed * SG_KT_TO_FPS;
if (speed == 0.0) {
hs = vs = 0.0;
} else {
}
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:
// 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
// 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
// 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
@ -1185,7 +1160,7 @@ SGVec3d FGAIBallistic::getCartOffsetPos(SGGeod inpos, double user_heading,
// Transform the user position to the horizontal local coordinate system.
SGQuatd hlTrans = SGQuatd::fromLonLat(inpos);
// and postrotate the orientation of the user model wrt the horizontal
// And postrotate the orientation of the user model wrt the horizontal
// local frame
hlTrans *= SGQuatd::fromYawPitchRollDeg(
user_heading,
@ -1203,21 +1178,22 @@ SGVec3d FGAIBallistic::getCartOffsetPos(SGGeod inpos, double user_heading,
}
void FGAIBallistic::setOffsetVelocity(double dt, SGGeod offsetpos) {
//calculate the distance from the previous offset position
// Calculate the distance from the previous offset position
SGVec3d cartoffsetPos = SGVec3d::fromGeod(offsetpos);
SGVec3d diff = cartoffsetPos - _oldcartoffsetPos;
double distance = norm(diff);
//calculate speed knots
// Calculate speed knots
speed = (distance / dt) * SG_MPS_TO_KT;
//now calulate the angle between the old and current postion positions (degrees)
// 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 {
}
else {
double sAngle = daltM / distance;
sAngle = SGMiscd::min(1, SGMiscd::max(-1, sAngle));
angle = SGMiscd::rad2deg(asin(sAngle));
@ -1225,28 +1201,27 @@ void FGAIBallistic::setOffsetVelocity(double dt, SGGeod offsetpos) {
_elevation = angle;
//calculate vertical and horizontal speed components
// Calculate vertical and horizontal speed components
calcVSHS();
//calculate the bearing of the new offset position from the old
//don't do this if speed is low
// Calculate the bearing of the new offset position from the old
// 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 {
}
else {
_azimuth = hdg;
//cout << " slow offset az " << _azimuth << endl;
}
//resolve horizontal speed into north and east components:
// Resolve horizontal speed into north and east components
calcNE();
// and finally store the new values
// And finally store the new values
_oldcartoffsetPos = cartoffsetPos;
_oldoffsetpos = offsetpos;
}
// end AIBallistic

View file

@ -59,13 +59,13 @@ public:
void setWind_from_east( double fps );
void setWind_from_north( double fps );
void setWind( bool val );
void setCd( double c );
void setCd(double cd);
void setCdRandomness(double randomness);
void setMass( double m );
void setWeight( double w );
void setNoRoll( bool nr );
void setRandom( bool r );
void setRandomness( double r );
// void setName(const string&);
void setLifeRandomness(double randomness);
void setCollision(bool c);
void setExpiry(bool e);
void setImpact(bool i);
@ -107,7 +107,6 @@ public:
bool getHtAGL(double start);
bool getSlaved() const;
// bool getFormate() const;
bool getSlavedLoad() const;
FGAIBallistic *ballistic;
@ -119,8 +118,11 @@ public:
SGPropertyNode_ptr _force_azimuth_node;
SGPropertyNode_ptr _force_elevation_node;
SGPropertyNode_ptr _pnode; // node for parent model
SGPropertyNode_ptr _p_pos_node; // nodes for parent parameters
// Node for parent model
SGPropertyNode_ptr _pnode;
// Nodes for parent parameters
SGPropertyNode_ptr _p_pos_node;
SGPropertyNode_ptr _p_lat_node;
SGPropertyNode_ptr _p_lon_node;
SGPropertyNode_ptr _p_alt_node;
@ -169,13 +171,14 @@ private:
bool _aero_stabilised; // if true, object will align with trajectory
double _drag_area; // equivalent drag area in ft2
double _life_timer; // seconds
double _buoyancy; // fps^2
bool _wind; // if true, local wind will be applied to object
double _Cd; // drag coefficient
double _cd; // drag coefficient
double _cd_randomness; // randomness of Cd. 1.0 means +- 100%, 0.0 means no randomness
double _life_timer; // seconds
double _mass; // slugs
bool _random; // modifier for Cd, life, az
double _randomness; // dimension for _random, only applies to life at present
double _life_randomness; // dimension for _random, only applies to life at present
double _load_resistance; // ground load resistanc N/m^2
double _frictionFactor; // dimensionless modifier for Coefficient of Friction
bool _solid; // if true ground is solid for FDMs
@ -194,18 +197,6 @@ private:
SGPropertyNode_ptr _impact_report_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_agl_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;
@ -213,6 +204,7 @@ private:
std::string _force_path;
std::string _contents_path;
void handleEndOfLife(double);
void handle_collision();
void handle_expiry();
void handle_impact();
@ -221,14 +213,9 @@ private:
void setContents(double c);
void calcVSHS();
void calcNE();
//void setOffsetPos(SGGeod pos, double heading, double pitch, double roll);
//void setOffsetVelocity(double dt, SGGeod pos);
SGVec3d getCartOffsetPos(SGGeod pos, double heading, double pitch, double roll) const;
//double getDistanceLoadToHitch() const;
//double getElevLoadToHitch() const;
//double getBearingLoadToHitch() const;
double getRecip(double az);
double getMass() const;
@ -237,12 +224,6 @@ private:
SGVec3d _oldcartoffsetPos;
SGVec3d _oldcartPos;
//SGGeod _parentpos;
//SGGeod _oldpos;
//SGGeod _offsetpos;
//SGGeod _oldoffsetpos;
};
#endif // _FG_AIBALLISTIC_HXX

View file

@ -259,7 +259,7 @@ bool FGSubmodelMgr::release(submodel *sm, double dt)
ballist->setName(sm->name);
ballist->setSlaved(sm->slaved);
ballist->setRandom(sm->random);
ballist->setRandomness(sm->randomness);
ballist->setLifeRandomness(sm->randomness);
ballist->setLatitude(offsetpos.getLatitudeDeg());
ballist->setLongitude(offsetpos.getLongitudeDeg());
ballist->setAltitude(offsetpos.getElevationFt());