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 "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
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
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 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
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
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 }