Some terrainsampler improvements
- use max. computation time instead of max computations per frame - restart computation of an area only after significant movememt - let the area move with a heading and a speed
This commit is contained in:
parent
52ac173257
commit
b2f8238696
1 changed files with 121 additions and 75 deletions
196
src/Environment/terrainsampler.cxx
Executable file → Normal file
196
src/Environment/terrainsampler.cxx
Executable file → Normal file
|
@ -40,14 +40,13 @@ namespace Environment {
|
||||||
*/
|
*/
|
||||||
class AreaSampler : public SGSubsystem {
|
class AreaSampler : public SGSubsystem {
|
||||||
public:
|
public:
|
||||||
AreaSampler( SGPropertyNode_ptr rootNode );
|
AreaSampler( SGPropertyNode_ptr rootNode );
|
||||||
virtual ~AreaSampler();
|
virtual ~AreaSampler();
|
||||||
void update( double dt );
|
void update( double dt );
|
||||||
void bind();
|
void bind();
|
||||||
void unbind();
|
void unbind();
|
||||||
|
void init();
|
||||||
double getOrientationDeg() const { return _orientation_rad * SG_RADIANS_TO_DEGREES; }
|
void reinit();
|
||||||
void setOrientationDeg( double value ) { _orientation_rad = value * SG_DEGREES_TO_RADIANS; }
|
|
||||||
|
|
||||||
int getElevationHistogramStep() const { return _elevationHistogramStep; }
|
int getElevationHistogramStep() const { return _elevationHistogramStep; }
|
||||||
void setElevationHistograpStep( int value ) {
|
void setElevationHistograpStep( int value ) {
|
||||||
|
@ -70,27 +69,30 @@ private:
|
||||||
|
|
||||||
bool _enabled;
|
bool _enabled;
|
||||||
bool _useAircraftPosition;
|
bool _useAircraftPosition;
|
||||||
double _latitude_deg;
|
double _heading_deg;
|
||||||
double _longitude_deg;
|
double _speed_kt;
|
||||||
double _orientation_rad;
|
int _radius;
|
||||||
int _radius;
|
double _max_computation_time_norm;
|
||||||
int _samples_per_frame;
|
|
||||||
int _max_samples; // keep xx samples in queue for analysis
|
int _max_samples; // keep xx samples in queue for analysis
|
||||||
int _analyze_every; // Run analysis every xx samples
|
double _reuse_samples_norm;
|
||||||
|
double _recalc_distance_norm;
|
||||||
int _elevationHistogramMax;
|
int _elevationHistogramMax;
|
||||||
int _elevationHistogramStep;
|
int _elevationHistogramStep;
|
||||||
int _elevationHistogramCount;
|
int _elevationHistogramCount;
|
||||||
|
SGGeod _inputPosition;
|
||||||
|
|
||||||
double _altOffset;
|
double _altOffset;
|
||||||
double _altMedian;
|
double _altMedian;
|
||||||
double _altMin;
|
double _altMin;
|
||||||
double _altLayered;
|
double _altLayered;
|
||||||
double _altMean;
|
double _altMean;
|
||||||
|
SGGeod _outputPosition;
|
||||||
|
|
||||||
|
SGPropertyNode_ptr _signalNode;
|
||||||
SGPropertyNode_ptr _positionLatitudeNode;
|
SGPropertyNode_ptr _positionLatitudeNode;
|
||||||
SGPropertyNode_ptr _positionLongitudeNode;
|
SGPropertyNode_ptr _positionLongitudeNode;
|
||||||
|
|
||||||
deque<double> elevations;
|
deque<double> _elevations;
|
||||||
TiedPropertyList _tiedProperties;
|
TiedPropertyList _tiedProperties;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -98,13 +100,13 @@ AreaSampler::AreaSampler( SGPropertyNode_ptr rootNode ) :
|
||||||
_rootNode(rootNode),
|
_rootNode(rootNode),
|
||||||
_enabled(true),
|
_enabled(true),
|
||||||
_useAircraftPosition(false),
|
_useAircraftPosition(false),
|
||||||
_latitude_deg(0.0),
|
_heading_deg(0.0),
|
||||||
_longitude_deg(0.0),
|
_speed_kt(0.0),
|
||||||
_orientation_rad(0.0),
|
_radius(40000.0),
|
||||||
_radius(40000.0),
|
_max_computation_time_norm(0.1),
|
||||||
_samples_per_frame(5),
|
|
||||||
_max_samples(1000),
|
_max_samples(1000),
|
||||||
_analyze_every(200),
|
_reuse_samples_norm(0.8),
|
||||||
|
_recalc_distance_norm(0.1),
|
||||||
_elevationHistogramMax(10000),
|
_elevationHistogramMax(10000),
|
||||||
_elevationHistogramStep(500),
|
_elevationHistogramStep(500),
|
||||||
_elevationHistogramCount(_elevationHistogramMax/_elevationHistogramStep),
|
_elevationHistogramCount(_elevationHistogramMax/_elevationHistogramStep),
|
||||||
|
@ -112,10 +114,12 @@ AreaSampler::AreaSampler( SGPropertyNode_ptr rootNode ) :
|
||||||
_altMedian(0),
|
_altMedian(0),
|
||||||
_altMin(0),
|
_altMin(0),
|
||||||
_altLayered(0),
|
_altLayered(0),
|
||||||
_altMean(0)
|
_altMean(0),
|
||||||
|
_signalNode(rootNode->getNode("output/valid", true )),
|
||||||
|
_positionLatitudeNode(fgGetNode( "/position/latitude-deg", true )),
|
||||||
|
_positionLongitudeNode(fgGetNode( "/position/longitude-deg", true ))
|
||||||
{
|
{
|
||||||
_positionLatitudeNode = fgGetNode( "/position/latitude-deg", true );
|
_inputPosition.setElevationM( SG_MAX_ELEVATION_M );
|
||||||
_positionLongitudeNode = fgGetNode( "/position/longitude-deg", true );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AreaSampler::~AreaSampler()
|
AreaSampler::~AreaSampler()
|
||||||
|
@ -130,14 +134,15 @@ void AreaSampler::bind()
|
||||||
|
|
||||||
_tiedProperties.setRoot( _rootNode->getNode( "input", true ) );
|
_tiedProperties.setRoot( _rootNode->getNode( "input", true ) );
|
||||||
_tiedProperties.Tie( "use-aircraft-position", &_useAircraftPosition );
|
_tiedProperties.Tie( "use-aircraft-position", &_useAircraftPosition );
|
||||||
_tiedProperties.Tie( "latitude-deg", &_latitude_deg );
|
_tiedProperties.Tie( "latitude-deg", &_inputPosition, &SGGeod::getLatitudeDeg, &SGGeod::setLatitudeDeg );
|
||||||
_tiedProperties.Tie( "latitude-deg", &_latitude_deg );
|
_tiedProperties.Tie( "longitude-deg", &_inputPosition, &SGGeod::getLongitudeDeg, &SGGeod::setLongitudeDeg );
|
||||||
_tiedProperties.Tie( "longitude-deg", &_longitude_deg );
|
_tiedProperties.Tie( "heading-deg", &_heading_deg );
|
||||||
_tiedProperties.Tie( "orientation-deg", this, &AreaSampler::getOrientationDeg, &AreaSampler::setOrientationDeg );
|
_tiedProperties.Tie( "speed-kt", &_speed_kt );
|
||||||
_tiedProperties.Tie( "radius-m", &_radius );
|
_tiedProperties.Tie( "radius-m", &_radius );
|
||||||
_tiedProperties.Tie( "max-samples-per-frame", &_samples_per_frame );
|
_tiedProperties.Tie( "max-computation-time-norm", &_max_computation_time_norm );
|
||||||
_tiedProperties.Tie( "max-samples", &_max_samples );
|
_tiedProperties.Tie( "max-samples", &_max_samples );
|
||||||
_tiedProperties.Tie( "analyse-every", &_analyze_every );
|
_tiedProperties.Tie( "reuse-samples-norm", &_reuse_samples_norm );
|
||||||
|
_tiedProperties.Tie( "recalc-distance-norm", &_recalc_distance_norm );
|
||||||
_tiedProperties.Tie( "elevation-histogram-max-ft", this, &AreaSampler::getElevationHistogramMax, &AreaSampler::setElevationHistograpMax );
|
_tiedProperties.Tie( "elevation-histogram-max-ft", this, &AreaSampler::getElevationHistogramMax, &AreaSampler::setElevationHistograpMax );
|
||||||
_tiedProperties.Tie( "elevation-histogram-step-ft", this, &AreaSampler::getElevationHistogramStep, &AreaSampler::setElevationHistograpStep );
|
_tiedProperties.Tie( "elevation-histogram-step-ft", this, &AreaSampler::getElevationHistogramStep, &AreaSampler::setElevationHistograpStep );
|
||||||
_tiedProperties.Tie( "elevation-histogram-count", this, &AreaSampler::getElevationHistogramCount );
|
_tiedProperties.Tie( "elevation-histogram-count", this, &AreaSampler::getElevationHistogramCount );
|
||||||
|
@ -148,6 +153,9 @@ void AreaSampler::bind()
|
||||||
_tiedProperties.Tie( "alt-min-ft", &_altMin );
|
_tiedProperties.Tie( "alt-min-ft", &_altMin );
|
||||||
_tiedProperties.Tie( "alt-layered-ft", &_altLayered );
|
_tiedProperties.Tie( "alt-layered-ft", &_altLayered );
|
||||||
_tiedProperties.Tie( "alt-mean-ft", &_altMean );
|
_tiedProperties.Tie( "alt-mean-ft", &_altMean );
|
||||||
|
_tiedProperties.Tie( "longitude-deg", &_outputPosition, &SGGeod::getLongitudeDeg );
|
||||||
|
_tiedProperties.Tie( "latitude-deg", &_outputPosition, &SGGeod::getLatitudeDeg );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AreaSampler::unbind()
|
void AreaSampler::unbind()
|
||||||
|
@ -155,45 +163,90 @@ void AreaSampler::unbind()
|
||||||
_tiedProperties.Untie();
|
_tiedProperties.Untie();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AreaSampler::init()
|
||||||
|
{
|
||||||
|
_signalNode->setBoolValue(false);
|
||||||
|
_elevations.clear();
|
||||||
|
_altOffset = 0.0;
|
||||||
|
_altMedian = 0.0;
|
||||||
|
_altMin = 0.0;
|
||||||
|
_altLayered = 0.0;
|
||||||
|
_altMean = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AreaSampler::reinit()
|
||||||
|
{
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
void AreaSampler::update( double dt )
|
void AreaSampler::update( double dt )
|
||||||
{
|
{
|
||||||
if( !(_enabled && dt > SGLimitsd::min()) )
|
// if not enabled or time has stalled, do nothing
|
||||||
|
if( !(_enabled && dt > SGLimitsd::min()) )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if( _useAircraftPosition ) {
|
// get the aircraft's position if requested
|
||||||
_longitude_deg = _positionLongitudeNode->getDoubleValue();
|
if( _useAircraftPosition && _speed_kt < 0.5 ) {
|
||||||
_latitude_deg = _positionLatitudeNode->getDoubleValue();
|
_inputPosition = SGGeod::fromDegM(
|
||||||
|
_positionLongitudeNode->getDoubleValue(),
|
||||||
|
_positionLatitudeNode->getDoubleValue(),
|
||||||
|
SG_MAX_ELEVATION_M );
|
||||||
}
|
}
|
||||||
|
|
||||||
SGGeoc center = SGGeoc::fromGeod( SGGeod::fromDegM( _longitude_deg, _latitude_deg, SG_MAX_ELEVATION_M ) );
|
// need geocentric coordinates
|
||||||
|
SGGeoc center = SGGeoc::fromGeod( _inputPosition );
|
||||||
|
|
||||||
|
// if a speed is set, move the input position
|
||||||
|
if( _speed_kt >= 0.5 ) {
|
||||||
|
double distance_m = _speed_kt * dt * SG_NM_TO_METER;
|
||||||
|
center = center.advanceRadM( _heading_deg * SG_DEGREES_TO_RADIANS, distance_m );
|
||||||
|
_inputPosition = SGGeod::fromGeoc( center );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( _signalNode->getBoolValue() ) {
|
||||||
|
// if we had finished the iteration and moved more than 10% of the radius
|
||||||
|
// of the sampling area, drop the oldest samples and continue sampling
|
||||||
|
if( SGGeoc::distanceM( center, SGGeoc::fromGeod(_outputPosition ) ) >= _recalc_distance_norm * _radius ) {
|
||||||
|
_elevations.resize( _max_samples * _reuse_samples_norm );
|
||||||
|
_signalNode->setBoolValue( false );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( _signalNode->getBoolValue() )
|
||||||
|
return; // nothing to do.
|
||||||
|
|
||||||
FGScenery * scenery = globals->get_scenery();
|
FGScenery * scenery = globals->get_scenery();
|
||||||
for( int i = 0;
|
|
||||||
i < _samples_per_frame;
|
|
||||||
i++ ) {
|
|
||||||
|
|
||||||
double distance = sg_random() * _radius;
|
SGTimeStamp start = SGTimeStamp::now();
|
||||||
double course = sg_random() * 2.0 * SG_PI;
|
while( (SGTimeStamp::now() - start).toSecs() < dt * _max_computation_time_norm ) {
|
||||||
SGGeod probe = SGGeod::fromGeoc(center.advanceRadM( course, distance ));
|
// sample until we used up all our configured time
|
||||||
double elevation_m = 0.0;
|
double distance = sg_random();
|
||||||
if (scenery->get_elevation_m( probe, elevation_m, NULL ))
|
distance = _radius * (1-distance*distance);
|
||||||
elevations.push_front(elevation_m *= SG_METER_TO_FEET);
|
double course = sg_random() * 2.0 * SG_PI;
|
||||||
|
SGGeod probe = SGGeod::fromGeoc(center.advanceRadM( course, distance ));
|
||||||
|
double elevation_m = 0.0;
|
||||||
|
|
||||||
|
if (scenery->get_elevation_m( probe, elevation_m, NULL ))
|
||||||
|
_elevations.push_front(elevation_m *= SG_METER_TO_FEET);
|
||||||
|
|
||||||
if( elevations.size() >= (deque<unsigned>::size_type)_max_samples ) {
|
if( _elevations.size() >= (deque<unsigned>::size_type)_max_samples ) {
|
||||||
|
// sampling complete?
|
||||||
analyse();
|
analyse();
|
||||||
elevations.resize( _max_samples - _analyze_every );
|
_outputPosition = _inputPosition;
|
||||||
|
_signalNode->setBoolValue( true );
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AreaSampler::analyse()
|
void AreaSampler::analyse()
|
||||||
{
|
{
|
||||||
double sum;
|
double sum;
|
||||||
|
|
||||||
vector<int> histogram(_elevationHistogramCount,0);
|
vector<int> histogram(_elevationHistogramCount,0);
|
||||||
|
|
||||||
for( deque<double>::size_type i = 0; i < elevations.size(); i++ ) {
|
for( deque<double>::size_type i = 0; i < _elevations.size(); i++ ) {
|
||||||
int idx = SGMisc<int>::clip( (int)(elevations[i]/_elevationHistogramStep), 0, histogram.size()-1 );
|
int idx = SGMisc<int>::clip( (int)(_elevations[i]/_elevationHistogramStep), 0, histogram.size()-1 );
|
||||||
histogram[idx]++;
|
histogram[idx]++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -201,7 +254,7 @@ void AreaSampler::analyse()
|
||||||
sum = 0.0;
|
sum = 0.0;
|
||||||
for( vector<int>::size_type i = 0; i < histogram.size(); i++ ) {
|
for( vector<int>::size_type i = 0; i < histogram.size(); i++ ) {
|
||||||
sum += histogram[i];
|
sum += histogram[i];
|
||||||
if( sum > 0.5 * elevations.size() ) {
|
if( sum > 0.5 * _elevations.size() ) {
|
||||||
_altMedian = i * _elevationHistogramStep;
|
_altMedian = i * _elevationHistogramStep;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -211,7 +264,7 @@ void AreaSampler::analyse()
|
||||||
sum = 0.0;
|
sum = 0.0;
|
||||||
for( vector<int>::size_type i = 0; i < histogram.size(); i++ ) {
|
for( vector<int>::size_type i = 0; i < histogram.size(); i++ ) {
|
||||||
sum += histogram[i];
|
sum += histogram[i];
|
||||||
if( sum > 0.3 * elevations.size() ) {
|
if( sum > 0.3 * _elevations.size() ) {
|
||||||
_altOffset = i * _elevationHistogramStep;
|
_altOffset = i * _elevationHistogramStep;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -222,7 +275,7 @@ void AreaSampler::analyse()
|
||||||
_altMean += histogram[i] * i;
|
_altMean += histogram[i] * i;
|
||||||
}
|
}
|
||||||
_altMean *= _elevationHistogramStep;
|
_altMean *= _elevationHistogramStep;
|
||||||
if( elevations.size() != 0.0 ) _altMean /= elevations.size();
|
if( _elevations.size() != 0.0 ) _altMean /= _elevations.size();
|
||||||
|
|
||||||
_altMin = 0.0;
|
_altMin = 0.0;
|
||||||
for( vector<int>::size_type i = 0; i < histogram.size(); i++ ) {
|
for( vector<int>::size_type i = 0; i < histogram.size(); i++ ) {
|
||||||
|
@ -238,7 +291,7 @@ void AreaSampler::analyse()
|
||||||
for( vector<int>::size_type i = 0; i < histogram.size()-1; i++ ) {
|
for( vector<int>::size_type i = 0; i < histogram.size()-1; i++ ) {
|
||||||
sum += histogram[i];
|
sum += histogram[i];
|
||||||
if( histogram[i] > n_max ) n_max = histogram[i];
|
if( histogram[i] > n_max ) n_max = histogram[i];
|
||||||
if( n_max > histogram[i+1] && sum > 0.3*elevations.size()) {
|
if( n_max > histogram[i+1] && sum > 0.3*_elevations.size()) {
|
||||||
alt_low_min = i * _elevationHistogramStep;
|
alt_low_min = i * _elevationHistogramStep;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -246,14 +299,6 @@ void AreaSampler::analyse()
|
||||||
|
|
||||||
_altLayered = 0.5 * (_altMin + _altOffset);
|
_altLayered = 0.5 * (_altMin + _altOffset);
|
||||||
|
|
||||||
#if 0
|
|
||||||
SG_LOG( SG_ALL, SG_ALERT, "TerrainPresampler - alalysis results:" <<
|
|
||||||
" total:" << elevations.size() <<
|
|
||||||
" mean:" << _altMean <<
|
|
||||||
" median:" << _altMedian <<
|
|
||||||
" min:" << _altMin <<
|
|
||||||
" alt_20:" << _altOffset );
|
|
||||||
#endif
|
|
||||||
#if 0
|
#if 0
|
||||||
append(alt_50_array, alt_med);
|
append(alt_50_array, alt_med);
|
||||||
#endif
|
#endif
|
||||||
|
@ -266,14 +311,15 @@ append(alt_50_array, alt_med);
|
||||||
class TerrainSamplerImplementation : public TerrainSampler
|
class TerrainSamplerImplementation : public TerrainSampler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TerrainSamplerImplementation ( SGPropertyNode_ptr rootNode );
|
TerrainSamplerImplementation ( SGPropertyNode_ptr rootNode );
|
||||||
virtual ~TerrainSamplerImplementation ();
|
virtual ~TerrainSamplerImplementation ();
|
||||||
|
|
||||||
virtual void init ();
|
virtual void init ();
|
||||||
virtual void reinit ();
|
virtual void postinit();
|
||||||
|
virtual void reinit ();
|
||||||
virtual void bind();
|
virtual void bind();
|
||||||
virtual void unbind();
|
virtual void unbind();
|
||||||
virtual void update (double delta_time_sec);
|
virtual void update (double delta_time_sec);
|
||||||
private:
|
private:
|
||||||
inline string areaSubsystemName( unsigned i ) {
|
inline string areaSubsystemName( unsigned i ) {
|
||||||
ostringstream name;
|
ostringstream name;
|
||||||
|
@ -281,7 +327,7 @@ private:
|
||||||
return name.str();
|
return name.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
SGPropertyNode_ptr _rootNode;
|
SGPropertyNode_ptr _rootNode;
|
||||||
bool _enabled;
|
bool _enabled;
|
||||||
TiedPropertyList _tiedProperties;
|
TiedPropertyList _tiedProperties;
|
||||||
};
|
};
|
||||||
|
@ -303,10 +349,14 @@ void TerrainSamplerImplementation::init()
|
||||||
for( PropertyList::size_type i = 0; i < areaNodes.size(); i++ )
|
for( PropertyList::size_type i = 0; i < areaNodes.size(); i++ )
|
||||||
set_subsystem( areaSubsystemName(i), new AreaSampler( areaNodes[i] ) );
|
set_subsystem( areaSubsystemName(i), new AreaSampler( areaNodes[i] ) );
|
||||||
|
|
||||||
SGSubsystemGroup::bind();// bind the subsystems before the get init()ed
|
|
||||||
SGSubsystemGroup::init();
|
SGSubsystemGroup::init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TerrainSamplerImplementation::postinit()
|
||||||
|
{
|
||||||
|
SGSubsystemGroup::bind();//
|
||||||
|
}
|
||||||
|
|
||||||
void TerrainSamplerImplementation::reinit()
|
void TerrainSamplerImplementation::reinit()
|
||||||
{
|
{
|
||||||
for( unsigned i = 0;; i++ ) {
|
for( unsigned i = 0;; i++ ) {
|
||||||
|
@ -334,8 +384,8 @@ void TerrainSamplerImplementation::unbind()
|
||||||
|
|
||||||
void TerrainSamplerImplementation::update( double dt )
|
void TerrainSamplerImplementation::update( double dt )
|
||||||
{
|
{
|
||||||
if( !(_enabled && dt > SGLimitsd::min()) )
|
if( !(_enabled && dt > SGLimitsd::min()) )
|
||||||
return;
|
return;
|
||||||
SGSubsystemGroup::update(dt);
|
SGSubsystemGroup::update(dt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -343,13 +393,9 @@ void TerrainSamplerImplementation::update( double dt )
|
||||||
|
|
||||||
/* implementation of the TerrainSampler factory to hide the implementation
|
/* implementation of the TerrainSampler factory to hide the implementation
|
||||||
details */
|
details */
|
||||||
TerrainSampler::~TerrainSampler ()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
TerrainSampler * TerrainSampler::createInstance( SGPropertyNode_ptr rootNode )
|
TerrainSampler * TerrainSampler::createInstance( SGPropertyNode_ptr rootNode )
|
||||||
{
|
{
|
||||||
return new TerrainSamplerImplementation( rootNode );
|
return new TerrainSamplerImplementation( rootNode );
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
Loading…
Add table
Reference in a new issue