mirror of
https://github.com/introlab/rtabmap_ros.git
synced 2026-10-04 00:37:46 +08:00
Tango: Added ICP refining option, mesh vs texture vs point cloud options, show/hide grid option, drift correction option
This commit is contained in:
@@ -37,7 +37,7 @@ namespace rtabmap {
|
|||||||
|
|
||||||
#define nullptr 0
|
#define nullptr 0
|
||||||
const int kVersionStringLength = 128;
|
const int kVersionStringLength = 128;
|
||||||
const int holeSize = 10;
|
const int holeSize = 1;
|
||||||
const float maxDepthError = 0.10;
|
const float maxDepthError = 0.10;
|
||||||
|
|
||||||
// Callbacks
|
// Callbacks
|
||||||
@@ -558,6 +558,8 @@ SensorData CameraTango::captureImage(CameraInfo * info)
|
|||||||
poseDepth.setNull();
|
poseDepth.setNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int scanDownsampling = 10;
|
||||||
|
cv::Mat scan;
|
||||||
if(!poseDepth.isNull() && !poseColor.isNull())
|
if(!poseDepth.isNull() && !poseColor.isNull())
|
||||||
{
|
{
|
||||||
// The Color Camera frame at timestamp t0 with respect to Depth
|
// The Color Camera frame at timestamp t0 with respect to Depth
|
||||||
@@ -568,11 +570,18 @@ SensorData CameraTango::captureImage(CameraInfo * info)
|
|||||||
int pixelsSet = 0;
|
int pixelsSet = 0;
|
||||||
depth = cv::Mat::zeros(model_.imageHeight()/8, model_.imageWidth()/8, CV_16UC1); // mm
|
depth = cv::Mat::zeros(model_.imageHeight()/8, model_.imageWidth()/8, CV_16UC1); // mm
|
||||||
CameraModel depthModel = model_.scaled(1.0f/8.0f);
|
CameraModel depthModel = model_.scaled(1.0f/8.0f);
|
||||||
|
std::vector<cv::Point3f> scanData(cloud.total());
|
||||||
|
int oi=0;
|
||||||
for(unsigned int i=0; i<cloud.total(); ++i)
|
for(unsigned int i=0; i<cloud.total(); ++i)
|
||||||
{
|
{
|
||||||
cv::Vec3f & p = cloud.at<cv::Vec3f>(i);
|
float * p = cloud.ptr<float>(0,i);
|
||||||
cv::Point3f pt = util3d::transformPoint(cv::Point3f(p[0], p[1], p[2]), colorToDepth);
|
cv::Point3f pt = util3d::transformPoint(cv::Point3f(p[0], p[1], p[2]), colorToDepth);
|
||||||
|
|
||||||
|
if(pt.z > 0.0f && i%scanDownsampling == 0)
|
||||||
|
{
|
||||||
|
scanData.at(oi++) = pt;
|
||||||
|
}
|
||||||
|
|
||||||
int pixel_x, pixel_y;
|
int pixel_x, pixel_y;
|
||||||
// get the coordinate on image plane.
|
// get the coordinate on image plane.
|
||||||
pixel_x = static_cast<int>((depthModel.fx()) * (pt.x / pt.z) + depthModel.cx());
|
pixel_x = static_cast<int>((depthModel.fx()) * (pt.x / pt.z) + depthModel.cx());
|
||||||
@@ -591,6 +600,10 @@ SensorData CameraTango::captureImage(CameraInfo * info)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(oi)
|
||||||
|
{
|
||||||
|
scan = cv::Mat(1, oi, CV_32FC3, scanData.data()).clone();
|
||||||
|
}
|
||||||
LOGI("pixels depth set= %d", pixelsSet);
|
LOGI("pixels depth set= %d", pixelsSet);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -607,7 +620,7 @@ SensorData CameraTango::captureImage(CameraInfo * info)
|
|||||||
//Rotate in RTAB-Map's coordinate
|
//Rotate in RTAB-Map's coordinate
|
||||||
Transform odom = rtabmap_world_T_opengl_world * poseColorOpenGL * depth_camera_T_opengl_camera * model.localTransform().inverse();
|
Transform odom = rtabmap_world_T_opengl_world * poseColorOpenGL * depth_camera_T_opengl_camera * model.localTransform().inverse();
|
||||||
|
|
||||||
data = SensorData(rgb, depth, model, this->getNextSeqID(), rgbStamp);
|
data = SensorData(scan, LaserScanInfo(cloud.total()/scanDownsampling, 0, model.localTransform()), rgb, depth, model, this->getNextSeqID(), rgbStamp);
|
||||||
data.setGroundTruth(odom);
|
data.setGroundTruth(odom);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -76,13 +76,23 @@ rtabmap::ParametersMap RTABMapApp::getRtabmapParameters()
|
|||||||
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kMemNotLinkedNodesKept(), std::string("false")));
|
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kMemNotLinkedNodesKept(), std::string("false")));
|
||||||
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kOptimizerIterations(), graphOptimization_?"10":"0"));
|
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kOptimizerIterations(), graphOptimization_?"10":"0"));
|
||||||
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kMemIncrementalMemory(), uBool2Str(!localizationMode_)));
|
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kMemIncrementalMemory(), uBool2Str(!localizationMode_)));
|
||||||
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kRtabmapMaxRetrieved(), uBool2Str(!localizationMode_)));
|
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kRtabmapMaxRetrieved(), "1"));
|
||||||
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kKpMaxDepth(), std::string("10"))); // to avoid extracting features in invalid depth (as we compute transformation directly from the words)
|
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kKpMaxDepth(), std::string("10"))); // to avoid extracting features in invalid depth (as we compute transformation directly from the words)
|
||||||
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kRGBDOptimizeFromGraphEnd(), std::string("true")));
|
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kRGBDOptimizeFromGraphEnd(), std::string("true")));
|
||||||
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kDbSqlite3InMemory(), std::string("true")));
|
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kDbSqlite3InMemory(), std::string("true")));
|
||||||
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kVisMinInliers(), std::string("15")));
|
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kVisMinInliers(), std::string("15")));
|
||||||
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kVisEstimationType(), std::string("0"))); // 0=3D-3D 1=PnP
|
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kVisEstimationType(), std::string("0"))); // 0=3D-3D 1=PnP
|
||||||
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kRGBDOptimizeMaxError(), std::string("0.05")));
|
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kRGBDOptimizeMaxError(), std::string("0.05")));
|
||||||
|
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kRGBDProximityPathMaxNeighbors(), std::string("0"))); // disable scan matching to merged nodes
|
||||||
|
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kRGBDProximityBySpace(), std::string("false"))); // just keep loop closure detection
|
||||||
|
|
||||||
|
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kRGBDNeighborLinkRefining(), uBool2Str(driftCorrection_)));
|
||||||
|
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kRegStrategy(), std::string(driftCorrection_?"1":"0")));
|
||||||
|
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kIcpPointToPlane(), std::string("false")));
|
||||||
|
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kIcpPointToPlaneNormalNeighbors(), std::string("6")));
|
||||||
|
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kIcpIterations(), std::string("10")));
|
||||||
|
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kIcpEpsilon(), std::string("0.001")));
|
||||||
|
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kIcpMaxCorrespondenceDistance(), std::string("0.05")));
|
||||||
|
|
||||||
return parameters;
|
return parameters;
|
||||||
}
|
}
|
||||||
@@ -95,13 +105,14 @@ RTABMapApp::RTABMapApp() :
|
|||||||
odomCloudShown_(true),
|
odomCloudShown_(true),
|
||||||
graphOptimization_(true),
|
graphOptimization_(true),
|
||||||
nodesFiltering_(false),
|
nodesFiltering_(false),
|
||||||
|
driftCorrection_(false),
|
||||||
localizationMode_(false),
|
localizationMode_(false),
|
||||||
trajectoryMode_(false),
|
trajectoryMode_(false),
|
||||||
autoExposure_(false),
|
autoExposure_(false),
|
||||||
fullResolution_(false),
|
fullResolution_(false),
|
||||||
maxCloudDepth_(0.0),
|
maxCloudDepth_(0.0),
|
||||||
meshTrianglePix_(1),
|
meshTrianglePix_(1),
|
||||||
meshAngleToleranceDeg_(10.0),
|
meshAngleToleranceDeg_(15.0),
|
||||||
clearSceneOnNextRender_(false),
|
clearSceneOnNextRender_(false),
|
||||||
totalPoints_(0),
|
totalPoints_(0),
|
||||||
totalPolygons_(0),
|
totalPolygons_(0),
|
||||||
@@ -109,7 +120,6 @@ RTABMapApp::RTABMapApp() :
|
|||||||
renderingFPS_(0.0f)
|
renderingFPS_(0.0f)
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RTABMapApp::~RTABMapApp() {
|
RTABMapApp::~RTABMapApp() {
|
||||||
@@ -422,7 +432,7 @@ int RTABMapApp::Render()
|
|||||||
pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud;
|
pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud;
|
||||||
pcl::IndicesPtr indices(new std::vector<int>);
|
pcl::IndicesPtr indices(new std::vector<int>);
|
||||||
LOGI("Creating node cloud %d (image size=%dx%d)", id, data.imageRaw().cols, data.imageRaw().rows);
|
LOGI("Creating node cloud %d (image size=%dx%d)", id, data.imageRaw().cols, data.imageRaw().rows);
|
||||||
cloud = rtabmap::util3d::cloudRGBFromSensorData(data, data.imageRaw().rows/data.depthRaw().rows, maxCloudDepth_, 0, indices.get());
|
cloud = rtabmap::util3d::cloudRGBFromSensorData(data, 1, maxCloudDepth_, 0, indices.get());
|
||||||
|
|
||||||
if(cloud->size() && indices->size())
|
if(cloud->size() && indices->size())
|
||||||
{
|
{
|
||||||
@@ -525,7 +535,7 @@ int RTABMapApp::Render()
|
|||||||
if(!event.data().imageRaw().empty() && !event.data().depthRaw().empty())
|
if(!event.data().imageRaw().empty() && !event.data().depthRaw().empty())
|
||||||
{
|
{
|
||||||
pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud;
|
pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud;
|
||||||
cloud = rtabmap::util3d::cloudRGBFromSensorData(event.data(), event.data().imageRaw().rows/event.data().depthRaw().rows, maxCloudDepth_);
|
cloud = rtabmap::util3d::cloudRGBFromSensorData(event.data(), 1, maxCloudDepth_);
|
||||||
if(cloud->size())
|
if(cloud->size())
|
||||||
{
|
{
|
||||||
LOGI("Created odom cloud (rgb=%dx%d depth=%dx%d cloud=%dx%d)",
|
LOGI("Created odom cloud (rgb=%dx%d depth=%dx%d cloud=%dx%d)",
|
||||||
@@ -599,9 +609,9 @@ void RTABMapApp::setOdomCloudShown(bool shown)
|
|||||||
odomCloudShown_ = shown;
|
odomCloudShown_ = shown;
|
||||||
main_scene_.setTraceVisible(shown);
|
main_scene_.setTraceVisible(shown);
|
||||||
}
|
}
|
||||||
void RTABMapApp::setMeshRendering(bool enabled)
|
void RTABMapApp::setMeshRendering(bool enabled, bool withTexture)
|
||||||
{
|
{
|
||||||
main_scene_.setMeshRendering(enabled);
|
main_scene_.setMeshRendering(enabled, withTexture);
|
||||||
}
|
}
|
||||||
void RTABMapApp::setLocalizationMode(bool enabled)
|
void RTABMapApp::setLocalizationMode(bool enabled)
|
||||||
{
|
{
|
||||||
@@ -643,9 +653,22 @@ void RTABMapApp::setNodesFiltering(bool enabled)
|
|||||||
nodesFiltering_ = enabled;
|
nodesFiltering_ = enabled;
|
||||||
setGraphOptimization(graphOptimization_); // this will resend the graph if paused
|
setGraphOptimization(graphOptimization_); // this will resend the graph if paused
|
||||||
}
|
}
|
||||||
|
void RTABMapApp::setDriftCorrection(bool enabled)
|
||||||
|
{
|
||||||
|
driftCorrection_ = enabled;
|
||||||
|
rtabmap::ParametersMap parameters;
|
||||||
|
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kRGBDNeighborLinkRefining(), uBool2Str(driftCorrection_)));
|
||||||
|
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kRegStrategy(), std::string(driftCorrection_?"1":"0")));
|
||||||
|
this->post(new rtabmap::ParamEvent(parameters));
|
||||||
|
}
|
||||||
void RTABMapApp::setGraphVisible(bool visible)
|
void RTABMapApp::setGraphVisible(bool visible)
|
||||||
{
|
{
|
||||||
main_scene_.setGraphVisible(visible);
|
main_scene_.setGraphVisible(visible);
|
||||||
|
main_scene_.setTraceVisible(visible);
|
||||||
|
}
|
||||||
|
void RTABMapApp::setGridVisible(bool visible)
|
||||||
|
{
|
||||||
|
main_scene_.setGridVisible(visible);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RTABMapApp::setAutoExposure(bool enabled)
|
void RTABMapApp::setAutoExposure(bool enabled)
|
||||||
@@ -907,49 +930,64 @@ bool RTABMapApp::exportMesh(const std::string & filePath)
|
|||||||
|
|
||||||
int RTABMapApp::postProcessing(int approach)
|
int RTABMapApp::postProcessing(int approach)
|
||||||
{
|
{
|
||||||
|
LOGI("postProcessing(%d)", approach);
|
||||||
int returnedValue = 0;
|
int returnedValue = 0;
|
||||||
if(rtabmap_)
|
if(rtabmap_)
|
||||||
{
|
{
|
||||||
std::map<int, rtabmap::Transform> poses;
|
std::map<int, rtabmap::Transform> poses;
|
||||||
std::multimap<int, rtabmap::Link> links;
|
std::multimap<int, rtabmap::Link> links;
|
||||||
if(approach == 2 || approach == 0)
|
|
||||||
{
|
|
||||||
if(approach == 2)
|
|
||||||
{
|
|
||||||
// detect more loop closures
|
|
||||||
returnedValue = rtabmap_->detectMoreLoopClosures();
|
|
||||||
}
|
|
||||||
|
|
||||||
if(returnedValue >= 0)
|
// detect more loop closures
|
||||||
|
if(approach == -1 || approach == 2)
|
||||||
|
{
|
||||||
|
// detect more loop closures
|
||||||
|
returnedValue = rtabmap_->detectMoreLoopClosures(0.5f, M_PI/6.0f, approach == -1?3:1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ICP refining
|
||||||
|
if(returnedValue >=0 && ((approach == -1 && !driftCorrection_) || approach == 3))
|
||||||
|
{
|
||||||
|
rtabmap::ParametersMap parameters;
|
||||||
|
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kRegStrategy(), std::string("1"))); // ICP
|
||||||
|
rtabmap_->parseParameters(parameters);
|
||||||
|
int r = rtabmap_->refineLinks();
|
||||||
|
if(approach == 3 )
|
||||||
|
{
|
||||||
|
returnedValue = r;
|
||||||
|
}
|
||||||
|
// reset back default registration (visual)
|
||||||
|
uInsert(parameters, rtabmap::ParametersPair(rtabmap::Parameters::kRegStrategy(), std::string(driftCorrection_?"1":"0"))); // Visual
|
||||||
|
rtabmap_->parseParameters(parameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
// graph optimization
|
||||||
|
if(returnedValue >=0)
|
||||||
|
{
|
||||||
|
if (approach == 1)
|
||||||
|
{
|
||||||
|
if(rtabmap::Optimizer::isAvailable(rtabmap::Optimizer::kTypeG2O))
|
||||||
|
{
|
||||||
|
std::map<int, rtabmap::Signature> signatures;
|
||||||
|
rtabmap_->getGraph(poses, links, false, true, &signatures);
|
||||||
|
|
||||||
|
rtabmap::ParametersMap param;
|
||||||
|
param.insert(rtabmap::ParametersPair(rtabmap::Parameters::kOptimizerIterations(), "30"));
|
||||||
|
param.insert(rtabmap::ParametersPair(rtabmap::Parameters::kOptimizerEpsilon(), "0"));
|
||||||
|
rtabmap::Optimizer * sba = rtabmap::Optimizer::create(rtabmap::Optimizer::kTypeG2O, param);
|
||||||
|
poses = sba->optimizeBA(poses.rbegin()->first, poses, links, signatures);
|
||||||
|
delete sba;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOGE("g2o not available!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
// simple graph optmimization
|
// simple graph optmimization
|
||||||
rtabmap_->getGraph(poses, links, true, true);
|
rtabmap_->getGraph(poses, links, true, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (approach == 1)
|
|
||||||
{
|
|
||||||
if(rtabmap::Optimizer::isAvailable(rtabmap::Optimizer::kTypeG2O))
|
|
||||||
{
|
|
||||||
std::map<int, rtabmap::Signature> signatures;
|
|
||||||
rtabmap_->getGraph(poses, links, false, true, &signatures);
|
|
||||||
|
|
||||||
rtabmap::ParametersMap param;
|
|
||||||
param.insert(rtabmap::ParametersPair(rtabmap::Parameters::kOptimizerIterations(), "30"));
|
|
||||||
param.insert(rtabmap::ParametersPair(rtabmap::Parameters::kOptimizerEpsilon(), "0"));
|
|
||||||
rtabmap::Optimizer * sba = rtabmap::Optimizer::create(rtabmap::Optimizer::kTypeG2O, param);
|
|
||||||
poses = sba->optimizeBA(poses.rbegin()->first, poses, links, signatures);
|
|
||||||
delete sba;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LOGE("g2o not available!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LOGE("Invalid approach %d (should be 0 (graph optimization), 1 (sba) or 2 (detect more loop closures))", approach);
|
|
||||||
returnedValue = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(poses.size())
|
if(poses.size())
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -112,12 +112,14 @@ class RTABMapApp : public UEventsHandler {
|
|||||||
void setPausedMapping(bool paused);
|
void setPausedMapping(bool paused);
|
||||||
void setMapCloudShown(bool shown);
|
void setMapCloudShown(bool shown);
|
||||||
void setOdomCloudShown(bool shown);
|
void setOdomCloudShown(bool shown);
|
||||||
void setMeshRendering(bool enabled);
|
void setMeshRendering(bool enabled, bool withTexture);
|
||||||
void setLocalizationMode(bool enabled);
|
void setLocalizationMode(bool enabled);
|
||||||
void setTrajectoryMode(bool enabled);
|
void setTrajectoryMode(bool enabled);
|
||||||
void setGraphOptimization(bool enabled);
|
void setGraphOptimization(bool enabled);
|
||||||
void setNodesFiltering(bool enabled);
|
void setNodesFiltering(bool enabled);
|
||||||
|
void setDriftCorrection(bool enabled);
|
||||||
void setGraphVisible(bool visible);
|
void setGraphVisible(bool visible);
|
||||||
|
void setGridVisible(bool visible);
|
||||||
void setAutoExposure(bool enabled);
|
void setAutoExposure(bool enabled);
|
||||||
void setFullResolution(bool enabled);
|
void setFullResolution(bool enabled);
|
||||||
void setMaxCloudDepth(float value);
|
void setMaxCloudDepth(float value);
|
||||||
@@ -145,6 +147,7 @@ class RTABMapApp : public UEventsHandler {
|
|||||||
bool odomCloudShown_;
|
bool odomCloudShown_;
|
||||||
bool graphOptimization_;
|
bool graphOptimization_;
|
||||||
bool nodesFiltering_;
|
bool nodesFiltering_;
|
||||||
|
bool driftCorrection_;
|
||||||
bool localizationMode_;
|
bool localizationMode_;
|
||||||
bool trajectoryMode_;
|
bool trajectoryMode_;
|
||||||
bool autoExposure_;
|
bool autoExposure_;
|
||||||
|
|||||||
@@ -133,9 +133,9 @@ Java_com_introlab_rtabmap_RTABMapLib_setOdomCloudShown(
|
|||||||
}
|
}
|
||||||
JNIEXPORT void JNICALL
|
JNIEXPORT void JNICALL
|
||||||
Java_com_introlab_rtabmap_RTABMapLib_setMeshRendering(
|
Java_com_introlab_rtabmap_RTABMapLib_setMeshRendering(
|
||||||
JNIEnv*, jobject, bool enabled)
|
JNIEnv*, jobject, bool enabled, bool withTexture)
|
||||||
{
|
{
|
||||||
return app.setMeshRendering(enabled);
|
return app.setMeshRendering(enabled, withTexture);
|
||||||
}
|
}
|
||||||
JNIEXPORT void JNICALL
|
JNIEXPORT void JNICALL
|
||||||
Java_com_introlab_rtabmap_RTABMapLib_setLocalizationMode(
|
Java_com_introlab_rtabmap_RTABMapLib_setLocalizationMode(
|
||||||
@@ -162,12 +162,24 @@ Java_com_introlab_rtabmap_RTABMapLib_setNodesFiltering(
|
|||||||
return app.setNodesFiltering(enabled);
|
return app.setNodesFiltering(enabled);
|
||||||
}
|
}
|
||||||
JNIEXPORT void JNICALL
|
JNIEXPORT void JNICALL
|
||||||
|
Java_com_introlab_rtabmap_RTABMapLib_setDriftCorrection(
|
||||||
|
JNIEnv*, jobject, bool enabled)
|
||||||
|
{
|
||||||
|
return app.setDriftCorrection(enabled);
|
||||||
|
}
|
||||||
|
JNIEXPORT void JNICALL
|
||||||
Java_com_introlab_rtabmap_RTABMapLib_setGraphVisible(
|
Java_com_introlab_rtabmap_RTABMapLib_setGraphVisible(
|
||||||
JNIEnv*, jobject, bool visible)
|
JNIEnv*, jobject, bool visible)
|
||||||
{
|
{
|
||||||
return app.setGraphVisible(visible);
|
return app.setGraphVisible(visible);
|
||||||
}
|
}
|
||||||
JNIEXPORT void JNICALL
|
JNIEXPORT void JNICALL
|
||||||
|
Java_com_introlab_rtabmap_RTABMapLib_setGridVisible(
|
||||||
|
JNIEnv*, jobject, bool visible)
|
||||||
|
{
|
||||||
|
return app.setGridVisible(visible);
|
||||||
|
}
|
||||||
|
JNIEXPORT void JNICALL
|
||||||
Java_com_introlab_rtabmap_RTABMapLib_setAutoExposure(
|
Java_com_introlab_rtabmap_RTABMapLib_setAutoExposure(
|
||||||
JNIEnv*, jobject, bool enabled)
|
JNIEnv*, jobject, bool enabled)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -180,11 +180,11 @@ void PointCloudDrawable::setPose(const rtabmap::Transform & pose)
|
|||||||
pose_ = glmFromTransform(pose);
|
pose_ = glmFromTransform(pose);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PointCloudDrawable::Render(const glm::mat4 & projectionMatrix, const glm::mat4 & viewMatrix, bool meshRendering, float pointSize) {
|
void PointCloudDrawable::Render(const glm::mat4 & projectionMatrix, const glm::mat4 & viewMatrix, bool meshRendering, float pointSize, bool textureRendering) {
|
||||||
|
|
||||||
if(vertex_buffers_ && nPoints_ && visible_)
|
if(vertex_buffers_ && nPoints_ && visible_)
|
||||||
{
|
{
|
||||||
if(meshRendering && textures_)
|
if(meshRendering && textureRendering && textures_)
|
||||||
{
|
{
|
||||||
glUseProgram(texture_shader_program_);
|
glUseProgram(texture_shader_program_);
|
||||||
|
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ class PointCloudDrawable {
|
|||||||
// @param view_mat: view matrix from current render camera.
|
// @param view_mat: view matrix from current render camera.
|
||||||
// @param model_mat: model matrix for this point cloud frame.
|
// @param model_mat: model matrix for this point cloud frame.
|
||||||
// @param vertices: all vertices in this point cloud frame.
|
// @param vertices: all vertices in this point cloud frame.
|
||||||
void Render(const glm::mat4 & projectionMatrix, const glm::mat4 & viewMatrix, bool meshRendering = true, float pointSize = 3.0f);
|
void Render(const glm::mat4 & projectionMatrix, const glm::mat4 & viewMatrix, bool meshRendering = true, float pointSize = 3.0f, bool textureRendering = false);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Vertex buffer of the point cloud geometry.
|
// Vertex buffer of the point cloud geometry.
|
||||||
|
|||||||
@@ -109,6 +109,7 @@ Scene::Scene() :
|
|||||||
trace_(0),
|
trace_(0),
|
||||||
graph_(0),
|
graph_(0),
|
||||||
graphVisible_(true),
|
graphVisible_(true),
|
||||||
|
gridVisible_(true),
|
||||||
traceVisible_(true),
|
traceVisible_(true),
|
||||||
currentPose_(0),
|
currentPose_(0),
|
||||||
cloud_shader_program_(0),
|
cloud_shader_program_(0),
|
||||||
@@ -116,6 +117,7 @@ Scene::Scene() :
|
|||||||
graph_shader_program_(0),
|
graph_shader_program_(0),
|
||||||
mapRendering_(true),
|
mapRendering_(true),
|
||||||
meshRendering_(true),
|
meshRendering_(true),
|
||||||
|
meshRenderingTexture_(true),
|
||||||
pointSize_(3.0f) {}
|
pointSize_(3.0f) {}
|
||||||
|
|
||||||
Scene::~Scene() {DeleteResources();}
|
Scene::~Scene() {DeleteResources();}
|
||||||
@@ -275,9 +277,11 @@ int Scene::Render() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(gridVisible_)
|
||||||
grid_->Render(gesture_camera_->GetProjectionMatrix(),
|
{
|
||||||
gesture_camera_->GetViewMatrix());
|
grid_->Render(gesture_camera_->GetProjectionMatrix(),
|
||||||
|
gesture_camera_->GetViewMatrix());
|
||||||
|
}
|
||||||
|
|
||||||
bool frustumCulling = true;
|
bool frustumCulling = true;
|
||||||
int cloudDrawn=0;
|
int cloudDrawn=0;
|
||||||
@@ -327,7 +331,7 @@ int Scene::Render() {
|
|||||||
for(unsigned int i=0; i<indices->size(); ++i)
|
for(unsigned int i=0; i<indices->size(); ++i)
|
||||||
{
|
{
|
||||||
++cloudDrawn;
|
++cloudDrawn;
|
||||||
pointClouds_.find(ids[indices->at(i)])->second->Render(gesture_camera_->GetProjectionMatrix(), gesture_camera_->GetViewMatrix(), meshRendering_, pointSize_);
|
pointClouds_.find(ids[indices->at(i)])->second->Render(gesture_camera_->GetProjectionMatrix(), gesture_camera_->GetViewMatrix(), meshRendering_, pointSize_, meshRenderingTexture_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -338,7 +342,7 @@ int Scene::Render() {
|
|||||||
if((mapRendering_ || iter->first < 0) && iter->second->isVisible())
|
if((mapRendering_ || iter->first < 0) && iter->second->isVisible())
|
||||||
{
|
{
|
||||||
++cloudDrawn;
|
++cloudDrawn;
|
||||||
iter->second->Render(gesture_camera_->GetProjectionMatrix(), gesture_camera_->GetViewMatrix(), meshRendering_, pointSize_);
|
iter->second->Render(gesture_camera_->GetProjectionMatrix(), gesture_camera_->GetViewMatrix(), meshRendering_, pointSize_, meshRenderingTexture_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -400,6 +404,11 @@ void Scene::setGraphVisible(bool visible)
|
|||||||
graphVisible_ = visible;
|
graphVisible_ = visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Scene::setGridVisible(bool visible)
|
||||||
|
{
|
||||||
|
gridVisible_ = visible;
|
||||||
|
}
|
||||||
|
|
||||||
void Scene::setTraceVisible(bool visible)
|
void Scene::setTraceVisible(bool visible)
|
||||||
{
|
{
|
||||||
traceVisible_ = visible;
|
traceVisible_ = visible;
|
||||||
|
|||||||
@@ -94,6 +94,7 @@ class Scene {
|
|||||||
const std::multimap<int, rtabmap::Link> & links);
|
const std::multimap<int, rtabmap::Link> & links);
|
||||||
|
|
||||||
void setGraphVisible(bool visible);
|
void setGraphVisible(bool visible);
|
||||||
|
void setGridVisible(bool visible);
|
||||||
void setTraceVisible(bool visible);
|
void setTraceVisible(bool visible);
|
||||||
|
|
||||||
void addCloud(
|
void addCloud(
|
||||||
@@ -109,7 +110,7 @@ class Scene {
|
|||||||
std::set<int> getAddedClouds() const;
|
std::set<int> getAddedClouds() const;
|
||||||
|
|
||||||
void setMapRendering(bool enabled) {mapRendering_ = enabled;}
|
void setMapRendering(bool enabled) {mapRendering_ = enabled;}
|
||||||
void setMeshRendering(bool enabled) {meshRendering_ = enabled;}
|
void setMeshRendering(bool enabled, bool withTexture) {meshRendering_ = enabled; meshRenderingTexture_ = withTexture;}
|
||||||
void setPointSize(float size) {pointSize_ = size;}
|
void setPointSize(float size) {pointSize_ = size;}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -129,6 +130,7 @@ class Scene {
|
|||||||
tango_gl::Trace* trace_;
|
tango_gl::Trace* trace_;
|
||||||
GraphDrawable * graph_;
|
GraphDrawable * graph_;
|
||||||
bool graphVisible_;
|
bool graphVisible_;
|
||||||
|
bool gridVisible_;
|
||||||
bool traceVisible_;
|
bool traceVisible_;
|
||||||
|
|
||||||
std::map<int, PointCloudDrawable*> pointClouds_;
|
std::map<int, PointCloudDrawable*> pointClouds_;
|
||||||
@@ -142,6 +144,7 @@ class Scene {
|
|||||||
|
|
||||||
bool mapRendering_;
|
bool mapRendering_;
|
||||||
bool meshRendering_;
|
bool meshRendering_;
|
||||||
|
bool meshRenderingTexture_;
|
||||||
float pointSize_;
|
float pointSize_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -8,11 +8,15 @@
|
|||||||
<group android:id="@+id/group_actions">
|
<group android:id="@+id/group_actions">
|
||||||
<item android:id="@+id/post_processing" android:title="Post-Processing...">
|
<item android:id="@+id/post_processing" android:title="Post-Processing...">
|
||||||
<menu>
|
<menu>
|
||||||
<group android:id="@+id/group_post_processing">
|
<item android:id="@+id/post_processing_standard" android:title="Standard Optimization" />
|
||||||
<item android:id="@+id/detect_more_loop_closures" android:title="Detect More Loop Closures" />
|
<item android:id="@+id/post_processing_advanced" android:title="Advanced..." >
|
||||||
<item android:id="@+id/global_graph_optimization" android:title="Global Graph Optimization" />
|
<menu >
|
||||||
<item android:id="@+id/sba" android:title="Bundle Adjustement" />
|
<item android:id="@+id/global_graph_optimization" android:title="Global Graph Optimization" />
|
||||||
</group>
|
<item android:id="@+id/detect_more_loop_closures" android:title="Detect More Loop Closures" />
|
||||||
|
<item android:id="@+id/icp_refining" android:title="ICP Refining" />
|
||||||
|
<item android:id="@+id/sba" android:title="Bundle Adjustement" />
|
||||||
|
</menu>
|
||||||
|
</item>
|
||||||
</menu>
|
</menu>
|
||||||
</item>
|
</item>
|
||||||
<item android:id="@+id/open" android:title="Open"/>
|
<item android:id="@+id/open" android:title="Open"/>
|
||||||
@@ -31,14 +35,23 @@
|
|||||||
<menu >
|
<menu >
|
||||||
<group android:id="@+id/group_rendering_visibility" android:checkableBehavior="all">
|
<group android:id="@+id/group_rendering_visibility" android:checkableBehavior="all">
|
||||||
<item android:id="@+id/debug" android:checked="false" android:title="Debug" />
|
<item android:id="@+id/debug" android:checked="false" android:title="Debug" />
|
||||||
<item android:id="@+id/mesh_rendering" android:checked="true" android:title="Mesh Rendering" />
|
<item android:id="@+id/menu_rendering" android:checkable="false" android:title="Mesh Rendering..." >
|
||||||
|
<menu>
|
||||||
|
<group android:checkableBehavior="single">
|
||||||
|
<item android:id="@+id/point_cloud" android:title="Point Cloud" />
|
||||||
|
<item android:id="@+id/mesh" android:title="Mesh" />
|
||||||
|
<item android:id="@+id/texture_mesh" android:checked="true" android:title="Texture Mesh" />
|
||||||
|
</group>
|
||||||
|
<item android:id="@+id/mesh_angle_tolerance" android:checkable="false" android:title="Mesh Angle Tolerance..." />
|
||||||
|
<item android:id="@+id/mesh_triangle_size" android:checkable="false" android:title="Mesh Triangle Size..." />
|
||||||
|
<item android:id="@+id/max_depth" android:checkable="false" android:title="Max Depth..." />
|
||||||
|
</menu>
|
||||||
|
</item>
|
||||||
<item android:id="@+id/map_shown" android:checked="true" android:title="Map Visible" />
|
<item android:id="@+id/map_shown" android:checked="true" android:title="Map Visible" />
|
||||||
<item android:id="@+id/odom_shown" android:checked="true" android:title="Odom Visible" />
|
<item android:id="@+id/odom_shown" android:checked="true" android:title="Odom Visible" />
|
||||||
<item android:id="@+id/graph_visible" android:checked="true" android:title="Graph Visible" />
|
<item android:id="@+id/graph_visible" android:checked="true" android:title="Graph Visible" />
|
||||||
|
<item android:id="@+id/grid_visible" android:checked="true" android:title="Grid Visible" />
|
||||||
<item android:id="@+id/auto_exposure" android:checked="false" android:title="Auto Exposure" />
|
<item android:id="@+id/auto_exposure" android:checked="false" android:title="Auto Exposure" />
|
||||||
<item android:id="@+id/max_depth" android:checkable="false" android:title="Cloud/Mesh Max Depth..." />
|
|
||||||
<item android:id="@+id/mesh_angle_tolerance" android:checkable="false" android:title="Mesh Angle Tolerance..." />
|
|
||||||
<item android:id="@+id/mesh_triangle_size" android:checkable="false" android:title="Mesh Triangle Size..." />
|
|
||||||
</group>
|
</group>
|
||||||
</menu>
|
</menu>
|
||||||
</item>
|
</item>
|
||||||
@@ -49,6 +62,7 @@
|
|||||||
<item android:id="@+id/trajectory_mode" android:checked="false" android:title="Trajectory Mode" />
|
<item android:id="@+id/trajectory_mode" android:checked="false" android:title="Trajectory Mode" />
|
||||||
<item android:id="@+id/graph_optimization" android:checked="true" android:title="Optimized Graph" />
|
<item android:id="@+id/graph_optimization" android:checked="true" android:title="Optimized Graph" />
|
||||||
<item android:id="@+id/nodes_filtering" android:checked="false" android:title="Nodes Filtering" />
|
<item android:id="@+id/nodes_filtering" android:checked="false" android:title="Nodes Filtering" />
|
||||||
|
<item android:id="@+id/drift_correction" android:checked="false" android:title="Drift Correction" />
|
||||||
<item android:id="@+id/resolution" android:checked="false" android:title="720p Mode" />
|
<item android:id="@+id/resolution" android:checked="false" android:title="720p Mode" />
|
||||||
<item android:id="@+id/menu_param_settings" android:checkable="false" android:title="Parameters...">
|
<item android:id="@+id/menu_param_settings" android:checkable="false" android:title="Parameters...">
|
||||||
<menu >
|
<menu >
|
||||||
|
|||||||
@@ -74,6 +74,10 @@ public class RTABMapActivity extends Activity implements OnClickListener {
|
|||||||
private MenuItem mItemExport;
|
private MenuItem mItemExport;
|
||||||
private MenuItem mItemLocalizationMode;
|
private MenuItem mItemLocalizationMode;
|
||||||
private MenuItem mItemTrajectoryMode;
|
private MenuItem mItemTrajectoryMode;
|
||||||
|
private MenuItem mItemRenderingPointCloud;
|
||||||
|
private MenuItem mItemRenderingMesh;
|
||||||
|
private MenuItem mItemRenderingTextureMesh;
|
||||||
|
|
||||||
|
|
||||||
private String mOpenedDatabasePath = "";
|
private String mOpenedDatabasePath = "";
|
||||||
private String mTempDatabasePath = "";
|
private String mTempDatabasePath = "";
|
||||||
@@ -81,7 +85,7 @@ public class RTABMapActivity extends Activity implements OnClickListener {
|
|||||||
private String mWorkingDirectory = "";
|
private String mWorkingDirectory = "";
|
||||||
|
|
||||||
private int mMaxDepthIndex = 5;
|
private int mMaxDepthIndex = 5;
|
||||||
private int mMeshAngleToleranceIndex = 1;
|
private int mMeshAngleToleranceIndex = 2;
|
||||||
private int mMeshTriangleSizeIndex = 0;
|
private int mMeshTriangleSizeIndex = 0;
|
||||||
|
|
||||||
private int mParamUpdateRateHzIndex = 1;
|
private int mParamUpdateRateHzIndex = 1;
|
||||||
@@ -316,6 +320,9 @@ public class RTABMapActivity extends Activity implements OnClickListener {
|
|||||||
mItemExport = menu.findItem(R.id.export);
|
mItemExport = menu.findItem(R.id.export);
|
||||||
mItemLocalizationMode = menu.findItem(R.id.localization_mode);
|
mItemLocalizationMode = menu.findItem(R.id.localization_mode);
|
||||||
mItemTrajectoryMode = menu.findItem(R.id.trajectory_mode);
|
mItemTrajectoryMode = menu.findItem(R.id.trajectory_mode);
|
||||||
|
mItemRenderingPointCloud = menu.findItem(R.id.point_cloud);
|
||||||
|
mItemRenderingMesh = menu.findItem(R.id.mesh);
|
||||||
|
mItemRenderingTextureMesh = menu.findItem(R.id.texture_mesh);
|
||||||
mItemSave.setEnabled(false);
|
mItemSave.setEnabled(false);
|
||||||
mItemExport.setEnabled(false);
|
mItemExport.setEnabled(false);
|
||||||
mItemOpen.setEnabled(false);
|
mItemOpen.setEnabled(false);
|
||||||
@@ -652,6 +659,33 @@ public class RTABMapActivity extends Activity implements OnClickListener {
|
|||||||
((TextView)findViewById(R.id.status)).setText(mItemLocalizationMode.isChecked()?"Localization":"Mapping");
|
((TextView)findViewById(R.id.status)).setText(mItemLocalizationMode.isChecked()?"Localization":"Mapping");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (itemId == R.id.post_processing_standard)
|
||||||
|
{
|
||||||
|
mProgressDialog.setTitle("Post-Processing");
|
||||||
|
mProgressDialog.setMessage(String.format("Please wait while optimizing..."));
|
||||||
|
mProgressDialog.show();
|
||||||
|
|
||||||
|
Thread workingThread = new Thread(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
final int loopDetected = RTABMapLib.postProcessing(-1);
|
||||||
|
runOnUiThread(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
mProgressDialog.dismiss();
|
||||||
|
if(loopDetected >= 0)
|
||||||
|
{
|
||||||
|
mTotalLoopClosures+=loopDetected;
|
||||||
|
mToast.makeText(getActivity(), String.format("Optimization done!"), mToast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
else if(loopDetected < 0)
|
||||||
|
{
|
||||||
|
mToast.makeText(getActivity(), String.format("Optimization failed!"), mToast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
workingThread.start();
|
||||||
|
}
|
||||||
else if (itemId == R.id.detect_more_loop_closures)
|
else if (itemId == R.id.detect_more_loop_closures)
|
||||||
{
|
{
|
||||||
mProgressDialog.setTitle("Post-Processing");
|
mProgressDialog.setTitle("Post-Processing");
|
||||||
@@ -679,6 +713,32 @@ public class RTABMapActivity extends Activity implements OnClickListener {
|
|||||||
});
|
});
|
||||||
workingThread.start();
|
workingThread.start();
|
||||||
}
|
}
|
||||||
|
else if (itemId == R.id.icp_refining)
|
||||||
|
{
|
||||||
|
mProgressDialog.setTitle("Post-Processing");
|
||||||
|
mProgressDialog.setMessage(String.format("Please wait while refining links..."));
|
||||||
|
mProgressDialog.show();
|
||||||
|
|
||||||
|
Thread workingThread = new Thread(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
final int linksRefined = RTABMapLib.postProcessing(3);
|
||||||
|
runOnUiThread(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
mProgressDialog.dismiss();
|
||||||
|
if(linksRefined >= 0)
|
||||||
|
{
|
||||||
|
mToast.makeText(getActivity(), String.format("Refining done! %d link(s) refined.", linksRefined), mToast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
else if(linksRefined < 0)
|
||||||
|
{
|
||||||
|
mToast.makeText(getActivity(), String.format("Refining failed!"), mToast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
workingThread.start();
|
||||||
|
}
|
||||||
else if (itemId == R.id.global_graph_optimization)
|
else if (itemId == R.id.global_graph_optimization)
|
||||||
{
|
{
|
||||||
mProgressDialog.setTitle("Post-Processing");
|
mProgressDialog.setTitle("Post-Processing");
|
||||||
@@ -743,10 +803,12 @@ public class RTABMapActivity extends Activity implements OnClickListener {
|
|||||||
mLayoutDebug.setVisibility(LinearLayout.VISIBLE);
|
mLayoutDebug.setVisibility(LinearLayout.VISIBLE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(itemId == R.id.mesh_rendering)
|
else if(itemId == R.id.mesh || itemId == R.id.texture_mesh || itemId == R.id.point_cloud)
|
||||||
{
|
{
|
||||||
item.setChecked(!item.isChecked());
|
item.setChecked(true);
|
||||||
RTABMapLib.setMeshRendering(item.isChecked());
|
RTABMapLib.setMeshRendering(
|
||||||
|
mItemRenderingMesh.isChecked() || mItemRenderingTextureMesh.isChecked(),
|
||||||
|
mItemRenderingTextureMesh.isChecked());
|
||||||
}
|
}
|
||||||
else if(itemId == R.id.map_shown)
|
else if(itemId == R.id.map_shown)
|
||||||
{
|
{
|
||||||
@@ -778,11 +840,21 @@ public class RTABMapActivity extends Activity implements OnClickListener {
|
|||||||
item.setChecked(!item.isChecked());
|
item.setChecked(!item.isChecked());
|
||||||
RTABMapLib.setNodesFiltering(item.isChecked());
|
RTABMapLib.setNodesFiltering(item.isChecked());
|
||||||
}
|
}
|
||||||
|
else if(itemId == R.id.drift_correction)
|
||||||
|
{
|
||||||
|
item.setChecked(!item.isChecked());
|
||||||
|
RTABMapLib.setDriftCorrection(item.isChecked());
|
||||||
|
}
|
||||||
else if(itemId == R.id.graph_visible)
|
else if(itemId == R.id.graph_visible)
|
||||||
{
|
{
|
||||||
item.setChecked(!item.isChecked());
|
item.setChecked(!item.isChecked());
|
||||||
RTABMapLib.setGraphVisible(item.isChecked());
|
RTABMapLib.setGraphVisible(item.isChecked());
|
||||||
}
|
}
|
||||||
|
else if(itemId == R.id.grid_visible)
|
||||||
|
{
|
||||||
|
item.setChecked(!item.isChecked());
|
||||||
|
RTABMapLib.setGridVisible(item.isChecked());
|
||||||
|
}
|
||||||
else if(itemId == R.id.auto_exposure)
|
else if(itemId == R.id.auto_exposure)
|
||||||
{
|
{
|
||||||
item.setChecked(!item.isChecked());
|
item.setChecked(!item.isChecked());
|
||||||
|
|||||||
@@ -58,12 +58,14 @@ public class RTABMapLib
|
|||||||
public static native void setPausedMapping(boolean paused);
|
public static native void setPausedMapping(boolean paused);
|
||||||
public static native void setMapCloudShown(boolean shown);
|
public static native void setMapCloudShown(boolean shown);
|
||||||
public static native void setOdomCloudShown(boolean shown);
|
public static native void setOdomCloudShown(boolean shown);
|
||||||
public static native void setMeshRendering(boolean enabled);
|
public static native void setMeshRendering(boolean enabled, boolean withTexture);
|
||||||
public static native void setLocalizationMode(boolean enabled);
|
public static native void setLocalizationMode(boolean enabled);
|
||||||
public static native void setTrajectoryMode(boolean enabled);
|
public static native void setTrajectoryMode(boolean enabled);
|
||||||
public static native void setGraphOptimization(boolean enabled);
|
public static native void setGraphOptimization(boolean enabled);
|
||||||
public static native void setNodesFiltering(boolean enabled);
|
public static native void setNodesFiltering(boolean enabled);
|
||||||
|
public static native void setDriftCorrection(boolean enabled);
|
||||||
public static native void setGraphVisible(boolean visible);
|
public static native void setGraphVisible(boolean visible);
|
||||||
|
public static native void setGridVisible(boolean visible);
|
||||||
public static native void setAutoExposure(boolean enabled);
|
public static native void setAutoExposure(boolean enabled);
|
||||||
public static native void setFullResolution(boolean enabled);
|
public static native void setFullResolution(boolean enabled);
|
||||||
public static native void setMaxCloudDepth(float value);
|
public static native void setMaxCloudDepth(float value);
|
||||||
|
|||||||
@@ -93,8 +93,7 @@ public:
|
|||||||
void emptyTrash();
|
void emptyTrash();
|
||||||
void joinTrashThread();
|
void joinTrashThread();
|
||||||
bool addLink(const Link & link, bool addInDatabase = false);
|
bool addLink(const Link & link, bool addInDatabase = false);
|
||||||
void updateLink(int fromId, int toId, const Transform & transform, float rotVariance, float transVariance);
|
void updateLink(const Link & link, bool updateInDatabase = false);
|
||||||
void updateLink(int fromId, int toId, const Transform & transform, const cv::Mat & covariance);
|
|
||||||
void removeAllVirtualLinks();
|
void removeAllVirtualLinks();
|
||||||
void removeVirtualLinks(int signatureId);
|
void removeVirtualLinks(int signatureId);
|
||||||
std::map<int, int> getNeighborsId(
|
std::map<int, int> getNeighborsId(
|
||||||
|
|||||||
@@ -128,6 +128,7 @@ public:
|
|||||||
bool global,
|
bool global,
|
||||||
std::map<int, Signature> * signatures = 0);
|
std::map<int, Signature> * signatures = 0);
|
||||||
int detectMoreLoopClosures(float clusterRadius = 0.5f, float clusterAngle = M_PI/6.0f, int iterations = 1);
|
int detectMoreLoopClosures(float clusterRadius = 0.5f, float clusterAngle = M_PI/6.0f, int iterations = 1);
|
||||||
|
int refineLinks();
|
||||||
|
|
||||||
int getPathStatus() const {return _pathStatus;} // -1=failed 0=idle/executing 1=success
|
int getPathStatus() const {return _pathStatus;} // -1=failed 0=idle/executing 1=success
|
||||||
void clearPath(int status); // -1=failed 0=idle/executing 1=success
|
void clearPath(int status); // -1=failed 0=idle/executing 1=success
|
||||||
|
|||||||
@@ -141,7 +141,7 @@ pcl::PointCloud<pcl::PointXYZ>::Ptr RTABMAP_EXP cloudFromSensorData(
|
|||||||
float maxDepth = 0.0f,
|
float maxDepth = 0.0f,
|
||||||
float minDepth = 0.0f,
|
float minDepth = 0.0f,
|
||||||
std::vector<int> * validIndices = 0,
|
std::vector<int> * validIndices = 0,
|
||||||
const ParametersMap & parameters = ParametersMap(),
|
const ParametersMap & stereoParameters = ParametersMap(),
|
||||||
const std::vector<float> & roiRatios = std::vector<float>()); // ignored for stereo
|
const std::vector<float> & roiRatios = std::vector<float>()); // ignored for stereo
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -164,7 +164,7 @@ pcl::PointCloud<pcl::PointXYZRGB>::Ptr RTABMAP_EXP cloudRGBFromSensorData(
|
|||||||
float maxDepth = 0.0f,
|
float maxDepth = 0.0f,
|
||||||
float minDepth = 0.0f,
|
float minDepth = 0.0f,
|
||||||
std::vector<int> * validIndices = 0,
|
std::vector<int> * validIndices = 0,
|
||||||
const ParametersMap & parameters = ParametersMap(),
|
const ParametersMap & stereoParameters = ParametersMap(),
|
||||||
const std::vector<float> & roiRatios = std::vector<float>()); // ignored for stereo
|
const std::vector<float> & roiRatios = std::vector<float>()); // ignored for stereo
|
||||||
|
|
||||||
pcl::PointCloud<pcl::PointXYZ> RTABMAP_EXP laserScanFromDepthImage(
|
pcl::PointCloud<pcl::PointXYZ> RTABMAP_EXP laserScanFromDepthImage(
|
||||||
|
|||||||
+49
-40
@@ -2422,54 +2422,63 @@ bool Memory::addLink(const Link & link, bool addInDatabase)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Memory::updateLink(int fromId, int toId, const Transform & transform, float rotVariance, float transVariance)
|
void Memory::updateLink(const Link & link, bool updateInDatabase)
|
||||||
{
|
{
|
||||||
Signature * fromS = this->_getSignature(fromId);
|
Signature * fromS = this->_getSignature(link.from());
|
||||||
Signature * toS = this->_getSignature(toId);
|
Signature * toS = this->_getSignature(link.to());
|
||||||
|
|
||||||
if(fromS->hasLink(toId) && toS->hasLink(fromId))
|
if(fromS && toS)
|
||||||
{
|
{
|
||||||
Link::Type type = fromS->getLinks().at(toId).type();
|
if(fromS->hasLink(link.to()) && toS->hasLink(link.from()))
|
||||||
fromS->removeLink(toId);
|
|
||||||
toS->removeLink(fromId);
|
|
||||||
|
|
||||||
fromS->addLink(Link(fromId, toId, type, transform, rotVariance, transVariance));
|
|
||||||
toS->addLink(Link(toId, fromId, type, transform.inverse(), rotVariance, transVariance));
|
|
||||||
|
|
||||||
if(type!=Link::kVirtualClosure)
|
|
||||||
{
|
{
|
||||||
_linksChanged = true;
|
Link::Type oldType = fromS->getLinks().at(link.to()).type();
|
||||||
|
|
||||||
|
fromS->removeLink(link.to());
|
||||||
|
toS->removeLink(link.from());
|
||||||
|
|
||||||
|
fromS->addLink(link);
|
||||||
|
toS->addLink(link.inverse());
|
||||||
|
|
||||||
|
if(oldType!=Link::kVirtualClosure || link.type()!=Link::kVirtualClosure)
|
||||||
|
{
|
||||||
|
_linksChanged = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UERROR("fromId=%d and toId=%d are not linked!", link.from(), link.to());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(!updateInDatabase)
|
||||||
|
{
|
||||||
|
if(!fromS)
|
||||||
|
{
|
||||||
|
UERROR("from=%d, to=%d, Signature %d not found in working/st memories", link.from(), link.to(), link.from());
|
||||||
|
}
|
||||||
|
if(!toS)
|
||||||
|
{
|
||||||
|
UERROR("from=%d, to=%d, Signature %d not found in working/st memories", link.from(), link.to(), link.to());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(fromS)
|
||||||
|
{
|
||||||
|
UDEBUG("Update link between %d and %d (db)", link.from(), link.to());
|
||||||
|
fromS->removeLink(link.to());
|
||||||
|
fromS->addLink(link);
|
||||||
|
_dbDriver->updateLink(link.inverse());
|
||||||
|
}
|
||||||
|
else if(toS)
|
||||||
|
{
|
||||||
|
UDEBUG("Update link between %d (db) and %d", link.from(), link.to());
|
||||||
|
toS->removeLink(link.from());
|
||||||
|
toS->addLink(link.inverse());
|
||||||
|
_dbDriver->updateLink(link);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
UERROR("fromId=%d and toId=%d are not linked!", fromId, toId);
|
UDEBUG("Update link between %d (db) and %d (db)", link.from(), link.to());
|
||||||
}
|
_dbDriver->updateLink(link);
|
||||||
}
|
_dbDriver->updateLink(link.inverse());
|
||||||
|
|
||||||
void Memory::updateLink(int fromId, int toId, const Transform & transform, const cv::Mat & covariance)
|
|
||||||
{
|
|
||||||
Signature * fromS = this->_getSignature(fromId);
|
|
||||||
Signature * toS = this->_getSignature(toId);
|
|
||||||
|
|
||||||
if(fromS->hasLink(toId) && toS->hasLink(fromId))
|
|
||||||
{
|
|
||||||
Link::Type type = fromS->getLinks().at(toId).type();
|
|
||||||
fromS->removeLink(toId);
|
|
||||||
toS->removeLink(fromId);
|
|
||||||
|
|
||||||
cv::Mat infMatrix = covariance.inv();
|
|
||||||
fromS->addLink(Link(fromId, toId, type, transform, infMatrix));
|
|
||||||
toS->addLink(Link(toId, fromId, type, transform.inverse(), infMatrix));
|
|
||||||
|
|
||||||
if(type!=Link::kVirtualClosure)
|
|
||||||
{
|
|
||||||
_linksChanged = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UERROR("fromId=%d and toId=%d are not linked!", fromId, toId);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+59
-5
@@ -1012,7 +1012,7 @@ bool Rtabmap::process(
|
|||||||
{
|
{
|
||||||
// set small variance
|
// set small variance
|
||||||
UDEBUG("Set small variance. The robot is not moving.");
|
UDEBUG("Set small variance. The robot is not moving.");
|
||||||
_memory->updateLink(oldId, signature->id(), guess, 0.0001, 0.0001);
|
_memory->updateLink(Link(oldId, signature->id(), signature->getLinks().begin()->second.type(), guess, 0.0001, 0.0001));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -1034,7 +1034,7 @@ bool Rtabmap::process(
|
|||||||
guess.prettyPrint().c_str(),
|
guess.prettyPrint().c_str(),
|
||||||
t.prettyPrint().c_str());
|
t.prettyPrint().c_str());
|
||||||
UASSERT(info.variance > 0.0);
|
UASSERT(info.variance > 0.0);
|
||||||
_memory->updateLink(oldId, signature->id(), t, info.variance, info.variance);
|
_memory->updateLink(Link(oldId, signature->id(), signature->getLinks().begin()->second.type(), t, info.variance, info.variance));
|
||||||
|
|
||||||
if(_optimizeFromGraphEnd)
|
if(_optimizeFromGraphEnd)
|
||||||
{
|
{
|
||||||
@@ -1058,7 +1058,7 @@ bool Rtabmap::process(
|
|||||||
if(info.variance > 0)
|
if(info.variance > 0)
|
||||||
{
|
{
|
||||||
double sqrtVar = sqrt(info.variance);
|
double sqrtVar = sqrt(info.variance);
|
||||||
_memory->updateLink(oldId, signature->id(), guess, sqrtVar, sqrtVar);
|
_memory->updateLink(Link(oldId, signature->id(), signature->getLinks().begin()->second.type(), guess, sqrtVar, sqrtVar));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
statistics_.addStatistic(Statistics::kNeighborLinkRefiningAccepted(), !t.isNull()?1.0f:0);
|
statistics_.addStatistic(Statistics::kNeighborLinkRefiningAccepted(), !t.isNull()?1.0f:0);
|
||||||
@@ -1821,7 +1821,7 @@ bool Rtabmap::process(
|
|||||||
UDEBUG("nearestPoses=%d", (int)nearestPoses.size());
|
UDEBUG("nearestPoses=%d", (int)nearestPoses.size());
|
||||||
|
|
||||||
// segment poses by paths, only one detection per path
|
// segment poses by paths, only one detection per path
|
||||||
std::map<int, std::map<int, Transform> > nearestPaths = getPaths(nearestPoses, _optimizedPoses.at(signature->id()), _proximityMaxNeighbors);
|
std::map<int, std::map<int, Transform> > nearestPaths = getPaths(nearestPoses, _optimizedPoses.at(signature->id()), _proximityMaxGraphDepth);
|
||||||
UDEBUG("nearestPaths=%d proximityMaxPaths=%d", (int)nearestPaths.size(), _proximityMaxPaths);
|
UDEBUG("nearestPaths=%d proximityMaxPaths=%d", (int)nearestPaths.size(), _proximityMaxPaths);
|
||||||
|
|
||||||
for(std::map<int, std::map<int, Transform> >::const_reverse_iterator iter=nearestPaths.rbegin();
|
for(std::map<int, std::map<int, Transform> >::const_reverse_iterator iter=nearestPaths.rbegin();
|
||||||
@@ -1886,13 +1886,21 @@ bool Rtabmap::process(
|
|||||||
// 2) compare locally with nearest locations by scan matching
|
// 2) compare locally with nearest locations by scan matching
|
||||||
//
|
//
|
||||||
UDEBUG("Proximity detection (local loop closure in SPACE with scan matching)");
|
UDEBUG("Proximity detection (local loop closure in SPACE with scan matching)");
|
||||||
if( !signature->sensorData().laserScanCompressed().empty() &&
|
if( _proximityMaxNeighbors > 0 &&
|
||||||
|
!signature->sensorData().laserScanCompressed().empty() &&
|
||||||
(_memory->isIncremental() || lastProximitySpaceClosureId == 0))
|
(_memory->isIncremental() || lastProximitySpaceClosureId == 0))
|
||||||
{
|
{
|
||||||
// In localization mode, no need to check local loop
|
// In localization mode, no need to check local loop
|
||||||
// closures if we are already localized by at least one
|
// closures if we are already localized by at least one
|
||||||
// local visual closure above.
|
// local visual closure above.
|
||||||
|
|
||||||
|
// Parse again with if different (normally, maxNeighbors would be smaller than MaxGraphDepth)
|
||||||
|
if(_proximityMaxNeighbors != _proximityMaxGraphDepth)
|
||||||
|
{
|
||||||
|
nearestPaths = getPaths(nearestPoses, _optimizedPoses.at(signature->id()), _proximityMaxNeighbors);
|
||||||
|
UDEBUG("nearestPaths=%d proximityMaxPaths=%d", (int)nearestPaths.size(), _proximityMaxPaths);
|
||||||
|
}
|
||||||
|
|
||||||
proximitySpacePaths = (int)nearestPaths.size();
|
proximitySpacePaths = (int)nearestPaths.size();
|
||||||
for(std::map<int, std::map<int, Transform> >::const_reverse_iterator iter=nearestPaths.rbegin();
|
for(std::map<int, std::map<int, Transform> >::const_reverse_iterator iter=nearestPaths.rbegin();
|
||||||
iter!=nearestPaths.rend() &&
|
iter!=nearestPaths.rend() &&
|
||||||
@@ -3412,6 +3420,52 @@ int Rtabmap::detectMoreLoopClosures(float clusterRadius, float clusterAngle, int
|
|||||||
return (int)loopClosuresAdded.size();
|
return (int)loopClosuresAdded.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Rtabmap::refineLinks()
|
||||||
|
{
|
||||||
|
if(!_rgbdSlamMode)
|
||||||
|
{
|
||||||
|
UERROR("Refining links can be done only in RGBD-SLAM mode.");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::list<Link> linksRefined;
|
||||||
|
|
||||||
|
std::map<int, Transform> poses;
|
||||||
|
std::multimap<int, Link> links;
|
||||||
|
std::map<int, Signature> signatures;
|
||||||
|
this->getGraph(poses, links, false, true, &signatures);
|
||||||
|
|
||||||
|
int i=0;
|
||||||
|
for(std::multimap<int, Link>::iterator iter=links.begin(); iter!= links.end(); ++iter)
|
||||||
|
{
|
||||||
|
int from = iter->second.from();
|
||||||
|
int to = iter->second.to();
|
||||||
|
|
||||||
|
UASSERT(signatures.find(from) != signatures.end());
|
||||||
|
UASSERT(signatures.find(to) != signatures.end());
|
||||||
|
|
||||||
|
RegistrationInfo info;
|
||||||
|
// use signatures instead of IDs because some signatures may not be in WM
|
||||||
|
Transform t = _memory->computeTransform(signatures.at(from), signatures.at(to), iter->second.transform(), &info);
|
||||||
|
|
||||||
|
if(!t.isNull())
|
||||||
|
{
|
||||||
|
linksRefined.push_back(Link(from, to, iter->second.type(), t, info.variance, info.variance));
|
||||||
|
UINFO("Refined link %d->%d! (%d/%d)", from, to, ++i, (int)links.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
UINFO("Total refined %d links.", (int)linksRefined.size());
|
||||||
|
|
||||||
|
if(linksRefined.size())
|
||||||
|
{
|
||||||
|
for(std::list<Link>::iterator iter=linksRefined.begin(); iter!=linksRefined.end(); ++iter)
|
||||||
|
{
|
||||||
|
_memory->updateLink(*iter, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (int)linksRefined.size();
|
||||||
|
}
|
||||||
|
|
||||||
void Rtabmap::clearPath(int status)
|
void Rtabmap::clearPath(int status)
|
||||||
{
|
{
|
||||||
UINFO("status=%d", status);
|
UINFO("status=%d", status);
|
||||||
|
|||||||
@@ -699,7 +699,7 @@ pcl::PointCloud<pcl::PointXYZ>::Ptr RTABMAP_EXP cloudFromSensorData(
|
|||||||
float maxDepth,
|
float maxDepth,
|
||||||
float minDepth,
|
float minDepth,
|
||||||
std::vector<int> * validIndices,
|
std::vector<int> * validIndices,
|
||||||
const ParametersMap & parameters,
|
const ParametersMap & stereoParameters,
|
||||||
const std::vector<float> & roiRatios)
|
const std::vector<float> & roiRatios)
|
||||||
{
|
{
|
||||||
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
|
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
|
||||||
@@ -815,7 +815,7 @@ pcl::PointCloud<pcl::PointXYZ>::Ptr RTABMAP_EXP cloudFromSensorData(
|
|||||||
}
|
}
|
||||||
|
|
||||||
cloud = cloudFromDisparity(
|
cloud = cloudFromDisparity(
|
||||||
util2d::disparityFromStereoImages(leftMono, sensorData.rightRaw(), parameters),
|
util2d::disparityFromStereoImages(leftMono, sensorData.rightRaw(), stereoParameters),
|
||||||
sensorData.stereoCameraModel(),
|
sensorData.stereoCameraModel(),
|
||||||
decimation,
|
decimation,
|
||||||
maxDepth,
|
maxDepth,
|
||||||
@@ -839,7 +839,7 @@ pcl::PointCloud<pcl::PointXYZRGB>::Ptr RTABMAP_EXP cloudRGBFromSensorData(
|
|||||||
float maxDepth,
|
float maxDepth,
|
||||||
float minDepth,
|
float minDepth,
|
||||||
std::vector<int> * validIndices,
|
std::vector<int> * validIndices,
|
||||||
const ParametersMap & parameters,
|
const ParametersMap & stereoParameters,
|
||||||
const std::vector<float> & roiRatios)
|
const std::vector<float> & roiRatios)
|
||||||
{
|
{
|
||||||
UASSERT(!sensorData.imageRaw().empty());
|
UASSERT(!sensorData.imageRaw().empty());
|
||||||
@@ -961,7 +961,7 @@ pcl::PointCloud<pcl::PointXYZRGB>::Ptr RTABMAP_EXP cloudRGBFromSensorData(
|
|||||||
maxDepth,
|
maxDepth,
|
||||||
minDepth,
|
minDepth,
|
||||||
validIndices,
|
validIndices,
|
||||||
parameters);
|
stereoParameters);
|
||||||
|
|
||||||
if(cloud->size())
|
if(cloud->size())
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user