YARP
Yet Another Robot Platform
 
Loading...
Searching...
No Matches
plotter.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2006-2021 Istituto Italiano di Tecnologia (IIT)
3 * SPDX-License-Identifier: GPL-3.0-or-later
4 */
5
6#include "plotter.h"
8#include "yarp/os/Time.h"
9#include "yarp/os/Stamp.h"
10#include <QDebug>
11#include <utility>
12
26Plotter::Plotter(const QString &title, int gridx, int gridy, int hspan, int vspan, float minval, float maxval, int size, const QString &bgcolor, bool autorescale, QObject *parent) :
27 QObject(parent),
28 title(title),
29 gridx(gridx),
30 gridy(gridy),
31 hspan(hspan),
32 vspan(vspan),
33 minval(minval),
34 maxval(maxval),
35 size(size),
36 bgcolor(bgcolor),
37 autorescale(autorescale),
38 initialSize(size),
39 start(0),
40 interact(false)
41{
42 connect(customPlot.axisRect(),SIGNAL(zoomRequest()),this,SLOT(onInteract()));
43 connect(customPlot.axisRect(),SIGNAL(dragStarted()),this,SLOT(onInteract()));
44
45 customPlot.axisRect()->setBackground(QBrush(QColor(bgcolor)));
46 customPlot.axisRect()->setupFullAxesBox(true);
47#if !defined(QCUSTOMPLOT_VERSION) || (QCUSTOMPLOT_VERSION < 0x020000)
48 customPlot.axisRect()->axis(QCPAxis::atBottom)->setTickLabelType(QCPAxis::ltNumber);
49 customPlot.axisRect()->axis(QCPAxis::atBottom)->setAutoTickStep(false);
50 customPlot.axisRect()->axis(QCPAxis::atBottom)->setTickStep(25);
51#else
52 QSharedPointer<QCPAxisTickerFixed> fixedTicker(new QCPAxisTickerFixed);
53 customPlot.axisRect()->axis(QCPAxis::atBottom)->setTicker(fixedTicker);
54 fixedTicker->setTickStep(25);
55 fixedTicker->setScaleStrategy(QCPAxisTickerFixed::ssNone);
56#endif
57 customPlot.axisRect()->axis(QCPAxis::atBottom)->setRange(0,size);
58 customPlot.axisRect()->axis(QCPAxis::atLeft)->setRange(minval, maxval);
59 customPlot.setInteractions( QCP::iRangeDrag | QCP::iRangeZoom );
60 auto* textLabel = new QCPItemText(&customPlot);
61#if !defined(QCUSTOMPLOT_VERSION) || (QCUSTOMPLOT_VERSION < 0x020000)
62 customPlot.addItem(textLabel);
63#else
64 // Nothing to do
65#endif
66 textLabel->setPositionAlignment(Qt::AlignTop|Qt::AlignHCenter);
67 textLabel->position->setType(QCPItemPosition::ptAxisRectRatio);
68 textLabel->position->setCoords(0.5, 0); // place position at center/top of axis rect
69 textLabel->setText(title);
70
71 connect(customPlot.xAxis, SIGNAL(rangeChanged(QCPRange)), customPlot.xAxis2, SLOT(setRange(QCPRange)));
72 connect(customPlot.yAxis, SIGNAL(rangeChanged(QCPRange)), customPlot.yAxis2, SLOT(setRange(QCPRange)));
73
74}
75
78{
79 interact = true;
80}
81
82
83
85{
86 for (int i=0;i<graphList.count(); i++) {
87 auto* idx = (Graph*)graphList.at(i);
88 if (idx) {
89 delete idx;
90 idx = nullptr;
91 }
92 }
93 graphList.clear();
94
95}
96
99{
100 interact = false;
101 customPlot.rescaleAxes(true);
102}
103
106{
108}
109
110
119Graph * Plotter::addGraph(QString remotePort,QString localPort,int index, QString title, QString color, QString type, int size, double graph_y_scale)
120{
121 Graph *graph = nullptr;
122 graph = new Graph(index,title,color,type,size,graph_y_scale,this->size);
123
124
125 for(int i=0;i<graphList.count();i++) {
126 auto* g = (Graph *)graphList.at(i);
127 Connection *con = g->getConnection();
128 if(!con){
129 continue;
130 }
131 if(con->remotePortName == remotePort && con->localPortName == localPort){
132 graph->curr_connection = g->curr_connection;
133 graph->deleteConnection = false;
134 break;
135 }
136 }
137 graphList.append(graph);
138
139
140 QCPGraph *customGraph = customPlot.addGraph(); // line
141 customGraph->setPen(QPen(QColor(color),size));
142 customGraph->setAntialiased(false);
143 customGraph->setLineStyle(QCPGraph::lsLine);
144
145 if(type == "points"){
146 customGraph->setLineStyle(QCPGraph::lsNone);
147 customGraph->setScatterStyle(QCPScatterStyle::ssDot);
148 }
149
150 if(type == "bars"){
151 customGraph->setLineStyle(QCPGraph::lsImpulse);
152 customGraph->setScatterStyle(QCPScatterStyle::ssNone);
153 }
154
155
156 QCPGraph *customGraphPoint = customPlot.addGraph(); // dot
157 customGraphPoint->setPen(QPen(QColor(color)));
158 customGraphPoint->setLineStyle(QCPGraph::lsNone);
159 customGraphPoint->setScatterStyle(QCPScatterStyle::ssDisc);
160
161 graph->setCustomGraph(customGraph);
162 graph->setCustomGraphPoint(customGraphPoint);
163 customPlot.replot();
164
165
166 return graph;
167}
168
169
172{
173 if (graphList.empty()) {
174 // Do not read data from this port if we don't need it
175 return;
176 }
177
178 int c = graphList.count();
179 for (int j=0;j < c; j++) {
180 auto* graph = (Graph*)graphList.at(j);
182 if(graph->deleteConnection){
183 b = graph->curr_connection->localPort->read(false);
184 }else{
185 b = graph->curr_connection->localPort->lastRead();
186 }
187 if (!b) {
188// qDebug("No data received. Using previous values.");
189 graph->appendPreviousValues();
190
191 } else {
192 if (b->size() == 1 && b->get(0).isList()) {
193 b = b->get(0).asList();
194 }
195 yarp::os::Stamp stmp;
196 graph->curr_connection->localPort->getEnvelope(stmp);
197
198 if (b->size() - 1 < (size_t) graph->index) {
199 qWarning() << "bottle size =" << b->size() << " requested index =" << graph->index;
200 continue;
201 }
202
203
204 double y = (float)(b->get(graph->index).asFloat64());
205
206 float t;
207 if (graph->curr_connection->realTime && stmp.isValid()) {
208 t = (float)(stmp.getTime() - graph->curr_connection->initialTime);
209 } else {
210 t = -1.0;
211 }
212
213 graph->appendValues(y,t);
214
215 }
216
217
218 }
219
220 // if the user did not interact with the plotter, it remains aligned to the right
221 // else, there is no alignment and the user has the freedom to pan and zoom it
222 if(!interact){
223 auto* graph = (Graph*)graphList.at(0);
224 if(graph){
225 customPlot.xAxis->setRange(graph->lastX+5, size, Qt::AlignRight);
226 }
227 }
228
229 customPlot.replot();
230
231}
232
233
236{
237 for (int j=0;j < graphList.count(); j++) {
238 auto* graph = (Graph*)graphList.at(j);
239 graph->clearData();
240 }
241 customPlot.replot();
242}
243
244
245/***********************************************************/
246Graph::Graph(int index, QString title, QString color, QString type, int size, double graph_y_scale, int buffer_size, QObject *parent) :
247 QObject(parent),
248 lastX(0),
249 lastY(0),
250 lastT(0),
251 deleteConnection(true),
252 customGraphPoint(nullptr),
253 customGraph(nullptr),
254 index(index),
255 graph_y_scale(graph_y_scale),
256 curr_connection(nullptr),
257 buffer_size(buffer_size),
258 numberAcquiredData(0),
259 lastIndex(0),
260 type(std::move(type)),
261 color(std::move(color)),
262 lineSize(size),
263 title(std::move(title))
264{}
265
266
267void Graph::init(QString remotePortName,
268 QString localPortName,
269 QString carrier,
270 bool persistent)
271{
272
274
275 if(!curr_connection){
276 if (persistent) {
277 style.persistent = persistent;
279 }
280 style.carrier = carrier.toLatin1().data();
281
282 curr_connection = new Connection(remotePortName, localPortName);
283 curr_connection->connect(style);
284 }
285}
286
288{
290 delete curr_connection;
291 curr_connection = nullptr;
292 }
293 clearData();
294}
299
302{
303 if(type.compare("lines") == 0){
304 return GRAPH_TYPE_LINE;
305 }
306 if(type.compare("bars") == 0){
307 return GRAPH_TYPE_BARS;
308 }
309 if(type.compare("points") == 0){
310 return GRAPH_TYPE_POINTS;
311 }
312
313 return GRAPH_TYPE_LINE;
314}
315
318{
319 return lineSize;
320}
321
324{
325 return color;
326}
327
333
335void Graph::appendValues(float y, float t)
336{
337 float _t = t;
338 if(t == -1){
339 _t = (float)numberAcquiredData;
340 }
341
342 //apply the y scale factor
343 y=y*graph_y_scale;
344
345 lastX = numberAcquiredData;
346 lastY = y;
347 lastT = _t;
348
350 customGraph->addData(lastX,lastY);
351#if !defined(QCUSTOMPLOT_VERSION) || (QCUSTOMPLOT_VERSION < 0x020000)
352 customGraphPoint->clearData();
353#else
354 customGraphPoint->data()->clear();
355#endif
356 customGraphPoint->addData(lastX,lastY);
357#if !defined(QCUSTOMPLOT_VERSION) || (QCUSTOMPLOT_VERSION < 0x020000)
358 customGraph->removeDataBefore(lastX - 4*buffer_size);
359#else
360 customGraph->data()->removeBefore(lastX - 4*buffer_size);
361#endif
362 numberAcquiredData++;
363 }
364
365}
366
370void Graph::setCustomGraph(QCPGraph *g)
371{
372 customGraph = g;
373}
374
379{
381}
382
383
386{
387 if(customGraph){
388#if !defined(QCUSTOMPLOT_VERSION) || (QCUSTOMPLOT_VERSION < 0x020000)
389 customGraph->clearData();
390#else
391 customGraph->data()->clear();
392#endif
393 }
395#if !defined(QCUSTOMPLOT_VERSION) || (QCUSTOMPLOT_VERSION < 0x020000)
396 customGraphPoint->clearData();
397#else
398 customGraphPoint->data()->clear();
399#endif
400 }
401
402}
403
404
405/***************************************************************/
406
407Connection::Connection(QString remotePortName, QString localPortName, QObject *parent): QObject(parent)
408{
409
410 this->remotePortName = remotePortName;
411 this->localPortName = localPortName;
413 realTime = false;
414 initialTime = 0.0;
415
416
417
418 // Open the local port
419 if (localPortName.isEmpty()) {
420 localPort->open("...");
421 } else {
422 localPort->open(localPortName.toLatin1().data());
423 }
424
425 realTime = true;
427}
428
433
436
437 //Get the name of the port after the port is open (and therefore the real name assigned)
438 const QString &realLocalPortName = localPort->getName().c_str();
439
440 // Connect local port to remote port
441 if (!yarp::os::Network::connect(remotePortName.toLatin1().data(), realLocalPortName.toLatin1().data(), style)) {
442 qWarning() << "Connection from port" << realLocalPortName.toLatin1().data() << "to port" << remotePortName.toLatin1().data()
443 << "was NOT successful. Waiting from explicit connection from user.";
444 } else {
445 qDebug("Listening to port %s from port %s",remotePortName.toLatin1().data(),realLocalPortName.toLatin1().data());
446 // Connection was successful. Save the ContactStyle in order to reuse it for disconnecting;
447 this->style = style;
448 }
449
450 yarp::os::Stamp stmp;
451 localPort->getEnvelope(stmp);
452 if (stmp.isValid()) {
453 qDebug("will use real time for port %s",remotePortName.toLatin1().data());
454 realTime = true;
455 initialTime = stmp.getTime();
456 } else {
457 qDebug("will NOT use real time for port %s",remotePortName.toLatin1().data());
458 realTime = false;
459 }
460}
461
463{
464 if(localPort)
465 {
467 delete localPort;
468 localPort = nullptr;
469 }
470}
size_t size_t
int SIGNAL(int pid, int signum)
Class representing a Connection.
Definition plotter.h:91
QString remotePortName
Definition plotter.h:101
QString localPortName
Definition plotter.h:102
Connection(QString remotePortName, QString localPortName, QObject *parent=0)
Definition plotter.cpp:407
yarp::os::ContactStyle style
Definition plotter.h:108
void freeResources()
Definition plotter.cpp:462
yarp::os::BufferedPort< yarp::os::Bottle > * localPort
Definition plotter.h:104
void connect(const yarp::os::ContactStyle &style)
Connect local port to remote port.
Definition plotter.cpp:435
double initialTime
Definition plotter.h:106
bool realTime
Definition plotter.h:105
Class representing a Graph.
Definition plotter.h:26
void init(QString remotePortName, QString localPortName, QString carrier, bool persistent)
Definition plotter.cpp:267
QCPGraph * customGraphPoint
Definition plotter.h:58
int getLineSize()
Return tickness of the graph.
Definition plotter.cpp:317
double graph_y_scale
Definition plotter.h:62
void setCustomGraphPoint(QCPGraph *)
Sets the Custom Graph Point from the QCustomPlot class to this graph.
Definition plotter.cpp:378
Connection * getConnection()
Definition plotter.cpp:295
double lastY
Definition plotter.h:49
void setCustomGraph(QCPGraph *)
Sets the Custom Graph from the QCustomPlot class to this graph.
Definition plotter.cpp:370
void appendPreviousValues()
Append the previous values acquired.
Definition plotter.cpp:329
void clearData()
Clears the custom graph datas.
Definition plotter.cpp:385
void appendValues(float y, float t)
Append the new values acquired.
Definition plotter.cpp:335
int getType()
Return the graph type.
Definition plotter.cpp:301
~Graph()
Definition plotter.cpp:287
Graph(int index, QString title, QString color, QString type, int size, double graph_y_scale, int buffer_size, QObject *parent=0)
Definition plotter.cpp:246
double lastT
Definition plotter.h:50
QCPGraph * customGraph
Definition plotter.h:59
QString getColor()
Return color of the grpah.
Definition plotter.cpp:323
double lastX
Definition plotter.h:48
bool deleteConnection
Definition plotter.h:56
Connection * curr_connection
Definition plotter.h:64
void rescale()
Rescales the plotter and its graphs.
Definition plotter.cpp:98
Graph * addGraph(QString remotePort, QString localPort, int index, QString title, QString color, QString type, int size, double graph_y_scale=1.0)
Add a Graph to the current Plotter.
Definition plotter.cpp:119
float minval
Definition plotter.h:149
void setPaintGeometry(QRectF)
Sets the paint geometry for this Plotter.
Definition plotter.cpp:105
QCustomPlot customPlot
Definition plotter.h:139
QList< QObject * > graphList
Definition plotter.h:138
int size
Definition plotter.h:151
float maxval
Definition plotter.h:150
QString title
Definition plotter.h:144
void onTimeout()
Timeout on which the data is acquired.
Definition plotter.cpp:171
QRectF paintRectGeometry
Definition plotter.h:141
void clear()
Clears the graphs data.
Definition plotter.cpp:235
bool interact
Definition plotter.h:156
~Plotter()
Definition plotter.cpp:84
QString bgcolor
Definition plotter.h:152
void onInteract()
Sets the interaction mode to true.
Definition plotter.cpp:77
Plotter(const QString &title, int gridx, int gridy, int hspan, int vspan, float minval, float maxval, int size, const QString &bgcolor, bool autorescale, QObject *parent=0)
Constructor of the class.
Definition plotter.cpp:26
A simple collection of objects that can be described and transmitted in a portable way.
Definition Bottle.h:64
size_type size() const
Gets the number of elements in the bottle.
Definition Bottle.cpp:251
bool read(ConnectionReader &reader) override
Set the bottle's value based on input from a network connection.
Definition Bottle.cpp:240
Value & get(size_type index) const
Reads a Value v from a certain part of the list.
Definition Bottle.cpp:246
A mini-server for performing network communication in the background.
std::string getName() const override
Get name of port.
bool getEnvelope(PortReader &envelope) override
Get the envelope information (e.g., a timestamp) from the last message received on the port.
bool open(const std::string &name) override
Start port operation, with a specific name, with automatically-chosen network parameters.
Preferences for how to communicate with a contact.
PersistenceType persistenceType
Specify kind of persistence to use.
std::string carrier
Request that communication be made using a particular carrier.
bool persistent
Specify whether a requested connection should be persistent.
static bool connect(const std::string &src, const std::string &dest, const std::string &carrier="", bool quiet=true)
Request that an output port connect to an input port.
Definition Network.cpp:682
static bool disconnect(const std::string &src, const std::string &dest, bool quiet)
Request that an output port disconnect from an input port.
Definition Network.cpp:700
An abstraction for a time stamp and/or sequence number.
Definition Stamp.h:21
double getTime() const
Get the time stamp.
Definition Stamp.cpp:34
bool isValid() const
Check if this Stamp is valid.
Definition Stamp.cpp:39
virtual yarp::conf::float64_t asFloat64() const
Get 64-bit floating point value.
Definition Value.cpp:222
virtual bool isList() const
Checks if value is a list.
Definition Value.cpp:162
virtual Bottle * asList() const
Get list value.
Definition Value.cpp:240
STL namespace.
double now()
Return the current time in seconds, relative to an arbitrary starting point.
Definition Time.cpp:121
#define GRAPH_TYPE_POINTS
Definition plotter.h:18
#define GRAPH_TYPE_BARS
Definition plotter.h:17
#define GRAPH_TYPE_LINE
Definition plotter.h:16