Skip to content

Commit

Permalink
Streaming fix (#30)
Browse files Browse the repository at this point in the history
* seems to work

* fix

* bug fix

* fix for window compilation
  • Loading branch information
facontidavide authored Mar 17, 2017
1 parent 46e1694 commit 0a13cdf
Show file tree
Hide file tree
Showing 10 changed files with 160 additions and 127 deletions.
10 changes: 6 additions & 4 deletions include/PlotJuggler/plotdata.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ template <typename Time, typename Value> class PlotDataGeneric

void setMaximumRangeX(Time max_range);

static std::mutex& asyncPushMutex() { return _mutex; }

protected:

std::string _name;
Expand All @@ -92,7 +94,7 @@ template <typename Time, typename Value> class PlotDataGeneric
private:

Time _max_range_X;
std::mutex _mutex;
static std::mutex _mutex;
};


Expand All @@ -111,6 +113,8 @@ typedef struct{

//-----------------------------------

template < typename Time, typename Value>
std::mutex PlotDataGeneric<Time, Value>::_mutex;


template < typename Time, typename Value>
Expand Down Expand Up @@ -140,16 +144,14 @@ inline void PlotDataGeneric<Time, Value>::pushBack(Point point)
template < typename Time, typename Value>
inline void PlotDataGeneric<Time, Value>::pushBackAsynchronously(Point point)
{
std::lock_guard<std::mutex> lock(_mutex);
_pushed_points.push_back( point );
while(_pushed_points.size() > ASYNC_BUFFER_CAPACITY) _pushed_points.pop_front();
}

template < typename Time, typename Value>
inline bool PlotDataGeneric<Time, Value>::flushAsyncBuffer()
{
std::lock_guard<std::mutex> lock(_mutex);

// std::lock_guard<std::mutex> lock(_mutex);
if( _pushed_points.empty() ) return false;

while( !_pushed_points.empty() )
Expand Down
2 changes: 1 addition & 1 deletion plotter_gui/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ QString getFunnySubtitle(){
case 4: return "Changing the world, one plot at a time";
case 5: return "Have you starred me on Github?";
case 6: return "Insert [useless message] here";
case 7: return "\"Harry Plotting\" was also an option";
case 7: return "\"Harry Plotter\" was also an option";
case 8: return "Add data and mix vigorously";
case 9: return "Just Plot It!";
case 10: return "I didn't find a better name...";
Expand Down
33 changes: 32 additions & 1 deletion plotter_gui/mainwindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1328,6 +1328,30 @@ void MainWindow::on_pushButtonStreaming_toggled(bool checked)

void MainWindow::onReplotRequested()
{
bool updated = false;

_tracker_time = std::numeric_limits<double>::max();

{
PlotData::asyncPushMutex().lock();

for(auto it : _mapped_plot_data.numeric)
{
PlotDataPtr data = ( it.second );
updated |= data->flushAsyncBuffer();
}

PlotData::asyncPushMutex().unlock();
}

if( updated )
{
forEachWidget( [](PlotWidget* plot)
{
plot->updateCurves(true);
} );
}

_main_tabbed_widget->currentTab()->maximumZoomOut() ;

for(SubWindow* subwin: _floating_window)
Expand All @@ -1346,9 +1370,16 @@ void MainWindow::onReplotRequested()
{
it.second->flushAsyncBuffer();
}
_tracker_time = std::numeric_limits<double>::max();

updateLeftTableValues();
updateTimeSlider();

forEachWidget( [&](PlotWidget* plot)
{
if( plot->isXYPlot()){
plot->setTrackerPosition( QPointF( _max_slider_time, 0.0));
}
} );
}
}

Expand Down
16 changes: 8 additions & 8 deletions plotter_gui/plotwidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -686,7 +686,6 @@ PlotData::RangeTime PlotWidget::maximumRangeX() const
for(auto it = _curve_list.begin(); it != _curve_list.end(); ++it)
{
TimeseriesQwt* series = static_cast<TimeseriesQwt*>( it->second->data() );
series->updateData(false);
auto range_X = series->getRangeX();

if( !range_X ) continue;
Expand Down Expand Up @@ -721,7 +720,6 @@ PlotData::RangeValue PlotWidget::maximumRangeY( PlotData::RangeTime range_X) co
for(auto it = _curve_list.begin(); it != _curve_list.end(); ++it)
{
TimeseriesQwt* series = static_cast<TimeseriesQwt*>( it->second->data() );
series->updateData(false);

const auto max_range_X = series->getRangeX();
if( !max_range_X ) continue;
Expand Down Expand Up @@ -763,19 +761,21 @@ PlotData::RangeValue PlotWidget::maximumRangeY( PlotData::RangeTime range_X) co
return PlotData::RangeValue({ bottom, top});
}

void PlotWidget::updateCurves(bool force)
{
for(auto it = _curve_list.begin(); it != _curve_list.end(); ++it)
{
TimeseriesQwt* series = static_cast<TimeseriesQwt*>( it->second->data() );
series->updateData();
}
}


void PlotWidget::replot()
{
if( _zoomer )
_zoomer->setZoomBase( false );

for(auto it = _curve_list.begin(); it != _curve_list.end(); ++it)
{
TimeseriesQwt* series = static_cast<TimeseriesQwt*>( it->second->data() );
series->updateData(false);
}

QwtPlot::replot();
}

Expand Down
2 changes: 2 additions & 0 deletions plotter_gui/plotwidget.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ class PlotWidget : public QwtPlot

public slots:

void updateCurves(bool force);

void replot() ;

void detachAllCurves();
Expand Down
136 changes: 63 additions & 73 deletions plotter_gui/timeseries_qwt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,77 +9,58 @@ TimeseriesQwt::TimeseriesQwt(PlotDataPtr base):
_subsample(1),
_transform( noTransform )
{

updateData();
}

QPointF TimeseriesQwt::sample(size_t i) const
{
if(_transform == noTransform) {
const auto& p = _plot_data->at( i );
return QPointF( p.x, p.y) ;
}
else {
return _cached_transformed_curve[i];
}
return _cached_transformed_curve[i];
}

QRectF TimeseriesQwt::boundingRect() const
{
qDebug() << "boundingRect not implemented";
return QRectF(0,0,1,1);
return _bounding_box;
}


size_t TimeseriesQwt::size() const
{
if(_transform == noTransform) {
return _plot_data->size();
}
else {
return _cached_transformed_curve.size();
}
return _cached_transformed_curve.size();
}


QRectF TimeseriesQwt::maximumBoundingRect(double min_X, double max_X)
{
int x1 = _plot_data->getIndexFromX( min_X );
int x2 = _plot_data->getIndexFromX( max_X );

if( x1 <0 || x2 <0){
return QRectF();
}

auto range_X = getRangeX();

if( !range_X ){
return QRectF();
}

auto range_Y = getRangeY( x1, x2 );
if( !range_Y){
return QRectF();
}

QRectF rect ( range_X->min,
range_Y->min,
range_X->max - range_X->min,
range_Y->max - range_Y->min );
return rect;
}

void TimeseriesQwt::setSubsampleFactor()
{
// _subsample = (_plot_data->size() / 2000) + 1;
}

void TimeseriesQwt::updateData(bool force_transform)
void TimeseriesQwt::updateData()
{
bool updated = _plot_data->flushAsyncBuffer();
if(_plot_data->size() == 0) return;

if(updated || force_transform)
double min_y =( std::numeric_limits<double>::max() );
double max_y =( std::numeric_limits<double>::min() );
double min_x =( std::numeric_limits<double>::max() );
double max_x =( std::numeric_limits<double>::min() );

//if(updated || force_transform)
{
if(_transform == firstDerivative)
if(_transform == noTransform)
{
_cached_transformed_curve.resize(_plot_data->size());
for (size_t i=0; i< _plot_data->size(); i++ )
{
const auto& p = _plot_data->at( i );
_cached_transformed_curve[i] = QPointF(p.x, p.y) ;

if(min_y > p.y) min_y =(p.y);
else if(max_y < p.y) max_y =(p.y);

if(min_x > p.x) min_x =(p.x);
else if(max_x < p.x) max_x =(p.x);
}
}
else if(_transform == firstDerivative)
{
if( _plot_data->size() < 1){
_cached_transformed_curve.clear();
Expand All @@ -94,7 +75,14 @@ void TimeseriesQwt::updateData(bool force_transform)
const auto& p1 = _plot_data->at( i+1 );
const auto delta = p1.x - p0.x;
const auto vel = (p1.y - p0.y) /delta;
_cached_transformed_curve[i] = QPointF( (p1.x + p0.x)*0.5, vel) ;
const QPointF p( (p1.x + p0.x)*0.5, vel);
_cached_transformed_curve[i] = p;

if(min_y > p.y()) min_y =(p.y());
else if(max_y < p.y()) max_y =(p.y());

if(min_x > p.x()) min_x =(p.x());
else if(max_x < p.x()) max_x =(p.x());
}
}
else if(_transform == secondDerivative)
Expand All @@ -113,7 +101,14 @@ void TimeseriesQwt::updateData(bool force_transform)
const auto& p2 = _plot_data->at( i+2 );
const auto delta = (p2.x - p0.x) *0.5;
const auto acc = ( p2.y - 2.0* p1.y + p0.y)/(delta*delta);
_cached_transformed_curve[i] = QPointF( (p2.x + p0.x)*0.5, acc ) ;
const QPointF p( (p2.x + p0.x)*0.5, acc );
_cached_transformed_curve[i] = p;

if(min_y > p.y()) min_y =(p.y());
else if(max_y < p.y()) max_y =(p.y());

if(min_x > p.x()) min_x =(p.x());
else if(max_x < p.x()) max_x =(p.x());
}
}
else if( _transform == XYPlot && _alternative_X_axis)
Expand All @@ -137,17 +132,28 @@ void TimeseriesQwt::updateData(bool force_transform)
QMessageBox::warning(0, QString("Warning"),
QString("The creation of the XY plot failed because at least two "
"timeseries don't share the same time axis.") );
throw std::runtime_error("back to no Transform");
}
else{
_cached_transformed_curve.resize(N);
for (size_t i=0; i<N; i++ )
{
_cached_transformed_curve[i] = QPointF(_alternative_X_axis->at(i).y,
_plot_data->at(i).y );
const QPointF p(_alternative_X_axis->at(i).y, _plot_data->at(i).y );
_cached_transformed_curve[i] = p;

if(min_y > p.y()) min_y =(p.y());
else if(max_y < p.y()) max_y =(p.y());

if(min_x > p.x()) min_x =(p.x());
else if(max_x < p.x()) max_x =(p.x());
}
}
}
}
_bounding_box.setBottom(min_y);
_bounding_box.setTop(max_y);
_bounding_box.setLeft(min_x);
_bounding_box.setRight(max_x);
}

PlotData::RangeTimeOpt TimeseriesQwt::getRangeX()
Expand All @@ -156,23 +162,7 @@ PlotData::RangeTimeOpt TimeseriesQwt::getRangeX()
if( this->size() < 2 )
return PlotData::RangeTimeOpt() ;
else{
if( _transform == XYPlot && _alternative_X_axis )
{
const double first_Y = _alternative_X_axis->at(0).y;
double y_min = first_Y;
double y_max = first_Y;

for (int i = 1; i < _alternative_X_axis->size(); i++)
{
const double Y = _alternative_X_axis->at(i).y;
if( Y < y_min ) y_min = Y;
else if( Y > y_max ) y_max = Y;
}
return PlotData::RangeTimeOpt( { y_min, y_max } );
}
else{
return PlotData::RangeTimeOpt( { sample(0).x(), sample( this->size() -1).x() } );
}
return PlotData::RangeTimeOpt( { _bounding_box.left(), _bounding_box.right() } );
}
}

Expand All @@ -183,11 +173,11 @@ PlotData::RangeValueOpt TimeseriesQwt::getRangeY(int first_index, int last_index
{
return PlotData::RangeValueOpt();
}
//std::lock_guard<std::mutex> lock(_mutex);

if( _transform == XYPlot && _alternative_X_axis ){
first_index = 0;
last_index = size() -1;
if( (_transform == XYPlot && _alternative_X_axis) ||
( first_index==0 && last_index == size() -1) )
{
return PlotData::RangeValueOpt( { _bounding_box.bottom(), _bounding_box.top() } );
}

const double first_Y = sample(first_index).y();
Expand Down Expand Up @@ -237,6 +227,6 @@ void TimeseriesQwt::setTransform(TimeseriesQwt::Transform trans)
if(trans != _transform)
{
_transform = trans;
updateData(true);
updateData();
}
}
6 changes: 3 additions & 3 deletions plotter_gui/timeseries_qwt.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,11 @@ class TimeseriesQwt: public QwtSeriesData<QPointF>

virtual size_t size() const override;

QRectF maximumBoundingRect(double min_X, double max_X);

PlotDataPtr data() { return _plot_data; }

void setSubsampleFactor();

void updateData(bool force_transform);
void updateData();

PlotData::RangeTimeOpt getRangeX();

Expand Down Expand Up @@ -59,6 +57,8 @@ class TimeseriesQwt: public QwtSeriesData<QPointF>
Transform _transform;

PlotDataPtr _alternative_X_axis;

QRectF _bounding_box;
};


Expand Down
Loading

0 comments on commit 0a13cdf

Please sign in to comment.