Results 1 to 12 of 12

Thread: Moving TimeScaleDraw in real time

  1. #1
    Join Date
    Oct 2013
    Location
    Quebec
    Posts
    31
    Thanks
    4
    Qt products
    Qt5
    Platforms
    Windows

    Default Moving TimeScaleDraw in real time

    Hi,

    Im drawning a qwtPlot with a X_axis that moves every 10 ms. The goal is to try and replicate real time moving of the axe.
    It is similar to the example "oscilloscope" except I move the axis interval every 10ms.
    I want to always leave a few seconds after the actual time so the user always know what is coming.

    Here is a screenshot of it working (bottom graph)
    https://www.dropbox.com/s/cztkhrm3cu...ivTimeDraw.png

    My problem:
    The moving of the scale is not too bad (a little laggy) but the main problem comes when a new TimeScaleDraw label appear on the right (i.e "01:00" in the example above is coming soon).
    When a new label needs to be writen on the right, it draws itself in one shot and it's pertubating the graph flow.
    It's hard to explain without a video but it would be fine if the label be shown gradually from the right (setting the min size or fixed size label somewhere?)
    I suspect the problem is with the TimeScalDraw label because if I use standard QwtScaleDraw with number like oscilloscope, I don't get the tick problem lag.



    Code:

    Qt Code:
    1. ////////////////////////////////////////////////////////////////////////////////
    2. /// TimeScaleDraw
    3. ////////////////////////////////////////////////////////////////////////////////
    4. class TimeScaleDraw: public QwtScaleDraw {
    5. public:
    6. TimeScaleDraw( const QTime &base ):
    7. baseTime( base )
    8. {
    9. }
    10.  
    11. virtual QwtText label( double v ) const {
    12. QTime upTime = baseTime.addSecs( static_cast<int>( v ) );
    13. return upTime.toString();
    14. }
    15.  
    16. private:
    17. QTime baseTime;
    18.  
    19. };
    To copy to clipboard, switch view to plain text mode 


    Event that is triggered every 10ms or so:
    Qt Code:
    1. void WorkoutPlotPower::moveInterval(double timeNow) {
    2.  
    3. d_interval = QwtInterval( timeNow - 15 ,
    4. timeNow + 15);
    5.  
    6.  
    7. setAxisScale( QwtPlot::xBottom, d_interval.minValue(), d_interval.maxValue() );
    8.  
    9.  
    10. }
    To copy to clipboard, switch view to plain text mode 

    Hope I can fix this or i'll have to rethink the real-time graph idea Merci!

  2. #2
    Join Date
    Feb 2006
    Location
    Munich, Germany
    Posts
    3,311
    Thanked 879 Times in 827 Posts
    Qt products
    Qt3 Qt4 Qt/Embedded
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: Moving TimeScaleDraw in real time

    Quote Originally Posted by Maximus2 View Post
    Hi,Im drawning a qwtPlot with a X_axis that moves every 10 ms.
    More than 25 fps ( for stuff like a line plot 10 fps should be fine as well ) doesn't make much sense - beside you want to heat your room with the CPU: too fast for human eyes !
    Also note, that when you are showing a range of 30 seconds you need a plot canvas with a width of 3000 pixels for a resolution of 10ms - otherwise most of your replots do silly repaints without changing anything.

    Disable antialiasing ( your screenshot looks like it is used ) ir possble - it is a main reason for losing performance and you won't have any useful effect when you have a sample rate, that is close to these 10ms.

    Also be careful that you don't trigger several replots/repaint for each cycle by accident.
    When a new label needs to be writen on the right, it draws itself in one shot and it's pertubating the graph flow.
    Are you talking about the effect, that the right end of the canvas gets shifted to the left when the rightmost tick label has not enough space to be painted below it ?
    If true you can avoid this by increasing the margin ( QwtPlotLayout::setCanvasMargin() ) to be larger than 50% of the width of a tick label.

    Uwe

  3. #3
    Join Date
    Oct 2013
    Location
    Quebec
    Posts
    31
    Thanks
    4
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: Moving TimeScaleDraw in real time

    Quote Originally Posted by Uwe View Post
    More than 25 fps ( for stuff like a line plot 10 fps should be fine as well ) doesn't make much sense - beside you want to heat your room with the CPU: too fast for human eyes !
    Also note, that when you are showing a range of 30 seconds you need a plot canvas with a width of 3000 pixels for a resolution of 10ms - otherwise most of your replots do silly repaints without changing anything.

    Disable antialiasing ( your screenshot looks like it is used ) ir possble - it is a main reason for losing performance and you won't have any useful effect when you have a sample rate, that is close to these 10ms.

    Also be careful that you don't trigger several replots/repaint for each cycle by accident.
    Thanks for your tips, I'm a newbie in that field so really welcome! I was being lazy and using the same timer as the clock refresh timer (10ms), I'll try with something around 25ms. Also that graph will take 1/3 of the screen width (so max ~640 pixels). The high refresh rate is mostly just for the axis change (xBottom) looking more fluid and a marker in the graph that shows the current time in seconds. I will draw a QwtCurve in the graph but with 4 points per seconds maximum(data income limit). Yes I was noticing high cpu usage and fan going crazy I'm probably doing a lot of silly replot like you said (the plot is set to setAutoReplot( true )). I will try to improve by using DirectPainter later maybe, now i'm just using "QVector<QPointF> powerSamples" as data for the curves, every new data point received trigger this slot:
    powerSamples.append(QPointF( timeNow, value ));
    powerCurve->setSamples(powerSamples);
    powerCurve->attach(this);
    Probably really bad ? Still seems to only uses ~5000k every workout so if the work isn't worth the cpu improvement I don't mind the memory usage

    When you say to disable antialiasing , you mean on every object in the plot ? For example : powerCurve->setRenderHint( QwtPlotItem::RenderAntialiased ); //--> Remove Antialiased ?
    so that "QwtPlot::drawItems" draw them without it? Is there an attribute like that for the axis ? I probably need to go read what Antiliasing do now!

    Quote Originally Posted by Uwe View Post
    Are you talking about the effect, that the right end of the canvas gets shifted to the left when the rightmost tick label has not enough space to be painted below it ?
    If true you can avoid this by increasing the margin ( QwtPlotLayout::setCanvasMargin() ) to be larger than 50% of the width of a tick label.
    Uwe
    Exactly! I added "plotLayout()->setCanvasMargin(15, 1);" to my QwtPlot class and it's working perfect now, except the room eating up :P

    Thanks for your support Uwe!
    Last edited by Maximus2; 10th December 2013 at 16:58.

  4. #4
    Join Date
    Oct 2013
    Location
    Quebec
    Posts
    31
    Thanks
    4
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: Moving TimeScaleDraw in real time

    Hopefully last time I disturb you !

    Is it possible to set some text/image/icon that stays on the same position relative to the QwtPlot ? (ex: hcenter/cventer of qwtplot)

    [Edit: Possible, found the answer here:
    http://www.qtcentre.org/threads/5696...wtText+refresh



    I would like to add a fixed position Qpixmap in the qwtPlot, not sure "QwtPlotTextLabel" support the pixmap?
    See example below (now using QwtPlotMarker with a custom symbol to draw the icon)

    Current UI :
    https://www.dropbox.com/s/fp60utrck6...mapQwtPlot.png
    Last edited by Maximus2; 10th December 2013 at 23:25.

  5. #5
    Join Date
    Feb 2006
    Location
    Munich, Germany
    Posts
    3,311
    Thanked 879 Times in 827 Posts
    Qt products
    Qt3 Qt4 Qt/Embedded
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: Moving TimeScaleDraw in real time

    I'll try with something around 25ms.
    Try something around 100ms - for a line plot, where most of the content doesn't change this should be fast enough. Disable autoreplot and do the replot driven by a QTimer.

    The high refresh rate is mostly just for the axis change (xBottom) looking more fluid and a marker in the graph that shows the current time in seconds.
    Nobody can read something that changes many times a second, but as all your labels are aligned to seconds a high refresh rate will simply redraw the same thing all the time. But this has absolutely no effect for looking more fluid.

    I will draw a QwtCurve in the graph but with 4 points per seconds maximum(data income limit).
    What is a sample rate of 250ms only.

    powerSamples.append(QPointF( timeNow, value ));
    The size of this buffer will grow and after some time throwing out the values that are out of the visible area will need some time. Better also remove the invisible leading points from the buffer in each cycle.

    When you say to disable antialiasing , ...
    For a curve with 120 points ( 30 seconds * 4 points ) you don't have to take care much of rendering performance.

    Also note that for a canvas with a width of ~600 pixels + showing a range of 30 seconds means, that each pixel covers a range of 50ms. Having a replot rate below this resolution will be nothing but a no-operation !

    Uwe

  6. #6
    Join Date
    Oct 2013
    Location
    Quebec
    Posts
    31
    Thanks
    4
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: Moving TimeScaleDraw in real time

    Quote Originally Posted by Uwe View Post
    Try something around 100ms - for a line plot, where most of the content doesn't change this should be fast enough. Disable autoreplot and do the replot driven by a QTimer.
    Here I just made a video to explain a little bit better my concern :
    https://www.youtube.com/watch?v=mxA6gz0H3uY

    First I changed AutoReplot() to false for both graph using your advice, now I use a 1sec replot() for the big graph up top. For this graph it's enough, since the scale is big and we can't see all the point(45min to 2hours workout with 4points per seconds on the curve).

    For the small plot down. I use a fast replot timer of 25ms now since lower than that it seems a bit "choppy" on moving the axis scale. See video for a feel for it (still a little bit choppy in the video).

    I used your advice and remove past value that are not shown in the 30sec graph scale, so the replot() should be faster:

    Qt Code:
    1. void WorkoutPlotPower::updatePowerCurve(double timeNow, int value) {
    2.  
    3.  
    4. if (powerSamples.size() > 120 ) ///After 30sec ((30*4) of data, we can erase past data not shown on graph for faster replot
    5. powerSamples.pop_front();
    6.  
    7. powerSamples.append(QPointF( timeNow, value ));
    8. powerCurve->setSamples(powerSamples);
    9. powerCurve->attach(this);
    10.  
    11. }
    To copy to clipboard, switch view to plain text mode 


    Hopefully you get what i'm trying to achieve in the real-time graph
    Thanks again for your help !

  7. #7
    Join Date
    Oct 2013
    Location
    Quebec
    Posts
    31
    Thanks
    4
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: Moving TimeScaleDraw in real time

    Whoa I can't find the edit button this morning..

    Here's my prototype video :
    https://www.youtube.com/watch?v=_H8zfInshdo

  8. #8
    Join Date
    Oct 2013
    Location
    Quebec
    Posts
    31
    Thanks
    4
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: Moving TimeScaleDraw in real time

    I don't know if you have solution for improving performance (moving a QwtPlotMarker and the moving graph axis in real time )

    For the QwtPlotMarker, since the position is always in middle of the graph canvas, I could use a custom QLabel that sit there and doesn't move.
    But for the Graph Axis, i haven't figured a solution yet. I guess my use case is just too demanding (reploting a 30sec graph every 25ms). My goal was to have a kind of feeling of real time, like a video game.

    You can still see the graph in action on the youtube link up there.

    Thank you


    Edit: The QwTPlotMarker has been replaced with a QFrame VLine that stays in the middle:
    ///////////////////////////////////////////////////////////////////////////////
    QFrame* myFrame = new QFrame();
    myFrame->setFrameShape(QFrame::VLine);
    myFrame->setStyleSheet( "color: blue;");
    myFrame->setLineWidth(4);
    myFrame->setContentsMargins(0, 30, 0, 0);


    widgetCanvas = this->canvas();
    QGridLayout *gridLayout;
    gridLayout = new QGridLayout(this);
    gridLayout->addWidget(myFrame, 0, 0, 1, 1);
    widgetCanvas->setLayout(gridLayout);
    /////////////////////////////////////////////////////////////////////////////
    Now to fix that axis..
    Last edited by Maximus2; 10th January 2014 at 07:17.

  9. #9
    Join Date
    Feb 2006
    Location
    Munich, Germany
    Posts
    3,311
    Thanked 879 Times in 827 Posts
    Qt products
    Qt3 Qt4 Qt/Embedded
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: Moving TimeScaleDraw in real time

    Quote Originally Posted by Maximus2 View Post
    For the QwtPlotMarker, since the position is always in middle of the graph canvas, I could use a custom QLabel that sit there and doesn't move..
    Sure, but for this particular use case this doesn't make much sense as all what needs to be done is a plot item that draws a vertical line in the center of the canvas:

    Qt Code:
    1. class MarkerItem: public QwtPlotItem
    2. {
    3. public:
    4. virtual void draw( QPainter *painter,
    5. const QwtScaleMap &, const QwtScaleMap &,
    6. const QRectF &canvasRect ) const
    7. {
    8. painter->setPen( ... );
    9. painter->drawLine( canvasRect.center.x(), canvasRect.top(), canvasRect.center.x(), canvasRect.bottom() );
    10. }
    11. };
    To copy to clipboard, switch view to plain text mode 

    Using widget overlays makes sense when the content of the overlay is moving fast and you want to avoid replots.

    But before using just any widget for such a use case you should have a look at QwtWidgetOverlay, what is tailored for this situation. In opposite to regular widgets it calculates a widget mask to avoid full repaints ( = flushing the backing store ) of the plot canvas, when its content changes. In a powerful environment you won't see the difference, but f.e. when running the itemeditor remote X11 ( or on slow embedded devices with QWS ) example you will see a major difference.

    Uwe

  10. The following user says thank you to Uwe for this useful post:

    Maximus2 (10th January 2014)

  11. #10
    Join Date
    Oct 2013
    Location
    Quebec
    Posts
    31
    Thanks
    4
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: Moving TimeScaleDraw in real time

    Hey Uwe,

    Just wanted to update this.
    I can move the graph in real-time successfully as shown here :
    https://www.youtube.com/watch?v=I7C-GyJBzog

    The graph is not lagging when the width of the graph is big enough and I'm happy with the performance.
    The only thing that I would like to improve is when the width of the graph get smaller (windows resize or smaller resolution), the bottom axis get laggier as the graph get smaller. Not sure why this happen, seems to be related to the bottom axis getting too small. Maybe I need to put a minimumWidth on the graph or find another elegant solution for smaller graph.

    On a side note, i'm using 6.1 inside Qt 5.4 and all is working fine, I had to modify qwt_transform.h and qwt_transform.cpp so it can compile under 5.4

    qwt_transform.h:
    Qt Code:
    1. static const double LogMin;
    2. static const double LogMax;
    3. //QT_STATIC_CONST double LogMin;
    4. //QT_STATIC_CONST double LogMax;
    To copy to clipboard, switch view to plain text mode 

    qwt_transform.cpp:
    Qt Code:
    1. const double QwtLogTransform::LogMin = 1.0e-150;
    2. const double QwtLogTransform::LogMax = 1.0e150;
    3. //QT_STATIC_CONST_IMPL double QwtLogTransform::LogMin = 1.0e-150;
    4. //QT_STATIC_CONST_IMPL double QwtLogTransform::LogMax = 1.0e150;
    To copy to clipboard, switch view to plain text mode 

    Thanks for Qwt i'm enjoying it,
    Max

  12. #11
    Join Date
    Feb 2006
    Location
    Munich, Germany
    Posts
    3,311
    Thanked 879 Times in 827 Posts
    Qt products
    Qt3 Qt4 Qt/Embedded
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: Moving TimeScaleDraw in real time

    This has been fixed in the 6.1 SVN branch some time ago. There will be a Qwt 6.1.2 as soon as I succeeded to build Qt 5.4.0 on my box - unfortunately building Qt 5.4.0 is far from being an easy one.

    Uwe

  13. #12
    Join Date
    Feb 2006
    Location
    Munich, Germany
    Posts
    3,311
    Thanked 879 Times in 827 Posts
    Qt products
    Qt3 Qt4 Qt/Embedded
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: Moving TimeScaleDraw in real time

    O.k done: Qwt 6.1.2 is available see https://sourceforge.net/projects/qwt/files/qwt/6.1.2

    Uwe

Similar Threads

  1. real time image GUI with Qt
    By sanda199 in forum Newbie
    Replies: 0
    Last Post: 25th January 2013, 06:43
  2. Real Time Applications in Qt
    By shammy in forum Qt Programming
    Replies: 1
    Last Post: 2nd October 2012, 07:17
  3. Qwt real time plotting
    By santoshpradeep in forum Qwt
    Replies: 8
    Last Post: 28th June 2012, 09:53
  4. Qwt real time
    By oddytz1989 in forum Qwt
    Replies: 3
    Last Post: 10th February 2012, 04:41
  5. real time plotting
    By gyre in forum Qwt
    Replies: 4
    Last Post: 11th December 2007, 16:13

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.