Compare commits

...
42 Commits
Author SHA1 Message Date
matlabbe 75854fc026 OccupancyGrid: updated parameters check 2017-08-04 11:41:50 -04:00
matlabbe d8a6ed4ba6 DbViewer: fixed voxelize assert when voxel size is set and there are no laser scans in database 2017-08-04 10:47:25 -04:00
matlabbe 459bbda60c increased package version to 0.13.2 2017-08-03 16:42:46 -04:00
matlabbe 2a9508b4e3 Fixed build for Lunar 2017-08-03 16:40:12 -04:00
matlabbe c0c288e0d9 Tango: removed seekbar for FOV(use pinch zoom instead), show UI on single tap instead of swipe down 2017-08-03 11:52:18 -04:00
matlabbe 82fd5b36a8 util3d::cloud[RGB]FromSensorData(): supporting roi ratios for stereo images 2017-08-02 15:14:03 -04:00
matlabbe dd3c7d8fa4 CameraStereoZed: fixed build for ZED sdk 2.1 (https://github.com/introlab/rtabmap_ros/issues/192) 2017-07-31 15:12:05 -04:00
matlabbe b63f073d90 CameraStereoZed: handling initialization failures 2017-07-31 14:11:32 -04:00
matlabbe 0491125e92 fixed voxelize assertion with c++ rgbd mapping example 2017-07-26 16:00:02 -04:00
matlabbe 3443c3b8ea RegistrationVis: fixed assert covariance in bundle adjustement when transform is perfect (covariance is null) by setting an epsilon to generated covariance is null or very close to 0 2017-07-26 15:27:54 -04:00
matlabbe be720be74a 💄 2017-07-26 11:46:59 -04:00
matlabbe f3e491f15b Added KAZE feature detector (OpenCV3) 2017-07-25 16:20:05 -04:00
matlabbe 5855198b5f Tango: swipe down to show hud, added notification sound after saving or exporting, added polygon cluster filtering export option, action and status bars are transparent 2017-07-24 20:24:16 -04:00
matlabbe 62de6fcdae util3d::denseMeshPostProcessing(): coloredOutput param not used anymore 2017-07-24 19:21:22 -04:00
matlabbe 57dc0cd53e DepthCalibration: support depth images smaller than RGB images 2017-07-24 13:06:30 -04:00
matlabbe 0a1694dd78 MainWindow: Detect more loop closures: uncompress images when reextract features on loop closure is enabled 2017-07-24 12:18:19 -04:00
matlabbe edc690973a DbViewer: added warning when reextract feature is false and signatures have no features 2017-07-24 11:48:49 -04:00
matlabbe 48148a9e26 DbViewer: fixed voxel assert 2017-07-23 22:33:26 -04:00
matlabbe 62b9911176 docker: fixed tango build with res tool prebuild 2017-07-13 14:33:52 -04:00
matlabbe fb69a37445 docker missing g++ 2017-07-13 14:18:58 -04:00
matlabbe 81ae1eae51 docker update 2017-07-13 14:14:51 -04:00
matlabbe 517c70d855 CMake: added ANDROID_PREBUILD option 2017-07-13 13:36:34 -04:00
matlabbe 85f7c1e73c OccupancyGrid/voxelize: if organized cloud, indices should not be null 2017-07-13 12:23:03 -04:00
matlabbe b4cfa0e844 RtabmapThread: use largest covariance instead of summation 2017-07-13 11:36:55 -04:00
matlabbe 3c758ab2f6 Update .travis.yml 2017-07-13 11:32:14 -04:00
matlabbe 1ed01b8d3d Memory: fixed cov->inf conversion error 2017-07-13 11:07:00 -04:00
matlabbe 19abbe0dbd DBViewer: fixing previous commit for very large databases (where we don't want to regenerate map if we don't show it) 2017-07-12 21:39:51 -04:00
matlabbe c833af1ae6 DBViewer: fixed disabled show/hide map option while map is available 2017-07-12 21:26:14 -04:00
matlabbe 78bdd4a087 Added check if covariance is invertible, if not an error is thrown 2017-07-12 16:41:47 -04:00
matlabbe dc77bb4332 OdometryViso2: updated for dynamic local transform 2017-07-10 17:34:37 -04:00
matlabbe 9e011d6ad9 Fixed changing local transform not handled correctly when changing for third party odometries 2017-07-07 19:41:11 -04:00
matlabbe f9ed36ed54 Parameters: renamed Rtabmap/VhStrategy to VhEp/Enabled 2017-07-05 13:38:27 -04:00
matlabbe 495681770e Tango: updated About copyright year 2017-07-03 18:48:02 -04:00
matlabbe eb1f0e0a8a Tango: aligned share sketchfab button to top (over pause) 2017-07-03 16:52:22 -04:00
matlabbe 23ae5caa3c Tango: bump apk version 2017-07-03 14:48:04 -04:00
matlabbe 4b7d558026 Tango: moved export to file button under share to sketchfab (fixing overlap of button on opengl status text), fixed export empty poses after resuming without relocalizing (append mode) 2017-07-03 14:42:48 -04:00
matlabbe 44969a7fdf Docker: added zesty 2017-06-29 14:32:12 -04:00
matlabbe 5f5c74f260 RGBDMapping example: fixed -lvtkproj4 not found error on Xenial 2017-06-29 16:59:15 +00:00
matlabbe 5646751f88 RTABMapConfig.cmake: Set WITH_GUI default true if no components are specified 2017-06-29 15:31:05 -04:00
matlabbe b6d3e785df Tango: fixed export failing after saving the database 2017-06-29 10:31:59 -04:00
matlabbe ebada30984 Tango: updated UI 2017-06-28 13:59:20 -04:00
matlabbe 64fc9f203e Tango: fixed build for Ikariotikos release 2017-06-27 11:45:51 -04:00
78 changed files with 1526 additions and 738 deletions
+1
View File
@@ -1,6 +1,7 @@
sudo: true sudo: true
dist: trusty dist: trusty
language: cpp language: cpp
group: deprecated-2017Q3
compiler: compiler:
- gcc - gcc
+18 -13
View File
@@ -21,7 +21,7 @@ SET(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake_modules")
####################### #######################
SET(RTABMAP_MAJOR_VERSION 0) SET(RTABMAP_MAJOR_VERSION 0)
SET(RTABMAP_MINOR_VERSION 13) SET(RTABMAP_MINOR_VERSION 13)
SET(RTABMAP_PATCH_VERSION 0) SET(RTABMAP_PATCH_VERSION 2)
SET(RTABMAP_VERSION SET(RTABMAP_VERSION
${RTABMAP_MAJOR_VERSION}.${RTABMAP_MINOR_VERSION}.${RTABMAP_PATCH_VERSION}) ${RTABMAP_MAJOR_VERSION}.${RTABMAP_MINOR_VERSION}.${RTABMAP_PATCH_VERSION})
@@ -124,6 +124,15 @@ set(INSTALL_CMAKE_DIR ${DEF_INSTALL_CMAKE_DIR} CACHE PATH
"Installation directory for CMake files") "Installation directory for CMake files")
####### BUILD OPTIONS ####### ####### BUILD OPTIONS #######
# ANDROID_PREBUILD (early exit if true)
OPTION( ANDROID_PREBUILD "Set to ON to build rtabmap resource build tool (required for android build)" OFF )
IF(ANDROID_PREBUILD)
MESSAGE("Option ANDROID_PREBUILD is set, only rtabmap resource tool will be built. You can use android toolchain after that.")
ADD_SUBDIRECTORY( utilite )
return()
ENDIF(ANDROID_PREBUILD)
IF(APPLE) IF(APPLE)
OPTION(BUILD_AS_BUNDLE "Set to ON to build as bundle (DragNDrop)" OFF) OPTION(BUILD_AS_BUNDLE "Set to ON to build as bundle (DragNDrop)" OFF)
ENDIF(APPLE) ENDIF(APPLE)
@@ -162,9 +171,11 @@ FIND_PACKAGE(OpenCV REQUIRED QUIET)
FIND_PACKAGE(PCL 1.7 REQUIRED QUIET) FIND_PACKAGE(PCL 1.7 REQUIRED QUIET)
FIND_PACKAGE(ZLIB REQUIRED QUIET) FIND_PACKAGE(ZLIB REQUIRED QUIET)
# fix libproj.so not found on Xenial
if(NOT "${PCL_LIBRARIES}" STREQUAL "") if(NOT "${PCL_LIBRARIES}" STREQUAL "")
# fix libproj.so not found on Xenial
list(REMOVE_ITEM PCL_LIBRARIES "vtkproj4") list(REMOVE_ITEM PCL_LIBRARIES "vtkproj4")
# fix libmpi.so not found on Zesty
list(REMOVE_ITEM PCL_LIBRARIES "/usr/lib/libmpi.so")
endif() endif()
# OpenMP ("-fopenmp" should be added for flann included in PCL) # OpenMP ("-fopenmp" should be added for flann included in PCL)
@@ -205,12 +216,12 @@ IF(WITH_QT)
IF("${VTK_MAJOR_VERSION}" GREATER 5) IF("${VTK_MAJOR_VERSION}" GREATER 5)
FIND_PACKAGE(Qt5 COMPONENTS Widgets Core Gui QUIET) FIND_PACKAGE(Qt5 COMPONENTS Widgets Core Gui QUIET)
IF(Qt5_FOUND) IF(Qt5_FOUND)
FIND_PACKAGE(Qt5 COMPONENTS Widgets Core Gui Svg) FIND_PACKAGE(Qt5 COMPONENTS Widgets Core Gui OPTIONAL_COMPONENTS Svg)
ENDIF(Qt5_FOUND) ENDIF(Qt5_FOUND)
ENDIF("${VTK_MAJOR_VERSION}" GREATER 5) ENDIF("${VTK_MAJOR_VERSION}" GREATER 5)
IF(NOT Qt5_FOUND) IF(NOT Qt5_FOUND)
FIND_PACKAGE(Qt4 COMPONENTS QtCore QtGui QtSvg) FIND_PACKAGE(Qt4 COMPONENTS QtCore QtGui OPTIONAL_COMPONENTS QtSvg)
ENDIF(NOT Qt5_FOUND) ENDIF(NOT Qt5_FOUND)
IF(QT4_FOUND OR Qt5_FOUND) IF(QT4_FOUND OR Qt5_FOUND)
@@ -369,7 +380,7 @@ IF(WITH_DVO)
ENDIF(dvo_core_FOUND) ENDIF(dvo_core_FOUND)
ENDIF(WITH_DVO) ENDIF(WITH_DVO)
IF(WITH_ORB_SLAM2 AND NOT G2O_FOUND AND NOT RealSense_FOUND) IF(WITH_ORB_SLAM2 AND NOT G2O_FOUND)
FIND_PACKAGE(ORB_SLAM2 QUIET) FIND_PACKAGE(ORB_SLAM2 QUIET)
IF(ORB_SLAM2_FOUND) IF(ORB_SLAM2_FOUND)
MESSAGE(STATUS "Found ORB_SLAM2: ${ORB_SLAM2_INCLUDE_DIRS}") MESSAGE(STATUS "Found ORB_SLAM2: ${ORB_SLAM2_INCLUDE_DIRS}")
@@ -381,12 +392,10 @@ IF(WITH_ORB_SLAM2 AND NOT G2O_FOUND AND NOT RealSense_FOUND)
MESSAGE(STATUS "Found Pangolin: ${Pangolin_INCLUDE_DIRS}") MESSAGE(STATUS "Found Pangolin: ${Pangolin_INCLUDE_DIRS}")
SET(ORB_SLAM2_INCLUDE_DIRS ${ORB_SLAM2_INCLUDE_DIRS} ${Pangolin_INCLUDE_DIRS}) SET(ORB_SLAM2_INCLUDE_DIRS ${ORB_SLAM2_INCLUDE_DIRS} ${Pangolin_INCLUDE_DIRS})
SET(ORB_SLAM2_LIBRARIES ${ORB_SLAM2_LIBRARIES} ${Pangolin_LIBRARIES}) SET(ORB_SLAM2_LIBRARIES ${ORB_SLAM2_LIBRARIES} ${Pangolin_LIBRARIES})
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=native") MESSAGE(WARNING "Don't forget to build ORB_SLAM2 (and included g2o) without \"-march=native\" to avoid crash when ORB_SLAM2 starts.")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native")
# There could be crash issues if built with RealSense
ENDIF() ENDIF()
ENDIF(ORB_SLAM2_FOUND) ENDIF(ORB_SLAM2_FOUND)
ENDIF(WITH_ORB_SLAM2 AND NOT G2O_FOUND AND NOT RealSense_FOUND) ENDIF(WITH_ORB_SLAM2 AND NOT G2O_FOUND)
IF(G2O_FOUND OR GTSAM_FOUND OR ZED_FOUND OR ANDROID OR RealSense_FOUND OR ORB_SLAM2_FOUND) IF(G2O_FOUND OR GTSAM_FOUND OR ZED_FOUND OR ANDROID OR RealSense_FOUND OR ORB_SLAM2_FOUND)
#Newest versions require std11 #Newest versions require std11
@@ -885,12 +894,8 @@ IF(ORB_SLAM2_FOUND)
MESSAGE(STATUS " With ORB_SLAM2 = YES (License: GPLv3)") MESSAGE(STATUS " With ORB_SLAM2 = YES (License: GPLv3)")
ELSEIF(NOT WITH_ORB_SLAM2) ELSEIF(NOT WITH_ORB_SLAM2)
MESSAGE(STATUS " With ORB_SLAM2 = NO (WITH_ORB_SLAM2=OFF)") MESSAGE(STATUS " With ORB_SLAM2 = NO (WITH_ORB_SLAM2=OFF)")
ELSEIF(G2O_FOUND AND RealSense_FOUND)
MESSAGE(STATUS " With ORB_SLAM2 = NO (WITH_G2O should be OFF as ORB_SLAM2 uses its own g2o version, WITH_REALSENSE should also be off to avoid eigen errors)")
ELSEIF(G2O_FOUND) ELSEIF(G2O_FOUND)
MESSAGE(STATUS " With ORB_SLAM2 = NO (WITH_G2O should be OFF as ORB_SLAM2 uses its own g2o version)") MESSAGE(STATUS " With ORB_SLAM2 = NO (WITH_G2O should be OFF as ORB_SLAM2 uses its own g2o version)")
ELSEIF(RealSense_FOUND)
MESSAGE(STATUS " With ORB_SLAM2 = NO (WITH_REALSENSE should be off to avoid eigen errors)")
ELSE() ELSE()
MESSAGE(STATUS " With ORB_SLAM2 = NO (ORB_SLAM2 not found, make sure environment variable ORB_SLAM2_ROOT_DIR is set)") MESSAGE(STATUS " With ORB_SLAM2 = NO (ORB_SLAM2 not found, make sure environment variable ORB_SLAM2_ROOT_DIR is set)")
ENDIF() ENDIF()
+3 -3
View File
@@ -47,11 +47,11 @@ ENDIF()
set(RTABMap_LIBRARIES ${RTABMap_CORE} ${RTABMap_UTILITE}) set(RTABMap_LIBRARIES ${RTABMap_CORE} ${RTABMap_UTILITE})
list(LENGTH RTABMap_FIND_COMPONENTS RTABMap_FIND_COMPONENTS_LENGTH) list(LENGTH RTABMap_FIND_COMPONENTS RTABMap_FIND_COMPONENTS_LENGTH)
set(WITH_GUI OFF) set(WITH_GUI ON)
if(${RTABMap_FIND_COMPONENTS_LENGTH} GREATER 0) if(${RTABMap_FIND_COMPONENTS_LENGTH} GREATER 0)
list (FIND RTABMap_FIND_COMPONENTS "gui" _index) list (FIND RTABMap_FIND_COMPONENTS "gui" _index)
if (${_index} GREATER -1) if (${_index} EQUAL -1)
set(WITH_GUI ON) set(WITH_GUI OFF)
endif() endif()
endif(${RTABMap_FIND_COMPONENTS_LENGTH} GREATER 0) endif(${RTABMap_FIND_COMPONENTS_LENGTH} GREATER 0)
+3 -2
View File
@@ -2,7 +2,7 @@
<!-- BEGIN_INCLUDE(manifest) --> <!-- BEGIN_INCLUDE(manifest) -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.introlab.rtabmap" package="com.introlab.rtabmap"
android:versionCode="51" android:versionCode="55"
android:versionName="@RTABMAP_VERSION@"> android:versionName="@RTABMAP_VERSION@">
<uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.CAMERA" />
@@ -31,7 +31,8 @@
android:label="@string/app_name" android:label="@string/app_name"
android:launchMode="singleTask" android:launchMode="singleTask"
android:screenOrientation="fullSensor" android:screenOrientation="fullSensor"
android:configChanges="orientation|screenSize|keyboardHidden"> android:configChanges="orientation|screenSize|keyboardHidden"
android:theme="@style/ThemeApp">
<!-- Tell NativeActivity the name of our .so --> <!-- Tell NativeActivity the name of our .so -->
<meta-data android:name="android.app.lib_name" <meta-data android:name="android.app.lib_name"
android:value="NativeRTABMap" /> android:value="NativeRTABMap" />
+1 -1
View File
@@ -1,7 +1,7 @@
<h3>Real-Time Appearance-Based Mapping</h3> <h3>Real-Time Appearance-Based Mapping</h3>
Version @RTABMAP_VERSION@<br> Version @RTABMAP_VERSION@<br>
Author: Mathieu Labb&eacute;<br> Author: Mathieu Labb&eacute;<br>
Copyright 2016<br> Copyright 2016-2017<br>
IntRoLab - Universit&eacute; de Sherbrooke<br> IntRoLab - Universit&eacute; de Sherbrooke<br>
<b>http://introlab.github.io/rtabmap</b><br><br> <b>http://introlab.github.io/rtabmap</b><br><br>
+1 -1
View File
@@ -189,7 +189,7 @@ bool CameraTango::init(const std::string & calibrationFolder, const std::string
{ {
close(); close();
TangoSupport_initializeLibrary(); TangoSupport_initialize(TangoService_getPoseAtTime, TangoService_getCameraIntrinsics);
// Connect to Tango // Connect to Tango
LOGI("NativeRTABMap: Setup tango config"); LOGI("NativeRTABMap: Setup tango config");
+48 -5
View File
@@ -298,7 +298,11 @@ int RTABMapApp::openDatabase(const std::string & databasePath, bool databaseInMe
optTexture_ = cv::Mat(); optTexture_ = cv::Mat();
cv::Mat cloudMat; cv::Mat cloudMat;
std::vector<std::vector<std::vector<unsigned int> > > polygons; std::vector<std::vector<std::vector<unsigned int> > > polygons;
#if PCL_VERSION_COMPARE(>=, 1, 8, 0)
std::vector<std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > > texCoords;
#else
std::vector<std::vector<Eigen::Vector2f> > texCoords; std::vector<std::vector<Eigen::Vector2f> > texCoords;
#endif
cv::Mat textures; cv::Mat textures;
std::map<int, rtabmap::Transform> optPoses; std::map<int, rtabmap::Transform> optPoses;
if(!databaseSource.empty()) if(!databaseSource.empty())
@@ -1051,6 +1055,7 @@ int RTABMapApp::Render()
pcl::fromPCLPointCloud2(optMesh_->cloud, *mesh.cloud); pcl::fromPCLPointCloud2(optMesh_->cloud, *mesh.cloud);
pcl::fromPCLPointCloud2(optMesh_->cloud, *mesh.normals); pcl::fromPCLPointCloud2(optMesh_->cloud, *mesh.normals);
mesh.polygons = optMesh_->tex_polygons[0]; mesh.polygons = optMesh_->tex_polygons[0];
mesh.pose.setIdentity();
if(optMesh_->tex_coordinates.size()) if(optMesh_->tex_coordinates.size())
{ {
mesh.texCoords = optMesh_->tex_coordinates[0]; mesh.texCoords = optMesh_->tex_coordinates[0];
@@ -1568,7 +1573,7 @@ int RTABMapApp::Render()
if(rtabmapEvents.size()) if(rtabmapEvents.size())
{ {
// send statistics to GUI // send statistics to GUI
LOGW("Posting PostRenderEvent! %fs", renderingTime_); LOGI("New data added to map, rendering time: %fs", renderingTime_);
UEventsManager::post(new PostRenderEvent(rtabmapEvents.back())); UEventsManager::post(new PostRenderEvent(rtabmapEvents.back()));
rtabmapEvents.pop_back(); rtabmapEvents.pop_back();
@@ -1740,6 +1745,10 @@ void RTABMapApp::setOrthoCropFactor(float value)
{ {
main_scene_.setOrthoCropFactor(value); main_scene_.setOrthoCropFactor(value);
} }
void RTABMapApp::setGridRotation(float value)
{
main_scene_.setGridRotation(value);
}
void RTABMapApp::setLighting(bool enabled) void RTABMapApp::setLighting(bool enabled)
{ {
main_scene_.setLighting(enabled); main_scene_.setLighting(enabled);
@@ -2011,8 +2020,10 @@ void RTABMapApp::save(const std::string & databasePath)
dataRecorderMode_ = dataRecorderModeBackup; dataRecorderMode_ = dataRecorderModeBackup;
} }
std::map<int, rtabmap::Transform> poses = rtabmap_->getLocalOptimizedPoses();
rtabmap_->close(true, databasePath); rtabmap_->close(true, databasePath);
rtabmap_->init(getRtabmapParameters(), dataRecorderMode_?"":databasePath); rtabmap_->init(getRtabmapParameters(), dataRecorderMode_?"":databasePath);
rtabmap_->setOptimizedPoses(poses);
if(dataRecorderMode_) if(dataRecorderMode_)
{ {
clearSceneOnNextRender_ = true; clearSceneOnNextRender_ = true;
@@ -2040,7 +2051,7 @@ bool RTABMapApp::exportMesh(
int optimizedMaxPolygons, int optimizedMaxPolygons,
float optimizedColorRadius, float optimizedColorRadius,
bool optimizedCleanWhitePolygons, bool optimizedCleanWhitePolygons,
bool optimizedColorWhitePolygons, // not yet used int optimizedMinClusterSize,
float optimizedMaxTextureDistance, float optimizedMaxTextureDistance,
int optimizedMinTextureClusterSize, int optimizedMinTextureClusterSize,
bool blockRendering) bool blockRendering)
@@ -2048,6 +2059,24 @@ bool RTABMapApp::exportMesh(
// make sure createdMeshes_ is not modified while exporting! We don't // make sure createdMeshes_ is not modified while exporting! We don't
// lock the meshesMutex_ because we want to continue rendering. // lock the meshesMutex_ because we want to continue rendering.
std::map<int, rtabmap::Transform> poses = rtabmap_->getLocalOptimizedPoses();
if(poses.empty())
{
// look if we just triggered new map without localizing afterward (pause/resume in append Mode)
std::multimap<int, rtabmap::Link> links;
rtabmap_->getGraph(
poses,
links,
true,
false);
if(poses.empty())
{
UERROR("Empty optimized poses!");
return false;
}
rtabmap_->setOptimizedPoses(poses);
}
if(blockRendering) if(blockRendering)
{ {
renderingMutex_.lock(); renderingMutex_.lock();
@@ -2060,8 +2089,6 @@ bool RTABMapApp::exportMesh(
try try
{ {
std::map<int, rtabmap::Transform> poses = rtabmap_->getLocalOptimizedPoses();
int totalSteps = 0; int totalSteps = 0;
totalSteps+=poses.size(); // assemble totalSteps+=poses.size(); // assemble
if(meshing) if(meshing)
@@ -2314,7 +2341,7 @@ bool RTABMapApp::exportMesh(
optimizedColorRadius, optimizedColorRadius,
textureSize == 0, textureSize == 0,
optimizedCleanWhitePolygons, optimizedCleanWhitePolygons,
0); optimizedMinClusterSize);
if(textureSize>0) if(textureSize>0)
{ {
@@ -2364,6 +2391,10 @@ bool RTABMapApp::exportMesh(
} }
} }
} }
else
{
UERROR("Merged cloud too small (%d points) to create polygons!", (int)mergedClouds->size());
}
} }
else // organized meshes else // organized meshes
{ {
@@ -2727,6 +2758,10 @@ bool RTABMapApp::exportMesh(
success = true; success = true;
} }
} }
else
{
UERROR("Merged cloud is empty!");
}
} }
progressionStatus_.finish(); progressionStatus_.finish();
@@ -2764,7 +2799,11 @@ bool RTABMapApp::postExportation(bool visualize)
{ {
cv::Mat cloudMat; cv::Mat cloudMat;
std::vector<std::vector<std::vector<unsigned int> > > polygons; std::vector<std::vector<std::vector<unsigned int> > > polygons;
#if PCL_VERSION_COMPARE(>=, 1, 8, 0)
std::vector<std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > > texCoords;
#else
std::vector<std::vector<Eigen::Vector2f> > texCoords; std::vector<std::vector<Eigen::Vector2f> > texCoords;
#endif
cv::Mat textures; cv::Mat textures;
std::map<int, rtabmap::Transform> optPoses; std::map<int, rtabmap::Transform> optPoses;
if(rtabmap_ && rtabmap_->getMemory()) if(rtabmap_ && rtabmap_->getMemory())
@@ -2801,7 +2840,11 @@ bool RTABMapApp::writeExportedMesh(const std::string & directory, const std::str
pcl::TextureMesh::Ptr textureMesh(new pcl::TextureMesh); pcl::TextureMesh::Ptr textureMesh(new pcl::TextureMesh);
cv::Mat cloudMat; cv::Mat cloudMat;
std::vector<std::vector<std::vector<unsigned int> > > polygons; std::vector<std::vector<std::vector<unsigned int> > > polygons;
#if PCL_VERSION_COMPARE(>=, 1, 8, 0)
std::vector<std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > > texCoords;
#else
std::vector<std::vector<Eigen::Vector2f> > texCoords; std::vector<std::vector<Eigen::Vector2f> > texCoords;
#endif
cv::Mat textures; cv::Mat textures;
std::map<int, rtabmap::Transform> optPoses; std::map<int, rtabmap::Transform> optPoses;
if(rtabmap_ && rtabmap_->getMemory()) if(rtabmap_ && rtabmap_->getMemory())
+2 -1
View File
@@ -121,6 +121,7 @@ class RTABMapApp : public UEventsHandler {
void setPointSize(float value); void setPointSize(float value);
void setFOV(float angle); void setFOV(float angle);
void setOrthoCropFactor(float value); void setOrthoCropFactor(float value);
void setGridRotation(float value);
void setLighting(bool enabled); void setLighting(bool enabled);
void setBackfaceCulling(bool enabled); void setBackfaceCulling(bool enabled);
void setWireframe(bool enabled); void setWireframe(bool enabled);
@@ -163,7 +164,7 @@ class RTABMapApp : public UEventsHandler {
int optimizedMaxPolygons, int optimizedMaxPolygons,
float optimizedColorRadius, float optimizedColorRadius,
bool optimizedCleanWhitePolygons, bool optimizedCleanWhitePolygons,
bool optimizedColorWhitePolygons, int optimizedMinClusterSize,
float optimizedMaxTextureDistance, float optimizedMaxTextureDistance,
int optimizedMinTextureClusterSize, int optimizedMinTextureClusterSize,
bool blockRendering); bool blockRendering);
+8 -2
View File
@@ -180,6 +180,12 @@ Java_com_introlab_rtabmap_RTABMapLib_setOrthoCropFactor(
return app.setOrthoCropFactor(value); return app.setOrthoCropFactor(value);
} }
JNIEXPORT void JNICALL JNIEXPORT void JNICALL
Java_com_introlab_rtabmap_RTABMapLib_setGridRotation(
JNIEnv*, jobject, float value)
{
return app.setGridRotation(value);
}
JNIEXPORT void JNICALL
Java_com_introlab_rtabmap_RTABMapLib_setLighting( Java_com_introlab_rtabmap_RTABMapLib_setLighting(
JNIEnv*, jobject, bool enabled) JNIEnv*, jobject, bool enabled)
{ {
@@ -371,7 +377,7 @@ Java_com_introlab_rtabmap_RTABMapLib_exportMesh(
int optimizedMaxPolygons, int optimizedMaxPolygons,
float optimizedColorRadius, float optimizedColorRadius,
bool optimizedCleanWhitePolygons, bool optimizedCleanWhitePolygons,
bool optimizedColorWhitePolygons, int optimizedMinClusterSize,
float optimizedMaxTextureDistance, float optimizedMaxTextureDistance,
int optimizedMinTextureClusterSize, int optimizedMinTextureClusterSize,
bool blockRendering) bool blockRendering)
@@ -389,7 +395,7 @@ Java_com_introlab_rtabmap_RTABMapLib_exportMesh(
optimizedMaxPolygons, optimizedMaxPolygons,
optimizedColorRadius, optimizedColorRadius,
optimizedCleanWhitePolygons, optimizedCleanWhitePolygons,
optimizedColorWhitePolygons, optimizedMinClusterSize,
optimizedMaxTextureDistance, optimizedMaxTextureDistance,
optimizedMinTextureClusterSize, optimizedMinTextureClusterSize,
blockRendering); blockRendering);
+2
View File
@@ -70,6 +70,7 @@ private:
bool isVisible() const {return visible_;} bool isVisible() const {return visible_;}
bool hasMesh() const {return polygons_.size()!=0;} bool hasMesh() const {return polygons_.size()!=0;}
bool hasTexture() const {return textures_ != 0;} bool hasTexture() const {return textures_ != 0;}
float getMinHeight() const {return minHeight_;}
const pcl::PointXYZ & aabbMinModel() const {return aabbMinModel_;} const pcl::PointXYZ & aabbMinModel() const {return aabbMinModel_;}
const pcl::PointXYZ & aabbMaxModel() const {return aabbMaxModel_;} const pcl::PointXYZ & aabbMaxModel() const {return aabbMaxModel_;}
const pcl::PointXYZ & aabbMinWorld() const {return aabbMinWorld_;} const pcl::PointXYZ & aabbMinWorld() const {return aabbMinWorld_;}
@@ -126,6 +127,7 @@ private:
bool visible_; bool visible_;
bool hasNormals_; bool hasNormals_;
std::vector<unsigned int> organizedToDenseIndices_; std::vector<unsigned int> organizedToDenseIndices_;
float minHeight_; // odom frame
float gainR_; float gainR_;
float gainG_; float gainG_;
+71 -2
View File
@@ -16,12 +16,16 @@
#include <tango-gl/conversions.h> #include <tango-gl/conversions.h>
#include <tango-gl/gesture_camera.h> #include <tango-gl/gesture_camera.h>
#include <tango-gl/util.h>
#include <rtabmap/utilite/ULogger.h> #include <rtabmap/utilite/ULogger.h>
#include <rtabmap/utilite/UStl.h> #include <rtabmap/utilite/UStl.h>
#include <rtabmap/utilite/UTimer.h> #include <rtabmap/utilite/UTimer.h>
#include <rtabmap/core/util3d_filtering.h> #include <rtabmap/core/util3d_filtering.h>
#include <rtabmap/core/util3d_transforms.h>
#include <rtabmap/core/util3d_surface.h>
#include <pcl/common/transforms.h> #include <pcl/common/transforms.h>
#include <pcl/common/common.h>
#include <glm/gtx/transform.hpp> #include <glm/gtx/transform.hpp>
@@ -32,7 +36,7 @@
// add an offset in z to our origin. We'll set this offset to 1.3 meters based // add an offset in z to our origin. We'll set this offset to 1.3 meters based
// on the average height of a human standing with a Tango device. This allows us // on the average height of a human standing with a Tango device. This allows us
// to place a grid roughly on the ground for most users. // to place a grid roughly on the ground for most users.
const glm::vec3 kHeightOffset = glm::vec3(0.0f, 1.3f, 0.0f); const glm::vec3 kHeightOffset = glm::vec3(0.0f, -1.3f, 0.0f);
// Color of the motion tracking trajectory. // Color of the motion tracking trajectory.
const tango_gl::Color kTraceColor(0.66f, 0.66f, 0.66f); const tango_gl::Color kTraceColor(0.66f, 0.66f, 0.66f);
@@ -130,7 +134,7 @@ void Scene::InitGLContent()
trace_->ClearVertexArray(); trace_->ClearVertexArray();
trace_->SetColor(kTraceColor); trace_->SetColor(kTraceColor);
grid_->SetColor(kGridColor); grid_->SetColor(kGridColor);
grid_->SetPosition(-kHeightOffset); grid_->SetPosition(kHeightOffset);
box_->SetShader(); box_->SetShader();
box_->SetColor(1,0,0); box_->SetColor(1,0,0);
@@ -194,6 +198,10 @@ void Scene::clear()
graph_ = 0; graph_ = 0;
} }
pointClouds_.clear(); pointClouds_.clear();
if(grid_)
{
grid_->SetPosition(kHeightOffset);
}
} }
//Should only be called in OpenGL thread! //Should only be called in OpenGL thread!
@@ -565,6 +573,15 @@ void Scene::setOrthoCropFactor(float value)
{ {
gesture_camera_->SetOrthoCropFactor(value); gesture_camera_->SetOrthoCropFactor(value);
} }
void Scene::setGridRotation(float angleDeg)
{
float angleRad = angleDeg * DEGREE_2_RADIANS;
if(grid_)
{
glm::quat rot = glm::rotate(glm::quat(1,0,0,0), angleRad, glm::vec3(0, 1, 0));
grid_->SetRotation(rot);
}
}
rtabmap::Transform Scene::GetOpenGLCameraPose(float * fov) const rtabmap::Transform Scene::GetOpenGLCameraPose(float * fov) const
{ {
@@ -669,6 +686,58 @@ void Scene::addMesh(
PointCloudDrawable * drawable = new PointCloudDrawable(mesh, createWireframe); PointCloudDrawable * drawable = new PointCloudDrawable(mesh, createWireframe);
drawable->setPose(pose); drawable->setPose(pose);
pointClouds_.insert(std::make_pair(id, drawable)); pointClouds_.insert(std::make_pair(id, drawable));
if(!mesh.pose.isNull() && mesh.cloud->size() && (!mesh.cloud->isOrganized() || mesh.indices->size()))
{
UTimer time;
float height = 0.0f;
Eigen::Affine3f affinePose = mesh.pose.toEigen3f();
if(mesh.polygons.size())
{
for(unsigned int i=0; i<mesh.polygons.size(); ++i)
{
for(unsigned int j=0; j<mesh.polygons[i].vertices.size(); ++j)
{
pcl::PointXYZRGB pt = pcl::transformPoint(mesh.cloud->at(mesh.polygons[i].vertices[j]), affinePose);
if(pt.z < height)
{
height = pt.z;
}
}
}
}
else
{
if(mesh.cloud->isOrganized())
{
for(unsigned int i=0; i<mesh.indices->size(); ++i)
{
pcl::PointXYZRGB pt = pcl::transformPoint(mesh.cloud->at(mesh.indices->at(i)), affinePose);
if(pt.z < height)
{
height = pt.z;
}
}
}
else
{
for(unsigned int i=0; i<mesh.cloud->size(); ++i)
{
pcl::PointXYZRGB pt = pcl::transformPoint(mesh.cloud->at(i), affinePose);
if(pt.z < height)
{
height = pt.z;
}
}
}
}
if(grid_->GetPosition().y == kHeightOffset.y || grid_->GetPosition().y > height)
{
grid_->SetPosition(glm::vec3(0,height,0));
}
LOGD("compute min height %f s", time.ticks());
}
} }
+1
View File
@@ -129,6 +129,7 @@ class Scene {
void setPointSize(float size) {pointSize_ = size;} void setPointSize(float size) {pointSize_ = size;}
void setFOV(float angle); void setFOV(float angle);
void setOrthoCropFactor(float value); void setOrthoCropFactor(float value);
void setGridRotation(float angleDeg);
void setLighting(bool enabled) {lighting_ = enabled;} void setLighting(bool enabled) {lighting_ = enabled;}
void setBackfaceCulling(bool enabled) {backfaceCulling_ = enabled;} void setBackfaceCulling(bool enabled) {backfaceCulling_ = enabled;}
void setWireframe(bool enabled) {wireFrame_ = enabled;} void setWireframe(bool enabled) {wireFrame_ = enabled;}
+21 -17
View File
@@ -63,11 +63,8 @@ GestureCamera::~GestureCamera() { delete cam_parent_transform_; }
void GestureCamera::OnTouchEvent(int touch_count, TouchEvent event, float x0, void GestureCamera::OnTouchEvent(int touch_count, TouchEvent event, float x0,
float y0, float x1, float y1) { float y0, float x1, float y1) {
if (camera_type_ == kFirstPerson) {
return;
}
if (touch_count == 1) { if (camera_type_!=kFirstPerson && touch_count == 1) {
switch (event) { switch (event) {
case kTouch0Down: { case kTouch0Down: {
cam_start_angle_ = cam_cur_angle_; cam_start_angle_ = cam_cur_angle_;
@@ -100,6 +97,7 @@ void GestureCamera::OnTouchEvent(int touch_count, TouchEvent event, float x0,
float abs_y = y0 - y1; float abs_y = y0 - y1;
start_touch_dist_ = std::sqrt(abs_x * abs_x + abs_y * abs_y); start_touch_dist_ = std::sqrt(abs_x * abs_x + abs_y * abs_y);
cam_start_dist_ = GetPosition().z; cam_start_dist_ = GetPosition().z;
cam_start_fov_ = this->getFOV();
// center touch // center touch
touch0_start_position_.x = (x0+x1)/2.0f; touch0_start_position_.x = (x0+x1)/2.0f;
@@ -111,25 +109,31 @@ void GestureCamera::OnTouchEvent(int touch_count, TouchEvent event, float x0,
float abs_y = y0 - y1; float abs_y = y0 - y1;
float dist = start_touch_dist_ - std::sqrt(abs_x * abs_x + abs_y * abs_y); float dist = start_touch_dist_ - std::sqrt(abs_x * abs_x + abs_y * abs_y);
cam_cur_dist_ = tango_gl::util::Clamp(cam_start_dist_ + dist * kZoomSpeed, if(camera_type_ == kFirstPerson)
kCamViewMinDist, kCamViewMaxDist);
this->SetOrthoMode(camera_type_ == kTopOrtho);
if(camera_type_ == kTopOrtho)
{ {
this->SetOrthoScale(cam_cur_dist_); this->SetFieldOfView(tango_gl::util::Clamp(cam_start_fov_ + dist * kZoomSpeed*10.0f, 45, 90));
} }
else
{
cam_cur_dist_ = tango_gl::util::Clamp(cam_start_dist_ + dist * kZoomSpeed,
kCamViewMinDist, kCamViewMaxDist);
glm::vec2 touch_center_position((x0+x1)/2.0f, (y0+y1)/2.0f); this->SetOrthoMode(camera_type_ == kTopOrtho);
glm::vec2 offset; if(camera_type_ == kTopOrtho)
offset.x = (touch_center_position.x - touch0_start_position_.x) * kMoveSpeed; {
offset.y = (touch_center_position.y - touch0_start_position_.y) * kMoveSpeed; this->SetOrthoScale(cam_cur_dist_);
touch0_start_position_ = touch_center_position; }
StartCameraToCurrentTransform(); glm::vec2 touch_center_position((x0+x1)/2.0f, (y0+y1)/2.0f);
glm::vec2 offset;
offset.x = (touch_center_position.x - touch0_start_position_.x) * kMoveSpeed;
offset.y = (touch_center_position.y - touch0_start_position_.y) * kMoveSpeed;
touch0_start_position_ = touch_center_position;
anchor_offset_ += glm::rotate(cam_parent_transform_->GetRotation(), glm::vec3(-offset.x, offset.y, 0)); StartCameraToCurrentTransform();
anchor_offset_ += glm::rotate(cam_parent_transform_->GetRotation(), glm::vec3(-offset.x, offset.y, 0));
}
break; break;
} }
default: { break; } default: { break; }
@@ -81,6 +81,7 @@ class GestureCamera : public Camera {
glm::quat cam_cur_target_rot_; glm::quat cam_cur_target_rot_;
float cam_start_dist_; float cam_start_dist_;
float cam_start_fov_;
float cam_cur_dist_; float cam_cur_dist_;
glm::vec3 anchor_offset_; glm::vec3 anchor_offset_;
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item>
<shape>
<gradient
android:endColor="#00ffffff"
android:startColor="#ff686868"
android:useLevel="false" />
</shape>
</item>
</layer-list>
+38 -49
View File
@@ -25,7 +25,7 @@
<RelativeLayout <RelativeLayout
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="match_parent"
android:fitsSystemWindows="true"> android:fitsSystemWindows="true">
<ToggleButton <ToggleButton
@@ -35,7 +35,7 @@
android:layout_above="@+id/light_button" android:layout_above="@+id/light_button"
android:layout_alignLeft="@+id/light_button" android:layout_alignLeft="@+id/light_button"
android:layout_alignParentRight="true" android:layout_alignParentRight="true"
android:layout_marginBottom="15dp" android:layout_marginBottom="5dp"
android:layout_marginRight="5dp" android:layout_marginRight="5dp"
android:paddingRight="5dp" android:paddingRight="5dp"
android:textOff="@string/wireframe" android:textOff="@string/wireframe"
@@ -48,7 +48,7 @@
android:layout_above="@+id/backface_button" android:layout_above="@+id/backface_button"
android:layout_alignLeft="@+id/backface_button" android:layout_alignLeft="@+id/backface_button"
android:layout_alignParentRight="true" android:layout_alignParentRight="true"
android:layout_marginBottom="15dp" android:layout_marginBottom="5dp"
android:layout_marginRight="5dp" android:layout_marginRight="5dp"
android:paddingRight="5dp" android:paddingRight="5dp"
android:textOff="@string/light_off" android:textOff="@string/light_off"
@@ -58,60 +58,36 @@
android:id="@+id/backface_button" android:id="@+id/backface_button"
android:layout_width="100dp" android:layout_width="100dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_above="@+id/first_person_button" android:layout_above="@+id/camera_button"
android:layout_alignLeft="@+id/first_person_button" android:layout_alignRight="@+id/camera_button"
android:layout_alignParentRight="true" android:layout_alignParentRight="true"
android:layout_marginBottom="5dp" android:layout_marginBottom="15dp"
android:layout_marginRight="5dp" android:layout_marginRight="5dp"
android:paddingRight="5dp" android:paddingRight="5dp"
android:textOff="@string/backface_off" android:textOff="@string/backface_off"
android:textOn="@string/backface_on" /> android:textOn="@string/backface_on" />
<ToggleButton <com.introlab.rtabmap.NDSpinner
android:id="@+id/first_person_button" android:id="@+id/camera_button"
android:layout_width="100dp" android:layout_width="140dp"
android:layout_height="wrap_content" android:layout_height="40dp"
android:layout_above="@+id/third_person_button"
android:layout_alignLeft="@+id/third_person_button"
android:layout_alignParentRight="true"
android:layout_marginBottom="5dp"
android:layout_marginRight="5dp"
android:paddingRight="5dp"
android:textOff="@string/first_person"
android:textOn="@string/first_person" />
<ToggleButton
android:id="@+id/third_person_button"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:layout_above="@+id/top_down_button"
android:layout_alignParentRight="true"
android:layout_marginBottom="5dp"
android:layout_marginRight="5dp"
android:paddingRight="5dp"
android:textOff="@string/third_person"
android:textOn="@string/third_person" />
<ToggleButton
android:id="@+id/top_down_button"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true" android:layout_alignParentBottom="true"
android:layout_alignParentRight="true" android:layout_alignParentRight="true"
android:layout_marginRight="5dp" android:layout_marginRight="5dp"
android:layout_marginBottom="10dp"
android:paddingRight="5dp" android:paddingRight="5dp"
android:textOff="@string/top_down" android:paddingBottom="10dp"
android:textOn="@string/top_down" /> android:text="@string/camera_button"
android:spinnerMode="dropdown"/>
<ToggleButton <ToggleButton
android:id="@+id/pause_button" android:id="@+id/pause_button"
android:layout_width="100dp" android:layout_width="100dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_alignLeft="@+id/first_person_button" android:layout_marginRight="5dp"
android:layout_alignParentTop="true" android:layout_alignParentTop="true"
android:layout_marginTop="61dp" android:layout_marginTop="10dp"
android:layout_alignParentRight="true" android:layout_alignParentRight="true"
android:paddingRight="5dp"
android:textOff="@string/pause" android:textOff="@string/pause"
android:textOn="@string/resume" /> android:textOn="@string/resume" />
@@ -119,37 +95,50 @@
android:id="@+id/button_shareToSketchfab" android:id="@+id/button_shareToSketchfab"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginRight="5dp"
android:layout_alignParentTop="true" android:layout_alignParentTop="true"
android:layout_alignRight="@+id/pause_button" android:layout_marginTop="10dp"
android:layout_alignParentRight="true"
android:text="@string/share_to_sketchfab" /> android:text="@string/share_to_sketchfab" />
<Button <Button
android:id="@+id/button_saveOnDevice" android:id="@+id/button_saveOnDevice"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_alignParentTop="true" android:layout_alignRight="@+id/button_shareToSketchfab"
android:layout_toLeftOf="@+id/button_shareToSketchfab" android:layout_below="@+id/button_shareToSketchfab"
android:text="@string/save_to_file" /> android:text="@string/save_to_file" />
<Button <Button
android:id="@+id/close_visualization_button" android:id="@+id/close_visualization_button"
android:layout_width="200dp" android:layout_width="200dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_alignBaseline="@+id/top_down_button" android:layout_above="@+id/camera_button"
android:layout_alignBottom="@+id/top_down_button"
android:layout_centerHorizontal="true" android:layout_centerHorizontal="true"
android:paddingLeft="5dp"
android:text="@string/close_visualization" /> android:text="@string/close_visualization" />
<SeekBar <SeekBar
android:id="@+id/seekBar_fov" android:id="@+id/seekBar_ortho_cut"
android:layout_width="200dp" android:layout_width="200dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:rotation="270" android:rotation="270"
android:layout_above="@+id/light_button"
android:layout_alignParentLeft="true" android:layout_alignParentLeft="true"
android:layout_alignBaseline="@+id/first_person_button"
android:layout_gravity="center" android:layout_gravity="center"
android:layout_marginLeft="-50dp" /> android:layout_marginLeft="-50dp"
android:progressDrawable="@drawable/custom_seekbar" />
<SeekBar
android:id="@+id/seekBar_grid"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignBottom="@+id/camera_button"
android:layout_marginLeft="35dp"
android:paddingBottom="10dp"
android:progressDrawable="@drawable/custom_seekbar" />
</RelativeLayout> </RelativeLayout>
</RelativeLayout> </RelativeLayout>
@@ -292,6 +292,14 @@
android:summary="@string/pref_summary_opt_clean_white" android:summary="@string/pref_summary_opt_clean_white"
android:defaultValue="@string/pref_default_opt_clean_white"/> android:defaultValue="@string/pref_default_opt_clean_white"/>
<ListPreference
android:key="@string/pref_key_opt_min_cluster_size"
android:title="@string/pref_title_opt_min_cluster_size"
android:summary="@string/pref_summary_opt_min_cluster_size"
android:entries="@array/pref_opt_min_cluster_size_keys"
android:entryValues="@array/pref_opt_min_cluster_size_values"
android:defaultValue="@string/pref_default_opt_min_cluster_size"/>
</PreferenceCategory> </PreferenceCategory>
</PreferenceScreen> </PreferenceScreen>
<ListPreference <ListPreference
@@ -308,6 +316,11 @@
android:entries="@array/pref_cluster_ratio_keys" android:entries="@array/pref_cluster_ratio_keys"
android:entryValues="@array/pref_cluster_ratio_values" android:entryValues="@array/pref_cluster_ratio_values"
android:defaultValue="@string/pref_default_cluster_ratio"/> android:defaultValue="@string/pref_default_cluster_ratio"/>
<SwitchPreference
android:key="@string/pref_key_notification_sound"
android:title="@string/pref_title_notification_sound"
android:summary="@string/pref_summary_notification_sound"
android:defaultValue="@string/pref_default_notification_sound"/>
</PreferenceCategory> </PreferenceCategory>
<PreferenceCategory <PreferenceCategory
android:title="@string/pref_title_presets"> android:title="@string/pref_title_presets">
+9
View File
@@ -0,0 +1,9 @@
<resources>
<string-array name="camera_view_array">
<item>First View</item>
<item>Third-P. View</item>
<item>Top View</item>
<item>Ortho View</item>
</string-array>
</resources>
+20 -6
View File
@@ -8,9 +8,7 @@
<string name="sketchfab">Upload to Sketchfab&#8230;</string> <string name="sketchfab">Upload to Sketchfab&#8230;</string>
<string name="status">"Status: "</string> <string name="status">"Status: "</string>
<string name="words">"Words: "</string> <string name="words">"Words: "</string>
<string name="first_person">First</string> <string name="camera_button">First View</string>
<string name="third_person">Third</string>
<string name="top_down">Top</string>
<string name="pause">Pause</string> <string name="pause">Pause</string>
<string name="resume">Resume</string> <string name="resume">Resume</string>
<string name="backface_on">Backface</string> <string name="backface_on">Backface</string>
@@ -126,10 +124,14 @@
<string name="pref_default_opt_color_radius">0.05</string> <string name="pref_default_opt_color_radius">0.05</string>
<string name="pref_key_opt_clean_white">pref_key_opt_clean_white</string> <string name="pref_key_opt_clean_white">pref_key_opt_clean_white</string>
<string name="pref_default_opt_clean_white">true</string> <string name="pref_default_opt_clean_white">true</string>
<string name="pref_key_opt_min_cluster_size">pref_key_opt_min_cluster_size</string>
<string name="pref_default_opt_min_cluster_size">0</string>
<string name="pref_key_gain_max_radius">pref_key_gain_max_radius</string> <string name="pref_key_gain_max_radius">pref_key_gain_max_radius</string>
<string name="pref_default_gain_max_radius">0.02</string> <string name="pref_default_gain_max_radius">0.02</string>
<string name="pref_key_cluster_ratio">pref_key_cluster_ratio</string> <string name="pref_key_cluster_ratio">pref_key_cluster_ratio</string>
<string name="pref_default_cluster_ratio">0.05</string> <string name="pref_default_cluster_ratio">0.05</string>
<string name="pref_key_notification_sound">pref_key_notification_sound</string>
<string name="pref_default_notification_sound">true</string>
<!-- Preference keys: END --> <!-- Preference keys: END -->
<string name="pref_title_rendering">Rendering</string> <string name="pref_title_rendering">Rendering</string>
@@ -308,7 +310,7 @@
<string name="pref_title_smoothing">Smoothing</string> <string name="pref_title_smoothing">Smoothing</string>
<string name="pref_summary_smoothing">Smooth the point clouds.</string> <string name="pref_summary_smoothing">Smooth the point clouds.</string>
<string name="pref_title_fisheye">Fish Eye Camera</string> <string name="pref_title_fisheye">Fish Eye Camera</string>
<string name="pref_summary_fisheye">Use fish eye camera instead of the color camera. Cannot be used on Yellowstone tablet.</string> <string name="pref_summary_fisheye">Use fish eye camera instead of the color camera. May not work on some devices.</string>
<string name="pref_title_update_rate">Update Rate</string> <string name="pref_title_update_rate">Update Rate</string>
<string name="pref_summary_update_rate">Rate at which a new node is added to map.</string> <string name="pref_summary_update_rate">Rate at which a new node is added to map.</string>
<string name="pref_title_time_thr">Time Limit</string> <string name="pref_title_time_thr">Time Limit</string>
@@ -659,22 +661,22 @@
<item>"2"</item> <item>"2"</item>
</string-array> </string-array>
<string-array name="pref_min_texture_cluster_size_keys"> <string-array name="pref_min_texture_cluster_size_keys">
<item>"Disabled"</item>
<item>"1000"</item> <item>"1000"</item>
<item>"500"</item> <item>"500"</item>
<item>"200"</item> <item>"200"</item>
<item>"100"</item> <item>"100"</item>
<item>"50"</item> <item>"50"</item>
<item>"10"</item> <item>"10"</item>
<item>"Disabled"</item>
</string-array> </string-array>
<string-array name="pref_min_texture_cluster_size_values"> <string-array name="pref_min_texture_cluster_size_values">
<item>"0"</item>
<item>"1000"</item> <item>"1000"</item>
<item>"500"</item> <item>"500"</item>
<item>"200"</item> <item>"200"</item>
<item>"100"</item> <item>"100"</item>
<item>"50"</item> <item>"50"</item>
<item>"10"</item> <item>"10"</item>
<item>"0"</item>
</string-array> </string-array>
<string name="pref_title_optimized">Optimized</string> <string name="pref_title_optimized">Optimized</string>
@@ -686,6 +688,8 @@
<string name="pref_summary_opt_color_radius">Radius used to transfer nearest color from the point cloud to reconstructed mesh. When exporting with texture, if Clean Mesh is also enabled, this will limit the number of polygons textured in holes.</string> <string name="pref_summary_opt_color_radius">Radius used to transfer nearest color from the point cloud to reconstructed mesh. When exporting with texture, if Clean Mesh is also enabled, this will limit the number of polygons textured in holes.</string>
<string name="pref_title_opt_clean_white">Clean Mesh</string> <string name="pref_title_opt_clean_white">Clean Mesh</string>
<string name="pref_summary_opt_clean_white">Clean mesh from textureless or colorless reconstructed polygons.</string> <string name="pref_summary_opt_clean_white">Clean mesh from textureless or colorless reconstructed polygons.</string>
<string name="pref_summary_opt_min_cluster_size">This can be used to filter polygons before texturing.</string>
<string name="pref_title_opt_min_cluster_size">Polygon Filtering</string>
<string-array name="pref_opt_depth_keys"> <string-array name="pref_opt_depth_keys">
<item>"Auto"</item> <item>"Auto"</item>
@@ -735,12 +739,22 @@
<item>"0.01"</item> <item>"0.01"</item>
<item>"-1"</item> <item>"-1"</item>
</string-array> </string-array>
<string-array name="pref_opt_min_cluster_size_keys">
<item>"Only biggest cluster kept"</item>
<item>"Keep all polygons"</item>
</string-array>
<string-array name="pref_opt_min_cluster_size_values">
<item>"-1"</item>
<item>"0"</item>
</string-array>
<string name="pref_title_general">General</string> <string name="pref_title_general">General</string>
<string name="pref_title_gain_max_radius">Color Correction Radius</string> <string name="pref_title_gain_max_radius">Color Correction Radius</string>
<string name="pref_summary_gain_max_radius">Radius used to find pixel correspondences for Adjust Colors optimization.</string> <string name="pref_summary_gain_max_radius">Radius used to find pixel correspondences for Adjust Colors optimization.</string>
<string name="pref_title_cluster_ratio">Noise Filtering Ratio</string> <string name="pref_title_cluster_ratio">Noise Filtering Ratio</string>
<string name="pref_summary_cluster_ratio">Polygon clusters with size smaller than this ratio of the largest cluster are removed by the Noise Filtering optimization.</string> <string name="pref_summary_cluster_ratio">Polygon clusters with size smaller than this ratio of the largest cluster are removed by the Noise Filtering optimization.</string>
<string name="pref_title_notification_sound">Notification Sound</string>
<string name="pref_summary_notification_sound">After saving database or preparing data to export, a notification sound is played.</string>
<string-array name="pref_gain_max_radius_keys"> <string-array name="pref_gain_max_radius_keys">
<item>"0.3 m"</item> <item>"0.3 m"</item>
+10
View File
@@ -0,0 +1,10 @@
<resources>
<style name="ThemeActionBar" parent="@android:style/Widget.DeviceDefault.ActionBar.Solid">
<item name="android:background">#20000000</item>
</style>
<style name="ThemeApp" parent="@android:style/Theme.DeviceDefault">
<item name="android:actionBarStyle">@style/ThemeActionBar</item>
<item name="android:windowActionBarOverlay">true</item>
</style>
</resources>
@@ -0,0 +1,43 @@
package com.introlab.rtabmap;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.Spinner;
/** Spinner extension that calls onItemSelected even when the selection is the same as its previous value
Author: Mattia Ruggiero
https://stackoverflow.com/questions/5335306/how-can-i-get-an-event-in-android-spinner-when-the-current-selected-item-is-sele
*/
public class NDSpinner extends Spinner {
public NDSpinner(Context context)
{ super(context); }
public NDSpinner(Context context, AttributeSet attrs)
{ super(context, attrs); }
public NDSpinner(Context context, AttributeSet attrs, int defStyle)
{ super(context, attrs, defStyle); }
@Override
public void setSelection(int position, boolean animate) {
boolean sameSelected = position == getSelectedItemPosition();
super.setSelection(position, animate);
if (sameSelected) {
// Spinner does not call the OnItemSelectedListener if the same item is selected, so do it manually now
//getOnItemSelectedListener().onItemSelected(this, getSelectedView(), position, getSelectedItemId());
}
}
@Override
public void setSelection(int position) {
boolean sameSelected = position == getSelectedItemPosition();
super.setSelection(position);
if (sameSelected) {
// Spinner does not call the OnItemSelectedListener if the same item is selected, so do it manually now
getOnItemSelectedListener().onItemSelected(this, getSelectedView(), position, getSelectedItemId());
}
}
}
@@ -89,6 +89,9 @@ import android.view.WindowManager;
import android.view.inputmethod.EditorInfo; import android.view.inputmethod.EditorInfo;
import android.webkit.WebView; import android.webkit.WebView;
import android.webkit.WebViewClient; import android.webkit.WebViewClient;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.Button; import android.widget.Button;
import android.widget.EditText; import android.widget.EditText;
import android.widget.LinearLayout; import android.widget.LinearLayout;
@@ -96,6 +99,7 @@ import android.widget.NumberPicker;
import android.widget.RelativeLayout; import android.widget.RelativeLayout;
import android.widget.SeekBar; import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener; import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.Spinner;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import android.widget.ToggleButton; import android.widget.ToggleButton;
@@ -104,7 +108,7 @@ import com.google.atap.tangoservice.Tango;
// The main activity of the application. This activity shows debug information // The main activity of the application. This activity shows debug information
// and a glSurfaceView that renders graphic content. // and a glSurfaceView that renders graphic content.
public class RTABMapActivity extends Activity implements OnClickListener { public class RTABMapActivity extends Activity implements OnClickListener, OnItemSelectedListener {
// Tag for debug logging. // Tag for debug logging.
public static final String TAG = RTABMapActivity.class.getSimpleName(); public static final String TAG = RTABMapActivity.class.getSimpleName();
@@ -134,7 +138,6 @@ public class RTABMapActivity extends Activity implements OnClickListener {
public static final long NOTOUCH_TIMEOUT = 5000; // 5 sec public static final long NOTOUCH_TIMEOUT = 5000; // 5 sec
private boolean mHudVisible = true; private boolean mHudVisible = true;
private boolean mTipOrthoShown_ = false;
private int mSavedRenderingType = 0; private int mSavedRenderingType = 0;
private boolean mMenuOpened = false; private boolean mMenuOpened = false;
@@ -182,9 +185,7 @@ public class RTABMapActivity extends Activity implements OnClickListener {
private MenuItem mItemStatusVisibility; private MenuItem mItemStatusVisibility;
private MenuItem mItemDebugVisibility; private MenuItem mItemDebugVisibility;
private ToggleButton mButtonFirst; private NDSpinner mButtonCameraView;
private ToggleButton mButtonThird;
private ToggleButton mButtonTop;
private ToggleButton mButtonPause; private ToggleButton mButtonPause;
private ToggleButton mButtonLighting; private ToggleButton mButtonLighting;
private ToggleButton mButtonWireframe; private ToggleButton mButtonWireframe;
@@ -192,7 +193,8 @@ public class RTABMapActivity extends Activity implements OnClickListener {
private Button mButtonCloseVisualization; private Button mButtonCloseVisualization;
private Button mButtonSaveOnDevice; private Button mButtonSaveOnDevice;
private Button mButtonShareOnSketchfab; private Button mButtonShareOnSketchfab;
private SeekBar mSeekBarFov; private SeekBar mSeekBarOrthoCut;
private SeekBar mSeekBarGrid;
private String mOpenedDatabasePath = ""; private String mOpenedDatabasePath = "";
private String mWorkingDirectory = ""; private String mWorkingDirectory = "";
@@ -255,6 +257,7 @@ public class RTABMapActivity extends Activity implements OnClickListener {
display.getSize(mScreenSize); display.getSize(mScreenSize);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
// Setting content view of this activity. // Setting content view of this activity.
setContentView(R.layout.activity_rtabmap); setContentView(R.layout.activity_rtabmap);
@@ -267,9 +270,7 @@ public class RTABMapActivity extends Activity implements OnClickListener {
mActionBarHeight = getActionBarHeight(); mActionBarHeight = getActionBarHeight();
// Buttons for selecting camera view and Set up button click listeners. // Buttons for selecting camera view and Set up button click listeners.
mButtonFirst = (ToggleButton)findViewById(R.id.first_person_button); mButtonCameraView = (NDSpinner)findViewById(R.id.camera_button);
mButtonThird = (ToggleButton)findViewById(R.id.third_person_button);
mButtonTop = (ToggleButton)findViewById(R.id.top_down_button);
mButtonPause = (ToggleButton)findViewById(R.id.pause_button); mButtonPause = (ToggleButton)findViewById(R.id.pause_button);
mButtonLighting = (ToggleButton)findViewById(R.id.light_button); mButtonLighting = (ToggleButton)findViewById(R.id.light_button);
mButtonWireframe = (ToggleButton)findViewById(R.id.wireframe_button); mButtonWireframe = (ToggleButton)findViewById(R.id.wireframe_button);
@@ -277,9 +278,7 @@ public class RTABMapActivity extends Activity implements OnClickListener {
mButtonCloseVisualization = (Button)findViewById(R.id.close_visualization_button); mButtonCloseVisualization = (Button)findViewById(R.id.close_visualization_button);
mButtonSaveOnDevice = (Button)findViewById(R.id.button_saveOnDevice); mButtonSaveOnDevice = (Button)findViewById(R.id.button_saveOnDevice);
mButtonShareOnSketchfab = (Button)findViewById(R.id.button_shareToSketchfab); mButtonShareOnSketchfab = (Button)findViewById(R.id.button_shareToSketchfab);
mButtonFirst.setOnClickListener(this); mButtonCameraView.setOnItemSelectedListener(this);
mButtonThird.setOnClickListener(this);
mButtonTop.setOnClickListener(this);
mButtonPause.setOnClickListener(this); mButtonPause.setOnClickListener(this);
mButtonLighting.setOnClickListener(this); mButtonLighting.setOnClickListener(this);
mButtonWireframe.setOnClickListener(this); mButtonWireframe.setOnClickListener(this);
@@ -287,7 +286,6 @@ public class RTABMapActivity extends Activity implements OnClickListener {
mButtonCloseVisualization.setOnClickListener(this); mButtonCloseVisualization.setOnClickListener(this);
mButtonSaveOnDevice.setOnClickListener(this); mButtonSaveOnDevice.setOnClickListener(this);
mButtonShareOnSketchfab.setOnClickListener(this); mButtonShareOnSketchfab.setOnClickListener(this);
mButtonFirst.setChecked(true);
mButtonLighting.setChecked(false); mButtonLighting.setChecked(false);
mButtonLighting.setVisibility(View.INVISIBLE); mButtonLighting.setVisibility(View.INVISIBLE);
mButtonWireframe.setChecked(false); mButtonWireframe.setChecked(false);
@@ -300,20 +298,43 @@ public class RTABMapActivity extends Activity implements OnClickListener {
mButtonBackfaceShown.setVisibility(mItemRenderingMesh.isChecked() || mItemRenderingTextureMesh.isChecked()?View.VISIBLE:View.INVISIBLE); mButtonBackfaceShown.setVisibility(mItemRenderingMesh.isChecked() || mItemRenderingTextureMesh.isChecked()?View.VISIBLE:View.INVISIBLE);
} }
mSeekBarFov = (SeekBar)findViewById(R.id.seekBar_fov); ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this, R.array.camera_view_array, android.R.layout.simple_spinner_item);
mSeekBarFov.setMax(45); adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
mSeekBarFov.setProgress(20); mButtonCameraView.setAdapter(adapter);
mSeekBarFov.setOnSeekBarChangeListener(new OnSeekBarChangeListener() { mButtonCameraView.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
resetNoTouchTimer();
return false;
}
});
mSeekBarOrthoCut = (SeekBar)findViewById(R.id.seekBar_ortho_cut);
mSeekBarOrthoCut.setMax(120);
mSeekBarOrthoCut.setProgress(80);
mSeekBarOrthoCut.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
@Override @Override
public void onProgressChanged(SeekBar seekBar, int progressValue, boolean fromUser) { public void onProgressChanged(SeekBar seekBar, int progressValue, boolean fromUser) {
if(mButtonFirst.isChecked()) RTABMapLib.setOrthoCropFactor((float)(120-progressValue)/20.0f - 3.0f);
{ resetNoTouchTimer();
RTABMapLib.setFOV((float)progressValue+45.0f); }
}
else if(mButtonTop.isChecked()) @Override
{ public void onStartTrackingTouch(SeekBar seekBar) {
RTABMapLib.setOrthoCropFactor((float)(120-progressValue)/20.0f - 3.0f); }
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
mSeekBarGrid = (SeekBar)findViewById(R.id.seekBar_grid);
mSeekBarGrid.setMax(180);
mSeekBarGrid.setProgress(90);
mSeekBarGrid.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progressValue, boolean fromUser) {
RTABMapLib.setGridRotation(((float)progressValue-90.0f)/2.0f);
resetNoTouchTimer(); resetNoTouchTimer();
} }
@@ -340,7 +361,7 @@ public class RTABMapActivity extends Activity implements OnClickListener {
@Override @Override
public boolean onTouch(View v, MotionEvent event) { public boolean onTouch(View v, MotionEvent event) {
resetNoTouchTimer(); resetNoTouchTimer(getActionBar().isShowing() && mHudVisible == false);
mGesDetect.onTouchEvent(event); mGesDetect.onTouchEvent(event);
@@ -701,7 +722,7 @@ public class RTABMapActivity extends Activity implements OnClickListener {
} }
TangoInitializationHelper.bindTangoService(getActivity(), mTangoServiceConnection); TangoInitializationHelper.bindTangoService(getActivity(), mTangoServiceConnection);
resetNoTouchTimer(); resetNoTouchTimer(true);
} }
private void setCamera(int type) private void setCamera(int type)
@@ -714,28 +735,13 @@ public class RTABMapActivity extends Activity implements OnClickListener {
updateStatusTexts(); updateStatusTexts();
RTABMapLib.setCamera(type); RTABMapLib.setCamera(type);
mButtonFirst.setChecked(type==0); mButtonCameraView.setSelection(type, true);
mButtonThird.setChecked(type==1); mSeekBarOrthoCut.setVisibility(type!=3?View.INVISIBLE:View.VISIBLE);
mButtonTop.setChecked(type==2 || type==3); mSeekBarGrid.setVisibility(mSeekBarGrid.isEnabled() && type==3?View.VISIBLE:View.INVISIBLE);
mButtonTop.setText(type==3?"Ortho":"Top");
mButtonTop.setTextOn(type==3?"Ortho":"Top");
mButtonTop.setTextOff(type==3?"Ortho":"Top");
mSeekBarFov.setVisibility(type!=0 && type!=3?View.INVISIBLE:View.VISIBLE);
if(type==0)
{
mSeekBarFov.setMax(45);
mSeekBarFov.setProgress(20);
}
if(type==3) if(type==3)
{ {
mSeekBarFov.setMax(120); mSeekBarOrthoCut.setMax(120);
mSeekBarFov.setProgress(80); mSeekBarOrthoCut.setProgress(80);
}
if(type==2 && !mTipOrthoShown_)
{
mToast.makeText(this, "Tip: Click again on Top to set Ortho mode.", mToast.LENGTH_LONG).show();
mTipOrthoShown_ = true;
} }
} }
@@ -743,15 +749,8 @@ public class RTABMapActivity extends Activity implements OnClickListener {
public void onClick(View v) { public void onClick(View v) {
// Handle button clicks. // Handle button clicks.
switch (v.getId()) { switch (v.getId()) {
case R.id.first_person_button: case R.id.gl_surface_view:
setCamera(0);
break;
case R.id.third_person_button:
setCamera(1);
break;
case R.id.top_down_button:
setCamera(mButtonFirst.isChecked() || mButtonThird.isChecked() || mButtonTop.getTextOn().equals("Ortho")?2:3);
break; break;
case R.id.pause_button: case R.id.pause_button:
pauseMapping(); pauseMapping();
@@ -793,6 +792,15 @@ public class RTABMapActivity extends Activity implements OnClickListener {
resetNoTouchTimer(); resetNoTouchTimer();
} }
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
setCamera(pos);
resetNoTouchTimer();
}
public void onNothingSelected(AdapterView<?> parent) {
resetNoTouchTimer();
}
private void setAndroidOrientation() { private void setAndroidOrientation() {
Display display = getWindowManager().getDefaultDisplay(); Display display = getWindowManager().getDefaultDisplay();
Camera.CameraInfo colorCameraInfo = new Camera.CameraInfo(); Camera.CameraInfo colorCameraInfo = new Camera.CameraInfo();
@@ -806,11 +814,26 @@ public class RTABMapActivity extends Activity implements OnClickListener {
@Override @Override
public boolean onDoubleTap(MotionEvent event) { public boolean onDoubleTap(MotionEvent event) {
if(!DISABLE_LOG) Log.i(TAG, "onDoubleTap");
float normalizedX = event.getX(0) / mScreenSize.x; float normalizedX = event.getX(0) / mScreenSize.x;
float normalizedY = event.getY(0) / mScreenSize.y; float normalizedY = event.getY(0) / mScreenSize.y;
RTABMapLib.onTouchEvent(3, event.getActionMasked(), normalizedX, normalizedY, 0.0f, 0.0f); RTABMapLib.onTouchEvent(3, event.getActionMasked(), normalizedX, normalizedY, 0.0f, 0.0f);
return true; return true;
} }
@Override
public boolean onSingleTapConfirmed(MotionEvent event) {
if(!DISABLE_LOG) Log.i(TAG, "onSingleTapConfirmed");
if(mHudVisible)
{
notouchHandler.removeCallbacks(notouchCallback);
notouchHandler.postDelayed(notouchCallback, 0);
}
else
{
resetNoTouchTimer(true);
}
return true;
}
} }
@Override @Override
@@ -1146,9 +1169,9 @@ public class RTABMapActivity extends Activity implements OnClickListener {
} }
updateState(State.STATE_VISUALIZING_WHILE_LOADING); updateState(State.STATE_VISUALIZING_WHILE_LOADING);
if(mButtonFirst.isChecked()) if(mButtonCameraView.getSelectedItemPosition() == 0)
{ {
setCamera(1); setCamera(2);
} }
mToast.makeText(getActivity(), String.format("Optimized mesh detected in the database, it is shown while the database is loading..."), mToast.LENGTH_LONG).show(); mToast.makeText(getActivity(), String.format("Optimized mesh detected in the database, it is shown while the database is loading..."), mToast.LENGTH_LONG).show();
mProgressDialog.dismiss(); mProgressDialog.dismiss();
@@ -1348,13 +1371,19 @@ public class RTABMapActivity extends Activity implements OnClickListener {
}; };
public void resetNoTouchTimer(){ public void resetNoTouchTimer(){
if(!mHudVisible) resetNoTouchTimer(false);
}
public void resetNoTouchTimer(boolean showHud){
if(showHud)
{ {
setNavVisibility(true);
mHudVisible = true; mHudVisible = true;
updateState(mState); setNavVisibility(true);
if(mItemSave != null)
{
updateState(mState);
}
} }
mHudVisible = true;
notouchHandler.removeCallbacks(notouchCallback); notouchHandler.removeCallbacks(notouchCallback);
notouchHandler.postDelayed(notouchCallback, NOTOUCH_TIMEOUT); notouchHandler.postDelayed(notouchCallback, NOTOUCH_TIMEOUT);
@@ -1371,6 +1400,7 @@ public class RTABMapActivity extends Activity implements OnClickListener {
mToast.makeText(getActivity(), String.format("Re-adding %d online clouds, this may take some time...", mMapNodes), mToast.LENGTH_LONG).show(); mToast.makeText(getActivity(), String.format("Re-adding %d online clouds, this may take some time...", mMapNodes), mToast.LENGTH_LONG).show();
} }
mState = state; mState = state;
if(!DISABLE_LOG) Log.i(TAG, String.format("updateState() state=%s hud=%d", state.toString(), mHudVisible?1:0));
switch(state) switch(state)
{ {
case STATE_PROCESSING: case STATE_PROCESSING:
@@ -1438,11 +1468,10 @@ public class RTABMapActivity extends Activity implements OnClickListener {
mItemDataRecorderMode.setEnabled(mButtonPause.isChecked()); mItemDataRecorderMode.setEnabled(mButtonPause.isChecked());
break; break;
} }
mButtonFirst.setVisibility(mHudVisible?View.VISIBLE:View.INVISIBLE); mButtonCameraView.setVisibility(mHudVisible?View.VISIBLE:View.INVISIBLE);
mButtonThird.setVisibility(mHudVisible?View.VISIBLE:View.INVISIBLE);
mButtonTop.setVisibility(mHudVisible?View.VISIBLE:View.INVISIBLE);
mButtonBackfaceShown.setVisibility(mHudVisible && (mItemRenderingMesh.isChecked() || mItemRenderingTextureMesh.isChecked())?View.VISIBLE:View.INVISIBLE); mButtonBackfaceShown.setVisibility(mHudVisible && (mItemRenderingMesh.isChecked() || mItemRenderingTextureMesh.isChecked())?View.VISIBLE:View.INVISIBLE);
mSeekBarFov.setVisibility(mHudVisible && (mButtonFirst.isChecked() || (mButtonTop.isChecked() && mButtonTop.getTextOn().equals("Ortho")))?View.VISIBLE:View.INVISIBLE); mSeekBarOrthoCut.setVisibility(mHudVisible && mButtonCameraView.getSelectedItemPosition() == 3?View.VISIBLE:View.INVISIBLE);
mSeekBarGrid.setVisibility(mHudVisible && mSeekBarGrid.isEnabled() && mButtonCameraView.getSelectedItemPosition() == 3?View.VISIBLE:View.INVISIBLE);
} }
private void pauseMapping() { private void pauseMapping() {
@@ -1682,6 +1711,8 @@ public class RTABMapActivity extends Activity implements OnClickListener {
else if(itemId == R.id.grid_visible) else if(itemId == R.id.grid_visible)
{ {
item.setChecked(!item.isChecked()); item.setChecked(!item.isChecked());
mSeekBarGrid.setEnabled(item.isChecked());
mSeekBarGrid.setVisibility(mHudVisible && mSeekBarGrid.isEnabled()&&mButtonCameraView.getSelectedItemPosition() == 3?View.VISIBLE:View.INVISIBLE);
RTABMapLib.setGridVisible(item.isChecked()); RTABMapLib.setGridVisible(item.isChecked());
} }
else if (itemId == R.id.save) else if (itemId == R.id.save)
@@ -1727,6 +1758,7 @@ public class RTABMapActivity extends Activity implements OnClickListener {
.setNegativeButton("No", new DialogInterface.OnClickListener() { .setNegativeButton("No", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) { public void onClick(DialogInterface dialog, int which) {
dialog.dismiss(); dialog.dismiss();
resetNoTouchTimer(true);
} }
}) })
.show(); .show();
@@ -1993,7 +2025,7 @@ public class RTABMapActivity extends Activity implements OnClickListener {
final int optimizedDepth = Integer.parseInt(sharedPref.getString(getString(R.string.pref_key_opt_depth), getString(R.string.pref_default_opt_depth))); final int optimizedDepth = Integer.parseInt(sharedPref.getString(getString(R.string.pref_key_opt_depth), getString(R.string.pref_default_opt_depth)));
final float optimizedColorRadius = Float.parseFloat(sharedPref.getString(getString(R.string.pref_key_opt_color_radius), getString(R.string.pref_default_opt_color_radius))); final float optimizedColorRadius = Float.parseFloat(sharedPref.getString(getString(R.string.pref_key_opt_color_radius), getString(R.string.pref_default_opt_color_radius)));
final boolean optimizedCleanWhitePolygons = sharedPref.getBoolean(getString(R.string.pref_key_opt_clean_white), Boolean.parseBoolean(getString(R.string.pref_default_opt_clean_white))); final boolean optimizedCleanWhitePolygons = sharedPref.getBoolean(getString(R.string.pref_key_opt_clean_white), Boolean.parseBoolean(getString(R.string.pref_default_opt_clean_white)));
final boolean optimizedColorWhitePolygons = false;//sharedPref.getBoolean("pref_key_opt_color_white", false); // not used final int optimizedMinClusterSize = Integer.parseInt(sharedPref.getString(getString(R.string.pref_key_opt_min_cluster_size), getString(R.string.pref_default_opt_min_cluster_size)));
final boolean blockRendering = sharedPref.getBoolean(getString(R.string.pref_key_block_render), Boolean.parseBoolean(getString(R.string.pref_default_block_render))); final boolean blockRendering = sharedPref.getBoolean(getString(R.string.pref_key_block_render), Boolean.parseBoolean(getString(R.string.pref_default_block_render)));
@@ -2024,7 +2056,7 @@ public class RTABMapActivity extends Activity implements OnClickListener {
optimizedMaxPolygons, optimizedMaxPolygons,
optimizedColorRadius, optimizedColorRadius,
optimizedCleanWhitePolygons, optimizedCleanWhitePolygons,
optimizedColorWhitePolygons, optimizedMinClusterSize,
maxTextureDistance, maxTextureDistance,
minTextureClusterSize, minTextureClusterSize,
blockRendering); blockRendering);
@@ -2041,6 +2073,25 @@ public class RTABMapActivity extends Activity implements OnClickListener {
final long endTime = System.currentTimeMillis()/1000; final long endTime = System.currentTimeMillis()/1000;
if(endTime-startTime > 10)
{
// build notification
// the addAction re-use the same intent to keep the example short
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(getActivity());
boolean notifySound = sharedPref.getBoolean(getString(R.string.pref_key_notification_sound), Boolean.parseBoolean(getString(R.string.pref_default_notification_sound)));
Notification n = new Notification.Builder(getActivity())
.setContentTitle(getString(R.string.app_name))
.setContentText("Data generated and ready to be exported!")
.setSmallIcon(R.drawable.ic_launcher)
.setDefaults(notifySound?Notification.DEFAULT_SOUND:0)
.setAutoCancel(true).build();
NotificationManager notificationManager =
(NotificationManager) getSystemService(NOTIFICATION_SERVICE);
notificationManager.notify(0, n);
}
// Visualize the result? // Visualize the result?
AlertDialog d = new AlertDialog.Builder(getActivity()) AlertDialog d = new AlertDialog.Builder(getActivity())
.setCancelable(false) .setCancelable(false)
@@ -2048,7 +2099,7 @@ public class RTABMapActivity extends Activity implements OnClickListener {
.setMessage(Html.fromHtml("Do you want visualize the result before saving to file or sharing to <a href=\"https://sketchfab.com/about\">Sketchfab</a>?")) .setMessage(Html.fromHtml("Do you want visualize the result before saving to file or sharing to <a href=\"https://sketchfab.com/about\">Sketchfab</a>?"))
.setPositiveButton("Yes", new DialogInterface.OnClickListener() { .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) { public void onClick(DialogInterface dialog, int which) {
resetNoTouchTimer(); resetNoTouchTimer(true);
mSavedRenderingType = mItemRenderingPointCloud.isChecked()?0:mItemRenderingMesh.isChecked()?1:2; mSavedRenderingType = mItemRenderingPointCloud.isChecked()?0:mItemRenderingMesh.isChecked()?1:2;
if(!meshing) if(!meshing)
{ {
@@ -2069,7 +2120,7 @@ public class RTABMapActivity extends Activity implements OnClickListener {
} }
updateState(State.STATE_VISUALIZING); updateState(State.STATE_VISUALIZING);
RTABMapLib.postExportation(true); RTABMapLib.postExportation(true);
if(mButtonFirst.isChecked()) if(mButtonCameraView.getSelectedItemPosition() == 0)
{ {
setCamera(2); setCamera(2);
} }
@@ -2096,6 +2147,7 @@ public class RTABMapActivity extends Activity implements OnClickListener {
}) })
.setNeutralButton("Cancel", new DialogInterface.OnClickListener() { .setNeutralButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) { public void onClick(DialogInterface dialog, int which) {
resetNoTouchTimer(true);
} }
}) })
.create(); .create();
@@ -2111,7 +2163,7 @@ public class RTABMapActivity extends Activity implements OnClickListener {
} }
else else
{ {
updateState(State.STATE_IDLE); updateState(previousState);
mToast.makeText(getActivity(), String.format("Exporting map failed!"), mToast.LENGTH_LONG).show(); mToast.makeText(getActivity(), String.format("Exporting map failed!"), mToast.LENGTH_LONG).show();
} }
mExportProgressDialog.dismiss(); mExportProgressDialog.dismiss();
@@ -2142,45 +2194,51 @@ public class RTABMapActivity extends Activity implements OnClickListener {
mProgressDialog.setMessage(String.format("Please wait while saving \"%s\"...", newDatabasePathHuman)); mProgressDialog.setMessage(String.format("Please wait while saving \"%s\"...", newDatabasePathHuman));
} }
mProgressDialog.show(); mProgressDialog.show();
final State previousState = mState;
updateState(State.STATE_PROCESSING); updateState(State.STATE_PROCESSING);
Thread saveThread = new Thread(new Runnable() { Thread saveThread = new Thread(new Runnable() {
public void run() { public void run() {
RTABMapLib.save(newDatabasePath); // save RTABMapLib.save(newDatabasePath); // save
runOnUiThread(new Runnable() { runOnUiThread(new Runnable() {
public void run() { public void run() {
String msg;
if(mOpenedDatabasePath.equals(newDatabasePath)) if(mOpenedDatabasePath.equals(newDatabasePath))
{ {
mToast.makeText(getActivity(), String.format("Database \"%s\" updated.", newDatabasePathHuman), mToast.LENGTH_LONG).show(); msg = String.format("Database \"%s\" updated.", newDatabasePathHuman);
} }
else else
{ {
mToast.makeText(getActivity(), String.format("Database saved to \"%s\".", newDatabasePathHuman), mToast.LENGTH_LONG).show(); msg = String.format("Database saved to \"%s\".", newDatabasePathHuman);
Intent intent = new Intent(getActivity(), RTABMapActivity.class);
// use System.currentTimeMillis() to have a unique ID for the pending intent
PendingIntent pIntent = PendingIntent.getActivity(getActivity(), (int) System.currentTimeMillis(), intent, 0);
// build notification
// the addAction re-use the same intent to keep the example short
Notification n = new Notification.Builder(getActivity())
.setContentTitle(getString(R.string.app_name))
.setContentText(newDatabasePathHuman + " saved!")
.setSmallIcon(R.drawable.ic_launcher)
.setContentIntent(pIntent)
.setAutoCancel(true).build();
NotificationManager notificationManager =
(NotificationManager) getSystemService(NOTIFICATION_SERVICE);
notificationManager.notify(0, n);
} }
mToast.makeText(getActivity(), msg, mToast.LENGTH_LONG).show();
// build notification
Intent intent = new Intent(getActivity(), RTABMapActivity.class);
// use System.currentTimeMillis() to have a unique ID for the pending intent
PendingIntent pIntent = PendingIntent.getActivity(getActivity(), (int) System.currentTimeMillis(), intent, 0);
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(getActivity());
boolean notifySound = sharedPref.getBoolean(getString(R.string.pref_key_notification_sound), Boolean.parseBoolean(getString(R.string.pref_default_notification_sound)));
Notification n = new Notification.Builder(getActivity())
.setContentTitle(getString(R.string.app_name))
.setContentText(msg)
.setSmallIcon(R.drawable.ic_launcher)
.setContentIntent(pIntent)
.setDefaults(notifySound?Notification.DEFAULT_SOUND:0)
.setAutoCancel(true).build();
NotificationManager notificationManager =
(NotificationManager) getSystemService(NOTIFICATION_SERVICE);
notificationManager.notify(0, n);
resetNoTouchTimer(true);
if(!mItemDataRecorderMode.isChecked()) if(!mItemDataRecorderMode.isChecked())
{ {
mOpenedDatabasePath = newDatabasePath; mOpenedDatabasePath = newDatabasePath;
} }
mProgressDialog.dismiss(); mProgressDialog.dismiss();
updateState(State.STATE_IDLE); updateState(previousState);
} }
}); });
} }
@@ -2215,6 +2273,7 @@ public class RTABMapActivity extends Activity implements OnClickListener {
public void onClick(DialogInterface dialog, int which) public void onClick(DialogInterface dialog, int which)
{ {
dialog.dismiss(); dialog.dismiss();
resetNoTouchTimer(true);
} }
}); });
builder.setPositiveButton("Ok", new DialogInterface.OnClickListener() { builder.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
@@ -2339,11 +2398,12 @@ public class RTABMapActivity extends Activity implements OnClickListener {
.setContentIntent(pIntent) .setContentIntent(pIntent)
.setAutoCancel(true).build(); .setAutoCancel(true).build();
NotificationManager notificationManager = NotificationManager notificationManager =
(NotificationManager) getSystemService(NOTIFICATION_SERVICE); (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
notificationManager.notify(0, n); notificationManager.notify(0, n);
resetNoTouchTimer(true);
} }
}); });
} }
@@ -2353,6 +2413,7 @@ public class RTABMapActivity extends Activity implements OnClickListener {
public void run() { public void run() {
mProgressDialog.dismiss(); mProgressDialog.dismiss();
mToast.makeText(getActivity(), String.format("Exporting mesh \"%s\" failed! No files found in tmp directory!? Last export may have failed or have been canceled.", pathHuman), mToast.LENGTH_LONG).show(); mToast.makeText(getActivity(), String.format("Exporting mesh \"%s\" failed! No files found in tmp directory!? Last export may have failed or have been canceled.", pathHuman), mToast.LENGTH_LONG).show();
resetNoTouchTimer(true);
} }
}); });
} }
@@ -2435,15 +2496,15 @@ public class RTABMapActivity extends Activity implements OnClickListener {
if(status >= 1 && status<=3) if(status >= 1 && status<=3)
{ {
mProgressDialog.dismiss(); mProgressDialog.dismiss();
resetNoTouchTimer(); resetNoTouchTimer(true);
updateState(State.STATE_VISUALIZING); updateState(State.STATE_VISUALIZING);
mToast.makeText(getActivity(), String.format("Database loaded!"), mToast.LENGTH_LONG).show(); mToast.makeText(getActivity(), String.format("Database loaded!"), mToast.LENGTH_LONG).show();
} }
else if(!mItemTrajectoryMode.isChecked()) else if(!mItemTrajectoryMode.isChecked())
{ {
if(mButtonFirst.isChecked()) if(mButtonCameraView.getSelectedItemPosition() == 0)
{ {
setCamera(1); setCamera(2);
} }
// creating meshes... // creating meshes...
updateState(State.STATE_IDLE); updateState(State.STATE_IDLE);
@@ -80,6 +80,7 @@ public class RTABMapLib
public static native void setPointSize(float value); public static native void setPointSize(float value);
public static native void setFOV(float value); public static native void setFOV(float value);
public static native void setOrthoCropFactor(float value); public static native void setOrthoCropFactor(float value);
public static native void setGridRotation(float value);
public static native void setLighting(boolean enabled); public static native void setLighting(boolean enabled);
public static native void setBackfaceCulling(boolean enabled); public static native void setBackfaceCulling(boolean enabled);
public static native void setWireframe(boolean enabled); public static native void setWireframe(boolean enabled);
@@ -108,7 +109,7 @@ public class RTABMapLib
int optimizedMaxPolygons, int optimizedMaxPolygons,
float optimizedColorRadius, float optimizedColorRadius,
boolean optimizedCleanWhitePolygons, boolean optimizedCleanWhitePolygons,
boolean optimizedColorWhitePolygons, int optimizedMinClusterSize,
float optimizedMaxTextureDistance, float optimizedMaxTextureDistance,
int optimizedMinTextureClusterSize, int optimizedMinTextureClusterSize,
boolean blockRendering); boolean blockRendering);
@@ -215,6 +215,7 @@ public class SettingsActivity extends PreferenceActivity implements OnSharedPref
((Preference)findPreference(getString(R.string.pref_key_opt_depth))).setSummary("("+((ListPreference)findPreference(getString(R.string.pref_key_opt_depth))).getEntry() + ") "+getString(R.string.pref_summary_opt_depth)); ((Preference)findPreference(getString(R.string.pref_key_opt_depth))).setSummary("("+((ListPreference)findPreference(getString(R.string.pref_key_opt_depth))).getEntry() + ") "+getString(R.string.pref_summary_opt_depth));
((Preference)findPreference(getString(R.string.pref_key_opt_color_radius))).setSummary("("+((ListPreference)findPreference(getString(R.string.pref_key_opt_color_radius))).getEntry() + ") "+getString(R.string.pref_summary_opt_color_radius)); ((Preference)findPreference(getString(R.string.pref_key_opt_color_radius))).setSummary("("+((ListPreference)findPreference(getString(R.string.pref_key_opt_color_radius))).getEntry() + ") "+getString(R.string.pref_summary_opt_color_radius));
((Preference)findPreference(getString(R.string.pref_key_opt_min_cluster_size))).setSummary("("+((ListPreference)findPreference(getString(R.string.pref_key_opt_min_cluster_size))).getEntry() + ") "+getString(R.string.pref_summary_opt_min_cluster_size));
((Preference)findPreference(getString(R.string.pref_key_cluster_ratio))).setSummary("("+((ListPreference)findPreference(getString(R.string.pref_key_cluster_ratio))).getEntry() + ") "+getString(R.string.pref_summary_cluster_ratio)); ((Preference)findPreference(getString(R.string.pref_key_cluster_ratio))).setSummary("("+((ListPreference)findPreference(getString(R.string.pref_key_cluster_ratio))).getEntry() + ") "+getString(R.string.pref_summary_cluster_ratio));
((Preference)findPreference(getString(R.string.pref_key_gain_max_radius))).setSummary("("+((ListPreference)findPreference(getString(R.string.pref_key_gain_max_radius))).getEntry() + ") "+getString(R.string.pref_summary_gain_max_radius)); ((Preference)findPreference(getString(R.string.pref_key_gain_max_radius))).setSummary("("+((ListPreference)findPreference(getString(R.string.pref_key_gain_max_radius))).getEntry() + ") "+getString(R.string.pref_summary_gain_max_radius));
@@ -272,6 +273,7 @@ public class SettingsActivity extends PreferenceActivity implements OnSharedPref
if(key.compareTo(getString(R.string.pref_key_opt_depth))==0) pref.setSummary("("+((ListPreference)pref).getEntry() + ") "+getString(R.string.pref_summary_opt_depth)); if(key.compareTo(getString(R.string.pref_key_opt_depth))==0) pref.setSummary("("+((ListPreference)pref).getEntry() + ") "+getString(R.string.pref_summary_opt_depth));
if(key.compareTo(getString(R.string.pref_key_opt_color_radius))==0) pref.setSummary("("+((ListPreference)pref).getEntry() + ") "+getString(R.string.pref_summary_opt_color_radius)); if(key.compareTo(getString(R.string.pref_key_opt_color_radius))==0) pref.setSummary("("+((ListPreference)pref).getEntry() + ") "+getString(R.string.pref_summary_opt_color_radius));
if(key.compareTo(getString(R.string.pref_key_opt_min_cluster_size))==0) pref.setSummary("("+((ListPreference)pref).getEntry() + ") "+getString(R.string.pref_summary_opt_min_cluster_size));
if(key.compareTo(getString(R.string.pref_key_cluster_ratio))==0) pref.setSummary("("+((ListPreference)pref).getEntry() + ") "+getString(R.string.pref_summary_cluster_ratio)); if(key.compareTo(getString(R.string.pref_key_cluster_ratio))==0) pref.setSummary("("+((ListPreference)pref).getEntry() + ") "+getString(R.string.pref_summary_cluster_ratio));
if(key.compareTo(getString(R.string.pref_key_gain_max_radius))==0) pref.setSummary("("+((ListPreference)pref).getEntry() + ") "+getString(R.string.pref_summary_gain_max_radius)); if(key.compareTo(getString(R.string.pref_key_gain_max_radius))==0) pref.setSummary("("+((ListPreference)pref).getEntry() + ") "+getString(R.string.pref_summary_gain_max_radius));
+5 -1
View File
@@ -74,7 +74,11 @@ ELSE()
ENDIF() ENDIF()
TARGET_LINK_LIBRARIES(rtabmap rtabmap_core rtabmap_gui rtabmap_utilite ${LIBRARIES}) TARGET_LINK_LIBRARIES(rtabmap rtabmap_core rtabmap_gui rtabmap_utilite ${LIBRARIES})
IF(Qt5_FOUND) IF(Qt5_FOUND)
QT5_USE_MODULES(rtabmap Widgets Core Gui Svg PrintSupport) IF(Qt5Svg_FOUND)
QT5_USE_MODULES(rtabmap Widgets Core Gui Svg PrintSupport)
ELSE()
QT5_USE_MODULES(rtabmap Widgets Core Gui PrintSupport)
ENDIF()
ENDIF(Qt5_FOUND) ENDIF(Qt5_FOUND)
IF(APPLE AND BUILD_AS_BUNDLE) IF(APPLE AND BUILD_AS_BUNDLE)
+4 -3
View File
@@ -9,12 +9,13 @@
find_path(ORB_SLAM2_INCLUDE_DIR NAMES System.h PATHS $ENV{ORB_SLAM2_ROOT_DIR}/include) find_path(ORB_SLAM2_INCLUDE_DIR NAMES System.h PATHS $ENV{ORB_SLAM2_ROOT_DIR}/include)
find_library(ORB_SLAM2_LIBRARY NAMES ORB_SLAM2 PATHS $ENV{ORB_SLAM2_ROOT_DIR}/lib) find_library(ORB_SLAM2_LIBRARY NAMES ORB_SLAM2 PATHS $ENV{ORB_SLAM2_ROOT_DIR}/lib)
find_library(g2o_LIBRARY NAMES g2o PATHS $ENV{ORB_SLAM2_ROOT_DIR}/Thirdparty/g2o/lib)
IF (ORB_SLAM2_INCLUDE_DIR AND ORB_SLAM2_LIBRARY) IF (ORB_SLAM2_INCLUDE_DIR AND ORB_SLAM2_LIBRARY AND g2o_LIBRARY)
SET(ORB_SLAM2_FOUND TRUE) SET(ORB_SLAM2_FOUND TRUE)
SET(ORB_SLAM2_INCLUDE_DIRS ${ORB_SLAM2_INCLUDE_DIR} $ENV{ORB_SLAM2_ROOT_DIR}) SET(ORB_SLAM2_INCLUDE_DIRS ${ORB_SLAM2_INCLUDE_DIR} $ENV{ORB_SLAM2_ROOT_DIR})
SET(ORB_SLAM2_LIBRARIES ${ORB_SLAM2_LIBRARY}) SET(ORB_SLAM2_LIBRARIES ${g2o_LIBRARY} ${ORB_SLAM2_LIBRARY})
ENDIF (ORB_SLAM2_INCLUDE_DIR AND ORB_SLAM2_LIBRARY) ENDIF (ORB_SLAM2_INCLUDE_DIR AND ORB_SLAM2_LIBRARY AND g2o_LIBRARY)
IF (ORB_SLAM2_FOUND) IF (ORB_SLAM2_FOUND)
# show which ORB_SLAM2 was found only if not quiet # show which ORB_SLAM2 was found only if not quiet
+16
View File
@@ -104,12 +104,20 @@ public:
const cv::Mat & cloud, const cv::Mat & cloud,
const std::map<int, Transform> & poses = std::map<int, Transform>(), // if we want to do localization afterward using optimized mesh const std::map<int, Transform> & poses = std::map<int, Transform>(), // if we want to do localization afterward using optimized mesh
const std::vector<std::vector<std::vector<unsigned int> > > & polygons = std::vector<std::vector<std::vector<unsigned int> > >(), // Textures -> polygons -> vertices const std::vector<std::vector<std::vector<unsigned int> > > & polygons = std::vector<std::vector<std::vector<unsigned int> > >(), // Textures -> polygons -> vertices
#if PCL_VERSION_COMPARE(>=, 1, 8, 0)
const std::vector<std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > > & texCoords = std::vector<std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > >(), // Textures -> uv coords for each vertex of the polygons
#else
const std::vector<std::vector<Eigen::Vector2f> > & texCoords = std::vector<std::vector<Eigen::Vector2f> >(), // Textures -> uv coords for each vertex of the polygons const std::vector<std::vector<Eigen::Vector2f> > & texCoords = std::vector<std::vector<Eigen::Vector2f> >(), // Textures -> uv coords for each vertex of the polygons
#endif
const cv::Mat & textures = cv::Mat()) const; // concatenated textures (assuming square textures with all same size); const cv::Mat & textures = cv::Mat()) const; // concatenated textures (assuming square textures with all same size);
cv::Mat loadOptimizedMesh( cv::Mat loadOptimizedMesh(
std::map<int, Transform> * poses = 0, std::map<int, Transform> * poses = 0,
std::vector<std::vector<std::vector<unsigned int> > > * polygons = 0, std::vector<std::vector<std::vector<unsigned int> > > * polygons = 0,
#if PCL_VERSION_COMPARE(>=, 1, 8, 0)
std::vector<std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > > * texCoords = 0,
#else
std::vector<std::vector<Eigen::Vector2f> > * texCoords = 0, std::vector<std::vector<Eigen::Vector2f> > * texCoords = 0,
#endif
cv::Mat * textures = 0) const; cv::Mat * textures = 0) const;
public: public:
@@ -219,12 +227,20 @@ private:
const cv::Mat & cloud, const cv::Mat & cloud,
const std::map<int, Transform> & poses, const std::map<int, Transform> & poses,
const std::vector<std::vector<std::vector<unsigned int> > > & polygons, const std::vector<std::vector<std::vector<unsigned int> > > & polygons,
#if PCL_VERSION_COMPARE(>=, 1, 8, 0)
const std::vector<std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > > & texCoords,
#else
const std::vector<std::vector<Eigen::Vector2f> > & texCoords, const std::vector<std::vector<Eigen::Vector2f> > & texCoords,
#endif
const cv::Mat & textures) const = 0; const cv::Mat & textures) const = 0;
virtual cv::Mat loadOptimizedMeshQuery( virtual cv::Mat loadOptimizedMeshQuery(
std::map<int, Transform> * poses, std::map<int, Transform> * poses,
std::vector<std::vector<std::vector<unsigned int> > > * polygons, std::vector<std::vector<std::vector<unsigned int> > > * polygons,
#if PCL_VERSION_COMPARE(>=, 1, 8, 0)
std::vector<std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > > * texCoords,
#else
std::vector<std::vector<Eigen::Vector2f> > * texCoords, std::vector<std::vector<Eigen::Vector2f> > * texCoords,
#endif
cv::Mat * textures) const = 0; cv::Mat * textures) const = 0;
// Load objects // Load objects
+14 -10
View File
@@ -105,7 +105,7 @@ public:
kFeatureGfttBrief=6, kFeatureGfttBrief=6,
kFeatureBrisk=7, kFeatureBrisk=7,
kFeatureGfttOrb=8, //new 0.10.11 kFeatureGfttOrb=8, //new 0.10.11
kFeatureFreak=9}; //new 0.11.14 kFeatureKaze=9}; //new 0.13.2
static Feature2D * create(const ParametersMap & parameters = ParametersMap()); static Feature2D * create(const ParametersMap & parameters = ParametersMap());
static Feature2D * create(Feature2D::Type type, const ParametersMap & parameters = ParametersMap()); // for convenience static Feature2D * create(Feature2D::Type type, const ParametersMap & parameters = ParametersMap()); // for convenience
@@ -433,27 +433,31 @@ private:
cv::Ptr<CV_BRISK> brisk_; cv::Ptr<CV_BRISK> brisk_;
}; };
//FREAK //KAZE
class RTABMAP_EXP FREAK : public Feature2D class RTABMAP_EXP KAZE : public Feature2D
{ {
public: public:
FREAK(const ParametersMap & parameters = ParametersMap()); KAZE(const ParametersMap & parameters = ParametersMap());
virtual ~FREAK(); virtual ~KAZE();
virtual void parseParameters(const ParametersMap & parameters); virtual void parseParameters(const ParametersMap & parameters);
virtual Feature2D::Type getType() const { return kFeatureFreak; } virtual Feature2D::Type getType() const { return kFeatureKaze; }
private: private:
virtual std::vector<cv::KeyPoint> generateKeypointsImpl(const cv::Mat & image, const cv::Rect & roi, const cv::Mat & mask = cv::Mat()) const; virtual std::vector<cv::KeyPoint> generateKeypointsImpl(const cv::Mat & image, const cv::Rect & roi, const cv::Mat & mask = cv::Mat()) const;
virtual cv::Mat generateDescriptorsImpl(const cv::Mat & image, std::vector<cv::KeyPoint> & keypoints) const; virtual cv::Mat generateDescriptorsImpl(const cv::Mat & image, std::vector<cv::KeyPoint> & keypoints) const;
private: private:
bool orientationNormalized_; bool extended_;
bool scaleNormalized_; bool upright_;
float patternScale_; float threshold_;
int nOctaves_; int nOctaves_;
int nOctaveLayers_;
int diffusivity_;
cv::Ptr<CV_FREAK> _freak; #if CV_MAJOR_VERSION > 2
cv::Ptr<cv::KAZE> kaze_;
#endif
}; };
+9
View File
@@ -42,6 +42,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "rtabmap/utilite/UStl.h" #include "rtabmap/utilite/UStl.h"
#include <opencv2/core/core.hpp> #include <opencv2/core/core.hpp>
#include <opencv2/features2d/features2d.hpp> #include <opencv2/features2d/features2d.hpp>
#include <pcl/pcl_config.h>
namespace rtabmap { namespace rtabmap {
@@ -98,12 +99,20 @@ public:
const cv::Mat & cloud, const cv::Mat & cloud,
const std::map<int, Transform> & poses = std::map<int, Transform>(), // if we want to do localization afterward using optimized mesh const std::map<int, Transform> & poses = std::map<int, Transform>(), // if we want to do localization afterward using optimized mesh
const std::vector<std::vector<std::vector<unsigned int> > > & polygons = std::vector<std::vector<std::vector<unsigned int> > >(), // Textures -> polygons -> vertices const std::vector<std::vector<std::vector<unsigned int> > > & polygons = std::vector<std::vector<std::vector<unsigned int> > >(), // Textures -> polygons -> vertices
#if PCL_VERSION_COMPARE(>=, 1, 8, 0)
const std::vector<std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > > & texCoords = std::vector<std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > >(), // Textures -> uv coords for each vertex of the polygons
#else
const std::vector<std::vector<Eigen::Vector2f> > & texCoords = std::vector<std::vector<Eigen::Vector2f> >(), // Textures -> uv coords for each vertex of the polygons const std::vector<std::vector<Eigen::Vector2f> > & texCoords = std::vector<std::vector<Eigen::Vector2f> >(), // Textures -> uv coords for each vertex of the polygons
#endif
const cv::Mat & textures = cv::Mat()) const; // concatenated textures (assuming square textures with all same size) const cv::Mat & textures = cv::Mat()) const; // concatenated textures (assuming square textures with all same size)
cv::Mat loadOptimizedMesh( cv::Mat loadOptimizedMesh(
std::map<int, Transform> * poses = 0, std::map<int, Transform> * poses = 0,
std::vector<std::vector<std::vector<unsigned int> > > * polygons = 0, std::vector<std::vector<std::vector<unsigned int> > > * polygons = 0,
#if PCL_VERSION_COMPARE(>=, 1, 8, 0)
std::vector<std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > > * texCoords = 0,
#else
std::vector<std::vector<Eigen::Vector2f> > * texCoords = 0, std::vector<std::vector<Eigen::Vector2f> > * texCoords = 0,
#endif
cv::Mat * textures = 0) const; cv::Mat * textures = 0) const;
void emptyTrash(); void emptyTrash();
void joinTrashThread(); void joinTrashThread();
@@ -47,6 +47,7 @@ public:
float getMinMapSize() const {return minMapSize_;} float getMinMapSize() const {return minMapSize_;}
bool isGridFromDepth() const {return occupancyFromCloud_;} bool isGridFromDepth() const {return occupancyFromCloud_;}
bool isFullUpdate() const {return fullUpdate_;} bool isFullUpdate() const {return fullUpdate_;}
bool isMapFrameProjection() const {return projMapFrame_;}
const std::map<int, Transform> & addedNodes() const {return addedNodes_;} const std::map<int, Transform> & addedNodes() const {return addedNodes_;}
int cacheSize() const {return (int)cache_.size();} int cacheSize() const {return (int)cache_.size();}
@@ -58,6 +58,7 @@ private:
dvo::core::RgbdCameraPyramid * camera_; dvo::core::RgbdCameraPyramid * camera_;
bool lost_; bool lost_;
Transform motionFromKeyFrame_; Transform motionFromKeyFrame_;
Transform previousLocalTransform_;
}; };
@@ -86,8 +86,6 @@ public:
return std::vector<float>(); return std::vector<float>();
} }
const OdometryInfo & info() const {return _info;} const OdometryInfo & info() const {return _info;}
double rotVariance() const {return uMax3(_info.covariance.at<double>(3,3), _info.covariance.at<double>(4,4), _info.covariance.at<double>(5,5));}
double transVariance() const {return uMax3(_info.covariance.at<double>(0,0), _info.covariance.at<double>(1,1), _info.covariance.at<double>(2,2));}
private: private:
SensorData _data; SensorData _data;
@@ -60,6 +60,7 @@ private:
fovis::StereoDepth * stereoDepth_; fovis::StereoDepth * stereoDepth_;
ParametersMap fovisParameters_; ParametersMap fovisParameters_;
bool lost_; bool lost_;
Transform previousLocalTransform_;
}; };
} }
@@ -54,6 +54,7 @@ private:
ORBSLAM2System * orbslam2_; ORBSLAM2System * orbslam2_;
ORB_SLAM2::System * system_; ORB_SLAM2::System * system_;
bool firstFrame_; bool firstFrame_;
Transform originLocalTransform_;
}; };
@@ -54,6 +54,7 @@ private:
bool lost_; bool lost_;
bool keep_reference_frame_; bool keep_reference_frame_;
Transform reference_motion_; Transform reference_motion_;
Transform previousLocalTransform_;
ParametersMap viso2Parameters_; ParametersMap viso2Parameters_;
}; };
+15 -8
View File
@@ -168,7 +168,6 @@ typedef std::pair<std::string, std::string> ParametersPair;
class RTABMAP_EXP Parameters class RTABMAP_EXP Parameters
{ {
// Rtabmap parameters // Rtabmap parameters
RTABMAP_PARAM(Rtabmap, VhStrategy, int, 0, "None 0, Similarity 1, Epipolar 2.");
RTABMAP_PARAM(Rtabmap, PublishStats, bool, true, "Publishing statistics."); RTABMAP_PARAM(Rtabmap, PublishStats, bool, true, "Publishing statistics.");
RTABMAP_PARAM(Rtabmap, PublishLastSignature, bool, true, "Publishing last signature."); RTABMAP_PARAM(Rtabmap, PublishLastSignature, bool, true, "Publishing last signature.");
RTABMAP_PARAM(Rtabmap, PublishPdf, bool, true, "Publishing pdf."); RTABMAP_PARAM(Rtabmap, PublishPdf, bool, true, "Publishing pdf.");
@@ -225,9 +224,9 @@ class RTABMAP_EXP Parameters
RTABMAP_PARAM(Kp, BadSignRatio, float, 0.5, "Bad signature ratio (less than Ratio x AverageWordsPerImage = bad)."); RTABMAP_PARAM(Kp, BadSignRatio, float, 0.5, "Bad signature ratio (less than Ratio x AverageWordsPerImage = bad).");
RTABMAP_PARAM(Kp, NndrRatio, float, 0.8, "NNDR ratio (A matching pair is detected, if its distance is closer than X times the distance of the second nearest neighbor.)"); RTABMAP_PARAM(Kp, NndrRatio, float, 0.8, "NNDR ratio (A matching pair is detected, if its distance is closer than X times the distance of the second nearest neighbor.)");
#ifdef RTABMAP_NONFREE #ifdef RTABMAP_NONFREE
RTABMAP_PARAM(Kp, DetectorStrategy, int, 0, "0=SURF 1=SIFT 2=ORB 3=FAST/FREAK 4=FAST/BRIEF 5=GFTT/FREAK 6=GFTT/BRIEF 7=BRISK 8=GFTT/ORB 9=FREAK."); RTABMAP_PARAM(Kp, DetectorStrategy, int, 0, "0=SURF 1=SIFT 2=ORB 3=FAST/FREAK 4=FAST/BRIEF 5=GFTT/FREAK 6=GFTT/BRIEF 7=BRISK 8=GFTT/ORB 9=KAZE.");
#else #else
RTABMAP_PARAM(Kp, DetectorStrategy, int, 2, "0=SURF 1=SIFT 2=ORB 3=FAST/FREAK 4=FAST/BRIEF 5=GFTT/FREAK 6=GFTT/BRIEF 7=BRISK 8=GFTT/ORB 9=FREAK."); RTABMAP_PARAM(Kp, DetectorStrategy, int, 2, "0=SURF 1=SIFT 2=ORB 3=FAST/FREAK 4=FAST/BRIEF 5=GFTT/FREAK 6=GFTT/BRIEF 7=BRISK 8=GFTT/ORB 9=KAZE.");
#endif #endif
RTABMAP_PARAM(Kp, TfIdfLikelihoodUsed, bool, true, "Use of the td-idf strategy to compute the likelihood."); RTABMAP_PARAM(Kp, TfIdfLikelihoodUsed, bool, true, "Use of the td-idf strategy to compute the likelihood.");
RTABMAP_PARAM(Kp, Parallelized, bool, true, "If the dictionary update and signature creation were parallelized."); RTABMAP_PARAM(Kp, Parallelized, bool, true, "If the dictionary update and signature creation were parallelized.");
@@ -295,22 +294,30 @@ class RTABMAP_EXP Parameters
RTABMAP_PARAM(BRISK, Octaves, int, 3, "Detection octaves. Use 0 to do single scale."); RTABMAP_PARAM(BRISK, Octaves, int, 3, "Detection octaves. Use 0 to do single scale.");
RTABMAP_PARAM(BRISK, PatternScale, float, 1,"Apply this scale to the pattern used for sampling the neighbourhood of a keypoint."); RTABMAP_PARAM(BRISK, PatternScale, float, 1,"Apply this scale to the pattern used for sampling the neighbourhood of a keypoint.");
RTABMAP_PARAM(KAZE, Extended, bool, false, "Set to enable extraction of extended (128-byte) descriptor.");
RTABMAP_PARAM(KAZE, Upright, bool, false, "Set to enable use of upright descriptors (non rotation-invariant).");
RTABMAP_PARAM(KAZE, Threshold, float, 0.001, "Detector response threshold to accept point.");
RTABMAP_PARAM(KAZE, NOctaves, int, 4, "Maximum octave evolution of the image.");
RTABMAP_PARAM(KAZE, NOctaveLayers, int, 4, "Default number of sublevels per scale level.");
RTABMAP_PARAM(KAZE, Diffusivity, int, 1, "Diffusivity type: 0=DIFF_PM_G1, 1=DIFF_PM_G2, 2=DIFF_WEICKERT or 3=DIFF_CHARBONNIER.");
// BayesFilter // BayesFilter
RTABMAP_PARAM(Bayes, VirtualPlacePriorThr, float, 0.9, "Virtual place prior"); RTABMAP_PARAM(Bayes, VirtualPlacePriorThr, float, 0.9, "Virtual place prior");
RTABMAP_PARAM_STR(Bayes, PredictionLC, "0.1 0.36 0.30 0.16 0.062 0.0151 0.00255 0.000324 2.5e-05 1.3e-06 4.8e-08 1.2e-09 1.9e-11 2.2e-13 1.7e-15 8.5e-18 2.9e-20 6.9e-23", "Prediction of loop closures (Gaussian-like, here with sigma=1.6) - Format: {VirtualPlaceProb, LoopClosureProb, NeighborLvl1, NeighborLvl2, ...}."); RTABMAP_PARAM_STR(Bayes, PredictionLC, "0.1 0.36 0.30 0.16 0.062 0.0151 0.00255 0.000324 2.5e-05 1.3e-06 4.8e-08 1.2e-09 1.9e-11 2.2e-13 1.7e-15 8.5e-18 2.9e-20 6.9e-23", "Prediction of loop closures (Gaussian-like, here with sigma=1.6) - Format: {VirtualPlaceProb, LoopClosureProb, NeighborLvl1, NeighborLvl2, ...}.");
RTABMAP_PARAM(Bayes, FullPredictionUpdate, bool, false, "Regenerate all the prediction matrix on each iteration (otherwise only removed/added ids are updated)."); RTABMAP_PARAM(Bayes, FullPredictionUpdate, bool, false, "Regenerate all the prediction matrix on each iteration (otherwise only removed/added ids are updated).");
// Verify hypotheses // Verify hypotheses
RTABMAP_PARAM(VhEp, Enabled, bool, false, uFormat("Verify visual loop closure hypothesis by computing a fundamental matrix. This is done prior to transformation computation when %s is enabled.", kRGBDEnabled().c_str()));
RTABMAP_PARAM(VhEp, MatchCountMin, int, 8, "Minimum of matching visual words pairs to accept the loop hypothesis."); RTABMAP_PARAM(VhEp, MatchCountMin, int, 8, "Minimum of matching visual words pairs to accept the loop hypothesis.");
RTABMAP_PARAM(VhEp, RansacParam1, float, 3, "Fundamental matrix (see cvFindFundamentalMat()): Max distance (in pixels) from the epipolar line for a point to be inlier."); RTABMAP_PARAM(VhEp, RansacParam1, float, 3, "Fundamental matrix (see cvFindFundamentalMat()): Max distance (in pixels) from the epipolar line for a point to be inlier.");
RTABMAP_PARAM(VhEp, RansacParam2, float, 0.99, "Fundamental matrix (see cvFindFundamentalMat()): Performance of the RANSAC."); RTABMAP_PARAM(VhEp, RansacParam2, float, 0.99, "Fundamental matrix (see cvFindFundamentalMat()): Performance of RANSAC.");
// RGB-D SLAM // RGB-D SLAM
RTABMAP_PARAM(RGBD, Enabled, bool, true, ""); RTABMAP_PARAM(RGBD, Enabled, bool, true, "");
RTABMAP_PARAM(RGBD, LinearUpdate, float, 0.1, "Minimum linear displacement to update the map. Rehearsal is done prior to this, so weights are still updated."); RTABMAP_PARAM(RGBD, LinearUpdate, float, 0.1, "Minimum linear displacement to update the map. Rehearsal is done prior to this, so weights are still updated.");
RTABMAP_PARAM(RGBD, AngularUpdate, float, 0.1, "Minimum angular displacement to update the map. Rehearsal is done prior to this, so weights are still updated."); RTABMAP_PARAM(RGBD, AngularUpdate, float, 0.1, "Minimum angular displacement to update the map. Rehearsal is done prior to this, so weights are still updated.");
RTABMAP_PARAM(RGBD, NewMapOdomChangeDistance, float, 0, "A new map is created if a change of odometry translation greater than X m is detected (0 m = disabled)."); RTABMAP_PARAM(RGBD, NewMapOdomChangeDistance, float, 0, "A new map is created if a change of odometry translation greater than X m is detected (0 m = disabled).");
RTABMAP_PARAM(RGBD, OptimizeFromGraphEnd, bool, false, "Optimize graph from the newest node. If false, the graph is optimized from the oldest node of the current graph (this adds an overhead computation to detect to oldest mode of the current graph, but it can be useful to preserve the map referential from the oldest node). Warning when set to false: when some nodes are transferred, the first referential of the local map may change, resulting in momentary changes in robot/map position (which are annoying in teleoperation)."); RTABMAP_PARAM(RGBD, OptimizeFromGraphEnd, bool, false, "Optimize graph from the newest node. If false, the graph is optimized from the oldest node of the current graph (this adds an overhead computation to detect to oldest node of the current graph, but it can be useful to preserve the map referential from the oldest node). Warning when set to false: when some nodes are transferred, the first referential of the local map may change, resulting in momentary changes in robot/map position (which are annoying in teleoperation).");
RTABMAP_PARAM(RGBD, OptimizeMaxError, float, 1, uFormat("Reject loop closures if optimization error is greater than this value (0=disabled). This will help to detect when a wrong loop closure is added to the graph. Not compatible with \"%s\" if enabled.", kOptimizerRobust().c_str())); RTABMAP_PARAM(RGBD, OptimizeMaxError, float, 1, uFormat("Reject loop closures if optimization error is greater than this value (0=disabled). This will help to detect when a wrong loop closure is added to the graph. Not compatible with \"%s\" if enabled.", kOptimizerRobust().c_str()));
RTABMAP_PARAM(RGBD, GoalReachedRadius, float, 0.5, "Goal reached radius (m)."); RTABMAP_PARAM(RGBD, GoalReachedRadius, float, 0.5, "Goal reached radius (m).");
RTABMAP_PARAM(RGBD, PlanStuckIterations, int, 0, "Mark the current goal node on the path as unreachable if it is not updated after X iterations (0=disabled). If all upcoming nodes on the path are unreachabled, the plan fails."); RTABMAP_PARAM(RGBD, PlanStuckIterations, int, 0, "Mark the current goal node on the path as unreachable if it is not updated after X iterations (0=disabled). If all upcoming nodes on the path are unreachabled, the plan fails.");
@@ -469,12 +476,12 @@ class RTABMAP_EXP Parameters
#ifndef RTABMAP_NONFREE #ifndef RTABMAP_NONFREE
#ifdef RTABMAP_OPENCV3 #ifdef RTABMAP_OPENCV3
// OpenCV 3 without xFeatures2D module doesn't have BRIEF // OpenCV 3 without xFeatures2D module doesn't have BRIEF
RTABMAP_PARAM(Vis, FeatureType, int, 8, "0=SURF 1=SIFT 2=ORB 3=FAST/FREAK 4=FAST/BRIEF 5=GFTT/FREAK 6=GFTT/BRIEF 7=BRISK 8=GFTT/ORB 9=FREAK."); RTABMAP_PARAM(Vis, FeatureType, int, 8, "0=SURF 1=SIFT 2=ORB 3=FAST/FREAK 4=FAST/BRIEF 5=GFTT/FREAK 6=GFTT/BRIEF 7=BRISK 8=GFTT/ORB 9=KAZE.");
#else #else
RTABMAP_PARAM(Vis, FeatureType, int, 6, "0=SURF 1=SIFT 2=ORB 3=FAST/FREAK 4=FAST/BRIEF 5=GFTT/FREAK 6=GFTT/BRIEF 7=BRISK 8=GFTT/ORB 9=FREAK."); RTABMAP_PARAM(Vis, FeatureType, int, 6, "0=SURF 1=SIFT 2=ORB 3=FAST/FREAK 4=FAST/BRIEF 5=GFTT/FREAK 6=GFTT/BRIEF 7=BRISK 8=GFTT/ORB 9=KAZE.");
#endif #endif
#else #else
RTABMAP_PARAM(Vis, FeatureType, int, 6, "0=SURF 1=SIFT 2=ORB 3=FAST/FREAK 4=FAST/BRIEF 5=GFTT/FREAK 6=GFTT/BRIEF 7=BRISK 8=GFTT/ORB 9=FREAK."); RTABMAP_PARAM(Vis, FeatureType, int, 6, "0=SURF 1=SIFT 2=ORB 3=FAST/FREAK 4=FAST/BRIEF 5=GFTT/FREAK 6=GFTT/BRIEF 7=BRISK 8=GFTT/ORB 9=KAZE.");
#endif #endif
RTABMAP_PARAM(Vis, MaxFeatures, int, 1000, "0 no limits."); RTABMAP_PARAM(Vis, MaxFeatures, int, 1000, "0 no limits.");
RTABMAP_PARAM(Vis, MaxDepth, float, 0, "Max depth of the features (0 means no limit)."); RTABMAP_PARAM(Vis, MaxDepth, float, 0, "Max depth of the features (0 means no limit).");
+4 -4
View File
@@ -25,8 +25,8 @@ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef REGISTRATION_H_ #ifndef RTABMAP_REGISTRATION_H_
#define REGISTRATION_H_ #define RTABMAP_REGISTRATION_H_
#include "rtabmap/core/RtabmapExp.h" // DLL export/import defines #include "rtabmap/core/RtabmapExp.h" // DLL export/import defines
@@ -76,7 +76,7 @@ public:
Transform computeTransformation( Transform computeTransformation(
const SensorData & from, const SensorData & from,
const SensorData & to, const SensorData & to,
Transform SensorData = Transform::getIdentity(), Transform guess = Transform::getIdentity(),
RegistrationInfo * info = 0) const; RegistrationInfo * info = 0) const;
Transform computeTransformationMod( Transform computeTransformationMod(
@@ -115,4 +115,4 @@ private:
} }
#endif /* REGISTRATION_H_ */ #endif /* RTABMAP_REGISTRATION_H_ */
+1
View File
@@ -215,6 +215,7 @@ private:
unsigned int _maxMemoryAllowed; // signatures count in WM unsigned int _maxMemoryAllowed; // signatures count in WM
float _loopThr; float _loopThr;
float _loopRatio; float _loopRatio;
bool _verifyLoopClosureHypothesis;
unsigned int _maxRetrieved; unsigned int _maxRetrieved;
unsigned int _maxLocalRetrieved; unsigned int _maxLocalRetrieved;
bool _rawDataKept; bool _rawDataKept;
@@ -121,7 +121,9 @@ typename pcl::PointCloud<PointT>::Ptr OccupancyGrid::segmentCloud(
{ {
UDEBUG(""); UDEBUG("");
// passthrough filter // passthrough filter
groundIndices = rtabmap::util3d::passThrough(cloud, indices, "z", minGroundHeight_!=0.0f?minGroundHeight_:std::numeric_limits<int>::min(), maxGroundHeight_); groundIndices = rtabmap::util3d::passThrough(cloud, indices, "z",
minGroundHeight_!=0.0f?minGroundHeight_:std::numeric_limits<int>::min(),
maxGroundHeight_!=0.0f?maxGroundHeight_:std::numeric_limits<int>::max());
pcl::IndicesPtr notObstacles = groundIndices; pcl::IndicesPtr notObstacles = groundIndices;
if(indices->size()) if(indices->size())
@@ -97,8 +97,7 @@ void denseMeshPostProcessing(
if(cloud.get()!=0 && if(cloud.get()!=0 &&
!hasColors && !hasColors &&
transferColorRadius >= 0.0 && transferColorRadius >= 0.0)
coloredOutput)
{ {
if(progressState) progressState->callback(uFormat("Transferring color from point cloud to mesh...")); if(progressState) progressState->callback(uFormat("Transferring color from point cloud to mesh..."));
@@ -179,63 +178,8 @@ void denseMeshPostProcessing(
} }
hasColors = true; hasColors = true;
} }
else if(cloud.get()!=0 &&
!hasColors &&
transferColorRadius > 0.0 &&
cleanMesh &&
!coloredOutput)
{
if(progressState) progressState->callback(uFormat("Removing polygons too far from the cloud..."));
// transfer color from point cloud to mesh if(minClusterSize)
typename pcl::search::KdTree<pointRGBT>::Ptr tree (new pcl::search::KdTree<pointRGBT>(true));
tree->setInputCloud(cloud);
pcl::PointCloud<pcl::PointNormal>::Ptr optimizedCloud(new pcl::PointCloud<pcl::PointNormal>);
pcl::fromPCLPointCloud2(mesh->cloud, *optimizedCloud);
std::vector<bool> closePts(optimizedCloud->size());
for(unsigned int i=0; i<optimizedCloud->size(); ++i)
{
std::vector<int> kIndices;
std::vector<float> kDistances;
pointRGBT pt;
pt.x = optimizedCloud->at(i).x;
pt.y = optimizedCloud->at(i).y;
pt.z = optimizedCloud->at(i).z;
tree->radiusSearch(pt, transferColorRadius, kIndices, kDistances);
if(kIndices.size())
{
closePts.at(i) = true;
}
else
{
closePts.at(i) = false;
}
}
// remove far polygons
std::vector<pcl::Vertices> filteredPolygons(mesh->polygons.size());
int oi=0;
for(unsigned int i=0; i<mesh->polygons.size(); ++i)
{
bool keepPolygon = true;
for(unsigned int j=0; j<mesh->polygons[i].vertices.size(); ++j)
{
if(!closePts.at(mesh->polygons[i].vertices[j]))
{
keepPolygon = false;
break;
}
}
if(keepPolygon)
{
filteredPolygons[oi++] = mesh->polygons[i];
}
}
filteredPolygons.resize(oi);
mesh->polygons = filteredPolygons;
}
if(minClusterSize && coloredOutput && !cleanMesh)
{ {
if(progressState) progressState->callback(uFormat("Filter small polygon clusters...")); if(progressState) progressState->callback(uFormat("Filter small polygon clusters..."));
@@ -290,7 +234,7 @@ void denseMeshPostProcessing(
int before = (int)mesh->polygons.size(); int before = (int)mesh->polygons.size();
mesh->polygons = filteredPolygons; mesh->polygons = filteredPolygons;
if(progressState) progressState->callback(uFormat("Filtered %1 polygons.", before-(int)mesh->polygons.size())); if(progressState) progressState->callback(uFormat("Filtered %d polygons.", before-(int)mesh->polygons.size()));
} }
// compute normals for the mesh if not already here, add also white color if colored output is required // compute normals for the mesh if not already here, add also white color if colored output is required
@@ -292,7 +292,7 @@ void denseMeshPostProcessing(
int maximumPolygons = 0, // 0=disabled int maximumPolygons = 0, // 0=disabled
const typename pcl::PointCloud<pointRGBT>::Ptr & cloud = pcl::PointCloud<pointRGBT>::Ptr(), // A RGB point cloud used to transfer colors back to mesh (needed for parameters below) const typename pcl::PointCloud<pointRGBT>::Ptr & cloud = pcl::PointCloud<pointRGBT>::Ptr(), // A RGB point cloud used to transfer colors back to mesh (needed for parameters below)
float transferColorRadius = 0.05f, // <0=disabled, 0=nearest color float transferColorRadius = 0.05f, // <0=disabled, 0=nearest color
bool coloredOutput = true, // If output should be colored bool coloredOutput = true, // Not used anymore, output is colored if transferColorRadius>=0
bool cleanMesh = true, // Remove polygons not colored (if coloredOutput is disabled, transferColorRadius is still used to clean the mesh) bool cleanMesh = true, // Remove polygons not colored (if coloredOutput is disabled, transferColorRadius is still used to clean the mesh)
int minClusterSize = 50, // Remove small polygon clusters after the mesh has been cleaned (0=disabled) int minClusterSize = 50, // Remove small polygon clusters after the mesh has been cleaned (0=disabled)
ProgressState * progressState = 0); ProgressState * progressState = 0);
+1 -1
View File
@@ -344,7 +344,7 @@ SET(RESOURCES_HEADERS
IF(ANDROID) IF(ANDROID)
IF(NOT RTABMAP_RES_TOOL) IF(NOT RTABMAP_RES_TOOL)
find_host_program(RTABMAP_RES_TOOL rtabmap-res_tool) find_host_program(RTABMAP_RES_TOOL rtabmap-res_tool PATHS ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
IF(NOT RTABMAP_RES_TOOL) IF(NOT RTABMAP_RES_TOOL)
MESSAGE( FATAL_ERROR "RTABMAP_RES_TOOL is not defined (it is the path to \"rtabmap-res_tool\" application created by a non-Android build)." ) MESSAGE( FATAL_ERROR "RTABMAP_RES_TOOL is not defined (it is the path to \"rtabmap-res_tool\" application created by a non-Android build)." )
ENDIF(NOT RTABMAP_RES_TOOL) ENDIF(NOT RTABMAP_RES_TOOL)
+12 -7
View File
@@ -860,18 +860,27 @@ bool CameraStereoZed::init(const std::string & calibrationFolder, const std::str
param.depth_minimum_distance=-1; param.depth_minimum_distance=-1;
param.camera_disable_self_calib=!selfCalibration_; param.camera_disable_self_calib=!selfCalibration_;
sl::ERROR_CODE r = sl::ERROR_CODE::SUCCESS;
if(src_ == CameraVideo::kVideoFile) if(src_ == CameraVideo::kVideoFile)
{ {
UINFO("svo file = %s", svoFilePath_.c_str()); UINFO("svo file = %s", svoFilePath_.c_str());
zed_ = new sl::Camera(); // Use in SVO playback mode zed_ = new sl::Camera(); // Use in SVO playback mode
param.svo_input_filename=svoFilePath_.c_str(); param.svo_input_filename=svoFilePath_.c_str();
zed_->open(param); r = zed_->open(param);
} }
else else
{ {
UINFO("Resolution=%d imagerate=%f device=%d", resolution_, getImageRate(), usbDevice_); UINFO("Resolution=%d imagerate=%f device=%d", resolution_, getImageRate(), usbDevice_);
zed_ = new sl::Camera(); // Use in Live Mode zed_ = new sl::Camera(); // Use in Live Mode
zed_->open(param); r = zed_->open(param);
}
if(r!=sl::ERROR_CODE::SUCCESS)
{
UERROR("Camera initialization failed: \"%s\"", errorCode2str(r).c_str());
delete zed_;
zed_ = 0;
return false;
} }
@@ -979,11 +988,7 @@ SensorData CameraStereoZed::captureImage(CameraInfo * info)
{ {
SensorData data; SensorData data;
#ifdef RTABMAP_ZED #ifdef RTABMAP_ZED
sl::RuntimeParameters rparam; sl::RuntimeParameters rparam((sl::SENSING_MODE)sensingMode_, quality_ > 0, quality_ > 0, sl::REFERENCE_FRAME_CAMERA);
rparam.sensing_mode=(sl::SENSING_MODE)sensingMode_;
rparam.enable_depth=quality_ > 0;
rparam.enable_point_cloud=quality_ > 0;
rparam.move_point_cloud_to_world_frame=false;
if(zed_) if(zed_)
{ {
UTimer timer; UTimer timer;
+8
View File
@@ -1043,7 +1043,11 @@ void DBDriver::saveOptimizedMesh(
const cv::Mat & cloud, const cv::Mat & cloud,
const std::map<int, Transform> & poses, const std::map<int, Transform> & poses,
const std::vector<std::vector<std::vector<unsigned int> > > & polygons, const std::vector<std::vector<std::vector<unsigned int> > > & polygons,
#if PCL_VERSION_COMPARE(>=, 1, 8, 0)
const std::vector<std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > > & texCoords,
#else
const std::vector<std::vector<Eigen::Vector2f> > & texCoords, const std::vector<std::vector<Eigen::Vector2f> > & texCoords,
#endif
const cv::Mat & textures) const const cv::Mat & textures) const
{ {
_dbSafeAccessMutex.lock(); _dbSafeAccessMutex.lock();
@@ -1054,7 +1058,11 @@ void DBDriver::saveOptimizedMesh(
cv::Mat DBDriver::loadOptimizedMesh( cv::Mat DBDriver::loadOptimizedMesh(
std::map<int, Transform> * poses, std::map<int, Transform> * poses,
std::vector<std::vector<std::vector<unsigned int> > > * polygons, std::vector<std::vector<std::vector<unsigned int> > > * polygons,
#if PCL_VERSION_COMPARE(>=, 1, 8, 0)
std::vector<std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f>> > * texCoords,
#else
std::vector<std::vector<Eigen::Vector2f> > * texCoords, std::vector<std::vector<Eigen::Vector2f> > * texCoords,
#endif
cv::Mat * textures) const cv::Mat * textures) const
{ {
_dbSafeAccessMutex.lock(); _dbSafeAccessMutex.lock();
+13 -1
View File
@@ -428,7 +428,7 @@ void DBDriverSqlite3::disconnectDatabaseQuery(bool save, const std::string & out
} }
if(outputFile.empty()) if(outputFile.empty())
{ {
UERROR("Database was initialized with an empty url (in memory). To save it " UERROR("Database was initialized with an empty url (in memory). To save it, "
"the output url should not be empty. The database is thus closed without being saved!"); "the output url should not be empty. The database is thus closed without being saved!");
} }
else else
@@ -3833,7 +3833,11 @@ void DBDriverSqlite3::saveOptimizedMeshQuery(
const cv::Mat & cloud, const cv::Mat & cloud,
const std::map<int, Transform> & poses, const std::map<int, Transform> & poses,
const std::vector<std::vector<std::vector<unsigned int> > > & polygons, const std::vector<std::vector<std::vector<unsigned int> > > & polygons,
#if PCL_VERSION_COMPARE(>=, 1, 8, 0)
const std::vector<std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > > & texCoords,
#else
const std::vector<std::vector<Eigen::Vector2f> > & texCoords, const std::vector<std::vector<Eigen::Vector2f> > & texCoords,
#endif
const cv::Mat & textures) const const cv::Mat & textures) const
{ {
UDEBUG(""); UDEBUG("");
@@ -4049,7 +4053,11 @@ void DBDriverSqlite3::saveOptimizedMeshQuery(
cv::Mat DBDriverSqlite3::loadOptimizedMeshQuery( cv::Mat DBDriverSqlite3::loadOptimizedMeshQuery(
std::map<int, Transform> * poses, std::map<int, Transform> * poses,
std::vector<std::vector<std::vector<unsigned int> > > * polygons, std::vector<std::vector<std::vector<unsigned int> > > * polygons,
#if PCL_VERSION_COMPARE(>=, 1, 8, 0)
std::vector<std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > > * texCoords,
#else
std::vector<std::vector<Eigen::Vector2f> > * texCoords, std::vector<std::vector<Eigen::Vector2f> > * texCoords,
#endif
cv::Mat * textures) const cv::Mat * textures) const
{ {
UDEBUG(""); UDEBUG("");
@@ -4158,7 +4166,11 @@ cv::Mat DBDriverSqlite3::loadOptimizedMeshQuery(
for(int t=0; t<serializedTexCoords.cols; ++t) for(int t=0; t<serializedTexCoords.cols; ++t)
{ {
UASSERT(int(serializedTexCoords.at<float>(t)) > 0); UASSERT(int(serializedTexCoords.at<float>(t)) > 0);
#if PCL_VERSION_COMPARE(>=, 1, 8, 0)
std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > materialtexCoords(int(serializedTexCoords.at<float>(t)));
#else
std::vector<Eigen::Vector2f> materialtexCoords(int(serializedTexCoords.at<float>(t))); std::vector<Eigen::Vector2f> materialtexCoords(int(serializedTexCoords.at<float>(t)));
#endif
++t; ++t;
UASSERT(t < serializedTexCoords.cols); UASSERT(t < serializedTexCoords.cols);
UDEBUG("materialtexCoords=%d", (int)materialtexCoords.size()); UDEBUG("materialtexCoords=%d", (int)materialtexCoords.size());
+10 -2
View File
@@ -91,8 +91,8 @@ private:
const cv::Point3f & viewpoint) const; const cv::Point3f & viewpoint) const;
virtual void updateDepthImageQuery( virtual void updateDepthImageQuery(
int nodeId, int nodeId,
const cv::Mat & image) const; const cv::Mat & image) const;
virtual void addStatisticsQuery(const Statistics & statistics) const; virtual void addStatisticsQuery(const Statistics & statistics) const;
virtual void savePreviewImageQuery(const cv::Mat & image) const; virtual void savePreviewImageQuery(const cv::Mat & image) const;
@@ -101,12 +101,20 @@ private:
const cv::Mat & cloud, const cv::Mat & cloud,
const std::map<int, Transform> & poses, const std::map<int, Transform> & poses,
const std::vector<std::vector<std::vector<unsigned int> > > & polygons, const std::vector<std::vector<std::vector<unsigned int> > > & polygons,
#if PCL_VERSION_COMPARE(>=, 1, 8, 0)
const std::vector<std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > > & texCoords,
#else
const std::vector<std::vector<Eigen::Vector2f> > & texCoords, const std::vector<std::vector<Eigen::Vector2f> > & texCoords,
#endif
const cv::Mat & textures) const; const cv::Mat & textures) const;
virtual cv::Mat loadOptimizedMeshQuery( virtual cv::Mat loadOptimizedMeshQuery(
std::map<int, Transform> * poses, std::map<int, Transform> * poses,
std::vector<std::vector<std::vector<unsigned int> > > * polygons, std::vector<std::vector<std::vector<unsigned int> > > * polygons,
#if PCL_VERSION_COMPARE(>=, 1, 8, 0)
std::vector<std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > > * texCoords,
#else
std::vector<std::vector<Eigen::Vector2f> > * texCoords, std::vector<std::vector<Eigen::Vector2f> > * texCoords,
#endif
cv::Mat * textures) const; cv::Mat * textures) const;
// Load objects // Load objects
+39 -37
View File
@@ -414,8 +414,7 @@ Feature2D * Feature2D::create(Feature2D::Type type, const ParametersMap & parame
if(type == Feature2D::kFeatureFastBrief || if(type == Feature2D::kFeatureFastBrief ||
type == Feature2D::kFeatureFastFreak || type == Feature2D::kFeatureFastFreak ||
type == Feature2D::kFeatureGfttBrief || type == Feature2D::kFeatureGfttBrief ||
type == Feature2D::kFeatureGfttFreak || type == Feature2D::kFeatureGfttFreak)
type == Feature2D::kFeatureFreak)
{ {
UWARN("BRIEF and FREAK features cannot be used because OpenCV was not built with xfeatures2d module. ORB is used instead."); UWARN("BRIEF and FREAK features cannot be used because OpenCV was not built with xfeatures2d module. ORB is used instead.");
type = Feature2D::kFeatureOrb; type = Feature2D::kFeatureOrb;
@@ -424,10 +423,15 @@ Feature2D * Feature2D::create(Feature2D::Type type, const ParametersMap & parame
#endif #endif
#if CV_MAJOR_VERSION < 3 #if CV_MAJOR_VERSION < 3
if(type == Feature2D::kFeatureFreak) if(type == Feature2D::kFeatureKaze)
{ {
UWARN("FREAK detector/descriptor can be used only with OpenCV3. GFTT/FREAK is used instead."); #ifdef RTABMAP_NONFREE
type = Feature2D::kFeatureGfttFreak; UWARN("KAZE detector/descriptor can be used only with OpenCV3. SURF is used instead.");
type = Feature2D::kFeatureSurf;
#else
UWARN("KAZE detector/descriptor can be used only with OpenCV3. ORB is used instead.");
type = Feature2D::kFeatureOrb;
#endif
} }
#endif #endif
@@ -461,6 +465,9 @@ Feature2D * Feature2D::create(Feature2D::Type type, const ParametersMap & parame
case Feature2D::kFeatureBrisk: case Feature2D::kFeatureBrisk:
feature2D = new BRISK(parameters); feature2D = new BRISK(parameters);
break; break;
case Feature2D::kFeatureKaze:
feature2D = new KAZE(parameters);
break;
#ifdef RTABMAP_NONFREE #ifdef RTABMAP_NONFREE
default: default:
feature2D = new SURF(parameters); feature2D = new SURF(parameters);
@@ -1469,71 +1476,66 @@ cv::Mat BRISK::generateDescriptorsImpl(const cv::Mat & image, std::vector<cv::Ke
return descriptors; return descriptors;
} }
////////////////////////// //////////////////////////
//FREAK //KAZE
////////////////////////// //////////////////////////
FREAK::FREAK(const ParametersMap & parameters) : KAZE::KAZE(const ParametersMap & parameters) :
orientationNormalized_(Parameters::defaultFREAKOrientationNormalized()), extended_(Parameters::defaultKAZEExtended()),
scaleNormalized_(Parameters::defaultFREAKScaleNormalized()), upright_(Parameters::defaultKAZEUpright()),
patternScale_(Parameters::defaultFREAKPatternScale()), threshold_(Parameters::defaultKAZEThreshold()),
nOctaves_(Parameters::defaultFREAKNOctaves()) nOctaves_(Parameters::defaultKAZENOctaves()),
nOctaveLayers_(Parameters::defaultKAZENOctaveLayers()),
diffusivity_(Parameters::defaultKAZEDiffusivity())
{ {
parseParameters(parameters); parseParameters(parameters);
} }
FREAK::~FREAK() KAZE::~KAZE()
{ {
} }
void FREAK::parseParameters(const ParametersMap & parameters) void KAZE::parseParameters(const ParametersMap & parameters)
{ {
Parameters::parse(parameters, Parameters::kFREAKOrientationNormalized(), orientationNormalized_); Parameters::parse(parameters, Parameters::kKAZEExtended(), extended_);
Parameters::parse(parameters, Parameters::kFREAKScaleNormalized(), scaleNormalized_); Parameters::parse(parameters, Parameters::kKAZEUpright(), upright_);
Parameters::parse(parameters, Parameters::kFREAKPatternScale(), patternScale_); Parameters::parse(parameters, Parameters::kKAZEThreshold(), threshold_);
Parameters::parse(parameters, Parameters::kFREAKNOctaves(), nOctaves_); Parameters::parse(parameters, Parameters::kKAZENOctaves(), nOctaves_);
Parameters::parse(parameters, Parameters::kKAZENOctaveLayers(), nOctaveLayers_);
Parameters::parse(parameters, Parameters::kKAZEDiffusivity(), diffusivity_);
#if CV_MAJOR_VERSION < 3 #if CV_MAJOR_VERSION > 2
_freak = cv::Ptr<CV_FREAK>(new CV_FREAK(orientationNormalized_, scaleNormalized_, patternScale_, nOctaves_)); kaze_ = cv::KAZE::create(extended_, upright_, threshold_, nOctaves_, nOctaveLayers_, diffusivity_);
#else #else
#ifdef HAVE_OPENCV_XFEATURES2D UWARN("RTAB-Map is not built with OpenCV3 so Kaze feature cannot be used!");
_freak = CV_FREAK::create(orientationNormalized_, scaleNormalized_, patternScale_, nOctaves_);
#else
UWARN("RTAB-Map is not built with OpenCV xfeatures2d module so Freak cannot be used!");
#endif
#endif #endif
} }
std::vector<cv::KeyPoint> FREAK::generateKeypointsImpl(const cv::Mat & image, const cv::Rect & roi, const cv::Mat & mask) const std::vector<cv::KeyPoint> KAZE::generateKeypointsImpl(const cv::Mat & image, const cv::Rect & roi, const cv::Mat & mask) const
{ {
UASSERT(!image.empty() && image.channels() == 1 && image.depth() == CV_8U); UASSERT(!image.empty() && image.channels() == 1 && image.depth() == CV_8U);
std::vector<cv::KeyPoint> keypoints; std::vector<cv::KeyPoint> keypoints;
#ifdef HAVE_OPENCV_XFEATURES2D #if CV_MAJOR_VERSION > 2
cv::Mat imgRoi(image, roi); cv::Mat imgRoi(image, roi);
cv::Mat maskRoi; cv::Mat maskRoi;
if (!mask.empty()) if (!mask.empty())
{ {
maskRoi = cv::Mat(mask, roi); maskRoi = cv::Mat(mask, roi);
} }
_freak->detect(imgRoi, keypoints, maskRoi); // Opencv keypoints kaze_->detect(imgRoi, keypoints, maskRoi); // Opencv keypoints
#else #else
UWARN("RTAB-Map is not built with OpenCV3 xfeatures2d module so Freak (for keypoint detection) cannot be used!"); UWARN("RTAB-Map is not built with OpenCV3 so Kaze feature cannot be used!");
#endif #endif
return keypoints; return keypoints;
} }
cv::Mat FREAK::generateDescriptorsImpl(const cv::Mat & image, std::vector<cv::KeyPoint> & keypoints) const cv::Mat KAZE::generateDescriptorsImpl(const cv::Mat & image, std::vector<cv::KeyPoint> & keypoints) const
{ {
UASSERT(!image.empty() && image.channels() == 1 && image.depth() == CV_8U); UASSERT(!image.empty() && image.channels() == 1 && image.depth() == CV_8U);
cv::Mat descriptors; cv::Mat descriptors;
#if CV_MAJOR_VERSION < 3 #if CV_MAJOR_VERSION > 2
_freak->compute(image, keypoints, descriptors); kaze_->compute(image, keypoints, descriptors);
#else #else
#ifdef HAVE_OPENCV_XFEATURES2D UWARN("RTAB-Map is not built with OpenCV3 so Kaze feature cannot be used!");
_freak->compute(image, keypoints, descriptors);
#else
UWARN("RTAB-Map is not built with OpenCV xfeatures2d module so Freak cannot be used!");
#endif
#endif #endif
return descriptors; return descriptors;
} }
+16
View File
@@ -718,7 +718,15 @@ void Memory::addSignatureToStm(Signature * signature, const cv::Mat & covariance
if(!signature->getPose().isNull() && if(!signature->getPose().isNull() &&
!_signatures.at(*_stMem.rbegin())->getPose().isNull()) !_signatures.at(*_stMem.rbegin())->getPose().isNull())
{ {
UASSERT(covariance.cols == 6 && covariance.rows == 6 && covariance.type() == CV_64FC1);
cv::Mat infMatrix = covariance.inv(); cv::Mat infMatrix = covariance.inv();
if((uIsFinite(covariance.at<double>(0,0)) && covariance.at<double>(0,0)>0.0) &&
!(uIsFinite(infMatrix.at<double>(0,0)) && infMatrix.at<double>(0,0)>0.0))
{
UERROR("Failed to invert the covariance matrix! Covariance matrix should be invertible!");
std::cout << "Covariance: " << covariance << std::endl;
infMatrix = cv::Mat::eye(6,6,CV_64FC1);
}
motionEstimate = _signatures.at(*_stMem.rbegin())->getPose().inverse() * signature->getPose(); motionEstimate = _signatures.at(*_stMem.rbegin())->getPose().inverse() * signature->getPose();
_signatures.at(*_stMem.rbegin())->addLink(Link(*_stMem.rbegin(), signature->id(), Link::kNeighbor, motionEstimate, infMatrix)); _signatures.at(*_stMem.rbegin())->addLink(Link(*_stMem.rbegin(), signature->id(), Link::kNeighbor, motionEstimate, infMatrix));
signature->addLink(Link(signature->id(), *_stMem.rbegin(), Link::kNeighbor, motionEstimate.inverse(), infMatrix)); signature->addLink(Link(signature->id(), *_stMem.rbegin(), Link::kNeighbor, motionEstimate.inverse(), infMatrix));
@@ -1671,7 +1679,11 @@ void Memory::saveOptimizedMesh(
const cv::Mat & cloud, const cv::Mat & cloud,
const std::map<int, Transform> & poses, const std::map<int, Transform> & poses,
const std::vector<std::vector<std::vector<unsigned int> > > & polygons, const std::vector<std::vector<std::vector<unsigned int> > > & polygons,
#if PCL_VERSION_COMPARE(>=, 1, 8, 0)
const std::vector<std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > > & texCoords,
#else
const std::vector<std::vector<Eigen::Vector2f> > & texCoords, const std::vector<std::vector<Eigen::Vector2f> > & texCoords,
#endif
const cv::Mat & textures) const const cv::Mat & textures) const
{ {
if(_dbDriver) if(_dbDriver)
@@ -1683,7 +1695,11 @@ void Memory::saveOptimizedMesh(
cv::Mat Memory::loadOptimizedMesh( cv::Mat Memory::loadOptimizedMesh(
std::map<int, Transform> * poses, std::map<int, Transform> * poses,
std::vector<std::vector<std::vector<unsigned int> > > * polygons, std::vector<std::vector<std::vector<unsigned int> > > * polygons,
#if PCL_VERSION_COMPARE(>=, 1, 8, 0)
std::vector<std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f>> > * texCoords,
#else
std::vector<std::vector<Eigen::Vector2f> > * texCoords, std::vector<std::vector<Eigen::Vector2f> > * texCoords,
#endif
cv::Mat * textures) const cv::Mat * textures) const
{ {
if(_dbDriver) if(_dbDriver)
+22 -21
View File
@@ -98,26 +98,6 @@ void OccupancyGrid::parseParameters(const ParametersMap & parameters)
Parameters::parse(parameters, Parameters::kGridMaxObstacleHeight(), maxObstacleHeight_); Parameters::parse(parameters, Parameters::kGridMaxObstacleHeight(), maxObstacleHeight_);
Parameters::parse(parameters, Parameters::kGridMinGroundHeight(), minGroundHeight_); Parameters::parse(parameters, Parameters::kGridMinGroundHeight(), minGroundHeight_);
Parameters::parse(parameters, Parameters::kGridMaxGroundHeight(), maxGroundHeight_); Parameters::parse(parameters, Parameters::kGridMaxGroundHeight(), maxGroundHeight_);
if(maxGroundHeight_ != 0.0f &&
maxObstacleHeight_ != 0.0f &&
maxObstacleHeight_ < maxGroundHeight_)
{
UWARN("\"%s\" should be lower than \"%s\", setting \"%s\" to 0 (disabled).",
Parameters::kGridMaxGroundHeight().c_str(),
Parameters::kGridMaxObstacleHeight().c_str(),
Parameters::kGridMaxObstacleHeight().c_str());
maxObstacleHeight_ = 0;
}
if(maxGroundHeight_ != 0.0f &&
minGroundHeight_ != 0.0f &&
maxGroundHeight_ < minGroundHeight_)
{
UWARN("\"%s\" should be lower than \"%s\", setting \"%s\" to 0 (disabled).",
Parameters::kGridMinGroundHeight().c_str(),
Parameters::kGridMaxGroundHeight().c_str(),
Parameters::kGridMinGroundHeight().c_str());
minGroundHeight_ = 0;
}
Parameters::parse(parameters, Parameters::kGridNormalK(), normalKSearch_); Parameters::parse(parameters, Parameters::kGridNormalK(), normalKSearch_);
if(Parameters::parse(parameters, Parameters::kGridMaxGroundAngle(), maxGroundAngle_)) if(Parameters::parse(parameters, Parameters::kGridMaxGroundAngle(), maxGroundAngle_))
{ {
@@ -182,6 +162,26 @@ void OccupancyGrid::parseParameters(const ParametersMap & parameters)
Parameters::kGridMaxGroundHeight().c_str(), cellSize_); Parameters::kGridMaxGroundHeight().c_str(), cellSize_);
maxGroundHeight_ = cellSize_; maxGroundHeight_ = cellSize_;
} }
if(maxGroundHeight_ != 0.0f &&
maxObstacleHeight_ != 0.0f &&
maxObstacleHeight_ < maxGroundHeight_)
{
UWARN("\"%s\" should be lower than \"%s\", setting \"%s\" to 0 (disabled).",
Parameters::kGridMaxGroundHeight().c_str(),
Parameters::kGridMaxObstacleHeight().c_str(),
Parameters::kGridMaxObstacleHeight().c_str());
maxObstacleHeight_ = 0;
}
if(maxGroundHeight_ != 0.0f &&
minGroundHeight_ != 0.0f &&
maxGroundHeight_ < minGroundHeight_)
{
UWARN("\"%s\" should be lower than \"%s\", setting \"%s\" to 0 (disabled).",
Parameters::kGridMinGroundHeight().c_str(),
Parameters::kGridMaxGroundHeight().c_str(),
Parameters::kGridMinGroundHeight().c_str());
minGroundHeight_ = 0;
}
} }
void OccupancyGrid::setCellSize(float cellSize) void OccupancyGrid::setCellSize(float cellSize)
@@ -299,7 +299,8 @@ void OccupancyGrid::createLocalMap(
viewPoint.z = viewpointRotated.z(); viewPoint.z = viewpointRotated.z();
} }
if(cloud->size()) if((cloud->is_dense && cloud->size()) ||
(!cloud->is_dense && indices->size()))
{ {
pcl::IndicesPtr groundIndices(new std::vector<int>); pcl::IndicesPtr groundIndices(new std::vector<int>);
pcl::IndicesPtr obstaclesIndices(new std::vector<int>); pcl::IndicesPtr obstaclesIndices(new std::vector<int>);
+16 -6
View File
@@ -90,6 +90,7 @@ void OdometryDVO::reset(const Transform & initialPose)
} }
lost_ = false; lost_ = false;
motionFromKeyFrame_.setIdentity(); motionFromKeyFrame_.setIdentity();
previousLocalTransform_.setNull();
#endif #endif
} }
@@ -192,6 +193,7 @@ Transform OdometryDVO::computeTransform(
dvo::core::RgbdImagePyramid * current = new dvo::core::RgbdImagePyramid(*camera_, grey_s16, depth_float); dvo::core::RgbdImagePyramid * current = new dvo::core::RgbdImagePyramid(*camera_, grey_s16, depth_float);
const Transform & localTransform = data.cameraModels()[0].localTransform();
cv::Mat covariance; cv::Mat covariance;
if(reference_ == 0) if(reference_ == 0)
{ {
@@ -245,16 +247,24 @@ Transform OdometryDVO::computeTransform(
reference_ = 0; // this will make restart from the next frame reference_ = 0; // this will make restart from the next frame
motionFromKeyFrame_.setIdentity(); motionFromKeyFrame_.setIdentity();
t.setNull(); t.setNull();
previousLocalTransform_.setNull();
covariance = cv::Mat::eye(6,6,CV_64FC1) * 9999.0; covariance = cv::Mat::eye(6,6,CV_64FC1) * 9999.0;
UWARN("dvo failed to estimate motion, tracking will be reinitialized on next frame."); UWARN("dvo failed to estimate motion, tracking will be reinitialized on next frame.");
} }
}
const Transform & localTransform = data.cameraModels()[0].localTransform(); if(!t.isNull() && !t.isIdentity() && !localTransform.isIdentity() && !localTransform.isNull())
if(!t.isNull() && !t.isIdentity() && !localTransform.isIdentity() && !localTransform.isNull()) {
{ // from camera frame to base frame
// from camera frame to base frame if(!previousLocalTransform_.isNull())
t = localTransform * t * localTransform.inverse(); {
t = previousLocalTransform_ * t * localTransform.inverse();
}
else
{
t = localTransform * t * localTransform.inverse();
}
previousLocalTransform_ = localTransform;
}
} }
if(info) if(info)
+12 -1
View File
@@ -111,6 +111,7 @@ void OdometryFovis::reset(const Transform & initialPose)
stereoDepth_ = 0; stereoDepth_ = 0;
} }
lost_ = false; lost_ = false;
previousLocalTransform_.setNull();
#endif #endif
} }
@@ -341,12 +342,14 @@ Transform OdometryFovis::computeTransform(
t.setNull(); t.setNull();
lost_ = true; lost_ = true;
covariance = cv::Mat::eye(6,6, CV_64FC1)*9999.0; covariance = cv::Mat::eye(6,6, CV_64FC1)*9999.0;
previousLocalTransform_.setNull();
} }
else if(lost_) else if(lost_)
{ {
lost_ = false; lost_ = false;
// we are not lost anymore but we don't know where we are now according to last valid pose // we are not lost anymore but we don't know where we are now according to last valid pose
covariance = cv::Mat::eye(6,6, CV_64FC1)*9999.0; covariance = cv::Mat::eye(6,6, CV_64FC1)*9999.0;
previousLocalTransform_.setNull();
} }
else else
{ {
@@ -362,7 +365,15 @@ Transform OdometryFovis::computeTransform(
if(!t.isNull() && !t.isIdentity() && !localTransform.isIdentity() && !localTransform.isNull()) if(!t.isNull() && !t.isIdentity() && !localTransform.isIdentity() && !localTransform.isNull())
{ {
// from camera frame to base frame // from camera frame to base frame
t = localTransform * t * localTransform.inverse(); if(!previousLocalTransform_.isNull())
{
t = previousLocalTransform_ * t * localTransform.inverse();
}
else
{
t = localTransform * t * localTransform.inverse();
}
previousLocalTransform_ = localTransform;
} }
if(info) if(info)
+12 -5
View File
@@ -33,6 +33,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "rtabmap/utilite/ULogger.h" #include "rtabmap/utilite/ULogger.h"
#include "rtabmap/utilite/UTimer.h" #include "rtabmap/utilite/UTimer.h"
#include "rtabmap/utilite/UStl.h" #include "rtabmap/utilite/UStl.h"
#include "rtabmap/utilite/UDirectory.h"
#ifdef RTABMAP_ORB_SLAM2 #ifdef RTABMAP_ORB_SLAM2
#include <System.h> #include <System.h>
@@ -495,6 +496,7 @@ public:
if(!vocabularyPath.empty()) if(!vocabularyPath.empty())
{ {
//Load ORB Vocabulary //Load ORB Vocabulary
vocabularyPath = uReplaceChar(vocabularyPath, '~', UDirectory::homeDir());
UWARN("Loading ORB Vocabulary: \"%s\". This could take a while...", vocabularyPath.c_str()); UWARN("Loading ORB Vocabulary: \"%s\". This could take a while...", vocabularyPath.c_str());
mpVocabulary = new ORB_SLAM2::ORBVocabulary(); mpVocabulary = new ORB_SLAM2::ORBVocabulary();
bool bVocLoad = mpVocabulary->loadFromTextFile(vocabularyPath); bool bVocLoad = mpVocabulary->loadFromTextFile(vocabularyPath);
@@ -773,6 +775,7 @@ void OdometryORBSLAM2::reset(const Transform & initialPose)
orbslam2_->shutdown(); orbslam2_->shutdown();
} }
firstFrame_ = true; firstFrame_ = true;
originLocalTransform_.setNull();
#endif #endif
} }
@@ -845,14 +848,17 @@ Transform OdometryORBSLAM2::computeTransform(
} }
else if(Tcw.cols == 4 && Tcw.rows == 4) else if(Tcw.cols == 4 && Tcw.rows == 4)
{ {
t = Transform(cv::Mat(Tcw, cv::Range(0,3), cv::Range(0,4)).clone()); t = Transform(cv::Mat(Tcw, cv::Range(0,3), cv::Range(0,4)));
if(!t.isNull() && !t.isIdentity() && !localTransform.isIdentity() && !localTransform.isNull()) if(!t.isNull() && !t.isIdentity() && !localTransform.isIdentity() && !localTransform.isNull())
{ {
// from camera frame to base frame if(originLocalTransform_.isNull())
t = localTransform * t.inverse() * localTransform.inverse(); {
originLocalTransform_ = localTransform;
}
t = originLocalTransform_ * t.inverse() * localTransform.inverse();
t = this->getPose().inverse() * t;
} }
t = this->getPose().inverse() * t;
if(firstFrame_) if(firstFrame_)
{ {
@@ -916,12 +922,13 @@ Transform OdometryORBSLAM2::computeTransform(
} }
info->wordMatches.resize(oi); info->wordMatches.resize(oi);
info->wordInliers.resize(oi); info->wordInliers.resize(oi);
info->inliers = oi;
std::vector<ORB_SLAM2::MapPoint*> mapPoints = orbslam2_->mpMap->GetAllMapPoints(); std::vector<ORB_SLAM2::MapPoint*> mapPoints = orbslam2_->mpMap->GetAllMapPoints();
for (unsigned int i = 0; i < mapPoints.size(); ++i) for (unsigned int i = 0; i < mapPoints.size(); ++i)
{ {
cv::Mat pt = mapPoints[i]->GetWorldPos(); cv::Mat pt = mapPoints[i]->GetWorldPos();
info->localMap.insert(std::make_pair(mapPoints[i]->mnId, util3d::transformPoint(cv::Point3f(pt), localTransform))); info->localMap.insert(std::make_pair(mapPoints[i]->mnId, util3d::transformPoint(cv::Point3f(pt), originLocalTransform_)));
} }
} }
} }
+12 -2
View File
@@ -86,6 +86,7 @@ void OdometryViso2::reset(const Transform & initialPose)
} }
lost_ = false; lost_ = false;
reference_motion_.setIdentity(); reference_motion_.setIdentity();
previousLocalTransform_.setNull();
#endif #endif
} }
@@ -253,10 +254,19 @@ Transform OdometryViso2::computeTransform(
} }
} }
if(!t.isNull() && !t.isIdentity() && !data.stereoCameraModel().localTransform().isIdentity() && !data.stereoCameraModel().localTransform().isNull()) const Transform & localTransform = data.stereoCameraModel().localTransform();
if(!t.isNull() && !t.isIdentity() && !localTransform.isIdentity() && !localTransform.isNull())
{ {
// from camera frame to base frame // from camera frame to base frame
t = data.stereoCameraModel().localTransform() * t * data.stereoCameraModel().localTransform().inverse(); if(!previousLocalTransform_.isNull())
{
t = previousLocalTransform_ * t * localTransform.inverse();
}
else
{
t = localTransform * t * localTransform.inverse();
}
previousLocalTransform_ = localTransform;
} }
if(info) if(info)
+6 -2
View File
@@ -156,7 +156,8 @@ bool Parameters::isFeatureParameter(const std::string & parameter)
group.compare("FREAK") == 0 || group.compare("FREAK") == 0 ||
group.compare("BRIEF") == 0 || group.compare("BRIEF") == 0 ||
group.compare("GFTT") == 0 || group.compare("GFTT") == 0 ||
group.compare("BRISK") == 0; group.compare("BRISK") == 0 ||
group.compare("KAZE") == 0;
} }
rtabmap::ParametersMap Parameters::getDefaultOdometryParameters(bool stereo, bool vis, bool icp) rtabmap::ParametersMap Parameters::getDefaultOdometryParameters(bool stereo, bool vis, bool icp)
@@ -224,6 +225,9 @@ const std::map<std::string, std::pair<bool, std::string> > & Parameters::getRemo
{ {
// removed parameters // removed parameters
// 0.13.1
removedParameters_.insert(std::make_pair("Rtabmap/VhStrategy", std::make_pair(true, Parameters::kVhEpEnabled())));
// 0.12.5 // 0.12.5
removedParameters_.insert(std::make_pair("Grid/FullUpdate", std::make_pair(true, Parameters::kGridGlobalFullUpdate()))); removedParameters_.insert(std::make_pair("Grid/FullUpdate", std::make_pair(true, Parameters::kGridGlobalFullUpdate())));
@@ -807,7 +811,7 @@ void Parameters::readINI(const std::string & configFile, ParametersMap & paramet
{ {
ULOGGER_WARN("Section \"Core\" in %s doesn't exist... " ULOGGER_WARN("Section \"Core\" in %s doesn't exist... "
"Ignore this warning if the ini file does not exist yet. " "Ignore this warning if the ini file does not exist yet. "
"The ini file will be automatically created when this node will close.", configFile.c_str()); "The ini file will be automatically created when rtabmap will close.", configFile.c_str());
} }
} }
+6 -6
View File
@@ -257,17 +257,17 @@ void Registration::normalizeCovariance(cv::Mat & covariance, const Transform & t
} }
double epsilon = 0.000001; double epsilon = 0.000001;
if(covariance.at<double>(0,0)<=0.0) if(covariance.at<double>(0,0)<=epsilon)
covariance.at<double>(0,0) = epsilon; // epsilon if exact transform covariance.at<double>(0,0) = epsilon; // epsilon if exact transform
if(covariance.at<double>(1,1)<=0.0) if(covariance.at<double>(1,1)<=epsilon)
covariance.at<double>(1,1) = epsilon; // epsilon if exact transform covariance.at<double>(1,1) = epsilon; // epsilon if exact transform
if(covariance.at<double>(2,2)<=0.0) if(covariance.at<double>(2,2)<=epsilon)
covariance.at<double>(2,2) = epsilon; // epsilon if exact transform covariance.at<double>(2,2) = epsilon; // epsilon if exact transform
if(covariance.at<double>(3,3)<=0.0) if(covariance.at<double>(3,3)<=epsilon)
covariance.at<double>(3,3) = epsilon; // epsilon if exact transform covariance.at<double>(3,3) = epsilon; // epsilon if exact transform
if(covariance.at<double>(4,4)<=0.0) if(covariance.at<double>(4,4)<=epsilon)
covariance.at<double>(4,4) = epsilon; // epsilon if exact transform covariance.at<double>(4,4) = epsilon; // epsilon if exact transform
if(covariance.at<double>(5,5)<=0.0) if(covariance.at<double>(5,5)<=epsilon)
covariance.at<double>(5,5) = epsilon; // epsilon if exact transform covariance.at<double>(5,5) = epsilon; // epsilon if exact transform
} }
+16 -2
View File
@@ -1234,6 +1234,20 @@ Transform RegistrationVis::computeTransformationImpl(
UINFO(msg.c_str()); UINFO(msg.c_str());
} }
} }
double epsilon = 0.000001;
if(covariances[dir].at<double>(0,0)<=epsilon)
covariances[dir].at<double>(0,0) = epsilon; // epsilon if exact transform
if(covariances[dir].at<double>(1,1)<=epsilon)
covariances[dir].at<double>(1,1) = epsilon; // epsilon if exact transform
if(covariances[dir].at<double>(2,2)<=epsilon)
covariances[dir].at<double>(2,2) = epsilon; // epsilon if exact transform
if(covariances[dir].at<double>(3,3)<=epsilon)
covariances[dir].at<double>(3,3) = epsilon; // epsilon if exact transform
if(covariances[dir].at<double>(4,4)<=epsilon)
covariances[dir].at<double>(4,4) = epsilon; // epsilon if exact transform
if(covariances[dir].at<double>(5,5)<=epsilon)
covariances[dir].at<double>(5,5) = epsilon; // epsilon if exact transform
} }
if(!_forwardEstimateOnly) if(!_forwardEstimateOnly)
@@ -1292,13 +1306,13 @@ Transform RegistrationVis::computeTransformationImpl(
poses.insert(std::make_pair(2, transforms[0])); poses.insert(std::make_pair(2, transforms[0]));
cv::Mat cov = covariances[0].clone(); cv::Mat cov = covariances[0].clone();
normalizeCovariance(cov, transform); normalizeCovariance(cov, transforms[0]);
links.insert(std::make_pair(1, Link(1, 2, Link::kNeighbor, transforms[0], cov.inv()))); links.insert(std::make_pair(1, Link(1, 2, Link::kNeighbor, transforms[0], cov.inv())));
if(!transforms[1].isNull() && inliers[1].size()) if(!transforms[1].isNull() && inliers[1].size())
{ {
cov = covariances[1].clone(); cov = covariances[1].clone();
normalizeCovariance(cov, transform); normalizeCovariance(cov, transforms[1]);
links.insert(std::make_pair(2, Link(2, 1, Link::kNeighbor, transforms[1], cov.inv()))); links.insert(std::make_pair(2, Link(2, 1, Link::kNeighbor, transforms[1], cov.inv())));
} }
+6 -14
View File
@@ -83,6 +83,7 @@ Rtabmap::Rtabmap() :
_maxMemoryAllowed(Parameters::defaultRtabmapMemoryThr()), // 0=inf _maxMemoryAllowed(Parameters::defaultRtabmapMemoryThr()), // 0=inf
_loopThr(Parameters::defaultRtabmapLoopThr()), _loopThr(Parameters::defaultRtabmapLoopThr()),
_loopRatio(Parameters::defaultRtabmapLoopRatio()), _loopRatio(Parameters::defaultRtabmapLoopRatio()),
_verifyLoopClosureHypothesis(Parameters::defaultVhEpEnabled()),
_maxRetrieved(Parameters::defaultRtabmapMaxRetrieved()), _maxRetrieved(Parameters::defaultRtabmapMaxRetrieved()),
_maxLocalRetrieved(Parameters::defaultRGBDMaxLocalRetrieved()), _maxLocalRetrieved(Parameters::defaultRGBDMaxLocalRetrieved()),
_rawDataKept(Parameters::defaultMemImageKept()), _rawDataKept(Parameters::defaultMemImageKept()),
@@ -401,6 +402,7 @@ void Rtabmap::parseParameters(const ParametersMap & parameters)
Parameters::parse(parameters, Parameters::kRtabmapMemoryThr(), _maxMemoryAllowed); Parameters::parse(parameters, Parameters::kRtabmapMemoryThr(), _maxMemoryAllowed);
Parameters::parse(parameters, Parameters::kRtabmapLoopThr(), _loopThr); Parameters::parse(parameters, Parameters::kRtabmapLoopThr(), _loopThr);
Parameters::parse(parameters, Parameters::kRtabmapLoopRatio(), _loopRatio); Parameters::parse(parameters, Parameters::kRtabmapLoopRatio(), _loopRatio);
Parameters::parse(parameters, Parameters::kVhEpEnabled(), _verifyLoopClosureHypothesis);
Parameters::parse(parameters, Parameters::kRtabmapMaxRetrieved(), _maxRetrieved); Parameters::parse(parameters, Parameters::kRtabmapMaxRetrieved(), _maxRetrieved);
Parameters::parse(parameters, Parameters::kRGBDMaxLocalRetrieved(), _maxLocalRetrieved); Parameters::parse(parameters, Parameters::kRGBDMaxLocalRetrieved(), _maxLocalRetrieved);
Parameters::parse(parameters, Parameters::kMemImageKept(), _rawDataKept); Parameters::parse(parameters, Parameters::kMemImageKept(), _rawDataKept);
@@ -470,22 +472,11 @@ void Rtabmap::parseParameters(const ParametersMap & parameters)
_memory->parseParameters(parameters); _memory->parseParameters(parameters);
} }
VhStrategy vhStrategy = kVhUndef; if(!_epipolarGeometry)
// Verifying hypotheses strategy
if((iter=parameters.find(Parameters::kRtabmapVhStrategy())) != parameters.end())
{
vhStrategy = (VhStrategy)std::atoi((*iter).second.c_str());
}
if(!_epipolarGeometry && vhStrategy == kVhEpipolar)
{ {
_epipolarGeometry = new EpipolarGeometry(_parameters); _epipolarGeometry = new EpipolarGeometry(_parameters);
} }
else if(_epipolarGeometry && vhStrategy == kVhNone) else
{
delete _epipolarGeometry;
_epipolarGeometry = 0;
}
else if(_epipolarGeometry)
{ {
_epipolarGeometry->parseParameters(parameters); _epipolarGeometry->parseParameters(parameters);
} }
@@ -1407,7 +1398,7 @@ bool Rtabmap::process(
// Ignore loop closure if there is only one loop closure hypothesis // Ignore loop closure if there is only one loop closure hypothesis
UDEBUG("rejected hypothesis: single hypothesis"); UDEBUG("rejected hypothesis: single hypothesis");
} }
else if(_epipolarGeometry && !_epipolarGeometry->check(signature, _memory->getSignature(_highestHypothesis.first))) else if(_verifyLoopClosureHypothesis && !_epipolarGeometry->check(signature, _memory->getSignature(_highestHypothesis.first)))
{ {
UWARN("rejected hypothesis: by epipolar geometry"); UWARN("rejected hypothesis: by epipolar geometry");
} }
@@ -2550,6 +2541,7 @@ bool Rtabmap::process(
id = _memory->getLastWorkingSignature()->id(); id = _memory->getLastWorkingSignature()->id();
UDEBUG("Refresh local map from %d", id); UDEBUG("Refresh local map from %d", id);
} }
UDEBUG("id=%d _optimizedPoses=%d", id, (int)_optimizedPoses.size());
if(id > 0) if(id > 0)
{ {
if(_lastLocalizationNodeId != 0) if(_lastLocalizationNodeId != 0)
+10 -11
View File
@@ -570,8 +570,7 @@ void RtabmapThread::addData(const OdometryEvent & odomEvent)
} }
if(!lastPose_.isIdentity() && if(!lastPose_.isIdentity() &&
(odomEvent.pose().isIdentity() || (odomEvent.pose().isIdentity() ||
odomEvent.rotVariance()>=9999 || odomEvent.info().covariance.at<double>(0,0)>=9999))
odomEvent.transVariance()>=9999))
{ {
if(odomEvent.pose().isIdentity()) if(odomEvent.pose().isIdentity())
{ {
@@ -579,21 +578,21 @@ void RtabmapThread::addData(const OdometryEvent & odomEvent)
} }
else else
{ {
UWARN("Odometry is reset (high variance (%f/%f >=9999 detected). Increment map id!", odomEvent.transVariance(), odomEvent.rotVariance()); UWARN("Odometry is reset (high variance (%f >=9999 detected). Increment map id!", odomEvent.info().covariance.at<double>(0,0));
} }
pushNewState(kStateTriggeringMap); pushNewState(kStateTriggeringMap);
covariance_ = cv::Mat(); covariance_ = cv::Mat();
} }
double maxRotVar = odomEvent.rotVariance(); if(uIsFinite(odomEvent.info().covariance.at<double>(0,0)) &&
double maxTransVar = odomEvent.transVariance(); odomEvent.info().covariance.at<double>(0,0) != 1.0 &&
if(maxRotVar != 1.0f && maxTransVar != 1.0f && !covariance_.empty()) odomEvent.info().covariance.at<double>(0,0)>0.0)
{ {
covariance_ += odomEvent.covariance(); // Use largest covariance error (to be independent of the odometry frame rate)
} if(covariance_.empty() || odomEvent.info().covariance.at<double>(0,0) > covariance_.at<double>(0,0))
else {
{ covariance_ = odomEvent.info().covariance;
covariance_ = odomEvent.covariance(); }
} }
if(ignoreFrame && !_createIntermediateNodes) if(ignoreFrame && !_createIntermediateNodes)
+69 -5
View File
@@ -957,9 +957,40 @@ pcl::PointCloud<pcl::PointXYZ>::Ptr RTABMAP_EXP cloudFromSensorData(
leftMono = sensorData.imageRaw(); leftMono = sensorData.imageRaw();
} }
cv::Mat right(sensorData.rightRaw());
StereoCameraModel model = sensorData.stereoCameraModel();
if( roiRatios.size() == 4 &&
((roiRatios[0] > 0.0f && roiRatios[0] <= 1.0f) ||
(roiRatios[1] > 0.0f && roiRatios[1] <= 1.0f) ||
(roiRatios[2] > 0.0f && roiRatios[2] <= 1.0f) ||
(roiRatios[3] > 0.0f && roiRatios[3] <= 1.0f)))
{
cv::Rect roi = util2d::computeRoi(leftMono, roiRatios);
if( roi.width%decimation==0 &&
roi.height%decimation==0)
{
leftMono = cv::Mat(leftMono, roi);
right = cv::Mat(right, roi);
model.roi(roi);
}
else
{
UERROR("Cannot apply ROI ratios [%f,%f,%f,%f] because resulting "
"dimension (left=%dx%d) cannot be divided exactly "
"by decimation parameter (%d). Ignoring ROI ratios...",
roiRatios[0],
roiRatios[1],
roiRatios[2],
roiRatios[3],
roi.width,
roi.height,
decimation);
}
}
cloud = cloudFromDisparity( cloud = cloudFromDisparity(
util2d::disparityFromStereoImages(leftMono, sensorData.rightRaw(), stereoParameters), util2d::disparityFromStereoImages(leftMono, right, stereoParameters),
sensorData.stereoCameraModel(), model,
decimation, decimation,
maxDepth, maxDepth,
minDepth, minDepth,
@@ -1091,10 +1122,43 @@ pcl::PointCloud<pcl::PointXYZRGB>::Ptr RTABMAP_EXP cloudRGBFromSensorData(
{ {
//stereo //stereo
UDEBUG(""); UDEBUG("");
cv::Mat left(sensorData.imageRaw());
cv::Mat right(sensorData.rightRaw());
StereoCameraModel model = sensorData.stereoCameraModel();
if( roiRatios.size() == 4 &&
((roiRatios[0] > 0.0f && roiRatios[0] <= 1.0f) ||
(roiRatios[1] > 0.0f && roiRatios[1] <= 1.0f) ||
(roiRatios[2] > 0.0f && roiRatios[2] <= 1.0f) ||
(roiRatios[3] > 0.0f && roiRatios[3] <= 1.0f)))
{
cv::Rect roi = util2d::computeRoi(left, roiRatios);
if( roi.width%decimation==0 &&
roi.height%decimation==0)
{
left = cv::Mat(left, roi);
right = cv::Mat(right, roi);
model.roi(roi);
}
else
{
UERROR("Cannot apply ROI ratios [%f,%f,%f,%f] because resulting "
"dimension (left=%dx%d) cannot be divided exactly "
"by decimation parameter (%d). Ignoring ROI ratios...",
roiRatios[0],
roiRatios[1],
roiRatios[2],
roiRatios[3],
roi.width,
roi.height,
decimation);
}
}
cloud = cloudFromStereoImages( cloud = cloudFromStereoImages(
sensorData.imageRaw(), left,
sensorData.rightRaw(), right,
sensorData.stereoCameraModel(), model,
decimation, decimation,
maxDepth, maxDepth,
minDepth, minDepth,
+13 -5
View File
@@ -142,6 +142,8 @@ pcl::PointCloud<pcl::PointXYZ>::Ptr voxelize(
float voxelSize) float voxelSize)
{ {
UASSERT(voxelSize > 0.0f); UASSERT(voxelSize > 0.0f);
UASSERT_MSG((cloud->is_dense && cloud->size()) || (!cloud->is_dense && indices->size()),
uFormat("Cloud size=%d indices=%d is_dense=%s", (int)cloud->size(), (int)indices->size(), cloud->is_dense?"true":"false").c_str());
pcl::PointCloud<pcl::PointXYZ>::Ptr output(new pcl::PointCloud<pcl::PointXYZ>); pcl::PointCloud<pcl::PointXYZ>::Ptr output(new pcl::PointCloud<pcl::PointXYZ>);
pcl::VoxelGrid<pcl::PointXYZ> filter; pcl::VoxelGrid<pcl::PointXYZ> filter;
filter.setLeafSize(voxelSize, voxelSize, voxelSize); filter.setLeafSize(voxelSize, voxelSize, voxelSize);
@@ -159,6 +161,8 @@ pcl::PointCloud<pcl::PointNormal>::Ptr voxelize(
float voxelSize) float voxelSize)
{ {
UASSERT(voxelSize > 0.0f); UASSERT(voxelSize > 0.0f);
UASSERT_MSG((cloud->is_dense && cloud->size()) || (!cloud->is_dense && indices->size()),
uFormat("Cloud size=%d indices=%d is_dense=%s", (int)cloud->size(), (int)indices->size(), cloud->is_dense?"true":"false").c_str());
pcl::PointCloud<pcl::PointNormal>::Ptr output(new pcl::PointCloud<pcl::PointNormal>); pcl::PointCloud<pcl::PointNormal>::Ptr output(new pcl::PointCloud<pcl::PointNormal>);
pcl::VoxelGrid<pcl::PointNormal> filter; pcl::VoxelGrid<pcl::PointNormal> filter;
filter.setLeafSize(voxelSize, voxelSize, voxelSize); filter.setLeafSize(voxelSize, voxelSize, voxelSize);
@@ -176,6 +180,8 @@ pcl::PointCloud<pcl::PointXYZRGB>::Ptr voxelize(
float voxelSize) float voxelSize)
{ {
UASSERT(voxelSize > 0.0f); UASSERT(voxelSize > 0.0f);
UASSERT_MSG((cloud->is_dense && cloud->size()) || (!cloud->is_dense && indices->size()),
uFormat("Cloud size=%d indices=%d is_dense=%s", (int)cloud->size(), (int)indices->size(), cloud->is_dense?"true":"false").c_str());
pcl::PointCloud<pcl::PointXYZRGB>::Ptr output(new pcl::PointCloud<pcl::PointXYZRGB>); pcl::PointCloud<pcl::PointXYZRGB>::Ptr output(new pcl::PointCloud<pcl::PointXYZRGB>);
pcl::VoxelGrid<pcl::PointXYZRGB> filter; pcl::VoxelGrid<pcl::PointXYZRGB> filter;
filter.setLeafSize(voxelSize, voxelSize, voxelSize); filter.setLeafSize(voxelSize, voxelSize, voxelSize);
@@ -193,6 +199,8 @@ pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr voxelize(
float voxelSize) float voxelSize)
{ {
UASSERT(voxelSize > 0.0f); UASSERT(voxelSize > 0.0f);
UASSERT_MSG((cloud->is_dense && cloud->size()) || (!cloud->is_dense && indices->size()),
uFormat("Cloud size=%d indices=%d is_dense=%s", (int)cloud->size(), (int)indices->size(), cloud->is_dense?"true":"false").c_str());
pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr output(new pcl::PointCloud<pcl::PointXYZRGBNormal>); pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr output(new pcl::PointCloud<pcl::PointXYZRGBNormal>);
pcl::VoxelGrid<pcl::PointXYZRGBNormal> filter; pcl::VoxelGrid<pcl::PointXYZRGBNormal> filter;
filter.setLeafSize(voxelSize, voxelSize, voxelSize); filter.setLeafSize(voxelSize, voxelSize, voxelSize);
@@ -266,7 +274,7 @@ pcl::IndicesPtr passThrough(
float max, float max,
bool negative) bool negative)
{ {
UASSERT(max > min); UASSERT_MSG(max > min, uFormat("cloud=%d, max=%f min=%f axis=%s", (int)cloud->size(), max, min, axis.c_str()).c_str());
UASSERT(axis.compare("x") == 0 || axis.compare("y") == 0 || axis.compare("z") == 0); UASSERT(axis.compare("x") == 0 || axis.compare("y") == 0 || axis.compare("z") == 0);
pcl::IndicesPtr output(new std::vector<int>); pcl::IndicesPtr output(new std::vector<int>);
@@ -287,7 +295,7 @@ pcl::IndicesPtr passThrough(
float max, float max,
bool negative) bool negative)
{ {
UASSERT(max > min); UASSERT_MSG(max > min, uFormat("cloud=%d, max=%f min=%f axis=%s", (int)cloud->size(), max, min, axis.c_str()).c_str());
UASSERT(axis.compare("x") == 0 || axis.compare("y") == 0 || axis.compare("z") == 0); UASSERT(axis.compare("x") == 0 || axis.compare("y") == 0 || axis.compare("z") == 0);
pcl::IndicesPtr output(new std::vector<int>); pcl::IndicesPtr output(new std::vector<int>);
@@ -308,7 +316,7 @@ pcl::PointCloud<pcl::PointXYZ>::Ptr passThrough(
float max, float max,
bool negative) bool negative)
{ {
UASSERT(max > min); UASSERT_MSG(max > min, uFormat("cloud=%d, max=%f min=%f axis=%s", (int)cloud->size(), max, min, axis.c_str()).c_str());
UASSERT(axis.compare("x") == 0 || axis.compare("y") == 0 || axis.compare("z") == 0); UASSERT(axis.compare("x") == 0 || axis.compare("y") == 0 || axis.compare("z") == 0);
pcl::PointCloud<pcl::PointXYZ>::Ptr output(new pcl::PointCloud<pcl::PointXYZ>); pcl::PointCloud<pcl::PointXYZ>::Ptr output(new pcl::PointCloud<pcl::PointXYZ>);
@@ -328,7 +336,7 @@ pcl::PointCloud<pcl::PointXYZRGB>::Ptr passThrough(
float max, float max,
bool negative) bool negative)
{ {
UASSERT(max > min); UASSERT_MSG(max > min, uFormat("cloud=%d, max=%f min=%f axis=%s", (int)cloud->size(), max, min, axis.c_str()).c_str());
UASSERT(axis.compare("x") == 0 || axis.compare("y") == 0 || axis.compare("z") == 0); UASSERT(axis.compare("x") == 0 || axis.compare("y") == 0 || axis.compare("z") == 0);
pcl::PointCloud<pcl::PointXYZRGB>::Ptr output(new pcl::PointCloud<pcl::PointXYZRGB>); pcl::PointCloud<pcl::PointXYZRGB>::Ptr output(new pcl::PointCloud<pcl::PointXYZRGB>);
@@ -348,7 +356,7 @@ pcl::PointCloud<pcl::PointNormal>::Ptr passThrough(
float max, float max,
bool negative) bool negative)
{ {
UASSERT(max > min); UASSERT_MSG(max > min, uFormat("cloud=%d, max=%f min=%f axis=%s", (int)cloud->size(), max, min, axis.c_str()).c_str());
UASSERT(axis.compare("x") == 0 || axis.compare("y") == 0 || axis.compare("z") == 0); UASSERT(axis.compare("x") == 0 || axis.compare("y") == 0 || axis.compare("z") == 0);
pcl::PointCloud<pcl::PointNormal>::Ptr output(new pcl::PointCloud<pcl::PointNormal>); pcl::PointCloud<pcl::PointNormal>::Ptr output(new pcl::PointCloud<pcl::PointNormal>);
+9 -2
View File
@@ -1,6 +1,13 @@
# Image: introlab3it/rtabmap:android-deps # Image: introlab3it/rtabmap:android-deps
FROM introlab3it/rtabmap FROM ubuntu:16.04
# Install build dependencies
RUN apt-get update && apt-get install -y \
git \
cmake \
g++ \
software-properties-common
ENV ANDROID_HOME=/opt/android-sdk ENV ANDROID_HOME=/opt/android-sdk
ENV ANDROID_NATIVE_API_LEVEL=android-19 ENV ANDROID_NATIVE_API_LEVEL=android-19
@@ -15,4 +22,4 @@ RUN /bin/bash -c "./setup_android_env.bash"
ADD install_deps.bash /root/install_deps.bash ADD install_deps.bash /root/install_deps.bash
RUN chmod +x install_deps.bash RUN chmod +x install_deps.bash
RUN /bin/bash -c "./install_deps.bash" RUN /bin/bash -c "./install_deps.bash /opt/android"
+33 -20
View File
@@ -1,5 +1,18 @@
#!/bin/bash #!/bin/bash
if [ $# -ne 1 ]; then
echo "install_deps.bash android_install_prefix # Example: install_deps.bash /opt/android"
exit 1
fi
prefix=$1
pwd=$(pwd)
wget -nv https://github.com/introlab/rtabmap/raw/master/cmake_modules/android.toolchain.cmake
# Install directory for all dependencies
mkdir -p $prefix/armeabi-v7a
mkdir -p $prefix/arm64-v8a
# Boost # Boost
echo "wget boost..." echo "wget boost..."
wget -nv https://downloads.sourceforge.net/project/boost/boost/1.59.0/boost_1_59_0.tar.gz wget -nv https://downloads.sourceforge.net/project/boost/boost/1.59.0/boost_1_59_0.tar.gz
@@ -9,11 +22,11 @@ wget -nv https://gist.github.com/matlabbe/0bce8feeb73a499a76afbbcc5c687221/raw/4
wget -nv https://gist.github.com/matlabbe/0bce8feeb73a499a76afbbcc5c687221/raw/e7fbf0e301cfea417a7aa69989a761a4de08b8c3/CMakeLists.txt wget -nv https://gist.github.com/matlabbe/0bce8feeb73a499a76afbbcc5c687221/raw/e7fbf0e301cfea417a7aa69989a761a4de08b8c3/CMakeLists.txt
mkdir build mkdir build
cd build cd build
cmake -DCMAKE_TOOLCHAIN_FILE=/root/android.toolchain.cmake -DANDROID_ABI=armeabi-v7a -DBUILD_SHARED_LIBS=OFF -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/opt/android/armeabi-v7a .. cmake -DCMAKE_TOOLCHAIN_FILE=$pwd/android.toolchain.cmake -DANDROID_ABI=armeabi-v7a -DBUILD_SHARED_LIBS=OFF -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=$prefix/armeabi-v7a ..
make make
make install make install
rm -r * rm -r *
cmake -DCMAKE_TOOLCHAIN_FILE=/root/android.toolchain.cmake -DANDROID_ABI=arm64-v8a -DBUILD_SHARED_LIBS=OFF -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/opt/android/arm64-v8a .. cmake -DCMAKE_TOOLCHAIN_FILE=$pwd/android.toolchain.cmake -DANDROID_ABI=arm64-v8a -DBUILD_SHARED_LIBS=OFF -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=$prefix/arm64-v8a ..
make make
make install make install
cd cd
@@ -26,11 +39,11 @@ tar -xzf 3.2.7.tar.gz
cd eigen-eigen-b30b87236a1b cd eigen-eigen-b30b87236a1b
mkdir build mkdir build
cd build cd build
cmake -DCMAKE_TOOLCHAIN_FILE=/root/android.toolchain.cmake -DANDROID_ABI=armeabi-v7a -DBUILD_SHARED_LIBS=OFF -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/opt/android/armeabi-v7a .. cmake -DCMAKE_TOOLCHAIN_FILE=$pwd/android.toolchain.cmake -DANDROID_ABI=armeabi-v7a -DBUILD_SHARED_LIBS=OFF -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=$prefix/armeabi-v7a ..
make make
make install make install
rm -r * rm -r *
cmake -DCMAKE_TOOLCHAIN_FILE=/root/android.toolchain.cmake -DANDROID_ABI=arm64-v8a -DBUILD_SHARED_LIBS=OFF -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/opt/android/arm64-v8a .. cmake -DCMAKE_TOOLCHAIN_FILE=$pwd/android.toolchain.cmake -DANDROID_ABI=arm64-v8a -DBUILD_SHARED_LIBS=OFF -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=$prefix/arm64-v8a ..
make make
make install make install
cd cd
@@ -43,11 +56,11 @@ unzip -qq flann-1.8.4-src.zip
cd flann-1.8.4-src cd flann-1.8.4-src
mkdir build mkdir build
cd build cd build
cmake -DCMAKE_TOOLCHAIN_FILE=/root/android.toolchain.cmake -DANDROID_ABI=armeabi-v7a -DBUILD_SHARED_LIBS=OFF -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/opt/android/armeabi-v7a .. cmake -DCMAKE_TOOLCHAIN_FILE=$pwd/android.toolchain.cmake -DANDROID_ABI=armeabi-v7a -DBUILD_SHARED_LIBS=OFF -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=$prefix/armeabi-v7a ..
make make
make install make install
rm -r * rm -r *
cmake -DCMAKE_TOOLCHAIN_FILE=/root/android.toolchain.cmake -DANDROID_ABI=arm64-v8a -DBUILD_SHARED_LIBS=OFF -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/opt/android/arm64-v8a .. cmake -DCMAKE_TOOLCHAIN_FILE=$pwd/android.toolchain.cmake -DANDROID_ABI=arm64-v8a -DBUILD_SHARED_LIBS=OFF -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=$prefix/arm64-v8a ..
make make
make install make install
cd cd
@@ -62,11 +75,11 @@ wget -nv https://gist.github.com/matlabbe/726b490c658afd3293f4b3f2f501b863/raw/d
git apply gtsam_GKlib_android_fix.patch git apply gtsam_GKlib_android_fix.patch
mkdir build mkdir build
cd build cd build
cmake -DCMAKE_TOOLCHAIN_FILE=/root/android.toolchain.cmake -DANDROID_ABI=armeabi-v7a -DMETIS_SHARED=OFF -DGTSAM_BUILD_STATIC_LIBRARY=ON -DGTSAM_BUILD_TESTS=OFF -DGTSAM_BUILD_EXAMPLES_ALWAYS=OFF -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/opt/android/armeabi-v7a .. cmake -DCMAKE_TOOLCHAIN_FILE=$pwd/android.toolchain.cmake -DANDROID_ABI=armeabi-v7a -DMETIS_SHARED=OFF -DGTSAM_BUILD_STATIC_LIBRARY=ON -DGTSAM_BUILD_TESTS=OFF -DGTSAM_BUILD_EXAMPLES_ALWAYS=OFF -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=$prefix/armeabi-v7a ..
make make
make install make install
rm -r * rm -r *
cmake -DCMAKE_TOOLCHAIN_FILE=/root/android.toolchain.cmake -DANDROID_ABI=arm64-v8a -DMETIS_SHARED=OFF -DGTSAM_BUILD_STATIC_LIBRARY=ON -DGTSAM_BUILD_TESTS=OFF -DGTSAM_BUILD_EXAMPLES_ALWAYS=OFF -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/opt/android/arm64-v8a .. cmake -DCMAKE_TOOLCHAIN_FILE=$pwd/android.toolchain.cmake -DANDROID_ABI=arm64-v8a -DMETIS_SHARED=OFF -DGTSAM_BUILD_STATIC_LIBRARY=ON -DGTSAM_BUILD_TESTS=OFF -DGTSAM_BUILD_EXAMPLES_ALWAYS=OFF -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=$prefix/arm64-v8a ..
make make
make install make install
cd cd
@@ -77,11 +90,11 @@ git clone https://github.com/RainerKuemmerle/g2o.git
cd g2o cd g2o
mkdir build mkdir build
cd build cd build
cmake -DCMAKE_TOOLCHAIN_FILE=/root/android.toolchain.cmake -DANDROID_ABI=armeabi-v7a -DBUILD_LGPL_SHARED_LIBS=OFF -DG2O_BUILD_APPS=OFF -DG2O_BUILD_EXAMPLES=OFF -DBUILD_SHARED_LIBS=OFF -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/opt/android/armeabi-v7a .. cmake -DCMAKE_TOOLCHAIN_FILE=$pwd/android.toolchain.cmake -DANDROID_ABI=armeabi-v7a -DBUILD_LGPL_SHARED_LIBS=OFF -DG2O_BUILD_APPS=OFF -DG2O_BUILD_EXAMPLES=OFF -DBUILD_SHARED_LIBS=OFF -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=$prefix/armeabi-v7a ..
make make
make install make install
rm -r * rm -r *
cmake -DCMAKE_TOOLCHAIN_FILE=/root/android.toolchain.cmake -DANDROID_ABI=arm64-v8a -DBUILD_LGPL_SHARED_LIBS=OFF -DG2O_BUILD_APPS=OFF -DG2O_BUILD_EXAMPLES=OFF -DBUILD_SHARED_LIBS=OFF -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/opt/android/arm64-v8a .. cmake -DCMAKE_TOOLCHAIN_FILE=$pwd/android.toolchain.cmake -DANDROID_ABI=arm64-v8a -DBUILD_LGPL_SHARED_LIBS=OFF -DG2O_BUILD_APPS=OFF -DG2O_BUILD_EXAMPLES=OFF -DBUILD_SHARED_LIBS=OFF -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=$prefix/arm64-v8a ..
make make
make install make install
cd cd
@@ -100,13 +113,13 @@ cd VTK
git checkout tags/v7.1.1 git checkout tags/v7.1.1
mkdir build mkdir build
cd build cd build
~/cmake-3.7.2-Linux-x86_64/bin/cmake -DBUILD_EXAMPLES=OFF -DBUILD_TESTING=OFF -DVTK_ANDROID_BUILD=ON -DANDROID_ARCH_ABI=armeabi-v7a -DBUILD_SHARED_LIBS=OFF -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/opt/android/armeabi-v7a .. ~/cmake-3.7.2-Linux-x86_64/bin/cmake -DBUILD_EXAMPLES=OFF -DBUILD_TESTING=OFF -DVTK_ANDROID_BUILD=ON -DANDROID_ARCH_ABI=armeabi-v7a -DBUILD_SHARED_LIBS=OFF -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=$prefix/armeabi-v7a ..
make make
cp -r CMakeExternals/Install/vtk-android/* /opt/android/armeabi-v7a/. cp -r CMakeExternals/Install/vtk-android/* $prefix/armeabi-v7a/.
rm -r * rm -r *
~/cmake-3.7.2-Linux-x86_64/bin/cmake -DBUILD_EXAMPLES=OFF -DBUILD_TESTING=OFF -DVTK_ANDROID_BUILD=ON -DANDROID_ARCH_ABI=arm64-v8a -DBUILD_SHARED_LIBS=OFF -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/opt/android/arm64-v8a .. ~/cmake-3.7.2-Linux-x86_64/bin/cmake -DBUILD_EXAMPLES=OFF -DBUILD_TESTING=OFF -DVTK_ANDROID_BUILD=ON -DANDROID_ARCH_ABI=arm64-v8a -DBUILD_SHARED_LIBS=OFF -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=$prefix/arm64-v8a ..
make make
cp -r CMakeExternals/Install/vtk-android/* /opt/android/arm64-v8a/. cp -r CMakeExternals/Install/vtk-android/* $prefix/arm64-v8a/.
cd cd
rm -r VTK cmake-3.7.2-Linux-x86_64 rm -r VTK cmake-3.7.2-Linux-x86_64
@@ -120,14 +133,14 @@ git apply pcl_1_8_0_vtk_android_support.patch
mkdir build mkdir build
cd build cd build
# do it 2 times because there is a cmake error on the first time and not the second time!? # do it 2 times because there is a cmake error on the first time and not the second time!?
cmake -DCMAKE_TOOLCHAIN_FILE=/root/android.toolchain.cmake -DANDROID_ABI=armeabi-v7a -DBUILD_apps=OFF -DBUILD_examples=OFF -DBUILD_tools=OFF -DBUILD_visualization=OFF -DBUILD_tracking=OFF -DBUILD_people=OFF -DBUILD_global_tests=OFF -DWITH_QT=OFF -DWITH_OPENGL=OFF -DWITH_VTK=ON -DPCL_SHARED_LIBS=OFF -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/opt/android/armeabi-v7a .. cmake -DCMAKE_TOOLCHAIN_FILE=$pwd/android.toolchain.cmake -DANDROID_ABI=armeabi-v7a -DBUILD_apps=OFF -DBUILD_examples=OFF -DBUILD_tools=OFF -DBUILD_visualization=OFF -DBUILD_tracking=OFF -DBUILD_people=OFF -DBUILD_global_tests=OFF -DWITH_QT=OFF -DWITH_OPENGL=OFF -DWITH_VTK=ON -DPCL_SHARED_LIBS=OFF -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=$prefix/armeabi-v7a ..
cmake -DCMAKE_TOOLCHAIN_FILE=/root/android.toolchain.cmake -DANDROID_ABI=armeabi-v7a -DBUILD_apps=OFF -DBUILD_examples=OFF -DBUILD_tools=OFF -DBUILD_visualization=OFF -DBUILD_tracking=OFF -DBUILD_people=OFF -DBUILD_global_tests=OFF -DWITH_QT=OFF -DWITH_OPENGL=OFF -DWITH_VTK=ON -DPCL_SHARED_LIBS=OFF -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/opt/android/armeabi-v7a .. cmake -DCMAKE_TOOLCHAIN_FILE=$pwd/android.toolchain.cmake -DANDROID_ABI=armeabi-v7a -DBUILD_apps=OFF -DBUILD_examples=OFF -DBUILD_tools=OFF -DBUILD_visualization=OFF -DBUILD_tracking=OFF -DBUILD_people=OFF -DBUILD_global_tests=OFF -DWITH_QT=OFF -DWITH_OPENGL=OFF -DWITH_VTK=ON -DPCL_SHARED_LIBS=OFF -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=$prefix/armeabi-v7a ..
make make
make install make install
rm -r * rm -r *
# do it 2 times because there is a cmake error on the first time and not the second time!? # do it 2 times because there is a cmake error on the first time and not the second time!?
cmake -DCMAKE_TOOLCHAIN_FILE=/root/android.toolchain.cmake -DANDROID_ABI=arm64-v8a -DBUILD_apps=OFF -DBUILD_examples=OFF -DBUILD_tools=OFF -DBUILD_visualization=OFF -DBUILD_tracking=OFF -DBUILD_people=OFF -DBUILD_global_tests=OFF -DWITH_QT=OFF -DWITH_OPENGL=OFF -DWITH_VTK=ON -DPCL_SHARED_LIBS=OFF -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/opt/android/arm64-v8a .. cmake -DCMAKE_TOOLCHAIN_FILE=$pwd/android.toolchain.cmake -DANDROID_ABI=arm64-v8a -DBUILD_apps=OFF -DBUILD_examples=OFF -DBUILD_tools=OFF -DBUILD_visualization=OFF -DBUILD_tracking=OFF -DBUILD_people=OFF -DBUILD_global_tests=OFF -DWITH_QT=OFF -DWITH_OPENGL=OFF -DWITH_VTK=ON -DPCL_SHARED_LIBS=OFF -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=$prefix/arm64-v8a ..
cmake -DCMAKE_TOOLCHAIN_FILE=/root/android.toolchain.cmake -DANDROID_ABI=arm64-v8a -DBUILD_apps=OFF -DBUILD_examples=OFF -DBUILD_tools=OFF -DBUILD_visualization=OFF -DBUILD_tracking=OFF -DBUILD_people=OFF -DBUILD_global_tests=OFF -DWITH_QT=OFF -DWITH_OPENGL=OFF -DWITH_VTK=ON -DPCL_SHARED_LIBS=OFF -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/opt/android/arm64-v8a .. cmake -DCMAKE_TOOLCHAIN_FILE=$pwd/android.toolchain.cmake -DANDROID_ABI=arm64-v8a -DBUILD_apps=OFF -DBUILD_examples=OFF -DBUILD_tools=OFF -DBUILD_visualization=OFF -DBUILD_tracking=OFF -DBUILD_people=OFF -DBUILD_global_tests=OFF -DWITH_QT=OFF -DWITH_OPENGL=OFF -DWITH_VTK=ON -DPCL_SHARED_LIBS=OFF -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=$prefix/arm64-v8a ..
make make
make install make install
cd cd
@@ -143,11 +156,11 @@ cd opencv
git checkout tags/3.2.0 git checkout tags/3.2.0
mkdir build mkdir build
cd build cd build
cmake -DCMAKE_TOOLCHAIN_FILE=/root/android.toolchain.cmake -DANDROID_ABI=armeabi-v7a -DOPENCV_EXTRA_MODULES_PATH=/root/opencv_contrib/modules -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF -DBUILD_TESTS=OFF -DBUILD_PERF_TESTS=OFF -DCMAKE_INSTALL_PREFIX=/opt/android/armeabi-v7a .. cmake -DCMAKE_TOOLCHAIN_FILE=$pwd/android.toolchain.cmake -DANDROID_ABI=armeabi-v7a -DOPENCV_EXTRA_MODULES_PATH=$pwd/opencv_contrib/modules -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF -DBUILD_TESTS=OFF -DBUILD_PERF_TESTS=OFF -DCMAKE_INSTALL_PREFIX=$prefix/armeabi-v7a ..
make make
make install make install
rm -r * rm -r *
cmake -DCMAKE_TOOLCHAIN_FILE=/root/android.toolchain.cmake -DANDROID_ABI=arm64-v8a -DOPENCV_EXTRA_MODULES_PATH=/root/opencv_contrib/modules -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF -DBUILD_TESTS=OFF -DBUILD_PERF_TESTS=OFF -DCMAKE_INSTALL_PREFIX=/opt/android/arm64-v8a .. cmake -DCMAKE_TOOLCHAIN_FILE=$pwd/android.toolchain.cmake -DANDROID_ABI=arm64-v8a -DOPENCV_EXTRA_MODULES_PATH=$pwd/opencv_contrib/modules -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF -DBUILD_TESTS=OFF -DBUILD_PERF_TESTS=OFF -DCMAKE_INSTALL_PREFIX=$prefix/arm64-v8a ..
make make
make install make install
cd cd
+1 -6
View File
@@ -22,9 +22,4 @@ echo "wget android-ndk..."
wget -nv https://dl.google.com/android/repository/android-ndk-r14-linux-x86_64.zip wget -nv https://dl.google.com/android/repository/android-ndk-r14-linux-x86_64.zip
unzip -qq android-ndk-r14-linux-x86_64.zip unzip -qq android-ndk-r14-linux-x86_64.zip
rm android-ndk-r14-linux-x86_64.zip rm android-ndk-r14-linux-x86_64.zip
mv android-ndk-r14 /opt/. mv android-ndk-r14 $ANDROID_NDK
# Install directory for all dependencies
mkdir -p /opt/android/armeabi-v7a
mkdir -p /opt/android/arm64-v8a
wget -nv https://github.com/introlab/rtabmap/raw/master/cmake_modules/android.toolchain.cmake
+1 -1
View File
@@ -6,6 +6,6 @@ WORKDIR /root/
ADD build.bash /root/build.bash ADD build.bash /root/build.bash
RUN chmod +x build.bash RUN chmod +x build.bash
RUN /bin/bash -c "./build.bash" RUN /bin/bash -c "./build.bash /opt/android"
WORKDIR /root/ WORKDIR /root/
+23 -10
View File
@@ -1,5 +1,12 @@
#!/bin/bash #!/bin/bash
if [ $# -ne 1 ]; then
echo "build.bash android_install_prefix # Example: build.bash /opt/android"
exit 1
fi
prefix=$1
# get rtabmap # get rtabmap
git clone https://github.com/introlab/rtabmap.git rtabmap-tango git clone https://github.com/introlab/rtabmap.git rtabmap-tango
@@ -7,33 +14,39 @@ git clone https://github.com/introlab/rtabmap.git rtabmap-tango
wget https://developers.google.com/tango/downloads/TangoSDK_Ikariotikos_C.zip wget https://developers.google.com/tango/downloads/TangoSDK_Ikariotikos_C.zip
unzip -qq TangoSDK_Ikariotikos_C.zip unzip -qq TangoSDK_Ikariotikos_C.zip
rm TangoSDK_Ikariotikos_C.zip rm TangoSDK_Ikariotikos_C.zip
cp -r lib_tango_client_api/include/* /opt/android/armeabi-v7a/include/. cp -r lib_tango_client_api/include/* $prefix/armeabi-v7a/include/.
cp -r lib_tango_client_api/include/* /opt/android/arm64-v8a/include/. cp -r lib_tango_client_api/include/* $prefix/arm64-v8a/include/.
cp -r lib_tango_client_api/lib/armeabi-v7a/* /opt/android/armeabi-v7a/lib/. cp -r lib_tango_client_api/lib/armeabi-v7a/* $prefix/armeabi-v7a/lib/.
cp -r lib_tango_client_api/lib/arm64-v8a/* /opt/android/arm64-v8a/lib/. cp -r lib_tango_client_api/lib/arm64-v8a/* $prefix/arm64-v8a/lib/.
rm -r lib_tango_client_api rm -r lib_tango_client_api
wget https://developers.google.com/tango/downloads/TangoSupport_Ikariotikos_C.zip wget https://developers.google.com/tango/downloads/TangoSupport_Ikariotikos_C.zip
unzip -qq TangoSupport_Ikariotikos_C.zip unzip -qq TangoSupport_Ikariotikos_C.zip
rm TangoSupport_Ikariotikos_C.zip rm TangoSupport_Ikariotikos_C.zip
cp -r lib_tango_support_api/include/* /opt/android/armeabi-v7a/include/. cp -r lib_tango_support_api/include/* $prefix/armeabi-v7a/include/.
cp -r lib_tango_support_api/include/* /opt/android/arm64-v8a/include/. cp -r lib_tango_support_api/include/* $prefix/arm64-v8a/include/.
cp -r lib_tango_support_api/lib/armeabi-v7a/* /opt/android/armeabi-v7a/lib/. cp -r lib_tango_support_api/lib/armeabi-v7a/* $prefix/armeabi-v7a/lib/.
cp -r lib_tango_support_api/lib/arm64-v8a/* /opt/android/arm64-v8a/lib/. cp -r lib_tango_support_api/lib/arm64-v8a/* $prefix/arm64-v8a/lib/.
cp -r lib_tango_support_api/lib/* rtabmap-tango/app/android/jni/third-party/lib/. cp -r lib_tango_support_api/lib/* rtabmap-tango/app/android/jni/third-party/lib/.
rm -r lib_tango_support_api rm -r lib_tango_support_api
wget https://developers.google.com/tango/downloads/TangoSDK_Ikariotikos_Java.jar wget https://developers.google.com/tango/downloads/TangoSDK_Ikariotikos_Java.jar
mv TangoSDK_Ikariotikos_Java.jar rtabmap-tango/app/android/libs/. mv TangoSDK_Ikariotikos_Java.jar rtabmap-tango/app/android/libs/.
# resource tool
cd rtabmap-tango/build
cmake -DANDROID_PREBUILD=ON ..
make
cd
# rtabmap # rtabmap
mkdir rtabmap-tango/build/armeabi-v7a mkdir rtabmap-tango/build/armeabi-v7a
cd rtabmap-tango/build/armeabi-v7a cd rtabmap-tango/build/armeabi-v7a
cmake -DCMAKE_TOOLCHAIN_FILE=../../cmake_modules/android.toolchain.cmake -DANDROID_ABI=armeabi-v7a -DBUILD_SHARED_LIBS=OFF -DBUILD_EXAMPLES=OFF -DBUILD_TOOLS=OFF -DCMAKE_BUILD_TYPE=Release -DOpenCV_DIR=/opt/android/armeabi-v7a/sdk/native/jni -DCMAKE_INSTALL_PREFIX=/opt/android/armeabi-v7a ../.. cmake -DCMAKE_TOOLCHAIN_FILE=../../cmake_modules/android.toolchain.cmake -DANDROID_ABI=armeabi-v7a -DBUILD_SHARED_LIBS=OFF -DBUILD_EXAMPLES=OFF -DBUILD_TOOLS=OFF -DCMAKE_BUILD_TYPE=Release -DOpenCV_DIR=$prefix/armeabi-v7a/sdk/native/jni -DCMAKE_INSTALL_PREFIX=$prefix/armeabi-v7a ../..
make make
cd cd
mkdir rtabmap-tango/build/arm64-v8a mkdir rtabmap-tango/build/arm64-v8a
cd rtabmap-tango/build/arm64-v8a cd rtabmap-tango/build/arm64-v8a
cmake -DCMAKE_TOOLCHAIN_FILE=../../cmake_modules/android.toolchain.cmake -DANDROID_ABI=arm64-v8a -DBUILD_SHARED_LIBS=OFF -DBUILD_EXAMPLES=OFF -DBUILD_TOOLS=OFF -DCMAKE_BUILD_TYPE=Release -DOpenCV_DIR=/opt/android/arm64-v8a/sdk/native/jni -DCMAKE_INSTALL_PREFIX=/opt/android/arm64-v8a ../.. cmake -DCMAKE_TOOLCHAIN_FILE=../../cmake_modules/android.toolchain.cmake -DANDROID_ABI=arm64-v8a -DBUILD_SHARED_LIBS=OFF -DBUILD_EXAMPLES=OFF -DBUILD_TOOLS=OFF -DCMAKE_BUILD_TYPE=Release -DOpenCV_DIR=$prefix/arm64-v8a/sdk/native/jni -DCMAKE_INSTALL_PREFIX=$prefix/arm64-v8a ../..
make make
# package with binaries of both architectures # package with binaries of both architectures
+33
View File
@@ -0,0 +1,33 @@
# Image: introlab3it/rtabmap:zesty
FROM ubuntu:17.04
# Install build dependencies
RUN apt-get update && apt-get install -y \
libsqlite3-dev \
libpcl-dev \
libopencv-dev \
git \
cmake \
libproj-dev \
libqt5svg5-dev \
software-properties-common
# Issue: http://www.pcl-users.org/Build-failure-on-Ubuntu-17-04-td4044552.html
RUN sed -i 's|/usr/lib/libmpi.so;||g' /usr/lib/x86_64-linux-gnu/cmake/pcl/PCLConfig.cmake
# Clone source code
WORKDIR /root/
RUN git clone https://github.com/introlab/rtabmap.git
# Build RTAB-Map project
RUN cd rtabmap/build && \
cmake .. && \
make -j$(nproc) && \
make install && \
cd ../.. && \
rm -rf rtabmap && \
ldconfig
WORKDIR /root
+6
View File
@@ -29,6 +29,12 @@ else()
IF(NOT Qt5_FOUND) IF(NOT Qt5_FOUND)
FIND_PACKAGE(Qt4 COMPONENTS QtCore QtGui QtSvg) FIND_PACKAGE(Qt4 COMPONENTS QtCore QtGui QtSvg)
ENDIF(NOT Qt5_FOUND) ENDIF(NOT Qt5_FOUND)
# fix libproj.so not found on Xenial
if(NOT "${PCL_LIBRARIES}" STREQUAL "")
list(REMOVE_ITEM PCL_LIBRARIES "vtkproj4")
endif()
endif() endif()
if(POLICY CMP0020) if(POLICY CMP0020)
+9 -2
View File
@@ -38,6 +38,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <stdio.h> #include <stdio.h>
#include <pcl/io/pcd_io.h> #include <pcl/io/pcd_io.h>
#include <pcl/io/ply_io.h> #include <pcl/io/ply_io.h>
#include <pcl/filters/filter.h>
#include "MapBuilder.h" #include "MapBuilder.h"
@@ -216,8 +217,14 @@ int main(int argc, char * argv[])
node.sensorData(), node.sensorData(),
4, // image decimation before creating the clouds 4, // image decimation before creating the clouds
4.0f, // maximum depth of the cloud 4.0f, // maximum depth of the cloud
0.01f); // Voxel grid filtering 0.0f);
*cloud += *util3d::transformPointCloud(tmp, iter->second); // transform the point cloud to its pose pcl::PointCloud<pcl::PointXYZRGB>::Ptr tmpNoNaN(new pcl::PointCloud<pcl::PointXYZRGB>);
std::vector<int> index;
pcl::removeNaNFromPointCloud(*tmp, *tmpNoNaN, index);
if(!tmpNoNaN->empty())
{
*cloud += *util3d::transformPointCloud(tmpNoNaN, iter->second); // transform the point cloud to its pose
}
} }
if(cloud->size()) if(cloud->size())
{ {
+1
View File
@@ -135,6 +135,7 @@ public:
signals: signals:
void configChanged(); void configChanged();
void mapShownRequested();
public slots: public slots:
void restoreDefaults(); void restoreDefaults();
+5 -1
View File
@@ -161,7 +161,11 @@ ADD_LIBRARY(rtabmap_gui ${SRC_FILES})
TARGET_LINK_LIBRARIES(rtabmap_gui rtabmap_core rtabmap_utilite ${LIBRARIES}) TARGET_LINK_LIBRARIES(rtabmap_gui rtabmap_core rtabmap_utilite ${LIBRARIES})
IF(Qt5_FOUND) IF(Qt5_FOUND)
QT5_USE_MODULES(rtabmap_gui Widgets Core Gui Svg PrintSupport) IF(Qt5Svg_FOUND)
QT5_USE_MODULES(rtabmap_gui Widgets Core Gui Svg PrintSupport)
ELSE()
QT5_USE_MODULES(rtabmap_gui Widgets Core Gui PrintSupport)
ENDIF()
ENDIF(Qt5_FOUND) ENDIF(Qt5_FOUND)
SET_TARGET_PROPERTIES( SET_TARGET_PROPERTIES(
+65 -46
View File
@@ -296,6 +296,7 @@ DatabaseViewer::DatabaseViewer(const QString & ini, QWidget * parent) :
connect(ui_->horizontalSlider_iterations, SIGNAL(sliderMoved(int)), this, SLOT(sliderIterationsValueChanged(int))); connect(ui_->horizontalSlider_iterations, SIGNAL(sliderMoved(int)), this, SLOT(sliderIterationsValueChanged(int)));
connect(ui_->spinBox_optimizationsFrom, SIGNAL(editingFinished()), this, SLOT(updateGraphView())); connect(ui_->spinBox_optimizationsFrom, SIGNAL(editingFinished()), this, SLOT(updateGraphView()));
connect(ui_->checkBox_spanAllMaps, SIGNAL(stateChanged(int)), this, SLOT(updateGraphView())); connect(ui_->checkBox_spanAllMaps, SIGNAL(stateChanged(int)), this, SLOT(updateGraphView()));
connect(ui_->graphViewer, SIGNAL(mapShownRequested()), this, SLOT(updateGraphView()));
connect(ui_->checkBox_ignorePoseCorrection, SIGNAL(stateChanged(int)), this, SLOT(updateGraphView())); connect(ui_->checkBox_ignorePoseCorrection, SIGNAL(stateChanged(int)), this, SLOT(updateGraphView()));
connect(ui_->checkBox_ignorePoseCorrection, SIGNAL(stateChanged(int)), this, SLOT(updateConstraintView())); connect(ui_->checkBox_ignorePoseCorrection, SIGNAL(stateChanged(int)), this, SLOT(updateConstraintView()));
connect(ui_->checkBox_ignoreGlobalLoop, SIGNAL(stateChanged(int)), this, SLOT(updateGraphView())); connect(ui_->checkBox_ignoreGlobalLoop, SIGNAL(stateChanged(int)), this, SLOT(updateGraphView()));
@@ -2559,6 +2560,7 @@ void DatabaseViewer::update(int value,
if(!data.imageRaw().empty()) if(!data.imageRaw().empty())
{ {
pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud; pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud;
pcl::IndicesPtr indices(new std::vector<int>);
if(!data.depthRaw().empty() && data.cameraModels().size()==1) if(!data.depthRaw().empty() && data.cameraModels().size()==1)
{ {
cv::Mat depth = data.depthRaw(); cv::Mat depth = data.depthRaw();
@@ -2569,8 +2571,9 @@ void DatabaseViewer::update(int value,
cloud = util3d::cloudFromDepthRGB( cloud = util3d::cloudFromDepthRGB(
data.imageRaw(), data.imageRaw(),
depth, depth,
data.cameraModels()[0]); data.cameraModels()[0],
if(cloud->size()) 1,0,0,indices.get());
if(indices->size())
{ {
cloud = util3d::transformPointCloud(cloud, data.cameraModels()[0].localTransform()); cloud = util3d::transformPointCloud(cloud, data.cameraModels()[0].localTransform());
} }
@@ -2578,13 +2581,13 @@ void DatabaseViewer::update(int value,
} }
else else
{ {
cloud = util3d::cloudRGBFromSensorData(data, 1, 0, 0, 0, ui_->parameters_toolbox->getParameters()); cloud = util3d::cloudRGBFromSensorData(data, 1, 0, 0, indices.get(), ui_->parameters_toolbox->getParameters());
} }
if(cloud->size()) if(indices->size())
{ {
if(ui_->doubleSpinBox_voxelSize->value() > 0.0) if(ui_->doubleSpinBox_voxelSize->value() > 0.0)
{ {
cloud = util3d::voxelize(cloud, ui_->doubleSpinBox_voxelSize->value()); cloud = util3d::voxelize(cloud, indices, ui_->doubleSpinBox_voxelSize->value());
} }
if(ui_->checkBox_showMesh->isChecked() && !cloud->is_dense) if(ui_->checkBox_showMesh->isChecked() && !cloud->is_dense)
@@ -2645,12 +2648,13 @@ void DatabaseViewer::update(int value,
else if(ui_->checkBox_showCloud->isChecked()) else if(ui_->checkBox_showCloud->isChecked())
{ {
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud; pcl::PointCloud<pcl::PointXYZ>::Ptr cloud;
cloud = util3d::cloudFromSensorData(data, 1, 0, 0, 0, ui_->parameters_toolbox->getParameters()); pcl::IndicesPtr indices(new std::vector<int>);
if(cloud->size()) cloud = util3d::cloudFromSensorData(data, 1, 0, 0, indices.get(), ui_->parameters_toolbox->getParameters());
if(indices->size())
{ {
if(ui_->doubleSpinBox_voxelSize->value() > 0.0) if(ui_->doubleSpinBox_voxelSize->value() > 0.0)
{ {
cloud = util3d::voxelize(cloud, ui_->doubleSpinBox_voxelSize->value()); cloud = util3d::voxelize(cloud, indices, ui_->doubleSpinBox_voxelSize->value());
} }
cloudViewer_->addCloud("cloud", cloud, pose); cloudViewer_->addCloud("cloud", cloud, pose);
@@ -3498,15 +3502,15 @@ void DatabaseViewer::updateConstraintView(
cloudTo=util3d::cloudRGBFromSensorData(dataTo, 1, 0, 0, indicesTo.get(), ui_->parameters_toolbox->getParameters()); cloudTo=util3d::cloudRGBFromSensorData(dataTo, 1, 0, 0, indicesTo.get(), ui_->parameters_toolbox->getParameters());
} }
if(cloudTo.get() && cloudTo->size()) if(cloudTo.get() && indicesTo->size())
{ {
cloudTo = rtabmap::util3d::transformPointCloud(cloudTo, t); cloudTo = rtabmap::util3d::transformPointCloud(cloudTo, t);
} }
// Gain compensation // Gain compensation
if(ui_->doubleSpinBox_gainCompensationRadius->value()>0.0 && if(ui_->doubleSpinBox_gainCompensationRadius->value()>0.0 &&
cloudFrom.get() && cloudFrom->size() && cloudFrom.get() && indicesFrom->size() &&
cloudTo.get() && cloudTo->size()) cloudTo.get() && indicesTo->size())
{ {
UTimer t; UTimer t;
GainCompensator compensator(ui_->doubleSpinBox_gainCompensationRadius->value()); GainCompensator compensator(ui_->doubleSpinBox_gainCompensationRadius->value());
@@ -3516,19 +3520,19 @@ void DatabaseViewer::updateConstraintView(
UINFO("Gain compensation time = %fs", t.ticks()); UINFO("Gain compensation time = %fs", t.ticks());
} }
if(cloudFrom.get() && cloudFrom->size()) if(cloudFrom.get() && indicesFrom->size())
{ {
if(ui_->doubleSpinBox_voxelSize->value() > 0.0) if(ui_->doubleSpinBox_voxelSize->value() > 0.0)
{ {
cloudFrom = util3d::voxelize(cloudFrom, ui_->doubleSpinBox_voxelSize->value()); cloudFrom = util3d::voxelize(cloudFrom, indicesFrom, ui_->doubleSpinBox_voxelSize->value());
} }
constraintsViewer_->addCloud("cloud0", cloudFrom, pose, Qt::red); constraintsViewer_->addCloud("cloud0", cloudFrom, pose, Qt::red);
} }
if(cloudTo.get() && cloudTo->size()) if(cloudTo.get() && indicesTo->size())
{ {
if(ui_->doubleSpinBox_voxelSize->value() > 0.0) if(ui_->doubleSpinBox_voxelSize->value() > 0.0)
{ {
cloudTo = util3d::voxelize(cloudTo, ui_->doubleSpinBox_voxelSize->value()); cloudTo = util3d::voxelize(cloudTo, indicesTo, ui_->doubleSpinBox_voxelSize->value());
} }
constraintsViewer_->addCloud("cloud1", cloudTo, pose, Qt::cyan); constraintsViewer_->addCloud("cloud1", cloudTo, pose, Qt::cyan);
} }
@@ -3751,45 +3755,51 @@ void DatabaseViewer::updateConstraintView(
// Added loop closure scans // Added loop closure scans
constraintsViewer_->removeCloud("scan0"); constraintsViewer_->removeCloud("scan0");
constraintsViewer_->removeCloud("scan1"); constraintsViewer_->removeCloud("scan1");
if(dataFrom.laserScanRaw().channels() == 6) if(!dataFrom.laserScanRaw().empty())
{ {
pcl::PointCloud<pcl::PointNormal>::Ptr scan; if(dataFrom.laserScanRaw().channels() == 6)
scan = rtabmap::util3d::laserScanToPointCloudNormal(dataFrom.laserScanRaw(), dataFrom.laserScanInfo().localTransform());
if(ui_->doubleSpinBox_voxelSize->value() > 0.0)
{ {
scan = util3d::voxelize(scan, ui_->doubleSpinBox_voxelSize->value()); pcl::PointCloud<pcl::PointNormal>::Ptr scan;
scan = rtabmap::util3d::laserScanToPointCloudNormal(dataFrom.laserScanRaw(), dataFrom.laserScanInfo().localTransform());
if(ui_->doubleSpinBox_voxelSize->value() > 0.0)
{
scan = util3d::voxelize(scan, ui_->doubleSpinBox_voxelSize->value());
}
constraintsViewer_->addCloud("scan0", scan, pose, Qt::yellow);
}
else
{
pcl::PointCloud<pcl::PointXYZ>::Ptr scan;
scan = rtabmap::util3d::laserScanToPointCloud(dataFrom.laserScanRaw(), dataFrom.laserScanInfo().localTransform());
if(ui_->doubleSpinBox_voxelSize->value() > 0.0)
{
scan = util3d::voxelize(scan, ui_->doubleSpinBox_voxelSize->value());
}
constraintsViewer_->addCloud("scan0", scan, pose, Qt::yellow);
} }
constraintsViewer_->addCloud("scan0", scan, pose, Qt::yellow);
} }
else if(!dataTo.laserScanRaw().empty())
{ {
pcl::PointCloud<pcl::PointXYZ>::Ptr scan; if(dataTo.laserScanRaw().channels() == 6)
scan = rtabmap::util3d::laserScanToPointCloud(dataFrom.laserScanRaw(), dataFrom.laserScanInfo().localTransform());
if(ui_->doubleSpinBox_voxelSize->value() > 0.0)
{ {
scan = util3d::voxelize(scan, ui_->doubleSpinBox_voxelSize->value()); pcl::PointCloud<pcl::PointNormal>::Ptr scan;
scan = rtabmap::util3d::laserScanToPointCloudNormal(dataTo.laserScanRaw(), t*dataTo.laserScanInfo().localTransform());
if(ui_->doubleSpinBox_voxelSize->value() > 0.0)
{
scan = util3d::voxelize(scan, ui_->doubleSpinBox_voxelSize->value());
}
constraintsViewer_->addCloud("scan1", scan, pose, Qt::magenta);
} }
constraintsViewer_->addCloud("scan0", scan, pose, Qt::yellow); else
}
if(dataTo.laserScanRaw().channels() == 6)
{
pcl::PointCloud<pcl::PointNormal>::Ptr scan;
scan = rtabmap::util3d::laserScanToPointCloudNormal(dataTo.laserScanRaw(), t*dataTo.laserScanInfo().localTransform());
if(ui_->doubleSpinBox_voxelSize->value() > 0.0)
{ {
scan = util3d::voxelize(scan, ui_->doubleSpinBox_voxelSize->value()); pcl::PointCloud<pcl::PointXYZ>::Ptr scan;
scan = rtabmap::util3d::laserScanToPointCloud(dataTo.laserScanRaw(), t*dataTo.laserScanInfo().localTransform());
if(ui_->doubleSpinBox_voxelSize->value() > 0.0)
{
scan = util3d::voxelize(scan, ui_->doubleSpinBox_voxelSize->value());
}
constraintsViewer_->addCloud("scan1", scan, pose, Qt::magenta);
} }
constraintsViewer_->addCloud("scan1", scan, pose, Qt::magenta);
}
else
{
pcl::PointCloud<pcl::PointXYZ>::Ptr scan;
scan = rtabmap::util3d::laserScanToPointCloud(dataTo.laserScanRaw(), t*dataTo.laserScanInfo().localTransform());
if(ui_->doubleSpinBox_voxelSize->value() > 0.0)
{
scan = util3d::voxelize(scan, ui_->doubleSpinBox_voxelSize->value());
}
constraintsViewer_->addCloud("scan1", scan, pose, Qt::magenta);
} }
} }
@@ -4090,7 +4100,7 @@ void DatabaseViewer::sliderIterationsValueChanged(int value)
++iter; ++iter;
} }
} }
UINFO("Update local maps list... done"); UINFO("Update local maps list... done (%d local maps, graph size=%d)", (int)localMaps.size(), (int)graph.size());
} }
ui_->graphViewer->updateGTGraph(groundTruthPoses_); ui_->graphViewer->updateGTGraph(groundTruthPoses_);
@@ -4835,6 +4845,15 @@ bool DatabaseViewer::addConstraint(int from, int to, bool silent)
toS->sensorData().setFeatures(std::vector<cv::KeyPoint>(), std::vector<cv::Point3f>(), cv::Mat()); toS->sensorData().setFeatures(std::vector<cv::KeyPoint>(), std::vector<cv::Point3f>(), cv::Mat());
} }
} }
else if(!reextractVisualFeatures && fromS->getWords().empty() && toS->getWords().empty())
{
UWARN("\"%s\" is false and signatures (%d and %d) don't have words, "
"registration will not be possible. Set \"%s\" to true.",
Parameters::kRGBDLoopClosureReextractFeatures().c_str(),
fromS->id(),
toS->id(),
Parameters::kRGBDLoopClosureReextractFeatures().c_str());
}
t = reg->computeTransformationMod(*fromS, *toS, Transform(), &info); t = reg->computeTransformationMod(*fromS, *toS, Transform(), &info);
delete reg; delete reg;
+112 -76
View File
@@ -227,25 +227,54 @@ void DepthCalibrationDialog::calibrate(
_ui->label_width->setText("NA"); _ui->label_width->setText("NA");
_ui->label_height->setText("NA"); _ui->label_height->setText("NA");
_imageSize = cv::Size(); _imageSize = cv::Size();
CameraModel model;
if(cachedSignatures.size()) if(cachedSignatures.size())
{ {
const Signature & s = cachedSignatures.begin().value(); const Signature & s = cachedSignatures.begin().value();
const SensorData & data = s.sensorData(); const SensorData & data = s.sensorData();
if(data.cameraModels().size() == 1 && data.cameraModels()[0].isValidForReprojection()) cv::Mat depth;
data.uncompressDataConst(0, &depth);
if(data.cameraModels().size() == 1 && data.cameraModels()[0].isValidForProjection() && !depth.empty())
{ {
_imageSize = data.cameraModels()[0].imageSize(); // use depth image size
_ui->label_width->setNum(data.cameraModels()[0].imageWidth()); _imageSize = depth.size();
_ui->label_height->setNum(data.cameraModels()[0].imageHeight()); _ui->label_width->setNum(_imageSize.width);
_ui->label_height->setNum(_imageSize.height);
if(data.cameraModels()[0].imageWidth() % _ui->spinBox_bin_width->value() != 0 || if(_imageSize.width % _ui->spinBox_bin_width->value() != 0 ||
data.cameraModels()[0].imageHeight() % _ui->spinBox_bin_height->value() != 0) _imageSize.height % _ui->spinBox_bin_height->value() != 0)
{ {
size_t bin_width, bin_height; size_t bin_width, bin_height;
clams::DiscreteDepthDistortionModel::getBinSize(data.cameraModels()[0].imageWidth(), data.cameraModels()[0].imageHeight(), bin_width, bin_height); clams::DiscreteDepthDistortionModel::getBinSize(_imageSize.width, _imageSize.height, bin_width, bin_height);
_ui->spinBox_bin_width->setValue(bin_width); _ui->spinBox_bin_width->setValue(bin_width);
_ui->spinBox_bin_height->setValue(bin_height); _ui->spinBox_bin_height->setValue(bin_height);
} }
} }
else if(data.cameraModels().size() > 1)
{
QMessageBox::warning(this, tr("Depth Calibration"),tr("Multi-camera not supported!"));
return;
}
else if(data.cameraModels().size() != 1)
{
QMessageBox::warning(this, tr("Depth Calibration"), tr("Camera model not found."));
return;
}
else if(data.cameraModels().size() == 1 && !data.cameraModels()[0].isValidForProjection())
{
QMessageBox::warning(this, tr("Depth Calibration"), tr("Camera model %1 not valid for projection.").arg(s.id()));
return;
}
else
{
QMessageBox::warning(this, tr("Depth Calibration"), tr("Depth image cannot be found in the cache, make sure to update cache before doing calibration."));
return;
}
}
else
{
QMessageBox::warning(this, tr("Depth Calibration"), tr("No signatures detected! Map is empty!?"));
return;
} }
if(this->exec() == QDialog::Accepted) if(this->exec() == QDialog::Accepted)
@@ -285,65 +314,63 @@ void DepthCalibrationDialog::calibrate(
{ {
const Signature & s = cachedSignatures.find(iter->first).value(); const Signature & s = cachedSignatures.find(iter->first).value();
SensorData data = s.sensorData(); SensorData data = s.sensorData();
if(data.cameraModels().size() == 1 && data.cameraModels()[0].isValidForReprojection())
cv::Mat depth, laserScan;
data.uncompressData(0, &depth, _ui->checkBox_laserScan->isChecked()?&laserScan:0);
if(data.cameraModels().size() == 1 && data.cameraModels()[0].isValidForProjection() && !depth.empty())
{ {
cv::Mat image, depth, laserScan; UASSERT(iter->first == data.id());
data.uncompressData(&image, &depth, _ui->checkBox_laserScan->isChecked()?&laserScan:0); pcl::PointCloud<pcl::PointXYZ>::Ptr cloud;
if(!image.empty() && !depth.empty())
if(_ui->checkBox_laserScan->isChecked())
{ {
UASSERT(iter->first == data.id()); cloud = util3d::laserScanToPointCloud(laserScan);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud; indices->resize(cloud->size());
for(unsigned int i=0; i<indices->size(); ++i)
if(_ui->checkBox_laserScan->isChecked())
{ {
cloud = util3d::laserScanToPointCloud(laserScan); indices->at(i) = i;
indices->resize(cloud->size());
for(unsigned int i=0; i<indices->size(); ++i)
{
indices->at(i) = i;
}
} }
else }
else
{
cloud = util3d::cloudFromSensorData(
data,
_ui->spinBox_decimation->value(),
_ui->doubleSpinBox_maxDepth->value(),
_ui->doubleSpinBox_minDepth->value(),
indices.get(),
parameters);
}
if(indices->size())
{
if(_ui->doubleSpinBox_voxelSize->value() > 0.0)
{ {
cloud = util3d::cloudFromSensorData( cloud = util3d::voxelize(cloud, indices, _ui->doubleSpinBox_voxelSize->value());
data,
_ui->spinBox_decimation->value(),
_ui->doubleSpinBox_maxDepth->value(),
_ui->doubleSpinBox_minDepth->value(),
indices.get(),
parameters);
} }
if(indices->size()) cloud = util3d::transformPointCloud(cloud, iter->second);
points+=cloud->size();
*map += *cloud;
sequence.insert(std::make_pair(iter->first, data));
cv::Size size = depth.size();
if(_model &&
(_model->getWidth()!=size.width ||
_model->getHeight()!=size.height))
{ {
if(_ui->doubleSpinBox_voxelSize->value() > 0.0) QString msg = tr("Depth images (%1x%2) in the map don't have the "
{ "same size then in the current model (%3x%4). You may want "
cloud = util3d::voxelize(cloud, indices, _ui->doubleSpinBox_voxelSize->value()); "to check \"Reset previous model\" before trying again.")
} .arg(size.width).arg(size.height)
.arg(_model->getWidth()).arg(_model->getHeight());
cloud = util3d::transformPointCloud(cloud, iter->second); QMessageBox::warning(this, tr("Depth Calibration"), msg);
_progressDialog->appendText(msg, Qt::darkRed);
points+=cloud->size(); _progressDialog->setAutoClose(false);
return;
*map += *cloud;
sequence.insert(std::make_pair(iter->first, data));
cv::Size size = data.cameraModels()[0].imageSize();
if(_model &&
(_model->getWidth()!=size.width ||
_model->getHeight()!=size.height))
{
QString msg = tr("Depth images (%1x%2) in the map don't have the "
"same size then in the current model (%3x%4). You may want "
"to check \"Reset previous model\" before trying again.")
.arg(size.width).arg(size.height)
.arg(_model->getWidth()).arg(_model->getHeight());
QMessageBox::warning(this, tr("Depth Calibration"), msg);
_progressDialog->appendText(msg, Qt::darkRed);
_progressDialog->setAutoClose(false);
return;
}
} }
} }
} }
@@ -434,7 +461,7 @@ void DepthCalibrationDialog::calibrate(
QDialog * dialog = new QDialog(this->parentWidget()?this->parentWidget():this, Qt::Window); QDialog * dialog = new QDialog(this->parentWidget()?this->parentWidget():this, Qt::Window);
dialog->setAttribute(Qt::WA_DeleteOnClose, true); dialog->setAttribute(Qt::WA_DeleteOnClose, true);
dialog->setWindowTitle(tr("Original/Map")); dialog->setWindowTitle(tr("Original/Map"));
dialog->setMinimumWidth(sequence.begin()->second.cameraModels()[0].imageWidth()); dialog->setMinimumWidth(_imageSize.width);
ImageView * imageView1 = new ImageView(dialog); ImageView * imageView1 = new ImageView(dialog);
imageView1->setMinimumSize(320, 240); imageView1->setMinimumSize(320, 240);
ImageView * imageView2 = new ImageView(dialog); ImageView * imageView2 = new ImageView(dialog);
@@ -450,7 +477,7 @@ void DepthCalibrationDialog::calibrate(
} }
//clams::DiscreteDepthDistortionModel model = clams::calibrate(sequence, poses, map); //clams::DiscreteDepthDistortionModel model = clams::calibrate(sequence, poses, map);
const cv::Size & imageSize = sequence.begin()->second.cameraModels()[0].imageSize(); const cv::Size & imageSize = _imageSize;
if(_model == 0) if(_model == 0)
{ {
size_t bin_width = _ui->spinBox_bin_width->value(); size_t bin_width = _ui->spinBox_bin_width->value();
@@ -487,24 +514,33 @@ void DepthCalibrationDialog::calibrate(
cv::Mat depthImage; cv::Mat depthImage;
ster->second.uncompressDataConst(0, &depthImage); ster->second.uncompressDataConst(0, &depthImage);
cv::Mat mapDepth; if(ster->second.cameraModels().size() == 1 && ster->second.cameraModels()[0].isValidForProjection() && !depthImage.empty())
clams::FrameProjector projector(ster->second.cameraModels()[0]);
mapDepth = projector.estimateMapDepth(
map,
iter->second.inverse(),
depthImage,
_ui->doubleSpinBox_coneRadius->value(),
_ui->doubleSpinBox_coneStdDevThresh->value());
if(ULogger::level() == ULogger::kDebug)
{ {
imageView1->setImage(uCvMat2QImage(depthImage)); cv::Mat mapDepth;
imageView2->setImage(uCvMat2QImage(mapDepth)); CameraModel model = ster->second.cameraModels()[0];
} if(model.imageWidth() != depthImage.cols)
{
UASSERT_MSG(model.imageHeight() % depthImage.rows == 0, uFormat("rgb=%d depth=%d", model.imageHeight(), depthImage.rows).c_str());
model = model.scaled(double(depthImage.rows) / double(model.imageHeight()));
}
clams::FrameProjector projector(model);
mapDepth = projector.estimateMapDepth(
map,
iter->second.inverse(),
depthImage,
_ui->doubleSpinBox_coneRadius->value(),
_ui->doubleSpinBox_coneStdDevThresh->value());
counts = _model->accumulate(mapDepth, depthImage); if(ULogger::level() == ULogger::kDebug)
_progressDialog->appendText(tr("Added %1 training examples from node %2 (%3/%4).").arg(counts).arg(iter->first).arg(++index).arg(sequence.size())); {
} imageView1->setImage(uCvMat2QImage(depthImage));
imageView2->setImage(uCvMat2QImage(mapDepth));
}
counts = _model->accumulate(mapDepth, depthImage);
_progressDialog->appendText(tr("Added %1 training examples from node %2 (%3/%4).").arg(counts).arg(iter->first).arg(++index).arg(sequence.size()));
}
}
_progressDialog->incrementStep(); _progressDialog->incrementStep();
QApplication::processEvents(); QApplication::processEvents();
} }
+17 -5
View File
@@ -37,7 +37,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <QtGui/QDesktopServices> #include <QtGui/QDesktopServices>
#include <QtGui/QContextMenuEvent> #include <QtGui/QContextMenuEvent>
#include <QColorDialog> #include <QColorDialog>
#ifdef QT_SVG_LIB
#include <QtSvg/QSvgGenerator> #include <QtSvg/QSvgGenerator>
#endif
#include <QInputDialog> #include <QInputDialog>
#include <QMessageBox> #include <QMessageBox>
@@ -1176,19 +1178,19 @@ void GraphViewer::setMaxLinkLength(float value)
} }
void GraphViewer::setGraphVisible(bool visible) void GraphViewer::setGraphVisible(bool visible)
{ {
_graphRoot->setVisible(!_graphRoot->isVisible()); _graphRoot->setVisible(visible);
} }
void GraphViewer::setGlobalPathVisible(bool visible) void GraphViewer::setGlobalPathVisible(bool visible)
{ {
_globalPathRoot->setVisible(!_globalPathRoot->isVisible()); _globalPathRoot->setVisible(visible);
} }
void GraphViewer::setLocalPathVisible(bool visible) void GraphViewer::setLocalPathVisible(bool visible)
{ {
_localPathRoot->setVisible(!_localPathRoot->isVisible()); _localPathRoot->setVisible(visible);
} }
void GraphViewer::setGtGraphVisible(bool visible) void GraphViewer::setGtGraphVisible(bool visible)
{ {
_gtGraphRoot->setVisible(!_gtGraphRoot->isVisible()); _gtGraphRoot->setVisible(visible);
} }
void GraphViewer::restoreDefaults() void GraphViewer::restoreDefaults()
@@ -1233,6 +1235,9 @@ void GraphViewer::contextMenuEvent(QContextMenuEvent * event)
QMenu menu; QMenu menu;
QAction * aScreenShotPNG = menu.addAction(tr("Take a screenshot (PNG)")); QAction * aScreenShotPNG = menu.addAction(tr("Take a screenshot (PNG)"));
QAction * aScreenShotSVG = menu.addAction(tr("Take a screenshot (SVG)")); QAction * aScreenShotSVG = menu.addAction(tr("Take a screenshot (SVG)"));
#ifndef QT_SVG_LIB
aScreenShotSVG->setEnabled(false);
#endif
menu.addSeparator(); menu.addSeparator();
QAction * aChangeNodeColor = menu.addAction(createIcon(_nodeColor), tr("Set node color...")); QAction * aChangeNodeColor = menu.addAction(createIcon(_nodeColor), tr("Set node color..."));
@@ -1361,7 +1366,6 @@ void GraphViewer::contextMenuEvent(QContextMenuEvent * event)
{ {
aShowHideGtGraph = menu.addAction(tr("Show ground truth graph")); aShowHideGtGraph = menu.addAction(tr("Show ground truth graph"));
} }
aShowHideGridMap->setEnabled(!_gridMap->pixmap().isNull());
aShowHideGraph->setEnabled(_nodeItems.size()); aShowHideGraph->setEnabled(_nodeItems.size());
aShowHideGlobalPath->setEnabled(_globalPathLinkItems.size()); aShowHideGlobalPath->setEnabled(_globalPathLinkItems.size());
aShowHideLocalPath->setEnabled(_localPathLinkItems.size()); aShowHideLocalPath->setEnabled(_localPathLinkItems.size());
@@ -1423,6 +1427,7 @@ void GraphViewer::contextMenuEvent(QContextMenuEvent * event)
} }
else else
{ {
#ifdef QT_SVG_LIB
QSvgGenerator svgGen; QSvgGenerator svgGen;
svgGen.setFileName( targetDir + name ); svgGen.setFileName( targetDir + name );
@@ -1434,6 +1439,9 @@ void GraphViewer::contextMenuEvent(QContextMenuEvent * event)
QPainter painter( &svgGen ); QPainter painter( &svgGen );
this->scene()->render(&painter); this->scene()->render(&painter);
#else
UERROR("RTAB-MAp is not built with Qt's SVG library, cannot save picture in svg format.");
#endif
} }
//reset scale //reset scale
@@ -1626,6 +1634,10 @@ void GraphViewer::contextMenuEvent(QContextMenuEvent * event)
else if(r == aShowHideGridMap) else if(r == aShowHideGridMap)
{ {
this->setGridMapVisible(!this->isGridMapVisible()); this->setGridMapVisible(!this->isGridMapVisible());
if(_gridMap->isVisible())
{
emit mapShownRequested();
}
} }
else if(r == aShowHideOrigin) else if(r == aShowHideOrigin)
{ {
+37 -1
View File
@@ -5008,9 +5008,11 @@ void MainWindow::postProcessing()
bool optimizeFromGraphEnd = Parameters::defaultRGBDOptimizeFromGraphEnd(); bool optimizeFromGraphEnd = Parameters::defaultRGBDOptimizeFromGraphEnd();
float optimizeMaxError = Parameters::defaultRGBDOptimizeMaxError(); float optimizeMaxError = Parameters::defaultRGBDOptimizeMaxError();
int optimizeIterations = Parameters::defaultOptimizerIterations(); int optimizeIterations = Parameters::defaultOptimizerIterations();
bool reextractFeatures = Parameters::defaultRGBDLoopClosureReextractFeatures();
Parameters::parse(parameters, Parameters::kRGBDOptimizeFromGraphEnd(), optimizeFromGraphEnd); Parameters::parse(parameters, Parameters::kRGBDOptimizeFromGraphEnd(), optimizeFromGraphEnd);
Parameters::parse(parameters, Parameters::kRGBDOptimizeMaxError(), optimizeMaxError); Parameters::parse(parameters, Parameters::kRGBDOptimizeMaxError(), optimizeMaxError);
Parameters::parse(parameters, Parameters::kOptimizerIterations(), optimizeIterations); Parameters::parse(parameters, Parameters::kOptimizerIterations(), optimizeIterations);
Parameters::parse(parameters, Parameters::kRGBDLoopClosureReextractFeatures(), reextractFeatures);
bool warn = false; bool warn = false;
int loopClosuresAdded = 0; int loopClosuresAdded = 0;
@@ -5089,6 +5091,40 @@ void MainWindow::postProcessing()
uInsert(parameters, ParametersPair(Parameters::kRegStrategy(), "2")); uInsert(parameters, ParametersPair(Parameters::kRegStrategy(), "2"));
} }
Registration * registration = Registration::create(parameters); Registration * registration = Registration::create(parameters);
if(reextractFeatures)
{
signatureFrom.sensorData().uncompressData();
signatureTo.sensorData().uncompressData();
if(signatureFrom.sensorData().imageRaw().empty() &&
signatureTo.sensorData().imageRaw().empty())
{
UWARN("\"%s\" is false and signatures (%d and %d) don't have raw "
"images. Update the cache.",
Parameters::kRGBDLoopClosureReextractFeatures().c_str());
}
else
{
signatureFrom.setWords(std::multimap<int, cv::KeyPoint>());
signatureFrom.setWords3(std::multimap<int, cv::Point3f>());
signatureFrom.setWordsDescriptors(std::multimap<int, cv::Mat>());
signatureFrom.sensorData().setFeatures(std::vector<cv::KeyPoint>(), std::vector<cv::Point3f>(), cv::Mat());
signatureTo.setWords(std::multimap<int, cv::KeyPoint>());
signatureTo.setWords3(std::multimap<int, cv::Point3f>());
signatureTo.setWordsDescriptors(std::multimap<int, cv::Mat>());
signatureTo.sensorData().setFeatures(std::vector<cv::KeyPoint>(), std::vector<cv::Point3f>(), cv::Mat());
}
}
else if(!reextractFeatures && signatureFrom.getWords().empty() && signatureTo.getWords().empty())
{
UWARN("\"%s\" is false and signatures (%d and %d) don't have words, "
"registration will not be possible. Set \"%s\" to true.",
Parameters::kRGBDLoopClosureReextractFeatures().c_str(),
signatureFrom.id(),
signatureTo.id(),
Parameters::kRGBDLoopClosureReextractFeatures().c_str());
}
transform = registration->computeTransformation(signatureFrom, signatureTo, Transform(), &info); transform = registration->computeTransformation(signatureFrom, signatureTo, Transform(), &info);
delete registration; delete registration;
if(!transform.isNull()) if(!transform.isNull())
@@ -5218,13 +5254,13 @@ void MainWindow::postProcessing()
_currentLinksMap.insert(std::make_pair(from, Link(from, to, Link::kUserClosure, transform, info.covariance.inv()))); _currentLinksMap.insert(std::make_pair(from, Link(from, to, Link::kUserClosure, transform, info.covariance.inv())));
++loopClosuresAdded; ++loopClosuresAdded;
_initProgressDialog->appendText(tr("Detected loop closure %1->%2! (%3/%4)").arg(from).arg(to).arg(i+1).arg(clusters.size())); _initProgressDialog->appendText(tr("Detected loop closure %1->%2! (%3/%4)").arg(from).arg(to).arg(i+1).arg(clusters.size()));
QApplication::processEvents();
} }
} }
} }
} }
} }
} }
QApplication::processEvents();
_initProgressDialog->incrementStep(); _initProgressDialog->incrementStep();
} }
_initProgressDialog->appendText(tr("Iteration %1/%2: Detected %3 loop closures!").arg(n+1).arg(detectLoopClosureIterations).arg(addedLinks.size()/2)); _initProgressDialog->appendText(tr("Iteration %1/%2: Detected %3 loop closures!").arg(n+1).arg(detectLoopClosureIterations).arg(addedLinks.size()/2));
+30 -7
View File
@@ -197,8 +197,8 @@ PreferencesDialog::PreferencesDialog(QWidget * parent) :
#if CV_MAJOR_VERSION >= 3 #if CV_MAJOR_VERSION >= 3
_ui->groupBox_fast_opencv2->setEnabled(false); _ui->groupBox_fast_opencv2->setEnabled(false);
#else #else
_ui->comboBox_detector_strategy->setItemData(9, 0, Qt::UserRole - 1); // No FREAK (detector+descriptor version) _ui->comboBox_detector_strategy->setItemData(9, 0, Qt::UserRole - 1); // No KAZE
_ui->reextract_type->setItemData(9, 0, Qt::UserRole - 1); // No FREAK (detector+descriptor version) _ui->reextract_type->setItemData(9, 0, Qt::UserRole - 1); // No KAZE
#endif #endif
_ui->comboBox_cameraImages_odomFormat->setItemData(4, 0, Qt::UserRole - 1); _ui->comboBox_cameraImages_odomFormat->setItemData(4, 0, Qt::UserRole - 1);
@@ -746,8 +746,16 @@ PreferencesDialog::PreferencesDialog(QWidget * parent) :
_ui->spinBox_BRISK_octaves->setObjectName(Parameters::kBRISKOctaves().c_str()); _ui->spinBox_BRISK_octaves->setObjectName(Parameters::kBRISKOctaves().c_str());
_ui->doubleSpinBox_BRISK_patterScale->setObjectName(Parameters::kBRISKPatternScale().c_str()); _ui->doubleSpinBox_BRISK_patterScale->setObjectName(Parameters::kBRISKPatternScale().c_str());
//KAZE
_ui->checkBox_kaze_extended->setObjectName(Parameters::kKAZEExtended().c_str());
_ui->checkBox_kaze_upright->setObjectName(Parameters::kKAZEUpright().c_str());
_ui->doubleSpinBox_kaze_threshold->setObjectName(Parameters::kKAZEThreshold().c_str());
_ui->spinBox_kaze_octaves->setObjectName(Parameters::kKAZENOctaves().c_str());
_ui->spinBox_kaze_octavelayers->setObjectName(Parameters::kKAZENOctaveLayers().c_str());
_ui->spinBox_kaze_diffusivity->setObjectName(Parameters::kKAZEDiffusivity().c_str());
// verifyHypotheses // verifyHypotheses
_ui->comboBox_vh_strategy->setObjectName(Parameters::kRtabmapVhStrategy().c_str()); _ui->groupBox_vh_epipolar2->setObjectName(Parameters::kVhEpEnabled().c_str());
_ui->surf_spinBox_matchCountMinAccepted->setObjectName(Parameters::kVhEpMatchCountMin().c_str()); _ui->surf_spinBox_matchCountMinAccepted->setObjectName(Parameters::kVhEpMatchCountMin().c_str());
_ui->surf_doubleSpinBox_ransacParam1->setObjectName(Parameters::kVhEpRansacParam1().c_str()); _ui->surf_doubleSpinBox_ransacParam1->setObjectName(Parameters::kVhEpRansacParam1().c_str());
_ui->surf_doubleSpinBox_ransacParam2->setObjectName(Parameters::kVhEpRansacParam2().c_str()); _ui->surf_doubleSpinBox_ransacParam2->setObjectName(Parameters::kVhEpRansacParam2().c_str());
@@ -1603,6 +1611,7 @@ void PreferencesDialog::resetSettings(QGroupBox * groupBox)
if(groupBox->objectName() == _ui->groupBox_odometry1->objectName()) if(groupBox->objectName() == _ui->groupBox_odometry1->objectName())
{ {
_ui->odom_registration->setCurrentIndex(3); _ui->odom_registration->setCurrentIndex(3);
updateOdometryVisibility();
} }
} }
} }
@@ -2363,19 +2372,33 @@ bool PreferencesDialog::validateForm()
#endif #endif
#if CV_MAJOR_VERSION < 3 #if CV_MAJOR_VERSION < 3
if (_ui->comboBox_detector_strategy->currentIndex() == Feature2D::kFeatureFreak) if (_ui->comboBox_detector_strategy->currentIndex() == Feature2D::kFeatureKaze)
{ {
#ifdef RTABMAP_NONFREE
QMessageBox::warning(this, tr("Parameter warning"), QMessageBox::warning(this, tr("Parameter warning"),
tr("Selected feature type (FREAK detector) is not available on OpenCV2. ORB is set instead " tr("Selected feature type (KAZE) is not available on OpenCV2. SURF is set instead "
"for the bag-of-words dictionary."));
_ui->comboBox_detector_strategy->setCurrentIndex(Feature2D::kFeatureSurf);
#else
QMessageBox::warning(this, tr("Parameter warning"),
tr("Selected feature type (KAZE) is not available on OpenCV2. ORB is set instead "
"for the bag-of-words dictionary.")); "for the bag-of-words dictionary."));
_ui->comboBox_detector_strategy->setCurrentIndex(Feature2D::kFeatureOrb); _ui->comboBox_detector_strategy->setCurrentIndex(Feature2D::kFeatureOrb);
#endif
} }
if (_ui->reextract_type->currentIndex() == Feature2D::kFeatureFreak) if (_ui->reextract_type->currentIndex() == Feature2D::kFeatureKaze)
{ {
#ifdef RTABMAP_NONFREE
QMessageBox::warning(this, tr("Parameter warning"), QMessageBox::warning(this, tr("Parameter warning"),
tr("Selected feature type (FREAK detector) is not available on OpenCV2. ORB is set instead " tr("Selected feature type (KAZE) is not available on OpenCV2. SURF is set instead "
"for the re-extraction of features on loop closure."));
_ui->reextract_type->setCurrentIndex(Feature2D::kFeatureSurf);
#else
QMessageBox::warning(this, tr("Parameter warning"),
tr("Selected feature type (KAZE) is not available on OpenCV2. ORB is set instead "
"for the re-extraction of features on loop closure.")); "for the re-extraction of features on loop closure."));
_ui->reextract_type->setCurrentIndex(Feature2D::kFeatureOrb); _ui->reextract_type->setCurrentIndex(Feature2D::kFeatureOrb);
#endif
} }
#endif #endif
+264 -134
View File
@@ -63,7 +63,7 @@
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>0</x> <x>0</x>
<y>-637</y> <y>0</y>
<width>678</width> <width>678</width>
<height>2739</height> <height>2739</height>
</rect> </rect>
@@ -95,7 +95,7 @@
<enum>QFrame::Raised</enum> <enum>QFrame::Raised</enum>
</property> </property>
<property name="currentIndex"> <property name="currentIndex">
<number>18</number> <number>34</number>
</property> </property>
<widget class="QWidget" name="page_22"> <widget class="QWidget" name="page_22">
<layout class="QVBoxLayout" name="verticalLayout_29" stretch="0,1"> <layout class="QVBoxLayout" name="verticalLayout_29" stretch="0,1">
@@ -6732,7 +6732,7 @@ generate the number of words requested.</string>
</item> </item>
<item> <item>
<property name="text"> <property name="text">
<string>FREAK</string> <string>KAZE</string>
</property> </property>
</item> </item>
</widget> </widget>
@@ -7480,13 +7480,13 @@ see Sqlite3 doc 'PRAGMA temp_store'.</string>
</layout> </layout>
</widget> </widget>
<widget class="QWidget" name="page_23"> <widget class="QWidget" name="page_23">
<layout class="QVBoxLayout" name="verticalLayout_2"> <layout class="QVBoxLayout" name="verticalLayout_2" stretch="0,1">
<item> <item>
<widget class="QGroupBox" name="groupBox_bayes1"> <widget class="QGroupBox" name="groupBox_bayes1">
<property name="title"> <property name="title">
<string>Loop Closure Detection</string> <string>Loop Closure Detection</string>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_22"> <layout class="QVBoxLayout" name="verticalLayout_22" stretch="0,0,0,1,0,0">
<item> <item>
<widget class="QLabel" name="label"> <widget class="QLabel" name="label">
<property name="text"> <property name="text">
@@ -7630,139 +7630,96 @@ see Sqlite3 doc 'PRAGMA temp_store'.</string>
</layout> </layout>
</item> </item>
<item> <item>
<widget class="QGroupBox" name="groupBox_vh_strategy2"> <widget class="QGroupBox" name="groupBox_vh_epipolar2">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="title"> <property name="title">
<string>Hypothesis Verification</string> <string>Hypothesis Verification</string>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_3"> <property name="checkable">
<item> <bool>true</bool>
<layout class="QGridLayout" name="gridLayout_10" columnstretch="0,1"> </property>
<item row="0" column="0"> <layout class="QGridLayout" name="gridLayout" columnstretch="0,10">
<widget class="QComboBox" name="comboBox_vh_strategy"> <item row="0" column="0">
<property name="sizeAdjustPolicy"> <widget class="QSpinBox" name="surf_spinBox_matchCountMinAccepted">
<enum>QComboBox::AdjustToContents</enum> <property name="minimum">
</property> <number>8</number>
<item> </property>
<property name="text"> <property name="maximum">
<string>No verification</string> <number>100000</number>
</property> </property>
</item> <property name="value">
<item> <number>11</number>
<property name="text"> </property>
<string>Epipolar constraints</string> </widget>
</property>
</item>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="label_50">
<property name="text">
<string>Hypothesis verification.</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
</layout>
</item> </item>
<item> <item row="0" column="1">
<widget class="QGroupBox" name="groupBox_vh_epipolar2"> <widget class="QLabel" name="label_25">
<property name="title"> <property name="text">
<string>Epipolar Constraints</string> <string>Minimum match count to accept a loop closure.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QDoubleSpinBox" name="surf_doubleSpinBox_ransacParam1">
<property name="decimals">
<number>1</number>
</property>
<property name="maximum">
<double>10.000000000000000</double>
</property>
<property name="singleStep">
<double>0.100000000000000</double>
</property>
<property name="value">
<double>3.000000000000000</double>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="label_27">
<property name="text">
<string>Fundamental Matrix : Distance (pixels) for inliers.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QDoubleSpinBox" name="surf_doubleSpinBox_ransacParam2">
<property name="decimals">
<number>2</number>
</property>
<property name="maximum">
<double>0.990000000000000</double>
</property>
<property name="singleStep">
<double>0.010000000000000</double>
</property>
<property name="value">
<double>0.990000000000000</double>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLabel" name="label_28">
<property name="text">
<string>Fundamental Matrix : Ransac performance.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property> </property>
<layout class="QGridLayout" name="gridLayout" columnstretch="0,10">
<item row="0" column="0">
<widget class="QSpinBox" name="surf_spinBox_matchCountMinAccepted">
<property name="minimum">
<number>8</number>
</property>
<property name="maximum">
<number>100000</number>
</property>
<property name="value">
<number>11</number>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="label_25">
<property name="text">
<string>Minimum match count to accept a loop closure.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QDoubleSpinBox" name="surf_doubleSpinBox_ransacParam1">
<property name="decimals">
<number>1</number>
</property>
<property name="maximum">
<double>10.000000000000000</double>
</property>
<property name="singleStep">
<double>0.100000000000000</double>
</property>
<property name="value">
<double>3.000000000000000</double>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="label_27">
<property name="text">
<string>Fundamental Matrix : Distance (pixels) for inliers.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QDoubleSpinBox" name="surf_doubleSpinBox_ransacParam2">
<property name="decimals">
<number>2</number>
</property>
<property name="maximum">
<double>0.990000000000000</double>
</property>
<property name="singleStep">
<double>0.010000000000000</double>
</property>
<property name="value">
<double>0.990000000000000</double>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLabel" name="label_28">
<property name="text">
<string>Fundamental Matrix : Ransac performance.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
</layout>
</widget> </widget>
</item> </item>
</layout> </layout>
@@ -13288,7 +13245,7 @@ Lower the ratio -&gt; higher the precision. 0 means disabled, matching the neare
</item> </item>
<item> <item>
<property name="text"> <property name="text">
<string>FREAK</string> <string>KAZE</string>
</property> </property>
</item> </item>
</widget> </widget>
@@ -15906,6 +15863,179 @@ Lower the ratio -&gt; higher the precision. 0 means disabled, matching the neare
</item> </item>
</layout> </layout>
</widget> </widget>
<widget class="QWidget" name="page_71">
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QGroupBox" name="groupBox_detector_kaze2">
<property name="title">
<string>KAZE</string>
</property>
<layout class="QGridLayout" name="gridLayout_95" columnstretch="0,1">
<item row="0" column="0">
<widget class="QCheckBox" name="checkBox_kaze_extended">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="label_420">
<property name="text">
<string>Set to enable use of upright descriptors (non rotation-invariant).</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLabel" name="label_416">
<property name="text">
<string>Maximum octave evolution of the image.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="checkBox_kaze_upright">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QLabel" name="label_417">
<property name="text">
<string>Default number of sublevels per scale level.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QSpinBox" name="spinBox_kaze_octavelayers">
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>16</number>
</property>
<property name="value">
<number>3</number>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QSpinBox" name="spinBox_kaze_octaves">
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>16</number>
</property>
<property name="value">
<number>16</number>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="label_419">
<property name="text">
<string>Set to enable extraction of extended (128-byte) descriptor.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QDoubleSpinBox" name="doubleSpinBox_kaze_threshold">
<property name="decimals">
<number>4</number>
</property>
<property name="minimum">
<double>0.000100000000000</double>
</property>
<property name="maximum">
<double>9999.000000000000000</double>
</property>
<property name="singleStep">
<double>0.001000000000000</double>
</property>
<property name="value">
<double>0.001000000000000</double>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLabel" name="label_418">
<property name="text">
<string>Detector response threshold to accept point.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QLabel" name="label_421">
<property name="text">
<string>Diffusivity type: 0=DIFF_PM_G1, 1=DIFF_PM_G2, 2=DIFF_WEICKERT or 3=DIFF_CHARBONNIER.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QSpinBox" name="spinBox_kaze_diffusivity">
<property name="maximum">
<number>3</number>
</property>
<property name="value">
<number>3</number>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer_65">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>2487</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</widget> </widget>
</item> </item>
</layout> </layout>
+1 -1
View File
@@ -1,7 +1,7 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<package> <package>
<name>rtabmap</name> <name>rtabmap</name>
<version>0.13.0</version> <version>0.13.2</version>
<description>RTAB-Map's standalone library. RTAB-Map is a RGB-D SLAM approach with real-time constraints.</description> <description>RTAB-Map's standalone library. RTAB-Map is a RGB-D SLAM approach with real-time constraints.</description>
<maintainer email="matlabbe@gmail.com">Mathieu Labbe</maintainer> <maintainer email="matlabbe@gmail.com">Mathieu Labbe</maintainer>
<author>Mathieu Labbe</author> <author>Mathieu Labbe</author>
+4 -1
View File
@@ -6,4 +6,7 @@ if(UNIX AND NOT ANDROID)
ENDIF(UNIX AND NOT ANDROID) ENDIF(UNIX AND NOT ANDROID)
ADD_SUBDIRECTORY( src ) ADD_SUBDIRECTORY( src )
ADD_SUBDIRECTORY( resource_generator )
IF(NOT ANDROID)
ADD_SUBDIRECTORY( resource_generator )
ENDIF(NOT ANDROID)