Compare commits

..

539 Commits

Author SHA1 Message Date
matlabbe
5e79fc559b merged master->jazzy 2024-07-22 20:59:09 -07:00
matlabbe
24ca56248f bump patch 2024-07-22 20:47:59 -07:00
matlabbe
0efd3c6b62 Merge branch 'clalancette-clalancette/switch-octomap-dependency' 2024-07-22 20:44:51 -07:00
matlabbe
49d67302d5 removed jazzy/rolling specific patches 2024-07-22 20:41:05 -07:00
matlabbe
41dcddc48e Merge branch 'clalancette/switch-octomap-dependency' of https://github.com/clalancette/rtabmap into clalancette-clalancette/switch-octomap-dependency 2024-07-22 20:39:56 -07:00
Chris Lalancette
ccca53be03 Switch the octomap dependency to the system version.
We are shortly going to be removing octomap the package
from ROS 2 Rolling; that's because it's ABI conflicts with
the system package.  Instead, switch rtabmap to use the system
package, which should work fine.

Signed-off-by: Chris Lalancette <clalancette@gmail.com>
2024-07-22 19:25:27 +00:00
matlabbe
08a44ec44f DBViewer: added option to ignore optimized graph guess when detecting more loop closures 2024-07-19 14:02:03 -07:00
matlabbe
04fdc0d9e2 Merge branch 'jazzy-devel' of github.com:introlab/rtabmap into jazzy-devel 2024-06-30 19:50:45 -07:00
matlabbe
41fe47efdf Fixed build with OpenCV 3.2 (ubuntu bionic). Added more devcontainers for different ubuntu versions for convenience. 2024-06-30 19:11:14 -07:00
matlabbe
7641f28250 Fixed build with OpenCV >= 4.7 (charucoboard errors) 2024-06-30 18:15:56 -07:00
matlabbe
f5a477f0f4 Charuco calibration + depthai calibration support (#1302)
* In progress: adding charuco option

* DepthAI: added raw image publishing mode (added support rtabmap's calibration file). Calibration: working charuco board calibration (on opencv 4.5).

* fixed build with Qt<5.14

* Updated calibration options

* Removed depthai flashing delays

* depthai: fixed camera not detected as calibrated in Mono-depth mode. Calibration: added option to scale sampling factor.
2024-06-30 17:11:37 -07:00
matlabbe
2fbe31f7cb Split dev containers for standalone and android 2024-06-28 08:08:40 -07:00
matlabbe
623d056436 fixed android build 2024-06-26 05:43:17 +00:00
matlabbe
1611aa14f6 fixed typo 2024-06-25 13:21:02 -07:00
matlabbe
7d970ef020 Fixed DBReader odometry ignored 2024-06-25 12:04:37 -07:00
matlabbe
1ab0133f14 Added uPad function for convenience 2024-06-19 15:58:24 -07:00
matlabbe
4c1822683a Added new parameter: RGBD/AggressiveLoopThr 2024-06-19 10:28:17 -07:00
matlabbe
7c601bb6e8 Fixed #1300 (proximity sort by distance) 2024-06-16 11:11:39 -07:00
matlabbe
0d221a806f Update behavior of Odom/AlignWithGround when odmetry is already aligned with gravity (just update z value). 2024-06-15 17:24:00 -07:00
matlabbe
28fd696c18 Fixed WITH_QT=OFF (to not build with Qt even if any dependency included it) 2024-06-15 14:21:51 -07:00
Adam Serafin
c58fffe56d Add flags for OpenNI (#1299)
* update openni defines

* minor fix

* fixed build + minor changes

---------

Co-authored-by: matlabbe <matlabbe@gmail.com>
2024-06-15 14:12:07 -07:00
matlabbe
2a840fe340 Fixed https://github.com/introlab/rtabmap_ros/issues/1173 (edited optimized map regenerated in localization mode) 2024-06-09 20:46:51 -07:00
matlabbe
0f03db9d7f Disabling temporary cmake-ros workflow on ubuntu 24.04/jazzy because of setup-ros failing on that base image 2024-06-09 11:36:49 -07:00
matlabbe
4349f304d2 Merge branch 'borongyuan-xvisio' 2024-06-09 11:13:51 -07:00
matlabbe
80a4ce02c9 Fixed build without xvisio sdk, Added xvisio camera option in main menu. 2024-06-09 11:13:29 -07:00
matlabbe
b37f7d6351 docker: Fixed typo 2024-06-09 10:20:18 -07:00
matlabbe
35d4bd768c ci/noble: moved opengv to top image to be built on ci 2024-06-09 10:20:18 -07:00
matlabbe
e6691658bd Fixed compilation warnings on 22.04 (Qt 5.15.3) 2024-06-09 10:20:18 -07:00
matlabbe
3cfcccdb1d Added CI for Ubuntu Noble/24.04 + docker 2024-06-09 10:20:18 -07:00
matlabbe
8310925c81 Calibration tool: added support for rational model (8 coeff) 2024-06-09 10:20:18 -07:00
matlabbe
99cb02fdff ORB_SLAM3: fixed error if left image is color. SensorCaptureThread: stop thread if data cannot be captured (e.g., end of dataset) instead of skipping indefinitly with error log. 2024-06-09 10:20:18 -07:00
matlabbe
8b372b52ac arcore_java: fixed high speed filtering jumping (#1281) 2024-06-09 10:20:18 -07:00
matlabbe
c25add868a arcore_java: disabled max speed localization filtering by default #1281 2024-06-09 10:20:18 -07:00
matlabbe
91cbbc8238 arcore: fixed pose not updated correctly 2024-06-09 10:20:18 -07:00
matlabbe
ccdddfc83f Refactored android docker to easily re-use rtabmap.bash in a dev container to install Tango/ARCore/AREngine dependencies. 2024-06-09 10:19:22 -07:00
matlabbe
9b255d1f27 docker: Fixed typo 2024-06-03 20:12:17 -07:00
matlabbe
3ab8ae7eaf ci/noble: moved opengv to top image to be built on ci 2024-06-03 07:33:26 -07:00
Borong Yuan
a327c9530c add XVSDK VIO 2024-06-03 10:28:45 +08:00
matlabbe
5b810da73b Fixed compilation warnings on 22.04 (Qt 5.15.3) 2024-06-02 15:04:36 -07:00
matlabbe
098301e52c Added CI for Ubuntu Noble/24.04 + docker 2024-06-02 14:38:50 -07:00
matlabbe
f2df35be01 Disabling gtsam ros dep for now (internal version error) for ROS2 Jazzy 2024-06-02 14:06:16 -07:00
matlabbe
2f21d42555 Calibration tool: added support for rational model (8 coeff) 2024-05-31 10:28:14 -07:00
Borong Yuan
fc9dcd6b3d rectify xvDepthColor 2024-05-30 19:41:48 +08:00
Borong Yuan
0ad1d0ad69 add CameraSeerSense to guilib 2024-05-30 16:55:37 +08:00
Borong Yuan
ce0c806d75 add CameraSeerSense methods 2024-05-29 19:41:14 +08:00
Borong Yuan
fb37b3adba add xvDepthColor 2024-05-28 17:08:49 +08:00
matlabbe
0f961783c1 merged master->rolling 2024-05-27 11:42:12 -07:00
matlabbe
da9ff08198 Removed grid_map_core missing dep on jazzy 2024-05-27 10:49:18 -07:00
matlabbe
32e03aaf68 ORB_SLAM3: fixed error if left image is color. SensorCaptureThread: stop thread if data cannot be captured (e.g., end of dataset) instead of skipping indefinitly with error log. 2024-05-26 18:04:07 -07:00
matlabbe
03afb94d92 arcore_java: fixed high speed filtering jumping (#1281) 2024-05-25 15:54:57 -07:00
matlabbe
c5c190a2a0 arcore_java: disabled max speed localization filtering by default #1281 2024-05-25 14:42:54 -07:00
matlabbe
bc66060fab arcore: fixed pose not updated correctly 2024-05-25 13:50:01 -07:00
Borong Yuan
3d5f1ad5c2 add xvImu 2024-05-24 23:12:16 +08:00
Borong Yuan
41a7eff8fa init CameraSeerSense 2024-05-23 20:51:13 +08:00
Borong Yuan
6acec02dbe add xvsdk cmake configs 2024-05-23 17:02:38 +08:00
Borong Yuan
fbeabf0751 Add ANMS (SSC method) (#1276) 2024-05-19 18:21:00 -07:00
matlabbe
0d4e4730c7 Merge branch 'borongyuan-likelihood_experiment' 2024-05-19 17:46:47 -07:00
matlabbe
995f65b2ec Added parameter Rtabmap/VirtualPlaceLikelihoodRatio to select how likelihood is normalized/adjusted (0=default old approach used in paper). 2024-05-19 17:46:00 -07:00
matlabbe
c034a9631c Merge branch 'likelihood_experiment' of https://github.com/borongyuan/rtabmap into borongyuan-likelihood_experiment 2024-05-19 14:57:58 -07:00
matlabbe
256dcbded4 Added script to reproduce results from loop closure detection paper. Added option to show Recall at 100% precision directly from rtabmap-console. Fixed retrieval not working on loop closure detection mode-only. Fixed showLogs.m error with Octave. 2024-05-19 14:54:37 -07:00
matlabbe
812caeeb9a docker: added libtbb-dev 2024-05-12 22:15:20 -07:00
matlabbe
a66564f98f docker/jammy/jammy-iron: added WITH_TBB option for opencv 2024-05-12 20:36:27 -07:00
matlabbe
375597af00 docker/focal: added WITH_TBB option for opencv 2024-05-12 19:58:12 -07:00
matlabbe
72d7418011 Fixed build with pcl<1.8 2024-05-12 19:13:05 -07:00
matlabbe
9505a21a7e DBViewer/Matcher tool: Fixed crash when python feature/matcher is used 2024-04-28 17:40:37 -07:00
matlabbe
36304b2cd1 frontiers docker: added missing pybind-dev dep 2024-04-28 11:46:37 -07:00
Borong Yuan
f3cfa7831d adjust likelihood using z-score 2024-04-28 12:22:26 +08:00
matlabbe
99c4612c64 Fixed #1268. Fixed ui warnings of labels with same name. 2024-04-27 14:58:33 -07:00
matlabbe
27dea71398 Apply fix from #979 2024-04-15 20:51:50 -07:00
matlabbe
726bceb816 fixing bionic build 2024-04-14 19:46:34 -07:00
matlabbe
700704bec9 LiDAR capture support in standalone library (#1264)
* Working rtabmap_lidar-mapping example (live and pcap)

* finalizing merge, added some deprecated

* fixed build

* Working deskewing for Lidar + Camera/IMU (no camera pose correction yet) and Lidar + Odom Sensor in main UI.

* backward compatibility

* fixed some not used variable warnings, fixed qt build for lidar mapping example

* Refactored CameraMobile, added AREngine background support, fixed LidarVPL16 build error with PCL 1.8

* ARCoreJava: buffer last depth image in case its stamp i higher than pose stamp. CameraMobile: added pose buffer. SensorCaptureThread: to get pose, odomSensor should be explicitly set, but can be same as lidar or camera  inputs.

* Working external lidar on iOS

* util3d::commonFiltering()/adjustNormalsToViewPoint() added organized cloud support. MainWindow: updated odomSensor setup

* fixed winsock include order

* reverted camera tool

* disable imu filtering when odom sensor is used

* Updated package version

* fixed windows build

* fixing more windows build erros
2024-04-14 19:06:04 -07:00
matlabbe
6a6913c939 Fixed #1262 2024-04-13 16:42:58 -07:00
Borong Yuan
a55b4203cd copy global descriptor (#1263) 2024-04-13 14:56:28 -07:00
matlabbe
a3267c9da6 UI: Added option to change map resolution on UI side, save/restore thresholds in figures, fixed basic panel's slam/rgbd mode checkboxes not changing the state of corresponding parameters. 2024-04-12 17:12:23 -07:00
matlabbe
fbbab1c077 Update README.md 2024-04-11 17:12:11 -07:00
mathieu86
4e7110930c DbViewer: switch between left and right views when double-clicking on single nodes 2024-04-11 13:01:00 -07:00
matlabbe
9266926a4a docker: enabled focal linux/arm/v7 2024-04-10 09:13:24 -07:00
Dominic Létourneau
5a159cef04 Create scheduled-stats.yml (#1260)
GitHub Stats for IntRoLab.
2024-04-09 09:09:21 -07:00
matlabbe
5ed1bf0ca8 GlobalDescriptor (PyDescriptor / netvlad) (#1163)
* First commit for pydescriptor

* Fixed Python refactoring errors

* GUI: added PyDescriptor parameters

* reordered python3 includes

* updated rtabmap_netvlad.py test main

* fixed build from last merge

* integrated https://github.com/introlab/rtabmap/pull/1255

* rescaled dot product result

Closing https://github.com/introlab/rtabmap/issues/1105
2024-04-07 15:48:16 -07:00
matlabbe
c33e995e83 Landmark constraints can now be rejected (in case we see same landmark at two different spots or constraint is poorly estimated). Optimizer/Robust can now be used with landmark constraints with orientation. 2024-04-06 13:41:03 -07:00
matlabbe
92edae35fc Fixed map empty on start if there is no global loop closure yet in localization mode when RGBD/OptimizeFromGraphEnd is true 2024-04-06 11:46:26 -07:00
matlabbe
d794669ef9 DBViewer: added buttons to edit/add priors 2024-04-02 17:37:52 -07:00
matlabbe
9cb0046734 fixing build with gtsam 4.0 2024-04-02 15:32:04 -07:00
matlabbe
76f63ab79a Fixing build with gtsam 4.2 2024-04-02 13:29:51 -07:00
matlabbe
063ca9c8ee fixed gtsam 4.3 build error (https://github.com/introlab/rtabmap/pull/1033#issuecomment-2031002034) 2024-04-01 23:05:16 -07:00
matlabbe
11adbdcc9f Fixed #1253 2024-03-31 14:53:00 -07:00
matlabbe
8612ebba93 fixed https://github.com/introlab/rtabmap_ros/issues/1134 2024-03-31 13:06:52 -07:00
matlabbe
a0476af896 UI: Exposed more depthai options, setting default rectification alpha to -1 to avoid OAK-D Pro crash 2024-03-30 18:08:32 -07:00
matlabbe
3b735907c8 DbViewer tool: added database's parameter overriding from arguments 2024-03-29 13:30:12 -07:00
matlabbe
0ba79be461 depthai >=2.24 requirement 2024-03-28 14:27:17 -07:00
matlabbe
cc17ebe92b iSAM2 integration (#1249)
* isam2 integration

* fonctional iSAM2, added related parameters

* updated default params after testing large-scale enviroment

* proximity search optimization

* boost<1.68 fix

* boost version

* Fixed map not showing in graphview

* iSAM2: supporting MM/localization/multi-session modes
2024-03-27 17:18:02 -07:00
Borong Yuan
bfeb487dba OAK Internal Sync & DepthAI HF-Net Support (#1193)
* Using Sync Node

* Using normalized IR intensity

* Set IMU output frequency to 200 Hz

* set sync threshold properly

* add depthai hfnet local head

* fix DB error

* add depthai hfnet global head

* fix data delay if image rate is set manually
2024-03-27 12:29:06 -07:00
matlabbe
bc6d390fb6 bionic docker: fixing cmake version for arm 2024-03-24 18:49:11 -07:00
matlabbe
f8a63ecf10 Fixing bionic docker (with cmake>=3.14) 2024-03-23 14:41:10 -07:00
matlabbe
7183b43c2a missed part from last commit 2024-03-23 14:34:54 -07:00
matlabbe
fa3ece5183 Increased minimal cmake version to 3.14 to use cmake's official FindSQLite3.cmake (#1250) 2024-03-23 14:32:18 -07:00
matlabbe
2f132b3a40 GUI: adjusted max limit of Optimizer/Epsilon 2024-03-19 16:34:11 -07:00
matlabbe
79dc180bf4 Fixed Odom/ResetCountdown not resetting anymore if next frame is also bad. 2024-03-17 17:19:08 -07:00
matlabbe
264c560a2c reverted 87faea7a85 for #783 (just don't include OptimizerCeres if -DWITH_CERES=OFF even if floam or okvis did include it) 2024-03-16 17:10:34 -07:00
matlabbe
4ce36ef245 Updated appveyor gdown version 2024-03-13 23:27:47 -07:00
matlabbe
d0227694c5 small fix for qt6 2024-03-13 22:52:44 -07:00
matlabbe
a6d9425bce DBViewer: support doubleclick on node or link in graphview to update correpsonding image view and constraints view, also added "Show pixel depth" menu option in ImageView to show pixel depth and pixel coordinate in map frame. 2024-03-13 22:42:47 -07:00
matlabbe
e299505a64 Fixed ORB_SLAM3 config for stereo mode 2024-03-12 23:13:06 -07:00
matlabbe
57b4954cb3 Update README.md 2024-03-10 15:24:48 -07:00
matlabbe
2577c47e77 Fixed #1232 2024-03-09 15:14:01 -08:00
matlabbe
52e1b01597 Fixed assert when exporting textured mesh with both multiband and blending enabled with grayscale images 2024-03-04 17:05:17 -08:00
matlabbe
8019a2dc49 Fixed #1227 2024-03-02 16:17:10 -08:00
matlabbe
33b875ecbf GraphView: fixed mouse cursor tracking inverted x-y values 2024-03-01 10:13:53 -08:00
matlabbe
c24f95a8d9 ExportCloudsDialog: added option to filter off-axis points 2024-02-29 16:19:57 -08:00
matlabbe
6f7e5cc97b Removed RGB option from main menu (#640) 2024-02-26 19:06:39 -08:00
matlabbe
fccf33dd96 GraphViewer: added "Show mouse cursor position (m)" context menu option. 2024-02-26 17:13:50 -08:00
Long Vuong
752ca76cf5 not limitKps inside Feature2D::generateKeypoints when using pyDetector (#1223)
* not limitKps when using pyDetector

* update with upstream

---------

Co-authored-by: Long Vuong <vuong@wheel.me>
2024-02-26 15:21:15 -08:00
matlabbe
81e249b56c Update README.md 2024-02-18 19:02:40 -08:00
matlabbe
ff7c8af56f Mac: fixed cloud viewer pushed back behind main window after dialog closes 2024-02-18 13:43:52 -08:00
matlabbe
a11ea291d8 Fixed #1211 2024-02-10 18:27:02 -08:00
matlabbe
cd615c6e52 docker focal deps: removed gtsam as already installed by ros now (fixing downstream gtsam version conflict errors) 2024-02-10 14:06:41 -08:00
Borong Yuan
1bd2d9fe81 superpoint torch using simple nms (#1213) 2024-02-10 13:54:20 -08:00
matlabbe
510aef19e4 Added Vis/PnPSplitLinearCovComponents parameter (default false -> same as before) 2024-02-07 14:43:16 -08:00
matlabbe
1dadd50cf2 cmake: added VTK_GLOBAL_WARNING_DISPLAY option (default off) for VTK>=9 (https://github.com/introlab/rtabmap_ros/issues/1111) 2024-02-03 17:04:48 -08:00
matlabbe
b2a86d640a Fixed zed build errors (windows, #1207) 2024-01-31 07:17:04 -08:00
matlabbe
c27507bc77 Added missing Open3D status in --version and About. 2024-01-27 15:20:10 -08:00
matlabbe
b374c6cd8e docker: jammy humble dep fix 2024-01-21 15:49:59 -08:00
matlabbe
29dc6c67fa docker: fixing humble arm64 build 2024-01-21 13:26:43 -08:00
matlabbe
10de748531 DatabaseViewer: Fixed seg fault on Mac when opening db 2024-01-21 13:05:02 -08:00
Borong Yuan
dcd5994456 support color histogram equalization (#1203) 2024-01-21 12:38:34 -08:00
matlabbe
13cd5e7a5e Export Poses: Added support of landmarks. Fixed g2o export with 6DoF landmark constaints. Adjusted g2o export landmark id. (#1199) 2024-01-20 12:04:26 -08:00
matlabbe
856e372dde fixed bundle windows qt plugins destination 2024-01-15 23:53:27 -08:00
matlabbe
423e67558b fixed windows ci 2024-01-15 23:39:41 -08:00
matlabbe
ace653593b working qt6/mac deploy 2024-01-15 20:51:12 -08:00
matlabbe
7b31c737be Deploy fix 2024-01-15 20:45:58 -08:00
matlabbe
0b534c9427 Qt6 deploy fixes for Mac 2024-01-15 20:41:18 -08:00
matlabbe
cdbdcfe676 Fixing appveyor regression with gdown tool 2024-01-13 18:47:45 -08:00
matlabbe
b7239fdc84 Added parameter Mem/RotateImagesUpsideUp 2024-01-10 14:54:55 -08:00
matlabbe
a0559b156b Fixed #1196 2024-01-06 16:11:25 -08:00
matlabbe
79db6b2811 Fixed warning with vtk 7.1. Dont add target "uninstall" if already added from some cmake dependencies 2024-01-03 18:08:06 -08:00
Borong Yuan
096592e4fc reimplement NMS using morphological operations (#1192) 2024-01-02 15:38:39 -08:00
matlabbe
d135ef02e2 DBViewer: updated refine constraints menu action with more options, DBDriver: added updateCalibration for convenience 2023-12-20 14:39:49 -08:00
matlabbe
ee09e92496 Fixed build on xenial, VTK<=7. 2023-12-19 19:39:50 -08:00
matlabbe
e619c57759 Removing MRPT from bionic docker 2023-12-19 08:59:16 -08:00
matlabbe
f6a0323d46 remove rolling from CI 2023-12-19 00:35:38 -08:00
matlabbe
933d26f005 DbViewer/info tool: Updated number of links to report unique links. Added statistics about length of loop closures in info tool. 2023-12-18 16:27:18 -08:00
matlabbe
ec8f9fdcfd typo 2023-12-18 10:29:58 -08:00
matlabbe
f4a60f0b6f CI: fixed fail-fast 2023-12-17 22:57:59 -08:00
matlabbe
ade94cde1c disabling fail-fast on docker ci 2023-12-17 22:49:18 -08:00
matlabbe
71415992ac GridMap integration (#1180)
* GridMap integration

* Removed GridGlobal/FullUpdate parameter. Bump version 0.21.3. Mvoed specialized global map classes under global_map sub dir. Renamed Map -> GlobalMap.

* UI: Added elevation map visualization

* Added LocalGridCache class to share cache between global maps

* Fixed OctoMap nans. DbViewer: Added frontiers visualization.

* convenient functions for ros

* Small fix

* fixed build without GridMap

* CI disabled fail-fast

* CI updated checkout action to v4
2023-12-17 22:44:11 -08:00
Borong Yuan
45392fcfc6 Add RGBD mode for OAK camera (#1179)
* update depthai params

* add color+depth mode

* workarounds to avoid performance issues
2023-12-14 09:59:35 -08:00
matlabbe
be3e6c538c Adding util3d::cloudsFromSensorData to be able to show in DBViewer individual clouds for each camera (#1182)
* splitting multicam generated clouds

* make sure returned cloud is valid (can be empty)
2023-12-13 12:15:29 -08:00
matlabbe
f56875db4a Preferences: Fixed recursive param update bug 2023-11-29 05:28:30 -08:00
Borong Yuan
0876603325 improve NMS implementation (#1173) 2023-11-28 13:36:28 -08:00
matlabbe
3a7f88dc6c Updated error log that should not show up if Optimizer/Robust is true (#1172) 2023-11-28 13:29:33 -08:00
Borong Yuan
07c24e95ba start outputting data after static initialization (#1171)
* start outputting data after static initialization

* restore pixel noise to 1
2023-11-28 13:20:45 -08:00
matlabbe
7ab1ee0a0b Update docker.yml 2023-11-23 18:25:50 -08:00
matlabbe
fc8ead2237 Update docker.yml 2023-11-23 18:06:24 -08:00
matlabbe
a1d43d2353 Remove default AUTOUIC=ON from all non-ui targets. Fixed yaml target not added correctly on Vcpkg. Fixed gui odom processing time. 2023-11-19 19:40:20 -08:00
matlabbe
aaff1abc4f Updating orbslam3 v1 support (#1152)
* Refactoring ORB_SLAM3 integration. Fixed realsense2 inter IMU stamps.

* Renamed OdometryORBSLAM -> OdometryORBSLAM2

* revert a change

* Fixed build without orb_slam

* Source camera: added feature detection option

* Fixed jfr2018 docker files
2023-11-19 01:05:52 -08:00
matlabbe
9c56a429cc Localization: Refactored getConnectedGraph() for 2d slam and tags (https://github.com/introlab/rtabmap_ros/issues/1057). Transform: Fixed is3DoF() and is 4DoF() 2023-11-16 22:44:32 -08:00
Borong Yuan
757d3eb90b fix protocol detection for undiscoverable devices (#1159) 2023-11-15 19:50:07 -08:00
matlabbe
4812ce4eaf Optimizer: fixed some constraints between same nodes with different type ignored. GraphViewer: fixed display of links between same nodes with different type 2023-11-12 17:14:17 -08:00
matlabbe
56552afa6c Tuning localization priors (added RGBD/LocalizationPriorError parameter) (#1156)
* tuning localization priors (for https://github.com/introlab/rtabmap_ros/issues/1057)

* Set prior error value to same than old default value
2023-11-05 15:14:11 -08:00
Borong Yuan
45a3b59a23 transform features after source images decimation (#1154) 2023-11-02 08:10:02 -07:00
matlabbe
08d0ef7408 report: added --gt option to input external ground truth file. DBViewer: fixed crash when unchecking "Ignore intermediate nodes". 2023-10-27 17:10:10 -07:00
Borong Yuan
8da6ea1707 Add missing filterKeypointsByDepth step (#1150)
* add missing filterKeypointsByDepth step

* Fix ORBOctree not using the depth mask

---------

Co-authored-by: matlabbe <matlabbe@gmail.com>
2023-10-26 13:15:34 -07:00
matlabbe
64962e8e3d Added multicameras support for F2F odometry / OpticalFlow 2023-10-25 14:54:20 -07:00
matlabbe
71bb0cf226 ios/android: fixed database loading failing when one node doesn't have any depth or scan (#1147). 2023-10-21 14:52:29 -07:00
Borong Yuan
948e15c72c Supplement and Adjust OpenVINS Parameters (#1145)
* set the PrintLevel of OpenVINS to be equivalent to that of ULogger

* use global FAST settings

* add online calibration params

* add dynamic initialization params

* add necessary feature initializer options

* fix segfault of OdomImageDecimation

* add mask settings

* use depth as mask in OpenVINS

* set twist covariance

* restore default values of VisMinDepth and VisMaxDepth
2023-10-21 14:24:51 -07:00
Borong Yuan
f06cc0b17f OAK bug fixes and improvements (#1143)
* *fix distortion correction problem of small FOV devices
*remove deprecated IMU firmware update API
*add useSpecTranslation option

* reduce depth image noise and simplify calculation for compressed transport
2023-10-07 20:40:30 -07:00
Borong Yuan
2aa139b579 Update odometry info of OpenVINS (#1142)
* add msckf features visualization

* fill localMap with active tracked features
2023-10-07 20:36:00 -07:00
Borong Yuan
67c6a15b93 OpenVINS Update (#1107)
* fix openvins build

* Add OpenVINS params to UI

* update OdometryOpenVINS implementation

* the pixel noise of most cameras should be less than 3 after factory calibration

* propagation and update are only performed after camera measurement feeding

* fix openvins feature reprojection
2023-10-02 07:53:29 -07:00
matlabbe
78c029d833 fixed https://github.com/introlab/rtabmap_ros/issues/1038 2023-10-01 09:07:15 -07:00
Borong Yuan
afd10b1aa6 add histogram equalization (#1137) 2023-09-21 15:46:10 -07:00
matlabbe
f1cd819673 Fixed superglue deadlock on standalone (#896). Fixed some elemSize opencv asserts in debug build (876) 2023-09-17 01:19:59 -07:00
matlabbe
fb466a6a96 StereoBM/StereoSGBM: Thresholding output to zero when minDisparity is used 2023-09-16 17:43:00 -07:00
matlabbe
0b7181fc88 Updated minimum cmake version for https://github.com/introlab/rtabmap/pull/1135#issuecomment-1719701828 2023-09-16 16:32:21 -07:00
matlabbe
97f2b4b65d Fixed autogen cmake warnings. Fixed pytorch requiring c++17. 2023-09-16 14:26:17 -07:00
matlabbe
39dedba93a workflow: removing EOL xenial 2023-09-14 08:44:26 -07:00
cdb0y511
49daa211ea use CMAKE_AUTOUIC, CMAKE_AUTOMOC and CMAKE_AUTORCC (#1135) 2023-09-14 08:25:00 -07:00
matlabbe
01c2e70b11 rtabmap-info: added --dump ini option 2023-09-08 14:53:21 -07:00
matlabbe
fa4a2eb5e3 Fixed build on 22.04 caused by 9e86faa4ad 2023-09-07 10:29:18 -07:00
matlabbe
9e86faa4ad GraphView: added right-click option to export 2d grid map directly from the view 2023-09-07 09:10:04 -07:00
matlabbe
e31eec2c55 docker: fixed typo jammy-iron-deps 2023-09-05 09:07:16 -07:00
matlabbe
2d7d0ec424 Fixed backward compatibility (xenial) from #1117 2023-09-05 08:51:57 -07:00
matlabbe
191e4250ef docker: Fixing jammy-iron build without arm64 2023-09-04 17:18:43 -07:00
matlabbe
e56e0c37f7 Fixed https://github.com/introlab/rtabmap_ros/issues/1024 2023-09-04 11:55:52 -07:00
cdb0y511
6a5b844bac fix for Undefined symbols for architecture x86_64: "Nabo::NearestNeighbourSearch (#1117)
related to https://github.com/ethz-asl/libpointmatcher/issues/514
employ fix from https://github.com/ethz-asl/libpointmatcher/pull/513
2023-08-27 13:36:49 -07:00
matlabbe
20ad6cca2c ros2/iron docker: disabled arm64 build for now (arm64 binaries not available) 2023-08-27 13:35:27 -07:00
matlabbe
f90fede65c ci: added ros2 iron docker image 2023-08-27 12:38:24 -07:00
Borong Yuan
61dbe51ee3 Update OAK stereo config and IMU rate (#1116)
* update OAK stereo config and imu rate

* enable brightness filter
2023-08-19 16:29:05 -07:00
Pierre Wendling
f2687ed1ff CMake: Add compatibility for yaml-cpp 0.8.0. (#1115)
- Upstream uses YAML_CPP_INCLUDE_DIR
- yaml-cpp 0.8.0 does not set YAML_CPP_LIBRARIES to the new target name.
- Debug builds of yaml-cpp suffix the library with `d`.
2023-08-18 18:06:45 -07:00
matlabbe
cdd8cd9e34 ICP/intensity: Applying fix from #1111 2023-08-13 14:58:15 -07:00
matlabbe
6d36fc1fcd package.xml: Added ROS gtsam as dependency 2023-08-13 13:50:08 -07:00
matlabbe
ba5579f063 Only remove compressed raw data when publish data is false (keep features/occupancy grid) 2023-08-11 16:31:26 -07:00
matlabbe
6395487b58 Stats: distance from last localization not increasing if small motion 2023-08-10 15:17:15 -07:00
Borong Yuan
f0ba56bf5e fix ros gtsam 4.2a9 build (#1108) 2023-08-07 07:33:23 -07:00
matlabbe
a94a4c9802 adding ros2 iron CI / docker, fixing #1103 2023-08-05 14:38:39 -07:00
matlabbe
e2f037189a git push origin masterMerge branch 'borongyuan-msckf_vio_update' 2023-07-30 12:15:03 -07:00
matlabbe
bcb29cfb66 msckf: backward compatibility update for euroc dataset evaluation 2023-07-30 12:14:35 -07:00
matlabbe
d25bb758ca Merge branch 'msckf_vio_update' of https://github.com/borongyuan/rtabmap into borongyuan-msckf_vio_update 2023-07-30 11:43:06 -07:00
matlabbe
424dc90dce Added Vis/PnPVarianceMedianRatio parameter (to tune pnp computed covariance) 2023-07-27 16:13:30 -07:00
Borong Yuan
5d6875ed98 change for initial frame update 2023-07-24 21:10:55 +08:00
Borong Yuan
f8b761d79b msckf_vio now supports c++14 2023-07-24 14:08:04 +08:00
matlabbe
446590b19f Merge branch 'guoqingzh-guoqingz/multi_noncentral' 2023-07-22 11:06:14 -04:00
matlabbe
3feb03cf35 Added Vis/PnPSamplingPolicy parameter (opengv "multi" ransac) 2023-07-22 11:05:21 -04:00
matlabbe
a593b0d525 Merge branch 'guoqingz/multi_noncentral' of https://github.com/guoqingzh/rtabmap into guoqingzh-guoqingz/multi_noncentral 2023-07-21 11:35:26 -04:00
matlabbe
ca4276a951 Merge branch 'borongyuan-oak-d-poe-update' 2023-07-21 09:10:27 -04:00
matlabbe
e8b54de94a CameraDepthAi: Fixed buffered frames 2023-07-21 09:10:06 -04:00
Borong Yuan
f9719c197d disparityToDepthUseSpecTranslation is enabled by default as recommended 2023-07-20 00:28:36 +08:00
Borong Yuan
d391f237eb update imu callback 2023-07-17 23:35:03 +08:00
Borong Yuan
0b4f5d2925 remove unnecessary conversion function 2023-07-17 17:00:43 +08:00
Borong Yuan
7d2272beb3 fix ProtocolToStr() visibility 2023-07-17 10:09:49 +08:00
Borong Yuan
6d690a315a Using VideoEncoder on PoE devices 2023-07-17 03:32:18 +08:00
Borong Yuan
ce81fe445a specify device using MXID or IP/USB name 2023-07-15 20:58:00 +08:00
Borong Yuan
a2a75a28ba add imu local transform for oak-d poe models 2023-07-14 20:18:48 +08:00
Guoqing Zhang
ddeca4585d Motion estimation: use MultiNoncentralAbsolutePoseSacProblem to estimate camera pose 2023-07-11 16:35:55 +03:00
matlabbe
64f79813cd Added error log message when graph optimization error is huge (error ratio over > 100) and RGBD/OptimizeMaxError is disabled. 2023-07-03 18:04:54 -07:00
matlabbe
b8c298efd9 Added devcontainer 2023-07-02 23:49:02 -07:00
matlabbe
97be9d4ace Localization mode: Fixed proximity detection permanently disabled when Rtabmap/StartNewMapOnLoopClosure is true 2023-06-27 17:25:07 -07:00
Chris Lalancette
f8c4b62591 Remove dependency on qt_gui_cpp. (#1072)
There is no dependency in this package on qt_gui_cpp.
Instead, just use a dependency on qtbase5-dev

Signed-off-by: Chris Lalancette <clalancette@gmail.com>
2023-06-27 13:07:47 -07:00
matlabbe
a1168ba8a9 docker: removed focal-foxy (EOL) 2023-06-27 12:14:00 -07:00
matlabbe
c307f5c65f Removing foxy from CI (EOL) 2023-06-27 12:11:07 -07:00
matlabbe
b0cf2e9927 Update cmake-ros.yml with setup-ros 0.6 2023-06-27 11:16:14 -07:00
matlabbe
c7e46c1431 rgbddatset tool: removed local covariance logic. DBViewer: fixed poses not aligned to groundtruth on start. 2023-06-25 17:42:54 -07:00
matlabbe
092f6abccc fixed downstream python cmake not found (#1063) 2023-06-21 21:04:29 -07:00
matlabbe
dcbad6a0aa NMS: optimized descriptor copy by rows 2023-06-20 21:52:43 -07:00
matlabbe
337832e1b8 Fixed NMS seg fault #1064 2023-06-20 20:53:32 -07:00
matlabbe
d901fb23e3 Merge branch 'depthai-superpoint' of https://github.com/borongyuan/rtabmap into borongyuan-depthai-superpoint 2023-06-19 18:39:15 -07:00
matlabbe
59d5675fe6 docker: remixed where deps are built for convenience 2023-06-19 15:17:02 -07:00
matlabbe
ab3ade0309 fixed #1051 2023-06-19 15:06:16 -07:00
Borong Yuan
720d50fe74 add depthai superpoint descriptor 2023-06-19 15:15:37 +08:00
matlabbe
33fb2f75ad Fixed Python.h not found error (#1054) 2023-06-17 15:46:44 -07:00
matlabbe
36c0054070 docker: focal-foxy-deps, switched opengv and opencv 2023-06-17 12:30:55 -07:00
Borong Yuan
55a84cfdaa add depthai superpoint detector 2023-06-17 16:53:25 +08:00
Borong Yuan
2dd64a6283 move NMS to util2d 2023-06-17 13:06:54 +08:00
matlabbe
f75839294a Fixes for rtabmap_viz info sub only (with local cache) 2023-06-16 16:30:07 -07:00
Borong Yuan
e219152e8f update to depthai-core v2.22.0 2023-06-15 14:02:09 +08:00
Borong Yuan
d031d79369 add depthai gftt detector (#1047)
* add depthai feature detector draft

* update depthai gftt config

* optimize to detect more features
2023-06-11 12:57:26 -07:00
matlabbe
0c476936e3 docker: added tegra path to LD_LIBRARY_PATH to images 2023-06-11 10:15:40 -07:00
matlabbe
d86193036f docker ros2: fixed entrypoint.sh not exec 2023-06-11 10:02:17 -07:00
matlabbe
0c3b202006 fixed build with MRPT 2023-06-06 08:51:40 -07:00
matlabbe
1cc7c2818f Localization covariance empty till localization 2023-06-05 20:08:21 -07:00
matlabbe
1e145550df Merge branch 'borongyuan-alphascaling' 2023-06-05 19:01:42 -07:00
matlabbe
2a3580e060 Merge branch 'master' of https://github.com/introlab/rtabmap into borongyuan-alphascaling 2023-06-05 19:00:44 -07:00
matlabbe
d3facb1a84 Added alpha=-1 option 2023-06-05 18:59:59 -07:00
matlabbe
bf5c70d2e2 docker: fixed copy of ros_entrypoint.sh 2023-06-05 08:24:07 -07:00
matlabbe
7f7609075f docker: fixed humble->jammy 2023-06-04 21:04:21 -07:00
matlabbe
cf49ebf238 Split ros2 docker images into 2 jobs for easier maintenance 2023-06-04 21:01:24 -07:00
matlabbe
879f0f6941 Merge branch 'alphascaling' of https://github.com/borongyuan/rtabmap into borongyuan-alphascaling 2023-06-04 16:14:24 -07:00
matlabbe
af481fc730 docker/foxy: re-enabled opencv 2023-06-04 16:12:43 -07:00
matlabbe
1b67d6a86a Triggering focal-foxy docker 2023-06-01 19:38:15 -07:00
Borong Yuan
31d975acd5 Add alphaScaling option 2023-05-31 22:15:16 +08:00
Borong Yuan
54c68f8e6c Updated disparity reprojection to account for cameras with different Fx and Fy values 2023-05-31 19:40:29 +08:00
Borong Yuan
aedfcdc576 alphaScaling test 2023-05-30 18:16:28 +08:00
matlabbe
bfc4e939d1 Docker: updated ros2 base image to support arm64 2023-05-29 23:24:47 -07:00
André Lison
67df99aa57 fixes for texture mesh export pcl > 1.13.0 (#1039)
Co-authored-by: FIRST_NAME LAST_NAME <MY_NAME@example.com>
2023-05-29 19:00:18 -07:00
matlabbe
d88c816ca1 Merge branch 'borongyuan-master' 2023-05-29 18:12:25 -07:00
matlabbe
5b1c9e7233 IMU board fix for original OAK-D 2023-05-29 17:02:53 -07:00
Borong Yuan
8d6c809c3c Update data sync implementation for DepthAI 2023-05-27 21:28:43 +08:00
Borong Yuan
52e417c313 Set IMU extrinsics to left camera optical frame 2023-05-25 12:19:07 +08:00
Borong Yuan
5592a1ebfe Update IMU local transform 2023-05-25 00:01:55 +08:00
Borong Yuan
42fbdda567 Merge branch 'introlab:master' into master 2023-05-23 10:08:21 +08:00
matlabbe
ae3fda37a9 Fixed not invertible error ofter wrong graph optimization (seen on localization mode, gtsam returning inf poses) 2023-05-22 17:56:59 -07:00
Borong Yuan
ffd89ead86 Get baseline using sdk method 2023-05-22 22:06:45 +08:00
Borong Yuan
937e9fbb3b Advanced parameter tuning for depth quality optimization 2023-05-22 20:29:44 +08:00
Borong Yuan
9ecf71e5ed Update DepthAI camera model 2023-05-22 18:37:08 +08:00
Borong Yuan
ff83b14b49 Add options to enable IR featues on OAK Pro models 2023-05-18 01:48:38 +08:00
matlabbe
263eb6fbde Update README.md 2023-05-15 11:10:28 -07:00
matlabbe
e7d61b3856 Update README.md 2023-05-15 10:45:16 -07:00
matlabbe
682d54725a Fixed build with gtsam 4.3.0 (#1033) 2023-05-14 13:14:53 -07:00
matlabbe
ba33c080bc Added RGBD/LocalizationSmoothing parameter and fixed related issues (#1032)
* removed code

* added landmark in graph optimization checks

* reverted smoothing, only if there is already a previous localization link

* Added RGBDLocalizationSmoothing parameter

* Update .appveyor.yml

* Update .appveyor.yml

* Update .appveyor.yml

* Update .appveyor.yml

* Update .appveyor.yml

* Update .appveyor.yml

* Update .appveyor.yml

* Update .appveyor.yml

* Update .appveyor.yml
2023-05-14 13:03:52 -07:00
matlabbe
2da448f4ee Docker: updated latest_deps dockerfile 2023-05-14 12:20:00 -07:00
matlabbe
376c82325e docker/focal: re-enabling opencv for arm64 (CI time limit issue) 2023-05-09 09:05:49 -07:00
matlabbe
95f65e1599 docker/focal: temporary disable opencv on arm64 build 2023-05-08 23:40:36 -07:00
matlabbe
060af6f7bb docker: cleanup files with nvidia, see new instructions on the wiki (no need to make another image anymore). Added latest OpenCV with xfeatures2d+nonfree modules. 2023-05-07 18:41:44 -07:00
matlabbe
999c01d71d Fixed https://github.com/introlab/rtabmap_ros/issues/948 2023-05-06 12:45:36 -07:00
matlabbe
a54f76238b cmake: WITH_OPENGV=On by default 2023-04-30 14:33:58 -07:00
matlabbe
f8f6b7788a Fixed #1015 2023-04-16 18:59:18 -07:00
matlabbe
e54195c47f ZED SDK 4 support (#1013) 2023-04-16 18:47:15 -07:00
matlabbe
e300d4c5c1 Added IMU support for camera images source with odom approach not supporting async imu 2023-04-16 17:32:32 -07:00
matlabbe
b91addb261 GUI: create simple calibration->fixed optical rotation 2023-04-15 18:24:14 -07:00
matlabbe
0f221ba3cd ParametersToolbox: fixed unsigned int parameter type not showing in toolbox 2023-04-14 17:50:34 -07:00
matlabbe
0070de4aaf explicitly set deps to install instead of relying on buildfarm (#1012)
* explicitly set deps to install instead of relying on buildfarm rtabmap (in case buildfarm build is failing)

* use rosdep instead

* missing rosdep update

* updated rosdep command

* removed rosdep init

* fixed qt_gui_cpp not found

* revert last commit, should be able to use qt_gui_cpp in rosdep

* removed deprecated 18.04
2023-04-09 14:40:57 -07:00
matlabbe
11b4becdde bump 0.21.1 2023-04-09 12:00:53 -07:00
matlabbe
8b8a512cbb Added Icp/ReciprocalCorrespondences (new default true) 2023-04-06 20:57:35 -07:00
matlabbe
141f2d3334 DbViewer: added align gps checkbox 2023-04-05 22:19:54 -07:00
matlabbe
6dca8ab0f3 Fixed seg fault on start with >= VTK9.1, MACOSX: fixed bundle with homebrew 2023-03-25 22:41:28 -07:00
matlabbe
fc7a6708c5 iOS: updated copyright years 2023-03-25 14:19:34 -07:00
matlabbe
11e5437eba iOS: Addressing #998 #1001 2023-03-25 14:11:42 -07:00
matlabbe
c4e94bcdc3 fix comment removed 2023-03-22 22:20:09 -07:00
matlabbe
51a7122dbe fixed cmake 2023-03-22 20:58:12 -07:00
matlabbe
d13f594d9c Fixed build with g2o binaries 2023-03-22 20:49:08 -07:00
matlabbe
85cc6fe3c7 fixed build with latest g2o c++17 (#999) 2023-03-22 20:42:33 -07:00
PonyPC
50a0961f4e Update OdometryORBSLAM.cpp (#991)
Fix RGBD with ORB SLAM
2023-03-20 19:35:39 -07:00
matlabbe
a406c37750 gtsam: Fixed metis linker errors on windows. Ceres: updated default solver options (working for BA and pose-graph optimizations, fixed #966) 2023-03-19 13:30:52 -07:00
matlabbe
1cb7f3fb87 octomap: fixed regression on ubuntu 16.04 2023-03-18 14:36:30 -07:00
matlabbe
ab99719a78 octomap: use cmake target (#995) 2023-03-18 14:19:16 -07:00
matlabbe
e66ea7b42b updated qt6 deploy configurations 2023-03-18 00:13:14 -07:00
matlabbe
46edd15121 Fixed bundle with Qt6 2023-03-16 23:07:13 -07:00
matlabbe
e7bea0ec03 Windows: Fixed QVTKWidget error with VTK9.2, fixed ambiguous "byte" compilation error 2023-03-16 19:27:54 -07:00
matlabbe
e3b7e9378d integrating c++17 fixes from #959 (ref:https://github.com/flann-lib/flann/pull/392), fixed pop_t error (b6e37553de) 2023-03-16 17:48:40 -07:00
matlabbe
6fe5e6375f Fixed g2o version not correctly used, D400: set default to IR+Depth 2023-03-13 22:10:24 -07:00
matlabbe
92b9cc89e0 fixed missing build dir 2023-03-13 03:20:06 -07:00
matlabbe
53025bf059 Update for windows release: added FindEigen3.cmake so that g2oConfig.cmake can find Eigen3 not using targets from PCL install, hiding console when creating a bundle app in windows, disabled vtk console 2023-03-13 03:10:16 -07:00
matlabbe
e51d161407 Export explicity Qt include dirs (compatibility with old cmake way) 2023-03-05 18:45:27 -08:00
matlabbe
3a3a4ed745 ubuntu 16.04: fixed cmake GREATER_EQUAL not defined 2023-03-05 17:46:01 -08:00
matlabbe
d6704ca2ed docker latest deps: added nvidia runtime stuff for convenience 2023-03-05 16:38:09 -08:00
matlabbe
8c5c4f63bf Qt6 compatibility (#968)
* Qt6 Compilation success

* Fixed qt5 backward compatibility

* Fixed build for qt<=5.9 (bionic)

* Added docker file for easy testing with latest Qt/VTK/PCL/OpenCV

* Fixed cmake for qt
2023-03-05 16:34:56 -08:00
matlabbe
98635ae33d GUI: fixed missing cache not republished in appearance-only mode 2023-03-04 13:38:27 -08:00
matlabbe
70cbe52fcf DbViewer: exporting map info in yaml file when exporting 2d occupancy grid (#978) 2023-02-25 17:12:51 -08:00
matlabbe
e6e6630d54 fixed typo 2023-02-25 14:05:12 -08:00
matlabbe
34fec972dc try workaround #980 2023-02-25 14:01:00 -08:00
matlabbe
67604a0fb0 cmake-ros workflow: increased setup-ros version to 0.5 2023-02-25 13:56:39 -08:00
matlabbe
731d73b798 CMake Config: added "rtabmap::" prefix for all rtabmap's targets, provide RTABMap_TARGETS list (used by ROS2/ament to detect modern cmake packages). 2023-02-22 23:07:30 -08:00
matlabbe
70c3d5d97f DbViewer: added convenient option to rotate the occupancy grid (affect only optimized graph for localization mode). 2023-02-22 17:20:09 -08:00
matlabbe
23b0b37493 ImageView: updated depth color map gradient, added option to set minimum depth. 2023-02-22 12:34:20 -08:00
matlabbe
c7f49134eb DBReader: fixed GUI freezing when consecutive stamps in loaded frames are very far apart. 2023-02-18 14:37:43 -08:00
matlabbe
549fc2a592 Config: Removed QtSvg from public dependency, changed find_package 2023-02-12 23:30:53 -08:00
matlabbe
7005a8aa2a fixed android prebuild error 2023-02-12 16:47:55 -08:00
matlabbe
2065688116 Config: added explicit compoments of dependencies 2023-02-12 16:28:42 -08:00
matlabbe
89e3e10d89 Refactoring RTABMapConfig.cmake with targets (#904)
* Config: Using cmake targets

* fixed RTABMAP_DEPRECATED build error

* fixed melodic build

* cleanup

* Fixed qhull exported library error

* Update svg depend private

* removed g2o from public interface

* Fixed Windows with external project

* removed some required dep

* Fixed nsis error (also fixed unspecified components)

* updated workflow rules
2023-02-12 16:18:01 -08:00
matlabbe
437ed09335 DBReader: added ignore priors option (added to gui and reprocess), Statistics: added info about distance/angle of the localization, RegVis: fixed inliers mean distance on multicam setup, About: added MRPT info 2023-02-10 17:29:10 -08:00
matlabbe
59d220c54f k4a: fixed playback fps and imu handling 2023-02-08 21:15:16 -08:00
matlabbe
2acd8f82b5 fixed #969 2023-02-08 19:02:42 -08:00
matlabbe
724e068194 fixed a seg fault 2023-02-08 18:46:02 -08:00
matlabbe
e30e6937fa docker: removed broken alicevision build from bionic 2023-02-05 09:08:01 -08:00
matlabbe
9406b15746 docker: fixed error 2023-02-04 21:33:34 -08:00
matlabbe
67ca39514a docker: fixing assimp cmake related error 2023-02-04 21:10:34 -08:00
matlabbe
5fd0448924 docker cleanup 2023-02-04 17:41:07 -08:00
matlabbe
413be8e824 updated docker 2023-02-03 18:06:56 -08:00
matlabbe
dcedd8bb6b Added MRPT optional dependency. Updated localization_pose + its covariance to be always published. 2023-02-03 17:25:38 -08:00
matlabbe
e4edee33eb Fixed build with cvsba and ceres 2023-01-28 18:49:58 -08:00
matlabbe
128d3b0d0a ZED: Fixed some warnings (#961) 2023-01-28 16:33:24 -08:00
matlabbe
ff61266430 docker: fixed focal-foxy build 2023-01-22 17:06:32 -08:00
matlabbe
f928cb6787 docker: added focal-foxy 2023-01-22 16:56:31 -08:00
matlabbe
3a9ae201a7 docker/jammy: added multiarh lib folder for arm64 2023-01-22 16:40:16 -08:00
matlabbe
34af17de59 Docker: Added jammy 2023-01-22 16:14:39 -08:00
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
658 changed files with 47134 additions and 23507 deletions

View File

@@ -17,6 +17,9 @@ init:
- call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x86_amd64
install:
# To download from google drive
- set PATH=C:\Python38-x64;C:\Python38-x64\Scripts;%PATH%
- ps: py -m pip --disable-pip-version-check install gdown>=5.1.0
# Qt
- set QTDIR=C:\Qt\5.10.1\msvc2015_64
# make sure Qt bin path is before cmake bin path to avoid copying qt5 dlls from cmake before qt installation
@@ -73,7 +76,7 @@ install:
- ps: "ls \"C:/Program Files/PCL\""
- set PATH=%PATH%;C:\Program Files\PCL\bin
# zlib
- ps: wget 'https://docs.google.com/uc?authuser=0&id=0B46akLGdg-uaYm9MTTI4MUtUcmc&export=download' -outfile zlib-1.2.8-vc2010-x64.zip
- ps: gdown -q 0B46akLGdg-uaYm9MTTI4MUtUcmc
- ps: Expand-Archive zlib-1.2.8-vc2010-x64.zip -DestinationPath 'C:\Program Files'
- ECHO "Installed zlib:"
- ps: "ls \"C:/Program Files/zlib\""

View File

@@ -0,0 +1,8 @@
{
"image": "introlab3it/rtabmap:android-deps",
"customizations": {
"vscode": {
"extensions": ["ms-vscode.cpptools-themes", "ms-vscode.cmake-tools", "vscjava.vscode-java-pack"]
}
}
}

View File

@@ -0,0 +1,8 @@
{
"image": "introlab3it/rtabmap:18.04",
"customizations": {
"vscode": {
"extensions": ["ms-vscode.cpptools-themes", "ms-vscode.cmake-tools"]
}
}
}

View File

@@ -0,0 +1,8 @@
{
"image": "introlab3it/rtabmap:20.04",
"customizations": {
"vscode": {
"extensions": ["ms-vscode.cpptools-themes", "ms-vscode.cmake-tools"]
}
}
}

View File

@@ -0,0 +1,8 @@
{
"image": "introlab3it/rtabmap:22.04",
"customizations": {
"vscode": {
"extensions": ["ms-vscode.cpptools-themes", "ms-vscode.cmake-tools"]
}
}
}

View File

@@ -0,0 +1,8 @@
{
"image": "introlab3it/rtabmap:24.04",
"customizations": {
"vscode": {
"extensions": ["ms-vscode.cpptools-themes", "ms-vscode.cmake-tools"]
}
}
}

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:
- master
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:
fail-fast: false
matrix:
ros_distribution: [ noetic, humble, iron]
include:
- ros_distribution: 'noetic'
os: ubuntu-20.04
- ros_distribution: 'humble'
os: ubuntu-22.04
- ros_distribution: 'iron'
os: ubuntu-22.04
# Currently CI has some errors on setup-ros with this OS, disabling for now
#- ros_distribution: 'jazzy'
# os: ubuntu-24.04
steps:
- uses: ros-tooling/setup-ros@v0.6
with:
required-ros-distributions: ${{ matrix.ros_distribution }}
- uses: actions/checkout@v4
- name: Install dependencies
run: |
source /opt/ros/${{ matrix.ros_distribution }}/setup.bash
rosdep update
rosdep install --from-paths ${{github.workspace}} -y
- 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

View File

@@ -2,59 +2,43 @@ name: CMake
on:
push:
branches: [ master ]
branches:
- master
pull_request:
branches: [ master ]
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_distro }} and ${{ matrix.os }}
name: ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-20.04, ubuntu-18.04]
include:
- os: ubuntu-20.04
ros_distro: 'noetic'
- os: ubuntu-18.04
ros_distro: 'melodic'
os: [ubuntu-24.04, ubuntu-22.04, ubuntu-20.04]
steps:
- uses: ros-tooling/setup-ros@v0.2
with:
required-ros-distributions: ${{ matrix.ros_distro }}
steps:
- name: Install dependencies
run: |
DEBIAN_FRONTEND=noninteractive
sudo apt-get update
sudo apt-get -y install ros-${{ matrix.ros_distro }}-rtabmap-ros
sudo apt-get -y remove ros-${{ matrix.ros_distro }}-rtabmap
sudo apt-get -y install libopencv-dev libpcl-dev git cmake software-properties-common libyaml-cpp-dev
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Configure CMake
# Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make.
# See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type
run: |
source /opt/ros/${{ matrix.ros_distro }}/setup.bash
cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
- name: Build
# Build your program with the given configuration
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}
- name: Info
working-directory: ${{github.workspace}}/bin
working-directory: ${{github.workspace}}/build/bin
run: |
source /opt/ros/${{ matrix.ros_distro }}/setup.bash
./rtabmap-console --version
# - name: Test

View File

@@ -6,56 +6,42 @@ on:
- 'master'
jobs:
docker:
docker_deps:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
docker_tag: [xenial, bionic, focal, android23, android24, android26]
docker_tag: [focal-deps, jammy-deps, jammy-iron-deps, noble-deps]
include:
- docker_tag: xenial
- docker_tag: focal-deps
docker_tags: |
introlab3it/rtabmap:xenial
introlab3it/rtabmap:16.04
docker_platforms: |
linux/amd64
docker_path: 'xenial'
- docker_tag: bionic
docker_tags: |
introlab3it/rtabmap:bionic
introlab3it/rtabmap:18.04
introlab3it/rtabmap:focal-deps
docker_platforms: |
linux/amd64
linux/arm64
docker_path: 'bionic'
- docker_tag: focal
linux/arm/v7
docker_path: 'focal/deps'
- docker_tag: jammy-deps
docker_tags: |
introlab3it/rtabmap:focal
introlab3it/rtabmap:20.04
introlab3it/rtabmap:latest
introlab3it/rtabmap:jammy-deps
docker_platforms: |
linux/amd64
linux/arm64
docker_path: 'focal'
- docker_tag: android23
docker_path: 'jammy/deps'
- docker_tag: jammy-iron-deps
docker_tags: |
introlab3it/rtabmap:android23
introlab3it/rtabmap:tango
introlab3it/rtabmap:jammy-iron-deps
docker_platforms: |
linux/amd64
docker_path: 'bionic/android/rtabmap_api23'
- docker_tag: android24
docker_path: 'jammy-iron/deps'
- docker_tag: noble-deps
docker_tags: |
introlab3it/rtabmap:android24
introlab3it/rtabmap:noble-deps
docker_platforms: |
linux/amd64
docker_path: 'bionic/android/rtabmap_api24'
- docker_tag: android26
docker_tags: |
introlab3it/rtabmap:android26
docker_platforms: |
linux/amd64
docker_path: 'bionic/android/rtabmap_api26'
linux/arm64
docker_path: 'noble/deps'
steps:
-
@@ -79,11 +65,135 @@ jobs:
name: Build and push
uses: docker/build-push-action@v2
with:
context: ./docker/${{ matrix.docker_path }}
context: .
push: true
platforms: ${{ matrix.docker_platforms }}
file: ./docker/${{ matrix.docker_path }}/Dockerfile
tags: ${{ matrix.docker_tags }}
cache-from: type=registry,ref=introlab3it/rtabmap:${{ matrix.docker_tag }}
cache-to: type=inline
docker:
needs: docker_deps
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
docker_tag: [bionic, focal, jammy, jammy-iron, noble, android23, android24, android26, android30]
include:
- 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
linux/arm/v7
docker_path: 'focal'
- docker_tag: jammy
docker_tags: |
introlab3it/rtabmap:jammy
introlab3it/rtabmap:22.04
docker_args: |
NOT_USED=0
docker_platforms: |
linux/amd64
linux/arm64
docker_path: 'jammy'
- docker_tag: jammy-iron
docker_tags: |
introlab3it/rtabmap:jammy-iron
docker_args: |
NOT_USED=0
docker_platforms: |
linux/amd64
docker_path: 'jammy-iron'
- docker_tag: noble
docker_tags: |
introlab3it/rtabmap:noble
introlab3it/rtabmap:24.04
docker_args: |
NOT_USED=0
docker_platforms: |
linux/amd64
linux/arm64
docker_path: 'noble'
- 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: |
CACHE_DATE=${{ github.head_ref }}.${{ github.sha }}
${{ matrix.docker_args }}
tags: ${{ matrix.docker_tags }}
cache-from: type=registry,ref=introlab3it/rtabmap:${{ matrix.docker_tag }}
cache-to: type=inline

16
.github/workflows/scheduled-stats.yml vendored Normal file
View File

@@ -0,0 +1,16 @@
name: RTAB-Map Scheduled Stats Extraction From GitHub
on:
workflow_dispatch:
schedule:
- cron: '0 5 * * *'
jobs:
get_stats:
runs-on: ubuntu-latest
steps:
- name: Update Stats
uses: introlab/github-stats-action@v1
with:
github-stats-token: ${{ secrets.STATS_TOKEN }}
google-application-credentials: ${{ secrets.GOOGLE_APPLICATION_CREDENTIALS }}
spreadsheet-id: ${{ secrets.SPREADSHEET_ID }}

2
.gitignore vendored
View File

@@ -10,3 +10,5 @@ app/android/AndroidManifest.xml
app/android/res/raw/
compile_flags.txt
tags
build_*
*.bak

File diff suppressed because it is too large Load Diff

View File

@@ -1,21 +1,25 @@
rtabmap ![.](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]
[![Downloads][downloads-image]][downloads]
[![License][license-image]][license]
Linux: [![Build Status](https://github.com/introlab/rtabmap/actions/workflows/cmake.yml/badge.svg)](https://github.com/introlab/rtabmap/actions/workflows/cmake.yml) [![docker](https://github.com/introlab/rtabmap/actions/workflows/docker.yml/badge.svg)](https://github.com/introlab/rtabmap/actions/workflows/docker.yml) 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.8-green.svg?style=flat
[release-image]: https://img.shields.io/badge/release-0.21.4-green.svg?style=flat
[releases]: https://github.com/introlab/rtabmap/releases
[downloads-image]: https://img.shields.io/github/downloads/introlab/rtabmap/total?label=downloads
[downloads]: https://github.com/introlab/rtabmap/releases
[license-image]: https://img.shields.io/badge/license-BSD-green.svg?style=flat
[license]: https://github.com/introlab/rtabmap/blob/master/LICENSE
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 +29,54 @@ 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="1">ROS 1</td>
<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>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>Iron</td>
<td><a href="http://build.ros2.org/job/Ibin_uJ64__rtabmap__ubuntu_jammy_amd64__binary/"><img src="http://build.ros2.org/buildStatus/icon?job=Ibin_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>
<tr>
<td>Docker</td>
<td>
<a href="https://hub.docker.com/r/introlab3it/rtabmap">rtabmap</a>
</td>
<td><img src="https://img.shields.io/docker/pulls/introlab3it/rtabmap.svg?label=pulls" alt="Docker Pulls"/></td>
</tr>
</tbody>
</table>

View File

@@ -1,99 +1,106 @@
# - Config file for the RTABMap package
# Components:
# core (required)
# gui (optional)
# utilite (required)
# It defines the following variables
# RTABMap_INCLUDE_DIRS - include directories for RTABMap
# RTABMap_LIBRARIES - libraries to link against
# RTABMap_CORE - core library
# RTABMap_UTILITE - utilite library
# RTABMap_GUI - gui library (set if RTABMap is built with Qt)
include(CMakeFindDependencyMacro)
# Compute paths
get_filename_component(RTABMap_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
set(RTABMap_INCLUDE_DIRS "@CONF_INCLUDE_DIRS@")
# Mandatory dependencies
find_dependency(OpenCV COMPONENTS core calib3d imgproc highgui stitching photo video OPTIONAL_COMPONENTS aruco xfeatures2d nonfree gpu cudafeatures2d)
#core lib
find_library(RTABMap_CORE_RELEASE NAMES rtabmap_core NO_DEFAULT_PATH HINTS @CONF_LIB_DIR@)
find_library(RTABMap_CORE_DEBUG NAMES rtabmap_cored NO_DEFAULT_PATH HINTS @CONF_LIB_DIR@)
IF(RTABMap_CORE_DEBUG AND RTABMap_CORE_RELEASE)
SET(RTABMap_CORE
debug ${RTABMap_CORE_DEBUG}
optimized ${RTABMap_CORE_RELEASE}
)
ELSEIF(RTABMap_CORE_DEBUG)
SET(RTABMap_CORE ${RTABMap_CORE_DEBUG})
if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/RTABMap_guiTargets.cmake")
find_dependency(PCL 1.7 COMPONENTS common io kdtree search surface filters registration sample_consensus segmentation visualization)
if(@CONF_QT_VERSION@ EQUAL 6)
find_dependency(Qt6 COMPONENTS Widgets Core Gui OpenGL)
elseif(@CONF_QT_VERSION@ EQUAL 5)
find_dependency(Qt5 COMPONENTS Widgets Core Gui OpenGL)
else() # Qt4
find_dependency(Qt4 COMPONENTS QtCore QtGui)
endif()
set(RTABMap_QT_VERSION @CONF_QT_VERSION@)
ELSE()
SET(RTABMap_CORE ${RTABMap_CORE_RELEASE})
find_dependency(PCL 1.7 COMPONENTS common io kdtree search surface filters registration sample_consensus segmentation)
ENDIF()
set(RTABMap_DEFINITIONS ${PCL_DEFINITIONS})
add_definitions(${RTABMap_DEFINITIONS}) # To include -march=native if set
# Optional dependencies
IF(EXISTS "${CMAKE_CURRENT_LIST_DIR}/@CONF_MODULES_DIR@")
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/@CONF_MODULES_DIR@")
ENDIF()
#utilite lib
find_library(RTABMap_UTILITE_RELEASE NAMES rtabmap_utilite NO_DEFAULT_PATH HINTS @CONF_LIB_DIR@)
find_library(RTABMap_UTILITE_DEBUG NAMES rtabmap_utilited NO_DEFAULT_PATH HINTS @CONF_LIB_DIR@)
IF(RTABMap_UTILITE_DEBUG AND RTABMap_UTILITE_RELEASE)
SET(RTABMap_UTILITE
debug ${RTABMap_UTILITE_DEBUG}
optimized ${RTABMap_UTILITE_RELEASE}
)
ELSEIF(RTABMap_UTILITE_DEBUG)
SET(RTABMap_UTILITE ${RTABMap_UTILITE_DEBUG})
ELSE()
SET(RTABMap_UTILITE ${RTABMap_UTILITE_RELEASE})
IF(@CONF_WITH_REALSENSE2@)
IF(WIN32)
find_dependency(RealSense2)
ELSE()
find_dependency(realsense2)
ENDIF()
ENDIF()
set(RTABMap_LIBRARIES ${RTABMap_CORE} ${RTABMap_UTILITE})
IF(@CONF_WITH_K4A@)
IF(WIN32)
find_dependency(K4A)
ELSE()
find_dependency(k4a)
find_dependency(k4arecord)
ENDIF()
ENDIF()
list(LENGTH RTABMap_FIND_COMPONENTS RTABMap_FIND_COMPONENTS_LENGTH)
set(WITH_GUI ON)
if(${RTABMap_FIND_COMPONENTS_LENGTH} GREATER 0)
list (FIND RTABMap_FIND_COMPONENTS "gui" _index)
if (${_index} EQUAL -1)
set(WITH_GUI OFF)
endif()
endif(${RTABMap_FIND_COMPONENTS_LENGTH} GREATER 0)
IF(@CONF_WITH_DEPTH_AI@)
find_dependency(depthai 2.24)
ENDIF()
IF(@CONF_WITH_XVSDK@)
find_dependency(xvsdk)
ENDIF()
#gui lib (OFF if RTAB-Map is not built with Qt)
if(@CONF_WITH_GUI@ AND ${WITH_GUI})
find_library(RTABMap_GUI_RELEASE NAMES rtabmap_gui NO_DEFAULT_PATH HINTS @CONF_LIB_DIR@)
find_library(RTABMap_GUI_DEBUG NAMES rtabmap_guid NO_DEFAULT_PATH HINTS @CONF_LIB_DIR@)
IF(RTABMap_GUI_DEBUG AND RTABMap_GUI_RELEASE)
SET(RTABMap_GUI
debug ${RTABMap_GUI_DEBUG}
optimized ${RTABMap_GUI_RELEASE}
)
ELSEIF(RTABMap_GUI_RELEASE)
SET(RTABMap_GUI ${RTABMap_GUI_RELEASE})
ELSEIF(RTABMap_GUI_DEBUG)
SET(RTABMap_GUI ${RTABMap_GUI_DEBUG})
ENDIF()
set(RTABMap_LIBRARIES ${RTABMap_LIBRARIES} ${RTABMap_GUI})
elseif(${WITH_GUI})
MESSAGE(WARNING "Asked for \"gui\" module but RTABMap hasn't been built with gui support.")
endif()
IF(@CONF_WITH_OCTOMAP@)
find_dependency(octomap)
ENDIF()
# Dependencies
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@")
IF(@CONF_WITH_GRIDMAP@)
find_dependency(grid_map_core)
ENDIF()
#backward compatibilities
set(RTABMAP_CORE ${RTABMap_CORE})
set(RTABMAP_UTILITE ${RTABMap_UTILITE})
if(RTABMap_GUI)
set(RTABMAP_GUI ${RTABMap_GUI})
set(RTABMAP_QT_VERSION @CONF_QT_VERSION@)
endif(RTABMap_GUI)
IF(@CONF_WITH_PYTHON@)
find_dependency(Python3 COMPONENTS Interpreter Development NumPy)
ENDIF()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(RTABMap DEFAULT_MSG RTABMap_LIBRARIES RTABMap_INCLUDE_DIRS)
mark_as_advanced(RTABMap_LIBRARIES RTABMap_INCLUDE_DIRS RTABMap_LIBRARY_DIRS)
# Provide those for backward compatibilities (e.g., catkin requires them to propagate dependencies)
set(RTABMap_INCLUDE_DIRS "")
set(RTABMap_LIBRARIES "")
set(RTABMap_TARGETS "")
set(_RTABMap_supported_components utilite core gui)
foreach(_comp ${_RTABMap_supported_components})
if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/RTABMap_${_comp}Targets.cmake")
include("${CMAKE_CURRENT_LIST_DIR}/RTABMap_${_comp}Targets.cmake")
set(RTABMap_${_comp}_FOUND True)
set(RTABMap_TARGETS
${RTABMap_TARGETS}
rtabmap::${_comp})
get_target_property(RTABMap_${_comp}_INCLUDE_DIRS rtabmap::${_comp} INTERFACE_INCLUDE_DIRECTORIES)
get_target_property(RTABMap_${_comp}_LIBRARIES rtabmap::${_comp} INTERFACE_LINK_LIBRARIES)
set(RTABMap_INCLUDE_DIRS
${RTABMap_INCLUDE_DIRS}
${RTABMap_${_comp}_INCLUDE_DIRS})
set(RTABMap_LIBRARIES
${RTABMap_LIBRARIES}
rtabmap::${_comp})
if(RTABMap_${_comp}_LIBRARIES)
set(RTABMap_LIBRARIES
${RTABMap_LIBRARIES}
${RTABMap_${_comp}_LIBRARIES})
endif()
else()
set(RTABMap_${_comp}_FOUND False)
endif()
endforeach()
include("${CMAKE_CURRENT_LIST_DIR}/RTABMapTargets.cmake")
foreach(_comp ${RTABMap_FIND_COMPONENTS})
if (NOT RTABMap_${_comp}_FOUND)
if(${RTABMap_FIND_REQUIRED_${_comp}})
set(RTABMap_FOUND False)
set(RTABMap_NOT_FOUND_MESSAGE "Unsupported or not found required component: ${_comp}")
endif()
endif()
endforeach()

View File

@@ -1,11 +0,0 @@
set(PACKAGE_VERSION "@RTABMAP_VERSION@")
# Check whether the requested PACKAGE_FIND_VERSION is compatible
if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}")
set(PACKAGE_VERSION_COMPATIBLE FALSE)
else()
set(PACKAGE_VERSION_COMPATIBLE TRUE)
if ("${PACKAGE_VERSION}" VERSION_EQUAL "${PACKAGE_FIND_VERSION}")
set(PACKAGE_VERSION_EXACT TRUE)
endif()
endif()

View File

@@ -40,10 +40,12 @@ 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
@MRPT@#define RTABMAP_MRPT
@VERTIGO@#define RTABMAP_VERTIGO
@OPENNI@#define RTABMAP_OPENNI
@OPENNI2@#define RTABMAP_OPENNI2
@FREENECT@#define RTABMAP_FREENECT
@FREENECT2@#define RTABMAP_FREENECT2
@@ -52,7 +54,9 @@ 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
@@ -65,7 +69,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@REALSENSE2@#define RTABMAP_REALSENSE2
@MYNTEYE@#define RTABMAP_MYNTEYE
@DEPTHAI@#define RTABMAP_DEPTHAI
@XVSDK@#define RTABMAP_XVSDK
@OCTOMAP@#define RTABMAP_OCTOMAP
@GRIDMAP@#define RTABMAP_GRIDMAP
@CPUTSDF@#define RTABMAP_CPUTSDF
@ALICE_VISION@#define RTABMAP_ALICE_VISION
@OPENCHISEL@#define RTABMAP_OPENCHISEL

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

@@ -334,11 +334,12 @@ void CameraARCore::setScreenRotationAndSize(ScreenRotation colorCameraToDisplayR
}
}
SensorData CameraARCore::captureImage(CameraInfo * info)
SensorData CameraARCore::updateDataOnRender(Transform & pose)
{
UScopeMutex lock(arSessionMutex_);
//LOGI("Capturing image...");
pose.setNull();
SensorData data;
if(!arSession_)
{
@@ -370,7 +371,7 @@ SensorData CameraARCore::captureImage(CameraInfo * info)
if (geometry_changed != 0 || !uvs_initialized_) {
ArFrame_transformCoordinates2d(
arSession_, arFrame_, AR_COORDINATES_2D_OPENGL_NORMALIZED_DEVICE_COORDINATES,
BackgroundRenderer::kNumVertices, BackgroundRenderer_kVertices, AR_COORDINATES_2D_TEXTURE_NORMALIZED,
BackgroundRenderer::kNumVertices, BackgroundRenderer_kVerticesDevice, AR_COORDINATES_2D_TEXTURE_NORMALIZED,
transformed_uvs_);
UASSERT(transformed_uvs_);
uvs_initialized_ = true;
@@ -393,7 +394,6 @@ SensorData CameraARCore::captureImage(CameraInfo * info)
ArTrackingState camera_tracking_state;
ArCamera_getTrackingState(arSession_, ar_camera, &camera_tracking_state);
Transform pose;
CameraModel model;
if(camera_tracking_state == AR_TRACKING_STATE_TRACKING)
{
@@ -401,24 +401,13 @@ SensorData CameraARCore::captureImage(CameraInfo * info)
float pose_raw[7];
ArCamera_getPose(arSession_, ar_camera, arPose_);
ArPose_getPoseRaw(arSession_, arPose_, pose_raw);
pose = Transform(pose_raw[4], pose_raw[5], pose_raw[6], pose_raw[0], pose_raw[1], pose_raw[2], pose_raw[3]);
pose = rtabmap::rtabmap_world_T_opengl_world * pose * rtabmap::opengl_world_T_rtabmap_world;
Transform poseArCore = Transform(pose_raw[4], pose_raw[5], pose_raw[6], pose_raw[0], pose_raw[1], pose_raw[2], pose_raw[3]);
poseArCore = rtabmap::rtabmap_world_T_opengl_world * poseArCore * rtabmap::opengl_world_T_rtabmap_world;
Transform poseArCore = pose;
if(pose.isNull())
if(poseArCore.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;
@@ -520,11 +509,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;
@@ -551,6 +540,17 @@ SensorData CameraARCore::captureImage(CameraInfo * info)
data = SensorData(scan, rgb, depthFromMotion_?getOcclusionImage():cv::Mat(), model, 0, stamp);
data.setFeatures(kpts, kpts3, cv::Mat());
if(!poseArCore.isNull())
{
pose = poseArCore;
this->poseReceived(pose, stamp);
// adjust origin
if(!getOriginOffset().isNull())
{
pose = getOriginOffset() * pose;
}
}
}
}
else
@@ -571,134 +571,6 @@ SensorData CameraARCore::captureImage(CameraInfo * info)
ArCamera_release(ar_camera);
return data;
}
void CameraARCore::capturePoseOnly()
{
UScopeMutex lock(arSessionMutex_);
//LOGI("Capturing image...");
if(!arSession_)
{
return;
}
if(textureId_ != 0)
{
glBindTexture(GL_TEXTURE_EXTERNAL_OES, textureId_);
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
ArSession_setCameraTextureName(arSession_, textureId_);
}
// Update session to get current frame and render camera background.
if (ArSession_update(arSession_, arFrame_) != AR_SUCCESS) {
LOGE("CameraARCore::capturePoseOnly() ArSession_update error");
return;
}
// If display rotation changed (also includes view size change), we need to
// re-query the uv coordinates for the on-screen portion of the camera image.
int32_t geometry_changed = 0;
ArFrame_getDisplayGeometryChanged(arSession_, arFrame_, &geometry_changed);
if (geometry_changed != 0 || !uvs_initialized_) {
ArFrame_transformCoordinates2d(
arSession_, arFrame_, AR_COORDINATES_2D_OPENGL_NORMALIZED_DEVICE_COORDINATES,
BackgroundRenderer::kNumVertices, BackgroundRenderer_kVertices, AR_COORDINATES_2D_TEXTURE_NORMALIZED,
transformed_uvs_);
UASSERT(transformed_uvs_);
uvs_initialized_ = true;
}
ArCamera* ar_camera;
ArFrame_acquireCamera(arSession_, arFrame_, &ar_camera);
ArCamera_getViewMatrix(arSession_, ar_camera, glm::value_ptr(viewMatrix_));
ArCamera_getProjectionMatrix(arSession_, ar_camera,
/*near=*/0.1f, /*far=*/100.f,
glm::value_ptr(projectionMatrix_));
// 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);
Transform pose;
CameraModel model;
if(camera_tracking_state == AR_TRACKING_STATE_TRACKING)
{
// pose in OpenGL coordinates
float pose_raw[7];
ArCamera_getPose(arSession_, ar_camera, arPose_);
ArPose_getPoseRaw(arSession_, arPose_, pose_raw);
pose = Transform(pose_raw[4], pose_raw[5], pose_raw[6], pose_raw[0], pose_raw[1], pose_raw[2], pose_raw[3]);
if(!pose.isNull())
{
pose = rtabmap::rtabmap_world_T_opengl_world * pose * rtabmap::opengl_world_T_rtabmap_world;
this->poseReceived(pose);
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)
{
LOGD("Acquire depth image!");
ArImage * depthImage = nullptr;
ArFrame_acquireDepthImage(arSession_, arFrame_, &depthImage);
ArImageFormat format;
ArImage_getFormat(arSession_, depthImage, &format);
if(format == AR_IMAGE_FORMAT_DEPTH16)
{
LOGD("Depth format detected!");
int planeCount;
ArImage_getNumberOfPlanes(arSession_, depthImage, &planeCount);
LOGD("planeCount=%d", planeCount);
UASSERT_MSG(planeCount == 1, uFormat("Error: getNumberOfPlanes() planceCount = %d", planeCount).c_str());
const uint8_t *data = nullptr;
int len = 0;
int stride;
int width;
int height;
ArImage_getWidth(arSession_, depthImage, &width);
ArImage_getHeight(arSession_, depthImage, &height);
ArImage_getPlaneRowStride(arSession_, depthImage, 0, &stride);
ArImage_getPlaneData(arSession_, depthImage, 0, &data, &len);
LOGD("width=%d, height=%d, bytes=%d stride=%d", width, height, len, stride);
cv::Mat occlusionImage = cv::Mat(height, width, CV_16UC1, (void*)data).clone();
float fx,fy, cx, cy;
int32_t rgb_width, rgb_height;
ArCamera_getImageIntrinsics(arSession_, ar_camera, arCameraIntrinsics_);
ArCameraIntrinsics_getFocalLength(arSession_, arCameraIntrinsics_, &fx, &fy);
ArCameraIntrinsics_getPrincipalPoint(arSession_, arCameraIntrinsics_, &cx, &cy);
ArCameraIntrinsics_getImageDimensions(arSession_, arCameraIntrinsics_, &rgb_width, &rgb_height);
float scaleX = (float)width / (float)rgb_width;
float scaleY = (float)height / (float)rgb_height;
CameraModel occlusionModel(fx*scaleX, fy*scaleY, cx*scaleX, cy*scaleY, pose*deviceTColorCamera_, 0, cv::Size(width, height));
this->setOcclusionImage(occlusionImage, occlusionModel);
}
ArImage_release(depthImage);
}
}
ArCamera_release(ar_camera);
}
} /* namespace rtabmap */

View File

@@ -63,23 +63,14 @@ public:
CameraARCore(void* env, void* context, void* activity, bool depthFromMotion = false, bool smoothing = false);
virtual ~CameraARCore();
bool uvsInitialized() const {return uvs_initialized_;}
const float* uvsTransformed() const {return transformed_uvs_;}
void getVPMatrices(glm::mat4 & view, glm::mat4 & projection) const {view=viewMatrix_; projection=projectionMatrix_;}
virtual void setScreenRotationAndSize(ScreenRotation colorCameraToDisplayRotation, int width, int height);
virtual bool init(const std::string & calibrationFolder = ".", const std::string & cameraName = "");
void setupGL();
virtual void close(); // close Tango connection
virtual void close(); // close ARCore connection
virtual std::string getSerial() const;
GLuint getTextureId() const {return textureId_;}
void imageCallback(AImageReader *reader);
protected:
virtual SensorData captureImage(CameraInfo * info = 0); // should be called in opengl thread
virtual void capturePoseOnly();
virtual SensorData updateDataOnRender(Transform & pose); // should be called in opengl thread
private:
rtabmap::Transform getPoseAtTimestamp(double timestamp);

View File

@@ -117,9 +117,6 @@ bool CameraAREngine::init(const std::string & calibrationFolder, const std::stri
deviceTColorCamera_ = opticalRotation;
// Required as ArSession_update does some off-screen OpenGL stuff...
HwArSession_setCameraTextureName(arSession_, textureId_);
if (HwArSession_resume(arSession_) != HWAR_SUCCESS)
{
UERROR("Cannot resume camera!");
@@ -169,38 +166,87 @@ void CameraAREngine::close()
CameraMobile::close();
}
SensorData CameraAREngine::captureImage(CameraInfo * info)
void CameraAREngine::setScreenRotationAndSize(ScreenRotation colorCameraToDisplayRotation, int width, int height)
{
CameraMobile::setScreenRotationAndSize(colorCameraToDisplayRotation, width, height);
if(arSession_)
{
int ret = static_cast<int>(colorCameraToDisplayRotation) + 1; // remove 90deg camera rotation
if (ret > 3) {
ret -= 4;
}
HwArSession_setDisplayGeometry(arSession_, ret, width, height);
}
}
SensorData CameraAREngine::updateDataOnRender(Transform & pose)
{
UScopeMutex lock(arSessionMutex_);
//LOGI("Capturing image...");
pose.setNull();
SensorData data;
if(!arSession_)
{
return data;
}
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);
}
if(textureId_!=0)
HwArSession_setCameraTextureName(arSession_, textureId_);
// Update session to get current frame and render camera background.
if (HwArSession_update(arSession_, arFrame_) != HWAR_SUCCESS) {
LOGE("CameraAREngine::captureImage() ArSession_update error");
return data;
}
// If display rotation changed (also includes view size change), we need to
// re-query the uv coordinates for the on-screen portion of the camera image.
int32_t geometry_changed = 0;
HwArFrame_getDisplayGeometryChanged(arSession_, arFrame_, &geometry_changed);
if (geometry_changed != 0 || !uvs_initialized_) {
HwArFrame_transformDisplayUvCoords(
arSession_, arFrame_,
BackgroundRenderer::kNumVertices*2, BackgroundRenderer_kVerticesView,
transformed_uvs_);
UERROR("uv: (%f,%f) (%f,%f) (%f,%f) (%f,%f)",
transformed_uvs_[0], transformed_uvs_[1],
transformed_uvs_[2], transformed_uvs_[3],
transformed_uvs_[4], transformed_uvs_[5],
transformed_uvs_[6], transformed_uvs_[7]);
UASSERT(transformed_uvs_);
uvs_initialized_ = true;
}
HwArCamera* ar_camera;
HwArFrame_acquireCamera(arSession_, arFrame_, &ar_camera);
HwArCamera_getViewMatrix(arSession_, ar_camera, glm::value_ptr(viewMatrix_));
HwArCamera_getProjectionMatrix(arSession_, ar_camera,
/*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_));
}
HwArTrackingState camera_tracking_state;
HwArCamera_getTrackingState(arSession_, ar_camera, &camera_tracking_state);
Transform pose;
if(camera_tracking_state == HWAR_TRACKING_STATE_TRACKING)
{
// pose in OpenGL coordinates
float pose_raw[7];
HwArCamera_getPose(arSession_, ar_camera, arPose_);
HwArPose_getPoseRaw(arSession_, arPose_, pose_raw);
pose = Transform(pose_raw[4], pose_raw[5], pose_raw[6], pose_raw[0], pose_raw[1], pose_raw[2], pose_raw[3]);
// Get calibration parameters
// FIXME: Hard-coded as getting intrinsics with the api fails
float fx=492.689667,fy=492.606201, cx=323.594849, cy=234.659744;
@@ -244,7 +290,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
@@ -274,6 +320,26 @@ SensorData CameraAREngine::captureImage(CameraInfo * info)
double stamp = double(timestamp_ns)/10e8;
CameraModel model = CameraModel(fx, fy, cx, cy, deviceTColorCamera_, 0, cv::Size(camWidth, camHeight));
data = SensorData(outputRGB, outputDepth, model, 0, stamp);
// pose in OpenGL coordinates
float pose_raw[7];
HwArCamera_getPose(arSession_, ar_camera, arPose_);
HwArPose_getPoseRaw(arSession_, arPose_, pose_raw);
pose = Transform(pose_raw[4], pose_raw[5], pose_raw[6], pose_raw[0], pose_raw[1], pose_raw[2], pose_raw[3]);
if(pose.isNull())
{
LOGE("CameraAREngine: Pose is null");
}
else
{
pose = rtabmap::rtabmap_world_T_opengl_world * pose * rtabmap::opengl_world_T_rtabmap_world;
this->poseReceived(pose, stamp);
// adjust origin
if(!getOriginOffset().isNull())
{
pose = getOriginOffset() * pose;
}
}
}
}
else
@@ -291,66 +357,8 @@ SensorData CameraAREngine::captureImage(CameraInfo * info)
}
HwArCamera_release(ar_camera);
if(pose.isNull())
{
LOGE("CameraAREngine: Pose is null");
}
else
{
pose = rtabmap::rtabmap_world_T_opengl_world * pose * rtabmap::opengl_world_T_rtabmap_world;
this->poseReceived(pose);
// adjust origin
if(!getOriginOffset().isNull())
{
pose = getOriginOffset() * pose;
}
info->odomPose = pose;
}
return data;
}
void CameraAREngine::capturePoseOnly()
{
UScopeMutex lock(arSessionMutex_);
//LOGI("Capturing image...");
SensorData data;
if(!arSession_)
{
return;
}
// Update session to get current frame and render camera background.
if (HwArSession_update(arSession_, arFrame_) != HWAR_SUCCESS) {
LOGE("CameraARCore::captureImage() ArSession_update error");
return;
}
HwArCamera* ar_camera;
HwArFrame_acquireCamera(arSession_, arFrame_, &ar_camera);
HwArTrackingState camera_tracking_state;
HwArCamera_getTrackingState(arSession_, ar_camera, &camera_tracking_state);
Transform pose;
CameraModel model;
if(camera_tracking_state == HWAR_TRACKING_STATE_TRACKING)
{
// pose in OpenGL coordinates
float pose_raw[7];
HwArCamera_getPose(arSession_, ar_camera, arPose_);
HwArPose_getPoseRaw(arSession_, arPose_, pose_raw);
pose = Transform(pose_raw[4], pose_raw[5], pose_raw[6], pose_raw[0], pose_raw[1], pose_raw[2], pose_raw[3]);
if(!pose.isNull())
{
pose = rtabmap::rtabmap_world_T_opengl_world * pose * rtabmap::opengl_world_T_rtabmap_world;
this->poseReceived(pose);
}
}
HwArCamera_release(ar_camera);
}
} /* namespace rtabmap */

View File

@@ -38,6 +38,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <rtabmap/utilite/UEvent.h>
#include <rtabmap/utilite/UTimer.h>
#include <boost/thread/mutex.hpp>
#include <background_renderer.h>
#include <huawei_arengine_interface.h>
@@ -48,13 +49,14 @@ public:
CameraAREngine(void* env, void* context, void* activity, bool smoothing = false);
virtual ~CameraAREngine();
virtual void setScreenRotationAndSize(ScreenRotation colorCameraToDisplayRotation, int width, int height);
virtual bool init(const std::string & calibrationFolder = ".", const std::string & cameraName = "");
virtual void close(); // close Tango connection
virtual void close(); // close AREngine connection
virtual std::string getSerial() const;
protected:
virtual SensorData captureImage(CameraInfo * info = 0);
virtual void capturePoseOnly();
virtual SensorData updateDataOnRender(Transform & pose);
private:
rtabmap::Transform getPoseAtTimestamp(double timestamp);
@@ -69,7 +71,6 @@ private:
HwArCameraIntrinsics *arCameraIntrinsics_ = nullptr;
HwArPose * arPose_ = nullptr;
bool arInstallRequested_;
GLuint textureId_;
UMutex arSessionMutex_;
};

View File

@@ -55,10 +55,8 @@ const rtabmap::Transform CameraMobile::opticalRotationInv = Transform(
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),
colorCameraToDisplayRotation_(ROTATION_0),
@@ -79,13 +77,12 @@ bool CameraMobile::init(const std::string &, const std::string &)
void CameraMobile::close()
{
previousPose_.setNull();
previousStamp_ = 0.0;
firstFrame_ = true;
lastKnownGPS_ = GPS();
lastEnvSensors_.clear();
originOffset_ = Transform();
originUpdate_ = false;
pose_ = Transform();
dataPose_ = Transform();
data_ = SensorData();
if(textureId_ != 0)
@@ -97,35 +94,107 @@ void CameraMobile::close()
void CameraMobile::resetOrigin()
{
previousPose_.setNull();
previousStamp_ = 0.0;
firstFrame_ = true;
lastKnownGPS_ = GPS();
lastEnvSensors_.clear();
pose_ = Transform();
dataPose_ = Transform();
data_ = SensorData();
originUpdate_ = true;
}
void CameraMobile::poseReceived(const Transform & pose)
bool CameraMobile::getPose(double stamp, Transform & pose, cv::Mat & covariance, double maxWaitTime)
{
pose.setNull();
int maxWaitTimeMs = maxWaitTime * 1000;
// Interpolate pose
if(!poseBuffer_.empty())
{
poseMutex_.lock();
int waitTry = 0;
while(maxWaitTimeMs>0 && poseBuffer_.rbegin()->first < stamp && waitTry < maxWaitTimeMs)
{
poseMutex_.unlock();
++waitTry;
uSleep(1);
poseMutex_.lock();
}
if(poseBuffer_.rbegin()->first < stamp)
{
if(maxWaitTimeMs > 0)
{
UWARN("Could not find poses to interpolate at time %f after waiting %d ms (latest is %f)...", stamp, maxWaitTimeMs, poseBuffer_.rbegin()->first);
}
else
{
UWARN("Could not find poses to interpolate at time %f (latest is %f)...", stamp, poseBuffer_.rbegin()->first);
}
}
else
{
std::map<double, Transform>::const_iterator iterB = poseBuffer_.lower_bound(stamp);
std::map<double, Transform>::const_iterator iterA = iterB;
if(iterA != poseBuffer_.begin())
{
iterA = --iterA;
}
if(iterB == poseBuffer_.end())
{
iterB = --iterB;
}
if(iterA == iterB && stamp == iterA->first)
{
pose = iterA->second;
}
else if(stamp >= iterA->first && stamp <= iterB->first)
{
pose = iterA->second.interpolate((stamp-iterA->first) / (iterB->first-iterA->first), iterB->second);
}
else // stamp < iterA->first
{
UWARN("Could not find pose data to interpolate at time %f (earliest is %f). Are sensors synchronized?", stamp, iterA->first);
}
}
poseMutex_.unlock();
}
return !pose.isNull();
}
void CameraMobile::poseReceived(const Transform & pose, double deviceStamp)
{
if(!pose.isNull())
{
// send pose of the camera (without optical rotation)
Transform p = pose*deviceTColorCamera_;
Transform p = pose;
if(originUpdate_)
{
originOffset_ = p.translation().inverse();
originUpdate_ = false;
}
if(stampEpochOffset_ == 0.0)
{
stampEpochOffset_ = UTimer::now() - deviceStamp;
}
double epochStamp = stampEpochOffset_ + deviceStamp;
if(!originOffset_.isNull())
{
this->post(new PoseEvent(originOffset_*p));
p = originOffset_*p;
}
else
{
this->post(new PoseEvent(p));
UScopeMutex lock(poseMutex_);
poseBuffer_.insert(poseBuffer_.end(), std::make_pair(epochStamp, p));
if(poseBuffer_.size() > 1000)
{
poseBuffer_.erase(poseBuffer_.begin());
}
}
// send pose of the camera (with optical rotation)
this->post(new PoseEvent(p * deviceTColorCamera_));
}
}
@@ -139,11 +208,20 @@ void CameraMobile::setGPS(const GPS & gps)
lastKnownGPS_ = gps;
}
void CameraMobile::setData(const SensorData & data, const Transform & pose, const glm::mat4 & viewMatrix, const glm::mat4 & projectionMatrix, const float * texCoord)
void CameraMobile::addEnvSensor(int type, float value)
{
LOGD("CameraMobile::setData pose=%s stamp=%f", pose.prettyPrint().c_str(), data.stamp());
lastEnvSensors_.insert(std::make_pair((EnvSensor::Type)type, EnvSensor((EnvSensor::Type)type, value)));
}
void CameraMobile::update(const SensorData & data, const Transform & pose, const glm::mat4 & viewMatrix, const glm::mat4 & projectionMatrix, const float * texCoord)
{
UScopeMutex lock(dataMutex_);
bool notify = !data_.isValid();
LOGD("CameraMobile::update pose=%s stamp=%f", pose.prettyPrint().c_str(), data.stamp());
data_ = data;
pose_ = pose;
dataPose_ = pose;
viewMatrix_ = viewMatrix;
projectionMatrix_ = projectionMatrix;
@@ -151,7 +229,7 @@ void CameraMobile::setData(const SensorData & data, const Transform & pose, cons
// adjust origin
if(!originOffset_.isNull())
{
pose_ = originOffset_ * pose_;
dataPose_ = originOffset_ * dataPose_;
viewMatrix_ = glm::inverse(rtabmap::glmFromTransform(rtabmap::opengl_world_T_rtabmap_world * originOffset_ *rtabmap::rtabmap_world_T_opengl_world)*glm::inverse(viewMatrix_));
}
@@ -166,12 +244,12 @@ void CameraMobile::setData(const SensorData & data, const Transform & pose, cons
uvs_initialized_ = true;
}
LOGD("CameraMobile::setData textureId_=%d", (int)textureId_);
LOGD("CameraMobile::update textureId_=%d", (int)textureId_);
if(textureId_ != 0 && texCoord != 0)
{
cv::Mat rgbImage;
cv::cvtColor(data.imageRaw(), rgbImage, CV_BGR2RGBA);
cv::cvtColor(data.imageRaw(), rgbImage, cv::COLOR_BGR2RGBA);
glBindTexture(GL_TEXTURE_2D, textureId_);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
@@ -193,78 +271,63 @@ void CameraMobile::setData(const SensorData & data, const Transform & pose, cons
return;
}
}
}
void CameraMobile::addEnvSensor(int type, float value)
{
lastEnvSensors_.insert(std::make_pair((EnvSensor::Type)type, EnvSensor((EnvSensor::Type)type, value)));
}
void CameraMobile::spinOnce()
{
if(!this->isRunning())
postUpdate();
if(notify)
{
bool ignoreFrame = false;
//float rate = 10.0f; // maximum 10 FPS for image data
double now = UTimer::now();
/*if(rate>0.0f)
{
if((spinOncePreviousStamp_>=0.0 && now>spinOncePreviousStamp_ && now - spinOncePreviousStamp_ < 1.0f/rate) ||
((spinOncePreviousStamp_<=0.0 || now<=spinOncePreviousStamp_) && spinOnceFrameRateTimer_.getElapsedTime() < 1.0f/rate))
{
ignoreFrame = true;
}
}*/
dataReady_.release();
}
}
if(!ignoreFrame)
void CameraMobile::updateOnRender()
{
UScopeMutex lock(dataMutex_);
bool notify = !data_.isValid();
data_ = updateDataOnRender(dataPose_);
if(data_.isValid())
{
postUpdate();
if(notify)
{
spinOnceFrameRateTimer_.start();
spinOncePreviousStamp_ = now;
mainLoop();
}
else
{
// just send pose
capturePoseOnly();
dataReady_.release();
}
}
}
void CameraMobile::mainLoopBegin()
SensorData CameraMobile::updateDataOnRender(Transform & pose)
{
double t = cameraStartedTime_.elapsed();
if(t < 5.0)
{
uSleep((5.0-t)*1000); // just to make sure that the camera is started
}
LOGE("To use CameraMobile::updateOnRender(), CameraMobile::updateDataOnRender() "
"should be overridden by inherited classes. Returning empty data!\n");
return SensorData();
}
void CameraMobile::mainLoop()
void CameraMobile::postUpdate()
{
CameraInfo info;
SensorData data = this->captureImage(&info);
if(data.isValid() && !info.odomPose.isNull())
if(data_.isValid())
{
if(lastKnownGPS_.stamp() > 0.0 && data.stamp()-lastKnownGPS_.stamp()<1.0)
if(lastKnownGPS_.stamp() > 0.0 && data_.stamp()-lastKnownGPS_.stamp()<1.0)
{
data.setGPS(lastKnownGPS_);
data_.setGPS(lastKnownGPS_);
}
else if(lastKnownGPS_.stamp()>0.0)
{
LOGD("GPS too old (current time=%f, gps time = %f)", data.stamp(), lastKnownGPS_.stamp());
LOGD("GPS too old (current time=%f, gps time = %f)", data_.stamp(), lastKnownGPS_.stamp());
}
if(lastEnvSensors_.size())
{
data.setEnvSensors(lastEnvSensors_);
data_.setEnvSensors(lastEnvSensors_);
lastEnvSensors_.clear();
}
if(smoothing_ && !data.depthRaw().empty())
if(smoothing_ && !data_.depthRaw().empty())
{
//UTimer t;
data.setDepthOrRightRaw(rtabmap::util2d::fastBilateralFiltering(data.depthRaw(), bilateralFilteringSigmaS, bilateralFilteringSigmaR));
data_.setDepthOrRightRaw(rtabmap::util2d::fastBilateralFiltering(data_.depthRaw(), bilateralFilteringSigmaS, bilateralFilteringSigmaR));
//LOGD("Bilateral filtering, time=%fs", t.ticks());
}
@@ -273,15 +336,15 @@ void CameraMobile::mainLoop()
{
UDEBUG("ROTATION_90");
cv::Mat rgb, depth;
cv::Mat rgbt(data.imageRaw().cols, data.imageRaw().rows, data.imageRaw().type());
cv::flip(data.imageRaw(),rgb,1);
cv::Mat rgbt(data_.imageRaw().cols, data_.imageRaw().rows, data_.imageRaw().type());
cv::flip(data_.imageRaw(),rgb,1);
cv::transpose(rgb,rgbt);
rgb = rgbt;
cv::Mat deptht(data.depthRaw().cols, data.depthRaw().rows, data.depthRaw().type());
cv::flip(data.depthRaw(),depth,1);
cv::Mat deptht(data_.depthRaw().cols, data_.depthRaw().rows, data_.depthRaw().type());
cv::flip(data_.depthRaw(),depth,1);
cv::transpose(depth,deptht);
depth = deptht;
CameraModel model = data.cameraModels()[0];
CameraModel model = data_.cameraModels()[0];
cv::Size sizet(model.imageHeight(), model.imageWidth());
model = CameraModel(
model.fy(),
@@ -290,25 +353,25 @@ void CameraMobile::mainLoop()
model.cx()>0?model.imageWidth()-model.cx():0,
model.localTransform()*rtabmap::Transform(0,-1,0,0, 1,0,0,0, 0,0,1,0));
model.setImageSize(sizet);
data.setRGBDImage(rgb, depth, model);
data_.setRGBDImage(rgb, depth, model);
std::vector<cv::KeyPoint> keypoints = data.keypoints();
std::vector<cv::KeyPoint> keypoints = data_.keypoints();
for(size_t i=0; i<keypoints.size(); ++i)
{
keypoints[i].pt.x = data.keypoints()[i].pt.y;
keypoints[i].pt.y = rgb.rows - data.keypoints()[i].pt.x;
keypoints[i].pt.x = data_.keypoints()[i].pt.y;
keypoints[i].pt.y = rgb.rows - data_.keypoints()[i].pt.x;
}
data.setFeatures(keypoints, data.keypoints3D(), cv::Mat());
data_.setFeatures(keypoints, data_.keypoints3D(), cv::Mat());
}
else if(colorCameraToDisplayRotation_ == ROTATION_180)
{
UDEBUG("ROTATION_180");
cv::Mat rgb, depth;
cv::flip(data.imageRaw(),rgb,1);
cv::flip(data_.imageRaw(),rgb,1);
cv::flip(rgb,rgb,0);
cv::flip(data.depthOrRightRaw(),depth,1);
cv::flip(data_.depthOrRightRaw(),depth,1);
cv::flip(depth,depth,0);
CameraModel model = data.cameraModels()[0];
CameraModel model = data_.cameraModels()[0];
cv::Size sizet(model.imageWidth(), model.imageHeight());
model = CameraModel(
model.fx(),
@@ -317,26 +380,26 @@ void CameraMobile::mainLoop()
model.cy()>0?model.imageHeight()-model.cy():0,
model.localTransform()*rtabmap::Transform(0,0,0,0,0,1,0));
model.setImageSize(sizet);
data.setRGBDImage(rgb, depth, model);
data_.setRGBDImage(rgb, depth, model);
std::vector<cv::KeyPoint> keypoints = data.keypoints();
std::vector<cv::KeyPoint> keypoints = data_.keypoints();
for(size_t i=0; i<keypoints.size(); ++i)
{
keypoints[i].pt.x = rgb.cols - data.keypoints()[i].pt.x;
keypoints[i].pt.y = rgb.rows - data.keypoints()[i].pt.y;
keypoints[i].pt.x = rgb.cols - data_.keypoints()[i].pt.x;
keypoints[i].pt.y = rgb.rows - data_.keypoints()[i].pt.y;
}
data.setFeatures(keypoints, data.keypoints3D(), cv::Mat());
data_.setFeatures(keypoints, data_.keypoints3D(), cv::Mat());
}
else if(colorCameraToDisplayRotation_ == ROTATION_270)
{
UDEBUG("ROTATION_270");
cv::Mat rgb(data.imageRaw().cols, data.imageRaw().rows, data.imageRaw().type());
cv::transpose(data.imageRaw(),rgb);
cv::Mat rgb(data_.imageRaw().cols, data_.imageRaw().rows, data_.imageRaw().type());
cv::transpose(data_.imageRaw(),rgb);
cv::flip(rgb,rgb,1);
cv::Mat depth(data.depthOrRightRaw().cols, data.depthOrRightRaw().rows, data.depthOrRightRaw().type());
cv::transpose(data.depthOrRightRaw(),depth);
cv::Mat depth(data_.depthOrRightRaw().cols, data_.depthOrRightRaw().rows, data_.depthOrRightRaw().type());
cv::transpose(data_.depthOrRightRaw(),depth);
cv::flip(depth,depth,1);
CameraModel model = data.cameraModels()[0];
CameraModel model = data_.cameraModels()[0];
cv::Size sizet(model.imageHeight(), model.imageWidth());
model = CameraModel(
model.fy(),
@@ -345,61 +408,54 @@ void CameraMobile::mainLoop()
model.cx(),
model.localTransform()*rtabmap::Transform(0,1,0,0, -1,0,0,0, 0,0,1,0));
model.setImageSize(sizet);
data.setRGBDImage(rgb, depth, model);
data_.setRGBDImage(rgb, depth, model);
std::vector<cv::KeyPoint> keypoints = data.keypoints();
std::vector<cv::KeyPoint> keypoints = data_.keypoints();
for(size_t i=0; i<keypoints.size(); ++i)
{
keypoints[i].pt.x = rgb.cols - data.keypoints()[i].pt.y;
keypoints[i].pt.y = data.keypoints()[i].pt.x;
keypoints[i].pt.x = rgb.cols - data_.keypoints()[i].pt.y;
keypoints[i].pt.y = data_.keypoints()[i].pt.x;
}
data.setFeatures(keypoints, data.keypoints3D(), cv::Mat());
data_.setFeatures(keypoints, data_.keypoints3D(), cv::Mat());
}
rtabmap::Transform pose = info.odomPose;
data.setGroundTruth(Transform());
// convert stamp to epoch
bool firstFrame = previousPose_.isNull();
if(firstFrame)
{
stampEpochOffset_ = UTimer::now()-data.stamp();
}
data.setStamp(stampEpochOffset_ + data.stamp());
OdometryInfo info;
if(!firstFrame)
{
info.interval = data.stamp()-previousStamp_;
info.transform = previousPose_.inverse() * pose;
}
// linear cov = 0.0001
info.reg.covariance = cv::Mat::eye(6,6,CV_64FC1) * (firstFrame?9999.0:0.0001);
if(!firstFrame)
{
// angular cov = 0.000001
info.reg.covariance.at<double>(3,3) *= 0.01;
info.reg.covariance.at<double>(4,4) *= 0.01;
info.reg.covariance.at<double>(5,5) *= 0.01;
}
LOGI("Publish odometry message (variance=%f)", firstFrame?9999:0.0001);
this->post(new OdometryEvent(data, pose, info));
previousPose_ = pose;
previousStamp_ = data.stamp();
}
else if(!this->isKilled() && info.odomPose.isNull())
{
LOGW("Odometry lost");
this->post(new OdometryEvent());
}
}
SensorData CameraMobile::captureImage(CameraInfo * info)
SensorData CameraMobile::captureImage(SensorCaptureInfo * info)
{
if(info)
SensorData data;
if(dataReady_.acquire(1, 5000))
{
info->odomPose = pose_;
UScopeMutex lock(dataMutex_);
data = data_;
data_ = SensorData();
}
return data_;
if(data.isValid())
{
data.setGroundTruth(Transform());
data.setStamp(stampEpochOffset_ + data.stamp());
if(info)
{
// linear cov = 0.0001
info->odomCovariance = cv::Mat::eye(6,6,CV_64FC1) * (firstFrame_?9999.0:0.0001);
if(!firstFrame_)
{
// angular cov = 0.000001
info->odomCovariance.at<double>(3,3) *= 0.01;
info->odomCovariance.at<double>(4,4) *= 0.01;
info->odomCovariance.at<double>(5,5) *= 0.01;
}
info->odomPose = dataPose_;
}
firstFrame_ = false;
}
else
{
UWARN("CameraMobile::captureImage() invalid data!");
}
return data;
}
LaserScan CameraMobile::scanFromPointCloudData(
@@ -432,23 +488,25 @@ LaserScan CameraMobile::scanFromPointCloudData(
//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))
if(pt.z > 0)
{
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;
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);

View File

@@ -68,7 +68,7 @@ private:
Transform pose_;
};
class CameraMobile : public Camera, public UThread, public UEventsSender {
class CameraMobile : public Camera, public UEventsSender {
public:
static const float bilateralFilteringSigmaS;
static const float bilateralFilteringSigmaR;
@@ -93,14 +93,20 @@ public:
// abstract functions
virtual bool init(const std::string & calibrationFolder = ".", const std::string & cameraName = "");
virtual void close(); // inherited classes should call its parent in their close().
virtual void close(); // inherited classes should call its parent at the end of their close().
virtual std::string getSerial() const {return "CameraMobile";}
void update(const SensorData & data, const Transform & pose, const glm::mat4 & viewMatrix, const glm::mat4 & projectionMatrix, const float * texCoord);
void updateOnRender();
const Transform & getOriginOffset() const {return originOffset_;} // in rtabmap frame
void resetOrigin();
virtual bool isCalibrated() const;
void poseReceived(const Transform & pose); // in rtabmap frame
virtual bool odomProvided() const { return true; }
virtual bool getPose(double epochStamp, Transform & pose, cv::Mat & covariance, double maxWaitTime = 0.06); // Return pose of device in rtabmap frame (with origin offset), stamp should be epoch time
void poseReceived(const Transform & pose, double deviceStamp); // original pose of device in rtabmap frame (without origin offset), stamp of the device (may be not epoch)
double getStampEpochOffset() const {return stampEpochOffset_;}
const CameraModel & getCameraModel() const {return model_;}
const Transform & getDeviceTColorCamera() const {return deviceTColorCamera_;}
@@ -108,10 +114,7 @@ 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, 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_;}
@@ -122,17 +125,15 @@ public:
const cv::Mat & getOcclusionImage(CameraModel * model=0) const {if(model)*model=occlusionModel_; return occlusionImage_; }
protected:
virtual SensorData captureImage(CameraInfo * info = 0);
virtual void capturePoseOnly() {}
virtual SensorData updateDataOnRender(Transform & pose);
virtual void mainLoopBegin();
virtual void mainLoop();
private:
virtual SensorData captureImage(SensorCaptureInfo * info = 0);
void postUpdate(); // Should be called while being protected by dataMutex_
protected:
CameraModel model_; // local transform is the device to camera optical rotation in rtabmap frame
Transform deviceTColorCamera_; // device to camera optical rotation in rtabmap frame
UTimer spinOnceFrameRateTimer_;
double spinOncePreviousStamp_;
GLuint textureId_;
glm::mat4 viewMatrix_;
@@ -141,9 +142,7 @@ protected:
bool uvs_initialized_ = false;
private:
Transform previousPose_;
double previousStamp_;
UTimer cameraStartedTime_;
bool firstFrame_;
double stampEpochOffset_;
bool smoothing_;
ScreenRotation colorCameraToDisplayRotation_;
@@ -152,8 +151,13 @@ private:
Transform originOffset_;
bool originUpdate_;
USemaphore dataReady_;
UMutex dataMutex_;
SensorData data_;
Transform pose_;
Transform dataPose_;
UMutex poseMutex_;
std::map<double, Transform> poseBuffer_; // <stamp, Pose>
cv::Mat occlusionImage_;
CameraModel occlusionModel_;

View File

@@ -101,7 +101,7 @@ void onPoseAvailableRouter(void* context, const TangoPoseData* pose)
if(pose->status_code == TANGO_POSE_VALID)
{
CameraTango* app = static_cast<CameraTango*>(context);
app->poseReceived(rtabmap_world_T_tango_world * app->tangoPoseToTransform(pose) * tango_device_T_rtabmap_world);
app->poseReceived(rtabmap_world_T_tango_world * app->tangoPoseToTransform(pose) * tango_device_T_rtabmap_world, pose->timestamp);
}
}
@@ -444,7 +444,7 @@ void CameraTango::cloudReceived(const cv::Mat & cloud, double timestamp)
//LOGD("Depth received! %fs (%d points)", timestamp, cloud.cols);
UASSERT(cloud.type() == CV_32FC4);
boost::mutex::scoped_lock lock(dataMutex_);
boost::mutex::scoped_lock lock(tangoDataMutex_);
// From post: http://stackoverflow.com/questions/29236110/timing-issues-with-tango-image-frames
// "In the current version of Project Tango Tablet RGB IR camera
@@ -463,7 +463,7 @@ void CameraTango::cloudReceived(const cv::Mat & cloud, double timestamp)
if(dt >= 0.0 && dt < 0.5)
{
bool notify = !data_.isValid();
bool notify = !tangoData_.isValid();
cv::Mat tangoImage = tangoColor_;
cv::Mat rgb;
@@ -478,15 +478,15 @@ void CameraTango::cloudReceived(const cv::Mat & cloud, double timestamp)
LOGD("tangoColorType=%d", tangoColorType);
if(tangoColorType == TANGO_HAL_PIXEL_FORMAT_RGBA_8888)
{
cv::cvtColor(tangoImage, rgb, CV_RGBA2BGR);
cv::cvtColor(tangoImage, rgb, cv::COLOR_RGBA2BGR);
}
else if(tangoColorType == TANGO_HAL_PIXEL_FORMAT_YV12)
{
cv::cvtColor(tangoImage, rgb, CV_YUV2BGR_YV12);
cv::cvtColor(tangoImage, rgb, cv::COLOR_YUV2BGR_YV12);
}
else if(tangoColorType == TANGO_HAL_PIXEL_FORMAT_YCrCb_420_SP)
{
cv::cvtColor(tangoImage, rgb, CV_YUV2BGR_NV21);
cv::cvtColor(tangoImage, rgb, cv::COLOR_YUV2BGR_NV21);
}
else if(tangoColorType == 35)
{
@@ -495,7 +495,7 @@ void CameraTango::cloudReceived(const cv::Mat & cloud, double timestamp)
else
{
LOGE("Not supported color format : %d.", tangoColorType);
data_ = SensorData();
tangoData_ = SensorData();
return;
}
@@ -678,24 +678,24 @@ void CameraTango::cloudReceived(const cv::Mat & cloud, double timestamp)
if(rawScanPublished_)
{
data_ = SensorData(LaserScan::backwardCompatibility(scan, cloud.total()/scanDownsampling, 0, scanLocalTransform), rgb, depth, model, this->getNextSeqID(), rgbStamp);
tangoData_ = SensorData(LaserScan::backwardCompatibility(scan, cloud.total()/scanDownsampling, 0, scanLocalTransform), rgb, depth, model, this->getNextSeqID(), rgbStamp);
}
else
{
data_ = SensorData(rgb, depth, model, this->getNextSeqID(), rgbStamp);
tangoData_ = SensorData(rgb, depth, model, this->getNextSeqID(), rgbStamp);
}
data_.setGroundTruth(odom);
tangoData_.setGroundTruth(odom);
}
else
{
LOGE("Could not get depth and rgb images!?!");
data_ = SensorData();
tangoData_ = SensorData();
return;
}
if(notify)
{
dataReady_.release();
tangoDataReady_.release();
}
LOGD("process cloud received %fs", timer.ticks());
}
@@ -709,7 +709,7 @@ void CameraTango::rgbReceived(const cv::Mat & tangoImage, int type, double times
{
//LOGD("RGB received! %fs", timestamp);
boost::mutex::scoped_lock lock(dataMutex_);
boost::mutex::scoped_lock lock(tangoDataMutex_);
tangoColor_ = tangoImage.clone();
tangoColorStamp_ = timestamp;
@@ -775,10 +775,11 @@ rtabmap::Transform CameraTango::getPoseAtTimestamp(double timestamp)
return pose;
}
SensorData CameraTango::captureImage(CameraInfo * info)
SensorData CameraTango::updateDataOnRender(Transform & pose)
{
//LOGI("Capturing image...");
pose.setNull();
if(textureId_ == 0)
{
glGenTextures(1, &textureId_);
@@ -797,10 +798,7 @@ SensorData CameraTango::captureImage(CameraInfo * info)
if (status == TANGO_SUCCESS)
{
if(info)
{
info->odomPose = getPoseAtTimestamp(video_overlay_timestamp);
}
pose = getPoseAtTimestamp(video_overlay_timestamp);
int rotation = static_cast<int>(getScreenRotation()) + 1; // remove 90deg camera rotation
if (rotation > 3) {
@@ -876,16 +874,13 @@ SensorData CameraTango::captureImage(CameraInfo * info)
}
SensorData data;
if(dataReady_.acquireTry(1))
if(tangoDataReady_.acquireTry(1))
{
boost::mutex::scoped_lock lock(dataMutex_);
data = data_;
data_ = SensorData();
if(info)
{
info->odomPose = data.groundTruth();
data.setGroundTruth(Transform());
}
boost::mutex::scoped_lock lock(tangoDataMutex_);
data = tangoData_;
tangoData_ = SensorData();
pose = data.groundTruth();
data.setGroundTruth(Transform());
}
return data;

View File

@@ -52,7 +52,6 @@ public:
virtual void close(); // close Tango connection
virtual std::string getSerial() const;
rtabmap::Transform tangoPoseToTransform(const TangoPoseData * tangoPose) const;
void setColorCamera(bool enabled) {if(!this->isRunning()) colorCamera_ = enabled;}
void setDecimation(int value) {decimation_ = value;}
void setRawScanPublished(bool enabled) {rawScanPublished_ = enabled;}
@@ -61,7 +60,7 @@ public:
void tangoEventReceived(int type, const char * key, const char * value);
protected:
virtual SensorData captureImage(CameraInfo * info = 0);
virtual SensorData updateDataOnRender(Transform & pose);
private:
rtabmap::Transform getPoseAtTimestamp(double timestamp);
@@ -71,12 +70,12 @@ private:
bool colorCamera_;
int decimation_;
bool rawScanPublished_;
SensorData data_;
SensorData tangoData_;
cv::Mat tangoColor_;
int tangoColorType_;
double tangoColorStamp_;
boost::mutex dataMutex_;
USemaphore dataReady_;
boost::mutex tangoDataMutex_;
USemaphore tangoDataReady_;
cv::Mat fisheyeRectifyMapX_;
cv::Mat fisheyeRectifyMapY_;
};

View File

@@ -64,6 +64,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <rtabmap/core/Memory.h>
#include <rtabmap/core/GainCompensator.h>
#include <rtabmap/core/DBDriver.h>
#include <rtabmap/core/Recovery.h>
#include <rtabmap/core/lidar/LidarVLP16.h>
#include <pcl/common/common.h>
#include <pcl/filters/extract_indices.h>
#include <pcl/io/ply_io.h>
@@ -82,6 +84,43 @@ static JavaVM *jvm;
static jobject RTABMapActivity = 0;
#endif
#ifdef __ANDROID__
#ifndef DISABLE_LOG
//ref: https://codelab.wordpress.com/2014/11/03/how-to-use-standard-output-streams-for-logging-in-android-apps/
static int pfd[2];
static pthread_t thr;
static void *thread_func(void*)
{
ssize_t rdsz;
char buf[128];
while((rdsz = read(pfd[0], buf, sizeof buf - 1)) > 0) {
if(buf[rdsz - 1] == '\n') --rdsz;
buf[rdsz] = 0; /* add null-terminator */
__android_log_write(ANDROID_LOG_DEBUG, LOG_TAG, buf);
}
return 0;
}
int start_logger()
{
/* make stdout line-buffered and stderr unbuffered */
setvbuf(stdout, 0, _IOLBF, 0);
setvbuf(stderr, 0, _IONBF, 0);
/* create the pipe and redirect stdout and stderr */
pipe(pfd);
dup2(pfd[1], 1);
dup2(pfd[1], 2);
/* spawn the logging thread */
if(pthread_create(&thr, 0, thread_func, 0) == -1)
return -1;
pthread_detach(thr);
return 0;
}
#endif
#endif
rtabmap::ParametersMap RTABMapApp::getRtabmapParameters()
{
rtabmap::ParametersMap parameters;
@@ -96,6 +135,7 @@ rtabmap::ParametersMap RTABMapApp::getRtabmapParameters()
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kRtabmapPublishLikelihood(), std::string("false")));
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kRtabmapPublishPdf(), std::string("false")));
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kRtabmapStartNewMapOnLoopClosure(), uBool2Str(!localizationMode_ && appendMode_)));
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kRGBDAggressiveLoopThr(), "0.0"));
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kMemBinDataKept(), uBool2Str(!trajectoryMode_)));
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kOptimizerIterations(), "10"));
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kMemIncrementalMemory(), uBool2Str(!localizationMode_)));
@@ -164,6 +204,7 @@ RTABMapApp::RTABMapApp() :
#endif
cameraDriver_(0),
camera_(0),
sensorCaptureThread_(0),
rtabmapThread_(0),
rtabmap_(0),
logHandler_(0),
@@ -178,6 +219,7 @@ RTABMapApp::RTABMapApp() :
cameraColor_(true),
fullResolution_(false),
appendMode_(true),
useExternalLidar_(false),
maxCloudDepth_(2.5),
minCloudDepth_(0.0),
cloudDensityLevel_(1),
@@ -243,6 +285,12 @@ RTABMapApp::RTABMapApp() :
this->registerToEventsManager();
LOGI("RTABMapApp::RTABMapApp() end");
#ifdef __ANDROID__
#ifndef DISABLE_LOG
start_logger();
#endif
#endif
}
#ifndef __ANDROID__ // __APPLE__
@@ -305,9 +353,9 @@ void RTABMapApp::setScreenRotation(int displayRotation, int cameraRotation)
}
}
int RTABMapApp::openDatabase(const std::string & databasePath, bool databaseInMemory, bool optimize, const std::string & databaseSource)
int RTABMapApp::openDatabase(const std::string & databasePath, bool databaseInMemory, bool optimize, bool clearDatabase)
{
LOGW("Opening database %s (inMemory=%d, optimize=%d)", databasePath.c_str(), databaseInMemory?1:0, optimize?1:0);
LOGW("Opening database %s (inMemory=%d, optimize=%d, clearDatabase=%d)", databasePath.c_str(), databaseInMemory?1:0, optimize?1:0, clearDatabase?1:0);
this->unregisterFromEventsManager(); // to ignore published init events when closing rtabmap
status_.first = rtabmap::RtabmapEventInit::kInitializing;
rtabmapMutex_.lock();
@@ -360,11 +408,11 @@ int RTABMapApp::openDatabase(const std::string & databasePath, bool databaseInMe
std::vector<std::vector<Eigen::Vector2f> > texCoords;
#endif
cv::Mat textures;
if(!databaseSource.empty())
if(!databasePath.empty() && UFile::exists(databasePath) && !clearDatabase)
{
UEventsManager::post(new rtabmap::RtabmapEventInit(rtabmap::RtabmapEventInit::kInfo, "Loading optimized cloud/mesh..."));
rtabmap::DBDriver * driver = rtabmap::DBDriver::create();
if(driver->openConnection(databaseSource))
if(driver->openConnection(databasePath))
{
cloudMat = driver->loadOptimizedMesh(&polygons, &texCoords, &textures);
if(!cloudMat.empty())
@@ -416,13 +464,11 @@ int RTABMapApp::openDatabase(const std::string & databasePath, bool databaseInMe
}
UEventsManager::post(new rtabmap::RtabmapEventInit(rtabmap::RtabmapEventInit::kInfo, "Loading database..."));
LOGI("Erasing database \"%s\"...", databasePath.c_str());
UFile::erase(databasePath);
if(!databaseSource.empty())
{
LOGI("Copying database source \"%s\" to \"%s\"...", databaseSource.c_str(), databasePath.c_str());
UFile::copy(databaseSource, databasePath);
}
if(clearDatabase)
{
LOGI("Erasing database \"%s\"...", databasePath.c_str());
UFile::erase(databasePath);
}
//Rtabmap
mapToOdom_.setIdentity();
@@ -448,7 +494,7 @@ int RTABMapApp::openDatabase(const std::string & databasePath, bool databaseInMe
poses,
links,
true,
true,
false, // Make sure poses are the same than optimized mesh (in case we switched RGBD/OptimizedFromGraphEnd)
&signatures,
true,
true,
@@ -495,7 +541,7 @@ int RTABMapApp::openDatabase(const std::string & databasePath, bool databaseInMe
// Voxelize and filter depending on the previous cloud?
pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud;
pcl::IndicesPtr indices(new std::vector<int>);
if(!data.imageRaw().empty() && !data.depthRaw().empty())
if(!data.imageRaw().empty() && !data.depthRaw().empty() && (!useExternalLidar_ || data.laserScanRaw().isEmpty()))
{
int meshDecimation = updateMeshDecimation(data.depthRaw().cols, data.depthRaw().rows);
@@ -593,7 +639,7 @@ int RTABMapApp::openDatabase(const std::string & databasePath, bool databaseInMe
if(renderingTextureDecimation_>1)
{
cv::Size reducedSize(data.imageRaw().cols/renderingTextureDecimation_, data.imageRaw().rows/renderingTextureDecimation_);
cv::resize(data.imageRaw(), inserted.first->second.texture, reducedSize, 0, 0, CV_INTER_LINEAR);
cv::resize(data.imageRaw(), inserted.first->second.texture, reducedSize, 0, 0, cv::INTER_LINEAR);
}
else
{
@@ -607,9 +653,9 @@ int RTABMapApp::openDatabase(const std::string & databasePath, bool databaseInMe
UWARN("Cloud %d is empty", id);
}
}
else
else if(!data.depthOrRightCompressed().empty() || !data.laserScanCompressed().isEmpty())
{
UERROR("Failed to uncompress data!");
UERROR("Failed to uncompress data! (rgb=%d, depth=%d, scan=%d)", data.imageCompressed().cols, data.depthOrRightCompressed().cols, data.laserScanCompressed().size());
status=-2;
}
}
@@ -843,7 +889,7 @@ bool RTABMapApp::startCamera()
#endif
LOGW("startCamera() camera driver=%d", cameraDriver_);
boost::mutex::scoped_lock lock(cameraMutex_);
if(cameraDriver_ == 0) // Tango
{
#ifdef RTABMAP_TANGO
@@ -895,6 +941,19 @@ bool RTABMapApp::startCamera()
LOGI("Start camera thread");
cameraJustInitialized_ = true;
if(useExternalLidar_)
{
rtabmap::LidarVLP16 * lidar = new rtabmap::LidarVLP16(boost::asio::ip::address_v4::from_string("192.168.1.201"), 2368, true);
lidar->init();
camera_->setImageRate(0); // if lidar, to get close camera synchronization
sensorCaptureThread_ = new rtabmap::SensorCaptureThread(lidar, camera_, camera_, rtabmap::Transform::getIdentity());
sensorCaptureThread_->setScanParameters(false, 1, 0.0f, 0.0f, 0.0f, 0, 0.0f, 0.0f, true);
}
else
{
sensorCaptureThread_ = new rtabmap::SensorCaptureThread(camera_);
}
sensorCaptureThread_->start();
return true;
}
UERROR("Failed camera initialization!");
@@ -906,13 +965,12 @@ void RTABMapApp::stopCamera()
LOGI("stopCamera()");
{
boost::mutex::scoped_lock lock(cameraMutex_);
if(camera_!=0)
if(sensorCaptureThread_!=0)
{
camera_->join(true);
camera_->close();
delete camera_;
sensorCaptureThread_->join(true);
delete sensorCaptureThread_; // camera_ is closed and deleted inside
sensorCaptureThread_ = 0;
camera_ = 0;
poseBuffer_.clear();
}
}
{
@@ -1199,7 +1257,12 @@ int RTABMapApp::Render()
std::list<rtabmap::RtabmapEvent*> rtabmapEvents;
try
{
UTimer fpsTime;
if(sensorCaptureThread_ == 0)
{
// We are not doing continous drawing, just measure single draw
fpsTime_.restart();
}
#ifdef DEBUG_RENDERING_PERFORMANCE
UTimer time;
#endif
@@ -1225,49 +1288,45 @@ int RTABMapApp::Render()
{
if(cameraDriver_ <= 2)
{
camera_->spinOnce();
camera_->updateOnRender();
}
#ifdef DEBUG_RENDERING_PERFORMANCE
LOGW("Camera spinOnce %fs", time.ticks());
LOGW("Camera updateOnRender %fs", time.ticks());
#endif
if(cameraDriver_ != 2)
if(main_scene_.background_renderer_ == 0 && camera_->getTextureId() != 0)
{
if(main_scene_.background_renderer_ == 0 && camera_->getTextureId() != 0)
main_scene_.background_renderer_ = new BackgroundRenderer();
main_scene_.background_renderer_->InitializeGlContent(((rtabmap::CameraMobile*)camera_)->getTextureId(), cameraDriver_ <= 2);
}
if(camera_->uvsInitialized())
{
uvsTransformed = ((rtabmap::CameraMobile*)camera_)->uvsTransformed();
((rtabmap::CameraMobile*)camera_)->getVPMatrices(arViewMatrix, arProjectionMatrix);
if(graphOptimization_ && !mapToOdom_.isIdentity())
{
main_scene_.background_renderer_ = new BackgroundRenderer();
main_scene_.background_renderer_->InitializeGlContent(((rtabmap::CameraMobile*)camera_)->getTextureId(), cameraDriver_ == 0 || cameraDriver_ == 1);
rtabmap::Transform mapCorrection = rtabmap::opengl_world_T_rtabmap_world * mapToOdom_ *rtabmap::rtabmap_world_T_opengl_world;
arViewMatrix = glm::inverse(rtabmap::glmFromTransform(mapCorrection)*glm::inverse(arViewMatrix));
}
if(camera_->uvsInitialized())
{
uvsTransformed = ((rtabmap::CameraMobile*)camera_)->uvsTransformed();
((rtabmap::CameraMobile*)camera_)->getVPMatrices(arViewMatrix, arProjectionMatrix);
if(graphOptimization_ && !mapToOdom_.isIdentity())
{
rtabmap::Transform mapCorrection = rtabmap::opengl_world_T_rtabmap_world * mapToOdom_ *rtabmap::rtabmap_world_T_opengl_world;
arViewMatrix = glm::inverse(rtabmap::glmFromTransform(mapCorrection)*glm::inverse(arViewMatrix));
}
}
if(!visualizingMesh_ && main_scene_.GetCameraType() == tango_gl::GestureCamera::kFirstPerson)
{
rtabmap::CameraModel occlusionModel;
cv::Mat occlusionImage = ((rtabmap::CameraMobile*)camera_)->getOcclusionImage(&occlusionModel);
}
if(!visualizingMesh_ && main_scene_.GetCameraType() == tango_gl::GestureCamera::kFirstPerson)
{
rtabmap::CameraModel occlusionModel;
cv::Mat occlusionImage = ((rtabmap::CameraMobile*)camera_)->getOcclusionImage(&occlusionModel);
if(occlusionModel.isValidForProjection())
{
pcl::IndicesPtr indices(new std::vector<int>);
int meshDecimation = updateMeshDecimation(occlusionImage.cols, occlusionImage.rows);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud = rtabmap::util3d::cloudFromDepth(occlusionImage, occlusionModel, meshDecimation, 0, 0, indices.get());
cloud = rtabmap::util3d::transformPointCloud(cloud, rtabmap::opengl_world_T_rtabmap_world*mapToOdom_*occlusionModel.localTransform());
occlusionMesh.cloud.reset(new pcl::PointCloud<pcl::PointXYZRGB>());
pcl::copyPointCloud(*cloud, *occlusionMesh.cloud);
occlusionMesh.indices = indices;
occlusionMesh.polygons = rtabmap::util3d::organizedFastMesh(cloud, 1.0*M_PI/180.0, false, meshTrianglePix_);
}
else if(!occlusionImage.empty())
{
UERROR("invalid occlusionModel: %f %f %f %f %dx%d", occlusionModel.fx(), occlusionModel.fy(), occlusionModel.cx(), occlusionModel.cy(), occlusionModel.imageWidth(), occlusionModel.imageHeight());
}
if(occlusionModel.isValidForProjection())
{
pcl::IndicesPtr indices(new std::vector<int>);
int meshDecimation = updateMeshDecimation(occlusionImage.cols, occlusionImage.rows);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud = rtabmap::util3d::cloudFromDepth(occlusionImage, occlusionModel, meshDecimation, 0, 0, indices.get());
cloud = rtabmap::util3d::transformPointCloud(cloud, rtabmap::opengl_world_T_rtabmap_world*mapToOdom_*occlusionModel.localTransform());
occlusionMesh.cloud.reset(new pcl::PointCloud<pcl::PointXYZRGB>());
pcl::copyPointCloud(*cloud, *occlusionMesh.cloud);
occlusionMesh.indices = indices;
occlusionMesh.polygons = rtabmap::util3d::organizedFastMesh(cloud, 1.0*M_PI/180.0, false, meshTrianglePix_);
}
else if(!occlusionImage.empty())
{
UERROR("invalid occlusionModel: %f %f %f %f %dx%d", occlusionModel.fx(), occlusionModel.fy(), occlusionModel.cx(), occlusionModel.cy(), occlusionModel.imageWidth(), occlusionModel.imageHeight());
}
}
#ifdef DEBUG_RENDERING_PERFORMANCE
@@ -1287,14 +1346,14 @@ int RTABMapApp::Render()
}
}
rtabmap::OdometryEvent odomEvent;
rtabmap::SensorEvent sensorEvent;
{
boost::mutex::scoped_lock lock(odomMutex_);
if(odomEvents_.size())
boost::mutex::scoped_lock lock(sensorMutex_);
if(sensorEvents_.size())
{
LOGI("Process odom events");
odomEvent = odomEvents_.back();
odomEvents_.clear();
LOGI("Process sensor events");
sensorEvent = sensorEvents_.back();
sensorEvents_.clear();
if(cameraJustInitialized_)
{
notifyCameraStarted = true;
@@ -1314,7 +1373,7 @@ int RTABMapApp::Render()
{
main_scene_.SetCameraPose(rtabmap::opengl_world_T_rtabmap_world*pose*rtabmap::optical_T_opengl);
}
if(camera_!=0 && cameraJustInitialized_)
if(sensorCaptureThread_!=0 && cameraJustInitialized_)
{
notifyCameraStarted = true;
cameraJustInitialized_ = false;
@@ -1399,7 +1458,14 @@ int RTABMapApp::Render()
}
else if(rtabmapThread_ && rtabmapThread_->isRunning() && landmark!=0)
{
main_scene_.setBackgroundColor(1, 0.65f, 0); // orange
if(rejected)
{
main_scene_.setBackgroundColor(0.5, 0.325f, 0); // dark orange
}
else
{
main_scene_.setBackgroundColor(1, 0.65f, 0); // orange
}
}
else if(rtabmapThread_ && rtabmapThread_->isRunning() && rejected>0)
{
@@ -1439,12 +1505,12 @@ int RTABMapApp::Render()
main_scene_.setMeshRendering(main_scene_.hasMesh(g_optMeshId), main_scene_.hasTexture(g_optMeshId));
fpsTime.restart();
main_scene_.setFrustumVisible(camera_!=0);
lastDrawnCloudsCount_ = main_scene_.Render(uvsTransformed, arViewMatrix, arProjectionMatrix);
if(renderingTime_ < fpsTime.elapsed())
double fpsTime = fpsTime_.ticks();
if(renderingTime_ < fpsTime)
{
renderingTime_ = fpsTime.elapsed();
renderingTime_ = fpsTime;
}
// revert state
@@ -1508,9 +1574,9 @@ int RTABMapApp::Render()
if(clearSceneOnNextRender_)
{
LOGI("Clearing all rendering data...");
odomMutex_.lock();
odomEvents_.clear();
odomMutex_.unlock();
sensorMutex_.lock();
sensorEvents_.clear();
sensorMutex_.unlock();
poseMutex_.lock();
poseEvents_.clear();
@@ -1571,7 +1637,7 @@ int RTABMapApp::Render()
{
cv::Size reducedSize(textureRaw.cols/renderingTextureDecimation_, textureRaw.rows/renderingTextureDecimation_);
LOGD("resize image from %dx%d to %dx%d", textureRaw.cols, textureRaw.rows, reducedSize.width, reducedSize.height);
cv::resize(textureRaw, iter->second.texture, reducedSize, 0, 0, CV_INTER_LINEAR);
cv::resize(textureRaw, iter->second.texture, reducedSize, 0, 0, cv::INTER_LINEAR);
}
else
{
@@ -1746,7 +1812,7 @@ int RTABMapApp::Render()
// Voxelize and filter depending on the previous cloud?
pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud;
pcl::IndicesPtr indices(new std::vector<int>);
if(!data.imageRaw().empty() && !data.depthRaw().empty())
if(!data.imageRaw().empty() && !data.depthRaw().empty() && (!useExternalLidar_ || data.laserScanRaw().isEmpty()))
{
int meshDecimation = updateMeshDecimation(data.depthRaw().cols, data.depthRaw().rows);
cloud = rtabmap::util3d::cloudRGBFromSensorData(data, meshDecimation, maxCloudDepth_, minCloudDepth_, indices.get());
@@ -1856,7 +1922,7 @@ int RTABMapApp::Render()
if(renderingTextureDecimation_ > 1)
{
cv::Size reducedSize(data.imageRaw().cols/renderingTextureDecimation_, data.imageRaw().rows/renderingTextureDecimation_);
cv::resize(data.imageRaw(), inserted.first->second.texture, reducedSize, 0, 0, CV_INTER_LINEAR);
cv::resize(data.imageRaw(), inserted.first->second.texture, reducedSize, 0, 0, cv::INTER_LINEAR);
#ifdef DEBUG_RENDERING_PERFORMANCE
LOGW("resize image from %dx%d to %dx%d (%fs)", data.imageRaw().cols, data.imageRaw().rows, reducedSize.width, reducedSize.height, time.ticks());
#endif
@@ -1950,26 +2016,26 @@ int RTABMapApp::Render()
}
else
{
main_scene_.setCloudVisible(-1, odomCloudShown_ && !trajectoryMode_ && camera_!=0);
main_scene_.setCloudVisible(-1, odomCloudShown_ && !trajectoryMode_ && sensorCaptureThread_!=0);
//just process the last one
if(!odomEvent.pose().isNull())
if(!sensorEvent.info().odomPose.isNull())
{
if(odomCloudShown_ && !trajectoryMode_)
{
if((!odomEvent.data().imageRaw().empty() && !odomEvent.data().depthRaw().empty()) || !odomEvent.data().laserScanRaw().isEmpty())
if((!sensorEvent.data().imageRaw().empty() && !sensorEvent.data().depthRaw().empty()) || !sensorEvent.data().laserScanRaw().isEmpty())
{
pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud;
pcl::IndicesPtr indices(new std::vector<int>);
if((!odomEvent.data().imageRaw().empty() && !odomEvent.data().depthRaw().empty()))
if(!sensorEvent.data().imageRaw().empty() && !sensorEvent.data().depthRaw().empty() && (!useExternalLidar_ || sensorEvent.data().laserScanRaw().isEmpty()))
{
int meshDecimation = updateMeshDecimation(odomEvent.data().depthRaw().cols, odomEvent.data().depthRaw().rows);
cloud = rtabmap::util3d::cloudRGBFromSensorData(odomEvent.data(), meshDecimation, maxCloudDepth_, minCloudDepth_, indices.get());
int meshDecimation = updateMeshDecimation(sensorEvent.data().depthRaw().cols, sensorEvent.data().depthRaw().rows);
cloud = rtabmap::util3d::cloudRGBFromSensorData(sensorEvent.data(), meshDecimation, maxCloudDepth_, minCloudDepth_, indices.get());
}
else
{
//scan
cloud = rtabmap::util3d::laserScanToPointCloudRGB(rtabmap::util3d::commonFiltering(odomEvent.data().laserScanRaw(), 1, minCloudDepth_, maxCloudDepth_), odomEvent.data().laserScanRaw().localTransform(), 255, 255, 255);
cloud = rtabmap::util3d::laserScanToPointCloudRGB(rtabmap::util3d::commonFiltering(sensorEvent.data().laserScanRaw(), 1, minCloudDepth_, maxCloudDepth_), sensorEvent.data().laserScanRaw().localTransform(), 255, 255, 255);
indices->resize(cloud->size());
for(unsigned int i=0; i<cloud->size(); ++i)
{
@@ -1980,10 +2046,10 @@ int RTABMapApp::Render()
if(cloud->size() && indices->size())
{
LOGI("Created odom cloud (rgb=%dx%d depth=%dx%d cloud=%dx%d)",
odomEvent.data().imageRaw().cols, odomEvent.data().imageRaw().rows,
odomEvent.data().depthRaw().cols, odomEvent.data().depthRaw().rows,
sensorEvent.data().imageRaw().cols, sensorEvent.data().imageRaw().rows,
sensorEvent.data().depthRaw().cols, sensorEvent.data().depthRaw().rows,
(int)cloud->width, (int)cloud->height);
main_scene_.addCloud(-1, cloud, indices, rtabmap::opengl_world_T_rtabmap_world*mapToOdom_*odomEvent.pose());
main_scene_.addCloud(-1, cloud, indices, rtabmap::opengl_world_T_rtabmap_world*mapToOdom_*sensorEvent.info().odomPose);
main_scene_.setCloudVisible(-1, true);
}
else
@@ -2046,13 +2112,13 @@ int RTABMapApp::Render()
notifyDataLoaded = true;
}
fpsTime.restart();
main_scene_.setFrustumVisible(camera_!=0);
main_scene_.setFrustumVisible(camera_!=0);
lastDrawnCloudsCount_ = main_scene_.Render(uvsTransformed, arViewMatrix, arProjectionMatrix, occlusionMesh, true);
if(renderingTime_ < fpsTime.elapsed())
double fpsTime = fpsTime_.ticks();
if(renderingTime_ < fpsTime)
{
renderingTime_ = fpsTime.elapsed();
}
renderingTime_ = fpsTime;
}
if(rtabmapEvents.size())
{
@@ -2073,10 +2139,10 @@ int RTABMapApp::Render()
lastPostRenderEventTime_ = UTimer::now();
if(camera_!=0 && lastPoseEventTime_>0.0 && UTimer::now()-lastPoseEventTime_ > 1.0)
if(sensorCaptureThread_!=0 && lastPoseEventTime_>0.0 && UTimer::now()-lastPoseEventTime_ > 1.0)
{
UERROR("TangoPoseEventNotReceived");
UEventsManager::post(new rtabmap::CameraInfoEvent(10, "TangoPoseEventNotReceived", uNumber2Str(UTimer::now()-lastPoseEventTime_)));
UEventsManager::post(new rtabmap::CameraInfoEvent(10, "TangoPoseEventNotReceived", uNumber2Str(UTimer::now()-lastPoseEventTime_, 6)));
}
}
}
@@ -2089,7 +2155,7 @@ int RTABMapApp::Render()
cv::Mat image(h, w, CV_8UC4);
glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, image.data);
cv::flip(image, image, 0);
cv::cvtColor(image, image, CV_RGBA2BGRA);
cv::cvtColor(image, image, cv::COLOR_RGBA2BGRA);
cv::Mat roi;
if(w>h)
{
@@ -2108,16 +2174,6 @@ int RTABMapApp::Render()
screenshotReady_.release();
}
if((openingDatabase_ && !visualizingMesh_) || exporting_ || postProcessing_)
{
// throttle rendering max 5Hz if we are doing some processing
double renderTime = fpsTime.elapsed();
if(0.2 - renderTime > 0.0)
{
uSleep((0.2 - renderTime)*1000);
}
}
if((rtabmapThread_==0 || !rtabmapThread_->isRunning()) && lastPostRenderEventTime_ > 0.0)
{
double interval = UTimer::now() - lastPostRenderEventTime_;
@@ -2275,7 +2331,7 @@ void RTABMapApp::setTrajectoryMode(bool enabled)
void RTABMapApp::setGraphOptimization(bool enabled)
{
graphOptimization_ = enabled;
if((camera_ == 0) && rtabmap_ && rtabmap_->getMemory()->getLastWorkingSignature()!=0)
if((sensorCaptureThread_ == 0) && rtabmap_ && rtabmap_->getMemory()->getLastWorkingSignature()!=0)
{
std::map<int, rtabmap::Transform> poses;
std::multimap<int, rtabmap::Link> links;
@@ -2550,6 +2606,26 @@ void RTABMapApp::save(const std::string & databasePath)
}
}
bool RTABMapApp::recover(const std::string & from, const std::string & to)
{
std::string errorMsg;
if(!databaseRecovery(from, false, &errorMsg, &progressionStatus_))
{
LOGE("Recovery Error: %s", errorMsg.c_str());
return false;
}
else
{
LOGI("Renaming %s to %s", from.c_str(), to.c_str());
if(UFile::rename(from, to) != 0)
{
LOGE("Failed renaming %s to %s", from.c_str(), to.c_str());
return false;
}
return true;
}
}
void RTABMapApp::cancelProcessing()
{
UWARN("Processing canceled!");
@@ -3645,19 +3721,12 @@ void RTABMapApp::postCameraPoseEvent(
if(qx==0 && qy==0 && qz==0 && qw==0)
{
// Lost! clear buffer
poseBuffer_.clear();
camera_->resetOrigin(); // we are lost, create new session on next valid frame
return;
}
rtabmap::Transform pose(x,y,z,qx,qy,qz,qw);
pose = rtabmap::rtabmap_world_T_opengl_world * pose * rtabmap::opengl_world_T_rtabmap_world;
camera_->poseReceived(pose);
poseBuffer_.insert(std::make_pair(stamp, pose));
if(poseBuffer_.size() > 1000)
{
poseBuffer_.erase(poseBuffer_.begin());
}
camera_->poseReceived(pose, stamp);
}
}
@@ -3704,14 +3773,14 @@ void RTABMapApp::postOdometryEvent(
cv::Mat yuv(rgbHeight+rgbHeight/2, rgbWidth, CV_8UC1);
memcpy(yuv.data, yPlane, yPlaneLen);
memcpy(yuv.data+yPlaneLen, vPlane, rgbHeight/2*rgbWidth);
cv::cvtColor(yuv, outputRGB, CV_YUV2BGR_NV21);
cv::cvtColor(yuv, outputRGB, cv::COLOR_YUV2BGR_NV21);
}
else
{
#ifdef __ANDROID__
cv::cvtColor(cv::Mat(rgbHeight+rgbHeight/2, rgbWidth, CV_8UC1, (void*)yPlane), outputRGB, CV_YUV2BGR_NV21);
cv::cvtColor(cv::Mat(rgbHeight+rgbHeight/2, rgbWidth, CV_8UC1, (void*)yPlane), outputRGB, cv::COLOR_YUV2BGR_NV21);
#else // __APPLE__
cv::cvtColor(cv::Mat(rgbHeight+rgbHeight/2, rgbWidth, CV_8UC1, (void*)yPlane), outputRGB, CV_YUV2RGB_NV21);
cv::cvtColor(cv::Mat(rgbHeight+rgbHeight/2, rgbWidth, CV_8UC1, (void*)yPlane), outputRGB, cv::COLOR_YUV2RGB_NV21);
#endif
}
@@ -3769,66 +3838,41 @@ void RTABMapApp::postOdometryEvent(
{
pose = rtabmap::rtabmap_world_T_opengl_world * pose * rtabmap::opengl_world_T_rtabmap_world;
rtabmap::Transform poseWithOriginOffset = pose;
if(!camera_->getOriginOffset().isNull())
{
poseWithOriginOffset = camera_->getOriginOffset() * pose;
}
// Registration depth to rgb
if(!outputDepth.empty() && !depthFrame.isNull() && depth_fx!=0 && (rgbFrame != depthFrame || depthStamp!=stamp))
{
UTimer time;
rtabmap::Transform motion = rtabmap::Transform::getIdentity();
if(depthStamp != stamp && !poseBuffer_.empty())
if(depthStamp != stamp)
{
// Interpolate pose
if(!poseBuffer_.empty())
rtabmap::Transform poseDepth;
cv::Mat cov;
if(!camera_->getPose(camera_->getStampEpochOffset()+depthStamp, poseDepth, cov, 0.0))
{
UERROR("Could not find pose at depth stamp %f (epoch=%f rgb=%f)!", depthStamp, camera_->getStampEpochOffset()+depthStamp, stamp);
}
else
{
if(poseBuffer_.rbegin()->first < depthStamp)
{
UWARN("Could not find poses to interpolate at time %f (last is %f)...", depthStamp, poseBuffer_.rbegin()->first);
}
else
{
std::map<double, rtabmap::Transform >::const_iterator iterB = poseBuffer_.lower_bound(depthStamp);
std::map<double, rtabmap::Transform >::const_iterator iterA = iterB;
rtabmap::Transform poseDepth;
if(iterA != poseBuffer_.begin())
{
iterA = --iterA;
}
if(iterB == poseBuffer_.end())
{
iterB = --iterB;
}
if(iterA == iterB && depthStamp == iterA->first)
{
poseDepth = iterA->second;
}
else if(depthStamp >= iterA->first && depthStamp <= iterB->first)
{
poseDepth = iterA->second.interpolate((depthStamp-iterA->first) / (iterB->first-iterA->first), iterB->second);
}
else if(depthStamp < iterA->first)
{
UERROR("Could not find poses to interpolate at image time %f (earliest is %f). Are sensors synchronized?", depthStamp, iterA->first);
}
else
{
UERROR("Could not find poses to interpolate at image time %f (between %f and %f), Are sensors synchronized?", depthStamp, iterA->first, iterB->first);
}
if(!poseDepth.isNull())
{
#ifndef DISABLE_LOG
UDEBUG("poseRGB =%s (stamp=%f)", pose.prettyPrint().c_str(), depthStamp);
UDEBUG("poseDepth=%s (stamp=%f)", poseDepth.prettyPrint().c_str(), depthStamp);
UDEBUG("poseRGB =%s (stamp=%f)", poseWithOriginOffset.prettyPrint().c_str(), stamp);
UDEBUG("poseDepth=%s (stamp=%f)", poseDepth.prettyPrint().c_str(), depthStamp);
#endif
motion = pose.inverse()*poseDepth;
// transform in camera frame
motion = poseWithOriginOffset.inverse()*poseDepth;
// transform in camera frame
#ifndef DISABLE_LOG
UDEBUG("motion=%s", motion.prettyPrint().c_str());
UDEBUG("motion=%s", motion.prettyPrint().c_str());
#endif
motion = rtabmap::CameraModel::opticalRotation().inverse() * motion * rtabmap::CameraModel::opticalRotation();
motion = rtabmap::CameraModel::opticalRotation().inverse() * motion * rtabmap::CameraModel::opticalRotation();
#ifndef DISABLE_LOG
UDEBUG("motion=%s", motion.prettyPrint().c_str());
UDEBUG("motion=%s", motion.prettyPrint().c_str());
#endif
}
}
}
}
rtabmap::Transform rgbToDepth = motion*rgbFrame.inverse()*depthFrame;
@@ -3877,11 +3921,6 @@ void RTABMapApp::postOdometryEvent(
if(!outputDepth.empty())
{
rtabmap::Transform poseWithOriginOffset = pose;
if(!camera_->getOriginOffset().isNull())
{
poseWithOriginOffset = camera_->getOriginOffset() * pose;
}
rtabmap::CameraModel depthModel = model.scaled(float(outputDepth.cols) / float(model.imageWidth()));
depthModel.setLocalTransform(poseWithOriginOffset*model.localTransform());
camera_->setOcclusionImage(outputDepth, depthModel);
@@ -3907,8 +3946,7 @@ void RTABMapApp::postOdometryEvent(
texCoords[5] = t5;
texCoords[6] = t6;
texCoords[7] = t7;
camera_->setData(data, pose, viewMatrixMat, projectionMatrix, main_scene_.GetCameraType() == tango_gl::GestureCamera::kFirstPerson?texCoords:0);
camera_->spinOnce();
camera_->update(data, pose, viewMatrixMat, projectionMatrix, main_scene_.GetCameraType() == tango_gl::GestureCamera::kFirstPerson?texCoords:0);
}
}
}
@@ -3925,17 +3963,17 @@ void RTABMapApp::postOdometryEvent(
bool RTABMapApp::handleEvent(UEvent * event)
{
if(camera_!=0)
if(sensorCaptureThread_!=0)
{
// called from events manager thread, so protect the data
if(event->getClassName().compare("OdometryEvent") == 0)
if(event->getClassName().compare("SensorEvent") == 0)
{
LOGI("Received OdometryEvent!");
if(odomMutex_.try_lock())
LOGI("Received SensorEvent!");
if(sensorMutex_.try_lock())
{
odomEvents_.clear();
odomEvents_.push_back(*((rtabmap::OdometryEvent*)(event)));
odomMutex_.unlock();
sensorEvents_.clear();
sensorEvents_.push_back(*((rtabmap::SensorEvent*)(event)));
sensorMutex_.unlock();
}
}
if(event->getClassName().compare("RtabmapEvent") == 0)

View File

@@ -40,7 +40,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "util.h"
#include "ProgressionStatus.h"
#include <rtabmap/core/SensorCaptureThread.h>
#include <rtabmap/core/RtabmapThread.h>
#include <rtabmap/core/SensorEvent.h>
#include <rtabmap/utilite/UEventsHandler.h>
#include <boost/thread/mutex.hpp>
#include <pcl/pcl_base.h>
@@ -75,7 +77,7 @@ class RTABMapApp : public UEventsHandler {
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__
@@ -153,6 +155,7 @@ class RTABMapApp : public UEventsHandler {
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,
@@ -208,6 +211,7 @@ class RTABMapApp : public UEventsHandler {
private:
int cameraDriver_;
rtabmap::CameraMobile * camera_;
rtabmap::SensorCaptureThread * sensorCaptureThread_;
rtabmap::RtabmapThread * rtabmapThread_;
rtabmap::Rtabmap * rtabmap_;
rtabmap::LogHandler * logHandler_;
@@ -223,6 +227,7 @@ class RTABMapApp : public UEventsHandler {
bool cameraColor_;
bool fullResolution_;
bool appendMode_;
bool useExternalLidar_;
float maxCloudDepth_;
float minCloudDepth_;
int cloudDensityLevel_;
@@ -265,18 +270,19 @@ 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::SensorEvent> sensorEvents_;
std::list<rtabmap::Transform> poseEvents_;
std::map<double, rtabmap::Transform> poseBuffer_;
rtabmap::Transform mapToOdom_;
boost::mutex cameraMutex_;
boost::mutex rtabmapMutex_;
boost::mutex meshesMutex_;
boost::mutex odomMutex_;
boost::mutex sensorMutex_;
boost::mutex poseMutex_;
boost::mutex renderingMutex_;

View File

@@ -155,7 +155,7 @@ void BackgroundRenderer::InitializeGlContent(GLuint textureId, bool oes)
}
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");
static_assert(std::extent<decltype(BackgroundRenderer_kVerticesDevice)>::value == kNumVertices * 2, "Incorrect kVertices length");
GLuint program = shaderPrograms_[depthTexture>0?1:0];
@@ -170,7 +170,7 @@ void BackgroundRenderer::Draw(const float * transformed_uvs, const GLuint & dept
else
#endif
glBindTexture(GL_TEXTURE_2D, texture_id_);
if(depthTexture>0)
{
// Texture activate unit 1
@@ -191,7 +191,7 @@ void BackgroundRenderer::Draw(const float * transformed_uvs, const GLuint & dept
GLuint attributeVertices = glGetAttribLocation(program, "a_Position");
GLuint attributeUvs = glGetAttribLocation(program, "a_TexCoord");
glVertexAttribPointer(attributeVertices, 2, GL_FLOAT, GL_FALSE, 0, BackgroundRenderer_kVertices);
glVertexAttribPointer(attributeVertices, 2, GL_FLOAT, GL_FALSE, 0, BackgroundRenderer_kVerticesDevice);
glVertexAttribPointer(attributeUvs, 2, GL_FLOAT, GL_FALSE, 0, transformed_uvs?transformed_uvs:BackgroundRenderer_kTexCoord);
glEnableVertexAttribArray(attributeVertices);

View File

@@ -28,9 +28,15 @@
#include "util.h"
static const GLfloat BackgroundRenderer_kVertices[] = {
static const GLfloat BackgroundRenderer_kVerticesDevice[] = {
-1.0f, -1.0f, +1.0f, -1.0f, -1.0f, +1.0f, +1.0f, +1.0f,
};
//static const GLfloat BackgroundRenderer_kVerticesView[] = {
// 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f,
//};
static const GLfloat BackgroundRenderer_kVerticesView[] = {
0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
};
static const GLfloat BackgroundRenderer_kTexCoord[] = {
1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
};

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
{

View File

@@ -309,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),
@@ -320,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),
@@ -337,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)
{
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");
polygons_.clear();
polygonLines_.clear();
polygonsLowRes_.clear();
polygonLinesLowRes_.clear();
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)
@@ -402,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;
}
}
}
}
}
@@ -418,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)
@@ -471,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)
@@ -504,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);
@@ -524,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)
@@ -538,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];
@@ -552,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;
@@ -570,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;
}
@@ -591,11 +688,13 @@ void PointCloudDrawable::updateMesh(const rtabmap::Mesh & mesh, bool createWiref
polygonsLowRes = mesh.polygonsLowRes; // only in organized we keep the low res
organizedToDenseIndices_ = std::vector<unsigned int>(mesh.cloud->width*mesh.cloud->height, -1);
totalPoints = (int)mesh.indices->size();
verticesLowRes_.resize(totalPoints);
verticesLowLowRes_.resize(totalPoints);
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);
@@ -628,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;
}
}
}
@@ -663,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())
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);
@@ -743,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);
@@ -771,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);
@@ -779,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);
@@ -793,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);
@@ -811,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())
{
@@ -886,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;
}
@@ -996,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);
@@ -1012,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)
@@ -1044,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
{
@@ -1106,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

@@ -70,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_;}
@@ -115,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

@@ -102,7 +102,7 @@ Scene::Scene() :
screenHeight_(0),
doubleTapOn_(false)
{
depthTextures_[0] = depthTextures_[1] = 0;
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(2, depthTextures_);
depthTextures_[0] = depthTextures_[1] = 0;
glDeleteTextures(1, &depthTexture_);
depthTexture_ = 0;
}
clear();
@@ -234,8 +234,8 @@ void Scene::SetupViewPort(int w, int h) {
fboId_ = 0;
glDeleteRenderbuffers(1, &rboId_);
rboId_ = 0;
glDeleteTextures(2, depthTextures_);
depthTextures_[0] = depthTextures_[1] = 0;
glDeleteTextures(1, &depthTexture_);
depthTexture_ = 0;
}
GLint originid = 0;
@@ -247,8 +247,8 @@ void Scene::SetupViewPort(int w, int h) {
glBindFramebuffer(GL_FRAMEBUFFER, fboId_);
// Create depth texture
glGenTextures(2, depthTextures_);
glBindTexture(GL_TEXTURE_2D, depthTextures_[0]);
glGenTextures(1, &depthTexture_);
glBindTexture(GL_TEXTURE_2D, depthTexture_);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
@@ -256,21 +256,13 @@ void Scene::SetupViewPort(int w, int h) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glBindTexture(GL_TEXTURE_2D, 0);
glBindTexture(GL_TEXTURE_2D, depthTextures_[1]);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
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);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
// Set the texture to be at the color attachment point of the FBO (we pack depth 32 bits in color)
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, depthTextures_[0], 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, depthTexture_, 0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rboId_);
GLuint status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
@@ -349,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(
@@ -389,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, bool mapping) {
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)
@@ -428,7 +422,7 @@ int Scene::Render(const float * uvsTransformed, glm::mat4 arViewMatrix, glm::mat
if(renderBackgroundCamera)
{
if(projectionMatrix[0][0] > arProjectionMatrix[0][0]-0.2)
if(projectionMatrix[0][0] > arProjectionMatrix[0][0]-0.3)
{
projectionMatrix = arProjectionMatrix;
viewMatrix = arViewMatrix;
@@ -486,9 +480,15 @@ 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 = (!meshRendering_ && occlusionMesh.cloud.get() && occlusionMesh.cloud->size()) || (blending_ && gesture_camera_->GetCameraType()!=tango_gl::GestureCamera::kTopOrtho && mapRendering_ && meshRendering_);
if(onlineBlending && fboId_)
{
GLint originid = 0;
@@ -499,7 +499,7 @@ 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);
// Draw scene
for(std::vector<PointCloudDrawable*>::const_iterator iter=cloudsToDraw.begin(); iter!=cloudsToDraw.end(); ++iter)
{
@@ -511,16 +511,12 @@ int Scene::Render(const float * uvsTransformed, glm::mat4 arViewMatrix, glm::mat
(*iter)->Render(projectionMatrix, viewMatrix, meshRendering_, pointSize_, false, false, distanceToCameraSqr, 0, 0, 0, 0, 0, true);
}
glBindTexture(GL_TEXTURE_2D, depthTextures_[1]);
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, screenWidth_, screenHeight_);
glBindTexture(GL_TEXTURE_2D, 0);
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, originid); // unbind
}
@@ -559,7 +555,7 @@ 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)
if(renderBackgroundCamera && (!onlineBlending || !meshRendering_))
{
background_renderer_->Draw(uvsTransformed, 0, screenWidth_, screenHeight_, false);
@@ -594,6 +590,10 @@ int Scene::Render(const float * uvsTransformed, glm::mat4 arViewMatrix, glm::mat
{
trace_->Render(projectionMatrix, viewMatrix);
}
else
{
trace_->ClearVertexArray();
}
}
if(gridVisible_ && !renderBackgroundCamera)
@@ -629,14 +629,14 @@ int Scene::Render(const float * uvsTransformed, glm::mat4 arViewMatrix, glm::mat
cloud->getPose().z() - openglCamera.z());
float distanceToCameraSqr = cloudToCamera[0]*cloudToCamera[0] + cloudToCamera[1]*cloudToCamera[1] + cloudToCamera[2]*cloudToCamera[2];
cloud->Render(projectionMatrix, viewMatrix, meshRendering_, pointSize_, meshRenderingTexture_, lighting_, distanceToCameraSqr, onlineBlending?depthTextures_[0]:0, screenWidth_, screenHeight_, gesture_camera_->getNearClipPlane(), gesture_camera_->getFarClipPlane(), false, wireFrame_);
cloud->Render(projectionMatrix, viewMatrix, meshRendering_, pointSize_, meshRenderingTexture_, lighting_, distanceToCameraSqr, onlineBlending?depthTexture_:0, screenWidth_, screenHeight_, gesture_camera_->getNearClipPlane(), gesture_camera_->getFarClipPlane(), false, wireFrame_);
}
if(onlineBlending)
{
if(renderBackgroundCamera)
if(renderBackgroundCamera && meshRendering_)
{
background_renderer_->Draw(uvsTransformed, depthTextures_[1], screenWidth_, screenHeight_, meshRendering_?mapping:false);
background_renderer_->Draw(uvsTransformed, depthTexture_, screenWidth_, screenHeight_, mapping);
}
glDisable (GL_BLEND);

View File

@@ -208,7 +208,7 @@ class Scene {
float b_;
GLuint fboId_;
GLuint rboId_;
GLuint depthTextures_[2]; // 0=objects+occlusion 1=objects only
GLuint depthTexture_; // 0=objects+occlusion
GLsizei screenWidth_;
GLsizei screenHeight_;
bool doubleTapOn_;

View File

@@ -183,7 +183,7 @@ void GestureCamera::SetCameraType(CameraType camera_index) {
case kFirstPerson:
SetOrthoMode(false);
SetFieldOfView(kLowestFov);
SetNearFarClipPlanes(0.1, 50);
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;

View File

@@ -1 +1,4 @@
*.jar
# Ignore everything in this directory
*
# Except this file
!.gitignore

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>
@@ -80,11 +80,11 @@
<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_default_arcore_localization_filtering_speed">0</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>
@@ -108,7 +108,7 @@
<string name="pref_key_features_type">pref_key_features_type</string>
<string name="pref_default_features_type">6</string>
<string name="pref_key_optimizer">pref_key_optimizer</string>
<string name="pref_default_optimizer">1</string>
<string name="pref_default_optimizer">2</string>
<string name="pref_key_optimize_end">pref_key_optimize_end</string>
<string name="pref_default_optimize_end">true</string>
<string name="pref_key_marker_detection">pref_key_marker_detection</string>
@@ -381,12 +381,14 @@
<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>

View File

@@ -115,6 +115,9 @@ public class ARCoreSharedCamera {
// Image reader that continuously processes CPU images.
public TOF_ImageReader mTOFImageReader = new TOF_ImageReader();
private boolean mTOFAvailable = false;
ByteBuffer mPreviousDepth = null;
double mPreviousDepthStamp = 0.0;
public boolean isDepthSupported() {return mTOFAvailable;}
@@ -688,7 +691,7 @@ public class ARCoreSharedCamera {
if(mToast!=null && previousAnchorPose != null)
{
String msg = "Tracking lost! If you are mapping, you will need to relocalize before continuing.";
if(!mToast.getView().isShown())
if(mToast.getView() == null || !mToast.getView().isShown())
{
mToast.makeText(mActivity.getApplicationContext(),
msg, Toast.LENGTH_LONG).show();
@@ -698,6 +701,7 @@ public class ARCoreSharedCamera {
mToast.setText(msg);
}
previousAnchorPose = null;
arCoreCorrection = Pose.IDENTITY;
}
}
});
@@ -718,7 +722,8 @@ public class ARCoreSharedCamera {
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());
// Only correct the translation to not lose rotation aligned with gravity
arCoreCorrection = arCoreCorrection.compose(previousAnchorPose.compose(pose.inverse()).extractTranslation());
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]));
@@ -736,7 +741,7 @@ public class ARCoreSharedCamera {
+ "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().isShown())
if(mToast.getView() == null || !mToast.getView().isShown())
{
mToast.makeText(mActivity.getApplicationContext(), msg, Toast.LENGTH_LONG).show();
}
@@ -744,7 +749,6 @@ public class ARCoreSharedCamera {
{
mToast.setText(msg);
}
previousAnchorPose = null;
}
}
});
@@ -755,9 +759,8 @@ public class ARCoreSharedCamera {
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));
if(!RTABMapActivity.DISABLE_LOG) Log.d(TAG, String.format("pose=%f %f %f arcore %f %f %f cor= %f %f %f stamp=%f", odomPose.tx(), odomPose.ty(), odomPose.tz(), pose.tx(), pose.ty(), pose.tz(), arCoreCorrection.tx(), arCoreCorrection.ty(), arCoreCorrection.tz(), 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();
@@ -813,6 +816,12 @@ public class ARCoreSharedCamera {
depth = mTOFImageReader.depth16_raw;
depthStamp = (double)mTOFImageReader.timestamp/10e8;
}
if(mPreviousDepth == null)
{
mPreviousDepth = depth;
mPreviousDepthStamp = depthStamp;
}
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));
@@ -825,13 +834,17 @@ public class ARCoreSharedCamera {
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,
depthStamp>stamp?mPreviousDepthStamp:depthStamp,
y, u, v, y.limit(), image.getWidth(), image.getHeight(), image.getFormat(),
depth, depth.limit(), mTOFImageReader.WIDTH, mTOFImageReader.HEIGHT, ImageFormat.DEPTH16,
depthStamp>stamp?mPreviousDepth:depth, depthStamp>stamp?mPreviousDepth.limit():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]);
mPreviousDepthStamp = depthStamp;
mPreviousDepth = depth;
}
else
{

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;
@@ -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)))
{
@@ -1167,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.
@@ -1490,7 +1637,7 @@ public class RTABMapActivity extends FragmentActivity implements OnClickListener
}
updateState(mState);
return true;
}
@@ -1992,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();
@@ -2024,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);
}
});
}
@@ -2144,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);
@@ -2217,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() {
@@ -2626,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());
@@ -2780,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()
{
@@ -3215,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";
@@ -3247,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
@@ -3280,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);
@@ -3334,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);
}
}
});
@@ -3371,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();
@@ -3397,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))
@@ -3424,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();
}
});
}
@@ -3443,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..."));
@@ -3471,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);
}
});
@@ -3498,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() {
@@ -3578,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);

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];

View File

@@ -979,9 +979,10 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CLANG_CXX_LIBRARY = "libc++";
CLANG_USE_OPTIMIZATION_PROFILE = NO;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 7;
CURRENT_PROJECT_VERSION = 1;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = 3RRB6NV8U9;
EXCLUDED_ARCHS = "";
@@ -1006,7 +1007,7 @@
"$(PROJECT_DIR)/RTABMapApp/Libraries/lib",
"$(PROJECT_DIR)/RTABMapApp/Libraries/share/OpenCV/3rdparty/lib",
);
MARKETING_VERSION = 0.20.12;
MARKETING_VERSION = 0.21.0;
OTHER_CFLAGS = "";
PRODUCT_BUNDLE_IDENTIFIER = com.introlab.rtabmap;
PRODUCT_NAME = "$(TARGET_NAME)";
@@ -1019,7 +1020,7 @@
"\"$(SRCROOT)/RTABMapApp/Libraries/include\"",
"\"$(SRCROOT)/RTABMapApp/Libraries/include/eigen3\"",
"\"$(SRCROOT)/RTABMapApp/Libraries/include/pcl-1.11\"",
"\"$(SRCROOT)/RTABMapApp/Libraries/include/rtabmap-0.20\"",
"\"$(SRCROOT)/RTABMapApp/Libraries/include/rtabmap-0.21\"",
"\"$(SRCROOT)/../android/jni/tango-gl/include\"",
"\"$(SRCROOT)/../android/jni/third-party/include\"",
"\"$(SRCROOT)/RTABMapApp/Libraries/lib/vtk.framework/Headers\"",
@@ -1038,7 +1039,7 @@
CLANG_USE_OPTIMIZATION_PROFILE = NO;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 7;
CURRENT_PROJECT_VERSION = 1;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = 3RRB6NV8U9;
FRAMEWORK_SEARCH_PATHS = (
@@ -1063,7 +1064,7 @@
"$(PROJECT_DIR)/RTABMapApp/Libraries/lib",
"$(PROJECT_DIR)/RTABMapApp/Libraries/share/OpenCV/3rdparty/lib",
);
MARKETING_VERSION = 0.20.12;
MARKETING_VERSION = 0.21.0;
ONLY_ACTIVE_ARCH = YES;
OTHER_CFLAGS = "";
PRODUCT_BUNDLE_IDENTIFIER = com.introlab.rtabmap;
@@ -1077,7 +1078,7 @@
"\"$(SRCROOT)/RTABMapApp/Libraries/include\"",
"\"$(SRCROOT)/RTABMapApp/Libraries/include/eigen3\"",
"\"$(SRCROOT)/RTABMapApp/Libraries/include/pcl-1.11\"",
"\"$(SRCROOT)/RTABMapApp/Libraries/include/rtabmap-0.20\"",
"\"$(SRCROOT)/RTABMapApp/Libraries/include/rtabmap-0.21\"",
"\"$(SRCROOT)/../android/jni/tango-gl/include\"",
"\"$(SRCROOT)/../android/jni/third-party/include\"",
"\"$(SRCROOT)/RTABMapApp/Libraries/lib/vtk.framework/Headers\"",

View File

@@ -39,6 +39,7 @@
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
enableGPUFrameCaptureMode = "2"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">

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

@@ -0,0 +1 @@
Libraries

View File

@@ -1,8 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="18122" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<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>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="18093"/>
<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>

View File

@@ -1,8 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="18122" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="zah-iI-EPt">
<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>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="18093"/>
<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"/>

View File

@@ -1,6 +0,0 @@
# Ignore everything
*
# But not these files...
!.gitignore
!install_deps.sh

View File

@@ -69,24 +69,11 @@ void setScreenRotationNative(const void *object, int displayRotation)
}
}
int openDatabaseNative(const void *object, const char * databasePath, bool databaseInMemory, bool optimize)
int openDatabaseNative(const void *object, const char * databasePath, bool databaseInMemory, bool optimize, bool clearDatabase)
{
if(object)
{
return native(object)->openDatabase(databasePath, databaseInMemory, optimize);
}
else
{
UERROR("object is null!");
return -1;
}
}
int openDatabase2Native(const void *object, const char * databaseSource, const char * databasePath, bool databaseInMemory, bool optimize)
{
if(object)
{
return native(object)->openDatabase(databasePath, databaseInMemory, optimize, databaseSource);
return native(object)->openDatabase(databasePath, databaseInMemory, optimize, clearDatabase);
}
else
{
@@ -107,6 +94,31 @@ void saveNative(const void *object, const char * databasePath)
}
}
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)
@@ -272,11 +284,11 @@ 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)
float x, float y, float z, float qx, float qy, float qz, float qw, double stamp)
{
if(object)
{
native(object)->postCameraPoseEvent(x,y,z,qx,qy,qz,qw,0.0);
native(object)->postCameraPoseEvent(x,y,z,qx,qy,qz,qw,stamp);
}
else
{
@@ -477,13 +489,6 @@ void setGridVisibleNative(const void *object, bool 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)

View File

@@ -32,9 +32,10 @@ void setupCallbacksNative(const void *object, void * classPtr,
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);
int openDatabase2Native(const void *object, const char * databaseSource, const char * databasePath, bool databaseInMemory, bool optimize);
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,
@@ -66,7 +67,7 @@ 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);
float x, float y, float z, float qx, float qy, float qz, float qw, double stamp);
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,
@@ -96,7 +97,6 @@ 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);

View File

@@ -113,17 +113,9 @@ class RTABMap {
setupGraphicNative(native_rtabmap, Int32(size.width), Int32(size.height));
}
func openDatabase(databasePath:String, databaseInMemory:Bool, optimize:Bool) -> Int {
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))
}
}
func openDatabase(databaseSource:String, databasePath:String, databaseInMemory:Bool, optimize:Bool) -> Int {
databasePath.utf8CString.withUnsafeBufferPointer { buffer -> Int in
databaseSource.utf8CString.withUnsafeBufferPointer { bufferSource -> Int in
return Int(openDatabase2Native(native_rtabmap, bufferSource.baseAddress, buffer.baseAddress, databaseInMemory, optimize))
}
return Int(openDatabaseNative(native_rtabmap, buffer.baseAddress, databaseInMemory, optimize, clearDatabase))
}
}
@@ -133,6 +125,18 @@ class RTABMap {
}
}
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)))
}
@@ -212,18 +216,18 @@ class RTABMap {
setCameraNative(native_rtabmap, Int32(type))
}
func postCameraPoseEvent(pose: simd_float4x4) {
func postCameraPoseEvent(pose: simd_float4x4, stamp: TimeInterval) {
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)
postCameraPoseEventNative(native_rtabmap, pose[3,0], pose[3,1], pose[3,2], quat.x, quat.y, quat.z, quat.w, stamp)
}
func notifyLost() {
// a null transform will make rtabmap creating a new session
postCameraPoseEventNative(native_rtabmap, 0,0,0,0,0,0,0)
postCameraPoseEventNative(native_rtabmap, 0,0,0,0,0,0,0,0)
}
func postOdometryEvent(frame: ARFrame, orientation: UIInterfaceOrientation, viewport: CGSize) {
@@ -235,7 +239,7 @@ class RTABMap {
let quat = GLKQuaternionMakeWithMatrix3(rotation)
postCameraPoseEventNative(native_rtabmap, pose[3,0], pose[3,1], pose[3,2], quat.x, quat.y, quat.z, quat.w)
postCameraPoseEventNative(native_rtabmap, pose[3,0], pose[3,1], pose[3,2], quat.x, quat.y, quat.z, quat.w, frame.timestamp)
let confMap = frame.sceneDepth?.confidenceMap
let depthMap = frame.sceneDepth?.depthMap
@@ -401,9 +405,6 @@ class RTABMap {
func setGridVisible(visible: Bool) {
setGridVisibleNative(native_rtabmap, visible)
}
func setRawScanSaved(enabled: Bool) {
setRawScanSavedNative(native_rtabmap, enabled)
}
func setFullResolution(enabled: Bool) {
setFullResolutionNative(native_rtabmap, enabled)
}
@@ -486,7 +487,7 @@ func getPreviewImage(databasePath: String) -> UIImage?
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 nil
return UIImage(named: "RTAB-Map1024")
}
return imageOut
}

View File

@@ -8,6 +8,7 @@
import GLKit
import ARKit
import Zip
import StoreKit
extension Array {
func size() -> Int {
@@ -41,6 +42,8 @@ class ViewController: GLKViewController, ARSessionDelegate, RTABMapObserver, UIP
private var mMaxFeatures: Int = 0
private var mLoopThr = 0.11
private var mReviewRequested = false
// UI states
private enum State {
case STATE_WELCOME, // Camera/Motion off - showing only buttons open and start new scan
@@ -112,6 +115,7 @@ class ViewController: GLKViewController, ARSessionDelegate, RTABMapObserver, UIP
@IBOutlet weak var toastLabel: UILabel!
let RTABMAP_TMP_DB = "rtabmap.tmp.db"
let RTABMAP_RECOVERY_DB = "rtabmap.tmp.recovery.db"
let RTABMAP_EXPORT_DIR = "Export"
func getDocumentDirectory() -> URL {
@@ -1315,7 +1319,6 @@ class ViewController: GLKViewController, ARSessionDelegate, RTABMapObserver, UIP
// update preference
rtabmap!.setOnlineBlending(enabled: defaults.bool(forKey: "Blending"));
rtabmap!.setNodesFiltering(enabled: defaults.bool(forKey: "NodesFiltering"));
rtabmap!.setRawScanSaved(enabled: defaults.bool(forKey: "SaveRawScan"));
rtabmap!.setFullResolution(enabled: defaults.bool(forKey: "HDMode"));
rtabmap!.setSmoothing(enabled: defaults.bool(forKey: "Smoothing"));
rtabmap!.setAppendMode(enabled: defaults.bool(forKey: "AppendMode"));
@@ -1340,6 +1343,7 @@ class ViewController: GLKViewController, ARSessionDelegate, RTABMapObserver, UIP
rtabmap!.setMappingParameter(key: "Vis/FeatureType", value: defaults.string(forKey: "FeatureType")!);
rtabmap!.setMappingParameter(key: "Mem/NotLinkedNodesKept", value: defaults.bool(forKey: "SaveAllFramesInDatabase") ? "true" : "false");
rtabmap!.setMappingParameter(key: "RGBD/OptimizeFromGraphEnd", value: defaults.bool(forKey: "OptimizationfromGraphEnd") ? "true" : "false");
rtabmap!.setMappingParameter(key: "RGBD/MaxOdomCacheSize", value: defaults.string(forKey: "MaximumOdometryCacheSize")!);
rtabmap!.setMappingParameter(key: "Optimizer/Strategy", value: defaults.string(forKey: "GraphOptimizer")!);
rtabmap!.setMappingParameter(key: "RGBD/ProximityBySpace", value: defaults.string(forKey: "ProximityDetection")!);
@@ -1413,12 +1417,19 @@ class ViewController: GLKViewController, ARSessionDelegate, RTABMapObserver, UIP
present(alertController, animated: true)
setGLCamera(type: 1);
setGLCamera(type: 0);
startCamera();
}
func newScan()
{
print("databases.size() = \(databases.size())")
if(databases.count >= 5 && !mReviewRequested && self.depthSupported)
{
SKStoreReviewController.requestReviewInCurrentScene()
mReviewRequested = true
}
if(mState == State.STATE_VISUALIZING)
{
closeVisualization()
@@ -1426,15 +1437,121 @@ class ViewController: GLKViewController, ARSessionDelegate, RTABMapObserver, UIP
mMapNodes = 0;
self.openedDatabasePath = nil
let tmpDatabase = self.getTmpDirectory().appendingPathComponent(self.RTABMAP_TMP_DB)
let tmpDatabase = self.getDocumentDirectory().appendingPathComponent(self.RTABMAP_TMP_DB)
let inMemory = UserDefaults.standard.bool(forKey: "DatabaseInMemory")
self.rtabmap!.openDatabase(databasePath: tmpDatabase.path, databaseInMemory: inMemory, optimize: false)
if(!(self.mState == State.STATE_CAMERA || self.mState == State.STATE_MAPPING))
if(!(self.mState == State.STATE_CAMERA || self.mState == State.STATE_MAPPING) &&
FileManager.default.fileExists(atPath: tmpDatabase.path) &&
tmpDatabase.fileSize > 1024*1024) // > 1MB
{
self.setGLCamera(type: 1);
self.startCamera();
dismiss(animated: true, completion: {
let msg = "The previous session (\(tmpDatabase.fileSizeString)) was not correctly saved, do you want to recover it?"
let alert = UIAlertController(title: "Recovery", message: msg, preferredStyle: .alert)
let alertActionNo = UIAlertAction(title: "Ignore", style: .destructive) {
(UIAlertAction) -> Void in
do {
try FileManager.default.removeItem(at: tmpDatabase)
}
catch {
print("Could not clear tmp database: \(error)")
}
self.newScan()
}
alert.addAction(alertActionNo)
let alertActionCancel = UIAlertAction(title: "Cancel", style: .cancel) {
(UIAlertAction) -> Void in
// do nothing
}
alert.addAction(alertActionCancel)
let alertActionYes = UIAlertAction(title: "Yes", style: .default) {
(UIAlertAction2) -> Void in
let fileName = Date().getFormattedDate(format: "yyMMdd-HHmmss") + ".db"
let outputDbPath = self.getDocumentDirectory().appendingPathComponent(fileName).path
var indicator: UIActivityIndicatorView?
let alertView = UIAlertController(title: "Recovering", message: "Please wait while recovering data...", preferredStyle: .alert)
let alertViewActionCancel = UIAlertAction(title: "Cancel", style: .cancel) {
(UIAlertAction) -> Void in
self.dismiss(animated: true, completion: {
self.progressView = nil
indicator = UIActivityIndicatorView(style: .large)
indicator?.frame = CGRect(x: 0.0, y: 0.0, width: 60.0, height: 60.0)
indicator?.center = self.view.center
self.view.addSubview(indicator!)
indicator?.bringSubviewToFront(self.view)
indicator?.startAnimating()
self.rtabmap!.cancelProcessing();
})
}
alertView.addAction(alertViewActionCancel)
let previousState = self.mState
self.updateState(state: .STATE_PROCESSING);
self.present(alertView, animated: true, completion: {
// Add your progressbar after alert is shown (and measured)
let margin:CGFloat = 8.0
let rect = CGRect(x: margin, y: 84.0, width: alertView.view.frame.width - margin * 2.0 , height: 2.0)
self.progressView = UIProgressView(frame: rect)
self.progressView!.progress = 0
self.progressView!.tintColor = self.view.tintColor
alertView.view.addSubview(self.progressView!)
var success : Bool = false
DispatchQueue.background(background: {
success = self.rtabmap!.recover(from: tmpDatabase.path, to: outputDbPath)
}, completion:{
if(indicator != nil)
{
indicator!.stopAnimating()
indicator!.removeFromSuperview()
}
if self.progressView != nil
{
self.dismiss(animated: self.openedDatabasePath == nil, completion: {
if(success)
{
let alertSaved = UIAlertController(title: "Database saved!", message: String(format: "Database \"%@\" successfully recovered!", fileName), preferredStyle: .alert)
let yes = UIAlertAction(title: "OK", style: .default) {
(UIAlertAction) -> Void in
self.openDatabase(fileUrl: URL(fileURLWithPath: outputDbPath))
}
alertSaved.addAction(yes)
self.present(alertSaved, animated: true, completion: nil)
}
else
{
self.updateState(state: previousState);
self.showToast(message: "Recovery failed!", seconds: 4)
}
})
}
else
{
self.showToast(message: "Recovery canceled", seconds: 2)
self.updateState(state: previousState);
}
})
})
}
alert.addAction(alertActionYes)
self.present(alert, animated: true, completion: nil)
})
}
else
{
self.rtabmap!.openDatabase(databasePath: tmpDatabase.path, databaseInMemory: inMemory, optimize: false, clearDatabase: true)
if(!(self.mState == State.STATE_CAMERA || self.mState == State.STATE_MAPPING))
{
self.setGLCamera(type: 0);
self.startCamera();
}
}
}
@@ -1518,12 +1635,19 @@ class ViewController: GLKViewController, ARSessionDelegate, RTABMapObserver, UIP
self.openedDatabasePath = URL(fileURLWithPath: filePath)
let alert = UIAlertController(title: "Database saved!", message: String(format: "Database \"%@\" successfully saved on the SD-CARD!", fileName), preferredStyle: .alert)
let alert = UIAlertController(title: "Database saved!", message: String(format: "Database \"%@\" successfully saved!", fileName), preferredStyle: .alert)
let yes = UIAlertAction(title: "OK", style: .default) {
(UIAlertAction) -> Void in
}
alert.addAction(yes)
self.present(alert, animated: true, completion: nil)
do {
let tmpDatabase = self.getDocumentDirectory().appendingPathComponent(self.RTABMAP_TMP_DB)
try FileManager.default.removeItem(at: tmpDatabase)
}
catch {
print("Could not clear tmp database: \(error)")
}
self.updateDatabases()
self.updateState(state: previousState)
})
@@ -1559,6 +1683,8 @@ class ViewController: GLKViewController, ARSessionDelegate, RTABMapObserver, UIP
indicator?.bringSubviewToFront(self.view)
indicator?.startAnimating()
self.rtabmap!.cancelProcessing()
})
}))
@@ -1663,6 +1789,7 @@ class ViewController: GLKViewController, ARSessionDelegate, RTABMapObserver, UIP
alertView.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: { _ in
self.dismiss(animated: true)
self.progressView = nil
self.rtabmap!.cancelProcessing()
}))
let previousState = mState
@@ -1799,7 +1926,6 @@ class ViewController: GLKViewController, ARSessionDelegate, RTABMapObserver, UIP
stopMapping(ignoreSaving: true)
}
let tmpDatabase = self.getTmpDirectory().appendingPathComponent(self.RTABMAP_TMP_DB)
openedDatabasePath = fileUrl;
let fileName: String = self.openedDatabasePath!.lastPathComponent
@@ -1811,7 +1937,7 @@ class ViewController: GLKViewController, ARSessionDelegate, RTABMapObserver, UIP
updateState(state: .STATE_PROCESSING);
var status = 0
DispatchQueue.background(background: {
status = self.rtabmap!.openDatabase(databaseSource: self.openedDatabasePath!.path, databasePath: tmpDatabase.path, databaseInMemory: true, optimize: false)
status = self.rtabmap!.openDatabase(databasePath: self.openedDatabasePath!.path, databaseInMemory: true, optimize: false, clearDatabase: false)
}, completion:{
// main thread
if(status == -1) {
@@ -1973,6 +2099,7 @@ class ViewController: GLKViewController, ARSessionDelegate, RTABMapObserver, UIP
alertView.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: { _ in
self.dismiss(animated: true)
self.progressView = nil
self.rtabmap!.cancelProcessing()
}))
let previousState = mState;
@@ -2072,7 +2199,7 @@ class ViewController: GLKViewController, ARSessionDelegate, RTABMapObserver, UIP
}
.sorted(by: { $0.1 > $1.1 }) // sort descending modification dates
.map { $0.0 } // extract file names
databases = data.filter{ $0.pathExtension == "db" }
databases = data.filter{ $0.pathExtension == "db" && $0.lastPathComponent != RTABMAP_TMP_DB && $0.lastPathComponent != RTABMAP_RECOVERY_DB }
} catch {
print("Error while enumerating files : \(error.localizedDescription)")
@@ -2210,6 +2337,14 @@ extension Date {
dateformat.dateFormat = format
return dateformat.string(from: self)
}
var millisecondsSince1970:Int64 {
Int64((self.timeIntervalSince1970 * 1000.0).rounded())
}
init(milliseconds:Int64) {
self = Date(timeIntervalSince1970: TimeInterval(milliseconds) / 1000)
}
}
extension DispatchQueue {
@@ -2322,3 +2457,11 @@ extension UserDefaults {
setDefaultsFromSettingsBundle()
}
}
extension SKStoreReviewController {
public static func requestReviewInCurrentScene() {
if let scene = UIApplication.shared.connectedScenes.first(where: { $0.activationState == .foregroundActive }) as? UIWindowScene {
requestReview(in: scene)
}
}
}

View File

@@ -1,7 +1,11 @@
#!/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
@@ -55,9 +59,11 @@ cd $pwd
# FLANN
echo "wget flann..."
curl -L http://www.cs.ubc.ca/research/flann/uploads/FLANN/flann-1.8.4-src.zip -o flann-1.8.4-src.zip
unzip -qq flann-1.8.4-src.zip
cd flann-1.8.4-src
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
@@ -66,7 +72,7 @@ cmake -G Xcode -DCMAKE_SYSTEM_NAME=iOS -DCMAKE_OSX_ARCHITECTURES=arm64 -DCMAKE_O
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-1.8.4-src.zip flann-1.8.4-src
#rm -r flann
# GTSAM
git clone https://bitbucket.org/gtborg/gtsam.git
@@ -105,7 +111,7 @@ 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 -DBUILD_EXAMPLES=OFF -DBUILD_TESTING=OFF -DVTK_IOS_BUILD=ON -DIOS_SIMULATOR_ARCHITECTURES=arm64 -DModule_vtkFiltersModeling=ON ..
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
@@ -116,7 +122,7 @@ 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
curl -L https://gist.github.com/matlabbe/f3ba9366eb91e1b855dadd2ddce5746d/raw/6869cf26211ab15492599e557b0e729b23b2c119/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
@@ -134,6 +140,8 @@ 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
@@ -145,6 +153,10 @@ cd $pwd
mkdir rtabmap
cd rtabmap
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 -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

@@ -13,7 +13,7 @@
<string>
======= RTAB-Map =======
RTAB-Map - https://github.com/introlab/rtabmap
Copyright (c) 2010-2021, Mathieu Labbe - IntRoLab - Universite de Sherbrooke, all rights reserved.
Copyright (c) 2010-2023, 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

View File

@@ -552,6 +552,50 @@
<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&apos;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>
@@ -708,22 +752,6 @@
<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>

View File

@@ -14,7 +14,7 @@
</dict>
<dict>
<key>DefaultValue</key>
<integer>2</integer>
<integer>1</integer>
<key>Key</key>
<string>PointCloudDensity</string>
<key>Title</key>
@@ -454,7 +454,7 @@
</dict>
<dict>
<key>FooterText</key>
<string>Copyright (c) 2010-2021, Mathieu Labbe - IntRoLab - Université de Sherbrooke. All rights reserved.</string>
<string>Copyright (c) 2010-2023, Mathieu Labbe - IntRoLab - Université de Sherbrooke. All rights reserved.</string>
<key>Title</key>
<string>About</string>
<key>Type</key>
@@ -462,7 +462,7 @@
</dict>
<dict>
<key>DefaultValue</key>
<string>0.20.12</string>
<string>0.21.0</string>
<key>Key</key>
<string>Version</string>
<key>Title</key>

View File

@@ -3,31 +3,6 @@ SET(SRC_FILES
main.cpp
)
SET(INCLUDE_DIRS
${PROJECT_SOURCE_DIR}/utilite/include
${PROJECT_SOURCE_DIR}/corelib/include
${PROJECT_SOURCE_DIR}/guilib/include
${CMAKE_CURRENT_SOURCE_DIR}
${OpenCV_INCLUDE_DIRS}
${PCL_INCLUDE_DIRS}
)
IF(QT4_FOUND)
INCLUDE(${QT_USE_FILE})
ENDIF(QT4_FOUND)
SET(LIBRARIES
${QT_LIBRARIES}
${OpenCV_LIBS}
${PCL_LIBRARIES}
)
# rc.exe has problems with these defintions... commented!
#add_definitions(${PCL_DEFINITIONS})
# Make sure the compiler can find include files from our library.
INCLUDE_DIRECTORIES(${INCLUDE_DIRS})
# For Apple set the icns file containing icons
IF(APPLE AND BUILD_AS_BUNDLE)
# set how it shows up in the Info.plist file
@@ -49,40 +24,37 @@ IF(WIN32)
ELSE( MINGW )
SET(SRC_FILES ${SRC_FILES} ${PROJECT_NAME}.rc)
ENDIF( MINGW )
ENDIF(WIN32)
ENDIF(WIN32)
IF(BUILD_AS_BUNDLE)
ADD_DEFINITIONS("-DBUILD_AS_BUNDLE")
ENDIF()
# Add binary
IF(APPLE AND BUILD_AS_BUNDLE)
ADD_EXECUTABLE(rtabmap MACOSX_BUNDLE ${SRC_FILES})
ELSEIF(MINGW)
ADD_EXECUTABLE(rtabmap WIN32 ${SRC_FILES})
ADD_EXECUTABLE(rtabmap_app MACOSX_BUNDLE ${SRC_FILES})
ELSEIF(WIN32 AND BUILD_AS_BUNDLE)
ADD_EXECUTABLE(rtabmap_app WIN32 ${SRC_FILES})
ELSE()
ADD_EXECUTABLE(rtabmap ${SRC_FILES})
ADD_EXECUTABLE(rtabmap_app ${SRC_FILES})
ENDIF()
TARGET_LINK_LIBRARIES(rtabmap rtabmap_core rtabmap_gui rtabmap_utilite ${LIBRARIES})
IF(Qt5_FOUND)
IF(Qt5Svg_FOUND)
QT5_USE_MODULES(rtabmap Widgets Core Gui Svg PrintSupport)
ELSE()
QT5_USE_MODULES(rtabmap Widgets Core Gui PrintSupport)
ENDIF()
ENDIF(Qt5_FOUND)
TARGET_LINK_LIBRARIES(rtabmap_app rtabmap_gui)
IF(APPLE AND BUILD_AS_BUNDLE)
SET_TARGET_PROPERTIES(rtabmap PROPERTIES
SET_TARGET_PROPERTIES(rtabmap_app PROPERTIES
OUTPUT_NAME ${CMAKE_BUNDLE_NAME})
ELSEIF(WIN32)
SET_TARGET_PROPERTIES(rtabmap PROPERTIES
SET_TARGET_PROPERTIES(rtabmap_app PROPERTIES
OUTPUT_NAME ${PROJECT_NAME})
ELSE()
SET_TARGET_PROPERTIES(rtabmap PROPERTIES
SET_TARGET_PROPERTIES(rtabmap_app PROPERTIES
OUTPUT_NAME ${PROJECT_PREFIX})
ENDIF()
#---------------------------
# Installation stuff
#---------------------------
INSTALL(TARGETS rtabmap
INSTALL(TARGETS rtabmap_app
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT runtime
BUNDLE DESTINATION "${CMAKE_BUNDLE_LOCATION}" COMPONENT runtime)
@@ -93,15 +65,18 @@ ENDIF(APPLE AND BUILD_AS_BUNDLE)
IF(BUILD_AS_BUNDLE AND (APPLE OR WIN32))
SET(APPS "\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/bin/${PROJECT_NAME}${CMAKE_EXECUTABLE_SUFFIX}")
SET(plugin_dest_dir bin)
SET(plugin_dest_dir bin/plugins)
SET(qtconf_dest_dir bin)
SET(openni2_dest_dir bin)
SET(thirdparty_dest_dir bin)
IF(APPLE)
SET(plugin_dest_dir MacOS)
SET(plugin_dest_dir MacOS/plugins)
IF(Qt6_FOUND)
SET(plugin_dest_dir PlugIns)
ENDIF()
SET(qtconf_dest_dir Resources)
SET(openni2_dest_dir MacOS)
SET(APPS "\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/MacOS/${CMAKE_BUNDLE_NAME}")
SET(thirdparty_dest_dir MacOS)
SET(APPS "\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/MacOS/${CMAKE_BUNDLE_NAME}")
ENDIF(APPLE)
IF(OpenNI2_FOUND)
@@ -117,11 +92,11 @@ IF(BUILD_AS_BUNDLE AND (APPLE OR WIN32))
ENDIF()
INSTALL(DIRECTORY "${OpenNI2_BIN_DIR}/OpenNI2"
DESTINATION ${openni2_dest_dir}
DESTINATION ${thirdparty_dest_dir}
COMPONENT runtime
REGEX ".*pdb" EXCLUDE)
INSTALL(FILES "${OpenNI2_BIN_DIR}/OpenNI.ini"
DESTINATION ${openni2_dest_dir}
DESTINATION ${thirdparty_dest_dir}
COMPONENT runtime)
ENDIF(OpenNI2_FOUND)
@@ -130,69 +105,124 @@ IF(BUILD_AS_BUNDLE AND (APPLE OR WIN32))
IF(WIN32)
file(TO_CMAKE_PATH "$ENV{K4A_ROOT_DIR}" ENV_K4A_ROOT_DIR)
INSTALL(FILES "${ENV_K4A_ROOT_DIR}/tools/depthengine_2_0.dll"
DESTINATION ${plugin_dest_dir}
DESTINATION ${thirdparty_dest_dir}
COMPONENT runtime)
ENDIF(WIN32)
ENDIF(k4a_FOUND)
# Install needed Qt plugins by copying directories from the qt installation
# One can cull what gets copied by using 'REGEX "..." EXCLUDE'
# Exclude debug libraries
IF(QT_PLUGINS_DIR)
INSTALL(DIRECTORY "${QT_PLUGINS_DIR}/imageformats"
DESTINATION ${plugin_dest_dir}/plugins
COMPONENT runtime
REGEX ".*d4.dll" EXCLUDE
REGEX ".*d4.a" EXCLUDE)
ELSE()
#Qt5
foreach(plugin ${Qt5Gui_PLUGINS})
get_target_property(plugin_loc ${plugin} LOCATION)
get_filename_component(plugin_dir ${plugin_loc} DIRECTORY)
string(REPLACE "plugins" ";" loc_list ${plugin_dir})
list(GET loc_list 1 plugin_type)
IF(NOT plugin_root)
get_filename_component(plugin_root ${plugin_dir} DIRECTORY)
ENDIF(NOT plugin_root)
#MESSAGE(STATUS "Qt5 plugin \"${plugin_loc}\" installed in \"${plugin_dest_dir}/plugins${plugin_type}\"")
INSTALL(FILES ${plugin_loc}
DESTINATION ${plugin_dest_dir}/plugins${plugin_type}
COMPONENT runtime)
endforeach()
IF(NOT Qt5Widgets_VERSION VERSION_LESS 5.10.0)
IF(WIN32)
SET(plugin_loc "${plugin_root}/styles/qwindowsvistastyle.dll")
ELSEIF(APPLE)
SET(plugin_loc "${plugin_root}/styles/libqmacstyle.dylib")
ENDIF()
IF(EXISTS ${plugin_loc})
get_filename_component(plugin_dir ${plugin_loc} DIRECTORY)
string(REPLACE "plugins" ";" loc_list ${plugin_dir})
list(GET loc_list 1 plugin_type)
INSTALL(FILES ${plugin_loc}
DESTINATION ${plugin_dest_dir}/plugins${plugin_type}
COMPONENT runtime)
#MESSAGE(STATUS "Qt5 plugin \"${plugin_loc}\" installed in \"${plugin_dest_dir}/plugins${plugin_type}\"")
ENDIF(EXISTS ${plugin_loc})
ENDIF(NOT Qt5Widgets_VERSION VERSION_LESS 5.10.0)
ENDIF()
# install a qt.conf file
# this inserts some cmake code into the install script to write the file
SET(QT_CONF_FILE [Paths]\nPlugins=plugins)
IF(APPLE)
SET(QT_CONF_FILE [Paths]\nPlugins=MacOS/plugins)
ENDIF(APPLE)
INSTALL(CODE "
file(WRITE \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${qtconf_dest_dir}/qt.conf\" \"${QT_CONF_FILE}\")
" COMPONENT runtime)
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 ${thirdparty_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)
IF(Qt6_FOUND)
# Reference: https://doc-snapshots.qt.io/qt6-6.4/qt-deploy-runtime-dependencies.html
# The following script must only be executed at install time
set(deploy_script "${CMAKE_CURRENT_BINARY_DIR}/deploy_app$<CONFIG>.cmake")
file(GENERATE OUTPUT ${deploy_script} CONTENT "
# Including the file pointed to by QT_DEPLOY_SUPPORT ensures the generated
# deployment script has access to qt_deploy_runtime_dependencies()
include(\"${QT_DEPLOY_SUPPORT}\")
qt_deploy_runtime_dependencies(
EXECUTABLE \"${APPS}\"
PLUGINS_DIR ${plugin_dest_dir}
GENERATE_QT_CONF
NO_TRANSLATIONS
VERBOSE
)")
IF("${CMAKE_BUILD_TYPE}" STREQUAL "" OR "${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
install(SCRIPT "${CMAKE_CURRENT_BINARY_DIR}/deploy_appDebug.cmake"
CONFIGURATIONS Debug
COMPONENT runtime)
ENDIF()
IF("${CMAKE_BUILD_TYPE}" STREQUAL "" OR "${CMAKE_BUILD_TYPE}" STREQUAL "Release")
install(SCRIPT "${CMAKE_CURRENT_BINARY_DIR}/deploy_appRelease.cmake"
CONFIGURATIONS Release
COMPONENT runtime)
ENDIF()
IF("${CMAKE_BUILD_TYPE}" STREQUAL "" OR "${CMAKE_BUILD_TYPE}" STREQUAL "RelWithDebInfo")
install(SCRIPT "${CMAKE_CURRENT_BINARY_DIR}/deploy_appRelWithDebInfo.cmake"
CONFIGURATIONS RelWithDebInfo
COMPONENT runtime)
ENDIF()
IF("${CMAKE_BUILD_TYPE}" STREQUAL "" OR "${CMAKE_BUILD_TYPE}" STREQUAL "MinSizeRel")
install(SCRIPT "${CMAKE_CURRENT_BINARY_DIR}/deploy_appMinSizeRel.cmake"
CONFIGURATIONS MinSizeRel
COMPONENT runtime)
ENDIF()
ELSEIF(Qt5_FOUND)
#Qt5
foreach(plugin ${Qt5Gui_PLUGINS})
get_target_property(plugin_loc ${plugin} LOCATION)
get_filename_component(plugin_dir ${plugin_loc} DIRECTORY)
string(REPLACE "plugins" ";" loc_list ${plugin_dir})
list(GET loc_list 1 plugin_type)
IF(NOT plugin_root)
get_filename_component(plugin_root ${plugin_dir} DIRECTORY)
ENDIF(NOT plugin_root)
#MESSAGE(STATUS "Qt5 plugin \"${plugin_loc}\" installed in \"${plugin_dest_dir}${plugin_type}\"")
INSTALL(FILES ${plugin_loc}
DESTINATION ${plugin_dest_dir}${plugin_type}
COMPONENT runtime)
endforeach()
IF(NOT Qt5Widgets_VERSION VERSION_LESS 5.10.0)
IF(WIN32)
SET(plugin_loc "${plugin_root}/styles/qwindowsvistastyle.dll")
ELSEIF(APPLE)
SET(plugin_loc "${plugin_root}/styles/libqmacstyle.dylib")
ENDIF()
IF(EXISTS ${plugin_loc})
get_filename_component(plugin_dir ${plugin_loc} DIRECTORY)
string(REPLACE "plugins" ";" loc_list ${plugin_dir})
list(GET loc_list 1 plugin_type)
INSTALL(FILES ${plugin_loc}
DESTINATION ${plugin_dest_dir}/plugins${plugin_type}
COMPONENT runtime)
#MESSAGE(STATUS "Qt5 plugin \"${plugin_loc}\" installed in \"${plugin_dest_dir}${plugin_type}\"")
ENDIF(EXISTS ${plugin_loc})
ENDIF(NOT Qt5Widgets_VERSION VERSION_LESS 5.10.0)
ELSEIF(QT_PLUGINS_DIR) # Qt4
# Install needed Qt plugins by copying directories from the qt installation
# One can cull what gets copied by using 'REGEX "..." EXCLUDE'
# Exclude debug libraries
INSTALL(DIRECTORY "${QT_PLUGINS_DIR}/imageformats"
DESTINATION ${plugin_dest_dir}
COMPONENT runtime
REGEX ".*d4.dll" EXCLUDE
REGEX ".*d4.a" EXCLUDE)
ENDIF()
IF(Qt5_FOUND OR QT4_FOUND)
# install a qt.conf file
# this inserts some cmake code into the install script to write the file
SET(QT_CONF_FILE [Paths]\nPlugins=plugins)
IF(APPLE)
SET(QT_CONF_FILE [Paths]\nPlugins=MacOS/plugins)
ENDIF(APPLE)
INSTALL(CODE "
file(WRITE \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${qtconf_dest_dir}/qt.conf\" \"${QT_CONF_FILE}\")
" COMPONENT runtime)
ENDIF()
# directories to look for dependencies
SET(DIRS ${QT_LIBRARY_DIRS} ${PROJECT_SOURCE_DIR}/bin)
SET(DIRS "${QT_LIBRARY_DIRS}" "\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/lib")
IF(APPLE)
SET(DIRS ${DIRS} /usr/local /usr/local/lib)
ENDIF(APPLE)
SET(DIRS ${DIRS} /usr/local /usr/local/lib /opt/homebrew /opt/homebrew/lib /opt/homebrew/lib/gcc/current)
ENDIF(APPLE)
# Now the work of copying dependencies into the bundle/package
# The quotes are escaped and variables to use at install time have their $ escaped
# An alternative is the do a configure_file() on a script and use install(SCRIPT ...).
@@ -200,10 +230,11 @@ IF(BUILD_AS_BUNDLE AND (APPLE OR WIN32))
# over.
# To find dependencies, cmake use "otool" on Apple and "dumpbin" on Windows (make sure you have one of them).
install(CODE "
file(GLOB_RECURSE QTPLUGINS \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${plugin_dest_dir}/plugins/*${CMAKE_SHARED_LIBRARY_SUFFIX}\")
file(GLOB_RECURSE QTPLUGINS \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${plugin_dest_dir}/*${CMAKE_SHARED_LIBRARY_SUFFIX}\")
set(BU_CHMOD_BUNDLE_ITEMS ON)
include(\"BundleUtilities\")
fixup_bundle(\"${APPS}\" \"\${QTPLUGINS}\" \"${DIRS}\")
" COMPONENT runtime)
" COMPONENT runtime)
ENDIF(BUILD_AS_BUNDLE AND (APPLE OR WIN32))

View File

@@ -36,10 +36,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "rtabmap/utilite/UFile.h"
#include "rtabmap/utilite/UConversion.h"
#include <vtkVersionMacros.h>
#include <vtkObject.h>
#ifdef RTABMAP_PYTHON
#include "rtabmap/core/PythonInterface.h"
#if VTK_MAJOR_VERSION > 9 || (VTK_MAJOR_VERSION==9 && VTK_MINOR_VERSION >= 1)
#include <QVTKRenderWidget.h>
#endif
using namespace rtabmap;
@@ -54,12 +55,9 @@ int main(int argc, char* argv[])
CoInitialize(nullptr);
#endif
#ifdef RTABMAP_PYTHON
PythonInterface python; // Make sure we initialize python in main thread
#endif
#if VTK_MAJOR_VERSION >= 8
vtkObject::GlobalWarningDisplayOff();
#if VTK_MAJOR_VERSION > 9 || (VTK_MAJOR_VERSION==9 && VTK_MINOR_VERSION >= 1)
// needed to ensure appropriate OpenGL context is created for VTK rendering.
QSurfaceFormat::setDefaultFormat(QVTKRenderWidget::defaultFormat());
#endif
/* Create tasks */

View File

@@ -0,0 +1,25 @@
To reproduce results (based on parameters of this [paper](https://introlab.3it.usherbrooke.ca/mediawiki-introlab/images/b/bc/TRO2013.pdf)):
```
rtabmap-console \
--Rtabmap/StatisticLogged true\
--Rtabmap/StatisticLoggedHeaders false\
--Kp/DetectorStrategy 0\
--Rtabmap/MemoryThr 300\
--Rtabmap/LoopRatio 0.9\
--SURF/HessianThreshold 150\
--Mem/STMSize 30\
--Vis/MaxFeatures 400\
--Kp/TfIdfLikelihoodUsed false\
--Kp/MaxFeatures 400\
--Kp/BadSignRatio 0.25\
--Mem/BadSignaturesIgnored true\
--Mem/RehearsalSimilarity 0.20\
--Mem/RecentWmRatio 0.2\
-gt "~/Downloads/UdeS_1Hz.png"\
~/Downloads/UdeS_1Hz
```
Adding the ground truth file here is optional to show recall at 100% precision at the end of the process directly without using the octave/MATLAB script below. For NewCollege and CityCentre datasets, `rtabmap-imagesJoiner` can be used to assemble the left and right images together.
To analyze with Octave/MATLAB, drop `LogF.txt` and `LogI.txt` generated files from command above in ShowLogs directly, then execute `showLogs.m`.

View File

@@ -1,4 +0,0 @@
This directory contains some basic concepts on Bayes filtering.
Main scripts :
RecursivesBayes.m
RecursivesBayesAvpd.m

View File

@@ -32,8 +32,7 @@ if ~isempty(GroundTruth)
if size(GroundTruth, 1) ~= length(LogF(:,1)) || size(GroundTruth, 1) ~= length(LogI(:,1))
error(['The ground truth size doesn''t match the log files (LogI=' num2str(length(LogI(:,1))) ', LogF=' num2str(length(LogF(:,1))) ', GT=' num2str(size(GroundTruth, 1)) ')'])
end
%[highestHypot, CorrespondingID, GT, Accepted, Good, Index, UnderLoopRatio] descending order
if(sum(LogI(:,8) == 10) > 0)
%OLD
@@ -111,14 +110,14 @@ if ~isempty(GroundTruth)
index = find(PR(:,1) == 1);
if ~isempty(index)
maxRecall = PR(index(end),2) * 100;
display(['Recall max (Precision=100%) = ' num2str(maxRecall) '% (p=' num2str(lc(index(end),1)) '), accepted=' num2str(sum(lc(1:index(end),5) & ~lc(1:index(end),7) & lc(1:index(end),2)))])
display(['Recall max (Precision=100%) = ' num2str(maxRecall) '% (p=' num2str(lc(index(end),1)) '), accepted=' num2str(sum(lc(1:index(end),5) & ~lc(1:index(end),7) & lc(1:index(end),2))) '/' num2str(GT_total_positives)])
else
display('Recall max (Precision=100%) = 0')
end
indexAccepted = find(PR(:,3) == 1);
if ~isempty(indexAccepted)
maxRecall = PR(indexAccepted(end),2) * 100;
display(['Recall max accepted (Precision=100%) = ' num2str(maxRecall) '% (p=' num2str(lc(indexAccepted(end),1)) '), accepted=' num2str(sum(lc(1:indexAccepted(end),5) & ~lc(1:indexAccepted(end),7) & lc(1:indexAccepted(end),2)))])
display(['Recall max accepted (Precision=100%) = ' num2str(maxRecall) '% (p=' num2str(lc(indexAccepted(end),1)) '), accepted=' num2str(sum(lc(1:indexAccepted(end),5) & ~lc(1:indexAccepted(end),7) & lc(1:indexAccepted(end),2))) '/' num2str(GT_total_positives)])
else
display('Recall max accepted (Precision=100%) = 0')
end

View File

@@ -22,6 +22,8 @@ function [LogF LogI] = showlogs(PathPrefix, GT_file)
set(0,'defaultAxesFontName', 'Times')
set(0,'defaultTextFontName', 'Times')
close all
if nargin < 2, GT_file = ''; end
if nargin < 1, PathPrefix = '.'; end
@@ -325,7 +327,7 @@ y(LogI(:, 1) == 0) = [];
x(LogI(:, 1) == 0) = [];
plot(x,y, 'g.')
set(datacursormode,'UpdateFcn',@(Y,X){sprintf('X: %0.2f',X.Position(1)),sprintf('Y: %0.2f',X.Position(2))})
%set(datacursormode,'UpdateFcn',@(Y,X){sprintf('X: %0.2f',X.Position(1)),sprintf('Y: %0.2f',X.Position(2))})
% %matched sign words
% y = LogI(:,2);
% x = 1:length(y);

View File

@@ -0,0 +1,8 @@
#!/bin/bash
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
$SCRIPT_DIR/run_bow.sh ~/loop_closure_detection_datasets/NewCollege ~/loop_closure_detection_datasets/NewCollege.png
$SCRIPT_DIR/run_bow.sh ~/loop_closure_detection_datasets/CityCentre ~/loop_closure_detection_datasets/CityCentre.png
$SCRIPT_DIR/run_bow.sh ~/loop_closure_detection_datasets/UdeS_1Hz ~/loop_closure_detection_datasets/UdeS_1Hz.png

View File

@@ -0,0 +1,32 @@
#!/bin/bash
DATASET_FOLDER=""
GT_FILE=""
if [ $# -eq 2 ]
then
DATASET_FOLDER=$1
GT_FILE=$2
else
echo "Usage: run_bow.sh \"dataset folder\" \"ground truth file\""
exit
fi
rtabmap-console \
-quiet \
--Rtabmap/StatisticLogged true\
--Rtabmap/StatisticLoggedHeaders false\
--Kp/DetectorStrategy 0\
--SURF/HessianThreshold 150\
--Rtabmap/MemoryThr 300\
--Rtabmap/LoopRatio 0.9\
--Mem/STMSize 30\
--Vis/MaxFeatures 400\
--Kp/TfIdfLikelihoodUsed false\
--Kp/MaxFeatures 400\
--Kp/BadSignRatio 0.25\
--Mem/BadSignaturesIgnored true\
--Mem/RehearsalSimilarity 0.20\
--Mem/RecentWmRatio 0.20\
-gt "$GT_FILE"\
"$DATASET_FOLDER"

View File

@@ -1,22 +0,0 @@
## Multi-Session Visual SLAM for Illumination Invariant Localization in Indoor Environments
* Paper: https://arxiv.org/abs/2103.03827
* The setup: we did 6 mapping sessions at dusk to evaluate how well RTAB-Map can localize (only by vision) on maps taken at different illumination conditions. The data has been collected with [RTAB-Map Tango](https://play.google.com/store/apps/details?id=com.introlab.rtabmap&hl=en_CA&gl=US).
![Overview](https://github.com/introlab/rtabmap/raw/master/archive/2020-IlluminationInvariant/images/fig_overview.jpg)]
## Description
This folder contains scripts to re-generate results from the paper. The main idea behind this work is that using Multi-Session mapping can help to localize visually in illumination changing environments even with features that are not very robust to such conditions. We compared common hand-made visual features like SIFT, SURF, BRIEF, BRISK, FREAK, DAISY, KAZE with learned descriptor SuperPoint. The following picture show how robust are the visual features tested when localizing against single session recorded at different time. For example, the bottom-left and top-right cells are when the robot tries to localize the night on a map taken the day or vice-versa. The diagonal is localization performance when the localization session is about the same time than when the map was recorded. SuperPoint has clearly an advantage on this single-session experiment.
![All sessions](https://github.com/introlab/rtabmap/raw/master/archive/2020-IlluminationInvariant/images/fig_single_percentage.jpg)]
The following image shows when we do the same localization experiment at different hours, but against maps created by assembling maps taken at different hours. In this case, we can see that even binary features like BRIEF can work relatively well in illumination-variant environments. See the paper for more detailled results and comments. The line `1+2+3+4+5+6` refers to the assembled map shown below containing all mapping sessions linked together in same database.
![All sessions](https://github.com/introlab/rtabmap/raw/master/archive/2020-IlluminationInvariant/images/fig_merged_percentage.jpg)]
![All sessions](https://github.com/introlab/rtabmap/raw/master/archive/2020-IlluminationInvariant/images/fig_map_merged_999.jpg)]

Binary file not shown.

Before

Width:  |  Height:  |  Size: 98 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 110 KiB

View File

@@ -1,19 +0,0 @@
#!/bin/bash
SKIP=0
if [ $# -eq 1 ]
then
SKIP=$1
fi
DETECTOR=(0 1 6 7 9 11 12 14) #0 1 6 7 8 9 11 12 13 14
PREFIX="/home/mathieu/workspace/rtabmap_cv_latest/bin/"
REPORT_TOOL="${PREFIX}rtabmap-report"
for d in "${DETECTOR[@]}"
do
$REPORT_TOOL --export --export_prefix "Stat$d" --loc 32 Loop/Odom_correction_norm/m Loop/Visual_inliers/ Timing/Total/ms Loop/Map_id/ Keypoint/Current_frame/words Memory/RAM_usage/MB Memory/RAM_estimated/MB Memory/Distance_travelled/m "$SKIP/$d/loc"
$REPORT_TOOL --export --export_prefix "Consecutive$d" --loc 32 Loop/Map_id/ "$SKIP/$d/consecutive_loc"
done

View File

@@ -1,42 +0,0 @@
#!/bin/bash
if [ $# -eq 0 ]
then
echo "No arguments supplied. It should be the detector number type (0=SURF 1=SIFT 2=ORB 3=FAST/FREAK 4=FAST/BRIEF 5=GFTT/FREAK 6=GFTT/BRIEF 7=BRISK 8=GFTT/ORB 9=KAZE 10=ORB-OCTREE 11=SuperPoint)."
exit
fi
TYPE=$1
SKIP=0
if [ $# -eq 2 ]
then
SKIP=$2
fi
PREFIX="/home/mathieu/workspace/rtabmap_cv_latest/bin/"
REPROCESS_TOOL="${PREFIX}rtabmap-reprocess"
DETECT_MORE_LOOP_CLOSURE_TOOL="${PREFIX}rtabmap-detectMoreLoopClosures"
[ ! -d "$SKIP" ] && mkdir $SKIP
[ ! -d "$SKIP/$TYPE" ] && mkdir $SKIP/$TYPE
# 'map_190321-164651.db' 'map_190321-172717.db' 'map_190321-175428.db' 'map_190321-182709.db' 'map_190321-185608.db' 'map_190321-193556.db'
DATABASES=( 'map_190321-164651.db' 'map_190321-172717.db' 'map_190321-175428.db' 'map_190321-182709.db' 'map_190321-185608.db' 'map_190321-193556.db' )
PARAMS="--Kp/DetectorStrategy $TYPE --Vis/FeatureType $TYPE"
if [ $TYPE -eq 2 ] || [ $TYPE -eq 3 ] || [ $TYPE -eq 4 ] || [ $TYPE -eq 5 ] || [ $TYPE -eq 6 ] || [ $TYPE -eq 7 ] || [ $TYPE -eq 8 ] || [ $TYPE -eq 10 ] || [ $TYPE -eq 12 ]
then
# binary descriptors
PARAMS="--Vis/CorNNDR 0.8 $PARAMS"
else
# float descriptors
PARAMS="--Vis/CorNNDR 0.6 $PARAMS"
if
echo $PARAMS
for db in "${DATABASES[@]}"
do
$REPROCESS_TOOL --skip $SKIP --RGBD/MarkerDetection false --RGBD/ProximityBySpace true --RGBD/LocalRadius 1 --Mem/InitWMWithAllNodes true --Rtabmap/TimeThr 0 --Mem/UseOdomFeatures false --Optimizer/GravitySigma 0.1 --Mem/UseOdomGravity true --RGBD/OptimizeFromGraphEnd false --Mem/DepthAsMask false --RGBD/OptimizeMaxError 4 --RGBD/ProximityOdomGuess false --Vis/MaxFeatures 1000 --Kp/MaxFeatures 400 --Vis/EpipolarGeometryVar 0.1 --Vis/EstimationType 1 --Vis/MinInliers 20 --Rtabmap/MaxRetrieved 2 --Optimizer/Iterations 20 --Mem/CompressionParallelized true --Kp/Parallelized true --Kp/MaxDepth 0 --Kp/BadSignRatio 0.2 --BRIEF/Bytes 32 --Kp/ByteToFloat true --SURF/HessianThreshold 100 --SIFT/ContrastThreshold 0.02 --BRISK/Thresh 10 --SuperPoint/ModelPath superpoint.pt --Rtabmap/PublishRAMUsage true --ORB/EdgeThreshold 19 --ORB/ScaleFactor 2 --ORB/NLevels 3 --uerror $PARAMS $db $SKIP/$TYPE/$db
$DETECT_MORE_LOOP_CLOSURE_TOOL --uwarn $SKIP/$TYPE/$db
done

View File

@@ -1,16 +0,0 @@
#!/bin/bash
SKIP=0
if [ $# -eq 1 ]
then
SKIP=$1
fi
DETECTOR=(0 1 6 7 9 11 12 14)
for d in "${DETECTOR[@]}"
do
./reprocess_maps.sh $d $SKIP
./run_merge.sh $d $SKIP
done

View File

@@ -1,13 +0,0 @@
#!/bin/bash
SKIP=0
if [ $# -eq 1 ]
then
SKIP=$1
fi
./reprocess_maps_all.sh $SKIP
./run_merge.sh $SKIP
./run_localization_single_all.sh $SKIP
./run_consecutive_localization_all.sh $SKIP

View File

@@ -1,31 +0,0 @@
#!/bin/bash
if [ $# -eq 0 ]
then
echo "No arguments supplied. It should be the detector number type (0=SURF 1=SIFT 2=ORB 3=FAST/FREAK 4=FAST/BRIEF 5=GFTT/FREAK 6=GFTT/BRIEF 7=BRISK 8=GFTT/ORB 9=KAZE 10=ORB-OCTREE 11=SuperPoint)."
exit
fi
TYPE=$1
SKIP=0
if [ $# -eq 2 ]
then
SKIP=$2
fi
PREFIX="/home/mathieu/workspace/rtabmap_cv_latest/bin/"
REPROCESS_TOOL="${PREFIX}rtabmap-reprocess"
SOURCE=('map_190321-164651.db' 'map_190321-172717.db' 'map_190321-175428.db' 'map_190321-182709.db' 'map_190321-185608.db')
TARGETS=($SKIP/$TYPE'/map_190321-172717.db;'$SKIP/$TYPE'/map_190321-175428.db;'$SKIP/$TYPE'/map_190321-193556.db' $SKIP/$TYPE'/map_190321-175428.db;'$SKIP/$TYPE'/map_190321-182709.db;' $SKIP/$TYPE'/map_190321-182709.db;'$SKIP/$TYPE'/map_190321-185608.db' $SKIP/$TYPE'/map_190321-185608.db;'$SKIP/$TYPE'/map_190321-193556.db' $SKIP/$TYPE'/map_190321-193556.db' )
[ ! -d "$SKIP/$TYPE/consecutive_loc" ] && mkdir $SKIP/$TYPE/consecutive_loc
for i in ${!SOURCE[@]}
do
db=${SOURCE[$i]}
loc_dbs=${TARGETS[$i]}
$REPROCESS_TOOL --Mem/IncrementalMemory false --RGBD/ProximityBySpace true --Mem/LocalizationDataSaved true --Mem/BinDataKept false --RGBD/SavedLocalizationIgnored true --uwarn "$SKIP/$TYPE/$db;$loc_dbs" $SKIP/$TYPE/consecutive_loc/loc_$db
done

View File

@@ -1,15 +0,0 @@
#!/bin/bash
SKIP=0
if [ $# -eq 1 ]
then
SKIP=$1
fi
DETECTOR=(0 1 6 7 9 11 12 14)
for d in "${DETECTOR[@]}"
do
./run_consecutive_localization.sh $d $SKIP
done

View File

@@ -1,38 +0,0 @@
#!/bin/bash
if [ $# -eq 0 ]
then
echo "No arguments supplied. It should be the detector number type (0=SURF 1=SIFT 2=ORB 3=FAST/FREAK 4=FAST/BRIEF 5=GFTT/FREAK 6=GFTT/BRIEF 7=BRISK 8=GFTT/ORB 9=KAZE 10=ORB-OCTREE 11=SuperPoint)."
exit
fi
TYPE=$1
SKIP=0
if [ $# -eq 2 ]
then
SKIP=$2
fi
PREFIX="/home/mathieu/workspace/rtabmap_cv_latest/bin/"
REPROCESS_TOOL="${PREFIX}rtabmap-reprocess"
# loc_190321-165128.db;loc_190321-173134.db;loc_190321-175823.db;loc_190321-183051.db;loc_190321-185950.db;loc_190321-194226.db
LOCALIZATION_DATABASES="loc_190321-165128.db;loc_190321-173134.db;loc_190321-175823.db;loc_190321-183051.db;loc_190321-185950.db;loc_190321-194226.db"
[ ! -d "$SKIP/$TYPE/loc" ] && mkdir $SKIP/$TYPE/accuracy
db=merged_9999.db
$REPROCESS_TOOL --skip $SKIP --Mem/IncrementalMemory false --RGBD/ProximityBySpace true --Mem/LocalizationDataSaved true --Mem/BinDataKept false --RGBD/SavedLocalizationIgnored true --Kp/IncrementalFlann false --Vis/MinInliers 20 --Rtabmap/PublishRAMUsage true --RGBD/ProximityOdomGuess false --Reg/RepeatOnce true --Vis/BundleAdjustment 1 --uwarn "$SKIP/$TYPE/$db;$LOCALIZATION_DATABASES" $SKIP/$TYPE/accuracy/ProxOff_DoubleRegOn_BaOn_$db
$REPROCESS_TOOL --skip $SKIP --Mem/IncrementalMemory false --RGBD/ProximityBySpace true --Mem/LocalizationDataSaved true --Mem/BinDataKept false --RGBD/SavedLocalizationIgnored true --Kp/IncrementalFlann false --Vis/MinInliers 20 --Rtabmap/PublishRAMUsage true --RGBD/ProximityOdomGuess false --Reg/RepeatOnce false --Vis/BundleAdjustment 1 --uwarn "$SKIP/$TYPE/$db;$LOCALIZATION_DATABASES" $SKIP/$TYPE/accuracy/ProxOff_DoubleRegOff_BaOn_$db
$REPROCESS_TOOL --skip $SKIP --Mem/IncrementalMemory false --RGBD/ProximityBySpace true --Mem/LocalizationDataSaved true --Mem/BinDataKept false --RGBD/SavedLocalizationIgnored true --Kp/IncrementalFlann false --Vis/MinInliers 20 --Rtabmap/PublishRAMUsage true --RGBD/ProximityOdomGuess false --Reg/RepeatOnce true --Vis/BundleAdjustment 0 --uwarn "$SKIP/$TYPE/$db;$LOCALIZATION_DATABASES" $SKIP/$TYPE/accuracy/ProxOff_DoubleRegOn_BaOff_$db
$REPROCESS_TOOL --skip $SKIP --Mem/IncrementalMemory false --RGBD/ProximityBySpace true --Mem/LocalizationDataSaved true --Mem/BinDataKept false --RGBD/SavedLocalizationIgnored true --Kp/IncrementalFlann false --Vis/MinInliers 20 --Rtabmap/PublishRAMUsage true --RGBD/ProximityOdomGuess false --Reg/RepeatOnce false --Vis/BundleAdjustment 0 --uwarn "$SKIP/$TYPE/$db;$LOCALIZATION_DATABASES" $SKIP/$TYPE/accuracy/ProxOff_DoubleRegOff_BaOff_$db
$REPROCESS_TOOL --skip $SKIP --Mem/IncrementalMemory false --RGBD/ProximityBySpace true --Mem/LocalizationDataSaved true --Mem/BinDataKept false --RGBD/SavedLocalizationIgnored true --Kp/IncrementalFlann false --Vis/MinInliers 20 --Rtabmap/PublishRAMUsage true --RGBD/ProximityOdomGuess true --Reg/RepeatOnce true --Vis/BundleAdjustment 1 --uwarn "$SKIP/$TYPE/$db;$LOCALIZATION_DATABASES" $SKIP/$TYPE/accuracy/ProxOn_DoubleRegOn_BaOn_$db
$REPROCESS_TOOL --skip $SKIP --Mem/IncrementalMemory false --RGBD/ProximityBySpace true --Mem/LocalizationDataSaved true --Mem/BinDataKept false --RGBD/SavedLocalizationIgnored true --Kp/IncrementalFlann false --Vis/MinInliers 20 --Rtabmap/PublishRAMUsage true --RGBD/ProximityOdomGuess true --Reg/RepeatOnce true --Vis/BundleAdjustment 0 --uwarn "$SKIP/$TYPE/$db;$LOCALIZATION_DATABASES" $SKIP/$TYPE/accuracy/ProxOn_DoubleRegOn_BaOff_$db

View File

@@ -1,32 +0,0 @@
#!/bin/bash
if [ $# -eq 0 ]
then
echo "No arguments supplied. It should be the detector number type (0=SURF 1=SIFT 2=ORB 3=FAST/FREAK 4=FAST/BRIEF 5=GFTT/FREAK 6=GFTT/BRIEF 7=BRISK 8=GFTT/ORB 9=KAZE 10=ORB-OCTREE 11=SuperPoint)."
exit
fi
TYPE=$1
SKIP=0
if [ $# -eq 2 ]
then
SKIP=$2
fi
PREFIX="/home/mathieu/workspace/rtabmap_cv_latest/bin/"
REPROCESS_TOOL="${PREFIX}rtabmap-reprocess"
# 'map_190321-164651.db' 'map_190321-172717.db' 'map_190321-175428.db' 'map_190321-182709.db' 'map_190321-185608.db' 'map_190321-193556.db' 'merged_9999.db' 'merged_135.db' 'merged_246.db' 'merged_16.db' 'merged_9999_reduced.db'
DATABASES=( 'map_190321-164651.db' 'map_190321-172717.db' 'map_190321-175428.db' 'map_190321-182709.db' 'map_190321-185608.db' 'map_190321-193556.db' 'merged_9999.db' 'merged_135.db' 'merged_246.db' 'merged_16.db' )
# loc_190321-165128.db;loc_190321-173134.db;loc_190321-175823.db;loc_190321-183051.db;loc_190321-185950.db;loc_190321-194226.db
LOCALIZATION_DATABASES="loc_190321-165128.db;loc_190321-173134.db;loc_190321-175823.db;loc_190321-183051.db;loc_190321-185950.db;loc_190321-194226.db"
[ ! -d "$SKIP/$TYPE/loc" ] && mkdir $SKIP/$TYPE/loc
echo $PARAMS
for db in "${DATABASES[@]}"
do
$REPROCESS_TOOL --skip $SKIP --Mem/IncrementalMemory false --RGBD/ProximityBySpace true --Mem/LocalizationDataSaved true --Mem/BinDataKept false --RGBD/SavedLocalizationIgnored true --Kp/IncrementalFlann false --Vis/MinInliers 20 --Rtabmap/PublishRAMUsage true --RGBD/ProximityOdomGuess false --uwarn "$SKIP/$TYPE/$db;$LOCALIZATION_DATABASES" $SKIP/$TYPE/loc/loc_$db
done

View File

@@ -1,15 +0,0 @@
#!/bin/bash
SKIP=0
if [ $# -eq 1 ]
then
SKIP=$1
fi
DETECTOR=(0 1 6 7 9 11 12 14)
for d in "${DETECTOR[@]}"
do
./run_localization_single.sh $d $SKIP
done

View File

@@ -1,38 +0,0 @@
#!/bin/bash
if [ $# -eq 0 ]
then
echo "No arguments supplied. It should be the detector number type (0=SURF 1=SIFT 2=ORB 3=FAST/FREAK 4=FAST/BRIEF 5=GFTT/FREAK 6=GFTT/BRIEF 7=BRISK 8=GFTT/ORB 9=KAZE 10=ORB-OCTREE 11=SuperPoint)."
exit
fi
TYPE=$1
SKIP=0
if [ $# -eq 2 ]
then
SKIP=$2
fi
PREFIX="/home/mathieu/workspace/rtabmap_cv_latest/bin/"
REPROCESS_TOOL="${PREFIX}rtabmap-reprocess"
DETECT_MORE_LOOP_CLOSURE_TOOL="${PREFIX}rtabmap-detectMoreLoopClosures"
DATABASES="$SKIP/$TYPE/map_190321-164651.db;$SKIP/$TYPE/map_190321-172717.db;$SKIP/$TYPE/map_190321-175428.db;$SKIP/$TYPE/map_190321-182709.db;$SKIP/$TYPE/map_190321-185608.db;$SKIP/$TYPE/map_190321-193556.db"
$REPROCESS_TOOL --uwarn --RGBD/OptimizeMaxError 0 "$DATABASES" $SKIP/$TYPE/merged_9999.db
$DETECT_MORE_LOOP_CLOSURE_TOOL $SKIP/$TYPE/merged_9999.db
#$REPROCESS_TOOL --uwarn --RGBD/OptimizeMaxError 0 --Mem/ReduceGraph true --Vis/MinInliers 60 "$DATABASES" $SKIP/$TYPE/merged_9999_reduced.db
#$DETECT_MORE_LOOP_CLOSURE_TOOL $SKIP/$TYPE/merged_9999_reduced.db
$REPROCESS_TOOL --uwarn --RGBD/OptimizeMaxError 0 "$SKIP/$TYPE/map_190321-164651.db;$SKIP/$TYPE/map_190321-193556.db" $SKIP/$TYPE/merged_16.db
$DETECT_MORE_LOOP_CLOSURE_TOOL $SKIP/$TYPE/merged_16.db
$REPROCESS_TOOL --uwarn --RGBD/OptimizeMaxError 0 "$SKIP/$TYPE/map_190321-164651.db;$SKIP/$TYPE/map_190321-175428.db;$SKIP/$TYPE/map_190321-185608.db" $SKIP/$TYPE/merged_135.db
$DETECT_MORE_LOOP_CLOSURE_TOOL $SKIP/$TYPE/merged_135.db
$REPROCESS_TOOL --uwarn --RGBD/OptimizeMaxError 0 "$SKIP/$TYPE/map_190321-172717.db;$SKIP/$TYPE/map_190321-182709.db;$SKIP/$TYPE/map_190321-193556.db" $SKIP/$TYPE/merged_246.db
$DETECT_MORE_LOOP_CLOSURE_TOOL $SKIP/$TYPE/merged_246.db

View File

@@ -1,19 +0,0 @@
#!/bin/bash
SKIP=0
if [ $# -eq 1 ]
then
SKIP=$1
fi
DETECTOR=(0 1 6 7 8 9 11 12 14)
PREFIX="/home/mathieu/workspace/rtabmap_cv_latest/bin/"
REPORT_TOOL="${PREFIX}rtabmap-report"
for d in "${DETECTOR[@]}"
do
valgrind --tool=massif --time-unit=ms --detailed-freq=1 --max-snapshots=100 ${PREFIX}rtabmap-reprocess --Mem/IncrementalMemory false --Kp/IncrementalFlann false "${SKIP}/${d}/merged_9999.db;map_190321-164651.db" output.db
rm output.db
done

View File

@@ -0,0 +1,106 @@
## Multi-Session Visual SLAM for Illumination Invariant Re-Localization in Indoor Environments
* Paper: https://doi.org/10.3389/frobt.2022.801886
* The setup: we did 6 mapping sessions at dusk to evaluate how well RTAB-Map can localize (only by vision) on maps taken at different illumination conditions. The data has been collected with [RTAB-Map Tango](https://play.google.com/store/apps/details?id=com.introlab.rtabmap&hl=en_CA&gl=US).
![Overview](https://github.com/introlab/rtabmap/raw/master/archive/2022-IlluminationInvariant/images/fig_overview.jpg)
## Description
This folder contains scripts to re-generate results from the paper. The main idea behind this work is that using multi-session mapping can help to localize visually in illumination changing environments even with features that are not very robust to such conditions. We compared common hand-made visual features like SIFT, SURF, BRIEF, BRISK, FREAK, DAISY, KAZE with learned descriptor SuperPoint. The following picture show how robust are the visual features tested when localizing against single session recorded at different time. For example, the bottom-left and top-right cells are when the robot tries to localize the night on a map taken the day or vice-versa. The diagonal is localization performance when the localization session is about the same time than when the map was recorded. SuperPoint has clearly an advantage on this single-session experiment.
![All sessions](https://github.com/introlab/rtabmap/raw/master/archive/2022-IlluminationInvariant/images/fig_single_percentage.jpg)
The following image shows when we do the same localization experiment at different hours, but against maps created by assembling maps taken at different hours. In this case, we can see that even binary features like BRIEF can work relatively well in illumination-variant environments. See the paper for more detailled results and comments. The line `1+2+3+4+5+6` refers to the assembled map shown below containing all mapping sessions linked together in same database.
![All sessions](https://github.com/introlab/rtabmap/raw/master/archive/2022-IlluminationInvariant/images/fig_merged_percentage.jpg)
![All sessions](https://github.com/introlab/rtabmap/raw/master/archive/2022-IlluminationInvariant/images/fig_map_merged_999.jpg)
## Dataset
We provide two formats: the first one is more general and the second one is used to produce the results in this paper with RTAB-Map. Please open issue if the links are outdated.
* [Images](https://drive.google.com/file/d/1fUm1m8oW6q8qlThx7BjrBH2vrVbNQ9bQ/view?usp=drive_link):
* `rgb`: folder containing *.jpg color camera images
* `depth`: folder containing *.png 16bits mm depth images
* `calib`: folder containing calibration for each color image. Each calibration contains also the transform between `device` and `camera` frames as `local_transform`.
* `device_poses.txt`: VIO poses of each image in `device` frame
* `camera_poses.txt`: VIO poses of each image in `camera` frame
* [RTAB-Map Databases](https://drive.google.com/file/d/1TklUcTKFSrcg8b0t0U80G_IpFRMVRlY5/view?usp=drive_link)
* Dataset now also available on [Federated Research Data Repository (FRDR)](https://doi.org/10.20383/103.0931) (if links above don't work)
## How reproduce results shown in the paper
1. RTAB-Map should be built from source with those dependencies (don't need to "install" it, we will launch it from build directory in the scripts below to avoid conflicting with another rtabmap already installed):
* Use Ubuntu 20.04+ to avoid any python2/python3 conflicts.
* OpenCV built with **xfeatures2d** and **nonfree** modules
* [torchlib c++](https://pytorch.org/get-started/locally/) (tested on v1.10.2) to enable [SuperPoint](https://github.com/magicleap/SuperPointPretrainedNetwork)
* Git clone [SuperGlue](https://github.com/magicleap/SuperGluePretrainedNetwork) into scripts directory.
* Generate `superpoint_v1.pt` in the scripts directory (can also be downloaded from [here](https://github.com/KinglittleQ/SuperPoint_SLAM/blob/master/superpoint.pt) but may not be compatible with more recent pytorch versions):
```bash
cd rtabmap/archive/2022-IlluminationInvariant/scripts
wget https://github.com/magicleap/SuperPointPretrainedNetwork/raw/master/superpoint_v1.pth
wget https://raw.githubusercontent.com/magicleap/SuperPointPretrainedNetwork/master/demo_superpoint.py
python trace.py
```
2. Download databases of the dataset and extract them.
3. Adjust the path inside `rtabmap_latest.sh` script to match where you just built rtabmap with right dependencies.
4. Run `run_all.sh DATABASES_PATH OUTPUT_PATH`, this script will do the following steps (warning, this could take hours to do...):
* Recreate the map databases for each feature type
* Create the merged databases
* Run localization databases over all map/merged databases
* Run consecutive localization experiment
5. Export statistics with `export_stats.sh` script.
6. Use the MatLab/Octave scripts in this folder to show results you want. Set `dataDir` to directory containing the exported statistics.
```
sudo apt install install octave liboctave-dev
# In octave:
pkg install -forge control signal
```
### Docker
1. Create the docker image:
```
cd rtabmap
docker build -t rtabmap_frontiers -f docker/frontiers2022/Dockerfile .
```
2. Assuming you extracted the databases of the dataset in `~/Downloads/Illumination_invariant_databases`, create an output directory for results:
```
mkdir ~/Downloads/Illumination_invariant_databases/results
```
3. Run script:
```
docker run --gpus all -it --rm --ipc=host --runtime=nvidia \
--user $(id -u):$(id -g) \
-w=/workspace/scripts \
-v ~/Downloads/Illumination_invariant_databases:/workspace/databases \
-v ~/Downloads/Illumination_invariant_databases/results:/workspace/results \
rtabmap_frontiers /workspace/scripts/run_all.sh /workspace/databases /workspace/results
```
4. Export statistics:
```
docker run --gpus all -it --rm --ipc=host --runtime=nvidia \
--env="DISPLAY=$DISPLAY" \
--env="QT_X11_NO_MITSHM=1" \
--volume="/tmp/.X11-unix:/tmp/.X11-unix:rw" \
--env="XAUTHORITY=$XAUTH" \
--volume="$XAUTH:$XAUTH" \
--user $(id -u):$(id -g) \
-w=/workspace/results \
-v ~/Downloads/Illumination_invariant_databases/results:/workspace/results \
rtabmap_frontiers /workspace/scripts/export_stats.sh /workspace/results
```

View File

Before

Width:  |  Height:  |  Size: 224 KiB

After

Width:  |  Height:  |  Size: 224 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 266 KiB

View File

Before

Width:  |  Height:  |  Size: 253 KiB

After

Width:  |  Height:  |  Size: 253 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 282 KiB

View File

@@ -2,24 +2,35 @@
clear all
close all
# sudo apt install octave-signal
pkg load signal
# rtabmap-report --loc 32 Loop/Odom_correction_norm/m Loop/Visual_inliers/ Timing/Total/ms . Keypoint/Current_frame/words
# Right-click on thr legend of the figure, copy all data to clipboard
# Paste in correction#.txt, inliers#.txt and time#.txt where # is the
# number of the descriptor used
# Use with files generated by export_stats.sh
skipFrameDir = '0';
prefix = 'Stat';
RAMaddOverhead = 1;
dataDir = 'SET_PATH_TO_RESULTS_DIR';
resultsToShow = 1; % 1=single 2=Consecutive
prefix = 'Stat';
RAMaddOverhead = 0;
% Inliers_ratio = 'Loop/Visual_inliers/' ./ 'Keypoint/Current_frame/words'
% Odometry_average = 'Memory/Distance_travelled/m'(2:end) - 'Memory/Distance_travelled/m'(1:end-1)
statNames = {'Loop/Odom_correction_norm/m', 'Inliers_ratio_%', 'Timing/Total/ms', 'Memory/RAM_usage/MB', 'Memory/RAM_estimated/MB', 'Keypoint/Current_frame/words', 'Loop/Map_id/'}; % 'Odometry_average'
datasets = [ 0 1 6 7 9 12 14 11]; % 0 1 6 7 8 9 11 12
statNames = {'Loop/Odom_correction_norm/m', 'Loop/Visual_inliers/', 'Inliers_ratio_%', 'Timing/Total/ms', 'Memory/RAM_usage/MB', 'Memory/RAM_estimated/MB', 'Keypoint/Current_frame/words', 'Loop/Map_id/', 'Memory/Local_graph_size/', 'Keypoint/Dictionary_size/words', 'Loop/Distance_since_last_loc/'}; % 'Odometry_average'
datasets = [ 0 1 6 7 9 14 11 111 ]; % 0 1 6 7 9 12 14 11
sep = [0, 1000, 3000, 5000, 7000, 9000, 12000];
sepName = {'16:51', '17:31', '17:58', '18:30', '18:59', '19:42'};
if resultsToShow == 2
sep = [0, 1000, 3000, 5000, 7000, 9000];
sepName = {'17:27', '17:54', '18:27', '18:56', '19:35'};
prefix = 'Consecutive';
statNames = {'Loop/Distance_since_last_loc/', 'Distance_since_last_loc_under_50cm'};
endif
MapsN = length(sepName);
allCumResults = {};
allMaxResults = {};
@@ -35,13 +46,15 @@ statName = strrep(statNames{s},'/','-');
for d=1:length(datasets)
if strcmp(statName,'Inliers_ratio_%')
data = dlmread([skipFrameDir '/' prefix num2str(datasets(d)) '-' 'Loop-Visual_inliers-' '.txt'], '\t', 1, 0, "emptyvalue", 0);
dataWords = dlmread([skipFrameDir '/' prefix num2str(datasets(d)) '-' 'Keypoint-Current_frame-words' '.txt'], '\t', 1, 0, "emptyvalue", 0);
data = dlmread([dataDir '/' prefix num2str(datasets(d)) '-' 'Loop-Visual_inliers-' '.txt'], '\t', 1, 0, "emptyvalue", 0);
dataWords = dlmread([dataDir '/' prefix num2str(datasets(d)) '-' 'Keypoint-Current_frame-words' '.txt'], '\t', 1, 0, "emptyvalue", 0);
data(:, 2:end) = data(:, 2:end) ./ dataWords(:, 2:end) * 100;
elseif strcmp(statName, 'Odometry_average')
data = dlmread([skipFrameDir '/' prefix num2str(datasets(d)) '-' 'Memory-Distance_travelled-m' '.txt'], '\t', 1, 0, "emptyvalue", 0);
data = dlmread([dataDir '/' prefix num2str(datasets(d)) '-' 'Memory-Distance_travelled-m' '.txt'], '\t', 1, 0, "emptyvalue", 0);
elseif strcmp(statName, 'Distance_since_last_loc_under_50cm')
data = dlmread([dataDir '/' prefix num2str(datasets(d)) '-' 'Loop-Distance_since_last_loc-' '.txt'], '\t', 1, 0, "emptyvalue", 0);
else
data = dlmread([skipFrameDir '/' prefix num2str(datasets(d)) '-' statName '.txt'], '\t', 1, 0, "emptyvalue", 0);
data = dlmread([dataDir '/' prefix num2str(datasets(d)) '-' statName '.txt'], '\t', 1, 0, "emptyvalue", 0);
endif
sessions = size(data,2)-1;
@@ -69,7 +82,7 @@ for i = 1:sessions
if datasets(d) == 7
%% 135 MB overhead for BRISK kernel
y = y + 135;
elseif datasets(d) == 11
elseif datasets(d) == 11 || datasets(d) == 111
%% 645 MB (library cuda) + 800 MB (network) for SuperPoint
y = y + 645+800;
elseif datasets(d) == 13 || datasets(d) == 14
@@ -81,6 +94,12 @@ for i = 1:sessions
if strcmp(statName, 'Loop-Map_id-')
nonzeros = y;
end
if strcmp(statName, 'Distance_since_last_loc_under_50cm')
y(y>0.55) = 0;
y(isnan(y)) = 0;
y(y>0) = 1;
nonzeros = y;
end
if length(nonzeros) > 0
avgValue = sum(nonzeros)/length(nonzeros);
avgResultsTmp(i,j) = avgValue;
@@ -103,7 +122,7 @@ for d=1:length(datasets)
if sum(totalResults{1,d}, 2)
cumResults(2:end-1,d+1) = sum(absResults{1,d}, 2) ./ sum(totalResults{1,d}, 2);
endif
cumResults(end,d+1) = sum(sum(absResults{1,d}(1:6,1:6).*eye(6,6))) / sum(sum(totalResults{1,d}(1:6,1:6).*eye(6,6)));
cumResults(end,d+1) = sum(sum(absResults{1,d}(1:MapsN,1:MapsN).*eye(MapsN,MapsN))) / sum(sum(totalResults{1,d}(1:MapsN,1:MapsN).*eye(MapsN,MapsN)));
end
cumResults(2:end-1,1) = 1:sessions;
@@ -123,7 +142,7 @@ for d=1:length(datasets)
if sum(totalResults{1,d}, 2)
cumMaxResults(2:end-1,d+1) = max(maxResults{1,d}, [], 2);
endif
cumMaxResults(end,d+1) = max(max(maxResults{1,d}(1:6,1:6).*eye(6,6)));
cumMaxResults(end,d+1) = max(max(maxResults{1,d}(1:MapsN,1:MapsN).*eye(MapsN,MapsN)));
end
cumMaxResults(2:end-1,1) = 1:sessions;
@@ -133,3 +152,18 @@ allMaxResults{2,s} = cumMaxResults;
endfor % statNames
if resultsToShow == 2
disp('30min')
for d=1:length(datasets)
round(sum(absResults{1,d} .* eye(5,5)) / sum(totalResults{1,d} .*eye(5,5)) * 100)
endfor
disp('60min')
for d=1:length(datasets)
round(sum(absResults{1,d} .* [[0;0;0;0] eye(4,4) ; [0 0 0 0 0]]) / sum(totalResults{1,d} .*[[0;0;0;0] eye(4,4) ; [0 0 0 0 0]]) * 100)
endfor
disp('120min')
for d=1:length(datasets)
round(avgResults{1,d}(1,5) * 100)
endfor
endif

View File

@@ -4,16 +4,15 @@ clear all
pkg load signal
# rtabmap-report --loc 32 Loop/Map_id/ loc
# Right-click on thr legend of the figure, copy all data to clipboard
# Paste in data#.txt where # is the number of the descriptor used
# Use with files generated by export_stats.sh
dataDir = 'SET_PATH_TO_RESULTS_DIR';
resultsToShow = 1; % 1=single loc, 2=merged loc, 3=consecutive
skipFrameDir = '0';
datasetPrefix = 'Stat';
datasets = [0 1 6 7 9 12 14 11]; % 0 1 6 7 8 9 11 12
datasets = [0 1 6 7 9 14 11 111]; % 0 1 6 7 8 9 11 12
datasetsName = {'SURF' 'SIFT' 'ORB' 'FAST/FREAK' 'FAST/BRIEF' 'GFTT/FREAK' 'GFTT/BRIEF' 'BRISK' 'GFTT/ORB' 'KAZE' 'ORB-OCTREE' 'SuperPoint' 'SURF/FREAK' 'GFTT/DAISY' 'SURF/DAISY'};
datasetsName{112} = 'SuperGlue'
sep = [0, 1000, 3000, 5000, 7000, 9000, 12000];
sepName = {'16:51', '17:31', '17:58', '18:30', '18:59', '19:42'};
@@ -41,13 +40,13 @@ globalc = [];
for d=1:length(datasets)
data = dlmread([skipFrameDir '/' datasetPrefix num2str(datasets(d)) '-Loop-Map_id-' '.txt'], '\t', 1, 0, "emptyvalue", NaN);
data = dlmread([dataDir '/' datasetPrefix num2str(datasets(d)) '-Loop-Map_id-' '.txt'], '\t', 1, 0, "emptyvalue", NaN);
curvesBeg = 2;
curvesEnd = size(data,2)-4;
curvesEnd = size(data,2)-5; % -4 for '0', -5 for '1'
if resultsToShow == 2
curvesBeg = 8;
curvesBeg = 8; % 2 if only 4 merged_reduced in stats, 8 to skip first 6
curvesEnd = size(data,2);
elseif resultsToShow == 3
curvesEnd = size(data,2);
@@ -198,7 +197,24 @@ for d=1:length(datasets)
data=percentResults{1,d}*100;
data(isnan(data)) = 0;
hAxes = gca;
imagesc( hAxes, data, [0, 100])
% Upscaling the image to reduce anti-aliasing effect in pfd viewers
scale = 50;
tickXStep = zeros(1, size(data, 2));
tickYStep = zeros(1, size(data, 1));
dataUp = upsample(upsample(data',scale)',scale);
for x=0:size(data, 2)-1
for y=1:scale-1
dataUp(:,(x*scale+1)+y) = dataUp(:,x*scale+1);
endfor
tickXStep(1,x+1) = scale/2 + scale*x;
endfor
for x=0:size(data, 1)-1
for y=1:scale-1
dataUp((x*scale+1)+y,:) = dataUp(x*scale+1,:);
endfor
tickYStep(1,x+1) = scale/2 + scale*x;
endfor
imagesc( hAxes, dataUp, [0, 100])
%title({"",datasetsName{datasets(d)+1}})
colors = [ones(100,1) [1:100]'*0.01 [1:100]'*0];
colors(1,:) = 1;
@@ -211,12 +227,14 @@ for d=1:length(datasets)
ylabel("Map")
endif
xlabel([datasetsName{datasets(d)+1} " Localization"])
set (gca, "xaxislocation", "top");
set(gca, "xaxislocation", "top");
set(gca, 'XTick', tickXStep)
set(gca, 'XTickLabel', sepName, 'fontsize',7)
set(gca, 'YTick', tickYStep)
if resultsToShow == 3
set(gca, 'YTickLabel', {'16:46', '17:27', '17:54', '18:27', '18:56'}, 'fontsize',7)
elseif resultsToShow == 2
set(gca, 'YTickLabel', {'1+6', '1+3+5', '2+4+6', '1+2+3+4+6', 'bundle', 'reduced'}, 'fontsize',7)
set(gca, 'YTickLabel', {'1+6', '1+3+5', '2+4+6', '1+2+3+4+5+6', '1-2-3-4-5-6', 'not set'}, 'fontsize',7)
else
set(gca, 'YTickLabel', {'16:46', '17:27', '17:54', '18:27', '18:56', '19:35'}, 'fontsize',7)
endif
@@ -232,4 +250,4 @@ for d=1:length(datasets)
endif
end
cumResults(2:end-1,1) = 1:curves;
cumResults
cumResults

View File

@@ -0,0 +1,109 @@
clear all
close all
# sudo apt install octave-signal
pkg load signal
# Use with files generated by export_stats.sh
dataDir = 'SET_PATH_TO_RESULTS_DIR';
prefix = 'Stat';
dataset = 6
sep = [0, 1000, 3000, 5000, 7000, 9000, 12000];
sepName = {'16:51', '17:31', '17:58', '18:30', '18:59', '19:42'};
statName = strrep('Loop/Distance_since_last_loc/','/','-');
data = dlmread([dataDir '/' prefix num2str(dataset) '-' statName '.txt'], '\t', 1, 0, "emptyvalue", 0);
sessions = size(data,2)-1
j = 1 % session #
x3 = data(:,1);
y3 = data(:,11);
y3 = y3(x3>=sep(j) & x3<=sep(j+1), :);
x3 = x3(x3>=sep(j) & x3<=sep(j+1), :);
max = 0;
for i=2:length(y3)
if isfinite(y3(i)) && isfinite(y3(i-1)) && (x3(i) - x3(i-1) < 1.5)
v = y3(i);
if v>max
max = v
endif
endif
endfor
xb = max/2:max:5;
[nn3, xx3] = hist (y3, xb);
nn3 = nn3/length(x3);
nn3(nn3==0) = NaN;
for j=1:6
x{j} = data(:,1);
y{j} = data(:,2);
y{j} = y{j}(x{j}>=sep(j) & x{j}<=sep(j+1), :);
x{j} = x{j}(x{j}>=sep(j) & x{j}<=sep(j+1), :);
[nn{j}, xx{j}] = hist (y{j}, xb);
%nn{j} = nn{j}/length(x{j});
%nn{j} = nn{j}/sum(nn{j});
for k=length(nn{j}):-1:1
if nn{j}(k) != 0
break;
else
nn{j}(k) = NaN;
endif
endfor
endfor
j = 6 % session #
x4 = data(:,1);
y4 = data(:,12);
y4 = y4(x4>=sep(j) & x4<=sep(j+1), :);
x4 = x4(x4>=sep(j) & x4<=sep(j+1), :);
[nn4, xx4] = hist (y4, xb);
nn4 = nn4/length(x4);
nn4(nn4==0) = NaN;
figure
hold on
%plot(x1,y1, '.-');
%plot(x2-x2(1),y2, '.-');
plot(x3-x3(1),y3, '.-');
%plot(x4-x4(1),y4, '.-');
%legend('Map1 -> LocA', 'Map1 -> LocF', 'Map1+2+3+4+5+6 -> LocF', 'Map1-2-3-4-5-6 -> LocF')
legend('Map1+2+3+4+5+6 -> LocA')
xlabel('Time')
ylabel('m')
title('Distance since last loc')
figure
hold on
%plot(x1,y1, '.-');
%plot(x2-x2(1),y2, '.-');
plot(x{6}-x{6}(1),y{6}, '.-');
%plot(x4-x4(1),y4, '.-');
%legend('Map1 -> LocA', 'Map1 -> LocF', 'Map1+2+3+4+5+6 -> LocF', 'Map1-2-3-4-5-6 -> LocF')
legend('Map1 -> LocF')
xlabel('Time')
ylabel('m')
title('Distance since last loc')
figure
hold on
for j=1:6
plot(xx{j},nn{j}, '-', 'linewidth', 3)
endfor
%plot(xx3,nn3, '.-', 'linewidth', 3)
%plot(xx4,nn4, '.-', 'linewidth', 3)
%legend('Loc-F', 'Loc-E', 'Loc-D', 'Loc-C', 'Loc-B', 'Loc-A')
legend('A-16:51', 'B-17:31', 'C-17:58', 'D-18:30', 'E-18:59', 'F-19:42', 'Map1+2+3+4+5+6 -> LocF', 'Map1-2-3-4-5-6 -> LocF')
%h = get(gca,'Children');
%set(gca,'Children',[h(6) h(5) h(4) h(3) h(2) h(1)])
%set(gca, 'YScale', 'log')
xlabel(['Distance not localized (m) Step ' num2str(max) ' m'])
ylabel('Re-Localization Probability on Map 1 (16:46)')

View File

@@ -0,0 +1,19 @@
#!/bin/bash
if [ $# -lt 1 ]
then
echo "No arguments supplied. It should be the data directory (where the reprocessed map databases are saved)."
exit
fi
DATA=$1
DETECTOR=(0 1 6 7 9 14 11 111)
source rtabmap_latest.bash
for d in "${DETECTOR[@]}"
do
rtabmap-report --export --export_prefix "Stat$d" --loc 32 Loop/Odom_correction_norm/m Loop/Visual_inliers/ Timing/Total/ms Timing/Proximity_by_space_visual/ms Timing/Likelihood_computation/ms Timing/Posterior_computation/ms TimingMem/Keypoints_detection/ms TimingMem/Descriptors_extraction/ms TimingMem/Add_new_words/ms Loop/Map_id/ Keypoint/Current_frame/words Memory/RAM_usage/MB Memory/RAM_estimated/MB Memory/Distance_travelled/m Loop/Distance_since_last_loc/ Memory/Local_graph_size/ Keypoint/Dictionary_size/words "$DATA/$d/loc"
rtabmap-report --export --export_prefix "Consecutive$d" --loc 32 Loop/Map_id/ Loop/Distance_since_last_loc/ "$DATA/$d/consecutive_loc"
done

View File

@@ -0,0 +1,41 @@
#!/bin/bash
if [ $# -lt 3 ]
then
echo "No arguments supplied. They should be 3: the detector number type (0=SURF 1=SIFT 2=ORB 3=FAST/FREAK 4=FAST/BRIEF 5=GFTT/FREAK 6=GFTT/BRIEF 7=BRISK 8=GFTT/ORB 9=KAZE 10=ORB-OCTREE 11=SuperPoint), the input directory (original maps) and the output data directory (where reprocessed map databases will be saved)."
exit
fi
TYPE=$1
INPUT=$2
OUTPUT=$3
source rtabmap_latest.bash
[ ! -d "$OUTPUT" ] && mkdir $OUTPUT
[ ! -d "$OUTPUT/$TYPE" ] && mkdir $OUTPUT/$TYPE
# 'map_190321-164651.db' 'map_190321-172717.db' 'map_190321-175428.db' 'map_190321-182709.db' 'map_190321-185608.db' 'map_190321-193556.db'
DATABASES=( 'map_190321-164651.db' 'map_190321-172717.db' 'map_190321-175428.db' 'map_190321-182709.db' 'map_190321-185608.db' 'map_190321-193556.db' )
PARAMS="--Kp/DetectorStrategy $TYPE --Vis/FeatureType $TYPE"
if [ $TYPE -eq 2 ] || [ $TYPE -eq 3 ] || [ $TYPE -eq 4 ] || [ $TYPE -eq 5 ] || [ $TYPE -eq 6 ] || [ $TYPE -eq 7 ] || [ $TYPE -eq 8 ] || [ $TYPE -eq 10 ] || [ $TYPE -eq 12 ]
then
# binary descriptors
PARAMS="--Vis/CorNNDR 0.8 $PARAMS"
else
# float descriptors
PARAMS="--Vis/CorNNDR 0.6 $PARAMS"
fi
if [ $TYPE -eq 111 ]
then
PARAMS="--Vis/CorNNType 6 --SuperGlue/Path SuperGluePretrainedNetwork/rtabmap_superglue.py --Reg/RepeatOnce false --Vis/CorGuessWinSize 0 $PARAMS --Kp/DetectorStrategy 11 --Vis/FeatureType 11"
fi
echo $PARAMS
for db in "${DATABASES[@]}"
do
rtabmap-reprocess --RGBD/MarkerDetection false --RGBD/ProximityBySpace true --RGBD/LocalRadius 1 --Mem/InitWMWithAllNodes true --Rtabmap/TimeThr 0 --Mem/UseOdomFeatures false --Optimizer/GravitySigma 0.1 --Mem/UseOdomGravity true --RGBD/OptimizeFromGraphEnd false --Mem/DepthAsMask false --RGBD/OptimizeMaxError 0 --RGBD/ProximityOdomGuess false --Vis/MaxFeatures 1000 --Kp/MaxFeatures 400 --Vis/EpipolarGeometryVar 0.1 --Vis/EstimationType 1 --Vis/MinInliers 20 --Rtabmap/MaxRetrieved 2 --Optimizer/Iterations 20 --Mem/CompressionParallelized true --Kp/Parallelized true --Kp/MaxDepth 0 --Kp/BadSignRatio 0.2 --BRIEF/Bytes 32 --Kp/ByteToFloat true --SURF/HessianThreshold 100 --SIFT/ContrastThreshold 0.02 --BRISK/Thresh 10 --SuperPoint/ModelPath superpoint_v1.pt --Rtabmap/PublishRAMUsage true --ORB/EdgeThreshold 19 --ORB/ScaleFactor 2 --ORB/NLevels 3 --Db/TargetVersion "" --Icp/CorrespondenceRatio 0.1 --RGBD/MaxOdomCacheSize 0 --uwarn $PARAMS $INPUT/$db $OUTPUT/$TYPE/$db
rtabmap-detectMoreLoopClosures --uwarn $OUTPUT/$TYPE/$db
done

View File

@@ -0,0 +1,18 @@
#!/bin/bash
if [ $# -lt 2 ]
then
echo "No arguments supplied. They should be 2: the input directory (original maps) and the output data directory (where reprocessed map databases will be saved)."
exit
fi
INPUT=$1
OUTPUT=$2
DETECTOR=(0 1 6 7 9 14 11 111)
for d in "${DETECTOR[@]}"
do
./reprocess_maps.sh $d $INPUT $OUTPUT
./run_merge.sh $d $OUTPUT
done

View File

@@ -0,0 +1,5 @@
#!/bin/bash
export PATH=~/workspace/rtabmap/build/bin:$PATH
export LD_LIBRARY_PATH=~/workspace/rtabmap/build/lib:$LD_LIBRARY_PATH

View File

@@ -0,0 +1,14 @@
#!/bin/bash
if [ $# -lt 2 ]
then
echo "No arguments supplied. They should be 2: the input directory (original maps) and the output data directory (where reprocessed map databases will be saved)."
exit
fi
INPUT=$1
OUTPUT=$2
./reprocess_maps_all.sh $INPUT $OUTPUT
./run_localization_single_all.sh $INPUT $OUTPUT
./run_consecutive_localization_all.sh $OUTPUT

View File

@@ -0,0 +1,25 @@
#!/bin/bash
if [ $# -lt 2 ]
then
echo "No arguments supplied. It should be the detector number type (0=SURF 1=SIFT 2=ORB 3=FAST/FREAK 4=FAST/BRIEF 5=GFTT/FREAK 6=GFTT/BRIEF 7=BRISK 8=GFTT/ORB 9=KAZE 10=ORB-OCTREE 11=SuperPoint) and the data directory (where map databases have been reprocessed)."
exit
fi
TYPE=$1
DATA=$2
source rtabmap_latest.bash
SOURCE=('map_190321-164651.db' 'map_190321-172717.db' 'map_190321-175428.db' 'map_190321-182709.db' 'map_190321-185608.db')
TARGETS=($DATA/$TYPE'/map_190321-172717.db;'$DATA/$TYPE'/map_190321-175428.db;'$DATA/$TYPE'/map_190321-193556.db' $DATA/$TYPE'/map_190321-175428.db;'$DATA/$TYPE'/map_190321-182709.db;' $DATA/$TYPE'/map_190321-182709.db;'$DATA/$TYPE'/map_190321-185608.db' $DATA/$TYPE'/map_190321-185608.db;'$DATA/$TYPE'/map_190321-193556.db' $DATA/$TYPE'/map_190321-193556.db' )
[ ! -d "$DATA/$TYPE/consecutive_loc" ] && mkdir $DATA/$TYPE/consecutive_loc
for i in ${!SOURCE[@]}
do
db=${SOURCE[$i]}
loc_dbs=${TARGETS[$i]}
rtabmap-reprocess --Mem/IncrementalMemory false --RGBD/ProximityBySpace true --RGBD/ProximityMaxPaths 1 --Mem/LocalizationDataSaved true --Mem/BinDataKept false --RGBD/SavedLocalizationIgnored true --Kp/IncrementalFlann false --Vis/MinInliers 20 --Rtabmap/PublishRAMUsage true --RGBD/ProximityOdomGuess false --uwarn "$DATA/$TYPE/$db;$loc_dbs" $DATA/$TYPE/consecutive_loc/loc_$db
done

View File

@@ -0,0 +1,16 @@
#!/bin/bash
if [ $# -lt 1 ]
then
echo "No arguments supplied. It should be the data directory (where the reprocessed map databases will be saved)."
exit
fi
DATA=$1
DETECTOR=(0 1 6 7 9 14 11 111)
for d in "${DETECTOR[@]}"
do
./run_consecutive_localization.sh $d $DATA
done

View File

@@ -0,0 +1,33 @@
#!/bin/bash
if [ $# -lt 3 ]
then
echo "No arguments supplied. They should be 3: the detector number type (0=SURF 1=SIFT 2=ORB 3=FAST/FREAK 4=FAST/BRIEF 5=GFTT/FREAK 6=GFTT/BRIEF 7=BRISK 8=GFTT/ORB 9=KAZE 10=ORB-OCTREE 11=SuperPoint), the input directory (original maps) and the output data directory (where reprocessed map databases will be saved)."
exit
fi
TYPE=$1
INPUT=$2
OUTPUT=$3
source rtabmap_latest.bash
# loc_190321-165128.db;loc_190321-173134.db;loc_190321-175823.db;loc_190321-183051.db;loc_190321-185950.db;loc_190321-194226.db
LOCALIZATION_DATABASES="$INPUT/loc_190321-165128.db;$INPUT/loc_190321-173134.db;$INPUT/loc_190321-175823.db;$INPUT/loc_190321-183051.db;$INPUT/loc_190321-185950.db;$INPUT/loc_190321-194226.db"
[ ! -d "$OUTPUT/$TYPE/loc" ] && mkdir $OUTPUT/$TYPE/accuracy
db=merged_123456.db
rtabmap-reprocess --Mem/IncrementalMemory false --RGBD/ProximityBySpace true --Mem/LocalizationDataSaved true --Mem/BinDataKept false --RGBD/SavedLocalizationIgnored true --Kp/IncrementalFlann false --Vis/MinInliers 20 --Rtabmap/PublishRAMUsage true --RGBD/ProximityOdomGuess false --Reg/RepeatOnce true --Vis/BundleAdjustment 1 --uwarn "$OUTPUT/$TYPE/$db;$LOCALIZATION_DATABASES" $OUTPUT/$TYPE/accuracy/ProxOff_DoubleRegOn_BaOn_$db
rtabmap-reprocess --Mem/IncrementalMemory false --RGBD/ProximityBySpace true --Mem/LocalizationDataSaved true --Mem/BinDataKept false --RGBD/SavedLocalizationIgnored true --Kp/IncrementalFlann false --Vis/MinInliers 20 --Rtabmap/PublishRAMUsage true --RGBD/ProximityOdomGuess false --Reg/RepeatOnce false --Vis/BundleAdjustment 1 --uwarn "$OUTPUT/$TYPE/$db;$LOCALIZATION_DATABASES" $OUTPUT/$TYPE/accuracy/ProxOff_DoubleRegOff_BaOn_$db
rtabmap-reprocess --Mem/IncrementalMemory false --RGBD/ProximityBySpace true --Mem/LocalizationDataSaved true --Mem/BinDataKept false --RGBD/SavedLocalizationIgnored true --Kp/IncrementalFlann false --Vis/MinInliers 20 --Rtabmap/PublishRAMUsage true --RGBD/ProximityOdomGuess false --Reg/RepeatOnce true --Vis/BundleAdjustment 0 --uwarn "$OUTPUT/$TYPE/$db;$LOCALIZATION_DATABASES" $OUTPUT/$TYPE/accuracy/ProxOff_DoubleRegOn_BaOff_$db
rtabmap-reprocess --Mem/IncrementalMemory false --RGBD/ProximityBySpace true --Mem/LocalizationDataSaved true --Mem/BinDataKept false --RGBD/SavedLocalizationIgnored true --Kp/IncrementalFlann false --Vis/MinInliers 20 --Rtabmap/PublishRAMUsage true --RGBD/ProximityOdomGuess false --Reg/RepeatOnce false --Vis/BundleAdjustment 0 --uwarn "$OUTPUT/$TYPE/$db;$LOCALIZATION_DATABASES" $OUTPUT/$TYPE/accuracy/ProxOff_DoubleRegOff_BaOff_$db
rtabmap-reprocess --Mem/IncrementalMemory false --RGBD/ProximityBySpace true --Mem/LocalizationDataSaved true --Mem/BinDataKept false --RGBD/SavedLocalizationIgnored true --Kp/IncrementalFlann false --Vis/MinInliers 20 --Rtabmap/PublishRAMUsage true --RGBD/ProximityOdomGuess true --Reg/RepeatOnce true --Vis/BundleAdjustment 1 --uwarn "$OUTPUT/$TYPE/$db;$LOCALIZATION_DATABASES" $OUTPUT/$TYPE/accuracy/ProxOn_DoubleRegOn_BaOn_$db
rtabmap-reprocess --Mem/IncrementalMemory false --RGBD/ProximityBySpace true --Mem/LocalizationDataSaved true --Mem/BinDataKept false --RGBD/SavedLocalizationIgnored true --Kp/IncrementalFlann false --Vis/MinInliers 20 --Rtabmap/PublishRAMUsage true --RGBD/ProximityOdomGuess true --Reg/RepeatOnce true --Vis/BundleAdjustment 0 --uwarn "$OUTPUT/$TYPE/$db;$LOCALIZATION_DATABASES" $OUTPUT/$TYPE/accuracy/ProxOn_DoubleRegOn_BaOff_$db

View File

@@ -0,0 +1,28 @@
#!/bin/bash
if [ $# -lt 3 ]
then
echo "No arguments supplied. They should be 3: the detector number type (0=SURF 1=SIFT 2=ORB 3=FAST/FREAK 4=FAST/BRIEF 5=GFTT/FREAK 6=GFTT/BRIEF 7=BRISK 8=GFTT/ORB 9=KAZE 10=ORB-OCTREE 11=SuperPoint), the input directory (original maps) and the output data directory (where reprocessed map databases will be saved)."
exit
fi
TYPE=$1
INPUT=$2
OUTPUT=$3
source rtabmap_latest.bash
# 'map_190321-164651.db' 'map_190321-172717.db' 'map_190321-175428.db' 'map_190321-182709.db' 'map_190321-185608.db' 'map_190321-193556.db' 'merged_123456.db' 'merged_135.db' 'merged_246.db' 'merged_16.db' 'merged_123456_reduced.db'
DATABASES=('map_190321-164651.db' 'map_190321-172717.db' 'map_190321-175428.db' 'map_190321-182709.db' 'map_190321-185608.db' 'map_190321-193556.db' 'merged_123456.db' 'merged_135.db' 'merged_246.db' 'merged_16.db' 'merged_123456_reduced.db')
# loc_190321-165128.db;loc_190321-173134.db;loc_190321-175823.db;loc_190321-183051.db;loc_190321-185950.db;loc_190321-194226.db
LOCALIZATION_DATABASES="$INPUT/loc_190321-165128.db;$INPUT/loc_190321-173134.db;$INPUT/loc_190321-175823.db;$INPUT/loc_190321-183051.db;$INPUT/loc_190321-185950.db;$INPUT/loc_190321-194226.db"
[ ! -d "$OUTPUT/$TYPE/loc" ] && mkdir $OUTPUT/$TYPE/loc
echo $PARAMS
for db in "${DATABASES[@]}"
do
rtabmap-reprocess -loc_null --Mem/IncrementalMemory false --RGBD/ProximityBySpace true --RGBD/ProximityMaxPaths 1 --Mem/LocalizationDataSaved true --Mem/BinDataKept false --RGBD/SavedLocalizationIgnored true --Kp/IncrementalFlann false --Vis/MinInliers 20 --Rtabmap/PublishRAMUsage true --RGBD/ProximityOdomGuess false --uwarn "$OUTPUT/$TYPE/$db;$LOCALIZATION_DATABASES" $OUTPUT/$TYPE/loc/loc_$db
done

View File

@@ -0,0 +1,17 @@
#!/bin/bash
if [ $# -lt 2 ]
then
echo "No arguments supplied. They should be 2: the input directory (original maps) and the output data directory (where reprocessed map databases will be saved)."
exit
fi
INPUT=$1
OUTPUT=$2
DETECTOR=(0 1 6 7 9 14 11 111)
for d in "${DETECTOR[@]}"
do
./run_localization_single.sh $d $INPUT $OUTPUT
done

View File

@@ -0,0 +1,34 @@
#!/bin/bash
if [ $# -lt 2 ]
then
echo "No arguments supplied. It should be the detector number type (0=SURF 1=SIFT 2=ORB 3=FAST/FREAK 4=FAST/BRIEF 5=GFTT/FREAK 6=GFTT/BRIEF 7=BRISK 8=GFTT/ORB 9=KAZE 10=ORB-OCTREE 11=SuperPoint) and the data directory (where map databases have been reprocessed)."
exit
fi
TYPE=$1
DATA=$2
MIN_INLIERS=20 #20 40 60 80
source rtabmap_latest.bash
DATABASES="$DATA/$TYPE/map_190321-164651.db;$DATA/$TYPE/map_190321-172717.db;$DATA/$TYPE/map_190321-175428.db;$DATA/$TYPE/map_190321-182709.db;$DATA/$TYPE/map_190321-185608.db;$DATA/$TYPE/map_190321-193556.db"
# To compute "Ground truth"
rtabmap-reprocess --uwarn "$DATABASES" $DATA/$TYPE/merged_123456.db
cp $DATA/$TYPE/merged_123456.db $DATA/$TYPE/merged_123456_gt.db
rtabmap-detectMoreLoopClosures -r 0.5 -i 5 $DATA/$TYPE/merged_123456_gt.db
rtabmap-reprocess --uwarn -gt $DATA/$TYPE/merged_123456_gt.db $DATA/$TYPE/merged_123456.db
rtabmap-reprocess --uwarn "$DATA/$TYPE/map_190321-164651.db;$DATA/$TYPE/map_190321-193556.db" $DATA/$TYPE/merged_16.db
rtabmap-reprocess --uwarn "$DATA/$TYPE/map_190321-164651.db;$DATA/$TYPE/map_190321-175428.db;$DATA/$TYPE/map_190321-185608.db" $DATA/$TYPE/merged_135.db
rtabmap-reprocess --uwarn "$DATA/$TYPE/map_190321-172717.db;$DATA/$TYPE/map_190321-182709.db;$DATA/$TYPE/map_190321-193556.db" $DATA/$TYPE/merged_246.db
# Reduced graph
rtabmap-reprocess --uwarn -gt --Mem/ReduceGraph true --Vis/MinInliers $MIN_INLIERS $DATA/$TYPE/merged_123456_gt.db $DATA/$TYPE/merged_123456_reduced.db

View File

@@ -0,0 +1,9 @@
import torch
import torchvision
from demo_superpoint import SuperPointNet
model = SuperPointNet()
model.load_state_dict(torch.load("superpoint_v1.pth"))
model.eval()
example = torch.rand(1, 1, 640, 480)
traced_script_module = torch.jit.trace(model, example)
traced_script_module.save("superpoint_v1.pt")

View File

@@ -0,0 +1,20 @@
#!/bin/bash
if [ $# -lt 2 ]
then
echo "No arguments supplied. They should be 2: the input directory (original maps) and the output data directory (where reprocessed map databases will be saved)."
exit
fi
INPUT=$1
OUTPUT=$2
DETECTOR=(0 1 6 7 9 14 11 111)
source rtabmap_latest.bash
for d in "${DETECTOR[@]}"
do
valgrind --tool=massif --time-unit=ms --detailed-freq=1 --max-snapshots=100 rtabmap-reprocess --Mem/IncrementalMemory false --Kp/IncrementalFlann false "${OUTPUT}/${d}/map_190321-164651.db;${INPUT}/loc_190321-165128.db" output.db
rm output.db
done

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