mirror of
https://github.com/introlab/rtabmap.git
synced 2026-09-01 17:10:26 +08:00
Added CameraInfo class (added Camera tab in Statistics panel). Scans/userData are not saved anymore when Mem/BinDataKept=false. StereoACameraImages: Fixed error when scan path is not set. Refactoring of OdometryOpticalFlow class to provide variance when 3D->2D estimation is used.
This commit is contained in:
@@ -31,6 +31,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
#include <opencv2/highgui/highgui.hpp>
|
#include <opencv2/highgui/highgui.hpp>
|
||||||
#include "rtabmap/core/SensorData.h"
|
#include "rtabmap/core/SensorData.h"
|
||||||
|
#include "rtabmap/core/CameraInfo.h"
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <stack>
|
#include <stack>
|
||||||
#include <list>
|
#include <list>
|
||||||
@@ -50,12 +51,11 @@ class RTABMAP_EXP Camera
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~Camera();
|
virtual ~Camera();
|
||||||
SensorData takeImage();
|
SensorData takeImage(CameraInfo * info = 0);
|
||||||
|
|
||||||
virtual bool init(const std::string & calibrationFolder = ".", const std::string & cameraName = "") = 0;
|
virtual bool init(const std::string & calibrationFolder = ".", const std::string & cameraName = "") = 0;
|
||||||
virtual bool isCalibrated() const = 0;
|
virtual bool isCalibrated() const = 0;
|
||||||
virtual std::string getSerial() const = 0;
|
virtual std::string getSerial() const = 0;
|
||||||
int getNextSeqID() {return ++_seq;}
|
|
||||||
|
|
||||||
//getters
|
//getters
|
||||||
float getImageRate() const {return _imageRate;}
|
float getImageRate() const {return _imageRate;}
|
||||||
@@ -78,6 +78,8 @@ protected:
|
|||||||
*/
|
*/
|
||||||
virtual SensorData captureImage() = 0;
|
virtual SensorData captureImage() = 0;
|
||||||
|
|
||||||
|
int getNextSeqID() {return ++_seq;}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
float _imageRate;
|
float _imageRate;
|
||||||
Transform _localTransform;
|
Transform _localTransform;
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
#include <rtabmap/utilite/UEvent.h>
|
#include <rtabmap/utilite/UEvent.h>
|
||||||
#include "rtabmap/core/SensorData.h"
|
#include "rtabmap/core/SensorData.h"
|
||||||
|
#include "rtabmap/core/CameraInfo.h"
|
||||||
|
|
||||||
namespace rtabmap
|
namespace rtabmap
|
||||||
{
|
{
|
||||||
@@ -43,11 +44,11 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CameraEvent(const cv::Mat & image, int seq=0, double stamp = 0.0, const std::string & cameraName = "") :
|
CameraEvent(const cv::Mat & image, int seq=0, double stamp = 0.0, const std::string & cameraName = std::string()) :
|
||||||
UEvent(kCodeData),
|
UEvent(kCodeData),
|
||||||
data_(image, seq, stamp),
|
data_(image, seq, stamp)
|
||||||
cameraName_(cameraName)
|
|
||||||
{
|
{
|
||||||
|
cameraInfo_.cameraName_ = cameraName;
|
||||||
}
|
}
|
||||||
|
|
||||||
CameraEvent() :
|
CameraEvent() :
|
||||||
@@ -55,23 +56,36 @@ public:
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
CameraEvent(const SensorData & data, const std::string & cameraName = "") :
|
CameraEvent(const SensorData & data) :
|
||||||
|
UEvent(kCodeData),
|
||||||
|
data_(data)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
CameraEvent(const SensorData & data, const std::string & cameraName) :
|
||||||
|
UEvent(kCodeData),
|
||||||
|
data_(data)
|
||||||
|
{
|
||||||
|
cameraInfo_.cameraName_ = cameraName;
|
||||||
|
}
|
||||||
|
CameraEvent(const SensorData & data, const CameraInfo & cameraInfo) :
|
||||||
UEvent(kCodeData),
|
UEvent(kCodeData),
|
||||||
data_(data),
|
data_(data),
|
||||||
cameraName_(cameraName)
|
cameraInfo_(cameraInfo)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
// Image or descriptors
|
// Image or descriptors
|
||||||
const SensorData & data() const {return data_;}
|
const SensorData & data() const {return data_;}
|
||||||
const std::string & cameraName() const {return cameraName_;}
|
const std::string & cameraName() const {return cameraInfo_.cameraName_;}
|
||||||
|
const CameraInfo & info() const {return cameraInfo_;}
|
||||||
|
|
||||||
virtual ~CameraEvent() {}
|
virtual ~CameraEvent() {}
|
||||||
virtual std::string getClassName() const {return std::string("CameraEvent");}
|
virtual std::string getClassName() const {return std::string("CameraEvent");}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SensorData data_;
|
SensorData data_;
|
||||||
std::string cameraName_;
|
CameraInfo cameraInfo_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace rtabmap
|
} // namespace rtabmap
|
||||||
|
|||||||
56
corelib/include/rtabmap/core/CameraInfo.h
Normal file
56
corelib/include/rtabmap/core/CameraInfo.h
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
Copyright (c) 2010-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
* Neither the name of the Universite de Sherbrooke nor the
|
||||||
|
names of its contributors may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace rtabmap
|
||||||
|
{
|
||||||
|
|
||||||
|
class CameraInfo
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
CameraInfo() :
|
||||||
|
cameraName_(""),
|
||||||
|
id_(0),
|
||||||
|
timeCapture_(0.0),
|
||||||
|
timeDisparity_(0.0),
|
||||||
|
timeMirroring_(0.0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
virtual ~CameraInfo() {}
|
||||||
|
|
||||||
|
std::string cameraName_;
|
||||||
|
int id_;
|
||||||
|
float timeCapture_;
|
||||||
|
float timeDisparity_;
|
||||||
|
float timeMirroring_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace rtabmap
|
||||||
@@ -64,6 +64,7 @@ public:
|
|||||||
double getPnPReprojError() const {return _pnpReprojError;}
|
double getPnPReprojError() const {return _pnpReprojError;}
|
||||||
int getPnPFlags() const {return _pnpFlags;}
|
int getPnPFlags() const {return _pnpFlags;}
|
||||||
const Transform & previousTransform() const {return previousTransform_;}
|
const Transform & previousTransform() const {return previousTransform_;}
|
||||||
|
bool isVarianceFromInliersCount() const {return _varianceFromInliersCount;}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual Transform computeTransform(const SensorData & image, OdometryInfo * info = 0) = 0;
|
virtual Transform computeTransform(const SensorData & image, OdometryInfo * info = 0) = 0;
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ Transform RTABMAP_EXP estimateMotion3DTo2D(
|
|||||||
int flagsPnP = 0,
|
int flagsPnP = 0,
|
||||||
const Transform & guess = Transform::getIdentity(),
|
const Transform & guess = Transform::getIdentity(),
|
||||||
const std::map<int, pcl::PointXYZ> & words3B = std::map<int, pcl::PointXYZ>(),
|
const std::map<int, pcl::PointXYZ> & words3B = std::map<int, pcl::PointXYZ>(),
|
||||||
double * varianceOut = 0,
|
double * varianceOut = 0, // mean reproj error if words3B is not set
|
||||||
std::vector<int> * matchesOut = 0,
|
std::vector<int> * matchesOut = 0,
|
||||||
std::vector<int> * inliersOut = 0);
|
std::vector<int> * inliersOut = 0);
|
||||||
|
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ Camera::~Camera()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SensorData Camera::takeImage()
|
SensorData Camera::takeImage(CameraInfo * info)
|
||||||
{
|
{
|
||||||
bool warnFrameRateTooHigh = false;
|
bool warnFrameRateTooHigh = false;
|
||||||
float actualFrameRate = 0;
|
float actualFrameRate = 0;
|
||||||
@@ -91,14 +91,20 @@ SensorData Camera::takeImage()
|
|||||||
|
|
||||||
UTimer timer;
|
UTimer timer;
|
||||||
SensorData data = this->captureImage();
|
SensorData data = this->captureImage();
|
||||||
|
double captureTime = timer.ticks();
|
||||||
if(warnFrameRateTooHigh)
|
if(warnFrameRateTooHigh)
|
||||||
{
|
{
|
||||||
UWARN("Camera: Cannot reach target image rate %f Hz, current rate is %f Hz and capture time = %f s.",
|
UWARN("Camera: Cannot reach target image rate %f Hz, current rate is %f Hz and capture time = %f s.",
|
||||||
_imageRate, actualFrameRate, timer.ticks());
|
_imageRate, actualFrameRate, captureTime);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
UDEBUG("Time capturing image = %fs", timer.ticks());
|
UDEBUG("Time capturing image = %fs", captureTime);
|
||||||
|
}
|
||||||
|
if(info)
|
||||||
|
{
|
||||||
|
info->id_ = data.id();
|
||||||
|
info->timeCapture_ = captureTime;
|
||||||
}
|
}
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -66,7 +66,8 @@ CameraImages::CameraImages(const std::string & path,
|
|||||||
_count(0),
|
_count(0),
|
||||||
_dir(0),
|
_dir(0),
|
||||||
_countScan(0),
|
_countScan(0),
|
||||||
_scanDir(0)
|
_scanDir(0),
|
||||||
|
_scanMaxPts(0)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -152,6 +153,7 @@ bool CameraImages::init(const std::string & calibrationFolder, const std::string
|
|||||||
}
|
}
|
||||||
if(!_scanPath.empty())
|
if(!_scanPath.empty())
|
||||||
{
|
{
|
||||||
|
UINFO("scan path=%s", _scanPath.c_str());
|
||||||
_scanDir = new UDirectory(_scanPath, "pcd bin"); // "bin" is for KITTI format
|
_scanDir = new UDirectory(_scanPath, "pcd bin"); // "bin" is for KITTI format
|
||||||
if(_scanPath[_scanPath.size()-1] != '\\' && _scanPath[_scanPath.size()-1] != '/')
|
if(_scanPath[_scanPath.size()-1] != '\\' && _scanPath[_scanPath.size()-1] != '/')
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -67,9 +67,9 @@ void CameraThread::setImageRate(float imageRate)
|
|||||||
|
|
||||||
void CameraThread::mainLoop()
|
void CameraThread::mainLoop()
|
||||||
{
|
{
|
||||||
UTimer timer;
|
|
||||||
UDEBUG("");
|
UDEBUG("");
|
||||||
SensorData data = _camera->takeImage();
|
CameraInfo info;
|
||||||
|
SensorData data = _camera->takeImage(&info);
|
||||||
|
|
||||||
if(!data.imageRaw().empty())
|
if(!data.imageRaw().empty())
|
||||||
{
|
{
|
||||||
@@ -79,6 +79,7 @@ void CameraThread::mainLoop()
|
|||||||
}
|
}
|
||||||
if(_mirroring && data.cameraModels().size() == 1)
|
if(_mirroring && data.cameraModels().size() == 1)
|
||||||
{
|
{
|
||||||
|
UTimer timer;
|
||||||
cv::Mat tmpRgb;
|
cv::Mat tmpRgb;
|
||||||
cv::flip(data.imageRaw(), tmpRgb, 1);
|
cv::flip(data.imageRaw(), tmpRgb, 1);
|
||||||
data.setImageRaw(tmpRgb);
|
data.setImageRaw(tmpRgb);
|
||||||
@@ -98,9 +99,11 @@ void CameraThread::mainLoop()
|
|||||||
cv::flip(data.depthRaw(), tmpDepth, 1);
|
cv::flip(data.depthRaw(), tmpDepth, 1);
|
||||||
data.setDepthOrRightRaw(tmpDepth);
|
data.setDepthOrRightRaw(tmpDepth);
|
||||||
}
|
}
|
||||||
|
info.timeMirroring_ = timer.ticks();
|
||||||
}
|
}
|
||||||
if(_stereoToDepth && data.stereoCameraModel().isValid() && !data.rightRaw().empty())
|
if(_stereoToDepth && data.stereoCameraModel().isValid() && !data.rightRaw().empty())
|
||||||
{
|
{
|
||||||
|
UTimer timer;
|
||||||
cv::Mat depth = util2d::depthFromDisparity(
|
cv::Mat depth = util2d::depthFromDisparity(
|
||||||
util2d::disparityFromStereoImages(data.imageRaw(), data.rightRaw()),
|
util2d::disparityFromStereoImages(data.imageRaw(), data.rightRaw()),
|
||||||
data.stereoCameraModel().left().fx(),
|
data.stereoCameraModel().left().fx(),
|
||||||
@@ -108,9 +111,11 @@ void CameraThread::mainLoop()
|
|||||||
data.setCameraModel(data.stereoCameraModel().left());
|
data.setCameraModel(data.stereoCameraModel().left());
|
||||||
data.setDepthOrRightRaw(depth);
|
data.setDepthOrRightRaw(depth);
|
||||||
data.setStereoCameraModel(StereoCameraModel());
|
data.setStereoCameraModel(StereoCameraModel());
|
||||||
|
info.timeDisparity_ = timer.ticks();
|
||||||
|
UINFO("Computing disparity = %f s", info.timeDisparity_);
|
||||||
}
|
}
|
||||||
|
info.cameraName_ = _camera->getSerial();
|
||||||
this->post(new CameraEvent(data, _camera->getSerial()));
|
this->post(new CameraEvent(data, info));
|
||||||
}
|
}
|
||||||
else if(!this->isKilled())
|
else if(!this->isKilled())
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -3548,13 +3548,6 @@ Signature * Memory::createSignature(const SensorData & data, const Transform & p
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
rtabmap::CompressionThread ctDepth2d(laserScan);
|
|
||||||
rtabmap::CompressionThread ctUserData(data.userDataRaw());
|
|
||||||
ctDepth2d.start();
|
|
||||||
ctUserData.start();
|
|
||||||
ctDepth2d.join();
|
|
||||||
ctUserData.join();
|
|
||||||
|
|
||||||
s = new Signature(id,
|
s = new Signature(id,
|
||||||
_idMapCount,
|
_idMapCount,
|
||||||
isIntermediateNode?-1:0, // tag intermediate nodes as weight=-1
|
isIntermediateNode?-1:0, // tag intermediate nodes as weight=-1
|
||||||
@@ -3563,25 +3556,23 @@ Signature * Memory::createSignature(const SensorData & data, const Transform & p
|
|||||||
pose,
|
pose,
|
||||||
stereoCameraModel.isValid()?
|
stereoCameraModel.isValid()?
|
||||||
SensorData(
|
SensorData(
|
||||||
ctDepth2d.getCompressedData(),
|
cv::Mat(),
|
||||||
maxLaserScanMaxPts,
|
0,
|
||||||
data.laserScanMaxRange(),
|
0,
|
||||||
cv::Mat(),
|
cv::Mat(),
|
||||||
cv::Mat(),
|
cv::Mat(),
|
||||||
stereoCameraModel,
|
stereoCameraModel,
|
||||||
id,
|
id,
|
||||||
0,
|
0):
|
||||||
ctUserData.getCompressedData()):
|
|
||||||
SensorData(
|
SensorData(
|
||||||
ctDepth2d.getCompressedData(),
|
cv::Mat(),
|
||||||
maxLaserScanMaxPts,
|
0,
|
||||||
data.laserScanMaxRange(),
|
0,
|
||||||
cv::Mat(),
|
cv::Mat(),
|
||||||
cv::Mat(),
|
cv::Mat(),
|
||||||
cameraModels,
|
cameraModels,
|
||||||
id,
|
id,
|
||||||
0,
|
0));
|
||||||
ctUserData.getCompressedData()));
|
|
||||||
}
|
}
|
||||||
s->setWords(words);
|
s->setWords(words);
|
||||||
s->setWords3(words3D);
|
s->setWords3(words3D);
|
||||||
|
|||||||
@@ -62,6 +62,7 @@ Odometry::Odometry(const rtabmap::ParametersMap & parameters) :
|
|||||||
{
|
{
|
||||||
Parameters::parse(parameters, Parameters::kOdomResetCountdown(), _resetCountdown);
|
Parameters::parse(parameters, Parameters::kOdomResetCountdown(), _resetCountdown);
|
||||||
Parameters::parse(parameters, Parameters::kVisMinInliers(), _minInliers);
|
Parameters::parse(parameters, Parameters::kVisMinInliers(), _minInliers);
|
||||||
|
UASSERT(_minInliers >= 1);
|
||||||
Parameters::parse(parameters, Parameters::kVisInlierDistance(), _inlierDistance);
|
Parameters::parse(parameters, Parameters::kVisInlierDistance(), _inlierDistance);
|
||||||
Parameters::parse(parameters, Parameters::kVisIterations(), _iterations);
|
Parameters::parse(parameters, Parameters::kVisIterations(), _iterations);
|
||||||
Parameters::parse(parameters, Parameters::kVisRefineIterations(), _refineIterations);
|
Parameters::parse(parameters, Parameters::kVisRefineIterations(), _refineIterations);
|
||||||
|
|||||||
@@ -65,6 +65,7 @@ OdometryBOW::OdometryBOW(const ParametersMap & parameters) :
|
|||||||
customParameters.insert(ParametersPair(Parameters::kMemBinDataKept(), "false"));
|
customParameters.insert(ParametersPair(Parameters::kMemBinDataKept(), "false"));
|
||||||
customParameters.insert(ParametersPair(Parameters::kMemSTMSize(), "0"));
|
customParameters.insert(ParametersPair(Parameters::kMemSTMSize(), "0"));
|
||||||
customParameters.insert(ParametersPair(Parameters::kMemNotLinkedNodesKept(), "false"));
|
customParameters.insert(ParametersPair(Parameters::kMemNotLinkedNodesKept(), "false"));
|
||||||
|
customParameters.insert(ParametersPair(Parameters::kMemSaveDepth16Format(), "false"));
|
||||||
int nn = Parameters::defaultVisNNType();
|
int nn = Parameters::defaultVisNNType();
|
||||||
float nndr = Parameters::defaultVisNNDR();
|
float nndr = Parameters::defaultVisNNDR();
|
||||||
int featureType = Parameters::defaultVisFeatureType();
|
int featureType = Parameters::defaultVisFeatureType();
|
||||||
@@ -120,7 +121,6 @@ OdometryBOW::OdometryBOW(const ParametersMap & parameters) :
|
|||||||
// init the local map with a all 3D features contained in the database
|
// init the local map with a all 3D features contained in the database
|
||||||
customParameters.insert(ParametersPair(Parameters::kMemIncrementalMemory(), "false"));
|
customParameters.insert(ParametersPair(Parameters::kMemIncrementalMemory(), "false"));
|
||||||
customParameters.insert(ParametersPair(Parameters::kMemInitWMWithAllNodes(), "true"));
|
customParameters.insert(ParametersPair(Parameters::kMemInitWMWithAllNodes(), "true"));
|
||||||
customParameters.insert(ParametersPair(Parameters::kMemSaveDepth16Format(), "false"));
|
|
||||||
_memory = new Memory(customParameters);
|
_memory = new Memory(customParameters);
|
||||||
if(!_memory->init(_fixedLocalMapPath, false, ParametersMap()))
|
if(!_memory->init(_fixedLocalMapPath, false, ParametersMap()))
|
||||||
{
|
{
|
||||||
@@ -257,7 +257,7 @@ Transform OdometryBOW::computeTransform(
|
|||||||
this->getPnPFlags(),
|
this->getPnPFlags(),
|
||||||
this->getPose(),
|
this->getPose(),
|
||||||
uMultimapToMap(newSignature->getWords3()),
|
uMultimapToMap(newSignature->getWords3()),
|
||||||
&variance,
|
isVarianceFromInliersCount()?0:&variance, // don't compute variance if we use inliers
|
||||||
&matches,
|
&matches,
|
||||||
&inliers);
|
&inliers);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -218,7 +218,9 @@ Transform OdometryOpticalFlow::computeTransform(
|
|||||||
int ki = 0;
|
int ki = 0;
|
||||||
for(unsigned int i=0; i<status.size(); ++i)
|
for(unsigned int i=0; i<status.size(); ++i)
|
||||||
{
|
{
|
||||||
if(status[i])
|
if(status[i] &&
|
||||||
|
uIsInBounds(newCorners[i].x, 0.0f, float(data.depthOrRightRaw().cols)) &&
|
||||||
|
uIsInBounds(newCorners[i].y, 0.0f, float(data.depthOrRightRaw().rows)))
|
||||||
{
|
{
|
||||||
refCorners3DKept->at(ki) = refCorners3D_->at(i);
|
refCorners3DKept->at(ki) = refCorners3D_->at(i);
|
||||||
objectPointsKept[ki] = objectPoints[i];
|
objectPointsKept[ki] = objectPoints[i];
|
||||||
@@ -232,23 +234,56 @@ Transform OdometryOpticalFlow::computeTransform(
|
|||||||
refCornersKept.resize(ki);
|
refCornersKept.resize(ki);
|
||||||
newCornersKept.resize(ki);
|
newCornersKept.resize(ki);
|
||||||
|
|
||||||
if(ki && ki >= this->getMinInliers())
|
correspondences = ki;
|
||||||
|
|
||||||
|
if(correspondences && correspondences >= this->getMinInliers())
|
||||||
{
|
{
|
||||||
|
// get new 3D points
|
||||||
|
pcl::PointCloud<pcl::PointXYZ>::Ptr newCorners3DKept;
|
||||||
|
if(!isVarianceFromInliersCount() || this->getEstimationType() != 1)
|
||||||
|
{
|
||||||
|
// Don't compute the new 3D points if the variance is not required on PnP estimation
|
||||||
|
if(!data.rightRaw().empty())
|
||||||
|
{
|
||||||
|
// stereo
|
||||||
|
newCorners3DKept = util3d::generateKeypoints3DStereo(
|
||||||
|
newCornersKept,
|
||||||
|
newLeftFrame,
|
||||||
|
data.rightRaw(),
|
||||||
|
data.stereoCameraModel().left().fx(),
|
||||||
|
data.stereoCameraModel().baseline(),
|
||||||
|
data.stereoCameraModel().left().cx(),
|
||||||
|
data.stereoCameraModel().left().cy(),
|
||||||
|
data.stereoCameraModel().left().localTransform(),
|
||||||
|
stereoWinSize_,
|
||||||
|
stereoMaxLevel_,
|
||||||
|
stereoIterations_,
|
||||||
|
stereoEps_,
|
||||||
|
stereoMaxSlope_);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//depth
|
||||||
|
std::vector<cv::KeyPoint> newCornersKeptKpt;
|
||||||
|
cv::KeyPoint::convert(newCornersKept, newCornersKeptKpt);
|
||||||
|
newCorners3DKept = util3d::generateKeypoints3DDepth(
|
||||||
|
newCornersKeptKpt,
|
||||||
|
data.depthRaw(),
|
||||||
|
data.cameraModels());
|
||||||
|
}
|
||||||
|
UASSERT(newCorners3DKept.get() != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<int> inliersV;
|
||||||
if(this->getEstimationType() == 1) // PnP
|
if(this->getEstimationType() == 1) // PnP
|
||||||
{
|
{
|
||||||
// find correspondences
|
|
||||||
if(this->isInfoDataFilled() && info)
|
if(this->isInfoDataFilled() && info)
|
||||||
{
|
{
|
||||||
info->refCorners = refCornersKept;
|
info->refCorners = refCornersKept;
|
||||||
info->newCorners = newCornersKept;
|
info->newCorners = newCornersKept;
|
||||||
}
|
}
|
||||||
|
|
||||||
correspondences = refCornersKept.size();
|
|
||||||
|
|
||||||
if(correspondences >= this->getMinInliers())
|
|
||||||
{
|
|
||||||
//PnPRansac
|
//PnPRansac
|
||||||
std::vector<int> inliersV;
|
|
||||||
cv::solvePnPRansac(
|
cv::solvePnPRansac(
|
||||||
objectPointsKept,
|
objectPointsKept,
|
||||||
newCornersKept,
|
newCornersKept,
|
||||||
@@ -277,7 +312,31 @@ Transform OdometryOpticalFlow::computeTransform(
|
|||||||
{
|
{
|
||||||
// make it incremental
|
// make it incremental
|
||||||
output = (localTransform * pnp).inverse();
|
output = (localTransform * pnp).inverse();
|
||||||
variance = 1; // FIXME, is there a way to compute a variance from the PNP approach?
|
|
||||||
|
// compute variance from 3D correspondences error
|
||||||
|
variance = 1;
|
||||||
|
if(!isVarianceFromInliersCount())
|
||||||
|
{
|
||||||
|
UASSERT(objectPointsKept.size() == newCorners3DKept->size());
|
||||||
|
std::vector<float> errorSqrdDists(inliersV.size());
|
||||||
|
int oi = 0;
|
||||||
|
for(unsigned int i=0; i<inliersV.size(); ++i)
|
||||||
|
{
|
||||||
|
if(pcl::isFinite(newCorners3DKept->at(inliersV[i])))
|
||||||
|
{
|
||||||
|
const cv::Point3f & objPt = objectPointsKept[inliersV[i]];
|
||||||
|
pcl::PointXYZ newPt = util3d::transformPoint(newCorners3DKept->at(inliersV[i]), output);
|
||||||
|
errorSqrdDists[oi++] = uNormSquared(objPt.x-newPt.x, objPt.y-newPt.y, objPt.z-newPt.z);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
errorSqrdDists.resize(oi);
|
||||||
|
if(errorSqrdDists.size())
|
||||||
|
{
|
||||||
|
std::sort(errorSqrdDists.begin(), errorSqrdDists.end());
|
||||||
|
double median_error_sqr = (double)errorSqrdDists[errorSqrdDists.size () >> 1];
|
||||||
|
variance = 2.1981 * median_error_sqr;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -291,12 +350,7 @@ Transform OdometryOpticalFlow::computeTransform(
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
UWARN("Not enough correspondences (%d < %d)", correspondences, this->getMinInliers());
|
// Get 3D correspondences (remove NaN)
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Get 3D correspondences
|
|
||||||
pcl::PointCloud<pcl::PointXYZ>::Ptr correspondencesRef(new pcl::PointCloud<pcl::PointXYZ>);
|
pcl::PointCloud<pcl::PointXYZ>::Ptr correspondencesRef(new pcl::PointCloud<pcl::PointXYZ>);
|
||||||
pcl::PointCloud<pcl::PointXYZ>::Ptr correspondencesNew(new pcl::PointCloud<pcl::PointXYZ>);
|
pcl::PointCloud<pcl::PointXYZ>::Ptr correspondencesNew(new pcl::PointCloud<pcl::PointXYZ>);
|
||||||
correspondencesRef->resize(newCornersKept.size());
|
correspondencesRef->resize(newCornersKept.size());
|
||||||
@@ -307,57 +361,15 @@ Transform OdometryOpticalFlow::computeTransform(
|
|||||||
info->newCorners.resize(newCornersKept.size());
|
info->newCorners.resize(newCornersKept.size());
|
||||||
}
|
}
|
||||||
int oi = 0;
|
int oi = 0;
|
||||||
if(!data.rightRaw().empty())
|
UASSERT(newCorners3DKept->size() == newCornersKept.size());
|
||||||
{
|
|
||||||
// stereo
|
|
||||||
pcl::PointCloud<pcl::PointXYZ>::Ptr newCorners3D = util3d::generateKeypoints3DStereo(
|
|
||||||
newCornersKept,
|
|
||||||
newLeftFrame,
|
|
||||||
data.rightRaw(),
|
|
||||||
data.stereoCameraModel().left().fx(),
|
|
||||||
data.stereoCameraModel().baseline(),
|
|
||||||
data.stereoCameraModel().left().cx(),
|
|
||||||
data.stereoCameraModel().left().cy(),
|
|
||||||
Transform::getIdentity(),
|
|
||||||
stereoWinSize_,
|
|
||||||
stereoMaxLevel_,
|
|
||||||
stereoIterations_,
|
|
||||||
stereoEps_,
|
|
||||||
stereoMaxSlope_);
|
|
||||||
|
|
||||||
UASSERT(newCorners3D->size() == refCorners3DKept->size());
|
|
||||||
for(unsigned int i=0; i<newCorners3D->size(); ++i)
|
|
||||||
{
|
|
||||||
if(pcl::isFinite(newCorners3D->at(i)) && (this->getMaxDepth() <= 0.0f || newCorners3D->at(i).z < this->getMaxDepth()))
|
|
||||||
{
|
|
||||||
//Add 3D correspondences!
|
|
||||||
correspondencesRef->at(oi) = refCorners3DKept->at(i);
|
|
||||||
correspondencesNew->at(oi) = util3d::transformPoint(newCorners3D->at(i), localTransform);
|
|
||||||
if(this->isInfoDataFilled() && info)
|
|
||||||
{
|
|
||||||
info->refCorners[oi] = refCornersKept[i];
|
|
||||||
info->newCorners[oi] = newCornersKept[i];
|
|
||||||
}
|
|
||||||
++oi;
|
|
||||||
}
|
|
||||||
}// end loop
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//depth
|
|
||||||
for(unsigned int i=0; i<newCornersKept.size(); ++i)
|
for(unsigned int i=0; i<newCornersKept.size(); ++i)
|
||||||
{
|
{
|
||||||
if(uIsInBounds(newCornersKept[i].x, 0.0f, float(data.depthRaw().cols)) &&
|
if(pcl::isFinite(newCorners3DKept->at(i)) &&
|
||||||
uIsInBounds(newCornersKept[i].y, 0.0f, float(data.depthRaw().rows)))
|
(this->getMaxDepth() == 0.0f || newCorners3DKept->at(i).z < this->getMaxDepth()))
|
||||||
{
|
|
||||||
pcl::PointXYZ pt = util3d::projectDepthTo3D(data.depthRaw(), newCornersKept[i].x, newCorners[i].y,
|
|
||||||
data.cameraModels()[0].cx(), data.cameraModels()[0].cy(), data.cameraModels()[0].fx(), data.cameraModels()[0].fy(), true);
|
|
||||||
if(pcl::isFinite(pt) &&
|
|
||||||
(this->getMaxDepth() == 0.0f || pt.z < this->getMaxDepth()))
|
|
||||||
{
|
{
|
||||||
//Add 3D correspondences!
|
//Add 3D correspondences!
|
||||||
correspondencesRef->at(oi) = refCorners3DKept->at(i);
|
correspondencesRef->at(oi) = refCorners3DKept->at(i);
|
||||||
correspondencesNew->at(oi) = util3d::transformPoint(pt, localTransform);
|
correspondencesNew->at(oi) = newCorners3DKept->at(i);
|
||||||
|
|
||||||
if(this->isInfoDataFilled() && info)
|
if(this->isInfoDataFilled() && info)
|
||||||
{
|
{
|
||||||
@@ -367,8 +379,6 @@ Transform OdometryOpticalFlow::computeTransform(
|
|||||||
++oi;
|
++oi;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
correspondencesRef->resize(oi);
|
correspondencesRef->resize(oi);
|
||||||
correspondencesNew->resize(oi);
|
correspondencesNew->resize(oi);
|
||||||
if(this->isInfoDataFilled() && info)
|
if(this->isInfoDataFilled() && info)
|
||||||
@@ -381,7 +391,6 @@ Transform OdometryOpticalFlow::computeTransform(
|
|||||||
|
|
||||||
if(correspondences >= this->getMinInliers())
|
if(correspondences >= this->getMinInliers())
|
||||||
{
|
{
|
||||||
std::vector<int> inliersV;
|
|
||||||
UTimer timerRANSAC;
|
UTimer timerRANSAC;
|
||||||
Transform t = util3d::transformFromXYZCorrespondences(
|
Transform t = util3d::transformFromXYZCorrespondences(
|
||||||
correspondencesNew,
|
correspondencesNew,
|
||||||
@@ -402,17 +411,17 @@ Transform OdometryOpticalFlow::computeTransform(
|
|||||||
{
|
{
|
||||||
UWARN("Transform not valid (inliers = %d/%d)", inliers, correspondences);
|
UWARN("Transform not valid (inliers = %d/%d)", inliers, correspondences);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(this->isInfoDataFilled() && info)
|
|
||||||
{
|
|
||||||
info->cornerInliers = inliersV;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
UWARN("Not enough correspondences (%d)", correspondences);
|
UWARN("Not enough correspondences (%d)", correspondences);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(this->isInfoDataFilled() && info)
|
||||||
|
{
|
||||||
|
info->cornerInliers = inliersV;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -458,6 +467,7 @@ Transform OdometryOpticalFlow::computeTransform(
|
|||||||
newCorners3D->resize(newCorners.size());
|
newCorners3D->resize(newCorners.size());
|
||||||
std::vector<cv::Point2f> newCornersFiltered(newCorners.size());
|
std::vector<cv::Point2f> newCornersFiltered(newCorners.size());
|
||||||
int oi=0;
|
int oi=0;
|
||||||
|
UTimer corner3dTimer;
|
||||||
if(!data.rightRaw().empty())
|
if(!data.rightRaw().empty())
|
||||||
{
|
{
|
||||||
/// stereo
|
/// stereo
|
||||||
@@ -515,6 +525,7 @@ Transform OdometryOpticalFlow::computeTransform(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
UDEBUG("Computing 3d corners = %f s", corner3dTimer.ticks());
|
||||||
newCornersFiltered.resize(oi);
|
newCornersFiltered.resize(oi);
|
||||||
newCorners3D->resize(oi);
|
newCorners3D->resize(oi);
|
||||||
|
|
||||||
|
|||||||
@@ -320,7 +320,7 @@ Transform RegistrationVis::computeTransformation(
|
|||||||
_PnPFlags,
|
_PnPFlags,
|
||||||
Transform::getIdentity(),
|
Transform::getIdentity(),
|
||||||
uMultimapToMap(*words3To),
|
uMultimapToMap(*words3To),
|
||||||
&variance,
|
_varianceFromInliersCount?0:&variance,
|
||||||
0,
|
0,
|
||||||
&inliersV);
|
&inliersV);
|
||||||
inliersCount = (int)inliersV.size();
|
inliersCount = (int)inliersV.size();
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include "rtabmap/core/EpipolarGeometry.h"
|
#include "rtabmap/core/EpipolarGeometry.h"
|
||||||
|
|
||||||
#include <rtabmap/utilite/ULogger.h>
|
#include <rtabmap/utilite/ULogger.h>
|
||||||
|
#include <rtabmap/utilite/UConversion.h>
|
||||||
#include <rtabmap/utilite/UMath.h>
|
#include <rtabmap/utilite/UMath.h>
|
||||||
|
|
||||||
#include <opencv2/video/tracking.hpp>
|
#include <opencv2/video/tracking.hpp>
|
||||||
@@ -71,7 +72,9 @@ pcl::PointCloud<pcl::PointXYZ>::Ptr generateKeypoints3DDepth(
|
|||||||
for(unsigned int i=0; i!=keypoints.size(); ++i)
|
for(unsigned int i=0; i!=keypoints.size(); ++i)
|
||||||
{
|
{
|
||||||
int cameraIndex = int(keypoints[i].pt.x / subImageWidth);
|
int cameraIndex = int(keypoints[i].pt.x / subImageWidth);
|
||||||
UASSERT(cameraIndex < (int)cameraModels.size());
|
UASSERT_MSG(cameraIndex < (int)cameraModels.size(),
|
||||||
|
uFormat("cameraIndex=%d, models=%d, kpt.x=%f, subImageWidth=%f",
|
||||||
|
cameraIndex, (int)cameraModels.size(), keypoints[i].pt.x, subImageWidth).c_str());
|
||||||
pcl::PointXYZ pt = util3d::projectDepthTo3D(
|
pcl::PointXYZ pt = util3d::projectDepthTo3D(
|
||||||
depth,
|
depth,
|
||||||
keypoints[i].pt.x-subImageWidth*cameraIndex,
|
keypoints[i].pt.x-subImageWidth*cameraIndex,
|
||||||
|
|||||||
@@ -159,6 +159,18 @@ Transform estimateMotion3DTo2D(
|
|||||||
*varianceOut = 2.1981 * median_error_sqr;
|
*varianceOut = 2.1981 * median_error_sqr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if(varianceOut)
|
||||||
|
{
|
||||||
|
// compute variance, which is the rms of reprojection errors
|
||||||
|
std::vector<cv::Point2f> imagePointsReproj;
|
||||||
|
cv::projectPoints(objectPoints, rvec, tvec, K, cv::Mat(), imagePointsReproj);
|
||||||
|
float err = 0.0f;
|
||||||
|
for(unsigned int i=0; i<inliers.size(); ++i)
|
||||||
|
{
|
||||||
|
err += uNormSquared(imagePoints.at(inliers[i]).x - imagePointsReproj.at(inliers[i]).x, imagePoints.at(inliers[i]).y - imagePointsReproj.at(inliers[i]).y);
|
||||||
|
}
|
||||||
|
*varianceOut = std::sqrt(err/float(inliers.size()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include "rtabmap/core/RtabmapEvent.h"
|
#include "rtabmap/core/RtabmapEvent.h"
|
||||||
#include "rtabmap/core/SensorData.h"
|
#include "rtabmap/core/SensorData.h"
|
||||||
#include "rtabmap/core/OdometryEvent.h"
|
#include "rtabmap/core/OdometryEvent.h"
|
||||||
|
#include "rtabmap/core/CameraInfo.h"
|
||||||
#include "rtabmap/gui/PreferencesDialog.h"
|
#include "rtabmap/gui/PreferencesDialog.h"
|
||||||
|
|
||||||
#include <pcl/point_cloud.h>
|
#include <pcl/point_cloud.h>
|
||||||
@@ -165,6 +166,7 @@ private slots:
|
|||||||
void selectScreenCaptureFormat(bool checked);
|
void selectScreenCaptureFormat(bool checked);
|
||||||
void takeScreenshot();
|
void takeScreenshot();
|
||||||
void updateElapsedTime();
|
void updateElapsedTime();
|
||||||
|
void processCameraInfo(const rtabmap::CameraInfo & info);
|
||||||
void processOdometry(const rtabmap::OdometryEvent & odom);
|
void processOdometry(const rtabmap::OdometryEvent & odom);
|
||||||
void applyPrefSettings(PreferencesDialog::PANEL_FLAGS flags);
|
void applyPrefSettings(PreferencesDialog::PANEL_FLAGS flags);
|
||||||
void applyPrefSettings(const rtabmap::ParametersMap & parameters);
|
void applyPrefSettings(const rtabmap::ParametersMap & parameters);
|
||||||
@@ -201,6 +203,7 @@ private slots:
|
|||||||
|
|
||||||
signals:
|
signals:
|
||||||
void statsReceived(const rtabmap::Statistics &);
|
void statsReceived(const rtabmap::Statistics &);
|
||||||
|
void cameraInfoReceived(const rtabmap::CameraInfo &);
|
||||||
void odometryReceived(const rtabmap::OdometryEvent &);
|
void odometryReceived(const rtabmap::OdometryEvent &);
|
||||||
void thresholdsChanged(int, int);
|
void thresholdsChanged(int, int);
|
||||||
void stateChanged(MainWindow::State);
|
void stateChanged(MainWindow::State);
|
||||||
|
|||||||
@@ -448,6 +448,9 @@ MainWindow::MainWindow(PreferencesDialog * prefDialog, QWidget * parent) :
|
|||||||
qRegisterMetaType<rtabmap::Statistics>("rtabmap::Statistics");
|
qRegisterMetaType<rtabmap::Statistics>("rtabmap::Statistics");
|
||||||
connect(this, SIGNAL(statsReceived(rtabmap::Statistics)), this, SLOT(processStats(rtabmap::Statistics)));
|
connect(this, SIGNAL(statsReceived(rtabmap::Statistics)), this, SLOT(processStats(rtabmap::Statistics)));
|
||||||
|
|
||||||
|
qRegisterMetaType<rtabmap::CameraInfo>("rtabmap::CameraInfo");
|
||||||
|
connect(this, SIGNAL(cameraInfoReceived(rtabmap::CameraInfo)), this, SLOT(processCameraInfo(rtabmap::CameraInfo)));
|
||||||
|
|
||||||
qRegisterMetaType<rtabmap::OdometryEvent>("rtabmap::OdometryEvent");
|
qRegisterMetaType<rtabmap::OdometryEvent>("rtabmap::OdometryEvent");
|
||||||
connect(this, SIGNAL(odometryReceived(rtabmap::OdometryEvent)), this, SLOT(processOdometry(rtabmap::OdometryEvent)));
|
connect(this, SIGNAL(odometryReceived(rtabmap::OdometryEvent)), this, SLOT(processOdometry(rtabmap::OdometryEvent)));
|
||||||
|
|
||||||
@@ -688,6 +691,10 @@ void MainWindow::handleEvent(UEvent* anEvent)
|
|||||||
}
|
}
|
||||||
emit noMoreImagesReceived();
|
emit noMoreImagesReceived();
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
emit cameraInfoReceived(cameraEvent->info());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if(anEvent->getClassName().compare("OdometryEvent") == 0)
|
else if(anEvent->getClassName().compare("OdometryEvent") == 0)
|
||||||
{
|
{
|
||||||
@@ -729,6 +736,13 @@ void MainWindow::handleEvent(UEvent* anEvent)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::processCameraInfo(const rtabmap::CameraInfo & info)
|
||||||
|
{
|
||||||
|
_ui->statsToolBox->updateStat("Camera/Time capturing/ms", (float)info.id_, (float)info.timeCapture_*1000.0);
|
||||||
|
_ui->statsToolBox->updateStat("Camera/Time disparity/ms", (float)info.id_, (float)info.timeDisparity_*1000.0);
|
||||||
|
_ui->statsToolBox->updateStat("Camera/Time mirroring/ms", (float)info.id_, (float)info.timeMirroring_*1000.0);
|
||||||
|
}
|
||||||
|
|
||||||
void MainWindow::processOdometry(const rtabmap::OdometryEvent & odom)
|
void MainWindow::processOdometry(const rtabmap::OdometryEvent & odom)
|
||||||
{
|
{
|
||||||
_processingOdometry = true;
|
_processingOdometry = true;
|
||||||
@@ -2999,6 +3013,7 @@ void MainWindow::startDetection()
|
|||||||
|
|
||||||
UEventsManager::addHandler(_odomThread);
|
UEventsManager::addHandler(_odomThread);
|
||||||
UEventsManager::createPipe(_camera, _odomThread, "CameraEvent");
|
UEventsManager::createPipe(_camera, _odomThread, "CameraEvent");
|
||||||
|
UEventsManager::createPipe(_camera, this, "CameraEvent");
|
||||||
_odomThread->start();
|
_odomThread->start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3059,6 +3074,7 @@ void MainWindow::startDetection()
|
|||||||
if(_odomThread)
|
if(_odomThread)
|
||||||
{
|
{
|
||||||
UEventsManager::createPipe(_dbReader, _odomThread, "CameraEvent");
|
UEventsManager::createPipe(_dbReader, _odomThread, "CameraEvent");
|
||||||
|
UEventsManager::createPipe(_dbReader, this, "CameraEvent");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3725,7 +3725,7 @@ Camera * PreferencesDialog::createCamera(bool useRawImages)
|
|||||||
else if(driver == kSrcStereoImages)
|
else if(driver == kSrcStereoImages)
|
||||||
{
|
{
|
||||||
camera = new CameraStereoImages(
|
camera = new CameraStereoImages(
|
||||||
_ui->lineEdit_cameraStereoImages_path_scans->text().append(QDir::separator()).toStdString(),
|
_ui->lineEdit_cameraStereoImages_path_scans->text().isEmpty()?"":_ui->lineEdit_cameraStereoImages_path_scans->text().append(QDir::separator()).toStdString(),
|
||||||
this->getStereoLaserLocalTransform(),
|
this->getStereoLaserLocalTransform(),
|
||||||
_ui->spinBox_cameraStereoImages_max_scan_pts->value(),
|
_ui->spinBox_cameraStereoImages_max_scan_pts->value(),
|
||||||
_ui->lineEdit_cameraStereoImages_path_left->text().append(QDir::separator()).toStdString(),
|
_ui->lineEdit_cameraStereoImages_path_left->text().append(QDir::separator()).toStdString(),
|
||||||
|
|||||||
Reference in New Issue
Block a user