line_panel.cpp
Go to the documentation of this file.
2 
3 namespace graph_rviz_plugin
4 {
5 
6 LinePanel::LinePanel(QWidget *parent) :
7  rviz::Panel(parent),
8  nh_(std::make_shared<ros::NodeHandle>()),
9  start_pause_button_(new QPushButton),
10  topic_button_(new QPushButton("Topics")),
11  stop_button_(new QPushButton("Stop")),
12  graph_settings_button_(new QPushButton("Graph settings")),
13  export_button_(new QPushButton("Export")),
14  graph_refresh_timer_(new QTimer(this)),
15  plot_(new QCustomPlot)
16 {
17  connect(this, &LinePanel::enable, this, &LinePanel::setEnabled);
18  setName("Line graph");
19  setObjectName(getName());
20 
21  yaxis_rescale_auto_ = true;
22  window_time_enable_ = false;
23  legend_enable_ = true;
24  graph_stopped_ = true;
25  y_max_ = 10;
26  refresh_freq_ = 40;
27 
28  qRegisterMetaType<QMessageBox::Icon>();
30 
31  connect(start_pause_button_, &QPushButton::clicked, this, &LinePanel::startPauseClicked);
32  connect(stop_button_, &QPushButton::clicked, this, &LinePanel::stopClicked);
33  connect(topic_button_, &QPushButton::clicked, this, &LinePanel::topicsSelectionClicked);
34  connect(graph_settings_button_, &QPushButton::clicked, this, &LinePanel::graphSettingsClicked);
35  QPushButton *settings_button = new QPushButton("Settings");
36  connect(settings_button, &QPushButton::clicked, this, &LinePanel::settingsClicked);
37  connect(export_button_, &QPushButton::clicked, this, &LinePanel::exportClicked);
38  QPushButton *reset_button = new QPushButton("Reset");
39  connect(reset_button, &QPushButton::clicked, this, &LinePanel::resetClicked);
40 
41  start_pause_button_->setText("Start");
42 
43  QHBoxLayout *button_layout = new QHBoxLayout();
44  button_layout->addWidget(start_pause_button_);
45  button_layout->addWidget(stop_button_);
46  button_layout->addStretch(1);
47  button_layout->addWidget(topic_button_);
48  button_layout->addWidget(graph_settings_button_);
49  button_layout->addWidget(settings_button);
50  button_layout->addWidget(export_button_);
51  button_layout->addStretch(1);
52  button_layout->addWidget(reset_button);
53 
54  QVBoxLayout *layout = new QVBoxLayout();
55  setLayout(layout);
56  layout->addLayout(button_layout);
57  layout->addWidget(plot_);
58 
59  connect(graph_refresh_timer_, &QTimer::timeout, this, &LinePanel::graphUpdate);
60 
61  QFont legendFont = font();
62  legendFont.setPointSize(9);
63  plot_->legend->setFont(legendFont);
64  plot_->legend->setBrush(QBrush(Qt::GlobalColor::white));
65 
66  start_pause_button_->setEnabled(false);
67  stop_button_->setEnabled(false);
68  graph_settings_button_->setEnabled(false);
69  export_button_->setEnabled(false);
70 
71  start_pause_button_->setMinimumWidth(45);
72  stop_button_->setMinimumWidth(45);
73  topic_button_->setMinimumWidth(50);
74  graph_settings_button_->setMinimumWidth(95);
75  settings_button->setMinimumWidth(70);
76  export_button_->setMinimumWidth(50);
77  reset_button->setMinimumWidth(45);
78 }
79 
81 {
82  nh_->shutdown();
83  graph_refresh_timer_->stop();
84 }
85 
87 {
88  for (unsigned i = 0; i < displayed_topics_.size(); i++)
89  {
90  plot_->addGraph();
92  plot_->graph(i)->setName(QString::fromStdString(displayed_topics_.at(i)->topic_name_));
93  plot_->graph(i)->addToLegend();
94  }
95 }
96 
98 {
99  for (unsigned i = 0; i < displayed_topics_.size(); i++)
100  {
101  plot_->graph(i)->setPen(QPen(displayed_topics_.at(i)->color_, displayed_topics_.at(i)->thickness_));
102  plot_->graph(i)->setLineStyle(displayed_topics_.at(i)->line_style_);
103  plot_->graph(i)->setVisible(displayed_topics_.at(i)->displayed_);
104  }
105 
106  plot_->replot();
107 }
108 
110 {
111  for (unsigned i = 0; i < displayed_topics_.size(); i++)
112  {
113  if (displayed_topics_.at(i)->data_update_ == true)
114  {
115  QVector<double> topic_data = displayed_topics_.at(i)->getTopicData();
116  QVector<double> topic_time = displayed_topics_.at(i)->getTopicTime();
117 
118  if (yaxis_rescale_auto_ == true)
119  plot_->yAxis->rescale(true);
120  else
122 
123  if (window_time_enable_ == false)
124  plot_->xAxis->rescale(true);
125  else
126  {
127  if (!topic_time.empty())
128  plot_->xAxis->setRange(topic_time.last(), w_time_, Qt::AlignRight);
129  else
130  plot_->xAxis->setRange(5, w_time_, Qt::AlignRight);
131  }
132 
133  plot_->graph(i)->setData(topic_time, topic_data, true);
134  displayed_topics_.at(i)->data_update_ = false;
135  plot_->replot();
136  }
137  }
138 }
139 
140 void LinePanel::displayMessageBoxHandler(const QString title,
141  const QString message,
142  const QString info_msg,
143  const QMessageBox::Icon icon)
144 {
145  const bool old(isEnabled());
146  Q_EMIT setEnabled(false);
147  QMessageBox msg_box;
148  msg_box.setWindowTitle(title);
149  msg_box.setText(message);
150  msg_box.setInformativeText(info_msg);
151  msg_box.setIcon(icon);
152  msg_box.setStandardButtons(QMessageBox::Ok);
153  msg_box.exec();
154  Q_EMIT setEnabled(old);
155 }
156 
157 void LinePanel::load(const rviz::Config &config)
158 {
159  rviz::Panel::load(config);
160 
161  unsigned i(0);
162  {
163  bool tmp;
164 
165  if (config.mapGetBool("window_time_enable", &tmp))
166  window_time_enable_ = tmp;
167 
168  if (config.mapGetBool("yaxis_rescale_auto", &tmp))
169  yaxis_rescale_auto_ = tmp;
170 
171  if (config.mapGetBool("legend_enable", &tmp))
172  legend_enable_ = tmp;
173  }
174 
175  {
176  float tmp;
177 
178  if (config.mapGetFloat("w_time", &tmp))
179  w_time_ = (double) tmp;
180 
181  if (config.mapGetFloat("y_min", &tmp))
182  y_min_ = (double) tmp;
183 
184  if (config.mapGetFloat("y_max", &tmp))
185  y_max_ = (double) tmp;
186  }
187 
188  {
189  int tmp;
190 
191  if (config.mapGetInt("refresh_freq", &tmp))
192  refresh_freq_ = std::abs(tmp);
193  }
194 
195  {
196  QString tmp;
197 
198  if (config.mapGetString("export_directory", &tmp))
199  export_directory_ = tmp;
200  }
201 
202  while (1)
203  {
204  QString topic_name;
205  QString topic_type;
206  int topic_thickness;
207  int color_index;
208 
209  if (!config.mapGetString("topic_" + QString::number(i) + "_name", &topic_name))
210  break;
211 
212  if (!config.mapGetString("topic_" + QString::number(i) + "_type", &topic_type))
213  break;
214 
215  if (!config.mapGetInt("topic_" + QString::number(i) + "_thickness", &topic_thickness))
216  break;
217 
218  if (!config.mapGetInt("topic_" + QString::number(i) + "_color", &color_index))
219  break;
220 
221  std::shared_ptr<TopicData> topic_data = std::make_shared<TopicData>(topic_name.toStdString(),
222  topic_type.toStdString(), nh_);
223  topic_data->thickness_ = topic_thickness;
224  topic_data->color_ = topic_color_class_.getColorFromIndex(color_index);
225  displayed_topics_.push_back(topic_data);
226  ++i;
227  }
228 
229  if (displayed_topics_.empty())
230  return;
231 
232  start_pause_button_->setEnabled(true);
233  stop_button_->setEnabled(true);
234  graph_settings_button_->setEnabled(true);
235  graphInit();
238 }
239 
240 void LinePanel::save(rviz::Config config) const
241 {
242  rviz::Panel::save(config);
243  config.mapSetValue("window_time_enable", window_time_enable_.load());
244  config.mapSetValue("yaxis_rescale_auto", yaxis_rescale_auto_.load());
245  config.mapSetValue("legend_enable", legend_enable_.load());
246  config.mapSetValue("w_time", w_time_);
247  config.mapSetValue("y_min", y_min_);
248  config.mapSetValue("y_max", y_max_);
249  config.mapSetValue("refresh_freq", refresh_freq_);
250  config.mapSetValue("export_directory", export_directory_);
251 
252  for (unsigned i = 0; i < displayed_topics_.size(); i++)
253  {
254  config.mapSetValue("topic_" + QString::number(i) + "_name",
255  QString::fromStdString(displayed_topics_.at(i)->topic_name_));
256  config.mapSetValue("topic_" + QString::number(i) + "_type",
257  QString::fromStdString(displayed_topics_.at(i)->topic_type_));
258  config.mapSetValue("topic_" + QString::number(i) + "_thickness", displayed_topics_.at(i)->thickness_);
259  config.mapSetValue("topic_" + QString::number(i) + "_color",
261  }
262 }
263 
265 {
266  if ((graph_refresh_timer_->isActive()) == false)
267  {
268  graph_refresh_timer_->start((1.0 / refresh_freq_) * 1000.0); // Hz > seconds > milliseconds
269  start_pause_button_->setText("Pause");
272  topic_button_->setEnabled(false);
273  stop_button_->setEnabled(true);
274  export_button_->setEnabled(false);
275 
276  if (graph_stopped_ == true)
277  {
278  graph_stopped_ = false;
279  plot_->clearGraphs();
281  plot_->replot();
282  graphInit();
283 
284  for (unsigned i = 0; i < displayed_topics_.size(); i++)
285  {
286  displayed_topics_.at(i)->clearData();
287  displayed_topics_.at(i)->startRefreshData();
288  }
289 
291  graphUpdate();
292  }
293 
294  return;
295  }
296 
297  else
298  {
299  graph_refresh_timer_->stop();
300  start_pause_button_->setText("Start");
302  export_button_->setEnabled(true);
303  return;
304  }
305 }
306 
308 {
309  topic_button_->setEnabled(true);
310 
311  if ((graph_refresh_timer_->isActive()) == true)
313 
314  for (unsigned i = 0; i < displayed_topics_.size(); i++)
315  displayed_topics_.at(i)->stopRefreshData();
316 
317  graph_stopped_ = true;
318 }
319 
321 {
322  if ((graph_refresh_timer_->isActive()) == true)
324 
325  for (unsigned i = 0; i < displayed_topics_.size(); i++)
326  {
327  displayed_topics_.at(i)->stopRefreshData();
328  displayed_topics_.at(i)->clearData();
329  }
330 
331  displayed_topics_.clear();
332  plot_->legend->setVisible(false);
333  plot_->clearGraphs();
335  plot_->replot();
336 
337  start_pause_button_->setEnabled(false);
338  stop_button_->setEnabled(false);
339  graph_settings_button_->setEnabled(false);
340  topic_button_->setEnabled(true);
341 
342  Q_EMIT configChanged();
343 }
344 
346 {
347  QString file_name = QFileDialog::getSaveFileName(this, tr("Save file"), export_directory_ + "/graph.png",
348  tr("PNG (*.png);; JPG (*.jpg) ;; PDF (*.pdf)"));
349 
350  if (file_name.isEmpty())
351  return;
352 
353  QFileInfo path = QFile(file_name);
354 
355  if (path.completeSuffix() == "png")
356  plot_->savePng(file_name);
357  else if (path.completeSuffix() == "jpg")
358  plot_->saveJpg(file_name);
359  else
360  plot_->savePdf(file_name);
361 
362  export_directory_ = path.absolutePath();
363 
364  Q_EMIT configChanged();
365 }
366 
368 {
369  std::vector<std::string> allowed_topics;
370  allowed_topics.emplace_back("std_msgs/Bool");
371  allowed_topics.emplace_back("std_msgs/Int8");
372  allowed_topics.emplace_back("std_msgs/UInt8");
373  allowed_topics.emplace_back("std_msgs/Int16");
374  allowed_topics.emplace_back("std_msgs/UInt16");
375  allowed_topics.emplace_back("std_msgs/Int32");
376  allowed_topics.emplace_back("std_msgs/UInt32");
377  allowed_topics.emplace_back("std_msgs/Int64");
378  allowed_topics.emplace_back("std_msgs/UInt64");
379  allowed_topics.emplace_back("std_msgs/Float32");
380  allowed_topics.emplace_back("std_msgs/Float64");
381 
382  SelectionTopics *topic_window = new SelectionTopics(nh_, displayed_topics_, allowed_topics, false);
383 
384  if (topic_window->supported_topics_.empty())
385  {
386  Q_EMIT displayMessageBox("No supported topic", "Error with topics, no supported topics found.", "",
387  QMessageBox::Icon::Warning);
388  return;
389  }
390 
391  if (topic_window->exec())
392  {
393  if ((graph_refresh_timer_->isActive()) == true)
395 
396  resetClicked();
397  displayed_topics_ = topic_window->displayed_topics_;
398 
399  for (unsigned i = 0; i < displayed_topics_.size(); i++)
401  i % ((topic_color_class_.colors_list_).size()));
402 
403  graphInit();
405  Q_EMIT configChanged();
407 
408  if (displayed_topics_.empty() == false)
409  {
410  start_pause_button_->setEnabled(true);
411  graph_settings_button_->setEnabled(true);
412  }
413  }
414 }
415 
417 {
418  GraphSettings *configure_topics = new GraphSettings(displayed_topics_);
419 
420  if (configure_topics->exec())
422 }
423 
425 {
428 
429  if (!configure_graph->exec())
430  return;
431 
432  window_time_enable_ = configure_graph->window_time_enable_;
433  yaxis_rescale_auto_ = configure_graph->scale_auto_;
434  w_time_ = configure_graph->w_time_;
435  y_min_ = configure_graph->y_min_;
436  y_max_ = configure_graph->y_max_;
437  legend_enable_ = configure_graph->legend_enable_;
439  refresh_freq_ = configure_graph->refresh_freq_; // Hz
440  Q_EMIT configChanged();
441 
442  // Restart the timer in case we are recording
443  if (graph_refresh_timer_->isActive())
444  {
445  graph_refresh_timer_->stop();
446  graph_refresh_timer_->start((1.0 / configure_graph->refresh_freq_) * 1000.0); // Hz > seconds > milliseconds
447  }
448 }
449 
450 void LinePanel::enableLegend(bool legend_enable)
451 {
452  plot_->legend->setVisible(legend_enable);
453 }
454 
455 }
457 
459 
bool saveJpg(const QString &fileName, int width=0, int height=0, double scale=1.0, int quality=-1, int resolution=96, QCP::ResolutionUnit resolutionUnit=QCP::ruDotsPerInch)
0x001 Axis ranges are draggable (see QCPAxisRect::setRangeDrag, QCPAxisRect::setRangeDragAxes) ...
Definition: qcustomplot.h:256
std::atomic< bool > window_time_enable_
Definition: line_panel.hpp:79
QCPGraph * graph(int index) const
void setName(const QString &name)
LinePanel(QWidget *parent=0)
Definition: line_panel.cpp:6
void rescale(bool onlyVisiblePlottables=false)
void setInteractions(const QCP::Interactions &interactions)
virtual QString getName() const
std::deque< std::shared_ptr< TopicData > > displayed_topics_
void setBrush(const QBrush &brush)
QPushButton * start_pause_button_
Definition: line_panel.hpp:67
int clearPlottables()
int getIndexFromColor(const QColor color) const
Definition: topic_color.cpp:18
Q_SLOT void replot(QCustomPlot::RefreshPriority refreshPriority=QCustomPlot::rpRefreshHint)
std::shared_ptr< ros::NodeHandle > nh_
Definition: line_panel.hpp:66
Q_SLOT void setRange(const QCPRange &range)
virtual void save(Config config) const
bool mapGetString(const QString &key, QString *value_out) const
void configChanged()
std::atomic< bool > graph_stopped_
Definition: line_panel.hpp:80
void displayMessageBoxHandler(const QString title, const QString text, const QString info="", const QMessageBox::Icon icon=QMessageBox::Icon::Information)
Definition: line_panel.cpp:140
QCPAxis * yAxis
Definition: qcustomplot.h:3739
void displayMessageBox(const QString, const QString, const QString, const QMessageBox::Icon)
void mapSetValue(const QString &key, QVariant value)
std::atomic< bool > yaxis_rescale_auto_
Definition: line_panel.hpp:78
virtual void save(rviz::Config config) const
Definition: line_panel.cpp:240
The central class of the library. This is the QWidget which displays the plot and interacts with the ...
Definition: qcustomplot.h:3590
QPushButton * graph_settings_button_
Definition: line_panel.hpp:70
bool savePng(const QString &fileName, int width=0, int height=0, double scale=1.0, int quality=-1, int resolution=96, QCP::ResolutionUnit resolutionUnit=QCP::ruDotsPerInch)
virtual void setName(const QString &name)
std::vector< std::pair< QString, QColor > > colors_list_
Definition: topic_color.hpp:17
bool savePdf(const QString &fileName, int width=0, int height=0, QCP::ExportPen exportPen=QCP::epAllowCosmetic, const QString &pdfCreator=QString(), const QString &pdfTitle=QString())
void setPen(const QPen &pen)
QCPGraph * addGraph(QCPAxis *keyAxis=0, QCPAxis *valueAxis=0)
QCPLegend * legend
Definition: qcustomplot.h:3740
bool mapGetFloat(const QString &key, float *value_out) const
void setInteraction(const QCP::Interaction &interaction, bool enabled=true)
void setLineStyle(LineStyle ls)
void setVisible(bool on)
void setData(QSharedPointer< QCPGraphDataContainer > data)
bool mapGetBool(const QString &key, bool *value_out) const
ros::master::V_TopicInfo supported_topics_
std::atomic< bool > legend_enable_
Definition: line_panel.hpp:77
void setFont(const QFont &font)
0x002 Axis ranges are zoomable with the mouse wheel (see QCPAxisRect::setRangeZoom, QCPAxisRect::setRangeZoomAxes)
Definition: qcustomplot.h:257
bool removeFromLegend(QCPLegend *legend) const
void enableLegend(bool legend_enable)
Definition: line_panel.cpp:450
virtual void load(const Config &config)
bool mapGetInt(const QString &key, int *value_out) const
#define PLUGINLIB_EXPORT_CLASS(class_type, base_class_type)
virtual void load(const rviz::Config &config)
Definition: line_panel.cpp:157
QColor getColorFromIndex(const int index) const
Definition: topic_color.cpp:10
QCPAxis * xAxis
Definition: qcustomplot.h:3739
std::deque< std::shared_ptr< TopicData > > displayed_topics_
Definition: line_panel.hpp:76
bool addToLegend(QCPLegend *legend)


graph_rviz_plugin
Author(s): Édouard Pronier, Victor Lamoine - Institut Maupertuis
autogenerated on Mon Feb 28 2022 22:27:30