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 #include "ArmarXPlotterDialog.h"
25 
30 
31 #include <SimoxUtility/algorithm/string/string_tools.h>
32 
33 //QT
34 #include <QTimer>
35 #include <QTime>
36 #include <QSettings>
37 #include <QDir>
38 #include <QStackedLayout>
39 #include <QTextEdit>
40 
41 
42 #include <IceUtil/IceUtil.h>
43 
44 #include <filesystem>
45 #include <sstream>
46 
47 
48 namespace armarx
49 {
51  startUpTime(QDateTime::currentDateTime())
52  {
53  plotterController = new PlotterController {this};
54  setTag("Plotter");
55  ui.setupUi(getWidget());
56  dialog = new ArmarXPlotterDialog(getWidget(), NULL);
57  loggingDir = (QDir::currentPath());
58  dialog->ui.editLoggingDirectory->setText(loggingDir);
59 
60  plotterController->setGraphStyle(ui.CBgraphStyle->currentText().toStdString());
61  ui.verticalLayout->insertWidget(0, plotterController->getPlotterWidget());
62  }
63 
65  {
66  // if(dialog && this->getState() == eManagedIceObjectInitialized)
67  // getArmarXManager()->removeObjectNonBlocking(dialog);
68  // delete dialog;
69  }
70 
72 
74  {
75  ARMARX_VERBOSE << "ArmarXPlotter started" << flush;
76  dialog->setIceManager(getIceManager());
77  plotterController->setIceManager(getIceManager());
78  connect(dialog, SIGNAL(accepted()), this, SLOT(configDone()));
79  connect(ui.BTNEdit, SIGNAL(clicked()), this, SLOT(configDialog()));
80  connect(ui.BTNPlotterStatus, SIGNAL(toggled(bool)), plotterController, SLOT(plottingPaused(bool)));
81 
82  connect(ui.BTNAutoScale, SIGNAL(toggled(bool)), plotterController, SLOT(autoScale(bool)));
83 
84  connect(ui.btnLogToFile, SIGNAL(toggled(bool)), this, SLOT(toggleLogging(bool)));
85 
86  connect(ui.CBgraphStyle, SIGNAL(currentTextChanged(QString)), this, SLOT(onGraphStyleChanged(QString)));
87 
88  connect(ui.btnClearHistory, SIGNAL(clicked()), plotterController, SLOT(clearHistory()));
89 
90  if (!QMetaObject::invokeMethod(plotterController, "setupCurves"))
91  {
92  ARMARX_WARNING << "Failed to invoke setupCurves";
93  }
94 
95  usingTopic("TopicReplayerListener");
96  }
97 
99  {
100  // unsubscribeFromTopic("TopicReplayerListener");
101  plotterController->deleteLater();
102  }
103 
104  void ArmarXPlotter::onCloseWidget(QCloseEvent* event)
105  {
106  ARMARX_VERBOSE << "closing" << flush;
107  timer->stop();
108 
109  if (logstream.is_open())
110  {
111  logstream.close();
112  }
113  }
114 
116  {
117  }
118 
120  {
121  if (!dialog)
122  {
123  return;
124  }
125 
126  dialog->ui.spinBoxUpdateInterval->setValue(plotterController->getUpdateInterval());
127  dialog->ui.spinBoxShownInterval->setValue(plotterController->getShownInterval());
128  dialog->ui.syncDataLogging->setChecked(syncDataLogging);
129  dialog->ui.listWidget->clear();
130  dialog->ui.listWidget->addItems(plotterController->getSelectedDatafields());
131  // if(dialog->exec())
132  // configDone();
133  dialog->setModal(true);
134  dialog->show();
135  // dialog->raise();
136  // dialog->activateWindow();
137  // dialog->setParent(0);
138  }
139 
141  {
142  {
143  // plotterController->clear();
144  std::unique_lock lock(dataMutex);
145  plotterController->setUpdateInterval(dialog->ui.spinBoxUpdateInterval->value());
146  plotterController->setShownInterval(dialog->ui.spinBoxShownInterval->value());
147  plotterController->setPollingInterval(dialog->ui.spinBoxPollingInterval->value());
148  // selectedChannels = dialog->getSelectedChannels();
149  loggingDir = dialog->ui.editLoggingDirectory->text();
150  syncDataLogging = dialog->ui.syncDataLogging->isChecked();
151  ui.btnLogToFile->setChecked(false);
152  ui.BTNPlotterStatus->setChecked(false);
153  plotterController->setSelectedDatafields(dialog->getSelectedDatafields());
154  }
155 
156  // plotterController->setupCurves();
157  }
158 
159  void ArmarXPlotter::toggleLogging(bool toggled)
160  {
161  std::lock_guard<std::mutex> lock(mutex);
162 
163  if (toggled)
164  {
165  std::filesystem::path outputPath;
166  if (filename.empty())
167  {
168  outputPath = loggingDir.toStdString() + "/datalog.csv";
169 
170  std::string time = IceUtil::Time::now().toDateTime();
171  time = simox::alg::replace_all(time, "/", "-");
172  time = simox::alg::replace_all(time, " ", "_");
173  time = simox::alg::replace_all(time, ":", "-");
174  outputPath = outputPath.parent_path() / (outputPath.stem().string() + "-" + time + outputPath.extension().string());
175 
176  }
177  else
178  {
179  std::filesystem::path path = filename;
180  outputPath = loggingDir.toStdString() + "/" + path.stem().string() + ".csv";
181  }
182 
183  ARMARX_INFO << "Logging to " << outputPath.string();
184  logstream.open(outputPath.string());
185  logStartTime = IceUtil::Time::now();
186 
187  if (!logstream.is_open())
188  {
189  ARMARX_ERROR << "Could not open file for logging: " << outputPath.string();
190  ui.btnLogToFile->setChecked(false);
191  }
192  else
193  {
194  std::lock_guard<std::mutex> lock(fileMutex);
195 
196  csvHeader = plotterController->getSelectedDatafieldsKeys();
197 
198  logstream << "Timestamp";
199  for (const auto& s : csvHeader)
200  {
201  logstream << "," << s;
202  }
203  logstream << std::endl;
204 
205  connect(plotterController, SIGNAL(newDataAvailable(long, std::map<std::string, VariantPtr>)), this, SLOT(logToFile(long, std::map<std::string, VariantPtr>)));
206  }
207 
208  }
209  else
210  {
211  filename = "";
212  QObject::disconnect(plotterController, SIGNAL(newDataAvailable(long, std::map<std::string, VariantPtr>)), this, SLOT(logToFile(long, std::map<std::string, VariantPtr>)));
213 
214  std::lock_guard<std::mutex> lock(fileMutex);
215 
216  logstream.flush();
217  ARMARX_INFO << "done writing log";
218  logstream.close();
219 
220  csvHeader.clear();
221  }
222  }
223 
224  void ArmarXPlotter::onGraphStyleChanged(const QString& style)
225  {
226  const auto st = style.toStdString();
227  plotterController->setGraphStyle(st);
228  if (plotterController->getGraphStyle() != st)
229  {
230  if (style == "Bar chart")
231  {
232  ui.BTNAutoScale->setDisabled(true);
233  }
234  else
235  {
236  ui.BTNAutoScale->setDisabled(false);
237  }
238  }
239  }
240 
241  void ArmarXPlotter::saveSettings(QSettings* settings)
242  {
243  std::unique_lock lock(dataMutex);
244  settings->setValue("updateInterval", plotterController->getUpdateInterval());
245  settings->setValue("shownInterval", plotterController->getShownInterval());
246  settings->setValue("pollingInterval", plotterController->getPollingInterval());
247  settings->setValue("selectedChannels", plotterController->getSelectedDatafields());
248  settings->setValue("autoScaleActive", ui.BTNAutoScale->isChecked());
249  settings->setValue("syncDataLogging", syncDataLogging);
250 
251  }
252 
253  void ArmarXPlotter::loadSettings(QSettings* settings)
254  {
255  std::unique_lock lock(dataMutex);
256  plotterController->setUpdateInterval(settings->value("updateInterval", 100).toInt());
257  plotterController->setShownInterval(settings->value("shownInterval", 60).toInt());
258  plotterController->setPollingInterval(settings->value("pollingInterval", 33).toInt());
259  plotterController->setSelectedDatafields(settings->value("selectedChannels", QStringList()).toStringList());
260  ui.BTNAutoScale->setChecked(settings->value("autoScaleActive", true).toBool());
261  syncDataLogging = settings->value("syncDataLogging", false).toBool();
262 
263  ARMARX_VERBOSE << "Settings loaded";
264  }
265 
266  void ArmarXPlotter::logToFile(long timestamp, const std::map<std::string, VariantPtr>& dataMaptoAppend)
267  {
268  std::lock_guard<std::mutex> lock(fileMutex);
269 
270  if (!logstream.is_open() || !dataMaptoAppend.size())
271  {
272  return;
273  }
274 
275  logstream << (IceUtil::Time::microSeconds(timestamp) - logStartTime).toMilliSecondsDouble();
276 
277  for (const auto& f : csvHeader)
278  {
279  logstream << ",";
280  if (dataMaptoAppend.count(f))
281  {
282  logstream << dataMaptoAppend.at(f)->Variant::getOutputValueOnly();
283  }
284  }
285  logstream << std::endl;
286  }
287 }
armarx::PlotterController::setPollingInterval
void setPollingInterval(int value)
Definition: PlotterController.cpp:866
armarx::ArmarXPlotterDialog
Definition: ArmarXPlotterDialog.h:49
armarx::PlotterController::setIceManager
void setIceManager(const IceManagerPtr &value)
Definition: PlotterController.cpp:886
ARMARX_VERBOSE
#define ARMARX_VERBOSE
Definition: Logging.h:180
armarx::ManagedIceObject::getIceManager
IceManagerPtr getIceManager() const
Returns the IceManager.
Definition: ManagedIceObject.cpp:353
armarx::PlotterController
Definition: PlotterController.h:75
armarx::ArmarXPlotter::onCloseWidget
void onCloseWidget(QCloseEvent *event)
emits the closeRequest signal
Definition: ArmarXPlotter.cpp:104
armarx::PlotterController::getPlotterWidget
QWidget * getPlotterWidget()
Definition: PlotterController.cpp:113
ArmarXPlotter.h
armarx::ArmarXPlotter::timer
QTimer * timer
Definition: ArmarXPlotter.h:115
armarx::ArmarXPlotter::ui
Ui::ArmarXPlotter ui
Definition: ArmarXPlotter.h:113
InvalidChannelException.h
armarx::ArmarXPlotter::ArmarXPlotter
ArmarXPlotter()
Definition: ArmarXPlotter.cpp:50
armarx::PlotterController::getPollingInterval
int getPollingInterval() const
Definition: PlotterController.cpp:861
DataFieldIdentifier.h
armarx::ArmarXPlotter::onExitComponent
void onExitComponent() override
Hook for subclass.
Definition: ArmarXPlotter.cpp:98
ObserverObjectFactories.h
currentDateTime
std::string currentDateTime()
Definition: XMLScenarioParser.cpp:60
armarx::PlotterController::getSelectedDatafields
QStringList getSelectedDatafields() const
Definition: PlotterController.cpp:785
armarx::ArmarXPlotter::toggleLogging
void toggleLogging(bool toggled)
Definition: ArmarXPlotter.cpp:159
armarx::ArmarXPlotter::loggingDir
QString loggingDir
Definition: ArmarXPlotter.h:118
armarx::ArmarXPlotter::onConnectComponent
void onConnectComponent() override
Pure virtual hook for the subclass.
Definition: ArmarXPlotter.cpp:73
armarx::flush
const LogSender::manipulator flush
Definition: LogSender.h:251
armarx::PlotterController::setUpdateInterval
void setUpdateInterval(int value)
Definition: PlotterController.cpp:880
armarx::ArmarXPlotter::configDone
void configDone()
Definition: ArmarXPlotter.cpp:140
armarx::ArmarXPlotter::configDialog
void configDialog()
Definition: ArmarXPlotter.cpp:119
armarx::ArmarXPlotter::~ArmarXPlotter
~ArmarXPlotter() override
Definition: ArmarXPlotter.cpp:64
ArmarXPlotterDialog.h
armarx::PlotterController::getGraphStyle
std::string getGraphStyle() const
Definition: PlotterController.cpp:949
ARMARX_ERROR
#define ARMARX_ERROR
Definition: Logging.h:189
armarx::PlotterController::getShownInterval
int getShownInterval() const
Definition: PlotterController.cpp:926
armarx::ManagedIceObject::usingTopic
void usingTopic(const std::string &name, bool orderedPublishing=false)
Registers a proxy for subscription after initialization.
Definition: ManagedIceObject.cpp:248
TimeUtil.h
armarx::PlotterController::setGraphStyle
void setGraphStyle(const std::string &style)
Definition: PlotterController.cpp:954
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:174
armarx::ArmarXPlotter::dialog
QPointer< ArmarXPlotterDialog > dialog
Definition: ArmarXPlotter.h:114
armarx::ArmarXPlotter::settings
std::shared_ptr< QSettings > settings
Definition: ArmarXPlotter.h:157
armarx::ArmarXPlotter::logToFile
void logToFile(long timestamp, const std::map< std::string, VariantPtr > &dataMaptoAppend)
Definition: ArmarXPlotter.cpp:266
armarx::PlotterController::getUpdateInterval
int getUpdateInterval() const
Definition: PlotterController.cpp:875
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:55
armarx::PlotterController::getSelectedDatafieldsKeys
std::vector< std::string > getSelectedDatafieldsKeys() const
Definition: PlotterController.cpp:793
armarx::ArmarXPlotter::loadSettings
void loadSettings(QSettings *settings) override
Implement to load the settings that are part of the GUI configuration.
Definition: ArmarXPlotter.cpp:253
ARMARX_WARNING
#define ARMARX_WARNING
Definition: Logging.h:186
armarx::PlotterController::setShownInterval
void setShownInterval(int value)
Definition: PlotterController.cpp:931
armarx::ArmarXPlotter::saveSettings
void saveSettings(QSettings *settings) override
Implement to save the settings as part of the GUI configuration.
Definition: ArmarXPlotter.cpp:241
armarx::PlotterController::setSelectedDatafields
void setSelectedDatafields(const QStringList &value, int samplingIntervalMs=-1)
Changes the datafields that are plotted.
Definition: PlotterController.cpp:848
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:28
armarx::ArmarXPlotter::ButtonAddSensorChannelClicked
void ButtonAddSensorChannelClicked()
Definition: ArmarXPlotter.cpp:115
armarx::ArmarXPlotter::onGraphStyleChanged
void onGraphStyleChanged(const QString &style)
Definition: ArmarXPlotter.cpp:224
armarx::ArmarXPlotter::onInitComponent
void onInitComponent() override
Pure virtual hook for the subclass.
Definition: ArmarXPlotter.cpp:71