Compare commits

...
322 Commits
Author SHA1 Message Date
matlabbe db3b901063 Update package.xml
Bump package version
2018-09-29 11:58:58 -04:00
matlabbe 8b055752aa RegistrationIcp: Fixed invalid variance set when structural complexity is low and input doesn't have normals. DBViewer: added check on angular error after optimizing the graph when adding a new constraint. Memory: added warning if odom angular variance detected is very high. 2018-09-28 22:02:07 -04:00
matlabbe dbb9cfa77a Parameters: Updated description of Rtabmap/TimeThr and Rtabmap/MemoryThr (https://github.com/introlab/rtabmap_ros/issues/276) 2018-09-28 15:37:24 -04:00
matlabbe 95e87fed14 MLS: added output voxel size parameter 2018-09-28 09:45:43 -04:00
matlabbe 02fdd677cf 💄 2018-09-27 16:08:55 -04:00
matlabbe 3b74534567 Parameters: Mem/LaserScanNormalRadius should be a float 2018-09-27 14:28:51 -04:00
matlabbe 790b0e5cf7 Memory: undistortion of features can be done also for RGB-only case 2018-09-27 10:19:28 -04:00
matlabbe 5e08da51aa RealSense: fixed color rectification. Fixed ZR300 odometry frame. 2018-09-26 20:51:12 -04:00
matlabbe 0c2287df77 CameraModel fisheye model: fixed typo 2018-09-25 14:36:59 -04:00
matlabbe b581a62c89 Fixed build with opencv < 2.4.10 for missing fisheye model 2018-09-24 15:09:12 -04:00
matlabbe c341648a44 Added parameter "Rtabmap/RectifyOnlyFeatures". Added support of fisheye distortion model. 2018-09-24 14:36:54 -04:00
matlabbe f903ffb927 Fixed regression errors for OpencV2 (#309) 2018-09-18 23:03:40 -04:00
matlabbe 124543c57d Fixed compilation errors with OpenCV 4.0.0 (#309) 2018-09-18 22:43:18 -04:00
matlabbe 829f05e2fb Implemented missing max angular optimization error check for RGBD/OptimizeMaxError 2018-09-18 22:34:15 -04:00
matlabbe d936b2d35a Added '*' to cmake info to show dependencies affecting default parameters 2018-09-18 17:00:37 -04:00
matlabbe 84a8e5830e fixed https://github.com/introlab/rtabmap_ros/issues/274 2018-09-18 12:30:01 -04:00
matlabbe eedc68c360 fixed #312 2018-09-18 12:20:15 -04:00
matlabbe 0cf37fbbf1 Added D415 icon 2018-09-15 11:37:02 -04:00
matlabbe 5f6dd0846d NoEventsExample: updated usage example info 2018-09-07 13:11:39 -04:00
matlabbe 3c15563569 fixed sqlite3 cmake info not correctly shown 2018-09-05 15:03:50 -04:00
matlabbe 1f985ddef0 FindSqlite3.cmake: removed sqlite3 executable search 2018-09-05 12:05:16 -04:00
matlabbe 43e144e7b6 CMake: using external sqlite3 is available, otherwise use internal copy. 2018-09-05 14:22:34 -04:00
matlabbe 9c70b7116b fixed a cmake warning 2018-09-04 19:01:43 -04:00
matlabbe 3c1095be65 Windows: BUILD_AS_BUNDLE option should now be set to ON to create package with all dependencies embedded, otherwise only rtabmap libraries and headers are installed (like default on linux and Mac). 2018-09-04 15:44:37 -04:00
matlabbe 89f27e84d0 💄 2018-08-29 15:36:53 -04:00
matlabbe f64a5e75d5 fixed fovis.hpp not found when using kinetic libfovis branch of https://github.com/srv/libfovis 2018-08-29 14:48:30 -04:00
matlabbe 94178c8cde LOAM: set back to ON by default as the pull request (https://github.com/laboshinl/loam_velodyne/pull/66) has been integrated 2018-08-29 14:38:50 -04:00
matlabbe 30290c36d7 Rtabmap: Added deleteLastLocation() and rejectLastLoopClosure() methods 2018-08-29 12:29:11 -04:00
matlabbe 956f07785b Fixed build error (vtk version issue) 2018-08-28 17:29:20 -04:00
matlabbe 3e6f14f3bd CloudViewer: added camera Ortho mode context menu option 2018-08-28 17:07:36 -04:00
matlabbe 7cb39f02f2 CloudViewer: Reduced interactor motion from 10 to 5 2018-08-28 11:49:32 -04:00
matlabbe c105804572 Moved DBDriverSqlite3.h to installed headers (changed some members from private to protected for easier inheritance) 2018-08-27 16:54:23 -04:00
matlabbe f498cf1b1a CloudViewer: added getColor(id) and setColor(id) to change color of an actor 2018-08-25 11:41:28 -04:00
matlabbe c0a2efe7e2 Fixed build with PCL <1.7.2 2018-08-24 16:17:30 -04:00
matlabbe 080d044c99 CloudViewer: added setInteractorLayer() function 2018-08-24 15:27:42 -04:00
matlabbe cbf14bfa08 CloudViewer: set minimum ambiant light of 0.5 for all meshes 2018-08-23 16:18:04 -04:00
matlabbe 110f4a99ee CloudViewer: added addOrUpdateQuad() function 2018-08-23 11:59:24 -04:00
matlabbe 63af05ef88 CloudViewer: refactoring + added CloudViewerCellPicker class to ignore picking backfaces (when backface culling is on) 2018-08-21 16:11:05 -04:00
matlabbe 0c790005b2 ImageView: colormap not updated if depth cv image is not set 2018-08-17 15:30:13 -04:00
matlabbe 3ce6de573d ImageView: added depth colormap menu option 2018-08-17 15:28:23 -04:00
matlabbe 67aa4cd28e DbViewer: added decimation parameter for cloud visualization. ImageView: adding scaling to height menu option. 2018-08-17 14:01:11 -04:00
matlabbe c18f3cd539 Added rtabmap-export example 2018-08-16 17:01:02 -04:00
matlabbe 9e13d5600a GUI: Fixed ProbMiss assert when resetting value to default 2018-08-16 16:51:29 -04:00
matlabbe 35d5200a3b Parameters in group GridGlobal: renamed OctoMapOccupancyThr to OccupancyThr, added ProbHit, ProbMiss, ProbClampingMin, ProbClampingMax. Using logodds approach from OctoMap to evaluate occupancy of standard grid map. ref https://github.com/introlab/rtabmap_ros/issues/269 2018-08-16 14:42:05 -04:00
matlabbe e0858a9c2a GraphView: added orientation visualization on nodes 2018-08-16 11:21:25 -04:00
matlabbe b8847fd006 0.17.5: added --version option on command line 2018-08-14 14:21:44 -04:00
matlabbe 714d95cc34 Removing redundant non null check before deleting a ptr in destructors #301 2018-08-09 15:53:47 -04:00
matlabbe 5e60a2596c DbViewer: show full covariance in Constraints View 2018-08-09 15:20:19 -04:00
matlabbe f281db8dd0 Windows: removed yaml_cpp required if pkgconfig is installed 2018-08-07 20:34:46 -04:00
matlabbe 7f09a9e0cb fixed #293 2018-08-06 16:34:09 -04:00
matlabbe fe52060de7 Update .travis.yml 2018-08-06 15:04:38 -04:00
matlabbe d5128ddc18 Added parameter Mem/CovOffDiagIgnored (default true) 2018-08-05 12:51:50 -04:00
matlabbe f938e8ce29 Calibration dialog: updated some tooltips 2018-08-03 14:49:39 -04:00
matlabbe a0342671ac OccupancyGrid: added getCache() method 2018-08-02 16:53:44 -04:00
matlabbe e03da92a90 FAST: disabled grid parameters by default 2018-07-27 16:41:19 -04:00
matlabbe 4d5b42ab79 rtabmap: parameters passed by arguments override those in the database loaded from command line. Dictionary: set words saved to avoid saving them in database (causing db error when remapping from an old db created by fixed dictionary). G2O: ba supporting words with negative ids. 2018-07-27 16:01:17 -04:00
matlabbe b63590bf1d Memory: Fixed features with no id (-1) ignored for triangulation from motion. Dictionary: matching with negative word ids is now allowed 2018-07-26 20:41:54 -04:00
matlabbe cfdee23d33 Statistics: added variance info of the loop closure/localization. GUI: Graph view option to show nodes on which loop closures/localizations happened 2018-07-26 14:40:16 -04:00
matlabbe 60499e895f Updated About dialog 2018-07-24 17:11:27 -04:00
matlabbe ddacee6d8b rtabmap-report: ignoring --scale option if no ground truth is found 2018-07-24 14:38:14 -04:00
matlabbe ae226cb1a2 0.17.4 (integrated MSCKF odom approach) 2018-07-23 15:56:53 -04:00
matlabbe a7e70ab80b Set LOAM default off as a special pull request should be used to use it as a library without ros 2018-07-20 19:41:50 -04:00
matlabbe e95cabb1fc fixed optimization error ratio bug where comparison was done using not highest ratio link but on highest abs error link instead. 2018-07-20 15:11:46 -04:00
matlabbe 173bd49a26 Handling intial odometry pose in all odometry approaches. For VIO approaches, gravity initialization is handled too. (#298) 2018-07-19 14:10:36 -04:00
matlabbe 9ae47b79f9 Working MSCKF 2018-07-18 16:15:41 -04:00
matlabbe 15e09cd0a8 Devel: new feature msckf_vio 2018-07-14 20:40:44 -04:00
matlabbe 89a0eb506b Fixed yaml-cpp not found on Ubuntu 14.04 2018-07-12 11:50:46 -04:00
matlabbe 4632c7650f Reloading fixed dictionary when clearing memory 2018-07-12 10:06:02 -04:00
Nicolai Behmann 281452434c Added support for OpenCV 3 CUDA ORB feature extractor and descriptor (#296)
* added cuda support for orb with OpenCV 3

* added support for OpenCV 3 CUDA ORB feature detector and descriptor
2018-07-11 12:33:31 -04:00
matlabbe ccdde45323 fixed build without RealSense2 2018-07-10 15:06:20 -04:00
matlabbe a3e13b8e72 appveyor: updated gtsam/pcl binaries 2018-07-10 13:58:34 -04:00
matlabbe 35bc2d06a6 Fixed building with RealSense2 on Windows 2018-07-10 13:09:52 -04:00
matlabbe ee00f81b5b updated appveyor script 2018-07-10 12:30:23 -04:00
matlabbe 974db316ce updated appveyor script 2018-07-10 12:21:55 -04:00
matlabbe d41c15dbc7 Rtabmap::computePath() added tolerance parameter to overwrite default RGBD/LocalRadius 2018-07-09 15:11:19 -04:00
matlabbe 41d5e11511 Preferences: updated a description text 2018-07-09 12:01:31 -04:00
matlabbe c8100e1464 Gui: show graph color based on visual features 2018-07-09 11:33:39 -04:00
matlabbe b783df397a fixed a cmake warning 2018-07-03 10:13:22 -04:00
matlabbe 62a64cd156 CameraRealSense2: increased wait time from 10 msec to 100 msec 2018-06-28 16:55:33 -04:00
matlabbe 675da6201a Added OdomLOAM/LocalMapping parameter 2018-06-28 11:30:21 -04:00
matlabbe d447329bf1 Added LOAM (loam_velodyne) odometry support 2018-06-28 11:10:46 -04:00
matlabbe 10b452197d fixed build without realsense 2018-06-19 14:00:26 -04:00
matlabbe 973bf93c77 RealSense: added depthScaledToRGBSize option to be able to feed ORB_SLAM2 with depth and RGB images with same size #287. 2018-06-19 13:53:03 -04:00
matlabbe c91431410e fixed g2o crash when failing computing marginals 2018-06-15 16:31:45 -04:00
matlabbe a3bdb027e7 0.17.3: realsense2 and zed-m support 2018-06-15 14:37:22 -04:00
matlabbe 502d5e75e8 CameraRealSense2: added IR-Depth mode option 2018-06-15 14:35:54 -04:00
matlabbe eb4de8e724 Added RealSense2 driver to UI 2018-06-15 13:29:08 -04:00
matlabbe 2060e0b1da Added CameraRealsSense2 driver (tested only with D435) 2018-06-15 12:24:00 -04:00
matlabbe dfcd7ae1a8 Added QT_NO_KEYWORDS definition to avoid conflicts between boost and qt macros 2018-06-15 12:17:11 -04:00
matlabbe c6d893bc98 MainWindow: Odometry visualization not updated if msgs are received faster than they can be visualized. ZED: self-calibration set to true by default (should be true for ZED-M vio) 2018-06-14 17:25:35 -04:00
matlabbe f638add755 fixed #286 2018-06-14 15:20:54 -04:00
matlabbe 9f22a2b1f8 Updated CameraStereoZed to latest zed sdk (2.4) 2018-06-03 02:40:19 -04:00
matlabbe 432b0dc6f6 fixed a build error 2018-06-01 16:33:11 -04:00
matlabbe 7424a1f463 When Mem/DepthAsMask is false, features without depth are triangulated using odometry. Added parameter RGBD/LocalBundleOnLoopClosure. 2018-06-01 16:26:09 -04:00
matlabbe 0bf83c0cd6 fixed frame trail on ros indigo 2018-05-30 17:24:21 -04:00
matlabbe 230e6a311d fixed previous commit 2018-05-30 17:20:54 -04:00
matlabbe 26c004eee0 Fixed g2o build error on 14.04/Indigo 2018-05-30 16:21:06 -04:00
matlabbe 1914275fa8 0.17.2: compute marginals (covariance) on graph optimization 2018-05-30 15:35:08 -04:00
matlabbe 055cccd151 rtabmap: support two usb devices for stereo input 2018-05-29 15:43:02 -04:00
matlabbe b6b0b9a984 Refactored and integrated pull request https://github.com/introlab/rtabmap/pull/285 2018-05-29 13:59:43 -04:00
matlabbe 0fc97c28c6 Merge pull request #284 from patrickelectric/corrections
PreferencesDialog: Add forgotten include
2018-05-29 12:48:49 -04:00
Patrick José Pereira 11c34d383d PreferencesDialog: Add forgotten include
Signed-off-by: Patrick José Pereira <patrickelectric@gmail.com>
2018-05-26 21:40:24 -03:00
matlabbe c68dde70ec Memory: added getDatabaseUrl() function 2018-05-25 13:54:29 -04:00
matlabbe 124d78fefd CloudViewer: custom interactor can be set for convenience 2018-05-25 12:32:22 -04:00
matlabbe d34a529116 Added Rtabmap/StartNewMapOnGoodSignature parameter 2018-05-24 14:53:47 -04:00
matlabbe 4df9ac995a Update .appveyor.yml 2018-05-22 15:42:45 -04:00
matlabbe 4149be47e0 appveyor: fixing gtsam and g2o download links 2018-05-22 12:28:55 -04:00
matlabbe b7da3f7a97 appveyor: added g2o and gtsam dependencies 2018-05-22 12:04:15 -04:00
matlabbe 206c4fe09c appveyor: using qt 5.10.1 instead of deprecated 5.8 2018-05-22 11:50:30 -04:00
matlabbe df7539a48e Update Parameters.h 2018-05-17 11:10:00 -04:00
matlabbe 9c91fb8cd8 0.17.1: Fixed issue #282 and https://github.com/introlab/rtabmap_ros/issues/243 2018-05-14 20:50:21 +00:00
matlabbe 5cdede1482 fixed a compilation warning 2018-05-10 13:57:02 -04:00
matlabbe fa174be741 Updated rtabmap-kitti tool 2018-05-10 13:14:07 -04:00
matlabbe 5e93803eef GUI: Fixed "map id of node -1 not found" error when enabling nodes filtering (https://github.com/introlab/rtabmap_ros/issues/235) 2018-05-08 20:05:29 -04:00
matlabbe bb0b12be27 Updated not incremental dictionary approach for save/reload (can set a database path as dictionary for convenience) 2018-05-08 18:50:39 -04:00
matlabbe 41e93ac6f0 Docker: re-added post_push so that additional tags are pushed with automated build 2018-05-07 09:28:08 -04:00
matlabbe 1df99efa14 Docker: added --cache-from to use cache 2018-05-06 23:46:04 -04:00
matlabbe 911b8158a4 Docker: added post_push hooks to add tags 2018-05-06 17:42:30 -04:00
matlabbe e875c7d6d1 Docker: android scripts updated 2018-05-04 19:52:11 -04:00
matlabbe 0ddbb28fd2 RGBD example: added code example to generate/update the global occupancy grid from rtabmap events. 2018-05-04 19:13:07 -04:00
matlabbe e54234ec50 Docker: fixing missing tag in automated build 2018-05-04 09:25:17 -04:00
matlabbe 6dd0cd27e1 Docker: added quotes around date, updated install_deps to use saved pwd instead of cd alone to return to root 2018-05-03 18:06:37 -04:00
matlabbe ec50b0c366 Docker: added hooks for main docker images 2018-05-03 09:11:27 -04:00
matlabbe 97b61f885d Docker: added hooks/build to xenial build with CACHE_DATE 2018-05-03 08:56:47 -04:00
matlabbe 0d7b8f13d8 Docker replaced -j3 by -j8 2018-05-02 16:19:15 -04:00
matlabbe 2bf7d87b29 Docker: add g2o/gtsam/libpointmatcher to dockerfiles 2018-05-02 16:10:36 -04:00
matlabbe 8d5d50a198 Fixed 2 cmake minor warnings on standard build 2018-05-02 12:46:45 -04:00
matlabbe aa743fc397 ROS: added libg2o dependency 2018-05-02 09:18:23 -04:00
matlabbe 29d16633f5 Added bionic dockerfile 2018-05-01 15:53:19 -04:00
matlabbe d92debe356 rtabmap::triggerNewMap(): reverting commit d9716590b1 to clear optimized poses so that occupancy grid is cleared when triggering a new map. MapCorrection is kept not cleared to support Tango switching mapping<->localization mode without jumping. 2018-04-30 20:03:01 -04:00
matlabbe 52aed1041c using copied version of solvePnPRansac for OpencV 3.3.1 too (along OpenCV2) to have stable transformation estimation (e.g., outdoor stereo demo is getting lost very often with the version of 3.3.1) 2018-04-30 17:44:13 -04:00
matlabbe 8fec570c13 Added Rtabmap::setInitialPose() 2018-04-30 14:49:41 -04:00
matlabbe a39d0840ce fixed #279 2018-04-30 11:16:26 -04:00
matlabbe 63cc86bdcd rtabmap: fixed optimization error seg fault when no maxLinearLink can be found 2018-04-27 19:42:30 -04:00
matlabbe 637514d00d DbViewer: fixed odom pose not added to odomPoses_ when a location doesn't have any links 2018-04-27 19:07:43 -04:00
matlabbe b2db31ff18 Fixed backward compatibility error when saving statistics to db 2018-04-27 18:48:10 -04:00
matlabbe b044bae304 DbViewer: added menu actions to view/update/export optimized mesh saved in database. CloudViewer: cubes can be added for convenience, fixed double-click not always working. util3d: added conversion function from LaserScan to PointCloud2, added conversion functions between polygons format saved in database and PCL polygons format with vertices. 2018-04-25 12:34:47 -04:00
matlabbe f13e384a1b Added util3d::fixTextureMeshForVisualization() 2018-04-16 17:50:00 -04:00
matlabbe bfce5cceb5 Fixed #275. Removed Grid/Scan2dMaxFilledRange parameter (use Grid/RangeMax instead). 2018-04-14 16:48:29 -04:00
matlabbe 344dc165bc fixed #276 and #277 2018-04-14 13:41:04 -04:00
matlabbe 79c4bd7850 Export: Added load and save settings buttons (#274) 2018-04-13 18:54:52 -04:00
matlabbe a82261a4df Export: Added Poisson auto depth (value=0). CloudViewer: Added measuring tool. 2018-04-13 18:19:13 -04:00
matlabbe 57a62dbbfd util3d::mergeTextures: Added assert msg 2018-04-10 12:21:48 -04:00
matlabbe cd125ae274 util3d::mergeTextures() added interface with single calibrations for convenience 2018-04-09 12:26:09 -04:00
matlabbe d9716590b1 Rtabmap: don't reset mapCorrection transform when triggering a new map 2018-04-05 11:28:07 -04:00
matlabbe 2b00b2c1c5 Tango: 0.17 fixing broken localization on visualization 2018-04-05 11:00:16 -04:00
matlabbe b3b0caa038 DbDriver: fixed save/load optimized mesh errors (0.17) 2018-04-05 10:15:06 -04:00
matlabbe db0e833ce9 Tango: fixed build 2018-04-05 09:44:14 -04:00
matlabbe 592b7c66c5 0.17.0: saving optimized poses and last localization pose to database (https://github.com/introlab/rtabmap_ros/issues/220). Parameters: fixed Icp default parameters when not built with libpointmatcher, added RGBD/SavedLocalizationIgnored (default false). DbViewer: added Export/Import 2D map (https://github.com/introlab/rtabmap_ros/issues/213). 2018-04-04 19:14:13 -04:00
matlabbe 34b32f53f6 Merge pull request #273 from mlong-xii/patch-1
Fix laserscan from depth
2018-03-28 15:33:31 -04:00
mlong-xii 9ade28ee00 Fix laserscan from depth
Mathieu, unless I'm missing something, you intended to change this to isEmpty() correct?
2018-03-28 14:14:13 -04:00
matlabbe 99acc9a6e7 Windows: Reordered libraries with gtsam at the end (which is static on Windows) 2018-03-28 11:04:18 -04:00
matlabbe d886c788e7 Fixed CMake keeping old install version path when changing version 2018-03-27 15:50:27 -04:00
matlabbe d2f7d8a9c4 ExportDialog: Added OpenChisel meshing option 2018-03-26 18:06:41 -04:00
matlabbe 7143f693d2 Euroc tool: fixed build error when c++11 is not used #272 2018-03-26 11:13:06 -04:00
matlabbe 9cfdc00d64 Okvis: removed some compilation warnings when not built with okvis 2018-03-23 14:54:49 -04:00
matlabbe 4f6ab68318 Update README.md 2018-03-23 12:49:21 -04:00
matlabbe 7c6439e075 CameraStereoImages: removed warning telling to calibrate the camera when only pose calibration file is not found 2018-03-22 12:40:16 -04:00
matlabbe 420fecad51 Docker updated artful image. Memory: fixed 2x icp correspondence ratio error (>1.0) when creating registration for icp proximity detection 2018-03-22 11:22:47 -04:00
matlabbe ef017c9e9d Docker: updated artful build 2018-03-22 10:07:19 -04:00
matlabbe 00412749e7 IMU: changed members from Eigen to cv to avoid seg faults about Eigen memory alignment when copying IMU object created dynamically (#270) 2018-03-21 21:31:41 -04:00
matlabbe 4188da2ef2 Docker: updated xenial with freenect/openni2 dependencies 2018-03-21 16:36:18 -04:00
matlabbe 8d93c275ab Tango: fixed optimized mesh where nans were removed before saving (causing trouble with corresponding polygons) 2018-03-21 16:00:12 -04:00
matlabbe b0b3b491a0 Docker: added android/install_deps_host.bash. ExportClouds: default voxel size 0.02->0.01 2018-03-20 16:47:18 -04:00
matlabbe dd59d3c713 Tango: fixed MaxOptimizeError value that now is a factor. Docker: updated tango download links 2018-03-18 18:47:13 -04:00
matlabbe 548f0b6130 Fixed Android build 2018-03-18 16:00:03 -04:00
matlabbe f7e007018f fixed Windows build 2018-03-18 19:43:20 -04:00
matlabbe 436e82653c Parameters: updated default of Icp/CorrespondenceRatio and Icp/PMOutlierRatio. Fixed OptimizerG2O build with ORB_SLAM2. Fixed seg fault after restarting ORB_SLAM2 odometry. 2018-03-17 18:20:32 -04:00
matlabbe ecf598e412 util3d::laserScanFromPointCloud(...): ignore NaN points and normals. RegistrationIcp: ignoring NaNs on conversion to PD format to fix some registration fails caused by NaNs. 2018-03-13 02:27:59 -04:00
matlabbe 257fe20c4f OdometryF2F: fixed published localScanMap in wrong frame 2018-03-13 00:01:32 -04:00
matlabbe ba011169b8 DbViewer: don't modify ground truth values (previously they were aligned with root) 2018-03-12 20:57:34 -04:00
matlabbe ffe50dad22 When exporting poses, set txt extension by default if not set 2018-03-12 20:26:34 -04:00
matlabbe dc289ba635 DbViewer: when align with ground truth is enabled, exported poses are those aligned with ground truth 2018-03-12 18:51:55 -04:00
matlabbe 10724fac3b fixed opencv2/core.hpp not found 2018-03-07 20:55:10 -05:00
matlabbe 4969ece356 0.16.3: Added OKVIS support (tested only on EuRoC dataset). Added IMU/IMUThread classes. Added OdomOKVIS/ConfigPath and Rtabmap/ImagesAlreadyRectified parameters. MainWindow, limited odom local feature map to maximum 50 meters from current pose (to avoid VTK glitching with near/far clipping plane). 2018-03-07 19:43:30 -05:00
matlabbe 2fad881202 fixed a compilation warning 2018-02-23 17:55:31 -05:00
matlabbe 39b363d0b5 Memory: compute scan max range if not set on signature creation. 2018-02-23 15:52:59 -05:00
matlabbe 215eff3212 MainWindow: updated default 2d scan with normals color for map and odom 2018-02-23 11:13:26 -05:00
matlabbe e1a0fc42ea Rtabmap: added ebug info when proximity scan matching is disabled 2018-02-23 10:47:07 -05:00
matlabbe 69d28db660 DbViewer: optimized fetching wm states from db, added checkbox along graph iteration slider to generate intermediate graphes. 2018-02-23 10:12:36 -05:00
matlabbe c3ab04b436 Report: removed a test UERROR 2018-02-22 16:37:55 -05:00
matlabbe 918281a804 Rgbd_dataset: fixed Rtabmap/CreateIntermediateNodes not used 2018-02-22 12:09:03 -05:00
matlabbe 297cf3f51e 0.16.2: Added wm_state field to database's Statistics table. New parameter "Rtabmap/SaveWMState" (default false). DbViewer: added option in GraphView to show only poses of the root id that were in WM at that time 2018-02-21 18:19:20 -05:00
matlabbe 93e1d732c9 DbViewer: added option to align scans/clouds to ground truth for convenience 2018-02-21 15:13:02 -05:00
matlabbe 1bfde1f9f0 Neigbor refining can be done with any Registration approach. Memory::computeIcpTransformMulti(): correspondences ratio increased by two times to accept transform 2018-02-21 12:23:12 -05:00
matlabbe 489ab86ac7 dbviewer: fixed variance*100 for proximity by space links (multi-scan). 2018-02-21 10:08:48 -05:00
matlabbe e8f7746c87 dbviewer: removed voxel filtering from scan display 2018-02-21 08:38:35 -05:00
matlabbe db1139e89e Gui: fixed default color for scans from odom in MainWindow and constraint view in dbviewer. Recovery/reprocess: fixed triggering new map on covariance >=9999. Reg: repeatOnce not done if it has a child. Statistics: added time proximity by space visual info. 2018-02-20 17:33:48 -05:00
matlabbe 5c04ce257b DbViewer: can launch with a directory argument to set current workspace for convenience. 2018-02-19 16:37:17 -05:00
matlabbe 6cdb2a48fd OctoMap: improved projection performance 2018-02-19 16:25:55 -05:00
matlabbe 37cbf79b4c DbViewer: fixed occupancy grid color options. Reprocess: added grid total time including rtabmap stats 2018-02-18 21:32:19 -05:00
matlabbe 00559ce8d6 ground segmentaiton: adjusted cluster inlier with centroid below max height of biggest cluster 2018-02-18 15:30:20 -05:00
matlabbe 07244a8a73 Fixed occupancy grid created from PointNormal with RGB 2018-02-18 15:10:25 -05:00
matlabbe d181bedbfc Gui 3d rendering: added default color scheme option, added min and max range options for laser scans 2018-02-17 09:46:08 -05:00
matlabbe 077b3ab59e RegistrationIcp: Added laserScanToDP() 2018-02-17 07:48:10 -05:00
matlabbe edbed67afe Windows: added missing RTABMAP_EXP in LaserScan class. Memory: fixed wrong laser scan format set when filtering is enabled. 2018-02-16 20:56:48 -05:00
matlabbe a947f8c783 Fixed 2d multi-scan matching fatal error 2018-02-16 20:23:42 -05:00
matlabbe 6e131dcd7e fixed build on linux 2018-02-16 19:54:49 -05:00
matlabbe d24097f73d 0.16.1: Added LaserScan class with new "format" field to distinguish easier between all kind of laser scans (XYZ, XYZRGB, XYZI, XYZNormal...) 2018-02-16 19:20:54 -05:00
matlabbe bfb3a58c01 Optimizer: added optimizeIncremental() method to solve optimization error problems when re-opening the database (when graph should be re-optimized from raw odometry poses, not latest optimized poses, #172) 2018-02-13 18:18:42 -05:00
matlabbe 02a64a7fa3 Added ctrl-c handling to reprocess and recovery tools. 2018-02-13 16:54:31 -05:00
matlabbe 3dfe1ccb1a DbViewer: updated warning msg when graph optimization fails. 2018-02-13 14:14:08 -05:00
matlabbe c6e5f1c9f8 Fixed PCL extract indices filter workaround for PointNormal type (not defined in current released PCL). Compression: Fixed OpenCV memory leak when converting uncompressed depth image to 32F format. 2018-02-13 12:36:23 -05:00
matlabbe 4c0a612ab5 util3d_filtering: refactored implementations using templates. Parameters: Changed Grid/DepthMin|Max to Grid/RangeMin|Max, added Grid/PreVoxelFiltering, added GridBlobal/OctoMapOccupancyThr. OccupancyGrid: supporting input clouds already having normals. Memory: don't save working directory parameter to database. 2018-02-13 10:16:48 -05:00
matlabbe 09cae9cbd3 DbViewer: added color selectors for obstacle, ground and empty cells. 2018-02-12 11:32:17 -05:00
matlabbe 1595405871 DbSqlite3: fixed Feature.depth_[x,y,z] not saving correctly NaN values (then NaNs were wrongly converted to 0 on reload). Gui: Added stereo exposure compensation option in Source panel. 2018-02-11 16:07:26 -05:00
matlabbe 1c8c233ebf fixed compilation errors on octomap >=1.8 introduced by previous commit for octomap < 1.8 2018-02-09 11:02:01 -05:00
matlabbe c2d0628da1 Fixed compilation errors with octomap < 1.8 2018-02-09 10:53:39 -05:00
matlabbe 2e58fa3c2f Fixed OctoMap build error with version <1.8 2018-02-08 22:04:50 -05:00
matlabbe fced2c521c 0.16.0: Database updated with Data.empty_cells, Admin.opt_map, Admin.opt_map_x_min and Admin.opt_map_y_min fields. Changed Parameter Grid/ProjRayTracing to Grid/RayTracing (OctoMap ray tracing done for 3D local grids). Improved OctoMap performance. 2018-02-08 21:40:17 -05:00
matlabbe e7ceacc215 Fixed broken incremental prediction matrix from commit 977d21e 2018-02-07 18:16:19 -05:00
matlabbe a320eb5d8e ExportCloudsDialog: voxel size is now to 0.02 by default to limit the size of generated cloud (using too much RAM may result in a crash) 2018-02-06 11:34:54 -05:00
matlabbe 42199eefd2 Added --poses option to report tool. Reprocess tool: Export ground/obstacles when 3d map is created. 2018-02-06 11:31:39 -05:00
matlabbe 56df87e60c GraphViewer: Added "hide/show graph nodes" menu action, added 1% border when exporting to SVG 2018-02-04 14:18:39 -05:00
matlabbe 90ed9cd15c Added support for latest g2o code (with c++11 interface) 2018-02-03 15:43:32 -05:00
matlabbe 8ca3bca810 Fixed build error in rtabmap-reprocess without octomap. Fixed non c++11 build for BayesFilter. 2018-02-02 13:12:14 -05:00
matlabbe 5d2912baa1 Merge branch 'master' of github.com:introlab/rtabmap into devel 2018-02-02 11:47:54 -05:00
matlabbe 129ec29af5 Update .appveyor.yml
Added devel branch
2018-02-02 11:47:20 -05:00
matlabbe 70991cf173 fixed a compilation warning and updated usage of benchmarking tools 2018-02-02 08:51:38 -05:00
matlabbe 61199eff9c fixed CameraThread compilation error with OpenCV<3, added yaml-cpp dependency to travis 2018-02-02 08:35:06 -05:00
matlabbe 4991d3dbab fixed yaml-cpp optional requirement 2018-02-02 08:27:49 -05:00
matlabbe 3405e8b8e1 Merge branch 'master' of https://github.com/introlab/rtabmap into devel 2018-02-01 22:19:34 -05:00
matlabbe 977d21eed5 Update 0.15.4.
Parameters:
-Added "GridGlobal/MaxNodes=0", "Rtabmap/PublishRAMUsage=false", "Mem/DepthAsMask=true", "Kp/FlannRebalancingFactor=2.0", "Vis/DepthAsMask=true".
-Modified "Kp/DetectorStrategy=6", "Kp/MaxFeatures=500",  "Mem/UseOdomFeatures=true", "GFTT/QualityLevel=0.001", "GFTT/MinDistance=3", "RGBD/OptimizeMaxError=1", "RGBD/ProximityPathFilteringRadius=1", "Odom/GuessMotion=true", "Odom/VisKeyFrameThr=150", "OdomF2M/BundleAdjustment=1", "Vis/Iterations=300" if built with g2o, "OdomF2M/BundleAdjustmentMaxFrames=10", "OdomFovis/MinFeaturesForEstimate=20", "OdomORBSLAM2/MapSize=3000", "Reg/RepeatOnce=true", "Vis/PnPRefineIterations=0" if built with g2o, "Vis/CorGuessMatchToProjection=true", "Vis/BundleAdjustment=1" if built with g2o, "Icp/MaxCorrespondenceDistance=0.1", "Icp/PointToPlaneK=5", "Icp/PointToPlaneRadius=1", "Icp/PM=true" if built with libpointmatcher, "Stereo/MaxLevel=5", "Stereo/MinDisparity=0.5".

BayesFilter: optimized prediction matrix update. Use of new argument "ignoreLocalSpaceLoopIds" of Memory::getNeighborsId() to ignore loop closure link by space in prediction update.
CameraThread: Added stereo exposure compensation option.
CameraRGB: Added forceGroundNormalsUp option and added support of ground truth from EuRoC dataset.
Statistics: Added "Memory/RAM_usage/MB".
Transform: Added clone() method to do deep copy.
Graph::importPoses(): EuRoC format support (9).
Rtabmap: Local visual loop closures are now identified as GlobalClosure link type.
OccupancyGrid/OctoMap: updated how cache is used (old node retrieved can be re-added to map without re-assembling the whole map).
OdometryF2F: when using ICP, increasing correspondence distance for first two frames. If Vis/CorType=1 and registration fails, second guess without motion is done with Vis/CorType=0.
OdometryF2M/RegVis: updated how features are removed from the map, using new projectedIDs filled in RegistrationInfo by RegistrationVis.
OdometryORBSLAM2: Maximum size of the feature map can be set with "OdomORBSLAM2/MapSize" parameter.
CloudViewer: fixed opengl camera drifting in follow mode.
DatabaseViewer: Added optimization scale option. ConstraintsView: hide loop closure links if type is ignored in gui parameters.
MainWindow: Support of "GridGlobal/MaxNodes" parameters when updating the maps.
UPlot: don't show ellipses when not in graphics view mode, updated how "random" colors are attributed to curves
Added rtabmap-euroc_dataset tool. Updated rtabmap-kitti_dataset and rtabmap-rgbd_dataset tools.
Added rtabmap-reprocess tool.
2018-02-01 22:17:46 -05:00
matlabbe 09e0d0b9d8 Added RTAB-Map100.png logo of 100 pixels height for main readme to fix docker main page <a><img> tags not supported 2018-01-14 17:20:39 -05:00
matlabbe 79c38d66cb Fixed #255 2018-01-03 20:03:36 -05:00
matlabbe d7871fec2b Db: Fixed octave field missing when opening databases prior to 0.12 2017-12-21 14:58:16 -05:00
matlabbe 9f80f4ac42 RegVis: convert to 3dof before SBA 2017-12-21 10:16:46 -05:00
matlabbe d6058768fc RegVis: fixed out-of-range vector error when guess is used and we match to projections. ImageView: Added right-click menu option to set a fixed size for features 2017-12-18 14:38:54 -05:00
matlabbe 6a50b3f149 util3d::voxelize() added warning if cloud is not dense, indices empty but cloud not empty 2017-12-15 15:25:37 -05:00
matlabbe 35045aa9d7 CameraRGB: updated error msg when depth format is wrong 2017-12-15 11:14:02 -05:00
matlabbe 398ca1f8e4 0.15.3: util3d::computeVarianceAndCorrespondences(): added max angle parameters for normal type. util3d::downsample(): added Normal types support. OccupancyGrid: fixed 2d scan with 5 channels not handled correctly on update. 2017-12-13 18:12:40 -05:00
matlabbe 7091406abc Merge branch 'master' of https://github.com/introlab/rtabmap into devel 2017-12-13 18:07:54 -05:00
matlabbe c21d478f5d ExportCloudsDialog: added more decimals to camera filtering options 2017-12-12 11:16:12 -05:00
matlabbe f973fc3743 Merge branch 'master' of https://github.com/introlab/rtabmap into devel 2017-12-11 17:10:08 -05:00
matlabbe d776092b35 RtabmapThread: when receiving new map event from odometry, wait until the buffer has reached the corresponding timestamp before triggering a new map. DBReader: regenerate stamps when sync capture rate with stamps in database is false. MainWindow: ask for PNG or JPEG format when activating auto capture. 2017-12-11 17:09:04 -05:00
matlabbe 775b80eff5 0.15.2: Fixed Transform's not orthogonal rotation matrix causing problems with GTSAM (normalize rotation each time transforms are multiplied, and for backward compatibility automatically normalize rotation of all transforms loaded from old databases prior to 0.15.2). Added Vis/CorGuessMatchToProjection, Icp/PMMatcherKnn and Icp/PMMatcherEpsilon parameters. CameraRGB: fixed max scans number when filtering. Link: transfering maximum covariance when merging. OptimizerGTSAM: updated how covariance are copied based on GTSAM official example. util3d::loadBINCloud(): fixed dim parameter not used. DatabaseViewer: Added option in graph view to ignore intermediate nodes when optimizing the graph. 2017-12-09 21:44:53 -05:00
matlabbe ff135322f6 Odom/AlignWithGround: fixed random crash when input is stereo and voxel filter is complaining about leaf size too small (limited max depth to 10 meters) 2017-12-06 15:40:41 -05:00
matlabbe dafaac412f DbViewer: fit in view the graph when changing iterations. Limited to 900MB creation of the grid map (in case graph is very erroneous). 2017-12-01 11:56:27 -05:00
matlabbe 4452e637ad 0.15.1: CameraImages: added ground truth time diff, fixed memory leak when loading binary scans. CameraRGBDImages and CameraStereoImages: fixed start id. Feature2D: added grid rows and cols parameters (Kp/GridRows, Kp/GridCols, Vis/GridRows, Vis/GridCols). OdomInfo: publish bundle frames. OdometryORBSLAM2: added OdomORBSLAM2/Fps and OdomORBSLAM2/MaxFeatures parameters. Registration: added Reg/RepeatOnce parameter and removed variance normalization. For util2d::getDepth() and util3d::projectDepthTo3D(), maxZError parameter is now depthErrorRatio to be dependent of the sensor range. Database: save image width and height from stereo calibration. OptimizerG2O: fixed SBA optimization when using g2o built from ORBSLAM2 library. OptimizerGTSAM: to increase optimization stability, all rotations in information matrix are divided by 100000. Added rtabmap-report tool. 2017-11-30 16:52:03 -05:00
matlabbe 821c1c938e DataRecorder: Can record odometry data if odometry is published by the camera (zed or realsense) 2017-11-21 14:14:37 -05:00
matlabbe 1df95702a3 DbViewer: Fixed octomap visualization when ground is not segmented 2017-11-21 13:24:21 -05:00
matlabbe 274e7c579e Added some warnings 2017-11-14 16:28:47 -05:00
matlabbe b820e98bdc Stereo: min and max disparity parameters are now float. ImageView: adjusted background color of info boxes. 2017-11-14 11:36:37 -05:00
matlabbe 10c5cb3721 GUI: Added missing Rtabmap/ComputeRMSE parameter 2017-11-10 16:03:25 -05:00
matlabbe cc7db6190f fixed --quiet option in dataset tools 2017-11-09 12:48:47 -05:00
matlabbe 9a9d81ca18 fixed build error with g2o: no member named 'linear' in 'g2o::SE2' 2017-11-09 12:22:32 -05:00
matlabbe 71d9816f4b 0.15: statistics are now compressed in database. Eigen issue: using linear() instead of rotation() to get rotation from affine3f. Increased loading speed of statistics in DatabaseViewer. Added graph:calcRMSE(). 2017-11-09 12:03:01 -05:00
matlabbe 8cdd138143 CameraK4W2: added depth to color registration. For CameraFreenect2, kTypeColor2DepthSD is now used by default. 2017-11-06 22:59:12 -05:00
matlabbe 7dabfdc207 Added CameraK4W2 (Kinect for Windows SDK v2 driver) 2017-11-06 00:19:12 -05:00
matlabbe 65e82eb37e appveyor: updated PATH to put qt bin before cmake bin 2017-11-05 18:03:33 -05:00
matlabbe 8a14e6ccb4 Update .appveyor.yml 2017-11-03 22:14:37 -04:00
matlabbe 5dadcf3862 apppveyor: activated gui build 2017-11-04 01:38:16 -04:00
matlabbe c001ff763a appveyor: disabled GUI build as QVTK lib is not built yet 2017-11-03 23:20:35 -04:00
matlabbe 3c59b601b5 updated appveyor.yml 2017-11-03 22:13:18 -04:00
matlabbe 4cb0d23136 updated appveyor.yml 2017-11-03 22:12:40 -04:00
matlabbe 2fd29c4b78 updated appveyor.yml 2017-11-03 22:04:07 -04:00
matlabbe c0344a56ff updated appveyor.yml 2017-11-03 21:39:13 -04:00
matlabbe 16692d47b2 updated appveyor.yml 2017-11-03 21:19:54 -04:00
matlabbe 204b3e1159 updated appveyor.yml 2017-11-03 21:10:24 -04:00
matlabbe 41d4ee20b0 updated appveyor.yml 2017-11-03 20:59:34 -04:00
matlabbe 4d17f3c2ff updated appveyor.yml 2017-11-03 20:54:27 -04:00
matlabbe 353fe177f4 updated appveyor.yml 2017-11-03 20:53:22 -04:00
matlabbe 4dc4239963 updated appveyor.yml 2017-11-03 20:48:36 -04:00
matlabbe 0a72cab089 updated appveyor.yml 2017-11-03 20:31:01 -04:00
matlabbe 57202b3ea0 updated appveyor.yml 2017-11-03 20:24:44 -04:00
matlabbe 69e7006cc8 updated appveyor.yml 2017-11-03 20:13:13 -04:00
matlabbe 7ee8652cc3 updated appveyor.yml 2017-11-03 20:02:11 -04:00
matlabbe 8f1331dab3 updated appveyor.yml 2017-11-03 19:54:57 -04:00
matlabbe 2998a54713 updated appveyor.yml 2017-11-03 19:47:45 -04:00
matlabbe ccba8e155e updated appveyor.yml 2017-11-03 19:42:55 -04:00
matlabbe e9317dc2c7 updated appveyor.yml 2017-11-03 19:36:04 -04:00
matlabbe 77f88e5cac appveyor.yml update 2017-11-03 11:47:10 -04:00
matlabbe 43649328cb update appveyor.yml 2017-11-03 11:35:33 -04:00
matlabbe 3629c8c493 added appveyor.yml 2017-11-03 11:33:21 -04:00
matlabbe 426a2f983c fixed mapId for pose -1 not found error when filtering nodes to be shown 2017-10-29 13:23:38 -04:00
matlabbe 85273b9ed7 fixed max tango pose radius 2017-10-29 10:48:04 -04:00
matlabbe 461dba87db fixed build without openni2 2017-10-25 17:58:08 +02:00
matlabbe d4982a8f24 CameraOpenni2: added ir/depth shift parameter 2017-10-25 15:11:26 +02:00
matlabbe de5f3657ab PreferencesDialog: added virtual getDefaultWorkingDirectory() for convenience (can be changed in inherited class) 2017-10-25 10:56:43 +02:00
matlabbe 7a2ddd3905 fixed statsProcessed() not emitted at the right place 2017-10-25 09:56:05 +02:00
matlabbe d5200f859d MainWindow: added signals after statistics/cameraInfo/odometry and 3D map event have been processed 2017-10-25 09:48:00 +02:00
matlabbe 6cee1d9ee6 RtabmapThread: UserData events are added to next node created instead of the last node created (same as rtabmap_ros UserData service) 2017-10-24 19:53:40 +02:00
matlabbe 6b9d4fe7c5 Fixed reset camera orientation 2017-10-24 12:33:50 +02:00
matlabbe 303f315b3e fixed assert when Odom/AlignWithGround is true and generated cloud is empty 2017-10-24 11:40:58 +02:00
matlabbe b6f41eecfd MainWindow: Fixed recovery msg error 2017-10-24 11:34:39 +02:00
matlabbe c880366aaf Removed pcl visualization dependency from core lib 2017-10-24 10:05:39 +02:00
matlabbe e40a7d6681 0.14.3: exposed all gui widgets to public API. CloudViewer: fixed camera orientation reset 2017-10-20 12:09:34 +02:00
matlabbe b3149a2b55 Tango: fixed bug where black point clound is shown when visualizing a mesh with texture 2017-10-19 20:58:51 +02:00
matlabbe 37a9712532 CloudViewer: added pcl visualizer access for inherited classes 2017-10-18 12:28:07 +02:00
matlabbe bcf65d4cae Windows: qvtk missing lib on apps building against rtabmap 2017-10-17 11:13:17 +02:00
matlabbe 521126c982 fixing docker latest build (exit not defined) 2017-10-13 09:29:13 -04:00
matlabbe e2aea92e3b Tango: asking for sharing before showing share intent (to avoid automatically stop tango is we don't want to share) 2017-10-12 20:55:14 -04:00
matlabbe e595f564b1 Parameters: removed Mem/LaserScanVoxelSize from getRemovedParameters() 2017-10-12 17:03:09 -04:00
matlabbe bfbabc62c4 Tango: Localization mode can be used in visualization 2017-10-12 15:54:16 -04:00
matlabbe d4248385f0 Added rtabmap::databaseRecovery() function, added rtabmap-recovery tool, added "Database recovery" menu action in DbViewer 2017-10-11 19:36:00 -04:00
matlabbe ab0aad87ec Increased ZED version requirement to 2 2017-10-11 16:44:53 -04:00
matlabbe 5ac5ff638e Update README.md 2017-10-11 13:45:45 -04:00
matlabbe ed80acd87f Update README.md 2017-10-11 13:45:24 -04:00
matlabbe fa27757719 Update README.md 2017-10-11 13:44:55 -04:00
matlabbe c02cc6d193 Updated About dialog 2017-10-11 13:40:31 -04:00
matlabbe 312f6515ff CameraFreenect2: fixed compilation error when not built with libfreenect2 2017-10-11 13:05:14 -04:00
matlabbe f6315e48d0 CameraFreenect2: added pipelineName parameter 2017-10-11 12:50:57 -04:00
matlabbe 8b3cff9f4c Tango: bump apk version 2017-10-10 12:39:51 -04:00
matlabbe 400952b327 ProximitySpace: extracting all paths inside local radius up to max graph depth, no length limit of the proximity space links. Fixed local scan matching assembling bug when laser local transform is set. DbViewer: we can now refine proximity detection by space (laser scan matching). 2017-10-09 18:45:42 -04:00
matlabbe 007d23308a Tango: updated how memory used and database size are computed 2017-10-09 18:04:54 -04:00
matlabbe 66e79e23cb Tango: kill camera instead of join to avoid lag when clicking pause 2017-10-09 13:05:41 -04:00
matlabbe 4de2ed767b FlannIndex: Fixed size_t matrix allocation error on 64 bits system 2017-10-09 10:51:18 -04:00
matlabbe 49f9a1e8d7 Tango: fixed database saved in memory option when disabled (now disabled by default) 2017-10-08 21:55:27 -04:00
matlabbe 9a09db9212 Tango: added "Pose (x,y,z)" in debug view 2017-10-06 13:42:12 -04:00
matlabbe 1aad6d0517 Merge pull request #238 from nrasulnrasul/patch-1
Proper closing of name space with in the #RTABMAP_H_
2017-10-06 11:22:16 -04:00
nayabrasul d927f1886c Update Rtabmap.h
Proper closing of name space with in the #RTABMAP_H_. Multiple includes of "Rtabmap.h" with in the application causing the compilation problem.
2017-10-06 16:57:30 +02:00
matlabbe 0b8ff7cc01 DbViewer: sorting loop closures by parent ids. When checking ignore pose correction, graph is optimized without them. 2017-10-05 17:10:15 -04:00
matlabbe c4ae4919a5 Tango: some default parameters tuning 2017-10-02 17:44:59 -04:00
matlabbe 83e7f06500 Tango: offset odom origin when reset 2017-10-02 13:19:02 -04:00
matlabbe 9abd925ab7 Reset bayes filter when new map is triggered 2017-09-29 13:28:17 -04:00
matlabbe 7e0c17c5aa Bump tango apk version 2017-09-29 12:47:53 -04:00
matlabbe 6da7788f61 Tango: added GPS to default status when saved, reduced to 1 sec for GPS too old 2017-09-29 12:45:02 -04:00
matlabbe b187409e59 ExportCloudsDialog: fixed assembled cloud not set to dense (as it should) before voxel filter 2017-09-29 12:03:48 -04:00
matlabbe 079be0e072 incremented release version in readme 2017-09-28 17:25:02 -04:00
matlabbe 81c8e1b192 Tango: add Maximum Motion Speed option (default low) to avoid blurry images 2017-09-28 17:15:53 -04:00
matlabbe 1220eab47a Added RGBD/LinearSpeedUpdate and RGBD/AngularSpeedUpdate parameters 2017-09-28 13:34:55 -04:00
matlabbe 44d1877892 Update AndroidManifest.xml.in
bumping apk version (google play store console error...)
2017-09-27 00:52:53 -04:00
270 changed files with 33320 additions and 9973 deletions
+107
View File
@@ -0,0 +1,107 @@
branches:
only:
- master
- devel
os: Visual Studio 2015
clone_folder: c:\projects\rtabmap
platform: x64
configuration: Release
init:
- cmake --version
- call "C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\SetEnv.cmd" /x64
- call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x86_amd64
install:
# Qt
- set QTDIR=C:\Qt\5.10.1\msvc2015_64
# make sure Qt bin path is before cmake bin path to avoid copying qt5 dlls from cmake before qt installation
- set PATH=%QTDIR%\bin;%PATH%
# Boost
- set PATH=%PATH%;C:\Libraries\boost_1_62_0\lib64-msvc-14.0
# Openni2
- ps: wget 'https://dl.dropboxusercontent.com/s/d98jv79l6oy9fxz/OpenNI2.exe?dl=0' -outfile OpenNI2.exe
- cmd: OpenNI2.exe -o"C:\Program Files" -y
- ECHO "Installed OpenNI2:"
- ps: "ls \"C:/Program Files/OpenNI2\""
- set PATH=%PATH%;C:\Program Files\OpenNI2\Redist
- set OPENNI2_INCLUDE64=C:\Program Files\OpenNI2\Include
- set OPENNI2_LIB64=C:\Program Files\OpenNI2\Lib
- set OPENNI2_REDIST64=C:\Program Files\OpenNI2\Redist
# OpenCV
- ps: wget 'http://kent.dl.sourceforge.net/project/opencvlibrary/opencv-win/3.3.1/opencv-3.3.1-vc14.exe' -outfile opencv-3.3.1-vc14.exe
- cmd: opencv-3.3.1-vc14.exe -o"C:\Program Files" -y
- ECHO "Installed OpenCV:"
- ps: "ls \"C:/Program Files/opencv/build\""
- set PATH=%PATH%;C:\Program Files\opencv\build\x64\vc14\bin
# VTK (including QVTK)
- ps: wget 'https://dl.dropboxusercontent.com/s/1l33b5l3f3y52gf/VTK-6_3-msvc140.exe?dl=0' -outfile VTK-6_3.exe
- cmd: VTK-6_3.exe -o"C:\Program Files" -y
- ECHO "Installed PCL:"
- ps: "ls \"C:/Program Files/VTK\""
- set PATH=%PATH%;C:\Program Files\VTK\bin
# QHull
- ps: wget 'https://dl.dropboxusercontent.com/s/9widnk9msdsh2b8/Qhull-msvc140.exe?dl=0' -outfile Qhull.exe
- cmd: Qhull.exe -o"C:\Program Files" -y
- ECHO "Installed PCL:"
- ps: "ls \"C:/Program Files/Qhull\""
- set PATH=%PATH%;C:\Program Files\Qhull\bin
# FLANN
- ps: wget 'https://dl.dropboxusercontent.com/s/7k58jbmqa51sxmh/FLANN-msvc140.exe?dl=0' -outfile FLANN.exe
- cmd: FLANN.exe -o"C:\Program Files" -y
- ECHO "Installed PCL:"
- ps: "ls \"C:/Program Files/FLANN\""
- set PATH=%PATH%;C:\Program Files\FLANN\bin
# Eigen
- ps: wget 'https://dl.dropboxusercontent.com/s/3v6i9i8dxj4o8ji/Eigen.exe?dl=0' -outfile Eigen.exe
- cmd: Eigen.exe -o"C:\Program Files" -y
- ECHO "Installed PCL:"
- ps: "ls \"C:/Program Files/Eigen\""
# PCL
- ps: wget 'https://dl.dropboxusercontent.com/s/r9tvi9md54zlul2/PCL-1_8_1-July2018-msvc140.exe?dl=0' -outfile PCL_1.8.1.exe
- cmd: PCL_1.8.1.exe -o"C:\Program Files" -y
- ECHO "Installed PCL:"
- ps: "ls \"C:/Program Files/PCL\""
- set PATH=%PATH%;C:\Program Files\PCL\bin
# zlib
- ps: wget 'https://docs.google.com/uc?authuser=0&id=0B46akLGdg-uaYm9MTTI4MUtUcmc&export=download' -outfile zlib-1.2.8-vc2010-x64.zip
- ps: Expand-Archive zlib-1.2.8-vc2010-x64.zip -DestinationPath 'C:\Program Files'
- ECHO "Installed zlib:"
- ps: "ls \"C:/Program Files/zlib\""
- set PATH=%PATH%;C:\Program Files\zlib\bin
# g2o
- ps: wget 'https://dl.dropboxusercontent.com/s/ht74s5pa21wokzw/g2o.exe?dl=0' -outfile g2o.exe
- cmd: g2o.exe -o"C:\Program Files" -y
- ECHO "Installed g2o:"
- ps: "ls \"C:/Program Files/g2o\""
- set PATH=%PATH%;C:\Program Files\g2o\bin
# GTSAM
- ps: wget 'https://dl.dropboxusercontent.com/s/0fpr6r4cgsqmvhf/GTSAM-4_0_0_alpha2-msvc140.exe?dl=0' -outfile GTSAM.exe
- cmd: GTSAM.exe -o"C:\Program Files" -y
- ECHO "Installed GTSAM:"
- ps: "ls \"C:/Program Files/GTSAM\""
- set PATH=%PATH%;C:\Program Files\GTSAM\bin
before_build:
- cd c:\projects\rtabmap\build
- ECHO %PROGRAMFILES%
- ECHO %PATH%
- cmake -G "Visual Studio 14 2015 Win64" -DOpenCV_DIR="C:\Program Files\opencv\build" -DPCL_DIR="C:\Program Files\PCL\cmake" -DZLIB_ROOT="C:\Program Files\zlib" -DBUILD_AS_BUNDLE=ON ..
after_build :
- cmake --build . --config Release --target package
artifacts:
- path: build\RTABMap-*
notifications:
- provider: Email
to:
- matlabbe@email.com
on_build_success: false
on_build_failure: false
on_build_status_changed: true
+1
View File
@@ -2,6 +2,7 @@
.DS_Store
.settings/language.settings.xml
.idea/
.vscode
cmake-build-debug/
app/android/.classpath
app/android/.project
+2
View File
@@ -14,11 +14,13 @@ addons:
- libopencv-dev
- libqt4-dev
- libsqlite3-dev
- libyaml-cpp-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 update && sudo apt-get install dpkg
- sudo apt-get -y install libpcl-1.7-all libfreenect-dev ros-indigo-libg2o ros-indigo-octomap libopenni2-dev
script:
+221 -34
View File
@@ -20,8 +20,8 @@ SET(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake_modules")
# VERSION
#######################
SET(RTABMAP_MAJOR_VERSION 0)
SET(RTABMAP_MINOR_VERSION 14)
SET(RTABMAP_PATCH_VERSION 0)
SET(RTABMAP_MINOR_VERSION 17)
SET(RTABMAP_PATCH_VERSION 6)
SET(RTABMAP_VERSION
${RTABMAP_MAJOR_VERSION}.${RTABMAP_MINOR_VERSION}.${RTABMAP_PATCH_VERSION})
@@ -113,15 +113,13 @@ SET( CMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG "${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}")
SET( CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE "${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}")
####### INSTALL DIR #######
set(INSTALL_INCLUDE_DIR include/${PROJECT_PREFIX}-${RTABMAP_MAJOR_VERSION}.${RTABMAP_MINOR_VERSION} CACHE PATH
"Installation directory for header files")
set(INSTALL_INCLUDE_DIR include/${PROJECT_PREFIX}-${RTABMAP_MAJOR_VERSION}.${RTABMAP_MINOR_VERSION})
if(WIN32 AND NOT CYGWIN)
set(DEF_INSTALL_CMAKE_DIR CMake)
else()
set(DEF_INSTALL_CMAKE_DIR ${CMAKE_INSTALL_LIBDIR}/${PROJECT_PREFIX}-${RTABMAP_MAJOR_VERSION}.${RTABMAP_MINOR_VERSION})
endif()
set(INSTALL_CMAKE_DIR ${DEF_INSTALL_CMAKE_DIR} CACHE PATH
"Installation directory for CMake files")
set(INSTALL_CMAKE_DIR ${DEF_INSTALL_CMAKE_DIR})
####### BUILD OPTIONS #######
@@ -133,9 +131,9 @@ IF(ANDROID_PREBUILD)
return()
ENDIF(ANDROID_PREBUILD)
IF(APPLE)
OPTION(BUILD_AS_BUNDLE "Set to ON to build as bundle (DragNDrop)" OFF)
ENDIF(APPLE)
IF(APPLE OR WIN32)
OPTION(BUILD_AS_BUNDLE "Set to ON to build as bundle with all embedded dependencies (DragNDrop for Mac, installer for Windows)" OFF)
ENDIF(APPLE OR WIN32)
OPTION(BUILD_APP "Build main application" ON)
OPTION(BUILD_TOOLS "Build tools" ON)
OPTION(BUILD_EXAMPLES "Build examples" ON)
@@ -148,6 +146,7 @@ option(WITH_QT "Include Qt support" ON)
ENDIF()
option(WITH_FREENECT "Include Freenect support" ON)
option(WITH_FREENECT2 "Include Freenect2 support" ON)
option(WITH_K4W2 "Include Kinect for Windows v2 support" ON)
option(WITH_OPENNI2 "Include OpenNI2 support" ON)
option(WITH_DC1394 "Include dc1394 support" ON)
option(WITH_G2O "Include g2o support" ON)
@@ -156,22 +155,43 @@ option(WITH_TORO "Include TORO support" ON)
option(WITH_VERTIGO "Include Vertigo support" ON)
option(WITH_CVSBA "Include cvsba support" ON)
option(WITH_POINTMATCHER "Include libpointmatcher support" ON)
option(WITH_LOAM "Include LOAM support" ON)
option(WITH_FLYCAPTURE2 "Include FlyCapture2/Triclops support" ON)
option(WITH_ZED "Include ZED sdk support" ON)
option(WITH_REALSENSE "Include RealSense support" ON)
option(WITH_REALSENSE_SLAM "Include RealSenseSlam support" ON)
option(WITH_REALSENSE2 "Include RealSense support" ON)
option(WITH_OCTOMAP "Include Octomap support" ON)
option(WITH_CPUTSDF "Include CPUTSDF support" ON)
option(WITH_OPENCHISEL "Include open_chisel support" ON)
option(WITH_FOVIS "Include FOVIS support" ON)
option(WITH_VISO2 "Include VISO2 support" ON)
option(WITH_DVO "Include DVO support" ON)
option(WITH_ORB_SLAM2 "Include ORB_SLAM2 support" ON)
option(WITH_OKVIS "Include OKVIS support" ON)
option(WITH_MSCKF_VIO "Include MSCKF_VIO support" OFF)
option(PCL_OMP "With PCL OMP implementations" ON)
FIND_PACKAGE(OpenCV REQUIRED QUIET)
FIND_PACKAGE(PCL 1.7 REQUIRED QUIET)
IF(WITH_QT)
FIND_PACKAGE(PCL 1.7 REQUIRED QUIET COMPONENTS common io kdtree search surface filters registration sample_consensus segmentation visualization)
ELSE()
FIND_PACKAGE(PCL 1.7 REQUIRED QUIET COMPONENTS common io kdtree search surface filters registration sample_consensus segmentation )
ENDIF()
if("${PCL_DEFINITIONS}" MATCHES "-march=native")
MESSAGE(WARNING "PCL definitions contain \"-march=native\", make sure all libraries using Eigen are also compiled with that flag to avoid some segmentation faults (with gdb referring to some Eigen functions).")
else()
MESSAGE(STATUS "PCL definitions don't contain \"-march=native\", make sure all libraries using Eigen are also compiled without that flag to avoid some segmentation faults (with gdb referring to some Eigen functions).")
endif()
FIND_PACKAGE(ZLIB REQUIRED QUIET)
FIND_PACKAGE(Sqlite3 QUIET)
IF(Sqlite3_FOUND)
MESSAGE(STATUS "Found Sqlite3: ${Sqlite3_INCLUDE_DIRS} ${Sqlite3_LIBRARIES}")
ENDIF(Sqlite3_FOUND)
if(NOT "${PCL_LIBRARIES}" STREQUAL "")
# fix libproj.so not found on Xenial
list(REMOVE_ITEM PCL_LIBRARIES "vtkproj4")
@@ -232,7 +252,12 @@ IF(WITH_QT)
SET(PCL_LIBRARIES "${PCL_LIBRARIES};vtkGUISupportQt")
SET(ADD_VTK_GUI_SUPPORT_QT_TO_CONF TRUE)
ENDIF(value EQUAL -1)
MESSAGE(STATUS "VTK_RENDERING_BACKEND=${VTK_RENDERING_BACKEND}")
IF(VTK_RENDERING_BACKEND STREQUAL "OpenGL2")
ADD_DEFINITIONS("-DVTK_OPENGL2")
ENDIF(VTK_RENDERING_BACKEND STREQUAL "OpenGL2")
ENDIF()
ADD_DEFINITIONS(-DQT_NO_KEYWORDS) # To avoid conflicts with boost signals/foreach and Qt macros
ENDIF(QT4_FOUND OR Qt5_FOUND)
ENDIF(WITH_QT)
@@ -261,6 +286,13 @@ IF(WITH_FREENECT2)
ENDIF(freenect2_FOUND)
ENDIF(WITH_FREENECT2)
IF(WITH_K4W2 AND WIN32)
FIND_PACKAGE(KinectSDK2 QUIET)
IF(KinectSDK2_FOUND)
MESSAGE(STATUS "Found Kinect for Windows 2: ${KinectSDK2_INCLUDE_DIRS}")
ENDIF(KinectSDK2_FOUND)
ENDIF(WITH_K4W2 AND WIN32)
# IF PCL depends on OpenNI2 (already found), ignore WITH_OPENNI2
IF(WITH_OPENNI2 OR OpenNI2_FOUND)
FIND_PACKAGE(OpenNI2 QUIET)
@@ -308,6 +340,14 @@ IF(WITH_POINTMATCHER)
ENDIF(libpointmatcher_FOUND)
ENDIF(WITH_POINTMATCHER)
IF(WITH_LOAM)
find_package(loam_velodyne QUIET)
IF(loam_velodyne_FOUND)
MESSAGE(STATUS "Found loam_velodyne: ${loam_velodyne_INCLUDE_DIRS}")
ENDIF(loam_velodyne_FOUND)
ENDIF(WITH_LOAM)
SET(ZED_FOUND FALSE)
IF(WITH_ZED)
IF(WIN32) # Windows
SET(ZED_INCLUDE_DIRS $ENV{ZED_INCLUDE_DIRS})
@@ -322,7 +362,7 @@ IF(WITH_ZED)
LINK_DIRECTORIES( ${LINK_DIRECTORIES} ${ZED_LIBRARY_DIR})
ENDIF(ZED_LIBRARIES AND ZED_INCLUDE_DIRS)
ELSE() # Linux
find_package(ZED 1 QUIET)
find_package(ZED 2 QUIET)
ENDIF(WIN32)
IF(ZED_FOUND)
@@ -351,10 +391,24 @@ IF(WITH_REALSENSE)
ENDIF(RealSenseSlam_FOUND)
ENDIF(WITH_REALSENSE)
IF(WITH_REALSENSE2)
IF(WIN32)
FIND_PACKAGE(RealSense2 QUIET)
ELSE()
FIND_PACKAGE(realsense2 QUIET)
ENDIF()
IF(realsense2_FOUND)
MESSAGE(STATUS "Found RealSense2: ${realsense2_INCLUDE_DIRS}")
ENDIF(realsense2_FOUND)
ENDIF(WITH_REALSENSE2)
IF(WITH_OCTOMAP)
FIND_PACKAGE(OCTOMAP QUIET)
IF(OCTOMAP_FOUND)
MESSAGE(STATUS "Found octomap: ${OCTOMAP_INCLUDE_DIRS}")
MESSAGE(STATUS "Found octomap ${OCTOMAP_VERSION}: ${OCTOMAP_INCLUDE_DIRS}")
IF(OCTOMAP_VERSION VERSION_LESS 1.8)
ADD_DEFINITIONS("-DOCTOMAP_PRE_18")
ENDIF(OCTOMAP_VERSION VERSION_LESS 1.8)
ENDIF(OCTOMAP_FOUND)
ENDIF(WITH_OCTOMAP)
@@ -365,6 +419,13 @@ IF(WITH_CPUTSDF)
ENDIF(CPUTSDF_FOUND)
ENDIF(WITH_CPUTSDF)
IF(WITH_OPENCHISEL)
find_package(open_chisel QUIET)
if(open_chisel_FOUND)
MESSAGE(STATUS "Found open_chisel: ${open_chisel_INCLUDE_DIRS}")
endif(open_chisel_FOUND)
ENDIF(WITH_OPENCHISEL)
IF(WITH_FOVIS)
FIND_PACKAGE(libfovis QUIET)
IF(libfovis_FOUND)
@@ -386,6 +447,27 @@ IF(WITH_DVO)
ENDIF(dvo_core_FOUND)
ENDIF(WITH_DVO)
IF(WITH_OKVIS)
FIND_PACKAGE(okvis 1.1 QUIET)
IF(okvis_FOUND)
MESSAGE(STATUS "Found okvis: ${OKVIS_INCLUDE_DIRS}")
find_package(brisk 2 REQUIRED)
MESSAGE(STATUS "Found brisk: ${BRISK_INCLUDE_DIRS}")
find_package(opengv REQUIRED)
MESSAGE(STATUS "Found opengv: ${OPENGV_INCLUDE_DIRS}")
find_package(Ceres REQUIRED CONFIG PATHS ${OKVIS_CERES_CONFIG} NO_DEFAULT_PATH)
MESSAGE(STATUS "Found ceres: ${CERES_INCLUDE_DIRS}")
ENDIF(okvis_FOUND)
ENDIF(WITH_OKVIS)
IF(WITH_MSCKF_VIO)
FIND_PACKAGE(msckf_vio QUIET)
IF(msckf_vio_FOUND)
MESSAGE(STATUS "Found msckf_vio: ${msckf_vio_INCLUDE_DIRS}")
ENDIF(msckf_vio_FOUND)
ENDIF(WITH_MSCKF_VIO)
IF(WITH_ORB_SLAM2 AND NOT G2O_FOUND)
FIND_PACKAGE(ORB_SLAM2 QUIET)
IF(ORB_SLAM2_FOUND)
@@ -398,12 +480,22 @@ IF(WITH_ORB_SLAM2 AND NOT G2O_FOUND)
MESSAGE(STATUS "Found Pangolin: ${Pangolin_INCLUDE_DIRS}")
SET(ORB_SLAM2_INCLUDE_DIRS ${ORB_SLAM2_INCLUDE_DIRS} ${Pangolin_INCLUDE_DIRS})
SET(ORB_SLAM2_LIBRARIES ${ORB_SLAM2_LIBRARIES} ${Pangolin_LIBRARIES})
MESSAGE(WARNING "Don't forget to build ORB_SLAM2 (and included g2o) without \"-march=native\" to avoid crash when ORB_SLAM2 starts.")
ENDIF()
ENDIF(ORB_SLAM2_FOUND)
ENDIF(WITH_ORB_SLAM2 AND NOT G2O_FOUND)
IF(G2O_FOUND OR GTSAM_FOUND OR ZED_FOUND OR ANDROID OR RealSense_FOUND OR ORB_SLAM2_FOUND)
IF(loam_velodyne_FOUND)
#LOAM requires c++14
IF(NOT MSVC)
include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("-std=c++14" COMPILER_SUPPORTS_CXX14)
IF(COMPILER_SUPPORTS_CXX14)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14")
ELSE()
message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++14 support. Please use a different C++ compiler if you want to use LOAM (set \"-DWITH_LOAM=OFF\" to build without LOAM).")
ENDIF()
ENDIF()
ELSEIF(G2O_FOUND OR GTSAM_FOUND OR ZED_FOUND OR ANDROID OR RealSense_FOUND OR realsense2_FOUND OR ORB_SLAM2_FOUND OR okvis_FOUND OR open_chisel_FOUND OR msckf_vio_FOUND)
#Newest versions require std11
IF(NOT MSVC)
include(CheckCXXCompilerFlag)
@@ -414,10 +506,10 @@ IF(G2O_FOUND OR GTSAM_FOUND OR ZED_FOUND OR ANDROID OR RealSense_FOUND OR ORB_SL
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).")
message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.")
ENDIF()
ENDIF()
ENDIF(G2O_FOUND OR GTSAM_FOUND OR ZED_FOUND OR ANDROID OR RealSense_FOUND OR ORB_SLAM2_FOUND)
ENDIF()
####### OSX BUNDLE CMAKE_INSTALL_PREFIX #######
IF(APPLE AND BUILD_AS_BUNDLE)
@@ -460,6 +552,9 @@ IF(NOT G2O_FOUND)
SET(G2O "//")
ELSE()
SET(CONF_DEPENDENCIES ${CONF_DEPENDENCIES} ${G2O_LIBRARIES})
IF(NOT G2O_CPP11)
SET(G2O_CPP_CONF "//")
ENDIF(NOT G2O_CPP11)
ENDIF()
IF(NOT GTSAM_FOUND)
SET(GTSAM "//")
@@ -480,6 +575,9 @@ ENDIF()
IF(NOT libpointmatcher_FOUND)
SET(POINTMATCHER "//")
ENDIF(NOT libpointmatcher_FOUND)
IF(NOT loam_velodyne_FOUND)
SET(LOAM "//")
ENDIF(NOT loam_velodyne_FOUND)
IF(NOT Freenect_FOUND)
SET(FREENECT "//")
ELSE()
@@ -490,6 +588,11 @@ IF(NOT freenect2_FOUND)
ELSE()
SET(CONF_DEPENDENCIES ${CONF_DEPENDENCIES} ${freenect2_LIBRARIES})
ENDIF()
IF(NOT KinectSDK2_FOUND)
SET(K4W2 "//")
ELSE()
SET(CONF_DEPENDENCIES ${CONF_DEPENDENCIES} ${KinectSDK2_LIBRARIES})
ENDIF()
IF(NOT OpenNI2_FOUND)
SET(OPENNI2 "//")
ELSE()
@@ -518,6 +621,11 @@ ENDIF()
IF(NOT RealSenseSlam_FOUND)
SET(REALSENSESLAM "//")
ENDIF(NOT RealSenseSlam_FOUND)
IF(NOT realsense2_FOUND)
SET(REALSENSE2 "//")
ELSE()
SET(CONF_DEPENDENCIES ${CONF_DEPENDENCIES} ${realsense2_LIBRARIES})
ENDIF()
IF(NOT OCTOMAP_FOUND)
SET(OCTOMAP "//")
ELSE()
@@ -528,6 +636,11 @@ IF(NOT CPUTSDF_FOUND)
ELSE()
SET(CONF_DEPENDENCIES ${CONF_DEPENDENCIES} ${CPUTSDF_LIBRARIES})
ENDIF()
IF(NOT open_chisel_FOUND)
SET(OPENCHISEL "//")
ELSE()
SET(CONF_DEPENDENCIES ${CONF_DEPENDENCIES} ${open_chisel_LIBRARIES})
ENDIF()
IF(NOT libfovis_FOUND)
SET(FOVIS "//")
ELSE()
@@ -543,6 +656,16 @@ IF(NOT dvo_core_FOUND)
ELSE()
SET(CONF_DEPENDENCIES ${CONF_DEPENDENCIES} ${dvo_core_LIBRARIES})
ENDIF()
IF(NOT okvis_FOUND)
SET(OKVIS "//")
ELSE()
SET(CONF_DEPENDENCIES ${CONF_DEPENDENCIES} ${OKVIS_LIBRARIES})
ENDIF()
IF(NOT msckf_vio_FOUND)
SET(MSCKF_VIO "//")
ELSE()
SET(CONF_DEPENDENCIES ${CONF_DEPENDENCIES} ${msckf_vio_LIBRARIES})
ENDIF()
IF(NOT ORB_SLAM2_FOUND)
SET(ORB_SLAM2 "//")
ELSE()
@@ -554,9 +677,13 @@ IF(ADD_VTK_GUI_SUPPORT_QT_TO_CONF)
ELSE()
SET(CONF_VTK_QT false)
ENDIF()
IF(NOT (OpenCV_FOUND AND OpenCV_VERSION_MAJOR EQUAL 3))
IF(VTK_USE_QVTK)
SET(CONF_DEPENDENCIES ${CONF_DEPENDENCIES} ${QVTK_LIBRARY})
ENDIF(VTK_USE_QVTK)
IF(NOT (OpenCV_FOUND AND NOT (OpenCV_VERSION_MAJOR LESS 3)))
SET(OPENCV3 "//")
ENDIF(NOT (OpenCV_FOUND AND OpenCV_VERSION_MAJOR EQUAL 3))
ENDIF(NOT (OpenCV_FOUND AND NOT (OpenCV_VERSION_MAJOR LESS 3)))
CONFIGURE_FILE(Version.h.in ${PROJECT_SOURCE_DIR}/corelib/include/${PROJECT_PREFIX}/core/Version.h)
ADD_SUBDIRECTORY( utilite )
@@ -676,7 +803,11 @@ IF(WIN32)
ELSE()
SET(CPACK_NSIS_INSTALL_ROOT "$PROGRAMFILES")
ENDIF()
SET(CPACK_GENERATOR "ZIP;NSIS")
IF(BUILD_AS_BUNDLE)
SET(CPACK_GENERATOR "ZIP;NSIS")
ELSE()
SET(CPACK_GENERATOR "ZIP")
ENDIF()
SET(CPACK_SOURCE_GENERATOR "ZIP")
SET(CPACK_NSIS_PACKAGE_NAME "${PROJECT_NAME}")
SET(ICON_PATH "${PROJECT_SOURCE_DIR}/app/src/${PROJECT_NAME}.ico")
@@ -731,27 +862,35 @@ IF(NOT WIN32)
# see comment above for the BUILD_SHARED_LIBS option on Windows
MESSAGE(STATUS " BUILD_SHARED_LIBS = ${BUILD_SHARED_LIBS}")
ENDIF(NOT WIN32)
IF(APPLE)
IF(APPLE OR WIN32)
MESSAGE(STATUS " BUILD_AS_BUNDLE = ${BUILD_AS_BUNDLE}")
ENDIF(APPLE)
ENDIF(APPLE OR WIN32)
MESSAGE(STATUS " CMAKE_CXX_FLAGS = ${CMAKE_CXX_FLAGS}")
MESSAGE(STATUS " PCL_DEFINITIONS = ${PCL_DEFINITIONS}")
MESSAGE(STATUS "Optional dependencies ('*' affects some default parameters) :")
IF(OpenCV_FOUND)
IF(OpenCV_VERSION_MAJOR EQUAL 2)
IF(OPENCV_NONFREE_FOUND)
MESSAGE(STATUS " With OpenCV 2 nonfree module (SIFT/SURF) = YES (License: Non commercial)")
MESSAGE(STATUS " *With OpenCV 2 nonfree module (SIFT/SURF) = YES (License: Non commercial)")
ELSE()
MESSAGE(STATUS " With OpenCV 2 nonfree module (SIFT/SURF) = NO (not found, License: BSD)")
MESSAGE(STATUS " *With OpenCV 2 nonfree module (SIFT/SURF) = NO (not found, License: BSD)")
ENDIF()
ELSE()
IF(OPENCV_XFEATURES2D_FOUND)
MESSAGE(STATUS " With OpenCV 3 xfeatures2d module (SIFT/SURF/BRIEF/FREAK) = YES (License: Non commercial)")
MESSAGE(STATUS " *With OpenCV 3 xfeatures2d module (SIFT/SURF/BRIEF/FREAK) = YES (License: Non commercial)")
ELSE()
MESSAGE(STATUS " With OpenCV 3 xfeatures2d module (SIFT/SURF/BRIEF/FREAK) = NO (not found, License: BSD)")
MESSAGE(STATUS " *With OpenCV 3 xfeatures2d module (SIFT/SURF/BRIEF/FREAK) = NO (not found, License: BSD)")
ENDIF()
ENDIF()
ENDIF(OpenCV_FOUND)
IF(Sqlite3_FOUND)
MESSAGE(STATUS " With external SQLite3 = YES (License: Public Domain)")
ELSE()
MESSAGE(STATUS " With external SQLite3 = NO (sqlite3 not found, internal version is used for convenience)")
ENDIF()
IF(Freenect_FOUND)
MESSAGE(STATUS " With Freenect = YES (License: Apache v2 and/or GPLv2)")
ELSEIF(NOT WITH_FREENECT)
@@ -776,6 +915,14 @@ ELSE()
MESSAGE(STATUS " With Freenect2 = NO (libfreenect2 not found)")
ENDIF()
IF(KinectSDK2_FOUND)
MESSAGE(STATUS " With Kinect for Windows 2 = YES (License: Apache v2 and/or GPLv2)")
ELSEIF(NOT WITH_K4W2)
MESSAGE(STATUS " With Kinect for Windows 2 = NO (WITH_K4W2=OFF)")
ELSE()
MESSAGE(STATUS " With Kinect for Windows 2 = NO (Kinect for Windows 2 SDK not found)")
ENDIF()
IF(DC1394_FOUND)
MESSAGE(STATUS " With dc1394 = YES (License: LGPL)")
ELSEIF(NOT WITH_DC1394)
@@ -799,19 +946,19 @@ MESSAGE(STATUS " With TORO = NO (WITH_TORO=OFF)")
ENDIF()
IF(G2O_FOUND)
MESSAGE(STATUS " With g2o = YES (License: BSD)")
MESSAGE(STATUS " *With g2o = YES (License: BSD)")
ELSEIF(NOT WITH_G2O)
MESSAGE(STATUS " With g2o = NO (WITH_G2O=OFF)")
MESSAGE(STATUS " *With g2o = NO (WITH_G2O=OFF)")
ELSE()
MESSAGE(STATUS " With g2o = NO (g2o not found)")
MESSAGE(STATUS " *With g2o = NO (g2o not found)")
ENDIF()
IF(GTSAM_FOUND)
MESSAGE(STATUS " With GTSAM = YES (License: BSD)")
MESSAGE(STATUS " *With GTSAM = YES (License: BSD)")
ELSEIF(NOT WITH_GTSAM)
MESSAGE(STATUS " With GTSAM = NO (WITH_GTSAM=OFF)")
MESSAGE(STATUS " *With GTSAM = NO (WITH_GTSAM=OFF)")
ELSE()
MESSAGE(STATUS " With GTSAM = NO (GTSAM not found)")
MESSAGE(STATUS " *With GTSAM = NO (GTSAM not found)")
ENDIF()
IF(G2O_FOUND OR GTSAM_FOUND)
@@ -833,11 +980,19 @@ MESSAGE(STATUS " With cvsba = NO (cvsba not found)")
ENDIF()
IF(libpointmatcher_FOUND)
MESSAGE(STATUS " With libpointmatcher = YES (License: BSD)")
MESSAGE(STATUS " *With libpointmatcher = YES (License: BSD)")
ELSEIF(NOT WITH_POINTMATCHER)
MESSAGE(STATUS " With libpointmatcher = NO (WITH_POINTMATCHER=OFF)")
MESSAGE(STATUS " *With libpointmatcher = NO (WITH_POINTMATCHER=OFF)")
ELSE()
MESSAGE(STATUS " With libpointmatcher = NO (libpointmatcher not found)")
MESSAGE(STATUS " *With libpointmatcher = NO (libpointmatcher not found)")
ENDIF()
IF(loam_velodyne_FOUND)
MESSAGE(STATUS " With loam_velodyne = YES (License: BSD)")
ELSEIF(NOT WITH_LOAM)
MESSAGE(STATUS " With loam_velodyne = NO (WITH_LOAM=OFF)")
ELSE()
MESSAGE(STATUS " With loam_velodyne = NO (loam_velodyne not found)")
ENDIF()
IF(ZED_FOUND)
@@ -867,6 +1022,14 @@ ELSE()
MESSAGE(STATUS " With RealSense = NO (librealsense not found)")
ENDIF()
IF(realsense2_FOUND)
MESSAGE(STATUS " With RealSense2 = YES (License: Apache-2)")
ELSEIF(NOT WITH_REALSENSE2)
MESSAGE(STATUS " With RealSense2 = NO (WITH_REALSENSE2=OFF)")
ELSE()
MESSAGE(STATUS " With RealSense2 = NO (librealsense2 not found)")
ENDIF()
IF(OCTOMAP_FOUND)
MESSAGE(STATUS " With OCTOMAP = YES (License: BSD)")
ELSEIF(NOT WITH_OCTOMAP)
@@ -883,6 +1046,14 @@ ELSE()
MESSAGE(STATUS " With CPUTSDF = NO (CPUTSDF not found)")
ENDIF()
IF(open_chisel_FOUND)
MESSAGE(STATUS " With OpenChisel = YES (License: ???)")
ELSEIF(NOT WITH_OPENCHISEL)
MESSAGE(STATUS " With OpenChisel = NO (WITH_OPENCHISEL=OFF)")
ELSE()
MESSAGE(STATUS " With OpenChisel = NO (open_chisel not found)")
ENDIF()
IF(libfovis_FOUND)
MESSAGE(STATUS " With libfovis = YES (License: GPLv2)")
ELSEIF(NOT WITH_FOVIS)
@@ -907,6 +1078,22 @@ ELSE()
MESSAGE(STATUS " With dvo_core = NO (dvo_core not found)")
ENDIF()
IF(okvis_FOUND)
MESSAGE(STATUS " With okvis = YES (License: BSD)")
ELSEIF(NOT WITH_OKVIS)
MESSAGE(STATUS " With okvis = NO (WITH_OKVIS=OFF)")
ELSE()
MESSAGE(STATUS " With okvis = NO (okvis not found)")
ENDIF()
IF(msckf_vio_FOUND)
MESSAGE(STATUS " With msckf_vio = YES (License: Penn Software License)")
ELSEIF(NOT WITH_MSCKF_VIO)
MESSAGE(STATUS " With msckf_vio = NO (WITH_MSCKF_VIO=OFF)")
ELSE()
MESSAGE(STATUS " With msckf_vio = NO (msckf_vio not found)")
ENDIF()
IF(ORB_SLAM2_FOUND)
MESSAGE(STATUS " With ORB_SLAM2 = YES (License: GPLv3)")
ELSEIF(NOT WITH_ORB_SLAM2)
+4 -3
View File
@@ -1,12 +1,13 @@
rtabmap [![Build Status](https://travis-ci.org/introlab/rtabmap.svg?branch=master)](https://travis-ci.org/introlab/rtabmap)
rtabmap ![Analytics](https://ga-beacon.appspot.com/UA-56986679-3/github-main?pixel)
=======
<a href="http://introlab.github.io/rtabmap"><img src="https://raw.githubusercontent.com/introlab/rtabmap/master/guilib/src/images/RTAB-Map.png" align="center" height="100">
[![RTAB-Map Logo](https://raw.githubusercontent.com/introlab/rtabmap/master/guilib/src/images/RTAB-Map100.png)](http://introlab.github.io/rtabmap)
[![Release][release-image]][releases]
[![License][license-image]][license]
Linux: [![Build Status](https://travis-ci.org/introlab/rtabmap.svg?branch=master)](https://travis-ci.org/introlab/rtabmap) Windows: [![Build status](https://ci.appveyor.com/api/projects/status/hr73xspix9oqa26h/branch/master?svg=true)](https://ci.appveyor.com/project/matlabbe/rtabmap/branch/master)
[release-image]: https://img.shields.io/badge/release-0.13.0-green.svg?style=flat
[release-image]: https://img.shields.io/badge/release-0.16.3-green.svg?style=flat
[releases]: https://github.com/introlab/rtabmap/releases
[license-image]: https://img.shields.io/badge/license-BSD-green.svg?style=flat
+7
View File
@@ -40,24 +40,31 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@NONFREE@#define RTABMAP_NONFREE
@TORO@#define RTABMAP_TORO
@G2O@#define RTABMAP_G2O
@G2O_CPP_CONF@#define RTABMAP_G2O_CPP11
@GTSAM@#define RTABMAP_GTSAM
@VERTIGO@#define RTABMAP_VERTIGO
@OPENCV3@#define RTABMAP_OPENCV3
@OPENNI2@#define RTABMAP_OPENNI2
@FREENECT@#define RTABMAP_FREENECT
@FREENECT2@#define RTABMAP_FREENECT2
@K4W2@#define RTABMAP_K4W2
@CVSBA@#define RTABMAP_CVSBA
@POINTMATCHER@#define RTABMAP_POINTMATCHER
@LOAM@#define RTABMAP_LOAM
@DC1394@#define RTABMAP_DC1394
@FLYCAPTURE2@#define RTABMAP_FLYCAPTURE2
@ZED@#define RTABMAP_ZED
@REALSENSE@#define RTABMAP_REALSENSE
@REALSENSESLAM@#define RTABMAP_REALSENSE_SLAM
@REALSENSE2@#define RTABMAP_REALSENSE2
@OCTOMAP@#define RTABMAP_OCTOMAP
@CPUTSDF@#define RTABMAP_CPUTSDF
@OPENCHISEL@#define RTABMAP_OPENCHISEL
@FOVIS@#define RTABMAP_FOVIS
@VISO2@#define RTABMAP_VISO2
@DVO@#define RTABMAP_DVO
@OKVIS@#define RTABMAP_OKVIS
@MSCKF_VIO@#define RTABMAP_MSCKF_VIO
@ORB_SLAM2@#define RTABMAP_ORB_SLAM2
#endif /* VERSION_H_ */
+1 -1
View File
@@ -2,7 +2,7 @@
<!-- BEGIN_INCLUDE(manifest) -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.introlab.rtabmap"
android:versionCode="58"
android:versionCode="70"
android:versionName="@RTABMAP_VERSION@">
<uses-permission android:name="android.permission.CAMERA" />
+88 -33
View File
@@ -46,7 +46,7 @@ const int scanDownsampling = 1;
void onPointCloudAvailableRouter(void* context, const TangoPointCloud* point_cloud)
{
CameraTango* app = static_cast<CameraTango*>(context);
if(point_cloud->num_points>0)
if(app->isRunning() && point_cloud->num_points>0)
{
app->cloudReceived(cv::Mat(1, point_cloud->num_points, CV_32FC4, point_cloud->points[0]), point_cloud->timestamp);
}
@@ -55,31 +55,34 @@ void onPointCloudAvailableRouter(void* context, const TangoPointCloud* point_clo
void onFrameAvailableRouter(void* context, TangoCameraId id, const TangoImageBuffer* color)
{
CameraTango* app = static_cast<CameraTango*>(context);
cv::Mat tangoImage;
if(color->format == TANGO_HAL_PIXEL_FORMAT_RGBA_8888)
if(app->isRunning())
{
tangoImage = cv::Mat(color->height, color->width, CV_8UC4, color->data);
}
else if(color->format == TANGO_HAL_PIXEL_FORMAT_YV12)
{
tangoImage = cv::Mat(color->height+color->height/2, color->width, CV_8UC1, color->data);
}
else if(color->format == TANGO_HAL_PIXEL_FORMAT_YCrCb_420_SP)
{
tangoImage = cv::Mat(color->height+color->height/2, color->width, CV_8UC1, color->data);
}
else if(color->format == 35)
{
tangoImage = cv::Mat(color->height+color->height/2, color->width, CV_8UC1, color->data);
}
else
{
LOGE("Not supported color format : %d.", color->format);
}
cv::Mat tangoImage;
if(color->format == TANGO_HAL_PIXEL_FORMAT_RGBA_8888)
{
tangoImage = cv::Mat(color->height, color->width, CV_8UC4, color->data);
}
else if(color->format == TANGO_HAL_PIXEL_FORMAT_YV12)
{
tangoImage = cv::Mat(color->height+color->height/2, color->width, CV_8UC1, color->data);
}
else if(color->format == TANGO_HAL_PIXEL_FORMAT_YCrCb_420_SP)
{
tangoImage = cv::Mat(color->height+color->height/2, color->width, CV_8UC1, color->data);
}
else if(color->format == 35)
{
tangoImage = cv::Mat(color->height+color->height/2, color->width, CV_8UC1, color->data);
}
else
{
LOGE("Not supported color format : %d.", color->format);
}
if(!tangoImage.empty())
{
app->rgbReceived(tangoImage, (unsigned int)color->format, color->timestamp);
if(!tangoImage.empty())
{
app->rgbReceived(tangoImage, (unsigned int)color->format, color->timestamp);
}
}
}
@@ -116,7 +119,8 @@ CameraTango::CameraTango(bool colorCamera, int decimation, bool publishRawScan,
cloudStamp_(0),
tangoColorType_(0),
tangoColorStamp_(0),
colorCameraToDisplayRotation_(ROTATION_0)
colorCameraToDisplayRotation_(ROTATION_0),
originUpdate_(false)
{
UASSERT(decimation >= 1);
}
@@ -189,8 +193,6 @@ bool CameraTango::init(const std::string & calibrationFolder, const std::string
{
close();
lastKnownGPS_ = GPS();
TangoSupport_initialize(TangoService_getPoseAtTime, TangoService_getCameraIntrinsics);
// Connect to Tango
@@ -427,12 +429,22 @@ void CameraTango::close()
{
TangoConfig_free(tango_config_);
tango_config_ = nullptr;
LOGI("TangoService_disconnect()");
TangoService_disconnect();
LOGI("TangoService_disconnect() done.");
}
previousPose_.setNull();
previousStamp_ = 0.0;
fisheyeRectifyMapX_ = cv::Mat();
fisheyeRectifyMapY_ = cv::Mat();
lastKnownGPS_ = GPS();
originOffset_ = Transform();
originUpdate_ = false;
}
void CameraTango::resetOrigin()
{
originUpdate_ = true;
}
void CameraTango::cloudReceived(const cv::Mat & cloud, double timestamp)
@@ -493,10 +505,23 @@ static rtabmap::Transform opticalRotation(
0.0f, 0.0f, -1.0f, 0.0f);
void CameraTango::poseReceived(const Transform & pose)
{
if(!pose.isNull() && pose.getNormSquared() < 100000)
if(!pose.isNull())
{
// send pose of the camera (without optical rotation), not the device
this->post(new PoseEvent(pose*deviceTColorCamera_*opticalRotation));
Transform p = pose*deviceTColorCamera_*opticalRotation;
if(originUpdate_)
{
originOffset_ = p.translation().inverse();
originUpdate_ = false;
}
if(!originOffset_.isNull())
{
this->post(new PoseEvent(originOffset_*p));
}
else
{
this->post(new PoseEvent(p));
}
}
}
@@ -706,6 +731,13 @@ SensorData CameraTango::captureImage(CameraInfo * info)
CameraModel depthModel = model_.scaled(1.0f/float(depthSizeDec));
std::vector<cv::Point3f> scanData(rawScanPublished_?cloud.total():0);
int oi=0;
int closePoints = 0;
float closeROI[4];
closeROI[0] = depth.cols/4;
closeROI[1] = 3*(depth.cols/4);
closeROI[2] = depth.rows/4;
closeROI[3] = 3*(depth.rows/4);
unsigned short minDepthValue=10000;
for(unsigned int i=0; i<cloud.total(); ++i)
{
float * p = cloud.ptr<float>(0,i);
@@ -724,6 +756,17 @@ SensorData CameraTango::captureImage(CameraInfo * info)
pixel_y_h = static_cast<int>((depthModel.fy()) * (pt.y / pt.z) + depthModel.cy() + 0.5f);
unsigned short depth_value(pt.z * 1000.0f);
if(pixel_x_l>=closeROI[0] && pixel_x_l<closeROI[1] &&
pixel_y_l>closeROI[2] && pixel_y_l<closeROI[3] &&
depth_value < 600)
{
++closePoints;
if(depth_value < minDepthValue)
{
minDepthValue = depth_value;
}
}
bool pixelSet = false;
if(pixel_x_l>=0 && pixel_x_l<depth.cols &&
pixel_y_l>0 && pixel_y_l<depth.rows && // ignore first line
@@ -753,6 +796,11 @@ SensorData CameraTango::captureImage(CameraInfo * info)
}
}
if(closePoints > 100)
{
this->post(new CameraTangoEvent(0, "TooClose", ""));
}
if(oi)
{
scan = cv::Mat(1, oi, CV_32FC3, scanData.data()).clone();
@@ -770,6 +818,12 @@ SensorData CameraTango::captureImage(CameraInfo * info)
Transform poseDevice = getPoseAtTimestamp(rgbStamp);
// adjust origin
if(!originOffset_.isNull())
{
poseDevice = originOffset_ * poseDevice;
}
//LOGD("Local = %s", model.localTransform().prettyPrint().c_str());
//LOGD("tango = %s", poseDevice.prettyPrint().c_str());
//LOGD("opengl(t)= %s", (opengl_world_T_tango_world * poseDevice).prettyPrint().c_str());
@@ -837,7 +891,7 @@ SensorData CameraTango::captureImage(CameraInfo * info)
if(rawScanPublished_)
{
data = SensorData(scan, LaserScanInfo(cloud.total()/scanDownsampling, 0, scanLocalTransform), rgb, depth, model, this->getNextSeqID(), rgbStamp);
data = SensorData(LaserScan::backwardCompatibility(scan, cloud.total()/scanDownsampling, 0, scanLocalTransform), rgb, depth, model, this->getNextSeqID(), rgbStamp);
}
else
{
@@ -845,7 +899,7 @@ SensorData CameraTango::captureImage(CameraInfo * info)
}
data.setGroundTruth(odom);
if(lastKnownGPS_.stamp() > 0.0 && rgbStamp-lastKnownGPS_.stamp()<2.0)
if(lastKnownGPS_.stamp() > 0.0 && rgbStamp-lastKnownGPS_.stamp()<1.0)
{
data.setGPS(lastKnownGPS_);
}
@@ -882,6 +936,7 @@ void CameraTango::mainLoop()
{
rtabmap::Transform pose = data.groundTruth();
data.setGroundTruth(Transform());
// convert stamp to epoch
bool firstFrame = previousPose_.isNull();
if(firstFrame)
@@ -895,8 +950,8 @@ void CameraTango::mainLoop()
info.interval = data.stamp()-previousStamp_;
info.transform = previousPose_.inverse() * pose;
}
info.reg.covariance = cv::Mat::eye(6,6,CV_64FC1) * (firstFrame?9999.0:0.000001);
LOGI("Publish odometry message (variance=%f)", firstFrame?9999:0.000001);
info.reg.covariance = cv::Mat::eye(6,6,CV_64FC1) * (firstFrame?9999.0:0.0001);
LOGI("Publish odometry message (variance=%f)", firstFrame?9999:0.0001);
this->post(new OdometryEvent(data, pose, info));
previousPose_ = pose;
previousStamp_ = data.stamp();
+3
View File
@@ -81,6 +81,7 @@ public:
virtual bool init(const std::string & calibrationFolder = ".", const std::string & cameraName = "");
void close(); // close Tango connection
void resetOrigin();
virtual bool isCalibrated() const;
virtual std::string getSerial() const;
const CameraModel & getCameraModel() const {return model_;}
@@ -129,6 +130,8 @@ private:
cv::Mat fisheyeRectifyMapX_;
cv::Mat fisheyeRectifyMapY_;
GPS lastKnownGPS_;
Transform originOffset_;
bool originUpdate_;
};
} /* namespace rtabmap */
+263 -114
View File
@@ -93,12 +93,13 @@ rtabmap::ParametersMap RTABMapApp::getRtabmapParameters()
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kKpParallelized(), std::string("false")));
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kKpMaxDepth(), std::string("10"))); // to avoid extracting features in invalid depth (as we compute transformation directly from the words)
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kRGBDOptimizeFromGraphEnd(), std::string("true")));
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kDbSqlite3InMemory(), std::string("true")));
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kVisMinInliers(), std::string("25")));
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.1")));
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kRGBDOptimizeMaxError(), std::string("1")));
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kRGBDProximityPathMaxNeighbors(), std::string("0"))); // disable scan matching to merged nodes
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kRGBDProximityBySpace(), std::string("false"))); // just keep loop closure detection
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kRGBDLinearUpdate(), std::string("0.05")));
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kRGBDAngularUpdate(), std::string("0.05")));
if(parameters.find(rtabmap::Parameters::kOptimizerStrategy()) != parameters.end())
{
@@ -183,11 +184,12 @@ RTABMapApp::RTABMapApp() :
lastDrawnCloudsCount_(0),
renderingTime_(0.0f),
lastPostRenderEventTime_(0.0),
processMemoryUsedBytes(0),
processGPUMemoryUsedBytes(0),
lastPoseEventTime_(0.0),
visualizingMesh_(false),
exportedMeshUpdated_(false),
optMesh_(new pcl::TextureMesh),
optRefId_(0),
optRefPose_(0),
mapToOdom_(rtabmap::Transform::getIdentity())
{
@@ -195,28 +197,45 @@ RTABMapApp::RTABMapApp() :
}
RTABMapApp::~RTABMapApp() {
if(camera_)
{
delete camera_;
}
if(rtabmapThread_)
{
rtabmapThread_->close(false);
delete rtabmapThread_;
}
if(logHandler_)
{
delete logHandler_;
}
boost::mutex::scoped_lock lock(rtabmapMutex_);
if(rtabmapEvents_.size())
{
for(std::list<rtabmap::RtabmapEvent*>::iterator iter=rtabmapEvents_.begin(); iter!=rtabmapEvents_.end(); ++iter)
{
delete *iter;
}
}
rtabmapEvents_.clear();
if(camera_)
{
delete camera_;
}
if(rtabmapThread_)
{
rtabmapThread_->close(false);
delete rtabmapThread_;
}
if(logHandler_)
{
delete logHandler_;
}
if(optRefPose_)
{
delete optRefPose_;
}
{
boost::mutex::scoped_lock lock(rtabmapMutex_);
if(rtabmapEvents_.size())
{
for(std::list<rtabmap::RtabmapEvent*>::iterator iter=rtabmapEvents_.begin(); iter!=rtabmapEvents_.end(); ++iter)
{
delete *iter;
}
}
rtabmapEvents_.clear();
}
{
boost::mutex::scoped_lock lock(visLocalizationMutex_);
if(visLocalizationEvents_.size())
{
for(std::list<rtabmap::RtabmapEvent*>::iterator iter=visLocalizationEvents_.begin(); iter!=visLocalizationEvents_.end(); ++iter)
{
delete *iter;
}
}
visLocalizationEvents_.clear();
}
}
void RTABMapApp::onCreate(JNIEnv* env, jobject caller_activity)
@@ -236,8 +255,7 @@ void RTABMapApp::onCreate(JNIEnv* env, jobject caller_activity)
lastDrawnCloudsCount_ = 0;
renderingTime_ = 0.0f;
lastPostRenderEventTime_ = 0.0;
processMemoryUsedBytes = 0;
processGPUMemoryUsedBytes = 0;
lastPoseEventTime_ = 0.0;
bufferedStatsData_.clear();
progressionStatus_.setJavaObjects(jvm, RTABMapActivity);
main_scene_.setBackgroundColor(backgroundColor_, backgroundColor_, backgroundColor_);
@@ -279,6 +297,13 @@ int RTABMapApp::openDatabase(const std::string & databasePath, bool databaseInMe
this->unregisterFromEventsManager(); // to ignore published init events when closing rtabmap
status_.first = rtabmap::RtabmapEventInit::kInitializing;
rtabmapMutex_.lock();
if(rtabmapEvents_.size())
{
for(std::list<rtabmap::RtabmapEvent*>::iterator iter=rtabmapEvents_.begin(); iter!=rtabmapEvents_.end(); ++iter)
{
delete *iter;
}
}
rtabmapEvents_.clear();
openingDatabase_ = true;
if(rtabmapThread_)
@@ -296,6 +321,12 @@ int RTABMapApp::openDatabase(const std::string & databasePath, bool databaseInMe
// Open visualization while we load (if there is an optimized mesh saved in database)
optMesh_.reset(new pcl::TextureMesh);
optTexture_ = cv::Mat();
optRefId_ = 0;
if(optRefPose_)
{
delete optRefPose_;
optRefPose_ = 0;
}
cv::Mat cloudMat;
std::vector<std::vector<std::vector<unsigned int> > > polygons;
#if PCL_VERSION_COMPARE(>=, 1, 8, 0)
@@ -304,14 +335,13 @@ int RTABMapApp::openDatabase(const std::string & databasePath, bool databaseInMe
std::vector<std::vector<Eigen::Vector2f> > texCoords;
#endif
cv::Mat textures;
std::map<int, rtabmap::Transform> optPoses;
if(!databaseSource.empty())
{
UEventsManager::post(new rtabmap::RtabmapEventInit(rtabmap::RtabmapEventInit::kInfo, "Loading optimized cloud/mesh..."));
rtabmap::DBDriver * driver = rtabmap::DBDriver::create();
if(driver->openConnection(databaseSource))
{
cloudMat = driver->loadOptimizedMesh(&optPoses, &polygons, &texCoords, &textures);
cloudMat = driver->loadOptimizedMesh(&polygons, &texCoords, &textures);
if(!cloudMat.empty())
{
LOGI("Open: Found optimized mesh! Visualizing it.");
@@ -403,7 +433,7 @@ int RTABMapApp::openDatabase(const std::string & databasePath, bool databaseInMe
}
{
LOGI("Creating the meshes (%d)....", poses.size());
LOGI("Creating the meshes (%d)....", (int)poses.size());
boost::mutex::scoped_lock lock(meshesMutex_);
createdMeshes_.clear();
int i=0;
@@ -480,16 +510,6 @@ int RTABMapApp::openDatabase(const std::string & databasePath, bool databaseInMe
UERROR("Failed to uncompress data!");
status=-2;
}
const rtabmap::Signature & s = signatures.at(id);
processMemoryUsedBytes += data.imageCompressed().total();
processMemoryUsedBytes += data.depthOrRightCompressed().total();
processMemoryUsedBytes += data.laserScanCompressed().total();
processMemoryUsedBytes += s.getWords().size()*4*8;
processMemoryUsedBytes += s.getWords3().size()*4*4;
if(!s.getWordsDescriptors().empty())
{
processMemoryUsedBytes +=s.getWordsDescriptors().size()*(4+s.getWordsDescriptors().begin()->second.total());
}
}
else
{
@@ -565,6 +585,19 @@ int RTABMapApp::openDatabase(const std::string & databasePath, bool databaseInMe
rtabmap_->setOptimizedPoses(poses);
// for optimized mesh
if(poses.size())
{
// just take the last as reference
optRefId_ = poses.rbegin()->first;
optRefPose_ = new rtabmap::Transform(poses.rbegin()->second);
}
if(camera_)
{
camera_->resetOrigin();
}
// Start threads
LOGI("Start rtabmap thread");
rtabmapThread_->registerToEventsManager();
@@ -735,7 +768,7 @@ std::vector<pcl::Vertices> RTABMapApp::filterOrganizedPolygons(
unsigned int biggestClusterSize = 0;
for(std::map<int, std::list<int> >::iterator iter=clusters.begin(); iter!=clusters.end(); ++iter)
{
LOGD("cluster %d = %d", iter->first, iter->second.size());
LOGD("cluster %d = %d", iter->first, (int)iter->second.size());
if(iter->second.size() > biggestClusterSize)
{
@@ -995,14 +1028,12 @@ int RTABMapApp::Render()
poseEvents_.clear();
}
}
rtabmap::Transform mapOdom = rtabmap::Transform::getIdentity();
if(!pose.isNull())
{
// update camera pose?
if(graphOptimization_ && !visualizingMesh_ && !mapToOdom_.isIdentity())
if(graphOptimization_ && !mapToOdom_.isIdentity())
{
mapOdom = mapToOdom_;
main_scene_.SetCameraPose(opengl_world_T_rtabmap_world*mapOdom*rtabmap_world_T_tango_world*pose);
main_scene_.SetCameraPose(opengl_world_T_rtabmap_world*mapToOdom_*rtabmap_world_T_tango_world*pose);
}
else
{
@@ -1013,6 +1044,7 @@ int RTABMapApp::Render()
notifyCameraStarted = true;
cameraJustInitialized_ = false;
}
lastPoseEventTime_ = UTimer::now();
}
rtabmap::OdometryEvent odomEvent;
@@ -1061,7 +1093,6 @@ int RTABMapApp::Render()
mesh.texCoords = optMesh_->tex_coordinates[0];
mesh.texture = optTexture_;
}
main_scene_.addMesh(g_optMeshId, mesh, opengl_world_T_rtabmap_world, true);
}
else
@@ -1071,6 +1102,58 @@ int RTABMapApp::Render()
pcl::fromPCLPointCloud2(optMesh_->cloud, *cloud);
main_scene_.addCloud(g_optMeshId, cloud, indices, opengl_world_T_rtabmap_world);
}
// clean up old messages if there are ones
boost::mutex::scoped_lock lock(visLocalizationMutex_);
if(visLocalizationEvents_.size())
{
for(std::list<rtabmap::RtabmapEvent*>::iterator iter=visLocalizationEvents_.begin(); iter!=visLocalizationEvents_.end(); ++iter)
{
delete *iter;
}
}
visLocalizationEvents_.clear();
}
std::list<rtabmap::RtabmapEvent*> visLocalizationEvents;
visLocalizationMutex_.lock();
visLocalizationEvents = visLocalizationEvents_;
visLocalizationEvents_.clear();
visLocalizationMutex_.unlock();
if(visLocalizationEvents.size())
{
const rtabmap::Statistics & stats = visLocalizationEvents.back()->getStats();
if(!stats.mapCorrection().isNull())
{
mapToOdom_ = stats.mapCorrection();
}
std::map<int, rtabmap::Transform>::const_iterator iter = stats.poses().find(optRefId_);
if(iter != stats.poses().end() && !iter->second.isNull() && optRefPose_)
{
// adjust opt mesh pose
main_scene_.setCloudPose(g_optMeshId, opengl_world_T_rtabmap_world * iter->second * (*optRefPose_).inverse());
}
int fastMovement = (int)uValue(stats.data(), rtabmap::Statistics::kMemoryFast_movement(), 0.0f);
int loopClosure = (int)uValue(stats.data(), rtabmap::Statistics::kLoopAccepted_hypothesis_id(), 0.0f);
int rejected = (int)uValue(stats.data(), rtabmap::Statistics::kLoopRejectedHypothesis(), 0.0f);
if(!paused_ && loopClosure>0)
{
main_scene_.setBackgroundColor(0, 0.5f, 0); // green
}
else if(!paused_ && rejected>0)
{
main_scene_.setBackgroundColor(0, 0.2f, 0); // dark green
}
else if(!paused_ && fastMovement)
{
main_scene_.setBackgroundColor(0.2f, 0, 0.2f); // dark magenta
}
else
{
main_scene_.setBackgroundColor(backgroundColor_, backgroundColor_, backgroundColor_);
}
}
//backup state
@@ -1088,6 +1171,20 @@ int RTABMapApp::Render()
// revert state
main_scene_.setMeshRendering(isMeshRendering, isTextureRendering);
if(visLocalizationEvents.size())
{
// send statistics to GUI
UEventsManager::post(new PostRenderEvent(visLocalizationEvents.back()));
visLocalizationEvents.pop_back();
for(std::list<rtabmap::RtabmapEvent*>::iterator iter=visLocalizationEvents.begin(); iter!=visLocalizationEvents.end(); ++iter)
{
delete *iter;
}
visLocalizationEvents.clear();
lastPostRenderEventTime_ = UTimer::now();
}
}
else
{
@@ -1155,8 +1252,7 @@ int RTABMapApp::Render()
lastDrawnCloudsCount_ = 0;
renderingTime_ = 0.0f;
lastPostRenderEventTime_ = 0.0;
processMemoryUsedBytes = 0;
processGPUMemoryUsedBytes = 0;
lastPoseEventTime_ = 0.0;
bufferedStatsData_.clear();
}
@@ -1170,7 +1266,6 @@ int RTABMapApp::Render()
if(added.size() != meshes)
{
LOGI("added (%d) != meshes (%d)", (int)added.size(), meshes);
processGPUMemoryUsedBytes = 0;
boost::mutex::scoped_lock lockRtabmap(rtabmapMutex_);
UASSERT(rtabmap_!=0);
for(std::map<int, Mesh>::iterator iter=createdMeshes_.begin(); iter!=createdMeshes_.end(); ++iter)
@@ -1205,14 +1300,6 @@ int RTABMapApp::Render()
main_scene_.addMesh(iter->first, iter->second, opengl_world_T_rtabmap_world*iter->second.pose);
main_scene_.setCloudVisible(iter->first, iter->second.visible);
long estimateGPUMem = 0;
estimateGPUMem += iter->second.cloud->size()*16; // 3*float + 1 float rgb
estimateGPUMem += iter->second.indices->size()*4; // int
estimateGPUMem += iter->second.polygons.size()*4*3; // 3 indices per polygon
estimateGPUMem += iter->second.polygonsLowRes.size()*4*3; // 3 indices per polygon
processGPUMemoryUsedBytes += estimateGPUMem + (iter->second.texture.empty()?0:iter->second.polygons.size()*3*8+iter->second.texture.total());
iter->second.texture = cv::Mat(); // don't keep textures in memory
}
}
@@ -1237,7 +1324,7 @@ int RTABMapApp::Render()
// update buffered signatures
std::map<int, rtabmap::SensorData> bufferedSensorData;
if(!trajectoryMode_ && !dataRecorderMode_)
if(!dataRecorderMode_)
{
for(std::list<rtabmap::RtabmapEvent*>::iterator iter=rtabmapEvents.begin(); iter!=rtabmapEvents.end(); ++iter)
{
@@ -1245,42 +1332,29 @@ int RTABMapApp::Render()
// Don't create mesh for the last node added if rehearsal happened or if discarded (small movement)
int smallMovement = (int)uValue(stats.data(), rtabmap::Statistics::kMemorySmall_movement(), 0.0f);
int fastMovement = (int)uValue(stats.data(), rtabmap::Statistics::kMemoryFast_movement(), 0.0f);
int rehearsalMerged = (int)uValue(stats.data(), rtabmap::Statistics::kMemoryRehearsal_merged(), 0.0f);
if(smallMovement == 0 && rehearsalMerged == 0)
if(!localizationMode_ && stats.getSignatures().size() &&
smallMovement == 0 && rehearsalMerged == 0 && fastMovement == 0)
{
for(std::map<int, rtabmap::Signature>::const_iterator jter=stats.getSignatures().begin(); jter!=stats.getSignatures().end(); ++jter)
int id = stats.getSignatures().rbegin()->first;
const rtabmap::Signature & s = stats.getSignatures().rbegin()->second;
if(!trajectoryMode_ &&
!s.sensorData().imageRaw().empty() &&
!s.sensorData().depthRaw().empty())
{
bool dataDetected = false;
if(!jter->second.sensorData().imageRaw().empty() &&
!jter->second.sensorData().depthRaw().empty())
{
if(!localizationMode_)
{
uInsert(bufferedSensorData, std::make_pair(jter->first, jter->second.sensorData()));
uInsert(rawPoses_, std::make_pair(jter->first, jter->second.getPose()));
dataDetected = true;
}
}
if(dataDetected)
{
processMemoryUsedBytes += jter->second.sensorData().imageCompressed().total();
processMemoryUsedBytes += jter->second.sensorData().depthOrRightCompressed().total();
processMemoryUsedBytes += jter->second.sensorData().laserScanCompressed().total();
processMemoryUsedBytes += jter->second.getWords().size()*4*8;
processMemoryUsedBytes += jter->second.getWords3().size()*4*4;
if(!jter->second.getWordsDescriptors().empty())
{
processMemoryUsedBytes += jter->second.getWordsDescriptors().size()*(4+jter->second.getWordsDescriptors().begin()->second.total());
}
}
uInsert(bufferedSensorData, std::make_pair(id, s.sensorData()));
}
uInsert(rawPoses_, std::make_pair(id, s.getPose()));
}
int loopClosure = (int)uValue(stats.data(), rtabmap::Statistics::kLoopAccepted_hypothesis_id(), 0.0f);
int rejected = (int)uValue(stats.data(), rtabmap::Statistics::kLoopRejectedHypothesis(), 0.0f);
if(!paused_ && loopClosure>0)
{
main_scene_.setBackgroundColor(0, 0.7f, 0); // green
main_scene_.setBackgroundColor(0, 0.5f, 0); // green
}
else if(!paused_ && rejected>0)
{
@@ -1290,12 +1364,17 @@ int RTABMapApp::Render()
{
main_scene_.setBackgroundColor(0, 0, 0.2f); // blue
}
else if(!paused_ && fastMovement)
{
main_scene_.setBackgroundColor(0.2f, 0, 0.2f); // dark magenta
}
else
{
main_scene_.setBackgroundColor(backgroundColor_, backgroundColor_, backgroundColor_);
}
}
}
#ifdef DEBUG_RENDERING_PERFORMANCE
LOGW("Looking fo data to load (%d) %fs", bufferedSensorData.size(), time.ticks());
#endif
@@ -1431,13 +1510,6 @@ int RTABMapApp::Render()
#ifdef DEBUG_RENDERING_PERFORMANCE
LOGW("Adding mesh to scene: %fs", time.ticks());
#endif
long estimateCPUMem = 0;
estimateCPUMem += mesh.cloud->size()*16; // 3*float + 1 float rgb
estimateCPUMem += mesh.indices->size()*4; // int
estimateCPUMem += mesh.polygons.size()*4*3; // 3 indices per polygon
processMemoryUsedBytes += estimateCPUMem;
processGPUMemoryUsedBytes += estimateCPUMem + (mesh.texture.empty()?0:mesh.polygons.size()*3*8+mesh.texture.total());
mesh.texture = cv::Mat(); // don't keep textures in memory
}
}
@@ -1500,7 +1572,7 @@ int RTABMapApp::Render()
odomEvent.data().imageRaw().cols, odomEvent.data().imageRaw().rows,
odomEvent.data().depthRaw().cols, odomEvent.data().depthRaw().rows,
(int)cloud->width, (int)cloud->height);
main_scene_.addCloud(-1, cloud, indices, opengl_world_T_rtabmap_world*mapOdom*odomEvent.pose());
main_scene_.addCloud(-1, cloud, indices, opengl_world_T_rtabmap_world*mapToOdom_*odomEvent.pose());
main_scene_.setCloudVisible(-1, true);
}
else
@@ -1584,6 +1656,12 @@ int RTABMapApp::Render()
rtabmapEvents.clear();
lastPostRenderEventTime_ = UTimer::now();
if(lastPoseEventTime_>0.0 && UTimer::now()-lastPoseEventTime_ > 1.0)
{
UERROR("TangoPoseEventNotReceived");
UEventsManager::post(new rtabmap::CameraTangoEvent(10, "TangoPoseEventNotReceived", uNumber2Str(UTimer::now()-lastPoseEventTime_)));
}
}
}
@@ -1697,7 +1775,10 @@ void RTABMapApp::setPausedMapping(bool paused)
{
{
boost::mutex::scoped_lock lock(renderingMutex_);
visualizingMesh_ = false;
if(!localizationMode_)
{
visualizingMesh_ = false;
}
main_scene_.setBackgroundColor(backgroundColor_, backgroundColor_, backgroundColor_);
}
paused_ = paused;
@@ -1992,6 +2073,11 @@ void RTABMapApp::resetMapping()
mapToOdom_.setIdentity();
clearSceneOnNextRender_ = true;
if(camera_)
{
camera_->resetOrigin();
}
UEventsManager::post(new rtabmap::RtabmapEventCmd(rtabmap::RtabmapEventCmd::kCmdResetMemory));
}
@@ -2020,12 +2106,19 @@ void RTABMapApp::save(const std::string & databasePath)
dataRecorderMode_ = false;
}
if(appendModeBackup || dataRecorderModeBackup)
bool localizationModeBackup = localizationMode_;
if(localizationMode_)
{
localizationMode_ = false;
}
if(appendModeBackup || dataRecorderModeBackup || localizationModeBackup)
{
rtabmap::ParametersMap parameters = getRtabmapParameters();
rtabmap_->parseParameters(parameters);
appendMode_ = appendModeBackup;
dataRecorderMode_ = dataRecorderModeBackup;
localizationMode_ = localizationModeBackup;
}
std::map<int, rtabmap::Transform> poses = rtabmap_->getLocalOptimizedPoses();
@@ -2157,11 +2250,12 @@ bool RTABMapApp::exportMesh(
++iter)
{
std::map<int, Mesh>::iterator jter = createdMeshes_.find(iter->first);
pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud;
pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZRGB>);
pcl::IndicesPtr indices(new std::vector<int>);
rtabmap::CameraModel model;
cv::Mat depth;
float gains[3] = {1.0f};
float gains[3];
gains[0] = gains[1] = gains[2] = 1.0f;
if(jter != createdMeshes_.end())
{
cloud = jter->second.cloud;
@@ -2280,7 +2374,7 @@ bool RTABMapApp::exportMesh(
poisson.setDepth(optimizedDepth);
poisson.setInputCloud(mergedClouds);
poisson.reconstruct(*mesh);
LOGI("Mesh reconstruction... done! %fs (%d polygons)", timer.ticks(), mesh->polygons.size());
LOGI("Mesh reconstruction... done! %fs (%d polygons)", timer.ticks(), (int)mesh->polygons.size());
if(progressionStatus_.isCanceled())
{
@@ -2611,7 +2705,7 @@ bool RTABMapApp::exportMesh(
// save in database
pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZRGBNormal>);
pcl::fromPCLPointCloud2(polygonMesh->cloud, *cloud);
cv::Mat cloudMat = rtabmap::compressData2(rtabmap::util3d::laserScanFromPointCloud(*cloud)); // for database
cv::Mat cloudMat = rtabmap::compressData2(rtabmap::util3d::laserScanFromPointCloud(*cloud, rtabmap::Transform(), false)); // for database
std::vector<std::vector<std::vector<unsigned int> > > polygons(1);
polygons[0].resize(polygonMesh->polygons.size());
for(unsigned int p=0; p<polygonMesh->polygons.size(); ++p)
@@ -2619,7 +2713,8 @@ bool RTABMapApp::exportMesh(
polygons[0][p] = polygonMesh->polygons[p].vertices;
}
boost::mutex::scoped_lock lock(rtabmapMutex_);
rtabmap_->getMemory()->saveOptimizedMesh(cloudMat, poses, polygons);
rtabmap_->getMemory()->saveOptimizedMesh(cloudMat, polygons);
success = true;
}
}
@@ -2627,7 +2722,7 @@ bool RTABMapApp::exportMesh(
{
pcl::PointCloud<pcl::PointNormal>::Ptr cloud(new pcl::PointCloud<pcl::PointNormal>);
pcl::fromPCLPointCloud2(textureMesh->cloud, *cloud);
cv::Mat cloudMat = rtabmap::compressData2(rtabmap::util3d::laserScanFromPointCloud(*cloud)); // for database
cv::Mat cloudMat = rtabmap::compressData2(rtabmap::util3d::laserScanFromPointCloud(*cloud, rtabmap::Transform(), false)); // for database
// save in database
std::vector<std::vector<std::vector<unsigned int> > > polygons(textureMesh->tex_polygons.size());
@@ -2640,7 +2735,7 @@ bool RTABMapApp::exportMesh(
}
}
boost::mutex::scoped_lock lock(rtabmapMutex_);
rtabmap_->getMemory()->saveOptimizedMesh(cloudMat, poses, polygons, textureMesh->tex_coordinates, globalTextures);
rtabmap_->getMemory()->saveOptimizedMesh(cloudMat, polygons, textureMesh->tex_coordinates, globalTextures);
success = true;
}
else
@@ -2663,7 +2758,8 @@ bool RTABMapApp::exportMesh(
std::map<int, Mesh>::iterator jter=createdMeshes_.find(iter->first);
pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZRGB>);
pcl::IndicesPtr indices(new std::vector<int>);
float gains[3] = {1.0f};
float gains[3];
gains[0] = gains[1] = gains[2] = 1.0f;
if(regenerateCloud)
{
if(jter != createdMeshes_.end())
@@ -2762,7 +2858,7 @@ bool RTABMapApp::exportMesh(
{
cv::Mat cloudMat = rtabmap::compressData2(rtabmap::util3d::laserScanFromPointCloud(*mergedClouds)); // for database
boost::mutex::scoped_lock lock(rtabmapMutex_);
rtabmap_->getMemory()->saveOptimizedMesh(cloudMat, poses);
rtabmap_->getMemory()->saveOptimizedMesh(cloudMat);
success = true;
}
}
@@ -2792,6 +2888,20 @@ bool RTABMapApp::exportMesh(
}
exporting_ = false;
optRefId_ = 0;
if(optRefPose_)
{
delete optRefPose_;
optRefPose_ = 0;
}
if(success && poses.size())
{
// for optimized mesh
// just take the last as reference
optRefId_ = poses.rbegin()->first;
optRefPose_ = new rtabmap::Transform(poses.rbegin()->second);
}
return success;
}
@@ -2801,10 +2911,10 @@ bool RTABMapApp::postExportation(bool visualize)
optMesh_.reset(new pcl::TextureMesh);
optTexture_ = cv::Mat();
exportedMeshUpdated_ = false;
visualizingMesh_ = false;
if(visualize)
{
visualizingMesh_ = false;
cv::Mat cloudMat;
std::vector<std::vector<std::vector<unsigned int> > > polygons;
#if PCL_VERSION_COMPARE(>=, 1, 8, 0)
@@ -2813,10 +2923,9 @@ bool RTABMapApp::postExportation(bool visualize)
std::vector<std::vector<Eigen::Vector2f> > texCoords;
#endif
cv::Mat textures;
std::map<int, rtabmap::Transform> optPoses;
if(rtabmap_ && rtabmap_->getMemory())
{
cloudMat = rtabmap_->getMemory()->loadOptimizedMesh(&optPoses, &polygons, &texCoords, &textures);
cloudMat = rtabmap_->getMemory()->loadOptimizedMesh(&polygons, &texCoords, &textures);
if(!cloudMat.empty())
{
LOGI("postExportation: Found optimized mesh! Visualizing it.");
@@ -2833,6 +2942,19 @@ bool RTABMapApp::postExportation(bool visualize)
}
}
}
else if(visualizingMesh_)
{
rtabmapMutex_.lock();
if(!rtabmap_->getLocalOptimizedPoses().empty())
{
rtabmap::Statistics stats;
stats.setPoses(rtabmap_->getLocalOptimizedPoses());
rtabmapEvents_.push_back(new rtabmap::RtabmapEvent(stats));
}
rtabmapMutex_.unlock();
visualizingMesh_ = false;
}
return visualizingMesh_;
}
@@ -2854,10 +2976,9 @@ bool RTABMapApp::writeExportedMesh(const std::string & directory, const std::str
std::vector<std::vector<Eigen::Vector2f> > texCoords;
#endif
cv::Mat textures;
std::map<int, rtabmap::Transform> optPoses;
if(rtabmap_ && rtabmap_->getMemory())
{
cloudMat = rtabmap_->getMemory()->loadOptimizedMesh(&optPoses, &polygons, &texCoords, &textures);
cloudMat = rtabmap_->getMemory()->loadOptimizedMesh(&polygons, &texCoords, &textures);
if(!cloudMat.empty())
{
LOGI("writeExportedMesh: Found optimized mesh!");
@@ -3070,8 +3191,16 @@ bool RTABMapApp::handleEvent(UEvent * event)
LOGI("Received RtabmapEvent event!");
if(camera_->isRunning())
{
boost::mutex::scoped_lock lock(rtabmapMutex_);
rtabmapEvents_.push_back((rtabmap::RtabmapEvent*)event);
if(visualizingMesh_)
{
boost::mutex::scoped_lock lock(visLocalizationMutex_);
visLocalizationEvents_.push_back((rtabmap::RtabmapEvent*)event);
}
else
{
boost::mutex::scoped_lock lock(rtabmapMutex_);
rtabmapEvents_.push_back((rtabmap::RtabmapEvent*)event);
}
return true;
}
}
@@ -3178,8 +3307,11 @@ bool RTABMapApp::handleEvent(UEvent * event)
uInsert(bufferedStatsData_, std::make_pair<std::string, float>(rtabmap::Statistics::kLoopVisual_matches(), uValue(stats.data(), rtabmap::Statistics::kLoopVisual_matches(), 0.0f)));
uInsert(bufferedStatsData_, std::make_pair<std::string, float>(rtabmap::Statistics::kLoopRejectedHypothesis(), uValue(stats.data(), rtabmap::Statistics::kLoopRejectedHypothesis(), 0.0f)));
uInsert(bufferedStatsData_, std::make_pair<std::string, float>(rtabmap::Statistics::kLoopOptimization_max_error(), uValue(stats.data(), rtabmap::Statistics::kLoopOptimization_max_error(), 0.0f)));
uInsert(bufferedStatsData_, std::make_pair<std::string, float>(rtabmap::Statistics::kLoopOptimization_max_error_ratio(), uValue(stats.data(), rtabmap::Statistics::kLoopOptimization_max_error_ratio(), 0.0f)));
uInsert(bufferedStatsData_, std::make_pair<std::string, float>(rtabmap::Statistics::kMemoryRehearsal_sim(), uValue(stats.data(), rtabmap::Statistics::kMemoryRehearsal_sim(), 0.0f)));
uInsert(bufferedStatsData_, std::make_pair<std::string, float>(rtabmap::Statistics::kLoopHighest_hypothesis_value(), uValue(stats.data(), rtabmap::Statistics::kLoopHighest_hypothesis_value(), 0.0f)));
uInsert(bufferedStatsData_, std::make_pair<std::string, float>(rtabmap::Statistics::kMemoryDistance_travelled(), uValue(stats.data(), rtabmap::Statistics::kMemoryDistance_travelled(), 0.0f)));
uInsert(bufferedStatsData_, std::make_pair<std::string, float>(rtabmap::Statistics::kMemoryFast_movement(), uValue(stats.data(), rtabmap::Statistics::kMemoryFast_movement(), 0.0f)));
}
// else use last data
@@ -3193,8 +3325,17 @@ bool RTABMapApp::handleEvent(UEvent * event)
int matches = (int)uValue(bufferedStatsData_, rtabmap::Statistics::kLoopVisual_matches(), 0.0f);
int rejected = (int)uValue(bufferedStatsData_, rtabmap::Statistics::kLoopRejectedHypothesis(), 0.0f);
float optimizationMaxError = uValue(bufferedStatsData_, rtabmap::Statistics::kLoopOptimization_max_error(), 0.0f);
float optimizationMaxErrorRatio = uValue(bufferedStatsData_, rtabmap::Statistics::kLoopOptimization_max_error_ratio(), 0.0f);
float rehearsalValue = uValue(bufferedStatsData_, rtabmap::Statistics::kMemoryRehearsal_sim(), 0.0f);
float hypothesis = uValue(bufferedStatsData_, rtabmap::Statistics::kLoopHighest_hypothesis_value(), 0.0f);
float distanceTravelled = uValue(bufferedStatsData_, rtabmap::Statistics::kMemoryDistance_travelled(), 0.0f);
int fastMovement = (int)uValue(bufferedStatsData_, rtabmap::Statistics::kMemoryFast_movement(), 0.0f);
rtabmap::Transform currentPose = main_scene_.GetCameraPose();
float x=0.0f,y=0.0f,z=0.0f,roll=0.0f,pitch=0.0f,yaw=0.0f;
if(!currentPose.isNull())
{
currentPose.getTranslationAndEulerAngles(x,y,z,roll,pitch,yaw);
}
// Call JAVA callback with some stats
UINFO("Send statistics to GUI");
@@ -3208,7 +3349,7 @@ bool RTABMapApp::handleEvent(UEvent * event)
jclass clazz = env->GetObjectClass(RTABMapActivity);
if(clazz)
{
jmethodID methodID = env->GetMethodID(clazz, "updateStatsCallback", "(IIIIFIIIIIIIFIFIFF)V" );
jmethodID methodID = env->GetMethodID(clazz, "updateStatsCallback", "(IIIIFIIIIIIFIFIFFFFIFFFFFF)V" );
if(methodID)
{
env->CallVoidMethod(RTABMapActivity, methodID,
@@ -3219,7 +3360,6 @@ bool RTABMapApp::handleEvent(UEvent * event)
updateTime,
loopClosureId,
highestHypId,
(int)((processMemoryUsedBytes+processGPUMemoryUsedBytes)/(1024*1024)),
databaseMemoryUsed,
inliers,
matches,
@@ -3229,7 +3369,16 @@ bool RTABMapApp::handleEvent(UEvent * event)
renderingTime_>0.0f?1.0f/renderingTime_:0.0f,
rejected,
rehearsalValue,
optimizationMaxError);
optimizationMaxError,
optimizationMaxErrorRatio,
distanceTravelled,
fastMovement,
x,
y,
z,
roll,
pitch,
yaw);
success = true;
}
}
+5 -2
View File
@@ -228,26 +228,29 @@ class RTABMapApp : public UEventsHandler {
int lastDrawnCloudsCount_;
float renderingTime_;
double lastPostRenderEventTime_;
long processMemoryUsedBytes;
long processGPUMemoryUsedBytes;
double lastPoseEventTime_;
std::map<std::string, float> bufferedStatsData_;
bool visualizingMesh_;
bool exportedMeshUpdated_;
pcl::TextureMesh::Ptr optMesh_;
cv::Mat optTexture_;
int optRefId_;
rtabmap::Transform * optRefPose_; // App crashes when loading native library if not dynamic
// main_scene_ includes all drawable object for visualizing Tango device's
// movement and point cloud.
Scene main_scene_;
std::list<rtabmap::RtabmapEvent*> rtabmapEvents_;
std::list<rtabmap::RtabmapEvent*> visLocalizationEvents_;
std::list<rtabmap::OdometryEvent> odomEvents_;
std::list<rtabmap::Transform> poseEvents_;
rtabmap::Transform mapToOdom_;
boost::mutex rtabmapMutex_;
boost::mutex visLocalizationMutex_;
boost::mutex meshesMutex_;
boost::mutex odomMutex_;
boost::mutex poseMutex_;
+1 -1
View File
@@ -96,9 +96,9 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="5dp"
android:layout_alignParentTop="true"
android:layout_marginTop="10dp"
android:layout_alignParentRight="true"
android:layout_below="@+id/pause_button"
android:text="@string/share_to_sketchfab" />
<Button
@@ -109,6 +109,13 @@
android:entries="@array/pref_update_rate_keys"
android:entryValues="@array/pref_update_rate_values"
android:defaultValue="@string/pref_default_update_rate"/>
<ListPreference
android:key="@string/pref_key_max_speed"
android:title="@string/pref_title_max_speed"
android:summary="@string/pref_summary_max_speed"
android:entries="@array/pref_max_speed_keys"
android:entryValues="@array/pref_max_speed_values"
android:defaultValue="@string/pref_default_max_speed"/>
<ListPreference
android:key="@string/pref_key_time_thr"
android:title="@string/pref_title_time_thr"
+44 -21
View File
@@ -34,7 +34,8 @@
<string name="memory">"Used Memory (MB): "</string>
<string name="hypothesis">"Hypothesis (%): "</string>
<string name="fps">"FPS (rendering): "</string>
<string name="gps">"GPS (long,lat,alt,bearing,acc): "</string>
<string name="distance">"Distance travelled: "</string>
<string name="gps">"GPS (long,lat,alt,bearing,err): "</string>
<string name="time">"Time: "</string>
<!-- Preference keys: BEGIN -->
@@ -53,7 +54,7 @@
<string name="pref_key_depth">pref_key_depth</string>
<string name="pref_default_depth">2.5</string>
<string name="pref_key_point_size">pref_key_point_size</string>
<string name="pref_default_point_size">5</string>
<string name="pref_default_point_size">10</string>
<string name="pref_key_angle">pref_key_angle</string>
<string name="pref_default_angle">20</string>
<string name="pref_key_triangle">pref_key_triangle</string>
@@ -77,6 +78,8 @@
<string name="pref_key_update_rate">pref_key_update_rate</string>
<string name="pref_default_update_rate">1</string>
<string name="pref_key_max_speed">pref_key_max_speed</string>
<string name="pref_default_max_speed">0</string>
<string name="pref_key_time_thr">pref_key_time_thr</string>
<string name="pref_default_time_thr">1000</string>
<string name="pref_key_mem_thr">pref_key_mem_thr</string>
@@ -88,7 +91,7 @@
<string name="pref_key_min_inliers">pref_key_min_inliers</string>
<string name="pref_default_min_inliers">25</string>
<string name="pref_key_opt_error">pref_key_opt_error</string>
<string name="pref_default_opt_error">0.1</string>
<string name="pref_default_opt_error">2</string>
<string name="pref_key_features_voc">pref_key_features_voc</string>
<string name="pref_default_features_voc">200</string>
<string name="pref_key_features">pref_key_features</string>
@@ -106,7 +109,7 @@
<string name="pref_key_gps_saved">pref_key_gps_saved</string>
<string name="pref_default_gps_saved">false</string>
<string name="pref_key_db_in_memory">pref_key_db_in_memory</string>
<string name="pref_default_db_in_memory">true</string>
<string name="pref_default_db_in_memory">false</string>
<string name="pref_key_cloud_voxel">pref_key_cloud_voxel</string>
<string name="pref_default_cloud_voxel">0.01</string>
@@ -317,6 +320,8 @@
<string name="pref_summary_fisheye">Use fish eye camera instead of the color camera. May not work on some devices.</string>
<string name="pref_title_update_rate">Update Rate</string>
<string name="pref_summary_update_rate">Rate at which a new node is added to map.</string>
<string name="pref_title_max_speed">Maximum Motion Speed</string>
<string name="pref_summary_max_speed">Images taken when the camera is moving too fast are ignored to avoid blurry textures.</string>
<string name="pref_title_time_thr">Time Limit</string>
<string name="pref_summary_time_thr">Maximum time allowed for map updates. If time to add a new node is above this theshold, some old parts of the map are temporarly forgotten to reduce time of next updates.</string>
<string name="pref_title_mem_thr">Memory Limit</string>
@@ -328,7 +333,7 @@
<string name="pref_title_min_inliers">Min Inliers</string>
<string name="pref_summary_min_inliers">Minimum visual inliers to accept a loop closure.</string>
<string name="pref_title_opt_error">Max Optimization Error</string>
<string name="pref_summary_opt_error">Reject any loop closures causing error corrections in the map higher than this threshold.</string>
<string name="pref_summary_opt_error">Reject any loop closures causing error corrections in the map higher than this factor of the link\'s variance.</string>
<string name="pref_title_features_voc">Max Features Extracted (Vocabulary)</string>
<string name="pref_summary_features_voc">Extracting more features per image would result in better loop closure hypotheses but more processing time is required.</string>
<string name="pref_title_features">Max Features Extracted (Loop Closure)</string>
@@ -366,6 +371,20 @@
<item>"1"</item>
<item>"0.5"</item>
</string-array>
<string-array name="pref_max_speed_keys">
<item>"No Limit"</item>
<item>"High"</item>
<item>"Medium"</item>
<item>"Low"</item>
<item>"Very Low"</item>
</string-array>
<string-array name="pref_max_speed_values">
<item>"0"</item>
<item>"0.4"</item>
<item>"0.3"</item>
<item>"0.2"</item>
<item>"0.1"</item>
</string-array>
<string-array name="pref_time_thr_keys">
<item>"No Limit"</item>
<item>"1500 ms"</item>
@@ -475,25 +494,29 @@
<item>"10"</item>
</string-array>
<string-array name="pref_opt_error_keys">
<item>"1.0 m"</item>
<item>"0.5 m"</item>
<item>"0.35 m"</item>
<item>"0.2 m"</item>
<item>"0.1 m"</item>
<item>"0.05 m"</item>
<item>"0.025 m"</item>
<item>"0.01 m"</item>
<item>"10x"</item>
<item>"9x"</item>
<item>"8x"</item>
<item>"7x"</item>
<item>"6x"</item>
<item>"5x"</item>
<item>"4x"</item>
<item>"3x"</item>
<item>"2x"</item>
<item>"1x"</item>
<item>"Disabled"</item>
</string-array>
<string-array name="pref_opt_error_values">
<item>"1.0"</item>
<item>"0.5"</item>
<item>"0.35"</item>
<item>"0.2"</item>
<item>"0.1"</item>
<item>"0.05"</item>
<item>"0.025"</item>
<item>"0.01"</item>
<item>"10"</item>
<item>"9"</item>
<item>"8"</item>
<item>"7"</item>
<item>"6"</item>
<item>"5"</item>
<item>"4"</item>
<item>"3"</item>
<item>"2"</item>
<item>"1"</item>
<item>"0"</item>
</string-array>
<string-array name="pref_features_voc_keys">
@@ -71,6 +71,7 @@ import android.os.Handler;
import android.os.Debug;
import android.os.IBinder;
import android.os.Message;
import android.preference.ListPreference;
import android.preference.PreferenceManager;
import android.text.Editable;
import android.text.Html;
@@ -181,7 +182,9 @@ public class RTABMapActivity extends Activity implements OnClickListener, OnItem
private long mOnPauseStamp = 0;
private boolean mOnPause = false;
private Date mDateOnPause = new Date();
private long mLastFastMovementNotificationStamp = 0;
private boolean mBlockBack = true;
private long mFreeMemoryOnStart = 0;
private MenuItem mItemSave;
private MenuItem mItemOpen;
@@ -220,6 +223,7 @@ public class RTABMapActivity extends Activity implements OnClickListener, OnItem
private String mLoopThr;
private String mMinInliers;
private String mMaxOptimizationError;
private boolean mGPSSaved = false;
private LocationManager mLocationManager;
private LocationListener mLocationListener;
@@ -235,7 +239,9 @@ public class RTABMapActivity extends Activity implements OnClickListener, OnItem
private AlertDialog mMemoryWarningDialog = null;
private String[] mStatusTexts = new String[16];
private final int STATUS_TEXTS_SIZE = 19;
private final int STATUS_TEXTS_POSE_INDEX = 5;
private String[] mStatusTexts = new String[STATUS_TEXTS_SIZE];
GestureDetector mGesDetect = null;
@@ -270,6 +276,8 @@ public class RTABMapActivity extends Activity implements OnClickListener, OnItem
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setTitle(R.string.menu_name);
mFreeMemoryOnStart = getFreeMemory();
// Query screen size, the screen size is used for computing the normalized
// touch point.
@@ -435,6 +443,10 @@ public class RTABMapActivity extends Activity implements OnClickListener, OnItem
@Override
public void onClick(DialogInterface dialog, int which) {
RTABMapLib.cancelProcessing();
mProgressDialog.setTitle("");
mProgressDialog.setMessage(String.format("Cancelling..."));
mProgressDialog.show();
}
});
@@ -449,6 +461,7 @@ public class RTABMapActivity extends Activity implements OnClickListener, OnItem
mWorkingDirectory = "";
mWorkingDirectoryHuman = "";
mTotalLoopClosures = 0;
mLastFastMovementNotificationStamp = System.currentTimeMillis()/1000;
if(Environment.getExternalStorageState().compareTo(Environment.MEDIA_MOUNTED)==0)
{
@@ -639,23 +652,22 @@ public class RTABMapActivity extends Activity implements OnClickListener, OnItem
if(!DISABLE_LOG) Log.i(TAG, "onPause()");
mOnPause = true;
mLocationManager.removeUpdates(mLocationListener);
mSensorManager.unregisterListener(this);
// This deletes OpenGL context!
mGLView.onPause();
RTABMapLib.onPause();
unbindService(mTangoServiceConnection);
if(!mButtonPause.isChecked())
{
mButtonPause.setChecked(true);
pauseMapping();
}
mLocationManager.removeUpdates(mLocationListener);
mSensorManager.unregisterListener(this);
RTABMapLib.onPause();
unbindService(mTangoServiceConnection);
// This deletes OpenGL context!
mGLView.onPause();
mOnPauseStamp = System.currentTimeMillis()/1000;
}
@@ -690,20 +702,30 @@ public class RTABMapActivity extends Activity implements OnClickListener, OnItem
if(!DISABLE_LOG) Log.d(TAG, "update preferences...");
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
mUpdateRate = sharedPref.getString(getString(R.string.pref_key_update_rate), getString(R.string.pref_default_update_rate));
String maxSpeed = sharedPref.getString(getString(R.string.pref_key_max_speed), getString(R.string.pref_default_max_speed));
mTimeThr = sharedPref.getString(getString(R.string.pref_key_time_thr), getString(R.string.pref_default_time_thr));
String memThr = sharedPref.getString(getString(R.string.pref_key_mem_thr), getString(R.string.pref_default_mem_thr));
mLoopThr = sharedPref.getString(getString(R.string.pref_key_loop_thr), getString(R.string.pref_default_loop_thr));
String simThr = sharedPref.getString(getString(R.string.pref_key_sim_thr), getString(R.string.pref_default_sim_thr));
mMinInliers = sharedPref.getString(getString(R.string.pref_key_min_inliers), getString(R.string.pref_default_min_inliers));
mMaxOptimizationError = sharedPref.getString(getString(R.string.pref_key_opt_error), getString(R.string.pref_default_opt_error));
float maxOptimizationError = Float.parseFloat(mMaxOptimizationError);
if(maxOptimizationError >0 && maxOptimizationError<1)
{
Log.w(TAG, "Migration of " + getString(R.string.pref_key_opt_error) + " from " + mMaxOptimizationError + " to " + getString(R.string.pref_default_opt_error)) ;
SharedPreferences.Editor editor = sharedPref.edit();
editor.putString(getString(R.string.pref_key_opt_error), getString(R.string.pref_default_opt_error));
editor.commit();
mMaxOptimizationError = getString(R.string.pref_default_opt_error);
}
mMaxFeatures = sharedPref.getString(getString(R.string.pref_key_features_voc), getString(R.string.pref_default_features_voc));
String maxFeaturesLoop = sharedPref.getString(getString(R.string.pref_key_features), getString(R.string.pref_default_features));
String featureType = sharedPref.getString(getString(R.string.pref_key_features_type), getString(R.string.pref_default_features_type));
boolean keepAllDb = sharedPref.getBoolean(getString(R.string.pref_key_keep_all_db), Boolean.parseBoolean(getString(R.string.pref_default_keep_all_db)));
boolean optimizeFromGraphEnd = sharedPref.getBoolean(getString(R.string.pref_key_optimize_end), Boolean.parseBoolean(getString(R.string.pref_default_optimize_end)));
String optimizer = sharedPref.getString(getString(R.string.pref_key_optimizer), getString(R.string.pref_default_optimizer));
boolean gpsSaved = sharedPref.getBoolean(getString(R.string.pref_key_gps_saved), Boolean.parseBoolean(getString(R.string.pref_default_gps_saved)));
if(gpsSaved)
mGPSSaved = sharedPref.getBoolean(getString(R.string.pref_key_gps_saved), Boolean.parseBoolean(getString(R.string.pref_default_gps_saved)));
if(mGPSSaved)
{
mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, mLocationListener);
mSensorManager.registerListener(this, mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION), SensorManager.SENSOR_DELAY_GAME);
@@ -720,6 +742,8 @@ public class RTABMapActivity extends Activity implements OnClickListener, OnItem
RTABMapLib.setMappingParameter("Rtabmap/DetectionRate", mUpdateRate);
RTABMapLib.setMappingParameter("Rtabmap/TimeThr", mTimeThr);
RTABMapLib.setMappingParameter("Rtabmap/MemoryThr", memThr);
RTABMapLib.setMappingParameter("RGBD/LinearSpeedUpdate", maxSpeed);
RTABMapLib.setMappingParameter("RGBD/AngularSpeedUpdate", String.valueOf(Float.parseFloat(maxSpeed)/2.0f));
RTABMapLib.setMappingParameter("Mem/RehearsalSimilarity", simThr);
RTABMapLib.setMappingParameter("Kp/MaxFeatures", mMaxFeatures);
RTABMapLib.setMappingParameter("Vis/MaxFeatures", maxFeaturesLoop);
@@ -798,8 +822,9 @@ public class RTABMapActivity extends Activity implements OnClickListener, OnItem
if(!DISABLE_LOG) Log.i(TAG, String.format("called setCamera(type=%d);", type));
// for convenience, for a refresh of the memory used
mStatusTexts[1] = getString(R.string.memory)+String.valueOf(Debug.getNativeHeapAllocatedSize()/(1024*1024));
mStatusTexts[2] = getString(R.string.free_memory)+String.valueOf(getFreeMemory());
long freeMemory = getFreeMemory();
mStatusTexts[1] = getString(R.string.memory)+String.valueOf(mFreeMemoryOnStart>freeMemory?mFreeMemoryOnStart-freeMemory:0);
mStatusTexts[2] = getString(R.string.free_memory)+String.valueOf(freeMemory);
updateStatusTexts();
RTABMapLib.setCamera(type);
@@ -989,11 +1014,11 @@ public class RTABMapActivity extends Activity implements OnClickListener, OnItem
}
else if((mItemStatusVisibility.isChecked() || mState == State.STATE_VISUALIZING_WHILE_LOADING))
{
mRenderer.updateTexts(Arrays.copyOfRange(mStatusTexts, 0, 3));
mRenderer.updateTexts(Arrays.copyOfRange(mStatusTexts, 0, STATUS_TEXTS_POSE_INDEX-1));
}
else if(mItemDebugVisibility.isChecked())
{
mRenderer.updateTexts(Arrays.copyOfRange(mStatusTexts, 4, mStatusTexts.length));
mRenderer.updateTexts(Arrays.copyOfRange(mStatusTexts, STATUS_TEXTS_POSE_INDEX-1, mStatusTexts.length));
}
else
{
@@ -1003,12 +1028,13 @@ public class RTABMapActivity extends Activity implements OnClickListener, OnItem
}
private void updateStatsUI(
int processMemoryUsed,
int loopClosureId,
int inliers,
int matches,
int rejected,
float optimizationMaxError,
float optimizationMaxErrorRatio,
boolean fastMovement,
String[] statusTexts)
{
mStatusTexts = statusTexts;
@@ -1019,10 +1045,10 @@ public class RTABMapActivity extends Activity implements OnClickListener, OnItem
if(!mButtonPause.isChecked())
{
//check if we are low in memory
long memoryUsed = processMemoryUsed;
long memoryFree = getFreeMemory();
long memoryUsed = mFreeMemoryOnStart>memoryFree?mFreeMemoryOnStart-memoryFree:0;
if(memoryFree < 200)
if(memoryFree < 400)
{
mButtonPause.setChecked(true);
pauseMapping();
@@ -1083,6 +1109,7 @@ public class RTABMapActivity extends Activity implements OnClickListener, OnItem
if(mButtonPause!=null && !mButtonPause.isChecked())
{
long currentTime = System.currentTimeMillis()/1000;
if(loopClosureId > 0)
{
mToast.setText(String.format("Loop closure detected! (%d/%d inliers)", inliers, matches));
@@ -1094,7 +1121,7 @@ public class RTABMapActivity extends Activity implements OnClickListener, OnItem
{
if(optimizationMaxError > 0.0f)
{
mToast.setText(String.format("Loop closure rejected, too high graph optimization error (%.3fm > %sm).", optimizationMaxError, mMaxOptimizationError));
mToast.setText(String.format("Loop closure rejected, too high graph optimization error (%.3fm: ratio=%.3f < factor=%sx).", optimizationMaxError, optimizationMaxErrorRatio, mMaxOptimizationError));
}
else
{
@@ -1107,6 +1134,19 @@ public class RTABMapActivity extends Activity implements OnClickListener, OnItem
}
mToast.show();
}
else if(fastMovement)
{
if(currentTime - mLastFastMovementNotificationStamp > 3)
{
mToast.setText("Move slower... blurry images are not added to map (\"Settings->Mapping...->Maximum Motion Speed\" is enabled).");
mToast.show();
}
}
if(!fastMovement)
{
mLastFastMovementNotificationStamp = currentTime;
}
}
}
@@ -1119,7 +1159,6 @@ public class RTABMapActivity extends Activity implements OnClickListener, OnItem
final float updateTime,
final int loopClosureId,
final int highestHypId,
final int processMemoryUsed,
final int databaseMemoryUsed,
final int inliers,
final int matches,
@@ -1129,11 +1168,20 @@ public class RTABMapActivity extends Activity implements OnClickListener, OnItem
final float fps,
final int rejected,
final float rehearsalValue,
final float optimizationMaxError)
final float optimizationMaxError,
final float optimizationMaxErrorRatio,
final float distanceTravelled,
final int fastMovement,
final float x,
final float y,
final float z,
final float roll,
final float pitch,
final float yaw)
{
if(!DISABLE_LOG) Log.i(TAG, String.format("updateStatsCallback()"));
final String[] statusTexts = new String[17];
final String[] statusTexts = new String[STATUS_TEXTS_SIZE];
if(mButtonPause!=null && !mButtonPause.isChecked())
{
String updateValue = mUpdateRate.compareTo("0")==0?"Max":mUpdateRate;
@@ -1143,32 +1191,10 @@ public class RTABMapActivity extends Activity implements OnClickListener, OnItem
{
statusTexts[0] = mStatusTexts[0];
}
// getNativeHeapAllocatedSize() is too slow, so we need to use the estimate.
// Multiply by 3/2 to match getNativeHeapAllocatedSize()
final int adjustedMemoryUsed = (processMemoryUsed*3)/2;
if(mButtonPause!=null)
{
if(!mButtonPause.isChecked())
{
statusTexts[1] = getString(R.string.memory)+adjustedMemoryUsed;
}
else if(mState == State.STATE_PROCESSING)
{
// This request is long to do, only do it when processing.
statusTexts[1] = getString(R.string.memory)+String.valueOf(Debug.getNativeHeapAllocatedSize()/(1024*1024));
}
else
{
statusTexts[1] = mStatusTexts[1];
}
}
else
{
statusTexts[1] = mStatusTexts[1];
}
statusTexts[2] = getString(R.string.free_memory)+getFreeMemory();
long memoryFree = getFreeMemory();
statusTexts[1] = getString(R.string.memory)+(mFreeMemoryOnStart>memoryFree?mFreeMemoryOnStart-memoryFree:0);
statusTexts[2] = getString(R.string.free_memory)+memoryFree;
if(loopClosureId > 0)
{
@@ -1177,29 +1203,36 @@ public class RTABMapActivity extends Activity implements OnClickListener, OnItem
mMapNodes = nodes;
if(mLastKnownLocation != null)
if(mGPSSaved)
{
long millisec = System.currentTimeMillis() - mLastKnownLocation.getTime();
if(millisec > 2000)
if(mLastKnownLocation != null)
{
statusTexts[3] = getString(R.string.gps)+String.format("[too old, %d ms]", millisec);
long millisec = System.currentTimeMillis() - mLastKnownLocation.getTime();
if(millisec > 1000)
{
statusTexts[3] = getString(R.string.gps)+String.format("[too old, %d ms]", millisec);
}
else
{
statusTexts[3] = getString(R.string.gps)+
String.format("%.2f %.2f %.2fm %.0fdeg %.0fm",
mLastKnownLocation.getLongitude(),
mLastKnownLocation.getLatitude(),
mLastKnownLocation.getAltitude(),
mCompassDeg,
mLastKnownLocation.getAccuracy());
}
}
else
{
statusTexts[3] = getString(R.string.gps)+
String.format("%.2f %.2f %.2fm %.0fdeg %.0fm",
mLastKnownLocation.getLongitude(),
mLastKnownLocation.getLatitude(),
mLastKnownLocation.getAltitude(),
mCompassDeg,
mLastKnownLocation.getAccuracy());
statusTexts[3] = getString(R.string.gps)+"[not yet available]";
}
}
String formattedDate = new SimpleDateFormat("HH:mm:ss.SSS").format(new Date());
statusTexts[4] = getString(R.string.time)+formattedDate;
int index = 5;
int index = STATUS_TEXTS_POSE_INDEX;
statusTexts[index++] = getString(R.string.nodes)+nodes+" (" + nodesDrawn + " shown)";
statusTexts[index++] = getString(R.string.words)+words;
statusTexts[index++] = getString(R.string.database_size)+databaseMemoryUsed;
@@ -1212,10 +1245,12 @@ public class RTABMapActivity extends Activity implements OnClickListener, OnItem
statusTexts[index++] = getString(R.string.inliers)+inliers;
statusTexts[index++] = getString(R.string.hypothesis)+(int)(hypothesis*100.0f) +" / " + (int)(Float.parseFloat(mLoopThr)*100.0f) + " (" + (loopClosureId>0?loopClosureId:highestHypId)+")";
statusTexts[index++] = getString(R.string.fps)+(int)fps+" Hz";
statusTexts[index++] = getString(R.string.distance)+(int)distanceTravelled+" m";
statusTexts[index++] = String.format("Pose (x,y,z): %.2f %.2f %.2f", x,y,z);
runOnUiThread(new Runnable() {
public void run() {
updateStatsUI(adjustedMemoryUsed, loopClosureId, inliers, matches, rejected, optimizationMaxError, statusTexts);
updateStatsUI(loopClosureId, inliers, matches, rejected, optimizationMaxError, optimizationMaxErrorRatio, fastMovement!=0, statusTexts);
}
});
}
@@ -1277,8 +1312,9 @@ public class RTABMapActivity extends Activity implements OnClickListener, OnItem
mStatusTexts[0] = getString(R.string.status)+(status == 1 && msg.isEmpty()?(mItemDataRecorderMode!=null&&mItemDataRecorderMode.isChecked()?"Recording":mItemLocalizationMode!=null&&mItemLocalizationMode.isChecked()?"Localization":"Mapping"):msg);
}
mStatusTexts[1] = getString(R.string.memory)+String.valueOf(Debug.getNativeHeapAllocatedSize()/(1024*1024));
mStatusTexts[2] = getString(R.string.free_memory)+String.valueOf(getFreeMemory());
long freeMemory = getFreeMemory();
mStatusTexts[1] = getString(R.string.memory)+String.valueOf(mFreeMemoryOnStart>freeMemory?mFreeMemoryOnStart-freeMemory:0);
mStatusTexts[2] = getString(R.string.free_memory)+String.valueOf(freeMemory);
updateStatusTexts();
}
}
@@ -1357,9 +1393,17 @@ public class RTABMapActivity extends Activity implements OnClickListener, OnItem
str = String.format("Too few features (%s) were tracked in the fisheye image. This may result in poor odometry!", value);
}
}
else if(key.equals("TooClose"))
{
str = String.format("Too close! Tip: Scan from at least ~1 meter from surfaces.", value);
}
else if(key.equals("TangoPoseEventNotReceived"))
{
str = String.format("No valid tango pose event received since %s sec.", value);
}
else
{
str = String.format("Unknown Tango event detected!? (type=%d)", type);
str = String.format("Unknown Tango event detected!? (type=%d, key=%s, value=%s)", type, key, value);
}
if(str!=null)
{
@@ -1428,6 +1472,7 @@ public class RTABMapActivity extends Activity implements OnClickListener, OnItem
}
else
{
mProgressDialog.dismiss();
mToast.makeText(getActivity(), String.format("Optimization canceled"), mToast.LENGTH_LONG).show();
}
updateState(State.STATE_IDLE);
@@ -1510,10 +1555,10 @@ public class RTABMapActivity extends Activity implements OnClickListener, OnItem
case STATE_VISUALIZING:
mButtonLighting.setVisibility(mHudVisible && !mItemRenderingPointCloud.isChecked()?View.VISIBLE:View.INVISIBLE);
mButtonWireframe.setVisibility(mHudVisible && !mItemRenderingPointCloud.isChecked()?View.VISIBLE:View.INVISIBLE);
mButtonCloseVisualization.setVisibility(mHudVisible?View.VISIBLE:View.INVISIBLE);
mButtonCloseVisualization.setVisibility(mHudVisible && mButtonPause.isChecked()?View.VISIBLE:View.INVISIBLE);
mButtonCloseVisualization.setEnabled(true);
mButtonSaveOnDevice.setVisibility(mHudVisible?View.VISIBLE:View.INVISIBLE);
mButtonShareOnSketchfab.setVisibility(mHudVisible?View.VISIBLE:View.INVISIBLE);
mButtonSaveOnDevice.setVisibility(mHudVisible && mButtonPause.isChecked()?View.VISIBLE:View.INVISIBLE);
mButtonShareOnSketchfab.setVisibility(mHudVisible && mButtonPause.isChecked()?View.VISIBLE:View.INVISIBLE);
mItemSave.setEnabled(mButtonPause.isChecked());
mItemExport.setEnabled(mButtonPause.isChecked() && !mItemDataRecorderMode.isChecked());
mItemOpen.setEnabled(false);
@@ -1521,7 +1566,8 @@ public class RTABMapActivity extends Activity implements OnClickListener, OnItem
mItemSettings.setEnabled(true);
mItemReset.setEnabled(true);
mItemModes.setEnabled(true);
mButtonPause.setVisibility(View.INVISIBLE);
mButtonPause.setVisibility(mHudVisible && mItemLocalizationMode.isChecked()?View.VISIBLE:View.GONE);
mItemLocalizationMode.setEnabled(mButtonPause.isChecked());
mItemDataRecorderMode.setEnabled(mButtonPause.isChecked());
break;
case STATE_VISUALIZING_WHILE_LOADING:
@@ -1565,15 +1611,23 @@ public class RTABMapActivity extends Activity implements OnClickListener, OnItem
private void pauseMapping() {
updateState(State.STATE_IDLE);
if(mState != State.STATE_VISUALIZING)
{
updateState(State.STATE_IDLE);
}
else
{
updateState(State.STATE_VISUALIZING);
}
if(mButtonPause.isChecked())
{
RTABMapLib.setPausedMapping(true);
mStatusTexts[0] = getString(R.string.status)+"Paused";
mStatusTexts[1] = getString(R.string.memory)+String.valueOf(Debug.getNativeHeapAllocatedSize()/(1024*1024));
mStatusTexts[2] = getString(R.string.free_memory)+String.valueOf(getFreeMemory());
long freeMemory = getFreeMemory();
mStatusTexts[1] = getString(R.string.memory)+String.valueOf(mFreeMemoryOnStart>freeMemory?mFreeMemoryOnStart-freeMemory:0);
mStatusTexts[2] = getString(R.string.free_memory)+String.valueOf(freeMemory);
updateStatusTexts();
mMapIsEmpty = false;
@@ -1607,6 +1661,7 @@ public class RTABMapActivity extends Activity implements OnClickListener, OnItem
mMemoryWarningDialog=null;
}
RTABMapLib.setPausedMapping(false);
mLastFastMovementNotificationStamp = System.currentTimeMillis()/1000;
if(mItemDataRecorderMode.isChecked())
{
@@ -1614,7 +1669,20 @@ public class RTABMapActivity extends Activity implements OnClickListener, OnItem
}
else if(!mMapIsEmpty)
{
mToast.makeText(getActivity(), String.format("On resume, a new map is created. Tip: Try relocalizing in the previous area."), mToast.LENGTH_LONG).show();
if(mItemLocalizationMode!=null && mItemLocalizationMode.isChecked())
{
mToast.makeText(getActivity(), String.format("Localization mode"), mToast.LENGTH_LONG).show();
}
else
{
mToast.makeText(getActivity(), String.format("On resume, a new map is created. Tip: Try relocalizing in the previous area."), mToast.LENGTH_LONG).show();
}
}
else if(mMapIsEmpty && mItemLocalizationMode!=null && mItemLocalizationMode.isChecked())
{
mItemLocalizationMode.setChecked(false);
RTABMapLib.setLocalizationMode(false);
mToast.makeText(getActivity(), String.format("Disabled localization mode as the map is empty, now mapping..."), mToast.LENGTH_LONG).show();
}
}
}
@@ -1780,6 +1848,10 @@ public class RTABMapActivity extends Activity implements OnClickListener, OnItem
{
item.setChecked(!item.isChecked());
RTABMapLib.setLocalizationMode(item.isChecked());
if(mState == State.STATE_VISUALIZING)
{
mButtonPause.setVisibility(mItemLocalizationMode.isChecked()?View.VISIBLE:View.GONE);
}
}
else if(itemId == R.id.trajectory_mode)
{
@@ -1867,7 +1939,7 @@ public class RTABMapActivity extends Activity implements OnClickListener, OnItem
{
mTotalLoopClosures = 0;
int index = 4;
int index = STATUS_TEXTS_POSE_INDEX;
mMapNodes = 0;
mStatusTexts[index++] = getString(R.string.nodes)+0;
mStatusTexts[index++] = getString(R.string.words)+0;
@@ -1881,13 +1953,14 @@ public class RTABMapActivity extends Activity implements OnClickListener, OnItem
mStatusTexts[index++] = getString(R.string.inliers)+0;
mStatusTexts[index++] = getString(R.string.hypothesis)+0;
mStatusTexts[index++] = getString(R.string.fps)+0;
mStatusTexts[index++] = getString(R.string.distance)+0;
mStatusTexts[index++] = String.format("Pose (x,y,z): 0 0 0");
updateStatusTexts();
mOpenedDatabasePath = "";
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
boolean databaseInMemory = sharedPref.getBoolean(getString(R.string.pref_key_db_in_memory), Boolean.parseBoolean(getString(R.string.pref_default_db_in_memory)));
String tmpDatabase = mWorkingDirectory+RTABMAP_TMP_DB;
(new File(tmpDatabase)).delete();
RTABMapLib.openDatabase(tmpDatabase, databaseInMemory, false);
mMapIsEmpty = true;
@@ -1906,7 +1979,7 @@ public class RTABMapActivity extends Activity implements OnClickListener, OnItem
public void onClick(DialogInterface dialog, int which) {
// reset
mTotalLoopClosures = 0;
int index = 4;
int index = STATUS_TEXTS_POSE_INDEX;
mMapNodes = 0;
mStatusTexts[index++] = getString(R.string.nodes)+0;
mStatusTexts[index++] = getString(R.string.words)+0;
@@ -1920,6 +1993,8 @@ public class RTABMapActivity extends Activity implements OnClickListener, OnItem
mStatusTexts[index++] = getString(R.string.inliers)+0;
mStatusTexts[index++] = getString(R.string.hypothesis)+0;
mStatusTexts[index++] = getString(R.string.fps)+0;
mStatusTexts[index++] = getString(R.string.distance)+0;
mStatusTexts[index++] = String.format("Pose (x,y,z): 0 0 0");
updateStatusTexts();
mItemDataRecorderMode.setChecked(!dataRecorderOldState);
@@ -1929,7 +2004,6 @@ public class RTABMapActivity extends Activity implements OnClickListener, OnItem
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(getActivity());
boolean databaseInMemory = sharedPref.getBoolean(getString(R.string.pref_key_db_in_memory), Boolean.parseBoolean(getString(R.string.pref_default_db_in_memory)));
String tmpDatabase = mWorkingDirectory+RTABMAP_TMP_DB;
(new File(tmpDatabase)).delete();
RTABMapLib.openDatabase(tmpDatabase, databaseInMemory, false);
mItemOpen.setEnabled(!mItemDataRecorderMode.isChecked() && mButtonPause.isChecked());
@@ -2376,6 +2450,7 @@ public class RTABMapActivity extends Activity implements OnClickListener, OnItem
}
else
{
mProgressDialog.dismiss();
mToast.makeText(getActivity(), String.format("Export canceled"), mToast.LENGTH_LONG).show();
updateState(previousState);
}
@@ -2436,22 +2511,42 @@ public class RTABMapActivity extends Activity implements OnClickListener, OnItem
notificationManager.notify(0, n);
// Send to...
File f = new File(newDatabasePath);
final File f = new File(newDatabasePath);
final int fileSizeMB = (int)f.length()/(1024 * 1024);
Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(f));
shareIntent.setType("application/octet-stream");
startActivity(Intent.createChooser(shareIntent, String.format("Database \"%s\" (%d MB) successfully saved on the SD-CARD! Share it?", newDatabasePathHuman, fileSizeMB)));
resetNoTouchTimer(true);
if(!mItemDataRecorderMode.isChecked())
{
mOpenedDatabasePath = newDatabasePath;
}
mProgressDialog.dismiss();
updateState(previousState);
new AlertDialog.Builder(getActivity())
.setTitle("Database saved!")
.setMessage(String.format("Database \"%s\" (%d MB) successfully saved on the SD-CARD! Share it?", newDatabasePathHuman, fileSizeMB))
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// Send to...
Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(f));
shareIntent.setType("application/octet-stream");
startActivity(Intent.createChooser(shareIntent, "Sharing..."));
resetNoTouchTimer(true);
if(!mItemDataRecorderMode.isChecked())
{
mOpenedDatabasePath = newDatabasePath;
}
mProgressDialog.dismiss();
updateState(previousState);
}
})
.setNegativeButton("No", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
resetNoTouchTimer(true);
if(!mItemDataRecorderMode.isChecked())
{
mOpenedDatabasePath = newDatabasePath;
}
mProgressDialog.dismiss();
updateState(previousState);
}
})
.show();
}
});
}
@@ -2597,16 +2692,30 @@ public class RTABMapActivity extends Activity implements OnClickListener, OnItem
public void run() {
mProgressDialog.dismiss();
// Send to...
File f = new File(zipOutput);
final File f = new File(zipOutput);
final int fileSizeMB = (int)f.length()/(1024 * 1024);
Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(f));
shareIntent.setType("application/zip");
startActivity(Intent.createChooser(shareIntent, String.format("Mesh \"%s\" (%d MB) successfully exported on the SD-CARD! Share it?", pathHuman, fileSizeMB)));
resetNoTouchTimer(true);
new AlertDialog.Builder(getActivity())
.setTitle("Database saved!")
.setMessage(String.format("Mesh \"%s\" (%d MB) successfully exported on the SD-CARD! Share it?", pathHuman, fileSizeMB))
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// Send to...
Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(f));
shareIntent.setType("application/zip");
startActivity(Intent.createChooser(shareIntent, "Sharing..."));
resetNoTouchTimer(true);
}
})
.setNegativeButton("No", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
resetNoTouchTimer(true);
}
})
.show();
}
});
}
@@ -195,6 +195,7 @@ public class SettingsActivity extends PreferenceActivity implements OnSharedPref
((Preference)findPreference(getString(R.string.pref_key_rendering_texture_decimation))).setSummary("("+((ListPreference)findPreference(getString(R.string.pref_key_rendering_texture_decimation))).getEntry() + ") "+getString(R.string.pref_summary_rendering_texture_decimation));
((Preference)findPreference(getString(R.string.pref_key_update_rate))).setSummary("("+((ListPreference)findPreference(getString(R.string.pref_key_update_rate))).getEntry() + ") "+getString(R.string.pref_summary_update_rate));
((Preference)findPreference(getString(R.string.pref_key_max_speed))).setSummary("("+((ListPreference)findPreference(getString(R.string.pref_key_max_speed))).getEntry() + ") "+getString(R.string.pref_summary_max_speed));
((Preference)findPreference(getString(R.string.pref_key_time_thr))).setSummary("("+((ListPreference)findPreference(getString(R.string.pref_key_time_thr))).getEntry() + ") "+getString(R.string.pref_summary_time_thr));
((Preference)findPreference(getString(R.string.pref_key_mem_thr))).setSummary("("+((ListPreference)findPreference(getString(R.string.pref_key_mem_thr))).getEntry() + ") "+getString(R.string.pref_summary_mem_thr));
((Preference)findPreference(getString(R.string.pref_key_loop_thr))).setSummary("("+((ListPreference)findPreference(getString(R.string.pref_key_loop_thr))).getEntry() + ") "+getString(R.string.pref_summary_loop_thr));
@@ -253,6 +254,7 @@ public class SettingsActivity extends PreferenceActivity implements OnSharedPref
if(key.compareTo(getString(R.string.pref_key_rendering_texture_decimation))==0) pref.setSummary("("+((ListPreference)pref).getEntry() + ") "+getString(R.string.pref_summary_rendering_texture_decimation));
if(key.compareTo(getString(R.string.pref_key_update_rate))==0) pref.setSummary("("+((ListPreference)pref).getEntry() + ") "+getString(R.string.pref_summary_update_rate));
if(key.compareTo(getString(R.string.pref_key_max_speed))==0) pref.setSummary("("+((ListPreference)pref).getEntry() + ") "+getString(R.string.pref_summary_max_speed));
if(key.compareTo(getString(R.string.pref_key_time_thr))==0) pref.setSummary("("+((ListPreference)pref).getEntry() + ") "+getString(R.string.pref_summary_time_thr));
if(key.compareTo(getString(R.string.pref_key_mem_thr))==0) pref.setSummary("("+((ListPreference)pref).getEntry() + ") "+getString(R.string.pref_summary_mem_thr));
if(key.compareTo(getString(R.string.pref_key_loop_thr))==0) pref.setSummary("("+((ListPreference)pref).getEntry() + ") "+getString(R.string.pref_summary_loop_thr));
+2 -2
View File
@@ -104,7 +104,7 @@ INSTALL(CODE "execute_process(COMMAND ln -s \"../MacOS/${CMAKE_BUNDLE_NAME}\" ${
WORKING_DIRECTORY \$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/bin)")
ENDIF(APPLE AND BUILD_AS_BUNDLE)
IF((APPLE AND BUILD_AS_BUNDLE) OR WIN32)
IF(BUILD_AS_BUNDLE AND (APPLE OR WIN32))
SET(APPS "\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/bin/${PROJECT_NAME}${CMAKE_EXECUTABLE_SUFFIX}")
SET(plugin_dest_dir bin)
SET(qtconf_dest_dir bin)
@@ -189,5 +189,5 @@ IF((APPLE AND BUILD_AS_BUNDLE) OR WIN32)
include(\"BundleUtilities\")
fixup_bundle(\"${APPS}\" \"\${QTPLUGINS}\" \"${DIRS}\")
" COMPONENT runtime)
ENDIF((APPLE AND BUILD_AS_BUNDLE) OR WIN32)
ENDIF(BUILD_AS_BUNDLE AND (APPLE OR WIN32))
+2 -2
View File
@@ -46,7 +46,7 @@ public:
}
virtual ~ObjDeletionHandler() {}
signals:
Q_SIGNALS:
void objDeletionEventReceived(int);
protected:
@@ -55,7 +55,7 @@ protected:
if(event->getClassName().compare("UObjDeletedEvent") == 0 &&
event->getCode() == _watchedId)
{
emit objDeletionEventReceived(_watchedId);
Q_EMIT objDeletionEventReceived(_watchedId);
}
return false;
}
+3 -3
View File
@@ -49,7 +49,7 @@ int main(int argc, char* argv[])
QApplication * app = new QApplication(argc, argv);
app->setStyleSheet("QMessageBox { messagebox-text-interaction-flags: 5; }"); // selectable message box
ParametersMap parameters = Parameters::parseArguments(argc, argv, true);
ParametersMap parameters = Parameters::parseArguments(argc, argv, false);
MainWindow * mainWindow = new MainWindow();
app->installEventFilter(mainWindow); // to catch FileOpen events.
@@ -85,9 +85,9 @@ int main(int argc, char* argv[])
if(!database.empty())
{
mainWindow->openDatabase(database.c_str());
mainWindow->openDatabase(database.c_str(), parameters);
}
if(parameters.size())
else if(parameters.size())
{
mainWindow->updateParameters(parameters);
}
+5 -5
View File
@@ -19,13 +19,13 @@ set(Triclops_LIBDIR $ENV{Triclops_ROOT_DIR}/lib)
endif()
#FlyCapture2 SDK
find_path(FlyCapture2_INCLUDE_DIR NAMES FlyCapture2.h PATHS $ENV{FlyCapture2_ROOT_DIR}/include)
find_library(FlyCapture2_LIBRARY NAMES FlyCapture2_v100 FlyCapture2 flycapture2 NO_DEFAULT_PATH PATHS ${FlyCapture2_LIBDIR})
find_path(FlyCapture2_INCLUDE_DIR NAMES FlyCapture2.h PATHS $ENV{FlyCapture2_ROOT_DIR}/include $ENV{FlyCapture2_ROOT_DIR}/include/flycapture)
find_library(FlyCapture2_LIBRARY NAMES FlyCapture2_v100 FlyCapture2 flycapture2 flycapture NO_DEFAULT_PATH PATHS ${FlyCapture2_LIBDIR})
# Triclops SDK
find_path(Triclops_INCLUDE_DIR NAMES triclops.h PATHS $ENV{Triclops_ROOT_DIR}/include)
find_library(Triclops_LIBRARY NAMES triclops triclops_v100 NO_DEFAULT_PATH PATHS ${Triclops_LIBDIR})
find_library(FlyCaptureBridge_LIBRARY NAMES flycapture2bridge flycapture2bridge_v100 NO_DEFAULT_PATH PATHS ${Triclops_LIBDIR})
find_path(Triclops_INCLUDE_DIR NAMES triclops.h PATHS $ENV{Triclops_ROOT_DIR}/include $ENV{Triclops_ROOT_DIR}/include/triclops)
find_library(Triclops_LIBRARY NAMES triclops triclops_v100 libtriclops.so.3 NO_DEFAULT_PATH PATHS ${Triclops_LIBDIR})
find_library(FlyCaptureBridge_LIBRARY NAMES flycapture2bridge flycapture2bridge_v100 libflycapture2bridge.so.3 NO_DEFAULT_PATH PATHS ${Triclops_LIBDIR})
find_library(pnmutils_LIBRARY NAMES pnmutils pnmutils_v100 NO_DEFAULT_PATH PATHS ${Triclops_LIBDIR})
IF (FlyCapture2_INCLUDE_DIR AND Triclops_INCLUDE_DIR AND FlyCapture2_LIBRARY AND Triclops_LIBRARY AND FlyCaptureBridge_LIBRARY AND pnmutils_LIBRARY)
+20 -2
View File
@@ -17,6 +17,14 @@ FIND_LIBRARY(CHOLMOD_LIB cholmod)
FIND_PATH(G2O_INCLUDE_DIR g2o/core/base_vertex.h
PATHS "C:\\Program Files\\g2o\\include")
FIND_FILE(G2O_CONFIG_FILE g2o/config.h
PATHS ${G2O_INCLUDE_DIR}
NO_DEFAULT_PATH)
#ifdef G2O_NUMBER_FORMAT_STR
#define G2O_CPP11 // we assume that if G2O_NUMBER_FORMAT_STR is defined, this is the new g2o code with c++11 interface
#endif
# Macro to unify finding both the debug and release versions of the
# libraries; this is adapted from the rtabmap config
@@ -75,7 +83,7 @@ ENDIF(G2O_SOLVER_CHOLMOD OR G2O_SOLVER_CSPARSE OR G2O_SOLVER_DENSE OR G2O_SOLVER
# G2O itself declared found if we found the core libraries and at least one solver
SET(G2O_FOUND "NO")
IF(G2O_STUFF_LIBRARY AND G2O_CORE_LIBRARY AND G2O_INCLUDE_DIR AND G2O_SOLVERS_FOUND)
IF(G2O_STUFF_LIBRARY AND G2O_CORE_LIBRARY AND G2O_INCLUDE_DIR AND G2O_CONFIG_FILE AND G2O_SOLVERS_FOUND)
SET(G2O_INCLUDE_DIRS ${G2O_INCLUDE_DIR})
SET(G2O_LIBRARIES
${G2O_CORE_LIBRARY}
@@ -105,5 +113,15 @@ IF(G2O_STUFF_LIBRARY AND G2O_CORE_LIBRARY AND G2O_INCLUDE_DIR AND G2O_SOLVERS_FO
${CHOLMOD_LIB})
ENDIF(G2O_SOLVER_CHOLMOD)
FILE(READ ${G2O_CONFIG_FILE} TMPTXT)
STRING(FIND "${TMPTXT}" "G2O_NUMBER_FORMAT_STR" matchres)
IF(${matchres} EQUAL -1)
MESSAGE(STATUS "Old g2o version detected with c++03 interface (config file: ${G2O_CONFIG_FILE}).")
SET(G2O_CPP11 0)
ELSE()
MESSAGE(WARNING "Latest g2o version detected with c++11 interface (config file: ${G2O_CONFIG_FILE}). Make sure g2o is built with \"-DBUILD_WITH_MARCH_NATIVE=OFF\" to avoid segmentation faults caused by Eigen.")
SET(G2O_CPP11 1)
ENDIF()
SET(G2O_FOUND "YES")
ENDIF(G2O_STUFF_LIBRARY AND G2O_CORE_LIBRARY AND G2O_INCLUDE_DIR AND G2O_SOLVERS_FOUND)
ENDIF(G2O_STUFF_LIBRARY AND G2O_CORE_LIBRARY AND G2O_INCLUDE_DIR AND G2O_CONFIG_FILE AND G2O_SOLVERS_FOUND)
+183
View File
@@ -0,0 +1,183 @@
#.rst:
# FindKinectSDK2
# --------------
#
# Find Kinect for Windows SDK v2 (Kinect SDK v2) include dirs, library dirs, libraries
#
# Use this module by invoking find_package with the form::
#
# find_package( KinectSDK2 [REQUIRED] )
#
# Results for users are reported in following variables::
#
# KinectSDK2_FOUND - Return "TRUE" when Kinect SDK v2 found. Otherwise, Return "FALSE".
# KinectSDK2_INCLUDE_DIRS - Kinect SDK v2 include directories. (${KinectSDK2_DIR}/inc)
# KinectSDK2_LIBRARY_DIRS - Kinect SDK v2 library directories. (${KinectSDK2_DIR}/Lib/x86 or ${KinectSDK2_DIR}/Lib/x64)
# KinectSDK2_LIBRARIES - Kinect SDK v2 library files. (${KinectSDK2_LIBRARY_DIRS}/Kinect20.lib (If check the box of any application festures, corresponding library will be added.))
# KinectSDK2_COMMANDS - Copy commands of redist files for application functions of Kinect SDK v2. (If uncheck the box of all application features, this variable has defined empty command.)
#
# This module reads hints about search locations from following environment variables::
#
# KINECTSDK20_DIR - Kinect SDK v2 root directory. (This environment variable has been set by installer of Kinect SDK v2.)
#
# CMake entries::
#
# KinectSDK2_DIR - Kinect SDK v2 root directory. (Default $ENV{KINECTSDK20_DIR})
# KinectSDK2_FACE - Check the box when using Face or HDFace features. (Default uncheck)
# KinectSDK2_FUSION - Check the box when using Fusion features. (Default uncheck)
# KinectSDK2_VGB - Check the box when using Visual Gesture Builder features. (Default uncheck)
#
# Example to find Kinect SDK v2::
#
# cmake_minimum_required( VERSION 2.8 )
#
# project( project )
# add_executable( project main.cpp )
# set_property( DIRECTORY PROPERTY VS_STARTUP_PROJECT "project" )
#
# # Find package using this module.
# find_package( KinectSDK2 REQUIRED )
#
# if(KinectSDK2_FOUND)
# # [C/C++]>[General]>[Additional Include Directories]
# include_directories( ${KinectSDK2_INCLUDE_DIRS} )
#
# # [Linker]>[General]>[Additional Library Directories]
# link_directories( ${KinectSDK2_LIBRARY_DIRS} )
#
# # [Linker]>[Input]>[Additional Dependencies]
# target_link_libraries( project ${KinectSDK2_LIBRARIES} )
#
# # [Build Events]>[Post-Build Event]>[Command Line]
# add_custom_command( TARGET project POST_BUILD ${KinectSDK2_COMMANDS} )
# endif()
#
# =============================================================================
#
# Copyright (c) 2016 Tsukasa SUGIURA
# Distributed under the MIT License.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
# The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
# =============================================================================
##### Utility #####
# Check Directory Macro
macro(CHECK_DIR _DIR)
if(NOT EXISTS "${${_DIR}}")
message(WARNING "Directory \"${${_DIR}}\" not found.")
set(KinectSDK2_FOUND FALSE)
unset(_DIR)
endif()
endmacro()
# Check Files Macro
macro(CHECK_FILES _FILES _DIR)
set(_MISSING_FILES)
foreach(_FILE ${${_FILES}})
if(NOT EXISTS "${_FILE}")
get_filename_component(_FILE ${_FILE} NAME)
set(_MISSING_FILES "${_MISSING_FILES}${_FILE}, ")
endif()
endforeach()
if(_MISSING_FILES)
message(WARNING "In directory \"${${_DIR}}\" not found files: ${_MISSING_FILES}")
set(KinectSDK2_FOUND FALSE)
unset(_FILES)
endif()
endmacro()
# Target Platform
set(TARGET_PLATFORM)
if(NOT CMAKE_CL_64)
set(TARGET_PLATFORM x86)
else()
set(TARGET_PLATFORM x64)
endif()
##### Find Kinect SDK v2 #####
# Found
set(KinectSDK2_FOUND TRUE)
if(MSVC_VERSION LESS 1700)
message(WARNING "Kinect for Windows SDK v2 supported Visual Studio 2012 or later.")
set(KinectSDK2_FOUND FALSE)
endif()
# Options
option(KinectSDK2_FACE "Face and HDFace features" FALSE)
option(KinectSDK2_FUSION "Fusion features" FALSE)
option(KinectSDK2_VGB "Visual Gesture Builder features" FALSE)
# Root Directoty
set(KinectSDK2_DIR)
if(KinectSDK2_FOUND)
set(KinectSDK2_DIR $ENV{KINECTSDK20_DIR} CACHE PATH "Kinect for Windows SDK v2 Install Path." FORCE)
check_dir(KinectSDK2_DIR)
endif()
# Include Directories
set(KinectSDK2_INCLUDE_DIRS)
if(KinectSDK2_FOUND)
set(KinectSDK2_INCLUDE_DIRS ${KinectSDK2_DIR}/inc)
check_dir(KinectSDK2_INCLUDE_DIRS)
endif()
# Library Directories
set(KinectSDK2_LIBRARY_DIRS)
if(KinectSDK2_FOUND)
set(KinectSDK2_LIBRARY_DIRS ${KinectSDK2_DIR}/Lib/${TARGET_PLATFORM})
check_dir(KinectSDK2_LIBRARY_DIRS)
endif()
# Dependencies
set(KinectSDK2_LIBRARIES)
if(KinectSDK2_FOUND)
set(KinectSDK2_LIBRARIES ${KinectSDK2_LIBRARY_DIRS}/Kinect20.lib)
if(KinectSDK2_FACE)
set(KinectSDK2_LIBRARIES ${KinectSDK2_LIBRARIES};${KinectSDK2_LIBRARY_DIRS}/Kinect20.Face.lib)
endif()
if(KinectSDK2_FUSION)
set(KinectSDK2_LIBRARIES ${KinectSDK2_LIBRARIES};${KinectSDK2_LIBRARY_DIRS}/Kinect20.Fusion.lib)
endif()
if(KinectSDK2_VGB)
set(KinectSDK2_LIBRARIES ${KinectSDK2_LIBRARIES};${KinectSDK2_LIBRARY_DIRS}/Kinect20.VisualGestureBuilder.lib)
endif()
check_files(KinectSDK2_LIBRARIES KinectSDK2_LIBRARY_DIRS)
endif()
# Custom Commands
set(KinectSDK2_COMMANDS)
if(KinectSDK2_FOUND)
if(KinectSDK2_FACE)
set(KinectSDK2_REDIST_DIR ${KinectSDK2_DIR}/Redist/Face/${TARGET_PLATFORM})
check_dir(KinectSDK2_REDIST_DIR)
list(APPEND KinectSDK2_COMMANDS COMMAND xcopy "${KinectSDK2_REDIST_DIR}" "$(OutDir)" /e /y /i /r > NUL)
endif()
if(KinectSDK2_FUSION)
set(KinectSDK2_REDIST_DIR ${KinectSDK2_DIR}/Redist/Fusion/${TARGET_PLATFORM})
check_dir(KinectSDK2_REDIST_DIR)
list(APPEND KinectSDK2_COMMANDS COMMAND xcopy "${KinectSDK2_REDIST_DIR}" "$(OutDir)" /e /y /i /r > NUL)
endif()
if(KinectSDK2_VGB)
set(KinectSDK2_REDIST_DIR ${KinectSDK2_DIR}/Redist/VGB/${TARGET_PLATFORM})
check_dir(KinectSDK2_REDIST_DIR)
list(APPEND KinectSDK2_COMMANDS COMMAND xcopy "${KinectSDK2_REDIST_DIR}" "$(OutDir)" /e /y /i /r > NUL)
endif()
# Empty Commands
if(NOT KinectSDK2_COMMANDS)
set(KinectSDK2_COMMANDS COMMAND)
endif()
endif()
message(STATUS "KinectSDK2_FOUND : ${KinectSDK2_FOUND}")
+41
View File
@@ -0,0 +1,41 @@
# - Find librealsense (https://github.com/IntelRealSense/librealsense)
#
# RealSense2_ROOT_DIR environment variable can be set to find the library.
#
# It sets the following variables:
# RealSense2_FOUND - Set to false, or undefined, if RealSense2 isn't found.
# RealSense2_INCLUDE_DIRS - The RealSense2 include directory.
# RealSense2_LIBRARIES - The RealSense2 library to link against.
#RealSense library
find_path(RealSense2_INCLUDE_DIRS NAMES librealsense2/rs.hpp PATHS $ENV{RealSense2_ROOT_DIR}/include)
if(CMAKE_CL_64)
find_library(RealSense2_LIBRARY NAMES realsense2 PATHS $ENV{RealSense2_ROOT_DIR}/lib $ENV{RealSense2_ROOT_DIR}/lib/x64 $ENV{RealSense2_ROOT_DIR}/bin $ENV{RealSense2_ROOT_DIR}/bin/x64)
else()
find_library(RealSense2_LIBRARY NAMES realsense2 PATHS $ENV{RealSense2_ROOT_DIR}/lib $ENV{RealSense2_ROOT_DIR}/lib/x86 $ENV{RealSense2_ROOT_DIR}/bin $ENV{RealSense2_ROOT_DIR}/bin/x86)
endif()
IF (RealSense2_INCLUDE_DIRS AND RealSense2_LIBRARY)
SET(RealSense2_FOUND TRUE)
ENDIF (RealSense2_INCLUDE_DIRS AND RealSense2_LIBRARY)
IF (RealSense2_FOUND)
SET(RealSense2_LIBRARIES ${RealSense2_LIBRARY})
# Compatibility with linux names
SET(realsense2_LIBRARIES ${RealSense2_LIBRARIES})
SET(realsense2_INCLUDE_DIRS ${RealSense2_INCLUDE_DIRS})
SET(realsense2_FOUND ${RealSense2_FOUND})
# show which RealSense was found only if not quiet
IF (NOT RealSense2_FIND_QUIETLY)
MESSAGE(STATUS "Found RealSense: ${RealSense2_LIBRARIES}")
ENDIF (NOT RealSense2_FIND_QUIETLY)
ELSE (RealSense2_FOUND)
# fatal error if RealSense is required but not found
IF (RealSense2_FIND_REQUIRED)
MESSAGE(FATAL_ERROR "Could not find RealSense2 (librealsense2)")
ENDIF (RealSense2_FIND_REQUIRED)
ENDIF (RealSense2_FOUND)
+14 -31
View File
@@ -2,46 +2,29 @@
# This module finds an installed Sqlite3 package.
#
# It sets the following variables:
# SQLITE3_FOUND - Set to false, or undefined, if Sqlite3 isn't found.
# SQLITE3_INCLUDE_DIR - The Sqlite3 include directory.
# SQLITE3_LIBRARY - The Sqlite3 library to link against.
# Sqlite3_FOUND - Set to false, or undefined, if Sqlite3 isn't found.
# Sqlite3_INCLUDE_DIR - The Sqlite3 include directory.
# Sqlite3_LIBRARY - The Sqlite3 library to link against.
SET(SQLITE3_VERSION_REQUIRED "3.6.0")
FIND_PATH(Sqlite3_INCLUDE_DIR sqlite3.h PATHS $ENV{Sqlite3_ROOT_DIR}/include $ENV{Sqlite3_ROOT_DIR})
IF(UNIX)
FIND_PROGRAM(SQLITE3_EXEC NAME sqlite3 PATHS)
IF(SQLITE3_EXEC)
MESSAGE(STATUS "Found Sqlite3 executable : ${SQLITE3_EXEC}")
EXECUTE_PROCESS(COMMAND ${SQLITE3_EXEC} --version
OUTPUT_VARIABLE SQLITE3_VERSION
OUTPUT_STRIP_TRAILING_WHITESPACE
WORKING_DIRECTORY "./"
)
IF(SQLITE3_VERSION VERSION_LESS SQLITE3_VERSION_REQUIRED)
MESSAGE(FATAL_ERROR "Sqlite ${SQLITE3_VERSION} found, but version ${SQLITE3_VERSION_REQUIRED} minimum is required")
ENDIF(SQLITE3_VERSION VERSION_LESS SQLITE3_VERSION_REQUIRED)
ELSE(SQLITE3_EXEC)
MESSAGE(FATAL_ERROR "Could not find Sqlite3 executable")
ENDIF(SQLITE3_EXEC)
ENDIF(UNIX)
FIND_LIBRARY(Sqlite3_LIBRARY NAMES sqlite3 PATHS $ENV{Sqlite3_ROOT_DIR}/lib $ENV{Sqlite3_ROOT_DIR})
FIND_PATH(SQLITE3_INCLUDE_DIR sqlite3.h)
IF (Sqlite3_INCLUDE_DIR AND Sqlite3_LIBRARY)
SET(Sqlite3_FOUND TRUE)
SET(Sqlite3_INCLUDE_DIRS ${Sqlite3_INCLUDE_DIR})
SET(Sqlite3_LIBRARIES ${Sqlite3_LIBRARY})
ENDIF (Sqlite3_INCLUDE_DIR AND Sqlite3_LIBRARY)
FIND_LIBRARY(SQLITE3_LIBRARY NAMES sqlite3.dll sqlite3)
IF (SQLITE3_INCLUDE_DIR AND SQLITE3_LIBRARY)
SET(SQLITE3_FOUND TRUE)
ENDIF (SQLITE3_INCLUDE_DIR AND SQLITE3_LIBRARY)
IF (SQLITE3_FOUND)
IF (Sqlite3_FOUND)
# show which Sqlite3 was found only if not quiet
IF (NOT Sqlite3_FIND_QUIETLY)
MESSAGE(STATUS "Found Sqlite3")
MESSAGE(STATUS "Found Sqlite3: ${Sqlite3_INCLUDE_DIRS} ${Sqlite3_LIBRARIES}")
ENDIF (NOT Sqlite3_FIND_QUIETLY)
ELSE (SQLITE3_FOUND)
ELSE (Sqlite3_FOUND)
# fatal error if Sqlite3 is required but not found
IF (Sqlite3_FIND_REQUIRED)
MESSAGE(FATAL_ERROR "Could not find Sqlite3")
ENDIF (Sqlite3_FIND_REQUIRED)
ENDIF (SQLITE3_FOUND)
ENDIF (Sqlite3_FOUND)
+3 -6
View File
@@ -59,18 +59,14 @@ public:
const std::vector<double> & getPredictionLC() const; // {Vp, Lc, l1, l2, l3, l4...}
std::string getPredictionLCStr() const; // for convenience {Vp, Lc, l1, l2, l3, l4...}
cv::Mat generatePrediction(const Memory * memory, const std::vector<int> & ids) const;
cv::Mat generatePrediction(const Memory * memory, const std::vector<int> & ids);
private:
cv::Mat updatePrediction(const cv::Mat & oldPrediction,
const Memory * memory,
const std::vector<int> & oldIds,
const std::vector<int> & newIds) const;
const std::vector<int> & newIds);
void updatePosterior(const Memory * memory, const std::vector<int> & likelihoodIds);
float addNeighborProb(cv::Mat & prediction,
unsigned int col,
const std::map<int, int> & neighbors,
const std::map<int, int> & idToIndexMap) const;
void normalize(cv::Mat & prediction, unsigned int index, float addedProbabilitiesSum, bool virtualPlaceUsed) const;
private:
@@ -80,6 +76,7 @@ private:
std::vector<double> _predictionLC; // {Vp, Lc, l1, l2, l3, l4...}
bool _fullPredictionUpdate;
float _totalPredictionLCValues;
std::map<int, std::map<int, int> > _neighborsIndex;
};
} // namespace rtabmap
+1
View File
@@ -66,6 +66,7 @@ public:
void setImageRate(float imageRate) {_imageRate = imageRate;}
void setLocalTransform(const Transform & localTransform) {_localTransform= localTransform;}
void resetTimer();
protected:
/**
* Constructor
@@ -59,6 +59,7 @@ public:
float timeCapture;
float timeDisparity;
float timeMirroring;
float timeStereoExposureCompensation;
float timeImageDecimation;
float timeScanFromDepth;
float timeUndistortDepth;
@@ -66,6 +67,7 @@ public:
float timeTotal;
Transform odomPose;
cv::Mat odomCovariance;
std::vector<float> odomVelocity;
};
} // namespace rtabmap
@@ -75,6 +75,7 @@ public:
virtual ~CameraModel() {}
void initRectificationMap();
bool isRectificationMapInitialized() {return !mapX_.empty() && !mapY_.empty();}
bool isValidForProjection() const {return fx()>0.0 && fy()>0.0 && cx()>0.0 && cy()>0.0;}
bool isValidForReprojection() const {return fx()>0.0 && fy()>0.0 && cx()>0.0 && cy()>0.0 && imageWidth()>0 && imageHeight()>0;}
+11 -8
View File
@@ -68,7 +68,7 @@ public:
const CameraModel & cameraModel() const {return _model;}
void setPath(const std::string & dir) {_path=dir;}
void setStartIndex(int index) {_startAt = index;} // negative means last
virtual void setStartIndex(int index) {_startAt = index;} // negative means last
void setDirRefreshed(bool enabled) {_refreshDir = enabled;}
void setImagesRectified(bool enabled) {_rectifyImages = enabled;}
void setBayerMode(int mode) {_bayerMode = mode;} // -1=disabled (default) 0=BayerBG, 1=BayerGB, 2=BayerRG, 3=BayerGR
@@ -87,7 +87,8 @@ public:
float voxelSize = 0.0f,
int normalsK = 0, // compute normals if > 0
float normalsRadius = 0, // compute normals if > 0
const Transform & localTransform=Transform::getIdentity())
const Transform & localTransform=Transform::getIdentity(),
bool forceGroundNormalsUp = false)
{
_scanPath = dir;
_scanLocalTransform = localTransform;
@@ -96,10 +97,7 @@ public:
_scanNormalsK = normalsK;
_scanNormalsRadius = normalsRadius;
_scanVoxelSize = voxelSize;
if(_scanDownsampleStep>1)
{
_scanMaxPts /= _scanDownsampleStep;
}
_scanForceGroundNormalsUp = forceGroundNormalsUp;
}
void setDepthFromScan(bool enabled, int fillHoles = 1, bool fillHolesFromBorder = false)
@@ -123,6 +121,9 @@ public:
_groundTruthFormat = format;
}
void setMaxPoseTimeDiff(double diff) {_maxPoseTimeDiff = diff;}
double getMaxPoseTimeDiff() const {return _maxPoseTimeDiff;}
void setDepth(bool isDepth, float depthScaleFactor = 1.0f)
{
_isDepth = isDepth;
@@ -135,7 +136,8 @@ protected:
std::list<Transform> & outputPoses,
std::list<double> & stamps,
const std::string & filePath,
int format) const;
int format,
double maxTimeDiff) const;
private:
std::string _path;
@@ -161,6 +163,7 @@ private:
float _scanVoxelSize;
int _scanNormalsK;
float _scanNormalsRadius;
bool _scanForceGroundNormalsUp;
bool _depthFromScan;
int _depthFromScanFillHoles; // <0:horizontal 0:disabled >0:vertical
@@ -172,9 +175,9 @@ private:
std::string _odometryPath;
int _odometryFormat;
std::string _groundTruthPath;
int _groundTruthFormat;
double _maxPoseTimeDiff;
std::list<double> _stamps;
std::list<Transform> odometry_;
+139 -3
View File
@@ -39,9 +39,14 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <pcl/pcl_config.h>
#ifdef HAVE_OPENNI
#if __linux__ && __i386__ && __cplusplus >= 201103L
#warning "Openni driver is not available on i386 when building with c++11 support"
#else
#define RTABMAP_OPENNI
#include <pcl/io/openni_camera/openni_depth_image.h>
#include <pcl/io/openni_camera/openni_image.h>
#endif
#endif
#include <boost/signals2/connection.hpp>
@@ -74,9 +79,25 @@ namespace rs
}
}
namespace rs2
{
class context;
class device;
class syncer;
}
struct rs2_intrinsics;
struct rs2_extrinsics;
typedef struct _freenect_context freenect_context;
typedef struct _freenect_device freenect_device;
typedef struct IKinectSensor IKinectSensor;
typedef struct ICoordinateMapper ICoordinateMapper;
typedef struct _DepthSpacePoint DepthSpacePoint;
typedef struct _ColorSpacePoint ColorSpacePoint;
typedef struct tagRGBQUAD RGBQUAD;
typedef struct IMultiSourceFrameReader IMultiSourceFrameReader;
namespace rtabmap
{
@@ -95,7 +116,7 @@ public:
float imageRate = 0,
const Transform & localTransform = Transform::getIdentity());
virtual ~CameraOpenni();
#ifdef HAVE_OPENNI
#ifdef RTABMAP_OPENNI
void image_cb (
const boost::shared_ptr<openni_wrapper::Image>& rgb,
const boost::shared_ptr<openni_wrapper::DepthImage>& depth,
@@ -178,6 +199,7 @@ public:
bool setGain(int value);
bool setMirroring(bool enabled);
void setOpenNI2StampsAndIDsUsed(bool used);
void setIRDepthShift(int horizontal, int vertical);
protected:
virtual SensorData captureImage(CameraInfo * info = 0);
@@ -193,6 +215,8 @@ private:
std::string _deviceId;
bool _openNI2StampsAndIDsUsed;
StereoCameraModel _stereoModel;
int _depthHShift;
int _depthVShift;
#endif
};
@@ -256,14 +280,15 @@ public:
public:
// default local transform z in, x right, y down));
CameraFreenect2(int deviceId= 0,
Type type = kTypeColor2DepthSD,
Type type = kTypeDepth2ColorSD,
float imageRate=0.0f,
const Transform & localTransform = Transform::getIdentity(),
float minDepth = 0.3f,
float maxDepth = 12.0f,
bool bilateralFiltering = true,
bool edgeAwareFiltering = true,
bool noiseFiltering = true);
bool noiseFiltering = true,
const std::string & pipelineName = "");
virtual ~CameraFreenect2();
virtual bool init(const std::string & calibrationFolder = ".", const std::string & cameraName = "");
@@ -287,6 +312,61 @@ private:
bool bilateralFiltering_;
bool edgeAwareFiltering_;
bool noiseFiltering_;
std::string pipelineName_;
#endif
};
/////////////////////////
// CameraK4W2
/////////////////////////
class RTABMAP_EXP CameraK4W2 :
public Camera
{
public:
static bool available();
enum Type {
kTypeColor2DepthSD,
kTypeDepth2ColorSD,
kTypeDepth2ColorHD
};
public:
static const int cDepthWidth = 512;
static const int cDepthHeight = 424;
static const int cColorWidth = 1920;
static const int cColorHeight = 1080;
public:
// default local transform z in, x right, y down));
CameraK4W2(int deviceId = 0, // not used
Type type = kTypeDepth2ColorSD,
float imageRate = 0.0f,
const Transform & localTransform = Transform::getIdentity());
virtual ~CameraK4W2();
virtual bool init(const std::string & calibrationFolder = ".", const std::string & cameraName = "");
virtual bool isCalibrated() const;
virtual std::string getSerial() const;
protected:
virtual SensorData captureImage(CameraInfo * info = 0);
private:
void close();
private:
#ifdef RTABMAP_K4W2
Type type_;
IKinectSensor* pKinectSensor_;
ICoordinateMapper* pCoordinateMapper_;
DepthSpacePoint* pDepthCoordinates_;
ColorSpacePoint* pColorCoordinates_;
IMultiSourceFrameReader* pMultiSourceFrameReader_;
RGBQUAD * pColorRGBX_;
INT_PTR hMSEvent;
CameraModel colorCameraModel_;
#endif
};
@@ -299,6 +379,7 @@ class RTABMAP_EXP CameraRealSense :
{
public:
static bool available();
enum RGBSource {kColor, kInfrared, kFishEye};
public:
// default local transform z in, x right, y down));
@@ -311,6 +392,8 @@ public:
const Transform & localTransform = Transform::getIdentity());
virtual ~CameraRealSense();
void setDepthScaledToRGBSize(bool enabled);
void setRGBSource(RGBSource source);
virtual bool init(const std::string & calibrationFolder = ".", const std::string & cameraName = "");
virtual bool isCalibrated() const;
virtual std::string getSerial() const;
@@ -327,6 +410,10 @@ private:
int presetRGB_;
int presetDepth_;
bool computeOdometry_;
bool depthScaledToRGBSize_;
RGBSource rgbSource_;
CameraModel cameraModel_;
std::vector<int> rsRectificationTable_;
int motionSeq_[2];
rs::slam::slam * slam_;
@@ -338,6 +425,53 @@ private:
USemaphore dataReady_;
#endif
};
/////////////////////////
// CameraRealSense2
/////////////////////////
class slam_event_handler;
class RTABMAP_EXP CameraRealSense2 :
public Camera
{
public:
static bool available();
public:
// default local transform z in, x right, y down));
CameraRealSense2(
const std::string & deviceId = "",
float imageRate = 0,
const Transform & localTransform = Transform::getIdentity());
virtual ~CameraRealSense2();
virtual bool init(const std::string & calibrationFolder = ".", const std::string & cameraName = "");
virtual bool isCalibrated() const;
virtual std::string getSerial() const;
// parameters are set during initialization
void setEmitterEnabled(bool enabled);
void setIRDepthFormat(bool enabled);
protected:
virtual SensorData captureImage(CameraInfo * info = 0);
private:
#ifdef RTABMAP_REALSENSE2
rs2::context * ctx_;
rs2::device * dev_;
std::string deviceId_;
rs2::syncer * syncer_;
float depth_scale_meters_;
rs2_intrinsics * depthIntrinsics_;
rs2_intrinsics * rgbIntrinsics_;
rs2_extrinsics * depthToRGBExtrinsics_;
cv::Mat depthBuffer_;
cv::Mat rgbBuffer_;
CameraModel model_;
bool emitterEnabled_;
bool irDepth_;
#endif
};
/////////////////////////
@@ -363,6 +497,8 @@ public:
virtual bool isCalibrated() const;
virtual std::string getSerial() const;
virtual void setStartIndex(int index) {CameraImages::setStartIndex(index);cameraDepth_.setStartIndex(index);} // negative means last
protected:
virtual SensorData captureImage(CameraInfo * info = 0);
+11 -2
View File
@@ -123,7 +123,7 @@ public:
bool computeOdometry = false,
float imageRate=0.0f,
const Transform & localTransform = Transform::getIdentity(),
bool selfCalibration = false);
bool selfCalibration = true);
CameraStereoZed(
const std::string & svoFilePath,
int quality = 1, // 0=NONE, 1=PERFORMANCE, 2=QUALITY
@@ -132,7 +132,7 @@ public:
bool computeOdometry = false,
float imageRate=0.0f,
const Transform & localTransform = Transform::getIdentity(),
bool selfCalibration = false);
bool selfCalibration = true);
virtual ~CameraStereoZed();
virtual bool init(const std::string & calibrationFolder = ".", const std::string & cameraName = "");
@@ -188,6 +188,8 @@ public:
virtual bool isCalibrated() const;
virtual std::string getSerial() const;
virtual void setStartIndex(int index) {CameraImages::setStartIndex(index);camera2_->setStartIndex(index);} // negative means last
protected:
virtual SensorData captureImage(CameraInfo * info = 0);
@@ -224,6 +226,12 @@ public:
bool rectifyImages = false,
float imageRate = 0.0f,
const Transform & localTransform = Transform::getIdentity());
CameraStereoVideo(
int deviceLeft,
int deviceRight,
bool rectifyImages = false,
float imageRate = 0.0f,
const Transform & localTransform = Transform::getIdentity());
virtual ~CameraStereoVideo();
virtual bool init(const std::string & calibrationFolder = ".", const std::string & cameraName = "");
@@ -243,6 +251,7 @@ private:
std::string cameraName_;
CameraVideo::Source src_;
int usbDevice_;
int usbDevice2_;
};
} // namespace rtabmap
@@ -60,6 +60,7 @@ public:
virtual ~CameraThread();
void setMirroringEnabled(bool enabled) {_mirroring = enabled;}
void setStereoExposureCompensation(bool enabled) {_stereoExposureCompensation = enabled;}
void setColorOnly(bool colorOnly) {_colorOnly = colorOnly;}
void setImageDecimation(int decimation) {_imageDecimation = decimation;}
void setStereoToDepth(bool enabled) {_stereoToDepth = enabled;}
@@ -100,6 +101,7 @@ private:
private:
Camera * _camera;
bool _mirroring;
bool _stereoExposureCompensation;
bool _colorOnly;
int _imageDecimation;
bool _stereoToDepth;
@@ -83,5 +83,8 @@ cv::Mat RTABMAP_EXP uncompressData(const cv::Mat & bytes);
cv::Mat RTABMAP_EXP uncompressData(const std::vector<unsigned char> & bytes);
cv::Mat RTABMAP_EXP uncompressData(const unsigned char * bytes, unsigned long size);
cv::Mat RTABMAP_EXP compressString(const std::string & str);
std::string RTABMAP_EXP uncompressString(const cv::Mat & bytes);
} /* namespace rtabmap */
#endif /* COMPRESSION_H_ */
+23 -13
View File
@@ -68,6 +68,7 @@ public:
virtual ~DBDriver();
virtual void parseParameters(const ParametersMap & parameters);
virtual bool isInMemory() const {return _url.empty();}
const std::string & getUrl() const {return _url;}
void beginTransaction() const;
@@ -91,6 +92,7 @@ public:
int nodeId,
const cv::Mat & ground,
const cv::Mat & obstacles,
const cv::Mat & empty,
float cellSize,
const cv::Point3f & viewpoint);
void updateDepthImage(int nodeId, const cv::Mat & image);
@@ -100,9 +102,12 @@ public:
void addStatistics(const Statistics & statistics) const;
void savePreviewImage(const cv::Mat & image) const;
cv::Mat loadPreviewImage() const;
void saveOptimizedPoses(const std::map<int, Transform> & optimizedPoses, const Transform & lastlocalizationPose) const;
std::map<int, Transform> loadOptimizedPoses(Transform * lastlocalizationPose) const;
void save2DMap(const cv::Mat & map, float xMin, float yMin, float cellSize) const;
cv::Mat load2DMap(float & xMin, float & yMin, float & cellSize) const;
void saveOptimizedMesh(
const cv::Mat & cloud,
const std::map<int, Transform> & poses = std::map<int, Transform>(), // if we want to do localization afterward using optimized mesh
const std::vector<std::vector<std::vector<unsigned int> > > & polygons = std::vector<std::vector<std::vector<unsigned int> > >(), // Textures -> polygons -> vertices
#if PCL_VERSION_COMPARE(>=, 1, 8, 0)
const std::vector<std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > > & texCoords = std::vector<std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > >(), // Textures -> uv coords for each vertex of the polygons
@@ -111,7 +116,6 @@ public:
#endif
const cv::Mat & textures = cv::Mat()) const; // concatenated textures (assuming square textures with all same size);
cv::Mat loadOptimizedMesh(
std::map<int, Transform> * poses = 0,
std::vector<std::vector<std::vector<unsigned int> > > * polygons = 0,
#if PCL_VERSION_COMPARE(>=, 1, 8, 0)
std::vector<std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > > * texCoords = 0,
@@ -144,12 +148,14 @@ public:
int getTotalNodesSize() const;
int getTotalDictionarySize() const;
ParametersMap getLastParameters() const;
std::map<std::string, float> getStatistics(int nodeId, double & stamp) const;
std::map<std::string, float> getStatistics(int nodeId, double & stamp, std::vector<int> * wmState=0) const;
std::map<int, std::pair<std::map<std::string, float>, double> > getAllStatistics() const;
std::map<int, std::vector<int> > getAllStatisticsWmStates() const;
void executeNoResult(const std::string & sql) const;
// Load objects
void load(VWDictionary * dictionary) const;
void load(VWDictionary * dictionary, bool lastStateOnly = true) const;
void loadLastNodes(std::list<Signature *> & signatures) const;
void loadSignatures(const std::list<int> & ids, std::list<Signature *> & signatures, std::set<int> * loadedFromTrash = 0);
void loadWords(const std::set<int> & wordIds, std::list<VisualWord *> & vws);
@@ -158,7 +164,7 @@ public:
void loadNodeData(std::list<Signature *> & signatures, bool images = true, bool scan = true, bool userData = true, bool occupancyGrid = true) const;
void getNodeData(int signatureId, SensorData & data, bool images = true, bool scan = true, bool userData = true, bool occupancyGrid = true) const;
bool getCalibration(int signatureId, std::vector<CameraModel> & models, StereoCameraModel & stereoModel) const;
bool getLaserScanInfo(int signatureId, LaserScanInfo & info) const;
bool getLaserScanInfo(int signatureId, LaserScan & info) const;
bool getNodeInfo(int signatureId, Transform & pose, int & mapId, int & weight, std::string & label, double & stamp, Transform & groundTruthPose, std::vector<float> & velocity, GPS & gps) const;
void loadLinks(int signatureId, std::map<int, Link> & links, Link::Type type = Link::kUndef) const;
void getWeight(int signatureId, int & weight) const;
@@ -173,7 +179,6 @@ public:
protected:
DBDriver(const ParametersMap & parameters = ParametersMap());
private:
virtual bool connectDatabaseQuery(const std::string & url, bool overwritten = false) = 0;
virtual void disconnectDatabaseQuery(bool save = true, const std::string & outputUrl = "") = 0;
virtual bool isConnectedQuery() const = 0;
@@ -195,13 +200,15 @@ private:
virtual int getTotalNodesSizeQuery() const = 0;
virtual int getTotalDictionarySizeQuery() const = 0;
virtual ParametersMap getLastParametersQuery() const = 0;
virtual std::map<std::string, float> getStatisticsQuery(int nodeId, double & stamp) const = 0;
virtual std::map<std::string, float> getStatisticsQuery(int nodeId, double & stamp, std::vector<int> * wmState) const = 0;
virtual std::map<int, std::pair<std::map<std::string, float>, double> > getAllStatisticsQuery() const = 0;
virtual std::map<int, std::vector<int> > getAllStatisticsWmStatesQuery() const = 0;
virtual void executeNoResultQuery(const std::string & sql) const = 0;
virtual void getWeightQuery(int signatureId, int & weight) const = 0;
virtual void saveQuery(const std::list<Signature *> & signatures) const = 0;
virtual void saveQuery(const std::list<Signature *> & signatures) = 0;
virtual void saveQuery(const std::list<VisualWord *> & words) const = 0;
virtual void updateQuery(const std::list<Signature *> & signatures, bool updateTimestamp) const = 0;
virtual void updateQuery(const std::list<VisualWord *> & words, bool updateTimestamp) const = 0;
@@ -213,6 +220,7 @@ private:
int nodeId,
const cv::Mat & ground,
const cv::Mat & obstacles,
const cv::Mat & empty,
float cellSize,
const cv::Point3f & viewpoint) const = 0;
@@ -223,9 +231,12 @@ private:
virtual void addStatisticsQuery(const Statistics & statistics) const = 0;
virtual void savePreviewImageQuery(const cv::Mat & image) const = 0;
virtual cv::Mat loadPreviewImageQuery() const = 0;
virtual void saveOptimizedPosesQuery(const std::map<int, Transform> & optimizedPoses, const Transform & lastlocalizationPose) const = 0;
virtual std::map<int, Transform> loadOptimizedPosesQuery(Transform * lastlocalizationPose) const = 0;
virtual void save2DMapQuery(const cv::Mat & map, float xMin, float yMin, float cellSize) const = 0;
virtual cv::Mat load2DMapQuery(float & xMin, float & yMin, float & cellSize) const = 0;
virtual void saveOptimizedMeshQuery(
const cv::Mat & cloud,
const std::map<int, Transform> & poses,
const std::vector<std::vector<std::vector<unsigned int> > > & polygons,
#if PCL_VERSION_COMPARE(>=, 1, 8, 0)
const std::vector<std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > > & texCoords,
@@ -234,7 +245,6 @@ private:
#endif
const cv::Mat & textures) const = 0;
virtual cv::Mat loadOptimizedMeshQuery(
std::map<int, Transform> * poses,
std::vector<std::vector<std::vector<unsigned int> > > * polygons,
#if PCL_VERSION_COMPARE(>=, 1, 8, 0)
std::vector<std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > > * texCoords,
@@ -244,7 +254,7 @@ private:
cv::Mat * textures) const = 0;
// Load objects
virtual void loadQuery(VWDictionary * dictionary) const = 0;
virtual void loadQuery(VWDictionary * dictionary, bool lastStateOnly = true) const = 0;
virtual void loadLastNodesQuery(std::list<Signature *> & signatures) const = 0;
virtual void loadSignaturesQuery(const std::list<int> & ids, std::list<Signature *> & signatures) const = 0;
virtual void loadWordsQuery(const std::set<int> & wordIds, std::list<VisualWord *> & vws) const = 0;
@@ -252,7 +262,7 @@ private:
virtual void loadNodeDataQuery(std::list<Signature *> & signatures, bool images=true, bool scan=true, bool userData=true, bool occupancyGrid=true) const = 0;
virtual bool getCalibrationQuery(int signatureId, std::vector<CameraModel> & models, StereoCameraModel & stereoModel) const = 0;
virtual bool getLaserScanInfoQuery(int signatureId, LaserScanInfo & info) const = 0;
virtual bool getLaserScanInfoQuery(int signatureId, LaserScan & info) const = 0;
virtual bool getNodeInfoQuery(int signatureId, Transform & pose, int & mapId, int & weight, std::string & label, double & stamp, Transform & groundTruthPose, std::vector<float> & velocity, GPS & gps) 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;
@@ -263,7 +273,7 @@ private:
private:
//non-abstract methods
void saveOrUpdate(const std::vector<Signature *> & signatures) const;
void saveOrUpdate(const std::vector<Signature *> & signatures);
void saveOrUpdate(const std::vector<VisualWord *> & words) const;
//thread stuff
@@ -31,7 +31,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "rtabmap/core/RtabmapExp.h" // DLL export/import defines
#include "rtabmap/core/DBDriver.h"
#include <opencv2/features2d/features2d.hpp>
#include "sqlite3/sqlite3.h"
typedef struct sqlite3_stmt sqlite3_stmt;
typedef struct sqlite3 sqlite3;
namespace rtabmap {
@@ -41,13 +43,14 @@ public:
virtual ~DBDriverSqlite3();
virtual void parseParameters(const ParametersMap & parameters);
virtual bool isInMemory() const {return getUrl().empty() || _dbInMemory;}
void setDbInMemory(bool dbInMemory);
void setJournalMode(int journalMode);
void setCacheSize(unsigned int cacheSize);
void setSynchronous(int synchronous);
void setTempStore(int tempStore);
private:
protected:
virtual bool connectDatabaseQuery(const std::string & url, bool overwritten = false);
virtual void disconnectDatabaseQuery(bool save = true, const std::string & outputUrl = "");
virtual bool isConnectedQuery() const;
@@ -69,13 +72,15 @@ private:
virtual int getTotalNodesSizeQuery() const;
virtual int getTotalDictionarySizeQuery() const;
virtual ParametersMap getLastParametersQuery() const;
virtual std::map<std::string, float> getStatisticsQuery(int nodeId, double & stamp) const;
virtual std::map<std::string, float> getStatisticsQuery(int nodeId, double & stamp, std::vector<int> * wmState) const;
virtual std::map<int, std::pair<std::map<std::string, float>, double> > getAllStatisticsQuery() const;
virtual std::map<int, std::vector<int> > getAllStatisticsWmStatesQuery() const;
virtual void executeNoResultQuery(const std::string & sql) const;
virtual void getWeightQuery(int signatureId, int & weight) const;
virtual void saveQuery(const std::list<Signature *> & signatures) const;
virtual void saveQuery(const std::list<Signature *> & signatures);
virtual void saveQuery(const std::list<VisualWord *> & words) const;
virtual void updateQuery(const std::list<Signature *> & signatures, bool updateTimestamp) const;
virtual void updateQuery(const std::list<VisualWord *> & words, bool updateTimestamp) const;
@@ -87,6 +92,7 @@ private:
int nodeId,
const cv::Mat & ground,
const cv::Mat & obstacles,
const cv::Mat & empty,
float cellSize,
const cv::Point3f & viewpoint) const;
@@ -97,9 +103,12 @@ private:
virtual void addStatisticsQuery(const Statistics & statistics) const;
virtual void savePreviewImageQuery(const cv::Mat & image) const;
virtual cv::Mat loadPreviewImageQuery() const;
virtual void saveOptimizedPosesQuery(const std::map<int, Transform> & optimizedPoses, const Transform & lastlocalizationPose) const;
virtual std::map<int, Transform> loadOptimizedPosesQuery(Transform * lastlocalizationPose) const;
virtual void save2DMapQuery(const cv::Mat & map, float xMin, float yMin, float cellSize) const;
virtual cv::Mat load2DMapQuery(float & xMin, float & yMin, float & cellSize) const;
virtual void saveOptimizedMeshQuery(
const cv::Mat & cloud,
const std::map<int, Transform> & poses,
const std::vector<std::vector<std::vector<unsigned int> > > & polygons,
#if PCL_VERSION_COMPARE(>=, 1, 8, 0)
const std::vector<std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > > & texCoords,
@@ -108,7 +117,6 @@ private:
#endif
const cv::Mat & textures) const;
virtual cv::Mat loadOptimizedMeshQuery(
std::map<int, Transform> * poses,
std::vector<std::vector<std::vector<unsigned int> > > * polygons,
#if PCL_VERSION_COMPARE(>=, 1, 8, 0)
std::vector<std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > > * texCoords,
@@ -118,7 +126,7 @@ private:
cv::Mat * textures) const;
// Load objects
virtual void loadQuery(VWDictionary * dictionary) const;
virtual void loadQuery(VWDictionary * dictionary, bool lastStateOnly = true) const;
virtual void loadLastNodesQuery(std::list<Signature *> & signatures) const;
virtual void loadSignaturesQuery(const std::list<int> & ids, std::list<Signature *> & signatures) const;
virtual void loadWordsQuery(const std::set<int> & wordIds, std::list<VisualWord *> & vws) const;
@@ -126,7 +134,7 @@ private:
virtual void loadNodeDataQuery(std::list<Signature *> & signatures, bool images=true, bool scan=true, bool userData=true, bool occupancyGrid=true) const;
virtual bool getCalibrationQuery(int signatureId, std::vector<CameraModel> & models, StereoCameraModel & stereoModel) const;
virtual bool getLaserScanInfoQuery(int signatureId, LaserScanInfo & info) const;
virtual bool getLaserScanInfoQuery(int signatureId, LaserScan & info) const;
virtual bool getNodeInfoQuery(int signatureId, Transform & pose, int & mapId, int & weight, std::string & label, double & stamp, Transform & groundTruthPose, std::vector<float> & velocity, GPS & gps) const;
virtual void getAllNodeIdsQuery(std::set<int> & ids, bool ignoreChildren, bool ignoreBadSignatures) const;
virtual void getAllLinksQuery(std::multimap<int, Link> & links, bool ignoreNullLinks) const;
@@ -161,6 +169,7 @@ private:
int nodeId,
const cv::Mat & ground,
const cv::Mat & obstacles,
const cv::Mat & empty,
float cellSize,
const cv::Point3f & viewpoint) const;
@@ -168,9 +177,12 @@ private:
void loadLinksQuery(std::list<Signature *> & signatures) const;
int loadOrSaveDb(sqlite3 *pInMemory, const std::string & fileName, int isSave) const;
private:
protected:
sqlite3 * _ppDb;
std::string _version;
private:
long _memoryUsedEstimate;
bool _dbInMemory;
unsigned int _cacheSize;
int _journalMode;
@@ -177,6 +177,8 @@ private:
int _subPixWinSize;
int _subPixIterations;
double _subPixEps;
int gridRows_;
int gridCols_;
// Stereo stuff
Stereo * _stereo;
};
+10 -5
View File
@@ -49,21 +49,25 @@ public:
// Note that useDistanceL1 doesn't have any effect if LSH is used
void buildLinearIndex(
const cv::Mat & features,
bool useDistanceL1 = false);
bool useDistanceL1 = false,
float rebalancingFactor = 2.0f);
void buildKDTreeIndex(
const cv::Mat & features,
int trees = 4,
bool useDistanceL1 = false);
bool useDistanceL1 = false,
float rebalancingFactor = 2.0f);
void buildKDTreeSingleIndex(
const cv::Mat & features,
int leafMaxSize = 10,
bool reorder = true,
bool useDistanceL1 = false);
bool useDistanceL1 = false,
float rebalancingFactor = 2.0f);
void buildLSHIndex(
const cv::Mat & features,
unsigned int table_number = 12,
unsigned int key_size = 20,
unsigned int multi_probe_level = 2);
unsigned int multi_probe_level = 2,
float rebalancingFactor = 2.0f);
bool isBuilt();
@@ -74,7 +78,7 @@ public:
void removePoint(unsigned int index);
// return squared distances
// return squared distances (indices should be casted in size_t)
void knnSearch(
const cv::Mat & query,
cv::Mat & indices,
@@ -102,6 +106,7 @@ private:
int featuresDim_;
bool isLSH_;
bool useDistanceL1_; // true=EUCLEDIAN_L2 false=MANHATTAN_L1
float rebalancingFactor_;
// keep feature in memory until the tree is rebuilt
// (in case the word is deleted when removed from the VWDictionary)
+31
View File
@@ -78,6 +78,30 @@ void RTABMAP_EXP calcKittiSequenceErrors(
float & t_err,
float & r_err);
/**
* Compute root-mean-square error (RMSE) like the TUM RGBD
* dataset's evaluation tool (absolute trajectory error).
* See https://vision.in.tum.de/data/datasets/rgbd-dataset
* @param groundTruth, Ground Truth poses
* @param poses, Estimated poses
* @return Gt to Map transform
*/
Transform RTABMAP_EXP calcRMSE(
const std::map<int, Transform> &groundTruth,
const std::map<int, Transform> &poses,
float & translational_rmse,
float & translational_mean,
float & translational_median,
float & translational_std,
float & translational_min,
float & translational_max,
float & rotational_rmse,
float & rotational_mean,
float & rotational_median,
float & rotational_std,
float & rotational_min,
float & rotational_max);
std::multimap<int, Link>::iterator RTABMAP_EXP findLink(
std::multimap<int, Link> & links,
int from,
@@ -99,6 +123,8 @@ std::multimap<int, int>::const_iterator RTABMAP_EXP findLink(
int to,
bool checkBothWays = true);
std::multimap<int, Link> RTABMAP_EXP filterDuplicateLinks(
const std::multimap<int, Link> & links);
std::multimap<int, Link> RTABMAP_EXP filterLinks(
const std::multimap<int, Link> & links,
Link::Type filteredType);
@@ -203,6 +229,11 @@ int RTABMAP_EXP findNearestNode(
const std::map<int, rtabmap::Transform> & nodes,
const rtabmap::Transform & targetPose);
std::vector<int> RTABMAP_EXP findNearestNodes(
const std::map<int, rtabmap::Transform> & nodes,
const rtabmap::Transform & targetPose,
int k);
/**
* Get nodes near the query
* @param nodeId the query id
+104
View File
@@ -0,0 +1,104 @@
/*
* IMU.h
*
* Created on: 2018-03-05
* Author: mathieu
*/
#ifndef IMU_H_
#define IMU_H_
#include <opencv2/core/core.hpp>
#include <rtabmap/utilite/ULogger.h>
namespace rtabmap {
// Correspondence class to sensor_msgs/IMU
class IMU
{
public:
IMU() {}
IMU(const cv::Vec4d & orientation,
const cv::Mat & orientationCovariance,
const cv::Vec3d & angularVelocity,
const cv::Mat & angularVelocityCovariance,
const cv::Vec3d & linearAcceleration,
const cv::Mat & linearAccelerationCovariance,
const Transform & localTransform = Transform::getIdentity()) :
orientation_(orientation),
orientationCovariance_(orientationCovariance),
angularVelocity_(angularVelocity),
angularVelocityCovariance_(angularVelocityCovariance),
linearAcceleration_(linearAcceleration),
linearAccelerationCovariance_(linearAccelerationCovariance),
localTransform_(localTransform)
{
}
IMU(const cv::Vec3d & angularVelocity,
const cv::Mat & angularVelocityCovariance,
const cv::Vec3d & linearAcceleration,
const cv::Mat & linearAccelerationCovariance,
const Transform & localTransform = Transform::getIdentity()) :
angularVelocity_(angularVelocity),
angularVelocityCovariance_(angularVelocityCovariance),
linearAcceleration_(linearAcceleration),
linearAccelerationCovariance_(linearAccelerationCovariance),
localTransform_(localTransform)
{
}
const cv::Vec4d & orientation() const {return orientation_;}
const cv::Mat & orientationCovariance() const {return orientationCovariance_;} // 3x3 double Row major about x, y, z axes, empty if orientation is not set
const cv::Vec3d & angularVelocity() const {return angularVelocity_;}
const cv::Mat & angularVelocityCovariance() const {return angularVelocityCovariance_;} // 3x3 double Row major about x, y, z axes, empty if angularVelocity is not set
const cv::Vec3d linearAcceleration() const {return linearAcceleration_;}
const cv::Mat & linearAccelerationCovariance() const {return linearAccelerationCovariance_;} // 3x3 double Row major x, y z, empty if linearAcceleration is not set
const Transform & localTransform() const {return localTransform_;}
bool empty() const
{
return localTransform_.isNull();
}
private:
cv::Vec4d orientation_;
cv::Mat orientationCovariance_; // 3x3 double Row major about x, y, z axes, empty if orientation is not set
cv::Vec3d angularVelocity_;
cv::Mat angularVelocityCovariance_; // 3x3 double Row major about x, y, z axes, empty if angularVelocity is not set
cv::Vec3d linearAcceleration_;
cv::Mat linearAccelerationCovariance_; // 3x3 double Row major x, y z, empty if linearAcceleration is not set
Transform localTransform_;
};
class IMUEvent : public UEvent
{
public:
IMUEvent() :
stamp_(0.0)
{}
IMUEvent(const IMU & data, double stamp) :
data_(data),
stamp_(stamp)
{
}
virtual std::string getClassName() const {return "IMUEvent";}
const IMU & getData() const {return data_;}
double getStamp() const {return stamp_;}
private:
IMU data_;
double stamp_;
};
}
#endif /* IMU_H_ */
@@ -1,65 +1,70 @@
/*
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 CORELIB_INCLUDE_RTABMAP_CORE_LASERSCANINFO_H_
#define CORELIB_INCLUDE_RTABMAP_CORE_LASERSCANINFO_H_
#include <rtabmap/utilite/ULogger.h>
namespace rtabmap {
class LaserScanInfo
{
public:
LaserScanInfo() :
maxPoints_(0),
maxRange_(0),
localTransform_(Transform::getIdentity())
{
}
LaserScanInfo(int maxPoints, float maxRange, const Transform & localTransform = Transform::getIdentity()) :
maxPoints_(maxPoints),
maxRange_(maxRange),
localTransform_(localTransform)
{
UASSERT(!localTransform.isNull());
}
int maxPoints() const {return maxPoints_;}
float maxRange() const {return maxRange_;}
Transform localTransform() const {return localTransform_;}
private:
int maxPoints_;
float maxRange_;
Transform localTransform_;
};
}
#endif /* CORELIB_INCLUDE_RTABMAP_CORE_LASERSCANINFO_H_ */
/*
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.
*/
#pragma once
#include "rtabmap/core/RtabmapExp.h" // DLL export/import defines
#include <rtabmap/core/Transform.h>
#include <rtabmap/utilite/UThread.h>
#include <rtabmap/utilite/UEventsSender.h>
#include <rtabmap/utilite/UTimer.h>
#include <fstream>
namespace rtabmap
{
/**
* Class IMUThread
*
*/
class RTABMAP_EXP IMUThread :
public UThread,
public UEventsSender
{
public:
IMUThread(int rate, const Transform & localTransform);
virtual ~IMUThread();
bool init(const std::string & path);
void setRate(int rate);
private:
virtual void mainLoopBegin();
virtual void mainLoop();
private:
int rate_;
Transform localTransform_;
std::ifstream imuFile_;
UTimer frameRateTimer_;
double captureDelay_;
double previousStamp_;
};
} // namespace rtabmap
+95
View File
@@ -0,0 +1,95 @@
/*
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 CORELIB_INCLUDE_RTABMAP_CORE_LASERSCAN_H_
#define CORELIB_INCLUDE_RTABMAP_CORE_LASERSCAN_H_
#include "rtabmap/core/RtabmapExp.h" // DLL export/import defines
#include <rtabmap/core/Transform.h>
namespace rtabmap {
class RTABMAP_EXP LaserScan
{
public:
enum Format{kUnknown=0,
kXY=1,
kXYI=2,
kXYNormal=3,
kXYINormal=4,
kXYZ=5,
kXYZI=6,
kXYZRGB=7,
kXYZNormal=8,
kXYZINormal=9,
kXYZRGBNormal=10};
static int channels(Format format);
static bool isScan2d(const Format & format);
static bool isScanHasNormals(const Format & format);
static bool isScanHasRGB(const Format & format);
static bool isScanHasIntensity(const Format & format);
static LaserScan backwardCompatibility(const cv::Mat & oldScanFormat, int maxPoints = 0, int maxRange = 0, const Transform & localTransform = Transform::getIdentity());
public:
LaserScan();
LaserScan(const cv::Mat & data, int maxPoints, float maxRange, Format format, const Transform & localTransform = Transform::getIdentity());
const cv::Mat & data() const {return data_;}
int maxPoints() const {return maxPoints_;}
float maxRange() const {return maxRange_;}
Format format() const {return format_;}
Transform localTransform() const {return localTransform_;}
bool isEmpty() const {return data_.empty();}
int size() const {return data_.cols;}
int dataType() const {return data_.type();}
bool is2d() const {return isScan2d(format_);}
bool hasNormals() const {return isScanHasNormals(format_);}
bool hasRGB() const {return isScanHasRGB(format_);}
bool hasIntensity() const {return isScanHasIntensity(format_);}
bool isCompressed() const {return !data_.empty() && data_.type()==CV_8UC1;}
LaserScan clone() const {return LaserScan(data_.clone(), maxPoints_, maxRange_, format_, localTransform_.clone());}
int getIntensityOffset() const {return hasIntensity()?(is2d()?2:3):-1;}
int getRGBOffset() const {return hasRGB()?(is2d()?2:3):-1;}
int getNormalsOffset() const {return hasNormals()?(2 + (is2d()?0:1) + ((hasRGB() || hasIntensity())?1:0)):-1;}
void clear() {data_ = cv::Mat();}
private:
cv::Mat data_;
int maxPoints_;
float maxRange_;
Format format_;
Transform localTransform_;
};
}
#endif /* CORELIB_INCLUDE_RTABMAP_CORE_LASERSCAN_H_ */
+18 -5
View File
@@ -95,9 +95,12 @@ public:
void saveStatistics(const Statistics & statistics);
void savePreviewImage(const cv::Mat & image) const;
cv::Mat loadPreviewImage() const;
void saveOptimizedPoses(const std::map<int, Transform> & optimizedPoses, const Transform & lastlocalizationPose) const;
std::map<int, Transform> loadOptimizedPoses(Transform * lastlocalizationPose) const;
void save2DMap(const cv::Mat & map, float xMin, float yMin, float cellSize) const;
cv::Mat load2DMap(float & xMin, float & yMin, float & cellSize) const;
void saveOptimizedMesh(
const cv::Mat & cloud,
const std::map<int, Transform> & poses = std::map<int, Transform>(), // if we want to do localization afterward using optimized mesh
const std::vector<std::vector<std::vector<unsigned int> > > & polygons = std::vector<std::vector<std::vector<unsigned int> > >(), // Textures -> polygons -> vertices
#if PCL_VERSION_COMPARE(>=, 1, 8, 0)
const std::vector<std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > > & texCoords = std::vector<std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > >(), // Textures -> uv coords for each vertex of the polygons
@@ -106,7 +109,6 @@ public:
#endif
const cv::Mat & textures = cv::Mat()) const; // concatenated textures (assuming square textures with all same size)
cv::Mat loadOptimizedMesh(
std::map<int, Transform> * poses = 0,
std::vector<std::vector<std::vector<unsigned int> > > * polygons = 0,
#if PCL_VERSION_COMPARE(>=, 1, 8, 0)
std::vector<std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > > * texCoords = 0,
@@ -127,6 +129,8 @@ public:
bool incrementMarginOnLoop = false,
bool ignoreLoopIds = false,
bool ignoreIntermediateNodes = false,
bool ignoreLocalSpaceLoopIds = false,
const std::set<int> & nodesSet = std::set<int>(),
double * dbAccessTime = 0) const;
std::map<int, float> getNeighborsIdRadius(
int signatureId,
@@ -134,6 +138,7 @@ public:
const std::map<int, Transform> & optimizedPoses,
int maxGraphDepth) const;
void deleteLocation(int locationId, std::list<int> * deletedWords = 0);
void saveLocationData(int locationId);
void removeLink(int idA, int idB);
void removeRawData(int id, bool image = true, bool scan = true, bool userData = true);
@@ -166,6 +171,7 @@ public:
bool setUserData(int id, const cv::Mat & data);
int getDatabaseMemoryUsed() const; // in bytes
std::string getDatabaseVersion() const;
std::string getDatabaseUrl() const;
double getDbSavingTime() const;
Transform getOdomPose(int signatureId, bool lookInDatabase = false) const;
Transform getGroundTruthPose(int signatureId, bool lookInDatabase = false) const;
@@ -220,7 +226,6 @@ public:
Transform computeTransform(Signature & fromS, Signature & toS, Transform guess, RegistrationInfo * info = 0, bool useKnownCorrespondencesIfPossible = false) const;
Transform computeTransform(int fromId, int toId, Transform guess, RegistrationInfo * info = 0, bool useKnownCorrespondencesIfPossible = false);
Transform computeIcpTransform(int fromId, int toId, Transform guess, RegistrationInfo * info = 0);
Transform computeIcpTransformMulti(
int newId,
int oldId,
@@ -279,20 +284,26 @@ private:
bool _generateIds;
bool _badSignaturesIgnored;
bool _mapLabelsAdded;
bool _depthAsMask;
int _imagePreDecimation;
int _imagePostDecimation;
bool _compressionParallelized;
float _laserScanDownsampleStepSize;
float _laserScanVoxelSize;
int _laserScanNormalK;
int _laserScanNormalRadius;
float _laserScanNormalRadius;
bool _reextractLoopClosureFeatures;
bool _localBundleOnLoopClosure;
float _rehearsalMaxDistance;
float _rehearsalMaxAngle;
bool _rehearsalWeightIgnoredWhileMoving;
bool _useOdometryFeatures;
bool _createOccupancyGrid;
int _visMaxFeatures;
int _visCorType;
bool _imagesAlreadyRectified;
bool _rectifyOnlyFeatures;
bool _covOffDiagonalIgnored;
int _idCount;
int _idMapCount;
@@ -302,6 +313,8 @@ private:
bool _linksChanged; // False by default, become true when links are modified.
int _signaturesAdded;
GPS _gpsOrigin;
std::vector<CameraModel> _rectCameraModels;
StereoCameraModel _rectStereoCameraModel;
std::map<int, Signature *> _signatures; // TODO : check if a signature is already added? although it is not supposed to occur...
std::set<int> _stMem; // id
@@ -315,7 +328,7 @@ private:
bool _parallelized;
Registration * _registrationPipeline;
RegistrationIcp * _registrationIcp;
RegistrationIcp * _registrationIcpMulti;
OccupancyGrid * _occupancy;
};
+49 -9
View File
@@ -39,17 +39,32 @@ namespace rtabmap {
class RTABMAP_EXP OccupancyGrid
{
public:
inline static float logodds(double probability)
{
return (float) log(probability/(1-probability));
}
inline static double probability(double logodds)
{
return 1. - ( 1. / (1. + exp(logodds)));
}
public:
OccupancyGrid(const ParametersMap & parameters = ParametersMap());
void parseParameters(const ParametersMap & parameters);
void setMap(const cv::Mat & map, float xMin, float yMin, float cellSize, const std::map<int, Transform> & poses);
void setCellSize(float cellSize);
float getCellSize() const {return cellSize_;}
void setCloudAssembling(bool enabled);
float getMinMapSize() const {return minMapSize_;}
bool isGridFromDepth() const {return occupancyFromCloud_;}
bool isGridFromDepth() const {return occupancyFromDepth_;}
bool isFullUpdate() const {return fullUpdate_;}
float getUpdateError() const {return updateError_;}
bool isMapFrameProjection() const {return projMapFrame_;}
const std::map<int, Transform> & addedNodes() const {return addedNodes_;}
int cacheSize() const {return (int)cache_.size();}
const std::map<int, std::pair<std::pair<cv::Mat, cv::Mat>, cv::Mat> > & getCache() const {return cache_;}
template<typename PointT>
typename pcl::PointCloud<PointT>::Ptr segmentCloud(
@@ -63,17 +78,31 @@ public:
void createLocalMap(
const Signature & node,
cv::Mat & ground,
cv::Mat & obstacles,
cv::Mat & groundCells,
cv::Mat & obstacleCells,
cv::Mat & emptyCells,
cv::Point3f & viewPoint) const;
void createLocalMap(
const LaserScan & cloud,
const Transform & pose,
cv::Mat & groundCells,
cv::Mat & obstacleCells,
cv::Mat & emptyCells,
cv::Point3f & viewPointInOut) const;
void clear();
void addToCache(
int nodeId,
const cv::Mat & ground,
const cv::Mat & obstacles);
const cv::Mat & obstacles,
const cv::Mat & empty);
void update(const std::map<int, Transform> & poses);
const cv::Mat getMap(float & xMin, float & yMin) const;
cv::Mat getMap(float & xMin, float & yMin) const;
cv::Mat getProbMap(float & xMin, float & yMin) const;
const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & getMapGround() const {return assembledGround_;}
const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & getMapObstacles() const {return assembledObstacles_;}
const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & getMapEmptyCells() const {return assembledEmptyCells_;}
private:
ParametersMap parameters_;
@@ -86,7 +115,8 @@ private:
float footprintHeight_;
int scanDecimation_;
float cellSize_;
bool occupancyFromCloud_;
bool preVoxelFiltering_;
bool occupancyFromDepth_;
bool projMapFrame_;
float maxObstacleHeight_;
int normalKSearch_;
@@ -102,20 +132,30 @@ private:
float noiseFilteringRadius_;
int noiseFilteringMinNeighbors_;
bool scan2dUnknownSpaceFilled_;
double scan2dMaxUnknownSpaceFilledRange_;
bool projRayTracing_;
bool rayTracing_;
bool fullUpdate_;
float minMapSize_;
bool erode_;
float footprintRadius_;
float updateError_;
float occupancyThr_;
float probHit_;
float probMiss_;
float probClampingMin_;
float probClampingMax_;
std::map<int, std::pair<cv::Mat, cv::Mat> > cache_;
std::map<int, std::pair<std::pair<cv::Mat, cv::Mat>, cv::Mat> > cache_; //<node id, < <ground, obstacles>, empty> >
cv::Mat map_;
cv::Mat mapInfo_;
std::map<int, std::pair<int, int> > cellCount_; //<node Id, cells>
float xMin_;
float yMin_;
std::map<int, Transform> addedNodes_;
bool cloudAssembling_;
pcl::PointCloud<pcl::PointXYZRGB>::Ptr assembledGround_;
pcl::PointCloud<pcl::PointXYZRGB>::Ptr assembledObstacles_;
pcl::PointCloud<pcl::PointXYZRGB>::Ptr assembledEmptyCells_;
};
}
+148 -16
View File
@@ -37,45 +37,163 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <pcl/point_types.h>
#include <rtabmap/core/Transform.h>
#include <rtabmap/core/Parameters.h>
#include <map>
#include <string>
namespace rtabmap {
class OcTreeNodeInfo
// forward declaraton for "friend"
class RtabmapColorOcTree;
class RtabmapColorOcTreeNode : public octomap::ColorOcTreeNode
{
public:
OcTreeNodeInfo(int nodeRefId, const octomap::OcTreeKey & key, bool isObstacle) :
nodeRefId_(nodeRefId),
key_(key),
isObstacle_(isObstacle) {}
enum OccupancyType {kTypeUnknown=-1, kTypeEmpty=0, kTypeGround=1, kTypeObstacle=100};
public:
friend class RtabmapColorOcTree; // needs access to node children (inherited)
RtabmapColorOcTreeNode() : ColorOcTreeNode(), nodeRefId_(0), type_(kTypeUnknown) {}
RtabmapColorOcTreeNode(const RtabmapColorOcTreeNode& rhs) : ColorOcTreeNode(rhs), nodeRefId_(rhs.nodeRefId_), type_(rhs.type_) {}
void setNodeRefId(int nodeRefId) {nodeRefId_ = nodeRefId;}
void setOccupancyType(char type) {type_=type;}
void setPointRef(const octomap::point3d & point) {pointRef_ = point;}
int getNodeRefId() const {return nodeRefId_;}
int getOccupancyType() const {return type_;}
const octomap::point3d & getPointRef() const {return pointRef_;}
// following methods defined for octomap < 1.8 compatibility
RtabmapColorOcTreeNode* getChild(unsigned int i);
const RtabmapColorOcTreeNode* getChild(unsigned int i) const;
bool pruneNode();
void expandNode();
bool createChild(unsigned int i);
private:
int nodeRefId_;
octomap::OcTreeKey key_;
bool isObstacle_;
int type_; // -1=undefined, 0=empty, 100=obstacle, 1=ground
octomap::point3d pointRef_;
};
// Same as official ColorOctree but using RtabmapColorOcTreeNode, which is inheriting ColorOcTreeNode
class RtabmapColorOcTree : public octomap::OccupancyOcTreeBase <RtabmapColorOcTreeNode> {
public:
/// Default constructor, sets resolution of leafs
RtabmapColorOcTree(double resolution);
/// virtual constructor: creates a new object of same type
/// (Covariant return type requires an up-to-date compiler)
RtabmapColorOcTree* create() const {return new RtabmapColorOcTree(resolution); }
std::string getTreeType() const {return "ColorOcTree";} // same type as ColorOcTree to be compatible with ROS OctoMap msg
/**
* Prunes a node when it is collapsible. This overloaded
* version only considers the node occupancy for pruning,
* different colors of child nodes are ignored.
* @return true if pruning was successful
*/
virtual bool pruneNode(RtabmapColorOcTreeNode* node);
virtual bool isNodeCollapsible(const RtabmapColorOcTreeNode* node) const;
// set node color at given key or coordinate. Replaces previous color.
RtabmapColorOcTreeNode* setNodeColor(const octomap::OcTreeKey& key, uint8_t r,
uint8_t g, uint8_t b);
RtabmapColorOcTreeNode* setNodeColor(float x, float y,
float z, uint8_t r,
uint8_t g, uint8_t b) {
octomap::OcTreeKey key;
if (!this->coordToKeyChecked(octomap::point3d(x,y,z), key)) return NULL;
return setNodeColor(key,r,g,b);
}
// integrate color measurement at given key or coordinate. Average with previous color
RtabmapColorOcTreeNode* averageNodeColor(const octomap::OcTreeKey& key, uint8_t r,
uint8_t g, uint8_t b);
RtabmapColorOcTreeNode* averageNodeColor(float x, float y,
float z, uint8_t r,
uint8_t g, uint8_t b) {
octomap:: OcTreeKey key;
if (!this->coordToKeyChecked(octomap::point3d(x,y,z), key)) return NULL;
return averageNodeColor(key,r,g,b);
}
// integrate color measurement at given key or coordinate. Average with previous color
RtabmapColorOcTreeNode* integrateNodeColor(const octomap::OcTreeKey& key, uint8_t r,
uint8_t g, uint8_t b);
RtabmapColorOcTreeNode* integrateNodeColor(float x, float y,
float z, uint8_t r,
uint8_t g, uint8_t b) {
octomap::OcTreeKey key;
if (!this->coordToKeyChecked(octomap::point3d(x,y,z), key)) return NULL;
return integrateNodeColor(key,r,g,b);
}
// update inner nodes, sets color to average child color
void updateInnerOccupancy();
protected:
void updateInnerOccupancyRecurs(RtabmapColorOcTreeNode* node, unsigned int depth);
/**
* Static member object which ensures that this OcTree's prototype
* ends up in the classIDMapping only once. You need this as a
* static member in any derived octree class in order to read .ot
* files through the AbstractOcTree factory. You should also call
* ensureLinking() once from the constructor.
*/
class StaticMemberInitializer{
public:
StaticMemberInitializer();
/**
* Dummy function to ensure that MSVC does not drop the
* StaticMemberInitializer, causing this tree failing to register.
* Needs to be called from the constructor of this octree.
*/
void ensureLinking() {};
};
/// static member to ensure static initialization (only once)
static StaticMemberInitializer RtabmapColorOcTreeMemberInit;
};
class RTABMAP_EXP OctoMap {
public:
OctoMap(float voxelSize = 0.1f, float occupancyThr = 0.5f, bool fullUpdate = false);
static void HSVtoRGB(float *r, float *g, float *b, float h, float s, float v);
public:
OctoMap(const ParametersMap & parameters);
OctoMap(float cellSize = 0.1f, float occupancyThr = 0.5f, bool fullUpdate = false, float updateError=0.01f);
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,
const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & ground,
const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & obstacles,
const pcl::PointXYZ & viewPoint);
void addToCache(int nodeId,
const cv::Mat & ground,
const cv::Mat & obstacles,
const cv::Mat & empty,
const cv::Point3f & viewPoint);
void update(const std::map<int, Transform> & poses);
const octomap::ColorOcTree * octree() const {return octree_;}
const RtabmapColorOcTree * 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;
std::vector<int> * emptyIndices = 0,
std::vector<int> * groundIndices = 0,
bool originalRefPoints = true) const;
cv::Mat createProjectionMap(
float & xMin,
@@ -89,16 +207,30 @@ public:
virtual ~OctoMap();
void clear();
void getGridMin(double & x, double & y, double & z) const {x=minValues_[0];y=minValues_[1];z=minValues_[2];}
void getGridMax(double & x, double & y, double & z) const {x=maxValues_[0];y=maxValues_[1];z=maxValues_[2];}
void setMaxRange(float value) {rangeMax_ = value;}
void setRayTracing(bool enabled) {rayTracing_ = enabled;}
bool hasColor() const {return hasColor_;}
private:
std::map<int, std::pair<cv::Mat, cv::Mat> > cache_;
std::map<int, std::pair<pcl::PointCloud<pcl::PointXYZRGB>::Ptr, pcl::PointCloud<pcl::PointXYZRGB>::Ptr> > cacheClouds_;
void updateMinMax(const octomap::point3d & point);
private:
std::map<int, std::pair<std::pair<cv::Mat, cv::Mat>, cv::Mat> > cache_; // [id: < <ground, obstacles>, empty>]
std::map<int, std::pair<const pcl::PointCloud<pcl::PointXYZRGB>::Ptr, const pcl::PointCloud<pcl::PointXYZRGB>::Ptr> > cacheClouds_; // [id: <ground, obstacles>]
std::map<int, cv::Point3f> cacheViewPoints_;
octomap::ColorOcTree * octree_;
std::map<octomap::ColorOcTreeNode*, OcTreeNodeInfo> occupiedCells_;
RtabmapColorOcTree * octree_;
std::map<int, Transform> addedNodes_;
octomap::KeyRay keyRay_;
bool hasColor_;
bool fullUpdate_;
float updateError_;
float rangeMax_;
bool rayTracing_;
double minValues_[3];
double maxValues_[3];
};
} /* namespace rtabmap */
+8 -1
View File
@@ -49,7 +49,10 @@ public:
kTypeFovis = 2,
kTypeViso2 = 3,
kTypeDVO = 4,
kTypeORBSLAM2 = 5
kTypeORBSLAM2 = 5,
kTypeOkvis = 6,
kTypeLOAM = 7,
kTypeMSCKF = 8
};
public:
@@ -62,6 +65,7 @@ public:
Transform process(SensorData & data, const Transform & guess, OdometryInfo * info = 0);
virtual void reset(const Transform & initialPose = Transform::getIdentity());
virtual Odometry::Type getType() = 0;
virtual bool canProcessRawImages() const {return false;}
//getters
const Transform & getPose() const {return _pose;}
@@ -69,6 +73,7 @@ public:
const Transform & previousVelocityTransform() const {return previousVelocityTransform_;}
double previousStamp() const {return previousStamp_;}
unsigned int framesProcessed() const {return framesProcessed_;}
bool imagesAlreadyRectified() const {return _imagesAlreadyRectified;}
private:
virtual Transform computeTransform(SensorData & data, const Transform & guess = Transform(), OdometryInfo * info = 0) = 0;
@@ -93,6 +98,8 @@ private:
float _kalmanMeasurementNoise;
int _imageDecimation;
bool _alignWithGround;
bool _publishRAMUsage;
bool _imagesAlreadyRectified;
Transform _pose;
int _resetCurrentCount;
double previousStamp_;
@@ -59,6 +59,7 @@ private:
Registration * registrationPipeline_;
Signature refFrame_;
Transform lastKeyFramePose_;
ParametersMap parameters_;
};
}
@@ -71,6 +71,7 @@ private:
Registration * regPipeline_;
Signature * map_;
Signature * lastFrame_;
int lastFrameOldestNewId_;
std::vector<std::pair<pcl::PointCloud<pcl::PointNormal>::Ptr, pcl::IndicesPtr> > scansBuffer_;
std::map<int, std::map<int, cv::Point3f> > bundleWordReferences_; //<WordId, <FrameId, pt2D+depth>>
@@ -80,6 +81,7 @@ private:
std::map<int, int> bundlePoseReferences_;
int bundleSeq_;
Optimizer * sba_;
ParametersMap parameters_;
};
}
+10 -1
View File
@@ -31,6 +31,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <map>
#include "rtabmap/core/Transform.h"
#include "rtabmap/core/RegistrationInfo.h"
#include "rtabmap/core/CameraModel.h"
#include "rtabmap/core/LaserScan.h"
#include <opencv2/features2d/features2d.hpp>
namespace rtabmap {
@@ -53,6 +55,7 @@ public:
stamp(0),
interval(0),
distanceTravelled(0.0f),
memoryUsage(0),
type(0)
{}
@@ -68,6 +71,8 @@ public:
output.localBundleOutliers = localBundleOutliers;
output.localBundleConstraints = localBundleConstraints;
output.localBundleTime = localBundleTime;
output.localBundlePoses = localBundlePoses;
output.localBundleModels = localBundleModels;
output.keyFrameAdded = keyFrameAdded;
output.timeEstimation = timeEstimation;
output.timeParticleFiltering = timeParticleFiltering;
@@ -77,6 +82,7 @@ public:
output.transformFiltered = transformFiltered;
output.transformGroundTruth = transformGroundTruth;
output.distanceTravelled = distanceTravelled;
output.memoryUsage = memoryUsage;
output.type = type;
return output;
}
@@ -90,6 +96,8 @@ public:
int localBundleOutliers;
int localBundleConstraints;
float localBundleTime;
std::map<int, Transform> localBundlePoses;
std::map<int, CameraModel> localBundleModels;
bool keyFrameAdded;
float timeEstimation;
float timeParticleFiltering;
@@ -99,13 +107,14 @@ public:
Transform transformFiltered;
Transform transformGroundTruth;
float distanceTravelled;
int memoryUsage; //MB
int type;
// F2M
std::multimap<int, cv::KeyPoint> words;
std::map<int, cv::Point3f> localMap;
cv::Mat localScanMap;
LaserScan localScanMap;
// F2F
std::vector<cv::Point2f> refCorners;
@@ -0,0 +1,75 @@
/*
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 ODOMETRYLOAM_H_
#define ODOMETRYLOAM_H_
#include <rtabmap/core/Odometry.h>
#ifdef RTABMAP_LOAM
#include <loam_velodyne/BasicScanRegistration.h>
#include <loam_velodyne/BasicLaserOdometry.h>
#include <loam_velodyne/BasicLaserMapping.h>
#include <loam_velodyne/BasicTransformMaintenance.h>
#include <loam_velodyne/MultiScanRegistration.h>
#endif
namespace rtabmap {
class RTABMAP_EXP OdometryLOAM : public Odometry
{
public:
OdometryLOAM(const rtabmap::ParametersMap & parameters = rtabmap::ParametersMap());
virtual ~OdometryLOAM();
virtual void reset(const Transform & initialPose = Transform::getIdentity());
virtual Odometry::Type getType() {return Odometry::kTypeLOAM;}
private:
virtual Transform computeTransform(SensorData & image, const Transform & guess = Transform(), OdometryInfo * info = 0);
private:
#ifdef RTABMAP_LOAM
std::vector<pcl::PointCloud<pcl::PointXYZI> > segmentScanRings(const pcl::PointCloud<pcl::PointXYZ> & laserCloudIn);
loam::BasicScanRegistration scanRegistration_;
loam::MultiScanMapper scanMapper_;
loam::BasicLaserOdometry * laserOdometry_;
loam::BasicLaserMapping * laserMapping_;
loam::BasicTransformMaintenance transformMaintenance_;
Transform lastPose_;
float scanPeriod_;
float linVar_;
float angVar_;
bool localMapping_;
bool lost_;
#endif
};
}
#endif /* ODOMETRYLOAM_H_ */
@@ -0,0 +1,65 @@
/*
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 ODOMETRYMSCKF_H_
#define ODOMETRYMSCKF_H_
#include <rtabmap/core/Odometry.h>
namespace rtabmap {
class ImageProcessorNoROS;
class MsckfVioNoROS;
class RTABMAP_EXP OdometryMSCKF : public Odometry
{
public:
OdometryMSCKF(const rtabmap::ParametersMap & parameters = rtabmap::ParametersMap());
virtual ~OdometryMSCKF();
virtual void reset(const Transform & initialPose = Transform::getIdentity());
virtual Odometry::Type getType() {return Odometry::kTypeMSCKF;}
virtual bool canProcessRawImages() const {return true;}
private:
virtual Transform computeTransform(SensorData & image, const Transform & guess = Transform(), OdometryInfo * info = 0);
private:
#ifdef RTABMAP_MSCKF_VIO
ImageProcessorNoROS * imageProcessor_;
MsckfVioNoROS * msckf_;
IMU lastImu_;
ParametersMap parameters_;
Transform flipXY_;
Transform previousPose_;
bool initGravity_;
#endif
};
}
#endif /* ODOMETRYMSCKF_H_ */
@@ -54,8 +54,9 @@ private:
#ifdef RTABMAP_ORB_SLAM2
ORBSLAM2System * orbslam2_;
bool firstFrame_;
#endif
Transform originLocalTransform_;
Transform previousPose_;
#endif
};
@@ -0,0 +1,68 @@
/*
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 ODOMETRYOKVIS_H_
#define ODOMETRYOKVIS_H_
#include <rtabmap/core/Odometry.h>
namespace okvis {
class ThreadedKFVio;
}
namespace rtabmap {
class OkvisCallbackHandler;
class RTABMAP_EXP OdometryOkvis : public Odometry
{
public:
OdometryOkvis(const rtabmap::ParametersMap & parameters = rtabmap::ParametersMap());
virtual ~OdometryOkvis();
virtual void reset(const Transform & initialPose = Transform::getIdentity());
virtual Odometry::Type getType() {return Odometry::kTypeOkvis;}
virtual bool canProcessRawImages() const {return true;}
private:
virtual Transform computeTransform(SensorData & image, const Transform & guess = Transform(), OdometryInfo * info = 0);
private:
std::string configFilename_;
#ifdef RTABMAP_OKVIS
OkvisCallbackHandler * okvisCallbackHandler_;
okvis::ThreadedKFVio * okvisEstimator_;
int imagesProcessed_;
bool initGravity_;
#endif
ParametersMap okvisParameters_;
IMU lastImu_; // only used for initialization
Transform previousPose_;
};
}
#endif /* ODOMETRYOKVIS_H_ */
@@ -62,10 +62,13 @@ private:
USemaphore _dataAdded;
UMutex _dataMutex;
std::list<SensorData> _dataBuffer;
std::list<SensorData> _imuBuffer;
Odometry * _odometry;
unsigned int _dataBufferMaxSize;
bool _resetOdometry;
Transform _resetPose;
double _lastImuStamp;
double _imuEstimatedDelay;
};
} // namespace rtabmap
+19 -2
View File
@@ -87,14 +87,31 @@ public:
virtual void parseParameters(const ParametersMap & parameters);
// inherited classes should implement one of these methods
virtual std::map<int, Transform> optimize(
std::map<int, Transform> optimizeIncremental(
int rootId,
const std::map<int, Transform> & poses,
const std::multimap<int, Link> & constraints,
std::list<std::map<int, Transform> > * intermediateGraphes = 0,
double * finalError = 0,
int * iterationsDone = 0);
std::map<int, Transform> optimize(
int rootId,
const std::map<int, Transform> & poses,
const std::multimap<int, Link> & constraints,
std::list<std::map<int, Transform> > * intermediateGraphes = 0,
double * finalError = 0,
int * iterationsDone = 0);
// inherited classes should implement one of these methods
virtual std::map<int, Transform> optimize(
int rootId,
const std::map<int, Transform> & poses,
const std::multimap<int, Link> & constraints,
cv::Mat & outputCovariance,
std::list<std::map<int, Transform> > * intermediateGraphes = 0,
double * finalError = 0,
int * iterationsDone = 0);
virtual std::map<int, Transform> optimizeBA(
int rootId, // if negative, all other poses are fixed
const std::map<int, Transform> & poses,
+7 -6
View File
@@ -64,12 +64,13 @@ public:
virtual void parseParameters(const ParametersMap & parameters);
virtual std::map<int, Transform> optimize(
int rootId,
const std::map<int, Transform> & poses,
const std::multimap<int, Link> & edgeConstraints,
std::list<std::map<int, Transform> > * intermediateGraphes = 0,
double * finalError = 0,
int * iterationsDone = 0);
int rootId,
const std::map<int, Transform> & poses,
const std::multimap<int, Link> & edgeConstraints,
cv::Mat & outputCovariance,
std::list<std::map<int, Transform> > * intermediateGraphes = 0,
double * finalError = 0,
int * iterationsDone = 0);
virtual std::map<int, Transform> optimizeBA(
int rootId,
@@ -56,6 +56,7 @@ public:
int rootId,
const std::map<int, Transform> & poses,
const std::multimap<int, Link> & edgeConstraints,
cv::Mat & outputCovariance,
std::list<std::map<int, Transform> > * intermediateGraphes = 0,
double * finalError = 0,
int * iterationsDone = 0);
@@ -66,6 +66,7 @@ public:
int rootId,
const std::map<int, Transform> & poses,
const std::multimap<int, Link> & edgeConstraints,
cv::Mat & outputCovariance,
std::list<std::map<int, Transform> > * intermediateGraphes = 0,
double * finalError = 0,
int * iterationsDone = 0);
+146 -43
View File
@@ -172,8 +172,11 @@ class RTABMAP_EXP Parameters
RTABMAP_PARAM(Rtabmap, PublishLastSignature, bool, true, "Publishing last signature.");
RTABMAP_PARAM(Rtabmap, PublishPdf, bool, true, "Publishing pdf.");
RTABMAP_PARAM(Rtabmap, PublishLikelihood, bool, true, "Publishing likelihood.");
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, PublishRAMUsage, bool, false, "Publishing RAM usage in statistics (may add a small overhead to get info from the system).");
RTABMAP_PARAM(Rtabmap, ComputeRMSE, bool, true, "Compute root mean square error (RMSE) and publish it in statistics, if ground truth is provided.");
RTABMAP_PARAM(Rtabmap, SaveWMState, bool, false, "Save working memory state after each update in statistics.");
RTABMAP_PARAM(Rtabmap, TimeThr, float, 0, "Maximum time allowed for map update (ms) (0 means infinity). When map update time exceeds this fixed time threshold, some nodes in Working Memory (WM) are transferred to Long-Term Memory to limit the size of the WM and decrease the update time.");
RTABMAP_PARAM(Rtabmap, MemoryThr, int, 0, uFormat("Maximum nodes in the Working Memory (0 means infinity). Similar to \"%s\", when the number of nodes in Working Memory (WM) exceeds this treshold, some nodes are transferred to Long-Term Memory to keep WM size fixed.", kRtabmapTimeThr().c_str()));
RTABMAP_PARAM(Rtabmap, DetectionRate, float, 1, "Detection rate (Hz). 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, CreateIntermediateNodes, bool, false, uFormat("Create intermediate nodes between loop closure detection. Only used when %s>0.", kRtabmapDetectionRate().c_str()));
@@ -183,6 +186,9 @@ class RTABMAP_EXP Parameters
RTABMAP_PARAM(Rtabmap, StatisticLogged, bool, false, "Logging enabled.");
RTABMAP_PARAM(Rtabmap, StatisticLoggedHeaders, bool, true, "Add column header description to log files.");
RTABMAP_PARAM(Rtabmap, StartNewMapOnLoopClosure, bool, false, "Start a new map only if there is a global loop closure with a previous map.");
RTABMAP_PARAM(Rtabmap, StartNewMapOnGoodSignature, bool, false, uFormat("Start a new map only if the first signature is not bad (i.e., has enough features, see %s).", kKpBadSignRatio().c_str()));
RTABMAP_PARAM(Rtabmap, ImagesAlreadyRectified, bool, true, "Images are already rectified. By default RTAB-Map assumes that received images are rectified. If they are not, they can be rectified by RTAB-Map if this parameter is false.");
RTABMAP_PARAM(Rtabmap, RectifyOnlyFeatures, bool, false, uFormat("If \"%s\" is false and this parameter is true, the whole RGB image will not be rectified, only the features. Warning: As projection of RGB-D image to point cloud is assuming that images are rectified, the generated point cloud map will have wrong colors if this parameter is true.", kRtabmapImagesAlreadyRectified().c_str()));
// Hypotheses selection
RTABMAP_PARAM(Rtabmap, LoopThr, float, 0.11, "Loop closing threshold.");
@@ -207,28 +213,36 @@ class RTABMAP_EXP Parameters
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, 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, DepthAsMask, bool, true, "Use depth image as mask when extracting features for vocabulary.");
RTABMAP_PARAM(Mem, ImagePreDecimation, int, 1, "Image decimation (>=1) before features extraction. Negative decimation is done from RGB size instead of depth size (if depth is smaller than RGB, it may be interpolated depending of the decimation value).");
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. Negative decimation is done from RGB size instead of depth size (if depth is smaller than RGB, it may be interpolated depending of the decimation value).");
RTABMAP_PARAM(Mem, CompressionParallelized, bool, true, "Compression of sensor data is multi-threaded.");
RTABMAP_PARAM(Mem, LaserScanDownsampleStepSize, int, 1, "If > 1, downsample the laser scans when creating a signature.");
RTABMAP_PARAM(Mem, LaserScanVoxelSize, float, 0.0, uFormat("If > 0 m, voxel filtering is done on laser scans when creating a signature. If the laser scan had normals, they will be removed. To recompute the normals, make sure to use \"%s\" or \"%s\" parameters.", kMemLaserScanNormalK().c_str(), kMemLaserScanNormalRadius().c_str()).c_str());
RTABMAP_PARAM(Mem, LaserScanNormalK, int, 0, "If > 0 and laser scans don't have normals, normals will be computed with K search neighbors when creating a signature.");
RTABMAP_PARAM(Mem, LaserScanNormalRadius, int, 0, "If > 0 m and laser scans don't have normals, normals will be computed with radius search neighbors when creating a signature.");
RTABMAP_PARAM(Mem, UseOdomFeatures, bool, false, "Use odometry features.");
RTABMAP_PARAM(Mem, LaserScanNormalRadius, float, 0.0, "If > 0 m and laser scans don't have normals, normals will be computed with radius search neighbors when creating a signature.");
RTABMAP_PARAM(Mem, UseOdomFeatures, bool, true, "Use odometry features.");
RTABMAP_PARAM(Mem, CovOffDiagIgnored, bool, true, "Ignore off diagonal values of the covariance matrix.");
// KeypointMemory (Keypoint-based)
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, 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, uFormat("When using FLANN based strategy, add/remove points to its index without always rebuilding the index (the index is built only when the dictionary increases of the factor \"%s\" in size).", kKpFlannRebalancingFactor().c_str()));
RTABMAP_PARAM(Kp, FlannRebalancingFactor, float, 2.0, uFormat("Factor used when rebuilding the incremental FLANN index (see \"%s\"). Set <=1 to disable.", kKpIncrementalFlann().c_str()));
RTABMAP_PARAM(Kp, MaxDepth, float, 0, "Filter extracted keypoints by depth (0=inf).");
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, 500, "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, NndrRatio, float, 0.8, "NNDR ratio (A matching pair is detected, if its distance is closer than X times the distance of the second nearest neighbor.)");
#ifdef RTABMAP_NONFREE
RTABMAP_PARAM(Kp, DetectorStrategy, int, 0, "0=SURF 1=SIFT 2=ORB 3=FAST/FREAK 4=FAST/BRIEF 5=GFTT/FREAK 6=GFTT/BRIEF 7=BRISK 8=GFTT/ORB 9=KAZE.");
#ifndef RTABMAP_NONFREE
#ifdef RTABMAP_OPENCV3
// OpenCV 3 without xFeatures2D module doesn't have BRIEF
RTABMAP_PARAM(Kp, DetectorStrategy, int, 8, "0=SURF 1=SIFT 2=ORB 3=FAST/FREAK 4=FAST/BRIEF 5=GFTT/FREAK 6=GFTT/BRIEF 7=BRISK 8=GFTT/ORB 9=KAZE.");
#else
RTABMAP_PARAM(Kp, DetectorStrategy, int, 2, "0=SURF 1=SIFT 2=ORB 3=FAST/FREAK 4=FAST/BRIEF 5=GFTT/FREAK 6=GFTT/BRIEF 7=BRISK 8=GFTT/ORB 9=KAZE.");
RTABMAP_PARAM(Kp, DetectorStrategy, int, 6, "0=SURF 1=SIFT 2=ORB 3=FAST/FREAK 4=FAST/BRIEF 5=GFTT/FREAK 6=GFTT/BRIEF 7=BRISK 8=GFTT/ORB 9=KAZE.");
#endif
#else
RTABMAP_PARAM(Kp, DetectorStrategy, int, 6, "0=SURF 1=SIFT 2=ORB 3=FAST/FREAK 4=FAST/BRIEF 5=GFTT/FREAK 6=GFTT/BRIEF 7=BRISK 8=GFTT/ORB 9=KAZE.");
#endif
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.");
@@ -238,6 +252,8 @@ class RTABMAP_EXP Parameters
RTABMAP_PARAM(Kp, SubPixWinSize, int, 3, "See cv::cornerSubPix().");
RTABMAP_PARAM(Kp, SubPixIterations, int, 0, "See cv::cornerSubPix(). 0 disables sub pixel refining.");
RTABMAP_PARAM(Kp, SubPixEps, double, 0.02, "See cv::cornerSubPix().");
RTABMAP_PARAM(Kp, GridRows, int, 1, uFormat("Number of rows of the grid used to extract uniformly \"%s / grid cells\" features from each cell.", kKpMaxFeatures().c_str()));
RTABMAP_PARAM(Kp, GridCols, int, 1, uFormat("Number of columns of the grid used to extract uniformly \"%s / grid cells\" features from each cell.", kKpMaxFeatures().c_str()));
//Database
RTABMAP_PARAM(DbSqlite3, InMemory, bool, false, "Using database in the memory instead of a file on the hard disk.");
@@ -269,11 +285,11 @@ class RTABMAP_EXP Parameters
RTABMAP_PARAM(FAST, GpuKeypointsRatio, double, 0.05, "Used with FAST GPU.");
RTABMAP_PARAM(FAST, MinThreshold, int, 7, "Minimum threshold. Used only when FAST/GridRows and FAST/GridCols are set.");
RTABMAP_PARAM(FAST, MaxThreshold, int, 200, "Maximum threshold. Used only when FAST/GridRows and FAST/GridCols are set.");
RTABMAP_PARAM(FAST, GridRows, int, 4, "Grid rows (0 to disable). Adapts the detector to partition the source image into a grid and detect points in each cell.");
RTABMAP_PARAM(FAST, GridCols, int, 4, "Grid cols (0 to disable). Adapts the detector to partition the source image into a grid and detect points in each cell.");
RTABMAP_PARAM(FAST, GridRows, int, 0, "Grid rows (0 to disable). Adapts the detector to partition the source image into a grid and detect points in each cell.");
RTABMAP_PARAM(FAST, GridCols, int, 0, "Grid cols (0 to disable). Adapts the detector to partition the source image into a grid and detect points in each cell.");
RTABMAP_PARAM(GFTT, QualityLevel, double, 0.01, "");
RTABMAP_PARAM(GFTT, MinDistance, double, 5, "");
RTABMAP_PARAM(GFTT, QualityLevel, double, 0.001, "");
RTABMAP_PARAM(GFTT, MinDistance, double, 3, "");
RTABMAP_PARAM(GFTT, BlockSize, int, 3, "");
RTABMAP_PARAM(GFTT, UseHarrisDetector, bool, false, "");
RTABMAP_PARAM(GFTT, K, double, 0.04, "");
@@ -316,11 +332,14 @@ class RTABMAP_EXP Parameters
// RGB-D SLAM
RTABMAP_PARAM(RGBD, Enabled, bool, true, "");
RTABMAP_PARAM(RGBD, LinearUpdate, float, 0.1, "Minimum linear displacement to update the map. Rehearsal is done prior to this, so weights are still updated.");
RTABMAP_PARAM(RGBD, 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, LinearUpdate, float, 0.1, "Minimum linear displacement (m) 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 (rad) to update the map. Rehearsal is done prior to this, so weights are still updated.");
RTABMAP_PARAM(RGBD, LinearSpeedUpdate, float, 0.0, "Maximum linear speed (m/s) to update the map (0 means not limit).");
RTABMAP_PARAM(RGBD, AngularSpeedUpdate, float, 0.0, "Maximum angular speed (rad/s) to update the map (0 means not limit).");
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 node of the current graph, but it can be useful to preserve the map referential from the oldest node). Warning when set to false: when some nodes are transferred, the first referential of the local map may change, resulting in momentary changes in robot/map position (which are annoying in teleoperation).");
RTABMAP_PARAM(RGBD, OptimizeMaxError, float, 1, uFormat("Reject loop closures if optimization error is greater than this value (0=disabled). This will help to detect when a wrong loop closure is added to the graph. Not compatible with \"%s\" if enabled.", kOptimizerRobust().c_str()));
RTABMAP_PARAM(RGBD, OptimizeMaxError, float, 1.0, uFormat("Reject loop closures if optimization error ratio is greater than this value (0=disabled). Ratio is computed as absolute error over standard deviation of each link. This will help to detect when a wrong loop closure is added to the graph. Not compatible with \"%s\" if enabled.", kOptimizerRobust().c_str()));
RTABMAP_PARAM(RGBD, SavedLocalizationIgnored, bool, false, "Ignore last saved localization pose from previous session. If true, RTAB-Map won't assume it is restarting from the same place than where it shut down previously.");
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, PlanLinearVelocity, float, 0, "Linear velocity (m/sec) used to compute path weights.");
@@ -332,6 +351,7 @@ class RTABMAP_EXP Parameters
RTABMAP_PARAM(RGBD, ScanMatchingIdsSavedInLinks, bool, true, "Save scan matching IDs in link's user data.");
RTABMAP_PARAM(RGBD, NeighborLinkRefining, bool, false, uFormat("When a new node is added to the graph, the transformation of its neighbor link to the previous node is refined using registration approach selected (%s).", kRegStrategy().c_str()));
RTABMAP_PARAM(RGBD, LoopClosureReextractFeatures, bool, false, "Extract features even if there are some already in the nodes.");
RTABMAP_PARAM(RGBD, LocalBundleOnLoopClosure, bool, false, "Do local bundle adjustment with neighborhood of the loop closure.");
RTABMAP_PARAM(RGBD, CreateOccupancyGrid, bool, false, "Create local occupancy grid maps. See \"Grid\" group for parameters.");
// Local/Proximity loop closure detection
@@ -339,7 +359,7 @@ class RTABMAP_EXP Parameters
RTABMAP_PARAM(RGBD, ProximityBySpace, bool, true, "Detection over locations (in Working Memory) near in space.");
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, ProximityMaxPaths, int, 3, "Maximum paths compared (from the most recent) for proximity detection by space. 0 means no limit.");
RTABMAP_PARAM(RGBD, ProximityPathFilteringRadius, float, 0.5, "Path filtering radius to reduce the number of nodes to compare in a path. A path should also be inside that radius to be considered for proximity detection.");
RTABMAP_PARAM(RGBD, ProximityPathFilteringRadius, float, 1, "Path filtering radius to reduce the number of nodes to compare in a path. A path should also be inside that radius to be considered for proximity detection.");
RTABMAP_PARAM(RGBD, ProximityPathMaxNeighbors, int, 0, "Maximum neighbor nodes compared on each path. Set to 0 to disable merging the laser scans.");
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, "Maximum angle (degrees) for visual proximity detection.");
@@ -364,7 +384,11 @@ class RTABMAP_EXP Parameters
RTABMAP_PARAM(Optimizer, Robust, bool, false, uFormat("Robust graph optimization using Vertigo (only work for g2o and GTSAM optimization strategies). Not compatible with \"%s\" if enabled.", kRGBDOptimizeMaxError().c_str()));
RTABMAP_PARAM(Optimizer, PriorsIgnored, bool, true, "Ignore prior constraints (global pose or GPS) while optimizing. Currently only g2o and gtsam optimization supports this.");
#ifdef RTABMAP_ORB_SLAM2
RTABMAP_PARAM(g2o, Solver, int, 3, "0=csparse 1=pcg 2=cholmod 3=Eigen");
#else
RTABMAP_PARAM(g2o, Solver, int, 0, "0=csparse 1=pcg 2=cholmod 3=Eigen");
#endif
RTABMAP_PARAM(g2o, Optimizer, int, 0, "0=Levenberg 1=GaussNewton");
RTABMAP_PARAM(g2o, PixelVariance, double, 1.0, "Pixel variance used for bundle adjustment.");
RTABMAP_PARAM(g2o, RobustKernelDelta, double, 8, "Robust kernel delta used for bundle adjustment (0 means don't use robust kernel). Observations with chi2 over this threshold will be ignored in the second optimization pass.");
@@ -373,7 +397,7 @@ class RTABMAP_EXP Parameters
RTABMAP_PARAM(GTSAM, Optimizer, int, 1, "0=Levenberg 1=GaussNewton 2=Dogleg");
// Odometry
RTABMAP_PARAM(Odom, Strategy, int, 0, "0=Frame-to-Map (F2M) 1=Frame-to-Frame (F2F) 2=Fovis 3=viso2 4=DVO-SLAM 5=ORB_SLAM2");
RTABMAP_PARAM(Odom, Strategy, int, 0, "0=Frame-to-Map (F2M) 1=Frame-to-Frame (F2F) 2=Fovis 3=viso2 4=DVO-SLAM 5=ORB_SLAM2 6=OKVIS 7=LOAM 8=MSCKF_VIO");
RTABMAP_PARAM(Odom, ResetCountdown, int, 0, "Automatically reset odometry after X consecutive images on which odometry cannot be computed (value=0 disables auto-reset).");
RTABMAP_PARAM(Odom, Holonomic, bool, true, "If the robot is holonomic (strafing commands can be issued). If not, y value will be estimated from x and yaw values (y=x*tan(yaw)).");
RTABMAP_PARAM(Odom, FillInfoData, bool, true, "Fill info with data (inliers/outliers features).");
@@ -386,9 +410,9 @@ class RTABMAP_EXP Parameters
RTABMAP_PARAM(Odom, ParticleLambdaR, float, 100, "Lambda of rotational components (roll,pitch,yaw).");
RTABMAP_PARAM(Odom, KalmanProcessNoise, float, 0.001, "Process noise covariance value.");
RTABMAP_PARAM(Odom, KalmanMeasurementNoise, float, 0.01, "Process measurement covariance value.");
RTABMAP_PARAM(Odom, GuessMotion, bool, false, "Guess next transformation from the last motion computed.");
RTABMAP_PARAM(Odom, GuessMotion, bool, true, "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, VisKeyFrameThr, int, 100, "[Visual] Create a new keyframe when the number of inliers drops under this threshold. Setting the value to 0 means that a keyframe is created for each processed frame.");
RTABMAP_PARAM(Odom, VisKeyFrameThr, int, 150, "[Visual] Create a new keyframe when the number of inliers drops under this threshold. Setting the value to 0 means that a keyframe is created for each processed frame.");
RTABMAP_PARAM(Odom, ScanKeyFrameThr, float, 0.9, "[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. Negative decimation is done from RGB size instead of depth size (if depth is smaller than RGB, it may be interpolated depending of the decimation value).");
RTABMAP_PARAM(Odom, AlignWithGround, bool, false, "Align odometry with the ground on initialization.");
@@ -399,8 +423,12 @@ class RTABMAP_EXP Parameters
RTABMAP_PARAM(OdomF2M, ScanMaxSize, int, 2000, "[Geometry] Maximum local scan map size.");
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(OdomF2M, ScanSubtractAngle, float, 45, uFormat("[Geometry] Max angle (degrees) used to filter points of a new added scan to local map (when \"%s\">0). 0 means any angle.", kOdomF2MScanSubtractRadius().c_str()).c_str());
#if defined(RTABMAP_G2O) || defined(RTABMAP_ORB_SLAM2)
RTABMAP_PARAM(OdomF2M, BundleAdjustment, int, 1, "Local bundle adjustment: 0=disabled, 1=g2o, 2=cvsba.");
#else
RTABMAP_PARAM(OdomF2M, BundleAdjustment, int, 0, "Local bundle adjustment: 0=disabled, 1=g2o, 2=cvsba.");
RTABMAP_PARAM(OdomF2M, BundleAdjustmentMaxFrames, int, 0, "Maximum frames used for bundle adjustment (0=inf or all current frames in the local map).");
#endif
RTABMAP_PARAM(OdomF2M, BundleAdjustmentMaxFrames, int, 10, "Maximum frames used for bundle adjustment (0=inf or all current frames in the local map).");
// Odometry Mono
RTABMAP_PARAM(OdomMono, InitMinFlow, float, 100, "Minimum optical flow required for the initialization step.");
@@ -426,7 +454,7 @@ class RTABMAP_EXP Parameters
RTABMAP_PARAM(OdomFovis, InlierMaxReprojectionError, double, 1.5, "The maximum image-space reprojection error (in pixels) a feature match is allowed to have and still be considered an inlier in the set of features used for motion estimation.");
RTABMAP_PARAM(OdomFovis, CliqueInlierThreshold, double, 0.1, "See Howard's greedy max-clique algorithm for determining the maximum set of mutually consisten feature matches. This specifies the compatibility threshold, in meters.");
RTABMAP_PARAM(OdomFovis, MinFeaturesForEstimate, int, 10, "Minimum number of features in the inlier set for the motion estimate to be considered valid.");
RTABMAP_PARAM(OdomFovis, MinFeaturesForEstimate, int, 20, "Minimum number of features in the inlier set for the motion estimate to be considered valid.");
RTABMAP_PARAM(OdomFovis, MaxMeanReprojectionError, double, 10.0, "Maximum mean reprojection error over the inlier feature matches for the motion estimate to be considered valid.");
RTABMAP_PARAM(OdomFovis, UseSubpixelRefinement, bool, true, "Specifies whether or not to refine feature matches to subpixel resolution.");
RTABMAP_PARAM(OdomFovis, FeatureSearchWindow, int, 25, "Specifies the size of the search window to apply when searching for feature matches across time frames. The search is conducted around the feature location predicted by the initial rotation estimate.");
@@ -456,13 +484,54 @@ class RTABMAP_EXP Parameters
RTABMAP_PARAM(OdomViso2, BucketHeight, double, 50, "Height of bucket.");
// Odometry ORB_SLAM2
RTABMAP_PARAM_STR(OdomORBSLAM2, VocPath, "", "Path to ORB vocabulary (*.txt).");
RTABMAP_PARAM(OdomORBSLAM2, Bf, double, 0.076, "Fake IR projector baseline (m) used only when stereo is not used.");
RTABMAP_PARAM(OdomORBSLAM2, ThDepth, double, 40.0, "Close/Far threshold. Baseline times.");
RTABMAP_PARAM_STR(OdomORBSLAM2, VocPath, "", "Path to ORB vocabulary (*.txt).");
RTABMAP_PARAM(OdomORBSLAM2, Bf, double, 0.076, "Fake IR projector baseline (m) used only when stereo is not used.");
RTABMAP_PARAM(OdomORBSLAM2, ThDepth, double, 40.0, "Close/Far threshold. Baseline times.");
RTABMAP_PARAM(OdomORBSLAM2, Fps, float, 0.0, "Camera FPS.");
RTABMAP_PARAM(OdomORBSLAM2, MaxFeatures, int, 1000, "Maximum ORB features extracted per frame.");
RTABMAP_PARAM(OdomORBSLAM2, MapSize, int, 3000, "Maximum size of the feature map (0 means infinite).");
// Odometry OKVIS
RTABMAP_PARAM_STR(OdomOKVIS, ConfigPath, "", "Path of OKVIS config file.");
// Odometry LOAM
RTABMAP_PARAM(OdomLOAM, Sensor, int, 2, "Velodyne sensor: 0=VLP-16, 1=HDL-32, 2=HDL-64E");
RTABMAP_PARAM(OdomLOAM, ScanPeriod, float, 0.1, "Scan period (s)");
RTABMAP_PARAM(OdomLOAM, LinVar, float, 0.01, "Linear output variance.");
RTABMAP_PARAM(OdomLOAM, AngVar, float, 0.01, "Angular output variance.");
RTABMAP_PARAM(OdomLOAM, LocalMapping, bool, true, "Local mapping. It adds more time to compute odometry, but accuracy is significantly improved.");
// Odometry MSCKF_VIO
RTABMAP_PARAM(OdomMSCKF, GridRow, int, 4, "");
RTABMAP_PARAM(OdomMSCKF, GridCol, int, 5, "");
RTABMAP_PARAM(OdomMSCKF, GridMinFeatureNum, int, 3, "");
RTABMAP_PARAM(OdomMSCKF, GridMaxFeatureNum, int, 4, "");
RTABMAP_PARAM(OdomMSCKF, PyramidLevels, int, 3, "");
RTABMAP_PARAM(OdomMSCKF, PatchSize, int, 15, "");
RTABMAP_PARAM(OdomMSCKF, FastThreshold, int, 10, "");
RTABMAP_PARAM(OdomMSCKF, MaxIteration, int, 30, "");
RTABMAP_PARAM(OdomMSCKF, TrackPrecision, double, 0.01, "");
RTABMAP_PARAM(OdomMSCKF, RansacThreshold, double, 3, "");
RTABMAP_PARAM(OdomMSCKF, StereoThreshold, double, 5, "");
RTABMAP_PARAM(OdomMSCKF, PositionStdThreshold, double, 8.0, "");
RTABMAP_PARAM(OdomMSCKF, RotationThreshold, double, 0.2618, "");
RTABMAP_PARAM(OdomMSCKF, TranslationThreshold, double, 0.4, "");
RTABMAP_PARAM(OdomMSCKF, TrackingRateThreshold, double, 0.5, "");
RTABMAP_PARAM(OdomMSCKF, OptTranslationThreshold, double, 0, "");
RTABMAP_PARAM(OdomMSCKF, NoiseGyro, double, 0.005, "");
RTABMAP_PARAM(OdomMSCKF, NoiseAcc, double, 0.05, "");
RTABMAP_PARAM(OdomMSCKF, NoiseGyroBias, double, 0.001, "");
RTABMAP_PARAM(OdomMSCKF, NoiseAccBias, double, 0.01, "");
RTABMAP_PARAM(OdomMSCKF, NoiseFeature, double, 0.035, "");
RTABMAP_PARAM(OdomMSCKF, InitCovVel, double, 0.25, "");
RTABMAP_PARAM(OdomMSCKF, InitCovGyroBias, double, 0.01, "");
RTABMAP_PARAM(OdomMSCKF, InitCovAccBias, double, 0.01, "");
RTABMAP_PARAM(OdomMSCKF, InitCovExRot, double, 0.00030462, "");
RTABMAP_PARAM(OdomMSCKF, InitCovExTrans, double, 0.000025, "");
RTABMAP_PARAM(OdomMSCKF, MaxCamStateSize, int, 20, "");
// Common registration parameters
RTABMAP_PARAM(Reg, VarianceFromInliersCount, bool, false, "Set variance as the inverse of the number of inliers. Otherwise, the variance is computed as the average 3D position error of the inliers.");
RTABMAP_PARAM(Reg, VarianceNormalized, bool, false, "Normalize covariance values. Position variances are multiplied by norm of the transform and orientation variances are multiplied by angle of the transform.");
RTABMAP_PARAM(Reg, RepeatOnce, bool, true, "Do a second registration with the output of the first registration as guess. Only done if no guess was provided for the first registration (like on loop closure). It can be useful if the registration approach used can use a guess to get better matches.");
RTABMAP_PARAM(Reg, Strategy, int, 0, "0=Vis, 1=Icp, 2=VisIcp");
RTABMAP_PARAM(Reg, Force3DoF, bool, false, "Force 3 degrees-of-freedom transform (3Dof: x,y and yaw). Parameters z, roll and pitch will be set to 0.");
@@ -473,10 +542,15 @@ class RTABMAP_EXP Parameters
RTABMAP_PARAM(Vis, RefineIterations, int, 5, uFormat("[%s = 0] Number of iterations used to refine the transformation found by RANSAC. 0 means that the transformation is not refined.", kVisEstimationType().c_str()));
RTABMAP_PARAM(Vis, PnPReprojError, float, 2, uFormat("[%s = 1] PnP reprojection error.", kVisEstimationType().c_str()));
RTABMAP_PARAM(Vis, PnPFlags, int, 0, uFormat("[%s = 1] PnP flags: 0=Iterative, 1=EPNP, 2=P3P", kVisEstimationType().c_str()));
RTABMAP_PARAM(Vis, PnPRefineIterations, int, 1, uFormat("[%s = 1] Refine iterations.", kVisEstimationType().c_str()));
#if defined(RTABMAP_G2O) || defined(RTABMAP_ORB_SLAM2)
RTABMAP_PARAM(Vis, PnPRefineIterations, int, 0, uFormat("[%s = 1] Refine iterations. Set to 0 if \"%s\" is also used.", kVisEstimationType().c_str(), kVisBundleAdjustment().c_str()));
#else
RTABMAP_PARAM(Vis, PnPRefineIterations, int, 1, uFormat("[%s = 1] Refine iterations. Set to 0 if \"%s\" is also used.", kVisEstimationType().c_str(), kVisBundleAdjustment().c_str()));
#endif
RTABMAP_PARAM(Vis, EpipolarGeometryVar, float, 0.02, uFormat("[%s = 2] Epipolar geometry maximum variance to accept the transformation.", kVisEstimationType().c_str()));
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, 300, "Maximum iterations to compute the transform.");
#ifndef RTABMAP_NONFREE
#ifdef RTABMAP_OPENCV3
// OpenCV 3 without xFeatures2D module doesn't have BRIEF
@@ -490,46 +564,68 @@ class RTABMAP_EXP Parameters
RTABMAP_PARAM(Vis, MaxFeatures, int, 1000, "0 no limits.");
RTABMAP_PARAM(Vis, MaxDepth, float, 0, "Max depth of the features (0 means no limit).");
RTABMAP_PARAM(Vis, MinDepth, float, 0, "Min depth of the features (0 means no limit).");
RTABMAP_PARAM(Vis, DepthAsMask, bool, true, "Use depth image as mask when extracting features.");
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, SubPixIterations, int, 0, "See cv::cornerSubPix(). 0 disables sub pixel refining.");
RTABMAP_PARAM(Vis, SubPixEps, float, 0.02, "See cv::cornerSubPix().");
RTABMAP_PARAM(Vis, GridRows, int, 1, uFormat("Number of rows of the grid used to extract uniformly \"%s / grid cells\" features from each cell.", kVisMaxFeatures().c_str()));
RTABMAP_PARAM(Vis, GridCols, int, 1, uFormat("Number of columns of the grid used to extract uniformly \"%s / grid cells\" features from each cell.", kVisMaxFeatures().c_str()));
RTABMAP_PARAM(Vis, CorType, int, 0, "Correspondences computation approach: 0=Features Matching, 1=Optical Flow");
RTABMAP_PARAM(Vis, CorNNType, int, 1, uFormat("[%s=0] kNNFlannNaive=0, kNNFlannKdTree=1, kNNFlannLSH=2, kNNBruteForce=3, kNNBruteForceGPU=4. Used for features matching approach.", kVisCorType().c_str()));
RTABMAP_PARAM(Vis, CorNNDR, float, 0.6, uFormat("[%s=0] NNDR: nearest neighbor distance ratio. Used for features matching approach.", kVisCorType().c_str()));
RTABMAP_PARAM(Vis, CorGuessWinSize, int, 20, uFormat("[%s=0] Matching window size (pixels) around projected points when a guess transform is provided to find correspondences. 0 means disabled.", kVisCorType().c_str()));
RTABMAP_PARAM(Vis, CorGuessMatchToProjection, bool, false, uFormat("[%s=0] Match frame's corners to source's projected points (when guess transform is provided) instead of projected points to frame's corners.", kVisCorType().c_str()));
RTABMAP_PARAM(Vis, CorFlowWinSize, int, 16, uFormat("[%s=1] See cv::calcOpticalFlowPyrLK(). Used for optical flow approach.", kVisCorType().c_str()));
RTABMAP_PARAM(Vis, CorFlowIterations, int, 30, uFormat("[%s=1] See cv::calcOpticalFlowPyrLK(). Used for optical flow approach.", kVisCorType().c_str()));
RTABMAP_PARAM(Vis, CorFlowEps, float, 0.01, uFormat("[%s=1] See cv::calcOpticalFlowPyrLK(). Used for optical flow approach.", kVisCorType().c_str()));
RTABMAP_PARAM(Vis, CorFlowMaxLevel, int, 3, uFormat("[%s=1] See cv::calcOpticalFlowPyrLK(). Used for optical flow approach.", kVisCorType().c_str()));
#if defined(RTABMAP_G2O) || defined(RTABMAP_ORB_SLAM2)
RTABMAP_PARAM(Vis, BundleAdjustment, int, 1, "Optimization with bundle adjustment: 0=disabled, 1=g2o, 2=cvsba.");
#else
RTABMAP_PARAM(Vis, BundleAdjustment, int, 0, "Optimization with bundle adjustment: 0=disabled, 1=g2o, 2=cvsba.");
#endif
// ICP registration parameters
RTABMAP_PARAM(Icp, MaxTranslation, float, 0.2, "Maximum ICP translation correction accepted (m).");
RTABMAP_PARAM(Icp, MaxRotation, float, 0.78, "Maximum ICP rotation correction accepted (rad).");
RTABMAP_PARAM(Icp, VoxelSize, float, 0.0, "Uniform sampling voxel size (0=disabled).");
RTABMAP_PARAM(Icp, DownsamplingStep, int, 1, "Downsampling step size (1=no sampling). This is done before uniform sampling.");
#ifdef RTABMAP_POINTMATCHER
RTABMAP_PARAM(Icp, MaxCorrespondenceDistance, float, 0.1, "Max distance for point correspondences.");
#else
RTABMAP_PARAM(Icp, MaxCorrespondenceDistance, float, 0.05, "Max distance for point correspondences.");
#endif
RTABMAP_PARAM(Icp, Iterations, int, 30, "Max iterations.");
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.1, "Ratio of matching correspondences to accept the transform.");
#ifdef RTABMAP_POINTMATCHER
RTABMAP_PARAM(Icp, PointToPlane, bool, true, "Use point to plane ICP.");
#else
RTABMAP_PARAM(Icp, PointToPlane, bool, false, "Use point to plane ICP.");
RTABMAP_PARAM(Icp, PointToPlaneK, int, 20, "Number of neighbors to compute normals for point to plane if the cloud doesn't have already normals.");
RTABMAP_PARAM(Icp, PointToPlaneRadius, float, 0.0, "Search radius to compute normals for point to plane if the cloud doesn't have already normals.");
#endif
RTABMAP_PARAM(Icp, PointToPlaneK, int, 5, "Number of neighbors to compute normals for point to plane if the cloud doesn't have already normals.");
RTABMAP_PARAM(Icp, PointToPlaneRadius, float, 1.0, "Search radius to compute normals for point to plane if the cloud doesn't have already normals.");
RTABMAP_PARAM(Icp, PointToPlaneMinComplexity, float, 0.02, "Minimum structural complexity (0.0=low, 1.0=high) of the scan to do point to plane registration, otherwise point to point registration is done instead.");
// libpointmatcher
#ifdef RTABMAP_POINTMATCHER
RTABMAP_PARAM(Icp, PM, bool, true, "Use libpointmatcher for ICP registration instead of PCL's implementation.");
#else
RTABMAP_PARAM(Icp, PM, bool, false, "Use libpointmatcher for ICP registration instead of PCL's implementation.");
#endif
RTABMAP_PARAM_STR(Icp, PMConfig, "", uFormat("Configuration file (*.yaml) used by libpointmatcher. Note that data filters set for libpointmatcher are done after filtering done by rtabmap (i.e., %s, %s), so make sure to disable those in rtabmap if you want to use only those from libpointmatcher. Parameters %s, %s and %s are also ignored if configuration file is set.", kIcpVoxelSize().c_str(), kIcpDownsamplingStep().c_str(), kIcpIterations().c_str(), kIcpEpsilon().c_str(), kIcpMaxCorrespondenceDistance().c_str()).c_str());
RTABMAP_PARAM(Icp, PMOutlierRatio, float, 0.85, "TrimmedDistOutlierFilter/ratio: For convenience when configuration file is not set. For kinect-like point cloud, use 0.65.");
RTABMAP_PARAM(Icp, PMMatcherKnn, int, 1, "KDTreeMatcher/knn: number of nearest neighbors to consider it the reference. For convenience when configuration file is not set.");
RTABMAP_PARAM(Icp, PMMatcherEpsilon, float, 0.0, "KDTreeMatcher/epsilon: approximation to use for the nearest-neighbor search. For convenience when configuration file is not set.");
RTABMAP_PARAM(Icp, PMOutlierRatio, float, 0.95, "TrimmedDistOutlierFilter/ratio: For convenience when configuration file is not set. For kinect-like point cloud, use 0.65.");
// Stereo disparity
RTABMAP_PARAM(Stereo, WinWidth, int, 15, "Window width.");
RTABMAP_PARAM(Stereo, WinHeight, int, 3, "Window height.");
RTABMAP_PARAM(Stereo, Iterations, int, 30, "Maximum iterations.");
RTABMAP_PARAM(Stereo, MaxLevel, int, 3, "Maximum pyramid level.");
RTABMAP_PARAM(Stereo, MinDisparity, int, 1, "Minimum disparity.");
RTABMAP_PARAM(Stereo, MaxDisparity, int, 128, "Maximum disparity.");
RTABMAP_PARAM(Stereo, MaxLevel, int, 5, "Maximum pyramid level.");
RTABMAP_PARAM(Stereo, MinDisparity, float, 0.5, "Minimum disparity.");
RTABMAP_PARAM(Stereo, MaxDisparity, float, 128.0, "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, SSD, bool, true, uFormat("[%s=false] Use Sum of Squared Differences (SSD) window, otherwise Sum of Absolute Differences (SAD) window is used.", kStereoOpticalFlow().c_str()));
RTABMAP_PARAM(Stereo, Eps, double, 0.01, uFormat("[%s=true] Epsilon stop criterion.", kStereoOpticalFlow().c_str()));
@@ -547,19 +643,20 @@ class RTABMAP_EXP Parameters
// Occupancy Grid
RTABMAP_PARAM(Grid, FromDepth, bool, true, "Create occupancy grid from depth image(s), otherwise it is created from laser scan.");
RTABMAP_PARAM(Grid, DepthDecimation, int, 4, uFormat("[%s=true] Decimation of the depth image before creating cloud. Negative decimation is done from RGB size instead of depth size (if depth is smaller than RGB, it may be interpolated depending of the decimation value).", kGridDepthDecimation().c_str()));
RTABMAP_PARAM(Grid, DepthMin, float, 0.0, uFormat("[%s=true] Minimum cloud's depth from sensor.", kGridFromDepth().c_str()));
RTABMAP_PARAM(Grid, DepthMax, float, 4.0, uFormat("[%s=true] Maximum cloud's depth from sensor. 0=inf.", kGridFromDepth().c_str()));
RTABMAP_PARAM(Grid, RangeMin, float, 0.0, "Minimum range from sensor.");
RTABMAP_PARAM(Grid, RangeMax, float, 5.0, "Maximum range from sensor. 0=inf.");
RTABMAP_PARAM_STR(Grid, DepthRoiRatios, "0.0 0.0 0.0 0.0", uFormat("[%s=true] Region of interest ratios [left, right, top, bottom].", kGridFromDepth().c_str()));
RTABMAP_PARAM(Grid, FootprintLength, float, 0.0, "Footprint length used to filter points over the footprint of the robot.");
RTABMAP_PARAM(Grid, FootprintWidth, float, 0.0, "Footprint width used to filter points over the footprint of the robot. Footprint length should be set.");
RTABMAP_PARAM(Grid, FootprintHeight, float, 0.0, "Footprint height used to filter points over the footprint of the robot. Footprint length and width should be set.");
RTABMAP_PARAM(Grid, ScanDecimation, int, 1, uFormat("[%s=false] Decimation of the laser scan before creating cloud.", kGridFromDepth().c_str()));
RTABMAP_PARAM(Grid, CellSize, float, 0.05, "Resolution of the occupancy grid.");
RTABMAP_PARAM(Grid, PreVoxelFiltering, bool, true, uFormat("Input cloud is downsampled by voxel filter (voxel size is \"%s\") before doing segmentation of obstacles and ground.", kGridCellSize().c_str()));
RTABMAP_PARAM(Grid, MapFrameProjection, bool, false, "Projection in map frame. On a 3D terrain and a fixed local camera transform (the cloud is created relative to ground), you may want to disable this to do the projection in robot frame instead.");
RTABMAP_PARAM(Grid, NormalsSegmentation, bool, true, "Segment ground from obstacles using point normals, otherwise a fast passthrough is used.");
RTABMAP_PARAM(Grid, MaxObstacleHeight, float, 0.0, "Maximum obstacles height (0=disabled).");
RTABMAP_PARAM(Grid, MinGroundHeight, float, 0.0, "Minimum ground height (0=disabled).");
RTABMAP_PARAM(Grid, MaxGroundHeight, float, 0.0, uFormat("Maximum ground height (0=disabled). Should be set if \"%s\" is true.", kGridNormalsSegmentation().c_str()));
RTABMAP_PARAM(Grid, MaxGroundHeight, float, 0.0, uFormat("Maximum ground height (0=disabled). Should be set if \"%s\" is false.", kGridNormalsSegmentation().c_str()));
RTABMAP_PARAM(Grid, MaxGroundAngle, float, 45, uFormat("[%s=true] Maximum angle (degrees) between point's normal to ground's normal to label it as ground. Points with higher angle difference are considered as obstacles.", kGridNormalsSegmentation().c_str()));
RTABMAP_PARAM(Grid, NormalK, int, 20, uFormat("[%s=true] K neighbors to compute normals.", kGridNormalsSegmentation().c_str()));
RTABMAP_PARAM(Grid, ClusterRadius, float, 0.1, uFormat("[%s=true] Cluster maximum radius.", kGridNormalsSegmentation().c_str()));
@@ -573,14 +670,20 @@ class RTABMAP_EXP Parameters
RTABMAP_PARAM(Grid, GroundIsObstacle, bool, false, uFormat("[%s=true] Ground segmentation (%s) is ignored, all points are obstacles. Use this only if you want an OctoMap with ground identified as an obstacle (e.g., with an UAV).", kGrid3D().c_str(), kGridNormalsSegmentation().c_str()));
RTABMAP_PARAM(Grid, NoiseFilteringRadius, float, 0.0, "Noise filtering radius (0=disabled). Done after segmentation.");
RTABMAP_PARAM(Grid, NoiseFilteringMinNeighbors, int, 5, "Noise filtering minimum neighbors.");
RTABMAP_PARAM(Grid, Scan2dUnknownSpaceFilled, bool, false, "Unknown space filled. Only used with 2D laser scans.");
RTABMAP_PARAM(Grid, Scan2dMaxFilledRange, float, 4.0, "Unknown space filled maximum range. If 0, the laser scan maximum range is used.");
RTABMAP_PARAM(Grid, ProjRayTracing, bool, true, uFormat("[%s=false] 2D ray tracing is done for each projected obstacle, filling unknown space between the sensor and obstacles.", kGrid3D().c_str()));
RTABMAP_PARAM(Grid, Scan2dUnknownSpaceFilled, bool, false, uFormat("Unknown space filled. Only used with 2D laser scans. Use %s to set maximum range if laser scan max range is to set.", kGridRangeMax().c_str()));
RTABMAP_PARAM(Grid, RayTracing, bool, false, uFormat("Ray tracing is done for each occupied cell, filling unknown space between the sensor and occupied cells. If %s=true, RTAB-Map should be built with OctoMap support, otherwise 3D ray tracing is ignored.", kGrid3D().c_str()));
RTABMAP_PARAM(GridGlobal, FullUpdate, bool, true, "When the graph is changed, the whole map will be reconstructed instead of moving individually each cells of the map. Also, data added to cache won't be released after updating the map. This process is longer but more robust to drift that would erase some parts of the map when it should not.");
RTABMAP_PARAM(GridGlobal, UpdateError, float, 0.01, "Graph changed detection error (m). Update map only if poses in new optimized graph have moved more than this value.");
RTABMAP_PARAM(GridGlobal, FootprintRadius, float, 0.0, "Footprint radius (m) used to clear all obstacles under the graph.");
RTABMAP_PARAM(GridGlobal, MinSize, float, 0.0, "Minimum map size (m).");
RTABMAP_PARAM(GridGlobal, Eroded, bool, false, "Erode obstacle cells.");
RTABMAP_PARAM(GridGlobal, MaxNodes, int, 0, "Maximum nodes assembled in the map starting from the last node (0=unlimited).");
RTABMAP_PARAM(GridGlobal, OccupancyThr, float, 0.5, "Occupancy threshold (value between 0 and 1).");
RTABMAP_PARAM(GridGlobal, ProbHit, float, 0.7, "Probability of a hit (value between 0.5 and 1).");
RTABMAP_PARAM(GridGlobal, ProbMiss, float, 0.4, "Probability of a miss (value between 0 and 0.5).");
RTABMAP_PARAM(GridGlobal, ProbClampingMin, float, 0.1192, "Probability clamping minimum (value between 0 and 1).");
RTABMAP_PARAM(GridGlobal, ProbClampingMax, float, 0.971, "Probability clamping maximum (value between 0 and 1).");
public:
virtual ~Parameters();
@@ -628,7 +731,7 @@ public:
static ParametersMap getDefaultParameters(const std::string & group);
static ParametersMap filterParameters(const ParametersMap & parameters, const std::string & group);
static void readINI(const std::string & configFile, ParametersMap & parameters);
static void readINI(const std::string & configFile, ParametersMap & parameters, bool modifiedOnly = false);
static void writeINI(const std::string & configFile, const ParametersMap & parameters);
/**
@@ -30,6 +30,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <rtabmap/utilite/ULogger.h>
namespace rtabmap {
class ProgressState
{
public:
@@ -55,5 +57,6 @@ private:
bool canceled_;
};
}
#endif /* CORELIB_INCLUDE_RTABMAP_CORE_PROGRESSSTATE_H_ */
+56
View File
@@ -0,0 +1,56 @@
/*
Copyright (c) 2010-2017, 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 RECOVERY_H_
#define RECOVERY_H_
#include "rtabmap/core/RtabmapExp.h" // DLL export/import defines
#include <string>
namespace rtabmap {
class ProgressState;
/**
* Return true on success. The database is
* renamed to "*.backup.db" before recovering.
* @param corruptedDatabase database to recover
* @param keepCorruptedDatabase if false and on recovery success, the backup database is removed
* @param errorMsg error message if the function returns false
* @param progressState A ProgressState object used to get status of the recovery process
*/
bool RTABMAP_EXP databaseRecovery(
const std::string & corruptedDatabase,
bool keepCorruptedDatabase = true,
std::string * errorMsg = 0,
ProgressState * progressState = 0);
}
#endif /* RECOVERY_H_ */
+6 -6
View File
@@ -45,6 +45,7 @@ public:
kTypeIcp = 1,
kTypeVisIcp = 2
};
static double COVARIANCE_EPSILON;
public:
static Registration * create(const ParametersMap & parameters);
@@ -58,12 +59,13 @@ public:
bool isScanRequired() const;
bool isUserDataRequired() const;
bool canUseGuess() const;
int getMinVisualCorrespondences() const;
float getMinGeometryCorrespondencesRatio() const;
bool varianceFromInliersCount() const {return varianceFromInliersCount_;}
bool repeatOnce() const {return repeatOnce_;}
bool force3DoF() const {return force3DoF_;}
bool covarianceNormalized() const {return covarianceNormalized_;}
// take ownership!
void setChildRegistration(Registration * child);
@@ -85,8 +87,6 @@ public:
Transform guess = Transform::getIdentity(),
RegistrationInfo * info = 0) const;
void normalizeCovariance(cv::Mat & covariance, const Transform & transform) const;
protected:
// take ownership of child
Registration(const ParametersMap & parameters = ParametersMap(), Registration * child = 0);
@@ -102,12 +102,12 @@ protected:
virtual bool isImageRequiredImpl() const {return false;}
virtual bool isScanRequiredImpl() const {return false;}
virtual bool isUserDataRequiredImpl() const {return false;}
virtual bool canUseGuessImpl() const {return false;}
virtual int getMinVisualCorrespondencesImpl() const {return 0;}
virtual float getMinGeometryCorrespondencesRatioImpl() const {return 0.0f;}
private:
bool varianceFromInliersCount_;
bool covarianceNormalized_;
bool repeatOnce_;
bool force3DoF_;
Registration * child_;
@@ -52,6 +52,7 @@ protected:
Transform guess,
RegistrationInfo & info) const;
virtual bool isScanRequiredImpl() const {return true;}
virtual bool canUseGuessImpl() const {return true;}
virtual float getMinGeometryCorrespondencesRatioImpl() const {return _correspondenceRatio;}
private:
@@ -69,6 +70,8 @@ private:
float _pointToPlaneMinComplexity;
bool _libpointmatcher;
std::string _libpointmatcherConfig;
int _libpointmatcherKnn;
float _libpointmatcherEpsilon;
float _libpointmatcherOutlierRatio;
void * _libpointmatcherICP;
};
@@ -35,6 +35,7 @@ class RegistrationInfo
{
public:
RegistrationInfo() :
totalTime(0.0),
inliers(0),
matches(0),
icpInliersRatio(0),
@@ -48,6 +49,7 @@ public:
RegistrationInfo copyWithoutData() const
{
RegistrationInfo output;
output.totalTime = totalTime;
output.covariance = covariance.clone();
output.rejectedMsg = rejectedMsg;
output.inliers = inliers;
@@ -61,12 +63,14 @@ public:
cv::Mat covariance;
std::string rejectedMsg;
double totalTime;
// RegistrationVis
int inliers;
std::vector<int> inliersIDs;
int matches;
std::vector<int> matchesIDs;
std::vector<int> projectedIDs; // "From" IDs
// RegistrationIcp
float icpInliersRatio;
@@ -61,6 +61,7 @@ protected:
RegistrationInfo & info) const;
virtual bool isImageRequiredImpl() const {return true;}
virtual bool canUseGuessImpl() const {return _correspondencesApproach != 0 || _guessWinSize>0;}
virtual int getMinVisualCorrespondencesImpl() const {return _minInliers;}
private:
@@ -81,7 +82,9 @@ private:
int _flowMaxLevel;
float _nndr;
int _guessWinSize;
bool _guessMatchToProjection;
int _bundleAdjustment;
bool _depthAsMask;
ParametersMap _featureParameters;
ParametersMap _bundleParameters;
+18 -7
View File
@@ -118,6 +118,7 @@ public:
const Statistics & getStatistics() const;
//bool getMetricData(int locationId, cv::Mat & rgb, cv::Mat & depth, float & depthConstant, Transform & pose, Transform & localTransform) const;
const std::map<int, Transform> & getLocalOptimizedPoses() const {return _optimizedPoses;}
const std::multimap<int, Link> & getLocalConstraints() const {return _constraints;}
Transform getPose(int locationId) const;
Transform getMapCorrection() const {return _mapCorrection;}
const Memory * getMemory() const {return _memory;}
@@ -128,6 +129,7 @@ public:
float getTimeThreshold() const {return _maxTimeAllowed;} // in ms
void setTimeThreshold(float maxTimeAllowed); // in ms
void setInitialPose(const Transform & initialPose);
int triggerNewMap();
bool labelLocation(int id, const std::string & label);
/**
@@ -151,7 +153,8 @@ public:
void parseParameters(const ParametersMap & parameters);
const ParametersMap & getParameters() const {return _parameters;}
void setWorkingDirectory(std::string path);
void rejectLoopClosure(int oldId, int newId);
void rejectLastLoopClosure();
void deleteLastLocation();
void setOptimizedPoses(const std::map<int, Transform> & poses);
void get3DMap(std::map<int, Signature> & signatures,
std::map<int, Transform> & poses,
@@ -161,15 +164,15 @@ public:
void getGraph(std::map<int, Transform> & poses,
std::multimap<int, Link> & constraints,
bool optimized,
bool global,
bool global,
std::map<int, Signature> * signatures = 0);
int detectMoreLoopClosures(float clusterRadius = 0.5f, float clusterAngle = M_PI/6.0f, int iterations = 1, const ProgressState * state = 0);
int refineLinks();
int getPathStatus() const {return _pathStatus;} // -1=failed 0=idle/executing 1=success
int getPathStatus() const {return _pathStatus;} // -1=failed 0=idle/executing 1=success
void clearPath(int status); // -1=failed 0=idle/executing 1=success
bool computePath(int targetNode, bool global);
bool computePath(const Transform & targetPose); // only in current optimized map
bool computePath(const Transform & targetPose, float tolerance = -1.0f); // only in current optimized map, tolerance (m) < 0 means RGBD/LocalRadius, 0 means infinite
const std::vector<std::pair<int, Transform> > & getPath() const {return _path;}
std::vector<std::pair<int, Transform> > getPathNextPoses() const;
std::vector<int> getPathNextNodes() const;
@@ -188,6 +191,7 @@ private:
void optimizeCurrentMap(int id,
bool lookInDatabase,
std::map<int, Transform> & optimizedPoses,
cv::Mat & covariance,
std::multimap<int, Link> * constraints = 0,
double * error = 0,
int * iterationsDone = 0) const;
@@ -196,6 +200,7 @@ private:
const std::set<int> & ids,
const std::map<int, Transform> & guessPoses,
bool lookInDatabase,
cv::Mat & covariance,
std::multimap<int, Link> * constraints = 0,
double * error = 0,
int * iterationsDone = 0) const;
@@ -211,6 +216,9 @@ private:
bool _publishLastSignatureData;
bool _publishPdf;
bool _publishLikelihood;
bool _publishRAMUsage;
bool _computeRMSE;
bool _saveWMState;
float _maxTimeAllowed; // in ms
unsigned int _maxMemoryAllowed; // signatures count in WM
float _loopThr;
@@ -225,6 +233,8 @@ private:
bool _rgbdSlamMode;
float _rgbdLinearUpdate;
float _rgbdAngularUpdate;
float _rgbdLinearSpeedUpdate;
float _rgbdAngularSpeedUpdate;
float _newMapOdomChangeDistance;
bool _neighborLinkRefining;
bool _proximityByTime;
@@ -240,13 +250,15 @@ private:
float _proximityAngle;
std::string _databasePath;
bool _optimizeFromGraphEnd;
float _optimizationMaxLinearError;
float _optimizationMaxError;
bool _startNewMapOnLoopClosure;
bool _startNewMapOnGoodSignature;
float _goalReachedRadius; // meters
bool _goalsSavedInUserData;
int _pathStuckIterations;
float _pathLinearVelocity;
float _pathAngularVelocity;
bool _savedLocalizationIgnored;
std::pair<int, float> _loopClosureHypothesis;
std::pair<int, float> _highestHypothesis;
@@ -291,6 +303,5 @@ private:
};
#endif /* RTABMAP_H_ */
} // namespace rtabmap
#endif /* RTABMAP_H_ */
+1 -1
View File
@@ -66,7 +66,6 @@ public:
kStateCleanDataBuffer,
kStatePublishingMap,
kStateTriggeringMap,
kStateAddingUserData,
kStateSettingGoal,
kStateCancellingGoal,
kStateLabelling
@@ -114,6 +113,7 @@ private:
std::queue<ParametersMap> _stateParam;
std::list<OdometryEvent> _dataBuffer;
std::list<double> _newMapEvents;
UMutex _dataMutex;
USemaphore _dataAdded;
unsigned int _dataBufferMaxSize;
+43 -23
View File
@@ -33,10 +33,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <rtabmap/core/CameraModel.h>
#include <rtabmap/core/StereoCameraModel.h>
#include <rtabmap/core/Transform.h>
#include <rtabmap/core/LaserScanInfo.h>
#include <rtabmap/core/GeodeticCoords.h>
#include <opencv2/core/core.hpp>
#include <opencv2/features2d/features2d.hpp>
#include <rtabmap/core/LaserScan.h>
#include <rtabmap/core/IMU.h>
namespace rtabmap
{
@@ -76,8 +77,7 @@ public:
// RGB-D constructor + laser scan
SensorData(
const cv::Mat & laserScan,
const LaserScanInfo & laserScanInfo,
const LaserScan & laserScan,
const cv::Mat & rgb,
const cv::Mat & depth,
const CameraModel & cameraModel,
@@ -96,8 +96,7 @@ public:
// Multi-cameras RGB-D constructor + laser scan
SensorData(
const cv::Mat & laserScan,
const LaserScanInfo & laserScanInfo,
const LaserScan & laserScan,
const cv::Mat & rgb,
const cv::Mat & depth,
const std::vector<CameraModel> & cameraModels,
@@ -116,8 +115,7 @@ public:
// Stereo constructor + laser scan
SensorData(
const cv::Mat & laserScan,
const LaserScanInfo & laserScanInfo,
const LaserScan & laserScan,
const cv::Mat & left,
const cv::Mat & right,
const StereoCameraModel & cameraModel,
@@ -125,7 +123,13 @@ public:
double stamp = 0.0,
const cv::Mat & userData = cv::Mat());
virtual ~SensorData() {}
// IMU constructor
SensorData(
const IMU & imu,
int id = 0,
double stamp = 0.0);
virtual ~SensorData();
bool isValid() const {
return !(_id == 0 &&
@@ -134,32 +138,32 @@ public:
_imageCompressed.empty() &&
_depthOrRightRaw.empty() &&
_depthOrRightCompressed.empty() &&
_laserScanRaw.empty() &&
_laserScanCompressed.empty() &&
_laserScanRaw.isEmpty() &&
_laserScanCompressed.isEmpty() &&
_cameraModels.size() == 0 &&
!_stereoCameraModel.isValidForProjection() &&
_userDataRaw.empty() &&
_userDataCompressed.empty() &&
_keypoints.size() == 0 &&
_descriptors.empty());
_descriptors.empty() &&
imu_.empty());
}
int id() const {return _id;}
void setId(int id) {_id = id;}
double stamp() const {return _stamp;}
void setStamp(double stamp) {_stamp = stamp;}
const LaserScanInfo & laserScanInfo() const {return _laserScanInfo;}
const cv::Mat & imageCompressed() const {return _imageCompressed;}
const cv::Mat & depthOrRightCompressed() const {return _depthOrRightCompressed;}
const cv::Mat & laserScanCompressed() const {return _laserScanCompressed;}
const LaserScan & laserScanCompressed() const {return _laserScanCompressed;}
const cv::Mat & imageRaw() const {return _imageRaw;}
const cv::Mat & depthOrRightRaw() const {return _depthOrRightRaw;}
const cv::Mat & laserScanRaw() const {return _laserScanRaw;}
const LaserScan & laserScanRaw() const {return _laserScanRaw;}
void setImageRaw(const cv::Mat & imageRaw) {_imageRaw = imageRaw;}
void setDepthOrRightRaw(const cv::Mat & depthOrImageRaw) {_depthOrRightRaw =depthOrImageRaw;}
void setLaserScanRaw(const cv::Mat & laserScanRaw, const LaserScanInfo & info) {_laserScanRaw =laserScanRaw;_laserScanInfo = info;}
void setLaserScanRaw(const LaserScan & laserScanRaw) {_laserScanRaw =laserScanRaw;}
void setCameraModel(const CameraModel & model) {_cameraModels.clear(); _cameraModels.push_back(model);}
void setCameraModels(const std::vector<CameraModel> & models) {_cameraModels = models;}
void setStereoCameraModel(const StereoCameraModel & stereoCameraModel) {_stereoCameraModel = stereoCameraModel;}
@@ -172,17 +176,19 @@ public:
void uncompressData(
cv::Mat * imageRaw,
cv::Mat * depthOrRightRaw,
cv::Mat * laserScanRaw = 0,
LaserScan * laserScanRaw = 0,
cv::Mat * userDataRaw = 0,
cv::Mat * groundCellsRaw = 0,
cv::Mat * obstacleCellsRaw = 0);
cv::Mat * obstacleCellsRaw = 0,
cv::Mat * emptyCellsRaw = 0);
void uncompressDataConst(
cv::Mat * imageRaw,
cv::Mat * depthOrRightRaw,
cv::Mat * laserScanRaw = 0,
LaserScan * laserScanRaw = 0,
cv::Mat * userDataRaw = 0,
cv::Mat * groundCellsRaw = 0,
cv::Mat * obstacleCellsRaw = 0) const;
cv::Mat * obstacleCellsRaw = 0,
cv::Mat * emptyCellsRaw = 0) const;
const std::vector<CameraModel> & cameraModels() const {return _cameraModels;}
const StereoCameraModel & stereoCameraModel() const {return _stereoCameraModel;}
@@ -203,6 +209,7 @@ public:
void setOccupancyGrid(
const cv::Mat & ground,
const cv::Mat & obstacles,
const cv::Mat & empty,
float cellSize,
const cv::Point3f & viewPoint);
// remove raw occupancy grids
@@ -211,6 +218,8 @@ public:
const cv::Mat & gridGroundCellsCompressed() const {return _groundCellsCompressed;}
const cv::Mat & gridObstacleCellsRaw() const {return _obstacleCellsRaw;}
const cv::Mat & gridObstacleCellsCompressed() const {return _obstacleCellsCompressed;}
const cv::Mat & gridEmptyCellsRaw() const {return _emptyCellsRaw;}
const cv::Mat & gridEmptyCellsCompressed() const {return _emptyCellsCompressed;}
float gridCellSize() const {return _cellSize;}
const cv::Point3f & gridViewPoint() const {return _viewPoint;}
@@ -232,7 +241,16 @@ public:
}
const GPS & gps() const {return gps_;}
void setIMU(const IMU & imu)
{
imu_ = imu;
}
const IMU & imu() const {return imu_;}
long getMemoryUsed() const; // Return memory usage in Bytes
void clearCompressedData() {_imageCompressed=cv::Mat(); _depthOrRightCompressed=cv::Mat(); _laserScanCompressed.clear(); _userDataCompressed=cv::Mat();}
bool isPointVisibleFromCameras(const cv::Point3f & pt) const; // assuming point is in robot frame
private:
int _id;
@@ -240,17 +258,15 @@ private:
cv::Mat _imageCompressed; // compressed image
cv::Mat _depthOrRightCompressed; // compressed image
cv::Mat _laserScanCompressed; // compressed data
LaserScan _laserScanCompressed; // compressed data
cv::Mat _imageRaw; // CV_8UC1 or CV_8UC3
cv::Mat _depthOrRightRaw; // depth CV_16UC1 or CV_32FC1, right image CV_8UC1
cv::Mat _laserScanRaw; // CV_32FC2 or CV_32FC3
LaserScan _laserScanRaw;
std::vector<CameraModel> _cameraModels;
StereoCameraModel _stereoCameraModel;
LaserScanInfo _laserScanInfo;
// user data
cv::Mat _userDataCompressed; // compressed data
cv::Mat _userDataRaw;
@@ -258,8 +274,10 @@ private:
// occupancy grid
cv::Mat _groundCellsCompressed;
cv::Mat _obstacleCellsCompressed;
cv::Mat _emptyCellsCompressed;
cv::Mat _groundCellsRaw;
cv::Mat _obstacleCellsRaw;
cv::Mat _emptyCellsRaw;
float _cellSize;
cv::Point3f _viewPoint;
@@ -274,6 +292,8 @@ private:
cv::Mat globalPoseCovariance_; // 6x6 double
GPS gps_;
IMU imu_;
};
}
+2
View File
@@ -134,6 +134,8 @@ public:
SensorData & sensorData() {return _sensorData;}
const SensorData & sensorData() const {return _sensorData;}
long getMemoryUsed(bool withSensorData=true) const; // Return memory usage in Bytes
private:
int _id;
int _mapId;
+30 -3
View File
@@ -64,8 +64,11 @@ class RTABMAP_EXP Statistics
RTABMAP_STATS(Loop, Visual_matches,);
RTABMAP_STATS(Loop, Last_id,);
RTABMAP_STATS(Loop, Optimization_max_error, m);
RTABMAP_STATS(Loop, Optimization_max_error_ratio, );
RTABMAP_STATS(Loop, Optimization_error, );
RTABMAP_STATS(Loop, Optimization_iterations, );
RTABMAP_STATS(Loop, Linear_variance,);
RTABMAP_STATS(Loop, Angular_variance,);
RTABMAP_STATS(Proximity, Time_detections,);
RTABMAP_STATS(Proximity, Space_last_detection_id,);
@@ -98,13 +101,17 @@ class RTABMAP_EXP Statistics
RTABMAP_STATS(Memory, Rehearsal_merged,);
RTABMAP_STATS(Memory, Local_graph_size,);
RTABMAP_STATS(Memory, Small_movement,);
RTABMAP_STATS(Memory, Fast_movement,);
RTABMAP_STATS(Memory, Odometry_variance_ang,);
RTABMAP_STATS(Memory, Odometry_variance_lin,);
RTABMAP_STATS(Memory, Distance_travelled, m);
RTABMAP_STATS(Memory, RAM_usage, MB);
RTABMAP_STATS(Memory, Triangulated_points, );
RTABMAP_STATS(Timing, Memory_update, ms);
RTABMAP_STATS(Timing, Neighbor_link_refining, ms);
RTABMAP_STATS(Timing, Proximity_by_time, ms);
RTABMAP_STATS(Timing, Proximity_by_space_visual, ms);
RTABMAP_STATS(Timing, Proximity_by_space, ms);
RTABMAP_STATS(Timing, Cleaning_neighbors, ms);
RTABMAP_STATS(Timing, Reactivation, ms);
@@ -128,20 +135,33 @@ class RTABMAP_EXP Statistics
RTABMAP_STATS(TimingMem, Subpixel, ms);
RTABMAP_STATS(TimingMem, Stereo_correspondences, ms);
RTABMAP_STATS(TimingMem, Descriptors_extraction, ms);
RTABMAP_STATS(TimingMem, Rectification, ms);
RTABMAP_STATS(TimingMem, Keypoints_3D, ms);
RTABMAP_STATS(TimingMem, Keypoints_3D_motion, ms);
RTABMAP_STATS(TimingMem, Joining_dictionary_update, ms);
RTABMAP_STATS(TimingMem, Add_new_words, ms);
RTABMAP_STATS(TimingMem, Compressing_data, ms);
RTABMAP_STATS(TimingMem, Post_decimation, ms);
RTABMAP_STATS(TimingMem, Scan_downsampling, ms);
RTABMAP_STATS(TimingMem, Scan_voxel_filtering, ms);
RTABMAP_STATS(TimingMem, Scan_normals, ms);
RTABMAP_STATS(TimingMem, Scan_filtering, ms);
RTABMAP_STATS(TimingMem, Occupancy_grid, ms);
RTABMAP_STATS(Keypoint, Dictionary_size, words);
RTABMAP_STATS(Keypoint, Indexed_words, words);
RTABMAP_STATS(Keypoint, Index_memory_usage, KB);
RTABMAP_STATS(Gt, Translational_rmse, m);
RTABMAP_STATS(Gt, Translational_mean, m);
RTABMAP_STATS(Gt, Translational_median, m);
RTABMAP_STATS(Gt, Translational_std, m);
RTABMAP_STATS(Gt, Translational_min, m);
RTABMAP_STATS(Gt, Translational_max, m);
RTABMAP_STATS(Gt, Rotational_rmse, deg);
RTABMAP_STATS(Gt, Rotational_mean, deg);
RTABMAP_STATS(Gt, Rotational_median, deg);
RTABMAP_STATS(Gt, Rotational_std, deg);
RTABMAP_STATS(Gt, Rotational_min, deg);
RTABMAP_STATS(Gt, Rotational_max, deg);
public:
static const std::map<std::string, float> & defaultData();
static std::string serializeData(const std::map<std::string, float> & data);
@@ -167,6 +187,7 @@ public:
void setConstraints(const std::multimap<int, Link> & constraints) {_constraints = constraints;}
void setMapCorrection(const Transform & mapCorrection) {_mapCorrection = mapCorrection;}
void setLoopClosureTransform(const Transform & loopClosureTransform) {_loopClosureTransform = loopClosureTransform;}
void setLocalizationCovariance(const cv::Mat & covariance) {_localizationCovariance = covariance;}
void setWeights(const std::map<int, int> & weights) {_weights = weights;}
void setPosterior(const std::map<int, float> & posterior) {_posterior = posterior;}
void setLikelihood(const std::map<int, float> & likelihood) {_likelihood = likelihood;}
@@ -174,6 +195,7 @@ public:
void setLocalPath(const std::vector<int> & localPath) {_localPath=localPath;}
void setCurrentGoalId(int goal) {_currentGoalId=goal;}
void setReducedIds(const std::map<int, int> & reducedIds) {_reducedIds = reducedIds;}
void setWmState(const std::vector<int> & state) {_wmState = state;}
// getters
bool extended() const {return _extended;}
@@ -188,6 +210,7 @@ public:
const std::multimap<int, Link> & constraints() const {return _constraints;}
const Transform & mapCorrection() const {return _mapCorrection;}
const Transform & loopClosureTransform() const {return _loopClosureTransform;}
const cv::Mat & localizationCovariance() const {return _localizationCovariance;}
const std::map<int, int> & weights() const {return _weights;}
const std::map<int, float> & posterior() const {return _posterior;}
const std::map<int, float> & likelihood() const {return _likelihood;}
@@ -195,6 +218,7 @@ public:
const std::vector<int> & localPath() const {return _localPath;}
int currentGoalId() const {return _currentGoalId;}
const std::map<int, int> & reducedIds() const {return _reducedIds;}
const std::vector<int> & wmState() const {return _wmState;}
const std::map<std::string, float> & data() const {return _data;}
@@ -212,6 +236,7 @@ private:
std::multimap<int, Link> _constraints;
Transform _mapCorrection;
Transform _loopClosureTransform;
cv::Mat _localizationCovariance;
std::map<int, int> _weights;
std::map<int, float> _posterior;
@@ -223,6 +248,8 @@ private:
std::map<int, int> _reducedIds;
std::vector<int> _wmState;
// Format for statistics (Plottable statistics must go in that map) :
// {"Group/Name/Unit", value}
// Example : {"Timing/Total time/ms", 500.0f}
+4 -4
View File
@@ -53,8 +53,8 @@ public:
cv::Size winSize() const {return cv::Size(winWidth_, winHeight_);}
int iterations() const {return iterations_;}
int maxLevel() const {return maxLevel_;}
int minDisparity() const {return minDisparity_;}
int maxDisparity() const {return maxDisparity_;}
float minDisparity() const {return minDisparity_;}
float maxDisparity() const {return maxDisparity_;}
bool winSSD() const {return winSSD_;}
private:
@@ -62,8 +62,8 @@ private:
int winHeight_;
int iterations_;
int maxLevel_;
int minDisparity_;
int maxDisparity_;
float minDisparity_;
float maxDisparity_;
bool winSSD_;
};
@@ -86,6 +86,7 @@ public:
bool isValidForRectification() const {return left_.isValidForRectification() && right_.isValidForRectification();}
void initRectificationMap() {left_.initRectificationMap(); right_.initRectificationMap();}
bool isRectificationMapInitialized() {return left_.isRectificationMapInitialized() && right_.isRectificationMapInitialized();}
void setName(const std::string & name, const std::string & leftSuffix = "left", const std::string & rightSuffix = "right");
const std::string & name() const {return name_;}
+3
View File
@@ -56,6 +56,8 @@ public:
// x,y, theta
Transform(float x, float y, float theta);
Transform clone() const;
float r11() const {return data()[0];}
float r12() const {return data()[1];}
float r13() const {return data()[2];}
@@ -112,6 +114,7 @@ public:
float getDistance(const Transform & t) const;
float getDistanceSquared(const Transform & t) const;
Transform interpolate(float t, const Transform & other) const;
void normalizeRotation();
std::string prettyPrint() const;
Transform operator*(const Transform & t) const;
@@ -109,6 +109,7 @@ protected:
private:
bool _incrementalDictionary;
bool _incrementalFlann;
float _rebalancingFactor;
float _nndrRatio;
std::string _dictionaryPath; // a pre-computed dictionary (.txt)
bool _newWordsComparedTogether;
@@ -45,14 +45,34 @@ typename pcl::PointCloud<PointT>::Ptr OccupancyGrid::segmentCloud(
pcl::IndicesPtr * flatObstacles) const
{
typename pcl::PointCloud<PointT>::Ptr cloud(new pcl::PointCloud<PointT>);
// voxelize to grid cell size
cloud = util3d::voxelize(cloudIn, indicesIn, cellSize_);
pcl::IndicesPtr indices(new std::vector<int>);
indices->resize(cloud->size());
for(unsigned int i=0; i<indices->size(); ++i)
if(preVoxelFiltering_)
{
indices->at(i) = i;
// voxelize to grid cell size
cloud = util3d::voxelize(cloudIn, indicesIn, cellSize_);
indices->resize(cloud->size());
for(unsigned int i=0; i<indices->size(); ++i)
{
indices->at(i) = i;
}
}
else
{
cloud = cloudIn;
if(indicesIn->empty() && cloud->is_dense)
{
indices->resize(cloud->size());
for(unsigned int i=0; i<indices->size(); ++i)
{
indices->at(i) = i;
}
}
else
{
indices = indicesIn;
}
}
// add pose rotation without yaw
@@ -83,8 +83,6 @@ void segmentObstaclesFromGround(
normalKSearch,
viewPoint);
UDEBUG("cloud=%d, indices=%d flatSurfaces=%d", (int)cloud->size(), (int)indices->size(), (int)flatSurfaces->size());
if(segmentFlatObstacles && flatSurfaces->size())
{
int biggestFlatSurfaceIndex;
@@ -95,7 +93,6 @@ void segmentObstaclesFromGround(
minClusterSize,
std::numeric_limits<int>::max(),
&biggestFlatSurfaceIndex);
UDEBUG("clusteredFlatSurfaces=%d", (int)clusteredFlatSurfaces.size());
// cluster all surfaces for which the centroid is in the Z-range of the bigger surface
if(clusteredFlatSurfaces.size())
@@ -112,8 +109,7 @@ void segmentObstaclesFromGround(
{
Eigen::Vector4f centroid(0,0,0,1);
pcl::compute3DCentroid(*cloud, *clusteredFlatSurfaces.at(i), centroid);
if(centroid[2] >= min[2]-0.01 &&
(centroid[2] <= max[2]+0.01 || (maxGroundHeight!=0.0f && centroid[2] <= maxGroundHeight+0.01))) // epsilon
if(maxGroundHeight==0.0f || centroid[2] <= maxGroundHeight || centroid[2] <= max[2]) // epsilon
{
ground = util3d::concatenate(ground, clusteredFlatSurfaces.at(i));
}
@@ -140,8 +136,6 @@ void segmentObstaclesFromGround(
ground = flatSurfaces;
}
UDEBUG("ground=%d", (int)ground->size());
if(ground->size() != cloud->size())
{
// Remove ground
+3 -3
View File
@@ -54,8 +54,8 @@ std::vector<cv::Point2f> RTABMAP_EXP calcStereoCorrespondences(
cv::Size winSize = cv::Size(6,3),
int maxLevel = 3,
int iterations = 5,
int minDisparity = 0,
int maxDisparity = 64,
float minDisparity = 0.0f,
float maxDisparity = 64.0f,
bool ssdApproach = true); // SSD by default, otherwise it is SAD
// exactly as cv::calcOpticalFlowPyrLK but it should be called with pyramid (from cv::buildOpticalFlowPyramid()) and delta drops the y error.
@@ -107,7 +107,7 @@ float RTABMAP_EXP getDepth(
const cv::Mat & depthImage,
float x, float y,
bool smoothing,
float maxZError = 0.02f,
float depthErrorRatio = 0.02f, //ratio
bool estWithNeighborsIfNull = false);
cv::Rect RTABMAP_EXP computeRoi(const cv::Mat & image, const std::string & roiRatios);
+74 -41
View File
@@ -72,7 +72,13 @@ pcl::PointXYZ RTABMAP_EXP projectDepthTo3D(
float cx, float cy,
float fx, float fy,
bool smoothing,
float maxZError = 0.02f);
float depthErrorRatio = 0.02f);
Eigen::Vector3f RTABMAP_EXP projectDepthTo3DRay(
const cv::Size & imageSize,
float x, float y,
float cx, float cy,
float fx, float fy);
RTABMAP_DEPRECATED (pcl::PointCloud<pcl::PointXYZ>::Ptr RTABMAP_EXP cloudFromDepth(
const cv::Mat & imageDepth,
@@ -190,41 +196,68 @@ pcl::PointCloud<pcl::PointXYZ> RTABMAP_EXP laserScanFromDepthImages(
float maxDepth,
float minDepth);
LaserScan RTABMAP_EXP laserScanFromPointCloud(const pcl::PCLPointCloud2 & cloud, bool filterNaNs = true);
// return CV_32FC3 (x,y,z)
cv::Mat RTABMAP_EXP laserScanFromPointCloud(const pcl::PointCloud<pcl::PointXYZ> & cloud, const Transform & transform = Transform());
cv::Mat RTABMAP_EXP laserScanFromPointCloud(const pcl::PointCloud<pcl::PointXYZ> & cloud, const Transform & transform = Transform(), bool filterNaNs = true);
cv::Mat RTABMAP_EXP laserScanFromPointCloud(const pcl::PointCloud<pcl::PointXYZ> & cloud, const pcl::IndicesPtr & indices, const Transform & transform = Transform(), bool filterNaNs = true);
// return CV_32FC6 (x,y,z,normal_x,normal_y,normal_z)
cv::Mat RTABMAP_EXP laserScanFromPointCloud(const pcl::PointCloud<pcl::PointNormal> & cloud, const Transform & transform = Transform());
cv::Mat RTABMAP_EXP laserScanFromPointCloud(const pcl::PointCloud<pcl::PointXYZ> & cloud, const pcl::PointCloud<pcl::Normal> & normals, const Transform & transform = Transform());
cv::Mat RTABMAP_EXP laserScanFromPointCloud(const pcl::PointCloud<pcl::PointNormal> & cloud, const Transform & transform = Transform(), bool filterNaNs = true);
cv::Mat RTABMAP_EXP laserScanFromPointCloud(const pcl::PointCloud<pcl::PointNormal> & cloud, const pcl::IndicesPtr & indices, const Transform & transform = Transform(), bool filterNaNs = true);
cv::Mat RTABMAP_EXP laserScanFromPointCloud(const pcl::PointCloud<pcl::PointXYZ> & cloud, const pcl::PointCloud<pcl::Normal> & normals, const Transform & transform = Transform(), bool filterNaNs = true);
// return CV_32FC4 (x,y,z,rgb)
cv::Mat RTABMAP_EXP laserScanFromPointCloud(const pcl::PointCloud<pcl::PointXYZRGB> & cloud, const Transform & transform = Transform());
cv::Mat RTABMAP_EXP laserScanFromPointCloud(const pcl::PointCloud<pcl::PointXYZRGB> & cloud, const Transform & transform = Transform(), bool filterNaNs = true);
cv::Mat RTABMAP_EXP laserScanFromPointCloud(const pcl::PointCloud<pcl::PointXYZRGB> & cloud, const pcl::IndicesPtr & indices, const Transform & transform = Transform(), bool filterNaNs = true);
// return CV_32FC4 (x,y,z,I)
cv::Mat RTABMAP_EXP laserScanFromPointCloud(const pcl::PointCloud<pcl::PointXYZI> & cloud, const Transform & transform = Transform(), bool filterNaNs = true);
cv::Mat RTABMAP_EXP laserScanFromPointCloud(const pcl::PointCloud<pcl::PointXYZI> & cloud, const pcl::IndicesPtr & indices, const Transform & transform = Transform(), bool filterNaNs = true);
// return CV_32FC7 (x,y,z,rgb,normal_x,normal_y,normal_z)
cv::Mat RTABMAP_EXP laserScanFromPointCloud(const pcl::PointCloud<pcl::PointXYZRGB> & cloud, const pcl::PointCloud<pcl::Normal> & normals, const Transform & transform = Transform());
// return CV_32FC7 (x,y,z,rgb,normal_x,normal_y,normal_z)
cv::Mat RTABMAP_EXP laserScanFromPointCloud(const pcl::PointCloud<pcl::PointXYZRGBNormal> & cloud, const Transform & transform = Transform());
cv::Mat RTABMAP_EXP laserScanFromPointCloud(const pcl::PointCloud<pcl::PointXYZRGB> & cloud, const pcl::PointCloud<pcl::Normal> & normals, const Transform & transform = Transform(), bool filterNaNs = true);
cv::Mat RTABMAP_EXP laserScanFromPointCloud(const pcl::PointCloud<pcl::PointXYZRGBNormal> & cloud, const Transform & transform = Transform(), bool filterNaNs = true);
cv::Mat RTABMAP_EXP laserScanFromPointCloud(const pcl::PointCloud<pcl::PointXYZRGBNormal> & cloud, const pcl::IndicesPtr & indices, const Transform & transform = Transform(), bool filterNaNs = true);
// return CV_32FC7 (x,y,z,I,normal_x,normal_y,normal_z)
cv::Mat RTABMAP_EXP laserScanFromPointCloud(const pcl::PointCloud<pcl::PointXYZI> & cloud, const pcl::PointCloud<pcl::Normal> & normals, const Transform & transform = Transform(), bool filterNaNs = true);
cv::Mat RTABMAP_EXP laserScanFromPointCloud(const pcl::PointCloud<pcl::PointXYZINormal> & cloud, const Transform & transform = Transform(), bool filterNaNs = true);
// return CV_32FC2 (x,y)
cv::Mat RTABMAP_EXP laserScan2dFromPointCloud(const pcl::PointCloud<pcl::PointXYZ> & cloud, const Transform & transform = Transform());
cv::Mat RTABMAP_EXP laserScan2dFromPointCloud(const pcl::PointCloud<pcl::PointXYZ> & cloud, const Transform & transform = Transform(), bool filterNaNs = true);
// return CV_32FC3 (x,y,I)
cv::Mat RTABMAP_EXP laserScan2dFromPointCloud(const pcl::PointCloud<pcl::PointXYZI> & cloud, const Transform & transform = Transform(), bool filterNaNs = true);
// return CV_32FC5 (x,y,normal_x, normal_y, normal_z)
cv::Mat RTABMAP_EXP laserScan2dFromPointCloud(const pcl::PointCloud<pcl::PointNormal> & cloud, const Transform & transform = Transform());
cv::Mat RTABMAP_EXP laserScan2dFromPointCloud(const pcl::PointCloud<pcl::PointXYZ> & cloud, const pcl::PointCloud<pcl::Normal> & normals, const Transform & transform = Transform());
// For laserScan of type CV_32FC2, z is set to null.
pcl::PointCloud<pcl::PointXYZ>::Ptr RTABMAP_EXP laserScanToPointCloud(const cv::Mat & laserScan, const Transform & transform = Transform());
// For laserScan of type CV_32FC2, CV_32FC3 and CV_32FC4, normals are set to null.
pcl::PointCloud<pcl::PointNormal>::Ptr RTABMAP_EXP laserScanToPointCloudNormal(const cv::Mat & laserScan, const Transform & transform = Transform());
// For laserScan of type CV_32FC2, CV_32FC3 and CV_32FC6, rgb is set to default r,g,b parameters.
pcl::PointCloud<pcl::PointXYZRGB>::Ptr RTABMAP_EXP laserScanToPointCloudRGB(const cv::Mat & laserScan, const Transform & transform = Transform(), unsigned char r = 255, unsigned char g = 255, unsigned char b = 255);
// For laserScan of type CV_32FC2, CV_32FC3 and CV_32FC6, rgb is set to default r,g,b parameters.
// For laserScan of type CV_32FC2, CV_32FC3 and CV_32FC4, normals are set to null.
pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr RTABMAP_EXP laserScanToPointCloudRGBNormal(const cv::Mat & laserScan, const Transform & transform = Transform(), unsigned char r = 255, unsigned char g = 255, unsigned char b = 255);
cv::Mat RTABMAP_EXP laserScan2dFromPointCloud(const pcl::PointCloud<pcl::PointNormal> & cloud, const Transform & transform = Transform(), bool filterNaNs = true);
cv::Mat RTABMAP_EXP laserScan2dFromPointCloud(const pcl::PointCloud<pcl::PointXYZ> & cloud, const pcl::PointCloud<pcl::Normal> & normals, const Transform & transform = Transform(), bool filterNaNs = true);
// return CV_32FC6 (x,y,I,normal_x, normal_y, normal_z)
cv::Mat RTABMAP_EXP laserScan2dFromPointCloud(const pcl::PointCloud<pcl::PointXYZINormal> & cloud, const Transform & transform = Transform(), bool filterNaNs = true);
cv::Mat RTABMAP_EXP laserScan2dFromPointCloud(const pcl::PointCloud<pcl::PointXYZI> & cloud, const pcl::PointCloud<pcl::Normal> & normals, const Transform & transform = Transform(), bool filterNaNs = true);
// For laserScan of type CV_32FC2, z is set to null.
pcl::PointXYZ RTABMAP_EXP laserScanToPoint(const cv::Mat & laserScan, int index);
// For laserScan of type CV_32FC2, CV_32FC3 and CV_32FC4, normals are set to null.
pcl::PointNormal RTABMAP_EXP laserScanToPointNormal(const cv::Mat & laserScan, int index);
// For laserScan of type CV_32FC2, CV_32FC3 and CV_32FC6, rgb is set to default r,g,b parameters.
pcl::PointXYZRGB RTABMAP_EXP laserScanToPointRGB(const cv::Mat & laserScan, int index, unsigned char r = 255, unsigned char g = 255, unsigned char b = 255);
// For laserScan of type CV_32FC2, CV_32FC3 and CV_32FC6, rgb is set to default r,g,b parameters.
// For laserScan of type CV_32FC2, CV_32FC3 and CV_32FC4, normals are set to null.
pcl::PointXYZRGBNormal RTABMAP_EXP laserScanToPointRGBNormal(const cv::Mat & laserScan, int index, unsigned char r, unsigned char g, unsigned char b);
pcl::PCLPointCloud2::Ptr RTABMAP_EXP laserScanToPointCloud2(const LaserScan & laserScan, const Transform & transform = Transform());
// For 2d laserScan, z is set to null.
pcl::PointCloud<pcl::PointXYZ>::Ptr RTABMAP_EXP laserScanToPointCloud(const LaserScan & laserScan, const Transform & transform = Transform());
// For laserScan without normals, normals are set to null.
pcl::PointCloud<pcl::PointNormal>::Ptr RTABMAP_EXP laserScanToPointCloudNormal(const LaserScan & laserScan, const Transform & transform = Transform());
// For laserScan without rgb, rgb is set to default r,g,b parameters.
pcl::PointCloud<pcl::PointXYZRGB>::Ptr RTABMAP_EXP laserScanToPointCloudRGB(const LaserScan & laserScan, const Transform & transform = Transform(), unsigned char r = 255, unsigned char g = 255, unsigned char b = 255);
// For laserScan without intensity, intensity is set to intensity parameter.
pcl::PointCloud<pcl::PointXYZI>::Ptr RTABMAP_EXP laserScanToPointCloudI(const LaserScan & laserScan, const Transform & transform = Transform(), float intensity = 0.0f);
// For laserScan without rgb, rgb is set to default r,g,b parameters.
// For laserScan without normals, normals are set to null.
pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr RTABMAP_EXP laserScanToPointCloudRGBNormal(const LaserScan & laserScan, const Transform & transform = Transform(), unsigned char r = 255, unsigned char g = 255, unsigned char b = 255);
// For laserScan without intensity, intensity is set to default intensity parameter.
// For laserScan without normals, normals are set to null.
pcl::PointCloud<pcl::PointXYZINormal>::Ptr RTABMAP_EXP laserScanToPointCloudINormal(const LaserScan & laserScan, const Transform & transform = Transform(), float intensity = 0.0f);
// For 2d laserScan, z is set to null.
pcl::PointXYZ RTABMAP_EXP laserScanToPoint(const LaserScan & laserScan, int index);
// For laserScan without normals, normals are set to null.
pcl::PointNormal RTABMAP_EXP laserScanToPointNormal(const LaserScan & laserScan, int index);
// For laserScan without rgb, rgb is set to default r,g,b parameters.
pcl::PointXYZRGB RTABMAP_EXP laserScanToPointRGB(const LaserScan & laserScan, int index, unsigned char r = 255, unsigned char g = 255, unsigned char b = 255);
// For laserScan without intensity, intensity is set to intensity parameter.
pcl::PointXYZI RTABMAP_EXP laserScanToPointI(const LaserScan & laserScan, int index, float intensity);
// For laserScan without rgb, rgb is set to default r,g,b parameters.
// For laserScan without normals, normals are set to null.
pcl::PointXYZRGBNormal RTABMAP_EXP laserScanToPointRGBNormal(const LaserScan & laserScan, int index, unsigned char r, unsigned char g, unsigned char b);
// For laserScan without intensity, intensity is set to default intensity parameter.
// For laserScan without normals, normals are set to null.
pcl::PointXYZINormal RTABMAP_EXP laserScanToPointINormal(const LaserScan & laserScan, int index, float intensity);
void RTABMAP_EXP getMinMax3D(const cv::Mat & laserScan, cv::Point3f & min, cv::Point3f & max);
void RTABMAP_EXP getMinMax3D(const cv::Mat & laserScan, pcl::PointXYZ & min, pcl::PointXYZ & max);
@@ -309,22 +342,22 @@ void RTABMAP_EXP savePCDWords(
const std::multimap<int, cv::Point3f> & words,
const Transform & transform = Transform::getIdentity());
pcl::PointCloud<pcl::PointXYZ>::Ptr RTABMAP_EXP loadBINCloud(const std::string & fileName, int dim);
/**
* Assume KITTI velodyne format
* Return scan 4 channels (format=XYZI).
*/
cv::Mat RTABMAP_EXP loadBINScan(const std::string & fileName);
pcl::PointCloud<pcl::PointXYZ>::Ptr RTABMAP_EXP loadBINCloud(const std::string & fileName);
RTABMAP_DEPRECATED(pcl::PointCloud<pcl::PointXYZ>::Ptr RTABMAP_EXP loadBINCloud(const std::string & fileName, int dim), "Use interface without dim argument.");
// Load *.pcd, *.ply or *.bin (KITTI format) with optional filtering.
// If normals are computed (normalsK>0), the returned scan type is CV_32FC6 instead of CV_32FC3
cv::Mat RTABMAP_EXP loadScan(
// Load *.pcd, *.ply or *.bin (KITTI format).
LaserScan RTABMAP_EXP loadScan(const std::string & path);
RTABMAP_DEPRECATED(pcl::PointCloud<pcl::PointXYZ>::Ptr RTABMAP_EXP loadCloud(
const std::string & path,
const Transform & transform = Transform::getIdentity(),
int downsampleStep = 1,
float voxelSize = 0.0f,
int normalsK = 0);
pcl::PointCloud<pcl::PointXYZ>::Ptr RTABMAP_EXP loadCloud(
const std::string & path,
const Transform & transform = Transform::getIdentity(),
int downsampleStep = 1,
float voxelSize = 0.0f);
float voxelSize = 0.0f), "Use loadScan() instead.");
} // namespace util3d
} // namespace rtabmap
+134 -3
View File
@@ -30,11 +30,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <rtabmap/core/RtabmapExp.h>
#include <rtabmap/core/Transform.h>
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl/pcl_base.h>
#include <pcl/ModelCoefficients.h>
#include <rtabmap/core/LaserScan.h>
namespace rtabmap
{
@@ -42,8 +42,29 @@ namespace rtabmap
namespace util3d
{
cv::Mat RTABMAP_EXP downsample(
const cv::Mat & cloud,
/**
* Do some filtering approaches and try to
* avoid converting between pcl and opencv and to avoid not needed
* operations like computing normals while the scan has already
* normals and voxel filtering is not used.
*/
LaserScan RTABMAP_EXP commonFiltering(
const LaserScan & scan,
int downsamplingStep,
float rangeMin = 0.0f,
float rangeMax = 0.0f,
float voxelSize = 0.0f,
int normalK = 0,
float normalRadius = 0.0f,
bool forceGroundNormalsUp = false);
LaserScan RTABMAP_EXP rangeFiltering(
const LaserScan & scan,
float rangeMin,
float rangeMax);
LaserScan RTABMAP_EXP downsample(
const LaserScan & cloud,
int step);
pcl::PointCloud<pcl::PointXYZ>::Ptr RTABMAP_EXP downsample(
const pcl::PointCloud<pcl::PointXYZ>::Ptr & cloud,
@@ -51,6 +72,12 @@ pcl::PointCloud<pcl::PointXYZ>::Ptr RTABMAP_EXP downsample(
pcl::PointCloud<pcl::PointXYZRGB>::Ptr RTABMAP_EXP downsample(
const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloud,
int step);
pcl::PointCloud<pcl::PointNormal>::Ptr RTABMAP_EXP downsample(
const pcl::PointCloud<pcl::PointNormal>::Ptr & cloud,
int step);
pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr RTABMAP_EXP downsample(
const pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr & cloud,
int step);
pcl::PointCloud<pcl::PointXYZ>::Ptr RTABMAP_EXP voxelize(
const pcl::PointCloud<pcl::PointXYZ>::Ptr & cloud,
@@ -68,6 +95,14 @@ pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr RTABMAP_EXP voxelize(
const pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr & cloud,
const pcl::IndicesPtr & indices,
float voxelSize);
pcl::PointCloud<pcl::PointXYZI>::Ptr RTABMAP_EXP voxelize(
const pcl::PointCloud<pcl::PointXYZI>::Ptr & cloud,
const pcl::IndicesPtr & indices,
float voxelSize);
pcl::PointCloud<pcl::PointXYZINormal>::Ptr RTABMAP_EXP voxelize(
const pcl::PointCloud<pcl::PointXYZINormal>::Ptr & cloud,
const pcl::IndicesPtr & indices,
float voxelSize);
pcl::PointCloud<pcl::PointXYZ>::Ptr RTABMAP_EXP voxelize(
const pcl::PointCloud<pcl::PointXYZ>::Ptr & cloud,
float voxelSize);
@@ -80,6 +115,12 @@ pcl::PointCloud<pcl::PointXYZRGB>::Ptr RTABMAP_EXP voxelize(
pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr RTABMAP_EXP voxelize(
const pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr & cloud,
float voxelSize);
pcl::PointCloud<pcl::PointXYZI>::Ptr RTABMAP_EXP voxelize(
const pcl::PointCloud<pcl::PointXYZI>::Ptr & cloud,
float voxelSize);
pcl::PointCloud<pcl::PointXYZINormal>::Ptr RTABMAP_EXP voxelize(
const pcl::PointCloud<pcl::PointXYZINormal>::Ptr & cloud,
float voxelSize);
inline pcl::PointCloud<pcl::PointXYZ>::Ptr uniformSampling(
const pcl::PointCloud<pcl::PointXYZ>::Ptr & cloud,
@@ -123,6 +164,34 @@ pcl::IndicesPtr RTABMAP_EXP passThrough(
float min,
float max,
bool negative = false);
pcl::IndicesPtr RTABMAP_EXP passThrough(
const pcl::PointCloud<pcl::PointXYZI>::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::PointNormal>::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::PointXYZRGBNormal>::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::PointXYZINormal>::Ptr & cloud,
const pcl::IndicesPtr & indices,
const std::string & axis,
float min,
float max,
bool negative = false);
pcl::PointCloud<pcl::PointXYZ>::Ptr RTABMAP_EXP passThrough(
const pcl::PointCloud<pcl::PointXYZ>::Ptr & cloud,
const std::string & axis,
@@ -135,6 +204,12 @@ pcl::PointCloud<pcl::PointXYZRGB>::Ptr RTABMAP_EXP passThrough(
float min,
float max,
bool negative = false);
pcl::PointCloud<pcl::PointXYZI>::Ptr RTABMAP_EXP passThrough(
const pcl::PointCloud<pcl::PointXYZI>::Ptr & cloud,
const std::string & axis,
float min,
float max,
bool negative = false);
pcl::PointCloud<pcl::PointNormal>::Ptr RTABMAP_EXP passThrough(
const pcl::PointCloud<pcl::PointNormal>::Ptr & cloud,
const std::string & axis,
@@ -147,6 +222,12 @@ pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr RTABMAP_EXP passThrough(
float min,
float max,
bool negative = false);
pcl::PointCloud<pcl::PointXYZINormal>::Ptr RTABMAP_EXP passThrough(
const pcl::PointCloud<pcl::PointXYZINormal>::Ptr & cloud,
const std::string & axis,
float min,
float max,
bool negative = false);
pcl::IndicesPtr RTABMAP_EXP cropBox(
const pcl::PointCloud<pcl::PointXYZ>::Ptr & cloud,
@@ -155,6 +236,13 @@ pcl::IndicesPtr RTABMAP_EXP cropBox(
const Eigen::Vector4f & max,
const Transform & transform = Transform::getIdentity(),
bool negative = false);
pcl::IndicesPtr RTABMAP_EXP cropBox(
const pcl::PointCloud<pcl::PointNormal>::Ptr & cloud,
const pcl::IndicesPtr & indices,
const Eigen::Vector4f & min,
const Eigen::Vector4f & max,
const Transform & transform = Transform::getIdentity(),
bool negative = false);
pcl::IndicesPtr RTABMAP_EXP cropBox(
const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloud,
const pcl::IndicesPtr & indices,
@@ -162,18 +250,37 @@ pcl::IndicesPtr RTABMAP_EXP cropBox(
const Eigen::Vector4f & max,
const Transform & transform = Transform::getIdentity(),
bool negative = false);
pcl::IndicesPtr RTABMAP_EXP cropBox(
const pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr & cloud,
const pcl::IndicesPtr & indices,
const Eigen::Vector4f & min,
const Eigen::Vector4f & max,
const Transform & transform = Transform::getIdentity(),
bool negative = false);
pcl::PointCloud<pcl::PointXYZ>::Ptr RTABMAP_EXP cropBox(
const pcl::PointCloud<pcl::PointXYZ>::Ptr & cloud,
const Eigen::Vector4f & min,
const Eigen::Vector4f & max,
const Transform & transform = Transform::getIdentity(),
bool negative = false);
pcl::PointCloud<pcl::PointNormal>::Ptr RTABMAP_EXP cropBox(
const pcl::PointCloud<pcl::PointNormal>::Ptr & cloud,
const Eigen::Vector4f & min,
const Eigen::Vector4f & max,
const Transform & transform = Transform::getIdentity(),
bool negative = false);
pcl::PointCloud<pcl::PointXYZRGB>::Ptr RTABMAP_EXP cropBox(
const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloud,
const Eigen::Vector4f & min,
const Eigen::Vector4f & max,
const Transform & transform = Transform::getIdentity(),
bool negative = false);
pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr RTABMAP_EXP cropBox(
const pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr & cloud,
const Eigen::Vector4f & min,
const Eigen::Vector4f & max,
const Transform & transform = Transform::getIdentity(),
bool negative = false);
//Note: This assumes a coordinate system where X is forward, * Y is up, and Z is right.
pcl::IndicesPtr RTABMAP_EXP frustumFiltering(
@@ -437,6 +544,13 @@ pcl::IndicesPtr RTABMAP_EXP normalFiltering(
const Eigen::Vector4f & normal,
int normalKSearch,
const Eigen::Vector4f & viewpoint);
pcl::IndicesPtr RTABMAP_EXP normalFiltering(
const pcl::PointCloud<pcl::PointNormal>::Ptr & cloud,
const pcl::IndicesPtr & indices,
float angleMax,
const Eigen::Vector4f & normal,
int normalKSearch,
const Eigen::Vector4f & viewpoint);
pcl::IndicesPtr RTABMAP_EXP normalFiltering(
const pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr & cloud,
const pcl::IndicesPtr & indices,
@@ -480,6 +594,13 @@ std::vector<pcl::IndicesPtr> RTABMAP_EXP extractClusters(
int minClusterSize,
int maxClusterSize = std::numeric_limits<int>::max(),
int * biggestClusterIndex = 0);
std::vector<pcl::IndicesPtr> RTABMAP_EXP extractClusters(
const pcl::PointCloud<pcl::PointNormal>::Ptr & cloud,
const pcl::IndicesPtr & indices,
float clusterTolerance,
int minClusterSize,
int maxClusterSize = std::numeric_limits<int>::max(),
int * biggestClusterIndex = 0);
std::vector<pcl::IndicesPtr> RTABMAP_EXP extractClusters(
const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloud,
const pcl::IndicesPtr & indices,
@@ -499,6 +620,10 @@ pcl::IndicesPtr RTABMAP_EXP extractIndices(
const pcl::PointCloud<pcl::PointXYZ>::Ptr & cloud,
const pcl::IndicesPtr & indices,
bool negative);
pcl::IndicesPtr RTABMAP_EXP extractIndices(
const pcl::PointCloud<pcl::PointNormal>::Ptr & cloud,
const pcl::IndicesPtr & indices,
bool negative);
pcl::IndicesPtr RTABMAP_EXP extractIndices(
const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloud,
const pcl::IndicesPtr & indices,
@@ -518,6 +643,12 @@ pcl::PointCloud<pcl::PointXYZRGB>::Ptr RTABMAP_EXP extractIndices(
const pcl::IndicesPtr & indices,
bool negative,
bool keepOrganized);
// PCL default lacks of pcl::PointNormal type support
//pcl::PointCloud<pcl::PointNormal>::Ptr RTABMAP_EXP extractIndices(
// const pcl::PointCloud<pcl::PointNormal>::Ptr & cloud,
// const pcl::IndicesPtr & indices,
// bool negative,
// bool keepOrganized);
pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr RTABMAP_EXP extractIndices(
const pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr & cloud,
const pcl::IndicesPtr & indices,
@@ -45,8 +45,8 @@ namespace util3d
RTABMAP_DEPRECATED(void RTABMAP_EXP occupancy2DFromLaserScan(
const cv::Mat & scan, // in /base_link frame
cv::Mat & ground,
cv::Mat & obstacles,
cv::Mat & empty,
cv::Mat & occupied,
float cellSize,
bool unknownSpaceFilled = false,
float scanMaxRange = 0.0f), "Use interface with \"viewpoint\" parameter to make sure the ray tracing origin is from the sensor and not the base.");
@@ -54,8 +54,8 @@ RTABMAP_DEPRECATED(void RTABMAP_EXP occupancy2DFromLaserScan(
RTABMAP_DEPRECATED(void RTABMAP_EXP occupancy2DFromLaserScan(
const cv::Mat & scan, // in /base_link frame
const cv::Point3f & viewpoint, // /base_link -> /base_scan
cv::Mat & ground,
cv::Mat & obstacles,
cv::Mat & empty,
cv::Mat & occupied,
float cellSize,
bool unknownSpaceFilled = false,
float scanMaxRange = 0.0f), "Use interface with scanHit/scanNoHit parameters: scanNoHit set to null matrix has the same functionality than this method.");
@@ -64,8 +64,8 @@ void RTABMAP_EXP occupancy2DFromLaserScan(
const cv::Mat & scanHit, // in /base_link frame
const cv::Mat & scanNoHit, // in /base_link frame
const cv::Point3f & viewpoint, // /base_link -> /base_scan
cv::Mat & ground,
cv::Mat & obstacles,
cv::Mat & empty,
cv::Mat & occupied,
float cellSize,
bool unknownSpaceFilled = false,
float scanMaxRange = 0.0f); // would be set if unknownSpaceFilled=true
@@ -114,7 +114,8 @@ void RTABMAP_EXP rayTrace(const cv::Point2i & start,
cv::Mat & grid,
bool stopOnObstacle);
cv::Mat RTABMAP_EXP convertMap2Image8U(const cv::Mat & map8S);
cv::Mat RTABMAP_EXP convertMap2Image8U(const cv::Mat & map8S, bool pgmFormat = false);
cv::Mat RTABMAP_EXP convertImage8U2Map(const cv::Mat & map8U, bool pgmFormat = false);
cv::Mat RTABMAP_EXP erodeMap(const cv::Mat & map);
@@ -63,6 +63,7 @@ void RTABMAP_EXP computeVarianceAndCorrespondences(
const pcl::PointCloud<pcl::PointNormal>::ConstPtr & cloudA,
const pcl::PointCloud<pcl::PointNormal>::ConstPtr & cloudB,
double maxCorrespondenceDistance,
double maxCorrespondenceAngle, // <=0 means that we don't care about normal angle difference
double & variance,
int & correspondencesOut);
void RTABMAP_EXP computeVarianceAndCorrespondences(
+64 -1
View File
@@ -38,6 +38,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <rtabmap/core/Transform.h>
#include <rtabmap/core/CameraModel.h>
#include <rtabmap/core/ProgressState.h>
#include <rtabmap/core/LaserScan.h>
#include <set>
#include <list>
@@ -174,6 +175,15 @@ pcl::TextureMesh::Ptr RTABMAP_EXP concatenateTextureMeshes(
void RTABMAP_EXP concatenateTextureMaterials(
pcl::TextureMesh & mesh, const cv::Size & imageSize, int textureSize, int maxTextures, float & scale, std::vector<bool> * materialsKept=0);
std::vector<std::vector<unsigned int> > RTABMAP_EXP convertPolygonsFromPCL(
const std::vector<pcl::Vertices> & polygons);
std::vector<std::vector<std::vector<unsigned int> > > RTABMAP_EXP convertPolygonsFromPCL(
const std::vector<std::vector<pcl::Vertices> > & polygons);
std::vector<pcl::Vertices> RTABMAP_EXP convertPolygonsToPCL(
const std::vector<std::vector<unsigned int> > & polygons);
std::vector<std::vector<pcl::Vertices> > RTABMAP_EXP convertPolygonsToPCL(
const std::vector<std::vector<std::vector<unsigned int> > > & tex_polygons);
pcl::TextureMesh::Ptr RTABMAP_EXP assembleTextureMesh(
const cv::Mat & cloudMat,
const std::vector<std::vector<std::vector<unsigned int> > > & polygons,
@@ -193,6 +203,24 @@ pcl::PolygonMesh::Ptr RTABMAP_EXP assemblePolygonMesh(
* Merge all textures in the mesh into "textureCount" textures of size "textureSize".
* @return merged textures corresponding to new materials set in TextureMesh (height=textureSize, width=textureSize*materials)
*/
cv::Mat RTABMAP_EXP mergeTextures(
pcl::TextureMesh & mesh,
const std::map<int, cv::Mat> & images, // raw or compressed, can be empty if memory or dbDriver should be used
const std::map<int, CameraModel> & calibrations, // Should match images
const Memory * memory = 0, // Should be set if images are not set
const DBDriver * dbDriver = 0, // Should be set if images and memory are not set
int textureSize = 4096,
int textureCount = 1,
const std::vector<std::map<int, pcl::PointXY> > & vertexToPixels = std::vector<std::map<int, pcl::PointXY> >(), // needed for parameters below
bool gainCompensation = true,
float gainBeta = 10.0f,
bool gainRGB = true, //Do gain compensation on each channel
bool blending = true,
int blendingDecimation = 0, //0=auto depending on projected polygon size and texture size
int brightnessContrastRatioLow = 0, //0=disabled, values between 0 and 100
int brightnessContrastRatioHigh = 0, //0=disabled, values between 0 and 100
bool exposureFusion = false, //Exposure fusion can be used only with OpenCV3
const ProgressState * state = 0);
cv::Mat RTABMAP_EXP mergeTextures(
pcl::TextureMesh & mesh,
const std::map<int, cv::Mat> & images, // raw or compressed, can be empty if memory or dbDriver should be used
@@ -212,6 +240,8 @@ cv::Mat RTABMAP_EXP mergeTextures(
bool exposureFusion = false, //Exposure fusion can be used only with OpenCV3
const ProgressState * state = 0);
void RTABMAP_EXP fixTextureMeshForVisualization(pcl::TextureMesh & textureMesh);
cv::Mat RTABMAP_EXP computeNormals(
const cv::Mat & laserScan,
int searchK,
@@ -226,6 +256,11 @@ pcl::PointCloud<pcl::Normal>::Ptr RTABMAP_EXP computeNormals(
int searchK = 20,
float searchRadius = 0.0f,
const Eigen::Vector3f & viewPoint = Eigen::Vector3f(0,0,0));
pcl::PointCloud<pcl::Normal>::Ptr RTABMAP_EXP computeNormals(
const pcl::PointCloud<pcl::PointXYZI>::Ptr & cloud,
int searchK = 20,
float searchRadius = 0.0f,
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::IndicesPtr & indices,
@@ -238,17 +273,33 @@ pcl::PointCloud<pcl::Normal>::Ptr RTABMAP_EXP computeNormals(
int searchK = 20,
float searchRadius = 0.0f,
const Eigen::Vector3f & viewPoint = Eigen::Vector3f(0,0,0));
pcl::PointCloud<pcl::Normal>::Ptr RTABMAP_EXP computeNormals(
const pcl::PointCloud<pcl::PointXYZI>::Ptr & cloud,
const pcl::IndicesPtr & indices,
int searchK = 20,
float searchRadius = 0.0f,
const Eigen::Vector3f & viewPoint = Eigen::Vector3f(0,0,0));
pcl::PointCloud<pcl::Normal>::Ptr RTABMAP_EXP computeNormals2D(
const pcl::PointCloud<pcl::PointXYZ>::Ptr & cloud,
int searchK = 5,
float searchRadius = 0.0f,
const Eigen::Vector3f & viewPoint = Eigen::Vector3f(0,0,0));
pcl::PointCloud<pcl::Normal>::Ptr RTABMAP_EXP computeNormals2D(
const pcl::PointCloud<pcl::PointXYZI>::Ptr & cloud,
int searchK = 5,
float searchRadius = 0.0f,
const Eigen::Vector3f & viewPoint = Eigen::Vector3f(0,0,0));
pcl::PointCloud<pcl::Normal>::Ptr RTABMAP_EXP computeFastOrganizedNormals2D(
const pcl::PointCloud<pcl::PointXYZ>::Ptr & cloud,
int searchK = 5,
float searchRadius = 0.0f,
const Eigen::Vector3f & viewPoint = Eigen::Vector3f(0,0,0));
pcl::PointCloud<pcl::Normal>::Ptr RTABMAP_EXP computeFastOrganizedNormals2D(
const pcl::PointCloud<pcl::PointXYZI>::Ptr & cloud,
int searchK = 5,
float searchRadius = 0.0f,
const Eigen::Vector3f & viewPoint = Eigen::Vector3f(0,0,0));
pcl::PointCloud<pcl::Normal>::Ptr RTABMAP_EXP computeFastOrganizedNormals(
const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloud,
@@ -263,7 +314,7 @@ pcl::PointCloud<pcl::Normal>::Ptr RTABMAP_EXP computeFastOrganizedNormals(
const Eigen::Vector3f & viewPoint = Eigen::Vector3f(0,0,0));
float RTABMAP_EXP computeNormalsComplexity(
const cv::Mat & scan,
const LaserScan & scan,
cv::Mat * pcaEigenVectors = 0,
cv::Mat * pcaEigenValues = 0);
float RTABMAP_EXP computeNormalsComplexity(
@@ -304,6 +355,18 @@ pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr RTABMAP_EXP mls(
float dilationVoxelSize = 1.0f, // VOXEL_GRID_DILATION
int dilationIterations = 0); // VOXEL_GRID_DILATION
LaserScan RTABMAP_EXP adjustNormalsToViewPoint(
const LaserScan & scan,
const Eigen::Vector3f & viewpoint,
bool forceGroundNormalsUp);
void RTABMAP_EXP adjustNormalsToViewPoint(
pcl::PointCloud<pcl::PointNormal>::Ptr & cloud,
const Eigen::Vector3f & viewpoint = Eigen::Vector3f(0,0,0),
bool forceGroundNormalsUp = false);
void RTABMAP_EXP adjustNormalsToViewPoint(
pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr & cloud,
const Eigen::Vector3f & viewpoint = Eigen::Vector3f(0,0,0),
bool forceGroundNormalsUp = false);
void RTABMAP_EXP adjustNormalsToViewPoints(
const std::map<int, Transform> & poses,
const pcl::PointCloud<pcl::PointXYZ>::Ptr & rawCloud,
@@ -34,6 +34,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <pcl/point_types.h>
#include <pcl/pcl_base.h>
#include <rtabmap/core/Transform.h>
#include <rtabmap/core/LaserScan.h>
namespace rtabmap
{
@@ -41,15 +42,15 @@ namespace rtabmap
namespace util3d
{
cv::Mat RTABMAP_EXP transformLaserScan(
const cv::Mat & laserScan,
LaserScan RTABMAP_EXP transformLaserScan(
const LaserScan & laserScan,
const Transform & transform);
pcl::PointCloud<pcl::PointXYZ>::Ptr RTABMAP_EXP transformPointCloud(
const pcl::PointCloud<pcl::PointXYZ>::Ptr & cloud,
const Transform & transform);
pcl::PointCloud<pcl::PointXYZ>::Ptr RTABMAP_EXP transformPointCloud(
const pcl::PointCloud<pcl::PointXYZ>::Ptr & cloud,
pcl::PointCloud<pcl::PointXYZI>::Ptr RTABMAP_EXP transformPointCloud(
const pcl::PointCloud<pcl::PointXYZI>::Ptr & cloud,
const Transform & transform);
pcl::PointCloud<pcl::PointXYZRGB>::Ptr RTABMAP_EXP transformPointCloud(
const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloud,
@@ -60,13 +61,16 @@ pcl::PointCloud<pcl::PointNormal>::Ptr RTABMAP_EXP transformPointCloud(
pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr RTABMAP_EXP transformPointCloud(
const pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr & cloud,
const Transform & transform);
pcl::PointCloud<pcl::PointXYZINormal>::Ptr RTABMAP_EXP transformPointCloud(
const pcl::PointCloud<pcl::PointXYZINormal>::Ptr & cloud,
const Transform & transform);
pcl::PointCloud<pcl::PointXYZ>::Ptr RTABMAP_EXP transformPointCloud(
const pcl::PointCloud<pcl::PointXYZ>::Ptr & cloud,
const pcl::IndicesPtr & indices,
const Transform & transform);
pcl::PointCloud<pcl::PointXYZ>::Ptr RTABMAP_EXP transformPointCloud(
const pcl::PointCloud<pcl::PointXYZ>::Ptr & cloud,
pcl::PointCloud<pcl::PointXYZI>::Ptr RTABMAP_EXP transformPointCloud(
const pcl::PointCloud<pcl::PointXYZI>::Ptr & cloud,
const pcl::IndicesPtr & indices,
const Transform & transform);
pcl::PointCloud<pcl::PointXYZRGB>::Ptr RTABMAP_EXP transformPointCloud(
@@ -81,6 +85,10 @@ pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr RTABMAP_EXP transformPointCloud(
const pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr & cloud,
const pcl::IndicesPtr & indices,
const Transform & transform);
pcl::PointCloud<pcl::PointXYZINormal>::Ptr RTABMAP_EXP transformPointCloud(
const pcl::PointCloud<pcl::PointXYZINormal>::Ptr & cloud,
const pcl::IndicesPtr & indices,
const Transform & transform);
cv::Point3f RTABMAP_EXP transformPoint(
const cv::Point3f & pt,
@@ -88,6 +96,9 @@ cv::Point3f RTABMAP_EXP transformPoint(
pcl::PointXYZ RTABMAP_EXP transformPoint(
const pcl::PointXYZ & pt,
const Transform & transform);
pcl::PointXYZI RTABMAP_EXP transformPoint(
const pcl::PointXYZI & pt,
const Transform & transform);
pcl::PointXYZRGB RTABMAP_EXP transformPoint(
const pcl::PointXYZRGB & pt,
const Transform & transform);
@@ -97,6 +108,9 @@ pcl::PointNormal RTABMAP_EXP transformPoint(
pcl::PointXYZRGBNormal RTABMAP_EXP transformPoint(
const pcl::PointXYZRGBNormal & point,
const Transform & transform);
pcl::PointXYZINormal RTABMAP_EXP transformPoint(
const pcl::PointXYZINormal & point,
const Transform & transform);
} // namespace util3d
} // namespace rtabmap
+130 -84
View File
@@ -30,6 +30,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "rtabmap/core/Signature.h"
#include "rtabmap/core/Parameters.h"
#include <iostream>
#include <set>
#if __cplusplus >= 201103L
#include <unordered_map>
#include <unordered_set>
#endif
#include "rtabmap/utilite/UtiLite.h"
@@ -125,6 +130,7 @@ void BayesFilter::reset()
{
_posterior.clear();
_prediction = cv::Mat();
_neighborsIndex.clear();
}
const std::map<int, float> & BayesFilter::computePosterior(const Memory * memory, const std::map<int, float> & likelihood)
@@ -219,7 +225,43 @@ const std::map<int, float> & BayesFilter::computePosterior(const Memory * memory
return _posterior;
}
cv::Mat BayesFilter::generatePrediction(const Memory * memory, const std::vector<int> & ids) const
float addNeighborProb(cv::Mat & prediction,
unsigned int col,
const std::map<int, int> & neighbors,
const std::vector<double> & predictionLC,
#if __cplusplus >= 201103L
const std::unordered_map<int, int> & idToIndex
#else
const std::map<int, int> & idToIndex
#endif
)
{
UASSERT(col < (unsigned int)prediction.cols &&
col < (unsigned int)prediction.rows);
float sum=0.0f;
float * dataPtr = (float*)prediction.data;
for(std::map<int, int>::const_iterator iter=neighbors.begin(); iter!=neighbors.end(); ++iter)
{
if(iter->first>=0)
{
#if __cplusplus >= 201103L
std::unordered_map<int, int>::const_iterator jter = idToIndex.find(iter->first);
#else
std::map<int, int>::const_iterator jter = idToIndex.find(iter->first);
#endif
if(jter != idToIndex.end())
{
UASSERT((iter->second+1) < (int)predictionLC.size());
sum += dataPtr[col + jter->second*prediction.cols] = predictionLC[iter->second+1];
}
}
}
return sum;
}
cv::Mat BayesFilter::generatePrediction(const Memory * memory, const std::vector<int> & ids)
{
if(!_fullPredictionUpdate && !_prediction.empty())
{
@@ -236,13 +278,21 @@ cv::Mat BayesFilter::generatePrediction(const Memory * memory, const std::vector
UTimer timerGlobal;
timerGlobal.start();
std::map<int, int> idToIndexMap;
#if __cplusplus >= 201103L
std::unordered_map<int,int> idToIndexMap;
idToIndexMap.reserve(ids.size());
#else
std::map<int,int> idToIndexMap;
#endif
for(unsigned int i=0; i<ids.size(); ++i)
{
UASSERT_MSG(ids[i] != 0, "Signature id is null ?!?");
idToIndexMap.insert(idToIndexMap.end(), std::make_pair(ids[i], i));
if(ids[i]>0)
{
idToIndexMap[ids[i]] = i;
}
}
//int rows = prediction.rows;
cv::Mat prediction = cv::Mat::zeros(ids.size(), ids.size(), CV_32FC1);
int cols = prediction.cols;
@@ -260,7 +310,13 @@ cv::Mat BayesFilter::generatePrediction(const Memory * memory, const std::vector
// Set high values (gaussians curves) to loop closure neighbors
// ADD prob for each neighbors
std::map<int, int> neighbors = memory->getNeighborsId(ids[i], _predictionLC.size()-1, 0, false, false, true);
std::map<int, int> neighbors = memory->getNeighborsId(ids[i], _predictionLC.size()-1, 0, false, false, true, true);
if(!_fullPredictionUpdate)
{
uInsert(_neighborsIndex, std::make_pair(ids[i], neighbors));
}
std::list<int> idsLoopMargin;
//filter neighbors in STM
for(std::map<int, int>::iterator iter=neighbors.begin(); iter!=neighbors.end();)
@@ -271,7 +327,7 @@ cv::Mat BayesFilter::generatePrediction(const Memory * memory, const std::vector
}
else
{
if(iter->second == 0)
if(iter->second == 0 && idToIndexMap.find(iter->first)!=idToIndexMap.end())
{
idsLoopMargin.push_back(iter->first);
}
@@ -288,10 +344,16 @@ cv::Mat BayesFilter::generatePrediction(const Memory * memory, const std::vector
// same neighbor tree for loop signatures (margin = 0)
for(std::list<int>::iterator iter = idsLoopMargin.begin(); iter!=idsLoopMargin.end(); ++iter)
{
if(!_fullPredictionUpdate)
{
uInsert(_neighborsIndex, std::make_pair(*iter, neighbors));
}
float sum = 0.0f; // sum values added
sum += this->addNeighborProb(prediction, idToIndexMap.at(*iter), neighbors, idToIndexMap);
int index = idToIndexMap.at(*iter);
sum += addNeighborProb(prediction, index, neighbors, _predictionLC, idToIndexMap);
idsDone.insert(*iter);
this->normalize(prediction, idToIndexMap.at(*iter), sum, ids[0]<0);
this->normalize(prediction, index, sum, ids[0]<0);
}
}
else
@@ -405,7 +467,7 @@ void BayesFilter::normalize(cv::Mat & prediction, unsigned int index, float adde
cv::Mat BayesFilter::updatePrediction(const cv::Mat & oldPrediction,
const Memory * memory,
const std::vector<int> & oldIds,
const std::vector<int> & newIds) const
const std::vector<int> & newIds)
{
UTimer timer;
UDEBUG("");
@@ -417,34 +479,40 @@ cv::Mat BayesFilter::updatePrediction(const cv::Mat & oldPrediction,
oldIds.size() == (unsigned int)oldPrediction.rows);
cv::Mat prediction = cv::Mat::zeros(newIds.size(), newIds.size(), CV_32FC1);
UDEBUG("time creating prediction = %fs", timer.restart());
// Create id to index maps
std::map<int, int> oldIdToIndexMap;
std::map<int, int> newIdToIndexMap;
for(unsigned int i=0; i<oldIds.size() || i<newIds.size(); ++i)
#if __cplusplus >= 201103L
std::unordered_set<int> oldIdsSet(oldIds.begin(), oldIds.end());
#else
std::set<int> oldIdsSet(oldIds.begin(), oldIds.end());
#endif
UDEBUG("time creating old ids set = %fs", timer.restart());
#if __cplusplus >= 201103L
std::unordered_map<int,int> newIdToIndexMap;
newIdToIndexMap.reserve(newIds.size());
#else
std::map<int,int> newIdToIndexMap;
#endif
for(unsigned int i=0; i<newIds.size(); ++i)
{
if(i<oldIds.size())
if(newIds[i]>0)
{
UASSERT(oldIds[i]);
oldIdToIndexMap.insert(oldIdToIndexMap.end(), std::make_pair(oldIds[i], i));
//UDEBUG("oldIdToIndexMap[%d] = %d", oldIds[i], i);
}
if(i<newIds.size())
{
UASSERT(newIds[i]);
newIdToIndexMap.insert(newIdToIndexMap.end(), std::make_pair(newIds[i], i));
//UDEBUG("newIdToIndexMap[%d] = %d", newIds[i], i);
newIdToIndexMap[newIds[i]] = i;
}
}
UDEBUG("time creating id-index maps = %fs", timer.restart());
UDEBUG("time creating id-index vector (size=%d oldIds.back()=%d newIds.back()=%d) = %fs", (int)newIdToIndexMap.size(), oldIds.back(), newIds.back(), timer.restart());
//Get removed ids
std::set<int> removedIds;
for(unsigned int i=0; i<oldIds.size(); ++i)
{
if(!uContains(newIdToIndexMap, oldIds[i]))
if(oldIds[i] > 0 && newIdToIndexMap.find(oldIds[i]) == newIdToIndexMap.end())
{
removedIds.insert(removedIds.end(), oldIds[i]);
_neighborsIndex.erase(oldIds[i]);
UDEBUG("removed id=%d at oldIndex=%d", oldIds[i], i);
}
}
@@ -476,16 +544,32 @@ cv::Mat BayesFilter::updatePrediction(const cv::Mat & oldPrediction,
UDEBUG("From removed id %d, %d neighbors to update.", oldIds[i], count);
}
}
if(i<newIds.size() && !uContains(oldIdToIndexMap,newIds[i]))
if(i<newIds.size() && oldIdsSet.find(newIds[i]) == oldIdsSet.end())
{
std::map<int, int> neighbors = memory->getNeighborsId(newIds[i], _predictionLC.size()-1, 0, false, false, true);
float sum = this->addNeighborProb(prediction, i, neighbors, newIdToIndexMap);
if(_neighborsIndex.find(newIds[i]) == _neighborsIndex.end())
{
std::map<int, int> neighbors = memory->getNeighborsId(newIds[i], _predictionLC.size()-1, 0, false, false, true, true);
for(std::map<int, int>::iterator iter=neighbors.begin(); iter!=neighbors.end(); ++iter)
{
std::map<int, std::map<int, int> >::iterator jter = _neighborsIndex.find(iter->first);
if(jter != _neighborsIndex.end())
{
uInsert(jter->second, std::make_pair(newIds[i], iter->second));
}
}
_neighborsIndex.insert(std::make_pair(newIds[i], neighbors));
}
const std::map<int, int> & neighbors = _neighborsIndex.at(newIds[i]);
//std::map<int, int> neighbors = memory->getNeighborsId(newIds[i], _predictionLC.size()-1, 0, false, false, true, true);
float sum = addNeighborProb(prediction, i, neighbors, _predictionLC, newIdToIndexMap);
this->normalize(prediction, i, sum, newIds[0]<0);
++added;
int count = 0;
for(std::map<int,int>::iterator iter=neighbors.begin(); iter!=neighbors.end(); ++iter)
for(std::map<int,int>::const_iterator iter=neighbors.begin(); iter!=neighbors.end(); ++iter)
{
if(uContains(oldIdToIndexMap, iter->first) &&
if(oldIdsSet.find(iter->first)!=oldIdsSet.end() &&
removedIds.find(iter->first) == removedIds.end())
{
idsToUpdate.insert(iter->first);
@@ -497,51 +581,33 @@ cv::Mat BayesFilter::updatePrediction(const cv::Mat & oldPrediction,
}
UDEBUG("time getting %d ids to update = %fs", idsToUpdate.size(), timer.restart());
UTimer t1;
double e0=0,e1=0, e2=0, e3=0, e4=0;
// update modified/added ids
int modified = 0;
std::set<int> idsDone;
for(std::set<int>::iterator iter = idsToUpdate.begin(); iter!=idsToUpdate.end(); ++iter)
{
if(idsDone.find(*iter) == idsDone.end() && *iter > 0)
int id = *iter;
if(id > 0)
{
std::map<int, int> neighbors = memory->getNeighborsId(*iter, _predictionLC.size()-1, 0, false, false, true);
int index = newIdToIndexMap.at(id);
std::list<int> idsLoopMargin;
//filter neighbors in STM
for(std::map<int, int>::iterator jter=neighbors.begin(); jter!=neighbors.end();)
{
if(memory->isInSTM(jter->first))
{
neighbors.erase(jter++);
}
else
{
if(jter->second == 0)
{
idsLoopMargin.push_back(jter->first);
}
++jter;
}
}
e0 = t1.ticks();
std::map<int, std::map<int, int> >::iterator kter = _neighborsIndex.find(id);
UASSERT_MSG(kter != _neighborsIndex.end(), uFormat("Did not find %d (current index size=%d)", id, (int)_neighborsIndex.size()).c_str());
const std::map<int, int> & neighbors = kter->second;
//std::map<int, int> neighbors = memory->getNeighborsId(id, _predictionLC.size()-1, 0, false, false, true, true);
e1+=t1.ticks();
// should at least have 1 id in idsMarginLoop
if(idsLoopMargin.size() == 0)
{
UFATAL("No 0 margin neighbor for signature %d !?!?", *iter);
}
float sum = addNeighborProb(prediction, index, neighbors, _predictionLC, newIdToIndexMap);
e3+=t1.ticks();
// same neighbor tree for loop signatures (margin = 0)
for(std::list<int>::iterator iter = idsLoopMargin.begin(); iter!=idsLoopMargin.end(); ++iter)
{
int index = newIdToIndexMap.at(*iter);
float sum = this->addNeighborProb(prediction, index, neighbors, newIdToIndexMap);
idsDone.insert(*iter);
this->normalize(prediction, index, sum, newIds[0]<0);
++modified;
}
this->normalize(prediction, index, sum, newIds[0]<0);
++modified;
e4+=t1.ticks();
}
}
UDEBUG("time updating modified/added %d ids = %fs", idsToUpdate.size(), timer.restart());
UDEBUG("time updating modified/added %d ids = %fs (e0=%f e1=%f e2=%f e3=%f e4=%f)", idsToUpdate.size(), timer.restart(), e0, e1, e2, e3, e4);
//UDEBUG("oldIds.size()=%d, oldPrediction.cols=%d, oldPrediction.rows=%d", oldIds.size(), oldPrediction.cols, oldPrediction.rows);
//UDEBUG("newIdToIndexMap.size()=%d, prediction.cols=%d, prediction.rows=%d", newIdToIndexMap.size(), prediction.cols, prediction.rows);
@@ -624,24 +690,4 @@ void BayesFilter::updatePosterior(const Memory * memory, const std::vector<int>
_posterior = newPosterior;
}
float BayesFilter::addNeighborProb(cv::Mat & prediction, unsigned int col, const std::map<int, int> & neighbors, const std::map<int, int> & idToIndexMap) const
{
UASSERT((unsigned int)prediction.cols == idToIndexMap.size() &&
(unsigned int)prediction.rows == idToIndexMap.size() &&
col < (unsigned int)prediction.cols &&
col < (unsigned int)prediction.rows);
float sum=0;
for(std::map<int, int>::const_iterator iter=neighbors.begin(); iter!=neighbors.end(); ++iter)
{
int index = uValue(idToIndexMap, iter->first, -1);
if(index >= 0)
{
sum += ((float*)prediction.data)[col + index*prediction.cols] = _predictionLC[iter->second+1];
}
}
return sum;
}
} // namespace rtabmap
+132 -23
View File
@@ -11,6 +11,8 @@ SET(SRC_FILES
DBDriverSqlite3.cpp
DBReader.cpp
Recovery.cpp
Camera.cpp
CameraThread.cpp
CameraRGB.cpp
@@ -44,6 +46,7 @@ SET(SRC_FILES
Graph.cpp
Compression.cpp
Link.cpp
LaserScan.cpp
Optimizer.cpp
OptimizerTORO.cpp
@@ -63,7 +66,12 @@ SET(SRC_FILES
OdometryFovis.cpp
OdometryViso2.cpp
OdometryDVO.cpp
OdometryOkvis.cpp
OdometryORBSLAM2.cpp
OdometryLOAM.cpp
OdometryMSCKF.cpp
IMUThread.cpp
Stereo.cpp
StereoDense.cpp
@@ -75,9 +83,7 @@ SET(SRC_FILES
rtflann/ext/lz4.c
rtflann/ext/lz4hc.c
FlannIndex.cpp
sqlite3/sqlite3.c
FlannIndex.cpp
#clams stuff
clams/discrete_depth_distortion_model_helpers.cpp
@@ -90,9 +96,20 @@ IF(OpenCV_VERSION_MAJOR EQUAL 2)
SET(SRC_FILES
${SRC_FILES}
opencv/Orb.cpp
opencv/solvepnp.cpp
)
ENDIF(OpenCV_VERSION_MAJOR EQUAL 2)
SET(SRC_FILES
${SRC_FILES}
opencv/solvepnp.cpp
)
# to get includes in visual studio
IF(MSVC)
FILE(GLOB HEADERS
../include/${PROJECT_PREFIX}/core/*.h
)
SET(SRC_FILES ${SRC_FILES} ${HEADERS})
ENDIF(MSVC)
SET(INCLUDE_DIRS
${PROJECT_SOURCE_DIR}/utilite/include
@@ -110,6 +127,26 @@ SET(LIBRARIES
${ZLIB_LIBRARIES}
)
IF(Sqlite3_FOUND)
SET(INCLUDE_DIRS
${INCLUDE_DIRS}
${Sqlite3_INCLUDE_DIRS}
)
SET(LIBRARIES
${LIBRARIES}
${Sqlite3_LIBRARIES}
)
ELSE()
SET(SRC_FILES
${SRC_FILES}
sqlite3/sqlite3.c
)
SET(INCLUDE_DIRS
${CMAKE_CURRENT_SOURCE_DIR}/sqlite3
${INCLUDE_DIRS}
)
ENDIF()
IF(Freenect_FOUND)
IF(Freenect_DASH_INCLUDES)
ADD_DEFINITIONS("-DFREENECT_DASH_INCLUDES")
@@ -146,6 +183,17 @@ IF(freenect2_FOUND)
)
ENDIF(freenect2_FOUND)
IF(KinectSDK2_FOUND)
SET(INCLUDE_DIRS
${INCLUDE_DIRS}
${KinectSDK2_INCLUDE_DIRS}
)
SET(LIBRARIES
${LIBRARIES}
${KinectSDK2_LIBRARIES}
)
ENDIF(KinectSDK2_FOUND)
IF(RealSense_FOUND)
SET(INCLUDE_DIRS
${INCLUDE_DIRS}
@@ -157,6 +205,24 @@ IF(RealSense_FOUND)
)
ENDIF(RealSense_FOUND)
IF(realsense2_FOUND)
SET(INCLUDE_DIRS
${INCLUDE_DIRS}
${realsense2_INCLUDE_DIRS}
)
IF(WIN32)
SET(LIBRARIES
${LIBRARIES}
${RealSense2_LIBRARIES}
)
ELSE()
SET(LIBRARIES
${LIBRARIES}
realsense2
)
ENDIF()
ENDIF(realsense2_FOUND)
IF(DC1394_FOUND)
SET(INCLUDE_DIRS
${INCLUDE_DIRS}
@@ -213,25 +279,6 @@ IF(G2O_FOUND)
ENDIF(WITH_VERTIGO)
ENDIF(G2O_FOUND)
IF(GTSAM_FOUND)
IF(GTSAM_INCLUDE_DIR)
SET(INCLUDE_DIRS
${GTSAM_INCLUDE_DIR} # place it in front to use Eigen installed by GTSAM
${INCLUDE_DIRS}
)
ELSE()
SET(INCLUDE_DIRS
${GTSAM_INCLUDE_DIRS} # cmake standard
${INCLUDE_DIRS}
)
ENDIF()
add_definitions("-DGTSAM_IMPORT_STATIC")
SET(LIBRARIES
${LIBRARIES}
gtsam
)
ENDIF(GTSAM_FOUND)
IF(cvsba_FOUND)
SET(INCLUDE_DIRS
${INCLUDE_DIRS}
@@ -254,6 +301,17 @@ IF(libpointmatcher_FOUND)
)
ENDIF(libpointmatcher_FOUND)
IF(loam_velodyne_FOUND)
SET(INCLUDE_DIRS
${INCLUDE_DIRS}
${loam_velodyne_INCLUDE_DIRS}
)
SET(LIBRARIES
${LIBRARIES}
${loam_velodyne_LIBRARIES}
)
ENDIF(loam_velodyne_FOUND)
IF(ZED_FOUND)
SET(INCLUDE_DIRS
${INCLUDE_DIRS}
@@ -323,6 +381,34 @@ IF(dvo_core_FOUND)
)
ENDIF(dvo_core_FOUND)
IF(okvis_FOUND)
SET(INCLUDE_DIRS
${OKVIS_INCLUDE_DIRS}
${BRISK_INCLUDE_DIRS}
${OPENGV_INCLUDE_DIRS}
${CERES_INCLUDE_DIRS}
${INCLUDE_DIRS}
)
SET(LIBRARIES
${OKVIS_LIBRARIES}
${BRISK_LIBRARIES}
${OPENGV_LIBRARIES}
${CERES_LIBRARIES}
${LIBRARIES}
)
ENDIF(okvis_FOUND)
IF(msckf_vio_FOUND)
SET(INCLUDE_DIRS
${msckf_vio_INCLUDE_DIRS}
${INCLUDE_DIRS}
)
SET(LIBRARIES
${msckf_vio_LIBRARIES}
${LIBRARIES}
)
ENDIF(msckf_vio_FOUND)
IF(ORB_SLAM2_FOUND)
SET(INCLUDE_DIRS
${ORB_SLAM2_INCLUDE_DIRS} #before so that g2o includes are taken from ORB_SLAM2 directory before the official g2o one
@@ -334,6 +420,29 @@ IF(ORB_SLAM2_FOUND)
)
ENDIF(ORB_SLAM2_FOUND)
IF(GTSAM_FOUND)
# Make sure GTSAM is built with system Eigen, not the included one in its package
IF(GTSAM_INCLUDE_DIR)
SET(INCLUDE_DIRS
${INCLUDE_DIRS}
${GTSAM_INCLUDE_DIR}
)
ELSE()
SET(INCLUDE_DIRS
${INCLUDE_DIRS}
${GTSAM_INCLUDE_DIRS}
)
ENDIF()
IF(WIN32)
# GTSAM should be built in STATIC on Windows to avoid "error C2338: THIS_METHOD_IS_ONLY_FOR_1x1_EXPRESSIONS" when building GTSAM
add_definitions("-DGTSAM_IMPORT_STATIC")
ENDIF(WIN32)
SET(LIBRARIES
${LIBRARIES}
gtsam # Windows: Place static libs at the end
)
ENDIF(GTSAM_FOUND)
####################################
# Generate resources files
####################################
+5
View File
@@ -59,6 +59,11 @@ Camera::~Camera()
UDEBUG("");
}
void Camera::resetTimer()
{
_frameRateTimer->start();
}
SensorData Camera::takeImage(CameraInfo * info)
{
bool warnFrameRateTooHigh = false;
+65 -9
View File
@@ -31,6 +31,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <rtabmap/utilite/UFile.h>
#include <rtabmap/utilite/UConversion.h>
#include <rtabmap/utilite/UMath.h>
#include <rtabmap/utilite/UStl.h>
#include <opencv2/imgproc/imgproc.hpp>
namespace rtabmap {
@@ -57,7 +58,7 @@ CameraModel::CameraModel(
localTransform_(localTransform)
{
UASSERT(K_.empty() || (K_.rows == 3 && K_.cols == 3 && K_.type() == CV_64FC1));
UASSERT(D_.empty() || (D_.rows == 1 && (D_.cols == 4 || D_.cols == 5 || D_.cols == 8) && D_.type() == CV_64FC1));
UASSERT(D_.empty() || (D_.rows == 1 && (D_.cols == 4 || D_.cols == 5 || D_.cols == 6 || D_.cols == 8) && D_.type() == CV_64FC1));
UASSERT(R_.empty() || (R_.rows == 3 && R_.cols == 3 && R_.type() == CV_64FC1));
UASSERT(P_.empty() || (P_.rows == 3 && P_.cols == 4 && P_.type() == CV_64FC1));
}
@@ -153,12 +154,33 @@ CameraModel::CameraModel(
void CameraModel::initRectificationMap()
{
UASSERT(imageSize_.height > 0 && imageSize_.width > 0);
UASSERT(D_.rows == 1 && (D_.cols == 4 || D_.cols == 5 || D_.cols == 8));
UASSERT(D_.rows == 1 && (D_.cols == 4 || D_.cols == 5 || D_.cols == 6 || D_.cols == 8));
UASSERT(R_.rows == 3 && R_.cols == 3);
UASSERT(P_.rows == 3 && P_.cols == 4);
// init rectification map
UINFO("Initialize rectify map");
cv::initUndistortRectifyMap(K_, D_, R_, P_, imageSize_, CV_32FC1, mapX_, mapY_);
if(D_.cols == 6)
{
#if CV_MAJOR_VERSION > 2 or (CV_MAJOR_VERSION == 2 and (CV_MINOR_VERSION >4 or (CV_MINOR_VERSION == 4 and CV_SUBMINOR_VERSION >=10)))
// Equidistant / FishEye
// get only k parameters (k1,k2,p1,p2,k3,k4)
cv::Mat D(1, 4, CV_64FC1);
D.at<double>(0,0) = D_.at<double>(0,1);
D.at<double>(0,1) = D_.at<double>(0,2);
D.at<double>(0,2) = D_.at<double>(0,4);
D.at<double>(0,3) = D_.at<double>(0,5);
cv::fisheye::initUndistortRectifyMap(K_, D, R_, P_, imageSize_, CV_32FC1, mapX_, mapY_);
}
else
#else
UWARN("Too old opencv version (%d,%d,%d) to support fisheye model (min 2.4.10 required)!",
CV_MAJOR_VERSION, CV_MINOR_VERSION, CV_SUBMINOR_VERSION);
}
#endif
{
// RadialTangential
cv::initUndistortRectifyMap(K_, D_, R_, P_, imageSize_, CV_32FC1, mapX_, mapY_);
}
}
void CameraModel::setImageSize(const cv::Size & size)
@@ -263,6 +285,27 @@ bool CameraModel::load(const std::string & directory, const std::string & camera
UWARN("Missing \"distorsion_coefficients\" field in \"%s\"", filePath.c_str());
}
n = fs["distortion_model"];
if(n.type() != cv::FileNode::NONE)
{
std::string distortionModel = (std::string)n;
if(D_.cols>=4 &&
(uStrContains(distortionModel, "fisheye") ||
uStrContains(distortionModel, "equidistant")))
{
cv::Mat D = cv::Mat::zeros(1,6,CV_64FC1);
D.at<double>(0,0) = D_.at<double>(0,0);
D.at<double>(0,1) = D_.at<double>(0,1);
D.at<double>(0,4) = D_.at<double>(0,2);
D.at<double>(0,5) = D_.at<double>(0,3);
D_ = D;
}
}
else
{
UWARN("Missing \"distortion_model\" field in \"%s\"", filePath.c_str());
}
n = fs["rectification_matrix"];
if(n.type() != cv::FileNode::NONE)
{
@@ -347,20 +390,33 @@ bool CameraModel::save(const std::string & directory) const
if(!D_.empty())
{
cv::Mat D = D_;
if(D_.cols == 6)
{
D = cv::Mat(1,4,CV_64FC1);
D.at<double>(0,0) = D_.at<double>(0,0);
D.at<double>(0,1) = D_.at<double>(0,1);
D.at<double>(0,2) = D_.at<double>(0,4);
D.at<double>(0,3) = D_.at<double>(0,5);
}
fs << "distortion_coefficients" << "{";
fs << "rows" << D_.rows;
fs << "cols" << D_.cols;
fs << "data" << std::vector<double>((double*)D_.data, ((double*)D_.data)+(D_.rows*D_.cols));
fs << "rows" << D.rows;
fs << "cols" << D.cols;
fs << "data" << std::vector<double>((double*)D.data, ((double*)D.data)+(D.rows*D.cols));
fs << "}";
// compaibility with ROS
if(D_.cols > 5)
if(D_.cols == 6)
{
fs << "distortion_model" << "rational_polynomial";
fs << "distortion_model" << "equidistant"; // equidistant, fisheye
}
else if(D.cols > 5)
{
fs << "distortion_model" << "rational_polynomial"; // rad tan
}
else
{
fs << "distortion_model" << "plumb_bob";
fs << "distortion_model" << "plumb_bob"; // rad tan
}
}
+131 -77
View File
@@ -37,6 +37,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <rtabmap/utilite/UTimer.h>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/imgproc/types_c.h>
#if CV_MAJOR_VERSION >= 3
#include <opencv2/videoio/videoio_c.h>
#endif
#include <rtabmap/core/util3d.h>
#include <rtabmap/core/util3d_filtering.h>
@@ -71,6 +75,7 @@ CameraImages::CameraImages() :
_scanVoxelSize(0.0f),
_scanNormalsK(0),
_scanNormalsRadius(0),
_scanForceGroundNormalsUp(false),
_depthFromScan(false),
_depthFromScanFillHoles(1),
_depthFromScanFillHolesFromBorder(false),
@@ -78,6 +83,7 @@ CameraImages::CameraImages() :
_syncImageRateWithStamps(true),
_odometryFormat(0),
_groundTruthFormat(0),
_maxPoseTimeDiff(0.02),
_captureDelay(0.0)
{}
CameraImages::CameraImages(const std::string & path,
@@ -101,6 +107,7 @@ CameraImages::CameraImages(const std::string & path,
_scanVoxelSize(0.0f),
_scanNormalsK(0),
_scanNormalsRadius(0),
_scanForceGroundNormalsUp(false),
_depthFromScan(false),
_depthFromScanFillHoles(1),
_depthFromScanFillHolesFromBorder(false),
@@ -108,6 +115,7 @@ CameraImages::CameraImages(const std::string & path,
_syncImageRateWithStamps(true),
_odometryFormat(0),
_groundTruthFormat(0),
_maxPoseTimeDiff(0.02),
_captureDelay(0.0)
{
@@ -116,14 +124,8 @@ CameraImages::CameraImages(const std::string & path,
CameraImages::~CameraImages()
{
UDEBUG("");
if(_dir)
{
delete _dir;
}
if(_scanDir)
{
delete _scanDir;
}
delete _dir;
delete _scanDir;
}
bool CameraImages::init(const std::string & calibrationFolder, const std::string & cameraName)
@@ -240,15 +242,43 @@ bool CameraImages::init(const std::string & calibrationFolder, const std::string
const std::list<std::string> & filenames = _dir->getFileNames();
for(std::list<std::string>::const_iterator iter=filenames.begin(); iter!=filenames.end(); ++iter)
{
// format is text_12234456.12334_text.png
// format is text_1223445645.12334_text.png or text_122344564512334_text.png
// If no decimals, 10 first number are the seconds
std::list<std::string> list = uSplit(*iter, '.');
if(list.size() == 3)
if(list.size() == 3 || list.size() == 2)
{
list.pop_back(); // remove extension
std::string decimals = uSplitNumChar(list.back()).front();
list.pop_back();
std::string sec = uSplitNumChar(list.back()).back();
double stamp = uStr2Double(sec + "." + decimals);
double stamp = 0.0;
if(list.size() == 1)
{
std::list<std::string> numberList = uSplitNumChar(list.front());
for(std::list<std::string>::iterator iter=numberList.begin(); iter!=numberList.end(); ++iter)
{
if(uIsNumber(*iter))
{
std::string decimals;
std::string sec;
if(iter->length()>10)
{
decimals = iter->substr(10, iter->size()-10);
sec = iter->substr(0, 10);
}
else
{
sec = *iter;
}
stamp = uStr2Double(sec + "." + decimals);
break;
}
}
}
else
{
std::string decimals = uSplitNumChar(list.back()).front();
list.pop_back();
std::string sec = uSplitNumChar(list.back()).back();
stamp = uStr2Double(sec + "." + decimals);
}
if(stamp > 0.0)
{
_stamps.push_back(stamp);
@@ -312,12 +342,12 @@ bool CameraImages::init(const std::string & calibrationFolder, const std::string
if(success && _odometryPath.size())
{
success = readPoses(odometry_, _stamps, _odometryPath, _odometryFormat);
success = readPoses(odometry_, _stamps, _odometryPath, _odometryFormat, _maxPoseTimeDiff);
}
if(success && _groundTruthPath.size())
{
success = readPoses(groundTruth_, _stamps, _groundTruthPath, _groundTruthFormat);
success = readPoses(groundTruth_, _stamps, _groundTruthPath, _groundTruthFormat, _maxPoseTimeDiff);
}
}
@@ -326,7 +356,7 @@ bool CameraImages::init(const std::string & calibrationFolder, const std::string
return success;
}
bool CameraImages::readPoses(std::list<Transform> & outputPoses, std::list<double> & inOutStamps, const std::string & filePath, int format) const
bool CameraImages::readPoses(std::list<Transform> & outputPoses, std::list<double> & inOutStamps, const std::string & filePath, int format, double maxTimeDiff) const
{
outputPoses.clear();
std::map<int, Transform> poses;
@@ -336,19 +366,19 @@ bool CameraImages::readPoses(std::list<Transform> & outputPoses, std::list<doubl
UERROR("Cannot read pose file \"%s\".", filePath.c_str());
return false;
}
else if((format != 1 && format != 5 && format != 6 && format != 7) && poses.size() != this->imagesCount())
else if((format != 1 && format != 5 && format != 6 && format != 7 && format != 9) && poses.size() != this->imagesCount())
{
UERROR("The pose count is not the same as the images (%d vs %d)! Please remove "
"the pose file path if you don't want to use it (current file path=%s).",
(int)poses.size(), this->imagesCount(), filePath.c_str());
return false;
}
else if((format == 1 || format == 5 || format == 6 || format == 7) && inOutStamps.size() == 0)
else if((format == 1 || format == 5 || format == 6 || format == 7 || format == 9) && inOutStamps.size() == 0)
{
UERROR("When using RGBD-SLAM, GPS, MALAGA and ST LUCIA formats, images must have timestamps!");
UERROR("When using RGBD-SLAM, GPS, MALAGA, ST LUCIA and EuRoC MAV formats, images must have timestamps!");
return false;
}
else if(format == 1 || format == 5 || format == 6 || format == 7)
else if(format == 1 || format == 5 || format == 6 || format == 7 || format == 9)
{
UDEBUG("");
//Match ground truth values with images
@@ -380,16 +410,21 @@ bool CameraImages::readPoses(std::list<Transform> & outputPoses, std::list<doubl
double stampBeg = beginIter->first;
double stampEnd = endIter->first;
UASSERT(stampEnd > stampBeg && *ster>stampBeg && *ster < stampEnd);
if(stampEnd - stampBeg > 10.0)
if(fabs(*ster-stampEnd) > maxTimeDiff || fabs(*ster-stampBeg) > maxTimeDiff)
{
warned = true;
UDEBUG("Cannot interpolate pose for stamp %f between %f and %f (>10 sec)",
*ster,
stampBeg,
stampEnd);
if(!warned)
{
UWARN("Cannot interpolate pose for stamp %f between %f and %f (> maximum time diff of %f sec)",
*ster,
stampBeg,
stampEnd,
maxTimeDiff);
}
warned=true;
}
else
{
warned=false;
float t = (*ster - stampBeg) / (stampEnd-stampBeg);
Transform & ta = poses.at(beginIter->second);
Transform & tb = poses.at(endIter->second);
@@ -492,7 +527,7 @@ SensorData CameraImages::captureImage(CameraInfo * info)
_captureDelay = 0.0;
cv::Mat img;
cv::Mat scan;
LaserScan scan(cv::Mat(), _scanMaxPts, 0, LaserScan::kUnknown, _scanLocalTransform);
double stamp = UTimer::now();
Transform odometryPose;
Transform groundTruthPose;
@@ -533,6 +568,26 @@ SensorData CameraImages::captureImage(CameraInfo * info)
}
}
}
if(_stamps.size())
{
stamp = _stamps.front();
_stamps.pop_front();
if(_stamps.size())
{
_captureDelay = _stamps.front() - stamp;
}
if(odometry_.size())
{
odometryPose = odometry_.front();
odometry_.pop_front();
}
if(groundTruth_.size())
{
groundTruthPose = groundTruth_.front();
groundTruth_.pop_front();
}
}
}
else
{
@@ -541,9 +596,48 @@ SensorData CameraImages::captureImage(CameraInfo * info)
if(!fileName.empty())
{
imageFilePath = _path + fileName;
if(_stamps.size())
{
stamp = _stamps.front();
_stamps.pop_front();
if(_stamps.size())
{
_captureDelay = _stamps.front() - stamp;
}
if(odometry_.size())
{
odometryPose = odometry_.front();
odometry_.pop_front();
}
if(groundTruth_.size())
{
groundTruthPose = groundTruth_.front();
groundTruth_.pop_front();
}
}
while(_count++ < _startAt && (fileName = _dir->getNextFileName()).size())
{
imageFilePath = _path + fileName;
if(_stamps.size())
{
stamp = _stamps.front();
_stamps.pop_front();
if(_stamps.size())
{
_captureDelay = _stamps.front() - stamp;
}
if(odometry_.size())
{
odometryPose = odometry_.front();
odometry_.pop_front();
}
if(groundTruth_.size())
{
groundTruthPose = groundTruth_.front();
groundTruth_.pop_front();
}
}
}
}
if(_scanDir)
@@ -560,26 +654,6 @@ SensorData CameraImages::captureImage(CameraInfo * info)
}
}
if(_stamps.size())
{
stamp = _stamps.front();
_stamps.pop_front();
if(_stamps.size())
{
_captureDelay = _stamps.front() - stamp;
}
if(odometry_.size())
{
odometryPose = odometry_.front();
odometry_.pop_front();
}
if(groundTruth_.size())
{
groundTruthPose = groundTruth_.front();
groundTruth_.pop_front();
}
}
if(!imageFilePath.empty())
{
ULOGGER_DEBUG("Loading image : %s", imageFilePath.c_str());
@@ -596,9 +670,9 @@ SensorData CameraImages::captureImage(CameraInfo * info)
{
if(img.type() != CV_16UC1 && img.type() != CV_32FC1)
{
UERROR("Depth is on and the loaded image has not a format supported (file = \"%s\"). "
"Formats supported are 16 bits 1 channel and 32 bits 1 channel.",
imageFilePath.c_str());
UERROR("Depth is on and the loaded image has not a format supported (file = \"%s\", type=%d). "
"Formats supported are 16 bits 1 channel (mm) and 32 bits 1 channel (m).",
imageFilePath.c_str(), img.type());
img = cv::Mat();
}
@@ -652,8 +726,9 @@ SensorData CameraImages::captureImage(CameraInfo * info)
if(!scanFilePath.empty())
{
// load without filtering
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud = util3d::loadCloud(scanFilePath, _scanLocalTransform);
UDEBUG("Loaded scan=%d points", (int)cloud->size());
scan = util3d::loadScan(scanFilePath);
scan = LaserScan(scan.data(), _scanMaxPts, 0.0f, scan.format(), _scanLocalTransform);
UDEBUG("Loaded scan=%d points", (int)scan.size());
if(_depthFromScan && !img.empty())
{
UDEBUG("Computing depth from scan...");
@@ -667,6 +742,7 @@ SensorData CameraImages::captureImage(CameraInfo * info)
}
else
{
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud = util3d::laserScanToPointCloud(scan, scan.localTransform());
depthFromScan = util3d::projectCloudToCamera(img.size(), _model.K(), cloud, _model.localTransform());
if(_depthFromScanFillHoles!=0)
{
@@ -675,29 +751,7 @@ SensorData CameraImages::captureImage(CameraInfo * info)
}
}
// filter the scan after registration
int previousSize = (int)cloud->size();
if(_scanDownsampleStep > 1 && cloud->size())
{
cloud = util3d::downsample(cloud, _scanDownsampleStep);
UDEBUG("Downsampling scan (step=%d): %d -> %d", _scanDownsampleStep, previousSize, (int)cloud->size());
}
previousSize = (int)cloud->size();
if(_scanVoxelSize > 0.0f && cloud->size())
{
cloud = util3d::voxelize(cloud, _scanVoxelSize);
UDEBUG("Voxel filtering scan (voxel=%f m): %d -> %d", _scanVoxelSize, previousSize, (int)cloud->size());
}
if((_scanNormalsK > 0 || _scanNormalsRadius) && cloud->size())
{
pcl::PointCloud<pcl::Normal>::Ptr normals = util3d::computeNormals(cloud, _scanNormalsK, _scanNormalsRadius);
pcl::PointCloud<pcl::PointNormal>::Ptr cloudNormals(new pcl::PointCloud<pcl::PointNormal>);
pcl::concatenateFields(*cloud, *normals, *cloudNormals);
scan = util3d::laserScanFromPointCloud(*cloudNormals, _scanLocalTransform.inverse());
}
else
{
scan = util3d::laserScanFromPointCloud(*cloud, _scanLocalTransform.inverse());
}
scan = util3d::commonFiltering(scan, _scanDownsampleStep, 0, 0, _scanVoxelSize, _scanNormalsK, _scanNormalsRadius, _scanForceGroundNormalsUp);
}
}
else
@@ -710,7 +764,7 @@ SensorData CameraImages::captureImage(CameraInfo * info)
_model.setImageSize(img.size());
}
SensorData data(scan, LaserScanInfo(scan.empty()?0:_scanMaxPts, 0, _scanLocalTransform), _isDepth?cv::Mat():img, _isDepth?img:depthFromScan, _model, this->getNextSeqID(), stamp);
SensorData data(scan, _isDepth?cv::Mat():img, _isDepth?img:depthFromScan, _model, this->getNextSeqID(), stamp);
data.setGroundTruth(groundTruthPose);
if(info && !odometryPose.isNull())
+1593 -147
View File
File diff suppressed because it is too large Load Diff
+86 -51
View File
@@ -39,6 +39,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <rtabmap/utilite/UTimer.h>
#include <rtabmap/utilite/UMath.h>
#include <opencv2/imgproc/types_c.h>
#if CV_MAJOR_VERSION >= 3
#include <opencv2/videoio/videoio_c.h>
#endif
#ifdef RTABMAP_DC1394
#include <dc1394/dc1394.h>
#endif
@@ -361,10 +366,7 @@ CameraStereoDC1394::CameraStereoDC1394(float imageRate, const Transform & localT
CameraStereoDC1394::~CameraStereoDC1394()
{
#ifdef RTABMAP_DC1394
if(device_)
{
delete device_;
}
delete device_;
#endif
}
@@ -379,7 +381,7 @@ bool CameraStereoDC1394::init(const std::string & calibrationFolder, const std::
// look for calibration files
if(!calibrationFolder.empty())
{
if(!stereoModel_.load(calibrationFolder, cameraName.empty()?device_->guid():cameraName))
if(!stereoModel_.load(calibrationFolder, cameraName.empty()?device_->guid():cameraName, false))
{
UWARN("Missing calibration files for camera \"%s\" in \"%s\" folder, you should calibrate the camera!",
cameraName.empty()?device_->guid().c_str():cameraName.c_str(), calibrationFolder.c_str());
@@ -829,10 +831,7 @@ CameraStereoZed::CameraStereoZed(
CameraStereoZed::~CameraStereoZed()
{
#ifdef RTABMAP_ZED
if(zed_)
{
delete zed_;
}
delete zed_;
#endif
}
@@ -855,7 +854,7 @@ bool CameraStereoZed::init(const std::string & calibrationFolder, const std::str
param.depth_mode=(sl::DEPTH_MODE)quality_;
param.coordinate_units=sl::UNIT_METER;
param.coordinate_system=(sl::COORDINATE_SYSTEM)sl::COORDINATE_SYSTEM_IMAGE ;
param.sdk_verbose=false;
param.sdk_verbose=true;
param.sdk_gpu_id=-1;
param.depth_minimum_distance=-1;
param.camera_disable_self_calib=!selfCalibration_;
@@ -877,7 +876,7 @@ bool CameraStereoZed::init(const std::string & calibrationFolder, const std::str
if(r!=sl::ERROR_CODE::SUCCESS)
{
UERROR("Camera initialization failed: \"%s\"", errorCode2str(r).c_str());
UERROR("Camera initialization failed: \"%s\"", toString(r).c_str());
delete zed_;
zed_ = 0;
return false;
@@ -888,19 +887,26 @@ bool CameraStereoZed::init(const std::string & calibrationFolder, const std::str
quality_, sl::UNIT_METER, sl::COORDINATE_SYSTEM_IMAGE , selfCalibration_?"true":"false");
UDEBUG("");
zed_->setConfidenceThreshold(confidenceThr_);
if(quality_!=sl::DEPTH_MODE_NONE)
{
zed_->setConfidenceThreshold(confidenceThr_);
}
if (computeOdometry_)
{
sl::TrackingParameters tparam;
tparam.enable_spatial_memory=false;
zed_->enableTracking(tparam);
if(r!=sl::ERROR_CODE::SUCCESS)
{
UERROR("Camera tracking initialization failed: \"%s\"", toString(r).c_str());
}
}
sl::CameraInformation infos = zed_->getCameraInformation();
sl::CalibrationParameters *stereoParams = &(infos.calibration_parameters );
sl::Resolution res = stereoParams->left_cam.image_size;
stereoModel_ = StereoCameraModel(
stereoParams->left_cam.fx,
stereoParams->left_cam.fy,
@@ -993,16 +999,17 @@ SensorData CameraStereoZed::captureImage(CameraInfo * info)
{
UTimer timer;
bool res = zed_->grab(rparam);
while (src_ == CameraVideo::kUsbDevice && res && timer.elapsed() < 2.0)
while (src_ == CameraVideo::kUsbDevice && res!=sl::SUCCESS && timer.elapsed() < 2.0)
{
// maybe there is a latency with the USB, try again in 10 ms (for the next 2 seconds)
uSleep(10);
res = zed_->grab(rparam);
}
if(!res)
if(res==sl::SUCCESS)
{
// get left image
sl::Mat tmp;zed_->retrieveImage(tmp,sl::VIEW_LEFT);
sl::Mat tmp;
zed_->retrieveImage(tmp,sl::VIEW_LEFT);
cv::Mat rgbaLeft = slMat2cvMat(tmp);
cv::Mat left;
@@ -1032,28 +1039,37 @@ SensorData CameraStereoZed::captureImage(CameraInfo * info)
if (computeOdometry_ && info)
{
sl::Pose pose;
zed_->getPosition(pose);
int trackingConfidence = pose.pose_confidence;
// FIXME What does pose_confidence == -1 mean?
if (trackingConfidence>0)
sl::TRACKING_STATE tracking_state = zed_->getPosition(pose);
if (tracking_state == sl::TRACKING_STATE_OK)
{
info->odomPose = zedPoseToTransform(pose);
if (!info->odomPose.isNull())
int trackingConfidence = pose.pose_confidence;
// FIXME What does pose_confidence == -1 mean?
if (trackingConfidence>0)
{
//transform x->forward, y->left, z->up
Transform opticalTransform(0, 0, 1, 0, -1, 0, 0, 0, 0, -1, 0, 0);
info->odomPose = opticalTransform * info->odomPose * opticalTransform.inverse();
if (lost_)
info->odomPose = zedPoseToTransform(pose);
if (!info->odomPose.isNull())
{
info->odomCovariance = cv::Mat::eye(6, 6, CV_64FC1) * 9999.0f; // don't know transform with previous pose
lost_ = false;
UDEBUG("Init %s (var=%f)", info->odomPose.prettyPrint().c_str(), 9999.0f);
//transform x->forward, y->left, z->up
Transform opticalTransform(0, 0, 1, 0, -1, 0, 0, 0, 0, -1, 0, 0);
info->odomPose = opticalTransform * info->odomPose * opticalTransform.inverse();
if (lost_)
{
info->odomCovariance = cv::Mat::eye(6, 6, CV_64FC1) * 9999.0f; // don't know transform with previous pose
lost_ = false;
UDEBUG("Init %s (var=%f)", info->odomPose.prettyPrint().c_str(), 9999.0f);
}
else
{
info->odomCovariance = cv::Mat::eye(6, 6, CV_64FC1) * 1.0f / float(trackingConfidence);
UDEBUG("Run %s (var=%f)", info->odomPose.prettyPrint().c_str(), 1.0f / float(trackingConfidence));
}
}
else
{
info->odomCovariance = cv::Mat::eye(6, 6, CV_64FC1) * 1.0f / float(trackingConfidence);
UDEBUG("Run %s (var=%f)", info->odomPose.prettyPrint().c_str(), 1.0f / float(trackingConfidence));
info->odomCovariance = cv::Mat::eye(6, 6, CV_64FC1) * 9999.0f; // lost
lost_ = true;
UWARN("ZED lost! (trackingConfidence=%d)", trackingConfidence);
}
}
else
@@ -1065,9 +1081,7 @@ SensorData CameraStereoZed::captureImage(CameraInfo * info)
}
else
{
info->odomCovariance = cv::Mat::eye(6, 6, CV_64FC1) * 9999.0f; // lost
lost_ = true;
UWARN("ZED lost! (trackingConfidence=%d)", trackingConfidence);
UWARN("Tracking not ok: state=\"%s\"", toString(tracking_state).c_str());
}
}
}
@@ -1135,10 +1149,7 @@ CameraStereoImages::CameraStereoImages(
CameraStereoImages::~CameraStereoImages()
{
UDEBUG("");
if(camera2_)
{
delete camera2_;
}
delete camera2_;
UDEBUG("");
}
@@ -1147,7 +1158,7 @@ bool CameraStereoImages::init(const std::string & calibrationFolder, const std::
// look for calibration files
if(!calibrationFolder.empty() && !cameraName.empty())
{
if(!stereoModel_.load(calibrationFolder, cameraName))
if(!stereoModel_.load(calibrationFolder, cameraName, false) && !stereoModel_.isValidForProjection())
{
UWARN("Missing calibration files for camera \"%s\" in \"%s\" folder, you should calibrate the camera!",
cameraName.c_str(), calibrationFolder.c_str());
@@ -1255,7 +1266,7 @@ SensorData CameraStereoImages::captureImage(CameraInfo * info)
stereoModel_.setImageSize(leftImage.size());
}
data = SensorData(left.laserScanRaw(), left.laserScanInfo(), leftImage, rightImage, stereoModel_, left.id()/(camera2_?1:2), left.stamp());
data = SensorData(left.laserScanRaw(), leftImage, rightImage, stereoModel_, left.id()/(camera2_?1:2), left.stamp());
data.setGroundTruth(left.groundTruth());
}
}
@@ -1279,7 +1290,8 @@ CameraStereoVideo::CameraStereoVideo(
path_(path),
rectifyImages_(rectifyImages),
src_(CameraVideo::kVideoFile),
usbDevice_(0)
usbDevice_(0),
usbDevice2_(-1)
{
}
@@ -1294,7 +1306,8 @@ CameraStereoVideo::CameraStereoVideo(
path2_(pathRight),
rectifyImages_(rectifyImages),
src_(CameraVideo::kVideoFile),
usbDevice_(0)
usbDevice_(0),
usbDevice2_(-1)
{
}
@@ -1306,7 +1319,22 @@ CameraStereoVideo::CameraStereoVideo(
Camera(imageRate, localTransform),
rectifyImages_(rectifyImages),
src_(CameraVideo::kUsbDevice),
usbDevice_(device)
usbDevice_(device),
usbDevice2_(-1)
{
}
CameraStereoVideo::CameraStereoVideo(
int deviceLeft,
int deviceRight,
bool rectifyImages,
float imageRate,
const Transform & localTransform) :
Camera(imageRate, localTransform),
rectifyImages_(rectifyImages),
src_(CameraVideo::kUsbDevice),
usbDevice_(deviceLeft),
usbDevice2_(deviceRight)
{
}
@@ -1330,20 +1358,27 @@ bool CameraStereoVideo::init(const std::string & calibrationFolder, const std::s
if (src_ == CameraVideo::kUsbDevice)
{
ULOGGER_DEBUG("CameraStereoVideo: Usb device initialization on device %d", usbDevice_);
capture_.open(usbDevice_);
if(usbDevice2_ < 0)
{
ULOGGER_DEBUG("CameraStereoVideo: Usb device initialization on device %d", usbDevice_);
}
else
{
ULOGGER_DEBUG("CameraStereoVideo: Usb device initialization on devices %d and %d", usbDevice_, usbDevice2_);
capture2_.open(usbDevice2_);
}
}
else if (src_ == CameraVideo::kVideoFile)
{
capture_.open(path_.c_str());
if(path2_.empty())
{
ULOGGER_DEBUG("CameraStereoVideo: filename=\"%s\"", path_.c_str());
capture_.open(path_.c_str());
}
else
{
ULOGGER_DEBUG("CameraStereoVideo: filenames=\"%s\" and \"%s\"", path_.c_str(), path2_.c_str());
capture_.open(path_.c_str());
capture2_.open(path2_.c_str());
}
}
@@ -1352,7 +1387,7 @@ bool CameraStereoVideo::init(const std::string & calibrationFolder, const std::s
ULOGGER_ERROR("CameraStereoVideo: Unknown source...");
}
if(!capture_.isOpened() || (!path2_.empty() && !capture2_.isOpened()))
if(!capture_.isOpened() || ((!path2_.empty() || usbDevice2_>=0) && !capture2_.isOpened()))
{
ULOGGER_ERROR("CameraStereoVideo: Failed to create a capture object!");
capture_.release();
@@ -1372,7 +1407,7 @@ bool CameraStereoVideo::init(const std::string & calibrationFolder, const std::s
// look for calibration files
if(!calibrationFolder.empty() && !cameraName_.empty())
{
if(!stereoModel_.load(calibrationFolder, cameraName_))
if(!stereoModel_.load(calibrationFolder, cameraName_, false))
{
UWARN("Missing calibration files for camera \"%s\" in \"%s\" folder, you should calibrate the camera!",
cameraName_.c_str(), calibrationFolder.c_str());
@@ -1411,11 +1446,11 @@ SensorData CameraStereoVideo::captureImage(CameraInfo * info)
SensorData data;
cv::Mat img;
if(capture_.isOpened() && (path2_.empty() || capture2_.isOpened()))
if(capture_.isOpened() && ((path2_.empty() && usbDevice2_ < 0) || capture2_.isOpened()))
{
cv::Mat leftImage;
cv::Mat rightImage;
if(path2_.empty())
if(path2_.empty() && usbDevice2_ < 0)
{
if(!capture_.read(img))
{
+38 -12
View File
@@ -36,7 +36,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "rtabmap/core/StereoDense.h"
#include "rtabmap/core/DBReader.h"
#include "rtabmap/core/clams/discrete_depth_distortion_model.h"
#include <opencv2/stitching/detail/exposure_compensate.hpp>
#include <rtabmap/utilite/UTimer.h>
#include <rtabmap/utilite/ULogger.h>
@@ -49,6 +49,7 @@ namespace rtabmap
CameraThread::CameraThread(Camera * camera, const ParametersMap & parameters) :
_camera(camera),
_mirroring(false),
_stereoExposureCompensation(false),
_colorOnly(false),
_imageDecimation(1),
_stereoToDepth(false),
@@ -72,14 +73,8 @@ CameraThread::~CameraThread()
{
UDEBUG("");
join(true);
if(_camera)
{
delete _camera;
}
if(_distortionModel)
{
delete _distortionModel;
}
delete _camera;
delete _distortionModel;
delete _stereoDense;
}
@@ -122,6 +117,7 @@ void CameraThread::enableBilateralFiltering(float sigmaS, float sigmaR)
void CameraThread::mainLoopBegin()
{
ULogger::registerCurrentThread("Camera");
_camera->resetTimer();
}
void CameraThread::mainLoop()
@@ -268,6 +264,33 @@ void CameraThread::postUpdate(SensorData * dataPtr, CameraInfo * info) const
}
if(info) info->timeMirroring = timer.ticks();
}
if(_stereoExposureCompensation && !data.imageRaw().empty() && !data.rightRaw().empty())
{
#if CV_MAJOR_VERSION < 3
UWARN("Stereo exposure compensation not implemented for OpenCV version under 3.");
#else
UDEBUG("");
UTimer timer;
cv::Ptr<cv::detail::ExposureCompensator> compensator = cv::detail::ExposureCompensator::createDefault(cv::detail::ExposureCompensator::GAIN);
std::vector<cv::Point> topLeftCorners(2, cv::Point(0,0));
std::vector<cv::UMat> images;
std::vector<cv::UMat> masks(2, cv::UMat(data.imageRaw().size(), CV_8UC1, cv::Scalar(255)));
images.push_back(data.imageRaw().getUMat(cv::ACCESS_READ));
images.push_back(data.rightRaw().getUMat(cv::ACCESS_READ));
compensator->feed(topLeftCorners, images, masks);
cv::Mat img = data.imageRaw().clone();
compensator->apply(0, cv::Point(0,0), img, masks[0]);
data.setImageRaw(img);
img = data.rightRaw().clone();
compensator->apply(1, cv::Point(0,0), img, masks[1]);
data.setDepthOrRightRaw(img);
cv::detail::GainCompensator * gainCompensator = (cv::detail::GainCompensator*)compensator.get();
UDEBUG("gains = %f %f ", gainCompensator->gains()[0], gainCompensator->gains()[1]);
if(info) info->timeStereoExposureCompensation = timer.ticks();
#endif
}
if(_stereoToDepth && !data.imageRaw().empty() && data.stereoCameraModel().isValidForProjection() && !data.rightRaw().empty())
{
UDEBUG("");
@@ -283,7 +306,8 @@ void CameraThread::postUpdate(SensorData * dataPtr, CameraInfo * info) const
data.stereoCameraModel().left().cx(),
data.stereoCameraModel().left().cy(),
data.stereoCameraModel().localTransform(),
-data.stereoCameraModel().baseline()*data.stereoCameraModel().left().fx());
-data.stereoCameraModel().baseline()*data.stereoCameraModel().left().fx(),
data.stereoCameraModel().left().imageSize());
data.setCameraModel(model);
data.setDepthOrRightRaw(depth);
data.setStereoCameraModel(StereoCameraModel());
@@ -295,7 +319,7 @@ void CameraThread::postUpdate(SensorData * dataPtr, CameraInfo * info) const
!data.depthRaw().empty())
{
UDEBUG("");
if(data.laserScanRaw().empty())
if(data.laserScanRaw().isEmpty())
{
UASSERT(_scanDecimation >= 1);
UTimer timer;
@@ -309,6 +333,7 @@ void CameraThread::postUpdate(SensorData * dataPtr, CameraInfo * info) const
float maxPoints = (data.depthRaw().rows/_scanDecimation)*(data.depthRaw().cols/_scanDecimation);
cv::Mat scan;
const Transform & baseToScan = data.cameraModels()[0].localTransform();
LaserScan::Format format = LaserScan::kXYZRGB;
if(validIndices->size())
{
if(_scanVoxelSize>0.0f)
@@ -333,6 +358,7 @@ void CameraThread::postUpdate(SensorData * dataPtr, CameraInfo * info) const
pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr cloudNormals(new pcl::PointCloud<pcl::PointXYZRGBNormal>);
pcl::concatenateFields(*cloud, *normals, *cloudNormals);
scan = util3d::laserScanFromPointCloud(*cloudNormals, baseToScan.inverse());
format = LaserScan::kXYZRGBNormal;
}
else
{
@@ -340,7 +366,7 @@ void CameraThread::postUpdate(SensorData * dataPtr, CameraInfo * info) const
}
}
}
data.setLaserScanRaw(scan, LaserScanInfo((int)maxPoints, _scanMaxDepth, baseToScan));
data.setLaserScanRaw(LaserScan(scan, (int)maxPoints, _scanMaxDepth, format, baseToScan));
if(info) info->timeScanFromDepth = timer.ticks();
}
else
+22 -1
View File
@@ -139,7 +139,11 @@ cv::Mat uncompressImage(const cv::Mat & bytes)
#endif
if(image.type() == CV_8UC4)
{
image = cv::Mat(image.size(), CV_32FC1, image.data).clone();
// Using clone() or copyTo() caused a memory leak !?!?
// image = cv::Mat(image.size(), CV_32FC1, image.data).clone();
cv::Mat depth(image.size(), CV_32FC1);
memcpy(depth.data, image.data, image.total()*image.elemSize());
image = depth;
}
}
return image;
@@ -270,4 +274,21 @@ cv::Mat uncompressData(const unsigned char * bytes, unsigned long size)
return data;
}
cv::Mat compressString(const std::string & str)
{
// +1 to include null character
return compressData2(cv::Mat(1, str.size()+1, CV_8SC1, (void *)str.data()));
}
std::string uncompressString(const cv::Mat & bytes)
{
cv::Mat strMat = uncompressData(bytes);
if(!strMat.empty())
{
UASSERT(strMat.type() == CV_8SC1 && strMat.rows == 1);
return (const char*)strMat.data;
}
return "";
}
} /* namespace rtabmap */
+63 -16
View File
@@ -29,12 +29,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "rtabmap/core/Signature.h"
#include "rtabmap/core/VisualWord.h"
#include "rtabmap/core/DBDriverSqlite3.h"
#include "rtabmap/utilite/UConversion.h"
#include "rtabmap/utilite/UMath.h"
#include "rtabmap/utilite/ULogger.h"
#include "rtabmap/utilite/UTimer.h"
#include "rtabmap/utilite/UStl.h"
#include "DBDriverSqlite3.h"
namespace rtabmap {
@@ -245,15 +245,33 @@ ParametersMap DBDriver::getLastParameters() const
return parameters;
}
std::map<std::string, float> DBDriver::getStatistics(int nodeId, double & stamp) const
std::map<std::string, float> DBDriver::getStatistics(int nodeId, double & stamp, std::vector<int> * wmState) const
{
std::map<std::string, float> statistics;
_dbSafeAccessMutex.lock();
statistics = getStatisticsQuery(nodeId, stamp);
statistics = getStatisticsQuery(nodeId, stamp, wmState);
_dbSafeAccessMutex.unlock();
return statistics;
}
std::map<int, std::pair<std::map<std::string, float>, double> > DBDriver::getAllStatistics() const
{
std::map<int, std::pair<std::map<std::string, float>, double> > statistics;
_dbSafeAccessMutex.lock();
statistics = getAllStatisticsQuery();
_dbSafeAccessMutex.unlock();
return statistics;
}
std::map<int, std::vector<int> > DBDriver::getAllStatisticsWmStates() const
{
std::map<int, std::vector<int> > wmStates;
_dbSafeAccessMutex.lock();
wmStates = getAllStatisticsWmStatesQuery();
_dbSafeAccessMutex.unlock();
return wmStates;
}
std::string DBDriver::getDatabaseVersion() const
{
std::string version = "0.0.0";
@@ -386,7 +404,7 @@ void DBDriver::asyncSave(VisualWord * vw)
}
}
void DBDriver::saveOrUpdate(const std::vector<Signature *> & signatures) const
void DBDriver::saveOrUpdate(const std::vector<Signature *> & signatures)
{
ULOGGER_DEBUG("");
std::list<Signature *> toSave;
@@ -418,7 +436,7 @@ void DBDriver::saveOrUpdate(const std::vector<Signature *> & signatures) const
void DBDriver::saveOrUpdate(const std::vector<VisualWord *> & words) const
{
ULOGGER_DEBUG("");
ULOGGER_DEBUG("words.size=%d", (int)words.size());
std::list<VisualWord *> toSave;
std::list<VisualWord *> toUpdate;
if(this->isConnected() && words.size())
@@ -466,17 +484,19 @@ void DBDriver::updateOccupancyGrid(
int nodeId,
const cv::Mat & ground,
const cv::Mat & obstacles,
const cv::Mat & empty,
float cellSize,
const cv::Point3f & viewpoint)
{
_dbSafeAccessMutex.lock();
//just to make sure the occupancy grids are compressed for convenience
SensorData data;
data.setOccupancyGrid(ground, obstacles, cellSize, viewpoint);
data.setOccupancyGrid(ground, obstacles, empty, cellSize, viewpoint);
this->updateOccupancyGridQuery(
nodeId,
data.gridGroundCellsCompressed(),
data.gridObstacleCellsCompressed(),
data.gridEmptyCellsCompressed(),
cellSize,
viewpoint);
_dbSafeAccessMutex.unlock();
@@ -491,10 +511,10 @@ void DBDriver::updateDepthImage(int nodeId, const cv::Mat & image)
_dbSafeAccessMutex.unlock();
}
void DBDriver::load(VWDictionary * dictionary) const
void DBDriver::load(VWDictionary * dictionary, bool lastStateOnly) const
{
_dbSafeAccessMutex.lock();
this->loadQuery(dictionary);
this->loadQuery(dictionary, lastStateOnly);
_dbSafeAccessMutex.unlock();
}
@@ -631,7 +651,7 @@ void DBDriver::getNodeData(
{
const Signature * s = _trashSignatures.at(signatureId);
if(!s->sensorData().imageCompressed().empty() ||
!s->sensorData().laserScanCompressed().empty() ||
!s->sensorData().laserScanCompressed().isEmpty() ||
!s->sensorData().userDataCompressed().empty() ||
s->sensorData().gridCellSize() != 0.0f ||
!s->isSaved())
@@ -682,7 +702,7 @@ bool DBDriver::getCalibration(
bool DBDriver::getLaserScanInfo(
int signatureId,
LaserScanInfo & info) const
LaserScan & info) const
{
UDEBUG("");
bool found = false;
@@ -690,7 +710,7 @@ bool DBDriver::getLaserScanInfo(
_trashesMutex.lock();
if(uContains(_trashSignatures, signatureId))
{
info = _trashSignatures.at(signatureId)->sensorData().laserScanInfo();
info = _trashSignatures.at(signatureId)->sensorData().laserScanCompressed();
found = true;
}
_trashesMutex.unlock();
@@ -1041,9 +1061,37 @@ cv::Mat DBDriver::loadPreviewImage() const
return image;
}
void DBDriver::saveOptimizedPoses(const std::map<int, Transform> & optimizedPoses, const Transform & lastlocalizationPose) const
{
_dbSafeAccessMutex.lock();
saveOptimizedPosesQuery(optimizedPoses, lastlocalizationPose);
_dbSafeAccessMutex.unlock();
}
std::map<int, Transform> DBDriver::loadOptimizedPoses(Transform * lastlocalizationPose) const
{
_dbSafeAccessMutex.lock();
std::map<int, Transform> poses = loadOptimizedPosesQuery(lastlocalizationPose);
_dbSafeAccessMutex.unlock();
return poses;
}
void DBDriver::save2DMap(const cv::Mat & map, float xMin, float yMin, float cellSize) const
{
_dbSafeAccessMutex.lock();
save2DMapQuery(map, xMin, yMin, cellSize);
_dbSafeAccessMutex.unlock();
}
cv::Mat DBDriver::load2DMap(float & xMin, float & yMin, float & cellSize) const
{
_dbSafeAccessMutex.lock();
cv::Mat map = load2DMapQuery(xMin, yMin, cellSize);
_dbSafeAccessMutex.unlock();
return map;
}
void DBDriver::saveOptimizedMesh(
const cv::Mat & cloud,
const std::map<int, Transform> & poses,
const std::vector<std::vector<std::vector<unsigned int> > > & polygons,
#if PCL_VERSION_COMPARE(>=, 1, 8, 0)
const std::vector<std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > > & texCoords,
@@ -1053,22 +1101,21 @@ void DBDriver::saveOptimizedMesh(
const cv::Mat & textures) const
{
_dbSafeAccessMutex.lock();
saveOptimizedMeshQuery(cloud, poses, polygons, texCoords, textures);
saveOptimizedMeshQuery(cloud, polygons, texCoords, textures);
_dbSafeAccessMutex.unlock();
}
cv::Mat DBDriver::loadOptimizedMesh(
std::map<int, Transform> * poses,
std::vector<std::vector<std::vector<unsigned int> > > * polygons,
#if PCL_VERSION_COMPARE(>=, 1, 8, 0)
std::vector<std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f>> > * texCoords,
std::vector<std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > > * texCoords,
#else
std::vector<std::vector<Eigen::Vector2f> > * texCoords,
#endif
cv::Mat * textures) const
{
_dbSafeAccessMutex.lock();
cv::Mat cloud = loadOptimizedMeshQuery(poses, polygons, texCoords, textures);
cv::Mat cloud = loadOptimizedMeshQuery(polygons, texCoords, textures);
_dbSafeAccessMutex.unlock();
return cloud;
}
File diff suppressed because it is too large Load Diff
+7 -3
View File
@@ -27,7 +27,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "rtabmap/core/DBReader.h"
#include "rtabmap/core/DBDriver.h"
#include "DBDriverSqlite3.h"
#include <rtabmap/utilite/ULogger.h>
#include <rtabmap/utilite/UFile.h>
@@ -131,7 +130,7 @@ bool DBReader::init(
rtabmap::ParametersMap parameters;
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kDbSqlite3InMemory(), "false"));
_dbDriver = new DBDriverSqlite3(parameters);
_dbDriver = DBDriver::create(parameters);
if(!_dbDriver)
{
UERROR("Driver doesn't exist.");
@@ -401,6 +400,10 @@ SensorData DBReader::getNextData(CameraInfo * info)
_previousStamp = stamp;
_previousMapID = mapId;
}
else
{
stamp = 0;
}
data.uncompressData();
if(data.cameraModels().size() > 1 &&
@@ -439,7 +442,7 @@ SensorData DBReader::getNextData(CameraInfo * info)
data.setGroundTruth(groundTruth);
data.setGPS(gps);
UDEBUG("Laser=%d RGB/Left=%d Depth/Right=%d, UserData=%d",
data.laserScanRaw().empty()?0:1,
data.laserScanRaw().isEmpty()?0:1,
data.imageRaw().empty()?0:1,
data.depthOrRightRaw().empty()?0:1,
data.userDataRaw().empty()?0:1);
@@ -456,6 +459,7 @@ SensorData DBReader::getNextData(CameraInfo * info)
{
info->odomPose = pose;
info->odomCovariance = infMatrix.inv();
info->odomVelocity = velocity;
UDEBUG("odom variance = %f/%f", info->odomCovariance.at<double>(0,0), info->odomCovariance.at<double>(5,5));
}
}
+63 -20
View File
@@ -327,7 +327,9 @@ Feature2D::Feature2D(const ParametersMap & parameters) :
_roiRatios(std::vector<float>(4, 0.0f)),
_subPixWinSize(Parameters::defaultKpSubPixWinSize()),
_subPixIterations(Parameters::defaultKpSubPixIterations()),
_subPixEps(Parameters::defaultKpSubPixEps())
_subPixEps(Parameters::defaultKpSubPixEps()),
gridRows_(Parameters::defaultKpGridRows()),
gridCols_(Parameters::defaultKpGridCols())
{
_stereo = new Stereo(parameters);
this->parseParameters(parameters);
@@ -346,6 +348,14 @@ void Feature2D::parseParameters(const ParametersMap & parameters)
Parameters::parse(parameters, Parameters::kKpSubPixWinSize(), _subPixWinSize);
Parameters::parse(parameters, Parameters::kKpSubPixIterations(), _subPixIterations);
Parameters::parse(parameters, Parameters::kKpSubPixEps(), _subPixEps);
Parameters::parse(parameters, Parameters::kKpGridRows(), gridRows_);
Parameters::parse(parameters, Parameters::kKpGridCols(), gridCols_);
UASSERT(gridRows_ >= 1 && gridCols_>=1);
if(maxFeatures_ > 0)
{
maxFeatures_ = maxFeatures_ / (gridRows_ * gridCols_);
}
// convert ROI from string to vector
ParametersMap::const_iterator iter;
@@ -533,23 +543,36 @@ std::vector<cv::KeyPoint> Feature2D::generateKeypoints(const cv::Mat & image, co
std::vector<cv::KeyPoint> keypoints;
UTimer timer;
cv::Rect globalRoi = Feature2D::computeRoi(image, _roiRatios);
if(!(globalRoi.width && globalRoi.height))
{
globalRoi = cv::Rect(0,0,image.cols, image.rows);
}
// Get keypoints
cv::Rect roi = Feature2D::computeRoi(image, _roiRatios);
keypoints = this->generateKeypointsImpl(image, roi.width && roi.height?roi:cv::Rect(0,0,image.cols, image.rows), mask);
UDEBUG("Keypoints extraction time = %f s, keypoints extracted = %d (mask empty=%d)", timer.ticks(), keypoints.size(), mask.empty()?1:0);
limitKeypoints(keypoints, maxFeatures_);
if(roi.x || roi.y)
int rowSize = globalRoi.height / gridRows_;
int colSize = globalRoi.width / gridCols_;
for (int i = 0; i<gridRows_; ++i)
{
// Adjust keypoint position to raw image
for(std::vector<cv::KeyPoint>::iterator iter=keypoints.begin(); iter!=keypoints.end(); ++iter)
for (int j = 0; j<gridCols_; ++j)
{
iter->pt.x += roi.x;
iter->pt.y += roi.y;
cv::Rect roi(globalRoi.x + j*colSize, globalRoi.y + i*rowSize, colSize, rowSize);
std::vector<cv::KeyPoint> sub_keypoints;
sub_keypoints = this->generateKeypointsImpl(image, roi, mask);
limitKeypoints(sub_keypoints, maxFeatures_);
if(roi.x || roi.y)
{
// Adjust keypoint position to raw image
for(std::vector<cv::KeyPoint>::iterator iter=sub_keypoints.begin(); iter!=sub_keypoints.end(); ++iter)
{
iter->pt.x += roi.x;
iter->pt.y += roi.y;
}
}
keypoints.insert( keypoints.end(), sub_keypoints.begin(), sub_keypoints.end() );
}
}
UDEBUG("Keypoints extraction time = %f s, keypoints extracted = %d (mask empty=%d)", timer.ticks(), keypoints.size(), mask.empty()?1:0);
if(keypoints.size() && _subPixWinSize > 0 && _subPixIterations > 0)
{
@@ -900,11 +923,11 @@ void ORB::parseParameters(const ParametersMap & parameters)
gpu_ = false;
}
#endif
if(gpu_)
if(gpu_ && cv::cuda::getCudaEnabledDeviceCount() == 0)
{
UWARN("GPU version of ORB available but not implemented yet! Using CPU version instead...");
UWARN("GPU version of ORB not available (no GPU found)! Using CPU version instead...");
gpu_ = false;
}
gpu_ = false;
#endif
if(gpu_)
{
@@ -917,7 +940,7 @@ void ORB::parseParameters(const ParametersMap & parameters)
#endif
#else
#ifdef HAVE_OPENCV_CUDAFEATURES2D
UFATAL("not implemented");
_gpuOrb = CV_ORB_GPU::create(this->getMaxFeatures(), scaleFactor_, nLevels_, edgeThreshold_, firstLevel_, WTA_K_, scoreType_, patchSize_, fastThreshold_);
#endif
#endif
}
@@ -954,7 +977,14 @@ std::vector<cv::KeyPoint> ORB::generateKeypointsImpl(const cv::Mat & image, cons
#endif
#else
#ifdef HAVE_OPENCV_CUDAFEATURES2D
UFATAL("not implemented");
cv::cuda::GpuMat d_image(imgRoi);
cv::cuda::GpuMat d_mask(maskRoi);
try {
_gpuOrb->detectAndCompute(d_image, d_mask, keypoints, cv::cuda::GpuMat(), false);
} catch (cv::Exception& e) {
const char* err_msg = e.what();
UWARN("OpenCV exception caught: %s", err_msg);
}
#endif
#endif
}
@@ -995,10 +1025,23 @@ cv::Mat ORB::generateDescriptorsImpl(const cv::Mat & image, std::vector<cv::KeyP
UERROR("GPU version of ORB not available (OpenCV not built with gpu/cuda module)! Using CPU version instead...");
#endif
#else
cv::cuda::GpuMat imgGpu(image);
cv::cuda::GpuMat descriptorsGPU;
#ifdef HAVE_OPENCV_CUDAFEATURES2D
UFATAL("not implemented");
cv::cuda::GpuMat d_image(image);
cv::cuda::GpuMat d_descriptors;
try {
_gpuOrb->detectAndCompute(d_image, cv::cuda::GpuMat(), keypoints, d_descriptors, true);
} catch (cv::Exception& e) {
const char* err_msg = e.what();
UWARN("OpenCV exception caught: %s", err_msg);
}
// Download descriptors
if (d_descriptors.empty())
descriptors = cv::Mat();
else
{
UASSERT(d_descriptors.type() == CV_32F || d_descriptors.type() == CV_8U);
d_descriptors.download(descriptors);
}
#endif
#endif
}
+21 -12
View File
@@ -38,7 +38,8 @@ FlannIndex::FlannIndex():
featuresType_(0),
featuresDim_(0),
isLSH_(false),
useDistanceL1_(false)
useDistanceL1_(false),
rebalancingFactor_(2.0f)
{
}
FlannIndex::~FlannIndex()
@@ -134,7 +135,8 @@ unsigned int FlannIndex::memoryUsed() const
void FlannIndex::buildLinearIndex(
const cv::Mat & features,
bool useDistanceL1)
bool useDistanceL1,
float rebalancingFactor)
{
this->release();
UASSERT(index_ == 0);
@@ -142,6 +144,7 @@ void FlannIndex::buildLinearIndex(
featuresType_ = features.type();
featuresDim_ = features.cols;
useDistanceL1_ = useDistanceL1;
rebalancingFactor_ = rebalancingFactor;
rtflann::LinearIndexParams params;
@@ -180,7 +183,8 @@ void FlannIndex::buildLinearIndex(
void FlannIndex::buildKDTreeIndex(
const cv::Mat & features,
int trees,
bool useDistanceL1)
bool useDistanceL1,
float rebalancingFactor)
{
this->release();
UASSERT(index_ == 0);
@@ -188,6 +192,7 @@ void FlannIndex::buildKDTreeIndex(
featuresType_ = features.type();
featuresDim_ = features.cols;
useDistanceL1_ = useDistanceL1;
rebalancingFactor_ = rebalancingFactor;
rtflann::KDTreeIndexParams params(trees);
@@ -227,7 +232,8 @@ void FlannIndex::buildKDTreeSingleIndex(
const cv::Mat & features,
int leafMaxSize,
bool reorder,
bool useDistanceL1)
bool useDistanceL1,
float rebalancingFactor)
{
this->release();
UASSERT(index_ == 0);
@@ -235,6 +241,7 @@ void FlannIndex::buildKDTreeSingleIndex(
featuresType_ = features.type();
featuresDim_ = features.cols;
useDistanceL1_ = useDistanceL1;
rebalancingFactor_ = rebalancingFactor;
rtflann::KDTreeSingleIndexParams params(leafMaxSize, reorder);
@@ -274,7 +281,8 @@ void FlannIndex::buildLSHIndex(
const cv::Mat & features,
unsigned int table_number,
unsigned int key_size,
unsigned int multi_probe_level)
unsigned int multi_probe_level,
float rebalancingFactor)
{
this->release();
UASSERT(index_ == 0);
@@ -282,6 +290,7 @@ void FlannIndex::buildLSHIndex(
featuresType_ = features.type();
featuresDim_ = features.cols;
useDistanceL1_ = true;
rebalancingFactor_ = rebalancingFactor;
rtflann::Matrix<unsigned char> dataset(features.data, features.rows, features.cols);
index_ = new rtflann::Index<rtflann::Hamming<unsigned char> >(dataset, rtflann::LshIndexParams(12, 20, 2));
@@ -315,8 +324,8 @@ unsigned int FlannIndex::addPoints(const cv::Mat & features)
rtflann::Index<rtflann::Hamming<unsigned char> > * index = (rtflann::Index<rtflann::Hamming<unsigned char> >*)index_;
removedPts = index->removedCount();
index->addPoints(points, 0);
// Rebuild index if it doubles in size
if(index->sizeAtBuild() * 2 < index->size()+index->removedCount())
// Rebuild index if it is now X times in size
if(rebalancingFactor_ > 1.0f && size_t(float(index->sizeAtBuild()) * rebalancingFactor_) < index->size()+index->removedCount())
{
UDEBUG("Rebuilding FLANN index: %d -> %d", (int)index->sizeAtBuild(), (int)(index->size()+index->removedCount()));
index->buildIndex();
@@ -333,7 +342,7 @@ unsigned int FlannIndex::addPoints(const cv::Mat & features)
removedPts = index->removedCount();
index->addPoints(points, 0);
// Rebuild index if it doubles in size
if(index->sizeAtBuild() * 2 < index->size()+index->removedCount())
if(rebalancingFactor_ > 1.0f && size_t(float(index->sizeAtBuild()) * rebalancingFactor_) < index->size()+index->removedCount())
{
UDEBUG("Rebuilding FLANN index: %d -> %d", (int)index->sizeAtBuild(), (int)(index->size()+index->removedCount()));
index->buildIndex();
@@ -347,7 +356,7 @@ unsigned int FlannIndex::addPoints(const cv::Mat & features)
removedPts = index->removedCount();
index->addPoints(points, 0);
// Rebuild index if it doubles in size
if(index->sizeAtBuild() * 2 < index->size()+index->removedCount())
if(rebalancingFactor_ > 1.0f && size_t(float(index->sizeAtBuild()) * rebalancingFactor_) < index->size()+index->removedCount())
{
UDEBUG("Rebuilding FLANN index: %d -> %d", (int)index->sizeAtBuild(), (int)(index->size()+index->removedCount()));
index->buildIndex();
@@ -361,7 +370,7 @@ unsigned int FlannIndex::addPoints(const cv::Mat & features)
removedPts = index->removedCount();
index->addPoints(points, 0);
// Rebuild index if it doubles in size
if(index->sizeAtBuild() * 2 < index->size()+index->removedCount())
if(rebalancingFactor_ > 1.0f && size_t(float(index->sizeAtBuild()) * rebalancingFactor_) < index->size()+index->removedCount())
{
UDEBUG("Rebuilding FLANN index: %d -> %d", (int)index->sizeAtBuild(), (int)(index->size()+index->removedCount()));
index->buildIndex();
@@ -436,10 +445,10 @@ void FlannIndex::knnSearch(
UERROR("Flann index not yet created!");
return;
}
indices.create(query.rows, knn, CV_32S);
indices.create(query.rows, knn, sizeof(size_t)==8?CV_64F:CV_32S);
dists.create(query.rows, knn, featuresType_ == CV_8UC1?CV_32S:CV_32F);
rtflann::Matrix<int> indicesF((int*)indices.data, indices.rows, indices.cols);
rtflann::Matrix<size_t> indicesF((size_t*)indices.data, indices.rows, indices.cols);
rtflann::SearchParams params = rtflann::SearchParams(checks, eps, sorted);
+221 -16
View File
@@ -35,6 +35,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <rtabmap/core/GeodeticCoords.h>
#include <rtabmap/core/Memory.h>
#include <rtabmap/core/util3d_filtering.h>
#include <rtabmap/core/util3d_registration.h>
#include <pcl/search/kdtree.h>
#include <pcl/common/eigen.h>
#include <pcl/common/common.h>
@@ -160,10 +161,10 @@ bool exportPoses(
bool importPoses(
const std::string & filePath,
int format, // 0=Raw, 1=RGBD-SLAM, 2=KITTI, 3=TORO, 4=g2o, 5=NewCollege(t,x,y), 6=Malaga Urban GPS, 7=St Lucia INS, 8=Karlsruhe
int format, // 0=Raw, 1=RGBD-SLAM, 2=KITTI, 3=TORO, 4=g2o, 5=NewCollege(t,x,y), 6=Malaga Urban GPS, 7=St Lucia INS, 8=Karlsruhe, 9=EuRoC MAC
std::map<int, Transform> & poses,
std::multimap<int, Link> * constraints, // optional for formats 3 and 4
std::map<int, double> * stamps) // optional for format 1
std::map<int, double> * stamps) // optional for format 1 and 9
{
UDEBUG("%s format=%d", filePath.c_str(), format);
if(format==3) // TORO
@@ -201,12 +202,50 @@ bool importPoses(
std::string str;
std::getline(file, str);
if(str.size() && str.at(str.size()-1) == '\r')
{
str = str.substr(0, str.size()-1);
}
if(str.empty() || str.at(0) == '#' || str.at(0) == '%')
{
continue;
}
if(format == 8) // Karlsruhe format
if(format == 9) // EuRoC format
{
std::list<std::string> strList = uSplit(str, ',');
if(strList.size() == 17)
{
double stamp = uStr2Double(strList.front())/1000000000.0;
strList.pop_front();
std::vector<std::string> v = uListToVector(strList);
Transform pose(uStr2Float(v[0]), uStr2Float(v[1]), uStr2Float(v[2]), // x y z
uStr2Float(v[4]), uStr2Float(v[5]), uStr2Float(v[6]), uStr2Float(v[3])); // qw qx qy qz -> qx qy qz qw
if(pose.isNull())
{
UWARN("Null transform read!? line parsed: \"%s\"", str.c_str());
}
else
{
if(stamps)
{
stamps->insert(std::make_pair(id, stamp));
}
// we need to rotate from IMU frame to world frame
Transform t( 0, 0, 1, 0,
0, -1, 0, 0,
1, 0, 0, 0);
pose = pose * t;
poses.insert(std::make_pair(id, pose));
}
}
else
{
UERROR("Error parsing \"%s\" with EuRoC MAV format (should have 17 values: stamp x y z qw qx qy qz vx vy vz vr vp vy ax ay az)", str.c_str());
}
}
else if(format == 8) // Karlsruhe format
{
std::vector<std::string> strList = uListToVector(uSplit(str));
if(strList.size() == 10)
@@ -363,7 +402,7 @@ bool importPoses(
}
else
{
UERROR("Error parsing \"%s\" with NewCollege format (should have 3 values: stamp x y)", str.c_str());
UERROR("Error parsing \"%s\" with NewCollege format (should have 3 values: stamp x y, found %d)", str.c_str(), (int)strList.size());
}
}
else if(format == 1) // rgbd-slam format
@@ -642,6 +681,143 @@ void calcKittiSequenceErrors (
}
// KITTI evaluation end
Transform calcRMSE (
const std::map<int, Transform> & groundTruth,
const std::map<int, Transform> & poses,
float & translational_rmse,
float & translational_mean,
float & translational_median,
float & translational_std,
float & translational_min,
float & translational_max,
float & rotational_rmse,
float & rotational_mean,
float & rotational_median,
float & rotational_std,
float & rotational_min,
float & rotational_max)
{
translational_rmse = 0.0f;
translational_mean = 0.0f;
translational_median = 0.0f;
translational_std = 0.0f;
translational_min = 0.0f;
translational_max = 0.0f;
rotational_rmse = 0.0f;
rotational_mean = 0.0f;
rotational_median = 0.0f;
rotational_std = 0.0f;
rotational_min = 0.0f;
rotational_max = 0.0f;
//align with ground truth for more meaningful results
pcl::PointCloud<pcl::PointXYZ> cloud1, cloud2;
cloud1.resize(poses.size());
cloud2.resize(poses.size());
int oi = 0;
int idFirst = 0;
for(std::map<int, Transform>::const_iterator iter=poses.begin(); iter!=poses.end(); ++iter)
{
std::map<int, Transform>::const_iterator jter=groundTruth.find(iter->first);
if(jter != groundTruth.end())
{
if(oi==0)
{
idFirst = iter->first;
}
cloud1[oi] = pcl::PointXYZ(jter->second.x(), jter->second.y(), jter->second.z());
cloud2[oi++] = pcl::PointXYZ(iter->second.x(), iter->second.y(), iter->second.z());
}
}
Transform t = Transform::getIdentity();
if(oi>5)
{
cloud1.resize(oi);
cloud2.resize(oi);
t = util3d::transformFromXYZCorrespondencesSVD(cloud2, cloud1);
}
else if(idFirst)
{
t = groundTruth.at(idFirst) * poses.at(idFirst).inverse();
}
std::vector<float> translationalErrors(poses.size());
std::vector<float> rotationalErrors(poses.size());
float sumTranslationalErrors = 0.0f;
float sumRotationalErrors = 0.0f;
float sumSqrdTranslationalErrors = 0.0f;
float sumSqrdRotationalErrors = 0.0f;
float radToDegree = 180.0f / M_PI;
oi=0;
for(std::map<int, Transform>::const_iterator iter=poses.begin(); iter!=poses.end(); ++iter)
{
std::map<int, Transform>::const_iterator jter = groundTruth.find(iter->first);
if(jter!=groundTruth.end())
{
Transform pose = t * iter->second;
Eigen::Vector3f xAxis(1,0,0);
Eigen::Vector3f vA = pose.toEigen3f().linear()*xAxis;
Eigen::Vector3f vB = jter->second.toEigen3f().linear()*xAxis;
double a = pcl::getAngle3D(Eigen::Vector4f(vA[0], vA[1], vA[2], 0), Eigen::Vector4f(vB[0], vB[1], vB[2], 0));
rotationalErrors[oi] = a*radToDegree;
translationalErrors[oi] = pose.getDistance(jter->second);
sumTranslationalErrors+=translationalErrors[oi];
sumSqrdTranslationalErrors+=translationalErrors[oi]*translationalErrors[oi];
sumRotationalErrors+=rotationalErrors[oi];
sumSqrdRotationalErrors+=rotationalErrors[oi]*rotationalErrors[oi];
if(oi == 0)
{
translational_min = translational_max = translationalErrors[oi];
rotational_min = rotational_max = rotationalErrors[oi];
}
else
{
if(translationalErrors[oi] < translational_min)
{
translational_min = translationalErrors[oi];
}
else if(translationalErrors[oi] > translational_max)
{
translational_max = translationalErrors[oi];
}
if(rotationalErrors[oi] < rotational_min)
{
rotational_min = rotationalErrors[oi];
}
else if(rotationalErrors[oi] > rotational_max)
{
rotational_max = rotationalErrors[oi];
}
}
++oi;
}
}
translationalErrors.resize(oi);
rotationalErrors.resize(oi);
if(oi)
{
float total = float(oi);
translational_rmse = std::sqrt(sumSqrdTranslationalErrors/total);
translational_mean = sumTranslationalErrors/total;
translational_median = translationalErrors[oi/2];
translational_std = std::sqrt(uVariance(translationalErrors, translational_mean));
rotational_rmse = std::sqrt(sumSqrdRotationalErrors/total);
rotational_mean = sumRotationalErrors/total;
rotational_median = rotationalErrors[oi/2];
rotational_std = std::sqrt(uVariance(rotationalErrors, rotational_mean));
}
return t;
}
////////////////////////////////////////////
// Graph utilities
@@ -773,6 +949,20 @@ std::multimap<int, int>::const_iterator findLink(
return links.end();
}
std::multimap<int, Link> filterDuplicateLinks(
const std::multimap<int, Link> & links)
{
std::multimap<int, Link> output;
for(std::multimap<int, Link>::const_iterator iter=links.begin(); iter!=links.end(); ++iter)
{
if(graph::findLink(output, iter->second.from(), iter->second.to(), true) == output.end())
{
output.insert(*iter);
}
}
return output;
}
std::multimap<int, Link> filterLinks(
const std::multimap<int, Link> & links,
Link::Type filteredType)
@@ -888,7 +1078,7 @@ std::map<int, Transform> radiusPosesFiltering(
std::set<int> cloudIndices;
const Transform & currentT = transforms.at(i);
Eigen::Vector3f vA = currentT.toEigen3f().rotation()*Eigen::Vector3f(1,0,0);
Eigen::Vector3f vA = currentT.toEigen3f().linear()*Eigen::Vector3f(1,0,0);
for(unsigned int j=0; j<kIndices.size(); ++j)
{
if(indicesChecked.find(kIndices[j]) == indicesChecked.end())
@@ -897,7 +1087,7 @@ std::map<int, Transform> radiusPosesFiltering(
{
const Transform & checkT = transforms.at(kIndices[j]);
// same orientation?
Eigen::Vector3f vB = checkT.toEigen3f().rotation()*Eigen::Vector3f(1,0,0);
Eigen::Vector3f vB = checkT.toEigen3f().linear()*Eigen::Vector3f(1,0,0);
double a = pcl::getAngle3D(Eigen::Vector4f(vA[0], vA[1], vA[2], 0), Eigen::Vector4f(vB[0], vB[1], vB[2], 0));
if(a <= angle)
{
@@ -993,7 +1183,7 @@ std::multimap<int, int> radiusPosesClustering(const std::map<int, Transform> & p
std::set<int> cloudIndices;
const Transform & currentT = transforms.at(i);
Eigen::Vector3f vA = currentT.toEigen3f().rotation()*Eigen::Vector3f(1,0,0);
Eigen::Vector3f vA = currentT.toEigen3f().linear()*Eigen::Vector3f(1,0,0);
for(unsigned int j=0; j<kIndices.size(); ++j)
{
if((int)i != kIndices[j])
@@ -1002,7 +1192,7 @@ std::multimap<int, int> radiusPosesClustering(const std::map<int, Transform> & p
{
const Transform & checkT = transforms.at(kIndices[j]);
// same orientation?
Eigen::Vector3f vB = checkT.toEigen3f().rotation()*Eigen::Vector3f(1,0,0);
Eigen::Vector3f vB = checkT.toEigen3f().linear()*Eigen::Vector3f(1,0,0);
double a = pcl::getAngle3D(Eigen::Vector4f(vA[0], vA[1], vA[2], 0), Eigen::Vector4f(vB[0], vB[1], vB[2], 0));
if(a <= angle)
{
@@ -1644,7 +1834,7 @@ std::list<std::pair<int, Transform> > computePath(
{
//Transform nextPose = iter->second;
//Eigen::Vector4f v1 = Eigen::Vector4f(nextPose.x()-previousIter->second.x(), nextPose.y()-previousIter->second.y(), nextPose.z()-previousIter->second.z(), 1.0f);
//Eigen::Vector4f v2 = nextPose.rotation().toEigen4f()*Eigen::Vector4f(1,0,0,1);
//Eigen::Vector4f v2 = nextPose.linear().toEigen4f()*Eigen::Vector4f(1,0,0,1);
//float angle = pcl::getAngle3D(v1, v2);
//float cost = angle ;
//UDEBUG("v1=%f,%f,%f v2=%f,%f,%f a=%f", v1[0], v1[1], v1[2], v2[0], v2[1], v2[2], cost);
@@ -1682,6 +1872,20 @@ int findNearestNode(
const rtabmap::Transform & targetPose)
{
int id = 0;
std::vector<int> nearestNodes = findNearestNodes(nodes, targetPose, 1);
if(nearestNodes.size())
{
id = nearestNodes[0];
}
return id;
}
std::vector<int> findNearestNodes(
const std::map<int, rtabmap::Transform> & nodes,
const rtabmap::Transform & targetPose,
int k)
{
std::vector<int> nearestIds;
if(nodes.size() && !targetPose.isNull())
{
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
@@ -1699,14 +1903,15 @@ int findNearestNode(
std::vector<int> ind;
std::vector<float> dist;
pcl::PointXYZ pt(targetPose.x(), targetPose.y(), targetPose.z());
kdTree->nearestKSearch(pt, 1, ind, dist);
if(ind.size() && dist.size() && ind[0] >= 0)
kdTree->nearestKSearch(pt, k, ind, dist);
nearestIds.resize(ind.size());
for(unsigned int i=0; i<ind.size(); ++i)
{
//UDEBUG("Nearest node = %d: %f", ids[ind[0]], dist[0]);
id = ids[ind[0]];
nearestIds[i] = ids[ind[i]];
}
}
return id;
return nearestIds;
}
// return <id, sqrd distance>, excluding query
@@ -1803,7 +2008,7 @@ std::map<int, Transform> getPosesInRadius(
pcl::PointXYZ pt(fromT.x(), fromT.y(), fromT.z());
kdTree->radiusSearch(pt, radius, ind, sqrdDist, 0);
Eigen::Vector3f vA = fromT.toEigen3f().rotation()*Eigen::Vector3f(1,0,0);
Eigen::Vector3f vA = fromT.toEigen3f().linear()*Eigen::Vector3f(1,0,0);
for(unsigned int i=0; i<ind.size(); ++i)
{
@@ -1813,7 +2018,7 @@ std::map<int, Transform> getPosesInRadius(
{
const Transform & checkT = nodes.at(ids[ind[i]]);
// same orientation?
Eigen::Vector3f vB = checkT.toEigen3f().rotation()*Eigen::Vector3f(1,0,0);
Eigen::Vector3f vB = checkT.toEigen3f().linear()*Eigen::Vector3f(1,0,0);
double a = pcl::getAngle3D(Eigen::Vector4f(vA[0], vA[1], vA[2], 0), Eigen::Vector4f(vB[0], vB[1], vB[2], 0));
if(a <= angle)
{
+154
View File
@@ -0,0 +1,154 @@
/*
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.
*/
#include "rtabmap/core/IMUThread.h"
#include "rtabmap/core/IMU.h"
#include <rtabmap/utilite/UTimer.h>
#include <rtabmap/utilite/ULogger.h>
#include <rtabmap/utilite/UConversion.h>
namespace rtabmap
{
IMUThread::IMUThread(int rate, const Transform & localTransform) :
rate_(rate),
localTransform_(localTransform),
captureDelay_(0.0),
previousStamp_(0.0)
{
}
IMUThread::~IMUThread()
{
imuFile_.close();
}
bool IMUThread::init(const std::string & path)
{
imuFile_.close();
captureDelay_ = 0.0;
previousStamp_ = 0.0;
// open the IMU file
std::string line;
imuFile_.open(path.c_str());
if (!imuFile_.good()) {
UERROR("no imu file found at %s",path.c_str());
return false;
}
int number_of_lines = 0;
while (std::getline(imuFile_, line))
++number_of_lines;
printf("No. IMU measurements: %d\n", number_of_lines-1);
if (number_of_lines - 1 <= 0) {
UERROR("no imu messages present in %s", path.c_str());
return false;
}
// set reading position to second line
imuFile_.clear();
imuFile_.seekg(0, std::ios::beg);
std::getline(imuFile_, line);
return true;
}
void IMUThread::setRate(int rate)
{
rate_ = rate;
}
void IMUThread::mainLoopBegin()
{
ULogger::registerCurrentThread("IMU");
frameRateTimer_.start();
}
void IMUThread::mainLoop()
{
UTimer totalTime;
UDEBUG("");
if(rate_>0 || captureDelay_)
{
double delay = rate_>0?1000.0/double(rate_):1000.0f*captureDelay_;
int sleepTime = delay - 1000.0f*frameRateTimer_.getElapsedTime();
if(sleepTime > 2)
{
uSleep(sleepTime-2);
}
// Add precision at the cost of a small overhead
delay/=1000.0;
while(frameRateTimer_.getElapsedTime() < delay-0.000001)
{
//
}
frameRateTimer_.start();
}
captureDelay_ = 0.0;
std::string line;
if (std::getline(imuFile_, line))
{
std::stringstream stream(line);
std::string s;
std::getline(stream, s, ',');
std::string nanoseconds = s.substr(s.size() - 9, 9);
std::string seconds = s.substr(0, s.size() - 9);
cv::Vec3d gyr;
for (int j = 0; j < 3; ++j) {
std::getline(stream, s, ',');
gyr[j] = uStr2Double(s);
}
cv::Vec3d acc;
for (int j = 0; j < 3; ++j) {
std::getline(stream, s, ',');
acc[j] = uStr2Double(s);
}
double stamp = double(uStr2Int(seconds)) + double(uStr2Int(nanoseconds))*1e-9;
if(previousStamp_>0 && stamp > previousStamp_)
{
captureDelay_ = stamp - previousStamp_;
}
previousStamp_ = stamp;
IMU imu(gyr, cv::Mat(), acc, cv::Mat(), localTransform_);
this->post(new IMUEvent(imu, stamp));
}
else if(!this->isKilled())
{
UWARN("no more imu data...");
this->kill();
this->post(new IMUEvent());
}
}
} // namespace rtabmap
+153
View File
@@ -0,0 +1,153 @@
/*
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.
*/
#include <rtabmap/core/LaserScan.h>
#include <rtabmap/utilite/ULogger.h>
#include <rtabmap/utilite/UConversion.h>
namespace rtabmap {
int LaserScan::channels(Format format)
{
int channels=0;
switch (format) {
case kXY:
channels = 2;
break;
case kXYZ:
case kXYI:
channels = 3;
break;
case kXYZI:
case kXYZRGB:
channels = 4;
break;
case kXYNormal:
channels = 5;
break;
case kXYZNormal:
case kXYINormal:
channels = 6;
break;
case kXYZINormal:
case kXYZRGBNormal:
channels = 7;
break;
default:
UFATAL("Unhandled type %d!", (int)format);
break;
}
return channels;
}
bool LaserScan::isScan2d(const Format & format)
{
return format==kXY || format==kXYI || format == kXYNormal || format == kXYINormal;
}
bool LaserScan::isScanHasNormals(const Format & format)
{
return format==kXYZNormal || format==kXYZINormal || format==kXYZRGBNormal || format == kXYNormal || format == kXYINormal;
}
bool LaserScan::isScanHasRGB(const Format & format)
{
return format==kXYZRGB || format==kXYZRGBNormal;
}
bool LaserScan::isScanHasIntensity(const Format & format)
{
return format==kXYZI || format==kXYZINormal || format == kXYI || format == kXYINormal;
}
LaserScan LaserScan::backwardCompatibility(const cv::Mat & oldScanFormat, int maxPoints, int maxRange, const Transform & localTransform)
{
if(!oldScanFormat.empty())
{
if(oldScanFormat.channels() == 2)
{
return LaserScan(oldScanFormat, maxPoints, maxRange, kXY, localTransform);
}
else if(oldScanFormat.channels() == 3)
{
return LaserScan(oldScanFormat, maxPoints, maxRange, kXYZ, localTransform);
}
else if(oldScanFormat.channels() == 4)
{
return LaserScan(oldScanFormat, maxPoints, maxRange, kXYZRGB, localTransform);
}
else if(oldScanFormat.channels() == 5)
{
return LaserScan(oldScanFormat, maxPoints, maxRange, kXYNormal, localTransform);
}
else if(oldScanFormat.channels() == 6)
{
return LaserScan(oldScanFormat, maxPoints, maxRange, kXYZNormal, localTransform);
}
else if(oldScanFormat.channels() == 7)
{
return LaserScan(oldScanFormat, maxPoints, maxRange, kXYZRGBNormal, localTransform);
}
}
return LaserScan();
}
LaserScan::LaserScan() :
maxPoints_(0),
maxRange_(0),
format_(kUnknown),
localTransform_(Transform::getIdentity())
{
}
LaserScan::LaserScan(const cv::Mat & data, int maxPoints, float maxRange, Format format, const Transform & localTransform) :
data_(data),
maxPoints_(maxPoints),
maxRange_(maxRange),
format_(format),
localTransform_(localTransform)
{
UASSERT(data.empty() || data.rows == 1);
UASSERT(data.empty() || data.type() == CV_8UC1 || data.type() == CV_32FC2 || data.type() == CV_32FC3 || data.type() == CV_32FC(4) || data.type() == CV_32FC(5) || data.type() == CV_32FC(6) || data.type() == CV_32FC(7));
UASSERT(!localTransform.isNull());
if(!data.empty() && !isCompressed())
{
if(format == kUnknown)
{
*this = backwardCompatibility(data_, maxPoints_, maxRange_, localTransform_);
}
else // verify that format corresponds to expected number of channels
{
UASSERT_MSG(data.channels() != 2 || (data.channels() == 2 && format == kXY), uFormat("format=%d", format).c_str());
UASSERT_MSG(data.channels() != 3 || (data.channels() == 3 && (format == kXYZ || format == kXYI)), uFormat("format=%d", format).c_str());
UASSERT_MSG(data.channels() != 4 || (data.channels() == 4 && (format == kXYZI || format == kXYZRGB)), uFormat("format=%d", format).c_str());
UASSERT_MSG(data.channels() != 5 || (data.channels() == 5 && (format == kXYNormal)), uFormat("format=%d", format).c_str());
UASSERT_MSG(data.channels() != 6 || (data.channels() == 6 && (format == kXYINormal || format == kXYZNormal)), uFormat("format=%d", format).c_str());
UASSERT_MSG(data.channels() != 7 || (data.channels() == 7 && (format == kXYZRGBNormal || format == kXYZINormal)), uFormat("format=%d", format).c_str());
}
}
}
}
+4 -3
View File
@@ -65,13 +65,13 @@ Link::Link(int from,
double Link::rotVariance() const
{
double min = uMin3(infMatrix_.at<double>(3,3), infMatrix_.at<double>(4,4), infMatrix_.at<double>(5,5));
double min = uMax3(infMatrix_.at<double>(3,3), infMatrix_.at<double>(4,4), infMatrix_.at<double>(5,5));
UASSERT(min > 0.0);
return 1.0/min;
}
double Link::transVariance() const
{
double min = uMin3(infMatrix_.at<double>(0,0), infMatrix_.at<double>(1,1), infMatrix_.at<double>(2,2));
double min = uMax3(infMatrix_.at<double>(0,0), infMatrix_.at<double>(1,1), infMatrix_.at<double>(2,2));
UASSERT(min > 0.0);
return 1.0/min;
}
@@ -117,7 +117,8 @@ Link Link::merge(const Link & link, Type outputType) const
link.to(),
outputType,
transform_.isNull()?Transform():transform_ * link.transform(), // FIXME, should be inf1^-1(inf1*t1 + inf2*t2)
transform_.isNull()?cv::Mat::eye(6,6,CV_64FC1):(infMatrix_.inv() + link.infMatrix().inv()).inv());
transform_.isNull()?cv::Mat::eye(6,6,CV_64FC1):(infMatrix_.at<double>(0,0)<link.infMatrix().at<double>(0,0)?infMatrix_:link.infMatrix()));
//transform_.isNull()?cv::Mat::eye(6,6,CV_64FC1):(infMatrix_.inv() + link.infMatrix().inv()).inv());
}
Link Link::inverse() const

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