Merge branch 'master' of github.com:introlab/rtabmap into gtest

This commit is contained in:
matlabbe
2025-12-21 11:59:54 -08:00
129 changed files with 11607 additions and 5269 deletions
+18 -1
View File
@@ -86,6 +86,13 @@ AboutDialog::AboutDialog(QWidget * parent) :
_ui->label_sptorch->setText("No");
_ui->label_sptorch_license->setEnabled(false);
#endif
#if defined(RTABMAP_TORCH) && defined(RTABMAP_PYTHON)
_ui->label_sprpautrat->setText("Yes");
_ui->label_sprpautrat_license->setEnabled(true);
#else
_ui->label_sprpautrat->setText("No");
_ui->label_sprpautrat_license->setEnabled(false);
#endif
#ifdef RTABMAP_PYTHON
_ui->label_pymatcher->setText("Yes");
_ui->label_pymatcher_license->setEnabled(true);
@@ -179,6 +186,8 @@ AboutDialog::AboutDialog(QWidget * parent) :
_ui->label_depthai->setText(CameraDepthAI::available() ? "Yes" : "No");
_ui->label_depthai_license->setEnabled(CameraDepthAI::available());
_ui->label_xvsdk->setText(CameraSeerSense::available() ? "Yes" : "No");
_ui->label_orbbec_sdk->setText(CameraOrbbecSDK::available() ? "Yes" : "No");
_ui->label_orbbec_sdk_license->setEnabled(CameraOrbbecSDK::available());
_ui->label_toro->setText(Optimizer::isAvailable(Optimizer::kTypeTORO)?"Yes":"No");
_ui->label_toro_license->setEnabled(Optimizer::isAvailable(Optimizer::kTypeTORO)?true:false);
@@ -281,7 +290,7 @@ AboutDialog::AboutDialog(QWidget * parent) :
_ui->label_msckf_license->setEnabled(false);
#endif
#ifdef RTABMAP_VINS
#ifdef RTABMAP_VINS_FUSION
_ui->label_vins_fusion->setText("Yes");
_ui->label_vins_fusion_license->setEnabled(true);
#else
@@ -297,6 +306,14 @@ AboutDialog::AboutDialog(QWidget * parent) :
_ui->label_openvins_license->setEnabled(false);
#endif
#ifdef RTABMAP_CUVSLAM
_ui->label_cuvslam->setText("Yes");
_ui->label_cuvslam_license->setEnabled(true);
#else
_ui->label_cuvslam->setText("No");
_ui->label_cuvslam_license->setEnabled(false);
#endif
}
AboutDialog::~AboutDialog()
+7 -10
View File
@@ -97,11 +97,7 @@ IF(MSVC)
SET(SRC_FILES ${SRC_FILES} ${HEADERS})
ENDIF(MSVC)
SET(INCLUDE_DIRS
${CMAKE_CURRENT_SOURCE_DIR}/../include
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_BINARY_DIR} # for qt ui generated in binary dir
)
SET(INCLUDE_DIRS "")
IF(QT4_FOUND)
INCLUDE(${QT_USE_FILE})
@@ -172,9 +168,6 @@ IF(VTK_USE_QVTK)
SET(LIBRARIES ${LIBRARIES} ${QVTK_LIBRARY})
ENDIF(VTK_USE_QVTK)
#include files
INCLUDE_DIRECTORIES(${INCLUDE_DIRS})
add_definitions(${PCL_DEFINITIONS})
# Include presets
@@ -205,8 +198,12 @@ generate_export_header(rtabmap_gui
DEPRECATED_MACRO_NAME RTABMAP_DEPRECATED)
target_include_directories(rtabmap_gui PUBLIC
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../include;${CMAKE_CURRENT_BINARY_DIR}/include;${PUBLIC_INCLUDE_DIRS}>"
"$<INSTALL_INTERFACE:${INSTALL_INCLUDE_DIR};${PUBLIC_INCLUDE_DIRS}>")
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR};${CMAKE_CURRENT_SOURCE_DIR}/../include;${CMAKE_CURRENT_BINARY_DIR};${CMAKE_CURRENT_BINARY_DIR}/include>"
"$<INSTALL_INTERFACE:${INSTALL_INCLUDE_DIR}>")
target_include_directories(rtabmap_gui SYSTEM PUBLIC
"$<BUILD_INTERFACE:${PUBLIC_INCLUDE_DIRS};${INCLUDE_DIRS}>"
"$<INSTALL_INTERFACE:${PUBLIC_INCLUDE_DIRS}>")
TARGET_LINK_LIBRARIES(rtabmap_gui
PUBLIC
+9 -8
View File
@@ -250,17 +250,18 @@ void CalibrationDialog::resetSettings()
cv::Mat drawChessboard(int squareSize, int boardWidth, int boardHeight, int borderSize)
{
int imageWidth = squareSize*boardWidth + borderSize;
int imageHeight = squareSize*boardHeight + borderSize;
cv::Mat chessboard(imageWidth, imageHeight, CV_8UC1, 255);
unsigned char color = 0;
int imageWidth = squareSize*(boardWidth+1) + 2*borderSize;
int imageHeight = squareSize*(boardHeight+1) + 2*borderSize;
cv::Mat chessboard(imageHeight, imageWidth, CV_8UC1, 255);
unsigned char rowColor = 0;
for(int i=borderSize;i<imageHeight-borderSize; i=i+squareSize) {
color=~color;
unsigned char colColor = rowColor;
for(int j=borderSize;j<imageWidth-borderSize;j=j+squareSize) {
cv::Mat roi=chessboard(cv::Rect(i,j,squareSize,squareSize));
roi.setTo(color);
color=~color;
cv::Mat roi=chessboard(cv::Rect(j,i,squareSize,squareSize));
roi.setTo(colColor);
colColor=~colColor;
}
rowColor = ~rowColor;
}
return chessboard;
}
+7 -1
View File
@@ -54,7 +54,9 @@ CameraViewer::CameraViewer(QWidget * parent, const ParametersMap & parameters) :
cloudView_(new CloudViewer(this)),
processingImages_(false),
parameters_(parameters),
markerDetector_(0)
markerDetector_(0),
lastCapturePeriod_(0.0),
previousCaptureStamp_(0.0)
{
qRegisterMetaType<rtabmap::SensorData>("rtabmap::SensorData");
@@ -115,6 +117,7 @@ CameraViewer::CameraViewer(QWidget * parent, const ParametersMap & parameters) :
vlayout->addLayout(layout2);
this->setLayout(vlayout);
fpsTimer_.start();
}
CameraViewer::~CameraViewer()
@@ -180,6 +183,7 @@ void CameraViewer::showImage(const rtabmap::SensorData & data)
imageView_->setImageDepth(depthOrRight);
sizes.append(QString(" Depth=%1x%2").arg(depthOrRight.cols).arg(depthOrRight.rows));
}
sizes.append(QString(" FPS capture=%1 render=%2").arg(lastCapturePeriod_>0.0?(int)round(1.0/lastCapturePeriod_):0).arg((int)round(1.0/fpsTimer_.restart()*1000)));
imageSizeLabel_->setText(sizes);
if(!depthOrRight.empty() &&
@@ -308,6 +312,8 @@ bool CameraViewer::handleEvent(UEvent * event)
{
if(camEvent->data().isValid())
{
lastCapturePeriod_ = camEvent->data().stamp() - previousCaptureStamp_;
previousCaptureStamp_ = camEvent->data().stamp();
if(!processingImages_ && this->isVisible() && camEvent->data().isValid())
{
processingImages_ = true;
+118 -151
View File
@@ -27,6 +27,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "rtabmap/gui/CloudViewer.h"
#include "rtabmap/gui/CloudViewerCellPicker.h"
#include "rtabmap/gui/PointCloudColorHandlerIntensityField.h"
#include "rtabmap/gui/PointCloudColorHandlerMinMaxGenericField.h"
#include <rtabmap/core/Version.h>
#include <rtabmap/core/util3d_transforms.h>
@@ -150,6 +152,8 @@ CloudViewer::CloudViewer(QWidget *parent, CloudViewerInteractorStyle * style) :
_renderingRate(5.0),
_octomapActor(0),
_intensityAbsMax(100.0f),
_cloudColorRangeMin(0.0f),
_cloudColorRangeMax(0.0f),
_coordinateFrameScale(1.0)
{
this->setMinimumSize(200, 200);
@@ -337,6 +341,12 @@ void CloudViewer::createMenu()
_aSetIntensityRainbowColormap->setCheckable(true);
_aSetIntensityRainbowColormap->setChecked(false);
_aSetIntensityMaximum = new QAction("Set maximum absolute intensity...", this);
_aSetCloudColorRangeMin = new QAction("Set minimum color range...", this);
_aSetCloudColorRangeMax = new QAction("Set maximum color range...", this);
_aCloudColorRangeInverted = new QAction("Inverted color scale", this);
_aCloudColorRangeInverted->setCheckable(true);
_aCloudColorRangeInverted->setChecked(false);
_aClearCloudColorRanges = new QAction("Reset ranges", this);
_aSetBackgroundColor = new QAction("Set background color...", this);
_aSetRenderingRate = new QAction("Set rendering rate...", this);
_aSetEDLShading = new QAction("Eye-Dome Lighting Shading", this);
@@ -402,6 +412,12 @@ void CloudViewer::createMenu()
scanMenu->addAction(_aSetIntensityRainbowColormap);
scanMenu->addAction(_aSetIntensityMaximum);
QMenu * cloudMenu = new QMenu("XYZ color", this);
cloudMenu->addAction(_aSetCloudColorRangeMin);
cloudMenu->addAction(_aSetCloudColorRangeMax);
cloudMenu->addAction(_aCloudColorRangeInverted);
cloudMenu->addAction(_aClearCloudColorRanges);
//menus
_menu = new QMenu(this);
_menu->addMenu(cameraMenu);
@@ -412,6 +428,7 @@ void CloudViewer::createMenu()
_menu->addMenu(gridMenu);
_menu->addMenu(normalsMenu);
_menu->addMenu(scanMenu);
_menu->addMenu(cloudMenu);
_menu->addAction(_aSetBackgroundColor);
_menu->addAction(_aSetRenderingRate);
_menu->addAction(_aSetEDLShading);
@@ -465,6 +482,10 @@ void CloudViewer::saveSettings(QSettings & settings, const QString & group) cons
settings.setValue("intensity_rainbow_colormap", this->isIntensityRainbowColormap());
settings.setValue("intensity_max", (double)this->getIntensityMax());
settings.setValue("color_range_min", (double)this->getCloudColorRangeMin());
settings.setValue("color_range_max", (double)this->getCloudColorRangeMax());
settings.setValue("color_range_inverted", (double)this->isCloudColorRangeInverted());
settings.setValue("trajectory_shown", this->isTrajectoryShown());
settings.setValue("trajectory_size", this->getTrajectorySize());
@@ -516,6 +537,10 @@ void CloudViewer::loadSettings(QSettings & settings, const QString & group)
this->setIntensityRainbowColormap(settings.value("intensity_rainbow_colormap", this->isIntensityRainbowColormap()).toBool());
this->setIntensityMax(settings.value("intensity_max", this->getIntensityMax()).toFloat());
this->setCloudColorRangeMin(settings.value("color_range_min", this->getCloudColorRangeMin()).toFloat());
this->setCloudColorRangeMax(settings.value("color_range_max", this->getCloudColorRangeMax()).toFloat());
this->setCloudColorRangeInverted(settings.value("color_range_inverted", this->isCloudColorRangeInverted()).toBool());
this->setTrajectoryShown(settings.value("trajectory_shown", this->isTrajectoryShown()).toBool());
this->setTrajectorySize(settings.value("trajectory_size", this->getTrajectorySize()).toUInt());
@@ -606,153 +631,6 @@ bool CloudViewer::updateCloudPose(
return false;
}
class PointCloudColorHandlerIntensityField : public pcl::visualization::PointCloudColorHandler<pcl::PCLPointCloud2>
{
typedef pcl::visualization::PointCloudColorHandler<pcl::PCLPointCloud2>::PointCloud PointCloud;
typedef PointCloud::Ptr PointCloudPtr;
typedef PointCloud::ConstPtr PointCloudConstPtr;
public:
typedef boost::shared_ptr<PointCloudColorHandlerIntensityField > Ptr;
typedef boost::shared_ptr<const PointCloudColorHandlerIntensityField > ConstPtr;
/** \brief Constructor. */
PointCloudColorHandlerIntensityField (const PointCloudConstPtr &cloud, float maxAbsIntensity = 0.0f, int colorMap = 0) :
pcl::visualization::PointCloudColorHandler<pcl::PCLPointCloud2>::PointCloudColorHandler (cloud),
maxAbsIntensity_(maxAbsIntensity),
colormap_(colorMap)
{
field_idx_ = pcl::getFieldIndex (*cloud, "intensity");
if (field_idx_ != -1)
capable_ = true;
else
capable_ = false;
}
/** \brief Empty destructor */
virtual ~PointCloudColorHandlerIntensityField () {}
/** \brief Obtain the actual color for the input dataset as vtk scalars.
* \param[out] scalars the output scalars containing the color for the dataset
* \return true if the operation was successful (the handler is capable and
* the input cloud was given as a valid pointer), false otherwise
*/
#if PCL_VERSION_COMPARE(>, 1, 11, 1)
virtual vtkSmartPointer<vtkDataArray> getColor () const {
vtkSmartPointer<vtkDataArray> scalars;
if (!capable_ || !cloud_)
return scalars;
#else
virtual bool getColor (vtkSmartPointer<vtkDataArray> &scalars) const {
if (!capable_ || !cloud_)
return (false);
#endif
if (!scalars)
scalars = vtkSmartPointer<vtkUnsignedCharArray>::New ();
scalars->SetNumberOfComponents (3);
vtkIdType nr_points = cloud_->width * cloud_->height;
// Allocate enough memory to hold all colors
float * intensities = new float[nr_points];
float intensity;
size_t point_offset = cloud_->fields[field_idx_].offset;
size_t j = 0;
// If XYZ present, check if the points are invalid
int x_idx = pcl::getFieldIndex (*cloud_, "x");
if (x_idx != -1)
{
float x_data, y_data, z_data;
size_t x_point_offset = cloud_->fields[x_idx].offset;
// Color every point
for (vtkIdType cp = 0; cp < nr_points; ++cp,
point_offset += cloud_->point_step,
x_point_offset += cloud_->point_step)
{
// Copy the value at the specified field
memcpy (&intensity, &cloud_->data[point_offset], sizeof (float));
memcpy (&x_data, &cloud_->data[x_point_offset], sizeof (float));
memcpy (&y_data, &cloud_->data[x_point_offset + sizeof (float)], sizeof (float));
memcpy (&z_data, &cloud_->data[x_point_offset + 2 * sizeof (float)], sizeof (float));
if (!std::isfinite (x_data) || !std::isfinite (y_data) || !std::isfinite (z_data))
continue;
intensities[j++] = intensity;
}
}
// No XYZ data checks
else
{
// Color every point
for (vtkIdType cp = 0; cp < nr_points; ++cp, point_offset += cloud_->point_step)
{
// Copy the value at the specified field
memcpy (&intensity, &cloud_->data[point_offset], sizeof (float));
intensities[j++] = intensity;
}
}
if (j != 0)
{
// Allocate enough memory to hold all colors
unsigned char* colors = new unsigned char[j * 3];
float min, max;
if(maxAbsIntensity_>0.0f)
{
max = maxAbsIntensity_;
}
else
{
uMinMax(intensities, j, min, max);
}
for(size_t k=0; k<j; ++k)
{
colors[k*3+0] = colors[k*3+1] = colors[k*3+2] = max>0?(unsigned char)(std::min(intensities[k]/max*255.0f, 255.0f)):255;
if(colormap_ == 1)
{
colors[k*3+0] = 255;
colors[k*3+2] = 0;
}
else if(colormap_ == 2)
{
float r,g,b;
util2d::HSVtoRGB(&r, &g, &b, colors[k*3+0]*299.0f/255.0f, 1.0f, 1.0f);
colors[k*3+0] = r*255.0f;
colors[k*3+1] = g*255.0f;
colors[k*3+2] = b*255.0f;
}
}
reinterpret_cast<vtkUnsignedCharArray*>(&(*scalars))->SetNumberOfTuples (j);
reinterpret_cast<vtkUnsignedCharArray*>(&(*scalars))->SetArray (colors, j*3, 0, vtkUnsignedCharArray::VTK_DATA_ARRAY_DELETE);
}
else
reinterpret_cast<vtkUnsignedCharArray*>(&(*scalars))->SetNumberOfTuples (0);
//delete [] colors;
delete [] intensities;
#if PCL_VERSION_COMPARE(>, 1, 11, 1)
return scalars;
#else
return (true);
#endif
}
protected:
/** \brief Get the name of the class. */
virtual std::string
getName () const { return ("PointCloudColorHandlerIntensityField"); }
/** \brief Get the name of the field used. */
virtual std::string
getFieldName () const { return ("intensity"); }
private:
float maxAbsIntensity_;
int colormap_; // 0=grayscale, 1=redYellow, 2=RainbowHSV
};
bool CloudViewer::addCloud(
const std::string & id,
const pcl::PCLPointCloud2Ptr & binaryCloud,
@@ -799,11 +677,20 @@ bool CloudViewer::addCloud(
_visualizer->addPointCloud (binaryCloud, colorHandler, origin, orientation, id, viewport);
// x,y,z
colorHandler.reset (new pcl::visualization::PointCloudColorHandlerGenericField<pcl::PCLPointCloud2> (binaryCloud, "x"));
colorHandler.reset (new PointCloudColorHandlerMinMaxGenericField (binaryCloud, "x",
_cloudColorRangeMin==0.0f?std::numeric_limits<float>::lowest():_cloudColorRangeMin,
_cloudColorRangeMax==0.0f?std::numeric_limits<float>::max():_cloudColorRangeMax,
_aCloudColorRangeInverted->isChecked()));
_visualizer->addPointCloud (binaryCloud, colorHandler, origin, orientation, id, viewport);
colorHandler.reset (new pcl::visualization::PointCloudColorHandlerGenericField<pcl::PCLPointCloud2> (binaryCloud, "y"));
colorHandler.reset (new PointCloudColorHandlerMinMaxGenericField (binaryCloud, "y",
_cloudColorRangeMin==0.0f?std::numeric_limits<float>::lowest():_cloudColorRangeMin,
_cloudColorRangeMax==0.0f?std::numeric_limits<float>::max():_cloudColorRangeMax,
_aCloudColorRangeInverted->isChecked()));
_visualizer->addPointCloud (binaryCloud, colorHandler, origin, orientation, id, viewport);
colorHandler.reset (new pcl::visualization::PointCloudColorHandlerGenericField<pcl::PCLPointCloud2> (binaryCloud, "z"));
colorHandler.reset (new PointCloudColorHandlerMinMaxGenericField (binaryCloud, "z",
_cloudColorRangeMin==0.0f?std::numeric_limits<float>::lowest():_cloudColorRangeMin,
_cloudColorRangeMax==0.0f?std::numeric_limits<float>::max():_cloudColorRangeMax,
_aCloudColorRangeInverted->isChecked()));
_visualizer->addPointCloud (binaryCloud, colorHandler, origin, orientation, id, viewport);
if(rgb)
@@ -3285,6 +3172,12 @@ bool CloudViewer::getCloudVisibility(const std::string & id)
return false;
}
int CloudViewer::getCloudColorIndex(const std::string & id) const
{
return _visualizer->getColorHandlerIndex(id);
}
void CloudViewer::setCloudColorIndex(const std::string & id, int index)
{
if(index>0)
@@ -3293,6 +3186,26 @@ void CloudViewer::setCloudColorIndex(const std::string & id, int index)
}
}
double CloudViewer::getCloudOpacity(const std::string & id) const
{
double opacity = 1.0;
if(!_visualizer->getPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_OPACITY, opacity, id))
{
#if VTK_MAJOR_VERSION >= 7
pcl::visualization::ShapeActorMap::iterator am_it = _visualizer->getShapeActorMap()->find (id);
if (am_it != _visualizer->getShapeActorMap()->end ())
{
vtkActor* actor = vtkActor::SafeDownCast (am_it->second);
if(actor)
{
opacity = actor->GetProperty ()->GetOpacity ();
}
}
#endif
}
return opacity;
}
void CloudViewer::setCloudOpacity(const std::string & id, double opacity)
{
double lastOpacity;
@@ -3320,6 +3233,12 @@ void CloudViewer::setCloudOpacity(const std::string & id, double opacity)
#endif
}
int CloudViewer::getCloudPointSize(const std::string & id) const
{
double size = 1.0;
_visualizer->getPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, size, id);
return (int)size;
}
void CloudViewer::setCloudPointSize(const std::string & id, int size)
{
double lastSize;
@@ -3611,9 +3530,33 @@ void CloudViewer::setIntensityMax(float value)
}
else
{
UERROR("Cannot set normals scale < 0, value=%f", value);
UERROR("Cannot set intensity < 0, value=%f", value);
}
}
float CloudViewer::getCloudColorRangeMin() const
{
return _cloudColorRangeMin;
}
float CloudViewer::getCloudColorRangeMax() const
{
return _cloudColorRangeMax;
}
bool CloudViewer::isCloudColorRangeInverted() const
{
return _aCloudColorRangeInverted->isChecked();
}
void CloudViewer::setCloudColorRangeMin(float value)
{
_cloudColorRangeMin = value;
}
void CloudViewer::setCloudColorRangeMax(float value)
{
_cloudColorRangeMax = value;
}
void CloudViewer::setCloudColorRangeInverted(bool enabled)
{
_aCloudColorRangeInverted->setChecked(enabled);
}
void CloudViewer::buildPickingLocator(bool enable)
{
@@ -3984,6 +3927,30 @@ void CloudViewer::handleAction(QAction * a)
{
this->setIntensityRainbowColormap(_aSetIntensityRainbowColormap->isChecked());
}
else if(a == _aSetCloudColorRangeMin)
{
bool ok;
double value = QInputDialog::getDouble(this, tr("Set minimum axis color range"), tr("Range (0=auto)"), _cloudColorRangeMin, -99999, 99999, 2, &ok);
if(ok)
{
this->setCloudColorRangeMin(value);
}
}
else if(a == _aSetCloudColorRangeMax)
{
bool ok;
double value = QInputDialog::getDouble(this, tr("Set maximum axis color range"), tr("Range (0=auto)"), _cloudColorRangeMax, -99999, 99999, 2, &ok);
if(ok)
{
this->setCloudColorRangeMax(value);
}
}
else if(a == _aClearCloudColorRanges)
{
_cloudColorRangeMin = 0.0f;
_cloudColorRangeMax = 0.0f;
_aCloudColorRangeInverted->setChecked(false);
}
else if(a == _aSetBackgroundColor)
{
QColor color = this->getDefaultBackgroundColor();
+100 -13
View File
@@ -394,11 +394,10 @@ DatabaseViewer::DatabaseViewer(const QString & ini, QWidget * parent) :
connect(ui_->toolButton_constraint, SIGNAL(clicked(bool)), this, SLOT(editConstraint()));
connect(ui_->checkBox_enableForAll, SIGNAL(stateChanged(int)), this, SLOT(updateConstraintButtons()));
ui_->horizontalSlider_iterations->setTracking(false);
ui_->horizontalSlider_iterations->setTracking(true);
ui_->horizontalSlider_iterations->setEnabled(false);
ui_->spinBox_optimizationsFrom->setEnabled(false);
connect(ui_->horizontalSlider_iterations, SIGNAL(valueChanged(int)), this, SLOT(sliderIterationsValueChanged(int)));
connect(ui_->horizontalSlider_iterations, SIGNAL(sliderMoved(int)), this, SLOT(sliderIterationsValueChanged(int)));
connect(ui_->spinBox_optimizationsFrom, SIGNAL(editingFinished()), this, SLOT(updateGraphView()));
connect(ui_->comboBox_optimizationFlavor, SIGNAL(activated(int)), this, SLOT(updateGraphView()));
connect(ui_->checkBox_spanAllMaps, SIGNAL(stateChanged(int)), this, SLOT(updateGraphView()));
@@ -445,6 +444,7 @@ DatabaseViewer::DatabaseViewer(const QString & ini, QWidget * parent) :
connect(ui_->graphViewer, SIGNAL(configChanged()), this, SLOT(configModified()));
connect(ui_->graphicsView_A, SIGNAL(configChanged()), this, SLOT(configModified()));
connect(ui_->graphicsView_B, SIGNAL(configChanged()), this, SLOT(configModified()));
connect(cloudViewer_, SIGNAL(configChanged()), this, SLOT(configModified()));
connect(ui_->comboBox_logger_level, SIGNAL(currentIndexChanged(int)), this, SLOT(configModified()));
connect(ui_->actionVertical_Layout, SIGNAL(toggled(bool)), this, SLOT(configModified()));
connect(ui_->actionConcise_Layout, SIGNAL(toggled(bool)), this, SLOT(configModified()));
@@ -453,6 +453,7 @@ DatabaseViewer::DatabaseViewer(const QString & ini, QWidget * parent) :
connect(ui_->checkBox_alignScansCloudsWithGroundTruth, SIGNAL(stateChanged(int)), this, SLOT(updateGraphView()));
connect(ui_->checkBox_ignoreIntermediateNodes, SIGNAL(stateChanged(int)), this, SLOT(configModified()));
connect(ui_->checkBox_ignoreIntermediateNodes, SIGNAL(stateChanged(int)), this, SLOT(updateGraphView()));
connect(ui_->comboBox_env_sensor_graph_colormap, SIGNAL(currentIndexChanged(int)), this, SLOT(updateGraphView()));
connect(ui_->checkBox_timeStats, SIGNAL(stateChanged(int)), this, SLOT(configModified()));
connect(ui_->checkBox_timeStats, SIGNAL(stateChanged(int)), this, SLOT(updateStatistics()));
// Graph view
@@ -653,6 +654,9 @@ void DatabaseViewer::readSettings()
ui_->graphicsView_A->loadSettings(settings, "ImageViewA");
ui_->graphicsView_B->loadSettings(settings, "ImageViewB");
// CloudViewer
cloudViewer_->loadSettings(settings, "CloudViewer");
// ICP parameters
settings.beginGroup("icp");
ui_->spinBox_icp_decimation->setValue(settings.value("decimation", ui_->spinBox_icp_decimation->value()).toInt());
@@ -747,6 +751,9 @@ void DatabaseViewer::writeSettings()
ui_->graphicsView_A->saveSettings(settings, "ImageViewA");
ui_->graphicsView_B->saveSettings(settings, "ImageViewB");
// CloudViewer
cloudViewer_->saveSettings(settings, "CloudViewer");
// save ICP parameters
settings.beginGroup("icp");
settings.setValue("decimation", ui_->spinBox_icp_decimation->value());
@@ -1122,6 +1129,7 @@ bool DatabaseViewer::closeDatabase()
lastWmIds_.clear();
mapIds_.clear();
weights_.clear();
envSensors_.clear();
wmStates_.clear();
links_.clear();
linksAdded_.clear();
@@ -1799,6 +1807,7 @@ void DatabaseViewer::updateIds()
idToIndex_.clear();
mapIds_.clear();
weights_.clear();
envSensors_.clear();
wmStates_.clear();
odomPoses_.clear();
groundTruthPoses_.clear();
@@ -1905,6 +1914,7 @@ void DatabaseViewer::updateIds()
dbDriver_->getNodeInfo(ids_[i], p, mapId, w, l, s, g, v, gps, sensors);
mapIds_.insert(std::make_pair(ids_[i], mapId));
weights_.insert(std::make_pair(ids_[i], w));
envSensors_.insert(std::make_pair(ids_[i], sensors));
if(w>=0)
{
for(std::multimap<int, Link>::iterator iter=links.find(ids_[i]); iter!=links.end() && iter->first==ids_[i]; ++iter)
@@ -5138,6 +5148,15 @@ void DatabaseViewer::update(int value,
cloudViewer_->removeAllLines();
cloudViewer_->removeAllFrustums();
cloudViewer_->removeOccupancyGridMap();
std::map<std::string, std::pair<int, int> > colorIndexAndPointSizeMap;
for(auto iter=cloudViewer_->getAddedClouds().constBegin(); iter!=cloudViewer_->getAddedClouds().constEnd(); ++iter) {
if(uStrContains(iter.key(), "cloud") || uStrContains(iter.key(), "scan")) {
colorIndexAndPointSizeMap.insert(std::make_pair(iter.key(),
std::make_pair(
cloudViewer_->getCloudColorIndex(iter.key())+1,
cloudViewer_->getCloudPointSize(iter.key()))));
}
}
cloudViewer_->removeAllClouds();
cloudViewer_->removeOctomap();
cloudViewer_->removeElevationMap();
@@ -5195,6 +5214,10 @@ void DatabaseViewer::update(int value,
pcl::PointCloud<pcl::PointXYZ>::Ptr scan = util3d::laserScanToPointCloud(laserScanRaw, laserScanRaw.localTransform());
cloudViewer_->addCloud("scan", scan, pose, Qt::yellow);
}
if(colorIndexAndPointSizeMap.find("scan") != colorIndexAndPointSizeMap.end()) {
cloudViewer_->setCloudColorIndex("scan", colorIndexAndPointSizeMap.at("scan").first);
cloudViewer_->setCloudPointSize("scan", colorIndexAndPointSizeMap.at("scan").second);
}
}
// add RGB-D cloud
@@ -5281,6 +5304,10 @@ void DatabaseViewer::update(int value,
}
cloudViewer_->addCloud("cloud", cloudValidPoints, pose);
if(colorIndexAndPointSizeMap.find("cloud") != colorIndexAndPointSizeMap.end()) {
cloudViewer_->setCloudColorIndex("cloud", colorIndexAndPointSizeMap.at("cloud").first);
cloudViewer_->setCloudPointSize("cloud", colorIndexAndPointSizeMap.at("cloud").second);
}
}
else
{
@@ -5404,7 +5431,12 @@ void DatabaseViewer::update(int value,
}
if(ui_->checkBox_showCloud->isChecked())
{
cloudViewer_->addCloud(uFormat("cloud_%d", i), cloud, pose);
std::string cloudName = uFormat("cloud_%d", i);
cloudViewer_->addCloud(cloudName, cloud, pose);
if(colorIndexAndPointSizeMap.find(cloudName) != colorIndexAndPointSizeMap.end()) {
cloudViewer_->setCloudColorIndex(cloudName, colorIndexAndPointSizeMap.at(cloudName).first);
cloudViewer_->setCloudPointSize(cloudName, colorIndexAndPointSizeMap.at(cloudName).second);
}
}
}
}
@@ -5434,7 +5466,12 @@ void DatabaseViewer::update(int value,
cloud = util3d::voxelize(cloud, indices, ui_->doubleSpinBox_voxelSize->value());
}
cloudViewer_->addCloud(uFormat("cloud_%d", i), cloud, pose);
std::string cloudName = uFormat("cloud_%d", i);
cloudViewer_->addCloud(cloudName, cloud, pose);
if(colorIndexAndPointSizeMap.find(cloudName) != colorIndexAndPointSizeMap.end()) {
cloudViewer_->setCloudColorIndex(cloudName, colorIndexAndPointSizeMap.at(cloudName).first);
cloudViewer_->setCloudPointSize(cloudName, colorIndexAndPointSizeMap.at(cloudName).second);
}
}
}
}
@@ -7066,6 +7103,7 @@ void DatabaseViewer::updateConstraintButtons()
void DatabaseViewer::sliderIterationsValueChanged(int value)
{
UDEBUG("sender=%s value=%d currentValue = %d", sender()?sender()->objectName().toStdString().c_str():"NA", value, ui_->horizontalSlider_iterations->value());
if(dbDriver_ && value >=0 && value < (int)graphes_.size())
{
std::map<int, rtabmap::Transform> graph = uValueAt(graphes_, value);
@@ -7208,7 +7246,47 @@ void DatabaseViewer::sliderIterationsValueChanged(int value)
ui_->graphViewer->updateGTGraph(groundTruthPoses_);
ui_->graphViewer->updateGPSGraph(gpsPoses_, gpsValues_);
ui_->graphViewer->updateGraph(graph, graphLinks_, mapIds_, weights_);
if(ui_->checkBox_wmState->isEnabled() &&
if(ui_->comboBox_env_sensor_graph_colormap->currentIndex() != 0)
{
std::map<int, float> colors;
EnvSensor::Type curentType = (EnvSensor::Type)ui_->comboBox_env_sensor_graph_colormap->currentIndex();
for(std::map<int, rtabmap::Transform>::iterator iter=graph.begin(); iter!=graph.end(); ++iter)
{
auto jter = envSensors_.find(iter->first);
if(jter != envSensors_.end() && jter->second.find(curentType) != jter->second.end())
{
colors.insert(std::make_pair(iter->first, jter->second.at(curentType).value()));
}
}
std::string legend;
bool invertedColor = false;
unsigned char hueMax = 240; // blue
switch(curentType)
{
case EnvSensor::kWifiSignalStrength:
legend = "Wifi Signal Strength (dBm)";
invertedColor = true;
hueMax = 120; // green
break;
case EnvSensor::kAmbientTemperature:
legend = "Ambient Temperature (Celcius)";
break;
case EnvSensor::kAmbientAirPressure:
legend = "Ambient Air Pressure (hPa)";
break;
case EnvSensor::kAmbientLight:
legend = "Ambient Light / Illuminance (lx)";
break;
case EnvSensor::kAmbientRelativeHumidity:
legend = "Ambient Relative Humidity (%)";
break;
default:
break;
}
ui_->graphViewer->updateNodeColorByValue(legend, colors, 0.0f, 0.0f, invertedColor, 0, hueMax, 1);
UDEBUG("Updated node color based on env sensor %d", (int)curentType);
}
else if(ui_->checkBox_wmState->isEnabled() &&
ui_->checkBox_wmState->isChecked() &&
!lastWmIds_.empty())
{
@@ -7229,6 +7307,7 @@ void DatabaseViewer::sliderIterationsValueChanged(int value)
{
ui_->graphViewer->updateNodeColorByValue("In WM", colors, 1, false, 1);
}
UDEBUG("Updated node color based working memory state");
}
QGraphicsRectItem * rectScaleItem = 0;
ui_->graphViewer->clearMap();
@@ -7432,13 +7511,16 @@ void DatabaseViewer::sliderIterationsValueChanged(int value)
}
#endif
}
ui_->graphViewer->fitInView(ui_->graphViewer->scene()->itemsBoundingRect(), Qt::KeepAspectRatio);
if(rectScaleItem != 0)
{
ui_->graphViewer->fitInView(rectScaleItem, Qt::KeepAspectRatio);
ui_->graphViewer->scene()->removeItem(rectScaleItem);
delete rectScaleItem;
}
else {
ui_->graphViewer->fitInView(ui_->graphViewer->sceneRect(), Qt::KeepAspectRatio);
}
ui_->graphViewer->update();
ui_->label_iterations->setNum(value);
@@ -8327,7 +8409,7 @@ void DatabaseViewer::refineConstraint(int from, int to, Registration * reg, Regi
}
Transform toPoseInv = filteredScanPoses.at(currentLink.to()).inverse();
dbDriver_->loadNodeData(fromS, !silent, true, !silent, !silent);
dbDriver_->loadNodeData(*fromS, !silent, true, !silent, !silent);
fromS->sensorData().uncompressData();
LaserScan fromScan = fromS->sensorData().laserScanRaw();
int maxPoints = fromScan.size();
@@ -8473,8 +8555,8 @@ void DatabaseViewer::refineConstraint(int from, int to, Registration * reg, Regi
reextractVisualFeatures ||
!silent)
{
dbDriver_->loadNodeData(fromS, reextractVisualFeatures || !silent || (reg->isScanRequired() && ui_->checkBox_icp_from_depth->isChecked()), reg->isScanRequired() || !silent, reg->isUserDataRequired() || !silent, !silent);
dbDriver_->loadNodeData(toS, reextractVisualFeatures || !silent || (reg->isScanRequired() && ui_->checkBox_icp_from_depth->isChecked()), reg->isScanRequired() || !silent, reg->isUserDataRequired() || !silent, !silent);
dbDriver_->loadNodeData(*fromS, reextractVisualFeatures || !silent || (reg->isScanRequired() && ui_->checkBox_icp_from_depth->isChecked()), reg->isScanRequired() || !silent, reg->isUserDataRequired() || !silent, !silent);
dbDriver_->loadNodeData(*toS, reextractVisualFeatures || !silent || (reg->isScanRequired() && ui_->checkBox_icp_from_depth->isChecked()), reg->isScanRequired() || !silent, reg->isUserDataRequired() || !silent, !silent);
if(!silent)
{
@@ -8569,6 +8651,7 @@ void DatabaseViewer::refineConstraint(int from, int to, Registration * reg, Regi
if(!transform.isNull())
{
UASSERT(!info.covariance.empty());
if(!transform.isIdentity())
{
if(info.covariance.at<double>(0,0)<=0.0)
@@ -8762,9 +8845,9 @@ bool DatabaseViewer::addConstraint(int from, int to, Registration * reg, bool si
!silent)
{
// Add sensor data to generate features
dbDriver_->loadNodeData(fromS, reextractVisualFeatures || !silent || (reg->isScanRequired() && ui_->checkBox_icp_from_depth->isChecked()), reg->isScanRequired() || !silent, reg->isUserDataRequired() || !silent, !silent);
dbDriver_->loadNodeData(*fromS, reextractVisualFeatures || !silent || (reg->isScanRequired() && ui_->checkBox_icp_from_depth->isChecked()), reg->isScanRequired() || !silent, reg->isUserDataRequired() || !silent, !silent);
fromS->sensorData().uncompressData();
dbDriver_->loadNodeData(toS, reextractVisualFeatures || !silent || (reg->isScanRequired() && ui_->checkBox_icp_from_depth->isChecked()), reg->isScanRequired() || !silent, reg->isUserDataRequired() || !silent, !silent);
dbDriver_->loadNodeData(*toS, reextractVisualFeatures || !silent || (reg->isScanRequired() && ui_->checkBox_icp_from_depth->isChecked()), reg->isScanRequired() || !silent, reg->isUserDataRequired() || !silent, !silent);
toS->sensorData().uncompressData();
if(reextractVisualFeatures)
{
@@ -9311,14 +9394,18 @@ std::multimap<int, rtabmap::Link> DatabaseViewer::updateLinksWithModifications(
if(findIter!=linksRefined_.end())
{
links.insert(*findIter); // add the refined link
links.insert(std::make_pair(findIter->second.to(), findIter->second.inverse())); // return both ways
if(findIter->second.from() != findIter->second.to()) {
links.insert(std::make_pair(findIter->second.to(), findIter->second.inverse())); // return both ways
}
UDEBUG("Added refined link (%d->%d, %d)", findIter->second.from(), findIter->second.to(), findIter->second.type());
continue;
}
UDEBUG("Added link (%d->%d, %d)", iter->second.from(), iter->second.to(), iter->second.type());
links.insert(*iter);
links.insert(std::make_pair(iter->second.to(), iter->second.inverse())); // return both ways
if(iter->second.from() != iter->second.to()) {
links.insert(std::make_pair(iter->second.to(), iter->second.inverse())); // return both ways
}
}
return links;
+296 -209
View File
@@ -337,17 +337,37 @@ GraphViewer::GraphViewer(QWidget * parent) :
_gridCellSize(0.0f),
_localRadius(0),
_loopClosureOutlierThr(0),
_maxLinkLength(0.02f),
_minLinkLength(0.02f),
_orientationENU(false),
_mouseTracking(false),
_viewPlane(XY),
_ensureFrameVisible(true)
{
this->setScene(new QGraphicsScene(this));
this->setDragMode(QGraphicsView::ScrollHandDrag);
_workingDirectory = QDir::homePath();
this->scene()->clear();
setupGraphicsScene();
// Match by default scan colors from DatabaseViewer
_highlightedNodes.push_back(QPair<QColor, NodeItem*>(Qt::yellow, nullptr));
_highlightedNodes.push_back(QPair<QColor, NodeItem*>(Qt::magenta, nullptr));
this->restoreDefaults();
this->fitInView(this->sceneRect(), Qt::KeepAspectRatio);
}
GraphViewer::~GraphViewer()
{
}
void GraphViewer::setupGraphicsScene()
{
if(this->scene())
{
delete this->scene();
}
this->setScene(new QGraphicsScene(this));
_world = (QGraphicsItem *)this->scene()->addEllipse(QRectF(-0.0001,-0.0001,0.0001,0.0001));
_root = (QGraphicsItem *)this->scene()->addEllipse(QRectF(-0.0001,-0.0001,0.0001,0.0001));
_root->setParentItem(_world);
@@ -485,17 +505,6 @@ GraphViewer::GraphViewer(QWidget * parent) :
_odomCacheOverlay->setBrush(QBrush(QColor(255, 255, 255, 150)));
_odomCacheOverlay->setPen(QPen(Qt::NoPen));
// Match by default scan colors from DatabaseViewer
_highlightedNodes.push_back(QPair<QColor, NodeItem*>(Qt::yellow, nullptr));
_highlightedNodes.push_back(QPair<QColor, NodeItem*>(Qt::magenta, nullptr));
this->restoreDefaults();
this->fitInView(this->sceneRect(), Qt::KeepAspectRatio);
}
GraphViewer::~GraphViewer()
{
}
void GraphViewer::setWorldMapRotation(const float & theta)
@@ -510,18 +519,48 @@ void GraphViewer::updateGraph(const std::map<int, Transform> & poses,
const std::map<int, int> & weights,
const std::set<int> & odomCacheIds)
{
UTimer timer;
bool wasVisible = _graphRoot->isVisible();
_graphRoot->show();
bool wasEmpty = _nodeItems.size() == 0 && _linkItems.size() == 0;
UDEBUG("poses=%d constraints=%d", (int)poses.size(), (int)constraints.size());
//Hide nodes and links
for(QMap<int, NodeItem*>::iterator iter = _nodeItems.begin(); iter!=_nodeItems.end(); ++iter)
if(!_graphRoot->isVisible())
{
UDEBUG("Ignoring updating graph, the graph root is not visible.");
return;
}
UTimer timer;
bool wasEmpty = _nodeItems.size() == 0 && _linkItems.size() == 0 && _gridMap->pixmap().isNull();
UDEBUG("poses=%ld constraints=%ld mapIds=%ld weights=%ld", poses.size(), constraints.size(), mapIds.size(), weights.size());
for(QMultiMap<int, LinkItem*>::iterator iter = _linkItems.begin(); iter!=_linkItems.end(); ++iter)
{
iter.value()->hide();
}
UDEBUG("hidden %d links", _linkItems.size());
int created = 0;
int reused = 0;
int removed = 0;
QMap<int, NodeItem*>::iterator nter = _nodeItems.begin();
std::map<int, Transform>::const_iterator iter=_nodeVisible?poses.begin():poses.end();
while(nter!=_nodeItems.end() || iter!=poses.end())
{
if(nter!=_nodeItems.end() && (iter==poses.end() || nter.key() < iter->first || iter->second.isNull()))
{
// NodeItem is not in poses anymore, increase only _nodeItems iterator
for(int i=0; i<_highlightedNodes.size(); ++i)
{
if(_highlightedNodes[i].second && _highlightedNodes[i].second == nter.value())
{
_highlightedNodes[i].second = nullptr;
}
}
delete nter.value();
nter = _nodeItems.erase(nter);
++removed;
continue;
}
QColor color = _nodeColor;
bool isOdomCache = odomCacheIds.find(iter.key()) != odomCacheIds.end();
if(iter.key()<0)
bool isOdomCache = odomCacheIds.find(iter->first) != odomCacheIds.end();
if(iter->first<0)
{
color = QColor(255-color.red(), 255-color.green(), 255-color.blue());
}
@@ -529,51 +568,50 @@ void GraphViewer::updateGraph(const std::map<int, Transform> & poses,
{
color = _nodeOdomCacheColor;
}
iter.value()->hide();
iter.value()->setColor(color); // reset color
iter.value()->setToolTipInfo(QString());
iter.value()->setZValue(iter.key()<0?21:20);
}
for(QMultiMap<int, LinkItem*>::iterator iter = _linkItems.begin(); iter!=_linkItems.end(); ++iter)
{
iter.value()->hide();
}
for(std::map<int, Transform>::const_iterator iter=poses.begin(); iter!=poses.end(); ++iter)
{
if(!iter->second.isNull())
UASSERT(iter!=poses.end());
if(nter == _nodeItems.end() || nter.key() > iter->first)
{
QMap<int, NodeItem*>::iterator itemIter = _nodeItems.find(iter->first);
if(itemIter != _nodeItems.end())
{
itemIter.value()->setPose(iter->second, _viewPlane);
itemIter.value()->show();
}
else
{
// create node item
QColor color = _nodeColor;
bool isOdomCache = odomCacheIds.find(iter->first) != odomCacheIds.end();
if(iter->first<0)
{
color = QColor(255-color.red(), 255-color.green(), 255-color.blue());
}
else if(isOdomCache)
{
color = _nodeOdomCacheColor;
}
const Transform & pose = iter->second;
NodeItem * item = new NodeItem(iter->first, uContains(mapIds, iter->first)?mapIds.at(iter->first):-1, pose, _nodeRadius, uContains(weights, iter->first)?weights.at(iter->first):-1, _viewPlane, _linkWidth);
this->scene()->addItem(item);
item->setZValue(iter->first<0?21:20);
item->setColor(color);
item->setParentItem(_graphRoot);
item->show();
_nodeItems.insert(iter->first, item);
}
// NodeItem is not in poses, create a new one and increase poses iterator
const Transform & pose = iter->second;
NodeItem * item = new NodeItem(
iter->first,
uValue(mapIds, iter->first, -1),
pose,
_nodeRadius,
uValue(weights, iter->first, -1),
_viewPlane,
_linkWidth);
this->scene()->addItem(item);
item->setZValue(iter->first<0?21:20);
item->setColor(color);
item->setParentItem(_graphRoot);
item->show();
_nodeItems.insert(iter->first, item);
++iter;
++created;
}
else
{
// NodeItem exists for the pose, copy data and increase both iterators
UASSERT(iter->first == nter.key());
nter.value()->setColor(color); // reset color
nter.value()->setToolTipInfo(QString());
nter.value()->setZValue(iter->first<0?21:20);
nter.value()->setPose(iter->second, _viewPlane);
nter.value()->show();
++nter;
++iter;
++reused;
}
}
UDEBUG("Nodes created=%d, reused=%d removed=%d", created, reused, removed);
created = 0;
reused = 0;
removed = 0;
int removedSmallLinks = 0;
int ignoredSmallLinks = 0;
for(std::multimap<int, Link>::const_iterator iter=constraints.begin(); iter!=constraints.end(); ++iter)
{
// make the first id the smallest one
@@ -587,30 +625,28 @@ void GraphViewer::updateGraph(const std::map<int, Transform> & poses,
std::map<int, Transform>::const_iterator jterA = poses.find(idFrom);
std::map<int, Transform>::const_iterator jterB = poses.find(idTo);
LinkItem * linkItem = 0;
if(jterA != poses.end() && jterB != poses.end() &&
_nodeItems.contains(idFrom) && _nodeItems.contains(idTo))
if(jterA != poses.end() && jterB != poses.end())
{
const Transform & poseA = jterA->second;
const Transform & poseB = jterB->second;
QMultiMap<int, LinkItem*>::iterator itemIter = _linkItems.end();
if(_linkItems.contains(idFrom))
QMultiMap<int, LinkItem*>::iterator itemIter = _linkItems.find(idFrom);
bool alreadyAdded = false;
while(itemIter != _linkItems.end() && itemIter.key() == idFrom)
{
itemIter = _linkItems.find(idFrom);
bool alreadyAdded = false;
while(itemIter != _linkItems.end() && itemIter.key() == idFrom)
if(itemIter.value()->to() == idTo)
{
if(itemIter.value()->to() == idTo && itemIter.value()->isVisible())
{
if(itemIter.value()->isVisible()) {
alreadyAdded = true;
break;
} else {
linkItem = itemIter.value();
}
++itemIter;
}
if(alreadyAdded){
continue;
break;
}
++itemIter;
}
if(alreadyAdded){
continue;
}
bool interSessionClosure = false;
@@ -625,11 +661,15 @@ void GraphViewer::updateGraph(const std::map<int, Transform> & poses,
if(isLinkedToOdomCachePoses)
{
_nodeItems.value(idFrom)->setZValue(odomCacheIds.find(idFrom)!=odomCacheIds.end()?24:23);
_nodeItems.value(idTo)->setZValue(odomCacheIds.find(idTo)!=odomCacheIds.end()?24:23);
if(_nodeItems.contains(idFrom)) {
_nodeItems.value(idFrom)->setZValue(odomCacheIds.find(idFrom)!=odomCacheIds.end()?24:23);
}
if(_nodeItems.contains(idTo)) {
_nodeItems.value(idTo)->setZValue(odomCacheIds.find(idTo)!=odomCacheIds.end()?24:23);
}
}
if(poseA.getDistance(poseB) > _maxLinkLength)
if(poseA.getDistance(poseB) > _minLinkLength)
{
if(linkItem == 0)
{
@@ -642,14 +682,24 @@ void GraphViewer::updateGraph(const std::map<int, Transform> & poses,
this->scene()->addItem(linkItem);
linkItem->setParentItem(_graphRoot);
_linkItems.insert(idFrom, linkItem);
++created;
}
else {
linkItem->setPoses(poseA, poseB, _viewPlane);
linkItem->show();
++reused;
}
}
else if(linkItem && itemIter != _linkItems.end())
else if(linkItem)
{
// erase small links
_linkItems.erase(itemIter);
delete linkItem;
linkItem = 0;
++removedSmallLinks;
}
else {
++ignoredSmallLinks;
}
if(linkItem)
@@ -730,71 +780,53 @@ void GraphViewer::updateGraph(const std::map<int, Transform> & poses,
}
}
}
UDEBUG("Links created=%d, reused=%d, small links: removed=%d ignored=%d", created, reused, removedSmallLinks, ignoredSmallLinks);
//remove not used nodes and links
for(QMap<int, NodeItem*>::iterator iter = _nodeItems.begin(); iter!=_nodeItems.end();)
{
if(!iter.value()->isVisible())
{
for(int i=0; i<_highlightedNodes.size(); ++i)
{
if(_highlightedNodes[i].second && _highlightedNodes[i].second == iter.value())
{
_highlightedNodes[i].second = nullptr;
}
}
delete iter.value();
iter = _nodeItems.erase(iter);
}
else
{
iter.value()->setVisible(_nodeVisible);
++iter;
}
}
removed = 0;
int visible = 0;
for(QMultiMap<int, LinkItem*>::iterator iter = _linkItems.begin(); iter!=_linkItems.end();)
{
if(!iter.value()->isVisible())
{
delete iter.value();
iter = _linkItems.erase(iter);
++removed;
}
else
{
++iter;
++visible;
}
}
UDEBUG("Links removed=%d, visible=%d", removed, visible);
if(_nodeItems.size())
{
(--_nodeItems.end()).value()->setColor(_nodeOdomCacheColor);
}
this->scene()->setSceneRect(this->scene()->itemsBoundingRect()); // Re-shrink the scene to it's bounding contents
QRectF rect = this->scene()->sceneRect();
if(!odomCacheIds.empty())
_odomCacheOverlay->setRect(this->scene()->itemsBoundingRect());
_odomCacheOverlay->setRect(rect);
else
_odomCacheOverlay->setRect(0, 0, 0, 0);
if(wasEmpty)
{
QRectF rect = this->scene()->itemsBoundingRect();
this->fitInView(rect.adjusted(-rect.width()/2.0f, -rect.height()/2.0f, rect.width()/2.0f, rect.height()/2.0f), Qt::KeepAspectRatio);
}
_graphRoot->setVisible(wasVisible);
UDEBUG("_nodeItems=%d, _linkItems=%d, timer=%fs", _nodeItems.size(), _linkItems.size(), timer.ticks());
}
void GraphViewer::updateGTGraph(const std::map<int, Transform> & poses)
{
if(!_gtGraphRoot->isVisible())
{
UDEBUG("Ignoring updating gt graph, the graph root is not visible.");
return;
}
UTimer timer;
bool wasVisible = _gtGraphRoot->isVisible();
_gtGraphRoot->show();
bool wasEmpty = _gtNodeItems.size() == 0 && _gtLinkItems.size() == 0;
UDEBUG("poses=%d", (int)poses.size());
//Hide nodes and links
for(QMap<int, NodeItem*>::iterator iter = _gtNodeItems.begin(); iter!=_gtNodeItems.end(); ++iter)
@@ -811,23 +843,26 @@ void GraphViewer::updateGTGraph(const std::map<int, Transform> & poses)
{
if(!iter->second.isNull())
{
QMap<int, NodeItem*>::iterator itemIter = _gtNodeItems.find(iter->first);
if(itemIter != _gtNodeItems.end())
if(_nodeVisible)
{
itemIter.value()->setPose(iter->second, _viewPlane);
itemIter.value()->show();
}
else
{
// create node item
const Transform & pose = iter->second;
NodeItem * item = new NodeItem(iter->first, -1, pose, _nodeRadius, -1, _viewPlane, _linkWidth);
this->scene()->addItem(item);
item->setZValue(20);
item->setColor(_gtPathColor);
item->setParentItem(_gtGraphRoot);
item->setVisible(_nodeVisible);
_gtNodeItems.insert(iter->first, item);
QMap<int, NodeItem*>::iterator itemIter = _gtNodeItems.find(iter->first);
if(itemIter != _gtNodeItems.end())
{
itemIter.value()->setPose(iter->second, _viewPlane);
itemIter.value()->show();
}
else
{
// create node item
const Transform & pose = iter->second;
NodeItem * item = new NodeItem(iter->first, -1, pose, _nodeRadius, -1, _viewPlane, _linkWidth);
this->scene()->addItem(item);
item->setZValue(20);
item->setColor(_gtPathColor);
item->setParentItem(_gtGraphRoot);
item->setVisible(_nodeVisible);
_gtNodeItems.insert(iter->first, item);
}
}
if(iter!=poses.begin())
@@ -913,20 +948,6 @@ void GraphViewer::updateGTGraph(const std::map<int, Transform> & poses)
++iter;
}
}
if(_gtNodeItems.size() || _gtLinkItems.size())
{
this->scene()->setSceneRect(this->scene()->itemsBoundingRect()); // Re-shrink the scene to it's bounding contents
if(wasEmpty)
{
QRectF rect = this->scene()->itemsBoundingRect();
this->fitInView(rect.adjusted(-rect.width()/2.0f, -rect.height()/2.0f, rect.width()/2.0f, rect.height()/2.0f), Qt::KeepAspectRatio);
}
}
_gtGraphRoot->setVisible(wasVisible);
UDEBUG("_gtNodeItems=%d, _gtLinkItems=%d timer=%fs", _gtNodeItems.size(), _gtLinkItems.size(), timer.ticks());
}
@@ -934,10 +955,11 @@ void GraphViewer::updateGPSGraph(
const std::map<int, Transform> & poses,
const std::map<int, GPS> & gpsValues)
{
if(!_gpsGraphRoot->isVisible()) {
UDEBUG("Ignoring updating gps graph, the graph root is not visible.");
return;
}
UTimer timer;
bool wasVisible = _gpsGraphRoot->isVisible();
_gpsGraphRoot->show();
bool wasEmpty = _gpsNodeItems.size() == 0 && _gpsNodeItems.size() == 0;
UDEBUG("poses=%d", (int)poses.size());
//Hide nodes and links
for(QMap<int, NodeItem*>::iterator iter = _gpsNodeItems.begin(); iter!=_gpsNodeItems.end(); ++iter)
@@ -954,24 +976,27 @@ void GraphViewer::updateGPSGraph(
{
if(!iter->second.isNull())
{
QMap<int, NodeItem*>::iterator itemIter = _gpsNodeItems.find(iter->first);
if(itemIter != _gpsNodeItems.end())
if(_nodeVisible)
{
itemIter.value()->setPose(iter->second, _viewPlane);
itemIter.value()->show();
}
else
{
// create node item
const Transform & pose = iter->second;
UASSERT(gpsValues.find(iter->first) != gpsValues.end());
NodeItem * item = new NodeGPSItem(iter->first, -1, pose, _nodeRadius, gpsValues.at(iter->first), _viewPlane, _linkWidth);
this->scene()->addItem(item);
item->setZValue(20);
item->setColor(_gpsPathColor);
item->setParentItem(_gpsGraphRoot);
item->setVisible(_nodeVisible);
_gpsNodeItems.insert(iter->first, item);
QMap<int, NodeItem*>::iterator itemIter = _gpsNodeItems.find(iter->first);
if(itemIter != _gpsNodeItems.end())
{
itemIter.value()->setPose(iter->second, _viewPlane);
itemIter.value()->show();
}
else
{
// create node item
const Transform & pose = iter->second;
UASSERT(gpsValues.find(iter->first) != gpsValues.end());
NodeItem * item = new NodeGPSItem(iter->first, -1, pose, _nodeRadius, gpsValues.at(iter->first), _viewPlane, _linkWidth);
this->scene()->addItem(item);
item->setZValue(20);
item->setColor(_gpsPathColor);
item->setParentItem(_gpsGraphRoot);
item->setVisible(_nodeVisible);
_gpsNodeItems.insert(iter->first, item);
}
}
if(iter!=poses.begin())
@@ -1043,20 +1068,6 @@ void GraphViewer::updateGPSGraph(
++iter;
}
}
if(_gpsNodeItems.size() || _gpsLinkItems.size())
{
this->scene()->setSceneRect(this->scene()->itemsBoundingRect()); // Re-shrink the scene to it's bounding contents
if(wasEmpty)
{
QRectF rect = this->scene()->itemsBoundingRect();
this->fitInView(rect.adjusted(-rect.width()/2.0f, -rect.height()/2.0f, rect.width()/2.0f, rect.height()/2.0f), Qt::KeepAspectRatio);
}
}
_gpsGraphRoot->setVisible(wasVisible);
UDEBUG("_gpsNodeItems=%d, _gpsLinkItems=%d timer=%fs", _gpsNodeItems.size(), _gpsLinkItems.size(), timer.ticks());
}
@@ -1085,6 +1096,7 @@ void GraphViewer::updateMap(const cv::Mat & map8U, float resolution, float xMin,
UASSERT(map8U.empty() || (!map8U.empty() && resolution > 0.0f));
if(!map8U.empty())
{
bool wasEmpty = _nodeItems.size() <= 1 && _linkItems.size() == 0 && _gridMap->pixmap().isNull();
_gridCellSize = resolution;
QImage image = uCvMat2QImage(map8U, false);
_gridMap->resetTransform();
@@ -1092,8 +1104,11 @@ void GraphViewer::updateMap(const cv::Mat & map8U, float resolution, float xMin,
_gridMap->setRotation(90);
_gridMap->setPixmap(QPixmap::fromImage(image));
_gridMap->setPos(-yMin*100.0f, -xMin*100.0f);
// Re-shrink the scene to it's bounding contents
this->scene()->setSceneRect(this->scene()->itemsBoundingRect());
if(wasEmpty)
{
this->fitInView(this->scene()->sceneRect(), Qt::KeepAspectRatio);
}
}
else
{
@@ -1134,6 +1149,66 @@ void GraphViewer::updateNodeColorByValue(const std::string & valueName, const st
}
}
void GraphViewer::updateNodeColorByValue(
const std::string & valueName,
const std::map<int, float> & values,
float min,
float max,
bool invertedColorScale,
unsigned short hueMin,
unsigned short hueMax,
int zValueOffset)
{
hueMax = hueMax > 360 ? 360 : hueMax;
//find min/max
if(min >= max)
{
bool firstValueSet = false;
for(std::map<int, float>::const_iterator iter = values.begin(); iter!=values.end(); ++iter)
{
if(iter->first > 0)
{
if(!firstValueSet) {
min = max = iter->second;
firstValueSet = true;
}
else if(iter->second>max)
{
max = iter->second;
}
else if(iter->second<min)
{
min = iter->second;
}
}
}
}
if(min < max && hueMin < hueMax)
{
float range = max - min;
float hueRange = float(hueMax - hueMin);
for(QMap<int, NodeItem*>::iterator iter = _nodeItems.begin(); iter!=_nodeItems.end(); ++iter)
{
std::map<int,float>::const_iterator jter = values.find(iter.key());
if(jter != values.end())
{
float v = jter->second;
v = std::min(v, max);
v = std::max(v, min);
iter.value()->setColor(QColor::fromHsvF(( invertedColorScale ? (v-min)/range : 1-(v-min)/range )*hueRange/360.0f + hueMin/360.0f, 1, 1, 1), valueName.c_str(), jter->second);
iter.value()->setZValue(iter.value()->zValue()+zValueOffset);
}
}
}
else if(min >= max) {
UWARN("min (%f) is not less than max (%f), cannot change color of the graph.", min, max);
}
else if(hueMin >= hueMax) {
UWARN("Hue min (%d) is not less than hue max (%d), cannot change color of the graph. The hue values should be set between 0 (red) and 360(pink).", (int)hueMin, (int)hueMax);
}
}
void GraphViewer::setGlobalPath(const std::vector<std::pair<int, Transform> > & globalPath)
{
UDEBUG("Set global path size=%d", (int)globalPath.size());
@@ -1200,6 +1275,11 @@ void GraphViewer::setNodeInfo(int id, const QString & info)
void GraphViewer::setLocalRadius(float radius)
{
_localRadius->setRect(-radius*100, -radius*100, radius*200, radius*200);
if(_nodeItems.empty() && _linkItems.empty() && _gridMap->pixmap().isNull())
{
QRectF rect = this->scene()->sceneRect();
this->fitInView(rect.adjusted(-rect.width()/2.0f, -rect.height()/2.0f, rect.width()/2.0f, rect.height()/2.0f), Qt::KeepAspectRatio);
}
}
void GraphViewer::updateLocalPath(const std::vector<int> & localPath)
@@ -1324,14 +1404,17 @@ void GraphViewer::clearGraph()
_worldMapRotation = 0.0f;
_referential->resetTransform();
_localRadius->resetTransform();
this->scene()->setSceneRect(this->scene()->itemsBoundingRect()); // Re-shrink the scene to it's bounding contents
}
void GraphViewer::clearMap()
{
_gridMap->setPixmap(QPixmap());
_gridCellSize = 0.0f;
this->scene()->setSceneRect(this->scene()->itemsBoundingRect()); // Re-shrink the scene to it's bounding contents
if(_gridMap->pixmap().isNull())
{
// there is no grid map, just return
return;
}
_gridMap->setPixmap(QPixmap());
}
void GraphViewer::clearPosterior()
@@ -1351,6 +1434,14 @@ void GraphViewer::clearAll()
{
clearMap();
clearGraph();
// The only way to re-shrink the dynamic scene rect is to re-create the QGraphicsScene.
QSettings tmp;
saveSettings(tmp);
QRectF localRadiusRectF = _localRadius->rect();
setupGraphicsScene();
loadSettings(tmp); // restore previous state
_localRadius->setRect(localRadiusRectF);
}
void GraphViewer::saveSettings(QSettings & settings, const QString & group) const
@@ -1387,8 +1478,9 @@ void GraphViewer::saveSettings(QSettings & settings, const QString & group) cons
settings.setValue("referential_visible", this->isReferentialVisible());
settings.setValue("local_radius_visible", this->isLocalRadiusVisible());
settings.setValue("loop_closure_outlier_thr", this->getLoopClosureOutlierThr());
settings.setValue("max_link_length", this->getMaxLinkLength());
settings.setValue("min_link_length", this->getMinLinkLength());
settings.setValue("graph_visible", this->isGraphVisible());
settings.setValue("node_visible", this->isNodeVisible());
settings.setValue("global_path_visible", this->isGlobalPathVisible());
settings.setValue("local_path_visible", this->isLocalPathVisible());
settings.setValue("gt_graph_visible", this->isGtGraphVisible());
@@ -1437,8 +1529,9 @@ void GraphViewer::loadSettings(QSettings & settings, const QString & group)
this->setLocalRadiusVisible(settings.value("local_radius_visible", this->isLocalRadiusVisible()).toBool());
this->setIntraInterSessionColorsEnabled(settings.value("intra_inter_session_colors_enabled", this->isIntraInterSessionColorsEnabled()).toBool());
this->setLoopClosureOutlierThr(settings.value("loop_closure_outlier_thr", this->getLoopClosureOutlierThr()).toDouble());
this->setMaxLinkLength(settings.value("max_link_length", this->getMaxLinkLength()).toDouble());
this->setMinLinkLength(settings.value("min_link_length", this->getMinLinkLength()).toDouble());
this->setGraphVisible(settings.value("graph_visible", this->isGraphVisible()).toBool());
this->setNodeVisible(settings.value("node_visible", this->isNodeVisible()).toBool());
this->setGlobalPathVisible(settings.value("global_path_visible", this->isGlobalPathVisible()).toBool());
this->setLocalPathVisible(settings.value("local_path_visible", this->isLocalPathVisible()).toBool());
this->setGtGraphVisible(settings.value("gt_graph_visible", this->isGtGraphVisible()).toBool());
@@ -1473,6 +1566,10 @@ bool GraphViewer::isGraphVisible() const
{
return _graphRoot->isVisible();
}
bool GraphViewer::isNodeVisible() const
{
return _nodeVisible;
}
bool GraphViewer::isGlobalPathVisible() const
{
return _globalPathRoot->isVisible();
@@ -1795,9 +1892,9 @@ void GraphViewer::setLoopClosureOutlierThr(float value)
{
_loopClosureOutlierThr = value;
}
void GraphViewer::setMaxLinkLength(float value)
void GraphViewer::setMinLinkLength(float value)
{
_maxLinkLength = value;
_minLinkLength = value;
}
void GraphViewer::setGraphVisible(bool visible)
{
@@ -1838,10 +1935,6 @@ void GraphViewer::setOrientationENU(bool enabled)
QTransform t;
t.rotateRadians(_worldMapRotation);
_root->setTransform(t);
if(_nodeItems.size() || _linkItems.size())
{
this->scene()->setSceneRect(this->scene()->itemsBoundingRect()); // Re-shrink the scene to it's bounding contents
}
}
void GraphViewer::setViewPlane(ViewPlane plane)
@@ -1868,11 +1961,6 @@ void GraphViewer::setViewPlane(ViewPlane plane)
_referentialXY->setVisible(plane==XY);
_referentialXZ->setVisible(plane==XZ);
_referentialYZ->setVisible(plane==YZ);
if(_nodeItems.size() || _linkItems.size())
{
this->scene()->setSceneRect(this->scene()->itemsBoundingRect()); // Re-shrink the scene to it's bounding contents
}
}
void GraphViewer::setEnsureFrameVisible(bool visible)
{
@@ -2063,7 +2151,7 @@ void GraphViewer::contextMenuEvent(QContextMenuEvent * event)
menu.addSeparator();
QAction * aSetNodeSize = menu.addAction(tr("Set node radius..."));
QAction * aSetLinkSize = menu.addAction(tr("Set link width..."));
QAction * aChangeMaxLinkLength = menu.addAction(tr("Set maximum link length..."));
QAction * aChangeMinLinkLength = menu.addAction(tr("Set minimum link length..."));
menu.addSeparator();
QAction * aEnsureFrameVisible;
QAction * aShowHideGridMap;
@@ -2181,12 +2269,12 @@ void GraphViewer::contextMenuEvent(QContextMenuEvent * event)
aMouseTracking->setCheckable(true);
aMouseTracking->setChecked(_mouseTracking);
aMouseTracking->setEnabled(_viewPlane == XY);
aShowHideGraph->setEnabled(_nodeItems.size() && _viewPlane == XY);
aShowHideGraphNodes->setEnabled(_nodeItems.size() && _graphRoot->isVisible());
aShowHideGraph->setEnabled(_viewPlane == XY);
aShowHideGraphNodes->setEnabled(_graphRoot->isVisible());
aShowHideGlobalPath->setEnabled(_globalPathLinkItems.size());
aShowHideLocalPath->setEnabled(_localPathLinkItems.size());
aShowHideGtGraph->setEnabled(_gtNodeItems.size());
aShowHideGPSGraph->setEnabled(_gpsNodeItems.size());
aShowHideGtGraph->setEnabled(_gtGraphRoot->isVisible());
aShowHideGPSGraph->setEnabled(_gpsGraphRoot->isVisible());
aShowHideOdomCacheOverlay->setEnabled(_odomCacheOverlay->rect().width()>0);
QMenu * viewPlaneMenu = menu.addMenu("View Plane...");
@@ -2303,8 +2391,7 @@ void GraphViewer::contextMenuEvent(QContextMenuEvent * event)
//reset scale
_root->setScale(1.0f);
this->scene()->setSceneRect(this->scene()->itemsBoundingRect()); // Re-shrink the scene to it's bounding contents
this->scene()->setSceneRect(QRectF());
QDesktopServices::openUrl(QUrl::fromLocalFile(filePath));
}
@@ -2366,13 +2453,13 @@ void GraphViewer::contextMenuEvent(QContextMenuEvent * event)
setLoopClosureOutlierThr(value);
}
}
else if(r == aChangeMaxLinkLength)
else if(r == aChangeMinLinkLength)
{
bool ok;
double value = QInputDialog::getDouble(this, tr("Maximum link length to be shown"), tr("Value (m)"), _maxLinkLength, 0.0, 1000.0, 3, &ok);
double value = QInputDialog::getDouble(this, tr("Minimum link length to be shown"), tr("Value (m)"), _minLinkLength, 0.0, 1000.0, 3, &ok);
if(ok)
{
setMaxLinkLength(value);
setMinLinkLength(value);
}
}
else if(r == aChangeNodeColor ||
+1
View File
@@ -44,6 +44,7 @@
<file>images/oakd.png</file>
<file>images/oakd_lite.png</file>
<file>images/astra.png</file>
<file>images/astra2.png</file>
<file>images/oakdpro.png</file>
<file>images/seer_sense_DS80.png</file>
</qresource>
+92 -11
View File
@@ -266,14 +266,16 @@ ImageView::ImageView(QWidget * parent) :
_colorMapBlueToRed = colorMap->addAction(tr("Blue to red"));
_colorMapBlueToRed->setCheckable(true);
_colorMapBlueToRed->setChecked(false);
_colorMapMinRange = colorMap->addAction(tr("Min Range..."));
_colorMapMaxRange = colorMap->addAction(tr("Max Range..."));
_colorMapInCameraFrame = colorMap->addAction(tr("Camera Frame"));
_colorMapInCameraFrame->setCheckable(true);
_colorMapInCameraFrame->setChecked(true);
_colorMapMinRange = colorMap->addAction(tr("Min Z..."));
_colorMapMaxRange = colorMap->addAction(tr("Max Z..."));
group = new QActionGroup(this);
group->addAction(_colorMapWhiteToBlack);
group->addAction(_colorMapBlackToWhite);
group->addAction(_colorMapRedToBlue);
group->addAction(_colorMapBlueToRed);
group->addAction(_colorMapMaxRange);
_mouseTracking = _menu->addAction(tr("Show pixel depth"));
_mouseTracking->setCheckable(true);
_mouseTracking->setChecked(false);
@@ -311,6 +313,7 @@ void ImageView::saveSettings(QSettings & settings, const QString & group) const
settings.setValue("graphics_view_scale", this->isGraphicsViewScaled());
settings.setValue("graphics_view_scale_to_height", this->isGraphicsViewScaledToHeight());
settings.setValue("colormap", _colorMapWhiteToBlack->isChecked()?0:_colorMapBlackToWhite->isChecked()?1:_colorMapRedToBlue->isChecked()?2:3);
settings.setValue("colormap_camera_frame", this->isDepthColorMapInCameraFrame());
settings.setValue("colormap_min_range", this->getDepthColorMapMinRange());
settings.setValue("colormap_max_range", this->getDepthColorMapMaxRange());
if(!group.isEmpty())
@@ -345,6 +348,7 @@ void ImageView::loadSettings(QSettings & settings, const QString & group)
_colorMapBlackToWhite->setChecked(colorMap==1);
_colorMapRedToBlue->setChecked(colorMap==2);
_colorMapBlueToRed->setChecked(colorMap==3);
this->setDepthColorMapInCameraFrame(settings.value("colormap_camera_frame", this->isDepthColorMapInCameraFrame()).toBool());
this->setDepthColorMapRange(
settings.value("colormap_min_range", this->getDepthColorMapMinRange()).toFloat(),
settings.value("colormap_max_range", settings.value("colormap_range" /*backward compatibility*/, this->getDepthColorMapMaxRange())).toFloat());
@@ -763,13 +767,20 @@ void ImageView::setBackgroundColor(const QColor & color)
}
}
void ImageView::setDepthColorMapInCameraFrame(bool enabled) {
_colorMapInCameraFrame->setChecked(enabled);
}
bool ImageView::isDepthColorMapInCameraFrame() const {
return _colorMapInCameraFrame->isChecked();
}
void ImageView::setDepthColorMapRange(float min, float max)
{
_depthColorMapMinRange = min;
_depthColorMapMaxRange = max;
}
void ImageView::computeScaleOffsets(const QRect & targetRect, float & scale, float & offsetX, float & offsetY) const
{
scale = 1.0f;
@@ -1054,10 +1065,17 @@ void ImageView::contextMenuEvent(QContextMenuEvent * e)
}
Q_EMIT configChanged();
}
else if(action == _colorMapInCameraFrame)
{
if(!_imageDepthCv.empty()) {
this->setImageDepth(_imageDepthCv, _imageDepthConfidenceCv);
}
Q_EMIT configChanged();
}
else if(action == _colorMapMinRange)
{
bool ok = false;
double value = QInputDialog::getDouble(this, tr("Set depth colormap min range"), tr("Range (m), 0=no limit"), _depthColorMapMinRange, 0, 9999, 1, &ok);
double value = QInputDialog::getDouble(this, tr("Set depth colormap min range"), tr("Range (m), 0=no limit"), _depthColorMapMinRange, -9999, 9999, 2, &ok);
if(ok)
{
this->setDepthColorMapRange(value, _depthColorMapMaxRange);
@@ -1070,7 +1088,7 @@ void ImageView::contextMenuEvent(QContextMenuEvent * e)
else if(action == _colorMapMaxRange)
{
bool ok = false;
double value = QInputDialog::getDouble(this, tr("Set depth colormap max range"), tr("Range (m), 0=no limit"), _depthColorMapMaxRange, 0, 9999, 1, &ok);
double value = QInputDialog::getDouble(this, tr("Set depth colormap max range"), tr("Range (m), 0=no limit"), _depthColorMapMaxRange, -9999, 9999, 2, &ok);
if(ok)
{
this->setDepthColorMapRange(_depthColorMapMinRange, value);
@@ -1123,14 +1141,14 @@ void ImageView::mouseMoveEvent(QMouseEvent * event)
if(_mouseTracking->isChecked() &&
!_graphicsView->scene()->sceneRect().isNull() &&
!_image.isNull() &&
!_imageDepthCv.empty() &&(_imageDepthCv.type() == CV_16UC1 || _imageDepthCv.type() == CV_32FC1))
!_imageDepthCv.empty() && (_imageDepthCv.type() == CV_16UC1 || _imageDepthCv.type() == CV_32FC1))
{
float scale, offsetX, offsetY;
computeScaleOffsets(this->rect(), scale, offsetX, offsetY);
float u = (event->pos().x() - offsetX) / scale;
float v = (event->pos().y() - offsetY) / scale;
float depthScale = 1;
if(_image.width() > _imageDepthCv.cols)
if(_image.width() != _imageDepthCv.cols)
{
depthScale = float(_imageDepthCv.cols) / float(_image.width());
}
@@ -1350,8 +1368,71 @@ void ImageView::setImageDepth(const cv::Mat & imageDepth, const cv::Mat & imageD
{
_imageDepthCv = imageDepth;
_imageDepthConfidenceCv = imageDepthConfidence;
QImage depth;
if(!_imageDepthCv.empty() && (_imageDepthCv.type() == CV_16UC1 || _imageDepthCv.type() == CV_32FC1)) {
if(_colorMapInCameraFrame->isChecked() || _models.empty() || !_models[0].isValidForProjection()) {
depth = uCvMat2QImage(_imageDepthCv, true, getDepthColorMap(), _depthColorMapMinRange, _depthColorMapMaxRange);
if(!_colorMapInCameraFrame->isChecked()) {
UWARN("Trying to set depth color map in base frame but the the camera model "
"is not valid for projection, showing depth in camera frame instead.");
}
}
else {
// convert the depth values in height values
cv::Mat depthInBaseFrame = _imageDepthCv.clone();
int subImageWidth = _imageDepthCv.cols / _models.size();
std::vector<CameraModel> models; // scale model to size of depth image if needed
for(const auto & model: _models) {
UASSERT(subImageWidth <= model.imageWidth());
if(subImageWidth < model.imageWidth()) {
models.push_back(model.scaled(float(subImageWidth)/float(model.imageWidth())));
}
else {
models.push_back(model);
}
}
if(depthInBaseFrame.type() == CV_16UC1) {
for(int v=0; v<depthInBaseFrame.rows; ++v){
unsigned short * rowPtr = depthInBaseFrame.ptr<unsigned short>(v);
for(int u=0; u<depthInBaseFrame.cols; ++u){
unsigned short & val = rowPtr[u];
if(val > 0) {
cv::Point3f pt;
int cameraIndex = u/subImageWidth;
UASSERT(cameraIndex>=0 && cameraIndex < (int)models.size() && subImageWidth == models[cameraIndex].imageWidth());
models[cameraIndex].project(u,v,float(val)/1000.0f, pt.x, pt.y, pt.z);
pt = util3d::transformPoint(pt, models[cameraIndex].localTransform());
val = (unsigned short)(pt.z*1000.0f);
}
}
}
}
else { // CV_32FC1
for(int v=0; v<depthInBaseFrame.rows; ++v){
float * rowPtr = depthInBaseFrame.ptr<float>(v);
for(int u=0; u<depthInBaseFrame.cols; ++u){
float & val = rowPtr[u];
if(val > 0) {
cv::Point3f pt;
int cameraIndex = u/subImageWidth;
UASSERT(cameraIndex>=0 && cameraIndex < (int)models.size() && subImageWidth == models[cameraIndex].imageWidth());
models[cameraIndex].project(u,v,val, pt.x, pt.y, pt.z);
pt = util3d::transformPoint(pt, models[cameraIndex].localTransform());
val = pt.z;
}
}
}
}
depth = uCvMat2QImage(depthInBaseFrame, true, getDepthColorMap(), _depthColorMapMinRange, _depthColorMapMaxRange);
}
}
else {
// right image grayscale or color
depth = uCvMat2QImage(_imageDepthCv, true, uCvQtDepthBlackToWhite);
}
setImageDepth(
uCvMat2QImage(_imageDepthCv, true, _imageDepthCv.type()==CV_8UC1?uCvQtDepthBlackToWhite:getDepthColorMap(), _depthColorMapMinRange, _depthColorMapMaxRange),
depth,
uCvMat2QImage(_imageDepthConfidenceCv, true, getDepthColorMap()));
}
@@ -1367,8 +1448,8 @@ void ImageView::setImageDepth(const QImage & imageDepth, const QImage & imageDep
UASSERT(_imageDepth.width() && _imageDepth.height());
if( _image.width() > 0 &&
_image.width() > _imageDepth.width() &&
_image.height() > _imageDepth.height())
_image.width() != _imageDepth.width() &&
_image.height() != _imageDepth.height())
{
// scale depth to rgb
_imageDepth = _imageDepth.scaled(_image.size());
+339 -274
View File
@@ -470,6 +470,7 @@ MainWindow::MainWindow(PreferencesDialog * prefDialog, QWidget * parent, bool sh
connect(_ui->actionDepthAI_oakdlite, SIGNAL(triggered()), this, SLOT(selectDepthAIOAKDLite()));
connect(_ui->actionDepthAI_oakdpro, SIGNAL(triggered()), this, SLOT(selectDepthAIOAKDPro()));
connect(_ui->actionXvisio_SeerSense, SIGNAL(triggered()), this, SLOT(selectXvisioSeerSense()));
connect(_ui->actionOrbbecSDK_astra2, SIGNAL(triggered()), this, SLOT(selectOrbbecSDK()));
connect(_ui->actionVelodyne_VLP_16, SIGNAL(triggered()), this, SLOT(selectVLP16()));
_ui->actionFreenect->setEnabled(CameraFreenect::available());
_ui->actionOpenNI_PCL->setEnabled(CameraOpenni::available());
@@ -499,6 +500,7 @@ MainWindow::MainWindow(PreferencesDialog * prefDialog, QWidget * parent, bool sh
_ui->actionDepthAI_oakdlite->setEnabled(CameraDepthAI::available());
_ui->actionDepthAI_oakdpro->setEnabled(CameraDepthAI::available());
_ui->actionXvisio_SeerSense->setEnabled(CameraSeerSense::available());
_ui->actionOrbbecSDK_astra2->setEnabled(CameraOrbbecSDK::available());
this->updateSelectSourceMenu();
connect(_ui->actionPreferences, SIGNAL(triggered()), this, SLOT(openPreferences()));
@@ -753,7 +755,7 @@ void MainWindow::setupMainLayout(bool vertical)
std::map<int, Transform> MainWindow::currentVisiblePosesMap() const
{
return _ui->widget_mapVisibility->getVisiblePoses();
return !_ui->widget_mapVisibility->isEmpty()?_ui->widget_mapVisibility->getVisiblePoses():_currentPosesMap;
}
void MainWindow::setCloudViewer(rtabmap::CloudViewer * cloudViewer)
@@ -1586,63 +1588,61 @@ void MainWindow::processOdometry(const rtabmap::OdometryEvent & odom, bool dataI
{
_odometryReceived = true;
// update camera position
if(data->cameraModels().size() && data->cameraModels()[0].isValidForProjection())
if(_cloudViewer->isVisible())
{
_cloudViewer->updateCameraFrustums(_odometryCorrection*odom.pose(), data->cameraModels());
}
else if(data->stereoCameraModels().size() && data->stereoCameraModels()[0].isValidForProjection())
{
_cloudViewer->updateCameraFrustums(_odometryCorrection*odom.pose(), data->stereoCameraModels());
}
else if(!data->laserScanRaw().isEmpty() ||
!data->laserScanCompressed().isEmpty())
{
Transform scanLocalTransform;
if(!data->laserScanRaw().isEmpty())
if(data->cameraModels().size() && data->cameraModels()[0].isValidForProjection())
{
scanLocalTransform = data->laserScanRaw().localTransform();
_cloudViewer->updateCameraFrustums(_odometryCorrection*odom.pose(), data->cameraModels());
}
else if(data->stereoCameraModels().size() && data->stereoCameraModels()[0].isValidForProjection())
{
_cloudViewer->updateCameraFrustums(_odometryCorrection*odom.pose(), data->stereoCameraModels());
}
else if(!data->laserScanRaw().isEmpty() ||
!data->laserScanCompressed().isEmpty())
{
Transform scanLocalTransform;
if(!data->laserScanRaw().isEmpty())
{
scanLocalTransform = data->laserScanRaw().localTransform();
}
else
{
scanLocalTransform = data->laserScanCompressed().localTransform();
}
//fake frustum
CameraModel model(
2,
2,
2,
1.5,
scanLocalTransform*CameraModel::opticalRotation(),
0,
cv::Size(4,3));
_cloudViewer->updateCameraFrustum(_odometryCorrection*odom.pose(), model);
}
#if PCL_VERSION_COMPARE(>=, 1, 7, 2)
if(_preferencesDialog->isFramesShown())
{
_cloudViewer->addOrUpdateLine("odom_to_base_link", _odometryCorrection, _odometryCorrection*odom.pose(), qRgb(255, 128, 0), true, false);
}
else
{
scanLocalTransform = data->laserScanCompressed().localTransform();
_cloudViewer->removeLine("odom_to_base_link");
}
//fake frustum
CameraModel model(
2,
2,
2,
1.5,
scanLocalTransform*CameraModel::opticalRotation(),
0,
cv::Size(4,3));
_cloudViewer->updateCameraFrustum(_odometryCorrection*odom.pose(), model);
}
#if PCL_VERSION_COMPARE(>=, 1, 7, 2)
if(_preferencesDialog->isFramesShown())
{
_cloudViewer->addOrUpdateLine("odom_to_base_link", _odometryCorrection, _odometryCorrection*odom.pose(), qRgb(255, 128, 0), true, false);
}
else
{
_cloudViewer->removeLine("odom_to_base_link");
}
#endif
_cloudViewer->updateCameraTargetPosition(_odometryCorrection*odom.pose());
UDEBUG("Time Update Pose: %fs", time.ticks());
}
_cloudViewer->refreshView();
if(_ui->graphicsView_graphView->isVisible())
{
if(!pose.isNull() && !odom.pose().isNull())
_cloudViewer->updateCameraTargetPosition(_odometryCorrection*odom.pose());
UDEBUG("Time Update Pose: %fs", time.ticks());
_cloudViewer->refreshView();
}
if(_ui->graphicsView_graphView->isVisible())
{
_ui->graphicsView_graphView->updateReferentialPosition(_odometryCorrection*odom.pose());
_ui->graphicsView_graphView->update();
UDEBUG("Time Update graphview: %fs", time.ticks());
}
}
}
if(_ui->dockWidget_odometry->isVisible() &&
!data->imageRaw().empty())
@@ -1675,7 +1675,7 @@ void MainWindow::processOdometry(const rtabmap::OdometryEvent & odom, bool dataI
odom.info().type == (int)Odometry::kTypeViso2 ||
odom.info().type == (int)Odometry::kTypeFovis ||
odom.info().type == (int)Odometry::kTypeMSCKF ||
odom.info().type == (int)Odometry::kTypeVINS ||
odom.info().type == (int)Odometry::kTypeVINSFusion ||
odom.info().type == (int)Odometry::kTypeOpenVINS)
{
std::vector<cv::KeyPoint> kpts;
@@ -1725,7 +1725,6 @@ void MainWindow::processOdometry(const rtabmap::OdometryEvent & odom, bool dataI
if( odom.info().type == (int)Odometry::kTypeF2M ||
odom.info().type == (int)Odometry::kTypeORBSLAM ||
odom.info().type == (int)Odometry::kTypeMSCKF ||
odom.info().type == (int)Odometry::kTypeVINS ||
odom.info().type == (int)Odometry::kTypeOpenVINS)
{
if(_ui->imageView_odometry->isFeaturesShown() && !_preferencesDialog->isOdomOnlyInliersShown())
@@ -1742,6 +1741,7 @@ void MainWindow::processOdometry(const rtabmap::OdometryEvent & odom, bool dataI
}
if((odom.info().type == (int)Odometry::kTypeF2F ||
odom.info().type == (int)Odometry::kTypeViso2 ||
odom.info().type == (int)Odometry::kTypeVINSFusion ||
odom.info().type == (int)Odometry::kTypeFovis) && odom.info().refCorners.size())
{
if(_ui->imageView_odometry->isFeaturesShown() || _ui->imageView_odometry->isLinesShown())
@@ -1795,6 +1795,7 @@ void MainWindow::processOdometry(const rtabmap::OdometryEvent & odom, bool dataI
//Process info
if(_preferencesDialog->isCacheSavedInFigures() || _ui->statsToolBox->isVisible())
{
UASSERT(odom.info().reg.covariance.total() == 36 && odom.info().reg.covariance.type() == CV_64FC1);
double linVar = uMax3(odom.info().reg.covariance.at<double>(0,0), odom.info().reg.covariance.at<double>(1,1)>=9999?0:odom.info().reg.covariance.at<double>(1,1), odom.info().reg.covariance.at<double>(2,2)>=9999?0:odom.info().reg.covariance.at<double>(2,2));
double angVar = uMax3(odom.info().reg.covariance.at<double>(3,3)>=9999?0:odom.info().reg.covariance.at<double>(3,3), odom.info().reg.covariance.at<double>(4,4)>=9999?0:odom.info().reg.covariance.at<double>(4,4), odom.info().reg.covariance.at<double>(5,5));
_ui->statsToolBox->updateStat("Odometry/Inliers/", _preferencesDialog->isTimeUsedInFigures()?data->stamp()-_firstStamp:(float)data->id(), (float)odom.info().reg.inliers, _preferencesDialog->isCacheSavedInFigures());
@@ -2028,13 +2029,14 @@ void MainWindow::processStats(const rtabmap::Statistics & stat)
{
// make sure data are uncompressed
// We don't need to uncompress images if we don't show them
bool uncompressImages = !signature.sensorData().imageCompressed().empty() && (
_ui->imageView_source->isVisible() ||
(_loopClosureViewer->isVisible() &&
!signature.sensorData().depthOrRightCompressed().empty()) ||
(_cloudViewer->isVisible() &&
_preferencesDialog->isCloudsShown(0) &&
!signature.sensorData().depthOrRightCompressed().empty()));
bool uncompressImages = (!signature.sensorData().imageCompressed().empty() &&
((_ui->imageView_source->isVisible() && _ui->imageView_source->isImageShown()) ||
_loopClosureViewer->isVisible()))
||
(!signature.sensorData().depthOrRightCompressed().empty() &&
((_ui->imageView_loopClosure->isVisible() && _ui->imageView_loopClosure->isImageShown()) ||
(_cloudViewer->isVisible() && _preferencesDialog->isCloudsShown(0))));
bool uncompressScan = !signature.sensorData().laserScanCompressed().isEmpty() && (
_loopClosureViewer->isVisible() ||
(_cloudViewer->isVisible() && _preferencesDialog->isScansShown(0)));
@@ -2113,11 +2115,19 @@ void MainWindow::processStats(const rtabmap::Statistics & stat)
_ui->imageView_source->clear();
_ui->imageView_loopClosure->clear();
if(signature.sensorData().imageRaw().empty() && signature.getWords().empty())
// To see colors
QRect rect(0,0,640,480); // default
if(signature.sensorData().cameraModels().size() && signature.sensorData().cameraModels().at(0).imageSize()!=cv::Size())
{
// To see colors
_ui->imageView_source->setSceneRect(QRect(0,0,640,480));
rect.setWidth(signature.sensorData().cameraModels().at(0).imageWidth()*signature.sensorData().cameraModels().size());
rect.setHeight(signature.sensorData().cameraModels().at(0).imageHeight());
}
else if(signature.sensorData().stereoCameraModels().size() && signature.sensorData().stereoCameraModels().at(0).left().imageSize()!=cv::Size())
{
rect.setWidth(signature.sensorData().stereoCameraModels().at(0).left().imageWidth()*signature.sensorData().stereoCameraModels().size());
rect.setHeight(signature.sensorData().stereoCameraModels().at(0).left().imageHeight());
}
_ui->imageView_source->setSceneRect(rect);
_ui->imageView_source->setBackgroundColor(_ui->imageView_source->getDefaultBackgroundColor());
_ui->imageView_loopClosure->setBackgroundColor(_ui->imageView_loopClosure->getDefaultBackgroundColor());
@@ -2258,22 +2268,27 @@ void MainWindow::processStats(const rtabmap::Statistics & stat)
QMap<int, Signature>::iterator iter = _cachedSignatures.find(shownLoopId);
if(iter != _cachedSignatures.end())
{
// uncompress after copy to avoid keeping uncompressed data in memory
loopSignature = iter.value();
bool uncompressImages = !loopSignature.sensorData().imageCompressed().empty() && (
_ui->imageView_source->isVisible() ||
(_loopClosureViewer->isVisible() &&
!loopSignature.sensorData().depthOrRightCompressed().empty()));
bool uncompressScan = _loopClosureViewer->isVisible() &&
!loopSignature.sensorData().laserScanCompressed().isEmpty();
if(uncompressImages || uncompressScan)
if((_ui->imageView_loopClosure->isVisible() && (_ui->imageView_loopClosure->isImageShown() || _ui->imageView_loopClosure->isImageDepthShown())) ||
_loopClosureViewer->isVisible())
{
cv::Mat tmpRGB, tmpDepth;
LaserScan tmpScan;
loopSignature.sensorData().uncompressData(
uncompressImages?&tmpRGB:0,
uncompressImages?&tmpDepth:0,
uncompressScan?&tmpScan:0);
// uncompress after copy to avoid keeping uncompressed data in memory
bool uncompressImages = !loopSignature.sensorData().imageCompressed().empty() && (
(_ui->imageView_loopClosure->isVisible() && (_ui->imageView_loopClosure->isImageShown() || _ui->imageView_loopClosure->isImageDepthShown())) ||
(_loopClosureViewer->isVisible() &&
!loopSignature.sensorData().depthOrRightCompressed().empty()));
bool uncompressScan = _loopClosureViewer->isVisible() &&
!loopSignature.sensorData().laserScanCompressed().isEmpty();
if(uncompressImages || uncompressScan)
{
cv::Mat tmpRGB, tmpDepth;
LaserScan tmpScan;
loopSignature.sensorData().uncompressData(
uncompressImages?&tmpRGB:0,
uncompressImages?&tmpDepth:0,
uncompressScan?&tmpScan:0);
}
}
}
}
@@ -2291,14 +2306,14 @@ void MainWindow::processStats(const rtabmap::Statistics & stat)
!loopSignature.sensorData().imageRaw().empty() ||
signature.getWords().size())
{
cv::Mat refImage = signature.sensorData().imageRaw();
cv::Mat loopImage = loopSignature.sensorData().imageRaw();
cv::Mat refImage = _ui->imageView_source->isImageShown()?signature.sensorData().imageRaw():cv::Mat();
cv::Mat loopImage = _ui->imageView_loopClosure->isImageShown()?loopSignature.sensorData().imageRaw():cv::Mat();
if( _preferencesDialog->isMarkerDetection() &&
_preferencesDialog->isLandmarksShown())
{
//draw markers
if(!signature.getLandmarks().empty())
if(!signature.getLandmarks().empty() && !refImage.empty())
{
if(refImage.channels() == 1)
{
@@ -2312,7 +2327,7 @@ void MainWindow::processStats(const rtabmap::Statistics & stat)
}
drawLandmarks(refImage, signature);
}
if(!loopSignature.getLandmarks().empty())
if(!loopSignature.getLandmarks().empty() && !loopImage.empty())
{
if(loopImage.channels() == 1)
{
@@ -2342,42 +2357,37 @@ void MainWindow::processStats(const rtabmap::Statistics & stat)
{
_ui->imageView_source->setImage(img);
}
if(!signature.sensorData().depthOrRightRaw().empty())
if(!signature.sensorData().depthOrRightRaw().empty() && _ui->imageView_source->isImageDepthShown())
{
_ui->imageView_source->setImageDepth(signature.sensorData().depthOrRightRaw(), signature.sensorData().depthConfidenceRaw());
}
if(img.isNull() && signature.sensorData().depthOrRightRaw().empty())
{
QRect sceneRect;
if(signature.sensorData().cameraModels().size())
{
for(unsigned int i=0; i<signature.sensorData().cameraModels().size(); ++i)
{
sceneRect.setWidth(sceneRect.width()+signature.sensorData().cameraModels()[i].imageWidth());
sceneRect.setHeight(std::max((int)sceneRect.height(), signature.sensorData().cameraModels()[i].imageHeight()));
}
}
else if(signature.sensorData().stereoCameraModels().size())
{
for(unsigned int i=0; i<signature.sensorData().cameraModels().size(); ++i)
{
sceneRect.setWidth(sceneRect.width()+signature.sensorData().stereoCameraModels()[i].left().imageWidth());
sceneRect.setHeight(std::max((int)sceneRect.height(), signature.sensorData().stereoCameraModels()[i].left().imageHeight()));
}
}
if(sceneRect.isValid())
{
_ui->imageView_source->setSceneRect(sceneRect);
}
}
if(!lcImg.isNull())
{
_ui->imageView_loopClosure->setImage(lcImg);
}
if(!loopSignature.sensorData().depthOrRightRaw().empty())
if(!loopSignature.sensorData().depthOrRightRaw().empty() && _ui->imageView_loopClosure->isImageDepthShown())
{
_ui->imageView_loopClosure->setImageDepth(loopSignature.sensorData().depthOrRightRaw(), loopSignature.sensorData().depthConfidenceRaw());
}
if(lcImg.isNull())
{
QRect sceneRect;
if(loopSignature.sensorData().cameraModels().size() && loopSignature.sensorData().cameraModels().at(0).imageSize()!=cv::Size())
{
rect.setWidth(loopSignature.sensorData().cameraModels().at(0).imageWidth()*loopSignature.sensorData().cameraModels().size());
rect.setHeight(loopSignature.sensorData().cameraModels().at(0).imageHeight());
}
else if(loopSignature.sensorData().stereoCameraModels().size() && loopSignature.sensorData().stereoCameraModels().at(0).left().imageSize()!=cv::Size())
{
rect.setWidth(loopSignature.sensorData().stereoCameraModels().at(0).left().imageWidth()*loopSignature.sensorData().stereoCameraModels().size());
rect.setHeight(loopSignature.sensorData().stereoCameraModels().at(0).left().imageHeight());
}
if(sceneRect.isValid())
{
_ui->imageView_loopClosure->setSceneRect(sceneRect);
}
}
if(_ui->imageView_loopClosure->sceneRect().isNull())
{
_ui->imageView_loopClosure->setSceneRect(_ui->imageView_source->sceneRect());
@@ -2391,18 +2401,37 @@ void MainWindow::processStats(const rtabmap::Statistics & stat)
UDEBUG("time= %d ms (update detection imageviews)", time.restart());
// do it after scaling
std::multimap<int, cv::KeyPoint> wordsA;
std::multimap<int, cv::KeyPoint> wordsB;
for(std::map<int, int>::const_iterator iter=signature.getWords().begin(); iter!=signature.getWords().end(); ++iter)
if(_ui->imageView_source->isFeaturesShown() || _ui->imageView_loopClosure->isFeaturesShown() ||
(_ui->imageView_source->isLinesShown() && _ui->imageView_loopClosure->isLinesShown()))
{
wordsA.insert(wordsA.end(), std::make_pair(iter->first, signature.getWordsKpts()[iter->second]));
// do it after scaling
std::multimap<int, cv::KeyPoint> wordsA;
std::multimap<int, cv::KeyPoint> wordsB;
if(signature.getWords().size() == signature.getWordsKpts().size() &&
(_ui->imageView_source->isFeaturesShown() || (_ui->imageView_source->isLinesShown() && _ui->imageView_loopClosure->isLinesShown())))
{
for(std::map<int, int>::const_iterator iter=signature.getWords().begin(); iter!=signature.getWords().end(); ++iter)
{
wordsA.insert(wordsA.end(), std::make_pair(iter->first, signature.getWordsKpts()[iter->second]));
}
}
if(loopSignature.getWords().size() == loopSignature.getWordsKpts().size() &&
(_ui->imageView_loopClosure->isFeaturesShown() || (_ui->imageView_source->isLinesShown() && _ui->imageView_loopClosure->isLinesShown())))
{
for(std::map<int, int>::const_iterator iter=loopSignature.getWords().begin(); iter!=loopSignature.getWords().end(); ++iter)
{
wordsB.insert(wordsB.end(), std::make_pair(iter->first, loopSignature.getWordsKpts()[iter->second]));
}
}
this->drawKeypoints(wordsA, wordsB);
}
for(std::map<int, int>::const_iterator iter=loopSignature.getWords().begin(); iter!=loopSignature.getWords().end(); ++iter)
{
wordsB.insert(wordsB.end(), std::make_pair(iter->first, loopSignature.getWordsKpts()[iter->second]));
else {
_ui->imageView_source->clearFeatures();
_ui->imageView_loopClosure->clearFeatures();
_ui->imageView_source->clearLines();
_ui->imageView_loopClosure->clearLines();
_lastIds.clear();
}
this->drawKeypoints(wordsA, wordsB);
UDEBUG("time= %d ms (draw keypoints)", time.restart());
@@ -2511,43 +2540,45 @@ void MainWindow::processStats(const rtabmap::Statistics & stat)
UDEBUG("%d %d %d", poses.size(), poses.size()?poses.rbegin()->first:0, stat.refImageId());
if(!_odometryReceived && poses.size() && poses.rbegin()->first == stat.refImageId())
{
if(poses.rbegin()->first == stat.getLastSignatureData().id())
if(_cloudViewer->isVisible())
{
if(stat.getLastSignatureData().sensorData().cameraModels().size() && stat.getLastSignatureData().sensorData().cameraModels()[0].isValidForProjection())
if(poses.rbegin()->first == stat.getLastSignatureData().id())
{
_cloudViewer->updateCameraFrustums(poses.rbegin()->second, stat.getLastSignatureData().sensorData().cameraModels());
}
else if(stat.getLastSignatureData().sensorData().stereoCameraModels().size() && stat.getLastSignatureData().sensorData().stereoCameraModels()[0].isValidForProjection())
{
_cloudViewer->updateCameraFrustums(poses.rbegin()->second, stat.getLastSignatureData().sensorData().stereoCameraModels());
}
else if(!stat.getLastSignatureData().sensorData().laserScanRaw().isEmpty() ||
!stat.getLastSignatureData().sensorData().laserScanCompressed().isEmpty())
{
Transform scanLocalTransform;
if(!stat.getLastSignatureData().sensorData().laserScanRaw().isEmpty())
if(stat.getLastSignatureData().sensorData().cameraModels().size() && stat.getLastSignatureData().sensorData().cameraModels()[0].isValidForProjection())
{
scanLocalTransform = stat.getLastSignatureData().sensorData().laserScanRaw().localTransform();
_cloudViewer->updateCameraFrustums(poses.rbegin()->second, stat.getLastSignatureData().sensorData().cameraModels());
}
else
else if(stat.getLastSignatureData().sensorData().stereoCameraModels().size() && stat.getLastSignatureData().sensorData().stereoCameraModels()[0].isValidForProjection())
{
scanLocalTransform = stat.getLastSignatureData().sensorData().laserScanCompressed().localTransform();
_cloudViewer->updateCameraFrustums(poses.rbegin()->second, stat.getLastSignatureData().sensorData().stereoCameraModels());
}
else if(!stat.getLastSignatureData().sensorData().laserScanRaw().isEmpty() ||
!stat.getLastSignatureData().sensorData().laserScanCompressed().isEmpty())
{
Transform scanLocalTransform;
if(!stat.getLastSignatureData().sensorData().laserScanRaw().isEmpty())
{
scanLocalTransform = stat.getLastSignatureData().sensorData().laserScanRaw().localTransform();
}
else
{
scanLocalTransform = stat.getLastSignatureData().sensorData().laserScanCompressed().localTransform();
}
//fake frustum
CameraModel model(
2,
2,
2,
1.5,
scanLocalTransform*CameraModel::opticalRotation(),
0,
cv::Size(4,3));
_cloudViewer->updateCameraFrustum(poses.rbegin()->second, model);
}
//fake frustum
CameraModel model(
2,
2,
2,
1.5,
scanLocalTransform*CameraModel::opticalRotation(),
0,
cv::Size(4,3));
_cloudViewer->updateCameraFrustum(poses.rbegin()->second, model);
}
_cloudViewer->updateCameraTargetPosition(poses.rbegin()->second);
}
_cloudViewer->updateCameraTargetPosition(poses.rbegin()->second);
if(_ui->graphicsView_graphView->isVisible())
{
_ui->graphicsView_graphView->updateReferentialPosition(poses.rbegin()->second);
@@ -2842,6 +2873,7 @@ void MainWindow::updateMapCloud(
_progressDialog->appendText(tr("Map update: %1 nodes shown of %2 (cloud filtering is on)").arg(poses.size()).arg(nodePoses.size()));
QApplication::processEvents();
}
UDEBUG("Filtered poses");
}
else
{
@@ -2849,27 +2881,33 @@ void MainWindow::updateMapCloud(
mapIds = mapIdsIn;
}
std::map<int, bool> posesMask;
for(std::map<int, Transform>::const_iterator iter = nodePoses.begin(); iter!=nodePoses.end(); ++iter)
if(_ui->widget_mapVisibility->isVisible())
{
posesMask.insert(posesMask.end(), std::make_pair(iter->first, poses.find(iter->first) != poses.end()));
std::map<int, bool> posesMask;
for(std::map<int, Transform>::const_iterator iter = nodePoses.begin(); iter!=nodePoses.end(); ++iter)
{
posesMask.insert(posesMask.end(), std::make_pair(iter->first, poses.find(iter->first) != poses.end()));
}
_ui->widget_mapVisibility->setMap(nodePoses, posesMask);
UDEBUG("Updated map visibility with %ld poses", nodePoses.size());
}
else {
_ui->widget_mapVisibility->clear();
}
_ui->widget_mapVisibility->setMap(nodePoses, posesMask);
if(groundTruths.size() && _ui->actionAnchor_clouds_to_ground_truth->isChecked())
{
int anchored = 0;
for(std::map<int, Transform>::iterator iter = poses.begin(); iter!=poses.end(); ++iter)
{
std::map<int, Transform>::const_iterator gtIter = groundTruths.find(iter->first);
if(gtIter!=groundTruths.end())
{
iter->second = gtIter->second;
}
else
{
UWARN("Not found ground truth pose for node %d", iter->first);
++anchored;
}
}
UDEBUG("Anchored %d/%ld poses to ground truth", anchored, poses.size());
}
else if(_currentGTPosesMap.size() == 0)
{
@@ -3041,7 +3079,9 @@ void MainWindow::updateMapCloud(
cv::Mat obstacles;
cv::Mat empty;
UTimer decompressionTime;
jter->sensorData().uncompressDataConst(0, 0, 0, 0, &ground, &obstacles, &empty);
UDEBUG("Uncompressed local occupancy grid of node %d (%f s)", jter->id(), decompressionTime.ticks());
double resolution = jter->sensorData().gridCellSize();
if(_preferencesDialog->getGridUIResolution() > jter->sensorData().gridCellSize())
@@ -3210,6 +3250,7 @@ void MainWindow::updateMapCloud(
if(_preferencesDialog->isGroundTruthAligned() && _currentGTPosesMap.size())
{
mapToGt = alignPosesToGroundTruth(_currentPosesMap, _currentGTPosesMap).inverse();
UDEBUG("Aligned poses to ground truth (%ld poses %ld gt poses)", _currentPosesMap.size(), _currentGTPosesMap.size());
}
std::map<int, Transform> posesWithOdomCache;
@@ -3224,7 +3265,9 @@ void MainWindow::updateMapCloud(
}
}
if((_preferencesDialog->isGraphsShown() || _preferencesDialog->isFrustumsShown(0)) && _currentPosesMap.size())
if( _cloudViewer->isVisible() &&
(_preferencesDialog->isGraphsShown() || _preferencesDialog->isFrustumsShown(0)) &&
_currentPosesMap.size())
{
UTimer timerGraph;
// Find all graphs
@@ -3327,7 +3370,7 @@ void MainWindow::updateMapCloud(
}
}
UDEBUG("timerGraph=%fs", timerGraph.ticks());
UDEBUG("timerGraph (CloudViewer)=%fs", timerGraph.ticks());
}
UDEBUG("labels.size()=%d", (int)labels.size());
@@ -4363,7 +4406,7 @@ void MainWindow::createAndAddFeaturesToMap(int nodeId, const Transform & pose, i
UASSERT(iter->getWords().size() == iter->getWords3().size());
float maxDepth = _preferencesDialog->getCloudMaxDepth(0);
UDEBUG("rgb.channels()=%d");
if(!iter->getWords3().empty() && !iter->getWordsKpts().empty())
if(!iter->getWords3().empty() && iter->getWords3().size() == iter->getWordsKpts().size())
{
Transform invLocalTransform = Transform::getIdentity();
if(iter.value().sensorData().cameraModels().size() == 1 &&
@@ -5012,96 +5055,113 @@ void MainWindow::drawKeypoints(const std::multimap<int, cv::KeyPoint> & refWords
timer.start();
ULOGGER_DEBUG("refWords.size() = %d", refWords.size());
if(refWords.size())
_ui->imageView_source->clearFeatures();
if(_ui->imageView_source->isFeaturesShown())
{
_ui->imageView_source->clearFeatures();
for(std::multimap<int, cv::KeyPoint>::const_iterator iter = refWords.begin(); iter != refWords.end(); ++iter )
{
int id = iter->first;
QColor color;
if(id<0)
{
// GRAY = NOT QUANTIZED
color = Qt::gray;
}
else if(uContains(loopWords, id))
{
// PINK = FOUND IN LOOP SIGNATURE
color = Qt::magenta;
}
else if(_lastIds.contains(id))
{
// BLUE = FOUND IN LAST SIGNATURE
color = Qt::blue;
}
else if(id<=_lastId)
{
// RED = ALREADY EXISTS
color = Qt::red;
}
else if(refWords.count(id) > 1)
{
// YELLOW = NEW and multiple times
color = Qt::yellow;
}
else
{
// GREEN = NEW
color = Qt::green;
}
_ui->imageView_source->addFeature(iter->first, iter->second, 0, color);
}
}
for(std::multimap<int, cv::KeyPoint>::const_iterator iter = refWords.begin(); iter != refWords.end(); ++iter )
{
int id = iter->first;
QColor color;
if(id<0)
{
// GRAY = NOT QUANTIZED
color = Qt::gray;
}
else if(uContains(loopWords, id))
{
// PINK = FOUND IN LOOP SIGNATURE
color = Qt::magenta;
}
else if(_lastIds.contains(id))
{
// BLUE = FOUND IN LAST SIGNATURE
color = Qt::blue;
}
else if(id<=_lastId)
{
// RED = ALREADY EXISTS
color = Qt::red;
}
else if(refWords.count(id) > 1)
{
// YELLOW = NEW and multiple times
color = Qt::yellow;
}
else
{
// GREEN = NEW
color = Qt::green;
}
_ui->imageView_source->addFeature(iter->first, iter->second, 0, color);
}
ULOGGER_DEBUG("source time = %f s", timer.ticks());
ULOGGER_DEBUG("source time (shown=%d) = %f s", _ui->imageView_source->isFeaturesShown()?1:0, timer.ticks());
timer.start();
ULOGGER_DEBUG("loopWords.size() = %d", loopWords.size());
QList<QPair<cv::Point2f, cv::Point2f> > uniqueCorrespondences;
if(loopWords.size())
_ui->imageView_loopClosure->clearFeatures();
if(_ui->imageView_loopClosure->isFeaturesShown())
{
_ui->imageView_loopClosure->clearFeatures();
}
for(std::multimap<int, cv::KeyPoint>::const_iterator iter = loopWords.begin(); iter != loopWords.end(); ++iter )
{
int id = iter->first;
QColor color;
if(id<0)
for(std::multimap<int, cv::KeyPoint>::const_iterator iter = loopWords.begin(); iter != loopWords.end(); ++iter )
{
// GRAY = NOT QUANTIZED
color = Qt::gray;
}
else if(uContains(refWords, id))
{
// PINK = FOUND IN LOOP SIGNATURE
color = Qt::magenta;
//To draw lines... get only unique correspondences
if(uValues(refWords, id).size() == 1 && uValues(loopWords, id).size() == 1)
int id = iter->first;
QColor color;
if(id<0)
{
const cv::KeyPoint & a = refWords.find(id)->second;
const cv::KeyPoint & b = iter->second;
uniqueCorrespondences.push_back(QPair<cv::Point2f, cv::Point2f>(a.pt, b.pt));
// GRAY = NOT QUANTIZED
color = Qt::gray;
}
else if(uContains(refWords, id))
{
// PINK = FOUND IN LOOP SIGNATURE
color = Qt::magenta;
//To draw lines... get only unique correspondences
if(uValues(refWords, id).size() == 1 && uValues(loopWords, id).size() == 1)
{
const cv::KeyPoint & a = refWords.find(id)->second;
const cv::KeyPoint & b = iter->second;
uniqueCorrespondences.push_back(QPair<cv::Point2f, cv::Point2f>(a.pt, b.pt));
}
}
else if(id<=_lastId)
{
// RED = ALREADY EXISTS
color = Qt::red;
}
else if(refWords.count(id) > 1)
{
// YELLOW = NEW and multiple times
color = Qt::yellow;
}
else
{
// GREEN = NEW
color = Qt::green;
}
_ui->imageView_loopClosure->addFeature(iter->first, iter->second, 0, color);
}
}
else if(_ui->imageView_source->isLinesShown() && _ui->imageView_loopClosure->isLinesShown())
{
for(std::multimap<int, cv::KeyPoint>::const_iterator iter = loopWords.begin(); iter != loopWords.end(); ++iter )
{
int id = iter->first;
if(id>=0 && uContains(refWords, id))
{
//To draw lines... get only unique correspondences
if(uValues(refWords, id).size() == 1 && uValues(loopWords, id).size() == 1)
{
const cv::KeyPoint & a = refWords.find(id)->second;
const cv::KeyPoint & b = iter->second;
uniqueCorrespondences.push_back(QPair<cv::Point2f, cv::Point2f>(a.pt, b.pt));
}
}
}
else if(id<=_lastId)
{
// RED = ALREADY EXISTS
color = Qt::red;
}
else if(refWords.count(id) > 1)
{
// YELLOW = NEW and multiple times
color = Qt::yellow;
}
else
{
// GREEN = NEW
color = Qt::green;
}
_ui->imageView_loopClosure->addFeature(iter->first, iter->second, 0, color);
}
ULOGGER_DEBUG("loop closure time (shown=%d) = %f s", _ui->imageView_loopClosure->isFeaturesShown()?1:0, timer.ticks());
ULOGGER_DEBUG("loop closure time = %f s", timer.ticks());
_lastIds.clear();
if(refWords.size()>0)
{
if((*refWords.rbegin()).first > _lastId)
@@ -5116,52 +5176,51 @@ void MainWindow::drawKeypoints(const std::multimap<int, cv::KeyPoint> & refWords
#endif
}
// Draw lines between corresponding features...
float scaleSource = _ui->imageView_source->viewScale();
float scaleLoop = _ui->imageView_loopClosure->viewScale();
UDEBUG("scale source=%f loop=%f", scaleSource, scaleLoop);
// Delta in actual window pixels
float sourceMarginX = (_ui->imageView_source->width() - _ui->imageView_source->sceneRect().width()*scaleSource)/2.0f;
float sourceMarginY = (_ui->imageView_source->height() - _ui->imageView_source->sceneRect().height()*scaleSource)/2.0f;
float loopMarginX = (_ui->imageView_loopClosure->width() - _ui->imageView_loopClosure->sceneRect().width()*scaleLoop)/2.0f;
float loopMarginY = (_ui->imageView_loopClosure->height() - _ui->imageView_loopClosure->sceneRect().height()*scaleLoop)/2.0f;
float deltaX = 0;
float deltaY = 0;
if(_preferencesDialog->isVerticalLayoutUsed())
_ui->imageView_source->clearLines();
_ui->imageView_loopClosure->clearLines();
if(_ui->imageView_source->isLinesShown() && _ui->imageView_loopClosure->isLinesShown())
{
deltaY = _ui->label_matchId->height() + _ui->imageView_source->height();
}
else
{
deltaX = _ui->imageView_source->width();
}
// Draw lines between corresponding features...
float scaleSource = _ui->imageView_source->viewScale();
float scaleLoop = _ui->imageView_loopClosure->viewScale();
UDEBUG("scale source=%f loop=%f", scaleSource, scaleLoop);
// Delta in actual window pixels
float sourceMarginX = (_ui->imageView_source->width() - _ui->imageView_source->sceneRect().width()*scaleSource)/2.0f;
float sourceMarginY = (_ui->imageView_source->height() - _ui->imageView_source->sceneRect().height()*scaleSource)/2.0f;
float loopMarginX = (_ui->imageView_loopClosure->width() - _ui->imageView_loopClosure->sceneRect().width()*scaleLoop)/2.0f;
float loopMarginY = (_ui->imageView_loopClosure->height() - _ui->imageView_loopClosure->sceneRect().height()*scaleLoop)/2.0f;
if(refWords.size() && loopWords.size())
{
_ui->imageView_source->clearLines();
_ui->imageView_loopClosure->clearLines();
}
float deltaX = 0;
float deltaY = 0;
for(QList<QPair<cv::Point2f, cv::Point2f> >::iterator iter = uniqueCorrespondences.begin();
iter!=uniqueCorrespondences.end();
++iter)
{
if(_preferencesDialog->isVerticalLayoutUsed())
{
deltaY = _ui->label_matchId->height() + _ui->imageView_source->height();
}
else
{
deltaX = _ui->imageView_source->width();
}
_ui->imageView_source->addLine(
iter->first.x,
iter->first.y,
(iter->second.x*scaleLoop+loopMarginX+deltaX-sourceMarginX)/scaleSource,
(iter->second.y*scaleLoop+loopMarginY+deltaY-sourceMarginY)/scaleSource,
_ui->imageView_source->getDefaultMatchingLineColor());
for(QList<QPair<cv::Point2f, cv::Point2f> >::iterator iter = uniqueCorrespondences.begin();
iter!=uniqueCorrespondences.end();
++iter)
{
_ui->imageView_loopClosure->addLine(
(iter->first.x*scaleSource+sourceMarginX-deltaX-loopMarginX)/scaleLoop,
(iter->first.y*scaleSource+sourceMarginY-deltaY-loopMarginY)/scaleLoop,
iter->second.x,
iter->second.y,
_ui->imageView_loopClosure->getDefaultMatchingLineColor());
_ui->imageView_source->addLine(
iter->first.x,
iter->first.y,
(iter->second.x*scaleLoop+loopMarginX+deltaX-sourceMarginX)/scaleSource,
(iter->second.y*scaleLoop+loopMarginY+deltaY-sourceMarginY)/scaleSource,
_ui->imageView_source->getDefaultMatchingLineColor());
_ui->imageView_loopClosure->addLine(
(iter->first.x*scaleSource+sourceMarginX-deltaX-loopMarginX)/scaleLoop,
(iter->first.y*scaleSource+sourceMarginY-deltaY-loopMarginY)/scaleLoop,
iter->second.x,
iter->second.y,
_ui->imageView_loopClosure->getDefaultMatchingLineColor());
}
}
_ui->imageView_source->update();
_ui->imageView_loopClosure->update();
@@ -5331,6 +5390,7 @@ void MainWindow::updateSelectSourceMenu()
_ui->actionDepthAI_oakdlite->setChecked(_preferencesDialog->getSourceDriver() == PreferencesDialog::kSrcStereoDepthAI);
_ui->actionDepthAI_oakdpro->setChecked(_preferencesDialog->getSourceDriver() == PreferencesDialog::kSrcStereoDepthAI);
_ui->actionXvisio_SeerSense->setChecked(_preferencesDialog->getSourceDriver() == PreferencesDialog::kSrcSeerSense);
_ui->actionOrbbecSDK_astra2->setChecked(_preferencesDialog->getSourceDriver() == PreferencesDialog::kSrcOrbbecSDK);
_ui->actionVelodyne_VLP_16->setChecked(_preferencesDialog->getLidarSourceDriver() == PreferencesDialog::kSrcLidarVLP16);
}
@@ -5989,7 +6049,7 @@ void MainWindow::startDetection()
_imuThread = 0;
}
if(!_sensorCapture->odomProvided() && !_preferencesDialog->isOdomDisabled())
if((!_sensorCapture->odomProvided() || _preferencesDialog->isOdomAsGuessEnabled()) && !_preferencesDialog->isOdomDisabled())
{
ParametersMap odomParameters = parameters;
if(_preferencesDialog->getOdomRegistrationApproach() < 3)
@@ -6047,7 +6107,7 @@ void MainWindow::startDetection()
}
}
if(_dataRecorder && _sensorCapture && _odomThread)
if(_dataRecorder && _sensorCapture)
{
UEventsManager::createPipe(_sensorCapture, _dataRecorder, "SensorEvent");
}
@@ -7207,6 +7267,11 @@ void MainWindow::selectK4A()
_preferencesDialog->selectSourceDriver(PreferencesDialog::kSrcK4A);
}
void MainWindow::selectOrbbecSDK()
{
_preferencesDialog->selectSourceDriver(PreferencesDialog::kSrcOrbbecSDK);
}
void MainWindow::selectRealSense()
{
_preferencesDialog->selectSourceDriver(PreferencesDialog::kSrcRealSense);
@@ -7981,7 +8046,7 @@ void MainWindow::exportClouds()
return;
}
std::map<int, Transform> poses = _ui->widget_mapVisibility->getVisiblePoses();
std::map<int, Transform> poses = !_ui->widget_mapVisibility->isEmpty()?_ui->widget_mapVisibility->getVisiblePoses():_currentPosesMap;
// Use ground truth poses if current clouds are using them
if(_currentGTPosesMap.size() && _ui->actionAnchor_clouds_to_ground_truth->isChecked())
@@ -8018,7 +8083,7 @@ void MainWindow::viewClouds()
return;
}
std::map<int, Transform> poses = _ui->widget_mapVisibility->getVisiblePoses();
std::map<int, Transform> poses = !_ui->widget_mapVisibility->isEmpty()?_ui->widget_mapVisibility->getVisiblePoses():_currentPosesMap;
// Use ground truth poses if current clouds are using them
if(_currentGTPosesMap.size() && _ui->actionAnchor_clouds_to_ground_truth->isChecked())
@@ -8094,7 +8159,7 @@ void MainWindow::exportImages()
QMessageBox::warning(this, tr("Export images..."), tr("Cannot export images, the cache is empty!"));
return;
}
std::map<int, Transform> poses = _ui->widget_mapVisibility->getVisiblePoses();
std::map<int, Transform> poses = !_ui->widget_mapVisibility->isEmpty()?_ui->widget_mapVisibility->getVisiblePoses():_currentPosesMap;
if(poses.empty())
{
@@ -8311,7 +8376,7 @@ void MainWindow::exportBundlerFormat()
return;
}
std::map<int, Transform> posesIn = _ui->widget_mapVisibility->getVisiblePoses();
std::map<int, Transform> posesIn = !_ui->widget_mapVisibility->isEmpty()?_ui->widget_mapVisibility->getVisiblePoses():_currentPosesMap;
// Use ground truth poses if current clouds are using them
if(_currentGTPosesMap.size() && _ui->actionAnchor_clouds_to_ground_truth->isChecked())
+6 -4
View File
@@ -149,11 +149,13 @@ void MultiSessionLocWidget::updateView(
Link link = loopLinks.find(nodeId) != loopLinks.end()?loopLinks.find(nodeId)->second:Link();
std::multimap<int, cv::KeyPoint> keypoints;
for(std::multimap<int, int>::const_iterator jter=s.getWords().begin(); jter!=s.getWords().end(); ++jter)
{
if(jter->first>0 && lastSignature.getWords().find(jter->first) != lastSignature.getWords().end())
if(s.getWords().size() == s.getWordsKpts().size()) {
for(std::multimap<int, int>::const_iterator jter=s.getWords().begin(); jter!=s.getWords().end(); ++jter)
{
keypoints.insert(std::make_pair(jter->first, s.getWordsKpts()[jter->second]));
if(jter->first>0 && lastSignature.getWords().find(jter->first) != lastSignature.getWords().end())
{
keypoints.insert(std::make_pair(jter->first, s.getWordsKpts()[jter->second]));
}
}
}
+156 -23
View File
@@ -226,7 +226,7 @@ PreferencesDialog::PreferencesDialog(QWidget * parent) :
#ifndef RTABMAP_MSCKF_VIO
_ui->odom_strategy->setItemData(8, 0, Qt::UserRole - 1);
#endif
#ifndef RTABMAP_VINS
#ifndef RTABMAP_VINS_FUSION
_ui->odom_strategy->setItemData(9, 0, Qt::UserRole - 1);
#endif
#ifndef RTABMAP_OPENVINS
@@ -238,6 +238,9 @@ PreferencesDialog::PreferencesDialog(QWidget * parent) :
#ifndef RTABMAP_OPEN3D
_ui->odom_strategy->setItemData(12, 0, Qt::UserRole - 1);
#endif
#ifndef RTABMAP_CUVSLAM
_ui->odom_strategy->setItemData(13, 0, Qt::UserRole - 1);
#endif
#if CV_MAJOR_VERSION < 3
_ui->stereosgbm_mode->setItemData(2, 0, Qt::UserRole - 1);
@@ -291,6 +294,10 @@ PreferencesDialog::PreferencesDialog(QWidget * parent) :
_ui->comboBox_detector_strategy->setItemData(11, 0, Qt::UserRole - 1);
_ui->vis_feature_detector->setItemData(11, 0, Qt::UserRole - 1);
#endif
#if !defined(RTABMAP_TORCH) || !defined(RTABMAP_PYTHON)
_ui->comboBox_detector_strategy->setItemData(16, 0, Qt::UserRole - 1);
_ui->vis_feature_detector->setItemData(16, 0, Qt::UserRole - 1);
#endif
#ifndef RTABMAP_PYTHON
_ui->comboBox_detector_strategy->setItemData(15, 0, Qt::UserRole - 1);
@@ -398,6 +405,10 @@ PreferencesDialog::PreferencesDialog(QWidget * parent) :
{
_ui->comboBox_cameraRGBD->setItemData(kSrcK4A - kSrcRGBD, 0, Qt::UserRole - 1);
}
if (!CameraOrbbecSDK::available())
{
_ui->comboBox_cameraRGBD->setItemData(kSrcOrbbecSDK - kSrcRGBD, 0, Qt::UserRole - 1);
}
if (!CameraRealSense::available())
{
_ui->comboBox_cameraRGBD->setItemData(kSrcRealSense - kSrcRGBD, 0, Qt::UserRole - 1);
@@ -767,19 +778,39 @@ PreferencesDialog::PreferencesDialog(QWidget * parent) :
connect(_ui->openni2_hshift, SIGNAL(valueChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->openni2_vshift, SIGNAL(valueChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->openni2_depth_decimation, SIGNAL(valueChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->comboBox_freenect2Format, SIGNAL(currentIndexChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->doubleSpinBox_freenect2MinDepth, SIGNAL(valueChanged(double)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->doubleSpinBox_freenect2MaxDepth, SIGNAL(valueChanged(double)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->checkBox_freenect2BilateralFiltering, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->checkBox_freenect2EdgeAwareFiltering, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->checkBox_freenect2NoiseFiltering, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->lineEdit_freenect2Pipeline, SIGNAL(textChanged(const QString &)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->comboBox_k4w2Format, SIGNAL(currentIndexChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->comboBox_k4a_rgb_resolution, SIGNAL(currentIndexChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->comboBox_k4a_framerate, SIGNAL(currentIndexChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->comboBox_k4a_depth_resolution, SIGNAL(currentIndexChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->checkbox_k4a_irDepth, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->lineEdit_k4a_mkv, SIGNAL(textChanged(const QString &)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->source_checkBox_useMKVStamps, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->spinBox_orbbec_sdk_color_width, SIGNAL(valueChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->spinBox_orbbec_sdk_color_height, SIGNAL(valueChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->spinBox_orbbec_sdk_depth_width, SIGNAL(valueChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->spinBox_orbbec_sdk_depth_height, SIGNAL(valueChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->checkBox_orbbec_sdk_color_rectification, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->checkBox_orbbec_sdk_imu, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->checkBox_orbbec_sdk_depth_mm, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->comboBox_realsensePresetRGB, SIGNAL(currentIndexChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->comboBox_realsensePresetDepth, SIGNAL(currentIndexChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->checkbox_realsenseOdom, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->checkbox_realsenseDepthScaledToRGBSize, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->comboBox_realsenseRGBSource, SIGNAL(currentIndexChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->checkbox_rs2_emitter, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->checkbox_rs2_irMode, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->checkbox_rs2_irDepth, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
@@ -918,6 +949,7 @@ PreferencesDialog::PreferencesDialog(QWidget * parent) :
connect(_ui->doubleSpinBox_odom_sensor_scale_factor, SIGNAL(valueChanged(double)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->doubleSpinBox_odom_sensor_wait_time, SIGNAL(valueChanged(double)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->checkBox_odom_sensor_use_as_gt, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->checkbox_passthrough_source_odom, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->comboBox_imuFilter_strategy, SIGNAL(currentIndexChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->comboBox_imuFilter_strategy, SIGNAL(currentIndexChanged(int)), _ui->stackedWidget_imuFilter, SLOT(setCurrentIndex(int)));
@@ -1005,6 +1037,7 @@ PreferencesDialog::PreferencesDialog(QWidget * parent) :
_ui->lineEdit_rgbCompressionFormat->setObjectName(Parameters::kMemImageCompressionFormat().c_str());
_ui->lineEdit_depthCompressionFormat->setObjectName(Parameters::kMemDepthCompressionFormat().c_str());
_ui->general_checkBox_keepDescriptors->setObjectName(Parameters::kMemRawDescriptorsKept().c_str());
_ui->general_checkBox_loadVisualLocalFeaturesOnInit->setObjectName(Parameters::kMemLoadVisualLocalFeaturesOnInit().c_str());
_ui->general_checkBox_saveDepth16bits->setObjectName(Parameters::kMemSaveDepth16Format().c_str());
_ui->general_checkBox_compressionParallelized->setObjectName(Parameters::kMemCompressionParallelized().c_str());
_ui->general_checkBox_reduceGraph->setObjectName(Parameters::kMemReduceGraph().c_str());
@@ -1079,6 +1112,8 @@ PreferencesDialog::PreferencesDialog(QWidget * parent) :
_ui->lineEdit_dictionaryPath->setObjectName(Parameters::kKpDictionaryPath().c_str());
connect(_ui->toolButton_dictionaryPath, SIGNAL(clicked()), this, SLOT(changeDictionaryPath()));
_ui->checkBox_kp_newWordsComparedTogether->setObjectName(Parameters::kKpNewWordsComparedTogether().c_str());
_ui->checkBox_kp_flannIndexSaved->setObjectName(Parameters::kKpFlannIndexSaved().c_str());
_ui->checkBox_kp_serializeWithChecksum->setObjectName(Parameters::kKpSerializeWithChecksum().c_str());
_ui->subpix_winSize_kp->setObjectName(Parameters::kKpSubPixWinSize().c_str());
_ui->subpix_iterations_kp->setObjectName(Parameters::kKpSubPixIterations().c_str());
_ui->subpix_eps_kp->setObjectName(Parameters::kKpSubPixEps().c_str());
@@ -1166,6 +1201,16 @@ PreferencesDialog::PreferencesDialog(QWidget * parent) :
_ui->spinBox_sptorch_minDistance->setObjectName(Parameters::kSuperPointNMSRadius().c_str());
_ui->checkBox_sptorch_cuda->setObjectName(Parameters::kSuperPointCuda().c_str());
// SuperPoint Rpautrat
_ui->lineEdit_sprpautrat_weights_path->setObjectName(Parameters::kSuperPointRpautratWeightsPath().c_str());
connect(_ui->toolButton_sprpautrat_weights_path, SIGNAL(clicked()), this, SLOT(changeSuperPointRpautratWeightsPath()));
_ui->lineEdit_sprpautrat_model_path->setObjectName(Parameters::kSuperPointRpautratModelPath().c_str());
connect(_ui->toolButton_sprpautrat_model_path, SIGNAL(clicked()), this, SLOT(changeSuperPointRpautratModelPath()));
_ui->doubleSpinBox_sprpautrat_threshold->setObjectName(Parameters::kSuperPointRpautratThreshold().c_str());
_ui->checkBox_sprpautrat_nms->setObjectName(Parameters::kSuperPointRpautratNMS().c_str());
_ui->spinBox_sprpautrat_minDistance->setObjectName(Parameters::kSuperPointRpautratNMSRadius().c_str());
_ui->checkBox_sprpautrat_cuda->setObjectName(Parameters::kSuperPointRpautratCuda().c_str());
// PyMatcher
_ui->lineEdit_pymatcher_path->setObjectName(Parameters::kPyMatcherPath().c_str());
connect(_ui->toolButton_pymatcher_path, SIGNAL(clicked()), this, SLOT(changePyMatcherPath()));
@@ -1553,8 +1598,8 @@ PreferencesDialog::PreferencesDialog(QWidget * parent) :
_ui->OdomMSCKFInitCovExTrans->setObjectName(Parameters::kOdomMSCKFInitCovExTrans().c_str());
// Odometry VINS
_ui->lineEdit_OdomVinsPath->setObjectName(Parameters::kOdomVINSConfigPath().c_str());
connect(_ui->toolButton_OdomVinsPath, SIGNAL(clicked()), this, SLOT(changeOdometryVINSConfigPath()));
_ui->lineEdit_OdomVinsFusionPath->setObjectName(Parameters::kOdomVINSFusionConfigPath().c_str());
connect(_ui->toolButton_OdomVinsFusionPath, SIGNAL(clicked()), this, SLOT(changeOdometryVINSFusionConfigPath()));
// Odometry OpenVINS
_ui->checkBox_OdomOpenVINSUseStereo->setObjectName(Parameters::kOdomOpenVINSUseStereo().c_str());
@@ -1631,12 +1676,14 @@ PreferencesDialog::PreferencesDialog(QWidget * parent) :
_ui->stereo_flow_eps->setObjectName(Parameters::kStereoEps().c_str());
_ui->stereo_opticalFlow->setObjectName(Parameters::kStereoOpticalFlow().c_str());
_ui->stereo_flow_gpu->setObjectName(Parameters::kStereoGpu().c_str());
// Odometry Open3D
_ui->odom_open3d_method->setObjectName(Parameters::kOdomOpen3DMethod().c_str());
_ui->odom_open3d_max_depth->setObjectName(Parameters::kOdomOpen3DMaxDepth().c_str());
// Odometry CuVSLAM
_ui->odom_cuvslam_multicam_mode->setObjectName(Parameters::kOdomCuVSLAMMulticamMode().c_str());
//StereoDense
_ui->comboBox_stereoDense_strategy->setObjectName(Parameters::kStereoDenseStrategy().c_str());
connect(_ui->comboBox_stereoDense_strategy, SIGNAL(currentIndexChanged(int)), _ui->stackedWidget_stereoDense, SLOT(setCurrentIndex(int)));
@@ -2228,6 +2275,13 @@ void PreferencesDialog::resetSettings(QGroupBox * groupBox)
_ui->comboBox_k4a_depth_resolution->setCurrentIndex(2);
_ui->checkbox_k4a_irDepth->setChecked(false);
_ui->lineEdit_k4a_mkv->clear();
_ui->spinBox_orbbec_sdk_color_width->setValue(800);
_ui->spinBox_orbbec_sdk_color_height->setValue(600);
_ui->spinBox_orbbec_sdk_depth_width->setValue(800);
_ui->spinBox_orbbec_sdk_depth_height->setValue(600);
_ui->checkBox_orbbec_sdk_color_rectification->setChecked(false);
_ui->checkBox_orbbec_sdk_imu->setChecked(true);
_ui->checkBox_orbbec_sdk_depth_mm->setChecked(true);
_ui->source_checkBox_useMKVStamps->setChecked(true);
_ui->lineEdit_cameraRGBDImages_path_rgb->setText("");
_ui->lineEdit_cameraRGBDImages_path_depth->setText("");
@@ -2306,6 +2360,7 @@ void PreferencesDialog::resetSettings(QGroupBox * groupBox)
_ui->doubleSpinBox_odom_sensor_scale_factor->setValue(1);
_ui->doubleSpinBox_odom_sensor_wait_time->setValue(100);
_ui->checkBox_odom_sensor_use_as_gt->setChecked(false);
_ui->checkbox_passthrough_source_odom->setChecked(false);
_ui->comboBox_imuFilter_strategy->setCurrentIndex(2);
_ui->doubleSpinBox_imuFilterMadgwickGain->setValue(Parameters::defaultImuFilterMadgwickGain());
@@ -2713,6 +2768,16 @@ void PreferencesDialog::readCameraSettings(const QString & filePath)
_ui->source_checkBox_useMKVStamps->setChecked(settings.value("useMkvStamps", _ui->source_checkBox_useMKVStamps->isChecked()).toBool());
settings.endGroup(); // K4A
settings.beginGroup("OrbbecSDK");
_ui->spinBox_orbbec_sdk_color_width->setValue(settings.value("color_width", _ui->spinBox_orbbec_sdk_color_width->value()).toInt());
_ui->spinBox_orbbec_sdk_color_height->setValue(settings.value("color_height", _ui->spinBox_orbbec_sdk_color_height->value()).toInt());
_ui->spinBox_orbbec_sdk_depth_width->setValue(settings.value("depth_width", _ui->spinBox_orbbec_sdk_depth_width->value()).toInt());
_ui->spinBox_orbbec_sdk_depth_height->setValue(settings.value("depth_height", _ui->spinBox_orbbec_sdk_depth_height->value()).toInt());
_ui->checkBox_orbbec_sdk_color_rectification->setChecked(settings.value("rectify_color", _ui->checkBox_orbbec_sdk_color_rectification->isChecked()).toBool());
_ui->checkBox_orbbec_sdk_imu->setChecked(settings.value("enable_imu", _ui->checkBox_orbbec_sdk_imu->isChecked()).toBool());
_ui->checkBox_orbbec_sdk_depth_mm->setChecked(settings.value("depth_mm", _ui->checkBox_orbbec_sdk_depth_mm->isChecked()).toBool());
settings.endGroup(); // Orbbec SDK
settings.beginGroup("RealSense");
_ui->comboBox_realsensePresetRGB->setCurrentIndex(settings.value("presetRGB", _ui->comboBox_realsensePresetRGB->currentIndex()).toInt());
_ui->comboBox_realsensePresetDepth->setCurrentIndex(settings.value("presetDepth", _ui->comboBox_realsensePresetDepth->currentIndex()).toInt());
@@ -2832,6 +2897,7 @@ void PreferencesDialog::readCameraSettings(const QString & filePath)
_ui->doubleSpinBox_odom_sensor_scale_factor->setValue(settings.value("odom_sensor_scale_factor", _ui->doubleSpinBox_odom_sensor_scale_factor->value()).toDouble());
_ui->doubleSpinBox_odom_sensor_wait_time->setValue(settings.value("odom_sensor_wait_time", _ui->doubleSpinBox_odom_sensor_wait_time->value()).toDouble());
_ui->checkBox_odom_sensor_use_as_gt->setChecked(settings.value("odom_sensor_odom_as_gt", _ui->checkBox_odom_sensor_use_as_gt->isChecked()).toBool());
_ui->checkbox_passthrough_source_odom->setChecked(settings.value("odom_sensor_as_guess", _ui->checkbox_passthrough_source_odom->isChecked()).toBool());
settings.endGroup(); // OdomSensor
settings.beginGroup("UsbCam");
@@ -3319,6 +3385,16 @@ void PreferencesDialog::writeCameraSettings(const QString & filePath) const
settings.setValue("useMkvStamps", _ui->source_checkBox_useMKVStamps->isChecked());
settings.endGroup(); // K4A
settings.beginGroup("OrbbecSDK");
settings.setValue("color_width", _ui->spinBox_orbbec_sdk_color_width->value());
settings.setValue("color_height", _ui->spinBox_orbbec_sdk_color_height->value());
settings.setValue("depth_width", _ui->spinBox_orbbec_sdk_depth_width->value());
settings.setValue("depth_height", _ui->spinBox_orbbec_sdk_depth_height->value());
settings.setValue("rectify_color", _ui->checkBox_orbbec_sdk_color_rectification->isChecked());
settings.setValue("enable_imu", _ui->checkBox_orbbec_sdk_imu->isChecked());
settings.setValue("depth_mm", _ui->checkBox_orbbec_sdk_depth_mm->isChecked());
settings.endGroup(); // Orbbec SDK
settings.beginGroup("RealSense");
settings.setValue("presetRGB", _ui->comboBox_realsensePresetRGB->currentIndex());
settings.setValue("presetDepth", _ui->comboBox_realsensePresetDepth->currentIndex());
@@ -3436,6 +3512,7 @@ void PreferencesDialog::writeCameraSettings(const QString & filePath) const
settings.setValue("odom_sensor_scale_factor", _ui->doubleSpinBox_odom_sensor_scale_factor->value());
settings.setValue("odom_sensor_wait_time", _ui->doubleSpinBox_odom_sensor_wait_time->value());
settings.setValue("odom_sensor_odom_as_gt", _ui->checkBox_odom_sensor_use_as_gt->isChecked());
settings.setValue("odom_sensor_as_guess", _ui->checkbox_passthrough_source_odom->isChecked());
settings.endGroup(); // OdomSensor
settings.beginGroup("UsbCam");
@@ -3730,15 +3807,6 @@ bool PreferencesDialog::validateForm()
_ui->odom_f2m_bundleStrategy->setCurrentIndex(0);
}
// verify that Robust and Reject threshold are not set at the same time
if(_ui->graphOptimization_robust->isChecked() && _ui->graphOptimization_maxError->value()>0.0)
{
QMessageBox::warning(this, tr("Parameter warning"),
tr("Robust graph optimization and maximum optimization error threshold cannot be "
"both used at the same time. Disabling robust optimization."));
_ui->graphOptimization_robust->setChecked(false);
}
//verify binary features and nearest neighbor
// BOW dictionary type
if(_ui->comboBox_dictionary_strategy->currentIndex() == VWDictionary::kNNFlannLSH && _ui->comboBox_detector_strategy->currentIndex() <= 1)
@@ -5473,9 +5541,10 @@ void PreferencesDialog::updateOdometryStackedIndex(int index)
_ui->groupBox_odomOKVIS->setVisible(index==6);
_ui->groupBox_odomLOAM->setVisible(index==7);
_ui->groupBox_odomMSCKF->setVisible(index==8);
_ui->groupBox_odomVINS->setVisible(index==9);
_ui->groupBox_odomVINSFusion->setVisible(index==9);
_ui->groupBox_odomOpenVINS->setVisible(index==10);
_ui->groupBox_odomOpen3D->setVisible(index==12);
_ui->groupBox_odomCuvslam->setVisible(index==13);
}
void PreferencesDialog::useOdomFeatures()
@@ -5564,20 +5633,20 @@ void PreferencesDialog::changeOdometryOKVISConfigPath()
}
}
void PreferencesDialog::changeOdometryVINSConfigPath()
void PreferencesDialog::changeOdometryVINSFusionConfigPath()
{
QString path;
if(_ui->lineEdit_OdomVinsPath->text().isEmpty())
if(_ui->lineEdit_OdomVinsFusionPath->text().isEmpty())
{
path = QFileDialog::getOpenFileName(this, tr("VINS-Fusion Config"), this->getWorkingDirectory(), tr("VINS-Fusion config (*.yaml)"));
}
else
{
path = QFileDialog::getOpenFileName(this, tr("VINS-Fusion Config"), _ui->lineEdit_OdomVinsPath->text(), tr("VINS-Fusion config (*.yaml)"));
path = QFileDialog::getOpenFileName(this, tr("VINS-Fusion Config"), _ui->lineEdit_OdomVinsFusionPath->text(), tr("VINS-Fusion config (*.yaml)"));
}
if(!path.isEmpty())
{
_ui->lineEdit_OdomVinsPath->setText(path);
_ui->lineEdit_OdomVinsFusionPath->setText(path);
}
}
@@ -5649,6 +5718,41 @@ void PreferencesDialog::changeSuperPointModelPath()
}
}
void PreferencesDialog::changeSuperPointRpautratWeightsPath()
{
QString path;
if(_ui->lineEdit_sprpautrat_weights_path->text().isEmpty())
{
path = QFileDialog::getOpenFileName(this, tr("Select SuperPoint weights"), this->getWorkingDirectory(), tr("SuperPoint weights (*.pth)"));
}
else
{
path = QFileDialog::getOpenFileName(this, tr("Select SuperPoint weights"), _ui->lineEdit_sprpautrat_weights_path->text(), tr("SuperPoint weights (*.pth)"));
}
if(!path.isEmpty())
{
_ui->lineEdit_sprpautrat_weights_path->setText(path);
}
}
void PreferencesDialog::changeSuperPointRpautratModelPath()
{
QString path;
if(_ui->lineEdit_sprpautrat_model_path->text().isEmpty())
{
path = QFileDialog::getOpenFileName(this, tr("Select SuperPoint Python Model"), this->getWorkingDirectory(), tr("SuperPoint Python Model (*.py)"));
}
else
{
path = QFileDialog::getOpenFileName(this, tr("Select SuperPoint Python Model"), _ui->lineEdit_sprpautrat_model_path->text(), tr("SuperPoint Python Model (*.py)"));
}
if(!path.isEmpty())
{
_ui->lineEdit_sprpautrat_model_path->setText(path);
}
}
void PreferencesDialog::changePyMatcherPath()
{
QString path;
@@ -5731,6 +5835,7 @@ void PreferencesDialog::updateSourceGrpVisibility()
_ui->comboBox_cameraRGBD->currentIndex() == kSrcFreenect2-kSrcRGBD ||
_ui->comboBox_cameraRGBD->currentIndex() == kSrcK4W2 - kSrcRGBD ||
_ui->comboBox_cameraRGBD->currentIndex() == kSrcK4A - kSrcRGBD ||
_ui->comboBox_cameraRGBD->currentIndex() == kSrcOrbbecSDK - kSrcRGBD ||
_ui->comboBox_cameraRGBD->currentIndex() == kSrcRealSense - kSrcRGBD ||
_ui->comboBox_cameraRGBD->currentIndex() == kSrcRGBDImages-kSrcRGBD ||
_ui->comboBox_cameraRGBD->currentIndex() == kSrcOpenNI_PCL-kSrcRGBD ||
@@ -5740,6 +5845,7 @@ void PreferencesDialog::updateSourceGrpVisibility()
_ui->groupBox_freenect2->setVisible(_ui->comboBox_sourceType->currentIndex() == 0 && _ui->comboBox_cameraRGBD->currentIndex() == kSrcFreenect2-kSrcRGBD);
_ui->groupBox_k4w2->setVisible(_ui->comboBox_sourceType->currentIndex() == 0 && _ui->comboBox_cameraRGBD->currentIndex() == kSrcK4W2 - kSrcRGBD);
_ui->groupBox_k4a->setVisible(_ui->comboBox_sourceType->currentIndex() == 0 && _ui->comboBox_cameraRGBD->currentIndex() == kSrcK4A - kSrcRGBD);
_ui->groupBox_orbbec_sdk->setVisible(_ui->comboBox_sourceType->currentIndex() == 0 && _ui->comboBox_cameraRGBD->currentIndex() == kSrcOrbbecSDK - kSrcRGBD);
_ui->groupBox_realsense->setVisible(_ui->comboBox_sourceType->currentIndex() == 0 && _ui->comboBox_cameraRGBD->currentIndex() == kSrcRealSense - kSrcRGBD);
_ui->groupBox_realsense2->setVisible(_ui->comboBox_sourceType->currentIndex() == 0 && _ui->comboBox_cameraRGBD->currentIndex() == kSrcRealSense2 - kSrcRGBD);
_ui->groupBox_cameraRGBDImages->setVisible(_ui->comboBox_sourceType->currentIndex() == 0 && _ui->comboBox_cameraRGBD->currentIndex() == kSrcRGBDImages-kSrcRGBD);
@@ -5783,7 +5889,7 @@ void PreferencesDialog::updateSourceGrpVisibility()
// Odom Sensor Group
_ui->frame_visual_odometry_sensor->setVisible(getOdomSourceDriver() != kSrcUndef); // Not Lidar None
_ui->groupBox_odom_sensor->setVisible(_ui->comboBox_sourceType->currentIndex() != 3); // Don't show when database is selected
_ui->comboBox_odom_sensor->setEnabled(_ui->comboBox_sourceType->currentIndex() != 3); // Don't enable when database is selected
// Lidar Sensor Group
_ui->comboBox_lidar_src->setEnabled(_ui->comboBox_sourceType->currentIndex() != 3); // Disable if database input
@@ -5809,6 +5915,7 @@ void PreferencesDialog::updateSourceGrpVisibility()
(_ui->comboBox_sourceType->currentIndex() == 2 && _ui->source_comboBox_image_type->currentIndex() == kSrcImages-kSrcRGB) ||
(_ui->comboBox_sourceType->currentIndex() == 0 && _ui->comboBox_cameraRGBD->currentIndex() == kSrcFreenect - kSrcRGBD) || //Kinect360
(_ui->comboBox_sourceType->currentIndex() == 0 && _ui->comboBox_cameraRGBD->currentIndex() == kSrcK4A - kSrcRGBD) || //K4A
(_ui->comboBox_sourceType->currentIndex() == 0 && _ui->comboBox_cameraRGBD->currentIndex() == kSrcOrbbecSDK - kSrcRGBD) || //Orbbec SDK
(_ui->comboBox_sourceType->currentIndex() == 0 && _ui->comboBox_cameraRGBD->currentIndex() == kSrcRealSense2 - kSrcRGBD) || //D435i
(_ui->comboBox_sourceType->currentIndex() == 0 && _ui->comboBox_cameraRGBD->currentIndex() == kSrcSeerSense - kSrcRGBD) ||
(_ui->comboBox_sourceType->currentIndex() == 1 && _ui->comboBox_cameraStereo->currentIndex() == kSrcStereoRealSense2 - kSrcStereo) || //T265
@@ -5816,7 +5923,6 @@ void PreferencesDialog::updateSourceGrpVisibility()
(_ui->comboBox_sourceType->currentIndex() == 1 && _ui->comboBox_cameraStereo->currentIndex() == kSrcStereoMyntEye - kSrcStereo) || // MYNT EYE S
(_ui->comboBox_sourceType->currentIndex() == 1 && _ui->comboBox_cameraStereo->currentIndex() == kSrcStereoZedOC - kSrcStereo) ||
(_ui->comboBox_sourceType->currentIndex() == 1 && _ui->comboBox_cameraStereo->currentIndex() == kSrcStereoDepthAI - kSrcStereo));
_ui->frame_imu_filtering->setVisible(getIMUFilteringStrategy() > 0); // Not None
_ui->stackedWidget_imuFilter->setVisible(_ui->comboBox_imuFilter_strategy->currentIndex() > 0);
_ui->groupBox_madgwickfilter->setVisible(_ui->comboBox_imuFilter_strategy->currentIndex() == 1);
_ui->groupBox_complementaryfilter->setVisible(_ui->comboBox_imuFilter_strategy->currentIndex() == 2);
@@ -5917,6 +6023,10 @@ bool PreferencesDialog::isOdomDisabled() const
{
return _ui->checkbox_odomDisabled->isChecked();
}
bool PreferencesDialog::isOdomAsGuessEnabled() const
{
return _ui->checkbox_passthrough_source_odom->isChecked();
}
bool PreferencesDialog::isOdomSensorAsGt() const
{
return _ui->checkBox_odom_sensor_use_as_gt->isChecked();
@@ -6637,6 +6747,26 @@ Camera * PreferencesDialog::createCamera(
_ui->comboBox_k4a_framerate->currentIndex(),
_ui->comboBox_k4a_depth_resolution->currentIndex());
}
else if (driver == kSrcOrbbecSDK)
{
camera = new CameraOrbbecSDK(
device.toStdString(),
_ui->spinBox_orbbec_sdk_color_width->value(),
_ui->spinBox_orbbec_sdk_color_height->value(),
_ui->spinBox_orbbec_sdk_depth_width->value(),
_ui->spinBox_orbbec_sdk_depth_height->value(),
this->getGeneralInputRate(),
this->getSourceLocalTransform());
((CameraOrbbecSDK*)camera)->enableColorRectification(_ui->checkBox_orbbec_sdk_color_rectification->isChecked());
((CameraOrbbecSDK*)camera)->enableImu(_ui->checkBox_orbbec_sdk_imu->isChecked());
((CameraOrbbecSDK*)camera)->enableDepthMM(_ui->checkBox_orbbec_sdk_depth_mm->isChecked());
camera->setInterIMUPublishing(
_ui->checkbox_publishInterIMU->isChecked(),
_ui->checkbox_publishInterIMU->isChecked() && getIMUFilteringStrategy()>0?
IMUFilter::create((IMUFilter::Type)(getIMUFilteringStrategy()-1), this->getAllParameters()):0,
getIMUFilteringBaseFrameConversion());
}
else if (driver == kSrcRealSense)
{
if(useRawImages && _ui->comboBox_realsenseRGBSource->currentIndex()!=2)
@@ -6677,7 +6807,8 @@ Camera * PreferencesDialog::createCamera(
camera->setInterIMUPublishing(
_ui->checkbox_publishInterIMU->isChecked(),
_ui->checkbox_publishInterIMU->isChecked() && getIMUFilteringStrategy()>0?
IMUFilter::create((IMUFilter::Type)(getIMUFilteringStrategy()-1), this->getAllParameters()):0);
IMUFilter::create((IMUFilter::Type)(getIMUFilteringStrategy()-1), this->getAllParameters()):0,
getIMUFilteringBaseFrameConversion());
if(driver == kSrcStereoRealSense2)
{
((CameraRealSense2*)camera)->setImagesRectified((_ui->checkBox_stereo_rectify->isEnabled() && _ui->checkBox_stereo_rectify->isChecked()) && !useRawImages);
@@ -6895,7 +7026,8 @@ Camera * PreferencesDialog::createCamera(
camera->setInterIMUPublishing(
_ui->checkbox_publishInterIMU->isChecked(),
_ui->checkbox_publishInterIMU->isChecked() && getIMUFilteringStrategy()>0?
IMUFilter::create((IMUFilter::Type)(getIMUFilteringStrategy()-1), this->getAllParameters()):0);
IMUFilter::create((IMUFilter::Type)(getIMUFilteringStrategy()-1), this->getAllParameters()):0,
getIMUFilteringBaseFrameConversion());
((CameraStereoZed*)camera)->setRightGrayScale(_ui->checkBox_stereo_rightGrayScale->isChecked());
}
else if (driver == kSrcStereoZedOC)
@@ -6944,7 +7076,8 @@ Camera * PreferencesDialog::createCamera(
camera->setInterIMUPublishing(
_ui->checkbox_publishInterIMU->isChecked(),
_ui->checkbox_publishInterIMU->isChecked() && getIMUFilteringStrategy()>0?
IMUFilter::create((IMUFilter::Type)(getIMUFilteringStrategy()-1), this->getAllParameters()):0);
IMUFilter::create((IMUFilter::Type)(getIMUFilteringStrategy()-1), this->getAllParameters()):0,
getIMUFilteringBaseFrameConversion());
}
else if(driver == kSrcUsbDevice)
{
+1 -1
View File
@@ -101,7 +101,7 @@ void ProgressDialog::setCancelButtonVisible(bool visible)
void ProgressDialog::appendText(const QString & text, const QColor & color)
{
UDEBUG(text.toStdString().c_str());
//UDEBUG(text.toStdString().c_str());
_text->setText(text);
QString html = tr("<html><font color=\"#999999\">%1 </font><font color=\"%2\">%3</font></html>").arg(QTime::currentTime().toString("HH:mm:ss")).arg(color.name()).arg(text);
_detailedText->append(html);
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

+436 -357
View File
@@ -17,7 +17,7 @@
<enum>Qt::LeftToRight</enum>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QVBoxLayout" name="verticalLayout_6" stretch="1,0,0">
<layout class="QVBoxLayout" name="verticalLayout_15" stretch="1,0,0">
<property name="spacing">
<number>0</number>
</property>
@@ -44,7 +44,7 @@
</layout>
</item>
<item>
<layout class="QGridLayout" name="gridLayout_11" rowstretch="1,0">
<layout class="QGridLayout" name="gridLayout_11">
<property name="spacing">
<number>0</number>
</property>
@@ -776,71 +776,90 @@
</layout>
</item>
<item row="1" column="1">
<widget class="QWidget" name="widget_imageControls_B">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="leftMargin">
<number>12</number>
</property>
<property name="topMargin">
<number>12</number>
</property>
<property name="rightMargin">
<number>12</number>
</property>
<property name="bottomMargin">
<number>12</number>
</property>
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="label_5">
<property name="text">
<string>Index :</string>
</property>
<widget class="QWidget" name="widget_imageControls_B" native="true">
<layout class="QVBoxLayout" name="verticalLayout_6">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="leftMargin">
<number>12</number>
</property>
<property name="topMargin">
<number>12</number>
</property>
<property name="rightMargin">
<number>12</number>
</property>
<property name="bottomMargin">
<number>12</number>
</property>
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="label_5">
<property name="text">
<string>Index :</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_4">
<property name="text">
<string>Id :</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QSpinBox" name="spinBox_indexB">
<property name="frame">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_idB">
<property name="text">
<string>idB</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QSlider" name="horizontalSlider_B">
<property name="focusPolicy">
<enum>Qt::ClickFocus</enum>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="tickPosition">
<enum>QSlider::TicksAbove</enum>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_4">
<property name="text">
<string>Id :</string>
</property>
</widget>
</item>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QSpinBox" name="spinBox_indexB">
<property name="frame">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_idB">
<property name="text">
<string>idB</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QSlider" name="horizontalSlider_B">
<property name="focusPolicy">
<enum>Qt::ClickFocus</enum>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="tickPosition">
<enum>QSlider::TicksAbove</enum>
</property>
</widget>
</item>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</item>
@@ -1252,322 +1271,382 @@
<widget class="rtabmap::GraphViewer" name="graphViewer"/>
</item>
<item>
<widget class="QWidget" name="widget_graphControl">
<layout class="QVBoxLayout" name="verticalLayout_91">
<widget class="QWidget" name="widget_graphControl" native="true">
<layout class="QVBoxLayout" name="verticalLayout_61">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_15">
<layout class="QVBoxLayout" name="verticalLayout_91">
<item>
<widget class="QLabel" name="label_rotation">
<property name="text">
<string>0.0 deg</string>
</property>
</widget>
</item>
<item>
<widget class="QSlider" name="horizontalSlider_rotation">
<property name="focusPolicy">
<enum>Qt::ClickFocus</enum>
</property>
<property name="minimum">
<number>-1799</number>
</property>
<property name="maximum">
<number>1800</number>
</property>
<property name="sliderPosition">
<number>0</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="tickPosition">
<enum>QSlider::TicksAbove</enum>
</property>
<property name="tickInterval">
<number>100</number>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_applyRotation">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The rotation will be applied temporary to optimized global graph. To save it to database, do File-&amp;gt;&amp;quot;Regenerate optimized 2D map...&amp;quot;.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Apply Rotation</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QLabel" name="label_iterations">
<property name="text">
<string>#</string>
</property>
</widget>
</item>
<item>
<widget class="QSlider" name="horizontalSlider_iterations">
<property name="focusPolicy">
<enum>Qt::ClickFocus</enum>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="tickPosition">
<enum>QSlider::TicksAbove</enum>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="comboBox_optimizationFlavor">
<property name="sizeAdjustPolicy">
<enum>QComboBox::AdjustToContents</enum>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_15">
<item>
<widget class="QLabel" name="label_rotation">
<property name="text">
<string>Global Iterative</string>
<string>0.0 deg</string>
</property>
</widget>
</item>
<item>
<property name="text">
<string>Global Full</string>
<widget class="QSlider" name="horizontalSlider_rotation">
<property name="focusPolicy">
<enum>Qt::ClickFocus</enum>
</property>
<property name="minimum">
<number>-1799</number>
</property>
<property name="maximum">
<number>1800</number>
</property>
<property name="sliderPosition">
<number>0</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="tickPosition">
<enum>QSlider::TicksAbove</enum>
</property>
<property name="tickInterval">
<number>100</number>
</property>
</widget>
</item>
<item>
<property name="text">
<string>Local Optimized</string>
<widget class="QPushButton" name="pushButton_applyRotation">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The rotation will be applied temporary to optimized global graph. To save it to database, do File-&amp;gt;&amp;quot;Regenerate optimized 2D map...&amp;quot;.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Apply Rotation</string>
</property>
</widget>
</item>
</widget>
</layout>
</item>
</layout>
</item>
<item>
<layout class="QGridLayout" name="gridLayout_5" columnstretch="0,1">
<item row="2" column="1">
<widget class="QLabel" name="label_alignPosesWithGroundTruth">
<property name="text">
<string>Align poses with ground truth</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QCheckBox" name="checkBox_ignoreIntermediateNodes">
<property name="text">
<string/>
</property>
<property name="checked">
<bool>false</bool>
</property>
</widget>
</item>
<item row="0" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_7" stretch="0,0,1">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QLabel" name="label_optimizeFrom">
<widget class="QLabel" name="label_iterations">
<property name="text">
<string>Root</string>
<string>#</string>
</property>
</widget>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBox_spanAllMaps">
<widget class="QSlider" name="horizontalSlider_iterations">
<property name="focusPolicy">
<enum>Qt::ClickFocus</enum>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="tickPosition">
<enum>QSlider::TicksAbove</enum>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="comboBox_optimizationFlavor">
<property name="sizeAdjustPolicy">
<enum>QComboBox::AdjustToContents</enum>
</property>
<item>
<property name="text">
<string>Global Iterative</string>
</property>
</item>
<item>
<property name="text">
<string>Global Full</string>
</property>
</item>
<item>
<property name="text">
<string>Local Optimized</string>
</property>
</item>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QGridLayout" name="gridLayout_5" columnstretch="0,1">
<item row="1" column="1">
<widget class="QLabel" name="label_alignPosesWithGPS">
<property name="text">
<string>Span to all maps</string>
<string>Align poses with GPS</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="8" column="1">
<widget class="QLabel" name="label_45">
<property name="text">
<string>Time grid (s)</string>
</property>
</widget>
</item>
<item row="7" column="1">
<widget class="QLabel" name="label_39">
<property name="text">
<string>Time optimization (s)</string>
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QLabel" name="label_timeOptimization">
<property name="text">
<string/>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="checkBox_alignPosesWithGPS">
<property name="text">
<string/>
</property>
<property name="checked">
<bool>true</bool>
<bool>true</bool>
</property>
</widget>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBox_wmState">
<item row="3" column="0">
<widget class="QCheckBox" name="checkBox_alignScansCloudsWithGroundTruth">
<property name="text">
<string>WM</string>
<string/>
</property>
</widget>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
<item row="9" column="0">
<widget class="QLabel" name="label_rmse">
<property name="text">
<string/>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLabel" name="label_alignPosesWithGroundTruth">
<property name="text">
<string>Align poses with ground truth</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="9" column="1">
<widget class="QLabel" name="label_rmse_title">
<property name="text">
<string>RMSE (m)</string>
</property>
</widget>
</item>
<item row="0" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_7" stretch="0,0,1">
<item>
<widget class="QLabel" name="label_optimizeFrom">
<property name="text">
<string>Root</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBox_spanAllMaps">
<property name="text">
<string>Span to all maps</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBox_wmState">
<property name="text">
<string>WM</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="0" column="0">
<widget class="QSpinBox" name="spinBox_optimizationsFrom"/>
</item>
<item row="11" column="0">
<widget class="QLabel" name="label_loopClosures">
<property name="text">
<string/>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="10" column="0">
<widget class="QLabel" name="label_poses">
<property name="text">
<string/>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QLabel" name="label_ignoreINtermediateNdoes">
<property name="text">
<string>Ignore intermediate nodes</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="label_pathLength">
<property name="text">
<string/>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="10" column="1">
<widget class="QLabel" name="label_52">
<property name="text">
<string>Poses</string>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QLabel" name="label_10">
<property name="text">
<string>Path length (m)</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLabel" name="label_alignScansCloudsWithGroundTruth">
<property name="text">
<string>Align scans/clouds with ground truth</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="11" column="1">
<widget class="QLabel" name="label_41">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;N: Neighbor&lt;/p&gt;&lt;p&gt;NM: Neighbor Merged&lt;/p&gt;&lt;p&gt;G: Global&lt;/p&gt;&lt;p&gt;LS: Local by Space (Proximity)&lt;/p&gt;&lt;p&gt;LT: Local by Time (Proximity)&lt;/p&gt;&lt;p&gt;U: User&lt;/p&gt;&lt;p&gt;P: Prior&lt;/p&gt;&lt;p&gt;LM: Landmark&lt;/p&gt;&lt;p&gt;GR: Gravity&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Links (N, NM, G, LS, LT, U, P, LM, GR)</string>
</property>
</widget>
</item>
<item row="8" column="0">
<widget class="QLabel" name="label_timeGrid">
<property name="text">
<string/>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QCheckBox" name="checkBox_ignoreIntermediateNodes">
<property name="text">
<string/>
</property>
<property name="checked">
<bool>false</bool>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QCheckBox" name="checkBox_alignPosesWithGroundTruth">
<property name="text">
<string/>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QLabel" name="label_21">
<property name="text">
<string>Env Sensor Colormap</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QComboBox" name="comboBox_env_sensor_graph_colormap">
<item>
<property name="text">
<string>Disabled</string>
</property>
</item>
<item>
<property name="text">
<string>Wifi</string>
</property>
</item>
<item>
<property name="text">
<string>Temperature</string>
</property>
</item>
<item>
<property name="text">
<string>Air Pressure</string>
</property>
</item>
<item>
<property name="text">
<string>Light</string>
</property>
</item>
<item>
<property name="text">
<string>Relative Humidity</string>
</property>
</item>
</widget>
</item>
</layout>
</item>
<item row="7" column="1">
<widget class="QLabel" name="label_45">
<property name="text">
<string>Time grid (s)</string>
</property>
</widget>
</item>
<item row="8" column="1">
<widget class="QLabel" name="label_rmse_title">
<property name="text">
<string>RMSE (m)</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QCheckBox" name="checkBox_alignScansCloudsWithGroundTruth">
<property name="text">
<string/>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="9" column="0">
<widget class="QLabel" name="label_poses">
<property name="text">
<string/>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="label_timeOptimization">
<property name="text">
<string/>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLabel" name="label_alignScansCloudsWithGroundTruth">
<property name="text">
<string>Align scans/clouds with ground truth</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="8" column="0">
<widget class="QLabel" name="label_rmse">
<property name="text">
<string/>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QLabel" name="label_timeGrid">
<property name="text">
<string/>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="10" column="1">
<widget class="QLabel" name="label_41">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;N: Neighbor&lt;/p&gt;&lt;p&gt;NM: Neighbor Merged&lt;/p&gt;&lt;p&gt;G: Global&lt;/p&gt;&lt;p&gt;LS: Local by Space (Proximity)&lt;/p&gt;&lt;p&gt;LT: Local by Time (Proximity)&lt;/p&gt;&lt;p&gt;U: User&lt;/p&gt;&lt;p&gt;P: Prior&lt;/p&gt;&lt;p&gt;LM: Landmark&lt;/p&gt;&lt;p&gt;GR: Gravity&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Links (N, NM, G, LS, LT, U, P, LM, GR)</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QLabel" name="label_10">
<property name="text">
<string>Path length (m)</string>
</property>
</widget>
</item>
<item row="9" column="1">
<widget class="QLabel" name="label_52">
<property name="text">
<string>Poses</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_pathLength">
<property name="text">
<string/>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QSpinBox" name="spinBox_optimizationsFrom"/>
</item>
<item row="10" column="0">
<widget class="QLabel" name="label_loopClosures">
<property name="text">
<string/>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QLabel" name="label_ignoreINtermediateNdoes">
<property name="text">
<string>Ignore intermediate nodes</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QLabel" name="label_39">
<property name="text">
<string>Time optimization (s)</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QCheckBox" name="checkBox_alignPosesWithGroundTruth">
<property name="text">
<string/>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="label_alignPosesWithGPS">
<property name="text">
<string>Align poses with GPS</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="checkBox_alignPosesWithGPS">
<property name="text">
<string/>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</layout>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
@@ -1805,7 +1884,7 @@
<property name="geometry">
<rect>
<x>0</x>
<y>-316</y>
<y>0</y>
<width>518</width>
<height>1071</height>
</rect>
@@ -1815,7 +1894,7 @@
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_16">
<item>
<layout class="QGridLayout" name="gridLayout_9" columnstretch="0,0">
<layout class="QGridLayout" name="gridLayout_9" columnstretch="0,1">
<item row="3" column="1">
<widget class="QLabel" name="label_octomap_empty_3">
<property name="text">
@@ -2526,8 +2605,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>296</width>
<height>272</height>
<width>222</width>
<height>306</height>
</rect>
</property>
<attribute name="label">
@@ -2700,8 +2779,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>428</width>
<height>196</height>
<width>181</width>
<height>485</height>
</rect>
</property>
<attribute name="label">
+1313 -1226
View File
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -360,7 +360,7 @@
<bool>false</bool>
</property>
<property name="minimum">
<number>2</number>
<number>3</number>
</property>
<property name="value">
<number>8</number>
@@ -373,7 +373,7 @@
<bool>false</bool>
</property>
<property name="minimum">
<number>2</number>
<number>3</number>
</property>
<property name="value">
<number>6</number>
+1 -1
View File
@@ -35,7 +35,7 @@
<number>99999</number>
</property>
<property name="value">
<number>100</number>
<number>500</number>
</property>
</widget>
</item>
+19
View File
@@ -239,9 +239,20 @@
</property>
<addaction name="actionXvisio_SeerSense"/>
</widget>
<widget class="QMenu" name="menuOrbbec_Astra_2">
<property name="title">
<string>Orbbec Astra 2</string>
</property>
<property name="icon">
<iconset resource="../GuiLib.qrc">
<normaloff>:/images/astra2.png</normaloff>:/images/astra2.png</iconset>
</property>
<addaction name="actionOrbbecSDK_astra2"/>
</widget>
<addaction name="menuKinect_for_Xbox_360"/>
<addaction name="menuXtion_PRO_LIVE"/>
<addaction name="menuOrbbec_Astra"/>
<addaction name="menuOrbbec_Astra_2"/>
<addaction name="menuSense_3D_scanner"/>
<addaction name="menuKinect_v2"/>
<addaction name="menuKinect_K4A"/>
@@ -1749,6 +1760,14 @@
<string>Xvisio</string>
</property>
</action>
<action name="actionOrbbecSDK_astra2">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Orbbec SDK</string>
</property>
</action>
</widget>
<customwidgets>
<customwidget>
File diff suppressed because it is too large Load Diff