WidgetController.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of ArmarX.
3  *
4  * Copyright (C) 2011-2016, High Performance Humanoid Technologies (H2T), Karlsruhe Institute of Technology (KIT), all rights reserved.
5  *
6  * ArmarX is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  *
10  * ArmarX is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  *
18  * \package VisionX::gui-plugins::WidgetController
19  * \author Philipp Schmidt ( ufedv at student dot kit dot edu )
20  * \date 2015
21  * \copyright http://www.gnu.org/licenses/gpl-2.0.txt
22  * GNU General Public License
23  */
24 
25 #include "WidgetController.h"
26 
27 #include <algorithm>
28 #include <type_traits>
29 
30 // Ice
31 #include <Ice/Ice.h>
32 #include <IceUtil/Time.h>
33 
34 // VisionX
36 
38 #include <VisionX/interface/core/PointCloudProviderInterface.h>
39 
40 // PCL tools
41 #include <QMainWindow>
42 
46 
47 #include "CoinPointCloud.h"
48 
49 namespace visionx
50 {
51  WidgetController::WidgetController() : recenterCamera(false)
52  {
53  qRegisterMetaType<IceGrid::ObjectInfoSeq>("IceGrid::ObjectInfoSeq");
54  }
55 
57  {
58  }
59 
60  void
61  WidgetController::loadSettings(QSettings* settings)
62  {
63  (void)settings; // Unused.
64  }
65 
66  void
67  WidgetController::saveSettings(QSettings* settings)
68  {
69  (void)settings; // Unused.
70  }
71 
72  void
74  {
75  automaticConversion = true;
76  }
77 
78  void
80  {
81  // Refresh list once.
82  this->refreshProviderList();
83 
84  // Ice is ready, allow refreshing of list.
85  QMetaObject::invokeMethod(widget.refreshButton, "setEnabled", Q_ARG(bool, true));
86  }
87 
88  void
90  {
91  QMetaObject::invokeMethod(widget.refreshButton, "setEnabled", Q_ARG(bool, false));
92  QMetaObject::invokeMethod(this, "disconnectQt");
93  }
94 
95  void
96  WidgetController::disconnectQt()
97  {
98  auto icemanager = this->getIceManager();
99  if (!icemanager)
100  {
101  return;
102  }
103  // Let's check which providers just went offline
104  for (int row = 0; row < widget.providerList->count(); row++)
105  {
106  QListWidgetItem* item = widget.providerList->item(row);
107  const std::string subscriber = item->text().toStdString();
108 
109  ARMARX_LOG << subscriber << " has state "
110  << icemanager->getIceGridSession()->getComponentState(subscriber)
111  << std::endl;
112 
113  // Check component status
114  if (icemanager->getIceGridSession()->getComponentState(subscriber) !=
116  {
117  // Unregister cloud
118  manager->unregisterPointCloud(subscriber);
119 
120  // Remove item from provider list (and free memory)
121  delete this->widget.providerList->takeItem(this->widget.providerList->row(item));
122 
123  // Indices got reduced by one
124  row--;
125 
126  // Release point cloud provider
127  this->releasePointCloudProvider(subscriber);
128  }
129  }
130  }
131 
132  void
134  {
135  }
136 
137  void
139  {
140  // Setup user interface
141  widget.setupUi(getWidget());
142  //qRegisterMetaType<visionx::CoinPointCloud*>("visionx::CoinPointCloud*");
143 
144  // Connect update calls with process calls
145  connect(this,
146  SIGNAL(newPointCloudReceived(QString, CoinPointCloud*)),
147  this,
148  SLOT(processPointCloud(QString, CoinPointCloud*)));
149 
150  // Add manager
151  manager = new Manager();
152  widget.pointCloudDisplay->getDisplay()->getRootNode()->addChild(manager);
153 
154  // Remove line counter in table
155  widget.tableWidget->verticalHeader()->setVisible(false);
156 
157  // Disable editing of table
158  widget.tableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);
159 
160  // Button for manual refreshing
161  connect(widget.refreshButton, SIGNAL(clicked()), this, SLOT(refreshProviderList()));
162 
163  // Do not allow refreshing until component connected and ice is ready
164  // widget.refreshButton->setEnabled(false);
165 
166  // Allow to chose background color
167  connect(widget.backgroundButton, SIGNAL(clicked()), this, SLOT(selectColor()));
168 
169  // Items get selected and deselected in list, show infos for pointcloud
170  connect(widget.providerList,
171  SIGNAL(itemPressed(QListWidgetItem*)),
172  this,
173  SLOT(showPointCloudInfo(QListWidgetItem*)));
174 
175  // Items get checked and unchecked in list, add to viewport
176  connect(widget.providerList,
177  SIGNAL(itemChanged(QListWidgetItem*)),
178  this,
179  SLOT(pointCloudChecked(QListWidgetItem*)));
180 
181  // Connect save point cloud button
182  connect(widget.saveButton, SIGNAL(clicked()), this, SLOT(savePointCloud()));
183 
184  // Connect spin box to change point size
185  connect(widget.doubleSpinBoxPointSize,
186  SIGNAL(valueChanged(double)),
187  this,
188  SLOT(setPointSize(double)));
189  }
190 
191  void
193  {
194  std::lock_guard<std::mutex> lock(mutex);
195 
196  // Fetch all point cloud providers for updates and save in buffer
197  for (const std::string& providerName : manager->getRegisteredPointClouds())
198  {
199  if (!isPointCloudProviderKnown(providerName) || !pointCloudHasNewData(providerName))
200  {
201  // Skip this one (disconnected in mean time or no new data available).
202  continue;
203  }
204 
205  // Save in this buffer
206  pcl::PointCloud<PointT>::Ptr providerBuffer(new pcl::PointCloud<PointT>());
207 
208  // Check point cloud type.
209  const visionx::MetaPointCloudFormatPtr info = getPointCloudFormat(providerName);
210  const visionx::PointContentType pointContentType = info->type;
211 
212  bool colorFromLabel =
213  tools::isLabeled(pointContentType) && this->widget.colorMode_label->isChecked();
214 
215  switch (pointContentType)
216  {
217  case visionx::PointContentType::ePoints:
218  getPointCloudAs(providerName, *providerBuffer);
219  break;
220  case visionx::PointContentType::eColoredPoints:
221  getPointCloudAs(providerName, *providerBuffer);
222  break;
223  case visionx::PointContentType::eColoredLabeledPoints:
224  getPointCloudAs(providerName, *providerBuffer);
225  break;
226  case visionx::PointContentType::eLabeledPoints:
227  getPointCloudAs(providerName, *providerBuffer);
228  break;
229  default:
230  ARMARX_WARNING << deactivateSpam() << "Unexpected point cloud content type: "
231  << tools::toString(pointContentType);
232  continue;
233  }
234 
235  CoinPointCloud* cloud =
236  new CoinPointCloud(providerBuffer, pointContentType, colorFromLabel, pointSize);
237  emit newPointCloudReceived(QString::fromStdString(providerName), cloud);
238  }
239  }
240 
241  template <class PointCloudT>
242  void
243  WidgetController::getPointCloudAs(const std::string& providerName,
244  PointCloudT& targetPointCloud)
245  {
246  using InputPointT = typename PointCloudT::PointType;
247 
248  typename pcl::PointCloud<InputPointT>::Ptr inputCloudPtr(
249  new pcl::PointCloud<InputPointT>());
250  if (getPointClouds(providerName, inputCloudPtr))
251  {
252  pcl::copyPointCloud(*inputCloudPtr, targetPointCloud);
253  }
254  }
255 
256  void
258  {
259  manager->updatePointCloud(providerName.toStdString(), *cloud);
260  if (recenterCamera)
261  {
262  widget.pointCloudDisplay->getDisplay()->cameraViewAll();
263  recenterCamera = false;
264  }
265 
266  auto* item = widget.providerList->currentItem();
267  if (item && providerName == item->text())
268  {
269  showPointCloudInfo(widget.providerList->currentItem());
270  }
271  }
272 
273  void
274  WidgetController::updateProviderList(IceGrid::ObjectInfoSeq objects)
275  {
276  ARMARX_INFO << "Updating cloudlist.";
277 
278  // Signal user we are fetching providers
279  widget.loadingStatusLabel->setText(QString::fromStdString("Loading..."));
280 
281  // Count how many providers are online
282  int counter = 0;
283 
284  // Iterate over all objects
285  for (const auto& object : objects)
286  {
287  const std::string name =
288  this->getIceManager()->getCommunicator()->proxyToString(object.proxy);
289  const std::string shortName = name.substr(0, name.find(' '));
290 
291  // Check if we didn't connect to this provider yet.
292  // Invariant: Every item in list widget is a provider we already connected in the past.
293  if (widget.providerList->findItems(QString::fromStdString(shortName), Qt::MatchExactly)
294  .count() == 0)
295  {
296  // Add new item and make it checkable.
297  QListWidgetItem* item =
298  new QListWidgetItem(QString::fromStdString(shortName), widget.providerList);
299  item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
300  item->setCheckState(Qt::Unchecked);
301 
302  // Subscribe to topic, provider is fetchable after that.
303  this->usingPointCloudProvider(shortName);
304  this->getPointCloudProvider(shortName);
305  }
306 
307  counter++;
308  }
309 
310  // Signal user we are done and show how many providers are online
311  widget.loadingStatusLabel->setText(QString::fromStdString(
312  "Loading complete: " + std::to_string(counter) + " provider found"));
313  }
314 
315  void
317  {
318  ARMARX_INFO << "Get cloud providers from ice.";
319  // Get ice grid admin
320  armarx::IceGridAdminPtr admin = this->getIceManager()->getIceGridSession();
321  IceGrid::ObjectInfoSeq objects =
322  admin->getRegisteredObjects<PointCloudProviderInterfacePrx>(
323  widget.lineEditPointCloudFilter->text().toStdString());
324  QMetaObject::invokeMethod(
325  this, "updateProviderList", Q_ARG(IceGrid::ObjectInfoSeq, objects));
326  }
327 
328  void
330  {
331  const std::string providerName = item->text().toStdString();
332  visionx::MetaPointCloudFormatPtr info = this->getPointCloudFormat(providerName);
333 
334  widget.tableWidget->setRowCount(8);
335  widget.tableWidget->setColumnCount(2);
336 
337  // Name
338  widget.tableWidget->setItem(0, 0, new QTableWidgetItem("Name"));
339  widget.tableWidget->setItem(0, 1, new QTableWidgetItem(item->text()));
340 
341  // Type
342  widget.tableWidget->setItem(1, 0, new QTableWidgetItem("Type"));
343  widget.tableWidget->setItem(
344  1,
345  1,
346  new QTableWidgetItem(QString::fromStdString(visionx::tools::toString(info->type))));
347 
348  // Width
349  widget.tableWidget->setItem(2, 0, new QTableWidgetItem("Width"));
350  widget.tableWidget->setItem(
351  2, 1, new QTableWidgetItem(QString::fromStdString(std::to_string(info->width))));
352 
353  // Height
354  widget.tableWidget->setItem(3, 0, new QTableWidgetItem("Height"));
355  widget.tableWidget->setItem(
356  3, 1, new QTableWidgetItem(QString::fromStdString(std::to_string(info->height))));
357 
358  // Size
359  widget.tableWidget->setItem(4, 0, new QTableWidgetItem("Size"));
360  widget.tableWidget->setItem(
361  4, 1, new QTableWidgetItem(QString::fromStdString(std::to_string(info->size))));
362 
363  // Capacity
364  widget.tableWidget->setItem(5, 0, new QTableWidgetItem("Capacity"));
365  widget.tableWidget->setItem(
366  5, 1, new QTableWidgetItem(QString::fromStdString(std::to_string(info->capacity))));
367 
368  // Sequence
369  widget.tableWidget->setItem(6, 0, new QTableWidgetItem("Sequence"));
370  widget.tableWidget->setItem(
371  6, 1, new QTableWidgetItem(QString::fromStdString(std::to_string(info->seq))));
372 
373  // Time provided
374  widget.tableWidget->setItem(7, 0, new QTableWidgetItem("Time Provided"));
375 
376  const bool showRawTimestamp = false;
377  const std::string timeProvided = showRawTimestamp
378  ? std::to_string(info->timeProvided) // Raw time stamp
379  : IceUtil::Time::microSeconds(info->timeProvided)
380  .toDateTime(); // Readable time stamp.
381  widget.tableWidget->setItem(
382  7, 1, new QTableWidgetItem(QString::fromStdString(timeProvided)));
383  }
384 
385  void
386  WidgetController::pointCloudChecked(QListWidgetItem* item)
387  {
388  std::lock_guard<std::mutex> lock(mutex);
389 
390  const std::string providerName = item->text().toStdString();
391 
392  if (item->checkState())
393  {
394  manager->registerPointCloud(providerName);
395  }
396  else
397  {
398  manager->unregisterPointCloud(providerName);
399  }
400  recenterCamera = true;
401  }
402 
403  void
405  {
406  QColor selectedColor = this->colorDialog.getColor();
407 
408  widget.pointCloudDisplay->getDisplay()->setBackgroundColor(
409  SbColor(selectedColor.red() / 255.0f,
410  selectedColor.green() / 255.0f,
411  selectedColor.blue() / 255.0f));
412  }
413 
414  void
416  {
417  if (widget.providerList->selectedItems().size() == 1)
418  {
419  SaveDialog saveDialog(this->getMainWindow());
420  const std::string providerID =
421  widget.providerList->selectedItems()[0]->text().toStdString();
422  const std::vector<std::string> clouds = manager->getRegisteredPointClouds();
423  if (std::find(clouds.begin(), clouds.end(), providerID) != clouds.end())
424  {
425  saveDialog.setPointCloudToSave(manager->getCloudByName(providerID));
426  int result = saveDialog.exec();
427 
428  if (result == QDialog::Accepted)
429  {
430  const CoinPointCloud& coinCloud = *manager->getCloudByName(providerID);
431  const pcl::PointCloud<PointT>& originalCloud = *coinCloud.getPCLCloud();
432  const std::string fileName = saveDialog.getResultFileName();
433 
434  switch (coinCloud.getOriginalType())
435  {
436  case visionx::PointContentType::ePoints:
437  storePointCloudAs(fileName, originalCloud);
438  break;
439  case visionx::PointContentType::eColoredPoints:
440  storePointCloudAs(fileName, originalCloud);
441  break;
442  case visionx::PointContentType::eColoredLabeledPoints:
443  storePointCloudAs(fileName, originalCloud);
444  break;
445  case visionx::PointContentType::eLabeledPoints:
446  storePointCloudAs(fileName, originalCloud);
447  break;
448  default:
450  << "Unexpected point cloud content type: "
451  << tools::toString(coinCloud.getOriginalType());
452  return;
453  }
454  }
455 
456  saveDialog.releaseBuffer();
457  }
458  }
459  }
460 
461  template <class PointCloudT>
462  void
463  WidgetController::storePointCloudAs(const std::string& filename, const PointCloudT& pointCloud)
464  {
465  using StoredPointT = typename PointCloudT::PointType;
466 
467  if (std::is_same<StoredPointT, PointT>())
468  {
469  pcl::io::savePCDFile(filename, pointCloud);
470  }
471  else
472  {
473  pcl::PointCloud<StoredPointT> stored;
474  pcl::copyPointCloud(pointCloud, stored);
475  pcl::io::savePCDFile(filename, stored);
476  }
477  }
478 
479  void
481  {
482  widget.configColumn->setVisible(false);
483  }
484 
485  void
487  {
488  widget.configColumn->setVisible(true);
489  }
490 } // namespace visionx
491 
492 void
493 visionx::WidgetController::setPointSize(double value)
494 {
495  ARMARX_VERBOSE << "Using new point size: " << value;
496  pointSize = static_cast<float>(value);
497 }
WidgetController.h
visionx::PointCloudProcessor::pointCloudHasNewData
bool pointCloudHasNewData(std::string providerName)
Returns current status for the given point cloud.
Definition: PointCloudProcessor.cpp:514
ARMARX_VERBOSE
#define ARMARX_VERBOSE
Definition: Logging.h:187
armarx::ManagedIceObject::getIceManager
IceManagerPtr getIceManager() const
Returns the IceManager.
Definition: ManagedIceObject.cpp:366
visionx::SaveDialog::setPointCloudToSave
void setPointCloudToSave(CoinPointCloud *cloud)
Definition: SaveDialog.cpp:49
visionx::armem::pointcloud::PointType
PointType
Definition: constants.h:78
visionx::PointCloudProcessor::getPointCloudFormat
MetaPointCloudFormatPtr getPointCloudFormat(std::string providerName)
Definition: PointCloudProcessor.cpp:534
visionx::PointCloudProcessor::automaticConversion
bool automaticConversion
Definition: PointCloudProcessor.h:654
visionx
ArmarX headers.
Definition: OpenPoseStressTest.h:38
CoinPointCloud.h
visionx::Manager::unregisterPointCloud
void unregisterPointCloud(const std::string &name)
Definition: Manager.cpp:48
visionx::WidgetController::newPointCloudReceived
void newPointCloudReceived(QString providerName, CoinPointCloud *cloud)
visionx::WidgetController::selectColor
void selectColor()
Definition: WidgetController.cpp:404
visionx::WidgetController::onInitPointCloudProcessor
void onInitPointCloudProcessor() override
Definition: WidgetController.cpp:73
PointCloudProvider.h
visionx::PointCloudProcessor::isPointCloudProviderKnown
bool isPointCloudProviderKnown(const std::string &providerName) const
Indicate whether the given name identifies a known point cloud provider.
Definition: PointCloudProcessor.cpp:416
visionx::tools::isLabeled
bool isLabeled(PointContentType type)
Definition: PointCloudConversions.cpp:131
visionx::WidgetController::onUnlockWidget
void onUnlockWidget() override
Definition: WidgetController.cpp:486
armarx::ArmarXWidgetController::getMainWindow
virtual QMainWindow * getMainWindow()
Returns the ArmarX MainWindow.
Definition: ArmarXWidgetController.cpp:136
visionx::CoinPointCloud::getPCLCloud
pcl::PointCloud< PointT >::ConstPtr getPCLCloud() const
Definition: CoinPointCloud.cpp:118
visionx::CoinPointCloud::getOriginalType
visionx::PointContentType getOriginalType() const
Definition: CoinPointCloud.cpp:124
segments.h
visionx::WidgetController::onDisconnectPointCloudProcessor
void onDisconnectPointCloudProcessor() override
Definition: WidgetController.cpp:89
visionx::WidgetController::refreshProviderList
void refreshProviderList()
Definition: WidgetController.cpp:316
visionx::Manager
Definition: Manager.h:34
cxxopts::value
std::shared_ptr< Value > value()
Definition: cxxopts.hpp:855
PCLUtilities.h
visionx::WidgetController::~WidgetController
~WidgetController() override
Controller destructor.
Definition: WidgetController.cpp:56
visionx::WidgetController::onConnectPointCloudProcessor
void onConnectPointCloudProcessor() override
Definition: WidgetController.cpp:79
visionx::WidgetController::onExitPointCloudProcessor
void onExitPointCloudProcessor() override
Definition: WidgetController.cpp:133
filename
std::string filename
Definition: VisualizationRobot.cpp:86
armarx::PointCloudT
pcl::PointCloud< PointT > PointCloudT
Definition: Common.h:32
visionx::tools::toString
std::string toString(PointContentType pointContent)
Definition: PointCloudConversions.cpp:839
visionx::PointCloudProcessor::getPointClouds
int getPointClouds(const PointCloudPtrT &pointCloudPtr)
Poll PointClouds from provider.
Definition: PointCloudProcessor.h:380
visionx::WidgetController::processPointCloud
void processPointCloud(QString providerName, CoinPointCloud *cloud)
Definition: WidgetController.cpp:257
armarx::statechartmodel::eActivated
@ eActivated
Definition: SignalType.h:38
visionx::Manager::getRegisteredPointClouds
std::vector< std::string > getRegisteredPointClouds()
Definition: Manager.cpp:67
armarx::to_string
const std::string & to_string(const std::string &s)
Definition: StringHelpers.h:41
ARMARX_LOG
#define ARMARX_LOG
Definition: Logging.h:165
visionx::CoinPointCloud
Definition: CoinPointCloud.h:38
visionx::Manager::updatePointCloud
void updatePointCloud(const std::string &name, CoinPointCloud &cloud)
Definition: Manager.cpp:88
visionx::WidgetController::saveSettings
void saveSettings(QSettings *settings) override
Definition: WidgetController.cpp:67
visionx::Manager::registerPointCloud
void registerPointCloud(const std::string &name)
Definition: Manager.cpp:38
visionx::SaveDialog
Definition: SaveDialog.h:38
visionx::Manager::getCloudByName
CoinPointCloud * getCloudByName(const std::string &name)
Definition: Manager.cpp:80
PointCloudConversions.h
visionx::PointCloudProcessor::releasePointCloudProvider
void releasePointCloudProvider(std::string providerName)
Removes topic subscription and provider proxy dependency to release a point cloud provider.
Definition: PointCloudProcessor.cpp:295
visionx::SaveDialog::getResultFileName
std::string getResultFileName()
After calling the dialog, this contains the chosen file name.
Definition: SaveDialog.cpp:62
visionx::WidgetController::WidgetController
WidgetController()
Controller constructor.
Definition: WidgetController.cpp:51
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:181
visionx::WidgetController::savePointCloud
void savePointCloud()
Definition: WidgetController.cpp:415
IceUtil::Handle< IceGridAdmin >
visionx::WidgetController::onLockWidget
void onLockWidget() override
Definition: WidgetController.cpp:480
visionx::WidgetController::postDocking
void postDocking() override
postDocking is called after the widget has been docked into the main window.
Definition: WidgetController.cpp:138
visionx::WidgetController::pointCloudChecked
void pointCloudChecked(QListWidgetItem *item)
Definition: WidgetController.cpp:386
visionx::PointCloudProcessor::usingPointCloudProvider
void usingPointCloudProvider(std::string providerName)
Registers a delayed topic subscription and a delayed provider proxy retrieval which will be available...
Definition: PointCloudProcessor.cpp:279
visionx::WidgetController::updateProviderList
void updateProviderList(IceGrid::ObjectInfoSeq objects)
Definition: WidgetController.cpp:274
visionx::SaveDialog::releaseBuffer
void releaseBuffer()
Definition: SaveDialog.cpp:56
armarx::Logging::deactivateSpam
SpamFilterDataPtr deactivateSpam(float deactivationDurationSec=10.0f, const std::string &identifier="", bool deactivate=true) const
disables the logging for the current line for the given amount of seconds.
Definition: Logging.cpp:99
armarx::ArmarXWidgetController::getWidget
virtual QPointer< QWidget > getWidget()
getWidget returns a pointer to the a widget of this controller.
Definition: ArmarXWidgetController.cpp:54
visionx::PointCloudProcessor::getPointCloudProvider
PointCloudProviderInfo getPointCloudProvider(std::string name, bool waitForProxy=false)
Select an PointCloudProvider.
Definition: PointCloudProcessor.cpp:325
visionx::WidgetController::showPointCloudInfo
void showPointCloudInfo(QListWidgetItem *item)
Definition: WidgetController.cpp:329
visionx::WidgetController::loadSettings
void loadSettings(QSettings *settings) override
Definition: WidgetController.cpp:61
ARMARX_WARNING
#define ARMARX_WARNING
Definition: Logging.h:193
CoinViewer.h
visionx::WidgetController::process
void process() override
Definition: WidgetController.cpp:192