mirror of
https://github.com/introlab/rtabmap.git
synced 2026-09-11 05:50:21 +08:00
Compare commits
19
Commits
0.21.4
...
add-pre-commit
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
85112c2cdf | ||
|
|
8657e18bda | ||
|
|
578bf0ed8f | ||
|
|
9f230f5b28 | ||
|
|
264c560a2c | ||
|
|
4ce36ef245 | ||
|
|
d0227694c5 | ||
|
|
a6d9425bce | ||
|
|
e299505a64 | ||
|
|
57b4954cb3 | ||
|
|
2577c47e77 | ||
|
|
52e1b01597 | ||
|
|
8019a2dc49 | ||
|
|
33b875ecbf | ||
|
|
c24f95a8d9 | ||
|
|
6f7e5cc97b | ||
|
|
fccf33dd96 | ||
|
|
752ca76cf5 | ||
|
|
81e249b56c |
+1
-1
@@ -19,7 +19,7 @@ init:
|
||||
install:
|
||||
# To download from google drive
|
||||
- set PATH=C:\Python38-x64;C:\Python38-x64\Scripts;%PATH%
|
||||
- ps: py -m pip --disable-pip-version-check install gdown==4.6.0
|
||||
- ps: py -m pip --disable-pip-version-check install gdown>=5.1.0
|
||||
# Qt
|
||||
- set QTDIR=C:\Qt\5.10.1\msvc2015_64
|
||||
# make sure Qt bin path is before cmake bin path to avoid copying qt5 dlls from cmake before qt installation
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
## Description
|
||||
|
||||
Please include a summary of the change and which issue is fixed (if any).
|
||||
|
||||
## Checklist:
|
||||
|
||||
- [ ] Did `pre-commit run --all-files` locally to fix any pre-commit failures on CI.
|
||||
@@ -0,0 +1,16 @@
|
||||
name: pre-commit
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- '**'
|
||||
push:
|
||||
branches: [master]
|
||||
|
||||
jobs:
|
||||
pre-commit:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-python@v3
|
||||
- uses: pre-commit/action@v3.0.1
|
||||
@@ -0,0 +1,31 @@
|
||||
# See https://pre-commit.com for more information
|
||||
# See https://pre-commit.com/hooks.html for more hooks
|
||||
|
||||
exclude: '^build/|^data/|^app/|^archive/|^cmake_modules/|^\..*'
|
||||
|
||||
repos:
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v3.2.0
|
||||
hooks:
|
||||
- id: trailing-whitespace
|
||||
- id: end-of-file-fixer
|
||||
- id: check-yaml
|
||||
- id: check-added-large-files
|
||||
|
||||
- repo: https://github.com/cheshirekow/cmake-format-precommit
|
||||
rev: v0.6.10
|
||||
hooks:
|
||||
- id: cmake-format
|
||||
- id: cmake-lint
|
||||
|
||||
- repo: https://github.com/pryorda/dockerfilelint-precommit-hooks
|
||||
rev: v0.1.0
|
||||
hooks:
|
||||
- id: dockerfilelint
|
||||
|
||||
- repo: https://github.com/pre-commit/mirrors-clang-format
|
||||
rev: v18.1.1
|
||||
hooks:
|
||||
- id: clang-format
|
||||
args: ["-style=Google", "-i"]
|
||||
|
||||
+3
-7
@@ -892,9 +892,9 @@ ENDIF()
|
||||
IF(NOT MRPT_FOUND)
|
||||
SET(MRPT "//")
|
||||
ENDIF(NOT MRPT_FOUND)
|
||||
IF(NOT CERES_FOUND)
|
||||
IF(NOT WITH_CERES OR NOT CERES_FOUND)
|
||||
SET(CERES "//")
|
||||
ENDIF(NOT CERES_FOUND)
|
||||
ENDIF(NOT WITH_CERES OR NOT CERES_FOUND)
|
||||
IF(NOT WITH_TORO)
|
||||
SET(TORO "//")
|
||||
ENDIF(NOT WITH_TORO)
|
||||
@@ -1406,12 +1406,8 @@ ELSE()
|
||||
MESSAGE(STATUS " *With GTSAM = NO (GTSAM not found)")
|
||||
ENDIF()
|
||||
|
||||
IF(CERES_FOUND)
|
||||
IF(WITH_CERES)
|
||||
IF(WITH_CERES AND CERES_FOUND)
|
||||
MESSAGE(STATUS " *With Ceres ${Ceres_VERSION} = YES (License: BSD)")
|
||||
ELSE()
|
||||
MESSAGE(STATUS " *With Ceres ${Ceres_VERSION} = YES (License: BSD, WITH_CERES=OFF but it is enabled by okvis or floam dependencies)")
|
||||
ENDIF()
|
||||
ELSEIF(NOT WITH_CERES)
|
||||
MESSAGE(STATUS " *With Ceres = NO (WITH_CERES=OFF)")
|
||||
ELSE()
|
||||
|
||||
@@ -7,7 +7,7 @@ rtabmap
|
||||
[![Downloads][downloads-image]][downloads]
|
||||
[![License][license-image]][license]
|
||||
|
||||
[release-image]: https://img.shields.io/badge/release-0.21.0-green.svg?style=flat
|
||||
[release-image]: https://img.shields.io/badge/release-0.21.4-green.svg?style=flat
|
||||
[releases]: https://github.com/introlab/rtabmap/releases
|
||||
|
||||
[downloads-image]: https://img.shields.io/github/downloads/introlab/rtabmap/total?label=downloads
|
||||
|
||||
@@ -25,13 +25,13 @@ The following image shows when we do the same localization experiment at differe
|
||||
|
||||
We provide two formats: the first one is more general and the second one is used to produce the results in this paper with RTAB-Map. Please open issue if the links are outdated.
|
||||
|
||||
* [Images](https://usherbrooke-my.sharepoint.com/:u:/g/personal/labm2414_usherbrooke_ca/EV8F4PZUxOxLhwAyEehlzKwBjF-9xNuxR32Q4mUjx5u-rA?e=eCJ3TW):
|
||||
* [Images](https://drive.google.com/file/d/1fUm1m8oW6q8qlThx7BjrBH2vrVbNQ9bQ/view?usp=drive_link):
|
||||
* `rgb`: folder containing *.jpg color camera images
|
||||
* `depth`: folder containing *.png 16bits mm depth images
|
||||
* `calib`: folder containing calibration for each color image. Each calibration contains also the transform between `device` and `camera` frames as `local_transform`.
|
||||
* `device_poses.txt`: VIO poses of each image in `device` frame
|
||||
* `camera_poses.txt`: VIO poses of each image in `camera` frame
|
||||
* [RTAB-Map Databases](https://usherbrooke-my.sharepoint.com/:u:/g/personal/labm2414_usherbrooke_ca/EU5fb0jEKzlGhPK3OWjMGLUBnDo1BRAoZwtB2czyeVLE_A?e=Y0JyXY)
|
||||
* [RTAB-Map Databases](https://drive.google.com/file/d/1TklUcTKFSrcg8b0t0U80G_IpFRMVRlY5/view?usp=drive_link)
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ public:
|
||||
private:
|
||||
virtual Transform computeTransform(SensorData & image, const Transform & guess = Transform(), OdometryInfo * info = 0);
|
||||
|
||||
bool init(const rtabmap::CameraModel & model, double stamp, bool stereo, double baseline);
|
||||
bool init(const rtabmap::CameraModel & model1, const rtabmap::CameraModel & model2, double stamp, bool stereo, double baseline);
|
||||
private:
|
||||
#if defined(RTABMAP_ORB_SLAM) and RTABMAP_ORB_SLAM == 3
|
||||
ORB_SLAM3::System * orbslam_;
|
||||
|
||||
@@ -734,7 +734,10 @@ std::vector<cv::KeyPoint> Feature2D::generateKeypoints(const cv::Mat & image, co
|
||||
cv::Rect roi(globalRoi.x + j*colSize, globalRoi.y + i*rowSize, colSize, rowSize);
|
||||
std::vector<cv::KeyPoint> subKeypoints;
|
||||
subKeypoints = this->generateKeypointsImpl(image, roi, mask);
|
||||
limitKeypoints(subKeypoints, maxFeatures);
|
||||
if (this->getType() != Feature2D::Type::kFeaturePyDetector)
|
||||
{
|
||||
limitKeypoints(subKeypoints, maxFeatures);
|
||||
}
|
||||
if(roi.x || roi.y)
|
||||
{
|
||||
// Adjust keypoint position to raw image
|
||||
|
||||
@@ -86,7 +86,7 @@ Odometry * Odometry::create(Odometry::Type & type, const ParametersMap & paramet
|
||||
break;
|
||||
case Odometry::kTypeORBSLAM:
|
||||
#if defined(RTABMAP_ORB_SLAM) and RTABMAP_ORB_SLAM == 2
|
||||
odometry = new OdometryORBSLAM(parameters);
|
||||
odometry = new OdometryORBSLAM2(parameters);
|
||||
#else
|
||||
odometry = new OdometryORBSLAM3(parameters);
|
||||
#endif
|
||||
|
||||
@@ -3027,7 +3027,7 @@ bool Rtabmap::process(
|
||||
// Landmark
|
||||
//============================================================
|
||||
std::map<int, std::set<int> > landmarksDetected; // <Landmark ID, list of nodes that saw this landmark>
|
||||
if(!signature->getLandmarks().empty())
|
||||
if(!signature->getLandmarks().empty() && !_graphOptimizer->landmarksIgnored())
|
||||
{
|
||||
bool hasGlobalLoopClosuresInOdomCache = !graph::filterLinks(_odomCacheConstraints, Link::kGlobalClosure, true).empty() || _loopClosureHypothesis.first != 0;
|
||||
UDEBUG("hasGlobalLoopClosuresInOdomCache=%d", hasGlobalLoopClosuresInOdomCache?1:0);
|
||||
@@ -3527,6 +3527,7 @@ bool Rtabmap::process(
|
||||
}
|
||||
|
||||
// update localization links
|
||||
UASSERT(uContains(optPoses, signature->id()));
|
||||
Transform newOptPoseInv = optPoses.at(signature->id()).inverse();
|
||||
for(std::multimap<int, Link>::iterator iter=localizationLinks.begin(); iter!=localizationLinks.end(); ++iter)
|
||||
{
|
||||
@@ -3539,6 +3540,7 @@ bool Rtabmap::process(
|
||||
else
|
||||
{
|
||||
// Adjust with optimized poses, this will smooth the localization
|
||||
UASSERT(uContains(optPoses, iter->first));
|
||||
Transform newT = newOptPoseInv * optPoses.at(iter->first);
|
||||
UDEBUG("Adjusted localization link %d->%d after optimization", iter->second.from(), iter->second.to());
|
||||
UDEBUG("from %s", iter->second.transform().prettyPrint().c_str());
|
||||
|
||||
@@ -103,7 +103,7 @@ bool OdometryORBSLAM3::canProcessAsyncIMU() const
|
||||
#endif
|
||||
}
|
||||
|
||||
bool OdometryORBSLAM3::init(const rtabmap::CameraModel & model, double stamp, bool stereo, double baseline)
|
||||
bool OdometryORBSLAM3::init(const rtabmap::CameraModel & model1, const rtabmap::CameraModel & model2, double stamp, bool stereo, double baseline)
|
||||
{
|
||||
#if defined(RTABMAP_ORB_SLAM) and RTABMAP_ORB_SLAM == 3
|
||||
std::string vocabularyPath;
|
||||
@@ -138,40 +138,45 @@ bool OdometryORBSLAM3::init(const rtabmap::CameraModel & model, double stamp, b
|
||||
|
||||
ofs << fixed << setprecision(13);
|
||||
|
||||
//# Camera calibration and distortion parameters (OpenCV)
|
||||
ofs << "Camera1.fx: " << model.fx() << std::endl;
|
||||
ofs << "Camera1.fy: " << model.fy() << std::endl;
|
||||
ofs << "Camera1.cx: " << model.cx() << std::endl;
|
||||
ofs << "Camera1.cy: " << model.cy() << std::endl;
|
||||
ofs << std::endl;
|
||||
for(int i=1; i<(stereo?3:2); ++i)
|
||||
{
|
||||
const CameraModel & model = i==1?model1:model2;
|
||||
|
||||
if(model.D().cols < 4)
|
||||
{
|
||||
ofs << "Camera1.k1: " << 0.0 << std::endl;
|
||||
ofs << "Camera1.k2: " << 0.0 << std::endl;
|
||||
ofs << "Camera1.p1: " << 0.0 << std::endl;
|
||||
ofs << "Camera1.p2: " << 0.0 << std::endl;
|
||||
if(!stereo)
|
||||
//# Camera calibration and distortion parameters (OpenCV)
|
||||
ofs << "Camera" << i << ".fx: " << model.fx() << std::endl;
|
||||
ofs << "Camera" << i << ".fy: " << model.fy() << std::endl;
|
||||
ofs << "Camera" << i << ".cx: " << model.cx() << std::endl;
|
||||
ofs << "Camera" << i << ".cy: " << model.cy() << std::endl;
|
||||
ofs << std::endl;
|
||||
|
||||
if(model.D().cols < 4)
|
||||
{
|
||||
ofs << "Camera1.k3: " << 0.0 << std::endl;
|
||||
ofs << "Camera" << i << ".k1: " << 0.0 << std::endl;
|
||||
ofs << "Camera" << i << ".k2: " << 0.0 << std::endl;
|
||||
ofs << "Camera" << i << ".p1: " << 0.0 << std::endl;
|
||||
ofs << "Camera" << i << ".p2: " << 0.0 << std::endl;
|
||||
if(!stereo)
|
||||
{
|
||||
ofs << "Camera" << i << ".k3: " << 0.0 << std::endl;
|
||||
}
|
||||
}
|
||||
if(model.D().cols >= 4)
|
||||
{
|
||||
ofs << "Camera" << i << ".k1: " << model.D().at<double>(0,0) << std::endl;
|
||||
ofs << "Camera" << i << ".k2: " << model.D().at<double>(0,1) << std::endl;
|
||||
ofs << "Camera" << i << ".p1: " << model.D().at<double>(0,2) << std::endl;
|
||||
ofs << "Camera" << i << ".p2: " << model.D().at<double>(0,3) << std::endl;
|
||||
}
|
||||
if(model.D().cols >= 5)
|
||||
{
|
||||
ofs << "Camera" << i << ".k3: " << model.D().at<double>(0,4) << std::endl;
|
||||
}
|
||||
if(model.D().cols > 5)
|
||||
{
|
||||
UWARN("Unhandled camera distortion size %d, only 5 first coefficients used", model.D().cols);
|
||||
}
|
||||
ofs << std::endl;
|
||||
}
|
||||
if(model.D().cols >= 4)
|
||||
{
|
||||
ofs << "Camera1.k1: " << model.D().at<double>(0,0) << std::endl;
|
||||
ofs << "Camera1.k2: " << model.D().at<double>(0,1) << std::endl;
|
||||
ofs << "Camera1.p1: " << model.D().at<double>(0,2) << std::endl;
|
||||
ofs << "Camera1.p2: " << model.D().at<double>(0,3) << std::endl;
|
||||
}
|
||||
if(model.D().cols >= 5)
|
||||
{
|
||||
ofs << "Camera1.k3: " << model.D().at<double>(0,4) << std::endl;
|
||||
}
|
||||
if(model.D().cols > 5)
|
||||
{
|
||||
UWARN("Unhandled camera distortion size %d, only 5 first coefficients used", model.D().cols);
|
||||
}
|
||||
ofs << std::endl;
|
||||
|
||||
//# IR projector baseline times fx (aprox.)
|
||||
if(baseline <= 0.0)
|
||||
@@ -179,15 +184,28 @@ bool OdometryORBSLAM3::init(const rtabmap::CameraModel & model, double stamp, b
|
||||
baseline = rtabmap::Parameters::defaultOdomORBSLAMBf();
|
||||
rtabmap::Parameters::parse(parameters_, rtabmap::Parameters::kOdomORBSLAMBf(), baseline);
|
||||
}
|
||||
ofs << "Camera.bf: " << model.fx()*baseline << std::endl;
|
||||
else
|
||||
{
|
||||
// # Transformation matrix from right camera to left camera
|
||||
ofs << "Stereo.T_c1_c2: !!opencv-matrix" << std::endl;
|
||||
ofs << " rows: 4" << std::endl;
|
||||
ofs << " cols: 4" << std::endl;
|
||||
ofs << " dt: f" << std::endl;
|
||||
ofs << " data: [" << 1 << ", " << 0 << ", " << 0 << ", " << baseline << ", " << std::endl;
|
||||
ofs << " " << 0 << ", " << 1 << ", " << 0 << ", " << 0 << ", " << std::endl;
|
||||
ofs << " " << 0 << ", " << 0 << ", " << 1 << ", " << 0 << ", " << std::endl;
|
||||
ofs << " 0.0, 0.0, 0.0, 1.0]" << std::endl;
|
||||
ofs << std::endl;
|
||||
}
|
||||
ofs << "Camera.bf: " << model1.fx()*baseline << std::endl;
|
||||
|
||||
ofs << "Camera.width: " << model.imageWidth() << std::endl;
|
||||
ofs << "Camera.height: " << model.imageHeight() << std::endl;
|
||||
ofs << "Camera.width: " << model1.imageWidth() << std::endl;
|
||||
ofs << "Camera.height: " << model1.imageHeight() << std::endl;
|
||||
ofs << std::endl;
|
||||
|
||||
//# Color order of the images (0: BGR, 1: RGB. It is ignored if images are grayscale)
|
||||
//Camera.RGB: 1
|
||||
ofs << "Camera.RGB: 1" << std::endl;
|
||||
ofs << "Camera.RGB: 0" << std::endl;
|
||||
ofs << std::endl;
|
||||
|
||||
float fps = rtabmap::Parameters::defaultOdomORBSLAMFps();
|
||||
@@ -222,7 +240,7 @@ bool OdometryORBSLAM3::init(const rtabmap::CameraModel & model, double stamp, b
|
||||
//# IMU Parameters TODO: hard-coded, not used
|
||||
//#--------------------------------------------------------------------------------------------
|
||||
// Transformation from camera 0 to body-frame (imu)
|
||||
rtabmap::Transform camImuT = model.localTransform()*imuLocalTransform_;
|
||||
rtabmap::Transform camImuT = model1.localTransform()*imuLocalTransform_;
|
||||
ofs << "IMU.T_b_c1: !!opencv-matrix" << std::endl;
|
||||
ofs << " rows: 4" << std::endl;
|
||||
ofs << " cols: 4" << std::endl;
|
||||
@@ -418,7 +436,7 @@ Transform OdometryORBSLAM3::computeTransform(
|
||||
}
|
||||
|
||||
CameraModel model = data.cameraModels().size()==1?data.cameraModels()[0]:data.stereoCameraModels()[0].left();
|
||||
if(!init(model, data.stamp(), stereo, data.cameraModels().size()==1?0.0:data.stereoCameraModels()[0].baseline()))
|
||||
if(!init(model, !stereo?model:data.stereoCameraModels()[0].right(), data.stamp(), stereo, data.cameraModels().size()==1?0.0:data.stereoCameraModels()[0].baseline()))
|
||||
{
|
||||
return t;
|
||||
}
|
||||
|
||||
@@ -2398,7 +2398,7 @@ bool multiBandTexturing(
|
||||
std::string tmpImageDirectory = outputDirectory+"/rtabmap_tmp_textures";
|
||||
UDirectory::removeDir(tmpImageDirectory);
|
||||
UDirectory::makeDir(tmpImageDirectory);
|
||||
UINFO("Temporary saving images in directory \"%s\"...", tmpImageDirectory.c_str());
|
||||
UINFO("Temporary saving images from %ld nodes in directory \"%s\"...", cameraPoses.size(), tmpImageDirectory.c_str());
|
||||
int viewId = 0;
|
||||
for(std::map<int, Transform>::const_iterator iter = cameraPoses.lower_bound(1); iter!=cameraPoses.end(); ++iter)
|
||||
{
|
||||
@@ -2510,28 +2510,45 @@ bool multiBandTexturing(
|
||||
imageSize.height = image.rows;
|
||||
imageSize.width = image.cols;
|
||||
}
|
||||
|
||||
UASSERT(image.cols % imageSize.width == 0);
|
||||
cv::Mat imageRoi = image.colRange(i*imageSize.width, (i+1)*imageSize.width);
|
||||
|
||||
if(gains.find(camId) != gains.end() &&
|
||||
gains.at(camId).find(i) != gains.at(camId).end())
|
||||
{
|
||||
const cv::Vec4d & g = gains.at(camId).at(i);
|
||||
std::vector<cv::Mat> channels;
|
||||
cv::split(imageRoi, channels);
|
||||
if(imageRoi.channels() == 1)
|
||||
{
|
||||
cv::multiply(imageRoi, g.val[0], imageRoi);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::vector<cv::Mat> channels;
|
||||
cv::split(imageRoi, channels);
|
||||
|
||||
// assuming BGR
|
||||
cv::multiply(channels[0], g.val[gainRGB?3:0], channels[0]);
|
||||
cv::multiply(channels[1], g.val[gainRGB?2:0], channels[1]);
|
||||
cv::multiply(channels[2], g.val[gainRGB?1:0], channels[2]);
|
||||
// assuming BGR
|
||||
cv::multiply(channels[0], g.val[gainRGB?3:0], channels[0]);
|
||||
cv::multiply(channels[1], g.val[gainRGB?2:0], channels[1]);
|
||||
cv::multiply(channels[2], g.val[gainRGB?1:0], channels[2]);
|
||||
|
||||
cv::Mat output;
|
||||
cv::merge(channels, output);
|
||||
imageRoi = output;
|
||||
cv::Mat output;
|
||||
cv::merge(channels, output);
|
||||
imageRoi = output;
|
||||
}
|
||||
}
|
||||
|
||||
if(blendingGains.find(camId) != blendingGains.end() &&
|
||||
blendingGains.at(camId).find(i) != blendingGains.at(camId).end())
|
||||
{
|
||||
// Should be color for blending options
|
||||
if(imageRoi.channels() == 1)
|
||||
{
|
||||
cv::Mat imageRoiColor;
|
||||
cv::cvtColor(imageRoi, imageRoiColor, CV_GRAY2BGR);
|
||||
imageRoi = imageRoiColor;
|
||||
}
|
||||
|
||||
cv::Mat g = blendingGains.at(camId).at(i);
|
||||
cv::Mat dst;
|
||||
cv::blur(g, dst, cv::Size(3,3));
|
||||
@@ -2559,9 +2576,7 @@ bool multiBandTexturing(
|
||||
sfmData.intrinsics.insert(std::make_pair((IndexT)viewId, camPtr));
|
||||
|
||||
std::string imagePath = tmpImageDirectory+uFormat("/%d.jpg", viewId);
|
||||
|
||||
cv::imwrite(imagePath, imageRoi);
|
||||
|
||||
std::shared_ptr<sfmData::View> viewPtr = std::make_shared<sfmData::View>(
|
||||
imagePath,
|
||||
(IndexT)viewId,
|
||||
@@ -2572,8 +2587,9 @@ bool multiBandTexturing(
|
||||
sfmData.views.insert(std::make_pair((IndexT)viewId, viewPtr));
|
||||
++viewId;
|
||||
}
|
||||
UDEBUG("camId=%d", camId);
|
||||
}
|
||||
UINFO("Temporary saving images in directory \"%s\"... done (%d images). %fs", tmpImageDirectory.c_str(), viewId, (int)cameraPoses.size(), timer.ticks());
|
||||
UINFO("Temporary saving images in directory \"%s\"... done (%d images of %d nodes). %fs", tmpImageDirectory.c_str(), viewId, (int)cameraPoses.size(), timer.ticks());
|
||||
|
||||
mvsUtils::MultiViewParams mp(sfmData);
|
||||
|
||||
|
||||
@@ -128,6 +128,8 @@ private Q_SLOTS:
|
||||
void updateAllLandmarkCovariances();
|
||||
void refineLinks();
|
||||
void resetAllChanges();
|
||||
void graphNodeSelected(int);
|
||||
void graphLinkSelected(int, int);
|
||||
void sliderAValueChanged(int);
|
||||
void sliderBValueChanged(int);
|
||||
void sliderAMoved(int);
|
||||
|
||||
@@ -166,12 +166,16 @@ public:
|
||||
Q_SIGNALS:
|
||||
void configChanged();
|
||||
void mapShownRequested();
|
||||
void nodeSelected(int);
|
||||
void linkSelected(int, int);
|
||||
|
||||
public Q_SLOTS:
|
||||
void restoreDefaults();
|
||||
|
||||
protected:
|
||||
virtual void wheelEvent ( QWheelEvent * event );
|
||||
virtual void mouseMoveEvent(QMouseEvent * event);
|
||||
virtual void mouseDoubleClickEvent(QMouseEvent * event);
|
||||
virtual void contextMenuEvent(QContextMenuEvent * event);
|
||||
|
||||
private:
|
||||
@@ -228,6 +232,7 @@ private:
|
||||
float _loopClosureOutlierThr;
|
||||
float _maxLinkLength;
|
||||
bool _orientationENU;
|
||||
bool _mouseTracking;
|
||||
ViewPlane _viewPlane;
|
||||
bool _ensureFrameVisible;
|
||||
};
|
||||
|
||||
@@ -37,6 +37,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include <opencv2/features2d/features2d.hpp>
|
||||
#include <map>
|
||||
#include "rtabmap/utilite/UCv2Qt.h"
|
||||
#include <rtabmap/core/CameraModel.h>
|
||||
|
||||
class QAction;
|
||||
class QMenu;
|
||||
@@ -96,7 +97,7 @@ public:
|
||||
void setFeatures(const std::vector<cv::KeyPoint> & features, const cv::Mat & depth = cv::Mat(), const QColor & color = Qt::yellow);
|
||||
void addFeature(int id, const cv::KeyPoint & kpt, float depth, QColor color);
|
||||
void addLine(float x1, float y1, float x2, float y2, QColor color, const QString & text = QString());
|
||||
void setImage(const QImage & image);
|
||||
void setImage(const QImage & image, const std::vector<CameraModel> & models = std::vector<CameraModel>(), const Transform & pose = Transform());
|
||||
void setImageDepth(const cv::Mat & imageDepth);
|
||||
void setImageDepth(const QImage & image);
|
||||
void setFeatureColor(int id, QColor color);
|
||||
@@ -121,6 +122,7 @@ protected:
|
||||
virtual void paintEvent(QPaintEvent *event);
|
||||
virtual void resizeEvent(QResizeEvent* event);
|
||||
virtual void contextMenuEvent(QContextMenuEvent * e);
|
||||
virtual void mouseMoveEvent(QMouseEvent * event);
|
||||
|
||||
private Q_SLOTS:
|
||||
void sceneRectChanged(const QRectF &rect);
|
||||
@@ -164,6 +166,7 @@ private:
|
||||
QAction * _colorMapBlueToRed;
|
||||
QAction * _colorMapMinRange;
|
||||
QAction * _colorMapMaxRange;
|
||||
QAction * _mouseTracking;
|
||||
QMenu * _featureMenu;
|
||||
QMenu * _scaleMenu;
|
||||
|
||||
@@ -175,6 +178,8 @@ private:
|
||||
QPixmap _image;
|
||||
QPixmap _imageDepth;
|
||||
cv::Mat _imageDepthCv;
|
||||
std::vector<CameraModel> _models;
|
||||
Transform _pose;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -170,7 +170,6 @@ protected Q_SLOTS:
|
||||
void depthCalibration();
|
||||
void openWorkingDirectory();
|
||||
void updateEditMenu();
|
||||
void selectStream();
|
||||
void selectOpenni();
|
||||
void selectFreenect();
|
||||
void selectOpenniCv();
|
||||
|
||||
@@ -268,6 +268,8 @@ DatabaseViewer::DatabaseViewer(const QString & ini, QWidget * parent) :
|
||||
connect(ui_->dockWidget_statistics->toggleViewAction(), SIGNAL(triggered()), this, SLOT(updateStatistics()));
|
||||
connect(ui_->dockWidget_info->toggleViewAction(), SIGNAL(triggered()), this, SLOT(updateInfo()));
|
||||
|
||||
connect(ui_->graphViewer, SIGNAL(nodeSelected(int)), this , SLOT(graphNodeSelected(int)));
|
||||
connect(ui_->graphViewer, SIGNAL(linkSelected(int,int)), this , SLOT(graphLinkSelected(int,int)));
|
||||
|
||||
connect(ui_->parameters_toolbox, SIGNAL(parametersChanged(const QStringList &)), this, SLOT(notifyParametersChanged(const QStringList &)));
|
||||
|
||||
@@ -4547,6 +4549,20 @@ void DatabaseViewer::resetAllChanges()
|
||||
}
|
||||
}
|
||||
|
||||
void DatabaseViewer::graphNodeSelected(int id)
|
||||
{
|
||||
if(id>0 && idToIndex_.contains(id))
|
||||
ui_->horizontalSlider_A->setValue(idToIndex_.value(id));
|
||||
}
|
||||
|
||||
void DatabaseViewer::graphLinkSelected(int from, int to)
|
||||
{
|
||||
if(from>0 && idToIndex_.contains(from))
|
||||
ui_->horizontalSlider_A->setValue(idToIndex_.value(from));
|
||||
if(to>0 && idToIndex_.contains(to))
|
||||
ui_->horizontalSlider_B->setValue(idToIndex_.value(to));
|
||||
}
|
||||
|
||||
void DatabaseViewer::sliderAValueChanged(int value)
|
||||
{
|
||||
this->update(value,
|
||||
@@ -4685,7 +4701,12 @@ void DatabaseViewer::update(int value,
|
||||
QRectF rect;
|
||||
if(!img.isNull())
|
||||
{
|
||||
view->setImage(img);
|
||||
Transform pose;
|
||||
if(!graphes_.empty() && graphes_.back().find(data.id())!=graphes_.back().end())
|
||||
{
|
||||
pose = graphes_.back().at(data.id());
|
||||
}
|
||||
view->setImage(img, data.cameraModels(), pose);
|
||||
rect = img.rect();
|
||||
}
|
||||
else
|
||||
|
||||
@@ -129,6 +129,14 @@ ExportCloudsDialog::ExportCloudsDialog(QWidget *parent) :
|
||||
connect(_ui->doubleSpinBox_minDepth, SIGNAL(valueChanged(double)), this, SIGNAL(configChanged()));
|
||||
connect(_ui->doubleSpinBox_ceilingHeight, SIGNAL(valueChanged(double)), this, SIGNAL(configChanged()));
|
||||
connect(_ui->doubleSpinBox_floorHeight, SIGNAL(valueChanged(double)), this, SIGNAL(configChanged()));
|
||||
connect(_ui->groupBox_offAxisFiltering, SIGNAL(toggled(bool)), this, SIGNAL(configChanged()));
|
||||
connect(_ui->doubleSpinBox_offAxisFilteringAngle, SIGNAL(valueChanged(double)), this, SIGNAL(configChanged()));
|
||||
connect(_ui->checkBox_offAxisFilteringPosX, SIGNAL(stateChanged(int)), this, SIGNAL(configChanged()));
|
||||
connect(_ui->checkBox_offAxisFilteringNegX, SIGNAL(stateChanged(int)), this, SIGNAL(configChanged()));
|
||||
connect(_ui->checkBox_offAxisFilteringPosY, SIGNAL(stateChanged(int)), this, SIGNAL(configChanged()));
|
||||
connect(_ui->checkBox_offAxisFilteringNegY, SIGNAL(stateChanged(int)), this, SIGNAL(configChanged()));
|
||||
connect(_ui->checkBox_offAxisFilteringPosZ, SIGNAL(stateChanged(int)), this, SIGNAL(configChanged()));
|
||||
connect(_ui->checkBox_offAxisFilteringNegZ, SIGNAL(stateChanged(int)), this, SIGNAL(configChanged()));
|
||||
connect(_ui->doubleSpinBox_footprintWidth, SIGNAL(valueChanged(double)), this, SIGNAL(configChanged()));
|
||||
connect(_ui->doubleSpinBox_footprintLength, SIGNAL(valueChanged(double)), this, SIGNAL(configChanged()));
|
||||
connect(_ui->doubleSpinBox_footprintHeight, SIGNAL(valueChanged(double)), this, SIGNAL(configChanged()));
|
||||
@@ -370,6 +378,14 @@ void ExportCloudsDialog::saveSettings(QSettings & settings, const QString & grou
|
||||
settings.setValue("regenerate_min_depth", _ui->doubleSpinBox_minDepth->value());
|
||||
settings.setValue("regenerate_ceiling", _ui->doubleSpinBox_ceilingHeight->value());
|
||||
settings.setValue("regenerate_floor", _ui->doubleSpinBox_floorHeight->value());
|
||||
settings.setValue("regenerate_offaxis_filtering", _ui->groupBox_offAxisFiltering->isChecked());
|
||||
settings.setValue("regenerate_offaxis_filtering_angle", _ui->doubleSpinBox_offAxisFilteringAngle->value());
|
||||
settings.setValue("regenerate_offaxis_filtering_pos_x", _ui->checkBox_offAxisFilteringPosX->isChecked());
|
||||
settings.setValue("regenerate_offaxis_filtering_neg_x", _ui->checkBox_offAxisFilteringNegX->isChecked());
|
||||
settings.setValue("regenerate_offaxis_filtering_pos_y", _ui->checkBox_offAxisFilteringPosY->isChecked());
|
||||
settings.setValue("regenerate_offaxis_filtering_neg_y", _ui->checkBox_offAxisFilteringNegY->isChecked());
|
||||
settings.setValue("regenerate_offaxis_filtering_pos_z", _ui->checkBox_offAxisFilteringPosZ->isChecked());
|
||||
settings.setValue("regenerate_offaxis_filtering_neg_z", _ui->checkBox_offAxisFilteringNegZ->isChecked());
|
||||
settings.setValue("regenerate_footprint_height", _ui->doubleSpinBox_footprintHeight->value());
|
||||
settings.setValue("regenerate_footprint_width", _ui->doubleSpinBox_footprintWidth->value());
|
||||
settings.setValue("regenerate_footprint_length", _ui->doubleSpinBox_footprintLength->value());
|
||||
@@ -543,6 +559,14 @@ void ExportCloudsDialog::loadSettings(QSettings & settings, const QString & grou
|
||||
_ui->doubleSpinBox_minDepth->setValue(settings.value("regenerate_min_depth", _ui->doubleSpinBox_minDepth->value()).toDouble());
|
||||
_ui->doubleSpinBox_ceilingHeight->setValue(settings.value("regenerate_ceiling", _ui->doubleSpinBox_ceilingHeight->value()).toDouble());
|
||||
_ui->doubleSpinBox_floorHeight->setValue(settings.value("regenerate_floor", _ui->doubleSpinBox_floorHeight->value()).toDouble());
|
||||
_ui->groupBox_offAxisFiltering->setChecked(settings.value("regenerate_offaxis_filtering", _ui->groupBox_offAxisFiltering->isChecked()).toBool());
|
||||
_ui->doubleSpinBox_offAxisFilteringAngle->setValue(settings.value("regenerate_offaxis_filtering_angle", _ui->doubleSpinBox_offAxisFilteringAngle->value()).toDouble());
|
||||
_ui->checkBox_offAxisFilteringPosX->setChecked(settings.value("regenerate_offaxis_filtering_pos_x", _ui->checkBox_offAxisFilteringPosX->isChecked()).toBool());
|
||||
_ui->checkBox_offAxisFilteringNegX->setChecked(settings.value("regenerate_offaxis_filtering_neg_x", _ui->checkBox_offAxisFilteringNegX->isChecked()).toBool());
|
||||
_ui->checkBox_offAxisFilteringPosY->setChecked(settings.value("regenerate_offaxis_filtering_pos_y", _ui->checkBox_offAxisFilteringPosY->isChecked()).toBool());
|
||||
_ui->checkBox_offAxisFilteringNegY->setChecked(settings.value("regenerate_offaxis_filtering_neg_y", _ui->checkBox_offAxisFilteringNegY->isChecked()).toBool());
|
||||
_ui->checkBox_offAxisFilteringPosZ->setChecked(settings.value("regenerate_offaxis_filtering_pos_z", _ui->checkBox_offAxisFilteringPosZ->isChecked()).toBool());
|
||||
_ui->checkBox_offAxisFilteringNegZ->setChecked(settings.value("regenerate_offaxis_filtering_neg_z", _ui->checkBox_offAxisFilteringNegZ->isChecked()).toBool());
|
||||
_ui->doubleSpinBox_footprintHeight->setValue(settings.value("regenerate_footprint_height", _ui->doubleSpinBox_footprintHeight->value()).toDouble());
|
||||
_ui->doubleSpinBox_footprintWidth->setValue(settings.value("regenerate_footprint_width", _ui->doubleSpinBox_footprintWidth->value()).toDouble());
|
||||
_ui->doubleSpinBox_footprintLength->setValue(settings.value("regenerate_footprint_length", _ui->doubleSpinBox_footprintLength->value()).toDouble());
|
||||
@@ -719,6 +743,14 @@ void ExportCloudsDialog::restoreDefaults()
|
||||
_ui->doubleSpinBox_minDepth->setValue(0);
|
||||
_ui->doubleSpinBox_ceilingHeight->setValue(0);
|
||||
_ui->doubleSpinBox_floorHeight->setValue(0);
|
||||
_ui->groupBox_offAxisFiltering->setChecked(false);
|
||||
_ui->doubleSpinBox_offAxisFilteringAngle->setValue(10);
|
||||
_ui->checkBox_offAxisFilteringPosX->setChecked(true);
|
||||
_ui->checkBox_offAxisFilteringNegX->setChecked(true);
|
||||
_ui->checkBox_offAxisFilteringPosY->setChecked(true);
|
||||
_ui->checkBox_offAxisFilteringNegY->setChecked(true);
|
||||
_ui->checkBox_offAxisFilteringPosZ->setChecked(true);
|
||||
_ui->checkBox_offAxisFilteringNegZ->setChecked(true);
|
||||
_ui->doubleSpinBox_footprintHeight->setValue(0);
|
||||
_ui->doubleSpinBox_footprintLength->setValue(0);
|
||||
_ui->doubleSpinBox_footprintWidth->setValue(0);
|
||||
@@ -3915,6 +3947,36 @@ std::map<int, std::pair<pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr, pcl::Indic
|
||||
UWARN("Point cloud %d doesn't have anymore points (had %d points) after radius filtering.", iter->first, (int)cloud->size());
|
||||
}
|
||||
}
|
||||
if( !indices->empty() && _ui->groupBox_offAxisFiltering->isChecked() &&
|
||||
(_ui->checkBox_offAxisFilteringPosX->isChecked() ||
|
||||
_ui->checkBox_offAxisFilteringNegX->isChecked() ||
|
||||
_ui->checkBox_offAxisFilteringPosY->isChecked() ||
|
||||
_ui->checkBox_offAxisFilteringNegY->isChecked() ||
|
||||
_ui->checkBox_offAxisFilteringPosZ->isChecked() ||
|
||||
_ui->checkBox_offAxisFilteringNegZ->isChecked()))
|
||||
{
|
||||
pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr cloudInMapFrame = util3d::transformPointCloud(cloud, iter->second);
|
||||
std::vector<pcl::IndicesPtr> indicesVector;
|
||||
double maxDeltaAngle = _ui->doubleSpinBox_offAxisFilteringAngle->value()*M_PI/180.0;
|
||||
Eigen::Vector4f viewpoint(iter->second.x(), iter->second.y(), iter->second.z(), 0);
|
||||
if(_ui->checkBox_offAxisFilteringPosX->isChecked())
|
||||
indicesVector.push_back(util3d::normalFiltering(cloudInMapFrame, indices, maxDeltaAngle, Eigen::Vector4f(1,0,0,0), 20, viewpoint));
|
||||
if(_ui->checkBox_offAxisFilteringPosY->isChecked())
|
||||
indicesVector.push_back(util3d::normalFiltering(cloudInMapFrame, indices, maxDeltaAngle, Eigen::Vector4f(0,1,0,0), 20, viewpoint));
|
||||
if(_ui->checkBox_offAxisFilteringPosZ->isChecked())
|
||||
indicesVector.push_back(util3d::normalFiltering(cloudInMapFrame, indices, maxDeltaAngle, Eigen::Vector4f(0,0,1,0), 20, viewpoint));
|
||||
if(_ui->checkBox_offAxisFilteringNegX->isChecked())
|
||||
indicesVector.push_back(util3d::normalFiltering(cloudInMapFrame, indices, maxDeltaAngle, Eigen::Vector4f(-1,0,0,0), 20, viewpoint));
|
||||
if(_ui->checkBox_offAxisFilteringNegY->isChecked())
|
||||
indicesVector.push_back(util3d::normalFiltering(cloudInMapFrame, indices, maxDeltaAngle, Eigen::Vector4f(0,-1,0,0), 20, viewpoint));
|
||||
if(_ui->checkBox_offAxisFilteringNegZ->isChecked())
|
||||
indicesVector.push_back(util3d::normalFiltering(cloudInMapFrame, indices, maxDeltaAngle, Eigen::Vector4f(0,0,-1,0), 20, viewpoint));
|
||||
indices = util3d::concatenate(indicesVector);
|
||||
if(indices->empty())
|
||||
{
|
||||
UWARN("Point cloud %d doesn't have anymore points (had %d points) after offaxis filtering.", iter->first, (int)cloud->size());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!indices->empty())
|
||||
@@ -4614,7 +4676,7 @@ void ExportCloudsDialog::saveTextureMeshes(
|
||||
path.toStdString(),
|
||||
mesh->cloud,
|
||||
mesh->tex_polygons[0],
|
||||
poses,
|
||||
filterNodes(poses),
|
||||
textureVertexToPixels,
|
||||
images,
|
||||
calibrations,
|
||||
|
||||
@@ -45,6 +45,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#endif
|
||||
#include <QInputDialog>
|
||||
#include <QMessageBox>
|
||||
#include <QToolTip>
|
||||
|
||||
#include <QtCore/QDir>
|
||||
#include <QtCore/QDateTime>
|
||||
@@ -316,6 +317,7 @@ GraphViewer::GraphViewer(QWidget * parent) :
|
||||
_loopClosureOutlierThr(0),
|
||||
_maxLinkLength(0.02f),
|
||||
_orientationENU(false),
|
||||
_mouseTracking(false),
|
||||
_viewPlane(XY),
|
||||
_ensureFrameVisible(true)
|
||||
{
|
||||
@@ -1789,6 +1791,50 @@ void GraphViewer::wheelEvent ( QWheelEvent * event )
|
||||
}
|
||||
}
|
||||
|
||||
void GraphViewer::mouseMoveEvent(QMouseEvent * event)
|
||||
{
|
||||
QPointF scenePoint = mapToScene(event->pos());
|
||||
if(_mouseTracking && _viewPlane==XY && this->sceneRect().contains(scenePoint))
|
||||
{
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||
QToolTip::showText(event->globalPosition().toPoint(), QString("%1m %2m").arg(-scenePoint.y()/100.0).arg(-scenePoint.x()/100.0));
|
||||
#else
|
||||
QToolTip::showText(event->globalPos(), QString("%1m %2m").arg(-scenePoint.y()/100.0).arg(-scenePoint.x()/100.0));
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
QToolTip::hideText();
|
||||
}
|
||||
QGraphicsView::mouseMoveEvent(event);
|
||||
}
|
||||
|
||||
void GraphViewer::mouseDoubleClickEvent(QMouseEvent * event)
|
||||
{
|
||||
QGraphicsItem *item = this->scene()->itemAt(mapToScene(event->pos()), QTransform());
|
||||
if(item)
|
||||
{
|
||||
NodeItem *nodeItem = qgraphicsitem_cast<NodeItem*>(item);
|
||||
LinkItem *linkItem = qgraphicsitem_cast<LinkItem*>(item);
|
||||
if(nodeItem && nodeItem->parentItem() == _graphRoot && nodeItem->id() != 0)
|
||||
{
|
||||
Q_EMIT nodeSelected(nodeItem->id());
|
||||
}
|
||||
else if(linkItem && linkItem->parentItem() == _graphRoot && linkItem->from() != 0 && linkItem->to() != 0)
|
||||
{
|
||||
Q_EMIT linkSelected(linkItem->from(), linkItem->to());
|
||||
}
|
||||
else
|
||||
{
|
||||
QGraphicsView::mouseDoubleClickEvent(event);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
QGraphicsView::mouseDoubleClickEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
QIcon createIcon(const QColor & color)
|
||||
{
|
||||
QPixmap pixmap(50, 50);
|
||||
@@ -1878,6 +1924,7 @@ void GraphViewer::contextMenuEvent(QContextMenuEvent * event)
|
||||
QAction * aShowHideGPSGraph;
|
||||
QAction * aShowHideOdomCacheOverlay;
|
||||
QAction * aOrientationENU;
|
||||
QAction * aMouseTracking;
|
||||
QAction * aViewPlaneXY;
|
||||
QAction * aViewPlaneXZ;
|
||||
QAction * aViewPlaneYZ;
|
||||
@@ -1976,6 +2023,10 @@ void GraphViewer::contextMenuEvent(QContextMenuEvent * event)
|
||||
aOrientationENU = menu.addAction(tr("ENU Orientation"));
|
||||
aOrientationENU->setCheckable(true);
|
||||
aOrientationENU->setChecked(_orientationENU);
|
||||
aMouseTracking = menu.addAction(tr("Show mouse cursor position (m)"));
|
||||
aMouseTracking->setCheckable(true);
|
||||
aMouseTracking->setChecked(_mouseTracking);
|
||||
aMouseTracking->setEnabled(_viewPlane == XY);
|
||||
aShowHideGraph->setEnabled(_nodeItems.size() && _viewPlane == XY);
|
||||
aShowHideGraphNodes->setEnabled(_nodeItems.size() && _graphRoot->isVisible());
|
||||
aShowHideGlobalPath->setEnabled(_globalPathLinkItems.size());
|
||||
@@ -2405,6 +2456,10 @@ void GraphViewer::contextMenuEvent(QContextMenuEvent * event)
|
||||
{
|
||||
this->setOrientationENU(!this->isOrientationENU());
|
||||
}
|
||||
else if(r == aMouseTracking)
|
||||
{
|
||||
_mouseTracking = aMouseTracking->isChecked();
|
||||
}
|
||||
else if(r == aViewPlaneXY)
|
||||
{
|
||||
this->setViewPlane(XY);
|
||||
|
||||
@@ -40,9 +40,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include <QColorDialog>
|
||||
#include <QPrinter>
|
||||
#include <QGraphicsRectItem>
|
||||
#include <QToolTip>
|
||||
#include "rtabmap/utilite/ULogger.h"
|
||||
#include "rtabmap/gui/KeypointItem.h"
|
||||
#include "rtabmap/core/util2d.h"
|
||||
#include "rtabmap/core/util3d_transforms.h"
|
||||
|
||||
#include <QtGlobal>
|
||||
#if QT_VERSION >= 0x050000
|
||||
@@ -268,9 +270,14 @@ ImageView::ImageView(QWidget * parent) :
|
||||
group->addAction(_colorMapRedToBlue);
|
||||
group->addAction(_colorMapBlueToRed);
|
||||
group->addAction(_colorMapMaxRange);
|
||||
_mouseTracking = _menu->addAction(tr("Show pixel depth"));
|
||||
_mouseTracking->setCheckable(true);
|
||||
_mouseTracking->setChecked(false);
|
||||
_saveImage = _menu->addAction(tr("Save picture..."));
|
||||
_saveImage->setEnabled(false);
|
||||
|
||||
setMouseTracking(true);
|
||||
|
||||
connect(_graphicsView->scene(), SIGNAL(sceneRectChanged(const QRectF &)), this, SLOT(sceneRectChanged(const QRectF &)));
|
||||
}
|
||||
|
||||
@@ -1047,6 +1054,65 @@ void ImageView::contextMenuEvent(QContextMenuEvent * e)
|
||||
}
|
||||
}
|
||||
|
||||
void ImageView::mouseMoveEvent(QMouseEvent * event)
|
||||
{
|
||||
if(_mouseTracking->isChecked() &&
|
||||
!_graphicsView->scene()->sceneRect().isNull() &&
|
||||
!_image.isNull() &&
|
||||
!_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() > _imageDepth.width())
|
||||
{
|
||||
depthScale = _imageDepth.width() / _image.width();
|
||||
}
|
||||
int ud = int(u*depthScale);
|
||||
int vd = int(v*depthScale);
|
||||
if( ud>=0 && vd>=0 &&
|
||||
ud < _imageDepthCv.cols &&
|
||||
vd < _imageDepthCv.rows)
|
||||
{
|
||||
float depth = 0;
|
||||
if(_imageDepthCv.type() == CV_32FC1)
|
||||
{
|
||||
depth = _imageDepthCv.at<float>(vd, ud);
|
||||
}
|
||||
else
|
||||
{
|
||||
depth = float(_imageDepthCv.at<unsigned short>(vd, ud)) / 1000.0f;
|
||||
}
|
||||
|
||||
cv::Point3f pt(0,0,0);
|
||||
if(depth>0 && !_models.empty() && !_pose.isNull())
|
||||
{
|
||||
int subImageWidth = _imageDepthCv.cols / _models.size();
|
||||
int subImageIndex = ud / subImageWidth;
|
||||
UASSERT(subImageIndex < (int)_models.size());
|
||||
float x,y,z;
|
||||
_models[subImageIndex].project(u, v, depth, x, y, z);
|
||||
pt = cv::Point3f(x,y,z);
|
||||
pt = util3d::transformPoint(pt, _pose*_models[subImageIndex].localTransform());
|
||||
}
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||
QToolTip::showText(event->globalPosition().toPoint(), pt.x!=0?tr("Depth=%1m Map=(%2,%3,%4)").arg(depth).arg(pt.x).arg(pt.y).arg(pt.z):depth > 0?tr("Depth=%1m").arg(depth):tr("Depth=NA"));
|
||||
#else
|
||||
QToolTip::showText(event->globalPos(), pt.x!=0?tr("Depth=%1m Map=(%2,%3,%4)").arg(depth).arg(pt.x).arg(pt.y).arg(pt.z):depth > 0?tr("Depth=%1m").arg(depth):tr("Depth=NA"));
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
QToolTip::hideText();
|
||||
}
|
||||
}
|
||||
QWidget::mouseMoveEvent(event);
|
||||
}
|
||||
|
||||
void ImageView::updateOpacity()
|
||||
{
|
||||
if(_imageItem && _imageDepthItem)
|
||||
@@ -1166,9 +1232,11 @@ void ImageView::addLine(float x1, float y1, float x2, float y2, QColor color, co
|
||||
}
|
||||
}
|
||||
|
||||
void ImageView::setImage(const QImage & image)
|
||||
void ImageView::setImage(const QImage & image, const std::vector<CameraModel> & models, const Transform & pose)
|
||||
{
|
||||
_image = QPixmap::fromImage(image);
|
||||
_models = models;
|
||||
_pose = pose;
|
||||
if(_graphicsView->isVisible())
|
||||
{
|
||||
if(_imageItem)
|
||||
@@ -1394,6 +1462,8 @@ void ImageView::clear()
|
||||
_imageItem = 0;
|
||||
}
|
||||
_image = QPixmap();
|
||||
_models.clear();
|
||||
_pose.setNull();
|
||||
|
||||
if(_imageDepthItem)
|
||||
{
|
||||
|
||||
@@ -435,7 +435,6 @@ MainWindow::MainWindow(PreferencesDialog * prefDialog, QWidget * parent, bool sh
|
||||
|
||||
//Settings menu
|
||||
connect(_ui->actionMore_options, SIGNAL(triggered()), this, SLOT(openPreferencesSource()));
|
||||
connect(_ui->actionUsbCamera, SIGNAL(triggered()), this, SLOT(selectStream()));
|
||||
connect(_ui->actionOpenNI_PCL, SIGNAL(triggered()), this, SLOT(selectOpenni()));
|
||||
connect(_ui->actionOpenNI_PCL_ASUS, SIGNAL(triggered()), this, SLOT(selectOpenni()));
|
||||
connect(_ui->actionFreenect, SIGNAL(triggered()), this, SLOT(selectFreenect()));
|
||||
@@ -5228,10 +5227,9 @@ bool MainWindow::eventFilter(QObject *obj, QEvent *event)
|
||||
|
||||
void MainWindow::updateSelectSourceMenu()
|
||||
{
|
||||
_ui->actionUsbCamera->setChecked(_preferencesDialog->getSourceDriver() == PreferencesDialog::kSrcUsbDevice);
|
||||
|
||||
_ui->actionMore_options->setChecked(
|
||||
_preferencesDialog->getSourceDriver() == PreferencesDialog::kSrcDatabase ||
|
||||
_preferencesDialog->getSourceDriver() == PreferencesDialog::kSrcUsbDevice ||
|
||||
_preferencesDialog->getSourceDriver() == PreferencesDialog::kSrcImages ||
|
||||
_preferencesDialog->getSourceDriver() == PreferencesDialog::kSrcVideo ||
|
||||
_preferencesDialog->getSourceDriver() == PreferencesDialog::kSrcStereoImages ||
|
||||
@@ -7061,11 +7059,6 @@ void MainWindow::updateEditMenu()
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::selectStream()
|
||||
{
|
||||
_preferencesDialog->selectSourceDriver(PreferencesDialog::kSrcUsbDevice);
|
||||
}
|
||||
|
||||
void MainWindow::selectOpenni()
|
||||
{
|
||||
_preferencesDialog->selectSourceDriver(PreferencesDialog::kSrcOpenNI_PCL);
|
||||
|
||||
+354
-212
@@ -6,7 +6,7 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1032</width>
|
||||
<width>919</width>
|
||||
<height>869</height>
|
||||
</rect>
|
||||
</property>
|
||||
@@ -23,9 +23,9 @@
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>-2140</y>
|
||||
<width>998</width>
|
||||
<height>5850</height>
|
||||
<y>-1328</y>
|
||||
<width>885</width>
|
||||
<height>6169</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_13">
|
||||
@@ -1086,220 +1086,362 @@
|
||||
<property name="checkable">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_9" columnstretch="0,1">
|
||||
<item row="0" column="0">
|
||||
<widget class="QDoubleSpinBox" name="doubleSpinBox_filteringRadius">
|
||||
<property name="suffix">
|
||||
<string> m</string>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>0.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.010000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>0.020000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_20">
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout_9" columnstretch="0,1">
|
||||
<item row="3" column="0">
|
||||
<widget class="QDoubleSpinBox" name="doubleSpinBox_floorHeight">
|
||||
<property name="suffix">
|
||||
<string> m</string>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>-1000.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>1000.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.100000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>0.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QDoubleSpinBox" name="doubleSpinBox_filteringRadius">
|
||||
<property name="suffix">
|
||||
<string> m</string>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>0.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.010000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>0.020000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QSpinBox" name="spinBox_filteringMinNeighbors">
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>2</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QLabel" name="label_144">
|
||||
<property name="text">
|
||||
<string>Footprint length.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QDoubleSpinBox" name="doubleSpinBox_footprintWidth">
|
||||
<property name="suffix">
|
||||
<string> m</string>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>0.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>1000.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.100000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>0.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QDoubleSpinBox" name="doubleSpinBox_footprintLength">
|
||||
<property name="suffix">
|
||||
<string> m</string>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>0.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>1000.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.100000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>0.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QLabel" name="label_145">
|
||||
<property name="text">
|
||||
<string>Footprint height. If negative, the footprint is filtered between [-height:height] around the base frame, otherwise it is [0:height]</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QDoubleSpinBox" name="doubleSpinBox_ceilingHeight">
|
||||
<property name="suffix">
|
||||
<string> m</string>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>-1000.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>1000.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.100000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>0.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLabel" name="label_141">
|
||||
<property name="text">
|
||||
<string>Floor filtering height. This is done in map frame.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="label_110">
|
||||
<property name="text">
|
||||
<string>Search radius.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QLabel" name="label_143">
|
||||
<property name="text">
|
||||
<string>Footprint width.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QDoubleSpinBox" name="doubleSpinBox_footprintHeight">
|
||||
<property name="suffix">
|
||||
<string> m</string>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>-1000.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>1000.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.100000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>0.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="label_112">
|
||||
<property name="text">
|
||||
<string>Minimum neighbors in the search radius.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLabel" name="label_140">
|
||||
<property name="text">
|
||||
<string>Ceiling filtering height. This is done in map frame.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="label_110">
|
||||
<property name="text">
|
||||
<string>Search radius.</string>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_offAxisFiltering">
|
||||
<property name="title">
|
||||
<string>Off-Axis Filtering</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QSpinBox" name="spinBox_filteringMinNeighbors">
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>2</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="label_112">
|
||||
<property name="text">
|
||||
<string>Minimum neighbors in the search radius.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QDoubleSpinBox" name="doubleSpinBox_ceilingHeight">
|
||||
<property name="suffix">
|
||||
<string> m</string>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>-1000.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>1000.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.100000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>0.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLabel" name="label_140">
|
||||
<property name="text">
|
||||
<string>Ceiling filtering height.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QDoubleSpinBox" name="doubleSpinBox_floorHeight">
|
||||
<property name="suffix">
|
||||
<string> m</string>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>-1000.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>1000.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.100000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>0.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLabel" name="label_141">
|
||||
<property name="text">
|
||||
<string>Floor filtering height.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QDoubleSpinBox" name="doubleSpinBox_footprintWidth">
|
||||
<property name="suffix">
|
||||
<string> m</string>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>0.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>1000.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.100000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>0.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QLabel" name="label_143">
|
||||
<property name="text">
|
||||
<string>Footprint width.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QDoubleSpinBox" name="doubleSpinBox_footprintLength">
|
||||
<property name="suffix">
|
||||
<string> m</string>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>0.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>1000.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.100000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>0.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QLabel" name="label_144">
|
||||
<property name="text">
|
||||
<string>Footprint length.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QDoubleSpinBox" name="doubleSpinBox_footprintHeight">
|
||||
<property name="suffix">
|
||||
<string> m</string>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>-1000.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>1000.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.100000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>0.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QLabel" name="label_145">
|
||||
<property name="text">
|
||||
<string>Footprint height. If negative, the footprint is filtered between [-height:height] around the base frame, otherwise it is [0:height]</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_21">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_148">
|
||||
<property name="text">
|
||||
<string>Keep only points with normals aligned with one/any of the map X-Y-Z axes.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout_24">
|
||||
<item row="0" column="0">
|
||||
<widget class="QCheckBox" name="checkBox_offAxisFilteringPosX">
|
||||
<property name="text">
|
||||
<string>+X</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="3">
|
||||
<widget class="QCheckBox" name="checkBox_offAxisFilteringNegY">
|
||||
<property name="text">
|
||||
<string>-Y</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QCheckBox" name="checkBox_offAxisFilteringNegX">
|
||||
<property name="text">
|
||||
<string>-X</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QCheckBox" name="checkBox_offAxisFilteringPosY">
|
||||
<property name="text">
|
||||
<string>+Y</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="4">
|
||||
<widget class="QCheckBox" name="checkBox_offAxisFilteringPosZ">
|
||||
<property name="text">
|
||||
<string>+Z</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="5">
|
||||
<widget class="QCheckBox" name="checkBox_offAxisFilteringNegZ">
|
||||
<property name="text">
|
||||
<string>-Z</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="6">
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout_23" columnstretch="0,1">
|
||||
<item row="0" column="0">
|
||||
<widget class="QDoubleSpinBox" name="doubleSpinBox_offAxisFilteringAngle">
|
||||
<property name="suffix">
|
||||
<string> deg</string>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>0.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>179.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>10.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="label_146">
|
||||
<property name="text">
|
||||
<string>Max angle error to keep the points. </string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
|
||||
@@ -105,16 +105,6 @@
|
||||
<property name="title">
|
||||
<string>Select source</string>
|
||||
</property>
|
||||
<widget class="QMenu" name="menuImage">
|
||||
<property name="title">
|
||||
<string>RGB camera</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../GuiLib.qrc">
|
||||
<normaloff>:/images/webcam.png</normaloff>:/images/webcam.png</iconset>
|
||||
</property>
|
||||
<addaction name="actionUsbCamera"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuRGB_D_camera">
|
||||
<property name="title">
|
||||
<string>RGB-D camera</string>
|
||||
@@ -342,7 +332,6 @@
|
||||
</widget>
|
||||
<addaction name="menuRGB_D_camera"/>
|
||||
<addaction name="menuStereo_camera"/>
|
||||
<addaction name="menuImage"/>
|
||||
<addaction name="actionMore_options"/>
|
||||
</widget>
|
||||
<addaction name="menuSelect_source"/>
|
||||
@@ -1244,18 +1233,6 @@
|
||||
<string>240p</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionUsbCamera">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../GuiLib.qrc">
|
||||
<normaloff>:/images/webcam.png</normaloff>:/images/webcam.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Usb camera</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionPrint_loop_closure_IDs_to_console">
|
||||
<property name="text">
|
||||
<string>Print loop closure IDs to console</string>
|
||||
|
||||
Reference in New Issue
Block a user