mirror of
https://github.com/introlab/rtabmap.git
synced 2026-10-04 09:07:47 +08:00
Merge branch 'master' of github.com:introlab/rtabmap into gtest
This commit is contained in:
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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 ||
|
||||
|
||||
@@ -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
@@ -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
@@ -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())
|
||||
|
||||
@@ -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]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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
@@ -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><html><head/><body><p>The rotation will be applied temporary to optimized global graph. To save it to database, do File-&gt;&quot;Regenerate optimized 2D map...&quot;.</p></body></html></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><html><head/><body><p>The rotation will be applied temporary to optimized global graph. To save it to database, do File-&gt;&quot;Regenerate optimized 2D map...&quot;.</p></body></html></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><html><head/><body><p>N: Neighbor</p><p>NM: Neighbor Merged</p><p>G: Global</p><p>LS: Local by Space (Proximity)</p><p>LT: Local by Time (Proximity)</p><p>U: User</p><p>P: Prior</p><p>LM: Landmark</p><p>GR: Gravity</p></body></html></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><html><head/><body><p>N: Neighbor</p><p>NM: Neighbor Merged</p><p>G: Global</p><p>LS: Local by Space (Proximity)</p><p>LT: Local by Time (Proximity)</p><p>U: User</p><p>P: Prior</p><p>LM: Landmark</p><p>GR: Gravity</p></body></html></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
File diff suppressed because it is too large
Load Diff
@@ -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>
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
<number>99999</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>100</number>
|
||||
<number>500</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
||||
@@ -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>
|
||||
|
||||
+1666
-978
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user