diff --git a/src/Environment/ridge_lift.cxx b/src/Environment/ridge_lift.cxx index f30a37400..0edbe2e85 100644 --- a/src/Environment/ridge_lift.cxx +++ b/src/Environment/ridge_lift.cxx @@ -32,14 +32,27 @@ #include
#include
+#include
#include #include #include + using std::string; #include "ridge_lift.hxx" +static string CreateIndexedPropertyName(string Property, int index) +{ + std::stringstream str; + str << index; + string tmp; + str >> tmp; + return Property + "[" + tmp + "]"; +} + +static const double BOUNDARY1_m = 40.0; + //constructor FGRidgeLift::FGRidgeLift () { @@ -49,19 +62,8 @@ FGRidgeLift::FGRidgeLift () dist_probe_m[3] = 2000.0; dist_probe_m[4] = -100.0; - BOUNDARY1_m = 40.0; // in meters - BOUNDARY2_m = 130.0; - - PI = 4.0*atan(1.0); // pi - deg2rad = (PI/180.0); - rad2deg = (180.0/PI); strength = 0.0; timer = 0.0; - scanned = false; - - earth_rad_ft=20899773.07; - for( int i = 0; i < sizeof(probe_elev_m)/sizeof(probe_elev_m[0]); i++ ) - probe_elev_m[i] = 0.0; } //destructor @@ -72,259 +74,165 @@ FGRidgeLift::~FGRidgeLift() void FGRidgeLift::init(void) { - _ridge_lift_fps_node = - fgGetNode("/environment/ridge-lift-fps" - , true); + _ridge_lift_fps_node = fgGetNode("/environment/ridge-lift-fps", true); _surface_wind_from_deg_node = fgGetNode("/environment/config/boundary/entry[0]/wind-from-heading-deg" , true); _surface_wind_speed_node = fgGetNode("/environment/config/boundary/entry[0]/wind-speed-kt" , true); - _earth_radius_node = - fgGetNode("/position/sea-level-radius-ft" - , true); - _user_longitude_node = - fgGetNode("/position/longitude-deg" - , true); - _user_latitude_node = - fgGetNode("/position/latitude-deg" - , true); - _user_altitude_ft_node = - fgGetNode("/position/altitude-ft" - , true); - _user_altitude_agl_ft_node = - fgGetNode("/position/altitude-agl-ft" - , true); + _earth_radius_node = fgGetNode("/position/sea-level-radius-ft", true); + _user_longitude_node = fgGetNode("/position/longitude-deg", true); + _user_latitude_node = fgGetNode("/position/latitude-deg", true); + _user_altitude_ft_node = fgGetNode("/position/altitude-ft", true); + _user_altitude_agl_ft_node = fgGetNode("/position/altitude-agl-ft", true); } void FGRidgeLift::bind() { + string prop; - fgTie("/environment/ridge-lift/probe-elev-m[0]", this, - &FGRidgeLift::get_probe_elev_m_0); // read-only - fgTie("/environment/ridge-lift/probe-elev-m[1]", this, - &FGRidgeLift::get_probe_elev_m_1); // read-only - fgTie("/environment/ridge-lift/probe-elev-m[2]", this, - &FGRidgeLift::get_probe_elev_m_2); // read-only - fgTie("/environment/ridge-lift/probe-elev-m[3]", this, - &FGRidgeLift::get_probe_elev_m_3); // read-only - fgTie("/environment/ridge-lift/probe-elev-m[4]", this, - &FGRidgeLift::get_probe_elev_m_4); // read-only + for( int i = 0; i < 5; i++ ) { + prop = CreateIndexedPropertyName("/environment/ridge-lift/probe-elev-m", i ); + fgTie( prop.c_str(), this, i, &FGRidgeLift::get_probe_elev_m); // read-only - fgTie("/environment/ridge-lift/probe-lat-deg[0]", this, - &FGRidgeLift::get_probe_lat_0); // read-only - fgTie("/environment/ridge-lift/probe-lat-deg[1]", this, - &FGRidgeLift::get_probe_lat_1); // read-only - fgTie("/environment/ridge-lift/probe-lat-deg[2]", this, - &FGRidgeLift::get_probe_lat_2); // read-only - fgTie("/environment/ridge-lift/probe-lat-deg[3]", this, - &FGRidgeLift::get_probe_lat_3); // read-only - fgTie("/environment/ridge-lift/probe-lat-deg[4]", this, - &FGRidgeLift::get_probe_lat_4); // read-only + prop = CreateIndexedPropertyName("/environment/ridge-lift/probe-lat-deg", i ); + fgTie( prop.c_str(), this, i, &FGRidgeLift::get_probe_lat_deg); // read-only - fgTie("/environment/ridge-lift/probe-lon-deg[0]", this, - &FGRidgeLift::get_probe_lon_0); // read-only - fgTie("/environment/ridge-lift/probe-lon-deg[1]", this, - &FGRidgeLift::get_probe_lon_1); // read-only - fgTie("/environment/ridge-lift/probe-lon-deg[2]", this, - &FGRidgeLift::get_probe_lon_2); // read-only - fgTie("/environment/ridge-lift/probe-lon-deg[3]", this, - &FGRidgeLift::get_probe_lon_3); // read-only - fgTie("/environment/ridge-lift/probe-lon-deg[4]", this, - &FGRidgeLift::get_probe_lon_4); // read-only + prop = CreateIndexedPropertyName("/environment/ridge-lift/probe-lon-deg", i ); + fgTie( prop.c_str(), this, i, &FGRidgeLift::get_probe_lon_deg); // read-only + } - fgTie("/environment/ridge-lift/slope[0]", this, - &FGRidgeLift::get_slope_0); // read-only - fgTie("/environment/ridge-lift/slope[1]", this, - &FGRidgeLift::get_slope_1); // read-only - fgTie("/environment/ridge-lift/slope[2]", this, - &FGRidgeLift::get_slope_2); // read-only - fgTie("/environment/ridge-lift/slope[3]", this, - &FGRidgeLift::get_slope_3); // read-only - + for( int i = 0; i < 4; i++ ) { + prop = CreateIndexedPropertyName("/environment/ridge-lift/slope", i ); + fgTie( prop.c_str(), this, i, &FGRidgeLift::get_slope); // read-only + } } void FGRidgeLift::unbind() { + string prop; - fgUntie("/environment/ridge-lift/probe-elev-m[0]"); - fgUntie("/environment/ridge-lift/probe-elev-m[1]"); - fgUntie("/environment/ridge-lift/probe-elev-m[2]"); - fgUntie("/environment/ridge-lift/probe-elev-m[3]"); - fgUntie("/environment/ridge-lift/probe-elev-m[4]"); + for( int i = 0; i < 5; i++ ) { - fgUntie("/environment/ridge-lift/probe-lat-deg[0]"); - fgUntie("/environment/ridge-lift/probe-lat-deg[1]"); - fgUntie("/environment/ridge-lift/probe-lat-deg[2]"); - fgUntie("/environment/ridge-lift/probe-lat-deg[3]"); - fgUntie("/environment/ridge-lift/probe-lat-deg[4]"); + prop = CreateIndexedPropertyName("/environment/ridge-lift/probe-elev-m", i ); + fgUntie( prop.c_str() ); - fgUntie("/environment/ridge-lift/probe-lon-deg[0]"); - fgUntie("/environment/ridge-lift/probe-lon-deg[1]"); - fgUntie("/environment/ridge-lift/probe-lon-deg[2]"); - fgUntie("/environment/ridge-lift/probe-lon-deg[3]"); - fgUntie("/environment/ridge-lift/probe-lon-deg[4]"); + prop = CreateIndexedPropertyName("/environment/ridge-lift/probe-lat-deg", i ); + fgUntie( prop.c_str() ); - fgUntie("/environment/ridge-lift/slope[0]"); - fgUntie("/environment/ridge-lift/slope[1]"); - fgUntie("/environment/ridge-lift/slope[2]"); - fgUntie("/environment/ridge-lift/slope[3]"); - + prop = CreateIndexedPropertyName("/environment/ridge-lift/probe-lon-deg", i ); + fgUntie( prop.c_str() ); + } + + for( int i = 0; i < 4; i++ ) { + prop = CreateIndexedPropertyName("/environment/ridge-lift/slope", i ); + fgUntie( prop.c_str() ); + } } void FGRidgeLift::update(double dt) { - Run(dt); -} -double FGRidgeLift::sign(double x) { - if (x == 0.0) - return x; - else - return x/fabs(x); -} - -void FGRidgeLift::Run(double dt) { - - // copy values - - user_latitude_deg = _user_latitude_node->getDoubleValue(); - user_longitude_deg = _user_longitude_node->getDoubleValue(); - //user_altitude_ft = _user_altitude_ft_node->getDoubleValue(); - - if ( ( _earth_radius_node->getDoubleValue() ) > 1.0 ) { - earth_rad_ft =_earth_radius_node->getDoubleValue(); } - else { earth_rad_ft=20899773.07; } - - //earth_rad_m = earth_rad_ft * 0.3048 ; - earth_rad_m = earth_rad_ft * SG_FEET_TO_METER ; - //get the windspeed at ground level - double ground_wind_from_deg = _surface_wind_from_deg_node->getDoubleValue(); - double ground_wind_speed_kts = _surface_wind_speed_node->getDoubleValue(); - //double ground_wind_speed_mps = ground_wind_speed_kts / SG_METER_TO_FEET; - double ground_wind_speed_mps = ground_wind_speed_kts / 3.2808399; + double ground_wind_from_rad = _surface_wind_from_deg_node->getDoubleValue() * SG_DEGREES_TO_RADIANS; + double ground_wind_speed_mps = _surface_wind_speed_node->getDoubleValue() * SG_NM_TO_METER / 3600; - //double ground_wind_from_rad = (user_longitude_deg < 0.0) ? - // PI*( ground_wind_from_deg/180.0) +PI : PI*( ground_wind_from_deg/180.0); - double ground_wind_from_rad = PI*( ground_wind_from_deg/180.0); - - // Placing the probes - - for (int i = 0; i <= 4; i++) - { - probe_lat_rad[i] = asin(sin(deg2rad*user_latitude_deg)*cos(dist_probe_m[i]/earth_rad_m) - +cos(deg2rad*user_latitude_deg)*sin(dist_probe_m[i]/earth_rad_m)*cos(ground_wind_from_rad)); - if (probe_lat_rad[i] == 0.0) { - probe_lon_rad[i] = (deg2rad*user_latitude_deg); // probe on a pole - } - else { - probe_lon_rad[i] = fmod((deg2rad*user_longitude_deg+asin(sin(ground_wind_from_rad) - *sin(dist_probe_m[i]/earth_rad_m)/cos(probe_lat_rad[i]))+PI) - ,(2.0*PI))-PI; - } - probe_lat_deg[i]= rad2deg*probe_lat_rad[i]; - probe_lon_deg[i]= rad2deg*probe_lon_rad[i]; - } - - // ground elevations - // every second - timer -= dt; if (timer <= 0.0 ) { - for (int i = 0; i <= 4; i++) - { - if (globals->get_scenery()->get_elevation_m(SGGeod::fromGeodM( - SGGeod::fromRad(probe_lon_rad[i],probe_lat_rad[i]), 20000), alt, 0)) - { - if ( alt > 0.1 ) { probe_elev_m[i] = alt; } else { probe_elev_m[i] = 0.1 ;}; - } - else { probe_elev_m[i] = 0.1;}; - } - timer = 1.0; - - } + // copy values - // slopes + double user_latitude_rad = _user_latitude_node->getDoubleValue() * SG_DEGREES_TO_RADIANS; + double user_longitude_rad = _user_longitude_node->getDoubleValue() * SG_DEGREES_TO_RADIANS; - double adj_slope[4]; + double earth_rad_m = _earth_radius_node->getDoubleValue() * SG_FEET_TO_METER; + if( earth_rad_m < SG_EPSILON ) + earth_rad_m = SG_EARTH_RAD * 1000; + + // Placing the probes - slope[0] = (probe_elev_m[0] - probe_elev_m[1]) / dist_probe_m[1]; - slope[1] = (probe_elev_m[1] - probe_elev_m[2]) / dist_probe_m[2]; - slope[2] = (probe_elev_m[2] - probe_elev_m[3]) / dist_probe_m[3]; - slope[3] = (probe_elev_m[4] - probe_elev_m[0]) / -dist_probe_m[4]; + for (int i = 0; i < sizeof(probe_lat_rad)/sizeof(probe_lat_rad[0]); i++) { + double probe_radius_ratio = dist_probe_m[i]/earth_rad_m; + + probe_lat_rad[i] = asin(sin(user_latitude_rad)*cos(probe_radius_ratio) + +cos(user_latitude_rad)*sin(probe_radius_ratio)*cos(ground_wind_from_rad)); + if (probe_lat_rad[i] < SG_EPSILON ) { + probe_lon_rad[i] = user_latitude_rad; // probe on a pole + } else { + probe_lon_rad[i] = fmod((user_longitude_rad+asin(sin(ground_wind_from_rad) + *sin(probe_radius_ratio)/cos(probe_lat_rad[i]))+SG_PI) + ,SGD_2PI)-SG_PI; + } + probe_lat_deg[i]= probe_lat_rad[i] * SG_RADIANS_TO_DEGREES; + probe_lon_deg[i]= probe_lon_rad[i] * SG_RADIANS_TO_DEGREES; + } - for (int i = 0; i < 4; i++) - { - adj_slope[i] = sin(atan(5.0 * pow ( (fabs(slope[i])),1.7) ) ) *sign(slope[i]); + for (int i = 0; i < sizeof(probe_elev_m)/sizeof(probe_elev_m[0]); i++) { + if (globals->get_scenery()->get_elevation_m(SGGeod::fromGeodM( + SGGeod::fromRad(probe_lon_rad[i],probe_lat_rad[i]), 20000), alt, 0)) { + if ( alt > 0.1 ) { + probe_elev_m[i] = alt; + } else { + probe_elev_m[i] = 0.1 ; + } + } else { + probe_elev_m[i] = 0.1; + } + } + + // slopes + double adj_slope[4]; + slope[0] = (probe_elev_m[0] - probe_elev_m[1]) / dist_probe_m[1]; + slope[1] = (probe_elev_m[1] - probe_elev_m[2]) / dist_probe_m[2]; + slope[2] = (probe_elev_m[2] - probe_elev_m[3]) / dist_probe_m[3]; + slope[3] = (probe_elev_m[4] - probe_elev_m[0]) / -dist_probe_m[4]; + + for (int i = 0; i < sizeof(slope)/sizeof(slope[0]); i++) + adj_slope[i] = sin(atan(5.0 * pow ( (fabs(slope[i])),1.7) ) ) *sign(slope[i]); + + //adjustment + adj_slope[0] = 0.2 * adj_slope[0]; + adj_slope[1] = 0.2 * adj_slope[1]; + if ( adj_slope [2] < 0.0 ) { + adj_slope[2] = 0.5 * adj_slope[2]; + } else { + adj_slope[2] = 0.0 ; + } + + if ( ( adj_slope [0] >= 0.0 ) && ( adj_slope [3] < 0.0 ) ) { + adj_slope[3] = 0.0; + } else { + adj_slope[3] = 0.2 * adj_slope[3]; + } + lift_factor = adj_slope[0]+adj_slope[1]+adj_slope[2]+adj_slope[3]; + + // restart the timer + timer = 1.0; } - //adjustment - - adj_slope[0] = 0.2 * adj_slope[0]; - adj_slope[1] = 0.2 * adj_slope[1]; - if ( adj_slope [2] < 0.0 ) - { - adj_slope[2] = 0.5 * adj_slope[2]; - } - else - { - adj_slope[2] = 0.0 ; - } - - if ( ( adj_slope [0] >= 0.0 ) && ( adj_slope [3] < 0.0 ) ) - { - adj_slope[3] = 0.0; - } - else - { - adj_slope[3] = 0.2 * adj_slope[3]; - } - - double lift_factor = adj_slope[0]+adj_slope[1]+adj_slope[2]+adj_slope[3]; - //user altitude above ground - - user_altitude_agl_ft = _user_altitude_agl_ft_node->getDoubleValue(); - user_altitude_agl_m = ( user_altitude_agl_ft / SG_METER_TO_FEET ); + double user_altitude_agl_m = _user_altitude_agl_ft_node->getDoubleValue() * SG_FEET_TO_METER; //boundaries - double agl_factor; - - if (lift_factor < 0.0) // in the sink - { + double boundary2_m = 130.0; // in the lift + if (lift_factor < 0.0) { // in the sink double highest_probe_temp= max ( probe_elev_m[1], probe_elev_m[2] ); double highest_probe_downwind_m= max ( highest_probe_temp, probe_elev_m[3] ); - BOUNDARY2_m = highest_probe_downwind_m - probe_elev_m[0]; - } - else // in the lift - { - BOUNDARY2_m = 130.0; + boundary2_m = highest_probe_downwind_m - probe_elev_m[0]; } - if ( user_altitude_agl_m < BOUNDARY1_m ) - { + double agl_factor; + if ( user_altitude_agl_m < BOUNDARY1_m ) { agl_factor = 0.5+0.5*user_altitude_agl_m /BOUNDARY1_m ; - } - else if ( user_altitude_agl_m < BOUNDARY2_m ) - { + } else if ( user_altitude_agl_m < boundary2_m ) { agl_factor = 1.0; - } - else - { - agl_factor = exp(-(2 + 2 * probe_elev_m[0] / 4000) * - (user_altitude_agl_m - BOUNDARY2_m) / max(probe_elev_m[0],200.0)); + } else { + agl_factor = exp(-(2 + probe_elev_m[0] / 2000) * + (user_altitude_agl_m - boundary2_m) / max(probe_elev_m[0],200.0)); } double lift_mps = lift_factor* ground_wind_speed_mps * agl_factor; //the updraft, finally, in ft per second - strength = lift_mps * SG_METER_TO_FEET ; + strength = fgGetLowPass( strength, lift_mps * SG_METER_TO_FEET, dt ); // if(isnan(strength)) strength=0; _ridge_lift_fps_node->setDoubleValue( strength ); } - - - - - - diff --git a/src/Environment/ridge_lift.hxx b/src/Environment/ridge_lift.hxx index c6f49ecf2..a4768d8de 100644 --- a/src/Environment/ridge_lift.hxx +++ b/src/Environment/ridge_lift.hxx @@ -50,41 +50,15 @@ public: inline double getStrength() const { return strength; }; - inline double get_probe_elev_m_0() const { return probe_elev_m[0]; }; - inline double get_probe_elev_m_1() const { return probe_elev_m[1]; }; - inline double get_probe_elev_m_2() const { return probe_elev_m[2]; }; - inline double get_probe_elev_m_3() const { return probe_elev_m[3]; }; - inline double get_probe_elev_m_4() const { return probe_elev_m[4]; }; - - inline double get_probe_lat_0() const { return probe_lat_deg[0]; }; - inline double get_probe_lat_1() const { return probe_lat_deg[1]; }; - inline double get_probe_lat_2() const { return probe_lat_deg[2]; }; - inline double get_probe_lat_3() const { return probe_lat_deg[3]; }; - inline double get_probe_lat_4() const { return probe_lat_deg[4]; }; - - inline double get_probe_lon_0() const { return probe_lon_deg[0]; }; - inline double get_probe_lon_1() const { return probe_lon_deg[1]; }; - inline double get_probe_lon_2() const { return probe_lon_deg[2]; }; - inline double get_probe_lon_3() const { return probe_lon_deg[3]; }; - inline double get_probe_lon_4() const { return probe_lon_deg[4]; }; - - inline double get_slope_0() const { return slope[0]; }; - inline double get_slope_1() const { return slope[1]; }; - inline double get_slope_2() const { return slope[2]; }; - inline double get_slope_3() const { return slope[3]; }; + inline double get_probe_elev_m( int index ) const { return probe_elev_m[index]; }; + inline double get_probe_lat_deg( int index ) const { return probe_lat_deg[index]; }; + inline double get_probe_lon_deg( int index ) const { return probe_lon_deg[index]; }; + inline double get_slope( int index ) const { return slope[index]; }; private: //void init(); - void Run(double dt); double dist_probe_m[5]; - double BOUNDARY1_m; - double BOUNDARY2_m; - double PI; // pi - double deg2rad; - double rad2deg; - - bool scanned; double strength; double timer; @@ -99,15 +73,13 @@ private: double probe_elev_m[5]; double slope[4]; - double earth_rad_ft; - double earth_rad_m; - double user_latitude_deg; - double user_longitude_deg; - //double user_altitude; - double user_altitude_agl_ft; - double user_altitude_agl_m; - double sign(double x); + double lift_factor; + + inline double sign(double x) const { + if( x == 0 ) return 0; + return x > 0 ? 1.0 : -1.0; + } SGPropertyNode_ptr _ridge_lift_fps_node; @@ -122,4 +94,4 @@ private: }; -#endif // _FG_RidgeLift_HXX \ No newline at end of file +#endif // _FG_RidgeLift_HXX