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
49namespace visionx
50{
51 WidgetController::WidgetController() : recenterCamera(false)
52 {
53 qRegisterMetaType<IceGrid::ObjectInfoSeq>("IceGrid::ObjectInfoSeq");
54 }
55
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
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) !=
115 armarx::IceGridAdmin::eActivated)
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
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
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
492void
493visionx::WidgetController::setPointSize(double value)
494{
495 ARMARX_VERBOSE << "Using new point size: " << value;
496 pointSize = static_cast<float>(value);
497}
SpamFilterDataPtr deactivateSpam(SpamFilterDataPtr const &spamFilter, float deactivationDurationSec, const std::string &identifier, bool deactivate)
Definition Logging.cpp:75
virtual QPointer< QWidget > getWidget()
getWidget returns a pointer to the a widget of this controller.
virtual QMainWindow * getMainWindow()
Returns the ArmarX MainWindow.
IceManagerPtr getIceManager() const
Returns the IceManager.
visionx::PointContentType getOriginalType() const
pcl::PointCloud< PointT >::ConstPtr getPCLCloud() const
void unregisterPointCloud(const std::string &name)
Definition Manager.cpp:48
void releasePointCloudProvider(std::string providerName)
Removes topic subscription and provider proxy dependency to release a point cloud provider.
bool isPointCloudProviderKnown(const std::string &providerName) const
Indicate whether the given name identifies a known point cloud provider.
int getPointClouds(const PointCloudPtrT &pointCloudPtr)
Poll PointClouds from provider.
MetaPointCloudFormatPtr getPointCloudFormat(std::string providerName)
void usingPointCloudProvider(std::string providerName)
Registers a delayed topic subscription and a delayed provider proxy retrieval which will be available...
PointCloudProviderInfo getPointCloudProvider(std::string name, bool waitForProxy=false)
Select an PointCloudProvider.
bool pointCloudHasNewData(std::string providerName)
Returns current status for the given point cloud.
std::string getResultFileName()
After calling the dialog, this contains the chosen file name.
void setPointCloudToSave(CoinPointCloud *cloud)
void newPointCloudReceived(QString providerName, CoinPointCloud *cloud)
~WidgetController() override
Controller destructor.
WidgetController()
Controller constructor.
void updateProviderList(IceGrid::ObjectInfoSeq objects)
void loadSettings(QSettings *settings) override
void saveSettings(QSettings *settings) override
void onExitPointCloudProcessor() override
void processPointCloud(QString providerName, CoinPointCloud *cloud)
void postDocking() override
postDocking is called after the widget has been docked into the main window.
void showPointCloudInfo(QListWidgetItem *item)
void onConnectPointCloudProcessor() override
void onDisconnectPointCloudProcessor() override
void pointCloudChecked(QListWidgetItem *item)
void onInitPointCloudProcessor() override
#define ARMARX_INFO
The normal logging level.
Definition Logging.h:181
#define ARMARX_WARNING
The logging level for unexpected behaviour, but not a serious problem.
Definition Logging.h:193
#define ARMARX_LOG
Definition Logging.h:165
#define ARMARX_VERBOSE
The logging level for verbose information.
Definition Logging.h:187
IceUtil::Handle< IceGridAdmin > IceGridAdminPtr
Definition ArmarXFwd.h:48
std::string toString(PointContentType pointContent)
bool isLabeled(PointContentType type)
ArmarX headers.