ParametersToolBox.cpp
Go to the documentation of this file.
00001 /*
00002 Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
00003 All rights reserved.
00004 
00005 Redistribution and use in source and binary forms, with or without
00006 modification, are permitted provided that the following conditions are met:
00007     * Redistributions of source code must retain the above copyright
00008       notice, this list of conditions and the following disclaimer.
00009     * Redistributions in binary form must reproduce the above copyright
00010       notice, this list of conditions and the following disclaimer in the
00011       documentation and/or other materials provided with the distribution.
00012     * Neither the name of the Universite de Sherbrooke nor the
00013       names of its contributors may be used to endorse or promote products
00014       derived from this software without specific prior written permission.
00015 
00016 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
00017 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00018 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00019 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
00020 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00021 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00022 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00023 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00024 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00025 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00026 */
00027 
00028 //
00029 // Original version from Find-Object: https://github.com/introlab/find-object
00030 //
00031 
00032 #include <rtabmap/core/Parameters.h>
00033 #include <rtabmap/core/Optimizer.h>
00034 
00035 #include "rtabmap/gui/ParametersToolBox.h"
00036 #include <QComboBox>
00037 #include <QDoubleSpinBox>
00038 #include <QLineEdit>
00039 #include <QStackedWidget>
00040 #include <QScrollArea>
00041 #include <QLabel>
00042 #include <QGroupBox>
00043 #include <QCheckBox>
00044 #include <QVBoxLayout>
00045 #include <QMessageBox>
00046 #include <QPushButton>
00047 #include <stdio.h>
00048 #include <rtabmap/utilite/ULogger.h>
00049 #include <rtabmap/utilite/UConversion.h>
00050 #include <rtabmap/utilite/UStl.h>
00051 #include <opencv2/opencv_modules.hpp>
00052 
00053 namespace rtabmap {
00054 
00055 ParametersToolBox::ParametersToolBox(QWidget *parent) :
00056         QWidget(parent),
00057         comboBox_(new QComboBox(this)),
00058         stackedWidget_(new QStackedWidget(this))
00059 {
00060         QVBoxLayout * layout = new QVBoxLayout(this);
00061         this->setLayout(layout);
00062 
00063         layout->addWidget(comboBox_);
00064         layout->addWidget(stackedWidget_, 1);
00065         QPushButton * resetButton = new QPushButton(this);
00066         resetButton->setText(tr("Restore Defaults"));
00067         layout->addWidget(resetButton);
00068         connect(resetButton, SIGNAL(clicked()), this, SLOT(resetCurrentPage()));
00069 }
00070 
00071 ParametersToolBox::~ParametersToolBox()
00072 {
00073 }
00074 
00075 QWidget * ParametersToolBox::getParameterWidget(const QString & key)
00076 {
00077         return this->findChild<QWidget*>(key);
00078 }
00079 
00080 QStringList ParametersToolBox::resetPage(int index)
00081 {
00082         QStringList paramChanged;
00083         const QObjectList & children = stackedWidget_->widget(index)->children().first()->children().first()->children();
00084         for(int j=0; j<children.size();++j)
00085         {
00086                 QString key = children.at(j)->objectName();
00087                 // ignore working memory
00088                 QString group = key.split("/").first();
00089                 if(parameters_.find(key.toStdString())!=parameters_.end())
00090                 {
00091                         UASSERT_MSG(parameters_.find(key.toStdString()) != parameters_.end(), uFormat("key=%s", key.toStdString().c_str()).c_str());
00092                         std::string value = Parameters::getDefaultParameters().at(key.toStdString());
00093                         parameters_.at(key.toStdString()) = value;
00094 
00095                         if(qobject_cast<QComboBox*>(children.at(j)))
00096                         {
00097                                 if(((QComboBox*)children.at(j))->currentIndex() != QString::fromStdString(value).split(':').first().toInt())
00098                                 {
00099                                         ((QComboBox*)children.at(j))->setCurrentIndex(QString::fromStdString(value).split(':').first().toInt());
00100                                         paramChanged.append(key);
00101                                 }
00102                         }
00103                         else if(qobject_cast<QSpinBox*>(children.at(j)))
00104                         {
00105                                 if(((QSpinBox*)children.at(j))->value() != uStr2Int(value))
00106                                 {
00107                                         ((QSpinBox*)children.at(j))->setValue(uStr2Int(value));
00108                                         paramChanged.append(key);
00109                                 }
00110                         }
00111                         else if(qobject_cast<QDoubleSpinBox*>(children.at(j)))
00112                         {
00113                                 if(((QDoubleSpinBox*)children.at(j))->value() != uStr2Double(value))
00114                                 {
00115                                         ((QDoubleSpinBox*)children.at(j))->setValue(uStr2Double(value));
00116                                         paramChanged.append(key);
00117                                 }
00118                         }
00119                         else if(qobject_cast<QCheckBox*>(children.at(j)))
00120                         {
00121                                 if(((QCheckBox*)children.at(j))->isChecked() != uStr2Bool(value))
00122                                 {
00123                                         ((QCheckBox*)children.at(j))->setChecked(uStr2Bool(value));
00124                                         paramChanged.append(key);
00125                                 }
00126                         }
00127                         else if(qobject_cast<QLineEdit*>(children.at(j)))
00128                         {
00129                                 if(((QLineEdit*)children.at(j))->text().compare(QString::fromStdString(value)) != 0)
00130                                 {
00131                                         ((QLineEdit*)children.at(j))->setText(QString::fromStdString(value));
00132                                         paramChanged.append(key);
00133                                 }
00134                         }
00135                 }
00136         }
00137         return paramChanged;
00138 }
00139 
00140 void ParametersToolBox::resetCurrentPage()
00141 {
00142         this->blockSignals(true);
00143         QStringList paramChanged = this->resetPage(stackedWidget_->currentIndex());
00144         this->blockSignals(false);
00145         Q_EMIT parametersChanged(paramChanged);
00146 }
00147 
00148 void ParametersToolBox::resetAllPages()
00149 {
00150         QStringList paramChanged;
00151         this->blockSignals(true);
00152         for(int i=0; i< stackedWidget_->count(); ++i)
00153         {
00154                 paramChanged.append(this->resetPage(i));
00155         }
00156         this->blockSignals(false);
00157         Q_EMIT parametersChanged(paramChanged);
00158 }
00159 
00160 void ParametersToolBox::updateParametersVisibility()
00161 {
00162         //show/hide not used parameters
00163         /*QComboBox * descriptorBox = this->findChild<QComboBox*>(Parameters::kFeature2D_2Descriptor());
00164         QComboBox * detectorBox = this->findChild<QComboBox*>(Parameters::kFeature2D_1Detector());
00165         if(descriptorBox && detectorBox)
00166         {
00167                 QString group = Parameters::kFeature2D_2Descriptor().split('/').first();
00168                 QWidget * panel = 0;
00169                 for(int i=0; i<this->count(); ++i)
00170                 {
00171                         if(this->widget(i)->objectName().compare(group) == 0)
00172                         {
00173                                 panel = this->widget(i);
00174                                 break;
00175                         }
00176                 }
00177                 if(panel)
00178                 {
00179                         const QObjectList & objects = panel->children();
00180                         QString descriptorName = descriptorBox->currentText();
00181                         QString detectorName = detectorBox->currentText();
00182 
00183                         for(int i=0; i<objects.size(); ++i)
00184                         {
00185                                 if(!objects[i]->objectName().isEmpty())
00186                                 {
00187                                         if(objects[i]->objectName().contains(descriptorName) || objects[i]->objectName().contains(detectorName))
00188                                         {
00189                                                 ((QWidget*)objects[i])->setVisible(true);
00190                                         }
00191                                         else if(objects[i]->objectName().contains("Fast") && detectorName == QString("ORB"))
00192                                         {
00193                                                 ((QWidget*)objects[i])->setVisible(true);       // ORB uses some FAST parameters
00194                                         }
00195                                         else if(!objects[i]->objectName().split('/').at(1).at(0).isDigit())
00196                                         {
00197                                                 ((QWidget*)objects[i])->setVisible(false);
00198                                         }
00199                                 }
00200                         }
00201                 }
00202         }*/
00203 }
00204 
00205 void ParametersToolBox::setupUi(const ParametersMap & parameters)
00206 {
00207         parameters_ = parameters;
00208         QWidget * currentItem = 0;
00209         QStringList groups;
00210         for(ParametersMap::const_iterator iter=parameters.begin();
00211                         iter!=parameters.end();
00212                         ++iter)
00213         {
00214                 QStringList splitted = QString::fromStdString(iter->first).split('/');
00215                 QString group = splitted.first();
00216 
00217                 QString name = splitted.last();
00218                 if(currentItem == 0 || currentItem->objectName().compare(group) != 0)
00219                 {
00220                         groups.push_back(group);
00221                         QScrollArea * area = new QScrollArea(this);
00222                         stackedWidget_->addWidget(area);
00223                         currentItem = new QWidget();
00224                         currentItem->setObjectName(group);
00225                         QVBoxLayout * layout = new QVBoxLayout(currentItem);
00226                         layout->setSizeConstraint(QLayout::SetMinimumSize);
00227                         layout->setContentsMargins(0,0,0,0);
00228                         layout->setSpacing(0);
00229                         area->setWidget(currentItem);
00230 
00231                         addParameter(layout, iter->first, iter->second);
00232                 }
00233                 else
00234                 {
00235                         addParameter((QVBoxLayout*)currentItem->layout(), iter->first, iter->second);
00236                 }
00237         }
00238         comboBox_->addItems(groups);
00239         connect(comboBox_, SIGNAL(currentIndexChanged(int)), stackedWidget_, SLOT(setCurrentIndex(int)));
00240 
00241         updateParametersVisibility();
00242 }
00243 
00244 void ParametersToolBox::updateParameter(const std::string & key, const std::string & value)
00245 {
00246         QString group = QString::fromStdString(key).split("/").first();
00247         if(parameters_.find(key) != parameters_.end())
00248         {
00249                 parameters_.at(key) = value;
00250                 QWidget * widget = this->findChild<QWidget*>(key.c_str());
00251                 QString type = QString::fromStdString(Parameters::getType(key));
00252                 if(type.compare("string") == 0)
00253                 {
00254                         QString valueQt = QString::fromStdString(value);
00255                         if(valueQt.contains(';'))
00256                         {
00257                                 // It's a list, just change the index
00258                                 QStringList splitted = valueQt.split(':');
00259                                 ((QComboBox*)widget)->setCurrentIndex(splitted.first().toInt());
00260                         }
00261                         else
00262                         {
00263                                 ((QLineEdit*)widget)->setText(valueQt);
00264                         }
00265                 }
00266                 else if(type.compare("int") == 0)
00267                 {
00268                         ((QSpinBox*)widget)->setValue(uStr2Int(value));
00269                 }
00270                 else if(type.compare("uint") == 0)
00271                 {
00272                         ((QSpinBox*)widget)->setValue(uStr2Int(value));
00273                 }
00274                 else if(type.compare("double") == 0)
00275                 {
00276                         ((QDoubleSpinBox*)widget)->setValue(uStr2Double(value));
00277                 }
00278                 else if(type.compare("float") == 0)
00279                 {
00280                         ((QDoubleSpinBox*)widget)->setValue(uStr2Float(value));
00281                 }
00282                 else if(type.compare("bool") == 0)
00283                 {
00284                         ((QCheckBox*)widget)->setChecked(uStr2Bool(value));
00285                 }
00286         }
00287 }
00288 
00289 void ParametersToolBox::addParameter(
00290                 QVBoxLayout * layout,
00291                 const std::string & key,
00292                 const std::string & value)
00293 {
00294         std::string type = Parameters::getType(key);
00295         if(type.compare("string") == 0)
00296         {
00297                 addParameter(layout, key.c_str(), QString::fromStdString(value));
00298         }
00299         else if(type.compare("int") == 0)
00300         {
00301                 addParameter(layout, key.c_str(), uStr2Int(value));
00302         }
00303         else if(type.compare("uint") == 0)
00304         {
00305                 addParameter(layout, key.c_str(), uStr2Int(value));
00306         }
00307         else if(type.compare("double") == 0)
00308         {
00309                 addParameter(layout, key.c_str(), uStr2Double(value));
00310         }
00311         else if(type.compare("float") == 0)
00312         {
00313                 addParameter(layout, key.c_str(), uStr2Double(value));
00314         }
00315         else if(type.compare("bool") == 0)
00316         {
00317                 addParameter(layout, key.c_str(), uStr2Bool(value));
00318         }
00319 }
00320 
00321 void ParametersToolBox::addParameter(QVBoxLayout * layout,
00322                 const QString & key,
00323                 const QString & value)
00324 {
00325         if(value.contains(';'))
00326         {
00327                 QComboBox * widget = new QComboBox(this);
00328                 widget->setObjectName(key);
00329                 QStringList splitted = value.split(':');
00330                 widget->addItems(splitted.last().split(';'));
00331 
00332                 widget->setCurrentIndex(splitted.first().toInt());
00333                 connect(widget, SIGNAL(currentIndexChanged(int)), this, SLOT(changeParameter(int)));
00334                 addParameter(layout, key, widget);
00335         }
00336         else
00337         {
00338                 QLineEdit * widget = new QLineEdit(value, this);
00339                 widget->setObjectName(key);
00340                 connect(widget, SIGNAL(editingFinished()), this, SLOT(changeParameter()));
00341                 addParameter(layout, key, widget);
00342         }
00343 }
00344 
00345 void ParametersToolBox::addParameter(QVBoxLayout * layout,
00346                 const QString & key,
00347                 const double & value)
00348 {
00349         QDoubleSpinBox * widget = new QDoubleSpinBox(this);
00350         int decimals = 0;
00351         int decimalValue = 0;
00352 
00353         QString str = Parameters::getDefaultParameters().at(key.toStdString()).c_str();
00354         if(!str.isEmpty())
00355         {
00356                 str.replace(',', '.');
00357                 QStringList items = str.split('.');
00358                 if(items.size() == 2)
00359                 {
00360                         decimals = items.back().length();
00361                         decimalValue = items.back().toInt();
00362                 }
00363         }
00364 
00365         double def = uStr2Double(Parameters::getDefaultParameters().at(key.toStdString()));
00366         if(def<0.001 || (decimals >= 4 && decimalValue>0))
00367         {
00368                 widget->setDecimals(5);
00369                 widget->setSingleStep(0.0001);
00370         }
00371         else if(def<0.01 || (decimals >= 3 && decimalValue>0))
00372         {
00373                 widget->setDecimals(4);
00374                 widget->setSingleStep(0.001);
00375         }
00376         else if(def<0.1 || (decimals >= 2 && decimalValue>0))
00377         {
00378                 widget->setDecimals(3);
00379                 widget->setSingleStep(0.01);
00380         }
00381         else if(def<1.0 || (decimals >= 1 && decimalValue>0))
00382         {
00383                 widget->setDecimals(2);
00384                 widget->setSingleStep(0.1);
00385         }
00386         else
00387         {
00388                 widget->setDecimals(1);
00389         }
00390 
00391 
00392         if(def>0.0)
00393         {
00394                 widget->setMaximum(def*1000000.0);
00395         }
00396         else if(def==0.0)
00397         {
00398                 widget->setMaximum(1000000.0);
00399         }
00400         else if(def<0.0)
00401         {
00402                 widget->setMinimum(def*1000000.0);
00403                 widget->setMaximum(0.0);
00404         }
00405 
00406         // set minimum for selected parameters
00407         if(key.compare(Parameters::kGridMinGroundHeight().c_str()) == 0 ||
00408                 key.compare(Parameters::kGridMaxGroundHeight().c_str()) == 0 ||
00409                 key.compare(Parameters::kGridMaxObstacleHeight().c_str()) == 0)
00410         {
00411                 widget->setMinimum(-1000000.0);
00412         }
00413 
00414         widget->setValue(value);
00415         widget->setObjectName(key);
00416         connect(widget, SIGNAL(editingFinished()), this, SLOT(changeParameter()));
00417         addParameter(layout, key, widget);
00418 }
00419 
00420 void ParametersToolBox::addParameter(QVBoxLayout * layout,
00421                 const QString & key,
00422                 const int & value)
00423 {
00424         QSpinBox * widget = new QSpinBox(this);
00425         int def = uStr2Int(Parameters::getDefaultParameters().at(key.toStdString()));
00426 
00427         if(def>0)
00428         {
00429                 widget->setMaximum(def*1000000);
00430         }
00431         else if(def == 0)
00432         {
00433                 widget->setMaximum(1000000);
00434         }
00435         else if(def<0)
00436         {
00437                 widget->setMinimum(def*1000000);
00438                 widget->setMaximum(0);
00439         }
00440         widget->setValue(value);
00441         widget->setObjectName(key);
00442 
00443         if(key.compare(Parameters::kVisFeatureType().c_str()) == 0)
00444         {
00445 #ifndef RTABMAP_NONFREE
00446                 if(value <= 1)
00447                 {
00448                         UWARN("SURF/SIFT not available, setting feature default to FAST/BRIEF.");
00449                         widget->setValue(4);
00450                 }
00451 #endif
00452         }
00453         if(key.compare(Parameters::kOptimizerStrategy().c_str()) == 0)
00454         {
00455                 if(value == 0 && !Optimizer::isAvailable(Optimizer::kTypeTORO))
00456                 {
00457                         if(Optimizer::isAvailable(Optimizer::kTypeGTSAM))
00458                         {
00459                                 UWARN("TORO is not available, setting optimization default to GTSAM.");
00460                                 widget->setValue(2);
00461                         }
00462                         else if(Optimizer::isAvailable(Optimizer::kTypeG2O))
00463                         {
00464                                 UWARN("TORO is not available, setting optimization default to g2o.");
00465                                 widget->setValue(1);
00466                         }
00467                 }
00468                 if(value == 1 && !Optimizer::isAvailable(Optimizer::kTypeG2O))
00469                 {
00470                         if(Optimizer::isAvailable(Optimizer::kTypeGTSAM))
00471                         {
00472                                 UWARN("g2o is not available, setting optimization default to GTSAM.");
00473                                 widget->setValue(2);
00474                         }
00475                         else if(Optimizer::isAvailable(Optimizer::kTypeTORO))
00476                         {
00477                                 UWARN("g2o is not available, setting optimization default to TORO.");
00478                                 widget->setValue(0);
00479                         }
00480                 }
00481                 if(value == 2 && !Optimizer::isAvailable(Optimizer::kTypeGTSAM))
00482                 {
00483                         if(Optimizer::isAvailable(Optimizer::kTypeG2O))
00484                         {
00485                                 UWARN("GTSAM is not available, setting optimization default to g2o.");
00486                                 widget->setValue(2);
00487                         }
00488                         else if(Optimizer::isAvailable(Optimizer::kTypeTORO))
00489                         {
00490                                 UWARN("GTSAM is not available, setting optimization default to TORO.");
00491                                 widget->setValue(1);
00492                         }
00493                 }
00494                 if(!Optimizer::isAvailable(Optimizer::kTypeG2O) &&
00495                         !Optimizer::isAvailable(Optimizer::kTypeGTSAM) &&
00496                         !Optimizer::isAvailable(Optimizer::kTypeTORO))
00497                 {
00498                         widget->setEnabled(false);
00499                 }
00500         }
00501 
00502         connect(widget, SIGNAL(editingFinished()), this, SLOT(changeParameter()));
00503         addParameter(layout, key, widget);
00504 }
00505 
00506 void ParametersToolBox::addParameter(QVBoxLayout * layout,
00507                 const QString & key,
00508                 const bool & value)
00509 {
00510         QCheckBox * widget = new QCheckBox(this);
00511         widget->setChecked(value);
00512         widget->setObjectName(key);
00513         connect(widget, SIGNAL(stateChanged(int)), this, SLOT(changeParameter(int)));
00514         addParameter(layout, key, widget);
00515 }
00516 
00517 void ParametersToolBox::addParameter(QVBoxLayout * layout, const QString & key, QWidget * widget)
00518 {
00519         QHBoxLayout * hLayout = new QHBoxLayout();
00520         layout->insertLayout(layout->count()-1, hLayout);
00521         QString tmp = key.split('/').last();
00522         QLabel * label = new QLabel(tmp, this);
00523         label->setObjectName(key+"/label");
00524         label->setToolTip(QString("<FONT>%1</FONT>").arg(Parameters::getDescription(key.toStdString()).c_str()));
00525         label->setTextInteractionFlags(Qt::TextSelectableByMouse);
00526         hLayout->addWidget(label);
00527         hLayout->addWidget(widget);
00528 }
00529 
00530 void ParametersToolBox::changeParameter(const QString & value)
00531 {
00532         if(sender())
00533         {
00534                 parameters_.at(sender()->objectName().toStdString()) = value.toStdString();
00535                 QStringList paramChanged;
00536                 paramChanged.append(sender()->objectName());
00537                 Q_EMIT parametersChanged(paramChanged);
00538         }
00539 }
00540 void ParametersToolBox::changeParameter()
00541 {
00542         if(sender())
00543         {
00544                 QDoubleSpinBox * doubleSpinBox = qobject_cast<QDoubleSpinBox*>(sender());
00545                 QSpinBox * spinBox = qobject_cast<QSpinBox*>(sender());
00546                 QLineEdit * lineEdit = qobject_cast<QLineEdit*>(sender());
00547                 if(doubleSpinBox)
00548                 {
00549                         parameters_.at(sender()->objectName().toStdString()) = uNumber2Str(doubleSpinBox->value());
00550                 }
00551                 else if(spinBox)
00552                 {
00553                         parameters_.at(sender()->objectName().toStdString()) = uNumber2Str(spinBox->value());
00554                 }
00555                 else if(lineEdit)
00556                 {
00557                         parameters_.at(sender()->objectName().toStdString()) =  lineEdit->text().toStdString();
00558                 }
00559                 QStringList paramChanged;
00560                 paramChanged.append(sender()->objectName());
00561                 Q_EMIT parametersChanged(paramChanged);
00562         }
00563 }
00564 
00565 void ParametersToolBox::changeParameter(const int & value)
00566 {
00567         if(sender())
00568         {
00569                 QStringList paramChanged;
00570                 QComboBox * comboBox = qobject_cast<QComboBox*>(sender());
00571                 QCheckBox * checkBox = qobject_cast<QCheckBox*>(sender());
00572                 if(comboBox)
00573                 {
00574                         QStringList items;
00575                         for(int i=0; i<comboBox->count(); ++i)
00576                         {
00577                                 items.append(comboBox->itemText(i));
00578                         }
00579                         QString merged = QString::number(value) + QString(":") + items.join(";");
00580                         parameters_.at(sender()->objectName().toStdString()) = merged.toStdString();
00581 
00582                         this->updateParametersVisibility();
00583                 }
00584                 else if(checkBox)
00585                 {
00586                         parameters_.at(sender()->objectName().toStdString()) = uBool2Str(value==Qt::Checked?true:false);
00587                 }
00588 
00589                 paramChanged.append(sender()->objectName());
00590                 Q_EMIT parametersChanged(paramChanged);
00591         }
00592 }
00593 
00594 } // namespace find_object


rtabmap
Author(s): Mathieu Labbe
autogenerated on Thu Jun 6 2019 21:59:21