Compare commits

..

328 Commits

Author SHA1 Message Date
matlabbe
95e6a9f039 bump 0.20.23 2023-01-21 16:09:41 -08:00
matlabbe
b5eef4b86a DBViewer: ignore marker constraints in refine, add marker priors when optimizing the graph 2023-01-21 15:52:01 -08:00
reito
40ab33031b fix bigobj under MSVC, fix yaml-cpp link. (#957) 2023-01-21 15:50:02 -08:00
reito
0e908206d0 OpenCV 4.7 moved aruco back to opencv repo, and makes some breaking changes. (#955) 2023-01-16 16:41:48 -08:00
matlabbe
6b9f7de782 Fixed a -pedantic warning 2023-01-16 14:14:25 -08:00
matlabbe
22fede9335 Reprocess: added --odom option to recompute odometry. 2023-01-15 15:07:24 -08:00
matlabbe
22917cc1c3 VTK9: Fixed vtkGUISupportQt -> VTK::GUISupportQt 2023-01-14 20:12:33 -08:00
matlabbe
98bf3fb184 workflows: removed galactic build (EOF) 2023-01-08 16:59:24 -08:00
matlabbe
8d301afe6c reprocess: added --default option 2023-01-08 16:29:44 -08:00
matlabbe
e3ceb8a572 VINS-Fusion: Fixed error wrongly logged when only imu is processed by vins. 2023-01-08 15:22:46 -08:00
matlabbe
f12cc83fc2 RegVis: using toSignature camera model for guess reprojection on optical flow mode (#947) 2022-12-20 20:51:56 -08:00
matlabbe
4a6a765cd1 Fixed #944 2022-12-14 19:42:56 -08:00
matlabbe
a4761ad397 Fixed #940 2022-12-11 01:12:21 -08:00
matlabbe
aa380de2a7 Update install_deps.sh
Removed vtk default iOS simulator build
2022-12-07 17:59:11 -08:00
matlabbe
467dc738c7 Fixed deprecated warning not set to right function 2022-12-05 20:32:53 -08:00
matlabbe
64cb7fb6fe export: when --images and --cam_projection are used, we export depth image from lidar projection to RGB frames 2022-12-04 17:23:33 -08:00
matlabbe
8a8c360f89 fixed compilation warning 2022-11-27 16:20:56 -08:00
matlabbe
83693ed1b9 detectMoreLoopClosures: fixed guess not set for lidar-only registration (https://github.com/introlab/rtabmap_ros/issues/727) 2022-11-26 20:24:43 -08:00
matlabbe
860c14e0ec rtabmap: fixed export poses in format 10 and 11 (#883) 2022-11-26 12:42:04 -08:00
matlabbe
85bc1ee27f GTSAM: return empty optimized poses in case of exception or error. g2o: don't assert on marginal not computed, log error and reutn empty optimized poses. 2022-11-22 12:26:02 -08:00
matlabbe
05676d1577 ios: Moved install_deps.sh in upper directory to easy cleanup Libraries. Fixed uNumber2Str(double) link error. 2022-11-19 12:41:01 -08:00
matlabbe
6d713c2ccb uNumberToStr(double): added "fixed" param (default false) to fix ros param double/int conversion issue. 2022-11-11 16:20:59 -08:00
matlabbe
16e3314e64 💄 2022-11-11 14:45:33 -08:00
matlabbe
d59a306ae3 Export: fixed depth image wrongly set for stereo data 2022-11-10 17:18:57 -08:00
matlabbe
bdfab4e0be reprocess: added "-a" option (append mode) 2022-11-02 15:06:13 -07:00
matlabbe
c9d50ef445 Export GPS poses: set 8 decimals (1 mm accuracy) https://github.com/introlab/rtabmap_ros/issues/833 2022-11-02 11:35:54 -07:00
matlabbe
2889cf8048 GUI: fixed latest data requested on localization mode 2022-10-31 13:21:13 -07:00
matlabbe
def876983d docker/android: fixed docker not detecting compilation failure. ios: added exit flag for install_deps.sh script 2022-10-30 15:07:55 -07:00
matlabbe
69214b927a fixed android build 2022-10-30 14:47:34 -07:00
matlabbe
67b2cbe5ca docker: set dummy build-args for build not required them 2022-10-30 14:39:33 -07:00
matlabbe
86f66cc8b8 Added missing signature info in republished data 2022-10-30 13:59:08 -07:00
matlabbe
d70924a3a4 bump package version 0.20.22 2022-10-28 12:30:01 -07:00
matlabbe
1297714271 Bump version 0.20.22. Refactored RtabmapThread commands handling. MainWindow/RtabmapThread/Statistics/UVariant: added new option to republish missing data on GUI side. MainWindow: fixed 1 sec lag when waypoints are used. Parameters: added Rtabmap/MaxRepublished (moved from rtabmap_ros). OccupancyGrid: fixed ground cells ignored if there are empty cells, also don't add pose in addedNodes if corresponding node was not in cache. 2022-10-28 12:25:48 -07:00
matlabbe
8e30c1c812 GraphView: added user link on inter/intra loop closure color scheme option 2022-10-24 17:45:16 -07:00
matlabbe
df888962f4 depthai: fixed app freezing if oakd device (oak-d lite) doesn't have imu and imu is requested. 2022-10-24 11:13:27 -07:00
matlabbe
a8cdf1f940 reprocess: disable Mem/UseOdomFeatures by default when there are more than 1 input database 2022-10-24 10:34:37 -07:00
matlabbe
769ace86ce Added oak-d lite menu option (depthai: imu is now optionnal) 2022-10-23 18:15:23 -07:00
matlabbe
97a150b180 DbViewer: added option to regenerate optimized 2d map from OctoMap (https://github.com/introlab/rtabmap_ros/issues/213) 2022-10-23 12:16:35 -07:00
matlabbe
6e8f43916c floam: republish input scan with features 2022-10-16 21:31:43 -07:00
matlabbe
5b0047efad docker: fixed AliceVision build (bionic/focal) 2022-10-15 14:06:20 -07:00
matlabbe
fdb78d33b0 DBViewer: added optimzed and prior poses in node details. Reprocess: add start_s, stop_s and pub_loops options. 2022-10-12 13:05:01 -07:00
matlabbe
2cbd43dfb6 Update cmake-ros.yml
Added ros2 distros
2022-10-09 12:47:03 -07:00
matlabbe
1f06386f37 Update README.md 2022-10-09 12:22:09 -07:00
matlabbe
1e9b090624 Gui: Added re-localization colors on odom cache graph. Added frame labels (map, odom). 2022-10-04 16:27:33 -07:00
matlabbe
7e3e5ec50b DBViewer: fixed matching lines when two images don't have the same number of cameras. Fixed nodes with w=-9 can be used to add constraint (in case localization data is saved in database). Add constraint: compute transform in order of the sliders. 2022-10-04 14:23:12 -07:00
matlabbe
8d23f19f6c bump ros package version 2022-10-01 18:30:51 -07:00
matlabbe
9afbcf2d06 detectMoreLoopClosures tool: regenerate global occupancy grid for convenience if there was one before 2022-09-30 15:48:09 -07:00
matlabbe
30bf5895ca Fixed #909 2022-09-30 14:17:23 -07:00
matlabbe
e0a2adcb45 Updated latest jfr2018 docker 2022-09-27 16:37:25 -07:00
matlabbe
87faea7a85 Fixed ceres linker issue with floam dependency (if WITH_CERES is OFF) 2022-09-27 23:35:13 +00:00
matlabbe
74c6e9cfec Fixed compilation error about stereoCameraModel() not found (#905) with OpenVINS odometry 2022-09-27 13:48:57 -07:00
matlabbe
675dad5f76 Fixed compilation error about stereoCameraModel() not found (#905) with odometry approaches: Fovis, MSCKF, Okvis, VINS, Viso2. 2022-09-27 18:56:05 +00:00
matlabbe
55546132a0 Fixed build on 16.04 2022-09-27 17:22:52 +00:00
matlabbe
fa31affea0 Pnp multicam refactoring (#902)
* gui: fixed wrongly showing landmark rejected when it was not (because a loop closure was rejected at the same time)

* Added Vis/PnPMaxVariance and RGBD/InvertedReg parameters. Implemented inlier distribution computation for multicam.

* On loc/small displacement: don't remove from odom cache if loop is rejected (maybe first loc)

* Loc: don't prune odom cache on small movement if delayed loc is enabled

* loc/small movement: cleanup bidirectional links

* Cov/PnP: fixed objPt transform to estimate depth

Co-authored-by: mathieu86 <mathieu@robust.ai>
2022-09-24 12:29:42 -07:00
matlabbe
95a76cb696 gui: fixed wrongly showing landmark rejected when it was not (because a loop closure was rejected at the same time) 2022-09-22 15:16:08 -07:00
matlabbe
737675c6f1 fixed dereference end iterator assert (#900) 2022-09-19 07:34:48 -07:00
matlabbe
4d6bc78e3d implement multi camera marker detection #898 (#899)
* Added multicamera marker detection support

* Fixed marker detection on camera index> 0

Co-authored-by: mathieu86 <mathieu@robust.ai>
2022-09-14 17:13:59 -07:00
matlabbe
adfb250d4e 2022-IlluminationInvariant: set RGBD/OptimizeMaxError to 0 to make it easier to reproduce results of the paper 2022-09-13 19:58:55 -07:00
matlabbe
a14b39b953 fixed android docker file not found on CI 2022-09-13 00:45:39 -07:00
matlabbe
3dd0965a15 Updated archive/2022-IlluminationInvariant/README.md 2022-09-13 00:29:44 -07:00
matlabbe
e059ead7f5 Merge branch 'master' of https://github.com/introlab/rtabmap 2022-09-12 23:22:59 -07:00
matlabbe
749cd096ff Fixed map::at() seg fault when localizing on a database with multiple disjoint sessions 2022-09-13 06:19:23 +00:00
matlabbe
37b920396c Added docker image for frontiers2022 (updated README in archive/2022-IlluminationInvariant) 2022-09-11 13:03:32 -07:00
matlabbe
0dc5fbdd70 fixed #873 2022-09-06 16:19:20 -07:00
matlabbe
f1c987a0ce Fixed android build (res tool not found) 2022-09-04 14:29:59 -04:00
matlabbe
69b0caed6f Update README.md 2022-09-04 13:39:40 -04:00
Windel Bouwman
8826f136a9 Use imported target for res_tool during cross compilation. (#865) 2022-09-04 13:18:14 -04:00
matlabbe
8cd4a6feff OdomF2M: fixed lidar-only broken from commit 9797918d52 2022-07-28 11:48:55 -04:00
matlabbe
33e54430a1 bump version 0.20.20 (api changes on CameraModel) 2022-07-28 10:51:13 -04:00
matlabbe
9797918d52 fixed https://github.com/introlab/rtabmap_ros/issues/790 2022-07-27 10:15:21 -04:00
matlabbe
aa3b71dbf6 docker: added missing wget dependency for arm64 (opengv dpendency) 2022-07-20 22:39:41 -04:00
matlabbe
34ed9d79c7 export: added --texture_blur filtering option 2022-07-20 22:08:45 -04:00
matlabbe
5943a8b065 Added stereo multi-camera support (#884)
* Integrated OpenGV

* Fixed build without opengv

* Cmake: moved OpenGV dependency status under solvers group

* Added multi-stereocamera models support

* Fixed OpenGV 0 sample error when one of the camera doesn't have features. Fixed g2o BA id offset with multi-camera.

* Fixed multicam 3d points generated from stereo correspondences

* db: Fixed multi stereo models not loaded correctly

* gui: fixed stereo rectification option, RegVis: fixed projection error with old databases (image size not set in calibration)

* OdomF2M: Fixed map.at error when bundle adjustment is not used

* depthai: added imu firmware update option for convenience

* Fixed various refactor errors

* Moved "large number stereo correspondences rejected" warning outside computeCorrespondences function for multicam

* Added error log if ba correspondences are computed with empty signatures

* fixed compilation errors with latest opencv

Co-authored-by: mathieu86 <mathieu@robust.ai>
2022-07-20 15:20:14 -04:00
matlabbe
71a28bb570 Update README.md 2022-06-29 22:23:56 -04:00
matlabbe
89f56642b7 Update README.md 2022-06-26 21:30:14 -07:00
matlabbe
fb6770d70f Update README.md 2022-06-26 20:59:20 -07:00
matlabbe
a10eb062e5 Update README.md 2022-06-26 20:58:15 -07:00
matlabbe
4d502c9e0d Create README.md 2022-06-26 20:54:34 -07:00
matlabbe
83c1adfd1e Updated illumination invariant paper documentation 2022-06-26 20:46:08 -07:00
mathieu86
bc42bc3520 Added Kp/ByteToFloat parameter to odom parameters 2022-06-09 10:51:08 -07:00
matlabbe
8f8256c1dd would fix: #618 #790 #795 (#871) 2022-05-30 07:24:04 -04:00
matlabbe
744c737da1 Update README.md 2022-05-28 17:22:50 -04:00
matlabbe
4cfd3ba496 Updated cmake workflow name 2022-05-28 17:20:49 -04:00
matlabbe
2da333895c workflow: added minimal build for Ubuntu 22.04 2022-05-28 17:14:55 -04:00
matlabbe
601e4015fb fixed android docker script path 2022-05-28 16:15:51 -04:00
matlabbe
47c94a4474 workflows docker: use current context instead of cloning the repo inside dockerfile 2022-05-28 16:11:52 -04:00
matlabbe
cf64b20e1f Fixed error: ‘drawAxis’ is not a member of ‘cv::aruco’ (opencv 4.5.5) 2022-05-10 22:47:15 -04:00
matlabbe
5d200a0799 Fixed _markerPriorsLinearVariance not intitialized 2022-05-05 11:08:44 -04:00
matlabbe
dab7aa6e58 export: added min_range option 2022-05-03 23:12:09 -04:00
matlabbe
b646c5e1db Marker priors (#859)
* Added MarkerPriors parameter

* Fixed Marker/Priors format to use '|' instead ';'. Fixed landmark priors not used.

* Marker: added priors variance parameters

* g2o: refactored backward compatibility includes

* fixed build with old g2o
2022-04-28 09:18:30 -04:00
matlabbe
190071678f Statistics: Added Memory/New_landmark. Rtabmap: don't remove node on small movements when a new landmark has been just detected. DbViewer: fixed missing statistics when ignored nodes are not saved in database. 2022-04-25 12:19:22 -04:00
matlabbe
dc58266eda ORBSLAM2: fixed build 2022-04-10 19:42:15 -04:00
matlabbe
e92dfd50e1 GUI: set default working dir if it is empty in the loaded config 2022-04-10 15:59:38 -04:00
matlabbe
1857111d7d Reprocess: added option to stream only one camera (in case of multi-camera database) 2022-04-06 14:07:23 -04:00
matlabbe
3e630e0250 UPlot: fixed number of digits after the decimal points to 6 when exporting data to text 2022-04-04 11:42:36 -04:00
matlabbe
d35193721b report tool: option --loc can be used without a number. 2022-04-01 13:53:32 -04:00
matlabbe
e46af2c3cd DbViewer: Added GroundTruth pose in node info labels 2022-03-31 12:00:52 -04:00
matlabbe
6cefc6d00a DBViewer: added camera frustums in Constraints View 2022-03-25 11:24:34 -04:00
matlabbe
ff739a98a5 Removed opencv's optflow module from required dependency (https://github.com/introlab/rtabmap/issues/427#issuecomment-1058767133) 2022-03-07 00:12:56 -05:00
matlabbe
4321c3040a CameraDepthAI: fixed imu transform and depth mode with latest depthai-core version 2022-03-06 22:25:01 -05:00
matlabbe
1e82fd3110 ImageView: added option to set maximum range for depth colormap 2022-03-03 18:01:04 -05:00
matlabbe
b9c7182a08 Update package.xml 2022-03-03 14:06:15 -05:00
matlabbe
656da152b3 multiband: fixed error when intermediate nodes without data are in memory 2022-03-01 18:42:43 -05:00
matlabbe
f140e99881 DBViewer: fixed kml export disabled for poses when there are gps values. Fixed commas used instead of dots for float in kml export on french machine. 2022-02-27 15:20:02 -05:00
matlabbe
53e0099dd8 ios: tmp database is now public, so it can be copied from file explorer / Finder in case recovery fails. 2022-02-27 14:32:19 -05:00
matlabbe
51f779628f Recovery: original database is erased/replaced only after successful recovery (in case there is an seg fault during recovery). 2022-02-27 13:50:40 -05:00
matlabbe
e7ee025127 Export: fixed texturing assert when there are intermediate nodes 2022-02-25 02:08:08 -05:00
matlabbe
e6a5fe9c26 Don't do neighbor refining if fast movement has been detected 2022-02-20 18:09:39 -05:00
matlabbe
e297320dd5 Removed backward compatibility with RGBD/OptimizeMaxError to be able to use ratio lower than 1. 2022-02-20 13:44:53 -05:00
matlabbe
4d895785a6 GraphViewer: added Ensure Frame Visible menu option. MainWindow: fixed loop signature failed to load image warning when camera is not used. 2022-02-19 16:16:29 -05:00
matlabbe
c2c68c0caf Updated exported poses in TUM format to avoid confusion with header when importing in CloudCompare 2022-02-18 12:17:47 -05:00
matlabbe
9bd758a62c SuperPoint: return at minimum 2 features or 0 (fixed crash when only one feature). Python: added main python instance from Rtabmap object (to get python instancied once for ROS). MultiSessionWidget: Fixed layout warning. Memory::computeTransform() avoid re-instanciating RegistrationVis when Reg/Strategy=1 for guess transform (to fix PyMatcher re-initialized every time). CMake: added video module to opencv required components. 2022-02-15 01:28:38 -05:00
matlabbe
578c19cc38 Export CLI: for --poses_camera option with intermediate nodes in db, re-use previous camera models of last valid node with data. 2022-02-13 14:45:08 -05:00
matlabbe
4776de7931 rtabmap: updated proximity paths check order when likehood is not available (use closest node). MainWindow: don't pause when error happens in monitoring mode / ROS. DbViewer: show local transform of scan. 2022-02-12 16:46:10 -05:00
matlabbe
191e165a28 GUI: Added Multi-Session Localization view. CameraModel: set localTransform to optical rotation in default constructor (fixed matrix invertion errors with code ignoring setting local transform), save/read local transform in/from camera calibration yaml file (so that local transform is also exported when extracting rgb/depth images). Rtabmap: in localization mode, ignore landmarks farther than RGBD/LocalRadius if no global loop closures are already in odometry cache. 2022-02-12 13:35:23 -05:00
matlabbe
f584f42ea4 rtabmap/dbreader: save odometry covariance in pose prior link when in localization mode and saving localization data. 2022-02-06 20:17:46 -05:00
matlabbe
b44b212218 Bump 0.20.19. OdomF2M: scale x0.1 covariance when local bundle adjustment is done. Rtabmap: fixed GT localization error when RGBD/MaxOdomCacheSize is used. 2022-02-06 17:41:53 -05:00
matlabbe
9ad6b626e4 Updated how covariance is computed for 2d-3d estimation without query's depth image available (instead of computed from reprojection error) 2022-02-05 16:41:43 -05:00
matlabbe
32ad92e2d2 GraphView: added optional overlay to better see odometry cache constraints. rtabmap: keep global loop closure id in statistics when proximity is detected on same node. 2022-02-03 21:58:36 -05:00
matlabbe
6f8f6d4d8e android: reverted export zip cleanup (keep zip files in export subdir for easy usb transfer) 2022-02-02 17:05:49 -05:00
matlabbe
c99203bbed CMake: added explicit opencv modules to avoid VTK6-VTK7 issues on Focal (vtk6 dependency coming with opencv_viz 4.2 module and vtk7 coming from PCL) 2022-02-01 13:40:02 -05:00
matlabbe
20d873c29e android: fixed backward compatibility target folder for android <30. Open: files are sorted by last modified date. 2022-01-30 15:47:08 -05:00
matlabbe
4d8c1d8b90 bump 0.20.18 2022-01-28 17:12:24 -05:00
matlabbe
315350dbfc CCCorelib: updated wrong output check. Updated RGBD/MaxOdomCacheSize approach to work properly with Rtabmap/CreateIntermediateNodes=true. 2022-01-28 14:48:32 -05:00
matlabbe
02140f92db fixed build 2022-01-27 22:55:59 -05:00
matlabbe
402afc07ed ExportDialog: added ground normals up option, added camera projection mask and decimation options. Export CLI: added --ground_normals_up and --cam_projection_mask options, changed --bin option by --ascii option (now binary by default). DBViewer: warn when scan from depth option is enabled but there is no depth. 2022-01-27 17:57:56 -05:00
matlabbe
a8e5bbf415 export: added --texture_roi_ratios option 2022-01-26 20:12:04 -05:00
matlabbe
5b3a7d5674 Localization: fixed always rejected localization when proximity and global loop closures are both detected at the same time at two different locations (clearing proximity detections from odometry cache if global loop closures are good). 2022-01-26 15:39:09 -05:00
matlabbe
d56692640e DBViewer: fixed grid cell size in 3D View. Memory/Grid, using Icp/PointToPlaneGroundNormalsUp parameter when normals are computed. Grid: fixed 2D noHit ray tracing. 2022-01-25 18:10:43 -05:00
Ben
2dc7b59b05 allow negative min disparity in StereoBM dialog (#817) 2022-01-24 17:02:47 -05:00
Ben
bbe10bca39 fix missing curl install in focal dockerfile (#816)
* add missing curl install to focal dockerfile

* add missing apt-get update
2022-01-24 16:44:39 -05:00
matlabbe
e2dc3ac67e OctoMap: fixed empty occupancy not correctly updated when ray tracing is done on more than one local map 2022-01-23 16:29:11 -05:00
matlabbe
83d1e27b81 Refactored graph::getPosesInRadius -> graph::findNearestPoses. Labels can be removed: added Remove label option in MainWindow. In localization mode, label set with id=0 is set to nearest node of current pose. 2022-01-20 18:56:38 -05:00
matlabbe
3c215b9b4d android: fixed driver preference for arcore 2022-01-20 10:57:39 -05:00
matlabbe
bdaed2f362 Tango: fixed google tango driver not selected automatically on first use 2022-01-19 20:24:23 -05:00
matlabbe
e048d8ae72 Fixed compilation error without octomap 2022-01-19 19:53:49 -05:00
matlabbe
5b868d665f Grid/Sensor=2: fixed viewpoint offset bug of the camera. 2022-01-19 19:27:32 -05:00
matlabbe
a56373f66d GUI/ExportClouds: fixed color of scans having RGB instead of intensity. 2022-01-19 16:59:43 -05:00
matlabbe
5ec73bee8d ios: improved significantly rendering performance 2022-01-19 02:11:38 -05:00
matlabbe
b1dd44526d ios: fixed background camera not shown in landscape mode (iPhone) 2022-01-17 22:06:35 -05:00
matlabbe
de62bbb9b7 Grid: don't filter max range before doing ray tracing (to ray trace empty space). 2022-01-17 14:22:11 -05:00
matlabbe
7a5c50cb0e Fixed compilation warnings 2022-01-16 15:27:52 -05:00
matlabbe
9622fe8393 Parameters: set default Icp/PointToPlaneRadius to 0 to avoid 'Both radius and K defined' error when using 3d lidar. 2022-01-16 12:56:18 -05:00
matlabbe
5f55f63443 report: ignoring landmarks after optimization to avoid errors when exporting poses 2022-01-15 22:02:45 -05:00
matlabbe
aa0e6ef692 GUI:Export Poses: fixed poses!=stamps issue when there are landmarks (landmarks now only exported with g2o format) 2022-01-15 21:49:40 -05:00
matlabbe
03a106ea36 Fixed build without g2o 2022-01-15 13:00:12 -05:00
matlabbe
29a2b64a0c RGBD/NeighborLinkRefining: do one proximity detection by time if intermediate nodes are added. Optimized radiusFiltering(). Updated default parameters of proportionalRadiusFiltering(). 2022-01-14 18:47:57 -05:00
matlabbe
51f6b32f47 Fixed windows build (https://ci.appveyor.com/project/matlabbe/rtabmap/builds/42207812) 2022-01-14 14:33:32 -05:00
matlabbe
9e0173f4cb Export: added random sample filter, added proportional radius filter, refactored when normals are computed (now after the clouds are assembled and voxelized), moved ceiling and floor filtering inside assembling loop. 2022-01-14 13:36:01 -05:00
matlabbe
12c2dd707c Localization with Reg/Force3DoF=true, fixed how graph optimization errors are computed (use only x,y,yaw). 2022-01-12 16:59:03 -05:00
matlabbe
fcec98105d Added RGBD/ProximityMergedScanCovFactor parameter. Localization: fixed output height when Reg/Force3DoF=true but input poses are 6DoF. Transform: added is3DoF() and is4DoF() functions. GTSAM: when Reg/Force3DoF=true, copy input roll,pitch,z values for output poses. RegIcp: fixed working memory dir '~' conversion. RGBD/ProximityGlobalScanMap: fixed map::at error when some nodes don't have scans. 2022-01-12 16:14:42 -05:00
matlabbe
a4ec95963e Fixed a debug information 2022-01-11 15:59:53 -05:00
matlabbe
49353b134c LaserScan: fixed destination format when source is empty with operator+ 2022-01-11 15:32:30 -05:00
Tim Clephas
f69085304e List dependencies only once (#812) 2022-01-11 10:40:48 -05:00
Marvin Stüde
3f797e02e3 Adds Boost serialization package for libpointmatcher case (#810) 2022-01-07 13:11:12 -05:00
matlabbe
ab50ba0b6c Fixed android30 2022-01-05 21:39:27 -05:00
matlabbe
528b640a18 workflows: added android30 docker image 2022-01-04 20:54:53 -05:00
matlabbe
4d8a7b4659 CameraTango: fixed opencv4 errors 2022-01-04 20:49:03 +00:00
matlabbe
ba6575fcb9 Added android30 build 2022-01-04 14:55:32 -05:00
matlabbe
1173f06bc8 android: fixed opencv4 deprecated errors 2022-01-04 19:46:20 +00:00
matlabbe
a08fce2068 ios: added requestReview() 2022-01-03 20:57:41 -05:00
matlabbe
d8324a11d5 android: fixed sharing file exiting bug, fixed camera not correctly set back to device default on reset settings. 2022-01-03 17:51:23 -05:00
matlabbe
a6c9b3babe 💄 changed some cmake warnings in info 2022-01-03 16:33:21 -05:00
matlabbe
145430cafd Fixed noetic build (g2o error) 2022-01-03 16:05:11 -05:00
matlabbe
5194f40794 Fixed g2o build error with melodic/noetic versions 2022-01-03 15:37:06 -05:00
matlabbe
129bbf8f98 ios: added placeholder R in Library view for db not having preview (like recovered database) 2022-01-03 13:44:29 -05:00
matlabbe
a9d4a16ba4 bump ios version 0.20.17 2022-01-02 23:40:46 -05:00
matlabbe
b2f13c2772 android: fixed g2o seg fault (CACHE_SE3_OFFSET not registered) 2022-01-02 23:30:55 -05:00
matlabbe
f3ace6c86a Added recovery feature to android 2022-01-02 18:09:57 -05:00
matlabbe
3147b4ab56 ios: added recovery feature 2022-01-02 17:08:44 -05:00
matlabbe
fcde52c6bf ios: set First-P. View by default 2021-12-30 15:37:46 -05:00
matlabbe
5b31a4725d Update README.md 2021-12-29 19:05:35 -05:00
matlabbe
e4955ee386 GUI: fixed mynteye raw images support error 2021-12-29 16:12:02 -05:00
matlabbe
e5b4973ddc GUI: Added Orbbec Astra icon 2021-12-29 15:53:40 -05:00
matlabbe
f3095a2e0a Calibration dialog: fixed right panel width size. Win32: packaging missing cudnn dlls (when torch is used) 2021-12-29 15:13:13 -05:00
matlabbe
044145926f ios: incremented build number 2021-12-28 18:35:55 -05:00
matlabbe
a3823594a4 Converted an assert to an error. 2021-12-26 14:53:22 -05:00
matlabbe
3071da42f3 Optimizer: don't fix roll/pitch on root node if gravity constraints are fed 2021-12-25 16:57:03 -05:00
matlabbe
93ee8f9b30 Working dir path: convert ~ to Home for convenience. Localization: don't show "cannot optimize" warning when RGBD/MaxOdomCacheSize=0 2021-12-24 18:24:44 -05:00
matlabbe
7ca881453e RGBD/StartAtOrigin: set first node of the graph, not Identity 2021-12-20 17:01:08 -05:00
matlabbe
8662eb0dd7 Statistics: added OdomCache data for debugging 2021-12-18 18:53:59 -05:00
matlabbe
33130890fd Localization: Improved resulting pose in case there are gravity constraints. iOS: clear odom trace when not visible, fixed opt mesh not correctly aligned with graph on loading when switching RGBD/OptimizeFromGraphEnd. 2021-12-18 15:37:49 -05:00
matlabbe
bca8b30832 Localization 2d Slam: automatically rotate landmark links to have z-axis up for correct 3DoF optimization. When RGBD/MaxOdomCacheSize is used, wait for at least 2 temporal localizations before adjusting the pose (to avoid big jumps when only one constraint is used). 2021-12-17 11:00:37 -05:00
matlabbe
6eb81cbb72 Added RGBD/MaxOdomCacheSize option to iOS App. 2021-12-12 20:40:28 -05:00
matlabbe
0e62050824 rtabmap: fixed graph re-optimized with only virtual links in localization mode (which can make gtsam crash because of under constrained covariance) 2021-12-12 13:07:02 -05:00
matlabbe
cf5e90238b Statistics: added LoopOdom_correction stats for landmark detections. 2021-12-10 21:58:11 -05:00
matlabbe
8cf12c6135 Improved localization mode accuracy (decreasing jumps on consecutive loop closures or landmark detections). Updated usage of parameter RGBD/MaxOdomCacheSize (default 0->10) 2021-12-10 17:48:36 -05:00
matlabbe
4ab0090ecd Support feature-only rectification when using external extracted features. 2021-12-06 09:26:10 -05:00
matlabbe
580e35afb1 Fixed missing 3D keypoints when RGBD/LoopClosureReextractFeatures=true and Reg/Strategy=1 (https://github.com/introlab/rtabmap_ros/issues/668). DBViewer: fixed wrong poses optimization with GTSAM when showing scans of loop closures by proximity by space (multiscan) while there are GPS priors. 2021-12-05 17:38:53 -05:00
matlabbe
12906f4490 DBViewer: export poses: added explicit otion for ground truth if available 2021-12-03 13:43:53 -05:00
matlabbe
baae713471 Fixed unknown lines for octomap 2D grid projection. (https://github.com/introlab/rtabmap_ros/issues/684) 2021-11-30 20:34:51 -05:00
matlabbe
67710ef94c Export: optimized camera projection RAM usage. Added --texture_angle and --cam_projection_decimation options. 2021-11-21 17:10:57 -05:00
matlabbe
090ae0c444 DbViewer: added option to show disparity instead of right image in main views for stereo data 2021-11-20 16:36:54 -05:00
matlabbe
6684bafe34 fixed typo 2021-11-16 18:22:45 -05:00
matlabbe
5fcbe2ed70 iOS: fixed install script (#785 #741) 2021-11-16 18:11:40 -05:00
matlabbe
459c7b2bd7 Export: added --min_cluster option. 2021-11-16 11:58:55 -05:00
matlabbe
9ae2c46546 CMake: fixed build without Python and Ceres if WITH_PYTHON and WITH_CERES are OFF (even if found by third party libraries, related to #783). 2021-11-15 18:00:17 -05:00
matlabbe
7af2a27e89 Improved log error when ROI is set with SuperPoint (https://github.com/introlab/rtabmap_ros/issues/676) 2021-11-14 20:26:42 -05:00
matlabbe
dbecaac809 Moved bin dir inside build directory (#784)
* Moved bin directory inside build directory (to make easier different builds with same source directory)

* Switched include order to avoid problems with remaining Version.h still in source directory taen before the one in binary dir. Fixed android build (updated res tool search path).

* workflow-cmake: fixed path to bin directory
2021-11-14 19:29:37 -05:00
matlabbe
6c07a670ee Added OdometryOpen3D 2021-11-13 19:45:57 -05:00
matlabbe
4ba805b5b3 Report: fixed landmarks not used during optimization. Reprocess: added --nolandmark option to ignore landmarks in input database. 2021-11-12 12:47:54 -05:00
matlabbe
b002e85e0f Update ProgressDialog.h
Typo param name should be in seconds, not milliseconds.
2021-11-09 17:36:34 -05:00
matlabbe
ec2aa5c952 OpenNI2: depth shift can be negative. MainWindow: postProcessing() refactoring (split with and without dialog). 2021-11-09 10:16:12 -05:00
matlabbe
06150c697f Fixed #750 2021-11-08 14:20:21 -05:00
matlabbe
38bcb0060c CMake: set default to OFF for some optional dependencies that require specific versions or patches before integrating with rtabmap, otherwise there could be seg faults on runtime even if compilation worked. 2021-11-08 13:47:27 -05:00
matlabbe
ddd5eb5a41 CameraRealSense2: Odom extrinsics against another sensor can be calibrated with having to calibrate stereo first. DBViewer: fixed local grid wrongly using global grid parameters. 2021-11-05 18:05:50 -04:00
matlabbe
20bc281db7 DbViewer: don't show landmark links for ignored ndoes (w=-9), auto-zoom grid map if there are a lot of unknowns. Updated Docker nvidia files to include default Documents/RTAB-Map directory. 2021-11-04 13:00:08 -04:00
matlabbe
7c5acd8970 Parameters: Changed Grid/FromDepth to Grid/Sensor to add a new choice to use both scan and depth for local grids. Increased version to 0.20.15. 2021-10-29 20:05:12 -04:00
matlabbe
1886f99cbf Merge branch 'RobotnikAutomation-master' 2021-10-29 13:58:14 -04:00
matlabbe
2ad334df90 Added filter_floor and adjusted default values. 2021-10-29 13:58:00 -04:00
matlabbe
0ab5a8f43e Merge branch 'master' of https://github.com/RobotnikAutomation/rtabmap into RobotnikAutomation-master 2021-10-29 13:57:16 -04:00
matlabbe
8682026396 Rtabmap: when optimizing graph, removed guess for rootid to avoid global rotation drift over time. CameraStereoImages: set BayerMode also to right image. GraphView: fixed 0 width for line inside NodeItem. Reprocess: added -loc_null and -gt options. 2021-10-23 11:17:42 -04:00
Ines
6cb741667d Add ceiling filter to rtabmap-export 2021-10-22 12:36:53 +02:00
matlabbe
56c5622d20 docker: added "make -j12" for rtabmap build 2021-10-16 18:14:24 -04:00
matlabbe
e245782c6c worflows: added back arm64 2021-10-15 14:58:56 -04:00
matlabbe
9895e4c162 workflow: test images without arm64 2021-10-15 09:29:34 -04:00
matlabbe
f67087075a Updated docker images (removed amd64 script) 2021-10-14 21:49:50 -04:00
matlabbe
d0242b14cf DetectMoreLoopClosures CLI: show overridden parameters 2021-10-11 13:52:55 -04:00
matlabbe
d16e24a1a3 Fixed compiler warning 2021-10-07 10:19:32 -04:00
matlabbe
ab5fd5018b DbViewer: added update all landmark covariances menu action, also enabled edit constraint on landmark links. Covariance can be set to 9999. 2021-10-06 11:34:40 -04:00
matlabbe
44810a14e0 Show if built with PDAL on --version option 2021-10-01 11:49:45 -04:00
matlabbe
697fe5ebb3 Workflows: updated docker multi-arch (removed armv7) 2021-09-30 18:00:17 -04:00
matlabbe
54c0ee4244 Workflows: added multi-arch docker images 2021-09-30 15:37:05 -04:00
matlabbe
d284cd11cf Updated package.xml version to 0.20.14 2021-09-30 10:14:24 -04:00
matlabbe
467ea42981 OdometryFLOAM: fixed published local scan map local transform 2021-09-30 10:05:56 -04:00
matlabbe
77d947d4fb Fixed FLOAM not working when local transform is not Identity. DBViewer: warn user when scan from dpeth is checked and there are no depth images in db. 2021-09-30 09:53:50 -04:00
matlabbe
533d78d570 Fixed OdometryOpenVINS build errors with latest OpenVINS code. 2021-09-28 17:12:08 -04:00
matlabbe
aee034c5ed Update CMakeLists.txt
Setting WITH_FLOAM to OFF by default because floam binaries (this [version](https://github.com/flynneva/floam)) in ros is not compatible.
2021-09-27 20:20:11 -04:00
matlabbe
0092e15cd7 Update docker.yml 2021-09-27 20:04:12 -04:00
matlabbe
23d9e0e4bb Docker: updated bionic/focal's geogram patch 2021-09-27 19:48:18 -04:00
matlabbe
8c56b5b1ce CMake: added WITH_OPENMP option (to be able to disable it). CameraOpenNI2: Added depth decimation parameter. CLAMS: can apply distortion model to smaller images. 2021-09-24 17:31:16 -04:00
matlabbe
bccc5b13af FLOAM: added some debug logs 2021-09-24 11:32:25 -04:00
matlabbe
5f65618d40 Added OdomLOAM/Resolution parameter 2021-09-22 10:48:59 -04:00
matlabbe
cff0d15460 Fixed "wrong scan number" error when OdomLOAM/Sensor is 0 (VLP16) 2021-09-22 10:06:34 -04:00
matlabbe
b6671f4d8c workflow/docker: added CACHE_DATE to android builds to avoid caching rtabmap build 2021-09-20 16:02:37 -04:00
matlabbe
9db66600b3 workflow: added android23 docker image 2021-09-20 15:46:14 -04:00
matlabbe
67cd4b69c1 workflow: updated docker tags / cache var 2021-09-20 13:34:30 -04:00
matlabbe
cffb7981b6 docker: fixed bionic build with latest alicevision (cmake>=3.11 required) 2021-09-20 12:32:51 -04:00
matlabbe
71ffd922ed workflow: fixed typo 2021-09-20 11:37:58 -04:00
matlabbe
870467393b workflow: add docker buildcache 2021-09-20 11:33:19 -04:00
matlabbe
79f203a2c4 docker workflow: fixed build matrix 2021-09-20 11:16:12 -04:00
matlabbe
baa5b638ae Added "docker" workflow 2021-09-20 11:11:21 -04:00
matlabbe
8f12463f71 Docker: upgraded alicevision version 2.4.0 in bionic/focal images 2021-09-19 20:42:56 -04:00
matlabbe
14b56813d3 Updated for AliceVision >=2.4.0 compatibility. Export: added --multiband_contrib option. 2021-09-19 20:20:45 -04:00
matlabbe
44b057b0d7 DbViewer: fixed icp from depth option not used when refining or adding loop closures automaticaly 2021-09-13 15:59:19 -04:00
matlabbe
a901f20d06 0.20.14: added globalBundleAdjustment CLI, added Rtabmap/Memory::cleanupLocalGrids function, init with optimizedPoses from db even in mapping mode, reprocess: added -db option to save optimized 2d grid in database. 2021-09-11 11:35:43 -04:00
matlabbe
3ba02d2ef6 Added OdometryFLOAM (Odom/Strategy=11) 2021-09-09 17:38:54 -04:00
matlabbe
263e0170f1 export: refactored ba (to support stereo data) 2021-09-09 14:22:02 -04:00
matlabbe
e017a0fcf4 DbViewer: fixed initial rootid with older databases, fixed RGBD/OptimizeFromGraphEnd not correctly used. 2021-09-08 18:13:20 -04:00
matlabbe
103db3181b Update README.md 2021-09-08 17:13:13 -04:00
matlabbe
bc253df24a Update README.md 2021-09-08 17:11:34 -04:00
matlabbe
544ea9dff2 Update cmake.yml 2021-09-08 13:31:00 -04:00
matlabbe
09c2c4bbcb Removed travis config, now use Github actions (see .github/workflows/cmake.yml) fixed #768 2021-09-08 12:09:59 -04:00
matlabbe
c209cf1c9b Update cmake.yml
Added info after build
2021-09-08 12:06:14 -04:00
matlabbe
202d59b408 Update cmake.yml
Added ros setup.bash before cmake
2021-09-08 11:59:04 -04:00
matlabbe
9671daf9c3 Update cmake.yml 2021-09-08 11:53:13 -04:00
matlabbe
b5518ff618 Update cmake.yml 2021-09-08 11:46:29 -04:00
matlabbe
2111b6497b Update cmake.yml
use setup-ros action
2021-09-08 11:37:03 -04:00
matlabbe
b51b2525a5 Added Github actions for melodic/focal 2021-09-08 11:24:11 -04:00
matlabbe
45d51808e3 💄 2021-09-08 09:38:16 -04:00
matlabbe
bc39b19517 projectCloudToCamerasImpl: fixed bug using wrong camera models 2021-09-08 09:34:21 -04:00
matlabbe
7baedf4c72 texturing: remove assert when poses and models are not the same size (just ignore poses without models, intermediate nodes issue) 2021-09-07 16:26:56 -04:00
matlabbe
20361400e1 export: output intensity channel with RGB when --cam_projection and --scan options are set (PDAL required) 2021-09-07 15:57:23 -04:00
matlabbe
c43118cde8 Fixed F2F-Optical flow not creating keyframes bug 2021-09-03 15:33:22 -04:00
matlabbe
371a3ef851 fixed CleanupLocalGrids install target 2021-09-01 10:23:45 -04:00
matlabbe
daefc5ff54 Added rtabmap-cleanupLocalGrids CLI 2021-08-28 22:19:59 -04:00
matlabbe
b932da6dcf DbViewer: Adjusted GraphView's root id based on latest valid node on initialization 2021-08-28 20:23:44 -04:00
matlabbe
f88ce1618b OdometryORBSLAM3: fixed re-initilisation of camera parameters when restarting camera with different config. 2021-08-26 15:34:48 -04:00
matlabbe
c5e4d67f80 export: don't assert if gain is zero (means disabled) 2021-08-16 20:27:31 -04:00
matlabbe
ed68fe777b Added more options for multiband texturing 2021-08-16 13:14:02 -04:00
matlabbe
6fb553a5e7 Update README.md 2021-08-13 14:46:56 -04:00
matlabbe
db00e04cc1 rtabmap-info: updated to show parameters not in the database. 2021-08-12 10:55:08 -04:00
matlabbe
eeecb21793 export tool: added --camera_projection_keep_all option 2021-08-03 13:46:39 -04:00
matlabbe
a5685c3e31 Fixed build without DepthAI dep 2021-07-28 17:05:16 -04:00
matlabbe
138d4aa1be If RGBD/LoopClosureReextractFeatures=true, don't save raw features (3d point, descriptor) to Feature table. 2021-07-28 14:32:32 -04:00
matlabbe
79d2b3fade Merge branch 'master' of https://github.com/introlab/rtabmap 2021-07-28 14:19:49 -04:00
matlabbe
32bf0f9d61 Fixed CameraDepthAI with latest depthai version (using now camera eeprom calibration and added imu support) 2021-07-28 14:19:30 -04:00
matlabbe
22a771e29c trigger travis.com 2021-07-20 14:09:40 -04:00
matlabbe
17d8a92614 Update README.md 2021-07-20 12:58:42 -04:00
matlabbe
a91cd0c659 Update README.md 2021-07-20 12:58:16 -04:00
matlabbe
ae92ec40d7 Fixed build with LOAM dependency 2021-07-14 13:22:47 -04:00
matlabbe
7338cb8a85 Localization: fixed initial graph optimization root id (based on RGBD/OptimizeFromGraphEnd) when optimized graph is not saved in db. 2021-07-09 14:57:15 -04:00
matlabbe
456560b9e4 DBViewer/Extract Images: export calibration for each image, also now export multi-camera calibrations. 2021-07-07 12:21:57 -04:00
matlabbe
f9257beeb8 export: updated default poses format (11) 2021-07-05 12:58:24 -04:00
matlabbe
485bf806bd export tool: use pcl's PLY writer instead of pdal if camera ids are not exported (ply compatibility issue when reading back using pcl) 2021-07-05 10:04:51 -04:00
matlabbe
68ae3b76af export: updated to export calibration for every files (to support auto-focus cameras). Added output_dir option. 2021-07-05 09:46:12 -04:00
matlabbe
05d45872f3 DBReader: publish landmarks by default (also added option to ignore them) 2021-06-29 16:03:21 -04:00
matlabbe
3da4bb9faa For Icp/DebugExportFormat and RGBD/ProximityGlobalScanMap, use Rtabmap/WorkingDirectory as output directory for debugging files. 2021-06-27 20:37:42 -04:00
matlabbe
a921d615c5 0.20.13: templated laserScanFromPointCloud() version with PCLPointCloud2 to be also used with sensor_msgs/PointCloud2 class (for rtabmap_ros). 2021-06-27 20:07:00 -04:00
matlabbe
2b9ae3a2ad Added Icp/DebugExportFormat parameter 2021-06-26 16:06:25 -04:00
matlabbe
1a64e05e2f fixed code merged 2021-06-26 13:47:49 -04:00
matlabbe
350f995ee9 merged master to scan_map branch 2021-06-25 16:38:03 -04:00
matlabbe
eabf3e3d57 Decimation parameters for feature detection cannot be negative anymore (always done based to RGB image and depth image is decimated only if it is bigger than decimated rgb image). MainWindow: fixed light blue screen-only on full rehearsal merge. 2021-06-25 12:54:52 -04:00
matlabbe
be24203840 iOS: added toast info on rejected loop closures 2021-06-24 22:39:25 -04:00
matlabbe
48ebf969bd OdometryInfo: fixed IcpRMS not copied in copyWithoutData() 2021-06-24 22:38:19 -04:00
matlabbe
656618ccb7 Merge branch 'master' of https://github.com/introlab/rtabmap into scan_map 2021-06-24 19:53:23 -04:00
matlabbe
f5ab422c42 Odom: when odom is auto reset, reprocess the latest image and return its pose 2021-06-24 13:41:38 -04:00
matlabbe
5a676e9032 Fixed negative Odom/ImageDecimation not handled 2021-06-24 12:44:18 -04:00
matlabbe
11e9837b82 Added RGBD/ProximityGlobalScanMap for proximity detection using the whole scan map in localization mode. Added Icp RMS statistics (CCCorelib). Updated how localization is corrected with gravity when available (simply use roll and pitch of current gravity constraint). 2021-06-23 17:13:07 -04:00
matlabbe
dddf6378ae MainWindow: fixed currentVisiblePosesMap 2021-06-22 08:16:39 -04:00
matlabbe
5167927d01 report: added --ignore_inter_nodes option. CloudViewer: set max absolute scan intensity to 100 (was 0=auto). reprocess/replay db: ignore intermediate nodes if Rtabmap/CreateIntermediateNodes is false. 2021-06-21 17:23:53 -04:00
matlabbe
f475f2d21c 0.20.12: iOS/android sync 2021-06-21 10:07:30 -04:00
matlabbe
9fccb8703a Merge branch 'master' of https://github.com/introlab/rtabmap into ios 2021-06-21 09:41:11 -04:00
matlabbe
62b5f13dd8 MainWindow: added currentVisiblePosesMap() 2021-06-20 23:05:24 -04:00
matlabbe
b8c22e1c99 Fixed pcl::voxelGrid filtering crash on Windows (latest PCL, eigen allocation issue) 2021-06-18 16:02:17 -04:00
matlabbe
d75cc04ad2 CloudViewer: fixed opengl not refreshed on update (VTK9). Fixed File Explorer hanging (Qt 5.12). Fixed backup database not deleted after a recovery. 2021-06-18 12:43:08 -04:00
Charles Maillette
8d2dbe32c4 Added libpdal to rtabmap docker build for focal (#735) 2021-06-17 15:36:28 -04:00
matlabbe
a9d4fc9291 Refactored Tango and ARCore texture management. Tango: added support with First-person AR mode. ARCoreJava: Added localization filtering speed option (avoid ARCore jumps), also manage when ARCore is lost (new session is created, relocalization needed to continue mapping). 2021-06-15 20:45:45 -04:00
matlabbe
696216b35b Fixed occlusion image origin offset (iOS and android). Android: disabled maximum odom image rate for faster feedback in First-Person. Min/Max range parameters also filter scans. Fixed background renderer not showing image (ARCore Java driver). 2021-06-13 22:07:47 -04:00
matlabbe
6342658ec5 iOS: fixed origin when we do New Scan while we were already mapping, improved FPV feedback in point cloud mode, showing camera overlay in visualization mode (pinch out to disable). Localization mode: Updated how marker detection transform are modified by gravity constraints. 2021-06-12 12:42:56 -04:00
matlabbe
3f633081cb iOS: improved feedback in first-person mapping mode (red background), fixed not matching camera overlay with 3D model, updated how memory usage is computed. 2021-06-11 21:41:59 -04:00
matlabbe
a6f3a81999 fixed ios build 2021-06-11 10:20:07 -04:00
matlabbe
3e3d4142fc RGBD/OptimizeMaxError default to 1 for mobile apps. iOS: increased Kp/MaxFeatures to 400 (was 200). 2021-06-11 09:29:37 -04:00
matlabbe
0a37d01d1d ios/android: Updated default MaxOptimizeError to 1.5x 2021-06-10 11:27:53 -04:00
matlabbe
ba38d9f321 Added depth/rgb registration option 2021-06-10 11:07:25 -04:00
matlabbe
d7b5fa5d17 fixed android build 2021-06-09 17:45:01 -04:00
matlabbe
766301b175 fixed desktop build 2021-06-09 11:25:01 -04:00
matlabbe
289d4afd76 ios first release 2021-06-08 00:06:49 -04:00
matlabbe
630cb6a59f Odometry: when "Rtabmap/ImagesAlreadyRectified" is false and odometry strategy doesn't support raw images, added rectification for RGB-D data (only rgb rectified though) for convenience. 2021-06-01 14:33:17 -04:00
matlabbe
12c46286f6 CameraRealSense2: added support for device id like D435, t265, L515, d435i, d415 for convenience (if we have multiple D435, we still need to use on of the serials shown in log info when starting the driver) 2021-06-01 11:40:46 -04:00
matlabbe
c9dbe6205d Docker: added nvidia drvier embedding examples for convenience 2021-05-30 14:21:17 -04:00
chameau5050
f94f9cbb9b improve flood fill and move it to update function (#727)
* add flood fill filter

* change to use unordoned_multiset

* remove recursivity in flood fill and move the flood fill into the update

* Refactoring of OctoMap constructors (keeping only one). Simplified floodfill parameters to only one and added it to UI.

* Fixed ray tracing not done in local 3D maps (OctoMap)

Co-authored-by: MarcLeclercGit <marcantoine.leclerc96@gmail.com>
Co-authored-by: matlabbe <matlabbe@gmail.com>
2021-05-30 10:12:07 -04:00
matlabbe
b7c2f6801b unknownSpaceFilled: refactored approach to fix the case of 360 scan with first ray y>=0 (turtlebot3 sim). 2021-05-27 18:19:34 -04:00
matlabbe
8b1b874bf3 Statistics: added LoopOptimization_max_ang_error stats 2021-05-27 13:00:29 -04:00
matlabbe
127a41a53e MainWindow::createCamera() fixed parameters not passed by reference 2021-05-26 21:13:14 -04:00
matlabbe
c1492533c3 OctoMap: fixed empty cells not all added to global occupancy grid 2021-05-26 16:27:49 -04:00
matlabbe
ada3e75005 Camera class: localTransform parameter should not have optical rotation anymore (it is added afterwards in the constructor). OdomSensor: the extrinsics should not contain optical rotation anymore. These 2 changes make it more convenient to set transfomation parameters in the UI. MainWindow::createCamera() now has odomSensor argument for convenience (for inherited classes to set both camera and odom sensor in the same function). 2021-05-26 13:40:46 -04:00
matlabbe
21dbeed4b7 Odom sensor option (#726)
* Added Odom Sensor option

* Odom Sensor: Added pose time offset parameter

* Gui: fixed odom cloud not shown when rgb/depth doesn't have same size. Odom sensor: fixed rawImages set on non-stereo camera (because stereoRectify wrongly set to all cameras)

* Calibration: fixed rgb and depth suffixes not correctly set. OpenNI2: horizontal and vertical shifts can be also set for default calib.

* Fixed a warning

* OdomSensor: added option to use odom sensor output as ground truth (for comparison between odom sensor and rtabmap odom). Added scale factor option.

* FindG2O.cmake: updated path suffixes to find EXTERNAL csparse

* Pose3GravityFactor: fixed dllimport error on windows

* UI: Statistics panel not updated if not visible and keep stats in cache is unchecked. Added description to some timing debug logs in processStatistics().

* Removed vtkOutputWindow on Windows

* Odom Sensor: added zed sdk support

* bump version 0.20.11
2021-05-23 17:21:12 -04:00
479 changed files with 32548 additions and 10280 deletions

1
.dockerignore Normal file
View File

@@ -0,0 +1 @@
build/*

64
.github/workflows/cmake-ros.yml vendored Normal file
View File

@@ -0,0 +1,64 @@
name: CMake-ROS
on:
push:
branches:
- '**'
pull_request:
branches:
- '**'
env:
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
BUILD_TYPE: Release
jobs:
build:
# The CMake configure and build commands are platform agnostic and should work equally
# well on Windows or Mac. You can convert this to a matrix build if you need
# cross-platform coverage.
# See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix
name: Build on ros ${{ matrix.ros_distribution }} and ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
matrix:
ros_distribution: [melodic, noetic, foxy, humble, rolling]
include:
- ros_distribution: 'melodic'
os: ubuntu-18.04
- ros_distribution: 'noetic'
os: ubuntu-20.04
- ros_distribution: 'foxy'
os: ubuntu-20.04
- ros_distribution: 'humble'
os: ubuntu-22.04
- ros_distribution: 'rolling'
os: ubuntu-22.04
steps:
- uses: ros-tooling/setup-ros@v0.4
with:
required-ros-distributions: ${{ matrix.ros_distribution }}
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get -y install ros-${{ matrix.ros_distribution }}-rtabmap
sudo apt-get -y remove ros-${{ matrix.ros_distribution }}-rtabmap
- uses: actions/checkout@v2
- name: Configure CMake
run: |
source /opt/ros/${{ matrix.ros_distribution }}/setup.bash
cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
- name: Build
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}
- name: Info
working-directory: ${{github.workspace}}/build/bin
run: |
source /opt/ros/${{ matrix.ros_distribution }}/setup.bash
./rtabmap-console --version

48
.github/workflows/cmake.yml vendored Normal file
View File

@@ -0,0 +1,48 @@
name: CMake
on:
push:
branches:
- '**'
pull_request:
branches:
- '**'
env:
BUILD_TYPE: Release
jobs:
build:
name: ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-22.04, ubuntu-20.04, ubuntu-18.04]
steps:
- name: Install dependencies
run: |
DEBIAN_FRONTEND=noninteractive
sudo apt-get update
sudo apt-get -y install libopencv-dev libpcl-dev git cmake software-properties-common libyaml-cpp-dev
- uses: actions/checkout@v2
- name: Configure CMake
run: |
cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
- name: Build
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}
- name: Info
working-directory: ${{github.workspace}}/build/bin
run: |
./rtabmap-console --version
# - name: Test
# working-directory: ${{github.workspace}}/build
# # Execute tests defined by the CMake configuration.
# # See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail
# run: ctest -C ${{env.BUILD_TYPE}}

111
.github/workflows/docker.yml vendored Normal file
View File

@@ -0,0 +1,111 @@
name: docker
on:
push:
branches:
- 'master'
jobs:
docker:
runs-on: ubuntu-latest
strategy:
matrix:
docker_tag: [xenial, bionic, focal, android23, android24, android26, android30]
include:
- docker_tag: xenial
docker_tags: |
introlab3it/rtabmap:xenial
introlab3it/rtabmap:16.04
docker_args: |
NOT_USED=0
docker_platforms: |
linux/amd64
docker_path: 'xenial'
- docker_tag: bionic
docker_tags: |
introlab3it/rtabmap:bionic
introlab3it/rtabmap:18.04
docker_args: |
NOT_USED=0
docker_platforms: |
linux/amd64
linux/arm64
docker_path: 'bionic'
- docker_tag: focal
docker_tags: |
introlab3it/rtabmap:focal
introlab3it/rtabmap:20.04
introlab3it/rtabmap:latest
docker_args: |
NOT_USED=0
docker_platforms: |
linux/amd64
linux/arm64
docker_path: 'focal'
- docker_tag: android23
docker_tags: |
introlab3it/rtabmap:android23
introlab3it/rtabmap:tango
docker_args: |
API_VERSION=23
docker_platforms: |
linux/amd64
docker_path: 'bionic/android/rtabmap_apiXX'
- docker_tag: android24
docker_tags: |
introlab3it/rtabmap:android24
docker_args: |
API_VERSION=24
docker_platforms: |
linux/amd64
docker_path: 'bionic/android/rtabmap_apiXX'
- docker_tag: android26
docker_tags: |
introlab3it/rtabmap:android26
docker_args: |
API_VERSION=26
docker_platforms: |
linux/amd64
docker_path: 'bionic/android/rtabmap_apiXX'
- docker_tag: android30
docker_tags: |
introlab3it/rtabmap:android30
docker_args: |
API_VERSION=30
docker_platforms: |
linux/amd64
docker_path: 'bionic/android/rtabmap_apiXX'
steps:
-
name: Checkout
uses: actions/checkout@v2
-
name: Set up QEMU
uses: docker/setup-qemu-action@v1
with:
platforms: all
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
-
name: Login to DockerHub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
-
name: Build and push
uses: docker/build-push-action@v2
with:
context: .
push: true
platforms: ${{ matrix.docker_platforms }}
file: ./docker/${{ matrix.docker_path }}/Dockerfile
build-args: |
${{ matrix.docker_args }}
tags: ${{ matrix.docker_tags }}
cache-from: type=registry,ref=introlab3it/rtabmap:${{ matrix.docker_tag }}
cache-to: type=inline

View File

@@ -1,80 +0,0 @@
language: cpp
jobs:
include:
# - name: osx
# compiler: clang
# os: osx
# install:
# - brew install sqlite
# - brew install pcl
# - brew install opencv@3
# - name: linux-trusty
# compiler: gcc
# os: linux
# 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
#
# before_script:
# - source /opt/ros/indigo/setup.bash
- name: linux-xenial
compiler: gcc
os: linux
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
before_script:
- source /opt/ros/kinetic/setup.bash
- name: linux-bionic
compiler: gcc
os: linux
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
before_script:
- source /opt/ros/melodic/setup.bash
- name: linux-focal
compiler: gcc
os: linux
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
before_script:
- source /opt/ros/noetic/setup.bash
script:
- mkdir -p build && cd build
- cmake ..
- make
notifications:
email:
- matlabbe@gmail.com

View File

@@ -1,6 +1,5 @@
# Top-Level CmakeLists.txt
# For GNUInstallDirs
cmake_minimum_required(VERSION 2.8.5)
cmake_minimum_required(VERSION 3.5)
PROJECT( RTABMap )
SET(PROJECT_PREFIX rtabmap)
@@ -21,7 +20,7 @@ SET(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake_modules")
#######################
SET(RTABMAP_MAJOR_VERSION 0)
SET(RTABMAP_MINOR_VERSION 20)
SET(RTABMAP_PATCH_VERSION 10)
SET(RTABMAP_PATCH_VERSION 23)
SET(RTABMAP_VERSION
${RTABMAP_MAJOR_VERSION}.${RTABMAP_MINOR_VERSION}.${RTABMAP_PATCH_VERSION})
@@ -41,7 +40,13 @@ IF(${CMAKE_GENERATOR} MATCHES ".*Makefiles")
ENDIF("${CMAKE_BUILD_TYPE}" STREQUAL "")
ENDIF(${CMAKE_GENERATOR} MATCHES ".*Makefiles")
IF(NOT ANDROID)
SET(MOBILE_BUILD OFF)
IF(ANDROID OR CMAKE_SYSTEM_NAME STREQUAL "iOS")
SET(MOBILE_BUILD ON)
ENDIF(ANDROID OR CMAKE_SYSTEM_NAME STREQUAL "iOS")
MESSAGE(STATUS "MOBILE_BUILD=${MOBILE_BUILD}")
IF(NOT MOBILE_BUILD)
SET(CMAKE_DEBUG_POSTFIX "d")
option(FLANN_KDTREE_MEM_OPT "Disable multi-threaded FLANN kd-tree to minimize memory allocations" OFF)
ELSE()
@@ -101,6 +106,7 @@ if(MSVC)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP${N}")
endif()
endif()
add_compile_options("/bigobj")
endif()
# [Eclipse] Automatic Discovery of Include directories (Optional, but handy)
@@ -118,9 +124,9 @@ OPTION( BUILD_SHARED_LIBS "Set to OFF to build static libraries" ON )
####### OUTPUT DIR #######
SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/bin)
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/bin)
SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/lib)
SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin)
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin)
SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib)
# Avoid Visual Studio bin/Release and bin/Debug sub directories
SET( CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}")
@@ -157,7 +163,7 @@ OPTION(BUILD_TOOLS "Build tools" ON)
OPTION(BUILD_EXAMPLES "Build examples" ON)
####### DEPENDENCIES #######
IF(ANDROID)
IF(MOBILE_BUILD)
option(WITH_QT "Include Qt support" OFF)
ELSE()
option(WITH_QT "Include Qt support" ON)
@@ -176,12 +182,14 @@ 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_CERES "Include Ceres support" OFF)
option(WITH_VERTIGO "Include Vertigo support" ON)
option(WITH_CVSBA "Include cvsba support" ON)
option(WITH_CVSBA "Include cvsba support" OFF)
option(WITH_POINTMATCHER "Include libpointmatcher support" ON)
option(WITH_CCCORELIB "Include CCCoreLib support" ON)
option(WITH_LOAM "Include LOAM support" ON)
option(WITH_CCCORELIB "Include CCCoreLib support" OFF)
option(WITH_OPEN3D "Include Open3D support" OFF)
option(WITH_LOAM "Include LOAM support" OFF)
option(WITH_FLOAM "Include FLOAM support" OFF)
option(WITH_FLYCAPTURE2 "Include FlyCapture2/Triclops support" ON)
option(WITH_ZED "Include ZED sdk support" ON)
option(WITH_ZEDOC "Include ZED Open Capture support" ON)
@@ -189,22 +197,24 @@ 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_DEPTHAI "Include depthai-core support" ON)
option(WITH_DEPTHAI "Include depthai-core support" OFF)
option(WITH_OCTOMAP "Include Octomap support" ON)
option(WITH_CPUTSDF "Include CPUTSDF support" ON)
option(WITH_OPENCHISEL "Include open_chisel support" ON)
option(WITH_CPUTSDF "Include CPUTSDF support" OFF)
option(WITH_OPENCHISEL "Include open_chisel support" OFF)
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)
option(WITH_ORB_SLAM "Include ORB_SLAM2 or ORB_SLAM3 support" ON)
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_OPENVINS "Include OpenVINS support" ON)
option(WITH_FOVIS "Include FOVIS support" OFF)
option(WITH_VISO2 "Include VISO2 support" OFF)
option(WITH_DVO "Include DVO support" OFF)
option(WITH_ORB_SLAM "Include ORB_SLAM2 or ORB_SLAM3 support" OFF)
option(WITH_OKVIS "Include OKVIS support" OFF)
option(WITH_MSCKF_VIO "Include MSCKF_VIO support" OFF)
option(WITH_VINS "Include VINS-Fusion support" OFF)
option(WITH_OPENVINS "Include OpenVINS support" OFF)
option(WITH_MADGWICK "Include Madgwick IMU filtering support" ON)
option(WITH_FASTCV "Include FastCV support" ON)
IF(ANDROID)
option(WITH_OPENMP "Include OpenMP support" ON)
option(WITH_OPENGV "Include OpenGV support" OFF)
IF(MOBILE_BUILD)
option(PCL_OMP "With PCL OMP implementations" OFF)
ELSE()
option(PCL_OMP "With PCL OMP implementations" ON)
@@ -213,7 +223,7 @@ 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)
FIND_PACKAGE(OpenCV REQUIRED QUIET COMPONENTS core calib3d imgproc highgui stitching photo video OPTIONAL_COMPONENTS aruco xfeatures2d nonfree gpu cudafeatures2d)
IF(WITH_QT)
FIND_PACKAGE(PCL 1.7 REQUIRED QUIET COMPONENTS common io kdtree search surface filters registration sample_consensus segmentation visualization)
@@ -248,18 +258,19 @@ endif()
# OpenMP ("-fopenmp" should be added for flann included in PCL)
# the gcc-4.2.1 coming with MacOS X is not compatible with the OpenMP pragmas we use, so disabling OpenMP for it
if((NOT APPLE) OR (NOT CMAKE_COMPILER_IS_GNUCXX) OR (GCC_VERSION VERSION_GREATER 4.2.1) OR (CMAKE_CXX_COMPILER_ID STREQUAL "Clang"))
find_package(OpenMP)
if(((NOT APPLE) OR (NOT CMAKE_COMPILER_IS_GNUCXX) OR (GCC_VERSION VERSION_GREATER 4.2.1) OR (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")) AND WITH_OPENMP)
find_package(OpenMP COMPONENTS C CXX)
endif()
if(OPENMP_FOUND)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
set(CMAKE_INSTALL_OPENMP_LIBRARIES TRUE)
message (STATUS "Found OpenMP")
message (STATUS "Found OpenMP: ${OpenMP_CXX_LIBRARIES}")
if(PCL_OMP)
message (STATUS "Add PCL_OMP to definitions")
add_definitions(-DPCL_OMP)
endif(PCL_OMP)
else(OPENMP_FOUND)
elseif(WITH_OPENMP)
message (STATUS "Not found OpenMP")
endif()
@@ -305,7 +316,11 @@ IF(WITH_QT)
IF(value EQUAL -1)
list(FIND PCL_LIBRARIES vtkGUISupportQt value)
IF(value EQUAL -1)
SET(PCL_LIBRARIES "${PCL_LIBRARIES};vtkGUISupportQt")
IF("${VTK_MAJOR_VERSION}" GREATER 8)
SET(PCL_LIBRARIES "${PCL_LIBRARIES};VTK::GUISupportQt")
ELSE()
SET(PCL_LIBRARIES "${PCL_LIBRARIES};vtkGUISupportQt")
ENDIF()
SET(ADD_VTK_GUI_SUPPORT_QT_TO_CONF TRUE)
ENDIF(value EQUAL -1)
ENDIF(value EQUAL -1)
@@ -340,6 +355,13 @@ IF(WITH_QT)
ENDIF(QT4_FOUND OR Qt5_FOUND)
ENDIF(WITH_QT)
IF(NOT VTK_FOUND)
# Newest PCL versions won't set -DDISABLE_VTK
IF(NOT "${PCL_DEFINITIONS}" MATCHES "-DDISABLE_VTK")
SET(PCL_DEFINITIONS "${PCL_DEFINITIONS};-DDISABLE_VTK")
ENDIF()
ENDIF(NOT VTK_FOUND)
IF(WITH_TORCH)
FIND_PACKAGE(Torch QUIET)
IF(TORCH_FOUND)
@@ -348,7 +370,7 @@ IF(WITH_TORCH)
ENDIF(WITH_TORCH)
IF(WITH_PYTHON)
FIND_PACKAGE(Python3 COMPONENTS Interpreter Development)
FIND_PACKAGE(Python3 COMPONENTS Interpreter Development NumPy)
IF(Python3_FOUND)
MESSAGE(STATUS "Found Python3")
ENDIF(Python3_FOUND)
@@ -424,16 +446,29 @@ IF(WITH_DC1394)
ENDIF(WITH_DC1394)
IF(WITH_G2O)
FIND_PACKAGE(g2o QUIET NO_MODULE)
FIND_PACKAGE(g2o QUIET NO_MODULE)
IF(g2o_FOUND)
MESSAGE(STATUS "Found g2o (targets)")
SET(G2O_FOUND ${g2o_FOUND})
SET(G2O_CPP11 1)
SET(G2O_FOUND ${g2o_FOUND})
get_target_property(G2O_INCLUDES g2o::core INTERFACE_INCLUDE_DIRECTORIES)
MESSAGE(STATUS "g2o include dir: ${G2O_INCLUDES}")
FIND_FILE(G2O_FACTORY_FILE g2o/core/factory.h
PATHS ${G2O_INCLUDES}
NO_DEFAULT_PATH)
FILE(READ ${G2O_FACTORY_FILE} TMPTXT)
STRING(FIND "${TMPTXT}" "shared_ptr" matchres)
IF(${matchres} EQUAL -1)
MESSAGE(STATUS "Old g2o factory version detected without shared ptr (factory file: ${G2O_FACTORY_FILE}).")
SET(G2O_CPP11 2)
ELSE()
MESSAGE(STATUS "Latest g2o factory version detected with shared ptr (factory file: ${G2O_FACTORY_FILE}).")
SET(G2O_CPP11 1)
ENDIF()
ELSE()
FIND_PACKAGE(G2O QUIET)
IF(G2O_FOUND)
MESSAGE(STATUS "Found g2o: ${G2O_INCLUDE_DIRS}")
ENDIF(G2O_FOUND)
FIND_PACKAGE(G2O QUIET)
IF(G2O_FOUND)
MESSAGE(STATUS "Found g2o: ${G2O_INCLUDE_DIRS}")
ENDIF(G2O_FOUND)
ENDIF()
ENDIF(WITH_G2O)
@@ -466,7 +501,7 @@ ENDIF(WITH_POINTMATCHER)
IF(libpointmatcher_FOUND OR GTSAM_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)
find_package(Boost COMPONENTS thread filesystem system program_options date_time chrono timer serialization REQUIRED)
ENDIF(Boost_MINOR_VERSION GREATER 47)
IF(WIN32)
MESSAGE(STATUS "Boost_LIBRARY_DIRS=${Boost_LIBRARY_DIRS}")
@@ -481,6 +516,19 @@ IF(WITH_CCCORELIB)
ENDIF(CCCoreLib_FOUND)
ENDIF(WITH_CCCORELIB)
IF(WITH_OPEN3D)
IF(${CMAKE_VERSION} VERSION_LESS "3.19.0")
MESSAGE(WARNING "Open3D requires CMake version >=3.19 (current is ${CMAKE_VERSION})")
ELSE()
# Build Open3D like this to avoid linker errors in rtabmap:
# cmake -DBUILD_SHARED_LIBS=ON -DGLIBCXX_USE_CXX11_ABI=ON -DCMAKE_BUILD_TYPE=Release ..
find_package(Open3D QUIET)
IF(Open3D_FOUND)
MESSAGE(STATUS "Found Open3D: ${Open3DINCLUDE_DIRS}")
ENDIF(Open3D_FOUND)
ENDIF()
ENDIF(WITH_OPEN3D)
IF(WITH_LOAM)
find_package(loam_velodyne QUIET)
IF(loam_velodyne_FOUND)
@@ -488,6 +536,14 @@ IF(WITH_LOAM)
ENDIF(loam_velodyne_FOUND)
ENDIF(WITH_LOAM)
IF(WITH_FLOAM)
find_package(floam QUIET)
IF(floam_FOUND)
MESSAGE(STATUS "Found floam: ${floam_INCLUDE_DIRS}")
FIND_PACKAGE(Ceres QUIET REQUIRED)
ENDIF(floam_FOUND)
ENDIF(WITH_FLOAM)
SET(ZED_FOUND FALSE)
IF(WITH_ZED)
find_package(ZED 2 QUIET)
@@ -589,6 +645,7 @@ IF(WITH_ALICE_VISION)
ENDIF(${AliceVision_VERSION} VERSION_LESS_EQUAL "2.2")
SET(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH};/usr/local/lib/cmake/modules")
find_package(Geogram REQUIRED QUIET)
find_package(assimp 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}")
@@ -630,9 +687,14 @@ IF(WITH_OKVIS)
ENDIF(WITH_OKVIS)
# If built with okvis, we found already ceres above
IF(NOT okvis_FOUND AND WITH_CERES)
IF(WITH_CERES)
IF(NOT okvis_FOUND AND NOT floam_FOUND)
FIND_PACKAGE(Ceres QUIET)
ENDIF(NOT okvis_FOUND AND WITH_CERES)
MESSAGE(STATUS "Found ceres ${Ceres_VERSION}: ${CERES_INCLUDE_DIRS}")
ENDIF(NOT okvis_FOUND AND NOT floam_FOUND)
ELSEIF(Ceres_FOUND)
MESSAGE(WARNING "WITH_CERES is OFF, but it still included by dependencies Okvis or FLOAM")
ENDIF()
IF(WITH_MSCKF_VIO)
FIND_PACKAGE(msckf_vio QUIET)
@@ -665,6 +727,13 @@ IF(WITH_FASTCV)
ENDIF(FastCV_FOUND)
ENDIF(WITH_FASTCV)
IF(WITH_OPENGV)
FIND_PACKAGE(opengv QUIET)
IF(opengv_FOUND)
MESSAGE(STATUS "Found OpenGV: ${opengv_INCLUDE_DIRS}")
ENDIF(opengv_FOUND)
ENDIF(WITH_OPENGV)
IF(WITH_ORB_SLAM AND NOT G2O_FOUND)
FIND_PACKAGE(ORB_SLAM QUIET)
IF(ORB_SLAM_FOUND)
@@ -673,8 +742,8 @@ IF(WITH_ORB_SLAM AND NOT G2O_FOUND)
ENDIF(WITH_ORB_SLAM AND NOT G2O_FOUND)
IF(NOT MSVC)
IF(loam_velodyne_FOUND OR PCL_VERSION VERSION_GREATER "1.9.1" OR TORCH_FOUND OR G2O_FOUND OR CCCoreLib_FOUND)
#LOAM, PCL>=1.10, latest g2o and CCCoreLib require c++14
IF((NOT WITH_MSCKF_VIO OR NOT msckf_vio_FOUND) AND (loam_velodyne_FOUND OR floam_FOUND OR PCL_VERSION VERSION_GREATER "1.9.1" OR TORCH_FOUND OR G2O_FOUND OR CCCoreLib_FOUND OR Open3D_FOUND))
#LOAM, PCL>=1.10, latest g2o and CCCoreLib require c++14, but MSCKF_VIO requires c++11
include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("-std=c++14" COMPILER_SUPPORTS_CXX14)
IF(COMPILER_SUPPORTS_CXX14)
@@ -683,7 +752,7 @@ IF(NOT MSVC)
ELSE()
message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++14 support. Please use a different C++ compiler if you want to use LOAM, latest PCL or g2o.")
ENDIF()
ENDIF(loam_velodyne_FOUND OR PCL_VERSION VERSION_GREATER "1.9.1" OR TORCH_FOUND OR G2O_FOUND OR CCCoreLib_FOUND)
ENDIF()
IF( (NOT (${CMAKE_CXX_STANDARD} STREQUAL "14")) AND (
G2O_FOUND OR
@@ -768,6 +837,7 @@ ENDIF()
IF(NOT G2O_FOUND)
SET(G2O "//")
SET(G2O_CPP_CONF "//")
ELSE()
SET(CONF_DEPENDENCIES ${CONF_DEPENDENCIES} ${G2O_LIBRARIES})
IF(NOT G2O_CPP11)
@@ -799,15 +869,24 @@ ENDIF(NOT libpointmatcher_FOUND)
IF(NOT CCCoreLib_FOUND)
SET(CCCORELIB "//")
ENDIF(NOT CCCoreLib_FOUND)
IF(NOT Open3D_FOUND)
SET(OPEN3D "//")
ENDIF(NOT Open3D_FOUND)
IF(NOT FastCV_FOUND)
SET(FASTCV "//")
ENDIF(NOT FastCV_FOUND)
IF(NOT opengv_FOUND)
SET(OPENGV "//")
ENDIF(NOT opengv_FOUND)
IF(NOT PDAL_FOUND)
SET(PDAL "//")
ENDIF(NOT PDAL_FOUND)
IF(NOT loam_velodyne_FOUND)
SET(LOAM "//")
ENDIF(NOT loam_velodyne_FOUND)
IF(NOT floam_FOUND)
SET(FLOAM "//")
ENDIF(NOT floam_FOUND)
IF(NOT Freenect_FOUND)
SET(FREENECT "//")
ELSE()
@@ -870,8 +949,12 @@ IF(NOT mynteye_FOUND)
SET(MYNTEYE "//")
ENDIF(NOT mynteye_FOUND)
IF(NOT depthai_FOUND)
SET(CONF_DEPTH_AI OFF)
SET(DEPTHAI "//")
ENDIF(NOT depthai_FOUND)
ELSE()
SET(CONF_DEPTH_AI ON)
SET(CONF_DEPENDENCIES ${CONF_DEPENDENCIES} depthai::core depthai::opencv)
ENDIF()
IF(NOT octomap_FOUND)
SET(OCTOMAP "//")
ELSE()
@@ -936,12 +1019,16 @@ ENDIF()
IF(NOT TORCH_FOUND)
SET(TORCH "//")
ENDIF()
IF(NOT Python3_FOUND)
IF(NOT WITH_PYTHON OR NOT Python3_FOUND)
SET(PYTHON "//")
ENDIF()
IF(ADD_VTK_GUI_SUPPORT_QT_TO_CONF)
SET(CONF_VTK_QT true)
SET(CONF_DEPENDENCIES ${CONF_DEPENDENCIES} vtkGUISupportQt)
IF("${VTK_MAJOR_VERSION}" GREATER 8)
SET(CONF_DEPENDENCIES ${CONF_DEPENDENCIES} VTK::GUISupportQt)
ELSE()
SET(CONF_DEPENDENCIES ${CONF_DEPENDENCIES} vtkGUISupportQt)
ENDIF()
ELSE()
SET(CONF_VTK_QT false)
ENDIF()
@@ -952,7 +1039,7 @@ IF(NOT WITH_MADGWICK)
SET(MADGWICK "//")
ENDIF()
CONFIGURE_FILE(Version.h.in ${PROJECT_SOURCE_DIR}/corelib/include/${PROJECT_PREFIX}/core/Version.h)
CONFIGURE_FILE(Version.h.in ${CMAKE_CURRENT_BINARY_DIR}/corelib/include/${PROJECT_PREFIX}/core/Version.h)
ADD_SUBDIRECTORY( utilite )
ADD_SUBDIRECTORY( corelib )
@@ -996,7 +1083,8 @@ file(RELATIVE_PATH REL_INCLUDE_DIR "${CMAKE_INSTALL_PREFIX}/${INSTALL_CMAKE_DIR}
file(RELATIVE_PATH REL_LIB_DIR "${CMAKE_INSTALL_PREFIX}/${INSTALL_CMAKE_DIR}" "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}")
# ... for the build tree
set(CONF_INCLUDE_DIRS "${PROJECT_SOURCE_DIR}/corelib/include"
set(CONF_INCLUDE_DIRS "${PROJECT_BINARY_DIR}/corelib/include"
"${PROJECT_SOURCE_DIR}/corelib/include"
"${PROJECT_SOURCE_DIR}/guilib/include"
"${PROJECT_SOURCE_DIR}/utilite/include")
set(CONF_LIB_DIR "${CMAKE_ARCHIVE_OUTPUT_DIRECTORY} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}")
@@ -1207,7 +1295,7 @@ ELSE()
MESSAGE(STATUS " With SupertPoint = NO (libtorch not found)")
ENDIF()
IF(Python3_FOUND)
IF(WITH_PYTHON AND Python3_FOUND)
MESSAGE(STATUS " With Python${Python3_VERSION_MAJOR}.${Python3_VERSION_MINOR} = YES (License: PSF)")
ELSEIF(NOT WITH_PYTHON)
MESSAGE(STATUS " With Python3 = NO (WITH_PYTHON=OFF)")
@@ -1262,7 +1350,11 @@ MESSAGE(STATUS " *With GTSAM = NO (GTSAM not found)")
ENDIF()
IF(CERES_FOUND)
MESSAGE(STATUS " *With Ceres = YES (License: BSD)")
IF(WITH_CERES)
MESSAGE(STATUS " *With Ceres ${Ceres_VERSION} = YES (License: BSD)")
ELSE()
MESSAGE(STATUS " *With Ceres ${Ceres_VERSION} = YES (License: BSD, WITH_CERES=OFF but it is enabled by okvis or floam dependencies)")
ENDIF()
ELSEIF(NOT WITH_CERES)
MESSAGE(STATUS " *With Ceres = NO (WITH_CERES=OFF)")
ELSE()
@@ -1297,12 +1389,30 @@ ENDIF()
IF(CCCoreLib_FOUND)
MESSAGE(STATUS " With CCCoreLib = YES (License: GPLv2)")
ELSEIF(NOT WITH_POINTMATCHER)
ELSEIF(NOT WITH_CCCORELIB)
MESSAGE(STATUS " With CCCoreLib = NO (WITH_CCCORELIB=OFF)")
ELSE()
MESSAGE(STATUS " With CCCoreLib = NO (CCCoreLib not found)")
ENDIF()
IF(Open3D_FOUND)
MESSAGE(STATUS " With Open3D = YES (License: MIT)")
ELSEIF(NOT WITH_OPEN3D)
MESSAGE(STATUS " With Open3D = NO (WITH_OPEN3D=OFF)")
ELSEIF(${CMAKE_VERSION} VERSION_LESS "3.19.0")
MESSAGE(STATUS " With Open3D = NO (Open3D requires CMake>=3.19)")
ELSE()
MESSAGE(STATUS " With Open3D = NO (Open3D not found)")
ENDIF()
IF(opengv_FOUND)
MESSAGE(STATUS " With OpenGV = YES (License: BSD)")
ELSEIF(NOT WITH_OPENGV)
MESSAGE(STATUS " With OpenGV = NO (WITH_OPENGV=OFF)")
ELSE()
MESSAGE(STATUS " With OpenGV = NO (OpenGV not found)")
ENDIF()
MESSAGE(STATUS "")
MESSAGE(STATUS " Reconstruction Approaches:")
IF(octomap_FOUND)
@@ -1460,6 +1570,14 @@ ELSE()
MESSAGE(STATUS " With loam_velodyne = NO (loam_velodyne not found)")
ENDIF()
IF(floam_FOUND)
MESSAGE(STATUS " With floam = YES (License: BSD)")
ELSEIF(NOT WITH_FLOAM)
MESSAGE(STATUS " With floam = NO (WITH_FLOAM=OFF)")
ELSE()
MESSAGE(STATUS " With floam = NO (floam not found)")
ENDIF()
IF(libfovis_FOUND)
MESSAGE(STATUS " With libfovis = YES (License: GPLv2)")
ELSEIF(NOT WITH_FOVIS)
@@ -1529,12 +1647,12 @@ 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 AND NOT CERES_FOUND)
IF(NOT GTSAM_FOUND AND NOT G2O_FOUND AND NOT WITH_TORO AND NOT WITH_CERES 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 AND NOT CERES_FOUND)
ENDIF(NOT GTSAM_FOUND AND NOT G2O_FOUND AND NOT WITH_TORO AND NOT WITH_CERES AND NOT CERES_FOUND)
# vim: set et ft=cmake fenc=utf-8 ff=unix sts=0 sw=2 ts=2 :

View File

@@ -1,13 +1,12 @@
rtabmap ![Analytics](https://ga-beacon-279122.nn.r.appspot.com/UA-56986679-3/github-main?pixel)
rtabmap
=======
[![RTAB-Map Logo](https://raw.githubusercontent.com/introlab/rtabmap/master/guilib/src/images/RTAB-Map100.png)](http://introlab.github.io/rtabmap)
[![Release][release-image]][releases]
[![License][license-image]][license]
Linux: [![Build Status](https://travis-ci.org/introlab/rtabmap.svg?branch=master)](https://travis-ci.org/introlab/rtabmap) Windows: [![Build status](https://ci.appveyor.com/api/projects/status/hr73xspix9oqa26h/branch/master?svg=true)](https://ci.appveyor.com/project/matlabbe/rtabmap/branch/master)
[release-image]: https://img.shields.io/badge/release-0.20.7-green.svg?style=flat
[release-image]: https://img.shields.io/badge/release-0.20.16-green.svg?style=flat
[releases]: https://github.com/introlab/rtabmap/releases
[license-image]: https://img.shields.io/badge/license-BSD-green.svg?style=flat
@@ -15,7 +14,8 @@ Linux: [![Build Status](https://travis-ci.org/introlab/rtabmap.svg?branch=master
RTAB-Map library and standalone application.
For more information, visit the [RTAB-Map's home page](http://introlab.github.io/rtabmap) or the [RTAB-Map's wiki](https://github.com/introlab/rtabmap/wiki).
* For more information (e.g., papers, major updates), visit [RTAB-Map's home page](http://introlab.github.io/rtabmap).
* For installation instructions and examples, visit [RTAB-Map's wiki](https://github.com/introlab/rtabmap/wiki).
To use RTAB-Map under ROS, visit the [rtabmap](http://wiki.ros.org/rtabmap) page on the ROS wiki.
@@ -25,3 +25,52 @@ This project is supported by [IntRoLab - Intelligent / Interactive / Integrated
<a href="https://introlab.3it.usherbrooke.ca/">
<img src="https://github.com/introlab/16SoundsUSB/blob/master/images/IntRoLab.png" alt="IntRoLab" height="100">
</a>
#### CI Latest
<table>
<tbody>
<tr>
<td>Linux</td>
<td><a href="https://github.com/introlab/rtabmap/actions/workflows/cmake.yml"><img src="https://github.com/introlab/rtabmap/actions/workflows/cmake.yml/badge.svg" alt="Build Status"/> <br> <a href="https://github.com/introlab/rtabmap/actions/workflows/cmake-ros.yml"><img src="https://github.com/introlab/rtabmap/actions/workflows/cmake-ros.yml/badge.svg" alt="Build Status"/> <br> <a href="https://github.com/introlab/rtabmap/actions/workflows/docker.yml"><img src="https://github.com/introlab/rtabmap/actions/workflows/docker.yml/badge.svg" alt="Build Status"/>
</td>
</tr>
<tr>
<td>Windows</td>
<td><a href="https://ci.appveyor.com/project/matlabbe/rtabmap/branch/master"><img src="https://ci.appveyor.com/api/projects/status/hr73xspix9oqa26h/branch/master?svg=true" alt="Build Status"/>
</td>
</tr>
</tbody>
</table>
#### ROS Binaries
`ros-$ROS_DISTRO-rtabmap`
<table>
<tbody>
<tr>
<td rowspan="2">ROS 1</td>
<td>Melodic</td>
<td><a href="http://build.ros.org/job/Mbin_ubv8_uBv8__rtabmap__ubuntu_bionic_arm64__binary/"><img src="http://build.ros.org/buildStatus/icon?job=Mbin_ubv8_uBv8__rtabmap__ubuntu_bionic_arm64__binary" alt="Build Status"/></td>
</tr>
<tr>
<td>Noetic</td>
<td><a href="http://build.ros.org/job/Nbin_ufv8_uFv8__rtabmap__ubuntu_focal_arm64__binary/"><img src="http://build.ros.org/buildStatus/icon?job=Nbin_ufv8_uFv8__rtabmap__ubuntu_focal_arm64__binary" alt="Build Status"/></td>
</tr>
<tr>
<td rowspan="3">ROS 2</td>
<td>Foxy</td>
<td><a href="http://build.ros2.org/job/Fbin_uF64__rtabmap__ubuntu_focal_amd64__binary/"><img src="http://build.ros2.org/buildStatus/icon?job=Fbin_uF64__rtabmap__ubuntu_focal_amd64__binary" alt="Build Status"/></td>
</tr>
<tr>
<td>Humble</td>
<td><a href="http://build.ros2.org/job/Hbin_uJ64__rtabmap__ubuntu_jammy_amd64__binary/"><img src="http://build.ros2.org/buildStatus/icon?job=Hbin_uJ64__rtabmap__ubuntu_jammy_amd64__binary" alt="Build Status"/></td>
</tr>
<tr>
<td>Rolling</td>
<td><a href="http://build.ros2.org/job/Rbin_uJ64__rtabmap__ubuntu_jammy_amd64__binary/"><img src="http://build.ros2.org/buildStatus/icon?job=Rbin_uJ64__rtabmap__ubuntu_jammy_amd64__binary" alt="Build Status"/></td>
</tr>
</tbody>
</table>

View File

@@ -81,6 +81,9 @@ endif()
if(@CONF_VTK_QT@ AND ${WITH_GUI})
find_package(VTK COMPONENTS vtkGUISupportQt NO_MODULE) # to define vtkGUISupportQt target
endif(@CONF_VTK_QT@ AND ${WITH_GUI})
if(@CONF_DEPTH_AI@)
FIND_PACKAGE(depthai 2 QUIET REQUIRED)
endif(@CONF_DEPTH_AI@)
SET(RTABMap_LIBRARIES ${RTABMap_LIBRARIES} "@CONF_DEPENDENCIES@")
#backward compatibilities

View File

@@ -40,7 +40,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@NONFREE@#define RTABMAP_NONFREE
@TORO@#define RTABMAP_TORO
@G2O@#define RTABMAP_G2O
@G2O_CPP_CONF@#define RTABMAP_G2O_CPP11
@G2O_CPP_CONF@#define RTABMAP_G2O_CPP11 @G2O_CPP11@
@GTSAM@#define RTABMAP_GTSAM
@CERES@#define RTABMAP_CERES
@VERTIGO@#define RTABMAP_VERTIGO
@@ -52,9 +52,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@CVSBA@#define RTABMAP_CVSBA
@POINTMATCHER@#define RTABMAP_POINTMATCHER
@CCCORELIB@#define RTABMAP_CCCORELIB
@OPEN3D@#define RTABMAP_OPEN3D
@FASTCV@#define RTABMAP_FASTCV
@OPENGV@#define RTABMAP_OPENGV
@PDAL@#define RTABMAP_PDAL
@LOAM@#define RTABMAP_LOAM
@FLOAM@#define RTABMAP_FLOAM
@DC1394@#define RTABMAP_DC1394
@FLYCAPTURE2@#define RTABMAP_FLYCAPTURE2
@ZED@#define RTABMAP_ZED

View File

@@ -17,6 +17,11 @@
<!-- This is the platform API where depth16 support in android was introduced. -->
<uses-sdk android:minSdkVersion="@ANDROID_NATIVE_API_LEVEL@" />
<queries>
<package android:name="com.google.ar.core" />
<package android:name="com.huawei.ar.engine" />
</queries>
<!-- This .apk has no Java code itself, so set hasCode to false. -->
<application
@@ -42,7 +47,16 @@
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND" />
<action android:name="android.intent.action.SEND_MULTIPLE" />
<action android:name="android.intent.action.OPEN_DOCUMENT" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="application/octet-stream" />
<data android:pathPattern=".*\.db" />
</intent-filter>
</activity>
<activity android:name="SettingsActivity" android:label="@string/settings" android:screenOrientation="fullSensor"/>

View File

@@ -3,6 +3,7 @@ SET(INCLUDE_DIRS
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/tango-gl/include
${CMAKE_CURRENT_SOURCE_DIR}/third-party/include
${PROJECT_BINARY_DIR}/corelib/include
${PROJECT_SOURCE_DIR}/corelib/include
${PROJECT_SOURCE_DIR}/utilite/include
${OpenCV_INCLUDE_DIRS}

View File

@@ -43,9 +43,6 @@ CameraARCore::CameraARCore(void* env, void* context, void* activity, bool depthF
context_(context),
activity_(activity),
arInstallRequested_(false),
textureId_(9999),
uvs_initialized_(false),
updateOcclusionImage_(false),
depthFromMotion_(depthFromMotion)
{
}
@@ -53,12 +50,6 @@ CameraARCore::CameraARCore(void* env, void* context, void* activity, bool depthF
CameraARCore::~CameraARCore() {
// Disconnect ARCore service
close();
if(textureId_ != 9999)
{
glDeleteTextures(1, &textureId_);
textureId_ = 9999;
}
}
@@ -176,7 +167,7 @@ bool CameraARCore::init(const std::string & calibrationFolder, const std::string
ArConfig_setDepthMode(arSession_, arConfig_, AR_DEPTH_MODE_DISABLED);
}
ArConfig_setFocusMode(arSession_, arConfig_, AR_FOCUS_MODE_AUTO);
ArConfig_setFocusMode(arSession_, arConfig_, AR_FOCUS_MODE_FIXED);
UASSERT(ArSession_configure(arSession_, arConfig_) == AR_SUCCESS);
ArFrame_create(arSession_, &arFrame_);
@@ -279,7 +270,6 @@ void CameraARCore::close()
arPose_ = nullptr;
CameraMobile::close();
occlusionImage_ = cv::Mat();
}
LaserScan CameraARCore::scanFromPointCloudData(
@@ -355,7 +345,7 @@ SensorData CameraARCore::captureImage(CameraInfo * info)
return data;
}
if(textureId_ == 9999)
if(textureId_ == 0)
{
glGenTextures(1, &textureId_);
glBindTexture(GL_TEXTURE_EXTERNAL_OES, textureId_);
@@ -364,7 +354,8 @@ SensorData CameraARCore::captureImage(CameraInfo * info)
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_);
if(textureId_!=0)
ArSession_setCameraTextureName(arSession_, textureId_);
// Update session to get current frame and render camera background.
if (ArSession_update(arSession_, arFrame_) != AR_SUCCESS) {
@@ -393,6 +384,12 @@ SensorData CameraARCore::captureImage(CameraInfo * info)
/*near=*/0.1f, /*far=*/100.f,
glm::value_ptr(projectionMatrix_));
// adjust origin
if(!getOriginOffset().isNull())
{
viewMatrix_ = glm::inverse(rtabmap::glmFromTransform(rtabmap::opengl_world_T_rtabmap_world * getOriginOffset() *rtabmap::rtabmap_world_T_opengl_world)*glm::inverse(viewMatrix_));
}
ArTrackingState camera_tracking_state;
ArCamera_getTrackingState(arSession_, ar_camera, &camera_tracking_state);
@@ -407,6 +404,22 @@ SensorData CameraARCore::captureImage(CameraInfo * info)
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;
Transform poseArCore = pose;
if(pose.isNull())
{
LOGE("CameraARCore: Pose is null");
}
else
{
this->poseReceived(pose);
// adjust origin
if(!getOriginOffset().isNull())
{
pose = getOriginOffset() * pose;
}
info->odomPose = pose;
}
// Get calibration parameters
float fx,fy, cx, cy;
int32_t width, height;
@@ -432,7 +445,7 @@ SensorData CameraARCore::captureImage(CameraInfo * info)
ArStatus status = ArFrame_acquireCameraImage(arSession_, arFrame_, &image);
if(status == AR_SUCCESS)
{
if(is_depth_supported && (updateOcclusionImage_||depthFromMotion_))
if(is_depth_supported)
{
LOGD("Acquire depth image!");
ArImage * depthImage = nullptr;
@@ -459,11 +472,12 @@ SensorData CameraARCore::captureImage(CameraInfo * info)
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();
cv::Mat 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));
CameraModel occlusionModel(fx*scaleX, fy*scaleY, cx*scaleX, cy*scaleY, pose*deviceTColorCamera_, 0, cv::Size(depth_width, depth_height));
this->setOcclusionImage(occlusionImage, occlusionModel);
}
ArImage_release(depthImage);
}
@@ -506,11 +520,11 @@ SensorData CameraARCore::captureImage(CameraInfo * info)
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);
cv::cvtColor(yuv, rgb, cv::COLOR_YUV2BGR_NV21);
}
else
{
cv::cvtColor(cv::Mat(height+height/2, width, CV_8UC1, (void*)plane_data), rgb, CV_YUV2BGR_NV21);
cv::cvtColor(cv::Mat(height+height/2, width, CV_8UC1, (void*)plane_data), rgb, cv::COLOR_YUV2BGR_NV21);
}
std::vector<cv::KeyPoint> kpts;
@@ -527,7 +541,7 @@ SensorData CameraARCore::captureImage(CameraInfo * info)
#endif
if(pointCloudData && points>0)
{
scan = scanFromPointCloudData(pointCloudData, points, pose, model, rgb, &kpts, &kpts3);
scan = scanFromPointCloudData(pointCloudData, points, poseArCore, model, rgb, &kpts, &kpts3);
}
}
else
@@ -535,7 +549,7 @@ SensorData CameraARCore::captureImage(CameraInfo * info)
LOGI("pointCloud empty");
}
data = SensorData(scan, rgb, depthFromMotion_?occlusionImage_:cv::Mat(), model, 0, stamp);
data = SensorData(scan, rgb, depthFromMotion_?getOcclusionImage():cv::Mat(), model, 0, stamp);
data.setFeatures(kpts, kpts3, cv::Mat());
}
}
@@ -556,15 +570,6 @@ SensorData CameraARCore::captureImage(CameraInfo * info)
ArCamera_release(ar_camera);
if(pose.isNull())
{
LOGE("CameraARCore: Pose is null");
}
else
{
this->poseReceived(pose);
info->odomPose = pose;
}
return data;
}
@@ -579,16 +584,15 @@ void CameraARCore::capturePoseOnly()
return;
}
if(textureId_ == 9999)
if(textureId_ != 0)
{
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_);
}
ArSession_setCameraTextureName(arSession_, textureId_);
// Update session to get current frame and render camera background.
if (ArSession_update(arSession_, arFrame_) != AR_SUCCESS) {
@@ -617,6 +621,12 @@ void CameraARCore::capturePoseOnly()
/*near=*/0.1f, /*far=*/100.f,
glm::value_ptr(projectionMatrix_));
// adjust origin
if(!getOriginOffset().isNull())
{
viewMatrix_ = glm::inverse(rtabmap::glmFromTransform(rtabmap::opengl_world_T_rtabmap_world * getOriginOffset() *rtabmap::rtabmap_world_T_opengl_world)*glm::inverse(viewMatrix_));
}
ArTrackingState camera_tracking_state;
ArCamera_getTrackingState(arSession_, ar_camera, &camera_tracking_state);
@@ -633,12 +643,17 @@ void CameraARCore::capturePoseOnly()
{
pose = rtabmap::rtabmap_world_T_opengl_world * pose * rtabmap::opengl_world_T_rtabmap_world;
this->poseReceived(pose);
if(!getOriginOffset().isNull())
{
pose = getOriginOffset() * pose;
}
}
int32_t is_depth_supported = 0;
ArSession_isDepthModeSupported(arSession_, AR_DEPTH_MODE_AUTOMATIC, &is_depth_supported);
if(is_depth_supported && updateOcclusionImage_)
if(is_depth_supported)
{
LOGD("Acquire depth image!");
ArImage * depthImage = nullptr;
@@ -665,7 +680,7 @@ void CameraARCore::capturePoseOnly()
LOGD("width=%d, height=%d, bytes=%d stride=%d", width, height, len, stride);
occlusionImage_ = cv::Mat(height, width, CV_16UC1, (void*)data).clone();
cv::Mat occlusionImage = cv::Mat(height, width, CV_16UC1, (void*)data).clone();
float fx,fy, cx, cy;
int32_t rgb_width, rgb_height;
@@ -676,7 +691,8 @@ void CameraARCore::capturePoseOnly()
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));
CameraModel occlusionModel(fx*scaleX, fy*scaleY, cx*scaleX, cy*scaleY, pose*deviceTColorCamera_, 0, cv::Size(width, height));
this->setOcclusionImage(occlusionImage, occlusionModel);
}
ArImage_release(depthImage);
}

View File

@@ -67,9 +67,6 @@ public:
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 = "");
@@ -97,17 +94,8 @@ private:
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_;
};

View File

@@ -244,7 +244,7 @@ SensorData CameraAREngine::captureImage(CameraInfo * info)
cv::Mat outputRGB;
if(imageData != nullptr && len>0)
{
cv::cvtColor(cv::Mat(height+height/2, width, CV_8UC1, (void*)imageData), outputRGB, CV_YUV2BGR_NV21);
cv::cvtColor(cv::Mat(height+height/2, width, CV_8UC1, (void*)imageData), outputRGB, cv::COLOR_YUV2BGR_NV21);
}
//Depth
@@ -300,6 +300,11 @@ SensorData CameraAREngine::captureImage(CameraInfo * info)
{
pose = rtabmap::rtabmap_world_T_opengl_world * pose * rtabmap::opengl_world_T_rtabmap_world;
this->poseReceived(pose);
// adjust origin
if(!getOriginOffset().isNull())
{
pose = getOriginOffset() * pose;
}
info->odomPose = pose;
}
return data;

View File

@@ -31,6 +31,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "rtabmap/core/util3d_transforms.h"
#include "rtabmap/core/OdometryEvent.h"
#include "rtabmap/core/util2d.h"
#include <glm/gtx/transform.hpp>
namespace rtabmap {
@@ -55,6 +56,8 @@ CameraMobile::CameraMobile(bool smoothing) :
Camera(10),
deviceTColorCamera_(Transform::getIdentity()),
spinOncePreviousStamp_(0.0),
textureId_(0),
uvs_initialized_(false),
previousStamp_(0.0),
stampEpochOffset_(0.0),
smoothing_(smoothing),
@@ -84,10 +87,22 @@ void CameraMobile::close()
originUpdate_ = false;
pose_ = Transform();
data_ = SensorData();
if(textureId_ != 0)
{
glDeleteTextures(1, &textureId_);
textureId_ = 0;
}
}
void CameraMobile::resetOrigin()
{
previousPose_.setNull();
previousStamp_ = 0.0;
lastKnownGPS_ = GPS();
lastEnvSensors_.clear();
pose_ = Transform();
data_ = SensorData();
originUpdate_ = true;
}
@@ -124,11 +139,60 @@ void CameraMobile::setGPS(const GPS & gps)
lastKnownGPS_ = gps;
}
void CameraMobile::setData(const SensorData & data, const Transform & pose)
void CameraMobile::setData(const SensorData & data, const Transform & pose, const glm::mat4 & viewMatrix, const glm::mat4 & projectionMatrix, const float * texCoord)
{
LOGD("CameraMobile::setData pose=%s stamp=%f", pose.prettyPrint().c_str(), data.stamp());
data_ = data;
pose_ = pose;
pose_ = pose;
viewMatrix_ = viewMatrix;
projectionMatrix_ = projectionMatrix;
// adjust origin
if(!originOffset_.isNull())
{
pose_ = originOffset_ * pose_;
viewMatrix_ = glm::inverse(rtabmap::glmFromTransform(rtabmap::opengl_world_T_rtabmap_world * originOffset_ *rtabmap::rtabmap_world_T_opengl_world)*glm::inverse(viewMatrix_));
}
if(textureId_ == 0)
{
glGenTextures(1, &textureId_);
}
if(texCoord)
{
memcpy(transformed_uvs_, texCoord, 8*sizeof(float));
uvs_initialized_ = true;
}
LOGD("CameraMobile::setData textureId_=%d", (int)textureId_);
if(textureId_ != 0 && texCoord != 0)
{
cv::Mat rgbImage;
cv::cvtColor(data.imageRaw(), rgbImage, cv::COLOR_BGR2RGBA);
glBindTexture(GL_TEXTURE_2D, textureId_);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
//glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
//glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
//glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, rgbImage.cols, rgbImage.rows, 0, GL_RGBA, GL_UNSIGNED_BYTE, rgbImage.data);
GLint error = glGetError();
if(error != GL_NO_ERROR)
{
LOGE("OpenGL: Could not allocate texture (0x%x)\n", error);
textureId_ = 0;
return;
}
}
}
void CameraMobile::addEnvSensor(int type, float value)
@@ -141,16 +205,16 @@ void CameraMobile::spinOnce()
if(!this->isRunning())
{
bool ignoreFrame = false;
float rate = 10.0f; // maximum 10 FPS for image data
//float rate = 10.0f; // maximum 10 FPS for image data
double now = UTimer::now();
if(rate>0.0f)
/*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)
{
@@ -322,7 +386,7 @@ void CameraMobile::mainLoop()
previousPose_ = pose;
previousStamp_ = data.stamp();
}
else if(!this->isKilled())
else if(!this->isKilled() && info.odomPose.isNull())
{
LOGW("Odometry lost");
this->post(new OdometryEvent());
@@ -338,4 +402,60 @@ SensorData CameraMobile::captureImage(CameraInfo * info)
return data_;
}
LaserScan CameraMobile::scanFromPointCloudData(
const cv::Mat & pointCloudData,
int points,
const Transform & pose,
const CameraModel & model,
const cv::Mat & rgb,
std::vector<cv::KeyPoint> * kpts,
std::vector<cv::Point3f> * kpts3D,
int kptsSize)
{
if(!pointCloudData.empty())
{
cv::Mat scanData(1, pointCloudData.cols, CV_32FC4);
float * ptr = scanData.ptr<float>();
const float * inPtr = pointCloudData.ptr<float>();
int ic = pointCloudData.channels();
UASSERT(pointCloudData.depth() == CV_32F && ic >= 3);
int oi = 0;
for(unsigned int i=0;i<points; ++i)
{
cv::Point3f pt(inPtr[i*ic], inPtr[i*ic + 1], inPtr[i*ic + 2]);
pt = util3d::transformPoint(pt, pose.inverse()*rtabmap_world_T_opengl_world);
ptr[oi*4] = pt.x;
ptr[oi*4 + 1] = pt.y;
ptr[oi*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,kptsSize));
if(kpts3D)
kpts3D->push_back(org);
*(int*)&ptr[oi*4 + 3] = int(b) | (int(g) << 8) | (int(r) << 16);
++oi;
}
//confidence
//*(int*)&ptr[i*4 + 3] = (int(pointCloudData[i*4 + 3] * 255.0f) << 8) | (int(255) << 16);
}
return LaserScan::backwardCompatibility(scanData.colRange(0, oi), 0, 10, rtabmap::Transform::getIdentity());
}
return LaserScan();
}
} /* namespace rtabmap */

View File

@@ -75,6 +75,17 @@ public:
static const rtabmap::Transform opticalRotation;
static const rtabmap::Transform opticalRotationInv;
public:
static LaserScan scanFromPointCloudData(
const cv::Mat & 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,
int kptsSize = 3);
public:
CameraMobile(bool smoothing = false);
@@ -97,9 +108,18 @@ public:
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 setData(const SensorData & data, const Transform & pose, const glm::mat4 & viewMatrix, const glm::mat4 & projectionMatrix, const float * texCoord);
void spinOnce(); // Should only be called if not thread is not running, otherwise it does nothing
GLuint getTextureId() {return textureId_;}
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_;}
ScreenRotation getScreenRotation() const {return colorCameraToDisplayRotation_;}
void setOcclusionImage(const cv::Mat & image, const CameraModel & model) {occlusionModel_ = model; occlusionImage_ = image;}
const cv::Mat & getOcclusionImage(CameraModel * model=0) const {if(model)*model=occlusionModel_; return occlusionImage_; }
protected:
virtual SensorData captureImage(CameraInfo * info = 0);
@@ -113,6 +133,12 @@ protected:
Transform deviceTColorCamera_; // device to camera optical rotation in rtabmap frame
UTimer spinOnceFrameRateTimer_;
double spinOncePreviousStamp_;
GLuint textureId_;
glm::mat4 viewMatrix_;
glm::mat4 projectionMatrix_;
float transformed_uvs_[8];
bool uvs_initialized_ = false;
private:
Transform previousPose_;
@@ -128,6 +154,9 @@ private:
SensorData data_;
Transform pose_;
cv::Mat occlusionImage_;
CameraModel occlusionModel_;
};
} /* namespace rtabmap */

View File

@@ -33,6 +33,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "rtabmap/core/util2d.h"
#include <tango_client_api.h>
#include <tango_support_api.h>
#include "tango-gl/camera.h"
namespace rtabmap {
@@ -42,11 +43,22 @@ const int holeSize = 5;
const float maxDepthError = 0.10;
const int scanDownsampling = 1;
//android phone
//11 10 01 00 // portrait
//01 11 00 10 // left
//10 00 11 01 // right
//00 01 10 11 // down
const float kTextureCoords0[] = {1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0};
const float kTextureCoords90[] = {0.0, 1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0};
const float kTextureCoords180[] = {0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0};
const float kTextureCoords270[] = {1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0};
// Callbacks
void onPointCloudAvailableRouter(void* context, const TangoPointCloud* point_cloud)
{
CameraTango* app = static_cast<CameraTango*>(context);
if(app->isRunning() && point_cloud->num_points>0)
if(point_cloud->num_points>0)
{
app->cloudReceived(cv::Mat(1, point_cloud->num_points, CV_32FC4, point_cloud->points[0]), point_cloud->timestamp);
}
@@ -55,34 +67,32 @@ void onPointCloudAvailableRouter(void* context, const TangoPointCloud* point_clo
void onFrameAvailableRouter(void* context, TangoCameraId id, const TangoImageBuffer* color)
{
CameraTango* app = static_cast<CameraTango*>(context);
if(app->isRunning())
{
cv::Mat tangoImage;
if(color->format == TANGO_HAL_PIXEL_FORMAT_RGBA_8888)
{
tangoImage = cv::Mat(color->height, color->width, CV_8UC4, color->data);
}
else if(color->format == TANGO_HAL_PIXEL_FORMAT_YV12)
{
tangoImage = cv::Mat(color->height+color->height/2, color->width, CV_8UC1, color->data);
}
else if(color->format == TANGO_HAL_PIXEL_FORMAT_YCrCb_420_SP)
{
tangoImage = cv::Mat(color->height+color->height/2, color->width, CV_8UC1, color->data);
}
else if(color->format == 35)
{
tangoImage = cv::Mat(color->height+color->height/2, color->width, CV_8UC1, color->data);
}
else
{
LOGE("Not supported color format : %d.", color->format);
}
if(!tangoImage.empty())
{
app->rgbReceived(tangoImage, (unsigned int)color->format, color->timestamp);
}
cv::Mat tangoImage;
if(color->format == TANGO_HAL_PIXEL_FORMAT_RGBA_8888)
{
tangoImage = cv::Mat(color->height, color->width, CV_8UC4, color->data);
}
else if(color->format == TANGO_HAL_PIXEL_FORMAT_YV12)
{
tangoImage = cv::Mat(color->height+color->height/2, color->width, CV_8UC1, color->data);
}
else if(color->format == TANGO_HAL_PIXEL_FORMAT_YCrCb_420_SP)
{
tangoImage = cv::Mat(color->height+color->height/2, color->width, CV_8UC1, color->data);
}
else if(color->format == 35)
{
tangoImage = cv::Mat(color->height+color->height/2, color->width, CV_8UC1, color->data);
}
else
{
LOGE("Not supported color format : %d.", color->format);
}
if(!tangoImage.empty())
{
app->rgbReceived(tangoImage, (unsigned int)color->format, color->timestamp);
}
}
@@ -110,7 +120,6 @@ CameraTango::CameraTango(bool colorCamera, int decimation, bool publishRawScan,
colorCamera_(colorCamera),
decimation_(decimation),
rawScanPublished_(publishRawScan),
cloudStamp_(0),
tangoColorType_(0),
tangoColorStamp_(0)
{
@@ -430,7 +439,7 @@ void CameraTango::close()
void CameraTango::cloudReceived(const cv::Mat & cloud, double timestamp)
{
if(this->isRunning() && !cloud.empty())
if(!cloud.empty())
{
//LOGD("Depth received! %fs (%d points)", timestamp, cloud.cols);
@@ -447,20 +456,248 @@ void CameraTango::cloudReceived(const cv::Mat & cloud, double timestamp)
// So, synchronize with the last RGB frame before the Depth is acquired
if(!tangoColor_.empty())
{
UTimer timer;
double dt = fabs(timestamp - tangoColorStamp_);
//LOGD("Depth: %f vs %f = %f", tangoColorStamp_, timestamp, dt);
if(dt >= 0.0 && dt < 0.5)
{
bool notify = cloud_.empty();
cloud_ = cloud.clone();
cloudStamp_ = timestamp;
bool notify = !data_.isValid();
cv::Mat tangoImage = tangoColor_;
cv::Mat rgb;
double cloudStamp = timestamp;
double rgbStamp = tangoColorStamp_;
int tangoColorType = tangoColorType_;
tangoColor_ = cv::Mat();
tangoColorStamp_ = 0.0;
tangoColorType_ = 0;
LOGD("tangoColorType=%d", tangoColorType);
if(tangoColorType == TANGO_HAL_PIXEL_FORMAT_RGBA_8888)
{
cv::cvtColor(tangoImage, rgb, cv::COLOR_RGBA2BGR);
}
else if(tangoColorType == TANGO_HAL_PIXEL_FORMAT_YV12)
{
cv::cvtColor(tangoImage, rgb, cv::COLOR_YUV2BGR_YV12);
}
else if(tangoColorType == TANGO_HAL_PIXEL_FORMAT_YCrCb_420_SP)
{
cv::cvtColor(tangoImage, rgb, cv::COLOR_YUV2BGR_NV21);
}
else if(tangoColorType == 35)
{
cv::cvtColor(tangoImage, rgb, cv::COLOR_YUV420sp2GRAY);
}
else
{
LOGE("Not supported color format : %d.", tangoColorType);
data_ = SensorData();
return;
}
//for(int i=0; i<rgb.cols; ++i)
//{
// UERROR("%d,%d,%d", (int)rgb.at<cv::Vec3b>(i)[0], (int)rgb.at<cv::Vec3b>(i)[1], (int)rgb.at<cv::Vec3b>(i)[2]);
//}
CameraModel model = model_;
if(colorCamera_)
{
if(decimation_ > 1)
{
rgb = util2d::decimate(rgb, decimation_);
model = model.scaled(1.0/double(decimation_));
}
}
else
{
//UTimer t;
cv::Mat rgbRect;
cv::remap(rgb, rgbRect, fisheyeRectifyMapX_, fisheyeRectifyMapY_, cv::INTER_LINEAR, cv::BORDER_CONSTANT, 0);
rgb = rgbRect;
//LOGD("Rectification time=%fs", t.ticks());
}
// Querying the depth image's frame transformation based on the depth image's
// timestamp.
cv::Mat depth;
// Calculate the relative pose from color camera frame at timestamp
// color_timestamp t1 and depth
// camera frame at depth_timestamp t0.
Transform colorToDepth;
TangoPoseData pose_color_image_t1_T_depth_image_t0;
if (TangoSupport_calculateRelativePose(
rgbStamp, colorCamera_?TANGO_COORDINATE_FRAME_CAMERA_COLOR:TANGO_COORDINATE_FRAME_CAMERA_FISHEYE, cloudStamp,
TANGO_COORDINATE_FRAME_CAMERA_DEPTH,
&pose_color_image_t1_T_depth_image_t0) == TANGO_SUCCESS)
{
colorToDepth = tangoPoseToTransform(&pose_color_image_t1_T_depth_image_t0);
}
else
{
LOGE(
"SynchronizationApplication: Could not find a valid relative pose at "
"time for color and "
" depth cameras.");
}
if(colorToDepth.getNormSquared() > 100000)
{
LOGE("Very large color to depth error detected (%s)! Ignoring this frame!", colorToDepth.prettyPrint().c_str());
colorToDepth.setNull();
}
cv::Mat scan;
if(!colorToDepth.isNull())
{
// The Color Camera frame at timestamp t0 with respect to Depth
// Camera frame at timestamp t1.
//LOGD("colorToDepth=%s", colorToDepth.prettyPrint().c_str());
LOGD("rgb=%dx%d cloud size=%d", rgb.cols, rgb.rows, (int)cloud.total());
int pixelsSet = 0;
int depthSizeDec = colorCamera_?8:1;
depth = cv::Mat::zeros(model_.imageHeight()/depthSizeDec, model_.imageWidth()/depthSizeDec, CV_16UC1); // mm
CameraModel depthModel = model_.scaled(1.0f/float(depthSizeDec));
std::vector<cv::Point3f> scanData(rawScanPublished_?cloud.total():0);
int oi=0;
int closePoints = 0;
float closeROI[4];
closeROI[0] = depth.cols/4;
closeROI[1] = 3*(depth.cols/4);
closeROI[2] = depth.rows/4;
closeROI[3] = 3*(depth.rows/4);
unsigned short minDepthValue=10000;
for(unsigned int i=0; i<cloud.total(); ++i)
{
const float * p = cloud.ptr<float>(0,i);
cv::Point3f pt = util3d::transformPoint(cv::Point3f(p[0], p[1], p[2]), colorToDepth);
if(pt.z > 0.0f && i%scanDownsampling == 0 && rawScanPublished_)
{
scanData.at(oi++) = pt;
}
int pixel_x_l, pixel_y_l, pixel_x_h, pixel_y_h;
// get the coordinate on image plane.
pixel_x_l = static_cast<int>((depthModel.fx()) * (pt.x / pt.z) + depthModel.cx());
pixel_y_l = static_cast<int>((depthModel.fy()) * (pt.y / pt.z) + depthModel.cy());
pixel_x_h = static_cast<int>((depthModel.fx()) * (pt.x / pt.z) + depthModel.cx() + 0.5f);
pixel_y_h = static_cast<int>((depthModel.fy()) * (pt.y / pt.z) + depthModel.cy() + 0.5f);
unsigned short depth_value(pt.z * 1000.0f);
if(pixel_x_l>=closeROI[0] && pixel_x_l<closeROI[1] &&
pixel_y_l>closeROI[2] && pixel_y_l<closeROI[3] &&
depth_value < 600)
{
++closePoints;
if(depth_value < minDepthValue)
{
minDepthValue = depth_value;
}
}
bool pixelSet = false;
if(pixel_x_l>=0 && pixel_x_l<depth.cols &&
pixel_y_l>0 && pixel_y_l<depth.rows && // ignore first line
depth_value)
{
unsigned short & depthPixel = depth.at<unsigned short>(pixel_y_l, pixel_x_l);
if(depthPixel == 0 || depthPixel > depth_value)
{
depthPixel = depth_value;
pixelSet = true;
}
}
if(pixel_x_h>=0 && pixel_x_h<depth.cols &&
pixel_y_h>0 && pixel_y_h<depth.rows && // ignore first line
depth_value)
{
unsigned short & depthPixel = depth.at<unsigned short>(pixel_y_h, pixel_x_h);
if(depthPixel == 0 || depthPixel > depth_value)
{
depthPixel = depth_value;
pixelSet = true;
}
}
if(pixelSet)
{
pixelsSet += 1;
}
}
if(closePoints > 100)
{
this->post(new CameraInfoEvent(0, "TooClose", ""));
}
if(oi)
{
scan = cv::Mat(1, oi, CV_32FC3, scanData.data()).clone();
}
//LOGD("pixels depth set= %d", pixelsSet);
}
else
{
LOGE("color to depth pose is null?!? (rgb stamp=%f) (depth stamp=%f)", rgbStamp, cloudStamp);
}
if(!rgb.empty() && !depth.empty())
{
depth = rtabmap::util2d::fillDepthHoles(depth, holeSize, maxDepthError);
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());
// adjust origin
if(!getOriginOffset().isNull())
{
odom = getOriginOffset() * odom;
}
// occlusion depth
if(!depth.empty())
{
rtabmap::CameraModel depthModel = model.scaled(float(depth.cols) / float(model.imageWidth()));
depthModel.setLocalTransform(odom*model.localTransform());
this->setOcclusionImage(depth, depthModel);
}
//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();
if(rawScanPublished_)
{
data_ = SensorData(LaserScan::backwardCompatibility(scan, cloud.total()/scanDownsampling, 0, scanLocalTransform), rgb, depth, model, this->getNextSeqID(), rgbStamp);
}
else
{
data_ = SensorData(rgb, depth, model, this->getNextSeqID(), rgbStamp);
}
data_.setGroundTruth(odom);
}
else
{
LOGE("Could not get depth and rgb images!?!");
data_ = SensorData();
return;
}
if(notify)
{
//LOGD("Cloud: Release semaphore");
dataReady_.release();
}
LOGD("process cloud received %fs", timer.ticks());
}
}
}
@@ -468,7 +705,7 @@ void CameraTango::cloudReceived(const cv::Mat & cloud, double timestamp)
void CameraTango::rgbReceived(const cv::Mat & tangoImage, int type, double timestamp)
{
if(this->isRunning() && !tangoImage.empty())
if(!tangoImage.empty())
{
//LOGD("RGB received! %fs", timestamp);
@@ -532,7 +769,6 @@ rtabmap::Transform CameraTango::getPoseAtTimestamp(double timestamp)
}
else
{
pose = rtabmap_world_T_tango_world * tangoPoseToTransform(&pose_start_service_T_device) * tango_device_T_rtabmap_world;
}
@@ -543,254 +779,112 @@ SensorData CameraTango::captureImage(CameraInfo * info)
{
//LOGI("Capturing image...");
SensorData data;
if(!dataReady_.acquire(1, 2000))
if(textureId_ == 0)
{
if(this->isRunning())
{
LOGE("Not received any frames since 2 seconds, try to restart the camera again.");
this->post(new CameraInfoEvent(0, "CameraTango", "No frames received since 2 seconds."));
boost::mutex::scoped_lock lock(dataMutex_);
if(!cloud_.empty() && !tangoColor_.empty())
{
UERROR("cloud and image were set!?");
}
}
cloud_ = cv::Mat();
cloudStamp_ = 0.0;
tangoColor_ = cv::Mat();
tangoColorStamp_ = 0.0;
tangoColorType_ = 0;
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);
}
else
// Update Texture (optional, just for first-view rendering)
if(colorCamera_ && textureId_)
{
cv::Mat cloud;
cv::Mat tangoImage;
cv::Mat rgb;
double cloudStamp = 0.0;
double rgbStamp = 0.0;
int tangoColorType = 0;
double video_overlay_timestamp;
TangoErrorType status = TangoService_updateTextureExternalOes(TANGO_CAMERA_COLOR, textureId_, &video_overlay_timestamp);
if (status == TANGO_SUCCESS)
{
boost::mutex::scoped_lock lock(dataMutex_);
cloud = cloud_;
cloudStamp = cloudStamp_;
cloud_ = cv::Mat();
cloudStamp_ = 0.0;
tangoImage = tangoColor_;
rgbStamp = tangoColorStamp_;
tangoColorType = tangoColorType_;
tangoColor_ = cv::Mat();
tangoColorStamp_ = 0.0;
tangoColorType_ = 0;
}
LOGD("tangoColorType=%d", tangoColorType);
if(tangoColorType == TANGO_HAL_PIXEL_FORMAT_RGBA_8888)
{
cv::cvtColor(tangoImage, rgb, CV_RGBA2BGR);
}
else if(tangoColorType == TANGO_HAL_PIXEL_FORMAT_YV12)
{
cv::cvtColor(tangoImage, rgb, CV_YUV2BGR_YV12);
}
else if(tangoColorType == TANGO_HAL_PIXEL_FORMAT_YCrCb_420_SP)
{
cv::cvtColor(tangoImage, rgb, CV_YUV2BGR_NV21);
}
else if(tangoColorType == 35)
{
cv::cvtColor(tangoImage, rgb, cv::COLOR_YUV420sp2GRAY);
}
else
{
LOGE("Not supported color format : %d.", tangoColorType);
return data;
}
//for(int i=0; i<rgb.cols; ++i)
//{
// UERROR("%d,%d,%d", (int)rgb.at<cv::Vec3b>(i)[0], (int)rgb.at<cv::Vec3b>(i)[1], (int)rgb.at<cv::Vec3b>(i)[2]);
//}
CameraModel model = model_;
if(colorCamera_)
{
if(decimation_ > 1)
if(info)
{
rgb = util2d::decimate(rgb, decimation_);
model = model.scaled(1.0/double(decimation_));
info->odomPose = getPoseAtTimestamp(video_overlay_timestamp);
}
}
else
{
//UTimer t;
cv::Mat rgbRect;
cv::remap(rgb, rgbRect, fisheyeRectifyMapX_, fisheyeRectifyMapY_, cv::INTER_LINEAR, cv::BORDER_CONSTANT, 0);
rgb = rgbRect;
//LOGD("Rectification time=%fs", t.ticks());
}
// Querying the depth image's frame transformation based on the depth image's
// timestamp.
cv::Mat depth;
int rotation = static_cast<int>(getScreenRotation()) + 1; // remove 90deg camera rotation
if (rotation > 3) {
rotation -= 4;
}
// Calculate the relative pose from color camera frame at timestamp
// color_timestamp t1 and depth
// camera frame at depth_timestamp t0.
Transform colorToDepth;
TangoPoseData pose_color_image_t1_T_depth_image_t0;
if (TangoSupport_calculateRelativePose(
rgbStamp, colorCamera_?TANGO_COORDINATE_FRAME_CAMERA_COLOR:TANGO_COORDINATE_FRAME_CAMERA_FISHEYE, cloudStamp,
TANGO_COORDINATE_FRAME_CAMERA_DEPTH,
&pose_color_image_t1_T_depth_image_t0) == TANGO_SUCCESS)
{
colorToDepth = tangoPoseToTransform(&pose_color_image_t1_T_depth_image_t0);
}
else
{
LOGE(
"SynchronizationApplication: Could not find a valid relative pose at "
"time for color and "
" depth cameras.");
}
if(colorToDepth.getNormSquared() > 100000)
{
LOGE("Very large color to depth error detected (%s)! Ignoring this frame!", colorToDepth.prettyPrint().c_str());
colorToDepth.setNull();
}
cv::Mat scan;
if(!colorToDepth.isNull())
{
// The Color Camera frame at timestamp t0 with respect to Depth
// Camera frame at timestamp t1.
//LOGD("colorToDepth=%s", colorToDepth.prettyPrint().c_str());
LOGD("rgb=%dx%d cloud size=%d", rgb.cols, rgb.rows, (int)cloud.total());
int pixelsSet = 0;
int depthSizeDec = colorCamera_?8:1;
depth = cv::Mat::zeros(model_.imageHeight()/depthSizeDec, model_.imageWidth()/depthSizeDec, CV_16UC1); // mm
CameraModel depthModel = model_.scaled(1.0f/float(depthSizeDec));
std::vector<cv::Point3f> scanData(rawScanPublished_?cloud.total():0);
int oi=0;
int closePoints = 0;
float closeROI[4];
closeROI[0] = depth.cols/4;
closeROI[1] = 3*(depth.cols/4);
closeROI[2] = depth.rows/4;
closeROI[3] = 3*(depth.rows/4);
unsigned short minDepthValue=10000;
for(unsigned int i=0; i<cloud.total(); ++i)
TangoDoubleMatrixTransformData matrix_transform;
status = TangoSupport_getDoubleMatrixTransformAtTime(
video_overlay_timestamp,
TANGO_COORDINATE_FRAME_CAMERA_COLOR,
TANGO_COORDINATE_FRAME_START_OF_SERVICE,
TANGO_SUPPORT_ENGINE_OPENGL,
TANGO_SUPPORT_ENGINE_OPENGL,
static_cast<TangoSupportRotation>(rotation),
&matrix_transform);
if (matrix_transform.status_code == TANGO_POSE_VALID)
{
float * p = cloud.ptr<float>(0,i);
cv::Point3f pt = util3d::transformPoint(cv::Point3f(p[0], p[1], p[2]), colorToDepth);
// Get projection matrix
TangoCameraIntrinsics color_camera_intrinsics;
int ret = TangoSupport_getCameraIntrinsicsBasedOnDisplayRotation(
TANGO_CAMERA_COLOR,
static_cast<TangoSupportRotation>(rotation),
&color_camera_intrinsics);
if(pt.z > 0.0f && i%scanDownsampling == 0 && rawScanPublished_)
{
scanData.at(oi++) = pt;
}
if (ret == TANGO_SUCCESS) {
float image_width = static_cast<float>(color_camera_intrinsics.width);
float image_height = static_cast<float>(color_camera_intrinsics.height);
float fx = static_cast<float>(color_camera_intrinsics.fx);
float fy = static_cast<float>(color_camera_intrinsics.fy);
float cx = static_cast<float>(color_camera_intrinsics.cx);
float cy = static_cast<float>(color_camera_intrinsics.cy);
int pixel_x_l, pixel_y_l, pixel_x_h, pixel_y_h;
// get the coordinate on image plane.
pixel_x_l = static_cast<int>((depthModel.fx()) * (pt.x / pt.z) + depthModel.cx());
pixel_y_l = static_cast<int>((depthModel.fy()) * (pt.y / pt.z) + depthModel.cy());
pixel_x_h = static_cast<int>((depthModel.fx()) * (pt.x / pt.z) + depthModel.cx() + 0.5f);
pixel_y_h = static_cast<int>((depthModel.fy()) * (pt.y / pt.z) + depthModel.cy() + 0.5f);
unsigned short depth_value(pt.z * 1000.0f);
if(pixel_x_l>=closeROI[0] && pixel_x_l<closeROI[1] &&
pixel_y_l>closeROI[2] && pixel_y_l<closeROI[3] &&
depth_value < 600)
{
++closePoints;
if(depth_value < minDepthValue)
viewMatrix_ = glm::make_mat4(matrix_transform.matrix);
if(!getOriginOffset().isNull())
{
minDepthValue = depth_value;
viewMatrix_ = glm::inverse(rtabmap::glmFromTransform(rtabmap::opengl_world_T_rtabmap_world * getOriginOffset() *rtabmap::rtabmap_world_T_opengl_world)*glm::inverse(viewMatrix_));
}
}
bool pixelSet = false;
if(pixel_x_l>=0 && pixel_x_l<depth.cols &&
pixel_y_l>0 && pixel_y_l<depth.rows && // ignore first line
depth_value)
{
unsigned short & depthPixel = depth.at<unsigned short>(pixel_y_l, pixel_x_l);
if(depthPixel == 0 || depthPixel > depth_value)
projectionMatrix_ = tango_gl::Camera::ProjectionMatrixForCameraIntrinsics(
image_width, image_height, fx, fy, cx, cy, 0.3, 50);
switch(rotation)
{
depthPixel = depth_value;
pixelSet = true;
case ROTATION_90:
memcpy(transformed_uvs_, kTextureCoords90, 8*sizeof(float));
break;
case ROTATION_180:
memcpy(transformed_uvs_, kTextureCoords180, 8*sizeof(float));
break;
case ROTATION_270:
memcpy(transformed_uvs_, kTextureCoords270, 8*sizeof(float));
break;
case ROTATION_0:
default:
memcpy(transformed_uvs_, kTextureCoords0, 8*sizeof(float));
}
uvs_initialized_ = true;
}
if(pixel_x_h>=0 && pixel_x_h<depth.cols &&
pixel_y_h>0 && pixel_y_h<depth.rows && // ignore first line
depth_value)
else
{
unsigned short & depthPixel = depth.at<unsigned short>(pixel_y_h, pixel_x_h);
if(depthPixel == 0 || depthPixel > depth_value)
{
depthPixel = depth_value;
pixelSet = true;
}
UERROR("TangoSupport_getCameraIntrinsicsBasedOnDisplayRotation failed!");
}
if(pixelSet)
{
pixelsSet += 1;
}
}
if(closePoints > 100)
{
this->post(new CameraInfoEvent(0, "TooClose", ""));
}
if(oi)
{
scan = cv::Mat(1, oi, CV_32FC3, scanData.data()).clone();
}
//LOGD("pixels depth set= %d", pixelsSet);
}
else
{
LOGE("color to depth pose is null?!? (rgb stamp=%f) (depth stamp=%f)", rgbStamp, cloudStamp);
}
if(!rgb.empty() && !depth.empty())
{
depth = rtabmap::util2d::fillDepthHoles(depth, holeSize, maxDepthError);
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());
// 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();
if(rawScanPublished_)
{
data = SensorData(LaserScan::backwardCompatibility(scan, cloud.total()/scanDownsampling, 0, scanLocalTransform), rgb, depth, model, this->getNextSeqID(), rgbStamp);
}
else
{
data = SensorData(rgb, depth, model, this->getNextSeqID(), rgbStamp);
UERROR("TangoSupport_getDoubleMatrixTransformAtTime failed!");
}
info->odomPose = odom;
}
else
{
LOGE("Could not get depth and rgb images!?!");
UERROR("TangoService_updateTextureExternalOes failed!");
}
}
SensorData data;
if(dataReady_.acquireTry(1))
{
boost::mutex::scoped_lock lock(dataMutex_);
data = data_;
data_ = SensorData();
if(info)
{
info->odomPose = data.groundTruth();
data.setGroundTruth(Transform());
}
}
return data;

View File

@@ -71,8 +71,7 @@ private:
bool colorCamera_;
int decimation_;
bool rawScanPublished_;
cv::Mat cloud_;
double cloudStamp_;
SensorData data_;
cv::Mat tangoColor_;
int tangoColorType_;
double tangoColorStamp_;

View File

@@ -11,7 +11,9 @@
#include <rtabmap/core/ProgressState.h>
#include <rtabmap/utilite/ULogger.h>
#include <rtabmap/utilite/UEventsManager.h>
#ifdef __ANDROID__
#include <jni.h>
#endif
namespace rtabmap {
@@ -27,16 +29,29 @@ public:
class ProgressionStatus: public ProgressState, public UEventsHandler
{
public:
ProgressionStatus() : count_(0), max_(100), jvm_(0), rtabmap_(0)
ProgressionStatus() : count_(0), max_(100)
#ifdef __ANDROID__
, jvm_(0), rtabmap_(0)
#else
, swiftClassPtr_(0)
#endif
{
registerToEventsManager();
}
#ifdef __ANDROID__
void setJavaObjects(JavaVM * jvm, jobject rtabmap)
{
jvm_ = jvm;
rtabmap_ = rtabmap;
}
#else
void setSwiftCallback(void * classPtr, void(*callback)(void *, int, int))
{
swiftClassPtr_ = classPtr;
swiftCallback = callback;
}
#endif
void reset(int max)
{
@@ -82,6 +97,7 @@ protected:
count_ += ((ProgressEvent*)event)->count_;
// Call JAVA callback
bool success = false;
#ifdef __ANDROID__
if(jvm_ && rtabmap_)
{
JNIEnv *env = 0;
@@ -103,6 +119,16 @@ protected:
}
jvm_->DetachCurrentThread();
}
#else // APPLE
if(swiftClassPtr_)
{
std::function<void()> actualCallback = [&](){
swiftCallback(swiftClassPtr_, count_, max_);
};
actualCallback();
success = true;
}
#endif
if(!success)
{
UERROR("Failed to call rtabmap::updateProgressionCallback");
@@ -114,8 +140,13 @@ protected:
private:
int count_;
int max_;
#ifdef __ANDROID__
JavaVM *jvm_;
jobject rtabmap_;
#else
void * swiftClassPtr_;
void(*swiftCallback)(void *, int, int);
#endif
};
}

File diff suppressed because it is too large Load Diff

View File

@@ -28,7 +28,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef RTABMAP_APP_H_
#define RTABMAP_APP_H_
#ifdef __ANDROID__
#include <jni.h>
#endif
#include <memory>
#include <tango-gl/util.h>
@@ -49,16 +51,38 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
class RTABMapApp : public UEventsHandler {
public:
// Constructor and deconstructor.
#ifdef __ANDROID__
RTABMapApp(JNIEnv* env, jobject caller_activity);
#else // __APPLE__
RTABMapApp();
void setupSwiftCallbacks(void * classPtr,
void(*progressCallback)(void *, int, int),
void(*initCallback)(void *, int, const char*),
void(*statsUpdatedCallback)(void *,
int, int, int, int,
float,
int, int, int, int, int ,int,
float,
int,
float,
int,
float, float, float, float,
int, int,
float, float, float, float, float, float));
#endif
~RTABMapApp();
void setScreenRotation(int displayRotation, int cameraRotation);
int openDatabase(const std::string & databasePath, bool databaseInMemory, bool optimize, const std::string & databaseSource=std::string());
int openDatabase(const std::string & databasePath, bool databaseInMemory, bool optimize, bool clearDatabase);
bool isBuiltWith(int cameraDriver) const;
#ifdef __ANDROID__
bool startCamera(JNIEnv* env, jobject iBinder, jobject context, jobject activity, int driver);
#else // __APPLE__
bool startCamera();
#endif
// Allocate OpenGL resources for rendering, mainly for initializing the Scene.
void InitializeGLContent();
@@ -117,16 +141,19 @@ class RTABMapApp : public UEventsHandler {
void setMinCloudDepth(float value);
void setCloudDensityLevel(int value);
void setMeshAngleTolerance(float value);
void setMeshDecimationFactor(float value);
void setMeshTriangleSize(int value);
void setClusterRatio(float value);
void setMaxGainRadius(float value);
void setRenderingTextureDecimation(int value);
void setBackgroundColor(float gray);
void setDepthConfidence(int value);
int setMappingParameter(const std::string & key, const std::string & value);
void setGPS(const rtabmap::GPS & gps);
void addEnvSensor(int type, float value);
void save(const std::string & databasePath);
bool recover(const std::string & from, const std::string & to);
void cancelProcessing();
bool exportMesh(
float cloudVoxelSize,
@@ -150,20 +177,29 @@ class RTABMapApp : public UEventsHandler {
int postProcessing(int approach);
void postCameraPoseEvent(
float x, float y, float z, float qx, float qy, float qz, float qw);
float x, float y, float z, float qx, float qy, float qz, float qw, double stamp);
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);
rtabmap::Transform pose,
float rgb_fx, float rgb_fy, float rgb_cx, float rgb_cy,
float depth_fx, float depth_fy, float depth_cx, float depth_cy,
const rtabmap::Transform & rgbFrame,
const rtabmap::Transform & depthFrame,
double stamp,
double depthStamp,
const void * yPlane, const void * uPlane, const void * vPlane, int yPlaneLen, int rgbWidth, int rgbHeight, int rgbFormat,
const void * depth, int depthLen, int depthWidth, int depthHeight, int depthFormat,
const void * conf, int confLen, int confWidth, int confHeight, int confFormat,
const float * points, int pointsLen, int pointsChannels,
const rtabmap::Transform & viewMatrix, //view matrix
float p00, float p11, float p02, float p12, float p22, float p32, float p23, // projection matrix
float t0, float t1, float t2, float t3, float t4, float t5, float t6, float t7); // tex coord
protected:
virtual bool handleEvent(UEvent * event);
private:
int updateMeshDecimation(int width, int height);
rtabmap::ParametersMap getRtabmapParameters();
bool smoothMesh(int id, rtabmap::Mesh & mesh);
void gainCompensation(bool full = false);
@@ -193,10 +229,12 @@ class RTABMapApp : public UEventsHandler {
int cloudDensityLevel_;
int meshTrianglePix_;
float meshAngleToleranceDeg_;
float meshDecimationFactor_;
float clusterRatio_;
float maxGainRadius_;
int renderingTextureDecimation_;
float backgroundColor_;
int depthConfidence_;
rtabmap::ParametersMap mappingParameters_;
@@ -210,7 +248,6 @@ class RTABMapApp : public UEventsHandler {
bool bilateralFilteringOnNextRender_;
bool takeScreenshotOnNextRender_;
bool cameraJustInitialized_;
int meshDecimation_;
int totalPoints_;
int totalPolygons_;
int lastDrawnCloudsCount_;
@@ -229,10 +266,13 @@ class RTABMapApp : public UEventsHandler {
// main_scene_ includes all drawable object for visualizing Tango device's
// movement and point cloud.
Scene main_scene_;
UTimer fpsTime_;
std::list<rtabmap::RtabmapEvent*> rtabmapEvents_;
std::list<rtabmap::OdometryEvent> odomEvents_;
std::list<rtabmap::Transform> poseEvents_;
std::map<double, rtabmap::Transform> poseBuffer_;
rtabmap::Transform mapToOdom_;
@@ -251,6 +291,23 @@ class RTABMapApp : public UEventsHandler {
std::pair<rtabmap::RtabmapEventInit::Status, std::string> status_;
rtabmap::ProgressionStatus progressionStatus_;
#ifndef __ANDROID__
void * swiftClassPtr_;
void(*swiftInitCallback)(void *, int, const char *);
void(*swiftStatsUpdatedCallback)(void *,
int, int, int, int,
float,
int, int, int, int, int ,int,
float,
int,
float,
int,
float, float, float, float,
int, int,
float, float, float, float, float, float);
#endif
};
#endif // TANGO_POINT_CLOUD_POINT_CLOUD_APP_H_

View File

@@ -34,55 +34,173 @@ const std::string kVertexShader =
" v_TexCoord = a_TexCoord;\n"
"}\n";
const std::string kFragmentShader =
const std::string kFragmentShaderOES =
"#extension GL_OES_EGL_image_external : require\n"
"precision mediump float;\n"
"varying vec2 v_TexCoord;\n"
"uniform samplerExternalOES sTexture;\n"
"uniform bool uRedUnknown;\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, uRedUnknown?0.0:grey, uRedUnknown?0.0:grey, 0.5);\n"
"}\n";
const std::string kFragmentShaderBlendingOES =
"#extension GL_OES_EGL_image_external : require\n"
"precision mediump float;\n"
"varying vec2 v_TexCoord;\n"
"uniform samplerExternalOES sTexture;\n"
"uniform sampler2D uDepthTexture;\n"
"uniform vec2 uScreenScale;\n"
"uniform bool uRedUnknown;\n"
"void main() {\n"
" vec4 sample = texture2D(sTexture, v_TexCoord);\n"
" vec2 coord = uScreenScale * gl_FragCoord.xy;\n;"
" vec4 depthPacked = texture2D(uDepthTexture, coord);\n"
" float depth = dot(depthPacked, 1./vec4(1.,255.,65025.,16581375.));\n"
" if(depth > 0.0)\n"
" gl_FragColor = vec4(sample.r, sample.g, sample.b, 0.5);\n"
" else {\n"
" float grey = 0.21 * sample.r + 0.71 * sample.g + 0.07 * sample.b;\n"
" gl_FragColor = vec4(grey, uRedUnknown?0.0:grey, uRedUnknown?0.0:grey, 0.5);\n"
" }\n"
"}\n";
const std::string kFragmentShader =
"precision mediump float;\n"
"varying vec2 v_TexCoord;\n"
"uniform sampler2D sTexture;\n"
"uniform bool uRedUnknown;\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"
" gl_FragColor = vec4(grey, uRedUnknown?0.0:grey, uRedUnknown?0.0:grey, 0.5);\n"
"}\n";
const std::string kFragmentShaderBlending =
"precision mediump float;\n"
"varying vec2 v_TexCoord;\n"
"uniform sampler2D sTexture;\n"
"uniform sampler2D uDepthTexture;\n"
"uniform vec2 uScreenScale;\n"
"uniform bool uRedUnknown;\n"
"void main() {\n"
" vec4 sample = texture2D(sTexture, v_TexCoord);\n"
" vec2 coord = uScreenScale * gl_FragCoord.xy;\n;"
" vec4 depthPacked = texture2D(uDepthTexture, coord);\n"
" float depth = dot(depthPacked, 1./vec4(1.,255.,65025.,16581375.));\n"
" if(depth > 0.0)\n"
" gl_FragColor = vec4(sample.r, sample.g, sample.b, 0.5);\n"
" else {\n"
" float grey = 0.21 * sample.r + 0.71 * sample.g + 0.07 * sample.b;\n"
" gl_FragColor = vec4(grey, uRedUnknown?0.0:grey, uRedUnknown?0.0:grey, 0.5);\n"
" }\n"
"}\n";
/* To debug depth texture
const std::string kFragmentShader =
"precision mediump float;\n"
"varying vec2 v_TexCoord;\n"
"uniform sampler2D sTexture;\n"
"void main() {\n"
" float uNearZ = 0.2;\n"
" float uFarZ = 1000.0;\n"
" float depth = texture2D(sTexture, v_TexCoord).r;\n"
" float num = (2.0 * uNearZ * uFarZ);\n"
" float diff = (uFarZ - uNearZ);\n"
" float add = (uFarZ + uNearZ);\n"
" float ndcDepth = depth * 2.0 - 1.0;\n" // Back to NDC
" float linearDepth = num / (add - ndcDepth * diff);\n" // inverse projection matrix
" float grey = linearDepth/3.0;\n"
" gl_FragColor = vec4(grey, grey, grey, 0.5);\n"
"}\n";
*/
} // namespace
void BackgroundRenderer::InitializeGlContent(GLuint textureId)
{
texture_id_ = textureId;
std::vector<GLuint> BackgroundRenderer::shaderPrograms_;
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);
BackgroundRenderer::~BackgroundRenderer()
{
for(unsigned int i=0; i<shaderPrograms_.size(); ++i)
{
glDeleteShader(shaderPrograms_[i]);
}
shaderPrograms_.clear();
}
void BackgroundRenderer::Draw(const float * transformed_uvs) {
void BackgroundRenderer::InitializeGlContent(GLuint textureId, bool oes)
{
LOGI("textureId=%d", textureId);
texture_id_ = textureId;
#ifdef __ANDROID__
oes_ = oes;
#endif
if(shaderPrograms_.empty())
{
shaderPrograms_.resize(2,0);
shaderPrograms_[0] = tango_gl::util::CreateProgram(
kVertexShader.c_str(),
oes_?kFragmentShaderOES.c_str():kFragmentShader.c_str());
UASSERT(shaderPrograms_[0]!=0);
shaderPrograms_[1] = tango_gl::util::CreateProgram(
kVertexShader.c_str(),
oes_?kFragmentShaderBlendingOES.c_str():kFragmentShaderBlending.c_str());
UASSERT(shaderPrograms_[1]!=0);
}
}
void BackgroundRenderer::Draw(const float * transformed_uvs, const GLuint & depthTexture, int screenWidth, int screenHeight, bool redUnknown) {
static_assert(std::extent<decltype(BackgroundRenderer_kVertices)>::value == kNumVertices * 2, "Incorrect kVertices length");
glUseProgram(shader_program_);
GLuint program = shaderPrograms_[depthTexture>0?1:0];
glUseProgram(program);
glDepthMask(GL_FALSE);
glEnable (GL_BLEND);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture_id_);
#ifdef __ANDROID__
if(oes_)
glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture_id_);
else
#endif
glBindTexture(GL_TEXTURE_2D, texture_id_);
if(depthTexture>0)
{
// Texture activate unit 1
glActiveTexture(GL_TEXTURE1);
// Bind the texture to this unit.
glBindTexture(GL_TEXTURE_2D, depthTexture);
// Tell the texture uniform sampler to use this texture in the shader by binding to texture unit 1.
GLuint depth_texture_handle = glGetUniformLocation(program, "uDepthTexture");
glUniform1i(depth_texture_handle, 1);
GLuint screenScale_handle = glGetUniformLocation(program, "uScreenScale");
glUniform2f(screenScale_handle, 1.0f/(float)screenWidth, 1.0f/(float)screenHeight);
}
GLuint screenScale_handle = glGetUniformLocation(program, "uRedUnknown");
glUniform1i(screenScale_handle, redUnknown);
glVertexAttribPointer(attribute_vertices_, 2, GL_FLOAT, GL_FALSE, 0, BackgroundRenderer_kVertices);
glVertexAttribPointer(attribute_uvs_, 2, GL_FLOAT, GL_FALSE, 0, transformed_uvs);
GLuint attributeVertices = glGetAttribLocation(program, "a_Position");
GLuint attributeUvs = glGetAttribLocation(program, "a_TexCoord");
glEnableVertexAttribArray(attribute_vertices_);
glEnableVertexAttribArray(attribute_uvs_);
glVertexAttribPointer(attributeVertices, 2, GL_FLOAT, GL_FALSE, 0, BackgroundRenderer_kVertices);
glVertexAttribPointer(attributeUvs, 2, GL_FLOAT, GL_FALSE, 0, transformed_uvs?transformed_uvs:BackgroundRenderer_kTexCoord);
glEnableVertexAttribArray(attributeVertices);
glEnableVertexAttribArray(attributeUvs);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glDisableVertexAttribArray(attribute_vertices_);
glDisableVertexAttribArray(attribute_uvs_);
glDisableVertexAttribArray(attributeVertices);
glDisableVertexAttribArray(attributeUvs);
glUseProgram(0);
glDepthMask(GL_TRUE);

View File

@@ -17,8 +17,13 @@
#ifndef C_ARCORE_AUGMENTED_IMAGE_BACKGROUND_RENDERER_H_
#define C_ARCORE_AUGMENTED_IMAGE_BACKGROUND_RENDERER_H_
#ifdef __ANDROID__
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#else // __APPLE__
#include <OpenGLES/ES2/gl.h>
#include <OpenGLES/ES2/glext.h>
#endif
#include <cstdlib>
#include "util.h"
@@ -26,6 +31,16 @@
static const GLfloat BackgroundRenderer_kVertices[] = {
-1.0f, -1.0f, +1.0f, -1.0f, -1.0f, +1.0f, +1.0f, +1.0f,
};
static const GLfloat BackgroundRenderer_kTexCoord[] = {
1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
};
//android phone
//11 10 01 00 // portrait
//01 11 00 10 // left
//10 00 11 01 // right
//00 01 10 11 // down
// This class renders the passthrough camera image into the OpenGL frame.
class BackgroundRenderer {
@@ -36,23 +51,20 @@ public:
public:
BackgroundRenderer() = default;
~BackgroundRenderer() = default;
~BackgroundRenderer();
// Sets up OpenGL state. Must be called on the OpenGL thread and before any
// other methods below.
void InitializeGlContent(GLuint textureId);
void InitializeGlContent(GLuint textureId, bool oes);
// 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);
void Draw(const float * transformed_uvs, const GLuint & depthTexture, int screenWidth, int screenHeight, bool redUnknown);
private:
GLuint shader_program_;
private:
static std::vector<GLuint> shaderPrograms_;
GLuint texture_id_;
GLuint attribute_vertices_;
GLuint attribute_uvs_;
bool oes_ = false;
};
#endif // C_ARCORE_AUGMENTED_IMAGE_BACKGROUND_RENDERER_H_

View File

@@ -31,7 +31,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "rtabmap/utilite/ULogger.h"
#include "util.h"
#ifdef __ANDROID__
#include <GLES2/gl2.h>
#else //__APPLE__
#include <OpenGLES/ES2/gl.h>
#endif
GraphDrawable::GraphDrawable(
GLuint shaderProgram,

View File

@@ -28,8 +28,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef GRAPH_DRAWABLE_H_
#define GRAPH_DRAWABLE_H_
#ifdef __ANDROID__
#include <jni.h>
#endif
#include <tango-gl/util.h>
#include <vector>
#include <pcl/point_cloud.h>

View File

@@ -89,13 +89,13 @@ Java_com_introlab_rtabmap_RTABMapLib_setScreenRotation(
JNIEXPORT int JNICALL
Java_com_introlab_rtabmap_RTABMapLib_openDatabase(
JNIEnv* env, jclass, jlong native_application, jstring databasePath, bool databaseInMemory, bool optimize)
JNIEnv* env, jclass, jlong native_application, jstring databasePath, bool databaseInMemory, bool optimize, bool clearDatabase)
{
std::string databasePathC;
GetJStringContent(env,databasePath,databasePathC);
if(native_application)
{
return native(native_application)->openDatabase(databasePathC, databaseInMemory, optimize);
return native(native_application)->openDatabase(databasePathC, databaseInMemory, optimize, clearDatabase);
}
else
{
@@ -104,17 +104,17 @@ Java_com_introlab_rtabmap_RTABMapLib_openDatabase(
}
}
JNIEXPORT int JNICALL
Java_com_introlab_rtabmap_RTABMapLib_openDatabase2(
JNIEnv* env, jclass, jlong native_application, jstring databaseSource, jstring databasePath, bool databaseInMemory, bool optimize)
JNIEXPORT bool JNICALL
Java_com_introlab_rtabmap_RTABMapLib_recover(
JNIEnv* env, jclass, jlong native_application, jstring from, jstring to)
{
if(native_application)
{
std::string databasePathC;
GetJStringContent(env,databasePath,databasePathC);
std::string databaseSourceC;
GetJStringContent(env,databaseSource,databaseSourceC);
return native(native_application)->openDatabase(databasePathC, databaseInMemory, optimize, databaseSourceC);
std::string toC;
GetJStringContent(env,to,toC);
std::string fromC;
GetJStringContent(env,from,fromC);
return native(native_application)->recover(fromC, toC);
}
else
{
@@ -869,11 +869,11 @@ Java_com_introlab_rtabmap_RTABMapLib_postProcessing(
JNIEXPORT void JNICALL
Java_com_introlab_rtabmap_RTABMapLib_postCameraPoseEvent(
JNIEnv* env, jclass, jlong native_application,
float x, float y, float z, float qx, float qy, float qz, float qw)
float x, float y, float z, float qx, float qy, float qz, float qw, double stamp)
{
if(native_application)
{
native(native_application)->postCameraPoseEvent(x,y,z,qx,qy,qz,qw);
native(native_application)->postCameraPoseEvent(x,y,z,qx,qy,qz,qw, stamp);
}
else
{
@@ -886,26 +886,36 @@ JNIEXPORT void JNICALL
Java_com_introlab_rtabmap_RTABMapLib_postOdometryEvent(
JNIEnv* env, jclass, jlong native_application,
float x, float y, float z, float qx, float qy, float qz, float qw,
float fx, float fy, float cx, float cy,
float rgb_fx, float rgb_fy, float rgb_cx, float rgb_cy,
float rgbFrameX, float rgbFrameY, float rgbFrameZ, float rgbFrameQX, float rgbFrameQY, float rgbFrameQZ, float rgbFrameQW,
double stamp,
jobject yPlane, jobject uPlane, jobject vPlane, int yPlaneLen, int rgbWidth, int rgbHeight, int rgbFormat,
jobject depth, int depthLen, int depthWidth, int depthHeight, int depthFormat,
jobject points, int pointsLen)
jobject points, int pointsLen,
float vx, float vy, float vz, float vqx, float vqy, float vqz, float vqw, //view matrix
float p00, float p11, float p02, float p12, float p22, float p32, float p23, // projection matrix
float t0, float t1, float t2, float t3, float t4, float t5, float t6, float t7) // tex coord
{
if(native_application)
{
void *yPtr = env->GetDirectBufferAddress(yPlane);
void *uPtr = env->GetDirectBufferAddress(uPlane);
void *vPtr = env->GetDirectBufferAddress(vPlane);
void *depthPtr = env->GetDirectBufferAddress(depth);
float *pointsPtr = (float *)env->GetDirectBufferAddress(points);
native(native_application)->postOdometryEvent(
x,y,z,qx,qy,qz,qw,
fx,fy,cx,cy,
rtabmap::Transform(x,y,z,qx,qy,qz,qw),
rgb_fx,rgb_fy,rgb_cx,rgb_cy,
0,0,0,0,
rtabmap::Transform(rgbFrameX, rgbFrameY, rgbFrameZ, rgbFrameQX, rgbFrameQY, rgbFrameQZ, rgbFrameQW),
rtabmap::Transform(),
stamp,
0,
yPtr, uPtr, vPtr, yPlaneLen, rgbWidth, rgbHeight, rgbFormat,
depthPtr, depthLen, depthWidth, depthHeight, depthFormat,
pointsPtr, pointsLen);
0,0,0,0,0, //depth
0,0,0,0,0, //conf
pointsPtr, pointsLen, 4,
rtabmap::Transform(vx, vy, vz, vqx, vqy, vqz, vqw),
p00, p11, p02, p12, p22, p32, p23,
t0, t1, t2, t3, t4, t5, t6, t7);
}
else
{
@@ -914,6 +924,44 @@ Java_com_introlab_rtabmap_RTABMapLib_postOdometryEvent(
}
}
JNIEXPORT void JNICALL
Java_com_introlab_rtabmap_RTABMapLib_postOdometryEventDepth(
JNIEnv* env, jclass, jlong native_application,
float x, float y, float z, float qx, float qy, float qz, float qw,
float rgb_fx, float rgb_fy, float rgb_cx, float rgb_cy,
float depth_fx, float depth_fy, float depth_cx, float depth_cy,
float rgbFrameX, float rgbFrameY, float rgbFrameZ, float rgbFrameQX, float rgbFrameQY, float rgbFrameQZ, float rgbFrameQW,
float depthFrameX, float depthFrameY, float depthFrameZ, float depthFrameQX, float depthFrameQY, float depthFrameQZ, float depthFrameQW,
double rgbStamp,
double depthStamp,
jobject yPlane, jobject uPlane, jobject vPlane, int yPlaneLen, int rgbWidth, int rgbHeight, int rgbFormat,
jobject depth, int depthLen, int depthWidth, int depthHeight, int depthFormat,
jobject points, int pointsLen,
float vx, float vy, float vz, float vqx, float vqy, float vqz, float vqw, //view matrix
float p00, float p11, float p02, float p12, float p22, float p32, float p23, // projection matrix
float t0, float t1, float t2, float t3, float t4, float t5, float t6, float t7) // tex coord)
{
void *yPtr = env->GetDirectBufferAddress(yPlane);
void *uPtr = env->GetDirectBufferAddress(uPlane);
void *vPtr = env->GetDirectBufferAddress(vPlane);
void *depthPtr = env->GetDirectBufferAddress(depth);
float *pointsPtr = (float *)env->GetDirectBufferAddress(points);
native(native_application)->postOdometryEvent(
rtabmap::Transform(x,y,z,qx,qy,qz,qw),
rgb_fx,rgb_fy,rgb_cx,rgb_cy,
depth_fx,depth_fy,depth_cx,depth_cy,
rtabmap::Transform(rgbFrameX, rgbFrameY, rgbFrameZ, rgbFrameQX, rgbFrameQY, rgbFrameQZ, rgbFrameQW),
rtabmap::Transform(depthFrameX, depthFrameY, depthFrameZ, depthFrameQX, depthFrameQY, depthFrameQZ, depthFrameQW),
rgbStamp,
depthStamp,
yPtr, uPtr, vPtr, yPlaneLen, rgbWidth, rgbHeight, rgbFormat,
depthPtr, depthLen, depthWidth, depthHeight, depthFormat,
0,0,0,0,0, // conf
pointsPtr, pointsLen, 4,
rtabmap::Transform(vx, vy, vz, vqx, vqy, vqz, vqw),
p00, p11, p02, p12, p22, p32, p23,
t0, t1, t2, t3, t4, t5, t6, t7);
}
#ifdef __cplusplus

View File

@@ -35,7 +35,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "util.h"
#include "pcl/common/transforms.h"
#ifdef __ANDROID__
#include <GLES2/gl2.h>
#else // __APPLE__
#include <OpenGLES/ES2/gl.h>
#endif
#define LOW_DEC 2
#define LOWLOW_DEC 4
@@ -257,7 +261,7 @@ const std::string kTextureMeshBlendingFragmentShader =
" float linearFragz = num / (add - ndcFragz * diff);\n" // inverse projection matrix
" if(linearFragz > linearDepth + 0.05)\n"
" alpha=0.0;\n"
" gl_FragColor = vec4(textureColor.r * uGainR * vLightWeighting, textureColor.g * uGainG * vLightWeighting, textureColor.b * uGainB * vLightWeighting, alpha);\n"
" gl_FragColor = vec4(textureColor.r * uGainR * vLightWeighting, textureColor.g * uGainG * vLightWeighting, textureColor.b * uGainB * vLightWeighting, alpha);\n"
"}\n";
std::vector<GLuint> PointCloudDrawable::shaderPrograms_;
@@ -305,8 +309,8 @@ PointCloudDrawable::PointCloudDrawable(
float gainR,
float gainG,
float gainB) :
vertex_buffers_(0),
textures_(0),
vertex_buffer_(0),
texture_(0),
nPoints_(0),
pose_(rtabmap::Transform::getIdentity()),
poseGl_(1.0f),
@@ -316,14 +320,16 @@ PointCloudDrawable::PointCloudDrawable(
gainG_(gainG),
gainB_(gainB)
{
index_buffers_.resize(6, 0);
index_buffers_count_.resize(6, 0);
updateCloud(cloud, indices);
}
PointCloudDrawable::PointCloudDrawable(
const rtabmap::Mesh & mesh,
bool createWireframe) :
vertex_buffers_(0),
textures_(0),
vertex_buffer_(0),
texture_(0),
nPoints_(0),
pose_(rtabmap::Transform::getIdentity()),
poseGl_(1.0f),
@@ -333,64 +339,83 @@ PointCloudDrawable::PointCloudDrawable(
gainG_(1.0f),
gainB_(1.0f)
{
index_buffers_.resize(6, 0);
index_buffers_count_.resize(6, 0);
updateMesh(mesh, createWireframe);
}
PointCloudDrawable::~PointCloudDrawable()
{
LOGI("Freeing cloud buffer %d", vertex_buffers_);
if (vertex_buffers_)
LOGI("Freeing cloud buffer %d", vertex_buffer_);
if (vertex_buffer_)
{
glDeleteBuffers(1, &vertex_buffers_);
glDeleteBuffers(1, &vertex_buffer_);
tango_gl::util::CheckGlError("PointCloudDrawable::~PointCloudDrawable()");
vertex_buffers_ = 0;
vertex_buffer_ = 0;
}
if (textures_)
if (texture_)
{
glDeleteTextures(1, &textures_);
glDeleteTextures(1, &texture_);
tango_gl::util::CheckGlError("PointCloudDrawable::~PointCloudDrawable()");
textures_ = 0;
texture_ = 0;
}
for(size_t i=0; i<index_buffers_.size(); ++i)
{
if(index_buffers_[i])
{
glDeleteBuffers(1, &index_buffers_[i]);
index_buffers_[i] = 0;
tango_gl::util::CheckGlError("PointCloudDrawable::~PointCloudDrawable()");
}
}
}
void PointCloudDrawable::updatePolygons(const std::vector<pcl::Vertices> & polygons, const std::vector<pcl::Vertices> & polygonsLowRes, bool createWireframe)
{
LOGD("Update polygons");
polygons_.clear();
polygonLines_.clear();
polygonsLowRes_.clear();
polygonLinesLowRes_.clear();
for(int i=0; i<4; ++i)
{
if(index_buffers_[i])
{
glDeleteBuffers(1, &index_buffers_[i]);
index_buffers_[i] = 0;
tango_gl::util::CheckGlError("PointCloudDrawable::updatePolygons() clearing polygon buffers");
}
}
//LOGD("Update polygons");
if(polygons.size() && organizedToDenseIndices_.size())
{
unsigned int polygonSize = polygons[0].vertices.size();
size_t polygonSize = polygons[0].vertices.size();
UASSERT(polygonSize == 3);
polygons_.resize(polygons.size() * polygonSize);
std::vector<std::vector<GLuint> > indexes(4);
indexes[0].resize(polygons.size() * polygonSize);
if(createWireframe)
polygonLines_.resize(polygons_.size()*2);
indexes[2].resize(indexes[0].size()*2);
int oi = 0;
int li = 0;
for(unsigned int i=0; i<polygons.size(); ++i)
for(size_t i=0; i<polygons.size(); ++i)
{
UASSERT(polygons[i].vertices.size() == polygonSize);
for(unsigned int j=0; j<polygonSize; ++j)
{
polygons_[oi++] = organizedToDenseIndices_.at(polygons[i].vertices[j]);
indexes[0][oi++] = organizedToDenseIndices_.at(polygons[i].vertices[j]);
if(createWireframe)
{
polygonLines_[li++] = organizedToDenseIndices_.at(polygons[i].vertices[j]);
polygonLines_[li++] = organizedToDenseIndices_.at(polygons[i].vertices[(j+1) % polygonSize]);
indexes[2][li++] = organizedToDenseIndices_.at(polygons[i].vertices[j]);
indexes[2][li++] = organizedToDenseIndices_.at(polygons[i].vertices[(j+1) % polygonSize]);
}
}
}
if(polygonsLowRes.size())
{
unsigned int polygonSize = polygonsLowRes[0].vertices.size();
size_t polygonSize = polygonsLowRes[0].vertices.size();
UASSERT(polygonSize == 3);
polygonsLowRes_.resize(polygonsLowRes.size() * polygonSize);
indexes[1].resize(polygonsLowRes.size() * polygonSize);
if(createWireframe)
polygonLinesLowRes_.resize(polygonsLowRes_.size()*2);
indexes[3].resize(indexes[1].size()*2);
int oi = 0;
int li = 0;
for(unsigned int i=0; i<polygonsLowRes.size(); ++i)
@@ -398,15 +423,44 @@ void PointCloudDrawable::updatePolygons(const std::vector<pcl::Vertices> & polyg
UASSERT(polygonsLowRes[i].vertices.size() == polygonSize);
for(unsigned int j=0; j<polygonSize; ++j)
{
polygonsLowRes_[oi++] = organizedToDenseIndices_.at(polygonsLowRes[i].vertices[j]);
indexes[1][oi++] = organizedToDenseIndices_.at(polygonsLowRes[i].vertices[j]);
if(createWireframe)
{
polygonLinesLowRes_[li++] = organizedToDenseIndices_.at(polygonsLowRes[i].vertices[j]);
polygonLinesLowRes_[li++] = organizedToDenseIndices_.at(polygonsLowRes[i].vertices[(j+1)%polygonSize]);
indexes[3][li++] = organizedToDenseIndices_.at(polygonsLowRes[i].vertices[j]);
indexes[3][li++] = organizedToDenseIndices_.at(polygonsLowRes[i].vertices[(j+1)%polygonSize]);
}
}
}
}
// Generate index buffers
for(size_t i=0; i<indexes.size(); ++i)
{
if(!indexes[i].empty())
{
glGenBuffers(1, &index_buffers_[i]);
if(!index_buffers_[i])
{
LOGE("OpenGL: could not generate index buffer %ld\n", i);
return;
}
LOGD("Adding polygon index %ld size=%ld", i, indexes[i].size());
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffers_[i]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(uint32_t) * indexes[i].size(), indexes[i].data(), GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
index_buffers_count_[i] = (int)indexes[i].size();
GLint error = glGetError();
if(error != GL_NO_ERROR)
{
LOGE("OpenGL: Could not allocate indexes (0x%x)\n", error);
index_buffers_[i] = 0;
return;
}
}
}
}
}
@@ -414,43 +468,51 @@ void PointCloudDrawable::updateCloud(const pcl::PointCloud<pcl::PointXYZRGB>::Pt
{
UASSERT(cloud.get() && !cloud->empty());
nPoints_ = 0;
polygons_.clear();
polygonsLowRes_.clear();
verticesLowRes_.clear();
verticesLowLowRes_.clear();
aabbMinModel_ = aabbMinWorld_ = pcl::PointXYZ(1000,1000,1000);
aabbMaxModel_ = aabbMaxWorld_ = pcl::PointXYZ(-1000,-1000,-1000);
if (vertex_buffers_)
if (vertex_buffer_)
{
glDeleteBuffers(1, &vertex_buffers_);
tango_gl::util::CheckGlError("PointCloudDrawable::~PointCloudDrawable()");
vertex_buffers_ = 0;
glDeleteBuffers(1, &vertex_buffer_);
tango_gl::util::CheckGlError("PointCloudDrawable::updateCloud() clear vertex buffer");
vertex_buffer_ = 0;
}
if (textures_)
if (texture_)
{
glDeleteTextures(1, &textures_);
tango_gl::util::CheckGlError("PointCloudDrawable::~PointCloudDrawable()");
textures_ = 0;
glDeleteTextures(1, &texture_);
tango_gl::util::CheckGlError("PointCloudDrawable::updateCloud() clear texture buffer");
texture_ = 0;
}
for(size_t i=0; i<index_buffers_.size(); ++i)
{
if(index_buffers_[i])
{
glDeleteBuffers(1, &index_buffers_[i]);
index_buffers_[i] = 0;
tango_gl::util::CheckGlError("PointCloudDrawable::updateCloud() clear index buffer");
}
}
glGenBuffers(1, &vertex_buffers_);
if(!vertex_buffers_)
glGenBuffers(1, &vertex_buffer_);
if(!vertex_buffer_)
{
LOGE("OpenGL: could not generate vertex buffers\n");
return;
}
LOGI("Creating cloud buffer %d", vertex_buffers_);
LOGI("Creating cloud buffer %d", vertex_buffer_);
std::vector<float> vertices;
int totalPoints = 0;
size_t totalPoints = 0;
std::vector<GLuint> verticesLowRes;
std::vector<GLuint> verticesLowLowRes;
if(indices.get() && indices->size())
{
totalPoints = indices->size();
vertices.resize(indices->size()*4);
verticesLowRes_.resize(cloud->isOrganized()?totalPoints:0);
verticesLowLowRes_.resize(cloud->isOrganized()?totalPoints:0);
verticesLowRes.resize(cloud->isOrganized()?totalPoints:0);
verticesLowLowRes.resize(cloud->isOrganized()?totalPoints:0);
int oi_low = 0;
int oi_lowlow = 0;
for(unsigned int i=0; i<indices->size(); ++i)
@@ -467,23 +529,23 @@ void PointCloudDrawable::updateCloud(const pcl::PointCloud<pcl::PointXYZRGB>::Pt
{
if(indices->at(i)%LOW_DEC == 0 && (indices->at(i)/cloud->width) % LOW_DEC == 0)
{
verticesLowRes_[oi_low++] = i;
verticesLowRes[oi_low++] = i;
}
if(indices->at(i)%LOWLOW_DEC == 0 && (indices->at(i)/cloud->width) % LOWLOW_DEC == 0)
{
verticesLowLowRes_[oi_lowlow++] = i;
verticesLowLowRes[oi_lowlow++] = i;
}
}
}
verticesLowRes_.resize(oi_low);
verticesLowLowRes_.resize(oi_lowlow);
verticesLowRes.resize(oi_low);
verticesLowLowRes.resize(oi_lowlow);
}
else
{
totalPoints = cloud->size();
vertices.resize(cloud->size()*4);
verticesLowRes_.resize(cloud->isOrganized()?totalPoints:0);
verticesLowLowRes_.resize(cloud->isOrganized()?totalPoints:0);
verticesLowRes.resize(cloud->isOrganized()?totalPoints:0);
verticesLowLowRes.resize(cloud->isOrganized()?totalPoints:0);
int oi_low = 0;
int oi_lowlow = 0;
for(unsigned int i=0; i<cloud->size(); ++i)
@@ -500,19 +562,19 @@ void PointCloudDrawable::updateCloud(const pcl::PointCloud<pcl::PointXYZRGB>::Pt
{
if(i%LOW_DEC == 0 && (i/cloud->width) % LOW_DEC == 0)
{
verticesLowRes_[oi_low++] = i;
verticesLowRes[oi_low++] = i;
}
if(i%LOWLOW_DEC == 0 && (i/cloud->width) % LOWLOW_DEC == 0)
{
verticesLowLowRes_[oi_lowlow++] = i;
verticesLowLowRes[oi_lowlow++] = i;
}
}
}
verticesLowRes_.resize(oi_low);
verticesLowLowRes_.resize(oi_lowlow);
verticesLowRes.resize(oi_low);
verticesLowLowRes.resize(oi_lowlow);
}
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffers_);
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * (int)vertices.size(), (const void *)vertices.data(), GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
@@ -520,11 +582,40 @@ void PointCloudDrawable::updateCloud(const pcl::PointCloud<pcl::PointXYZRGB>::Pt
if(error != GL_NO_ERROR)
{
LOGE("OpenGL: Could not allocate point cloud (0x%x)\n", error);
vertex_buffers_ = 0;
vertex_buffer_ = 0;
return;
}
// vertex index buffers
for(size_t i=4; i<5; ++i)
{
if((i==4 && !verticesLowRes.empty()) ||
(i==5 && !verticesLowLowRes.empty()))
{
glGenBuffers(1, &index_buffers_[i]);
if(!index_buffers_[i])
{
LOGE("OpenGL: could not generate index buffer %ld\n", i);
return;
}
index_buffers_count_[i] = i==4?(int)verticesLowRes.size():(int)verticesLowLowRes.size();
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffers_[i]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(uint32_t) * index_buffers_count_[i], i==4?verticesLowRes.data():verticesLowLowRes.data(), GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
nPoints_ = totalPoints;
GLint error = glGetError();
if(error != GL_NO_ERROR)
{
LOGE("OpenGL: Could not allocate indexes (0x%x)\n", error);
index_buffers_[i] = 0;
return;
}
}
}
nPoints_ = (int)totalPoints;
}
void PointCloudDrawable::updateMesh(const rtabmap::Mesh & mesh, bool createWireframe)
@@ -534,12 +625,22 @@ void PointCloudDrawable::updateMesh(const rtabmap::Mesh & mesh, bool createWiref
aabbMinModel_ = aabbMinWorld_ = pcl::PointXYZ(1000,1000,1000);
aabbMaxModel_ = aabbMaxWorld_ = pcl::PointXYZ(-1000,-1000,-1000);
if (vertex_buffers_)
if (vertex_buffer_)
{
glDeleteBuffers(1, &vertex_buffers_);
tango_gl::util::CheckGlError("PointCloudDrawable::~PointCloudDrawable()");
vertex_buffers_ = 0;
glDeleteBuffers(1, &vertex_buffer_);
tango_gl::util::CheckGlError("PointCloudDrawable::updateMesh() clear vertex buffer");
vertex_buffer_ = 0;
}
for(size_t i=0; i<index_buffers_.size(); ++i)
{
if(index_buffers_[i])
{
glDeleteBuffers(1, &index_buffers_[i]);
index_buffers_[i] = 0;
tango_gl::util::CheckGlError("PointCloudDrawable::updateMesh() clear index buffer");
}
}
gainR_ = mesh.gains[0];
gainG_ = mesh.gains[1];
@@ -548,17 +649,17 @@ void PointCloudDrawable::updateMesh(const rtabmap::Mesh & mesh, bool createWiref
bool textureUpdate = false;
if(!mesh.texture.empty() && mesh.texture.type() == CV_8UC3)
{
if (textures_)
if (texture_)
{
glDeleteTextures(1, &textures_);
tango_gl::util::CheckGlError("PointCloudDrawable::~PointCloudDrawable()");
textures_ = 0;
glDeleteTextures(1, &texture_);
tango_gl::util::CheckGlError("PointCloudDrawable::updateMesh() clear texture buffer");
texture_ = 0;
}
textureUpdate = true;
}
glGenBuffers(1, &vertex_buffers_);
if(!vertex_buffers_)
glGenBuffers(1, &vertex_buffer_);
if(!vertex_buffer_)
{
LOGE("OpenGL: could not generate vertex buffers\n");
return;
@@ -566,10 +667,10 @@ void PointCloudDrawable::updateMesh(const rtabmap::Mesh & mesh, bool createWiref
if(textureUpdate)
{
glGenTextures(1, &textures_);
if(!textures_)
glGenTextures(1, &texture_);
if(!texture_)
{
vertex_buffers_ = 0;
vertex_buffer_ = 0;
LOGE("OpenGL: could not generate texture buffers\n");
return;
}
@@ -580,18 +681,20 @@ void PointCloudDrawable::updateMesh(const rtabmap::Mesh & mesh, bool createWiref
int totalPoints = 0;
std::vector<pcl::Vertices> polygons = mesh.polygons;
std::vector<pcl::Vertices> polygonsLowRes;
hasNormals_ = mesh.normals.get() && mesh.normals->size() == mesh.cloud->size();
hasNormals_ = mesh.normals.get() && mesh.normals->size() == mesh.cloud->size();
UASSERT(!hasNormals_ || mesh.cloud->size() == mesh.normals->size());
if(mesh.cloud->isOrganized()) // assume organized mesh
{
polygonsLowRes = mesh.polygonsLowRes; // only in organized we keep the low res
organizedToDenseIndices_ = std::vector<unsigned int>(mesh.cloud->width*mesh.cloud->height, -1);
totalPoints = mesh.indices->size();
verticesLowRes_.resize(totalPoints);
verticesLowLowRes_.resize(totalPoints);
totalPoints = (int)mesh.indices->size();
std::vector<GLuint> verticesLowRes;
std::vector<GLuint> verticesLowLowRes;
verticesLowRes.resize(totalPoints);
verticesLowLowRes.resize(totalPoints);
int oi_low = 0;
int oi_lowlow = 0;
if(textures_ && polygons.size())
if(texture_ && polygons.size())
{
int items = hasNormals_?9:6;
vertices = std::vector<float>(mesh.indices->size()*items);
@@ -624,11 +727,11 @@ void PointCloudDrawable::updateMesh(const rtabmap::Mesh & mesh, bool createWiref
if(mesh.indices->at(i)%LOW_DEC == 0 && (mesh.indices->at(i)/mesh.cloud->width) % LOW_DEC == 0)
{
verticesLowRes_[oi_low++] = i;
verticesLowRes[oi_low++] = i;
}
if(mesh.indices->at(i)%LOWLOW_DEC == 0 && (mesh.indices->at(i)/mesh.cloud->width) % LOWLOW_DEC == 0)
{
verticesLowLowRes_[oi_lowlow++] = i;
verticesLowLowRes[oi_lowlow++] = i;
}
}
}
@@ -659,20 +762,48 @@ void PointCloudDrawable::updateMesh(const rtabmap::Mesh & mesh, bool createWiref
if(mesh.indices->at(i)%LOW_DEC == 0 && (mesh.indices->at(i)/mesh.cloud->width) % LOW_DEC == 0)
{
verticesLowRes_[oi_low++] = i;
verticesLowRes[oi_low++] = i;
}
if(mesh.indices->at(i)%LOWLOW_DEC == 0 && (mesh.indices->at(i)/mesh.cloud->width) % LOWLOW_DEC == 0)
{
verticesLowLowRes_[oi_lowlow++] = i;
verticesLowLowRes[oi_lowlow++] = i;
}
}
}
verticesLowRes_.resize(oi_low);
verticesLowLowRes_.resize(oi_lowlow);
verticesLowRes.resize(oi_low);
verticesLowLowRes.resize(oi_lowlow);
// vertex index buffers
for(size_t i=4; i<5; ++i)
{
if((i==4 && !verticesLowRes.empty()) ||
(i==5 && !verticesLowLowRes.empty()))
{
glGenBuffers(1, &index_buffers_[i]);
if(!index_buffers_[i])
{
LOGE("OpenGL: could not generate index buffer %ld\n", i);
return;
}
index_buffers_count_[i] = i==4?(int)verticesLowRes.size():(int)verticesLowLowRes.size();
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffers_[i]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(uint32_t) * index_buffers_count_[i], i==4?verticesLowRes.data():verticesLowLowRes.data(), GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
GLint error = glGetError();
if(error != GL_NO_ERROR)
{
LOGE("OpenGL: Could not allocate indexes (0x%x)\n", error);
index_buffers_[i] = 0;
return;
}
}
}
}
else // assume dense mesh with texCoords set to polygons
{
if(textures_ && polygons.size() && mesh.normals->size())
if(texture_ && polygons.size())
{
//LOGD("Dense mesh with texture (%d texCoords %d points %d polygons %dx%d)",
// (int)mesh.texCoords.size(), (int)mesh.cloud->size(), (int)mesh.polygons.size(), texture.cols, texture.rows);
@@ -681,14 +812,14 @@ void PointCloudDrawable::updateMesh(const rtabmap::Mesh & mesh, bool createWiref
// tex_coordinates should be linked to points, not
// polygon vertices. Points linked to multiple different texCoords (different textures) should
// be duplicated.
totalPoints = mesh.texCoords.size();
vertices = std::vector<float>(mesh.texCoords.size()*9);
totalPoints = (int)mesh.texCoords.size();
int items = hasNormals_?9:6;
vertices = std::vector<float>(mesh.texCoords.size()*items);
organizedToDenseIndices_ = std::vector<unsigned int>(totalPoints, -1);
UASSERT_MSG(mesh.texCoords.size() == polygons[0].vertices.size()*polygons.size(),
uFormat("%d vs %d x %d", (int)mesh.texCoords.size(), (int)polygons[0].vertices.size(), (int)polygons.size()).c_str());
int items = hasNormals_?9:6;
unsigned int oi=0;
for(unsigned int i=0; i<polygons.size(); ++i)
{
@@ -739,7 +870,7 @@ void PointCloudDrawable::updateMesh(const rtabmap::Mesh & mesh, bool createWiref
}
else
{
totalPoints = mesh.cloud->size();
totalPoints = (int)mesh.cloud->size();
//LOGD("Dense mesh");
int items = hasNormals_?7:4;
organizedToDenseIndices_ = std::vector<unsigned int>(totalPoints, -1);
@@ -767,7 +898,7 @@ void PointCloudDrawable::updateMesh(const rtabmap::Mesh & mesh, bool createWiref
}
}
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffers_);
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * (int)vertices.size(), (const void *)vertices.data(), GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
@@ -775,11 +906,11 @@ void PointCloudDrawable::updateMesh(const rtabmap::Mesh & mesh, bool createWiref
if(error != GL_NO_ERROR)
{
LOGE("OpenGL: Could not allocate point cloud (0x%x)\n", error);
vertex_buffers_ = 0;
vertex_buffer_ = 0;
return;
}
if(textures_ && textureUpdate)
if(texture_ && textureUpdate)
{
//GLint maxTextureSize = 0;
//glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);
@@ -789,13 +920,13 @@ void PointCloudDrawable::updateMesh(const rtabmap::Mesh & mesh, bool createWiref
//LOGW("maxTextureUnits=%d", maxTextureUnits);
// gen texture from image
glBindTexture(GL_TEXTURE_2D, textures_);
glBindTexture(GL_TEXTURE_2D, texture_);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
cv::Mat rgbImage;
cv::cvtColor(mesh.texture, rgbImage, CV_BGR2RGBA);
cv::cvtColor(mesh.texture, rgbImage, cv::COLOR_BGR2RGBA);
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
//glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
@@ -807,20 +938,17 @@ void PointCloudDrawable::updateMesh(const rtabmap::Mesh & mesh, bool createWiref
if(error != GL_NO_ERROR)
{
LOGE("OpenGL: Could not allocate texture (0x%x)\n", error);
textures_ = 0;
texture_ = 0;
glDeleteBuffers(1, &vertex_buffers_);
vertex_buffers_ = 0;
glDeleteBuffers(1, &vertex_buffer_);
vertex_buffer_ = 0;
return;
}
}
nPoints_ = totalPoints;
if(polygons_.size() != polygons.size())
{
updatePolygons(polygons, polygonsLowRes, createWireframe);
}
updatePolygons(polygons, polygonsLowRes, createWireframe);
if(!pose_.isNull())
{
@@ -882,14 +1010,14 @@ void PointCloudDrawable::Render(
bool packDepthToColorChannel,
bool wireFrame) const
{
if(vertex_buffers_ && nPoints_ && visible_ && !shaderPrograms_.empty())
if(vertex_buffer_ && nPoints_ && visible_ && !shaderPrograms_.empty())
{
if(packDepthToColorChannel || !hasNormals_)
{
lighting = false;
}
if(packDepthToColorChannel || !(meshRendering && textureRendering && textures_))
if(packDepthToColorChannel || !(meshRendering && textureRendering && texture_))
{
textureRendering = false;
}
@@ -992,7 +1120,7 @@ void PointCloudDrawable::Render(
// Texture activate unit 0
glActiveTexture(GL_TEXTURE0);
// Bind the texture to this unit.
glBindTexture(GL_TEXTURE_2D, textures_);
glBindTexture(GL_TEXTURE_2D, texture_);
// Tell the texture uniform sampler to use this texture in the shader by binding to texture unit 0.
GLuint texture_handle = glGetUniformLocation(program, "uTexture");
glUniform1i(texture_handle, 0);
@@ -1008,8 +1136,8 @@ void PointCloudDrawable::Render(
}
tango_gl::util::CheckGlError("Pointcloud::Render() common");
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffers_);
if(textures_)
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_);
if(texture_)
{
glVertexAttribPointer(attribute_vertex, 3, GL_FLOAT, GL_FALSE, (hasNormals_?9:6)*sizeof(GLfloat), 0);
if(textureRendering)
@@ -1040,53 +1168,49 @@ void PointCloudDrawable::Render(
tango_gl::util::CheckGlError("Pointcloud::Render() set attribute pointer");
UTimer drawTime;
if(textureRendering)
if((textureRendering || meshRendering) && index_buffers_[0])
{
if(distanceToCameraSqr<16.0f || polygonsLowRes_.empty())
float dist = meshRendering?50.0f:16.0f;
if(distanceToCameraSqr<dist || index_buffers_[1]==0)
{
wireFrame = wireFrame && polygonLines_.size();
wireFrame = wireFrame && index_buffers_[2];
if(wireFrame)
glDrawElements(GL_LINES, polygonLines_.size(), GL_UNSIGNED_INT, polygonLines_.data());
{
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffers_[2]);
glDrawElements(GL_LINES, index_buffers_count_[2], GL_UNSIGNED_INT, 0);
}
else
glDrawElements(GL_TRIANGLES, polygons_.size(), GL_UNSIGNED_INT, polygons_.data());
{
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffers_[0]);
glDrawElements(GL_TRIANGLES, index_buffers_count_[0], GL_UNSIGNED_INT, 0);
}
}
else
{
wireFrame = wireFrame && polygonLinesLowRes_.size();
wireFrame = wireFrame && index_buffers_[3];
if(wireFrame)
glDrawElements(GL_LINES, polygonLinesLowRes_.size(), GL_UNSIGNED_INT, polygonLinesLowRes_.data());
{
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffers_[3]);
glDrawElements(GL_LINES, index_buffers_count_[3], GL_UNSIGNED_INT, 0);
}
else
glDrawElements(GL_TRIANGLES, polygonsLowRes_.size(), GL_UNSIGNED_INT, polygonsLowRes_.data());
{
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffers_[1]);
glDrawElements(GL_TRIANGLES, index_buffers_count_[1], GL_UNSIGNED_INT, 0);
}
}
}
else if(meshRendering && polygons_.size())
else if(index_buffers_[4])
{
if(distanceToCameraSqr<50.0f || polygonsLowRes_.empty())
if(distanceToCameraSqr>600.0f && index_buffers_[5])
{
wireFrame = wireFrame && polygonLines_.size();
if(wireFrame)
glDrawElements(GL_LINES, polygonLines_.size(), GL_UNSIGNED_INT, polygonLines_.data());
else
glDrawElements(GL_TRIANGLES, polygons_.size(), GL_UNSIGNED_INT, polygons_.data());
}
else
{
wireFrame = wireFrame && polygonLinesLowRes_.size();
if(wireFrame)
glDrawElements(GL_LINES, polygonLinesLowRes_.size(), GL_UNSIGNED_INT, polygonLinesLowRes_.data());
else
glDrawElements(GL_TRIANGLES, polygonsLowRes_.size(), GL_UNSIGNED_INT, polygonsLowRes_.data());
}
}
else if(!verticesLowRes_.empty())
{
if(distanceToCameraSqr>600.0f)
{
glDrawElements(GL_POINTS, verticesLowLowRes_.size(), GL_UNSIGNED_INT, verticesLowLowRes_.data());
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffers_[5]);
glDrawElements(GL_POINTS, index_buffers_count_[5], GL_UNSIGNED_INT, 0);
}
else if(distanceToCameraSqr>150.0f)
{
glDrawElements(GL_POINTS, verticesLowRes_.size(), GL_UNSIGNED_INT, verticesLowRes_.data());
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffers_[4]);
glDrawElements(GL_POINTS, index_buffers_count_[4], GL_UNSIGNED_INT, 0);
}
else
{
@@ -1102,6 +1226,7 @@ void PointCloudDrawable::Render(
glDisableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glUseProgram(0);
tango_gl::util::CheckGlError("Pointcloud::Render() cleaning");

View File

@@ -28,7 +28,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef TANGO_POINT_CLOUD_POINT_CLOUD_DRAWABLE_H_
#define TANGO_POINT_CLOUD_POINT_CLOUD_DRAWABLE_H_
#ifdef __ANDROID__
#include <jni.h>
#endif
#include <tango-gl/util.h>
#include <vector>
@@ -68,8 +70,8 @@ private:
rtabmap::Transform getPose() const {return pose_;}
const glm::mat4 & getPoseGl() const {return poseGl_;}
bool isVisible() const {return visible_;}
bool hasMesh() const {return polygons_.size()!=0;}
bool hasTexture() const {return textures_ != 0;}
bool hasMesh() const {return index_buffers_[0] != 0;}
bool hasTexture() const {return texture_ != 0;}
float getMinHeight() const {return minHeight_;}
const pcl::PointXYZ & aabbMinModel() const {return aabbMinModel_;}
const pcl::PointXYZ & aabbMaxModel() const {return aabbMaxModel_;}
@@ -113,14 +115,10 @@ private:
private:
// Vertex buffer of the point cloud geometry.
GLuint vertex_buffers_;
GLuint textures_;
std::vector<GLuint> polygons_;
std::vector<GLuint> polygonsLowRes_;
std::vector<GLuint> polygonLines_;
std::vector<GLuint> polygonLinesLowRes_;
std::vector<GLuint> verticesLowRes_;
std::vector<GLuint> verticesLowLowRes_;
GLuint vertex_buffer_;
GLuint texture_;
std::vector<GLuint> index_buffers_;
std::vector<int> index_buffers_count_;
int nPoints_;
rtabmap::Transform pose_;
glm::mat4 poseGl_;

View File

@@ -88,7 +88,7 @@ Scene::Scene() :
mapRendering_(true),
meshRendering_(true),
meshRenderingTexture_(true),
pointSize_(5.0f),
pointSize_(10.0f),
boundingBoxRendering_(false),
lighting_(false),
backfaceCulling_(true),
@@ -98,11 +98,11 @@ Scene::Scene() :
b_(0.0f),
fboId_(0),
rboId_(0),
depthTexture_(0),
screenWidth_(0),
screenHeight_(0),
doubleTapOn_(false)
{
depthTexture_ = 0;
gesture_camera_ = new tango_gl::GestureCamera();
gesture_camera_->SetCameraType(
tango_gl::GestureCamera::kThirdPersonFollow);
@@ -179,8 +179,8 @@ void Scene::DeleteResources() {
fboId_ = 0;
glDeleteRenderbuffers(1, &rboId_);
rboId_ = 0;
glDeleteTextures(1, &depthTexture_);
depthTexture_ = 0;
glDeleteTextures(1, &depthTexture_);
depthTexture_ = 0;
}
clear();
@@ -220,11 +220,14 @@ void Scene::SetupViewPort(int w, int h) {
if (h == 0) {
LOGE("Setup graphic height not valid");
}
UASSERT(gesture_camera_ != 0);
gesture_camera_->SetWindowSize(static_cast<float>(w), static_cast<float>(h));
glViewport(0, 0, w, h);
if(screenWidth_ != w || screenHeight_ != h || fboId_ == 0)
{
UINFO("Setup viewport OpenGL: %dx%d", w, h);
if(fboId_>0)
{
glDeleteFramebuffers(1, &fboId_);
@@ -232,9 +235,12 @@ void Scene::SetupViewPort(int w, int h) {
glDeleteRenderbuffers(1, &rboId_);
rboId_ = 0;
glDeleteTextures(1, &depthTexture_);
depthTexture_ = 0;
depthTexture_ = 0;
}
GLint originid = 0;
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &originid);
// regenerate fbo texture
// create a framebuffer object, you need to delete them when program exits.
glGenFramebuffers(1, &fboId_);
@@ -249,7 +255,7 @@ void Scene::SetupViewPort(int w, int h) {
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glBindTexture(GL_TEXTURE_2D, 0);
glGenRenderbuffers(1, &rboId_);
glBindRenderbuffer(GL_RENDERBUFFER, rboId_);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, w, h);
@@ -260,12 +266,9 @@ void Scene::SetupViewPort(int w, int h) {
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rboId_);
GLuint status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if ( status != GL_FRAMEBUFFER_COMPLETE)
{
LOGE("Frame buffer cannot be generated! Status: %in", status);
}
glBindFramebuffer(GL_FRAMEBUFFER,0);
}
UASSERT ( status == GL_FRAMEBUFFER_COMPLETE);
glBindFramebuffer(GL_FRAMEBUFFER, originid);
}
screenWidth_ = w;
screenHeight_ = h;
}
@@ -338,8 +341,9 @@ std::vector<glm::vec4> computeFrustumPlanes(const glm::mat4 & mat, bool normaliz
/**
* Tells whether or not b is intersecting f.
* http://www.txutxi.com/?p=584
* @param f Viewing frustum.
* @param b An axis aligned bounding box.
* @param planes Viewing frustum.
* @param boxMin The axis aligned bounding box min.
* @param boxMax The axis aligned bounding box max.
* @return True if b intersects f, false otherwise.
*/
bool intersectFrustumAABB(
@@ -378,7 +382,8 @@ bool intersectFrustumAABB(
}
//Should only be called in OpenGL thread!
int Scene::Render(const float * uvsTransformed, glm::mat4 arViewMatrix, glm::mat4 arProjectionMatrix, const rtabmap::Mesh & occlusionMesh) {
int Scene::Render(const float * uvsTransformed, glm::mat4 arViewMatrix, glm::mat4 arProjectionMatrix, const rtabmap::Mesh & occlusionMesh, bool mapping)
{
UASSERT(gesture_camera_ != 0);
if(currentPose_ == 0)
@@ -411,13 +416,21 @@ int Scene::Render(const float * uvsTransformed, glm::mat4 arViewMatrix, glm::mat
bool renderBackgroundCamera =
background_renderer_ &&
gesture_camera_->GetCameraType() == tango_gl::GestureCamera::kFirstPerson &&
!rtabmap::glmToTransform(arProjectionMatrix).isNull() &&
uvsTransformed;
gesture_camera_->GetCameraType() == tango_gl::GestureCamera::kFirstPerson &&
!rtabmap::glmToTransform(arProjectionMatrix).isNull() &&
uvsTransformed;
if(renderBackgroundCamera)
{
projectionMatrix = arProjectionMatrix;
viewMatrix = arViewMatrix;
if(projectionMatrix[0][0] > arProjectionMatrix[0][0]-0.3)
{
projectionMatrix = arProjectionMatrix;
viewMatrix = arViewMatrix;
}
else
{
renderBackgroundCamera = false;
}
}
rtabmap::Transform openglCamera = GetOpenGLCameraPose();//*rtabmap::Transform(0.0f, 0.0f, 3.0f, 0.0f, 0.0f, 0.0f);
@@ -467,34 +480,45 @@ int Scene::Render(const float * uvsTransformed, glm::mat4 arViewMatrix, glm::mat
glDisable(GL_CULL_FACE);
}
UTimer timer;
bool onlineBlending =
(!meshRendering_ &&
occlusionMesh.cloud.get() &&
occlusionMesh.cloud->size()) ||
(blending_ &&
gesture_camera_->GetCameraType()!=tango_gl::GestureCamera::kTopOrtho &&
mapRendering_ && meshRendering_ &&
(cloudsToDraw.size() > 1 || (renderBackgroundCamera && wireFrame_)));
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_)
{
GLint originid = 0;
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &originid);
// set the rendering destination to FBO
glBindFramebuffer(GL_FRAMEBUFFER, fboId_);
glClearColor(0, 0, 0, 0);
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
if(renderBackgroundCamera)
{
PointCloudDrawable drawable(occlusionMesh);
drawable.Render(projectionMatrix, viewMatrix, true, pointSize_, false, false, 999.0f, 0, 0, 0, 0, 0, true);
}
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, 0, 0, 0, 0, 0, true);
}
}
// Draw scene
for(std::vector<PointCloudDrawable*>::const_iterator iter=cloudsToDraw.begin(); iter!=cloudsToDraw.end(); ++iter)
{
Eigen::Vector3f cloudToCamera(
(*iter)->getPose().x() - openglCamera.x(),
(*iter)->getPose().y() - openglCamera.y(),
(*iter)->getPose().z() - openglCamera.z());
float distanceToCameraSqr = cloudToCamera[0]*cloudToCamera[0] + cloudToCamera[1]*cloudToCamera[1] + cloudToCamera[2]*cloudToCamera[2];
(*iter)->Render(projectionMatrix, viewMatrix, meshRendering_, pointSize_, false, false, distanceToCameraSqr, 0, 0, 0, 0, 0, true);
}
if(!meshRendering_ && occlusionMesh.cloud.get() && occlusionMesh.cloud->size())
{
PointCloudDrawable drawable(occlusionMesh);
drawable.Render(projectionMatrix, viewMatrix, true, pointSize_, false, false, 0, 0, 0, 0, 0, 0, true);
}
// back to normal window-system-provided framebuffer
glBindFramebuffer(GL_FRAMEBUFFER, 0); // unbind
glBindFramebuffer(GL_FRAMEBUFFER, originid); // unbind
}
if(doubleTapOn_ && gesture_camera_->GetCameraType() != tango_gl::GestureCamera::kFirstPerson)
@@ -502,10 +526,16 @@ int Scene::Render(const float * uvsTransformed, glm::mat4 arViewMatrix, glm::mat
glClearColor(0, 0, 0, 0);
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
// FIXME: we could use the depthTexture if already computed!
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_*10.0f, false, false, 999.0f, 0, 0, 0, 0, 0, true);
Eigen::Vector3f cloudToCamera(
(*iter)->getPose().x() - openglCamera.x(),
(*iter)->getPose().y() - openglCamera.y(),
(*iter)->getPose().z() - openglCamera.z());
float distanceToCameraSqr = cloudToCamera[0]*cloudToCamera[0] + cloudToCamera[1]*cloudToCamera[1] + cloudToCamera[2]*cloudToCamera[2];
(*iter)->Render(projectionMatrix, viewMatrix, meshRendering_, pointSize_*10.0f, false, false, distanceToCameraSqr, 0, 0, 0, 0, 0, true);
}
GLubyte zValue[4];
@@ -524,15 +554,15 @@ int Scene::Render(const float * uvsTransformed, glm::mat4 arViewMatrix, glm::mat
glClearColor(r_, g_, b_, 1.0f);
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
if(renderBackgroundCamera && (!onlineBlending || !meshRendering_))
{
background_renderer_->Draw(uvsTransformed, 0, screenWidth_, screenHeight_, false);
if(renderBackgroundCamera)
{
background_renderer_->Draw(uvsTransformed);
//To debug occlusion image:
//PointCloudDrawable drawable(occlusionMesh);
//drawable.Render(projectionMatrix, viewMatrix, true, pointSize_, false, false, 999.0f);
}
//To debug occlusion image:
//PointCloudDrawable drawable(occlusionMesh);
//drawable.Render(projectionMatrix, viewMatrix, true, pointSize_, false, false, 999.0f);
}
if(!currentPose_->isNull())
{
@@ -560,6 +590,10 @@ int Scene::Render(const float * uvsTransformed, glm::mat4 arViewMatrix, glm::mat
{
trace_->Render(projectionMatrix, viewMatrix);
}
else
{
trace_->ClearVertexArray();
}
}
if(gridVisible_ && !renderBackgroundCamera)
@@ -600,10 +634,15 @@ int Scene::Render(const float * uvsTransformed, glm::mat4 arViewMatrix, glm::mat
if(onlineBlending)
{
if(renderBackgroundCamera && meshRendering_)
{
background_renderer_->Draw(uvsTransformed, depthTexture_, screenWidth_, screenHeight_, mapping);
}
glDisable (GL_BLEND);
glDepthMask(GL_TRUE);
}
//draw markers on foreground
for(std::map<int, tango_gl::Axis*>::const_iterator iter=markers_.begin(); iter!=markers_.end(); ++iter)
{
@@ -680,18 +719,10 @@ void Scene::updateGraph(
const std::multimap<int, rtabmap::Link> & links)
{
LOGI("updateGraph");
if(graph_)
{
delete graph_;
graph_ = 0;
}
//create
if(graphVisible_)
{
UASSERT(graph_shader_program_ != 0);
graph_ = new GraphDrawable(graph_shader_program_, poses, links);
}
UASSERT(graph_shader_program_ != 0);
delete graph_;
graph_ = new GraphDrawable(graph_shader_program_, poses, links);
}
void Scene::setGraphVisible(bool visible)

View File

@@ -17,7 +17,9 @@
#ifndef TANGO_POINT_CLOUD_SCENE_H_
#define TANGO_POINT_CLOUD_SCENE_H_
#ifdef __ANDROID__
#include <jni.h>
#endif
#include <memory>
#include <set>
@@ -35,10 +37,10 @@
#include <rtabmap/core/Transform.h>
#include <rtabmap/core/Link.h>
#include <point_cloud_drawable.h>
#include <graph_drawable.h>
#include <bounding_box_drawable.h>
#include <background_renderer.h>
#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>
@@ -72,7 +74,7 @@ class Scene {
// frame's timestamp.
// @param: point_cloud_vertices, point cloud's vertices of the current point
// frame.
int Render(const float * uvsTransformed = 0, glm::mat4 arViewMatrix = glm::mat4(0), glm::mat4 arProjectionMatrix=glm::mat4(0), const rtabmap::Mesh & occlusionMesh=rtabmap::Mesh());
int Render(const float * uvsTransformed = 0, glm::mat4 arViewMatrix = glm::mat4(0), glm::mat4 arProjectionMatrix=glm::mat4(0), const rtabmap::Mesh & occlusionMesh=rtabmap::Mesh(), bool mapping=false);
// Set render camera's viewing angle, first person, third person or top down.
//
@@ -153,6 +155,7 @@ class Scene {
float getPointSize() const {return pointSize_;}
bool isLighting() const {return lighting_;}
bool isBackfaceCulling() const {return backfaceCulling_;}
bool isWireframe() const {return wireFrame_;}
BackgroundRenderer * background_renderer_;
@@ -205,7 +208,7 @@ class Scene {
float b_;
GLuint fboId_;
GLuint rboId_;
GLuint depthTexture_;
GLuint depthTexture_; // 0=objects+occlusion
GLsizei screenWidth_;
GLsizei screenHeight_;
bool doubleTapOn_;

View File

@@ -24,8 +24,8 @@ Camera::Camera() {
aspect_ratio_ = 4.0f / 3.0f;
width_ = 800.0f;
height_ = 600.0f;
near_clip_plane_ = 0.2f;
far_clip_plane_ = 1000.0f;
near_clip_plane_ = 0.5f;
far_clip_plane_ = 50.0f;
ortho_ = false;
orthoScale_ = 2.0f;
orthoCropFactor_ = -1.0f;

View File

@@ -43,9 +43,11 @@ const float kCamViewMaxDist = 100.f;
// FOV set up values.
// Third and top down camera's FOV is 65 degrees.
// First person camera's FOV is 45 degrees.
const float kHighFov = 65.0f;
// First person camera's FOV is 85 degrees.
const float kHighestFov = 120.0f;
const float kHighFov = 85.0f;
const float kLowFov = 65.0f;
const float kLowestFov = 40.0f;
}
namespace tango_gl {
@@ -111,7 +113,7 @@ void GestureCamera::OnTouchEvent(int touch_count, TouchEvent event, float x0,
if(camera_type_ == kFirstPerson)
{
this->SetFieldOfView(tango_gl::util::Clamp(cam_start_fov_ + dist * kZoomSpeed*10.0f, 45, 90));
this->SetFieldOfView(tango_gl::util::Clamp(cam_start_fov_ + dist * kZoomSpeed*10.0f, kLowestFov, kHighestFov));
}
else
{
@@ -179,8 +181,9 @@ void GestureCamera::SetCameraType(CameraType camera_index) {
camera_type_ = camera_index;
switch (camera_index) {
case kFirstPerson:
SetOrthoMode(false);
SetFieldOfView(kLowFov);
SetOrthoMode(false);
SetFieldOfView(kLowestFov);
SetNearFarClipPlanes(0.25, 25);
SetPosition(glm::vec3(0.0f, 0.0f, 0.0f));
SetRotation(glm::quat(1.0f, 0.0f, 0.0f, 0.0f));
cam_cur_dist_ = 0.0f;
@@ -193,11 +196,12 @@ void GestureCamera::SetCameraType(CameraType camera_index) {
break;
case kThirdPerson:
case kThirdPersonFollow:
SetOrthoMode(false);
SetFieldOfView(kHighFov);
SetOrthoMode(false);
SetFieldOfView(kLowFov);
SetNearFarClipPlanes(1, 50);
SetPosition(glm::vec3(0.0f, 0.0f, 0.0f));
SetRotation(glm::quat(1.0f, 0.0f, 0.0f, 0.0f));
cam_cur_dist_ = kThirdPersonFollow?kThirdPersonFollowCameraDist:kThirdPersonCameraDist;
cam_cur_dist_ = camera_index==kThirdPersonFollow?kThirdPersonFollowCameraDist:kThirdPersonCameraDist;
anchor_offset_ = glm::vec3(0.0f,0.0f,0.0f);
cam_cur_angle_.x = -M_PI / 12.0f;
cam_cur_angle_.y = kThirdPersonFollow?0:M_PI / 2.0f;
@@ -208,7 +212,8 @@ void GestureCamera::SetCameraType(CameraType camera_index) {
SetPosition(glm::vec3(0.0f, 0.0f, 0.0f));
SetRotation(glm::quat(1.0f, 0.0f, 0.0f, 0.0f));
SetOrthoMode(false);
SetFieldOfView(kHighFov);
SetFieldOfView(kLowFov);
SetNearFarClipPlanes(1, 50);
cam_cur_dist_ = kTopDownCameraDist;
anchor_offset_ = glm::vec3(0.0f,0.0f,0.0f);
cam_cur_angle_.x = -M_PI / 2.0f;
@@ -222,6 +227,8 @@ void GestureCamera::SetCameraType(CameraType camera_index) {
SetOrthoMode(true);
SetOrthoScale(kTopDownCameraDist);
SetOrthoCropFactor(-1.0f);
SetFieldOfView(kLowFov);
SetNearFarClipPlanes(1, 50);
cam_cur_dist_ = kTopDownCameraDist;
anchor_offset_ = glm::vec3(0.0f,0.0f,0.0f);
cam_cur_angle_.x = -M_PI / 2.0f;

View File

@@ -18,7 +18,10 @@
#define TANGO_GL_TEXTURE_H_
#include <errno.h>
#ifdef __ANDROID__
#include <png.h>
#endif
#include "tango-gl/util.h"
@@ -30,11 +33,15 @@ class Texture {
Texture& operator=(const Texture&) = delete;
~Texture();
#ifdef __ANDROID__
bool LoadFromPNG(const char* file_path);
#endif
GLuint GetTextureID() const;
private:
#ifdef __ANDROID__
png_uint_32 width_, height_;
#endif
int bit_depth_, color_type_;
char* byte_data_;
GLuint texture_id_;

View File

@@ -21,10 +21,16 @@
#define GL_VERTEX_PROGRAM_POINT_SIZE 0x8642
#include <stdlib.h>
#ifdef __ANDROID__
#include <jni.h>
#include <android/log.h>
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#else // __APPLE__
#include <OpenGLES/ES2/gl.h>
#include <OpenGLES/ES2/glext.h>
#include <syslog.h>
#endif
#include "glm/glm.hpp"
#include "glm/gtc/matrix_transform.hpp"
@@ -33,17 +39,28 @@
#include "glm/gtx/matrix_decompose.hpp"
#define LOG_TAG "rtabmap"
#ifdef DISABLE_LOG
#if defined(DISABLE_LOG)
#define LOGD(...) ;
#define LOGI(...) ;
#define LOGW(...) ;
#else
#ifdef __APPLE__
#define LOGD(...) fprintf(stderr, __VA_ARGS__); fprintf(stderr, "\n")
#define LOGI(...) fprintf(stderr, __VA_ARGS__); fprintf(stderr, "\n")
#define LOGW(...) fprintf(stderr, __VA_ARGS__); fprintf(stderr, "\n")
#else
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN,LOG_TAG,__VA_ARGS__)
#endif
#endif
#ifdef __APPLE__
#define LOGE(...) fprintf(stderr, __VA_ARGS__); fprintf(stderr, "\n")
#define LOGF(...) fprintf(stderr, __VA_ARGS__); fprintf(stderr, "\n")
#else
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
#define LOGF(...) __android_log_print(ANDROID_LOG_FATAL,LOG_TAG,__VA_ARGS__)
#endif
#ifndef M_PI
#define M_PI 3.1415926f

View File

@@ -57,7 +57,7 @@ Quad::Quad() {
Quad::~Quad() { glDeleteShader(shader_program_); }
void Quat::SetTextureId(GLuint texture_id) { texture_id_ = texture_id; }
void Quad::SetTextureId(GLuint texture_id) { texture_id_ = texture_id; }
void Quad::Render(const glm::mat4& projection_mat,
const glm::mat4& view_mat) const {

View File

@@ -34,11 +34,13 @@ static int RoundUpPowerOfTwo(int w) {
}
Texture::Texture(const char* file_path) {
#ifdef __ANDROID__
if (!LoadFromPNG(file_path)) {
LOGE("Texture initialing error");
}
#endif
}
#ifdef __ANDROID__
bool Texture::LoadFromPNG(const char* file_path) {
FILE* file = fopen(file_path, "rb");
@@ -94,7 +96,7 @@ bool Texture::LoadFromPNG(const char* file_path) {
return true;
}
#endif
GLuint Texture::GetTextureID() const { return texture_id_; }
Texture::~Texture() {

View File

@@ -28,8 +28,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef UTIL_H_
#define UTIL_H_
#include <android/log.h>
#include <rtabmap/utilite/UEventsHandler.h>
#include <rtabmap/utilite/ULogger.h>
#include <rtabmap/core/CameraModel.h>
@@ -46,8 +44,13 @@ class LogHandler : public UEventsHandler
public:
LogHandler()
{
ULogger::setLevel(ULogger::kDebug);
ULogger::setEventLevel(ULogger::kDebug);
#ifdef DISABLE_LOG
ULogger::setLevel(ULogger::kWarning);
ULogger::setEventLevel(ULogger::kWarning);
#else
ULogger::setLevel(ULogger::kDebug);
ULogger::setEventLevel(ULogger::kDebug);
#endif
ULogger::setPrintThreadId(true);
registerToEventsManager();
@@ -55,7 +58,7 @@ public:
protected:
virtual bool handleEvent(UEvent * event)
{
if(event->getClassName().compare("ULogEvent") == 0)
if(event->getClassName().compare("ULogEvent") == 0)
{
ULogEvent * logEvent = (ULogEvent*)event;
if(logEvent->getCode() == ULogger::kDebug)
@@ -78,7 +81,6 @@ protected:
{
LOGF("%s", logEvent->getMsg().c_str());
}
}
return false;
}

View File

@@ -97,11 +97,18 @@
android:title="@string/pref_title_resolution"
android:summary="@string/pref_summary_resolution"
android:defaultValue="@string/pref_default_resolution"/>
<com.introlab.rtabmap.CustomSwitchPreference
<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"/>
<ListPreference
android:key="@string/pref_key_arcore_localization_filtering_speed"
android:title="@string/pref_title_arcore_localization_filtering_speed"
android:summary="@string/pref_summary_arcore_localization_filtering_speed"
android:entries="@array/pref_arcore_localization_filtering_speed_keys"
android:entryValues="@array/pref_arcore_localization_filtering_speed_values"
android:defaultValue="@string/pref_default_arcore_localization_filtering_speed"/>
<com.introlab.rtabmap.CustomSwitchPreference
android:key="@string/pref_key_smoothing"
android:title="@string/pref_title_smoothing"

View File

@@ -11,23 +11,6 @@
<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:title="Export">
<menu>
<item android:id="@+id/export_point_cloud_menu" android:title="Point Cloud">
<menu>
<item android:id="@+id/export_point_cloud" android:title="Current Density" />
<item android:id="@+id/export_point_cloud_highrez" android:title="Max Density" />
</menu>
</item>
<item android:id="@+id/export_optimized_mesh_menu" android:title="Optimized Mesh..." >
<menu>
<item android:id="@+id/export_optimized_mesh" android:title="Colored Mesh" />
<item android:id="@+id/export_optimized_mesh_texture" android:title="Textured Mesh" />
</menu>
</item>
</menu>
</item>
<item android:id="@+id/post_processing" android:title="Optimize">
<menu>
@@ -46,6 +29,23 @@
</menu>
</item>
<item android:id="@+id/export" android:title="Assemble">
<menu>
<item android:id="@+id/export_point_cloud_menu" android:title="Point Cloud">
<menu>
<item android:id="@+id/export_point_cloud" android:title="Current Density" />
<item android:id="@+id/export_point_cloud_highrez" android:title="Max Density" />
</menu>
</item>
<item android:id="@+id/export_optimized_mesh_menu" android:title="Optimized Mesh..." >
<menu>
<item android:id="@+id/export_optimized_mesh" android:title="Colored Mesh" />
<item android:id="@+id/export_optimized_mesh_texture" android:title="Textured Mesh" />
</menu>
</item>
</menu>
</item>
<item android:id="@+id/menu_rendering_settings" android:title="Visibility...">
<menu >
<group android:id="@+id/group_rendering_visibility" android:checkableBehavior="all">

View File

@@ -19,7 +19,7 @@
<string name="light_off">Lighting</string>
<string name="wireframe">Wireframe</string>
<string name="close_visualization">Close Visualization</string>
<string name="save_to_file">Export to File&#8230;</string>
<string name="save_to_file">Export OBJ/PLY&#8230;</string>
<string name="share_to_sketchfab">Share to Sketchfab&#8230;</string>
<string name="start">Start</string>
<string name="nodes">"Nodes (WM): "</string>
@@ -51,7 +51,7 @@
<string name="pref_key_remove_button">pref_key_remove_button</string>
<string name="pref_key_reset_button">pref_key_reset_button</string>
<string name="pref_key_density">pref_key_density</string>
<string name="pref_default_density">1</string>
<string name="pref_default_density">2</string>
<string name="pref_key_min_depth">pref_key_min_depth</string>
<string name="pref_default_min_depth">0</string>
<string name="pref_key_depth">pref_key_depth</string>
@@ -65,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">false</string>
<string name="pref_default_blending">true</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>
@@ -75,20 +75,22 @@
<string name="pref_key_resolution">pref_key_resolution</string>
<string name="pref_default_resolution">false</string>
<string name="pref_key_smoothing">pref_key_smoothing</string>
<string name="pref_default_smoothing">true</string>
<string name="pref_default_smoothing">false</string>
<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_default_camera_driver">-1</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_arcore_localization_filtering_speed">pref_key_arcore_localization_filtering_speed</string>
<string name="pref_default_arcore_localization_filtering_speed">1</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>
<string name="pref_default_max_speed">0</string>
<string name="pref_key_time_thr">pref_key_time_thr</string>
<string name="pref_default_time_thr">1000</string>
<string name="pref_default_time_thr">0</string>
<string name="pref_key_mem_thr">pref_key_mem_thr</string>
<string name="pref_default_mem_thr">0</string>
<string name="pref_key_loop_thr">pref_key_loop_thr</string>
@@ -98,7 +100,7 @@
<string name="pref_key_min_inliers">pref_key_min_inliers</string>
<string name="pref_default_min_inliers">25</string>
<string name="pref_key_opt_error">pref_key_opt_error</string>
<string name="pref_default_opt_error">3</string>
<string name="pref_default_opt_error">1</string>
<string name="pref_key_features_voc">pref_key_features_voc</string>
<string name="pref_default_features_voc">200</string>
<string name="pref_key_features">pref_key_features</string>
@@ -162,7 +164,7 @@
<string name="pref_title_triangle">Mesh Triangle Size</string>
<string name="pref_summary_triangle">Size in pixels of the polygons created from the depth image.</string>
<string name="pref_title_rendering_texture_decimation">Texture Resolution</string>
<string name="pref_summary_rendering_texture_decimation">Resolution of the texture for online rendering. This doesn\'t affect Export results.</string>
<string name="pref_summary_rendering_texture_decimation">Resolution of the texture for online rendering. This doesn\'t affect Assembling results.</string>
<string name="pref_title_min_depth">Min Depth</string>
<string name="pref_summary_min_depth">Points under the minimum depth are not rendered.</string>
<string name="pref_title_depth">Max Depth</string>
@@ -324,9 +326,11 @@
<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_summary_camera_driver">AR sdk used 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_arcore_localization_filtering_speed">ARCore Localization Filtering Speed</string>
<string name="pref_summary_arcore_localization_filtering_speed">Filter ARCore\'s localizations to avoid jumps in odometry when creating a map with RTAB-Map, which would cause large drift errors that are difficult to correct. Set a speed threshold to detect those events.</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>
@@ -373,16 +377,18 @@
<string name="pref_summary_gps_saved">Save GPS to database.</string>
<string name="pref_title_env_sensors_saved">Save Environmental Sensors</string>
<string name="pref_summary_env_sensors_saved">Save Wifi strength, temperature, air pressure, light intensity and relative humidity to database.</string>
<string name="pref_title_db_in_memory">Database In Memory</string>
<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>"Auto"</item>
<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>"-1"</item>
<item>"0"</item>
<item>"1"</item>
<item>"2"</item>
@@ -406,6 +412,24 @@
<item>"1"</item>
<item>"0.5"</item>
</string-array>
<string-array name="pref_arcore_localization_filtering_speed_keys">
<item>"Disabled"</item>
<item>"5 m/s"</item>
<item>"4 m/s"</item>
<item>"3 m/s"</item>
<item>"2 m/s"</item>
<item>"1 m/s"</item>
<item>"0.5 m/s"</item>
</string-array>
<string-array name="pref_arcore_localization_filtering_speed_values">
<item>"0"</item>
<item>"5"</item>
<item>"4"</item>
<item>"3"</item>
<item>"2"</item>
<item>"1"</item>
<item>"0.5"</item>
</string-array>
<string-array name="pref_max_speed_keys">
<item>"No Limit"</item>
<item>"High"</item>
@@ -433,7 +457,7 @@
<item>"700 ms"</item>
<item>"600 ms"</item>
<item>"500 ms"</item>
<item>"400"</item>
<item>"400 ms"</item>
</string-array>
<string-array name="pref_time_thr_values">
<item>"0"</item>
@@ -529,29 +553,25 @@
<item>"10"</item>
</string-array>
<string-array name="pref_opt_error_keys">
<item>"10x"</item>
<item>"9x"</item>
<item>"8x"</item>
<item>"7x"</item>
<item>"6x"</item>
<item>"5x"</item>
<item>"4x"</item>
<item>"3.5x"</item>
<item>"3x"</item>
<item>"2.5x"</item>
<item>"2x"</item>
<item>"1.5x"</item>
<item>"1x"</item>
<item>"0.5x"</item>
<item>"Disabled"</item>
</string-array>
<string-array name="pref_opt_error_values">
<item>"10"</item>
<item>"9"</item>
<item>"8"</item>
<item>"7"</item>
<item>"6"</item>
<item>"5"</item>
<item>"4"</item>
<item>"3.5"</item>
<item>"3"</item>
<item>"2.5"</item>
<item>"2"</item>
<item>"1.5"</item>
<item>"1"</item>
<item>"0.5"</item>
<item>"0"</item>
</string-array>
<string-array name="pref_features_voc_keys">
@@ -712,9 +732,9 @@
<item>"1"</item>
</string-array>
<string name="pref_title_export_sub">Exporting&#8230;</string>
<string name="pref_title_export">Exporting</string>
<string name="pref_summary_export">Advanced parameters used when exporting the map.</string>
<string name="pref_title_export_sub">Assembling&#8230;</string>
<string name="pref_title_export">Assembling</string>
<string name="pref_summary_export">Advanced parameters used when assembling the map.</string>
<string name="pref_title_cloud_voxel">Voxel Size</string>
<string name="pref_summary_cloud_voxel">If you don\'t need a very precise point cloud, you can set this to reduce the output point cloud size. This is also used for optimized mesh.</string>
<string name="pref_title_texture_size">Texture Size</string>
@@ -727,8 +747,8 @@
<string name="pref_summary_max_texture_distance">Maximum distance from a camera for polygons to be textured by this camera.</string>
<string name="pref_title_min_texture_cluster_size">Min Texture Cluster Size</string>
<string name="pref_summary_min_texture_cluster_size">Minimum polygon cluster size to be textured by a camera. This helps to filter sparse textured polygons.</string>
<string name="pref_title_block_render">Block Rendering Thread While Exporting</string>
<string name="pref_summary_block_render">This decreases exporting time, but freezes rendering while exporting. This also clears temporary the rendered clouds/meshes from memory during exporting, this can be useful to avoid out of memory errors.</string>
<string name="pref_title_block_render">Block Rendering Thread While Assembling</string>
<string name="pref_summary_block_render">This decreases assembling time, but freezes rendering while assembling. This also clears temporary the rendered clouds/meshes from memory during assembling, this can be useful to avoid out of memory errors.</string>
<string-array name="pref_cloud_voxel_keys">
<item>"0.2 m"</item>
@@ -834,7 +854,7 @@
<string name="pref_title_opt_depth">Reconstruction Depth</string>
<string name="pref_summary_opt_depth">Lowering this parameter decreases reconstruction time, but geometry precision is lower. Minimum polygon size: map length / 2^depth). \"Auto\" means that depth is chosen so that polygon size is just under 3 cm.</string>
<string name="pref_title_opt_color_radius">Color Radius</string>
<string name="pref_summary_opt_color_radius">Radius used to transfer nearest color from the point cloud to reconstructed mesh. When exporting with texture, if Clean Mesh is also enabled, this will limit the number of polygons textured in holes.</string>
<string name="pref_summary_opt_color_radius">Radius used to transfer nearest color from the point cloud to reconstructed mesh. When assembling with texture, if Clean Mesh is also enabled, this will limit the number of polygons textured in holes.</string>
<string name="pref_title_opt_clean_white">Clean Mesh</string>
<string name="pref_summary_opt_clean_white">Clean mesh from textureless or colorless reconstructed polygons.</string>
<string name="pref_summary_opt_min_cluster_size">This can be used to filter polygons before texturing.</string>
@@ -868,10 +888,10 @@
<item>"0.2 m"</item>
<item>"0.1 m"</item>
<item>"0.05 m"</item>
<item>"0.025"</item>
<item>"0.02"</item>
<item>"0.015"</item>
<item>"0.01"</item>
<item>"0.025 m"</item>
<item>"0.02 m"</item>
<item>"0.015 m"</item>
<item>"0.01 m"</item>
<item>"Disabled"</item>
</string-array>
<string-array name="pref_opt_color_radius_values">

View File

@@ -8,11 +8,14 @@ import java.util.EnumSet;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import com.google.ar.core.Anchor;
import com.google.ar.core.Camera;
import com.google.ar.core.CameraConfig;
import com.google.ar.core.CameraConfigFilter;
import com.google.ar.core.CameraIntrinsics;
import com.google.ar.core.Config;
import com.google.ar.core.Coordinates2d;
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;
@@ -29,6 +32,7 @@ import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.CameraMetadata;
import android.hardware.camera2.CaptureFailure;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.TotalCaptureResult;
@@ -40,27 +44,39 @@ import android.os.HandlerThread;
import android.support.annotation.NonNull;
import android.util.Log;
import android.view.Surface;
import android.widget.Toast;
public class ARCoreSharedCamera {
public static final String TAG = ARCoreSharedCamera.class.getSimpleName();
private static final float[] QUAD_COORDS =
new float[] {
-1.0f, -1.0f, +1.0f, -1.0f, -1.0f, +1.0f, +1.0f, +1.0f,
};
private static RTABMapActivity mActivity;
public ARCoreSharedCamera(RTABMapActivity c) {
public ARCoreSharedCamera(RTABMapActivity c, float arCoreLocalizationFilteringSpeed) {
mActivity = c;
mARCoreLocalizationFilteringSpeed = arCoreLocalizationFilteringSpeed;
}
// 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;
private int depthWidth = 640;
private int depthHeight = 480;
// GL Surface used to draw camera preview image.
public GLSurfaceView surfaceView;
// ARCore session that supports camera sharing.
private Session sharedSession;
private Pose previousAnchorPose = null;
private long previousAnchorTimeStamp;
private Pose arCoreCorrection = Pose.IDENTITY;
private Pose odomPose = Pose.IDENTITY;
private float mARCoreLocalizationFilteringSpeed = 1.0f;
// Camera capture session. Used by both non-AR and AR modes.
private CameraCaptureSession captureSession;
@@ -78,9 +94,16 @@ public class ARCoreSharedCamera {
// ARCore shared camera instance, obtained from ARCore session that supports sharing.
private SharedCamera sharedCamera;
private Toast mToast = null;
// Camera ID for the camera used by ARCore.
private String cameraId;
private String depthCameraId;
private Pose rgbExtrinsics;
private Pose depthExtrinsics;
private float[] depthIntrinsics = null;
private AtomicBoolean mReady = new AtomicBoolean(false);
@@ -95,6 +118,11 @@ public class ARCoreSharedCamera {
public boolean isDepthSupported() {return mTOFAvailable;}
public void setToast(Toast toast)
{
mToast = toast;
}
// Camera device state callback.
private final CameraDevice.StateCallback cameraDeviceCallback =
new CameraDevice.StateCallback() {
@@ -176,7 +204,7 @@ public class ARCoreSharedCamera {
@NonNull CameraCaptureSession session,
@NonNull CaptureRequest request,
@NonNull TotalCaptureResult result) {
Log.i(TAG, "onCaptureCompleted");
//Log.i(TAG, "onCaptureCompleted");
}
//@Override // android 23
@@ -251,7 +279,7 @@ public class ARCoreSharedCamera {
// 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());
if (mTOFAvailable && cameraId.compareTo(depthCameraId) == 0) surfaceList.add(mTOFImageReader.imageReader.getSurface());
// Surface list should now contain three surfacemReadymReadys:
// 0. sharedCamera.getSurfaceTexture()
// 1. …
@@ -272,8 +300,6 @@ public class ARCoreSharedCamera {
} catch (CameraAccessException e) {
Log.e(TAG, "CameraAccessException", e);
}
}
// Start background handler thread, used to run callbacks without blocking UI thread.
@@ -298,17 +324,32 @@ public class ARCoreSharedCamera {
}
mTOFImageReader.stopBackgroundThread();
}
private long mPreviousTime = 0;
/**
* Return true if the given array contains the given integer.
*
* @param modes array to check.
* @param mode integer to get for.
* @return true if the array contains the given integer, otherwise false.
*/
private static boolean contains(int[] modes, int mode) {
if (modes == null) {
return false;
}
for (int i : modes) {
if (i == mode) {
return true;
}
}
return false;
}
// Perform various checks, then open camera device and create CPU image reader.
public boolean openCamera() {
close();
startBackgroundThread();
mPreviousTime = System.currentTimeMillis();
if(cameraTextureId == -1)
{
@@ -317,7 +358,7 @@ public class ARCoreSharedCamera {
cameraTextureId = textures[0];
}
Log.v(TAG + " opencamera: ", "Perform various checks, then open camera device and create CPU image reader.");
Log.v(TAG, "Perform various checks, then open camera device and create CPU image reader.");
// Don't open camera if already opened.
if (cameraDevice != null) {
return false;
@@ -331,14 +372,40 @@ public class ARCoreSharedCamera {
Log.e(TAG, "Failed to create ARCore session that supports camera sharing", e);
return false;
}
// First obtain the session handle before getting the list of various camera configs.
// Create filter here with desired fps filters.
CameraConfigFilter cameraConfigFilter = new CameraConfigFilter(sharedSession);
CameraConfig[] cameraConfigs = sharedSession.getSupportedCameraConfigs(cameraConfigFilter).toArray(new CameraConfig[0]);
Log.i(TAG, "Size of supported CameraConfigs list is " + cameraConfigs.length);
// Determine the highest and lowest CPU resolutions.
int highestResolutionIndex=-1;
int highestResolution = 0;
for(int i=0; i<cameraConfigs.length; ++i)
{
Log.i(TAG, "Camera ID: " + cameraConfigs[i].getCameraId());
Log.i(TAG, "Resolution: " + cameraConfigs[i].getImageSize().getWidth() + "x" + cameraConfigs[i].getImageSize().getHeight());
if(highestResolution == 0 || highestResolution < cameraConfigs[i].getImageSize().getWidth())
{
highestResolutionIndex = i;
highestResolution = cameraConfigs[i].getImageSize().getWidth();
}
}
if(highestResolutionIndex>=0)
{
//Log.i(TAG, "Setting camera resolution to " + cameraConfigs[highestResolutionIndex].getImageSize().getWidth() + "x" + cameraConfigs[highestResolutionIndex].getImageSize().getHeight());
//FIXME: Can we make it work to use HD rgb images? To avoid this error "CaptureRequest contains unconfigured Input/Output Surface!"
//sharedSession.setCameraConfig(cameraConfigs[highestResolutionIndex]);
}
// 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.setUpdateMode(Config.UpdateMode.BLOCKING);
config.setPlaneFindingMode(Config.PlaneFindingMode.DISABLED);
config.setLightEstimationMode(Config.LightEstimationMode.DISABLED);
//config.setCloudAnchorMode(Config.CloudAnchorMode.ENABLED);
config.setCloudAnchorMode(Config.CloudAnchorMode.DISABLED);
sharedSession.configure(config);
}
@@ -347,27 +414,128 @@ public class ARCoreSharedCamera {
sharedCamera = sharedSession.getSharedCamera();
// Store the ID of the camera used by ARCore.
cameraId = sharedSession.getCameraConfig().getCameraId();
initCamera(mActivity, cameraId, 1);
ArrayList<String> resolutions;
Log.d(TAG, "Shared camera ID: " + cameraId);
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;
// Store a reference to the camera system service.
cameraManager = (CameraManager) mActivity.getSystemService(Context.CAMERA_SERVICE);
depthCameraId = null;
// show all cameras
try {
// Find a CameraDevice that supports DEPTH16 captures, and configure state.
for (String tmpCameraId : cameraManager.getCameraIdList()) {
CameraCharacteristics characteristics = cameraManager.getCameraCharacteristics(tmpCameraId);
Log.i(TAG, "Camera " + tmpCameraId + " extrinsics:");
float[] translation = characteristics.get(CameraCharacteristics.LENS_POSE_TRANSLATION);
if(translation != null)
{
Log.i(TAG, String.format("Translation (x,y,z): %f,%f,%f", translation[0], translation[1], translation[2]));
}
float[] rotation = characteristics.get(CameraCharacteristics.LENS_POSE_ROTATION);
if(rotation != null)
{
Log.i(TAG, String.format("Rotation (qx,qy,qz,qw): %f,%f,%f,%f", rotation[0], rotation[1], rotation[2], rotation[3]));
}
if(tmpCameraId.compareTo(cameraId)==0 && translation!=null && rotation!=null)
{
rgbExtrinsics = new Pose(translation, rotation);
Log.i(TAG,"Set rgb extrinsics!");
}
if (!contains(characteristics.get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES), CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_DEPTH_OUTPUT) ||
characteristics.get(CameraCharacteristics.LENS_FACING) == CameraMetadata.LENS_FACING_FRONT) {
continue;
}
Log.i(TAG, "Camera " + tmpCameraId + " has depth output available");
depthCameraId = tmpCameraId;
if(translation!=null && rotation != null)
{
depthExtrinsics = new Pose(translation, rotation);
Log.i(TAG,"Set depth extrinsics!");
}
depthIntrinsics = characteristics.get(CameraCharacteristics.LENS_INTRINSIC_CALIBRATION);
Log.i(TAG, String.format("Intrinsics (fx,fy,cx,cy,s): %f,%f,%f,%f,%f",
depthIntrinsics[0],
depthIntrinsics[1],
depthIntrinsics[2],
depthIntrinsics[3],
depthIntrinsics[4]));
}
} catch (CameraAccessException e) {
e.printStackTrace();
}
if(rgbExtrinsics == null)
{
float[] translation = {0,0,0};
float[] rotation = {0,0,0,1};
rgbExtrinsics = new Pose(translation, rotation);
}
if(depthExtrinsics == null)
{
depthExtrinsics = rgbExtrinsics;
}
if(depthCameraId != null)
{
ArrayList<String> resolutions = getResolutions(mActivity, depthCameraId, ImageFormat.DEPTH16);
if (resolutions != null) {
float[] newDepthIntrinsics = null;
int largestWidth = 0;
for( String temp : resolutions) {
Log.i(TAG, "DEPTH16 resolution: " + temp);
depthWidth = Integer.parseInt(temp.split("x")[0]);
depthHeight = Integer.parseInt(temp.split("x")[1]);
if(depthIntrinsics != null)
{
if(depthIntrinsics[0] != 0)
{
if(largestWidth == 0 && depthWidth>largestWidth)
{
largestWidth = depthWidth; // intrinsics should match this resolution
}
// Samsung Galaxy Note10+: take smallest resolution and match the intrinsics
if(depthWidth < largestWidth)
{
float scale = (float)depthWidth/(float)largestWidth;
newDepthIntrinsics = depthIntrinsics.clone();
newDepthIntrinsics[0] *= scale;
newDepthIntrinsics[1] *= scale;
newDepthIntrinsics[2] *= scale;
newDepthIntrinsics[3] *= scale;
}
}
else if(depthWidth ==240 && depthHeight==180)
{
// Huawei P30 Pro: only 240x180 is working
break;
}
}
}
if (resolutions.size()>0) {
mTOFAvailable = true;
if(newDepthIntrinsics!=null) {
depthIntrinsics = newDepthIntrinsics;
}
}
}
}
Log.i(TAG, "TOF_available: " + mTOFAvailable);
// Color CPU Image.
// Use the currently configured CPU image size.
//Size desiredCPUImageSize = sharedSession.getCameraConfig().getImageSize();
if (mTOFAvailable) mTOFImageReader.createImageReader(DEPTH_WIDTH, DEPTH_HEIGHT);
if (mTOFAvailable) mTOFImageReader.createImageReader(depthWidth, depthHeight);
// When ARCore is running, make sure it also updates our CPU image surface.
if (mTOFAvailable) {
if (mTOFAvailable && cameraId.compareTo(depthCameraId) == 0) {
sharedCamera.setAppSurfaces(this.cameraId, Arrays.asList(mTOFImageReader.imageReader.getSurface()));
}
@@ -376,15 +544,14 @@ public class ARCoreSharedCamera {
// 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);
if(mTOFAvailable && cameraId.compareTo(depthCameraId) != 0)
{
cameraManager.openCamera(depthCameraId, mTOFImageReader.cameraDeviceCallback, mTOFImageReader.backgroundHandler);
}
} catch (CameraAccessException e) {
Log.e(TAG, "Failed to open camera", e);
return false;
@@ -395,17 +562,62 @@ public class ARCoreSharedCamera {
Log.e(TAG, "Failed to open camera", e);
return false;
}
Log.i(TAG, " opencamera: TOF_available: " + mTOFAvailable);
return true;
}
public static void rotationMatrixToQuaternion(float[] R, float[] q) {
final float m00 = R[0];
final float m10 = R[1];
final float m20 = R[2];
final float m01 = R[4];
final float m11 = R[5];
final float m21 = R[6];
final float m02 = R[8];
final float m12 = R[9];
final float m22 = R[10];
float tr = m00 + m11 + m22;
if (tr > 0) {
float S = (float) Math.sqrt(tr + 1.0) * 2; // S=4*qw
q[0] = 0.25f * S;/* w w w.j ava 2s.co m*/
q[1] = (m21 - m12) / S;
q[2] = (m02 - m20) / S;
q[3] = (m10 - m01) / S;
} else if ((m00 > m11) & (m00 > m22)) {
float S = (float) Math.sqrt(1.0 + m00 - m11 - m22) * 2; //
// S=4*q[1]
q[0] = (m21 - m12) / S;
q[1] = 0.25f * S;
q[2] = (m01 + m10) / S;
q[3] = (m02 + m20) / S;
} else if (m11 > m22) {
float S = (float) Math.sqrt(1.0 + m11 - m00 - m22) * 2; //
// S=4*q[2]
q[0] = (m02 - m20) / S;
q[1] = (m01 + m10) / S;
q[2] = 0.25f * S;
q[3] = (m12 + m21) / S;
} else {
float S = (float) Math.sqrt(1.0 + m22 - m00 - m11) * 2; //
// S=4*q[3]
q[0] = (m10 - m01) / S;
q[1] = (m02 + m20) / S;
q[2] = (m12 + m21) / S;
q[3] = 0.25f * S;
}
}
// Close the camera device.
public void close() {
Log.w(TAG, "close()");
if (sharedSession != null) {
sharedSession.pause();
sharedSession.close();
sharedSession = null;
}
if (captureSession != null) {
@@ -414,12 +626,10 @@ public class ARCoreSharedCamera {
}
if (cameraDevice != null) {
cameraDevice.close();
cameraDevice = null;
}
if (mTOFImageReader.imageReader != null) {
mTOFImageReader.imageReader.close();
mTOFImageReader.imageReader = null;
}
mTOFImageReader.close();
if(cameraTextureId>=0)
{
@@ -429,12 +639,17 @@ public class ARCoreSharedCamera {
stopBackgroundThread();
}
/*************************************************** ONDRAWFRAME ARCORE ************************************************************* */
public void setDisplayGeometry(int rotation, int width, int height)
{
if(sharedSession!=null)
sharedSession.setDisplayGeometry(rotation, width, height);
}
/*************************************************** ONDRAWFRAME ARCORE ************************************************************* */
// Draw frame when in AR mode. Called on the GL thread.
public void updateGL() throws CameraNotAvailableException {
if(!mReady.get())
if(!mReady.get() || sharedSession == null)
{
return;
}
@@ -455,29 +670,98 @@ public class ARCoreSharedCamera {
camera = frame.getCamera();
}else
{
Log.e(TAG, String.format("frame.getCamera() null!"));
return;
}
if (camera == null) return;
// If not tracking, don't draw 3D objects.
if (camera.getTrackingState() == TrackingState.PAUSED) return;
if (camera == null) {
Log.e(TAG, String.format("camera is null!"));
return;
}
if (camera.getTrackingState() != TrackingState.TRACKING) {
final String trackingState = camera.getTrackingState().toString();
Log.e(TAG, String.format("Tracking lost! state=%s", trackingState));
// This will force a new session on the next frame received
RTABMapLib.postCameraPoseEvent(RTABMapActivity.nativeApplication, 0,0,0,0,0,0,0,0);
mActivity.runOnUiThread(new Runnable() {
public void run() {
if(mToast!=null && previousAnchorPose != null)
{
String msg = "Tracking lost! If you are mapping, you will need to relocalize before continuing.";
if(mToast.getView() == null || !mToast.getView().isShown())
{
mToast.makeText(mActivity.getApplicationContext(),
msg, Toast.LENGTH_LONG).show();
}
else
{
mToast.setText(msg);
}
previousAnchorPose = null;
}
}
});
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)
// Remove ARCore SLAM corrections by integrating pose from previous frame anchor
if(previousAnchorPose == null || mARCoreLocalizationFilteringSpeed==0)
{
return;
odomPose = pose;
}
mPreviousTime = System. currentTimeMillis();
else
{
float[] t = previousAnchorPose.inverse().compose(pose).getTranslation();
final double speed = Math.sqrt(t[0]*t[0]+t[1]*t[1]+t[2]*t[2])/((double)(frame.getTimestamp()-previousAnchorTimeStamp)/10e8);
if(speed>=mARCoreLocalizationFilteringSpeed)
{
arCoreCorrection = arCoreCorrection.compose(previousAnchorPose).compose(pose.inverse());
t = arCoreCorrection.getTranslation();
Log.e(TAG, String.format("POTENTIAL TELEPORTATION!!!!!!!!!!!!!! previous anchor moved (speed=%f), new arcorrection: %f %f %f", speed, t[0], t[1], t[2]));
t = odomPose.getTranslation();
float[] t2 = (arCoreCorrection.compose(pose)).getTranslation();
float[] t3 = previousAnchorPose.getTranslation();
float[] t4 = pose.getTranslation();
Log.e(TAG, String.format("Odom = %f %f %f -> %f %f %f ArCore= %f %f %f -> %f %f %f", t[0], t[1], t[2], t2[0], t2[1], t2[2], t3[0], t3[1], t3[2], t4[0], t4[1], t4[2]));
mActivity.runOnUiThread(new Runnable() {
public void run() {
if(mToast!=null)
{
String msg = String.format("ARCore localization has been suppressed "
+ "because of high speed detected (%f m/s) causing a jump! You can change "
+ "ARCore localization filtering speed in Settings->Mapping if you are "
+ "indeed moving as fast.", speed);
if(mToast.getView() == null || !mToast.getView().isShown())
{
mToast.makeText(mActivity.getApplicationContext(), msg, Toast.LENGTH_LONG).show();
}
else
{
mToast.setText(msg);
}
previousAnchorPose = null;
}
}
});
}
odomPose = arCoreCorrection.compose(pose);
}
previousAnchorPose = pose;
previousAnchorTimeStamp = frame.getTimestamp();
double stamp = (double)frame.getTimestamp()/10e8;
if(!RTABMapActivity.DISABLE_LOG) Log.d(TAG, String.format("pose=%f %f %f q=%f %f %f %f stamp=%f", odomPose.tx(), odomPose.ty(), odomPose.tz(), odomPose.qx(), odomPose.qy(), odomPose.qz(), odomPose.qw(), stamp));
RTABMapLib.postCameraPoseEvent(RTABMapActivity.nativeApplication, odomPose.tx(), odomPose.ty(), odomPose.tz(), odomPose.qx(), odomPose.qy(), odomPose.qz(), odomPose.qw(), stamp);
CameraIntrinsics intrinsics = camera.getImageIntrinsics();
try{
Image image = frame.acquireCameraImage();
if(!RTABMapActivity.DISABLE_LOG) Log.d(TAG, String.format("frame=%d vs image=%d", frame.getTimestamp(), image.getTimestamp()));
PointCloud cloud = frame.acquirePointCloud();
FloatBuffer points = cloud.getPoints();
@@ -502,33 +786,66 @@ public class ARCoreSharedCamera {
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",
if(!RTABMapActivity.DISABLE_LOG) Log.d(TAG, String.format("RGB %dx%d len=%dbytes format=%d stamp=%f",
image.getWidth(), image.getHeight(), y.limit(), image.getFormat(), stamp));
float[] texCoord = new float[8];
frame.transformCoordinates2d(
Coordinates2d.OPENGL_NORMALIZED_DEVICE_COORDINATES,
QUAD_COORDS,
Coordinates2d.IMAGE_NORMALIZED,
texCoord);
float[] p = new float[16];
camera.getProjectionMatrix(p, 0, 0.1f, 100.0f);
float[] viewMatrix = new float[16];
arCoreCorrection.compose(camera.getDisplayOrientedPose()).inverse().toMatrix(viewMatrix, 0);
float[] quat = new float[4];
rotationMatrixToQuaternion(viewMatrix, quat);
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));
ByteBuffer depth;
double depthStamp;
synchronized (mTOFImageReader) {
depth = mTOFImageReader.depth16_raw;
depthStamp = (double)mTOFImageReader.timestamp/10e8;
}
RTABMapLib.postOdometryEvent(
if(!RTABMapActivity.DISABLE_LOG) Log.d(TAG, String.format("Depth %dx%d len=%dbytes format=%d stamp=%f",
mTOFImageReader.WIDTH, mTOFImageReader.HEIGHT, depth.limit(), ImageFormat.DEPTH16, depthStamp));
RTABMapLib.postOdometryEventDepth(
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,
odomPose.tx(), odomPose.ty(), odomPose.tz(), odomPose.qx(), odomPose.qy(), odomPose.qz(), odomPose.qw(),
fl[0], fl[1], pp[0], pp[1],
depthIntrinsics[0], depthIntrinsics[1], depthIntrinsics[2], depthIntrinsics[3],
rgbExtrinsics.tx(), rgbExtrinsics.ty(), rgbExtrinsics.tz(), rgbExtrinsics.qx(), rgbExtrinsics.qy(), rgbExtrinsics.qz(), rgbExtrinsics.qw(),
depthExtrinsics.tx(), depthExtrinsics.ty(), depthExtrinsics.tz(), depthExtrinsics.qx(), depthExtrinsics.qy(), depthExtrinsics.qz(), depthExtrinsics.qw(),
stamp,
depthStamp,
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);
depth, depth.limit(), mTOFImageReader.WIDTH, mTOFImageReader.HEIGHT, ImageFormat.DEPTH16,
points, points.limit()/4,
viewMatrix[12], viewMatrix[13], viewMatrix[14], quat[1], quat[2], quat[3], quat[0],
p[0], p[5], p[8], p[9], p[10], p[11], p[14],
texCoord[0],texCoord[1],texCoord[2],texCoord[3],texCoord[4],texCoord[5],texCoord[6],texCoord[7]);
}
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,
odomPose.tx(), odomPose.ty(), odomPose.tz(), odomPose.qx(), odomPose.qy(), odomPose.qz(), odomPose.qw(),
fl[0], fl[1], pp[0], pp[1],
rgbExtrinsics.tx(), rgbExtrinsics.ty(), rgbExtrinsics.tz(), rgbExtrinsics.qx(), rgbExtrinsics.qy(), rgbExtrinsics.qz(), rgbExtrinsics.qw(),
stamp,
y, u, v, y.limit(), image.getWidth(), image.getHeight(), image.getFormat(),
bb, 0, 0, 0, ImageFormat.DEPTH16,
points, points.limit()/4);
points, points.limit()/4,
viewMatrix[12], viewMatrix[13], viewMatrix[14], quat[1], quat[2], quat[3], quat[0],
p[0], p[5], p[8], p[9], p[10], p[11], p[14],
texCoord[0],texCoord[1],texCoord[2],texCoord[3],texCoord[4],texCoord[5],texCoord[6],texCoord[7]);
}
image.close();
@@ -545,8 +862,8 @@ public class ARCoreSharedCamera {
/********************************************************************************************************************* */
public ArrayList<String> getResolutions (Context context, String cameraId,int imageFormat){
Log.v(TAG + "getResolutions:", " cameraId:" + cameraId + " imageFormat: " + imageFormat);
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 {
@@ -562,27 +879,4 @@ public class ARCoreSharedCamera {
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,166 @@
package com.introlab.rtabmap;
/*
* Copyright 2017 Google LLC
*
* 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.
*/
import android.app.Activity;
import android.content.Context;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraManager;
import android.hardware.display.DisplayManager;
import android.hardware.display.DisplayManager.DisplayListener;
import android.view.Display;
import android.view.Surface;
import android.view.WindowManager;
import com.google.ar.core.Session;
/**
* Helper to track the display rotations. In particular, the 180 degree rotations are not notified
* by the onSurfaceChanged() callback, and thus they require listening to the android display
* events.
*/
public final class DisplayRotationHelper implements DisplayListener {
private boolean viewportChanged;
private int viewportWidth;
private int viewportHeight;
private final Display display;
private final DisplayManager displayManager;
private final CameraManager cameraManager;
/**
* Constructs the DisplayRotationHelper but does not register the listener yet.
*
* @param context the Android {@link Context}.
*/
public DisplayRotationHelper(Context context) {
displayManager = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
cameraManager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
display = windowManager.getDefaultDisplay();
}
/** Registers the display listener. Should be called from {@link Activity#onResume()}. */
public void onResume() {
displayManager.registerDisplayListener(this, null);
}
/** Unregisters the display listener. Should be called from {@link Activity#onPause()}. */
public void onPause() {
displayManager.unregisterDisplayListener(this);
}
/**
* Records a change in surface dimensions. This will be later used by {@link
* #updateSessionIfNeeded(Session)}. Should be called from {@link
* android.opengl.GLSurfaceView.Renderer
* #onSurfaceChanged(javax.microedition.khronos.opengles.GL10, int, int)}.
*
* @param width the updated width of the surface.
* @param height the updated height of the surface.
*/
public void onSurfaceChanged(int width, int height) {
viewportWidth = width;
viewportHeight = height;
viewportChanged = true;
}
/**
* Updates the session display geometry if a change was posted either by {@link
* #onSurfaceChanged(int, int)} call or by {@link #onDisplayChanged(int)} system callback. This
* function should be called explicitly before each call to {@link Session#update()}. This
* function will also clear the 'pending update' (viewportChanged) flag.
*
* @param session the {@link Session} object to update if display geometry changed.
*/
public void updateSessionIfNeeded(ARCoreSharedCamera session) {
if (viewportChanged) {
int displayRotation = display.getRotation();
session.setDisplayGeometry(displayRotation, viewportWidth, viewportHeight);
viewportChanged = false;
}
}
/**
* Returns the aspect ratio of the GL surface viewport while accounting for the display rotation
* relative to the device camera sensor orientation.
*/
public float getCameraSensorRelativeViewportAspectRatio(String cameraId) {
float aspectRatio;
int cameraSensorToDisplayRotation = getCameraSensorToDisplayRotation(cameraId);
switch (cameraSensorToDisplayRotation) {
case 90:
case 270:
aspectRatio = (float) viewportHeight / (float) viewportWidth;
break;
case 0:
case 180:
aspectRatio = (float) viewportWidth / (float) viewportHeight;
break;
default:
throw new RuntimeException("Unhandled rotation: " + cameraSensorToDisplayRotation);
}
return aspectRatio;
}
/**
* Returns the rotation of the back-facing camera with respect to the display. The value is one of
* 0, 90, 180, 270.
*/
public int getCameraSensorToDisplayRotation(String cameraId) {
CameraCharacteristics characteristics;
try {
characteristics = cameraManager.getCameraCharacteristics(cameraId);
} catch (CameraAccessException e) {
throw new RuntimeException("Unable to determine display orientation", e);
}
// Camera sensor orientation.
int sensorOrientation = characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
// Current display orientation.
int displayOrientation = toDegrees(display.getRotation());
// Make sure we return 0, 90, 180, or 270 degrees.
return (sensorOrientation - displayOrientation + 360) % 360;
}
private int toDegrees(int rotation) {
switch (rotation) {
case Surface.ROTATION_0:
return 0;
case Surface.ROTATION_90:
return 90;
case Surface.ROTATION_180:
return 180;
case Surface.ROTATION_270:
return 270;
default:
throw new RuntimeException("Unknown rotation " + rotation);
}
}
@Override
public void onDisplayAdded(int displayId) {}
@Override
public void onDisplayRemoved(int displayId) {}
@Override
public void onDisplayChanged(int displayId) {
viewportChanged = true;
}
}

View File

@@ -2,6 +2,7 @@ package com.introlab.rtabmap;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
@@ -25,6 +26,8 @@ import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.ProgressDialog;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnShowListener;
@@ -35,6 +38,7 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.database.Cursor;
import android.hardware.Camera;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
@@ -46,6 +50,7 @@ import android.hardware.display.DisplayManager;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.media.MediaScannerConnection;
import android.net.Uri;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
@@ -56,6 +61,8 @@ import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.preference.PreferenceManager;
import android.provider.MediaStore;
import android.provider.OpenableColumns;
import android.support.v4.app.FragmentActivity;
import android.support.v4.content.FileProvider;
import android.text.InputType;
@@ -104,7 +111,7 @@ public class RTABMapActivity extends FragmentActivity implements OnClickListener
// Tag for debug logging.
public static final String TAG = RTABMapActivity.class.getSimpleName();
public static boolean DISABLE_LOG = true;
public static boolean DISABLE_LOG = false;
// The minimum Tango Core version required from this application.
private static final int MIN_TANGO_CORE_VERSION = 9377;
@@ -118,7 +125,7 @@ public class RTABMapActivity extends FragmentActivity implements OnClickListener
public static final String RTABMAP_TMP_DB = "rtabmap.tmp.db";
public static final String RTABMAP_TMP_DIR = "tmp";
public static final String RTABMAP_TMP_FILENAME = "map";
public static final String RTABMAP_SDCARD_PATH = "/sdcard/";
public static final String RTABMAP_SDCARD_PATH = "/Internal storage/";
public static final String RTABMAP_EXPORT_DIR = "Export/";
public static final String RTABMAP_AUTH_TOKEN_KEY = "com.introlab.rtabmap.AUTH_TOKEN";
@@ -256,6 +263,8 @@ public class RTABMapActivity extends FragmentActivity implements OnClickListener
ARCoreSharedCamera mArCoreCamera = null;
int mCameraDriver = 0;
private String mIntentDbToOpen = null;
//Tango Service connection.
boolean mCameraServiceConnectionUsed = false;
@@ -494,10 +503,29 @@ public class RTABMapActivity extends FragmentActivity implements OnClickListener
mWorkingDirectoryHuman = "";
mTotalLoopClosures = 0;
mLastFastMovementNotificationStamp = System.currentTimeMillis()/1000;
if(Environment.getExternalStorageState().compareTo(Environment.MEDIA_MOUNTED)==0)
int targetSdkVersion= 0;
try {
ApplicationInfo app = this.getPackageManager().getApplicationInfo("com.introlab.rtabmap", 0);
targetSdkVersion = app.targetSdkVersion;
} catch (NameNotFoundException e) {
e.printStackTrace();
}
if(Environment.getExternalStorageState().compareTo(Environment.MEDIA_MOUNTED)==0 &&
(targetSdkVersion < 30 || getActivity().getExternalFilesDirs(null).length >=1))
{
File extStore = Environment.getExternalStorageDirectory();
File extStore;
if(targetSdkVersion < 30)
{
extStore = Environment.getExternalStorageDirectory();
}
else // >= android30
{
extStore = getActivity().getExternalFilesDirs(null)[0];
}
mWorkingDirectory = extStore.getAbsolutePath() + "/" + getString(R.string.app_name) + "/";
extStore = new File(mWorkingDirectory);
extStore.mkdirs();
@@ -507,7 +535,7 @@ public class RTABMapActivity extends FragmentActivity implements OnClickListener
{
// show warning that data cannot be saved!
mToast.makeText(getApplicationContext(),
String.format("Failed to get external storage path (SD-CARD, state=%s). Saving disabled.",
String.format("Failed to get external storage path (state=%s). Saving disabled.",
Environment.getExternalStorageState()), mToast.LENGTH_LONG).show();
}
@@ -574,33 +602,141 @@ public class RTABMapActivity extends FragmentActivity implements OnClickListener
DISABLE_LOG = !( 0 != ( getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE ) );
if (!PermissionHelper.hasPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
PermissionHelper.requestPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
}
else
{
postCreate();
}
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
String cameraDriverStr = sharedPref.getString(getString(R.string.pref_key_camera_driver), getString(R.string.pref_default_camera_driver));
mCameraDriver = Integer.parseInt(cameraDriverStr);
isArCoreAvailable();
isArEngineAvailable();
if (!PermissionHelper.hasPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
PermissionHelper.requestPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
}
else
{
// Get intent, action and MIME type
Intent intent = getIntent();
String action = intent.getAction();
String type = intent.getType();
if (Intent.ACTION_SEND.equals(action) && type != null) {
if ("application/octet-stream".equals(type)) {
Uri imageUri = (Uri) intent.getParcelableExtra(Intent.EXTRA_STREAM);
if (imageUri != null) {
String fileName = getFileName(imageUri);
Log.i(TAG, "Intent received: " + imageUri.getPath() + " Name:" + fileName);
if(fileName.endsWith(".db"))
{
File file = new File(mWorkingDirectory+fileName);
if(file.exists())
{
mToast.makeText(this, fileName + " already exists in RTAB-Map's library! Cannot be copied.", mToast.LENGTH_LONG).show();
}
else
{
copy(imageUri, file);
mIntentDbToOpen = fileName;
}
}
}
}
} else if (Intent.ACTION_SEND_MULTIPLE.equals(action) && type != null) {
if (type.startsWith("application/")) {
ArrayList<Uri> imageUris = intent.getParcelableArrayListExtra(Intent.EXTRA_STREAM);
if (imageUris != null) {
boolean added = false;
for(Uri imageUri: imageUris)
{
String fileName = getFileName(imageUri);
Log.i(TAG, "Intent received: " + imageUri.getPath() + " Name:" + fileName);
if(fileName.endsWith(".db"))
{
File file = new File(mWorkingDirectory+"/"+getFileName(imageUri));
if(!file.exists())
{
copy(imageUri, file);
added = true;
}
else
{
Log.e(TAG, fileName + " already exists in RTAB-Map's library! Cannot be copied.");
}
}
}
if(added)
{
openDatabase();
}
}
}
}
postCreate();
}
}
public void copy(File src, File dst) throws IOException {
InputStream in = new FileInputStream(src);
OutputStream out = new FileOutputStream(dst);
// Transfer bytes from in to out
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
in.close();
out.close();
}
public void copy(Uri uri, File file)
{
InputStream in;
try {
in = getApplicationContext().getContentResolver().openInputStream(uri);
OutputStream out = new FileOutputStream(file);
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
in.close();
out.close();
} catch (IOException e) {
Log.e(TAG, e.getMessage());
}
}
public String getFileName(Uri uri) {
String result = null;
if (uri.getScheme().equals("content")) {
Cursor cursor = getContentResolver().query(uri, null, null, null, null);
try {
if (cursor != null && cursor.moveToFirst()) {
result = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
}
} finally {
cursor.close();
}
}
if (result == null) {
result = uri.getPath();
int cut = result.lastIndexOf('/');
if (cut != -1) {
result = result.substring(cut + 1);
}
}
return result;
}
// Should be called only if read/write permissions are granted!
private void postCreate()
{
Log.i(TAG, "postCreate()");
String tmpDatabase = mWorkingDirectory+RTABMAP_TMP_DB;
(new File(tmpDatabase)).delete();
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
boolean databaseInMemory = sharedPref.getBoolean(getString(R.string.pref_key_db_in_memory), Boolean.parseBoolean(getString(R.string.pref_default_db_in_memory)));
RTABMapLib.openDatabase(nativeApplication, tmpDatabase, databaseInMemory, false);
final String[] files = Util.loadFileList(mWorkingDirectory, true);
if(files.length == 0)
{
@@ -613,6 +749,17 @@ public class RTABMapActivity extends FragmentActivity implements OnClickListener
Log.i(TAG, String.format("updateCameraDriverSettings() mCameraDriver=%d RTABMapLib.isBuiltWith(%d)=%d", mCameraDriver, mCameraDriver, RTABMapLib.isBuiltWith(nativeApplication, mCameraDriver)?1:0));
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
String cameraDriverStr = sharedPref.getString(getString(R.string.pref_key_camera_driver), getString(R.string.pref_default_camera_driver));
mCameraDriver = Integer.parseInt(cameraDriverStr);
if(mCameraDriver == -1)
{
// Prioritize tango if available
mCameraDriver = 0;
SharedPreferences.Editor editor = sharedPref.edit();
editor.putString(getString(R.string.pref_key_camera_driver), "0");
editor.commit();
}
if(mCameraDriver == 0 && (!CheckTangoCoreVersion(MIN_TANGO_CORE_VERSION) || !RTABMapLib.isBuiltWith(nativeApplication, 0)))
{
@@ -1075,6 +1222,7 @@ public class RTABMapActivity extends FragmentActivity implements OnClickListener
setAndroidOrientation();
updateCameraDriverSettings();
updatePreferences();
if(mState == State.STATE_MAPPING || mState == State.STATE_CAMERA)
@@ -1166,7 +1314,7 @@ public class RTABMapActivity extends FragmentActivity implements OnClickListener
final boolean depthFromMotion = sharedPref.getBoolean(getString(R.string.pref_key_depth_from_motion), Boolean.parseBoolean(getString(R.string.pref_default_depth_from_motion)));
mCameraDriver = Integer.parseInt(cameraDriverStr);
if(!DISABLE_LOG) Log.i(TAG, String.format("startCamera() driver=%d", mCameraDriver));
Log.i(TAG, String.format("startCamera() driver=%d", mCameraDriver));
if(mCameraDriver == 0) // Tango
{
// Check if the Tango Core is out dated.
@@ -1235,7 +1383,10 @@ public class RTABMapActivity extends FragmentActivity implements OnClickListener
if(cameraStartSucess && mCameraDriver == 3)
{
synchronized (this) {
mArCoreCamera = new ARCoreSharedCamera(getActivity());
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(getActivity());
String arCoreLocalizationFiltering = sharedPref.getString(getString(R.string.pref_key_arcore_localization_filtering_speed), getString(R.string.pref_default_arcore_localization_filtering_speed));
mArCoreCamera = new ARCoreSharedCamera(getActivity(), Float.parseFloat(arCoreLocalizationFiltering));
mArCoreCamera.setToast(mToast);
mProgressDialog.setTitle("");
mProgressDialog.setMessage(message);
mProgressDialog.show();
@@ -1486,7 +1637,7 @@ public class RTABMapActivity extends FragmentActivity implements OnClickListener
}
updateState(mState);
return true;
}
@@ -1988,6 +2139,7 @@ public class RTABMapActivity extends FragmentActivity implements OnClickListener
final int loopDetected = RTABMapLib.postProcessing(nativeApplication, -1);
runOnUiThread(new Runnable() {
public void run() {
updateState(State.STATE_IDLE);
if(mExportProgressDialog.isShowing())
{
mExportProgressDialog.dismiss();
@@ -2020,8 +2172,6 @@ public class RTABMapActivity extends FragmentActivity implements OnClickListener
mProgressDialog.dismiss();
mToast.makeText(getActivity(), String.format("Optimization canceled"), mToast.LENGTH_LONG).show();
}
updateState(State.STATE_IDLE);
}
});
}
@@ -2140,7 +2290,7 @@ public class RTABMapActivity extends FragmentActivity implements OnClickListener
mButtonCloseVisualization.setVisibility(mHudVisible && mState != State.STATE_VISUALIZING_CAMERA?View.VISIBLE:View.INVISIBLE);
mButtonCloseVisualization.setEnabled(true);
mButtonSaveOnDevice.setVisibility(mHudVisible && mState != State.STATE_VISUALIZING_CAMERA?View.VISIBLE:View.INVISIBLE);
mButtonShareOnSketchfab.setVisibility(mHudVisible && mState != State.STATE_VISUALIZING_CAMERA?View.VISIBLE:View.INVISIBLE);
//mButtonShareOnSketchfab.setVisibility(mHudVisible && mState != State.STATE_VISUALIZING_CAMERA?View.VISIBLE:View.INVISIBLE);
mButtonLibrary.setVisibility(View.INVISIBLE);
mButtonNewScan.setVisibility(View.INVISIBLE);
mItemSave.setEnabled(mState != State.STATE_VISUALIZING_CAMERA);
@@ -2213,6 +2363,12 @@ public class RTABMapActivity extends FragmentActivity implements OnClickListener
{
mGLView.setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);
}
if(mState == State.STATE_WELCOME && mIntentDbToOpen != null)
{
openDatabase(mIntentDbToOpen, false);
mIntentDbToOpen = null;
}
}
private void startMapping() {
@@ -2622,7 +2778,7 @@ public class RTABMapActivity extends FragmentActivity implements OnClickListener
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(getActivity());
boolean databaseInMemory = sharedPref.getBoolean(getString(R.string.pref_key_db_in_memory), Boolean.parseBoolean(getString(R.string.pref_default_db_in_memory)));
String tmpDatabase = mWorkingDirectory+RTABMAP_TMP_DB;
RTABMapLib.openDatabase(nativeApplication, tmpDatabase, databaseInMemory, false);
RTABMapLib.openDatabase(nativeApplication, tmpDatabase, databaseInMemory, false, true);
mItemLocalizationMode.setEnabled(!mItemDataRecorderMode.isChecked());
@@ -2776,16 +2932,110 @@ public class RTABMapActivity extends FragmentActivity implements OnClickListener
mOpenedDatabasePath = "";
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
boolean databaseInMemory = sharedPref.getBoolean(getString(R.string.pref_key_db_in_memory), Boolean.parseBoolean(getString(R.string.pref_default_db_in_memory)));
String tmpDatabase = mWorkingDirectory+RTABMAP_TMP_DB;
RTABMapLib.openDatabase(nativeApplication, tmpDatabase, databaseInMemory, false);
if(!(mState == State.STATE_CAMERA || mState ==State.STATE_MAPPING))
final String tmpDatabase = mWorkingDirectory+RTABMAP_TMP_DB;
File newFile = new File(tmpDatabase);
final int fileSizeMB = (int)newFile.length()/(1024 * 1024);
if(!(mState == State.STATE_CAMERA || mState ==State.STATE_MAPPING) &&
newFile.exists() &&
fileSizeMB>1) // >1MB
{
setCamera(1);
startCamera(String.format("Hold Tight! Initializing Camera Service...\n"
+ "Tip: If the camera is still drifting just after the mapping has started, do \"Reset\"."));
AlertDialog d2 = new AlertDialog.Builder(getActivity())
.setCancelable(false)
.setTitle("Recovery")
.setMessage(String.format("The previous session (%d MB) was not correctly saved, do you want to recover it?", fileSizeMB))
.setNegativeButton("Ignore", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
(new File(tmpDatabase)).delete();
newScan();
}
})
.setNeutralButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// do nothing
}
})
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
final String fileName = new SimpleDateFormat("yyMMdd-HHmmss").format(new Date()) + ".db";
final String outputDbPath = mWorkingDirectory + fileName;
mExportProgressDialog.setTitle("Recovering");
mExportProgressDialog.setMessage(String.format("Please wait while recovering data..."));
mExportProgressDialog.setProgress(0);
final State previousState = mState;
mExportProgressDialog.show();
updateState(State.STATE_PROCESSING);
Thread exportThread = new Thread(new Runnable() {
public void run() {
final long startTime = System.currentTimeMillis()/1000;
final boolean success = RTABMapLib.recover(
nativeApplication,
tmpDatabase,
outputDbPath);
runOnUiThread(new Runnable() {
public void run() {
if(mExportProgressDialog.isShowing())
{
if(success)
{
AlertDialog d2 = new AlertDialog.Builder(getActivity())
.setCancelable(false)
.setTitle("Database saved!")
.setMessage(String.format("Database \"%s\" (%d MB) successfully saved!", fileName, fileSizeMB))
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
openDatabase(fileName, false);
}
})
.create();
d2.setCanceledOnTouchOutside(true);
d2.show();
}
else
{
updateState(previousState);
mToast.makeText(getActivity(), String.format("Recovery failed!"), mToast.LENGTH_LONG).show();
}
mExportProgressDialog.dismiss();
}
else
{
mToast.makeText(getActivity(), String.format("Recovery canceled"), mToast.LENGTH_LONG).show();
updateState(previousState);
}
}
});
}
});
exportThread.start();
refreshSystemMediaScanDataBase(getActivity(), outputDbPath);
}
})
.create();
d2.setCanceledOnTouchOutside(false);
d2.show();
}
else
{
RTABMapLib.openDatabase(nativeApplication, tmpDatabase, databaseInMemory, false, true);
if(!(mState == State.STATE_CAMERA || mState ==State.STATE_MAPPING))
{
setCamera(0);
startCamera(String.format("Hold Tight! Initializing Camera Service...\n"
+ "Tip: If the camera is still drifting just after the mapping has started, do \"Reset\"."));
}
}
}
private void openDatabase()
{
@@ -3211,7 +3461,7 @@ public class RTABMapActivity extends FragmentActivity implements OnClickListener
context.sendBroadcast(mediaScanIntent);
}
private void saveDatabase(String fileName)
private void saveDatabase(final String fileName)
{
final String newDatabasePath = mWorkingDirectory + fileName + ".db";
final String newDatabasePathHuman = mWorkingDirectoryHuman + fileName + ".db";
@@ -3243,7 +3493,7 @@ public class RTABMapActivity extends FragmentActivity implements OnClickListener
mSavedStamp = System.currentTimeMillis();
msg = String.format("Database saved to \"%s\".", newDatabasePathHuman);
}
// build notification
Intent intent = new Intent(getActivity(), RTABMapActivity.class);
// use System.currentTimeMillis() to have a unique ID for the pending intent
@@ -3276,7 +3526,7 @@ public class RTABMapActivity extends FragmentActivity implements OnClickListener
AlertDialog d2 = new AlertDialog.Builder(getActivity())
.setCancelable(false)
.setTitle("Database saved!")
.setMessage(String.format("Database \"%s\" (%d MB) successfully saved on the SD-CARD!", newDatabasePathHuman, fileSizeMB))
.setMessage(String.format("Database \"%s\" (%d MB) successfully saved!", newDatabasePathHuman, fileSizeMB))
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
resetNoTouchTimer(true);
@@ -3330,30 +3580,7 @@ public class RTABMapActivity extends FragmentActivity implements OnClickListener
dialog.dismiss();
if(!fileName.isEmpty())
{
File newFile = new File(mWorkingDirectory + RTABMAP_EXPORT_DIR + fileName + ".zip");
if(newFile.exists())
{
AlertDialog ad = new AlertDialog.Builder(getActivity())
.setCancelable(false)
.setTitle("File Already Exists")
.setMessage("Do you want to overwrite the existing file?")
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
writeExportedFiles(fileName);
}
})
.setNegativeButton("No", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
saveOnDevice();
}
}).create();
ad.setCanceledOnTouchOutside(false);
ad.show();
}
else
{
writeExportedFiles(fileName);
}
writeExportedFiles(fileName);
}
}
});
@@ -3367,7 +3594,7 @@ public class RTABMapActivity extends FragmentActivity implements OnClickListener
{
Log.i(TAG, String.format("Write exported mesh to \"%s\"", fileName));
mProgressDialog.setTitle("Saving to sd-card");
mProgressDialog.setTitle("Exporting");
mProgressDialog.setMessage(String.format("Compressing the files..."));
mProgressDialog.show();
@@ -3393,7 +3620,7 @@ public class RTABMapActivity extends FragmentActivity implements OnClickListener
}
File exportDir = new File(mWorkingDirectory + RTABMAP_EXPORT_DIR);
exportDir.mkdirs();
final String pathHuman = mWorkingDirectoryHuman + RTABMAP_EXPORT_DIR + fileName + ".zip";
final String zipOutput = mWorkingDirectory+RTABMAP_EXPORT_DIR+fileName+".zip";
if(RTABMapLib.writeExportedMesh(nativeApplication, mWorkingDirectory + RTABMAP_TMP_DIR, RTABMAP_TMP_FILENAME))
@@ -3420,7 +3647,7 @@ public class RTABMapActivity extends FragmentActivity implements OnClickListener
final String msg = e.getMessage();
runOnUiThread(new Runnable() {
public void run() {
mToast.makeText(getActivity(), String.format("Exporting mesh \"%s\" failed! Error=%s", pathHuman, msg), mToast.LENGTH_LONG).show();
mToast.makeText(getActivity(), String.format("Exporting mesh \"%s\" failed! Error=%s", fileName, msg), mToast.LENGTH_LONG).show();
}
});
}
@@ -3439,13 +3666,14 @@ public class RTABMapActivity extends FragmentActivity implements OnClickListener
AlertDialog d = new AlertDialog.Builder(getActivity())
.setCancelable(false)
.setTitle("Mesh Saved!")
.setMessage(String.format("Mesh \"%s\" (%d MB) successfully exported on the SD-CARD! Share it?", pathHuman, fileSizeMB))
.setMessage(String.format("Mesh \"%s\" (%d MB) successfully exported! Share it?", pathHuman, fileSizeMB))
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// Send to...
Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(f));
shareIntent.putExtra(Intent.EXTRA_STREAM, FileProvider.getUriForFile(getActivity(), getActivity().getApplicationContext().getPackageName() + ".provider", f));
shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
shareIntent.setType("application/zip");
startActivity(Intent.createChooser(shareIntent, "Sharing..."));
@@ -3467,7 +3695,7 @@ public class RTABMapActivity extends FragmentActivity implements OnClickListener
runOnUiThread(new Runnable() {
public void run() {
mProgressDialog.dismiss();
mToast.makeText(getActivity(), String.format("Exporting mesh \"%s\" failed! No files found in tmp directory!? Last export may have failed or have been canceled.", pathHuman), mToast.LENGTH_LONG).show();
mToast.makeText(getActivity(), String.format("Exporting mesh \"%s\" failed! No files found in tmp directory!? Last export may have failed or have been canceled.", fileName), mToast.LENGTH_LONG).show();
resetNoTouchTimer(true);
}
});
@@ -3494,8 +3722,7 @@ public class RTABMapActivity extends FragmentActivity implements OnClickListener
Thread openThread = new Thread(new Runnable() {
public void run() {
final String tmpDatabase = mWorkingDirectory+RTABMAP_TMP_DB;
final int status = RTABMapLib.openDatabase2(nativeApplication, mOpenedDatabasePath, tmpDatabase, databaseInMemory, optimize);
final int status = RTABMapLib.openDatabase(nativeApplication, mOpenedDatabasePath, databaseInMemory, optimize, false);
runOnUiThread(new Runnable() {
public void run() {
@@ -3574,20 +3801,6 @@ public class RTABMapActivity extends FragmentActivity implements OnClickListener
openThread.start();
}
public void copy(File src, File dst) throws IOException {
InputStream in = new FileInputStream(src);
OutputStream out = new FileOutputStream(dst);
// Transfer bytes from in to out
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
in.close();
out.close();
}
private void shareToSketchfab()
{
if (!PermissionHelper.hasPermission(this, Manifest.permission.INTERNET)) {

View File

@@ -34,9 +34,10 @@ public class RTABMapLib
public static native void setScreenRotation(long nativeApplication, int displayRotation, int cameraRotation);
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 int openDatabase(long nativeApplication, String databasePath, boolean databaseInMemory, boolean optimize, boolean clearDatabase);
public static native boolean recover(long nativeApplication, String from, String to);
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);
@@ -134,13 +135,30 @@ public class RTABMapLib
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 postCameraPoseEvent(long nativeApplication, float x, float y, float z, float qx, float qy, float qz, float qw, double stamp);
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,
float rgb_fx, float rgb_fy, float rgb_cx, float rgb_cy,
float rgbFrameX, float rgbFrameY, float rgbFrameZ, float rgbFrameQX, float rgbFrameQY, float rgbFrameQZ, float rgbFrameQW,
double stamp,
ByteBuffer yPlane, ByteBuffer uPlane, ByteBuffer vPlane, int yPlaneLen, int rgbWidth, int rgbHeight, int rgbFormat,
FloatBuffer points, int pointsLen,
float vx, float vy, float vz, float vqx, float vqy, float vqz, float vqw, //view matrix
float p00, float p11, float p02, float p12, float p22, float p32, float p23, // projection matrix
float t0, float t1, float t2, float t3, float t4, float t5, float t6, float t7); // tex coord
public static native void postOdometryEventDepth(long nativeApplication,
float x, float y, float z, float qx, float qy, float qz, float qw,
float rgb_fx, float rgb_fy, float rgb_cx, float rgb_cy,
float depth_fx, float depth_fy, float depth_cx, float depth_cy,
float rgbFrameX, float rgbFrameY, float rgbFrameZ, float rgbFrameQX, float rgbFrameQY, float rgbFrameQZ, float rgbFrameQW,
float depthFrameX, float depthFrameY, float depthFrameZ, float depthFrameQX, float depthFrameQY, float depthFrameQZ, float depthFrameQW,
double rgbStamp,
double depthStamp,
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);
FloatBuffer points, int pointsLen,
float vx, float vy, float vz, float vqx, float vqy, float vqz, float vqw, //view matrix
float p00, float p11, float p02, float p12, float p22, float p32, float p23, // projection matrix
float t0, float t1, float t2, float t3, float t4, float t5, float t6, float t7); // tex coord
}

View File

@@ -44,12 +44,14 @@ public class Renderer implements GLSurfaceView.Renderer {
private float mTextColor = 1.0f;
private int mOffset = 0;
private ARCoreSharedCamera mCamera = null;
private DisplayRotationHelper mDisplayRotationHelper = null;
private Vector<TextObject> mTexts;
private static RTABMapActivity mActivity;
public Renderer(RTABMapActivity c) {
mActivity = c;
mDisplayRotationHelper = new DisplayRotationHelper(/*context=*/ c);
}
private ProgressDialog mProgressDialog = null;
@@ -76,6 +78,11 @@ public class Renderer implements GLSurfaceView.Renderer {
public void setCamera(ARCoreSharedCamera camera)
{
mCamera = camera;
if(mCamera!=null)
{
mDisplayRotationHelper.onDisplayChanged(0);
mDisplayRotationHelper.updateSessionIfNeeded(mCamera);
}
}
// Render loop of the Gl context.
@@ -84,17 +91,23 @@ public class Renderer implements GLSurfaceView.Renderer {
synchronized (this) {
if(mActivity.nativeApplication != 0)
{
int step = 0;
try
{
if(mCamera!=null)
{
step=1;
mCamera.updateGL();
}
step=2;
final int value = RTABMapLib.render(mActivity.nativeApplication);
if(mTextManager!=null)
{
step=3;
if(mTextChanged)
{
mTextChanged = false;
@@ -118,7 +131,7 @@ public class Renderer implements GLSurfaceView.Renderer {
Matrix.translateM(mvp, 0, mtrxProjectionAndView, 0, 0, mOffset, 0);
mTextManager.Draw(mvp);
}
step=4;
if(value != 0 && mProgressDialog != null && mProgressDialog.isShowing())
{
mActivity.runOnUiThread(new Runnable() {
@@ -135,7 +148,7 @@ public class Renderer implements GLSurfaceView.Renderer {
public void run() {
if(mToast!=null)
{
mToast.makeText(mActivity, String.format("Out of Memory!"), Toast.LENGTH_SHORT).show();
mToast.makeText(mActivity.getApplicationContext(), String.format("Out of Memory!"), Toast.LENGTH_SHORT).show();
}
}
});
@@ -146,7 +159,7 @@ public class Renderer implements GLSurfaceView.Renderer {
public void run() {
if(mToast!=null)
{
mToast.makeText(mActivity, String.format("Rendering Error!"), Toast.LENGTH_SHORT).show();
mToast.makeText(mActivity.getApplicationContext(), String.format("Rendering Error!"), Toast.LENGTH_SHORT).show();
}
}
});
@@ -154,11 +167,14 @@ public class Renderer implements GLSurfaceView.Renderer {
}
catch(final Exception e)
{
final int stepF = step;
mActivity.runOnUiThread(new Runnable() {
public void run() {
if(mToast!=null)
{
mToast.makeText(mActivity, String.format("Rendering error! %s", e.getMessage()), Toast.LENGTH_SHORT).show();
String msg = String.format("Rendering error! (exception=%s) step=%d", e.getMessage(), stepF);
Log.e("RTABMapActivity", msg);
mToast.makeText(mActivity.getApplicationContext(), msg, Toast.LENGTH_LONG).show();
}
}
@@ -176,6 +192,12 @@ public class Renderer implements GLSurfaceView.Renderer {
RTABMapLib.setupGraphic(mActivity.nativeApplication, width, height);
}
mDisplayRotationHelper.onSurfaceChanged(width, height);
if(mCamera!=null)
{
mDisplayRotationHelper.updateSessionIfNeeded(mCamera);
}
mSurfaceHeight = (float)height;
// Clear our matrices

View File

@@ -222,6 +222,7 @@ public class SettingsActivity extends PreferenceActivity implements OnSharedPref
((Preference)findPreference(getString(R.string.pref_key_background_color))).setSummary("("+((ListPreference)findPreference(getString(R.string.pref_key_background_color))).getEntry() + ") "+getString(R.string.pref_summary_background_color));
((Preference)findPreference(getString(R.string.pref_key_rendering_texture_decimation))).setSummary("("+((ListPreference)findPreference(getString(R.string.pref_key_rendering_texture_decimation))).getEntry() + ") "+getString(R.string.pref_summary_rendering_texture_decimation));
((Preference)findPreference(getString(R.string.pref_key_arcore_localization_filtering_speed))).setSummary("("+((ListPreference)findPreference(getString(R.string.pref_key_arcore_localization_filtering_speed))).getEntry() + ") "+getString(R.string.pref_summary_arcore_localization_filtering_speed));
((Preference)findPreference(getString(R.string.pref_key_update_rate))).setSummary("("+((ListPreference)findPreference(getString(R.string.pref_key_update_rate))).getEntry() + ") "+getString(R.string.pref_summary_update_rate));
((Preference)findPreference(getString(R.string.pref_key_max_speed))).setSummary("("+((ListPreference)findPreference(getString(R.string.pref_key_max_speed))).getEntry() + ") "+getString(R.string.pref_summary_max_speed));
((Preference)findPreference(getString(R.string.pref_key_time_thr))).setSummary("("+((ListPreference)findPreference(getString(R.string.pref_key_time_thr))).getEntry() + ") "+getString(R.string.pref_summary_time_thr));
@@ -284,6 +285,7 @@ public class SettingsActivity extends PreferenceActivity implements OnSharedPref
if(key.compareTo(getString(R.string.pref_key_background_color))==0) pref.setSummary("("+((ListPreference)pref).getEntry() + ") "+getString(R.string.pref_summary_background_color));
if(key.compareTo(getString(R.string.pref_key_rendering_texture_decimation))==0) pref.setSummary("("+((ListPreference)pref).getEntry() + ") "+getString(R.string.pref_summary_rendering_texture_decimation));
if(key.compareTo(getString(R.string.pref_key_arcore_localization_filtering_speed))==0) pref.setSummary("("+((ListPreference)pref).getEntry() + ") "+getString(R.string.pref_summary_arcore_localization_filtering_speed));
if(key.compareTo(getString(R.string.pref_key_update_rate))==0) pref.setSummary("("+((ListPreference)pref).getEntry() + ") "+getString(R.string.pref_summary_update_rate));
if(key.compareTo(getString(R.string.pref_key_max_speed))==0) pref.setSummary("("+((ListPreference)pref).getEntry() + ") "+getString(R.string.pref_summary_max_speed));
if(key.compareTo(getString(R.string.pref_key_time_thr))==0) pref.setSummary("("+((ListPreference)pref).getEntry() + ") "+getString(R.string.pref_summary_time_thr));

View File

@@ -2,18 +2,33 @@ package com.introlab.rtabmap;
import android.graphics.ImageFormat;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCaptureSession;
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.media.ImageReader;
import android.os.Handler;
import android.os.HandlerThread;
import android.support.annotation.NonNull;
import android.util.Log;
import android.view.Surface;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class TOF_ImageReader implements ImageReader.OnImageAvailableListener {
public int WIDTH;
public int HEIGHT;
public static final String TAG = TOF_ImageReader.class.getSimpleName();
public int WIDTH;
public int HEIGHT;
public ImageReader imageReader;
public int frameCount = 0;
public long timestamp;
@@ -21,16 +36,177 @@ public class TOF_ImageReader implements ImageReader.OnImageAvailableListener {
// Looper handler thread.
private HandlerThread backgroundThread;
// Looper handler.
private Handler backgroundHandler;
public Handler backgroundHandler;
public ByteBuffer depth16_raw;
// Camera capture session.
private CameraCaptureSession captureSession = null;
// Camera device.
private CameraDevice cameraDevice = null;
// Camera preview capture request builder
private CaptureRequest.Builder previewCaptureRequestBuilder;
TOF_ImageReader(){
}
public void close()
{
Log.i(TAG, "close()");
if (captureSession != null) {
captureSession.close();
captureSession = null;
}
if (cameraDevice != null) {
cameraDevice.close();
cameraDevice = null;
}
if (imageReader != null) {
imageReader.close();
imageReader = null;
}
}
// Camera device state callback.
public final CameraDevice.StateCallback cameraDeviceCallback =
new CameraDevice.StateCallback() {
@Override
public void onOpened(@NonNull CameraDevice cameraDevice) {
Log.d(TAG, "Camera depth ID " + cameraDevice.getId() + " opened.");
TOF_ImageReader.this.cameraDevice = cameraDevice;
createCameraPreviewSession();
}
@Override
public void onClosed(@NonNull CameraDevice cameraDevice) {
Log.d(TAG, "Camera device ID " + cameraDevice.getId() + " closed.");
TOF_ImageReader.this.cameraDevice = null;
}
@Override
public void onDisconnected(@NonNull CameraDevice cameraDevice) {
Log.w(TAG, "Camera depth ID " + cameraDevice.getId() + " disconnected.");
cameraDevice.close();
TOF_ImageReader.this.cameraDevice = null;
}
@Override
public void onError(@NonNull CameraDevice cameraDevice, int error) {
Log.e(TAG, "Camera depth ID " + cameraDevice.getId() + " error " + error);
cameraDevice.close();
TOF_ImageReader.this.cameraDevice = null;
}
};
private CameraCaptureSession.StateCallback captureStateCallback = 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.");
}
@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);
}
};
// 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.");
frameCount = 0;
try {
// Create an ARCore compatible capture request using `TEMPLATE_RECORD`.
previewCaptureRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);
previewCaptureRequestBuilder.addTarget(imageReader.getSurface());
// Create camera capture session for camera preview using callback.
cameraDevice.createCaptureSession(Arrays.asList(imageReader.getSurface()), captureStateCallback, backgroundHandler);
} catch (CameraAccessException e) {
Log.e(TAG, "CameraAccessException", e);
}
}
public void createImageReader(int width, int height){
this.WIDTH = width;
this.HEIGHT = height;
Log.w(TAG, String.valueOf(width) + "x" + String.valueOf(height));
WIDTH = width;
HEIGHT = height;
this.imageReader =
ImageReader.newInstance(
width,
@@ -45,18 +221,20 @@ public class TOF_ImageReader implements ImageReader.OnImageAvailableListener {
public void onImageAvailable(ImageReader imageReader) {
Image image = imageReader.acquireLatestImage();
if (image == null) {
Log.w("RTABMapActivity", "onImageAvailable: Skipping null image.");
Log.w(TAG, "onImageAvailable: Skipping null image.");
return;
}
else{
if(image.getFormat() == ImageFormat.DEPTH16){
this.timestamp = image.getTimestamp();
depth16_raw = image.getPlanes()[0].getBuffer().asReadOnlyBuffer();
synchronized (this) {
depth16_raw = image.getPlanes()[0].getBuffer().asReadOnlyBuffer();
timestamp = image.getTimestamp();
}
// copy raw undecoded DEPTH16 format depth data to NativeBuffer
frameCount++;
}
else{
Log.w("RTABMapActivity", "onImageAvailable: depth image not in DEPTH16 format, skipping image");
Log.w(TAG, "onImageAvailable: depth image not in DEPTH16 format, skipping image");
}
}
image.close();
@@ -78,7 +256,7 @@ public class TOF_ImageReader implements ImageReader.OnImageAvailableListener {
this.backgroundThread = null;
this.backgroundHandler = null;
} catch (InterruptedException e) {
Log.e("RTABMapActivity", "Interrupted while trying to join depth background handler thread", e);
Log.e(TAG, "Interrupted while trying to join depth background handler thread", e);
}
}
}

View File

@@ -7,7 +7,11 @@ import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
@@ -55,7 +59,7 @@ public class Util {
}
}
public static String[] loadFileList(String directory, final boolean databasesOnly) {
public static String[] loadFileList(final String directory, final boolean databasesOnly) {
File path = new File(directory);
String fileList[];
try {
@@ -83,6 +87,25 @@ public class Util {
};
fileList = path.list(filter);
Arrays.sort(fileList);
List<String> fileListt = new ArrayList<String>(Arrays.asList(fileList));
Collections.sort(fileListt, new Comparator<String>() {
@Override
public int compare(String filename1, String filename2) {
File file1 = new File(directory+"/"+filename1);
File file2 = new File(directory+"/"+filename2);
long k = file1.lastModified() - file2.lastModified();
if(k > 0){
return -1;
}else if(k == 0){
return 0;
}else{
return 1;
}
}
});
fileListt.toArray(fileList);
}
else {
fileList = new String[0];

68
app/ios/.gitignore vendored Normal file
View File

@@ -0,0 +1,68 @@
# Xcode
#
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
## User settings
xcuserdata/
## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9)
*.xcscmblueprint
*.xccheckout
## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4)
build/
DerivedData/
*.moved-aside
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
## Obj-C/Swift specific
*.hmap
## App packaging
*.ipa
*.dSYM.zip
*.dSYM
# CocoaPods
#
# We recommend against adding the Pods directory to your .gitignore. However
# you should judge for yourself, the pros and cons are mentioned at:
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
#
# Pods/
#
# Add this line if you want to avoid checking in source code from the Xcode workspace
# *.xcworkspace
# Carthage
#
# Add this line if you want to avoid checking in source code from Carthage dependencies.
# Carthage/Checkouts
Carthage/Build/
# fastlane
#
# It is recommended to not store the screenshots in the git repo.
# Instead, use fastlane to re-generate the screenshots whenever they are needed.
# For more information about the recommended setup visit:
# https://docs.fastlane.tools/best-practices/source-control/#source-control
fastlane/report.xml
fastlane/Preview.html
fastlane/screenshots/**/*.png
fastlane/test_output
# Code Injection
#
# After new code Injection tools there's a generated folder /iOSInjectionProject
# https://github.com/johnno1962/injectionforxcode
iOSInjectionProject/

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:">
</FileRef>
</Workspace>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>

View File

@@ -0,0 +1,16 @@
{
"object": {
"pins": [
{
"package": "Zip",
"repositoryURL": "https://github.com/marmelroy/Zip.git",
"state": {
"branch": null,
"revision": "bd19d974e8a38cc8d3a88c90c8a107386c3b8ccf",
"version": "2.1.1"
}
}
]
},
"version": 1
}

View File

@@ -0,0 +1,79 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1230"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "4EE015C1259A2AF0008CCE65"
BuildableName = "RTABMapApp.app"
BlueprintName = "RTABMapApp"
ReferencedContainer = "container:RTABMapApp.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Release"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
enableGPUFrameCaptureMode = "2"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "4EE015C1259A2AF0008CCE65"
BuildableName = "RTABMapApp.app"
BlueprintName = "RTABMapApp"
ReferencedContainer = "container:RTABMapApp.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "4EE015C1259A2AF0008CCE65"
BuildableName = "RTABMapApp.app"
BlueprintName = "RTABMapApp"
ReferencedContainer = "container:RTABMapApp.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

1
app/ios/RTABMapApp/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
Libraries

View File

@@ -0,0 +1,76 @@
//
// AppDelegate.swift
// GLKittutorial
//
// Created by Mathieu Labbe on 2020-12-28.
//
import UIKit
import ARKit
func setDefaultsFromSettingsBundle() {
let plistFiles = ["Root", "Mapping", "Assembling"]
for plistName in plistFiles {
//Read PreferenceSpecifiers from Root.plist in Settings.Bundle
if let settingsURL = Bundle.main.url(forResource: plistName, withExtension: "plist", subdirectory: "Settings.bundle"),
let settingsPlist = NSDictionary(contentsOf: settingsURL),
let preferences = settingsPlist["PreferenceSpecifiers"] as? [NSDictionary] {
for prefSpecification in preferences {
if let key = prefSpecification["Key"] as? String, let value = prefSpecification["DefaultValue"] {
//If key doesn't exists in userDefaults then register it, else keep original value
if UserDefaults.standard.value(forKey: key) == nil {
UserDefaults.standard.set(value, forKey: key)
NSLog("registerDefaultsFromSettingsBundle: Set following to UserDefaults - (key: \(key), value: \(value), type: \(type(of: value)))")
}
}
}
} else {
NSLog("registerDefaultsFromSettingsBundle: Could not find Settings.bundle")
}
}
}
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Always set Version to default
let defaults = UserDefaults.standard
defaults.removeObject(forKey: "Version")
setDefaultsFromSettingsBundle()
// Override point for customization after application launch.
if !ARWorldTrackingConfiguration.supportsFrameSemantics(.sceneDepth) {
// Ensure that the device supports scene depth and present
// an error-message view controller, if not.
let storyboard = UIStoryboard(name: "Main", bundle: nil)
window?.rootViewController = storyboard.instantiateViewController(withIdentifier: "unsupportedDeviceMessage")
}
return true
}
// MARK: UISceneSession Lifecycle
func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
// Called when a new scene session is being created.
// Use this method to select a configuration to create the new scene with.
return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
}
func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
// Called when the user discards a scene session.
// If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
// Use this method to release any resources that were specific to the discarded scenes, as they will not return.
}
}

View File

@@ -0,0 +1,11 @@
{
"colors" : [
{
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -0,0 +1,116 @@
{
"images" : [
{
"filename" : "RTAB-Map40-1.png",
"idiom" : "iphone",
"scale" : "2x",
"size" : "20x20"
},
{
"filename" : "RTAB-Map60.png",
"idiom" : "iphone",
"scale" : "3x",
"size" : "20x20"
},
{
"filename" : "RTAB-Map58-1.png",
"idiom" : "iphone",
"scale" : "2x",
"size" : "29x29"
},
{
"filename" : "RTAB-Map87.png",
"idiom" : "iphone",
"scale" : "3x",
"size" : "29x29"
},
{
"filename" : "RTAB-Map80-1.png",
"idiom" : "iphone",
"scale" : "2x",
"size" : "40x40"
},
{
"filename" : "RTAB-Map120-1.png",
"idiom" : "iphone",
"scale" : "3x",
"size" : "40x40"
},
{
"filename" : "RTAB-Map120.png",
"idiom" : "iphone",
"scale" : "2x",
"size" : "60x60"
},
{
"filename" : "RTAB-Map180.png",
"idiom" : "iphone",
"scale" : "3x",
"size" : "60x60"
},
{
"filename" : "RTAB-Map20.png",
"idiom" : "ipad",
"scale" : "1x",
"size" : "20x20"
},
{
"filename" : "RTAB-Map40.png",
"idiom" : "ipad",
"scale" : "2x",
"size" : "20x20"
},
{
"filename" : "RTAB-Map29.png",
"idiom" : "ipad",
"scale" : "1x",
"size" : "29x29"
},
{
"filename" : "RTAB-Map58.png",
"idiom" : "ipad",
"scale" : "2x",
"size" : "29x29"
},
{
"filename" : "RTAB-Map40-2.png",
"idiom" : "ipad",
"scale" : "1x",
"size" : "40x40"
},
{
"filename" : "RTAB-Map80.png",
"idiom" : "ipad",
"scale" : "2x",
"size" : "40x40"
},
{
"filename" : "RTAB-Map76.png",
"idiom" : "ipad",
"scale" : "1x",
"size" : "76x76"
},
{
"filename" : "RTAB-Map152.png",
"idiom" : "ipad",
"scale" : "2x",
"size" : "76x76"
},
{
"filename" : "RTAB-Map167.png",
"idiom" : "ipad",
"scale" : "2x",
"size" : "83.5x83.5"
},
{
"filename" : "RTAB-Map1024.png",
"idiom" : "ios-marketing",
"scale" : "1x",
"size" : "1024x1024"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 442 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

View File

@@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -0,0 +1,86 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="19455" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<device id="retina6_1" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="19454"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="EHf-IW-A2E">
<objects>
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="DqX-Vd-Tpo" userLabel="ViewButton">
<rect key="frame" x="342" y="799.5" width="52" height="40.5"/>
<constraints>
<constraint firstAttribute="width" constant="52" id="m5V-wG-7GI"/>
<constraint firstAttribute="height" constant="44" id="pbH-yg-ZHL"/>
</constraints>
<color key="tintColor" white="0.33333333333333331" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<state key="normal" backgroundImage="eye" catalog="system">
<color key="titleColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</state>
</button>
<stackView opaque="NO" contentMode="scaleToFill" spacing="20" translatesAutoresizingMaskIntoConstraints="NO" id="Ybb-6v-Prf">
<rect key="frame" x="254" y="64" width="140" height="60"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="qpg-QD-geo" userLabel="LibraryButton">
<rect key="frame" x="0.0" y="1" width="60" height="57.5"/>
<constraints>
<constraint firstAttribute="height" constant="60" id="MMK-i4-ipl"/>
<constraint firstAttribute="width" constant="60" id="MSB-kf-WKH"/>
</constraints>
<color key="tintColor" white="0.33333333333333331" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<state key="normal" backgroundImage="folder" catalog="system">
<color key="titleColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</state>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Xjn-gQ-W57" userLabel="MenuButton">
<rect key="frame" x="80" y="0.5" width="60" height="59"/>
<constraints>
<constraint firstAttribute="height" constant="60" id="h7m-oO-bNI"/>
<constraint firstAttribute="width" constant="60" id="q9I-XS-C8P"/>
</constraints>
<color key="tintColor" white="0.33333333333333331" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<state key="normal" backgroundImage="ellipsis.circle" catalog="system"/>
</button>
</subviews>
</stackView>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="RTAB-Map1024" translatesAutoresizingMaskIntoConstraints="NO" id="TNo-z5-pM0">
<rect key="frame" x="177" y="418" width="60" height="60"/>
<constraints>
<constraint firstAttribute="width" constant="60" id="Lio-4G-f3t"/>
<constraint firstAttribute="height" constant="60" id="Q5D-zG-PAv"/>
</constraints>
</imageView>
</subviews>
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
<color key="backgroundColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstItem="TNo-z5-pM0" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="centerY" id="4fp-du-TTg"/>
<constraint firstItem="Ybb-6v-Prf" firstAttribute="top" secondItem="6Tk-OE-BBY" secondAttribute="top" constant="20" id="Dcs-0a-Uhe"/>
<constraint firstItem="6Tk-OE-BBY" firstAttribute="trailing" secondItem="DqX-Vd-Tpo" secondAttribute="trailing" constant="20" id="TTR-AB-iCr"/>
<constraint firstItem="6Tk-OE-BBY" firstAttribute="trailing" secondItem="Ybb-6v-Prf" secondAttribute="trailing" constant="20" id="YPK-bW-6AC"/>
<constraint firstItem="6Tk-OE-BBY" firstAttribute="bottom" secondItem="DqX-Vd-Tpo" secondAttribute="bottom" constant="20" id="cnW-a0-bhz"/>
<constraint firstItem="TNo-z5-pM0" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="epw-Qw-hdY"/>
</constraints>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="52.173913043478265" y="375"/>
</scene>
</scenes>
<resources>
<image name="RTAB-Map1024" width="591" height="649"/>
<image name="ellipsis.circle" catalog="system" width="128" height="121"/>
<image name="eye" catalog="system" width="128" height="81"/>
<image name="folder" catalog="system" width="128" height="97"/>
</resources>
</document>

View File

@@ -0,0 +1,271 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="19455" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="zah-iI-EPt">
<device id="retina3_5" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="19454"/>
<capability name="Image references" minToolsVersion="12.0"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="System colors in document resources" minToolsVersion="11.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--GLKit View Controller-->
<scene sceneID="1cO-Jt-3GG">
<objects>
<glkViewController preferredFramesPerSecond="30" id="zah-iI-EPt" customClass="ViewController" customModule="RTABMapApp" customModuleProvider="target" sceneMemberID="viewController">
<glkView key="view" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" drawableDepthFormat="24" enableSetNeedsDisplay="NO" id="sqF-4e-2HU">
<rect key="frame" x="0.0" y="0.0" width="320" height="480"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" translatesAutoresizingMaskIntoConstraints="NO" id="kPv-DO-hpd">
<rect key="frame" x="250" y="180" width="60" height="120"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="mJN-Ru-yPg" userLabel="StopButton">
<rect key="frame" x="0.0" y="0.5" width="60" height="59"/>
<constraints>
<constraint firstAttribute="height" constant="60" id="g9J-0P-CmQ"/>
<constraint firstAttribute="width" constant="60" id="m06-eJ-dIn"/>
</constraints>
<color key="tintColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<state key="normal" backgroundImage="stop.circle" catalog="system"/>
<connections>
<action selector="stopAction:" destination="zah-iI-EPt" eventType="touchUpInside" id="3iJ-xb-gzb"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="7Lv-u6-mGh" userLabel="RecordButton">
<rect key="frame" x="0.0" y="60.5" width="60" height="59"/>
<constraints>
<constraint firstAttribute="height" constant="60" id="DQI-eQ-v3X"/>
<constraint firstAttribute="width" constant="60" id="Oeu-YT-wMz"/>
</constraints>
<fontDescription key="fontDescription" type="system" pointSize="18"/>
<color key="tintColor" systemColor="systemRedColor"/>
<inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="0.0" maxY="20"/>
<state key="normal" backgroundImage="record.circle" catalog="system"/>
<connections>
<action selector="recordAction:" destination="zah-iI-EPt" eventType="touchUpInside" id="dzY-yL-YBg"/>
</connections>
</button>
</subviews>
</stackView>
<stackView opaque="NO" contentMode="scaleToFill" spacing="20" translatesAutoresizingMaskIntoConstraints="NO" id="ozY-dg-YOd">
<rect key="frame" x="160" y="20" width="140" height="60"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="9kh-4C-KyP" userLabel="LibraryButton">
<rect key="frame" x="0.0" y="1" width="60" height="57.5"/>
<constraints>
<constraint firstAttribute="width" constant="60" id="Ekq-3J-kUL"/>
<constraint firstAttribute="height" constant="60" id="fqe-e7-0uk"/>
</constraints>
<color key="tintColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<state key="normal" backgroundImage="folder" catalog="system">
<color key="titleColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</state>
<connections>
<action selector="libraryAction:" destination="zah-iI-EPt" eventType="touchUpInside" id="WOh-uA-T5h"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="y53-OI-O76" userLabel="MenuButton">
<rect key="frame" x="80" y="0.5" width="60" height="59"/>
<constraints>
<constraint firstAttribute="height" constant="60" id="L5T-8h-ale"/>
<constraint firstAttribute="width" constant="60" id="pLI-ns-KHQ"/>
</constraints>
<color key="tintColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<state key="normal" backgroundImage="ellipsis.circle" catalog="system"/>
</button>
</subviews>
</stackView>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="wordWrap" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="KlF-4H-k6I">
<rect key="frame" x="16" y="20" width="31" height="14.5"/>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.29820365646258501" colorSpace="custom" customColorSpace="sRGB"/>
<fontDescription key="fontDescription" type="system" pointSize="12"/>
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
</label>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="773-n4-lob" userLabel="ViewButton">
<rect key="frame" x="248" y="417.5" width="52" height="40.5"/>
<constraints>
<constraint firstAttribute="width" constant="52" id="epT-x2-WRc"/>
<constraint firstAttribute="height" constant="44" id="wAe-I1-qhs"/>
</constraints>
<color key="tintColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<state key="normal" backgroundImage="eye" catalog="system">
<color key="titleColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</state>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="012-W3-dOS" userLabel="CloseVisualization">
<rect key="frame" x="75" y="434" width="170.5" height="22"/>
<color key="tintColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<state key="normal" title="Close Visualization" image="xmark.square" catalog="system">
<color key="titleColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</state>
<connections>
<action selector="closeVisualizationAction:" destination="zah-iI-EPt" eventType="touchUpInside" id="DqP-oy-XPe"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="9oq-op-NGV" userLabel="StopCamera">
<rect key="frame" x="98" y="433" width="124.5" height="22"/>
<color key="tintColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<state key="normal" title="Stop Camera" image="xmark.square" catalog="system">
<color key="titleColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</state>
<connections>
<action selector="stopCameraAction:" destination="zah-iI-EPt" eventType="touchUpInside" id="YZq-pZ-8Te"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleAspectFit" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Jj4-ow-MwD" userLabel="NewScanButtonLarge">
<rect key="frame" x="73.5" y="224" width="173" height="32"/>
<color key="tintColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<state key="normal" title="Start the Camera">
<color key="titleColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<imageReference key="image" image="plus.app" catalog="system" symbolScale="large"/>
<preferredSymbolConfiguration key="preferredSymbolConfiguration" configurationType="font">
<fontDescription key="fontDescription" style="UICTFontTextStyleTitle1"/>
</preferredSymbolConfiguration>
</state>
<connections>
<action selector="newScanAction:" destination="zah-iI-EPt" eventType="touchUpInside" id="jL9-xF-V9K"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="3Sc-lx-YKH">
<rect key="frame" x="161" y="96" width="149" height="22"/>
<color key="tintColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<state key="normal" title="Export OBJ-PLY" image="square.and.arrow.up" catalog="system"/>
<connections>
<action selector="exportOBJPLYAction:" destination="zah-iI-EPt" eventType="touchUpInside" id="md0-pv-zlf"/>
</connections>
</button>
<slider opaque="NO" contentMode="scaleToFill" placeholderIntrinsicWidth="114" placeholderIntrinsicHeight="30" contentHorizontalAlignment="center" contentVerticalAlignment="center" value="80" minValue="0.0" maxValue="120" translatesAutoresizingMaskIntoConstraints="NO" id="30J-Tx-NRW" userLabel="OrthoClipDistanceSlider">
<rect key="frame" x="-2" y="344" width="122" height="31"/>
<constraints>
<constraint firstAttribute="width" constant="118" id="dsv-im-K52"/>
</constraints>
<connections>
<action selector="clipDistanceAction:" destination="zah-iI-EPt" eventType="valueChanged" id="iKj-nz-0KW"/>
</connections>
</slider>
<slider opaque="NO" contentMode="scaleToFill" placeholderIntrinsicWidth="114" placeholderIntrinsicHeight="30" contentHorizontalAlignment="center" contentVerticalAlignment="center" value="90" minValue="0.0" maxValue="180" translatesAutoresizingMaskIntoConstraints="NO" id="Z1x-Af-hdf" userLabel="GridRotationSlider">
<rect key="frame" x="99" y="389" width="122" height="31"/>
<constraints>
<constraint firstAttribute="width" constant="118" id="KDl-lP-Jj7"/>
</constraints>
<connections>
<action selector="rotateGridAction:" destination="zah-iI-EPt" eventType="valueChanged" id="eiC-QR-TYH"/>
</connections>
</slider>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Toast Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="JMv-UE-cvK" userLabel="ToastLabel">
<rect key="frame" x="116.5" y="330" width="87.5" height="20.5"/>
<color key="backgroundColor" white="0.0" alpha="0.3002232142857143" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<accessibility key="accessibilityConfiguration">
<accessibilityTraits key="traits" staticText="YES" notEnabled="YES"/>
</accessibility>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<viewLayoutGuide key="safeArea" id="qAR-pI-uT2"/>
<constraints>
<constraint firstItem="KlF-4H-k6I" firstAttribute="leading" secondItem="qAR-pI-uT2" secondAttribute="leading" constant="16" id="14l-HO-Yqo"/>
<constraint firstItem="kPv-DO-hpd" firstAttribute="centerY" secondItem="sqF-4e-2HU" secondAttribute="centerY" id="4S8-5c-tBm"/>
<constraint firstItem="KlF-4H-k6I" firstAttribute="top" secondItem="qAR-pI-uT2" secondAttribute="top" constant="20" id="CS3-Rk-Wxs"/>
<constraint firstItem="012-W3-dOS" firstAttribute="centerX" secondItem="sqF-4e-2HU" secondAttribute="centerX" id="IsC-yB-kNs"/>
<constraint firstItem="qAR-pI-uT2" firstAttribute="trailing" secondItem="773-n4-lob" secondAttribute="trailing" constant="20" id="N8s-Yg-VsL"/>
<constraint firstItem="JMv-UE-cvK" firstAttribute="centerX" secondItem="sqF-4e-2HU" secondAttribute="centerX" id="NIf-UH-gZ7"/>
<constraint firstItem="qAR-pI-uT2" firstAttribute="bottom" secondItem="773-n4-lob" secondAttribute="bottom" constant="20" id="O9t-O0-69d"/>
<constraint firstItem="Jj4-ow-MwD" firstAttribute="centerX" secondItem="sqF-4e-2HU" secondAttribute="centerX" id="OLx-LR-8xj"/>
<constraint firstItem="012-W3-dOS" firstAttribute="top" secondItem="Z1x-Af-hdf" secondAttribute="bottom" constant="15" id="RpS-k0-btM"/>
<constraint firstItem="ozY-dg-YOd" firstAttribute="top" secondItem="qAR-pI-uT2" secondAttribute="top" constant="20" id="TFT-we-noh"/>
<constraint firstItem="30J-Tx-NRW" firstAttribute="leading" secondItem="sqF-4e-2HU" secondAttribute="leading" id="ZBG-GX-P1X"/>
<constraint firstItem="3Sc-lx-YKH" firstAttribute="top" secondItem="ozY-dg-YOd" secondAttribute="bottom" constant="16" id="abR-Tj-Nua"/>
<constraint firstItem="qAR-pI-uT2" firstAttribute="bottom" secondItem="012-W3-dOS" secondAttribute="bottom" constant="24" id="dcl-mV-bH1"/>
<constraint firstItem="9oq-op-NGV" firstAttribute="centerX" secondItem="sqF-4e-2HU" secondAttribute="centerX" id="g5b-gW-Amg"/>
<constraint firstItem="Z1x-Af-hdf" firstAttribute="centerX" secondItem="sqF-4e-2HU" secondAttribute="centerX" id="i2j-zQ-m1V"/>
<constraint firstItem="Z1x-Af-hdf" firstAttribute="top" secondItem="JMv-UE-cvK" secondAttribute="bottom" constant="38.5" id="icg-DR-ZpX"/>
<constraint firstItem="qAR-pI-uT2" firstAttribute="bottom" secondItem="9oq-op-NGV" secondAttribute="bottom" constant="25" id="lFI-66-D3N"/>
<constraint firstAttribute="trailing" secondItem="kPv-DO-hpd" secondAttribute="trailing" constant="10" id="lFv-p3-LIS"/>
<constraint firstItem="qAR-pI-uT2" firstAttribute="trailing" secondItem="ozY-dg-YOd" secondAttribute="trailing" constant="20" id="ov4-d2-OMy"/>
<constraint firstItem="012-W3-dOS" firstAttribute="top" secondItem="30J-Tx-NRW" secondAttribute="bottom" constant="60" id="tbj-nG-nfI"/>
<constraint firstItem="qAR-pI-uT2" firstAttribute="trailing" secondItem="3Sc-lx-YKH" secondAttribute="trailing" constant="10" id="v2K-Dp-Kyn"/>
<constraint firstItem="Jj4-ow-MwD" firstAttribute="centerY" secondItem="sqF-4e-2HU" secondAttribute="centerY" id="vmc-4u-BtF"/>
</constraints>
<connections>
<outlet property="delegate" destination="zah-iI-EPt" id="zXM-3t-Cw4"/>
</connections>
</glkView>
<connections>
<outlet property="closeVisualizationButton" destination="012-W3-dOS" id="qSV-q9-eOP"/>
<outlet property="exportOBJPLYButton" destination="3Sc-lx-YKH" id="ZvS-VQ-nsg"/>
<outlet property="libraryButton" destination="9kh-4C-KyP" id="Mvv-uQ-kmi"/>
<outlet property="menuButton" destination="y53-OI-O76" id="v3g-JB-SsY"/>
<outlet property="newScanButtonLarge" destination="Jj4-ow-MwD" id="0Hv-3K-Xjh"/>
<outlet property="orthoDistanceSlider" destination="30J-Tx-NRW" id="4J1-8u-tDY"/>
<outlet property="orthoGridSlider" destination="Z1x-Af-hdf" id="Zsn-xz-jn0"/>
<outlet property="recordButton" destination="7Lv-u6-mGh" id="xTu-EK-FH2"/>
<outlet property="statusLabel" destination="KlF-4H-k6I" id="NmA-K5-UOw"/>
<outlet property="stopButton" destination="mJN-Ru-yPg" id="DND-gz-jLg"/>
<outlet property="stopCameraButton" destination="9oq-op-NGV" id="sxO-jc-luC"/>
<outlet property="toastLabel" destination="JMv-UE-cvK" id="9a7-QF-h02"/>
<outlet property="viewButton" destination="773-n4-lob" id="deU-Na-mBk"/>
</connections>
</glkViewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="plN-WG-seA" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="-234.375" y="-586.25"/>
</scene>
<!--Unsupported View Controller-->
<scene sceneID="sJB-xy-u63">
<objects>
<viewController storyboardIdentifier="unsupportedDeviceMessage" id="v3G-nW-gVc" userLabel="Unsupported View Controller" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="hzM-1k-POo">
<rect key="frame" x="0.0" y="0.0" width="320" height="480"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Unsupported Device" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" enabled="NO" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="kZt-ct-4KD">
<rect key="frame" x="21.5" y="165" width="277.5" height="30"/>
<fontDescription key="fontDescription" style="UICTFontTextStyleTitle1"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" enabled="NO" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="4Js-Hw-3QU">
<rect key="frame" x="21.5" y="203" width="277.5" height="74"/>
<string key="text">This sample app requires a LiDAR-capable device, such as the second-generation iPad Pro 11-inch and fourth-generation iPad Pro 12.9-inch.</string>
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<viewLayoutGuide key="safeArea" id="Wfl-Ts-arS"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<constraints>
<constraint firstItem="kZt-ct-4KD" firstAttribute="centerX" secondItem="hzM-1k-POo" secondAttribute="centerX" id="5BV-Ql-eBq"/>
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="4Js-Hw-3QU" secondAttribute="trailing" constant="20" symbolic="YES" id="5Sg-eL-Yhf"/>
<constraint firstItem="4Js-Hw-3QU" firstAttribute="centerY" secondItem="hzM-1k-POo" secondAttribute="centerY" id="M1k-d1-BNV"/>
<constraint firstItem="4Js-Hw-3QU" firstAttribute="top" secondItem="kZt-ct-4KD" secondAttribute="bottom" constant="8" symbolic="YES" id="PjQ-ik-Z1B"/>
<constraint firstItem="kZt-ct-4KD" firstAttribute="width" secondItem="4Js-Hw-3QU" secondAttribute="width" id="aQe-nl-Pyq"/>
<constraint firstItem="4Js-Hw-3QU" firstAttribute="centerX" secondItem="hzM-1k-POo" secondAttribute="centerX" id="cww-hm-oLb"/>
<constraint firstItem="4Js-Hw-3QU" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="hzM-1k-POo" secondAttribute="leading" constant="20" symbolic="YES" id="jfM-fP-rth"/>
</constraints>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="jam-V0-csO" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="476" y="-586"/>
</scene>
</scenes>
<resources>
<image name="ellipsis.circle" catalog="system" width="128" height="121"/>
<image name="eye" catalog="system" width="128" height="81"/>
<image name="folder" catalog="system" width="128" height="97"/>
<image name="plus.app" catalog="system" width="128" height="114"/>
<image name="record.circle" catalog="system" width="128" height="121"/>
<image name="square.and.arrow.up" catalog="system" width="115" height="128"/>
<image name="stop.circle" catalog="system" width="128" height="121"/>
<image name="xmark.square" catalog="system" width="128" height="114"/>
<systemColor name="systemRedColor">
<color red="1" green="0.23137254901960785" blue="0.18823529411764706" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</systemColor>
</resources>
</document>

View File

@@ -0,0 +1,186 @@
/**
* Copyright (c) 2017 Razeware LLC
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
* distribute, sublicense, create a derivative work, and/or sell copies of the
* Software in any work that is designed, intended, or marketed for pedagogical or
* instructional purposes related to programming, coding, application development,
* or information technology. Permission for such use, copying, modification,
* merger, publication, distribution, sublicensing, creation of derivative works,
* or sale is expressly withheld.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
import UIKit
protocol DatabaseViewDelegate: class {
func databaseShared(databaseURL: URL)
func databaseRenamed(databaseURL: URL)
func databaseDeleted(databaseURL: URL)
}
class DatabaseView: UIView {
private var coverImageView: UIImageView!
private var indicatorView: UIActivityIndicatorView!
private var valueObservation: NSKeyValueObservation!
private var textLabel: UILabel!
private var databaseURL: URL!
public var delegate: DatabaseViewDelegate!
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commonInit(databasePath: "NA")
}
init(frame: CGRect, databaseURL: URL) {
super.init(frame: frame)
self.databaseURL = databaseURL
commonInit(databasePath: databaseURL.path)
DispatchQueue.global().async {
let downloadedImage = getPreviewImage(databasePath: databaseURL.path)
DispatchQueue.main.async {
self.coverImageView.image = downloadedImage
}
}
}
private func commonInit(databasePath: String) {
// Setup the background
backgroundColor = .black
// Create the cover image view
coverImageView = UIImageView()
coverImageView.translatesAutoresizingMaskIntoConstraints = false
valueObservation = coverImageView.observe(\.image, options: [.new]) { [unowned self] observed, change in
if change.newValue is UIImage {
self.indicatorView.stopAnimating()
}
}
//Text Label
textLabel = UILabel()
textLabel.numberOfLines = 0
textLabel.text =
URL(fileURLWithPath: databasePath).lastPathComponent + "\n" +
URL(fileURLWithPath: databasePath).fileSizeString + "\n" +
(try! URL(fileURLWithPath: databasePath).resourceValues(forKeys: [.contentModificationDateKey]).contentModificationDate!.getFormattedDate(format: "yyyy-MM-dd HH:mm:ss"))
textLabel.textColor = .white
textLabel.textAlignment = .left
//Stack View
let stackView = UIStackView()
stackView.axis = NSLayoutConstraint.Axis.horizontal
stackView.distribution = UIStackView.Distribution.fill
stackView.alignment = UIStackView.Alignment.center
stackView.spacing = 8.0
stackView.addArrangedSubview(coverImageView)
stackView.addArrangedSubview(textLabel)
stackView.translatesAutoresizingMaskIntoConstraints = false
addSubview(stackView)
// Create the indicator view
indicatorView = UIActivityIndicatorView()
indicatorView.translatesAutoresizingMaskIntoConstraints = false
indicatorView.style = .whiteLarge
indicatorView.startAnimating()
addSubview(indicatorView)
NSLayoutConstraint.activate([
stackView.leftAnchor.constraint(equalTo: self.leftAnchor),
stackView.rightAnchor.constraint(equalTo: self.rightAnchor),
stackView.topAnchor.constraint(equalTo: self.topAnchor),
stackView.bottomAnchor.constraint(equalTo: self.bottomAnchor),
stackView.leadingAnchor.constraint(equalTo: self.leadingAnchor),
coverImageView.widthAnchor.constraint(equalToConstant: 180 - 5),
indicatorView.centerXAnchor.constraint(equalTo: coverImageView.centerXAnchor),
indicatorView.centerYAnchor.constraint(equalTo: coverImageView.centerYAnchor)
])
let interaction = UIContextMenuInteraction(delegate: self)
self.addInteraction(interaction)
}
func highlightDatabase(_ didHighlightView: Bool) {
if didHighlightView == true {
backgroundColor = .white
textLabel.textColor = .black
} else {
backgroundColor = .black
textLabel.textColor = .white
}
}
}
extension URL {
var attributes: [FileAttributeKey : Any]? {
do {
return try FileManager.default.attributesOfItem(atPath: path)
} catch let error as NSError {
print("FileAttribute error: \(error)")
}
return nil
}
var fileSize: UInt64 {
return attributes?[.size] as? UInt64 ?? UInt64(0)
}
var fileSizeString: String {
return ByteCountFormatter.string(fromByteCount: Int64(fileSize), countStyle: .file)
}
var creationDate: Date? {
return attributes?[.creationDate] as? Date
}
}
extension DatabaseView: UIContextMenuInteractionDelegate {
func contextMenuInteraction(_ interaction: UIContextMenuInteraction, configurationForMenuAtLocation location: CGPoint) -> UIContextMenuConfiguration? {
return UIContextMenuConfiguration(identifier: nil, previewProvider: nil) { suggestedActions in
// Create an action for sharing
let share = UIAction(title: "Share", image: UIImage(systemName: "square.and.arrow.up")) { action in
// Show system share sheet
self.delegate?.databaseShared(databaseURL: self.databaseURL)
}
// Create an action for renaming
let rename = UIAction(title: "Rename", image: UIImage(systemName: "square.and.pencil")) { action in
// Perform renaming
self.delegate?.databaseRenamed(databaseURL: self.databaseURL)
}
// Here we specify the "destructive" attribute to show that its destructive in nature
let delete = UIAction(title: "Delete", image: UIImage(systemName: "trash"), attributes: .destructive) { action in
// Perform delete
self.delegate?.databaseDeleted(databaseURL: self.databaseURL)
}
// Create and return a UIMenu with all of the actions as children
return UIMenu(title: "", children: [share, rename, delete])
}
}
}

View File

@@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -0,0 +1,21 @@
{
"images" : [
{
"filename" : "RTAB-Map1024.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

View File

@@ -0,0 +1,80 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIcons</key>
<dict/>
<key>CFBundleIcons~ipad</key>
<dict/>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>RTAB-Map</string>
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>$(MARKETING_VERSION)</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>LSSupportsOpeningDocumentsInPlace</key>
<true/>
<key>NSCameraUsageDescription</key>
<string>The camera is used for scanning (ideally with LiDAR).</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>The GPS is used when GPS option is enabled in Settings-&gt;Mapping...</string>
<key>UIApplicationSceneManifest</key>
<dict>
<key>UIApplicationSupportsMultipleScenes</key>
<false/>
<key>UISceneConfigurations</key>
<dict>
<key>UIWindowSceneSessionRoleApplication</key>
<array>
<dict>
<key>UISceneConfigurationName</key>
<string>Default Configuration</string>
<key>UISceneDelegateClassName</key>
<string>$(PRODUCT_MODULE_NAME).SceneDelegate</string>
<key>UISceneStoryboardFile</key>
<string>Main</string>
</dict>
</array>
</dict>
</dict>
<key>UIApplicationSupportsIndirectInputEvents</key>
<true/>
<key>UIFileSharingEnabled</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
<string>opengles-2</string>
<string>arkit</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
</dict>
</plist>

View File

@@ -0,0 +1,621 @@
//
// PCLWrapper.cpp
// ThreeDScanner
//
// Created by Steven Roach on 2/9/18.
// Copyright © 2018 Steven Roach. All rights reserved.
//
#include "NativeWrapper.hpp"
#include "RTABMapApp.h"
#include <rtabmap/core/DBDriverSqlite3.h>
inline RTABMapApp *native(const void *object) {
return (RTABMapApp *)object;
}
const void * createNativeApplication()
{
RTABMapApp *app = new RTABMapApp();
return (void *)app;
}
void setupCallbacksNative(const void *object, void * classPtr,
void(*progressCallback)(void*, int, int),
void(*initCallback)(void *, int, const char*),
void(*statsUpdatedCallback)(void *,
int, int, int, int,
float,
int, int, int, int, int ,int,
float,
int,
float,
int,
float, float, float, float,
int, int,
float, float, float, float, float, float))
{
if(object)
{
native(object)->setupSwiftCallbacks(classPtr, progressCallback, initCallback, statsUpdatedCallback);
}
else
{
UERROR("object is null!");
}
}
void destroyNativeApplication(const void *object)
{
if(object)
{
delete native(object);
}
else
{
UERROR("object is null!");
}
}
void setScreenRotationNative(const void *object, int displayRotation)
{
if(object)
{
return native(object)->setScreenRotation(displayRotation, 0);
}
else
{
UERROR("object is null!");
}
}
int openDatabaseNative(const void *object, const char * databasePath, bool databaseInMemory, bool optimize, bool clearDatabase)
{
if(object)
{
return native(object)->openDatabase(databasePath, databaseInMemory, optimize, clearDatabase);
}
else
{
UERROR("object is null!");
return -1;
}
}
void saveNative(const void *object, const char * databasePath)
{
if(object)
{
return native(object)->save(databasePath);
}
else
{
UERROR("object is null!");
}
}
bool recoverNative(const void *object, const char * from, const char * to)
{
if(object)
{
return native(object)->recover(from, to);
}
else
{
UERROR("object is null!");
}
return false;
}
void cancelProcessingNative(const void *object)
{
if(object)
{
native(object)->cancelProcessing();
}
else
{
UERROR("object is null!");
}
}
int postProcessingNative(const void *object, int approach)
{
if(object)
{
return native(object)->postProcessing(approach);
}
else
{
UERROR("object is null!");
}
return -1;
}
bool exportMeshNative(
const void *object,
float cloudVoxelSize,
bool regenerateCloud,
bool meshing,
int textureSize,
int textureCount,
int normalK,
bool optimized,
float optimizedVoxelSize,
int optimizedDepth,
int optimizedMaxPolygons,
float optimizedColorRadius,
bool optimizedCleanWhitePolygons,
int optimizedMinClusterSize,
float optimizedMaxTextureDistance,
int optimizedMinTextureClusterSize,
bool blockRendering)
{
if(object)
{
return native(object)->exportMesh(cloudVoxelSize, regenerateCloud, meshing, textureSize, textureCount, normalK, optimized, optimizedVoxelSize, optimizedDepth, optimizedMaxPolygons, optimizedColorRadius, optimizedCleanWhitePolygons, optimizedMinClusterSize, optimizedMaxTextureDistance, optimizedMinTextureClusterSize, blockRendering);
}
else
{
UERROR("object is null!");
}
return false;
}
bool postExportationNative(const void *object, bool visualize)
{
if(object)
{
return native(object)->postExportation(visualize);
}
else
{
UERROR("object is null!");
}
return false;
}
bool writeExportedMeshNative(const void *object, const char * directory, const char * name)
{
if(object)
{
return native(object)->writeExportedMesh(directory, name);
}
else
{
UERROR("object is null!");
}
return false;
}
void initGlContentNative(const void *object) {
if(object)
{
native(object)->InitializeGLContent();
}
else
{
UERROR("object is null!");
}
}
void setupGraphicNative(const void *object, int width, int height) {
if(object)
{
native(object)->SetViewPort(width, height);
}
else
{
UERROR("object is null!");
}
}
void onTouchEventNative(const void *object, int touch_count, int event, float x0, float y0, float x1,
float y1) {
if(object)
{
using namespace tango_gl;
GestureCamera::TouchEvent touch_event =
static_cast<GestureCamera::TouchEvent>(event);
native(object)->OnTouchEvent(touch_count, touch_event, x0, y0, x1, y1);
}
else
{
UERROR("object is null!");
}
}
void setPausedMappingNative(const void *object, bool paused)
{
if(object)
{
return native(object)->setPausedMapping(paused);
}
else
{
UERROR("object is null!");
}
}
int renderNative(const void *object) {
if(object)
{
return native(object)->Render();
}
else
{
UERROR("object is null!");
return -1;
}
}
bool startCameraNative(const void *object) {
if(object)
{
return native(object)->startCamera();
}
else
{
UERROR("object is null!");
return false;
}
}
void stopCameraNative(const void *object) {
if(object)
{
native(object)->stopCamera();
}
else
{
UERROR("object is null!");
}
}
void setCameraNative(const void *object, int type) {
if(object)
{
native(object)->SetCameraType(tango_gl::GestureCamera::CameraType(type));
}
else
{
UERROR("object is null!");
}
}
void postCameraPoseEventNative(const void *object,
float x, float y, float z, float qx, float qy, float qz, float qw)
{
if(object)
{
native(object)->postCameraPoseEvent(x,y,z,qx,qy,qz,qw,0.0);
}
else
{
UERROR("object is null!");
return;
}
}
void postOdometryEventNative(const void *object,
float x, float y, float z, float qx, float qy, float qz, float qw,
float fx, float fy, float cx, float cy,
double stamp,
const void * yPlane, const void * uPlane, const void * vPlane, int yPlaneLen, int rgbWidth, int rgbHeight, int rgbFormat,
const void * depth, int depthLen, int depthWidth, int depthHeight, int depthFormat,
const void * conf, int confLen, int confWidth, int confHeight, int confFormat,
const void * points, int pointsLen, int pointsChannels,
float vx, float vy, float vz, float vqx, float vqy, float vqz, float vqw,
float p00, float p11, float p02, float p12, float p22, float p32, float p23,
float t0, float t1, float t2, float t3, float t4, float t5, float t6, float t7)
{
if(object)
{
native(object)->postOdometryEvent(
rtabmap::Transform(x,y,z,qx,qy,qz,qw),
fx,fy,cx,cy, 0,0,0,0,
rtabmap::Transform(), rtabmap::Transform(),
stamp, 0,
yPlane, uPlane, vPlane, yPlaneLen, rgbWidth, rgbHeight, rgbFormat,
depth, depthLen, depthWidth, depthHeight, depthFormat,
conf, confLen, confWidth, confHeight, confFormat,
(const float *)points, pointsLen, pointsChannels,
rtabmap::Transform(vx, vy, vz, vqx, vqy, vqz, vqw),
p00, p11, p02, p12, p22, p32, p23,
t0, t1, t2, t3, t4, t5, t6, t7);
}
else
{
UERROR("object is null!");
return;
}
}
ImageNative getPreviewImageNative(const char * databasePath)
{
ImageNative imageNative;
imageNative.data = 0;
imageNative.objectPtr = 0;
rtabmap::DBDriverSqlite3 driver;
if(driver.openConnection(databasePath))
{
cv::Mat image = driver.loadPreviewImage();
if(image.empty())
{
return imageNative;
}
cv::Mat * imagePtr = new cv::Mat();
// We should add alpha channel
cv::cvtColor(image, *imagePtr, cv::COLOR_BGR2BGRA);
std::vector<cv::Mat> channels;
cv::split(*imagePtr, channels);
channels.back() = cv::Scalar(255);
cv::merge(channels, *imagePtr);
imageNative.objectPtr = imagePtr;
imageNative.data = imagePtr->data;
imageNative.width = imagePtr->cols;
imageNative.height = imagePtr->rows;
imageNative.channels = imagePtr->channels();
}
return imageNative;
}
void releasePreviewImageNative(ImageNative image)
{
if(image.objectPtr)
{
delete (cv::Mat*)image.objectPtr;
}
}
// Parameters
void setOnlineBlendingNative(const void *object, bool enabled)
{
if(object)
native(object)->setOnlineBlending(enabled);
else
UERROR("object is null!");
}
void setMapCloudShownNative(const void *object, bool shown)
{
if(object)
native(object)->setMapCloudShown(shown);
else
UERROR("object is null!");
}
void setOdomCloudShownNative(const void *object, bool shown)
{
if(object)
native(object)->setOdomCloudShown(shown);
else
UERROR("object is null!");
}
void setMeshRenderingNative(const void *object, bool enabled, bool withTexture)
{
if(object)
native(object)->setMeshRendering(enabled, withTexture);
else
UERROR("object is null!");
}
void setPointSizeNative(const void *object, float value)
{
if(object)
native(object)->setPointSize(value);
else
UERROR("object is null!");
}
void setFOVNative(const void *object, float angle)
{
if(object)
native(object)->setFOV(angle);
else
UERROR("object is null!");
}
void setOrthoCropFactorNative(const void *object, float value)
{
if(object)
native(object)->setOrthoCropFactor(value);
else
UERROR("object is null!");
}
void setGridRotationNative(const void *object, float value)
{
if(object)
native(object)->setGridRotation(value);
else
UERROR("object is null!");
}
void setLightingNative(const void *object, bool enabled)
{
if(object)
native(object)->setLighting(enabled);
else
UERROR("object is null!");
}
void setBackfaceCullingNative(const void *object, bool enabled)
{
if(object)
native(object)->setBackfaceCulling(enabled);
else
UERROR("object is null!");
}
void setWireframeNative(const void *object, bool enabled)
{
if(object)
native(object)->setWireframe(enabled);
else
UERROR("object is null!");
}
void setLocalizationModeNative(const void *object, bool enabled)
{
if(object)
native(object)->setLocalizationMode(enabled);
else
UERROR("object is null!");
}
void setTrajectoryModeNative(const void *object, bool enabled)
{
if(object)
native(object)->setTrajectoryMode(enabled);
else
UERROR("object is null!");
}
void setGraphOptimizationNative(const void *object, bool enabled)
{
if(object)
native(object)->setGraphOptimization(enabled);
else
UERROR("object is null!");
}
void setNodesFilteringNative(const void *object, bool enabled)
{
if(object)
native(object)->setNodesFiltering(enabled);
else
UERROR("object is null!");
}
void setGraphVisibleNative(const void *object, bool visible)
{
if(object)
native(object)->setGraphVisible(visible);
else
UERROR("object is null!");
}
void setGridVisibleNative(const void *object, bool visible)
{
if(object)
native(object)->setGridVisible(visible);
else
UERROR("object is null!");
}
void setRawScanSavedNative(const void *object, bool enabled)
{
if(object)
native(object)->setRawScanSaved(enabled);
else
UERROR("object is null!");
}
void setFullResolutionNative(const void *object, bool enabled)
{
if(object)
native(object)->setFullResolution(enabled);
else
UERROR("object is null!");
}
void setSmoothingNative(const void *object, bool enabled)
{
if(object)
native(object)->setSmoothing(enabled);
else
UERROR("object is null!");
}
void setAppendModeNative(const void *object, bool enabled)
{
if(object)
native(object)->setAppendMode(enabled);
else
UERROR("object is null!");
}
void setMaxCloudDepthNative(const void *object, float value)
{
if(object)
native(object)->setMaxCloudDepth(value);
else
UERROR("object is null!");
}
void setMinCloudDepthNative(const void *object, float value)
{
if(object)
native(object)->setMinCloudDepth(value);
else
UERROR("object is null!");
}
void setCloudDensityLevelNative(const void *object, int value)
{
if(object)
native(object)->setCloudDensityLevel(value);
else
UERROR("object is null!");
}
void setMeshAngleToleranceNative(const void *object, float value)
{
if(object)
native(object)->setMeshAngleTolerance(value);
else
UERROR("object is null!");
}
void setMeshDecimationFactorNative(const void *object, float value)
{
if(object)
native(object)->setMeshDecimationFactor(value);
else
UERROR("object is null!");
}
void setMeshTriangleSizeNative(const void *object, int value)
{
if(object)
native(object)->setMeshTriangleSize(value);
else
UERROR("object is null!");
}
void setClusterRatioNative(const void *object, float value)
{
if(object)
native(object)->setClusterRatio(value);
else
UERROR("object is null!");
}
void setMaxGainRadiusNative(const void *object, float value)
{
if(object)
native(object)->setMaxGainRadius(value);
else
UERROR("object is null!");
}
void setRenderingTextureDecimationNative(const void *object, int value)
{
if(object)
native(object)->setRenderingTextureDecimation(value);
else
UERROR("object is null!");
}
void setBackgroundColorNative(const void *object, float gray)
{
if(object)
native(object)->setBackgroundColor(gray);
else
UERROR("object is null!");
}
void setDepthConfidenceNative(const void *object, int value)
{
if(object)
native(object)->setDepthConfidence(value);
else
UERROR("object is null!");
}
int setMappingParameterNative(const void *object, const char * key, const char * value)
{
if(object)
return native(object)->setMappingParameter(key, value);
else
UERROR("object is null!");
return -1;
}
void setGPSNative(const void *object, double stamp, double longitude, double latitude, double altitude, double accuracy, double bearing)
{
rtabmap::GPS gps(stamp, longitude, latitude, altitude, accuracy, bearing);
if(object)
return native(object)->setGPS(gps);
else
UERROR("object is null!");
}
void addEnvSensorNative(const void *object, int type, float value)
{
if(object)
return native(object)->addEnvSensor(type, value);
else
UERROR("object is null!");
}

View File

@@ -0,0 +1,137 @@
//
// PCLWrapper.hpp
// ThreeDScanner
//
// Created by Steven Roach on 2/9/18.
// Copyright © 2018 Steven Roach. All rights reserved.
//
#ifndef NativeWrapper_hpp
#define NativeWrapper_hpp
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
const void *createNativeApplication();
void setupCallbacksNative(const void *object, void * classPtr,
void(*progressCallback)(void*, int, int),
void(*initCallback)(void *, int, const char*),
void(*statsUpdatedCallback)(void *,
int, int, int, int,
float,
int, int, int, int, int ,int,
float,
int,
float,
int,
float, float, float, float,
int, int,
float, float, float, float, float, float));
void destroyNativeApplication(const void *object);
void setScreenRotationNative(const void *object, int displayRotation);
int openDatabaseNative(const void *object, const char * databasePath, bool databaseInMemory, bool optimize, bool clearDatabase);
void saveNative(const void *object, const char * databasePath);
bool recoverNative(const void *object, const char * from, const char * to);
void cancelProcessingNative(const void * object);
int postProcessingNative(const void *object, int approach);
bool exportMeshNative(
const void *object,
float cloudVoxelSize,
bool regenerateCloud,
bool meshing,
int textureSize,
int textureCount,
int normalK,
bool optimized,
float optimizedVoxelSize,
int optimizedDepth,
int optimizedMaxPolygons,
float optimizedColorRadius,
bool optimizedCleanWhitePolygons,
int optimizedMinClusterSize,
float optimizedMaxTextureDistance,
int optimizedMinTextureClusterSize,
bool blockRendering);
bool postExportationNative(const void *object, bool visualize);
bool writeExportedMeshNative(const void *object, const char * directory, const char * name);
void initGlContentNative(const void *object);
void setupGraphicNative(const void *object, int width, int height);
void onTouchEventNative(const void *object, int touch_count, int event, float x0, float y0, float x1,
float y1);
void setPausedMappingNative(const void *object, bool paused);
int renderNative(const void *object);
bool startCameraNative(const void *object);
void stopCameraNative(const void *object);
void setCameraNative(const void *object, int type);
void postCameraPoseEventNative(const void *object,
float x, float y, float z, float qx, float qy, float qz, float qw);
void postOdometryEventNative(const void *object,
float x, float y, float z, float qx, float qy, float qz, float qw,
float fx, float fy, float cx, float cy,
double stamp,
const void * yPlane, const void * uPlane, const void * vPlane, int yPlaneLen, int rgbWidth, int rgbHeight, int rgbFormat,
const void * depth, int depthLen, int depthWidth, int depthHeight, int depthFormat,
const void * conf, int confLen, int confWidth, int confHeight, int confFormat,
const void * points, int pointsLen, int pointsChannels,
float vx, float vy, float vz, float vqx, float vqy, float vqz, float vqw,
float p00, float p11, float p02, float p12, float p22, float p32, float p23,
float t0, float t1, float t2, float t3, float t4, float t5, float t6, float t7);
void setOnlineBlendingNative(const void *object, bool enabled);
void setMapCloudShownNative(const void *object, bool shown);
void setOdomCloudShownNative(const void *object, bool shown);
void setMeshRenderingNative(const void *object, bool enabled, bool withTexture);
void setPointSizeNative(const void *object, float value);
void setFOVNative(const void *object, float angle);
void setOrthoCropFactorNative(const void *object, float value);
void setGridRotationNative(const void *object, float value);
void setLightingNative(const void *object, bool enabled);
void setBackfaceCullingNative(const void *object, bool enabled);
void setWireframeNative(const void *object, bool enabled);
void setLocalizationModeNative(const void *object, bool enabled);
void setTrajectoryModeNative(const void *object, bool enabled);
void setGraphOptimizationNative(const void *object, bool enabled);
void setNodesFilteringNative(const void *object, bool enabled);
void setGraphVisibleNative(const void *object, bool visible);
void setGridVisibleNative(const void *object, bool visible);
void setRawScanSavedNative(const void *object, bool enabled);
void setFullResolutionNative(const void *object, bool enabled);
void setSmoothingNative(const void *object, bool enabled);
void setAppendModeNative(const void *object, bool enabled);
void setMaxCloudDepthNative(const void *object, float value);
void setMinCloudDepthNative(const void *object, float value);
void setCloudDensityLevelNative(const void *object, int value);
void setMeshAngleToleranceNative(const void *object, float value);
void setMeshDecimationFactorNative(const void *object, float value);
void setMeshTriangleSizeNative(const void *object, int value);
void setClusterRatioNative(const void *object, float value);
void setMaxGainRadiusNative(const void *object, float value);
void setRenderingTextureDecimationNative(const void *object, int value);
void setBackgroundColorNative(const void *object, float gray);
void setDepthConfidenceNative(const void *object, int value);
int setMappingParameterNative(const void *object, const char * key, const char * value);
typedef struct ImageNative
{
const void * objectPtr;
void * data;
int width;
int height;
int channels;
int totalBytes;
} ImageNative;
ImageNative getPreviewImageNative(const char * databasePath);
void releasePreviewImageNative(ImageNative image);
void setGPSNative(const void *object, double stamp, double longitude, double latitude, double altitude, double accuracy, double bearing);
void addEnvSensorNative(const void *object, int type, float value);
#ifdef __cplusplus
}
#endif
#endif /* NativeWrapper_hpp */

View File

@@ -0,0 +1,16 @@
//
// PointCloud.swift
// ThreeDScanner
//
// Created by Steven Roach on 4/3/18.
// Copyright © 2018 Steven Roach. All rights reserved.
//
import Foundation
import SceneKit
internal struct PointCloud {
internal var points: [vector_float3] = []
internal var framePointsSizes: [Int32] = []
internal var frameViewpoints: [SCNVector3] = []
}

View File

@@ -0,0 +1,16 @@
//
// PointCloudData.swift
// ThreeDScanner
//
// Created by Steven Roach on 4/3/18.
// Copyright © 2018 Steven Roach. All rights reserved.
//
import Foundation
import SceneKit
internal struct PointCloud {
internal var points: [vector_float3] = []
internal var pointCloudFrameSizes: [Int32] = []
internal var pointCloudFrameViewpoints: [SCNVector3] = []
}

View File

@@ -0,0 +1,549 @@
//
// RTABMap.swift
// RTABMapApp
//
// Created by Mathieu Labbe on 2020-12-31.
//
import Foundation
import ARKit
class RTABMap {
var native_rtabmap: UnsafeMutableRawPointer
struct Observation {
weak var observer: RTABMapObserver?
}
private var observations = [ObjectIdentifier : Observation]()
func addObserver(_ observer: RTABMapObserver) {
let id = ObjectIdentifier(observer)
observations[id] = Observation(observer: observer)
}
func removeObserver(_ observer: RTABMapObserver) {
let id = ObjectIdentifier(observer)
observations.removeValue(forKey: id)
}
init() {
native_rtabmap = UnsafeMutableRawPointer(mutating: createNativeApplication())
}
func setupCallbacksWithCPP()
{
setupCallbacksNative(native_rtabmap,
UnsafeMutableRawPointer(Unmanaged.passUnretained(self).toOpaque()),
//progressCallback
{(observer, count, max) -> Void in
// Extract pointer to `self` from void pointer:
let mySelf = Unmanaged<RTABMap>.fromOpaque(observer!).takeUnretainedValue()
// Call instance method:
//mySelf.TestMethod();
for (id, observation) in mySelf.observations {
// If the observer is no longer in memory, we
// can clean up the observation for its ID
guard let observer = observation.observer else {
mySelf.observations.removeValue(forKey: id)
continue
}
observer.progressUpdated(mySelf, count: Int(count), max: Int(max))
}
},
//initCallback
{(observer, status, msg) -> Void in
// Extract pointer to `self` from void pointer:
let mySelf = Unmanaged<RTABMap>.fromOpaque(observer!).takeUnretainedValue()
// Call instance method:
//mySelf.TestMethod();
for (id, observation) in mySelf.observations {
// If the observer is no longer in memory, we
// can clean up the observation for its ID
guard let observer = observation.observer else {
mySelf.observations.removeValue(forKey: id)
continue
}
let str = String(cString: msg!)
observer.initEventReceived(mySelf, status: Int(status), msg: str)
}
},
//statsUpdatedCallback
{(observer, nodes, words, points, polygons, updateTime, loopClosureId, highestHypId, databaseMemoryUsed, inliers, matches, featuresExtracted, hypothesis, nodesDrawn, fps, rejected, rehearsalValue, optimizationMaxError, optimizationMaxErrorRatio, distanceTravelled, fastMovement, landmarkDetected, x, y, z, roll, pitch, yaw) -> Void in
// Extract pointer to `self` from void pointer:
let mySelf = Unmanaged<RTABMap>.fromOpaque(observer!).takeUnretainedValue()
// Call instance method:
//mySelf.TestMethod();
for (id, observation) in mySelf.observations {
// If the observer is no longer in memory, we
// can clean up the observation for its ID
guard let observer = observation.observer else {
mySelf.observations.removeValue(forKey: id)
continue
}
observer.statsUpdated(mySelf, nodes: Int(nodes), words: Int(words), points: Int(points), polygons: Int(polygons), updateTime: updateTime, loopClosureId: Int(loopClosureId), highestHypId: Int(highestHypId), databaseMemoryUsed: Int(databaseMemoryUsed), inliers: Int(inliers), matches: Int(matches), featuresExtracted: Int(featuresExtracted), hypothesis: hypothesis, nodesDrawn: Int(nodesDrawn), fps: fps, rejected: Int(rejected), rehearsalValue: rehearsalValue, optimizationMaxError: optimizationMaxError, optimizationMaxErrorRatio: optimizationMaxErrorRatio, distanceTravelled: distanceTravelled, fastMovement: Int(fastMovement), landmarkDetected: Int(landmarkDetected), x: x, y: y, z: z, roll: roll, pitch: pitch, yaw: yaw)
}
})
}
deinit {
destroyNativeApplication(native_rtabmap)
}
func initGlContent() {
initGlContentNative(native_rtabmap)
}
func setupGraphic(size: CGSize, orientation: UIInterfaceOrientation) {
var rotation: Int32
switch orientation.rawValue {
case 4:
rotation=2
case 1:
rotation=3
case 2:
rotation=1
default:
rotation=0
}
//NSLog("Orientation: ios %d android %d, view=%dx%d", orientation.rawValue, rotation, Int32(size.width), Int32(size.height))
setScreenRotationNative(native_rtabmap, rotation)
setupGraphicNative(native_rtabmap, Int32(size.width), Int32(size.height));
}
func openDatabase(databasePath:String, databaseInMemory:Bool, optimize:Bool, clearDatabase: Bool) -> Int {
databasePath.utf8CString.withUnsafeBufferPointer { buffer -> Int in
return Int(openDatabaseNative(native_rtabmap, buffer.baseAddress, databaseInMemory, optimize, clearDatabase))
}
}
func save(databasePath:String) {
databasePath.utf8CString.withUnsafeBufferPointer { buffer in
saveNative(native_rtabmap, databasePath)
}
}
func recover(from: String, to: String) -> Bool {
from.utf8CString.withUnsafeBufferPointer { bufferFrom -> Bool in
to.utf8CString.withUnsafeBufferPointer { bufferTo -> Bool in
return recoverNative(native_rtabmap, bufferFrom.baseAddress, bufferTo.baseAddress)
}
}
}
func cancelProcessing() {
cancelProcessingNative(native_rtabmap);
}
func postProcessing(approach: Int) -> Int {
return Int(postProcessingNative(native_rtabmap, Int32(approach)))
}
func exportMesh(
cloudVoxelSize: Float,
regenerateCloud: Bool,
meshing: Bool,
textureSize: Int,
textureCount: Int,
normalK: Int,
optimized: Bool,
optimizedVoxelSize: Float,
optimizedDepth: Int,
optimizedMaxPolygons: Int,
optimizedColorRadius: Float,
optimizedCleanWhitePolygons: Bool,
optimizedMinClusterSize: Int,
optimizedMaxTextureDistance: Float,
optimizedMinTextureClusterSize: Int,
blockRendering: Bool) -> Bool
{
return exportMeshNative(native_rtabmap,
cloudVoxelSize,
regenerateCloud,
meshing,
Int32(textureSize),
Int32(textureCount),
Int32(normalK),
optimized,
optimizedVoxelSize,
Int32(optimizedDepth),
Int32(optimizedMaxPolygons),
optimizedColorRadius,
optimizedCleanWhitePolygons,
Int32(optimizedMinClusterSize),
optimizedMaxTextureDistance,
Int32(optimizedMinTextureClusterSize),
blockRendering)
}
func postExportation(visualize: Bool) -> Bool
{
return postExportationNative(native_rtabmap, visualize)
}
func writeExportedMesh(directory: String, name: String) -> Bool
{
directory.utf8CString.withUnsafeBufferPointer { bufferDir in
name.utf8CString.withUnsafeBufferPointer { bufferName in
return writeExportedMeshNative(native_rtabmap, bufferDir.baseAddress, bufferName.baseAddress)
}
}
}
func onTouchEvent(touch_count: Int, event: Int, x0: Float, y0: Float, x1: Float, y1: Float) {
onTouchEventNative(native_rtabmap, Int32(touch_count), Int32(event), x0, y0, x1, y1)
}
func setPausedMapping(paused: Bool) {
setPausedMappingNative(native_rtabmap, paused)
}
func render() -> Int {
return Int(renderNative(native_rtabmap))
}
func startCamera() -> Bool {
return startCameraNative(native_rtabmap)
}
func stopCamera() {
stopCameraNative(native_rtabmap)
}
func setCamera(type: Int) {
setCameraNative(native_rtabmap, Int32(type))
}
func postCameraPoseEvent(pose: simd_float4x4) {
let rotation = GLKMatrix3(
m: (pose[0,0], pose[0,1], pose[0,2],
pose[1,0], pose[1,1], pose[1,2],
pose[2,0], pose[2,1], pose[2,2]))
let quat = GLKQuaternionMakeWithMatrix3(rotation)
postCameraPoseEventNative(native_rtabmap, pose[3,0], pose[3,1], pose[3,2], quat.x, quat.y, quat.z, quat.w)
}
func notifyLost() {
// a null transform will make rtabmap creating a new session
postCameraPoseEventNative(native_rtabmap, 0,0,0,0,0,0,0)
}
func postOdometryEvent(frame: ARFrame, orientation: UIInterfaceOrientation, viewport: CGSize) {
let pose = frame.camera.transform // ViewMatrix
let rotation = GLKMatrix3(
m: (pose[0,0], pose[0,1], pose[0,2],
pose[1,0], pose[1,1], pose[1,2],
pose[2,0], pose[2,1], pose[2,2]))
let quat = GLKQuaternionMakeWithMatrix3(rotation)
postCameraPoseEventNative(native_rtabmap, pose[3,0], pose[3,1], pose[3,2], quat.x, quat.y, quat.z, quat.w)
let confMap = frame.sceneDepth?.confidenceMap
let depthMap = frame.sceneDepth?.depthMap
let points = frame.rawFeaturePoints?.points
if points != nil && (depthMap != nil || points!.count>0)
{
let v = frame.camera.viewMatrix(for: orientation)
let p = frame.camera.projectionMatrix(for: orientation, viewportSize: viewport, zNear: 0.5, zFar: 50.0)
let rotation = GLKMatrix3(
m: (v[0,0], v[0,1], v[0,2],
v[1,0], v[1,1], v[1,2],
v[2,0], v[2,1], v[2,2]))
let quatv = GLKQuaternionMakeWithMatrix3(rotation)
let texX1 = (1-(2*frame.camera.intrinsics[0,0]/Float(frame.camera.imageResolution.width)) / p[0,0])/2
let texY1 = (1-(2*frame.camera.intrinsics[1,1]/Float(frame.camera.imageResolution.height)) / p[1,1])/2
let texX2 = (1-(2*frame.camera.intrinsics[0,0]/Float(frame.camera.imageResolution.width)) / p[1,1])/2
let texY2 = (1-(2*frame.camera.intrinsics[1,1]/Float(frame.camera.imageResolution.height)) / p[0,0])/2
//11 10 01 00 // portrait
//01 11 00 10 // right
//10 00 11 01 // left
//00 01 10 11 // down
var texCoord: [Float]
switch orientation {
case .portrait:
texCoord = [1-texX2, 1-texY2, 1-texX2,texY2, texX2, 1-texY2, texX2, texY2]
case .landscapeRight:
texCoord = [texX1, 1-texY1, 1-texX1, 1-texY1, texX1, texY1, 1-texX1, texY1]
case .landscapeLeft:
texCoord = [1-texX1, texY1, texX1, texY1, 1-texX1, 1-texY1, texX1, 1-texY1]
default: // down
texCoord = [texX2, texY2, texX2, 1-texY2, 1-texX2, texY2, 1-texX2, 1-texY2]
}
frame.rawFeaturePoints?.points.withUnsafeBufferPointer { bufferPoints in
CVPixelBufferLockBaseAddress(frame.capturedImage, CVPixelBufferLockFlags.readOnly)
var depthDataPtr: UnsafeMutableRawPointer?
var depthSize: Int32 = 0
var depthWidth: Int32 = 0
var depthHeight: Int32 = 0
var depthFormat: Int32 = 0
if depthMap != nil {
CVPixelBufferLockBaseAddress(depthMap!, CVPixelBufferLockFlags.readOnly)
depthDataPtr = CVPixelBufferGetBaseAddress(depthMap!)!
depthSize = Int32(CVPixelBufferGetDataSize(depthMap!))
depthWidth = Int32(CVPixelBufferGetWidth(depthMap!))
depthHeight = Int32(CVPixelBufferGetHeight(depthMap!))
depthFormat = Int32(CVPixelBufferGetPixelFormatType(depthMap!))
}
var confDataPtr: UnsafeMutableRawPointer?
var confSize: Int32 = 0
var confWidth: Int32 = 0
var confHeight: Int32 = 0
var confFormat: Int32 = 0
if confMap != nil {
CVPixelBufferLockBaseAddress(confMap!, CVPixelBufferLockFlags.readOnly)
confDataPtr = CVPixelBufferGetBaseAddress(confMap!)!
confSize = Int32(CVPixelBufferGetDataSize(confMap!))
confWidth = Int32(CVPixelBufferGetWidth(confMap!))
confHeight = Int32(CVPixelBufferGetHeight(confMap!))
confFormat = Int32(CVPixelBufferGetPixelFormatType(confMap!))
}
if(frame.lightEstimate != nil) {
addEnvSensor(type: 4, value: Float(frame.lightEstimate!.ambientIntensity))
}
postOdometryEventNative(native_rtabmap,
pose[3,0], pose[3,1], pose[3,2], quat.x, quat.y, quat.z, quat.w,
frame.camera.intrinsics[0,0], // fx
frame.camera.intrinsics[1,1], // fy
frame.camera.intrinsics[2,0], // cx
frame.camera.intrinsics[2,1], // cy
frame.timestamp,
CVPixelBufferGetBaseAddressOfPlane(frame.capturedImage, 0), // y plane pointer
nil, // u plane pointer
CVPixelBufferGetBaseAddressOfPlane(frame.capturedImage, 1), // v plane pointer
Int32(CVPixelBufferGetBytesPerRowOfPlane(frame.capturedImage, 0)) * Int32(CVPixelBufferGetHeightOfPlane(frame.capturedImage, 0)), // yPlaneLen
Int32(CVPixelBufferGetWidth(frame.capturedImage)), // rgb width
Int32(CVPixelBufferGetHeight(frame.capturedImage)), // rgb height
Int32(CVPixelBufferGetPixelFormatType(frame.capturedImage)), // rgb format
depthDataPtr, // depth pointer
depthSize, // depth size
depthWidth, // depth width
depthHeight, // depth height
depthFormat, // depth format
confDataPtr, // conf pointer
confSize, // conf size
confWidth, // conf width
confHeight, // conf height
confFormat, // conf format
bufferPoints.baseAddress, Int32(frame.rawFeaturePoints!.points.count), 4,
v[3,0], v[3,1], v[3,2], quatv.x, quatv.y, quatv.z, quatv.w,
p[0,0], p[1,1], p[2,0], p[2,1], p[2,2], p[2,3], p[3,2],
texCoord[0],texCoord[1],texCoord[2],texCoord[3],texCoord[4],texCoord[5],texCoord[6],texCoord[7])
if depthMap != nil {
CVPixelBufferUnlockBaseAddress(depthMap!, CVPixelBufferLockFlags.readOnly)
}
if confMap != nil {
CVPixelBufferUnlockBaseAddress(confMap!, CVPixelBufferLockFlags.readOnly)
}
CVPixelBufferUnlockBaseAddress(frame.capturedImage, CVPixelBufferLockFlags.readOnly)
}
}
}
// Parameters
func setOnlineBlending(enabled: Bool) {
setOnlineBlendingNative(native_rtabmap, enabled)
}
func setMapCloudShown(shown: Bool) {
setMapCloudShownNative(native_rtabmap, shown)
}
func setOdomCloudShown(shown: Bool) {
setOdomCloudShownNative(native_rtabmap, shown)
}
func setMeshRendering(enabled: Bool, withTexture: Bool) {
setMeshRenderingNative(native_rtabmap, enabled, withTexture)
}
func setPointSize(value: Float) {
setPointSizeNative(native_rtabmap, value)
}
func setFOV(angle: Float) {
setFOVNative(native_rtabmap, angle)
}
func setOrthoCropFactor(value: Float) {
setOrthoCropFactorNative(native_rtabmap, value)
}
func setGridRotation(value: Float) {
setGridRotationNative(native_rtabmap, value)
}
func setLighting(enabled: Bool) {
setLightingNative(native_rtabmap, enabled)
}
func setBackfaceCulling(enabled: Bool) {
setBackfaceCullingNative(native_rtabmap, enabled)
}
func setWireframe(enabled: Bool) {
setWireframeNative(native_rtabmap, enabled)
}
func setLocalizationMode(enabled: Bool) {
setLocalizationModeNative(native_rtabmap, enabled)
}
func setTrajectoryMode(enabled: Bool) {
setTrajectoryModeNative(native_rtabmap, enabled)
}
func setGraphOptimization(enabled: Bool) {
setGraphOptimizationNative(native_rtabmap, enabled)
}
func setNodesFiltering(enabled: Bool) {
setNodesFilteringNative(native_rtabmap, enabled)
}
func setGraphVisible(visible: Bool) {
setGraphVisibleNative(native_rtabmap, visible)
}
func setGridVisible(visible: Bool) {
setGridVisibleNative(native_rtabmap, visible)
}
func setRawScanSaved(enabled: Bool) {
setRawScanSavedNative(native_rtabmap, enabled)
}
func setFullResolution(enabled: Bool) {
setFullResolutionNative(native_rtabmap, enabled)
}
func setSmoothing(enabled: Bool) {
setSmoothingNative(native_rtabmap, enabled)
}
func setAppendMode(enabled: Bool) {
setAppendModeNative(native_rtabmap, enabled)
}
func setMaxCloudDepth(value: Float) {
setMaxCloudDepthNative(native_rtabmap, value)
}
func setMinCloudDepth(value: Float) {
setMinCloudDepthNative(native_rtabmap, value)
}
func setCloudDensityLevel(value: Int) {
setCloudDensityLevelNative(native_rtabmap, Int32(value))
}
func setMeshAngleTolerance(value: Float) {
setMeshAngleToleranceNative(native_rtabmap, value)
}
func setMeshDecimationFactor(value: Float) {
setMeshDecimationFactorNative(native_rtabmap, value)
}
func setMeshTriangleSize(value: Int) {
setMeshTriangleSizeNative(native_rtabmap, Int32(value))
}
func setClusterRatio(value: Float) {
setClusterRatioNative(native_rtabmap, value)
}
func setMaxGainRadius(value: Float) {
setMaxGainRadiusNative(native_rtabmap, value)
}
func setRenderingTextureDecimation(value: Int) {
setRenderingTextureDecimationNative(native_rtabmap, Int32(value))
}
func setBackgroundColor(gray: Float) {
setBackgroundColorNative(native_rtabmap, gray)
}
func setDepthConfidence(value: Int) {
setDepthConfidenceNative(native_rtabmap, Int32(value))
}
func setMappingParameter(key: String, value: String) {
key.utf8CString.withUnsafeBufferPointer { bufferKey in
value.utf8CString.withUnsafeBufferPointer { bufferValue in
setMappingParameterNative(native_rtabmap, bufferKey.baseAddress, bufferValue.baseAddress)
}
}
}
func setGPS(location: CLLocation)
{
setGPSNative(native_rtabmap, location.timestamp.timeIntervalSince1970, location.coordinate.longitude, location.coordinate.latitude, location.altitude, location.horizontalAccuracy, location.course < 0.0 ? 0.0 : location.course)
}
func addEnvSensor(type: Int, value: Float)
{
addEnvSensorNative(native_rtabmap, Int32(type), value)
}
func setOrthoCropFactor(_ value: Float)
{
setOrthoCropFactorNative(native_rtabmap, value)
}
func setGridRotation(_ value: Float)
{
setGridRotationNative(native_rtabmap, value)
}
}
func getPreviewImage(databasePath: String) -> UIImage?
{
let imageOut = databasePath.utf8CString.withUnsafeBufferPointer { buffer -> UIImage? in
var image = ImageNative()
image = getPreviewImageNative(buffer.baseAddress)
if let dataPtr = UnsafeRawPointer(image.data)
{
// copy data in swift
let data = Data(bytes: dataPtr, count: Int(image.width*image.height*image.channels))
// release memory
releasePreviewImageNative(image)
// Create bitmap image
let bitmap = CIImage(bitmapData: data, bytesPerRow: Int(image.width*image.channels), size: CGSize(width: Int(image.width), height: Int(image.height)), format: CIFormat.BGRA8, colorSpace: nil)
return UIImage(ciImage: bitmap)
}
return UIImage(named: "RTAB-Map1024")
}
return imageOut
}
protocol RTABMapObserver: class {
func progressUpdated(_ rtabmap: RTABMap, count: Int, max: Int)
func initEventReceived(_ rtabmap: RTABMap, status: Int, msg: String)
func statsUpdated(_ rtabmap: RTABMap,
nodes: Int,
words: Int,
points: Int,
polygons: Int,
updateTime: Float,
loopClosureId: Int,
highestHypId: Int,
databaseMemoryUsed: Int,
inliers: Int,
matches: Int,
featuresExtracted: Int,
hypothesis: Float,
nodesDrawn: Int,
fps: Float,
rejected: Int,
rehearsalValue: Float,
optimizationMaxError: Float,
optimizationMaxErrorRatio: Float,
distanceTravelled: Float,
fastMovement: Int,
landmarkDetected: Int,
x: Float,
y: Float,
z: Float,
roll: Float,
pitch: Float,
yaw: Float)
}
extension String {
func toPointer() -> UnsafePointer<UInt8>? {
guard let data = self.data(using: String.Encoding.utf8) else { return nil }
let buffer = UnsafeMutablePointer<UInt8>.allocate(capacity: data.count)
let stream = OutputStream(toBuffer: buffer, capacity: data.count)
stream.open()
data.withUnsafeBytes({ (p: UnsafePointer<UInt8>) -> Void in
stream.write(p, maxLength: data.count)
})
stream.close()
return UnsafePointer<UInt8>(buffer)
}
}

View File

@@ -0,0 +1,6 @@
//
// Use this file to import your target's public headers that you would like to expose to Swift.
//
#include "NativeWrapper.hpp"
#import <sqlite3.h>

View File

@@ -0,0 +1,52 @@
//
// SceneDelegate.swift
// GLKittutorial
//
// Created by Mathieu Labbe on 2020-12-28.
//
import UIKit
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
// Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
// If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
// This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
guard let _ = (scene as? UIWindowScene) else { return }
}
func sceneDidDisconnect(_ scene: UIScene) {
// Called as the scene is being released by the system.
// This occurs shortly after the scene enters the background, or when its session is discarded.
// Release any resources associated with this scene that can be re-created the next time the scene connects.
// The scene may re-connect later, as its session was not necessarily discarded (see `application:didDiscardSceneSessions` instead).
}
func sceneDidBecomeActive(_ scene: UIScene) {
// Called when the scene has moved from an inactive state to an active state.
// Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
}
func sceneWillResignActive(_ scene: UIScene) {
// Called when the scene will move from an active state to an inactive state.
// This may occur due to temporary interruptions (ex. an incoming phone call).
}
func sceneWillEnterForeground(_ scene: UIScene) {
// Called as the scene transitions from the background to the foreground.
// Use this method to undo the changes made on entering the background.
}
func sceneDidEnterBackground(_ scene: UIScene) {
// Called as the scene transitions from the foreground to the background.
// Use this method to save data, release shared resources, and store enough scene-specific state information
// to restore the scene back to its current state.
}
}

View File

@@ -0,0 +1,138 @@
/*
* Copyright (c) 2017 Razeware LLC
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
* distribute, sublicense, create a derivative work, and/or sell copies of the
* Software in any work that is designed, intended, or marketed for pedagogical or
* instructional purposes related to programming, coding, application development,
* or information technology. Permission for such use, copying, modification,
* merger, publication, distribution, sublicensing, creation of derivative works,
* or sale is expressly withheld.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
import UIKit
protocol VerticalViewDataSource: class {
// Ask the data source how many views it wants to present inside the horizontal scroller
func numberOfViews(in verticalScrollerView: VerticalScrollerView) -> Int
// Ask the data source to return the view that should appear at <index>
func getScrollerViewItem(_ verticalScrollerView: VerticalScrollerView, viewAt index: Int) -> UIView
}
protocol VerticalScrollerViewDelegate: class {
// inform the delegate that the view at <index> has been selected
func verticalScrollerView(_ verticalScrollerView: VerticalScrollerView, didSelectViewAt index: Int)
}
class VerticalScrollerView: UIView {
weak var dataSource: VerticalViewDataSource?
weak var delegate: VerticalScrollerViewDelegate?
// 1
private enum ViewConstants {
static let Padding: CGFloat = 5
static let Dimensions: CGFloat = 185
static let Offset: CGFloat = 10
}
// 2
private let scroller = UIScrollView()
// 3
private var contentViews = [UIView]()
override init(frame: CGRect) {
super.init(frame: frame)
initializeScrollView()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
initializeScrollView()
}
func initializeScrollView() {
addSubview(scroller)
scroller.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
scroller.leadingAnchor.constraint(equalTo: self.leadingAnchor),
scroller.trailingAnchor.constraint(equalTo: self.trailingAnchor),
scroller.topAnchor.constraint(equalTo: self.topAnchor),
scroller.bottomAnchor.constraint(equalTo: self.bottomAnchor)
])
let tapRecognizer = UITapGestureRecognizer(target: self, action: #selector(scrollerTapped(gesture:)))
scroller.addGestureRecognizer(tapRecognizer)
}
func scrollToView(at index: Int, animated: Bool = true) {
let centralView = contentViews[index]
let targetCenter = centralView.center
let targetOffsetY = targetCenter.y - (scroller.bounds.height / 2)
scroller.setContentOffset(CGPoint(x: 0, y: targetOffsetY), animated: animated)
}
@objc func scrollerTapped(gesture: UITapGestureRecognizer) {
let location = gesture.location(in: scroller)
guard
let index = contentViews.index(where: { $0.frame.contains(location)})
else { return }
delegate?.verticalScrollerView(self, didSelectViewAt: index)
scrollToView(at: index)
}
func view(at index :Int) -> UIView {
return contentViews[index]
}
func reload() {
// 1 - Check if there is a data source, if not there is nothing to load.
guard let dataSource = dataSource else {
return
}
//2 - Remove the old content views
contentViews.forEach { $0.removeFromSuperview() }
// 3 - yValue is the starting point of each view inside the scroller
var yValue = ViewConstants.Offset
// 4 - Fetch and add the new views
contentViews = (0..<dataSource.numberOfViews(in: self)).map {
index in
// 5 - add a view at the right position
yValue += ViewConstants.Padding
let view = dataSource.getScrollerViewItem(self, viewAt: index)
view.frame = CGRect(x: ViewConstants.Padding, y: CGFloat(yValue), width: ViewConstants.Dimensions*2, height: ViewConstants.Dimensions)
scroller.addSubview(view)
yValue += ViewConstants.Dimensions + ViewConstants.Padding
// 6 - Store the view so we can reference it later
return view
}
// 7
scroller.contentSize = CGSize(width: frame.size.width, height: CGFloat(yValue + ViewConstants.Offset))
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,162 @@
#!/bin/bash
set -euxo pipefail
# Tested on Apple Silicon Mac, with cmake 3.19.2.
mkdir Libraries
cd Libraries
pwd=$(pwd)
prefix=$pwd
sysroot=iphoneos
#sysroot=iphonesimulator
# Install directory for all dependencies
mkdir -p $prefix
# openmp
# based on https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/libomp.rb
#curl -L https://github.com/llvm/llvm-project/releases/download/llvmorg-11.1.0/openmp-11.1.0.src.tar.xz -o openmp-11.1.0.src.tar.xz
#tar -xzf openmp-11.1.0.src.tar.xz
#cd openmp-11.1.0.src
#curl -L https://raw.githubusercontent.com/Homebrew/formula-patches/7e2ee1d7/libomp/arm.patch -o arm.patch
#patch -p1 < arm.patch
#mkdir build
#cd build
#cmake -G Xcode -DCMAKE_SYSTEM_NAME=iOS -DCMAKE_OSX_SYSROOT=$sysroot -DBUILD_SHARED_LIBS=OFF -DCMAKE_BUILD_TYPE=Release -DCMAKE_OSX_DEPLOYMENT_TARGET=11.0 -DCMAKE_C_FLAGS=-fembed-bitcode -DCMAKE_CXX_FLAGS=-fembed-bitcode -DCMAKE_INSTALL_PREFIX=$prefix -DLIBOMP_INSTALL_ALIASES=OFF -DLIBOMP_ENABLE_SHARED=OFF ..
#cmake --build . --config Release -- CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED="NO" CODE_SIGN_ENTITLEMENTS="" CODE_SIGNING_ALLOWED="NO"
#cp runtime/src/Release-iphoneos/libomp.a runtime/src/.
#cmake --build . --config Release --target install -- CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED="NO" CODE_SIGN_ENTITLEMENTS="" CODE_SIGNING_ALLOWED="NO"
# Boost
echo "wget boost..."
curl -L https://downloads.sourceforge.net/project/boost/boost/1.59.0/boost_1_59_0.tar.gz -o boost_1_59_0.tar.gz
tar -xzf boost_1_59_0.tar.gz
cd boost_1_59_0
curl -L https://gist.github.com/matlabbe/0bce8feeb73a499a76afbbcc5c687221/raw/489ff2869eccd6f8d03ffb9090ef839108762741/BoostConfig.cmake.in -o BoostConfig.cmake.in
curl -L https://gist.github.com/matlabbe/0bce8feeb73a499a76afbbcc5c687221/raw/b07fe7d4e5dfe5f1d110c733e5cf660d79a26378/CMakeLists.txt -o CMakeLists.txt
mkdir build
cd build
cmake -G Xcode -DCMAKE_SYSTEM_NAME=iOS -DCMAKE_OSX_ARCHITECTURES=arm64 -DCMAKE_OSX_SYSROOT=$sysroot -DBUILD_SHARED_LIBS=OFF -DCMAKE_BUILD_TYPE=Release -DCMAKE_OSX_DEPLOYMENT_TARGET=11.0 -DCMAKE_C_FLAGS=-fembed-bitcode -DCMAKE_CXX_FLAGS=-fembed-bitcode -DCMAKE_INSTALL_PREFIX=$prefix ..
cmake --build . --config Release
cmake --build . --config Release --target install
cd $pwd
#rm -r boost_1_59_0.tar.gz boost_1_59_0
# eigen
echo "wget eigen..."
curl -L https://gitlab.com/libeigen/eigen/-/archive/3.3.9/eigen-3.3.9.tar.gz -o 3.3.9.tar.gz
tar -xzf 3.3.9.tar.gz
cd eigen-3.3.9
mkdir build
cd build
cmake -G Xcode -DCMAKE_SYSTEM_NAME=iOS -DCMAKE_OSX_ARCHITECTURES=arm64 -DCMAKE_OSX_SYSROOT=$sysroot -DBUILD_SHARED_LIBS=OFF -DCMAKE_BUILD_TYPE=Release -DCMAKE_OSX_DEPLOYMENT_TARGET=11.0 -DCMAKE_C_FLAGS=-fembed-bitcode -DCMAKE_CXX_FLAGS=-fembed-bitcode -DCMAKE_INSTALL_PREFIX=$prefix ..
cmake --build . --config Release
cmake --build . --config Release --target install
cd $pwd
#rm -r 3.3.9.tar.gz eigen-3.3.9
# FLANN
echo "wget flann..."
git clone https://github.com/flann-lib/flann.git
cd flann
git checkout 1.8.4
curl -L https://gist.githubusercontent.com/matlabbe/c858ba36fb85d5e44d8667dfb3543e12/raw/8fc40aa9bc3267604869444020476a49f14ab424/flann_ios.patch -o flann_ios.patch
git apply flann_ios.patch
mkdir build
cd build
# comment "add_subdirectory( test )" in top CMakeLists.txt
# comment "add_subdirectory( doc )" in top CMakeLists.txt
cmake -G Xcode -DCMAKE_SYSTEM_NAME=iOS -DCMAKE_OSX_ARCHITECTURES=arm64 -DCMAKE_OSX_SYSROOT=$sysroot -DBUILD_SHARED_LIBS=OFF -DCMAKE_BUILD_TYPE=Release -DCMAKE_OSX_DEPLOYMENT_TARGET=11.0 -DCMAKE_C_FLAGS=-fembed-bitcode -DCMAKE_CXX_FLAGS=-fembed-bitcode -DCMAKE_INSTALL_PREFIX=$prefix -DBUILD_PYTHON_BINDINGS=OFF -DBUILD_MATLAB_BINDINGS=OFF -DBUILD_C_BINDINGS=OFF ..
cmake --build . --config Release -- CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED="NO" CODE_SIGN_ENTITLEMENTS="" CODE_SIGNING_ALLOWED="NO"
cmake --build . --config Release --target install -- CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED="NO" CODE_SIGN_ENTITLEMENTS="" CODE_SIGNING_ALLOWED="NO"
cd $pwd
#rm -r flann
# GTSAM
git clone https://bitbucket.org/gtborg/gtsam.git
cd gtsam
git checkout fbb9d3bdda8b88df51896bc401bfd170573e66f5
# patch
curl -L https://gist.github.com/matlabbe/76d658dddb841b3355ae3a6e32850cd8/raw/7033cba1c89097b0c830651d7277c04dc92cbdd9/gtsam_GKlib_ios_fix.patch -o gtsam_GKlib_ios_fix.patch
git apply gtsam_GKlib_ios_fix.patch
mkdir build
cd build
cmake -G Xcode -DCMAKE_SYSTEM_NAME=iOS -DCMAKE_OSX_ARCHITECTURES=arm64 -DCMAKE_OSX_SYSROOT=$sysroot -DBUILD_SHARED_LIBS=OFF -DCMAKE_BUILD_TYPE=Release -DCMAKE_OSX_DEPLOYMENT_TARGET=11.0 -DCMAKE_C_FLAGS=-fembed-bitcode -DCMAKE_CXX_FLAGS=-fembed-bitcode -DCMAKE_INSTALL_PREFIX=$prefix -DMETIS_SHARED=OFF -DGTSAM_BUILD_STATIC_LIBRARY=ON -DGTSAM_BUILD_TESTS=OFF -DGTSAM_BUILD_EXAMPLES_ALWAYS=OFF -DGTSAM_USE_SYSTEM_EIGEN=ON -DGTSAM_WRAP_SERIALIZATION=OFF -DGTSAM_BUILD_WRAP=OFF -DGTSAM_INSTALL_CPPUNITLITE=OFF -DCMAKE_FIND_ROOT_PATH=$prefix ..
cmake --build . --config Release -- CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED="NO" CODE_SIGN_ENTITLEMENTS="" CODE_SIGNING_ALLOWED="NO"
cmake --build . --config Release --target install -- CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED="NO" CODE_SIGN_ENTITLEMENTS="" CODE_SIGNING_ALLOWED="NO"
cd $pwd
#rm -rf gtsam
# g2o
git clone https://github.com/RainerKuemmerle/g2o.git
cd g2o
git checkout a3f7706bdbb849b2808dc3e1b7aee189f63b498e
# patch
curl -L https://gist.github.com/matlabbe/b9ccfeae8f0744b275cab23510872680/raw/a58e06accba3976420d4b61341685c123193810e/g2o_ios_fix.patch -o g2o_ios_fix.patch
git apply g2o_ios_fix.patch
mkdir build
cd build
cmake -G Xcode -DCMAKE_SYSTEM_NAME=iOS -DCMAKE_OSX_ARCHITECTURES=arm64 -DCMAKE_OSX_SYSROOT=$sysroot -DBUILD_SHARED_LIBS=OFF -DCMAKE_BUILD_TYPE=Release -DCMAKE_OSX_DEPLOYMENT_TARGET=11.0 -DCMAKE_C_FLAGS=-fembed-bitcode -DCMAKE_CXX_FLAGS=-fembed-bitcode -DCMAKE_INSTALL_PREFIX=$prefix -DBUILD_LGPL_SHARED_LIBS=OFF -DG2O_BUILD_APPS=OFF -DG2O_BUILD_EXAMPLES=OFF -DCMAKE_FIND_ROOT_PATH=$prefix ..
cmake --build . --config Release -- CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED="NO" CODE_SIGN_ENTITLEMENTS="" CODE_SIGNING_ALLOWED="NO"
cmake --build . --config Release --target install -- CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED="NO" CODE_SIGN_ENTITLEMENTS="" CODE_SIGNING_ALLOWED="NO"
cd $pwd
#rm -rf g2o
# VTK
git clone https://github.com/Kitware/VTK.git
cd VTK
git checkout tags/v8.2.0
git cherry-pick bf3ae8072df2393c7270509bae41be0776826346
mkdir build
cd build
cmake -DBUILD_SHARED_LIBS=OFF -DCMAKE_BUILD_TYPE=Release -DCMAKE_FRAMEWORK_INSTALL_PREFIX=$prefix/lib -DIOS_DEVICE_ARCHITECTURES="arm64" -DIOS_SIMULATOR_ARCHITECTURES="" -DBUILD_EXAMPLES=OFF -DBUILD_TESTING=OFF -DVTK_IOS_BUILD=ON -DModule_vtkFiltersModeling=ON ..
# For iphonesimulator: add -DIOS_DEVICE_ARCHITECTURES=""
cmake --build . --config Release
cd $pwd
#rm -rf VTK
# PCL
git clone https://github.com/PointCloudLibrary/pcl.git
cd pcl
git checkout tags/pcl-1.11.1
# patch
curl -L https://gist.github.com/matlabbe/f3ba9366eb91e1b855dadd2ddce5746d/raw/4a66ebb9faa1dfe997a0860d733bc5473cff20ee/pcl_1_11_1_vtk_ios_support.patch -o pcl_1_11_1_vtk_ios_support.patch
git apply pcl_1_11_1_vtk_ios_support.patch
mkdir build
cd build
cmake -G Xcode -DCMAKE_SYSTEM_NAME=iOS -DCMAKE_OSX_ARCHITECTURES=arm64 -DCMAKE_OSX_SYSROOT=$sysroot -DBUILD_SHARED_LIBS=OFF -DCMAKE_BUILD_TYPE=Release -DCMAKE_OSX_DEPLOYMENT_TARGET=11.0 -DCMAKE_C_FLAGS=-fembed-bitcode -DCMAKE_CXX_FLAGS=-fembed-bitcode -DCMAKE_INSTALL_PREFIX=$prefix -DBUILD_apps=OFF -DBUILD_examples=OFF -DBUILD_tools=OFF -DBUILD_visualization=OFF -DBUILD_tracking=OFF -DBUILD_people=OFF -DBUILD_global_tests=OFF -DWITH_QT=OFF -DWITH_OPENGL=OFF -DWITH_VTK=ON -DPCL_SHARED_LIBS=OFF -DCMAKE_FIND_ROOT_PATH=$prefix ..
cmake --build . --config Release
cmake --build . --config Release --target install
cd $pwd
#rm -rf pcl
# OpenCV
git clone https://github.com/opencv/opencv_contrib.git
cd opencv_contrib
git checkout tags/3.4.2
cd $pwd
git clone https://github.com/opencv/opencv.git
cd opencv
git checkout tags/3.4.2
curl -L https://gist.githubusercontent.com/matlabbe/fdc3ab4854f3a68fbde7277f543b4e5b/raw/f340839c09165056d3845645df24b76507542fd2/opencv_ios.patch -o opencv_ios.patch
git apply opencv_ios.patch
mkdir build
cd build
# add "add_definitions(-DPNG_ARM_NEON_OPT=0)" in 3rdparty/libpng/CMakeLists.txt
cmake -G Xcode -DCMAKE_SYSTEM_NAME=iOS -DCMAKE_OSX_ARCHITECTURES=arm64 -DCMAKE_OSX_SYSROOT=$sysroot -DBUILD_SHARED_LIBS=OFF -DCMAKE_BUILD_TYPE=Release -DCMAKE_OSX_DEPLOYMENT_TARGET=11.0 -DCMAKE_C_FLAGS=-fembed-bitcode -DCMAKE_CXX_FLAGS=-fembed-bitcode -DCMAKE_INSTALL_PREFIX=$prefix -DOPENCV_EXTRA_MODULES_PATH=$prefix/opencv_contrib/modules -DBUILD_TESTS=OFF -DBUILD_PERF_TESTS=OFF -DWITH_CUDA=OFF -DBUILD_opencv_apps=OFF -DBUILD_opencv_xobjdetect=OFF -DBUILD_opencv_stereo=OFF ..
cmake --build . --config Release
cmake --build . --config Release --target install
cd $pwd
#rm -rf opencv opencv_contrib
mkdir rtabmap
cd rtabmap
cmake -DANDROID_PREBUILD=ON ../../../../..
cmake --build . --config Release
mkdir ios
cd ios
cmake -G Xcode -DCMAKE_SYSTEM_NAME=iOS -DCMAKE_OSX_ARCHITECTURES=arm64 -DCMAKE_OSX_SYSROOT=$sysroot -DBUILD_SHARED_LIBS=OFF -DCMAKE_BUILD_TYPE=Release -DCMAKE_OSX_DEPLOYMENT_TARGET=11.0 -DCMAKE_C_FLAGS=-fembed-bitcode -DCMAKE_CXX_FLAGS=-fembed-bitcode -DCMAKE_INSTALL_PREFIX=$prefix -DCMAKE_FIND_ROOT_PATH=$prefix -DWITH_QT=OFF -DBUILD_APP=OFF -DBUILD_TOOLS=OFF -DWITH_TORO=OFF -DWITH_VERTIGO=OFF -DWITH_MADGWICK=OFF -DWITH_ORB_OCTREE=OFF -DBUILD_EXAMPLES=OFF ../../../../../..
cmake --build . --config Release
cmake --build . --config Release --target install

View File

@@ -0,0 +1,351 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>StringsTable</key>
<string>Assembling</string>
<key>PreferenceSpecifiers</key>
<array>
<dict>
<key>Type</key>
<string>PSGroupSpecifier</string>
<key>FooterText</key>
<string>If you don&apos;t need a very precise point cloud, you can set this to reduce the output point cloud size. This is also used for optimized mesh.</string>
</dict>
<dict>
<key>Type</key>
<string>PSMultiValueSpecifier</string>
<key>Title</key>
<string>Voxel Size</string>
<key>Key</key>
<string>VoxelSize</string>
<key>DefaultValue</key>
<real>0.01</real>
<key>Titles</key>
<array>
<string>20 cm</string>
<string>10 cm</string>
<string>5 cm</string>
<string>2 cm</string>
<string>1 cm</string>
<string>0.5 cm</string>
<string>Disabled</string>
</array>
<key>Values</key>
<array>
<real>0.2</real>
<real>0.1</real>
<real>0.05</real>
<real>0.02</real>
<real>0.01</real>
<real>0.005</real>
<real>0</real>
</array>
</dict>
<dict>
<key>Type</key>
<string>PSGroupSpecifier</string>
<key>FooterText</key>
<string>If the map is large, you may want to increase this to maximize the texture resolution.</string>
</dict>
<dict>
<key>Type</key>
<string>PSMultiValueSpecifier</string>
<key>Title</key>
<string>Texture Size</string>
<key>Key</key>
<string>TextureSize</string>
<key>DefaultValue</key>
<integer>4096</integer>
<key>Titles</key>
<array>
<string>16384x16384</string>
<string>8192x8192</string>
<string>4096x4096</string>
<string>2048x2048</string>
<string>1024x1024</string>
</array>
<key>Values</key>
<array>
<integer>16384</integer>
<integer>8192</integer>
<integer>4096</integer>
<integer>2048</integer>
<integer>1024</integer>
</array>
</dict>
<dict>
<key>Type</key>
<string>PSGroupSpecifier</string>
<key>FooterText</key>
<string>Note that all textures are still merged into one for visualization, but exported in multiple files.</string>
</dict>
<dict>
<key>Type</key>
<string>PSMultiValueSpecifier</string>
<key>Title</key>
<string>Maximum Output Textures</string>
<key>Key</key>
<string>MaximumOutputTextures</string>
<key>DefaultValue</key>
<integer>1</integer>
<key>Titles</key>
<array>
<string>8</string>
<string>7</string>
<string>6</string>
<string>5</string>
<string>4</string>
<string>3</string>
<string>2</string>
<string>1</string>
</array>
<key>Values</key>
<array>
<integer>8</integer>
<integer>7</integer>
<integer>6</integer>
<integer>5</integer>
<integer>4</integer>
<integer>3</integer>
<integer>2</integer>
<integer>1</integer>
</array>
</dict>
<dict>
<key>Type</key>
<string>PSGroupSpecifier</string>
<key>FooterText</key>
<string>K-nearest neighbors used for normal computation when a mesh is created.</string>
</dict>
<dict>
<key>Type</key>
<string>PSMultiValueSpecifier</string>
<key>Title</key>
<string>Normal K</string>
<key>Key</key>
<string>NormalK</string>
<key>DefaultValue</key>
<integer>18</integer>
<key>Titles</key>
<array>
<string>30</string>
<string>24</string>
<string>18</string>
<string>12</string>
<string>6</string>
</array>
<key>Values</key>
<array>
<integer>30</integer>
<integer>24</integer>
<integer>18</integer>
<integer>12</integer>
<integer>6</integer>
</array>
</dict>
<dict>
<key>Type</key>
<string>PSGroupSpecifier</string>
<key>FooterText</key>
<string>Maximum distance from a camera for polygons to be textured by this camera.</string>
</dict>
<dict>
<key>Type</key>
<string>PSMultiValueSpecifier</string>
<key>Title</key>
<string>Max Texture Distance</string>
<key>Key</key>
<string>MaxTextureDistance</string>
<key>DefaultValue</key>
<real>3</real>
<key>Titles</key>
<array>
<string>No Limit</string>
<string>5 m</string>
<string>4.5 m</string>
<string>4 m</string>
<string>3.5 m</string>
<string>3 m</string>
<string>2.5 m</string>
<string>2 m</string>
</array>
<key>Values</key>
<array>
<real>0</real>
<real>5</real>
<real>4.5</real>
<real>4</real>
<real>3.5</real>
<real>3</real>
<real>2.5</real>
<real>2</real>
</array>
</dict>
<dict>
<key>Type</key>
<string>PSGroupSpecifier</string>
<key>FooterText</key>
<string>Minimum polygon cluster size to be textured by a camera. This helps to filter sparse textured polygons.</string>
</dict>
<dict>
<key>Type</key>
<string>PSMultiValueSpecifier</string>
<key>Title</key>
<string>Min Texture Cluster Size</string>
<key>Key</key>
<string>MinTextureClusterSize</string>
<key>DefaultValue</key>
<integer>50</integer>
<key>Titles</key>
<array>
<string>1000</string>
<string>500</string>
<string>200</string>
<string>100</string>
<string>50</string>
<string>10</string>
<string>Disabled</string>
</array>
<key>Values</key>
<array>
<integer>1000</integer>
<integer>500</integer>
<integer>200</integer>
<integer>100</integer>
<integer>50</integer>
<integer>10</integer>
<integer>0</integer>
</array>
</dict>
<dict>
<key>Type</key>
<string>PSGroupSpecifier</string>
<key>Title</key>
<string>Optimized</string>
<key>FooterText</key>
<string>Lowering this parameter decreases reconstruction time, but geometry precision is lower. Minimum polygon size: map length / 2^depth). &quot;Auto&quot; means that depth is chosen so that polygon size is just under 3 cm.</string>
</dict>
<dict>
<key>Type</key>
<string>PSMultiValueSpecifier</string>
<key>Title</key>
<string>Reconstruction Depth</string>
<key>Key</key>
<string>ReconstructionDepth</string>
<key>DefaultValue</key>
<integer>0</integer>
<key>Titles</key>
<array>
<string>Auto</string>
<string>12</string>
<string>11</string>
<string>10</string>
<string>9</string>
<string>8</string>
<string>7</string>
<string>6</string>
</array>
<key>Values</key>
<array>
<integer>0</integer>
<integer>12</integer>
<integer>11</integer>
<integer>10</integer>
<integer>9</integer>
<integer>8</integer>
<integer>7</integer>
<integer>6</integer>
</array>
</dict>
<dict>
<key>Type</key>
<string>PSGroupSpecifier</string>
<key>FooterText</key>
<string>Radius used to transfer nearest color from the point cloud to reconstructed mesh. When exporting with texture, if Clean Mesh is also enabled, this will limit the number of polygons textured in holes.</string>
</dict>
<dict>
<key>Type</key>
<string>PSMultiValueSpecifier</string>
<key>Title</key>
<string>Color Radius</string>
<key>Key</key>
<string>ColorRadius</string>
<key>DefaultValue</key>
<real>0.05</real>
<key>Titles</key>
<array>
<string>Nearest</string>
<string>2 m</string>
<string>1 m</string>
<string>0.5 m</string>
<string>0.2 m</string>
<string>0.1 m</string>
<string>0.05 m</string>
<string>0.025 m</string>
<string>0.02 m</string>
<string>0.015 m</string>
<string>0.01 m</string>
<string>Disabled</string>
</array>
<key>Values</key>
<array>
<real>0</real>
<real>2</real>
<real>1</real>
<real>0.5</real>
<real>0.2</real>
<real>0.1</real>
<real>0.05</real>
<real>0.025</real>
<real>0.02</real>
<real>0.015</real>
<real>0.01</real>
<real>-1</real>
</array>
</dict>
<dict>
<key>Type</key>
<string>PSGroupSpecifier</string>
<key>FooterText</key>
<string>Clean mesh from textureless or colorless reconstructed polygons.</string>
</dict>
<dict>
<key>Type</key>
<string>PSToggleSwitchSpecifier</string>
<key>Title</key>
<string>Clean Mesh</string>
<key>Key</key>
<string>CleanMesh</string>
<key>DefaultValue</key>
<true/>
</dict>
<dict>
<key>Type</key>
<string>PSGroupSpecifier</string>
<key>FooterText</key>
<string>This can be used to filter polygons before texturing.</string>
</dict>
<dict>
<key>Type</key>
<string>PSMultiValueSpecifier</string>
<key>Title</key>
<string>Polygon Filtering</string>
<key>Key</key>
<string>PolygonFiltering</string>
<key>DefaultValue</key>
<integer>0</integer>
<key>Titles</key>
<array>
<string>Only biggest cluster kept</string>
<string>Keep all polygons</string>
</array>
<key>Values</key>
<array>
<integer>-1</integer>
<integer>0</integer>
</array>
</dict>
</array>
</dict>
</plist>

View File

@@ -0,0 +1,173 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>StringsTable</key>
<string>License</string>
<key>PreferenceSpecifiers</key>
<array>
<dict>
<key>Type</key>
<string>PSGroupSpecifier</string>
<key>FooterText</key>
<string>
======= RTAB-Map =======
RTAB-Map - https://github.com/introlab/rtabmap
Copyright (c) 2010-2022, Mathieu Labbe - IntRoLab - Universite de Sherbrooke, all rights reserved.
Copyright (c) XXX, contributors, 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 copyright holders nor the names of the
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.
======= OpenCV =======
Copyright (C) 2000-2021, Intel Corporation, all rights reserved.
Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved.
Copyright (C) 2009-2016, NVIDIA Corporation, all rights reserved.
Copyright (C) 2010-2013, Advanced Micro Devices, Inc., all rights reserved.
Copyright (C) 2015-2021, OpenCV Foundation, all rights reserved.
Copyright (C) 2015-2016, Itseez Inc., all rights reserved.
Copyright (C) 2019-2021, Xperience AI, all rights reserved.
Third party copyrights are property of their respective owners.
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 names of the copyright holders nor the names of the 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 copyright holders 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.
======= Point Cloud Library =======
Point Cloud Library (PCL) - www.pointclouds.org
Copyright (c) 2009-2012, Willow Garage, Inc.
Copyright (c) 2012-, Open Perception, Inc.
Copyright (c) XXX, respective authors.
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 copyright holder(s) 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 OWNER 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.
======= g2o =======
g2o - General Graph Optimization
Copyright (C) 2011 R. Kuemmerle, G. Grisetti, W. Burgard
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.
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.
======= GTSAM =======
Copyright (c) 2010, Georgia Tech Research Corporation
Atlanta, Georgia 30332-0415
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 copyright holders 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.
</string>
</dict>
</array>
</dict>
</plist>

View File

@@ -0,0 +1,805 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>StringsTable</key>
<string>Mapping</string>
<key>PreferenceSpecifiers</key>
<array>
<dict>
<key>Type</key>
<string>PSGroupSpecifier</string>
<key>FooterText</key>
<string>When resuming mapping, wait for a relocalization on the current map before starting a new map.</string>
</dict>
<dict>
<key>Type</key>
<string>PSToggleSwitchSpecifier</string>
<key>Title</key>
<string>Append Mode</string>
<key>Key</key>
<string>AppendMode</string>
<key>DefaultValue</key>
<true/>
</dict>
<dict>
<key>Type</key>
<string>PSGroupSpecifier</string>
<key>FooterText</key>
<string>Save HD images of the color camera if you want very detailed textures. More memory will be required.</string>
</dict>
<dict>
<key>Type</key>
<string>PSToggleSwitchSpecifier</string>
<key>Title</key>
<string>HD Mode</string>
<key>Key</key>
<string>HDMode</string>
<key>DefaultValue</key>
<false/>
</dict>
<dict>
<key>Type</key>
<string>PSGroupSpecifier</string>
<key>FooterText</key>
<string>When this is disabled (or the phone doesn&apos;t have LiDAR), only tracked features from ARKit will be mapped into a point cloud.</string>
</dict>
<dict>
<key>Type</key>
<string>PSToggleSwitchSpecifier</string>
<key>Title</key>
<string>LiDAR Mode</string>
<key>Key</key>
<string>LidarMode</string>
<key>DefaultValue</key>
<true/>
</dict>
<dict>
<key>Type</key>
<string>PSGroupSpecifier</string>
<key>FooterText</key>
<string>Smooth the point clouds.</string>
</dict>
<dict>
<key>Type</key>
<string>PSToggleSwitchSpecifier</string>
<key>Title</key>
<string>Smoothing</string>
<key>Key</key>
<string>Smoothing</string>
<key>DefaultValue</key>
<false/>
</dict>
<dict>
<key>Type</key>
<string>PSGroupSpecifier</string>
<key>Title</key>
<string>Core</string>
<key>FooterText</key>
<string>Rate at which a new node is added to map.</string>
</dict>
<dict>
<key>Type</key>
<string>PSMultiValueSpecifier</string>
<key>Title</key>
<string>Update Rate</string>
<key>Key</key>
<string>UpdateRate</string>
<key>DefaultValue</key>
<string>1</string>
<key>Titles</key>
<array>
<string>Max</string>
<string>5 Hz</string>
<string>4 Hz</string>
<string>3 Hz</string>
<string>2 Hz</string>
<string>1 Hz</string>
<string>0.5 Hz</string>
</array>
<key>Values</key>
<array>
<string>0</string>
<string>5</string>
<string>4</string>
<string>3</string>
<string>2</string>
<string>1</string>
<string>0.5</string>
</array>
</dict>
<dict>
<key>Type</key>
<string>PSGroupSpecifier</string>
<key>FooterText</key>
<string>Images taken when the camera is moving too fast are ignored to avoid blurry textures.</string>
</dict>
<dict>
<key>Type</key>
<string>PSMultiValueSpecifier</string>
<key>Title</key>
<string>Maximum Motion Speed</string>
<key>Key</key>
<string>MaximumMotionSpeed</string>
<key>DefaultValue</key>
<string>0</string>
<key>Titles</key>
<array>
<string>No Limit</string>
<string>High</string>
<string>Medium</string>
<string>Low</string>
<string>Very Low</string>
</array>
<key>Values</key>
<array>
<string>0</string>
<string>0.4</string>
<string>0.3</string>
<string>0.2</string>
<string>0.1</string>
</array>
</dict>
<dict>
<key>Type</key>
<string>PSGroupSpecifier</string>
<key>FooterText</key>
<string>Maximum time allowed for map updates. If time to add a new node is above this theshold, some old parts of the map are temporarly forgotten to reduce time of next updates.</string>
</dict>
<dict>
<key>Type</key>
<string>PSMultiValueSpecifier</string>
<key>Title</key>
<string>Time Limit</string>
<key>Key</key>
<string>TimeLimit</string>
<key>DefaultValue</key>
<string>0</string>
<key>Titles</key>
<array>
<string>No Limit</string>
<string>1500 ms</string>
<string>1400 ms</string>
<string>1300 ms</string>
<string>1200 ms</string>
<string>1100 ms</string>
<string>1000 ms</string>
<string>900 ms</string>
<string>800 ms</string>
<string>700 ms</string>
<string>600 ms</string>
<string>500 ms</string>
<string>400 ms</string>
</array>
<key>Values</key>
<array>
<string>0</string>
<string>1500</string>
<string>1400</string>
<string>1300</string>
<string>1200</string>
<string>1100</string>
<string>1000</string>
<string>900</string>
<string>800</string>
<string>700</string>
<string>600</string>
<string>500</string>
<string>400</string>
</array>
</dict>
<dict>
<key>Type</key>
<string>PSGroupSpecifier</string>
<key>FooterText</key>
<string>Maximum nodes kept in working memory.</string>
</dict>
<dict>
<key>Type</key>
<string>PSMultiValueSpecifier</string>
<key>Title</key>
<string>Memory Limit</string>
<key>Key</key>
<string>MemoryLimit</string>
<key>DefaultValue</key>
<string>0</string>
<key>Titles</key>
<array>
<string>No Limit</string>
<string>500 nodes</string>
<string>400 nodes</string>
<string>300 nodes</string>
<string>200 nodes</string>
<string>100 nodes</string>
<string>50 nodes</string>
</array>
<key>Values</key>
<array>
<string>0</string>
<string>500</string>
<string>400</string>
<string>300</string>
<string>200</string>
<string>100</string>
<string>50</string>
</array>
</dict>
<dict>
<key>Type</key>
<string>PSGroupSpecifier</string>
<key>FooterText</key>
<string>Proximity detections are loop closures found by comparing current frame with frames inside a radius of the current pose. Unlike global loop closure detection, this approach is dependent of odometry.</string>
</dict>
<dict>
<key>Type</key>
<string>PSToggleSwitchSpecifier</string>
<key>Title</key>
<string>Proximity Detection</string>
<key>Key</key>
<string>ProximityDetection</string>
<key>DefaultValue</key>
<true/>
</dict>
<dict>
<key>Type</key>
<string>PSGroupSpecifier</string>
<key>FooterText</key>
<string>Threshold at which loop closure hypotheses are accepted. Higher means more robust to false loop closures while rejecting more good loop closures.</string>
</dict>
<dict>
<key>Type</key>
<string>PSMultiValueSpecifier</string>
<key>Title</key>
<string>Loop Closure Threshold</string>
<key>Key</key>
<string>LoopClosureThreshold</string>
<key>DefaultValue</key>
<real>0.11</real>
<key>Titles</key>
<array>
<string>0.90</string>
<string>0.80</string>
<string>0.70</string>
<string>0.60</string>
<string>0.50</string>
<string>0.40</string>
<string>0.30</string>
<string>0.20</string>
<string>0.15</string>
<string>0.11</string>
<string>0.10</string>
</array>
<key>Values</key>
<array>
<real>0.9</real>
<real>0.8</real>
<real>0.7</real>
<real>0.6</real>
<real>0.5</real>
<real>0.4</real>
<real>0.3</real>
<real>0.2</real>
<real>0.15</real>
<real>0.11</real>
<real>0.1</real>
</array>
</dict>
<dict>
<key>Type</key>
<string>PSGroupSpecifier</string>
<key>FooterText</key>
<string>Threshold at which consecutive images are considered the same, so the corresponding node&apos;s weight is increased. The background turns dark blue when this happens.</string>
</dict>
<dict>
<key>Type</key>
<string>PSMultiValueSpecifier</string>
<key>Title</key>
<string>Similarity Threshold</string>
<key>Key</key>
<string>SimilarityThreshold</string>
<key>DefaultValue</key>
<real>0.3</real>
<key>Titles</key>
<array>
<string>Disabled</string>
<string>0.60</string>
<string>0.50</string>
<string>0.40</string>
<string>0.30</string>
<string>0.20</string>
<string>0.10</string>
</array>
<key>Values</key>
<array>
<real>1</real>
<real>0.6</real>
<real>0.5</real>
<real>0.4</real>
<real>0.3</real>
<real>0.2</real>
<real>0.1</real>
</array>
</dict>
<dict>
<key>Type</key>
<string>PSGroupSpecifier</string>
<key>FooterText</key>
<string>Minimum visual inliers to accept a loop closure.</string>
</dict>
<dict>
<key>Type</key>
<string>PSMultiValueSpecifier</string>
<key>Title</key>
<string>Min Inliers</string>
<key>Key</key>
<string>MinInliers</string>
<key>DefaultValue</key>
<string>25</string>
<key>Titles</key>
<array>
<string>35</string>
<string>30</string>
<string>25</string>
<string>20</string>
<string>15</string>
<string>10</string>
</array>
<key>Values</key>
<array>
<string>35</string>
<string>30</string>
<string>25</string>
<string>20</string>
<string>15</string>
<string>10</string>
</array>
</dict>
<dict>
<key>Type</key>
<string>PSGroupSpecifier</string>
<key>FooterText</key>
<string>Reject any loop closures causing error corrections in the map higher than this factor of the link&apos;s variance.</string>
</dict>
<dict>
<key>Type</key>
<string>PSMultiValueSpecifier</string>
<key>Title</key>
<string>Max Optimization Error</string>
<key>Key</key>
<string>MaxOptimizationError</string>
<key>DefaultValue</key>
<integer>1</integer>
<key>Titles</key>
<array>
<string>4x</string>
<string>3.5x</string>
<string>3x</string>
<string>2.5x</string>
<string>2x</string>
<string>1.5x</string>
<string>1x</string>
<string>0.5x</string>
<string>Disabled</string>
</array>
<key>Values</key>
<array>
<real>4</real>
<real>3.5</real>
<real>3</real>
<real>2.5</real>
<real>2</real>
<real>1.5</real>
<real>1</real>
<real>0.5</real>
<real>0</real>
</array>
</dict>
<dict>
<key>Type</key>
<string>PSGroupSpecifier</string>
<key>FooterText</key>
<string>Extracting more features per image would result in better loop closure hypotheses but more processing time is required.</string>
</dict>
<dict>
<key>Type</key>
<string>PSMultiValueSpecifier</string>
<key>Title</key>
<string>Max Features Extracted (Vocabulary)</string>
<key>Key</key>
<string>MaxFeaturesExtractedVocabulary</string>
<key>DefaultValue</key>
<string>400</string>
<key>Titles</key>
<array>
<string>No Limit</string>
<string>1000</string>
<string>900</string>
<string>800</string>
<string>700</string>
<string>600</string>
<string>500</string>
<string>400</string>
<string>300</string>
<string>200</string>
<string>100</string>
<string>Disabled</string>
</array>
<key>Values</key>
<array>
<string>0</string>
<string>1000</string>
<string>900</string>
<string>800</string>
<string>700</string>
<string>600</string>
<string>500</string>
<string>400</string>
<string>300</string>
<string>200</string>
<string>100</string>
<string>-1</string>
</array>
</dict>
<dict>
<key>Type</key>
<string>PSGroupSpecifier</string>
<key>FooterText</key>
<string>Extracting more features per image would result in better loop closure transforms but more processing time is required.</string>
</dict>
<dict>
<key>Type</key>
<string>PSMultiValueSpecifier</string>
<key>Title</key>
<string>Max Features Extracted (Loop Closure)</string>
<key>Key</key>
<string>MaxFeaturesExtractedLoopClosure</string>
<key>DefaultValue</key>
<string>400</string>
<key>Titles</key>
<array>
<string>No Limit</string>
<string>1000</string>
<string>900</string>
<string>800</string>
<string>700</string>
<string>600</string>
<string>500</string>
<string>400</string>
<string>300</string>
<string>200</string>
<string>100</string>
</array>
<key>Values</key>
<array>
<string>0</string>
<string>1000</string>
<string>900</string>
<string>800</string>
<string>700</string>
<string>600</string>
<string>500</string>
<string>400</string>
<string>300</string>
<string>200</string>
<string>100</string>
</array>
</dict>
<dict>
<key>Type</key>
<string>PSGroupSpecifier</string>
<key>FooterText</key>
<string>BRIEF features are fast to compute but are not rotation invariant like FREAK. Warning: Changing feature type will automatically reset the map!</string>
</dict>
<dict>
<key>Type</key>
<string>PSMultiValueSpecifier</string>
<key>Title</key>
<string>Feature Type</string>
<key>Key</key>
<string>FeatureType</string>
<key>DefaultValue</key>
<string>6</string>
<key>Titles</key>
<array>
<string>BRIEF</string>
<string>FREAK</string>
</array>
<key>Values</key>
<array>
<string>6</string>
<string>5</string>
</array>
</dict>
<dict>
<key>Type</key>
<string>PSGroupSpecifier</string>
<key>FooterText</key>
<string>Graph optimization approach.</string>
</dict>
<dict>
<key>Type</key>
<string>PSMultiValueSpecifier</string>
<key>Title</key>
<string>Graph Optimizer</string>
<key>Key</key>
<string>GraphOptimizer</string>
<key>DefaultValue</key>
<string>2</string>
<key>Titles</key>
<array>
<string>GTSAM</string>
<string>g2o</string>
</array>
<key>Values</key>
<array>
<string>2</string>
<string>1</string>
</array>
</dict>
<dict>
<key>Type</key>
<string>PSGroupSpecifier</string>
<key>FooterText</key>
<string>The map&apos;s graph is optimized from the last node. The map is moved when a loop closure happens instead of jumping the current pose back to localized area.</string>
</dict>
<dict>
<key>Type</key>
<string>PSToggleSwitchSpecifier</string>
<key>Title</key>
<string>Optimization from Graph End</string>
<key>Key</key>
<string>OptimizationfromGraphEnd</string>
<key>DefaultValue</key>
<true/>
</dict>
<dict>
<key>Type</key>
<string>PSGroupSpecifier</string>
<key>FooterText</key>
<string>Used only in localization mode (when clicking First-P. View during visualization). This is used to get smoother localizations and to verify localization transforms (when Max Optimization Error is not disabled) to make sure we don't teleport to a location very similar to one we previously localized on.</string>
</dict>
<dict>
<key>Type</key>
<string>PSMultiValueSpecifier</string>
<key>Title</key>
<string>Maximum odometry cache size</string>
<key>Key</key>
<string>MaximumOdometryCacheSize</string>
<key>DefaultValue</key>
<string>10</string>
<key>Titles</key>
<array>
<string>500</string>
<string>200</string>
<string>100</string>
<string>75</string>
<string>50</string>
<string>40</string>
<string>30</string>
<string>20</string>
<string>10</string>
<string>5</string>
<string>Disabled</string>
</array>
<key>Values</key>
<array>
<string>500</string>
<string>200</string>
<string>100</string>
<string>75</string>
<string>50</string>
<string>40</string>
<string>30</string>
<string>20</string>
<string>10</string>
<string>5</string>
<string>0</string>
</array>
</dict>
<dict>
<key>Type</key>
<string>PSGroupSpecifier</string>
<key>FooterText</key>
<string>ArUco markers can be detected for localization and graph optimization.</string>
</dict>
<dict>
<key>Type</key>
<string>PSMultiValueSpecifier</string>
<key>Title</key>
<string>ArUco Marker Detection</string>
<key>Key</key>
<string>ArUcoMarkerDetection</string>
<key>DefaultValue</key>
<integer>-1</integer>
<key>Titles</key>
<array>
<string>Disabled</string>
<string>4X4_50</string>
<string>4X4_100</string>
<string>4X4_250</string>
<string>4X4_1000</string>
<string>5X5_50</string>
<string>5X5_100</string>
<string>5X5_250</string>
<string>5X5_1000</string>
<string>6X6_50</string>
<string>6X6_100</string>
<string>6X6_250</string>
<string>6X6_1000</string>
<string>7X7_50</string>
<string>7X7_100</string>
<string>7X7_250</string>
<string>7X7_1000</string>
<string>ARUCO_ORIGINAL</string>
<string>APRILTAG_16h5</string>
<string>APRILTAG_25h9</string>
<string>APRILTAG_36h10</string>
<string>APRILTAG_36h11</string>
</array>
<key>Values</key>
<array>
<integer>-1</integer>
<integer>0</integer>
<integer>1</integer>
<integer>2</integer>
<integer>3</integer>
<integer>4</integer>
<integer>5</integer>
<integer>6</integer>
<integer>7</integer>
<integer>8</integer>
<integer>9</integer>
<integer>10</integer>
<integer>11</integer>
<integer>12</integer>
<integer>13</integer>
<integer>14</integer>
<integer>15</integer>
<integer>16</integer>
<integer>17</integer>
<integer>18</integer>
<integer>19</integer>
<integer>20</integer>
</array>
</dict>
<dict>
<key>Type</key>
<string>PSGroupSpecifier</string>
<key>FooterText</key>
<string>Size of markers are automatically initialized on the first marker seen. All markers should have the same size. This value is the maximum depth error to do the initialization to get accurate size of the tag. The lower it is, the more perpendicular the camera should be from the marker to do initialization, but size estimated would be more accurate.</string>
</dict>
<dict>
<key>Type</key>
<string>PSMultiValueSpecifier</string>
<key>Title</key>
<string>Marker Depth Error Estimation</string>
<key>Key</key>
<string>MarkerDepthErrorEstimation</string>
<key>DefaultValue</key>
<real>0.04</real>
<key>Titles</key>
<array>
<string>1 cm</string>
<string>2 cm</string>
<string>3 cm</string>
<string>4 cm</string>
<string>5 cm</string>
<string>6 cm</string>
<string>7 cm</string>
<string>8 cm</string>
<string>9 cm</string>
<string>10 cm</string>
<string>15 cm</string>
<string>20 cm</string>
<string>30 cm</string>
<string>40 cm</string>
<string>50 cm</string>
<string>100 cm</string>
</array>
<key>Values</key>
<array>
<real>0.01</real>
<real>0.02</real>
<real>0.03</real>
<real>0.04</real>
<real>0.05</real>
<real>0.06</real>
<real>0.07000000000000001</real>
<real>0.08</real>
<real>0.09</real>
<real>0.1</real>
<real>0.15</real>
<real>0.2</real>
<real>0.3</real>
<real>0.4</real>
<real>0.5</real>
<real>1</real>
</array>
</dict>
<dict>
<key>Type</key>
<string>PSGroupSpecifier</string>
<key>FooterText</key>
<string>If marker size is 0, marker size is estimated using depth camera on first detection, then the same size is assumed for next detections, thus all markers should have the same size (markers could then be detected farther from the camera). When the marker size is set &gt;0, all markers are estimated with this parameter (this can be useful on devices without depth camera). Finally, if marker size is &lt;0, the size of each marker is estimated the first time they are detected using the depth camera (thus markers can have different size). Note that if the marker is already in the database with a known size, the size contained in the database is used directly.</string>
</dict>
<dict>
<key>Type</key>
<string>PSTextFieldSpecifier</string>
<key>Title</key>
<string>Marker Size (cm)</string>
<key>Key</key>
<string>MarkerSize</string>
<key>DefaultValue</key>
<string>-1</string>
<key>KeyboardType</key>
<string>NumberPad</string>
</dict>
<dict>
<key>Type</key>
<string>PSGroupSpecifier</string>
<key>Title</key>
<string>Database</string>
<key>FooterText</key>
<string>Discarded frames while not moving are still saved in database. Useful to replay exactly the scanning on RTAB-Map Desktop.</string>
</dict>
<dict>
<key>Type</key>
<string>PSToggleSwitchSpecifier</string>
<key>Title</key>
<string>Save All Frames in Database</string>
<key>Key</key>
<string>SaveAllFramesInDatabase</string>
<key>DefaultValue</key>
<true/>
</dict>
<dict>
<key>Type</key>
<string>PSGroupSpecifier</string>
<key>FooterText</key>
<string>Save raw point clouds in database.</string>
</dict>
<dict>
<key>Type</key>
<string>PSToggleSwitchSpecifier</string>
<key>Title</key>
<string>Save Raw Scan</string>
<key>Key</key>
<string>SaveRawScan</string>
<key>DefaultValue</key>
<true/>
</dict>
<dict>
<key>Type</key>
<string>PSGroupSpecifier</string>
<key>FooterText</key>
<string>Save GPS to database.</string>
</dict>
<dict>
<key>Type</key>
<string>PSToggleSwitchSpecifier</string>
<key>Title</key>
<string>Save GPS</string>
<key>Key</key>
<string>SaveGPS</string>
<key>DefaultValue</key>
<false/>
</dict>
<dict>
<key>Type</key>
<string>PSGroupSpecifier</string>
<key>FooterText</key>
<string>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>
</dict>
<dict>
<key>Type</key>
<string>PSToggleSwitchSpecifier</string>
<key>Title</key>
<string>Database in Memory</string>
<key>Key</key>
<string>DatabaseInMemory</string>
<key>DefaultValue</key>
<false/>
</dict>
</array>
</dict>
</plist>

View File

@@ -0,0 +1,487 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PreferenceSpecifiers</key>
<array>
<dict>
<key>FooterText</key>
<string>Decrease density to reduce rendering time and memory. Tip: To apply a different density to current map: save the map, change density and re-open the same map to regenerate the point clouds at this density. Points over the maximum depth, under minimum depth or under the depth confidence are not rendered.</string>
<key>Title</key>
<string>Rendering</string>
<key>Type</key>
<string>PSGroupSpecifier</string>
</dict>
<dict>
<key>DefaultValue</key>
<integer>1</integer>
<key>Key</key>
<string>PointCloudDensity</string>
<key>Title</key>
<string>Point Cloud Density</string>
<key>Titles</key>
<array>
<string>Maximum</string>
<string>High</string>
<string>Low</string>
<string>Very Low</string>
</array>
<key>Type</key>
<string>PSMultiValueSpecifier</string>
<key>Values</key>
<array>
<integer>0</integer>
<integer>1</integer>
<integer>2</integer>
<integer>3</integer>
</array>
</dict>
<dict>
<key>DefaultValue</key>
<integer>3</integer>
<key>Key</key>
<string>MaxDepth</string>
<key>Title</key>
<string>Max Depth</string>
<key>Titles</key>
<array>
<string>No Limit</string>
<string>5 m</string>
<string>4.5 m</string>
<string>4 m</string>
<string>3.5 m</string>
<string>3 m</string>
<string>2.5 m</string>
<string>2 m</string>
<string>1.5 m</string>
<string>1 m</string>
</array>
<key>Type</key>
<string>PSMultiValueSpecifier</string>
<key>Values</key>
<array>
<real>0.0</real>
<real>5</real>
<real>4.5</real>
<real>4</real>
<real>3.5</real>
<real>3</real>
<real>2.5</real>
<real>2</real>
<real>1.5</real>
<real>1</real>
</array>
</dict>
<dict>
<key>DefaultValue</key>
<real>0.0</real>
<key>Key</key>
<string>MinDepth</string>
<key>Title</key>
<string>Min Depth</string>
<key>Titles</key>
<array>
<string>0 m</string>
<string>0.3 m</string>
<string>0.5 m</string>
<string>0.75 m</string>
<string>1 m</string>
<string>1.5 m</string>
<string>2 m</string>
<string>2.5 m</string>
<string>3 m</string>
</array>
<key>Type</key>
<string>PSMultiValueSpecifier</string>
<key>Values</key>
<array>
<real>0.0</real>
<real>0.29999999999999999</real>
<real>0.5</real>
<real>0.75</real>
<real>1</real>
<real>1.5</real>
<real>2</real>
<real>2.5</real>
<real>3</real>
</array>
</dict>
<dict>
<key>DefaultValue</key>
<integer>2</integer>
<key>Key</key>
<string>DepthConfidence</string>
<key>Title</key>
<string>Depth Confidence</string>
<key>Titles</key>
<array>
<string>High</string>
<string>Medium</string>
<string>Low</string>
</array>
<key>Type</key>
<string>PSMultiValueSpecifier</string>
<key>Values</key>
<array>
<integer>2</integer>
<integer>1</integer>
<integer>0</integer>
</array>
</dict>
<dict>
<key>FooterText</key>
<string>Increase minimum polygon angle to force scanning perpendicular to surfaces. Set a decimation factor to reduce the number of polygons. The higher the factor, the less polygons will remain. Note that the decimation factor is done after decreasing point cloud density. Decimation factor and texture resolution don't affect post-processing.</string>
<key>Type</key>
<string>PSGroupSpecifier</string>
</dict>
<dict>
<key>DefaultValue</key>
<integer>20</integer>
<key>Key</key>
<string>MeshAngleTolerance</string>
<key>Title</key>
<string>Mesh Angle Tolerance (deg)</string>
<key>Titles</key>
<array>
<string>60</string>
<string>45</string>
<string>35</string>
<string>30</string>
<string>25</string>
<string>20</string>
<string>15</string>
<string>10</string>
<string>5</string>
</array>
<key>Type</key>
<string>PSMultiValueSpecifier</string>
<key>Values</key>
<array>
<integer>60</integer>
<integer>45</integer>
<integer>35</integer>
<integer>30</integer>
<integer>25</integer>
<integer>20</integer>
<integer>15</integer>
<integer>10</integer>
<integer>5</integer>
</array>
</dict>
<dict>
<key>DefaultValue</key>
<integer>2</integer>
<key>Key</key>
<string>MeshTriangleSize</string>
<key>Title</key>
<string>Mesh Triangle Size</string>
<key>Titles</key>
<array>
<string>6 pix</string>
<string>5 pix</string>
<string>4 pix</string>
<string>3 pix</string>
<string>2 pix</string>
</array>
<key>Type</key>
<string>PSMultiValueSpecifier</string>
<key>Values</key>
<array>
<integer>6</integer>
<integer>5</integer>
<integer>4</integer>
<integer>3</integer>
<integer>2</integer>
</array>
</dict>
<dict>
<key>DefaultValue</key>
<real>0.0</real>
<key>Key</key>
<string>MeshDecimationFactor</string>
<key>Title</key>
<string>Mesh Decimation Factor</string>
<key>Titles</key>
<array>
<string>99%</string>
<string>95%</string>
<string>90%</string>
<string>80%</string>
<string>70%</string>
<string>60%</string>
<string>50%</string>
<string>40%</string>
<string>30%</string>
<string>20%</string>
<string>10%</string>
<string>Disabled</string>
</array>
<key>Type</key>
<string>PSMultiValueSpecifier</string>
<key>Values</key>
<array>
<real>0.98999999999999999</real>
<real>0.94999999999999996</real>
<real>0.90000000000000002</real>
<real>0.80000000000000004</real>
<real>0.69999999999999996</real>
<real>0.59999999999999998</real>
<real>0.5</real>
<real>0.40000000000000002</real>
<real>0.29999999999999999</real>
<real>0.20000000000000001</real>
<real>0.10000000000000001</real>
<real>0.0</real>
</array>
</dict>
<dict>
<key>DefaultValue</key>
<integer>4</integer>
<key>Key</key>
<string>TextureResolution</string>
<key>Title</key>
<string>Texture Resolution</string>
<key>Titles</key>
<array>
<string>Maximum</string>
<string>High</string>
<string>Low</string>
<string>Very Low</string>
</array>
<key>Type</key>
<string>PSMultiValueSpecifier</string>
<key>Values</key>
<array>
<integer>1</integer>
<integer>2</integer>
<integer>4</integer>
<integer>8</integer>
</array>
</dict>
<dict>
<key>FooterText</key>
<string>Enable Blending to get smoother colors on overlapping surfaces. When Nodes Filetring is enabled, only the newest point clouds of loop closures are rendered.</string>
<key>Type</key>
<string>PSGroupSpecifier</string>
</dict>
<dict>
<key>DefaultValue</key>
<real>0.20000000000000001</real>
<key>Key</key>
<string>BackgroundColor</string>
<key>Title</key>
<string>Background Color</string>
<key>Titles</key>
<array>
<string>0.9</string>
<string>Light Gray</string>
<string>0.7</string>
<string>0.6</string>
<string>Gray</string>
<string>0.4</string>
<string>0.3</string>
<string>Dark Gray</string>
<string>0.1</string>
<string>Black</string>
</array>
<key>Type</key>
<string>PSMultiValueSpecifier</string>
<key>Values</key>
<array>
<real>0.90000000000000002</real>
<real>0.80000000000000004</real>
<real>0.69999999999999996</real>
<real>0.59999999999999998</real>
<real>0.5</real>
<real>0.40000000000000002</real>
<real>0.29999999999999999</real>
<real>0.20000000000000001</real>
<real>0.10000000000000001</real>
<real>0.0</real>
</array>
</dict>
<dict>
<key>DefaultValue</key>
<integer>10</integer>
<key>Key</key>
<string>PointSize</string>
<key>Title</key>
<string>Point Size</string>
<key>Titles</key>
<array>
<string>50</string>
<string>30</string>
<string>25</string>
<string>15</string>
<string>10</string>
<string>5</string>
<string>1</string>
</array>
<key>Type</key>
<string>PSMultiValueSpecifier</string>
<key>Values</key>
<array>
<integer>50</integer>
<integer>30</integer>
<integer>25</integer>
<integer>15</integer>
<integer>10</integer>
<integer>5</integer>
<integer>1</integer>
</array>
</dict>
<dict>
<key>DefaultValue</key>
<true/>
<key>Key</key>
<string>Blending</string>
<key>Title</key>
<string>Blending</string>
<key>Type</key>
<string>PSToggleSwitchSpecifier</string>
</dict>
<dict>
<key>DefaultValue</key>
<false/>
<key>Key</key>
<string>NodesFiltering</string>
<key>Title</key>
<string>Nodes Filtering</string>
<key>Type</key>
<string>PSToggleSwitchSpecifier</string>
</dict>
<dict>
<key>Title</key>
<string>General</string>
<key>Type</key>
<string>PSGroupSpecifier</string>
</dict>
<dict>
<key>File</key>
<string>Mapping</string>
<key>Title</key>
<string>Mapping...</string>
<key>Type</key>
<string>PSChildPaneSpecifier</string>
</dict>
<dict>
<key>File</key>
<string>Assembling</string>
<key>Title</key>
<string>Assembling...</string>
<key>Type</key>
<string>PSChildPaneSpecifier</string>
</dict>
<dict>
<key>FooterText</key>
<string>Color CorrectionRadius is used to find pixel correspondences for Adjust Colors optimization. Noise Filtering Ratio is used to remove polygon clusters smaller than this ratio of the largest cluster during Noise Filtering optimization.</string>
<key>Title</key>
<string>Optimization</string>
<key>Type</key>
<string>PSGroupSpecifier</string>
</dict>
<dict>
<key>DefaultValue</key>
<real>0.02</real>
<key>Key</key>
<string>ColorCorrectionRadius</string>
<key>Title</key>
<string>Color Correction Radius</string>
<key>Titles</key>
<array>
<string>30 cm</string>
<string>20 cm</string>
<string>10 cm</string>
<string>5 cm</string>
<string>2.5 cm</string>
<string>2 cm</string>
<string>1.5 cm</string>
<string>1 cm</string>
</array>
<key>Type</key>
<string>PSMultiValueSpecifier</string>
<key>Values</key>
<array>
<real>0.29999999999999999</real>
<real>0.20000000000000001</real>
<real>0.10000000000000001</real>
<real>0.050000000000000003</real>
<real>0.025000000000000001</real>
<real>0.02</real>
<real>0.014999999999999999</real>
<real>0.01</real>
</array>
</dict>
<dict>
<key>DefaultValue</key>
<real>0.050000000000000003</real>
<key>Key</key>
<string>NoiseFilteringRatio</string>
<key>Title</key>
<string>Noise Filtering Ratio</string>
<key>Titles</key>
<array>
<string>Keep Largest Only</string>
<string>0.9</string>
<string>0.8</string>
<string>0.7</string>
<string>0.6</string>
<string>0.5</string>
<string>0.4</string>
<string>0.3</string>
<string>0.2</string>
<string>0.1</string>
<string>0.05</string>
<string>0.01</string>
</array>
<key>Type</key>
<string>PSMultiValueSpecifier</string>
<key>Values</key>
<array>
<real>1</real>
<real>0.90000000000000002</real>
<real>0.80000000000000004</real>
<real>0.69999999999999996</real>
<real>0.59999999999999998</real>
<real>0.5</real>
<real>0.40000000000000002</real>
<real>0.29999999999999999</real>
<real>0.20000000000000001</real>
<real>0.10000000000000001</real>
<real>0.050000000000000003</real>
<real>0.01</real>
</array>
</dict>
<dict>
<key>FooterText</key>
<string>Copyright (c) 2010-2022, Mathieu Labbe - IntRoLab - Université de Sherbrooke. All rights reserved.</string>
<key>Title</key>
<string>About</string>
<key>Type</key>
<string>PSGroupSpecifier</string>
</dict>
<dict>
<key>DefaultValue</key>
<string>0.20.19</string>
<key>Key</key>
<string>Version</string>
<key>Title</key>
<string>Version</string>
<key>Type</key>
<string>PSTitleValueSpecifier</string>
</dict>
<dict>
<key>File</key>
<string>License</string>
<key>Key</key>
<string></string>
<key>Title</key>
<string>License</string>
<key>Type</key>
<string>PSChildPaneSpecifier</string>
</dict>
</array>
<key>StringsTable</key>
<string>Root</string>
</dict>
</plist>

Binary file not shown.

View File

@@ -4,6 +4,7 @@ SET(SRC_FILES
)
SET(INCLUDE_DIRS
${PROJECT_BINARY_DIR}/corelib/include
${PROJECT_SOURCE_DIR}/utilite/include
${PROJECT_SOURCE_DIR}/corelib/include
${PROJECT_SOURCE_DIR}/guilib/include
@@ -134,6 +135,24 @@ IF(BUILD_AS_BUNDLE AND (APPLE OR WIN32))
COMPONENT runtime)
ENDIF(WIN32)
ENDIF(k4a_FOUND)
IF(Torch_FOUND)
# Install needed cudnn_ops_infer64_8.dll and cudnn_cnn_infer64_8.dll
# TODO: should be a more general way to include them if version is different
IF(WIN32 AND CUDA_FOUND)
find_file(CUDNN_OPS_DLL NAMES cudnn_ops_infer64_8.dll)
find_file(CUDNN_CNN_DLL NAMES cudnn_cnn_infer64_8.dll)
IF(CUDNN_OPS_DLL AND CUDNN_CNN_DLL)
MESSAGE(STATUS "Found ${CUDNN_OPS_DLL}")
MESSAGE(STATUS "Found ${CUDNN_CNN_DLL}")
INSTALL(FILES ${CUDNN_OPS_DLL} ${CUDNN_CNN_DLL}
DESTINATION ${plugin_dest_dir}
COMPONENT runtime)
ELSE()
MESSAGE(AUTHOR_WARNING "Using Torch with CUDA, but cudnn_ops_infer64_8.dll and cudnn_cnn_infer64_8.dll are not found on the PATH, so it won't be added to package.")
ENDIF()
ENDIF(WIN32 AND CUDA_FOUND)
ENDIF(Torch_FOUND)
# Install needed Qt plugins by copying directories from the qt installation
# One can cull what gets copied by using 'REGEX "..." EXCLUDE'
@@ -153,17 +172,17 @@ 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)
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()
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")
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)

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