mirror of
https://github.com/introlab/rtabmap.git
synced 2026-09-02 01:20:25 +08:00
Added close buttons to CameraViewer and OdometryViewer dialogs
This commit is contained in:
@@ -31,7 +31,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include "rtabmap/gui/RtabmapGuiExp.h" // DLL export/import defines
|
#include "rtabmap/gui/RtabmapGuiExp.h" // DLL export/import defines
|
||||||
|
|
||||||
#include <rtabmap/utilite/UEventsHandler.h>
|
#include <rtabmap/utilite/UEventsHandler.h>
|
||||||
#include <QWidget>
|
#include <QDialog>
|
||||||
#include <rtabmap/core/SensorData.h>
|
#include <rtabmap/core/SensorData.h>
|
||||||
|
|
||||||
namespace rtabmap {
|
namespace rtabmap {
|
||||||
@@ -39,7 +39,7 @@ namespace rtabmap {
|
|||||||
class ImageView;
|
class ImageView;
|
||||||
class CloudViewer;
|
class CloudViewer;
|
||||||
|
|
||||||
class RTABMAPGUI_EXP CameraViewer : public QWidget, public UEventsHandler
|
class RTABMAPGUI_EXP CameraViewer : public QDialog, public UEventsHandler
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
@@ -49,7 +49,7 @@ public:
|
|||||||
public slots:
|
public slots:
|
||||||
void showImage(const rtabmap::SensorData & data);
|
void showImage(const rtabmap::SensorData & data);
|
||||||
protected:
|
protected:
|
||||||
void handleEvent(UEvent * event);
|
virtual void handleEvent(UEvent * event);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ImageView* imageView_;
|
ImageView* imageView_;
|
||||||
|
|||||||
@@ -31,47 +31,50 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include "rtabmap/gui/RtabmapGuiExp.h" // DLL export/import defines
|
#include "rtabmap/gui/RtabmapGuiExp.h" // DLL export/import defines
|
||||||
|
|
||||||
#include "rtabmap/core/SensorData.h"
|
#include "rtabmap/core/SensorData.h"
|
||||||
#include "rtabmap/gui/CloudViewer.h"
|
#include "rtabmap/core/OdometryInfo.h"
|
||||||
|
#include <QDialog>
|
||||||
#include "rtabmap/utilite/UEventsHandler.h"
|
#include "rtabmap/utilite/UEventsHandler.h"
|
||||||
#include "rtabmap/utilite/UTimer.h"
|
|
||||||
#include "rtabmap/utilite/UMutex.h"
|
class QSpinBox;
|
||||||
|
class QDoubleSpinBox;
|
||||||
|
|
||||||
namespace rtabmap {
|
namespace rtabmap {
|
||||||
|
|
||||||
class RTABMAPGUI_EXP OdometryViewer : public CloudViewer, public UEventsHandler
|
class ImageView;
|
||||||
|
class CloudViewer;
|
||||||
|
|
||||||
|
class RTABMAPGUI_EXP OdometryViewer : public QDialog, public UEventsHandler
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
OdometryViewer(int maxClouds = 10, int decimation = 2, float voxelSize = 0.0f, int qualityWarningThr=0, QWidget * parent = 0);
|
OdometryViewer(int maxClouds = 10, int decimation = 2, float voxelSize = 0.0f, int qualityWarningThr=0, QWidget * parent = 0);
|
||||||
virtual ~OdometryViewer() {}
|
virtual ~OdometryViewer();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
virtual void clear();
|
virtual void clear();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void handleAction(QAction * a);
|
|
||||||
virtual void handleEvent(UEvent * event);
|
virtual void handleEvent(UEvent * event);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void processData();
|
void processData(const rtabmap::SensorData & data, const rtabmap::OdometryInfo & info);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
UMutex dataMutex_;
|
ImageView* imageView_;
|
||||||
std::list<rtabmap::SensorData> data_;
|
CloudViewer* cloudView_;
|
||||||
int dataQuality_;
|
bool processingData_;
|
||||||
|
bool odomImageShow_;
|
||||||
|
bool odomImageDepthShow_;
|
||||||
|
|
||||||
Transform lastOdomPose_;
|
Transform lastOdomPose_;
|
||||||
UTimer timer_;
|
|
||||||
int maxClouds_;
|
|
||||||
float voxelSize_;
|
|
||||||
int decimation_;
|
|
||||||
int qualityWarningThr_;
|
int qualityWarningThr_;
|
||||||
int id_;
|
int id_;
|
||||||
std::map<int, pcl::PointCloud<pcl::PointXYZRGB>::Ptr > clouds_;
|
|
||||||
QAction * _aSetVoxelSize;
|
QSpinBox * maxCloudsSpin_;
|
||||||
QAction * _aSetDecimation;
|
QDoubleSpinBox * voxelSpin_;
|
||||||
QAction * _aSetCloudHistorySize;
|
QSpinBox * decimationSpin_;
|
||||||
QAction * _aPause;
|
int validDecimationValue_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} /* namespace rtabmap */
|
} /* namespace rtabmap */
|
||||||
|
|||||||
@@ -57,8 +57,6 @@ class QDoubleSpinBox;
|
|||||||
|
|
||||||
namespace rtabmap {
|
namespace rtabmap {
|
||||||
|
|
||||||
class OdometryThread;
|
|
||||||
class CameraThread;
|
|
||||||
class Signature;
|
class Signature;
|
||||||
class LoopClosureViewer;
|
class LoopClosureViewer;
|
||||||
class CameraRGBD;
|
class CameraRGBD;
|
||||||
@@ -245,9 +243,7 @@ private slots:
|
|||||||
void updateBasicParameter();
|
void updateBasicParameter();
|
||||||
void openDatabaseViewer();
|
void openDatabaseViewer();
|
||||||
void showOpenNI2GroupBox(bool);
|
void showOpenNI2GroupBox(bool);
|
||||||
void cleanOdometryTest();
|
|
||||||
void testOdometry();
|
void testOdometry();
|
||||||
void cleanRGBDCameraTest();
|
|
||||||
void testRGBDCamera();
|
void testRGBDCamera();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@@ -299,10 +295,6 @@ private:
|
|||||||
|
|
||||||
QProgressDialog * _progressDialog;
|
QProgressDialog * _progressDialog;
|
||||||
|
|
||||||
//Odometry test
|
|
||||||
CameraThread * _cameraThread;
|
|
||||||
OdometryThread * _odomThread;
|
|
||||||
|
|
||||||
//calibration
|
//calibration
|
||||||
CalibrationDialog * _calibrationDialog;
|
CalibrationDialog * _calibrationDialog;
|
||||||
|
|
||||||
|
|||||||
@@ -34,12 +34,14 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include <rtabmap/gui/UCv2Qt.h>
|
#include <rtabmap/gui/UCv2Qt.h>
|
||||||
#include <QtCore/QMetaType>
|
#include <QtCore/QMetaType>
|
||||||
#include <QHBoxLayout>
|
#include <QHBoxLayout>
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
#include <QDialogButtonBox>
|
||||||
|
|
||||||
namespace rtabmap {
|
namespace rtabmap {
|
||||||
|
|
||||||
|
|
||||||
CameraViewer::CameraViewer(QWidget * parent) :
|
CameraViewer::CameraViewer(QWidget * parent) :
|
||||||
QWidget(parent),
|
QDialog(parent),
|
||||||
imageView_(new ImageView(this)),
|
imageView_(new ImageView(this)),
|
||||||
cloudView_(new CloudViewer(this)),
|
cloudView_(new CloudViewer(this)),
|
||||||
processingImages_(false)
|
processingImages_(false)
|
||||||
@@ -48,13 +50,22 @@ CameraViewer::CameraViewer(QWidget * parent) :
|
|||||||
|
|
||||||
imageView_->setImageDepthShown(true);
|
imageView_->setImageDepthShown(true);
|
||||||
imageView_->setMinimumSize(320, 240);
|
imageView_->setMinimumSize(320, 240);
|
||||||
QHBoxLayout * layout = new QHBoxLayout(this);
|
QHBoxLayout * layout = new QHBoxLayout();
|
||||||
layout->setMargin(0);
|
layout->setMargin(0);
|
||||||
layout->addWidget(imageView_);
|
layout->addWidget(imageView_,1);
|
||||||
layout->addWidget(cloudView_);
|
layout->addWidget(cloudView_,1);
|
||||||
layout->setStretch(0, 1);
|
|
||||||
layout->setStretch(1, 1);
|
QDialogButtonBox * buttonBox = new QDialogButtonBox(this);
|
||||||
this->setLayout(layout);
|
buttonBox->setStandardButtons(QDialogButtonBox::Close);
|
||||||
|
connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
|
||||||
|
|
||||||
|
QVBoxLayout * vlayout = new QVBoxLayout(this);
|
||||||
|
vlayout->setMargin(0);
|
||||||
|
vlayout->setSpacing(0);
|
||||||
|
vlayout->addLayout(layout, 1);
|
||||||
|
vlayout->addWidget(buttonBox);
|
||||||
|
|
||||||
|
this->setLayout(vlayout);
|
||||||
}
|
}
|
||||||
|
|
||||||
CameraViewer::~CameraViewer()
|
CameraViewer::~CameraViewer()
|
||||||
|
|||||||
@@ -31,200 +31,320 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include "rtabmap/core/OdometryEvent.h"
|
#include "rtabmap/core/OdometryEvent.h"
|
||||||
#include "rtabmap/utilite/ULogger.h"
|
#include "rtabmap/utilite/ULogger.h"
|
||||||
#include "rtabmap/utilite/UConversion.h"
|
#include "rtabmap/utilite/UConversion.h"
|
||||||
#include <pcl/common/transforms.h>
|
#include "rtabmap/gui/UCv2Qt.h"
|
||||||
#include <pcl/io/pcd_io.h>
|
|
||||||
#include <QInputDialog>
|
#include "rtabmap/gui/ImageView.h"
|
||||||
#include <QAction>
|
#include "rtabmap/gui/CloudViewer.h"
|
||||||
#include <QMenu>
|
|
||||||
#include <QtGui/QKeyEvent>
|
#include <QPushButton>
|
||||||
|
#include <QSpinBox>
|
||||||
|
#include <QDoubleSpinBox>
|
||||||
|
#include <QLabel>
|
||||||
|
#include <QHBoxLayout>
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
|
||||||
namespace rtabmap {
|
namespace rtabmap {
|
||||||
|
|
||||||
|
|
||||||
OdometryViewer::OdometryViewer(int maxClouds, int decimation, float voxelSize, int qualityWarningThr, QWidget * parent) :
|
OdometryViewer::OdometryViewer(int maxClouds, int decimation, float voxelSize, int qualityWarningThr, QWidget * parent) :
|
||||||
CloudViewer(parent),
|
QDialog(parent),
|
||||||
dataQuality_(-1),
|
imageView_(new ImageView(this)),
|
||||||
|
cloudView_(new CloudViewer(this)),
|
||||||
|
processingData_(false),
|
||||||
|
odomImageShow_(true),
|
||||||
|
odomImageDepthShow_(true),
|
||||||
lastOdomPose_(Transform::getIdentity()),
|
lastOdomPose_(Transform::getIdentity()),
|
||||||
maxClouds_(maxClouds),
|
|
||||||
voxelSize_(voxelSize),
|
|
||||||
decimation_(decimation),
|
|
||||||
qualityWarningThr_(qualityWarningThr),
|
qualityWarningThr_(qualityWarningThr),
|
||||||
id_(0),
|
id_(0),
|
||||||
_aSetVoxelSize(0),
|
validDecimationValue_(1)
|
||||||
_aSetDecimation(0),
|
|
||||||
_aSetCloudHistorySize(0),
|
|
||||||
_aPause(0)
|
|
||||||
{
|
{
|
||||||
|
|
||||||
//add actions to CloudViewer menu
|
qRegisterMetaType<rtabmap::SensorData>("rtabmap::SensorData");
|
||||||
_aSetVoxelSize = new QAction("Set voxel size...", this);
|
qRegisterMetaType<rtabmap::OdometryInfo>("rtabmap::OdometryInfo");
|
||||||
_aSetDecimation = new QAction("Set depth image decimation...", this);
|
|
||||||
_aSetCloudHistorySize = new QAction("Set cloud history size...", this);
|
imageView_->setImageDepthShown(true);
|
||||||
_aPause = new QAction("Pause", this);
|
imageView_->setMinimumSize(320, 240);
|
||||||
_aPause->setCheckable(true);
|
|
||||||
menu()->addAction(_aSetVoxelSize);
|
cloudView_->setCameraFree();
|
||||||
menu()->addAction(_aSetDecimation);
|
cloudView_->setGridShown(true);
|
||||||
menu()->addAction(_aSetCloudHistorySize);
|
|
||||||
menu()->addAction(_aPause);
|
QLabel * maxCloudsLabel = new QLabel("Max clouds", this);
|
||||||
|
QLabel * voxelLabel = new QLabel("Voxel", this);
|
||||||
|
QLabel * decimationLabel = new QLabel("Decimation", this);
|
||||||
|
maxCloudsSpin_ = new QSpinBox(this);
|
||||||
|
maxCloudsSpin_->setMinimum(0);
|
||||||
|
maxCloudsSpin_->setMaximum(100);
|
||||||
|
maxCloudsSpin_->setValue(maxClouds);
|
||||||
|
voxelSpin_ = new QDoubleSpinBox(this);
|
||||||
|
voxelSpin_->setMinimum(0);
|
||||||
|
voxelSpin_->setMaximum(1);
|
||||||
|
voxelSpin_->setDecimals(3);
|
||||||
|
voxelSpin_->setSingleStep(0.01);
|
||||||
|
voxelSpin_->setSuffix(" m");
|
||||||
|
voxelSpin_->setValue(voxelSize);
|
||||||
|
decimationSpin_ = new QSpinBox(this);
|
||||||
|
decimationSpin_->setMinimum(1);
|
||||||
|
decimationSpin_->setMaximum(16);
|
||||||
|
decimationSpin_->setValue(decimation);
|
||||||
|
QPushButton * clearButton = new QPushButton("clear", this);
|
||||||
|
QPushButton * closeButton = new QPushButton("close", this);
|
||||||
|
connect(clearButton, SIGNAL(clicked()), this, SLOT(clear()));
|
||||||
|
connect(closeButton, SIGNAL(clicked()), this, SLOT(reject()));
|
||||||
|
|
||||||
|
//layout
|
||||||
|
QHBoxLayout * layout = new QHBoxLayout();
|
||||||
|
layout->setMargin(0);
|
||||||
|
layout->setSpacing(0);
|
||||||
|
layout->addWidget(imageView_,1);
|
||||||
|
layout->addWidget(cloudView_,1);
|
||||||
|
|
||||||
|
QHBoxLayout * hlayout2 = new QHBoxLayout();
|
||||||
|
hlayout2->setMargin(0);
|
||||||
|
hlayout2->addWidget(maxCloudsLabel);
|
||||||
|
hlayout2->addWidget(maxCloudsSpin_);
|
||||||
|
hlayout2->addWidget(voxelLabel);
|
||||||
|
hlayout2->addWidget(voxelSpin_);
|
||||||
|
hlayout2->addWidget(decimationLabel);
|
||||||
|
hlayout2->addWidget(decimationSpin_);
|
||||||
|
hlayout2->addStretch(1);
|
||||||
|
hlayout2->addWidget(clearButton);
|
||||||
|
hlayout2->addWidget(closeButton);
|
||||||
|
|
||||||
|
QVBoxLayout * vlayout = new QVBoxLayout(this);
|
||||||
|
vlayout->setMargin(0);
|
||||||
|
vlayout->setSpacing(0);
|
||||||
|
vlayout->addLayout(layout, 1);
|
||||||
|
vlayout->addLayout(hlayout2);
|
||||||
|
|
||||||
|
this->setLayout(vlayout);
|
||||||
|
}
|
||||||
|
|
||||||
|
OdometryViewer::~OdometryViewer()
|
||||||
|
{
|
||||||
|
this->unregisterFromEventsManager();
|
||||||
|
this->clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void OdometryViewer::clear()
|
void OdometryViewer::clear()
|
||||||
{
|
{
|
||||||
dataMutex_.lock();
|
cloudView_->clear();
|
||||||
data_.clear();
|
|
||||||
dataMutex_.unlock();
|
|
||||||
clouds_.clear();
|
|
||||||
CloudViewer::clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void OdometryViewer::processData()
|
void OdometryViewer::processData(const rtabmap::SensorData & data, const rtabmap::OdometryInfo & info)
|
||||||
{
|
{
|
||||||
rtabmap::SensorData data;
|
processingData_ = true;
|
||||||
int quality = -1;
|
int quality = info.inliers;
|
||||||
dataMutex_.lock();
|
|
||||||
if(data_.size())
|
|
||||||
{
|
|
||||||
data = data_.back();
|
|
||||||
data_.clear();
|
|
||||||
quality = dataQuality_;
|
|
||||||
dataQuality_ = -1;
|
|
||||||
}
|
|
||||||
dataMutex_.unlock();
|
|
||||||
|
|
||||||
if(!data.image().empty() && !data.depth().empty() && data.fx()>0.0f && data.fy()>0.0f && this->isVisible())
|
bool lost = false;
|
||||||
|
bool lostStateChanged = false;
|
||||||
|
|
||||||
|
if(data.pose().isNull())
|
||||||
|
{
|
||||||
|
UDEBUG("odom lost"); // use last pose
|
||||||
|
lostStateChanged = imageView_->getBackgroundColor() != Qt::darkRed;
|
||||||
|
imageView_->setBackgroundColor(Qt::darkRed);
|
||||||
|
cloudView_->setBackgroundColor(Qt::darkRed);
|
||||||
|
|
||||||
|
lost = true;
|
||||||
|
}
|
||||||
|
else if(info.inliers>0 &&
|
||||||
|
qualityWarningThr_ &&
|
||||||
|
info.inliers < qualityWarningThr_)
|
||||||
|
{
|
||||||
|
UDEBUG("odom warn, quality(inliers)=%d thr=%d", info.inliers, qualityWarningThr_);
|
||||||
|
lostStateChanged = imageView_->getBackgroundColor() == Qt::darkRed;
|
||||||
|
imageView_->setBackgroundColor(Qt::darkYellow);
|
||||||
|
cloudView_->setBackgroundColor(Qt::darkYellow);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UDEBUG("odom ok");
|
||||||
|
lostStateChanged = imageView_->getBackgroundColor() == Qt::darkRed;
|
||||||
|
imageView_->setBackgroundColor(cloudView_->getDefaultBackgroundColor());
|
||||||
|
cloudView_->setBackgroundColor(Qt::black);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if(!data.image().empty() && !data.depthOrRightImage().empty() && data.fx()>0.0f && data.fyOrBaseline()>0.0f)
|
||||||
{
|
{
|
||||||
UDEBUG("New pose = %s, quality=%d", data.pose().prettyPrint().c_str(), quality);
|
UDEBUG("New pose = %s, quality=%d", data.pose().prettyPrint().c_str(), quality);
|
||||||
|
|
||||||
|
if(data.image().cols % decimationSpin_->value() == 0 &&
|
||||||
|
data.image().rows % decimationSpin_->value() == 0)
|
||||||
|
{
|
||||||
|
validDecimationValue_ = decimationSpin_->value();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UWARN("Decimation (%d) must be a denominator of the width and height of "
|
||||||
|
"the image (%d/%d). Using last valid decimation value (%d).",
|
||||||
|
decimationSpin_->value(),
|
||||||
|
data.image().cols,
|
||||||
|
data.image().rows,
|
||||||
|
validDecimationValue_);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// visualization: buffering the clouds
|
// visualization: buffering the clouds
|
||||||
// Create the new cloud
|
// Create the new cloud
|
||||||
pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud;
|
pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud;
|
||||||
if(data.depth().type() == CV_8UC1)
|
if(!data.depth().empty())
|
||||||
{
|
|
||||||
cloud = util3d::cloudFromStereoImages(
|
|
||||||
data.image(),
|
|
||||||
data.depth(),
|
|
||||||
data.cx(), data.cy(),
|
|
||||||
data.fx(), data.fy(),
|
|
||||||
decimation_);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
cloud = util3d::cloudFromDepthRGB(
|
cloud = util3d::cloudFromDepthRGB(
|
||||||
data.image(),
|
data.image(),
|
||||||
data.depth(),
|
data.depth(),
|
||||||
data.cx(), data.cy(),
|
data.cx(), data.cy(),
|
||||||
data.fx(), data.fy(),
|
data.fx(), data.fy(),
|
||||||
decimation_);
|
validDecimationValue_);
|
||||||
}
|
}
|
||||||
|
else if(!data.rightImage().empty())
|
||||||
if(voxelSize_ > 0.0f)
|
|
||||||
{
|
{
|
||||||
cloud = util3d::voxelize<pcl::PointXYZRGB>(cloud, voxelSize_);
|
cloud = util3d::cloudFromStereoImages(
|
||||||
|
data.image(),
|
||||||
|
data.rightImage(),
|
||||||
|
data.cx(), data.cy(),
|
||||||
|
data.fx(), data.baseline(),
|
||||||
|
validDecimationValue_);
|
||||||
}
|
}
|
||||||
|
|
||||||
cloud = util3d::transformPointCloud<pcl::PointXYZRGB>(cloud, data.localTransform());
|
if(voxelSpin_->value() > 0.0f && cloud->size())
|
||||||
|
{
|
||||||
|
cloud = util3d::voxelize<pcl::PointXYZRGB>(cloud, voxelSpin_->value());
|
||||||
|
}
|
||||||
|
|
||||||
|
if(cloud->size())
|
||||||
|
{
|
||||||
|
cloud = util3d::transformPointCloud<pcl::PointXYZRGB>(cloud, data.localTransform());
|
||||||
|
}
|
||||||
|
|
||||||
if(!data.pose().isNull())
|
if(!data.pose().isNull())
|
||||||
{
|
{
|
||||||
lastOdomPose_ = data.pose();
|
lastOdomPose_ = data.pose();
|
||||||
if(this->getAddedClouds().contains("cloudtmp"))
|
if(cloudView_->getAddedClouds().contains("cloudtmp"))
|
||||||
{
|
{
|
||||||
this->removeCloud("cloudtmp");
|
cloudView_->removeCloud("cloudtmp");
|
||||||
}
|
}
|
||||||
|
|
||||||
data.id()?id_=data.id():++id_;
|
data.id()?id_=data.id():++id_;
|
||||||
|
|
||||||
clouds_.insert(std::make_pair(id_, cloud));
|
while(maxCloudsSpin_->value()>0 && (int)cloudView_->getAddedClouds().size() > maxCloudsSpin_->value())
|
||||||
|
|
||||||
while(maxClouds_>0 && (int)clouds_.size() > maxClouds_)
|
|
||||||
{
|
{
|
||||||
this->removeCloud(uFormat("cloud%d", clouds_.begin()->first));
|
cloudView_->removeCloud(cloudView_->getAddedClouds().begin().key());
|
||||||
clouds_.erase(clouds_.begin());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(clouds_.size())
|
cloudView_->addOrUpdateCloud(uFormat("cloud%d", id_), cloud, data.pose());
|
||||||
{
|
|
||||||
this->addCloud(uFormat("cloud%d", clouds_.rbegin()->first), clouds_.rbegin()->second, data.pose());
|
|
||||||
}
|
|
||||||
|
|
||||||
this->updateCameraTargetPosition(data.pose());
|
cloudView_->updateCameraTargetPosition(data.pose());
|
||||||
|
|
||||||
if(qualityWarningThr_ && quality>=0 && quality < qualityWarningThr_)
|
|
||||||
{
|
|
||||||
this->setBackgroundColor(Qt::darkYellow);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
this->setBackgroundColor(this->getDefaultBackgroundColor());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
this->addOrUpdateCloud("cloudtmp", cloud, lastOdomPose_);
|
cloudView_->addOrUpdateCloud("cloudtmp", cloud, lastOdomPose_);
|
||||||
this->setBackgroundColor(Qt::darkRed);
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!data.image().empty())
|
||||||
|
{
|
||||||
|
if(info.type == 0)
|
||||||
|
{
|
||||||
|
imageView_->setFeatures(info.words, Qt::yellow);
|
||||||
|
}
|
||||||
|
else if(info.type == 1)
|
||||||
|
{
|
||||||
|
imageView_->setFeatures(info.refCorners, Qt::red);
|
||||||
}
|
}
|
||||||
|
|
||||||
this->update();
|
imageView_->clearLines();
|
||||||
|
if(lost)
|
||||||
|
{
|
||||||
|
if(lostStateChanged)
|
||||||
|
{
|
||||||
|
// save state
|
||||||
|
odomImageShow_ = imageView_->isImageShown();
|
||||||
|
odomImageDepthShow_ = imageView_->isImageDepthShown();
|
||||||
|
}
|
||||||
|
imageView_->setImageDepth(uCvMat2QImage(data.image()));
|
||||||
|
imageView_->setImageShown(true);
|
||||||
|
imageView_->setImageDepthShown(true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(lostStateChanged)
|
||||||
|
{
|
||||||
|
// restore state
|
||||||
|
imageView_->setImageShown(odomImageShow_);
|
||||||
|
imageView_->setImageDepthShown(odomImageDepthShow_);
|
||||||
|
}
|
||||||
|
|
||||||
|
imageView_->setImage(uCvMat2QImage(data.image()));
|
||||||
|
if(imageView_->isImageDepthShown())
|
||||||
|
{
|
||||||
|
imageView_->setImageDepth(uCvMat2QImage(data.depthOrRightImage()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(info.type == 0)
|
||||||
|
{
|
||||||
|
if(imageView_->isFeaturesShown())
|
||||||
|
{
|
||||||
|
for(unsigned int i=0; i<info.wordMatches.size(); ++i)
|
||||||
|
{
|
||||||
|
imageView_->setFeatureColor(info.wordMatches[i], Qt::red); // outliers
|
||||||
|
}
|
||||||
|
for(unsigned int i=0; i<info.wordInliers.size(); ++i)
|
||||||
|
{
|
||||||
|
imageView_->setFeatureColor(info.wordInliers[i], Qt::green); // inliers
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(info.type == 1)
|
||||||
|
{
|
||||||
|
if(imageView_->isFeaturesShown() || imageView_->isLinesShown())
|
||||||
|
{
|
||||||
|
//draw lines
|
||||||
|
UASSERT(info.refCorners.size() == info.newCorners.size());
|
||||||
|
for(unsigned int i=0; i<info.cornerInliers.size(); ++i)
|
||||||
|
{
|
||||||
|
if(imageView_->isFeaturesShown())
|
||||||
|
{
|
||||||
|
imageView_->setFeatureColor(info.cornerInliers[i], Qt::green); // inliers
|
||||||
|
}
|
||||||
|
if(imageView_->isLinesShown())
|
||||||
|
{
|
||||||
|
imageView_->addLine(
|
||||||
|
info.refCorners[info.cornerInliers[i]].pt.x,
|
||||||
|
info.refCorners[info.cornerInliers[i]].pt.y,
|
||||||
|
info.newCorners[info.cornerInliers[i]].pt.x,
|
||||||
|
info.newCorners[info.cornerInliers[i]].pt.y,
|
||||||
|
Qt::blue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
imageView_->update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
if(!data.image().empty())
|
||||||
|
{
|
||||||
|
imageView_->setSceneRect(QRectF(0,0,(float)data.image().cols, (float)data.image().rows));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cloudView_->update();
|
||||||
|
processingData_ = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OdometryViewer::handleEvent(UEvent * event)
|
void OdometryViewer::handleEvent(UEvent * event)
|
||||||
{
|
{
|
||||||
if(!_aPause->isChecked())
|
if(!processingData_ && this->isVisible())
|
||||||
{
|
{
|
||||||
if(event->getClassName().compare("OdometryEvent") == 0)
|
if(event->getClassName().compare("OdometryEvent") == 0)
|
||||||
{
|
{
|
||||||
rtabmap::OdometryEvent * odomEvent = (rtabmap::OdometryEvent*)event;
|
rtabmap::OdometryEvent * odomEvent = (rtabmap::OdometryEvent*)event;
|
||||||
|
if(odomEvent->data().isValid())
|
||||||
bool empty = false;
|
|
||||||
dataMutex_.lock();
|
|
||||||
if(data_.empty())
|
|
||||||
{
|
{
|
||||||
data_.push_back(odomEvent->data());
|
processingData_ = true;
|
||||||
empty= true;
|
QMetaObject::invokeMethod(this, "processData",
|
||||||
|
Q_ARG(rtabmap::SensorData, odomEvent->data()),
|
||||||
|
Q_ARG(rtabmap::OdometryInfo, odomEvent->info()));
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
data_.back() = odomEvent->data();
|
|
||||||
}
|
|
||||||
dataQuality_ = odomEvent->info().inliers;
|
|
||||||
dataMutex_.unlock();
|
|
||||||
if(empty)
|
|
||||||
{
|
|
||||||
QMetaObject::invokeMethod(this, "processData");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void OdometryViewer::handleAction(QAction * a)
|
|
||||||
{
|
|
||||||
CloudViewer::handleAction(a);
|
|
||||||
if(a == _aSetVoxelSize)
|
|
||||||
{
|
|
||||||
bool ok;
|
|
||||||
double value = QInputDialog::getDouble(this, tr("Set voxel size"), tr("Size (0=disabled)"), voxelSize_, 0.0, 0.1, 2, &ok);
|
|
||||||
if(ok)
|
|
||||||
{
|
|
||||||
voxelSize_ = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(a == _aSetCloudHistorySize)
|
|
||||||
{
|
|
||||||
bool ok;
|
|
||||||
int value = QInputDialog::getInt(this, tr("Set cloud history size"), tr("Size (0=infinite)"), maxClouds_, 0, 100, 1, &ok);
|
|
||||||
if(ok)
|
|
||||||
{
|
|
||||||
maxClouds_ = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(a == _aSetDecimation)
|
|
||||||
{
|
|
||||||
bool ok;
|
|
||||||
int value = QInputDialog::getInt(this, tr("Set depth image decimation"), tr("Decimation"), decimation_, 1, 8, 1, &ok);
|
|
||||||
if(ok)
|
|
||||||
{
|
|
||||||
decimation_ = value;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -81,11 +81,10 @@ PreferencesDialog::PreferencesDialog(QWidget * parent) :
|
|||||||
_ui(0),
|
_ui(0),
|
||||||
_indexModel(0),
|
_indexModel(0),
|
||||||
_initialized(false),
|
_initialized(false),
|
||||||
_cameraThread(0),
|
|
||||||
_odomThread(0),
|
|
||||||
_calibrationDialog(new CalibrationDialog(false, ".", this))
|
_calibrationDialog(new CalibrationDialog(false, ".", this))
|
||||||
{
|
{
|
||||||
ULOGGER_DEBUG("");
|
ULOGGER_DEBUG("");
|
||||||
|
_calibrationDialog->setWindowFlags(Qt::Window);
|
||||||
|
|
||||||
_ui = new Ui_preferencesDialog();
|
_ui = new Ui_preferencesDialog();
|
||||||
_ui->setupUi(this);
|
_ui->setupUi(this);
|
||||||
@@ -3254,25 +3253,18 @@ void PreferencesDialog::testOdometry()
|
|||||||
|
|
||||||
void PreferencesDialog::testOdometry(int type)
|
void PreferencesDialog::testOdometry(int type)
|
||||||
{
|
{
|
||||||
if(_cameraThread)
|
|
||||||
{
|
|
||||||
QMessageBox::warning(this,
|
|
||||||
tr("RTAB-Map"),
|
|
||||||
tr("A camera is already running!"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
UASSERT(_odomThread == 0 && _cameraThread == 0);
|
|
||||||
|
|
||||||
CameraRGBD * camera = this->createCameraRGBD();
|
CameraRGBD * camera = this->createCameraRGBD();
|
||||||
|
|
||||||
if(!camera->init(this->getCameraInfoDir().toStdString()))
|
if(camera == 0 || !camera->init(this->getCameraInfoDir().toStdString()))
|
||||||
{
|
{
|
||||||
QMessageBox::warning(this,
|
QMessageBox::warning(this,
|
||||||
tr("RTAB-Map"),
|
tr("RTAB-Map"),
|
||||||
tr("RGBD camera initialization failed!"));
|
tr("RGBD camera initialization failed!"));
|
||||||
delete camera;
|
if(camera)
|
||||||
camera = 0;
|
{
|
||||||
|
delete camera;
|
||||||
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
else if(dynamic_cast<CameraOpenNI2*>(camera) != 0)
|
else if(dynamic_cast<CameraOpenNI2*>(camera) != 0)
|
||||||
{
|
{
|
||||||
@@ -3287,110 +3279,56 @@ void PreferencesDialog::testOdometry(int type)
|
|||||||
}
|
}
|
||||||
camera->setMirroringEnabled(isSourceMirroring());
|
camera->setMirroringEnabled(isSourceMirroring());
|
||||||
|
|
||||||
|
ParametersMap parameters = this->getAllParameters();
|
||||||
if(camera)
|
Odometry * odometry;
|
||||||
|
if(this->getOdomStrategy() == 1)
|
||||||
{
|
{
|
||||||
ParametersMap parameters = this->getAllParameters();
|
odometry = new OdometryOpticalFlow(parameters);
|
||||||
Odometry * odometry;
|
|
||||||
if(this->getOdomStrategy() == 1)
|
|
||||||
{
|
|
||||||
odometry = new OdometryOpticalFlow(parameters);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
odometry = new OdometryBOW(parameters);
|
|
||||||
}
|
|
||||||
|
|
||||||
_odomThread = new OdometryThread(odometry); // take ownership of odometry
|
|
||||||
|
|
||||||
QDialog * window = new QDialog(this);
|
|
||||||
window->setWindowModality(Qt::WindowModal);
|
|
||||||
window->setWindowTitle(tr("Odometry viewer"));
|
|
||||||
window->setMinimumWidth(800);
|
|
||||||
window->setMinimumHeight(600);
|
|
||||||
connect( window, SIGNAL(finished(int)), this, SLOT(cleanOdometryTest()) );
|
|
||||||
|
|
||||||
OdometryViewer * odomViewer = new OdometryViewer(10,
|
|
||||||
_ui->spinBox_decimation_odom->value(),
|
|
||||||
_ui->doubleSpinBox_voxelSize_odom->value(),
|
|
||||||
this->getOdomQualityWarnThr(),
|
|
||||||
window);
|
|
||||||
connect( window, SIGNAL(finished(int)), odomViewer, SLOT(clear()) );
|
|
||||||
|
|
||||||
odomViewer->setCameraFree();
|
|
||||||
odomViewer->setGridShown(true);
|
|
||||||
|
|
||||||
QVBoxLayout *layout = new QVBoxLayout();
|
|
||||||
layout->addWidget(odomViewer);
|
|
||||||
window->setLayout(layout);
|
|
||||||
|
|
||||||
UEventsManager::addHandler(_odomThread);
|
|
||||||
UEventsManager::addHandler(odomViewer);
|
|
||||||
|
|
||||||
_cameraThread = new CameraThread(camera);
|
|
||||||
UEventsManager::createPipe(_cameraThread, _odomThread, "CameraEvent");
|
|
||||||
UEventsManager::createPipe(_odomThread, odomViewer, "OdometryEvent");
|
|
||||||
|
|
||||||
window->showNormal();
|
|
||||||
|
|
||||||
_ui->pushButton_testOdometry->setEnabled(false);
|
|
||||||
|
|
||||||
QApplication::processEvents();
|
|
||||||
uSleep(500);
|
|
||||||
QApplication::processEvents();
|
|
||||||
|
|
||||||
_odomThread->start();
|
|
||||||
_cameraThread->start();
|
|
||||||
}
|
}
|
||||||
}
|
else
|
||||||
|
|
||||||
void PreferencesDialog::cleanOdometryTest()
|
|
||||||
{
|
|
||||||
UDEBUG("");
|
|
||||||
if(_cameraThread)
|
|
||||||
{
|
{
|
||||||
_cameraThread->join(true);
|
odometry = new OdometryBOW(parameters);
|
||||||
delete _cameraThread;
|
|
||||||
_cameraThread = 0;
|
|
||||||
}
|
}
|
||||||
if(_odomThread)
|
|
||||||
{
|
|
||||||
_odomThread->join(true);
|
|
||||||
delete _odomThread;
|
|
||||||
_odomThread = 0;
|
|
||||||
}
|
|
||||||
_ui->pushButton_testOdometry->setEnabled(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PreferencesDialog::cleanRGBDCameraTest()
|
OdometryThread odomThread(odometry); // take ownership of odometry
|
||||||
{
|
odomThread.registerToEventsManager();
|
||||||
UDEBUG("");
|
|
||||||
if(_cameraThread)
|
OdometryViewer * odomViewer = new OdometryViewer(10,
|
||||||
{
|
_ui->spinBox_decimation_odom->value(),
|
||||||
_cameraThread->join(true);
|
_ui->doubleSpinBox_voxelSize_odom->value(),
|
||||||
delete _cameraThread;
|
this->getOdomQualityWarnThr(),
|
||||||
_cameraThread = 0;
|
this);
|
||||||
}
|
odomViewer->setWindowTitle(tr("Odometry viewer"));
|
||||||
_ui->pushButton_test_rgbd_camera->setEnabled(true);
|
odomViewer->resize(1280, 480+QPushButton().minimumHeight());
|
||||||
|
odomViewer->registerToEventsManager();
|
||||||
|
|
||||||
|
CameraThread cameraThread(camera); // take ownership of camera
|
||||||
|
UEventsManager::createPipe(&cameraThread, &odomThread, "CameraEvent");
|
||||||
|
UEventsManager::createPipe(&odomThread, odomViewer, "OdometryEvent");
|
||||||
|
|
||||||
|
odomThread.start();
|
||||||
|
cameraThread.start();
|
||||||
|
|
||||||
|
odomViewer->exec();
|
||||||
|
delete odomViewer;
|
||||||
|
|
||||||
|
cameraThread.join(true);
|
||||||
|
odomThread.join(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PreferencesDialog::testRGBDCamera()
|
void PreferencesDialog::testRGBDCamera()
|
||||||
{
|
{
|
||||||
if(_cameraThread)
|
|
||||||
{
|
|
||||||
QMessageBox::warning(this,
|
|
||||||
tr("RTAB-Map"),
|
|
||||||
tr("A camera is already running!"));
|
|
||||||
}
|
|
||||||
|
|
||||||
CameraRGBD * camera = this->createCameraRGBD();
|
CameraRGBD * camera = this->createCameraRGBD();
|
||||||
if(!camera->init(this->getCameraInfoDir().toStdString()))
|
if(camera == 0 || !camera->init(this->getCameraInfoDir().toStdString()))
|
||||||
{
|
{
|
||||||
QMessageBox::warning(this,
|
QMessageBox::warning(this,
|
||||||
tr("RTAB-Map"),
|
tr("RTAB-Map"),
|
||||||
tr("RGBD camera initialization failed!"));
|
tr("RGBD camera initialization failed!"));
|
||||||
delete camera;
|
if(camera)
|
||||||
camera = 0;
|
{
|
||||||
|
delete camera;
|
||||||
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
else if(dynamic_cast<CameraOpenNI2*>(camera) != 0)
|
else if(dynamic_cast<CameraOpenNI2*>(camera) != 0)
|
||||||
{
|
{
|
||||||
@@ -3405,41 +3343,34 @@ void PreferencesDialog::testRGBDCamera()
|
|||||||
}
|
}
|
||||||
camera->setMirroringEnabled(isSourceMirroring());
|
camera->setMirroringEnabled(isSourceMirroring());
|
||||||
|
|
||||||
|
// Create DataRecorder without init it, just to show images...
|
||||||
|
CameraViewer * window = new CameraViewer(this);
|
||||||
|
window->setWindowTitle(tr("RGBD camera viewer"));
|
||||||
|
window->resize(1280, 480+QPushButton().minimumHeight());
|
||||||
|
window->registerToEventsManager();
|
||||||
|
|
||||||
if(camera)
|
CameraThread cameraThread(camera);
|
||||||
{
|
UEventsManager::createPipe(&cameraThread, window, "CameraEvent");
|
||||||
_ui->pushButton_test_rgbd_camera->setEnabled(false);
|
|
||||||
|
|
||||||
// Create DataRecorder without init it, just to show images...
|
cameraThread.start();
|
||||||
CameraViewer * window = new CameraViewer(this);
|
window->exec();
|
||||||
window->setWindowModality(Qt::WindowModal);
|
delete window;
|
||||||
window->setAttribute(Qt::WA_DeleteOnClose);
|
cameraThread.join(true);
|
||||||
window->setWindowFlags(Qt::Dialog);
|
|
||||||
window->setWindowTitle(tr("RGBD camera viewer"));
|
|
||||||
window->setMinimumWidth(1280);
|
|
||||||
window->setMinimumHeight(480);
|
|
||||||
connect( window, SIGNAL(destroyed(QObject*)), this, SLOT(cleanRGBDCameraTest()) );
|
|
||||||
window->registerToEventsManager();
|
|
||||||
|
|
||||||
_cameraThread = new CameraThread(camera);
|
|
||||||
UEventsManager::createPipe(_cameraThread, window, "CameraEvent");
|
|
||||||
|
|
||||||
window->showNormal();
|
|
||||||
|
|
||||||
_cameraThread->start();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PreferencesDialog::calibrate()
|
void PreferencesDialog::calibrate()
|
||||||
{
|
{
|
||||||
CameraRGBD * camera = this->createCameraRGBD();
|
CameraRGBD * camera = this->createCameraRGBD();
|
||||||
if(!camera->init("")) // don't set calibration folder to use raw images
|
if(camera == 0 || !camera->init("")) // don't set calibration folder to use raw images
|
||||||
{
|
{
|
||||||
QMessageBox::warning(this,
|
QMessageBox::warning(this,
|
||||||
tr("RTAB-Map"),
|
tr("RTAB-Map"),
|
||||||
tr("RGBD camera initialization failed!"));
|
tr("RGBD camera initialization failed!"));
|
||||||
delete camera;
|
if(camera)
|
||||||
camera = 0;
|
{
|
||||||
|
delete camera;
|
||||||
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
else if(dynamic_cast<CameraOpenNI2*>(camera) != 0)
|
else if(dynamic_cast<CameraOpenNI2*>(camera) != 0)
|
||||||
{
|
{
|
||||||
@@ -3455,34 +3386,31 @@ void PreferencesDialog::calibrate()
|
|||||||
camera->setMirroringEnabled(isSourceMirroring());
|
camera->setMirroringEnabled(isSourceMirroring());
|
||||||
|
|
||||||
|
|
||||||
if(camera)
|
if(!this->getCameraInfoDir().isEmpty())
|
||||||
{
|
{
|
||||||
if(!this->getCameraInfoDir().isEmpty())
|
QDir dir(this->getCameraInfoDir());
|
||||||
|
if (!dir.exists())
|
||||||
{
|
{
|
||||||
QDir dir(this->getCameraInfoDir());
|
UINFO("Creating camera_info directory: \"%s\"", this->getCameraInfoDir().toStdString().c_str());
|
||||||
if (!dir.exists())
|
if(!dir.mkpath(this->getCameraInfoDir()))
|
||||||
{
|
{
|
||||||
UINFO("Creating camera_info directory: \"%s\"", this->getCameraInfoDir().toStdString().c_str());
|
UWARN("Could create camera_info directory: \"%s\"", this->getCameraInfoDir().toStdString().c_str());
|
||||||
if(!dir.mkpath(this->getCameraInfoDir()))
|
|
||||||
{
|
|
||||||
UWARN("Could create camera_info directory: \"%s\"", this->getCameraInfoDir().toStdString().c_str());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_calibrationDialog->setStereoMode(dynamic_cast<CameraStereoDC1394*>(camera)!=0);
|
|
||||||
_calibrationDialog->setSavingDirectory(this->getCameraInfoDir());
|
|
||||||
_calibrationDialog->registerToEventsManager();
|
|
||||||
|
|
||||||
CameraThread cameraThread(camera);
|
|
||||||
UEventsManager::createPipe(&cameraThread, _calibrationDialog, "CameraEvent");
|
|
||||||
|
|
||||||
cameraThread.start();
|
|
||||||
|
|
||||||
_calibrationDialog->exec();
|
|
||||||
_calibrationDialog->unregisterFromEventsManager();
|
|
||||||
|
|
||||||
cameraThread.join(true);
|
|
||||||
}
|
}
|
||||||
|
_calibrationDialog->setStereoMode(dynamic_cast<CameraStereoDC1394*>(camera)!=0);
|
||||||
|
_calibrationDialog->setSavingDirectory(this->getCameraInfoDir());
|
||||||
|
_calibrationDialog->registerToEventsManager();
|
||||||
|
|
||||||
|
CameraThread cameraThread(camera);
|
||||||
|
UEventsManager::createPipe(&cameraThread, _calibrationDialog, "CameraEvent");
|
||||||
|
|
||||||
|
cameraThread.start();
|
||||||
|
|
||||||
|
_calibrationDialog->exec();
|
||||||
|
_calibrationDialog->unregisterFromEventsManager();
|
||||||
|
|
||||||
|
cameraThread.join(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>486</width>
|
<width>486</width>
|
||||||
<height>369</height>
|
<height>425</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
|
|||||||
@@ -59,6 +59,10 @@ int main(int argc, char * argv[])
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if(strcmp(argv[argc-1], "--help") == 0)
|
||||||
|
{
|
||||||
|
showUsage();
|
||||||
|
}
|
||||||
driver = atoi(argv[argc-1]);
|
driver = atoi(argv[argc-1]);
|
||||||
if(driver < 0 || driver > 6)
|
if(driver < 0 || driver > 6)
|
||||||
{
|
{
|
||||||
@@ -134,7 +138,7 @@ int main(int argc, char * argv[])
|
|||||||
|
|
||||||
if(!camera->init())
|
if(!camera->init())
|
||||||
{
|
{
|
||||||
printf("Camera init failed!\n");
|
printf("Camera init failed! Please select another driver (see \"--help\").\n");
|
||||||
delete camera;
|
delete camera;
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,14 +16,8 @@ SET(LIBRARIES
|
|||||||
${QT_LIBRARIES}
|
${QT_LIBRARIES}
|
||||||
)
|
)
|
||||||
|
|
||||||
IF("${RTABMAP_QT_VERSION}" STREQUAL "4")
|
|
||||||
QT4_WRAP_CPP(moc_srcs OdomInfoWidget.h)
|
|
||||||
ELSE()
|
|
||||||
QT5_WRAP_CPP(moc_srcs OdomInfoWidget.h)
|
|
||||||
ENDIF()
|
|
||||||
|
|
||||||
SET(SRC_FILES
|
SET(SRC_FILES
|
||||||
main.cpp OdomInfoWidget.cpp ${moc_srcs}
|
main.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
add_definitions(${PCL_DEFINITIONS})
|
add_definitions(${PCL_DEFINITIONS})
|
||||||
|
|||||||
@@ -1,208 +0,0 @@
|
|||||||
/*
|
|
||||||
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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "OdomInfoWidget.h"
|
|
||||||
|
|
||||||
#include <rtabmap/utilite/ULogger.h>
|
|
||||||
#include <rtabmap/core/OdometryEvent.h>
|
|
||||||
#include <rtabmap/core/util3d.h>
|
|
||||||
#include <rtabmap/gui/ImageView.h>
|
|
||||||
#include <rtabmap/gui/UCv2Qt.h>
|
|
||||||
#include <QtCore/QMetaType>
|
|
||||||
#include <QtGui/QCloseEvent>
|
|
||||||
#include <QLabel>
|
|
||||||
#include <QVBoxLayout>
|
|
||||||
|
|
||||||
OdomInfoWidget::OdomInfoWidget(QWidget * parent) :
|
|
||||||
QWidget(parent),
|
|
||||||
imageView_(new rtabmap::ImageView(this)),
|
|
||||||
label_(new QLabel(this)),
|
|
||||||
processingOdomInfo_(false),
|
|
||||||
receivingRate_(0),
|
|
||||||
lastTime_(0),
|
|
||||||
odomImageShow_(true),
|
|
||||||
odomImageDepthShow_(false)
|
|
||||||
{
|
|
||||||
qRegisterMetaType<rtabmap::SensorData>("rtabmap::SensorData");
|
|
||||||
qRegisterMetaType<rtabmap::OdometryInfo>("rtabmap::OdometryInfo");
|
|
||||||
|
|
||||||
imageView_->setMinimumSize(320, 240);
|
|
||||||
QVBoxLayout * layout = new QVBoxLayout(this);
|
|
||||||
layout->setMargin(0);
|
|
||||||
layout->addWidget(imageView_);
|
|
||||||
layout->addWidget(label_);
|
|
||||||
layout->setStretch(0,1);
|
|
||||||
this->setLayout(layout);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
OdomInfoWidget::~OdomInfoWidget()
|
|
||||||
{
|
|
||||||
this->unregisterFromEventsManager();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void OdomInfoWidget::processOdomInfo(const rtabmap::SensorData & data, const rtabmap::OdometryInfo & info)
|
|
||||||
{
|
|
||||||
processingOdomInfo_ = true;
|
|
||||||
|
|
||||||
const rtabmap::Transform & pose = data.pose();
|
|
||||||
bool lost = false;
|
|
||||||
bool lostStateChanged = false;
|
|
||||||
|
|
||||||
if(pose.isNull())
|
|
||||||
{
|
|
||||||
// lost
|
|
||||||
lostStateChanged = imageView_->getBackgroundColor() != Qt::darkRed;
|
|
||||||
imageView_->setBackgroundColor(Qt::darkRed);
|
|
||||||
lost = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// ok
|
|
||||||
lostStateChanged = imageView_->getBackgroundColor() == Qt::darkRed;
|
|
||||||
imageView_->setBackgroundColor(Qt::black);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!data.image().empty())
|
|
||||||
{
|
|
||||||
if(imageView_->isFeaturesShown())
|
|
||||||
{
|
|
||||||
if(info.type == 0)
|
|
||||||
{
|
|
||||||
imageView_->setFeatures(info.words, Qt::yellow);
|
|
||||||
}
|
|
||||||
else if(info.type == 1)
|
|
||||||
{
|
|
||||||
imageView_->setFeatures(info.refCorners, Qt::red);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
imageView_->clearLines();
|
|
||||||
if(lost)
|
|
||||||
{
|
|
||||||
if(lostStateChanged)
|
|
||||||
{
|
|
||||||
// save state
|
|
||||||
odomImageShow_ = imageView_->isImageShown();
|
|
||||||
odomImageDepthShow_ = imageView_->isImageDepthShown();
|
|
||||||
}
|
|
||||||
imageView_->setImageDepth(uCvMat2QImage(data.image()));
|
|
||||||
imageView_->setImageShown(true);
|
|
||||||
imageView_->setImageDepthShown(true);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if(lostStateChanged)
|
|
||||||
{
|
|
||||||
// restore state
|
|
||||||
imageView_->setImageShown(odomImageShow_);
|
|
||||||
imageView_->setImageDepthShown(odomImageDepthShow_);
|
|
||||||
}
|
|
||||||
|
|
||||||
imageView_->setImage(uCvMat2QImage(data.image()));
|
|
||||||
if(imageView_->isImageDepthShown())
|
|
||||||
{
|
|
||||||
imageView_->setImageDepth(uCvMat2QImage(data.depthOrRightImage()));
|
|
||||||
}
|
|
||||||
|
|
||||||
if(info.type == 0)
|
|
||||||
{
|
|
||||||
if(imageView_->isFeaturesShown())
|
|
||||||
{
|
|
||||||
for(unsigned int i=0; i<info.wordMatches.size(); ++i)
|
|
||||||
{
|
|
||||||
imageView_->setFeatureColor(info.wordMatches[i], Qt::red); // outliers
|
|
||||||
}
|
|
||||||
for(unsigned int i=0; i<info.wordInliers.size(); ++i)
|
|
||||||
{
|
|
||||||
imageView_->setFeatureColor(info.wordInliers[i], Qt::green); // inliers
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(info.type == 1)
|
|
||||||
{
|
|
||||||
if(imageView_->isFeaturesShown() || imageView_->isLinesShown())
|
|
||||||
{
|
|
||||||
//draw lines
|
|
||||||
UASSERT(info.refCorners.size() == info.newCorners.size());
|
|
||||||
for(unsigned int i=0; i<info.cornerInliers.size(); ++i)
|
|
||||||
{
|
|
||||||
if(imageView_->isFeaturesShown())
|
|
||||||
{
|
|
||||||
imageView_->setFeatureColor(info.cornerInliers[i], Qt::green); // inliers
|
|
||||||
}
|
|
||||||
if(imageView_->isLinesShown())
|
|
||||||
{
|
|
||||||
imageView_->addLine(
|
|
||||||
info.refCorners[info.cornerInliers[i]].pt.x,
|
|
||||||
info.refCorners[info.cornerInliers[i]].pt.y,
|
|
||||||
info.newCorners[info.cornerInliers[i]].pt.x,
|
|
||||||
info.newCorners[info.cornerInliers[i]].pt.y,
|
|
||||||
Qt::blue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
imageView_->update();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
if(!data.image().empty())
|
|
||||||
{
|
|
||||||
imageView_->setSceneRect(QRectF(0,0,(float)data.image().cols, (float)data.image().rows));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
label_->setText(tr("Rate=~%1 Hz").arg(receivingRate_));
|
|
||||||
processingOdomInfo_ = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void OdomInfoWidget::closeEvent(QCloseEvent* event)
|
|
||||||
{
|
|
||||||
this->unregisterFromEventsManager();
|
|
||||||
event->accept();
|
|
||||||
}
|
|
||||||
|
|
||||||
void OdomInfoWidget::handleEvent(UEvent * event)
|
|
||||||
{
|
|
||||||
if(event->getClassName().compare("OdometryEvent") == 0)
|
|
||||||
{
|
|
||||||
rtabmap::OdometryEvent * odomEvent = (rtabmap::OdometryEvent*)event;
|
|
||||||
receivingRate_ = 1.0f/timer_.ticks();
|
|
||||||
|
|
||||||
// update max 10 Hz
|
|
||||||
if(UTimer::now() - lastTime_ > 0.1)
|
|
||||||
{
|
|
||||||
lastTime_ = UTimer::now();
|
|
||||||
if(!processingOdomInfo_ && this->isVisible())
|
|
||||||
{
|
|
||||||
QMetaObject::invokeMethod(this, "processOdomInfo",
|
|
||||||
Q_ARG(rtabmap::SensorData, odomEvent->data()),
|
|
||||||
Q_ARG(rtabmap::OdometryInfo, odomEvent->info()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,66 +0,0 @@
|
|||||||
/*
|
|
||||||
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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef ODOMINFOWIDGET_H_
|
|
||||||
#define ODOMINFOWIDGET_H_
|
|
||||||
|
|
||||||
#include <rtabmap/utilite/UEventsHandler.h>
|
|
||||||
#include <QWidget>
|
|
||||||
#include <rtabmap/utilite/UTimer.h>
|
|
||||||
#include <rtabmap/core/SensorData.h>
|
|
||||||
#include <rtabmap/core/OdometryInfo.h>
|
|
||||||
|
|
||||||
class QLabel;
|
|
||||||
|
|
||||||
namespace rtabmap{
|
|
||||||
class ImageView;
|
|
||||||
}
|
|
||||||
|
|
||||||
class OdomInfoWidget : public QWidget, public UEventsHandler
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
OdomInfoWidget(QWidget * parent = 0);
|
|
||||||
virtual ~OdomInfoWidget();
|
|
||||||
public slots:
|
|
||||||
void processOdomInfo(const rtabmap::SensorData & data, const rtabmap::OdometryInfo & info);
|
|
||||||
protected:
|
|
||||||
virtual void closeEvent(QCloseEvent* event);
|
|
||||||
void handleEvent(UEvent * event);
|
|
||||||
|
|
||||||
private:
|
|
||||||
rtabmap::ImageView* imageView_;
|
|
||||||
QLabel* label_;
|
|
||||||
UTimer timer_;
|
|
||||||
bool processingOdomInfo_;
|
|
||||||
double receivingRate_;
|
|
||||||
double lastTime_;
|
|
||||||
bool odomImageShow_;
|
|
||||||
bool odomImageDepthShow_;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* ODOMINFOWIDGET_H_ */
|
|
||||||
@@ -36,15 +36,15 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include <rtabmap/core/DBReader.h>
|
#include <rtabmap/core/DBReader.h>
|
||||||
#include <rtabmap/core/VWDictionary.h>
|
#include <rtabmap/core/VWDictionary.h>
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
|
#include <QPushButton>
|
||||||
#include <pcl/console/print.h>
|
#include <pcl/console/print.h>
|
||||||
#include "OdomInfoWidget.h"
|
|
||||||
|
|
||||||
void showUsage()
|
void showUsage()
|
||||||
{
|
{
|
||||||
printf("\nUsage:\n"
|
printf("\nUsage:\n"
|
||||||
"odometryViewer [options]\n"
|
"odometryViewer [options]\n"
|
||||||
"Options:\n"
|
"Options:\n"
|
||||||
" -driver # Driver number to use: 0=OpenNI-PCL, 1=OpenNI2, 2=Freenect, 3=OpenNI-CV, 4=OpenNI-CV-ASUS\n"
|
" -driver # Driver number to use: 0=OpenNI-PCL, 1=OpenNI2, 2=Freenect, 3=OpenNI-CV, 4=OpenNI-CV-ASUS, 5=Freenect2, 6=dc1394\n"
|
||||||
" -o # Odometry type (default 6): 0=SURF, 1=SIFT, 2=ORB, 3=FAST/FREAK, 4=FAST/BRIEF, 5=GFTT/FREAK, 6=GFTT/BRIEF, 7=BRISK\n"
|
" -o # Odometry type (default 6): 0=SURF, 1=SIFT, 2=ORB, 3=FAST/FREAK, 4=FAST/BRIEF, 5=GFTT/FREAK, 6=GFTT/BRIEF, 7=BRISK\n"
|
||||||
" -nn # Nearest neighbor strategy (default 3): kNNFlannNaive=0, kNNFlannKdTree=1, kNNFlannLSH=2, kNNBruteForce=3, kNNBruteForceGPU=4\n"
|
" -nn # Nearest neighbor strategy (default 3): kNNFlannNaive=0, kNNFlannKdTree=1, kNNFlannLSH=2, kNNBruteForce=3, kNNBruteForceGPU=4\n"
|
||||||
" -nndr # Nearest neighbor distance ratio (default 0.7)\n"
|
" -nndr # Nearest neighbor distance ratio (default 0.7)\n"
|
||||||
@@ -90,6 +90,8 @@ int main (int argc, char * argv[])
|
|||||||
{
|
{
|
||||||
ULogger::setType(ULogger::kTypeConsole);
|
ULogger::setType(ULogger::kTypeConsole);
|
||||||
ULogger::setLevel(ULogger::kInfo);
|
ULogger::setLevel(ULogger::kInfo);
|
||||||
|
ULogger::setPrintTime(false);
|
||||||
|
ULogger::setPrintWhere(false);
|
||||||
|
|
||||||
// parse arguments
|
// parse arguments
|
||||||
float rate = 0.0;
|
float rate = 0.0;
|
||||||
@@ -126,7 +128,7 @@ int main (int argc, char * argv[])
|
|||||||
if(i < argc)
|
if(i < argc)
|
||||||
{
|
{
|
||||||
driver = std::atoi(argv[i]);
|
driver = std::atoi(argv[i]);
|
||||||
if(driver < 0 || driver > 4)
|
if(driver < 0 || driver > 6)
|
||||||
{
|
{
|
||||||
showUsage();
|
showUsage();
|
||||||
}
|
}
|
||||||
@@ -501,6 +503,8 @@ int main (int argc, char * argv[])
|
|||||||
if(strcmp(argv[i], "-debug") == 0)
|
if(strcmp(argv[i], "-debug") == 0)
|
||||||
{
|
{
|
||||||
ULogger::setLevel(ULogger::kDebug);
|
ULogger::setLevel(ULogger::kDebug);
|
||||||
|
ULogger::setPrintTime(true);
|
||||||
|
ULogger::setPrintWhere(true);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -680,23 +684,11 @@ int main (int argc, char * argv[])
|
|||||||
}
|
}
|
||||||
rtabmap::OdometryThread odomThread(odom);
|
rtabmap::OdometryThread odomThread(odom);
|
||||||
rtabmap::OdometryViewer odomViewer(maxClouds, 2, 0.0, 50);
|
rtabmap::OdometryViewer odomViewer(maxClouds, 2, 0.0, 50);
|
||||||
OdomInfoWidget odomInfoWidget;
|
|
||||||
UEventsManager::addHandler(&odomThread);
|
UEventsManager::addHandler(&odomThread);
|
||||||
UEventsManager::addHandler(&odomViewer);
|
UEventsManager::addHandler(&odomViewer);
|
||||||
UEventsManager::addHandler(&odomInfoWidget);
|
|
||||||
|
|
||||||
odomViewer.setCameraFree();
|
odomViewer.setWindowTitle("Odometry view");
|
||||||
odomViewer.setGridShown(true);
|
odomViewer.resize(1280, 480+QPushButton().minimumHeight());
|
||||||
|
|
||||||
odomViewer.setWindowTitle("Odometry 3D view");
|
|
||||||
odomViewer.setMinimumWidth(800);
|
|
||||||
odomViewer.setMinimumHeight(500);
|
|
||||||
odomViewer.showNormal();
|
|
||||||
|
|
||||||
odomInfoWidget.setWindowTitle("Odometry info");
|
|
||||||
odomInfoWidget.showNormal();
|
|
||||||
|
|
||||||
app.processEvents();
|
|
||||||
|
|
||||||
if(inputDatabase.size())
|
if(inputDatabase.size())
|
||||||
{
|
{
|
||||||
@@ -756,6 +748,24 @@ int main (int argc, char * argv[])
|
|||||||
}
|
}
|
||||||
camera = new rtabmap::CameraOpenNICV(true, rate, t);
|
camera = new rtabmap::CameraOpenNICV(true, rate, t);
|
||||||
}
|
}
|
||||||
|
else if(driver == 5)
|
||||||
|
{
|
||||||
|
if(!rtabmap::CameraFreenect2::available())
|
||||||
|
{
|
||||||
|
UERROR("Not built with Freenect2 support...");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
camera = new rtabmap::CameraFreenect2(0, rate, t);
|
||||||
|
}
|
||||||
|
else if(driver == 6)
|
||||||
|
{
|
||||||
|
if(!rtabmap::CameraStereoDC1394::available())
|
||||||
|
{
|
||||||
|
UERROR("Not built with dc1394 support...");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
camera = new rtabmap::CameraStereoDC1394(rate, t);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
UFATAL("Camera driver (%d) not found!", driver);
|
UFATAL("Camera driver (%d) not found!", driver);
|
||||||
@@ -763,16 +773,28 @@ int main (int argc, char * argv[])
|
|||||||
|
|
||||||
//pcl::console::setVerbosityLevel(pcl::console::L_DEBUG);
|
//pcl::console::setVerbosityLevel(pcl::console::L_DEBUG);
|
||||||
|
|
||||||
rtabmap::CameraThread cameraThread(camera);
|
if(camera->init())
|
||||||
if(cameraThread.init())
|
|
||||||
{
|
{
|
||||||
odomThread.start();
|
if(camera->isCalibrated())
|
||||||
cameraThread.start();
|
{
|
||||||
|
rtabmap::CameraThread cameraThread(camera);
|
||||||
|
|
||||||
app.exec();
|
odomThread.start();
|
||||||
|
cameraThread.start();
|
||||||
|
|
||||||
cameraThread.kill();
|
odomViewer.exec();
|
||||||
odomThread.join(true);
|
|
||||||
|
cameraThread.kill();
|
||||||
|
odomThread.join(true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("The camera is not calibrated! You should calibrate the camera first.\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("Failed to initialize the camera! Please select another driver (see \"--help\").\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user