signal_helper.cpp
Go to the documentation of this file.
1 /*********************************************************************
2  *
3  * Software License Agreement
4  *
5  * Copyright (c) 2020,
6  * TU Dortmund - Institute of Control Theory and Systems Engineering.
7  * All rights reserved.
8  *
9  * This program is free software: you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation, either version 3 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program. If not, see <https://www.gnu.org/licenses/>.
21  *
22  * Authors: Christoph Rösmann
23  *********************************************************************/
24 
25 #include <corbo-core/console.h>
27 #include <corbo-gui/utilities.h>
28 
29 #include <memory>
30 #include <string>
31 
32 namespace corbo {
33 namespace gui {
34 
35 void SignalHelper::addSignal(const messages::Signal& signal)
36 {
37  std::stringstream issues;
38 
39  if (signal.header().name().empty())
40  {
41  PRINT_WARNING_NAMED("Received signal without id/namespace. Skipping...");
42  return;
43  }
44 
45  if (signal.has_measurement())
46  {
47  Measurement::Ptr measurement = std::make_shared<Measurement>();
48  measurement->fromMessage(signal, &issues);
49  if (!issues.str().empty())
50  {
51  PRINT_WARNING_NAMED(issues.str());
52  return;
53  }
54  addMeasurement(QString::fromStdString(signal.header().name()), measurement);
55  }
56  else if (signal.has_time_series())
57  {
58  TimeSeriesSignal::Ptr ts = std::make_shared<TimeSeriesSignal>();
59  ts->fromMessage(signal, &issues);
60 
61  if (!issues.str().empty())
62  {
63  PRINT_WARNING_NAMED(issues.str());
64  return;
65  }
66  addTimeSeries(QString::fromStdString(signal.header().name()), ts);
67  }
68  else if (signal.has_indexed_values())
69  {
70  IndexedValuesSignal::Ptr indexed_values = std::make_shared<IndexedValuesSignal>();
71  indexed_values->fromMessage(signal, &issues);
72 
73  if (!issues.str().empty())
74  {
75  PRINT_WARNING_NAMED(issues.str());
76  return;
77  }
78  addIndexedValues(QString::fromStdString(signal.header().name()), indexed_values);
79  }
80  else if (signal.has_indexed_values_set())
81  {
82  IndexedValuesSetSignal::Ptr indexed_values_set = std::make_shared<IndexedValuesSetSignal>();
83  indexed_values_set->fromMessage(signal, &issues);
84 
85  if (!issues.str().empty())
86  {
87  PRINT_WARNING_NAMED(issues.str());
88  return;
89  }
90  addIndexedValuesSet(QString::fromStdString(signal.header().name()), indexed_values_set);
91  }
92  else if (signal.has_matrix())
93  {
94  MatrixSignal::Ptr matrix_signal = std::make_shared<MatrixSignal>();
95  matrix_signal->fromMessage(signal, &issues);
96 
97  if (!issues.str().empty())
98  {
99  PRINT_WARNING_NAMED(issues.str());
100  return;
101  }
102  addMatrixSignal(QString::fromStdString(signal.header().name()), matrix_signal);
103  }
104  else
105  {
106  PRINT_ERROR_NAMED("The gui currently does not support the message type of " << signal.header().name());
107  }
108 
109  // else if (signal.has_values())
110  // {
111  // ValuesSignal::Ptr signal_obj = std::make_shared<ValuesSignal>();
112  // signal_obj->fromMessage(signal, &issues);
113  // if (!issues.str().empty())
114  // {
115  // PRINT_WARNING("SignalHelper::addSignal(): " << issues.str());
116  // return;
117  // }
118  // addValuesSignal(QString::fromStdString(signal.header().name()), signal_obj);
119  // }
120 }
121 
122 void SignalHelper::addMeasurement(const QString& name, Measurement::ConstPtr measurement)
123 {
124  QString key = name2Key(name);
125  auto it = _signal_map.find(key);
126 
127  if (it == _signal_map.end())
128  {
129  // new signal
130  it = _signal_map.insert(key, SignalData());
131  it->name = name;
132  extractNamespace(name, it->namespaces);
133  it->short_name = it->namespaces.back();
134  it->task_id = _id;
135  it->dimension = measurement->header.value_dimension;
136  it->zero_order_hold = measurement->header.zero_order_hold;
137  for (const std::string& label : measurement->getValueLabels()) it->value_labels.push_back(QString::fromStdString(label));
138 
139  TimeSeriesSignal::Ptr ts = std::make_shared<TimeSeriesSignal>(measurement->header.value_dimension);
140  ts->header = measurement->header;
141  if (!measurement->getValues().empty()) ts->add(*measurement);
142  it->signal = ts;
143  emit newMeasurement(key, measurement, *it, true);
144  emit newSignal(key, *it);
145  }
146  else
147  {
148  if (!measurement->getValues().empty())
149  {
150  std::static_pointer_cast<TimeSeriesSignal>(it->signal)->add(*measurement);
151  }
152  emit newMeasurement(key, measurement, *it, false);
153  }
154 
155  if (!measurement->getValues().empty())
156  {
157  _signal_tree_map[_id].sendMeasurement(measurement);
158  }
159 }
160 
161 void SignalHelper::addTimeSeries(const QString& name, TimeSeriesSignal::Ptr ts)
162 {
163  QString key = name2Key(name);
164  auto it = _signal_map.find(key);
165  if (it == _signal_map.end())
166  {
167  // new signal
168  it = _signal_map.insert(key, SignalData());
169  it->name = name;
170  extractNamespace(name, it->namespaces);
171  it->short_name = it->namespaces.back();
172  it->task_id = _id;
173  it->dimension =
174  ts->getTimeSeries() ? ts->getTimeSeries()->getValueDimension() : ts->header.value_dimension; // TODO(roesmann) unqiue variable?
175  it->zero_order_hold = ts->header.zero_order_hold;
176  std::vector<std::string> sublabels;
177  ts->getValueLabels(sublabels);
178  for (const std::string& label : sublabels) it->value_labels.push_back(QString::fromStdString(label));
179 
180  // Create parent signal
181  TimeSeriesSequenceSignal::Ptr sequence = std::make_shared<TimeSeriesSequenceSignal>(it->dimension);
182  sequence->header = ts->header;
183  if (!ts->isEmpty()) sequence->add(ts->getTimeSeriesPtr());
184  it->signal = sequence;
185  emit newTimeSeries(key, ts, *it, true);
186  emit newSignal(key, *it);
187  }
188  else
189  {
190  if (!ts->isEmpty())
191  {
192  std::static_pointer_cast<TimeSeriesSequenceSignal>(it->signal)->add(ts->getTimeSeriesPtr());
193  }
194  emit newTimeSeries(key, ts, *it, false);
195  }
196 
197  if (!ts->isEmpty())
198  {
199  // add time series to signal tree map
200  _signal_tree_map[_id].sendTimeSeries(ts);
201  }
202 }
203 
204 void SignalHelper::addIndexedValues(const QString& name, IndexedValuesSignal::Ptr indexed_values)
205 {
206  QString key = name2Key(name);
207  auto it = _signal_map.find(key);
208 
209  if (it == _signal_map.end())
210  {
211  // new signal
212  it = _signal_map.insert(key, SignalData());
213  it->name = name;
214  extractNamespace(name, it->namespaces);
215  it->short_name = it->namespaces.back();
216  it->task_id = _id;
217  it->dimension = 1; // values are not intended to be shown as separate signal-widgets.
218  it->zero_order_hold = indexed_values->header.zero_order_hold;
219 
220  IndexedValuesSetSignal::Ptr set = std::make_shared<IndexedValuesSetSignal>();
221  set->header = indexed_values->header;
222  if (!indexed_values->isEmpty()) set->add(*indexed_values);
223  it->signal = set;
224  emit newIndexedValues(key, indexed_values, *it, true);
225  emit newSignal(key, *it);
226  }
227  else
228  {
229  if (!indexed_values->isEmpty())
230  {
231  std::static_pointer_cast<IndexedValuesSetSignal>(it->signal)->add(*indexed_values);
232  }
233  emit newIndexedValues(key, indexed_values, *it, false);
234  }
235 
236  if (!indexed_values->isEmpty())
237  {
238  _signal_tree_map[_id].sendIndexedValues(indexed_values);
239  }
240 }
241 
242 void SignalHelper::addIndexedValuesSet(const QString& name, IndexedValuesSetSignal::Ptr indexed_values_set)
243 {
244  PRINT_ERROR_NAMED("not yet implemented!");
245  /*
246  QString key = name2Key(name);
247  auto it = _signal_map.find(key);
248  if (it == _signal_map.end())
249  {
250  // new signal
251  it = _signal_map.insert(key, SignalData());
252  it->name = name;
253  extractNamespace(name, it->namespaces);
254  it->short_name = it->namespaces.back();
255  it->task_id = _id;
256  it->dimension =
257  ts->getTimeSeries() ? ts->getTimeSeries()->getValueDimension() : ts->header.value_dimension; // TODO(roesmann) unqiue variable?
258  it->zero_order_hold = ts->header.zero_order_hold;
259  std::vector<std::string> sublabels;
260  ts->getValueLabels(sublabels);
261  for (const std::string& label : sublabels) it->value_labels.push_back(QString::fromStdString(label));
262 
263  // Create parent signal
264  TimeSeriesSequenceSignal::Ptr sequence = std::make_shared<TimeSeriesSequenceSignal>(it->dimension);
265  sequence->header = ts->header;
266  if (!ts->isEmpty()) sequence->add(ts->getTimeSeriesPtr());
267  it->signal = sequence;
268  emit newIndexedValuesSet(key, indexed_values_set, *it, true);
269  emit newSignal(key, *it);
270  }
271  else
272  {
273  if (!indexed_values_set->isEmpty())
274  {
275  std::static_pointer_cast<TimeSeriesSequenceSignal>(it->signal)->add(ts->getTimeSeriesPtr());
276  }
277  emit newIndexedValuesSet(key, indexed_values_set, *it, false);
278  }
279  */
280 }
281 
282 void SignalHelper::addMatrixSignal(const QString& name, MatrixSignal::Ptr matrix_signal)
283 {
284  QString key = name2Key(name);
285  auto it = _signal_map.find(key);
286 
287  if (it == _signal_map.end())
288  {
289  // new signal
290  it = _signal_map.insert(key, SignalData());
291  it->name = name;
292  extractNamespace(name, it->namespaces);
293  it->short_name = it->namespaces.back();
294  it->task_id = _id;
295  it->dimension = 1; // values are not intended to be shown as separate signal-widgets.
296  it->zero_order_hold = matrix_signal->header.zero_order_hold;
297 
298  MatrixSetSignal::Ptr set = std::make_shared<MatrixSetSignal>();
299  set->header = matrix_signal->header;
300  if (!matrix_signal->isEmpty()) set->add(matrix_signal);
301  it->signal = set;
302  emit newMatrixSignal(key, matrix_signal, *it, true);
303  emit newSignal(key, *it);
304  }
305  else
306  {
307  if (!matrix_signal->isEmpty())
308  {
309  std::static_pointer_cast<MatrixSetSignal>(it->signal)->add(matrix_signal);
310  }
311  emit newMatrixSignal(key, matrix_signal, *it, false);
312  }
313 
314  if (!matrix_signal->isEmpty())
315  {
316  _signal_tree_map[_id].sendMatrix(matrix_signal);
317  }
318 }
319 
320 // void SignalHelper::addSignal(const QString& name, const SignalInterface::Ptr signal)
321 //{
322 
323 // QString key = name2Key(name);
324 // auto it = _signal_map.find(key);
325 
326 // if (it != _signal_map.end())
327 // {
328 // return; // TODO
329 // }
330 // // // signal already known, replace
331 // // it->name = name;
332 // // extractNamespace(name, it->namespaces);
333 // // it->short_name = it->namespaces.back();
334 // // it->signal = signal;
335 // // it->task_id = _id;
336 // // emit newSignal(key, *it, true);
337 // // }
338 
339 // // check parent type
340 // switch (signal->header.parent_type)
341 // {
342 // case SignalType::NoParent:
343 // {
344 // break;
345 // }
346 // default:
347 // {
348 // }
349 // }
350 
351 // else
352 // {
353 
354 // // check if we need an appropriate parent signal
355 // if (signal->header.has_parent)
356 // {
357 // it->signal = signal;
358 // }
359 // else
360 // {
361 // // add signal directly
362 // }
363 // emit newSignal(key, *it, false);
364 // }
365 //}
366 
368 {
369  auto signal_it = _signal_map.find(key);
370  if (signal_it != _signal_map.end())
371  {
372  return &signal_it.value();
373  }
374  return nullptr;
375 }
376 const SignalHelper::SignalData* SignalHelper::signalData(const QString& key) const
377 {
378  auto signal_it = _signal_map.find(key);
379  if (signal_it != _signal_map.end())
380  {
381  return &signal_it.value();
382  }
383  return nullptr;
384 }
385 
386 void SignalHelper::extractNamespace(const QString& name, QStringList& namespaces) { namespaces = name.split(corbo::SIGNAL_NAMESPACE_DELIMITER); }
387 
388 QString SignalHelper::name2Key(const QString& name) const { return name2Key(name, _id); }
389 QString SignalHelper::name2Key(const QString& name, int id) { return QString::number(id) + util::SIGNAL_NAMESPACE_PREFIX_DELIMITER + name; }
390 
391 bool SignalHelper::key2Name(const QString& key, QString& name, int& id)
392 {
393  bool ret_val = true;
394  QStringList token = key.split(util::SIGNAL_NAMESPACE_PREFIX_DELIMITER);
395  if (token.size() < 2)
396  {
397  name = key;
398  id = 0;
399  ret_val = false;
400  }
401  else
402  {
403  id = token.front().toInt(&ret_val);
404  name = token.back();
405  }
406  PRINT_WARNING_COND(!ret_val, "SignalHelper::key2Name(): unknown format in " << key.toStdString());
407  return ret_val;
408 }
409 
410 void SignalHelper::clearSeries(int task_id)
411 {
412  QMutableHashIterator<QString, SignalData> map_it(_signal_map);
413  while (map_it.hasNext())
414  {
415  map_it.next();
416 
417  if (map_it.value().task_id == task_id)
418  {
419  QString removed_name = map_it.value().name;
420  int removed_id = map_it.value().task_id;
421  map_it.remove();
422  emit signalRemoved(name2Key(removed_name, removed_id), ALL_VALUES);
423  }
424  }
425  _signal_tree_map.erase(task_id);
426 }
427 
428 void SignalHelper::clearNamespace(const QString& namespace_pattern, int task_id)
429 {
430  QMutableHashIterator<QString, SignalData> map_it(_signal_map);
431  while (map_it.hasNext())
432  {
433  map_it.next();
434 
435  if (task_id < 0 || map_it.value().task_id != task_id) continue;
436 
437  if (map_it.value().name.contains(namespace_pattern))
438  {
439  QString removed_name = map_it.value().name;
440  int removed_id = map_it.value().task_id;
441  map_it.remove();
442  emit signalRemoved(name2Key(removed_name, removed_id), ALL_VALUES);
443  }
444  }
445  PRINT_WARNING_NAMED("This function is random");
446 }
447 
449 {
450  QMutableHashIterator<QString, SignalData> map_it(_signal_map);
451  while (map_it.hasNext())
452  {
453  map_it.next();
454 
455  QString removed_name = map_it.value().name;
456  int removed_id = map_it.value().task_id;
457  map_it.remove();
458  emit signalRemoved(name2Key(removed_name, removed_id), ALL_VALUES);
459  }
460  _signal_tree_map.clear();
461 }
462 
463 void SignalHelper::removeSignal(const QString& key)
464 {
465  auto it = _signal_map.find(key);
466  if (it != _signal_map.end())
467  {
468  _signal_map.erase(it);
469  emit signalRemoved(key, ALL_VALUES);
470  }
471 
472  QString name;
473  int id;
474  key2Name(key, name, id);
475 
476  _signal_tree_map[id].removeSignal(name.toStdString());
477 
478  if (_signal_tree_map[id].isEmpty())
479  {
480  _signal_tree_map.erase(id);
481  }
482 }
483 
484 void SignalHelper::removeSignal(const QString& key, int value_idx)
485 {
486  auto it = _signal_map.find(key);
487  if (it != _signal_map.end())
488  {
489  // remove value_idx from the set of used indices
490  auto idx_it = it->active_indices.find(value_idx);
491  if (idx_it != it->active_indices.end())
492  {
493  it->active_indices.erase(idx_it);
494 
495  // if this was the last value_idx, remove completely
496  if (it->active_indices.isEmpty())
497  {
498  // _signal_map.erase(it);
499  removeSignal(key);
500  // emit signalRemoved(key, ALL_VALUES);
501  }
502  else
503  emit signalRemoved(key, value_idx);
504  }
505  }
506 }
507 
509 {
510  PRINT_INFO("---");
511  PRINT_INFO("Signals: ");
512  for (auto it = _signal_map.begin(); it != _signal_map.end(); ++it)
513  {
514  PRINT_INFO(it.key().toStdString());
515  }
516  PRINT_INFO("---");
517 }
518 
519 } // namespace gui
520 } // namespace corbo
corbo::MatrixSignal::Ptr
std::shared_ptr< MatrixSignal > Ptr
Definition: signals.h:564
PRINT_WARNING_NAMED
#define PRINT_WARNING_NAMED(msg)
Definition: console.h:255
corbo::gui::util::SIGNAL_NAMESPACE_PREFIX_DELIMITER
constexpr const char SIGNAL_NAMESPACE_PREFIX_DELIMITER[]
Definition: gui/include/corbo-gui/utilities.h:93
corbo::gui::SignalHelper::clearNamespace
void clearNamespace(const QString &namespace_pattern, int task_id)
Definition: signal_helper.cpp:472
corbo::gui::SignalHelper::newMeasurement
void newMeasurement(const QString &key, Measurement::ConstPtr measurement, SignalData &signal_data, bool first)
PRINT_ERROR_NAMED
#define PRINT_ERROR_NAMED(msg)
Definition: console.h:260
corbo
Definition: communication/include/corbo-communication/utilities.h:37
corbo::gui::SignalHelper::clearSeries
void clearSeries(int task_id)
Definition: signal_helper.cpp:454
signal_helper.h
console.h
corbo::gui::SignalHelper::key2Name
static bool key2Name(const QString &key, QString &name, int &id)
Definition: signal_helper.cpp:435
corbo::MatrixSetSignal::Ptr
std::shared_ptr< MatrixSetSignal > Ptr
Definition: signals.h:632
corbo::gui::SignalHelper::newIndexedValues
void newIndexedValues(const QString &key, IndexedValuesSignal::ConstPtr indexed_values, SignalData &signal_data, bool first)
corbo::Measurement::Ptr
std::shared_ptr< Measurement > Ptr
Definition: signals.h:196
corbo::gui::SignalHelper::addMeasurement
void addMeasurement(const QString &name, Measurement::ConstPtr measurement)
Definition: signal_helper.cpp:166
corbo::gui::SignalHelper::_signal_tree_map
std::map< int, CommonSignalTarget > _signal_tree_map
Definition: signal_helper.h:186
corbo::gui::SignalHelper::addIndexedValuesSet
void addIndexedValuesSet(const QString &name, IndexedValuesSetSignal::Ptr indexed_values_set)
Definition: signal_helper.cpp:286
corbo::gui::SignalHelper::addSignal
void addSignal(const messages::Signal &signal)
Definition: signal_helper.cpp:79
corbo::gui::SignalHelper::name2Key
static QString name2Key(const QString &name, int id)
Definition: signal_helper.cpp:433
PRINT_WARNING_COND
#define PRINT_WARNING_COND(cond, msg)
Print msg-stream only if cond == true.
Definition: console.h:159
corbo::gui::SignalHelper::signalData
SignalData * signalData(const QString &key)
Definition: signal_helper.cpp:411
corbo::gui::SignalHelper::addMatrixSignal
void addMatrixSignal(const QString &name, MatrixSignal::Ptr matrix_signal)
Definition: signal_helper.cpp:326
corbo::gui::SignalHelper::clearAll
void clearAll()
Definition: signal_helper.cpp:492
corbo::gui::SignalHelper::addTimeSeries
void addTimeSeries(const QString &name, TimeSeriesSignal::Ptr ts)
Definition: signal_helper.cpp:205
corbo::gui::SignalHelper::removeSignal
void removeSignal(const QString &key)
Definition: signal_helper.cpp:507
corbo::SIGNAL_NAMESPACE_DELIMITER
constexpr const char SIGNAL_NAMESPACE_DELIMITER
Definition: signals.h:68
corbo::IndexedValuesSignal::Ptr
std::shared_ptr< IndexedValuesSignal > Ptr
Definition: signals.h:415
corbo::gui::SignalHelper::signalRemoved
void signalRemoved(const QString &key, int value_idx)
corbo::gui::SignalHelper::newTimeSeries
void newTimeSeries(const QString &key, TimeSeriesSignal::ConstPtr ts, SignalData &signal_data, bool first)
corbo::gui::SignalHelper::extractNamespace
static void extractNamespace(const QString &name, QStringList &namespaces)
Definition: signal_helper.cpp:430
corbo::gui::SignalHelper::addIndexedValues
void addIndexedValues(const QString &name, IndexedValuesSignal::Ptr indexed_values)
Definition: signal_helper.cpp:248
corbo::IndexedValuesSetSignal::Ptr
std::shared_ptr< IndexedValuesSetSignal > Ptr
Definition: signals.h:499
corbo::gui::SignalHelper::SignalData
Definition: signal_helper.h:116
corbo::gui::SignalHelper::newSignal
void newSignal(const QString &key, SignalData &signal_data)
corbo::gui::SignalHelper::_id
int _id
Definition: signal_helper.h:188
corbo::TimeSeriesSequenceSignal::Ptr
std::shared_ptr< TimeSeriesSequenceSignal > Ptr
Definition: signals.h:358
corbo::gui::SignalHelper::_signal_map
SignalMap _signal_map
Definition: signal_helper.h:185
corbo::gui::SignalHelper::printSignals
void printSignals()
Definition: signal_helper.cpp:552
PRINT_INFO
#define PRINT_INFO(msg)
Print msg-stream.
Definition: console.h:117
corbo::gui::SignalHelper::newMatrixSignal
void newMatrixSignal(const QString &key, MatrixSignal::ConstPtr matrix_signal, SignalData &signal_data, bool first)
corbo::Measurement::ConstPtr
std::shared_ptr< const Measurement > ConstPtr
Definition: signals.h:197
corbo::gui::SignalHelper::ALL_VALUES
static constexpr const int ALL_VALUES
Definition: signal_helper.h:114
utilities.h
corbo::TimeSeriesSignal::Ptr
std::shared_ptr< TimeSeriesSignal > Ptr
Definition: signals.h:269


control_box_rst
Author(s): Christoph Rösmann
autogenerated on Wed Mar 2 2022 00:06:12