mirror of
https://github.com/introlab/rtabmap.git
synced 2026-09-01 17:10:26 +08:00
Added CalibrationDialog in Preferences->source for convenience. The database is also changed to handle new FX, FY, CX and CY intrinsic parameters instead of only depthConstant parameter. Added version of the database in a new table Admin. Updated to version 0.7.0.
git-svn-id: http://rtabmap.googlecode.com/svn/trunk/rtabmap@1613 f169173b-cf89-36c8-b27e-44dbe73f0c83
This commit is contained in:
@@ -27,11 +27,23 @@ public:
|
||||
CalibrationDialog(QWidget * parent = 0);
|
||||
virtual ~CalibrationDialog();
|
||||
|
||||
bool isCalibrated() const {return calibrated_;}
|
||||
const cv::Mat & cameraMatrix() const {return cameraMatrix_;} // Matrix K
|
||||
const cv::Mat & distCoeffs() const {return distCoeffs_;} // Matrix D
|
||||
float fx() const {return cameraMatrix_.at<double>(0,0);} // K(0)
|
||||
float fy() const {return cameraMatrix_.at<double>(1,1);} // K(4)
|
||||
float cx() const {return cameraMatrix_.at<double>(0,2);} // K(2)
|
||||
float cy() const {return cameraMatrix_.at<double>(1,2);} // K(5)
|
||||
|
||||
public slots:
|
||||
void setBoardWidth(int width);
|
||||
void setBoardHeight(int height);
|
||||
void setSquareSize(double size);
|
||||
|
||||
private slots:
|
||||
void processImage(const cv::Mat & image);
|
||||
void restart();
|
||||
void calibrate();
|
||||
void exit();
|
||||
|
||||
protected:
|
||||
virtual void closeEvent(QCloseEvent* event);
|
||||
|
||||
@@ -189,7 +189,10 @@ private:
|
||||
int id,
|
||||
const cv::Mat & rgb,
|
||||
const cv::Mat & depth,
|
||||
float depthConstant,
|
||||
float fx,
|
||||
float fy,
|
||||
float cx,
|
||||
float cy,
|
||||
const Transform & localTransform,
|
||||
const Transform & pose,
|
||||
float voxelSize,
|
||||
@@ -224,7 +227,10 @@ private:
|
||||
QMap<int, std::vector<unsigned char> > _imagesMap;
|
||||
QMap<int, std::vector<unsigned char> > _depthsMap;
|
||||
QMap<int, std::vector<unsigned char> > _depths2DMap;
|
||||
QMap<int, float> _depthConstantsMap;
|
||||
QMap<int, float> _depthFxsMap;
|
||||
QMap<int, float> _depthFysMap;
|
||||
QMap<int, float> _depthCxsMap;
|
||||
QMap<int, float> _depthCysMap;
|
||||
QMap<int, Transform> _localTransformsMap;
|
||||
std::map<int, Transform> _currentPosesMap;
|
||||
Transform _odometryCorrection;
|
||||
|
||||
@@ -159,7 +159,10 @@ public:
|
||||
Src getSourceRGBD() const; // Openni group
|
||||
QString getSourceOpenniDevice() const; //Openni group
|
||||
Transform getSourceOpenniLocalTransform() const; //Openni group
|
||||
float getSourceOpenniFocalLength() const; // Openni group
|
||||
float getSourceOpenniFx() const; // Openni group
|
||||
float getSourceOpenniFy() const; // Openni group
|
||||
float getSourceOpenniCx() const; // Openni group
|
||||
float getSourceOpenniCy() const; // Openni group
|
||||
|
||||
int getIgnoredDCComponents() const;
|
||||
|
||||
@@ -219,6 +222,7 @@ private slots:
|
||||
void openDatabaseViewer();
|
||||
void cleanOdometryTest();
|
||||
void testOdometry();
|
||||
void calibrate();
|
||||
|
||||
protected:
|
||||
virtual void showEvent ( QShowEvent * event );
|
||||
|
||||
@@ -93,8 +93,6 @@ SET(LIBRARIES
|
||||
${QT_LIBRARIES}
|
||||
${OpenCV_LIBS}
|
||||
${PCL_LIBRARIES}
|
||||
QVTK
|
||||
vtkHybrid
|
||||
)
|
||||
|
||||
#include files
|
||||
|
||||
@@ -37,7 +37,15 @@ CalibrationDialog::CalibrationDialog(QWidget * parent) :
|
||||
|
||||
connect(ui_->pushButton_calibrate, SIGNAL(clicked()), this, SLOT(calibrate()));
|
||||
connect(ui_->pushButton_restart, SIGNAL(clicked()), this, SLOT(restart()));
|
||||
connect(ui_->pushButton_exit, SIGNAL(clicked()), this, SLOT(exit()));
|
||||
|
||||
connect(ui_->spinBox_boardWidth, SIGNAL(valueChanged(int)), this, SLOT(setBoardWidth(int)));
|
||||
connect(ui_->spinBox_boardHeight, SIGNAL(valueChanged(int)), this, SLOT(setBoardHeight(int)));
|
||||
connect(ui_->doubleSpinBox_squareSize, SIGNAL(valueChanged(double)), this, SLOT(setSquareSize(double)));
|
||||
|
||||
connect(ui_->buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
|
||||
connect(ui_->buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
|
||||
|
||||
ui_->image_view->setFocus();
|
||||
|
||||
ui_->progressBar_count->setMaximum(COUNT_MIN);
|
||||
ui_->progressBar_count->setFormat("%v");
|
||||
@@ -51,6 +59,33 @@ CalibrationDialog::~CalibrationDialog()
|
||||
delete ui_;
|
||||
}
|
||||
|
||||
void CalibrationDialog::setBoardWidth(int width)
|
||||
{
|
||||
if(width != boardSize_.width)
|
||||
{
|
||||
boardSize_.width = width;
|
||||
this->restart();
|
||||
}
|
||||
}
|
||||
|
||||
void CalibrationDialog::setBoardHeight(int height)
|
||||
{
|
||||
if(height != boardSize_.height)
|
||||
{
|
||||
boardSize_.height = height;
|
||||
this->restart();
|
||||
}
|
||||
}
|
||||
|
||||
void CalibrationDialog::setSquareSize(double size)
|
||||
{
|
||||
if(size != squareSize_)
|
||||
{
|
||||
squareSize_ = size;
|
||||
this->restart();
|
||||
}
|
||||
}
|
||||
|
||||
void CalibrationDialog::closeEvent(QCloseEvent* event)
|
||||
{
|
||||
this->unregisterFromEventsManager();
|
||||
@@ -197,7 +232,7 @@ void CalibrationDialog::restart()
|
||||
imageParams_.clear();
|
||||
|
||||
ui_->pushButton_calibrate->setEnabled(false);
|
||||
ui_->pushButton_save->setEnabled(false);
|
||||
ui_->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
|
||||
ui_->checkBox_rectified->setEnabled(false);
|
||||
|
||||
ui_->progressBar_count->reset();
|
||||
@@ -286,12 +321,9 @@ void CalibrationDialog::calibrate()
|
||||
|
||||
ui_->checkBox_rectified->setEnabled(true);
|
||||
ui_->checkBox_rectified->setChecked(true);
|
||||
}
|
||||
}
|
||||
|
||||
void CalibrationDialog::exit()
|
||||
{
|
||||
this->close();
|
||||
ui_->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
float CalibrationDialog::getArea(const std::vector<cv::Point2f> & corners, const cv::Size & boardSize)
|
||||
|
||||
@@ -448,13 +448,13 @@ void CloudViewer::updateCameraPosition(const Transform & pose)
|
||||
cameras.front().view[2] = Fp[10];
|
||||
}
|
||||
|
||||
_visualizer->removeCoordinateSystem(0);
|
||||
_visualizer->addCoordinateSystem(0.2, m, 0);
|
||||
_visualizer->setCameraPosition(
|
||||
cameras.front().pos[0], cameras.front().pos[1], cameras.front().pos[2],
|
||||
cameras.front().focal[0], cameras.front().focal[1], cameras.front().focal[2],
|
||||
cameras.front().view[0], cameras.front().view[1], cameras.front().view[2]);
|
||||
}
|
||||
_visualizer->removeCoordinateSystem(0);
|
||||
_visualizer->addCoordinateSystem(0.2, m, 0);
|
||||
}
|
||||
|
||||
_lastPose = pose;
|
||||
|
||||
@@ -200,17 +200,17 @@ void DatabaseViewer::exportDatabase()
|
||||
{
|
||||
int id = ids_.at(i);
|
||||
std::vector<unsigned char> compressedRgb, compressedDepth, compressedDepth2d;
|
||||
float tmpDepthConstant;
|
||||
float tmpFx, tmpFy, tmpCx, tmpCy;
|
||||
rtabmap::Transform tmpLocalTransform, pose;
|
||||
|
||||
memory_->getImageDepth(id, compressedRgb, compressedDepth, compressedDepth2d, tmpDepthConstant, tmpLocalTransform);
|
||||
memory_->getImageDepth(id, compressedRgb, compressedDepth, compressedDepth2d, tmpFx, tmpFy, tmpCx, tmpCy, tmpLocalTransform);
|
||||
if(dialog.isOdomExported())
|
||||
{
|
||||
memory_->getPose(id, pose, true);
|
||||
}
|
||||
|
||||
cv::Mat rgb, depth, depth2d;
|
||||
float depthConstant = 0;
|
||||
float fx = 0, fy = 0, cx = 0, cy = 0;
|
||||
rtabmap::Transform localTransform;
|
||||
|
||||
if(dialog.isRgbExported())
|
||||
@@ -220,7 +220,10 @@ void DatabaseViewer::exportDatabase()
|
||||
if(dialog.isDepthExported())
|
||||
{
|
||||
depth = rtabmap::util3d::uncompressImage(compressedDepth);
|
||||
depthConstant = tmpDepthConstant;
|
||||
fx = tmpFx;
|
||||
fy = tmpFy;
|
||||
cx = tmpCx;
|
||||
cy = tmpCy;
|
||||
localTransform = tmpLocalTransform;
|
||||
}
|
||||
if(dialog.isDepth2dExported())
|
||||
@@ -228,7 +231,7 @@ void DatabaseViewer::exportDatabase()
|
||||
depth2d = rtabmap::util3d::uncompressData(compressedDepth2d);
|
||||
}
|
||||
|
||||
rtabmap::Image data(rgb, depth, depth2d, depthConstant, pose, localTransform, id);
|
||||
rtabmap::Image data(rgb, depth, depth2d, fx, fy, cx, cy, pose, localTransform, id);
|
||||
recorder.addData(data);
|
||||
|
||||
progressDialog.appendText(tr("Exported node %1").arg(id));
|
||||
@@ -518,17 +521,17 @@ void DatabaseViewer::view3DMap()
|
||||
if(!pose.isNull())
|
||||
{
|
||||
std::vector<unsigned char> image, depth, depth2d;
|
||||
float depthConstant;
|
||||
float fx, fy, cx, cy;
|
||||
rtabmap::Transform localTransform;
|
||||
memory_->getImageDepth(iter->first, image, depth, depth2d, depthConstant, localTransform);
|
||||
memory_->getImageDepth(iter->first, image, depth, depth2d, fx, fy, cx, cy, localTransform);
|
||||
pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud;
|
||||
cv::Mat imageMat = rtabmap::util3d::uncompressImage(image);
|
||||
cv::Mat depthMat = rtabmap::util3d::uncompressImage(depth);
|
||||
cloud = rtabmap::util3d::cloudFromDepthRGB(
|
||||
imageMat,
|
||||
depthMat,
|
||||
depthMat.cols/2, depthMat.rows/2,
|
||||
1.0f/depthConstant, 1.0f/depthConstant,
|
||||
cx, cy,
|
||||
fx, fy,
|
||||
decimation);
|
||||
|
||||
if(maxDepth)
|
||||
@@ -616,17 +619,17 @@ void DatabaseViewer::generate3DMap()
|
||||
if(!pose.isNull())
|
||||
{
|
||||
std::vector<unsigned char> image, depth, depth2d;
|
||||
float depthConstant;
|
||||
float fx, fy, cx, cy;
|
||||
rtabmap::Transform localTransform;
|
||||
memory_->getImageDepth(iter->first, image, depth, depth2d, depthConstant, localTransform);
|
||||
memory_->getImageDepth(iter->first, image, depth, depth2d, fx, fy, cx, cy, localTransform);
|
||||
pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud;
|
||||
cv::Mat imageMat = rtabmap::util3d::uncompressImage(image);
|
||||
cv::Mat depthMat = rtabmap::util3d::uncompressImage(depth);
|
||||
cloud = rtabmap::util3d::cloudFromDepthRGB(
|
||||
imageMat,
|
||||
depthMat,
|
||||
depthMat.cols/2, depthMat.rows/2,
|
||||
1.0f/depthConstant, 1.0f/depthConstant,
|
||||
cx, cy,
|
||||
fx, fy,
|
||||
decimation);
|
||||
|
||||
if(maxDepth)
|
||||
@@ -703,9 +706,9 @@ void DatabaseViewer::update(int value,
|
||||
if(memory_)
|
||||
{
|
||||
std::vector<unsigned char> image, depth, depth2d;
|
||||
float depthConstant;
|
||||
float fx, fy, cx, cy;
|
||||
rtabmap::Transform localTransform;
|
||||
memory_->getImageDepth(id, image, depth, depth2d, depthConstant, localTransform);
|
||||
memory_->getImageDepth(id, image, depth, depth2d, fx, fy, cx, cy, localTransform);
|
||||
cv::Mat imageMat = rtabmap::util3d::uncompressImage(image);
|
||||
cv::Mat depthMat = rtabmap::util3d::uncompressImage(depth);
|
||||
if(!image.empty())
|
||||
@@ -830,17 +833,18 @@ void DatabaseViewer::updateConstraintView(const rtabmap::Link & link)
|
||||
ui_->horizontalSlider_A->setValue(idToIndex_.value(link.from()));
|
||||
ui_->horizontalSlider_B->setValue(idToIndex_.value(link.to()));
|
||||
|
||||
float depthConstantA, depthConstantB;
|
||||
float fxA, fyA, cxA, cyA;
|
||||
float fxB, fyB, cxB, cyB;
|
||||
rtabmap::Transform localTransformA, localTransformB;
|
||||
|
||||
std::vector<unsigned char> imageBytesA, depthBytesA, depth2dBytesA;
|
||||
memory_->getImageDepth(link.from(), imageBytesA, depthBytesA, depth2dBytesA, depthConstantA, localTransformA);
|
||||
memory_->getImageDepth(link.from(), imageBytesA, depthBytesA, depth2dBytesA, fxA, fyA, cxA, cyA, localTransformA);
|
||||
cv::Mat imageA = rtabmap::util3d::uncompressImage(imageBytesA);
|
||||
cv::Mat depthA = rtabmap::util3d::uncompressImage(depthBytesA);
|
||||
cv::Mat depth2dA = rtabmap::util3d::uncompressData(depth2dBytesA);
|
||||
|
||||
std::vector<unsigned char> imageBytesB, depthBytesB, depth2dBytesB;
|
||||
memory_->getImageDepth(link.to(), imageBytesB, depthBytesB, depth2dBytesB, depthConstantB, localTransformB);
|
||||
memory_->getImageDepth(link.to(), imageBytesB, depthBytesB, depth2dBytesB, fxB, fyB, cxB, cyB, localTransformB);
|
||||
cv::Mat imageB = rtabmap::util3d::uncompressImage(imageBytesB);
|
||||
cv::Mat depthB = rtabmap::util3d::uncompressImage(depthBytesB);
|
||||
cv::Mat depth2dB = rtabmap::util3d::uncompressData(depth2dBytesB);
|
||||
@@ -850,10 +854,8 @@ void DatabaseViewer::updateConstraintView(const rtabmap::Link & link)
|
||||
cloudA = rtabmap::util3d::cloudFromDepthRGB(
|
||||
imageA,
|
||||
depthA,
|
||||
depthA.cols/2,
|
||||
depthA.rows/2,
|
||||
1.0f/depthConstantA,
|
||||
1.0f/depthConstantA,
|
||||
cxA, cyA,
|
||||
fxA, fyA,
|
||||
1);
|
||||
|
||||
cloudA = rtabmap::util3d::removeNaNFromPointCloud(cloudA);
|
||||
@@ -863,10 +865,8 @@ void DatabaseViewer::updateConstraintView(const rtabmap::Link & link)
|
||||
cloudB = rtabmap::util3d::cloudFromDepthRGB(
|
||||
imageB,
|
||||
depthB,
|
||||
depthB.cols/2,
|
||||
depthB.rows/2,
|
||||
1.0f/depthConstantB,
|
||||
1.0f/depthConstantB,
|
||||
cxB, cyB,
|
||||
fxB, fyB,
|
||||
1);
|
||||
|
||||
cloudB = rtabmap::util3d::removeNaNFromPointCloud(cloudB);
|
||||
@@ -908,13 +908,13 @@ void DatabaseViewer::sliderIterationsValueChanged(int value)
|
||||
UINFO("Update scans list...");
|
||||
for(int i=0; i<ids_.size(); ++i)
|
||||
{
|
||||
std::vector<unsigned char> imageBytesA, depthBytesA, depth2dBytesA;
|
||||
float depthConstantA;
|
||||
rtabmap::Transform localTransformA;
|
||||
memory_->getImageDepth(ids_.at(i), imageBytesA, depthBytesA, depth2dBytesA, depthConstantA, localTransformA);
|
||||
if(depth2dBytesA.size())
|
||||
std::vector<unsigned char> imageBytes, depthBytes, depth2dBytes;
|
||||
float fx, fy, cx, cy;
|
||||
rtabmap::Transform localTransform;
|
||||
memory_->getImageDepth(ids_.at(i), imageBytes, depthBytes, depth2dBytes, fx, fy, cx, cy, localTransform);
|
||||
if(depth2dBytes.size())
|
||||
{
|
||||
scans_.insert(ids_.at(i), depth2dBytesA);
|
||||
scans_.insert(ids_.at(i), depth2dBytes);
|
||||
}
|
||||
}
|
||||
UINFO("Update scans list... done");
|
||||
|
||||
@@ -129,10 +129,8 @@ void LoopClosureViewer::updateView(const Transform & transform)
|
||||
pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloudA;
|
||||
cloudA = util3d::cloudFromDepthRGB(
|
||||
imageA,
|
||||
depthA,
|
||||
depthA.cols/2,
|
||||
depthA.rows/2,
|
||||
1.0f/sA_->getDepthConstant(),
|
||||
depthA,
|
||||
sA_->getDepthCx(), sA_->getDepthCy(),
|
||||
sA_->getDepthFx(), sA_->getDepthFy(),
|
||||
decimation);
|
||||
|
||||
@@ -151,10 +149,8 @@ void LoopClosureViewer::updateView(const Transform & transform)
|
||||
pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloudB;
|
||||
cloudB = util3d::cloudFromDepthRGB(
|
||||
imageB,
|
||||
depthB,
|
||||
depthB.cols/2,
|
||||
depthB.rows/2,
|
||||
1.0f/sB_->getDepthConstant(),
|
||||
depthB,
|
||||
sB_->getDepthCx(), sB_->getDepthCy(),
|
||||
sB_->getDepthFx(), sB_->getDepthFy(),
|
||||
decimation);
|
||||
|
||||
|
||||
@@ -575,14 +575,18 @@ void MainWindow::processOdometry(const rtabmap::Image & data, int quality)
|
||||
if(data.depth().cols == data.image().cols &&
|
||||
data.depth().rows == data.image().rows &&
|
||||
!data.depth().empty() &&
|
||||
data.depthConstant() > 0.0f &&
|
||||
data.depthFx() > 0.0f &&
|
||||
data.depthFy() > 0.0f &&
|
||||
_preferencesDialog->isCloudsShown(1))
|
||||
{
|
||||
pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud;
|
||||
cloud = createCloud(0,
|
||||
data.image(),
|
||||
data.depth(),
|
||||
data.depthConstant(),
|
||||
data.depthFx(),
|
||||
data.depthFy(),
|
||||
data.depthCx(),
|
||||
data.depthCy(),
|
||||
data.localTransform(),
|
||||
pose,
|
||||
_preferencesDialog->getCloudVoxelSize(1),
|
||||
@@ -685,12 +689,18 @@ void MainWindow::processStats(const rtabmap::Statistics & stat)
|
||||
{
|
||||
if(!iter->second.empty() && !_depthsMap.contains(iter->first))
|
||||
{
|
||||
float constant = uValue(stat.getDepthConstants(), iter->first, 0.0f);
|
||||
float fx = uValue(stat.getDepthFxs(), iter->first, 0.0f);
|
||||
float fy = uValue(stat.getDepthFys(), iter->first, 0.0f);
|
||||
float cx = uValue(stat.getDepthCxs(), iter->first, 0.0f);
|
||||
float cy = uValue(stat.getDepthCys(), iter->first, 0.0f);
|
||||
Transform transform = uValue(stat.getLocalTransforms(), iter->first, Transform());
|
||||
if(constant != 0.0f && !transform.isNull())
|
||||
if(fx > 0.0f && fy > 0.0f && !transform.isNull())
|
||||
{
|
||||
_depthsMap.insert(iter->first, iter->second);
|
||||
_depthConstantsMap.insert(iter->first, constant);
|
||||
_depthFxsMap.insert(iter->first, fx);
|
||||
_depthFysMap.insert(iter->first, fy);
|
||||
_depthCxsMap.insert(iter->first, cx);
|
||||
_depthCysMap.insert(iter->first, cy);
|
||||
_localTransformsMap.insert(iter->first, transform);
|
||||
}
|
||||
else
|
||||
@@ -992,7 +1002,10 @@ void MainWindow::processStats(const rtabmap::Statistics & stat)
|
||||
_depths2DMap.value(loopOldId, std::vector<unsigned char>()),
|
||||
_imagesMap.value(loopOldId, std::vector<unsigned char>()),
|
||||
_depthsMap.value(loopOldId, std::vector<unsigned char>()),
|
||||
_depthConstantsMap.value(loopOldId, 0.0f),
|
||||
_depthFxsMap.value(loopOldId, 0.0f),
|
||||
_depthFysMap.value(loopOldId, 0.0f),
|
||||
_depthCxsMap.value(loopOldId, 0.0f),
|
||||
_depthCysMap.value(loopOldId, 0.0f),
|
||||
_localTransformsMap.value(loopOldId, Transform()));
|
||||
|
||||
Signature * loopNew = new Signature(
|
||||
@@ -1004,7 +1017,10 @@ void MainWindow::processStats(const rtabmap::Statistics & stat)
|
||||
_depths2DMap.value(loopNewId, std::vector<unsigned char>()),
|
||||
_imagesMap.value(loopNewId, std::vector<unsigned char>()),
|
||||
_depthsMap.value(loopNewId, std::vector<unsigned char>()),
|
||||
_depthConstantsMap.value(loopNewId, 0.0f),
|
||||
_depthFxsMap.value(loopNewId, 0.0f),
|
||||
_depthFysMap.value(loopNewId, 0.0f),
|
||||
_depthCxsMap.value(loopNewId, 0.0f),
|
||||
_depthCysMap.value(loopNewId, 0.0f),
|
||||
_localTransformsMap.value(loopNewId, Transform()));
|
||||
|
||||
_ui->widget_loopClosureViewer->setData(loopOld, loopNew);
|
||||
@@ -1212,7 +1228,10 @@ void MainWindow::createAndAddCloudToMap(int nodeId, const Transform & pose)
|
||||
cloud = createCloud(nodeId,
|
||||
util3d::uncompressImage(_imagesMap.value(nodeId)),
|
||||
util3d::uncompressImage(_depthsMap.value(nodeId)),
|
||||
_depthConstantsMap.value(nodeId),
|
||||
_depthFxsMap.value(nodeId),
|
||||
_depthFysMap.value(nodeId),
|
||||
_depthCxsMap.value(nodeId),
|
||||
_depthCysMap.value(nodeId),
|
||||
_localTransformsMap.value(nodeId),
|
||||
Transform::getIdentity(),
|
||||
_preferencesDialog->getCloudVoxelSize(0),
|
||||
@@ -1376,7 +1395,10 @@ void MainWindow::processRtabmapEvent3DMap(const rtabmap::RtabmapEvent3DMap & eve
|
||||
UINFO(" images = %d", event.getImages().size());
|
||||
UINFO(" depths = %d", event.getDepths().size());
|
||||
UINFO(" depths2d = %d", event.getDepths2d().size());
|
||||
UINFO(" depthConstants = %d", event.getDepthConstants().size());
|
||||
UINFO(" depthFxs = %d", event.getDepthFxs().size());
|
||||
UINFO(" depthFys = %d", event.getDepthFys().size());
|
||||
UINFO(" depthCxs = %d", event.getDepthCxs().size());
|
||||
UINFO(" depthCys = %d", event.getDepthCys().size());
|
||||
UINFO(" localTransforms = %d", event.getLocalTransforms().size());
|
||||
UINFO(" poses = %d", event.getPoses().size());
|
||||
UINFO(" constraints = %d", event.getConstraints().size());
|
||||
@@ -1401,13 +1423,40 @@ void MainWindow::processRtabmapEvent3DMap(const rtabmap::RtabmapEvent3DMap & eve
|
||||
_initProgressDialog->appendText(tr("Inserted %1 depth images.").arg(_depthsMap.size()));
|
||||
_initProgressDialog->incrementStep();
|
||||
|
||||
for(std::map<int, float>::const_iterator iter = event.getDepthConstants().begin();
|
||||
iter!=event.getDepthConstants().end();
|
||||
for(std::map<int, float>::const_iterator iter = event.getDepthFxs().begin();
|
||||
iter!=event.getDepthFxs().end();
|
||||
++iter)
|
||||
{
|
||||
_depthConstantsMap.insert(iter->first, iter->second);
|
||||
_depthFxsMap.insert(iter->first, iter->second);
|
||||
}
|
||||
_initProgressDialog->appendText(tr("Inserted %1 depth constants.").arg(_depthConstantsMap.size()));
|
||||
_initProgressDialog->appendText(tr("Inserted %1 depth fx parameters.").arg(_depthFxsMap.size()));
|
||||
_initProgressDialog->incrementStep();
|
||||
|
||||
for(std::map<int, float>::const_iterator iter = event.getDepthFys().begin();
|
||||
iter!=event.getDepthFys().end();
|
||||
++iter)
|
||||
{
|
||||
_depthFysMap.insert(iter->first, iter->second);
|
||||
}
|
||||
_initProgressDialog->appendText(tr("Inserted %1 depth fy parameters.").arg(_depthFysMap.size()));
|
||||
_initProgressDialog->incrementStep();
|
||||
|
||||
for(std::map<int, float>::const_iterator iter = event.getDepthCxs().begin();
|
||||
iter!=event.getDepthCxs().end();
|
||||
++iter)
|
||||
{
|
||||
_depthCxsMap.insert(iter->first, iter->second);
|
||||
}
|
||||
_initProgressDialog->appendText(tr("Inserted %1 depth cx parameters.").arg(_depthCxsMap.size()));
|
||||
_initProgressDialog->incrementStep();
|
||||
|
||||
for(std::map<int, float>::const_iterator iter = event.getDepthCys().begin();
|
||||
iter!=event.getDepthCys().end();
|
||||
++iter)
|
||||
{
|
||||
_depthCysMap.insert(iter->first, iter->second);
|
||||
}
|
||||
_initProgressDialog->appendText(tr("Inserted %1 depth cy parameters.").arg(_depthCysMap.size()));
|
||||
_initProgressDialog->incrementStep();
|
||||
|
||||
for(std::map<int, std::vector<unsigned char> >::const_iterator iter = event.getDepths2d().begin();
|
||||
@@ -1966,14 +2015,20 @@ void MainWindow::startDetection()
|
||||
_preferencesDialog->getSourceOpenniDevice().toStdString(),
|
||||
_preferencesDialog->getGeneralInputRate(),
|
||||
_preferencesDialog->getSourceOpenniLocalTransform(),
|
||||
_preferencesDialog->getSourceOpenniFocalLength());
|
||||
_preferencesDialog->getSourceOpenniFx(),
|
||||
_preferencesDialog->getSourceOpenniFy(),
|
||||
_preferencesDialog->getSourceOpenniCx(),
|
||||
_preferencesDialog->getSourceOpenniCy());
|
||||
}
|
||||
else if(_preferencesDialog->getSourceRGBD() == PreferencesDialog::kSrcOpenNI2)
|
||||
{
|
||||
camera = new CameraOpenNI2(
|
||||
_preferencesDialog->getGeneralInputRate(),
|
||||
_preferencesDialog->getSourceOpenniLocalTransform(),
|
||||
_preferencesDialog->getSourceOpenniFocalLength());
|
||||
_preferencesDialog->getSourceOpenniFx(),
|
||||
_preferencesDialog->getSourceOpenniFy(),
|
||||
_preferencesDialog->getSourceOpenniCx(),
|
||||
_preferencesDialog->getSourceOpenniCy());
|
||||
}
|
||||
else if(_preferencesDialog->getSourceRGBD() == PreferencesDialog::kSrcFreenect)
|
||||
{
|
||||
@@ -1981,7 +2036,10 @@ void MainWindow::startDetection()
|
||||
_preferencesDialog->getSourceOpenniDevice().isEmpty()?0:atoi(_preferencesDialog->getSourceOpenniDevice().toStdString().c_str()),
|
||||
_preferencesDialog->getGeneralInputRate(),
|
||||
_preferencesDialog->getSourceOpenniLocalTransform(),
|
||||
_preferencesDialog->getSourceOpenniFocalLength());
|
||||
_preferencesDialog->getSourceOpenniFx(),
|
||||
_preferencesDialog->getSourceOpenniFy(),
|
||||
_preferencesDialog->getSourceOpenniCx(),
|
||||
_preferencesDialog->getSourceOpenniCy());
|
||||
}
|
||||
else if(_preferencesDialog->getSourceRGBD() == PreferencesDialog::kSrcOpenNI_CV ||
|
||||
_preferencesDialog->getSourceRGBD() == PreferencesDialog::kSrcOpenNI_CV_ASUS)
|
||||
@@ -1990,7 +2048,10 @@ void MainWindow::startDetection()
|
||||
_preferencesDialog->getSourceRGBD() == PreferencesDialog::kSrcOpenNI_CV_ASUS,
|
||||
_preferencesDialog->getGeneralInputRate(),
|
||||
_preferencesDialog->getSourceOpenniLocalTransform(),
|
||||
_preferencesDialog->getSourceOpenniFocalLength());
|
||||
_preferencesDialog->getSourceOpenniFx(),
|
||||
_preferencesDialog->getSourceOpenniFy(),
|
||||
_preferencesDialog->getSourceOpenniCx(),
|
||||
_preferencesDialog->getSourceOpenniCy());
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2611,7 +2672,10 @@ void MainWindow::clearTheCache()
|
||||
_imagesMap.clear();
|
||||
_depthsMap.clear();
|
||||
_depths2DMap.clear();
|
||||
_depthConstantsMap.clear();
|
||||
_depthFxsMap.clear();
|
||||
_depthFysMap.clear();
|
||||
_depthCxsMap.clear();
|
||||
_depthCysMap.clear();
|
||||
_localTransformsMap.clear();
|
||||
_ui->widget_cloudViewer->removeAllClouds();
|
||||
_ui->widget_cloudViewer->render();
|
||||
@@ -3481,7 +3545,10 @@ pcl::PointCloud<pcl::PointXYZRGB>::Ptr MainWindow::createCloud(
|
||||
int id,
|
||||
const cv::Mat & rgb,
|
||||
const cv::Mat & depth,
|
||||
float depthConstant,
|
||||
float fx,
|
||||
float fy,
|
||||
float cx,
|
||||
float cy,
|
||||
const Transform & localTransform,
|
||||
const Transform & pose,
|
||||
float voxelSize,
|
||||
@@ -3492,11 +3559,9 @@ pcl::PointCloud<pcl::PointXYZRGB>::Ptr MainWindow::createCloud(
|
||||
pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud = util3d::cloudFromDepthRGB(
|
||||
rgb,
|
||||
depth,
|
||||
float(depth.cols/2),
|
||||
float(depth.rows/2),
|
||||
1.0f/depthConstant,
|
||||
1.0f/depthConstant,
|
||||
decimation);
|
||||
cx, cy,
|
||||
fx, fy,
|
||||
decimation);
|
||||
|
||||
if(cloud->size())
|
||||
{
|
||||
@@ -3543,7 +3608,10 @@ pcl::PointCloud<pcl::PointXYZRGB>::Ptr MainWindow::createAssembledCloud(const st
|
||||
cloud = createCloud(iter->first,
|
||||
util3d::uncompressImage(_imagesMap.value(iter->first)),
|
||||
util3d::uncompressImage(_depthsMap.value(iter->first)),
|
||||
_depthConstantsMap.value(iter->first),
|
||||
_depthFxsMap.value(iter->first),
|
||||
_depthFysMap.value(iter->first),
|
||||
_depthCxsMap.value(iter->first),
|
||||
_depthCysMap.value(iter->first),
|
||||
_localTransformsMap.value(iter->first),
|
||||
iter->second,
|
||||
_preferencesDialog->getCloudVoxelSize(2),
|
||||
@@ -3619,7 +3687,10 @@ std::map<int, pcl::PointCloud<pcl::PointXYZRGB>::Ptr > MainWindow::createPointCl
|
||||
cloud = createCloud(iter->first,
|
||||
util3d::uncompressImage(_imagesMap.value(iter->first)),
|
||||
util3d::uncompressImage(_depthsMap.value(iter->first)),
|
||||
_depthConstantsMap.value(iter->first),
|
||||
_depthFxsMap.value(iter->first),
|
||||
_depthFysMap.value(iter->first),
|
||||
_depthCxsMap.value(iter->first),
|
||||
_depthCysMap.value(iter->first),
|
||||
_localTransformsMap.value(iter->first),
|
||||
Transform::getIdentity(),
|
||||
_preferencesDialog->getCloudVoxelSize(2),
|
||||
@@ -3686,7 +3757,10 @@ std::map<int, pcl::PolygonMesh::Ptr> MainWindow::createMeshes(const std::map<int
|
||||
cloud = createCloud(iter->first,
|
||||
util3d::uncompressImage(_imagesMap.value(iter->first)),
|
||||
util3d::uncompressImage(_depthsMap.value(iter->first)),
|
||||
_depthConstantsMap.value(iter->first),
|
||||
_depthFxsMap.value(iter->first),
|
||||
_depthFysMap.value(iter->first),
|
||||
_depthCxsMap.value(iter->first),
|
||||
_depthCysMap.value(iter->first),
|
||||
_localTransformsMap.value(iter->first),
|
||||
Transform::getIdentity(),
|
||||
_preferencesDialog->getCloudVoxelSize(2),
|
||||
|
||||
@@ -62,7 +62,7 @@ void OdometryViewer::processData()
|
||||
}
|
||||
dataMutex_.unlock();
|
||||
|
||||
if(!data.image().empty() && !data.depth().empty() && data.depthConstant()>0.0f && this->isVisible())
|
||||
if(!data.image().empty() && !data.depth().empty() && data.depthFx()>0.0f && data.depthFy()>0.0f && this->isVisible())
|
||||
{
|
||||
UDEBUG("New pose = %s, quality=%d", data.pose().prettyPrint().c_str(), quality);
|
||||
|
||||
@@ -72,11 +72,9 @@ void OdometryViewer::processData()
|
||||
cloud = util3d::cloudFromDepthRGB(
|
||||
data.image(),
|
||||
data.depth(),
|
||||
float(data.depth().cols/2),
|
||||
float(data.depth().rows/2),
|
||||
1.0f/data.depthConstant(),
|
||||
1.0f/data.depthConstant(),
|
||||
decimation_);
|
||||
data.depthCx(), data.depthCy(),
|
||||
data.depthFx(), data.depthFy(),
|
||||
decimation_);
|
||||
|
||||
if(voxelSize_ > 0.0f)
|
||||
{
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "rtabmap/gui/PreferencesDialog.h"
|
||||
#include "rtabmap/gui/DatabaseViewer.h"
|
||||
#include "rtabmap/gui/OdometryViewer.h"
|
||||
#include "rtabmap/gui/CalibrationDialog.h"
|
||||
|
||||
#include <QtCore/QSettings>
|
||||
#include <QtCore/QDir>
|
||||
@@ -256,7 +257,11 @@ PreferencesDialog::PreferencesDialog(QWidget * parent) :
|
||||
_ui->radioButton_openni2->setEnabled(CameraOpenNI2::available());
|
||||
connect(_ui->lineEdit_openniDevice, SIGNAL(textChanged(const QString &)), this, SLOT(makeObsoleteSourcePanel()));
|
||||
connect(_ui->lineEdit_openniLocalTransform, SIGNAL(textChanged(const QString &)), this, SLOT(makeObsoleteSourcePanel()));
|
||||
connect(_ui->doubleSpinBox_openniFocal, SIGNAL(valueChanged(double)), this, SLOT(makeObsoleteSourcePanel()));
|
||||
connect(_ui->doubleSpinBox_openniFx, SIGNAL(valueChanged(double)), this, SLOT(makeObsoleteSourcePanel()));
|
||||
connect(_ui->doubleSpinBox_openniFy, SIGNAL(valueChanged(double)), this, SLOT(makeObsoleteSourcePanel()));
|
||||
connect(_ui->doubleSpinBox_openniCx, SIGNAL(valueChanged(double)), this, SLOT(makeObsoleteSourcePanel()));
|
||||
connect(_ui->doubleSpinBox_openniCy, SIGNAL(valueChanged(double)), this, SLOT(makeObsoleteSourcePanel()));
|
||||
connect(_ui->pushButton_calibrate, SIGNAL(clicked()), this, SLOT(calibrate()));
|
||||
|
||||
|
||||
//Rtabmap basic
|
||||
@@ -807,7 +812,10 @@ void PreferencesDialog::resetSettings(QGroupBox * groupBox)
|
||||
_ui->radioButton_opennicvasus->setChecked(false);
|
||||
_ui->lineEdit_openniDevice->setText("");
|
||||
_ui->lineEdit_openniLocalTransform->setText("0 0 0 -PI_2 0 -PI_2");
|
||||
_ui->doubleSpinBox_openniFocal->setValue(0.0);
|
||||
_ui->doubleSpinBox_openniFx->setValue(0.0);
|
||||
_ui->doubleSpinBox_openniFy->setValue(0.0);
|
||||
_ui->doubleSpinBox_openniCx->setValue(0.0);
|
||||
_ui->doubleSpinBox_openniCy->setValue(0.0);
|
||||
}
|
||||
else if(groupBox->objectName() == _ui->groupBox_rtabmap_basic0->objectName())
|
||||
{
|
||||
@@ -1063,7 +1071,10 @@ void PreferencesDialog::readCameraSettings(const QString & filePath)
|
||||
_ui->radioButton_opennicvasus->setChecked(settings.value("openniCvAsusType", _ui->radioButton_opennicvasus->isChecked()).toBool());
|
||||
_ui->lineEdit_openniDevice->setText(settings.value("device",_ui->lineEdit_openniDevice->text()).toString());
|
||||
_ui->lineEdit_openniLocalTransform->setText(settings.value("localTransform",_ui->lineEdit_openniLocalTransform->text()).toString());
|
||||
_ui->doubleSpinBox_openniFocal->setValue(settings.value("focalLength", _ui->doubleSpinBox_openniFocal->value()).toDouble());
|
||||
_ui->doubleSpinBox_openniFx->setValue(settings.value("fx", _ui->doubleSpinBox_openniFx->value()).toDouble());
|
||||
_ui->doubleSpinBox_openniFy->setValue(settings.value("fy", _ui->doubleSpinBox_openniFy->value()).toDouble());
|
||||
_ui->doubleSpinBox_openniCx->setValue(settings.value("cx", _ui->doubleSpinBox_openniCx->value()).toDouble());
|
||||
_ui->doubleSpinBox_openniCy->setValue(settings.value("cy", _ui->doubleSpinBox_openniCy->value()).toDouble());
|
||||
settings.endGroup(); // Openni
|
||||
}
|
||||
|
||||
@@ -1273,7 +1284,10 @@ void PreferencesDialog::writeCameraSettings(const QString & filePath)
|
||||
settings.setValue("openniCvAsusType", _ui->radioButton_opennicvasus->isChecked());
|
||||
settings.setValue("device", _ui->lineEdit_openniDevice->text());
|
||||
settings.setValue("localTransform", _ui->lineEdit_openniLocalTransform->text());
|
||||
settings.setValue("focalLength", _ui->doubleSpinBox_openniFocal->value());
|
||||
settings.setValue("fx", _ui->doubleSpinBox_openniFx->value());
|
||||
settings.setValue("fy", _ui->doubleSpinBox_openniFy->value());
|
||||
settings.setValue("cx", _ui->doubleSpinBox_openniCx->value());
|
||||
settings.setValue("cy", _ui->doubleSpinBox_openniCy->value());
|
||||
settings.endGroup();
|
||||
}
|
||||
|
||||
@@ -2640,9 +2654,21 @@ Transform PreferencesDialog::getSourceOpenniLocalTransform() const
|
||||
return t;
|
||||
}
|
||||
|
||||
float PreferencesDialog::getSourceOpenniFocalLength() const
|
||||
float PreferencesDialog::getSourceOpenniFx() const
|
||||
{
|
||||
return _ui->doubleSpinBox_openniFocal->value();
|
||||
return _ui->doubleSpinBox_openniFx->value();
|
||||
}
|
||||
float PreferencesDialog::getSourceOpenniFy() const
|
||||
{
|
||||
return _ui->doubleSpinBox_openniFy->value();
|
||||
}
|
||||
float PreferencesDialog::getSourceOpenniCx() const
|
||||
{
|
||||
return _ui->doubleSpinBox_openniCx->value();
|
||||
}
|
||||
float PreferencesDialog::getSourceOpenniCy() const
|
||||
{
|
||||
return _ui->doubleSpinBox_openniCy->value();
|
||||
}
|
||||
|
||||
bool PreferencesDialog::isStatisticsPublished() const
|
||||
@@ -2778,14 +2804,20 @@ void PreferencesDialog::testOdometry(int type)
|
||||
this->getSourceOpenniDevice().toStdString(),
|
||||
this->getGeneralInputRate(),
|
||||
this->getSourceOpenniLocalTransform(),
|
||||
this->getSourceOpenniFocalLength());
|
||||
this->getSourceOpenniFx(),
|
||||
this->getSourceOpenniFy(),
|
||||
this->getSourceOpenniCx(),
|
||||
this->getSourceOpenniCy());
|
||||
}
|
||||
else if(this->getSourceRGBD() == kSrcOpenNI2)
|
||||
{
|
||||
camera = new CameraOpenNI2(
|
||||
this->getGeneralInputRate(),
|
||||
this->getSourceOpenniLocalTransform(),
|
||||
this->getSourceOpenniFocalLength());
|
||||
this->getSourceOpenniFx(),
|
||||
this->getSourceOpenniFy(),
|
||||
this->getSourceOpenniCx(),
|
||||
this->getSourceOpenniCy());
|
||||
|
||||
}
|
||||
else if(this->getSourceRGBD() == kSrcFreenect)
|
||||
@@ -2794,7 +2826,10 @@ void PreferencesDialog::testOdometry(int type)
|
||||
this->getSourceOpenniDevice().isEmpty()?0:atoi(this->getSourceOpenniDevice().toStdString().c_str()),
|
||||
this->getGeneralInputRate(),
|
||||
this->getSourceOpenniLocalTransform(),
|
||||
this->getSourceOpenniFocalLength());
|
||||
this->getSourceOpenniFx(),
|
||||
this->getSourceOpenniFy(),
|
||||
this->getSourceOpenniCx(),
|
||||
this->getSourceOpenniCy());
|
||||
}
|
||||
else if(this->getSourceRGBD() == kSrcOpenNI_CV || this->getSourceRGBD() == kSrcOpenNI_CV_ASUS)
|
||||
{
|
||||
@@ -2802,7 +2837,10 @@ void PreferencesDialog::testOdometry(int type)
|
||||
this->getSourceRGBD() == kSrcOpenNI_CV_ASUS,
|
||||
this->getGeneralInputRate(),
|
||||
this->getSourceOpenniLocalTransform(),
|
||||
this->getSourceOpenniFocalLength());
|
||||
this->getSourceOpenniFx(),
|
||||
this->getSourceOpenniFy(),
|
||||
this->getSourceOpenniCx(),
|
||||
this->getSourceOpenniCy());
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2881,4 +2919,90 @@ void PreferencesDialog::cleanOdometryTest()
|
||||
_ui->pushButton_testOdometry->setEnabled(true);
|
||||
}
|
||||
|
||||
|
||||
void PreferencesDialog::calibrate()
|
||||
{
|
||||
CameraRGBD * camera = 0;
|
||||
if(this->getSourceRGBD() == kSrcOpenNI_PCL)
|
||||
{
|
||||
camera = new CameraOpenni(
|
||||
this->getSourceOpenniDevice().toStdString(),
|
||||
this->getGeneralInputRate(),
|
||||
this->getSourceOpenniLocalTransform(),
|
||||
this->getSourceOpenniFx(),
|
||||
this->getSourceOpenniFy(),
|
||||
this->getSourceOpenniCx(),
|
||||
this->getSourceOpenniCy());
|
||||
}
|
||||
else if(this->getSourceRGBD() == kSrcOpenNI2)
|
||||
{
|
||||
camera = new CameraOpenNI2(
|
||||
this->getGeneralInputRate(),
|
||||
this->getSourceOpenniLocalTransform(),
|
||||
this->getSourceOpenniFx(),
|
||||
this->getSourceOpenniFy(),
|
||||
this->getSourceOpenniCx(),
|
||||
this->getSourceOpenniCy());
|
||||
|
||||
}
|
||||
else if(this->getSourceRGBD() == kSrcFreenect)
|
||||
{
|
||||
camera = new CameraFreenect(
|
||||
this->getSourceOpenniDevice().isEmpty()?0:atoi(this->getSourceOpenniDevice().toStdString().c_str()),
|
||||
this->getGeneralInputRate(),
|
||||
this->getSourceOpenniLocalTransform(),
|
||||
this->getSourceOpenniFx(),
|
||||
this->getSourceOpenniFy(),
|
||||
this->getSourceOpenniCx(),
|
||||
this->getSourceOpenniCy());
|
||||
}
|
||||
else if(this->getSourceRGBD() == kSrcOpenNI_CV || this->getSourceRGBD() == kSrcOpenNI_CV_ASUS)
|
||||
{
|
||||
camera = new CameraOpenNICV(
|
||||
this->getSourceRGBD() == kSrcOpenNI_CV_ASUS,
|
||||
this->getGeneralInputRate(),
|
||||
this->getSourceOpenniLocalTransform(),
|
||||
this->getSourceOpenniFx(),
|
||||
this->getSourceOpenniFy(),
|
||||
this->getSourceOpenniCx(),
|
||||
this->getSourceOpenniCy());
|
||||
}
|
||||
else
|
||||
{
|
||||
UFATAL("RGBD Source type undefined!");
|
||||
}
|
||||
|
||||
if(!camera->init())
|
||||
{
|
||||
QMessageBox::warning(this,
|
||||
tr("RTAB-Map"),
|
||||
tr("RGBD camera initialization failed!"));
|
||||
delete camera;
|
||||
camera = 0;
|
||||
}
|
||||
|
||||
|
||||
if(camera)
|
||||
{
|
||||
CalibrationDialog * dialog = new CalibrationDialog(this);
|
||||
dialog->registerToEventsManager();
|
||||
|
||||
CameraThread cameraThread(camera);
|
||||
UEventsManager::createPipe(&cameraThread, dialog, "CameraEvent");
|
||||
|
||||
cameraThread.start();
|
||||
|
||||
if(dialog->exec() == QDialog::Accepted)
|
||||
{
|
||||
_ui->doubleSpinBox_openniFx->setValue(dialog->fx());
|
||||
_ui->doubleSpinBox_openniFy->setValue(dialog->fy());
|
||||
_ui->doubleSpinBox_openniCx->setValue(dialog->cx());
|
||||
_ui->doubleSpinBox_openniCy->setValue(dialog->cy());
|
||||
}
|
||||
|
||||
cameraThread.join(true);
|
||||
delete dialog;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -222,7 +222,7 @@ p, li { white-space: pre-wrap; }
|
||||
<item>
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Copyright (C) 2011 IntRoLab - Université de Sherbrooke</string>
|
||||
<string>Copyright (C) 2010-2014 IntRoLab - Université de Sherbrooke</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>629</width>
|
||||
<height>452</height>
|
||||
<width>1040</width>
|
||||
<height>745</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@@ -33,84 +33,158 @@
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Count</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QProgressBar" name="progressBar_count">
|
||||
<property name="value">
|
||||
<number>24</number>
|
||||
</property>
|
||||
<property name="format">
|
||||
<string>%p</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>X</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QProgressBar" name="progressBar_x">
|
||||
<property name="value">
|
||||
<number>24</number>
|
||||
</property>
|
||||
<property name="format">
|
||||
<string>%p%</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Y</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QProgressBar" name="progressBar_y">
|
||||
<property name="value">
|
||||
<number>24</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Size</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QProgressBar" name="progressBar_size">
|
||||
<property name="value">
|
||||
<number>24</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Skew</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QProgressBar" name="progressBar_skew">
|
||||
<property name="value">
|
||||
<number>24</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Chessboard</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout_3">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_12">
|
||||
<property name="toolTip">
|
||||
<string>Number of inner squares on the board</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Board width</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QSpinBox" name="spinBox_boardWidth">
|
||||
<property name="minimum">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>8</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_15">
|
||||
<property name="toolTip">
|
||||
<string>Number of inner squares on the board</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Board height</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QSpinBox" name="spinBox_boardHeight">
|
||||
<property name="minimum">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>6</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_16">
|
||||
<property name="text">
|
||||
<string>Square size (m)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QDoubleSpinBox" name="doubleSpinBox_squareSize">
|
||||
<property name="decimals">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>0.033000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_2">
|
||||
<property name="title">
|
||||
<string>Progress</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Count</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QProgressBar" name="progressBar_count">
|
||||
<property name="value">
|
||||
<number>24</number>
|
||||
</property>
|
||||
<property name="format">
|
||||
<string>%p</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>X</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QProgressBar" name="progressBar_x">
|
||||
<property name="value">
|
||||
<number>24</number>
|
||||
</property>
|
||||
<property name="format">
|
||||
<string>%p%</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Y</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QProgressBar" name="progressBar_y">
|
||||
<property name="value">
|
||||
<number>24</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Size</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QProgressBar" name="progressBar_size">
|
||||
<property name="value">
|
||||
<number>24</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Skew</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QProgressBar" name="progressBar_skew">
|
||||
<property name="value">
|
||||
<number>24</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_calibrate">
|
||||
@@ -120,134 +194,139 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout_2">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="text">
|
||||
<string>fx</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="label_fx">
|
||||
<property name="text">
|
||||
<string>0</string>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_9">
|
||||
<property name="text">
|
||||
<string>fy</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="label_fy">
|
||||
<property name="text">
|
||||
<string>0</string>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_10">
|
||||
<property name="text">
|
||||
<string>cx</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLabel" name="label_cx">
|
||||
<property name="text">
|
||||
<string>0</string>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_11">
|
||||
<property name="text">
|
||||
<string>cy</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLabel" name="label_cy">
|
||||
<property name="text">
|
||||
<string>0</string>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="toolTip">
|
||||
<string>Camera matrix</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>K</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QLineEdit" name="lineEdit_K">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="toolTip">
|
||||
<string>Distorsion coefficients</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>D</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QLineEdit" name="lineEdit_D">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="0">
|
||||
<widget class="QLabel" name="label_13">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="label_14">
|
||||
<property name="toolTip">
|
||||
<string>Avg. reproduction error</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Error</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QLabel" name="label_error">
|
||||
<property name="text">
|
||||
<string>0</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
<widget class="QGroupBox" name="groupBox_3">
|
||||
<property name="title">
|
||||
<string>Camera intrinsic parameters</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout_2">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="text">
|
||||
<string>fx</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="label_fx">
|
||||
<property name="text">
|
||||
<string>0</string>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_9">
|
||||
<property name="text">
|
||||
<string>fy</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="label_fy">
|
||||
<property name="text">
|
||||
<string>0</string>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_10">
|
||||
<property name="text">
|
||||
<string>cx</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLabel" name="label_cx">
|
||||
<property name="text">
|
||||
<string>0</string>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_11">
|
||||
<property name="text">
|
||||
<string>cy</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLabel" name="label_cy">
|
||||
<property name="text">
|
||||
<string>0</string>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="toolTip">
|
||||
<string>Camera matrix</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>K</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QLineEdit" name="lineEdit_K">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="toolTip">
|
||||
<string>Distorsion coefficients</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>D</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QLineEdit" name="lineEdit_D">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="label_14">
|
||||
<property name="toolTip">
|
||||
<string>Avg. reproduction error</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Error</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QLabel" name="label_error">
|
||||
<property name="text">
|
||||
<string>0</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0" colspan="2">
|
||||
<widget class="QLabel" name="label_13">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
@@ -258,13 +337,6 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_save">
|
||||
<property name="text">
|
||||
<string>Save</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
@@ -285,28 +357,11 @@
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_exit">
|
||||
<property name="text">
|
||||
<string>Exit</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1007</width>
|
||||
<width>1035</width>
|
||||
<height>628</height>
|
||||
</rect>
|
||||
</property>
|
||||
@@ -63,9 +63,9 @@
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>709</width>
|
||||
<height>853</height>
|
||||
<y>-617</y>
|
||||
<width>732</width>
|
||||
<height>1198</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_16">
|
||||
@@ -86,7 +86,7 @@
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>1</number>
|
||||
<number>3</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="page_22">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_29">
|
||||
@@ -1763,25 +1763,97 @@ when using the file type, logs are saved in LogRtabmap.txt (located in the worki
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QDoubleSpinBox" name="doubleSpinBox_openniFocal">
|
||||
<property name="maximum">
|
||||
<double>1000.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLabel" name="label_160">
|
||||
<property name="text">
|
||||
<string>Intrinsic focal length (fx=fy, K[4]). Set 0 to use the default from the camera. Examples: ~525 for Kinect, ~545 for Xtion Pro Live.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_3">
|
||||
<property name="title">
|
||||
<string>Calibration</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_41">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_160">
|
||||
<property name="text">
|
||||
<string>Camera intrinsic parameters. While the default values are good, a calibration is recommended to increase the precision of the 3D clouds. Set values to 0 to use the default parameters from the camera. For example, the focal length is ~525 for Kinect and ~545 for Xtion Pro Live. The button "Calibrate" below can be used to calibrate the camera with a chessboard pattern.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout_21">
|
||||
<property name="fieldGrowthPolicy">
|
||||
<enum>QFormLayout::ExpandingFieldsGrow</enum>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QDoubleSpinBox" name="doubleSpinBox_openniFx">
|
||||
<property name="maximum">
|
||||
<double>1000.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="label_161">
|
||||
<property name="text">
|
||||
<string>fx=K[0]</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QDoubleSpinBox" name="doubleSpinBox_openniFy">
|
||||
<property name="maximum">
|
||||
<double>1000.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="label_162">
|
||||
<property name="text">
|
||||
<string>fy=K[4]</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QDoubleSpinBox" name="doubleSpinBox_openniCx">
|
||||
<property name="maximum">
|
||||
<double>1000.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLabel" name="label_166">
|
||||
<property name="text">
|
||||
<string>cx=K[2]</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QDoubleSpinBox" name="doubleSpinBox_openniCy">
|
||||
<property name="maximum">
|
||||
<double>1000.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLabel" name="label_165">
|
||||
<property name="text">
|
||||
<string>cy=K[5]</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_calibrate">
|
||||
<property name="text">
|
||||
<string>Calibrate</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
|
||||
Reference in New Issue
Block a user