Compare commits

..
183 Commits
Author SHA1 Message Date
matlabbe 1a1cf5f672 Freenect2: Fixed initRectifyMap error with custom calibration 2016-07-21 12:40:25 -04:00
matlabbe 759c917498 Octomap: changed warning log "Did not find...in cahe" to a debug log 2016-07-21 10:14:22 -04:00
matlabbe d7b1d617ea GUI: Fixed loaded parameters not actually modified from opened database 2016-07-20 17:07:35 -04:00
matlabbe 1e47271c91 DBReader: Fixed wrong virtual inherited function name odometryProvided() -> odomProvided() 2016-07-20 16:37:32 -04:00
matlabbe 1dca6116be Fixed default parameters on init for octomap 2016-07-20 15:17:59 -04:00
matlabbe ff59274c95 updated LICENSE year 2016-07-17 22:01:57 -04:00
matlabbe ca6cd19fb1 Updated Copyright year and About dialog summary 2016-07-17 21:57:10 -04:00
matlabbe be61eefdf9 Fixed build errors without octomap 2016-07-17 21:36:54 -04:00
matlabbe cf2bb6b599 CMake: Added PCL_OMP option (default ON) to use OMP implementations of some PCL classes (#50) 2016-07-17 21:04:11 -04:00
matlabbe d739d04232 Disable multi-arch lib by default (#97) 2016-07-17 20:12:13 -04:00
matlabbe 711ff2692c Updated default x-axis units of the figures with time stamps instead of IDs (#48). 2016-07-17 19:58:32 -04:00
matlabbe 705f4337e4 Fixed #42 2016-07-17 17:44:12 -04:00
matlabbe 237ab2be45 Projection map frame is still doing roll/pitch transformation (without z) 2016-07-17 17:06:36 -04:00
matlabbe 536136af77 Fixed octomap height when in /map frame. Preferences: added Cloud Filtering and Occupancy Grid Map subpanels to 3D Rendering 2016-07-17 16:47:06 -04:00
matlabbe d4e5cfb548 fixed octomap ground cells removed when updating graph 2016-07-17 15:37:08 -04:00
matlabbe b5e5e9508c fixed crash when activating octomap while mapping 2016-07-17 14:58:28 -04:00
matlabbe f161609a24 Added octomap ground is an obstacle option 2016-07-16 10:57:59 -04:00
matlabbe b4b7b6f455 Added Octomap visualization and export options 2016-07-15 17:46:13 -04:00
Mathieu Labbe c24079884d Reset stuck when moving toward the goal 2016-07-11 17:40:34 -04:00
matlabbe 38c3e3600d Planning stuck detection updated: now using distance to goal 2016-07-11 17:16:11 -04:00
matlabbe 09795678ef Merge branch 'master' of github.com:introlab/rtabmap into devel 2016-07-08 19:45:00 -04:00
matlabbe b3207d6402 PLanning: Detect if the pose is reachable from the current node before looking for the nearest one 2016-07-08 19:44:44 -04:00
matlabbe c6439cb1b7 Merge branch 'master' of github.com:introlab/rtabmap into devel 2016-07-08 19:23:05 -04:00
matlabbe 61f6e5ff79 Using fly distance instead of path distance to update the farthest goals 2016-07-08 19:22:48 -04:00
matlabbe 4cd8705710 Fixed cloudFromDepth() method when depth image is not the same size as the calibration file. That fixes projection map created from Tango databases (where depth size != rgb size) 2016-07-08 12:47:23 -04:00
matlabbe c8cd2545d3 fixed build without octomap 2016-07-08 00:21:36 -04:00
matlabbe 6f310ff63a util2d::getDepth(): fixed small error on depth assignation (mm) 2016-07-05 18:21:39 -04:00
matlabbe 20862f07bc RegistrationInfo: added IcpTranslation and IcpRotation members 2016-07-05 11:23:59 -04:00
matlabbe 1365eaca3a Merged master to devel 2016-07-04 15:38:28 -04:00
matlabbe 9dfc7801a0 Fixed fatal error in #91 2016-07-04 13:39:33 -04:00
matlabbe 02d4ca5c8b util3d::segmentObstaclesFromGround: added viewPoint argument (default 0,0,100) 2016-07-04 11:47:10 -04:00
matlabbe c2a7b2f13a Odometry: Added process() with optional guess interface 2016-06-30 11:34:46 -04:00
matlabbe 4115bc416e Added OctoMap class 2016-06-28 19:00:44 -04:00
matlabbe 060a3fd47e Merge branch 'master' of github.com:introlab/rtabmap into devel 2016-06-27 16:11:08 -04:00
matlabbe 84726fa45c Update Odometry.cpp 2016-06-27 16:10:18 -04:00
matlabbe 3609c961ea Merge branch 'master' of github.com:introlab/rtabmap into devel 2016-06-27 16:08:53 -04:00
matlabbe 756e176878 Update Odometry.cpp
Odometry: Added additional debug information on dt>0 assert
2016-06-27 16:08:25 -04:00
matlabbe 1398b71b60 Merge branch 'master' of github.com:introlab/rtabmap into devel 2016-06-27 12:17:55 -04:00
matlabbe f69ca56179 Features2D: Using 255 mask values for ORB (#89). Fixed ignored mask by FAST when called from ORB. 2016-06-27 11:54:21 -04:00
matlabbe a310b5e864 DB: Added error when loading a database with version more recent than installed rtabmap version 2016-06-25 13:28:26 -04:00
matlabbe 517bfa5272 OdometryF2M: updated how local scan map is updated 2016-06-25 13:18:09 -04:00
matlabbe ca95c9de97 Changed an OpenCV_LIBS to OpenCV_LIBRARIES 2016-06-24 21:00:12 -04:00
matlabbe 37c269bc0b fixed a warning 2016-06-24 19:23:11 -04:00
matlabbe e90c97f8a4 ZED driver: added option to use visual odometry approach from zed sdk. RtabmapThread: fixed thread state change on new map trigger on Odometry init (variance=9999). Odometry: on init, verify that the first frame is ok before sending first pose. Parameters: Mem/SaveDepth16Format is now false by default 2016-06-24 18:49:34 -04:00
matlabbe af6e17fce8 GUI: Added color code for odometry features 2016-06-24 16:02:27 -04:00
matlabbe b86352bfc0 merged master to devel 2016-06-23 15:44:24 -04:00
matlabbe f03a1b50ef Fixed build with ZED SDK 1.0.0... cmake find_package ZED version 1 (#85) 2016-06-23 15:41:32 -04:00
matlabbe 70da8d26c0 Fixed build with ZED SDK 1.0.0 (#85) 2016-06-23 15:40:11 -04:00
matlabbe 333c7433e8 Merge branch 'master' of https://github.com/introlab/rtabmap into devel 2016-06-23 11:27:58 -04:00
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 42c3186a53 Memory::computeTransform(): fixed null guess sent to pure ICP registration 2016-06-21 16:42:21 -04:00
matlabbe 530919c531 CameraThread: fixed scan from depth max points with multi-camera 2016-06-21 11:36:50 -04:00
matlabbe 0ec39e3c77 DBReader now inherits from Camera (so that CameraThread's post processing stuff can be used with a database stream) 2016-06-21 11:22:24 -04:00
matlabbe cdddb1209e DBReader: added camera selection 2016-06-20 10:50:01 -04:00
matlabbe 62db5370aa CloudViewer: Added updateCameraFrustum() method (multi-cameras supported) 2016-06-19 18:33:36 -04:00
matlabbe ab991c2a7d CameraModel::scaled() scale Tx an Ty too 2016-06-17 16:47:02 -04:00
matlabbe d03b54d95a Parameters: removed trailing 0 for double/float parameters, to avoid serializing with them (so that we don't have the 0.0 != 0 when loading parameters from database) 2016-06-16 15:34:27 -04:00
matlabbe 62a982ef9f DbDriverSqlite3: Fixed multi-camera calibration loading error with version >= 0.11.2 2016-06-16 14:57:55 -04:00
matlabbe 798c3cb373 Registration: added warning when GuessFlowSize is set and multi-camera is detected instead of crashing on an assert 2016-06-15 18:13:11 -04:00
matlabbe 7f55e2c9bb Merge branch 'master' of github.com:introlab/rtabmap into devel 2016-06-15 16:39:25 -04:00
matlabbe 8e76de7d34 Fixed GTSAM/Eigen include dir 2016-06-15 15:48:56 -04:00
matlabbe ac284ab067 GUI: fixed odometry visibility flickering 2016-06-15 14:18:26 -04:00
matlabbe 95f9304f4f CameraStereo: fixed rectify=false ignored 2016-06-15 11:36:37 -04:00
matlabbe 7b733686cb Updated CameraVideo and CameraStereoVideo constructor interface with USB 2016-06-15 11:30:05 -04:00
matlabbe bdafb9a3f1 Merge branch 'master' of github.com:introlab/rtabmap into devel 2016-06-14 11:56:22 -04:00
matlabbe abd376a44c segmentObstaclesFromGround() fixed identical ground and obstacles indices 2016-06-14 11:55:58 -04:00
matlabbe 38a7993a9b Database: added "parameters" field in Statistics table. GUI: detecting if parameters in database are different from the Preferences, if so ask user to update them. 2016-06-13 17:34:17 -04:00
matlabbe 3edb133727 Increased default Stereo/MaxDisparity to 128 2016-06-13 14:37:19 -04:00
matlabbe 84dd258777 Added "Odom/AligWithGround" parameter. Added util3d::extractPlane(). 2016-06-12 21:45:22 -04:00
matlabbe 543b8df045 MainWindow: Added statistics about how much size the created clouds take in RAM. Avoid caching data on small movements. Export: Fixed meshing checkbox and pipeline combo box not saved/loaded. PreferencesDialog: Added option to disable caching the point clouds. computeNormals(): added viewpoint parameter. mls(): making sure that all returned normals are normalized. 2016-06-12 17:53:35 -04:00
matlabbe cb7c76889d API achange (0.11.8): computeNormals returns only pcl::Normal cloud, not pcl::PointNormal or pcl::PointXYZRGBNormal types. MainWindow: Normals are not kept in cache to save RAM. ProgressDialog: check if auto-close is still checked when close() slot is called. 2016-06-12 13:51:49 -04:00
matlabbe 9f296c67b2 GUI: Added more parameters for 3D projection grid map 2016-06-10 20:12:13 -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 https://github.com/introlab/rtabmap/commit/ad0afc58c0d404b420108e527e454201d89a840e#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 1fbcc2319a 0.11.5: added RTABMAP_QT_VERSION to RTABMapConfig.cmake (used by rtabmap_ros to know to which Qt version it should link) 2016-05-09 11:17:51 -04:00
matlabbe c7670c505d ROS: Added qt_gui_core dependency to get libqt4-dev or libqt5-dev installed 2016-05-08 11:56:25 -04:00
matlabbe 80c84a66fe package.xml: added dependency to libvtk-qt (fixing Kinetic on Wily build) 2016-05-06 15:33:10 -04:00
matlabbe 5e4111d67e ROS: removed libopenni2-dev dependency as it is not yet available on Jessie 2016-05-06 13:07:38 -04:00
matlabbe c8ed731809 Fixed package dependencies for Kinetic 2016-05-06 12:55:19 -04:00
matlabbe 22577bdf71 ROS: updated package version to 0.11.4 2016-05-06 12:36:11 -04:00
matlabbe 622dfb370d Merge branch 'master' of https://github.com/introlab/rtabmap 2016-05-05 18:25:46 -04:00
matlabbe ad0afc58c0 Fixed crash on startup with vtk6+qt5. All cloud viewers in QDockWidget are now created manually instead of being defined in the *.ui files. The generated ui didn't pass the top level parent window to constructor of CloudViewer, which caused a problem when initializing the QVTKWidget. 2016-05-05 18:25:26 -04:00
matlabbe 7c8583f025 fixed crash from #79 2016-05-05 11:53:09 -04:00
matlabbe 74d0bfa1bb Qt5: fixed "read parameters..." progress dialog showing up on start 2016-05-04 19:03:22 -04:00
matlabbe e1866d38af Fixed cmake erros on system with Qt4 2016-05-04 16:51:41 -04:00
matlabbe b8c2cd9f94 Auto detect which Qt version to use (Qt5 has priority if both are installed). ROS Kinetic fix for vtk libproj.so not found bug. 2016-05-04 16:45:19 -04:00
matlabbe d2882a88f3 fixed isnan() not defined 2016-05-03 20:44:06 -04:00
matlabbe 7230474f98 MainWindow: update pose in 3D Map view even if odometry has no images 2016-04-29 14:29:55 -04:00
matlabbe b2c36742ee travis: disabled email notifications 2016-04-28 10:11:44 -04:00
matlabbe 427f44dca3 Update README.md 2016-04-28 10:01:58 -04:00
matlabbe fc7659888c travis: auto answer yes on apt-get 2016-04-28 09:49:33 -04:00
matlabbe f81734a8e5 travis: added ros keys 2016-04-28 09:44:09 -04:00
matlabbe d92c3d224c travis updated 2016-04-28 09:36:44 -04:00
matlabbe 70fd054f67 travis pcl 2016-04-28 09:31:19 -04:00
matlabbe 5a3c7c7a24 updated .travis.yml 2016-04-28 09:27:28 -04:00
matlabbe 1091960282 Added .travis.yml 2016-04-28 09:15:36 -04:00
matlabbe a78587e505 Hidden FPS shown in CloudViewer 2016-04-26 14:24:09 -04:00
matlabbe f408ef8922 Calibration: added max scale parameter 2016-04-25 17:02:25 -04:00
matlabbe 8e1fc0df56 Calibration: added support for stereo IR cameras 2016-04-25 09:52:03 -04:00
Mathieu Labbe 4cc1c66f09 Segment ground/obstacles: added max ground height parameter 2016-04-15 17:41:40 -04:00
Mathieu Labbe 8bb5f0d905 Fixed Vis/MinDepth not working (with depth image in mm) 2016-04-14 11:24:36 -04:00
Mathieu Labbe d5b385ec69 PreferencesDialog: Removed NN warning when RTABMAP_NONFREE=0 2016-04-14 11:01:24 -04:00
matlabbe 7c0db617cf GraphViewer: added hide/show graphs and paths options 2016-04-13 12:57:28 -04:00
matlabbe 809f5dd4df MainWindow: working directory of GUI widgets can be updated when running 2016-04-13 11:58:54 -04:00
matlabbe 9339b86633 API change: segmentObstaclesFromGround() and normalFiltering() 2016-04-12 18:57:04 -04:00
matlabbe fc76e5b8f3 3D projection: adding pose rotation (roll, pitch) before projection 2016-04-12 17:45:50 -04:00
matlabbe f511896c43 MainWindow: Fixed "Invalid (NaN, Inf) point coordinates given to radiusSearch" error when creating occupancy map from projection 2016-04-12 17:16:13 -04:00
matlabbe b53b861342 GUI: Fixed viewpoint including local transform when generating organized mesh 2016-04-12 16:47:55 -04:00
matlabbe 684e9fb8b9 0.11.4: API change: added minDepth parameter to cloudFromXXXXX() methods and removed voxel parameter 2016-04-12 15:14:04 -04:00
matlabbe f185a4d739 Updated default RGBD/OptimizeMaxError to 0.05 m for Tango app 2016-04-11 10:43:28 -04:00
matlabbe 29dd529762 Main app: Open database as argument, file association *.db on Mac OS X, automatically ask to download clouds when opening a database 2016-04-10 14:52:14 -04:00
matlabbe 72fc714cb4 Tango: fixed export with optimization, added "Nodes Filtering" option 2016-04-09 18:57:49 -04:00
matlabbe 656431a03f Tango: Fixed Mem/ImagePreDecimation when changing to/from 720p mode 2016-04-09 12:08:30 -04:00
matlabbe cc9c9d552c Tango: Fixed auto-exposure config error (now ignoring it), updated log info 2016-04-08 18:58:18 -04:00
matlabbe ab35106359 Fixed build errors with log2 not defined on some os 2016-04-08 17:20:13 -04:00
matlabbe dece54ca3e Added parameters: Mem/ImagePreDecimation Mem/ImagePostDecimation Odom/ImageDecimation 2016-04-08 16:15:08 -04:00
matlabbe 0b3da6b246 DbViewer: labels are now selectable 2016-04-07 12:26:24 -04:00
matlabbe d5553db9eb DbViewer: Added calibration info 2016-04-07 12:15:58 -04:00
matlabbe 748360aac7 Vocabulary: Binary descriptors are saved as is even if there is a float conversion for flann 2016-04-07 11:48:07 -04:00
matlabbe 0bb82af91c Tango: moved Auto-exposure option in Rendering menu, updated pop-up time "Loop closure detected" 2016-04-06 18:07:45 -04:00
matlabbe 9270fc9ca9 Fixed OptimizerG2O::pixelVariance_ not initialized 2016-04-06 17:02:31 -04:00
matlabbe d2ebdea96d Added parameter "g2o/PixelVariance" (default 1) 2016-04-06 15:24:36 -04:00
matlabbe 000a2727ef Added .gitignore 2016-04-05 17:10:08 -04:00
matlabbe e3a44bbb08 Tango: increased package version to 2 2016-04-04 13:24:25 -04:00
matlabbe af405e69b1 Tango #57: Increased version to 0.11.3, updated Post-Processing actions, added mesh rendering actions, fixed point cloud rendering 2016-04-04 13:03:43 -04:00
matlabbe ff32f54aa8 Rtabmap::detectMoreLoopClosures(): use Memory::computeTransform() with signature parameters 2016-04-03 21:49:12 -04:00
matlabbe 5d9522c901 Tango #57: Global optimization / Post-processing on pause 2016-04-03 21:35:30 -04:00
matlabbe 30e52b785a Tango #57: Added 720p option, Export PLY or OBJ, Added Rendering and Mapping menus, RtabmapThread: Fixed large covariance (9999) detection 2016-04-02 15:17:40 -04:00
matlabbe d489cd48e9 Frustum hiding on action click 2016-03-31 12:44:03 -04:00
matlabbe 30777b630a Fixed issue #10 (missing one iteration on rtabmap-console) 2016-03-29 13:07:32 -04:00
matlabbe 8030d89634 Implemented OptimizerG2O::optimimzeBA(). Updated PostProcessingDialog (g2o sba option). Fixed words descriptors not filled in rtabmap::getMap3D(). CameraModelD(): return 5 null coeff distorsions if not set 2016-03-28 18:19:17 -04:00
matlabbe 18759e7197 CMake: Added info about CMAKE_INSTALL_LIBDIR 2016-03-23 19:56:45 -04:00
matlabbe d74cb1b232 Updated pull request (supporting internal/external build) 2016-03-23 19:07:44 -04:00
matlabbe cee3a77a4c Merge pull request #61 from Wade5566/patch-1
Update CMakeLists.txt
2016-03-23 19:06:40 -04:00
matlabbe 1120a74b13 Updated RGB-D mapping C++ example 2016-03-23 14:18:22 -04:00
Wade5566 6a787670a1 Update CMakeLists.txt
Fix the CMakeLists.txt which cannot be used
2016-03-23 17:48:16 +08:00
matlabbe a01fb82f51 ExportCloudsDialog: Updated TextureMesh export. MainWindow: fixed exporting only visible clouds. 2016-03-22 20:44:18 -04:00
matlabbe c43fd6a2a7 Optimizer::create() updated interface 2016-03-22 11:06:45 -04:00
matlabbe 9385aa2332 Tango: Added OBJ export (with texture) 2016-03-21 20:03:03 -04:00
matlabbe bc78f789eb Tango: Added texture to meshes #57 2016-03-21 15:45:26 -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
243 changed files with 13103 additions and 5757 deletions
+7
View File
@@ -0,0 +1,7 @@
/lib
.DS_Store
.settings/language.settings.xml
app/android/.classpath
app/android/.project
app/android/AndroidManifest.xml
app/android/res/raw/
+29
View File
@@ -0,0 +1,29 @@
sudo: true
dist: trusty
language: cpp
compiler:
- gcc
- clang
addons:
apt:
packages:
- cmake
- libopencv-dev
- libqt4-dev
- libsqlite3-dev
install:
- sudo sh -c 'echo "deb http://packages.ros.org/ros/ubuntu trusty main" > /etc/apt/sources.list.d/ros-latest.list'
- wget http://packages.ros.org/ros.key -O - | sudo apt-key add -
- sudo apt-get update
- sudo apt-get -y install libpcl-1.7-all libfreenect-dev
script:
- mkdir -p build && cd build
- cmake ..
- make
notifications:
email: false
+151 -39
View File
@@ -6,9 +6,10 @@ SET(PROJECT_PREFIX rtabmap)
# Catkin doesn't support multiarch library path, # Catkin doesn't support multiarch library path,
# fix to "lib" if not set by user. # fix to "lib" if not set by user.
IF(NOT DEFINED CMAKE_INSTALL_LIBDIR) OPTION(MULTI_ARCH "Activate multi-arch lib directory (debian)" OFF)
IF(NOT MULTI_ARCH AND NOT DEFINED CMAKE_INSTALL_LIBDIR)
set(CMAKE_INSTALL_LIBDIR "lib") set(CMAKE_INSTALL_LIBDIR "lib")
ENDIF(NOT DEFINED CMAKE_INSTALL_LIBDIR) ENDIF(NOT MULTI_ARCH AND NOT DEFINED CMAKE_INSTALL_LIBDIR)
INCLUDE(GNUInstallDirs) INCLUDE(GNUInstallDirs)
@@ -20,7 +21,7 @@ SET(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake_modules")
####################### #######################
SET(RTABMAP_MAJOR_VERSION 0) SET(RTABMAP_MAJOR_VERSION 0)
SET(RTABMAP_MINOR_VERSION 11) SET(RTABMAP_MINOR_VERSION 11)
SET(RTABMAP_PATCH_VERSION 2) SET(RTABMAP_PATCH_VERSION 8)
SET(RTABMAP_VERSION SET(RTABMAP_VERSION
${RTABMAP_MAJOR_VERSION}.${RTABMAP_MINOR_VERSION}.${RTABMAP_PATCH_VERSION}) ${RTABMAP_MAJOR_VERSION}.${RTABMAP_MINOR_VERSION}.${RTABMAP_PATCH_VERSION})
@@ -32,8 +33,6 @@ SET(PROJECT_VERSION_PATCH ${RTABMAP_PATCH_VERSION})
SET(PROJECT_SOVERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}") SET(PROJECT_SOVERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}")
SET(RTABMAP_QT_VERSION 4 CACHE STRING "Which QT version to use")
####### COMPILATION PARAMS ####### ####### COMPILATION PARAMS #######
# In case of Makefiles if the user does not setup CMAKE_BUILD_TYPE, assume it's Release: # In case of Makefiles if the user does not setup CMAKE_BUILD_TYPE, assume it's Release:
IF(${CMAKE_GENERATOR} MATCHES ".*Makefiles") IF(${CMAKE_GENERATOR} MATCHES ".*Makefiles")
@@ -138,11 +137,19 @@ option(WITH_TORO "Include TORO support" ON)
option(WITH_VERTIGO "Include Vertigo support" ON) option(WITH_VERTIGO "Include Vertigo support" ON)
option(WITH_CVSBA "Include cvsba support" ON) option(WITH_CVSBA "Include cvsba support" ON)
option(WITH_FLYCAPTURE2 "Include FlyCapture2/Triclops support" ON) option(WITH_FLYCAPTURE2 "Include FlyCapture2/Triclops support" ON)
option(WITH_ZED "Include ZED sdk support" ON)
option(WITH_OCTOMAP "Include Octomap support" ON)
option(PCL_OMP "With PCL OMP implementations" ON)
FIND_PACKAGE(OpenCV REQUIRED QUIET) FIND_PACKAGE(OpenCV REQUIRED QUIET)
FIND_PACKAGE(PCL 1.7 REQUIRED QUIET) FIND_PACKAGE(PCL 1.7 REQUIRED QUIET)
FIND_PACKAGE(ZLIB REQUIRED QUIET) FIND_PACKAGE(ZLIB REQUIRED QUIET)
# fix libproj.so not found on Xenial
if(NOT "${PCL_LIBRARIES}" STREQUAL "")
list(REMOVE_ITEM PCL_LIBRARIES "vtkproj4")
endif()
# OpenMP ("-fopenmp" should be added for flann included in PCL) # OpenMP ("-fopenmp" should be added for flann included in PCL)
# the gcc-4.2.1 coming with MacOS X is not compatible with the OpenMP pragmas we use, so disabling OpenMP for it # the gcc-4.2.1 coming with MacOS X is not compatible with the OpenMP pragmas we use, so disabling OpenMP for it
if((NOT APPLE) OR (NOT CMAKE_COMPILER_IS_GNUCXX) OR (GCC_VERSION VERSION_GREATER 4.2.1) OR (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")) if((NOT APPLE) OR (NOT CMAKE_COMPILER_IS_GNUCXX) OR (GCC_VERSION VERSION_GREATER 4.2.1) OR (CMAKE_CXX_COMPILER_ID STREQUAL "Clang"))
@@ -152,6 +159,9 @@ if(OPENMP_FOUND)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
message (STATUS "Found OpenMP") message (STATUS "Found OpenMP")
if(PCL_OMP)
add_definitions(-DPCL_OMP)
endif(PCL_OMP)
else(OPENMP_FOUND) else(OPENMP_FOUND)
message (STATUS "Not found OpenMP") message (STATUS "Not found OpenMP")
endif() endif()
@@ -167,14 +177,22 @@ IF(ZLIB_FOUND)
ENDIF(ZLIB_FOUND) ENDIF(ZLIB_FOUND)
IF(WITH_QT) IF(WITH_QT)
# If Qt is here, the GUI will be built FIND_PACKAGE(VTK)
IF("${RTABMAP_QT_VERSION}" STREQUAL "4") IF(NOT VTK_FOUND)
MESSAGE(FATAL_ERROR "VTK is required when using Qt. Set -DWITH_QT=OFF if you don't want gui tools.")
ENDIF(NOT VTK_FOUND)
# If Qt is here, the GUI will be built
# look for Qt5 (if vtk>5 is installed) before Qt4
IF("${VTK_MAJOR_VERSION}" GREATER 5)
FIND_PACKAGE(Qt5 COMPONENTS Widgets Core Gui Svg QUIET)
ENDIF("${VTK_MAJOR_VERSION}" GREATER 5)
IF(NOT Qt5_FOUND)
FIND_PACKAGE(Qt4 COMPONENTS QtCore QtGui QtSvg) FIND_PACKAGE(Qt4 COMPONENTS QtCore QtGui QtSvg)
ELSE() ENDIF(NOT Qt5_FOUND)
FIND_PACKAGE(Qt5 COMPONENTS Widgets Core Gui Svg)
ENDIF()
IF(QT4_FOUND OR Qt5_FOUND) IF(QT4_FOUND OR Qt5_FOUND)
FIND_PACKAGE(VTK REQUIRED)
IF("${VTK_MAJOR_VERSION}" EQUAL 5) IF("${VTK_MAJOR_VERSION}" EQUAL 5)
FIND_PACKAGE(QVTK REQUIRED) # only for VTK 5 FIND_PACKAGE(QVTK REQUIRED) # only for VTK 5
ENDIF("${VTK_MAJOR_VERSION}" EQUAL 5) ENDIF("${VTK_MAJOR_VERSION}" EQUAL 5)
@@ -198,12 +216,13 @@ IF(WITH_FREENECT2)
ENDIF(freenect2_FOUND) ENDIF(freenect2_FOUND)
ENDIF(WITH_FREENECT2) ENDIF(WITH_FREENECT2)
IF(WITH_OPENNI2) # IF PCL depends on OpenNI2 (already found), ignore WITH_OPENNI2
IF(WITH_OPENNI2 OR OpenNI2_FOUND)
FIND_PACKAGE(OpenNI2 QUIET) FIND_PACKAGE(OpenNI2 QUIET)
IF(OpenNI2_FOUND) IF(OpenNI2_FOUND)
MESSAGE(STATUS "Found OpenNI2: ${OpenNI2_INCLUDE_DIRS}") MESSAGE(STATUS "Found OpenNI2: ${OpenNI2_INCLUDE_DIRS}")
ENDIF(OpenNI2_FOUND) ENDIF(OpenNI2_FOUND)
ENDIF(WITH_OPENNI2) ENDIF(WITH_OPENNI2 OR OpenNI2_FOUND)
IF(WITH_DC1394) IF(WITH_DC1394)
FIND_PACKAGE(DC1394 QUIET) FIND_PACKAGE(DC1394 QUIET)
@@ -223,22 +242,6 @@ IF(WITH_GTSAM)
FIND_PACKAGE(GTSAM QUIET) FIND_PACKAGE(GTSAM QUIET)
ENDIF(WITH_GTSAM) ENDIF(WITH_GTSAM)
IF(G2O_FOUND OR GTSAM_FOUND)
#Newest versions require std11
IF(NOT MSVC)
include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X)
IF(COMPILER_SUPPORTS_CXX11)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
ELSEIF(COMPILER_SUPPORTS_CXX0X)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
ELSE()
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) IF(WITH_FLYCAPTURE2)
FIND_PACKAGE(FlyCapture2 QUIET) FIND_PACKAGE(FlyCapture2 QUIET)
IF(FlyCapture2_FOUND) IF(FlyCapture2_FOUND)
@@ -253,6 +256,58 @@ IF(WITH_CVSBA)
ENDIF(cvsba_FOUND) ENDIF(cvsba_FOUND)
ENDIF(WITH_CVSBA) 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 1 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(WITH_OCTOMAP)
FIND_PACKAGE(OCTOMAP QUIET)
IF(OCTOMAP_FOUND)
MESSAGE(STATUS "Found octomap: ${OCTOMAP_INCLUDE_DIRS}")
ENDIF(OCTOMAP_FOUND)
ENDIF(WITH_OCTOMAP)
IF(G2O_FOUND OR GTSAM_FOUND OR ZED_FOUND)
#Newest versions require std11
IF(NOT MSVC)
include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X)
IF(COMPILER_SUPPORTS_CXX11)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
ELSEIF(COMPILER_SUPPORTS_CXX0X)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
ELSE()
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 OR ZED_FOUND)
####### OSX BUNDLE CMAKE_INSTALL_PREFIX ####### ####### OSX BUNDLE CMAKE_INSTALL_PREFIX #######
IF(APPLE AND BUILD_AS_BUNDLE) IF(APPLE AND BUILD_AS_BUNDLE)
IF(Qt5_FOUND OR (QT4_FOUND AND QT_QTCORE_FOUND AND QT_QTGUI_FOUND)) IF(Qt5_FOUND OR (QT4_FOUND AND QT_QTCORE_FOUND AND QT_QTGUI_FOUND))
@@ -282,15 +337,24 @@ ENDIF(APPLE AND BUILD_AS_BUNDLE)
####### SOURCES (Projects) ####### ####### 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)) IF(NOT (OPENCV_NONFREE_FOUND OR OPENCV_XFEATURES2D_FOUND))
SET(NONFREE "//") SET(NONFREE "//")
ENDIF(NOT (OPENCV_NONFREE_FOUND OR OPENCV_XFEATURES2D_FOUND)) ENDIF(NOT (OPENCV_NONFREE_FOUND OR OPENCV_XFEATURES2D_FOUND))
IF(NOT G2O_FOUND) IF(NOT G2O_FOUND)
SET(G2O "//") SET(G2O "//")
ENDIF(NOT G2O_FOUND) ELSE()
SET(CONF_DEPENDENCIES ${CONF_DEPENDENCIES} ${G2O_LIBRARIES})
ENDIF()
IF(NOT GTSAM_FOUND) IF(NOT GTSAM_FOUND)
SET(GTSAM "//") SET(GTSAM "//")
ENDIF(NOT GTSAM_FOUND) ELSE()
SET(CONF_DEPENDENCIES ${CONF_DEPENDENCIES} ${GTSAM_LIBRARIES})
ENDIF()
IF(NOT WITH_TORO) IF(NOT WITH_TORO)
SET(TORO "//") SET(TORO "//")
ENDIF(NOT WITH_TORO) ENDIF(NOT WITH_TORO)
@@ -299,22 +363,44 @@ IF(NOT WITH_VERTIGO)
ENDIF(NOT WITH_VERTIGO) ENDIF(NOT WITH_VERTIGO)
IF(NOT cvsba_FOUND) IF(NOT cvsba_FOUND)
SET(CVSBA "//") SET(CVSBA "//")
ENDIF(NOT cvsba_FOUND) ELSE()
SET(CONF_DEPENDENCIES ${CONF_DEPENDENCIES} ${cvsba_LIBRARIES})
ENDIF()
IF(NOT Freenect_FOUND) IF(NOT Freenect_FOUND)
SET(FREENECT "//") SET(FREENECT "//")
ENDIF(NOT Freenect_FOUND) ELSE()
SET(CONF_DEPENDENCIES ${CONF_DEPENDENCIES} ${Freenect_LIBRARIES})
ENDIF()
IF(NOT freenect2_FOUND) IF(NOT freenect2_FOUND)
SET(FREENECT2 "//") SET(FREENECT2 "//")
ENDIF(NOT freenect2_FOUND) ELSE()
SET(CONF_DEPENDENCIES ${CONF_DEPENDENCIES} ${freenect2_LIBRARIES})
ENDIF()
IF(NOT OpenNI2_FOUND) IF(NOT OpenNI2_FOUND)
SET(OPENNI2 "//") SET(OPENNI2 "//")
ENDIF(NOT OpenNI2_FOUND) ELSE()
SET(CONF_DEPENDENCIES ${CONF_DEPENDENCIES} ${OpenNI2_LIBRARIES})
ENDIF()
IF(NOT DC1394_FOUND) IF(NOT DC1394_FOUND)
SET(DC1394 "//") SET(DC1394 "//")
ENDIF(NOT DC1394_FOUND) ELSE()
SET(CONF_DEPENDENCIES ${CONF_DEPENDENCIES} ${DC1394_LIBRARIES})
ENDIF()
IF(NOT FlyCapture2_FOUND) IF(NOT FlyCapture2_FOUND)
SET(FLYCAPTURE2 "//") 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 OCTOMAP_FOUND)
SET(OCTOMAP "//")
ELSE()
SET(CONF_DEPENDENCIES ${CONF_DEPENDENCIES} ${OCTOMAP_LIBRARIES})
ENDIF()
IF(NOT (OpenCV_FOUND AND OpenCV_VERSION_MAJOR EQUAL 3)) IF(NOT (OpenCV_FOUND AND OpenCV_VERSION_MAJOR EQUAL 3))
SET(OPENCV3 "//") SET(OPENCV3 "//")
ENDIF(NOT (OpenCV_FOUND AND OpenCV_VERSION_MAJOR EQUAL 3)) ENDIF(NOT (OpenCV_FOUND AND OpenCV_VERSION_MAJOR EQUAL 3))
@@ -365,9 +451,14 @@ file(RELATIVE_PATH REL_LIB_DIR "${CMAKE_INSTALL_PREFIX}/${INSTALL_CMAKE_DIR}" "$
set(CONF_INCLUDE_DIRS "${PROJECT_SOURCE_DIR}/corelib/include" set(CONF_INCLUDE_DIRS "${PROJECT_SOURCE_DIR}/corelib/include"
"${PROJECT_SOURCE_DIR}/guilib/include" "${PROJECT_SOURCE_DIR}/guilib/include"
"${PROJECT_SOURCE_DIR}/utilite/include") "${PROJECT_SOURCE_DIR}/utilite/include")
set(CONF_LIB_DIR "${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}") set(CONF_LIB_DIR "${CMAKE_ARCHIVE_OUTPUT_DIRECTORY} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}")
IF(QT4_FOUND OR Qt5_FOUND) IF(QT4_FOUND OR Qt5_FOUND)
set(CONF_WITH_GUI ON) set(CONF_WITH_GUI ON)
IF(QT4_FOUND)
set(CONF_QT_VERSION 4)
ELSE()
set(CONF_QT_VERSION 5)
ENDIF()
ELSE() ELSE()
set(CONF_WITH_GUI OFF) set(CONF_WITH_GUI OFF)
ENDIF() ENDIF()
@@ -479,6 +570,7 @@ MESSAGE(STATUS "Info :")
MESSAGE(STATUS " Version : ${RTABMAP_VERSION}") MESSAGE(STATUS " Version : ${RTABMAP_VERSION}")
MESSAGE(STATUS " CMAKE_INSTALL_PREFIX = ${CMAKE_INSTALL_PREFIX}") MESSAGE(STATUS " CMAKE_INSTALL_PREFIX = ${CMAKE_INSTALL_PREFIX}")
MESSAGE(STATUS " CMAKE_BUILD_TYPE = ${CMAKE_BUILD_TYPE}") MESSAGE(STATUS " CMAKE_BUILD_TYPE = ${CMAKE_BUILD_TYPE}")
MESSAGE(STATUS " CMAKE_INSTALL_LIBDIR = ${CMAKE_INSTALL_LIBDIR}")
MESSAGE(STATUS " BUILD_APP = ${BUILD_APP}") MESSAGE(STATUS " BUILD_APP = ${BUILD_APP}")
MESSAGE(STATUS " BUILD_TOOLS = ${BUILD_TOOLS}") MESSAGE(STATUS " BUILD_TOOLS = ${BUILD_TOOLS}")
MESSAGE(STATUS " BUILD_EXAMPLES = ${BUILD_EXAMPLES}") MESSAGE(STATUS " BUILD_EXAMPLES = ${BUILD_EXAMPLES}")
@@ -583,6 +675,26 @@ ELSE()
MESSAGE(STATUS " With cvsba = NO (cvsba not found)") MESSAGE(STATUS " With cvsba = NO (cvsba not found)")
ENDIF() 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(OCTOMAP_FOUND)
MESSAGE(STATUS " With OCTOMAP = YES (License: BSD)")
ELSEIF(NOT WITH_OCTOMAP)
MESSAGE(STATUS " With OCTOMAP = NO (WITH_OCTOMAP=OFF)")
ELSE()
MESSAGE(STATUS " With OCTOMAP = NO (octomap not found)")
ENDIF()
IF(QT4_FOUND) IF(QT4_FOUND)
MESSAGE(STATUS " With Qt4 = YES (License: Open Source or Commercial)") MESSAGE(STATUS " With Qt4 = YES (License: Open Source or Commercial)")
ELSEIF(Qt5_FOUND) ELSEIF(Qt5_FOUND)
@@ -590,7 +702,7 @@ MESSAGE(STATUS " With Qt5 = YES (License: Open Source or Comme
ELSEIF(NOT WITH_QT) ELSEIF(NOT WITH_QT)
MESSAGE(STATUS " With Qt = NO (WITH_QT=OFF)") MESSAGE(STATUS " With Qt = NO (WITH_QT=OFF)")
ELSE() ELSE()
MESSAGE(STATUS " With Qt = NO (Qt not found, to use Qt5 you should set -DRTABMAP_QT_VERSION=5)") MESSAGE(STATUS " With Qt = NO (Qt not found)")
ENDIF() ENDIF()
MESSAGE(STATUS "--------------------------------------------") MESSAGE(STATUS "--------------------------------------------")
+1 -1
View File
@@ -1,4 +1,4 @@
Copyright (c) 2010-2015, Mathieu Labbe - IntRoLab - Universite de Sherbrooke Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
+1 -1
View File
@@ -1,4 +1,4 @@
rtabmap rtabmap [![Build Status](https://travis-ci.org/introlab/rtabmap.svg?branch=master)](https://travis-ci.org/introlab/rtabmap)
======= =======
RTAB-Map library and standalone application. RTAB-Map library and standalone application.
+16 -16
View File
@@ -11,41 +11,41 @@ get_filename_component(RTABMap_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
set(RTABMap_INCLUDE_DIRS "@CONF_INCLUDE_DIRS@") set(RTABMap_INCLUDE_DIRS "@CONF_INCLUDE_DIRS@")
#core lib #core lib
find_library(RTABMap_CORE_RELEASE NAMES rtabmap_core NO_DEFAULT_PATH HINTS "@CONF_LIB_DIR@") find_library(RTABMap_CORE_RELEASE NAMES rtabmap_core NO_DEFAULT_PATH HINTS @CONF_LIB_DIR@)
find_library(RTABMap_CORE_DEBUG NAMES rtabmap_cored NO_DEFAULT_PATH HINTS "@CONF_LIB_DIR@") find_library(RTABMap_CORE_DEBUG NAMES rtabmap_cored NO_DEFAULT_PATH HINTS @CONF_LIB_DIR@)
IF(RTABMap_CORE_DEBUG AND RTABMap_CORE_RELEASE) IF(RTABMap_CORE_DEBUG AND RTABMap_CORE_RELEASE)
SET(RTABMap_CORE SET(RTABMap_CORE
debug ${RTABMap_CORE_DEBUG} debug ${RTABMap_CORE_DEBUG}
optimized ${RTABMap_CORE_RELEASE} optimized ${RTABMap_CORE_RELEASE}
) )
ELSEIF(RTABMap_CORE_RELEASE)
SET(RTABMap_CORE ${RTABMap_CORE_RELEASE})
ELSEIF(RTABMap_CORE_DEBUG) ELSEIF(RTABMap_CORE_DEBUG)
SET(RTABMap_CORE ${RTABMap_CORE_DEBUG}) SET(RTABMap_CORE ${RTABMap_CORE_DEBUG})
ELSE()
SET(RTABMap_CORE ${RTABMap_CORE_RELEASE})
ENDIF() ENDIF()
#utilite lib #utilite lib
find_library(RTABMap_UTILITE_RELEASE NAMES rtabmap_utilite NO_DEFAULT_PATH HINTS "@CONF_LIB_DIR@") find_library(RTABMap_UTILITE_RELEASE NAMES rtabmap_utilite NO_DEFAULT_PATH HINTS @CONF_LIB_DIR@)
find_library(RTABMap_UTILITE_DEBUG NAMES rtabmap_utilited NO_DEFAULT_PATH HINTS "@CONF_LIB_DIR@") find_library(RTABMap_UTILITE_DEBUG NAMES rtabmap_utilited NO_DEFAULT_PATH HINTS @CONF_LIB_DIR@)
IF(RTABMap_UTILITE_DEBUG AND RTABMap_UTILITE_RELEASE) IF(RTABMap_UTILITE_DEBUG AND RTABMap_UTILITE_RELEASE)
SET(RTABMap_UTILITE SET(RTABMap_UTILITE
debug ${RTABMap_UTILITE_DEBUG} debug ${RTABMap_UTILITE_DEBUG}
optimized ${RTABMap_UTILITE_RELEASE} optimized ${RTABMap_UTILITE_RELEASE}
) )
ELSEIF(RTABMap_UTILITE_RELEASE)
SET(RTABMap_UTILITE ${RTABMap_UTILITE_RELEASE})
ELSEIF(RTABMap_UTILITE_DEBUG) ELSEIF(RTABMap_UTILITE_DEBUG)
SET(RTABMap_UTILITE ${RTABMap_UTILITE_DEBUG}) SET(RTABMap_UTILITE ${RTABMap_UTILITE_DEBUG})
ELSE()
SET(RTABMap_UTILITE ${RTABMap_UTILITE_RELEASE})
ENDIF() ENDIF()
set(RTABMap_LIBRARIES ${RTABMap_CORE} ${RTABMap_UTILITE}) set(RTABMap_LIBRARIES ${RTABMap_CORE} ${RTABMap_UTILITE})
#gui lib (OFF if RTAB-Map is not built with Qt) #gui lib (OFF if RTAB-Map is not built with Qt)
if(@CONF_WITH_GUI@) if(@CONF_WITH_GUI@)
find_library(RTABMap_GUI_RELEASE NAMES rtabmap_gui NO_DEFAULT_PATH HINTS "@CONF_LIB_DIR@") find_library(RTABMap_GUI_RELEASE NAMES rtabmap_gui NO_DEFAULT_PATH HINTS @CONF_LIB_DIR@)
find_library(RTABMap_GUI_DEBUG NAMES rtabmap_guid NO_DEFAULT_PATH HINTS "@CONF_LIB_DIR@") find_library(RTABMap_GUI_DEBUG NAMES rtabmap_guid NO_DEFAULT_PATH HINTS @CONF_LIB_DIR@)
IF(RTABMap_GUI_DEBUG AND RTABMap_GUI_RELEASE) IF(RTABMap_GUI_DEBUG AND RTABMap_GUI_RELEASE)
SET(RTABMap_GUI SET(RTABMap_GUI
@@ -61,13 +61,13 @@ if(@CONF_WITH_GUI@)
set(RTABMap_LIBRARIES ${RTABMap_LIBRARIES} ${RTABMap_GUI}) set(RTABMap_LIBRARIES ${RTABMap_LIBRARIES} ${RTABMap_GUI})
endif(@CONF_WITH_GUI@) endif(@CONF_WITH_GUI@)
# Dependencies
set(RTABMap_LIBRARIES ${RTABMap_LIBRARIES} @CONF_DEPENDENCIES@)
#backward compatibilities #backward compatibilities
if(RTABMap_CORE) set(RTABMAP_CORE ${RTABMap_CORE})
set(RTABMAP_CORE ${RTABMap_CORE}) set(RTABMAP_UTILITE ${RTABMap_UTILITE})
endif(RTABMap_CORE)
if(RTABMap_UTILITE)
set(RTABMAP_UTILITE ${RTABMap_UTILITE})
endif(RTABMap_UTILITE)
if(RTABMap_GUI) if(RTABMap_GUI)
set(RTABMAP_GUI ${RTABMap_GUI}) set(RTABMAP_GUI ${RTABMap_GUI})
set(RTABMAP_QT_VERSION @CONF_QT_VERSION@)
endif(RTABMap_GUI) endif(RTABMap_GUI)
+2
View File
@@ -49,6 +49,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@CVSBA@#define RTABMAP_CVSBA @CVSBA@#define RTABMAP_CVSBA
@DC1394@#define RTABMAP_DC1394 @DC1394@#define RTABMAP_DC1394
@FLYCAPTURE2@#define RTABMAP_FLYCAPTURE2 @FLYCAPTURE2@#define RTABMAP_FLYCAPTURE2
@ZED@#define RTABMAP_ZED
@OCTOMAP@#define RTABMAP_OCTOMAP
#endif /* VERSION_H_ */ #endif /* VERSION_H_ */
BIN
View File
Binary file not shown.
@@ -0,0 +1,11 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=1.6
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.source=1.6
@@ -2,8 +2,8 @@
<!-- BEGIN_INCLUDE(manifest) --> <!-- BEGIN_INCLUDE(manifest) -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.introlab.rtabmap" package="com.introlab.rtabmap"
android:versionCode="1" android:versionCode="9"
android:versionName="0.11.2"> android:versionName="@RTABMAP_VERSION@">
<uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
@@ -11,7 +11,7 @@
<uses-permission android:name="android.permission.READ_FRAME_BUFFER" /> <uses-permission android:name="android.permission.READ_FRAME_BUFFER" />
<uses-permission android:name="android.permission.ACCESS_SURFACE_FLINGER" /> <uses-permission android:name="android.permission.ACCESS_SURFACE_FLINGER" />
<uses-feature android:glEsVersion="0x00020000" /> <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. --> <!-- This is the platform API where NativeActivity was introduced. -->
<uses-sdk android:minSdkVersion="17" /> <uses-sdk android:minSdkVersion="17" />
+9
View File
@@ -14,11 +14,20 @@ if(NOT ANDROID_EXECUTABLE)
message(FATAL_ERROR "Can not find android command line tool: android") message(FATAL_ERROR "Can not find android command line tool: android")
endif() endif()
configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/AndroidManifest.xml.in"
"${CMAKE_CURRENT_SOURCE_DIR}/AndroidManifest.xml")
configure_file( configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/AndroidManifest.xml" "${CMAKE_CURRENT_SOURCE_DIR}/AndroidManifest.xml"
"${CMAKE_CURRENT_BINARY_DIR}/AndroidManifest.xml" "${CMAKE_CURRENT_BINARY_DIR}/AndroidManifest.xml"
COPYONLY) COPYONLY)
configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/info.txt.in"
"${CMAKE_CURRENT_SOURCE_DIR}/res/raw/info.txt")
configure_file( configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/ant.properties.in" "${CMAKE_CURRENT_SOURCE_DIR}/ant.properties.in"
"${CMAKE_CURRENT_BINARY_DIR}/ant.properties" "${CMAKE_CURRENT_BINARY_DIR}/ant.properties"
@@ -1,5 +1,5 @@
<h3>Real-Time Appearance-Based Mapping</h3> <h3>Real-Time Appearance-Based Mapping</h3>
Version 0.11.2<br> Version @RTABMAP_VERSION@<br>
Author: Mathieu Labb&eacute;<br> Author: Mathieu Labb&eacute;<br>
Copyright 2016<br> Copyright 2016<br>
IntRoLab - Universit&eacute; de Sherbrooke<br> IntRoLab - Universit&eacute; de Sherbrooke<br>
+31 -19
View File
@@ -99,8 +99,12 @@ static rtabmap::Transform opticalRotation(
CameraTango::CameraTango(int decimation, bool autoExposure) : CameraTango::CameraTango(int decimation, bool autoExposure) :
Camera(0, opticalRotation), Camera(0, opticalRotation),
tango_config_(0), tango_config_(0),
firstFrame_(true),
decimation_(decimation), decimation_(decimation),
autoExposure_(autoExposure) autoExposure_(autoExposure),
cloudStamp_(0),
tangoColorType_(0),
tangoColorStamp_(0)
{ {
UASSERT(decimation >= 1); UASSERT(decimation >= 1);
} }
@@ -125,8 +129,7 @@ bool CameraTango::init(const std::string & calibrationFolder, const std::string
// Set auto-recovery for motion tracking as requested by the user. // Set auto-recovery for motion tracking as requested by the user.
bool is_atuo_recovery = true; bool is_atuo_recovery = true;
int ret = TangoConfig_setBool(tango_config_, "config_enable_auto_recovery", int ret = TangoConfig_setBool(tango_config_, "config_enable_auto_recovery", is_atuo_recovery);
is_atuo_recovery);
if (ret != TANGO_SUCCESS) if (ret != TANGO_SUCCESS)
{ {
LOGE("NativeRTABMap: config_enable_auto_recovery() failed with error code: %d", ret); LOGE("NativeRTABMap: config_enable_auto_recovery() failed with error code: %d", ret);
@@ -141,13 +144,15 @@ bool CameraTango::init(const std::string & calibrationFolder, const std::string
return false; return false;
} }
// disable auto exposure // disable auto exposure (disabled, seems broken on latest Tango releases)
ret = TangoConfig_setBool(tango_config_, "config_color_mode_auto", autoExposure_); ret = TangoConfig_setBool(tango_config_, "config_color_mode_auto", autoExposure_);
if (ret != TANGO_SUCCESS) if (ret != TANGO_SUCCESS)
{ {
LOGE("NativeRTABMap: config_color_mode_auto() failed with error code: %d", ret); LOGE("NativeRTABMap: config_color_mode_auto() failed with error code: %d", ret);
return false; //return false;
} }
else
{
if(!autoExposure_) if(!autoExposure_)
{ {
ret = TangoConfig_setInt32(tango_config_, "config_color_iso", 800); ret = TangoConfig_setInt32(tango_config_, "config_color_iso", 800);
@@ -157,6 +162,13 @@ bool CameraTango::init(const std::string & calibrationFolder, const std::string
return false; return false;
} }
} }
bool verifyAutoExposureState;
int32_t verifyIso, verifyExp;
TangoConfig_getBool( tango_config_, "config_color_mode_auto", &verifyAutoExposureState );
TangoConfig_getInt32( tango_config_, "config_color_iso", &verifyIso );
TangoConfig_getInt32( tango_config_, "config_color_exp", &verifyExp );
LOGI( "NativeRTABMap: config_color autoExposure=%s %d %d", verifyAutoExposureState?"On" : "Off", verifyIso, verifyExp );
}
// Enable depth. // Enable depth.
ret = TangoConfig_setBool(tango_config_, "config_enable_depth", true); ret = TangoConfig_setBool(tango_config_, "config_enable_depth", true);
@@ -173,15 +185,13 @@ bool CameraTango::init(const std::string & calibrationFolder, const std::string
ret = TangoConfig_setBool(tango_config_, "config_enable_low_latency_imu_integration", true); ret = TangoConfig_setBool(tango_config_, "config_enable_low_latency_imu_integration", true);
if (ret != TANGO_SUCCESS) if (ret != TANGO_SUCCESS)
{ {
LOGE("Failed to enable low latency imu integration."); LOGE("NativeRTABMap: Failed to enable low latency imu integration.");
return false; return false;
} }
// Get TangoCore version string from service. // Get TangoCore version string from service.
char tango_core_version[kVersionStringLength]; char tango_core_version[kVersionStringLength];
ret = TangoConfig_getString( ret = TangoConfig_getString(tango_config_, "tango_service_library_version", tango_core_version, kVersionStringLength);
tango_config_, "tango_service_library_version",
tango_core_version, kVersionStringLength);
if (ret != TANGO_SUCCESS) if (ret != TANGO_SUCCESS)
{ {
LOGE("NativeRTABMap: get tango core version failed with error code: %d", ret); LOGE("NativeRTABMap: get tango core version failed with error code: %d", ret);
@@ -197,14 +207,14 @@ bool CameraTango::init(const std::string & calibrationFolder, const std::string
ret = TangoService_connectOnXYZijAvailable(onPointCloudAvailableRouter); ret = TangoService_connectOnXYZijAvailable(onPointCloudAvailableRouter);
if (ret != TANGO_SUCCESS) if (ret != TANGO_SUCCESS)
{ {
LOGE("PointCloudApp: Failed to connect to point cloud callback with error code: %d", ret); LOGE("NativeRTABMap: Failed to connect to point cloud callback with error code: %d", ret);
return false; return false;
} }
ret = TangoService_connectOnFrameAvailable(TANGO_CAMERA_COLOR, this, onFrameAvailableRouter); ret = TangoService_connectOnFrameAvailable(TANGO_CAMERA_COLOR, this, onFrameAvailableRouter);
if (ret != TANGO_SUCCESS) if (ret != TANGO_SUCCESS)
{ {
LOGE("PointCloudApp: Failed to connect to color callback with error code: %d", ret); LOGE("NativeRTABMap: Failed to connect to color callback with error code: %d", ret);
return false; return false;
} }
@@ -216,7 +226,7 @@ bool CameraTango::init(const std::string & calibrationFolder, const std::string
ret = TangoService_connectOnPoseAvailable(1, &pair, onPoseAvailableRouter); ret = TangoService_connectOnPoseAvailable(1, &pair, onPoseAvailableRouter);
if (ret != TANGO_SUCCESS) if (ret != TANGO_SUCCESS)
{ {
LOGE("PointCloudApp: Failed to connect to pose callback with error code: %d", ret); LOGE("NativeRTABMap: Failed to connect to pose callback with error code: %d", ret);
return false; return false;
} }
@@ -234,7 +244,7 @@ bool CameraTango::init(const std::string & calibrationFolder, const std::string
ret = TangoService_connect(this, tango_config_); ret = TangoService_connect(this, tango_config_);
if (ret != TANGO_SUCCESS) if (ret != TANGO_SUCCESS)
{ {
LOGE("PointCloudApp: Failed to connect to the Tango service with error code: %d", ret); LOGE("NativeRTABMap: Failed to connect to the Tango service with error code: %d", ret);
return false; return false;
} }
@@ -253,7 +263,7 @@ bool CameraTango::init(const std::string & calibrationFolder, const std::string
ret = TangoService_getPoseAtTime(0.0, frame_pair, &pose_data); ret = TangoService_getPoseAtTime(0.0, frame_pair, &pose_data);
if (ret != TANGO_SUCCESS) if (ret != TANGO_SUCCESS)
{ {
LOGE("PointCloudApp: Failed to get transform between the IMU frame and device frames"); LOGE("NativeRTABMap: Failed to get transform between the IMU frame and device frames");
return false; return false;
} }
imuTDevice_ = rtabmap::Transform( imuTDevice_ = rtabmap::Transform(
@@ -271,7 +281,7 @@ bool CameraTango::init(const std::string & calibrationFolder, const std::string
ret = TangoService_getPoseAtTime(0.0, frame_pair, &pose_data); ret = TangoService_getPoseAtTime(0.0, frame_pair, &pose_data);
if (ret != TANGO_SUCCESS) if (ret != TANGO_SUCCESS)
{ {
LOGE("PointCloudApp: Failed to get transform between the color camera frame and device frames"); LOGE("NativeRTABMap: Failed to get transform between the color camera frame and device frames");
return false; return false;
} }
imuTDepthCamera_ = rtabmap::Transform( imuTDepthCamera_ = rtabmap::Transform(
@@ -290,7 +300,7 @@ bool CameraTango::init(const std::string & calibrationFolder, const std::string
ret = TangoService_getCameraIntrinsics(TANGO_CAMERA_COLOR, &color_camera_intrinsics); ret = TangoService_getCameraIntrinsics(TANGO_CAMERA_COLOR, &color_camera_intrinsics);
if (ret != TANGO_SUCCESS) if (ret != TANGO_SUCCESS)
{ {
LOGE("SynchronizationApplication: Failed to get the intrinsics for the color camera with error code: %d.", ret); LOGE("NativeRTABMap: Failed to get the intrinsics for the color camera with error code: %d.", ret);
return false; return false;
} }
model_ = CameraModel( model_ = CameraModel(
@@ -318,6 +328,7 @@ void CameraTango::close()
tango_config_ = nullptr; tango_config_ = nullptr;
TangoService_disconnect(); TangoService_disconnect();
} }
firstFrame_ = true;
} }
void CameraTango::cloudReceived(const cv::Mat & cloud, double timestamp) void CameraTango::cloudReceived(const cv::Mat & cloud, double timestamp)
@@ -374,7 +385,6 @@ void CameraTango::poseReceived(const Transform & pose)
void CameraTango::tangoEventReceived(int type, const char * key, const char * value) void CameraTango::tangoEventReceived(int type, const char * key, const char * value)
{ {
LOGE("Tango event: %s:%s", key, value);
this->post(new CameraTangoEvent(type, key, value)); this->post(new CameraTangoEvent(type, key, value));
} }
@@ -454,7 +464,7 @@ rtabmap::Transform CameraTango::getPoseAtTimestamp(double timestamp, bool inOpen
return pose; return pose;
} }
SensorData CameraTango::captureImage() SensorData CameraTango::captureImage(CameraInfo * info)
{ {
LOGI("Capturing image..."); LOGI("Capturing image...");
@@ -624,7 +634,9 @@ void CameraTango::mainLoop()
{ {
rtabmap::Transform pose = data.groundTruth(); rtabmap::Transform pose = data.groundTruth();
data.setGroundTruth(Transform()); data.setGroundTruth(Transform());
this->post(new OdometryEvent(data, pose, 0.0001, 0.0001)); LOGI("Publish odometry message (variance=%f)", firstFrame_?9999:0.0001);
this->post(new OdometryEvent(data, pose, firstFrame_?9999:0.0001, firstFrame_?9999:0.0001));
firstFrame_ = false;
} }
else if(!this->isKilled()) else if(!this->isKilled())
{ {
+3 -1
View File
@@ -77,6 +77,7 @@ public:
virtual bool isCalibrated() const; virtual bool isCalibrated() const;
virtual std::string getSerial() const; virtual std::string getSerial() const;
rtabmap::Transform tangoPoseToTransform(const TangoPoseData * tangoPose, bool inOpenGLFrame) const; rtabmap::Transform tangoPoseToTransform(const TangoPoseData * tangoPose, bool inOpenGLFrame) const;
void setDecimation(int value) {decimation_ = value;}
void setAutoExposure(bool enabled) {autoExposure_ = enabled;} void setAutoExposure(bool enabled) {autoExposure_ = enabled;}
void cloudReceived(const cv::Mat & cloud, double timestamp); void cloudReceived(const cv::Mat & cloud, double timestamp);
@@ -85,7 +86,7 @@ public:
void tangoEventReceived(int type, const char * key, const char * value); void tangoEventReceived(int type, const char * key, const char * value);
protected: protected:
virtual SensorData captureImage(); virtual SensorData captureImage(CameraInfo * info = 0);
private: private:
rtabmap::Transform getPoseAtTimestamp(double timestamp, bool inOpenGLFrame); rtabmap::Transform getPoseAtTimestamp(double timestamp, bool inOpenGLFrame);
@@ -95,6 +96,7 @@ private:
private: private:
void * tango_config_; void * tango_config_;
bool firstFrame_;
int decimation_; int decimation_;
bool autoExposure_; bool autoExposure_;
cv::Mat cloud_; cv::Mat cloud_;
+472 -215
View File
@@ -36,63 +36,53 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <rtabmap/core/Graph.h> #include <rtabmap/core/Graph.h>
#include <rtabmap/utilite/UEventsManager.h> #include <rtabmap/utilite/UEventsManager.h>
#include <rtabmap/utilite/UStl.h> #include <rtabmap/utilite/UStl.h>
#include <rtabmap/utilite/UDirectory.h>
#include <rtabmap/utilite/UFile.h>
#include <opencv2/opencv_modules.hpp> #include <opencv2/opencv_modules.hpp>
#include <rtabmap/core/util3d_surface.h> #include <rtabmap/core/util3d_surface.h>
#include <rtabmap/utilite/UConversion.h> #include <rtabmap/utilite/UConversion.h>
#include <rtabmap/utilite/UTimer.h> #include <rtabmap/utilite/UTimer.h>
#include <rtabmap/core/ParamEvent.h> #include <rtabmap/core/ParamEvent.h>
#include <rtabmap/core/Compression.h>
#include <rtabmap/core/Optimizer.h>
#include <rtabmap/core/VWDictionary.h>
#include <rtabmap/core/Memory.h>
#include <pcl/filters/extract_indices.h> #include <pcl/filters/extract_indices.h>
#include <pcl/io/ply_io.h> #include <pcl/io/ply_io.h>
#include <pcl/io/obj_io.h>
const int kVersionStringLength = 128; const int kVersionStringLength = 128;
const int cameraTangoDecimation = 2;
const int renderingCloudDecimation = 8;
const float renderingCloudMaxDepth = 4.0f;
const int maxFeatures = 400;
const float meshAngleTolerance = 0.1745; // 10 degrees
const int meshTrianglePixels = 1;
const bool substractFiltering = false;
const float subtractRadius = 0.02;
const float subtractMaxAngle = M_PI/4.0f;
const int minNeighborsInRadius = 5;
const float closeVerticesDistance = 0.02f;
static JavaVM *jvm; static JavaVM *jvm;
static jobject RTABMapActivity = 0; static jobject RTABMapActivity = 0;
namespace {
constexpr int kTangoCoreMinimumVersion = 9377;
} // anonymous namespace.
rtabmap::ParametersMap RTABMapApp::getRtabmapParameters() rtabmap::ParametersMap RTABMapApp::getRtabmapParameters()
{ {
rtabmap::ParametersMap parameters; rtabmap::ParametersMap parameters;
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kRtabmapLoopThr(), "0.11")); parameters.insert(mappingParameters_.begin(), mappingParameters_.end());
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kRGBDLoopClosureReextractFeatures(), std::string("false")));
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kKpDetectorStrategy(), std::string("6"))); // GFTT/BRIEF parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kKpDetectorStrategy(), std::string("6"))); // GFTT/BRIEF
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kGFTTQualityLevel(), std::string("0.0001"))); parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kGFTTQualityLevel(), std::string("0.0001")));
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kGFTTMinDistance(), std::string("10"))); parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kMemImagePreDecimation(), std::string(fullResolution_?"2":"1")));
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kFASTThreshold(), std::string("1"))); parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kFASTThreshold(), std::string("1")));
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kBRIEFBytes(), std::string("64"))); parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kBRIEFBytes(), std::string("64")));
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kMemImageKept(), "false")); parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kRtabmapTimeThr(), std::string("800")));
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kMemBinDataKept(), uBool2Str(!trajectoryMode_))); parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kMemBinDataKept(), uBool2Str(!trajectoryMode_)));
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kMemRawDescriptorsKept(), "true")); // for visual registration
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kMemNotLinkedNodesKept(), std::string("false"))); parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kMemNotLinkedNodesKept(), std::string("false")));
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kKpNNStrategy(), std::string("1"))); // Kd-tree parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kOptimizerIterations(), graphOptimization_?"10":"0"));
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kKpMaxFeatures(), std::string("200")));
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kKpNndrRatio(), std::string("0.8"))); // set the one for kd-tree
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kKpMaxFeatures(), !loopClosureDetection_?std::string("-1"):uNumber2Str(maxFeatures))); // Kd-tree
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kOptimizerIterations(), uNumber2Str(graphOptimization_?rtabmap::Parameters::defaultOptimizerIterations():0)));
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kMemIncrementalMemory(), uBool2Str(!localizationMode_))); parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kMemIncrementalMemory(), uBool2Str(!localizationMode_)));
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kRtabmapMaxRetrieved(), uBool2Str(!localizationMode_))); parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kRtabmapMaxRetrieved(), uBool2Str(!localizationMode_)));
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kKpMaxDepth(), std::string("10"))); // to avoid extracting features in invalid depth (as we compute transformation directly from the words) parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kKpMaxDepth(), std::string("10"))); // to avoid extracting features in invalid depth (as we compute transformation directly from the words)
//parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kMemImageDecimation(), std::string("2")));
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kRGBDOptimizeFromGraphEnd(), std::string("true"))); parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kRGBDOptimizeFromGraphEnd(), std::string("true")));
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kRGBDOptimizeMaxError(), std::string("1")));
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kOptimizerRobust(), std::string("false")));
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kOptimizerVarianceIgnored(), std::string("false")));
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kRtabmapTimeThr(), std::string("700")));
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kDbSqlite3InMemory(), std::string("true"))); parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kDbSqlite3InMemory(), std::string("true")));
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kMemUseDepthAsMask(), std::string("true")));
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kVisMinInliers(), std::string("15"))); parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kVisMinInliers(), std::string("15")));
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kVisRefineIterations(), std::string("5"))); parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kVisEstimationType(), std::string("0"))); // 0=3D-3D 1=PnP
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kRGBDOptimizeMaxError(), std::string("0.05")));
return parameters; return parameters;
} }
@@ -100,19 +90,26 @@ rtabmap::ParametersMap RTABMapApp::getRtabmapParameters()
RTABMapApp::RTABMapApp() : RTABMapApp::RTABMapApp() :
camera_(0), camera_(0),
rtabmapThread_(0), rtabmapThread_(0),
rtabmap_(0),
logHandler_(0), logHandler_(0),
mapCloudShown_(true),
odomCloudShown_(true), odomCloudShown_(true),
loopClosureDetection_(true),
graphOptimization_(true), graphOptimization_(true),
nodesFiltering_(false),
localizationMode_(false), localizationMode_(false),
trajectoryMode_(false), trajectoryMode_(false),
autoExposure_(false), autoExposure_(false),
fullResolution_(false),
maxCloudDepth_(0.0),
meshTrianglePix_(1),
meshAngleToleranceDeg_(10.0),
clearSceneOnNextRender_(false), clearSceneOnNextRender_(false),
totalPoints_(0), totalPoints_(0),
totalPolygons_(0), totalPolygons_(0),
lastDrawnCloudsCount_(0) lastDrawnCloudsCount_(0),
renderingFPS_(0.0f)
{ {
} }
RTABMapApp::~RTABMapApp() { RTABMapApp::~RTABMapApp() {
@@ -131,22 +128,19 @@ RTABMapApp::~RTABMapApp() {
} }
} }
int RTABMapApp::TangoInitialize(JNIEnv* env, jobject caller_activity) void RTABMapApp::onCreate(JNIEnv* env, jobject caller_activity)
{ {
env->GetJavaVM(&jvm); env->GetJavaVM(&jvm);
RTABMapActivity = env->NewGlobalRef(caller_activity); RTABMapActivity = env->NewGlobalRef(caller_activity);
LOGI("RTABMapApp::TangoInitialize()"); LOGI("RTABMapApp::onCreate()");
createdMeshes_.clear(); createdMeshes_.clear();
previousCloud_.first = 0;
previousCloud_.second.first.reset();
previousCloud_.second.second.reset();
rawPoses_.clear(); rawPoses_.clear();
clearSceneOnNextRender_ = true; clearSceneOnNextRender_ = true;
totalPoints_ = 0; totalPoints_ = 0;
totalPolygons_ = 0; totalPolygons_ = 0;
lastDrawnCloudsCount_ = 0; lastDrawnCloudsCount_ = 0;
renderingFPS_ = 0.0f;
if(camera_) if(camera_)
{ {
@@ -157,6 +151,7 @@ int RTABMapApp::TangoInitialize(JNIEnv* env, jobject caller_activity)
rtabmapThread_->close(false); rtabmapThread_->close(false);
delete rtabmapThread_; delete rtabmapThread_;
rtabmapThread_ = 0; rtabmapThread_ = 0;
rtabmap_ = 0;
} }
if(logHandler_ == 0) if(logHandler_ == 0)
@@ -168,13 +163,7 @@ int RTABMapApp::TangoInitialize(JNIEnv* env, jobject caller_activity)
this->registerToEventsManager(); this->registerToEventsManager();
camera_ = new rtabmap::CameraTango(cameraTangoDecimation, autoExposure_); 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) void RTABMapApp::openDatabase(const std::string & databasePath)
@@ -187,20 +176,21 @@ void RTABMapApp::openDatabase(const std::string & databasePath)
rtabmapThread_->close(false); rtabmapThread_->close(false);
delete rtabmapThread_; delete rtabmapThread_;
rtabmapThread_ = 0; rtabmapThread_ = 0;
rtabmap_ = 0;
} }
//Rtabmap //Rtabmap
rtabmap::Rtabmap * rtabmap = new rtabmap::Rtabmap(); rtabmap_ = new rtabmap::Rtabmap();
rtabmap::ParametersMap parameters = getRtabmapParameters(); rtabmap::ParametersMap parameters = getRtabmapParameters();
rtabmap->init(parameters, databasePath); rtabmap_->init(parameters, databasePath);
rtabmapThread_ = new rtabmap::RtabmapThread(rtabmap); rtabmapThread_ = new rtabmap::RtabmapThread(rtabmap_);
// Generate all meshes // Generate all meshes
std::map<int, rtabmap::Signature> signatures; std::map<int, rtabmap::Signature> signatures;
std::map<int, rtabmap::Transform> poses; std::map<int, rtabmap::Transform> poses;
std::multimap<int, rtabmap::Link> links; std::multimap<int, rtabmap::Link> links;
rtabmap->get3DMap( rtabmap_->get3DMap(
signatures, signatures,
poses, poses,
links, links,
@@ -210,6 +200,9 @@ void RTABMapApp::openDatabase(const std::string & databasePath)
clearSceneOnNextRender_ = true; clearSceneOnNextRender_ = true;
rtabmap::Statistics stats; rtabmap::Statistics stats;
stats.setSignatures(signatures); stats.setSignatures(signatures);
stats.addStatistic(rtabmap::Statistics::kMemoryWorking_memory_size(), (float)rtabmap_->getWMSize());
stats.addStatistic(rtabmap::Statistics::kKeypointDictionary_size(), (float)rtabmap_->getMemory()->getVWDictionary()->getVisualWords().size());
stats.addStatistic(rtabmap::Statistics::kMemoryDatabase_memory_used(), (float)rtabmap_->getMemory()->getDatabaseMemoryUsed());
stats.setPoses(poses); stats.setPoses(poses);
stats.setConstraints(links); stats.setConstraints(links);
rtabmapEvents_.push_back(stats); rtabmapEvents_.push_back(stats);
@@ -225,22 +218,27 @@ void RTABMapApp::openDatabase(const std::string & databasePath)
rtabmapMutex_.unlock(); rtabmapMutex_.unlock();
} }
int RTABMapApp::onResume() bool RTABMapApp::onTangoServiceConnected(JNIEnv* env, jobject iBinder)
{ {
LOGW("onResume()"); LOGW("onTangoServiceConnected()");
if(camera_) if(camera_)
{ {
camera_->join(true); camera_->join(true);
if (TangoService_setBinder(env, iBinder) != TANGO_SUCCESS) {
LOGE("TangoHandler::ConnectTango, TangoService_setBinder error");
return false;
}
if(camera_->init()) if(camera_->init())
{ {
LOGI("Start camera thread"); LOGI("Start camera thread");
camera_->start(); camera_->start();
return TANGO_SUCCESS; return true;
} }
LOGE("Failed camera initialization!"); LOGE("Failed camera initialization!");
} }
return TANGO_ERROR; return false;
} }
void RTABMapApp::onPause() void RTABMapApp::onPause()
@@ -272,6 +270,20 @@ void RTABMapApp::SetViewPort(int width, int height)
main_scene_.SetupViewPort(width, height); main_scene_.SetupViewPort(width, height);
} }
class PostRenderEvent : public UEvent
{
public:
PostRenderEvent(const rtabmap::Statistics & stats) :
stats_(stats)
{
}
virtual std::string getClassName() const {return "PostRenderEvent";}
const rtabmap::Statistics & getStats() const {return stats_;}
private:
rtabmap::Statistics stats_;
};
// OpenGL thread // OpenGL thread
int RTABMapApp::Render() int RTABMapApp::Render()
{ {
@@ -296,13 +308,11 @@ int RTABMapApp::Render()
main_scene_.clear(); main_scene_.clear();
clearSceneOnNextRender_ = false; clearSceneOnNextRender_ = false;
createdMeshes_.clear(); createdMeshes_.clear();
previousCloud_.first = 0;
previousCloud_.second.first.reset();
previousCloud_.second.second.reset();
rawPoses_.clear(); rawPoses_.clear();
totalPoints_ = 0; totalPoints_ = 0;
totalPolygons_ = 0; totalPolygons_ = 0;
lastDrawnCloudsCount_ = 0; lastDrawnCloudsCount_ = 0;
renderingFPS_ = 0.0f;
} }
// Process events // Process events
@@ -374,20 +384,14 @@ int RTABMapApp::Render()
} }
} }
const std::multimap<int, rtabmap::Link> & links = rtabmapEvents.back().constraints();
if(poses.size()) if(poses.size())
{ {
const std::multimap<int, rtabmap::Link> & links = rtabmapEvents.back().constraints();
//update graph //update graph
main_scene_.updateGraph(poses, links); main_scene_.updateGraph(poses, links);
// update clouds // update clouds
boost::mutex::scoped_lock lock(meshesMutex_);
//filter poses?
// make sure the last pose is here though
//poses.insert(*rtabmapEvents.back().poses().rbegin());
std::set<std::string> strIds; std::set<std::string> strIds;
for(std::map<int, rtabmap::Transform>::iterator iter=poses.begin(); iter!=poses.end(); ++iter) for(std::map<int, rtabmap::Transform>::iterator iter=poses.begin(); iter!=poses.end(); ++iter)
{ {
@@ -399,6 +403,15 @@ int RTABMapApp::Render()
//just update pose //just update pose
main_scene_.setCloudPose(id, iter->second); main_scene_.setCloudPose(id, iter->second);
main_scene_.setCloudVisible(id, true); main_scene_.setCloudVisible(id, true);
std::map<int, Mesh>::iterator meshIter = createdMeshes_.find(id);
if(meshIter!=createdMeshes_.end())
{
meshIter->second.pose = iter->second;
}
else
{
UERROR("Not found mesh %d !?!?", id);
}
} }
else if(uContains(bufferedSensorData, id)) else if(uContains(bufferedSensorData, id))
{ {
@@ -406,73 +419,46 @@ int RTABMapApp::Render()
if(!data.imageRaw().empty() && !data.depthRaw().empty()) if(!data.imageRaw().empty() && !data.depthRaw().empty())
{ {
// Voxelize and filter depending on the previous cloud? // Voxelize and filter depending on the previous cloud?
pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloudWithoutNormals; pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud;
pcl::IndicesPtr indices(new std::vector<int>); pcl::IndicesPtr indices(new std::vector<int>);
LOGI("Creating node cloud %d (image size=%dx%d)", id, data.imageRaw().cols, data.imageRaw().rows); LOGI("Creating node cloud %d (image size=%dx%d)", id, data.imageRaw().cols, data.imageRaw().rows);
cloudWithoutNormals = rtabmap::util3d::cloudRGBFromSensorData(data, renderingCloudDecimation, renderingCloudMaxDepth, 0, 0, indices.get()); cloud = rtabmap::util3d::cloudRGBFromSensorData(data, data.imageRaw().rows/data.depthRaw().rows, maxCloudDepth_, 0, indices.get());
//compute normals
pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr cloud = rtabmap::util3d::computeNormals(cloudWithoutNormals, 6);
if(cloud->size() && indices->size()) if(cloud->size() && indices->size())
{ {
UTimer time; UTimer time;
// substract? set points to NaN which are over previous cloud
pcl::IndicesPtr indicesKept = indices;
if(substractFiltering &&
subtractRadius > 0.0 &&
indices->size() &&
previousCloud_.first > 0 &&
previousCloud_.second.first.get() != 0 &&
previousCloud_.second.second.get() != 0 &&
previousCloud_.second.second->size() &&
poses.find(previousCloud_.first) != poses.end())
{
rtabmap::Transform t = iter->second.inverse() * poses.at(previousCloud_.first);
pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr previousCloud = rtabmap::util3d::transformPointCloud(previousCloud_.second.first, t);
indicesKept = rtabmap::util3d::subtractFiltering(
cloud,
indices,
previousCloud,
previousCloud_.second.second,
subtractRadius,
subtractMaxAngle,
minNeighborsInRadius);
UINFO("Subtraction %fs", time.ticks());
}
previousCloud_.first = id;
previousCloud_.second.first = cloud;
previousCloud_.second.second = indices;
// pcl::organizedFastMesh doesn't take indices, so set to NaN points we don't need to mesh // pcl::organizedFastMesh doesn't take indices, so set to NaN points we don't need to mesh
pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr output(new pcl::PointCloud<pcl::PointXYZRGBNormal>); pcl::PointCloud<pcl::PointXYZRGB>::Ptr output(new pcl::PointCloud<pcl::PointXYZRGB>);
pcl::ExtractIndices<pcl::PointXYZRGBNormal> filter; pcl::ExtractIndices<pcl::PointXYZRGB> filter;
filter.setIndices(indicesKept); filter.setIndices(indices);
filter.setKeepOrganized(true); filter.setKeepOrganized(true);
filter.setInputCloud(cloud); filter.setInputCloud(cloud);
filter.filter(*output); filter.filter(*output);
LOGE("Filtering %d from %d -> %d (%fs)", (int)indices->size(), (int)indices->size(), (int)indicesKept->size(), time.ticks());
std::vector<pcl::Vertices> polygons = rtabmap::util3d::organizedFastMesh(output, meshAngleTolerance, false, meshTrianglePixels); std::vector<pcl::Vertices> polygons = rtabmap::util3d::organizedFastMesh(output, meshAngleToleranceDeg_*M_PI/180.0, false, meshTrianglePix_);
pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr outputCloud(new pcl::PointCloud<pcl::PointXYZRGBNormal>); pcl::PointCloud<pcl::PointXYZRGB>::Ptr outputCloud(new pcl::PointCloud<pcl::PointXYZRGB>);
std::vector<pcl::Vertices> outputPolygons; std::vector<pcl::Vertices> outputPolygons;
rtabmap::util3d::filterNotUsedVerticesFromMesh(
*output, outputCloud = output;
polygons, outputPolygons = polygons;
*outputCloud,
outputPolygons);
LOGI("Creating mesh, %d polygons (%fs)", (int)outputPolygons.size(), time.ticks()); LOGI("Creating mesh, %d polygons (%fs)", (int)outputPolygons.size(), time.ticks());
if(outputCloud->size()) if(outputCloud->size() && outputPolygons.size())
{ {
totalPolygons_ += outputPolygons.size(); totalPolygons_ += outputPolygons.size();
main_scene_.addOrUpdateCloud(id, outputCloud, outputPolygons, iter->second);
main_scene_.addCloud(id, outputCloud, outputPolygons, iter->second, data.imageRaw());
// protect createdMeshes_ used also by exportMesh() method // protect createdMeshes_ used also by exportMesh() method
boost::mutex::scoped_lock lock(meshesMutex_); std::pair<std::map<int, Mesh>::iterator, bool> inserted = createdMeshes_.insert(std::make_pair(id, Mesh()));
createdMeshes_.insert(std::make_pair(id, std::make_pair(std::make_pair(outputCloud, outputPolygons), iter->second))); UASSERT(inserted.second);
inserted.first->second.cloud = outputCloud;
inserted.first->second.polygons = outputPolygons;
inserted.first->second.pose = iter->second;
inserted.first->second.texture = data.imageCompressed();
} }
else else
{ {
@@ -486,13 +472,29 @@ int RTABMapApp::Render()
} }
} }
//filter poses?
if(poses.size() > 2)
{
if(nodesFiltering_)
{
for(std::multimap<int, rtabmap::Link>::const_iterator iter=links.begin(); iter!=links.end(); ++iter)
{
if(iter->second.type() != rtabmap::Link::kNeighbor)
{
int oldId = iter->second.to()>iter->second.from()?iter->second.from():iter->second.to();
poses.erase(oldId);
}
}
}
}
//update cloud visibility //update cloud visibility
std::set<int> addedClouds = main_scene_.getAddedClouds(); std::set<int> addedClouds = main_scene_.getAddedClouds();
for(std::set<int>::const_iterator iter=addedClouds.begin(); for(std::set<int>::const_iterator iter=addedClouds.begin();
iter!=addedClouds.end(); iter!=addedClouds.end();
++iter) ++iter)
{ {
if(*iter > 0 && (!mapCloudShown_ || poses.find(*iter) == poses.end())) if(*iter > 0 && poses.find(*iter) == poses.end())
{ {
main_scene_.setCloudVisible(*iter, false); main_scene_.setCloudVisible(*iter, false);
} }
@@ -513,23 +515,25 @@ int RTABMapApp::Render()
} }
} }
main_scene_.setCloudVisible(-1, odomCloudShown_ && !trajectoryMode_);
//just process the last one //just process the last one
if(set && !event.pose().isNull()) if(set && !event.pose().isNull())
{ {
main_scene_.setCloudVisible(-1, false);
if(odomCloudShown_ && !trajectoryMode_) if(odomCloudShown_ && !trajectoryMode_)
{ {
if(!event.data().imageRaw().empty() && !event.data().depthRaw().empty()) if(!event.data().imageRaw().empty() && !event.data().depthRaw().empty())
{ {
LOGI("Creating Odom cloud (rgb=%dx%d depth=%dx%d)",
event.data().imageRaw().cols, event.data().imageRaw().rows,
event.data().depthRaw().cols, event.data().depthRaw().rows);
pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud; pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud;
cloud = rtabmap::util3d::cloudRGBFromSensorData(event.data(), renderingCloudDecimation, renderingCloudMaxDepth); cloud = rtabmap::util3d::cloudRGBFromSensorData(event.data(), event.data().imageRaw().rows/event.data().depthRaw().rows, maxCloudDepth_);
if(cloud->size()) if(cloud->size())
{ {
std::vector<pcl::Vertices> polygons = rtabmap::util3d::organizedFastMesh(cloud, meshAngleTolerance, false, meshTrianglePixels); LOGI("Created odom cloud (rgb=%dx%d depth=%dx%d cloud=%dx%d)",
main_scene_.addOrUpdateCloud(-1, cloud, polygons, opengl_world_T_rtabmap_world*event.pose()); event.data().imageRaw().cols, event.data().imageRaw().rows,
event.data().depthRaw().cols, event.data().depthRaw().rows,
(int)cloud->width, (int)cloud->height);
std::vector<pcl::Vertices> polygons = rtabmap::util3d::organizedFastMesh(cloud, meshAngleToleranceDeg_*M_PI/180.0, false, meshTrianglePix_);
main_scene_.addCloud(-1, cloud, polygons, opengl_world_T_rtabmap_world*event.pose(), event.data().imageRaw());
main_scene_.setCloudVisible(-1, true); main_scene_.setCloudVisible(-1, true);
} }
else else
@@ -545,7 +549,16 @@ int RTABMapApp::Render()
} }
} }
UTimer fpsTime;
lastDrawnCloudsCount_ = main_scene_.Render(); lastDrawnCloudsCount_ = main_scene_.Render();
renderingFPS_ = 1.0/fpsTime.elapsed();
if(rtabmapEvents.size())
{
// send statistics to GUI
LOGI("Posting PostRenderEvent!");
UEventsManager::post(new PostRenderEvent(rtabmapEvents.back()));
}
return notifyDataLoaded?1:0; return notifyDataLoaded?1:0;
} }
@@ -579,7 +592,7 @@ void RTABMapApp::setPausedMapping(bool paused)
} }
void RTABMapApp::setMapCloudShown(bool shown) void RTABMapApp::setMapCloudShown(bool shown)
{ {
mapCloudShown_ = shown; main_scene_.setMapRendering(shown);
} }
void RTABMapApp::setOdomCloudShown(bool shown) void RTABMapApp::setOdomCloudShown(bool shown)
{ {
@@ -608,6 +621,27 @@ void RTABMapApp::setTrajectoryMode(bool enabled)
void RTABMapApp::setGraphOptimization(bool enabled) void RTABMapApp::setGraphOptimization(bool enabled)
{ {
graphOptimization_ = enabled; graphOptimization_ = enabled;
if(!camera_->isRunning())
{
std::map<int, rtabmap::Transform> poses;
std::multimap<int, rtabmap::Link> links;
rtabmap_->getGraph(poses, links, true, true);
if(poses.size())
{
boost::mutex::scoped_lock lock(rtabmapMutex_);
rtabmap::Statistics stats = rtabmap_->getStatistics();
stats.setPoses(poses);
stats.setConstraints(links);
rtabmapEvents_.push_back(stats);
rtabmap_->setOptimizedPoses(poses);
}
}
}
void RTABMapApp::setNodesFiltering(bool enabled)
{
nodesFiltering_ = enabled;
setGraphOptimization(graphOptimization_); // this will resend the graph if paused
} }
void RTABMapApp::setGraphVisible(bool visible) void RTABMapApp::setGraphVisible(bool visible)
{ {
@@ -621,12 +655,54 @@ void RTABMapApp::setAutoExposure(bool enabled)
autoExposure_ = enabled; autoExposure_ = enabled;
if(camera_) if(camera_)
{ {
camera_->join(true);
camera_->close();
camera_->setAutoExposure(autoExposure_); camera_->setAutoExposure(autoExposure_);
onResume();
} }
resetMapping(); }
}
void RTABMapApp::setFullResolution(bool enabled)
{
if(fullResolution_ != enabled)
{
fullResolution_ = enabled;
if(camera_)
{
camera_->setDecimation(fullResolution_?1:2);
}
rtabmap::ParametersMap parameters;
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kMemImagePreDecimation(), std::string(fullResolution_?"2":"1")));
this->post(new rtabmap::ParamEvent(parameters));
}
}
void RTABMapApp::setMaxCloudDepth(float value)
{
maxCloudDepth_ = value;
}
void RTABMapApp::setMeshAngleTolerance(float value)
{
meshAngleToleranceDeg_ = value;
}
void RTABMapApp::setMeshTriangleSize(int value)
{
meshTrianglePix_ = value;
}
int RTABMapApp::setMappingParameter(const std::string & key, const std::string & value)
{
if(rtabmap::Parameters::getDefaultParameters().find(key) != rtabmap::Parameters::getDefaultParameters().end())
{
LOGI(uFormat("Setting param \"%s\" to \"\"", key.c_str(), value.c_str()).c_str());
uInsert(mappingParameters_, rtabmap::ParametersPair(key, value));
UEventsManager::post(new rtabmap::ParamEvent(mappingParameters_));
return 0;
}
else
{
LOGE(uFormat("Key \"%s\" doesn't exist!", key.c_str()).c_str());
return -1;
} }
} }
@@ -651,54 +727,160 @@ bool RTABMapApp::exportMesh(const std::string & filePath)
bool success = false; bool success = false;
//Assemble the meshes //Assemble the meshes
UINFO("Organized fast mesh... "); if(UFile::getExtension(filePath).compare("obj") == 0)
{
pcl::TextureMesh textureMesh;
std::vector<cv::Mat> textures;
int totalPolygons = 0;
pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr mergedClouds(new pcl::PointCloud<pcl::PointXYZRGBNormal>); pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr mergedClouds(new pcl::PointCloud<pcl::PointXYZRGBNormal>);
{
boost::mutex::scoped_lock lock(meshesMutex_);
textureMesh.tex_materials.resize(createdMeshes_.size());
textureMesh.tex_polygons.resize(createdMeshes_.size());
textureMesh.tex_coordinates.resize(createdMeshes_.size());
textures.resize(createdMeshes_.size());
int polygonsStep = 0;
int oi = 0;
for(std::map<int, Mesh>::iterator iter=createdMeshes_.begin();
iter!= createdMeshes_.end();
++iter)
{
UASSERT(!iter->second.cloud->is_dense);
if(!iter->second.texture.empty() &&
iter->second.cloud->size() &&
iter->second.polygons.size())
{
// OBJ format requires normals
pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr cloudWithNormals;
cloudWithNormals = rtabmap::util3d::computeNormals(iter->second.cloud, 20);
// create dense cloud
pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr denseCloud(new pcl::PointCloud<pcl::PointXYZRGBNormal>);
std::vector<pcl::Vertices> densePolygons;
std::map<int, int> newToOldIndices;
newToOldIndices = rtabmap::util3d::filterNotUsedVerticesFromMesh(
*cloudWithNormals,
iter->second.polygons,
*denseCloud,
densePolygons);
// polygons
UASSERT(densePolygons.size());
unsigned int polygonSize = densePolygons.front().vertices.size();
textureMesh.tex_polygons[oi].resize(densePolygons.size());
textureMesh.tex_coordinates[oi].resize(densePolygons.size() * polygonSize);
for(unsigned int j=0; j<densePolygons.size(); ++j)
{
pcl::Vertices vertices = densePolygons[j];
UASSERT(polygonSize == vertices.vertices.size());
for(unsigned int k=0; k<vertices.vertices.size(); ++k)
{
//uv
std::map<int, int>::iterator jter = newToOldIndices.find(vertices.vertices[k]);
textureMesh.tex_coordinates[oi][j*vertices.vertices.size()+k] = Eigen::Vector2f(
float(jter->second % iter->second.cloud->width) / float(iter->second.cloud->width), // u
float(iter->second.cloud->height - jter->second / iter->second.cloud->width) / float(iter->second.cloud->height)); // v
vertices.vertices[k] += polygonsStep;
}
textureMesh.tex_polygons[oi][j] = vertices;
}
totalPolygons += densePolygons.size();
polygonsStep += denseCloud->size();
pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr transformedCloud = rtabmap::util3d::transformPointCloud(denseCloud, iter->second.pose);
if(mergedClouds->size() == 0)
{
*mergedClouds = *transformedCloud;
}
else
{
*mergedClouds += *transformedCloud;
}
textures[oi] = iter->second.texture;
textureMesh.tex_materials[oi].tex_illum = 1;
textureMesh.tex_materials[oi].tex_name = uFormat("material_%d", iter->first);
++oi;
}
else
{
UERROR("Texture not set for mesh %d", iter->first);
}
}
textureMesh.tex_materials.resize(oi);
textureMesh.tex_polygons.resize(oi);
textures.resize(oi);
if(textures.size())
{
pcl::toPCLPointCloud2(*mergedClouds, textureMesh.cloud);
std::string textureDirectory = uSplit(filePath, '.').front();
UINFO("Saving %d textures to %s.", textures.size(), textureDirectory.c_str());
UDirectory::makeDir(textureDirectory);
for(unsigned int i=0;i<textures.size(); ++i)
{
cv::Mat rawImage = rtabmap::uncompressImage(textures[i]);
std::string texFile = textureDirectory+"/"+textureMesh.tex_materials[i].tex_name+".png";
cv::imwrite(texFile, rawImage);
UINFO("Saved %s (%d bytes).", texFile.c_str(), rawImage.total()*rawImage.channels());
// relative path
textureMesh.tex_materials[i].tex_file = uSplit(UFile::getName(filePath), '.').front()+"/"+textureMesh.tex_materials[i].tex_name+".png";
}
UINFO("Saving obj (%d vertices, %d polygons) to %s.", (int)mergedClouds->size(), totalPolygons, filePath.c_str());
success = pcl::io::saveOBJFile(filePath, textureMesh) == 0;
if(success)
{
UINFO("Saved obj to %s!", filePath.c_str());
}
else
{
UERROR("Failed saving obj to %s!", filePath.c_str());
}
}
}
}
else
{
pcl::PointCloud<pcl::PointXYZRGB>::Ptr mergedClouds(new pcl::PointCloud<pcl::PointXYZRGB>);
std::vector<pcl::Vertices> mergedPolygons; std::vector<pcl::Vertices> mergedPolygons;
{ {
boost::mutex::scoped_lock lock(meshesMutex_); boost::mutex::scoped_lock lock(meshesMutex_);
for(std::map<int, std::pair<std::pair<pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr, std::vector<pcl::Vertices> >, rtabmap::Transform> >::iterator iter=createdMeshes_.begin(); for(std::map<int, Mesh>::iterator iter=createdMeshes_.begin();
iter!= createdMeshes_.end(); iter!= createdMeshes_.end();
++iter) ++iter)
{ {
pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr transformedCloud = rtabmap::util3d::transformPointCloud(iter->second.first.first, iter->second.second); pcl::PointCloud<pcl::PointXYZRGB>::Ptr denseCloud(new pcl::PointCloud<pcl::PointXYZRGB>);
std::vector<pcl::Vertices> densePolygons;
rtabmap::util3d::filterNotUsedVerticesFromMesh(
*iter->second.cloud,
iter->second.polygons,
*denseCloud,
densePolygons);
pcl::PointCloud<pcl::PointXYZRGB>::Ptr transformedCloud = rtabmap::util3d::transformPointCloud(denseCloud, iter->second.pose);
if(mergedClouds->size() == 0) if(mergedClouds->size() == 0)
{ {
*mergedClouds = *transformedCloud; *mergedClouds = *transformedCloud;
mergedPolygons = iter->second.first.second; mergedPolygons = densePolygons;
} }
else else
{ {
rtabmap::util3d::appendMesh(*mergedClouds, mergedPolygons, *transformedCloud, iter->second.first.second); rtabmap::util3d::appendMesh(*mergedClouds, mergedPolygons, *transformedCloud, densePolygons);
} }
} }
} }
if(closeVerticesDistance)
{
UINFO("Filtering assembled mesh (points=%d, polygons=%d, close vertices=%fm)...",
(int)mergedClouds->size(), (int)mergedPolygons.size(), closeVerticesDistance);
mergedPolygons = rtabmap::util3d::filterCloseVerticesFromMesh(
mergedClouds,
mergedPolygons,
closeVerticesDistance,
M_PI/4,
true);
// filter invalid polygons
unsigned int count = mergedPolygons.size();
mergedPolygons = rtabmap::util3d::filterInvalidPolygons(mergedPolygons);
UINFO("Filtered %d invalid polygons.", (int)count-mergedPolygons.size());
// filter not used vertices
pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr filteredCloud(new pcl::PointCloud<pcl::PointXYZRGBNormal>);
std::vector<pcl::Vertices> filteredPolygons;
rtabmap::util3d::filterNotUsedVerticesFromMesh(*mergedClouds, mergedPolygons, *filteredCloud, filteredPolygons);
mergedClouds = filteredCloud;
mergedPolygons = filteredPolygons;
}
if(mergedClouds->size() && mergedPolygons.size()) if(mergedClouds->size() && mergedPolygons.size())
{ {
@@ -706,12 +888,85 @@ bool RTABMapApp::exportMesh(const std::string & filePath)
pcl::toPCLPointCloud2(*mergedClouds, mesh.cloud); pcl::toPCLPointCloud2(*mergedClouds, mesh.cloud);
mesh.polygons = mergedPolygons; mesh.polygons = mergedPolygons;
UINFO("Saving to %s.", filePath.c_str()); UINFO("Saving ply (%d vertices, %d polygons) to %s.", (int)mergedClouds->size(), (int)mergedPolygons.size(), filePath.c_str());
success = pcl::io::savePLYFileBinary(filePath, mesh) == 0; success = pcl::io::savePLYFileBinary(filePath, mesh) == 0;
if(success)
{
UINFO("Saved ply to %s!", filePath.c_str());
}
else
{
UERROR("Failed saving ply to %s!", filePath.c_str());
}
}
} }
return success; return success;
} }
int RTABMapApp::postProcessing(int approach)
{
int returnedValue = 0;
if(rtabmap_)
{
std::map<int, rtabmap::Transform> poses;
std::multimap<int, rtabmap::Link> links;
if(approach == 2 || approach == 0)
{
if(approach == 2)
{
// detect more loop closures
returnedValue = rtabmap_->detectMoreLoopClosures();
}
if(returnedValue >= 0)
{
// simple graph optmimization
rtabmap_->getGraph(poses, links, true, true);
}
}
else if (approach == 1)
{
if(rtabmap::Optimizer::isAvailable(rtabmap::Optimizer::kTypeG2O))
{
std::map<int, rtabmap::Signature> signatures;
rtabmap_->getGraph(poses, links, false, true, &signatures);
rtabmap::ParametersMap param;
param.insert(rtabmap::ParametersPair(rtabmap::Parameters::kOptimizerIterations(), "30"));
param.insert(rtabmap::ParametersPair(rtabmap::Parameters::kOptimizerEpsilon(), "0"));
rtabmap::Optimizer * sba = rtabmap::Optimizer::create(rtabmap::Optimizer::kTypeG2O, param);
poses = sba->optimizeBA(poses.rbegin()->first, poses, links, signatures);
delete sba;
}
else
{
LOGE("g2o not available!");
}
}
else
{
LOGE("Invalid approach %d (should be 0 (graph optimization), 1 (sba) or 2 (detect more loop closures))", approach);
returnedValue = -1;
}
if(poses.size())
{
boost::mutex::scoped_lock lock(rtabmapMutex_);
rtabmap::Statistics stats = rtabmap_->getStatistics();
stats.setPoses(poses);
stats.setConstraints(links);
rtabmapEvents_.push_back(stats);
rtabmap_->setOptimizedPoses(poses);
}
else
{
returnedValue = -1;
}
}
return returnedValue;
}
void RTABMapApp::handleEvent(UEvent * event) void RTABMapApp::handleEvent(UEvent * event)
{ {
if(camera_ && camera_->isRunning()) if(camera_ && camera_->isRunning())
@@ -719,7 +974,7 @@ void RTABMapApp::handleEvent(UEvent * event)
// called from events manager thread, so protect the data // called from events manager thread, so protect the data
if(event->getClassName().compare("OdometryEvent") == 0) if(event->getClassName().compare("OdometryEvent") == 0)
{ {
LOGI("GUI: Received OdometryEvent!"); LOGI("Received OdometryEvent!");
if(odomMutex_.try_lock()) if(odomMutex_.try_lock())
{ {
odomEvents_.clear(); odomEvents_.clear();
@@ -733,67 +988,11 @@ void RTABMapApp::handleEvent(UEvent * event)
if(status_.first == rtabmap::RtabmapEventInit::kInitialized && if(status_.first == rtabmap::RtabmapEventInit::kInitialized &&
event->getClassName().compare("RtabmapEvent") == 0) event->getClassName().compare("RtabmapEvent") == 0)
{ {
LOGI("GUI: Received RtabmapEvent!"); LOGI("Received RtabmapEvent!");
int nodes =0;
int words = 0;
int loopClosureId = 0;
float updateTime = 0.0f;
int databaseMemoryUsed = 0;
int inliers = 0;
int featuresExtracted = 0;
float hypothesis = 0.0f;
{
boost::mutex::scoped_lock lock(rtabmapMutex_);
if(camera_->isRunning()) if(camera_->isRunning())
{ {
boost::mutex::scoped_lock lock(rtabmapMutex_);
rtabmapEvents_.push_back(((rtabmap::RtabmapEvent*)event)->getStats()); rtabmapEvents_.push_back(((rtabmap::RtabmapEvent*)event)->getStats());
nodes = (int)uValue(rtabmapEvents_.back().data(), rtabmap::Statistics::kMemoryWorking_memory_size(), 0.0f) +
uValue(rtabmapEvents_.back().data(), rtabmap::Statistics::kMemoryShort_time_memory_size(), 0.0f);
words = (int)uValue(rtabmapEvents_.back().data(), rtabmap::Statistics::kKeypointDictionary_size(), 0.0f);
updateTime = uValue(rtabmapEvents_.back().data(), rtabmap::Statistics::kTimingTotal(), 0.0f);
loopClosureId = rtabmapEvents_.back().loopClosureId()>0?rtabmapEvents_.back().loopClosureId():rtabmapEvents_.back().localLoopClosureId()>0?rtabmapEvents_.back().localLoopClosureId():0;
databaseMemoryUsed = (int)uValue(rtabmapEvents_.back().data(), rtabmap::Statistics::kMemoryDatabase_memory_used(), 0.0f);
inliers = (int)uValue(rtabmapEvents_.back().data(), rtabmap::Statistics::kLoopVisual_inliers(), 0.0f);
featuresExtracted = rtabmapEvents_.back().getSignatures().size()?rtabmapEvents_.back().getSignatures().rbegin()->second.getWords().size():0;
hypothesis = uValue(rtabmapEvents_.back().data(), rtabmap::Statistics::kLoopHighest_hypothesis_value(), 0.0f);
}
}
// Call JAVA callback with some stats
bool success = false;
if(jvm && RTABMapActivity)
{
JNIEnv *env = 0;
jint rs = jvm->AttachCurrentThread(&env, NULL);
if(rs == JNI_OK && env)
{
jclass clazz = env->GetObjectClass(RTABMapActivity);
if(clazz)
{
jmethodID methodID = env->GetMethodID(clazz, "updateStatsCallback", "(IIIIFIIIIFI)V" );
if(methodID)
{
env->CallVoidMethod(RTABMapActivity, methodID,
nodes,
words,
totalPoints_,
totalPolygons_,
updateTime,
loopClosureId,
databaseMemoryUsed,
inliers,
featuresExtracted,
hypothesis,
lastDrawnCloudsCount_);
success = true;
}
}
}
jvm->DetachCurrentThread();
}
if(!success)
{
UERROR("Failed to call RTABMapActivity::updateStatsCallback");
} }
} }
} }
@@ -844,7 +1043,7 @@ void RTABMapApp::handleEvent(UEvent * event)
if(event->getClassName().compare("RtabmapEventInit") == 0) if(event->getClassName().compare("RtabmapEventInit") == 0)
{ {
LOGI("GUI: Received RtabmapEventInit!"); LOGI("Received RtabmapEventInit!");
status_.first = ((rtabmap::RtabmapEventInit*)event)->getStatus(); status_.first = ((rtabmap::RtabmapEventInit*)event)->getStatus();
status_.second = ((rtabmap::RtabmapEventInit*)event)->getInfo(); status_.second = ((rtabmap::RtabmapEventInit*)event)->getInfo();
@@ -881,5 +1080,63 @@ void RTABMapApp::handleEvent(UEvent * event)
UERROR("Failed to call RTABMapActivity::rtabmapInitEventsCallback"); UERROR("Failed to call RTABMapActivity::rtabmapInitEventsCallback");
} }
} }
if(event->getClassName().compare("PostRenderEvent") == 0)
{
LOGI("Received PostRenderEvent!");
const rtabmap::Statistics & stats = ((PostRenderEvent*)event)->getStats();
int nodes = (int)uValue(stats.data(), rtabmap::Statistics::kMemoryWorking_memory_size(), 0.0f) +
uValue(stats.data(), rtabmap::Statistics::kMemoryShort_time_memory_size(), 0.0f);
int words = (int)uValue(stats.data(), rtabmap::Statistics::kKeypointDictionary_size(), 0.0f);
float updateTime = uValue(stats.data(), rtabmap::Statistics::kTimingTotal(), 0.0f);
int loopClosureId = stats.loopClosureId()>0?stats.loopClosureId():stats.proximityDetectionId()>0?stats.proximityDetectionId():0;
int highestHypId = (int)uValue(stats.data(), rtabmap::Statistics::kLoopHighest_hypothesis_id(), 0.0f);
int databaseMemoryUsed = (int)uValue(stats.data(), rtabmap::Statistics::kMemoryDatabase_memory_used(), 0.0f);
int inliers = (int)uValue(stats.data(), rtabmap::Statistics::kLoopVisual_inliers(), 0.0f);
int rejected = (int)uValue(stats.data(), rtabmap::Statistics::kLoopRejectedHypothesis(), 0.0f);
int featuresExtracted = stats.getSignatures().size()?stats.getSignatures().rbegin()->second.getWords().size():0;
float hypothesis = uValue(stats.data(), rtabmap::Statistics::kLoopHighest_hypothesis_value(), 0.0f);
// Call JAVA callback with some stats
UINFO("Send statistics to GUI");
bool success = false;
if(jvm && RTABMapActivity)
{
JNIEnv *env = 0;
jint rs = jvm->AttachCurrentThread(&env, NULL);
if(rs == JNI_OK && env)
{
jclass clazz = env->GetObjectClass(RTABMapActivity);
if(clazz)
{
jmethodID methodID = env->GetMethodID(clazz, "updateStatsCallback", "(IIIIFIIIIIFIFI)V" );
if(methodID)
{
env->CallVoidMethod(RTABMapActivity, methodID,
nodes,
words,
totalPoints_,
totalPolygons_,
updateTime,
loopClosureId,
highestHypId,
databaseMemoryUsed,
inliers,
featuresExtracted,
hypothesis,
lastDrawnCloudsCount_,
renderingFPS_,
rejected);
success = true;
}
}
}
jvm->DetachCurrentThread();
}
if(!success)
{
UERROR("Failed to call RTABMapActivity::updateStatsCallback");
}
}
} }
+28 -9
View File
@@ -50,14 +50,11 @@ class RTABMapApp : public UEventsHandler {
RTABMapApp(); RTABMapApp();
~RTABMapApp(); ~RTABMapApp();
// Initialize the Tango Service, this function starts the communication void onCreate(JNIEnv* env, jobject caller_activity);
// 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 openDatabase(const std::string & databasePath); void openDatabase(const std::string & databasePath);
int onResume(); bool onTangoServiceConnected(JNIEnv* env, jobject iBinder);
// Explicitly reset motion tracking and restart the pipeline. // Explicitly reset motion tracking and restart the pipeline.
// Note that this will cause motion tracking to re-initialize. // Note that this will cause motion tracking to re-initialize.
@@ -119,12 +116,19 @@ class RTABMapApp : public UEventsHandler {
void setLocalizationMode(bool enabled); void setLocalizationMode(bool enabled);
void setTrajectoryMode(bool enabled); void setTrajectoryMode(bool enabled);
void setGraphOptimization(bool enabled); void setGraphOptimization(bool enabled);
void setNodesFiltering(bool enabled);
void setGraphVisible(bool visible); void setGraphVisible(bool visible);
void setAutoExposure(bool enabled); void setAutoExposure(bool enabled);
void setFullResolution(bool enabled);
void setMaxCloudDepth(float value);
void setMeshAngleTolerance(float value);
void setMeshTriangleSize(int value);
int setMappingParameter(const std::string & key, const std::string & value);
void resetMapping(); void resetMapping();
void save(); void save();
bool exportMesh(const std::string & filePath); bool exportMesh(const std::string & filePath);
int postProcessing(int approach);
protected: protected:
virtual void handleEvent(UEvent * event); virtual void handleEvent(UEvent * event);
@@ -135,20 +139,28 @@ class RTABMapApp : public UEventsHandler {
private: private:
rtabmap::CameraTango * camera_; rtabmap::CameraTango * camera_;
rtabmap::RtabmapThread * rtabmapThread_; rtabmap::RtabmapThread * rtabmapThread_;
rtabmap::Rtabmap * rtabmap_;
LogHandler * logHandler_; LogHandler * logHandler_;
bool mapCloudShown_;
bool odomCloudShown_; bool odomCloudShown_;
bool loopClosureDetection_;
bool graphOptimization_; bool graphOptimization_;
bool nodesFiltering_;
bool localizationMode_; bool localizationMode_;
bool trajectoryMode_; bool trajectoryMode_;
bool autoExposure_; bool autoExposure_;
bool fullResolution_;
float maxCloudDepth_;
int meshTrianglePix_;
float meshAngleToleranceDeg_;
rtabmap::ParametersMap mappingParameters_;
bool clearSceneOnNextRender_; bool clearSceneOnNextRender_;
int totalPoints_; int totalPoints_;
int totalPolygons_; int totalPolygons_;
int lastDrawnCloudsCount_; int lastDrawnCloudsCount_;
float renderingFPS_;
// main_scene_ includes all drawable object for visualizing Tango device's // main_scene_ includes all drawable object for visualizing Tango device's
// movement and point cloud. // movement and point cloud.
@@ -163,9 +175,16 @@ class RTABMapApp : public UEventsHandler {
boost::mutex odomMutex_; boost::mutex odomMutex_;
boost::mutex poseMutex_; boost::mutex poseMutex_;
std::map<int, std::pair<std::pair<pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr, std::vector<pcl::Vertices> >, rtabmap::Transform > > createdMeshes_; struct Mesh
{
pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud;
std::vector<pcl::Vertices> polygons;
rtabmap::Transform pose;
cv::Mat texture;
};
std::map<int, Mesh> createdMeshes_;
std::map<int, rtabmap::Transform> rawPoses_; std::map<int, rtabmap::Transform> rawPoses_;
std::pair<int, std::pair<pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr, pcl::IndicesPtr> > previousCloud_;
std::pair<rtabmap::RtabmapEventInit::Status, std::string> status_; std::pair<rtabmap::RtabmapEventInit::Status, std::string> status_;
}; };
+55 -7
View File
@@ -48,11 +48,11 @@ void GetJStringContent(JNIEnv *AEnv, jstring AStr, std::string &ARes) {
AEnv->ReleaseStringUTFChars(AStr,s); AEnv->ReleaseStringUTFChars(AStr,s);
} }
JNIEXPORT jint JNICALL JNIEXPORT void JNICALL
Java_com_introlab_rtabmap_RTABMapLib_initialize( Java_com_introlab_rtabmap_RTABMapLib_onCreate(
JNIEnv* env, jobject, jobject activity) JNIEnv* env, jobject, jobject activity)
{ {
return app.TangoInitialize(env, activity); return app.onCreate(env, activity);
} }
JNIEXPORT void JNICALL JNIEXPORT void JNICALL
@@ -64,10 +64,10 @@ Java_com_introlab_rtabmap_RTABMapLib_openDatabase(
return app.openDatabase(databasePathC); return app.openDatabase(databasePathC);
} }
JNIEXPORT jint JNICALL JNIEXPORT bool JNICALL
Java_com_introlab_rtabmap_RTABMapLib_onResume( Java_com_introlab_rtabmap_RTABMapLib_onTangoServiceConnected(
JNIEnv*, jobject) { JNIEnv* env, jobject, jobject iBinder) {
return app.onResume(); return app.onTangoServiceConnected(env, iBinder);
} }
JNIEXPORT void JNICALL JNIEXPORT void JNICALL
@@ -156,6 +156,12 @@ Java_com_introlab_rtabmap_RTABMapLib_setGraphOptimization(
return app.setGraphOptimization(enabled); return app.setGraphOptimization(enabled);
} }
JNIEXPORT void JNICALL JNIEXPORT void JNICALL
Java_com_introlab_rtabmap_RTABMapLib_setNodesFiltering(
JNIEnv*, jobject, bool enabled)
{
return app.setNodesFiltering(enabled);
}
JNIEXPORT void JNICALL
Java_com_introlab_rtabmap_RTABMapLib_setGraphVisible( Java_com_introlab_rtabmap_RTABMapLib_setGraphVisible(
JNIEnv*, jobject, bool visible) JNIEnv*, jobject, bool visible)
{ {
@@ -167,6 +173,39 @@ Java_com_introlab_rtabmap_RTABMapLib_setAutoExposure(
{ {
return app.setAutoExposure(enabled); return app.setAutoExposure(enabled);
} }
JNIEXPORT void JNICALL
Java_com_introlab_rtabmap_RTABMapLib_setFullResolution(
JNIEnv*, jobject, bool enabled)
{
return app.setFullResolution(enabled);
}
JNIEXPORT void JNICALL
Java_com_introlab_rtabmap_RTABMapLib_setMaxCloudDepth(
JNIEnv*, jobject, float value)
{
return app.setMaxCloudDepth(value);
}
JNIEXPORT void JNICALL
Java_com_introlab_rtabmap_RTABMapLib_setMeshAngleTolerance(
JNIEnv*, jobject, float value)
{
return app.setMeshAngleTolerance(value);
}
JNIEXPORT void JNICALL
Java_com_introlab_rtabmap_RTABMapLib_setMeshTriangleSize(
JNIEnv*, jobject, int value)
{
return app.setMeshTriangleSize(value);
}
JNIEXPORT jint JNICALL
Java_com_introlab_rtabmap_RTABMapLib_setMappingParameter(
JNIEnv* env, jobject, jstring key, jstring value)
{
std::string keyC, valueC;
GetJStringContent(env,key,keyC);
GetJStringContent(env,value,valueC);
return app.setMappingParameter(keyC, valueC);
}
JNIEXPORT void JNICALL JNIEXPORT void JNICALL
Java_com_introlab_rtabmap_RTABMapLib_resetMapping( Java_com_introlab_rtabmap_RTABMapLib_resetMapping(
@@ -191,6 +230,15 @@ Java_com_introlab_rtabmap_RTABMapLib_exportMesh(
return app.exportMesh(filePathC); return app.exportMesh(filePathC);
} }
JNIEXPORT int JNICALL
Java_com_introlab_rtabmap_RTABMapLib_postProcessing(
JNIEnv* env, jobject, int approach)
{
return app.postProcessing(approach);
}
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
+156 -98
View File
@@ -1,104 +1,98 @@
/* /*
* Copyright 2014 Google Inc. All Rights Reserved. Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
* 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. Redistribution and use in source and binary forms, with or without
* You may obtain a copy of the License at modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* http://www.apache.org/licenses/LICENSE-2.0 notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* Unless required by applicable law or agreed to in writing, software notice, this list of conditions and the following disclaimer in the
* distributed under the License is distributed on an "AS IS" BASIS, documentation and/or other materials provided with the distribution.
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * Neither the name of the Universite de Sherbrooke nor the
* See the License for the specific language governing permissions and names of its contributors may be used to endorse or promote products
* limitations under the License. derived from this software without specific prior written permission.
*/
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sstream> #include <sstream>
#include "point_cloud_drawable.h" #include "point_cloud_drawable.h"
#include "rtabmap/utilite/ULogger.h" #include "rtabmap/utilite/ULogger.h"
#include "rtabmap/utilite/UConversion.h"
#include <opencv2/imgproc/imgproc.hpp>
#include "util.h" #include "util.h"
#include <GLES2/gl2.h> #include <GLES2/gl2.h>
PointCloudDrawable::PointCloudDrawable( PointCloudDrawable::PointCloudDrawable(
GLuint shaderProgram, GLuint cloudShaderProgram,
const pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr & cloud, GLuint textureShaderProgram,
const std::vector<pcl::Vertices> & indices) :
vertex_buffers_(0),
nPoints_(0),
pose_(1.0f),
visible_(true),
shader_program_(shaderProgram)
{
UASSERT(!cloud->empty());
glGenBuffers(1, &vertex_buffers_);
if(vertex_buffers_)
{
LOGI("Creating cloud buffer %d", vertex_buffers_);
std::vector<float> vertices = std::vector<float>(cloud->size()*4);
for(unsigned int i=0; i<cloud->size(); ++i)
{
vertices[i*4] = cloud->at(i).x;
vertices[i*4+1] = cloud->at(i).y;
vertices[i*4+2] = cloud->at(i).z;
vertices[i*4+3] = cloud->at(i).rgb;
}
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffers_);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * (int)vertices.size(), (const void *)vertices.data(), GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
GLint error = glGetError();
if(error != GL_NO_ERROR)
{
LOGI("OpenGL: Could not allocate point cloud (0x%x)\n", error);
vertex_buffers_ = 0;
}
else
{
nPoints_ = cloud->size();
if(indices.size())
{
int polygonSize = indices[0].vertices.size();
UASSERT(polygonSize == 3);
indices_.resize(indices.size() * polygonSize);
int oi = 0;
for(unsigned int i=0; i<indices.size(); ++i)
{
UASSERT((int)indices[i].vertices.size() == polygonSize);
for(int j=0; j<polygonSize; ++j)
{
indices_[oi++] = (unsigned short)indices[i].vertices[j];
}
}
}
}
}
}
PointCloudDrawable::PointCloudDrawable(
GLuint shaderProgram,
const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloud, const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloud,
const std::vector<pcl::Vertices> & indices) : const std::vector<pcl::Vertices> & polygons,
const cv::Mat & image) :
vertex_buffers_(0), vertex_buffers_(0),
textures_(0),
nPoints_(0), nPoints_(0),
pose_(1.0f), pose_(1.0f),
visible_(true), visible_(true),
shader_program_(shaderProgram) cloud_shader_program_(cloudShaderProgram),
texture_shader_program_(textureShaderProgram)
{ {
UASSERT(!cloud->empty()); UASSERT(!cloud->empty());
glGenBuffers(1, &vertex_buffers_); glGenBuffers(1, &vertex_buffers_);
if(!vertex_buffers_)
if(vertex_buffers_)
{ {
LOGE("OpenGL: could not generate vertex buffers\n");
return;
}
if(!cloud->is_dense && !image.empty())
{
LOGI("cloud=%dx%d image=%dx%d\n", (int)cloud->width, (int)cloud->height, image.cols, image.rows);
UASSERT(polygons.size() && !cloud->is_dense && !image.empty() && image.type() == CV_8UC3);
glGenTextures(1, &textures_);
if(!textures_)
{
vertex_buffers_ = 0;
LOGE("OpenGL: could not generate vertex buffers\n");
return;
}
}
LOGI("Creating cloud buffer %d", vertex_buffers_); LOGI("Creating cloud buffer %d", vertex_buffers_);
std::vector<float> vertices = std::vector<float>(cloud->size()*4); std::vector<float> vertices;
if(textures_)
{
vertices = std::vector<float>(cloud->size()*6);
for(unsigned int i=0; i<cloud->size(); ++i)
{
vertices[i*6] = cloud->at(i).x;
vertices[i*6+1] = cloud->at(i).y;
vertices[i*6+2] = cloud->at(i).z;
// rgb
vertices[i*6+3] = cloud->at(i).rgb;
// texture uv
vertices[i*6+4] = float(i % cloud->width)/float(cloud->width); //u
vertices[i*6+5] = float(i/cloud->width)/float(cloud->height); //v
}
}
else
{
vertices = std::vector<float>(cloud->size()*4);
for(unsigned int i=0; i<cloud->size(); ++i) for(unsigned int i=0; i<cloud->size(); ++i)
{ {
vertices[i*4] = cloud->at(i).x; vertices[i*4] = cloud->at(i).x;
@@ -106,6 +100,7 @@ PointCloudDrawable::PointCloudDrawable(
vertices[i*4+2] = cloud->at(i).z; vertices[i*4+2] = cloud->at(i).z;
vertices[i*4+3] = cloud->at(i).rgb; vertices[i*4+3] = cloud->at(i).rgb;
} }
}
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffers_); glBindBuffer(GL_ARRAY_BUFFER, vertex_buffers_);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * (int)vertices.size(), (const void *)vertices.data(), GL_STATIC_DRAW); glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * (int)vertices.size(), (const void *)vertices.data(), GL_STATIC_DRAW);
@@ -114,27 +109,47 @@ PointCloudDrawable::PointCloudDrawable(
GLint error = glGetError(); GLint error = glGetError();
if(error != GL_NO_ERROR) if(error != GL_NO_ERROR)
{ {
LOGI("OpenGL: Could not allocate point cloud (0x%x)\n", error); LOGE("OpenGL: Could not allocate point cloud (0x%x)\n", error);
vertex_buffers_ = 0; vertex_buffers_ = 0;
return;
} }
else
if(textures_)
{ {
// gen texture from image
glBindTexture(GL_TEXTURE_2D, textures_);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
cv::Mat rgbImage;
cv::cvtColor(image, rgbImage, CV_BGR2RGB);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, rgbImage.cols, rgbImage.rows, 0, GL_RGB, GL_UNSIGNED_BYTE, rgbImage.data);
GLint error = glGetError();
if(error != GL_NO_ERROR)
{
LOGE("OpenGL: Could not allocate texture (0x%x)\n", error);
textures_ = 0;
glDeleteBuffers(1, &vertex_buffers_);
vertex_buffers_ = 0;
return;
}
}
nPoints_ = cloud->size(); nPoints_ = cloud->size();
if(indices.size()) if(polygons.size())
{ {
int polygonSize = indices[0].vertices.size(); int polygonSize = polygons[0].vertices.size();
UASSERT(polygonSize == 3); UASSERT(polygonSize == 3);
indices_.resize(indices.size() * polygonSize); polygons_.resize(polygons.size() * polygonSize);
int oi = 0; int oi = 0;
for(unsigned int i=0; i<indices.size(); ++i) for(unsigned int i=0; i<polygons.size(); ++i)
{ {
UASSERT((int)indices[i].vertices.size() == polygonSize); UASSERT((int)polygons[i].vertices.size() == polygonSize);
for(int j=0; j<polygonSize; ++j) for(int j=0; j<polygonSize; ++j)
{ {
indices_[oi++] = (unsigned short)indices[i].vertices[j]; polygons_[oi++] = (unsigned short)polygons[i].vertices[j];
}
}
} }
} }
} }
@@ -149,6 +164,13 @@ PointCloudDrawable::~PointCloudDrawable()
tango_gl::util::CheckGlError("PointCloudDrawable::~PointCloudDrawable()"); tango_gl::util::CheckGlError("PointCloudDrawable::~PointCloudDrawable()");
vertex_buffers_ = 0; vertex_buffers_ = 0;
} }
if (textures_)
{
glDeleteTextures(1, &textures_);
tango_gl::util::CheckGlError("PointCloudDrawable::~PointCloudDrawable()");
textures_ = 0;
}
} }
void PointCloudDrawable::setPose(const rtabmap::Transform & pose) void PointCloudDrawable::setPose(const rtabmap::Transform & pose)
@@ -162,33 +184,69 @@ void PointCloudDrawable::Render(const glm::mat4 & projectionMatrix, const glm::m
if(vertex_buffers_ && nPoints_ && visible_) if(vertex_buffers_ && nPoints_ && visible_)
{ {
glUseProgram(shader_program_); if(meshRendering && textures_)
{
glUseProgram(texture_shader_program_);
GLuint mvp_handle_ = glGetUniformLocation(shader_program_, "mvp"); GLuint mvp_handle_ = glGetUniformLocation(texture_shader_program_, "mvp");
glm::mat4 mvp_mat = projectionMatrix * viewMatrix * pose_; glm::mat4 mvp_mat = projectionMatrix * viewMatrix * pose_;
glUniformMatrix4fv(mvp_handle_, 1, GL_FALSE, glm::value_ptr(mvp_mat)); glUniformMatrix4fv(mvp_handle_, 1, GL_FALSE, glm::value_ptr(mvp_mat));
GLuint point_size_handle_ = glGetUniformLocation(shader_program_, "point_size"); // Texture activate unit 0
glActiveTexture(GL_TEXTURE0);
// Bind the texture to this unit.
glBindTexture(GL_TEXTURE_2D, textures_);
// Tell the texture uniform sampler to use this texture in the shader by binding to texture unit 0.
GLuint texture_handle = glGetUniformLocation(texture_shader_program_, "u_Texture");
glUniform1i(texture_handle, 0);
GLint attribute_vertex = glGetAttribLocation(texture_shader_program_, "vertex");
GLint attribute_texture = glGetAttribLocation(texture_shader_program_, "a_TexCoordinate");
glEnableVertexAttribArray(attribute_vertex);
glEnableVertexAttribArray(attribute_texture);
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffers_);
glVertexAttribPointer(attribute_vertex, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), 0);
glVertexAttribPointer(attribute_texture, 2, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), (GLvoid*) (4 * sizeof(GLfloat)));
glDrawElements(GL_TRIANGLES, polygons_.size(), GL_UNSIGNED_SHORT, polygons_.data());
}
else // point cloud or colored mesh
{
glUseProgram(cloud_shader_program_);
GLuint mvp_handle_ = glGetUniformLocation(cloud_shader_program_, "mvp");
glm::mat4 mvp_mat = projectionMatrix * viewMatrix * pose_;
glUniformMatrix4fv(mvp_handle_, 1, GL_FALSE, glm::value_ptr(mvp_mat));
GLuint point_size_handle_ = glGetUniformLocation(cloud_shader_program_, "point_size");
glUniform1f(point_size_handle_, pointSize); glUniform1f(point_size_handle_, pointSize);
GLint attribute_vertex = glGetAttribLocation(shader_program_, "vertex"); GLint attribute_vertex = glGetAttribLocation(cloud_shader_program_, "vertex");
GLint attribute_color = glGetAttribLocation(shader_program_, "color"); GLint attribute_color = glGetAttribLocation(cloud_shader_program_, "color");
glEnableVertexAttribArray(attribute_vertex); glEnableVertexAttribArray(attribute_vertex);
glEnableVertexAttribArray(attribute_color); glEnableVertexAttribArray(attribute_color);
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffers_); glBindBuffer(GL_ARRAY_BUFFER, vertex_buffers_);
if(textures_)
{
glVertexAttribPointer(attribute_vertex, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), 0);
glVertexAttribPointer(attribute_color, 3, GL_UNSIGNED_BYTE, GL_TRUE, 6*sizeof(GLfloat), (GLvoid*) (3 * sizeof(GLfloat)));
}
else
{
glVertexAttribPointer(attribute_vertex, 3, GL_FLOAT, GL_FALSE, 4*sizeof(GLfloat), 0); glVertexAttribPointer(attribute_vertex, 3, GL_FLOAT, GL_FALSE, 4*sizeof(GLfloat), 0);
glVertexAttribPointer(attribute_color, 3, GL_UNSIGNED_BYTE, GL_TRUE, 4*sizeof(GLfloat), (GLvoid*) (3 * sizeof(GLfloat))); glVertexAttribPointer(attribute_color, 3, GL_UNSIGNED_BYTE, GL_TRUE, 4*sizeof(GLfloat), (GLvoid*) (3 * sizeof(GLfloat)));
}
if(meshRendering && indices_.size()) if(meshRendering && polygons_.size())
{ {
glDrawElements(GL_TRIANGLES, indices_.size(), GL_UNSIGNED_SHORT, indices_.data()); glDrawElements(GL_TRIANGLES, polygons_.size(), GL_UNSIGNED_SHORT, polygons_.data());
} }
else else
{ {
glDrawArrays(GL_POINTS, 0, nPoints_); glDrawArrays(GL_POINTS, 0, nPoints_);
} }
}
glDisableVertexAttribArray(0); glDisableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ARRAY_BUFFER, 0);
+33 -22
View File
@@ -1,18 +1,29 @@
/* /*
* Copyright 2014 Google Inc. All Rights Reserved. Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
* 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. Redistribution and use in source and binary forms, with or without
* You may obtain a copy of the License at modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* http://www.apache.org/licenses/LICENSE-2.0 notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* Unless required by applicable law or agreed to in writing, software notice, this list of conditions and the following disclaimer in the
* distributed under the License is distributed on an "AS IS" BASIS, documentation and/or other materials provided with the distribution.
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * Neither the name of the Universite de Sherbrooke nor the
* See the License for the specific language governing permissions and names of its contributors may be used to endorse or promote products
* limitations under the License. derived from this software without specific prior written permission.
*/
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef TANGO_POINT_CLOUD_POINT_CLOUD_DRAWABLE_H_ #ifndef TANGO_POINT_CLOUD_POINT_CLOUD_DRAWABLE_H_
#define TANGO_POINT_CLOUD_POINT_CLOUD_DRAWABLE_H_ #define TANGO_POINT_CLOUD_POINT_CLOUD_DRAWABLE_H_
@@ -31,13 +42,11 @@
class PointCloudDrawable { class PointCloudDrawable {
public: public:
PointCloudDrawable( PointCloudDrawable(
GLuint shaderProgram, GLuint cloudShaderProgram,
const pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr & cloud, GLuint textureShaderProgram,
const std::vector<pcl::Vertices> & indices = std::vector<pcl::Vertices>());
PointCloudDrawable(
GLuint shaderProgram,
const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloud, const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloud,
const std::vector<pcl::Vertices> & indices = std::vector<pcl::Vertices>()); const std::vector<pcl::Vertices> & polygons = std::vector<pcl::Vertices>(),
const cv::Mat & image = cv::Mat());
virtual ~PointCloudDrawable(); virtual ~PointCloudDrawable();
void setPose(const rtabmap::Transform & pose); void setPose(const rtabmap::Transform & pose);
@@ -56,12 +65,14 @@ class PointCloudDrawable {
private: private:
// Vertex buffer of the point cloud geometry. // Vertex buffer of the point cloud geometry.
GLuint vertex_buffers_; GLuint vertex_buffers_;
std::vector<GLushort> indices_; GLuint textures_;
std::vector<GLushort> polygons_;
int nPoints_; int nPoints_;
glm::mat4 pose_; glm::mat4 pose_;
bool visible_; bool visible_;
GLuint shader_program_; GLuint cloud_shader_program_;
GLuint texture_shader_program_;
}; };
#endif // TANGO_POINT_CLOUD_POINT_CLOUD_DRAWABLE_H_ #endif // TANGO_POINT_CLOUD_POINT_CLOUD_DRAWABLE_H_
+45 -25
View File
@@ -60,6 +60,26 @@ const std::string kPointCloudFragmentShader =
" gl_FragColor = vec4(v_color.z, v_color.y, v_color.x, 1.0);\n" " gl_FragColor = vec4(v_color.z, v_color.y, v_color.x, 1.0);\n"
"}\n"; "}\n";
const std::string kTextureMeshVertexShader =
"precision mediump float;\n"
"precision mediump int;\n"
"attribute vec3 vertex;\n"
"attribute vec2 a_TexCoordinate;\n"
"uniform mat4 mvp;\n"
"varying vec2 v_TexCoordinate;\n"
"void main() {\n"
" gl_Position = mvp*vec4(vertex.x, vertex.y, vertex.z, 1.0);\n"
" v_TexCoordinate = a_TexCoordinate;\n"
"}\n";
const std::string kTextureMeshFragmentShader =
"precision mediump float;\n"
"precision mediump int;\n"
"uniform sampler2D u_Texture;\n"
"varying vec2 v_TexCoordinate;\n"
"void main() {\n"
" gl_FragColor = texture2D(u_Texture, v_TexCoordinate);\n"
"}\n";
const std::string kGraphVertexShader = const std::string kGraphVertexShader =
"precision mediump float;\n" "precision mediump float;\n"
"precision mediump int;\n" "precision mediump int;\n"
@@ -92,7 +112,9 @@ Scene::Scene() :
traceVisible_(true), traceVisible_(true),
currentPose_(0), currentPose_(0),
cloud_shader_program_(0), cloud_shader_program_(0),
texture_mesh_shader_program_(0),
graph_shader_program_(0), graph_shader_program_(0),
mapRendering_(true),
meshRendering_(true), meshRendering_(true),
pointSize_(3.0f) {} pointSize_(3.0f) {}
@@ -130,6 +152,11 @@ void Scene::InitGLContent()
cloud_shader_program_ = tango_gl::util::CreateProgram(kPointCloudVertexShader.c_str(), kPointCloudFragmentShader.c_str()); cloud_shader_program_ = tango_gl::util::CreateProgram(kPointCloudVertexShader.c_str(), kPointCloudFragmentShader.c_str());
UASSERT(cloud_shader_program_ != 0); UASSERT(cloud_shader_program_ != 0);
} }
if(texture_mesh_shader_program_ == 0)
{
texture_mesh_shader_program_ = tango_gl::util::CreateProgram(kTextureMeshVertexShader.c_str(), kTextureMeshFragmentShader.c_str());
UASSERT(texture_mesh_shader_program_ != 0);
}
if(graph_shader_program_ == 0) if(graph_shader_program_ == 0)
{ {
graph_shader_program_ = tango_gl::util::CreateProgram(kGraphVertexShader.c_str(), kGraphFragmentShader.c_str()); graph_shader_program_ = tango_gl::util::CreateProgram(kGraphVertexShader.c_str(), kGraphFragmentShader.c_str());
@@ -156,6 +183,10 @@ void Scene::DeleteResources() {
glDeleteShader(cloud_shader_program_); glDeleteShader(cloud_shader_program_);
cloud_shader_program_ = 0; cloud_shader_program_ = 0;
} }
if (texture_mesh_shader_program_) {
glDeleteShader(texture_mesh_shader_program_);
texture_mesh_shader_program_ = 0;
}
if (graph_shader_program_) { if (graph_shader_program_) {
glDeleteShader(graph_shader_program_); glDeleteShader(graph_shader_program_);
graph_shader_program_ = 0; graph_shader_program_ = 0;
@@ -250,7 +281,7 @@ int Scene::Render() {
bool frustumCulling = true; bool frustumCulling = true;
int cloudDrawn=0; int cloudDrawn=0;
if(frustumCulling) if(mapRendering_ && frustumCulling)
{ {
//Use camera frustum to cull nodes that don't need to be drawn //Use camera frustum to cull nodes that don't need to be drawn
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>); pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
@@ -303,11 +334,14 @@ int Scene::Render() {
else else
{ {
for(std::map<int, PointCloudDrawable*>::const_iterator iter=pointClouds_.begin(); iter!=pointClouds_.end(); ++iter) for(std::map<int, PointCloudDrawable*>::const_iterator iter=pointClouds_.begin(); iter!=pointClouds_.end(); ++iter)
{
if((mapRendering_ || iter->first < 0) && iter->second->isVisible())
{ {
++cloudDrawn; ++cloudDrawn;
iter->second->Render(gesture_camera_->GetProjectionMatrix(), gesture_camera_->GetViewMatrix(), meshRendering_, pointSize_); iter->second->Render(gesture_camera_->GetProjectionMatrix(), gesture_camera_->GetViewMatrix(), meshRendering_, pointSize_);
} }
} }
}
if(graphVisible_ && graph_) if(graphVisible_ && graph_)
{ {
@@ -372,31 +406,12 @@ void Scene::setTraceVisible(bool visible)
} }
//Should only be called in OpenGL thread! //Should only be called in OpenGL thread!
void Scene::addOrUpdateCloud( void Scene::addCloud(
int id,
const pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr & cloud,
const std::vector<pcl::Vertices> & polygons,
const rtabmap::Transform & pose)
{
LOGI("addOrUpdateCloud cloud %d", id);
std::map<int, PointCloudDrawable*>::iterator iter=pointClouds_.find(id);
if(iter != pointClouds_.end())
{
delete iter->second;
pointClouds_.erase(iter);
}
//create
UASSERT(cloud_shader_program_ != 0);
PointCloudDrawable * drawable = new PointCloudDrawable(cloud_shader_program_, cloud, polygons);
drawable->setPose(pose);
pointClouds_.insert(std::make_pair(id, drawable));
}
void Scene::addOrUpdateCloud(
int id, int id,
const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloud, const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloud,
const std::vector<pcl::Vertices> & polygons, const std::vector<pcl::Vertices> & polygons,
const rtabmap::Transform & pose) const rtabmap::Transform & pose,
const cv::Mat & image)
{ {
LOGI("addOrUpdateCloud cloud %d", id); LOGI("addOrUpdateCloud cloud %d", id);
std::map<int, PointCloudDrawable*>::iterator iter=pointClouds_.find(id); std::map<int, PointCloudDrawable*>::iterator iter=pointClouds_.find(id);
@@ -407,8 +422,13 @@ void Scene::addOrUpdateCloud(
} }
//create //create
UASSERT(cloud_shader_program_ != 0); UASSERT(cloud_shader_program_ != 0 && texture_mesh_shader_program_!=0);
PointCloudDrawable * drawable = new PointCloudDrawable(cloud_shader_program_, cloud, polygons); PointCloudDrawable * drawable = new PointCloudDrawable(
cloud_shader_program_,
texture_mesh_shader_program_,
cloud,
polygons,
image);
drawable->setPose(pose); drawable->setPose(pose);
pointClouds_.insert(std::make_pair(id, drawable)); pointClouds_.insert(std::make_pair(id, drawable));
} }
+6 -7
View File
@@ -96,22 +96,19 @@ class Scene {
void setGraphVisible(bool visible); void setGraphVisible(bool visible);
void setTraceVisible(bool visible); void setTraceVisible(bool visible);
void addOrUpdateCloud( void addCloud(
int id,
const pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr & cloud,
const std::vector<pcl::Vertices> & polygons,
const rtabmap::Transform & pose);
void addOrUpdateCloud(
int id, int id,
const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloud, const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloud,
const std::vector<pcl::Vertices> & polygons, const std::vector<pcl::Vertices> & polygons,
const rtabmap::Transform & pose); const rtabmap::Transform & pose,
const cv::Mat & image = cv::Mat());
void setCloudPose(int id, const rtabmap::Transform & pose); void setCloudPose(int id, const rtabmap::Transform & pose);
void setCloudVisible(int id, bool visible); void setCloudVisible(int id, bool visible);
bool hasCloud(int id) const; bool hasCloud(int id) const;
std::set<int> getAddedClouds() const; std::set<int> getAddedClouds() const;
void setMapRendering(bool enabled) {mapRendering_ = enabled;}
void setMeshRendering(bool enabled) {meshRendering_ = enabled;} void setMeshRendering(bool enabled) {meshRendering_ = enabled;}
void setPointSize(float size) {pointSize_ = size;} void setPointSize(float size) {pointSize_ = size;}
@@ -140,8 +137,10 @@ class Scene {
// Shader to display point cloud. // Shader to display point cloud.
GLuint cloud_shader_program_; GLuint cloud_shader_program_;
GLuint texture_mesh_shader_program_;
GLuint graph_shader_program_; GLuint graph_shader_program_;
bool mapRendering_;
bool meshRendering_; bool meshRendering_;
float pointSize_; float pointSize_;
}; };
@@ -219,6 +219,21 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" /> android:layout_height="wrap_content" />
</LinearLayout> </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> </LinearLayout>
+56 -19
View File
@@ -6,26 +6,63 @@
</group> </group>
<group android:id="@+id/group_actions"> <group android:id="@+id/group_actions">
<item android:id="@+id/open" android:title="Open"/> <item android:id="@+id/post_processing" android:title="Post-Processing...">
<item android:id="@+id/save" android:title="Save"/> <menu>
<item android:id="@+id/export" android:title="Export (*.ply)"/> <group android:id="@+id/group_post_processing">
<item android:id="@+id/reset" android:title="Reset"/> <item android:id="@+id/detect_more_loop_closures" android:title="Detect More Loop Closures" />
<item android:id="@+id/about" android:title="About"/> <item android:id="@+id/global_graph_optimization" android:title="Global Graph Optimization" />
</group> <item android:id="@+id/sba" android:title="Bundle Adjustement" />
<item android:id="@+id/menu_settings" android:title="Options..." android:orderInCategory="2">
<menu >
<group android:id="@+id/group_visibility" android:checkableBehavior="all">
<item android:id="@+id/debug" android:checked="false" android:title="Debug" />
<item android:id="@+id/localization_mode" android:checked="false" android:title="Localization Mode" />
<item android:id="@+id/trajectory_mode" android:checked="false" android:title="Trajectory Mode" />
<item android:id="@+id/mesh_rendering" android:checked="true" android:title="Mesh Rendering" />
<item android:id="@+id/auto_exposure" android:checked="false" android:title="Auto Exposure" />
<item android:id="@+id/map_shown" android:checked="true" android:title="Map Visible" />
<item android:id="@+id/odom_shown" android:checked="true" android:title="Odom Visible" />
<item android:id="@+id/graph_visible" android:checked="true" android:title="Graph Visible" />
<item android:id="@+id/graph_optimization" android:checked="true" android:title="Optimized Graph" />
</group> </group>
</menu> </menu>
</item> </item>
<item android:id="@+id/open" android:title="Open"/>
<item android:id="@+id/save" android:title="Save"/>
<item android:id="@+id/export" android:title="Export...">
<menu>
<group android:id="@+id/group_export">
<item android:id="@+id/export_ply" android:title="Mesh (.ply)" />
<item android:id="@+id/export_obj" android:title="Mesh with texture (*.obj)" />
</group>
</menu>
</item>
<item android:id="@+id/reset" android:title="Reset"/>
<item android:id="@+id/menu_rendering_settings" android:title="Rendering Options...">
<menu >
<group android:id="@+id/group_rendering_visibility" android:checkableBehavior="all">
<item android:id="@+id/debug" android:checked="false" android:title="Debug" />
<item android:id="@+id/mesh_rendering" android:checked="true" android:title="Mesh Rendering" />
<item android:id="@+id/map_shown" android:checked="true" android:title="Map Visible" />
<item android:id="@+id/odom_shown" android:checked="true" android:title="Odom Visible" />
<item android:id="@+id/graph_visible" android:checked="true" android:title="Graph Visible" />
<item android:id="@+id/auto_exposure" android:checked="false" android:title="Auto Exposure" />
<item android:id="@+id/max_depth" android:checkable="false" android:title="Cloud/Mesh Max Depth..." />
<item android:id="@+id/mesh_angle_tolerance" android:checkable="false" android:title="Mesh Angle Tolerance..." />
<item android:id="@+id/mesh_triangle_size" android:checkable="false" android:title="Mesh Triangle Size..." />
</group>
</menu>
</item>
<item android:id="@+id/menu_mapping_settings" android:title="Mapping Options...">
<menu >
<group android:id="@+id/group_mapping_visibility" android:checkableBehavior="all">
<item android:id="@+id/localization_mode" android:checked="false" android:title="Localization Mode" />
<item android:id="@+id/trajectory_mode" android:checked="false" android:title="Trajectory Mode" />
<item android:id="@+id/graph_optimization" android:checked="true" android:title="Optimized Graph" />
<item android:id="@+id/nodes_filtering" android:checked="false" android:title="Nodes Filtering" />
<item android:id="@+id/resolution" android:checked="false" android:title="720p Mode" />
<item android:id="@+id/menu_param_settings" android:checkable="false" android:title="Parameters...">
<menu >
<item android:id="@+id/update_rate" android:title="Map Update Rate..." />
<item android:id="@+id/time_threshold" android:title="Time Threshold..." />
<item android:id="@+id/loop_threshold" android:title="Loop Closure Threshold..." />
<item android:id="@+id/optimize_error" android:title="Max Optimization Error..." />
<item android:id="@+id/features" android:title="Max Features Extracted..." />
</menu>
</item>
</group>
</menu>
</item>
<item android:id="@+id/about" android:title="About"/>
</group>
</menu> </menu>
+2 -1
View File
@@ -9,7 +9,7 @@
<string name="third_person">Third</string> <string name="third_person">Third</string>
<string name="top_down">Top</string> <string name="top_down">Top</string>
<string name="start">Start</string> <string name="start">Start</string>
<string name="nodes">"Nodes: "</string> <string name="nodes">"Nodes (WM): "</string>
<string name="points">"Number of points: "</string> <string name="points">"Number of points: "</string>
<string name="update_time">"Update time (ms): "</string> <string name="update_time">"Update time (ms): "</string>
<string name="loop_closure">"Loop closure ID: "</string> <string name="loop_closure">"Loop closure ID: "</string>
@@ -20,5 +20,6 @@
<string name="polygons">"Polygons: "</string> <string name="polygons">"Polygons: "</string>
<string name="memory">"Memory (MB): "</string> <string name="memory">"Memory (MB): "</string>
<string name="hypothesis">"Hypothesis: "</string> <string name="hypothesis">"Hypothesis: "</string>
<string name="fps">"FPS (rendering): "</string>
</resources> </resources>
@@ -9,8 +9,10 @@ import android.app.Notification;
import android.app.NotificationManager; import android.app.NotificationManager;
import android.app.PendingIntent; import android.app.PendingIntent;
import android.app.ProgressDialog; import android.app.ProgressDialog;
import android.content.ComponentName;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.PackageInfo; import android.content.pm.PackageInfo;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.PackageManager.NameNotFoundException;
@@ -20,6 +22,7 @@ import android.os.Bundle;
import android.os.Environment; import android.os.Environment;
import android.os.Handler; import android.os.Handler;
import android.os.Debug; import android.os.Debug;
import android.os.IBinder;
import android.text.Editable; import android.text.Editable;
import android.text.InputType; import android.text.InputType;
import android.util.Log; import android.util.Log;
@@ -30,6 +33,7 @@ import android.view.MenuInflater;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.View; import android.view.View;
import android.view.View.OnClickListener; import android.view.View.OnClickListener;
import android.view.WindowManager;
import android.widget.EditText; import android.widget.EditText;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.TextView; import android.widget.TextView;
@@ -66,6 +70,7 @@ public class RTABMapActivity extends Activity implements OnClickListener {
private MenuItem mItemPause; private MenuItem mItemPause;
private MenuItem mItemSave; private MenuItem mItemSave;
private MenuItem mItemOpen; private MenuItem mItemOpen;
private MenuItem mItemPostProcessing;
private MenuItem mItemExport; private MenuItem mItemExport;
private MenuItem mItemLocalizationMode; private MenuItem mItemLocalizationMode;
private MenuItem mItemTrajectoryMode; private MenuItem mItemTrajectoryMode;
@@ -75,10 +80,46 @@ public class RTABMapActivity extends Activity implements OnClickListener {
private String mNewDatabasePath = ""; private String mNewDatabasePath = "";
private String mWorkingDirectory = ""; private String mWorkingDirectory = "";
private int mMaxDepthIndex = 5;
private int mMeshAngleToleranceIndex = 1;
private int mMeshTriangleSizeIndex = 0;
private int mParamUpdateRateHzIndex = 1;
private int mParamTimeThrMsIndex = 4;
private int mParamMaxFeaturesIndex = 4;
private int mParamLoopThrMsIndex = 1;
private int mParamOptimizeErrorIndex = 3;
final String[] mUpdateRateValues = {"0.5", "1", "2", "Max"};
final String[] mTimeThrValues = {"400", "500", "600", "700", "800", "900", "1000", "1100", "1200", "1300", "1400", "1500", "No Limit"};
final String[] mMaxFeaturesValues = {"Disabled", "100", "200", "300", "400", "500", "600", "700", "800", "900", "1000", "No Limit"};
final String[] mLoopThrValues = {"Disabled", "0.11", "0.20", "0.30", "0.40", "0.50", "0.60", "0.70", "0.80", "0.90"};
final String[] mOptimizeErrorValues = {"Disabled", "0.01", "0.025", "0.05", "0.1", "0.2", "0.35", "0.5", "1"};
private LinearLayout mLayoutDebug; private LinearLayout mLayoutDebug;
private int mTotalLoopClosures = 0; private int mTotalLoopClosures = 0;
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 @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
@@ -89,6 +130,8 @@ public class RTABMapActivity extends Activity implements OnClickListener {
Display display = getWindowManager().getDefaultDisplay(); Display display = getWindowManager().getDefaultDisplay();
display.getSize(mScreenSize); display.getSize(mScreenSize);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
// Setting content view of this activity. // Setting content view of this activity.
setContentView(R.layout.activity_rtabmap); setContentView(R.layout.activity_rtabmap);
@@ -97,6 +140,8 @@ public class RTABMapActivity extends Activity implements OnClickListener {
findViewById(R.id.third_person_button).setOnClickListener(this); findViewById(R.id.third_person_button).setOnClickListener(this);
findViewById(R.id.top_down_button).setOnClickListener(this); findViewById(R.id.top_down_button).setOnClickListener(this);
mToast = Toast.makeText(getApplicationContext(), "", Toast.LENGTH_SHORT);
// OpenGL view where all of the graphics are drawn. // OpenGL view where all of the graphics are drawn.
mGLView = (GLSurfaceView) findViewById(R.id.gl_surface_view); mGLView = (GLSurfaceView) findViewById(R.id.gl_surface_view);
@@ -115,7 +160,7 @@ public class RTABMapActivity extends Activity implements OnClickListener {
// Check if the Tango Core is out dated. // Check if the Tango Core is out dated.
if (!CheckTangoCoreVersion(MIN_TANGO_CORE_VERSION)) { if (!CheckTangoCoreVersion(MIN_TANGO_CORE_VERSION)) {
Toast.makeText(this, "Tango Core out dated, please update in Play Store", Toast.LENGTH_LONG).show(); mToast.makeText(this, "Tango Core out dated, please update in Play Store", mToast.LENGTH_LONG).show();
finish(); finish();
return; return;
} }
@@ -143,12 +188,12 @@ public class RTABMapActivity extends Activity implements OnClickListener {
else else
{ {
// show warning that data cannot be saved! // show warning that data cannot be saved!
Toast.makeText(getApplicationContext(), mToast.makeText(getApplicationContext(),
String.format("Failed to get external storage path (SD-CARD, state=%s). Saving disabled.", String.format("Failed to get external storage path (SD-CARD, state=%s). Saving disabled.",
Environment.getExternalStorageState()), Toast.LENGTH_LONG).show(); Environment.getExternalStorageState()), mToast.LENGTH_LONG).show();
} }
RTABMapLib.initialize(this); RTABMapLib.onCreate(this);
RTABMapLib.openDatabase(mTempDatabasePath); RTABMapLib.openDatabase(mTempDatabasePath);
} }
@@ -158,8 +203,8 @@ public class RTABMapActivity extends Activity implements OnClickListener {
if (requestCode == Tango.TANGO_INTENT_ACTIVITYCODE) { if (requestCode == Tango.TANGO_INTENT_ACTIVITYCODE) {
// Make sure the request was successful // Make sure the request was successful
if (resultCode == RESULT_CANCELED) { if (resultCode == RESULT_CANCELED) {
Toast.makeText(this, "Motion Tracking Permissions Required!", mToast.makeText(this, "Motion Tracking Permissions Required!",
Toast.LENGTH_SHORT).show(); mToast.LENGTH_SHORT).show();
finish(); finish();
} }
} }
@@ -169,6 +214,8 @@ public class RTABMapActivity extends Activity implements OnClickListener {
protected void onResume() { protected void onResume() {
super.onResume(); super.onResume();
TangoInitializationHelper.bindTangoService(this, mTangoServiceConnection);
Log.i(TAG, String.format("onResume()")); Log.i(TAG, String.format("onResume()"));
if (Tango.hasPermission(this, Tango.PERMISSIONTYPE_MOTION_TRACKING)) { if (Tango.hasPermission(this, Tango.PERMISSIONTYPE_MOTION_TRACKING)) {
@@ -182,12 +229,7 @@ public class RTABMapActivity extends Activity implements OnClickListener {
mItemPause.setChecked(false); mItemPause.setChecked(false);
mItemSave.setEnabled(false); mItemSave.setEnabled(false);
mItemExport.setEnabled(false); mItemExport.setEnabled(false);
} mItemPostProcessing.setEnabled(false);
if(RTABMapLib.onResume()!=0)
{
Toast.makeText(getApplicationContext(),
String.format("Failed to connect with Tango!"), Toast.LENGTH_SHORT).show();
} }
} else { } else {
@@ -207,6 +249,8 @@ public class RTABMapActivity extends Activity implements OnClickListener {
RTABMapLib.onPause(); RTABMapLib.onPause();
mOpenedDatabasePath = ""; mOpenedDatabasePath = "";
RTABMapLib.openDatabase(mTempDatabasePath); RTABMapLib.openDatabase(mTempDatabasePath);
unbindService(mTangoServiceConnection);
} }
@Override @Override
@@ -268,12 +312,14 @@ public class RTABMapActivity extends Activity implements OnClickListener {
mItemPause = menu.findItem(R.id.pause); mItemPause = menu.findItem(R.id.pause);
mItemSave = menu.findItem(R.id.save); mItemSave = menu.findItem(R.id.save);
mItemOpen = menu.findItem(R.id.open); mItemOpen = menu.findItem(R.id.open);
mItemPostProcessing = menu.findItem(R.id.post_processing);
mItemExport = menu.findItem(R.id.export); mItemExport = menu.findItem(R.id.export);
mItemLocalizationMode = menu.findItem(R.id.localization_mode); mItemLocalizationMode = menu.findItem(R.id.localization_mode);
mItemTrajectoryMode = menu.findItem(R.id.trajectory_mode); mItemTrajectoryMode = menu.findItem(R.id.trajectory_mode);
mItemSave.setEnabled(false); mItemSave.setEnabled(false);
mItemExport.setEnabled(false); mItemExport.setEnabled(false);
mItemOpen.setEnabled(false); mItemOpen.setEnabled(false);
mItemPostProcessing.setEnabled(false);
return true; return true;
} }
@@ -285,15 +331,18 @@ public class RTABMapActivity extends Activity implements OnClickListener {
int polygons, int polygons,
float updateTime, float updateTime,
int loopClosureId, int loopClosureId,
int highestHypId,
int databaseMemoryUsed, int databaseMemoryUsed,
int inliers, int inliers,
int featuresExtracted, int featuresExtracted,
float hypothesis, float hypothesis,
int nodesDrawn) int nodesDrawn,
float fps,
int rejected)
{ {
if(mItemPause!=null) if(mItemPause!=null)
{ {
((TextView)findViewById(R.id.status)).setText(mItemPause.isChecked()?"Paused":mItemLocalizationMode.isChecked()?"Localization":"Mapping"); ((TextView)findViewById(R.id.status)).setText(mItemPause.isChecked()?"Paused":mItemLocalizationMode.isChecked()?String.format("Localization (%s Hz)", mUpdateRateValues[mParamUpdateRateHzIndex]):String.format("Mapping (%s Hz)", mUpdateRateValues[mParamUpdateRateHzIndex]));
} }
((TextView)findViewById(R.id.points)).setText(String.valueOf(points)); ((TextView)findViewById(R.id.points)).setText(String.valueOf(points));
@@ -303,15 +352,26 @@ public class RTABMapActivity extends Activity implements OnClickListener {
((TextView)findViewById(R.id.memory)).setText(String.valueOf(Debug.getNativeHeapAllocatedSize()/(1024*1024))); ((TextView)findViewById(R.id.memory)).setText(String.valueOf(Debug.getNativeHeapAllocatedSize()/(1024*1024)));
((TextView)findViewById(R.id.db_size)).setText(String.valueOf(databaseMemoryUsed)); ((TextView)findViewById(R.id.db_size)).setText(String.valueOf(databaseMemoryUsed));
((TextView)findViewById(R.id.inliers)).setText(String.valueOf(inliers)); ((TextView)findViewById(R.id.inliers)).setText(String.valueOf(inliers));
((TextView)findViewById(R.id.features)).setText(String.valueOf(featuresExtracted)); ((TextView)findViewById(R.id.features)).setText(String.format("%d / %s", featuresExtracted, mMaxFeaturesValues[mParamMaxFeaturesIndex]));
((TextView)findViewById(R.id.update_time)).setText(String.format("%.3f", updateTime)); ((TextView)findViewById(R.id.update_time)).setText(String.format("%.3f / %s", updateTime, mTimeThrValues[mParamTimeThrMsIndex]));
((TextView)findViewById(R.id.hypothesis)).setText(String.format("%.3f (%d)", hypothesis, loopClosureId)); ((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) if(loopClosureId > 0)
{ {
++mTotalLoopClosures; ++mTotalLoopClosures;
((TextView)findViewById(R.id.total_loop)).setText(String.valueOf(mTotalLoopClosures));
Toast.makeText(this, "Loop closure detected!", Toast.LENGTH_SHORT).show(); mToast.setText("Loop closure detected!");
mToast.show();
} }
else if(rejected > 0 && inliers >= 15)
{
mToast.setText("Loop closure rejected after graph optimization.");
mToast.show();
}
}
((TextView)findViewById(R.id.total_loop)).setText(String.valueOf(mTotalLoopClosures));
} }
// called from jni // called from jni
@@ -322,17 +382,20 @@ public class RTABMapActivity extends Activity implements OnClickListener {
final int polygons, final int polygons,
final float updateTime, final float updateTime,
final int loopClosureId, final int loopClosureId,
final int highestHypId,
final int databaseMemoryUsed, final int databaseMemoryUsed,
final int inliers, final int inliers,
final int features, final int features,
final float hypothesis, final float hypothesis,
final int nodesDrawn) final int nodesDrawn,
final float fps,
final int rejected)
{ {
Log.i(TAG, String.format("updateStatsCallback()")); Log.i(TAG, String.format("updateStatsCallback()"));
runOnUiThread(new Runnable() { runOnUiThread(new Runnable() {
public void run() { public void run() {
updateStatsUI(nodes, words, points, polygons, updateTime, loopClosureId, databaseMemoryUsed, inliers, features, hypothesis, nodesDrawn); updateStatsUI(nodes, words, points, polygons, updateTime, loopClosureId, highestHypId, databaseMemoryUsed, inliers, features, hypothesis, nodesDrawn, fps, rejected);
} }
}); });
} }
@@ -409,7 +472,7 @@ public class RTABMapActivity extends Activity implements OnClickListener {
if(!msg.isEmpty()) if(!msg.isEmpty())
{ {
Toast.makeText(this, msg, Toast.LENGTH_LONG).show(); mToast.makeText(this, msg, mToast.LENGTH_LONG).show();
} }
mOpenedDatabasePath = ""; mOpenedDatabasePath = "";
@@ -428,6 +491,7 @@ public class RTABMapActivity extends Activity implements OnClickListener {
((TextView)findViewById(R.id.features)).setText(String.valueOf(0)); ((TextView)findViewById(R.id.features)).setText(String.valueOf(0));
((TextView)findViewById(R.id.update_time)).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.hypothesis)).setText(String.valueOf(0));
((TextView)findViewById(R.id.fps)).setText(String.valueOf(0));
mTotalLoopClosures = 0; mTotalLoopClosures = 0;
((TextView)findViewById(R.id.total_loop)).setText(String.valueOf(mTotalLoopClosures)); ((TextView)findViewById(R.id.total_loop)).setText(String.valueOf(mTotalLoopClosures));
@@ -437,6 +501,7 @@ public class RTABMapActivity extends Activity implements OnClickListener {
{ {
mItemPause.setChecked(false); mItemPause.setChecked(false);
mItemOpen.setEnabled(false); mItemOpen.setEnabled(false);
mItemPostProcessing.setEnabled(false);
mItemSave.setEnabled(false); mItemSave.setEnabled(false);
mItemExport.setEnabled(false); mItemExport.setEnabled(false);
RTABMapLib.setPausedMapping(false); // resume mapping RTABMapLib.setPausedMapping(false); // resume mapping
@@ -476,25 +541,35 @@ public class RTABMapActivity extends Activity implements OnClickListener {
* "AreaDescriptionSaveProgress:X" - ADF saving is X * 100 percent complete. * "AreaDescriptionSaveProgress:X" - ADF saving is X * 100 percent complete.
* "Unknown" * "Unknown"
*/ */
String str = null;
if(key.equals("TangoServiceException")) if(key.equals("TangoServiceException"))
Toast.makeText(this, String.format("Tango service exception: %s", value), Toast.LENGTH_SHORT).show(); str = String.format("Tango service exception: %s", value);
else if(key.equals("FisheyeOverExposed")) else if(key.equals("FisheyeOverExposed"))
;//Toast.makeText(this, String.format("The fisheye image is over exposed with average pixel value %s px.", value), Toast.LENGTH_SHORT).show(); ;//str = String.format("The fisheye image is over exposed with average pixel value %s px.", value);
else if(key.equals("FisheyeUnderExposed")) else if(key.equals("FisheyeUnderExposed"))
;//Toast.makeText(this, String.format("The fisheye image is under exposed with average pixel value %s px.", value), Toast.LENGTH_SHORT).show(); ;//str = String.format("The fisheye image is under exposed with average pixel value %s px.", value);
else if(key.equals("ColorOverExposed")) else if(key.equals("ColorOverExposed"))
;//Toast.makeText(this, String.format("The color image is over exposed with average pixel value %s px.", value), Toast.LENGTH_SHORT).show(); ;//str = String.format("The color image is over exposed with average pixel value %s px.", value);
else if(key.equals("ColorUnderExposed")) else if(key.equals("ColorUnderExposed"))
;//Toast.makeText(this, String.format("The color image is under exposed with average pixel value %s px.", value), Toast.LENGTH_SHORT).show(); ;//str = String.format("The color image is under exposed with average pixel value %s px.", value);
else if(key.equals("CameraTango")) else if(key.equals("CameraTango"))
Toast.makeText(this, value, Toast.LENGTH_SHORT).show(); str = value;
else if(key.equals("TooFewFeaturesTracked")) else if(key.equals("TooFewFeaturesTracked"))
{ {
if(!value.equals("0")) if(!value.equals("0"))
Toast.makeText(this, String.format("Too few features (%s) were tracked in the fisheye image. This may result in poor odometry!", value), Toast.LENGTH_SHORT).show(); {
str = String.format("Too few features (%s) were tracked in the fisheye image. This may result in poor odometry!", value);
}
} }
else else
Toast.makeText(this, String.format("Unknown Tango event detected!? (type=%d)", type), Toast.LENGTH_SHORT).show(); {
str = String.format("Unknown Tango event detected!? (type=%d)", type);
}
if(str!=null)
{
mToast.setText(str);
mToast.show();
}
} }
//called from jni //called from jni
@@ -503,14 +578,15 @@ public class RTABMapActivity extends Activity implements OnClickListener {
final String key, final String key,
final String value) final String value)
{ {
Log.i(TAG, String.format("tangoEventCallback()")); if(mItemPause != null && !mItemPause.isChecked())
{
runOnUiThread(new Runnable() { runOnUiThread(new Runnable() {
public void run() { public void run() {
tangoEventUI(type, key, value); tangoEventUI(type, key, value);
} }
}); });
} }
}
private boolean CheckTangoCoreVersion(int minVersion) { private boolean CheckTangoCoreVersion(int minVersion) {
int versionNumber = 0; int versionNumber = 0;
@@ -542,7 +618,7 @@ public class RTABMapActivity extends Activity implements OnClickListener {
@Override @Override
public boolean accept(File dir, String filename) { public boolean accept(File dir, String filename) {
File sel = new File(dir, filename); File sel = new File(dir, filename);
return filename.endsWith(".db") || sel.isDirectory(); return filename.endsWith(".db");
} }
}; };
@@ -563,6 +639,7 @@ public class RTABMapActivity extends Activity implements OnClickListener {
mItemSave.setEnabled(item.isChecked()); mItemSave.setEnabled(item.isChecked());
mItemExport.setEnabled(item.isChecked()); mItemExport.setEnabled(item.isChecked());
mItemOpen.setEnabled(item.isChecked()); mItemOpen.setEnabled(item.isChecked());
mItemPostProcessing.setEnabled(item.isChecked());
// mItemSave.setEnabled(item.isChecked() && !mWorkingDirectory.isEmpty()); // mItemSave.setEnabled(item.isChecked() && !mWorkingDirectory.isEmpty());
if(item.isChecked()) if(item.isChecked())
{ {
@@ -575,6 +652,85 @@ public class RTABMapActivity extends Activity implements OnClickListener {
((TextView)findViewById(R.id.status)).setText(mItemLocalizationMode.isChecked()?"Localization":"Mapping"); ((TextView)findViewById(R.id.status)).setText(mItemLocalizationMode.isChecked()?"Localization":"Mapping");
} }
} }
else if (itemId == R.id.detect_more_loop_closures)
{
mProgressDialog.setTitle("Post-Processing");
mProgressDialog.setMessage(String.format("Please wait while detecting more loop closures..."));
mProgressDialog.show();
Thread workingThread = new Thread(new Runnable() {
public void run() {
final int loopDetected = RTABMapLib.postProcessing(2);
runOnUiThread(new Runnable() {
public void run() {
mProgressDialog.dismiss();
if(loopDetected >= 0)
{
mTotalLoopClosures+=loopDetected;
mToast.makeText(getActivity(), String.format("Detection done! %d new loop closure(s) added.", loopDetected), mToast.LENGTH_SHORT).show();
}
else if(loopDetected < 0)
{
mToast.makeText(getActivity(), String.format("Detection failed!"), mToast.LENGTH_SHORT).show();
}
}
});
}
});
workingThread.start();
}
else if (itemId == R.id.global_graph_optimization)
{
mProgressDialog.setTitle("Post-Processing");
mProgressDialog.setMessage(String.format("Global graph optimization..."));
mProgressDialog.show();
Thread workingThread = new Thread(new Runnable() {
public void run() {
final int value = RTABMapLib.postProcessing(0);
runOnUiThread(new Runnable() {
public void run() {
mProgressDialog.dismiss();
if(value >= 0)
{
mToast.makeText(getActivity(), String.format("Optimization done!"), mToast.LENGTH_SHORT).show();
}
else if(value < 0)
{
mToast.makeText(getActivity(), String.format("Optimization failed!"), mToast.LENGTH_SHORT).show();
}
}
});
}
});
workingThread.start();
}
else if (itemId == R.id.sba)
{
mProgressDialog.setTitle("Post-Processing");
mProgressDialog.setMessage(String.format("Bundle adjustement..."));
mProgressDialog.show();
Thread workingThread = new Thread(new Runnable() {
public void run() {
final int value = RTABMapLib.postProcessing(1);
runOnUiThread(new Runnable() {
public void run() {
mProgressDialog.dismiss();
if(value >= 0)
{
mToast.makeText(getActivity(), String.format("Optimization done!"), mToast.LENGTH_SHORT).show();
}
else if(value < 0)
{
mToast.makeText(getActivity(), String.format("Optimization failed!"), mToast.LENGTH_SHORT).show();
}
}
});
}
});
workingThread.start();
}
else if(itemId == R.id.debug) else if(itemId == R.id.debug)
{ {
item.setChecked(!item.isChecked()); item.setChecked(!item.isChecked());
@@ -617,6 +773,11 @@ public class RTABMapActivity extends Activity implements OnClickListener {
item.setChecked(!item.isChecked()); item.setChecked(!item.isChecked());
RTABMapLib.setGraphOptimization(item.isChecked()); RTABMapLib.setGraphOptimization(item.isChecked());
} }
else if(itemId == R.id.nodes_filtering)
{
item.setChecked(!item.isChecked());
RTABMapLib.setNodesFiltering(item.isChecked());
}
else if(itemId == R.id.graph_visible) else if(itemId == R.id.graph_visible)
{ {
item.setChecked(!item.isChecked()); item.setChecked(!item.isChecked());
@@ -626,6 +787,177 @@ public class RTABMapActivity extends Activity implements OnClickListener {
{ {
item.setChecked(!item.isChecked()); item.setChecked(!item.isChecked());
RTABMapLib.setAutoExposure(item.isChecked()); RTABMapLib.setAutoExposure(item.isChecked());
// restart Tango service
onPause();
onResume();
}
else if(itemId == R.id.resolution)
{
item.setChecked(!item.isChecked());
RTABMapLib.setFullResolution(item.isChecked());
}
else if(itemId == R.id.max_depth)
{
// get double
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Max Depth (m)");
final String[] values = {"1", "2", "3", "4", "5", "No Limit"};
builder.setSingleChoiceItems(values, mMaxDepthIndex, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
if(which >=0 && which < 6)
{
mMaxDepthIndex = which;
RTABMapLib.setMaxCloudDepth(which < 5?Float.parseFloat(values[which]):0);
}
}
});
builder.show();
}
else if(itemId == R.id.mesh_angle_tolerance)
{
// get double
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Mesh Angle Tolerance (deg)");
final String[] values = {"5", "10", "15", "20", "25", "30"};
builder.setSingleChoiceItems(values, mMeshAngleToleranceIndex, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
if(which >=0 && which < 6)
{
mMeshAngleToleranceIndex = which;
RTABMapLib.setMeshAngleTolerance(Float.parseFloat(values[which]));
}
}
});
builder.show();
}
else if(itemId == R.id.mesh_triangle_size)
{
// get double
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Mesh Triangle Size (pixels)");
final String[] values = {"2", "3", "4", "5", "6"};
builder.setSingleChoiceItems(values, mMeshTriangleSizeIndex, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
if(which >=0 && which < 5)
{
mMeshTriangleSizeIndex = which;
RTABMapLib.setMeshTriangleSize(Integer.parseInt(values[which]));
}
}
});
builder.show();
}
else if(itemId == R.id.update_rate)
{
// get double
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Update Rate (Hz)");
builder.setSingleChoiceItems(mUpdateRateValues, mParamUpdateRateHzIndex, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
if(which >=0 && which < mUpdateRateValues.length)
{
mParamUpdateRateHzIndex = which;
if(RTABMapLib.setMappingParameter("Rtabmap/DetectionRate", mUpdateRateValues[which]) != 0)
{
mToast.makeText(getActivity(), "Failed to set parameter \"Rtabmap/DetectionRate\"!", mToast.LENGTH_LONG).show();
}
}
}
});
builder.show();
}
else if(itemId == R.id.time_threshold)
{
// get double
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Time Threshold (ms)");
builder.setSingleChoiceItems(mTimeThrValues, mParamTimeThrMsIndex, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
if(which >=0 && which < mTimeThrValues.length)
{
mParamTimeThrMsIndex = which;
if(RTABMapLib.setMappingParameter("Rtabmap/TimeThr", which==mTimeThrValues.length-1?"0":mTimeThrValues[which]) != 0)
{
mToast.makeText(getActivity(), "Failed to set parameter \"Rtabmap/TimeThr\"!", mToast.LENGTH_LONG).show();
}
}
}
});
builder.show();
}
else if(itemId == R.id.features)
{
// get double
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Max Features");
builder.setSingleChoiceItems(mMaxFeaturesValues, mParamMaxFeaturesIndex, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
if(which >=0 && which < mMaxFeaturesValues.length)
{
mParamMaxFeaturesIndex = which;
if(RTABMapLib.setMappingParameter("Kp/MaxFeatures", which==0?"-1":which==mMaxFeaturesValues.length-1?"0":mMaxFeaturesValues[which]) != 0)
{
mToast.makeText(getActivity(),"Failed to set parameter \"Kp/MaxFeatures\"!", mToast.LENGTH_LONG).show();
}
}
}
});
builder.show();
}
else if(itemId == R.id.loop_threshold)
{
// get double
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Loop Closure Threshold");
builder.setSingleChoiceItems(mLoopThrValues, mParamLoopThrMsIndex, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
if(which >=0 && which < mLoopThrValues.length)
{
mParamLoopThrMsIndex = which;
if(RTABMapLib.setMappingParameter("Rtabmap/LoopThr", which==0?"1":mLoopThrValues[which]) != 0)
{
mToast.makeText(getActivity(), "Failed to set parameter \"Rtabmap/LoopThr\"!", mToast.LENGTH_LONG).show();
}
}
}
});
builder.show();
}
else if(itemId == R.id.optimize_error)
{
// get double
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Max Optimization Error (m)");
builder.setSingleChoiceItems(mOptimizeErrorValues, mParamOptimizeErrorIndex, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
if(which >=0 && which < mOptimizeErrorValues.length)
{
mParamOptimizeErrorIndex = which;
if(RTABMapLib.setMappingParameter("RGBD/OptimizeMaxError", which==0?"0":mOptimizeErrorValues[which]) != 0)
{
mToast.makeText(getActivity(), "Failed to set parameter \"RGBD/OptimizeMaxError\"!", mToast.LENGTH_LONG).show();
}
}
}
});
builder.show();
} }
else if (itemId == R.id.save) else if (itemId == R.id.save)
{ {
@@ -641,6 +973,7 @@ public class RTABMapActivity extends Activity implements OnClickListener {
public void onClick(DialogInterface dialog, int which) public void onClick(DialogInterface dialog, int which)
{ {
final String fileName = input.getText().toString(); final String fileName = input.getText().toString();
dialog.dismiss();
if(!fileName.isEmpty()) if(!fileName.isEmpty())
{ {
File newFile = new File(mWorkingDirectory + fileName + ".db"); File newFile = new File(mWorkingDirectory + fileName + ".db");
@@ -661,6 +994,7 @@ public class RTABMapActivity extends Activity implements OnClickListener {
//disable gui actions //disable gui actions
mItemSave.setEnabled(false); mItemSave.setEnabled(false);
mItemOpen.setEnabled(false); mItemOpen.setEnabled(false);
mItemPostProcessing.setEnabled(false);
mItemExport.setEnabled(false); mItemExport.setEnabled(false);
} }
}) })
@@ -683,6 +1017,7 @@ public class RTABMapActivity extends Activity implements OnClickListener {
//disable gui actions //disable gui actions
mItemSave.setEnabled(false); mItemSave.setEnabled(false);
mItemOpen.setEnabled(false); mItemOpen.setEnabled(false);
mItemPostProcessing.setEnabled(false);
mItemExport.setEnabled(false); mItemExport.setEnabled(false);
} }
} }
@@ -700,6 +1035,7 @@ public class RTABMapActivity extends Activity implements OnClickListener {
//disable gui actions //disable gui actions
mItemSave.setEnabled(false); mItemSave.setEnabled(false);
mItemOpen.setEnabled(false); mItemOpen.setEnabled(false);
mItemPostProcessing.setEnabled(false);
mItemExport.setEnabled(false); mItemExport.setEnabled(false);
} }
} }
@@ -715,6 +1051,7 @@ public class RTABMapActivity extends Activity implements OnClickListener {
((TextView)findViewById(R.id.features)).setText(String.valueOf(0)); ((TextView)findViewById(R.id.features)).setText(String.valueOf(0));
((TextView)findViewById(R.id.update_time)).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.hypothesis)).setText(String.valueOf(0));
((TextView)findViewById(R.id.fps)).setText(String.valueOf(0));
mTotalLoopClosures = 0; mTotalLoopClosures = 0;
((TextView)findViewById(R.id.total_loop)).setText(String.valueOf(mTotalLoopClosures)); ((TextView)findViewById(R.id.total_loop)).setText(String.valueOf(mTotalLoopClosures));
@@ -728,10 +1065,15 @@ public class RTABMapActivity extends Activity implements OnClickListener {
RTABMapLib.openDatabase(mTempDatabasePath); RTABMapLib.openDatabase(mTempDatabasePath);
} }
} }
else if(itemId == R.id.export) else if(itemId == R.id.export_obj || itemId == R.id.export_ply)
{ {
final String extension = itemId == R.id.export_ply ? ".ply" : ".obj";
final boolean isOBJ = itemId == R.id.export_obj;
final int polygons = Integer.parseInt(((TextView)findViewById(R.id.polygons)).getText().toString());
AlertDialog.Builder builder = new AlertDialog.Builder(this); AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("File Name (*.ply):"); builder.setTitle(String.format("File Name (*%s):", extension));
final EditText input = new EditText(this); final EditText input = new EditText(this);
input.setInputType(InputType.TYPE_CLASS_TEXT); input.setInputType(InputType.TYPE_CLASS_TEXT);
builder.setView(input); builder.setView(input);
@@ -740,9 +1082,10 @@ public class RTABMapActivity extends Activity implements OnClickListener {
public void onClick(DialogInterface dialog, int which) public void onClick(DialogInterface dialog, int which)
{ {
final String fileName = input.getText().toString(); final String fileName = input.getText().toString();
dialog.dismiss();
if(!fileName.isEmpty()) if(!fileName.isEmpty())
{ {
File newFile = new File(mWorkingDirectory + fileName + ".ply"); File newFile = new File(mWorkingDirectory + fileName + extension);
if(newFile.exists()) if(newFile.exists())
{ {
new AlertDialog.Builder(getActivity()) new AlertDialog.Builder(getActivity())
@@ -750,12 +1093,26 @@ public class RTABMapActivity extends Activity implements OnClickListener {
.setMessage("Do you want to overwrite the existing file?") .setMessage("Do you want to overwrite the existing file?")
.setPositiveButton("Yes", new DialogInterface.OnClickListener() { .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) { public void onClick(DialogInterface dialog, int which) {
final String path = mWorkingDirectory + fileName + ".ply"; final String path = mWorkingDirectory + fileName + extension;
mItemExport.setEnabled(false); mItemExport.setEnabled(false);
mProgressDialog.setTitle("Exporting"); mProgressDialog.setTitle("Exporting");
mProgressDialog.setMessage(String.format("Please wait while exporting \"%s\"...", fileName+".ply")); if(polygons > 1000000)
{
mProgressDialog.setMessage(String.format(
"Please wait while exporting \"%s\"...\n"
+ "Tip: With more than 1M polygons, to reduce exporting time and file size, consider:\n"
+ " a) increasing triangle size (Rendering options)\n"
+ " b) decreasing maximum camera depth (Rendering options)\n"
+ " c) activate Nodes Filtering (Mapping options)\n"
+ "then save/open to refresh the meshes.", fileName+extension));
}
else
{
mProgressDialog.setMessage(String.format("Please wait while exporting \"%s\"...", fileName+extension));
}
mProgressDialog.show(); mProgressDialog.show();
Thread exportThread = new Thread(new Runnable() { Thread exportThread = new Thread(new Runnable() {
@@ -765,11 +1122,18 @@ public class RTABMapActivity extends Activity implements OnClickListener {
public void run() { public void run() {
if(success) if(success)
{ {
Toast.makeText(getActivity(), String.format("Mesh \"%s\" successfully exported!", path), Toast.LENGTH_LONG).show(); if(isOBJ)
{
mToast.makeText(getActivity(), String.format("Mesh \"%s\" (with textures \"%s/\" and \"%s\") successfully exported!", path, fileName, fileName + ".mtl"), mToast.LENGTH_LONG).show();
} }
else else
{ {
Toast.makeText(getActivity(), String.format("Exporting mesh to \"%s\" failed!", path), Toast.LENGTH_LONG).show(); mToast.makeText(getActivity(), String.format("Mesh \"%s\" successfully exported!", path), mToast.LENGTH_LONG).show();
}
}
else
{
mToast.makeText(getActivity(), String.format("Exporting mesh to \"%s\" failed!", path), mToast.LENGTH_LONG).show();
} }
mItemExport.setEnabled(true); mItemExport.setEnabled(true);
mProgressDialog.dismiss(); mProgressDialog.dismiss();
@@ -789,10 +1153,10 @@ public class RTABMapActivity extends Activity implements OnClickListener {
} }
else else
{ {
final String path = mWorkingDirectory + fileName + ".ply"; final String path = mWorkingDirectory + fileName + extension;
mItemExport.setEnabled(false); mItemExport.setEnabled(false);
mProgressDialog.setTitle("Exporting"); mProgressDialog.setTitle("Exporting");
mProgressDialog.setMessage(String.format("Please wait while exporting \"%s\"...", fileName+".ply")); mProgressDialog.setMessage(String.format("Please wait while exporting \"%s\"...", fileName+extension));
mProgressDialog.show(); mProgressDialog.show();
Thread exportThread = new Thread(new Runnable() { Thread exportThread = new Thread(new Runnable() {
public void run() { public void run() {
@@ -801,11 +1165,18 @@ public class RTABMapActivity extends Activity implements OnClickListener {
public void run() { public void run() {
if(success) if(success)
{ {
Toast.makeText(getActivity(), String.format("Mesh \"%s\" successfully exported!", path), Toast.LENGTH_LONG).show(); if(isOBJ)
{
mToast.makeText(getActivity(), String.format("Mesh \"%s\" (with textures \"%s/\" and \"%s\") successfully exported!", path, fileName, fileName + ".mtl"), mToast.LENGTH_LONG).show();
} }
else else
{ {
Toast.makeText(getActivity(), String.format("Exporting mesh to \"%s\" failed!", path), Toast.LENGTH_LONG).show(); mToast.makeText(getActivity(), String.format("Mesh \"%s\" successfully exported!", path), mToast.LENGTH_LONG).show();
}
}
else
{
mToast.makeText(getActivity(), String.format("Exporting mesh to \"%s\" failed!", path), mToast.LENGTH_LONG).show();
} }
mItemExport.setEnabled(true); mItemExport.setEnabled(true);
mProgressDialog.dismiss(); mProgressDialog.dismiss();
@@ -834,7 +1205,7 @@ public class RTABMapActivity extends Activity implements OnClickListener {
if(!mItemTrajectoryMode.isChecked()) if(!mItemTrajectoryMode.isChecked())
{ {
mProgressDialog.setTitle("Loading"); mProgressDialog.setTitle("Loading");
mProgressDialog.setMessage(String.format("Please wait while loading \"%s\"...", files[which])); mProgressDialog.setMessage(String.format("Database \"%s\" loaded. Please wait while creating point clouds and meshes...", files[which]));
mProgressDialog.show(); mProgressDialog.show();
} }
@@ -1,6 +1,8 @@
package com.introlab.rtabmap; package com.introlab.rtabmap;
import android.os.IBinder;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.util.Log;
// Wrapper for native library // Wrapper for native library
@@ -8,19 +10,29 @@ import android.view.KeyEvent;
public class RTABMapLib public class RTABMapLib
{ {
static 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"); System.loadLibrary("NativeRTABMap");
} }
// Initialize the Tango Service, this function starts the communication // Initialize the Tango Service, this function starts the communication
// between the application and Tango Service. // between the application and Tango Service.
// The activity object is used for checking if the API version is outdated. // 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 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. // Release all non OpenGl resources that are allocated from the program.
public static native void onPause(); public static native void onPause();
@@ -50,12 +62,19 @@ public class RTABMapLib
public static native void setLocalizationMode(boolean enabled); public static native void setLocalizationMode(boolean enabled);
public static native void setTrajectoryMode(boolean enabled); public static native void setTrajectoryMode(boolean enabled);
public static native void setGraphOptimization(boolean enabled); public static native void setGraphOptimization(boolean enabled);
public static native void setNodesFiltering(boolean enabled);
public static native void setGraphVisible(boolean visible); public static native void setGraphVisible(boolean visible);
public static native void setAutoExposure(boolean enabled); public static native void setAutoExposure(boolean enabled);
public static native void setFullResolution(boolean enabled);
public static native void setMaxCloudDepth(float value);
public static native void setMeshAngleTolerance(float value);
public static native void setMeshTriangleSize(int value);
public static native int setMappingParameter(String key, String value);
public static native void resetMapping(); public static native void resetMapping();
public static native void save(); public static native void save();
public static native boolean exportMesh(String filePath); public static native boolean exportMesh(String filePath);
public static native int postProcessing(int approach);
public static native String getStatus(); public static native String getStatus();
public static native int getTotalNodes(); public static native int getTotalNodes();
@@ -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;
}
}
+19 -5
View File
@@ -5,7 +5,7 @@ SET(headers_ui
) )
#This will generate moc_* for Qt #This will generate moc_* for Qt
IF("${RTABMAP_QT_VERSION}" STREQUAL "4") IF(QT4_FOUND)
QT4_WRAP_CPP(moc_srcs ${headers_ui}) QT4_WRAP_CPP(moc_srcs ${headers_ui})
ELSE() ELSE()
QT5_WRAP_CPP(moc_srcs ${headers_ui}) QT5_WRAP_CPP(moc_srcs ${headers_ui})
@@ -25,9 +25,9 @@ SET(INCLUDE_DIRS
${PCL_INCLUDE_DIRS} ${PCL_INCLUDE_DIRS}
) )
IF("${RTABMAP_QT_VERSION}" STREQUAL "4") IF(QT4_FOUND)
INCLUDE(${QT_USE_FILE}) INCLUDE(${QT_USE_FILE})
ENDIF() ENDIF(QT4_FOUND)
SET(LIBRARIES SET(LIBRARIES
${QT_LIBRARIES} ${QT_LIBRARIES}
@@ -73,9 +73,9 @@ ELSE()
ADD_EXECUTABLE(rtabmap ${SRC_FILES}) ADD_EXECUTABLE(rtabmap ${SRC_FILES})
ENDIF() ENDIF()
TARGET_LINK_LIBRARIES(rtabmap rtabmap_core rtabmap_gui rtabmap_utilite ${LIBRARIES}) TARGET_LINK_LIBRARIES(rtabmap rtabmap_core rtabmap_gui rtabmap_utilite ${LIBRARIES})
IF("${RTABMAP_QT_VERSION}" STREQUAL "5") IF(Qt5_FOUND)
QT5_USE_MODULES(rtabmap Widgets Core Gui Svg PrintSupport) QT5_USE_MODULES(rtabmap Widgets Core Gui Svg PrintSupport)
ENDIF() ENDIF(Qt5_FOUND)
IF(APPLE AND BUILD_AS_BUNDLE) IF(APPLE AND BUILD_AS_BUNDLE)
SET_TARGET_PROPERTIES(rtabmap PROPERTIES SET_TARGET_PROPERTIES(rtabmap PROPERTIES
@@ -137,11 +137,25 @@ IF((APPLE AND BUILD_AS_BUNDLE) OR WIN32)
# Install needed Qt plugins by copying directories from the qt installation # Install needed Qt plugins by copying directories from the qt installation
# One can cull what gets copied by using 'REGEX "..." EXCLUDE' # One can cull what gets copied by using 'REGEX "..." EXCLUDE'
# Exclude debug libraries # Exclude debug libraries
IF(QT_PLUGINS_DIR)
INSTALL(DIRECTORY "${QT_PLUGINS_DIR}/imageformats" INSTALL(DIRECTORY "${QT_PLUGINS_DIR}/imageformats"
DESTINATION ${plugin_dest_dir}/plugins DESTINATION ${plugin_dest_dir}/plugins
COMPONENT runtime COMPONENT runtime
REGEX ".*d4.dll" EXCLUDE REGEX ".*d4.dll" EXCLUDE
REGEX ".*d4.a" 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 # install a qt.conf file
# this inserts some cmake code into the install script to write the file # this inserts some cmake code into the install script to write the file
+1 -1
View File
@@ -1,5 +1,5 @@
/* /*
Copyright (c) 2010-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
+21 -1
View File
@@ -1,5 +1,5 @@
/* /*
Copyright (c) 2010-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
@@ -33,6 +33,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "rtabmap/gui/MainWindow.h" #include "rtabmap/gui/MainWindow.h"
#include <QMessageBox> #include <QMessageBox>
#include "rtabmap/utilite/UObjDeletionThread.h" #include "rtabmap/utilite/UObjDeletionThread.h"
#include "rtabmap/utilite/UFile.h"
#include "rtabmap/utilite/UConversion.h"
#include "ObjDeletionHandler.h" #include "ObjDeletionHandler.h"
using namespace rtabmap; using namespace rtabmap;
@@ -46,6 +48,19 @@ int main(int argc, char* argv[])
/* Create tasks */ /* Create tasks */
QApplication * app = new QApplication(argc, argv); QApplication * app = new QApplication(argc, argv);
MainWindow * mainWindow = new MainWindow(); MainWindow * mainWindow = new MainWindow();
app->installEventFilter(mainWindow); // to catch FileOpen events.
std::string database;
for(int i=1; i<argc; ++i)
{
std::string value = uReplaceChar(argv[i], '~', UDirectory::homeDir());
if(UFile::exists(value) &&
UFile::getExtension(value).compare("db") == 0)
{
database = value;
break;
}
}
UINFO("Program started..."); UINFO("Program started...");
@@ -65,6 +80,11 @@ int main(int argc, char* argv[])
rtabmap->start(); // start it not initialized... will be initialized by event from the gui rtabmap->start(); // start it not initialized... will be initialized by event from the gui
UEventsManager::addHandler(rtabmap); UEventsManager::addHandler(rtabmap);
if(!database.empty())
{
QMetaObject::invokeMethod(mainWindow, "openDatabase", Qt::QueuedConnection, Q_ARG(QString, QString(database.c_str())));
}
// Now wait for application to finish // Now wait for application to finish
app->connect( app, SIGNAL( lastWindowClosed() ), app->connect( app, SIGNAL( lastWindowClosed() ),
app, SLOT( quit() ) ); app, SLOT( quit() ) );
+1
View File
@@ -79,6 +79,7 @@ IF(G2O_STUFF_LIBRARY AND G2O_CORE_LIBRARY AND G2O_INCLUDE_DIR AND G2O_SOLVERS_FO
${G2O_CORE_LIBRARY} ${G2O_CORE_LIBRARY}
${G2O_TYPES_SLAM2D} ${G2O_TYPES_SLAM2D}
${G2O_TYPES_SLAM3D} ${G2O_TYPES_SLAM3D}
${G2O_TYPES_SBA}
${G2O_STUFF_LIBRARY}) ${G2O_STUFF_LIBRARY})
IF(CSPARSE_FOUND) IF(CSPARSE_FOUND)
+56
View File
@@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
<string>${MACOSX_BUNDLE_EXECUTABLE_NAME}</string>
<key>CFBundleGetInfoString</key>
<string>${MACOSX_BUNDLE_INFO_STRING}</string>
<key>CFBundleIconFile</key>
<string>${MACOSX_BUNDLE_ICON_FILE}</string>
<key>CFBundleIdentifier</key>
<string>${MACOSX_BUNDLE_GUI_IDENTIFIER}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleLongVersionString</key>
<string>${MACOSX_BUNDLE_LONG_VERSION_STRING}</string>
<key>CFBundleName</key>
<string>${MACOSX_BUNDLE_BUNDLE_NAME}</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>${MACOSX_BUNDLE_SHORT_VERSION_STRING}</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>${MACOSX_BUNDLE_BUNDLE_VERSION}</string>
<key>CSResourcesFileMapped</key>
<true/>
<key>LSRequiresCarbon</key>
<true/>
<key>NSHumanReadableCopyright</key>
<string>${MACOSX_BUNDLE_COPYRIGHT}</string>
<!-- File type associations -->
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>db</string>
</array>
<!-- <key>CFBundleTypeIconFile</key> -->
<!-- <string>rtabmap_db.icns</string> -->
<key>CFBundleTypeName</key>
<string>RTAB-Map Database</string>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>LSIsAppleDefaultForType</key>
<string>Yes</string>
</dict>
</array>
</dict>
</plist>
+1 -1
View File
@@ -1,5 +1,5 @@
/* /*
Copyright (c) 2010-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
+3 -2
View File
@@ -1,5 +1,5 @@
/* /*
Copyright (c) 2010-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
@@ -56,6 +56,7 @@ public:
virtual bool init(const std::string & calibrationFolder = ".", const std::string & cameraName = "") = 0; virtual bool init(const std::string & calibrationFolder = ".", const std::string & cameraName = "") = 0;
virtual bool isCalibrated() const = 0; virtual bool isCalibrated() const = 0;
virtual std::string getSerial() const = 0; virtual std::string getSerial() const = 0;
virtual bool odomProvided() const { return false; }
//getters //getters
float getImageRate() const {return _imageRate;} float getImageRate() const {return _imageRate;}
@@ -76,7 +77,7 @@ protected:
/** /**
* returned rgb and depth images should be already rectified if calibration was loaded * returned rgb and depth images should be already rectified if calibration was loaded
*/ */
virtual SensorData captureImage() = 0; virtual SensorData captureImage(CameraInfo * info = 0) = 0;
int getNextSeqID() {return ++_seq;} int getNextSeqID() {return ++_seq;}
+1 -1
View File
@@ -1,5 +1,5 @@
/* /*
Copyright (c) 2010-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
+7 -2
View File
@@ -1,5 +1,5 @@
/* /*
Copyright (c) 2010-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
@@ -39,22 +39,27 @@ public:
CameraInfo() : CameraInfo() :
cameraName(""), cameraName(""),
id(0), id(0),
stamp(0.0),
timeCapture(0.0f), timeCapture(0.0f),
timeDisparity(0.0f), timeDisparity(0.0f),
timeMirroring(0.0f), timeMirroring(0.0f),
timeImageDecimation(0.0f), timeImageDecimation(0.0f),
timeScanFromDepth(0.0f) timeScanFromDepth(0.0f),
odomCovariance(cv::Mat::eye(6,6,CV_64FC1))
{ {
} }
virtual ~CameraInfo() {} virtual ~CameraInfo() {}
std::string cameraName; std::string cameraName;
int id; int id;
double stamp;
float timeCapture; float timeCapture;
float timeDisparity; float timeDisparity;
float timeMirroring; float timeMirroring;
float timeImageDecimation; float timeImageDecimation;
float timeScanFromDepth; float timeScanFromDepth;
Transform odomPose;
cv::Mat odomCovariance;
}; };
} // namespace rtabmap } // namespace rtabmap
+2 -2
View File
@@ -1,5 +1,5 @@
/* /*
Copyright (c) 2010-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
@@ -99,7 +99,7 @@ public:
cv::Mat K_raw() const {return K_;} //intrinsic camera matrix (before rectification) cv::Mat K_raw() const {return K_;} //intrinsic camera matrix (before rectification)
cv::Mat D_raw() const {return D_;} //intrinsic distorsion matrix (before rectification) cv::Mat D_raw() const {return D_;} //intrinsic distorsion matrix (before rectification)
cv::Mat K() const {return !P_.empty()?P_.colRange(0,3):K_;} // if P exists, return rectified version cv::Mat K() const {return !P_.empty()?P_.colRange(0,3):K_;} // if P exists, return rectified version
cv::Mat D() const {return P_.empty()&&!D_.empty()?D_:cv::Mat::zeros(1,4,CV_64FC1);} // if P exists, return rectified version cv::Mat D() const {return P_.empty()&&!D_.empty()?D_:cv::Mat::zeros(1,5,CV_64FC1);} // if P exists, return rectified version
cv::Mat R() const {return R_;} //rectification matrix cv::Mat R() const {return R_;} //rectification matrix
cv::Mat P() const {return P_;} //projection matrix cv::Mat P() const {return P_;} //projection matrix
+4 -3
View File
@@ -1,5 +1,5 @@
/* /*
Copyright (c) 2010-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
@@ -119,7 +119,7 @@ public:
} }
protected: protected:
virtual SensorData captureImage(); virtual SensorData captureImage(CameraInfo * info = 0);
private: private:
std::string _path; std::string _path;
@@ -178,6 +178,7 @@ public:
public: public:
CameraVideo(int usbDevice = 0, CameraVideo(int usbDevice = 0,
bool rectifyImages = false,
float imageRate = 0, float imageRate = 0,
const Transform & localTransform = Transform::getIdentity()); const Transform & localTransform = Transform::getIdentity());
CameraVideo(const std::string & filePath, CameraVideo(const std::string & filePath,
@@ -193,7 +194,7 @@ public:
const std::string & getFilePath() const {return _filePath;} const std::string & getFilePath() const {return _filePath;}
protected: protected:
virtual SensorData captureImage(); virtual SensorData captureImage(CameraInfo * info = 0);
private: private:
// File type // File type
+7 -7
View File
@@ -1,5 +1,5 @@
/* /*
Copyright (c) 2010-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
@@ -97,7 +97,7 @@ public:
virtual std::string getSerial() const; virtual std::string getSerial() const;
protected: protected:
virtual SensorData captureImage(); virtual SensorData captureImage(CameraInfo * info = 0);
private: private:
pcl::Grabber* interface_; pcl::Grabber* interface_;
@@ -131,7 +131,7 @@ public:
virtual std::string getSerial() const {return "";} // unknown with OpenCV virtual std::string getSerial() const {return "";} // unknown with OpenCV
protected: protected:
virtual SensorData captureImage(); virtual SensorData captureImage(CameraInfo * info = 0);
private: private:
bool _asus; bool _asus;
@@ -168,7 +168,7 @@ public:
void setOpenNI2StampsAndIDsUsed(bool used) {_openNI2StampsAndIDsUsed = used;} void setOpenNI2StampsAndIDsUsed(bool used) {_openNI2StampsAndIDsUsed = used;}
protected: protected:
virtual SensorData captureImage(); virtual SensorData captureImage(CameraInfo * info = 0);
private: private:
openni::Device * _device; openni::Device * _device;
@@ -204,7 +204,7 @@ public:
virtual std::string getSerial() const; virtual std::string getSerial() const;
protected: protected:
virtual SensorData captureImage(); virtual SensorData captureImage(CameraInfo * info = 0);
private: private:
int deviceId_; int deviceId_;
@@ -249,7 +249,7 @@ public:
virtual std::string getSerial() const; virtual std::string getSerial() const;
protected: protected:
virtual SensorData captureImage(); virtual SensorData captureImage(CameraInfo * info = 0);
private: private:
int deviceId_; int deviceId_;
@@ -291,7 +291,7 @@ public:
virtual std::string getSerial() const; virtual std::string getSerial() const;
protected: protected:
virtual SensorData captureImage(); virtual SensorData captureImage(CameraInfo * info = 0);
private: private:
CameraImages cameraDepth_; CameraImages cameraDepth_;
+71 -5
View File
@@ -1,5 +1,5 @@
/* /*
Copyright (c) 2010-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
@@ -39,6 +39,14 @@ namespace FlyCapture2
class Camera; class Camera;
} }
namespace sl
{
namespace zed
{
class Camera;
}
}
namespace rtabmap namespace rtabmap
{ {
@@ -62,7 +70,7 @@ public:
virtual std::string getSerial() const; virtual std::string getSerial() const;
protected: protected:
virtual SensorData captureImage(); virtual SensorData captureImage(CameraInfo * info = 0);
private: private:
DC1394Device *device_; DC1394Device *device_;
@@ -87,13 +95,64 @@ public:
virtual std::string getSerial() const; virtual std::string getSerial() const;
protected: protected:
virtual SensorData captureImage(); virtual SensorData captureImage(CameraInfo * info = 0);
private: private:
FlyCapture2::Camera * camera_; FlyCapture2::Camera * camera_;
void * triclopsCtx_; // TriclopsContext 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,
bool computeOdometry = false,
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,
bool computeOdometry = false,
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;
virtual bool odomProvided() const { return computeOdometry_; }
protected:
virtual SensorData captureImage(CameraInfo * info = 0);
private:
sl::zed::Camera * zed_;
StereoCameraModel stereoModel_;
CameraVideo::Source src_;
int usbDevice_;
std::string svoFilePath_;
int resolution_;
int quality_;
int sensingMode_;
int confidenceThr_;
bool computeOdometry_;
bool lost_;
};
///////////////////////// /////////////////////////
// CameraStereoImages // CameraStereoImages
///////////////////////// /////////////////////////
@@ -123,7 +182,7 @@ public:
virtual std::string getSerial() const; virtual std::string getSerial() const;
protected: protected:
virtual SensorData captureImage(); virtual SensorData captureImage(CameraInfo * info = 0);
private: private:
CameraImages * camera2_; CameraImages * camera2_;
@@ -147,6 +206,11 @@ public:
bool rectifyImages = false, bool rectifyImages = false,
float imageRate=0.0f, float imageRate=0.0f,
const Transform & localTransform = Transform::getIdentity()); const Transform & localTransform = Transform::getIdentity());
CameraStereoVideo(
int device,
bool rectifyImages = false,
float imageRate = 0.0f,
const Transform & localTransform = Transform::getIdentity());
virtual ~CameraStereoVideo(); virtual ~CameraStereoVideo();
virtual bool init(const std::string & calibrationFolder = ".", const std::string & cameraName = ""); virtual bool init(const std::string & calibrationFolder = ".", const std::string & cameraName = "");
@@ -154,7 +218,7 @@ public:
virtual std::string getSerial() const; virtual std::string getSerial() const;
protected: protected:
virtual SensorData captureImage(); virtual SensorData captureImage(CameraInfo * info = 0);
private: private:
cv::VideoCapture capture_; cv::VideoCapture capture_;
@@ -162,6 +226,8 @@ private:
bool rectifyImages_; bool rectifyImages_;
StereoCameraModel stereoModel_; StereoCameraModel stereoModel_;
std::string cameraName_; std::string cameraName_;
CameraVideo::Source src_;
int usbDevice_;
}; };
} // namespace rtabmap } // namespace rtabmap
+2 -1
View File
@@ -1,5 +1,5 @@
/* /*
Copyright (c) 2010-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
@@ -91,6 +91,7 @@ private:
bool _scanFromDepth; bool _scanFromDepth;
int _scanDecimation; int _scanDecimation;
float _scanMaxDepth; float _scanMaxDepth;
float _scanMinDepth;
float _scanVoxelSize; float _scanVoxelSize;
int _scanNormalsK; int _scanNormalsK;
StereoDense * _stereoDense; StereoDense * _stereoDense;
+1 -1
View File
@@ -1,5 +1,5 @@
/* /*
Copyright (c) 2010-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
+8 -4
View File
@@ -1,5 +1,5 @@
/* /*
Copyright (c) 2010-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
@@ -88,13 +88,13 @@ public:
void updateLink(const Link & link); void updateLink(const Link & link);
public: public:
void addStatisticsAfterRun(int stMemSize, int lastSignAdded, int processMemUsed, int databaseMemUsed, int dictionarySize) const; void addStatisticsAfterRun(int stMemSize, int lastSignAdded, int processMemUsed, int databaseMemUsed, int dictionarySize, const ParametersMap & parameters) const;
public: public:
// Mutex-protected methods of abstract versions below // Mutex-protected methods of abstract versions below
bool openConnection(const std::string & url, bool overwritten = false); bool openConnection(const std::string & url, bool overwritten = false);
void closeConnection(); void closeConnection(bool save = true);
bool isConnected() const; bool isConnected() const;
long getMemoryUsed() const; // In bytes long getMemoryUsed() const; // In bytes
std::string getDatabaseVersion() const; std::string getDatabaseVersion() const;
@@ -107,6 +107,7 @@ public:
int getLastDictionarySize() const; // working memory int getLastDictionarySize() const; // working memory
int getTotalNodesSize() const; int getTotalNodesSize() const;
int getTotalDictionarySize() const; int getTotalDictionarySize() const;
ParametersMap getLastParameters() const;
void executeNoResult(const std::string & sql) const; void executeNoResult(const std::string & sql) const;
@@ -119,6 +120,7 @@ public:
// Specific queries... // Specific queries...
void loadNodeData(std::list<Signature *> & signatures) const; void loadNodeData(std::list<Signature *> & signatures) const;
void getNodeData(int signatureId, SensorData & data) const; void getNodeData(int signatureId, SensorData & data) const;
bool getCalibration(int signatureId, std::vector<CameraModel> & models, StereoCameraModel & stereoModel) const;
bool getNodeInfo(int signatureId, Transform & pose, int & mapId, int & weight, std::string & label, double & stamp, Transform & groundTruthPose) const; bool getNodeInfo(int signatureId, Transform & pose, int & mapId, int & weight, std::string & label, double & stamp, Transform & groundTruthPose) const;
void loadLinks(int signatureId, std::map<int, Link> & links, Link::Type type = Link::kUndef) const; void loadLinks(int signatureId, std::map<int, Link> & links, Link::Type type = Link::kUndef) const;
void getWeight(int signatureId, int & weight) const; void getWeight(int signatureId, int & weight) const;
@@ -135,7 +137,7 @@ protected:
private: private:
virtual bool connectDatabaseQuery(const std::string & url, bool overwritten = false) = 0; virtual bool connectDatabaseQuery(const std::string & url, bool overwritten = false) = 0;
virtual void disconnectDatabaseQuery() = 0; virtual void disconnectDatabaseQuery(bool save = true) = 0;
virtual bool isConnectedQuery() const = 0; virtual bool isConnectedQuery() const = 0;
virtual long getMemoryUsedQuery() const = 0; // In bytes virtual long getMemoryUsedQuery() const = 0; // In bytes
virtual bool getDatabaseVersionQuery(std::string & version) const = 0; virtual bool getDatabaseVersionQuery(std::string & version) const = 0;
@@ -148,6 +150,7 @@ private:
virtual int getLastDictionarySizeQuery() const = 0; virtual int getLastDictionarySizeQuery() const = 0;
virtual int getTotalNodesSizeQuery() const = 0; virtual int getTotalNodesSizeQuery() const = 0;
virtual int getTotalDictionarySizeQuery() const = 0; virtual int getTotalDictionarySizeQuery() const = 0;
virtual ParametersMap getLastParametersQuery() const = 0;
virtual void executeNoResultQuery(const std::string & sql) const = 0; virtual void executeNoResultQuery(const std::string & sql) const = 0;
@@ -169,6 +172,7 @@ private:
virtual void loadLinksQuery(int signatureId, std::map<int, Link> & links, Link::Type type = Link::kUndef) const = 0; virtual void loadLinksQuery(int signatureId, std::map<int, Link> & links, Link::Type type = Link::kUndef) const = 0;
virtual void loadNodeDataQuery(std::list<Signature *> & signatures) const = 0; virtual void loadNodeDataQuery(std::list<Signature *> & signatures) const = 0;
virtual bool getCalibrationQuery(int signatureId, std::vector<CameraModel> & models, StereoCameraModel & stereoModel) const = 0;
virtual bool getNodeInfoQuery(int signatureId, Transform & pose, int & mapId, int & weight, std::string & label, double & stamp, Transform & groundTruthPose) const = 0; virtual bool getNodeInfoQuery(int signatureId, Transform & pose, int & mapId, int & weight, std::string & label, double & stamp, Transform & groundTruthPose) const = 0;
virtual void getAllNodeIdsQuery(std::set<int> & ids, bool ignoreChildren, bool ignoreBadSignatures) const = 0; virtual void getAllNodeIdsQuery(std::set<int> & ids, bool ignoreChildren, bool ignoreBadSignatures) const = 0;
virtual void getAllLinksQuery(std::multimap<int, Link> & links, bool ignoreNullLinks) const = 0; virtual void getAllLinksQuery(std::multimap<int, Link> & links, bool ignoreNullLinks) const = 0;
+25 -15
View File
@@ -1,5 +1,5 @@
/* /*
Copyright (c) 2010-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
@@ -30,11 +30,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "rtabmap/core/RtabmapExp.h" // DLL export/import defines #include "rtabmap/core/RtabmapExp.h" // DLL export/import defines
#include <rtabmap/utilite/UThreadNode.h>
#include <rtabmap/utilite/UTimer.h> #include <rtabmap/utilite/UTimer.h>
#include <rtabmap/utilite/UEventsSender.h>
#include <rtabmap/core/Transform.h> #include <rtabmap/core/Transform.h>
#include <rtabmap/core/OdometryEvent.h> #include <rtabmap/core/Camera.h>
#include <opencv2/core/core.hpp> #include <opencv2/core/core.hpp>
@@ -45,34 +43,45 @@ namespace rtabmap {
class DBDriver; class DBDriver;
class RTABMAP_EXP DBReader : public UThreadNode, public UEventsSender { class RTABMAP_EXP DBReader : public Camera {
public: public:
DBReader(const std::string & databasePath, DBReader(const std::string & databasePath,
float frameRate = 0.0f, float frameRate = 0.0f, // -1 = use Database stamps, 0 = inf
bool odometryIgnored = false, bool odometryIgnored = false,
bool ignoreGoalDelay = false, bool ignoreGoalDelay = false,
bool goalsIgnored = false); bool goalsIgnored = false,
int startIndex = 0,
int cameraIndex = -1);
DBReader(const std::list<std::string> & databasePaths, DBReader(const std::list<std::string> & databasePaths,
float frameRate = 0.0f, float frameRate = 0.0f, // -1 = use Database stamps, 0 = inf
bool odometryIgnored = false, bool odometryIgnored = false,
bool ignoreGoalDelay = false, bool ignoreGoalDelay = false,
bool goalsIgnored = false); bool goalsIgnored = false,
int startIndex = 0,
int cameraIndex = -1);
virtual ~DBReader(); virtual ~DBReader();
bool init(int startIndex=0); virtual bool init(
void setFrameRate(float frameRate); const std::string & calibrationFolder = ".",
OdometryEvent getNextData(); const std::string & cameraName = "");
virtual bool isCalibrated() const;
virtual std::string getSerial() const;
virtual bool odomProvided() const {return !_odometryIgnored;}
protected: protected:
virtual void mainLoopBegin(); virtual SensorData captureImage(CameraInfo * info = 0);
virtual void mainLoop();
private:
SensorData getNextData(CameraInfo * info = 0);
private: private:
std::list<std::string> _paths; std::list<std::string> _paths;
float _frameRate; // -1 = use Database stamps, 0 = inf
bool _odometryIgnored; bool _odometryIgnored;
bool _ignoreGoalDelay; bool _ignoreGoalDelay;
bool _goalsIgnored; bool _goalsIgnored;
int _startIndex;
int _cameraIndex;
DBDriver * _dbDriver; DBDriver * _dbDriver;
UTimer _timer; UTimer _timer;
@@ -80,6 +89,7 @@ private:
std::set<int>::iterator _currentId; std::set<int>::iterator _currentId;
double _previousStamp; double _previousStamp;
int _previousMapID; int _previousMapID;
bool _calibrated;
}; };
} /* namespace rtabmap */ } /* namespace rtabmap */
@@ -1,5 +1,5 @@
/* /*
Copyright (c) 2010-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
+1 -1
View File
@@ -1,5 +1,5 @@
/* /*
Copyright (c) 2010-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
+8 -1
View File
@@ -1,5 +1,5 @@
/* /*
Copyright (c) 2010-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
@@ -79,6 +79,13 @@ std::multimap<int, int>::const_iterator RTABMAP_EXP findLink(
int to, int to,
bool checkBothWays = true); 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. //Note: This assumes a coordinate system where X is forward, * Y is up, and Z is right.
std::map<int, Transform> RTABMAP_EXP frustumPosesFiltering( std::map<int, Transform> RTABMAP_EXP frustumPosesFiltering(
const std::map<int, Transform> & poses, const std::map<int, Transform> & poses,
+1 -1
View File
@@ -1,5 +1,5 @@
/* /*
Copyright (c) 2010-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
+1 -1
View File
@@ -1,5 +1,5 @@
/* /*
Copyright (c) 2010-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
+11 -5
View File
@@ -1,5 +1,5 @@
/* /*
Copyright (c) 2010-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
@@ -91,7 +91,7 @@ public:
int cleanup(); int cleanup();
void emptyTrash(); void emptyTrash();
void joinTrashThread(); void joinTrashThread();
bool addLink(const Link & link); bool addLink(const Link & link, bool addInDatabase = false);
void updateLink(int fromId, int toId, const Transform & transform, float rotVariance, float transVariance); void updateLink(int fromId, int toId, const Transform & transform, float rotVariance, float transVariance);
void updateLink(int fromId, int toId, const Transform & transform, const cv::Mat & covariance); void updateLink(int fromId, int toId, const Transform & transform, const cv::Mat & covariance);
void removeAllVirtualLinks(); void removeAllVirtualLinks();
@@ -147,10 +147,14 @@ public:
Transform & groundTruth, Transform & groundTruth,
bool lookInDatabase = false) const; bool lookInDatabase = false) const;
cv::Mat getImageCompressed(int signatureId) const; cv::Mat getImageCompressed(int signatureId) const;
SensorData getNodeData(int nodeId, bool uncompressedData = false, bool keepLoadedDataInMemory = true); SensorData getNodeData(int nodeId, bool uncompressedData = false) const;
void getNodeWords(int nodeId, void getNodeWords(int nodeId,
std::multimap<int, cv::KeyPoint> & words, std::multimap<int, cv::KeyPoint> & words,
std::multimap<int, cv::Point3f> & words3); std::multimap<int, cv::Point3f> & words3,
std::multimap<int, cv::Mat> & wordsDescriptors);
void getNodeCalibration(int nodeId,
std::vector<CameraModel> & models,
StereoCameraModel & stereoModel);
SensorData getSignatureDataConst(int locationId) const; SensorData getSignatureDataConst(int locationId) const;
std::set<int> getAllSignatureIds() const; std::set<int> getAllSignatureIds() const;
bool memoryChanged() const {return _memoryChanged;} bool memoryChanged() const {return _memoryChanged;}
@@ -181,6 +185,7 @@ public:
std::multimap<int, Link> & links, std::multimap<int, Link> & links,
bool lookInDatabase = false); bool lookInDatabase = false);
Transform computeTransform(Signature & fromS, Signature & toS, Transform guess, RegistrationInfo * info = 0) const;
Transform computeTransform(int fromId, int toId, Transform guess, RegistrationInfo * info = 0); Transform computeTransform(int fromId, int toId, Transform guess, RegistrationInfo * info = 0);
Transform computeIcpTransform(int fromId, int toId, Transform guess, RegistrationInfo * info = 0); Transform computeIcpTransform(int fromId, int toId, Transform guess, RegistrationInfo * info = 0);
Transform computeIcpTransformMulti( Transform computeIcpTransformMulti(
@@ -239,7 +244,8 @@ private:
bool _generateIds; bool _generateIds;
bool _badSignaturesIgnored; bool _badSignaturesIgnored;
bool _mapLabelsAdded; bool _mapLabelsAdded;
int _imageDecimation; int _imagePreDecimation;
int _imagePostDecimation;
float _laserScanDownsampleStepSize; float _laserScanDownsampleStepSize;
bool _reextractLoopClosureFeatures; bool _reextractLoopClosureFeatures;
float _rehearsalMaxDistance; float _rehearsalMaxDistance;
+96
View File
@@ -0,0 +1,96 @@
/*
Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Universite de Sherbrooke nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SRC_OCTOMAP_H_
#define SRC_OCTOMAP_H_
#include "rtabmap/core/RtabmapExp.h" // DLL export/import defines
#include <octomap/ColorOcTree.h>
#include <octomap/OcTreeKey.h>
#include <pcl/pcl_base.h>
#include <pcl/point_types.h>
#include <rtabmap/core/Transform.h>
#include <map>
#include <string>
namespace rtabmap {
class OcTreeNodeInfo
{
public:
OcTreeNodeInfo(int nodeRefId, const octomap::OcTreeKey & key, bool isObstacle) :
nodeRefId_(nodeRefId),
key_(key),
isObstacle_(isObstacle) {}
int nodeRefId_;
octomap::OcTreeKey key_;
bool isObstacle_;
};
class RTABMAP_EXP OctoMap {
public:
OctoMap(float voxelSize = 0.1f);
const std::map<int, Transform> & addedNodes() const {return addedNodes_;}
void addToCache(int nodeId,
pcl::PointCloud<pcl::PointXYZRGB>::Ptr & ground,
pcl::PointCloud<pcl::PointXYZRGB>::Ptr & obstacles);
void update(const std::map<int, Transform> & poses);
const octomap::ColorOcTree * octree() const {return octree_;}
pcl::PointCloud<pcl::PointXYZRGB>::Ptr createCloud(
unsigned int treeDepth = 0,
std::vector<int> * obstacleIndices = 0,
std::vector<int> * emptyIndices = 0) const;
cv::Mat createProjectionMap(
float & xMin,
float & yMin,
float & gridCellSize,
float minGridSize);
bool writeBinary(const std::string & path);
virtual ~OctoMap();
void clear();
private:
std::map<int, std::pair<pcl::PointCloud<pcl::PointXYZRGB>::Ptr, pcl::PointCloud<pcl::PointXYZRGB>::Ptr> > cache_;
octomap::ColorOcTree * octree_;
std::map<octomap::ColorOcTreeNode*, OcTreeNodeInfo> occupiedCells_;
std::map<int, Transform> addedNodes_;
octomap::KeyRay keyRay_;
};
} /* namespace rtabmap */
#endif /* SRC_OCTOMAP_H_ */
+5 -1
View File
@@ -1,5 +1,5 @@
/* /*
Copyright (c) 2010-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
@@ -55,12 +55,14 @@ public:
public: public:
virtual ~Odometry(); virtual ~Odometry();
Transform process(SensorData & data, OdometryInfo * info = 0); Transform process(SensorData & data, OdometryInfo * info = 0);
Transform process(SensorData & data, const Transform & guess, OdometryInfo * info = 0);
virtual void reset(const Transform & initialPose = Transform::getIdentity()); virtual void reset(const Transform & initialPose = Transform::getIdentity());
//getters //getters
const Transform & getPose() const {return _pose;} const Transform & getPose() const {return _pose;}
bool isInfoDataFilled() const {return _fillInfoData;} bool isInfoDataFilled() const {return _fillInfoData;}
const Transform & previousVelocityTransform() const {return previousVelocityTransform_;} const Transform & previousVelocityTransform() const {return previousVelocityTransform_;}
double previousStamp() const {return previousStamp_;}
private: private:
virtual Transform computeTransform(SensorData & data, const Transform & guess = Transform(), OdometryInfo * info = 0) = 0; virtual Transform computeTransform(SensorData & data, const Transform & guess = Transform(), OdometryInfo * info = 0) = 0;
@@ -83,6 +85,8 @@ private:
bool _fillInfoData; bool _fillInfoData;
float _kalmanProcessNoise; float _kalmanProcessNoise;
float _kalmanMeasurementNoise; float _kalmanMeasurementNoise;
int _imageDecimation;
bool _alignWithGround;
Transform _pose; Transform _pose;
int _resetCurrentCount; int _resetCurrentCount;
double previousStamp_; double previousStamp_;
+1 -1
View File
@@ -1,5 +1,5 @@
/* /*
Copyright (c) 2010-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
+2 -2
View File
@@ -1,5 +1,5 @@
/* /*
Copyright (c) 2010-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
@@ -55,7 +55,7 @@ private:
Registration * registrationPipeline_; Registration * registrationPipeline_;
Signature refFrame_; Signature refFrame_;
Transform motionSinceLastKeyFrame_; Transform lastKeyFramePose_;
}; };
} }
+4 -3
View File
@@ -1,5 +1,5 @@
/* /*
Copyright (c) 2010-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
@@ -31,6 +31,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <rtabmap/core/Odometry.h> #include <rtabmap/core/Odometry.h>
#include <pcl/point_cloud.h> #include <pcl/point_cloud.h>
#include <pcl/point_types.h> #include <pcl/point_types.h>
#include <pcl/pcl_base.h>
namespace rtabmap { namespace rtabmap {
@@ -57,13 +58,13 @@ private:
int maxNewFeatures_; int maxNewFeatures_;
float scanKeyFrameThr_; float scanKeyFrameThr_;
int scanMaximumMapSize_; int scanMaximumMapSize_;
float scanSubstractRadius_; float scanSubtractRadius_;
std::string fixedMapPath_; std::string fixedMapPath_;
Registration * regPipeline_; Registration * regPipeline_;
Signature * map_; Signature * map_;
Signature * lastFrame_; Signature * lastFrame_;
std::map<int, pcl::PointCloud<pcl::PointNormal>::Ptr > scansBuffer_; std::vector<std::pair<pcl::PointCloud<pcl::PointNormal>::Ptr, pcl::IndicesPtr> > scansBuffer_;
}; };
} }
+1 -1
View File
@@ -1,5 +1,5 @@
/* /*
Copyright (c) 2010-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
+1 -1
View File
@@ -1,5 +1,5 @@
/* /*
Copyright (c) 2010-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
@@ -1,5 +1,5 @@
/* /*
Copyright (c) 2010-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
+9 -2
View File
@@ -1,5 +1,5 @@
/* /*
Copyright (c) 2010-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
@@ -53,7 +53,7 @@ public:
}; };
static bool isAvailable(Optimizer::Type type); static bool isAvailable(Optimizer::Type type);
static Optimizer * create(const ParametersMap & parameters); static Optimizer * create(const ParametersMap & parameters);
static Optimizer * create(Optimizer::Type & type, const ParametersMap & parameters = ParametersMap()); static Optimizer * create(Optimizer::Type type, const ParametersMap & parameters = ParametersMap());
// Get connected poses and constraints from a set of links // Get connected poses and constraints from a set of links
static void getConnectedGraph( static void getConnectedGraph(
@@ -99,6 +99,13 @@ public:
virtual void parseParameters(const ParametersMap & parameters); virtual void parseParameters(const ParametersMap & parameters);
void computeBACorrespondences(
const std::map<int, Transform> & poses,
const std::multimap<int, Link> & links,
const std::map<int, Signature> & signatures,
std::map<int, cv::Point3f> & points3DMap,
std::map<int, std::map<int, cv::Point2f> > & wordReferences); // <ID words, IDs frames + keypoint>
protected: protected:
Optimizer( Optimizer(
int iterations = Parameters::defaultOptimizerIterations(), int iterations = Parameters::defaultOptimizerIterations(),
+3 -14
View File
@@ -1,5 +1,5 @@
/* /*
Copyright (c) 2010-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
@@ -44,29 +44,18 @@ public:
int iterations = Parameters::defaultOptimizerIterations(), int iterations = Parameters::defaultOptimizerIterations(),
bool slam2d = Parameters::defaultOptimizerSlam2D(), bool slam2d = Parameters::defaultOptimizerSlam2D(),
bool covarianceIgnored = Parameters::defaultOptimizerVarianceIgnored()) : bool covarianceIgnored = Parameters::defaultOptimizerVarianceIgnored()) :
Optimizer(iterations, slam2d, covarianceIgnored), Optimizer(iterations, slam2d, covarianceIgnored) {}
inlierDistance_(0.02),
minInliers_(10){}
OptimizerCVSBA(const ParametersMap & parameters) : OptimizerCVSBA(const ParametersMap & parameters) :
Optimizer(parameters), Optimizer(parameters) {}
inlierDistance_(0.02),
minInliers_(10){}
virtual ~OptimizerCVSBA() {} virtual ~OptimizerCVSBA() {}
virtual Type type() const {return kTypeCVSBA;} virtual Type type() const {return kTypeCVSBA;}
void setInlierDistance(float inlierDistance) {inlierDistance_ = inlierDistance;}
void setMinInliers(int minInliers) {minInliers_ = minInliers;}
virtual std::map<int, Transform> optimizeBA( virtual std::map<int, Transform> optimizeBA(
int rootId, int rootId,
const std::map<int, Transform> & poses, const std::map<int, Transform> & poses,
const std::multimap<int, Link> & links, const std::multimap<int, Link> & links,
const std::map<int, Signature> & signatures); const std::map<int, Signature> & signatures);
private:
float inlierDistance_;
float minInliers_;
}; };
} /* namespace rtabmap */ } /* namespace rtabmap */
+10 -2
View File
@@ -1,5 +1,5 @@
/* /*
Copyright (c) 2010-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
@@ -50,7 +50,8 @@ public:
OptimizerG2O(const ParametersMap & parameters = ParametersMap()) : OptimizerG2O(const ParametersMap & parameters = ParametersMap()) :
Optimizer(parameters), Optimizer(parameters),
solver_(Parameters::defaultg2oSolver()), solver_(Parameters::defaultg2oSolver()),
optimizer_(Parameters::defaultg2oOptimizer()) optimizer_(Parameters::defaultg2oOptimizer()),
pixelVariance_(Parameters::defaultg2oPixelVariance())
{ {
parseParameters(parameters); parseParameters(parameters);
} }
@@ -68,9 +69,16 @@ public:
double * finalError = 0, double * finalError = 0,
int * iterationsDone = 0); int * iterationsDone = 0);
virtual std::map<int, Transform> optimizeBA(
int rootId,
const std::map<int, Transform> & poses,
const std::multimap<int, Link> & links,
const std::map<int, Signature> & signatures);
private: private:
int solver_; int solver_;
int optimizer_; int optimizer_;
double pixelVariance_;
}; };
} /* namespace rtabmap */ } /* namespace rtabmap */
@@ -1,5 +1,5 @@
/* /*
Copyright (c) 2010-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
+1 -1
View File
@@ -1,5 +1,5 @@
/* /*
Copyright (c) 2010-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
+1 -1
View File
@@ -1,5 +1,5 @@
/* /*
Copyright (c) 2010-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
+43 -27
View File
@@ -1,5 +1,5 @@
/* /*
Copyright (c) 2010-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
@@ -172,9 +172,9 @@ class RTABMAP_EXP Parameters
RTABMAP_PARAM(Rtabmap, PublishLastSignature, bool, true, "Publishing last signature."); RTABMAP_PARAM(Rtabmap, PublishLastSignature, bool, true, "Publishing last signature.");
RTABMAP_PARAM(Rtabmap, PublishPdf, bool, true, "Publishing pdf."); RTABMAP_PARAM(Rtabmap, PublishPdf, bool, true, "Publishing pdf.");
RTABMAP_PARAM(Rtabmap, PublishLikelihood, bool, true, "Publishing likelihood."); RTABMAP_PARAM(Rtabmap, PublishLikelihood, bool, true, "Publishing likelihood.");
RTABMAP_PARAM(Rtabmap, TimeThr, float, 0.0, "Maximum time allowed for the detector (ms) (0 means infinity)."); RTABMAP_PARAM(Rtabmap, TimeThr, float, 0, "Maximum time allowed for the detector (ms) (0 means infinity).");
RTABMAP_PARAM(Rtabmap, MemoryThr, int, 0, "Maximum signatures in the Working Memory (ms) (0 means infinity)."); RTABMAP_PARAM(Rtabmap, MemoryThr, int, 0, "Maximum signatures in the Working Memory (ms) (0 means infinity).");
RTABMAP_PARAM(Rtabmap, DetectionRate, float, 1.0, "Detection rate. RTAB-Map will filter input images to satisfy this rate."); RTABMAP_PARAM(Rtabmap, DetectionRate, float, 1, "Detection rate. RTAB-Map will filter input images to satisfy this rate.");
RTABMAP_PARAM(Rtabmap, ImageBufferSize, unsigned int, 1, "Data buffer size (0 min inf)."); RTABMAP_PARAM(Rtabmap, ImageBufferSize, unsigned int, 1, "Data buffer size (0 min inf).");
RTABMAP_PARAM(Rtabmap, CreateIntermediateNodes, bool, false, "Create intermediate nodes between loop closure detection. Only used when Rtabmap/DetectionRate>0."); RTABMAP_PARAM(Rtabmap, CreateIntermediateNodes, bool, false, "Create intermediate nodes between loop closure detection. Only used when Rtabmap/DetectionRate>0.");
RTABMAP_PARAM_STR(Rtabmap, WorkingDirectory, "", "Working directory."); RTABMAP_PARAM_STR(Rtabmap, WorkingDirectory, "", "Working directory.");
@@ -186,7 +186,7 @@ class RTABMAP_EXP Parameters
// Hypotheses selection // Hypotheses selection
RTABMAP_PARAM(Rtabmap, LoopThr, float, 0.11, "Loop closing threshold."); RTABMAP_PARAM(Rtabmap, LoopThr, float, 0.11, "Loop closing threshold.");
RTABMAP_PARAM(Rtabmap, LoopRatio, float, 0.0, "The loop closure hypothesis must be over LoopRatio x lastHypothesisValue."); RTABMAP_PARAM(Rtabmap, LoopRatio, float, 0, "The loop closure hypothesis must be over LoopRatio x lastHypothesisValue.");
// Memory // Memory
RTABMAP_PARAM(Mem, RehearsalSimilarity, float, 0.6, "Rehearsal similarity."); RTABMAP_PARAM(Mem, RehearsalSimilarity, float, 0.6, "Rehearsal similarity.");
@@ -194,7 +194,7 @@ class RTABMAP_EXP Parameters
RTABMAP_PARAM(Mem, BinDataKept, bool, true, "Keep binary data in db."); RTABMAP_PARAM(Mem, BinDataKept, bool, true, "Keep binary data in db.");
RTABMAP_PARAM(Mem, RawDescriptorsKept, bool, true, "Raw descriptors kept in memory."); RTABMAP_PARAM(Mem, RawDescriptorsKept, bool, true, "Raw descriptors kept in memory.");
RTABMAP_PARAM(Mem, MapLabelsAdded, bool, true, "Create map labels. The first node of a map will be labelled as \"map#\" where # is the map ID."); RTABMAP_PARAM(Mem, MapLabelsAdded, bool, true, "Create map labels. The first node of a map will be labelled as \"map#\" where # is the map ID.");
RTABMAP_PARAM(Mem, SaveDepth16Format, bool, true, "Save depth image into 16 bits format to reduce memory used. Warning: values over ~65 meters are ignored (maximum 65535 millimeters)."); RTABMAP_PARAM(Mem, SaveDepth16Format, bool, false, "Save depth image into 16 bits format to reduce memory used. Warning: values over ~65 meters are ignored (maximum 65535 millimeters).");
RTABMAP_PARAM(Mem, NotLinkedNodesKept, bool, true, "Keep not linked nodes in db (rehearsed nodes and deleted nodes)."); RTABMAP_PARAM(Mem, NotLinkedNodesKept, bool, true, "Keep not linked nodes in db (rehearsed nodes and deleted nodes).");
RTABMAP_PARAM(Mem, STMSize, unsigned int, 10, "Short-term memory size."); RTABMAP_PARAM(Mem, STMSize, unsigned int, 10, "Short-term memory size.");
RTABMAP_PARAM(Mem, IncrementalMemory, bool, true, "SLAM mode, otherwise it is Localization mode."); RTABMAP_PARAM(Mem, IncrementalMemory, bool, true, "SLAM mode, otherwise it is Localization mode.");
@@ -206,7 +206,8 @@ class RTABMAP_EXP Parameters
RTABMAP_PARAM(Mem, GenerateIds, bool, true, "True=Generate location IDs, False=use input image IDs."); RTABMAP_PARAM(Mem, GenerateIds, bool, true, "True=Generate location IDs, False=use input image IDs.");
RTABMAP_PARAM(Mem, BadSignaturesIgnored, bool, false, "Bad signatures are ignored."); RTABMAP_PARAM(Mem, BadSignaturesIgnored, bool, false, "Bad signatures are ignored.");
RTABMAP_PARAM(Mem, InitWMWithAllNodes, bool, false, "Initialize the Working Memory with all nodes in Long-Term Memory. When false, it is initialized with nodes of the previous session."); RTABMAP_PARAM(Mem, InitWMWithAllNodes, bool, false, "Initialize the Working Memory with all nodes in Long-Term Memory. When false, it is initialized with nodes of the previous session.");
RTABMAP_PARAM(Mem, ImageDecimation, int, 1, "Image decimation (>=1) when creating a signature."); RTABMAP_PARAM(Mem, ImagePreDecimation, int, 1, "Image decimation (>=1) before features extraction.");
RTABMAP_PARAM(Mem, ImagePostDecimation, int, 1, "Image decimation (>=1) of saved data in created signatures (after features extraction). Decimation is done from the original image.");
RTABMAP_PARAM(Mem, LaserScanDownsampleStepSize, int, 1, "If > 1, downsample the laser scans when creating a signature."); RTABMAP_PARAM(Mem, LaserScanDownsampleStepSize, int, 1, "If > 1, downsample the laser scans when creating a signature.");
RTABMAP_PARAM(Mem, UseOdomFeatures, bool, false, "Use odometry features."); RTABMAP_PARAM(Mem, UseOdomFeatures, bool, false, "Use odometry features.");
@@ -214,15 +215,15 @@ class RTABMAP_EXP Parameters
RTABMAP_PARAM(Kp, NNStrategy, int, 1, "kNNFlannNaive=0, kNNFlannKdTree=1, kNNFlannLSH=2, kNNBruteForce=3, kNNBruteForceGPU=4"); RTABMAP_PARAM(Kp, NNStrategy, int, 1, "kNNFlannNaive=0, kNNFlannKdTree=1, kNNFlannLSH=2, kNNBruteForce=3, kNNBruteForceGPU=4");
RTABMAP_PARAM(Kp, IncrementalDictionary, bool, true, ""); RTABMAP_PARAM(Kp, IncrementalDictionary, bool, true, "");
RTABMAP_PARAM(Kp, IncrementalFlann, bool, true, "When using FLANN based strategy, add/remove points to its index without always rebuilding the index (the index is built only when the dictionary doubles in size)."); RTABMAP_PARAM(Kp, IncrementalFlann, bool, true, "When using FLANN based strategy, add/remove points to its index without always rebuilding the index (the index is built only when the dictionary doubles in size).");
RTABMAP_PARAM(Kp, MaxDepth, float, 0.0, "Filter extracted keypoints by depth (0=inf)."); RTABMAP_PARAM(Kp, MaxDepth, float, 0, "Filter extracted keypoints by depth (0=inf).");
RTABMAP_PARAM(Kp, MinDepth, float, 0.0, "Filter extracted keypoints by depth."); RTABMAP_PARAM(Kp, MinDepth, float, 0, "Filter extracted keypoints by depth.");
RTABMAP_PARAM(Kp, MaxFeatures, int, 400, "Maximum features extracted from the images (0 means not bounded, <0 means no extraction)."); RTABMAP_PARAM(Kp, MaxFeatures, int, 400, "Maximum features extracted from the images (0 means not bounded, <0 means no extraction).");
RTABMAP_PARAM(Kp, BadSignRatio, float, 0.5, "Bad signature ratio (less than Ratio x AverageWordsPerImage = bad)."); RTABMAP_PARAM(Kp, BadSignRatio, float, 0.5, "Bad signature ratio (less than Ratio x AverageWordsPerImage = bad).");
RTABMAP_PARAM(Kp, NndrRatio, float, 0.8, "NNDR ratio (A matching pair is detected, if its distance is closer than X times the distance of the second nearest neighbor.)"); RTABMAP_PARAM(Kp, NndrRatio, float, 0.8, "NNDR ratio (A matching pair is detected, if its distance is closer than X times the distance of the second nearest neighbor.)");
#ifdef RTABMAP_NONFREE #ifdef RTABMAP_NONFREE
RTABMAP_PARAM(Kp, DetectorStrategy, int, 0, "0=SURF 1=SIFT 2=ORB 3=FAST/FREAK 4=FAST/BRIEF 5=GFTT/FREAK 6=GFTT/BRIEF 7=BRISK."); 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 #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 #endif
RTABMAP_PARAM(Kp, TfIdfLikelihoodUsed, bool, true, "Use of the td-idf strategy to compute the likelihood."); RTABMAP_PARAM(Kp, TfIdfLikelihoodUsed, bool, true, "Use of the td-idf strategy to compute the likelihood.");
RTABMAP_PARAM(Kp, Parallelized, bool, true, "If the dictionary update and signature creation were parallelized."); RTABMAP_PARAM(Kp, Parallelized, bool, true, "If the dictionary update and signature creation were parallelized.");
@@ -242,7 +243,7 @@ class RTABMAP_EXP Parameters
// Keypoints descriptors/detectors // Keypoints descriptors/detectors
RTABMAP_PARAM(SURF, Extended, bool, false, "Extended descriptor flag (true - use extended 128-element descriptors; false - use 64-element descriptors)."); RTABMAP_PARAM(SURF, Extended, bool, false, "Extended descriptor flag (true - use extended 128-element descriptors; false - use 64-element descriptors).");
RTABMAP_PARAM(SURF, HessianThreshold, float, 500.0, "Threshold for hessian keypoint detector used in SURF."); RTABMAP_PARAM(SURF, HessianThreshold, float, 500, "Threshold for hessian keypoint detector used in SURF.");
RTABMAP_PARAM(SURF, Octaves, int, 4, "Number of pyramid octaves the keypoint detector will use."); RTABMAP_PARAM(SURF, Octaves, int, 4, "Number of pyramid octaves the keypoint detector will use.");
RTABMAP_PARAM(SURF, OctaveLayers, int, 2, "Number of octave layers within each octave."); RTABMAP_PARAM(SURF, OctaveLayers, int, 2, "Number of octave layers within each octave.");
RTABMAP_PARAM(SURF, Upright, bool, false, "Up-right or rotated features flag (true - do not compute orientation of features; false - compute orientation)."); RTABMAP_PARAM(SURF, Upright, bool, false, "Up-right or rotated features flag (true - do not compute orientation of features; false - compute orientation).");
@@ -252,7 +253,7 @@ class RTABMAP_EXP Parameters
RTABMAP_PARAM(SIFT, NFeatures, int, 0, "The number of best features to retain. The features are ranked by their scores (measured in SIFT algorithm as the local contrast)."); RTABMAP_PARAM(SIFT, NFeatures, int, 0, "The number of best features to retain. The features are ranked by their scores (measured in SIFT algorithm as the local contrast).");
RTABMAP_PARAM(SIFT, NOctaveLayers, int, 3, "The number of layers in each octave. 3 is the value used in D. Lowe paper. The number of octaves is computed automatically from the image resolution."); RTABMAP_PARAM(SIFT, NOctaveLayers, int, 3, "The number of layers in each octave. 3 is the value used in D. Lowe paper. The number of octaves is computed automatically from the image resolution.");
RTABMAP_PARAM(SIFT, ContrastThreshold, double, 0.04, "The contrast threshold used to filter out weak features in semi-uniform (low-contrast) regions. The larger the threshold, the less features are produced by the detector."); RTABMAP_PARAM(SIFT, ContrastThreshold, double, 0.04, "The contrast threshold used to filter out weak features in semi-uniform (low-contrast) regions. The larger the threshold, the less features are produced by the detector.");
RTABMAP_PARAM(SIFT, EdgeThreshold, double, 10.0, "The threshold used to filter out edge-like features. Note that the its meaning is different from the contrastThreshold, i.e. the larger the edgeThreshold, the less features are filtered out (more features are retained)."); RTABMAP_PARAM(SIFT, EdgeThreshold, double, 10, "The threshold used to filter out edge-like features. Note that the its meaning is different from the contrastThreshold, i.e. the larger the edgeThreshold, the less features are filtered out (more features are retained).");
RTABMAP_PARAM(SIFT, Sigma, double, 1.6, "The sigma of the Gaussian applied to the input image at the octave #0. If your image is captured with a weak camera with soft lenses, you might want to reduce the number."); RTABMAP_PARAM(SIFT, Sigma, double, 1.6, "The sigma of the Gaussian applied to the input image at the octave #0. If your image is captured with a weak camera with soft lenses, you might want to reduce the number.");
RTABMAP_PARAM(BRIEF, Bytes, int, 32, "Bytes is a length of descriptor in bytes. It can be equal 16, 32 or 64 bytes."); RTABMAP_PARAM(BRIEF, Bytes, int, 32, "Bytes is a length of descriptor in bytes. It can be equal 16, 32 or 64 bytes.");
@@ -283,12 +284,12 @@ class RTABMAP_EXP Parameters
RTABMAP_PARAM(FREAK, OrientationNormalized, bool, true, "Enable orientation normalization."); RTABMAP_PARAM(FREAK, OrientationNormalized, bool, true, "Enable orientation normalization.");
RTABMAP_PARAM(FREAK, ScaleNormalized, bool, true, "Enable scale normalization."); RTABMAP_PARAM(FREAK, ScaleNormalized, bool, true, "Enable scale normalization.");
RTABMAP_PARAM(FREAK, PatternScale, float, 22.0, "Scaling of the description pattern."); RTABMAP_PARAM(FREAK, PatternScale, float, 22, "Scaling of the description pattern.");
RTABMAP_PARAM(FREAK, NOctaves, int, 4, "Number of octaves covered by the detected keypoints."); RTABMAP_PARAM(FREAK, NOctaves, int, 4, "Number of octaves covered by the detected keypoints.");
RTABMAP_PARAM(BRISK, Thresh, int, 30, "FAST/AGAST detection threshold score."); RTABMAP_PARAM(BRISK, Thresh, int, 30, "FAST/AGAST detection threshold score.");
RTABMAP_PARAM(BRISK, Octaves, int, 3, "Detection octaves. Use 0 to do single scale."); RTABMAP_PARAM(BRISK, Octaves, int, 3, "Detection octaves. Use 0 to do single scale.");
RTABMAP_PARAM(BRISK, PatternScale, float, 1.0, "Apply this scale to the pattern used for sampling the neighbourhood of a keypoint."); RTABMAP_PARAM(BRISK, PatternScale, float, 1, "Apply this scale to the pattern used for sampling the neighbourhood of a keypoint.");
// BayesFilter // BayesFilter
RTABMAP_PARAM(Bayes, VirtualPlacePriorThr, float, 0.9, "Virtual place prior"); RTABMAP_PARAM(Bayes, VirtualPlacePriorThr, float, 0.9, "Virtual place prior");
@@ -297,7 +298,7 @@ class RTABMAP_EXP Parameters
// Verify hypotheses // Verify hypotheses
RTABMAP_PARAM(VhEp, MatchCountMin, int, 8, "Minimum of matching visual words pairs to accept the loop hypothesis."); RTABMAP_PARAM(VhEp, MatchCountMin, int, 8, "Minimum of matching visual words pairs to accept the loop hypothesis.");
RTABMAP_PARAM(VhEp, RansacParam1, float, 3.0, "Fundamental matrix (see cvFindFundamentalMat()): Max distance (in pixels) from the epipolar line for a point to be inlier."); RTABMAP_PARAM(VhEp, RansacParam1, float, 3, "Fundamental matrix (see cvFindFundamentalMat()): Max distance (in pixels) from the epipolar line for a point to be inlier.");
RTABMAP_PARAM(VhEp, RansacParam2, float, 0.99, "Fundamental matrix (see cvFindFundamentalMat()): Performance of the RANSAC."); RTABMAP_PARAM(VhEp, RansacParam2, float, 0.99, "Fundamental matrix (see cvFindFundamentalMat()): Performance of the RANSAC.");
// RGB-D SLAM // RGB-D SLAM
@@ -306,11 +307,11 @@ class RTABMAP_EXP Parameters
RTABMAP_PARAM(RGBD, AngularUpdate, float, 0.1, "Minimum angular displacement to update the map. Rehearsal is done prior to this, so weights are still updated."); RTABMAP_PARAM(RGBD, AngularUpdate, float, 0.1, "Minimum angular displacement to update the map. Rehearsal is done prior to this, so weights are still updated.");
RTABMAP_PARAM(RGBD, NewMapOdomChangeDistance, float, 0, "A new map is created if a change of odometry translation greater than X m is detected (0 m = disabled)."); RTABMAP_PARAM(RGBD, NewMapOdomChangeDistance, float, 0, "A new map is created if a change of odometry translation greater than X m is detected (0 m = disabled).");
RTABMAP_PARAM(RGBD, OptimizeFromGraphEnd, bool, false, "Optimize graph from the newest node. If false, the graph is optimized from the oldest node of the current graph (this adds an overhead computation to detect to oldest mode of the current graph, but it can be useful to preserve the map referential from the oldest node). Warning when set to false: when some nodes are transferred, the first referential of the local map may change, resulting in momentary changes in robot/map position (which are annoying in teleoperation)."); RTABMAP_PARAM(RGBD, OptimizeFromGraphEnd, bool, false, "Optimize graph from the newest node. If false, the graph is optimized from the oldest node of the current graph (this adds an overhead computation to detect to oldest mode of the current graph, but it can be useful to preserve the map referential from the oldest node). Warning when set to false: when some nodes are transferred, the first referential of the local map may change, resulting in momentary changes in robot/map position (which are annoying in teleoperation).");
RTABMAP_PARAM(RGBD, OptimizeMaxError, float, 1.0, "Reject loop closures if optimization error is greater than this value (0=disabled). This will help to detect when a wrong loop closure is added to the graph. Not compatible with \"Optimizer/Robust\" if enabled."); RTABMAP_PARAM(RGBD, OptimizeMaxError, float, 1, "Reject loop closures if optimization error is greater than this value (0=disabled). This will help to detect when a wrong loop closure is added to the graph. Not compatible with \"Optimizer/Robust\" if enabled.");
RTABMAP_PARAM(RGBD, GoalReachedRadius, float, 0.5, "Goal reached radius (m)."); RTABMAP_PARAM(RGBD, GoalReachedRadius, float, 0.5, "Goal reached radius (m).");
RTABMAP_PARAM(RGBD, PlanStuckIterations, int, 0, "Mark the current goal node on the path as unreachable if it is not updated after X iterations (0=disabled). If all upcoming nodes on the path are unreachabled, the plan fails."); RTABMAP_PARAM(RGBD, PlanStuckIterations, int, 0, "Mark the current goal node on the path as unreachable if it is not updated after X iterations (0=disabled). If all upcoming nodes on the path are unreachabled, the plan fails.");
RTABMAP_PARAM(RGBD, PlanLinearVelocity, float, 0.0, "Linear velocity (m/sec) used to compute path weights."); RTABMAP_PARAM(RGBD, PlanLinearVelocity, float, 0, "Linear velocity (m/sec) used to compute path weights.");
RTABMAP_PARAM(RGBD, PlanAngularVelocity, float, 0.0, "Angular velocity (rad/sec) used to compute path weights."); RTABMAP_PARAM(RGBD, PlanAngularVelocity, float, 0, "Angular velocity (rad/sec) used to compute path weights.");
RTABMAP_PARAM(RGBD, GoalsSavedInUserData, bool, false, "When a goal is received and processed with success, it is saved in user data of the location with this format: \"GOAL:#\"."); RTABMAP_PARAM(RGBD, GoalsSavedInUserData, bool, false, "When a goal is received and processed with success, it is saved in user data of the location with this format: \"GOAL:#\".");
RTABMAP_PARAM(RGBD, MaxLocalRetrieved, unsigned int, 2, "Maximum local locations retrieved (0=disabled) near the current pose in the local map or on the current planned path (those on the planned path have priority)."); RTABMAP_PARAM(RGBD, MaxLocalRetrieved, unsigned int, 2, "Maximum local locations retrieved (0=disabled) near the current pose in the local map or on the current planned path (those on the planned path have priority).");
RTABMAP_PARAM(RGBD, LocalRadius, float, 10, "Local radius (m) for nodes selection in the local map. This parameter is used in some approaches about the local map management."); RTABMAP_PARAM(RGBD, LocalRadius, float, 10, "Local radius (m) for nodes selection in the local map. This parameter is used in some approaches about the local map management.");
@@ -322,11 +323,10 @@ class RTABMAP_EXP Parameters
// Local/Proximity loop closure detection // Local/Proximity loop closure detection
RTABMAP_PARAM(RGBD, ProximityByTime, bool, false, "Detection over all locations in STM."); 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, 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, 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, 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."); 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.");
RTABMAP_PARAM(RGBD, ProximityAngle, float, 45.0, "Maximum angle (degrees) for visual proximity detection."); RTABMAP_PARAM(RGBD, ProximityAngle, float, 45, "Maximum angle (degrees) for visual proximity detection.");
// Graph optimization // Graph optimization
#ifdef RTABMAP_GTSAM #ifdef RTABMAP_GTSAM
@@ -346,6 +346,7 @@ class RTABMAP_EXP Parameters
RTABMAP_PARAM(g2o, Solver, int, 0, "0=csparse 1=pcg 2=cholmod"); RTABMAP_PARAM(g2o, Solver, int, 0, "0=csparse 1=pcg 2=cholmod");
RTABMAP_PARAM(g2o, Optimizer, int, 0, "0=Levenberg 1=GaussNewton"); RTABMAP_PARAM(g2o, Optimizer, int, 0, "0=Levenberg 1=GaussNewton");
RTABMAP_PARAM(g2o, PixelVariance, double, 1, "Pixel variance used for SBA.");
// Odometry // Odometry
RTABMAP_PARAM(Odom, Strategy, int, 0, "0=Frame-to-Map (F2M) 1=Frame-to-Frame (F2F)"); RTABMAP_PARAM(Odom, Strategy, int, 0, "0=Frame-to-Map (F2M) 1=Frame-to-Frame (F2F)");
@@ -364,12 +365,14 @@ class RTABMAP_EXP Parameters
RTABMAP_PARAM(Odom, GuessMotion, bool, false, "Guess next transformation from the last motion computed."); RTABMAP_PARAM(Odom, GuessMotion, bool, false, "Guess next transformation from the last motion computed.");
RTABMAP_PARAM(Odom, KeyFrameThr, float, 0.3, "[Visual] Create a new keyframe when the number of inliers drops under this ratio of features in last frame. Setting the value to 0 means that a keyframe is created for each processed frame."); RTABMAP_PARAM(Odom, KeyFrameThr, float, 0.3, "[Visual] Create a new keyframe when the number of inliers drops under this ratio of features in last frame. Setting the value to 0 means that a keyframe is created for each processed frame.");
RTABMAP_PARAM(Odom, ScanKeyFrameThr, float, 0.7, "[Geometry] Create a new keyframe when the number of ICP inliers drops under this ratio of points in last frame's scan. Setting the value to 0 means that a keyframe is created for each processed frame."); RTABMAP_PARAM(Odom, ScanKeyFrameThr, float, 0.7, "[Geometry] Create a new keyframe when the number of ICP inliers drops under this ratio of points in last frame's scan. Setting the value to 0 means that a keyframe is created for each processed frame.");
RTABMAP_PARAM(Odom, ImageDecimation, int, 1, "Decimation of the images before registration.");
RTABMAP_PARAM(Odom, AlignWithGround, bool, false, "Align odometry with the ground on initialization.");
// Odometry Bag-of-words // Odometry Bag-of-words
RTABMAP_PARAM(OdomF2M, MaxSize, int, 2000, "[Visual] Local map size: If > 0 (example 5000), the odometry will maintain a local map of X maximum words."); RTABMAP_PARAM(OdomF2M, MaxSize, int, 2000, "[Visual] Local map size: If > 0 (example 5000), the odometry will maintain a local map of X maximum words.");
RTABMAP_PARAM(OdomF2M, MaxNewFeatures, int, 0, "[Visual] Maximum features (sorted by keypoint response) added to local map from a new key-frame. 0 means no limit."); RTABMAP_PARAM(OdomF2M, MaxNewFeatures, int, 0, "[Visual] Maximum features (sorted by keypoint response) added to local map from a new key-frame. 0 means no limit.");
RTABMAP_PARAM(OdomF2M, ScanMaxSize, int, 2000, "[Geometry] Maximum local scan map size."); RTABMAP_PARAM(OdomF2M, ScanMaxSize, int, 2000, "[Geometry] Maximum local scan map size.");
RTABMAP_PARAM(OdomF2M, ScanSubstractRadius, float, 0.05, "[Geometry] Radius used to filter points of a new added scan to local map. This could match the voxel size of the scans."); RTABMAP_PARAM(OdomF2M, ScanSubtractRadius, float, 0.05, "[Geometry] Radius used to filter points of a new added scan to local map. This could match the voxel size of the scans.");
RTABMAP_PARAM_STR(OdomF2M, FixedMapPath, "", "Path to a fixed map (RTAB-Map's database) to be used for odometry. Odometry will be constraint to this map. RGB-only images can be used if odometry PnP estimation is used.") RTABMAP_PARAM_STR(OdomF2M, FixedMapPath, "", "Path to a fixed map (RTAB-Map's database) to be used for odometry. Odometry will be constraint to this map. RGB-only images can be used if odometry PnP estimation is used.")
// Odometry Mono // Odometry Mono
@@ -388,16 +391,26 @@ class RTABMAP_EXP Parameters
RTABMAP_PARAM(Vis, ForwardEstOnly, bool, true, "Forward estimation only (A->B). If false, a transformation is also computed in backward direction (B->A), then the two resulting transforms are merged (middle interpolation between the transforms)."); RTABMAP_PARAM(Vis, ForwardEstOnly, bool, true, "Forward estimation only (A->B). If false, a transformation is also computed in backward direction (B->A), then the two resulting transforms are merged (middle interpolation between the transforms).");
RTABMAP_PARAM(Vis, InlierDistance, float, 0.1, "[Vis/EstimationType = 0] Maximum distance for feature correspondences. Used by 3D->3D estimation approach."); RTABMAP_PARAM(Vis, InlierDistance, float, 0.1, "[Vis/EstimationType = 0] Maximum distance for feature correspondences. Used by 3D->3D estimation approach.");
RTABMAP_PARAM(Vis, RefineIterations, int, 5, "[Vis/EstimationType = 0] Number of iterations used to refine the transformation found by RANSAC. 0 means that the transformation is not refined."); RTABMAP_PARAM(Vis, RefineIterations, int, 5, "[Vis/EstimationType = 0] Number of iterations used to refine the transformation found by RANSAC. 0 means that the transformation is not refined.");
RTABMAP_PARAM(Vis, PnPReprojError, float, 2.0, "[Vis/EstimationType = 1] PnP reprojection error."); RTABMAP_PARAM(Vis, PnPReprojError, float, 2, "[Vis/EstimationType = 1] PnP reprojection error.");
RTABMAP_PARAM(Vis, PnPFlags, int, 1, "[Vis/EstimationType = 1] PnP flags: 0=Iterative, 1=EPNP, 2=P3P"); RTABMAP_PARAM(Vis, PnPFlags, int, 1, "[Vis/EstimationType = 1] PnP flags: 0=Iterative, 1=EPNP, 2=P3P");
RTABMAP_PARAM(Vis, PnPRefineIterations, int, 1, "[Vis/EstimationType = 1] Refine iterations."); RTABMAP_PARAM(Vis, PnPRefineIterations, int, 1, "[Vis/EstimationType = 1] Refine iterations.");
RTABMAP_PARAM(Vis, EpipolarGeometryVar, float, 0.02, "[Vis/EstimationType = 2] Epipolar geometry maximum variance to accept the transformation."); 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, 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, 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, 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, MaxDepth, float, 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)."); RTABMAP_PARAM(Vis, MinDepth, float, 0, "Min depth of the features (0 means no limit).");
RTABMAP_PARAM_STR(Vis, RoiRatios, "0.0 0.0 0.0 0.0", "Region of interest ratios [left, right, top, bottom]."); RTABMAP_PARAM_STR(Vis, RoiRatios, "0.0 0.0 0.0 0.0", "Region of interest ratios [left, right, top, bottom].");
RTABMAP_PARAM(Vis, SubPixWinSize, int, 3, "See cv::cornerSubPix()."); RTABMAP_PARAM(Vis, SubPixWinSize, int, 3, "See cv::cornerSubPix().");
RTABMAP_PARAM(Vis, SubPixIterations, int, 0, "See cv::cornerSubPix(). 0 disables sub pixel refining."); RTABMAP_PARAM(Vis, SubPixIterations, int, 0, "See cv::cornerSubPix(). 0 disables sub pixel refining.");
@@ -418,7 +431,7 @@ class RTABMAP_EXP Parameters
RTABMAP_PARAM(Icp, DownsamplingStep, int, 1, "Downsampling step size (1=no sampling). This is done before uniform sampling."); RTABMAP_PARAM(Icp, DownsamplingStep, int, 1, "Downsampling step size (1=no sampling). This is done before uniform sampling.");
RTABMAP_PARAM(Icp, MaxCorrespondenceDistance, float, 0.05, "Max distance for point correspondences."); RTABMAP_PARAM(Icp, MaxCorrespondenceDistance, float, 0.05, "Max distance for point correspondences.");
RTABMAP_PARAM(Icp, Iterations, int, 30, "Max iterations."); RTABMAP_PARAM(Icp, Iterations, int, 30, "Max iterations.");
RTABMAP_PARAM(Icp, Epsilon, float, 0.0, "Set the transformation epsilon (maximum allowable difference between two consecutive transformations) in order for an optimization to be considered as having converged to the final solution."); RTABMAP_PARAM(Icp, Epsilon, float, 0, "Set the transformation epsilon (maximum allowable difference between two consecutive transformations) in order for an optimization to be considered as having converged to the final solution.");
RTABMAP_PARAM(Icp, CorrespondenceRatio, float, 0.2, "Ratio of matching correspondences to accept the transform."); RTABMAP_PARAM(Icp, CorrespondenceRatio, float, 0.2, "Ratio of matching correspondences to accept the transform.");
RTABMAP_PARAM(Icp, PointToPlane, bool, false, "Use point to plane ICP."); RTABMAP_PARAM(Icp, PointToPlane, bool, false, "Use point to plane ICP.");
RTABMAP_PARAM(Icp, PointToPlaneNormalNeighbors, int, 20, "Number of neighbors to compute normals for point to plane."); RTABMAP_PARAM(Icp, PointToPlaneNormalNeighbors, int, 20, "Number of neighbors to compute normals for point to plane.");
@@ -429,7 +442,7 @@ class RTABMAP_EXP Parameters
RTABMAP_PARAM(Stereo, Iterations, int, 30, "Maximum iterations."); RTABMAP_PARAM(Stereo, Iterations, int, 30, "Maximum iterations.");
RTABMAP_PARAM(Stereo, MaxLevel, int, 3, "Maximum pyramid level."); RTABMAP_PARAM(Stereo, MaxLevel, int, 3, "Maximum pyramid level.");
RTABMAP_PARAM(Stereo, MinDisparity, int, 1, "Minimum disparity."); RTABMAP_PARAM(Stereo, MinDisparity, int, 1, "Minimum disparity.");
RTABMAP_PARAM(Stereo, MaxDisparity, int, 64, "Maximum disparity."); RTABMAP_PARAM(Stereo, MaxDisparity, int, 128, "Maximum disparity.");
RTABMAP_PARAM(Stereo, OpticalFlow, bool, true, "Use optical flow to find stereo correspondences, otherwise a simple block matching approach is used."); RTABMAP_PARAM(Stereo, OpticalFlow, bool, true, "Use optical flow to find stereo correspondences, otherwise a simple block matching approach is used.");
RTABMAP_PARAM(Stereo, SSD, bool, true, "[Stereo/OpticalFlow = false] Use Sum of Squared Differences (SSD) window, otherwise Sum of Absolute Differences (SAD) window is used."); RTABMAP_PARAM(Stereo, SSD, bool, true, "[Stereo/OpticalFlow = false] Use Sum of Squared Differences (SSD) window, otherwise Sum of Absolute Differences (SAD) window is used.");
RTABMAP_PARAM(Stereo, Eps, double, 0.01, "[Stereo/OpticalFlow = true] Epsilon stop criterion."); RTABMAP_PARAM(Stereo, Eps, double, 0.01, "[Stereo/OpticalFlow = true] Epsilon stop criterion.");
@@ -482,6 +495,9 @@ public:
static std::string getVersion(); static std::string getVersion();
static std::string getDefaultDatabaseName(); static std::string getDefaultDatabaseName();
static std::string serialize(const ParametersMap & parameters);
static ParametersMap deserialize(const std::string & parameters);
static bool isFeatureParameter(const std::string & param); static bool isFeatureParameter(const std::string & param);
static ParametersMap getDefaultOdometryParameters(bool stereo = false); static ParametersMap getDefaultOdometryParameters(bool stereo = false);
static ParametersMap getDefaultParameters(const std::string & group); static ParametersMap getDefaultParameters(const std::string & group);
@@ -1,5 +1,5 @@
/* /*
Copyright (c) 2010-2015, Mathieu Labbe - IntRoLab - Universite de Sherbrooke Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
+1 -1
View File
@@ -1,5 +1,5 @@
/* /*
Copyright (c) 2010-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
@@ -1,5 +1,5 @@
/* /*
Copyright (c) 2010-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
@@ -1,9 +1,29 @@
/* /*
* RegistrationInfo.h Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
* All rights reserved.
* Created on: Jan 5, 2016
* Author: mathieu Redistribution and use in source and binary forms, with or without
*/ modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Universite de Sherbrooke nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef REGISTRATIONINFO_H_ #ifndef REGISTRATIONINFO_H_
#define REGISTRATIONINFO_H_ #define REGISTRATIONINFO_H_
@@ -18,7 +38,9 @@ public:
variance(0), variance(0),
inliers(0), inliers(0),
matches(0), matches(0),
icpInliersRatio(0) icpInliersRatio(0),
icpTranslation(0.0f),
icpRotation(0.0f)
{ {
} }
@@ -33,6 +55,8 @@ public:
// RegistrationIcp // RegistrationIcp
float icpInliersRatio; float icpInliersRatio;
float icpTranslation;
float icpRotation;
}; };
} }
@@ -1,5 +1,5 @@
/* /*
Copyright (c) 2010-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
+5 -2
View File
@@ -1,5 +1,5 @@
/* /*
Copyright (c) 2010-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
@@ -70,6 +70,7 @@ public:
void close(bool databaseSaved = true); void close(bool databaseSaved = true);
const std::string & getWorkingDir() const {return _wDir;} const std::string & getWorkingDir() const {return _wDir;}
bool isRGBDMode() const { return _rgbdSlamMode; }
int getLoopClosureId() const {return _loopClosureHypothesis.first;} int getLoopClosureId() const {return _loopClosureHypothesis.first;}
float getLoopClosureValue() const {return _loopClosureHypothesis.second;} float getLoopClosureValue() const {return _loopClosureHypothesis.second;}
int getHighestHypothesisId() const {return _highestHypothesis.first;} int getHighestHypothesisId() const {return _highestHypothesis.first;}
@@ -115,6 +116,7 @@ public:
const ParametersMap & getParameters() const {return _parameters;} const ParametersMap & getParameters() const {return _parameters;}
void setWorkingDirectory(std::string path); void setWorkingDirectory(std::string path);
void rejectLoopClosure(int oldId, int newId); void rejectLoopClosure(int oldId, int newId);
void setOptimizedPoses(const std::map<int, Transform> & poses);
void get3DMap(std::map<int, Signature> & signatures, void get3DMap(std::map<int, Signature> & signatures,
std::map<int, Transform> & poses, std::map<int, Transform> & poses,
std::multimap<int, Link> & constraints, std::multimap<int, Link> & constraints,
@@ -125,6 +127,7 @@ public:
bool optimized, bool optimized,
bool global, bool global,
std::map<int, Signature> * signatures = 0); std::map<int, Signature> * signatures = 0);
int detectMoreLoopClosures(float clusterRadius = 0.5f, float clusterAngle = M_PI/6.0f, int iterations = 1);
int getPathStatus() const {return _pathStatus;} // -1=failed 0=idle/executing 1=success int getPathStatus() const {return _pathStatus;} // -1=failed 0=idle/executing 1=success
void clearPath(int status); // -1=failed 0=idle/executing 1=success void clearPath(int status); // -1=failed 0=idle/executing 1=success
@@ -194,7 +197,6 @@ private:
int _proximityMaxGraphDepth; int _proximityMaxGraphDepth;
float _proximityFilteringRadius; float _proximityFilteringRadius;
bool _proximityRawPosesUsed; bool _proximityRawPosesUsed;
bool _proximityScansMerged;
float _proximityAngle; float _proximityAngle;
std::string _databasePath; std::string _databasePath;
bool _optimizeFromGraphEnd; bool _optimizeFromGraphEnd;
@@ -244,6 +246,7 @@ private:
unsigned int _pathGoalIndex; unsigned int _pathGoalIndex;
Transform _pathTransformToGoal; Transform _pathTransformToGoal;
int _pathStuckCount; int _pathStuckCount;
float _pathStuckDistance;
}; };
+1 -1
View File
@@ -1,5 +1,5 @@
/* /*
Copyright (c) 2010-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
+1 -1
View File
@@ -1,5 +1,5 @@
/* /*
Copyright (c) 2010-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
+1 -1
View File
@@ -1,5 +1,5 @@
/* /*
Copyright (c) 2010-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
+3 -1
View File
@@ -1,5 +1,5 @@
/* /*
Copyright (c) 2010-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
@@ -194,6 +194,8 @@ public:
void setGroundTruth(const Transform & pose) {groundTruth_ = pose;} void setGroundTruth(const Transform & pose) {groundTruth_ = pose;}
const Transform & groundTruth() const {return groundTruth_;} const Transform & groundTruth() const {return groundTruth_;}
long getMemoryUsed() const; // Return memory usage in Bytes
private: private:
int _id; int _id;
double _stamp; double _stamp;
+1 -1
View File
@@ -1,5 +1,5 @@
/* /*
Copyright (c) 2010-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
+4 -1
View File
@@ -1,5 +1,5 @@
/* /*
Copyright (c) 2010-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
@@ -145,6 +145,7 @@ public:
void setRefImageId(int refImageId) {_refImageId = refImageId;} void setRefImageId(int refImageId) {_refImageId = refImageId;}
void setLoopClosureId(int loopClosureId) {_loopClosureId = loopClosureId;} void setLoopClosureId(int loopClosureId) {_loopClosureId = loopClosureId;}
void setProximityDetectionId(int id) {_proximiyDetectionId = id;} void setProximityDetectionId(int id) {_proximiyDetectionId = id;}
void setStamp(double stamp) {_stamp = stamp;}
void setSignatures(const std::map<int, Signature> & signatures) {_signatures = signatures;} void setSignatures(const std::map<int, Signature> & signatures) {_signatures = signatures;}
@@ -165,6 +166,7 @@ public:
int refImageId() const {return _refImageId;} int refImageId() const {return _refImageId;}
int loopClosureId() const {return _loopClosureId;} int loopClosureId() const {return _loopClosureId;}
int proximityDetectionId() const {return _proximiyDetectionId;} int proximityDetectionId() const {return _proximiyDetectionId;}
double stamp() const {return _stamp;}
const std::map<int, Signature> & getSignatures() const {return _signatures;} const std::map<int, Signature> & getSignatures() const {return _signatures;}
@@ -188,6 +190,7 @@ private:
int _refImageId; int _refImageId;
int _loopClosureId; int _loopClosureId;
int _proximiyDetectionId; int _proximiyDetectionId;
double _stamp;
std::map<int, Signature> _signatures; std::map<int, Signature> _signatures;
+1 -1
View File
@@ -1,5 +1,5 @@
/* /*
Copyright (c) 2010-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
@@ -1,5 +1,5 @@
/* /*
Copyright (c) 2010-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
+1 -1
View File
@@ -1,5 +1,5 @@
/* /*
Copyright (c) 2010-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
+1 -1
View File
@@ -1,5 +1,5 @@
/* /*
Copyright (c) 2010-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
+1 -1
View File
@@ -1,5 +1,5 @@
/* /*
Copyright (c) 2010-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
+1 -1
View File
@@ -1,5 +1,5 @@
/* /*
Copyright (c) 2010-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
+1 -1
View File
@@ -1,5 +1,5 @@
/* /*
Copyright (c) 2010-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
@@ -1,9 +1,29 @@
/* /*
* util3d_mapping.hpp Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
* All rights reserved.
* Created on: 2015-05-13
* Author: mathieu Redistribution and use in source and binary forms, with or without
*/ modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Universite de Sherbrooke nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef UTIL3D_MAPPING_HPP_ #ifndef UTIL3D_MAPPING_HPP_
#define UTIL3D_MAPPING_HPP_ #define UTIL3D_MAPPING_HPP_
@@ -17,19 +37,40 @@
namespace rtabmap{ namespace rtabmap{
namespace util3d{ namespace util3d{
template<typename PointT>
typename pcl::PointCloud<PointT>::Ptr projectCloudOnXYPlane(
const typename pcl::PointCloud<PointT> & cloud)
{
typename pcl::PointCloud<PointT>::Ptr output(new pcl::PointCloud<PointT>);
*output = cloud;
for(unsigned int i=0; i<output->size(); ++i)
{
output->at(i).z = 0;
}
return output;
}
template<typename PointT> template<typename PointT>
void segmentObstaclesFromGround( void segmentObstaclesFromGround(
const typename pcl::PointCloud<PointT>::Ptr & cloud, const typename pcl::PointCloud<PointT>::Ptr & cloud,
const typename pcl::IndicesPtr & indices, const typename pcl::IndicesPtr & indices,
pcl::IndicesPtr & ground, pcl::IndicesPtr & ground,
pcl::IndicesPtr & obstacles, pcl::IndicesPtr & obstacles,
float normalRadiusSearch, int normalKSearch,
float groundNormalAngle, float groundNormalAngle,
float clusterRadius,
int minClusterSize, int minClusterSize,
bool segmentFlatObstacles) bool segmentFlatObstacles,
float maxGroundHeight,
pcl::IndicesPtr * flatObstacles,
const Eigen::Vector4f & viewPoint)
{ {
ground.reset(new std::vector<int>); ground.reset(new std::vector<int>);
obstacles.reset(new std::vector<int>); obstacles.reset(new std::vector<int>);
if(flatObstacles)
{
flatObstacles->reset(new std::vector<int>);
}
if(cloud->size()) if(cloud->size())
{ {
@@ -39,8 +80,8 @@ void segmentObstaclesFromGround(
indices, indices,
groundNormalAngle, groundNormalAngle,
Eigen::Vector4f(0,0,1,0), Eigen::Vector4f(0,0,1,0),
normalRadiusSearch*2.0f, normalKSearch,
Eigen::Vector4f(0,0,100,0)); viewPoint);
if(segmentFlatObstacles) if(segmentFlatObstacles)
{ {
@@ -48,27 +89,47 @@ void segmentObstaclesFromGround(
std::vector<pcl::IndicesPtr> clusteredFlatSurfaces = extractClusters( std::vector<pcl::IndicesPtr> clusteredFlatSurfaces = extractClusters(
cloud, cloud,
flatSurfaces, flatSurfaces,
normalRadiusSearch*2.0f, clusterRadius,
minClusterSize, minClusterSize,
std::numeric_limits<int>::max(), std::numeric_limits<int>::max(),
&biggestFlatSurfaceIndex); &biggestFlatSurfaceIndex);
// cluster all surfaces for which the centroid is in the Z-range of the bigger surface // cluster all surfaces for which the centroid is in the Z-range of the bigger surface
if(clusteredFlatSurfaces.size())
{
ground = clusteredFlatSurfaces.at(biggestFlatSurfaceIndex); ground = clusteredFlatSurfaces.at(biggestFlatSurfaceIndex);
Eigen::Vector4f min,max; Eigen::Vector4f min,max;
pcl::getMinMax3D(*cloud, *clusteredFlatSurfaces.at(biggestFlatSurfaceIndex), min, max); pcl::getMinMax3D(*cloud, *clusteredFlatSurfaces.at(biggestFlatSurfaceIndex), min, max);
if(maxGroundHeight <= 0 || min[2] < maxGroundHeight)
{
for(unsigned int i=0; i<clusteredFlatSurfaces.size(); ++i) for(unsigned int i=0; i<clusteredFlatSurfaces.size(); ++i)
{ {
if((int)i!=biggestFlatSurfaceIndex) if((int)i!=biggestFlatSurfaceIndex)
{ {
Eigen::Vector4f centroid; Eigen::Vector4f centroid;
pcl::compute3DCentroid(*cloud, *clusteredFlatSurfaces.at(i), 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)); ground = util3d::concatenate(ground, clusteredFlatSurfaces.at(i));
} }
else if(flatObstacles)
{
*flatObstacles = util3d::concatenate(*flatObstacles, clusteredFlatSurfaces.at(i));
}
}
}
}
else
{
// reject ground!
ground.reset(new std::vector<int>);
if(flatObstacles)
{
*flatObstacles = flatSurfaces;
}
} }
} }
} }
@@ -82,17 +143,26 @@ void segmentObstaclesFromGround(
// Remove ground // Remove ground
pcl::IndicesPtr otherStuffIndices = util3d::extractIndices(cloud, ground, true); pcl::IndicesPtr otherStuffIndices = util3d::extractIndices(cloud, ground, true);
// 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());
}
//Cluster remaining stuff (obstacles) //Cluster remaining stuff (obstacles)
if(otherStuffIndices->size())
{
std::vector<pcl::IndicesPtr> clusteredObstaclesSurfaces = util3d::extractClusters( std::vector<pcl::IndicesPtr> clusteredObstaclesSurfaces = util3d::extractClusters(
cloud, cloud,
otherStuffIndices, otherStuffIndices,
normalRadiusSearch*2.0f, clusterRadius,
minClusterSize); minClusterSize);
// merge indices // merge indices
obstacles = util3d::concatenate(clusteredObstaclesSurfaces); obstacles = util3d::concatenate(clusteredObstaclesSurfaces);
} }
} }
}
} }
template<typename PointT> template<typename PointT>
@@ -100,10 +170,14 @@ void segmentObstaclesFromGround(
const typename pcl::PointCloud<PointT>::Ptr & cloud, const typename pcl::PointCloud<PointT>::Ptr & cloud,
pcl::IndicesPtr & ground, pcl::IndicesPtr & ground,
pcl::IndicesPtr & obstacles, pcl::IndicesPtr & obstacles,
float normalRadiusSearch, int normalKSearch,
float groundNormalAngle, float groundNormalAngle,
float clusterRadius,
int minClusterSize, int minClusterSize,
bool segmentFlatObstacles) bool segmentFlatObstacles,
float maxGroundHeight,
pcl::IndicesPtr * flatObstacles,
const Eigen::Vector4f & viewPoint)
{ {
pcl::IndicesPtr indices(new std::vector<int>); pcl::IndicesPtr indices(new std::vector<int>);
segmentObstaclesFromGround<PointT>( segmentObstaclesFromGround<PointT>(
@@ -111,10 +185,87 @@ void segmentObstaclesFromGround(
indices, indices,
ground, ground,
obstacles, obstacles,
normalRadiusSearch, normalKSearch,
groundNormalAngle, groundNormalAngle,
clusterRadius,
minClusterSize, minClusterSize,
segmentFlatObstacles); segmentFlatObstacles,
maxGroundHeight,
flatObstacles,
viewPoint);
}
template<typename PointT>
void occupancy2DFromGroundObstacles(
const typename pcl::PointCloud<PointT>::Ptr & cloud,
const pcl::IndicesPtr & groundIndices,
const pcl::IndicesPtr & obstaclesIndices,
cv::Mat & ground,
cv::Mat & obstacles,
float cellSize)
{
typename pcl::PointCloud<PointT>::Ptr groundCloud(new pcl::PointCloud<PointT>);
typename pcl::PointCloud<PointT>::Ptr obstaclesCloud(new pcl::PointCloud<PointT>);
if(groundIndices->size())
{
pcl::copyPointCloud(*cloud, *groundIndices, *groundCloud);
}
if(obstaclesIndices->size())
{
pcl::copyPointCloud(*cloud, *obstaclesIndices, *obstaclesCloud);
}
occupancy2DFromGroundObstacles<PointT>(
groundCloud,
obstaclesCloud,
ground,
obstacles,
cellSize);
}
template<typename PointT>
void occupancy2DFromGroundObstacles(
const typename pcl::PointCloud<PointT>::Ptr & groundCloud,
const typename pcl::PointCloud<PointT>::Ptr & obstaclesCloud,
cv::Mat & ground,
cv::Mat & obstacles,
float cellSize)
{
ground = cv::Mat();
if(groundCloud->size())
{
//project on XY plane
typename pcl::PointCloud<PointT>::Ptr groundCloudProjected;
groundCloudProjected = util3d::projectCloudOnXYPlane(*groundCloud);
//voxelize to grid cell size
groundCloudProjected = util3d::voxelize(groundCloudProjected, cellSize);
ground = cv::Mat((int)groundCloudProjected->size(), 1, CV_32FC2);
for(unsigned int i=0;i<groundCloudProjected->size(); ++i)
{
ground.at<cv::Vec2f>(i)[0] = groundCloudProjected->at(i).x;
ground.at<cv::Vec2f>(i)[1] = groundCloudProjected->at(i).y;
}
}
obstacles = cv::Mat();
if(obstaclesCloud->size())
{
//project on XY plane
typename pcl::PointCloud<PointT>::Ptr obstaclesCloudProjected;
obstaclesCloudProjected = util3d::projectCloudOnXYPlane(*obstaclesCloud);
//voxelize to grid cell size
obstaclesCloudProjected = util3d::voxelize(obstaclesCloudProjected, cellSize);
obstacles = cv::Mat((int)obstaclesCloudProjected->size(), 1, CV_32FC2);
for(unsigned int i=0;i<obstaclesCloudProjected->size(); ++i)
{
obstacles.at<cv::Vec2f>(i)[0] = obstaclesCloudProjected->at(i).x;
obstacles.at<cv::Vec2f>(i)[1] = obstaclesCloudProjected->at(i).y;
}
}
} }
template<typename PointT> template<typename PointT>
@@ -125,7 +276,9 @@ void occupancy2DFromCloud3D(
cv::Mat & obstacles, cv::Mat & obstacles,
float cellSize, float cellSize,
float groundNormalAngle, float groundNormalAngle,
int minClusterSize) int minClusterSize,
bool segmentFlatObstacles,
float maxGroundHeight)
{ {
if(cloud->size() == 0) if(cloud->size() == 0)
{ {
@@ -138,52 +291,20 @@ void occupancy2DFromCloud3D(
indices, indices,
groundIndices, groundIndices,
obstaclesIndices, obstaclesIndices,
cellSize, 20,
groundNormalAngle, groundNormalAngle,
minClusterSize); cellSize*2.0f,
minClusterSize,
segmentFlatObstacles,
maxGroundHeight);
pcl::PointCloud<pcl::PointXYZ>::Ptr groundCloud(new pcl::PointCloud<pcl::PointXYZ>); occupancy2DFromGroundObstacles<PointT>(
pcl::PointCloud<pcl::PointXYZ>::Ptr obstaclesCloud(new pcl::PointCloud<pcl::PointXYZ>); cloud,
groundIndices,
if(groundIndices->size()) obstaclesIndices,
{ ground,
pcl::copyPointCloud(*cloud, *groundIndices, *groundCloud); obstacles,
//project on XY plane cellSize);
util3d::projectCloudOnXYPlane(groundCloud);
//voxelize to grid cell size
groundCloud = util3d::voxelize(groundCloud, cellSize);
}
if(obstaclesIndices->size())
{
pcl::copyPointCloud(*cloud, *obstaclesIndices, *obstaclesCloud);
//project on XY plane
util3d::projectCloudOnXYPlane(obstaclesCloud);
//voxelize to grid cell size
obstaclesCloud = util3d::voxelize(obstaclesCloud, cellSize);
}
ground = cv::Mat();
if(groundCloud->size())
{
ground = cv::Mat((int)groundCloud->size(), 1, CV_32FC2);
for(unsigned int i=0;i<groundCloud->size(); ++i)
{
ground.at<cv::Vec2f>(i)[0] = groundCloud->at(i).x;
ground.at<cv::Vec2f>(i)[1] = groundCloud->at(i).y;
}
}
obstacles = cv::Mat();
if(obstaclesCloud->size())
{
obstacles = cv::Mat((int)obstaclesCloud->size(), 1, CV_32FC2);
for(unsigned int i=0;i<obstaclesCloud->size(); ++i)
{
obstacles.at<cv::Vec2f>(i)[0] = obstaclesCloud->at(i).x;
obstacles.at<cv::Vec2f>(i)[1] = obstaclesCloud->at(i).y;
}
}
} }
template<typename PointT> template<typename PointT>
@@ -193,10 +314,12 @@ void occupancy2DFromCloud3D(
cv::Mat & obstacles, cv::Mat & obstacles,
float cellSize, float cellSize,
float groundNormalAngle, float groundNormalAngle,
int minClusterSize) int minClusterSize,
bool segmentFlatObstacles,
float maxGroundHeight)
{ {
pcl::IndicesPtr indices(new std::vector<int>); pcl::IndicesPtr indices(new std::vector<int>);
occupancy2DFromCloud3D<PointT>(cloud, indices, ground, obstacles, cellSize, groundNormalAngle, minClusterSize); occupancy2DFromCloud3D<PointT>(cloud, indices, ground, obstacles, cellSize, groundNormalAngle, minClusterSize, segmentFlatObstacles, maxGroundHeight);
} }
} }
+3 -2
View File
@@ -1,5 +1,5 @@
/* /*
Copyright (c) 2010-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
@@ -32,6 +32,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <opencv2/core/core.hpp> #include <opencv2/core/core.hpp>
#include <rtabmap/core/Transform.h> #include <rtabmap/core/Transform.h>
#include <rtabmap/core/Parameters.h>
namespace rtabmap namespace rtabmap
{ {
@@ -68,7 +69,7 @@ void RTABMAP_EXP calcOpticalFlowPyrLKStereo( cv::InputArray _prevImg, cv::InputA
cv::Mat RTABMAP_EXP disparityFromStereoImages( cv::Mat RTABMAP_EXP disparityFromStereoImages(
const cv::Mat & leftImage, const cv::Mat & leftImage,
const cv::Mat & rightImage, 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, cv::Mat RTABMAP_EXP depthFromDisparity(const cv::Mat & disparity,
float fx, float baseline, float fx, float baseline,
+40 -16
View File
@@ -1,5 +1,5 @@
/* /*
Copyright (c) 2010-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
@@ -33,8 +33,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <pcl/point_cloud.h> #include <pcl/point_cloud.h>
#include <pcl/point_types.h> #include <pcl/point_types.h>
#include <pcl/pcl_base.h> #include <pcl/pcl_base.h>
#include <pcl/TextureMesh.h>
#include <rtabmap/core/Transform.h> #include <rtabmap/core/Transform.h>
#include <rtabmap/core/SensorData.h> #include <rtabmap/core/SensorData.h>
#include <rtabmap/core/Parameters.h>
#include <opencv2/core/core.hpp> #include <opencv2/core/core.hpp>
#include <map> #include <map>
#include <list> #include <list>
@@ -72,21 +74,38 @@ pcl::PointXYZ RTABMAP_EXP projectDepthTo3D(
bool smoothing, bool smoothing,
float maxZError = 0.02f); float maxZError = 0.02f);
pcl::PointCloud<pcl::PointXYZ>::Ptr RTABMAP_EXP cloudFromDepth( RTABMAP_DEPRECATED (pcl::PointCloud<pcl::PointXYZ>::Ptr RTABMAP_EXP cloudFromDepth(
const cv::Mat & imageDepth, const cv::Mat & imageDepth,
float cx, float cy, float cx, float cy,
float fx, float fy, float fx, float fy,
int decimation = 1, int decimation = 1,
float maxDepth = 0.0f, float maxDepth = 0.0f,
float minDepth = 0.0f,
std::vector<int> * validIndices = 0), "Use cloudFromDepth with CameraModel interface.");
pcl::PointCloud<pcl::PointXYZ>::Ptr RTABMAP_EXP cloudFromDepth(
const cv::Mat & imageDepth,
const CameraModel & model,
int decimation = 1,
float maxDepth = 0.0f,
float minDepth = 0.0f,
std::vector<int> * validIndices = 0); std::vector<int> * validIndices = 0);
pcl::PointCloud<pcl::PointXYZRGB>::Ptr RTABMAP_EXP cloudFromDepthRGB( RTABMAP_DEPRECATED (pcl::PointCloud<pcl::PointXYZRGB>::Ptr RTABMAP_EXP cloudFromDepthRGB(
const cv::Mat & imageRgb, const cv::Mat & imageRgb,
const cv::Mat & imageDepth, const cv::Mat & imageDepth,
float cx, float cy, float cx, float cy,
float fx, float fy, float fx, float fy,
int decimation = 1, int decimation = 1,
float maxDepth = 0.0f, float maxDepth = 0.0f,
float minDepth = 0.0f,
std::vector<int> * validIndices = 0), "Use cloudFromDepthRGB with CameraModel interface.");
pcl::PointCloud<pcl::PointXYZRGB>::Ptr RTABMAP_EXP cloudFromDepthRGB(
const cv::Mat & imageRgb,
const cv::Mat & imageDepth,
const CameraModel & model,
int decimation = 1,
float maxDepth = 0.0f,
float minDepth = 0.0f,
std::vector<int> * validIndices = 0); std::vector<int> * validIndices = 0);
pcl::PointCloud<pcl::PointXYZ>::Ptr RTABMAP_EXP cloudFromDisparity( pcl::PointCloud<pcl::PointXYZ>::Ptr RTABMAP_EXP cloudFromDisparity(
@@ -94,6 +113,7 @@ pcl::PointCloud<pcl::PointXYZ>::Ptr RTABMAP_EXP cloudFromDisparity(
const StereoCameraModel & model, const StereoCameraModel & model,
int decimation = 1, int decimation = 1,
float maxDepth = 0.0f, float maxDepth = 0.0f,
float minDepth = 0.0f,
std::vector<int> * validIndices = 0); std::vector<int> * validIndices = 0);
pcl::PointCloud<pcl::PointXYZRGB>::Ptr RTABMAP_EXP cloudFromDisparityRGB( pcl::PointCloud<pcl::PointXYZRGB>::Ptr RTABMAP_EXP cloudFromDisparityRGB(
@@ -102,6 +122,7 @@ pcl::PointCloud<pcl::PointXYZRGB>::Ptr RTABMAP_EXP cloudFromDisparityRGB(
const StereoCameraModel & model, const StereoCameraModel & model,
int decimation = 1, int decimation = 1,
float maxDepth = 0.0f, float maxDepth = 0.0f,
float minDepth = 0.0f,
std::vector<int> * validIndices = 0); std::vector<int> * validIndices = 0);
pcl::PointCloud<pcl::PointXYZRGB>::Ptr RTABMAP_EXP cloudFromStereoImages( pcl::PointCloud<pcl::PointXYZRGB>::Ptr RTABMAP_EXP cloudFromStereoImages(
@@ -110,29 +131,28 @@ pcl::PointCloud<pcl::PointXYZRGB>::Ptr RTABMAP_EXP cloudFromStereoImages(
const StereoCameraModel & model, const StereoCameraModel & model,
int decimation = 1, int decimation = 1,
float maxDepth = 0.0f, float maxDepth = 0.0f,
std::vector<int> * validIndices = 0); float minDepth = 0.0f,
std::vector<int> * validIndices = 0,
const ParametersMap & parameters = ParametersMap());
pcl::PointCloud<pcl::PointXYZ>::Ptr RTABMAP_EXP cloudFromSensorData( pcl::PointCloud<pcl::PointXYZ>::Ptr RTABMAP_EXP cloudFromSensorData(
const SensorData & sensorData, const SensorData & sensorData,
int decimation = 1, int decimation = 1,
float maxDepth = 0.0f, float maxDepth = 0.0f,
float voxelSize = 0.0f, float minDepth = 0.0f,
int samples = 0, 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 "voxelSize" and * Create an RGB cloud from the images contained in SensorData. If there is only one camera,
* "samples" are not set (0), the returned cloud is organized. Otherwise, all NaN * the returned cloud is organized. Otherwise, all NaN
* points are removed and the cloud will be dense. * points are removed and the cloud will be dense.
* *
* Note that multiple RGB-D camera images will result in a dense cloud.
*
* @param sensorData, the sensor data. * @param sensorData, the sensor data.
* @param decimation, images are decimated by this factor before projecting points to 3D. The factor * @param decimation, images are decimated by this factor before projecting points to 3D. The factor
* should be a factor of the image width and height. * should be a factor of the image width and height.
* @param maxDepth, maximum depth of the projected points (farther points are set to null in case of an organized cloud). * @param maxDepth, maximum depth of the projected points (farther points are set to null in case of an organized cloud).
* @param voxelSize, use a voxel grid filter with this size of voxel. * @param minDepth, minimum depth of the projected points (closer points are set to null in case of an organized cloud).
* @param samples, random sampling filtering target cloud size.
* @param validIndices, the indices of valid points in the cloud * @param validIndices, the indices of valid points in the cloud
* @return a RGB cloud. * @return a RGB cloud.
*/ */
@@ -140,9 +160,9 @@ pcl::PointCloud<pcl::PointXYZRGB>::Ptr RTABMAP_EXP cloudRGBFromSensorData(
const SensorData & sensorData, const SensorData & sensorData,
int decimation = 1, int decimation = 1,
float maxDepth = 0.0f, float maxDepth = 0.0f,
float voxelSize = 0.0f, float minDepth = 0.0f,
int samples = 0, std::vector<int> * validIndices = 0,
std::vector<int> * validIndices = 0); const ParametersMap & parameters = ParametersMap());
pcl::PointCloud<pcl::PointXYZ> RTABMAP_EXP laserScanFromDepthImage( pcl::PointCloud<pcl::PointXYZ> RTABMAP_EXP laserScanFromDepthImage(
const cv::Mat & depthImage, const cv::Mat & depthImage,
@@ -151,6 +171,7 @@ pcl::PointCloud<pcl::PointXYZ> RTABMAP_EXP laserScanFromDepthImage(
float cx, float cx,
float cy, float cy,
float maxDepth = 0, float maxDepth = 0,
float minDepth = 0,
const Transform & localTransform = Transform::getIdentity()); const Transform & localTransform = Transform::getIdentity());
// return CV_32FC3 // return CV_32FC3
@@ -201,6 +222,9 @@ pcl::PointCloud<pcl::PointXYZ>::Ptr RTABMAP_EXP concatenateClouds(
pcl::PointCloud<pcl::PointXYZRGB>::Ptr RTABMAP_EXP concatenateClouds( pcl::PointCloud<pcl::PointXYZRGB>::Ptr RTABMAP_EXP concatenateClouds(
const std::list<pcl::PointCloud<pcl::PointXYZRGB>::Ptr> & clouds); const std::list<pcl::PointCloud<pcl::PointXYZRGB>::Ptr> & clouds);
pcl::TextureMesh::Ptr RTABMAP_EXP concatenateTextureMeshes(
const std::list<pcl::TextureMesh::Ptr> & meshes);
/** /**
* @brief Concatenate a vector of indices to a single vector. * @brief Concatenate a vector of indices to a single vector.
* *
@@ -1,5 +1,5 @@
/* /*
Copyright (c) 2010-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
@@ -1,5 +1,5 @@
/* /*
Copyright (c) 2010-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
@@ -1,5 +1,5 @@
/* /*
Copyright (c) 2010-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
@@ -34,6 +34,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <pcl/point_cloud.h> #include <pcl/point_cloud.h>
#include <pcl/point_types.h> #include <pcl/point_types.h>
#include <pcl/pcl_base.h> #include <pcl/pcl_base.h>
#include <pcl/ModelCoefficients.h>
namespace rtabmap namespace rtabmap
{ {
@@ -108,6 +109,20 @@ pcl::PointCloud<pcl::PointXYZRGB>::Ptr RTABMAP_EXP randomSampling(
int samples); 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( pcl::PointCloud<pcl::PointXYZ>::Ptr RTABMAP_EXP passThrough(
const pcl::PointCloud<pcl::PointXYZ>::Ptr & cloud, const pcl::PointCloud<pcl::PointXYZ>::Ptr & cloud,
const std::string & axis, const std::string & axis,
@@ -344,13 +359,13 @@ pcl::IndicesPtr RTABMAP_EXP normalFiltering(
const pcl::PointCloud<pcl::PointXYZ>::Ptr & cloud, const pcl::PointCloud<pcl::PointXYZ>::Ptr & cloud,
float angleMax, float angleMax,
const Eigen::Vector4f & normal, const Eigen::Vector4f & normal,
float radiusSearch, int normalKSearch,
const Eigen::Vector4f & viewpoint); const Eigen::Vector4f & viewpoint);
pcl::IndicesPtr RTABMAP_EXP normalFiltering( pcl::IndicesPtr RTABMAP_EXP normalFiltering(
const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloud, const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloud,
float angleMax, float angleMax,
const Eigen::Vector4f & normal, const Eigen::Vector4f & normal,
float radiusSearch, int normalKSearch,
const Eigen::Vector4f & viewpoint); const Eigen::Vector4f & viewpoint);
/** /**
@@ -365,7 +380,7 @@ pcl::IndicesPtr RTABMAP_EXP normalFiltering(
* @param indices the input indices of the cloud to process, if empty, all points in the cloud are processed. * @param indices the input indices of the cloud to process, if empty, all points in the cloud are processed.
* @param angleMax the maximum angle. * @param angleMax the maximum angle.
* @param normal the normal to which each point's normal is compared. * @param normal the normal to which each point's normal is compared.
* @param radiusSearch radius parameter used for normal estimation (see pcl::NormalEstimation). * @param normalKSearch number of neighbor points used for normal estimation (see pcl::NormalEstimation).
* @param viewpoint from which viewpoint the normals should be estimated (see pcl::NormalEstimation). * @param viewpoint from which viewpoint the normals should be estimated (see pcl::NormalEstimation).
* @return the indices of the points which respect the normal constraint. * @return the indices of the points which respect the normal constraint.
*/ */
@@ -375,21 +390,21 @@ pcl::IndicesPtr RTABMAP_EXP normalFiltering(
const pcl::IndicesPtr & indices, const pcl::IndicesPtr & indices,
float angleMax, float angleMax,
const Eigen::Vector4f & normal, const Eigen::Vector4f & normal,
float radiusSearch, int normalKSearch,
const Eigen::Vector4f & viewpoint); const Eigen::Vector4f & viewpoint);
pcl::IndicesPtr RTABMAP_EXP normalFiltering( pcl::IndicesPtr RTABMAP_EXP normalFiltering(
const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloud, const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloud,
const pcl::IndicesPtr & indices, const pcl::IndicesPtr & indices,
float angleMax, float angleMax,
const Eigen::Vector4f & normal, const Eigen::Vector4f & normal,
float radiusSearch, int normalKSearch,
const Eigen::Vector4f & viewpoint); const Eigen::Vector4f & viewpoint);
pcl::IndicesPtr RTABMAP_EXP normalFiltering( pcl::IndicesPtr RTABMAP_EXP normalFiltering(
const pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr & cloud, const pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr & cloud,
const pcl::IndicesPtr & indices, const pcl::IndicesPtr & indices,
float angleMax, float angleMax,
const Eigen::Vector4f & normal, const Eigen::Vector4f & normal,
float radiusSearch, int normalKSearch,
const Eigen::Vector4f & viewpoint); const Eigen::Vector4f & viewpoint);
/** /**
@@ -471,6 +486,18 @@ pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr RTABMAP_EXP extractIndices(
bool negative, bool negative,
bool keepOrganized); bool keepOrganized);
pcl::IndicesPtr extractPlane(
const pcl::PointCloud<pcl::PointXYZ>::Ptr & cloud,
float distanceThreshold,
int maxIterations = 100,
pcl::ModelCoefficients * coefficientsOut = 0);
pcl::IndicesPtr extractPlane(
const pcl::PointCloud<pcl::PointXYZ>::Ptr & cloud,
const pcl::IndicesPtr & indices,
float distanceThreshold,
int maxIterations = 100,
pcl::ModelCoefficients * coefficientsOut = 0);
} // namespace util3d } // namespace util3d
} // namespace rtabmap } // namespace rtabmap
+39 -9
View File
@@ -1,5 +1,5 @@
/* /*
Copyright (c) 2010-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
@@ -76,8 +76,9 @@ void RTABMAP_EXP rayTrace(const cv::Point2i & start,
cv::Mat RTABMAP_EXP convertMap2Image8U(const cv::Mat & map8S); cv::Mat RTABMAP_EXP convertMap2Image8U(const cv::Mat & map8S);
void RTABMAP_EXP projectCloudOnXYPlane( template<typename PointT>
pcl::PointCloud<pcl::PointXYZ>::Ptr & cloud); typename pcl::PointCloud<PointT>::Ptr projectCloudOnXYPlane(
const typename pcl::PointCloud<PointT> & cloud);
// templated methods // templated methods
template<typename PointT> template<typename PointT>
@@ -86,19 +87,44 @@ void segmentObstaclesFromGround(
const pcl::IndicesPtr & indices, const pcl::IndicesPtr & indices,
pcl::IndicesPtr & ground, pcl::IndicesPtr & ground,
pcl::IndicesPtr & obstacles, pcl::IndicesPtr & obstacles,
float normalRadiusSearch, int normalKSearch,
float groundNormalAngle, float groundNormalAngle,
float clusterRadius,
int minClusterSize, int minClusterSize,
bool segmentFlatObstacles = false); bool segmentFlatObstacles = false,
float maxGroundHeight = 0.0f,
pcl::IndicesPtr * flatObstacles = 0,
const Eigen::Vector4f & viewPoint = Eigen::Vector4f(0,0,100,0));
template<typename PointT> template<typename PointT>
void segmentObstaclesFromGround( void segmentObstaclesFromGround(
const typename pcl::PointCloud<PointT>::Ptr & cloud, const typename pcl::PointCloud<PointT>::Ptr & cloud,
pcl::IndicesPtr & ground, pcl::IndicesPtr & ground,
pcl::IndicesPtr & obstacles, pcl::IndicesPtr & obstacles,
float normalRadiusSearch, int normalKSearch,
float groundNormalAngle, float groundNormalAngle,
float clusterRadius,
int minClusterSize, int minClusterSize,
bool segmentFlatObstacles = false); bool segmentFlatObstacles = false,
float maxGroundHeight = 0.0f,
pcl::IndicesPtr * flatObstacles = 0,
const Eigen::Vector4f & viewPoint = Eigen::Vector4f(0,0,100,0));
template<typename PointT>
void occupancy2DFromGroundObstacles(
const typename pcl::PointCloud<PointT>::Ptr & cloud,
const pcl::IndicesPtr & groundIndices,
const pcl::IndicesPtr & obstaclesIndices,
cv::Mat & ground,
cv::Mat & obstacles,
float cellSize);
template<typename PointT>
void occupancy2DFromGroundObstacles(
const typename pcl::PointCloud<PointT>::Ptr & groundCloud,
const typename pcl::PointCloud<PointT>::Ptr & obstaclesCloud,
cv::Mat & ground,
cv::Mat & obstacles,
float cellSize);
template<typename PointT> template<typename PointT>
void occupancy2DFromCloud3D( void occupancy2DFromCloud3D(
@@ -107,7 +133,9 @@ void occupancy2DFromCloud3D(
cv::Mat & obstacles, cv::Mat & obstacles,
float cellSize = 0.05f, float cellSize = 0.05f,
float groundNormalAngle = M_PI_4, float groundNormalAngle = M_PI_4,
int minClusterSize = 20); int minClusterSize = 20,
bool segmentFlatObstacles = false,
float maxGroundHeight = 0.0f);
template<typename PointT> template<typename PointT>
void occupancy2DFromCloud3D( void occupancy2DFromCloud3D(
const typename pcl::PointCloud<PointT>::Ptr & cloud, const typename pcl::PointCloud<PointT>::Ptr & cloud,
@@ -116,7 +144,9 @@ void occupancy2DFromCloud3D(
cv::Mat & obstacles, cv::Mat & obstacles,
float cellSize = 0.05f, float cellSize = 0.05f,
float groundNormalAngle = M_PI_4, float groundNormalAngle = M_PI_4,
int minClusterSize = 20); int minClusterSize = 20,
bool segmentFlatObstacles = false,
float maxGroundHeight = 0.0f);
} // namespace util3d } // namespace util3d
} // namespace rtabmap } // namespace rtabmap
@@ -1,5 +1,5 @@
/* /*
Copyright (c) 2010-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
@@ -1,5 +1,5 @@
/* /*
Copyright (c) 2010-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
@@ -92,18 +92,6 @@ Transform RTABMAP_EXP icpPointToPlane(
float epsilon = 0.0f, float epsilon = 0.0f,
bool icp2D = false); bool icp2D = false);
pcl::PointCloud<pcl::PointXYZ>::Ptr RTABMAP_EXP getICPReadyCloud(
const cv::Mat & depth,
float fx,
float fy,
float cx,
float cy,
int decimation,
double maxDepth,
float voxel,
int samples,
const Transform & transform = Transform::getIdentity());
} // namespace util3d } // namespace util3d
} // namespace rtabmap } // namespace rtabmap
+33 -15
View File
@@ -1,5 +1,5 @@
/* /*
Copyright (c) 2010-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
@@ -78,12 +78,23 @@ void RTABMAP_EXP appendMesh(
std::vector<pcl::Vertices> & polygonsA, std::vector<pcl::Vertices> & polygonsA,
const pcl::PointCloud<pcl::PointXYZRGBNormal> & cloudB, const pcl::PointCloud<pcl::PointXYZRGBNormal> & cloudB,
const std::vector<pcl::Vertices> & polygonsB); const std::vector<pcl::Vertices> & polygonsB);
void RTABMAP_EXP appendMesh(
pcl::PointCloud<pcl::PointXYZRGB> & cloudA,
std::vector<pcl::Vertices> & polygonsA,
const pcl::PointCloud<pcl::PointXYZRGB> & cloudB,
const std::vector<pcl::Vertices> & polygonsB);
void RTABMAP_EXP filterNotUsedVerticesFromMesh( // return map from new to old polygon indices
std::map<int, int> RTABMAP_EXP filterNotUsedVerticesFromMesh(
const pcl::PointCloud<pcl::PointXYZRGBNormal> & cloud, const pcl::PointCloud<pcl::PointXYZRGBNormal> & cloud,
const std::vector<pcl::Vertices> & polygons, const std::vector<pcl::Vertices> & polygons,
pcl::PointCloud<pcl::PointXYZRGBNormal> & outputCloud, pcl::PointCloud<pcl::PointXYZRGBNormal> & outputCloud,
std::vector<pcl::Vertices> & outputPolygons); std::vector<pcl::Vertices> & outputPolygons);
std::map<int, int> RTABMAP_EXP filterNotUsedVerticesFromMesh(
const pcl::PointCloud<pcl::PointXYZRGB> & cloud,
const std::vector<pcl::Vertices> & polygons,
pcl::PointCloud<pcl::PointXYZRGB> & outputCloud,
std::vector<pcl::Vertices> & outputPolygons);
std::vector<pcl::Vertices> RTABMAP_EXP filterCloseVerticesFromMesh( std::vector<pcl::Vertices> RTABMAP_EXP filterCloseVerticesFromMesh(
const pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr cloud, const pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr cloud,
@@ -110,32 +121,39 @@ pcl::TextureMesh::Ptr RTABMAP_EXP createTextureMesh(
const std::map<int, Transform> & poses, const std::map<int, Transform> & poses,
const std::map<int, CameraModel> & cameraModels, const std::map<int, CameraModel> & cameraModels,
const std::map<int, cv::Mat> & images, const std::map<int, cv::Mat> & images,
const std::string & tmpDirectory = "."); const std::string & tmpDirectory = ".",
int kNormalSearch = 20); // if mesh doesn't have normals, compute them with k neighbors
pcl::PointCloud<pcl::PointNormal>::Ptr RTABMAP_EXP computeNormals( pcl::PointCloud<pcl::Normal>::Ptr RTABMAP_EXP computeNormals(
const pcl::PointCloud<pcl::PointXYZ>::Ptr & cloud, const pcl::PointCloud<pcl::PointXYZ>::Ptr & cloud,
int normalKSearch = 20); int normalKSearch = 20,
pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr RTABMAP_EXP computeNormals( const Eigen::Vector3f & viewPoint = Eigen::Vector3f(0,0,0));
pcl::PointCloud<pcl::Normal>::Ptr RTABMAP_EXP computeNormals(
const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloud, const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloud,
int normalKSearch = 20); int normalKSearch = 20,
pcl::PointCloud<pcl::PointNormal>::Ptr RTABMAP_EXP computeNormals( const Eigen::Vector3f & viewPoint = Eigen::Vector3f(0,0,0));
pcl::PointCloud<pcl::Normal>::Ptr RTABMAP_EXP computeNormals(
const pcl::PointCloud<pcl::PointXYZ>::Ptr & cloud, const pcl::PointCloud<pcl::PointXYZ>::Ptr & cloud,
const pcl::IndicesPtr & indices, const pcl::IndicesPtr & indices,
int normalKSearch = 20); int normalKSearch = 20,
pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr RTABMAP_EXP computeNormals( const Eigen::Vector3f & viewPoint = Eigen::Vector3f(0,0,0));
pcl::PointCloud<pcl::Normal>::Ptr RTABMAP_EXP computeNormals(
const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloud, const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloud,
const pcl::IndicesPtr & indices, const pcl::IndicesPtr & indices,
int normalKSearch = 20); int normalKSearch = 20,
const Eigen::Vector3f & viewPoint = Eigen::Vector3f(0,0,0));
pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr computeFastOrganizedNormals( pcl::PointCloud<pcl::Normal>::Ptr computeFastOrganizedNormals(
const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloud, const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloud,
float maxDepthChangeFactor = 0.02f, float maxDepthChangeFactor = 0.02f,
float normalSmoothingSize = 10.0f); float normalSmoothingSize = 10.0f,
pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr computeFastOrganizedNormals( const Eigen::Vector3f & viewPoint = Eigen::Vector3f(0,0,0));
pcl::PointCloud<pcl::Normal>::Ptr computeFastOrganizedNormals(
const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloud, const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloud,
const pcl::IndicesPtr & indices, const pcl::IndicesPtr & indices,
float maxDepthChangeFactor = 0.02f, float maxDepthChangeFactor = 0.02f,
float normalSmoothingSize = 10.0f); float normalSmoothingSize = 10.0f,
const Eigen::Vector3f & viewPoint = Eigen::Vector3f(0,0,0));
pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr RTABMAP_EXP mls( pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr RTABMAP_EXP mls(
const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloud, const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloud,
@@ -1,5 +1,5 @@
/* /*
Copyright (c) 2010-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
+1 -1
View File
@@ -1,5 +1,5 @@
/* /*
Copyright (c) 2010-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
+44 -1
View File
@@ -188,10 +188,17 @@ IF(G2O_FOUND)
ENDIF(G2O_FOUND) ENDIF(G2O_FOUND)
IF(GTSAM_FOUND) IF(GTSAM_FOUND)
IF(GTSAM_INCLUDE_DIR)
SET(INCLUDE_DIRS SET(INCLUDE_DIRS
${GTSAM_INCLUDE_DIR} # place it in front to use Eigen installed by GTSAM
${INCLUDE_DIRS} ${INCLUDE_DIRS}
${GTSAM_INCLUDE_DIRS}
) )
ELSE()
SET(INCLUDE_DIRS
${GTSAM_INCLUDE_DIRS} # cmake standard
${INCLUDE_DIRS}
)
ENDIF()
SET(LIBRARIES SET(LIBRARIES
${LIBRARIES} ${LIBRARIES}
gtsam gtsam
@@ -209,6 +216,42 @@ IF(cvsba_FOUND)
) )
ENDIF(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)
IF(OCTOMAP_FOUND)
SET(INCLUDE_DIRS
${INCLUDE_DIRS}
${OCTOMAP_INCLUDE_DIRS}
)
SET(LIBRARIES
${LIBRARIES}
${OCTOMAP_LIBRARIES}
)
SET(SRC_FILES
${SRC_FILES}
OctoMap.cpp
)
ENDIF(OCTOMAP_FOUND)
#################################### ####################################
# Generate resources files # Generate resources files
#################################### ####################################
+3 -2
View File
@@ -1,5 +1,5 @@
/* /*
Copyright (c) 2010-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
@@ -88,7 +88,7 @@ SensorData Camera::takeImage(CameraInfo * info)
} }
UTimer timer; UTimer timer;
SensorData data = this->captureImage(); SensorData data = this->captureImage(info);
double captureTime = timer.ticks(); double captureTime = timer.ticks();
if(warnFrameRateTooHigh) if(warnFrameRateTooHigh)
{ {
@@ -102,6 +102,7 @@ SensorData Camera::takeImage(CameraInfo * info)
if(info) if(info)
{ {
info->id = data.id(); info->id = data.id();
info->stamp = data.stamp();
info->timeCapture = captureTime; info->timeCapture = captureTime;
} }
return data; return data;
+3 -1
View File
@@ -1,5 +1,5 @@
/* /*
Copyright (c) 2010-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
@@ -371,6 +371,8 @@ CameraModel CameraModel::scaled(double scale) const
P.at<double>(1,1) *= scale; P.at<double>(1,1) *= scale;
P.at<double>(0,2) *= scale; P.at<double>(0,2) *= scale;
P.at<double>(1,2) *= scale; P.at<double>(1,2) *= scale;
P.at<double>(0,3) *= scale;
P.at<double>(1,3) *= scale;
} }
scaledModel = CameraModel(name_, cv::Size(double(imageSize_.width)*scale, double(imageSize_.height)*scale), K, D_, R_, P, localTransform_); scaledModel = CameraModel(name_, cv::Size(double(imageSize_.width)*scale, double(imageSize_.height)*scale), K, D_, R_, P, localTransform_);
} }
+19 -11
View File
@@ -1,5 +1,5 @@
/* /*
Copyright (c) 2010-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
@@ -42,6 +42,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <rtabmap/core/util3d_filtering.h> #include <rtabmap/core/util3d_filtering.h>
#include <rtabmap/core/util3d_surface.h> #include <rtabmap/core/util3d_surface.h>
#include <pcl/common/io.h>
#include <iostream> #include <iostream>
#include <fstream> #include <fstream>
#include <cmath> #include <cmath>
@@ -436,7 +438,7 @@ std::vector<std::string> CameraImages::filenames() const
return std::vector<std::string>(); return std::vector<std::string>();
} }
SensorData CameraImages::captureImage() SensorData CameraImages::captureImage(CameraInfo * info)
{ {
if(syncImageRateWithStamps_ && _captureDelay>0.0) if(syncImageRateWithStamps_ && _captureDelay>0.0)
{ {
@@ -661,7 +663,9 @@ SensorData CameraImages::captureImage()
} }
if(_scanNormalsK > 0 && cloud->size()) if(_scanNormalsK > 0 && cloud->size())
{ {
pcl::PointCloud<pcl::PointNormal>::Ptr cloudNormals = util3d::computeNormals(cloud, _scanNormalsK); pcl::PointCloud<pcl::Normal>::Ptr normals = util3d::computeNormals(cloud, _scanNormalsK);
pcl::PointCloud<pcl::PointNormal>::Ptr cloudNormals(new pcl::PointCloud<pcl::PointNormal>);
pcl::concatenateFields(*cloud, *normals, *cloudNormals);
scan = util3d::laserScanFromPointCloud(*cloudNormals); scan = util3d::laserScanFromPointCloud(*cloudNormals);
} }
else else
@@ -692,10 +696,11 @@ SensorData CameraImages::captureImage()
///////////////////////// /////////////////////////
CameraVideo::CameraVideo( CameraVideo::CameraVideo(
int usbDevice, int usbDevice,
bool rectifyImages,
float imageRate, float imageRate,
const Transform & localTransform) : const Transform & localTransform) :
Camera(imageRate, localTransform), Camera(imageRate, localTransform),
_rectifyImages(false), _rectifyImages(rectifyImages),
_src(kUsbDevice), _src(kUsbDevice),
_usbDevice(usbDevice) _usbDevice(usbDevice)
{ {
@@ -722,7 +727,7 @@ CameraVideo::~CameraVideo()
bool CameraVideo::init(const std::string & calibrationFolder, const std::string & cameraName) bool CameraVideo::init(const std::string & calibrationFolder, const std::string & cameraName)
{ {
_guid.clear(); _guid = cameraName;
if(_capture.isOpened()) if(_capture.isOpened())
{ {
_capture.release(); _capture.release();
@@ -749,20 +754,23 @@ bool CameraVideo::init(const std::string & calibrationFolder, const std::string
return false; return false;
} }
else else
{
if (_guid.empty())
{ {
unsigned int guid = (unsigned int)_capture.get(CV_CAP_PROP_GUID); unsigned int guid = (unsigned int)_capture.get(CV_CAP_PROP_GUID);
if(guid != 0 && guid != 0xffffffff) if (guid != 0 && guid != 0xffffffff)
{ {
_guid = uFormat("%08x", guid); _guid = uFormat("%08x", guid);
} }
}
// look for calibration files // 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!", 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 else
{ {
@@ -793,7 +801,7 @@ std::string CameraVideo::getSerial() const
return _guid; return _guid;
} }
SensorData CameraVideo::captureImage() SensorData CameraVideo::captureImage(CameraInfo * info)
{ {
cv::Mat img; cv::Mat img;
if(_capture.isOpened()) if(_capture.isOpened())
@@ -805,7 +813,7 @@ SensorData CameraVideo::captureImage()
_model.setImageSize(img.size()); _model.setImageSize(img.size());
} }
if(_model.isValidForRectification() && (_src != kVideoFile || _rectifyImages)) if(_model.isValidForRectification() && _rectifyImages)
{ {
img = _model.rectifyImage(img); img = _model.rectifyImage(img);
} }

Some files were not shown because too many files have changed in this diff Show More