30 #include <qwt_legend_label.h>
50 qRegisterMetaType<std::map<std::string, VariantPtr>>(
"std::map<std::string, VariantPtr>");
52 widget->setMinimumHeight(150);
59 (void)
new QwtPlotPanner(
plotter->canvas());
62 QwtPlotMagnifier* magnifier =
new QwtPlotMagnifier(
plotter->canvas());
63 magnifier->setAxisEnabled(QwtPlot::xBottom,
false);
65 dynamic_cast<QwtPlotCanvas&
>(*
plotter->canvas())
66 .setPaintAttribute(QwtPlotCanvas::BackingStore,
69 QwtLegend* legend =
new QwtLegend;
70 legend->setDefaultItemMode(QwtLegendData::Mode::Checkable);
71 plotter->insertLegend(legend, QwtPlot::BottomLegend);
74 plotter->setAxisTitle(QwtPlot::xBottom,
"Time (in sec)");
75 plotter->enableAxis(QwtPlot::yLeft,
false);
77 plotter->enableAxis(QwtPlot::yRight,
true);
78 plotter->setAxisAutoScale(QwtPlot::yRight,
true);
85 SIGNAL(checked(
const QVariant&,
bool,
int)),
93 QWidget* barsWidget =
new QWidget();
95 barsWidget->setAccessibleName(
"barsWidget");
139 for (
auto& markerChannel :
markers)
141 for (
auto it = markerChannel.second.begin(); it != markerChannel.second.end();)
145 for (
auto elem : it->second)
147 elem.second->detach();
149 it = markerChannel.second.erase(it);
158 GraphDataMap::iterator it =
dataMap.begin();
162 std::map<std::string, QwtPlotMarkerPtr>& markerSubMap =
markers[datafieldId][age];
164 std::string
value = var->getString();
165 auto it2 = markerSubMap.find(
value);
166 if (it2 != markerSubMap.end())
169 marker->setXValue(0.001 * age.toMilliSecondsDouble());
174 marker->setValue(0.001 * age.toMilliSecondsDouble(), 0);
175 marker->setLabel(QwtText(QString::fromStdString(
value)));
176 marker->setLineStyle(QwtPlotMarker::VLine);
177 marker->setLabelAlignment(Qt::AlignBottom | Qt::AlignLeft);
179 for (
auto& markerSubMap :
markers)
181 if (markerSubMap.first == datafieldId)
187 marker->setLinePen(QColor(Qt::GlobalColor((i) % 5 + 13)));
189 markerSubMap[
value] = marker;
193 for (; it !=
dataMap.end(); ++it)
196 QVector<QPointF> pointList;
198 auto datafieldId = it->first;
199 std::vector<TimeData>& dataVec = it->second;
201 pointList.reserve(dataVec.size());
208 for (
int i = dataVec.size() - 1; i >= 0; --i)
217 if (var->getInitialized())
219 float xValue = 0.001 * age.toMilliSecondsDouble();
220 auto type = var->getType();
223 var->getFloat() != std::numeric_limits<float>::infinity())
225 yValue = (var->getFloat());
228 var->getDouble() != std::numeric_limits<double>::infinity())
230 yValue = (var->getDouble());
233 var->getInt() != std::numeric_limits<int>::infinity())
235 yValue = (var->getInt());
238 var->getLong() != std::numeric_limits<long>::infinity())
240 yValue =
static_cast<double>(var->getLong());
244 yValue = (var->getBool() ? 1 : -1);
248 addMarker(age, var, datafieldId);
255 pointList.push_back(QPointF(xValue, yValue));
262 <<
"uninitialized field: " << it->first;
276 QwtSeriesData<QPointF>* pointSeries =
new QwtPointSeriesData(pointList);
278 if (pointList.size() > 0 &&
curves.find(it->first) !=
curves.end() &&
281 QwtPlotCurve* curve =
curves[it->first];
282 curve->setData(pointSeries);
283 curve->setYAxis(QwtPlot::yRight);
284 QwtThermo* bar =
bars[it->first];
285 bar->setValue(pointList.first().y());
286 float range = curve->maxYValue() - curve->minYValue();
287 bar->setLowerBound(curve->minYValue() - 0.05 * range);
288 bar->setUpperBound((curve->maxYValue()) + range * 0.05);
302 item->setVisible(on);
303 QwtLegend* lgd = qobject_cast<QwtLegend*>(
plotter->legend());
305 QList<QWidget*> legendWidgets = lgd->legendWidgets(
plotter->itemToInfo(item));
307 if (legendWidgets.size() == 1)
309 QwtLegendLabel* legendLabel = qobject_cast<QwtLegendLabel*>(legendWidgets[0]);
313 legendLabel->setChecked(on);
322 ARMARX_WARNING <<
"found " << legendWidgets.size() <<
" items for the given curve";
332 plotter->setAxisAutoScale(QwtPlot::yRight, toggled);
359 std::map<std::string, VariantPtr>
362 using clock_t = std::chrono::high_resolution_clock;
363 const auto now = [] {
return clock_t::now(); };
364 const auto dt_ms = [](
auto t0,
auto t1) ->
float
365 {
return std::chrono::duration_cast<std::chrono::nanoseconds>(t1 - t0).count() / 1e6f; };
371 std::map<std::string, DataFieldIdentifierBaseList> channelsSplittedByObserver;
372 for (QString
const& channel : channels)
375 channelsSplittedByObserver[identifier->getObserverName()].push_back(identifier);
378 std::map<std::string, VariantPtr> newData;
379 const auto time_clear_start = now();
385 GraphDataMap::iterator itmap =
dataMap.begin();
387 for (; itmap !=
dataMap.end(); ++itmap)
389 std::vector<TimeData>& dataVec = itmap->second;
390 int stepSize = std::max<int>(1, dataVec.size() * 0.01);
391 int thresholdIndex = -1;
393 for (
unsigned int i = 0; i < dataVec.size(); i += stepSize)
399 if ((now - dataVec[i].time).toSecondsDouble() >
shownInterval * 2 ||
400 (thresholdIndex != -1 &&
411 if (thresholdIndex != -1)
413 unsigned int offset =
std::min((
int)dataVec.size(), thresholdIndex);
416 if (offset > dataVec.size())
422 dataVec.erase(dataVec.begin(), dataVec.begin() + offset);
429 const auto time_clear_end = now();
433 std::map<std::string, DataFieldIdentifierBaseList>::iterator it =
434 channelsSplittedByObserver.begin();
435 const auto time_get_data_start = now();
436 float time_get_data_get_variants = 0;
437 float time_get_data_find_obs = 0;
438 float time_get_data_lock = 0;
439 float time_get_data_process = 0;
440 std::map<std::string, float> time_get_data_get_variants_per_obs;
443 for (; it != channelsSplittedByObserver.end(); ++it)
445 const std::string& observerName = it->first;
447 const auto time_get_data_find_obs_start = now();
453 time_get_data_find_obs += dt_ms(time_get_data_find_obs_start, now());
456 iceManager->getProxy<ObserverInterfacePrx>(observerName);
458 time_get_data_find_obs += dt_ms(time_get_data_find_obs_start, now());
461 const auto time_get_data_get_variants_start = now();
462 TimedVariantBaseList variants =
proxyMap[observerName]->getDataFields(it->second);
463 const auto time_get_data_get_variants_dt =
464 dt_ms(time_get_data_get_variants_start, now());
465 time_get_data_get_variants_per_obs[observerName] = time_get_data_get_variants_dt;
466 time_get_data_get_variants += time_get_data_get_variants_dt;
468 const auto time_get_data_lock_start = now();
470 time_get_data_lock += dt_ms(time_get_data_lock_start, now());
472 const auto time_get_data_process_start = now();
473 for (
unsigned int i = 0; i < variants.size(); ++i)
476 VariantPtr var = VariantPtr::dynamicCast(variants[i]);
478 DataFieldIdentifierPtr::dynamicCast(it->second[i])->getIdentifierStr();
479 if (!var->getInitialized())
484 auto type = var->getType();
488 dataMap[
id].rbegin()->
data->getString() != var->getString())
520 for (
const auto& e : dict)
527 std::string key =
id +
"." + e.first;
529 VariantPtr var = VariantPtr::dynamicCast(e.second);
530 auto type = var->getType();
549 time_get_data_process += dt_ms(time_get_data_process_start, now());
552 catch (Ice::NotRegisteredException& e)
555 <<
"Caught Ice::NotRegisteredException: " << e.what();
565 catch (armarx::UserException& e)
568 <<
"\nReason: " << e.reason;
574 const auto time_get_data_end = now();
577 const auto dt_get_data = dt_ms(time_get_data_start, time_get_data_end);
578 const auto dt_clear = dt_ms(time_clear_start, time_clear_end);
579 out <<
"timings PlotterController::getData"
580 <<
"\ndt_clear " << dt_clear <<
" ms"
581 <<
"\ndt_get_data " << dt_get_data <<
" ms"
582 <<
"\n time_get_data_find_obs " << time_get_data_find_obs <<
" ms"
583 <<
"\n time_get_data_get_variants " << time_get_data_get_variants <<
" ms";
584 for (
const auto& [k,
v] : time_get_data_get_variants_per_obs)
586 out <<
"\n " << k <<
"\t" <<
v;
588 out <<
"\n time_get_data_lock " << time_get_data_lock <<
" ms"
589 <<
"\n time_get_data_process " << time_get_data_process <<
" ms";
598 if (samplingIntervalMs < 0)
605 std::map<std::string, TimedVariantBaseList> histories;
618 auto prx =
iceManager->getProxy<ObserverInterfacePrx>(identifier->observerName);
622 auto id = identifier->getIdentifierStr();
623 auto historiesIt = histories.find(
id);
625 if (historiesIt == histories.end())
627 auto start = IceUtil::Time::now();
628 histories[id] = prx->getPartialDatafieldHistory(
629 identifier->channelName,
630 identifier->datafieldName,
631 (now - IceUtil::Time::seconds(
shownInterval)).toMicroSeconds(),
632 now.toMicroSeconds(),
635 << (IceUtil::Time::now() - start).toMilliSecondsDouble()
636 <<
" got " << histories[identifier->channelName].size()
638 historiesIt = histories.find(
id);
641 long lastTimestamp = 0;
643 VariantPtr var = VariantPtr::dynamicCast(prx->getDataField(identifier));
644 auto type = var->getType();
657 for (TimedVariantBasePtr& entry : historiesIt->second)
659 if (lastTimestamp + pollingInterval < entry->getTimestamp())
662 TimeData(IceUtil::Time::microSeconds(entry->getTimestamp()),
663 VariantPtr::dynamicCast(entry)));
664 lastTimestamp = entry->getTimestamp();
670 auto id = identifier->getIdentifierStr();
686 std::string key =
id +
"." + e.first;
687 ARMARX_VERBOSE << key <<
": " << *VariantPtr::dynamicCast(e.second);
688 QwtPlotCurve* curve =
createCurve(QString::fromStdString(key));
691 QwtThermo* bar =
createBar(QString::fromStdString(key));
695 for (
auto& entry : historiesIt->second)
697 if (lastTimestamp + pollingInterval < entry->getTimestamp())
700 for (
const auto& e : dict)
707 std::string key =
id +
"." + e.first;
709 VariantPtr var = VariantPtr::dynamicCast(e.second);
710 auto type = var->getType();
724 IceUtil::Time::microSeconds(entry->getTimestamp()),
761 QwtPlotItem* plotItem =
plotter->infoToItem(itemInfo);
775 QwtPlotCurve* curve =
new QwtPlotCurve(label);
776 curve->setRenderHint(QwtPlotItem::RenderAntialiased);
778 curve->setStyle(QwtPlotCurve::Lines);
780 curve->setPaintAttribute(QwtPlotCurve::ClipPolygons,
true);
794 QwtThermo* bar =
new QwtThermo(this->
widget);
795 bar->setAccessibleName(label);
796 bar->setFillBrush(QBrush(QColor(Qt::GlobalColor((
bars.size() + 7) % 15))));
798 "* { background-color: rgb(240, 240, 240); }");
800 QTextEdit* lab =
new QTextEdit(label, this->
widget);
801 lab->setStyleSheet(
"* { background-color: rgb(240, 240, 240); }");
802 lab->setLineWrapMode(QTextEdit::WidgetWidth);
803 lab->setTextInteractionFlags(
nullptr);
804 lab->setFrameStyle(0);
805 int linecount = lab->document()->blockCount();
806 lab->setMaximumHeight(70 * linecount);
807 lab->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
808 QVBoxLayout* layout =
new QVBoxLayout();
809 layout->addWidget(bar);
810 layout->addWidget(lab);
812 QWidget*
widget =
new QWidget(layout->widget());
813 widget->setLayout(layout);
826 std::vector<std::string>
830 std::vector<std::string> keys;
840 ObserverInterfacePrx observer =
841 iceManager->getProxy<ObserverInterfacePrx>(identifier->observerName);
843 VariantPtr var = VariantPtr::dynamicCast(observer->getDataField(identifier));
857 if (e.first ==
"timestamp")
866 keys.push_back(identifier->getIdentifierStr() +
"." + e.first);
934 int containedItems =
barlayout->count() - 1;
937 int i = containedItems; i >= 0;
942 child->widget()->deleteLater();
1004 if (style ==
"Bar chart")
1011 QwtPlotCurve::CurveStyle st = QwtPlotCurve::Lines;
1012 if (style ==
"Curve (line, steps)")
1014 st = QwtPlotCurve::Steps;
1016 else if (style ==
"Curve (dots)")
1018 st = QwtPlotCurve::Dots;
1020 for (
const auto& [_, curve] :
curves)
1022 curve->setStyle(st);
1029 std::vector<Qt::GlobalColor>