datastream_zcm.cpp
Go to the documentation of this file.
1 #include "datastream_zcm.h"
2 
3 #include <QTextStream>
4 #include <QFile>
5 #include <QMessageBox>
6 #include <QDebug>
7 
8 #include <iomanip>
9 #include <iostream>
10 #include <mutex>
11 
12 #include <QSettings>
13 #include <QFileDialog>
14 #include <QMessageBox>
15 
16 using namespace std;
17 using namespace PJ;
18 
19 template <typename T>
20 double toDouble(const void* data) {
21  return static_cast<double>(*reinterpret_cast<const T*>(data));
22 }
23 
24 DataStreamZcm::DataStreamZcm(): _subs(nullptr), _running(false)
25 {
26  _dialog = new QDialog;
27  _ui = new Ui::DialogZcm;
28  _ui->setupUi(_dialog);
29 
30  _config_widget = new ConfigZCM("DataStreamZcm", _dialog);
31  _ui->mainLayout->insertWidget(5, _config_widget, 1);
32 }
33 
35 {
36  shutdown();
37  delete _dialog;
38 }
39 
40 const char* DataStreamZcm::name() const
41 {
42  return "Zcm Streamer";
43 }
44 
45 bool DataStreamZcm::start(QStringList*)
46 {
47  if (_running) {
48  return false;
49  }
50 
51  // We create a Dialog to request the folder to populate zcm::TypeDb
52  // and the string to pass to the subscriber.
53 
54  // Initialize the lineEdits in the ui with the previous value;
55  QSettings settings;
56  auto const subscribe_text = settings.value("DataStreamZcm::subscribe", ".*").toString();
57  _ui->lineEditSubscribe->setText(subscribe_text);
58 
59  {
60  auto transport = QString(getenv("ZCM_DEFAULT_URL"));
61  transport = settings.value("DataStreamZcm::transport", transport).toString();
62  _ui->lineEditTransport->setText(transport);
63  }
64 
65  // start the dialog and check that OK was pressed
66  _dialog->restoreGeometry(settings.value("DataStreamZcm::geometry").toByteArray());
67  int res = _dialog->exec();
68 
69  settings.setValue("DataStreamZcm::geometry", _dialog->saveGeometry());
70  if (res == QDialog::Rejected) {
71  return false;
72  }
73 
74  // save the current configuration for the next execution
75  settings.setValue("DataStreamZcm::subscribe", _ui->lineEditSubscribe->text());
76  settings.setValue("DataStreamZcm::transport", _ui->lineEditTransport->text());
77 
78  _transport = _ui->lineEditTransport->text();
79 
80  if(!_zcm) {
81  try {
82  _zcm.reset(new zcm::ZCM(_transport.toStdString()));
83  }
84  catch(std::exception& ex) {
85  QMessageBox::warning(nullptr, "Error",
86  tr("Exception from zcm::ZCM() :\n%1").arg(ex.what()));
87  return false;
88  }
89  if (!_zcm->good()) {
90  QMessageBox::warning(nullptr, "Error", "Failed to create zcm::ZCM()");
91  _zcm.reset();
92  return false;
93  }
94  }
95 
96  auto libraries = _config_widget->getLibraries();
97 
98  // reset the types if it is the first time or folder changed
99  if(_types_library != libraries || !_types)
100  {
101  _types_library = libraries;
102  _types.reset(new zcm::TypeDb(_types_library.toStdString()));
103  if(!_types->good()) {
104  QMessageBox::warning(nullptr, "Error", "Failed to create zcm::TypeDb()");
105  _types.reset();
106  return false;
107  }
108  }
109 
110  if(_subscribe_string != _ui->lineEditSubscribe->text() || !_subs)
111  {
112  _subscribe_string = _ui->lineEditSubscribe->text();
113  if (_subs) {
114  _zcm->unsubscribe(_subs);
115  }
116  _subs =_zcm->subscribe(_subscribe_string.toStdString(), &DataStreamZcm::handler, this);
117  if (!_subs) {
118  QMessageBox::warning(nullptr, "Error", "Failed to subscribe");
119  return false;
120  }
121  }
122 
123  _zcm->start();
124  _running = true;
125  return true;
126 }
127 
129 {
130  if (!_running) {
131  return;
132  }
133  if (_subs) {
134  _zcm->unsubscribe(_subs);
135  _subs = nullptr;
136  }
137  _zcm->stop();
138  _zcm.reset(nullptr);
139  _running = false;
140 }
141 
143 {
144  return _running;
145 }
146 
147 bool DataStreamZcm::xmlSaveState(QDomDocument& doc, QDomElement& parent_element) const
148 {
149  // RRR (Bendes): Probably also transport string here
150  QDomElement elem = doc.createElement("config");
151  elem.setAttribute("folder", _types_library);
152  elem.setAttribute("subscribe", _subscribe_string);
153  elem.setAttribute("transport", _transport);
154  parent_element.appendChild(elem);
155  return true;
156 }
157 
158 bool DataStreamZcm::xmlLoadState(const QDomElement& parent_element)
159 {
160  QDomElement elem = parent_element.firstChildElement("config");
161  if (!elem.isNull())
162  {
163  // RRR (Bendes): Probably also transport string here
164  _types_library = elem.attribute("folder");
165  _subscribe_string = elem.attribute("subscribe");
166  _transport = elem.attribute("transport");
167  QSettings settings;
168  settings.setValue("DataStreamZcm::folder", _types_library);
169  settings.setValue("DataStreamZcm::subscribe", _subscribe_string);
170  settings.setValue("DataStreamZcm::transport", _transport);
171  }
172  return true;
173 }
174 
175 
176 void DataStreamZcm::processData(const string& name, zcm_field_type_t type,
177  const void* data, void* usr)
178 {
179  DataStreamZcm *me = (DataStreamZcm*)usr;
180  switch (type) {
181  case ZCM_FIELD_INT8_T: me->_numerics.emplace_back(name, toDouble<int8_t>(data)); break;
182  case ZCM_FIELD_INT16_T: me->_numerics.emplace_back(name, toDouble<int16_t>(data)); break;
183  case ZCM_FIELD_INT32_T: me->_numerics.emplace_back(name, toDouble<int32_t>(data)); break;
184  case ZCM_FIELD_INT64_T: me->_numerics.emplace_back(name, toDouble<int64_t>(data)); break;
185  case ZCM_FIELD_BYTE: me->_numerics.emplace_back(name, toDouble<uint8_t>(data)); break;
186  case ZCM_FIELD_FLOAT: me->_numerics.emplace_back(name, toDouble<float>(data)); break;
187  case ZCM_FIELD_DOUBLE: me->_numerics.emplace_back(name, toDouble<double>(data)); break;
188  case ZCM_FIELD_BOOLEAN: me->_numerics.emplace_back(name, toDouble<bool>(data)); break;
189  case ZCM_FIELD_STRING: me->_strings.emplace_back(name, string((const char*)data)); break;
190  case ZCM_FIELD_USER_TYPE: assert(false && "Should not be possble");
191  }
192 };
193 
194 
195 void DataStreamZcm::handler(const zcm::ReceiveBuffer* rbuf, const string& channel)
196 {
197  zcm::Introspection::processEncodedType(channel,
198  rbuf->data, rbuf->data_size,
199  "/",
200  *_types.get(), processData, this);
201  {
202  std::lock_guard<std::mutex> lock(mutex());
203 
204  for (auto& n : _numerics) {
205  auto itr = dataMap().numeric.find(n.first);
206  if (itr == dataMap().numeric.end()) {
207  itr = dataMap().addNumeric(n.first);
208  }
209  itr->second.pushBack({ double(rbuf->recv_utime) / 1e6, n.second });
210  }
211  for (auto& s : _strings) {
212  auto itr = dataMap().strings.find(s.first);
213  if (itr == dataMap().strings.end()) {
214  itr = dataMap().addStringSeries(s.first);
215  }
216  itr->second.pushBack({ double(rbuf->recv_utime) / 1e6, s.second });
217  }
218  }
219 
220  emit dataReceived();
221 
222  _numerics.clear();
223  _strings.clear();
224 }
225 
227 {
228  QString url = getenv("ZCM_DEFAULT_URL");
229  if (url.isEmpty()) {
230  QMessageBox::warning(nullptr, "Error", "Environment variable ZCM_DEFAULT_URL not set");
231  } else {
232  _ui->lineEditTransport->setText(url);
233  }
234 }
235 
void on_pushButtonUrl_clicked()
QString _types_library
QString _subscribe_string
#define nullptr
Definition: backward.hpp:386
std::unique_ptr< zcm::TypeDb > _types
virtual bool xmlSaveState(QDomDocument &doc, QDomElement &parent_element) const override
Override this method to save the status of the plugin to XML.
std::unique_ptr< zcm::ZCM > _zcm
QString _transport
XmlRpcServer s
ConfigZCM * _config_widget
auto arg(const Char *name, const T &arg) -> detail::named_arg< Char, T >
Definition: core.h:1736
virtual ~DataStreamZcm()
void handler(const zcm::ReceiveBuffer *rbuf, const std::string &channel)
std::mutex & mutex()
type
Definition: core.h:1059
zcm::Subscription * _subs
virtual bool isRunning() const override
isRunning
TimeseriesMap numeric
Numerical timeseries.
Definition: plotdata.h:38
std::vector< std::pair< std::string, std::string > > _strings
#define assert(condition)
Definition: lz4.c:245
virtual void shutdown() override
shutdown Stop streaming
static void processData(const std::string &name, zcm_field_type_t type, const void *data, void *usr)
StringSeriesMap strings
Series of strings.
Definition: plotdata.h:45
TimeseriesMap::iterator addNumeric(const std::string &name, PlotGroup::Ptr group={})
Definition: plotdata.cpp:51
double toDouble(const void *data)
PlotDataMapRef & dataMap()
StringSeriesMap::iterator addStringSeries(const std::string &name, PlotGroup::Ptr group={})
Definition: plotdata.cpp:63
QString getLibraries() const
Definition: config_zcm.cpp:40
virtual const char * name() const override
Name of the plugin type, NOT the particular instance.
Ui::DialogZcm * _ui
virtual bool xmlLoadState(const QDomElement &parent_element) override
Override this method to load the status of the plugin from XML.
std::vector< std::pair< std::string, double > > _numerics
dictionary data
Definition: mqtt_test.py:22
QDialog * _dialog
virtual bool start(QStringList *) override
start streaming.
Definition: format.h:895


plotjuggler
Author(s): Davide Faconti
autogenerated on Mon Jun 19 2023 03:01:01