UI: Added option to change map resolution on UI side, save/restore thresholds in figures, fixed basic panel's slam/rgbd mode checkboxes not changing the state of corresponding parameters.

This commit is contained in:
matlabbe
2024-04-12 17:12:23 -07:00
parent fbbab1c077
commit a3267c9da6
8 changed files with 213 additions and 45 deletions

View File

@@ -264,6 +264,11 @@ MainWindow::MainWindow(PreferencesDialog * prefDialog, QWidget * parent, bool sh
setupMainLayout(_preferencesDialog->isVerticalLayoutUsed());
ParametersMap parameters = _preferencesDialog->getAllParameters();
// Override map resolution for UI
if(_preferencesDialog->getGridUIResolution()>0)
{
uInsert(parameters, ParametersPair(Parameters::kGridCellSize(), uNumber2Str(_preferencesDialog->getGridUIResolution())));
}
_occupancyGrid = new OccupancyGrid(&_cachedLocalMaps, parameters);
#ifdef RTABMAP_OCTOMAP
_octomap = new OctoMap(&_cachedLocalMaps, parameters);
@@ -3002,7 +3007,28 @@ void MainWindow::updateMapCloud(
jter->sensorData().uncompressDataConst(0, 0, 0, 0, &ground, &obstacles, &empty);
_cachedLocalMaps.add(iter->first, ground, obstacles, empty, jter->sensorData().gridCellSize(), jter->sensorData().gridViewPoint());
double resolution = jter->sensorData().gridCellSize();
if(_preferencesDialog->getGridUIResolution() > jter->sensorData().gridCellSize())
{
resolution = _preferencesDialog->getGridUIResolution();
pcl::PointCloud<pcl::PointXYZ>::Ptr groundCloud = util3d::voxelize(util3d::laserScanToPointCloud(LaserScan::backwardCompatibility(ground)), resolution);
pcl::PointCloud<pcl::PointXYZ>::Ptr obstaclesCloud = util3d::voxelize(util3d::laserScanToPointCloud(LaserScan::backwardCompatibility(obstacles)), resolution);
pcl::PointCloud<pcl::PointXYZ>::Ptr emptyCloud = util3d::voxelize(util3d::laserScanToPointCloud(LaserScan::backwardCompatibility(empty)), resolution);
if(ground.channels() == 2)
ground = util3d::laserScan2dFromPointCloud(*groundCloud).data();
else
ground = util3d::laserScanFromPointCloud(*groundCloud).data();
if(obstacles.channels() == 2)
obstacles = util3d::laserScan2dFromPointCloud(*obstaclesCloud).data();
else
obstacles = util3d::laserScanFromPointCloud(*obstaclesCloud).data();
if(empty.channels() == 2)
empty = util3d::laserScan2dFromPointCloud(*emptyCloud).data();
else
empty = util3d::laserScanFromPointCloud(*emptyCloud).data();
}
_cachedLocalMaps.add(iter->first, ground, obstacles, empty, resolution, jter->sensorData().gridViewPoint());
}
}
@@ -5976,6 +6002,12 @@ void MainWindow::startDetection()
"progress will not be shown in the GUI."));
}
// Override map resolution for UI
if(_preferencesDialog->getGridUIResolution()>0)
{
uInsert(parameters, ParametersPair(Parameters::kGridCellSize(), uNumber2Str(_preferencesDialog->getGridUIResolution())));
}
_cachedLocalMaps.clear();
delete _occupancyGrid;
@@ -7513,7 +7545,8 @@ void MainWindow::saveFigures()
{
QList<int> curvesPerFigure;
QStringList curveNames;
_ui->statsToolBox->getFiguresSetup(curvesPerFigure, curveNames);
QStringList curveThresholds;
_ui->statsToolBox->getFiguresSetup(curvesPerFigure, curveNames, curveThresholds);
QStringList curvesPerFigureStr;
for(int i=0; i<curvesPerFigure.size(); ++i)
@@ -7526,17 +7559,24 @@ void MainWindow::saveFigures()
}
_preferencesDialog->saveCustomConfig("Figures", "counts", curvesPerFigureStr.join(" "));
_preferencesDialog->saveCustomConfig("Figures", "curves", curveNames.join(" "));
_preferencesDialog->saveCustomConfig("Figures", "thresholds", curveThresholds.join(" "));
}
void MainWindow::loadFigures()
{
QString curvesPerFigure = _preferencesDialog->loadCustomConfig("Figures", "counts");
QString curveNames = _preferencesDialog->loadCustomConfig("Figures", "curves");
QString curveThresholds = _preferencesDialog->loadCustomConfig("Figures", "thresholds");
if(!curvesPerFigure.isEmpty())
{
QStringList curvesPerFigureList = curvesPerFigure.split(" ");
QStringList curvesNamesList = curveNames.split(" ");
QStringList curveThresholdsList = curveThresholds.split(" ");
if(curveThresholdsList[0].isEmpty()) {
curveThresholdsList.clear();
}
UASSERT(curveThresholdsList.isEmpty() || curveThresholdsList.size() == curvesNamesList.size());
int j=0;
for(int i=0; i<curvesPerFigureList.size(); ++i)
@@ -7553,7 +7593,23 @@ void MainWindow::loadFigures()
_ui->statsToolBox->addCurve(curvesNamesList[j++].replace('_', ' '));
for(int k=1; k<count && j<curveNames.size(); ++k)
{
_ui->statsToolBox->addCurve(curvesNamesList[j++].replace('_', ' '), false);
if(curveThresholdsList.size())
{
bool ok = false;
double thresholdValue = curveThresholdsList[j].toDouble(&ok);
if(ok)
{
_ui->statsToolBox->addThreshold(curvesNamesList[j++].replace('_', ' '), thresholdValue);
}
else
{
_ui->statsToolBox->addCurve(curvesNamesList[j++].replace('_', ' '), false);
}
}
else
{
_ui->statsToolBox->addCurve(curvesNamesList[j++].replace('_', ' '), false);
}
}
}
}

View File

@@ -626,6 +626,7 @@ PreferencesDialog::PreferencesDialog(QWidget * parent) :
connect(_ui->doubleSpinBox_subtractFilteringRadius, SIGNAL(valueChanged(double)), this, SLOT(makeObsoleteCloudRenderingPanel()));
connect(_ui->doubleSpinBox_subtractFilteringAngle, SIGNAL(valueChanged(double)), this, SLOT(makeObsoleteCloudRenderingPanel()));
connect(_ui->doubleSpinBox_map_resolution, SIGNAL(valueChanged(double)), this, SLOT(makeObsoleteCloudRenderingPanel()));
connect(_ui->checkBox_map_shown, SIGNAL(clicked(bool)), this, SLOT(makeObsoleteCloudRenderingPanel()));
connect(_ui->doubleSpinBox_map_opacity, SIGNAL(valueChanged(double)), this, SLOT(makeObsoleteCloudRenderingPanel()));
connect(_ui->checkBox_elevation_shown, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteCloudRenderingPanel()));
@@ -2005,6 +2006,7 @@ void PreferencesDialog::resetSettings(QGroupBox * groupBox)
}
else if(groupBox->objectName() == _ui->groupBox_gridMap2->objectName())
{
_ui->doubleSpinBox_map_resolution->setValue(0);
_ui->checkBox_map_shown->setChecked(false);
_ui->doubleSpinBox_map_opacity->setValue(0.75);
_ui->checkBox_elevation_shown->setCheckState(Qt::Unchecked);
@@ -2490,6 +2492,7 @@ void PreferencesDialog::readGuiSettings(const QString & filePath)
_ui->doubleSpinBox_subtractFilteringRadius->setValue(settings.value("subtractFilteringRadius", _ui->doubleSpinBox_subtractFilteringRadius->value()).toDouble());
_ui->doubleSpinBox_subtractFilteringAngle->setValue(settings.value("subtractFilteringAngle", _ui->doubleSpinBox_subtractFilteringAngle->value()).toDouble());
_ui->doubleSpinBox_map_resolution->setValue(settings.value("gridUIResolution", _ui->doubleSpinBox_map_resolution->value()).toDouble());
_ui->checkBox_map_shown->setChecked(settings.value("gridMapShown", _ui->checkBox_map_shown->isChecked()).toBool());
_ui->doubleSpinBox_map_opacity->setValue(settings.value("gridMapOpacity", _ui->doubleSpinBox_map_opacity->value()).toDouble());
_ui->checkBox_elevation_shown->setCheckState((Qt::CheckState)settings.value("elevationMapShown", _ui->checkBox_elevation_shown->checkState()).toInt());
@@ -3033,6 +3036,7 @@ void PreferencesDialog::writeGuiSettings(const QString & filePath) const
settings.setValue("subtractFilteringRadius", _ui->doubleSpinBox_subtractFilteringRadius->value());
settings.setValue("subtractFilteringAngle", _ui->doubleSpinBox_subtractFilteringAngle->value());
settings.setValue("gridUIResolution", _ui->doubleSpinBox_map_resolution->value());
settings.setValue("gridMapShown", _ui->checkBox_map_shown->isChecked());
settings.setValue("gridMapOpacity", _ui->doubleSpinBox_map_opacity->value());
settings.setValue("elevationMapShown", _ui->checkBox_elevation_shown->checkState());
@@ -4964,6 +4968,7 @@ void PreferencesDialog::updateBasicParameter()
{
_ui->general_checkBox_activateRGBD->blockSignals(true);
_ui->general_checkBox_activateRGBD->setChecked(_ui->general_checkBox_activateRGBD_2->isChecked());
addParameter(_ui->general_checkBox_activateRGBD, _ui->general_checkBox_activateRGBD->isChecked());
_ui->general_checkBox_activateRGBD->blockSignals(false);
}
else if(sender() == _ui->general_checkBox_SLAM_mode)
@@ -4976,6 +4981,7 @@ void PreferencesDialog::updateBasicParameter()
{
_ui->general_checkBox_SLAM_mode->blockSignals(true);
_ui->general_checkBox_SLAM_mode->setChecked(_ui->general_checkBox_SLAM_mode_2->isChecked());
addParameter(_ui->general_checkBox_SLAM_mode, _ui->general_checkBox_SLAM_mode->isChecked());
_ui->general_checkBox_SLAM_mode->blockSignals(false);
}
else
@@ -5899,6 +5905,10 @@ double PreferencesDialog::getSubtractFilteringAngle() const
{
return _ui->doubleSpinBox_subtractFilteringAngle->value()*M_PI/180.0;
}
double PreferencesDialog::getGridUIResolution() const
{
return _ui->doubleSpinBox_map_resolution->value();
}
bool PreferencesDialog::getGridMapShown() const
{
return _ui->checkBox_map_shown->isChecked();

View File

@@ -584,10 +584,11 @@ void StatsToolBox::contextMenuEvent(QContextMenuEvent * event)
}
}
void StatsToolBox::getFiguresSetup(QList<int> & curvesPerFigure, QStringList & curveNames)
void StatsToolBox::getFiguresSetup(QList<int> & curvesPerFigure, QStringList & curveNames, QStringList & curveThresholds)
{
curvesPerFigure.clear();
curveNames.clear();
curveThresholds.clear();
for(QMap<QString, QWidget*>::iterator i=_figures.begin(); i!=_figures.end(); ++i)
{
QList<UPlot *> plots = i.value()->findChildren<UPlot *>();
@@ -596,6 +597,10 @@ void StatsToolBox::getFiguresSetup(QList<int> & curvesPerFigure, QStringList & c
QStringList names = plots[0]->curveNames();
curvesPerFigure.append(names.size());
curveNames.append(names);
for(int j=0; j<names.size(); ++j)
{
curveThresholds.append(plots[0]->isThreshold(names[j])?QString::number(plots[0]->getThresholdValue(names[j])):"NA");
}
}
else
{
@@ -628,6 +633,22 @@ void StatsToolBox::addCurve(const QString & name, bool newFigure, bool cacheOn)
ULOGGER_ERROR("Not supposed to be here...");
}
}
void StatsToolBox::addThreshold(const QString & name, qreal value)
{
QString plotName = _plotMenu->actions().last()->text();
QWidget * fig = _figures.value(plotName, (QWidget*)0);
if(fig)
{
UPlot * plot = fig->findChild<UPlot *>(plotName);
if(plot)
plot->addThreshold(name, value);
}
else
{
UERROR("There are no figures, cannot add threshold \"%s\"", name.toStdString().c_str());
}
}
void StatsToolBox::setWorkingDirectory(const QString & workingDirectory)
{

View File

@@ -95,7 +95,7 @@
<enum>QFrame::Raised</enum>
</property>
<property name="currentIndex">
<number>11</number>
<number>3</number>
</property>
<widget class="QWidget" name="page_22">
<layout class="QVBoxLayout" name="verticalLayout_29" stretch="0,0">
@@ -2414,7 +2414,33 @@ Show a yellow background when the number of odometry inliers goes under this thr
</item>
<item>
<layout class="QGridLayout" name="gridLayout_20" columnstretch="0,1">
<item row="1" column="0">
<item row="1" column="1">
<widget class="QLabel" name="label_map_shown">
<property name="text">
<string>Show in 3D map view.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="label_map_shown_2">
<property name="text">
<string>Resolution. Set 0 to use same value from Local Occupancy Grid panel.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QDoubleSpinBox" name="doubleSpinBox_map_opacity">
<property name="suffix">
<string/>
@@ -2433,27 +2459,7 @@ Show a yellow background when the number of odometry inliers goes under this thr
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="label_map_shown">
<property name="text">
<string>Show in 3D map view.</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="label_170">
<property name="text">
<string>Opacity.</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="0" column="0">
<item row="1" column="0">
<widget class="QCheckBox" name="checkBox_map_shown">
<property name="text">
<string/>
@@ -2463,17 +2469,7 @@ Show a yellow background when the number of odometry inliers goes under this thr
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLabel" name="label_show_elevation">
<property name="text">
<string>Show Elevation Map in 3D map view.</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="2" column="0">
<item row="3" column="0">
<widget class="QCheckBox" name="checkBox_elevation_shown">
<property name="toolTip">
<string>Partially checked: Height color map. Checked: RGB color map.</string>
@@ -2489,6 +2485,54 @@ Show a yellow background when the number of odometry inliers goes under this thr
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLabel" name="label_show_elevation">
<property name="text">
<string>Show Elevation Map in 3D map view.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLabel" name="label_170">
<property name="text">
<string>Opacity.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QDoubleSpinBox" name="doubleSpinBox_map_resolution">
<property name="suffix">
<string> m</string>
</property>
<property name="decimals">
<number>2</number>
</property>
<property name="minimum">
<double>0.000000000000000</double>
</property>
<property name="maximum">
<double>10.000000000000000</double>
</property>
<property name="singleStep">
<double>0.010000000000000</double>
</property>
<property name="value">
<double>0.000000000000000</double>
</property>
</widget>
</item>
</layout>
</item>
<item>

View File

@@ -1055,6 +1055,7 @@ UPlotCurveThreshold::UPlotCurveThreshold(const QString & name, qreal thesholdVal
UPlotCurve(name, parent),
_orientation(orientation)
{
_threshold = thesholdValue;
if(_orientation == Qt::Horizontal)
{
this->addValue(0, thesholdValue);
@@ -1080,6 +1081,7 @@ void UPlotCurveThreshold::setThreshold(qreal threshold)
if(_items.size() == 3)
{
UPlotItem * item = 0;
_threshold = threshold;
if(_orientation == Qt::Horizontal)
{
item = (UPlotItem*)_items.at(0);
@@ -2193,10 +2195,10 @@ bool UPlot::addCurve(UPlotCurve * curve, bool ownershipTransferred)
return false;
}
QStringList UPlot::curveNames()
QStringList UPlot::curveNames() const
{
QStringList names;
for(QList<UPlotCurve*>::iterator iter = _curves.begin(); iter!=_curves.end(); ++iter)
for(QList<UPlotCurve*>::const_iterator iter = _curves.constBegin(); iter!=_curves.constEnd(); ++iter)
{
if(*iter)
{
@@ -2206,9 +2208,38 @@ QStringList UPlot::curveNames()
return names;
}
bool UPlot::contains(const QString & curveName)
bool UPlot::isThreshold(const QString & curveName) const
{
for(QList<UPlotCurve*>::iterator iter = _curves.begin(); iter!=_curves.end(); ++iter)
for(QList<UPlotCurve*>::const_iterator iter = _curves.constBegin(); iter!=_curves.constEnd(); ++iter)
{
if(*iter && (*iter)->name().compare(curveName) == 0)
{
return qobject_cast<UPlotCurveThreshold*>(*iter) != 0;
}
}
return false;
}
double UPlot::getThresholdValue(const QString & curveName) const
{
for(QList<UPlotCurve*>::const_iterator iter = _curves.constBegin(); iter!=_curves.constEnd(); ++iter)
{
if(*iter && (*iter)->name().compare(curveName) == 0)
{
UPlotCurveThreshold* curve = qobject_cast<UPlotCurveThreshold*>(*iter);
if(curve)
{
return curve->getThreshold();
}
}
}
UERROR("Curve \"%s\" not found as theshold!", curveName.toStdString().c_str());
return 0;
}
bool UPlot::contains(const QString & curveName) const
{
for(QList<UPlotCurve*>::const_iterator iter = _curves.constBegin(); iter!=_curves.constEnd(); ++iter)
{
if(*iter && (*iter)->name().compare(curveName) == 0)
{