CloudViewer: Added local transformation between base frame and camera frame (when they are not the same)

This commit is contained in:
matlabbe
2016-05-17 16:32:21 -04:00
parent 2db6b2ceef
commit 0ae131108d
4 changed files with 125 additions and 26 deletions
+11 -1
View File
@@ -142,7 +142,8 @@ public:
void removeOccupancyGridMap(); void removeOccupancyGridMap();
void updateCameraTargetPosition( void updateCameraTargetPosition(
const Transform & pose); const Transform & pose,
const Transform & localTransform = Transform::getIdentity());
void addOrUpdateCoordinate( void addOrUpdateCoordinate(
const std::string & id, const std::string & id,
@@ -154,6 +155,14 @@ public:
void removeCoordinate(const std::string & id); void removeCoordinate(const std::string & id);
void removeAllCoordinates(); void removeAllCoordinates();
void addOrUpdateArrow(
const std::string & id,
const Transform & from,
const Transform & to,
const QColor & color);
void removeArrow(const std::string & id);
void removeAllArrows();
void addOrUpdateFrustum( void addOrUpdateFrustum(
const std::string & id, const std::string & id,
const Transform & transform, const Transform & transform,
@@ -282,6 +291,7 @@ private:
std::set<std::string> _graphes; std::set<std::string> _graphes;
std::set<std::string> _coordinates; std::set<std::string> _coordinates;
std::set<std::string> _texts; std::set<std::string> _texts;
std::set<std::string> _arrows;
std::set<std::string> _frustums; std::set<std::string> _frustums;
pcl::PointCloud<pcl::PointXYZ>::Ptr _trajectory; pcl::PointCloud<pcl::PointXYZ>::Ptr _trajectory;
unsigned int _maxTrajectorySize; unsigned int _maxTrajectorySize;
-1
View File
@@ -229,7 +229,6 @@ private:
void update3DMapVisibility(bool cloudsShown, bool scansShown); void update3DMapVisibility(bool cloudsShown, bool scansShown);
void updateMapCloud( void updateMapCloud(
const std::map<int, Transform> & poses, const std::map<int, Transform> & poses,
const Transform & pose,
const std::multimap<int, Link> & constraints, const std::multimap<int, Link> & constraints,
const std::map<int, int> & mapIds, const std::map<int, int> & mapIds,
const std::map<int, std::string> & labels, const std::map<int, std::string> & labels,
+75 -3
View File
@@ -172,6 +172,7 @@ void CloudViewer::clear()
this->removeAllClouds(); this->removeAllClouds();
this->removeAllGraphs(); this->removeAllGraphs();
this->removeAllCoordinates(); this->removeAllCoordinates();
this->removeAllArrows();
this->removeAllFrustums(); this->removeAllFrustums();
this->removeAllTexts(); this->removeAllTexts();
this->clearTrajectory(); this->clearTrajectory();
@@ -792,6 +793,62 @@ void CloudViewer::removeAllCoordinates()
UASSERT(_coordinates.empty()); UASSERT(_coordinates.empty());
} }
void CloudViewer::addOrUpdateArrow(
const std::string & id,
const Transform & from,
const Transform & to,
const QColor & color)
{
if(id.empty())
{
UERROR("id should not be empty!");
return;
}
removeArrow(id);
if(!from.isNull() && !to.isNull())
{
_arrows.insert(id);
QColor c = Qt::gray;
if(color.isValid())
{
c = color;
}
pcl::PointXYZ pt1(from.x(), from.y(), from.z());
pcl::PointXYZ pt2(to.x(), to.y(), to.z());
_visualizer->addArrow(pt2, pt1, c.redF(), c.greenF(), c.blueF(), false, id);
}
}
void CloudViewer::removeArrow(const std::string & id)
{
if(id.empty())
{
UERROR("id should not be empty!");
return;
}
if(_arrows.find(id) != _arrows.end())
{
_visualizer->removeShape(id);
_arrows.erase(id);
}
}
void CloudViewer::removeAllArrows()
{
std::set<std::string> arrows = _arrows;
for(std::set<std::string>::iterator iter = arrows.begin(); iter!=arrows.end(); ++iter)
{
this->removeArrow(*iter);
}
UASSERT(_arrows.empty());
}
static const float frustum_vertices[] = { static const float frustum_vertices[] = {
0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
@@ -1055,6 +1112,7 @@ void CloudViewer::setFrustumShown(bool shown)
if(!shown) if(!shown)
{ {
this->removeFrustum("reference_frustum"); this->removeFrustum("reference_frustum");
this->removeArrow("reference_frustum_arrow");
this->update(); this->update();
} }
_aShowFrustum->setChecked(shown); _aShowFrustum->setChecked(shown);
@@ -1074,8 +1132,12 @@ void CloudViewer::setFrustumColor(QColor value)
if(_frustums.find("reference_frustum") != _frustums.end()) if(_frustums.find("reference_frustum") != _frustums.end())
{ {
_visualizer->setShapeRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, value.redF(), value.greenF(), value.blueF(), "reference_frustum"); _visualizer->setShapeRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, value.redF(), value.greenF(), value.blueF(), "reference_frustum");
this->update();
} }
if(_arrows.find("reference_frustum_arrow") != _arrows.end())
{
_visualizer->setShapeRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, value.redF(), value.greenF(), value.blueF(), "reference_frustum_arrow");
}
this->update();
_frustumColor = value; _frustumColor = value;
} }
@@ -1189,7 +1251,7 @@ void CloudViewer::setCameraPosition(
_visualizer->setCameraPosition(x,y,z, focalX,focalY,focalX, upX,upY,upZ); _visualizer->setCameraPosition(x,y,z, focalX,focalY,focalX, upX,upY,upZ);
} }
void CloudViewer::updateCameraTargetPosition(const Transform & pose) void CloudViewer::updateCameraTargetPosition(const Transform & pose, const Transform & localTransform)
{ {
if(!pose.isNull()) if(!pose.isNull())
{ {
@@ -1305,7 +1367,17 @@ void CloudViewer::updateCameraTargetPosition(const Transform & pose)
} }
else */ if(_aShowFrustum->isChecked()) else */ if(_aShowFrustum->isChecked())
{ {
this->addOrUpdateFrustum("reference_frustum", pose, _frustumScale, _frustumColor); Transform baseToCamera = Transform::getIdentity();
Transform opticalRot(0, 0, 1, 0, -1, 0, 0, 0, 0, -1, 0, 0);
if(!localTransform.isNull() && !localTransform.isIdentity())
{
baseToCamera = localTransform*opticalRot.inverse();
}
this->addOrUpdateFrustum("reference_frustum", pose * baseToCamera, _frustumScale, _frustumColor);
if(!baseToCamera.isIdentity())
{
this->addOrUpdateArrow("reference_frustum_arrow", pose, pose * baseToCamera, _frustumColor);
}
} }
vtkRenderer* renderer = _visualizer->getRendererCollection()->GetFirstRenderer(); vtkRenderer* renderer = _visualizer->getRendererCollection()->GetFirstRenderer();
+39 -21
View File
@@ -775,6 +775,8 @@ void MainWindow::handleEvent(UEvent* anEvent)
{ {
// we receive too many odometry events! just send without data // we receive too many odometry events! just send without data
SensorData data(cv::Mat(), odomEvent->data().id(), odomEvent->data().stamp()); SensorData data(cv::Mat(), odomEvent->data().id(), odomEvent->data().stamp());
data.setCameraModels(odomEvent->data().cameraModels());
data.setStereoCameraModel(odomEvent->data().stereoCameraModel());
data.setGroundTruth(odomEvent->data().groundTruth()); data.setGroundTruth(odomEvent->data().groundTruth());
OdometryEvent tmp(data, odomEvent->pose(), odomEvent->covariance(), odomEvent->info().copyWithoutData()); OdometryEvent tmp(data, odomEvent->pose(), odomEvent->covariance(), odomEvent->info().copyWithoutData());
emit odometryReceived(tmp); emit odometryReceived(tmp);
@@ -1036,7 +1038,17 @@ void MainWindow::processOdometry(const rtabmap::OdometryEvent & odom)
if(!odom.pose().isNull()) if(!odom.pose().isNull())
{ {
// update camera position // update camera position
_cloudViewer->updateCameraTargetPosition(_odometryCorrection*odom.pose()); Transform localTransform;
if(odom.data().cameraModels().size() && !odom.data().cameraModels()[0].localTransform().isNull())
{
localTransform = odom.data().cameraModels()[0].localTransform();
}
else if(!odom.data().stereoCameraModel().localTransform().isNull())
{
localTransform = odom.data().stereoCameraModel().localTransform();
}
_cloudViewer->updateCameraTargetPosition(_odometryCorrection*odom.pose(), localTransform);
} }
_cloudViewer->update(); _cloudViewer->update();
@@ -1527,9 +1539,30 @@ void MainWindow::processStats(const rtabmap::Statistics & stat)
Transform groundTruthOffset = alignPosesToGroundTruth(poses, groundTruth); Transform groundTruthOffset = alignPosesToGroundTruth(poses, groundTruth);
UDEBUG("time= %d ms", time.restart()); UDEBUG("time= %d ms", time.restart());
if(!_odometryReceived && poses.size())
{
Transform localTransform = Transform::getIdentity();
std::map<int, Signature>::const_iterator iter = stat.getSignatures().find(poses.rbegin()->first);
if(iter != stat.getSignatures().end())
{
if(iter->second.sensorData().cameraModels().size() && !iter->second.sensorData().cameraModels()[0].localTransform().isNull())
{
localTransform = iter->second.sensorData().cameraModels()[0].localTransform();
}
else if(!iter->second.sensorData().stereoCameraModel().localTransform().isNull())
{
localTransform = iter->second.sensorData().stereoCameraModel().localTransform();
}
}
_cloudViewer->updateCameraTargetPosition(poses.rbegin()->second, localTransform);
if(_ui->graphicsView_graphView->isVisible())
{
_ui->graphicsView_graphView->updateReferentialPosition(poses.rbegin()->second);
}
}
updateMapCloud( updateMapCloud(
poses, poses,
_odometryReceived||poses.size()==0?Transform():poses.rbegin()->second,
stat.constraints(), stat.constraints(),
mapIds, mapIds,
labels, labels,
@@ -1725,15 +1758,14 @@ void MainWindow::processStats(const rtabmap::Statistics & stat)
void MainWindow::updateMapCloud( void MainWindow::updateMapCloud(
const std::map<int, Transform> & posesIn, const std::map<int, Transform> & posesIn,
const Transform & currentPose,
const std::multimap<int, Link> & constraints, const std::multimap<int, Link> & constraints,
const std::map<int, int> & mapIdsIn, const std::map<int, int> & mapIdsIn,
const std::map<int, std::string> & labels, const std::map<int, std::string> & labels,
const std::map<int, Transform> & groundTruths, // ground truth should contain only valid transforms const std::map<int, Transform> & groundTruths, // ground truth should contain only valid transforms
bool verboseProgress) bool verboseProgress)
{ {
UDEBUG("posesIn=%d constraints=%d mapIdsIn=%d labelsIn=%d currentPose=%s", UDEBUG("posesIn=%d constraints=%d mapIdsIn=%d labelsIn=%d",
(int)posesIn.size(), (int)constraints.size(), (int)mapIdsIn.size(), (int)labels.size(), currentPose.prettyPrint().c_str()); (int)posesIn.size(), (int)constraints.size(), (int)mapIdsIn.size(), (int)labels.size());
if(posesIn.size()) if(posesIn.size())
{ {
_currentPosesMap = posesIn; _currentPosesMap = posesIn;
@@ -1810,7 +1842,7 @@ void MainWindow::updateMapCloud(
} }
// Map updated! regenerate the assembled cloud, last pose is the new one // Map updated! regenerate the assembled cloud, last pose is the new one
UDEBUG("Update map with %d locations (currentPose=%s)", poses.size(), currentPose.prettyPrint().c_str()); UDEBUG("Update map with %d locations", poses.size());
QMap<std::string, Transform> viewerClouds = _cloudViewer->getAddedClouds(); QMap<std::string, Transform> viewerClouds = _cloudViewer->getAddedClouds();
int i=1; int i=1;
for(std::map<int, Transform>::const_iterator iter = poses.begin(); iter!=poses.end(); ++iter) for(std::map<int, Transform>::const_iterator iter = poses.begin(); iter!=poses.end(); ++iter)
@@ -2040,11 +2072,6 @@ void MainWindow::updateMapCloud(
if(_ui->graphicsView_graphView->isVisible()) if(_ui->graphicsView_graphView->isVisible())
{ {
_ui->graphicsView_graphView->updateGraph(posesIn, constraints, mapIdsIn); _ui->graphicsView_graphView->updateGraph(posesIn, constraints, mapIdsIn);
if(!currentPose.isNull())
{
_ui->graphicsView_graphView->updateReferentialPosition(currentPose);
}
_ui->graphicsView_graphView->updateGTGraph(_currentGTPosesMap); _ui->graphicsView_graphView->updateGTGraph(_currentGTPosesMap);
} }
cv::Mat map8U; cv::Mat map8U;
@@ -2147,12 +2174,6 @@ void MainWindow::updateMapCloud(
} }
} }
if(!currentPose.isNull())
{
UDEBUG("");
_cloudViewer->updateCameraTargetPosition(currentPose);
}
UDEBUG(""); UDEBUG("");
_cloudViewer->update(); _cloudViewer->update();
UDEBUG(""); UDEBUG("");
@@ -2813,7 +2834,7 @@ void MainWindow::processRtabmapEvent3DMap(const rtabmap::RtabmapEvent3DMap & eve
QApplication::processEvents(); QApplication::processEvents();
std::map<int, Transform> poses = event.getPoses(); std::map<int, Transform> poses = event.getPoses();
alignPosesToGroundTruth(poses, groundTruth); alignPosesToGroundTruth(poses, groundTruth);
this->updateMapCloud(poses, Transform(), event.getConstraints(), mapIds, labels, groundTruth, true); this->updateMapCloud(poses, event.getConstraints(), mapIds, labels, groundTruth, true);
_initProgressDialog->appendText("Updating the 3D map cloud... done."); _initProgressDialog->appendText("Updating the 3D map cloud... done.");
} }
else else
@@ -2957,7 +2978,6 @@ void MainWindow::applyPrefSettings(PreferencesDialog::PANEL_FLAGS flags)
{ {
this->updateMapCloud( this->updateMapCloud(
std::map<int, Transform>(_currentPosesMap), std::map<int, Transform>(_currentPosesMap),
Transform(),
std::multimap<int, Link>(_currentLinksMap), std::multimap<int, Link>(_currentLinksMap),
std::map<int, int>(_currentMapIds), std::map<int, int>(_currentMapIds),
std::map<int, std::string>(_currentLabels), std::map<int, std::string>(_currentLabels),
@@ -4289,7 +4309,6 @@ void MainWindow::postProcessing()
alignPosesToGroundTruth(optimizedPoses, _currentGTPosesMap); alignPosesToGroundTruth(optimizedPoses, _currentGTPosesMap);
this->updateMapCloud( this->updateMapCloud(
optimizedPoses, optimizedPoses,
Transform(),
std::multimap<int, Link>(_currentLinksMap), std::multimap<int, Link>(_currentLinksMap),
std::map<int, int>(_currentMapIds), std::map<int, int>(_currentMapIds),
std::map<int, std::string>(_currentLabels), std::map<int, std::string>(_currentLabels),
@@ -4652,7 +4671,6 @@ void MainWindow::anchorCloudsToGroundTruth()
{ {
this->updateMapCloud( this->updateMapCloud(
std::map<int, Transform>(_currentPosesMap), std::map<int, Transform>(_currentPosesMap),
Transform(),
std::multimap<int, Link>(_currentLinksMap), std::multimap<int, Link>(_currentLinksMap),
std::map<int, int>(_currentMapIds), std::map<int, int>(_currentMapIds),
std::map<int, std::string>(_currentLabels), std::map<int, std::string>(_currentLabels),