32 #include "CameraAvailability.h"
39 #include <media/NdkImage.h>
41 #ifdef RTABMAP_ARENGINE
56 #include <opencv2/opencv_modules.hpp>
69 #include <pcl/common/common.h>
70 #include <pcl/filters/extract_indices.h>
71 #include <pcl/io/ply_io.h>
72 #include <pcl/io/obj_io.h>
73 #include <pcl/surface/poisson.h>
74 #include <pcl/surface/vtk_smoothing/vtk_mesh_quadric_decimation.h>
78 #elif defined(RTABMAP_LIBLAS)
83 #define DEBUG_RENDERING_PERFORMANCE
89 static jobject RTABMapActivity = 0;
97 static void *thread_func(
void*)
101 while((rdsz = read(pfd[0], buf,
sizeof buf - 1)) > 0) {
102 if(buf[rdsz - 1] ==
'\n') --rdsz;
104 __android_log_write(ANDROID_LOG_DEBUG,
LOG_TAG, buf);
112 setvbuf(stdout, 0, _IOLBF, 0);
113 setvbuf(stderr, 0, _IONBF, 0);
121 if(pthread_create(&thr, 0, thread_func, 0) == -1)
141 parameters.insert(
rtabmap::ParametersPair(rtabmap::Parameters::kRtabmapPublishLikelihood(), std::string(
"false")));
150 parameters.insert(
rtabmap::ParametersPair(rtabmap::Parameters::kMemCompressionParallelized(), std::string(
"false")));
152 parameters.insert(
rtabmap::ParametersPair(rtabmap::Parameters::kRGBDOptimizeFromGraphEnd(), std::string(
"true")));
154 parameters.insert(
rtabmap::ParametersPair(rtabmap::Parameters::kVisPnPVarianceMedianRatio(), std::string(
"2")));
155 parameters.insert(
rtabmap::ParametersPair(rtabmap::Parameters::kRGBDProximityPathMaxNeighbors(), std::string(
"0")));
156 parameters.insert(
rtabmap::ParametersPair(rtabmap::Parameters::kRGBDProximityBySpace(), std::string(
"false")));
162 if(parameters.find(rtabmap::Parameters::kOptimizerStrategy()) != parameters.end())
164 if(parameters.at(rtabmap::Parameters::kOptimizerStrategy()).compare(
"2") == 0)
170 else if(parameters.at(rtabmap::Parameters::kOptimizerStrategy()).compare(
"1") == 0)
190 parameters.insert(
rtabmap::ParametersPair(rtabmap::Parameters::kIcpCorrespondenceRatio(), std::string(
"0.49")));
191 parameters.insert(
rtabmap::ParametersPair(rtabmap::Parameters::kIcpMaxCorrespondenceDistance(), std::string(
"0.05")));
222 sensorCaptureThread_(0),
226 odomCloudShown_(
true),
227 graphOptimization_(
true),
228 nodesFiltering_(
false),
229 localizationMode_(
false),
230 trajectoryMode_(
false),
231 rawScanSaved_(
false),
233 depthFromMotion_(
false),
235 fullResolution_(
false),
237 useExternalLidar_(
false),
240 cloudDensityLevel_(1),
242 meshAngleToleranceDeg_(20.0),
243 meshDecimationFactor_(0),
245 maxGainRadius_(0.02
f),
246 renderingTextureDecimation_(4),
247 backgroundColor_(0.2
f),
249 upstreamRelocalizationMaxAcc_(0.0
f),
250 exportPointCloudFormat_(
"ply"),
251 dataRecorderMode_(
false),
252 clearSceneOnNextRender_(
false),
253 openingDatabase_(
false),
255 postProcessing_(
false),
256 filterPolygonsOnNextRender_(
false),
257 gainCompensationOnNextRender_(0),
258 bilateralFilteringOnNextRender_(
false),
259 takeScreenshotOnNextRender_(
false),
260 cameraJustInitialized_(
false),
263 lastDrawnCloudsCount_(0),
264 renderingTime_(0.0
f),
265 lastPostRenderEventTime_(0.0),
266 lastPoseEventTime_(0.0),
267 visualizingMesh_(
false),
268 exportedMeshUpdated_(
false),
269 measuresUpdated_(
false),
270 targetPoint_(new
pcl::PointCloud<
pcl::PointXYZRGB>),
271 quadSample_(new
pcl::PointCloud<
pcl::PointXYZ>),
272 quadSamplePolygons_(2),
274 measuringTextSize_(0.05
f),
277 addMeasureClicked_(
false),
278 teleportClicked_(
false),
279 removeMeasureClicked_(
false),
280 optTextureMesh_(new
pcl::TextureMesh),
283 mapToOdom_(
rtabmap::Transform::getIdentity())
286 pcl::PointXYZRGB ptWhite;
287 ptWhite.r = ptWhite.g = ptWhite.b = 255;
288 targetPoint_->push_back(ptWhite);
289 snapAxes_.push_back(cv::Vec3f(1,0,0));
290 snapAxes_.push_back(cv::Vec3f(0,1,0));
291 snapAxes_.push_back(cv::Vec3f(0,0,1));
293 float quadSize = 0.05f;
294 quadSample_->push_back(pcl::PointXYZ(-quadSize, -quadSize, 0.0
f));
295 quadSample_->push_back(pcl::PointXYZ(quadSize, -quadSize, 0.0
f));
296 quadSample_->push_back(pcl::PointXYZ(quadSize, quadSize, 0.0
f));
297 quadSample_->push_back(pcl::PointXYZ(-quadSize, quadSize, 0.0
f));
298 quadSamplePolygons_[0].vertices.resize(3);
299 quadSamplePolygons_[0].vertices[0] = 0;
300 quadSamplePolygons_[0].vertices[1] = 1;
301 quadSamplePolygons_[0].vertices[2] = 2;
302 quadSamplePolygons_[1].vertices.resize(3);
303 quadSamplePolygons_[1].vertices[0] = 0;
304 quadSamplePolygons_[1].vertices[1] = 2;
305 quadSamplePolygons_[1].vertices[2] = 3;
308 env->GetJavaVM(&jvm);
309 RTABMapActivity =
env->NewGlobalRef(caller_activity);
312 LOGI(
"RTABMapApp::RTABMapApp()");
314 progressionStatus_.setJavaObjects(jvm, RTABMapActivity);
316 main_scene_.setBackgroundColor(backgroundColor_, backgroundColor_, backgroundColor_);
320 this->registerToEventsManager();
321 LOGI(
"RTABMapApp::RTABMapApp() end");
330 #ifndef __ANDROID__ // __APPLE__
332 void(*progressCallback)(
void *,
int,
int),
333 void(*initCallback)(
void *,
int,
const char*),
334 void(*statsUpdatedCallback)(
void *,
337 int,
int,
int,
int,
int ,
int,
342 float,
float,
float,
float,
344 float,
float,
float,
float,
float,
float),
345 void(*cameraInfoEventCallback)(
void *,
int,
const char*,
const char*))
356 LOGI(
"~RTABMapApp() begin");
376 LOGI(
"~RTABMapApp() end");
394 LOGW(
"Opening database %s (inMemory=%d, optimize=%d, clearDatabase=%d)", databasePath.c_str(), databaseInMemory?1:0,
optimize?1:0, clearDatabase?1:0);
407 bool restartThread =
false;
445 std::vector<std::vector<std::vector<RTABMAP_PCL_INDEX> > > polygons;
446 #if PCL_VERSION_COMPARE(>=, 1, 8, 0)
447 std::vector<std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > > texCoords;
449 std::vector<std::vector<Eigen::Vector2f> > texCoords;
452 if(!databasePath.empty() &&
UFile::exists(databasePath) && !clearDatabase)
459 if(!cloudMat.empty())
461 LOGI(
"Open: Found optimized mesh! Visualizing it.");
472 LOGI(
"Open: Polygon mesh");
477 LOGI(
"Open: Point cloud");
483 LOGI(
"Open: No optimized mesh found.");
511 LOGI(
"Erasing database \"%s\"...", databasePath.c_str());
521 LOGI(
"Initializing database...");
524 if(parameters.find(rtabmap::Parameters::kRtabmapDetectionRate()) != parameters.end())
530 std::map<int, rtabmap::Signature> signatures;
531 std::map<int, rtabmap::Transform> poses;
532 std::multimap<int, rtabmap::Link> links;
533 LOGI(
"Loading full map from database...");
546 if(signatures.size() && poses.empty())
548 LOGE(
"Failed to optimize the graph!");
553 LOGI(
"Creating the meshes (%d)....", (
int)poses.size());
559 for(std::map<int, rtabmap::Transform>::iterator
iter=poses.begin();
iter!=poses.end() && status>=0; ++
iter)
563 int id =
iter->first;
564 if(!
iter->second.isNull())
570 rawPoses_.insert(std::make_pair(
id, signatures.at(
id).getPose()));
573 data.uncompressData(&tmpA, &depth);
575 if(!(!
data.imageRaw().empty() && !
data.depthRaw().empty()) && !
data.laserScanCompressed().isEmpty())
578 data.uncompressData(0, 0, &scan);
581 if((!
data.imageRaw().empty() && !
data.depthRaw().empty()) || !
data.laserScanRaw().isEmpty())
584 pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud;
585 pcl::IndicesPtr
indices(
new std::vector<int>);
596 indices->resize(cloud->size());
597 for(
unsigned int i=0;
i<cloud->size(); ++
i)
603 if(cloud->size() &&
indices->size())
605 std::vector<pcl::Vertices> polygons;
606 std::vector<pcl::Vertices> polygonsLowRes;
607 #if PCL_VERSION_COMPARE(>=, 1, 8, 0)
608 std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > texCoords;
610 std::vector<Eigen::Vector2f> texCoords;
618 pcl::PolygonMesh::Ptr tmpMesh(
new pcl::PolygonMesh);
619 pcl::toPCLPointCloud2(*cloud, tmpMesh->cloud);
620 tmpMesh->polygons = polygons;
621 rtabmap::util3d::denseMeshPostProcessing<pcl::PointXYZRGB>(tmpMesh,
meshDecimationFactor_, 0, cloud, 0);
622 if(!tmpMesh->polygons.empty())
627 std::map<int, rtabmap::CameraModel> cameraModels;
629 cameraModels.insert(std::make_pair(0,
data.cameraModels()[0]));
634 std::map<int, cv::Mat>());
635 pcl::fromPCLPointCloud2(textureMesh->cloud, *cloud);
636 polygons = textureMesh->tex_polygons[0];
637 texCoords = textureMesh->tex_coordinates[0];
641 pcl::fromPCLPointCloud2(tmpMesh->cloud, *cloud);
642 polygons = tmpMesh->polygons;
645 indices->resize(cloud->size());
646 for(
unsigned int i=0;
i<cloud->size(); ++
i)
656 #ifdef DEBUG_RENDERING_PERFORMANCE
657 LOGW(
"Mesh simplication, %d polygons, %d points (%fs)", (
int)polygons.size(), (
int)cloud->size(),
timer.ticks());
669 inserted.first->second.cloud = cloud;
670 inserted.first->second.indices =
indices;
671 inserted.first->second.polygons = polygons;
672 inserted.first->second.polygonsLowRes = polygonsLowRes;
673 inserted.first->second.visible =
true;
674 inserted.first->second.cameraModel =
data.cameraModels()[0];
675 inserted.first->second.gains[0] = 1.0;
676 inserted.first->second.gains[1] = 1.0;
677 inserted.first->second.gains[2] = 1.0;
680 inserted.first->second.texCoords = texCoords;
684 cv::resize(
data.imageRaw(), inserted.first->second.texture, reducedSize, 0, 0, cv::INTER_LINEAR);
688 inserted.first->second.texture =
data.imageRaw();
691 LOGI(
"Created cloud %d (%fs, %d points)",
id,
timer.ticks(), (
int)cloud->size());
695 UWARN(
"Cloud %d is empty",
id);
698 else if(!
data.depthOrRightCompressed().empty() || !
data.laserScanCompressed().isEmpty())
700 UERROR(
"Failed to uncompress data! (rgb=%d, depth=%d, scan=%d)",
data.imageCompressed().cols,
data.depthOrRightCompressed().cols,
data.laserScanCompressed().size());
706 UWARN(
"Data for node %d not found",
id);
711 UWARN(
"Pose %d is null !?",
id);
722 UERROR(
"Exception! msg=\"%s\"",
e.what());
725 catch (
const cv::Exception &
e)
727 UERROR(
"Exception! msg=\"%s\"",
e.what());
730 catch (
const std::exception &
e)
732 UERROR(
"Exception! msg=\"%s\"",
e.what());
754 LOGI(
"Polygon filtering...");
759 if(
iter->second.polygons.size())
768 LOGI(
"Open: add rtabmap event to update the scene");
773 stats.setPoses(poses);
774 stats.setConstraints(links);
817 if(poses.empty() || status>0)
832 if((height >= 480 || width >= 480) && width % 20 == 0 && height % 20 == 0)
836 else if(width % 15 == 0 && height % 15 == 0)
840 else if(width % 10 == 0 && height % 10 == 0)
844 else if(width % 8 == 0 && height % 8 == 0)
850 UERROR(
"Could not set decimation to high (size=%dx%d)", width, height);
855 if((height >= 480 || width >= 480) && width % 10 == 0 && height % 10 == 0)
859 else if(width % 5 == 0 && height % 5 == 0)
863 else if(width % 4 == 0 && height % 4 == 0)
869 UERROR(
"Could not set decimation to medium (size=%dx%d)", width, height);
874 if((height >= 480 || width >= 480) && width % 5 == 0 && height % 5 == 0)
878 else if(width % 3 == 0 && width % 3 == 0)
882 else if(width % 2 == 0 && width % 2 == 0)
888 UERROR(
"Could not set decimation to low (size=%dx%d)", width, height);
898 if(cameraDriver == 0)
907 if(cameraDriver == 1)
909 #ifdef RTABMAP_ARCORE
916 if(cameraDriver == 2)
918 #ifdef RTABMAP_ARENGINE
939 cameraDriver_ = driver;
943 LOGW(
"startCamera() camera driver=%d", cameraDriver_);
944 boost::mutex::scoped_lock lock(cameraMutex_);
946 if(cameraDriver_ == 0)
949 camera_ =
new rtabmap::CameraTango(cameraColor_, !cameraColor_ || fullResolution_?1:2, rawScanSaved_, smoothing_);
951 if (TangoService_setBinder(
env, iBinder) != TANGO_SUCCESS) {
952 UERROR(
"TangoHandler::ConnectTango, TangoService_setBinder error");
958 UERROR(
"RTAB-Map is not built with Tango support!");
961 else if(cameraDriver_ == 1)
963 #ifdef RTABMAP_ARCORE
964 camera_ =
new rtabmap::CameraARCore(
env, context, activity, depthFromMotion_, smoothing_, upstreamRelocalizationMaxAcc_);
966 UERROR(
"RTAB-Map is not built with ARCore support!");
969 else if(cameraDriver_ == 2)
971 #ifdef RTABMAP_ARENGINE
974 UERROR(
"RTAB-Map is not built with AREngine support!");
977 else if(cameraDriver_ == 3)
984 UERROR(
"Unknown or not supported camera driver! %d", cameraDriver_);
988 if(rtabmapThread_ && dataRecorderMode_)
991 camera_->setFrameRate(rtabmapThread_->getDetectorRate());
992 rtabmapThread_->setDetectorRate(0);
997 camera_->setScreenRotationAndSize(main_scene_.getScreenRotation(), main_scene_.getViewPortWidth(), main_scene_.getViewPortHeight());
1000 LOGI(
"Cloud density level %d", cloudDensityLevel_);
1002 LOGI(
"Start camera thread");
1003 cameraJustInitialized_ =
true;
1004 if(useExternalLidar_)
1008 camera_->setImageRate(0);
1010 sensorCaptureThread_->setScanParameters(
false, 1, 0.0
f, 0.0
f, 0.0
f, 0, 0.0
f, 0.0
f,
true);
1016 sensorCaptureThread_->start();
1019 UERROR(
"Failed camera initialization!");
1025 LOGI(
"stopCamera()");
1045 const std::vector<pcl::Vertices> & polygons,
1046 int cloudSize)
const
1048 std::vector<int> vertexToCluster(cloudSize, 0);
1049 std::map<int, std::list<int> > clusters;
1050 int lastClusterID = 0;
1052 for(
unsigned int i=0;
i<polygons.size(); ++
i)
1055 for(
unsigned int j=0;
j<polygons[
i].vertices.size(); ++
j)
1057 if(vertexToCluster[polygons[
i].
vertices[
j]]>0)
1059 clusterID = vertexToCluster[polygons[
i].vertices[
j]];
1065 clusters.at(clusterID).push_back(
i);
1069 clusterID = ++lastClusterID;
1070 std::list<int> polygons;
1071 polygons.push_back(
i);
1072 clusters.insert(std::make_pair(clusterID, polygons));
1074 for(
unsigned int j=0;
j<polygons[
i].vertices.size(); ++
j)
1076 vertexToCluster[polygons[
i].vertices[
j]] = clusterID;
1080 unsigned int biggestClusterSize = 0;
1081 for(std::map<
int, std::list<int> >::
iterator iter=clusters.begin();
iter!=clusters.end(); ++
iter)
1085 if(
iter->second.size() > biggestClusterSize)
1087 biggestClusterSize =
iter->second.size();
1090 unsigned int minClusterSize = (
unsigned int)(
float(biggestClusterSize)*
clusterRatio_);
1094 std::vector<pcl::Vertices> filteredPolygons(polygons.size());
1096 for(std::map<
int, std::list<int> >::
iterator iter=clusters.begin();
iter!=clusters.end(); ++
iter)
1098 if(
iter->second.size() >= minClusterSize)
1100 for(std::list<int>::iterator jter=
iter->second.begin(); jter!=
iter->second.end(); ++jter)
1102 filteredPolygons[oi++] = polygons[*jter];
1106 filteredPolygons.resize(oi);
1107 return filteredPolygons;
1112 const std::vector<pcl::Vertices> & polygons,
1113 int cloudSize)
const
1116 std::vector<std::set<int> > neighbors;
1117 std::vector<std::set<int> > vertexToPolygons;
1125 unsigned int biggestClusterSize = 0;
1128 if(
iter->size() > biggestClusterSize)
1130 biggestClusterSize =
iter->size();
1133 unsigned int minClusterSize = (
unsigned int)(
float(biggestClusterSize)*
clusterRatio_);
1134 LOGI(
"Biggest cluster = %d -> minClusterSize(ratio=%f)=%d",
1137 std::vector<pcl::Vertices> filteredPolygons(polygons.size());
1139 for(std::list<std::list<int> >::
iterator jter=clusters.begin(); jter!=clusters.end(); ++jter)
1141 if(jter->size() >= minClusterSize)
1143 for(std::list<int>::iterator kter=jter->begin(); kter!=jter->end(); ++kter)
1145 filteredPolygons[oi++] = polygons.at(*kter);
1149 filteredPolygons.resize(oi);
1150 return filteredPolygons;
1200 cv::Mat depth = cv::Mat::zeros(mesh.
cloud->height, mesh.
cloud->width, CV_32FC1);
1202 for(
unsigned int i=0;
i<mesh.
indices->size(); ++
i)
1206 if(mesh.
cloud->at(index).x > 0)
1209 depth.at<
float>(index) = pt.z;
1214 LOGI(
"smoothMesh() Bilateral filtering of %d, time=%fs",
id,
t.ticks());
1216 if(!depth.empty() && mesh.
indices->size())
1218 pcl::IndicesPtr newIndices(
new std::vector<int>(mesh.
indices->size()));
1220 for(
unsigned int i=0;
i<mesh.
indices->size(); ++
i)
1224 pcl::PointXYZRGB & pt = mesh.
cloud->at(index);
1226 if(depth.at<
float>(index) > 0)
1228 newPt.z = depth.at<
float>(index);
1230 newIndices->at(oi++) = index;
1234 newPt.x = newPt.y = newPt.z = std::numeric_limits<float>::quiet_NaN();
1240 newIndices->resize(oi);
1244 std::vector<pcl::Vertices> polygons;
1249 LOGI(
"smoothMesh() Reconstructing the mesh of %d, time=%fs",
id,
t.ticks());
1254 UERROR(
"smoothMesh() Failed to smooth surface %d",
id);
1262 UTimer tGainCompensation;
1263 LOGI(
"Gain compensation...");
1266 std::map<int, pcl::PointCloud<pcl::PointXYZRGB>::Ptr > clouds;
1267 std::map<int, pcl::IndicesPtr>
indices;
1270 clouds.insert(std::make_pair(
iter->first,
iter->second.cloud));
1273 std::map<int, rtabmap::Transform> poses;
1274 std::multimap<int, rtabmap::Link> links;
1280 for(std::map<
int, pcl::PointCloud<pcl::PointXYZRGB>::Ptr>::const_iterator
iter=clouds.begin();
iter!=clouds.end(); ++
iter)
1282 int from =
iter->first;
1283 std::map<int, pcl::PointCloud<pcl::PointXYZRGB>::Ptr>::const_iterator jter =
iter;
1285 for(;jter!=clouds.end(); ++jter)
1287 int to = jter->first;
1295 if(clouds.size() > 1 && links.size())
1298 LOGI(
"Gain compensation... compute gain: links=%d, time=%fs", (
int)links.size(), tGainCompensation.
ticks());
1303 if(!
iter->second.cloud->empty())
1305 if(clouds.size() > 1 && links.size())
1308 LOGI(
"%d mesh has gain %f,%f,%f",
iter->first,
iter->second.gains[0],
iter->second.gains[1],
iter->second.gains[2]);
1312 LOGI(
"Gain compensation... applying gain: meshes=%d, time=%fs", (
int)
createdMeshes_.size(), tGainCompensation.
ticks());
1318 std::list<rtabmap::RtabmapEvent*> rtabmapEvents;
1327 #ifdef DEBUG_RENDERING_PERFORMANCE
1332 bool notifyDataLoaded =
false;
1333 bool notifyCameraStarted =
false;
1341 const float* uvsTransformed = 0;
1354 #ifdef DEBUG_RENDERING_PERFORMANCE
1355 LOGD(
"Camera updateOnRender %fs",
time.ticks());
1380 pcl::IndicesPtr
indices(
new std::vector<int>);
1384 occlusionMesh.
cloud.reset(
new pcl::PointCloud<pcl::PointXYZRGB>());
1385 pcl::copyPointCloud(*cloud, *occlusionMesh.
cloud);
1389 else if(!occlusionImage.empty())
1391 UERROR(
"invalid occlusionModel: %f %f %f %f %dx%d", occlusionModel.
fx(), occlusionModel.
fy(), occlusionModel.
cx(), occlusionModel.
cy(), occlusionModel.
imageWidth(), occlusionModel.
imageHeight());
1394 #ifdef DEBUG_RENDERING_PERFORMANCE
1395 LOGD(
"Update background and occlusion mesh %fs",
time.ticks());
1416 LOGI(
"Process sensor events");
1421 notifyCameraStarted =
true;
1440 notifyCameraStarted =
true;
1456 LOGI(
"Adding optimized mesh to opengl (%d points, %d polygons, %d tex_coords, materials=%d texture=%dx%d)...",
1466 optMesh_.
cloud.reset(
new pcl::PointCloud<pcl::PointXYZRGB>);
1470 bool hasColors =
false;
1498 pcl::IndicesPtr
indices(
new std::vector<int>);
1499 pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud(
new pcl::PointCloud<pcl::PointXYZRGB>);
1529 std::list<Measure> measures =
measures_;
1539 float sphereRadius = 0.02f;
1540 float quadSize=0.05f;
1541 float quadAlpha = 0.3f;
1548 float restrictiveSnapThr = 0.9999;
1549 for(std::list<Measure>::iterator
iter=measures.begin();
iter!=measures.end(); ++
iter)
1553 bool sameNormal =
false;
1554 if(
iter->n1().dot(
iter->n2()) > 0.99)
1557 Eigen::Vector3f
n(
iter->n1()[0],
iter->n1()[1],
iter->n1()[2]);
1561 if(
fabs(n1ProdX) > restrictiveSnapThr)
1565 else if(
fabs(n1ProdY) > restrictiveSnapThr)
1569 else if(
fabs(n1ProdZ) > restrictiveSnapThr)
1576 LOGI(
"dist=%f, %f,%f,%f -> %f,%f,%f",
m.length(),
1577 m.pt1().x,
m.pt1().y,
m.pt1().z,
1578 m.pt2().x,
m.pt2().y,
m.pt2().z);
1583 if (
fabs(
iter->n1()[2]) < 0.00001 && sameNormal)
1586 cv::Point3f
n = cv::Vec3f(0,0,1).cross(
iter->n1());
1589 cv::Point3f pa = pt1 +
n;
1590 cv::Point3f pb = pt1 -
n;
1592 cv::Point3f
pc = pt2 +
n;
1593 cv::Point3f pd = pt2 -
n;
1597 float diff =
m.length();
1601 static const double METERS_PER_FOOT = 0.3048;
1602 static double INCHES_PER_FOOT = 12.0;
1603 double lengthInFeet =
diff / METERS_PER_FOOT;
1604 int feet = (
int)lengthInFeet;
1605 float inches = (lengthInFeet - feet) * INCHES_PER_FOOT;
1620 q1.setFromTwoVectors(Eigen::Vector3f(0,0,1), Eigen::Vector3f(
n1[0],
n1[1],
n1[2]));
1621 q2.setFromTwoVectors(Eigen::Vector3f(0,0,1), Eigen::Vector3f(
n2[0],
n2[1],
n2[2]));
1625 main_scene_.
addQuad(++quadId, quadSize,
rtabmap::Transform(pt1.x, pt1.y, pt1.z, q1.x(), q1.y(), q1.z(), q1.w()), quadColor, quadAlpha);
1626 main_scene_.
addQuad(++quadId, quadSize,
rtabmap::Transform(pt2.x, pt2.y, pt2.z, q2.x(), q2.y(), q2.z(), q2.w()), quadColor, quadAlpha);
1630 main_scene_.
addCircle(++circleId, quadSize/2,
rtabmap::Transform(pt1.x, pt1.y, pt1.z, q1.x(), q1.y(), q1.z(), q1.w()), quadColor, quadAlpha);
1631 main_scene_.
addCircle(++circleId, quadSize/2,
rtabmap::Transform(pt2.x, pt2.y, pt2.z, q2.x(), q2.y(), q2.z(), q2.w()), quadColor, quadAlpha);
1643 if(rtabmapEvents.size())
1646 if(!
stats.mapCorrection().isNull())
1651 std::map<int, rtabmap::Transform>::const_iterator
iter =
stats.poses().find(
optRefId_);
1657 int fastMovement = (
int)
uValue(
stats.data(), rtabmap::Statistics::kMemoryFast_movement(), 0.0f);
1658 int loopClosure = (
int)
uValue(
stats.data(), rtabmap::Statistics::kLoopAccepted_hypothesis_id(), 0.0f);
1659 int proximityClosureId =
int(
uValue(
stats.data(), rtabmap::Statistics::kProximitySpace_last_detection_id(), 0.0f));
1660 int rejected = (
int)
uValue(
stats.data(), rtabmap::Statistics::kLoopRejectedHypothesis(), 0.0f);
1661 int landmark = (
int)
uValue(
stats.data(), rtabmap::Statistics::kLoopLandmark_detected(), 0.0f);
1695 for(std::map<int, rtabmap::Transform>::const_iterator
iter=
stats.poses().begin();
1699 int id =
iter->first;
1730 if(rtabmapEvents.size())
1733 if(rtabmapEvents.back()->getStats().refImageId()>0 ||
1734 !rtabmapEvents.back()->getStats().data().empty())
1737 rtabmapEvents.pop_back();
1740 for(std::list<rtabmap::RtabmapEvent*>::iterator
iter=rtabmapEvents.begin();
iter!=rtabmapEvents.end(); ++
iter)
1744 rtabmapEvents.clear();
1771 if(rtabmapEvents.front()->getStats().refImageId()>0 && rtabmapEvents.front()->getStats().refImageId() <
createdMeshes_.rbegin()->first)
1773 LOGI(
"Detected new database! new=%d old=%d", rtabmapEvents.front()->getStats().refImageId(),
createdMeshes_.rbegin()->first);
1778 #ifdef DEBUG_RENDERING_PERFORMANCE
1779 if(rtabmapEvents.size())
1781 LOGW(
"begin and getting rtabmap events %fs",
time.ticks());
1788 LOGI(
"Clearing all rendering data...");
1802 LOGI(
"Clearing meshes...");
1808 notifyDataLoaded =
true;
1828 if(added.size() != meshes)
1830 LOGI(
"added (%d) != meshes (%d)", (
int)added.size(), meshes);
1837 LOGI(
"Re-add mesh %d to OpenGL context",
iter->first);
1848 if(!textureRaw.empty())
1853 LOGD(
"resize image from %dx%d to %dx%d", textureRaw.cols, textureRaw.rows, reducedSize.width, reducedSize.height);
1854 cv::resize(textureRaw,
iter->second.texture, reducedSize, 0, 0, cv::INTER_LINEAR);
1858 iter->second.texture = textureRaw;
1865 iter->second.texture = cv::Mat();
1870 else if(notifyDataLoaded)
1879 if(rtabmapEvents.size())
1881 #ifdef DEBUG_RENDERING_PERFORMANCE
1882 LOGW(
"Process rtabmap events %fs",
time.ticks());
1884 LOGI(
"Process rtabmap events");
1888 std::map<int, rtabmap::SensorData> bufferedSensorData;
1891 for(std::list<rtabmap::RtabmapEvent*>::iterator
iter=rtabmapEvents.begin();
iter!=rtabmapEvents.end(); ++
iter)
1896 int smallMovement = (
int)
uValue(
stats.data(), rtabmap::Statistics::kMemorySmall_movement(), 0.0f);
1897 int fastMovement = (
int)
uValue(
stats.data(), rtabmap::Statistics::kMemoryFast_movement(), 0.0f);
1898 int rehearsalMerged = (
int)
uValue(
stats.data(), rtabmap::Statistics::kMemoryRehearsal_merged(), 0.0f);
1900 smallMovement == 0 && rehearsalMerged == 0 && fastMovement == 0)
1902 int id =
stats.getLastSignatureData().id();
1906 ((!
s.sensorData().imageRaw().empty() && !
s.sensorData().depthRaw().empty()) ||
1907 !
s.sensorData().laserScanRaw().isEmpty()))
1909 uInsert(bufferedSensorData, std::make_pair(
id,
s.sensorData()));
1915 int loopClosure = (
int)
uValue(
stats.data(), rtabmap::Statistics::kLoopAccepted_hypothesis_id(), 0.0f);
1916 int proximityClosureId =
int(
uValue(
stats.data(), rtabmap::Statistics::kProximitySpace_last_detection_id(), 0.0f));
1917 int rejected = (
int)
uValue(
stats.data(), rtabmap::Statistics::kLoopRejectedHypothesis(), 0.0f);
1918 int landmark = (
int)
uValue(
stats.data(), rtabmap::Statistics::kLoopLandmark_detected(), 0.0f);
1950 #ifdef DEBUG_RENDERING_PERFORMANCE
1951 LOGW(
"Looking for data to load (%d) %fs", (
int)bufferedSensorData.size(),
time.ticks());
1954 std::map<int, rtabmap::Transform> posesWithMarkers = rtabmapEvents.back()->getStats().poses();
1955 if(!rtabmapEvents.back()->getStats().mapCorrection().isNull())
1957 mapToOdom_ = rtabmapEvents.back()->getStats().mapCorrection();
1961 for(std::map<int, rtabmap::Transform>::iterator
iter=posesWithMarkers.begin();
iter!=posesWithMarkers.end(); ++
iter)
1965 std::map<int, rtabmap::Transform>::iterator jter =
rawPoses_.find(
iter->first);
1977 std::map<int, rtabmap::Transform> poses(posesWithMarkers.lower_bound(0), posesWithMarkers.end());
1978 const std::multimap<int, rtabmap::Link> & links = rtabmapEvents.back()->getStats().constraints();
1984 #ifdef DEBUG_RENDERING_PERFORMANCE
1985 LOGW(
"Update graph: %fs",
time.ticks());
1990 std::set<std::string> strIds;
1991 for(std::map<int, rtabmap::Transform>::iterator
iter=poses.begin();
iter!=poses.end(); ++
iter)
1993 int id =
iter->first;
1994 if(!
iter->second.isNull())
2001 std::map<int, rtabmap::Mesh>::iterator meshIter =
createdMeshes_.find(
id);
2004 meshIter->second.visible =
true;
2009 bufferedSensorData.find(
id) != bufferedSensorData.end())
2013 cv::Mat tmpA, depth;
2014 data.uncompressData(&tmpA, &depth);
2015 if(!(!
data.imageRaw().empty() && !
data.depthRaw().empty()) && !
data.laserScanCompressed().isEmpty())
2018 data.uncompressData(0, 0, &scan);
2020 #ifdef DEBUG_RENDERING_PERFORMANCE
2021 LOGW(
"Decompressing data: %fs",
time.ticks());
2024 if((!
data.imageRaw().empty() && !
data.depthRaw().empty()) || !
data.laserScanRaw().isEmpty())
2027 pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud;
2028 pcl::IndicesPtr
indices(
new std::vector<int>);
2038 indices->resize(cloud->size());
2039 for(
unsigned int i=0;
i<cloud->size(); ++
i)
2044 #ifdef DEBUG_RENDERING_PERFORMANCE
2045 LOGW(
"Creating node cloud %d (depth=%dx%d rgb=%dx%d, %fs)",
id,
data.depthRaw().cols,
data.depthRaw().rows,
data.imageRaw().cols,
data.imageRaw().rows,
time.ticks());
2047 if(cloud->size() &&
indices->size())
2049 std::vector<pcl::Vertices> polygons;
2050 std::vector<pcl::Vertices> polygonsLowRes;
2051 #if PCL_VERSION_COMPARE(>=, 1, 8, 0)
2052 std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > texCoords;
2054 std::vector<Eigen::Vector2f> texCoords;
2056 pcl::PointCloud<pcl::Normal>::Ptr normals(
new pcl::PointCloud<pcl::Normal>);
2060 #ifdef DEBUG_RENDERING_PERFORMANCE
2061 LOGW(
"Creating mesh, %d polygons (%fs)", (
int)polygons.size(),
time.ticks());
2066 pcl::PolygonMesh::Ptr tmpMesh(
new pcl::PolygonMesh);
2067 pcl::toPCLPointCloud2(*cloud, tmpMesh->cloud);
2068 tmpMesh->polygons = polygons;
2069 rtabmap::util3d::denseMeshPostProcessing<pcl::PointXYZRGB>(tmpMesh,
meshDecimationFactor_, 0, cloud, 0);
2071 if(!tmpMesh->polygons.empty())
2076 std::map<int, rtabmap::CameraModel> cameraModels;
2078 cameraModels.insert(std::make_pair(0,
data.cameraModels()[0]));
2083 std::map<int, cv::Mat>());
2084 pcl::fromPCLPointCloud2(textureMesh->cloud, *cloud);
2085 polygons = textureMesh->tex_polygons[0];
2086 texCoords = textureMesh->tex_coordinates[0];
2090 pcl::fromPCLPointCloud2(tmpMesh->cloud, *cloud);
2091 polygons = tmpMesh->polygons;
2094 indices->resize(cloud->size());
2095 for(
unsigned int i=0;
i<cloud->size(); ++
i)
2104 #ifdef DEBUG_RENDERING_PERFORMANCE
2105 LOGW(
"Creating mesh, %d polygons (%fs)", (
int)polygons.size(),
time.ticks());
2108 #ifdef DEBUG_RENDERING_PERFORMANCE
2109 LOGW(
"Mesh simplication, %d polygons, %d points (%fs)", (
int)polygons.size(), (
int)cloud->size(),
time.ticks());
2116 #ifdef DEBUG_RENDERING_PERFORMANCE
2117 LOGW(
"Creating mesh, %d polygons (%fs)", (
int)polygons.size(),
time.ticks());
2124 inserted.first->second.cloud = cloud;
2125 inserted.first->second.indices =
indices;
2126 inserted.first->second.polygons = polygons;
2127 inserted.first->second.polygonsLowRes = polygonsLowRes;
2128 inserted.first->second.visible =
true;
2129 inserted.first->second.cameraModel =
data.cameraModels()[0];
2130 inserted.first->second.gains[0] = 1.0;
2131 inserted.first->second.gains[1] = 1.0;
2132 inserted.first->second.gains[2] = 1.0;
2135 inserted.first->second.texCoords = texCoords;
2139 cv::resize(
data.imageRaw(), inserted.first->second.texture, reducedSize, 0, 0, cv::INTER_LINEAR);
2140 #ifdef DEBUG_RENDERING_PERFORMANCE
2141 LOGW(
"resize image from %dx%d to %dx%d (%fs)",
data.imageRaw().cols,
data.imageRaw().rows, reducedSize.width, reducedSize.height,
time.ticks());
2146 inserted.first->second.texture =
data.imageRaw();
2159 #ifdef DEBUG_RENDERING_PERFORMANCE
2160 LOGW(
"Adding mesh to scene: %fs",
time.ticks());
2170 if(poses.size() > 2)
2174 for(std::multimap<int, rtabmap::Link>::const_iterator
iter=links.begin();
iter!=links.end(); ++
iter)
2178 int oldId =
iter->second.to()>
iter->second.from()?
iter->second.from():
iter->second.to();
2190 for(std::set<int>::const_iterator
iter=addedClouds.begin();
2191 iter!=addedClouds.end();
2194 if(*
iter > 0 && poses.find(*
iter) == poses.end())
2199 meshIter->second.visible =
false;
2206 for(std::set<int>::const_iterator
iter=addedMarkers.begin();
2207 iter!=addedMarkers.end();
2210 if(posesWithMarkers.find(*
iter) == posesWithMarkers.end())
2215 for(std::map<int, rtabmap::Transform>::const_iterator
iter=posesWithMarkers.begin();
2216 iter!=posesWithMarkers.end() &&
iter->first<0;
2219 int id =
iter->first;
2243 pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud;
2244 pcl::IndicesPtr
indices(
new std::vector<int>);
2254 indices->resize(cloud->size());
2255 for(
unsigned int i=0;
i<cloud->size(); ++
i)
2261 if(cloud->size() &&
indices->size())
2263 LOGI(
"Created odom cloud (rgb=%dx%d depth=%dx%d cloud=%dx%d)",
2266 (
int)cloud->width, (
int)cloud->height);
2272 UERROR(
"Generated cloud is empty!");
2277 UWARN(
"Odom data images/scans are empty!");
2291 notifyDataLoaded =
true;
2296 LOGI(
"Bilateral filtering...");
2301 if(
iter->second.cloud->size() &&
iter->second.indices->size())
2309 notifyDataLoaded =
true;
2314 LOGI(
"Polygon filtering...");
2320 if(
iter->second.polygons.size())
2327 notifyDataLoaded =
true;
2338 if(rtabmapEvents.size())
2342 if(rtabmapEvents.back()->getStats().refImageId()>0 ||
2343 !rtabmapEvents.back()->getStats().data().empty())
2346 rtabmapEvents.pop_back();
2349 for(std::list<rtabmap::RtabmapEvent*>::iterator
iter=rtabmapEvents.begin();
iter!=rtabmapEvents.end(); ++
iter)
2353 rtabmapEvents.clear();
2359 UERROR(
"TangoPoseEventNotReceived");
2370 cv::Mat image(
h,
w, CV_8UC4);
2371 glReadPixels(0, 0,
w,
h, GL_RGBA, GL_UNSIGNED_BYTE, image.data);
2372 cv::flip(image, image, 0);
2373 cv::cvtColor(image, image, cv::COLOR_RGBA2BGRA);
2386 LOGI(
"Saving screenshot %dx%d...", roi.cols, roi.rows);
2395 double updateInterval = 1.0;
2405 if(interval >= updateInterval)
2416 return notifyDataLoaded||notifyCameraStarted?1:0;
2420 for(std::list<rtabmap::RtabmapEvent*>::iterator
iter=rtabmapEvents.begin();
iter!=rtabmapEvents.end(); ++
iter)
2424 rtabmapEvents.clear();
2425 UERROR(
"Exception! msg=\"%s\"",
e.what());
2428 catch(
const cv::Exception &
e)
2430 for(std::list<rtabmap::RtabmapEvent*>::iterator
iter=rtabmapEvents.begin();
iter!=rtabmapEvents.end(); ++
iter)
2434 rtabmapEvents.clear();
2435 UERROR(
"Exception! msg=\"%s\"",
e.what());
2438 catch(
const std::exception &
e)
2440 for(std::list<rtabmap::RtabmapEvent*>::iterator
iter=rtabmapEvents.begin();
iter!=rtabmapEvents.end(); ++
iter)
2444 rtabmapEvents.clear();
2445 UERROR(
"Exception! msg=\"%s\"",
e.what());
2454 Eigen::Vector3f
origin(openglCam.
x(), openglCam.
y(), openglCam.
z());
2455 Eigen::Vector3f rtabmapOrigin(rtabmapCam.
x(), rtabmapCam.
y(), rtabmapCam.
z());
2457 Eigen::Vector3f dir(
v.x(),
v.y(),
v.z());
2459 Eigen::Vector3f rtabmapDir(
v.x(),
v.y(),
v.z());
2464 float circleRadius = 0.025;
2465 float quadSize=0.05f;
2466 float quadAlpha = 0.3f;
2484 bool removed =
false;
2489 for(
int i=0;
i<2;++
i)
2492 cv::Point3f pt =
i==0?
m.pt1():
m.pt2();
2493 cv::Point3f
n =
i==0?
m.n1():
m.n2();
2497 q.setFromTwoVectors(Eigen::Vector3f(0,0,-1), Eigen::Vector3f(
n.x,
n.y,
n.z));
2499 Eigen::Vector3f nTmp;
2537 cv::Point3f pt(intersectionPt[0], intersectionPt[1], intersectionPt[2]);
2629 if(measure.
length()>=0.01f)
2678 float quadWidthLeft = 0.05;
2679 float quadWidthRight = quadWidthLeft;
2680 float quadHeightBottom = quadWidthLeft;
2681 float quadHeightTop = quadWidthLeft;
2682 cv::Point3f pt2 = pt;
2683 float lineLength = 0.0f;
2691 lineLength =
fabs(
n);
2696 quadHeightTop =
v.z>quadSize?
v.z:quadSize;
2697 quadHeightBottom = -
v.z>quadSize?-
v.z:quadSize;
2700 cv::Point3f
y = cv::Point3f(0,0,1).cross(
normal);
2702 quadWidthRight =
n>quadSize?
n:quadSize;
2703 quadWidthLeft =
n<-quadSize?
fabs(
n):quadSize;
2706 quadWidthLeft =
n>quadSize?
n:quadSize;
2707 quadWidthRight =
n<-quadSize?
fabs(
n):quadSize;
2708 float tmp =quadHeightTop;
2709 quadHeightTop= quadHeightBottom;
2710 quadHeightBottom = tmp;
2715 cv::Point3f
x =
normal.cross(cv::Point3f(0,0,1));
2717 quadWidthRight =
n<-quadSize?
fabs(
n):quadSize;
2718 quadWidthLeft =
n>quadSize?
n:quadSize;
2725 quadHeightBottom =
v.x<-quadSize?
fabs(
v.x):quadSize;
2726 quadHeightTop =
v.x>quadSize?
v.x:quadSize;
2727 quadWidthRight =
v.y<-quadSize?
fabs(
v.y):quadSize;
2728 quadWidthLeft =
v.y>quadSize?
v.y:quadSize;
2732 quadHeightTop =
v.x<-quadSize?
fabs(
v.x):quadSize;
2733 quadHeightBottom =
v.x>quadSize?
v.x:quadSize;
2734 quadWidthRight =
v.y<-quadSize?
fabs(
v.y):quadSize;
2735 quadWidthLeft =
v.y>quadSize?
v.y:quadSize;
2741 lineLength = cv::norm(
v);
2744 std::string
text =
uFormat(
"%0.2f m", lineLength);
2747 static const double METERS_PER_FOOT = 0.3048;
2748 static double INCHES_PER_FOOT = 12.0;
2749 double lengthInFeet = lineLength / METERS_PER_FOOT;
2750 int feet = (
int)lengthInFeet;
2751 float inches = (lengthInFeet - feet) * INCHES_PER_FOOT;
2765 q.setFromTwoVectors(Eigen::Vector3f(0,0,1), Eigen::Vector3f(normalGl.x,normalGl.y,normalGl.z));
2777 q1.setFromTwoVectors(Eigen::Vector3f(0,0,1), Eigen::Vector3f(normalGL1[0],normalGL1[0],normalGL1[0]));
2784 q1.x(),q1.y(), q1.z(), q1.w()), color, quadAlpha);
2798 q.x(),
q.y(),
q.z(),
q.w()), quadColor, quadAlpha);
2846 float x0,
float y0,
float x1,
float y1) {
2953 std::map<int, rtabmap::Transform> poses;
2954 std::multimap<int, rtabmap::Link> links;
2960 stats.setPoses(poses);
2961 stats.setConstraints(links);
2963 LOGI(
"Send rtabmap event to update graph...");
3119 #if defined(RTABMAP_PDAL) || defined(RTABMAP_LIBLAS)
3126 UERROR(
"Not supported point cloud format %s",
format.c_str());
3135 std::string compatibleKey =
key;
3141 if(
iter->second.first)
3144 compatibleKey =
iter->second.second;
3145 LOGW(
"Parameter name changed: \"%s\" -> \"%s\". Please update the code accordingly. Value \"%s\" is still set to the new parameter name.",
3146 iter->first.c_str(),
iter->second.second.c_str(),
value.c_str());
3150 if(
iter->second.second.empty())
3152 UERROR(
"Parameter \"%s\" doesn't exist anymore!",
3153 iter->first.c_str());
3157 UERROR(
"Parameter \"%s\" doesn't exist anymore! You may look at this similar parameter: \"%s\"",
3158 iter->first.c_str(),
iter->second.second.c_str());
3165 LOGI(
"%s",
uFormat(
"Setting param \"%s\" to \"%s\"", compatibleKey.c_str(),
value.c_str()).c_str());
3172 UERROR(
uFormat(
"Key \"%s\" doesn't exist!", compatibleKey.c_str()).c_str());
3197 LOGI(
"Saving database to %s", databasePath.c_str());
3201 LOGI(
"Taking screenshot...");
3205 UERROR(
"Failed to take a screenshot after 2 sec!");
3227 if(appendModeBackup || dataRecorderModeBackup || localizationModeBackup)
3252 std::string errorMsg;
3255 LOGE(
"Recovery Error: %s", errorMsg.c_str());
3260 LOGI(
"Renaming %s to %s", from.c_str(), to.c_str());
3263 LOGE(
"Failed renaming %s to %s", from.c_str(), to.c_str());
3272 UWARN(
"Processing canceled!");
3277 float cloudVoxelSize,
3278 bool regenerateCloud,
3284 float optimizedVoxelSize,
3286 int optimizedMaxPolygons,
3287 float optimizedColorRadius,
3288 bool optimizedCleanWhitePolygons,
3289 int optimizedMinClusterSize,
3290 float optimizedMaxTextureDistance,
3291 int optimizedMinTextureClusterSize,
3292 int textureVertexColorPolicy,
3293 bool blockRendering)
3302 std::multimap<int, rtabmap::Link> links;
3310 UERROR(
"Empty optimized poses!");
3324 bool success =
false;
3329 totalSteps+=poses.size();
3334 totalSteps += poses.size();
3340 if(optimizedMaxPolygons > 0)
3350 totalSteps+=poses.size()+1;
3355 totalSteps += poses.size()+1;
3365 pcl::PolygonMesh::Ptr polygonMesh(
new pcl::PolygonMesh);
3366 pcl::TextureMesh::Ptr textureMesh(
new pcl::TextureMesh);
3367 std::vector<std::map<int, pcl::PointXY> > vertexToPixels;
3368 cv::Mat globalTextures;
3369 int totalPolygons = 0;
3374 std::map<int, rtabmap::CameraModel> cameraModels;
3375 std::map<int, cv::Mat> cameraDepths;
3378 LOGI(
"Assemble clouds (%d)...", (
int)poses.size());
3382 pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr mergedClouds(
new pcl::PointCloud<pcl::PointXYZRGBNormal>);
3383 for(std::map<int, rtabmap::Transform>::iterator
iter=poses.begin();
3388 pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud(
new pcl::PointCloud<pcl::PointXYZRGB>);
3389 pcl::IndicesPtr
indices(
new std::vector<int>);
3393 gains[0] = gains[1] = gains[2] = 1.0f;
3396 cloud = jter->second.cloud;
3397 indices = jter->second.indices;
3398 model = jter->second.cameraModel;
3399 gains[0] = jter->second.gains[0];
3400 gains[1] = jter->second.gains[1];
3401 gains[2] = jter->second.gains[2];
3404 data.uncompressData(0, &depth);
3409 data.uncompressData();
3410 if(!
data.imageRaw().empty() && !
data.depthRaw().empty() &&
data.cameraModels().size() == 1)
3415 depth =
data.depthRaw();
3418 if(cloud->size() &&
indices->size() &&
model.isValidForProjection())
3420 pcl::PointCloud<pcl::PointXYZRGB>::Ptr transformedCloud(
new pcl::PointCloud<pcl::PointXYZRGB>);
3421 if(optimizedVoxelSize > 0.0
f)
3430 pcl::copyPointCloud(*cloud, *
indices, *transformedCloud);
3434 Eigen::Vector3f viewpoint(
iter->second.x(),
iter->second.y(),
iter->second.z());
3437 pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr cloudWithNormals(
new pcl::PointCloud<pcl::PointXYZRGBNormal>);
3438 pcl::concatenateFields(*transformedCloud, *normals, *cloudWithNormals);
3440 if(textureSize == 0 && (gains[0] != 1.0 || gains[1] != 1.0 || gains[2] != 1.0))
3442 for(
unsigned int i=0;
i<cloudWithNormals->size(); ++
i)
3444 pcl::PointXYZRGBNormal & pt = cloudWithNormals->at(
i);
3452 if(mergedClouds->size() == 0)
3454 *mergedClouds = *cloudWithNormals;
3458 *mergedClouds += *cloudWithNormals;
3462 cameraModels.insert(std::make_pair(
iter->first,
model));
3465 cameraDepths.insert(std::make_pair(
iter->first, depth));
3468 LOGI(
"Assembled %d points (%d/%d total=%d)", (
int)cloudWithNormals->size(), ++cloudCount, (
int)poses.size(), (
int)mergedClouds->size());
3472 UERROR(
"Cloud %d not found or empty",
iter->first);
3486 LOGI(
"Assembled clouds (%d)... done! %fs (total points=%d)", (
int)
cameraPoses.size(),
timer.ticks(), (
int)mergedClouds->size());
3488 if(mergedClouds->size()>=3)
3490 if(optimizedDepth == 0)
3495 optimizedDepth = 12;
3496 for(
int i=6;
i<12; ++
i)
3498 if(mapLength/
float(1<<
i) < 0.03
f)
3504 LOGI(
"optimizedDepth=%d (map length=%f)", optimizedDepth, mapLength);
3508 LOGI(
"Mesh reconstruction...");
3509 pcl::PolygonMesh::Ptr mesh(
new pcl::PolygonMesh);
3510 pcl::Poisson<pcl::PointXYZRGBNormal> poisson;
3511 poisson.setDepth(optimizedDepth);
3512 poisson.setInputCloud(mergedClouds);
3513 poisson.reconstruct(*mesh);
3514 LOGI(
"Mesh reconstruction... done! %fs (%d polygons)",
timer.ticks(), (
int)mesh->polygons.size());
3528 if(mesh->polygons.size())
3530 totalPolygons=(
int)mesh->polygons.size();
3532 if(optimizedMaxPolygons > 0 && optimizedMaxPolygons < (
int)mesh->polygons.size())
3535 unsigned int count = mesh->polygons.size();
3537 LOGI(
"Mesh decimation (max polygons %d/%d -> factor=%f)...", optimizedMaxPolygons, (
int)
count,
factor);
3541 pcl::PolygonMesh::Ptr output(
new pcl::PolygonMesh);
3542 pcl::MeshQuadricDecimationVTK mqd;
3543 mqd.setTargetReductionFactor(
factor);
3544 mqd.setInputMesh(mesh);
3545 mqd.process (*output);
3553 LOGI(
"Mesh decimated (factor=%f) from %d to %d polygons (%fs)",
factor,
count, (
int)mesh->polygons.size(),
timer.ticks());
3554 if(count < mesh->polygons.size())
3556 UWARN(
"Decimated mesh has more polygons than before!");
3559 UWARN(
"RTAB-Map is not built with PCL-VTK module so mesh decimation cannot be used!");
3575 rtabmap::util3d::denseMeshPostProcessing<pcl::PointXYZRGBNormal>(
3580 optimizedColorRadius,
3581 !(textureSize > 0 && textureVertexColorPolicy == 0),
3582 optimizedCleanWhitePolygons,
3583 optimizedMinClusterSize);
3587 LOGI(
"Texturing... cameraPoses=%d, cameraDepths=%d", (
int)
cameraPoses.size(), (
int)cameraDepths.size());
3593 optimizedMaxTextureDistance,
3596 optimizedMinTextureClusterSize,
3597 std::vector<float>(),
3600 LOGI(
"Texturing... done! %fs",
timer.ticks());
3613 if(textureMesh->tex_coordinates.size() && optimizedCleanWhitePolygons)
3615 LOGI(
"Cleanup mesh...");
3617 LOGI(
"Cleanup mesh... done! %fs",
timer.ticks());
3621 for(
unsigned int t=0;
t<textureMesh->tex_polygons.size(); ++
t)
3623 totalPolygons+=textureMesh->tex_polygons[
t].size();
3628 totalPolygons = (
int)mesh->polygons.size();
3635 UERROR(
"Merged cloud too small (%d points) to create polygons!", (
int)mergedClouds->size());
3640 pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr mergedClouds(
new pcl::PointCloud<pcl::PointXYZRGBNormal>);
3644 textureMesh->tex_materials.resize(poses.size());
3645 textureMesh->tex_polygons.resize(poses.size());
3646 textureMesh->tex_coordinates.resize(poses.size());
3649 int polygonsStep = 0;
3651 for(std::map<int, rtabmap::Transform>::iterator
iter=poses.begin();
3655 LOGI(
"Assembling cloud %d (total=%d)...",
iter->first, (
int)poses.size());
3658 pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud(
new pcl::PointCloud<pcl::PointXYZRGB>);
3659 std::vector<pcl::Vertices> polygons;
3660 float gains[3] = {1.0f};
3663 cloud = jter->second.cloud;
3664 polygons= jter->second.polygons;
3665 if(cloud->size() && polygons.size() == 0)
3669 gains[0] = jter->second.gains[0];
3670 gains[1] = jter->second.gains[1];
3671 gains[2] = jter->second.gains[2];
3676 data.uncompressData();
3677 if(!
data.imageRaw().empty() && !
data.depthRaw().empty() &&
data.cameraModels().size() == 1)
3685 if(cloud->size() && polygons.size())
3688 pcl::PointCloud<pcl::PointXYZRGB>::Ptr outputCloud(
new pcl::PointCloud<pcl::PointXYZRGB>);
3689 std::vector<pcl::Vertices> outputPolygons;
3694 pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr cloudWithNormals(
new pcl::PointCloud<pcl::PointXYZRGBNormal>);
3695 pcl::concatenateFields(*outputCloud, *normals, *cloudWithNormals);
3697 UASSERT(outputPolygons.size());
3699 totalPolygons+=outputPolygons.size();
3701 if(textureSize == 0)
3706 if(gains[0] != 1.0
f || gains[1] != 1.0
f || gains[2] != 1.0
f)
3708 for(
unsigned int i=0;
i<cloudWithNormals->size(); ++
i)
3710 pcl::PointXYZRGBNormal & pt = cloudWithNormals->at(
i);
3717 if(mergedClouds->size() == 0)
3719 *mergedClouds = *cloudWithNormals;
3720 polygonMesh->polygons = outputPolygons;
3730 size_t polygonSize = outputPolygons.front().vertices.size();
3731 textureMesh->tex_polygons[oi].resize(outputPolygons.size());
3732 textureMesh->tex_coordinates[oi].resize(outputPolygons.size() * polygonSize);
3733 for(
unsigned int j=0;
j<outputPolygons.size(); ++
j)
3735 pcl::Vertices
vertices = outputPolygons[
j];
3737 for(
unsigned int k=0; k<
vertices.vertices.size(); ++k)
3741 int originalVertex = denseToOrganizedIndices[
vertices.vertices[k]];
3742 textureMesh->tex_coordinates[oi][
j*
vertices.vertices.size()+k] = Eigen::Vector2f(
3743 float(originalVertex % cloud->width) /
float(cloud->width),
3744 float(cloud->height - originalVertex / cloud->width) /
float(cloud->height));
3746 vertices.vertices[k] += polygonsStep;
3748 textureMesh->tex_polygons[oi][
j] =
vertices;
3751 polygonsStep += outputCloud->size();
3754 if(mergedClouds->size() == 0)
3756 *mergedClouds = *transformedCloud;
3760 *mergedClouds += *transformedCloud;
3763 textureMesh->tex_materials[oi].tex_illum = 1;
3764 textureMesh->tex_materials[oi].tex_name =
uFormat(
"material_%d",
iter->first);
3771 UERROR(
"Mesh not found for mesh %d",
iter->first);
3785 if(textureSize == 0)
3787 if(mergedClouds->size())
3789 pcl::toPCLPointCloud2(*mergedClouds, polygonMesh->cloud);
3793 polygonMesh->polygons.clear();
3798 textureMesh->tex_materials.resize(oi);
3799 textureMesh->tex_polygons.resize(oi);
3801 if(mergedClouds->size())
3803 pcl::toPCLPointCloud2(*mergedClouds, textureMesh->cloud);
3810 if(textureSize>0 && totalPolygons && textureMesh->tex_materials.size())
3812 LOGI(
"Merging %d textures...", (
int)textureMesh->tex_materials.size());
3815 std::map<int, cv::Mat>(),
3816 std::map<
int, std::vector<rtabmap::CameraModel> >(),
3822 true, 10.0f,
true ,
true, 0, 0, 0,
false,
3825 textureVertexColorPolicy == 1);
3826 LOGI(
"Merging %d textures... globalTextures=%dx%d", (
int)textureMesh->tex_materials.size(),
3827 globalTextures.cols, globalTextures.rows);
3843 if(textureSize == 0)
3845 UASSERT((
int)polygonMesh->polygons.size() == totalPolygons);
3846 if(polygonMesh->polygons.size())
3849 pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr cloud(
new pcl::PointCloud<pcl::PointXYZRGBNormal>);
3850 pcl::fromPCLPointCloud2(polygonMesh->cloud, *cloud);
3852 std::vector<std::vector<std::vector<RTABMAP_PCL_INDEX> > > polygons(1);
3853 polygons[0].resize(polygonMesh->polygons.size());
3854 for(
unsigned int p=0;
p<polygonMesh->polygons.size(); ++
p)
3856 polygons[0][
p] = polygonMesh->polygons[
p].vertices;
3864 else if(textureMesh->tex_materials.size())
3866 bool hasColors =
false;
3867 for(
unsigned int i=0;
i<textureMesh->cloud.fields.size(); ++
i)
3869 if(textureMesh->cloud.fields[
i].name.compare(
"rgb") == 0)
3878 pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr cloud(
new pcl::PointCloud<pcl::PointXYZRGBNormal>);
3879 pcl::fromPCLPointCloud2(textureMesh->cloud, *cloud);
3884 pcl::PointCloud<pcl::PointNormal>::Ptr cloud(
new pcl::PointCloud<pcl::PointNormal>);
3885 pcl::fromPCLPointCloud2(textureMesh->cloud, *cloud);
3890 std::vector<std::vector<std::vector<RTABMAP_PCL_INDEX> > > polygons(textureMesh->tex_polygons.size());
3891 for(
unsigned int t=0;
t<textureMesh->tex_polygons.size(); ++
t)
3893 polygons[
t].resize(textureMesh->tex_polygons[
t].size());
3894 for(
unsigned int p=0;
p<textureMesh->tex_polygons[
t].size(); ++
p)
3896 polygons[
t][
p] = textureMesh->tex_polygons[
t][
p].vertices;
3905 UERROR(
"Failed exporting texture mesh! There are no textures!");
3910 UERROR(
"Failed exporting mesh! There are no polygons!");
3915 pcl::PointCloud<pcl::PointXYZRGB>::Ptr mergedClouds(
new pcl::PointCloud<pcl::PointXYZRGB>);
3916 for(std::map<int, rtabmap::Transform>::iterator
iter=poses.begin();
3921 pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud(
new pcl::PointCloud<pcl::PointXYZRGB>);
3922 pcl::IndicesPtr
indices(
new std::vector<int>);
3924 gains[0] = gains[1] = gains[2] = 1.0f;
3929 gains[0] = jter->second.gains[0];
3930 gains[1] = jter->second.gains[1];
3931 gains[2] = jter->second.gains[2];
3934 data.uncompressData();
3935 if(!
data.imageRaw().empty() && !
data.depthRaw().empty())
3940 else if(!
data.laserScanRaw().empty())
3944 indices->resize(cloud->size());
3945 for(
unsigned int i=0;
i<cloud->size(); ++
i)
3955 cloud = jter->second.cloud;
3956 indices = jter->second.indices;
3957 gains[0] = jter->second.gains[0];
3958 gains[1] = jter->second.gains[1];
3959 gains[2] = jter->second.gains[2];
3964 data.uncompressData();
3965 if(!
data.imageRaw().empty() && !
data.depthRaw().empty())
3970 else if(!
data.laserScanRaw().empty())
3974 indices->resize(cloud->size());
3975 for(
unsigned int i=0;
i<cloud->size(); ++
i)
3982 if(cloud->size() &&
indices->size())
3985 pcl::PointCloud<pcl::PointXYZRGB>::Ptr transformedCloud(
new pcl::PointCloud<pcl::PointXYZRGB>);
3986 if(cloudVoxelSize > 0.0
f)
3995 pcl::copyPointCloud(*cloud, *
indices, *transformedCloud);
3999 if(gains[0] != 1.0
f || gains[1] != 1.0
f || gains[2] != 1.0
f)
4002 for(
unsigned int i=0;
i<transformedCloud->size(); ++
i)
4004 pcl::PointXYZRGB & pt = transformedCloud->at(
i);
4013 if(mergedClouds->size() == 0)
4015 *mergedClouds = *transformedCloud;
4019 *mergedClouds += *transformedCloud;
4035 if(mergedClouds->size())
4037 if(cloudVoxelSize > 0.0
f)
4052 UERROR(
"Merged cloud is empty!");
4063 catch (std::exception &
e)
4065 UERROR(
"Out of memory! %s",
e.what());
4082 if(success && poses.size())
4095 LOGI(
"postExportation(visualize=%d)", visualize?1:0);
4105 std::vector<std::vector<std::vector<RTABMAP_PCL_INDEX> > > polygons;
4106 #if PCL_VERSION_COMPARE(>=, 1, 8, 0)
4107 std::vector<std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > > texCoords;
4109 std::vector<std::vector<Eigen::Vector2f> > texCoords;
4115 if(!cloudMat.empty())
4117 LOGI(
"postExportation: Found optimized mesh! Visualizing it.");
4128 LOGI(
"postExportation: No optimized mesh found.");
4159 stats.setPoses(poses);
4160 stats.setConstraints(links);
4173 LOGI(
"writeExportedMesh: dir=%s name=%s", directory.c_str(),
name.c_str());
4176 bool success =
false;
4178 pcl::PolygonMesh::Ptr polygonMesh(
new pcl::PolygonMesh);
4179 pcl::TextureMesh::Ptr textureMesh(
new pcl::TextureMesh);
4181 std::vector<std::vector<std::vector<RTABMAP_PCL_INDEX> > > polygons;
4182 #if PCL_VERSION_COMPARE(>=, 1, 8, 0)
4183 std::vector<std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > > texCoords;
4185 std::vector<std::vector<Eigen::Vector2f> > texCoords;
4191 if(!cloudMat.empty())
4193 LOGI(
"writeExportedMesh: Found optimized mesh!");
4194 if(textures.empty())
4205 LOGI(
"writeExportedMesh: No optimized mesh found.");
4209 if(polygonMesh->cloud.data.size())
4211 #if defined(RTABMAP_PDAL) || defined(RTABMAP_LIBLAS)
4215 LOGI(
"Saving las (%d vertices) to %s.", (
int)polygonMesh->cloud.data.size()/polygonMesh->cloud.point_step, filePath.c_str());
4216 pcl::PointCloud<pcl::PointXYZRGB> output;
4217 pcl::fromPCLPointCloud2(polygonMesh->cloud, output);
4225 LOGI(
"Saved las to %s!", filePath.c_str());
4229 UERROR(
"Failed saving las to %s!", filePath.c_str());
4237 LOGI(
"Saving ply (%d vertices, %d polygons) to %s.", (
int)polygonMesh->cloud.data.size()/polygonMesh->cloud.point_step, (
int)polygonMesh->polygons.size(), filePath.c_str());
4238 success = pcl::io::savePLYFileBinary(filePath, *polygonMesh) == 0;
4241 LOGI(
"Saved ply to %s!", filePath.c_str());
4245 UERROR(
"Failed saving ply to %s!", filePath.c_str());
4249 else if(textureMesh->cloud.data.size())
4252 LOGD(
"Saving texture(s) (%d)", textures.empty()?0:textures.cols/textures.rows);
4253 UASSERT(textures.empty() || textures.cols % textures.rows == 0);
4254 UASSERT((
int)textureMesh->tex_materials.size() == textures.cols/textures.rows);
4255 for(
unsigned int i=0;
i<textureMesh->tex_materials.size(); ++
i)
4257 std::string baseNameNum =
name;
4258 if(textureMesh->tex_materials.size()>1)
4263 textureMesh->tex_materials[
i].tex_file = baseNameNum+
".jpg";
4264 LOGI(
"Saving texture to %s.", fullPath.c_str());
4265 success = cv::imwrite(fullPath, textures(
cv::Range::all(), cv::Range(
i*textures.rows, (
i+1)*textures.rows)));
4268 LOGI(
"Failed saving %s!", fullPath.c_str());
4272 LOGI(
"Saved %s.", fullPath.c_str());
4284 int totalPolygons = 0;
4285 for(
unsigned int i=0;
i<textureMesh->tex_polygons.size(); ++
i)
4287 totalPolygons += textureMesh->tex_polygons[
i].size();
4289 LOGI(
"Saving obj (%d vertices, %d polygons) to %s.", (
int)textureMesh->cloud.data.size()/textureMesh->cloud.point_step, totalPolygons, filePath.c_str());
4294 LOGI(
"Saved obj to %s!", filePath.c_str());
4298 UERROR(
"Failed saving obj to %s!", filePath.c_str());
4309 LOGI(
"postProcessing begin(%d)", approach);
4310 int returnedValue = 0;
4313 std::map<int, rtabmap::Transform> poses;
4314 std::multimap<int, rtabmap::Link> links;
4317 if(approach == -1 || approach == 2)
4332 if(returnedValue >=0)
4338 std::map<int, rtabmap::Signature> signatures;
4345 poses = sba->
optimizeBA(poses.rbegin()->first, poses, links, signatures);
4350 UERROR(
"g2o not available!");
4353 else if(approach!=4 && approach!=5 && approach != 7)
4364 stats.setPoses(poses);
4365 stats.setConstraints(links);
4367 LOGI(
"PostProcessing, sending rtabmap event to update graph...");
4372 else if(approach!=4 && approach!=5 && approach != 7)
4377 if(returnedValue >=0)
4381 if(approach == -1 || approach == 4)
4387 if(approach == -1 || approach == 5 || approach == 6)
4401 LOGI(
"postProcessing end(%d) -> %d", approach, returnedValue);
4402 return returnedValue;
4467 float rgb_fx,
float rgb_fy,
float rgb_cx,
float rgb_cy,
4468 float depth_fx,
float depth_fy,
float depth_cx,
float depth_cy,
4473 const void * yPlane,
const void * uPlane,
const void * vPlane,
int yPlaneLen,
int rgbWidth,
int rgbHeight,
int rgbFormat,
4474 const void * depth,
int depthLen,
int depthWidth,
int depthHeight,
int depthFormat,
4475 const void *
conf,
int confLen,
int confWidth,
int confHeight,
int confFormat,
4476 const float * points,
int pointsLen,
int pointsChannels,
4478 float p00,
float p11,
float p02,
float p12,
float p22,
float p32,
float p23,
4479 float t0,
float t1,
float t2,
float t3,
float t4,
float t5,
float t6,
float t7)
4481 #if defined(RTABMAP_ARCORE) || defined(__APPLE__)
4491 if(rgb_fx > 0.0
f && rgb_fy > 0.0
f && rgb_cx > 0.0
f && rgb_cy > 0.0
f && stamp > 0.0
f && yPlane && vPlane && yPlaneLen == rgbWidth*rgbHeight)
4496 #if defined(RTABMAP_ARCORE)
4497 if(rgbFormat == AR_IMAGE_FORMAT_YUV_420_888 &&
4498 (depth==0 || depthFormat == AIMAGE_FORMAT_DEPTH16))
4500 if(rgbFormat == 875704422 &&
4501 (depth==0 || depthFormat == 1717855600))
4508 if((
long)vPlane-(
long)yPlane != yPlaneLen)
4511 cv::Mat yuv(rgbHeight+rgbHeight/2, rgbWidth, CV_8UC1);
4512 memcpy(yuv.data, yPlane, yPlaneLen);
4513 memcpy(yuv.data+yPlaneLen, vPlane, rgbHeight/2*rgbWidth);
4514 cv::cvtColor(yuv, outputRGB, cv::COLOR_YUV2BGR_NV21);
4519 cv::cvtColor(cv::Mat(rgbHeight+rgbHeight/2, rgbWidth, CV_8UC1, (
void*)yPlane), outputRGB, cv::COLOR_YUV2BGR_NV21);
4521 cv::cvtColor(cv::Mat(rgbHeight+rgbHeight/2, rgbWidth, CV_8UC1, (
void*)yPlane), outputRGB, cv::COLOR_YUV2RGB_NV21);
4526 cv::Mat outputDepth;
4527 if(depth && depthHeight>0 && depthWidth>0)
4532 if(depthLen == 4*depthWidth*depthHeight)
4535 outputDepth = cv::Mat(depthHeight, depthWidth, CV_32FC1, (
void*)depth).clone();
4536 if(
conf && confWidth == depthWidth && confHeight == depthHeight && confFormat == 1278226488 &&
depthConfidence_>0)
4538 const unsigned char * confPtr = (
const unsigned char *)
conf;
4539 float * depthPtr = outputDepth.ptr<
float>();
4541 for (
int y = 0;
y < outputDepth.rows; ++
y)
4543 for (
int x = 0;
x < outputDepth.cols; ++
x)
4551 depthPtr[
y*outputDepth.cols +
x] = 0.0f;
4558 else if(depthLen == 2*depthWidth*depthHeight)
4561 outputDepth = cv::Mat(depthHeight, depthWidth, CV_16UC1);
4563 for (
int y = 0;
y < outputDepth.rows; ++
y)
4565 for (
int x = 0;
x < outputDepth.cols; ++
x)
4567 uint16_t depthSample = dataShort[
y*outputDepth.cols +
x];
4568 uint16_t depthRange = (depthSample & 0x1FFF);
4575 if(!outputRGB.empty())
4584 if(!outputDepth.empty() && !depthFrame.
isNull() && depth_fx!=0 && (rgbFrame != depthFrame || depthStamp!=stamp))
4588 if(depthStamp != stamp)
4608 motion = poseRgb.
inverse()*poseDepth;
4620 float scale = (
float)outputDepth.cols/(
float)outputRGB.cols;
4621 cv::Mat colorK = (cv::Mat_<double>(3,3) <<
4625 cv::Mat depthK = (cv::Mat_<double>(3,3) <<
4626 depth_fx, 0, depth_cx,
4627 0, depth_fy, depth_cy,
4631 UDEBUG(
"Depth registration time: %fs",
time.elapsed());
4645 std::vector<cv::KeyPoint> kpts;
4646 std::vector<cv::Point3f> kpts3;
4648 if(points && pointsLen>0)
4650 cv::Mat pointsMat(1, pointsLen, CV_32FC(pointsChannels), (
void*)points);
4651 if(outputDepth.empty())
4663 if(!outputDepth.empty())
4671 data.setFeatures(kpts, kpts3, cv::Mat());
4673 projectionMatrix[0][0] = p00;
4674 projectionMatrix[1][1] = p11;
4675 projectionMatrix[2][0] = p02;
4676 projectionMatrix[2][1] = p12;
4677 projectionMatrix[2][2] =
p22;
4678 projectionMatrix[2][3] = p32;
4679 projectionMatrix[3][2] = p23;
4696 UERROR(
"Missing image information! fx=%f fy=%f cx=%f cy=%f stamp=%f yPlane=%d vPlane=%d yPlaneLen=%d rgbWidth=%d rgbHeight=%d",
4697 rgb_fx, rgb_fy, rgb_cx, rgb_cy, stamp, yPlane?1:0, vPlane?1:0, yPlaneLen, rgbWidth, rgbHeight);
4701 UERROR(
"Not built with ARCore or iOS!");
4712 LOGI(
"Received SensorEvent!");
4722 LOGI(
"Received RtabmapEvent event! status=%d",
status_.first);
4731 LOGW(
"Received RtabmapEvent event but ignoring it while we are initializing...status=%d",
status_.first);
4746 if(event->
getClassName().compare(
"CameraInfoEvent") == 0)
4751 bool success =
false;
4753 if(jvm && RTABMapActivity)
4756 jint
rs = jvm->AttachCurrentThread(&
env,
NULL);
4757 if(
rs == JNI_OK &&
env)
4759 jclass clazz =
env->GetObjectClass(RTABMapActivity);
4762 jmethodID methodID =
env->GetMethodID(clazz,
"cameraEventCallback",
"(ILjava/lang/String;Ljava/lang/String;)V" );
4765 env->CallVoidMethod(RTABMapActivity, methodID,
4767 env->NewStringUTF(tangoEvent->
key().c_str()),
4768 env->NewStringUTF(tangoEvent->
value().c_str()));
4773 jvm->DetachCurrentThread();
4778 std::function<void()> actualCallback = [&](){
4787 UERROR(
"Failed to call RTABMapActivity::tangoEventCallback");
4791 if(event->
getClassName().compare(
"RtabmapEventInit") == 0)
4795 LOGI(
"Received RtabmapEventInit! Status=%d info=%s", (
int)
status_.first,
status_.second.c_str());
4798 bool success =
false;
4800 if(jvm && RTABMapActivity)
4803 jint
rs = jvm->AttachCurrentThread(&
env,
NULL);
4804 if(
rs == JNI_OK &&
env)
4806 jclass clazz =
env->GetObjectClass(RTABMapActivity);
4809 jmethodID methodID =
env->GetMethodID(clazz,
"rtabmapInitEventCallback",
"(ILjava/lang/String;)V" );
4812 env->CallVoidMethod(RTABMapActivity, methodID,
4819 jvm->DetachCurrentThread();
4824 std::function<void()> actualCallback = [&](){
4833 UERROR(
"Failed to call RTABMapActivity::rtabmapInitEventsCallback");
4837 if(event->
getClassName().compare(
"PostRenderEvent") == 0)
4839 LOGI(
"Received PostRenderEvent!");
4841 int loopClosureId = 0;
4842 int featuresExtracted = 0;
4845 LOGI(
"Received PostRenderEvent! has getRtabmapEvent");
4848 loopClosureId =
stats.loopClosureId()>0?
stats.loopClosureId():
stats.proximityDetectionId()>0?
stats.proximityDetectionId():0;
4849 featuresExtracted =
stats.getLastSignatureData().getWords().size();
4851 uInsert(
bufferedStatsData_, std::make_pair<std::string, float>(rtabmap::Statistics::kMemoryWorking_memory_size(),
uValue(
stats.data(), rtabmap::Statistics::kMemoryWorking_memory_size(), 0.0f)));
4852 uInsert(
bufferedStatsData_, std::make_pair<std::string, float>(rtabmap::Statistics::kMemoryShort_time_memory_size(),
uValue(
stats.data(), rtabmap::Statistics::kMemoryShort_time_memory_size(), 0.0f)));
4853 uInsert(
bufferedStatsData_, std::make_pair<std::string, float>(rtabmap::Statistics::kKeypointDictionary_size(),
uValue(
stats.data(), rtabmap::Statistics::kKeypointDictionary_size(), 0.0f)));
4855 uInsert(
bufferedStatsData_, std::make_pair<std::string, float>(rtabmap::Statistics::kLoopHighest_hypothesis_id(),
uValue(
stats.data(), rtabmap::Statistics::kLoopHighest_hypothesis_id(), 0.0f)));
4856 uInsert(
bufferedStatsData_, std::make_pair<std::string, float>(rtabmap::Statistics::kMemoryDatabase_memory_used(),
uValue(
stats.data(), rtabmap::Statistics::kMemoryDatabase_memory_used(), 0.0f)));
4857 uInsert(
bufferedStatsData_, std::make_pair<std::string, float>(rtabmap::Statistics::kLoopVisual_inliers(),
uValue(
stats.data(), rtabmap::Statistics::kLoopVisual_inliers(), 0.0f)));
4858 uInsert(
bufferedStatsData_, std::make_pair<std::string, float>(rtabmap::Statistics::kLoopVisual_matches(),
uValue(
stats.data(), rtabmap::Statistics::kLoopVisual_matches(), 0.0f)));
4859 uInsert(
bufferedStatsData_, std::make_pair<std::string, float>(rtabmap::Statistics::kLoopRejectedHypothesis(),
uValue(
stats.data(), rtabmap::Statistics::kLoopRejectedHypothesis(), 0.0f)));
4860 uInsert(
bufferedStatsData_, std::make_pair<std::string, float>(rtabmap::Statistics::kLoopOptimization_max_error(),
uValue(
stats.data(), rtabmap::Statistics::kLoopOptimization_max_error(), 0.0f)));
4861 uInsert(
bufferedStatsData_, std::make_pair<std::string, float>(rtabmap::Statistics::kLoopOptimization_max_error_ratio(),
uValue(
stats.data(), rtabmap::Statistics::kLoopOptimization_max_error_ratio(), 0.0f)));
4862 uInsert(
bufferedStatsData_, std::make_pair<std::string, float>(rtabmap::Statistics::kMemoryRehearsal_sim(),
uValue(
stats.data(), rtabmap::Statistics::kMemoryRehearsal_sim(), 0.0f)));
4863 uInsert(
bufferedStatsData_, std::make_pair<std::string, float>(rtabmap::Statistics::kLoopHighest_hypothesis_value(),
uValue(
stats.data(), rtabmap::Statistics::kLoopHighest_hypothesis_value(), 0.0f)));
4864 uInsert(
bufferedStatsData_, std::make_pair<std::string, float>(rtabmap::Statistics::kMemoryDistance_travelled(),
uValue(
stats.data(), rtabmap::Statistics::kMemoryDistance_travelled(), 0.0f)));
4865 uInsert(
bufferedStatsData_, std::make_pair<std::string, float>(rtabmap::Statistics::kMemoryFast_movement(),
uValue(
stats.data(), rtabmap::Statistics::kMemoryFast_movement(), 0.0f)));
4866 uInsert(
bufferedStatsData_, std::make_pair<std::string, float>(rtabmap::Statistics::kLoopLandmark_detected(),
uValue(
stats.data(), rtabmap::Statistics::kLoopLandmark_detected(), 0.0f)));
4880 float optimizationMaxErrorRatio =
uValue(
bufferedStatsData_, rtabmap::Statistics::kLoopOptimization_max_error_ratio(), 0.0
f);
4888 if(!currentPose.
isNull())
4894 UINFO(
"Send statistics to GUI");
4895 bool success =
false;
4897 if(jvm && RTABMapActivity)
4900 jint
rs = jvm->AttachCurrentThread(&
env,
NULL);
4901 if(
rs == JNI_OK &&
env)
4903 jclass clazz =
env->GetObjectClass(RTABMapActivity);
4906 jmethodID methodID =
env->GetMethodID(clazz,
"updateStatsCallback",
"(IIIIFIIIIIIFIFIFFFFIIFFFFFF)V" );
4909 env->CallVoidMethod(RTABMapActivity, methodID,
4926 optimizationMaxError,
4927 optimizationMaxErrorRatio,
4941 jvm->DetachCurrentThread();
4946 std::function<void()> actualCallback = [&](){
4964 optimizationMaxError,
4965 optimizationMaxErrorRatio,
4982 UERROR(
"Failed to call RTABMapActivity::updateStatsCallback");