ArmarXPlotter.cpp
Go to the documentation of this file.
1 /*
2 * This file is part of ArmarX.
3 *
4 * ArmarX is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * ArmarX is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * @package ArmarX::Gui
17 * @author Mirko Waechter ( mirko.waechter at kit dot edu)
18 * @date 2012
19 * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
20 * GNU General Public License
21 */
22 
23 #include "ArmarXPlotter.h"
24 
25 #include <SimoxUtility/algorithm/string/string_tools.h>
26 
31 
32 #include "ArmarXPlotterDialog.h"
33 
34 //QT
35 #include <filesystem>
36 #include <sstream>
37 
38 #include <QDir>
39 #include <QSettings>
40 #include <QStackedLayout>
41 #include <QTextEdit>
42 #include <QTime>
43 #include <QTimer>
44 
45 #include <IceUtil/IceUtil.h>
46 
47 namespace armarx
48 {
49  ArmarXPlotter::ArmarXPlotter() : startUpTime(QDateTime::currentDateTime())
50  {
51  plotterController = new PlotterController{this};
52  setTag("Plotter");
53  ui.setupUi(getWidget());
54  dialog = new ArmarXPlotterDialog(getWidget(), NULL);
55  loggingDir = (QDir::currentPath());
56  dialog->ui.editLoggingDirectory->setText(loggingDir);
57 
58  plotterController->setGraphStyle(ui.CBgraphStyle->currentText().toStdString());
59  ui.verticalLayout->insertWidget(0, plotterController->getPlotterWidget());
60  }
61 
63  {
64  // if(dialog && this->getState() == eManagedIceObjectInitialized)
65  // getArmarXManager()->removeObjectNonBlocking(dialog);
66  // delete dialog;
67  }
68 
69  void
71  {
72  }
73 
74  void
76  {
77  ARMARX_VERBOSE << "ArmarXPlotter started" << flush;
78  dialog->setIceManager(getIceManager());
79  plotterController->setIceManager(getIceManager());
80  connect(dialog, SIGNAL(accepted()), this, SLOT(configDone()));
81  connect(ui.BTNEdit, SIGNAL(clicked()), this, SLOT(configDialog()));
82  connect(ui.BTNPlotterStatus,
83  SIGNAL(toggled(bool)),
84  plotterController,
85  SLOT(plottingPaused(bool)));
86 
87  connect(ui.BTNAutoScale, SIGNAL(toggled(bool)), plotterController, SLOT(autoScale(bool)));
88 
89  connect(ui.btnLogToFile, SIGNAL(toggled(bool)), this, SLOT(toggleLogging(bool)));
90 
91  connect(ui.CBgraphStyle,
92  SIGNAL(currentTextChanged(QString)),
93  this,
94  SLOT(onGraphStyleChanged(QString)));
95 
96  connect(ui.btnClearHistory, SIGNAL(clicked()), plotterController, SLOT(clearHistory()));
97 
98  if (!QMetaObject::invokeMethod(plotterController, "setupCurves"))
99  {
100  ARMARX_WARNING << "Failed to invoke setupCurves";
101  }
102 
103  usingTopic("TopicReplayerListener");
104  }
105 
106  void
108  {
109  // unsubscribeFromTopic("TopicReplayerListener");
110  plotterController->deleteLater();
111  }
112 
113  void
114  ArmarXPlotter::onCloseWidget(QCloseEvent* event)
115  {
116  ARMARX_VERBOSE << "closing" << flush;
117  timer->stop();
118 
119  if (logstream.is_open())
120  {
121  logstream.close();
122  }
123  }
124 
125  void
127  {
128  }
129 
130  void
132  {
133  if (!dialog)
134  {
135  return;
136  }
137 
138  dialog->ui.spinBoxUpdateInterval->setValue(plotterController->getUpdateInterval());
139  dialog->ui.spinBoxShownInterval->setValue(plotterController->getShownInterval());
140  dialog->ui.syncDataLogging->setChecked(syncDataLogging);
141  dialog->ui.listWidget->clear();
142  dialog->ui.listWidget->addItems(plotterController->getSelectedDatafields());
143  // if(dialog->exec())
144  // configDone();
145  dialog->setModal(true);
146  dialog->show();
147  // dialog->raise();
148  // dialog->activateWindow();
149  // dialog->setParent(0);
150  }
151 
152  void
154  {
155  {
156  // plotterController->clear();
157  std::unique_lock lock(dataMutex);
158  plotterController->setUpdateInterval(dialog->ui.spinBoxUpdateInterval->value());
159  plotterController->setShownInterval(dialog->ui.spinBoxShownInterval->value());
160  plotterController->setPollingInterval(dialog->ui.spinBoxPollingInterval->value());
161  // selectedChannels = dialog->getSelectedChannels();
162  loggingDir = dialog->ui.editLoggingDirectory->text();
163  syncDataLogging = dialog->ui.syncDataLogging->isChecked();
164  ui.btnLogToFile->setChecked(false);
165  ui.BTNPlotterStatus->setChecked(false);
166  plotterController->setSelectedDatafields(dialog->getSelectedDatafields());
167  }
168 
169  // plotterController->setupCurves();
170  }
171 
172  void
174  {
175  std::lock_guard<std::mutex> lock(mutex);
176 
177  if (toggled)
178  {
179  std::filesystem::path outputPath;
180  if (filename.empty())
181  {
182  outputPath = loggingDir.toStdString() + "/datalog.csv";
183 
184  std::string time = IceUtil::Time::now().toDateTime();
185  time = simox::alg::replace_all(time, "/", "-");
186  time = simox::alg::replace_all(time, " ", "_");
187  time = simox::alg::replace_all(time, ":", "-");
188  outputPath = outputPath.parent_path() / (outputPath.stem().string() + "-" + time +
189  outputPath.extension().string());
190  }
191  else
192  {
193  std::filesystem::path path = filename;
194  outputPath = loggingDir.toStdString() + "/" + path.stem().string() + ".csv";
195  }
196 
197  ARMARX_INFO << "Logging to " << outputPath.string();
198  logstream.open(outputPath.string());
199  logStartTime = IceUtil::Time::now();
200 
201  if (!logstream.is_open())
202  {
203  ARMARX_ERROR << "Could not open file for logging: " << outputPath.string();
204  ui.btnLogToFile->setChecked(false);
205  }
206  else
207  {
208  std::lock_guard<std::mutex> lock(fileMutex);
209 
210  csvHeader = plotterController->getSelectedDatafieldsKeys();
211 
212  logstream << "Timestamp";
213  for (const auto& s : csvHeader)
214  {
215  logstream << "," << s;
216  }
217  logstream << std::endl;
218 
219  connect(plotterController,
220  SIGNAL(newDataAvailable(long, std::map<std::string, VariantPtr>)),
221  this,
222  SLOT(logToFile(long, std::map<std::string, VariantPtr>)));
223  }
224  }
225  else
226  {
227  filename = "";
228  QObject::disconnect(plotterController,
229  SIGNAL(newDataAvailable(long, std::map<std::string, VariantPtr>)),
230  this,
231  SLOT(logToFile(long, std::map<std::string, VariantPtr>)));
232 
233  std::lock_guard<std::mutex> lock(fileMutex);
234 
235  logstream.flush();
236  ARMARX_INFO << "done writing log";
237  logstream.close();
238 
239  csvHeader.clear();
240  }
241  }
242 
243  void
245  {
246  const auto st = style.toStdString();
247  plotterController->setGraphStyle(st);
248  if (plotterController->getGraphStyle() != st)
249  {
250  if (style == "Bar chart")
251  {
252  ui.BTNAutoScale->setDisabled(true);
253  }
254  else
255  {
256  ui.BTNAutoScale->setDisabled(false);
257  }
258  }
259  }
260 
261  void
262  ArmarXPlotter::saveSettings(QSettings* settings)
263  {
264  std::unique_lock lock(dataMutex);
265  settings->setValue("updateInterval", plotterController->getUpdateInterval());
266  settings->setValue("shownInterval", plotterController->getShownInterval());
267  settings->setValue("pollingInterval", plotterController->getPollingInterval());
268  settings->setValue("selectedChannels", plotterController->getSelectedDatafields());
269  settings->setValue("autoScaleActive", ui.BTNAutoScale->isChecked());
270  settings->setValue("syncDataLogging", syncDataLogging);
271  }
272 
273  void
274  ArmarXPlotter::loadSettings(QSettings* settings)
275  {
276  std::unique_lock lock(dataMutex);
277  plotterController->setUpdateInterval(settings->value("updateInterval", 100).toInt());
278  plotterController->setShownInterval(settings->value("shownInterval", 60).toInt());
279  plotterController->setPollingInterval(settings->value("pollingInterval", 33).toInt());
280  plotterController->setSelectedDatafields(
281  settings->value("selectedChannels", QStringList()).toStringList());
282  ui.BTNAutoScale->setChecked(settings->value("autoScaleActive", true).toBool());
283  syncDataLogging = settings->value("syncDataLogging", false).toBool();
284 
285  ARMARX_VERBOSE << "Settings loaded";
286  }
287 
288  void
289  ArmarXPlotter::logToFile(long timestamp,
290  const std::map<std::string, VariantPtr>& dataMaptoAppend)
291  {
292  std::lock_guard<std::mutex> lock(fileMutex);
293 
294  if (!logstream.is_open() || !dataMaptoAppend.size())
295  {
296  return;
297  }
298 
299  logstream << (IceUtil::Time::microSeconds(timestamp) - logStartTime).toMilliSecondsDouble();
300 
301  for (const auto& f : csvHeader)
302  {
303  logstream << ",";
304  if (dataMaptoAppend.count(f))
305  {
306  logstream << dataMaptoAppend.at(f)->Variant::getOutputValueOnly();
307  }
308  }
309  logstream << std::endl;
310  }
311 } // namespace armarx
armarx::PlotterController::setPollingInterval
void setPollingInterval(int value)
Definition: PlotterController.cpp:900
armarx::ArmarXPlotterDialog
Definition: ArmarXPlotterDialog.h:48
armarx::PlotterController::setIceManager
void setIceManager(const IceManagerPtr &value)
Definition: PlotterController.cpp:923
ARMARX_VERBOSE
#define ARMARX_VERBOSE
Definition: Logging.h:187
armarx::ManagedIceObject::getIceManager
IceManagerPtr getIceManager() const
Returns the IceManager.
Definition: ManagedIceObject.cpp:366
armarx::PlotterController
Definition: PlotterController.h:75
armarx::ArmarXPlotter::onCloseWidget
void onCloseWidget(QCloseEvent *event)
emits the closeRequest signal
Definition: ArmarXPlotter.cpp:114
armarx::PlotterController::getPlotterWidget
QWidget * getPlotterWidget()
Definition: PlotterController.cpp:114
ArmarXPlotter.h
armarx::ArmarXPlotter::timer
QTimer * timer
Definition: ArmarXPlotter.h:118
armarx::ArmarXPlotter::ui
Ui::ArmarXPlotter ui
Definition: ArmarXPlotter.h:116
InvalidChannelException.h
armarx::ArmarXPlotter::ArmarXPlotter
ArmarXPlotter()
Definition: ArmarXPlotter.cpp:49
armarx::PlotterController::getPollingInterval
int getPollingInterval() const
Definition: PlotterController.cpp:894
DataFieldIdentifier.h
armarx::ArmarXPlotter::onExitComponent
void onExitComponent() override
Hook for subclass.
Definition: ArmarXPlotter.cpp:107
ObserverObjectFactories.h
currentDateTime
std::string currentDateTime()
Definition: XMLScenarioParser.cpp:59
armarx::PlotterController::getSelectedDatafields
QStringList getSelectedDatafields() const
Definition: PlotterController.cpp:820
armarx::ArmarXPlotter::toggleLogging
void toggleLogging(bool toggled)
Definition: ArmarXPlotter.cpp:173
armarx::ArmarXPlotter::loggingDir
QString loggingDir
Definition: ArmarXPlotter.h:121
armarx::ArmarXPlotter::onConnectComponent
void onConnectComponent() override
Pure virtual hook for the subclass.
Definition: ArmarXPlotter.cpp:75
armarx::flush
const LogSender::manipulator flush
Definition: LogSender.h:251
armarx::PlotterController::setUpdateInterval
void setUpdateInterval(int value)
Definition: PlotterController.cpp:916
armarx::ArmarXPlotter::configDone
void configDone()
Definition: ArmarXPlotter.cpp:153
armarx::ArmarXPlotter::configDialog
void configDialog()
Definition: ArmarXPlotter.cpp:131
armarx::ArmarXPlotter::~ArmarXPlotter
~ArmarXPlotter() override
Definition: ArmarXPlotter.cpp:62
ArmarXPlotterDialog.h
armarx::PlotterController::getGraphStyle
std::string getGraphStyle() const
Definition: PlotterController.cpp:993
ARMARX_ERROR
#define ARMARX_ERROR
Definition: Logging.h:196
armarx::PlotterController::getShownInterval
int getShownInterval() const
Definition: PlotterController.cpp:967
armarx::ManagedIceObject::usingTopic
void usingTopic(const std::string &name, bool orderedPublishing=false)
Registers a proxy for subscription after initialization.
Definition: ManagedIceObject.cpp:254
TimeUtil.h
armarx::PlotterController::setGraphStyle
void setGraphStyle(const std::string &style)
Definition: PlotterController.cpp:999
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:181
armarx::ArmarXPlotter::dialog
QPointer< ArmarXPlotterDialog > dialog
Definition: ArmarXPlotter.h:117
armarx::ArmarXPlotter::settings
std::shared_ptr< QSettings > settings
Definition: ArmarXPlotter.h:165
armarx::ArmarXPlotter::logToFile
void logToFile(long timestamp, const std::map< std::string, VariantPtr > &dataMaptoAppend)
Definition: ArmarXPlotter.cpp:289
armarx::PlotterController::getUpdateInterval
int getUpdateInterval() const
Definition: PlotterController.cpp:910
armarx::ArmarXWidgetController::getWidget
virtual QPointer< QWidget > getWidget()
getWidget returns a pointer to the a widget of this controller.
Definition: ArmarXWidgetController.cpp:54
armarx::Logging::setTag
void setTag(const LogTag &tag)
Definition: Logging.cpp:54
armarx::PlotterController::getSelectedDatafieldsKeys
std::vector< std::string > getSelectedDatafieldsKeys() const
Definition: PlotterController.cpp:827
armarx::ArmarXPlotter::loadSettings
void loadSettings(QSettings *settings) override
Implement to load the settings that are part of the GUI configuration.
Definition: ArmarXPlotter.cpp:274
ARMARX_WARNING
#define ARMARX_WARNING
Definition: Logging.h:193
armarx::PlotterController::setShownInterval
void setShownInterval(int value)
Definition: PlotterController.cpp:973
armarx::ArmarXPlotter::saveSettings
void saveSettings(QSettings *settings) override
Implement to save the settings as part of the GUI configuration.
Definition: ArmarXPlotter.cpp:262
armarx::PlotterController::setSelectedDatafields
void setSelectedDatafields(const QStringList &value, int samplingIntervalMs=-1)
Changes the datafields that are plotted.
Definition: PlotterController.cpp:880
armarx::ctrlutil::s
double s(double t, double s0, double v0, double a0, double j)
Definition: CtrlUtil.h:33
armarx
This file offers overloads of toIce() and fromIce() functions for STL container types.
Definition: ArmarXTimeserver.cpp:27
armarx::ArmarXPlotter::ButtonAddSensorChannelClicked
void ButtonAddSensorChannelClicked()
Definition: ArmarXPlotter.cpp:126
armarx::ArmarXPlotter::onGraphStyleChanged
void onGraphStyleChanged(const QString &style)
Definition: ArmarXPlotter.cpp:244
armarx::ArmarXPlotter::onInitComponent
void onInitComponent() override
Pure virtual hook for the subclass.
Definition: ArmarXPlotter.cpp:70