mirror of
https://github.com/introlab/rtabmap.git
synced 2026-09-02 01:20:25 +08:00
Added ViewPlane XY, XZ and YZ options to GraphViewer
Parameter RGBD/SavedLocalizationIgnored now called RGBD/StartAtOrigin (updated description, used only in localization mode) IcpReg: if Force4DoF, set lower covariance values for roll and pitch DbViewer: updated detectMoreLoopClosures with new minRadius option and update optimized poses between each new accepted loop closures. MainWindow: suppressed warning if depth image is not found in current node data (when rgb is). 3D Map view: changed default map point size to 1 (was 2)
This commit is contained in:
@@ -428,6 +428,7 @@ DatabaseViewer::DatabaseViewer(const QString & ini, QWidget * parent) :
|
||||
connect(ui_->checkBox_icp_from_depth, SIGNAL(stateChanged(int)), this, SLOT(configModified()));
|
||||
|
||||
connect(ui_->doubleSpinBox_detectMore_radius, SIGNAL(valueChanged(double)), this, SLOT(configModified()));
|
||||
connect(ui_->doubleSpinBox_detectMore_radiusMin, SIGNAL(valueChanged(double)), this, SLOT(configModified()));
|
||||
connect(ui_->doubleSpinBox_detectMore_angle, SIGNAL(valueChanged(double)), this, SLOT(configModified()));
|
||||
connect(ui_->spinBox_detectMore_iterations, SIGNAL(valueChanged(int)), this, SLOT(configModified()));
|
||||
connect(ui_->checkBox_detectMore_intraSession, SIGNAL(stateChanged(int)), this, SLOT(configModified()));
|
||||
@@ -588,6 +589,7 @@ void DatabaseViewer::readSettings()
|
||||
exportDialog_->loadSettings(settings, exportDialog_->objectName());
|
||||
settings.beginGroup("PostProcessingDialog");
|
||||
ui_->doubleSpinBox_detectMore_radius->setValue(settings.value("cluster_radius", ui_->doubleSpinBox_detectMore_radius->value()).toDouble());
|
||||
ui_->doubleSpinBox_detectMore_radiusMin->setValue(settings.value("cluster_radius_min", ui_->doubleSpinBox_detectMore_radiusMin->value()).toDouble());
|
||||
ui_->doubleSpinBox_detectMore_angle->setValue(settings.value("cluster_angle", ui_->doubleSpinBox_detectMore_angle->value()).toDouble());
|
||||
ui_->spinBox_detectMore_iterations->setValue(settings.value("iterations", ui_->spinBox_detectMore_iterations->value()).toInt());
|
||||
ui_->checkBox_detectMore_intraSession->setChecked(settings.value("intra_session", ui_->checkBox_detectMore_intraSession->isChecked()).toBool());
|
||||
@@ -674,6 +676,7 @@ void DatabaseViewer::writeSettings()
|
||||
exportDialog_->saveSettings(settings, exportDialog_->objectName());
|
||||
settings.beginGroup("PostProcessingDialog");
|
||||
settings.setValue("cluster_radius", ui_->doubleSpinBox_detectMore_radius->value());
|
||||
settings.setValue("cluster_radius_min", ui_->doubleSpinBox_detectMore_radiusMin->value());
|
||||
settings.setValue("cluster_angle", ui_->doubleSpinBox_detectMore_angle->value());
|
||||
settings.setValue("iterations", ui_->spinBox_detectMore_iterations->value());
|
||||
settings.setValue("intra_session", ui_->checkBox_detectMore_intraSession->isChecked());
|
||||
@@ -745,6 +748,7 @@ void DatabaseViewer::restoreDefaultSettings()
|
||||
ui_->checkBox_icp_from_depth->setChecked(false);
|
||||
|
||||
ui_->doubleSpinBox_detectMore_radius->setValue(1.0);
|
||||
ui_->doubleSpinBox_detectMore_radiusMin->setValue(0.0);
|
||||
ui_->doubleSpinBox_detectMore_angle->setValue(30.0);
|
||||
ui_->spinBox_detectMore_iterations->setValue(5);
|
||||
ui_->checkBox_detectMore_intraSession->setChecked(true);
|
||||
@@ -3910,7 +3914,7 @@ void DatabaseViewer::detectMoreLoopClosures()
|
||||
QMessageBox::warning(this, tr("Cannot generate a graph"), tr("No graph in database?!"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::map<int, Transform> optimizedPoses = graphes_.back();
|
||||
|
||||
@@ -3939,6 +3943,7 @@ void DatabaseViewer::detectMoreLoopClosures()
|
||||
if(!interSession && !intraSession)
|
||||
{
|
||||
QMessageBox::warning(this, tr("Cannot detect more loop closures"), tr("Intra and inter session parameters are disabled! Enable one or both."));
|
||||
return;
|
||||
}
|
||||
|
||||
for(int n=0; n<iterations; ++n)
|
||||
@@ -3948,7 +3953,7 @@ void DatabaseViewer::detectMoreLoopClosures()
|
||||
std::map<int, Transform>(optimizedPoses.upper_bound(0), optimizedPoses.end()),
|
||||
ui_->doubleSpinBox_detectMore_radius->value(),
|
||||
ui_->doubleSpinBox_detectMore_angle->value()*CV_PI/180.0);
|
||||
|
||||
|
||||
progressDialog->setMaximumSteps(progressDialog->maximumSteps()+(int)clusters.size());
|
||||
progressDialog->appendText(tr("Looking for more loop closures, %1 clusters found.").arg(clusters.size()));
|
||||
QApplication::processEvents();
|
||||
@@ -3980,18 +3985,26 @@ void DatabaseViewer::detectMoreLoopClosures()
|
||||
{
|
||||
if(!findActiveLink(from, to).isValid() && !containsLink(linksRemoved_, from, to) &&
|
||||
addedLinks.find(from) == addedLinks.end() &&
|
||||
addedLinks.find(to) == addedLinks.end())
|
||||
{
|
||||
addedLinks.find(to) == addedLinks.end())
|
||||
{
|
||||
// Reverify if in the bounds with the current optimized graph
|
||||
Transform delta = optimizedPoses.at(from).inverse() * optimizedPoses.at(to);
|
||||
if(delta.getNorm() < ui_->doubleSpinBox_detectMore_radius->value() &&
|
||||
if(addConstraint(from, to, true))
|
||||
{
|
||||
UINFO("Added new loop closure between %d and %d.", from, to);
|
||||
++added;
|
||||
addedLinks.insert(from);
|
||||
addedLinks.insert(to);
|
||||
delta.getNorm() >= ui_->doubleSpinBox_detectMore_radiusMin->value())
|
||||
{
|
||||
checkedLoopClosures.insert(std::make_pair(from, to));
|
||||
if(addConstraint(from, to, true))
|
||||
{
|
||||
UINFO("Added new loop closure between %d and %d.", from, to);
|
||||
++added;
|
||||
addedLinks.insert(from);
|
||||
addedLinks.insert(to);
|
||||
lastAdded.first = from;
|
||||
lastAdded.second = to;
|
||||
|
||||
lastAdded.second = to;
|
||||
|
||||
progressDialog->appendText(tr("Detected loop closure %1->%2! (%3/%4)").arg(from).arg(to).arg(i+1).arg(clusters.size()));
|
||||
QApplication::processEvents();
|
||||
|
||||
optimizedPoses = graphes_.back();
|
||||
}
|
||||
}
|
||||
@@ -4008,6 +4021,12 @@ void DatabaseViewer::detectMoreLoopClosures()
|
||||
progressDialog->appendText(tr("Iteration %1/%2: Detected %3 loop closures!").arg(n+1).arg(iterations).arg(addedLinks.size()/2));
|
||||
if(addedLinks.size() == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if(n+1<iterations)
|
||||
{
|
||||
// Re-optimize the map before doing next iterations
|
||||
this->updateGraphView();
|
||||
optimizedPoses = graphes_.back();
|
||||
}
|
||||
}
|
||||
@@ -7666,7 +7685,7 @@ bool DatabaseViewer::addConstraint(int from, int to, bool silent)
|
||||
if(!reg->isImageRequired())
|
||||
{
|
||||
// make a fake guess using globally optimized poses
|
||||
if(graphes_.size())
|
||||
if(graphes_.size())
|
||||
{
|
||||
std::map<int, Transform> optimizedPoses = graphes_.back();
|
||||
if(optimizedPoses.size() > 0)
|
||||
@@ -7877,6 +7896,11 @@ bool DatabaseViewer::addConstraint(int from, int to, bool silent)
|
||||
tr("%1").arg(msg.c_str()));
|
||||
}
|
||||
|
||||
updateConstraints = false;
|
||||
}
|
||||
|
||||
if(updateConstraints && silent && !graphes_.empty() && graphes_.back().size() == poses.size())
|
||||
{
|
||||
graphes_.back() = poses;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ class NodeItem: public QGraphicsEllipseItem
|
||||
{
|
||||
public:
|
||||
// in meter
|
||||
NodeItem(int id, int mapId, const Transform & pose, float radius, int weight=-1) :
|
||||
NodeItem(int id, int mapId, const Transform & pose, float radius, int weight, GraphViewer::ViewPlane plane) :
|
||||
QGraphicsEllipseItem(QRectF(-radius*100.0f,-radius*100.0f,radius*100.0f*2.0f,radius*100.0f*2.0f)),
|
||||
_id(id),
|
||||
_mapId(mapId),
|
||||
@@ -75,7 +75,7 @@ public:
|
||||
_pose(pose),
|
||||
_line(0)
|
||||
{
|
||||
this->setPos(-pose.y()*100.0f,-pose.x()*100.0f);
|
||||
this->setPose(pose, plane);
|
||||
this->setBrush(pen().color());
|
||||
this->setAcceptHoverEvents(true);
|
||||
float r,p,yaw;
|
||||
@@ -109,7 +109,21 @@ public:
|
||||
int id() const {return _id;};
|
||||
int mapId() const {return _mapId;}
|
||||
const Transform & pose() const {return _pose;}
|
||||
void setPose(const Transform & pose) {this->setPos(-pose.y()*100.0f,-pose.x()*100.0f); _pose=pose;}
|
||||
void setPose(const Transform & pose, GraphViewer::ViewPlane plane) {
|
||||
switch(plane)
|
||||
{
|
||||
case GraphViewer::XZ:
|
||||
this->setPos(pose.x()*100.0f,-pose.z()*100.0f);
|
||||
break;
|
||||
case GraphViewer::YZ:
|
||||
this->setPos(pose.y()*100.0f,-pose.z()*100.0f);
|
||||
break;
|
||||
default: // XY
|
||||
this->setPos(-pose.y()*100.0f,-pose.x()*100.0f);
|
||||
break;
|
||||
}
|
||||
_pose=pose;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void hoverEnterEvent ( QGraphicsSceneHoverEvent * event )
|
||||
@@ -143,8 +157,8 @@ private:
|
||||
class NodeGPSItem: public NodeItem
|
||||
{
|
||||
public:
|
||||
NodeGPSItem(int id, int mapId, const Transform & pose, float radius, const GPS & gps) :
|
||||
NodeItem(id, mapId, pose, radius),
|
||||
NodeGPSItem(int id, int mapId, const Transform & pose, float radius, const GPS & gps, GraphViewer::ViewPlane plane) :
|
||||
NodeItem(id, mapId, pose, radius, -1, plane),
|
||||
_gps(gps)
|
||||
{
|
||||
}
|
||||
@@ -167,8 +181,7 @@ class LinkItem: public QGraphicsLineItem
|
||||
{
|
||||
public:
|
||||
// in meter
|
||||
LinkItem(int from, int to, const Transform & poseA, const Transform & poseB, const Link & link, bool interSessionClosure) :
|
||||
QGraphicsLineItem(-poseA.y()*100.0f, -poseA.x()*100.0f, -poseB.y()*100.0f, -poseB.x()*100.0f),
|
||||
LinkItem(int from, int to, const Transform & poseA, const Transform & poseB, const Link & link, bool interSessionClosure, GraphViewer::ViewPlane plane) :
|
||||
_from(from),
|
||||
_to(to),
|
||||
_poseA(poseA),
|
||||
@@ -176,6 +189,7 @@ public:
|
||||
_link(link),
|
||||
_interSession(interSessionClosure)
|
||||
{
|
||||
this->setPoses(poseA, poseB, plane);
|
||||
this->setAcceptHoverEvents(true);
|
||||
}
|
||||
virtual ~LinkItem() {}
|
||||
@@ -187,9 +201,20 @@ public:
|
||||
this->setPen(p);
|
||||
}
|
||||
|
||||
void setPoses(const Transform & poseA, const Transform & poseB)
|
||||
void setPoses(const Transform & poseA, const Transform & poseB, GraphViewer::ViewPlane plane)
|
||||
{
|
||||
this->setLine(-poseA.y()*100.0f, -poseA.x()*100.0f, -poseB.y()*100.0f, -poseB.x()*100.0f);
|
||||
switch(plane)
|
||||
{
|
||||
case GraphViewer::XZ:
|
||||
this->setLine(poseA.x()*100.0f, -poseA.z()*100.0f, poseB.x()*100.0f, -poseB.z()*100.0f);
|
||||
break;
|
||||
case GraphViewer::YZ:
|
||||
this->setLine(poseA.y()*100.0f, -poseA.z()*100.0f, poseB.y()*100.0f, -poseB.z()*100.0f);
|
||||
break;
|
||||
default: // XY
|
||||
this->setLine(-poseA.y()*100.0f, -poseA.x()*100.0f, -poseB.y()*100.0f, -poseB.x()*100.0f);
|
||||
break;
|
||||
}
|
||||
_poseA = poseA;
|
||||
_poseB = poseB;
|
||||
}
|
||||
@@ -274,7 +299,8 @@ GraphViewer::GraphViewer(QWidget * parent) :
|
||||
_localRadius(0),
|
||||
_loopClosureOutlierThr(0),
|
||||
_maxLinkLength(0.02f),
|
||||
_orientationENU(false)
|
||||
_orientationENU(false),
|
||||
_viewPlane(XY)
|
||||
{
|
||||
this->setScene(new QGraphicsScene(this));
|
||||
this->setDragMode(QGraphicsView::ScrollHandDrag);
|
||||
@@ -286,30 +312,99 @@ GraphViewer::GraphViewer(QWidget * parent) :
|
||||
_root->setParentItem(_world);
|
||||
|
||||
// add referential
|
||||
QGraphicsLineItem * item;
|
||||
_originReferential = new QGraphicsItemGroup();
|
||||
this->scene()->addItem(_originReferential); // ownership transfered
|
||||
QGraphicsLineItem * item = this->scene()->addLine(0,0,0,-100, QPen(QBrush(Qt::red), _linkWidth));
|
||||
|
||||
// XY referential
|
||||
_originReferentialXY = new QGraphicsItemGroup();
|
||||
this->scene()->addItem(_originReferentialXY); // ownership transfered
|
||||
item = this->scene()->addLine(0,0,0,-100, QPen(QBrush(Qt::red), _linkWidth));
|
||||
item->setZValue(1);
|
||||
item->setParentItem(_root);
|
||||
_originReferential->addToGroup(item);
|
||||
_originReferentialXY->addToGroup(item);
|
||||
item = this->scene()->addLine(0,0,-100,0, QPen(QBrush(Qt::green), _linkWidth));
|
||||
item->setZValue(1);
|
||||
item->setParentItem(_root);
|
||||
_originReferential->addToGroup(item);
|
||||
_originReferentialXY->addToGroup(item);
|
||||
_originReferential->addToGroup(_originReferentialXY);
|
||||
|
||||
// XZ referential
|
||||
_originReferentialXZ = new QGraphicsItemGroup();
|
||||
this->scene()->addItem(_originReferentialXZ); // ownership transfered
|
||||
item = this->scene()->addLine(0,0,100,0, QPen(QBrush(Qt::red), _linkWidth));
|
||||
item->setZValue(1);
|
||||
item->setParentItem(_root);
|
||||
_originReferentialXZ->addToGroup(item);
|
||||
item = this->scene()->addLine(0,0,0,-100, QPen(QBrush(Qt::blue), _linkWidth));
|
||||
item->setZValue(1);
|
||||
item->setParentItem(_root);
|
||||
_originReferentialXZ->addToGroup(item);
|
||||
_originReferential->addToGroup(_originReferentialXZ);
|
||||
_originReferentialXZ->setVisible(false);
|
||||
|
||||
// YZ referential
|
||||
_originReferentialYZ = new QGraphicsItemGroup();
|
||||
this->scene()->addItem(_originReferentialYZ); // ownership transfered
|
||||
item = this->scene()->addLine(0,0,100,0, QPen(QBrush(Qt::green), _linkWidth));
|
||||
item->setZValue(1);
|
||||
item->setParentItem(_root);
|
||||
_originReferentialYZ->addToGroup(item);
|
||||
item = this->scene()->addLine(0,0,0,-100, QPen(QBrush(Qt::blue), _linkWidth));
|
||||
item->setZValue(1);
|
||||
item->setParentItem(_root);
|
||||
_originReferentialYZ->addToGroup(item);
|
||||
_originReferential->addToGroup(_originReferentialYZ);
|
||||
_originReferentialYZ->setVisible(false);
|
||||
|
||||
_originReferential->setZValue(1);
|
||||
_originReferential->setParentItem(_root);
|
||||
|
||||
// current pose
|
||||
_referential = new QGraphicsItemGroup();
|
||||
this->scene()->addItem(_referential); // ownership transfered
|
||||
|
||||
// XY
|
||||
_referentialXY = new QGraphicsItemGroup();
|
||||
this->scene()->addItem(_referentialXY); // ownership transfered
|
||||
item = this->scene()->addLine(0,0,0,-50, QPen(QBrush(Qt::red), _linkWidth));
|
||||
item->setZValue(100);
|
||||
item->setParentItem(_root);
|
||||
_referential->addToGroup(item);
|
||||
_referentialXY->addToGroup(item);
|
||||
item = this->scene()->addLine(0,0,-50,0, QPen(QBrush(Qt::green), _linkWidth));
|
||||
item->setZValue(100);
|
||||
item->setParentItem(_root);
|
||||
_referential->addToGroup(item);
|
||||
_referentialXY->addToGroup(item);
|
||||
_referential->addToGroup(_referentialXY);
|
||||
|
||||
// XZ
|
||||
_referentialXZ = new QGraphicsItemGroup();
|
||||
this->scene()->addItem(_referentialXZ); // ownership transfered
|
||||
item = this->scene()->addLine(0,0,50,0, QPen(QBrush(Qt::red), _linkWidth));
|
||||
item->setZValue(100);
|
||||
item->setParentItem(_root);
|
||||
_referentialXZ->addToGroup(item);
|
||||
item = this->scene()->addLine(0,0,0,-50, QPen(QBrush(Qt::blue), _linkWidth));
|
||||
item->setZValue(100);
|
||||
item->setParentItem(_root);
|
||||
_referentialXZ->addToGroup(item);
|
||||
_referential->addToGroup(_referentialXZ);
|
||||
_referentialXZ->setVisible(false);
|
||||
|
||||
// XZ
|
||||
_referentialYZ = new QGraphicsItemGroup();
|
||||
this->scene()->addItem(_referentialYZ); // ownership transfered
|
||||
item = this->scene()->addLine(0,0,50,0, QPen(QBrush(Qt::green), _linkWidth));
|
||||
item->setZValue(100);
|
||||
item->setParentItem(_root);
|
||||
_referentialYZ->addToGroup(item);
|
||||
item = this->scene()->addLine(0,0,0,-50, QPen(QBrush(Qt::blue), _linkWidth));
|
||||
item->setZValue(100);
|
||||
item->setParentItem(_root);
|
||||
_referentialYZ->addToGroup(item);
|
||||
_referential->addToGroup(_referentialYZ);
|
||||
_referentialYZ->setVisible(false);
|
||||
|
||||
_referential->setZValue(100);
|
||||
_referential->setParentItem(_root);
|
||||
|
||||
@@ -388,14 +483,14 @@ void GraphViewer::updateGraph(const std::map<int, Transform> & poses,
|
||||
QMap<int, NodeItem*>::iterator itemIter = _nodeItems.find(iter->first);
|
||||
if(itemIter != _nodeItems.end())
|
||||
{
|
||||
itemIter.value()->setPose(iter->second);
|
||||
itemIter.value()->setPose(iter->second, _viewPlane);
|
||||
itemIter.value()->show();
|
||||
}
|
||||
else
|
||||
{
|
||||
// create node item
|
||||
const Transform & pose = iter->second;
|
||||
NodeItem * item = new NodeItem(iter->first, uContains(mapIds, iter->first)?mapIds.at(iter->first):-1, pose, _nodeRadius, uContains(weights, iter->first)?weights.at(iter->first):-1);
|
||||
NodeItem * item = new NodeItem(iter->first, uContains(mapIds, iter->first)?mapIds.at(iter->first):-1, pose, _nodeRadius, uContains(weights, iter->first)?weights.at(iter->first):-1, _viewPlane);
|
||||
this->scene()->addItem(item);
|
||||
item->setZValue(iter->first<0?21:20);
|
||||
item->setColor(iter->first<0?QColor(255-_nodeColor.red(), 255-_nodeColor.green(), 255-_nodeColor.blue()):_nodeColor);
|
||||
@@ -429,7 +524,7 @@ void GraphViewer::updateGraph(const std::map<int, Transform> & poses,
|
||||
{
|
||||
if(itemIter.value()->to() == idTo)
|
||||
{
|
||||
itemIter.value()->setPoses(poseA, poseB);
|
||||
itemIter.value()->setPoses(poseA, poseB, _viewPlane);
|
||||
itemIter.value()->show();
|
||||
linkItem = itemIter.value();
|
||||
break;
|
||||
@@ -449,7 +544,7 @@ void GraphViewer::updateGraph(const std::map<int, Transform> & poses,
|
||||
if(linkItem == 0)
|
||||
{
|
||||
//create a link item
|
||||
linkItem = new LinkItem(idFrom, idTo, poseA, poseB, iter->second, interSessionClosure);
|
||||
linkItem = new LinkItem(idFrom, idTo, poseA, poseB, iter->second, interSessionClosure, _viewPlane);
|
||||
QPen p = linkItem->pen();
|
||||
p.setWidthF(_linkWidth*100.0f);
|
||||
linkItem->setPen(p);
|
||||
@@ -608,14 +703,14 @@ void GraphViewer::updateGTGraph(const std::map<int, Transform> & poses)
|
||||
QMap<int, NodeItem*>::iterator itemIter = _gtNodeItems.find(iter->first);
|
||||
if(itemIter != _gtNodeItems.end())
|
||||
{
|
||||
itemIter.value()->setPose(iter->second);
|
||||
itemIter.value()->setPose(iter->second, _viewPlane);
|
||||
itemIter.value()->show();
|
||||
}
|
||||
else
|
||||
{
|
||||
// create node item
|
||||
const Transform & pose = iter->second;
|
||||
NodeItem * item = new NodeItem(iter->first, -1, pose, _nodeRadius);
|
||||
NodeItem * item = new NodeItem(iter->first, -1, pose, _nodeRadius, -1, _viewPlane);
|
||||
this->scene()->addItem(item);
|
||||
item->setZValue(20);
|
||||
item->setColor(_gtPathColor);
|
||||
@@ -640,7 +735,7 @@ void GraphViewer::updateGTGraph(const std::map<int, Transform> & poses)
|
||||
{
|
||||
if(linkIter.value()->to() == iter->first)
|
||||
{
|
||||
linkIter.value()->setPoses(previousPose, currentPose);
|
||||
linkIter.value()->setPoses(previousPose, currentPose, _viewPlane);
|
||||
linkIter.value()->show();
|
||||
linkItem = linkIter.value();
|
||||
break;
|
||||
@@ -651,7 +746,7 @@ void GraphViewer::updateGTGraph(const std::map<int, Transform> & poses)
|
||||
if(linkItem == 0)
|
||||
{
|
||||
//create a link item
|
||||
linkItem = new LinkItem(iterPrevious->first, iter->first, previousPose, currentPose, Link(), 1);
|
||||
linkItem = new LinkItem(iterPrevious->first, iter->first, previousPose, currentPose, Link(), 1, _viewPlane);
|
||||
QPen p = linkItem->pen();
|
||||
p.setWidthF(_linkWidth*100.0f);
|
||||
linkItem->setPen(p);
|
||||
@@ -737,7 +832,7 @@ void GraphViewer::updateGPSGraph(
|
||||
QMap<int, NodeItem*>::iterator itemIter = _gpsNodeItems.find(iter->first);
|
||||
if(itemIter != _gpsNodeItems.end())
|
||||
{
|
||||
itemIter.value()->setPose(iter->second);
|
||||
itemIter.value()->setPose(iter->second, _viewPlane);
|
||||
itemIter.value()->show();
|
||||
}
|
||||
else
|
||||
@@ -745,7 +840,7 @@ void GraphViewer::updateGPSGraph(
|
||||
// create node item
|
||||
const Transform & pose = iter->second;
|
||||
UASSERT(gpsValues.find(iter->first) != gpsValues.end());
|
||||
NodeItem * item = new NodeGPSItem(iter->first, -1, pose, _nodeRadius, gpsValues.at(iter->first));
|
||||
NodeItem * item = new NodeGPSItem(iter->first, -1, pose, _nodeRadius, gpsValues.at(iter->first), _viewPlane);
|
||||
this->scene()->addItem(item);
|
||||
item->setZValue(20);
|
||||
item->setColor(_gpsPathColor);
|
||||
@@ -770,7 +865,7 @@ void GraphViewer::updateGPSGraph(
|
||||
{
|
||||
if(linkIter.value()->to() == iter->first)
|
||||
{
|
||||
linkIter.value()->setPoses(previousPose, currentPose);
|
||||
linkIter.value()->setPoses(previousPose, currentPose, _viewPlane);
|
||||
linkIter.value()->show();
|
||||
linkItem = linkIter.value();
|
||||
break;
|
||||
@@ -781,7 +876,7 @@ void GraphViewer::updateGPSGraph(
|
||||
if(linkItem == 0)
|
||||
{
|
||||
//create a link item
|
||||
linkItem = new LinkItem(iterPrevious->first, iter->first, previousPose, currentPose, Link(), 1);
|
||||
linkItem = new LinkItem(iterPrevious->first, iter->first, previousPose, currentPose, Link(), 1, _viewPlane);
|
||||
QPen p = linkItem->pen();
|
||||
p.setWidthF(_linkWidth*100.0f);
|
||||
linkItem->setPen(p);
|
||||
@@ -844,7 +939,8 @@ void GraphViewer::updateReferentialPosition(const Transform & t)
|
||||
{
|
||||
QTransform qt;
|
||||
qt.translate(-t.o24()*100.0f, -t.o14()*100.0f);
|
||||
qt.rotateRadians(-t.theta());
|
||||
if(_viewPlane == XY)
|
||||
qt.rotateRadians(-t.theta());
|
||||
|
||||
_referential->setTransform(qt);
|
||||
_localRadius->setTransform(qt);
|
||||
@@ -921,7 +1017,7 @@ void GraphViewer::setGlobalPath(const std::vector<std::pair<int, Transform> > &
|
||||
//create a link item
|
||||
int idFrom = globalPath[i].first;
|
||||
int idTo = globalPath[i+1].first;
|
||||
LinkItem * item = new LinkItem(idFrom, idTo, globalPath[i].second, globalPath[i+1].second, Link(), false);
|
||||
LinkItem * item = new LinkItem(idFrom, idTo, globalPath[i].second, globalPath[i+1].second, Link(), false, _viewPlane);
|
||||
QPen p = item->pen();
|
||||
p.setWidthF(_linkWidth*100.0f);
|
||||
item->setPen(p);
|
||||
@@ -953,7 +1049,7 @@ void GraphViewer::setCurrentGoalID(int id, const Transform & pose)
|
||||
Transform t = pose * oldPose->getPoseA().inverse();
|
||||
for(QMultiMap<int, LinkItem*>::iterator iter=_globalPathLinkItems.begin(); iter!=_globalPathLinkItems.end(); ++iter)
|
||||
{
|
||||
iter.value()->setPoses(t*iter.value()->getPoseA(), t*iter.value()->getPoseB());
|
||||
iter.value()->setPoses(t*iter.value()->getPoseA(), t*iter.value()->getPoseB(), _viewPlane);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -989,7 +1085,7 @@ void GraphViewer::updateLocalPath(const std::vector<int> & localPath)
|
||||
{
|
||||
if(itemIter.value()->to() == idTo)
|
||||
{
|
||||
itemIter.value()->setPoses(_nodeItems.value(idFrom)->pose(), _nodeItems.value(idTo)->pose());
|
||||
itemIter.value()->setPoses(_nodeItems.value(idFrom)->pose(), _nodeItems.value(idTo)->pose(), _viewPlane);
|
||||
itemIter.value()->show();
|
||||
updated = true;
|
||||
break;
|
||||
@@ -1000,7 +1096,7 @@ void GraphViewer::updateLocalPath(const std::vector<int> & localPath)
|
||||
if(!updated)
|
||||
{
|
||||
//create a link item
|
||||
LinkItem * item = new LinkItem(idFrom, idTo, _nodeItems.value(idFrom)->pose(), _nodeItems.value(idTo)->pose(), Link(), false);
|
||||
LinkItem * item = new LinkItem(idFrom, idTo, _nodeItems.value(idFrom)->pose(), _nodeItems.value(idTo)->pose(), Link(), false, _viewPlane);
|
||||
QPen p = item->pen();
|
||||
p.setWidthF(_linkWidth*100.0f);
|
||||
item->setPen(p);
|
||||
@@ -1113,6 +1209,7 @@ void GraphViewer::saveSettings(QSettings & settings, const QString & group) cons
|
||||
settings.setValue("gt_graph_visible", this->isGtGraphVisible());
|
||||
settings.setValue("gps_graph_visible", this->isGPSGraphVisible());
|
||||
settings.setValue("orientation_ENU", this->isOrientationENU());
|
||||
settings.setValue("view_plane", (int)this->getViewPlane());
|
||||
if(!group.isEmpty())
|
||||
{
|
||||
settings.endGroup();
|
||||
@@ -1155,6 +1252,7 @@ void GraphViewer::loadSettings(QSettings & settings, const QString & group)
|
||||
this->setGtGraphVisible(settings.value("gt_graph_visible", this->isGtGraphVisible()).toBool());
|
||||
this->setGPSGraphVisible(settings.value("gps_graph_visible", this->isGPSGraphVisible()).toBool());
|
||||
this->setOrientationENU(settings.value("orientation_ENU", this->isOrientationENU()).toBool());
|
||||
this->setViewPlane((ViewPlane)settings.value("view_plane", (int)this->getViewPlane()).toInt());
|
||||
if(!group.isEmpty())
|
||||
{
|
||||
settings.endGroup();
|
||||
@@ -1201,6 +1299,10 @@ bool GraphViewer::isOrientationENU() const
|
||||
{
|
||||
return _orientationENU;
|
||||
}
|
||||
GraphViewer::ViewPlane GraphViewer::getViewPlane() const
|
||||
{
|
||||
return _viewPlane;
|
||||
}
|
||||
|
||||
void GraphViewer::setWorkingDirectory(const QString & path)
|
||||
{
|
||||
@@ -1441,7 +1543,11 @@ void GraphViewer::setIntraInterSessionColorsEnabled(bool enabled)
|
||||
|
||||
void GraphViewer::setGridMapVisible(bool visible)
|
||||
{
|
||||
_gridMap->setVisible(visible);
|
||||
if(visible && _viewPlane!=XY)
|
||||
{
|
||||
UWARN("Grid map can be shown only with view plane is XY.");
|
||||
}
|
||||
_gridMap->setVisible(_viewPlane==XY && visible);
|
||||
}
|
||||
void GraphViewer::setOriginVisible(bool visible)
|
||||
{
|
||||
@@ -1485,6 +1591,11 @@ void GraphViewer::setGPSGraphVisible(bool visible)
|
||||
}
|
||||
void GraphViewer::setOrientationENU(bool enabled)
|
||||
{
|
||||
if(enabled && _viewPlane!=XY)
|
||||
{
|
||||
UWARN("ENU orientation can be set only with view plane is XY.");
|
||||
}
|
||||
enabled = _viewPlane==XY && enabled;
|
||||
if(_orientationENU!=enabled)
|
||||
{
|
||||
_orientationENU = enabled;
|
||||
@@ -1506,6 +1617,37 @@ void GraphViewer::setOrientationENU(bool enabled)
|
||||
}
|
||||
}
|
||||
|
||||
void GraphViewer::setViewPlane(ViewPlane plane)
|
||||
{
|
||||
if(plane != XY)
|
||||
{
|
||||
setOrientationENU(false);
|
||||
setGridMapVisible(false);
|
||||
}
|
||||
_viewPlane = plane;
|
||||
|
||||
for(QMap<int, NodeItem*>::iterator iter=_nodeItems.begin(); iter!=_nodeItems.end(); ++iter)
|
||||
{
|
||||
iter.value()->setPose(iter.value()->pose(), _viewPlane);
|
||||
}
|
||||
for(QMultiMap<int, LinkItem*>::iterator iter=_linkItems.begin(); iter!=_linkItems.end(); ++iter)
|
||||
{
|
||||
iter.value()->setPoses(iter.value()->getPoseA(), iter.value()->getPoseB(), _viewPlane);
|
||||
}
|
||||
|
||||
_originReferentialXY->setVisible(plane==XY);
|
||||
_originReferentialXZ->setVisible(plane==XZ);
|
||||
_originReferentialYZ->setVisible(plane==YZ);
|
||||
_referentialXY->setVisible(plane==XY);
|
||||
_referentialXZ->setVisible(plane==XZ);
|
||||
_referentialYZ->setVisible(plane==YZ);
|
||||
|
||||
if(_nodeItems.size() || _linkItems.size())
|
||||
{
|
||||
this->scene()->setSceneRect(this->scene()->itemsBoundingRect()); // Re-shrink the scene to it's bounding contents
|
||||
}
|
||||
}
|
||||
|
||||
void GraphViewer::restoreDefaults()
|
||||
{
|
||||
setNodeRadius(0.01f);
|
||||
@@ -1620,6 +1762,9 @@ void GraphViewer::contextMenuEvent(QContextMenuEvent * event)
|
||||
QAction * aShowHideGtGraph;
|
||||
QAction * aShowHideGPSGraph;
|
||||
QAction * aOrientationENU;
|
||||
QAction * aViewPlaneXY;
|
||||
QAction * aViewPlaneXZ;
|
||||
QAction * aViewPlaneYZ;
|
||||
if(_gridMap->isVisible())
|
||||
{
|
||||
aShowHideGridMap = menu.addAction(tr("Hide grid map"));
|
||||
@@ -1628,6 +1773,7 @@ void GraphViewer::contextMenuEvent(QContextMenuEvent * event)
|
||||
{
|
||||
aShowHideGridMap = menu.addAction(tr("Show grid map"));
|
||||
}
|
||||
aShowHideGridMap->setEnabled(_viewPlane == XY);
|
||||
if(_originReferential->isVisible())
|
||||
{
|
||||
aShowHideOrigin = menu.addAction(tr("Hide origin referential"));
|
||||
@@ -1703,12 +1849,24 @@ void GraphViewer::contextMenuEvent(QContextMenuEvent * event)
|
||||
aOrientationENU = menu.addAction(tr("ENU Orientation"));
|
||||
aOrientationENU->setCheckable(true);
|
||||
aOrientationENU->setChecked(_orientationENU);
|
||||
aShowHideGraph->setEnabled(_nodeItems.size());
|
||||
aShowHideGraph->setEnabled(_nodeItems.size() && _viewPlane == XY);
|
||||
aShowHideGraphNodes->setEnabled(_nodeItems.size() && _graphRoot->isVisible());
|
||||
aShowHideGlobalPath->setEnabled(_globalPathLinkItems.size());
|
||||
aShowHideLocalPath->setEnabled(_localPathLinkItems.size());
|
||||
aShowHideGtGraph->setEnabled(_gtNodeItems.size());
|
||||
aShowHideGPSGraph->setEnabled(_gpsNodeItems.size());
|
||||
|
||||
QMenu * viewPlaneMenu = menu.addMenu("View Plane...");
|
||||
aViewPlaneXY = viewPlaneMenu->addAction("XY");
|
||||
aViewPlaneXY->setCheckable(true);
|
||||
aViewPlaneXY->setChecked(_viewPlane == XY);
|
||||
aViewPlaneXZ = viewPlaneMenu->addAction("XZ");
|
||||
aViewPlaneXZ->setCheckable(true);
|
||||
aViewPlaneXZ->setChecked(_viewPlane == XZ);
|
||||
aViewPlaneYZ = viewPlaneMenu->addAction("YZ");
|
||||
aViewPlaneYZ->setCheckable(true);
|
||||
aViewPlaneYZ->setChecked(_viewPlane == YZ);
|
||||
|
||||
menu.addSeparator();
|
||||
QAction * aRestoreDefaults = menu.addAction(tr("Restore defaults"));
|
||||
|
||||
@@ -2060,6 +2218,18 @@ void GraphViewer::contextMenuEvent(QContextMenuEvent * event)
|
||||
{
|
||||
this->setOrientationENU(!this->isOrientationENU());
|
||||
}
|
||||
else if(r == aViewPlaneXY)
|
||||
{
|
||||
this->setViewPlane(XY);
|
||||
}
|
||||
else if(r == aViewPlaneXZ)
|
||||
{
|
||||
this->setViewPlane(XZ);
|
||||
}
|
||||
else if(r == aViewPlaneYZ)
|
||||
{
|
||||
this->setViewPlane(YZ);
|
||||
}
|
||||
|
||||
if(r)
|
||||
{
|
||||
|
||||
@@ -1806,7 +1806,7 @@ void MainWindow::processStats(const rtabmap::Statistics & stat)
|
||||
LaserScan tmpScan;
|
||||
signature.sensorData().uncompressData(
|
||||
uncompressImages?&tmpRgb:0,
|
||||
uncompressImages?&tmpDepth:0,
|
||||
uncompressImages && !signature.sensorData().depthOrRightCompressed().empty()?&tmpDepth:0,
|
||||
uncompressScan?&tmpScan:0,
|
||||
0, &tmpG, &tmpO, &tmpE);
|
||||
|
||||
|
||||
@@ -1056,7 +1056,7 @@ PreferencesDialog::PreferencesDialog(QWidget * parent) :
|
||||
_ui->rgdb_angularUpdate->setObjectName(Parameters::kRGBDAngularUpdate().c_str());
|
||||
_ui->rgdb_linearSpeedUpdate->setObjectName(Parameters::kRGBDLinearSpeedUpdate().c_str());
|
||||
_ui->rgdb_angularSpeedUpdate->setObjectName(Parameters::kRGBDAngularSpeedUpdate().c_str());
|
||||
_ui->rgbd_savedLocalizationIgnored->setObjectName(Parameters::kRGBDSavedLocalizationIgnored().c_str());
|
||||
_ui->rgbd_savedLocalizationIgnored->setObjectName(Parameters::kRGBDStartAtOrigin().c_str());
|
||||
_ui->rgdb_rehearsalWeightIgnoredWhileMoving->setObjectName(Parameters::kMemRehearsalWeightIgnoredWhileMoving().c_str());
|
||||
_ui->rgdb_newMapOdomChange->setObjectName(Parameters::kRGBDNewMapOdomChangeDistance().c_str());
|
||||
_ui->odomScanHistory->setObjectName(Parameters::kRGBDNeighborLinkRefining().c_str());
|
||||
@@ -1781,10 +1781,10 @@ void PreferencesDialog::resetSettings(QGroupBox * groupBox)
|
||||
_3dRenderingVoxelSizeScan[i]->setValue(0.0);
|
||||
_3dRenderingColorScheme[i]->setValue(0);
|
||||
_3dRenderingOpacity[i]->setValue(i==0?1.0:0.75);
|
||||
_3dRenderingPtSize[i]->setValue(2);
|
||||
_3dRenderingPtSize[i]->setValue(i==0?1:2);
|
||||
_3dRenderingColorSchemeScan[i]->setValue(0);
|
||||
_3dRenderingOpacityScan[i]->setValue(i==0?1.0:0.5);
|
||||
_3dRenderingPtSizeScan[i]->setValue(2);
|
||||
_3dRenderingPtSizeScan[i]->setValue(i==0?1:2);
|
||||
_3dRenderingPtSizeFeatures[i]->setValue(3);
|
||||
_3dRenderingGravity[i]->setChecked(false);
|
||||
_3dRenderingGravityLength[i]->setValue(1);
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>311</width>
|
||||
<width>422</width>
|
||||
<height>311</height>
|
||||
</rect>
|
||||
</property>
|
||||
@@ -304,7 +304,7 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>311</width>
|
||||
<width>421</width>
|
||||
<height>311</height>
|
||||
</rect>
|
||||
</property>
|
||||
@@ -1379,7 +1379,7 @@
|
||||
<item>
|
||||
<widget class="QToolBox" name="toolBox">
|
||||
<property name="currentIndex">
|
||||
<number>1</number>
|
||||
<number>2</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="page_3">
|
||||
<property name="geometry">
|
||||
@@ -1541,7 +1541,7 @@
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>-330</y>
|
||||
<y>0</y>
|
||||
<width>519</width>
|
||||
<height>871</height>
|
||||
</rect>
|
||||
@@ -2116,15 +2116,15 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>226</width>
|
||||
<height>160</height>
|
||||
<width>312</width>
|
||||
<height>243</height>
|
||||
</rect>
|
||||
</property>
|
||||
<attribute name="label">
|
||||
<string>Detect more loop closures</string>
|
||||
</attribute>
|
||||
<layout class="QGridLayout" name="gridLayout_10" columnstretch="0,1">
|
||||
<item row="3" column="1">
|
||||
<item row="4" column="1">
|
||||
<widget class="QLabel" name="label_32">
|
||||
<property name="text">
|
||||
<string>Intra-session</string>
|
||||
@@ -2153,11 +2153,11 @@
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="label_29">
|
||||
<property name="text">
|
||||
<string>Radius</string>
|
||||
<string>Radius Max</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<item row="2" column="0">
|
||||
<widget class="QDoubleSpinBox" name="doubleSpinBox_detectMore_angle">
|
||||
<property name="suffix">
|
||||
<string> degrees</string>
|
||||
@@ -2176,14 +2176,14 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<item row="2" column="1">
|
||||
<widget class="QLabel" name="label_30">
|
||||
<property name="text">
|
||||
<string>Angle</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<item row="3" column="0">
|
||||
<widget class="QSpinBox" name="spinBox_detectMore_iterations">
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
@@ -2196,14 +2196,14 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<item row="3" column="1">
|
||||
<widget class="QLabel" name="label_31">
|
||||
<property name="text">
|
||||
<string>Iterations</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<item row="6" column="0">
|
||||
<spacer name="verticalSpacer_5">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
@@ -2216,27 +2216,53 @@
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<item row="5" column="1">
|
||||
<widget class="QLabel" name="label_34">
|
||||
<property name="text">
|
||||
<string>Inter-session</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<item row="4" column="0">
|
||||
<widget class="QCheckBox" name="checkBox_detectMore_intraSession">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<item row="5" column="0">
|
||||
<widget class="QCheckBox" name="checkBox_detectMore_interSession">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="label_36">
|
||||
<property name="text">
|
||||
<string>Radius Min</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QDoubleSpinBox" name="doubleSpinBox_detectMore_radiusMin">
|
||||
<property name="suffix">
|
||||
<string> m</string>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>10.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.100000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>0.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="page_2">
|
||||
|
||||
@@ -63,7 +63,7 @@
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>-2259</y>
|
||||
<y>0</y>
|
||||
<width>686</width>
|
||||
<height>3414</height>
|
||||
</rect>
|
||||
@@ -95,7 +95,7 @@
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>5</number>
|
||||
<number>12</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="page_22">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_29" stretch="0,1">
|
||||
@@ -11004,7 +11004,7 @@ If set to false, classic RTAB-Map loop closure detection is done using only imag
|
||||
<item row="4" column="1">
|
||||
<widget class="QLabel" name="label_scanMatching_2">
|
||||
<property name="text">
|
||||
<string>Ignore last saved localization pose from previous session. If true, RTAB-Map won't assume it is restarting from the same place than where it shut down previously. In localization mode, the robot will assume that it is starting from the origin of the map.</string>
|
||||
<string>If true, rtabmap will assume the robot is restarting from origin of the map. If false, rtabmap will assume the robot is restarting from the last saved localization pose from previous session (the place where it shut down previously). Used only in localization mode.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
|
||||
Reference in New Issue
Block a user