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


plotjuggler
Author(s): Davide Faconti
autogenerated on Mon Nov 11 2024 03:23:44