X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FEnvironment%2Fridge_lift.cxx;h=cac1388aa90dfb6644c5f2aa4df6d959e4f5707f;hb=c71c9aee0a321192d01f89f161cbdbd6112491b6;hp=fa121a1a5ca5f984d065ac4063aae7d6cfc9dec4;hpb=1ce2924c28da536dd7d0830f505eb6566fdd67a1;p=flightgear.git diff --git a/src/Environment/ridge_lift.cxx b/src/Environment/ridge_lift.cxx index fa121a1a5..cac1388aa 100644 --- a/src/Environment/ridge_lift.cxx +++ b/src/Environment/ridge_lift.cxx @@ -36,38 +36,32 @@ #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 inline double sign(double x) { - return x == 0 ? 0 : x > 0 ? 1.0 : -1.0; -} +static const double BOUNDARY1_m = 40.0; -static const double BOUNDARY1_m = 40.0; +const double FGRidgeLift::dist_probe_m[] = { // in meters + 0.0, + 250.0, + 750.0, + 2000.0, + -100.0 +}; //constructor FGRidgeLift::FGRidgeLift () { - dist_probe_m[0] = 0.0; // in meters - dist_probe_m[1] = 250.0; - dist_probe_m[2] = 750.0; - dist_probe_m[3] = 2000.0; - dist_probe_m[4] = -100.0; - strength = 0.0; timer = 0.0; + for( int i = 0; i < 5; i++ ) + probe_elev_m[i] = probe_lat_deg[i] = probe_lon_deg[i] = 0.0; + + for( int i = 0; i < 4; i++ ) + slope[i] = 0.0; } //destructor @@ -78,6 +72,8 @@ FGRidgeLift::~FGRidgeLift() void FGRidgeLift::init(void) { + _enabled_node = fgGetNode( "/environment/ridge-lift/enabled", false ); + _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" @@ -85,119 +81,91 @@ void FGRidgeLift::init(void) _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); + _ground_elev_node = fgGetNode("/position/ground-elev-ft", true ); } void FGRidgeLift::bind() { string prop; + _tiedProperties.setRoot( fgGetNode("/environment/ridge-lift",true)); 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 - - prop = CreateIndexedPropertyName("/environment/ridge-lift/probe-lat-deg", i ); - fgTie( prop.c_str(), this, i, &FGRidgeLift::get_probe_lat_deg); // read-only - - prop = CreateIndexedPropertyName("/environment/ridge-lift/probe-lon-deg", i ); - fgTie( prop.c_str(), this, i, &FGRidgeLift::get_probe_lon_deg); // read-only + _tiedProperties.Tie( "probe-elev-m", i, this, i, &FGRidgeLift::get_probe_elev_m ); + _tiedProperties.Tie( "probe-lat-deg", i, this, i, &FGRidgeLift::get_probe_lat_deg ); + _tiedProperties.Tie( "probe-lon-deg", i, this, i, &FGRidgeLift::get_probe_lon_deg ); } 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 + _tiedProperties.Tie( "slope", i, this, i, &FGRidgeLift::get_slope ); } } void FGRidgeLift::unbind() { - string prop; - - for( int i = 0; i < 5; i++ ) { - - prop = CreateIndexedPropertyName("/environment/ridge-lift/probe-elev-m", i ); - fgUntie( prop.c_str() ); - - prop = CreateIndexedPropertyName("/environment/ridge-lift/probe-lat-deg", i ); - fgUntie( prop.c_str() ); - - 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() ); - } + _tiedProperties.Untie(); } void FGRidgeLift::update(double dt) { - //get the windspeed at ground level + if( dt <= SGLimitsd::min() ) // paused, do nothing but keep current lift + return; - 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; + if( _enabled_node && false == _enabled_node->getBoolValue() ) { + // do nothing if lift has been zeroed + if( strength != 0.0 ) { + if( strength > 0.1 ) { + // slowly fade out strong lifts + strength = fgGetLowPass( strength, 0, dt ); + } else { + strength = 0.0; + } + _ridge_lift_fps_node->setDoubleValue( strength ); + } + return; + } timer -= dt; if (timer <= 0.0 ) { - // copy values - 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 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 - - 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 < sizeof(probe_elev_m)/sizeof(probe_elev_m[0]); i++) { - double elevation = 0; - if (globals->get_scenery()->get_elevation_m(SGGeod::fromGeodM( - SGGeod::fromRad(probe_lon_rad[i],probe_lat_rad[i]), 20000), elevation, 0)) { - if ( elevation > 0.1 ) { - probe_elev_m[i] = elevation; - } else { - probe_elev_m[i] = 0.1 ; - } - } else { - probe_elev_m[i] = 0.1; + // probe0 is current position + probe_lat_deg[0] = _user_latitude_node->getDoubleValue(); + probe_lon_deg[0] = _user_longitude_node->getDoubleValue(); + probe_elev_m[0] = _ground_elev_node->getDoubleValue() * SG_FEET_TO_METER; + + // position is geodetic, need geocentric for advanceRadM + SGGeod myGeodPos = SGGeod::fromDegM( probe_lon_deg[0], probe_lat_deg[0], 20000.0 ); + SGGeoc myGeocPos = SGGeoc::fromGeod( myGeodPos ); + double ground_wind_from_rad = _surface_wind_from_deg_node->getDoubleValue() * SG_DEGREES_TO_RADIANS; + + // compute the remaining probes + for (unsigned i = 1; i < sizeof(probe_elev_m)/sizeof(probe_elev_m[0]); i++) { + SGGeoc probe = myGeocPos.advanceRadM( ground_wind_from_rad, dist_probe_m[i] ); + // convert to geodetic position for ground level computation + SGGeod probeGeod = SGGeod::fromGeoc( probe ); + probe_lat_deg[i] = probeGeod.getLatitudeDeg(); + probe_lon_deg[i] = probeGeod.getLongitudeDeg(); + if (!globals->get_scenery()->get_elevation_m( probeGeod, probe_elev_m[i], NULL )) { + // no ground found? use elevation of previous probe :-( + probe_elev_m[i] = probe_elev_m[i-1]; } } // slopes - double adj_slope[4]; + double adj_slope[sizeof(slope)]; 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]); + for (unsigned i = 0; i < sizeof(slope)/sizeof(slope[0]); i++) + adj_slope[i] = sin(atan(5.0 * pow ( (fabs(slope[i])),1.7) ) ) *SG_SIGN(slope[i]); //adjustment - adj_slope[0] = 0.2 * adj_slope[0]; - adj_slope[1] = 0.2 * adj_slope[1]; + adj_slope[0] *= 0.2; + adj_slope[1] *= 0.2; if ( adj_slope [2] < 0.0 ) { - adj_slope[2] = 0.5 * adj_slope[2]; + adj_slope[2] *= 0.5; } else { adj_slope[2] = 0.0 ; } @@ -205,7 +173,7 @@ void FGRidgeLift::update(double dt) { 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]; + adj_slope[3] *= 0.2; } lift_factor = adj_slope[0]+adj_slope[1]+adj_slope[2]+adj_slope[3]; @@ -219,8 +187,8 @@ void FGRidgeLift::update(double dt) { //boundaries 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] ); + double highest_probe_temp= std::max ( probe_elev_m[1], probe_elev_m[2] ); + double highest_probe_downwind_m= std::max ( highest_probe_temp, probe_elev_m[3] ); boundary2_m = highest_probe_downwind_m - probe_elev_m[0]; } @@ -231,13 +199,13 @@ void FGRidgeLift::update(double dt) { agl_factor = 1.0; } else { agl_factor = exp(-(2 + probe_elev_m[0] / 2000) * - (user_altitude_agl_m - boundary2_m) / max(probe_elev_m[0],200.0)); + (user_altitude_agl_m - boundary2_m) / std::max(probe_elev_m[0],200.0)); } + double ground_wind_speed_mps = _surface_wind_speed_node->getDoubleValue() * SG_NM_TO_METER / 3600; double lift_mps = lift_factor* ground_wind_speed_mps * agl_factor; //the updraft, finally, in ft per second strength = fgGetLowPass( strength, lift_mps * SG_METER_TO_FEET, dt ); -// if(isnan(strength)) strength=0; - _ridge_lift_fps_node->setDoubleValue( strength ); + _ridge_lift_fps_node->setDoubleValue( strength ); }