Compare commits

..

48 Commits

Author SHA1 Message Date
matlabbe
f2d48cb894 Fixed ICP-only registration with already provided guess (no need to do visual guess, as the guess can be already good) 2016-06-23 11:08:20 -04:00
matlabbe
22766e958f Update VWDictionary.cpp
Fixed "HAVE_OPENCV_CUDAFEATURES2D" build error of https://github.com/introlab/rtabmap/issues/85
2016-06-22 19:28:22 -04:00
matlabbe
8e76de7d34 Fixed GTSAM/Eigen include dir 2016-06-15 15:48:56 -04:00
matlabbe
abd376a44c segmentObstaclesFromGround() fixed identical ground and obstacles indices 2016-06-14 11:55:58 -04:00
matlabbe
4a3f490814 Added Reg/Force2D compatibility name for Reg/Force3DoF 2016-06-09 15:49:17 -04:00
matlabbe
cbf348fafa labels can be saved in localization mode 2016-06-08 18:19:51 -04:00
matlabbe
e205883de5 Export: set 0 voxel size by default 2016-06-08 11:53:25 -04:00
matlabbe
ce04336648 fixed cmake warning, removed a .DS_Store from repository 2016-06-04 16:21:00 -04:00
matlabbe
a8bf7e5d5f Fixed Qt5 plugins release. Zed driver: sdded 2 seconds delay before sending grab error. 2016-06-04 15:17:13 -04:00
matlabbe
69e1973544 Update MainWindow.cpp 2016-06-03 15:06:18 -04:00
matlabbe
2f817568e2 MainWindow: Don't show an error if a created cloud is empty 2016-06-02 17:52:22 -04:00
matlabbe
d9611f784c Added ZED parameters 2016-06-02 17:27:12 -04:00
matlabbe
9430bcbf2e Increased ROS package version to 0.11.7 2016-06-01 14:53:00 -04:00
matlabbe
a6f7062f92 Export intern dependencies in RTABMapConfig.cmake 2016-06-01 13:13:30 -04:00
matlabbe
e234717129 Fixed ZED sdk build on Linux (added c++11) 2016-05-31 20:19:04 -04:00
matlabbe
6f1f490370 0.11.7: Added ZED sdk support 2016-05-31 19:09:49 -04:00
matlabbe
b2bb421063 Fixed pcl:OrganizedFastMesh link error for type pcl::PointXYZRGBNormal with PCL 1.8 (issue #75) 2016-05-31 12:23:13 -04:00
matlabbe
be13a9b967 Fixed localization bug when virtual links are added 2016-05-26 17:28:06 -04:00
matlabbe
0fa41d317a Added log msg to tell when switching from Mapping to Localization is finished 2016-05-26 12:51:32 -04:00
matlabbe
a4d36e0212 MainWindow: fixed same bug as previous commit 30fecd412c but on runtime 2016-05-26 12:38:18 -04:00
matlabbe
30fecd412c MainWindow: Fixed clouds shown (and should not) after refreshing map with grid from projection enabled and cloud map visualization unchecked 2016-05-26 12:35:02 -04:00
matlabbe
0d61c12dcd Create map from projection: Removed debug cloud saved 2016-05-26 12:23:44 -04:00
matlabbe
7f2a899c6f Updated default decimation to 4 instead of 8 2016-05-26 12:13:59 -04:00
matlabbe
0bbb773e95 fixed passthrough not using input indices 2016-05-21 16:02:57 -04:00
matlabbe
7aa9c92971 Added util3d::pasthrough returning indices for convenience. segmentObstaclesFromGound(): filtering obstacles under maxGroundHeight if set 2016-05-21 15:54:37 -04:00
Mathieu Labbe
904f4bb4d8 Features2d: updated computeROI() to be more precise 2016-05-21 14:56:25 -04:00
matlabbe
09696195f4 Version 0.11.6 2016-05-20 17:27:03 -04:00
matlabbe
971c96f566 MainWindow projected map: fixed bad occupancy from wrong normals after voxel filtering. util3d::segmentObstaclesFromGround(): added flatObstacles argument. 2016-05-20 17:25:52 -04:00
matlabbe
4fdaa2b708 CloudViewer: fixed numpad color not working -> reverted changes from ad0afc58c0 (diff-d7a550026127f42ccabdb5e42979eeeb) 2016-05-20 16:38:35 -04:00
matlabbe
9f6af75f79 Local scan matching: set larger scan points for max scan points when it is not set. Fixed missing scan Ids in links' user data to correctly visualize proximity links by space in DatabaseViewer. CloudViewer: using line instead of arrow between the referential and the frustum. removed parameter "RGBD/ProximityPathScansMerged" as visual proximity by space already does that. 2016-05-20 11:44:50 -04:00
matlabbe
b29ce28877 CloudViewer: Fixed crash when changing frustum's color 2016-05-19 17:19:11 -04:00
matlabbe
ff7406a755 Memory::computeTransform(): removed setting guess to identity if input guess is null 2016-05-19 17:01:46 -04:00
matlabbe
a8be08a19a Registration: if parent registration fails, continue with the child if the prior guess is not null 2016-05-19 16:11:26 -04:00
matlabbe
1ecaae364c Generalized neighbor link refining using registration done in Memory (can be visual, visual+icp or, icp) 2016-05-19 15:35:30 -04:00
Mathieu Labbe
2637f74094 Added some debug info 2016-05-19 14:31:29 -04:00
Mathieu Labbe
02d944aa67 CalibrationDialog: fixed D not shown properly, add scroll area for small screens 2016-05-19 11:40:48 -04:00
matlabbe
a6bad6d2a5 F2F nonholonomic bad transforms fixed (https://github.com/introlab/rtabmap_ros/issues/74) 2016-05-17 18:10:24 -04:00
matlabbe
0ae131108d CloudViewer: Added local transformation between base frame and camera frame (when they are not the same) 2016-05-17 16:32:21 -04:00
matlabbe
2db6b2ceef segmentObstaclesFromGround: Added epsilon for ground surface inclusion inside maximum and minimum heights 2016-05-16 16:26:16 -04:00
matlabbe
f19c058634 Merge branch 'jade-devel' of https://github.com/introlab/rtabmap into jade-devel 2016-05-14 12:11:10 -04:00
matlabbe
ceb4acd749 Merge branch 'master' of https://github.com/introlab/rtabmap into jade-devel 2016-05-14 12:09:29 -04:00
matlabbe
dde0e26110 Tango: C-API Code Migration to Mira release 2016-05-12 14:34:51 -04:00
matlabbe
b0629d626e Merge branch 'master' of github.com:introlab/rtabmap into jade-devel 2015-10-17 14:16:14 -04:00
matlabbe
ec09d69145 jade package: libfreenect -> libfreenect-dev 2015-08-04 15:52:13 -04:00
matlabbe
8ddbc6bf96 Merge branch 'master' of https://github.com/introlab/rtabmap into jade-devel 2015-05-12 08:37:38 -04:00
matlabbe
b608e50296 Merge branch 'master' of https://github.com/introlab/rtabmap into jade-devel 2015-05-12 08:29:41 -04:00
matlabbe
7fa791992c Jade branch: changed libfreenect to libfreenect-dev ROS dependency (run-depend) 2015-05-10 21:22:59 -04:00
matlabbe
fae21132ee Jade branch: changed libfreenect to libfreenect-dev ROS dependency 2015-05-10 21:13:52 -04:00
65 changed files with 2367 additions and 1069 deletions

View File

@@ -20,7 +20,7 @@ SET(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake_modules")
#######################
SET(RTABMAP_MAJOR_VERSION 0)
SET(RTABMAP_MINOR_VERSION 11)
SET(RTABMAP_PATCH_VERSION 5)
SET(RTABMAP_PATCH_VERSION 7)
SET(RTABMAP_VERSION
${RTABMAP_MAJOR_VERSION}.${RTABMAP_MINOR_VERSION}.${RTABMAP_PATCH_VERSION})
@@ -136,6 +136,7 @@ option(WITH_TORO "Include TORO support" ON)
option(WITH_VERTIGO "Include Vertigo support" ON)
option(WITH_CVSBA "Include cvsba support" ON)
option(WITH_FLYCAPTURE2 "Include FlyCapture2/Triclops support" ON)
option(WITH_ZED "Include ZED sdk support" ON)
FIND_PACKAGE(OpenCV REQUIRED QUIET)
FIND_PACKAGE(PCL 1.7 REQUIRED QUIET)
@@ -235,7 +236,50 @@ IF(WITH_GTSAM)
FIND_PACKAGE(GTSAM QUIET)
ENDIF(WITH_GTSAM)
IF(G2O_FOUND OR GTSAM_FOUND)
IF(WITH_FLYCAPTURE2)
FIND_PACKAGE(FlyCapture2 QUIET)
IF(FlyCapture2_FOUND)
MESSAGE(STATUS "Found FlyCapture2: ${FlyCapture2_INCLUDE_DIRS}")
ENDIF(FlyCapture2_FOUND)
ENDIF(WITH_FLYCAPTURE2)
IF(WITH_CVSBA)
FIND_PACKAGE(cvsba QUIET)
IF(cvsba_FOUND)
MESSAGE(STATUS "Found cvsba: ${cvsba_INCLUDE_DIRS}")
ENDIF(cvsba_FOUND)
ENDIF(WITH_CVSBA)
IF(WITH_ZED)
IF(WIN32) # Windows
SET(ZED_INCLUDE_DIRS $ENV{ZED_INCLUDE_DIRS})
if (CMAKE_CL_64) # 64 bits
SET(ZED_LIBRARIES $ENV{ZED_LIBRARIES_64})
else(CMAKE_CL_64) # 32 bits
message("32bits compilation is no more available with CUDA7.0")
endif(CMAKE_CL_64)
SET(ZED_LIBRARY_DIR $ENV{ZED_LIBRARY_DIR})
IF(ZED_LIBRARIES AND ZED_INCLUDE_DIRS)
SET(ZED_FOUND TRUE)
LINK_DIRECTORIES( ${LINK_DIRECTORIES} ${ZED_LIBRARY_DIR})
ENDIF(ZED_LIBRARIES AND ZED_INCLUDE_DIRS)
ELSE() # Linux
find_package(ZED 0.9 QUIET)
ENDIF(WIN32)
IF(ZED_FOUND)
MESSAGE(STATUS "Found ZED sdk: ${ZED_INCLUDE_DIRS}")
## look for CUDA
find_package(CUDA)
IF(CUDA_FOUND)
MESSAGE(STATUS "Found CUDA: ${CUDA_INCLUDE_DIRS}")
ELSE()
MESSAGE(FATAL_ERROR "CUDA is required to build with Zed sdk! Set -DWITH_ZED=OFF if you don't have CUDA.")
ENDIF()
ENDIF(ZED_FOUND)
ENDIF(WITH_ZED)
IF(G2O_FOUND OR GTSAM_FOUND OR ZED_FOUND)
#Newest versions require std11
IF(NOT MSVC)
include(CheckCXXCompilerFlag)
@@ -249,21 +293,7 @@ IF(G2O_FOUND OR GTSAM_FOUND)
message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler if you want to use g2o or gtsam (set \"-DWITH_G2O=OFF -DWITH_GTSAM=OFF\" to build without g2o and gtsam).")
ENDIF()
ENDIF()
ENDIF(G2O_FOUND OR GTSAM_FOUND)
IF(WITH_FLYCAPTURE2)
FIND_PACKAGE(FlyCapture2 QUIET)
IF(FlyCapture2_FOUND)
MESSAGE(STATUS "Found FlyCapture2: ${FlyCapture2_INCLUDE_DIRS}")
ENDIF(FlyCapture2_FOUND)
ENDIF(WITH_FLYCAPTURE2)
IF(WITH_CVSBA)
FIND_PACKAGE(cvsba QUIET)
IF(cvsba_FOUND)
MESSAGE(STATUS "Found cvsba: ${cvsba_INCLUDE_DIRS}")
ENDIF(cvsba_FOUND)
ENDIF(WITH_CVSBA)
ENDIF(G2O_FOUND OR GTSAM_FOUND OR ZED_FOUND)
####### OSX BUNDLE CMAKE_INSTALL_PREFIX #######
IF(APPLE AND BUILD_AS_BUNDLE)
@@ -294,15 +324,24 @@ ENDIF(APPLE AND BUILD_AS_BUNDLE)
####### SOURCES (Projects) #######
# CONF_DEPENDENCIES contains only dependencies not required by the headers
SET(CONF_DEPENDENCIES
${ZLIB_LIBRARIES}
)
IF(NOT (OPENCV_NONFREE_FOUND OR OPENCV_XFEATURES2D_FOUND))
SET(NONFREE "//")
ENDIF(NOT (OPENCV_NONFREE_FOUND OR OPENCV_XFEATURES2D_FOUND))
IF(NOT G2O_FOUND)
SET(G2O "//")
ENDIF(NOT G2O_FOUND)
ELSE()
SET(CONF_DEPENDENCIES ${CONF_DEPENDENCIES} ${G2O_LIBRARIES})
ENDIF()
IF(NOT GTSAM_FOUND)
SET(GTSAM "//")
ENDIF(NOT GTSAM_FOUND)
ELSE()
SET(CONF_DEPENDENCIES ${CONF_DEPENDENCIES} ${GTSAM_LIBRARIES})
ENDIF()
IF(NOT WITH_TORO)
SET(TORO "//")
ENDIF(NOT WITH_TORO)
@@ -311,22 +350,39 @@ IF(NOT WITH_VERTIGO)
ENDIF(NOT WITH_VERTIGO)
IF(NOT cvsba_FOUND)
SET(CVSBA "//")
ENDIF(NOT cvsba_FOUND)
ELSE()
SET(CONF_DEPENDENCIES ${CONF_DEPENDENCIES} ${cvsba_LIBRARIES})
ENDIF()
IF(NOT Freenect_FOUND)
SET(FREENECT "//")
ENDIF(NOT Freenect_FOUND)
ELSE()
SET(CONF_DEPENDENCIES ${CONF_DEPENDENCIES} ${Freenect_LIBRARIES})
ENDIF()
IF(NOT freenect2_FOUND)
SET(FREENECT2 "//")
ENDIF(NOT freenect2_FOUND)
ELSE()
SET(CONF_DEPENDENCIES ${CONF_DEPENDENCIES} ${freenect2_LIBRARIES})
ENDIF()
IF(NOT OpenNI2_FOUND)
SET(OPENNI2 "//")
ENDIF(NOT OpenNI2_FOUND)
ELSE()
SET(CONF_DEPENDENCIES ${CONF_DEPENDENCIES} ${OpenNI2_LIBRARIES})
ENDIF()
IF(NOT DC1394_FOUND)
SET(DC1394 "//")
ENDIF(NOT DC1394_FOUND)
ELSE()
SET(CONF_DEPENDENCIES ${CONF_DEPENDENCIES} ${DC1394_LIBRARIES})
ENDIF()
IF(NOT FlyCapture2_FOUND)
SET(FLYCAPTURE2 "//")
ENDIF(NOT FlyCapture2_FOUND)
ELSE()
SET(CONF_DEPENDENCIES ${CONF_DEPENDENCIES} ${FlyCapture2_LIBRARIES})
ENDIF()
IF(NOT ZED_FOUND)
SET(ZED "//")
ELSE()
SET(CONF_DEPENDENCIES ${CONF_DEPENDENCIES} ${ZED_LIBRARIES} ${CUDA_LIBRARIES})
ENDIF()
IF(NOT (OpenCV_FOUND AND OpenCV_VERSION_MAJOR EQUAL 3))
SET(OPENCV3 "//")
ENDIF(NOT (OpenCV_FOUND AND OpenCV_VERSION_MAJOR EQUAL 3))
@@ -601,6 +657,18 @@ ELSE()
MESSAGE(STATUS " With cvsba = NO (cvsba not found)")
ENDIF()
IF(ZED_FOUND)
IF(CUDA_FOUND)
MESSAGE(STATUS " With ZED = YES (With CUDA)")
ELSE()
MESSAGE(STATUS " With ZED = YES (Without CUDA)")
ENDIF()
ELSEIF(NOT WITH_ZED)
MESSAGE(STATUS " With ZED = NO (WITH_ZED=OFF)")
ELSE()
MESSAGE(STATUS " With ZED = NO (ZED sdk not found)")
ENDIF()
IF(QT4_FOUND)
MESSAGE(STATUS " With Qt4 = YES (License: Open Source or Commercial)")
ELSEIF(Qt5_FOUND)

View File

@@ -61,6 +61,9 @@ if(@CONF_WITH_GUI@)
set(RTABMap_LIBRARIES ${RTABMap_LIBRARIES} ${RTABMap_GUI})
endif(@CONF_WITH_GUI@)
# Dependencies
set(RTABMap_LIBRARIES ${RTABMap_LIBRARIES} @CONF_DEPENDENCIES@)
#backward compatibilities
set(RTABMAP_CORE ${RTABMap_CORE})
set(RTABMAP_UTILITE ${RTABMap_UTILITE})

View File

@@ -49,6 +49,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@CVSBA@#define RTABMAP_CVSBA
@DC1394@#define RTABMAP_DC1394
@FLYCAPTURE2@#define RTABMAP_FLYCAPTURE2
@ZED@#define RTABMAP_ZED
#endif /* VERSION_H_ */

BIN
app/.DS_Store vendored

Binary file not shown.

View File

@@ -2,7 +2,7 @@
<!-- BEGIN_INCLUDE(manifest) -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.introlab.rtabmap"
android:versionCode="8"
android:versionCode="9"
android:versionName="@RTABMAP_VERSION@">
<uses-permission android:name="android.permission.CAMERA" />
@@ -11,7 +11,7 @@
<uses-permission android:name="android.permission.READ_FRAME_BUFFER" />
<uses-permission android:name="android.permission.ACCESS_SURFACE_FLINGER" />
<uses-feature android:glEsVersion="0x00020000" />
<uses-library android:name="com.projecttango.libtango_device" android:required="true" />
<uses-library android:name="com.projecttango.libtango_device2" android:required="true" />
<!-- This is the platform API where NativeActivity was introduced. -->
<uses-sdk android:minSdkVersion="17" />

View File

@@ -56,6 +56,10 @@ const int kVersionStringLength = 128;
static JavaVM *jvm;
static jobject RTABMapActivity = 0;
namespace {
constexpr int kTangoCoreMinimumVersion = 9377;
} // anonymous namespace.
rtabmap::ParametersMap RTABMapApp::getRtabmapParameters()
{
rtabmap::ParametersMap parameters;
@@ -101,7 +105,9 @@ RTABMapApp::RTABMapApp() :
clearSceneOnNextRender_(false),
totalPoints_(0),
totalPolygons_(0),
lastDrawnCloudsCount_(0)
lastDrawnCloudsCount_(0),
renderingFPS_(0.0f)
{
}
@@ -122,19 +128,19 @@ RTABMapApp::~RTABMapApp() {
}
}
int RTABMapApp::TangoInitialize(JNIEnv* env, jobject caller_activity)
void RTABMapApp::onCreate(JNIEnv* env, jobject caller_activity)
{
env->GetJavaVM(&jvm);
RTABMapActivity = env->NewGlobalRef(caller_activity);
LOGI("RTABMapApp::TangoInitialize()");
LOGI("RTABMapApp::onCreate()");
createdMeshes_.clear();
rawPoses_.clear();
clearSceneOnNextRender_ = true;
totalPoints_ = 0;
totalPolygons_ = 0;
lastDrawnCloudsCount_ = 0;
renderingFPS_ = 0.0f;
if(camera_)
{
@@ -158,12 +164,6 @@ int RTABMapApp::TangoInitialize(JNIEnv* env, jobject caller_activity)
this->registerToEventsManager();
camera_ = new rtabmap::CameraTango(fullResolution_?1:2, autoExposure_);
// The first thing we need to do for any Tango enabled application is to
// initialize the service. We'll do that here, passing on the JNI environment
// and jobject corresponding to the Android activity that is calling us.
return TangoService_initialize(env, caller_activity);
}
void RTABMapApp::openDatabase(const std::string & databasePath)
@@ -218,22 +218,27 @@ void RTABMapApp::openDatabase(const std::string & databasePath)
rtabmapMutex_.unlock();
}
int RTABMapApp::onResume()
bool RTABMapApp::onTangoServiceConnected(JNIEnv* env, jobject iBinder)
{
LOGW("onResume()");
LOGW("onTangoServiceConnected()");
if(camera_)
{
camera_->join(true);
if (TangoService_setBinder(env, iBinder) != TANGO_SUCCESS) {
LOGE("TangoHandler::ConnectTango, TangoService_setBinder error");
return false;
}
if(camera_->init())
{
LOGI("Start camera thread");
camera_->start();
return TANGO_SUCCESS;
return true;
}
LOGE("Failed camera initialization!");
}
return TANGO_ERROR;
return false;
}
void RTABMapApp::onPause()
@@ -307,6 +312,7 @@ int RTABMapApp::Render()
totalPoints_ = 0;
totalPolygons_ = 0;
lastDrawnCloudsCount_ = 0;
renderingFPS_ = 0.0f;
}
// Process events
@@ -543,7 +549,9 @@ int RTABMapApp::Render()
}
}
UTimer fpsTime;
lastDrawnCloudsCount_ = main_scene_.Render();
renderingFPS_ = 1.0/fpsTime.elapsed();
if(rtabmapEvents.size())
{
@@ -647,10 +655,7 @@ void RTABMapApp::setAutoExposure(bool enabled)
autoExposure_ = enabled;
if(camera_)
{
camera_->join(true);
camera_->close();
camera_->setAutoExposure(autoExposure_);
onResume();
}
}
}
@@ -1104,7 +1109,7 @@ void RTABMapApp::handleEvent(UEvent * event)
jclass clazz = env->GetObjectClass(RTABMapActivity);
if(clazz)
{
jmethodID methodID = env->GetMethodID(clazz, "updateStatsCallback", "(IIIIFIIIIIFII)V" );
jmethodID methodID = env->GetMethodID(clazz, "updateStatsCallback", "(IIIIFIIIIIFIFI)V" );
if(methodID)
{
env->CallVoidMethod(RTABMapActivity, methodID,
@@ -1120,6 +1125,7 @@ void RTABMapApp::handleEvent(UEvent * event)
featuresExtracted,
hypothesis,
lastDrawnCloudsCount_,
renderingFPS_,
rejected);
success = true;
}

View File

@@ -50,14 +50,11 @@ class RTABMapApp : public UEventsHandler {
RTABMapApp();
~RTABMapApp();
// Initialize the Tango Service, this function starts the communication
// between the application and the Tango Service.
// The activity object is used for checking if the API version is outdated.
int TangoInitialize(JNIEnv* env, jobject caller_activity);
void onCreate(JNIEnv* env, jobject caller_activity);
void openDatabase(const std::string & databasePath);
int onResume();
bool onTangoServiceConnected(JNIEnv* env, jobject iBinder);
// Explicitly reset motion tracking and restart the pipeline.
// Note that this will cause motion tracking to re-initialize.
@@ -163,6 +160,7 @@ class RTABMapApp : public UEventsHandler {
int totalPoints_;
int totalPolygons_;
int lastDrawnCloudsCount_;
float renderingFPS_;
// main_scene_ includes all drawable object for visualizing Tango device's
// movement and point cloud.

View File

@@ -48,11 +48,11 @@ void GetJStringContent(JNIEnv *AEnv, jstring AStr, std::string &ARes) {
AEnv->ReleaseStringUTFChars(AStr,s);
}
JNIEXPORT jint JNICALL
Java_com_introlab_rtabmap_RTABMapLib_initialize(
JNIEXPORT void JNICALL
Java_com_introlab_rtabmap_RTABMapLib_onCreate(
JNIEnv* env, jobject, jobject activity)
{
return app.TangoInitialize(env, activity);
return app.onCreate(env, activity);
}
JNIEXPORT void JNICALL
@@ -64,10 +64,10 @@ Java_com_introlab_rtabmap_RTABMapLib_openDatabase(
return app.openDatabase(databasePathC);
}
JNIEXPORT jint JNICALL
Java_com_introlab_rtabmap_RTABMapLib_onResume(
JNIEnv*, jobject) {
return app.onResume();
JNIEXPORT bool JNICALL
Java_com_introlab_rtabmap_RTABMapLib_onTangoServiceConnected(
JNIEnv* env, jobject, jobject iBinder) {
return app.onTangoServiceConnected(env, iBinder);
}
JNIEXPORT void JNICALL

View File

@@ -219,6 +219,21 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/fps" />
<TextView
android:id="@+id/fps"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
</LinearLayout>

View File

@@ -20,5 +20,6 @@
<string name="polygons">"Polygons: "</string>
<string name="memory">"Memory (MB): "</string>
<string name="hypothesis">"Hypothesis: "</string>
<string name="fps">"FPS (rendering): "</string>
</resources>

View File

@@ -9,8 +9,10 @@ import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.ProgressDialog;
import android.content.ComponentName;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
@@ -20,6 +22,7 @@ import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Debug;
import android.os.IBinder;
import android.text.Editable;
import android.text.InputType;
import android.util.Log;
@@ -99,6 +102,24 @@ public class RTABMapActivity extends Activity implements OnClickListener {
private Toast mToast = null;
//Tango Service connection.
ServiceConnection mTangoServiceConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName name, IBinder service) {
if(!RTABMapLib.onTangoServiceConnected(service))
{
mToast.makeText(getApplicationContext(),
String.format("Failed to intialize Tango!"), mToast.LENGTH_SHORT).show();
}
}
public void onServiceDisconnected(ComponentName name) {
// Handle this if you need to gracefully shutdown/retry
// in the event that Tango itself crashes/gets upgraded while running.
mToast.makeText(getApplicationContext(),
String.format("Tango disconnected!"), mToast.LENGTH_SHORT).show();
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -172,7 +193,7 @@ public class RTABMapActivity extends Activity implements OnClickListener {
Environment.getExternalStorageState()), mToast.LENGTH_LONG).show();
}
RTABMapLib.initialize(this);
RTABMapLib.onCreate(this);
RTABMapLib.openDatabase(mTempDatabasePath);
}
@@ -193,6 +214,8 @@ public class RTABMapActivity extends Activity implements OnClickListener {
protected void onResume() {
super.onResume();
TangoInitializationHelper.bindTangoService(this, mTangoServiceConnection);
Log.i(TAG, String.format("onResume()"));
if (Tango.hasPermission(this, Tango.PERMISSIONTYPE_MOTION_TRACKING)) {
@@ -209,12 +232,6 @@ public class RTABMapActivity extends Activity implements OnClickListener {
mItemPostProcessing.setEnabled(false);
}
if(RTABMapLib.onResume()!=0)
{
mToast.makeText(getApplicationContext(),
String.format("Failed to connect with Tango!"), mToast.LENGTH_SHORT).show();
}
} else {
Log.i(TAG, String.format("Asking for motion tracking permission"));
startActivityForResult(
@@ -232,6 +249,8 @@ public class RTABMapActivity extends Activity implements OnClickListener {
RTABMapLib.onPause();
mOpenedDatabasePath = "";
RTABMapLib.openDatabase(mTempDatabasePath);
unbindService(mTangoServiceConnection);
}
@Override
@@ -318,6 +337,7 @@ public class RTABMapActivity extends Activity implements OnClickListener {
int featuresExtracted,
float hypothesis,
int nodesDrawn,
float fps,
int rejected)
{
if(mItemPause!=null)
@@ -335,6 +355,7 @@ public class RTABMapActivity extends Activity implements OnClickListener {
((TextView)findViewById(R.id.features)).setText(String.format("%d / %s", featuresExtracted, mMaxFeaturesValues[mParamMaxFeaturesIndex]));
((TextView)findViewById(R.id.update_time)).setText(String.format("%.3f / %s", updateTime, mTimeThrValues[mParamTimeThrMsIndex]));
((TextView)findViewById(R.id.hypothesis)).setText(String.format("%.3f / %s (%d)", hypothesis, mLoopThrValues[mParamLoopThrMsIndex], loopClosureId>0?loopClosureId:highestHypId));
((TextView)findViewById(R.id.fps)).setText(String.format("%.3f Hz", fps));
if(mItemPause!=null && !mItemPause.isChecked())
{
if(loopClosureId > 0)
@@ -367,13 +388,14 @@ public class RTABMapActivity extends Activity implements OnClickListener {
final int features,
final float hypothesis,
final int nodesDrawn,
final float fps,
final int rejected)
{
Log.i(TAG, String.format("updateStatsCallback()"));
runOnUiThread(new Runnable() {
public void run() {
updateStatsUI(nodes, words, points, polygons, updateTime, loopClosureId, highestHypId, databaseMemoryUsed, inliers, features, hypothesis, nodesDrawn, rejected);
updateStatsUI(nodes, words, points, polygons, updateTime, loopClosureId, highestHypId, databaseMemoryUsed, inliers, features, hypothesis, nodesDrawn, fps, rejected);
}
});
}
@@ -469,6 +491,7 @@ public class RTABMapActivity extends Activity implements OnClickListener {
((TextView)findViewById(R.id.features)).setText(String.valueOf(0));
((TextView)findViewById(R.id.update_time)).setText(String.valueOf(0));
((TextView)findViewById(R.id.hypothesis)).setText(String.valueOf(0));
((TextView)findViewById(R.id.fps)).setText(String.valueOf(0));
mTotalLoopClosures = 0;
((TextView)findViewById(R.id.total_loop)).setText(String.valueOf(mTotalLoopClosures));
@@ -764,6 +787,10 @@ public class RTABMapActivity extends Activity implements OnClickListener {
{
item.setChecked(!item.isChecked());
RTABMapLib.setAutoExposure(item.isChecked());
// restart Tango service
onPause();
onResume();
}
else if(itemId == R.id.resolution)
{
@@ -1024,6 +1051,7 @@ public class RTABMapActivity extends Activity implements OnClickListener {
((TextView)findViewById(R.id.features)).setText(String.valueOf(0));
((TextView)findViewById(R.id.update_time)).setText(String.valueOf(0));
((TextView)findViewById(R.id.hypothesis)).setText(String.valueOf(0));
((TextView)findViewById(R.id.fps)).setText(String.valueOf(0));
mTotalLoopClosures = 0;
((TextView)findViewById(R.id.total_loop)).setText(String.valueOf(mTotalLoopClosures));

View File

@@ -1,6 +1,8 @@
package com.introlab.rtabmap;
import android.os.IBinder;
import android.view.KeyEvent;
import android.util.Log;
// Wrapper for native library
@@ -8,19 +10,29 @@ import android.view.KeyEvent;
public class RTABMapLib
{
static
{
System.loadLibrary("NativeRTABMap");
static {
// This project depends on tango_client_api, so we need to make sure we load
// the correct library first.
if (TangoInitializationHelper.loadTangoSharedLibrary() ==
TangoInitializationHelper.ARCH_ERROR) {
Log.e(RTABMapActivity.class.getSimpleName(), "ERROR! Unable to load libtango_client_api.so!");
}
System.loadLibrary("NativeRTABMap");
}
// Initialize the Tango Service, this function starts the communication
// between the application and Tango Service.
// The activity object is used for checking if the API version is outdated.
public static native int initialize(RTABMapActivity activity);
public static native void onCreate(RTABMapActivity activity);
public static native void openDatabase(String databasePath);
public static native int onResume();
/*
* Called when the Tango service is connected.
*
* @param binder The native binder object.
*/
public static native boolean onTangoServiceConnected(IBinder binder);
// Release all non OpenGl resources that are allocated from the program.
public static native void onPause();

View File

@@ -0,0 +1,136 @@
/*
* Copyright 2016 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copied for convenience from https://github.com/googlesamples/tango-examples-c/blob/master/cpp_example_util/app/src/main/java/com/projecttango/examples/cpp/util/TangoInitializationHelper.java
*/
package com.introlab.rtabmap;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Build;
import android.os.IBinder;
import android.util.Log;
import java.io.File;
/**
* Functions for simplifying the process of initializing TangoService, and function
* handles loading correct libtango_client_api.so.
*/
public class TangoInitializationHelper {
public static final int ARCH_ERROR = -2;
public static final int ARCH_FALLBACK = -1;
public static final int ARCH_DEFAULT = 0;
public static final int ARCH_ARM64 = 1;
public static final int ARCH_ARM32 = 2;
public static final int ARCH_X86_64 = 3;
public static final int ARCH_X86 = 4;
/**
* Only for apps using the C API:
* Initializes the underlying TangoService for native apps.
*
* @return returns false if the device doesn't have the Tango running as Android Service.
* Otherwise ture.
*/
public static final boolean bindTangoService(final Context context,
ServiceConnection connection) {
Intent intent = new Intent();
intent.setClassName("com.google.tango", "com.google.atap.tango.TangoService");
boolean hasJavaService = (context.getPackageManager().resolveService(intent, 0) != null);
// User doesn't have the latest packagename for TangoCore, fallback to the previous name.
if (!hasJavaService) {
intent = new Intent();
intent.setClassName("com.projecttango.tango", "com.google.atap.tango.TangoService");
hasJavaService = (context.getPackageManager().resolveService(intent, 0) != null);
}
// User doesn't have a Java-fied TangoCore at all; fallback to the deprecated approach
// of doing nothing and letting the native side auto-init to the system-service version
// of Tango.
if (!hasJavaService) {
return false;
}
return context.bindService(intent, connection, Context.BIND_AUTO_CREATE);
}
/**
* Load the libtango_client_api.so library based on different Tango device setup.
*
* @return returns the loaded architecture id.
*/
public static final int loadTangoSharedLibrary() {
int loadedSoId = ARCH_ERROR;
String basePath = "/data/data/com.google.tango/libfiles/";
if (!(new File(basePath).exists())) {
basePath = "/data/data/com.projecttango.tango/libfiles/";
}
Log.i("TangoInitializationHelper", "basePath: " + basePath);
try {
System.load(basePath + "arm64-v8a/libtango_client_api.so");
loadedSoId = ARCH_ARM64;
Log.i("TangoInitializationHelper", "Success! Using arm64-v8a/libtango_client_api.");
} catch (UnsatisfiedLinkError e) {
}
if (loadedSoId < ARCH_DEFAULT) {
try {
System.load(basePath + "armeabi-v7a/libtango_client_api.so");
loadedSoId = ARCH_ARM32;
Log.i("TangoInitializationHelper", "Success! Using armeabi-v7a/libtango_client_api.");
} catch (UnsatisfiedLinkError e) {
}
}
if (loadedSoId < ARCH_DEFAULT) {
try {
System.load(basePath + "x86_64/libtango_client_api.so");
loadedSoId = ARCH_X86_64;
Log.i("TangoInitializationHelper", "Success! Using x86_64/libtango_client_api.");
} catch (UnsatisfiedLinkError e) {
}
}
if (loadedSoId < ARCH_DEFAULT) {
try {
System.load(basePath + "x86/libtango_client_api.so");
loadedSoId = ARCH_X86;
Log.i("TangoInitializationHelper", "Success! Using x86/libtango_client_api.");
} catch (UnsatisfiedLinkError e) {
}
}
if (loadedSoId < ARCH_DEFAULT) {
try {
System.load(basePath + "default/libtango_client_api.so");
loadedSoId = ARCH_DEFAULT;
Log.i("TangoInitializationHelper", "Success! Using default/libtango_client_api.");
} catch (UnsatisfiedLinkError e) {
}
}
if (loadedSoId < ARCH_DEFAULT) {
try {
System.loadLibrary("tango_client_api");
loadedSoId = ARCH_FALLBACK;
Log.i("TangoInitializationHelper", "Falling back to libtango_client_api.so symlink.");
} catch (UnsatisfiedLinkError e) {
}
}
return loadedSoId;
}
}

View File

@@ -137,11 +137,25 @@ IF((APPLE AND BUILD_AS_BUNDLE) OR WIN32)
# Install needed Qt plugins by copying directories from the qt installation
# One can cull what gets copied by using 'REGEX "..." EXCLUDE'
# Exclude debug libraries
INSTALL(DIRECTORY "${QT_PLUGINS_DIR}/imageformats"
IF(QT_PLUGINS_DIR)
INSTALL(DIRECTORY "${QT_PLUGINS_DIR}/imageformats"
DESTINATION ${plugin_dest_dir}/plugins
COMPONENT runtime
REGEX ".*d4.dll" EXCLUDE
REGEX ".*d4.a" EXCLUDE)
ELSE()
#Qt5
foreach(plugin ${Qt5Gui_PLUGINS})
get_target_property(plugin_loc ${plugin} LOCATION)
get_filename_component(plugin_dir ${plugin_loc} DIRECTORY)
string(REPLACE "plugins" ";" loc_list ${plugin_dir})
list(GET loc_list 1 plugin_type)
#MESSAGE(STATUS "Qt5 plugin \"${plugin_loc}\" installed in \"${plugin_dest_dir}/plugins${plugin_type}\"")
INSTALL(FILES ${plugin_loc}
DESTINATION ${plugin_dest_dir}/plugins${plugin_type}
COMPONENT runtime)
endforeach()
ENDIF()
# install a qt.conf file
# this inserts some cmake code into the install script to write the file

View File

@@ -39,6 +39,14 @@ namespace FlyCapture2
class Camera;
}
namespace sl
{
namespace zed
{
class Camera;
}
}
namespace rtabmap
{
@@ -94,6 +102,52 @@ private:
void * triclopsCtx_; // TriclopsContext
};
/////////////////////////
// CameraStereoZED
/////////////////////////
class RTABMAP_EXP CameraStereoZed :
public Camera
{
public:
static bool available();
public:
CameraStereoZed(
int deviceId,
int resolution = 2, // 0=HD2K, 1=HD1080, 2=HD720, 3=VGA
int quality = 1, // 0=NONE, 1=PERFORMANCE, 2=QUALITY
int sensingMode = 1,// 0=FULL, 1=RAW
int confidenceThr = 100,
float imageRate=0.0f,
const Transform & localTransform = Transform::getIdentity());
CameraStereoZed(
const std::string & svoFilePath,
int quality = 1, // 0=NONE, 1=PERFORMANCE, 2=QUALITY
int sensingMode = 1,// 0=FULL, 1=RAW
int confidenceThr = 100,
float imageRate=0.0f,
const Transform & localTransform = Transform::getIdentity());
virtual ~CameraStereoZed();
virtual bool init(const std::string & calibrationFolder = ".", const std::string & cameraName = "");
virtual bool isCalibrated() const;
virtual std::string getSerial() const;
protected:
virtual SensorData captureImage();
private:
sl::zed::Camera * zed_;
StereoCameraModel stereoModel_;
CameraVideo::Source src_;
int usbDevice_;
std::string svoFilePath_;
int resolution_;
int quality_;
int sensingMode_;
int confidenceThr_;
};
/////////////////////////
// CameraStereoImages
/////////////////////////
@@ -147,6 +201,10 @@ public:
bool rectifyImages = false,
float imageRate=0.0f,
const Transform & localTransform = Transform::getIdentity());
CameraStereoVideo(
int device,
float imageRate = 0.0f,
const Transform & localTransform = Transform::getIdentity());
virtual ~CameraStereoVideo();
virtual bool init(const std::string & calibrationFolder = ".", const std::string & cameraName = "");
@@ -162,6 +220,8 @@ private:
bool rectifyImages_;
StereoCameraModel stereoModel_;
std::string cameraName_;
CameraVideo::Source src_;
int usbDevice_;
};
} // namespace rtabmap

View File

@@ -79,6 +79,13 @@ std::multimap<int, int>::const_iterator RTABMAP_EXP findLink(
int to,
bool checkBothWays = true);
std::multimap<int, Link> RTABMAP_EXP filterLinks(
const std::multimap<int, Link> & links,
Link::Type filteredType);
std::map<int, Link> RTABMAP_EXP filterLinks(
const std::map<int, Link> & links,
Link::Type filteredType);
//Note: This assumes a coordinate system where X is forward, * Y is up, and Z is right.
std::map<int, Transform> RTABMAP_EXP frustumPosesFiltering(
const std::map<int, Transform> & poses,

View File

@@ -55,7 +55,7 @@ private:
Registration * registrationPipeline_;
Signature refFrame_;
Transform motionSinceLastKeyFrame_;
Transform lastKeyFramePose_;
};
}

View File

@@ -221,9 +221,9 @@ class RTABMAP_EXP Parameters
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.)");
#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.");
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.");
#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.");
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.");
#endif
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.");
@@ -323,7 +323,6 @@ class RTABMAP_EXP Parameters
// Local/Proximity loop closure detection
RTABMAP_PARAM(RGBD, ProximityByTime, bool, false, "Detection over all locations in STM.");
RTABMAP_PARAM(RGBD, ProximityBySpace, bool, true, "Detection over locations (in Working Memory or STM) near in space.");
RTABMAP_PARAM(RGBD, ProximityPathScansMerged, bool, true, "Merge close laser scans on each path. If false, only the nearest laser scan on the path is used for ICP.");
RTABMAP_PARAM(RGBD, ProximityMaxGraphDepth, int, 50, "Maximum depth from the current/last loop closure location and the local loop closure hypotheses. Set 0 to ignore.");
RTABMAP_PARAM(RGBD, ProximityPathFilteringRadius, float, 0.5, "Path filtering radius.");
RTABMAP_PARAM(RGBD, ProximityPathRawPosesUsed, bool, true, "When comparing to a local path, merge the scan using the odometry poses (with neighbor link optimizations) instead of the ones in the optimized local graph.");
@@ -397,7 +396,17 @@ class RTABMAP_EXP Parameters
RTABMAP_PARAM(Vis, EpipolarGeometryVar, float, 0.02, "[Vis/EstimationType = 2] Epipolar geometry maximum variance to accept the transformation.");
RTABMAP_PARAM(Vis, MinInliers, int, 20, "Minimum feature correspondences to compute/accept the transformation.");
RTABMAP_PARAM(Vis, Iterations, int, 100, "Maximum iterations to compute the transform.");
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.");
#ifndef RTABMAP_NONFREE
#ifdef RTABMAP_OPENCV3
// 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.");
#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.");
#endif
#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.");
#endif
RTABMAP_PARAM(Vis, MaxFeatures, int, 1000, "0 no limits.");
RTABMAP_PARAM(Vis, MaxDepth, float, 0.0, "Max depth of the features (0 means no limit).");
RTABMAP_PARAM(Vis, MinDepth, float, 0.0, "Min depth of the features (0 means no limit).");

View File

@@ -196,7 +196,6 @@ private:
int _proximityMaxGraphDepth;
float _proximityFilteringRadius;
bool _proximityRawPosesUsed;
bool _proximityScansMerged;
float _proximityAngle;
std::string _databasePath;
bool _optimizeFromGraphEnd;

View File

@@ -28,10 +28,15 @@ void segmentObstaclesFromGround(
float clusterRadius,
int minClusterSize,
bool segmentFlatObstacles,
float maxGroundHeight)
float maxGroundHeight,
pcl::IndicesPtr * flatObstacles)
{
ground.reset(new std::vector<int>);
obstacles.reset(new std::vector<int>);
if(flatObstacles)
{
flatObstacles->reset(new std::vector<int>);
}
if(cloud->size())
{
@@ -71,10 +76,15 @@ void segmentObstaclesFromGround(
{
Eigen::Vector4f centroid;
pcl::compute3DCentroid(*cloud, *clusteredFlatSurfaces.at(i), centroid);
if(centroid[2] >= min[2] && centroid[2] <= max[2])
if(centroid[2] >= min[2]-0.01 &&
(centroid[2] <= max[2]+0.01 || (maxGroundHeight>0 && centroid[2] <= maxGroundHeight+0.01))) // epsilon
{
ground = util3d::concatenate(ground, clusteredFlatSurfaces.at(i));
}
else if(flatObstacles)
{
*flatObstacles = util3d::concatenate(*flatObstacles, clusteredFlatSurfaces.at(i));
}
}
}
}
@@ -82,6 +92,10 @@ void segmentObstaclesFromGround(
{
// reject ground!
ground.reset(new std::vector<int>);
if(flatObstacles)
{
*flatObstacles = flatSurfaces;
}
}
}
}
@@ -95,15 +109,24 @@ void segmentObstaclesFromGround(
// Remove ground
pcl::IndicesPtr otherStuffIndices = util3d::extractIndices(cloud, ground, true);
//Cluster remaining stuff (obstacles)
std::vector<pcl::IndicesPtr> clusteredObstaclesSurfaces = util3d::extractClusters(
cloud,
otherStuffIndices,
clusterRadius,
minClusterSize);
// If ground height is set, remove obstacles under it
if(maxGroundHeight > 0.0f)
{
otherStuffIndices = rtabmap::util3d::passThrough(cloud, otherStuffIndices, "z", maxGroundHeight, std::numeric_limits<float>::max());
}
// merge indices
obstacles = util3d::concatenate(clusteredObstaclesSurfaces);
//Cluster remaining stuff (obstacles)
if(otherStuffIndices->size())
{
std::vector<pcl::IndicesPtr> clusteredObstaclesSurfaces = util3d::extractClusters(
cloud,
otherStuffIndices,
clusterRadius,
minClusterSize);
// merge indices
obstacles = util3d::concatenate(clusteredObstaclesSurfaces);
}
}
}
}
@@ -118,7 +141,8 @@ void segmentObstaclesFromGround(
float clusterRadius,
int minClusterSize,
bool segmentFlatObstacles,
float maxGroundHeight)
float maxGroundHeight,
pcl::IndicesPtr * flatObstacles)
{
pcl::IndicesPtr indices(new std::vector<int>);
segmentObstaclesFromGround<PointT>(
@@ -131,7 +155,8 @@ void segmentObstaclesFromGround(
clusterRadius,
minClusterSize,
segmentFlatObstacles,
maxGroundHeight);
maxGroundHeight,
flatObstacles);
}
template<typename PointT>

View File

@@ -32,6 +32,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <opencv2/core/core.hpp>
#include <rtabmap/core/Transform.h>
#include <rtabmap/core/Parameters.h>
namespace rtabmap
{
@@ -68,7 +69,7 @@ void RTABMAP_EXP calcOpticalFlowPyrLKStereo( cv::InputArray _prevImg, cv::InputA
cv::Mat RTABMAP_EXP disparityFromStereoImages(
const cv::Mat & leftImage,
const cv::Mat & rightImage,
int type = CV_32FC1); // CV_32FC1 or CV_16SC1
const ParametersMap & parameters = ParametersMap());
cv::Mat RTABMAP_EXP depthFromDisparity(const cv::Mat & disparity,
float fx, float baseline,

View File

@@ -36,6 +36,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <pcl/TextureMesh.h>
#include <rtabmap/core/Transform.h>
#include <rtabmap/core/SensorData.h>
#include <rtabmap/core/Parameters.h>
#include <opencv2/core/core.hpp>
#include <map>
#include <list>
@@ -116,14 +117,16 @@ pcl::PointCloud<pcl::PointXYZRGB>::Ptr RTABMAP_EXP cloudFromStereoImages(
int decimation = 1,
float maxDepth = 0.0f,
float minDepth = 0.0f,
std::vector<int> * validIndices = 0);
std::vector<int> * validIndices = 0,
const ParametersMap & parameters = ParametersMap());
pcl::PointCloud<pcl::PointXYZ>::Ptr RTABMAP_EXP cloudFromSensorData(
const SensorData & sensorData,
int decimation = 1,
float maxDepth = 0.0f,
float minDepth = 0.0f,
std::vector<int> * validIndices = 0);
std::vector<int> * validIndices = 0,
const ParametersMap & parameters = ParametersMap());
/**
* Create an RGB cloud from the images contained in SensorData. If there is only one camera,
@@ -143,7 +146,8 @@ pcl::PointCloud<pcl::PointXYZRGB>::Ptr RTABMAP_EXP cloudRGBFromSensorData(
int decimation = 1,
float maxDepth = 0.0f,
float minDepth = 0.0f,
std::vector<int> * validIndices = 0);
std::vector<int> * validIndices = 0,
const ParametersMap & parameters = ParametersMap());
pcl::PointCloud<pcl::PointXYZ> RTABMAP_EXP laserScanFromDepthImage(
const cv::Mat & depthImage,

View File

@@ -108,6 +108,20 @@ pcl::PointCloud<pcl::PointXYZRGB>::Ptr RTABMAP_EXP randomSampling(
int samples);
pcl::IndicesPtr RTABMAP_EXP passThrough(
const pcl::PointCloud<pcl::PointXYZ>::Ptr & cloud,
const pcl::IndicesPtr & indices,
const std::string & axis,
float min,
float max,
bool negative = false);
pcl::IndicesPtr RTABMAP_EXP passThrough(
const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloud,
const pcl::IndicesPtr & indices,
const std::string & axis,
float min,
float max,
bool negative = false);
pcl::PointCloud<pcl::PointXYZ>::Ptr RTABMAP_EXP passThrough(
const pcl::PointCloud<pcl::PointXYZ>::Ptr & cloud,
const std::string & axis,

View File

@@ -91,7 +91,8 @@ void segmentObstaclesFromGround(
float clusterRadius,
int minClusterSize,
bool segmentFlatObstacles = false,
float maxGroundHeight = 0.0f);
float maxGroundHeight = 0.0f,
pcl::IndicesPtr * flatObstacles = 0);
template<typename PointT>
void segmentObstaclesFromGround(
const typename pcl::PointCloud<PointT>::Ptr & cloud,
@@ -102,7 +103,8 @@ void segmentObstaclesFromGround(
float clusterRadius,
int minClusterSize,
bool segmentFlatObstacles = false,
float maxGroundHeight = 0.0f);
float maxGroundHeight = 0.0f,
pcl::IndicesPtr * flatObstacles = 0);
template<typename PointT>
void occupancy2DFromCloud3D(

View File

@@ -188,10 +188,17 @@ IF(G2O_FOUND)
ENDIF(G2O_FOUND)
IF(GTSAM_FOUND)
SET(INCLUDE_DIRS
${INCLUDE_DIRS}
${GTSAM_INCLUDE_DIRS}
)
IF(GTSAM_INCLUDE_DIR)
SET(INCLUDE_DIRS
${GTSAM_INCLUDE_DIR} # place it in front to use Eigen installed by GTSAM
${INCLUDE_DIRS}
)
ELSE()
SET(INCLUDE_DIRS
${GTSAM_INCLUDE_DIRS} # cmake standard
${INCLUDE_DIRS}
)
ENDIF()
SET(LIBRARIES
${LIBRARIES}
gtsam
@@ -209,6 +216,27 @@ IF(cvsba_FOUND)
)
ENDIF(cvsba_FOUND)
IF(ZED_FOUND)
SET(INCLUDE_DIRS
${INCLUDE_DIRS}
${ZED_INCLUDE_DIRS}
)
SET(LIBRARIES
${LIBRARIES}
${ZED_LIBRARIES}
)
IF(CUDA_FOUND)
SET(INCLUDE_DIRS
${INCLUDE_DIRS}
${CUDA_INCLUDE_DIRS}
)
SET(LIBRARIES
${LIBRARIES}
${CUDA_LIBRARIES}
)
ENDIF(CUDA_FOUND)
ENDIF(ZED_FOUND)
####################################
# Generate resources files
####################################

View File

@@ -722,7 +722,7 @@ CameraVideo::~CameraVideo()
bool CameraVideo::init(const std::string & calibrationFolder, const std::string & cameraName)
{
_guid.clear();
_guid = cameraName;
if(_capture.isOpened())
{
_capture.release();
@@ -750,19 +750,22 @@ bool CameraVideo::init(const std::string & calibrationFolder, const std::string
}
else
{
unsigned int guid = (unsigned int)_capture.get(CV_CAP_PROP_GUID);
if(guid != 0 && guid != 0xffffffff)
if (_guid.empty())
{
_guid = uFormat("%08x", guid);
unsigned int guid = (unsigned int)_capture.get(CV_CAP_PROP_GUID);
if (guid != 0 && guid != 0xffffffff)
{
_guid = uFormat("%08x", guid);
}
}
// look for calibration files
if(!calibrationFolder.empty() && (!_guid.empty() || !cameraName.empty()))
if(!calibrationFolder.empty() && !_guid.empty())
{
if(!_model.load(calibrationFolder, (cameraName.empty()?_guid:cameraName)))
if(!_model.load(calibrationFolder, _guid))
{
UWARN("Missing calibration files for camera \"%s\" in \"%s\" folder, you should calibrate the camera!",
cameraName.empty()?_guid.c_str():cameraName.c_str(), calibrationFolder.c_str());
_guid.c_str(), calibrationFolder.c_str());
}
else
{

View File

@@ -48,6 +48,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <fc2triclops.h>
#endif
#ifdef RTABMAP_ZED
#include <zed/Camera.hpp>
#endif
namespace rtabmap
{
@@ -731,6 +735,214 @@ SensorData CameraStereoFlyCapture2::captureImage()
return data;
}
//
// CameraStereoZED
//
bool CameraStereoZed::available()
{
#ifdef RTABMAP_ZED
return true;
#else
return false;
#endif
}
CameraStereoZed::CameraStereoZed(
int deviceId,
int resolution,
int quality,
int sensingMode,
int confidenceThr,
float imageRate,
const Transform & localTransform) :
Camera(imageRate, localTransform),
zed_(0),
src_(CameraVideo::kUsbDevice),
usbDevice_(deviceId),
svoFilePath_(""),
resolution_(resolution),
quality_(quality),
sensingMode_(sensingMode),
confidenceThr_(confidenceThr)
{
#ifdef RTABMAP_ZED
UASSERT(resolution_ >= sl::zed::HD2K && resolution_ <=sl::zed::VGA);
UASSERT(quality_ >= sl::zed::NONE && quality_ <=sl::zed::QUALITY);
UASSERT(sensingMode_ >= sl::zed::FULL && sensingMode_ <=sl::zed::RAW);
UASSERT(confidenceThr_ >= 0 && confidenceThr_ <=100);
#endif
}
CameraStereoZed::CameraStereoZed(
const std::string & filePath,
int quality,
int sensingMode,
int confidenceThr,
float imageRate,
const Transform & localTransform) :
Camera(imageRate, localTransform),
zed_(0),
src_(CameraVideo::kVideoFile),
usbDevice_(0),
svoFilePath_(filePath),
resolution_(2),
quality_(quality),
sensingMode_(sensingMode),
confidenceThr_(confidenceThr)
{
#ifdef RTABMAP_ZED
UASSERT(resolution_ >= sl::zed::HD2K && resolution_ <=sl::zed::VGA);
UASSERT(quality_ >= sl::zed::NONE && quality_ <=sl::zed::QUALITY);
UASSERT(sensingMode_ >= sl::zed::FULL && sensingMode_ <=sl::zed::RAW);
UASSERT(confidenceThr_ >= 0 && confidenceThr_ <=100);
#endif
}
CameraStereoZed::~CameraStereoZed()
{
#ifdef RTABMAP_ZED
if(zed_)
{
delete zed_;
}
#endif
}
bool CameraStereoZed::init(const std::string & calibrationFolder, const std::string & cameraName)
{
#ifdef RTABMAP_ZED
if(zed_)
{
delete zed_;
zed_ = 0;
}
if(src_ == CameraVideo::kVideoFile)
{
zed_ = new sl::zed::Camera(svoFilePath_); // Use in SVO playback mode
}
else
{
if(zed_->isZEDconnected())
{
zed_ = new sl::zed::Camera((sl::zed::ZEDResolution_mode)resolution_, getImageRate(), usbDevice_); // Use in Live Mode
}
else
{
UERROR("ZED camera initialization failed: ZED is not connected!");
return false;
}
}
//init WITH self-calibration (- last parameter to false -)
sl::zed::ERRCODE err = zed_->init(
(sl::zed::MODE)quality_,
-1, // search for any GPU
true, false, false);
// Quit if an error occurred
if (err != sl::zed::SUCCESS)
{
UERROR("ZED camera initialization failed: %s", sl::zed::errcode2str(err).c_str());
delete zed_;
zed_ = 0;
return false;
}
zed_->setConfidenceThreshold(confidenceThr_);
sl::zed::StereoParameters * stereoParams = zed_->getParameters();
sl::zed::resolution res = zed_->getImageSize();
stereoModel_ = StereoCameraModel(
stereoParams->LeftCam.fx,
stereoParams->LeftCam.fy,
stereoParams->LeftCam.cx,
stereoParams->LeftCam.cy,
stereoParams->baseline/1000.0f,
this->getLocalTransform(),
cv::Size(res.width, res.height));
return true;
#else
UERROR("CameraStereoZED: RTAB-Map is not built with ZED sdk support!");
#endif
return false;
}
bool CameraStereoZed::isCalibrated() const
{
return stereoModel_.isValidForProjection();
}
std::string CameraStereoZed::getSerial() const
{
#ifdef RTABMAP_ZED
if(zed_)
{
return uFormat("%x", zed_->getZEDSerial());
}
#endif
return "";
}
SensorData CameraStereoZed::captureImage()
{
SensorData data;
#ifdef RTABMAP_ZED
if(zed_)
{
UTimer timer;
bool res = zed_->grab((sl::zed::SENSING_MODE)sensingMode_, quality_ > 0, quality_ > 0, false);
while (src_ == CameraVideo::kUsbDevice && res && timer.elapsed() < 2.0)
{
// maybe there is a latency with the USB, try again in 10 ms (for the next 2 seconds)
uSleep(10);
res = zed_->grab((sl::zed::SENSING_MODE)sensingMode_, quality_ > 0, quality_ > 0, false);
}
if(!res)
{
// get left image
cv::Mat rgbaLeft = slMat2cvMat(zed_->retrieveImage(static_cast<sl::zed::SIDE> (sl::zed::STEREO_LEFT)));
cv::Mat left;
cv::cvtColor(rgbaLeft, left, cv::COLOR_BGRA2BGR);
if(quality_ > 0)
{
// get depth image
cv::Mat depth;
slMat2cvMat(zed_->retrieveMeasure(sl::zed::MEASURE::DEPTH)).copyTo(depth);
depth /= 1000.0; // to meters
data = SensorData(left, depth, stereoModel_.left(), this->getNextSeqID(), UTimer::now());
}
else
{
// get right image
cv::Mat rgbaRight = slMat2cvMat(zed_->retrieveImage(static_cast<sl::zed::SIDE> (sl::zed::STEREO_RIGHT)));
cv::Mat right;
cv::cvtColor(rgbaRight, right, cv::COLOR_BGRA2GRAY);
data = SensorData(left, right, stereoModel_, this->getNextSeqID(), UTimer::now());
}
}
else if(src_ == CameraVideo::kUsbDevice)
{
UERROR("CameraStereoZed: Failed to grab images after 2 seconds!");
}
else
{
UWARN("CameraStereoZed: end of stream is reached!");
}
}
#else
UERROR("CameraStereoZED: RTAB-Map is not built with ZED sdk support!");
#endif
return data;
}
//
// CameraStereoImages
//
@@ -921,7 +1133,21 @@ CameraStereoVideo::CameraStereoVideo(
const Transform & localTransform) :
Camera(imageRate, localTransform),
path_(path),
rectifyImages_(rectifyImages)
rectifyImages_(rectifyImages),
src_(CameraVideo::kVideoFile),
usbDevice_(0)
{
}
CameraStereoVideo::CameraStereoVideo(
int device,
float imageRate,
const Transform & localTransform) :
Camera(imageRate, localTransform),
path_(""),
rectifyImages_(false),
src_(CameraVideo::kUsbDevice),
usbDevice_(device)
{
}
@@ -932,29 +1158,51 @@ CameraStereoVideo::~CameraStereoVideo()
bool CameraStereoVideo::init(const std::string & calibrationFolder, const std::string & cameraName)
{
cameraName_ = cameraName;
if(capture_.isOpened())
{
capture_.release();
}
ULOGGER_DEBUG("Camera: filename=\"%s\"", path_.c_str());
capture_.open(path_.c_str());
if (src_ == CameraVideo::kUsbDevice)
{
ULOGGER_DEBUG("CameraStereoVideo: Usb device initialization on device %d", usbDevice_);
capture_.open(usbDevice_);
}
else if (src_ == CameraVideo::kVideoFile)
{
ULOGGER_DEBUG("CameraStereoVideo: filename=\"%s\"", path_.c_str());
capture_.open(path_.c_str());
}
else
{
ULOGGER_ERROR("CameraStereoVideo: Unknown source...");
}
if(!capture_.isOpened())
{
ULOGGER_ERROR("Camera: Failed to create a capture object!");
ULOGGER_ERROR("CameraStereoVideo: Failed to create a capture object!");
capture_.release();
return false;
}
else
{
// look for calibration files
cameraName_ = cameraName;
if(!calibrationFolder.empty() && !cameraName.empty())
if (cameraName_.empty())
{
if(!stereoModel_.load(calibrationFolder, cameraName))
unsigned int guid = (unsigned int)capture_.get(CV_CAP_PROP_GUID);
if (guid != 0 && guid != 0xffffffff)
{
cameraName_ = uFormat("%08x", guid);
}
}
// look for calibration files
if(!calibrationFolder.empty() && !cameraName_.empty())
{
if(!stereoModel_.load(calibrationFolder, cameraName_))
{
UWARN("Missing calibration files for camera \"%s\" in \"%s\" folder, you should calibrate the camera!",
cameraName.c_str(), calibrationFolder.c_str());
cameraName_.c_str(), calibrationFolder.c_str());
}
else
{
@@ -1007,7 +1255,7 @@ SensorData CameraStereoVideo::captureImage()
rightCvt = true;
}
if(rectifyImages_ && stereoModel_.left().isValidForRectification() && stereoModel_.right().isValidForRectification())
if((src_ != CameraVideo::kVideoFile || rectifyImages_) && stereoModel_.left().isValidForRectification() && stereoModel_.right().isValidForRectification())
{
leftImage = stereoModel_.left().rectifyImage(leftImage);
rightImage = stereoModel_.right().rectifyImage(rightImage);

View File

@@ -308,10 +308,9 @@ cv::Rect Feature2D::computeRoi(const cv::Mat & image, const std::vector<float> &
}
//right roi
roi.width = width - roi.x;
if(roiRatios[1] > 0 && roiRatios[1] < 1 - roiRatios[0])
{
roi.width -= width * roiRatios[1];
roi.width -= width * roiRatios[1] + width * roiRatios[0];
}
//top roi
@@ -321,10 +320,9 @@ cv::Rect Feature2D::computeRoi(const cv::Mat & image, const std::vector<float> &
}
//bottom roi
roi.height = height - roi.y;
if(roiRatios[3] > 0 && roiRatios[3] < 1 - roiRatios[2])
{
roi.height -= height * roiRatios[3];
roi.height -= height * roiRatios[3] + height * roiRatios[2];
}
UDEBUG("roi = %d, %d, %d, %d", roi.x, roi.y, roi.width, roi.height);

View File

@@ -561,6 +561,36 @@ std::multimap<int, int>::const_iterator findLink(
return links.end();
}
std::multimap<int, Link> filterLinks(
const std::multimap<int, Link> & links,
Link::Type filteredType)
{
std::multimap<int, Link> output;
for(std::multimap<int, Link>::const_iterator iter=links.begin(); iter!=links.end(); ++iter)
{
if(iter->second.type() != filteredType)
{
output.insert(*iter);
}
}
return output;
}
std::map<int, Link> filterLinks(
const std::map<int, Link> & links,
Link::Type filteredType)
{
std::map<int, Link> output;
for(std::map<int, Link>::const_iterator iter=links.begin(); iter!=links.end(); ++iter)
{
if(iter->second.type() != filteredType)
{
output.insert(*iter);
}
}
return output;
}
std::map<int, Transform> frustumPosesFiltering(
const std::map<int, Transform> & poses,
const Transform & cameraPose,

View File

@@ -495,7 +495,8 @@ void Memory::parseParameters(const ParametersMap & parameters)
if((_memoryChanged || _linksChanged) && _dbDriver)
{
UWARN("Switching from Mapping to Localization mode, the database will be saved and reloaded.");
this->init(_dbDriver->getUrl());
this->init(_dbDriver->getUrl());
UWARN("Switching from Mapping to Localization mode, the database is reloaded!");
}
}
_incrementalMemory = value;
@@ -1901,6 +1902,7 @@ bool Memory::labelSignature(int id, const std::string & label)
if(s)
{
s->setLabel(label);
_linksChanged = s->isSaved(); // HACK to get label updated in Localization mode
UWARN("Label \"%s\" set to node %d", label.c_str(), id);
return true;
}
@@ -2122,28 +2124,13 @@ Transform Memory::computeTransform(
// compute transform fromId -> toId
std::vector<int> inliersV;
if(_reextractLoopClosureFeatures || (fromS.getWords().size() && toS.getWords().size()))
if(_reextractLoopClosureFeatures ||
(fromS.getWords().size() && toS.getWords().size()) ||
(!guess.isNull() && !_registrationPipeline->isImageRequired()))
{
Signature tmpFrom = fromS;
Signature tmpTo = toS;
// make a guess fast with known correspondences (if there are)
RegistrationVis regVis(parameters_);
if(tmpFrom.getWords().size() &&
tmpTo.getWords().size() &&
tmpFrom.getWords3().size() &&
tmpTo.getWords3().size())
{
UDEBUG("");
// Remove descriptors, this will avoid recomputation of the correspondences in regVis
tmpFrom.setWordsDescriptors(std::multimap<int, cv::Mat>());
tmpTo.setWordsDescriptors(std::multimap<int, cv::Mat>());
guess = regVis.computeTransformation(tmpFrom, tmpTo, guess, info);
// set back descriptors
tmpFrom.setWordsDescriptors(fromS.getWordsDescriptors());
tmpTo.setWordsDescriptors(toS.getWordsDescriptors());
}
if(_reextractLoopClosureFeatures)
{
UDEBUG("");
@@ -2157,44 +2144,33 @@ Transform Memory::computeTransform(
tmpTo.sensorData().setFeatures(std::vector<cv::KeyPoint>(), cv::Mat());
}
if(guess.isNull())
{
if(!_registrationPipeline->isImageRequired())
{
UDEBUG("");
// no visual in the pipeline, make visual registration for guess
guess = regVis.computeTransformation(tmpFrom, tmpTo, guess, info);
}
else
{
UDEBUG("");
guess.setIdentity();
}
}
if(!guess.isNull())
if(guess.isNull() && !_registrationPipeline->isImageRequired())
{
UDEBUG("");
transform = _registrationPipeline->computeTransformation(tmpFrom, tmpTo, guess, info);
// no visual in the pipeline, make visual registration for guess
RegistrationVis regVis(parameters_);
guess = regVis.computeTransformation(tmpFrom, tmpTo, guess, info);
}
if(!transform.isNull())
transform = _registrationPipeline->computeTransformation(tmpFrom, tmpTo, guess, info);
if(!transform.isNull())
{
UDEBUG("");
// verify if it is a 180 degree transform, well verify > 90
float x,y,z, roll,pitch,yaw;
transform.getTranslationAndEulerAngles(x,y,z, roll,pitch,yaw);
if(fabs(roll) > CV_PI/2 ||
fabs(pitch) > CV_PI/2 ||
fabs(yaw) > CV_PI/2)
{
UDEBUG("");
// verify if it is a 180 degree transform, well verify > 90
float x,y,z, roll,pitch,yaw;
transform.getTranslationAndEulerAngles(x,y,z, roll,pitch,yaw);
if(fabs(roll) > CV_PI/2 ||
fabs(pitch) > CV_PI/2 ||
fabs(yaw) > CV_PI/2)
transform.setNull();
std::string msg = uFormat("Too large rotation detected! (roll=%f, pitch=%f, yaw=%f)",
roll, pitch, yaw);
UINFO(msg.c_str());
if(info)
{
transform.setNull();
std::string msg = uFormat("Too large rotation detected! (roll=%f, pitch=%f, yaw=%f)",
roll, pitch, yaw);
UINFO(msg.c_str());
if(info)
{
info->rejectedMsg = msg;
}
info->rejectedMsg = msg;
}
}
}
@@ -2298,6 +2274,7 @@ Transform Memory::computeIcpTransformMulti(
SensorData assembledData;
Transform toPose = poses.at(toId);
std::string msg;
int maxPoints = fromScan.cols;
pcl::PointCloud<pcl::PointXYZ>::Ptr assembledToClouds(new pcl::PointCloud<pcl::PointXYZ>);
for(std::map<int, Transform>::const_iterator iter = poses.begin(); iter!=poses.end(); ++iter)
{
@@ -2309,6 +2286,10 @@ Transform Memory::computeIcpTransformMulti(
cv::Mat scan;
s->sensorData().uncompressData(0, 0, &scan);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud = util3d::laserScanToPointCloud(scan, toPose.inverse() * iter->second);
if(scan.cols > maxPoints)
{
maxPoints = scan.cols;
}
*assembledToClouds += *cloud;
}
else
@@ -2319,7 +2300,7 @@ Transform Memory::computeIcpTransformMulti(
}
if(assembledToClouds->size())
{
assembledData.setLaserScanRaw(util3d::laserScanFromPointCloud(*assembledToClouds, Transform()), fromS->sensorData().laserScanMaxPts(), fromS->sensorData().laserScanMaxRange());
assembledData.setLaserScanRaw(util3d::laserScanFromPointCloud(*assembledToClouds, Transform()), fromS->sensorData().laserScanMaxPts()?fromS->sensorData().laserScanMaxPts():maxPoints, fromS->sensorData().laserScanMaxRange());
}
Transform guess = poses.at(fromId).inverse() * poses.at(toId);
@@ -3427,7 +3408,7 @@ Signature * Memory::createSignature(const SensorData & data, const Transform & p
UASSERT(keypoints3D.size() == 0 || keypoints3D.size() == wordIds.size());
unsigned int i=0;
float decimationRatio = preDecimation / _imagePostDecimation;
double log2value = log(preDecimation)/log(2);
double log2value = log(double(preDecimation))/log(2.0);
for(std::list<int>::iterator iter=wordIds.begin(); iter!=wordIds.end() && i < keypoints.size(); ++iter, ++i)
{
cv::KeyPoint kpt = keypoints[i];

View File

@@ -253,7 +253,7 @@ Transform Odometry::process(SensorData & data, OdometryInfo * info)
// transform back the keypoints in the original image
std::vector<cv::KeyPoint> kpts = decimatedData.keypoints();
double log2value = log(_imageDecimation)/log(2);
double log2value = log(double(_imageDecimation))/log(2.0);
for(unsigned int i=0; i<kpts.size(); ++i)
{
kpts[i].pt.x *= _imageDecimation;
@@ -401,15 +401,7 @@ Transform Odometry::process(SensorData & data, OdometryInfo * info)
else if(!_holonomic)
{
// arc trajectory around ICR
float tmpY = vyaw!=0.0f ? vx / tan((CV_PI-vyaw)/2.0f) : 0.0f;
if(fabs(tmpY) < fabs(vy) || (tmpY<=0 && vy >=0) || (tmpY>=0 && vy<=0))
{
vy = tmpY;
}
else
{
vyaw = (atan(vx/vy)*2.0f-CV_PI)*-1;
}
vy = vyaw!=0.0f ? vx / tan((CV_PI-vyaw)/2.0f) : 0.0f;
if(_force3DoF)
{
vz = 0.0f;

View File

@@ -39,8 +39,7 @@ namespace rtabmap {
OdometryF2F::OdometryF2F(const ParametersMap & parameters) :
Odometry(parameters),
keyFrameThr_(Parameters::defaultOdomKeyFrameThr()),
scanKeyFrameThr_(Parameters::defaultOdomScanKeyFrameThr()),
motionSinceLastKeyFrame_(Transform::getIdentity())
scanKeyFrameThr_(Parameters::defaultOdomScanKeyFrameThr())
{
registrationPipeline_ = Registration::create(parameters);
Parameters::parse(parameters, Parameters::kOdomKeyFrameThr(), keyFrameThr_);
@@ -58,7 +57,7 @@ void OdometryF2F::reset(const Transform & initialPose)
{
Odometry::reset(initialPose);
refFrame_ = Signature();
motionSinceLastKeyFrame_.setIdentity();
lastKeyFramePose_.setNull();
}
// return not null transform if odometry is correctly computed
@@ -83,6 +82,13 @@ Transform OdometryF2F::computeTransform(
RegistrationInfo regInfo;
UASSERT(!this->getPose().isNull());
if(lastKeyFramePose_.isNull())
{
lastKeyFramePose_ = this->getPose(); // reset to current pose
}
Transform motionSinceLastKeyFrame = lastKeyFramePose_.inverse()*this->getPose();
Signature newFrame(data);
if(refFrame_.sensorData().isValid())
{
@@ -90,7 +96,7 @@ Transform OdometryF2F::computeTransform(
output = registrationPipeline_->computeTransformationMod(
tmpRefFrame,
newFrame,
!guess.isNull()?motionSinceLastKeyFrame_*guess:Transform(),
!guess.isNull()?motionSinceLastKeyFrame*guess:Transform(),
&regInfo);
if(info && this->isInfoDataFilled())
@@ -117,7 +123,7 @@ Transform OdometryF2F::computeTransform(
info->cornerInliers[i] = idToIndex.at(regInfo.inliersIDs[i]);
}
Transform t = this->getPose()*motionSinceLastKeyFrame_.inverse();
Transform t = this->getPose()*motionSinceLastKeyFrame.inverse();
for(std::multimap<int, cv::Point3f>::const_iterator iter=tmpRefFrame.getWords3().begin(); iter!=tmpRefFrame.getWords3().end(); ++iter)
{
info->localMap.insert(std::make_pair(iter->first, util3d::transformPoint(iter->second, t)));
@@ -135,8 +141,7 @@ Transform OdometryF2F::computeTransform(
if(!output.isNull())
{
output = motionSinceLastKeyFrame_.inverse() * output;
motionSinceLastKeyFrame_ *= output;
output = motionSinceLastKeyFrame.inverse() * output;
// new key-frame?
if( (registrationPipeline_->isImageRequired() && (keyFrameThr_ == 0 || float(regInfo.inliers) <= keyFrameThr_*float(refFrame_.sensorData().keypoints().size()))) ||
@@ -167,7 +172,7 @@ Transform OdometryF2F::computeTransform(
refFrame_.setWordsDescriptors(std::multimap<int, cv::Mat>());
//reset motion
motionSinceLastKeyFrame_.setIdentity();
lastKeyFramePose_.setNull();
}
else
{

View File

@@ -155,14 +155,20 @@ const std::map<std::string, std::pair<bool, std::string> > & Parameters::getRemo
{
// removed parameters
// 0.11.8
removedParameters_.insert(std::make_pair("Reg/Force2D", std::make_pair(true, Parameters::kRegForce3DoF())));
// 0.11.6
removedParameters_.insert(std::make_pair("RGBD/ProximityPathScansMerged", std::make_pair(false, "")));
// 0.11.3
removedParameters_.insert(std::make_pair("Mem/ImageDecimation", std::make_pair(true, Parameters::kMemImagePostDecimation())));
removedParameters_.insert(std::make_pair("Mem/ImageDecimation", std::make_pair(true, Parameters::kMemImagePostDecimation())));
// 0.11.2
removedParameters_.insert(std::make_pair("OdomLocalMap/HistorySize", std::make_pair(true, Parameters::kOdomF2MMaxSize())));
removedParameters_.insert(std::make_pair("OdomLocalMap/FixedMapPath", std::make_pair(true, Parameters::kOdomF2MFixedMapPath())));
removedParameters_.insert(std::make_pair("OdomF2F/GuessMotion", std::make_pair(true, Parameters::kOdomGuessMotion())));
removedParameters_.insert(std::make_pair("OdomF2F/KeyFrameThr", std::make_pair(false, Parameters::kOdomKeyFrameThr())));
removedParameters_.insert(std::make_pair("OdomF2F/KeyFrameThr", std::make_pair(false, Parameters::kOdomKeyFrameThr())));
// 0.11.0
removedParameters_.insert(std::make_pair("OdomBow/LocalHistorySize", std::make_pair(true, Parameters::kOdomF2MMaxSize())));
@@ -244,7 +250,7 @@ const std::map<std::string, std::pair<bool, std::string> > & Parameters::getRemo
removedParameters_.insert(std::make_pair("RGBD/LocalLoopDetectionBySpace", std::make_pair(true, Parameters::kRGBDProximityBySpace())));
removedParameters_.insert(std::make_pair("RGBD/LocalLoopDetectionTime", std::make_pair(true, Parameters::kRGBDProximityByTime())));
removedParameters_.insert(std::make_pair("RGBD/LocalLoopDetectionSpace", std::make_pair(true, Parameters::kRGBDProximityBySpace())));
removedParameters_.insert(std::make_pair("RGBD/LocalLoopDetectionPathScansMerged", std::make_pair(true, Parameters::kRGBDProximityPathScansMerged())));
removedParameters_.insert(std::make_pair("RGBD/LocalLoopDetectionPathScansMerged", std::make_pair(false, "")));
removedParameters_.insert(std::make_pair("RGBD/LocalLoopDetectionMaxGraphDepth", std::make_pair(true, Parameters::kRGBDProximityMaxGraphDepth())));
removedParameters_.insert(std::make_pair("RGBD/LocalLoopDetectionPathFilteringRadius", std::make_pair(true, Parameters::kRGBDProximityPathFilteringRadius())));
removedParameters_.insert(std::make_pair("RGBD/LocalLoopDetectionPathRawPosesUsed", std::make_pair(true, Parameters::kRGBDProximityPathRawPosesUsed())));

View File

@@ -186,6 +186,11 @@ Transform Registration::computeTransformationMod(
info = *infoOut;
}
if(!guess.isNull() && force3DoF_)
{
guess = guess.to3DoF();
}
Transform t = computeTransformationImpl(from, to, guess, info);
if(varianceFromInliersCount_)
@@ -207,6 +212,11 @@ Transform Registration::computeTransformationMod(
{
t = child_->computeTransformationMod(from, to, force3DoF_?t.to3DoF():t, &info);
}
else if(!guess.isNull())
{
UDEBUG("This registration approach failed, continue with the guess for the next registration");
t = child_->computeTransformationMod(from, to, guess, &info);
}
}
else if(!t.isNull() && force3DoF_)
{

View File

@@ -113,7 +113,7 @@ Transform RegistrationIcp::computeTransformationImpl(
if(!guess.isNull() && !dataFrom.laserScanRaw().empty() && !dataTo.laserScanRaw().empty())
{
// ICP with guess transform
int maxLaserScans = dataTo.laserScanMaxPts();
int maxLaserScans = dataTo.laserScanMaxPts()?dataTo.laserScanMaxPts():dataFrom.laserScanMaxPts();
cv::Mat fromScan = dataFrom.laserScanRaw();
cv::Mat toScan = dataTo.laserScanRaw();
if(_downsamplingStep>1)
@@ -309,8 +309,13 @@ Transform RegistrationIcp::computeTransformationImpl(
}
else
{
UWARN("Maximum laser scans points not set for signature %d, correspondences ratio set relative instead of absolute!",
dataTo.id());
static bool warningShown = false;
if(!warningShown)
{
UWARN("Maximum laser scans points not set for signature %d, correspondences ratio set relative instead of absolute! This message will only appear once.",
dataTo.id());
warningShown = true;
}
correspondencesRatio = float(correspondences)/float(toScan.cols>fromScan.cols?toScan.cols:fromScan.cols);
}

View File

@@ -100,7 +100,6 @@ Rtabmap::Rtabmap() :
_proximityMaxGraphDepth(Parameters::defaultRGBDProximityMaxGraphDepth()),
_proximityFilteringRadius(Parameters::defaultRGBDProximityPathFilteringRadius()),
_proximityRawPosesUsed(Parameters::defaultRGBDProximityPathRawPosesUsed()),
_proximityScansMerged(Parameters::defaultRGBDProximityPathScansMerged()),
_proximityAngle(Parameters::defaultRGBDProximityAngle()*M_PI/180.0f),
_databasePath(""),
_optimizeFromGraphEnd(Parameters::defaultRGBDOptimizeFromGraphEnd()),
@@ -411,7 +410,6 @@ void Rtabmap::parseParameters(const ParametersMap & parameters)
Parameters::parse(parameters, Parameters::kRGBDProximityMaxGraphDepth(), _proximityMaxGraphDepth);
Parameters::parse(parameters, Parameters::kRGBDProximityPathFilteringRadius(), _proximityFilteringRadius);
Parameters::parse(parameters, Parameters::kRGBDProximityPathRawPosesUsed(), _proximityRawPosesUsed);
Parameters::parse(parameters, Parameters::kRGBDProximityPathScansMerged(), _proximityScansMerged);
Parameters::parse(parameters, Parameters::kRGBDProximityAngle(), _proximityAngle);
_proximityAngle *= M_PI/180.0f;
Parameters::parse(parameters, Parameters::kRGBDOptimizeFromGraphEnd(), _optimizeFromGraphEnd);
@@ -1013,17 +1011,16 @@ bool Rtabmap::process(
else
{
//============================================================
// Scan matching
// Refine neighbor links
//============================================================
if(!signature->sensorData().laserScanCompressed().empty())
{
UINFO("Odometry correction by scan matching");
Transform guess = signature->getLinks().begin()->second.transform().inverse();
UINFO("Odometry refining: guess = %s", guess.prettyPrint().c_str());
RegistrationInfo info;
Transform t = _memory->computeIcpTransform(oldId, signature->id(), guess, &info);
Transform t = _memory->computeTransform(oldId, signature->id(), guess, &info);
if(!t.isNull())
{
UINFO("Scan matching: update neighbor link (%d->%d, variance=%f) from %s to %s",
UINFO("Odometry refining: update neighbor link (%d->%d, variance=%f) from %s to %s",
oldId,
signature->id(),
info.variance,
@@ -1050,7 +1047,7 @@ bool Rtabmap::process(
}
else
{
UINFO("Scan matching rejected: %s", info.rejectedMsg.c_str());
UINFO("Odometry refining rejected: %s", info.rejectedMsg.c_str());
if(info.variance > 0)
{
double sqrtVar = sqrt(info.variance);
@@ -1065,7 +1062,7 @@ bool Rtabmap::process(
}
}
timeNeighborLinkRefining = timer.ticks();
ULOGGER_INFO("timeScanMatching=%fs", timeNeighborLinkRefining);
ULOGGER_INFO("timeOdometryRefining=%fs", timeNeighborLinkRefining);
UASSERT(oldS->hasLink(signature->id()));
UASSERT(uContains(_optimizedPoses, oldId));
@@ -1837,7 +1834,8 @@ bool Rtabmap::process(
_optimizedPoses.at(signature->id()).getDistanceSquared(_optimizedPoses.at(nearestId)) < _proximityFilteringRadius*_proximityFilteringRadius))
{
RegistrationInfo info;
Transform transform = _memory->computeTransform(signature->id(), nearestId, Transform(), &info);
Transform guess = _optimizedPoses.at(signature->id()).inverse() * _optimizedPoses.at(nearestId);
Transform transform = _memory->computeTransform(signature->id(), nearestId, guess, &info);
if(!transform.isNull())
{
if(_proximityFilteringRadius <= 0 || transform.getNormSquared() <= _proximityFilteringRadius*_proximityFilteringRadius)
@@ -1902,47 +1900,37 @@ bool Rtabmap::process(
(_proximityFilteringRadius <= 0.0f ||
_optimizedPoses.at(signature->id()).getDistanceSquared(_optimizedPoses.at(nearestId)) < _proximityFilteringRadius*_proximityFilteringRadius))
{
if(!_proximityScansMerged)
{
//only keep the nearest node
std::map<int, Transform> tmp;
tmp.insert(*path.find(nearestId));
path = tmp;
}
else
// Assemble scans in the path and do ICP only
if(_proximityRawPosesUsed)
{
// Assemble scans in the path and do ICP only
if(_proximityRawPosesUsed)
//optimize the path's poses locally
path = optimizeGraph(nearestId, uKeysSet(path), std::map<int, Transform>(), false);
// transform local poses in optimized graph referential
UASSERT(uContains(path, nearestId));
Transform t = _optimizedPoses.at(nearestId) * path.at(nearestId).inverse();
for(std::map<int, Transform>::iterator jter=path.begin(); jter!=path.end(); ++jter)
{
//optimize the path's poses locally
path = optimizeGraph(nearestId, uKeysSet(path), std::map<int, Transform>(), false);
// transform local poses in optimized graph referential
UASSERT(uContains(path, nearestId));
Transform t = _optimizedPoses.at(nearestId) * path.at(nearestId).inverse();
for(std::map<int, Transform>::iterator jter=path.begin(); jter!=path.end(); ++jter)
{
jter->second = t * jter->second;
}
}
if(path.size() > 2 && _proximityFilteringRadius > 0.0f)
{
// path filtering
std::map<int, Transform> filteredPath = graph::radiusPosesFiltering(path, _proximityFilteringRadius, 0, true);
// make sure the current pose is still here
filteredPath.insert(*path.find(nearestId));
path = filteredPath;
jter->second = t * jter->second;
}
}
std::map<int, Transform> filteredPath = path;
if(path.size() > 2 && _proximityFilteringRadius > 0.0f)
{
// path filtering
filteredPath = graph::radiusPosesFiltering(path, _proximityFilteringRadius, 0, true);
// make sure the current pose is still here
filteredPath.insert(*path.find(nearestId));
}
if(path.size() > 0)
if(filteredPath.size() > 0)
{
// add current node to poses
path.insert(std::make_pair(signature->id(), _optimizedPoses.at(signature->id())));
filteredPath.insert(std::make_pair(signature->id(), _optimizedPoses.at(signature->id())));
//The nearest will be the reference for a loop closure transform
if(signature->getLinks().find(nearestId) == signature->getLinks().end())
{
RegistrationInfo info;
Transform transform = _memory->computeIcpTransformMulti(signature->id(), nearestId, path, &info);
Transform transform = _memory->computeIcpTransformMulti(signature->id(), nearestId, filteredPath, &info);
if(!transform.isNull())
{
if(_proximityFilteringRadius <= 0 || transform.getNormSquared() <= _proximityFilteringRadius*_proximityFilteringRadius)
@@ -1959,14 +1947,11 @@ bool Rtabmap::process(
stream << "SCANS:";
for(std::map<int, Transform>::iterator iter=path.begin(); iter!=path.end(); ++iter)
{
if(iter->first!=signature->id())
if(iter != path.begin())
{
if(iter != path.begin())
{
stream << ";";
}
stream << uNumber2Str(iter->first);
stream << ";";
}
stream << uNumber2Str(iter->first);
}
std::string scansStr = stream.str();
scanMatchingIds = cv::Mat(1, int(scansStr.size()+1), CV_8SC1, (void *)scansStr.c_str());
@@ -2051,14 +2036,17 @@ bool Rtabmap::process(
{
UASSERT(uContains(_optimizedPoses, signature->id()));
//used in localization mode: filter virtual links
std::map<int, Link> localizationLinks = graph::filterLinks(signature->getLinks(), Link::kVirtualClosure);
// Note that in localization mode, we don't re-optimize the graph
// if:
// 1- there are no signatures retrieved,
// 2- we are relocalizing on a node already in the optimized graph
if(!_memory->isIncremental() &&
signaturesRetrieved.size() == 0 &&
signature->getLinks().size() &&
uContains(_optimizedPoses, signature->getLinks().begin()->first))
localizationLinks.size() &&
uContains(_optimizedPoses, localizationLinks.begin()->first))
{
// If there are no signatures retrieved, we don't
// need to re-optimize the graph. Just update the last
@@ -2070,8 +2058,8 @@ bool Rtabmap::process(
// update all previous nodes
// Normally _mapCorrection should be identity, but if _optimizeFromGraphEnd
// parameters just changed state, we should put back all poses without map correction.
Transform oldPose = _optimizedPoses.at(signature->getLinks().begin()->first);
Transform u = signature->getPose() * signature->getLinks().begin()->second.transform();
Transform oldPose = _optimizedPoses.at(localizationLinks.begin()->first);
Transform u = signature->getPose() * localizationLinks.begin()->second.transform();
Transform up = u * oldPose.inverse();
Transform mapCorrectionInv = _mapCorrection.inverse();
for(std::map<int, Transform>::iterator iter=_optimizedPoses.begin(); iter!=_optimizedPoses.end(); ++iter)
@@ -2082,7 +2070,7 @@ bool Rtabmap::process(
}
else
{
_optimizedPoses.at(signature->id()) = _optimizedPoses.at(signature->getLinks().begin()->first) * signature->getLinks().begin()->second.transform().inverse();
_optimizedPoses.at(signature->id()) = _optimizedPoses.at(localizationLinks.begin()->first) * localizationLinks.begin()->second.transform().inverse();
}
}
else

View File

@@ -150,7 +150,13 @@ std::vector<cv::Point2f> StereoOpticalFlow::computeCorrespondences(
if(countFlowRejected + countDisparityRejected > (int)status.size()/2)
{
UWARN("A large number (%d/%d) of stereo correspondences are rejected! Optical flow may have failed, images are not calibrated or the background is too far (no disparity between the images).", countFlowRejected+countDisparityRejected, (int)status.size());
UWARN("A large number (%d/%d) of stereo correspondences are rejected! "
"Optical flow may have failed, images are not calibrated, "
"the background is too far (no disparity between the images) or "
"maximum disparity may be too small (%d).",
countFlowRejected+countDisparityRejected,
(int)status.size(),
this->maxDisparity());
}
return rightCorners;

View File

@@ -542,7 +542,7 @@ void VWDictionary::setNNStrategy(NNStrategy strategy)
}
#endif
#else
#if HAVE_OPENCV_CUDAFEATURES2D
#ifdef HAVE_OPENCV_CUDAFEATURES2D
if(strategy == kNNBruteForceGPU && !cv::cuda::getCudaEnabledDeviceCount())
{
UERROR("Nearest neighobr strategy \"kNNBruteForceGPU\" chosen but no CUDA devices found! Doing \"kNNBruteForce\" instead.");

View File

@@ -33,6 +33,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <rtabmap/utilite/UTimer.h>
#include <rtabmap/utilite/UStl.h>
#include <rtabmap/core/util3d_transforms.h>
#include <rtabmap/core/StereoDense.h>
#include <opencv2/calib3d/calib3d.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/video/tracking.hpp>
@@ -724,12 +725,11 @@ void calcOpticalFlowPyrLKStereo( cv::InputArray _prevImg, cv::InputArray _nextIm
cv::Mat disparityFromStereoImages(
const cv::Mat & leftImage,
const cv::Mat & rightImage,
int type)
const ParametersMap & parameters)
{
UASSERT(!leftImage.empty() && !rightImage.empty());
UASSERT(leftImage.cols == rightImage.cols && leftImage.rows == rightImage.rows);
UASSERT((leftImage.type() == CV_8UC1 || leftImage.type() == CV_8UC3) && rightImage.type() == CV_8UC1);
UASSERT(type == CV_32FC1 || type == CV_16SC1);
cv::Mat leftMono;
if(leftImage.channels() == 3)
@@ -741,32 +741,9 @@ cv::Mat disparityFromStereoImages(
leftMono = leftImage;
}
cv::Mat disparity;
#if CV_MAJOR_VERSION < 3
cv::StereoBM stereo(cv::StereoBM::BASIC_PRESET);
stereo.state->SADWindowSize = 15;
stereo.state->minDisparity = 0;
stereo.state->numberOfDisparities = 64;
stereo.state->preFilterSize = 9;
stereo.state->preFilterCap = 31;
stereo.state->uniquenessRatio = 15;
stereo.state->textureThreshold = 10;
stereo.state->speckleWindowSize = 100;
stereo.state->speckleRange = 4;
stereo(leftMono, rightImage, disparity, type);
#else
cv::Ptr<cv::StereoBM> stereo = cv::StereoBM::create();
stereo->setBlockSize(15);
stereo->setMinDisparity(0);
stereo->setNumDisparities(64);
stereo->setPreFilterSize(9);
stereo->setPreFilterCap(31);
stereo->setUniquenessRatio(15);
stereo->setTextureThreshold(10);
stereo->setSpeckleWindowSize(100);
stereo->setSpeckleRange(4);
stereo->compute(leftMono, rightImage, disparity);
#endif
return disparity;
StereoBM stereo(parameters);
return stereo.computeDisparity(leftMono, rightImage);
}
cv::Mat depthFromDisparity(const cv::Mat & disparity,

View File

@@ -249,8 +249,8 @@ pcl::PointCloud<pcl::PointXYZ>::Ptr cloudFromDepth(
std::vector<int> * validIndices)
{
UASSERT(!imageDepth.empty() && (imageDepth.type() == CV_16UC1 || imageDepth.type() == CV_32FC1));
UASSERT(imageDepth.rows % decimation == 0);
UASSERT(imageDepth.cols % decimation == 0);
UASSERT_MSG(imageDepth.rows % decimation == 0, uFormat("rows=%d decimation=%d", imageDepth.rows, decimation).c_str());
UASSERT_MSG(imageDepth.cols % decimation == 0, uFormat("cols=%d decimation=%d", imageDepth.cols, decimation).c_str());
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
if(decimation < 1)
@@ -588,7 +588,8 @@ pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloudFromStereoImages(
int decimation,
float maxDepth,
float minDepth,
std::vector<int> * validIndices)
std::vector<int> * validIndices,
const ParametersMap & parameters)
{
UASSERT(!imageLeft.empty() && !imageRight.empty());
UASSERT(imageRight.type() == CV_8UC1);
@@ -623,7 +624,7 @@ pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloudFromStereoImages(
return cloudFromDisparityRGB(
leftColor,
util2d::disparityFromStereoImages(leftMono, rightMono),
util2d::disparityFromStereoImages(leftMono, rightMono, parameters),
modelDecimation,
decimation,
maxDepth,
@@ -636,7 +637,8 @@ pcl::PointCloud<pcl::PointXYZ>::Ptr RTABMAP_EXP cloudFromSensorData(
int decimation,
float maxDepth,
float minDepth,
std::vector<int> * validIndices)
std::vector<int> * validIndices,
const ParametersMap & parameters)
{
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
@@ -696,7 +698,7 @@ pcl::PointCloud<pcl::PointXYZ>::Ptr RTABMAP_EXP cloudFromSensorData(
leftMono = sensorData.imageRaw();
}
cloud = cloudFromDisparity(
util2d::disparityFromStereoImages(leftMono, sensorData.rightRaw()),
util2d::disparityFromStereoImages(leftMono, sensorData.rightRaw(), parameters),
sensorData.stereoCameraModel(),
decimation,
maxDepth,
@@ -719,7 +721,8 @@ pcl::PointCloud<pcl::PointXYZRGB>::Ptr RTABMAP_EXP cloudRGBFromSensorData(
int decimation,
float maxDepth,
float minDepth,
std::vector<int> * validIndices)
std::vector<int> * validIndices,
const ParametersMap & parameters)
{
UASSERT(!sensorData.imageRaw().empty());
UASSERT((!sensorData.depthRaw().empty() && sensorData.cameraModels().size()) ||
@@ -804,7 +807,8 @@ pcl::PointCloud<pcl::PointXYZRGB>::Ptr RTABMAP_EXP cloudRGBFromSensorData(
decimation,
maxDepth,
minDepth,
validIndices);
validIndices,
parameters);
if(cloud->size())
{

View File

@@ -45,6 +45,18 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <rtabmap/utilite/UMath.h>
#include <rtabmap/utilite/UConversion.h>
#if PCL_VERSION_COMPARE(>=, 1, 8, 0)
#include <pcl/impl/instantiate.hpp>
#include <pcl/point_types.h>
#include <pcl/segmentation/impl/extract_clusters.hpp>
#include <pcl/segmentation/extract_labeled_clusters.h>
#include <pcl/segmentation/impl/extract_labeled_clusters.hpp>
PCL_INSTANTIATE(EuclideanClusterExtraction, (pcl::PointXYZRGBNormal))
PCL_INSTANTIATE(extractEuclideanClusters, (pcl::PointXYZRGBNormal))
PCL_INSTANTIATE(extractEuclideanClusters_indices, (pcl::PointXYZRGBNormal))
#endif
namespace rtabmap
{
@@ -88,7 +100,7 @@ pcl::PointCloud<pcl::PointXYZ>::Ptr downsample(
}
else
{
int finalSize = cloud->size()/step;
int finalSize = int(cloud->size())/step;
output->resize(finalSize);
int oi = 0;
for(unsigned int i=0; i<cloud->size()-step+1; i+=step)
@@ -111,7 +123,7 @@ pcl::PointCloud<pcl::PointXYZRGB>::Ptr downsample(
}
else
{
int finalSize = cloud->size()/step;
int finalSize = int(cloud->size())/step;
output->resize(finalSize);
int oi = 0;
for(int i=0; i<(int)cloud->size()-step+1; i+=step)
@@ -244,6 +256,48 @@ pcl::PointCloud<pcl::PointXYZRGB>::Ptr randomSampling(
return output;
}
pcl::IndicesPtr passThrough(
const pcl::PointCloud<pcl::PointXYZ>::Ptr & cloud,
const pcl::IndicesPtr & indices,
const std::string & axis,
float min,
float max,
bool negative)
{
UASSERT(max > min);
UASSERT(axis.compare("x") == 0 || axis.compare("y") == 0 || axis.compare("z") == 0);
pcl::IndicesPtr output(new std::vector<int>);
pcl::PassThrough<pcl::PointXYZ> filter;
filter.setNegative(negative);
filter.setFilterFieldName(axis);
filter.setFilterLimits(min, max);
filter.setInputCloud(cloud);
filter.setIndices(indices);
filter.filter(*output);
return output;
}
pcl::IndicesPtr passThrough(
const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloud,
const pcl::IndicesPtr & indices,
const std::string & axis,
float min,
float max,
bool negative)
{
UASSERT(max > min);
UASSERT(axis.compare("x") == 0 || axis.compare("y") == 0 || axis.compare("z") == 0);
pcl::IndicesPtr output(new std::vector<int>);
pcl::PassThrough<pcl::PointXYZRGB> filter;
filter.setNegative(negative);
filter.setFilterFieldName(axis);
filter.setFilterLimits(min, max);
filter.setInputCloud(cloud);
filter.setIndices(indices);
filter.filter(*output);
return output;
}
pcl::PointCloud<pcl::PointXYZ>::Ptr passThrough(
const pcl::PointCloud<pcl::PointXYZ>::Ptr & cloud,

View File

@@ -46,6 +46,16 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "pcl18/surface/organized_fast_mesh.h"
#else
#include <pcl/surface/organized_fast_mesh.h>
#include <pcl/surface/impl/marching_cubes.hpp>
#include <pcl/surface/impl/organized_fast_mesh.hpp>
#include <pcl/impl/instantiate.hpp>
#include <pcl/point_types.h>
// Instantiations of specific point types
PCL_INSTANTIATE(OrganizedFastMesh, (pcl::PointXYZRGBNormal))
#include <pcl/features/impl/normal_3d_omp.hpp>
PCL_INSTANTIATE_PRODUCT(NormalEstimationOMP, ((pcl::PointXYZRGB))((pcl::Normal)))
#endif
namespace rtabmap
@@ -177,10 +187,10 @@ void appendMesh(
UDEBUG("cloudA=%d polygonsA=%d cloudB=%d polygonsB=%d", (int)cloudA.size(), (int)polygonsA.size(), (int)cloudB.size(), (int)polygonsB.size());
UASSERT(!cloudA.isOrganized() && !cloudB.isOrganized());
int sizeA = cloudA.size();
int sizeA = (int)cloudA.size();
cloudA += cloudB;
int sizePolygonsA = polygonsA.size();
int sizePolygonsA = (int)polygonsA.size();
polygonsA.resize(sizePolygonsA+polygonsB.size());
for(unsigned int i=0; i<polygonsB.size(); ++i)
@@ -203,10 +213,10 @@ void appendMesh(
UDEBUG("cloudA=%d polygonsA=%d cloudB=%d polygonsB=%d", (int)cloudA.size(), (int)polygonsA.size(), (int)cloudB.size(), (int)polygonsB.size());
UASSERT(!cloudA.isOrganized() && !cloudB.isOrganized());
int sizeA = cloudA.size();
int sizeA = (int)cloudA.size();
cloudA += cloudB;
int sizePolygonsA = polygonsA.size();
int sizePolygonsA = (int)polygonsA.size();
polygonsA.resize(sizePolygonsA+polygonsB.size());
for(unsigned int i=0; i<polygonsB.size(); ++i)

View File

@@ -33,6 +33,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <rtabmap/utilite/UEventsHandler.h>
#include <QDialog>
#include <rtabmap/core/SensorData.h>
#include <rtabmap/core/Parameters.h>
class QSpinBox;
class QCheckBox;
@@ -47,7 +48,9 @@ class RTABMAPGUI_EXP CameraViewer : public QDialog, public UEventsHandler
{
Q_OBJECT
public:
CameraViewer(QWidget * parent = 0);
CameraViewer(
QWidget * parent = 0,
const ParametersMap & parameters = ParametersMap());
virtual ~CameraViewer();
public slots:
@@ -61,6 +64,7 @@ private:
bool processingImages_;
QSpinBox * decimationSpin_;
int validDecimationValue_;
ParametersMap parameters_;
QPushButton * pause_;
QCheckBox * showCloudCheckbox_;
QCheckBox * showScanCheckbox_;

View File

@@ -142,7 +142,8 @@ public:
void removeOccupancyGridMap();
void updateCameraTargetPosition(
const Transform & pose);
const Transform & pose,
const Transform & localTransform = Transform::getIdentity());
void addOrUpdateCoordinate(
const std::string & id,
@@ -154,6 +155,15 @@ public:
void removeCoordinate(const std::string & id);
void removeAllCoordinates();
void addOrUpdateLine(
const std::string & id,
const Transform & from,
const Transform & to,
const QColor & color,
bool arrow = false);
void removeLine(const std::string & id);
void removeAllLines();
void addOrUpdateFrustum(
const std::string & id,
const Transform & transform,
@@ -282,6 +292,7 @@ private:
std::set<std::string> _graphes;
std::set<std::string> _coordinates;
std::set<std::string> _texts;
std::set<std::string> _lines;
std::set<std::string> _frustums;
pcl::PointCloud<pcl::PointXYZ>::Ptr _trajectory;
unsigned int _maxTrajectorySize;

View File

@@ -57,7 +57,7 @@ public slots:
void setDecimation(int decimation) {decimation_ = decimation;}
void setMaxDepth(int maxDepth) {maxDepth_ = maxDepth;}
void setMinDepth(int minDepth) {minDepth_ = minDepth;}
void updateView(const Transform & AtoB = Transform());
void updateView(const Transform & AtoB = Transform(), const ParametersMap & parameters = ParametersMap());
protected:
virtual void showEvent(QShowEvent * event);

View File

@@ -153,6 +153,8 @@ private slots:
void selectFreenect2();
void selectStereoDC1394();
void selectStereoFlyCapture2();
void selectStereoZed();
void selectStereoUsb();
void dumpTheMemory();
void dumpThePrediction();
void sendGoal();
@@ -229,7 +231,6 @@ private:
void update3DMapVisibility(bool cloudsShown, bool scansShown);
void updateMapCloud(
const std::map<int, Transform> & poses,
const Transform & pose,
const std::multimap<int, Link> & constraints,
const std::map<int, int> & mapIds,
const std::map<int, std::string> & labels,

View File

@@ -31,6 +31,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "rtabmap/gui/RtabmapGuiExp.h" // DLL export/import defines
#include "rtabmap/core/OdometryEvent.h"
#include "rtabmap/core/Parameters.h"
#include <QDialog>
#include "rtabmap/utilite/UEventsHandler.h"
@@ -49,7 +50,14 @@ class RTABMAPGUI_EXP OdometryViewer : public QDialog, public UEventsHandler
Q_OBJECT
public:
OdometryViewer(int maxClouds = 10, int decimation = 2, float voxelSize = 0.0f, float maxDepth = 0, int qualityWarningThr=0, QWidget * parent = 0);
OdometryViewer(
int maxClouds = 10,
int decimation = 2,
float voxelSize = 0.0f,
float maxDepth = 0,
int qualityWarningThr=0,
QWidget * parent = 0,
const ParametersMap & parameters = ParametersMap());
virtual ~OdometryViewer();
public slots:
@@ -83,6 +91,7 @@ private:
QCheckBox * featuresShown_;
QLabel * timeLabel_;
int validDecimationValue_;
ParametersMap parameters_;
};
} /* namespace rtabmap */

View File

@@ -96,6 +96,8 @@ public:
kSrcFlyCapture2 = 101,
kSrcStereoImages = 102,
kSrcStereoVideo = 103,
kSrcStereoZed = 104,
kSrcStereoUsb = 105,
kSrcRGB = 200,
kSrcUsbDevice = 200,
@@ -283,6 +285,7 @@ private slots:
void selectSourceStereoVideoPath();
void selectSourceOniPath();
void selectSourceOni2Path();
void selectSourceSvoPath();
void updateSourceGrpVisibility();
void testOdometry();
void testCamera();

View File

@@ -722,8 +722,8 @@ void CalibrationDialog::calibrate()
P.at<double>(2,3) = 1;
K.copyTo(P.colRange(0,3).rowRange(0,3));
std::cout << "cameraMatrix = " << K << std::endl;
std::cout << "distCoeffs = " << D << std::endl;
std::cout << "K = " << K << std::endl;
std::cout << "D = " << D << std::endl;
std::cout << "width = " << imageSize_[id].width << std::endl;
std::cout << "height = " << imageSize_[id].height << std::endl;
@@ -738,8 +738,8 @@ void CalibrationDialog::calibrate()
ui_->label_error->setNum(totalAvgErr);
std::stringstream strK, strD, strR, strP;
strK << models_[id].K();
strD << models_[id].D();
strK << models_[id].K_raw();
strD << models_[id].D_raw();
strR << models_[id].R();
strP << models_[id].P();
ui_->lineEdit_K->setText(strK.str().c_str());
@@ -756,8 +756,8 @@ void CalibrationDialog::calibrate()
ui_->label_error_2->setNum(totalAvgErr);
std::stringstream strK, strD, strR, strP;
strK << models_[id].K();
strD << models_[id].D();
strK << models_[id].K_raw();
strD << models_[id].D_raw();
strR << models_[id].R();
strP << models_[id].P();
ui_->lineEdit_K_2->setText(strK.str().c_str());
@@ -806,6 +806,11 @@ void CalibrationDialog::calibrate()
#endif
UINFO("stereo calibration... done with RMS error=%f", rms);
std::cout << "R = " << R << std::endl;
std::cout << "T = " << T << std::endl;
std::cout << "E = " << E << std::endl;
std::cout << "F = " << F << std::endl;
if(imageSize_[0] == imageSize_[1])
{
//Stereo, compute stereo rectification

View File

@@ -47,12 +47,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace rtabmap {
CameraViewer::CameraViewer(QWidget * parent) :
CameraViewer::CameraViewer(QWidget * parent, const ParametersMap & parameters) :
QDialog(parent),
imageView_(new ImageView(this)),
cloudView_(new CloudViewer(this)),
processingImages_(false),
validDecimationValue_(1)
validDecimationValue_(1),
parameters_(parameters)
{
qRegisterMetaType<rtabmap::SensorData>("rtabmap::SensorData");
@@ -146,12 +147,12 @@ void CameraViewer::showImage(const rtabmap::SensorData & data)
if(!data.imageRaw().empty() && !data.depthOrRightRaw().empty())
{
showCloudCheckbox_->setEnabled(true);
cloudView_->addCloud("cloud", util3d::cloudRGBFromSensorData(data, validDecimationValue_));
cloudView_->addCloud("cloud", util3d::cloudRGBFromSensorData(data, validDecimationValue_, 0, 0, 0, parameters_));
}
else if(!data.depthOrRightRaw().empty())
{
showCloudCheckbox_->setEnabled(true);
cloudView_->addCloud("cloud", util3d::cloudFromSensorData(data, validDecimationValue_));
cloudView_->addCloud("cloud", util3d::cloudFromSensorData(data, validDecimationValue_, 0, 0, 0, parameters_));
}
}
}

View File

@@ -172,6 +172,7 @@ void CloudViewer::clear()
this->removeAllClouds();
this->removeAllGraphs();
this->removeAllCoordinates();
this->removeAllLines();
this->removeAllFrustums();
this->removeAllTexts();
this->clearTrajectory();
@@ -792,6 +793,70 @@ void CloudViewer::removeAllCoordinates()
UASSERT(_coordinates.empty());
}
void CloudViewer::addOrUpdateLine(
const std::string & id,
const Transform & from,
const Transform & to,
const QColor & color,
bool arrow)
{
if(id.empty())
{
UERROR("id should not be empty!");
return;
}
removeLine(id);
if(!from.isNull() && !to.isNull())
{
_lines.insert(id);
QColor c = Qt::gray;
if(color.isValid())
{
c = color;
}
pcl::PointXYZ pt1(from.x(), from.y(), from.z());
pcl::PointXYZ pt2(to.x(), to.y(), to.z());
if(arrow)
{
_visualizer->addArrow(pt2, pt1, c.redF(), c.greenF(), c.blueF(), false, id);
}
else
{
_visualizer->addLine(pt2, pt1, c.redF(), c.greenF(), c.blueF(), id);
}
}
}
void CloudViewer::removeLine(const std::string & id)
{
if(id.empty())
{
UERROR("id should not be empty!");
return;
}
if(_lines.find(id) != _lines.end())
{
_visualizer->removeShape(id);
_lines.erase(id);
}
}
void CloudViewer::removeAllLines()
{
std::set<std::string> arrows = _lines;
for(std::set<std::string>::iterator iter = arrows.begin(); iter!=arrows.end(); ++iter)
{
this->removeLine(*iter);
}
UASSERT(_lines.empty());
}
static const float frustum_vertices[] = {
0.0f, 0.0f, 0.0f,
1.0f, 1.0f, 1.0f,
@@ -1055,6 +1120,7 @@ void CloudViewer::setFrustumShown(bool shown)
if(!shown)
{
this->removeFrustum("reference_frustum");
this->removeLine("reference_frustum_line");
this->update();
}
_aShowFrustum->setChecked(shown);
@@ -1074,8 +1140,8 @@ void CloudViewer::setFrustumColor(QColor value)
if(_frustums.find("reference_frustum") != _frustums.end())
{
_visualizer->setShapeRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, value.redF(), value.greenF(), value.blueF(), "reference_frustum");
this->update();
}
this->update();
_frustumColor = value;
}
@@ -1189,7 +1255,7 @@ void CloudViewer::setCameraPosition(
_visualizer->setCameraPosition(x,y,z, focalX,focalY,focalX, upX,upY,upZ);
}
void CloudViewer::updateCameraTargetPosition(const Transform & pose)
void CloudViewer::updateCameraTargetPosition(const Transform & pose, const Transform & localTransform)
{
if(!pose.isNull())
{
@@ -1305,7 +1371,17 @@ void CloudViewer::updateCameraTargetPosition(const Transform & pose)
}
else */ if(_aShowFrustum->isChecked())
{
this->addOrUpdateFrustum("reference_frustum", pose, _frustumScale, _frustumColor);
Transform baseToCamera = Transform::getIdentity();
Transform opticalRot(0, 0, 1, 0, -1, 0, 0, 0, 0, -1, 0, 0);
if(!localTransform.isNull() && !localTransform.isIdentity())
{
baseToCamera = localTransform*opticalRot.inverse();
}
this->addOrUpdateFrustum("reference_frustum", pose * baseToCamera, _frustumScale, _frustumColor);
if(!baseToCamera.isIdentity())
{
this->addOrUpdateLine("reference_frustum_line", pose, pose * baseToCamera, _frustumColor);
}
}
vtkRenderer* renderer = _visualizer->getRendererCollection()->GetFirstRenderer();
@@ -1578,7 +1654,7 @@ void CloudViewer::keyReleaseEvent(QKeyEvent * event) {
}
else
{
QWidget::keyPressEvent(event);
QVTKWidget::keyPressEvent(event);
}
}
@@ -1678,7 +1754,7 @@ void CloudViewer::keyPressEvent(QKeyEvent * event)
}
else
{
QWidget::keyPressEvent(event);
QVTKWidget::keyPressEvent(event);
}
}

View File

@@ -1509,7 +1509,7 @@ void DatabaseViewer::view3DMap()
pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud;
UASSERT(data.imageRaw().empty() || data.imageRaw().type()==CV_8UC3 || data.imageRaw().type() == CV_8UC1);
UASSERT(data.depthOrRightRaw().empty() || data.depthOrRightRaw().type()==CV_8UC1 || data.depthOrRightRaw().type() == CV_16UC1 || data.depthOrRightRaw().type() == CV_32FC1);
cloud = util3d::cloudRGBFromSensorData(data, decimation, maxDepth);
cloud = util3d::cloudRGBFromSensorData(data, decimation, maxDepth, 0, 0, ui_->parameters_toolbox->getParameters());
if(cloud->size())
{
@@ -1733,7 +1733,7 @@ void DatabaseViewer::generate3DMap()
UASSERT(data.imageRaw().empty() || data.imageRaw().type()==CV_8UC3 || data.imageRaw().type() == CV_8UC1);
UASSERT(data.depthOrRightRaw().empty() || data.depthOrRightRaw().type()==CV_8UC1 || data.depthOrRightRaw().type() == CV_16UC1 || data.depthOrRightRaw().type() == CV_32FC1);
pcl::IndicesPtr validIndices(new std::vector<int>);
cloud = util3d::cloudRGBFromSensorData(data, decimation, maxDepth, 0, validIndices.get());
cloud = util3d::cloudRGBFromSensorData(data, decimation, maxDepth, 0, validIndices.get(), ui_->parameters_toolbox->getParameters());
if(assemble)
{
@@ -2275,7 +2275,7 @@ void DatabaseViewer::update(int value,
}
else
{
cloud = util3d::cloudRGBFromSensorData(data);
cloud = util3d::cloudRGBFromSensorData(data, 1, 0, 0, 0, ui_->parameters_toolbox->getParameters());
}
if(cloud->size())
{
@@ -2312,7 +2312,7 @@ void DatabaseViewer::update(int value,
else
{
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud;
cloud = util3d::cloudFromSensorData(data);
cloud = util3d::cloudFromSensorData(data, 1, 0, 0, 0, ui_->parameters_toolbox->getParameters());
if(cloud->size())
{
view3D->addCloud("0", cloud);
@@ -2945,11 +2945,11 @@ void DatabaseViewer::updateConstraintView(
pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloudFrom, cloudTo;
if(!dataFrom.imageRaw().empty() && !dataFrom.depthOrRightRaw().empty())
{
cloudFrom=util3d::cloudRGBFromSensorData(dataFrom, 1);
cloudFrom=util3d::cloudRGBFromSensorData(dataFrom, 1, 0, 0, 0, ui_->parameters_toolbox->getParameters());
}
if(!dataTo.imageRaw().empty() && !dataTo.depthOrRightRaw().empty())
{
cloudTo=util3d::cloudRGBFromSensorData(dataTo, 1);
cloudTo=util3d::cloudRGBFromSensorData(dataTo, 1, 0, 0, 0, ui_->parameters_toolbox->getParameters());
}
if(cloudFrom.get() && cloudFrom->size())
@@ -3080,6 +3080,7 @@ void DatabaseViewer::updateConstraintView(
memcmp(userData.data, "SCANS:", 6) == 0)
{
std::string scansStr = (const char *)userData.data;
UINFO("Detected \"%s\" in links's user data", scansStr.c_str());
if(!scansStr.empty())
{
std::list<std::string> strs = uSplit(scansStr, ':');
@@ -3128,6 +3129,22 @@ void DatabaseViewer::updateConstraintView(
posesOut,
linksOut);
if(poses.size() != posesOut.size())
{
UWARN("Scan poses input and output are different! %d vs %d", (int)poses.size(), (int)posesOut.size());
UWARN("Input poses: ");
for(std::map<int, Transform>::iterator iter=poses.begin(); iter!=poses.end(); ++iter)
{
UWARN(" %d", iter->first);
}
UWARN("Input links: ");
std::multimap<int, Link> modifiedLinks = updateLinksWithModifications(links_);
for(std::multimap<int, Link>::iterator iter=modifiedLinks.begin(); iter!=modifiedLinks.end(); ++iter)
{
UWARN(" %d->%d", iter->second.from(), iter->second.to());
}
}
QTime time;
time.start();
std::map<int, rtabmap::Transform> finalPoses = optimizer->optimize(link.to(), posesOut, linksOut);
@@ -3329,7 +3346,8 @@ void DatabaseViewer::sliderIterationsValueChanged(int value)
ui_->spinBox_projDecimation->value(),
ui_->doubleSpinBox_projMaxDepth->value(),
ui_->doubleSpinBox_projMinDepth->value(),
validIndices.get());
validIndices.get(),
ui_->parameters_toolbox->getParameters());
UASSERT(ui_->doubleSpinBox_gridCellSize->value() > 0);
cloud = util3d::voxelize(cloud, validIndices, ui_->doubleSpinBox_gridCellSize->value());
@@ -3776,12 +3794,16 @@ void DatabaseViewer::refineConstraint(int from, int to, bool silent, bool update
dataFrom,
ui_->spinBox_icp_decimation->value(),
ui_->doubleSpinBox_icp_maxDepth->value(),
ui_->doubleSpinBox_icp_minDepth->value());
ui_->doubleSpinBox_icp_minDepth->value(),
0,
ui_->parameters_toolbox->getParameters());
pcl::PointCloud<pcl::PointXYZ>::Ptr cloudTo = util3d::cloudFromSensorData(
dataTo,
ui_->spinBox_icp_decimation->value(),
ui_->doubleSpinBox_icp_maxDepth->value(),
ui_->doubleSpinBox_icp_minDepth->value());
ui_->doubleSpinBox_icp_minDepth->value(),
0,
ui_->parameters_toolbox->getParameters());
int maxLaserScans = cloudFrom->size();
dataFrom.setLaserScanRaw(util3d::laserScanFromPointCloud(*util3d::removeNaNFromPointCloud(cloudFrom), Transform()), maxLaserScans, 0);
dataTo.setLaserScanRaw(util3d::laserScanFromPointCloud(*util3d::removeNaNFromPointCloud(cloudTo), Transform()), maxLaserScans, 0);

View File

@@ -255,7 +255,7 @@ void ExportCloudsDialog::restoreDefaults()
_ui->spinBox_filteringMinNeighbors->setValue(2);
_ui->checkBox_assemble->setChecked(true);
_ui->doubleSpinBox_voxelSize_assembled->setValue(0.01);
_ui->doubleSpinBox_voxelSize_assembled->setValue(0.0);
_ui->groupBox_subtraction->setChecked(false);
_ui->doubleSpinBox_subtractPointFilteringRadius->setValue(0.02);
@@ -337,7 +337,8 @@ void ExportCloudsDialog::exportClouds(
const std::map<int, int> & mapIds,
const QMap<int, Signature> & cachedSignatures,
const std::map<int, std::pair<pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr, pcl::IndicesPtr> > & createdClouds,
const QString & workingDirectory)
const QString & workingDirectory,
const ParametersMap & parameters)
{
std::map<int, pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr> clouds;
std::map<int, pcl::PolygonMesh::Ptr> meshes;
@@ -351,6 +352,7 @@ void ExportCloudsDialog::exportClouds(
cachedSignatures,
createdClouds,
workingDirectory,
parameters,
clouds,
meshes,
textureMeshes))
@@ -387,7 +389,8 @@ void ExportCloudsDialog::viewClouds(
const std::map<int, int> & mapIds,
const QMap<int, Signature> & cachedSignatures,
const std::map<int, std::pair<pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr, pcl::IndicesPtr> > & createdClouds,
const QString & workingDirectory)
const QString & workingDirectory,
const ParametersMap & parameters)
{
std::map<int, pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr> clouds;
std::map<int, pcl::PolygonMesh::Ptr> meshes;
@@ -401,6 +404,7 @@ void ExportCloudsDialog::viewClouds(
cachedSignatures,
createdClouds,
workingDirectory,
parameters,
clouds,
meshes,
textureMeshes))
@@ -517,6 +521,7 @@ bool ExportCloudsDialog::getExportedClouds(
const QMap<int, Signature> & cachedSignatures,
const std::map<int, std::pair<pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr, pcl::IndicesPtr> > & createdClouds,
const QString & workingDirectory,
const ParametersMap & parameters,
std::map<int, pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr> & cloudsWithNormals,
std::map<int, pcl::PolygonMesh::Ptr> & meshes,
std::map<int, pcl::TextureMesh::Ptr> & textureMeshes)
@@ -550,7 +555,8 @@ bool ExportCloudsDialog::getExportedClouds(
std::map<int, std::pair<pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr, pcl::IndicesPtr> > clouds = this->getClouds(
poses,
cachedSignatures,
createdClouds);
createdClouds,
parameters);
pcl::PointCloud<pcl::PointXYZ>::Ptr rawAssembledCloud(new pcl::PointCloud<pcl::PointXYZ>);
std::vector<int> rawCameraIndices;
@@ -1006,7 +1012,8 @@ bool ExportCloudsDialog::getExportedClouds(
std::map<int, std::pair<pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr, pcl::IndicesPtr> > ExportCloudsDialog::getClouds(
const std::map<int, Transform> & poses,
const QMap<int, Signature> & cachedSignatures,
const std::map<int, std::pair<pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr, pcl::IndicesPtr> > & createdClouds) const
const std::map<int, std::pair<pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr, pcl::IndicesPtr> > & createdClouds,
const ParametersMap & parameters) const
{
std::map<int, std::pair<pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr, pcl::IndicesPtr> > clouds;
int i=0;
@@ -1038,7 +1045,8 @@ std::map<int, std::pair<pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr, pcl::Indic
_ui->spinBox_decimation->value(),
_ui->doubleSpinBox_maxDepth->value(),
_ui->doubleSpinBox_minDepth->value(),
indices.get());
indices.get(),
parameters);
// Don't voxelize if we create organized mesh
if(!(_ui->comboBox_pipeline->currentIndex()==0 && _ui->groupBox_meshing->isChecked()))

View File

@@ -33,6 +33,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <QtCore/QSettings>
#include <rtabmap/core/Signature.h>
#include <rtabmap/core/Parameters.h>
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
@@ -63,14 +64,16 @@ public:
const std::map<int, int> & mapIds,
const QMap<int, Signature> & cachedSignatures,
const std::map<int, std::pair<pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr, pcl::IndicesPtr> > & createdClouds,
const QString & workingDirectory);
const QString & workingDirectory,
const ParametersMap & parameters);
void viewClouds(
const std::map<int, Transform> & poses,
const std::map<int, int> & mapIds,
const QMap<int, Signature> & cachedSignatures,
const std::map<int, std::pair<pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr, pcl::IndicesPtr> > & createdClouds,
const QString & workingDirectory);
const QString & workingDirectory,
const ParametersMap & parameters);
signals:
void configChanged();
@@ -86,13 +89,15 @@ private:
std::map<int, std::pair<pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr, pcl::IndicesPtr> > getClouds(
const std::map<int, Transform> & poses,
const QMap<int, Signature> & cachedSignatures,
const std::map<int, std::pair<pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr, pcl::IndicesPtr> > & createdClouds) const;
const std::map<int, std::pair<pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr, pcl::IndicesPtr> > & createdClouds,
const ParametersMap & parameters) const;
bool getExportedClouds(
const std::map<int, Transform> & poses,
const std::map<int, int> & mapIds,
const QMap<int, Signature> & cachedSignatures,
const std::map<int, std::pair<pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr, pcl::IndicesPtr> > & createdClouds,
const QString & workingDirectory,
const ParametersMap & parameters,
std::map<int, pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr> & clouds,
std::map<int, pcl::PolygonMesh::Ptr> & meshes,
std::map<int, pcl::TextureMesh::Ptr> & textureMeshes);

View File

@@ -29,6 +29,7 @@
<file>images/sense.png</file>
<file>images/xtion_pro_live.png</file>
<file>images/bumblebee2.png</file>
<file>images/webcam.png</file>
<file>images/webcam.png</file>
<file>images/zed.png</file>
</qresource>
</RCC>

View File

@@ -67,7 +67,7 @@ void LoopClosureViewer::setData(const Signature & sA, const Signature & sB)
}
}
void LoopClosureViewer::updateView(const Transform & transform)
void LoopClosureViewer::updateView(const Transform & transform, const ParametersMap & parameters)
{
if(sA_.id()>0 && sB_.id()>0)
{
@@ -106,8 +106,8 @@ void LoopClosureViewer::updateView(const Transform & transform)
if(!t.isNull())
{
//cloud 3d
pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloudA, cloudB;
cloudA = util3d::cloudRGBFromSensorData(sA_.sensorData(), decimation, maxDepth, minDepth);
pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloudA, cloudB;
cloudA = util3d::cloudRGBFromSensorData(sA_.sensorData(), decimation, maxDepth, minDepth, 0, parameters);
cloudB = util3d::cloudRGBFromSensorData(sB_.sensorData(), decimation, maxDepth, minDepth, 0, parameters);
//cloud 2d

View File

@@ -399,6 +399,8 @@ MainWindow::MainWindow(PreferencesDialog * prefDialog, QWidget * parent) :
connect(_ui->actionFreenect2, SIGNAL(triggered()), this, SLOT(selectFreenect2()));
connect(_ui->actionStereoDC1394, SIGNAL(triggered()), this, SLOT(selectStereoDC1394()));
connect(_ui->actionStereoFlyCapture2, SIGNAL(triggered()), this, SLOT(selectStereoFlyCapture2()));
connect(_ui->actionStereoZed, SIGNAL(triggered()), this, SLOT(selectStereoZed()));
connect(_ui->actionStereoUsb, SIGNAL(triggered()), this, SLOT(selectStereoUsb()));
_ui->actionFreenect->setEnabled(CameraFreenect::available());
_ui->actionOpenNI_CV->setEnabled(CameraOpenNICV::available());
_ui->actionOpenNI_CV_ASUS->setEnabled(CameraOpenNICV::available());
@@ -408,6 +410,7 @@ MainWindow::MainWindow(PreferencesDialog * prefDialog, QWidget * parent) :
_ui->actionFreenect2->setEnabled(CameraFreenect2::available());
_ui->actionStereoDC1394->setEnabled(CameraStereoDC1394::available());
_ui->actionStereoFlyCapture2->setEnabled(CameraStereoFlyCapture2::available());
_ui->actionStereoZed->setEnabled(CameraStereoZed::available());
this->updateSelectSourceMenu();
connect(_ui->actionPreferences, SIGNAL(triggered()), this, SLOT(openPreferences()));
@@ -775,6 +778,8 @@ void MainWindow::handleEvent(UEvent* anEvent)
{
// we receive too many odometry events! just send without data
SensorData data(cv::Mat(), odomEvent->data().id(), odomEvent->data().stamp());
data.setCameraModels(odomEvent->data().cameraModels());
data.setStereoCameraModel(odomEvent->data().stereoCameraModel());
data.setGroundTruth(odomEvent->data().groundTruth());
OdometryEvent tmp(data, odomEvent->pose(), odomEvent->covariance(), odomEvent->info().copyWithoutData());
emit odometryReceived(tmp);
@@ -876,63 +881,78 @@ void MainWindow::processOdometry(const rtabmap::OdometryEvent & odom)
(odom.data().cameraModels().size() || odom.data().stereoCameraModel().isValidForProjection()) &&
_preferencesDialog->isCloudsShown(1))
{
pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud;
pcl::IndicesPtr indices(new std::vector<int>);
cloud = util3d::cloudRGBFromSensorData(odom.data(),
_preferencesDialog->getCloudDecimation(1),
_preferencesDialog->getCloudMaxDepth(1),
_preferencesDialog->getCloudMinDepth(1),
indices.get());
if(indices->size())
if(odom.data().imageRaw().cols % _preferencesDialog->getCloudDecimation(1) != 0 ||
odom.data().imageRaw().rows % _preferencesDialog->getCloudDecimation(1) != 0)
{
UERROR("Decimation (%d) is not modulo of the image resolution (%dx%d)! The cloud cannot be "
"created. Go to Preferences->3D Rendering under \"Odom\" column to modify this parameter.",
_preferencesDialog->getCloudDecimation(1),
odom.data().imageRaw().cols,
odom.data().imageRaw().rows);
}
else
{
cloud = util3d::transformPointCloud(cloud, pose);
if(_preferencesDialog->isCloudMeshing())
pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud;
pcl::IndicesPtr indices(new std::vector<int>);
cloud = util3d::cloudRGBFromSensorData(odom.data(),
_preferencesDialog->getCloudDecimation(1),
_preferencesDialog->getCloudMaxDepth(1),
_preferencesDialog->getCloudMinDepth(1),
indices.get(),
_preferencesDialog->getAllParameters());
if(indices->size())
{
// we need to extract indices as pcl::OrganizedFastMesh doesn't take indices
pcl::PointCloud<pcl::PointXYZRGB>::Ptr output(new pcl::PointCloud<pcl::PointXYZRGB>);
output = util3d::extractIndices(cloud, indices, false, true);
cloud = util3d::transformPointCloud(cloud, pose);
// Fast organized mesh
Eigen::Vector3f viewpoint(0.0f,0.0f,0.0f);
if(odom.data().cameraModels().size() && !odom.data().cameraModels()[0].localTransform().isNull())
if(_preferencesDialog->isCloudMeshing())
{
viewpoint[0] = odom.data().cameraModels()[0].localTransform().x();
viewpoint[1] = odom.data().cameraModels()[0].localTransform().y();
viewpoint[2] = odom.data().cameraModels()[0].localTransform().z();
// we need to extract indices as pcl::OrganizedFastMesh doesn't take indices
pcl::PointCloud<pcl::PointXYZRGB>::Ptr output(new pcl::PointCloud<pcl::PointXYZRGB>);
output = util3d::extractIndices(cloud, indices, false, true);
// Fast organized mesh
Eigen::Vector3f viewpoint(0.0f,0.0f,0.0f);
if(odom.data().cameraModels().size() && !odom.data().cameraModels()[0].localTransform().isNull())
{
viewpoint[0] = odom.data().cameraModels()[0].localTransform().x();
viewpoint[1] = odom.data().cameraModels()[0].localTransform().y();
viewpoint[2] = odom.data().cameraModels()[0].localTransform().z();
}
else if(!odom.data().stereoCameraModel().localTransform().isNull())
{
viewpoint[0] = odom.data().stereoCameraModel().localTransform().x();
viewpoint[1] = odom.data().stereoCameraModel().localTransform().y();
viewpoint[2] = odom.data().stereoCameraModel().localTransform().z();
}
std::vector<pcl::Vertices> polygons = util3d::organizedFastMesh(
output,
_preferencesDialog->getCloudMeshingAngle(),
_preferencesDialog->isCloudMeshingQuad(),
_preferencesDialog->getCloudMeshingTriangleSize(),
Eigen::Vector3f(pose.x(), pose.y(), pose.z()) + viewpoint);
if(polygons.size())
{
if(!_cloudViewer->addCloudMesh("cloudOdom", output, polygons, _odometryCorrection))
{
UERROR("Adding cloudOdom to viewer failed!");
}
}
}
else if(!odom.data().stereoCameraModel().localTransform().isNull())
else
{
viewpoint[0] = odom.data().stereoCameraModel().localTransform().x();
viewpoint[1] = odom.data().stereoCameraModel().localTransform().y();
viewpoint[2] = odom.data().stereoCameraModel().localTransform().z();
}
std::vector<pcl::Vertices> polygons = util3d::organizedFastMesh(
output,
_preferencesDialog->getCloudMeshingAngle(),
_preferencesDialog->isCloudMeshingQuad(),
_preferencesDialog->getCloudMeshingTriangleSize(),
Eigen::Vector3f(pose.x(), pose.y(), pose.z()) + viewpoint);
if(polygons.size())
{
if(!_cloudViewer->addCloudMesh("cloudOdom", output, polygons, _odometryCorrection))
if(!_cloudViewer->addCloud("cloudOdom", cloud, _odometryCorrection))
{
UERROR("Adding cloudOdom to viewer failed!");
}
}
}
else
{
if(!_cloudViewer->addCloud("cloudOdom", cloud, _odometryCorrection))
{
UERROR("Adding cloudOdom to viewer failed!");
}
}
_cloudViewer->setCloudVisibility("cloudOdom", true);
_cloudViewer->setCloudOpacity("cloudOdom", _preferencesDialog->getCloudOpacity(1));
_cloudViewer->setCloudPointSize("cloudOdom", _preferencesDialog->getCloudPointSize(1));
_cloudViewer->setCloudVisibility("cloudOdom", true);
_cloudViewer->setCloudOpacity("cloudOdom", _preferencesDialog->getCloudOpacity(1));
_cloudViewer->setCloudPointSize("cloudOdom", _preferencesDialog->getCloudPointSize(1));
cloudUpdated = true;
cloudUpdated = true;
}
}
}
@@ -1036,7 +1056,17 @@ void MainWindow::processOdometry(const rtabmap::OdometryEvent & odom)
if(!odom.pose().isNull())
{
// update camera position
_cloudViewer->updateCameraTargetPosition(_odometryCorrection*odom.pose());
Transform localTransform;
if(odom.data().cameraModels().size() && !odom.data().cameraModels()[0].localTransform().isNull())
{
localTransform = odom.data().cameraModels()[0].localTransform();
}
else if(!odom.data().stereoCameraModel().localTransform().isNull())
{
localTransform = odom.data().stereoCameraModel().localTransform();
}
_cloudViewer->updateCameraTargetPosition(_odometryCorrection*odom.pose(), localTransform);
}
_cloudViewer->update();
@@ -1527,9 +1557,30 @@ void MainWindow::processStats(const rtabmap::Statistics & stat)
Transform groundTruthOffset = alignPosesToGroundTruth(poses, groundTruth);
UDEBUG("time= %d ms", time.restart());
if(!_odometryReceived && poses.size())
{
Transform localTransform = Transform::getIdentity();
std::map<int, Signature>::const_iterator iter = stat.getSignatures().find(poses.rbegin()->first);
if(iter != stat.getSignatures().end())
{
if(iter->second.sensorData().cameraModels().size() && !iter->second.sensorData().cameraModels()[0].localTransform().isNull())
{
localTransform = iter->second.sensorData().cameraModels()[0].localTransform();
}
else if(!iter->second.sensorData().stereoCameraModel().localTransform().isNull())
{
localTransform = iter->second.sensorData().stereoCameraModel().localTransform();
}
}
_cloudViewer->updateCameraTargetPosition(poses.rbegin()->second, localTransform);
if(_ui->graphicsView_graphView->isVisible())
{
_ui->graphicsView_graphView->updateReferentialPosition(poses.rbegin()->second);
}
}
updateMapCloud(
poses,
_odometryReceived||poses.size()==0?Transform():poses.rbegin()->second,
stat.constraints(),
mapIds,
labels,
@@ -1554,7 +1605,7 @@ void MainWindow::processStats(const rtabmap::Statistics & stat)
if(_ui->dockWidget_loopClosureViewer->isVisible())
{
UTimer loopTimer;
_loopClosureViewer->updateView();
_loopClosureViewer->updateView(Transform(), _preferencesDialog->getAllParameters());
UINFO("Updating loop closure cloud view time=%fs", loopTimer.elapsed());
_ui->statsToolBox->updateStat("GUI/RGB-D closure view/ms", stat.refImageId(), int(loopTimer.elapsed()*1000.0f));
}
@@ -1725,15 +1776,14 @@ void MainWindow::processStats(const rtabmap::Statistics & stat)
void MainWindow::updateMapCloud(
const std::map<int, Transform> & posesIn,
const Transform & currentPose,
const std::multimap<int, Link> & constraints,
const std::map<int, int> & mapIdsIn,
const std::map<int, std::string> & labels,
const std::map<int, Transform> & groundTruths, // ground truth should contain only valid transforms
bool verboseProgress)
{
UDEBUG("posesIn=%d constraints=%d mapIdsIn=%d labelsIn=%d currentPose=%s",
(int)posesIn.size(), (int)constraints.size(), (int)mapIdsIn.size(), (int)labels.size(), currentPose.prettyPrint().c_str());
UDEBUG("posesIn=%d constraints=%d mapIdsIn=%d labelsIn=%d",
(int)posesIn.size(), (int)constraints.size(), (int)mapIdsIn.size(), (int)labels.size());
if(posesIn.size())
{
_currentPosesMap = posesIn;
@@ -1810,7 +1860,7 @@ void MainWindow::updateMapCloud(
}
// Map updated! regenerate the assembled cloud, last pose is the new one
UDEBUG("Update map with %d locations (currentPose=%s)", poses.size(), currentPose.prettyPrint().c_str());
UDEBUG("Update map with %d locations", poses.size());
QMap<std::string, Transform> viewerClouds = _cloudViewer->getAddedClouds();
int i=1;
for(std::map<int, Transform>::const_iterator iter = poses.begin(); iter!=poses.end(); ++iter)
@@ -1835,13 +1885,17 @@ void MainWindow::updateMapCloud(
UERROR("Updating pose cloud %d failed!", iter->first);
}
}
_cloudViewer->setCloudVisibility(cloudName, true);
_cloudViewer->setCloudVisibility(cloudName, (_cloudViewer->isVisible() && _preferencesDialog->isCloudsShown(0)));
_cloudViewer->setCloudOpacity(cloudName, _preferencesDialog->getCloudOpacity(0));
_cloudViewer->setCloudPointSize(cloudName, _preferencesDialog->getCloudPointSize(0));
}
else if(_cachedSignatures.contains(iter->first))
else if(_createdClouds.find(iter->first) == _createdClouds.end() && _cachedSignatures.contains(iter->first))
{
this->createAndAddCloudToMap(iter->first, iter->second, uValue(mapIds, iter->first, -1));
if(_createdClouds.find(iter->first) != _createdClouds.end())
{
_cloudViewer->setCloudVisibility(cloudName.c_str(), _cloudViewer->isVisible() && _preferencesDialog->isCloudsShown(0));
}
}
}
else if(viewerClouds.contains(cloudName))
@@ -2040,11 +2094,6 @@ void MainWindow::updateMapCloud(
if(_ui->graphicsView_graphView->isVisible())
{
_ui->graphicsView_graphView->updateGraph(posesIn, constraints, mapIdsIn);
if(!currentPose.isNull())
{
_ui->graphicsView_graphView->updateReferentialPosition(currentPose);
}
_ui->graphicsView_graphView->updateGTGraph(_currentGTPosesMap);
}
cv::Mat map8U;
@@ -2147,12 +2196,6 @@ void MainWindow::updateMapCloud(
}
}
if(!currentPose.isNull())
{
UDEBUG("");
_cloudViewer->updateCameraTargetPosition(currentPose);
}
UDEBUG("");
_cloudViewer->update();
UDEBUG("");
@@ -2192,12 +2235,25 @@ void MainWindow::createAndAddCloudToMap(int nodeId, const Transform & pose, int
pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloudWithoutNormals;
pcl::IndicesPtr indices(new std::vector<int>);
UASSERT(nodeId == data.id());
if(image.cols % _preferencesDialog->getCloudDecimation(0) != 0 ||
image.rows % _preferencesDialog->getCloudDecimation(0) != 0)
{
UERROR("Decimation (%d) is not modulo of the image resolution (%dx%d)! The cloud cannot be "
"created. Go to Preferences->3D Rendering under \"Map\" column to modify this parameter.",
_preferencesDialog->getCloudDecimation(0),
image.cols,
image.rows);
return;
}
// Create organized cloud
cloudWithoutNormals = util3d::cloudRGBFromSensorData(data,
_preferencesDialog->getCloudDecimation(0),
_preferencesDialog->getCloudMaxDepth(0),
_preferencesDialog->getCloudMinDepth(0),
indices.get());
indices.get(),
_preferencesDialog->getAllParameters());
//compute normals
pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr cloud = util3d::computeNormals(cloudWithoutNormals, 10);
@@ -2209,14 +2265,14 @@ void MainWindow::createAndAddCloudToMap(int nodeId, const Transform & pose, int
float groundNormalMaxAngle = M_PI_4;
int minClusterSize = 20;
cv::Mat ground, obstacles;
pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr voxelCloud = util3d::voxelize(cloud, indices, cellSize);
pcl::PointCloud<pcl::PointXYZRGB>::Ptr voxelCloud = util3d::voxelize(cloudWithoutNormals, indices, cellSize);
// add pose rotation without yaw
float roll, pitch, yaw;
pose.getEulerAngles(roll, pitch, yaw);
voxelCloud = util3d::transformPointCloud(voxelCloud, Transform(0,0,0, roll, pitch, 0));
util3d::occupancy2DFromCloud3D<pcl::PointXYZRGBNormal>(
util3d::occupancy2DFromCloud3D<pcl::PointXYZRGB>(
voxelCloud,
ground,
obstacles,
@@ -2538,7 +2594,7 @@ Transform MainWindow::alignPosesToGroundTruth(
Transform t = Transform::getIdentity();
if(groundTruth.size() && poses.size())
{
unsigned int maxSize = poses.size()>groundTruth.size()?poses.size():groundTruth.size();
unsigned int maxSize = poses.size()>groundTruth.size()? (unsigned int)poses.size(): (unsigned int)groundTruth.size();
pcl::PointCloud<pcl::PointXYZ> cloud1, cloud2;
cloud1.resize(maxSize);
cloud2.resize(maxSize);
@@ -2813,7 +2869,7 @@ void MainWindow::processRtabmapEvent3DMap(const rtabmap::RtabmapEvent3DMap & eve
QApplication::processEvents();
std::map<int, Transform> poses = event.getPoses();
alignPosesToGroundTruth(poses, groundTruth);
this->updateMapCloud(poses, Transform(), event.getConstraints(), mapIds, labels, groundTruth, true);
this->updateMapCloud(poses, event.getConstraints(), mapIds, labels, groundTruth, true);
_initProgressDialog->appendText("Updating the 3D map cloud... done.");
}
else
@@ -2957,7 +3013,6 @@ void MainWindow::applyPrefSettings(PreferencesDialog::PANEL_FLAGS flags)
{
this->updateMapCloud(
std::map<int, Transform>(_currentPosesMap),
Transform(),
std::multimap<int, Link>(_currentLinksMap),
std::map<int, int>(_currentMapIds),
std::map<int, std::string>(_currentLabels),
@@ -3219,7 +3274,10 @@ void MainWindow::updateSelectSourceMenu()
_preferencesDialog->getSourceDriver() == PreferencesDialog::kSrcDatabase ||
_preferencesDialog->getSourceDriver() == PreferencesDialog::kSrcImages ||
_preferencesDialog->getSourceDriver() == PreferencesDialog::kSrcVideo ||
_preferencesDialog->getSourceDriver() == PreferencesDialog::kSrcStereoImages);
_preferencesDialog->getSourceDriver() == PreferencesDialog::kSrcStereoImages ||
_preferencesDialog->getSourceDriver() == PreferencesDialog::kSrcStereoVideo ||
_preferencesDialog->getSourceDriver() == PreferencesDialog::kSrcRGBDImages
);
_ui->actionOpenNI_PCL->setChecked(_preferencesDialog->getSourceDriver() == PreferencesDialog::kSrcOpenNI_PCL);
_ui->actionOpenNI_PCL_ASUS->setChecked(_preferencesDialog->getSourceDriver() == PreferencesDialog::kSrcOpenNI_PCL);
@@ -3232,6 +3290,8 @@ void MainWindow::updateSelectSourceMenu()
_ui->actionFreenect2->setChecked(_preferencesDialog->getSourceDriver() == PreferencesDialog::kSrcFreenect2);
_ui->actionStereoDC1394->setChecked(_preferencesDialog->getSourceDriver() == PreferencesDialog::kSrcDC1394);
_ui->actionStereoFlyCapture2->setChecked(_preferencesDialog->getSourceDriver() == PreferencesDialog::kSrcFlyCapture2);
_ui->actionStereoZed->setChecked(_preferencesDialog->getSourceDriver() == PreferencesDialog::kSrcStereoZed);
_ui->actionStereoUsb->setChecked(_preferencesDialog->getSourceDriver() == PreferencesDialog::kSrcStereoUsb);
}
void MainWindow::changeImgRateSetting()
@@ -4289,7 +4349,6 @@ void MainWindow::postProcessing()
alignPosesToGroundTruth(optimizedPoses, _currentGTPosesMap);
this->updateMapCloud(
optimizedPoses,
Transform(),
std::multimap<int, Link>(_currentLinksMap),
std::map<int, int>(_currentMapIds),
std::map<int, std::string>(_currentLabels),
@@ -4429,7 +4488,15 @@ void MainWindow::selectStereoFlyCapture2()
{
_preferencesDialog->selectSourceDriver(PreferencesDialog::kSrcFlyCapture2);
}
void MainWindow::selectStereoZed()
{
_preferencesDialog->selectSourceDriver(PreferencesDialog::kSrcStereoZed);
}
void MainWindow::selectStereoUsb()
{
_preferencesDialog->selectSourceDriver(PreferencesDialog::kSrcStereoUsb);
}
void MainWindow::dumpTheMemory()
{
@@ -4652,7 +4719,6 @@ void MainWindow::anchorCloudsToGroundTruth()
{
this->updateMapCloud(
std::map<int, Transform>(_currentPosesMap),
Transform(),
std::multimap<int, Link>(_currentLinksMap),
std::map<int, int>(_currentMapIds),
std::map<int, std::string>(_currentLabels),
@@ -5070,7 +5136,8 @@ void MainWindow::exportClouds()
_currentMapIds,
_cachedSignatures,
_createdClouds,
_preferencesDialog->getWorkingDirectory());
_preferencesDialog->getWorkingDirectory(),
_preferencesDialog->getAllParameters());
}
void MainWindow::viewClouds()
@@ -5085,7 +5152,8 @@ void MainWindow::viewClouds()
_currentMapIds,
_cachedSignatures,
_createdClouds,
_preferencesDialog->getWorkingDirectory());
_preferencesDialog->getWorkingDirectory(),
_preferencesDialog->getAllParameters());
}

View File

@@ -49,7 +49,14 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace rtabmap {
OdometryViewer::OdometryViewer(int maxClouds, int decimation, float voxelSize, float maxDepth, int qualityWarningThr, QWidget * parent) :
OdometryViewer::OdometryViewer(
int maxClouds,
int decimation,
float voxelSize,
float maxDepth,
int qualityWarningThr,
QWidget * parent,
const ParametersMap & parameters) :
QDialog(parent),
imageView_(new ImageView(this)),
cloudView_(new CloudViewer(this)),
@@ -59,7 +66,8 @@ OdometryViewer::OdometryViewer(int maxClouds, int decimation, float voxelSize, f
lastOdomPose_(Transform::getIdentity()),
qualityWarningThr_(qualityWarningThr),
id_(0),
validDecimationValue_(1)
validDecimationValue_(1),
parameters_(parameters)
{
qRegisterMetaType<rtabmap::OdometryEvent>("rtabmap::OdometryEvent");
@@ -241,7 +249,8 @@ void OdometryViewer::processData(const rtabmap::OdometryEvent & odom)
validDecimationValue_,
0,
0,
validIndices.get());
validIndices.get(),
parameters_);
if(voxelSpin_->value())
{

View File

@@ -237,6 +237,11 @@ PreferencesDialog::PreferencesDialog(QWidget * parent) :
{
_ui->comboBox_cameraStereo->setItemData(1, 0, Qt::UserRole - 1);
}
if (!CameraStereoZed::available())
{
_ui->comboBox_cameraRGBD->setItemData(7, 0, Qt::UserRole - 1);
_ui->comboBox_cameraStereo->setItemData(4, 0, Qt::UserRole - 1);
}
_ui->openni2_exposure->setEnabled(CameraOpenNI2::exposureGainAvailable());
_ui->openni2_gain->setEnabled(CameraOpenNI2::exposureGainAvailable());
@@ -466,6 +471,13 @@ PreferencesDialog::PreferencesDialog(QWidget * parent) :
connect(_ui->lineEdit_cameraStereoVideo_path, SIGNAL(textChanged(const QString &)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->checkBox_stereoVideo_rectify, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->comboBox_stereoZed_resolution, SIGNAL(currentIndexChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->comboBox_stereoZed_quality, SIGNAL(currentIndexChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->comboBox_stereoZed_sensingMode, SIGNAL(currentIndexChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->spinBox_stereoZed_confidenceThr, SIGNAL(valueChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->toolButton_zedSvoPath, SIGNAL(clicked()), this, SLOT(selectSourceSvoPath()));
connect(_ui->lineEdit_zedSvoPath, SIGNAL(textChanged(const QString &)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->checkbox_rgbd_colorOnly, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->spinBox_source_imageDecimation, SIGNAL(valueChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->checkbox_stereo_depthGenerated, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
@@ -684,7 +696,6 @@ PreferencesDialog::PreferencesDialog(QWidget * parent) :
_ui->localDetection_pathFilteringRadius->setObjectName(Parameters::kRGBDProximityPathFilteringRadius().c_str());
_ui->localDetection_angle->setObjectName(Parameters::kRGBDProximityAngle().c_str());
_ui->checkBox_localSpacePathOdomPosesUsed->setObjectName(Parameters::kRGBDProximityPathRawPosesUsed().c_str());
_ui->checkBox_localSpaceAssembleScans->setObjectName(Parameters::kRGBDProximityPathScansMerged().c_str());
_ui->rgdb_localImmunizationRatio->setObjectName(Parameters::kRGBDLocalImmunizationRatio().c_str());
_ui->loopClosure_reextract->setObjectName(Parameters::kRGBDLoopClosureReextractFeatures().c_str());
@@ -1142,7 +1153,7 @@ void PreferencesDialog::resetSettings(QGroupBox * groupBox)
for(int i=0; i<2; ++i)
{
_3dRenderingShowClouds[i]->setChecked(true);
_3dRenderingDecimation[i]->setValue(8);
_3dRenderingDecimation[i]->setValue(4);
_3dRenderingMaxDepth[i]->setValue(0.0);
_3dRenderingMinDepth[i]->setValue(0.0);
_3dRenderingShowScans[i]->setChecked(true);
@@ -1272,6 +1283,11 @@ void PreferencesDialog::resetSettings(QGroupBox * groupBox)
_ui->checkBox_stereoImages_rectify->setChecked(false);
_ui->lineEdit_cameraStereoVideo_path->setText("");
_ui->checkBox_stereoVideo_rectify->setChecked(false);
_ui->comboBox_stereoZed_resolution->setCurrentIndex(2);
_ui->comboBox_stereoZed_quality->setCurrentIndex(1);
_ui->comboBox_stereoZed_sensingMode->setCurrentIndex(1);
_ui->spinBox_stereoZed_confidenceThr->setValue(100);
_ui->lineEdit_zedSvoPath->clear();
_ui->checkBox_cameraImages_timestamps->setChecked(false);
_ui->checkBox_cameraImages_syncTimeStamps->setChecked(true);
@@ -1596,6 +1612,15 @@ void PreferencesDialog::readCameraSettings(const QString & filePath)
_ui->checkBox_stereoVideo_rectify->setChecked(settings.value("rectify",_ui->checkBox_stereoVideo_rectify->isChecked()).toBool());
settings.endGroup(); // StereoVideo
settings.beginGroup("StereoZed");
_ui->comboBox_stereoZed_resolution->setCurrentIndex(settings.value("resolution", _ui->comboBox_stereoZed_resolution->currentIndex()).toInt());
_ui->comboBox_stereoZed_quality->setCurrentIndex(settings.value("quality", _ui->comboBox_stereoZed_quality->currentIndex()).toInt());
_ui->comboBox_stereoZed_sensingMode->setCurrentIndex(settings.value("sensing_mode", _ui->comboBox_stereoZed_sensingMode->currentIndex()).toInt());
_ui->spinBox_stereoZed_confidenceThr->setValue(settings.value("confidence_thr", _ui->spinBox_stereoZed_confidenceThr->value()).toInt());
_ui->lineEdit_zedSvoPath->setText(settings.value("svo_path", _ui->lineEdit_zedSvoPath->text()).toString());
settings.endGroup(); // StereoZed
settings.beginGroup("Images");
_ui->source_images_lineEdit_path->setText(settings.value("path", _ui->source_images_lineEdit_path->text()).toString());
_ui->source_images_spinBox_startPos->setValue(settings.value("startPos",_ui->source_images_spinBox_startPos->value()).toInt());
@@ -1980,6 +2005,16 @@ void PreferencesDialog::writeCameraSettings(const QString & filePath) const
settings.setValue("rectify", _ui->checkBox_stereoVideo_rectify->isChecked());
settings.endGroup(); // StereoVideo
settings.beginGroup("StereoZed");
settings.setValue("resolution", _ui->comboBox_stereoZed_resolution->currentIndex());
settings.setValue("quality", _ui->comboBox_stereoZed_quality->currentIndex());
settings.setValue("sensing_mode", _ui->comboBox_stereoZed_sensingMode->currentIndex());
settings.setValue("confidence_thr", _ui->spinBox_stereoZed_confidenceThr->value());
settings.setValue("svo_path", _ui->lineEdit_zedSvoPath->text());
settings.endGroup(); // StereoZed
settings.beginGroup("Images");
settings.setValue("path", _ui->source_images_lineEdit_path->text());
settings.setValue("startPos", _ui->source_images_spinBox_startPos->value());
@@ -2557,17 +2592,16 @@ void PreferencesDialog::selectSourceDriver(Src src)
else if(src >= kSrcStereo && src<kSrcRGB)
{
_ui->comboBox_sourceType->setCurrentIndex(1);
_ui->comboBox_cameraRGBD->setCurrentIndex(src - kSrcStereo);
_ui->comboBox_cameraStereo->setCurrentIndex(src - kSrcStereo);
}
else if(src >= kSrcRGB && src<kSrcDatabase)
{
_ui->comboBox_sourceType->setCurrentIndex(2);
_ui->comboBox_cameraRGBD->setCurrentIndex(src - kSrcRGB);
_ui->source_comboBox_image_type->setCurrentIndex(src - kSrcRGB);
}
else if(src >= kSrcDatabase)
{
_ui->comboBox_sourceType->setCurrentIndex(3);
_ui->comboBox_cameraRGBD->setCurrentIndex(src - kSrcDatabase);
}
if(validateForm())
@@ -2816,6 +2850,20 @@ void PreferencesDialog::selectSourceOni2Path()
}
}
void PreferencesDialog::selectSourceSvoPath()
{
QString dir = _ui->lineEdit_zedSvoPath->text();
if(dir.isEmpty())
{
dir = getWorkingDirectory();
}
QString path = QFileDialog::getOpenFileName(this, tr("Select file"), _ui->lineEdit_zedSvoPath->text(), tr("ZED (*.svo)"));
if(!path.isEmpty())
{
_ui->lineEdit_zedSvoPath->setText(path);
}
}
void PreferencesDialog::setParameter(const std::string & key, const std::string & value)
{
UDEBUG("%s=%s", key.c_str(), value.c_str());
@@ -3428,8 +3476,13 @@ void PreferencesDialog::updateSourceGrpVisibility()
_ui->groupBox_cameraRGBDImages->setVisible(_ui->comboBox_sourceType->currentIndex() == 0 && _ui->comboBox_cameraRGBD->currentIndex() == kSrcRGBDImages-kSrcRGBD);
_ui->groupBox_openni->setVisible(_ui->comboBox_sourceType->currentIndex() == 0 && _ui->comboBox_cameraRGBD->currentIndex() == kSrcOpenNI_PCL-kSrcRGBD);
_ui->stackedWidget_stereo->setVisible(_ui->comboBox_sourceType->currentIndex() == 1 && (_ui->comboBox_cameraStereo->currentIndex() == kSrcStereoVideo-kSrcStereo || _ui->comboBox_cameraStereo->currentIndex() == kSrcStereoImages-kSrcStereo));
_ui->stackedWidget_stereo->setVisible(_ui->comboBox_sourceType->currentIndex() == 1 &&
(_ui->comboBox_cameraStereo->currentIndex() == kSrcStereoVideo-kSrcStereo ||
_ui->comboBox_cameraStereo->currentIndex() == kSrcStereoImages-kSrcStereo ||
_ui->comboBox_cameraStereo->currentIndex() == kSrcStereoZed - kSrcStereo));
_ui->groupBox_cameraStereoImages->setVisible(_ui->comboBox_sourceType->currentIndex() == 1 && _ui->comboBox_cameraStereo->currentIndex() == kSrcStereoImages-kSrcStereo);
_ui->groupBox_cameraStereoVideo->setVisible(_ui->comboBox_sourceType->currentIndex() == 1 && _ui->comboBox_cameraStereo->currentIndex() == kSrcStereoVideo - kSrcStereo);
_ui->groupBox_cameraStereoZed->setVisible(_ui->comboBox_sourceType->currentIndex() == 1 && _ui->comboBox_cameraStereo->currentIndex() == kSrcStereoZed - kSrcStereo);
_ui->stackedWidget_image->setVisible(_ui->comboBox_sourceType->currentIndex() == 2 && (_ui->source_comboBox_image_type->currentIndex() == kSrcImages-kSrcRGB || _ui->source_comboBox_image_type->currentIndex() == kSrcVideo-kSrcRGB));
_ui->source_groupBox_images->setVisible(_ui->comboBox_sourceType->currentIndex() == 2 && _ui->source_comboBox_image_type->currentIndex() == kSrcImages-kSrcRGB);
@@ -3949,6 +4002,13 @@ Camera * PreferencesDialog::createCamera(bool useRawImages)
_ui->lineEdit_cameraImages_timestamps->text().toStdString(),
_ui->checkBox_cameraImages_syncTimeStamps->isChecked());
}
else if (driver == kSrcStereoUsb)
{
camera = new CameraStereoVideo(
this->getSourceDevice().isEmpty() ? 0 : atoi(this->getSourceDevice().toStdString().c_str()),
this->getGeneralInputRate(),
this->getSourceLocalTransform());
}
else if(driver == kSrcStereoVideo)
{
camera = new CameraStereoVideo(
@@ -3957,6 +4017,30 @@ Camera * PreferencesDialog::createCamera(bool useRawImages)
this->getGeneralInputRate(),
this->getSourceLocalTransform());
}
else if (driver == kSrcStereoZed)
{
if(!_ui->lineEdit_zedSvoPath->text().isEmpty())
{
camera = new CameraStereoZed(
_ui->lineEdit_zedSvoPath->text().toStdString(),
_ui->comboBox_stereoZed_quality->currentIndex(),
_ui->comboBox_stereoZed_sensingMode->currentIndex(),
_ui->spinBox_stereoZed_confidenceThr->value(),
this->getGeneralInputRate(),
this->getSourceLocalTransform());
}
else
{
camera = new CameraStereoZed(
this->getSourceDevice().isEmpty()?0:atoi(this->getSourceDevice().toStdString().c_str()),
_ui->comboBox_stereoZed_resolution->currentIndex(),
_ui->comboBox_stereoZed_quality->currentIndex(),
_ui->comboBox_stereoZed_sensingMode->currentIndex(),
_ui->spinBox_stereoZed_confidenceThr->value(),
this->getGeneralInputRate(),
this->getSourceLocalTransform());
}
}
else if(driver == kSrcUsbDevice)
{
camera = new CameraVideo(
@@ -4220,7 +4304,8 @@ void PreferencesDialog::testOdometry()
0.0f,
_ui->doubleSpinBox_maxDepth_odom->value(),
this->getOdomQualityWarnThr(),
this);
this,
this->getAllParameters());
odomViewer->setWindowTitle(tr("Odometry viewer"));
odomViewer->resize(1280, 480+QPushButton().minimumHeight());
odomViewer->registerToEventsManager();
@@ -4270,7 +4355,7 @@ void PreferencesDialog::testOdometry()
void PreferencesDialog::testCamera()
{
CameraViewer * window = new CameraViewer(this);
CameraViewer * window = new CameraViewer(this, this->getAllParameters());
window->setWindowTitle(tr("Camera viewer"));
window->resize(1280, 480+QPushButton().minimumHeight());
window->registerToEventsManager();

BIN
guilib/src/images/zed.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

File diff suppressed because it is too large Load Diff

View File

@@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>1012</width>
<height>711</height>
<height>712</height>
</rect>
</property>
<property name="windowTitle">
@@ -27,7 +27,7 @@
<x>0</x>
<y>0</y>
<width>1012</width>
<height>25</height>
<height>21</height>
</rect>
</property>
<widget class="QMenu" name="menuFile">
@@ -190,7 +190,19 @@
<addaction name="actionStereoDC1394"/>
<addaction name="actionStereoFlyCapture2"/>
</widget>
<widget class="QMenu" name="menuZed_camera">
<property name="title">
<string>Zed camera</string>
</property>
<property name="icon">
<iconset resource="../GuiLib.qrc">
<normaloff>:/images/zed.png</normaloff>:/images/zed.png</iconset>
</property>
<addaction name="actionStereoZed"/>
<addaction name="actionStereoUsb"/>
</widget>
<addaction name="menuBumblebee2_2"/>
<addaction name="menuZed_camera"/>
</widget>
<addaction name="menuRGB_D_camera"/>
<addaction name="menuStereo_camera"/>
@@ -1325,7 +1337,7 @@
<bool>true</bool>
</property>
<property name="text">
<string>More options...</string>
<string>More Options...</string>
</property>
</action>
<action name="actionLabel_current_location">
@@ -1391,6 +1403,22 @@
<string>Anchor clouds to ground truth</string>
</property>
</action>
<action name="actionStereoZed">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Zed sdk</string>
</property>
</action>
<action name="actionStereoUsb">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Stereo Usb Camera</string>
</property>
</action>
</widget>
<customwidgets>
<customwidget>

View File

@@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>984</width>
<height>693</height>
<height>713</height>
</rect>
</property>
<property name="sizePolicy">
@@ -63,7 +63,7 @@
<property name="geometry">
<rect>
<x>0</x>
<y>-466</y>
<y>-477</y>
<width>686</width>
<height>2023</height>
</rect>
@@ -86,7 +86,7 @@
<enum>QFrame::Raised</enum>
</property>
<property name="currentIndex">
<number>1</number>
<number>3</number>
</property>
<widget class="QWidget" name="page_22">
<layout class="QVBoxLayout" name="verticalLayout_29" stretch="0,1">
@@ -2006,7 +2006,7 @@ when using the file type, logs are saved in LogRtabmap.txt (located in the worki
<item>
<widget class="QStackedWidget" name="stackedWidget_src">
<property name="currentIndex">
<number>3</number>
<number>1</number>
</property>
<widget class="QWidget" name="page_41">
<layout class="QVBoxLayout" name="verticalLayout_64">
@@ -2111,7 +2111,7 @@ when using the file type, logs are saved in LogRtabmap.txt (located in the worki
<item>
<widget class="QStackedWidget" name="stackedWidget_rgbd">
<property name="currentIndex">
<number>6</number>
<number>0</number>
</property>
<widget class="QWidget" name="page_32">
<layout class="QVBoxLayout" name="verticalLayout_63">
@@ -2182,7 +2182,7 @@ when using the file type, logs are saved in LogRtabmap.txt (located in the worki
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>306</height>
<height>0</height>
</size>
</property>
</spacer>
@@ -2199,7 +2199,7 @@ when using the file type, logs are saved in LogRtabmap.txt (located in the worki
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>306</height>
<height>0</height>
</size>
</property>
</spacer>
@@ -2216,7 +2216,7 @@ when using the file type, logs are saved in LogRtabmap.txt (located in the worki
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>306</height>
<height>0</height>
</size>
</property>
</spacer>
@@ -2730,7 +2730,7 @@ when using the file type, logs are saved in LogRtabmap.txt (located in the worki
<item>
<widget class="QLabel" name="label_46">
<property name="text">
<string>Grabber for stereo devices (i.e., Bumblebee2).</string>
<string>Grabber for stereo devices (i.e., Bumblebee2, Zed camera).</string>
</property>
<property name="wordWrap">
<bool>true</bool>
@@ -2764,12 +2764,22 @@ when using the file type, logs are saved in LogRtabmap.txt (located in the worki
<string>Video (Side-by-Side)</string>
</property>
</item>
<item>
<property name="text">
<string>ZED sdk</string>
</property>
</item>
<item>
<property name="text">
<string>Usb camera (Side-by-Side)</string>
</property>
</item>
</widget>
</item>
<item row="0" column="2">
<widget class="QLabel" name="label_240">
<property name="text">
<string>Driver</string>
<string>Driver.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
@@ -2786,7 +2796,7 @@ when using the file type, logs are saved in LogRtabmap.txt (located in the worki
<item row="1" column="2">
<widget class="QLabel" name="label_247">
<property name="text">
<string>Generate disparity image and convert it to depth. The resulting output is a RGB-D image instead of stereo images.</string>
<string>Generate disparity image and convert it to depth. The resulting output is a RGB-D image instead of stereo images. Dense disparity parameters can found under StereoBM tab.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
@@ -2798,7 +2808,7 @@ when using the file type, logs are saved in LogRtabmap.txt (located in the worki
<item>
<widget class="QStackedWidget" name="stackedWidget_stereo">
<property name="currentIndex">
<number>3</number>
<number>4</number>
</property>
<widget class="QWidget" name="page_49">
<layout class="QVBoxLayout" name="verticalLayout_91">
@@ -2810,7 +2820,7 @@ when using the file type, logs are saved in LogRtabmap.txt (located in the worki
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>306</height>
<height>0</height>
</size>
</property>
</spacer>
@@ -2827,7 +2837,7 @@ when using the file type, logs are saved in LogRtabmap.txt (located in the worki
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>306</height>
<height>0</height>
</size>
</property>
</spacer>
@@ -2943,7 +2953,7 @@ when using the file type, logs are saved in LogRtabmap.txt (located in the worki
<widget class="QWidget" name="page_50">
<layout class="QVBoxLayout" name="verticalLayout_78">
<item>
<widget class="QGroupBox" name="groupBox_cameraStereoImages_2">
<widget class="QGroupBox" name="groupBox_cameraStereoVideo">
<property name="sizePolicy">
<sizepolicy hsizetype="Ignored" vsizetype="Ignored">
<horstretch>0</horstretch>
@@ -3006,6 +3016,202 @@ when using the file type, logs are saved in LogRtabmap.txt (located in the worki
</item>
</layout>
</widget>
<widget class="QWidget" name="page_59">
<layout class="QVBoxLayout" name="verticalLayout_101">
<item>
<widget class="QGroupBox" name="groupBox_cameraStereoZed">
<property name="sizePolicy">
<sizepolicy hsizetype="Ignored" vsizetype="Ignored">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Zed sdk</string>
</property>
<layout class="QGridLayout" name="gridLayout_37" columnstretch="0,1">
<item row="2" column="0">
<widget class="QComboBox" name="comboBox_stereoZed_sensingMode">
<item>
<property name="text">
<string>FULL</string>
</property>
</item>
<item>
<property name="text">
<string>RAW</string>
</property>
</item>
</widget>
</item>
<item row="4" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_8">
<item>
<widget class="QToolButton" name="toolButton_zedSvoPath">
<property name="text">
<string>...</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="lineEdit_zedSvoPath">
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</item>
<item row="0" column="0">
<widget class="QComboBox" name="comboBox_stereoZed_resolution">
<item>
<property name="text">
<string>HD2K</string>
</property>
</item>
<item>
<property name="text">
<string>HD1080</string>
</property>
</item>
<item>
<property name="text">
<string>HD720</string>
</property>
</item>
<item>
<property name="text">
<string>VGA</string>
</property>
</item>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="label_274">
<property name="text">
<string>Resolution. Not used when a SVO file is used.</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="QComboBox" name="comboBox_stereoZed_quality">
<item>
<property name="text">
<string>NONE</string>
</property>
</item>
<item>
<property name="text">
<string>PERFORMANCE</string>
</property>
</item>
<item>
<property name="text">
<string>QUALITY</string>
</property>
</item>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="label_290">
<property name="text">
<string>Quality. If NONE, the disparity is not computed on the GPU.</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="1">
<widget class="QLabel" name="label_291">
<property name="text">
<string>Sensing mode.</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="1">
<widget class="QLabel" name="label_305">
<property name="text">
<string>Path to a *.SVO file.</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">
<spacer name="verticalSpacer_54">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>13</height>
</size>
</property>
</spacer>
</item>
<item row="3" column="1">
<widget class="QLabel" name="label_306">
<property name="text">
<string>Filtering value for the disparity map (and by extension the depth map). A lower value means more confidence and precision (but less density), an upper value reduces the filtering (more density, less certainty).</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="0">
<widget class="QSpinBox" name="spinBox_stereoZed_confidenceThr">
<property name="maximum">
<number>100</number>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="page_60">
<layout class="QVBoxLayout" name="verticalLayout_103">
<item>
<spacer name="verticalSpacer_53">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>217</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
@@ -3069,7 +3275,7 @@ when using the file type, logs are saved in LogRtabmap.txt (located in the worki
<item>
<widget class="QStackedWidget" name="stackedWidget_image">
<property name="currentIndex">
<number>1</number>
<number>0</number>
</property>
<widget class="QWidget" name="page_7">
<layout class="QVBoxLayout" name="verticalLayout_30">
@@ -3430,7 +3636,7 @@ when using the file type, logs are saved in LogRtabmap.txt (located in the worki
<item row="1" column="2">
<widget class="QLabel" name="label_255">
<property name="text">
<string>Use file names as timestamps. Format is epoch time. Example: &quot;1305031102.175304.png&quot;</string>
<string>Use file names as timestamps. Format is epoch time. Example: &quot;1305031102.175304.png&quot;.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
@@ -6683,7 +6889,20 @@ If set to false, classic RTAB-Map loop closure detection is done using only imag
</item>
<item>
<layout class="QGridLayout" name="gridLayout_50" columnstretch="0,1">
<item row="3" column="0">
<item row="3" column="1">
<widget class="QLabel" name="label_scanMatching_4">
<property name="text">
<string>When comparing to a local path, merge the laser scans using the odometry poses instead of the ones in the optimized local graph.</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="localDetection_pathFilteringRadius">
<property name="suffix">
<string> m</string>
@@ -6699,7 +6918,7 @@ If set to false, classic RTAB-Map loop closure detection is done using only imag
</property>
</widget>
</item>
<item row="3" column="1">
<item row="2" column="1">
<widget class="QLabel" name="label_space3_3">
<property name="text">
<string>Path filtering radius to avoid merging laser scans which are close. 0 to ignore.</string>
@@ -6712,20 +6931,7 @@ If set to false, classic RTAB-Map loop closure detection is done using only imag
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QLabel" name="label_scanMatching_4">
<property name="text">
<string>When comparing to a local path, merge the laser scans using the odometry poses instead of the ones in the optimized local graph.</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">
<item row="3" column="0">
<widget class="QCheckBox" name="checkBox_localSpacePathOdomPosesUsed">
<property name="text">
<string/>
@@ -6755,7 +6961,7 @@ If set to false, classic RTAB-Map loop closure detection is done using only imag
</property>
</widget>
</item>
<item row="6" column="1">
<item row="5" column="1">
<widget class="QLabel" name="label_scanMatching_6">
<property name="text">
<string>Save scan matching IDs in link's user data.</string>
@@ -6768,33 +6974,13 @@ If set to false, classic RTAB-Map loop closure detection is done using only imag
</property>
</widget>
</item>
<item row="6" column="0">
<item row="5" column="0">
<widget class="QCheckBox" name="checkBox_localSpaceScanMatchingIDsSaved">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLabel" name="label_scanMatching_7">
<property name="text">
<string>Merge close laser scans on each path. If false, only the nearest laser scan on the path is used for ICP.</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="QCheckBox" name="checkBox_localSpaceAssembleScans">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="label_scanMatching_8">
<property name="text">

View File

@@ -1,7 +1,7 @@
<?xml version="1.0"?>
<package>
<name>rtabmap</name>
<version>0.11.5</version>
<version>0.11.7</version>
<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>
<author>Mathieu Labbe</author>

View File

@@ -53,6 +53,7 @@ void showUsage()
" 5=Freenect2 (Kinect v2)\n"
" 6=DC1394 (Bumblebee2)\n"
" 7=FlyCapture2 (Bumblebee2)\n"
" 8=ZED stereo\n"
" Options:\n"
" -rate #.# Input rate Hz (default 0=inf)\n"
" -save_stereo \"path\" Save stereo images in a folder or a video file (side by side *.avi).\n"
@@ -149,9 +150,9 @@ int main(int argc, char * argv[])
// last
driver = atoi(argv[i]);
if(driver < 0 || driver > 7)
if(driver < 0 || driver > 8)
{
UERROR("driver should be between 0 and 6.");
UERROR("driver should be between 0 and 8.");
showUsage();
}
}
@@ -235,6 +236,15 @@ int main(int argc, char * argv[])
}
camera = new rtabmap::CameraStereoFlyCapture2();
}
else if(driver == 8)
{
if(!rtabmap::CameraStereoZed::available())
{
UERROR("Not built with ZED sdk support...");
exit(-1);
}
camera = new rtabmap::CameraStereoZed(0);
}
else
{
UFATAL("");