Compare commits

..

360 Commits

Author SHA1 Message Date
matlabbe
839045a538 package.xml: 0.20.7 2020-12-12 19:05:06 -05:00
matlabbe
a824945816 package.xml: removed libvtk-qt as there are conflicts on noetic with libpcl-dev (which is using vtk7) 2020-12-12 17:32:30 -05:00
matlabbe
1acf8ff193 RegIcp: don't assert if normals cannot be computed properly before doing complexity check, just reject the transform 2020-12-12 16:53:07 -05:00
matlabbe
51826c9a97 RegIcp: fixed KDTreeMatcherIntensity build error on Mac. 2020-12-11 17:22:29 -05:00
matlabbe
7a5d04062d vtk8: disabled vtkOutputWindow 2020-12-11 17:05:37 -05:00
matlabbe
049238dd59 Gui: added L515 icon 2020-12-11 09:56:17 -05:00
42Max42
3271723034 superpoint, fixing slow convert after cnn (#659)
* fixing slow convert after cnn

* restoring cmake
2020-12-11 09:27:18 -05:00
matlabbe
da8e76ffed rtabmap-matcher: added --calibration_to option (to use a different calibration file for the second image). 2020-12-05 13:21:58 -05:00
matlabbe
3131474102 Added Db/TargetVersion parameter (#652) 2020-12-03 15:45:40 -05:00
matlabbe
3ffc8ce73f DBViewer: enabled Reject button on landmark links 2020-11-30 23:17:47 -05:00
matlabbe
ee44adeb1f fixed #648 (build error without OctoMap dependency) 2020-11-30 12:33:08 -05:00
matlabbe
96c1c81e22 fixed build with older libpointmatcher versions <10300 2020-11-29 19:30:30 -05:00
matlabbe
0022b6b993 ExportCloudsDialog: added colormap option when showing scans 2020-11-28 18:02:54 -05:00
matlabbe
721e046f5d fixed build 2020-11-28 17:36:42 -05:00
matlabbe
d733029565 Increased version to 0.20.7. OdometryF2M: added support for intensity field, removed ignored key frames when there is low scan complexity. RegistrationIcp: added Icp/PMMatcherIntensity, Icp/PointToPlaneGroundNormalsUp and Icp/PointToPlaneLowComplexityStrategy parameters. Rtabmap: when graph optimized from end, increased optimization error before warning that resulting map correction is not identity (this could happen with GTSAM as the root is not perfectly fixed). CloudViewer: added coordinate frame scaling option, added rainbow colormap option for scan intensity. DBViewer: fixed local proximity merged scans not shown modified after refining those links, show intensity, fixed constraints view not updated after rejecting a link. MainWindow: added intesity support with odometry scans. 2020-11-28 17:28:34 -05:00
matlabbe
7859313beb AppVeyor: updated realsense2 sdk to 2.40. CameraRealSense2: When GlobalTimeSync option is off, don't wait 35 ms for imu (and fails), just take the latest one directly (https://github.com/introlab/rtabmap/issues/614#issuecomment-732244439). 2020-11-23 11:36:27 -05:00
matlabbe
80199f23b5 RegIcp: complexity, checking if second eigen value is also under Icp/PointToPlaneMinComplexity to limit to only one axis. DbViewer: fixed refine link with scans having RGB channel. 2020-11-22 19:32:01 -05:00
matlabbe
bce7ae6acd Fixed GTSAM reference frame yaw drift over time when gravity links are used 2020-11-22 16:40:30 -05:00
matlabbe
f88845e138 fixed #643 2020-11-22 14:29:05 -05:00
matlabbe
bdc7be40b4 Fix for previous commit e4cb59b74d (otherwise imu are ignored if globalTimeSync is off) 2020-11-22 12:38:21 -05:00
matlabbe
e4cb59b74d Added suggestion from https://github.com/introlab/rtabmap/issues/614#issuecomment-731769818 2020-11-22 12:32:39 -05:00
matlabbe
dab407e5b9 fixed ad44b65a28 (commitcomment-44427459) 2020-11-22 11:10:35 -05:00
matlabbe
98a499b603 Optimizer: fall back on g2o or gtsam first if one or the other is not available (instead of going TORO). ExportClouds: added ceiling and floor filtering options. 2020-11-22 01:23:08 -05:00
matlabbe
f5d7dc2814 PreferencesDialog: Added Marker/MaxRange and Marker/MinRange parameters to UI. 2020-11-21 17:23:41 -05:00
matlabbe
ab1aa5578a Fixed build 2020-11-21 17:12:09 -05:00
matlabbe
ccbdb586da DbViewer: Added datbabase path to window title 2020-11-21 16:37:40 -05:00
David Molina
f467f2af7f Added Marker/MaxRange and Marker/MinRange parameters (#630)
* ADD 3 meter limit for marker detections

* ADD Marker/MaxRange and Marker/MinRange parameters for controlling marker detection
ADD ctags ignore

Co-authored-by: John Paul Soliva <soliva@seaos.co.jp>
Co-authored-by: Tim Fronsee <tfronsee21@gmail.com>
2020-11-21 16:18:22 -05:00
matlabbe
7c4d2bbdf4 DbViewer: before resetting all changes, added a confirmation message box! 2020-11-21 16:15:27 -05:00
matlabbe
fb206b4f1e DbViewer: fixed scan disappearing after editing constraint 2020-11-21 14:35:29 -05:00
matlabbe
ddecefbb9c 💄 2020-11-21 12:34:17 -05:00
matlabbe
ad44b65a28 Allow partial support for AliceVision v2.3.0 (see #564 for remaining issues) 2020-11-20 13:42:56 -05:00
matlabbe
fdaaa6ccfa Fixed bug L500 gyro/acc not detected (#629) 2020-11-19 13:49:10 -05:00
matlabbe
34e1af7e22 RealSense2: added error message for L515 if resolution is not 640x480 30 fps (#629) 2020-11-19 10:38:15 -05:00
matlabbe
54e2688a1d Fixed build with pcl > 1.11.1 (#641) 2020-11-14 16:52:01 -05:00
matlabbe
f9abcf9e35 fixed opencv2 build 2020-11-14 14:41:37 -05:00
matlabbe
01eb57f293 CameraImages: added configForEachFrame option (added to GUI too). CameraThread: for decimation, if depth is smaller than RGB, RGB is decimated first and if the resulting RGB image is smaller than the original depth, we then decimate the depth. 2020-11-14 13:39:12 -05:00
matlabbe
7be22d1b67 Added check to make sure input odometry poses are invertible. Source/DB: added stereo to depth option. 2020-11-06 21:37:59 -05:00
matlabbe
4b527f9c36 Update .appveyor.yml 2020-11-06 18:56:32 -05:00
matlabbe
4d965c2089 Update .appveyor.yml 2020-11-06 18:18:06 -05:00
matlabbe
47cbd633c3 Update .appveyor.yml 2020-11-06 18:11:29 -05:00
matlabbe
b95537a680 Added c++11 definition when latest libpointmatcher is found 2020-11-06 16:37:29 -05:00
matlabbe
e102243f0e Fixed weight=-8 bug when moving rehearsed node to trash 2020-11-06 14:47:10 -05:00
matlabbe
e7a2f206a0 Gui: fixed warning scan not found when uncompressing data. Don't disable Mem/UseOdomFeatures checkbox anymore in monitoring mode (ROS). 2020-11-05 15:50:05 -05:00
matlabbe
d04b1a13be multiband: add multi-camera support. rtabmap-export: updated options (now supporting creating point cloud from scans). 2020-11-04 14:02:18 -05:00
matlabbe
92b1dabf1c MainWindow: avoid uncompressing images/scans if they are not shown 2020-11-03 16:12:43 -05:00
matlabbe
e269067d4c Texturing: add distanceToCamPolicy option 2020-11-03 16:11:37 -05:00
matlabbe
596cd10b69 Fixed -lBoost::timer not found on ubuntu18.04/arm64 (#587) 2020-11-01 13:08:55 -05:00
matlabbe
6a730b51c7 GUI-Preferences: disabled Daisy feature option on OpenCV 2 2020-11-01 13:01:23 -05:00
matlabbe
4ecf37a3ab fixed build with OpenCV 2.4 2020-11-01 12:49:21 -05:00
matlabbe
99275fba1d Added Daisy descriptor. ORB: updated default parameters. Making ORBOctree using ORB parameters. Updated Vis/CorNNDR default from 0.6 to 0.8 (increase number of matches with binary descriptors, increase slightly feature matching time with float descriptors). Note that jfr2018 scripts have been updated to use old value 0.6. rtabmap-info: show descriptor dimension and type. 2020-11-01 11:28:59 -05:00
matlabbe
25c2a51ee3 fixed windows build 2020-10-29 18:03:36 -04:00
matlabbe
600484e12c Update .appveyor.yml
#624
2020-10-29 11:52:25 -04:00
matlabbe
8878d9fcdf Update .appveyor.yml
#624
2020-10-29 11:44:31 -04:00
matlabbe
72e1649cdd DataRecorder: added imu filtering by default 2020-10-22 18:02:24 -04:00
matlabbe
afbc0edbd6 Local occupancy grid: fixed empty obstacles with scans having intensity channel when Grid/RangeMax is used. 2020-10-21 15:38:19 -04:00
matlabbe
fbc30042c4 Fixed biggest index/min/max when Grid/MaxGroundHeight is set (http://official-rtab-map-forum.67519.x6.nabble.com/Comparison-between-realsense-D435-vs-T265-vs-T265-D435-dual-setup-td6456i20.html) 2020-10-18 15:56:13 -04:00
matlabbe
a4da1e14b4 SIFT: fixed SIFT not extracted with OpenCV >=4.4 and >=3.4.11 when nonfree is false 2020-10-17 20:34:24 -04:00
matlabbe
3047b7da6b CameraRealSense2: update for L515 support 2020-10-17 19:57:27 -04:00
matlabbe
bbb3c56008 Fixed android build 2020-10-16 14:55:50 -04:00
matlabbe
f71f00277c DbViewer::AddConstraint: don't ask ofr manual constraint if already aborted previous question (when Reg/Strategy=1). 2020-10-12 17:41:06 -04:00
matlabbe
0e5ec91280 DbViewer: added option to ignore landmarks. Show landmark id in Constraints View. 2020-10-12 15:29:20 -04:00
matlabbe
3aae79270f Output an error if a timestamp file is missing instead of asserting #613 2020-10-12 14:30:57 -04:00
matlabbe
1b4a992b55 Merge branch 'master' of https://github.com/introlab/rtabmap into devel 2020-10-12 13:16:08 -04:00
matlabbe
384b120d2e Fixed landmark ignored when Rtabmap/StartNewMapOnLoopClosure is true and a loop closure is rejected (before graph optimization) 2020-10-12 13:05:14 -04:00
matlabbe
304c365ae6 Kp/ByteToFloat: Changed default of false
Based on http://official-rtab-map-forum.67519.x6.nabble.com/ZED2-rtabmap-loop-closure-and-twisted-map-tp6986p7002.html
2020-10-12 11:04:59 -04:00
matlabbe
d5572d03ad DbViewer: added checkbox to enable Add for nodes not linked to graph 2020-10-09 12:15:33 -04:00
matlabbe
6d552b7873 DbViewer: fixed depth of features not shown 2020-10-09 11:10:48 -04:00
matlabbe
32eb266c79 fixed CMP0020 cmake warning 2020-10-09 11:10:21 -04:00
matlabbe
2cb509c825 DbViewer: manual constraints can now be added (http://official-rtab-map-forum.67519.x6.nabble.com/Manually-adding-modifying-node-constraints-td6983.html) 2020-10-07 15:41:13 -04:00
matlabbe
168c87b5ba Added statitic Timing/RAM_estimation/. Updated VWDictionary::getMemoryUsed(). 2020-10-05 22:11:28 -04:00
matlabbe
a80e062bef Fixed build error in Trusty 2020-10-05 18:17:18 -04:00
matlabbe
9e321971ef Removed debug log 2020-10-05 17:49:26 -04:00
matlabbe
8260733b11 fixed detectMoreLoopClosures when RGBD/LocalBundleOnLoopClosure is true 2020-10-05 17:47:13 -04:00
matlabbe
bbccbd63e4 Increased version to 0.20.5
Refactored how features are stored in Signature (significative memory optimization, causing major refactoring in Memory, RegistrationVis, OdometryF2M)
FLANN: optimized memory usage when Kp/IncrementalFlann is false
Added memory usage functions
Added statistics Loop/Visual_inliers_ratio/ and Memory/RAM_estimated/MB
EpipolarGeometry: templated findPairs functions
graph::filterLinks: added inverted option
LocalBundleOnLoopClosure: Force to use only neighbor links
MainWindow: fixed max depth filtering for map's features
Rtabmap::getSignatureCopy() fixed links not returned
Added UPlot::getAllCurveDataAsText() function.
DbViewer: fixed features not rendered in right view when failing ro refine a constraint
report: added --export and --export_prefix options (to export figures data)
2020-10-05 17:34:32 -04:00
matlabbe
bedc771fa4 Rtabmap: added getNodesInRadius() public functions 2020-09-28 12:03:42 -04:00
matlabbe
933ac736f1 Increased version 0.20.4. Added parameter Kp/ByteToFloat (default true to use less memory with kdtree and binary descriptors). Memory/Sqlite3: Setting weight to -9 for invalid nodes (to make sure they are not reloaded from database, to fix a graph reduced issue). Added 12-SURF/FREAK detector approach. rtabmap-info: added number of nodes in each sessions. 2020-09-28 10:29:14 -04:00
matlabbe
c5158cade5 Fixed loop closure rejected if the camera on the robot changes orientation accordingly to base frame (http://official-rtab-map-forum.67519.x6.nabble.com/Mapping-with-multiple-stereocameras-localization-with-multiple-monochrome-monocular-cameras-tp6647p6953.html). The reason why that check was there was because ICP flipping 180 deg in some cases, but should be already detected with that commit 7a1cf84b08 (diff-b65a61c23197f7ff77a877f62b630b2cR283). 2020-09-27 14:38:36 -04:00
matlabbe
eef0a23b1b Reprocess: added --skip option (to skip frames when reprocessing). Rtabmap: always save Loop/Map_id/ stat. UPlot: export NaN insted of NA for invalid values (compatible with octave). GraphViewer and ImageView: added support for PDF output format, also changed default directory to User's Pictures standard folder. 2020-09-21 19:32:48 -04:00
matlabbe
3d33370e4c DbViewer: fixed error log when showing landmarks in Constraints view. 2020-09-15 17:12:00 -04:00
matlabbe
4e6e404951 Fixed "[Setjac] infinite jac" error when Vis/ForwardEstOnly is false. OptimizerG2O: Added a check to ignore invalid 3d points. 2020-09-15 15:18:49 -04:00
matlabbe
29368ebdb3 report: fixed database order in localization results 2020-09-15 14:06:23 -04:00
matlabbe
a24211583d Rtabmap: init Bayes prediction when loading a database 2020-09-11 10:55:33 -04:00
matlabbe
d50b33a7b8 Preferences: updated warnings for free sift (#596) 2020-09-10 17:56:49 -04:00
matlabbe
a689d8a23f report: fixed how localization stats are split against localization sessions only 2020-09-10 14:09:27 -04:00
matlabbe
bd80811ea1 Stats: added Loop/Distance_since_last_loc 2020-09-10 14:07:53 -04:00
matlabbe
cabf03af44 Memory: fixed keypoints3d wrongly copied when not using odom features 2020-09-08 21:24:47 -04:00
matlabbe
f93cdc31a6 Gui/source/K4A: added more description 2020-09-04 15:12:05 -04:00
matlabbe
e0973fea92 CameraK4A: added imu support with playback. Fixed windows build error. 2020-09-04 14:10:32 -04:00
matlabbe
49cb470b8d CameraK4A: refactored to unify playback and real device code. Fixed ir option (with rectification). 2020-09-04 12:48:18 -04:00
matlabbe
d2784095a3 Added K4A status on --version. About: added Mynteye status 2020-09-04 10:39:15 -04:00
matlabbe
1db17dd118 rtabmap-report: added loc_delay option. Db info: added unused space 2020-09-03 15:23:48 -04:00
matlabbe
23d8353540 Rtabmap::detectMoreLoopClosures, use optimized graph as guess if RGBD/ProximityOdomGuess is true. Reprocess: added options to generate scan from depth image and/or pre-process input scans. 2020-08-28 16:24:07 -04:00
matlabbe
96a628877c reprocess: when merging databases, return number of sessions merged when program exists. export: added --save_in_db option. 2020-08-28 12:29:16 -04:00
matlabbe
24052a6ebe fixed pcl::getAngle3D not found error on latest pcl version (6df3e602a7 (diff-8e08415b9972a447d115dbca3f8fa0a1)) 2020-08-25 10:56:30 -04:00
matlabbe
775c9318d3 Fixed Too large rotation detected message 2020-08-21 15:57:28 -04:00
matlabbe
f263d560b4 OdomF2M: fixed complexity null for first scan is not having normals already 2020-08-21 14:32:08 -04:00
matlabbe
729f96f467 TORO: added warnings when prior or landmark links are detected 2020-08-21 11:26:22 -04:00
matlabbe
8d63e9eae1 Fixed 'cannot find -lBoost::thread' build error when building only with libpointmatcher dependency 2020-08-14 12:25:03 -04:00
matlabbe
39f68c44c6 Recovery: set back database in mapping mode after being saved in localization mode 2020-08-03 13:46:42 -04:00
matlabbe
0a9d237ac2 0.20.3: CameraRealSense2: Fixed D435i accel/gyro profile selection to avoid crash. Fixed Integrated D415 fix (#469) 2020-08-01 20:29:47 -04:00
matlabbe
07d21e6b03 VINS update log: printf to UDEBUG 2020-07-30 12:34:58 -04:00
matlabbe
53a759e2da Fixed missing vins usage with run_euroc_datasets.sh 2020-07-29 11:50:53 -04:00
matlabbe
6741355842 Ignore invalid GPS values (NaN #570) 2020-07-29 10:39:34 -04:00
matlabbe
1460c56254 Merge branch 'melodic-devel' of https://github.com/introlab/rtabmap 2020-07-12 15:02:00 -04:00
matlabbe
dec135a3fb package.xml: added explicitly libvtk-qt dependency for debian build error 2020-07-12 14:59:40 -04:00
matlabbe
9edd9b741d tango-api19: fixed docker build 2020-07-10 22:16:16 -04:00
matlabbe
43eba76a20 docker: updated tango-api19 image 2020-07-10 15:26:59 -04:00
matlabbe
bf45a0cba2 docker: fixed arcore not correctly extracted 2020-07-10 09:04:38 -04:00
matlabbe
4be07fc3e9 fixed tango build without arcore support 2020-07-10 08:58:56 -04:00
matlabbe
4e32e8846c fixed build error 2020-07-08 21:34:41 -04:00
matlabbe
6468245317 Reprocess: added loc stats in motion, added option to export odom and loc poses in g2o format 2020-07-08 21:25:14 -04:00
matlabbe
169b79215d Memory::computeIcpTransformMulti() added support for 3d scans with RGB channel (L515) 2020-07-08 13:43:28 -04:00
matlabbe
4a09c4bdcf Odometry: fixed Reg/Force3DoF ignored if filters are not used 2020-07-08 10:03:54 -04:00
matlabbe
3505611fb5 reprocess: set Mem/UseOdomFeatures to false if Kp/DetectorStrategy or Vis/FeatureType is overwritten (#566) 2020-07-06 13:31:01 -04:00
matlabbe
55228aa574 Update README.md 2020-07-02 21:43:10 -04:00
matlabbe
e800662bac Fixed build with OpenCV >= 3.4.11 2020-07-02 16:29:23 -04:00
matlabbe
33e9abdfad Mac: fixed crash when discarding a signature (not moving enough) with self refenced links. Fixed link error with realsense2 library on Mac. 2020-07-02 12:54:43 -04:00
matlabbe
cd10cafd0e Windows: fixed CameraRealSense2 driver freezing on close. 2020-07-01 20:58:04 -04:00
matlabbe
736cf0efc7 Windows: fixed stamp now() issue 2020-07-01 16:53:57 -04:00
matlabbe
4f6d8b1fbe Windows: add depthengine_2_0.dll plugin when packaging with K4A support 2020-07-01 14:46:37 -04:00
matlabbe
8fa216bd9d Fixed default odom gravity sigma value to -1. Preferences: set 720p by default for K4A driver 2020-07-01 14:04:19 -04:00
matlabbe
661a05b0da CameraMyntEye: fixed M_PI not defined error 2020-06-30 23:36:12 -04:00
matlabbe
0809946c66 Windows: Fixed stereoRectifyFisheye.h 'cannot convert from cv::Mat to CvMat' compilation error with opencv >=3.4.4. Fixed k4a/k4atypes.h not found on guilib compilation. 2020-06-30 23:18:31 -04:00
matlabbe
4857d43146 android: ui update. fixed arcore java driver not stopping in background 2020-06-29 20:41:59 -04:00
matlabbe
b7ada1992e android: added occlusion detection using arcore depth api (for FPS view). Added depth from motion option in Mapping options. 2020-06-29 20:25:58 -04:00
matlabbe
2ee3445728 Docker: updated arcore 1.18 download link 2020-06-29 15:35:14 -04:00
matlabbe
4142ff003c Added AR mapping mode (select ARCore ndk driver and set first person view) 2020-06-29 15:24:35 -04:00
matlabbe
542f06ec24 ARCore: features from arcore are used directly for keypoints 2020-06-29 15:08:24 -04:00
matlabbe
dacf724ea6 Rtabmap::addLink() support multi-session 2020-06-25 13:56:01 -04:00
matlabbe
274903dd63 Rtabmap::getSignatureCopy() added withWords and withGlobalDescriptors options 2020-06-22 22:56:25 -04:00
matlabbe
c19f81ac12 Memory::getNodeData() removing not wanted data if the node with all its data has been found in working memory. 2020-06-22 22:29:26 -04:00
matlabbe
846bd59d0b Rtabmap::addLink() removed an error log that is actually a debug log. 2020-06-22 21:53:22 -04:00
matlabbe
6e1f07e097 CameraK4A: fixed IMU local transform, fixed some compilation warnings. 2020-06-22 19:42:55 -04:00
matlabbe
1ca2c25a10 DbViewer: fixed empty from scan when refining proximity link by space 2020-06-22 13:07:27 -04:00
matlabbe
c5ec4f337b util3d::segmentObstaclesFromGround() fixed no ground returned if maximum ground height is set and the biggest plane was not under that height (e.g., ceiling having more points than ground) 2020-06-18 21:30:43 -04:00
matlabbe
554b08256b Statistics: Added Odometry_correction_acc_* 2020-06-18 14:47:00 -04:00
matlabbe
a2b0de2a4d MacOSX bundle: fixed ui native style with Qt>=5.10 2020-06-18 12:09:26 -04:00
matlabbe
fb6659e29d CloudViewer: reduced ambient lighting for textureMesh with VTK>=7 2020-06-18 11:28:53 -04:00
matlabbe
db00f55981 CloudViewer: fixed texture not shown with VTK>=7 2020-06-18 10:59:42 -04:00
matlabbe
ffdb2eb855 Docker: added focal image, fixed bionic image not building with alicevision. Updated travis with focal build. 2020-06-09 21:15:54 -04:00
matlabbe
13679cc52a Export tool: fixed generated texture output directory 2020-06-09 12:58:55 -04:00
matlabbe
4769fc235f Refactoring: set default local transform for camera drivers to opticalRotation. Added CameraModel::opticalRtotation() static function for convenience. Added CameraModel::load() from file directly for convenience. Added Camera::initFromFile() for convenience. Transform: Added opengl_T_rtabmap() and opengl_T_rtabmap() functions for convenience (convert back and forth between rtabmap world and opengl world coordinate frames) 2020-06-08 11:40:47 -04:00
matlabbe
ff5695878c Rtabmap::init() added loadDatabaseParameters argument for convenience (default false to be backward compatible) 2020-06-08 10:35:12 -04:00
matlabbe
6029b6283d Rtabmap: Refactored how fake odom is generated in localization mode when no odom is provided. Trigger new map in localization mode also clears last localization pose if RGBD/SavedLocalizationIgnored is true. 2020-06-08 10:14:21 -04:00
matlabbe
86ac63ab19 UPlot: changed float to qreal (double). Added UPlot::frameData() function. 2020-06-07 11:55:27 -04:00
Thomas Kircher
de5610bd08 Added preferences for Azure Kinect camera (#559)
* Added Kinect for Azure menu option

* Reintegrated Kinect for Azure initialization code, fixed previous GUI commit

* Added ifdefs to fix build

* Added preliminary K4A device support

* Edits to K4A camera implementation

* K4A minor initialization fix

* Typo

* Another initialization fix

* Update CameraRGBD tool to display K4A camera output

* K4A added model parameter so we can create maps

* Added combo boxes for K4A options

* Functionalized combo boxes for K4A options

* Finished adding K4A preferences
2020-06-04 11:34:37 -04:00
matlabbe
7a9a5d2ef9 CloudViewer: updated camera clipping 2 2020-06-03 14:50:59 -04:00
matlabbe
b6d4c6f024 CloudViewer: fixed camera clipping the grid 2020-06-03 13:41:36 -04:00
matlabbe
ff3c6c8e06 Update README.md 2020-06-02 19:59:21 -04:00
matlabbe
e2007a8f82 CloudViewer: fixed build with vtk<6 2020-06-01 22:18:45 -04:00
matlabbe
bda18bc517 CloudViewer: added EDL shading option 2020-06-01 21:44:42 -04:00
matlabbe
d00717b068 package.xml: removed explicit dependency to libvtk-qt (https://github.com/introlab/rtabmap/issues/557) 2020-06-01 11:42:35 -04:00
matlabbe
c7be9a23ee OdometryF2M: refactored imu buffer 2020-05-31 14:33:20 -04:00
matlabbe
caffb56246 DBViewer: fixed StereoSGBM panel not shown. Odometry: fixed Odom/GuessSmoothingDelay type 2020-05-31 13:26:54 -04:00
matlabbe
d5cfd8013d CameraMyntEye: added setIrControl() 2020-05-31 12:17:14 -04:00
matlabbe
415a2778f1 Added Features2d::limitKeypoints() with grid options. Odometry: if imu is provided and no guess is provided, the change of orientation of imu is used for rotation guess (overwrite rotation from Odom/GuessFromMotion). OdometryInfo: added gravity errors when imu is used. Preferences: added a second GravitySigma parameter (overwritting Optimizer/GravitySigma for odometry is not negative) for F2M odometry panel. 2020-05-31 11:22:12 -04:00
matlabbe
6e55525a7b Memory::getNeighborsId() fixed no link returned when looking in database 2020-05-30 09:20:32 -04:00
matlabbe
7eae992d6f rtabmap-report: fixed map.at() error if the database as empty statistics 2020-05-28 21:21:31 -04:00
matlabbe
2509b6ee09 Statistics: added MapToOdom and MapToBase stats 2020-05-28 21:04:01 -04:00
matlabbe
45ddce938a CameraMyntEye/GUI: added manual/auto exposure option (default auto). Rtabmap: refactored warning when RGBD/OptimizeFromGraphEnd changes state. 2020-05-28 19:50:02 -04:00
matlabbe
6e0081e248 MainWindow: made mynteye action checkable. 2020-05-28 14:04:10 -04:00
matlabbe
bf39c5295b Ported PCL 1.11 deprecated changes to PCL 1.10 (#550) 2020-05-27 17:45:16 -04:00
matlabbe
8842d0c0e3 fixed isfinite -> std::isfinite 2020-05-27 16:39:50 -04:00
matlabbe
511be5f663 Fixed build with pcl 1.11 (#550). Fixed pcl 1.11 warnings (boost->std). 2020-05-27 16:35:33 -04:00
matlabbe
ae5ce029d6 Fixed SIFT build issue between OpenCV 4.3.0 and OpenCV 4.3.0-dev 2020-05-27 10:35:18 -04:00
matlabbe
798466bb05 Increased ros package version to 0.20.0. Parameters: fixed default feature detector when xfeatures2d is not found 2020-05-26 22:44:44 -04:00
matlabbe
0902ccc340 Updated error message when SBA is done on multicam setup. 2020-05-26 11:04:23 -04:00
matlabbe
208f1e5b7c OdomF2M: fixed complexity check on 2d scans (https://github.com/introlab/rtabmap_ros/issues/412) 2020-05-25 20:07:58 -04:00
matlabbe
b40d9610ed Preferences: Fixed xfeatures2d features not available without nonfree on OpenCV >= 3.4.2 (https://github.com/introlab/rtabmap_ros/issues/422) 2020-05-25 17:31:13 -04:00
Thomas Kircher
35385e299d K4A mapping working now (#554)
* Added Kinect for Azure menu option

* Reintegrated Kinect for Azure initialization code, fixed previous GUI commit

* Added ifdefs to fix build

* Added preliminary K4A device support

* Edits to K4A camera implementation

* K4A minor initialization fix

* Typo

* Another initialization fix

* Update CameraRGBD tool to display K4A camera output

* K4A added model parameter so we can create maps
2020-05-25 11:46:16 -04:00
matlabbe
6acfc62196 CloudViewer: adjust frustum fov based on camera model (https://github.com/introlab/rtabmap_ros/issues/419) 2020-05-24 11:13:13 -04:00
matlabbe
eb9999d7b1 Rtabmap::addLink() supporting localization mode. MainWindow: fixed flickering camera frustum. 2020-05-21 21:26:29 -04:00
matlabbe
69a2aacc8e Parameters: added SIFT/RootSIFT parameter. 2020-05-21 17:09:20 -04:00
Thomas Kircher
013bd0c72a K4A device, fixed some stale edits (#553)
* Added Kinect for Azure menu option

* Reintegrated Kinect for Azure initialization code, fixed previous GUI commit

* Added ifdefs to fix build

* Added preliminary K4A device support

* Edits to K4A camera implementation

* K4A minor initialization fix

* Typo

* Another initialization fix

* Update CameraRGBD tool to display K4A camera output
2020-05-20 19:36:15 -04:00
Thomas Kircher
89ece8cd4e Preliminary K4A device support (#552)
* Added Kinect for Azure menu option

* Reintegrated Kinect for Azure initialization code, fixed previous GUI commit

* Added ifdefs to fix build

* Added preliminary K4A device support
2020-05-20 15:31:30 -04:00
matlabbe
360a153565 Parameters: Renamed SuperGlue group to PyMatcher group. Added OANet python script. 2020-05-20 09:45:39 -04:00
matlabbe
63d40b2240 Fixing trusty build 2020-05-19 18:06:20 -04:00
matlabbe
cb60443a33 Fixing OpenCV<3 build 2020-05-19 15:44:41 -04:00
matlabbe
609d45ac9b 💄 2020-05-19 15:33:32 -04:00
Thomas Kircher
b542d6a0db Added Kinect for Azure menu option (#551)
* Added Kinect for Azure menu option

* Reintegrated Kinect for Azure initialization code, fixed previous GUI commit

* Added ifdefs to fix build
2020-05-19 15:03:36 -04:00
matlabbe
c7b84c60bc Parameters: added Mem/StereoFromMotion (default false) and RGBD/ProximityOdomGuess (default false). Visual proximity detection is done before computing the loop closure transform (the later is ignored if visual proximity succeeded with a node close to loop closure, add Loop/Suppressed_hypothesis_id statistics to know when this happens). Changed Loop/Map_correction to Loop/Odom_correction (to better see the actual jumps of localization about /base_link frame, not /odom frame). util3d::generateWords3DMono() is now using openCV's implementation of five-point algorithm (this fixed some cases for which the older approach couldn't find any solution). UPlot: added scrolling area on the legend, added global legend option to show all curve statistics (mean, stddev,max). MainWindow's open dialog: reopen last directory when reopening a different database. ParametersToolBox: show default parameter value in tooltip. rtabmap-report: add --start option. rtabmap-reprocess: show details about proximity and loop detections, reset all localization statistics after changing database. 2020-05-19 15:01:50 -04:00
matlabbe
55509c6c27 Fixed build with OpencV 2.4 and Qt4 2020-05-13 15:15:52 -04:00
matlabbe
00695731fe SuperGlue: added traceback when there is an error with python. 2020-05-13 11:18:34 -04:00
matlabbe
09d2f7d232 Fixed android build 2020-05-12 22:04:03 -04:00
matlabbe
e906b40e50 Fixed build with opencv < 3.4.1 2020-05-12 10:26:08 -04:00
matlabbe
1b675c3dcb Preferences: fixed SuperGlue/Indoor widget not found 2020-05-11 14:10:49 -04:00
matlabbe
d2673ed2fa Added GMS matching approach (Vis/CorNNType=7). Added GMS/ parameters. Added SuperGlue/Indoor parameter. ImageView: updating feature and line colors directly when changing color (option menu), fixed items already added to scene warning when switching to GraphicsView. 2020-05-11 13:23:26 -04:00
matlabbe
cc9fd439fe SuperPoint: updated descriptor normalization process to match exactly the implementation in SuperGlue. generateWords3DMono: use variance at 25% instead of 50% of the sqrd variance vector (to do the same than with PnP), also fixed return camera transform to include local transform of the camera model. rtabmap-matcher: updated default parameters when no depth images are used, added reproj error in title bar. 2020-05-10 14:13:41 -04:00
matlabbe
fbdc3780c7 Freenect: fixed imu local transform. Preferences: show imu filters with freenect driver. 2020-05-09 23:13:39 -04:00
matlabbe
c44837a4cb Fixed build without SuperGlue 2020-05-09 21:41:38 -04:00
matlabbe
91285e5e97 Added SuperGlue support (Vis/CorNNType=6). Added rtabmap-matcher tool. DBViewer: show matches/inliers when refine also fails. SIFT: make sift always available on OpenCV 4.3.0 (#538). Parameters: changed SPTorch prefix to SuperPoint, replaced Vis/CorCrossCheck by Vis/CorNNType=5. 2020-05-09 21:13:41 -04:00
matlabbe
abc3ebee8c fixed #538 2020-05-09 11:48:06 -04:00
matlabbe
1af139134e Deprecated Rtabmap::get3DMap(), use Rtabmap::getGraph() instead with setting to true the data flags. Rtabmap::getGraph() now ignores children nodes. 2020-05-06 08:04:58 -04:00
matlabbe
7d377d26df Added Rtabmap::getSignatureCopy() 2020-05-05 13:26:40 -04:00
matlabbe
7041d5fd34 Fixed #541 2020-05-03 22:59:35 -04:00
matlabbe
c19da22ca4 0.20: added GlobalDescriptor table in database 2020-05-03 21:46:25 -04:00
matlabbe
50c3bb7ce9 fixed #540 2020-05-03 14:05:14 -04:00
matlabbe
0a4d0038cb Preferences dialog: fixed missing Vis/CorCrossCheck checkbox 2020-05-02 11:03:17 -04:00
matlabbe
d14efea4ac Added Vis/CorCrossCheck parameter (to use BFMatcher with crosscheck option instead of knn with NNDR for features matching). DBViewer: after refine or add constraint, lines indicating feature correspondences are now shown with different color if they are inliers. Re-enabled saving/loading settings of the ImageViews (feature color, line color, transparency...). 2020-05-01 22:12:56 -04:00
matlabbe
45223b306a Increased SPTorch/Threshold decimals for more fine tuning in DBViewer 2020-05-01 19:59:28 -04:00
matlabbe
3e9cff4053 fixed build with opencv 4.3 2020-05-01 09:51:54 -04:00
matlabbe
46886f2637 Report: added invert and ids options. Reprocess: show node id along map id when processing. 2020-04-30 17:00:09 -04:00
matlabbe
40804d9120 Statistics: added x,y,z map corrections. Report: added options --stats to show available statistics to plot in a database 2020-04-30 15:48:47 -04:00
matlabbe
803c99cee2 RegVis: fixed Vis/MaxDepth and Vis/MinDepth ignored when features are already extracted. 2020-04-30 15:07:32 -04:00
matlabbe
5d16ae8cfe DBViewer: fixed calibration not found on refining without re-extracting features, fixed visualized ids switched on refine in some cases, fixed clouds not shown in constraints view after refine without re-extracting features 2020-04-30 14:17:46 -04:00
matlabbe
ace93b0356 GUI: check mynteye when selected 2020-04-30 01:00:17 -04:00
matlabbe
14ec619b1e Added MYNT EYE S support. Fixed StereoCameraModel rectification not done with non-square images, also updated to support fisheye model. 2020-04-30 00:57:47 -04:00
matlabbe
b3eee0d7bf android: fixed yuv conversion bug on some devices, updated default driver based on which one is available and built with it. 2020-04-29 12:18:02 -04:00
matlabbe
37e0860b0c android: Fixed upload button not visible in Sketchfab activity, webview can be canceled 2020-04-27 17:35:06 -04:00
matlabbe
be57c2752d Fixed gravity links not added for optimization when both prior and gravity links are added to same nodes 2020-04-26 23:45:32 -04:00
matlabbe
1a3c90e898 cleanup some debug logs 2020-04-26 14:57:27 -04:00
matlabbe
06482d2378 ARCore: when tof camera is not available, use arcore point cloud as keypoints 2020-04-26 14:48:48 -04:00
matlabbe
3abdd22031 android: fixed state locked in processing after saving 2020-04-26 09:40:50 -04:00
matlabbe
66fca15cc6 Added rtabmap-info console tool 2020-04-24 13:45:41 -04:00
matlabbe
0c04b77cd7 Android: simplified default workflow (open -> scan -> optimize/export -> save) 2020-04-24 09:22:14 -04:00
matlabbe
6bb6178ae5 android: fixed Resume disabled when returning from Visualization 2020-04-24 08:23:17 -04:00
matlabbe
4ad92f0261 Docker: fixed android-## cloning branch 2020-04-24 07:33:48 -04:00
matlabbe
bc8d811f69 Dictionary: fixed L2SQR format for GPU BF 2020-04-23 22:56:42 -04:00
matlabbe
e8be3f21fa SuperPoint: fixed nms bug 2020-04-23 20:06:48 -04:00
matlabbe
31e5f7804e DbViewer: set horizontal layout by default 2020-04-23 15:27:31 -04:00
matlabbe
9b54aeee22 Android: set estimation type to default PnP 2020-04-23 15:13:58 -04:00
matlabbe
00d8375a2e RGBD/SavedLocalizationIgnored: if true, it is now starting at the origin (0,0,0) instead of null (not linked to graph). 2020-04-23 11:57:01 -04:00
matlabbe
046e0b7888 updated xenial tango docker file 2020-04-23 08:08:57 -04:00
matlabbe
35074f6d9f DBViewer: fixed missing parameter groups in Core Parameters. MainWindow: disabled frames by default. 2020-04-22 18:30:42 -04:00
matlabbe
94360e19e0 DBReader: changed maxFrames option to stopId and startIndex to startId. Reprocess: added options to start and stop at specific ids in the database. 2020-04-22 16:20:29 -04:00
matlabbe
012439aa0b Tango refactoring (#534)
* Created general CameraMobile interface. Tango is now optional. Camera is disabled on visualizaion (battery saving).

* Working android app on non-tango android phones (tested on x86_64 android emulator).

* fixed typo

* android: updated tango not available msg

* android: fixed build with latest android sdk/ndk

* Added ARCore limited support for pose and rgb streams.

* Added AREngine support. Don't assert if depth size is not a modulo of rgb size.

* Added ARCore shared camera support

* android: fixed read/write runtime permissions for >=api23. arcore ndk: added feature point cloud. Fixed file sharing persmissions (>=api24 issue)

* ARCore NDK: mapping with feature point cloud

* android: Added post build strip command to reduce native library size

* android: fixed some compilation issues

* android: put back gtsam as default optimizer, manifest min api is dynamic based on cmake parameters

* AREngine: min api 24

* android: Fixed build without AREngine

* android: fixed not available libraries for API<24

* android: fixed build with old cmake versions

* android: set arcore min api to 23

* android: fixed arengine error on start when not built with native arengine support

* android: fixed tango camera permission for api>=23

* Added bionic android docker files

* Fixed wrong 3D words projection when depth size is not an exact multiple of rgb size. DbViewer: fixed images size not correctly shown in label of the calibration. ImageView: fixed depth scale when depth size is not a multiple of rgb size

* CameraMobile: added exact display rotation for local transform

* DbViewer: fixed gravity link shown in constraint view, show full local transform matrix in camera calibration label

* Android: fixed localization mode in visualization, fixed some tansitions between some UI states

* Android: Hide stop button when HUD is hidden. Updated About years.
2020-04-22 15:05:07 -04:00
matlabbe
931d525874 Fixed build on kinetic (octomap version issue #529) 2020-04-20 09:58:00 -04:00
matlabbe
7cfc51315d CMake: find octomap instead of OCTOMAP #529 2020-04-18 16:03:09 -04:00
matlabbe
de4b17332d Preferences: fixed some not clickable external links 2020-04-17 16:06:56 -04:00
matlabbe
6074e84653 Fixed compilation issues with libtorch 1.4.0 2020-04-17 08:32:44 -04:00
matlabbe
f575652456 0.19.7: added SuperPoint Torch feature support. RegVis: keep Feature2D detectors as class members instead of recreating them at each registration. 2020-04-16 17:59:45 -04:00
matlabbe
2ff582f06f DbViewer: fixed refineConstraints to make sure from id is the smallest id. Fixed correspondence lines drawn when images don't have the same size. 2020-04-15 14:54:36 -04:00
matlabbe
de354b901d RegInfo: added icpStructuralDistribution info 2020-04-14 17:06:53 -04:00
matlabbe
607dc67135 IMU: removing yaw from local imu transform when creating gravity links 2020-04-10 19:24:45 -04:00
matlabbe
d6269bb5d6 GUI: changed TF link colors from yellow to orange (as yellow already used for gravity) 2020-04-10 13:40:59 -04:00
matlabbe
43df2a05da OdomF2M: fixed roll/pitch ignored in imu local transform 2020-04-09 19:22:57 -04:00
matlabbe
1b4b1c2832 Report: add compilation when qt is not used 2020-04-09 11:00:42 -04:00
matlabbe
18ff5bb410 OdomF2M/Icp: fixed substracting points when normals are not used 2020-04-09 09:59:22 -04:00
matlabbe
c0313a6d09 GUI/Source: color only option now also available for stereo cameras (meaning only left frame published). Db: fixed non-valid 3d words saved when no ones were in the signature (on loading, we don't set words3 if they are all null). 2020-04-08 20:00:41 -04:00
matlabbe
82a19a2ff1 DbViewer: Updated add constraint order (from=old, to=newer) 2020-04-08 18:52:38 -04:00
matlabbe
7e8e80db2c Fixed map_id not starting at 0 when empty 2020-04-08 17:02:44 -04:00
matlabbe
cdff33b1c2 Added Mem/LocalizationDataSaved parameter 2020-04-05 19:21:20 -04:00
matlabbe
e83838f744 CameraRealSense2: fixed ifstream imcomplete type error 2020-04-05 12:30:46 -04:00
matlabbe
b3f7d1881f GUI: added options to hide map/odom frames and yellow TF links. CloudViewer: added option to show/hide camera axis 2020-04-03 20:04:15 -04:00
matlabbe
9c62a11316 fixed #525 2020-04-03 17:28:23 -04:00
matlabbe
034adb9f1f fixed #503 2020-04-02 15:07:32 -04:00
matlabbe
fd1fa0320a fixed build with latest libpointmatcher 2020-04-01 15:52:46 -04:00
matlabbe
b95195d8bb CameraRealSense2: added json preset file option (#513) 2020-04-01 12:25:28 -04:00
matlabbe
dcc15f7555 MainWindow: added TG_error_lin and TG_error_ang stats for odometry (error of actual odometry transform compared to ground truth) 2020-03-31 11:52:27 -04:00
matlabbe
0eb978cb0b RegInfo: fixed copy without data. 2020-03-28 18:48:51 -04:00
matlabbe
451211cfb1 OdomInfo: added icpCorrespondences. Stats: using norm instead of x for distance/speed. Added odometry speed statistic in mph 2020-03-28 17:07:22 -04:00
matlabbe
06caa328a4 Lidar low complexity update. util3d::computeNormalsComplexity(): added optional transform (used in RegistrationIcp to get normal vectors in right coordinate frame). RegistrationIcp: Fixed PointToPoint ICP not used with PM when recomputing transform from low complexity. Added more info in warning messages when low complexity happens. OdometryF2M: avoid adding key frame when scan has low complexity. Same for the first frame to init the local scan map. 2020-03-28 16:25:27 -04:00
matlabbe
5122d9ac02 Memory: fixed fisheye distortion index error when rectifying only features 2020-03-24 11:46:16 -04:00
matlabbe
d201e25006 CloudViewer: Fixed normals_scale=0 2020-03-12 16:41:52 -04:00
matlabbe
b7bed0d1a5 Report: ignore total slam time on intermediate nodes 2020-03-12 14:12:00 -04:00
matlabbe
9993c4f2f7 Parameters.h: fixed warning C4305 2020-03-12 00:57:11 -04:00
matlabbe
5371f94c8f VS2019: fixed build 2020-03-11 23:34:55 -04:00
matlabbe
39724e239c rtabmap: fixed graph not re-optimized (if empty) after first localization on landmark 2020-03-10 13:08:47 -04:00
matlabbe
bfc64c451a MainWindow: added /map and /odom coordinate frames 2020-03-10 10:30:42 -04:00
matlabbe
6133399b2e util3d: added intersectRayMesh() and intersectRayTriangle() functions 2020-03-03 14:32:12 -05:00
matlabbe
c2dde973a6 Odometry: rectify stereo images for convenience if Rtabmap/ImagesAlreadyRectified is false and odometry strategy cannot process raw images 2020-03-02 16:57:14 -05:00
matlabbe
3ea64fbfc3 Rtabmap: do localization if a landmark already in graph is detected 2020-03-01 18:41:49 -05:00
matlabbe
cb80d85dd6 DbViewer: removed graph optimization from latest optimized poses (see http://official-rtab-map-forum.67519.x6.nabble.com/Database-Post-Processing-Save-refined-links-td6504.html) 2020-03-01 16:59:46 -05:00
matlabbe
dceec711e0 report: added --loop option to compute loop closure errors 2020-03-01 14:11:37 -05:00
matlabbe
67f1ce600f ament f7deefb31d for OpencV >=3.4.4 2020-02-29 15:22:14 -05:00
shovington
d0f84f9460 add option to create a report.csv file in /tools/Report (#512)
Co-authored-by: John <john.bobzwik@gmail.com>
2020-02-27 16:28:02 -05:00
matlabbe
5daf4e5b2b Rtabmap: avoid optimizing for only gravity if odometry is already aligned with gravity 2020-02-26 13:40:03 -05:00
matlabbe
80bee99bfc ExportDialog: show (disabled) multi-band option even if not available for viewing (only for exporting) 2020-02-22 18:16:45 -05:00
matlabbe
882f2010ce MainWindow/rtabmapviz: Ignore Odometry stats included in rtabmap's Statistics object (to avoid plot reset when also receiving those from odom info) 2020-02-21 16:16:36 -05:00
matlabbe
352507cb1c Update downsampling filtering approach for ring-like lidars like the ouster 2020-02-21 15:01:31 -05:00
matlabbe
e7a7ab8031 CloudViewer: added scan red colormap and max intensity options 2020-02-20 15:33:50 -05:00
matlabbe
bd979cca34 Fixed rejected 180deg loop closure with multi-camera setup 2020-02-19 14:35:37 -05:00
matlabbe
ab9f05fb0f Parameters: fixed "False" conversion independently of the case 2020-02-17 12:41:20 -05:00
matlabbe
5c197f176e DBViewer: fixed Yes vs YesToAll after editing 2d occupancy grid 2020-02-13 17:43:47 -05:00
matlabbe
5fef44ec2b DBViewer: Added option to crop empty space from local grid and scans after 2d occupancy grid is manually edited 2020-02-13 17:32:39 -05:00
matlabbe
79b480da4b Rtabmap: added addLink() function 2020-02-11 23:33:18 -05:00
matlabbe
e1ecf55d03 fixed 14.04 build 2020-02-05 20:46:15 -05:00
matlabbe
c9f21e7ebf fixed #498 2020-02-05 20:01:02 -05:00
matlabbe
f7deefb31d Fixed compilation with OpenCV 4.2 #502 (see ad146e5a6b and https://github.com/opencv/opencv/pull/16046) 2020-02-05 11:52:31 -05:00
matlabbe
e2e2227895 ZED: Fixed compilation error with ZED SDK3 (#499). Added textureness confidence thr parameter (default 90, working only with ZED SDK3) 2020-02-03 17:59:07 -05:00
Walter Lucetti
8810c9e694 Compilation fixes (#501)
Great! Thx a lot!
It should fix issue #499 as well.
2020-01-31 14:17:10 -05:00
matlabbe
f7540196d4 Fixed many compilation warnings (c++14, like pedantic warnings) 2020-01-30 17:23:02 -05:00
matlabbe
ccc5a5be5a OctoMap::createCloud() added cloud probability output option.
CameraRealSense2: added new warnings to debug easier timestamps problems.
GUI: added gravity visualization.
DbViewer: empty clouds in OctoMap mode have color depending on probability of occupancy.
Brought general changes from local xvision branch.
2020-01-22 10:34:21 -05:00
matlabbe
f9e818c900 CMake: alice vision option off by default (because it needs to be modified to be compatible https://gist.github.com/matlabbe/469bba5e7733ad6f2e3d7857b84f1f9e) 2020-01-06 13:39:35 -05:00
matlabbe
356094fac4 Intermediate nodes are now filtered if RGBD/LinearUpdate is set. 2019-12-20 17:07:31 -05:00
matlabbe
7d1a97696b OctoMap: fixed frontier with higher tree depth 2019-12-20 15:56:52 -05:00
Louis Petit
af2b221958 OctoMap added frontier cloud output 2019-12-17 17:31:37 -05:00
matlabbe
af9e113112 Gui: added missing OdomF2M/ScanRange parameter 2019-12-11 17:17:29 -05:00
matlabbe
62a2af193c fixed a compilation warning 2019-12-11 15:58:05 -05:00
PrescilliaA
4479a6f7e8 Odometry local map can be limited by range (#482)
* Odometry local map is now dependent on robot range and not on time, recalculating normals after adding new scan to the map as well
2019-12-11 13:43:38 -05:00
matlabbe
2d7ab7bdef Report: support Odometry/TimeEstimation/ms from ros 2019-12-11 11:33:19 -05:00
matlabbe
57a27a5d17 MainWindow: added virtual functions for convenience 2019-12-10 18:48:54 -05:00
matlabbe
1d7dee8976 kitti-tool: fixed no scan bug when using velodyne odom 2019-12-10 18:39:39 -05:00
matlabbe
9582ea4b55 Update .travis.yml 2019-11-24 09:57:49 -05:00
matlabbe
edee5acdbf DBViewer: we can now add new links between disconnected maps using only lidar. Export: convert intensity to grayscale when exporting colored mesh. 2019-11-23 17:58:40 -05:00
matlabbe
85e7c9cf04 fixed undefined reference to vtkSmartVolumeMapper::SetRequestedRenderModeToRayCast() when using PCL 1.9.1 2019-11-21 04:07:38 +00:00
matlabbe
b39fd0321e Update FindK4A.cmake 2019-11-19 09:39:42 -05:00
matlabbe
5f12459437 Docker removed disco and eoan images (keep only LTS images) 2019-11-09 08:48:55 -05:00
matlabbe
070b308595 Docker: xenial and bionic images now depend on ros:kinetic-perception and ros:melodic-perception respectively 2019-11-08 18:41:11 -05:00
matlabbe
e7be12e0ff Docker: removed alicevision from xenial as Eigen >=3.3 is required 2019-11-06 09:58:52 -05:00
matlabbe
d4cb623d9c docker: removed eol ubuntu distros 2019-11-04 08:46:58 -05:00
matlabbe
486b32a7d6 Added alicevision dependency in docker files. Added cosmic, disco and eoan docker files. 2019-11-03 21:14:47 -05:00
matlabbe
179f17d267 0.19.6: Added auto brightness/contrast and texture format options to multiband approach. rtabmap-export moved from examples to tools directory. 2019-11-03 14:10:02 -05:00
matlabbe
5d789f75a9 Merge branch 'alicevision' 2019-10-28 21:17:16 -04:00
matlabbe
2afa76c07c AliceVision integration, see util3d::multiBandTexturing() 2019-10-28 21:16:02 -04:00
matlabbe
260192bcc4 CameraRealSense2: Updated how D435i timestamp issue is handled (see also https://github.com/IntelRealSense/librealsense/issues/4505) 2019-10-25 18:21:40 -04:00
matlabbe
c16b22de57 Added alicevision dependency 2019-10-24 08:56:23 -04:00
matlabbe
79ad8dc4be Fixed #453 2019-10-23 12:43:36 -04:00
matlabbe
6435c74bfe DBViewer: Added "Edit Constraint" button 2019-10-18 12:22:51 -04:00
matlabbe
dd8e21e05d Features2D: set GFTT/ORB by default if GFTT/BRIEF is not available. RealSense2: fixed T265 local pose frame (when using realsense vio) 2019-10-13 19:04:11 -04:00
matlabbe
8924f9c5dc Docker/jfr2018: update msckf patch file (melodic) 2019-10-13 18:07:43 -04:00
matlabbe
981ac69c2c Zed-mini: added imu thread to publish async imu events at 200 Hz (to support VINS odometry). 2019-10-13 17:40:09 -04:00
matlabbe
1e298dcfa2 CameraRealSense2: updated how imu are published in inter mode and fixed some local transforms. GUI-VINS: features are shown in Odometry view. 2019-10-13 14:48:11 -04:00
matlabbe
9cb1e4bbc5 CameraRealSense2: Added Dual Mode (T265+D400) 2019-10-03 21:06:33 -04:00
matlabbe
3ab5ec218b Fixed #409 2019-10-01 20:53:48 -04:00
matlabbe
d360420204 report tool: exporting poses in RGB-D dataset format by default, also exporting odom, slam and gt poses. 2019-09-29 19:38:54 -04:00
matlabbe
3fd5cdfb75 DbViewer/detect more loop closures: removed a messagebox when silent and icp-only is used 2019-09-26 12:29:11 -04:00
matlabbe
547da3f3ce CloudViewer: showing intensity as grayscale instead of generic color handler 2019-09-24 18:18:49 -04:00
matlabbe
aeb2804da8 ViewClouds: fixed wrong color index used by default when normals are not computed with clouds having intensity 2019-09-24 15:55:25 -04:00
matlabbe
cf1997804f ExportClouds: Fixed exported intensity values (packing/unpacking full float intensity value, not assuming 0-100 like before) 2019-09-24 15:46:35 -04:00
matlabbe
ae374f134b Fixed https://github.com/introlab/rtabmap_ros/issues/351 2019-09-22 20:09:58 -04:00
matlabbe
c437375f08 Localization: Fixed local map cleared when gravity links are added and no localization happened. Fixed "Word not found" error on initialization when Mem/InitWMWithAllNodes is true. 2019-09-19 15:23:18 -04:00
matlabbe
955660ba2a CameraRealSense2: added stereo ir support for D400 cameras, added publishInterIMU parameter (required for VINS fusion). 2019-09-18 20:55:48 -04:00
matlabbe
b2b1977f8b Deprecated getClosestTransform(), use getTransform() instead. OdometryF2M: removed patch about forcing roll/pitch from IMU (BA is already doing the job). 2019-09-15 17:31:58 -04:00
matlabbe
350d3cd85f CameraRealSense2: fixed wrong IR image index. DBReader: fixed imu not published. OdometryF2M: use IMU roll/pitch values when IMU is used (reducing variance on those angles before BA). 2019-09-13 21:45:13 -04:00
matlabbe
bdc8d839ff Optimizing the graph if gravity or prior constraints are added in SLAM mode 2019-09-12 18:56:01 -04:00
matlabbe
5b6eddabde Added support D435i IMU in IR mode 2019-09-12 17:21:35 -04:00
matlabbe
e968fd3ef4 Remove landmark links when a node is deleted (and removed from the graph) #441 2019-09-01 13:17:44 -04:00
matlabbe
380fffb1d9 fixed #435 2019-08-27 15:30:13 -04:00
matlabbe
536f001479 Added OptimizerCeres class (Optimizer/Strategy=3) 2019-08-17 03:55:04 -04:00
matlabbe
38044040a6 Fixed mask when there are inf values in depth image 2019-08-16 16:38:25 -04:00
matlabbe
2a1b737470 OdometryVINS: fixed output pose orientation (D435i and euroc compatible) 2019-08-15 16:46:56 -04:00
matlabbe
4b118ae660 Added FastCV support (see FAST/CV parameter). VWDictionary: loading fixed dictionary only on updates (to avoid loading it multiple times when memory is reset). 2019-08-14 12:09:56 -04:00
matlabbe
d5b4b25287 updated ORBExtractor opencv include (compatibility issue https://github.com/introlab/rtabmap_ros/issues/333) 2019-08-09 15:31:47 -04:00
matlabbe
262d74d1e3 fixed a compilation error 2019-08-01 16:29:44 -04:00
matlabbe
6767c2ade2 0.19.5: added Icp/RangeMin and Icp/RangeMax parameters 2019-08-01 16:21:01 -04:00
matlabbe
487caab349 CMake: added RTABMAP_QT_VERSION option (default auto) 2019-07-31 10:37:59 -04:00
matlabbe
283274e056 DbViewer: Added Gravity info (https://github.com/introlab/rtabmap_ros/issues/323) 2019-07-29 10:45:16 -04:00
matlabbe
1a5220182c CloudViewer: added vtkTexture.h include (#425) 2019-07-28 21:24:55 -04:00
matlabbe
cd5e4f3055 Travis: added xenial build 2019-07-28 20:53:08 -04:00
matlabbe
7ea08b87d5 Travis: added bionic build 2019-07-28 20:46:04 -04:00
matlabbe
a90356f0c9 fixed https://github.com/introlab/rtabmap_ros/issues/326 2019-07-26 14:03:32 -04:00
matlabbe
6713fe8bd2 fixed https://github.com/introlab/rtabmap_ros/issues/330 2019-07-25 13:15:44 -04:00
matlabbe
62d8a892c6 DbViewer: fixed graph not re-optimized after refining an added link. Rtabmap: RGBD/ProximityPathMaxNeighbors=1 means only nearest node on a path 2019-07-23 15:21:32 -04:00
matlabbe
3558640407 OptimizerGTSAM: fixed landmarks not transformed back in 3D after 2D optimization (slam2d) 2019-07-17 12:15:04 -04:00
matlabbe
5222506578 DbViewer: neighbor links can be rejected (a warning about splitting the graph is shown though) 2019-07-11 18:53:47 -04:00
matlabbe
89f1e809e6 CameraK4A: use mkv framerate if camera rate is -1. Preferences/Source: fixed imu filter parameters not reset on restore defaults 2019-07-11 18:13:20 -04:00
matlabbe
0973f48b2c CameraK4A: added finding lib on linux 2019-07-10 12:34:13 -04:00
matlabbe
3c7719f6d8 Added CameraK4A driver (only MKV playback supported yet). Fixed build with realsense2 support on Windows. Preferences: added imu filtering parameters to ini file. 2019-07-09 20:48:09 -04:00
matlabbe
63be7c85fc DBViewer: when adding new constraints, if visual reg is not used, we use optimized graph as guess 2019-07-05 16:28:31 -04:00
matlabbe
78d0d60b9f Added RealSense SR300 camera support (#421) 2019-07-05 11:19:45 -04:00
matlabbe
bb94adc846 UPlot: Fixed backward compatibility with Qt4 2019-07-03 14:22:17 -04:00
matlabbe
abbf7e4476 Updated UPlot data copy to include data of all curves (common x-axis), added also mean and max along stddev in legend item option 2019-07-03 12:01:34 -04:00
matlabbe
72e613fe28 UPlot: updated copy curve data to clipboard format to be more convenient for copy/paste directly in excel, also added curve names as header 2019-06-26 16:59:44 -04:00
matlabbe
49977b5475 Added ground truth localization error stats 2019-06-26 16:21:03 -04:00
matlabbe
9d8fd364e3 UI/Preferences: Adjusted Vis/MinInliersDistribution decimals 2019-06-18 14:22:29 -04:00
matlabbe
50fdc210c9 Memory: added some warnings about pre-postdecimation parameters, updated their description (removed negative decimation comment) 2019-06-17 10:19:54 -04:00
matlabbe
d205683eb5 Added parameters Vis/MeanInliersDistance and Vis/MinInliersDistribution 2019-06-16 18:54:39 -04:00
matlabbe
85edc57ba5 Added RGBD/MaxLocalizationDistance parameter 2019-06-12 16:03:52 -04:00
matlabbe
b5f5623af4 CameraRealSense2: updated how stamping is done, updated default D435 frame resolution/fps 2019-06-06 17:17:11 -04:00
334 changed files with 33896 additions and 9494 deletions

View File

@@ -35,7 +35,7 @@ install:
# 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
- ps: wget 'http://kent.dl.sourceforge.net/project/opencvlibrary/opencv-win/2.4.13/opencv-2.4.13.6-vc14.exe' -outfile opencv-2.4.13.6-vc14.exe
- ps: $url = "https://downloads.sourceforge.net/project/opencvlibrary/opencv-win/2.4.13/opencv-2.4.13.6-vc14.exe?r=&ts="+([int64](([datetime]::UtcNow)-(get-date "1/1/1970")).TotalSeconds) ; wget $url -outfile opencv-2.4.13.6-vc14.exe
- cmd: opencv-2.4.13.6-vc14.exe -o"C:\Program Files" -y
- ECHO "Installed OpenCV:"
- ps: "ls \"C:/Program Files/opencv/build\""
@@ -115,6 +115,20 @@ install:
- cmd: yaml-cpp.exe -o"C:\Program Files" -y
- ECHO "Installed yaml-cpp:"
- ps: "ls \"C:/Program Files/yaml-cpp\""
# RealSense2
- ps: wget 'https://github.com/IntelRealSense/librealsense/releases/download/v2.40.0/Intel.RealSense.SDK-WIN10-2.40.0.2482.exe' -outfile realsense2.exe
- cmd: realsense2.exe /VERYSILENT
- ECHO "Installed RealSense2:"
- ps: "ls \"C:/Program Files (x86)/Intel RealSense SDK 2.0\""
- set PATH=%PATH%;C:\Program Files (x86)\Intel RealSense SDK 2.0\bin\x64
- set RealSense2_ROOT_DIR=C:\Program Files (x86)\Intel RealSense SDK 2.0
# Kinect 4 Azure
- ps: wget 'https://download.microsoft.com/download/3/d/6/3d6d9e99-a251-4cf3-8c6a-8e108e960b4b/Azure%20Kinect%20SDK%201.4.1.exe' -outfile azure.exe
- cmd: azure.exe /quiet
- ECHO "Installed Kinect For Azure:"
- ps: "ls \"C:/Program Files/Azure Kinect SDK v1.4.1\""
- set PATH=%PATH%;C:\Program Files\Azure Kinect SDK v1.4.1\tools
- set K4A_ROOT_DIR=C:\Program Files\Azure Kinect SDK v1.4.1
before_build:
- cd c:\projects\rtabmap\build

2
.gitignore vendored
View File

@@ -8,3 +8,5 @@ app/android/.classpath
app/android/.project
app/android/AndroidManifest.xml
app/android/res/raw/
compile_flags.txt
tags

View File

@@ -1,33 +1,72 @@
sudo: true
dist: trusty
language: cpp
group: deprecated-2017Q3
compiler:
- gcc
- clang
addons:
apt:
packages:
- cmake
- libopencv-dev
- libqt4-dev
- libsqlite3-dev
- libyaml-cpp-dev
matrix:
include:
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
- dist: trusty
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 ros-indigo-rtabmap-ros
- sudo apt-get -y remove ros-indigo-rtabmap
script:
- source /opt/ros/indigo/setup.bash
- mkdir -p build && cd build
- cmake ..
- make
script:
- source /opt/ros/indigo/setup.bash
- mkdir -p build && cd build
- cmake ..
- make
- dist: xenial
install:
- sudo sh -c 'echo "deb http://packages.ros.org/ros/ubuntu xenial 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 ros-kinetic-rtabmap-ros
- sudo apt-get -y remove ros-kinetic-rtabmap
script:
- source /opt/ros/kinetic/setup.bash
- mkdir -p build && cd build
- cmake ..
- make
- dist: bionic
install:
- sudo sh -c 'echo "deb http://packages.ros.org/ros/ubuntu bionic 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 ros-melodic-rtabmap-ros
- sudo apt-get -y remove ros-melodic-rtabmap
script:
- source /opt/ros/melodic/setup.bash
- mkdir -p build && cd build
- cmake ..
- make
- dist: focal
install:
- sudo sh -c 'echo "deb http://packages.ros.org/ros/ubuntu focal 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 ros-noetic-rtabmap-ros
- sudo apt-get -y remove ros-noetic-rtabmap
script:
- source /opt/ros/noetic/setup.bash
- mkdir -p build && cd build
- cmake ..
- make
notifications:
email:

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 19)
SET(RTABMAP_PATCH_VERSION 3)
SET(RTABMAP_MINOR_VERSION 20)
SET(RTABMAP_PATCH_VERSION 7)
SET(RTABMAP_VERSION
${RTABMAP_MAJOR_VERSION}.${RTABMAP_MINOR_VERSION}.${RTABMAP_PATCH_VERSION})
@@ -61,7 +61,7 @@ ELSE ()
ENDIF()
if(POLICY CMP0020)
cmake_policy(SET CMP0020 OLD)
cmake_policy(SET CMP0020 NEW)
endif()
if(POLICY CMP0043)
cmake_policy(SET CMP0043 OLD)
@@ -163,14 +163,18 @@ ELSE()
option(WITH_QT "Include Qt support" ON)
ENDIF()
option(WITH_ORB_OCTREE "Include ORB Octree feature support" ON)
option(WITH_SUPERPOINT_TORCH "Include SuperPoint Torch feature support" ON)
option(WITH_PYMATCHER "Include Python3 matchers support" OFF)
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_K4A "Include Kinect for Azure support" ON)
option(WITH_OPENNI2 "Include OpenNI2 support" ON)
option(WITH_DC1394 "Include dc1394 support" ON)
option(WITH_G2O "Include g2o support" ON)
option(WITH_GTSAM "Include GTSAM support" ON)
option(WITH_TORO "Include TORO support" ON)
option(WITH_CERES "Include Ceres support" ON)
option(WITH_VERTIGO "Include Vertigo support" ON)
option(WITH_CVSBA "Include cvsba support" ON)
option(WITH_POINTMATCHER "Include libpointmatcher support" ON)
@@ -180,9 +184,11 @@ 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_MYNTEYE "Include mynteye-s 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_ALICE_VISION "Include AliceVision support" OFF)
option(WITH_FOVIS "Include FOVIS support" ON)
option(WITH_VISO2 "Include VISO2 support" ON)
option(WITH_DVO "Include DVO support" ON)
@@ -191,7 +197,15 @@ option(WITH_OKVIS "Include OKVIS support" ON)
option(WITH_MSCKF_VIO "Include MSCKF_VIO support" OFF)
option(WITH_VINS "Include VINS-Fusion support" ON)
option(WITH_MADGWICK "Include Madgwick IMU filtering support" ON)
option(WITH_FASTCV "Include FastCV support" ON)
IF(ANDROID)
option(PCL_OMP "With PCL OMP implementations" OFF)
ELSE()
option(PCL_OMP "With PCL OMP implementations" ON)
ENDIF()
set(RTABMAP_QT_VERSION AUTO CACHE STRING "Force a specific Qt version.")
set_property(CACHE RTABMAP_QT_VERSION PROPERTY STRINGS AUTO 4 5)
FIND_PACKAGE(OpenCV REQUIRED QUIET)
@@ -263,14 +277,18 @@ IF(WITH_QT)
# If Qt is here, the GUI will be built
# look for Qt5 (if vtk>5 is installed) before Qt4
IF("${VTK_MAJOR_VERSION}" GREATER 5)
FIND_PACKAGE(Qt5 COMPONENTS Widgets Core Gui QUIET)
IF(Qt5_FOUND)
FIND_PACKAGE(Qt5 COMPONENTS Widgets Core Gui OPTIONAL_COMPONENTS Svg)
ENDIF(Qt5_FOUND)
if(RTABMAP_QT_VERSION STREQUAL "AUTO" OR RTABMAP_QT_VERSION STREQUAL "5")
FIND_PACKAGE(Qt5 COMPONENTS Widgets Core Gui QUIET)
IF(Qt5_FOUND)
FIND_PACKAGE(Qt5 COMPONENTS Widgets Core Gui OPTIONAL_COMPONENTS Svg)
ENDIF(Qt5_FOUND)
ENDIF(RTABMAP_QT_VERSION STREQUAL "AUTO" OR RTABMAP_QT_VERSION STREQUAL "5")
ENDIF("${VTK_MAJOR_VERSION}" GREATER 5)
IF(NOT Qt5_FOUND)
FIND_PACKAGE(Qt4 COMPONENTS QtCore QtGui OPTIONAL_COMPONENTS QtSvg)
IF(RTABMAP_QT_VERSION STREQUAL "AUTO" OR RTABMAP_QT_VERSION STREQUAL "4")
FIND_PACKAGE(Qt4 COMPONENTS QtCore QtGui OPTIONAL_COMPONENTS QtSvg)
ENDIF(RTABMAP_QT_VERSION STREQUAL "AUTO" OR RTABMAP_QT_VERSION STREQUAL "4")
ENDIF(NOT Qt5_FOUND)
IF(QT4_FOUND OR Qt5_FOUND)
@@ -282,15 +300,42 @@ 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")
MESSAGE(STATUS "VTK_RENDERING_BACKEND=${VTK_RENDERING_BACKEND}")
IF(VTK_RENDERING_BACKEND STREQUAL "OpenGL2")
ADD_DEFINITIONS("-DVTK_OPENGL2")
# see issue #525
list(FIND PCL_LIBRARIES vtkRenderingVolumeOpenGL2 value)
IF(value EQUAL -1)
SET(PCL_LIBRARIES "${PCL_LIBRARIES};vtkRenderingVolumeOpenGL2")
ENDIF(value EQUAL -1)
ELSEIF(VTK_RENDERING_BACKEND STREQUAL "OpenGL")
# PCL 1.9 not adding vtkRenderingVolumeOpenGL as dependency anymore, so add it for us
list(FIND PCL_LIBRARIES vtkRenderingVolumeOpenGL value)
IF(value EQUAL -1)
SET(PCL_LIBRARIES "${PCL_LIBRARIES};vtkRenderingVolumeOpenGL")
ENDIF(value EQUAL -1)
ENDIF()
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)
IF(WITH_SUPERPOINT_TORCH)
FIND_PACKAGE(Torch QUIET)
IF(TORCH_FOUND)
MESSAGE(STATUS "Found Torch: ${TORCH_INCLUDE_DIRS}")
ENDIF(TORCH_FOUND)
ENDIF(WITH_SUPERPOINT_TORCH)
IF(WITH_PYMATCHER)
FIND_PACKAGE(Python3 COMPONENTS Interpreter Development)
IF(Python3_FOUND)
MESSAGE(STATUS "Found Python3")
ENDIF(Python3_FOUND)
ENDIF(WITH_PYMATCHER)
IF(WITH_FREENECT)
FIND_PACKAGE(Freenect QUIET)
IF(Freenect_FOUND)
@@ -323,6 +368,21 @@ IF(WITH_K4W2 AND WIN32)
ENDIF(KinectSDK2_FOUND)
ENDIF(WITH_K4W2 AND WIN32)
IF(WITH_K4A)
IF(WIN32)
FIND_PACKAGE(K4A QUIET)
ELSE()
FIND_PACKAGE(k4a QUIET)
FIND_PACKAGE(k4arecord QUIET)
IF(NOT (k4a_FOUND AND k4arecord_FOUND))
SET(k4a_FOUND FALSE)
ENDIF(NOT (k4a_FOUND AND k4arecord_FOUND))
ENDIF()
IF(k4a_FOUND)
MESSAGE(STATUS "Found Kinect for Azure: ${k4a_INCLUDE_DIRS}")
ENDIF(k4a_FOUND)
ENDIF(WITH_K4A)
# IF PCL depends on OpenNI2 (already found), ignore WITH_OPENNI2
IF(WITH_OPENNI2 OR OpenNI2_FOUND)
FIND_PACKAGE(OpenNI2 QUIET)
@@ -367,6 +427,10 @@ ENDIF(WITH_CVSBA)
IF(WITH_POINTMATCHER)
find_package(libpointmatcher QUIET)
IF(libpointmatcher_FOUND)
find_package(Boost COMPONENTS thread filesystem system program_options date_time REQUIRED)
if (Boost_MINOR_VERSION GREATER 47)
find_package(Boost COMPONENTS thread filesystem system program_options date_time chrono timer REQUIRED)
endif (Boost_MINOR_VERSION GREATER 47)
MESSAGE(STATUS "Found libpointmatcher: ${libpointmatcher_INCLUDE_DIRS}")
ENDIF(libpointmatcher_FOUND)
ENDIF(WITH_POINTMATCHER)
@@ -411,7 +475,7 @@ ENDIF(WITH_REALSENSE)
IF(WITH_REALSENSE2)
IF(WIN32)
FIND_PACKAGE(RealSense2 QUIET)
ELSE()
ELSE()
FIND_PACKAGE(realsense2 QUIET)
ENDIF()
IF(realsense2_FOUND)
@@ -419,14 +483,21 @@ IF(WITH_REALSENSE2)
ENDIF(realsense2_FOUND)
ENDIF(WITH_REALSENSE2)
IF(WITH_MYNTEYE)
FIND_PACKAGE(mynteye QUIET)
IF(mynteye_FOUND)
MESSAGE(STATUS "Found mynteye-s: ${mynteye_INCLUDE_DIRS}")
ENDIF(mynteye_FOUND)
ENDIF(WITH_MYNTEYE)
IF(WITH_OCTOMAP)
FIND_PACKAGE(OCTOMAP QUIET)
IF(OCTOMAP_FOUND)
MESSAGE(STATUS "Found octomap ${OCTOMAP_VERSION}: ${OCTOMAP_INCLUDE_DIRS}")
IF(OCTOMAP_VERSION VERSION_LESS 1.8)
FIND_PACKAGE(octomap QUIET)
IF(octomap_FOUND)
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(octomap_VERSION VERSION_LESS 1.8)
ENDIF(octomap_FOUND)
ENDIF(WITH_OCTOMAP)
IF(WITH_CPUTSDF)
@@ -443,6 +514,17 @@ IF(WITH_OPENCHISEL)
endif(open_chisel_FOUND)
ENDIF(WITH_OPENCHISEL)
IF(WITH_ALICE_VISION)
find_package(AliceVision CONFIG QUIET)
IF(AliceVision_FOUND)
SET(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH};/usr/local/lib/cmake/modules")
find_package(Geogram REQUIRED QUIET)
add_definitions("-DRTABMAP_ALICE_VISION_MAJOR=${AliceVision_VERSION_MAJOR}")
add_definitions("-DRTABMAP_ALICE_VISION_MINOR=${AliceVision_VERSION_MINOR}")
add_definitions("-DRTABMAP_ALICE_VISION_PATCH=${AliceVision_VERSION_PATCH}")
ENDIF(AliceVision_FOUND)
ENDIF(WITH_ALICE_VISION)
IF(WITH_FOVIS)
FIND_PACKAGE(libfovis QUIET)
IF(libfovis_FOUND)
@@ -477,6 +559,11 @@ IF(WITH_OKVIS)
ENDIF(okvis_FOUND)
ENDIF(WITH_OKVIS)
# If built with okvis, we found already ceres above
IF(NOT okvis_FOUND AND WITH_CERES)
FIND_PACKAGE(Ceres QUIET)
ENDIF(NOT okvis_FOUND AND WITH_CERES)
IF(WITH_MSCKF_VIO)
FIND_PACKAGE(msckf_vio QUIET)
IF(msckf_vio_FOUND)
@@ -494,6 +581,12 @@ IF(WITH_VINS)
ENDIF(vins_FOUND)
ENDIF(WITH_VINS)
IF(WITH_FASTCV)
FIND_PACKAGE(FastCV QUIET)
IF(FastCV_FOUND)
MESSAGE(STATUS "Found FastCV: ${FastCV_INCLUDE_DIRS}")
ENDIF(FastCV_FOUND)
ENDIF(WITH_FASTCV)
IF(WITH_ORB_SLAM2 AND NOT G2O_FOUND)
FIND_PACKAGE(ORB_SLAM2 QUIET)
@@ -511,8 +604,8 @@ IF(WITH_ORB_SLAM2 AND NOT G2O_FOUND)
ENDIF(ORB_SLAM2_FOUND)
ENDIF(WITH_ORB_SLAM2 AND NOT G2O_FOUND)
IF(loam_velodyne_FOUND)
#LOAM requires c++14
IF(loam_velodyne_FOUND OR PCL_VERSION VERSION_GREATER "1.9.1" OR TORCH_FOUND)
#LOAM and PCL>=1.10 require c++14
IF(NOT MSVC)
include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("-std=c++14" COMPILER_SUPPORTS_CXX14)
@@ -524,6 +617,7 @@ IF(loam_velodyne_FOUND)
ENDIF()
ELSEIF(G2O_FOUND OR
GTSAM_FOUND OR
CERES_FOUND OR
ZED_FOUND OR
ANDROID OR
RealSense_FOUND OR
@@ -532,7 +626,8 @@ ELSEIF(G2O_FOUND OR
okvis_FOUND OR
open_chisel_FOUND OR
msckf_vio_FOUND OR
vins_FOUND)
vins_FOUND OR
libpointmatcher_FOUND)
#Newest versions require std11
IF(NOT MSVC)
include(CheckCXXCompilerFlag)
@@ -582,6 +677,10 @@ ENDIF(APPLE AND BUILD_AS_BUNDLE)
SET(CONF_DEPENDENCIES
${ZLIB_LIBRARIES}
)
# OpenCV2 has nonfree if OPENCV_NONFREE_FOUND
# OpenCV<=3.4.2 has nonfree if OPENCV_XFEATURES2D_FOUND
# OpenCV>3.4.2 has nonfree if OPENCV_XFEATURES2D_FOUND and OPENCV_ENABLE_NONFREE is defined
IF(NOT (OPENCV_NONFREE_FOUND OR OPENCV_XFEATURES2D_FOUND))
SET(NONFREE "//")
ELSEIF(OpenCV_VERSION VERSION_GREATER "3.4.2")
@@ -608,6 +707,9 @@ IF(NOT GTSAM_FOUND)
ELSE()
SET(CONF_DEPENDENCIES ${CONF_DEPENDENCIES} ${GTSAM_LIBRARIES})
ENDIF()
IF(NOT CERES_FOUND)
SET(CERES "//")
ENDIF(NOT CERES_FOUND)
IF(NOT WITH_TORO)
SET(TORO "//")
ENDIF(NOT WITH_TORO)
@@ -622,6 +724,9 @@ ENDIF()
IF(NOT libpointmatcher_FOUND)
SET(POINTMATCHER "//")
ENDIF(NOT libpointmatcher_FOUND)
IF(NOT FastCV_FOUND)
SET(FASTCV "//")
ENDIF(NOT FastCV_FOUND)
IF(NOT loam_velodyne_FOUND)
SET(LOAM "//")
ENDIF(NOT loam_velodyne_FOUND)
@@ -640,6 +745,11 @@ IF(NOT KinectSDK2_FOUND)
ELSE()
SET(CONF_DEPENDENCIES ${CONF_DEPENDENCIES} ${KinectSDK2_LIBRARIES})
ENDIF()
IF(NOT k4a_FOUND)
SET(K4A "//")
ELSE()
SET(CONF_DEPENDENCIES ${CONF_DEPENDENCIES} ${k4a_LIBRARIES})
ENDIF()
IF(NOT OpenNI2_FOUND)
SET(OPENNI2 "//")
ELSE()
@@ -673,7 +783,10 @@ IF(NOT realsense2_FOUND)
ELSE()
SET(CONF_DEPENDENCIES ${CONF_DEPENDENCIES} ${realsense2_LIBRARIES})
ENDIF()
IF(NOT OCTOMAP_FOUND)
IF(NOT mynteye_FOUND)
SET(MYNTEYE "//")
ENDIF(NOT mynteye_FOUND)
IF(NOT octomap_FOUND)
SET(OCTOMAP "//")
ELSE()
SET(CONF_DEPENDENCIES ${CONF_DEPENDENCIES} ${OCTOMAP_LIBRARIES})
@@ -688,6 +801,9 @@ IF(NOT open_chisel_FOUND)
ELSE()
SET(CONF_DEPENDENCIES ${CONF_DEPENDENCIES} ${open_chisel_LIBRARIES})
ENDIF()
IF(NOT AliceVision_FOUND)
SET(ALICE_VISION "//")
ENDIF(NOT AliceVision_FOUND)
IF(NOT libfovis_FOUND)
SET(FOVIS "//")
ELSE()
@@ -726,6 +842,12 @@ ENDIF()
IF(NOT WITH_ORB_OCTREE)
SET(ORB_OCTREE "//")
ENDIF()
IF(NOT TORCH_FOUND)
SET(SUPERPOINT_TORCH "//")
ENDIF()
IF(NOT Python3_FOUND)
SET(PYMATCHER "//")
ENDIF()
IF(ADD_VTK_GUI_SUPPORT_QT_TO_CONF)
SET(CONF_VTK_QT true)
SET(CONF_DEPENDENCIES ${CONF_DEPENDENCIES} vtkGUISupportQt)
@@ -739,9 +861,6 @@ IF(NOT WITH_MADGWICK)
SET(MADGWICK "//")
ENDIF()
IF(NOT (OpenCV_FOUND AND NOT (OpenCV_VERSION_MAJOR LESS 3)))
SET(OPENCV3 "//")
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 )
@@ -928,10 +1047,12 @@ ENDIF(APPLE OR WIN32)
MESSAGE(STATUS " CMAKE_CXX_FLAGS = ${CMAKE_CXX_FLAGS}")
MESSAGE(STATUS " FLANN_KDTREE_MEM_OPT = ${FLANN_KDTREE_MEM_OPT}")
MESSAGE(STATUS " PCL_DEFINITIONS = ${PCL_DEFINITIONS}")
MESSAGE(STATUS " PCL_VERSION = ${PCL_VERSION}")
IF(PCL_COMPILE_OPTIONS)
MESSAGE(STATUS " PCL_COMPILE_OPTIONS = ${PCL_COMPILE_OPTIONS}")
ENDIF(PCL_COMPILE_OPTIONS)
MESSAGE(STATUS "")
MESSAGE(STATUS "Optional dependencies ('*' affects some default parameters) :")
IF(OpenCV_FOUND)
IF(OpenCV_VERSION_MAJOR EQUAL 2)
@@ -942,13 +1063,30 @@ IF(OpenCV_FOUND)
ENDIF()
ELSE()
IF(OPENCV_XFEATURES2D_FOUND)
MESSAGE(STATUS " *With OpenCV ${OpenCV_VERSION_MAJOR} xfeatures2d module (SIFT/SURF/BRIEF/FREAK) = YES (License: Non commercial)")
IF(NONFREE STREQUAL "//")
MESSAGE(STATUS " *With OpenCV ${OpenCV_VERSION} xfeatures2d = YES, nonfree = NO (License: BSD)")
ELSE()
MESSAGE(STATUS " *With OpenCV ${OpenCV_VERSION} xfeatures2d = YES, nonfree = YES (License: Non commercial)")
ENDIF()
ELSE()
MESSAGE(STATUS " *With OpenCV ${OpenCV_VERSION_MAJOR} xfeatures2d module (SIFT/SURF/BRIEF/FREAK) = NO (not found, License: BSD)")
MESSAGE(STATUS " *With OpenCV ${OpenCV_VERSION} xfeatures2d = NO, nonfree = NO (License: BSD)")
ENDIF()
ENDIF()
ENDIF(OpenCV_FOUND)
IF(QT4_FOUND)
MESSAGE(STATUS " With Qt4 = YES (License: Open Source or Commercial)")
MESSAGE(STATUS " With VTK ${VTK_MAJOR_VERSION}.${VTK_MINOR_VERSION} = YES (License: BSD)")
ELSEIF(Qt5_FOUND)
MESSAGE(STATUS " With Qt ${Qt5_VERSION} = YES (License: Open Source or Commercial)")
MESSAGE(STATUS " With VTK ${VTK_MAJOR_VERSION}.${VTK_MINOR_VERSION} = YES (License: BSD)")
ELSEIF(NOT WITH_QT)
MESSAGE(STATUS " With Qt = NO (WITH_QT=OFF)")
ELSE()
MESSAGE(STATUS " With Qt = NO (Qt not found)")
ENDIF()
IF(Sqlite3_FOUND)
MESSAGE(STATUS " With external SQLite3 = YES (License: Public Domain)")
ELSE()
@@ -961,12 +1099,130 @@ ELSE()
MESSAGE(STATUS " With ORB OcTree = NO (WITH_ORB_OCTREE=OFF)")
ENDIF()
IF(TORCH_FOUND)
MESSAGE(STATUS " With SupertPoint = YES (License: GPLv3) libtorch=${Torch_VERSION}")
ELSEIF(NOT WITH_SUPERPOINT_TORCH)
MESSAGE(STATUS " With SupertPoint = NO (WITH_SUPERPOINT_TORCH=OFF)")
ELSE()
MESSAGE(STATUS " With SupertPoint = NO (libtorch not found)")
ENDIF()
IF(Python3_FOUND)
MESSAGE(STATUS " With Python3 = YES (License: PSF)")
ELSEIF(NOT WITH_PYMATCHER)
MESSAGE(STATUS " With Python3 = NO (WITH_PYMATCHER=OFF)")
ELSE()
MESSAGE(STATUS " With Python3 = NO (python3 not found)")
ENDIF()
IF(WITH_MADGWICK)
MESSAGE(STATUS " With Madgwick = YES (License: GPL)")
ELSE()
MESSAGE(STATUS " With Madgwick = NO (WITH_MADGWICK=OFF)")
ENDIF()
IF(FastCV_FOUND)
MESSAGE(STATUS " With FastCV = YES (License: Apache v2)")
ELSEIF(NOT WITH_FASTCV)
MESSAGE(STATUS " With FastCV = NO (WITH_FASTCV=OFF)")
ELSE()
MESSAGE(STATUS " With FastCV = NO (FastCV not found)")
ENDIF()
MESSAGE(STATUS "")
MESSAGE(STATUS " Solvers:")
IF(WITH_TORO)
MESSAGE(STATUS " With TORO = YES (License: Creative Commons [Attribution-NonCommercial-ShareAlike])")
ELSE()
MESSAGE(STATUS " With TORO = NO (WITH_TORO=OFF)")
ENDIF()
IF(G2O_FOUND)
MESSAGE(STATUS " *With g2o = YES (License: BSD)")
ELSEIF(NOT WITH_G2O)
MESSAGE(STATUS " *With g2o = NO (WITH_G2O=OFF)")
ELSE()
MESSAGE(STATUS " *With g2o = NO (g2o not found)")
ENDIF()
IF(GTSAM_FOUND)
MESSAGE(STATUS " *With GTSAM = YES (License: BSD)")
ELSEIF(NOT WITH_GTSAM)
MESSAGE(STATUS " *With GTSAM = NO (WITH_GTSAM=OFF)")
ELSE()
MESSAGE(STATUS " *With GTSAM = NO (GTSAM not found)")
ENDIF()
IF(CERES_FOUND)
MESSAGE(STATUS " *With Ceres = YES (License: BSD)")
ELSEIF(NOT WITH_CERES)
MESSAGE(STATUS " *With Ceres = NO (WITH_CERES=OFF)")
ELSE()
MESSAGE(STATUS " *With Ceres = NO (Ceres not found)")
ENDIF()
IF(G2O_FOUND OR GTSAM_FOUND)
IF(WITH_VERTIGO)
MESSAGE(STATUS " With VERTIGO = YES (License: GPLv3)")
ELSE()
MESSAGE(STATUS " With VERTIGO = NO (WITH_VERTIGO=OFF)")
ENDIF()
ELSE()
MESSAGE(STATUS " With VERTIGO = NO (GTSAM or g2o required)")
ENDIF()
IF(cvsba_FOUND)
MESSAGE(STATUS " With cvsba = YES (License: GPLv2)")
ELSEIF(NOT WITH_CVSBA)
MESSAGE(STATUS " With cvsba = NO (WITH_CVSBA=OFF)")
ELSE()
MESSAGE(STATUS " With cvsba = NO (cvsba not found)")
ENDIF()
IF(libpointmatcher_FOUND)
MESSAGE(STATUS " *With libpointmatcher = YES (License: BSD)")
ELSEIF(NOT WITH_POINTMATCHER)
MESSAGE(STATUS " *With libpointmatcher = NO (WITH_POINTMATCHER=OFF)")
ELSE()
MESSAGE(STATUS " *With libpointmatcher = NO (libpointmatcher not found)")
ENDIF()
MESSAGE(STATUS "")
MESSAGE(STATUS " Reconstruction Approaches:")
IF(octomap_FOUND)
MESSAGE(STATUS " With OCTOMAP = YES (License: BSD)")
ELSEIF(NOT WITH_OCTOMAP)
MESSAGE(STATUS " With OCTOMAP = NO (WITH_OCTOMAP=OFF)")
ELSE()
MESSAGE(STATUS " With OCTOMAP = NO (octomap not found)")
ENDIF()
IF(CPUTSDF_FOUND)
MESSAGE(STATUS " With CPUTSDF = YES (License: BSD)")
ELSEIF(NOT WITH_CPUTSDF)
MESSAGE(STATUS " With CPUTSDF = NO (WITH_CPUTSDF=OFF)")
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(AliceVision_FOUND)
MESSAGE(STATUS " With AliceVision ${AliceVision_VERSION} = YES (License: MPLv2)")
ELSEIF(NOT WITH_ALICE_VISION)
MESSAGE(STATUS " With AliceVision = NO (WITH_ALICE_VISION=OFF)")
ELSE()
MESSAGE(STATUS " With AliceVision = NO (AliceVision not found)")
ENDIF()
MESSAGE(STATUS "")
MESSAGE(STATUS " Camera Drivers:")
IF(Freenect_FOUND)
MESSAGE(STATUS " With Freenect = YES (License: Apache v2 and/or GPLv2)")
ELSEIF(NOT WITH_FREENECT)
@@ -999,6 +1255,14 @@ ELSE()
MESSAGE(STATUS " With Kinect for Windows 2 = NO (Kinect for Windows 2 SDK not found)")
ENDIF()
IF(k4a_FOUND)
MESSAGE(STATUS " With Kinect for Azure = YES (License: MIT)")
ELSEIF(NOT WITH_K4A)
MESSAGE(STATUS " With Kinect for Azure = NO (WITH_K4A=OFF)")
ELSE()
MESSAGE(STATUS " With Kinect for Azure = NO (Kinect for Azure SDK not found)")
ENDIF()
IF(DC1394_FOUND)
MESSAGE(STATUS " With dc1394 = YES (License: LGPL)")
ELSEIF(NOT WITH_DC1394)
@@ -1015,72 +1279,12 @@ ELSE()
MESSAGE(STATUS " With FlyCapture2/Triclops = NO (Point Grey SDK not found)")
ENDIF()
IF(WITH_TORO)
MESSAGE(STATUS " With TORO = YES (License: Creative Commons [Attribution-NonCommercial-ShareAlike])")
ELSE()
MESSAGE(STATUS " With TORO = NO (WITH_TORO=OFF)")
ENDIF()
IF(G2O_FOUND)
MESSAGE(STATUS " *With g2o = YES (License: BSD)")
ELSEIF(NOT WITH_G2O)
MESSAGE(STATUS " *With g2o = NO (WITH_G2O=OFF)")
ELSE()
MESSAGE(STATUS " *With g2o = NO (g2o not found)")
ENDIF()
IF(GTSAM_FOUND)
MESSAGE(STATUS " *With GTSAM = YES (License: BSD)")
ELSEIF(NOT WITH_GTSAM)
MESSAGE(STATUS " *With GTSAM = NO (WITH_GTSAM=OFF)")
ELSE()
MESSAGE(STATUS " *With GTSAM = NO (GTSAM not found)")
ENDIF()
IF(G2O_FOUND OR GTSAM_FOUND)
IF(WITH_VERTIGO)
MESSAGE(STATUS " With VERTIGO = YES (License: GPLv3)")
ELSE()
MESSAGE(STATUS " With VERTIGO = NO (WITH_VERTIGO=OFF)")
ENDIF()
ELSE()
MESSAGE(STATUS " With VERTIGO = NO (GTSAM or g2o required)")
ENDIF()
IF(cvsba_FOUND)
MESSAGE(STATUS " With cvsba = YES (License: GPLv2)")
ELSEIF(NOT WITH_CVSBA)
MESSAGE(STATUS " With cvsba = NO (WITH_CVSBA=OFF)")
ELSE()
MESSAGE(STATUS " With cvsba = NO (cvsba not found)")
ENDIF()
IF(libpointmatcher_FOUND)
MESSAGE(STATUS " *With libpointmatcher = YES (License: BSD)")
ELSEIF(NOT WITH_POINTMATCHER)
MESSAGE(STATUS " *With libpointmatcher = NO (WITH_POINTMATCHER=OFF)")
ELSE()
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)
IF(CUDA_FOUND)
MESSAGE(STATUS " With ZED = YES (With CUDA)")
ELSE()
MESSAGE(STATUS " With ZED = YES (Without CUDA)")
ENDIF()
IF(ZED_FOUND AND CUDA_FOUND)
MESSAGE(STATUS " With ZED = YES")
ELSEIF(NOT WITH_ZED)
MESSAGE(STATUS " With ZED = NO (WITH_ZED=OFF)")
ELSE()
MESSAGE(STATUS " With ZED = NO (ZED sdk not found)")
MESSAGE(STATUS " With ZED = NO (ZED sdk and/or cuda not found)")
ENDIF()
IF(RealSense_FOUND)
@@ -1106,28 +1310,22 @@ ELSE()
MESSAGE(STATUS " With RealSense2 = NO (librealsense2 not found)")
ENDIF()
IF(OCTOMAP_FOUND)
MESSAGE(STATUS " With OCTOMAP = YES (License: BSD)")
ELSEIF(NOT WITH_OCTOMAP)
MESSAGE(STATUS " With OCTOMAP = NO (WITH_OCTOMAP=OFF)")
IF(mynteye_FOUND)
MESSAGE(STATUS " With MyntEyeS = YES (License: Apache-2)")
ELSEIF(NOT WITH_MYNTEYE)
MESSAGE(STATUS " With MyntEyeS = NO (WITH_MYNTEYE=OFF)")
ELSE()
MESSAGE(STATUS " With OCTOMAP = NO (octomap not found)")
MESSAGE(STATUS " With MyntEyeS = NO (mynteye s sdk not found)")
ENDIF()
IF(CPUTSDF_FOUND)
MESSAGE(STATUS " With CPUTSDF = YES (License: BSD)")
ELSEIF(NOT WITH_CPUTSDF)
MESSAGE(STATUS " With CPUTSDF = NO (WITH_CPUTSDF=OFF)")
MESSAGE(STATUS "")
MESSAGE(STATUS " Odometry Approaches:")
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 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)")
MESSAGE(STATUS " With loam_velodyne = NO (loam_velodyne not found)")
ENDIF()
IF(libfovis_FOUND)
@@ -1188,23 +1386,15 @@ ELSE()
MESSAGE(STATUS " With ORB_SLAM2 = NO (ORB_SLAM2 not found, make sure environment variable ORB_SLAM2_ROOT_DIR is set)")
ENDIF()
IF(QT4_FOUND)
MESSAGE(STATUS " With Qt4 = YES (License: Open Source or Commercial)")
ELSEIF(Qt5_FOUND)
MESSAGE(STATUS " With Qt5 = YES (License: Open Source or Commercial)")
ELSEIF(NOT WITH_QT)
MESSAGE(STATUS " With Qt = NO (WITH_QT=OFF)")
ELSE()
MESSAGE(STATUS " With Qt = NO (Qt not found)")
ENDIF()
MESSAGE(STATUS "Show all options with: cmake -LA | grep WITH_")
MESSAGE(STATUS "--------------------------------------------")
IF(NOT GTSAM_FOUND AND NOT G2O_FOUND AND NOT WITH_TORO)
IF(NOT GTSAM_FOUND AND NOT G2O_FOUND AND NOT WITH_TORO AND NOT CERES_FOUND)
MESSAGE(SEND_ERROR "No graph optimizer found! You should have at least one of these options:
g2o (https://github.com/RainerKuemmerle/g2o)
GTSAM (https://collab.cc.gatech.edu/borg/gtsam)
Ceres (http://ceres-solver.org)
set -DWITH_TORO=ON")
ENDIF(NOT GTSAM_FOUND AND NOT G2O_FOUND AND NOT WITH_TORO)
ENDIF(NOT GTSAM_FOUND AND NOT G2O_FOUND AND NOT WITH_TORO AND NOT CERES_FOUND)
# vim: set et ft=cmake fenc=utf-8 ff=unix sts=0 sw=2 ts=2 :

View File

@@ -1,4 +1,4 @@
rtabmap ![Analytics](https://ga-beacon.appspot.com/UA-56986679-3/github-main?pixel)
rtabmap ![Analytics](https://ga-beacon-279122.nn.r.appspot.com/UA-56986679-3/github-main?pixel)
=======
[![RTAB-Map Logo](https://raw.githubusercontent.com/introlab/rtabmap/master/guilib/src/images/RTAB-Map100.png)](http://introlab.github.io/rtabmap)
@@ -7,7 +7,7 @@ rtabmap ![Analytics](https://ga-beacon.appspot.com/UA-56986679-3/github-main?pix
[![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.18.0-green.svg?style=flat
[release-image]: https://img.shields.io/badge/release-0.20.2-green.svg?style=flat
[releases]: https://github.com/introlab/rtabmap/releases
[license-image]: https://img.shields.io/badge/license-BSD-green.svg?style=flat

View File

@@ -74,7 +74,7 @@ if(@CONF_WITH_GUI@ AND ${WITH_GUI})
set(RTABMap_LIBRARIES ${RTABMap_LIBRARIES} ${RTABMap_GUI})
elseif(${WITH_GUI})
MESSAGE(ERROR "Asked for \"gui\" module but RTABMap hasn't been built with gui support.")
MESSAGE(WARNING "Asked for \"gui\" module but RTABMap hasn't been built with gui support.")
endif()
# Dependencies

View File

@@ -42,14 +42,16 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@G2O@#define RTABMAP_G2O
@G2O_CPP_CONF@#define RTABMAP_G2O_CPP11
@GTSAM@#define RTABMAP_GTSAM
@CERES@#define RTABMAP_CERES
@VERTIGO@#define RTABMAP_VERTIGO
@OPENCV3@#define RTABMAP_OPENCV3
@OPENNI2@#define RTABMAP_OPENNI2
@FREENECT@#define RTABMAP_FREENECT
@FREENECT2@#define RTABMAP_FREENECT2
@K4W2@#define RTABMAP_K4W2
@K4A@#define RTABMAP_K4A
@CVSBA@#define RTABMAP_CVSBA
@POINTMATCHER@#define RTABMAP_POINTMATCHER
@FASTCV@#define RTABMAP_FASTCV
@LOAM@#define RTABMAP_LOAM
@DC1394@#define RTABMAP_DC1394
@FLYCAPTURE2@#define RTABMAP_FLYCAPTURE2
@@ -57,8 +59,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@REALSENSE@#define RTABMAP_REALSENSE
@REALSENSESLAM@#define RTABMAP_REALSENSE_SLAM
@REALSENSE2@#define RTABMAP_REALSENSE2
@MYNTEYE@#define RTABMAP_MYNTEYE
@OCTOMAP@#define RTABMAP_OCTOMAP
@CPUTSDF@#define RTABMAP_CPUTSDF
@ALICE_VISION@#define RTABMAP_ALICE_VISION
@OPENCHISEL@#define RTABMAP_OPENCHISEL
@FOVIS@#define RTABMAP_FOVIS
@VISO2@#define RTABMAP_VISO2
@@ -68,8 +72,21 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@VINS@#define RTABMAP_VINS
@ORB_SLAM2@#define RTABMAP_ORB_SLAM2
@ORB_OCTREE@#define RTABMAP_ORB_OCTREE
@SUPERPOINT_TORCH@#define RTABMAP_SUPERPOINT_TORCH
@PYMATCHER@#define RTABMAP_PYMATCHER
@MADGWICK@#define RTABMAP_MADGWICK
#include <pcl/pcl_config.h>
#if PCL_VERSION_COMPARE(>, 1, 11, 1)
#include <pcl/types.h>
#define RTABMAP_PCL_INDEX pcl::index_t
#elif PCL_VERSION_COMPARE(>=, 1, 10, 0)
#define RTABMAP_PCL_INDEX std::uint32_t
#else
#include <pcl/pcl_macros.h>
#define RTABMAP_PCL_INDEX pcl::uint32_t
#endif
#endif /* VERSION_H_ */

View File

@@ -1 +1,2 @@
/bin/
/gen/

View File

@@ -8,8 +8,6 @@
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_FRAME_BUFFER" />
<uses-permission android:name="android.permission.ACCESS_SURFACE_FLINGER" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
@@ -17,8 +15,8 @@
<uses-feature android:name="android.hardware.location.gps" />
<uses-feature android:glEsVersion="0x00020000" />
<!-- This is the platform API where NativeActivity was introduced. -->
<uses-sdk android:minSdkVersion="19" />
<!-- This is the platform API where depth16 support in android was introduced. -->
<uses-sdk android:minSdkVersion="@ANDROID_NATIVE_API_LEVEL@" />
<!-- This .apk has no Java code itself, so set hasCode to false. -->
<application
@@ -26,7 +24,9 @@
android:icon="@drawable/ic_launcher"
android:debuggable="@ANDROID_DEBUGGABLE@">
<uses-library android:name="com.projecttango.libtango_device2" android:required="true" />
<uses-library android:name="com.projecttango.libtango_device2" android:required="false" />
<meta-data android:name="com.google.ar.core" android:value="optional" />
<meta-data android:name="com.huawei.ar.engine" android:value="optional" />
<!-- Our activity is the built-in NativeActivity framework class.
This will take care of integrating with our NDK code. -->
@@ -47,6 +47,27 @@
<activity android:name="SettingsActivity" android:label="@string/settings" android:screenOrientation="fullSensor"/>
<activity android:name="SketchfabActivity" android:label="@string/sketchfab" android:screenOrientation="fullSensor"/>
<meta-data
android:name="com.google.ar.core.min_apk_version"
android:value="191106000" /> <!-- This activity is critical for installing ARCore when it is not already present. -->
<activity
android:name="com.google.ar.core.InstallActivity"
android:configChanges="keyboardHidden|orientation|screenSize"
android:excludeFromRecents="true"
android:exported="false"
android:launchMode="singleTop"
android:theme="@android:style/Theme.Material.Light.Dialog.Alert" />
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.introlab.rtabmap.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths"/>
</provider>
</application>
</manifest>

View File

@@ -1,10 +1,95 @@
option(WITH_TANGO "Include Tango support" ON)
option(WITH_ARCORE "Include ARCore support" ON)
option(WITH_ARENGINE "Include AREngine support" ON)
option(DISABLE_LOG "Disable Android logging (should be true in release)" ON)
option(DEPTH_TEST "Enable depth test on ARCore" OFF)
# Google Tango needs access to system shared
# libraries (e.g. libbinder.so) that are not accessible
# with android >=24
IF(WITH_TANGO AND ${ANDROID_NATIVE_API_LEVEL} LESS 24)
FIND_PACKAGE(Tango QUIET)
IF(Tango_FOUND)
MESSAGE(STATUS "Found Tango: ${Tango_INCLUDE_DIRS}")
ENDIF(Tango_FOUND)
ENDIF(WITH_TANGO AND ${ANDROID_NATIVE_API_LEVEL} LESS 24)
IF(WITH_ARCORE AND ${ANDROID_NATIVE_API_LEVEL} GREATER 22)
FIND_PACKAGE(ARCore QUIET)
IF(ARCore_FOUND)
MESSAGE(STATUS "Found ARCore: ${ARCore_INCLUDE_DIRS}")
ENDIF(ARCore_FOUND)
ENDIF(WITH_ARCORE AND ${ANDROID_NATIVE_API_LEVEL} GREATER 22)
IF(WITH_ARENGINE AND ${ANDROID_NATIVE_API_LEVEL} GREATER 23)
FIND_PACKAGE(AREngine QUIET)
IF(AREngine_FOUND)
MESSAGE(STATUS "Found AREngine: ${AREngine_INCLUDE_DIRS}")
ENDIF(AREngine_FOUND)
ENDIF(WITH_ARENGINE AND ${ANDROID_NATIVE_API_LEVEL} GREATER 23)
IF(NOT Tango_FOUND)
SET(TANGO "//")
ENDIF(NOT Tango_FOUND)
IF(NOT ARCore_FOUND)
SET(ARCORE "//")
ENDIF(NOT ARCore_FOUND)
IF(NOT AREngine_FOUND)
SET(ARENGINE "//")
ENDIF(NOT AREngine_FOUND)
CONFIGURE_FILE(CameraAvailability.h.in ${CMAKE_CURRENT_SOURCE_DIR}/jni/CameraAvailability.h)
IF(DISABLE_LOG)
ADD_DEFINITIONS(-DDISABLE_LOG)
ENDIF(DISABLE_LOG)
IF(DEPTH_TEST)
ADD_DEFINITIONS(-DDEPTH_TEST)
ENDIF(DEPTH_TEST)
MESSAGE(STATUS "--------------------------------------------")
MESSAGE(STATUS "Android build info:")
MESSAGE(STATUS " DISABLE_LOG = ${DISABLE_LOG}")
MESSAGE(STATUS " DEPTH_TEST = ${DEPTH_TEST}")
IF(Tango_FOUND)
MESSAGE(STATUS " With Tango = YES")
ELSEIF(NOT WITH_TANGO)
MESSAGE(STATUS " With Tango = NO (WITH_TANGO=OFF)")
ELSE()
IF(${ANDROID_NATIVE_API_LEVEL} GREATER 23)
MESSAGE(STATUS " With Tango = NO (ANDROID_NATIVE_API_LEVEL should be <= 23)")
ELSE()
MESSAGE(STATUS " With Tango = NO (tango not found)")
ENDIF()
ENDIF()
IF(ARCore_FOUND)
MESSAGE(STATUS " With ARCore = YES")
ELSEIF(NOT WITH_ARCORE)
MESSAGE(STATUS " With ARCore = NO (WITH_ARCORE=OFF)")
ELSE()
IF(${ANDROID_NATIVE_API_LEVEL} LESS 23)
MESSAGE(STATUS " With ARCore = NO (ANDROID_NATIVE_API_LEVEL should be >= 23)")
ELSE()
MESSAGE(STATUS " With ARCore = NO (ARCore not found)")
ENDIF()
ENDIF()
IF(AREngine_FOUND)
MESSAGE(STATUS " With AREngine = YES")
ELSEIF(NOT WITH_ARENGINE)
MESSAGE(STATUS " With AREngine = NO (WITH_ARENGINE=OFF)")
ELSE()
IF(${ANDROID_NATIVE_API_LEVEL} LESS 24)
MESSAGE(STATUS " With AREngine = NO (ANDROID_NATIVE_API_LEVEL should be >= 24)")
ELSE()
MESSAGE(STATUS " With AREngine = NO (AREngine not found)")
ENDIF()
ENDIF()
MESSAGE(STATUS " ANDROID_NATIVE_API_LEVEL = ${ANDROID_NATIVE_API_LEVEL}")
MESSAGE(STATUS " ANDROID_COMPILER_FLAGS_RELEASE = ${ANDROID_COMPILER_FLAGS_RELEASE}")
MESSAGE(STATUS " ANDROID_TOOLCHAIN_PREFIX = ${ANDROID_TOOLCHAIN_PREFIX}")
MESSAGE(STATUS "DISABLE_LOG = ${DISABLE_LOG}")
IF(DISABLE_LOG)
SET(ANDROID_DEBUGGABLE false)
@@ -29,7 +114,8 @@ endif()
configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/AndroidManifest.xml.in"
"${CMAKE_CURRENT_SOURCE_DIR}/AndroidManifest.xml")
"${CMAKE_CURRENT_SOURCE_DIR}/AndroidManifest.xml"
@ONLY)
configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/AndroidManifest.xml"

View File

@@ -0,0 +1,39 @@
/*
Copyright (c) 2010-2014, 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 UNIVERTY DE SHERBROOKE 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 CAMERAAVAILABILITY_H_
#define CAMERAAVAILABILITY_H_
// This is auto-generated!
@TANGO@#define RTABMAP_TANGO
@ARCORE@#define RTABMAP_ARCORE
@ARENGINE@#define RTABMAP_ARENGINE
#endif /* CAMERAAVAILABILITY_H_ */

View File

@@ -6,8 +6,8 @@
<copy todir="${native.libs.dir}/${android.abi}">
<fileset dir="${srcdir}/jni/third-party/lib" includes="*.so"/>
</copy>
<copy todir="${native.libs.dir}">
<fileset dir="${srcdir}/jni/third-party/lib" includes="${android.abi}/*.so"/>
</copy>
<copy todir="${native.libs.dir}">
<fileset dir="${srcdir}/jni/third-party/lib" includes="${android.abi}/*.so"/>
</copy>
</target>
</project>

View File

@@ -1,7 +1,7 @@
<h3>Real-Time Appearance-Based Mapping</h3>
Version @RTABMAP_VERSION@<br>
Author: Mathieu Labb&eacute;<br>
Copyright 2016-2018<br>
Copyright 2016-2020<br>
IntRoLab - Universit&eacute; de Sherbrooke<br>
<b>http://introlab.github.io/rtabmap</b><br><br>

1
app/android/jni/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
CameraAvailability.h

View File

@@ -1,6 +1,4 @@
find_package(Tango REQUIRED)
SET(INCLUDE_DIRS
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/tango-gl/include
@@ -9,27 +7,22 @@ SET(INCLUDE_DIRS
${PROJECT_SOURCE_DIR}/utilite/include
${OpenCV_INCLUDE_DIRS}
${PCL_INCLUDE_DIRS}
${Tango_INCLUDE_DIRS}
"${ANDROID_NDK}/platforms/android-${ANDROID_NATIVE_API_LEVEL}/arch-${ANDROID_ARCH_NAME}/usr/include"
)
SET(LIBRARIES
${OpenCV_LIBRARIES}
${PCL_LIBRARIES}
${Tango_LIBRARIES}
)
add_definitions(${PCL_DEFINITIONS})
INCLUDE_DIRECTORIES(${INCLUDE_DIRS})
set(sources
jni_interface.cpp
CameraTango.cpp
CameraMobile.cpp
RTABMapApp.cpp
scene.cpp
point_cloud_drawable.cpp
graph_drawable.cpp
background_renderer.cc
tango-gl/axis.cpp
tango-gl/camera.cpp
tango-gl/conversions.cpp
@@ -44,6 +37,82 @@ set(sources
tango-gl/util.cpp
)
IF(OPENMP_FOUND)
file(COPY ${OpenMP_CXX_LIBRARIES}
DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/../libs/${ANDROID_NDK_ABI_NAME})
ENDIF(OPENMP_FOUND)
IF(Tango_FOUND)
SET(sources
${sources}
CameraTango.cpp
)
SET(INCLUDE_DIRS
${INCLUDE_DIRS}
${Tango_INCLUDE_DIRS}
)
SET(LIBRARIES
${LIBRARIES}
${Tango_LIBRARIES}
)
file(COPY ${Tango_support_LIBRARY}
DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/../libs/${ANDROID_NDK_ABI_NAME})
ENDIF(Tango_FOUND)
IF(ARCore_FOUND)
SET(sources
${sources}
CameraARCore.cpp
)
SET(INCLUDE_DIRS
${INCLUDE_DIRS}
${ARCore_INCLUDE_DIRS}
)
SET(LIBRARIES
${LIBRARIES}
${ARCore_LIBRARIES}
)
file(COPY ${ARCore_c_LIBRARY}
DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/../libs/${ANDROID_NDK_ABI_NAME})
file(COPY ${ARCore_jni_LIBRARY}
DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/../libs/${ANDROID_NDK_ABI_NAME})
ENDIF(ARCore_FOUND)
IF(AREngine_FOUND)
SET(sources
${sources}
CameraAREngine.cpp
)
SET(INCLUDE_DIRS
${INCLUDE_DIRS}
${AREngine_INCLUDE_DIRS}
)
SET(LIBRARIES
${LIBRARIES}
${AREngine_LIBRARIES}
camera2ndk
mediandk
)
file(COPY ${AREngine_impl_LIBRARY}
DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/../libs/${ANDROID_NDK_ABI_NAME})
file(COPY ${AREngine_jni_LIBRARY}
DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/../libs/${ANDROID_NDK_ABI_NAME})
file(COPY ${AREngine_ndk_LIBRARY}
DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/../libs/${ANDROID_NDK_ABI_NAME})
ENDIF(AREngine_FOUND)
add_definitions(${PCL_DEFINITIONS})
INCLUDE_DIRECTORIES(${INCLUDE_DIRS})
add_library(NativeRTABMap SHARED ${sources})
target_link_libraries(NativeRTABMap ${LIBRARIES}
android
@@ -58,3 +127,10 @@ set_target_properties(NativeRTABMap PROPERTIES
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/../libs/${ANDROID_NDK_ABI_NAME}"
LIBRARY_OUTPUT_DIRECTORY_DEBUG "${CMAKE_CURRENT_BINARY_DIR}/../libs/${ANDROID_NDK_ABI_NAME}"
LIBRARY_OUTPUT_DIRECTORY_RELEASE "${CMAKE_CURRENT_BINARY_DIR}/../libs/${ANDROID_NDK_ABI_NAME}")
IF(ANDROID_NATIVE_API_LEVEL GREATER 22)
add_custom_command(TARGET NativeRTABMap POST_BUILD
COMMAND "${ANDROID_TOOLCHAIN_PREFIX}strip" -g -S -d --strip-debug --verbose
"${CMAKE_CURRENT_BINARY_DIR}/../libs/${ANDROID_NDK_ABI_NAME}/libNativeRTABMap.so"
COMMENT "Strip debug symbols done on final binary.")
ENDIF(ANDROID_NATIVE_API_LEVEL GREATER 22)

View File

@@ -0,0 +1,688 @@
/*
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 "CameraARCore.h"
#include "util.h"
#include "rtabmap/utilite/ULogger.h"
#include "rtabmap/core/util3d_transforms.h"
#include "rtabmap/core/OdometryEvent.h"
#include "rtabmap/core/util2d.h"
namespace rtabmap {
//////////////////////////////
// CameraARCore
//////////////////////////////
CameraARCore::CameraARCore(void* env, void* context, void* activity, bool depthFromMotion, bool smoothing):
CameraMobile(smoothing),
env_(env),
context_(context),
activity_(activity),
arInstallRequested_(false),
textureId_(9999),
uvs_initialized_(false),
updateOcclusionImage_(false),
depthFromMotion_(depthFromMotion)
{
}
CameraARCore::~CameraARCore() {
// Disconnect ARCore service
close();
if(textureId_ != 9999)
{
glDeleteTextures(1, &textureId_);
textureId_ = 9999;
}
}
struct CameraConfig {
int32_t width = 0;
int32_t height = 0;
std::string config_label;
ArCameraConfig* config = nullptr;
};
void getCameraConfigLowestAndHighestResolutions(
std::vector<CameraConfig> & camera_configs,
CameraConfig** lowest_resolution_config,
CameraConfig** highest_resolution_config) {
if (camera_configs.empty()) {
return;
}
int low_resolution_config_idx = 0;
int high_resolution_config_idx = 0;
int32_t smallest_height = camera_configs[0].height;
int32_t largest_height = camera_configs[0].height;
for (int i = 1; i < camera_configs.size(); ++i) {
int32_t image_height = camera_configs[i].height;
if (image_height < smallest_height) {
smallest_height = image_height;
low_resolution_config_idx = i;
} else if (image_height > largest_height) {
largest_height = image_height;
high_resolution_config_idx = i;
}
}
if (low_resolution_config_idx == high_resolution_config_idx) {
*lowest_resolution_config = &camera_configs[low_resolution_config_idx];
} else {
*lowest_resolution_config = &camera_configs[low_resolution_config_idx];
*highest_resolution_config = &camera_configs[high_resolution_config_idx];
}
}
void copyCameraConfig(
const ArSession* ar_session, const ArCameraConfigList* all_configs,
int index, int num_configs, CameraConfig* camera_config) {
if (camera_config != nullptr && index >= 0 && index < num_configs) {
ArCameraConfig_create(ar_session, &camera_config->config);
ArCameraConfigList_getItem(ar_session, all_configs, index,
camera_config->config);
ArCameraConfig_getImageDimensions(ar_session, camera_config->config,
&camera_config->width,
&camera_config->height);
camera_config->config_label = "(" + std::to_string(camera_config->width) +
"x" + std::to_string(camera_config->height) +
")";
}
}
void destroyCameraConfigs(std::vector<CameraConfig> & camera_configs) {
for (int i = 0; i < camera_configs.size(); ++i) {
if (camera_configs[i].config != nullptr) {
ArCameraConfig_destroy(camera_configs[i].config);
}
}
}
std::string CameraARCore::getSerial() const
{
return "ARCore";
}
bool CameraARCore::init(const std::string & calibrationFolder, const std::string & cameraName)
{
close();
UScopeMutex lock(arSessionMutex_);
ArInstallStatus install_status;
// If install was not yet requested, that means that we are resuming the
// activity first time because of explicit user interaction (such as
// launching the application)
bool user_requested_install = !arInstallRequested_;
// === ATTENTION! ATTENTION! ATTENTION! ===
// This method can and will fail in user-facing situations. Your
// application must handle these cases at least somewhat gracefully. See
// HelloAR Java sample code for reasonable behavior.
ArCoreApk_requestInstall(env_, activity_, user_requested_install, &install_status);
switch (install_status)
{
case AR_INSTALL_STATUS_INSTALLED:
break;
case AR_INSTALL_STATUS_INSTALL_REQUESTED:
arInstallRequested_ = true;
return false;
}
// === ATTENTION! ATTENTION! ATTENTION! ===
// This method can and will fail in user-facing situations. Your
// application must handle these cases at least somewhat gracefully. See
// HelloAR Java sample code for reasonable behavior.
UASSERT(ArSession_create(env_, context_, &arSession_) == AR_SUCCESS);
UASSERT(arSession_);
int32_t is_depth_supported = 0;
ArSession_isDepthModeSupported(arSession_, AR_DEPTH_MODE_AUTOMATIC, &is_depth_supported);
ArConfig_create(arSession_, &arConfig_);
UASSERT(arConfig_);
if (is_depth_supported!=0) {
ArConfig_setDepthMode(arSession_, arConfig_, AR_DEPTH_MODE_AUTOMATIC);
} else {
ArConfig_setDepthMode(arSession_, arConfig_, AR_DEPTH_MODE_DISABLED);
}
ArConfig_setFocusMode(arSession_, arConfig_, AR_FOCUS_MODE_AUTO);
UASSERT(ArSession_configure(arSession_, arConfig_) == AR_SUCCESS);
ArFrame_create(arSession_, &arFrame_);
UASSERT(arFrame_);
ArCameraIntrinsics_create(arSession_, &arCameraIntrinsics_);
UASSERT(arCameraIntrinsics_);
ArPose_create(arSession_, nullptr, &arPose_);
UASSERT(arPose_);
ArCameraConfigList* all_camera_configs = nullptr;
int32_t num_configs = 0;
ArCameraConfigList_create(arSession_, &all_camera_configs);
// Create filter first to get both 30 and 60 fps.
ArCameraConfigFilter* camera_config_filter = nullptr;
ArCameraConfigFilter_create(arSession_, &camera_config_filter);
ArCameraConfigFilter_setTargetFps(arSession_, camera_config_filter, AR_CAMERA_CONFIG_TARGET_FPS_30 | AR_CAMERA_CONFIG_TARGET_FPS_60);
ArSession_getSupportedCameraConfigsWithFilter(arSession_, camera_config_filter, all_camera_configs);
ArCameraConfigList_getSize(arSession_, all_camera_configs, &num_configs);
if (num_configs < 1) {
UERROR("No camera config found");
close();
return false;
}
std::vector<CameraConfig> camera_configs;
CameraConfig* cpu_low_resolution_camera_config_ptr = nullptr;
CameraConfig* cpu_high_resolution_camera_config_ptr = nullptr;
camera_configs.resize(num_configs);
for (int i = 0; i < num_configs; ++i) {
copyCameraConfig(arSession_, all_camera_configs, i, num_configs,
&camera_configs[i]);
}
// Determine the highest and lowest CPU resolutions.
cpu_low_resolution_camera_config_ptr = nullptr;
cpu_high_resolution_camera_config_ptr = nullptr;
getCameraConfigLowestAndHighestResolutions(
camera_configs,
&cpu_low_resolution_camera_config_ptr,
&cpu_high_resolution_camera_config_ptr);
// Cleanup the list obtained as it is safe to destroy the list as camera
// config instances were explicitly created and copied. Refer to the
// previous comment.
ArCameraConfigList_destroy(all_camera_configs);
ArSession_setCameraConfig(arSession_, cpu_low_resolution_camera_config_ptr->config);
/// Sets the behavior of @ref ArSession_update(). See
/// ::ArUpdateMode for available options.
ArConfig_setUpdateMode(arSession_, arConfig_, AR_UPDATE_MODE_BLOCKING);
deviceTColorCamera_ = opticalRotation;
if (ArSession_resume(arSession_) != ArStatus::AR_SUCCESS)
{
UERROR("Cannot resume camera!");
// In a rare case (such as another camera app launching) the camera may be
// given to a different app and so may not be available to this app. Handle
// this properly and recreate the session at the next iteration.
close();
return false;
}
return true;
}
void CameraARCore::close()
{
UScopeMutex lock(arSessionMutex_);
if(arSession_!= nullptr)
{
ArSession_destroy(arSession_);
}
arSession_ = nullptr;
if(arConfig_!= nullptr)
{
ArConfig_destroy(arConfig_);
}
arConfig_ = nullptr;
if (arFrame_ != nullptr)
{
ArFrame_destroy(arFrame_);
}
arFrame_ = nullptr;
if (arCameraIntrinsics_ != nullptr)
{
ArCameraIntrinsics_destroy(arCameraIntrinsics_);
}
arCameraIntrinsics_ = nullptr;
if (arPose_ != nullptr)
{
ArPose_destroy(arPose_);
}
arPose_ = nullptr;
CameraMobile::close();
occlusionImage_ = cv::Mat();
}
LaserScan CameraARCore::scanFromPointCloudData(
const float * pointCloudData,
int points,
const Transform & pose,
const CameraModel & model,
const cv::Mat & rgb,
std::vector<cv::KeyPoint> * kpts,
std::vector<cv::Point3f> * kpts3D)
{
if(pointCloudData && points>0)
{
cv::Mat scanData(1, points, CV_32FC4);
float * ptr = scanData.ptr<float>();
for(unsigned int i=0;i<points; ++i)
{
cv::Point3f pt(pointCloudData[i*4], pointCloudData[i*4 + 1], pointCloudData[i*4 + 2]);
pt = util3d::transformPoint(pt, pose.inverse()*rtabmap_world_T_opengl_world);
ptr[i*4] = pt.x;
ptr[i*4 + 1] = pt.y;
ptr[i*4 + 2] = pt.z;
//get color from rgb image
cv::Point3f org= pt;
pt = util3d::transformPoint(pt, opticalRotationInv);
int u,v;
model.reproject(pt.x, pt.y, pt.z, u, v);
unsigned char r=255,g=255,b=255;
if(model.inFrame(u, v))
{
b=rgb.at<cv::Vec3b>(v,u).val[0];
g=rgb.at<cv::Vec3b>(v,u).val[1];
r=rgb.at<cv::Vec3b>(v,u).val[2];
if(kpts)
kpts->push_back(cv::KeyPoint(u,v,3));
if(kpts3D)
kpts3D->push_back(org);
}
*(int*)&ptr[i*4 + 3] = int(b) | (int(g) << 8) | (int(r) << 16);
//confidence
//*(int*)&ptr[i*4 + 3] = (int(pointCloudData[i*4 + 3] * 255.0f) << 8) | (int(255) << 16);
}
return LaserScan::backwardCompatibility(scanData, 0, 10, rtabmap::Transform::getIdentity());
}
return LaserScan();
}
void CameraARCore::setScreenRotationAndSize(ScreenRotation colorCameraToDisplayRotation, int width, int height)
{
CameraMobile::setScreenRotationAndSize(colorCameraToDisplayRotation, width, height);
if(arSession_)
{
int ret = static_cast<int>(colorCameraToDisplayRotation) + 1; // remove 90deg camera rotation
if (ret > 3) {
ret -= 4;
}
ArSession_setDisplayGeometry(arSession_, ret, width, height);
}
}
SensorData CameraARCore::captureImage(CameraInfo * info)
{
UScopeMutex lock(arSessionMutex_);
//LOGI("Capturing image...");
SensorData data;
if(!arSession_)
{
return data;
}
if(textureId_ == 9999)
{
glGenTextures(1, &textureId_);
glBindTexture(GL_TEXTURE_EXTERNAL_OES, textureId_);
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
}
ArSession_setCameraTextureName(arSession_, textureId_);
// Update session to get current frame and render camera background.
if (ArSession_update(arSession_, arFrame_) != AR_SUCCESS) {
LOGE("CameraARCore::captureImage() ArSession_update error");
return data;
}
// If display rotation changed (also includes view size change), we need to
// re-query the uv coordinates for the on-screen portion of the camera image.
int32_t geometry_changed = 0;
ArFrame_getDisplayGeometryChanged(arSession_, arFrame_, &geometry_changed);
if (geometry_changed != 0 || !uvs_initialized_) {
ArFrame_transformCoordinates2d(
arSession_, arFrame_, AR_COORDINATES_2D_OPENGL_NORMALIZED_DEVICE_COORDINATES,
BackgroundRenderer::kNumVertices, BackgroundRenderer_kVertices, AR_COORDINATES_2D_TEXTURE_NORMALIZED,
transformed_uvs_);
UASSERT(transformed_uvs_);
uvs_initialized_ = true;
}
ArCamera* ar_camera;
ArFrame_acquireCamera(arSession_, arFrame_, &ar_camera);
ArCamera_getViewMatrix(arSession_, ar_camera, glm::value_ptr(viewMatrix_));
ArCamera_getProjectionMatrix(arSession_, ar_camera,
/*near=*/0.1f, /*far=*/100.f,
glm::value_ptr(projectionMatrix_));
ArTrackingState camera_tracking_state;
ArCamera_getTrackingState(arSession_, ar_camera, &camera_tracking_state);
Transform pose;
CameraModel model;
if(camera_tracking_state == AR_TRACKING_STATE_TRACKING)
{
// pose in OpenGL coordinates
float pose_raw[7];
ArCamera_getPose(arSession_, ar_camera, arPose_);
ArPose_getPoseRaw(arSession_, arPose_, pose_raw);
pose = Transform(pose_raw[4], pose_raw[5], pose_raw[6], pose_raw[0], pose_raw[1], pose_raw[2], pose_raw[3]);
pose = rtabmap::rtabmap_world_T_opengl_world * pose * rtabmap::opengl_world_T_rtabmap_world;
// Get calibration parameters
float fx,fy, cx, cy;
int32_t width, height;
ArCamera_getImageIntrinsics(arSession_, ar_camera, arCameraIntrinsics_);
ArCameraIntrinsics_getFocalLength(arSession_, arCameraIntrinsics_, &fx, &fy);
ArCameraIntrinsics_getPrincipalPoint(arSession_, arCameraIntrinsics_, &cx, &cy);
ArCameraIntrinsics_getImageDimensions(arSession_, arCameraIntrinsics_, &width, &height);
#ifndef DISABLE_LOG
LOGI("%f %f %f %f %d %d", fx, fy, cx, cy, width, height);
#endif
if(fx > 0 && fy > 0 && width > 0 && height > 0 && cx > 0 && cy > 0)
{
model = CameraModel(fx, fy, cx, cy, deviceTColorCamera_, 0, cv::Size(width, height));
ArPointCloud * pointCloud = nullptr;
ArFrame_acquirePointCloud(arSession_, arFrame_, &pointCloud);
int32_t is_depth_supported = 0;
ArSession_isDepthModeSupported(arSession_, AR_DEPTH_MODE_AUTOMATIC, &is_depth_supported);
ArImage * image = nullptr;
ArStatus status = ArFrame_acquireCameraImage(arSession_, arFrame_, &image);
if(status == AR_SUCCESS)
{
if(is_depth_supported && (updateOcclusionImage_||depthFromMotion_))
{
LOGD("Acquire depth image!");
ArImage * depthImage = nullptr;
ArFrame_acquireDepthImage(arSession_, arFrame_, &depthImage);
ArImageFormat format;
ArImage_getFormat(arSession_, depthImage, &format);
if(format == AR_IMAGE_FORMAT_DEPTH16)
{
LOGD("Depth format detected!");
int planeCount;
ArImage_getNumberOfPlanes(arSession_, depthImage, &planeCount);
LOGD("planeCount=%d", planeCount);
UASSERT_MSG(planeCount == 1, uFormat("Error: getNumberOfPlanes() planceCount = %d", planeCount).c_str());
const uint8_t *data = nullptr;
int len = 0;
int stride;
int depth_width;
int depth_height;
ArImage_getWidth(arSession_, depthImage, &depth_width);
ArImage_getHeight(arSession_, depthImage, &depth_height);
ArImage_getPlaneRowStride(arSession_, depthImage, 0, &stride);
ArImage_getPlaneData(arSession_, depthImage, 0, &data, &len);
LOGD("width=%d, height=%d, bytes=%d stride=%d", depth_width, depth_height, len, stride);
occlusionImage_ = cv::Mat(depth_height, depth_width, CV_16UC1, (void*)data).clone();
float scaleX = (float)depth_width / (float)width;
float scaleY = (float)depth_height / (float)height;
occlusionModel_ = CameraModel(fx*scaleX, fy*scaleY, cx*scaleX, cy*scaleY, pose*deviceTColorCamera_, 0, cv::Size(depth_width, depth_height));
}
ArImage_release(depthImage);
}
int64_t timestamp_ns;
ArImageFormat format;
ArImage_getTimestamp(arSession_, image, &timestamp_ns);
ArImage_getFormat(arSession_, image, &format);
if(format == AR_IMAGE_FORMAT_YUV_420_888)
{
#ifndef DISABLE_LOG
int32_t num_planes;
ArImage_getNumberOfPlanes(arSession_, image, &num_planes);
for(int i=0;i<num_planes; ++i)
{
int32_t pixel_stride;
int32_t row_stride;
ArImage_getPlanePixelStride(arSession_, image, i, &pixel_stride);
ArImage_getPlaneRowStride(arSession_, image, i, &row_stride);
LOGI("Plane %d/%d: pixel stride=%d, row stride=%d", i+1, num_planes, pixel_stride, row_stride);
}
#endif
const uint8_t * plane_data;
const uint8_t * plane_uv_data;
int32_t data_length;
ArImage_getPlaneData(arSession_, image, 0, &plane_data, &data_length);
int32_t uv_data_length;
ArImage_getPlaneData(arSession_, image, 2, &plane_uv_data, &uv_data_length);
if(plane_data != nullptr && data_length == height*width)
{
double stamp = double(timestamp_ns)/10e8;
#ifndef DISABLE_LOG
LOGI("data_length=%d stamp=%f", data_length, stamp);
#endif
cv::Mat rgb;
if((long)plane_uv_data-(long)plane_data != data_length)
{
// The uv-plane is not concatenated to y plane in memory, so concatenate them
cv::Mat yuv(height+height/2, width, CV_8UC1);
memcpy(yuv.data, plane_data, data_length);
memcpy(yuv.data+data_length, plane_uv_data, height/2*width);
cv::cvtColor(yuv, rgb, CV_YUV2BGR_NV21);
}
else
{
cv::cvtColor(cv::Mat(height+height/2, width, CV_8UC1, (void*)plane_data), rgb, CV_YUV2BGR_NV21);
}
std::vector<cv::KeyPoint> kpts;
std::vector<cv::Point3f> kpts3;
LaserScan scan;
if(pointCloud)
{
int32_t points = 0;
ArPointCloud_getNumberOfPoints(arSession_, pointCloud, &points);
const float * pointCloudData = 0;
ArPointCloud_getData(arSession_, pointCloud, &pointCloudData);
#ifndef DISABLE_LOG
LOGI("pointCloudData=%d size=%d", pointCloudData?1:0, points);
#endif
if(pointCloudData && points>0)
{
scan = scanFromPointCloudData(pointCloudData, points, pose, model, rgb, &kpts, &kpts3);
}
}
else
{
LOGI("pointCloud empty");
}
data = SensorData(scan, rgb, depthFromMotion_?occlusionImage_:cv::Mat(), model, 0, stamp);
data.setFeatures(kpts, kpts3, cv::Mat());
}
}
else
{
LOGE("CameraARCore: cannot convert image format %d", format);
}
}
else
{
LOGE("CameraARCore: failed to get rgb image (status=%d)", (int)status);
}
ArImage_release(image);
ArPointCloud_release(pointCloud);
}
}
ArCamera_release(ar_camera);
if(pose.isNull())
{
LOGE("CameraARCore: Pose is null");
}
else
{
this->poseReceived(pose);
info->odomPose = pose;
}
return data;
}
void CameraARCore::capturePoseOnly()
{
UScopeMutex lock(arSessionMutex_);
//LOGI("Capturing image...");
if(!arSession_)
{
return;
}
if(textureId_ == 9999)
{
glGenTextures(1, &textureId_);
glBindTexture(GL_TEXTURE_EXTERNAL_OES, textureId_);
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
}
ArSession_setCameraTextureName(arSession_, textureId_);
// Update session to get current frame and render camera background.
if (ArSession_update(arSession_, arFrame_) != AR_SUCCESS) {
LOGE("CameraARCore::capturePoseOnly() ArSession_update error");
return;
}
// If display rotation changed (also includes view size change), we need to
// re-query the uv coordinates for the on-screen portion of the camera image.
int32_t geometry_changed = 0;
ArFrame_getDisplayGeometryChanged(arSession_, arFrame_, &geometry_changed);
if (geometry_changed != 0 || !uvs_initialized_) {
ArFrame_transformCoordinates2d(
arSession_, arFrame_, AR_COORDINATES_2D_OPENGL_NORMALIZED_DEVICE_COORDINATES,
BackgroundRenderer::kNumVertices, BackgroundRenderer_kVertices, AR_COORDINATES_2D_TEXTURE_NORMALIZED,
transformed_uvs_);
UASSERT(transformed_uvs_);
uvs_initialized_ = true;
}
ArCamera* ar_camera;
ArFrame_acquireCamera(arSession_, arFrame_, &ar_camera);
ArCamera_getViewMatrix(arSession_, ar_camera, glm::value_ptr(viewMatrix_));
ArCamera_getProjectionMatrix(arSession_, ar_camera,
/*near=*/0.1f, /*far=*/100.f,
glm::value_ptr(projectionMatrix_));
ArTrackingState camera_tracking_state;
ArCamera_getTrackingState(arSession_, ar_camera, &camera_tracking_state);
Transform pose;
CameraModel model;
if(camera_tracking_state == AR_TRACKING_STATE_TRACKING)
{
// pose in OpenGL coordinates
float pose_raw[7];
ArCamera_getPose(arSession_, ar_camera, arPose_);
ArPose_getPoseRaw(arSession_, arPose_, pose_raw);
pose = Transform(pose_raw[4], pose_raw[5], pose_raw[6], pose_raw[0], pose_raw[1], pose_raw[2], pose_raw[3]);
if(!pose.isNull())
{
pose = rtabmap::rtabmap_world_T_opengl_world * pose * rtabmap::opengl_world_T_rtabmap_world;
this->poseReceived(pose);
}
int32_t is_depth_supported = 0;
ArSession_isDepthModeSupported(arSession_, AR_DEPTH_MODE_AUTOMATIC, &is_depth_supported);
if(is_depth_supported && updateOcclusionImage_)
{
LOGD("Acquire depth image!");
ArImage * depthImage = nullptr;
ArFrame_acquireDepthImage(arSession_, arFrame_, &depthImage);
ArImageFormat format;
ArImage_getFormat(arSession_, depthImage, &format);
if(format == AR_IMAGE_FORMAT_DEPTH16)
{
LOGD("Depth format detected!");
int planeCount;
ArImage_getNumberOfPlanes(arSession_, depthImage, &planeCount);
LOGD("planeCount=%d", planeCount);
UASSERT_MSG(planeCount == 1, uFormat("Error: getNumberOfPlanes() planceCount = %d", planeCount).c_str());
const uint8_t *data = nullptr;
int len = 0;
int stride;
int width;
int height;
ArImage_getWidth(arSession_, depthImage, &width);
ArImage_getHeight(arSession_, depthImage, &height);
ArImage_getPlaneRowStride(arSession_, depthImage, 0, &stride);
ArImage_getPlaneData(arSession_, depthImage, 0, &data, &len);
LOGD("width=%d, height=%d, bytes=%d stride=%d", width, height, len, stride);
occlusionImage_ = cv::Mat(height, width, CV_16UC1, (void*)data).clone();
float fx,fy, cx, cy;
int32_t rgb_width, rgb_height;
ArCamera_getImageIntrinsics(arSession_, ar_camera, arCameraIntrinsics_);
ArCameraIntrinsics_getFocalLength(arSession_, arCameraIntrinsics_, &fx, &fy);
ArCameraIntrinsics_getPrincipalPoint(arSession_, arCameraIntrinsics_, &cx, &cy);
ArCameraIntrinsics_getImageDimensions(arSession_, arCameraIntrinsics_, &rgb_width, &rgb_height);
float scaleX = (float)width / (float)rgb_width;
float scaleY = (float)height / (float)rgb_height;
occlusionModel_ = CameraModel(fx*scaleX, fy*scaleY, cx*scaleX, cy*scaleY, pose*deviceTColorCamera_, 0, cv::Size(width, height));
}
ArImage_release(depthImage);
}
}
ArCamera_release(ar_camera);
}
} /* namespace rtabmap */

View File

@@ -0,0 +1,115 @@
/*
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 CAMERAARCORE_H_
#define CAMERAARCORE_H_
#include "CameraMobile.h"
#include <rtabmap/core/Camera.h>
#include <rtabmap/core/GeodeticCoords.h>
#include <rtabmap/utilite/UMutex.h>
#include <rtabmap/utilite/USemaphore.h>
#include <rtabmap/utilite/UEventsSender.h>
#include <rtabmap/utilite/UThread.h>
#include <rtabmap/utilite/UEvent.h>
#include <rtabmap/utilite/UTimer.h>
#include <boost/thread/mutex.hpp>
#include <background_renderer.h>
#include <arcore_c_api.h>
#include <camera/NdkCameraDevice.h>
#include <camera/NdkCameraManager.h>
#include <media/NdkImageReader.h>
#include <android/native_window.h>
namespace rtabmap {
class CameraARCore : public CameraMobile {
public:
static LaserScan scanFromPointCloudData(
const float * pointCloudData,
int points,
const Transform & pose,
const CameraModel & model,
const cv::Mat & rgb,
std::vector<cv::KeyPoint> * kpts = 0,
std::vector<cv::Point3f> * kpts3D = 0);
public:
CameraARCore(void* env, void* context, void* activity, bool depthFromMotion = false, bool smoothing = false);
virtual ~CameraARCore();
bool uvsInitialized() const {return uvs_initialized_;}
const float* uvsTransformed() const {return transformed_uvs_;}
void getVPMatrices(glm::mat4 & view, glm::mat4 & projection) const {view=viewMatrix_; projection=projectionMatrix_;}
void updateOcclusionImage(bool enabled) {updateOcclusionImage_ = enabled;}
const cv::Mat & getOcclusionImage(CameraModel * model=0) const {if(model)*model=occlusionModel_; return occlusionImage_; }
virtual void setScreenRotationAndSize(ScreenRotation colorCameraToDisplayRotation, int width, int height);
virtual bool init(const std::string & calibrationFolder = ".", const std::string & cameraName = "");
void setupGL();
virtual void close(); // close Tango connection
virtual std::string getSerial() const;
GLuint getTextureId() const {return textureId_;}
void imageCallback(AImageReader *reader);
protected:
virtual SensorData captureImage(CameraInfo * info = 0); // should be called in opengl thread
virtual void capturePoseOnly();
private:
rtabmap::Transform getPoseAtTimestamp(double timestamp);
private:
void * env_;
void * context_;
void * activity_;
ArSession* arSession_ = nullptr;
ArConfig* arConfig_ = nullptr;
ArFrame* arFrame_ = nullptr;
ArCameraIntrinsics *arCameraIntrinsics_ = nullptr;
ArPose * arPose_ = nullptr;
bool arInstallRequested_;
GLuint textureId_;
UMutex arSessionMutex_;
float transformed_uvs_[BackgroundRenderer::kNumVertices*2];
bool uvs_initialized_ = false;
glm::mat4 viewMatrix_;
glm::mat4 projectionMatrix_;
bool updateOcclusionImage_;
cv::Mat occlusionImage_;
CameraModel occlusionModel_;
bool depthFromMotion_;
};
} /* namespace rtabmap */
#endif /* CAMERAARCORE_H_ */

View File

@@ -0,0 +1,351 @@
/*
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 "CameraAREngine.h"
#include "util.h"
#include "rtabmap/utilite/ULogger.h"
#include "rtabmap/core/util3d_transforms.h"
#include "rtabmap/core/OdometryEvent.h"
#include "rtabmap/core/util2d.h"
#include <media/NdkImage.h>
namespace rtabmap {
//////////////////////////////
// CameraAREngine
//////////////////////////////
CameraAREngine::CameraAREngine(void* env, void* context, void* activity, bool smoothing):
CameraMobile(smoothing),
env_(env),
context_(context),
activity_(activity),
arInstallRequested_(false)
{
glGenTextures(1, &textureId_);
}
CameraAREngine::~CameraAREngine() {
// Disconnect ARCore service
close();
glDeleteTextures(1, &textureId_);
}
std::string CameraAREngine::getSerial() const
{
return "AREngine";
}
bool CameraAREngine::init(const std::string & calibrationFolder, const std::string & cameraName)
{
close();
UScopeMutex lock(arSessionMutex_);
HwArInstallStatus install_status;
// If install was not yet requested, that means that we are resuming the
// activity first time because of explicit user interaction (such as
// launching the application)
bool user_requested_install = !arInstallRequested_;
// === ATTENTION! ATTENTION! ATTENTION! ===
// This method can and will fail in user-facing situations. Your
// application must handle these cases at least somewhat gracefully. See
// HelloAR Java sample code for reasonable behavior.
HwArEnginesApk_requestInstall(env_, activity_, user_requested_install, &install_status);
switch (install_status)
{
case HWAR_INSTALL_STATUS_INSTALLED:
break;
case HWAR_INSTALL_STATUS_INSTALL_REQUESTED:
arInstallRequested_ = true;
return false;
}
// === ATTENTION! ATTENTION! ATTENTION! ===
// This method can and will fail in user-facing situations. Your
// application must handle these cases at least somewhat gracefully. See
// HelloAR Java sample code for reasonable behavior.
UASSERT(HwArSession_create(env_, context_, &arSession_) == HWAR_SUCCESS);
UASSERT(arSession_);
HwArConfig_create(arSession_, &arConfig_);
UASSERT(arConfig_);
HwArConfig_setFocusMode(arSession_, arConfig_, HWAR_FOCUS_MODE_FIXED);
UASSERT(HwArSession_configure(arSession_, arConfig_) == HWAR_SUCCESS);
HwArFrame_create(arSession_, &arFrame_);
UASSERT(arFrame_);
HwArCameraIntrinsics_create(arSession_, &arCameraIntrinsics_); // May fail?!
//UASSERT(arCameraIntrinsics_);
HwArPose_create(arSession_, nullptr, &arPose_);
UASSERT(arPose_);
/// Sets the behavior of @ref ArSession_update(). See
/// ::ArUpdateMode for available options.
HwArConfig_setUpdateMode(arSession_, arConfig_, HWAR_UPDATE_MODE_BLOCKING);
deviceTColorCamera_ = opticalRotation;
// Required as ArSession_update does some off-screen OpenGL stuff...
HwArSession_setCameraTextureName(arSession_, textureId_);
if (HwArSession_resume(arSession_) != HWAR_SUCCESS)
{
UERROR("Cannot resume camera!");
// In a rare case (such as another camera app launching) the camera may be
// given to a different app and so may not be available to this app. Handle
// this properly and recreate the session at the next iteration.
close();
return false;
}
return true;
}
void CameraAREngine::close()
{
UScopeMutex lock(arSessionMutex_);
if (arCameraIntrinsics_ != nullptr)
{
HwArCameraIntrinsics_destroy(arSession_, arCameraIntrinsics_);
}
arCameraIntrinsics_ = nullptr;
if(arSession_!= nullptr)
{
HwArSession_destroy(arSession_);
}
arSession_ = nullptr;
if(arConfig_!= nullptr)
{
HwArConfig_destroy(arConfig_);
}
arConfig_ = nullptr;
if (arFrame_ != nullptr)
{
HwArFrame_destroy(arFrame_);
}
arFrame_ = nullptr;
if (arPose_ != nullptr)
{
HwArPose_destroy(arPose_);
}
arPose_ = nullptr;
CameraMobile::close();
}
SensorData CameraAREngine::captureImage(CameraInfo * info)
{
UScopeMutex lock(arSessionMutex_);
//LOGI("Capturing image...");
SensorData data;
if(!arSession_)
{
return data;
}
// Update session to get current frame and render camera background.
if (HwArSession_update(arSession_, arFrame_) != HWAR_SUCCESS) {
LOGE("CameraAREngine::captureImage() ArSession_update error");
return data;
}
HwArCamera* ar_camera;
HwArFrame_acquireCamera(arSession_, arFrame_, &ar_camera);
HwArTrackingState camera_tracking_state;
HwArCamera_getTrackingState(arSession_, ar_camera, &camera_tracking_state);
Transform pose;
if(camera_tracking_state == HWAR_TRACKING_STATE_TRACKING)
{
// pose in OpenGL coordinates
float pose_raw[7];
HwArCamera_getPose(arSession_, ar_camera, arPose_);
HwArPose_getPoseRaw(arSession_, arPose_, pose_raw);
pose = Transform(pose_raw[4], pose_raw[5], pose_raw[6], pose_raw[0], pose_raw[1], pose_raw[2], pose_raw[3]);
// Get calibration parameters
// FIXME: Hard-coded as getting intrinsics with the api fails
float fx=492.689667,fy=492.606201, cx=323.594849, cy=234.659744;
int32_t camWidth=640, camHeight=480;
//HwArCamera_getImageIntrinsics(arSession_, ar_camera, arCameraIntrinsics_);
//HwArCameraIntrinsics_getFocalLength(arSession_, arCameraIntrinsics_, &fx, &fy);
//HwArCameraIntrinsics_getPrincipalPoint(arSession_, arCameraIntrinsics_, &cx, &cy);
//HwArCameraIntrinsics_getImageDimensions(arSession_, arCameraIntrinsics_, &camWidth, &camHeight);
LOGI("%f %f %f %f %d %d", fx, fy, cx, cy, camWidth, camHeight);
if(fx > 0 && fy > 0 && camWidth > 0 && camHeight > 0 && cx > 0 && cy > 0)
{
//ArPointCloud * point_cloud;
//ArFrame_acquirePointCloud(ar_session_, ar_frame_, &point_cloud);
HwArImage * image = nullptr;
HwArImage * depthImage = nullptr;
HwArStatus statusRgb = HwArFrame_acquireCameraImage(arSession_, arFrame_, &image);
HwArStatus statusDepth = HwArFrame_acquireDepthImage(arSession_, arFrame_, &depthImage);
if(statusRgb == HWAR_SUCCESS && statusDepth == HWAR_SUCCESS)
{
int64_t timestamp_ns;
HwArFrame_getTimestamp(arSession_, arFrame_, &timestamp_ns);
int planeCount;
uint8_t *imageData = nullptr;
int len = 0;
int stride;
int width;
int height;
const AImage* ndkImageRGB;
HwArImage_getNdkImage(image, &ndkImageRGB);
AImage_getNumberOfPlanes(ndkImageRGB, &planeCount);
AImage_getWidth(ndkImageRGB, &width);
AImage_getHeight(ndkImageRGB, &height);
AImage_getPlaneRowStride(ndkImageRGB, 0, &stride);
AImage_getPlaneData(ndkImageRGB, 0, &imageData, &len);
LOGI("RGB: width=%d, height=%d, bytes=%d stride=%d planeCount=%d", width, height, len, stride, planeCount);
cv::Mat outputRGB;
if(imageData != nullptr && len>0)
{
cv::cvtColor(cv::Mat(height+height/2, width, CV_8UC1, (void*)imageData), outputRGB, CV_YUV2BGR_NV21);
}
//Depth
const AImage* ndkImageDepth;
HwArImage_getNdkImage(depthImage, &ndkImageDepth);
AImage_getNumberOfPlanes(ndkImageDepth, &planeCount);
AImage_getWidth(ndkImageDepth, &width);
AImage_getHeight(ndkImageDepth, &height);
AImage_getPlaneRowStride(ndkImageDepth, 0, &stride);
AImage_getPlaneData(ndkImageDepth, 0, &imageData, &len);
LOGI("Depth: width=%d, height=%d, bytes=%d stride=%d planeCount=%d", width, height, len, stride, planeCount);
cv::Mat outputDepth(height, width, CV_16UC1);
uint16_t *dataShort = (uint16_t *)imageData;
for (int y = 0; y < outputDepth.rows; ++y)
{
for (int x = 0; x < outputDepth.cols; ++x)
{
uint16_t depthSample = dataShort[y*outputDepth.cols + x];
uint16_t depthRange = (depthSample & 0x1FFF); // first 3 bits are confidence
outputDepth.at<uint16_t>(y,x) = depthRange;
}
}
if(!outputRGB.empty() && !outputDepth.empty())
{
double stamp = double(timestamp_ns)/10e8;
CameraModel model = CameraModel(fx, fy, cx, cy, deviceTColorCamera_, 0, cv::Size(camWidth, camHeight));
data = SensorData(outputRGB, outputDepth, model, 0, stamp);
}
}
else
{
LOGE("CameraAREngine: failed to get rgb image (status=%d %d)", (int)statusRgb, (int)statusDepth);
}
HwArImage_release(image);
HwArImage_release(depthImage);
}
else
{
LOGE("Invalid intrinsics!");
}
}
HwArCamera_release(ar_camera);
if(pose.isNull())
{
LOGE("CameraAREngine: Pose is null");
}
else
{
pose = rtabmap::rtabmap_world_T_opengl_world * pose * rtabmap::opengl_world_T_rtabmap_world;
this->poseReceived(pose);
info->odomPose = pose;
}
return data;
}
void CameraAREngine::capturePoseOnly()
{
UScopeMutex lock(arSessionMutex_);
//LOGI("Capturing image...");
SensorData data;
if(!arSession_)
{
return;
}
// Update session to get current frame and render camera background.
if (HwArSession_update(arSession_, arFrame_) != HWAR_SUCCESS) {
LOGE("CameraARCore::captureImage() ArSession_update error");
return;
}
HwArCamera* ar_camera;
HwArFrame_acquireCamera(arSession_, arFrame_, &ar_camera);
HwArTrackingState camera_tracking_state;
HwArCamera_getTrackingState(arSession_, ar_camera, &camera_tracking_state);
Transform pose;
CameraModel model;
if(camera_tracking_state == HWAR_TRACKING_STATE_TRACKING)
{
// pose in OpenGL coordinates
float pose_raw[7];
HwArCamera_getPose(arSession_, ar_camera, arPose_);
HwArPose_getPoseRaw(arSession_, arPose_, pose_raw);
pose = Transform(pose_raw[4], pose_raw[5], pose_raw[6], pose_raw[0], pose_raw[1], pose_raw[2], pose_raw[3]);
if(!pose.isNull())
{
pose = rtabmap::rtabmap_world_T_opengl_world * pose * rtabmap::opengl_world_T_rtabmap_world;
this->poseReceived(pose);
}
}
HwArCamera_release(ar_camera);
}
} /* namespace rtabmap */

View File

@@ -0,0 +1,78 @@
/*
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 CAMERAARENGINE_H_
#define CAMERAARENGINE_H_
#include "CameraMobile.h"
#include <rtabmap/core/Camera.h>
#include <rtabmap/core/GeodeticCoords.h>
#include <rtabmap/utilite/UMutex.h>
#include <rtabmap/utilite/USemaphore.h>
#include <rtabmap/utilite/UEventsSender.h>
#include <rtabmap/utilite/UThread.h>
#include <rtabmap/utilite/UEvent.h>
#include <rtabmap/utilite/UTimer.h>
#include <boost/thread/mutex.hpp>
#include <huawei_arengine_interface.h>
namespace rtabmap {
class CameraAREngine : public CameraMobile {
public:
CameraAREngine(void* env, void* context, void* activity, bool smoothing = false);
virtual ~CameraAREngine();
virtual bool init(const std::string & calibrationFolder = ".", const std::string & cameraName = "");
virtual void close(); // close Tango connection
virtual std::string getSerial() const;
protected:
virtual SensorData captureImage(CameraInfo * info = 0);
virtual void capturePoseOnly();
private:
rtabmap::Transform getPoseAtTimestamp(double timestamp);
private:
void * env_;
void * context_;
void * activity_;
HwArSession* arSession_ = nullptr;
HwArConfig* arConfig_ = nullptr;
HwArFrame* arFrame_ = nullptr;
HwArCameraIntrinsics *arCameraIntrinsics_ = nullptr;
HwArPose * arPose_ = nullptr;
bool arInstallRequested_;
GLuint textureId_;
UMutex arSessionMutex_;
};
} /* namespace rtabmap */
#endif /* CAMERAARENGINE_H_ */

View File

@@ -0,0 +1,341 @@
/*
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 "CameraMobile.h"
#include "util.h"
#include "rtabmap/utilite/ULogger.h"
#include "rtabmap/core/util3d_transforms.h"
#include "rtabmap/core/OdometryEvent.h"
#include "rtabmap/core/util2d.h"
namespace rtabmap {
#define nullptr 0
//////////////////////////////
// CameraMobile
//////////////////////////////
const float CameraMobile::bilateralFilteringSigmaS = 2.0f;
const float CameraMobile::bilateralFilteringSigmaR = 0.075f;
const rtabmap::Transform CameraMobile::opticalRotation = Transform(
0.0f, 0.0f, 1.0f, 0.0f,
-1.0f, 0.0f, 0.0f, 0.0f,
0.0f, -1.0f, 0.0f, 0.0f);
const rtabmap::Transform CameraMobile::opticalRotationInv = Transform(
0.0f, -1.0f, 0.0f, 0.0f,
0.0f, 0.0f, -1.0f, 0.0f,
1.0f, 0.0f, 0.0f, 0.0f);
CameraMobile::CameraMobile(bool smoothing) :
Camera(10),
deviceTColorCamera_(Transform::getIdentity()),
spinOncePreviousStamp_(0.0),
previousStamp_(0.0),
stampEpochOffset_(0.0),
smoothing_(smoothing),
colorCameraToDisplayRotation_(ROTATION_0),
originUpdate_(false)
{
}
CameraMobile::~CameraMobile() {
// Disconnect camera service
close();
}
bool CameraMobile::init(const std::string &, const std::string &)
{
deviceTColorCamera_ = opticalRotation;
return true;
}
void CameraMobile::close()
{
previousPose_.setNull();
previousStamp_ = 0.0;
lastKnownGPS_ = GPS();
lastEnvSensors_.clear();
originOffset_ = Transform();
originUpdate_ = false;
pose_ = Transform();
data_ = SensorData();
}
void CameraMobile::resetOrigin()
{
originUpdate_ = true;
}
void CameraMobile::poseReceived(const Transform & pose)
{
if(!pose.isNull())
{
// send pose of the camera (without optical rotation)
Transform p = pose*deviceTColorCamera_;
if(originUpdate_)
{
originOffset_ = p.translation().inverse();
originUpdate_ = false;
}
if(!originOffset_.isNull())
{
this->post(new PoseEvent(originOffset_*p));
}
else
{
this->post(new PoseEvent(p));
}
}
}
bool CameraMobile::isCalibrated() const
{
return model_.isValidForProjection();
}
void CameraMobile::setGPS(const GPS & gps)
{
lastKnownGPS_ = gps;
}
void CameraMobile::setData(const SensorData & data, const Transform & pose)
{
LOGD("CameraMobile::setData pose=%s stamp=%f", pose.prettyPrint().c_str(), data.stamp());
data_ = data;
pose_ = pose;
}
void CameraMobile::addEnvSensor(int type, float value)
{
lastEnvSensors_.insert(std::make_pair((EnvSensor::Type)type, EnvSensor((EnvSensor::Type)type, value)));
}
void CameraMobile::spinOnce()
{
if(!this->isRunning())
{
bool ignoreFrame = false;
float rate = 10.0f; // maximum 10 FPS for image data
double now = UTimer::now();
if(rate>0.0f)
{
if((spinOncePreviousStamp_>=0.0 && now>spinOncePreviousStamp_ && now - spinOncePreviousStamp_ < 1.0f/rate) ||
((spinOncePreviousStamp_<=0.0 || now<=spinOncePreviousStamp_) && spinOnceFrameRateTimer_.getElapsedTime() < 1.0f/rate))
{
ignoreFrame = true;
}
}
if(!ignoreFrame)
{
spinOnceFrameRateTimer_.start();
spinOncePreviousStamp_ = now;
mainLoop();
}
else
{
// just send pose
capturePoseOnly();
}
}
}
void CameraMobile::mainLoopBegin()
{
double t = cameraStartedTime_.elapsed();
if(t < 5.0)
{
uSleep((5.0-t)*1000); // just to make sure that the camera is started
}
}
void CameraMobile::mainLoop()
{
CameraInfo info;
SensorData data = this->captureImage(&info);
if(data.isValid() && !info.odomPose.isNull())
{
if(lastKnownGPS_.stamp() > 0.0 && data.stamp()-lastKnownGPS_.stamp()<1.0)
{
data.setGPS(lastKnownGPS_);
}
else if(lastKnownGPS_.stamp()>0.0)
{
LOGD("GPS too old (current time=%f, gps time = %f)", data.stamp(), lastKnownGPS_.stamp());
}
if(lastEnvSensors_.size())
{
data.setEnvSensors(lastEnvSensors_);
lastEnvSensors_.clear();
}
if(smoothing_ && !data.depthRaw().empty())
{
//UTimer t;
data.setDepthOrRightRaw(rtabmap::util2d::fastBilateralFiltering(data.depthRaw(), bilateralFilteringSigmaS, bilateralFilteringSigmaR));
//LOGD("Bilateral filtering, time=%fs", t.ticks());
}
// Rotate image depending on the camera orientation
if(colorCameraToDisplayRotation_ == ROTATION_90)
{
UDEBUG("ROTATION_90");
cv::Mat rgb, depth;
cv::Mat rgbt(data.imageRaw().cols, data.imageRaw().rows, data.imageRaw().type());
cv::flip(data.imageRaw(),rgb,1);
cv::transpose(rgb,rgbt);
rgb = rgbt;
cv::Mat deptht(data.depthRaw().cols, data.depthRaw().rows, data.depthRaw().type());
cv::flip(data.depthRaw(),depth,1);
cv::transpose(depth,deptht);
depth = deptht;
CameraModel model = data.cameraModels()[0];
cv::Size sizet(model.imageHeight(), model.imageWidth());
model = CameraModel(
model.fy(),
model.fx(),
model.cy(),
model.cx()>0?model.imageWidth()-model.cx():0,
model.localTransform()*rtabmap::Transform(0,-1,0,0, 1,0,0,0, 0,0,1,0));
model.setImageSize(sizet);
data.setRGBDImage(rgb, depth, model);
std::vector<cv::KeyPoint> keypoints = data.keypoints();
for(size_t i=0; i<keypoints.size(); ++i)
{
keypoints[i].pt.x = data.keypoints()[i].pt.y;
keypoints[i].pt.y = rgb.rows - data.keypoints()[i].pt.x;
}
data.setFeatures(keypoints, data.keypoints3D(), cv::Mat());
}
else if(colorCameraToDisplayRotation_ == ROTATION_180)
{
UDEBUG("ROTATION_180");
cv::Mat rgb, depth;
cv::flip(data.imageRaw(),rgb,1);
cv::flip(rgb,rgb,0);
cv::flip(data.depthOrRightRaw(),depth,1);
cv::flip(depth,depth,0);
CameraModel model = data.cameraModels()[0];
cv::Size sizet(model.imageWidth(), model.imageHeight());
model = CameraModel(
model.fx(),
model.fy(),
model.cx()>0?model.imageWidth()-model.cx():0,
model.cy()>0?model.imageHeight()-model.cy():0,
model.localTransform()*rtabmap::Transform(0,0,0,0,0,1,0));
model.setImageSize(sizet);
data.setRGBDImage(rgb, depth, model);
std::vector<cv::KeyPoint> keypoints = data.keypoints();
for(size_t i=0; i<keypoints.size(); ++i)
{
keypoints[i].pt.x = rgb.cols - data.keypoints()[i].pt.x;
keypoints[i].pt.y = rgb.rows - data.keypoints()[i].pt.y;
}
data.setFeatures(keypoints, data.keypoints3D(), cv::Mat());
}
else if(colorCameraToDisplayRotation_ == ROTATION_270)
{
UDEBUG("ROTATION_270");
cv::Mat rgb(data.imageRaw().cols, data.imageRaw().rows, data.imageRaw().type());
cv::transpose(data.imageRaw(),rgb);
cv::flip(rgb,rgb,1);
cv::Mat depth(data.depthOrRightRaw().cols, data.depthOrRightRaw().rows, data.depthOrRightRaw().type());
cv::transpose(data.depthOrRightRaw(),depth);
cv::flip(depth,depth,1);
CameraModel model = data.cameraModels()[0];
cv::Size sizet(model.imageHeight(), model.imageWidth());
model = CameraModel(
model.fy(),
model.fx(),
model.cy()>0?model.imageHeight()-model.cy():0,
model.cx(),
model.localTransform()*rtabmap::Transform(0,1,0,0, -1,0,0,0, 0,0,1,0));
model.setImageSize(sizet);
data.setRGBDImage(rgb, depth, model);
std::vector<cv::KeyPoint> keypoints = data.keypoints();
for(size_t i=0; i<keypoints.size(); ++i)
{
keypoints[i].pt.x = rgb.cols - data.keypoints()[i].pt.y;
keypoints[i].pt.y = data.keypoints()[i].pt.x;
}
data.setFeatures(keypoints, data.keypoints3D(), cv::Mat());
}
rtabmap::Transform pose = info.odomPose;
data.setGroundTruth(Transform());
// convert stamp to epoch
bool firstFrame = previousPose_.isNull();
if(firstFrame)
{
stampEpochOffset_ = UTimer::now()-data.stamp();
}
data.setStamp(stampEpochOffset_ + data.stamp());
OdometryInfo info;
if(!firstFrame)
{
info.interval = data.stamp()-previousStamp_;
info.transform = previousPose_.inverse() * pose;
}
// linear cov = 0.0001
info.reg.covariance = cv::Mat::eye(6,6,CV_64FC1) * (firstFrame?9999.0:0.0001);
if(!firstFrame)
{
// angular cov = 0.000001
info.reg.covariance.at<double>(3,3) *= 0.01;
info.reg.covariance.at<double>(4,4) *= 0.01;
info.reg.covariance.at<double>(5,5) *= 0.01;
}
LOGI("Publish odometry message (variance=%f)", firstFrame?9999:0.0001);
this->post(new OdometryEvent(data, pose, info));
previousPose_ = pose;
previousStamp_ = data.stamp();
}
else if(!this->isKilled())
{
LOGW("Odometry lost");
this->post(new OdometryEvent());
}
}
SensorData CameraMobile::captureImage(CameraInfo * info)
{
if(info)
{
info->odomPose = pose_;
}
return data_;
}
} /* namespace rtabmap */

View File

@@ -0,0 +1,134 @@
/*
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 CAMERAMOBILE_H_
#define CAMERAMOBILE_H_
#include <rtabmap/core/Camera.h>
#include <rtabmap/core/GeodeticCoords.h>
#include <rtabmap/utilite/UMutex.h>
#include <rtabmap/utilite/USemaphore.h>
#include <rtabmap/utilite/UEventsSender.h>
#include <rtabmap/utilite/UThread.h>
#include <rtabmap/utilite/UEvent.h>
#include <rtabmap/utilite/UTimer.h>
#include <boost/thread/mutex.hpp>
#include "util.h"
namespace rtabmap {
class CameraInfoEvent: public UEvent
{
public:
CameraInfoEvent(int type, const std::string & key, const std::string & value) : type_(type), key_(key), value_(value) {}
virtual std::string getClassName() const {return "CameraInfoEvent";}
int type() const {return type_;}
const std::string & key() const {return key_;}
const std::string & value() const {return value_;}
private:
int type_;
std::string key_;
std::string value_;
};
class PoseEvent: public UEvent
{
public:
PoseEvent(const Transform & pose) : pose_(pose) {}
virtual std::string getClassName() const {return "PoseEvent";}
const Transform & pose() const {return pose_;}
private:
Transform pose_;
};
class CameraMobile : public Camera, public UThread, public UEventsSender {
public:
static const float bilateralFilteringSigmaS;
static const float bilateralFilteringSigmaR;
static const rtabmap::Transform opticalRotation;
static const rtabmap::Transform opticalRotationInv;
public:
CameraMobile(bool smoothing = false);
virtual ~CameraMobile();
// abstract functions
virtual bool init(const std::string & calibrationFolder = ".", const std::string & cameraName = "");
virtual void close(); // inherited classes should call its parent in their close().
virtual std::string getSerial() const {return "CameraMobile";}
const Transform & getOriginOffset() const {return originOffset_;} // in rtabmap frame
void resetOrigin();
virtual bool isCalibrated() const;
void poseReceived(const Transform & pose); // in rtabmap frame
const CameraModel & getCameraModel() const {return model_;}
const Transform & getDeviceTColorCamera() const {return deviceTColorCamera_;}
void setSmoothing(bool enabled) {smoothing_ = enabled;}
virtual void setScreenRotationAndSize(ScreenRotation colorCameraToDisplayRotation, int width, int height) {colorCameraToDisplayRotation_ = colorCameraToDisplayRotation;}
void setGPS(const GPS & gps);
void addEnvSensor(int type, float value);
void setData(const SensorData & data, const Transform & pose);
void spinOnce(); // Should only be called if not thread is not running, otherwise it does nothing
protected:
virtual SensorData captureImage(CameraInfo * info = 0);
virtual void capturePoseOnly() {}
virtual void mainLoopBegin();
virtual void mainLoop();
protected:
CameraModel model_; // local transform is the device to camera optical rotation in rtabmap frame
Transform deviceTColorCamera_; // device to camera optical rotation in rtabmap frame
UTimer spinOnceFrameRateTimer_;
double spinOncePreviousStamp_;
private:
Transform previousPose_;
double previousStamp_;
UTimer cameraStartedTime_;
double stampEpochOffset_;
bool smoothing_;
ScreenRotation colorCameraToDisplayRotation_;
GPS lastKnownGPS_;
EnvSensors lastEnvSensors_;
Transform originOffset_;
bool originUpdate_;
SensorData data_;
Transform pose_;
};
} /* namespace rtabmap */
#endif /* CAMERATANGO_H_ */

View File

@@ -91,7 +91,7 @@ void onPoseAvailableRouter(void* context, const TangoPoseData* pose)
if(pose->status_code == TANGO_POSE_VALID)
{
CameraTango* app = static_cast<CameraTango*>(context);
app->poseReceived(app->tangoPoseToTransform(pose));
app->poseReceived(rtabmap_world_T_tango_world * app->tangoPoseToTransform(pose) * tango_device_T_rtabmap_world);
}
}
@@ -104,23 +104,15 @@ void onTangoEventAvailableRouter(void* context, const TangoEvent* event)
//////////////////////////////
// CameraTango
//////////////////////////////
const float CameraTango::bilateralFilteringSigmaS = 2.0f;
const float CameraTango::bilateralFilteringSigmaR = 0.075f;
CameraTango::CameraTango(bool colorCamera, int decimation, bool publishRawScan, bool smoothing) :
Camera(0),
CameraMobile(smoothing),
tango_config_(0),
previousStamp_(0.0),
stampEpochOffset_(0.0),
colorCamera_(colorCamera),
decimation_(decimation),
rawScanPublished_(publishRawScan),
smoothing_(smoothing),
cloudStamp_(0),
tangoColorType_(0),
tangoColorStamp_(0),
colorCameraToDisplayRotation_(ROTATION_0),
originUpdate_(false)
tangoColorStamp_(0)
{
UASSERT(decimation >= 1);
}
@@ -350,6 +342,7 @@ bool CameraTango::init(const std::string & calibrationFolder, const std::string
pose_data.orientation[1],
pose_data.orientation[2],
pose_data.orientation[3]);
deviceTColorCamera_ = rtabmap_world_T_opengl_world * deviceTColorCamera_;
// camera intrinsic
TangoCameraIntrinsics color_camera_intrinsics;
@@ -408,18 +401,14 @@ bool CameraTango::init(const std::string & calibrationFolder, const std::string
model_ = CameraModel(colorCamera_?"color":"fisheye",
cv::Size(color_camera_intrinsics.width, color_camera_intrinsics.height),
K, D, R, P,
tango_device_T_rtabmap_device.inverse()*deviceTColorCamera_); // device to camera optical rotation in rtabmap frame
deviceTColorCamera_);
if(!colorCamera_)
{
initFisheyeRectificationMap(model_, fisheyeRectifyMapX_, fisheyeRectifyMapY_);
}
LOGI("deviceTColorCameraTango =%s", deviceTColorCamera_.prettyPrint().c_str());
LOGI("deviceTColorCameraRtabmap=%s", (tango_device_T_rtabmap_device.inverse()*deviceTColorCamera_).prettyPrint().c_str());
cameraStartedTime_.restart();
LOGI("deviceTColorCameraRtabmap =%s", deviceTColorCamera_.prettyPrint().c_str());
return true;
}
@@ -433,19 +422,10 @@ void CameraTango::close()
TangoService_disconnect();
LOGI("TangoService_disconnect() done.");
}
previousPose_.setNull();
previousStamp_ = 0.0;
fisheyeRectifyMapX_ = cv::Mat();
fisheyeRectifyMapY_ = cv::Mat();
lastKnownGPS_ = GPS();
lastEnvSensors_.clear();
originOffset_ = Transform();
originUpdate_ = false;
}
void CameraTango::resetOrigin()
{
originUpdate_ = true;
CameraMobile::close();
}
void CameraTango::cloudReceived(const cv::Mat & cloud, double timestamp)
@@ -500,40 +480,9 @@ void CameraTango::rgbReceived(const cv::Mat & tangoImage, int type, double times
}
}
static rtabmap::Transform opticalRotation(
1.0f, 0.0f, 0.0f, 0.0f,
0.0f, -1.0f, 0.0f, 0.0f,
0.0f, 0.0f, -1.0f, 0.0f);
void CameraTango::poseReceived(const Transform & pose)
{
if(!pose.isNull())
{
// send pose of the camera (without optical rotation), not the device
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));
}
}
}
void CameraTango::tangoEventReceived(int type, const char * key, const char * value)
{
this->post(new CameraTangoEvent(type, key, value));
}
bool CameraTango::isCalibrated() const
{
return model_.isValidForProjection();
this->post(new CameraInfoEvent(type, key, value));
}
std::string CameraTango::getSerial() const
@@ -541,16 +490,6 @@ std::string CameraTango::getSerial() const
return "Tango";
}
void CameraTango::setGPS(const GPS & gps)
{
lastKnownGPS_ = gps;
}
void CameraTango::addEnvSensor(int type, float value)
{
lastEnvSensors_.insert(std::make_pair((EnvSensor::Type)type, EnvSensor((EnvSensor::Type)type, value)));
}
rtabmap::Transform CameraTango::tangoPoseToTransform(const TangoPoseData * tangoPose) const
{
UASSERT(tangoPose);
@@ -594,7 +533,7 @@ rtabmap::Transform CameraTango::getPoseAtTimestamp(double timestamp)
else
{
pose = tangoPoseToTransform(&pose_start_service_T_device);
pose = rtabmap_world_T_tango_world * tangoPoseToTransform(&pose_start_service_T_device) * tango_device_T_rtabmap_world;
}
return pose;
@@ -610,7 +549,7 @@ SensorData CameraTango::captureImage(CameraInfo * info)
if(this->isRunning())
{
LOGE("Not received any frames since 2 seconds, try to restart the camera again.");
this->post(new CameraTangoEvent(0, "CameraTango", "No frames received since 2 seconds."));
this->post(new CameraInfoEvent(0, "CameraTango", "No frames received since 2 seconds."));
boost::mutex::scoped_lock lock(dataMutex_);
if(!cloud_.empty() && !tangoColor_.empty())
@@ -804,7 +743,7 @@ SensorData CameraTango::captureImage(CameraInfo * info)
if(closePoints > 100)
{
this->post(new CameraTangoEvent(0, "TooClose", ""));
this->post(new CameraInfoEvent(0, "TooClose", ""));
}
if(oi)
@@ -822,78 +761,23 @@ SensorData CameraTango::captureImage(CameraInfo * info)
{
depth = rtabmap::util2d::fillDepthHoles(depth, holeSize, maxDepthError);
Transform poseDevice = getPoseAtTimestamp(rgbStamp);
// adjust origin
if(!originOffset_.isNull())
{
poseDevice = originOffset_ * poseDevice;
}
Transform odom = getPoseAtTimestamp(rgbStamp);
//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());
//Rotate in RTAB-Map's coordinate
Transform odom = rtabmap_world_T_tango_world * poseDevice * tango_device_T_rtabmap_device;
// adjust origin
if(!getOriginOffset().isNull())
{
odom = getOriginOffset() * odom;
}
//LOGD("rtabmap = %s", odom.prettyPrint().c_str());
//LOGD("opengl(r)= %s", (opengl_world_T_rtabmap_world * odom * rtabmap_device_T_opengl_device).prettyPrint().c_str());
Transform scanLocalTransform = model.localTransform();
// Rotate image depending on the camera orientation
if(colorCameraToDisplayRotation_ == ROTATION_90)
{
cv::Mat rgbt(rgb.cols, rgb.rows, rgb.type());
cv::flip(rgb,rgb,1);
cv::transpose(rgb,rgbt);
rgb = rgbt;
cv::Mat deptht(depth.cols, depth.rows, depth.type());
cv::flip(depth,depth,1);
cv::transpose(depth,deptht);
depth = deptht;
cv::Size sizet(model.imageHeight(), model.imageWidth());
model = CameraModel(model.fy(), model.fx(), model.cy(), model.cx()>0?model.imageWidth()-model.cx():0, model.localTransform()*rtabmap::Transform(0,0,0,0,0,1.57079632679489661923132169163975144));
model.setImageSize(sizet);
}
else if(colorCameraToDisplayRotation_ == ROTATION_180)
{
cv::flip(rgb,rgb,1);
cv::flip(rgb,rgb,0);
cv::flip(depth,depth,1);
cv::flip(depth,depth,0);
cv::Size sizet(model.imageWidth(), model.imageHeight());
model = CameraModel(
model.fx(),
model.fy(),
model.cx()>0?model.imageWidth()-model.cx():0,
model.cy()>0?model.imageHeight()-model.cy():0,
model.localTransform()*rtabmap::Transform(0,0,0,0,0,1.57079632679489661923132169163975144*2.0));
model.setImageSize(sizet);
}
else if(colorCameraToDisplayRotation_ == ROTATION_270)
{
cv::Mat rgbt(rgb.cols, rgb.rows, rgb.type());
cv::transpose(rgb,rgbt);
cv::flip(rgbt,rgbt,1);
rgb = rgbt;
cv::Mat deptht(depth.cols, depth.rows, depth.type());
cv::transpose(depth,deptht);
cv::flip(deptht,deptht,1);
depth = deptht;
cv::Size sizet(model.imageHeight(), model.imageWidth());
model = CameraModel(model.fy(), model.fx(), model.cy()>0?model.imageHeight()-model.cy():0, model.cx(), model.localTransform()*rtabmap::Transform(0,0,0,0,0,-1.57079632679489661923132169163975144));
model.setImageSize(sizet);
}
if(smoothing_)
{
//UTimer t;
depth = rtabmap::util2d::fastBilateralFiltering(depth, bilateralFilteringSigmaS, bilateralFilteringSigmaR);
//LOGD("Bilateral filtering, time=%fs", t.ticks());
}
if(rawScanPublished_)
{
data = SensorData(LaserScan::backwardCompatibility(scan, cloud.total()/scanDownsampling, 0, scanLocalTransform), rgb, depth, model, this->getNextSeqID(), rgbStamp);
@@ -902,22 +786,7 @@ SensorData CameraTango::captureImage(CameraInfo * info)
{
data = SensorData(rgb, depth, model, this->getNextSeqID(), rgbStamp);
}
data.setGroundTruth(odom);
if(lastKnownGPS_.stamp() > 0.0 && rgbStamp-lastKnownGPS_.stamp()<1.0)
{
data.setGPS(lastKnownGPS_);
}
else if(lastKnownGPS_.stamp()>0.0)
{
LOGD("GPS too old (current time=%f, gps time = %f)", rgbStamp, lastKnownGPS_.stamp());
}
if(lastEnvSensors_.size())
{
data.setEnvSensors(lastEnvSensors_);
lastEnvSensors_.clear();
}
info->odomPose = odom;
}
else
{
@@ -928,64 +797,4 @@ SensorData CameraTango::captureImage(CameraInfo * info)
}
void CameraTango::mainLoopBegin()
{
double t = cameraStartedTime_.elapsed();
if(t < 5.0)
{
uSleep((5.0-t)*1000); // just to make sure that the camera is started
}
}
void CameraTango::mainLoop()
{
if(tango_config_)
{
SensorData data = this->captureImage();
if(!data.groundTruth().isNull())
{
rtabmap::Transform pose = data.groundTruth();
data.setGroundTruth(Transform());
// convert stamp to epoch
bool firstFrame = previousPose_.isNull();
if(firstFrame)
{
stampEpochOffset_ = UTimer::now()-data.stamp();
}
data.setStamp(stampEpochOffset_ + data.stamp());
OdometryInfo info;
if(!firstFrame)
{
info.interval = data.stamp()-previousStamp_;
info.transform = previousPose_.inverse() * pose;
}
// linear cov = 0.0001
info.reg.covariance = cv::Mat::eye(6,6,CV_64FC1) * (firstFrame?9999.0:0.0001);
if(!firstFrame)
{
// angular cov = 0.000001
info.reg.covariance.at<double>(3,3) *= 0.01;
info.reg.covariance.at<double>(4,4) *= 0.01;
info.reg.covariance.at<double>(5,5) *= 0.01;
}
LOGI("Publish odometry message (variance=%f)", firstFrame?9999:0.0001);
this->post(new OdometryEvent(data, pose, info));
previousPose_ = pose;
previousStamp_ = data.stamp();
}
else if(!this->isKilled())
{
LOGW("Odometry lost");
this->post(new OdometryEvent());
}
}
else
{
UERROR("Camera not initialized, cannot start thread.");
this->kill();
}
}
} /* namespace rtabmap */

View File

@@ -28,6 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef CAMERATANGO_H_
#define CAMERATANGO_H_
#include "CameraMobile.h"
#include <rtabmap/core/Camera.h>
#include <rtabmap/core/GeodeticCoords.h>
#include <rtabmap/utilite/UMutex.h>
@@ -37,66 +38,26 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <rtabmap/utilite/UEvent.h>
#include <rtabmap/utilite/UTimer.h>
#include <boost/thread/mutex.hpp>
#include <tango_client_api.h>
#include <tango_support_api.h>
class TangoPoseData;
namespace rtabmap {
class PoseEvent: public UEvent
{
public:
PoseEvent(const Transform & pose) : pose_(pose) {}
virtual std::string getClassName() const {return "PoseEvent";}
const Transform & pose() const {return pose_;}
private:
Transform pose_;
};
class CameraTangoEvent: public UEvent
{
public:
CameraTangoEvent(int type, const std::string & key, const std::string & value) : type_(type), key_(key), value_(value) {}
virtual std::string getClassName() const {return "CameraTangoEvent";}
int type() const {return type_;}
const std::string & key() const {return key_;}
const std::string & value() const {return value_;}
private:
int type_;
std::string key_;
std::string value_;
};
class CameraTango : public Camera, public UThread, public UEventsSender {
public:
static const float bilateralFilteringSigmaS;
static const float bilateralFilteringSigmaR;
class CameraTango : public CameraMobile {
public:
CameraTango(bool colorCamera, int decimation, bool publishRawScan, bool smoothing);
virtual ~CameraTango();
virtual bool init(const std::string & calibrationFolder = ".", const std::string & cameraName = "");
void close(); // close Tango connection
void resetOrigin();
virtual bool isCalibrated() const;
virtual void close(); // close Tango connection
virtual std::string getSerial() const;
const CameraModel & getCameraModel() const {return model_;}
rtabmap::Transform tangoPoseToTransform(const TangoPoseData * tangoPose) const;
void setColorCamera(bool enabled) {if(!this->isRunning()) colorCamera_ = enabled;}
void setDecimation(int value) {decimation_ = value;}
void setSmoothing(bool enabled) {smoothing_ = enabled;}
void setRawScanPublished(bool enabled) {rawScanPublished_ = enabled;}
void setScreenRotation(TangoSupportRotation colorCameraToDisplayRotation) {colorCameraToDisplayRotation_ = colorCameraToDisplayRotation;}
void setGPS(const GPS & gps);
void addEnvSensor(int type, float value);
void cloudReceived(const cv::Mat & cloud, double timestamp);
void rgbReceived(const cv::Mat & tangoImage, int type, double timestamp);
void poseReceived(const Transform & pose);
void tangoEventReceived(int type, const char * key, const char * value);
protected:
@@ -105,19 +66,11 @@ protected:
private:
rtabmap::Transform getPoseAtTimestamp(double timestamp);
virtual void mainLoopBegin();
virtual void mainLoop();
private:
void * tango_config_;
Transform previousPose_;
double previousStamp_;
UTimer cameraStartedTime_;
double stampEpochOffset_;
bool colorCamera_;
int decimation_;
bool rawScanPublished_;
bool smoothing_;
cv::Mat cloud_;
double cloudStamp_;
cv::Mat tangoColor_;
@@ -125,15 +78,8 @@ private:
double tangoColorStamp_;
boost::mutex dataMutex_;
USemaphore dataReady_;
CameraModel model_;
Transform deviceTColorCamera_;
TangoSupportRotation colorCameraToDisplayRotation_;
cv::Mat fisheyeRectifyMapX_;
cv::Mat fisheyeRectifyMapY_;
GPS lastKnownGPS_;
EnvSensors lastEnvSensors_;
Transform originOffset_;
bool originUpdate_;
};
} /* namespace rtabmap */

File diff suppressed because it is too large Load Diff

View File

@@ -31,11 +31,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <jni.h>
#include <memory>
#include <tango_client_api.h> // NOLINT
#include <tango-gl/util.h>
#include "scene.h"
#include "CameraTango.h"
#include "CameraMobile.h"
#include "util.h"
#include "ProgressionStatus.h"
@@ -45,43 +44,20 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <pcl/pcl_base.h>
#include <pcl/TextureMesh.h>
// RTABMapApp handles the application lifecycle and resources.
class RTABMapApp : public UEventsHandler {
public:
// Constructor and deconstructor.
RTABMapApp();
RTABMapApp(JNIEnv* env, jobject caller_activity);
~RTABMapApp();
void onCreate(JNIEnv* env, jobject caller_activity);
void setScreenRotation(int displayRotation, int cameraRotation);
int openDatabase(const std::string & databasePath, bool databaseInMemory, bool optimize, const std::string & databaseSource=std::string());
bool onTangoServiceConnected(JNIEnv* env, jobject iBinder);
// Explicitly reset motion tracking and restart the pipeline.
// Note that this will cause motion tracking to re-initialize.
void TangoResetMotionTracking();
// Tango Service point cloud callback function for depth data. Called when new
// new point cloud data is available from the Tango Service.
//
// @param pose: The current point cloud returned by the service,
// caller allocated.
void onPointCloudAvailable(const TangoXYZij* xyz_ij);
// Tango service pose callback function for pose data. Called when new
// information about device pose is available from the Tango Service.
//
// @param pose: The current pose returned by the service, caller allocated.
void onPoseAvailable(const TangoPoseData* pose);
// Tango service event callback function for event data. Called when new events
// are available from the Tango Service.
//
// @param event: Tango event, caller allocated.
void onTangoEventAvailable(const TangoEvent* event);
bool isBuiltWith(int cameraDriver) const;
bool startCamera(JNIEnv* env, jobject iBinder, jobject context, jobject activity, int driver);
// Allocate OpenGL resources for rendering, mainly for initializing the Scene.
void InitializeGLContent();
@@ -92,8 +68,7 @@ class RTABMapApp : public UEventsHandler {
// Main render loop.
int Render();
// Release all non-OpenGL allocated resources.
void onPause();
void stopCamera();
// Set render camera's viewing angle, first person, third person or top down.
//
@@ -135,6 +110,7 @@ class RTABMapApp : public UEventsHandler {
void setCameraColor(bool enabled);
void setFullResolution(bool enabled);
void setSmoothing(bool enabled);
void setDepthFromMotion(bool enabled);
void setAppendMode(bool enabled);
void setDataRecorderMode(bool enabled);
void setMaxCloudDepth(float value);
@@ -150,7 +126,6 @@ class RTABMapApp : public UEventsHandler {
void setGPS(const rtabmap::GPS & gps);
void addEnvSensor(int type, float value);
void resetMapping();
void save(const std::string & databasePath);
void cancelProcessing();
bool exportMesh(
@@ -174,21 +149,33 @@ class RTABMapApp : public UEventsHandler {
bool writeExportedMesh(const std::string & directory, const std::string & name);
int postProcessing(int approach);
void postCameraPoseEvent(
float x, float y, float z, float qx, float qy, float qz, float qw);
void postOdometryEvent(
float x, float y, float z, float qx, float qy, float qz, float qw,
float fx, float fy, float cx, float cy,
double stamp,
void * yPlane, void * uPlane, void * vPlane, int yPlaneLen, int rgbWidth, int rgbHeight, int rgbFormat,
void * depth, int depthLen, int depthWidth, int depthHeight, int depthFormat,
float * points, int pointsLen);
protected:
virtual bool handleEvent(UEvent * event);
private:
rtabmap::ParametersMap getRtabmapParameters();
bool smoothMesh(int id, Mesh & mesh);
bool smoothMesh(int id, rtabmap::Mesh & mesh);
void gainCompensation(bool full = false);
std::vector<pcl::Vertices> filterOrganizedPolygons(const std::vector<pcl::Vertices> & polygons, int cloudSize) const;
std::vector<pcl::Vertices> filterPolygons(const std::vector<pcl::Vertices> & polygons, int cloudSize) const;
private:
rtabmap::CameraTango * camera_;
int cameraDriver_;
rtabmap::CameraMobile * camera_;
rtabmap::RtabmapThread * rtabmapThread_;
rtabmap::Rtabmap * rtabmap_;
LogHandler * logHandler_;
rtabmap::LogHandler * logHandler_;
bool odomCloudShown_;
bool graphOptimization_;
@@ -197,6 +184,7 @@ class RTABMapApp : public UEventsHandler {
bool trajectoryMode_;
bool rawScanSaved_;
bool smoothing_;
bool depthFromMotion_;
bool cameraColor_;
bool fullResolution_;
bool appendMode_;
@@ -212,7 +200,6 @@ class RTABMapApp : public UEventsHandler {
rtabmap::ParametersMap mappingParameters_;
bool paused_;
bool dataRecorderMode_;
bool clearSceneOnNextRender_;
bool openingDatabase_;
@@ -244,14 +231,13 @@ class RTABMapApp : public UEventsHandler {
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 cameraMutex_;
boost::mutex rtabmapMutex_;
boost::mutex visLocalizationMutex_;
boost::mutex meshesMutex_;
boost::mutex odomMutex_;
boost::mutex poseMutex_;
@@ -259,7 +245,7 @@ class RTABMapApp : public UEventsHandler {
USemaphore screenshotReady_;
std::map<int, Mesh> createdMeshes_;
std::map<int, rtabmap::Mesh> createdMeshes_;
std::map<int, rtabmap::Transform> rawPoses_;
std::pair<rtabmap::RtabmapEventInit::Status, std::string> status_;

View File

@@ -0,0 +1,92 @@
/*
* Copyright 2018 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// This modules handles drawing the passthrough camera image into the OpenGL
// scene.
#include "background_renderer.h"
#include <type_traits>
namespace {
const std::string kVertexShader =
"attribute vec4 a_Position;\n"
"attribute vec2 a_TexCoord;\n"
"varying vec2 v_TexCoord;\n"
"void main() {\n"
" gl_Position = a_Position;\n"
" v_TexCoord = a_TexCoord;\n"
"}\n";
const std::string kFragmentShader =
"#extension GL_OES_EGL_image_external : require\n"
"precision mediump float;\n"
"varying vec2 v_TexCoord;\n"
"uniform samplerExternalOES sTexture;\n"
"void main() {\n"
" vec4 sample = texture2D(sTexture, v_TexCoord);\n"
" float grey = 0.21 * sample.r + 0.71 * sample.g + 0.07 * sample.b;\n"
" gl_FragColor = vec4(grey, grey, grey, 0.5);\n"
"}\n";
} // namespace
void BackgroundRenderer::InitializeGlContent(GLuint textureId)
{
texture_id_ = textureId;
shader_program_ = tango_gl::util::CreateProgram(kVertexShader.c_str(), kFragmentShader.c_str());
if (!shader_program_) {
LOGE("Could not create program.");
}
glUseProgram(shader_program_);
attribute_vertices_ = glGetAttribLocation(shader_program_, "a_Position");
attribute_uvs_ = glGetAttribLocation(shader_program_, "a_TexCoord");
glUseProgram(0);
}
void BackgroundRenderer::Draw(const float * transformed_uvs) {
static_assert(std::extent<decltype(BackgroundRenderer_kVertices)>::value == kNumVertices * 2, "Incorrect kVertices length");
glUseProgram(shader_program_);
glDepthMask(GL_FALSE);
glEnable (GL_BLEND);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture_id_);
glVertexAttribPointer(attribute_vertices_, 2, GL_FLOAT, GL_FALSE, 0, BackgroundRenderer_kVertices);
glVertexAttribPointer(attribute_uvs_, 2, GL_FLOAT, GL_FALSE, 0, transformed_uvs);
glEnableVertexAttribArray(attribute_vertices_);
glEnableVertexAttribArray(attribute_uvs_);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glDisableVertexAttribArray(attribute_vertices_);
glDisableVertexAttribArray(attribute_uvs_);
glUseProgram(0);
glDepthMask(GL_TRUE);
glDisable (GL_BLEND);
tango_gl::util::CheckGlError("BackgroundRenderer::Draw() error");
}

View File

@@ -0,0 +1,58 @@
/*
* Copyright 2018 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef C_ARCORE_AUGMENTED_IMAGE_BACKGROUND_RENDERER_H_
#define C_ARCORE_AUGMENTED_IMAGE_BACKGROUND_RENDERER_H_
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#include <cstdlib>
#include "util.h"
static const GLfloat BackgroundRenderer_kVertices[] = {
-1.0f, -1.0f, +1.0f, -1.0f, -1.0f, +1.0f, +1.0f, +1.0f,
};
// This class renders the passthrough camera image into the OpenGL frame.
class BackgroundRenderer {
public:
// Positions of the quad vertices in clip space (X, Y).
static constexpr int kNumVertices = 4;
public:
BackgroundRenderer() = default;
~BackgroundRenderer() = default;
// Sets up OpenGL state. Must be called on the OpenGL thread and before any
// other methods below.
void InitializeGlContent(GLuint textureId);
// Draws the background image. This methods must be called for every ArFrame
// returned by ArSession_update() to catch display geometry change events.
void Draw(const float * transformed_uvs);
private:
GLuint shader_program_;
GLuint texture_id_;
GLuint attribute_vertices_;
GLuint attribute_uvs_;
};
#endif // C_ARCORE_AUGMENTED_IMAGE_BACKGROUND_RENDERER_H_

File diff suppressed because it is too large Load Diff

View File

@@ -318,7 +318,7 @@ PointCloudDrawable::PointCloudDrawable(
}
PointCloudDrawable::PointCloudDrawable(
const Mesh & mesh,
const rtabmap::Mesh & mesh,
bool createWireframe) :
vertex_buffers_(0),
textures_(0),
@@ -525,7 +525,7 @@ void PointCloudDrawable::updateCloud(const pcl::PointCloud<pcl::PointXYZRGB>::Pt
nPoints_ = totalPoints;
}
void PointCloudDrawable::updateMesh(const Mesh & mesh, bool createWireframe)
void PointCloudDrawable::updateMesh(const rtabmap::Mesh & mesh, bool createWireframe)
{
UASSERT(mesh.cloud.get() && !mesh.cloud->empty());
nPoints_ = 0;

View File

@@ -55,13 +55,13 @@ private:
float gainG = 1.0f,
float gainB = 1.0f);
PointCloudDrawable(
const Mesh & mesh,
const rtabmap::Mesh & mesh,
bool createWireframe = false);
virtual ~PointCloudDrawable();
void updatePolygons(const std::vector<pcl::Vertices> & polygons, const std::vector<pcl::Vertices> & polygonsLowRes = std::vector<pcl::Vertices>(), bool createWireframe = false);
void updateCloud(const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloud, const pcl::IndicesPtr & indices);
void updateMesh(const Mesh & mesh, bool createWireframe = false);
void updateMesh(const rtabmap::Mesh & mesh, bool createWireframe = false);
void setPose(const rtabmap::Transform & pose);
void setVisible(bool visible) {visible_=visible;}
void setGains(float gainR, float gainG, float gainB) {gainR_ = gainR; gainG_ = gainG; gainB_ = gainB;}

View File

@@ -69,6 +69,7 @@ const std::string kGraphFragmentShader =
Scene::Scene() :
background_renderer_(0),
gesture_camera_(0),
axis_(0),
frustum_(0),
@@ -79,7 +80,8 @@ Scene::Scene() :
graphVisible_(true),
gridVisible_(true),
traceVisible_(true),
color_camera_to_display_rotation_(ROTATION_0),
frustumVisible_(true),
color_camera_to_display_rotation_(rtabmap::ROTATION_0),
currentPose_(0),
graph_shader_program_(0),
blending_(true),
@@ -108,6 +110,7 @@ Scene::Scene() :
Scene::~Scene() {
DeleteResources();
delete gesture_camera_;
delete currentPose_;
}
//Should only be called in OpenGL thread!
@@ -126,7 +129,6 @@ void Scene::InitGLContent()
trace_ = new tango_gl::Trace();
grid_ = new tango_gl::Grid();
box_ = new BoundingBoxDrawable();
currentPose_ = new rtabmap::Transform();
axis_->SetScale(glm::vec3(0.5f,0.5f,0.5f));
@@ -158,8 +160,9 @@ void Scene::DeleteResources() {
delete frustum_;
delete trace_;
delete grid_;
delete currentPose_;
delete box_;
delete background_renderer_;
background_renderer_ = 0;
}
PointCloudDrawable::releaseShaderPrograms();
@@ -364,9 +367,13 @@ bool intersectFrustumAABB(
}
//Should only be called in OpenGL thread!
int Scene::Render() {
int Scene::Render(const float * uvsTransformed, glm::mat4 arViewMatrix, glm::mat4 arProjectionMatrix, const rtabmap::Mesh & occlusionMesh) {
UASSERT(gesture_camera_ != 0);
if(currentPose_ == 0)
{
currentPose_ = new rtabmap::Transform(0,0,0,0,0,-M_PI/2.0f);
}
glm::vec3 position(currentPose_->x(), currentPose_->y(), currentPose_->z());
Eigen::Quaternionf quat = currentPose_->getQuaternionf();
glm::quat rotation(quat.w(), quat.x(), quat.y(), quat.z());
@@ -391,6 +398,17 @@ int Scene::Render() {
glm::mat4 projectionMatrix = gesture_camera_->GetProjectionMatrix();
glm::mat4 viewMatrix = gesture_camera_->GetViewMatrix();
bool renderBackgroundCamera =
background_renderer_ &&
gesture_camera_->GetCameraType() == tango_gl::GestureCamera::kFirstPerson &&
!rtabmap::glmToTransform(arProjectionMatrix).isNull() &&
uvsTransformed;
if(renderBackgroundCamera)
{
projectionMatrix = arProjectionMatrix;
viewMatrix = arViewMatrix;
}
rtabmap::Transform openglCamera = GetOpenGLCameraPose();//*rtabmap::Transform(0.0f, 0.0f, 3.0f, 0.0f, 0.0f, 0.0f);
// transform in same coordinate as frustum filtering
openglCamera *= rtabmap::Transform(
@@ -440,7 +458,7 @@ int Scene::Render() {
UTimer timer;
bool onlineBlending = blending_ && gesture_camera_->GetCameraType()!=tango_gl::GestureCamera::kTopOrtho && mapRendering_ && meshRendering_ && cloudsToDraw.size()>1;
bool onlineBlending = (renderBackgroundCamera && occlusionMesh.cloud.get() && occlusionMesh.cloud->size()) || (blending_ && gesture_camera_->GetCameraType()!=tango_gl::GestureCamera::kTopOrtho && mapRendering_ && meshRendering_ && cloudsToDraw.size()>1);
if(onlineBlending && fboId_)
{
// set the rendering destination to FBO
@@ -450,11 +468,19 @@ int Scene::Render() {
glClearColor(1, 1, 1, 1);
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
// Draw scene
for(std::vector<PointCloudDrawable*>::const_iterator iter=cloudsToDraw.begin(); iter!=cloudsToDraw.end(); ++iter)
if(renderBackgroundCamera)
{
// set large distance to cam to use low res polygons for fast processing
(*iter)->Render(projectionMatrix, viewMatrix, meshRendering_, pointSize_, false, false, 999.0f);
PointCloudDrawable drawable(occlusionMesh);
drawable.Render(projectionMatrix, viewMatrix, true, pointSize_, false, false, 999.0f);
}
else
{
// Draw scene
for(std::vector<PointCloudDrawable*>::const_iterator iter=cloudsToDraw.begin(); iter!=cloudsToDraw.end(); ++iter)
{
// set large distance to cam to use low res polygons for fast processing
(*iter)->Render(projectionMatrix, viewMatrix, meshRendering_, pointSize_, false, false, 999.0f);
}
}
// back to normal window-system-provided framebuffer
@@ -491,9 +517,18 @@ int Scene::Render() {
glClearColor(r_, g_, b_, 1.0f);
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
if(renderBackgroundCamera)
{
background_renderer_->Draw(uvsTransformed);
//To debug occlusion image:
//PointCloudDrawable drawable(occlusionMesh);
//drawable.Render(projectionMatrix, viewMatrix, true, pointSize_, false, false, 999.0f);
}
if(!currentPose_->isNull())
{
if (gesture_camera_->GetCameraType() != tango_gl::GestureCamera::kFirstPerson)
if (frustumVisible_ && gesture_camera_->GetCameraType() != tango_gl::GestureCamera::kFirstPerson)
{
frustum_->SetPosition(position);
frustum_->SetRotation(rotation);
@@ -502,8 +537,13 @@ int Scene::Render() {
frustum_->SetScale(kFrustumScale);
frustum_->Render(projectionMatrix, viewMatrix);
axis_->SetPosition(position);
axis_->SetRotation(rotation);
rtabmap::Transform cameraFrame = *currentPose_*rtabmap::optical_T_opengl*rtabmap::CameraMobile::opticalRotationInv;
glm::vec3 positionCamera(cameraFrame.x(), cameraFrame.y(), cameraFrame.z());
Eigen::Quaternionf quatCamera = cameraFrame.getQuaternionf();
glm::quat rotationCamera(quatCamera.w(), quatCamera.x(), quatCamera.y(), quatCamera.z());
axis_->SetPosition(positionCamera);
axis_->SetRotation(rotationCamera);
axis_->Render(projectionMatrix, viewMatrix);
}
@@ -512,11 +552,11 @@ int Scene::Render() {
{
trace_->Render(projectionMatrix, viewMatrix);
}
}
if(gridVisible_)
{
grid_->Render(projectionMatrix, viewMatrix);
}
if(gridVisible_ && !renderBackgroundCamera)
{
grid_->Render(projectionMatrix, viewMatrix);
}
if(graphVisible_ && graph_)
@@ -571,8 +611,11 @@ void Scene::SetCameraType(tango_gl::GestureCamera::CameraType camera_type) {
void Scene::SetCameraPose(const rtabmap::Transform & pose)
{
UASSERT(currentPose_ != 0);
UASSERT(!pose.isNull());
if(currentPose_ ==0)
{
currentPose_ = new rtabmap::Transform(0,0,0,0,0,-M_PI/2.0f);
}
*currentPose_ = pose;
}
@@ -600,7 +643,7 @@ rtabmap::Transform Scene::GetOpenGLCameraPose(float * fov) const
{
*fov = gesture_camera_->getFOV();
}
return glmToTransform(gesture_camera_->GetTransformationMatrix());
return rtabmap::glmToTransform(gesture_camera_->GetTransformationMatrix());
}
void Scene::OnTouchEvent(int touch_count,
@@ -658,6 +701,11 @@ void Scene::setTraceVisible(bool visible)
traceVisible_ = visible;
}
void Scene::setFrustumVisible(bool visible)
{
frustumVisible_ = visible;
}
//Should only be called in OpenGL thread!
void Scene::addMarker(
int id,
@@ -728,7 +776,7 @@ void Scene::addCloud(
void Scene::addMesh(
int id,
const Mesh & mesh,
const rtabmap::Mesh & mesh,
const rtabmap::Transform & pose,
bool createWireframe)
{
@@ -847,7 +895,7 @@ void Scene::updateCloudPolygons(int id, const std::vector<pcl::Vertices> & polyg
}
}
void Scene::updateMesh(int id, const Mesh & mesh)
void Scene::updateMesh(int id, const rtabmap::Mesh & mesh)
{
std::map<int, PointCloudDrawable*>::iterator iter=pointClouds_.find(id);
if(iter != pointClouds_.end())

View File

@@ -21,7 +21,7 @@
#include <memory>
#include <set>
#include <tango_client_api.h> // NOLINT
#include "CameraMobile.h"
#include <tango-gl/axis.h>
#include <tango-gl/camera.h>
#include <tango-gl/color.h>
@@ -38,6 +38,7 @@
#include <point_cloud_drawable.h>
#include <graph_drawable.h>
#include <bounding_box_drawable.h>
#include <background_renderer.h>
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
@@ -60,7 +61,8 @@ class Scene {
int getViewPortWidth() const {return screenWidth_;}
int getViewPortHeight() const {return screenHeight_;}
void setScreenRotation(TangoSupportRotation colorCameraToDisplayRotation) {color_camera_to_display_rotation_ = colorCameraToDisplayRotation;}
rtabmap::ScreenRotation getScreenRotation() const {return color_camera_to_display_rotation_;}
void setScreenRotation(rtabmap::ScreenRotation colorCameraToDisplayRotation) {color_camera_to_display_rotation_ = colorCameraToDisplayRotation;}
void clear(); // removed all point clouds
@@ -70,15 +72,16 @@ class Scene {
// frame's timestamp.
// @param: point_cloud_vertices, point cloud's vertices of the current point
// frame.
int Render();
int Render(const float * uvsTransformed = 0, glm::mat4 arViewMatrix = glm::mat4(0), glm::mat4 arProjectionMatrix=glm::mat4(0), const rtabmap::Mesh & occlusionMesh=rtabmap::Mesh());
// Set render camera's viewing angle, first person, third person or top down.
//
// @param: camera_type, camera type includes first person, third person and
// top down
void SetCameraType(tango_gl::GestureCamera::CameraType camera_type);
tango_gl::GestureCamera::CameraType GetCameraType() const {return gesture_camera_->GetCameraType();}
void SetCameraPose(const rtabmap::Transform & pose);
void SetCameraPose(const rtabmap::Transform & pose); // opengl camera
rtabmap::Transform GetCameraPose() const {return currentPose_!=0?*currentPose_:rtabmap::Transform();}
rtabmap::Transform GetOpenGLCameraPose(float * fov = 0) const;
@@ -101,6 +104,7 @@ class Scene {
void setGraphVisible(bool visible);
void setGridVisible(bool visible);
void setTraceVisible(bool visible);
void setFrustumVisible(bool visible);
void addMarker(int id, const rtabmap::Transform & pose);
void setMarkerPose(int id, const rtabmap::Transform & pose);
@@ -115,7 +119,7 @@ class Scene {
const rtabmap::Transform & pose);
void addMesh(
int id,
const Mesh & mesh,
const rtabmap::Mesh & mesh,
const rtabmap::Transform & pose,
bool createWireframe = false);
@@ -126,7 +130,7 @@ class Scene {
bool hasTexture(int id) const;
std::set<int> getAddedClouds() const;
void updateCloudPolygons(int id, const std::vector<pcl::Vertices> & polygons);
void updateMesh(int id, const Mesh & mesh);
void updateMesh(int id, const rtabmap::Mesh & mesh);
void updateGains(int id, float gainR, float gainG, float gainB);
void setBlending(bool enabled) {blending_ = enabled;}
@@ -150,6 +154,8 @@ class Scene {
bool isLighting() const {return lighting_;}
bool isBackfaceCulling() const {return backfaceCulling_;}
BackgroundRenderer * background_renderer_;
private:
// Camera object that allows user to use touch input to interact with.
tango_gl::GestureCamera* gesture_camera_;
@@ -172,10 +178,11 @@ class Scene {
bool graphVisible_;
bool gridVisible_;
bool traceVisible_;
bool frustumVisible_;
std::map<int, tango_gl::Axis*> markers_;
TangoSupportRotation color_camera_to_display_rotation_;
rtabmap::ScreenRotation color_camera_to_display_rotation_;
std::map<int, PointCloudDrawable*> pointClouds_;

View File

@@ -18,11 +18,14 @@
namespace tango_gl {
static const float float_vertices[] = {
0.0f, 0.0f, 0.0f, -1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
1.0f, -1.0f, 0.0f, 0.0f, 0.0f, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f,
0.0f, 1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f,
1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f,
-1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f};
0.0f, 0.0f, 0.0f, -1.0f, 1.0f, -1.0f,
0.0f, 0.0f, 0.0f, 1.0f, 1.0f, -1.0f,
0.0f, 0.0f, 0.0f, -1.0f, -1.0f, -1.0f,
0.0f, 0.0f, 0.0f, 1.0f, -1.0f, -1.0f,
-1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f,
1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f,
1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f,
-1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f};
Frustum::Frustum() : Line(3.0f, GL_LINES) {
SetShader();

View File

@@ -199,8 +199,8 @@ void GestureCamera::SetCameraType(CameraType camera_index) {
SetRotation(glm::quat(1.0f, 0.0f, 0.0f, 0.0f));
cam_cur_dist_ = kThirdPersonFollow?kThirdPersonFollowCameraDist:kThirdPersonCameraDist;
anchor_offset_ = glm::vec3(0.0f,0.0f,0.0f);
cam_cur_angle_.x = -M_PI / 6.0f;
cam_cur_angle_.y = kThirdPersonFollow?0:M_PI / 4.0f;
cam_cur_angle_.x = -M_PI / 12.0f;
cam_cur_angle_.y = kThirdPersonFollow?0:M_PI / 2.0f;
cam_cur_target_rot_ = glm::quat(1,0,0,0);
StartCameraToCurrentTransform();
break;

View File

@@ -31,13 +31,17 @@ Grid::Grid(float density, int qx, int qy) : Line(1.0f, GL_LINES) {
// Horizontal line.
for (int i = 0; i < (qy + 1); i++) {
vec_vertices_.push_back(glm::vec3(-width, 0.0f, -height + i * density));
vec_vertices_.push_back(glm::vec3(width, 0.0f, -height + i * density));
for (int j = 0; j < (qx + 1); j++) {
vec_vertices_.push_back(glm::vec3(-width + j*density, 0.0f, -height + i * density));
vec_vertices_.push_back(glm::vec3(-width+ + (j+1)*density, 0.0f, -height + i * density));
}
}
for (int i = 0; i < (qx + 1); i++) {
vec_vertices_.push_back(glm::vec3(-width + i * density, 0.0f, -height));
vec_vertices_.push_back(glm::vec3(-width + i * density, 0.0f, height));
for (int j = 0; j < (qy + 1); j++) {
vec_vertices_.push_back(glm::vec3(-width + i * density, 0.0f, -height + j*density));
vec_vertices_.push_back(glm::vec3(-width + i * density, 0.0f, -height + (j+1)*density));
}
}
}
} // namespace tango_gl

View File

@@ -25,7 +25,6 @@
#include <android/log.h>
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#include <tango_support_api.h>
#include "glm/glm.hpp"
#include "glm/gtc/matrix_transform.hpp"
@@ -44,6 +43,7 @@
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN,LOG_TAG,__VA_ARGS__)
#endif
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
#define LOGF(...) __android_log_print(ANDROID_LOG_FATAL,LOG_TAG,__VA_ARGS__)
#ifndef M_PI
#define M_PI 3.1415926f
@@ -84,32 +84,6 @@ namespace util {
glm::vec3 ApplyTransform(const glm::mat4& mat, const glm::vec3& vec);
// Get the Android rotation integer value from color camera to display.
// This function is used to compute the orientation difference to handle
// the portrait and landscape mode for color camera display.
//
// @param display: integer value of display orientation, values available
// are 0, 1, 2 ,3. Followed by Android display orientation standard:
// https://developer.android.com/reference/android/view/Display.html#getRotation()
// @param color_camera: integer value of color camera oreintation, values
// available are 0, 90, 180, 270. Followed by Android camera orientation
// standard:
// https://developer.android.com/reference/android/hardware/Camera.CameraInfo.html#orientation
TangoSupportRotation GetAndroidRotationFromColorCameraToDisplay(
int display_rotation, int color_camera_rotation);
// Get the Android rotation integer value from color camera to display.
// This function is used to compute the orientation difference to handle
// the portrait and landscape mode for color camera display.
//
// @param display: the device display orientation.
// @param color_camera: integer value of color camera oreintation, values
// available are 0, 90, 180, 270. Followed by Android camera orientation
// standard:
// https://developer.android.com/reference/android/hardware/Camera.CameraInfo.html#orientation
TangoSupportRotation GetAndroidRotationFromColorCameraToDisplay(
TangoSupportRotation display_rotation, int color_camera_rotation);
} // namespace util
} // namespace tango_gl
#endif // TANGO_GL_RENDERER_GL_UTIL

View File

@@ -238,23 +238,4 @@ glm::vec3 util::ApplyTransform(const glm::mat4& mat, const glm::vec3& vec) {
return glm::vec3(mat * glm::vec4(vec, 1.0f));
}
TangoSupportRotation util::GetAndroidRotationFromColorCameraToDisplay(
int display_rotation, int color_camera_rotation) {
TangoSupportRotation r =
static_cast<TangoSupportRotation>(display_rotation);
return util::GetAndroidRotationFromColorCameraToDisplay(
r, color_camera_rotation);
}
TangoSupportRotation util::GetAndroidRotationFromColorCameraToDisplay(
TangoSupportRotation display_rotation, int color_camera_rotation) {
int color_camera_n = NormalizedColorCameraRotation(color_camera_rotation);
int ret = static_cast<int>(display_rotation) - color_camera_n;
if (ret < 0) {
ret += 4;
}
return static_cast<TangoSupportRotation>(ret % 4);
}
} // namespace tango_gl

View File

@@ -39,6 +39,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <pcl/Vertices.h>
#include <pcl/pcl_base.h>
namespace rtabmap {
class LogHandler : public UEventsHandler
{
public:
@@ -58,19 +60,23 @@ protected:
ULogEvent * logEvent = (ULogEvent*)event;
if(logEvent->getCode() == ULogger::kDebug)
{
LOGD(logEvent->getMsg().c_str());
LOGD("%s", logEvent->getMsg().c_str());
}
else if(logEvent->getCode() == ULogger::kInfo)
{
LOGI(logEvent->getMsg().c_str());
LOGI("%s", logEvent->getMsg().c_str());
}
else if(logEvent->getCode() == ULogger::kWarning)
{
LOGW(logEvent->getMsg().c_str());
LOGW("%s", logEvent->getMsg().c_str());
}
else if(logEvent->getCode() >= ULogger::kError)
{
LOGE(logEvent->getMsg().c_str());
LOGE("%s", logEvent->getMsg().c_str());
}
else if(logEvent->getCode() >= ULogger::kFatal)
{
LOGF("%s", logEvent->getMsg().c_str());
}
}
@@ -78,6 +84,11 @@ protected:
}
};
static const rtabmap::Transform optical_T_opengl(
1.0f, 0.0f, 0.0f, 0.0f,
0.0f, -1.0f, 0.0f, 0.0f,
0.0f, 0.0f, -1.0f, 0.0f);
static const rtabmap::Transform opengl_world_T_tango_world(
1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
@@ -88,20 +99,25 @@ static const rtabmap::Transform rtabmap_world_T_tango_world(
-1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f);
static const rtabmap::Transform tango_device_T_rtabmap_device(
static const rtabmap::Transform tango_device_T_rtabmap_world(
0.0f, -1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
-1.0f, 0.0f, 0.0f, 0.0f);
static const rtabmap::Transform tango_world_T_rtabmap_world(
0.0f, -1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f);
static const rtabmap::Transform opengl_world_T_rtabmap_world(
0.0f, -1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
-1.0f, 0.0f, 0.0f, 0.0f);
static const rtabmap::Transform rtabmap_device_T_opengl_device(
0.0f, 0.0f, -1.0f, 0.0f,
-1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f);
static const rtabmap::Transform rtabmap_world_T_opengl_world(
0.0f, 0.0f,-1.0f, 0.0f,
-1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f);
inline glm::mat4 glmFromTransform(const rtabmap::Transform & transform)
{
@@ -173,4 +189,81 @@ public:
cv::Mat texture;
};
typedef enum {
/// Not apply any rotation.
ROTATION_IGNORED = -1,
/// 0 degree rotation (natural orientation)
ROTATION_0 = 0,
/// 90 degree rotation.
ROTATION_90 = 1,
/// 180 degree rotation.
ROTATION_180 = 2,
/// 270 degree rotation.
ROTATION_270 = 3
} ScreenRotation;
inline int NormalizedColorCameraRotation(int camera_rotation) {
int camera_n = 0;
switch (camera_rotation) {
case 90:
camera_n = 1;
break;
case 180:
camera_n = 2;
break;
case 270:
camera_n = 3;
break;
default:
camera_n = 0;
break;
}
return camera_n;
}
// Get the Android rotation integer value from color camera to display.
// This function is used to compute the orientation difference to handle
// the portrait and landscape mode for color camera display.
//
// @param display: the device display orientation.
// @param color_camera: integer value of color camera oreintation, values
// available are 0, 90, 180, 270. Followed by Android camera orientation
// standard:
// https://developer.android.com/reference/android/hardware/Camera.CameraInfo.html#orientation
inline ScreenRotation GetAndroidRotationFromColorCameraToDisplay(
ScreenRotation display_rotation, int color_camera_rotation) {
int color_camera_n = NormalizedColorCameraRotation(color_camera_rotation);
int ret = static_cast<int>(display_rotation) - color_camera_n;
if (ret < 0) {
ret += 4;
}
return static_cast<ScreenRotation>(ret % 4);
}
// Get the Android rotation integer value from color camera to display.
// This function is used to compute the orientation difference to handle
// the portrait and landscape mode for color camera display.
//
// @param display: integer value of display orientation, values available
// are 0, 1, 2 ,3. Followed by Android display orientation standard:
// https://developer.android.com/reference/android/view/Display.html#getRotation()
// @param color_camera: integer value of color camera orientation, values
// available are 0, 90, 180, 270. Followed by Android camera orientation
// standard:
// https://developer.android.com/reference/android/hardware/Camera.CameraInfo.html#orientation
inline ScreenRotation GetAndroidRotationFromColorCameraToDisplay(
int display_rotation, int color_camera_rotation) {
ScreenRotation r =
static_cast<ScreenRotation>(display_rotation);
return GetAndroidRotationFromColorCameraToDisplay(
r, color_camera_rotation);
}
}
#endif /* UTIL_H_ */

1
app/android/libs/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
*.jar

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

View File

@@ -27,6 +27,26 @@
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<ImageButton
android:id="@+id/start_button"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:src="@drawable/start96"
android:background="@null"
android:layout_marginBottom="10dp" />
<ImageButton
android:id="@+id/stop_button"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:src="@drawable/stop96"
android:background="@null"
android:layout_marginBottom="10dp" />
<ToggleButton
android:id="@+id/wireframe_button"
@@ -80,16 +100,6 @@
android:text="@string/camera_button"
android:spinnerMode="dropdown"/>
<ToggleButton
android:id="@+id/pause_button"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:layout_marginRight="5dp"
android:layout_alignParentTop="true"
android:layout_marginTop="10dp"
android:layout_alignParentRight="true"
android:textOff="@string/pause"
android:textOn="@string/resume" />
<Button
android:id="@+id/button_shareToSketchfab"
@@ -138,7 +148,23 @@
android:paddingBottom="10dp"
android:progressDrawable="@drawable/custom_seekbar" />
<Button
android:id="@+id/button_library"
android:layout_width="match_parent"
android:layout_height="100dp"
android:layout_centerHorizontal="true"
android:layout_gravity="top"
android:layout_marginTop="100dp"
android:text="@string/library" />
<Button
android:id="@+id/button_new_scan"
android:layout_width="match_parent"
android:layout_height="100dp"
android:layout_alignLeft="@+id/button_library"
android:layout_below="@+id/button_library"
android:layout_marginTop="20dp"
android:text="@string/new_scan" />
</RelativeLayout>
</RelativeLayout>

View File

@@ -1,5 +1,13 @@
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<ListPreference
android:key="@string/pref_key_camera_driver"
android:title="@string/pref_title_camera_driver"
android:summary="@string/pref_summary_camera_driver"
android:entries="@array/pref_camera_driver_keys"
android:entryValues="@array/pref_camera_driver_values"
android:defaultValue="@string/pref_default_camera_driver"/>
<PreferenceCategory
android:title="@string/pref_title_rendering">
<ListPreference
@@ -78,7 +86,7 @@
android:title="@string/pref_title_mapping_sub"
android:summary="@string/pref_summary_mapping"
android:persistent="false">
<com.introlab.rtabmap.CustomSwitchPreference
android:key="@string/pref_key_append"
android:title="@string/pref_title_append"
@@ -89,6 +97,11 @@
android:title="@string/pref_title_resolution"
android:summary="@string/pref_summary_resolution"
android:defaultValue="@string/pref_default_resolution"/>
<com.introlab.rtabmap.CustomSwitchPreference
android:key="@string/pref_key_depth_from_motion"
android:title="@string/pref_title_depth_from_motion"
android:summary="@string/pref_summary_depth_from_motion"
android:defaultValue="@string/pref_default_depth_from_motion"/>
<com.introlab.rtabmap.CustomSwitchPreference
android:key="@string/pref_key_smoothing"
android:title="@string/pref_title_smoothing"

View File

@@ -62,20 +62,11 @@
android:checked="true"
android:text="Draft Mode" />
<LinearLayout
<Button
android:id="@+id/button_ok"
android:layout_width="match_parent"
android:layout_height="0dip"
android:layout_weight="1"
android:gravity="right|bottom"
android:orientation="horizontal" >
<Button
android:id="@+id/button_ok"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0.06"
android:text="Upload" />
</LinearLayout>
android:layout_height="wrap_content"
android:text="Upload" />
</LinearLayout>
</ScrollView>

View File

@@ -7,9 +7,12 @@
<item android:id="@+id/mesh" android:title="Mesh" />
<item android:id="@+id/texture_mesh" android:checked="true" android:title="Texture Mesh" />
</group>
<item android:id="@+id/save" android:title="Save" android:showAsAction="ifRoom"/>
<item android:id="@+id/new_scan" android:title="New Scan"/>
<item android:id="@+id/open" android:title="Library" android:showAsAction="ifRoom"/>
<item android:id="@+id/save" android:title="Save"/>
<item android:id="@+id/export" android:showAsAction="ifRoom" android:title="Export">
<item android:id="@+id/export" android:title="Export">
<menu>
<item android:id="@+id/export_point_cloud_menu" android:title="Point Cloud">
<menu>
@@ -26,7 +29,7 @@
</menu>
</item>
<item android:id="@+id/post_processing" android:title="Optimize" android:showAsAction="ifRoom">
<item android:id="@+id/post_processing" android:title="Optimize">
<menu>
<item android:id="@+id/post_processing_standard" android:title="Standard Optimization" />
<item android:id="@+id/post_processing_advanced" android:title="Advanced..." >
@@ -43,8 +46,6 @@
</menu>
</item>
<item android:id="@+id/open" android:title="Open" android:showAsAction="ifRoom"/>
<item android:id="@+id/menu_rendering_settings" android:title="Visibility...">
<menu >
<group android:id="@+id/group_rendering_visibility" android:checkableBehavior="all">
@@ -68,7 +69,7 @@
</menu>
</item>
<item android:id="@+id/settings" android:title="Settings"/>
<item android:id="@+id/reset" android:title="Reset"/>
<item android:id="@+id/resume" android:title="Resume"/>
<item android:id="@+id/about" android:title="About"/>
</group>
</menu>

View File

@@ -1,4 +1,3 @@
<resources>
<dimen name="image_width">150dp</dimen>
</resources>
<resources>
<dimen name="image_width">150dp</dimen>
</resources>

View File

@@ -9,8 +9,10 @@
<string name="status">"Status: "</string>
<string name="words">"Words: "</string>
<string name="camera_button">First View</string>
<string name="pause">Pause</string>
<string name="resume">Resume</string>
<string name="library">Library</string>
<string name="new_scan">New Scan</string>
<string name="pause">Stop</string>
<string name="resume">Start</string>
<string name="backface_on">Backface</string>
<string name="backface_off">Backface</string>
<string name="light_on">Lighting</string>
@@ -63,7 +65,7 @@
<string name="pref_key_rendering_texture_decimation">pref_key_rendering_texture_decimation</string>
<string name="pref_default_rendering_texture_decimation">4</string>
<string name="pref_key_blending">pref_key_blending</string>
<string name="pref_default_blending">true</string>
<string name="pref_default_blending">false</string>
<string name="pref_key_background_color">pref_key_background_color</string>
<string name="pref_default_background_color">0.2</string>
<string name="pref_key_nodes_filtering">pref_key_nodes_filtering</string>
@@ -77,6 +79,10 @@
<string name="pref_key_fisheye">pref_key_fisheye</string>
<string name="pref_default_fisheye">false</string>
<string name="pref_key_camera_driver">pref_key_camera_driver</string>
<string name="pref_default_camera_driver">0</string>
<string name="pref_key_depth_from_motion">pref_key_depth_from_motion</string>
<string name="pref_default_depth_from_motion">false</string>
<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>
@@ -317,6 +323,10 @@
<string name="pref_summary_mapping">Advanced mapping parameters for fine tuning.</string>
<string name="pref_title_mapping_core">Core</string>
<string name="pref_title_mapping_database">Database</string>
<string name="pref_title_camera_driver">Camera Driver</string>
<string name="pref_summary_camera_driver">AR sdk use for capturing 6DoF poses and images. A TOF camera is required to record a 3D model.</string>
<string name="pref_title_depth_from_motion">Depth From Motion</string>
<string name="pref_summary_depth_from_motion">Use ARCore\'s depth API to compute depth image from motion. If the phone has a TOF camera and is supported by ARCore, results should be better. Currently supported only with ARCore NDK driver.</string>
<string name="pref_title_append">Append Mode</string>
<string name="pref_summary_append">When resuming mapping, wait for a relocalization on the current map before starting a new map.</string>
<string name="pref_title_resolution">HD Mode</string>
@@ -366,6 +376,18 @@
<string name="pref_title_db_in_memory">Database In Memory</string>
<string name="pref_summary_db_in_memory">The database is kept in RAM for fast access. Set to false to reduce RAM used at the cost of slower access. This parameter is applied on reset or when a database is opened.</string>
<string-array name="pref_camera_driver_keys">
<item>"Google Tango NDK"</item>
<item>"ARCore NDK"</item>
<item>"AREngine NDK"</item>
<item>"ARCore Java"</item>
</string-array>
<string-array name="pref_camera_driver_values">
<item>"0"</item>
<item>"1"</item>
<item>"2"</item>
<item>"3"</item>
</string-array>
<string-array name="pref_update_rate_keys">
<item>"Max"</item>
<item>"5 Hz"</item>

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="external_files" path="."/>
</paths>

View File

@@ -0,0 +1,588 @@
package com.introlab.rtabmap;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.EnumSet;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import com.google.ar.core.Camera;
import com.google.ar.core.CameraIntrinsics;
import com.google.ar.core.Config;
import com.google.ar.core.Frame;
import com.google.ar.core.ImageMetadata;
import com.google.ar.core.PointCloud;
import com.google.ar.core.Pose;
import com.google.ar.core.Session;
import com.google.ar.core.SharedCamera;
import com.google.ar.core.TrackingState;
import com.google.ar.core.exceptions.CameraNotAvailableException;
import com.google.ar.core.exceptions.NotYetAvailableException;
import com.google.ar.core.exceptions.UnavailableException;
import android.content.Context;
import android.graphics.ImageFormat;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.CaptureFailure;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.TotalCaptureResult;
import android.media.Image;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.os.Handler;
import android.os.HandlerThread;
import android.support.annotation.NonNull;
import android.util.Log;
import android.view.Surface;
public class ARCoreSharedCamera {
public static final String TAG = ARCoreSharedCamera.class.getSimpleName();
private static RTABMapActivity mActivity;
public ARCoreSharedCamera(RTABMapActivity c) {
mActivity = c;
}
// Depth TOF Image.
// Use 240 * 180 for now, hardcoded for Huawei P30 Pro
private static final int DEPTH_WIDTH = 240;
private static final int DEPTH_HEIGHT = 180;
// GL Surface used to draw camera preview image.
public GLSurfaceView surfaceView;
// ARCore session that supports camera sharing.
private Session sharedSession;
// Camera capture session. Used by both non-AR and AR modes.
private CameraCaptureSession captureSession;
// Reference to the camera system service.
private CameraManager cameraManager;
// Camera device. Used by both non-AR and AR modes.
private CameraDevice cameraDevice;
// Looper handler thread.
private HandlerThread backgroundThread;
// Looper handler.
private Handler backgroundHandler;
// ARCore shared camera instance, obtained from ARCore session that supports sharing.
private SharedCamera sharedCamera;
// Camera ID for the camera used by ARCore.
private String cameraId;
private AtomicBoolean mReady = new AtomicBoolean(false);
// Camera preview capture request builder
private CaptureRequest.Builder previewCaptureRequestBuilder;
private int cameraTextureId = -1;
// Image reader that continuously processes CPU images.
public TOF_ImageReader mTOFImageReader = new TOF_ImageReader();
private boolean mTOFAvailable = false;
public boolean isDepthSupported() {return mTOFAvailable;}
// Camera device state callback.
private final CameraDevice.StateCallback cameraDeviceCallback =
new CameraDevice.StateCallback() {
@Override
public void onOpened(@NonNull CameraDevice cameraDevice) {
Log.d(TAG, "Camera device ID " + cameraDevice.getId() + " opened.");
ARCoreSharedCamera.this.cameraDevice = cameraDevice;
createCameraPreviewSession();
}
@Override
public void onClosed(@NonNull CameraDevice cameraDevice) {
Log.d(TAG, "Camera device ID " + cameraDevice.getId() + " closed.");
ARCoreSharedCamera.this.cameraDevice = null;
}
@Override
public void onDisconnected(@NonNull CameraDevice cameraDevice) {
Log.w(TAG, "Camera device ID " + cameraDevice.getId() + " disconnected.");
cameraDevice.close();
ARCoreSharedCamera.this.cameraDevice = null;
}
@Override
public void onError(@NonNull CameraDevice cameraDevice, int error) {
Log.e(TAG, "Camera device ID " + cameraDevice.getId() + " error " + error);
cameraDevice.close();
ARCoreSharedCamera.this.cameraDevice = null;
}
};
// Repeating camera capture session state callback.
CameraCaptureSession.StateCallback cameraCaptureCallback =
new CameraCaptureSession.StateCallback() {
// Called when the camera capture session is first configured after the app
// is initialized, and again each time the activity is resumed.
@Override
public void onConfigured(@NonNull CameraCaptureSession session) {
Log.d(TAG, "Camera capture session configured.");
captureSession = session;
setRepeatingCaptureRequest();
}
@Override
public void onSurfacePrepared(
@NonNull CameraCaptureSession session, @NonNull Surface surface) {
Log.d(TAG, "Camera capture surface prepared.");
}
@Override
public void onReady(@NonNull CameraCaptureSession session) {
Log.d(TAG, "Camera capture session ready.");
}
@Override
public void onActive(@NonNull CameraCaptureSession session) {
Log.d(TAG, "Camera capture session active.");
resumeARCore();
}
@Override
public void onClosed(@NonNull CameraCaptureSession session) {
Log.d(TAG, "Camera capture session closed.");
}
@Override
public void onConfigureFailed(@NonNull CameraCaptureSession session) {
Log.e(TAG, "Failed to configure camera capture session.");
}
};
// Repeating camera capture session capture callback.
private final CameraCaptureSession.CaptureCallback captureSessionCallback =
new CameraCaptureSession.CaptureCallback() {
@Override
public void onCaptureCompleted(
@NonNull CameraCaptureSession session,
@NonNull CaptureRequest request,
@NonNull TotalCaptureResult result) {
Log.i(TAG, "onCaptureCompleted");
}
//@Override // android 23
public void onCaptureBufferLost(
@NonNull CameraCaptureSession session,
@NonNull CaptureRequest request,
@NonNull Surface target,
long frameNumber) {
Log.e(TAG, "onCaptureBufferLost: " + frameNumber);
}
@Override
public void onCaptureFailed(
@NonNull CameraCaptureSession session,
@NonNull CaptureRequest request,
@NonNull CaptureFailure failure) {
Log.e(TAG, "onCaptureFailed: " + failure.getFrameNumber() + " " + failure.getReason());
}
@Override
public void onCaptureSequenceAborted(
@NonNull CameraCaptureSession session, int sequenceId) {
Log.e(TAG, "onCaptureSequenceAborted: " + sequenceId + " " + session);
}
};
private void resumeARCore() {
// Ensure that session is valid before triggering ARCore resume. Handles the case where the user
// manually uninstalls ARCore while the app is paused and then resumes.
if (sharedSession == null) {
return;
}
try {
Log.i(TAG, "Resume ARCore.");
// Resume ARCore.
sharedSession.resume();
// Set capture session callback while in AR mode.
sharedCamera.setCaptureCallback(captureSessionCallback, backgroundHandler);
} catch (CameraNotAvailableException e) {
Log.e(TAG, "Failed to resume ARCore session", e);
return;
}
}
// Called when starting non-AR mode or switching to non-AR mode.
// Also called when app starts in AR mode, or resumes in AR mode.
private void setRepeatingCaptureRequest() {
try {
captureSession.setRepeatingRequest(
previewCaptureRequestBuilder.build(), captureSessionCallback, backgroundHandler);
} catch (CameraAccessException e) {
Log.e(TAG, "Failed to set repeating request", e);
}
}
private void createCameraPreviewSession() {
Log.e(TAG, "createCameraPreviewSession: " + "starting camera preview session.");
try {
// Note that isGlAttached will be set to true in AR mode in onDrawFrame().
sharedSession.setCameraTextureName(cameraTextureId);
// Create an ARCore compatible capture request using `TEMPLATE_RECORD`.
previewCaptureRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);
// Build surfaces list, starting with ARCore provided surfaces.
List<Surface> surfaceList = sharedCamera.getArCoreSurfaces();
Log.e(TAG, " createCameraPreviewSession: " + "surfaceList: sharedCamera.getArCoreSurfaces(): " + surfaceList.size());
// Add a CPU image reader surface. On devices that don't support CPU image access, the image
// may arrive significantly later, or not arrive at all.
if (mTOFAvailable) surfaceList.add(mTOFImageReader.imageReader.getSurface());
// Surface list should now contain three surfacemReadymReadys:
// 0. sharedCamera.getSurfaceTexture()
// 1. …
// 2. depthImageReader.getSurface()
// Add ARCore surfaces and CPU image surface targets.
for (Surface surface : surfaceList) {
previewCaptureRequestBuilder.addTarget(surface);
}
// Wrap our callback in a shared camera callback.
CameraCaptureSession.StateCallback wrappedCallback = sharedCamera.createARSessionStateCallback(cameraCaptureCallback, backgroundHandler);
// Create camera capture session for camera preview using ARCore wrapped callback.
cameraDevice.createCaptureSession(surfaceList, wrappedCallback, backgroundHandler);
mReady.set(true);
} catch (CameraAccessException e) {
Log.e(TAG, "CameraAccessException", e);
}
}
// Start background handler thread, used to run callbacks without blocking UI thread.
private void startBackgroundThread() {
backgroundThread = new HandlerThread("sharedCameraBackground");
backgroundThread.start();
backgroundHandler = new Handler(backgroundThread.getLooper());
mTOFImageReader.startBackgroundThread();
}
// Stop background handler thread.
private void stopBackgroundThread() {
if (backgroundThread != null) {
backgroundThread.quitSafely();
try {
backgroundThread.join();
backgroundThread = null;
backgroundHandler = null;
} catch (InterruptedException e) {
Log.e(TAG, "Interrupted while trying to join background handler thread", e);
}
}
mTOFImageReader.stopBackgroundThread();
}
private long mPreviousTime = 0;
// Perform various checks, then open camera device and create CPU image reader.
public boolean openCamera() {
close();
startBackgroundThread();
mPreviousTime = System.currentTimeMillis();
if(cameraTextureId == -1)
{
int[] textures = new int[1];
GLES20.glGenTextures(1, textures, 0);
cameraTextureId = textures[0];
}
Log.v(TAG + " opencamera: ", "Perform various checks, then open camera device and create CPU image reader.");
// Don't open camera if already opened.
if (cameraDevice != null) {
return false;
}
if (sharedSession == null) {
try {
// Create ARCore session that supports camera sharing.
sharedSession = new Session(mActivity, EnumSet.of(Session.Feature.SHARED_CAMERA));
} catch (UnavailableException e) {
Log.e(TAG, "Failed to create ARCore session that supports camera sharing", e);
return false;
}
// Enable auto focus mode while ARCore is running.
Config config = sharedSession.getConfig();
config.setFocusMode(Config.FocusMode.FIXED);
config.setUpdateMode(Config.UpdateMode.LATEST_CAMERA_IMAGE);
config.setPlaneFindingMode(Config.PlaneFindingMode.DISABLED);
config.setLightEstimationMode(Config.LightEstimationMode.DISABLED);
//config.setCloudAnchorMode(Config.CloudAnchorMode.ENABLED);
sharedSession.configure(config);
}
// Store the ARCore shared camera reference.
sharedCamera = sharedSession.getSharedCamera();
// Store the ID of the camera used by ARCore.
cameraId = sharedSession.getCameraConfig().getCameraId();
initCamera(mActivity, cameraId, 1);
ArrayList<String> resolutions;
mTOFAvailable = false;
resolutions = getResolutions(mActivity, cameraId, ImageFormat.DEPTH16);
if (resolutions != null) {
for( String temp : resolutions) {
Log.e(TAG + "DEPTH16 resolution: ", temp);
};
if (resolutions.size()>0) mTOFAvailable = true;
}
// Color CPU Image.
// Use the currently configured CPU image size.
//Size desiredCPUImageSize = sharedSession.getCameraConfig().getImageSize();
if (mTOFAvailable) mTOFImageReader.createImageReader(DEPTH_WIDTH, DEPTH_HEIGHT);
// When ARCore is running, make sure it also updates our CPU image surface.
if (mTOFAvailable) {
sharedCamera.setAppSurfaces(this.cameraId, Arrays.asList(mTOFImageReader.imageReader.getSurface()));
}
try {
// Wrap our callback in a shared camera callback.
CameraDevice.StateCallback wrappedCallback = sharedCamera.createARDeviceStateCallback(cameraDeviceCallback, backgroundHandler);
// Store a reference to the camera system service.
cameraManager = (CameraManager) mActivity.getSystemService(Context.CAMERA_SERVICE);
// Get the characteristics for the ARCore camera.
//CameraCharacteristics characteristics = cameraManager.getCameraCharacteristics(this.cameraId);
// Open the camera device using the ARCore wrapped callback.
cameraManager.openCamera(cameraId, wrappedCallback, backgroundHandler);
} catch (CameraAccessException e) {
Log.e(TAG, "Failed to open camera", e);
return false;
} catch (IllegalArgumentException e) {
Log.e(TAG, "Failed to open camera", e);
return false;
} catch (SecurityException e) {
Log.e(TAG, "Failed to open camera", e);
return false;
}
Log.i(TAG, " opencamera: TOF_available: " + mTOFAvailable);
return true;
}
// Close the camera device.
public void close() {
if (sharedSession != null) {
sharedSession.pause();
}
if (captureSession != null) {
captureSession.close();
captureSession = null;
}
if (cameraDevice != null) {
cameraDevice.close();
}
if (mTOFImageReader.imageReader != null) {
mTOFImageReader.imageReader.close();
mTOFImageReader.imageReader = null;
}
if(cameraTextureId>=0)
{
GLES20.glDeleteTextures(1, new int[] {cameraTextureId}, 0);
}
stopBackgroundThread();
}
/*************************************************** ONDRAWFRAME ARCORE ************************************************************* */
// Draw frame when in AR mode. Called on the GL thread.
public void updateGL() throws CameraNotAvailableException {
if(!mReady.get())
{
return;
}
if (mTOFAvailable && mTOFImageReader.frameCount == 0) return;
// Perform ARCore per-frame update.
Frame frame = null;
try {
frame = sharedSession.update();
} catch (Exception e) {
e.printStackTrace();
return;
}
Camera camera = null;
if (frame != null) {
camera = frame.getCamera();
}else
{
return;
}
if (camera == null) return;
// If not tracking, don't draw 3D objects.
if (camera.getTrackingState() == TrackingState.PAUSED) return;
if (frame.getTimestamp() != 0) {
Pose pose = camera.getPose();
if(!RTABMapActivity.DISABLE_LOG) Log.d(TAG, String.format("pose=%f %f %f q=%f %f %f %f", pose.tx(), pose.ty(), pose.tz(), pose.qx(), pose.qy(), pose.qz(), pose.qw()));
RTABMapLib.postCameraPoseEvent(RTABMapActivity.nativeApplication, pose.tx(), pose.ty(), pose.tz(), pose.qx(), pose.qy(), pose.qz(), pose.qw());
int rateMs = 100; // send images at most 10 Hz
if(System. currentTimeMillis() - mPreviousTime < rateMs)
{
return;
}
mPreviousTime = System. currentTimeMillis();
CameraIntrinsics intrinsics = camera.getImageIntrinsics();
try{
Image image = frame.acquireCameraImage();
PointCloud cloud = frame.acquirePointCloud();
FloatBuffer points = cloud.getPoints();
if (image.getFormat() != ImageFormat.YUV_420_888) {
throw new IllegalArgumentException(
"Expected image in YUV_420_888 format, got format " + image.getFormat());
}
if(!RTABMapActivity.DISABLE_LOG)
{
for(int i =0;i<image.getPlanes().length;++i)
{
Log.d(TAG, String.format("Plane[%d] pixel stride = %d, row stride = %d", i, image.getPlanes()[i].getPixelStride(), image.getPlanes()[i].getRowStride()));
}
}
float[] fl = intrinsics.getFocalLength();
float[] pp = intrinsics.getPrincipalPoint();
if(!RTABMapActivity.DISABLE_LOG) Log.d(TAG, String.format("fx=%f fy=%f cx=%f cy=%f", fl[0], fl[1], pp[0], pp[1]));
ByteBuffer y = image.getPlanes()[0].getBuffer().asReadOnlyBuffer();
ByteBuffer u = image.getPlanes()[1].getBuffer().asReadOnlyBuffer();
ByteBuffer v = image.getPlanes()[2].getBuffer().asReadOnlyBuffer();
double stamp = (double)image.getTimestamp()/10e8;
if(!RTABMapActivity.DISABLE_LOG) Log.d(TAG, String.format("RGB %dx%d len=%dbytes format=%d =%f",
image.getWidth(), image.getHeight(), y.limit(), image.getFormat(), stamp));
if(mTOFAvailable)
{
if(!RTABMapActivity.DISABLE_LOG) Log.d(TAG, String.format("Depth %dx%d len=%dbytes format=%d stamp=%f",
mTOFImageReader.WIDTH, mTOFImageReader.HEIGHT, mTOFImageReader.depth16_raw.limit(), ImageFormat.DEPTH16, (double)mTOFImageReader.timestamp/10e9));
RTABMapLib.postOdometryEvent(
RTABMapActivity.nativeApplication,
pose.tx(), pose.ty(), pose.tz(), pose.qx(), pose.qy(), pose.qz(), pose.qw(),
fl[0], fl[1], pp[0], pp[1], stamp,
y, u, v, y.limit(), image.getWidth(), image.getHeight(), image.getFormat(),
mTOFImageReader.depth16_raw, mTOFImageReader.depth16_raw.limit(), mTOFImageReader.WIDTH, mTOFImageReader.HEIGHT, ImageFormat.DEPTH16,
points, points.limit()/4);
}
else
{
ByteBuffer bb = ByteBuffer.allocate(0);
RTABMapLib.postOdometryEvent(
RTABMapActivity.nativeApplication,
pose.tx(), pose.ty(), pose.tz(), pose.qx(), pose.qy(), pose.qz(), pose.qw(),
fl[0], fl[1], pp[0], pp[1], stamp,
y, u, v, y.limit(), image.getWidth(), image.getHeight(), image.getFormat(),
bb, 0, 0, 0, ImageFormat.DEPTH16,
points, points.limit()/4);
}
image.close();
cloud.close();
} catch (NotYetAvailableException e) {
}
}
}
/********************************************************************************************************************* */
/*************************************************** End ************************************************************* */
/********************************************************************************************************************* */
public ArrayList<String> getResolutions (Context context, String cameraId,int imageFormat){
Log.v(TAG + "getResolutions:", " cameraId:" + cameraId + " imageFormat: " + imageFormat);
ArrayList<String> output = new ArrayList<String>();
try {
CameraManager manager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
for (android.util.Size s : characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP).getOutputSizes(imageFormat)) {
output.add(s.getWidth() + "x" + s.getHeight());
}
} catch (Exception e) {
e.printStackTrace();
}
return output;
}
public void initCamera (Context context, String cameraId,int index){
boolean ok = false;
try {
int current = 0;
CameraManager manager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
for (android.util.Size s : characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP).getOutputSizes(ImageFormat.DEPTH16)) {
ok = true;
if (current == index)
break;
else ;
current++;
}
} catch (Exception e) {
e.printStackTrace();
}
if (!ok) {
Log.e(TAG + " initCamera", "Depth sensor not found!");
}
}
}

View File

@@ -0,0 +1,79 @@
/*
* Copyright 2018 Google Inc. All Rights Reserved.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.introlab.rtabmap;
import android.Manifest;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.provider.Settings;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
/** Helper to ask camera permission. */
public class PermissionHelper {
public static final int CAMERA_CODE = 0;
public static final int READ_EXTERNAL_STORAGE_CODE = 1;
public static final int WRITE_EXTERNAL_STORAGE_CODE = 2;
public static final int INTERNET_CODE = 3;
public static final int ACCESS_NETWORK_STATE_CODE = 4;
public static final int ACCESS_FINE_LOCATION_CODE = 5;
public static final int ACCESS_WIFI_STATE_CODE = 6;
/** Check to see we have the necessary permissions for this app. */
public static boolean hasPermission(Activity activity, String permission) {
return ContextCompat.checkSelfPermission(activity, permission) == PackageManager.PERMISSION_GRANTED;
}
/** Check to see we have the necessary permissions for this app, and ask for them if we don't. */
public static void requestPermission(Activity activity, String permission) {
int requestCode = -1;
if (permission == Manifest.permission.CAMERA) {
requestCode = CAMERA_CODE;
} else if(permission == Manifest.permission.READ_EXTERNAL_STORAGE) {
requestCode = READ_EXTERNAL_STORAGE_CODE;
} else if(permission == Manifest.permission.WRITE_EXTERNAL_STORAGE) {
requestCode = WRITE_EXTERNAL_STORAGE_CODE;
} else if(permission == Manifest.permission.INTERNET) {
requestCode = INTERNET_CODE;
} else if(permission == Manifest.permission.ACCESS_NETWORK_STATE) {
requestCode = ACCESS_NETWORK_STATE_CODE;
} else if(permission == Manifest.permission.ACCESS_FINE_LOCATION) {
requestCode = ACCESS_FINE_LOCATION_CODE;
} else if(permission == Manifest.permission.ACCESS_WIFI_STATE) {
requestCode = ACCESS_WIFI_STATE_CODE;
}
if(requestCode >=0)
{
ActivityCompat.requestPermissions(
activity, new String[] {permission}, requestCode);
}
}
/** Check to see if we need to show the rationale for this permission. */
public static boolean shouldShowRequestPermissionRationale(Activity activity, String permission) {
return ActivityCompat.shouldShowRequestPermissionRationale(activity, permission);
}
/** Launch Application Setting to grant permission. */
public static void launchPermissionSettings(Activity activity) {
Intent intent = new Intent();
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
intent.setData(Uri.fromParts("package", activity.getPackageName(), null));
activity.startActivity(intent);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,10 @@
package com.introlab.rtabmap;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import android.app.Activity;
import android.content.Context;
import android.os.IBinder;
import android.view.KeyEvent;
import android.util.Log;
@@ -15,7 +20,7 @@ public class RTABMapLib
// the correct library first.
if (TangoInitializationHelper.loadTangoSharedLibrary() ==
TangoInitializationHelper.ARCH_ERROR) {
Log.e(RTABMapActivity.class.getSimpleName(), "ERROR! Unable to load libtango_client_api.so!");
Log.w(RTABMapActivity.class.getSimpleName(), "WArning! Unable to load libtango_client_api.so! This can be safely ignored if RTAB-Map NDK is not build with tango support.");
}
System.loadLibrary("NativeRTABMap");
}
@@ -23,88 +28,85 @@ public class RTABMapLib
// Initialize the Tango Service, this function starts the communication
// between the application and Tango Service.
// The activity object is used for checking if the API version is outdated.
public static native void onCreate(RTABMapActivity activity);
public static native long createNativeApplication(RTABMapActivity activity);
public static native void setScreenRotation(int displayRotation, int cameraRotation);
public static native void destroyNativeApplication(long nativeApplication);
public static native int openDatabase(String databasePath, boolean databaseInMemory, boolean optimize);
public static native int openDatabase2(String databaseSource, String databasePath, boolean databaseInMemory, boolean optimize);
public static native void setScreenRotation(long nativeApplication, int displayRotation, int cameraRotation);
/*
* Called when the Tango service is connected.
*
* @param binder The native binder object.
*/
public static native boolean onTangoServiceConnected(IBinder binder);
// Release all non OpenGl resources that are allocated from the program.
public static native void onPause();
public static native int openDatabase(long nativeApplication, String databasePath, boolean databaseInMemory, boolean optimize);
public static native int openDatabase2(long nativeApplication, String databaseSource, String databasePath, boolean databaseInMemory, boolean optimize);
public static native boolean isBuiltWith(long nativeApplication, int cameraDriver);
public static native boolean startCamera(long nativeApplication, IBinder binder, Context context, Activity activity, int driver);
public static native void stopCamera(long nativeApplication);
// Allocate OpenGL resources for rendering.
public static native void initGlContent();
public static native void initGlContent(long nativeApplication);
// Setup the view port width and height.
public static native void setupGraphic(int width, int height);
public static native void setupGraphic(long nativeApplication, int width, int height);
// Main render loop.
public static native int render();
public static native int render(long nativeApplication);
// Set the render camera's viewing angle:
// first person, third person, or top down.
public static native void setCamera(int cameraIndex);
public static native void setCamera(long nativeApplication, int cameraIndex);
// Pass touch events to the native layer.
public static native void onTouchEvent(int touchCount, int event0,
public static native void onTouchEvent(long nativeApplication, int touchCount, int event0,
float x0, float y0, float x1, float y1);
public static native void setPausedMapping(boolean paused);
public static native void setOnlineBlending(boolean enabled);
public static native void setMapCloudShown(boolean shown);
public static native void setOdomCloudShown(boolean shown);
public static native void setMeshRendering(boolean enabled, boolean withTexture);
public static native void setLocalizationMode(boolean enabled);
public static native void setTrajectoryMode(boolean enabled);
public static native void setGraphOptimization(boolean enabled);
public static native void setNodesFiltering(boolean enabled);
public static native void setGraphVisible(boolean visible);
public static native void setGridVisible(boolean visible);
public static native void setRawScanSaved(boolean enabled);
public static native void setFullResolution(boolean enabled);
public static native void setSmoothing(boolean enabled);
public static native void setCameraColor(boolean enabled);
public static native void setAppendMode(boolean enabled);
public static native void setDataRecorderMode(boolean enabled);
public static native void setMaxCloudDepth(float value);
public static native void setMinCloudDepth(float value);
public static native void setPointSize(float value);
public static native void setFOV(float value);
public static native void setOrthoCropFactor(float value);
public static native void setGridRotation(float value);
public static native void setLighting(boolean enabled);
public static native void setBackfaceCulling(boolean enabled);
public static native void setWireframe(boolean enabled);
public static native void setCloudDensityLevel(int value);
public static native void setMeshAngleTolerance(float value);
public static native void setMeshTriangleSize(int value);
public static native void setClusterRatio(float value);
public static native void setMaxGainRadius(float value);
public static native void setRenderingTextureDecimation(int value);
public static native void setBackgroundColor(float gray);
public static native int setMappingParameter(String key, String value);
public static native void setPausedMapping(long nativeApplication, boolean paused);
public static native void setOnlineBlending(long nativeApplication, boolean enabled);
public static native void setMapCloudShown(long nativeApplication, boolean shown);
public static native void setOdomCloudShown(long nativeApplication, boolean shown);
public static native void setMeshRendering(long nativeApplication, boolean enabled, boolean withTexture);
public static native void setLocalizationMode(long nativeApplication, boolean enabled);
public static native void setTrajectoryMode(long nativeApplication, boolean enabled);
public static native void setGraphOptimization(long nativeApplication, boolean enabled);
public static native void setNodesFiltering(long nativeApplication, boolean enabled);
public static native void setGraphVisible(long nativeApplication, boolean visible);
public static native void setGridVisible(long nativeApplication, boolean visible);
public static native void setRawScanSaved(long nativeApplication, boolean enabled);
public static native void setFullResolution(long nativeApplication, boolean enabled);
public static native void setSmoothing(long nativeApplication, boolean enabled);
public static native void setDepthFromMotion(long nativeApplication, boolean enabled);
public static native void setCameraColor(long nativeApplication, boolean enabled);
public static native void setAppendMode(long nativeApplication, boolean enabled);
public static native void setDataRecorderMode(long nativeApplication, boolean enabled);
public static native void setMaxCloudDepth(long nativeApplication, float value);
public static native void setMinCloudDepth(long nativeApplication, float value);
public static native void setPointSize(long nativeApplication, float value);
public static native void setFOV(long nativeApplication, float value);
public static native void setOrthoCropFactor(long nativeApplication, float value);
public static native void setGridRotation(long nativeApplication, float value);
public static native void setLighting(long nativeApplication, boolean enabled);
public static native void setBackfaceCulling(long nativeApplication, boolean enabled);
public static native void setWireframe(long nativeApplication, boolean enabled);
public static native void setCloudDensityLevel(long nativeApplication, int value);
public static native void setMeshAngleTolerance(long nativeApplication, float value);
public static native void setMeshTriangleSize(long nativeApplication, int value);
public static native void setClusterRatio(long nativeApplication, float value);
public static native void setMaxGainRadius(long nativeApplication, float value);
public static native void setRenderingTextureDecimation(long nativeApplication, int value);
public static native void setBackgroundColor(long nativeApplication, float gray);
public static native int setMappingParameter(long nativeApplication, String key, String value);
public static native void setGPS(
long nativeApplication,
double stamp,
double longitude,
double latitude,
double altitude,
double accuracy,
double bearing);
public static native void addEnvSensor(int type, float value);
public static native void addEnvSensor(long nativeApplication, int type, float value);
public static native void resetMapping();
public static native void save(String outputDatabasePath);
public static native void cancelProcessing();
public static native void save(long nativeApplication, String outputDatabasePath);
public static native void cancelProcessing(long nativeApplication);
public static native boolean exportMesh(
long nativeApplication,
float cloudVoxelSize,
boolean regenerateCloud,
boolean meshing,
@@ -121,15 +123,24 @@ public class RTABMapLib
float optimizedMaxTextureDistance,
int optimizedMinTextureClusterSize,
boolean blockRendering);
public static native boolean writeExportedMesh(String directory, String name);
public static native boolean postExportation(boolean visualize);
public static native int postProcessing(int approach);
public static native boolean writeExportedMesh(long nativeApplication, String directory, String name);
public static native boolean postExportation(long nativeApplication, boolean visualize);
public static native int postProcessing(long nativeApplication, int approach);
public static native String getStatus();
public static native int getTotalNodes();
public static native int getTotalWords();
public static native int getTotalPoints();
public static native float getUpdateTime();
public static native int getLoopClosureId();
public static native String getStatus(long nativeApplication);
public static native int getTotalNodes(long nativeApplication);
public static native int getTotalWords(long nativeApplication);
public static native int getTotalPoints(long nativeApplication);
public static native float getUpdateTime(long nativeApplication);
public static native int getLoopClosureId(long nativeApplication);
public static native void postCameraPoseEvent(long nativeApplication, float x, float y, float z, float qx, float qy, float qz, float qw);
public static native void postOdometryEvent(long nativeApplication,
float x, float y, float z, float qx, float qy, float qz, float qw,
float fx, float fy, float cx, float cy,
double stamp,
ByteBuffer yPlane, ByteBuffer uPlane, ByteBuffer vPlane, int yPlaneLen, int rgbWidth, int rgbHeight, int rgbFormat,
ByteBuffer depth, int depthLen, int depthWidth, int depthHeight, int depthFormat,
FloatBuffer points, int pointsLen);
}

View File

@@ -43,6 +43,7 @@ public class Renderer implements GLSurfaceView.Renderer {
private float mSurfaceHeight = 0.0f;
private float mTextColor = 1.0f;
private int mOffset = 0;
private ARCoreSharedCamera mCamera = null;
private Vector<TextObject> mTexts;
@@ -71,91 +72,109 @@ public class Renderer implements GLSurfaceView.Renderer {
{
mOffset = offset;
}
public void setCamera(ARCoreSharedCamera camera)
{
mCamera = camera;
}
// Render loop of the Gl context.
public void onDrawFrame(GL10 useGLES20instead) {
try
{
final int value = RTABMapLib.render();
if(mTextManager!=null)
synchronized (this) {
if(mActivity.nativeApplication != 0)
{
if(mTextChanged)
try
{
mTextChanged = false;
Vector<TextObject> txtcollection = new Vector<TextObject>();
mTextLock.lock();
try {
if(mTexts.size() > 0)
{
txtcollection.addAll(mTexts);
}
} finally {
mTextLock.unlock();
}
// Prepare the text for rendering
mTextManager.PrepareDraw(txtcollection);
}
float[] mvp = new float[16];
Matrix.translateM(mvp, 0, mtrxProjectionAndView, 0, 0, mOffset, 0);
mTextManager.Draw(mvp);
}
if(value != 0 && mProgressDialog != null && mProgressDialog.isShowing())
{
mActivity.runOnUiThread(new Runnable() {
public void run() {
if(!RTABMapActivity.DISABLE_LOG) Log.i("RTABMapActivity", "Renderer: dismiss dialog, value received=" + String.valueOf(value));
mProgressDialog.dismiss();
mActivity.resetNoTouchTimer();
}
});
}
if(value==-1)
{
mActivity.runOnUiThread(new Runnable() {
public void run() {
if(mToast!=null)
{
mToast.makeText(mActivity, String.format("Out of Memory!"), Toast.LENGTH_SHORT).show();
}
}
});
}
else if(value==-2)
{
mActivity.runOnUiThread(new Runnable() {
public void run() {
if(mToast!=null)
{
mToast.makeText(mActivity, String.format("Rendering Error!"), Toast.LENGTH_SHORT).show();
}
}
});
}
}
catch(final Exception e)
{
mActivity.runOnUiThread(new Runnable() {
public void run() {
if(mToast!=null)
if(mCamera!=null)
{
mToast.makeText(mActivity, String.format("Rendering error! %s", e.getMessage()), Toast.LENGTH_SHORT).show();
mCamera.updateGL();
}
final int value = RTABMapLib.render(mActivity.nativeApplication);
if(mTextManager!=null)
{
if(mTextChanged)
{
mTextChanged = false;
Vector<TextObject> txtcollection = new Vector<TextObject>();
mTextLock.lock();
try {
if(mTexts.size() > 0)
{
txtcollection.addAll(mTexts);
}
} finally {
mTextLock.unlock();
}
// Prepare the text for rendering
mTextManager.PrepareDraw(txtcollection);
}
float[] mvp = new float[16];
Matrix.translateM(mvp, 0, mtrxProjectionAndView, 0, 0, mOffset, 0);
mTextManager.Draw(mvp);
}
if(value != 0 && mProgressDialog != null && mProgressDialog.isShowing())
{
mActivity.runOnUiThread(new Runnable() {
public void run() {
if(!RTABMapActivity.DISABLE_LOG) Log.i("RTABMapActivity", "Renderer: dismiss dialog, value received=" + String.valueOf(value));
mProgressDialog.dismiss();
mActivity.resetNoTouchTimer();
}
});
}
if(value==-1)
{
mActivity.runOnUiThread(new Runnable() {
public void run() {
if(mToast!=null)
{
mToast.makeText(mActivity, String.format("Out of Memory!"), Toast.LENGTH_SHORT).show();
}
}
});
}
else if(value==-2)
{
mActivity.runOnUiThread(new Runnable() {
public void run() {
if(mToast!=null)
{
mToast.makeText(mActivity, String.format("Rendering Error!"), Toast.LENGTH_SHORT).show();
}
}
});
}
}
});
catch(final Exception e)
{
mActivity.runOnUiThread(new Runnable() {
public void run() {
if(mToast!=null)
{
mToast.makeText(mActivity, String.format("Rendering error! %s", e.getMessage()), Toast.LENGTH_SHORT).show();
}
}
});
}
}
}
}
// Called when the surface size changes.
public void onSurfaceChanged(GL10 useGLES20instead, int width, int height) {
RTABMapLib.setupGraphic(width, height);
if(mActivity.nativeApplication!=0)
{
RTABMapLib.setupGraphic(mActivity.nativeApplication, width, height);
}
mSurfaceHeight = (float)height;
@@ -180,7 +199,10 @@ public class Renderer implements GLSurfaceView.Renderer {
// Called when the surface is created or recreated.
public void onSurfaceCreated(GL10 useGLES20instead, EGLConfig config) {
RTABMapLib.initGlContent();
if(mActivity.nativeApplication != 0)
{
RTABMapLib.initGlContent(mActivity.nativeApplication);
}
// Create our text manager
mTextManager = new TextManager(mActivity);

View File

@@ -7,11 +7,14 @@ import java.util.Arrays;
import java.util.Iterator;
import java.util.Map.Entry;
import android.Manifest;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.preference.CheckBoxPreference;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.PreferenceActivity;
@@ -19,6 +22,7 @@ import android.text.InputType;
import android.view.WindowManager;
import android.view.inputmethod.EditorInfo;
import android.widget.EditText;
import android.widget.Toast;
public class SettingsActivity extends PreferenceActivity implements OnSharedPreferenceChangeListener {
@@ -34,7 +38,7 @@ public class SettingsActivity extends PreferenceActivity implements OnSharedPref
@Override
public boolean onPreferenceClick(Preference preference) {
getPreferenceScreen().getSharedPreferences().edit().clear().commit();
recreate();
return true;
@@ -184,7 +188,31 @@ public class SettingsActivity extends PreferenceActivity implements OnSharedPref
}
});
Preference buttonGPS = findPreference(getString(R.string.pref_key_gps_saved));
buttonGPS.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
if(((CustomSwitchPreference)preference).isChecked())
{
if (!PermissionHelper.hasPermission(getActivity(), Manifest.permission.ACCESS_FINE_LOCATION)) {
((CustomSwitchPreference)preference).setChecked(false);
PermissionHelper.requestPermission(getActivity(), Manifest.permission.ACCESS_FINE_LOCATION);
return false;
}
}
return true;
}
});
if(((CustomSwitchPreference)buttonGPS).isChecked())
{
if (!PermissionHelper.hasPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)) {
((CustomSwitchPreference)buttonGPS).setChecked(false);
PermissionHelper.requestPermission(this, Manifest.permission.ACCESS_FINE_LOCATION);
}
}
((Preference)findPreference(getString(R.string.pref_key_camera_driver))).setSummary("("+((ListPreference)findPreference(getString(R.string.pref_key_camera_driver))).getEntry() + ") "+getString(R.string.pref_summary_camera_driver));
((Preference)findPreference(getString(R.string.pref_key_density))).setSummary("("+((ListPreference)findPreference(getString(R.string.pref_key_density))).getEntry() + ") "+getString(R.string.pref_summary_density));
((Preference)findPreference(getString(R.string.pref_key_depth))).setSummary("("+((ListPreference)findPreference(getString(R.string.pref_key_depth))).getEntry() + ") "+getString(R.string.pref_summary_depth));
((Preference)findPreference(getString(R.string.pref_key_min_depth))).setSummary("("+((ListPreference)findPreference(getString(R.string.pref_key_min_depth))).getEntry() + ") "+getString(R.string.pref_summary_min_depth));
@@ -228,6 +256,7 @@ public class SettingsActivity extends PreferenceActivity implements OnSharedPref
Preference pref = findPreference(key);
if (pref instanceof ListPreference) {
if(key.compareTo(getString(R.string.pref_key_camera_driver))==0) pref.setSummary("("+ ((ListPreference)pref).getEntry() + ") "+getString(R.string.pref_summary_camera_driver));
if(key.compareTo(getString(R.string.pref_key_density))==0) pref.setSummary("("+ ((ListPreference)pref).getEntry() + ") "+getString(R.string.pref_summary_density));
if(key.compareTo(getString(R.string.pref_key_depth))==0)
{
@@ -331,4 +360,28 @@ public class SettingsActivity extends PreferenceActivity implements OnSharedPref
}
ed.commit(); //save it.
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] results) {
switch (requestCode) {
case PermissionHelper.ACCESS_FINE_LOCATION_CODE: {
// If request is cancelled, the result arrays are empty.
if (results.length > 0 && results[0] == PackageManager.PERMISSION_GRANTED) {
// permission was granted, yay! Do the
// contacts-related task you need to do.
Preference buttonGPS = findPreference(getString(R.string.pref_key_gps_saved));
((CustomSwitchPreference)buttonGPS).setChecked(true);
} else {
// permission denied, boo! Disable the
// functionality that depends on this permission.
Toast.makeText(this, "Location permission is needed to use GPS functionality", Toast.LENGTH_LONG).show();
if (!PermissionHelper.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_FINE_LOCATION)) {
PermissionHelper.launchPermissionSettings(this); // Permission denied with checking "Do not ask again".
}
}
return;
}
}
}
}

View File

@@ -169,8 +169,8 @@ public class SketchfabActivity extends Activity implements OnClickListener {
WebView web;
mAuthDialog = new Dialog(this);
mAuthDialog.setCancelable(false);
mAuthDialog.setCanceledOnTouchOutside(false);
mAuthDialog.setCancelable(true);
mAuthDialog.setCanceledOnTouchOutside(true);
mAuthDialog.setContentView(R.layout.auth_dialog);
web = (WebView)mAuthDialog.findViewById(R.id.webv);
web.setWebContentsDebuggingEnabled(!RTABMapActivity.DISABLE_LOG);
@@ -245,7 +245,7 @@ public class SketchfabActivity extends Activity implements OnClickListener {
File exportDir = new File(mWorkingDirectory + RTABMapActivity.RTABMAP_EXPORT_DIR);
exportDir.mkdirs();
if(RTABMapLib.writeExportedMesh(mWorkingDirectory + RTABMapActivity.RTABMAP_TMP_DIR, RTABMapActivity.RTABMAP_TMP_FILENAME))
if(RTABMapLib.writeExportedMesh(RTABMapActivity.nativeApplication, mWorkingDirectory + RTABMapActivity.RTABMAP_TMP_DIR, RTABMapActivity.RTABMAP_TMP_FILENAME))
{
String[] files = new String[0];
// verify if we have all files

View File

@@ -0,0 +1,87 @@
package com.introlab.rtabmap;
import android.graphics.ImageFormat;
import android.media.Image;
import android.media.ImageReader;
import android.os.Handler;
import android.os.HandlerThread;
import android.util.Log;
import java.nio.ByteBuffer;
public class TOF_ImageReader implements ImageReader.OnImageAvailableListener {
public int WIDTH;
public int HEIGHT;
public ImageReader imageReader;
public int frameCount = 0;
public long timestamp;
// Looper handler thread.
private HandlerThread backgroundThread;
// Looper handler.
private Handler backgroundHandler;
public ByteBuffer depth16_raw;
TOF_ImageReader(){
}
public void createImageReader(int width, int height){
this.WIDTH = width;
this.HEIGHT = height;
this.imageReader =
ImageReader.newInstance(
width,
height,
ImageFormat.DEPTH16,
2);
this.imageReader.setOnImageAvailableListener(this, this.backgroundHandler);
}
// CPU image reader callback.
@Override
public void onImageAvailable(ImageReader imageReader) {
Image image = imageReader.acquireLatestImage();
if (image == null) {
Log.w("RTABMapActivity", "onImageAvailable: Skipping null image.");
return;
}
else{
if(image.getFormat() == ImageFormat.DEPTH16){
this.timestamp = image.getTimestamp();
depth16_raw = image.getPlanes()[0].getBuffer().asReadOnlyBuffer();
// copy raw undecoded DEPTH16 format depth data to NativeBuffer
frameCount++;
}
else{
Log.w("RTABMapActivity", "onImageAvailable: depth image not in DEPTH16 format, skipping image");
}
}
image.close();
}
// Start background handler thread, used to run callbacks without blocking UI thread.
public void startBackgroundThread() {
this.backgroundThread = new HandlerThread("DepthDecoderThread");
this.backgroundThread.start();
this.backgroundHandler = new Handler(backgroundThread.getLooper());
}
// Stop background handler thread.
public void stopBackgroundThread() {
if (this.backgroundThread != null) {
this.backgroundThread.quitSafely();
try {
this.backgroundThread.join();
this.backgroundThread = null;
this.backgroundHandler = null;
} catch (InterruptedException e) {
Log.e("RTABMapActivity", "Interrupted while trying to join depth background handler thread", e);
}
}
}
}

View File

@@ -17,6 +17,7 @@ import android.graphics.Typeface;
import android.opengl.GLES20;
import android.opengl.GLUtils;
import android.text.TextPaint;
import android.util.Log;
public class TextManager {
@@ -336,6 +337,8 @@ public class TextManager {
float y = val.y;
String text = val.text;
Log.i("RTABMapActivity", String.format("convertTextToTriangleInfo() set status=%s", text));
// Create
for(int j=0; j<text.length(); j++)
{

View File

@@ -137,6 +137,16 @@ IF(BUILD_AS_BUNDLE AND (APPLE OR WIN32))
DESTINATION ${openni2_dest_dir}
COMPONENT runtime)
ENDIF(OpenNI2_FOUND)
IF(k4a_FOUND)
# Install needed depthengine_2_0.dll
IF(WIN32)
file(TO_CMAKE_PATH "$ENV{K4A_ROOT_DIR}" ENV_K4A_ROOT_DIR)
INSTALL(FILES "${ENV_K4A_ROOT_DIR}/tools/depthengine_2_0.dll"
DESTINATION ${plugin_dest_dir}
COMPONENT runtime)
ENDIF(WIN32)
ENDIF(k4a_FOUND)
# Install needed Qt plugins by copying directories from the qt installation
# One can cull what gets copied by using 'REGEX "..." EXCLUDE'
@@ -156,26 +166,28 @@ IF(BUILD_AS_BUNDLE AND (APPLE OR WIN32))
list(GET loc_list 1 plugin_type)
IF(NOT plugin_root)
get_filename_component(plugin_root ${plugin_dir} DIRECTORY)
ENDIF(NOT plugin_root)
#MESSAGE(STATUS "Qt5 plugin \"${plugin_loc}\" installed in \"${plugin_dest_dir}/plugins${plugin_type}\"")
ENDIF(NOT plugin_root)
#MESSAGE(STATUS "Qt5 plugin \"${plugin_loc}\" installed in \"${plugin_dest_dir}/plugins${plugin_type}\"")
INSTALL(FILES ${plugin_loc}
DESTINATION ${plugin_dest_dir}/plugins${plugin_type}
COMPONENT runtime)
endforeach()
IF(WIN32)
IF(NOT Qt5Widgets_VERSION VERSION_LESS 5.10.0)
SET(plugin_loc "${plugin_root}/styles/qwindowsvistastyle.dll")
IF(EXISTS ${plugin_loc})
get_filename_component(plugin_dir ${plugin_loc} DIRECTORY)
string(REPLACE "plugins" ";" loc_list ${plugin_dir})
list(GET loc_list 1 plugin_type)
INSTALL(FILES ${plugin_loc}
DESTINATION ${plugin_dest_dir}/plugins${plugin_type}
COMPONENT runtime)
#MESSAGE(STATUS "Qt5 plugin \"${plugin_loc}\" installed in \"${plugin_dest_dir}/plugins${plugin_type}\"")
ENDIF(EXISTS ${plugin_loc})
ENDIF(NOT Qt5Widgets_VERSION VERSION_LESS 5.10.0)
ENDIF(WIN32)
endforeach()
IF(NOT Qt5Widgets_VERSION VERSION_LESS 5.10.0)
IF(WIN32)
SET(plugin_loc "${plugin_root}/styles/qwindowsvistastyle.dll")
ELSEIF(APPLE)
SET(plugin_loc "${plugin_root}/styles/libqmacstyle.dylib")
ENDIF()
IF(EXISTS ${plugin_loc})
get_filename_component(plugin_dir ${plugin_loc} DIRECTORY)
string(REPLACE "plugins" ";" loc_list ${plugin_dir})
list(GET loc_list 1 plugin_type)
INSTALL(FILES ${plugin_loc}
DESTINATION ${plugin_dest_dir}/plugins${plugin_type}
COMPONENT runtime)
#MESSAGE(STATUS "Qt5 plugin \"${plugin_loc}\" installed in \"${plugin_dest_dir}/plugins${plugin_type}\"")
ENDIF(EXISTS ${plugin_loc})
ENDIF(NOT Qt5Widgets_VERSION VERSION_LESS 5.10.0)
ENDIF()
# install a qt.conf file

View File

@@ -0,0 +1,31 @@
# - Find ARCore
# This module finds an installed ARCore client C-API package.
#
# It sets the following variables:
# ARCore_FOUND - Set to false, or undefined, if ARCore isn't found.
# ARCore_INCLUDE_DIRS - The ARCore include directory.
# ARCore_LIBRARIES - The ARCore library to link against.
FIND_PATH(ARCore_INCLUDE_DIR arcore_c_api.h)
FIND_LIBRARY(ARCore_c_LIBRARY NAMES arcore_sdk_c PATH_SUFFIXES ${ANDROID_ABI})
FIND_LIBRARY(ARCore_jni_LIBRARY NAMES arcore_sdk_jni PATH_SUFFIXES ${ANDROID_ABI})
IF (ARCore_INCLUDE_DIR AND ARCore_c_LIBRARY AND ARCore_jni_LIBRARY)
SET(ARCore_FOUND TRUE)
SET(ARCore_INCLUDE_DIRS ${ARCore_INCLUDE_DIR})
SET(ARCore_LIBRARIES ${ARCore_c_LIBRARY} ${ARCore_jni_LIBRARY})
ENDIF (ARCore_INCLUDE_DIR AND ARCore_c_LIBRARY AND ARCore_jni_LIBRARY)
IF (ARCore_FOUND)
# show which ARCore was found only if not quiet
IF (NOT ARCore_FIND_QUIETLY)
MESSAGE(STATUS "Found ARCore: ${ARCore_INCLUDE_DIRS}")
ENDIF (NOT ARCore_FIND_QUIETLY)
ELSE (ARCore_FOUND)
# fatal error if ARCore is required but not found
IF (ARCore_FIND_REQUIRED)
MESSAGE(FATAL_ERROR "Could not find ARCore (client and/or support libraries)")
ENDIF (ARCore_FIND_REQUIRED)
ENDIF (ARCore_FOUND)

View File

@@ -0,0 +1,32 @@
# - Find AREngine
# This module finds an installed AREngine client C-API package.
#
# It sets the following variables:
# AREngine_FOUND - Set to false, or undefined, if AREngine isn't found.
# AREngine_INCLUDE_DIRS - The AREngine include directory.
# AREngine_LIBRARIES - The AREngine library to link against.
FIND_PATH(AREngine_INCLUDE_DIR huawei_arengine_interface.h)
FIND_LIBRARY(AREngine_impl_LIBRARY NAMES huawei_arengine_impl PATH_SUFFIXES ${ANDROID_ABI})
FIND_LIBRARY(AREngine_jni_LIBRARY NAMES huawei_arengine_jni PATH_SUFFIXES ${ANDROID_ABI})
FIND_LIBRARY(AREngine_ndk_LIBRARY NAMES huawei_arengine_ndk PATH_SUFFIXES ${ANDROID_ABI})
IF (AREngine_INCLUDE_DIR AND AREngine_impl_LIBRARY AND AREngine_jni_LIBRARY AND AREngine_ndk_LIBRARY)
SET(AREngine_FOUND TRUE)
SET(AREngine_INCLUDE_DIRS ${AREngine_INCLUDE_DIR})
SET(AREngine_LIBRARIES ${AREngine_impl_LIBRARY} ${AREngine_jni_LIBRARY} ${AREngine_ndk_LIBRARY})
ENDIF (AREngine_INCLUDE_DIR AND AREngine_impl_LIBRARY AND AREngine_jni_LIBRARY AND AREngine_ndk_LIBRARY)
IF (AREngine_FOUND)
# show which AREngine was found only if not quiet
IF (NOT AREngine_FIND_QUIETLY)
MESSAGE(STATUS "Found AREngine: ${AREngine_INCLUDE_DIRS}")
ENDIF (NOT AREngine_FIND_QUIETLY)
ELSE (AREngine_FOUND)
# fatal error if AREngine is required but not found
IF (AREngine_FIND_REQUIRED)
MESSAGE(FATAL_ERROR "Could not find AREngine's impl, jni and ndk libraries)")
ENDIF (AREngine_FIND_REQUIRED)
ENDIF (AREngine_FOUND)

View File

@@ -0,0 +1,37 @@
# - Find FastCV (https://developer.qualcomm.com/software/fastcv-sdk)
#
# It sets the following variables:
# FastCV_FOUND - Set to false, or undefined, if FastCV isn't found.
# FastCV_INCLUDE_DIRS - The FastCV include directory.
# FastCV_LIBRARIES - The FastCV library to link against.
IF(NOT WIN32 AND NOT APPLE)
EXECUTE_PROCESS( COMMAND uname -m COMMAND tr -d '\n' OUTPUT_VARIABLE ARCHITECTURE )
MESSAGE( STATUS "Architecture: ${ARCHITECTURE}" )
# Currently only tested on aarch64!
IF(${ARCHITECTURE} STREQUAL "aarch64")
find_path(FastCV_INCLUDE_DIRS NAMES fastcv.h PATH_SUFFIXES fastcv)
find_library(FastCV_LIBRARY NAMES fastcvopt fastcv)
ENDIF(${ARCHITECTURE} STREQUAL "aarch64")
ENDIF(NOT WIN32 AND NOT APPLE)
IF (FastCV_INCLUDE_DIRS AND FastCV_LIBRARY)
SET(FastCV_FOUND TRUE)
ENDIF (FastCV_INCLUDE_DIRS AND FastCV_LIBRARY)
IF (FastCV_FOUND)
SET(FastCV_LIBRARIES ${FastCV_LIBRARY})
# show which RealSense was found only if not quiet
IF (NOT FastCV_FIND_QUIETLY)
MESSAGE(STATUS "Found FastCV: ${FastCV_LIBRARIES}")
ENDIF (NOT FastCV_FIND_QUIETLY)
ELSE (FastCV_FOUND)
# fatal error if RealSense is required but not found
IF (FastCV_FIND_REQUIRED)
MESSAGE(FATAL_ERROR "Could not find FastCV")
ENDIF (FastCV_FIND_REQUIRED)
ENDIF (FastCV_FOUND)

View File

@@ -0,0 +1,34 @@
# - Find K4A
# This module finds an kinect 4 azure SDK
#
# It sets the following variables:
# K4A_FOUND - Set to false, or undefined, if K4A isn't found.
# K4A_INCLUDE_DIRS - The K4A include directory.
# K4A_LIBRARIES - The K4A library to link against.
find_library(K4A_LIBRARY NAMES k4a NO_DEFAULT_PATH PATHS $ENV{K4A_ROOT_DIR}/sdk/windows-desktop/amd64/release/lib)
find_library(K4ARECORD_LIBRARY NAMES k4arecord NO_DEFAULT_PATH PATHS $ENV{K4A_ROOT_DIR}/sdk/windows-desktop/amd64/release/lib)
find_path(K4A_INCLUDE_DIR NAMES k4a/k4a.h PATHS $ENV{K4A_ROOT_DIR}/sdk/include)
IF (K4A_INCLUDE_DIR AND K4A_LIBRARY AND K4ARECORD_LIBRARY)
SET(K4A_FOUND TRUE)
SET(K4A_INCLUDE_DIRS ${K4A_INCLUDE_DIR})
SET(K4A_LIBRARIES ${K4A_LIBRARY} ${K4ARECORD_LIBRARY})
# Compatibility with linux names
SET(k4a_LIBRARIES ${K4A_LIBRARIES})
SET(k4a_INCLUDE_DIRS ${K4A_INCLUDE_DIRS})
SET(k4a_FOUND ${K4A_FOUND})
ENDIF (K4A_INCLUDE_DIR AND K4A_LIBRARY AND K4ARECORD_LIBRARY)
IF (K4A_FOUND)
# show which K4A was found only if not quiet
IF (NOT K4A_FIND_QUIETLY)
MESSAGE(STATUS "Found K4A: ${K4A_LIBRARIES}")
ENDIF (NOT K4A_FIND_QUIETLY)
ELSE (K4A_FOUND)
# fatal error if K4A is required but not found
IF (K4A_FIND_REQUIRED)
MESSAGE(FATAL_ERROR "Could not find K4A (Kinect for Azure SDK)")
ENDIF (K4A_FIND_REQUIRED)
ENDIF (K4A_FOUND)

View File

@@ -61,6 +61,8 @@ public:
cv::Mat generatePrediction(const Memory * memory, const std::vector<int> & ids);
unsigned long getMemoryUsed() const;
private:
cv::Mat updatePrediction(const cv::Mat & oldPrediction,
const Memory * memory,

View File

@@ -53,6 +53,7 @@ public:
virtual ~Camera();
SensorData takeImage(CameraInfo * info = 0);
bool initFromFile(const std::string & calibrationPath);
virtual bool init(const std::string & calibrationFolder = ".", const std::string & cameraName = "") = 0;
virtual bool isCalibrated() const = 0;
virtual std::string getSerial() const = 0;
@@ -73,7 +74,7 @@ protected:
*
* @param imageRate : image/second , 0 for fast as the camera can
*/
Camera(float imageRate = 0, const Transform & localTransform = Transform::getIdentity());
Camera(float imageRate = 0, const Transform & localTransform = CameraModel::opticalRotation());
/**
* returned rgb and depth images should be already rectified if calibration was loaded

View File

@@ -37,6 +37,13 @@ namespace rtabmap {
class RTABMAP_EXP CameraModel
{
public:
/**
* Optical rotation used to transform image coordinate frame (x->right, y->down, z->forward)
* to robot coordinate frame (x->forward, y->left, z->up).
*/
static Transform opticalRotation() {return Transform(0,0,1,0, -1,0,0,0, 0,-1,0,0);}
public:
CameraModel();
// K is the camera intrinsic 3x3 CV_64FC1
@@ -50,7 +57,7 @@ public:
const cv::Mat & D,
const cv::Mat & R,
const cv::Mat & P,
const Transform & localTransform = Transform::getIdentity());
const Transform & localTransform = opticalRotation());
// minimal
CameraModel(
@@ -58,7 +65,7 @@ public:
double fy,
double cx,
double cy,
const Transform & localTransform = Transform::getIdentity(),
const Transform & localTransform = opticalRotation(),
double Tx = 0.0f,
const cv::Size & imageSize = cv::Size(0,0));
// minimal to be saved
@@ -68,14 +75,14 @@ public:
double fy,
double cx,
double cy,
const Transform & localTransform = Transform::getIdentity(),
const Transform & localTransform = opticalRotation(),
double Tx = 0.0f,
const cv::Size & imageSize = cv::Size(0,0));
virtual ~CameraModel() {}
void initRectificationMap();
bool isRectificationMapInitialized() {return !mapX_.empty() && !mapY_.empty();}
bool isRectificationMapInitialized() const {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;}
@@ -113,6 +120,12 @@ public:
int imageWidth() const {return imageSize_.width;}
int imageHeight() const {return imageSize_.height;}
double fovX() const; // in radians
double fovY() const; // in radians
double horizontalFOV() const; // in degrees
double verticalFOV() const; // in degrees
bool load(const std::string & filePath);
bool load(const std::string & directory, const std::string & cameraName);
bool save(const std::string & directory) const;
std::vector<unsigned char> serialize() const;
@@ -122,9 +135,6 @@ public:
CameraModel scaled(double scale) const;
CameraModel roi(const cv::Rect & roi) const;
double horizontalFOV() const; // in degrees
double verticalFOV() const; // in degrees
// For depth images, your should use cv::INTER_NEAREST
cv::Mat rectifyImage(const cv::Mat & raw, int interpolation = cv::INTER_LINEAR) const;
cv::Mat rectifyDepth(const cv::Mat & raw) const;
@@ -148,5 +158,7 @@ private:
Transform localTransform_;
};
RTABMAP_EXP std::ostream& operator<<(std::ostream& os, const CameraModel& model);
} /* namespace rtabmap */
#endif /* CAMERAMODEL_H_ */

View File

@@ -36,4 +36,5 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <rtabmap/core/camera/CameraRealSense.h>
#include <rtabmap/core/camera/CameraRealSense2.h>
#include <rtabmap/core/camera/CameraRGBDImages.h>
#include <rtabmap/core/camera/CameraK4A.h>

View File

@@ -33,3 +33,4 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <rtabmap/core/camera/CameraStereoVideo.h>
#include <rtabmap/core/camera/CameraStereoZed.h>
#include <rtabmap/core/camera/CameraStereoTara.h>
#include <rtabmap/core/camera/CameraMyntEye.h>

View File

@@ -72,6 +72,15 @@ public:
void enableIMUFiltering(int filteringStrategy=1, const ParametersMap & parameters = ParametersMap());
void disableIMUFiltering();
RTABMAP_DEPRECATED(void setScanParameters(
bool fromDepth,
int downsampleStep, // decimation of the depth image in case the scan is from depth image
float rangeMin,
float rangeMax,
float voxelSize,
int normalsK,
int normalsRadius,
bool forceGroundNormalsUp) , "Use new version of this function with groundNormalsUp=0.8 for forceGroundNormalsUp=True and groundNormalsUp=0.0 for forceGroundNormalsUp=False.");
void setScanParameters(
bool fromDepth,
int downsampleStep=1, // decimation of the depth image in case the scan is from depth image
@@ -80,17 +89,7 @@ public:
float voxelSize = 0.0f,
int normalsK = 0,
int normalsRadius = 0.0f,
bool forceGroundNormalsUp = false)
{
_scanFromDepth = fromDepth;
_scanDownsampleStep=downsampleStep;
_scanRangeMin = rangeMin;
_scanRangeMax = rangeMax;
_scanVoxelSize = voxelSize;
_scanNormalsK = normalsK;
_scanNormalsRadius = normalsRadius;
_scanForceGroundNormalsUp = forceGroundNormalsUp;
}
float groundNormalsUp = 0.0f);
void postUpdate(SensorData * data, CameraInfo * info = 0) const;
@@ -119,7 +118,7 @@ private:
float _scanVoxelSize;
int _scanNormalsK;
float _scanNormalsRadius;
bool _scanForceGroundNormalsUp;
float _scanForceGroundNormalsUp;
StereoDense * _stereoDense;
clams::DiscreteDepthDistortionModel * _distortionModel;
bool _bilateralFiltering;

View File

@@ -70,6 +70,7 @@ public:
virtual void parseParameters(const ParametersMap & parameters);
virtual bool isInMemory() const {return _url.empty();}
const std::string & getUrl() const {return _url;}
const std::string & getTargetVersion() const {return _targetVersion;}
void beginTransaction() const;
void commit() const;
@@ -96,10 +97,11 @@ public:
float cellSize,
const cv::Point3f & viewpoint);
void updateDepthImage(int nodeId, const cv::Mat & image);
void updateLaserScan(int nodeId, const LaserScan & scan);
public:
void addInfoAfterRun(int stMemSize, int lastSignAdded, int processMemUsed, int databaseMemUsed, int dictionarySize, const ParametersMap & parameters) const;
void addStatistics(const Statistics & statistics) const;
void addStatistics(const Statistics & statistics, bool saveWmState) const;
void savePreviewImage(const cv::Mat & image) const;
cv::Mat loadPreviewImage() const;
void saveOptimizedPoses(const std::map<int, Transform> & optimizedPoses, const Transform & lastlocalizationPose) const;
@@ -108,7 +110,7 @@ public:
cv::Mat load2DMap(float & xMin, float & yMin, float & cellSize) const;
void saveOptimizedMesh(
const cv::Mat & cloud,
const std::vector<std::vector<std::vector<unsigned int> > > & polygons = std::vector<std::vector<std::vector<unsigned int> > >(), // Textures -> polygons -> vertices
const std::vector<std::vector<std::vector<RTABMAP_PCL_INDEX> > > & polygons = std::vector<std::vector<std::vector<RTABMAP_PCL_INDEX> > >(), // Textures -> polygons -> vertices
#if PCL_VERSION_COMPARE(>=, 1, 8, 0)
const std::vector<std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > > & texCoords = std::vector<std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > >(), // Textures -> uv coords for each vertex of the polygons
#else
@@ -116,7 +118,7 @@ public:
#endif
const cv::Mat & textures = cv::Mat()) const; // concatenated textures (assuming square textures with all same size);
cv::Mat loadOptimizedMesh(
std::vector<std::vector<std::vector<unsigned int> > > * polygons = 0,
std::vector<std::vector<std::vector<RTABMAP_PCL_INDEX> > > * polygons = 0,
#if PCL_VERSION_COMPARE(>=, 1, 8, 0)
std::vector<std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > > * texCoords = 0,
#else
@@ -130,7 +132,7 @@ public:
bool openConnection(const std::string & url, bool overwritten = false);
void closeConnection(bool save = true, const std::string & outputUrl = "");
bool isConnected() const;
long getMemoryUsed() const; // In bytes
unsigned long getMemoryUsed() const; // In bytes
std::string getDatabaseVersion() const;
long getNodesMemoryUsed() const;
long getLinksMemoryUsed() const;
@@ -156,11 +158,13 @@ public:
// Load objects
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);
void loadLastNodes(std::list<Signature *> & signatures) const; // returned signatures must be freed after usage
Signature * loadSignature(int id, bool * loadedFromTrash = 0); // returned signature must be freed after usage, call loadSignatures() instead if more than one signature should be loaded
void loadSignatures(const std::list<int> & ids, std::list<Signature *> & signatures, std::set<int> * loadedFromTrash = 0); // returned signatures must be freed after usage
void loadWords(const std::set<int> & wordIds, std::list<VisualWord *> & vws); // returned words must be freed after usage
// Specific queries...
void loadNodeData(Signature * signature, bool images = true, bool scan = true, bool userData = true, bool occupancyGrid = true) const;
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;
@@ -172,6 +176,7 @@ public:
void getAllNodeIds(std::set<int> & ids, bool ignoreChildren = false, bool ignoreBadSignatures = false) const;
void getAllLinks(std::multimap<int, Link> & links, bool ignoreNullLinks = true, bool withLandmarks = false) const;
void getLastNodeId(int & id) const;
void getLastMapId(int & mapId) const;
void getLastWordId(int & id) const;
void getInvertedIndexNi(int signatureId, int & ni) const;
void getNodesObservingLandmark(int landmarkId, std::map<int, Link> & nodes) const;
@@ -184,7 +189,7 @@ protected:
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;
virtual long getMemoryUsedQuery() const = 0; // In bytes
virtual unsigned long getMemoryUsedQuery() const = 0; // In bytes
virtual bool getDatabaseVersionQuery(std::string & version) const = 0;
virtual long getNodesMemoryUsedQuery() const = 0;
virtual long getLinksMemoryUsedQuery() const = 0;
@@ -219,18 +224,22 @@ protected:
virtual void updateLinkQuery(const Link & link) const = 0;
virtual void updateOccupancyGridQuery(
int nodeId,
const cv::Mat & ground,
const cv::Mat & obstacles,
const cv::Mat & empty,
float cellSize,
const cv::Point3f & viewpoint) const = 0;
int nodeId,
const cv::Mat & ground,
const cv::Mat & obstacles,
const cv::Mat & empty,
float cellSize,
const cv::Point3f & viewpoint) const = 0;
virtual void updateDepthImageQuery(
int nodeId,
const cv::Mat & image) const = 0;
int nodeId,
const cv::Mat & image) const = 0;
virtual void addStatisticsQuery(const Statistics & statistics) const = 0;
virtual void updateLaserScanQuery(
int nodeId,
const LaserScan & scan) const = 0;
virtual void addStatisticsQuery(const Statistics & statistics, bool saveWmState) 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;
@@ -239,7 +248,7 @@ protected:
virtual cv::Mat load2DMapQuery(float & xMin, float & yMin, float & cellSize) const = 0;
virtual void saveOptimizedMeshQuery(
const cv::Mat & cloud,
const std::vector<std::vector<std::vector<unsigned int> > > & polygons,
const std::vector<std::vector<std::vector<RTABMAP_PCL_INDEX> > > & polygons,
#if PCL_VERSION_COMPARE(>=, 1, 8, 0)
const std::vector<std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > > & texCoords,
#else
@@ -247,7 +256,7 @@ protected:
#endif
const cv::Mat & textures) const = 0;
virtual cv::Mat loadOptimizedMeshQuery(
std::vector<std::vector<std::vector<unsigned int> > > * polygons,
std::vector<std::vector<std::vector<RTABMAP_PCL_INDEX> > > * polygons,
#if PCL_VERSION_COMPARE(>=, 1, 8, 0)
std::vector<std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > > * texCoords,
#else
@@ -269,7 +278,7 @@ protected:
virtual void getLastNodeIdsQuery(std::set<int> & ids) 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, bool withLandmarks) const = 0;
virtual void getLastIdQuery(const std::string & tableName, int & id) const = 0;
virtual void getLastIdQuery(const std::string & tableName, int & id, const std::string & fieldName="id") const = 0;
virtual void getInvertedIndexNiQuery(int signatureId, int & ni) const = 0;
virtual void getNodesObservingLandmarkQuery(int landmarkId, std::map<int, Link> & nodes) const = 0;
virtual void getNodeIdByLabelQuery(const std::string & label, int & id) const = 0;
@@ -292,6 +301,7 @@ private:
USemaphore _addSem;
double _emptyTrashesTime;
std::string _url;
std::string _targetVersion;
bool _timestampUpdate;
};

View File

@@ -54,7 +54,7 @@ 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;
virtual long getMemoryUsedQuery() const; // In bytes
virtual unsigned long getMemoryUsedQuery() const; // In bytes
virtual bool getDatabaseVersionQuery(std::string & version) const;
virtual long getNodesMemoryUsedQuery() const;
virtual long getLinksMemoryUsedQuery() const;
@@ -100,7 +100,11 @@ protected:
int nodeId,
const cv::Mat & image) const;
virtual void addStatisticsQuery(const Statistics & statistics) const;
void updateLaserScanQuery(
int nodeId,
const LaserScan & scan) const;
virtual void addStatisticsQuery(const Statistics & statistics, bool saveWmState) 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;
@@ -109,7 +113,7 @@ protected:
virtual cv::Mat load2DMapQuery(float & xMin, float & yMin, float & cellSize) const;
virtual void saveOptimizedMeshQuery(
const cv::Mat & cloud,
const std::vector<std::vector<std::vector<unsigned int> > > & polygons,
const std::vector<std::vector<std::vector<RTABMAP_PCL_INDEX> > > & polygons,
#if PCL_VERSION_COMPARE(>=, 1, 8, 0)
const std::vector<std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > > & texCoords,
#else
@@ -117,7 +121,7 @@ protected:
#endif
const cv::Mat & textures) const;
virtual cv::Mat loadOptimizedMeshQuery(
std::vector<std::vector<std::vector<unsigned int> > > * polygons,
std::vector<std::vector<std::vector<RTABMAP_PCL_INDEX> > > * polygons,
#if PCL_VERSION_COMPARE(>=, 1, 8, 0)
std::vector<std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > > * texCoords,
#else
@@ -139,7 +143,7 @@ protected:
virtual void getLastNodeIdsQuery(std::set<int> & ids) const;
virtual void getAllNodeIdsQuery(std::set<int> & ids, bool ignoreChildren, bool ignoreBadSignatures) const;
virtual void getAllLinksQuery(std::multimap<int, Link> & links, bool ignoreNullLinks, bool withLandmarks) const;
virtual void getLastIdQuery(const std::string & tableName, int & id) const;
virtual void getLastIdQuery(const std::string & tableName, int & id, const std::string & fieldName="id") const;
virtual void getInvertedIndexNiQuery(int signatureId, int & ni) const;
virtual void getNodesObservingLandmarkQuery(int landmarkId, std::map<int, Link> & nodes) const;
virtual void getNodeIdByLabelQuery(const std::string & label, int & id) const;
@@ -150,20 +154,24 @@ private:
std::string queryStepImage() const;
std::string queryStepDepth() const;
std::string queryStepDepthUpdate() const;
std::string queryStepScanUpdate() const;
std::string queryStepSensorData() const;
std::string queryStepLinkUpdate() const;
std::string queryStepLink() const;
std::string queryStepWordsChanged() const;
std::string queryStepKeypoint() const;
std::string queryStepGlobalDescriptor() const;
std::string queryStepOccupancyGridUpdate() const;
void stepNode(sqlite3_stmt * ppStmt, const Signature * s) const;
void stepImage(sqlite3_stmt * ppStmt, int id, const cv::Mat & imageBytes) const;
void stepDepth(sqlite3_stmt * ppStmt, const SensorData & sensorData) const;
void stepDepthUpdate(sqlite3_stmt * ppStmt, int nodeId, const cv::Mat & imageCompressed) const;
void stepScanUpdate(sqlite3_stmt * ppStmt, int nodeId, const LaserScan & image) const;
void stepSensorData(sqlite3_stmt * ppStmt, const SensorData & sensorData) const;
void stepLink(sqlite3_stmt * ppStmt, const Link & link) const;
void stepWordsChanged(sqlite3_stmt * ppStmt, int signatureId, int oldWordId, int newWordId) const;
void stepKeypoint(sqlite3_stmt * ppStmt, int signatureId, int wordId, const cv::KeyPoint & kp, const cv::Point3f & pt, const cv::Mat & descriptor) const;
void stepKeypoint(sqlite3_stmt * ppStmt, int nodeID, int wordId, const cv::KeyPoint & kp, const cv::Point3f & pt, const cv::Mat & descriptor) const;
void stepGlobalDescriptor(sqlite3_stmt * ppStmt, int nodeId, const GlobalDescriptor & descriptor) const;
void stepOccupancyGridUpdate(sqlite3_stmt * ppStmt,
int nodeId,
const cv::Mat & ground,
@@ -181,7 +189,7 @@ protected:
std::string _version;
private:
long _memoryUsedEstimate;
unsigned long _memoryUsedEstimate;
bool _dbInMemory;
unsigned int _cacheSize;
int _journalMode;

View File

@@ -50,17 +50,17 @@ public:
bool odometryIgnored = false,
bool ignoreGoalDelay = false,
bool goalsIgnored = false,
int startIndex = 0,
int startId = 0,
int cameraIndex = -1,
int maxFrames = 0);
int stopId = 0);
DBReader(const std::list<std::string> & databasePaths,
float frameRate = 0.0f, // -1 = use Database stamps, 0 = inf
bool odometryIgnored = false,
bool ignoreGoalDelay = false,
bool goalsIgnored = false,
int startIndex = 0,
int startId = 0,
int cameraIndex = -1,
int maxFrames = 0);
int stopId = 0);
virtual ~DBReader();
virtual bool init(
@@ -82,8 +82,8 @@ private:
bool _odometryIgnored;
bool _ignoreGoalDelay;
bool _goalsIgnored;
int _startIndex;
int _maxFrames;
int _startId;
int _stopId;
int _cameraIndex;
DBDriver * _dbDriver;
@@ -95,7 +95,6 @@ private:
double _previousStamp;
int _previousMapID;
bool _calibrated;
int _framesPublished;
};
} /* namespace rtabmap */

View File

@@ -29,6 +29,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "rtabmap/core/RtabmapExp.h" // DLL export/import defines
#include "rtabmap/core/Parameters.h"
#include "rtabmap/utilite/UStl.h"
#include <opencv2/core/core.hpp>
#include <opencv2/features2d/features2d.hpp>
#include <pcl/point_cloud.h>
@@ -75,8 +76,8 @@ public:
static cv::Mat findFFromWords(
const std::list<std::pair<int, std::pair<cv::KeyPoint, cv::KeyPoint> > > & pairs, // id, kpt1, kpt2
std::vector<uchar> & status,
double ransacParam1 = 3.0,
double ransacParam2 = 0.99);
double ransacReprojThreshold = 3.0,
double ransacConfidence = 0.99);
// assume a canonical camera (without K)
static void findRTFromP(
@@ -91,41 +92,133 @@ public:
* if a=[1 2 3 4 6], b=[1 2 4 5 6], results= [(1,1) (2,2) (4,4) (6,6)]
* realPairsCount = 4
*/
template<typename T>
static int findPairs(
const std::map<int, cv::KeyPoint> & wordsA,
const std::map<int, cv::KeyPoint> & wordsB,
std::list<std::pair<int, std::pair<cv::KeyPoint, cv::KeyPoint> > > & pairs,
bool ignoreNegativeIds = true);
const std::map<int, T> & wordsA,
const std::map<int, T> & wordsB,
std::list<std::pair<int, std::pair<T, T> > > & pairs,
bool ignoreNegativeIds = true)
{
int realPairsCount = 0;
pairs.clear();
for(typename std::map<int, T>::const_iterator i=wordsA.begin(); i!=wordsA.end(); ++i)
{
if(!ignoreNegativeIds || (ignoreNegativeIds && i->first>=0))
{
std::map<int, cv::KeyPoint>::const_iterator ptB = wordsB.find(i->first);
if(ptB != wordsB.end())
{
pairs.push_back(std::pair<int, std::pair<T, T> >(i->first, std::make_pair(i->second, ptB->second)));
++realPairsCount;
}
}
}
return realPairsCount;
}
/**
* if a=[1 2 3 4 6 6], b=[1 1 2 4 5 6 6], results= [(1,1a) (2,2) (4,4) (6a,6a) (6b,6b)]
* realPairsCount = 5
*/
template<typename T>
static int findPairs(
const std::multimap<int, cv::KeyPoint> & wordsA,
const std::multimap<int, cv::KeyPoint> & wordsB,
std::list<std::pair<int, std::pair<cv::KeyPoint, cv::KeyPoint> > > & pairs,
bool ignoreNegativeIds = true);
const std::multimap<int, T> & wordsA,
const std::multimap<int, T> & wordsB,
std::list<std::pair<int, std::pair<T, T> > > & pairs,
bool ignoreNegativeIds = true)
{
const std::list<int> & ids = uUniqueKeys(wordsA);
typename std::multimap<int, T>::const_iterator iterA;
typename std::multimap<int, T>::const_iterator iterB;
pairs.clear();
int realPairsCount = 0;
for(std::list<int>::const_iterator i=ids.begin(); i!=ids.end(); ++i)
{
if(!ignoreNegativeIds || (ignoreNegativeIds && *i >= 0))
{
iterA = wordsA.find(*i);
iterB = wordsB.find(*i);
while(iterA != wordsA.end() && iterB != wordsB.end() && (*iterA).first == (*iterB).first && (*iterA).first == *i)
{
pairs.push_back(std::pair<int, std::pair<T, T> >(*i, std::make_pair((*iterA).second, (*iterB).second)));
++iterA;
++iterB;
++realPairsCount;
}
}
}
return realPairsCount;
}
/**
* if a=[1 2 3 4 6 6], b=[1 1 2 4 5 6 6], results= [(2,2) (4,4)]
* realPairsCount = 5
*/
template<typename T>
static int findPairsUnique(
const std::multimap<int, cv::KeyPoint> & wordsA,
const std::multimap<int, cv::KeyPoint> & wordsB,
std::list<std::pair<int, std::pair<cv::KeyPoint, cv::KeyPoint> > > & pairs,
bool ignoreNegativeIds = true);
const std::multimap<int, T> & wordsA,
const std::multimap<int, T> & wordsB,
std::list<std::pair<int, std::pair<T, T> > > & pairs,
bool ignoreNegativeIds = true)
{
const std::list<int> & ids = uUniqueKeys(wordsA);
int realPairsCount = 0;
pairs.clear();
for(std::list<int>::const_iterator i=ids.begin(); i!=ids.end(); ++i)
{
if(!ignoreNegativeIds || (ignoreNegativeIds && *i>=0))
{
std::list<T> ptsA = uValues(wordsA, *i);
std::list<T> ptsB = uValues(wordsB, *i);
if(ptsA.size() == 1 && ptsB.size() == 1)
{
pairs.push_back(std::pair<int, std::pair<T, T> >(*i, std::pair<T, T>(ptsA.front(), ptsB.front())));
++realPairsCount;
}
else if(ptsA.size()>1 && ptsB.size()>1)
{
// just update the count
realPairsCount += ptsA.size() > ptsB.size() ? ptsB.size() : ptsA.size();
}
}
}
return realPairsCount;
}
/**
* if a=[1 2 3 4 6 6], b=[1 1 2 4 5 6 6], results= [(1,1a) (1,1b) (2,2) (4,4) (6a,6a) (6a,6b) (6b,6a) (6b,6b)]
* realPairsCount = 5
*/
template<typename T>
static int findPairsAll(
const std::multimap<int, cv::KeyPoint> & wordsA,
const std::multimap<int, cv::KeyPoint> & wordsB,
std::list<std::pair<int, std::pair<cv::KeyPoint, cv::KeyPoint> > > & pairs,
bool ignoreNegativeIds = true);
const std::multimap<int, T> & wordsA,
const std::multimap<int, T> & wordsB,
std::list<std::pair<int, std::pair<T, T> > > & pairs,
bool ignoreNegativeIds = true)
{
const std::list<int> & ids = uUniqueKeys(wordsA);
pairs.clear();
int realPairsCount = 0;;
for(std::list<int>::const_iterator iter=ids.begin(); iter!=ids.end(); ++iter)
{
if(!ignoreNegativeIds || (ignoreNegativeIds && *iter>=0))
{
std::list<T> ptsA = uValues(wordsA, *iter);
std::list<T> ptsB = uValues(wordsB, *iter);
realPairsCount += ptsA.size() > ptsB.size() ? ptsB.size() : ptsA.size();
for(typename std::list<T>::iterator jter=ptsA.begin(); jter!=ptsA.end(); ++jter)
{
for(typename std::list<T>::iterator kter=ptsB.begin(); kter!=ptsB.end(); ++kter)
{
pairs.push_back(std::pair<int, std::pair<T, T> >(*iter, std::pair<T, T>(*jter, *kter)));
}
}
}
}
return realPairsCount;
}
static cv::Mat linearLSTriangulation(
cv::Point3d u, //homogenous image point (u,v,1)

View File

@@ -61,8 +61,11 @@ typedef cv::gpu::FAST_GPU CV_FAST_GPU;
namespace cv{
namespace xfeatures2d {
class FREAK;
class DAISY;
class BriefDescriptorExtractor;
#if CV_MAJOR_VERSION < 3 || (CV_MAJOR_VERSION == 4 && CV_MINOR_VERSION <= 3) || (CV_MAJOR_VERSION == 3 && (CV_MINOR_VERSION < 4 || (CV_MINOR_VERSION==4 && CV_SUBMINOR_VERSION<11)))
class SIFT;
#endif
class SURF;
}
namespace cuda {
@@ -71,10 +74,15 @@ class ORB;
class SURF_CUDA;
}
}
#if CV_MAJOR_VERSION < 3 || (CV_MAJOR_VERSION == 4 && CV_MINOR_VERSION <= 3) || (CV_MAJOR_VERSION == 3 && (CV_MINOR_VERSION < 4 || (CV_MINOR_VERSION==4 && CV_SUBMINOR_VERSION<11)))
typedef cv::xfeatures2d::SIFT CV_SIFT;
#else
typedef cv::SIFT CV_SIFT; // SIFT is back in features2d since 4.4.0 / 3.4.11
#endif
typedef cv::xfeatures2d::SURF CV_SURF;
typedef cv::FastFeatureDetector CV_FAST;
typedef cv::xfeatures2d::FREAK CV_FREAK;
typedef cv::xfeatures2d::DAISY CV_DAISY;
typedef cv::GFTTDetector CV_GFTT;
typedef cv::xfeatures2d::BriefDescriptorExtractor CV_BRIEF;
typedef cv::BRISK CV_BRISK;
@@ -87,6 +95,7 @@ typedef cv::cuda::FastFeatureDetector CV_FAST_GPU;
namespace rtabmap {
class ORBextractor;
class SPDetector;
class Stereo;
#if CV_MAJOR_VERSION < 3
@@ -107,7 +116,49 @@ public:
kFeatureBrisk=7,
kFeatureGfttOrb=8, //new 0.10.11
kFeatureKaze=9, //new 0.13.2
kFeatureOrbOctree=10}; //new 0.19.2
kFeatureOrbOctree=10, //new 0.19.2
kFeatureSuperPointTorch=11, //new 0.19.7
kFeatureSurfFreak=12, //new 0.20.4
kFeatureGfttDaisy=13, //new 0.20.6
kFeatureSurfDaisy=14}; //new 0.20.6
static std::string typeName(Type type)
{
switch(type){
case kFeatureSurf:
return "SURF";
case kFeatureSift:
return "SIFT";
case kFeatureOrb:
return "ORB";
case kFeatureFastFreak:
return "FAST+FREAK";
case kFeatureFastBrief:
return "FAST+BRIEF";
case kFeatureGfttFreak:
return "GFTT+Freak";
case kFeatureGfttBrief:
return "GFTT+Brief";
case kFeatureBrisk:
return "BRISK";
case kFeatureGfttOrb:
return "GFTT+ORB";
case kFeatureKaze:
return "KAZE";
case kFeatureOrbOctree:
return "ORB-OCTREE";
case kFeatureSuperPointTorch:
return "SUPERPOINT";
case kFeatureSurfFreak:
return "SURF+Freak";
case kFeatureGfttDaisy:
return "GFTT+Daisy";
case kFeatureSurfDaisy:
return "SURF+Daisy";
default:
return "Unknown";
}
}
static Feature2D * create(const ParametersMap & parameters = ParametersMap());
static Feature2D * create(Feature2D::Type type, const ParametersMap & parameters = ParametersMap()); // for convenience
@@ -123,6 +174,12 @@ public:
const cv::Mat & depth,
float minDepth,
float maxDepth);
static void filterKeypointsByDepth(
std::vector<cv::KeyPoint> & keypoints,
cv::Mat & descriptors,
std::vector<cv::Point3f> & keypoints3D,
float minDepth,
float maxDepth);
static void filterKeypointsByDisparity(
std::vector<cv::KeyPoint> & keypoints,
@@ -138,6 +195,7 @@ public:
static void limitKeypoints(std::vector<cv::KeyPoint> & keypoints, cv::Mat & descriptors, int maxKeypoints);
static void limitKeypoints(std::vector<cv::KeyPoint> & keypoints, std::vector<cv::Point3f> & keypoints3D, cv::Mat & descriptors, int maxKeypoints);
static void limitKeypoints(const std::vector<cv::KeyPoint> & keypoints, std::vector<bool> & inliers, int maxKeypoints);
static void limitKeypoints(const std::vector<cv::KeyPoint> & keypoints, std::vector<bool> & inliers, int maxKeypoints, const cv::Size & imageSize, int gridRows, int gridCols);
static cv::Rect computeRoi(const cv::Mat & image, const std::string & roiRatios);
static cv::Rect computeRoi(const cv::Mat & image, const std::vector<float> & roiRatios);
@@ -145,6 +203,8 @@ public:
int getMaxFeatures() const {return maxFeatures_;}
float getMinDepth() const {return _minDepth;}
float getMaxDepth() const {return _maxDepth;}
int getGridRows() const {return gridRows_;}
int getGridCols() const {return gridCols_;}
public:
virtual ~Feature2D();
@@ -231,6 +291,7 @@ private:
double contrastThreshold_;
double edgeThreshold_;
double sigma_;
bool rootSIFT_;
cv::Ptr<CV_SIFT> _sift;
};
@@ -278,7 +339,7 @@ public:
private:
virtual std::vector<cv::KeyPoint> generateKeypointsImpl(const cv::Mat & image, const cv::Rect & roi, const cv::Mat & mask = cv::Mat());
virtual cv::Mat generateDescriptorsImpl(const cv::Mat & image, std::vector<cv::KeyPoint> & keypoints) const {return cv::Mat();}
virtual cv::Mat generateDescriptorsImpl(const cv::Mat &, std::vector<cv::KeyPoint> &) const {return cv::Mat();}
private:
int threshold_;
@@ -289,6 +350,14 @@ private:
int maxThreshold_;
int gridRows_;
int gridCols_;
int fastCV_;
bool fastCVinit_;
int fastCVMaxFeatures_;
int fastCVLastImageHeight_;
uint32_t* fastCVCorners_= NULL;
uint32_t* fastCVCornerScores_ = NULL;
void* fastCVTempBuf_ = NULL;
cv::Ptr<cv::FeatureDetector> _fast;
cv::Ptr<CV_FAST_GPU> _gpuFast;
@@ -398,6 +467,28 @@ private:
cv::Ptr<CV_FREAK> _freak;
};
//SURF_FREAK
class RTABMAP_EXP SURF_FREAK : public SURF
{
public:
SURF_FREAK(const ParametersMap & parameters = ParametersMap());
virtual ~SURF_FREAK();
virtual void parseParameters(const ParametersMap & parameters);
virtual Feature2D::Type getType() const {return kFeatureSurfFreak;}
private:
virtual cv::Mat generateDescriptorsImpl(const cv::Mat & image, std::vector<cv::KeyPoint> & keypoints) const;
private:
bool orientationNormalized_;
bool scaleNormalized_;
float patternScale_;
int nOctaves_;
cv::Ptr<CV_FREAK> _freak;
};
//GFTT_ORB
class RTABMAP_EXP GFTT_ORB : public GFTT
{
@@ -481,6 +572,8 @@ private:
private:
float scaleFactor_;
int nLevels_;
int patchSize_;
int edgeThreshold_;
int fastThreshold_;
int fastMinThreshold_;
@@ -488,6 +581,76 @@ private:
cv::Mat descriptors_;
};
//SuperPointTorch
class RTABMAP_EXP SuperPointTorch : public Feature2D
{
public:
SuperPointTorch(const ParametersMap & parameters = ParametersMap());
virtual ~SuperPointTorch();
virtual void parseParameters(const ParametersMap & parameters);
virtual Feature2D::Type getType() const { return kFeatureSuperPointTorch; }
private:
virtual std::vector<cv::KeyPoint> generateKeypointsImpl(const cv::Mat & image, const cv::Rect & roi, const cv::Mat & mask = cv::Mat());
virtual cv::Mat generateDescriptorsImpl(const cv::Mat & image, std::vector<cv::KeyPoint> & keypoints) const;
cv::Ptr<SPDetector> superPoint_;
std::string path_;
float threshold_;
bool nms_;
int minDistance_;
bool cuda_;
};
//GFTT_DAISY
class RTABMAP_EXP GFTT_DAISY : public GFTT
{
public:
GFTT_DAISY(const ParametersMap & parameters = ParametersMap());
virtual ~GFTT_DAISY();
virtual void parseParameters(const ParametersMap & parameters);
virtual Feature2D::Type getType() const {return kFeatureGfttDaisy;}
private:
virtual cv::Mat generateDescriptorsImpl(const cv::Mat & image, std::vector<cv::KeyPoint> & keypoints) const;
private:
bool orientationNormalized_;
bool scaleNormalized_;
float patternScale_;
int nOctaves_;
#if CV_MAJOR_VERSION > 2
cv::Ptr<CV_DAISY> _daisy;
#endif
};
//SURF_DAISY
class RTABMAP_EXP SURF_DAISY : public SURF
{
public:
SURF_DAISY(const ParametersMap & parameters = ParametersMap());
virtual ~SURF_DAISY();
virtual void parseParameters(const ParametersMap & parameters);
virtual Feature2D::Type getType() const {return kFeatureSurfDaisy;}
private:
virtual cv::Mat generateDescriptorsImpl(const cv::Mat & image, std::vector<cv::KeyPoint> & keypoints) const;
private:
bool orientationNormalized_;
bool scaleNormalized_;
float patternScale_;
int nOctaves_;
#if CV_MAJOR_VERSION > 2
cv::Ptr<CV_DAISY> _daisy;
#endif
};
}

View File

@@ -43,8 +43,8 @@ public:
void release();
unsigned int indexedFeatures() const;
// return KB
unsigned int memoryUsed() const;
// return Bytes
unsigned long memoryUsed() const;
// Note that useDistanceL1 doesn't have any effect if LSH is used
void buildLinearIndex(
@@ -74,7 +74,7 @@ public:
int featuresType() const {return featuresType_;}
int featuresDim() const {return featuresDim_;}
unsigned int addPoints(const cv::Mat & features);
std::vector<unsigned int> addPoints(const cv::Mat & features);
void removePoint(unsigned int index);

View File

@@ -0,0 +1,59 @@
/*
Copyright (c) 2010-2020, 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 <opencv2/core/core.hpp>
namespace rtabmap
{
class GlobalDescriptor
{
public:
GlobalDescriptor(int type, const cv::Mat & data, const cv::Mat & info = cv::Mat()) :
type_(type),
info_(info),
data_(data)
{}
GlobalDescriptor() :
type_(-1) // Not set
{}
virtual ~GlobalDescriptor() {}
int type() const {return type_;}
const cv::Mat info() const {return info_;}
const cv::Mat data() const {return data_;}
private:
int type_;
cv::Mat info_;
cv::Mat data_;
};
} // namespace rtabmap

View File

@@ -35,6 +35,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <rtabmap/core/Parameters.h>
#include <rtabmap/core/Link.h>
#include <rtabmap/core/GPS.h>
#include <rtabmap/core/CameraModel.h>
namespace rtabmap {
class Memory;
@@ -55,10 +56,10 @@ namespace graph {
bool RTABMAP_EXP importPoses(
const std::string & filePath,
int format, // 0=Raw, 1=RGBD-SLAM motion capture (10=without change of coordinate frame), 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 motion capture (10=without change of coordinate frame), 2=KITTI, 3=TORO, 4=g2o, 5=NewCollege(t,x,y), 6=Malaga Urban GPS, 7=St Lucia INS, 8=Karlsruhe, 9=EuRoC MAV
std::map<int, Transform> & poses,
std::multimap<int, Link> * constraints = 0, // optional for formats 3 and 4
std::map<int, double> * stamps = 0); // optional for format 1
std::map<int, double> * stamps = 0); // optional for format 1 and 9
bool RTABMAP_EXP exportGPS(
const std::string & filePath,
@@ -155,12 +156,20 @@ std::list<Link> RTABMAP_EXP findLinks(
std::multimap<int, Link> RTABMAP_EXP filterDuplicateLinks(
const std::multimap<int, Link> & links);
/**
* Return links not of type "filteredType". If inverted=true, return links of of type "filteredType".
*/
std::multimap<int, Link> RTABMAP_EXP filterLinks(
const std::multimap<int, Link> & links,
Link::Type filteredType);
Link::Type filteredType,
bool inverted = false);
/**
* Return links not of type "filteredType". If inverted=true, return links of of type "filteredType".
*/
std::map<int, Link> RTABMAP_EXP filterLinks(
const std::map<int, Link> & links,
Link::Type filteredType);
Link::Type filteredType,
bool inverted = false);
//Note: This assumes a coordinate system where X is forward, * Y is up, and Z is right.
std::map<int, Transform> RTABMAP_EXP frustumPosesFiltering(
@@ -255,11 +264,26 @@ std::list<std::pair<int, Transform> > RTABMAP_EXP computePath(
float linearVelocity = 0.0f, // m/sec
float angularVelocity = 0.0f); // rad/sec
/**
* Get the nearest node of the target pose
* @param nodes the nodes to search for
* @param targetPose the target pose to search around
* @param distance squared distance of the nearest node found (optional)
* @return the node id.
*/
int RTABMAP_EXP findNearestNode(
const std::map<int, rtabmap::Transform> & nodes,
const rtabmap::Transform & targetPose);
const rtabmap::Transform & targetPose,
float * distance = 0);
std::vector<int> RTABMAP_EXP findNearestNodes(
/**
* Get K nearest nodes of the target pose
* @param nodes the nodes to search for
* @param targetPose the target pose to search around
* @param k number of nearest neighbors to search for
* @return the node ids with squared distance to target pose.
*/
std::map<int, float> RTABMAP_EXP findNearestNodes(
const std::map<int, rtabmap::Transform> & nodes,
const rtabmap::Transform & targetPose,
int k);
@@ -275,11 +299,20 @@ std::map<int, float> RTABMAP_EXP getNodesInRadius(
int nodeId,
const std::map<int, Transform> & nodes,
float radius);
std::map<int, float> RTABMAP_EXP getNodesInRadius(
const Transform & targetPose,
const std::map<int, Transform> & nodes,
float radius);
std::map<int, Transform> RTABMAP_EXP getPosesInRadius(
int nodeId,
const std::map<int, Transform> & nodes,
float radius,
float angle = 0.0f);
std::map<int, Transform> RTABMAP_EXP getPosesInRadius(
const Transform & targetPose,
const std::map<int, Transform> & nodes,
float radius,
float angle = 0.0f);
float RTABMAP_EXP computePathLength(
const std::vector<std::pair<int, Transform> > & path,

View File

@@ -97,6 +97,7 @@ public:
float angleIncrement() const {return angleIncrement_;}
Transform localTransform() const {return localTransform_;}
bool empty() const {return data_.empty();}
bool isEmpty() const {return data_.empty();}
int size() const {return data_.cols;}
int dataType() const {return data_.type();}

View File

@@ -54,6 +54,8 @@ public:
kAllWithLandmarks = 98,
kAllWithoutLandmarks = 99,
kUndef = 99};
static std::string typeName(Type type);
Link();
Link(int from,
int to,
@@ -68,9 +70,10 @@ public:
int to() const {return to_;}
const Transform & transform() const {return transform_;}
Type type() const {return type_;}
std::string typeName() const {return typeName(type_);}
const cv::Mat & infMatrix() const {return infMatrix_;}
double rotVariance() const;
double transVariance() const;
double rotVariance(bool minimum = true) const;
double transVariance(bool minimum = true) const;
void setFrom(int from) {from_ = from;}
void setTo(int to) {to_ = to;}

View File

@@ -50,6 +50,8 @@ private:
cv::Ptr<cv::aruco::DetectorParameters> detectorParams_;
float markerLength_;
float maxDepthError_;
float maxRange_;
float minRange_;
int dictionaryId_;
cv::Ptr<cv::aruco::Dictionary> dictionary_;
#endif

View File

@@ -93,7 +93,7 @@ public:
std::set<int> reactivateSignatures(const std::list<int> & ids, unsigned int maxLoaded, double & timeDbAccess);
int cleanup();
void saveStatistics(const Statistics & statistics);
void saveStatistics(const Statistics & statistics, bool saveWMState);
void savePreviewImage(const cv::Mat & image) const;
cv::Mat loadPreviewImage() const;
void saveOptimizedPoses(const std::map<int, Transform> & optimizedPoses, const Transform & lastlocalizationPose) const;
@@ -102,7 +102,7 @@ public:
cv::Mat load2DMap(float & xMin, float & yMin, float & cellSize) const;
void saveOptimizedMesh(
const cv::Mat & cloud,
const std::vector<std::vector<std::vector<unsigned int> > > & polygons = std::vector<std::vector<std::vector<unsigned int> > >(), // Textures -> polygons -> vertices
const std::vector<std::vector<std::vector<RTABMAP_PCL_INDEX> > > & polygons = std::vector<std::vector<std::vector<RTABMAP_PCL_INDEX> > >(), // Textures -> polygons -> vertices
#if PCL_VERSION_COMPARE(>=, 1, 8, 0)
const std::vector<std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > > & texCoords = std::vector<std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > >(), // Textures -> uv coords for each vertex of the polygons
#else
@@ -110,7 +110,7 @@ public:
#endif
const cv::Mat & textures = cv::Mat()) const; // concatenated textures (assuming square textures with all same size)
cv::Mat loadOptimizedMesh(
std::vector<std::vector<std::vector<unsigned int> > > * polygons = 0,
std::vector<std::vector<std::vector<RTABMAP_PCL_INDEX> > > * polygons = 0,
#if PCL_VERSION_COMPARE(>=, 1, 8, 0)
std::vector<std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > > * texCoords = 0,
#else
@@ -197,18 +197,20 @@ public:
EnvSensors & sensors,
bool lookInDatabase = false) const;
cv::Mat getImageCompressed(int signatureId) const;
SensorData getNodeData(int nodeId, bool uncompressedData = false) const;
void getNodeWords(int nodeId,
std::multimap<int, cv::KeyPoint> & words,
std::multimap<int, cv::Point3f> & words3,
std::multimap<int, cv::Mat> & wordsDescriptors);
SensorData getNodeData(int locationId, bool images, bool scan, bool userData, bool occupancyGrid) const;
void getNodeWordsAndGlobalDescriptors(int nodeId,
std::multimap<int, int> & words,
std::vector<cv::KeyPoint> & wordsKpts,
std::vector<cv::Point3f> & words3,
cv::Mat & wordsDescriptors,
std::vector<GlobalDescriptor> & globalDescriptors) const;
void getNodeCalibration(int nodeId,
std::vector<CameraModel> & models,
StereoCameraModel & stereoModel);
SensorData getSignatureDataConst(int locationId, bool images = true, bool scan = true, bool userData = true, bool occupancyGrid = true) const;
std::set<int> getAllSignatureIds() const;
StereoCameraModel & stereoModel) const;
std::set<int> getAllSignatureIds(bool ignoreChildren = true) const;
bool memoryChanged() const {return _memoryChanged;}
bool isIncremental() const {return _incrementalMemory;}
bool isLocalizationDataSaved() const {return _localizationDataSaved;}
const Signature * getSignature(int id) const;
bool isInSTM(int signatureId) const {return _stMem.find(signatureId) != _stMem.end();}
bool isInWM(int signatureId) const {return _workingMem.find(signatureId) != _workingMem.end();}
@@ -218,11 +220,13 @@ public:
const Feature2D * getFeature2D() const {return _feature2D;}
bool isGraphReduced() const {return _reduceGraph;}
const std::vector<double> & getOdomMaxInf() const {return _odomMaxInf;}
bool isOdomGravityUsed() const {return _useOdometryGravity;}
void dumpMemoryTree(const char * fileNameTree) const;
virtual void dumpMemory(std::string directory) const;
virtual void dumpSignatures(const char * fileNameSign, bool words3D) const;
void dumpDictionary(const char * fileNameRef, const char * fileNameDesc) const;
unsigned long getMemoryUsed() const; //Bytes
void generateGraph(const std::string & fileName, const std::set<int> & ids = std::set<int>());
@@ -290,6 +294,7 @@ private:
bool _saveIntermediateNodeData;
std::string _rgbCompressionFormat;
bool _incrementalMemory;
bool _localizationDataSaved;
bool _reduceGraph;
int _maxStMemSize;
float _recentWmRatio;
@@ -299,6 +304,7 @@ private:
bool _badSignaturesIgnored;
bool _mapLabelsAdded;
bool _depthAsMask;
bool _stereoFromMotion;
int _imagePreDecimation;
int _imagePostDecimation;
bool _compressionParallelized;
@@ -346,7 +352,7 @@ private:
//Keypoint stuff
VWDictionary * _vwd;
Feature2D * _feature2D;
float _badSignRatio;;
float _badSignRatio;
bool _tfIdfLikelihoodUsed;
bool _parallelized;

View File

@@ -104,6 +104,8 @@ public:
const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & getMapObstacles() const {return assembledObstacles_;}
const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & getMapEmptyCells() const {return assembledEmptyCells_;}
unsigned long getMemoryUsed() const;
private:
ParametersMap parameters_;
int cloudDecimation_;

View File

@@ -168,9 +168,6 @@ class RtabmapColorOcTree : public octomap::OccupancyOcTreeBase <RtabmapColorOcTr
};
class RTABMAP_EXP OctoMap {
public:
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);
@@ -194,7 +191,9 @@ public:
std::vector<int> * obstacleIndices = 0,
std::vector<int> * emptyIndices = 0,
std::vector<int> * groundIndices = 0,
bool originalRefPoints = true) const;
bool originalRefPoints = true,
std::vector<int> * frontierIndices = 0,
std::vector<double> * cloudProb = 0) const;
cv::Mat createProjectionMap(
float & xMin,

View File

@@ -78,6 +78,9 @@ public:
unsigned int framesProcessed() const {return framesProcessed_;}
bool imagesAlreadyRectified() const {return _imagesAlreadyRectified;}
protected:
const std::map<double, Transform> & imus() const {return imus_;}
private:
virtual Transform computeTransform(SensorData & data, const Transform & guess = Transform(), OdometryInfo * info = 0) = 0;
@@ -90,7 +93,7 @@ private:
bool _force3DoF;
bool _holonomic;
bool guessFromMotion_;
bool guessSmoothingDelay_;
float guessSmoothingDelay_;
int _filteringStrategy;
int _particleSize;
float _particleNoiseT;
@@ -109,12 +112,15 @@ private:
double previousStamp_;
std::list<std::pair<std::vector<float>, double> > previousVelocities_;
Transform velocityGuess_;
Transform imuLastTransform_;
Transform previousGroundTruthPose_;
float distanceTravelled_;
unsigned int framesProcessed_;
std::vector<ParticleFilter *> particleFilters_;
cv::KalmanFilter kalmanFilter_;
StereoCameraModel stereoModel_;
std::map<double, Transform> imus_;
protected:
Odometry(const rtabmap::ParametersMap & parameters);

View File

@@ -56,6 +56,8 @@ public:
interval(0),
distanceTravelled(0.0f),
memoryUsage(0),
gravityRollError(0.0),
gravityPitchError(0.0),
type(0)
{}
@@ -81,8 +83,11 @@ public:
output.transform = transform;
output.transformFiltered = transformFiltered;
output.transformGroundTruth = transformGroundTruth;
output.guessVelocity = guessVelocity;
output.distanceTravelled = distanceTravelled;
output.memoryUsage = memoryUsage;
output.gravityRollError = gravityRollError;
output.gravityPitchError = gravityPitchError;
output.type = type;
return output;
}
@@ -109,6 +114,8 @@ public:
Transform guessVelocity;
float distanceTravelled;
int memoryUsage; //MB
double gravityRollError;
double gravityPitchError;
int type;

View File

@@ -62,7 +62,8 @@ public:
kTypeTORO = 0,
kTypeG2O = 1,
kTypeGTSAM = 2,
kTypeCVSBA = 3
kTypeCeres = 3,
kTypeCVSBA = 4
};
static bool isAvailable(Optimizer::Type type);
static Optimizer * create(const ParametersMap & parameters);

View File

@@ -32,6 +32,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "rtabmap/core/RtabmapExp.h" // DLL export/import defines
#include "rtabmap/core/Version.h" // DLL export/import defines
#include <rtabmap/utilite/UConversion.h>
#include <opencv2/core/version.hpp>
#include <opencv2/opencv_modules.hpp>
#include <string>
#include <map>
@@ -62,7 +64,7 @@ typedef std::pair<std::string, std::string> ParametersPair;
#define RTABMAP_PARAM(PREFIX, NAME, TYPE, DEFAULT_VALUE, DESCRIPTION) \
public: \
static std::string k##PREFIX##NAME() {return std::string(#PREFIX "/" #NAME);} \
static TYPE default##PREFIX##NAME() {return DEFAULT_VALUE;} \
static TYPE default##PREFIX##NAME() {return (TYPE)DEFAULT_VALUE;} \
static std::string type##PREFIX##NAME() {return std::string(#TYPE);} \
private: \
class Dummy##PREFIX##NAME { \
@@ -71,7 +73,7 @@ typedef std::pair<std::string, std::string> ParametersPair;
parametersType_.insert(ParametersPair(#PREFIX "/" #NAME, #TYPE)); \
descriptions_.insert(ParametersPair(#PREFIX "/" #NAME, DESCRIPTION));} \
}; \
Dummy##PREFIX##NAME dummy##PREFIX##NAME;
Dummy##PREFIX##NAME dummy##PREFIX##NAME
// end define PARAM
/**
@@ -105,7 +107,7 @@ typedef std::pair<std::string, std::string> ParametersPair;
parametersType_.insert(ParametersPair(#PREFIX "/" #NAME, "string")); \
descriptions_.insert(ParametersPair(#PREFIX "/" #NAME, DESCRIPTION));} \
}; \
Dummy##PREFIX##NAME dummy##PREFIX##NAME;
Dummy##PREFIX##NAME dummy##PREFIX##NAME
// end define PARAM
/**
@@ -138,7 +140,7 @@ typedef std::pair<std::string, std::string> ParametersPair;
parametersType_.insert(ParametersPair(#PREFIX "/" #NAME, #TYPE)); \
descriptions_.insert(ParametersPair(#PREFIX "/" #NAME, DESCRIPTION));} \
}; \
Dummy##PREFIX##NAME dummy##PREFIX##NAME;
Dummy##PREFIX##NAME dummy##PREFIX##NAME
// end define PARAM
/**
@@ -207,6 +209,7 @@ class RTABMAP_EXP Parameters
RTABMAP_PARAM_STR(Mem, ImageCompressionFormat, ".jpg", "RGB image compression format. It should be \".jpg\" or \".png\".");
RTABMAP_PARAM(Mem, STMSize, unsigned int, 10, "Short-term memory size.");
RTABMAP_PARAM(Mem, IncrementalMemory, bool, true, "SLAM mode, otherwise it is Localization mode.");
RTABMAP_PARAM(Mem, LocalizationDataSaved, bool, false, uFormat("Save localization data during localization session (when %s=false). When enabled, the database will then also grow in localization mode. This mode would be used only for debugging purpose.", kMemIncrementalMemory().c_str()).c_str());
RTABMAP_PARAM(Mem, ReduceGraph, bool, false, "Reduce graph. Merge nodes when loop closures are added (ignoring those with user data set).");
RTABMAP_PARAM(Mem, RecentWmRatio, float, 0.2, "Ratio of locations after the last loop closure in WM that cannot be transferred.");
RTABMAP_PARAM(Mem, TransferSortingByWeightId, bool, false, "On transfer, signatures are sorted by weight->ID only (i.e. the oldest of the lowest weighted signatures are transferred first). If false, the signatures are sorted by weight->Age->ID (i.e. the oldest inserted in WM of the lowest weighted signatures are transferred first). Note that retrieval updates the age, not the ID.");
@@ -216,8 +219,9 @@ class RTABMAP_EXP Parameters
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, StereoFromMotion, bool, false, uFormat("Triangulate features without depth using stereo from motion (odometry). It would be ignored if %s is true and the feature detector used supports masking.", kMemDepthAsMask().c_str()));
RTABMAP_PARAM(Mem, ImagePreDecimation, int, 1, "Image decimation (>=1) before features extraction.");
RTABMAP_PARAM(Mem, ImagePostDecimation, int, 1, "Image decimation (>=1) of saved data in created signatures (after features extraction). Decimation is done from the original image.");
RTABMAP_PARAM(Mem, 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()));
@@ -232,20 +236,17 @@ class RTABMAP_EXP Parameters
RTABMAP_PARAM(Kp, IncrementalDictionary, bool, true, "");
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, ByteToFloat, bool, false, uFormat("For %s=1, binary descriptors are converted to float by converting each byte to float instead of converting each bit to float. When converting bytes instead of bits, less memory is used and search is faster at the cost of slightly less accurate matching.", kKpNNStrategy().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, 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.)");
#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 10=ORB-OCTREE.");
#if CV_MAJOR_VERSION > 2 && !defined(HAVE_OPENCV_XFEATURES2D)
// OpenCV>2 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 10=ORB-OCTREE 11=SuperPoint 12=SURF/FREAK 13=GFTT/DAISY 14=SURF/DAISY");
#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 10=ORB-OCTREE.");
#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 10=ORB-OCTREE.");
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 10=ORB-OCTREE 11=SuperPoint 12=SURF/FREAK 13=GFTT/DAISY 14=SURF/DAISY");
#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.");
@@ -264,6 +265,7 @@ class RTABMAP_EXP Parameters
RTABMAP_PARAM(DbSqlite3, JournalMode, int, 3, "0=DELETE, 1=TRUNCATE, 2=PERSIST, 3=MEMORY, 4=OFF (see sqlite3 doc : \"PRAGMA journal_mode\")");
RTABMAP_PARAM(DbSqlite3, Synchronous, int, 0, "0=OFF, 1=NORMAL, 2=FULL (see sqlite3 doc : \"PRAGMA synchronous\")");
RTABMAP_PARAM(DbSqlite3, TempStore, int, 2, "0=DEFAULT, 1=FILE, 2=MEMORY (see sqlite3 doc : \"PRAGMA temp_store\")");
RTABMAP_PARAM_STR(Db, TargetVersion, "", "Target database version for backward compatibility purpose. Only Major and minor versions are used and should be set (e.g., 0.19 vs 0.20 or 1.0 vs 2.0). Patch version is ignored (e.g., 0.20.1 and 0.20.3 will generate a 0.20 database).");
// Keypoints descriptors/detectors
RTABMAP_PARAM(SURF, Extended, bool, false, "Extended descriptor flag (true - use extended 128-element descriptors; false - use 64-element descriptors).");
@@ -279,6 +281,7 @@ class RTABMAP_EXP Parameters
RTABMAP_PARAM(SIFT, ContrastThreshold, double, 0.04, "The contrast threshold used to filter out weak features in semi-uniform (low-contrast) regions. The larger the threshold, the less features are produced by the detector.");
RTABMAP_PARAM(SIFT, EdgeThreshold, double, 10, "The threshold used to filter out edge-like features. Note that the its meaning is different from the contrastThreshold, i.e. the larger the edgeThreshold, the less features are filtered out (more features are retained).");
RTABMAP_PARAM(SIFT, Sigma, double, 1.6, "The sigma of the Gaussian applied to the input image at the octave #0. If your image is captured with a weak camera with soft lenses, you might want to reduce the number.");
RTABMAP_PARAM(SIFT, RootSIFT, bool, false, "Apply RootSIFT normalization of the descriptors.");
RTABMAP_PARAM(BRIEF, Bytes, int, 32, "Bytes is a length of descriptor in bytes. It can be equal 16, 32 or 64 bytes.");
@@ -290,6 +293,7 @@ class RTABMAP_EXP Parameters
RTABMAP_PARAM(FAST, MaxThreshold, int, 200, "Maximum threshold. Used only when FAST/GridRows and FAST/GridCols are set.");
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(FAST, CV, int, 0, "Enable FastCV implementation if non-zero (and RTAB-Map is built with FastCV support). Values should be 9 and 10.");
RTABMAP_PARAM(GFTT, QualityLevel, double, 0.001, "");
RTABMAP_PARAM(GFTT, MinDistance, double, 3, "");
@@ -297,9 +301,9 @@ class RTABMAP_EXP Parameters
RTABMAP_PARAM(GFTT, UseHarrisDetector, bool, false, "");
RTABMAP_PARAM(GFTT, K, double, 0.04, "");
RTABMAP_PARAM(ORB, ScaleFactor, float, 1.2, "Pyramid decimation ratio, greater than 1. scaleFactor==2 means the classical pyramid, where each next level has 4x less pixels than the previous, but such a big scale factor will degrade feature matching scores dramatically. On the other hand, too close to 1 scale factor will mean that to cover certain scale range you will need more pyramid levels and so the speed will suffer.");
RTABMAP_PARAM(ORB, NLevels, int, 8, "The number of pyramid levels. The smallest level will have linear size equal to input_image_linear_size/pow(scaleFactor, nlevels).");
RTABMAP_PARAM(ORB, EdgeThreshold, int, 31, "This is size of the border where the features are not detected. It should roughly match the patchSize parameter.");
RTABMAP_PARAM(ORB, ScaleFactor, float, 2, "Pyramid decimation ratio, greater than 1. scaleFactor==2 means the classical pyramid, where each next level has 4x less pixels than the previous, but such a big scale factor will degrade feature matching scores dramatically. On the other hand, too close to 1 scale factor will mean that to cover certain scale range you will need more pyramid levels and so the speed will suffer.");
RTABMAP_PARAM(ORB, NLevels, int, 3, "The number of pyramid levels. The smallest level will have linear size equal to input_image_linear_size/pow(scaleFactor, nlevels).");
RTABMAP_PARAM(ORB, EdgeThreshold, int, 19, "This is size of the border where the features are not detected. It should roughly match the patchSize parameter.");
RTABMAP_PARAM(ORB, FirstLevel, int, 0, "It should be 0 in the current implementation.");
RTABMAP_PARAM(ORB, WTA_K, int, 2, "The number of points that produce each element of the oriented BRIEF descriptor. The default value 2 means the BRIEF where we take a random point pair and compare their brightnesses, so we get 0/1 response. Other possible values are 3 and 4. For example, 3 means that we take 3 random points (of course, those point coordinates are random, but they are generated from the pre-defined seed, so each element of BRIEF descriptor is computed deterministically from the pixel rectangle), find point of maximum brightness and output index of the winner (0, 1 or 2). Such output will occupy 2 bits, and therefore it will need a special variant of Hamming distance, denoted as NORM_HAMMING2 (2 bits per bin). When WTA_K=4, we take 4 random points to compute each bin (that will also occupy 2 bits with possible values 0, 1, 2 or 3).");
RTABMAP_PARAM(ORB, ScoreType, int, 0, "The default HARRIS_SCORE=0 means that Harris algorithm is used to rank features (the score is written to KeyPoint::score and is used to retain best nfeatures features); FAST_SCORE=1 is alternative value of the parameter that produces slightly less stable keypoints, but it is a little faster to compute.");
@@ -317,11 +321,17 @@ class RTABMAP_EXP Parameters
RTABMAP_PARAM(KAZE, Extended, bool, false, "Set to enable extraction of extended (128-byte) descriptor.");
RTABMAP_PARAM(KAZE, Upright, bool, false, "Set to enable use of upright descriptors (non rotation-invariant).");
RTABMAP_PARAM(KAZE, Threshold, float, 0.001, "Detector response threshold to accept point.");
RTABMAP_PARAM(KAZE, Threshold, float, 0.001, "Detector response threshold to accept keypoint.");
RTABMAP_PARAM(KAZE, NOctaves, int, 4, "Maximum octave evolution of the image.");
RTABMAP_PARAM(KAZE, NOctaveLayers, int, 4, "Default number of sublevels per scale level.");
RTABMAP_PARAM(KAZE, Diffusivity, int, 1, "Diffusivity type: 0=DIFF_PM_G1, 1=DIFF_PM_G2, 2=DIFF_WEICKERT or 3=DIFF_CHARBONNIER.");
RTABMAP_PARAM_STR(SuperPoint, ModelPath, "", "[Required] Path to pre-trained weights Torch file of SuperPoint (*.pt).");
RTABMAP_PARAM(SuperPoint, Threshold, float, 0.010, "Detector response threshold to accept keypoint.");
RTABMAP_PARAM(SuperPoint, NMS, bool, true, "If true, non-maximum suppression is applied to detected keypoints.");
RTABMAP_PARAM(SuperPoint, NMSRadius, int, 4, uFormat("[%s=true] Minimum distance (pixels) between keypoints.", kSuperPointNMS().c_str()));
RTABMAP_PARAM(SuperPoint, Cuda, bool, true, "Use Cuda device for Torch, otherwise CPU device is used by default.");
// BayesFilter
RTABMAP_PARAM(Bayes, VirtualPlacePriorThr, float, 0.9, "Virtual place prior");
RTABMAP_PARAM_STR(Bayes, PredictionLC, "0.1 0.36 0.30 0.16 0.062 0.0151 0.00255 0.000324 2.5e-05 1.3e-06 4.8e-08 1.2e-09 1.9e-11 2.2e-13 1.7e-15 8.5e-18 2.9e-20 6.9e-23", "Prediction of loop closures (Gaussian-like, here with sigma=1.6) - Format: {VirtualPlaceProb, LoopClosureProb, NeighborLvl1, NeighborLvl2, ...}.");
@@ -342,6 +352,7 @@ class RTABMAP_EXP Parameters
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, 3.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, MaxLoopClosureDistance, float, 0.0, "Reject loop closures/localizations if the distance from the map is over this distance (0=disabled).");
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.");
@@ -369,28 +380,35 @@ class RTABMAP_EXP Parameters
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.");
RTABMAP_PARAM(RGBD, ProximityOdomGuess, bool, false, "Use odometry as motion guess for visual proximity detection.");
// Graph optimization
#ifdef RTABMAP_GTSAM
RTABMAP_PARAM(Optimizer, Strategy, int, 2, "Graph optimization strategy: 0=TORO, 1=g2o and 2=GTSAM.");
RTABMAP_PARAM(Optimizer, Strategy, int, 2, "Graph optimization strategy: 0=TORO, 1=g2o, 2=GTSAM and 3=Ceres.");
RTABMAP_PARAM(Optimizer, Iterations, int, 20, "Optimization iterations.");
RTABMAP_PARAM(Optimizer, Epsilon, double, 0.00001, "Stop optimizing when the error improvement is less than this value.");
#else
#ifdef RTABMAP_G2O
RTABMAP_PARAM(Optimizer, Strategy, int, 1, "Graph optimization strategy: 0=TORO, 1=g2o and 2=GTSAM.");
RTABMAP_PARAM(Optimizer, Strategy, int, 1, "Graph optimization strategy: 0=TORO, 1=g2o, 2=GTSAM and 3=Ceres.");
RTABMAP_PARAM(Optimizer, Iterations, int, 20, "Optimization iterations.");
RTABMAP_PARAM(Optimizer, Epsilon, double, 0.0, "Stop optimizing when the error improvement is less than this value.");
#else
RTABMAP_PARAM(Optimizer, Strategy, int, 0, "Graph optimization strategy: 0=TORO, 1=g2o and 2=GTSAM.");
#ifdef RTABMAP_CERES
RTABMAP_PARAM(Optimizer, Strategy, int, 3, "Graph optimization strategy: 0=TORO, 1=g2o, 2=GTSAM and 3=Ceres.");
RTABMAP_PARAM(Optimizer, Iterations, int, 20, "Optimization iterations.");
RTABMAP_PARAM(Optimizer, Epsilon, double, 0.000001, "Stop optimizing when the error improvement is less than this value.");
#else
RTABMAP_PARAM(Optimizer, Strategy, int, 0, "Graph optimization strategy: 0=TORO, 1=g2o, 2=GTSAM and 3=Ceres.");
RTABMAP_PARAM(Optimizer, Iterations, int, 100, "Optimization iterations.");
RTABMAP_PARAM(Optimizer, Epsilon, double, 0.00001, "Stop optimizing when the error improvement is less than this value.");
#endif
#endif
#endif
RTABMAP_PARAM(Optimizer, VarianceIgnored, bool, false, "Ignore constraints' variance. If checked, identity information matrix is used for each constraint. Otherwise, an information matrix is generated from the variance saved in the links.");
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.");
RTABMAP_PARAM(Optimizer, LandmarksIgnored, bool, false, "Ignore landmark constraints while optimizing. Currently only g2o and gtsam optimization supports this.");
RTABMAP_PARAM(Optimizer, GravitySigma, float, 0.0, uFormat("Gravity sigma value (>=0, typically between 0.1 and 0.3). Optimization is done while preserving gravity orientation of the poses. This should be used only with visual/lidar inertial odometry approaches, for which we assume that all odometry poses are aligned with gravity. Set to 0 to disable gravity constraints. Currently supported only with GTSAM optimization strategy (see %s).", kOptimizerStrategy().c_str()));
RTABMAP_PARAM(Optimizer, GravitySigma, float, 0.0, uFormat("Gravity sigma value (>=0, typically between 0.1 and 0.3). Optimization is done while preserving gravity orientation of the poses. This should be used only with visual/lidar inertial odometry approaches, for which we assume that all odometry poses are aligned with gravity. Set to 0 to disable gravity constraints. Currently supported only with g2o and GTSAM optimization strategies (see %s).", kOptimizerStrategy().c_str()));
#ifdef RTABMAP_ORB_SLAM2
RTABMAP_PARAM(g2o, Solver, int, 3, "0=csparse 1=pcg 2=cholmod 3=Eigen");
@@ -405,7 +423,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 6=OKVIS 7=LOAM 8=MSCKF_VIO");
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 9=VINS-Fusion");
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).");
@@ -432,11 +450,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());
RTABMAP_PARAM(OdomF2M, ScanRange, float, 0, "[Geometry] Distance Range used to filter points of local map (when > 0). 0 means local map is updated using time and not range.");
RTABMAP_PARAM(OdomF2M, ValidDepthRatio, float, 0.75, "If a new frame has points without valid depth, they are added to local feature map only if points with valid depth on total points is over this ratio. Setting to 1 means no points without valid depth are added to local feature map.");
#if defined(RTABMAP_G2O) || defined(RTABMAP_ORB_SLAM2)
RTABMAP_PARAM(OdomF2M, BundleAdjustment, int, 1, "Local bundle adjustment: 0=disabled, 1=g2o, 2=cvsba.");
RTABMAP_PARAM(OdomF2M, BundleAdjustment, int, 1, "Local bundle adjustment: 0=disabled, 1=g2o, 2=cvsba, 3=Ceres.");
#else
RTABMAP_PARAM(OdomF2M, BundleAdjustment, int, 0, "Local bundle adjustment: 0=disabled, 1=g2o, 2=cvsba.");
RTABMAP_PARAM(OdomF2M, BundleAdjustment, int, 0, "Local bundle adjustment: 0=disabled, 1=g2o, 2=cvsba, 3=Ceres.");
#endif
RTABMAP_PARAM(OdomF2M, BundleAdjustmentMaxFrames, int, 10, "Maximum frames used for bundle adjustment (0=inf or all current frames in the local map).");
@@ -561,18 +580,17 @@ class RTABMAP_EXP Parameters
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, EpipolarGeometryVar, float, 0.1, 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, MeanInliersDistance, float, 0.0, "Maximum distance (m) of the mean distance of inliers from the camera to accept the transformation. 0 means disabled.");
RTABMAP_PARAM(Vis, MinInliersDistribution, float, 0.0, "Minimum distribution value of the inliers in the image to accept the transformation. The distribution is the second eigen value of the PCA (Principal Component Analysis) on the keypoints of the normalized image [-0.5, 0.5]. The value would be between 0 and 0.5. 0 means disabled.");
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
RTABMAP_PARAM(Vis, FeatureType, int, 8, "0=SURF 1=SIFT 2=ORB 3=FAST/FREAK 4=FAST/BRIEF 5=GFTT/FREAK 6=GFTT/BRIEF 7=BRISK 8=GFTT/ORB 9=KAZE 10=ORB-OCTREE.");
#if CV_MAJOR_VERSION > 2 && !defined(HAVE_OPENCV_XFEATURES2D)
// OpenCV>2 without xFeatures2D module doesn't have BRIEF
RTABMAP_PARAM(Vis, FeatureType, int, 8, "0=SURF 1=SIFT 2=ORB 3=FAST/FREAK 4=FAST/BRIEF 5=GFTT/FREAK 6=GFTT/BRIEF 7=BRISK 8=GFTT/ORB 9=KAZE 10=ORB-OCTREE 11=SuperPoint 12=SURF/FREAK 13=GFTT/DAISY 14=SURF/DAISY");
#else
RTABMAP_PARAM(Vis, FeatureType, int, 6, "0=SURF 1=SIFT 2=ORB 3=FAST/FREAK 4=FAST/BRIEF 5=GFTT/FREAK 6=GFTT/BRIEF 7=BRISK 8=GFTT/ORB 9=KAZE 10=ORB-OCTREE.");
#endif
#else
RTABMAP_PARAM(Vis, FeatureType, int, 6, "0=SURF 1=SIFT 2=ORB 3=FAST/FREAK 4=FAST/BRIEF 5=GFTT/FREAK 6=GFTT/BRIEF 7=BRISK 8=GFTT/ORB 9=KAZE 10=ORB-OCTREE.");
RTABMAP_PARAM(Vis, FeatureType, int, 6, "0=SURF 1=SIFT 2=ORB 3=FAST/FREAK 4=FAST/BRIEF 5=GFTT/FREAK 6=GFTT/BRIEF 7=BRISK 8=GFTT/ORB 9=KAZE 10=ORB-OCTREE 11=SuperPoint 12=SURF/FREAK 13=GFTT/DAISY 14=SURF/DAISY");
#endif
RTABMAP_PARAM(Vis, MaxFeatures, int, 1000, "0 no limits.");
RTABMAP_PARAM(Vis, MaxDepth, float, 0, "Max depth of the features (0 means no limit).");
@@ -585,8 +603,8 @@ class RTABMAP_EXP Parameters
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, CorNNType, int, 1, uFormat("[%s=0] kNNFlannNaive=0, kNNFlannKdTree=1, kNNFlannLSH=2, kNNBruteForce=3, kNNBruteForceGPU=4, BruteForceCrossCheck=5, SuperGlue=6, GMS=7. Used for features matching approach.", kVisCorType().c_str()));
RTABMAP_PARAM(Vis, CorNNDR, float, 0.8, uFormat("[%s=0] NNDR: nearest neighbor distance ratio. Used for knn 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()));
@@ -594,16 +612,29 @@ class RTABMAP_EXP Parameters
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.");
RTABMAP_PARAM(Vis, BundleAdjustment, int, 1, "Optimization with bundle adjustment: 0=disabled, 1=g2o, 2=cvsba, 3=Ceres.");
#else
RTABMAP_PARAM(Vis, BundleAdjustment, int, 0, "Optimization with bundle adjustment: 0=disabled, 1=g2o, 2=cvsba.");
RTABMAP_PARAM(Vis, BundleAdjustment, int, 0, "Optimization with bundle adjustment: 0=disabled, 1=g2o, 2=cvsba, 3=Ceres.");
#endif
// Features matching approaches
RTABMAP_PARAM_STR(PyMatcher, Path, "", "Path to python script file (see available ones in rtabmap/corelib/src/pymatcher/*). See the header to see where the script should be copied.");
RTABMAP_PARAM(PyMatcher, Iterations, int, 20, "Sinkhorn iterations. Used by SuperGlue.");
RTABMAP_PARAM(PyMatcher, Threshold, float, 0.2, "Used by SuperGlue.");
RTABMAP_PARAM(PyMatcher, Cuda, bool, true, "Used by SuperGlue.");
RTABMAP_PARAM_STR(PyMatcher, Model, "indoor", "For SuperGlue, set only \"indoor\" or \"outdoor\". For OANet, set path to one of the pth file (e.g., \"OANet/model/gl3d/sift-4000/model_best.pth\").");
RTABMAP_PARAM(GMS, WithRotation, bool, false, "Take rotation transformation into account.");
RTABMAP_PARAM(GMS, WithScale, bool, false, "Take scale transformation into account.");
RTABMAP_PARAM(GMS, ThresholdFactor, double, 6.0, "The higher, the less matches.");
// 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.");
RTABMAP_PARAM(Icp, RangeMin, float, 0, "Minimum range filtering (0=disabled).");
RTABMAP_PARAM(Icp, RangeMax, float, 0, "Maximum range filtering (0=disabled).");
#ifdef RTABMAP_POINTMATCHER
RTABMAP_PARAM(Icp, MaxCorrespondenceDistance, float, 0.1, "Max distance for point correspondences.");
#else
@@ -613,13 +644,15 @@ class RTABMAP_EXP Parameters
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.1, "Ratio of matching correspondences to accept the transform.");
#ifdef RTABMAP_POINTMATCHER
RTABMAP_PARAM(Icp, PointToPlane, bool, true, "Use point to plane ICP.");
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, PointToPlane, bool, false, "Use point to plane ICP.");
#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.");
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, PointToPlaneGroundNormalsUp, float, 0.0, "Invert normals on ground if they are pointing down (useful for ring-like 3D LiDARs). 0 means disabled, 1 means only normals perfectly aligned with -z axis. This is only done with 3D scans.");
RTABMAP_PARAM(Icp, PointToPlaneMinComplexity, float, 0.02, uFormat("Minimum structural complexity (0.0=low, 1.0=high) of the scan to do PointToPlane registration, otherwise PointToPoint registration is done instead and strategy from %s is used. This check is done only when %s=true.", kIcpPointToPlaneLowComplexityStrategy().c_str(), kIcpPointToPlane().c_str()));
RTABMAP_PARAM(Icp, PointToPlaneLowComplexityStrategy, int, 1, uFormat("If structural complexity is below %s: set to 0 to so that the transform is automatically rejected, set to 1 to limit ICP correction in axes with most constraints (e.g., for a corridor-like environment, the resulting transform will be limited in y and yaw, x will taken from the guess), set to 2 to accept \"as is\" the transform computed by PointToPoint.", kIcpPointToPlaneMinComplexity().c_str()));
// libpointmatcher
#ifdef RTABMAP_POINTMATCHER
@@ -630,6 +663,7 @@ class RTABMAP_EXP Parameters
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, 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, PMMatcherIntensity, bool, false, uFormat("KDTreeMatcher: among nearest neighbors, keep only the one with the most similar intensity. This only work with %s>1.", kIcpPMMatcherKnn().c_str()));
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
@@ -723,6 +757,8 @@ class RTABMAP_EXP Parameters
RTABMAP_PARAM(Marker, VarianceLinear, float, 0.001, "Linear variance to set on marker detections.");
RTABMAP_PARAM(Marker, VarianceAngular, float, 0.01, "Angular variance to set on marker detections. Set to >=9999 to use only position (xyz) constraint in graph optimization.");
RTABMAP_PARAM(Marker, CornerRefinementMethod, int, 0, "Corner refinement method (0: None, 1: Subpixel, 2:contour, 3: AprilTag2). For OpenCV <3.3.0, this is \"doCornerRefinement\" parameter: set 0 for false and 1 for true.");
RTABMAP_PARAM(Marker, MaxRange, float, 0.0, "Maximum range in which markers will be detected. <=0 for unlimited range.");
RTABMAP_PARAM(Marker, MinRange, float, 0.0, "Miniminum range in which markers will be detected. <=0 for unlimited range.");
RTABMAP_PARAM(ImuFilter, MadgwickGain, double, 0.1, "Gain of the filter. Higher values lead to faster convergence but more noise. Lower values lead to slower convergence but smoother signal, belongs in [0, 1].");
RTABMAP_PARAM(ImuFilter, MadgwickZeta, double, 0.0, "Gyro drift gain (approx. rad/s), belongs in [-1, 1].");
@@ -810,4 +846,3 @@ private:
}
#endif /* PARAMETERS_H_ */

View File

@@ -60,6 +60,8 @@ private:
float _maxRotation;
float _voxelSize;
int _downsamplingStep;
float _rangeMin;
float _rangeMax;
float _maxCorrespondenceDistance;
int _maxIterations;
float _epsilon;
@@ -67,11 +69,14 @@ private:
bool _pointToPlane;
int _pointToPlaneK;
float _pointToPlaneRadius;
float _pointToPlaneGroundNormalsUp;
float _pointToPlaneMinComplexity;
int _pointToPlaneLowComplexityStrategy;
bool _libpointmatcher;
std::string _libpointmatcherConfig;
int _libpointmatcherKnn;
float _libpointmatcherEpsilon;
bool _libpointmatcherIntensity;
float _libpointmatcherOutlierRatio;
void * _libpointmatcherICP;
};

View File

@@ -37,11 +37,15 @@ public:
RegistrationInfo() :
totalTime(0.0),
inliers(0),
inliersMeanDistance(0.0f),
inliersDistribution(0.0f),
matches(0),
icpInliersRatio(0),
icpTranslation(0.0f),
icpRotation(0.0f),
icpStructuralComplexity(0.0f)
icpStructuralComplexity(0.0f),
icpStructuralDistribution(0.0f),
icpCorrespondences(0)
{
}
@@ -53,11 +57,15 @@ public:
output.covariance = covariance.clone();
output.rejectedMsg = rejectedMsg;
output.inliers = inliers;
output.inliersMeanDistance = inliersMeanDistance;
output.inliersDistribution = inliersDistribution;
output.matches = matches;
output.icpInliersRatio = icpInliersRatio;
output.icpTranslation = icpTranslation;
output.icpRotation = icpRotation;
output.icpStructuralComplexity = icpStructuralComplexity;
output.icpStructuralDistribution = icpStructuralDistribution;
output.icpCorrespondences = icpCorrespondences;
return output;
}
@@ -67,6 +75,9 @@ public:
// RegistrationVis
int inliers;
float inliersRatio;
float inliersMeanDistance;
float inliersDistribution;
std::vector<int> inliersIDs;
int matches;
std::vector<int> matchesIDs;
@@ -77,6 +88,8 @@ public:
float icpTranslation;
float icpRotation;
float icpStructuralComplexity;
float icpStructuralDistribution;
int icpCorrespondences;
};
}

View File

@@ -37,6 +37,10 @@ namespace rtabmap {
class Feature2D;
#ifdef RTABMAP_PYMATCHER
class PyMatcher;
#endif
// Visual registration
class RTABMAP_EXP RegistrationVis : public Registration
{
@@ -50,8 +54,11 @@ public:
float getInlierDistance() const {return _inlierDistance;}
int getIterations() const {return _iterations;}
int getMinInliers() const {return _minInliers;}
int getNNType() const {return _nnType;}
float getNNDR() const {return _nndr;}
int getEstimationType() const {return _estimationType;}
Feature2D * createFeatureDetector() const; // for convenience
const Feature2D * getDetector() const {return _detectorFrom;}
protected:
virtual Transform computeTransformationImpl(
@@ -81,13 +88,26 @@ private:
float _flowEps;
int _flowMaxLevel;
float _nndr;
int _nnType;
bool _gmsWithRotation;
bool _gmsWithScale;
double _gmsThresholdFactor;
int _guessWinSize;
bool _guessMatchToProjection;
int _bundleAdjustment;
bool _depthAsMask;
float _minInliersDistributionThr;
float _maxInliersMeanDistance;
ParametersMap _featureParameters;
ParametersMap _bundleParameters;
Feature2D * _detectorFrom;
Feature2D * _detectorTo;
#ifdef RTABMAP_PYMATCHER
PyMatcher * _pyMatcher;
#endif
};
}

View File

@@ -86,8 +86,32 @@ public:
const cv::Mat & image,
int id=0, const std::map<std::string, float> & externalStats = std::map<std::string, float>());
void init(const ParametersMap & parameters, const std::string & databasePath = "");
void init(const std::string & configFile = "", const std::string & databasePath = "");
/**
* Initialize Rtabmap with parameters and a database
* @param parameters Parameters overriding default parameters and database parameters
* (@see loadDatabaseParameters)
* @param databasePath The database input/output path. If not set, an
* empty database is used in RAM. If set and the file doesn't exist,
* it will be created empty. If the database exists, nodes and
* vocabulary will be loaded in working memory.
* @param loadDatabaseParameters If an existing database is used (@see databasePath),
* the parameters inside are loaded and set to current
* Rtabmap instance.
*/
void init(const ParametersMap & parameters, const std::string & databasePath = "", bool loadDatabaseParameters = false);
/**
* Initialize Rtabmap with parameters from a configuration file and a database
* @param configFile Configuration file (*.ini) overriding default parameters and database parameters
* (@see loadDatabaseParameters)
* @param databasePath The database input/output path. If not set, an
* empty database is used in RAM. If set and the file doesn't exist,
* it will be created empty. If the database exists, nodes and
* vocabulary will be loaded in working memory.
* @param loadDatabaseParameters If an existing database is used (@see databasePath),
* the parameters inside are loaded and set to current
* Rtabmap instance.
*/
void init(const std::string & configFile = "", const std::string & databasePath = "", bool loadDatabaseParameters = false);
/**
* Close rtabmap. This will delete rtabmap object if set.
@@ -112,11 +136,9 @@ public:
std::map<int, int> getWeights() const;
int getTotalMemSize() const;
double getLastProcessTime() const {return _lastProcessTime;};
std::multimap<int, cv::KeyPoint> getWords(int locationId) const;
bool isInSTM(int locationId) const;
bool isIDsGenerated() const;
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;
@@ -156,16 +178,26 @@ public:
void rejectLastLoopClosure();
void deleteLastLocation();
void setOptimizedPoses(const std::map<int, Transform> & poses);
void get3DMap(std::map<int, Signature> & signatures,
std::map<int, Transform> & poses,
std::multimap<int, Link> & constraints,
bool optimized,
bool global) const;
Signature getSignatureCopy(int id, bool images, bool scan, bool userData, bool occupancyGrid, bool withWords, bool withGlobalDescriptors) const;
RTABMAP_DEPRECATED(
void get3DMap(std::map<int, Signature> & signatures,
std::map<int, Transform> & poses,
std::multimap<int, Link> & constraints,
bool optimized,
bool global) const, "Use getGraph() instead with withImages=true, withScan=true, withUserData=true and withGrid=true.");
void getGraph(std::map<int, Transform> & poses,
std::multimap<int, Link> & constraints,
bool optimized,
bool global,
std::map<int, Signature> * signatures = 0);
std::map<int, Signature> * signatures = 0,
bool withImages = false,
bool withScan = false,
bool withUserData = false,
bool withGrid = false,
bool withWords = true,
bool withGlobalDescriptors = true) const;
std::map<int, Transform> getNodesInRadius(const Transform & pose, float radius); // If radius=0, RGBD/LocalRadius is used. Can return landmarks.
std::map<int, Transform> getNodesInRadius(int nodeId, float radius); // If nodeId==0, return poses around latest node. If radius=0, RGBD/LocalRadius is used. Can return landmarks and use landmark id (negative) as request.
int detectMoreLoopClosures(
float clusterRadius = 0.5f,
float clusterAngle = M_PI/6.0f,
@@ -174,6 +206,7 @@ public:
bool interSession = true,
const ProgressState * state = 0);
int refineLinks();
bool addLink(const Link & link);
cv::Mat getInformation(const cv::Mat & covariance) const;
int getPathStatus() const {return _pathStatus;} // -1=failed 0=idle/executing 1=success
@@ -230,6 +263,7 @@ private:
unsigned int _maxMemoryAllowed; // signatures count in WM
float _loopThr;
float _loopRatio;
float _maxLoopClosureDistance;
bool _verifyLoopClosureHypothesis;
unsigned int _maxRetrieved;
unsigned int _maxLocalRetrieved;
@@ -255,6 +289,7 @@ private:
float _proximityFilteringRadius;
bool _proximityRawPosesUsed;
float _proximityAngle;
bool _proximityOdomGuess;
std::string _databasePath;
bool _optimizeFromGraphEnd;
float _optimizationMaxError;
@@ -275,6 +310,8 @@ private:
double _lastProcessTime;
bool _someNodesHaveBeenTransferred;
float _distanceTravelled;
float _distanceTravelledSinceLastLocalization;
bool _optimizeFromGraphEndChanged;
// Abstract classes containing all loop closure
// strategies for a type of signature or configuration.
@@ -304,6 +341,8 @@ private:
bool _currentSessionHasGPS;
std::map<int, Transform> _odomCachePoses; // used in localization mode to reject loop closures
std::multimap<int, Link> _odomCacheConstraints; // used in localization mode to reject loop closures
std::map<int, Transform> _odomCacheAddLink; // used in localization mode when adding external link
std::vector<float> _odomCorrectionAcc;
// Planning stuff
int _pathStatus;

View File

@@ -40,6 +40,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <rtabmap/core/GPS.h>
#include <rtabmap/core/EnvSensor.h>
#include <rtabmap/core/Landmark.h>
#include <rtabmap/core/GlobalDescriptor.h>
namespace rtabmap
{
@@ -249,6 +250,11 @@ public:
const std::vector<cv::Point3f> & keypoints3D() const {return _keypoints3D;}
const cv::Mat & descriptors() const {return _descriptors;}
void addGlobalDescriptor(const GlobalDescriptor & descriptor) {_globalDescriptors.push_back(descriptor);}
void setGlobalDescriptors(const std::vector<GlobalDescriptor> & descriptors) {_globalDescriptors = descriptors;}
void clearGlobalDescriptors() {_globalDescriptors.clear();}
const std::vector<GlobalDescriptor> & globalDescriptors() const {return _globalDescriptors;}
void setGroundTruth(const Transform & pose) {groundTruth_ = pose;}
const Transform & groundTruth() const {return groundTruth_;}
@@ -269,7 +275,7 @@ public:
void setLandmarks(const Landmarks & landmarks) {_landmarks = landmarks;}
const Landmarks & landmarks() const {return _landmarks;}
long getMemoryUsed() const; // Return memory usage in Bytes
unsigned long getMemoryUsed() const; // Return memory usage in Bytes
/**
* Clear compressed rgb/depth (left/right) images, compressed laser scan and compressed user data.
* Raw data are kept is set.
@@ -323,6 +329,9 @@ private:
std::vector<cv::Point3f> _keypoints3D;
cv::Mat _descriptors;
// global descriptors
std::vector<GlobalDescriptor> _globalDescriptors;
Transform groundTruth_;
Transform globalPose_;

View File

@@ -86,12 +86,13 @@ public:
void changeLinkIds(int idFrom, int idTo);
void removeLinks();
void removeLinks(bool keepSelfReferringLinks = false);
void removeLink(int idTo);
void removeVirtualLinks();
void addLandmark(const Link & landmark) {_landmarks.insert(std::make_pair(landmark.to(), landmark));}
const std::map<int, Link> & getLandmarks() const {return _landmarks;}
void removeLandmarks() {_landmarks.clear();}
void setSaved(bool saved) {_saved = saved;}
void setModified(bool modified) {_modified = modified; _linksModified = modified;}
@@ -103,19 +104,18 @@ public:
//visual words stuff
void removeAllWords();
void removeWord(int wordId);
void changeWordsRef(int oldWordId, int activeWordId);
void setWords(const std::multimap<int, cv::KeyPoint> & words);
void setWords(const std::multimap<int, int> & words, const std::vector<cv::KeyPoint> & keypoints, const std::vector<cv::Point3f> & words3, const cv::Mat & descriptors);
bool isEnabled() const {return _enabled;}
void setEnabled(bool enabled) {_enabled = enabled;}
const std::multimap<int, cv::KeyPoint> & getWords() const {return _words;}
const std::multimap<int, int> & getWords() const {return _words;}
const std::vector<cv::KeyPoint> & getWordsKpts() const {return _wordsKpts;}
int getInvalidWordsCount() const {return _invalidWordsCount;}
const std::map<int, int> & getWordsChanged() const {return _wordsChanged;}
const std::multimap<int, cv::Mat> & getWordsDescriptors() const {return _wordsDescriptors;}
void setWordsDescriptors(const std::multimap<int, cv::Mat> & descriptors) {_wordsDescriptors = descriptors;}
const cv::Mat & getWordsDescriptors() const {return _wordsDescriptors;}
void setWordsDescriptors(const cv::Mat & descriptors);
//metric stuff
void setWords3(const std::multimap<int, cv::Point3f> & words3) {_words3 = words3;}
void setPose(const Transform & pose) {_pose = pose;}
void setGroundTruthPose(const Transform & pose) {_groundTruthPose = pose;}
void setVelocity(float vx, float vy, float vz, float vroll, float vpitch, float vyaw) {
@@ -128,7 +128,7 @@ public:
_velocity[5]=vyaw;
}
const std::multimap<int, cv::Point3f> & getWords3() const {return _words3;}
const std::vector<cv::Point3f> & getWords3() const {return _words3;}
const Transform & getPose() const {return _pose;}
cv::Mat getPoseCovariance() const;
const Transform & getGroundTruthPose() const {return _groundTruthPose;}
@@ -137,7 +137,7 @@ public:
SensorData & sensorData() {return _sensorData;}
const SensorData & sensorData() const {return _sensorData;}
long getMemoryUsed(bool withSensorData=true) const; // Return memory usage in Bytes
unsigned long getMemoryUsed(bool withSensorData=true) const; // Return memory usage in Bytes
private:
int _id;
@@ -154,9 +154,10 @@ private:
// Contains all words (Some can be duplicates -> if a word appears 2
// times in the signature, it will be 2 times in this list)
// Words match with the CvSeq keypoints and descriptors
std::multimap<int, cv::KeyPoint> _words; // word <id, keypoint>
std::multimap<int, cv::Point3f> _words3; // word <id, point> // in base_link frame (localTransform applied))
std::multimap<int, cv::Mat> _wordsDescriptors;
std::multimap<int, int> _words; // word <id, keypoint index>
std::vector<cv::KeyPoint> _wordsKpts;
std::vector<cv::Point3f> _words3; // in base_link frame (localTransform applied))
cv::Mat _wordsDescriptors;
std::map<int, int> _wordsChanged; // <oldId, newId>
bool _enabled;
int _invalidWordsCount;

View File

@@ -48,20 +48,26 @@ namespace rtabmap {
public: \
Dummy##PREFIX##NAME() {if(!_defaultDataInitialized)_defaultData.insert(std::pair<std::string, float>(#PREFIX "/" #NAME "/" #UNIT, 0.0f));} \
}; \
Dummy##PREFIX##NAME dummy##PREFIX##NAME;
Dummy##PREFIX##NAME dummy##PREFIX##NAME
class RTABMAP_EXP Statistics
{
RTABMAP_STATS(Loop, Id,); // Combined loop or proximity detection
RTABMAP_STATS(Loop, RejectedHypothesis,);
RTABMAP_STATS(Loop, Accepted_hypothesis_id,);
RTABMAP_STATS(Loop, Suppressed_hypothesis_id,);
RTABMAP_STATS(Loop, Highest_hypothesis_id,);
RTABMAP_STATS(Loop, Highest_hypothesis_value,);
RTABMAP_STATS(Loop, Vp_hypothesis,);
RTABMAP_STATS(Loop, Reactivate_id,);
RTABMAP_STATS(Loop, Hypothesis_ratio,);
RTABMAP_STATS(Loop, Hypothesis_reactivated,);
RTABMAP_STATS(Loop, Map_id,);
RTABMAP_STATS(Loop, Visual_words,);
RTABMAP_STATS(Loop, Visual_inliers,);
RTABMAP_STATS(Loop, Visual_inliers_ratio,);
RTABMAP_STATS(Loop, Visual_matches,);
RTABMAP_STATS(Loop, Distance_since_last_loc,);
RTABMAP_STATS(Loop, Last_id,);
RTABMAP_STATS(Loop, Optimization_max_error, m);
RTABMAP_STATS(Loop, Optimization_max_error_ratio, );
@@ -71,6 +77,42 @@ class RTABMAP_EXP Statistics
RTABMAP_STATS(Loop, Angular_variance,);
RTABMAP_STATS(Loop, Landmark_detected,);
RTABMAP_STATS(Loop, Landmark_detected_node_ref,);
RTABMAP_STATS(Loop, Visual_inliers_mean_dist,m);
RTABMAP_STATS(Loop, Visual_inliers_distribution,);
//Odom correction
RTABMAP_STATS(Loop, Odom_correction_norm, m);
RTABMAP_STATS(Loop, Odom_correction_angle, deg);
RTABMAP_STATS(Loop, Odom_correction_x, m);
RTABMAP_STATS(Loop, Odom_correction_y, m);
RTABMAP_STATS(Loop, Odom_correction_z, m);
RTABMAP_STATS(Loop, Odom_correction_roll, deg);
RTABMAP_STATS(Loop, Odom_correction_pitch, deg);
RTABMAP_STATS(Loop, Odom_correction_yaw, deg);
//Odom correction
RTABMAP_STATS(Loop, Odom_correction_acc_norm, m);
RTABMAP_STATS(Loop, Odom_correction_acc_angle, deg);
RTABMAP_STATS(Loop, Odom_correction_acc_x, m);
RTABMAP_STATS(Loop, Odom_correction_acc_y, m);
RTABMAP_STATS(Loop, Odom_correction_acc_z, m);
RTABMAP_STATS(Loop, Odom_correction_acc_roll, deg);
RTABMAP_STATS(Loop, Odom_correction_acc_pitch, deg);
RTABMAP_STATS(Loop, Odom_correction_acc_yaw, deg);
// Map to Odom
RTABMAP_STATS(Loop, MapToOdom_norm, m);
RTABMAP_STATS(Loop, MapToOdom_angle, deg);
RTABMAP_STATS(Loop, MapToOdom_x, m);
RTABMAP_STATS(Loop, MapToOdom_y, m);
RTABMAP_STATS(Loop, MapToOdom_z, m);
RTABMAP_STATS(Loop, MapToOdom_roll, deg);
RTABMAP_STATS(Loop, MapToOdom_pitch, deg);
RTABMAP_STATS(Loop, MapToOdom_yaw, deg);
// Map to Base
RTABMAP_STATS(Loop, MapToBase_x, m);
RTABMAP_STATS(Loop, MapToBase_y, m);
RTABMAP_STATS(Loop, MapToBase_z, m);
RTABMAP_STATS(Loop, MapToBase_roll, deg);
RTABMAP_STATS(Loop, MapToBase_pitch, deg);
RTABMAP_STATS(Loop, MapToBase_yaw, deg);
RTABMAP_STATS(Proximity, Time_detections,);
RTABMAP_STATS(Proximity, Space_last_detection_id,);
@@ -108,6 +150,7 @@ class RTABMAP_EXP Statistics
RTABMAP_STATS(Memory, Odometry_variance_lin,);
RTABMAP_STATS(Memory, Distance_travelled, m);
RTABMAP_STATS(Memory, RAM_usage, MB);
RTABMAP_STATS(Memory, RAM_estimated, MB);
RTABMAP_STATS(Memory, Triangulated_points, );
RTABMAP_STATS(Timing, Memory_update, ms);
@@ -130,6 +173,7 @@ class RTABMAP_EXP Statistics
RTABMAP_STATS(Timing, Joining_trash, ms);
RTABMAP_STATS(Timing, Emptying_trash, ms);
RTABMAP_STATS(Timing, Finalizing_statistics, ms);
RTABMAP_STATS(Timing, RAM_estimation, ms);
RTABMAP_STATS(TimingMem, Pre_update, ms);
RTABMAP_STATS(TimingMem, Signature_creation, ms);
@@ -150,6 +194,7 @@ class RTABMAP_EXP Statistics
RTABMAP_STATS(TimingMem, Markers_detection, ms);
RTABMAP_STATS(Keypoint, Dictionary_size, words);
RTABMAP_STATS(Keypoint, Current_frame, words);
RTABMAP_STATS(Keypoint, Indexed_words, words);
RTABMAP_STATS(Keypoint, Index_memory_usage, KB);
@@ -165,6 +210,8 @@ class RTABMAP_EXP Statistics
RTABMAP_STATS(Gt, Rotational_std, deg);
RTABMAP_STATS(Gt, Rotational_min, deg);
RTABMAP_STATS(Gt, Rotational_max, deg);
RTABMAP_STATS(Gt, Localization_linear_error, m);
RTABMAP_STATS(Gt, Localization_angular_error, deg);
public:
static const std::map<std::string, float> & defaultData();

View File

@@ -43,7 +43,7 @@ public:
const cv::Size & imageSize2,
const cv::Mat & K2, const cv::Mat & D2, const cv::Mat & R2, const cv::Mat & P2,
const cv::Mat & R, const cv::Mat & T, const cv::Mat & E, const cv::Mat & F,
const Transform & localTransform = Transform::getIdentity());
const Transform & localTransform = Transform(0,0,1,0, -1,0,0,0, 0,-1,0,0));
// if R and T are not null, left and right camera models should be valid to be rectified.
StereoCameraModel(
@@ -68,7 +68,7 @@ public:
double cx,
double cy,
double baseline,
const Transform & localTransform = Transform::getIdentity(),
const Transform & localTransform = Transform(0,0,1,0, -1,0,0,0, 0,-1,0,0),
const cv::Size & imageSize = cv::Size(0,0));
//minimal to be saved
StereoCameraModel(
@@ -78,7 +78,7 @@ public:
double cx,
double cy,
double baseline,
const Transform & localTransform = Transform::getIdentity(),
const Transform & localTransform = Transform(0,0,1,0, -1,0,0,0, 0,-1,0,0),
const cv::Size & imageSize = cv::Size(0,0));
virtual ~StereoCameraModel() {}
@@ -86,7 +86,7 @@ public:
bool isValidForRectification() const {return left_.isValidForRectification() && right_.isValidForRectification();}
void initRectificationMap() {left_.initRectificationMap(); right_.initRectificationMap();}
bool isRectificationMapInitialized() {return left_.isRectificationMapInitialized() && right_.isRectificationMapInitialized();}
bool isRectificationMapInitialized() const {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_;}
@@ -125,6 +125,9 @@ public:
const std::string & getLeftSuffix() const {return leftSuffix_;}
const std::string & getRightSuffix() const {return rightSuffix_;}
private:
void updateStereoRectification();
private:
std::string leftSuffix_;
std::string rightSuffix_;

View File

@@ -98,6 +98,7 @@ public:
float theta() const;
bool isInvertible() const;
Transform inverse() const;
Transform rotation() const;
Transform translation() const;
@@ -140,6 +141,15 @@ public:
static Transform fromEigen3f(const Eigen::Isometry3f & matrix);
static Transform fromEigen3d(const Eigen::Isometry3d & matrix);
static Transform opengl_T_rtabmap() {return Transform(
0.0f, -1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
-1.0f, 0.0f, 0.0f, 0.0f);}
static Transform rtabmap_T_opengl() {return Transform(
0.0f, 0.0f,-1.0f, 0.0f,
-1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f);}
/**
* Format (3 values): x y z
* Format (6 values): x y z roll pitch yaw
@@ -150,10 +160,13 @@ public:
static Transform fromString(const std::string & string);
static bool canParseString(const std::string & string);
static Transform getClosestTransform(
static Transform getTransform(
const std::map<double, Transform> & tfBuffer,
const double & stamp);
RTABMAP_DEPRECATED(static Transform getClosestTransform(
const std::map<double, Transform> & tfBuffer,
const double & stamp,
double * stampDiff = 0);
double * stampDiff), "Use Transform::getTransform() instead to get always accurate transforms.");
private:
cv::Mat data_;

View File

@@ -55,6 +55,23 @@ public:
kNNUndef};
static const int ID_START;
static const int ID_INVALID;
static std::string nnStrategyName(NNStrategy strategy)
{
switch(strategy) {
case kNNFlannNaive:
return "FLANN NAIVE";
case kNNFlannKdTree:
return "FLANN KD-TREE";
case kNNFlannLSH:
return "FLANN LSH";
case kNNBruteForce:
return "BRUTE FORCE";
case kNNBruteForceGPU:
return "BRUTE FORCE GPU";
default:
return "Unknown";
}
}
public:
VWDictionary(const ParametersMap & parameters = ParametersMap());
@@ -83,8 +100,9 @@ public:
int getLastIndexedWordId() const;
int getTotalActiveReferences() const {return _totalActiveReferences;}
unsigned int getIndexedWordsCount() const;
unsigned int getIndexMemoryUsed() const;
void setNNStrategy(NNStrategy strategy);
unsigned int getIndexMemoryUsed() const; // KB
unsigned long getMemoryUsed() const; //Bytes
bool setNNStrategy(NNStrategy strategy); // Return true if the search tree has been re-initialized
bool isIncremental() const {return _incrementalDictionary;}
bool isIncrementalFlann() const {return _incrementalFlann;}
void setIncrementalDictionary();
@@ -100,8 +118,8 @@ public:
void deleteUnusedWords();
public:
static cv::Mat convertBinTo32F(const cv::Mat & descriptorsIn);
static cv::Mat convert32FToBin(const cv::Mat & descriptorsIn);
static cv::Mat convertBinTo32F(const cv::Mat & descriptorsIn, bool byteToFloat = true);
static cv::Mat convert32FToBin(const cv::Mat & descriptorsIn, bool byteToFloat = true);
protected:
int getNextId();
@@ -114,8 +132,10 @@ private:
bool _incrementalDictionary;
bool _incrementalFlann;
float _rebalancingFactor;
bool _byteToFloat;
float _nndrRatio;
std::string _dictionaryPath; // a pre-computed dictionary (.txt)
std::string _dictionaryPath; // a pre-computed dictionary (.txt or .db)
std::string _newDictionaryPath; // a pre-computed dictionary (.txt or .db)
bool _newWordsComparedTogether;
int _lastWordId;
bool useDistanceL1_;

View File

@@ -43,6 +43,7 @@ public:
void addRef(int signatureId);
int removeAllRef(int signatureId);
unsigned long getMemoryUsed() const;
int getTotalReferences() const {return _totalReferences;}
int id() const {return _id;}

View File

@@ -53,7 +53,7 @@ public:
CameraFreenect(int deviceId= 0,
Type type = kTypeColorDepth,
float imageRate=0.0f,
const Transform & localTransform = Transform::getIdentity());
const Transform & localTransform = CameraModel::opticalRotation());
virtual ~CameraFreenect();
virtual bool init(const std::string & calibrationFolder = ".", const std::string & cameraName = "");

View File

@@ -65,7 +65,7 @@ public:
CameraFreenect2(int deviceId= 0,
Type type = kTypeDepth2ColorSD,
float imageRate=0.0f,
const Transform & localTransform = Transform::getIdentity(),
const Transform & localTransform = CameraModel::opticalRotation(),
float minDepth = 0.3f,
float maxDepth = 12.0f,
bool bilateralFiltering = true,

View File

@@ -46,7 +46,7 @@ public:
CameraImages(
const std::string & path,
float imageRate = 0,
const Transform & localTransform = Transform::getIdentity());
const Transform & localTransform = CameraModel::opticalRotation());
virtual ~CameraImages();
virtual bool init(const std::string & calibrationFolder = ".", const std::string & cameraName = "");
@@ -74,6 +74,11 @@ public:
_syncImageRateWithStamps = syncImageRateWithStamps;
}
void setConfigForEachFrame(bool value)
{
_hasConfigForEachFrame = value;
}
void setScanPath(
const std::string & dir,
int maxScanPts = 0,
@@ -116,12 +121,14 @@ public:
protected:
virtual SensorData captureImage(CameraInfo * info = 0);
private:
bool readPoses(
std::list<Transform> & outputPoses,
std::list<double> & stamps,
const std::string & filePath,
int format,
double maxTimeDiff) const;
std::list<Transform> & outputPoses,
std::list<double> & stamps,
const std::string & filePath,
int format,
double maxTimeDiff) const;
private:
std::string _path;
@@ -151,6 +158,7 @@ private:
bool _depthFromScanFillHolesFromBorder;
bool _filenamesAreTimestamps;
bool _hasConfigForEachFrame;
std::string _timestampsPath;
bool _syncImageRateWithStamps;
@@ -162,8 +170,10 @@ private:
std::list<double> _stamps;
std::list<Transform> odometry_;
std::list<cv::Mat> covariances_;
std::list<Transform> groundTruth_;
CameraModel _model;
std::list<CameraModel> _models;
UTimer _captureTimer;
double _captureDelay;

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