00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include <rtabmap/core/Parameters.h>
00033 #include <rtabmap/core/Optimizer.h>
00034
00035 #include "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 <opencv2/opencv_modules.hpp>
00051
00052 namespace rtabmap {
00053
00054 ParametersToolBox::ParametersToolBox(QWidget *parent) :
00055 QWidget(parent),
00056 comboBox_(new QComboBox(this)),
00057 stackedWidget_(new QStackedWidget(this)),
00058 parameters_(Parameters::getDefaultParameters())
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
00088 QString group = key.split("/").first();
00089 if(!ignoredGroups_.contains(group) && 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
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203 }
00204
00205 void ParametersToolBox::setupUi(const QSet<QString> & ignoredGroups)
00206 {
00207 ignoredGroups_ = ignoredGroups;
00208 QWidget * currentItem = 0;
00209 const ParametersMap & parameters = Parameters::getDefaultParameters();
00210 QStringList groups;
00211 for(ParametersMap::const_iterator iter=parameters.begin();
00212 iter!=parameters.end();
00213 ++iter)
00214 {
00215 QStringList splitted = QString::fromStdString(iter->first).split('/');
00216 QString group = splitted.first();
00217 if(!ignoredGroups_.contains(group))
00218 {
00219 QString name = splitted.last();
00220 if(currentItem == 0 || currentItem->objectName().compare(group) != 0)
00221 {
00222 groups.push_back(group);
00223 QScrollArea * area = new QScrollArea(this);
00224 stackedWidget_->addWidget(area);
00225 currentItem = new QWidget();
00226 currentItem->setObjectName(group);
00227 QVBoxLayout * layout = new QVBoxLayout(currentItem);
00228 layout->setSizeConstraint(QLayout::SetMinimumSize);
00229 layout->setContentsMargins(0,0,0,0);
00230 layout->setSpacing(0);
00231 area->setWidget(currentItem);
00232
00233 addParameter(layout, iter->first, iter->second);
00234 }
00235 else
00236 {
00237 addParameter((QVBoxLayout*)currentItem->layout(), iter->first, iter->second);
00238 }
00239 }
00240 }
00241 comboBox_->addItems(groups);
00242 connect(comboBox_, SIGNAL(currentIndexChanged(int)), stackedWidget_, SLOT(setCurrentIndex(int)));
00243
00244 updateParametersVisibility();
00245 }
00246
00247 void ParametersToolBox::updateParameter(const std::string & key, const std::string & value)
00248 {
00249 QString group = QString::fromStdString(key).split("/").first();
00250 if(!ignoredGroups_.contains(group))
00251 {
00252 if(parameters_.find(key) == parameters_.end())
00253 {
00254 UWARN("key=\"%s\" doesn't exist", key.c_str());
00255 }
00256 else
00257 {
00258 parameters_.at(key) = value;
00259 QWidget * widget = this->findChild<QWidget*>(key.c_str());
00260 QString type = QString::fromStdString(Parameters::getType(key));
00261 if(type.compare("string") == 0)
00262 {
00263 QString valueQt = QString::fromStdString(value);
00264 if(valueQt.contains(';'))
00265 {
00266
00267 QStringList splitted = valueQt.split(':');
00268 ((QComboBox*)widget)->setCurrentIndex(splitted.first().toInt());
00269 }
00270 else
00271 {
00272 ((QLineEdit*)widget)->setText(valueQt);
00273 }
00274 }
00275 else if(type.compare("int") == 0)
00276 {
00277 ((QSpinBox*)widget)->setValue(uStr2Int(value));
00278 }
00279 else if(type.compare("uint") == 0)
00280 {
00281 ((QSpinBox*)widget)->setValue(uStr2Int(value));
00282 }
00283 else if(type.compare("double") == 0)
00284 {
00285 ((QDoubleSpinBox*)widget)->setValue(uStr2Double(value));
00286 }
00287 else if(type.compare("float") == 0)
00288 {
00289 ((QDoubleSpinBox*)widget)->setValue(uStr2Float(value));
00290 }
00291 else if(type.compare("bool") == 0)
00292 {
00293 ((QCheckBox*)widget)->setChecked(uStr2Bool(value));
00294 }
00295 }
00296 }
00297 }
00298
00299 void ParametersToolBox::addParameter(
00300 QVBoxLayout * layout,
00301 const std::string & key,
00302 const std::string & value)
00303 {
00304 std::string type = Parameters::getType(key);
00305 if(type.compare("string") == 0)
00306 {
00307 addParameter(layout, key.c_str(), QString::fromStdString(value));
00308 }
00309 else if(type.compare("int") == 0)
00310 {
00311 addParameter(layout, key.c_str(), uStr2Int(value));
00312 }
00313 else if(type.compare("uint") == 0)
00314 {
00315 addParameter(layout, key.c_str(), uStr2Int(value));
00316 }
00317 else if(type.compare("double") == 0)
00318 {
00319 addParameter(layout, key.c_str(), uStr2Double(value));
00320 }
00321 else if(type.compare("float") == 0)
00322 {
00323 addParameter(layout, key.c_str(), uStr2Double(value));
00324 }
00325 else if(type.compare("bool") == 0)
00326 {
00327 addParameter(layout, key.c_str(), uStr2Bool(value));
00328 }
00329 }
00330
00331 void ParametersToolBox::addParameter(QVBoxLayout * layout,
00332 const QString & key,
00333 const QString & value)
00334 {
00335 if(value.contains(';'))
00336 {
00337 QComboBox * widget = new QComboBox(this);
00338 widget->setObjectName(key);
00339 QStringList splitted = value.split(':');
00340 widget->addItems(splitted.last().split(';'));
00341
00342 widget->setCurrentIndex(splitted.first().toInt());
00343 connect(widget, SIGNAL(currentIndexChanged(int)), this, SLOT(changeParameter(int)));
00344 addParameter(layout, key, widget);
00345 }
00346 else
00347 {
00348 QLineEdit * widget = new QLineEdit(value, this);
00349 widget->setObjectName(key);
00350 connect(widget, SIGNAL(editingFinished()), this, SLOT(changeParameter()));
00351 addParameter(layout, key, widget);
00352 }
00353 }
00354
00355 void ParametersToolBox::addParameter(QVBoxLayout * layout,
00356 const QString & key,
00357 const double & value)
00358 {
00359 QDoubleSpinBox * widget = new QDoubleSpinBox(this);
00360 double def = uStr2Double(Parameters::getDefaultParameters().at(key.toStdString()));
00361 if(def<0.01)
00362 {
00363 widget->setDecimals(4);
00364 }
00365 else if(def<0.1)
00366 {
00367 widget->setDecimals(3);
00368 }
00369
00370 if(def>0.0)
00371 {
00372 widget->setMaximum(def*1000000.0);
00373 }
00374 else if(def==0.0)
00375 {
00376 widget->setMaximum(1000000.0);
00377 }
00378 else if(def<0.0)
00379 {
00380 widget->setMinimum(def*1000000.0);
00381 widget->setMaximum(0.0);
00382 }
00383 widget->setValue(value);
00384 widget->setObjectName(key);
00385 connect(widget, SIGNAL(editingFinished()), this, SLOT(changeParameter()));
00386 addParameter(layout, key, widget);
00387 }
00388
00389 void ParametersToolBox::addParameter(QVBoxLayout * layout,
00390 const QString & key,
00391 const int & value)
00392 {
00393 QSpinBox * widget = new QSpinBox(this);
00394 int def = uStr2Int(Parameters::getDefaultParameters().at(key.toStdString()));
00395
00396 if(def>0)
00397 {
00398 widget->setMaximum(def*1000000);
00399 }
00400 else if(def == 0)
00401 {
00402 widget->setMaximum(1000000);
00403 }
00404 else if(def<0)
00405 {
00406 widget->setMinimum(def*1000000);
00407 widget->setMaximum(0);
00408 }
00409 widget->setValue(value);
00410 widget->setObjectName(key);
00411
00412 if(key.compare(Parameters::kVisFeatureType().c_str()) == 0)
00413 {
00414 #ifndef RTABMAP_NONFREE
00415 if(value <= 1)
00416 {
00417 UWARN("SURF/SIFT not available, setting feature default to FAST/BRIEF.");
00418 widget->setValue(4);
00419 }
00420 #endif
00421 }
00422 if(key.compare(Parameters::kOptimizerStrategy().c_str()) == 0)
00423 {
00424 if(value == 0 && !Optimizer::isAvailable(Optimizer::kTypeTORO))
00425 {
00426 if(Optimizer::isAvailable(Optimizer::kTypeGTSAM))
00427 {
00428 UWARN("TORO is not available, setting optimization default to GTSAM.");
00429 widget->setValue(2);
00430 }
00431 else if(Optimizer::isAvailable(Optimizer::kTypeG2O))
00432 {
00433 UWARN("TORO is not available, setting optimization default to g2o.");
00434 widget->setValue(1);
00435 }
00436 }
00437 if(value == 1 && !Optimizer::isAvailable(Optimizer::kTypeG2O))
00438 {
00439 if(Optimizer::isAvailable(Optimizer::kTypeGTSAM))
00440 {
00441 UWARN("g2o is not available, setting optimization default to GTSAM.");
00442 widget->setValue(2);
00443 }
00444 else if(Optimizer::isAvailable(Optimizer::kTypeTORO))
00445 {
00446 UWARN("g2o is not available, setting optimization default to TORO.");
00447 widget->setValue(0);
00448 }
00449 }
00450 if(value == 2 && !Optimizer::isAvailable(Optimizer::kTypeGTSAM))
00451 {
00452 if(Optimizer::isAvailable(Optimizer::kTypeG2O))
00453 {
00454 UWARN("GTSAM is not available, setting optimization default to g2o.");
00455 widget->setValue(2);
00456 }
00457 else if(Optimizer::isAvailable(Optimizer::kTypeTORO))
00458 {
00459 UWARN("GTSAM is not available, setting optimization default to TORO.");
00460 widget->setValue(1);
00461 }
00462 }
00463 if(!Optimizer::isAvailable(Optimizer::kTypeG2O) &&
00464 !Optimizer::isAvailable(Optimizer::kTypeGTSAM) &&
00465 !Optimizer::isAvailable(Optimizer::kTypeTORO))
00466 {
00467 widget->setEnabled(false);
00468 }
00469 }
00470
00471 connect(widget, SIGNAL(editingFinished()), this, SLOT(changeParameter()));
00472 addParameter(layout, key, widget);
00473 }
00474
00475 void ParametersToolBox::addParameter(QVBoxLayout * layout,
00476 const QString & key,
00477 const bool & value)
00478 {
00479 QCheckBox * widget = new QCheckBox(this);
00480 widget->setChecked(value);
00481 widget->setObjectName(key);
00482 connect(widget, SIGNAL(stateChanged(int)), this, SLOT(changeParameter(int)));
00483 addParameter(layout, key, widget);
00484 }
00485
00486 void ParametersToolBox::addParameter(QVBoxLayout * layout, const QString & key, QWidget * widget)
00487 {
00488 QHBoxLayout * hLayout = new QHBoxLayout();
00489 layout->insertLayout(layout->count()-1, hLayout);
00490 QString tmp = key.split('/').last();
00491 if(tmp.at(0).isDigit())
00492 {
00493 tmp.remove(0,1);
00494 }
00495 QLabel * label = new QLabel(tmp, this);
00496 label->setObjectName(key+"/label");
00497 label->setToolTip(QString("<FONT>%1</FONT>").arg(Parameters::getDescription(key.toStdString()).c_str()));
00498 label->setTextInteractionFlags(Qt::TextSelectableByMouse);
00499 hLayout->addWidget(label);
00500 hLayout->addWidget(widget);
00501 }
00502
00503 void ParametersToolBox::changeParameter(const QString & value)
00504 {
00505 if(sender())
00506 {
00507 parameters_.at(sender()->objectName().toStdString()) = value.toStdString();
00508 QStringList paramChanged;
00509 paramChanged.append(sender()->objectName());
00510 Q_EMIT parametersChanged(paramChanged);
00511 }
00512 }
00513 void ParametersToolBox::changeParameter()
00514 {
00515 if(sender())
00516 {
00517 QDoubleSpinBox * doubleSpinBox = qobject_cast<QDoubleSpinBox*>(sender());
00518 QSpinBox * spinBox = qobject_cast<QSpinBox*>(sender());
00519 QLineEdit * lineEdit = qobject_cast<QLineEdit*>(sender());
00520 if(doubleSpinBox)
00521 {
00522 parameters_.at(sender()->objectName().toStdString()) = uNumber2Str(doubleSpinBox->value());
00523 }
00524 else if(spinBox)
00525 {
00526 parameters_.at(sender()->objectName().toStdString()) = uNumber2Str(spinBox->value());
00527 }
00528 else if(lineEdit)
00529 {
00530 parameters_.at(sender()->objectName().toStdString()) = lineEdit->text().toStdString();
00531 }
00532 QStringList paramChanged;
00533 paramChanged.append(sender()->objectName());
00534 Q_EMIT parametersChanged(paramChanged);
00535 }
00536 }
00537
00538 void ParametersToolBox::changeParameter(const int & value)
00539 {
00540 if(sender())
00541 {
00542 QStringList paramChanged;
00543 QComboBox * comboBox = qobject_cast<QComboBox*>(sender());
00544 QCheckBox * checkBox = qobject_cast<QCheckBox*>(sender());
00545 if(comboBox)
00546 {
00547 QStringList items;
00548 for(int i=0; i<comboBox->count(); ++i)
00549 {
00550 items.append(comboBox->itemText(i));
00551 }
00552 QString merged = QString::number(value) + QString(":") + items.join(";");
00553 parameters_.at(sender()->objectName().toStdString()) = merged.toStdString();
00554
00555 this->updateParametersVisibility();
00556 }
00557 else if(checkBox)
00558 {
00559 parameters_.at(sender()->objectName().toStdString()) = uBool2Str(value==Qt::Checked?true:false);
00560 }
00561
00562 paramChanged.append(sender()->objectName());
00563 Q_EMIT parametersChanged(paramChanged);
00564 }
00565 }
00566
00567 }