AffordancePipelineGuiWidgetController.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 VisionX::gui-plugins::AffordancePipelineGuiWidgetController
17 * \author Peter Kaiser ( peter dot kaiser at kit dot edu )
18 * \date 2016
19 * \copyright http://www.gnu.org/licenses/gpl-2.0.txt
20 * GNU General Public License
21 */
22
24
25#include <string>
26
27#include <QCheckBox>
28#include <QListWidget>
29#include <QPushButton>
30
33
36
38
39using namespace armarx;
40
42{
43 widget.setupUi(getWidget());
44 updateTimer = new QTimer(this);
45}
46
51
52void
54{
55 pointCloudProviderNames.clear();
56 QList<QVariant> names = settings->value("pointCloudProviderNames", QList<QVariant>()).toList();
57 for (int i = 0; i < names.count(); i++)
58 {
59 pointCloudProviderNames.push_back(names[i].toString().toStdString());
60 }
61
62 filteredPointCloudProviderNames.clear();
63 names = settings->value("filteredPointCloudProviderNames", QList<QVariant>()).toList();
64 for (int i = 0; i < names.count(); i++)
65 {
66 filteredPointCloudProviderNames.push_back(names[i].toString().toStdString());
67 }
68
69 pointCloudProviderDisplayNames.clear();
70 names = settings->value("pointCloudProviderDisplayNames", QList<QVariant>()).toList();
71 for (int i = 0; i < names.count(); i++)
72 {
73 pointCloudProviderDisplayNames.push_back(names[i].toString().toStdString());
74 }
75
76 pipelineConfigFiles.clear();
77 names = settings->value("pipelineConfigFiles", QList<QVariant>()).toList();
78 for (int i = 0; i < names.count(); i++)
79 {
80 pipelineConfigFiles.push_back(names[i].toString().toStdString());
81 }
82
83 pointCloudSegmenterName =
84 settings->value("pointCloudSegmenterName", "").toString().toStdString();
85 primitiveExtractorName = settings->value("primitiveExtractorName", "").toString().toStdString();
86 affordanceExtractionName =
87 settings->value("affordanceExtractionName", "").toString().toStdString();
88 pipelineVisualizationName =
89 settings->value("pipelineVisualizationName", "").toString().toStdString();
90 robotStateComponentName =
91 settings->value("robotStateComponentName", "").toString().toStdString();
92 platform = settings->value("platform", "").toString().toStdString();
93}
94
95void
97{
98 QList<QVariant> names;
99 for (auto& name : pointCloudProviderNames)
100 {
101 names.append(QString::fromStdString(name));
102 }
103 settings->setValue("pointCloudProviderNames", names);
104
105 names.clear();
106 for (auto& name : filteredPointCloudProviderNames)
107 {
108 names.append(QString::fromStdString(name));
109 }
110 settings->setValue("filteredPointCloudProviderNames", names);
111
112 names.clear();
113 for (auto& name : pointCloudProviderDisplayNames)
114 {
115 names.append(QString::fromStdString(name));
116 }
117 settings->setValue("pointCloudProviderDisplayNames", names);
118
119 names.clear();
120 for (auto& filename : pipelineConfigFiles)
121 {
122 names.append(QString::fromStdString(filename));
123 }
124 settings->setValue("pipelineConfigFiles", names);
125
126 settings->setValue("pointCloudSegmenterName", QString::fromStdString(pointCloudSegmenterName));
127 settings->setValue("primitiveExtractorName", QString::fromStdString(primitiveExtractorName));
128 settings->setValue("affordanceExtractionName",
129 QString::fromStdString(affordanceExtractionName));
130 settings->setValue("pipelineVisualizationName",
131 QString::fromStdString(pipelineVisualizationName));
132 settings->setValue("robotStateComponentName", QString::fromStdString(robotStateComponentName));
133 settings->setValue("platform", QString::fromStdString(platform));
134}
135
136void
138{
139 for (auto& provider : pointCloudProviderNames)
140 {
141 usingProxy(provider);
142 }
143
144 for (auto& provider : filteredPointCloudProviderNames)
145 {
146 usingProxy(provider);
147 }
148
149 usingProxy(pointCloudSegmenterName);
150 usingProxy(primitiveExtractorName);
151 usingProxy(affordanceExtractionName);
152 usingProxy(pipelineVisualizationName);
153 usingProxy(robotStateComponentName);
154}
155
156void
158{
159 pointCloudProviders.clear();
160 for (auto& provider : pointCloudProviderNames)
161 {
162 pointCloudProviders.push_back(
164 }
165
166 filteredPointCloudProviders.clear();
167 for (auto& provider : filteredPointCloudProviderNames)
168 {
169 filteredPointCloudProviders.push_back(
171 }
172
173 pointCloudSegmenter =
175 primitiveExtractor = getProxy<visionx::PrimitiveMapperInterfacePrx>(primitiveExtractorName);
176 affordanceExtraction = getProxy<AffordanceExtractionInterfacePrx>(affordanceExtractionName);
177 pipelineVisualization =
179 robotStateComponent = getProxy<RobotStateComponentInterfacePrx>(robotStateComponentName);
180
181 // Load pipeline config files
182 widget.comboBoxSegmentation->clear();
183 for (unsigned int i = 0; i < pipelineConfigFiles.size(); i++)
184 {
185 widget.comboBoxSegmentation->addItem(QString::fromStdString("C" + std::to_string(i)));
186 }
187
188 // Initialize provider list in UI
189 widget.comboBoxPointCloudSource->clear();
190 for (auto& provider : pointCloudProviderDisplayNames)
191 {
192 widget.comboBoxPointCloudSource->addItem(QString::fromStdString(provider));
193 }
194 widget.comboBoxPointCloudSource->setCurrentIndex(0);
196
197 // Clear any previous visualization
198 pipelineVisualization->clearVisualization();
199
201
202 connect(widget.pushButtonStart, SIGNAL(clicked()), this, SLOT(startPipeline()));
203 connect(widget.pushButtonPause, SIGNAL(clicked()), this, SLOT(pausePipeline()));
204 connect(widget.pushButtonStep, SIGNAL(clicked()), this, SLOT(stepPipeline()));
205
206 connect(widget.comboBoxCropping,
207 SIGNAL(currentIndexChanged(int)),
208 this,
209 SLOT(croppingSelected(int)));
210 connect(widget.comboBoxPointCloudSource,
211 SIGNAL(currentIndexChanged(int)),
212 this,
213 SLOT(pointCloudSourceSelected(int)));
214 connect(widget.comboBoxSegmentation,
215 SIGNAL(currentIndexChanged(int)),
216 this,
217 SLOT(segmentationSetupSelected(int)));
218 connect(widget.checkBoxShowPrimitives,
219 SIGNAL(toggled(bool)),
220 this,
221 SLOT(visualizationOptionsChanged(bool)));
222 connect(widget.checkBoxShowAffordances,
223 SIGNAL(toggled(bool)),
224 this,
225 SLOT(visualizationOptionsChanged(bool)));
226
227 connect(updateTimer, SIGNAL(timeout()), this, SLOT(updatePipelineStatus()));
228 updateTimer->start(500);
229
230 // Set default cropping setup
231 widget.comboBoxCropping->setCurrentIndex(3);
232
233 // Set default segmentation setup
234 widget.comboBoxSegmentation->setCurrentIndex(0);
235
236 // Initially start in paused mode
238
239 QMetaObject::invokeMethod(
240 this, "visualizationOptionsChanged", Qt::QueuedConnection, Q_ARG(bool, true));
241}
242
243void
245{
246 QObject::disconnect(this, SLOT(startPipeline()));
247 QObject::disconnect(this, SLOT(pausePipeline()));
248 QObject::disconnect(this, SLOT(stepPipeline()));
249 QObject::disconnect(this, SLOT(croppingSelected(int)));
250 QObject::disconnect(this, SLOT(segmentationSetupSelected(int)));
251 QObject::disconnect(this, SLOT(pointCloudSourceSelected(int)));
252 QObject::disconnect(this, SLOT(visualizationOptionsChanged(bool)));
253
254 QObject::disconnect(this, SLOT(updatePipelineStatus()));
255 updateTimer->stop();
256
257 widget.labelProviderStatus->setText("Stopped");
258 widget.labelSegmenterStatus->setText("Stopped");
259 widget.labelPrimitivesStatus->setText("Stopped");
260 widget.labelAffordancesStatus->setText("Stopped");
261}
262
263void
265{
266 try
267 {
268 bool providerStatus = pointCloudProviders[currentPointCloudProvider]->isCaptureEnabled();
269 bool segmenterStatus = pointCloudSegmenter->isPipelineStepEnabled();
270 bool primitivesStatus = primitiveExtractor->isPipelineStepEnabled();
271 bool affordancesStatus = affordanceExtraction->isPipelineStepEnabled();
272
273 widget.labelProviderStatus->setText(providerStatus ? "Running" : "Paused");
274 widget.labelSegmenterStatus->setText(segmenterStatus ? "Running" : "Paused");
275 widget.labelPrimitivesStatus->setText(primitivesStatus ? "Running" : "Paused");
276 widget.labelAffordancesStatus->setText(affordancesStatus ? "Running" : "Paused");
277
278 widget.labelProviderTimestamp->setText(formatTimestamp(
279 pointCloudProviders[currentPointCloudProvider]->getPointCloudFormat()->timeProvided));
280 widget.labelSegmenterTimestamp->setText(
281 formatTimestamp(pointCloudSegmenter->getLastProcessedTimestamp()->timestamp));
282 widget.labelPrimitivesTimestamp->setText(
283 formatTimestamp(primitiveExtractor->getLastProcessedTimestamp()->timestamp));
284 widget.labelAffordancesTimestamp->setText(
285 formatTimestamp(affordanceExtraction->getLastProcessedTimestamp()->timestamp));
286
287 bool status = providerStatus && segmenterStatus && primitivesStatus && affordancesStatus;
288 widget.pushButtonStart->setEnabled(!status);
289 widget.pushButtonPause->setEnabled(status);
290 widget.pushButtonStep->setEnabled(!status);
291 }
292 catch (const Ice::ConnectionRefusedException& e)
293 {
294 ARMARX_INFO << "The pipeline has been killed";
295 }
296}
297
298void
300{
301 ARMARX_INFO << "Starting perception pipeline";
302
303 pointCloudSegmenter->enablePipelineStep();
304 primitiveExtractor->enablePipelineStep();
305 affordanceExtraction->enablePipelineStep();
306 pointCloudProviders[currentPointCloudProvider]->begin_startCapture();
307}
308
309void
311{
312 ARMARX_INFO << "Pausing perception pipeline";
313
314 pointCloudProviders[currentPointCloudProvider]->begin_stopCapture();
315 pointCloudSegmenter->disablePipelineStep();
316 primitiveExtractor->disablePipelineStep();
317 affordanceExtraction->disablePipelineStep();
318}
319
320void
322{
323 ARMARX_INFO << "Stepping perception pipeline";
324
325 pointCloudSegmenter->enablePipelineStep();
326 primitiveExtractor->enablePipelineStep();
327 affordanceExtraction->enablePipelineStep();
328 pointCloudProviders[currentPointCloudProvider]->begin_startCaptureForNumFrames(1);
329}
330
331void
333{
334 pipelineVisualization->begin_enableVisualization(widget.checkBoxShowPrimitives->isChecked(),
335 widget.checkBoxShowAffordances->isChecked(),
336 false);
337}
338
339void
341{
342 std::string filename =
343 QFileDialog::getOpenFileName(
344 getWidget(), tr("Open Affordance Scene"), "~", tr("Scene Files (*.scene)"))
345 .toStdString();
346 if (filename == "")
347 {
348 return;
349 }
350
351 affordanceExtraction->importScene(filename);
352}
353
354void
356{
357 std::string filename = QFileDialog::getSaveFileName(
358 NULL, tr("Save Affordance Scene"), "", tr("Scene Files (*.scene)"))
359 .toStdString();
360 if (filename == "")
361 {
362 return;
363 }
364
365 affordanceExtraction->exportScene(filename);
366}
367
368void
370{
371 Eigen::Vector3f min, max;
372
373 // Account for robots which don't have their root pose in the ground plane (e.g. ARMAR-4 as opposed to ARMAR-III)
374 float root_z =
375 PosePtr::dynamicCast(robotStateComponent->getSynchronizedRobot()->getGlobalPose())
376 ->toEigen()(2, 3);
377
378 switch (index)
379 {
380 case 0:
381 // Effectively disable cropping
382 min << -10000, -10000, -10000;
383 max << 10000, 10000, 10000;
384 break;
385
386 case 1:
387 min << -3000, 300, 0 - root_z;
388 max << 3000, 3000, 3000 - root_z;
389 break;
390
391 case 2:
392 min << -2000, 300, 300 - root_z;
393 max << 2000, 3000, 2500 - root_z;
394 break;
395
396 case 3:
397 min << -1000, 300, 600 - root_z;
398 max << 1000, 2000, 1500 - root_z;
399 break;
400
401 case 4:
402 min << -500, 300, 1000 - root_z;
403 max << 500, 2000, 1500 - root_z;
404 break;
405
406 default:
407 ARMARX_WARNING << "Unknown cropping setup selected";
408 break;
409 }
410
411 for (auto& provider : filteredPointCloudProviders)
412 {
413 provider->setCroppingParameters(new armarx::Vector3(min), new armarx::Vector3(max), "Root");
414 }
415}
416
417void
419{
420 currentPointCloudProvider = index;
421 pointCloudSegmenter->begin_changePointCloudProvider(
422 filteredPointCloudProviderNames[currentPointCloudProvider] + "Result");
423
424 segmentationSetupSelected(widget.comboBoxSegmentation->currentIndex());
425}
426
427void
429{
430 if (index < 0 || static_cast<std::size_t>(index) >= pipelineConfigFiles.size())
431 {
432 return;
433 }
434
435 primitiveExtractor->loadParametersFromFile(pipelineConfigFiles[index]);
436 pointCloudSegmenter->loadLccpParametersFromFile(pipelineConfigFiles[index]);
437}
438
439QString
440AffordancePipelineGuiWidgetController::formatTimestamp(long timestamp)
441{
442 IceUtil::Time time = IceUtil::Time::microSeconds(timestamp);
443 return QString(time.toDateTime().substr(time.toDateTime().find(' ') + 1).c_str());
444}
445
446QPointer<QDialog>
448{
449 if (!configDialog)
450 {
451 configDialog = new AffordancePipelineGuiConfigDialog(parent);
452 }
453
454 return qobject_cast<AffordancePipelineGuiConfigDialog*>(configDialog);
455}
456
457void
459{
460 pointCloudProviderNames = configDialog->getProviderNames();
461 pointCloudProviderDisplayNames = configDialog->getProviderDisplayNames();
462 filteredPointCloudProviderNames = configDialog->getFilteredProviderNames();
463 pipelineConfigFiles = configDialog->getPipelineConfigurationFiles();
464
465 pointCloudSegmenterName =
466 configDialog->pointCloudSegmenterProxyFinder->getSelectedProxyName().toStdString();
467 primitiveExtractorName =
468 configDialog->primitiveExtractorProxyFinder->getSelectedProxyName().toStdString();
469 affordanceExtractionName =
470 configDialog->affordanceExtractionProxyFinder->getSelectedProxyName().toStdString();
471 pipelineVisualizationName =
472 configDialog->pipelineVisualizationProxyFinder->getSelectedProxyName().toStdString();
473 robotStateComponentName =
474 configDialog->robotStateComponentProxyFinder->getSelectedProxyName().toStdString();
475 platform = configDialog->getPlatform();
476}
477
478QPointer<QWidget>
480{
481 if (customToolbar)
482 {
483 if (parent != customToolbar->parent())
484 {
485 customToolbar->setParent(parent);
486 }
487
488 return customToolbar;
489 }
490
491 customToolbar = new QToolBar(parent);
492 customToolbar->setIconSize(QSize(16, 16));
493 customToolbar->addAction(
494 QIcon(":/icons/document-open-folder.png"), "Load Scene File", this, SLOT(loadScene()));
495 customToolbar->addAction(
496 QIcon(":/icons/document-save-5.ico"), "Save Scene File", this, SLOT(saveScene()));
497
498 return customToolbar;
499}
std::string timestamp()
uint8_t index
QPointer< QWidget > getCustomTitlebarWidget(QWidget *parent=0) override
getTitleToolbar returns a pointer to the a toolbar widget of this controller.
QPointer< QDialog > getConfigDialog(QWidget *parent=0) override
getConfigDialog returns a pointer to the a configuration widget of this controller.
void configured() override
This function must be implemented by the user, if he supplies a config dialog.
virtual QPointer< QWidget > getWidget()
getWidget returns a pointer to the a widget of this controller.
bool usingProxy(const std::string &name, const std::string &endpoints="")
Registers a proxy for retrieval after initialization and adds it to the dependency list.
Ice::ObjectPrx getProxy(long timeoutMs=0, bool waitForScheduler=true) const
Returns the proxy of this object (optionally it waits for the proxy)
The Vector3 class.
Definition Pose.h:113
#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
This file offers overloads of toIce() and fromIce() functions for STL container types.
std::vector< T > max(const std::vector< T > &v1, const std::vector< T > &v2)
std::vector< T > min(const std::vector< T > &v1, const std::vector< T > &v2)