1
0
Fork 0

AIThermal/AIStorm: Maintenance

virtaul dtor
ensure all members are initialized
config.h is unused
bool assignment via int type fixed
This commit is contained in:
Scott Giese 2022-01-15 15:51:49 -06:00
parent 75941319d2
commit 3f2c9ece5a
4 changed files with 131 additions and 166 deletions

View file

@ -18,25 +18,21 @@
// along with this program; if not, write to the Free Software // along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#ifdef HAVE_CONFIG_H #include <cmath>
# include <config.h> #include <cstdlib>
#endif #include <string>
#include <time.h>
#include <Main/fg_props.hxx> #include <Main/fg_props.hxx>
#include <Main/globals.hxx> #include <Main/globals.hxx>
#include <Scenery/scenery.hxx> #include <Scenery/scenery.hxx>
#include <string>
#include <cmath>
#include <cstdlib>
#include <time.h>
using std::string; using std::string;
#include "AIStorm.hxx" #include "AIStorm.hxx"
FGAIStorm::FGAIStorm() : FGAIStorm::FGAIStorm() : FGAIBase(otStorm, false)
FGAIBase(otStorm, false)
{ {
delay = 3.6; delay = 3.6;
subflashes = 1; subflashes = 1;
@ -61,9 +57,6 @@ FGAIStorm::FGAIStorm() :
} }
FGAIStorm::~FGAIStorm() {
}
void FGAIStorm::readFromScenario(SGPropertyNode* scFileNode) { void FGAIStorm::readFromScenario(SGPropertyNode* scFileNode) {
if (!scFileNode) if (!scFileNode)
return; return;
@ -83,15 +76,12 @@ void FGAIStorm::update(double dt) {
void FGAIStorm::Run(double dt) { void FGAIStorm::Run(double dt) {
double speed_north_deg_sec; double speed_north_deg_sec;
double speed_east_deg_sec; double speed_east_deg_sec;
// convert speed to degrees per second // convert speed to degrees per second
speed_north_deg_sec = cos( hdg / SG_RADIANS_TO_DEGREES ) speed_north_deg_sec = cos(hdg / SG_RADIANS_TO_DEGREES) * speed * 1.686 / ft_per_deg_lat;
* speed * 1.686 / ft_per_deg_lat; speed_east_deg_sec = sin(hdg / SG_RADIANS_TO_DEGREES) * speed * 1.686 / ft_per_deg_lon;
speed_east_deg_sec = sin( hdg / SG_RADIANS_TO_DEGREES )
* speed * 1.686 / ft_per_deg_lon;
// set new position // set new position
pos.setLatitudeDeg( pos.getLatitudeDeg() + speed_north_deg_sec * dt); pos.setLatitudeDeg( pos.getLatitudeDeg() + speed_north_deg_sec * dt);
@ -132,8 +122,7 @@ void FGAIStorm::Run(double dt) {
timer = 0.0; timer = 0.0;
flashed = 0; flashed = 0;
} }
} } else {
else {
timer += dt; timer += dt;
} }
@ -152,6 +141,5 @@ void FGAIStorm::Run(double dt) {
turb_mag_node->setDoubleValue(strength_norm); turb_mag_node->setDoubleValue(strength_norm);
turb_rate_node->setDoubleValue(0.5); turb_rate_node->setDoubleValue(0.5);
} }
} }

View file

@ -20,22 +20,22 @@
#pragma once #pragma once
#include <string>
#include "AIManager.hxx" #include "AIManager.hxx"
#include "AIBase.hxx" #include "AIBase.hxx"
#include <string>
class FGAIStorm : public FGAIBase { class FGAIStorm : public FGAIBase {
public: public:
FGAIStorm(); FGAIStorm();
~FGAIStorm(); virtual ~FGAIStorm() = default;
const char* getTypeString(void) const override { return "thunderstorm"; }
void readFromScenario(SGPropertyNode* scFileNode) override; void readFromScenario(SGPropertyNode* scFileNode) override;
void update(double dt) override; void update(double dt) override;
inline void setStrengthNorm( double s ) { strength_norm = s; }; inline void setStrengthNorm( double s ) { strength_norm = s; };
inline void setDiameter( double d ) { diameter = d; }; inline void setDiameter( double d ) { diameter = d; };
inline void setHeight( double h ) { height = h; }; inline void setHeight( double h ) { height = h; };
@ -43,12 +43,11 @@ public:
inline double getDiameter() const { return diameter; }; inline double getDiameter() const { return diameter; };
inline double getHeight() const { return height; }; inline double getHeight() const { return height; };
const char* getTypeString(void) const override { return "thunderstorm"; }
private: private:
double diameter; // diameter of turbulence zone, in nm double diameter = 0.0; // diameter of turbulence zone, in nm
double height; // top of turbulence zone, in feet MSL double height = 0.0; // top of turbulence zone, in feet MSL
double strength_norm; // strength of turbulence double strength_norm = 0.0; // strength of turbulence
void Run(double dt); void Run(double dt);
// lightning stuff // lightning stuff
@ -65,5 +64,4 @@ private:
// turbulence stuff // turbulence stuff
SGPropertyNode_ptr turb_mag_node; SGPropertyNode_ptr turb_mag_node;
SGPropertyNode_ptr turb_rate_node; SGPropertyNode_ptr turb_rate_node;
}; };

View file

@ -20,24 +20,21 @@
// along with this program; if not, write to the Free Software // along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#ifdef HAVE_CONFIG_H #include <cmath>
# include <config.h> #include <string>
#endif
#include <Main/fg_props.hxx> #include <Main/fg_props.hxx>
#include <Main/globals.hxx> #include <Main/globals.hxx>
#include <Scenery/scenery.hxx> #include <Scenery/scenery.hxx>
#include <string>
#include <cmath>
using std::string; using std::string;
#include "AIThermal.hxx" #include "AIThermal.hxx"
FGAIThermal::FGAIThermal() : FGAIThermal::FGAIThermal() : FGAIBase(otThermal, false)
FGAIBase(otThermal, false)
{ {
altitude_agl_ft = 0.0;
max_strength = 6.0; max_strength = 6.0;
diameter = 0.5; diameter = 0.5;
strength = factor = 0.0; strength = factor = 0.0;
@ -47,8 +44,6 @@ FGAIThermal::FGAIThermal() :
alt=0.0; alt=0.0;
} }
FGAIThermal::~FGAIThermal() {
}
void FGAIThermal::readFromScenario(SGPropertyNode* scFileNode) { void FGAIThermal::readFromScenario(SGPropertyNode* scFileNode) {
if (!scFileNode) if (!scFileNode)
@ -72,28 +67,20 @@ bool FGAIThermal::init(ModelSearchOrder searchOrder) {
fgGetNode("/environment/config/aloft/entry[2]/wind-from-heading-deg", true); fgGetNode("/environment/config/aloft/entry[2]/wind-from-heading-deg", true);
_aloft_wind_speed_node = _aloft_wind_speed_node =
fgGetNode("/environment/config/aloft/entry[2]/wind-speed-kt", true); fgGetNode("/environment/config/aloft/entry[2]/wind-speed-kt", true);
do_agl_calc = 1; do_agl_calc = true;
return FGAIBase::init(searchOrder); return FGAIBase::init(searchOrder);
} }
void FGAIThermal::bind() { void FGAIThermal::bind() {
FGAIBase::bind(); FGAIBase::bind();
tie("position/altitude-agl-ft", // for debug and tweak tie("position/altitude-agl-ft", SGRawValuePointer<double>(&altitude_agl_ft));
SGRawValuePointer<double>(&altitude_agl_ft)); tie("alt-rel", SGRawValuePointer<double>(&alt_rel));
tie("alt-rel", // for debug and tweak tie("time", SGRawValuePointer<double>(&time));
SGRawValuePointer<double>(&alt_rel)); tie("xx", SGRawValuePointer<double>(&xx));
tie("time", // for debug and tweak tie("is-forming", SGRawValuePointer<bool>(&is_forming));
SGRawValuePointer<double>(&time)); tie("is-formed", SGRawValuePointer<bool>(&is_formed));
tie("xx", // for debug and tweak tie("is-dying", SGRawValuePointer<bool>(&is_dying));
SGRawValuePointer<double>(&xx)); tie("is-dead", SGRawValuePointer<bool>(&is_dead));
tie("is-forming", // for debug abd tweak
SGRawValuePointer<bool>(&is_forming));
tie("is-formed", // for debug abd tweak
SGRawValuePointer<bool>(&is_formed));
tie("is-dying", // for debug abd tweak
SGRawValuePointer<bool>(&is_dying));
tie("is-dead", // for debug abd tweak
SGRawValuePointer<bool>(&is_dead));
} }
void FGAIThermal::update(double dt) { void FGAIThermal::update(double dt) {
@ -103,28 +90,24 @@ void FGAIThermal::update(double dt) {
} }
//the formula to get the available portion of VUpMax depending on altitude //the formula to get the available portion of VUpMax depending on altitude
//returns a double between 0 and 1 //returns a double between 0 and 1
double FGAIThermal::get_strength_fac(double alt_frac) { double FGAIThermal::get_strength_fac(double alt_frac) {
double PI = 4.0 * atan(1.0); double PI = 4.0 * atan(1.0);
double fac = 0.0; double fac = 0.0;
if ( alt_frac <=0.0 ) { // do submarines get thermals ? if ( alt_frac <=0.0 ) { // do submarines get thermals ?
fac = 0.0; fac = 0.0;
} } else if ((alt_frac > 0.0) && (alt_frac <= 0.1)) { // ground layer
else if ( ( alt_frac>0.0 ) && (alt_frac<=0.1) ) { // ground layer
fac = ( 0.1*( pow( (10.0*alt_frac),10.0) ) ); fac = ( 0.1*( pow( (10.0*alt_frac),10.0) ) );
} } else if ((alt_frac > 0.1) && (alt_frac <= 1.0)) { // main body of the thermal
else if ( ( alt_frac>0.1 ) && (alt_frac<=1.0) ) { // main body of the thermal
fac = 0.4175 - 0.5825* ( cos ( PI* (1.0-sqrt(alt_frac) ) +PI) ) ; fac = 0.4175 - 0.5825* ( cos ( PI* (1.0-sqrt(alt_frac) ) +PI) ) ;
} } else if ((alt_frac > 1.0) && (alt_frac < 1.1)) { //above the ceiling, but not above the cloud
else if ( ( alt_frac >1.0 ) && (alt_frac < 1.1 ) ) { //above the ceiling, but not above the cloud
fac = (0.5 * ( 1.0 + cos ( PI*( (-2.0*alt_frac)*5.0 ) ) ) ); fac = (0.5 * ( 1.0 + cos ( PI*( (-2.0*alt_frac)*5.0 ) ) ) );
} } else if (alt_frac >= 1.1) { //above the cloud
else if ( alt_frac >= 1.1 ) { //above the cloud
fac = 0.0; fac = 0.0;
} }
return fac; return fac;
} }
@ -156,15 +139,13 @@ double t4 = tmin4/tmin3;
// the time elapsed since the thermal was born, in a 0-1 fraction of tmin3 // the time elapsed since the thermal was born, in a 0-1 fraction of tmin3
time = cycle_timer/alive_cycle_time; time = cycle_timer/alive_cycle_time;
//comment above and // comment above and uncomment below to freeze the time cycle
//uncomment below to freeze the time cycle // time=0.5;
time=0.5;
if ( time >= t4) { if ( time >= t4) {
cycle_timer = 60*(rand()%31); cycle_timer = 60*(rand()%31);
} }
//the position of the thermal 'top' //the position of the thermal 'top'
double thermal_foot_lat = (pos.getLatitudeDeg()); double thermal_foot_lat = (pos.getLatitudeDeg());
double thermal_foot_lon = (pos.getLongitudeDeg()); double thermal_foot_lon = (pos.getLongitudeDeg());
@ -199,20 +180,16 @@ double dist_center;
double slice_center_lon; double slice_center_lon;
double slice_center_lat; double slice_center_lat;
//we need to know the thermal foot AGL altitude //we need to know the thermal foot AGL altitude
//we could do this only once, as thermal don't move //we could do this only once, as thermal don't move
//but then agl info is lost on user reset //but then agl info is lost on user reset
//so we only do this every 10 seconds to save cpu //so we only do this every 10 seconds to save cpu
dt_count += dt; dt_count += dt;
if (dt_count >= 10.0 ) { if (dt_count >= 10.0 ) {
//double alt;
if (getGroundElevationM(SGGeod::fromGeodM(pos, 20000), alt, 0)) { if (getGroundElevationM(SGGeod::fromGeodM(pos, 20000), alt, 0)) {
ground_elev_ft = alt * SG_METER_TO_FEET; ground_elev_ft = alt * SG_METER_TO_FEET;
do_agl_calc = 0; do_agl_calc = false;
altitude_agl_ft = height - ground_elev_ft ; altitude_agl_ft = height - ground_elev_ft ;
dt_count = 0.0; dt_count = 0.0;
} }
@ -220,14 +197,12 @@ if (dt_count >= 10.0 ) {
//user altitude relative to the thermal height, seen AGL from the thermal foot //user altitude relative to the thermal height, seen AGL from the thermal foot
double user_altitude = globals->get_aircraft_position().getElevationFt(); double user_altitude = globals->get_aircraft_position().getElevationFt();
if ( user_altitude < 1.0 ) { user_altitude = 1.0 ;}; // an ugly way to avoid NaNs for users at alt 0 if ( user_altitude < 1.0 ) { user_altitude = 1.0 ;}; // an ugly way to avoid NaNs for users at alt 0
double user_altitude_agl= ( user_altitude - ground_elev_ft ) ; double user_altitude_agl= ( user_altitude - ground_elev_ft ) ;
alt_rel = user_altitude_agl / altitude_agl_ft; alt_rel = user_altitude_agl / altitude_agl_ft;
//the updraft user feels ! //the updraft user feels !
double Vup; double Vup;
@ -258,26 +233,34 @@ if (time <= t1) {
xx = ( time / t1 ); xx = ( time / t1 );
maxstrengthavail = xx* get_strength_fac ( alt_rel / xx ); maxstrengthavail = xx* get_strength_fac ( alt_rel / xx );
is_forming=1;is_formed=0;is_dying=0;is_dead=0; is_forming = true;
is_formed = false;
is_dying = false;
is_dead = false;
} } else if ((time > t1) && (time <= t2)) {
else if ( (time > t1) && (time <= t2) ) {
maxstrengthavail = get_strength_fac ( (alt_rel) ); maxstrengthavail = get_strength_fac ( (alt_rel) );
is_forming=0;is_formed=1;is_dying=0;is_dead=0; is_forming = false;
is_formed = true;
is_dying = false;
is_dead = false;
} } else if ((time > t2) && (time <= t3)) {
else if ( (time > t2) && (time <= t3) ) {
xx= ( ( time - t2) / (1.0 - t2) ) ; xx= ( ( time - t2) / (1.0 - t2) ) ;
maxstrengthavail = get_strength_fac ( alt_rel - xx ); maxstrengthavail = get_strength_fac ( alt_rel - xx );
is_forming=0;is_formed=0;is_dying=1;is_dead=0; is_forming = false;
is_formed = false;
is_dying = true;
is_dead = false;
} } else {
else {
maxstrengthavail = 0.0; maxstrengthavail = 0.0;
is_forming=0;is_formed=0;is_dying=0;is_dead=1; is_forming = false;
is_formed = false;
is_dying = false;
is_dead = true;
} }
//we get the diameter of the thermal slice at the user altitude //we get the diameter of the thermal slice at the user altitude
@ -285,11 +268,9 @@ else {
if ((alt_rel >= 0.0) && (alt_rel < 1.0)) { if ((alt_rel >= 0.0) && (alt_rel < 1.0)) {
Rsink = (shaping * Rmax) + (((1.0 - shaping) * Rmax * alt_rel) / altitude_agl_ft); // in the main thermal body Rsink = (shaping * Rmax) + (((1.0 - shaping) * Rmax * alt_rel) / altitude_agl_ft); // in the main thermal body
} } else if ((alt_rel >= 1.0) && (alt_rel < 1.1)) {
else if ( (alt_rel >=1.0) && (alt_rel < 1.1) ) {
Rsink = (Rmax / 2.0) * (1.0 + cos((10.0 * PI * alt_rel) - (2.0 * PI))); // above the ceiling Rsink = (Rmax / 2.0) * (1.0 + cos((10.0 * PI * alt_rel) - (2.0 * PI))); // above the ceiling
} } else {
else {
Rsink = 0.0; // above the cloud Rsink = 0.0; // above the cloud
} }
@ -347,14 +328,11 @@ if ( max_strength >=0.0 ) { // this is a thermal
if ((dist_center >= 0.0) && (dist_center < Rup)) { //user is in the updraft area if ((dist_center >= 0.0) && (dist_center < Rup)) { //user is in the updraft area
Vup = v_up_max * cos(dist_center * PI / (2.0 * Rup)); Vup = v_up_max * cos(dist_center * PI / (2.0 * Rup));
} } else if ((dist_center > Rup) && (dist_center <= ((Rup + Rsink) / 2.0))) { //user in the 1st half of the sink area
else if ( ( dist_center > Rup ) && ( dist_center <= ((Rup+Rsink)/2.0) ) ) { //user in the 1st half of the sink area
Vup = v_up_min * cos((dist_center - (Rup + Rsink) / 2.0) * PI / (2.0 * ((Rup + Rsink) / 2.0 - Rup))); Vup = v_up_min * cos((dist_center - (Rup + Rsink) / 2.0) * PI / (2.0 * ((Rup + Rsink) / 2.0 - Rup)));
} } else if ((dist_center > ((Rup + Rsink) / 2.0)) && dist_center <= Rsink) { // user in the 2nd half of the sink area
else if ( ( dist_center > ((Rup+Rsink)/2.0) ) && dist_center <= Rsink ) { // user in the 2nd half of the sink area
Vup = (global_sink + v_up_min) / 2.0 + (global_sink - v_up_min) / 2.0 * cos((dist_center - Rsink) * PI / ((Rsink - Rup) / 2.0)); Vup = (global_sink + v_up_min) / 2.0 + (global_sink - v_up_min) / 2.0 * cos((dist_center - Rsink) * PI / ((Rsink - Rup) / 2.0));
} } else { // outside the thermal
else { // outside the thermal
Vup = global_sink; Vup = global_sink;
} }
} }
@ -363,14 +341,16 @@ else { // this is a sink, we don't want updraft on the sides, nor do we want to
if (alt_rel <= 1.1) { if (alt_rel <= 1.1) {
double fac = (1.0 - (1.0 - 1.815 * alt_rel) * (1.0 - 1.815 * alt_rel)); double fac = (1.0 - (1.0 - 1.815 * alt_rel) * (1.0 - 1.815 * alt_rel));
Vup = fac * (global_sink + ((v_up_max - global_sink) / 2.0) * (1.0 + cos(dist_center * PI / Rmax))); Vup = fac * (global_sink + ((v_up_max - global_sink) / 2.0) * (1.0 + cos(dist_center * PI / Rmax)));
} else {
Vup = global_sink;
} }
else { Vup = global_sink; }
} }
//correct for no global sink above clouds and outside thermals //correct for no global sink above clouds and outside thermals
if ( ( (alt_rel > 1.0) && (alt_rel <1.1)) && ( dist_center > Rsink ) ) { if ( ( (alt_rel > 1.0) && (alt_rel <1.1)) && ( dist_center > Rsink ) ) {
Vup = global_sink * ( 11.0 -10.0 * alt_rel ); Vup = global_sink * ( 11.0 -10.0 * alt_rel );
} }
if ( alt_rel >= 1.1 ) { if ( alt_rel >= 1.1 ) {
Vup = 0.0; Vup = 0.0;
} }
@ -380,5 +360,3 @@ range = dist_center;
} }

View file

@ -32,8 +32,9 @@ class FGAIThermal : public FGAIBase {
public: public:
FGAIThermal(); FGAIThermal();
~FGAIThermal(); virtual ~FGAIThermal() = default;
const char* getTypeString(void) const override { return "thermal"; }
void readFromScenario(SGPropertyNode* scFileNode) override; void readFromScenario(SGPropertyNode* scFileNode) override;
bool init(ModelSearchOrder searchOrder) override; bool init(ModelSearchOrder searchOrder) override;
@ -54,36 +55,36 @@ public:
inline double getV_up_min() const { return v_up_min; }; inline double getV_up_min() const { return v_up_min; };
inline double getR_up_frac() const { return r_up_frac; }; inline double getR_up_frac() const { return r_up_frac; };
const char* getTypeString(void) const override { return "thermal"; }
void getGroundElev(double dt); void getGroundElev(double dt);
private: private:
void Run(double dt); void Run(double dt);
double get_strength_fac(double alt_frac); double get_strength_fac(double alt_frac);
double max_strength; double max_strength;
double strength; double strength;
double diameter; double diameter;
double height; double height = 0.0;
double factor; double factor;
double alt_rel; double alt_rel = 0.0;
double alt; double alt;
double v_up_max; double v_up_max = 0.0;
double v_up_min; double v_up_min = 0.0;
double r_up_frac; double r_up_frac = 0.0;
double cycle_timer; double cycle_timer;
double dt_count; double dt_count;
double time; double time = 0.0;
double xx; double xx = 0.0;
double ground_elev_ft; // ground level in ft double ground_elev_ft; // ground level in ft
double altitude_agl_ft; // altitude above ground in feet
bool do_agl_calc; bool do_agl_calc = false;
bool is_forming; bool is_forming = false;
bool is_formed; bool is_formed = false;
bool is_dying; bool is_dying = false;
bool is_dead; bool is_dead = false;
SGPropertyNode_ptr _surface_wind_from_deg_node; SGPropertyNode_ptr _surface_wind_from_deg_node;
SGPropertyNode_ptr _surface_wind_speed_node; SGPropertyNode_ptr _surface_wind_speed_node;
SGPropertyNode_ptr _aloft_wind_from_deg_node; SGPropertyNode_ptr _aloft_wind_from_deg_node;
SGPropertyNode_ptr _aloft_wind_speed_node; SGPropertyNode_ptr _aloft_wind_speed_node;
}; };