Compare commits

..
Author SHA1 Message Date
matlabbe 594498ddea initial commit 2025-06-16 08:30:00 -07:00
111 changed files with 3407 additions and 8443 deletions
-24
View File
@@ -1,24 +0,0 @@
FROM introlab3it/rtabmap:android-noble-deps
# remove ubuntu user
RUN touch /var/mail/ubuntu && chown ubuntu /var/mail/ubuntu && userdel -r ubuntu
RUN apt-get update && apt-get install -y sudo && \
apt-get clean && rm -rf /var/lib/apt/lists/
ARG USERNAME=vscode
ARG USER_UID=1000
ARG USER_GID=1000
RUN set -ex && \
groupadd --gid ${USER_GID} ${USERNAME} && \
useradd --uid ${USER_UID} --gid ${USER_GID} -m ${USERNAME} && \
usermod -a -G sudo ${USERNAME} && \
echo "${USERNAME} ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/${USERNAME} && \
chmod 0440 /etc/sudoers.d/${USERNAME}
RUN chmod +x /opt/android-sdk/tools/android
RUN echo "source /usr/share/bash-completion/completions/git" >> /home/${USERNAME}/.bashrc
+1 -13
View File
@@ -1,21 +1,9 @@
{ {
"build": { "image": "introlab3it/rtabmap:android-deps",
"dockerfile": "Dockerfile"
},
"customizations": { "customizations": {
"vscode": { "vscode": {
"extensions": ["ms-vscode.cpptools-themes", "ms-vscode.cmake-tools", "vscjava.vscode-java-pack"] "extensions": ["ms-vscode.cpptools-themes", "ms-vscode.cmake-tools", "vscjava.vscode-java-pack"]
} }
}, },
"workspaceMount": "source=${localWorkspaceFolder},target=/home/vscode/rtabmap,type=bind",
"workspaceFolder": "/home/vscode/rtabmap",
"postStartCommand": "./.devcontainer/android/init.sh",
"settings": {
"terminal.integrated.defaultProfile.linux": "bash"
},
"remoteUser": "vscode",
"runArgs": ["--privileged", "--network=host"] "runArgs": ["--privileged", "--network=host"]
} }
-17
View File
@@ -1,17 +0,0 @@
#!/bin/bash
set -e
echo "Running post-start initialization..."
# copy required jars
cp /opt/android/lib/*.jar app/android/libs/.
mkdir -p build_android/arm64-v8a
# resource tool
cd build_android
cmake -DANDROID_PREBUILD=ON ..
make
echo -e "\nTo build the APK, do (adjust API number):"
echo -e '\nexport ANDROID_API=30 && cd build_android/arm64-v8a && cmake -DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK/build/cmake/android.toolchain.cmake -DANDROID_ABI=arm64-v8a -DANDROID_NDK=$ANDROID_NDK -DANDROID_NATIVE_API_LEVEL=$ANDROID_API -DBUILD_SHARED_LIBS=OFF -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/opt/android/arm64-v8a -DCMAKE_FIND_ROOT_PATH="/opt/android/arm64-v8a/bin;/opt/android/arm64-v8a;/opt/android/arm64-v8a/share" -DBUILD_EXAMPLES=OFF -DBUILD_TOOLS=OFF -DOpenCV_DIR=/opt/android/arm64-v8a/sdk/native/jni ../..\nmake -j6\n'
-21
View File
@@ -1,21 +0,0 @@
FROM introlab3it/rtabmap:focal-deps
RUN apt-get update && apt-get install -y sudo && \
apt-get clean && rm -rf /var/lib/apt/lists/
ARG USERNAME=vscode
ARG USER_UID=1000
ARG USER_GID=1000
RUN set -ex && \
groupadd --gid ${USER_GID} ${USERNAME} && \
useradd --uid ${USER_UID} --gid ${USER_GID} -m ${USERNAME} && \
usermod -a -G sudo ${USERNAME} && \
echo "${USERNAME} ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/${USERNAME} && \
chmod 0440 /etc/sudoers.d/${USERNAME}
RUN mkdir -p /home/${USERNAME}/Documents/RTAB-Map && chown -R ${USERNAME} /home/${USERNAME}
RUN echo "source /usr/share/bash-completion/completions/git" >> /home/${USERNAME}/.bashrc
+2 -12
View File
@@ -1,18 +1,8 @@
{ {
"build": { "image": "introlab3it/rtabmap:20.04",
"dockerfile": "Dockerfile"
},
"customizations": { "customizations": {
"vscode": { "vscode": {
"extensions": ["ms-vscode.cpptools-themes", "ms-vscode.cmake-tools"] "extensions": ["ms-vscode.cpptools-themes", "ms-vscode.cmake-tools"]
} }
}, }
"workspaceMount": "source=${localWorkspaceFolder},target=/home/vscode/rtabmap,type=bind",
"workspaceFolder": "/home/vscode/rtabmap",
//"mounts": ["source=${localEnv:HOME}/Documents/RTAB-Map,target=/home/vscode/Documents/RTAB-Map,type=bind,consistency=cached"],
"settings": {
"terminal.integrated.defaultProfile.linux": "bash"
},
"remoteUser": "vscode",
"runArgs": ["--privileged", "--network=host"]
} }
-21
View File
@@ -1,21 +0,0 @@
FROM introlab3it/rtabmap:jammy-deps
RUN apt-get update && apt-get install -y sudo && \
apt-get clean && rm -rf /var/lib/apt/lists/
ARG USERNAME=vscode
ARG USER_UID=1000
ARG USER_GID=1000
RUN set -ex && \
groupadd --gid ${USER_GID} ${USERNAME} && \
useradd --uid ${USER_UID} --gid ${USER_GID} -m ${USERNAME} && \
usermod -a -G sudo ${USERNAME} && \
echo "${USERNAME} ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/${USERNAME} && \
chmod 0440 /etc/sudoers.d/${USERNAME}
RUN mkdir -p /home/${USERNAME}/Documents/RTAB-Map && chown -R ${USERNAME} /home/${USERNAME}
RUN echo "source /usr/share/bash-completion/completions/git" >> /home/${USERNAME}/.bashrc
+2 -12
View File
@@ -1,18 +1,8 @@
{ {
"build": { "image": "introlab3it/rtabmap:22.04",
"dockerfile": "Dockerfile"
},
"customizations": { "customizations": {
"vscode": { "vscode": {
"extensions": ["ms-vscode.cpptools-themes", "ms-vscode.cmake-tools"] "extensions": ["ms-vscode.cpptools-themes", "ms-vscode.cmake-tools"]
} }
}, }
"workspaceMount": "source=${localWorkspaceFolder},target=/home/vscode/rtabmap,type=bind",
"workspaceFolder": "/home/vscode/rtabmap",
//"mounts": ["source=${localEnv:HOME}/Documents/RTAB-Map,target=/home/vscode/Documents/RTAB-Map,type=bind,consistency=cached"],
"settings": {
"terminal.integrated.defaultProfile.linux": "bash"
},
"remoteUser": "vscode",
"runArgs": ["--privileged", "--network=host"]
} }
@@ -1,104 +0,0 @@
ARG ROS_DISTRO=jazzy
FROM osrf/ros:${ROS_DISTRO}-desktop
# Install build dependencies with Qt6 (issue: rtabmap has black window)
#RUN apt-get update && \
# apt-get install -y git software-properties-common ros-${ROS_DISTRO}-rtabmap-ros libqt6* qt6* qml6* && \
# apt-get remove -y ros-${ROS_DISTRO}-rtabmap* ros-${ROS_DISTRO}-gtsam ros-${ROS_DISTRO}-libg2o libpcl* libqt5* qt5* libvtk* libopencv* && \
# apt-get clean && rm -rf /var/lib/apt/lists/
# Install build dependencies with Qt5
RUN apt-get update && \
apt-get install -y git software-properties-common ros-${ROS_DISTRO}-rtabmap-ros && \
apt-get remove -y ros-${ROS_DISTRO}-rtabmap* ros-${ROS_DISTRO}-gtsam ros-${ROS_DISTRO}-libg2o libpcl* libvtk* libopencv* && \
apt-get clean && rm -rf /var/lib/apt/lists/
# remove ubuntu user
RUN touch /var/mail/ubuntu && chown ubuntu /var/mail/ubuntu && userdel -r ubuntu
RUN apt-get update && apt-get install -y sudo && \
apt-get clean && rm -rf /var/lib/apt/lists/
ARG USERNAME=vscode
ARG USER_UID=1000
ARG USER_GID=1000
RUN set -ex && \
groupadd --gid ${USER_GID} ${USERNAME} && \
useradd --uid ${USER_UID} --gid ${USER_GID} -m ${USERNAME} && \
usermod -a -G sudo ${USERNAME} && \
echo "${USERNAME} ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/${USERNAME} && \
chmod 0440 /etc/sudoers.d/${USERNAME}
RUN mkdir -p /home/${USERNAME}/Documents/RTAB-Map
RUN echo "source /usr/share/bash-completion/completions/git" >> /home/${USERNAME}/.bashrc
WORKDIR /home/${USERNAME}/
RUN rm /bin/sh && ln -s /bin/bash /bin/sh
# We build main dependencies from source, cleaning up the
# build directory after install but keeping the source code
# to change version/reinstall from inside the dev container
# if needed.
# Build latest VTK with Qt6
RUN git clone https://github.com/Kitware/VTK.git
RUN cd VTK && \
mkdir build && \
cd build && \
cmake -DVTK_GROUP_ENABLE_Qt=YES .. && \
make -j$(nproc) && \
make install && \
make clean
# Build latest PCL with latest VTK
# Make sure all libraries depending on Eigen are built with same CXX standard (17)
RUN git clone https://github.com/PointCloudLibrary/pcl.git
RUN cd pcl && \
mkdir build && \
cd build && \
cmake -DCMAKE_CXX_STANDARD=17 -DBUILD_tools=ON -DPCL_ENABLE_AVX=OFF -DPCL_ENABLE_MARCHNATIVE=OFF -DPCL_ENABLE_SSE=OFF .. && \
make -j$(nproc) && \
make install && \
make clean
# Build latest OpenCV
RUN git clone https://github.com/opencv/opencv.git
RUN git clone https://github.com/opencv/opencv_contrib.git
RUN cd opencv && \
mkdir build && \
cd build && \
cmake -DBUILD_opencv_python3=OFF -DBUILD_opencv_python_bindings_generator=OFF -DBUILD_opencv_python_tests=OFF -DBUILD_PERF_TESTS=OFF -DBUILD_TESTS=OFF -DOPENCV_ENABLE_NONFREE=ON -DOPENCV_EXTRA_MODULES_PATH=../../opencv_contrib/modules .. && \
make -j$(nproc) && \
make install && \
make clean
# Build latest gtsam
RUN git clone https://github.com/borglab/gtsam.git
RUN cd gtsam && \
mkdir build && \
cd build && \
cmake -DCMAKE_CXX_STANDARD=17 -DGTSAM_BUILD_WITH_MARCH_NATIVE=OFF -DGTSAM_BUILD_EXAMPLES_ALWAYS=OFF -DGTSAM_BUILD_TESTS=OFF -DGTSAM_BUILD_STATIC_LIBRARY=OFF -DGTSAM_BUILD_UNSTABLE=OFF -DGTSAM_INSTALL_CPPUNILITE=OFF -DGTSAM_USE_SYSTEM_EIGEN=ON -DCMAKE_BUILD_TYPE=Release .. && \
make -j$(nproc) && \
make install && \
make clean
# Build latest g2o
RUN git clone https://github.com/RainerKuemmerle/g2o.git
RUN cd g2o && \
mkdir build && \
cd build && \
cmake -DCMAKE_CXX_STANDARD=17 -DBUILD_WITH_MARCH_NATIVE=OFF -DG2O_BUILD_APPS=OFF -DG2O_BUILD_EXAMPLES=OFF -DG2O_USE_OPENGL=OFF -DCMAKE_BUILD_TYPE=Release .. && \
make -j$(nproc) && \
make install && \
make clean
# ros2 seems not sourcing by default its multi-arch folders
ENV LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/opt/ros/${ROS_DISTRO}/lib/x86_64-linux-gnu
RUN ldconfig
RUN chown -R ${USERNAME} /home/${USERNAME}
@@ -1,21 +0,0 @@
{
"build": {
"dockerfile": "Dockerfile",
"args": {
"ROS_DISTRO": "jazzy"
}
},
"customizations": {
"vscode": {
"extensions": ["ms-vscode.cpptools-themes", "ms-vscode.cmake-tools"]
}
},
"workspaceMount": "source=${localWorkspaceFolder},target=/home/vscode/rtabmap,type=bind",
"workspaceFolder": "/home/vscode/rtabmap",
//"mounts": ["source=${localEnv:HOME}/Documents/RTAB-Map,target=/home/vscode/Documents/RTAB-Map,type=bind,consistency=cached"],
"settings": {
"terminal.integrated.defaultProfile.linux": "bash"
},
"remoteUser": "vscode",
"runArgs": ["--privileged", "--network=host"]
}
-25
View File
@@ -1,25 +0,0 @@
FROM introlab3it/rtabmap:noble-deps
# For devcontainer
# remove ubuntu user
RUN touch /var/mail/ubuntu && chown ubuntu /var/mail/ubuntu && userdel -r ubuntu
RUN apt-get update && apt-get install -y sudo && \
apt-get clean && rm -rf /var/lib/apt/lists/
ARG USERNAME=vscode
ARG USER_UID=1000
ARG USER_GID=1000
RUN set -ex && \
groupadd --gid ${USER_GID} ${USERNAME} && \
useradd --uid ${USER_UID} --gid ${USER_GID} -m ${USERNAME} && \
usermod -a -G sudo ${USERNAME} && \
echo "${USERNAME} ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/${USERNAME} && \
chmod 0440 /etc/sudoers.d/${USERNAME}
RUN mkdir -p /home/${USERNAME}/Documents/RTAB-Map && chown -R ${USERNAME} /home/${USERNAME}
RUN echo "source /usr/share/bash-completion/completions/git" >> /home/${USERNAME}/.bashrc
+2 -12
View File
@@ -1,18 +1,8 @@
{ {
"build": { "image": "introlab3it/rtabmap:24.04",
"dockerfile": "Dockerfile"
},
"customizations": { "customizations": {
"vscode": { "vscode": {
"extensions": ["ms-vscode.cpptools-themes", "ms-vscode.cmake-tools"] "extensions": ["ms-vscode.cpptools-themes", "ms-vscode.cmake-tools"]
} }
}, }
"workspaceMount": "source=${localWorkspaceFolder},target=/home/vscode/rtabmap,type=bind",
"workspaceFolder": "/home/vscode/rtabmap",
//"mounts": ["source=${localEnv:HOME}/Documents/RTAB-Map,target=/home/vscode/Documents/RTAB-Map,type=bind,consistency=cached"],
"settings": {
"terminal.integrated.defaultProfile.linux": "bash"
},
"remoteUser": "vscode",
"runArgs": ["--privileged", "--network=host"]
} }
-79
View File
@@ -1,79 +0,0 @@
FROM ubuntu:24.04
ENV DEBIAN_FRONTEND=noninteractive
# Install ROS2
RUN apt update && \
apt install software-properties-common -y && \
add-apt-repository universe && \
apt update && \
apt install curl -y && \
curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key -o /usr/share/keyrings/ros-archive-keyring.gpg && \
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] http://packages.ros.org/ros2/ubuntu $(. /etc/os-release && echo $UBUNTU_CODENAME) main" | tee /etc/apt/sources.list.d/ros2.list > /dev/null && \
apt-get clean && rm -rf /var/lib/apt/lists/
# Install build dependencies
RUN apt-get update && \
apt upgrade -y && \
apt-get install -y \
git \
wget \
libtbb-dev \
libproj-dev \
libpcl-dev \
liboctomap-dev \
libfreenect-dev \
ros-rolling-ros-base \
ros-dev-tools \
ros-rolling-cv-bridge \
ros-rolling-image-geometry \
ros-rolling-laser-geometry \
ros-rolling-pcl-conversions \
ros-rolling-rviz-common \
ros-rolling-rviz-rendering \
ros-rolling-rviz-default-plugins \
ros-rolling-pcl-ros \
ros-rolling-imu-filter-madgwick \
ros-rolling-image-transport \
ros-rolling-octomap-msgs \
ros-rolling-libg2o \
ros-rolling-gtsam \
ros-rolling-libpointmatcher \
ros-rolling-qt-gui-cpp \
ros-rolling-diagnostic-updater && \
apt-get clean && rm -rf /var/lib/apt/lists/
WORKDIR /root/
RUN rm /bin/sh && ln -s /bin/bash /bin/sh
RUN echo -e '#!/bin/bash\nset -e\n\n# setup ros2 environment\nsource "/opt/ros/rolling/setup.bash" --\nexec "$@"' > /ros_entrypoint.sh
RUN chmod +x /ros_entrypoint.sh
ENTRYPOINT [ "/ros_entrypoint.sh" ]
# ros2 seems not sourcing by default its multi-arch folders
ENV LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/opt/ros/rolling/lib/x86_64-linux-gnu
# For devcontainer
# remove ubuntu user
RUN touch /var/mail/ubuntu && chown ubuntu /var/mail/ubuntu && userdel -r ubuntu
RUN apt-get update && apt-get install -y sudo && \
apt-get clean && rm -rf /var/lib/apt/lists/
ARG USERNAME=vscode
ARG USER_UID=1000
ARG USER_GID=1000
RUN set -ex && \
groupadd --gid ${USER_GID} ${USERNAME} && \
useradd --uid ${USER_UID} --gid ${USER_GID} -m ${USERNAME} && \
usermod -a -G sudo ${USERNAME} && \
echo "${USERNAME} ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/${USERNAME} && \
chmod 0440 /etc/sudoers.d/${USERNAME}
RUN mkdir -p /home/${USERNAME}/Documents/RTAB-Map && chown -R ${USERNAME} /home/${USERNAME}
RUN echo "source /usr/share/bash-completion/completions/git" >> /home/${USERNAME}/.bashrc
-18
View File
@@ -1,18 +0,0 @@
{
"build": {
"dockerfile": "Dockerfile"
},
"customizations": {
"vscode": {
"extensions": ["ms-vscode.cpptools-themes", "ms-vscode.cmake-tools"]
}
},
"workspaceMount": "source=${localWorkspaceFolder},target=/home/vscode/rtabmap,type=bind",
"workspaceFolder": "/home/vscode/rtabmap",
//"mounts": ["source=${localEnv:HOME}/Documents/RTAB-Map,target=/home/vscode/Documents/RTAB-Map,type=bind,consistency=cached"],
"settings": {
"terminal.integrated.defaultProfile.linux": "bash"
},
"remoteUser": "vscode",
"runArgs": ["--privileged", "--network=host"]
}
+2 -9
View File
@@ -19,26 +19,19 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
os: [ubuntu-24.04, ubuntu-22.04] os: [ubuntu-24.04, ubuntu-22.04]
include:
- os: ubuntu-22.04
extra_deps: "libunwind-dev libceres-dev"
extra_cmake_def: ""
- os: ubuntu-24.04
extra_deps: "libg2o-dev libceres-dev"
extra_cmake_def: "-DWITH_CERES=ON"
steps: steps:
- name: Install dependencies - name: Install dependencies
run: | run: |
DEBIAN_FRONTEND=noninteractive DEBIAN_FRONTEND=noninteractive
sudo apt-get update sudo apt-get update
sudo apt-get -y install libopencv-dev libpcl-dev git cmake software-properties-common libyaml-cpp-dev ${{ matrix.extra_deps }} sudo apt-get -y install libopencv-dev libpcl-dev git cmake software-properties-common libyaml-cpp-dev
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Configure CMake - name: Configure CMake
run: | run: |
cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} ${{ matrix.extra_cmake_def }} cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
- name: Build - name: Build
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}
+4 -4
View File
@@ -150,7 +150,7 @@ jobs:
API_VERSION=23 API_VERSION=23
docker_platforms: | docker_platforms: |
linux/amd64 linux/amd64
docker_path: 'noble/android/rtabmap_apiXX' docker_path: 'bionic/android/rtabmap_apiXX'
- docker_tag: android24 - docker_tag: android24
docker_tags: | docker_tags: |
introlab3it/rtabmap:android24 introlab3it/rtabmap:android24
@@ -158,7 +158,7 @@ jobs:
API_VERSION=24 API_VERSION=24
docker_platforms: | docker_platforms: |
linux/amd64 linux/amd64
docker_path: 'noble/android/rtabmap_apiXX' docker_path: 'bionic/android/rtabmap_apiXX'
- docker_tag: android26 - docker_tag: android26
docker_tags: | docker_tags: |
introlab3it/rtabmap:android26 introlab3it/rtabmap:android26
@@ -166,7 +166,7 @@ jobs:
API_VERSION=26 API_VERSION=26
docker_platforms: | docker_platforms: |
linux/amd64 linux/amd64
docker_path: 'noble/android/rtabmap_apiXX' docker_path: 'bionic/android/rtabmap_apiXX'
- docker_tag: android30 - docker_tag: android30
docker_tags: | docker_tags: |
introlab3it/rtabmap:android30 introlab3it/rtabmap:android30
@@ -174,7 +174,7 @@ jobs:
API_VERSION=30 API_VERSION=30
docker_platforms: | docker_platforms: |
linux/amd64 linux/amd64
docker_path: 'noble/android/rtabmap_apiXX' docker_path: 'bionic/android/rtabmap_apiXX'
steps: steps:
- -
+42 -98
View File
@@ -19,8 +19,8 @@ SET(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake_modules")
# VERSION # VERSION
####################### #######################
SET(RTABMAP_MAJOR_VERSION 0) SET(RTABMAP_MAJOR_VERSION 0)
SET(RTABMAP_MINOR_VERSION 23) SET(RTABMAP_MINOR_VERSION 22)
SET(RTABMAP_PATCH_VERSION 1) SET(RTABMAP_PATCH_VERSION 0)
SET(RTABMAP_VERSION SET(RTABMAP_VERSION
${RTABMAP_MAJOR_VERSION}.${RTABMAP_MINOR_VERSION}.${RTABMAP_PATCH_VERSION}) ${RTABMAP_MAJOR_VERSION}.${RTABMAP_MINOR_VERSION}.${RTABMAP_PATCH_VERSION})
@@ -203,11 +203,10 @@ option(WITH_ZED "Include ZED sdk support" ON)
option(WITH_ZEDOC "Include ZED Open Capture support" ON) option(WITH_ZEDOC "Include ZED Open Capture support" ON)
option(WITH_REALSENSE "Include RealSense support" ON) option(WITH_REALSENSE "Include RealSense support" ON)
option(WITH_REALSENSE_SLAM "Include RealSenseSlam support" ON) option(WITH_REALSENSE_SLAM "Include RealSenseSlam support" ON)
option(WITH_REALSENSE2 "Include RealSense2 support" ON) option(WITH_REALSENSE2 "Include RealSense support" ON)
option(WITH_MYNTEYE "Include mynteye-s support" ON) option(WITH_MYNTEYE "Include mynteye-s support" ON)
option(WITH_DEPTHAI "Include depthai-core support" OFF) option(WITH_DEPTHAI "Include depthai-core support" OFF)
option(WITH_XVSDK "Include XVisio SDK support" OFF) option(WITH_XVSDK "Include XVisio SDK support" OFF)
option(WITH_ORBBEC_SDK "Include Orbbec SDK v2 support" OFF)
option(WITH_OCTOMAP "Include OctoMap support" ON) option(WITH_OCTOMAP "Include OctoMap support" ON)
option(WITH_GRIDMAP "Include GridMap support" OFF) option(WITH_GRIDMAP "Include GridMap support" OFF)
option(WITH_CPUTSDF "Include CPUTSDF support" OFF) option(WITH_CPUTSDF "Include CPUTSDF support" OFF)
@@ -219,9 +218,8 @@ option(WITH_DVO "Include DVO support" OFF)
option(WITH_ORB_SLAM "Include ORB_SLAM2 or ORB_SLAM3 support" OFF) option(WITH_ORB_SLAM "Include ORB_SLAM2 or ORB_SLAM3 support" OFF)
option(WITH_OKVIS "Include OKVIS support" OFF) option(WITH_OKVIS "Include OKVIS support" OFF)
option(WITH_MSCKF_VIO "Include MSCKF_VIO support" OFF) option(WITH_MSCKF_VIO "Include MSCKF_VIO support" OFF)
option(WITH_VINS_FUSION "Include VINS-Fusion support" OFF) option(WITH_VINS "Include VINS-Fusion support" OFF)
option(WITH_OPENVINS "Include OpenVINS support" OFF) option(WITH_OPENVINS "Include OpenVINS support" OFF)
option(WITH_CUVSLAM "Include cuVSLAM support" OFF)
option(WITH_MADGWICK "Include Madgwick IMU filtering support" ON) option(WITH_MADGWICK "Include Madgwick IMU filtering support" ON)
option(WITH_FASTCV "Include FastCV support" ON) option(WITH_FASTCV "Include FastCV support" ON)
option(WITH_OPENMP "Include OpenMP support" ON) option(WITH_OPENMP "Include OpenMP support" ON)
@@ -398,7 +396,7 @@ IF(NOT VTK_FOUND)
ENDIF(NOT VTK_FOUND) ENDIF(NOT VTK_FOUND)
IF(WITH_TORCH) IF(WITH_TORCH)
FIND_PACKAGE(Torch) FIND_PACKAGE(Torch QUIET)
IF(TORCH_FOUND) IF(TORCH_FOUND)
MESSAGE(STATUS "Found Torch: ${TORCH_INCLUDE_DIRS}") MESSAGE(STATUS "Found Torch: ${TORCH_INCLUDE_DIRS}")
ENDIF(TORCH_FOUND) ENDIF(TORCH_FOUND)
@@ -420,14 +418,14 @@ IF(WITH_PDAL)
ENDIF(WITH_PDAL) ENDIF(WITH_PDAL)
IF(WITH_LIBLAS) IF(WITH_LIBLAS)
FIND_PACKAGE(libLAS) FIND_PACKAGE(libLAS QUIET)
IF(libLAS_FOUND) IF(libLAS_FOUND)
MESSAGE(STATUS "Found libLAS ${libLAS_VERSION}: ${libLAS_INCLUDE_DIRS}") MESSAGE(STATUS "Found libLAS ${libLAS_VERSION}: ${libLAS_INCLUDE_DIRS}")
ENDIF(libLAS_FOUND) ENDIF(libLAS_FOUND)
ENDIF(WITH_LIBLAS) ENDIF(WITH_LIBLAS)
IF(WITH_CUDASIFT) IF(WITH_CUDASIFT)
FIND_PACKAGE(CudaSift 3) FIND_PACKAGE(CudaSift 3 QUIET)
IF(CudaSift_FOUND) IF(CudaSift_FOUND)
MESSAGE(STATUS "Found CudaSift") MESSAGE(STATUS "Found CudaSift")
ENDIF(CudaSift_FOUND) ENDIF(CudaSift_FOUND)
@@ -518,15 +516,6 @@ IF(WITH_G2O)
FIND_PACKAGE(G2O QUIET) FIND_PACKAGE(G2O QUIET)
IF(G2O_FOUND) IF(G2O_FOUND)
MESSAGE(STATUS "Found g2o: ${G2O_INCLUDE_DIRS}") MESSAGE(STATUS "Found g2o: ${G2O_INCLUDE_DIRS}")
FIND_FILE(G2O_FACTORY_FILE g2o/core/factory.h
PATHS ${G2O_INCLUDES}
NO_DEFAULT_PATH)
FILE(READ ${G2O_FACTORY_FILE} TMPTXT)
STRING(FIND "${TMPTXT}" "shared_ptr" matchres)
IF(NOT ${matchres} EQUAL -1)
MESSAGE(STATUS "Latest g2o factory version detected with shared ptr (factory file: ${G2O_FACTORY_FILE}).")
SET(G2O_CPP11 1)
ENDIF()
ENDIF(G2O_FOUND) ENDIF(G2O_FOUND)
ENDIF() ENDIF()
ENDIF(WITH_G2O) ENDIF(WITH_G2O)
@@ -552,7 +541,7 @@ IF(WITH_FLYCAPTURE2)
ENDIF(WITH_FLYCAPTURE2) ENDIF(WITH_FLYCAPTURE2)
IF(WITH_CVSBA) IF(WITH_CVSBA)
FIND_PACKAGE(cvsba) FIND_PACKAGE(cvsba QUIET)
IF(cvsba_FOUND) IF(cvsba_FOUND)
MESSAGE(STATUS "Found cvsba: ${cvsba_INCLUDE_DIRS}") MESSAGE(STATUS "Found cvsba: ${cvsba_INCLUDE_DIRS}")
ENDIF(cvsba_FOUND) ENDIF(cvsba_FOUND)
@@ -578,14 +567,10 @@ IF(WITH_POINTMATCHER)
ENDIF(WITH_POINTMATCHER) ENDIF(WITH_POINTMATCHER)
IF(libpointmatcher_FOUND OR GTSAM_FOUND) IF(libpointmatcher_FOUND OR GTSAM_FOUND)
find_package(Boost COMPONENTS thread filesystem program_options date_time REQUIRED)
IF(Boost_MINOR_VERSION GREATER 80)
find_package(Boost COMPONENTS thread filesystem program_options date_time chrono timer serialization REQUIRED)
ELSEIF(Boost_MINOR_VERSION GREATER 47)
find_package(Boost COMPONENTS thread filesystem system program_options date_time chrono timer serialization REQUIRED)
ELSE()
find_package(Boost COMPONENTS thread filesystem system program_options date_time REQUIRED) find_package(Boost COMPONENTS thread filesystem system program_options date_time REQUIRED)
ENDIF() IF(Boost_MINOR_VERSION GREATER 47)
find_package(Boost COMPONENTS thread filesystem system program_options date_time chrono timer serialization REQUIRED)
ENDIF(Boost_MINOR_VERSION GREATER 47)
IF(WIN32) IF(WIN32)
MESSAGE(STATUS "Boost_LIBRARY_DIRS=${Boost_LIBRARY_DIRS}") MESSAGE(STATUS "Boost_LIBRARY_DIRS=${Boost_LIBRARY_DIRS}")
link_directories(${Boost_LIBRARY_DIRS}) link_directories(${Boost_LIBRARY_DIRS})
@@ -593,7 +578,7 @@ IF(libpointmatcher_FOUND OR GTSAM_FOUND)
ENDIF(libpointmatcher_FOUND OR GTSAM_FOUND) ENDIF(libpointmatcher_FOUND OR GTSAM_FOUND)
IF(WITH_CCCORELIB) IF(WITH_CCCORELIB)
find_package(CCCoreLib) find_package(CCCoreLib QUIET)
IF(CCCoreLib_FOUND) IF(CCCoreLib_FOUND)
MESSAGE(STATUS "Found CCCoreLib: ${CCCoreLib_INCLUDE_DIRS}") MESSAGE(STATUS "Found CCCoreLib: ${CCCoreLib_INCLUDE_DIRS}")
ENDIF(CCCoreLib_FOUND) ENDIF(CCCoreLib_FOUND)
@@ -605,7 +590,7 @@ IF(WITH_OPEN3D)
ELSE() ELSE()
# Build Open3D like this to avoid linker errors in rtabmap: # Build Open3D like this to avoid linker errors in rtabmap:
# cmake -DBUILD_SHARED_LIBS=ON -DGLIBCXX_USE_CXX11_ABI=ON -DCMAKE_BUILD_TYPE=Release .. # cmake -DBUILD_SHARED_LIBS=ON -DGLIBCXX_USE_CXX11_ABI=ON -DCMAKE_BUILD_TYPE=Release ..
find_package(Open3D) find_package(Open3D QUIET)
IF(Open3D_FOUND) IF(Open3D_FOUND)
MESSAGE(STATUS "Found Open3D: ${Open3DINCLUDE_DIRS}") MESSAGE(STATUS "Found Open3D: ${Open3DINCLUDE_DIRS}")
ENDIF(Open3D_FOUND) ENDIF(Open3D_FOUND)
@@ -613,17 +598,17 @@ IF(WITH_OPEN3D)
ENDIF(WITH_OPEN3D) ENDIF(WITH_OPEN3D)
IF(WITH_LOAM) IF(WITH_LOAM)
find_package(loam_velodyne) find_package(loam_velodyne QUIET)
IF(loam_velodyne_FOUND) IF(loam_velodyne_FOUND)
MESSAGE(STATUS "Found loam_velodyne: ${loam_velodyne_INCLUDE_DIRS}") MESSAGE(STATUS "Found loam_velodyne: ${loam_velodyne_INCLUDE_DIRS}")
ENDIF(loam_velodyne_FOUND) ENDIF(loam_velodyne_FOUND)
ENDIF(WITH_LOAM) ENDIF(WITH_LOAM)
IF(WITH_FLOAM) IF(WITH_FLOAM)
find_package(floam) find_package(floam QUIET)
IF(floam_FOUND) IF(floam_FOUND)
MESSAGE(STATUS "Found floam: ${floam_INCLUDE_DIRS}") MESSAGE(STATUS "Found floam: ${floam_INCLUDE_DIRS}")
FIND_PACKAGE(Ceres REQUIRED) FIND_PACKAGE(Ceres QUIET REQUIRED)
ENDIF(floam_FOUND) ENDIF(floam_FOUND)
ENDIF(WITH_FLOAM) ENDIF(WITH_FLOAM)
@@ -690,26 +675,19 @@ IF(WITH_MYNTEYE)
ENDIF(WITH_MYNTEYE) ENDIF(WITH_MYNTEYE)
IF(WITH_DEPTHAI) IF(WITH_DEPTHAI)
FIND_PACKAGE(depthai 2.24) FIND_PACKAGE(depthai 2.24 QUIET)
IF(depthai_FOUND) IF(depthai_FOUND)
MESSAGE(STATUS "Found depthai-core (targets)") MESSAGE(STATUS "Found depthai-core (targets)")
ENDIF(depthai_FOUND) ENDIF(depthai_FOUND)
ENDIF(WITH_DEPTHAI) ENDIF(WITH_DEPTHAI)
IF(WITH_XVSDK) IF(WITH_XVSDK)
FIND_PACKAGE(xvsdk) FIND_PACKAGE(xvsdk QUIET)
IF(xvsdk_FOUND) IF(xvsdk_FOUND)
MESSAGE(STATUS "Found xvsdk (targets)") MESSAGE(STATUS "Found xvsdk (targets)")
ENDIF(xvsdk_FOUND) ENDIF(xvsdk_FOUND)
ENDIF(WITH_XVSDK) ENDIF(WITH_XVSDK)
IF(WITH_ORBBEC_SDK)
FIND_PACKAGE(OrbbecSDK 2)
IF(OrbbecSDK_FOUND)
MESSAGE(STATUS "Found OrbbecSDK v2 (targets)")
ENDIF(OrbbecSDK_FOUND)
ENDIF(WITH_ORBBEC_SDK)
IF(WITH_OCTOMAP) IF(WITH_OCTOMAP)
FIND_PACKAGE(octomap QUIET) FIND_PACKAGE(octomap QUIET)
IF(octomap_FOUND) IF(octomap_FOUND)
@@ -721,35 +699,35 @@ IF(WITH_OCTOMAP)
ENDIF(WITH_OCTOMAP) ENDIF(WITH_OCTOMAP)
IF(WITH_GRIDMAP) IF(WITH_GRIDMAP)
FIND_PACKAGE(grid_map_core) FIND_PACKAGE(grid_map_core QUIET)
IF(grid_map_core_FOUND) IF(grid_map_core_FOUND)
MESSAGE(STATUS "Found grid_map_core ${grid_map_core_VERSION}: ${grid_map_core_INCLUDE_DIRS}") MESSAGE(STATUS "Found grid_map_core ${grid_map_core_VERSION}: ${grid_map_core_INCLUDE_DIRS}")
ENDIF(grid_map_core_FOUND) ENDIF(grid_map_core_FOUND)
ENDIF(WITH_GRIDMAP) ENDIF(WITH_GRIDMAP)
IF(WITH_CPUTSDF) IF(WITH_CPUTSDF)
FIND_PACKAGE(CPUTSDF) FIND_PACKAGE(CPUTSDF QUIET)
IF(CPUTSDF_FOUND) IF(CPUTSDF_FOUND)
MESSAGE(STATUS "Found CPUTSDF: ${CPUTSDF_INCLUDE_DIRS}") MESSAGE(STATUS "Found CPUTSDF: ${CPUTSDF_INCLUDE_DIRS}")
ENDIF(CPUTSDF_FOUND) ENDIF(CPUTSDF_FOUND)
ENDIF(WITH_CPUTSDF) ENDIF(WITH_CPUTSDF)
IF(WITH_OPENCHISEL) IF(WITH_OPENCHISEL)
find_package(open_chisel) find_package(open_chisel QUIET)
if(open_chisel_FOUND) if(open_chisel_FOUND)
MESSAGE(STATUS "Found open_chisel: ${open_chisel_INCLUDE_DIRS}") MESSAGE(STATUS "Found open_chisel: ${open_chisel_INCLUDE_DIRS}")
endif(open_chisel_FOUND) endif(open_chisel_FOUND)
ENDIF(WITH_OPENCHISEL) ENDIF(WITH_OPENCHISEL)
IF(WITH_ALICE_VISION) IF(WITH_ALICE_VISION)
find_package(AliceVision CONFIG) find_package(AliceVision CONFIG QUIET)
IF(AliceVision_FOUND) IF(AliceVision_FOUND)
IF(${AliceVision_VERSION} VERSION_LESS_EQUAL "2.2") IF(${AliceVision_VERSION} VERSION_LESS_EQUAL "2.2")
find_package(Boost COMPONENTS log log_setup container REQUIRED) find_package(Boost COMPONENTS log log_setup container REQUIRED)
ENDIF(${AliceVision_VERSION} VERSION_LESS_EQUAL "2.2") ENDIF(${AliceVision_VERSION} VERSION_LESS_EQUAL "2.2")
SET(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH};/usr/local/lib/cmake/modules") SET(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH};/usr/local/lib/cmake/modules")
find_package(Geogram REQUIRED) find_package(Geogram REQUIRED QUIET)
find_package(assimp) find_package(assimp QUIET)
add_definitions("-DRTABMAP_ALICE_VISION_MAJOR=${AliceVision_VERSION_MAJOR}") add_definitions("-DRTABMAP_ALICE_VISION_MAJOR=${AliceVision_VERSION_MAJOR}")
add_definitions("-DRTABMAP_ALICE_VISION_MINOR=${AliceVision_VERSION_MINOR}") add_definitions("-DRTABMAP_ALICE_VISION_MINOR=${AliceVision_VERSION_MINOR}")
add_definitions("-DRTABMAP_ALICE_VISION_PATCH=${AliceVision_VERSION_PATCH}") add_definitions("-DRTABMAP_ALICE_VISION_PATCH=${AliceVision_VERSION_PATCH}")
@@ -757,28 +735,28 @@ IF(WITH_ALICE_VISION)
ENDIF(WITH_ALICE_VISION) ENDIF(WITH_ALICE_VISION)
IF(WITH_FOVIS) IF(WITH_FOVIS)
FIND_PACKAGE(libfovis) FIND_PACKAGE(libfovis QUIET)
IF(libfovis_FOUND) IF(libfovis_FOUND)
MESSAGE(STATUS "Found libfovis: ${libfovis_INCLUDE_DIRS}") MESSAGE(STATUS "Found libfovis: ${libfovis_INCLUDE_DIRS}")
ENDIF(libfovis_FOUND) ENDIF(libfovis_FOUND)
ENDIF(WITH_FOVIS) ENDIF(WITH_FOVIS)
IF(WITH_VISO2) IF(WITH_VISO2)
FIND_PACKAGE(libviso2) FIND_PACKAGE(libviso2 QUIET)
IF(libviso2_FOUND) IF(libviso2_FOUND)
MESSAGE(STATUS "Found libviso2: ${libviso2_INCLUDE_DIRS}") MESSAGE(STATUS "Found libviso2: ${libviso2_INCLUDE_DIRS}")
ENDIF(libviso2_FOUND) ENDIF(libviso2_FOUND)
ENDIF(WITH_VISO2) ENDIF(WITH_VISO2)
IF(WITH_DVO) IF(WITH_DVO)
FIND_PACKAGE(dvo_core) FIND_PACKAGE(dvo_core QUIET)
IF(dvo_core_FOUND) IF(dvo_core_FOUND)
MESSAGE(STATUS "Found dvo_core: ${dvo_core_INCLUDE_DIRS}") MESSAGE(STATUS "Found dvo_core: ${dvo_core_INCLUDE_DIRS}")
ENDIF(dvo_core_FOUND) ENDIF(dvo_core_FOUND)
ENDIF(WITH_DVO) ENDIF(WITH_DVO)
IF(WITH_OKVIS) IF(WITH_OKVIS)
FIND_PACKAGE(okvis 1.1) FIND_PACKAGE(okvis 1.1 QUIET)
IF(okvis_FOUND) IF(okvis_FOUND)
MESSAGE(STATUS "Found okvis: ${OKVIS_INCLUDE_DIRS}") MESSAGE(STATUS "Found okvis: ${OKVIS_INCLUDE_DIRS}")
find_package(brisk 2 REQUIRED) find_package(brisk 2 REQUIRED)
@@ -793,7 +771,7 @@ ENDIF(WITH_OKVIS)
# If built with okvis, we found already ceres above # If built with okvis, we found already ceres above
IF(WITH_CERES) IF(WITH_CERES)
IF(NOT okvis_FOUND AND NOT floam_FOUND) IF(NOT okvis_FOUND AND NOT floam_FOUND)
FIND_PACKAGE(Ceres) FIND_PACKAGE(Ceres QUIET)
MESSAGE(STATUS "Found ceres ${Ceres_VERSION}: ${CERES_INCLUDE_DIRS}") MESSAGE(STATUS "Found ceres ${Ceres_VERSION}: ${CERES_INCLUDE_DIRS}")
ENDIF(NOT okvis_FOUND AND NOT floam_FOUND) ENDIF(NOT okvis_FOUND AND NOT floam_FOUND)
ELSEIF(Ceres_FOUND) ELSEIF(Ceres_FOUND)
@@ -801,33 +779,28 @@ ELSEIF(Ceres_FOUND)
ENDIF() ENDIF()
IF(WITH_MSCKF_VIO) IF(WITH_MSCKF_VIO)
FIND_PACKAGE(msckf_vio) FIND_PACKAGE(msckf_vio QUIET)
IF(msckf_vio_FOUND) IF(msckf_vio_FOUND)
MESSAGE(STATUS "Found msckf_vio: ${msckf_vio_INCLUDE_DIRS}") MESSAGE(STATUS "Found msckf_vio: ${msckf_vio_INCLUDE_DIRS}")
ENDIF(msckf_vio_FOUND) ENDIF(msckf_vio_FOUND)
ENDIF(WITH_MSCKF_VIO) ENDIF(WITH_MSCKF_VIO)
IF(WITH_VINS AND NOT WITH_VINS_FUSION) IF(WITH_VINS)
message(DEPRECATION "The option WITH_VINS is deprecated and will be removed in a future version. Please use WITH_VINS_FUSION instead.") FIND_PACKAGE(vins QUIET)
set(WITH_VINS_FUSION ON)
ENDIF(WITH_VINS AND NOT WITH_VINS_FUSION)
IF(WITH_VINS_FUSION)
FIND_PACKAGE(vins)
IF(vins_FOUND) IF(vins_FOUND)
MESSAGE(STATUS "Found vins-fusion: ${vins_INCLUDE_DIRS}") MESSAGE(STATUS "Found vins: ${vins_INCLUDE_DIRS}")
IF(okvis_FOUND) IF(okvis_FOUND)
MESSAGE(WARNING "VINS-Fusion and OKVIS will be both linked to project, make sure VINS-Fusion has been built with against same Ceres version than OKVIS to avoid some crashes.") MESSAGE(WARNING "VINS and OKVIS will be both linked to project, make sure VINS has been built with against same Ceres version than OKVIS to avoid some crashes.")
ENDIF(okvis_FOUND) ENDIF(okvis_FOUND)
ENDIF(vins_FOUND) ENDIF(vins_FOUND)
ENDIF(WITH_VINS_FUSION) ENDIF(WITH_VINS)
IF(WITH_OPENVINS) IF(WITH_OPENVINS)
FIND_PACKAGE(ov_msckf) FIND_PACKAGE(ov_msckf QUIET)
# On ROS2, the indirect includes and libraries # On ROS2, the indirect includes and libraries
# are not forwarded by ov_msckf target, append them manually # are not forwarded by ov_msckf target, append them manually
FIND_PACKAGE(ov_core) FIND_PACKAGE(ov_core QUIET)
FIND_PACKAGE(ov_init) FIND_PACKAGE(ov_init QUIET)
IF(ov_msckf_FOUND AND ov_core_FOUND AND ov_init_FOUND) IF(ov_msckf_FOUND AND ov_core_FOUND AND ov_init_FOUND)
SET(ov_msckf_INCLUDE_DIRS SET(ov_msckf_INCLUDE_DIRS
${ov_msckf_INCLUDE_DIRS} ${ov_msckf_INCLUDE_DIRS}
@@ -856,19 +829,12 @@ IF(WITH_OPENGV)
ENDIF(WITH_OPENGV) ENDIF(WITH_OPENGV)
IF(WITH_ORB_SLAM AND NOT G2O_FOUND) IF(WITH_ORB_SLAM AND NOT G2O_FOUND)
FIND_PACKAGE(ORB_SLAM) FIND_PACKAGE(ORB_SLAM QUIET)
IF(ORB_SLAM_FOUND) IF(ORB_SLAM_FOUND)
MESSAGE(STATUS "Found ORB_SLAM${ORB_SLAM_VERSION}: ${ORB_SLAM_INCLUDE_DIRS}") MESSAGE(STATUS "Found ORB_SLAM${ORB_SLAM_VERSION}: ${ORB_SLAM_INCLUDE_DIRS}")
ENDIF(ORB_SLAM_FOUND) ENDIF(ORB_SLAM_FOUND)
ENDIF(WITH_ORB_SLAM AND NOT G2O_FOUND) ENDIF(WITH_ORB_SLAM AND NOT G2O_FOUND)
IF(WITH_CUVSLAM)
FIND_PACKAGE(CuVSLAM)
IF(CUVSLAM_FOUND)
MESSAGE(STATUS "Found cuVSLAM: ${CUVSLAM_INCLUDE_DIRS}")
ENDIF()
ENDIF(WITH_CUVSLAM)
SET(DISABLE_NEW_DTAGS_FLAG "--disable-new-dtags") SET(DISABLE_NEW_DTAGS_FLAG "--disable-new-dtags")
IF(NOT (APPLE OR WIN32) AND BUILD_WITH_RPATH_NOT_RUNPATH) IF(NOT (APPLE OR WIN32) AND BUILD_WITH_RPATH_NOT_RUNPATH)
ADD_LINK_OPTIONS(LINKER:${DISABLE_NEW_DTAGS_FLAG}) ADD_LINK_OPTIONS(LINKER:${DISABLE_NEW_DTAGS_FLAG})
@@ -1092,9 +1058,6 @@ IF(NOT xvsdk_FOUND)
ELSE() ELSE()
SET(CONF_WITH_XVSDK 1) SET(CONF_WITH_XVSDK 1)
ENDIF() ENDIF()
IF(NOT OrbbecSDK_FOUND)
SET(ORBBEC_SDK "//")
ENDIF(NOT OrbbecSDK_FOUND)
IF(NOT octomap_FOUND) IF(NOT octomap_FOUND)
SET(OCTOMAP "//") SET(OCTOMAP "//")
SET(CONF_WITH_OCTOMAP 0) SET(CONF_WITH_OCTOMAP 0)
@@ -1129,14 +1092,11 @@ IF(NOT msckf_vio_FOUND)
SET(MSCKF_VIO "//") SET(MSCKF_VIO "//")
ENDIF() ENDIF()
IF(NOT vins_FOUND) IF(NOT vins_FOUND)
SET(VINSFUSION "//") SET(VINS "//")
ENDIF() ENDIF()
IF(NOT ov_msckf_FOUND) IF(NOT ov_msckf_FOUND)
SET(OPENVINS "//") SET(OPENVINS "//")
ENDIF() ENDIF()
IF(NOT CUVSLAM_FOUND)
SET(CUVSLAM "//")
ENDIF()
IF(NOT ORB_SLAM_FOUND) IF(NOT ORB_SLAM_FOUND)
SET(ORB_SLAM "//") SET(ORB_SLAM "//")
ENDIF() ENDIF()
@@ -1607,7 +1567,7 @@ ENDIF()
IF(grid_map_core_FOUND) IF(grid_map_core_FOUND)
MESSAGE(STATUS " With GridMap ${grid_map_core_VERSION} = YES (License: BSD)") MESSAGE(STATUS " With GridMap ${grid_map_core_VERSION} = YES (License: BSD)")
ELSEIF(NOT WITH_GRIDMAP) ELSEIF(NOT WITH_OCTOMAP)
MESSAGE(STATUS " With GridMap = NO (WITH_GRIDMAP=OFF)") MESSAGE(STATUS " With GridMap = NO (WITH_GRIDMAP=OFF)")
ELSE() ELSE()
MESSAGE(STATUS " With GridMap = NO (grid_map_core not found)") MESSAGE(STATUS " With GridMap = NO (grid_map_core not found)")
@@ -1770,14 +1730,6 @@ ELSE()
MESSAGE(STATUS " With XVisio SDK = NO (xvsdk not found)") MESSAGE(STATUS " With XVisio SDK = NO (xvsdk not found)")
ENDIF() ENDIF()
IF(OrbbecSDK_FOUND)
MESSAGE(STATUS " With Orbbec SDK ${OrbbecSDK_VERSION} = YES (License: MIT)")
ELSEIF(NOT WITH_ORBBEC_SDK)
MESSAGE(STATUS " With Orbbec SDK = NO (WITH_ORBBEC_SDK=OFF)")
ELSE()
MESSAGE(STATUS " With Orbbec SDK = NO (OrbbecSDK v2 not found)")
ENDIF()
MESSAGE(STATUS "") MESSAGE(STATUS "")
MESSAGE(STATUS " Odometry Approaches:") MESSAGE(STATUS " Odometry Approaches:")
IF(loam_velodyne_FOUND) IF(loam_velodyne_FOUND)
@@ -1839,7 +1791,7 @@ ENDIF()
IF(vins_FOUND) IF(vins_FOUND)
MESSAGE(STATUS " With VINS-Fusion = YES (License: GPLv3)") MESSAGE(STATUS " With VINS-Fusion = YES (License: GPLv3)")
ELSEIF(NOT WITH_VINS) ELSEIF(NOT WITH_VINS)
MESSAGE(STATUS " With VINS-Fusion = NO (WITH_VINS_FUSION=OFF)") MESSAGE(STATUS " With VINS-Fusion = NO (WITH_VINS=OFF)")
ELSE() ELSE()
MESSAGE(STATUS " With VINS-Fusion = NO (VINS-Fusion not found)") MESSAGE(STATUS " With VINS-Fusion = NO (VINS-Fusion not found)")
ENDIF() ENDIF()
@@ -1862,14 +1814,6 @@ ELSE()
MESSAGE(STATUS " With ORB_SLAM = NO (ORB_SLAM2 and ORB_SLAM3 not found, make sure environment variable ORB_SLAM_ROOT_DIR is set)") MESSAGE(STATUS " With ORB_SLAM = NO (ORB_SLAM2 and ORB_SLAM3 not found, make sure environment variable ORB_SLAM_ROOT_DIR is set)")
ENDIF() ENDIF()
IF(CUVSLAM_FOUND)
MESSAGE(STATUS " With cuVSLAM = YES (License: NVIDIA ISAAC ROS SOFTWARE LICENSE)")
ELSEIF(NOT WITH_CUVSLAM)
MESSAGE(STATUS " With cuVSLAM = NO (WITH_CUVSLAM=OFF)")
ELSE()
MESSAGE(STATUS " With cuVSLAM = NO (cuVSLAM not found, make sure cuVSLAM is installed)")
ENDIF()
MESSAGE(STATUS "Show all options with: cmake -LA | grep WITH_") MESSAGE(STATUS "Show all options with: cmake -LA | grep WITH_")
MESSAGE(STATUS "--------------------------------------------") MESSAGE(STATUS "--------------------------------------------")
+1 -3
View File
@@ -72,7 +72,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@MYNTEYE@#define RTABMAP_MYNTEYE @MYNTEYE@#define RTABMAP_MYNTEYE
@DEPTHAI@#define RTABMAP_DEPTHAI @DEPTHAI@#define RTABMAP_DEPTHAI
@XVSDK@#define RTABMAP_XVSDK @XVSDK@#define RTABMAP_XVSDK
@ORBBEC_SDK@#define RTABMAP_ORBBEC_SDK
@OCTOMAP@#define RTABMAP_OCTOMAP @OCTOMAP@#define RTABMAP_OCTOMAP
@GRIDMAP@#define RTABMAP_GRIDMAP @GRIDMAP@#define RTABMAP_GRIDMAP
@CPUTSDF@#define RTABMAP_CPUTSDF @CPUTSDF@#define RTABMAP_CPUTSDF
@@ -83,9 +82,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@DVO@#define RTABMAP_DVO @DVO@#define RTABMAP_DVO
@OKVIS@#define RTABMAP_OKVIS @OKVIS@#define RTABMAP_OKVIS
@MSCKF_VIO@#define RTABMAP_MSCKF_VIO @MSCKF_VIO@#define RTABMAP_MSCKF_VIO
@VINSFUSION@#define RTABMAP_VINS_FUSION @VINS@#define RTABMAP_VINS
@OPENVINS@#define RTABMAP_OPENVINS @OPENVINS@#define RTABMAP_OPENVINS
@CUVSLAM@#define RTABMAP_CUVSLAM
@ORB_SLAM@#define RTABMAP_ORB_SLAM @ORB_SLAM_VERSION@ @ORB_SLAM@#define RTABMAP_ORB_SLAM @ORB_SLAM_VERSION@
@ORB_OCTREE@#define RTABMAP_ORB_OCTREE @ORB_OCTREE@#define RTABMAP_ORB_OCTREE
@TORCH@#define RTABMAP_TORCH @TORCH@#define RTABMAP_TORCH
+1 -28
View File
@@ -34,7 +34,7 @@ ENDIF()
IF(APPLE AND BUILD_AS_BUNDLE) IF(APPLE AND BUILD_AS_BUNDLE)
ADD_EXECUTABLE(rtabmap_app MACOSX_BUNDLE ${SRC_FILES}) ADD_EXECUTABLE(rtabmap_app MACOSX_BUNDLE ${SRC_FILES})
ELSEIF(WIN32 AND BUILD_AS_BUNDLE) ELSEIF(WIN32 AND BUILD_AS_BUNDLE)
ADD_EXECUTABLE(rtabmap_app ${SRC_FILES}) ADD_EXECUTABLE(rtabmap_app WIN32 ${SRC_FILES})
ELSE() ELSE()
ADD_EXECUTABLE(rtabmap_app ${SRC_FILES}) ADD_EXECUTABLE(rtabmap_app ${SRC_FILES})
ENDIF() ENDIF()
@@ -110,33 +110,6 @@ IF(BUILD_AS_BUNDLE AND (APPLE OR WIN32))
ENDIF(WIN32) ENDIF(WIN32)
ENDIF(k4a_FOUND) ENDIF(k4a_FOUND)
IF(ZED_FOUND)
# Install needed zlibwapi.dll
IF(WIN32)
file(TO_CMAKE_PATH "$ENV{ZED_SDK_ROOT_DIR}" ENV_ZED_SDK_ROOT_DIR)
INSTALL(FILES "${ENV_ZED_SDK_ROOT_DIR}/bin/zlibwapi.dll"
DESTINATION ${thirdparty_dest_dir}
COMPONENT runtime)
ENDIF(WIN32)
ENDIF(ZED_FOUND)
IF(OrbbecSDK_FOUND)
# Install needed "extensions" folder
IF(WIN32)
find_path(OrbbecSDK_BIN_DIR NAMES OrbbecSDK.dll)
IF(NOT OrbbecSDK_BIN_DIR)
MESSAGE(FATAL_ERROR "OrbbecSDK.dll not found! Verify your PATH.")
ENDIF(NOT OrbbecSDK_BIN_DIR)
MESSAGE(FATAL "OrbbecSDK_BIN_DIR=${OrbbecSDK_BIN_DIR}")
INSTALL(DIRECTORY "${OrbbecSDK_BIN_DIR}/extensions"
DESTINATION ${thirdparty_dest_dir}
COMPONENT runtime
FILES_MATCHING
PATTERN "*.lib" EXCLUDE
PATTERN "*")
ENDIF(WIN32)
ENDIF(OrbbecSDK_FOUND)
IF(Torch_FOUND) IF(Torch_FOUND)
# Install needed cudnn_ops_infer64_8.dll and cudnn_cnn_infer64_8.dll # 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 # TODO: should be a more general way to include them if version is different
@@ -15,7 +15,7 @@ RAMaddOverhead = 0;
% Inliers_ratio = 'Loop/Visual_inliers/' ./ 'Keypoint/Current_frame/words' % Inliers_ratio = 'Loop/Visual_inliers/' ./ 'Keypoint/Current_frame/words'
% Odometry_average = 'Memory/Distance_travelled/m'(2:end) - 'Memory/Distance_travelled/m'(1:end-1) % Odometry_average = 'Memory/Distance_travelled/m'(2:end) - 'Memory/Distance_travelled/m'(1:end-1)
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/m'}; % 'Odometry_average' 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 datasets = [ 0 1 6 7 9 14 11 111 ]; % 0 1 6 7 9 12 14 11
@@ -26,7 +26,7 @@ if resultsToShow == 2
sep = [0, 1000, 3000, 5000, 7000, 9000]; sep = [0, 1000, 3000, 5000, 7000, 9000];
sepName = {'17:27', '17:54', '18:27', '18:56', '19:35'}; sepName = {'17:27', '17:54', '18:27', '18:56', '19:35'};
prefix = 'Consecutive'; prefix = 'Consecutive';
statNames = {'Loop/Distance_since_last_loc/m', 'Distance_since_last_loc_under_50cm'}; statNames = {'Loop/Distance_since_last_loc/', 'Distance_since_last_loc_under_50cm'};
endif endif
MapsN = length(sepName); MapsN = length(sepName);
@@ -52,7 +52,7 @@ if strcmp(statName,'Inliers_ratio_%')
elseif strcmp(statName, 'Odometry_average') elseif strcmp(statName, 'Odometry_average')
data = dlmread([dataDir '/' 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') elseif strcmp(statName, 'Distance_since_last_loc_under_50cm')
data = dlmread([dataDir '/' prefix num2str(datasets(d)) '-' 'Loop-Distance_since_last_loc-m' '.txt'], '\t', 1, 0, "emptyvalue", 0); data = dlmread([dataDir '/' prefix num2str(datasets(d)) '-' 'Loop-Distance_since_last_loc-' '.txt'], '\t', 1, 0, "emptyvalue", 0);
else else
data = dlmread([dataDir '/' 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 endif
@@ -13,7 +13,7 @@ source rtabmap_latest.bash
for d in "${DETECTOR[@]}" for d in "${DETECTOR[@]}"
do 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/m Memory/Local_graph_size/ Keypoint/Dictionary_size/words "$DATA/$d/loc" 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/m "$DATA/$d/consecutive_loc" rtabmap-report --export --export_prefix "Consecutive$d" --loc 32 Loop/Map_id/ Loop/Distance_since_last_loc/ "$DATA/$d/consecutive_loc"
done done
-79
View File
@@ -1,79 +0,0 @@
# - Find cuVSLAM library (https://github.com/NVIDIA-ISAAC-ROS/isaac_ros_visual_slam)
#
# CUVSLAM_ROOT_DIR environment variable can be set to find the library.
#
# It sets the following variables:
# CUVSLAM_FOUND - Set to false, or undefined, if cuVSLAM isn't found.
# CUVSLAM_INCLUDE_DIRS - The cuVSLAM include directory.
# CUVSLAM_LIBRARIES - The cuVSLAM library to link against.
find_package(CUDA REQUIRED)
find_package(Eigen3 REQUIRED)
find_path(CUVSLAM_INCLUDE_DIRS
NAMES cuvslam.h
PATHS
/usr/include
/usr/local/include
/opt/cuvslam/include
/opt/ros/humble/share/isaac_ros_nitros/cuvslam/include
$ENV{CUVSLAM_ROOT}/include
$ENV{CUVSLAM_ROOT_DIR}/include
)
find_library(CUVSLAM_LIBRARY
NAMES cuvslam
PATHS
/usr/lib
/usr/local/lib
/opt/cuvslam/lib
/opt/ros/humble/share/isaac_ros_nitros/cuvslam/lib
$ENV{CUVSLAM_ROOT}/lib
$ENV{CUVSLAM_ROOT_DIR}/lib
)
if(CUVSLAM_INCLUDE_DIRS AND CUVSLAM_LIBRARY)
set(CUVSLAM_FOUND TRUE)
set(CUVSLAM_LIBRARIES
${CUVSLAM_LIBRARY}
${CUDA_LIBRARIES}
# Eigen3 is header-only, so we don't need to link to it
)
set(CUVSLAM_INCLUDE_DIRS
${CUVSLAM_INCLUDE_DIRS}
${CUDA_INCLUDE_DIRS}
${EIGEN3_INCLUDE_DIR}
)
endif()
# Handle the QUIET and REQUIRED arguments
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(CuVSLAM
FOUND_VAR CUVSLAM_FOUND
REQUIRED_VARS CUVSLAM_LIBRARIES CUVSLAM_INCLUDE_DIRS
HANDLE_COMPONENTS
)
if(CUVSLAM_FOUND)
# Create imported target for modern CMake usage
if(NOT TARGET cuvslam::cuvslam)
add_library(cuvslam::cuvslam UNKNOWN IMPORTED)
set_target_properties(cuvslam::cuvslam PROPERTIES
IMPORTED_LOCATION "${CUVSLAM_LIBRARY}"
INTERFACE_INCLUDE_DIRECTORIES "${CUVSLAM_INCLUDE_DIRS}"
INTERFACE_LINK_LIBRARIES "${CUVSLAM_LIBRARIES};Eigen3::Eigen"
)
endif()
# Show which cuVSLAM was found only if not quiet
if(NOT CUVSLAM_FIND_QUIETLY)
message(STATUS "Found cuVSLAM: ${CUVSLAM_LIBRARIES}")
endif()
else()
# Fatal error if cuVSLAM is required but not found
if(CUVSLAM_FIND_REQUIRED)
message(FATAL_ERROR "Could not find cuVSLAM library")
endif()
endif()
mark_as_advanced(CUVSLAM_INCLUDE_DIRS CUVSLAM_LIBRARY)
+2 -2
View File
@@ -27,10 +27,10 @@
if(NOT Eigen3_FIND_VERSION) if(NOT Eigen3_FIND_VERSION)
if(NOT Eigen3_FIND_VERSION_MAJOR) if(NOT Eigen3_FIND_VERSION_MAJOR)
set(Eigen3_FIND_VERSION_MAJOR 3) set(Eigen3_FIND_VERSION_MAJOR 2)
endif() endif()
if(NOT Eigen3_FIND_VERSION_MINOR) if(NOT Eigen3_FIND_VERSION_MINOR)
set(Eigen3_FIND_VERSION_MINOR 0) set(Eigen3_FIND_VERSION_MINOR 91)
endif() endif()
if(NOT Eigen3_FIND_VERSION_PATCH) if(NOT Eigen3_FIND_VERSION_PATCH)
set(Eigen3_FIND_VERSION_PATCH 0) set(Eigen3_FIND_VERSION_PATCH 0)
+2 -8
View File
@@ -10,6 +10,8 @@
<string>${MACOSX_BUNDLE_INFO_STRING}</string> <string>${MACOSX_BUNDLE_INFO_STRING}</string>
<key>CFBundleIconFile</key> <key>CFBundleIconFile</key>
<string>${MACOSX_BUNDLE_ICON_FILE}</string> <string>${MACOSX_BUNDLE_ICON_FILE}</string>
<key>CFBundleIdentifier</key>
<string>${MACOSX_BUNDLE_GUI_IDENTIFIER}</string>
<key>CFBundleInfoDictionaryVersion</key> <key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string> <string>6.0</string>
<key>CFBundleLongVersionString</key> <key>CFBundleLongVersionString</key>
@@ -30,14 +32,6 @@
<true/> <true/>
<key>NSHumanReadableCopyright</key> <key>NSHumanReadableCopyright</key>
<string>${MACOSX_BUNDLE_COPYRIGHT}</string> <string>${MACOSX_BUNDLE_COPYRIGHT}</string>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.files.downloads.read-write</key>
<true/>
<key>com.apple.security.files.downloads.read-only</key>
<false/>
<key>com.apple.security.device.camera</key>
<true/>
<!-- File type associations --> <!-- File type associations -->
<key>CFBundleDocumentTypes</key> <key>CFBundleDocumentTypes</key>
@@ -38,4 +38,3 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <rtabmap/core/camera/CameraRGBDImages.h> #include <rtabmap/core/camera/CameraRGBDImages.h>
#include <rtabmap/core/camera/CameraK4A.h> #include <rtabmap/core/camera/CameraK4A.h>
#include <rtabmap/core/camera/CameraSeerSense.h> #include <rtabmap/core/camera/CameraSeerSense.h>
#include <rtabmap/core/camera/CameraOrbbecSDK.h>
+7 -11
View File
@@ -129,7 +129,6 @@ public:
std::vector<std::vector<Eigen::Vector2f> > * texCoords = 0, std::vector<std::vector<Eigen::Vector2f> > * texCoords = 0,
#endif #endif
cv::Mat * textures = 0) const; cv::Mat * textures = 0) const;
void saveFlannIndex(const std::vector<unsigned char> & indexData) const;
public: public:
// Mutex-protected methods of abstract versions below // Mutex-protected methods of abstract versions below
@@ -162,20 +161,19 @@ public:
void executeNoResult(const std::string & sql) const; void executeNoResult(const std::string & sql) const;
// Load objects // Load objects
void load(VWDictionary & dictionary, bool lastStateOnly = true) const; void load(VWDictionary * dictionary, bool lastStateOnly = true) const;
void loadLastNodes(std::list<Signature *> & signatures, bool loadWordIdsOnly = false) const; // returned signatures must be freed after usage void loadLastNodes(std::list<Signature *> & signatures) const; // returned signatures must be freed after usage
Signature * loadSignature(int id, bool * loadedFromTrash = 0); // returned signature must be freed after usage, call loadSignatures() instead if more than one signature should be loaded Signature * loadSignature(int id, bool * loadedFromTrash = 0); // returned signature must be freed after usage, call loadSignatures() instead if more than one signature should be loaded
void loadSignatures(const std::list<int> & ids, std::list<Signature *> & signatures, std::set<int> * loadedFromTrash = 0, bool loadWordIdsOnly = false); // returned signatures must be freed after usage void loadSignatures(const std::list<int> & ids, std::list<Signature *> & signatures, std::set<int> * loadedFromTrash = 0); // returned signatures must be freed after usage
void loadWords(const std::set<int> & wordIds, std::list<VisualWord *> & vws); // returned words must be freed after usage void loadWords(const std::set<int> & wordIds, std::list<VisualWord *> & vws); // returned words must be freed after usage
// Specific queries... // Specific queries...
void loadNodeData(Signature & signature, bool images = true, bool scan = true, bool userData = true, bool occupancyGrid = true) const; void loadNodeData(Signature * signature, bool images = true, bool scan = true, bool userData = true, bool occupancyGrid = true) const;
void loadNodeData(std::list<Signature *> & signatures, bool images = true, bool scan = true, bool userData = true, bool occupancyGrid = true) const; void loadNodeData(std::list<Signature *> & signatures, bool images = true, bool scan = true, bool userData = true, bool occupancyGrid = true) const;
void getNodeData(int signatureId, SensorData & data, bool images = true, bool scan = true, bool userData = true, bool occupancyGrid = true) const; void getNodeData(int signatureId, SensorData & data, bool images = true, bool scan = true, bool userData = true, bool occupancyGrid = true) const;
bool getCalibration(int signatureId, std::vector<CameraModel> & models, std::vector<StereoCameraModel> & stereoModels) const; bool getCalibration(int signatureId, std::vector<CameraModel> & models, std::vector<StereoCameraModel> & stereoModels) const;
bool getLaserScanInfo(int signatureId, LaserScan & info) const; bool getLaserScanInfo(int signatureId, LaserScan & info) const;
bool getNodeInfo(int signatureId, Transform & pose, int & mapId, int & weight, std::string & label, double & stamp, Transform & groundTruthPose, std::vector<float> & velocity, GPS & gps, EnvSensors & sensors) const; bool getNodeInfo(int signatureId, Transform & pose, int & mapId, int & weight, std::string & label, double & stamp, Transform & groundTruthPose, std::vector<float> & velocity, GPS & gps, EnvSensors & sensors) const;
void getLocalFeatures(int signatureId, std::multimap<int, int> & words, std::vector<cv::KeyPoint> & keypoints, std::vector<cv::Point3f> & points, cv::Mat & descriptors) const;
void loadLinks(int signatureId, std::multimap<int, Link> & links, Link::Type type = Link::kUndef) const; void loadLinks(int signatureId, std::multimap<int, Link> & links, Link::Type type = Link::kUndef) const;
void getWeight(int signatureId, int & weight) const; void getWeight(int signatureId, int & weight) const;
void getLastNodeIds(std::set<int> & ids) const; void getLastNodeIds(std::set<int> & ids) const;
@@ -276,12 +274,11 @@ protected:
std::vector<std::vector<Eigen::Vector2f> > * texCoords, std::vector<std::vector<Eigen::Vector2f> > * texCoords,
#endif #endif
cv::Mat * textures) const = 0; cv::Mat * textures) const = 0;
virtual void saveFlannIndexQuery(const std::vector<unsigned char> & indexData) const = 0;
// Load objects // Load objects
virtual void loadQuery(VWDictionary & dictionary, bool lastStateOnly = true) const = 0; virtual void loadQuery(VWDictionary * dictionary, bool lastStateOnly = true) const = 0;
virtual void loadLastNodesQuery(std::list<Signature *> & signatures, bool loadWordIdsOnly) const = 0; virtual void loadLastNodesQuery(std::list<Signature *> & signatures) const = 0;
virtual void loadSignaturesQuery(const std::list<int> & ids, std::list<Signature *> & signatures, bool loadWordIdsOnly) const = 0; virtual void loadSignaturesQuery(const std::list<int> & ids, std::list<Signature *> & signatures) const = 0;
virtual void loadWordsQuery(const std::set<int> & wordIds, std::list<VisualWord *> & vws) const = 0; virtual void loadWordsQuery(const std::set<int> & wordIds, std::list<VisualWord *> & vws) const = 0;
virtual void loadLinksQuery(int signatureId, std::multimap<int, Link> & links, Link::Type type = Link::kUndef) const = 0; virtual void loadLinksQuery(int signatureId, std::multimap<int, Link> & links, Link::Type type = Link::kUndef) const = 0;
@@ -289,7 +286,6 @@ protected:
virtual bool getCalibrationQuery(int signatureId, std::vector<CameraModel> & models, std::vector<StereoCameraModel> & stereoModels) const = 0; virtual bool getCalibrationQuery(int signatureId, std::vector<CameraModel> & models, std::vector<StereoCameraModel> & stereoModels) const = 0;
virtual bool getLaserScanInfoQuery(int signatureId, LaserScan & info) const = 0; virtual bool getLaserScanInfoQuery(int signatureId, LaserScan & info) const = 0;
virtual bool getNodeInfoQuery(int signatureId, Transform & pose, int & mapId, int & weight, std::string & label, double & stamp, Transform & groundTruthPose, std::vector<float> & velocity, GPS & gps, EnvSensors & sensors) const = 0; virtual bool getNodeInfoQuery(int signatureId, Transform & pose, int & mapId, int & weight, std::string & label, double & stamp, Transform & groundTruthPose, std::vector<float> & velocity, GPS & gps, EnvSensors & sensors) const = 0;
virtual void getLocalFeaturesQuery(int signatureId, std::multimap<int, int> & words, std::vector<cv::KeyPoint> & keypoints, std::vector<cv::Point3f> & points, cv::Mat & descriptors) const = 0;
virtual void getLastNodeIdsQuery(std::set<int> & ids) const = 0; virtual void getLastNodeIdsQuery(std::set<int> & ids) const = 0;
virtual void getAllNodeIdsQuery(std::set<int> & ids, bool ignoreChildren, bool ignoreBadSignatures, bool ignoreIntermediateNodes) const = 0; virtual void getAllNodeIdsQuery(std::set<int> & ids, bool ignoreChildren, bool ignoreBadSignatures, bool ignoreIntermediateNodes) const = 0;
virtual void getAllOdomPosesQuery(std::map<int, Transform> & poses, bool ignoreChildren, bool ignoreIntermediateNodes) const = 0; virtual void getAllOdomPosesQuery(std::map<int, Transform> & poses, bool ignoreChildren, bool ignoreIntermediateNodes) const = 0;
@@ -135,12 +135,10 @@ protected:
#endif #endif
cv::Mat * textures) const; cv::Mat * textures) const;
virtual void saveFlannIndexQuery(const std::vector<unsigned char> & indexData) const;
// Load objects // Load objects
virtual void loadQuery(VWDictionary & dictionary, bool lastStateOnly = true) const; virtual void loadQuery(VWDictionary * dictionary, bool lastStateOnly = true) const;
virtual void loadLastNodesQuery(std::list<Signature *> & signatures, bool loadWordIdsOnly) const; virtual void loadLastNodesQuery(std::list<Signature *> & signatures) const;
virtual void loadSignaturesQuery(const std::list<int> & ids, std::list<Signature *> & signatures, bool loadWordIdsOnly) const; virtual void loadSignaturesQuery(const std::list<int> & ids, std::list<Signature *> & signatures) const;
virtual void loadWordsQuery(const std::set<int> & wordIds, std::list<VisualWord *> & vws) const; virtual void loadWordsQuery(const std::set<int> & wordIds, std::list<VisualWord *> & vws) const;
virtual void loadLinksQuery(int signatureId, std::multimap<int, Link> & links, Link::Type type = Link::kUndef) const; virtual void loadLinksQuery(int signatureId, std::multimap<int, Link> & links, Link::Type type = Link::kUndef) const;
@@ -148,7 +146,6 @@ protected:
virtual bool getCalibrationQuery(int signatureId, std::vector<CameraModel> & models, std::vector<StereoCameraModel> & stereoModels) const; virtual bool getCalibrationQuery(int signatureId, std::vector<CameraModel> & models, std::vector<StereoCameraModel> & stereoModels) const;
virtual bool getLaserScanInfoQuery(int signatureId, LaserScan & info) const; virtual bool getLaserScanInfoQuery(int signatureId, LaserScan & info) const;
virtual bool getNodeInfoQuery(int signatureId, Transform & pose, int & mapId, int & weight, std::string & label, double & stamp, Transform & groundTruthPose, std::vector<float> & velocity, GPS & gps, EnvSensors & sensors) const; virtual bool getNodeInfoQuery(int signatureId, Transform & pose, int & mapId, int & weight, std::string & label, double & stamp, Transform & groundTruthPose, std::vector<float> & velocity, GPS & gps, EnvSensors & sensors) const;
virtual void getLocalFeaturesQuery(int signatureId, std::multimap<int, int> & words, std::vector<cv::KeyPoint> & keypoints, std::vector<cv::Point3f> & points, cv::Mat & descriptors) const;
virtual void getLastNodeIdsQuery(std::set<int> & ids) const; virtual void getLastNodeIdsQuery(std::set<int> & ids) const;
virtual void getAllNodeIdsQuery(std::set<int> & ids, bool ignoreChildren, bool ignoreBadSignatures, bool ignoreIntermediateNodes) const; virtual void getAllNodeIdsQuery(std::set<int> & ids, bool ignoreChildren, bool ignoreBadSignatures, bool ignoreIntermediateNodes) const;
virtual void getAllOdomPosesQuery(std::map<int, Transform> & poses, bool ignoreChildren, bool ignoreIntermediateNodes) const; virtual void getAllOdomPosesQuery(std::map<int, Transform> & poses, bool ignoreChildren, bool ignoreIntermediateNodes) const;
@@ -193,8 +190,6 @@ private:
const cv::Point3f & viewpoint) const; const cv::Point3f & viewpoint) const;
private: private:
void loadWordsQuery(std::list<Signature *> & signatures) const;
void loadWordIdsQuery(std::list<Signature *> & signatures) const;
void loadLinksQuery(std::list<Signature *> & signatures) const; void loadLinksQuery(std::list<Signature *> & signatures) const;
int loadOrSaveDb(sqlite3 *pInMemory, const std::string & fileName, int isSave) const; int loadOrSaveDb(sqlite3 *pInMemory, const std::string & fileName, int isSave) const;
+15 -26
View File
@@ -37,48 +37,37 @@ namespace rtabmap {
class RTABMAP_CORE_EXPORT FlannIndex class RTABMAP_CORE_EXPORT FlannIndex
{ {
public: public:
// A forward of the internal enum, indexes should match. See src/rtflann/defines.h
enum flann_algorithm_t
{
FLANN_INDEX_LINEAR = 0,
FLANN_INDEX_KDTREE = 1,
FLANN_INDEX_KDTREE_SINGLE = 4,
FLANN_INDEX_LSH = 6,
};
FlannIndex(); FlannIndex();
virtual ~FlannIndex(); virtual ~FlannIndex();
void release(); void release();
std::vector<unsigned char> serializeIndex(bool computeChecksum = true) const;
size_t indexedFeatures() const; size_t indexedFeatures() const;
// return Bytes // return Bytes
size_t memoryUsed() const; size_t memoryUsed() const;
// Note that useDistanceL1 doesn't have any effect if LSH is used // Note that useDistanceL1 doesn't have any effect if LSH is used
void buildIndex( void buildLinearIndex(
flann_algorithm_t algorithm,
const cv::Mat & features, const cv::Mat & features,
bool useDistanceL1 = false, bool useDistanceL1 = false,
float rebalancingFactor = 2.0f); float rebalancingFactor = 2.0f);
// Return false if the indexData doesn't correspond to expected features used and parameters. void buildKDTreeIndex(
bool loadIndex(
const std::vector<unsigned char> & indexData,
flann_algorithm_t algorithm,
const cv::Mat & features, const cv::Mat & features,
int trees = 4,
bool useDistanceL1 = false, bool useDistanceL1 = false,
float rebalancingFactor = 2.0f, float rebalancingFactor = 2.0f);
std::string * errorMsg = NULL); void buildKDTreeSingleIndex(
bool loadIndex(
const unsigned char * indexData,
size_t indexDataSize,
flann_algorithm_t algorithm,
const cv::Mat & features, const cv::Mat & features,
int leafMaxSize = 10,
bool reorder = true,
bool useDistanceL1 = false, bool useDistanceL1 = false,
float rebalancingFactor = 2.0f, float rebalancingFactor = 2.0f);
std::string * errorMsg = NULL); void buildLSHIndex(
const cv::Mat & features,
unsigned int table_number = 12,
unsigned int key_size = 20,
unsigned int multi_probe_level = 2,
float rebalancingFactor = 2.0f);
bool isBuilt(); bool isBuilt();
@@ -115,9 +104,9 @@ private:
unsigned int nextIndex_; unsigned int nextIndex_;
int featuresType_; int featuresType_;
int featuresDim_; int featuresDim_;
bool isLSH_;
bool useDistanceL1_; // true=EUCLEDIAN_L2 false=MANHATTAN_L1 bool useDistanceL1_; // true=EUCLEDIAN_L2 false=MANHATTAN_L1
float rebalancingFactor_; float rebalancingFactor_;
flann_algorithm_t algorithm_;
// keep feature in memory until the tree is rebuilt // keep feature in memory until the tree is rebuilt
// (in case the word is deleted when removed from the VWDictionary) // (in case the word is deleted when removed from the VWDictionary)
-1
View File
@@ -53,7 +53,6 @@ public:
public: public:
virtual ~GlobalMap(); virtual ~GlobalMap();
bool fullUpdateNeeded(const std::map<int, Transform> & poses) const;
bool update(const std::map<int, Transform> & poses); // return true if map has changed bool update(const std::map<int, Transform> & poses); // return true if map has changed
virtual void clear(); virtual void clear();
+1 -1
View File
@@ -56,7 +56,7 @@ bool RTABMAP_CORE_EXPORT exportPoses(
bool RTABMAP_CORE_EXPORT importPoses( bool RTABMAP_CORE_EXPORT importPoses(
const std::string & filePath, const std::string & filePath,
int format, // 0=Raw, 1=RGBD-SLAM motion capture (10=without change of coordinate frame, 11=10+ID), 2=KITTI, 3=TORO, 4=g2o, 5=NewCollege(t,x,y), 6=Malaga Urban GPS, 7=St Lucia INS, 8=Karlsruhe, 9=EuRoC MAV, 12=rgbd_bonn int format, // 0=Raw, 1=RGBD-SLAM motion capture (10=without change of coordinate frame, 11=10+ID), 2=KITTI, 3=TORO, 4=g2o, 5=NewCollege(t,x,y), 6=Malaga Urban GPS, 7=St Lucia INS, 8=Karlsruhe, 9=EuRoC MAV
std::map<int, Transform> & poses, std::map<int, Transform> & poses,
std::multimap<int, Link> * constraints = 0, // optional for formats 3 and 4 std::multimap<int, Link> * constraints = 0, // optional for formats 3 and 4
std::map<int, double> * stamps = 0); // optional for format 1 and 9 std::map<int, double> * stamps = 0); // optional for format 1 and 9
-4
View File
@@ -264,7 +264,6 @@ private:
void addSignatureToStm(Signature * signature, const cv::Mat & covariance); void addSignatureToStm(Signature * signature, const cv::Mat & covariance);
void clear(); void clear();
void loadDataFromDb(bool postInitClosingEvents); void loadDataFromDb(bool postInitClosingEvents);
void saveFlannIndex(bool postInitClosingEvents);
void moveToTrash(Signature * s, bool keepLinkedToGraph = true, std::list<int> * deletedWords = 0); void moveToTrash(Signature * s, bool keepLinkedToGraph = true, std::list<int> * deletedWords = 0);
void moveSignatureToWMFromSTM(int id, int * reducedTo = 0); void moveSignatureToWMFromSTM(int id, int * reducedTo = 0);
@@ -300,7 +299,6 @@ private:
float _similarityThreshold; float _similarityThreshold;
bool _binDataKept; bool _binDataKept;
bool _rawDescriptorsKept; bool _rawDescriptorsKept;
bool _loadVisualLocalFeaturesOnInit;
bool _saveDepth16Format; bool _saveDepth16Format;
bool _notLinkedNodesKeptInDb; bool _notLinkedNodesKeptInDb;
bool _saveIntermediateNodeData; bool _saveIntermediateNodeData;
@@ -308,7 +306,6 @@ private:
std::string _depthCompressionFormat; std::string _depthCompressionFormat;
bool _incrementalMemory; bool _incrementalMemory;
bool _localizationDataSaved; bool _localizationDataSaved;
bool _flannIndexSaved;
bool _reduceGraph; bool _reduceGraph;
int _maxStMemSize; int _maxStMemSize;
float _recentWmRatio; float _recentWmRatio;
@@ -356,7 +353,6 @@ private:
bool _linksChanged; // False by default, become true when links are modified. bool _linksChanged; // False by default, become true when links are modified.
int _signaturesAdded; int _signaturesAdded;
bool _allNodesInWM; bool _allNodesInWM;
bool _receivingOdometryFeatures;
GPS _gpsOrigin; GPS _gpsOrigin;
std::vector<CameraModel> _rectCameraModels; std::vector<CameraModel> _rectCameraModels;
std::vector<StereoCameraModel> _rectStereoCameraModels; std::vector<StereoCameraModel> _rectStereoCameraModels;
+2 -3
View File
@@ -53,11 +53,10 @@ public:
kTypeOkvis = 6, kTypeOkvis = 6,
kTypeLOAM = 7, kTypeLOAM = 7,
kTypeMSCKF = 8, kTypeMSCKF = 8,
kTypeVINSFusion = 9, kTypeVINS = 9,
kTypeOpenVINS = 10, kTypeOpenVINS = 10,
kTypeFLOAM = 11, kTypeFLOAM = 11,
kTypeOpen3D = 12, kTypeOpen3D = 12
kTypeCuVSLAM = 13
}; };
public: public:
@@ -29,7 +29,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define ODOMETRYTHREAD_H_ #define ODOMETRYTHREAD_H_
#include <rtabmap/core/rtabmap_core_export.h> #include <rtabmap/core/rtabmap_core_export.h>
#include <rtabmap/core/SensorEvent.h>
#include <rtabmap/core/SensorData.h> #include <rtabmap/core/SensorData.h>
#include <rtabmap/utilite/UThread.h> #include <rtabmap/utilite/UThread.h>
#include <rtabmap/utilite/UEventsHandler.h> #include <rtabmap/utilite/UEventsHandler.h>
@@ -56,21 +55,20 @@ private:
// MAIN LOOP // MAIN LOOP
//============================================================ //============================================================
virtual void mainLoop(); virtual void mainLoop();
void addData(const SensorEvent & data); void addData(const SensorData & data);
bool getData(SensorEvent & data); bool getData(SensorData & data);
private: private:
USemaphore _dataAdded; USemaphore _dataAdded;
UMutex _dataMutex; UMutex _dataMutex;
std::list<SensorEvent> _dataBuffer; std::list<SensorData> _dataBuffer;
std::list<SensorData> _imuBuffer; std::list<SensorData> _imuBuffer;
Odometry * _odometry; Odometry * _odometry;
unsigned int _dataBufferMaxSize; unsigned int _dataBufferMaxSize;
bool _resetOdometry; bool _resetOdometry;
Transform _resetPose; Transform _resetPose;
Transform _previousGuessPose; double _lastImuStamp;
double _oldestAsyncImuStamp; double _imuEstimatedDelay;
double _newestAsyncImuStamp;
}; };
} // namespace rtabmap } // namespace rtabmap
+7 -10
View File
@@ -204,7 +204,6 @@ class RTABMAP_CORE_EXPORT Parameters
RTABMAP_PARAM(Mem, ImageKept, bool, false, "Keep raw images in RAM."); RTABMAP_PARAM(Mem, ImageKept, bool, false, "Keep raw images in RAM.");
RTABMAP_PARAM(Mem, BinDataKept, bool, true, "Keep binary data in db."); RTABMAP_PARAM(Mem, BinDataKept, bool, true, "Keep binary data in db.");
RTABMAP_PARAM(Mem, RawDescriptorsKept, bool, true, "Raw descriptors kept in memory."); RTABMAP_PARAM(Mem, RawDescriptorsKept, bool, true, "Raw descriptors kept in memory.");
RTABMAP_PARAM(Mem, LoadVisualLocalFeaturesOnInit, bool, true, "Load all local visual features (keypoints, descriptors and 3D points) in RAM when loading an existing database. This can add significant time to initialize the memory but the features will be already loaded before computing loop closure transforms. If false, the features are loaded on-demand from the database when a loop closure transformation should be estimated.");
RTABMAP_PARAM(Mem, MapLabelsAdded, bool, true, "Create map labels. The first node of a map will be labeled as \"map#\" where # is the map ID."); RTABMAP_PARAM(Mem, MapLabelsAdded, bool, true, "Create map labels. The first node of a map will be labeled as \"map#\" where # is the map ID.");
RTABMAP_PARAM(Mem, SaveDepth16Format, bool, false, "Save depth image into 16 bits format to reduce memory used. Warning: values over ~65 meters are ignored (maximum 65535 millimeters)."); RTABMAP_PARAM(Mem, SaveDepth16Format, bool, false, "Save depth image into 16 bits format to reduce memory used. Warning: values over ~65 meters are ignored (maximum 65535 millimeters).");
RTABMAP_PARAM(Mem, NotLinkedNodesKept, bool, true, "Keep not linked nodes in db (rehearsed nodes and deleted nodes)."); RTABMAP_PARAM(Mem, NotLinkedNodesKept, bool, true, "Keep not linked nodes in db (rehearsed nodes and deleted nodes).");
@@ -214,7 +213,7 @@ class RTABMAP_CORE_EXPORT Parameters
RTABMAP_PARAM(Mem, STMSize, unsigned int, 10, "Short-term memory size."); RTABMAP_PARAM(Mem, STMSize, unsigned int, 10, "Short-term memory size.");
RTABMAP_PARAM(Mem, IncrementalMemory, bool, true, "SLAM mode, otherwise it is Localization mode."); RTABMAP_PARAM(Mem, IncrementalMemory, bool, true, "SLAM mode, otherwise it is Localization mode.");
RTABMAP_PARAM(Mem, LocalizationDataSaved, bool, false, uFormat("Save localization data during localization session (when %s=false). When enabled, the database will then also grow in localization mode. This mode would be used only for debugging purpose.", kMemIncrementalMemory().c_str()).c_str()); RTABMAP_PARAM(Mem, LocalizationDataSaved, bool, false, uFormat("Save localization data during localization session (when %s=false). When enabled, the database will then also grow in localization mode. This mode would be used only for debugging purpose.", kMemIncrementalMemory().c_str()).c_str());
RTABMAP_PARAM(Mem, ReduceGraph, bool, false, uFormat("Reduce graph. Merge nodes when loop closures are added (ignoring those with user data). Note that this approach assumes that 100%% of the loop closures accepted are good, so it is highly recommended to enable \"%s\" at the same time.", kRGBDOptimizeMaxError().c_str())); RTABMAP_PARAM(Mem, ReduceGraph, bool, false, "Reduce graph. Merge nodes when loop closures are added (ignoring those with user data set).");
RTABMAP_PARAM(Mem, RecentWmRatio, float, 0.2, "Ratio of locations after the last loop closure in WM that cannot be transferred."); RTABMAP_PARAM(Mem, RecentWmRatio, float, 0.2, "Ratio of locations after the last loop closure in WM that cannot be transferred.");
RTABMAP_PARAM(Mem, TransferSortingByWeightId, bool, false, "On transfer, signatures are sorted by weight->ID only (i.e. the oldest of the lowest weighted signatures are transferred first). If false, the signatures are sorted by weight->Age->ID (i.e. the oldest inserted in WM of the lowest weighted signatures are transferred first). Note that retrieval updates the age, not the ID."); RTABMAP_PARAM(Mem, TransferSortingByWeightId, bool, false, "On transfer, signatures are sorted by weight->ID only (i.e. the oldest of the lowest weighted signatures are transferred first). If false, the signatures are sorted by weight->Age->ID (i.e. the oldest inserted in WM of the lowest weighted signatures are transferred first). Note that retrieval updates the age, not the ID.");
RTABMAP_PARAM(Mem, RehearsalIdUpdatedToNewOne, bool, false, "On merge, update to new id. When false, no copy."); RTABMAP_PARAM(Mem, RehearsalIdUpdatedToNewOne, bool, false, "On merge, update to new id. When false, no copy.");
@@ -261,8 +260,6 @@ class RTABMAP_CORE_EXPORT Parameters
RTABMAP_PARAM_STR(Kp, RoiRatios, "0.0 0.0 0.0 0.0", "Region of interest ratios [left, right, top, bottom]."); RTABMAP_PARAM_STR(Kp, RoiRatios, "0.0 0.0 0.0 0.0", "Region of interest ratios [left, right, top, bottom].");
RTABMAP_PARAM_STR(Kp, DictionaryPath, "", "Path of the pre-computed dictionary"); RTABMAP_PARAM_STR(Kp, DictionaryPath, "", "Path of the pre-computed dictionary");
RTABMAP_PARAM(Kp, NewWordsComparedTogether, bool, true, "When adding new words to dictionary, they are compared also with each other (to detect same words in the same signature)."); RTABMAP_PARAM(Kp, NewWordsComparedTogether, bool, true, "When adding new words to dictionary, they are compared also with each other (to detect same words in the same signature).");
RTABMAP_PARAM(Kp, FlannIndexSaved, bool, false, uFormat("Save FLANN index during localization session (when %s=false). The FLANN index will be saved to database after the first time localization mode is used, then on next sessions, the index is reloaded from the database instead of being rebuilt again. This can save significant loading time when the visual word dictionary is big (>1M words). Note that if the dictionary is modified (parameters or data), the index will be rebuilt and saved again on the next session.", kMemIncrementalMemory().c_str()).c_str());
RTABMAP_PARAM(Kp, SerializeWithChecksum, bool, true, "On serialization of the FLANN index, compute checksum of the data used by the FLANN index. This adds a slight overhead on serialization/deserialization to make sure that the dictionary data correspond to same data used when the index was built.");
RTABMAP_PARAM(Kp, SubPixWinSize, int, 3, "See cv::cornerSubPix()."); RTABMAP_PARAM(Kp, SubPixWinSize, int, 3, "See cv::cornerSubPix().");
RTABMAP_PARAM(Kp, SubPixIterations, int, 0, "See cv::cornerSubPix(). 0 disables sub pixel refining."); RTABMAP_PARAM(Kp, SubPixIterations, int, 0, "See cv::cornerSubPix(). 0 disables sub pixel refining.");
RTABMAP_PARAM(Kp, SubPixEps, double, 0.02, "See cv::cornerSubPix()."); RTABMAP_PARAM(Kp, SubPixEps, double, 0.02, "See cv::cornerSubPix().");
@@ -369,7 +366,7 @@ class RTABMAP_CORE_EXPORT Parameters
RTABMAP_PARAM(RGBD, AggressiveLoopThr, float, 0.05, uFormat("Loop closure threshold used (overriding %s) when a new mapping session is not yet linked to a map of the highest loop closure hypothesis. In localization mode, this threshold is used when there are no loop closure constraints with any map in the cache (%s). In all cases, the goal is to aggressively loop on a previous map in the database. Only used when %s is enabled. Set 1 to disable.", kRtabmapLoopThr().c_str(), kRGBDMaxOdomCacheSize().c_str(), kRGBDEnabled().c_str())); RTABMAP_PARAM(RGBD, AggressiveLoopThr, float, 0.05, uFormat("Loop closure threshold used (overriding %s) when a new mapping session is not yet linked to a map of the highest loop closure hypothesis. In localization mode, this threshold is used when there are no loop closure constraints with any map in the cache (%s). In all cases, the goal is to aggressively loop on a previous map in the database. Only used when %s is enabled. Set 1 to disable.", kRtabmapLoopThr().c_str(), kRGBDMaxOdomCacheSize().c_str(), kRGBDEnabled().c_str()));
RTABMAP_PARAM(RGBD, NewMapOdomChangeDistance, float, 0, "A new map is created if a change of odometry translation greater than X m is detected (0 m = disabled)."); RTABMAP_PARAM(RGBD, NewMapOdomChangeDistance, float, 0, "A new map is created if a change of odometry translation greater than X m is detected (0 m = disabled).");
RTABMAP_PARAM(RGBD, OptimizeFromGraphEnd, bool, false, "Optimize graph from the newest node. If false, the graph is optimized from the oldest node of the current graph (this adds an overhead computation to detect to oldest node of the current graph, but it can be useful to preserve the map referential from the oldest node). Warning when set to false: when some nodes are transferred, the first referential of the local map may change, resulting in momentary changes in robot/map position (which are annoying in teleoperation)."); RTABMAP_PARAM(RGBD, OptimizeFromGraphEnd, bool, false, "Optimize graph from the newest node. If false, the graph is optimized from the oldest node of the current graph (this adds an overhead computation to detect to oldest node of the current graph, but it can be useful to preserve the map referential from the oldest node). Warning when set to false: when some nodes are transferred, the first referential of the local map may change, resulting in momentary changes in robot/map position (which are annoying in teleoperation).");
RTABMAP_PARAM(RGBD, OptimizeMaxError, float, 3.0, uFormat("Reject loop closures if optimization error ratio is greater than this value (0=disabled). Ratio is computed as absolute error over standard deviation of each link. This will help to detect when a wrong loop closure is added to the graph. If used with \"%s\", the disabled loop closure links will be removed.", kOptimizerRobust().c_str())); RTABMAP_PARAM(RGBD, OptimizeMaxError, float, 3.0, uFormat("Reject loop closures if optimization error ratio is greater than this value (0=disabled). Ratio is computed as absolute error over standard deviation of each link. This will help to detect when a wrong loop closure is added to the graph. Not compatible with \"%s\" if enabled.", kOptimizerRobust().c_str()));
RTABMAP_PARAM(RGBD, MaxLoopClosureDistance, float, 0.0, "Reject loop closures/localizations if the distance from the map is over this distance (0=disabled)."); RTABMAP_PARAM(RGBD, MaxLoopClosureDistance, float, 0.0, "Reject loop closures/localizations if the distance from the map is over this distance (0=disabled).");
RTABMAP_PARAM(RGBD, ForceOdom3DoF, bool, true, uFormat("Force odometry pose to be 3DoF if %s=true.", kRegForce3DoF().c_str())); RTABMAP_PARAM(RGBD, ForceOdom3DoF, bool, true, uFormat("Force odometry pose to be 3DoF if %s=true.", kRegForce3DoF().c_str()));
RTABMAP_PARAM(RGBD, StartAtOrigin, bool, false, uFormat("If true, rtabmap will assume the robot is starting from origin of the map. If false, rtabmap will assume the robot is restarting from the last saved localization pose from previous session (the place where it shut down previously). Used only in localization mode (%s=false).", kMemIncrementalMemory().c_str())); RTABMAP_PARAM(RGBD, StartAtOrigin, bool, false, uFormat("If true, rtabmap will assume the robot is starting from origin of the map. If false, rtabmap will assume the robot is restarting from the last saved localization pose from previous session (the place where it shut down previously). Used only in localization mode (%s=false).", kMemIncrementalMemory().c_str()));
@@ -431,7 +428,7 @@ class RTABMAP_CORE_EXPORT Parameters
#endif #endif
#endif #endif
RTABMAP_PARAM(Optimizer, VarianceIgnored, bool, false, "Ignore constraints' variance. If checked, identity information matrix is used for each constraint. Otherwise, an information matrix is generated from the variance saved in the links."); RTABMAP_PARAM(Optimizer, VarianceIgnored, bool, false, "Ignore constraints' variance. If checked, identity information matrix is used for each constraint. Otherwise, an information matrix is generated from the variance saved in the links.");
RTABMAP_PARAM(Optimizer, Robust, bool, false, "Robust graph optimization using Vertigo (only work for g2o and GTSAM optimization strategies)."); RTABMAP_PARAM(Optimizer, Robust, bool, false, uFormat("Robust graph optimization using Vertigo (only work for g2o and GTSAM optimization strategies). Not compatible with \"%s\" if enabled.", kRGBDOptimizeMaxError().c_str()));
RTABMAP_PARAM(Optimizer, PriorsIgnored, bool, true, "Ignore prior constraints (global pose or GPS) while optimizing. Currently only g2o and gtsam optimization supports this."); RTABMAP_PARAM(Optimizer, PriorsIgnored, bool, true, "Ignore prior constraints (global pose or GPS) while optimizing. Currently only g2o and gtsam optimization supports this.");
RTABMAP_PARAM(Optimizer, LandmarksIgnored, bool, false, "Ignore landmark constraints while optimizing. Currently only g2o and gtsam optimization supports this."); RTABMAP_PARAM(Optimizer, LandmarksIgnored, bool, false, "Ignore landmark constraints while optimizing. Currently only g2o and gtsam optimization supports this.");
#if defined(RTABMAP_G2O) || defined(RTABMAP_GTSAM) #if defined(RTABMAP_G2O) || defined(RTABMAP_GTSAM)
@@ -456,8 +453,8 @@ class RTABMAP_CORE_EXPORT Parameters
RTABMAP_PARAM(GTSAM, IncRelinearizeSkip, int, 1, "Only relinearize any variables every X calls to ISAM2::update(). See GTSAM::ISAM2 doc for more info."); RTABMAP_PARAM(GTSAM, IncRelinearizeSkip, int, 1, "Only relinearize any variables every X calls to ISAM2::update(). See GTSAM::ISAM2 doc for more info.");
// Odometry // Odometry
RTABMAP_PARAM(Odom, Strategy, int, 0, "0=Frame-to-Map (F2M) 1=Frame-to-Frame (F2F) 2=Fovis 3=viso2 4=DVO-SLAM 5=ORB_SLAM2 6=OKVIS 7=LOAM 8=MSCKF_VIO 9=VINS-Fusion 10=OpenVINS 11=FLOAM 12=Open3D 13=cuVSLAM"); RTABMAP_PARAM(Odom, Strategy, int, 0, "0=Frame-to-Map (F2M) 1=Frame-to-Frame (F2F) 2=Fovis 3=viso2 4=DVO-SLAM 5=ORB_SLAM2 6=OKVIS 7=LOAM 8=MSCKF_VIO 9=VINS-Fusion 10=OpenVINS 11=FLOAM 12=Open3D");
RTABMAP_PARAM(Odom, ResetCountdown, int, 0, "Automatically reset odometry after X consecutive images where odometry cannot be computed (a value of 0 disables auto-reset). When a reset occurs, odometry resumes from the last successfully computed pose with large covariance to trigger a new map. If external odometry is used, it will also be reset based on the motion estimated relative to the last computed pose but no large covariance will be received, so that a new map won't be triggered."); RTABMAP_PARAM(Odom, ResetCountdown, int, 0, "Automatically reset odometry after X consecutive images on which odometry cannot be computed (value=0 disables auto-reset).");
RTABMAP_PARAM(Odom, Holonomic, bool, true, "If the robot is holonomic (strafing commands can be issued). If not, y value will be estimated from x and yaw values (y=x*tan(yaw))."); RTABMAP_PARAM(Odom, Holonomic, bool, true, "If the robot is holonomic (strafing commands can be issued). If not, y value will be estimated from x and yaw values (y=x*tan(yaw)).");
RTABMAP_PARAM(Odom, FillInfoData, bool, true, "Fill info with data (inliers/outliers features)."); RTABMAP_PARAM(Odom, FillInfoData, bool, true, "Fill info with data (inliers/outliers features).");
RTABMAP_PARAM(Odom, ImageBufferSize, unsigned int, 1, "Data buffer size (0 min inf)."); RTABMAP_PARAM(Odom, ImageBufferSize, unsigned int, 1, "Data buffer size (0 min inf).");
@@ -606,8 +603,8 @@ class RTABMAP_CORE_EXPORT Parameters
RTABMAP_PARAM(OdomMSCKF, InitCovExTrans, double, 0.000025, ""); RTABMAP_PARAM(OdomMSCKF, InitCovExTrans, double, 0.000025, "");
RTABMAP_PARAM(OdomMSCKF, MaxCamStateSize, int, 20, ""); RTABMAP_PARAM(OdomMSCKF, MaxCamStateSize, int, 20, "");
// Odometry VINS-Fusion // Odometry VINS
RTABMAP_PARAM_STR(OdomVINSFusion, ConfigPath, "", "Path of VINS-Fusion config file."); RTABMAP_PARAM_STR(OdomVINS, ConfigPath, "", "Path of VINS config file.");
// Odometry OpenVINS // Odometry OpenVINS
RTABMAP_PARAM(OdomOpenVINS, UseStereo, bool, true, "If we have more than 1 camera, if we should try to track stereo constraints between pairs"); RTABMAP_PARAM(OdomOpenVINS, UseStereo, bool, true, "If we have more than 1 camera, if we should try to track stereo constraints between pairs");
@@ -8,7 +8,6 @@
#ifndef CORELIB_SRC_PYTHON_PYTHONINTERFACE_H_ #ifndef CORELIB_SRC_PYTHON_PYTHONINTERFACE_H_
#define CORELIB_SRC_PYTHON_PYTHONINTERFACE_H_ #define CORELIB_SRC_PYTHON_PYTHONINTERFACE_H_
#include "rtabmap/core/rtabmap_core_export.h" // DLL export/import defines
#include <string> #include <string>
#include <rtabmap/utilite/UMutex.h> #include <rtabmap/utilite/UMutex.h>
@@ -24,7 +23,7 @@ namespace rtabmap {
* Create a single PythonInterface on main thread at * Create a single PythonInterface on main thread at
* global scope before any Python classes. * global scope before any Python classes.
*/ */
class RTABMAP_CORE_EXPORT PythonInterface class PythonInterface
{ {
public: public:
PythonInterface(); PythonInterface();
@@ -35,7 +34,7 @@ private:
pybind11::gil_scoped_release* release_; pybind11::gil_scoped_release* release_;
}; };
std::string RTABMAP_CORE_EXPORT getPythonTraceback(); std::string getPythonTraceback();
} }
+2
View File
@@ -50,6 +50,7 @@ class BayesFilter;
class Signature; class Signature;
class Optimizer; class Optimizer;
class PythonInterface; class PythonInterface;
class DBDriver;
class RTABMAP_CORE_EXPORT Rtabmap class RTABMAP_CORE_EXPORT Rtabmap
{ {
@@ -371,6 +372,7 @@ private:
Transform _lastLocalizationPose; // Corrected odometry pose. In mapping mode, this corresponds to last pose return by getLocalOptimizedPoses(). Transform _lastLocalizationPose; // Corrected odometry pose. In mapping mode, this corresponds to last pose return by getLocalOptimizedPoses().
int _lastLocalizationNodeId; // for localization mode int _lastLocalizationNodeId; // for localization mode
cv::Mat _localizationCovariance; cv::Mat _localizationCovariance;
DBDriver * _externalLocalizationDbDriver;
std::map<int, std::pair<cv::Point3d, Transform> > _gpsGeocentricCache; std::map<int, std::pair<cv::Point3d, Transform> > _gpsGeocentricCache;
bool _currentSessionHasGPS; bool _currentSessionHasGPS;
LaserScan _globalScanMap; LaserScan _globalScanMap;
@@ -107,11 +107,7 @@ public:
bool isIncrementalFlann() const {return _incrementalFlann;} bool isIncrementalFlann() const {return _incrementalFlann;}
void setIncrementalDictionary(); void setIncrementalDictionary();
void setFixedDictionary(const std::string & dictionaryPath); void setFixedDictionary(const std::string & dictionaryPath);
bool isModified() const;
std::vector<unsigned char> serializeIndex() const;
void deserializeIndex(const std::vector<unsigned char> & data);
void deserializeIndex(const unsigned char * data, size_t size);
void exportDictionary(const char * fileNameReferences, const char * fileNameDescriptors) const; void exportDictionary(const char * fileNameReferences, const char * fileNameDescriptors) const;
void clear(bool printWarningsIfNotEmpty = true); void clear(bool printWarningsIfNotEmpty = true);
@@ -141,12 +137,10 @@ private:
std::string _dictionaryPath; // a pre-computed dictionary (.txt or .db) std::string _dictionaryPath; // a pre-computed dictionary (.txt or .db)
std::string _newDictionaryPath; // a pre-computed dictionary (.txt or .db) std::string _newDictionaryPath; // a pre-computed dictionary (.txt or .db)
bool _newWordsComparedTogether; bool _newWordsComparedTogether;
bool _serializeWithChecksum;
int _lastWordId; int _lastWordId;
bool useDistanceL1_; bool useDistanceL1_;
FlannIndex * _flannIndex; FlannIndex * _flannIndex;
cv::Mat _dataTree; cv::Mat _dataTree;
bool _modified;
NNStrategy _strategy; NNStrategy _strategy;
std::map<int ,int> _mapIndexId; std::map<int ,int> _mapIndexId;
std::map<int ,int> _mapIdIndex; std::map<int ,int> _mapIdIndex;
@@ -94,14 +94,14 @@ public:
_depthFromScanFillHolesFromBorder = fillHolesFromBorder; _depthFromScanFillHolesFromBorder = fillHolesFromBorder;
} }
// 0=Raw, 1=RGBD-SLAM motion capture (10=without change of coordinate frame, 11=10+ID), 2=KITTI, 3=TORO, 4=g2o, 5=NewCollege(t,x,y), 6=Malaga Urban GPS, 7=St Lucia INS, 8=Karlsruhe, 9=EuRoC MAV, 12=rgbd_bonn // Format: 0=Raw, 1=RGBD-SLAM, 2=KITTI, 3=TORO, 4=g2o, 5=NewCollege(t,x,y), 6=Malaga Urban GPS, 7=St Lucia INS, 8=Karlsruhe
void setOdometryPath(const std::string & filePath, int format = 0) void setOdometryPath(const std::string & filePath, int format = 0)
{ {
_odometryPath = filePath; _odometryPath = filePath;
_odometryFormat = format; _odometryFormat = format;
} }
// 0=Raw, 1=RGBD-SLAM motion capture (10=without change of coordinate frame, 11=10+ID), 2=KITTI, 3=TORO, 4=g2o, 5=NewCollege(t,x,y), 6=Malaga Urban GPS, 7=St Lucia INS, 8=Karlsruhe, 9=EuRoC MAV, 12=rgbd_bonn // Format: 0=Raw, 1=RGBD-SLAM, 2=KITTI, 3=TORO, 4=g2o, 5=NewCollege(t,x,y), 6=Malaga Urban GPS, 7=St Lucia INS, 8=Karlsruhe
void setGroundTruthPath(const std::string & filePath, int format = 0) void setGroundTruthPath(const std::string & filePath, int format = 0)
{ {
_groundTruthPath = filePath; _groundTruthPath = filePath;
@@ -1,105 +0,0 @@
/*
Copyright (c) 2010-2025, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Universite de Sherbrooke nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include "rtabmap/core/CameraModel.h"
#include "rtabmap/core/Camera.h"
#include "rtabmap/core/Version.h"
#ifdef RTABMAP_ORBBEC_SDK
namespace ob
{
class Pipeline;
class Align;
}
#endif
namespace rtabmap
{
class RTABMAP_CORE_EXPORT CameraOrbbecSDK :
public Camera
{
public:
static bool available();
public:
// deviceId can be either an index (e.g., "0"), an UID (e.g, "2-1-2" or "gmsl-1") or a serial ("AAA6454S")
CameraOrbbecSDK(
std::string deviceId = "",
int colorWidth = 800,
int colorHeight = 600,
int depthWidth = 800,
int depthHeight = 600,
float imageRate = 0.0f,
const Transform & localTransform = Transform::getIdentity());
virtual ~CameraOrbbecSDK();
virtual bool init(const std::string & calibrationFolder = ".", const std::string & cameraName = "");
virtual bool isCalibrated() const;
virtual std::string getSerial() const;
void close();
// Should be set before initializing
void enableColorRectification(bool enabled);
void enableImu(bool enabled);
void enableDepthMM(bool enabled);
protected:
virtual SensorData captureImage(SensorCaptureInfo * info = 0);
private:
#ifdef RTABMAP_ORBBEC_SDK
std::string deviceId_;
int colorWidth_;
int colorHeight_;
int depthWidth_;
int depthHeight_;
ob::Pipeline * pipeline_;
ob::Pipeline * imuPipeline_;
ob::Align * alignFilter_;
CameraModel model_;
Transform imuLocalTransform_;
bool imuLocalTransformInitialized_;
uint64_t lastAccStamp_;
uint64_t lastImageStamp_;
bool globalTimestampAvailable_;
bool rectifyColor_;
bool convertDepthToMM_;
bool imuPublished_;
std::map<double, cv::Vec6f> imuBuffer_;
UMutex imuMutex_;
#endif
};
} // namespace rtabmap
@@ -1,86 +0,0 @@
/*
Copyright (c) 2025 Felix Toft
Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Universite de Sherbrooke nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef ODOMETRYCUVSLAM_H_
#define ODOMETRYCUVSLAM_H_
#include <rtabmap/core/Odometry.h>
#include <memory>
#ifdef RTABMAP_CUVSLAM
#include <cuvslam.h>
#include <ground_constraint.h>
#include <cuda_runtime.h>
#endif
namespace rtabmap {
class RTABMAP_CORE_EXPORT OdometryCuVSLAM : public Odometry
{
public:
OdometryCuVSLAM(const rtabmap::ParametersMap & parameters = rtabmap::ParametersMap());
virtual ~OdometryCuVSLAM();
virtual void reset(const Transform & initialPose = Transform::getIdentity());
virtual Odometry::Type getType() {return Odometry::kTypeCuVSLAM;}
private:
virtual Transform computeTransform(SensorData & image, const Transform & guess = Transform(), OdometryInfo * info = 0);
private:
#ifdef RTABMAP_CUVSLAM
CUVSLAM_TrackerHandle cuvslam_handle_;
CUVSLAM_GroundConstraintHandle ground_constraint_handle_;
std::vector<CUVSLAM_Camera> cuvslam_cameras_;
std::vector<std::array<float, 12>> intrinsics_;
// State tracking
bool initialized_;
bool lost_;
bool tracking_;
bool planar_constraints_;
Transform previous_pose_;
double last_timestamp_;
//visualization
std::vector<CUVSLAM_Observation> observations_;
std::vector<CUVSLAM_Landmark> landmarks_;
// GPU memory management
std::vector<uint8_t *> gpu_left_image_data_; // pointers to all gpu images
std::vector<uint8_t *> gpu_right_image_data_;
std::vector<size_t> gpu_left_image_sizes_; // size of one image
std::vector<size_t> gpu_right_image_sizes_;
cudaStream_t cuda_stream_;
#endif
};
}
#endif /* ODOMETRYCUVSLAM_H_ */
@@ -25,7 +25,39 @@ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#pragma once #ifndef ODOMETRYVINS_H_
#pragma message("Warning: OdometryVINS.h is deprecated. Please use OdometryVINSFusion.h instead.") #define ODOMETRYVINS_H_
#include "rtabmap/core/odometry/OdometryVINSFusion.h" #include <rtabmap/core/Odometry.h>
namespace rtabmap {
class VinsEstimator;
class RTABMAP_CORE_EXPORT OdometryVINS : public Odometry
{
public:
OdometryVINS(const rtabmap::ParametersMap & parameters = rtabmap::ParametersMap());
virtual ~OdometryVINS();
virtual void reset(const Transform & initialPose = Transform::getIdentity());
virtual Odometry::Type getType() {return Odometry::kTypeVINS;}
virtual bool canProcessRawImages() const {return true;}
virtual bool canProcessAsyncIMU() const {return true;}
private:
virtual Transform computeTransform(SensorData & image, const Transform & guess = Transform(), OdometryInfo * info = 0);
private:
#ifdef RTABMAP_VINS
VinsEstimator * vinsEstimator_;
bool initGravity_;
Transform previousPose_;
Transform previousLocalTransform_;
IMU lastImu_;
#endif
};
}
#endif /* ODOMETRYVINS_H_ */
@@ -1,64 +0,0 @@
/*
Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Universite de Sherbrooke nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef ODOMETRYVINSFUSION_H_
#define ODOMETRYVINSFUSION_H_
#include <rtabmap/core/Odometry.h>
namespace rtabmap {
class VinsFusionEstimator;
class RTABMAP_CORE_EXPORT OdometryVINSFusion : public Odometry
{
public:
OdometryVINSFusion(const rtabmap::ParametersMap & parameters = rtabmap::ParametersMap());
virtual ~OdometryVINSFusion();
virtual void reset(const Transform & initialPose = Transform::getIdentity());
virtual Odometry::Type getType() {return Odometry::kTypeVINSFusion;}
virtual bool canProcessRawImages() const {return true;}
virtual bool canProcessAsyncIMU() const {return true;}
private:
virtual Transform computeTransform(SensorData & image, const Transform & guess = Transform(), OdometryInfo * info = 0);
private:
#ifdef RTABMAP_VINS_FUSION
VinsFusionEstimator * vinsEstimator_;
bool initGravity_;
Transform previousPose_;
Transform previousLocalTransform_;
IMU lastImu_;
double lastImuStamp_;
#endif
};
}
#endif /* ODOMETRYVINSFUSION_H_ */
+7 -24
View File
@@ -41,7 +41,6 @@ SET(SRC_FILES
camera/CameraMyntEye.cpp camera/CameraMyntEye.cpp
camera/CameraDepthAI.cpp camera/CameraDepthAI.cpp
camera/CameraSeerSense.cpp camera/CameraSeerSense.cpp
camera/CameraOrbbecSDK.cpp
EpipolarGeometry.cpp EpipolarGeometry.cpp
VisualWord.cpp VisualWord.cpp
@@ -99,10 +98,9 @@ SET(SRC_FILES
odometry/OdometryLOAM.cpp odometry/OdometryLOAM.cpp
odometry/OdometryFLOAM.cpp odometry/OdometryFLOAM.cpp
odometry/OdometryMSCKF.cpp odometry/OdometryMSCKF.cpp
odometry/OdometryVINSFusion.cpp odometry/OdometryVINS.cpp
odometry/OdometryOpenVINS.cpp odometry/OdometryOpenVINS.cpp
odometry/OdometryOpen3D.cpp odometry/OdometryOpen3D.cpp
odometry/OdometryCuVSLAM.cpp
IMU.cpp IMU.cpp
IMUThread.cpp IMUThread.cpp
@@ -165,6 +163,10 @@ IF(MSVC)
ENDIF(MSVC) ENDIF(MSVC)
SET(INCLUDE_DIRS SET(INCLUDE_DIRS
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/../include
${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_CURRENT_BINARY_DIR}/include
${ZLIB_INCLUDE_DIRS} ${ZLIB_INCLUDE_DIRS}
) )
@@ -392,13 +394,6 @@ IF(xvsdk_FOUND)
) )
ENDIF(xvsdk_FOUND) ENDIF(xvsdk_FOUND)
IF(OrbbecSDK_FOUND)
SET(LIBRARIES
${LIBRARIES}
ob::OrbbecSDK
)
ENDIF(OrbbecSDK_FOUND)
IF(TARGET OpenMP::OpenMP_CXX) IF(TARGET OpenMP::OpenMP_CXX)
SET(LIBRARIES SET(LIBRARIES
${LIBRARIES} ${LIBRARIES}
@@ -773,13 +768,6 @@ IF(ORB_SLAM_FOUND)
) )
ENDIF(ORB_SLAM_FOUND) ENDIF(ORB_SLAM_FOUND)
IF(CUVSLAM_FOUND)
SET(LIBRARIES
${LIBRARIES}
cuvslam::cuvslam
)
ENDIF(CUVSLAM_FOUND)
IF(GTSAM_FOUND) IF(GTSAM_FOUND)
# Make sure GTSAM is built with system Eigen, not the included one in its package # Make sure GTSAM is built with system Eigen, not the included one in its package
IF(GTSAM_INCLUDE_DIR) IF(GTSAM_INCLUDE_DIR)
@@ -828,7 +816,6 @@ CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/resources/DatabaseSchema.sql.in ${CMA
SET(RESOURCES SET(RESOURCES
${CMAKE_CURRENT_SOURCE_DIR}/resources/DatabaseSchema.sql ${CMAKE_CURRENT_SOURCE_DIR}/resources/DatabaseSchema.sql
${CMAKE_CURRENT_SOURCE_DIR}/resources/backward_compatibility/DatabaseSchema_0_22_0.sql
${CMAKE_CURRENT_SOURCE_DIR}/resources/backward_compatibility/DatabaseSchema_0_20_0.sql ${CMAKE_CURRENT_SOURCE_DIR}/resources/backward_compatibility/DatabaseSchema_0_20_0.sql
${CMAKE_CURRENT_SOURCE_DIR}/resources/backward_compatibility/DatabaseSchema_0_18_3.sql ${CMAKE_CURRENT_SOURCE_DIR}/resources/backward_compatibility/DatabaseSchema_0_18_3.sql
${CMAKE_CURRENT_SOURCE_DIR}/resources/backward_compatibility/DatabaseSchema_0_18_0.sql ${CMAKE_CURRENT_SOURCE_DIR}/resources/backward_compatibility/DatabaseSchema_0_18_0.sql
@@ -870,12 +857,8 @@ generate_export_header(rtabmap_core
DEPRECATED_MACRO_NAME RTABMAP_DEPRECATED) DEPRECATED_MACRO_NAME RTABMAP_DEPRECATED)
target_include_directories(rtabmap_core PUBLIC target_include_directories(rtabmap_core PUBLIC
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR};${CMAKE_CURRENT_SOURCE_DIR}/../include;${CMAKE_CURRENT_BINARY_DIR};${CMAKE_CURRENT_BINARY_DIR}/include>" "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../include;${CMAKE_CURRENT_BINARY_DIR}/include;${PUBLIC_INCLUDE_DIRS};${INCLUDE_DIRS}>"
"$<INSTALL_INTERFACE:${INSTALL_INCLUDE_DIR}>") "$<INSTALL_INTERFACE:${INSTALL_INCLUDE_DIR};${PUBLIC_INCLUDE_DIRS}>")
target_include_directories(rtabmap_core SYSTEM PUBLIC
"$<BUILD_INTERFACE:${PUBLIC_INCLUDE_DIRS};${INCLUDE_DIRS}>"
"$<INSTALL_INTERFACE:${PUBLIC_INCLUDE_DIRS}>")
TARGET_LINK_LIBRARIES(rtabmap_core TARGET_LINK_LIBRARIES(rtabmap_core
PUBLIC PUBLIC
+1 -1
View File
@@ -554,7 +554,7 @@ unsigned int CameraModel::deserialize(const unsigned char * data, unsigned int d
int iR = 8; int iR = 8;
int iP = 9; int iP = 9;
int iL = 10; int iL = 10;
//UDEBUG("Header: %d %d %d %d %d %d %d %d %d %d %d", header[0],header[1],header[2],header[3],header[4],header[5],header[6],header[7],header[8],header[9],header[10]); UDEBUG("Header: %d %d %d %d %d %d %d %d %d %d %d", header[0],header[1],header[2],header[3],header[4],header[5],header[6],header[7],header[8],header[9],header[10]);
unsigned int requiredDataSize = sizeof(int)*headerSize + unsigned int requiredDataSize = sizeof(int)*headerSize +
sizeof(double)*(header[iK]+header[iD]+header[iR]+header[iP]) + sizeof(double)*(header[iK]+header[iD]+header[iR]+header[iP]) +
sizeof(float)*header[iL]; sizeof(float)*header[iL];
+8 -55
View File
@@ -383,7 +383,7 @@ void DBDriver::asyncSave(Signature * s)
{ {
if(s) if(s)
{ {
//UDEBUG("s=%d", s->id()); UDEBUG("s=%d", s->id());
_trashesMutex.lock(); _trashesMutex.lock();
{ {
_trashSignatures.insert(std::pair<int, Signature*>(s->id(), s)); _trashSignatures.insert(std::pair<int, Signature*>(s->id(), s));
@@ -531,17 +531,17 @@ void DBDriver::updateLaserScan(int nodeId, const LaserScan & scan)
_dbSafeAccessMutex.unlock(); _dbSafeAccessMutex.unlock();
} }
void DBDriver::load(VWDictionary & dictionary, bool lastStateOnly) const void DBDriver::load(VWDictionary * dictionary, bool lastStateOnly) const
{ {
_dbSafeAccessMutex.lock(); _dbSafeAccessMutex.lock();
this->loadQuery(dictionary, lastStateOnly); this->loadQuery(dictionary, lastStateOnly);
_dbSafeAccessMutex.unlock(); _dbSafeAccessMutex.unlock();
} }
void DBDriver::loadLastNodes(std::list<Signature *> & signatures, bool loadWordIdsOnly) const void DBDriver::loadLastNodes(std::list<Signature *> & signatures) const
{ {
_dbSafeAccessMutex.lock(); _dbSafeAccessMutex.lock();
this->loadLastNodesQuery(signatures, loadWordIdsOnly); this->loadLastNodesQuery(signatures);
_dbSafeAccessMutex.unlock(); _dbSafeAccessMutex.unlock();
} }
@@ -564,8 +564,7 @@ Signature * DBDriver::loadSignature(int id, bool * loadedFromTrash)
} }
void DBDriver::loadSignatures(const std::list<int> & signIds, void DBDriver::loadSignatures(const std::list<int> & signIds,
std::list<Signature *> & signatures, std::list<Signature *> & signatures,
std::set<int> * loadedFromTrash, std::set<int> * loadedFromTrash)
bool loadWordIdsOnly)
{ {
UDEBUG(""); UDEBUG("");
// look up in the trash before the database // look up in the trash before the database
@@ -610,7 +609,7 @@ void DBDriver::loadSignatures(const std::list<int> & signIds,
if(ids.size()) if(ids.size())
{ {
_dbSafeAccessMutex.lock(); _dbSafeAccessMutex.lock();
this->loadSignaturesQuery(ids, signatures, loadWordIdsOnly); this->loadSignaturesQuery(ids, signatures);
_dbSafeAccessMutex.unlock(); _dbSafeAccessMutex.unlock();
} }
} }
@@ -657,10 +656,10 @@ void DBDriver::loadWords(const std::set<int> & wordIds, std::list<VisualWord *>
} }
} }
void DBDriver::loadNodeData(Signature & signature, bool images, bool scan, bool userData, bool occupancyGrid) const void DBDriver::loadNodeData(Signature * signature, bool images, bool scan, bool userData, bool occupancyGrid) const
{ {
std::list<Signature *> signatures; std::list<Signature *> signatures;
signatures.push_back(&signature); signatures.push_back(signature);
this->loadNodeData(signatures, images, scan, userData, occupancyGrid); this->loadNodeData(signatures, images, scan, userData, occupancyGrid);
} }
@@ -824,45 +823,6 @@ bool DBDriver::getNodeInfo(
return found; return found;
} }
void DBDriver::getLocalFeatures(
int signatureId,
std::multimap<int, int> & words,
std::vector<cv::KeyPoint> & keypoints,
std::vector<cv::Point3f> & points,
cv::Mat & descriptors) const
{
bool found = false;
// look in the trash
_trashesMutex.lock();
if(uContains(_trashSignatures, signatureId))
{
const Signature * s = _trashSignatures.at(signatureId);
UASSERT(s != 0);
found = true;
if(!s->getWords().empty())
{
words = s->getWords();
if(s->getWordsKpts().empty()){
found = false; // Force checking the database in case the local features were not loaded in RAM
}
else
{
words = s->getWords();
keypoints = s->getWordsKpts();
points = s->getWords3();
descriptors = s->getWordsDescriptors().clone();
}
}
}
_trashesMutex.unlock();
if(!found)
{
UScopeMutex lock(_dbSafeAccessMutex);
getLocalFeaturesQuery(signatureId, words, keypoints, points, descriptors);
}
}
void DBDriver::loadLinks(int signatureId, std::multimap<int, Link> & links, Link::Type type) const void DBDriver::loadLinks(int signatureId, std::multimap<int, Link> & links, Link::Type type) const
{ {
bool found = false; bool found = false;
@@ -1327,13 +1287,6 @@ cv::Mat DBDriver::loadOptimizedMesh(
return cloud; return cloud;
} }
void DBDriver::saveFlannIndex(const std::vector<unsigned char> & indexData) const
{
_dbSafeAccessMutex.lock();
saveFlannIndexQuery(indexData);
_dbSafeAccessMutex.unlock();
}
void DBDriver::generateGraph( void DBDriver::generateGraph(
const std::string & fileName, const std::string & fileName,
const std::set<int> & idsInput, const std::set<int> & idsInput,
+186 -387
View File
@@ -34,7 +34,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "rtabmap/core/util3d.h" #include "rtabmap/core/util3d.h"
#include "rtabmap/core/Compression.h" #include "rtabmap/core/Compression.h"
#include "DatabaseSchema_sql.h" #include "DatabaseSchema_sql.h"
#include "DatabaseSchema_0_22_0_sql.h"
#include "DatabaseSchema_0_20_0_sql.h" #include "DatabaseSchema_0_20_0_sql.h"
#include "DatabaseSchema_0_18_3_sql.h" #include "DatabaseSchema_0_18_3_sql.h"
#include "DatabaseSchema_0_18_0_sql.h" #include "DatabaseSchema_0_18_0_sql.h"
@@ -405,7 +404,6 @@ bool DBDriverSqlite3::connectDatabaseQuery(const std::string & url, bool overwri
schemas.push_back(std::make_pair("0.18.0", DATABASESCHEMA_0_18_0_SQL)); schemas.push_back(std::make_pair("0.18.0", DATABASESCHEMA_0_18_0_SQL));
schemas.push_back(std::make_pair("0.18.3", DATABASESCHEMA_0_18_3_SQL)); schemas.push_back(std::make_pair("0.18.3", DATABASESCHEMA_0_18_3_SQL));
schemas.push_back(std::make_pair("0.20.0", DATABASESCHEMA_0_20_0_SQL)); schemas.push_back(std::make_pair("0.20.0", DATABASESCHEMA_0_20_0_SQL));
schemas.push_back(std::make_pair("0.22.0", DATABASESCHEMA_0_22_0_SQL));
schemas.push_back(std::make_pair(uNumber2Str(RTABMAP_VERSION_MAJOR)+"."+uNumber2Str(RTABMAP_VERSION_MINOR), DATABASESCHEMA_SQL)); schemas.push_back(std::make_pair(uNumber2Str(RTABMAP_VERSION_MAJOR)+"."+uNumber2Str(RTABMAP_VERSION_MINOR), DATABASESCHEMA_SQL));
for(size_t i=0; i<schemas.size(); ++i) for(size_t i=0; i<schemas.size(); ++i)
{ {
@@ -1298,8 +1296,8 @@ std::map<int, std::vector<int> > DBDriverSqlite3::getAllStatisticsWmStatesQuery(
void DBDriverSqlite3::loadNodeDataQuery(std::list<Signature *> & signatures, bool images, bool scan, bool userData, bool occupancyGrid) const void DBDriverSqlite3::loadNodeDataQuery(std::list<Signature *> & signatures, bool images, bool scan, bool userData, bool occupancyGrid) const
{ {
//UDEBUG("load data for %d signatures images=%d scan=%d userData=%d, grid=%d", UDEBUG("load data for %d signatures images=%d scan=%d userData=%d, grid=%d",
// (int)signatures.size(), images?1:0, scan?1:0, userData?1:0, occupancyGrid?1:0); (int)signatures.size(), images?1:0, scan?1:0, userData?1:0, occupancyGrid?1:0);
if(!images && !scan && !userData && !occupancyGrid) if(!images && !scan && !userData && !occupancyGrid)
{ {
@@ -1447,7 +1445,7 @@ void DBDriverSqlite3::loadNodeDataQuery(std::list<Signature *> & signatures, boo
{ {
UASSERT(*iter != 0); UASSERT(*iter != 0);
//ULOGGER_DEBUG("Loading data for %d...", (*iter)->id()); ULOGGER_DEBUG("Loading data for %d...", (*iter)->id());
// bind id // bind id
rc = sqlite3_bind_int(ppStmt, 1, (*iter)->id()); rc = sqlite3_bind_int(ppStmt, 1, (*iter)->id());
UASSERT_MSG(rc == SQLITE_OK, uFormat("DB error (%s): %s", _version.c_str(), sqlite3_errmsg(_ppDb)).c_str()); UASSERT_MSG(rc == SQLITE_OK, uFormat("DB error (%s): %s", _version.c_str(), sqlite3_errmsg(_ppDb)).c_str());
@@ -1876,7 +1874,7 @@ void DBDriverSqlite3::loadNodeDataQuery(std::list<Signature *> & signatures, boo
// Finalize (delete) the statement // Finalize (delete) the statement
rc = sqlite3_finalize(ppStmt); rc = sqlite3_finalize(ppStmt);
UASSERT_MSG(rc == SQLITE_OK, uFormat("DB error (%s): %s", _version.c_str(), sqlite3_errmsg(_ppDb)).c_str()); UASSERT_MSG(rc == SQLITE_OK, uFormat("DB error (%s): %s", _version.c_str(), sqlite3_errmsg(_ppDb)).c_str());
//ULOGGER_DEBUG("Time=%fs", timer.ticks()); ULOGGER_DEBUG("Time=%fs", timer.ticks());
} }
} }
@@ -2393,23 +2391,6 @@ bool DBDriverSqlite3::getNodeInfoQuery(int signatureId,
return found; return found;
} }
void DBDriverSqlite3::getLocalFeaturesQuery(
int signatureId,
std::multimap<int, int> & words,
std::vector<cv::KeyPoint> & keypoints,
std::vector<cv::Point3f> & points,
cv::Mat & descriptors) const
{
Signature s(signatureId);
std::list<Signature *> ids;
ids.push_back(&s);
this->loadWordsQuery(ids);
words = ids.front()->getWords();
keypoints = ids.front()->getWordsKpts();
points = ids.front()->getWords3();
descriptors = ids.front()->getWordsDescriptors().clone();
}
void DBDriverSqlite3::getLastNodeIdsQuery(std::set<int> & ids) const void DBDriverSqlite3::getLastNodeIdsQuery(std::set<int> & ids) const
{ {
if(_ppDb) if(_ppDb)
@@ -3006,7 +2987,7 @@ void DBDriverSqlite3::getWeightQuery(int nodeId, int & weight) const
} }
//may be slower than the previous version but don't have a limit of words that can be loaded at the same time //may be slower than the previous version but don't have a limit of words that can be loaded at the same time
void DBDriverSqlite3::loadSignaturesQuery(const std::list<int> & ids, std::list<Signature *> & nodes, bool loadWordIdsOnly) const void DBDriverSqlite3::loadSignaturesQuery(const std::list<int> & ids, std::list<Signature *> & nodes) const
{ {
ULOGGER_DEBUG("count=%d", (int)ids.size()); ULOGGER_DEBUG("count=%d", (int)ids.size());
if(_ppDb && ids.size()) if(_ppDb && ids.size())
@@ -3170,7 +3151,7 @@ void DBDriverSqlite3::loadSignaturesQuery(const std::list<int> & ids, std::list<
// create the node // create the node
if(id) if(id)
{ {
//ULOGGER_DEBUG("Creating %d (map=%d, pose=%s)", *iter, mapId, pose.prettyPrint().c_str()); ULOGGER_DEBUG("Creating %d (map=%d, pose=%s)", *iter, mapId, pose.prettyPrint().c_str());
Signature * s = new Signature( Signature * s = new Signature(
id, id,
mapId, mapId,
@@ -3209,17 +3190,175 @@ void DBDriverSqlite3::loadSignaturesQuery(const std::list<int> & ids, std::list<
ULOGGER_DEBUG("Time=%fs", timer.ticks()); ULOGGER_DEBUG("Time=%fs", timer.ticks());
// Prepare the query... Get the map from signature and visual words // Prepare the query... Get the map from signature and visual words
UDEBUG("Loading local features (ids only=%s)....", loadWordIdsOnly?"true":"false"); std::stringstream query2;
if(loadWordIdsOnly) { if(uStrNumCmp(_version, "0.13.0") >= 0)
this->loadWordIdsQuery(nodes); {
query2 << "SELECT word_id, pos_x, pos_y, size, dir, response, octave, depth_x, depth_y, depth_z, descriptor_size, descriptor "
"FROM Feature "
"WHERE node_id = ? ";
} }
else { else if(uStrNumCmp(_version, "0.12.0") >= 0)
this->loadWordsQuery(nodes); {
query2 << "SELECT word_id, pos_x, pos_y, size, dir, response, octave, depth_x, depth_y, depth_z, descriptor_size, descriptor "
"FROM Map_Node_Word "
"WHERE node_id = ? ";
} }
UDEBUG("Loading local features.... done! (in %f s)", timer.ticks()); else if(uStrNumCmp(_version, "0.11.2") >= 0)
{
query2 << "SELECT word_id, pos_x, pos_y, size, dir, response, depth_x, depth_y, depth_z, descriptor_size, descriptor "
"FROM Map_Node_Word "
"WHERE node_id = ? ";
}
else
{
query2 << "SELECT word_id, pos_x, pos_y, size, dir, response, depth_x, depth_y, depth_z "
"FROM Map_Node_Word "
"WHERE node_id = ? ";
}
query2 << " ORDER BY word_id"; // Needed for fast insertion below
query2 << ";";
rc = sqlite3_prepare_v2(_ppDb, query2.str().c_str(), -1, &ppStmt, 0);
UASSERT_MSG(rc == SQLITE_OK, uFormat("DB error (%s): %s", _version.c_str(), sqlite3_errmsg(_ppDb)).c_str());
float nanFloat = std::numeric_limits<float>::quiet_NaN ();
for(std::list<Signature*>::const_iterator iter=nodes.begin(); iter!=nodes.end(); ++iter)
{
//ULOGGER_DEBUG("Loading words of %d...", (*iter)->id());
// bind id
rc = sqlite3_bind_int(ppStmt, 1, (*iter)->id());
UASSERT_MSG(rc == SQLITE_OK, uFormat("DB error (%s): %s", _version.c_str(), sqlite3_errmsg(_ppDb)).c_str());
int visualWordId = 0;
int descriptorSize = 0;
const void * descriptor = 0;
int dRealSize = 0;
cv::KeyPoint kpt;
std::multimap<int, int> visualWords;
std::vector<cv::KeyPoint> visualWordsKpts;
std::vector<cv::Point3f> visualWords3;
cv::Mat descriptors;
bool allWords3NaN = true;
cv::Point3f depth(0,0,0);
// Process the result if one
rc = sqlite3_step(ppStmt);
while(rc == SQLITE_ROW)
{
int index = 0;
visualWordId = sqlite3_column_int(ppStmt, index++);
kpt.pt.x = sqlite3_column_double(ppStmt, index++);
kpt.pt.y = sqlite3_column_double(ppStmt, index++);
kpt.size = sqlite3_column_int(ppStmt, index++);
kpt.angle = sqlite3_column_double(ppStmt, index++);
kpt.response = sqlite3_column_double(ppStmt, index++);
if(uStrNumCmp(_version, "0.12.0") >= 0)
{
kpt.octave = sqlite3_column_int(ppStmt, index++);
}
if(sqlite3_column_type(ppStmt, index) == SQLITE_NULL)
{
depth.x = nanFloat;
++index;
}
else
{
depth.x = sqlite3_column_double(ppStmt, index++);
}
if(sqlite3_column_type(ppStmt, index) == SQLITE_NULL)
{
depth.y = nanFloat;
++index;
}
else
{
depth.y = sqlite3_column_double(ppStmt, index++);
}
if(sqlite3_column_type(ppStmt, index) == SQLITE_NULL)
{
depth.z = nanFloat;
++index;
}
else
{
depth.z = sqlite3_column_double(ppStmt, index++);
}
visualWordsKpts.push_back(kpt);
visualWords.insert(visualWords.end(), std::make_pair(visualWordId, visualWordsKpts.size()-1));
visualWords3.push_back(depth);
if(allWords3NaN && util3d::isFinite(depth))
{
allWords3NaN = false;
}
if(uStrNumCmp(_version, "0.11.2") >= 0)
{
descriptorSize = sqlite3_column_int(ppStmt, index++); // VisualWord descriptor size
descriptor = sqlite3_column_blob(ppStmt, index); // VisualWord descriptor array
dRealSize = sqlite3_column_bytes(ppStmt, index++);
if(descriptor && descriptorSize>0 && dRealSize>0)
{
cv::Mat d;
if(dRealSize == descriptorSize)
{
// CV_8U binary descriptors
d = cv::Mat(1, descriptorSize, CV_8U);
}
else if(dRealSize/int(sizeof(float)) == descriptorSize)
{
// CV_32F
d = cv::Mat(1, descriptorSize, CV_32F);
}
else
{
UFATAL("Saved buffer size (%d bytes) is not the same as descriptor size (%d)", dRealSize, descriptorSize);
}
memcpy(d.data, descriptor, dRealSize);
descriptors.push_back(d);
}
}
rc = sqlite3_step(ppStmt);
}
UASSERT_MSG(rc == SQLITE_DONE, uFormat("DB error (%s): %s", _version.c_str(), sqlite3_errmsg(_ppDb)).c_str());
if(visualWords.size()==0)
{
UDEBUG("Empty signature detected! (id=%d)", (*iter)->id());
}
else
{
if(allWords3NaN)
{
visualWords3.clear();
}
(*iter)->setWords(visualWords, visualWordsKpts, visualWords3, descriptors);
ULOGGER_DEBUG("Add %d keypoints, %d 3d points and %d descriptors to node %d", (int)visualWords.size(), allWords3NaN?0:(int)visualWords3.size(), (int)descriptors.rows, (*iter)->id());
}
//reset
rc = sqlite3_reset(ppStmt);
UASSERT_MSG(rc == SQLITE_OK, uFormat("DB error (%s): %s", _version.c_str(), sqlite3_errmsg(_ppDb)).c_str());
}
// Finalize (delete) the statement
rc = sqlite3_finalize(ppStmt);
UASSERT_MSG(rc == SQLITE_OK, uFormat("DB error (%s): %s", _version.c_str(), sqlite3_errmsg(_ppDb)).c_str());
ULOGGER_DEBUG("Time=%fs", timer.ticks());
this->loadLinksQuery(nodes); this->loadLinksQuery(nodes);
ULOGGER_DEBUG("Time loading links=%fs", timer.ticks()); ULOGGER_DEBUG("Time load links=%fs", timer.ticks());
for(std::list<Signature*>::iterator iter = nodes.begin(); iter!=nodes.end(); ++iter) for(std::list<Signature*>::iterator iter = nodes.begin(); iter!=nodes.end(); ++iter)
{ {
@@ -3487,7 +3626,7 @@ void DBDriverSqlite3::loadSignaturesQuery(const std::list<int> & ids, std::list<
} }
} }
void DBDriverSqlite3::loadLastNodesQuery(std::list<Signature *> & nodes, bool loadWordIdsOnly) const void DBDriverSqlite3::loadLastNodesQuery(std::list<Signature *> & nodes) const
{ {
ULOGGER_DEBUG(""); ULOGGER_DEBUG("");
if(_ppDb) if(_ppDb)
@@ -3533,15 +3672,15 @@ void DBDriverSqlite3::loadLastNodesQuery(std::list<Signature *> & nodes, bool lo
UASSERT_MSG(rc == SQLITE_OK, uFormat("DB error (%s): %s", _version.c_str(), sqlite3_errmsg(_ppDb)).c_str()); UASSERT_MSG(rc == SQLITE_OK, uFormat("DB error (%s): %s", _version.c_str(), sqlite3_errmsg(_ppDb)).c_str());
ULOGGER_DEBUG("Loading %d signatures...", ids.size()); ULOGGER_DEBUG("Loading %d signatures...", ids.size());
this->loadSignaturesQuery(ids, nodes, loadWordIdsOnly); this->loadSignaturesQuery(ids, nodes);
ULOGGER_DEBUG("loaded=%d, Time=%fs", nodes.size(), timer.ticks()); ULOGGER_DEBUG("loaded=%d, Time=%fs", nodes.size(), timer.ticks());
} }
} }
void DBDriverSqlite3::loadQuery(VWDictionary & dictionary, bool lastStateOnly) const void DBDriverSqlite3::loadQuery(VWDictionary * dictionary, bool lastStateOnly) const
{ {
ULOGGER_DEBUG(""); ULOGGER_DEBUG("");
if(_ppDb) if(_ppDb && dictionary)
{ {
std::string type; std::string type;
UTimer timer; UTimer timer;
@@ -3604,11 +3743,11 @@ void DBDriverSqlite3::loadQuery(VWDictionary & dictionary, bool lastStateOnly) c
memcpy(d.data, descriptor, dRealSize); memcpy(d.data, descriptor, dRealSize);
VisualWord * vw = new VisualWord(id, d); VisualWord * vw = new VisualWord(id, d);
vw->setSaved(true); vw->setSaved(true);
dictionary.addWord(vw); dictionary->addWord(vw);
if(++count % 5000 == 0) if(++count % 5000 == 0)
{ {
//ULOGGER_DEBUG("Loaded %d words...", count); ULOGGER_DEBUG("Loaded %d words...", count);
} }
rc = sqlite3_step(ppStmt); // next result... rc = sqlite3_step(ppStmt); // next result...
} }
@@ -3619,50 +3758,9 @@ void DBDriverSqlite3::loadQuery(VWDictionary & dictionary, bool lastStateOnly) c
// Get Last word id // Get Last word id
getLastWordId(id); getLastWordId(id);
dictionary.setLastWordId(id); dictionary->setLastWordId(id);
if(uStrNumCmp(_version, "0.23.0") >= 0) { ULOGGER_DEBUG("Time=%fs", timer.ticks());
// load dictionary index
std::stringstream query3;
query3 << "SELECT dictionary_index "
<< "FROM Admin "
<< "WHERE version='" << _version.c_str()
<<"';";
rc = sqlite3_prepare_v2(_ppDb, query3.str().c_str(), -1, &ppStmt, 0);
UASSERT_MSG(rc == SQLITE_OK, uFormat("DB error (%s): %s", _version.c_str(), sqlite3_errmsg(_ppDb)).c_str());
// Process the result if one
rc = sqlite3_step(ppStmt);
UASSERT_MSG(rc == SQLITE_ROW, uFormat("DB error (%s): Not found first Admin row: query=\"%s\"", _version.c_str(), query3.str().c_str()).c_str());
if(rc == SQLITE_ROW)
{
const void * data = 0;
int dataSize = 0;
int index = 0;
//opt_poses
data = sqlite3_column_blob(ppStmt, index);
dataSize = sqlite3_column_bytes(ppStmt, index++);
if(dataSize>4 && data)
{
UDEBUG("A flann index was saved in the database (size=%ld).", dataSize);
dictionary.deserializeIndex((const unsigned char*)data, dataSize);
}
else {
UDEBUG("No flann index was saved in the database.");
}
rc = sqlite3_step(ppStmt); // next result...
}
UASSERT_MSG(rc == SQLITE_DONE, uFormat("DB error (%s): %s", _version.c_str(), sqlite3_errmsg(_ppDb)).c_str());
// Finalize (delete) the statement
rc = sqlite3_finalize(ppStmt);
UASSERT_MSG(rc == SQLITE_OK, uFormat("DB error (%s): %s", _version.c_str(), sqlite3_errmsg(_ppDb)).c_str());
}
ULOGGER_DEBUG("Loaded %d words... time=%fs", count, timer.ticks());
} }
} }
@@ -3762,262 +3860,6 @@ void DBDriverSqlite3::loadWordsQuery(const std::set<int> & wordIds, std::list<Vi
} }
} }
void DBDriverSqlite3::loadWordIdsQuery(std::list<Signature *> & signatures) const
{
if(_ppDb)
{
int rc = SQLITE_OK;
sqlite3_stmt * ppStmt = 0;
std::stringstream query;
if(uStrNumCmp(_version, "0.13.0") >= 0)
{
query << "SELECT word_id "
"FROM Feature "
"WHERE node_id = ? ";
}
else if(uStrNumCmp(_version, "0.12.0") >= 0)
{
query << "SELECT word_id "
"FROM Map_Node_Word "
"WHERE node_id = ? ";
}
else if(uStrNumCmp(_version, "0.11.2") >= 0)
{
query << "SELECT word_id "
"FROM Map_Node_Word "
"WHERE node_id = ? ";
}
else
{
query << "SELECT word_id "
"FROM Map_Node_Word "
"WHERE node_id = ? ";
}
query << " ORDER BY word_id"; // Needed for fast insertion below
query << ";";
rc = sqlite3_prepare_v2(_ppDb, query.str().c_str(), -1, &ppStmt, 0);
UASSERT_MSG(rc == SQLITE_OK, uFormat("DB error (%s): %s", _version.c_str(), sqlite3_errmsg(_ppDb)).c_str());
for(std::list<Signature*>::const_iterator iter=signatures.begin(); iter!=signatures.end(); ++iter)
{
//ULOGGER_DEBUG("Loading words of %d...", (*iter)->id());
// bind id
rc = sqlite3_bind_int(ppStmt, 1, (*iter)->id());
UASSERT_MSG(rc == SQLITE_OK, uFormat("DB error (%s): %s", _version.c_str(), sqlite3_errmsg(_ppDb)).c_str());
int visualWordId = 0;
std::multimap<int, int> visualWords;
// Process the result if one
rc = sqlite3_step(ppStmt);
while(rc == SQLITE_ROW)
{
int index = 0;
visualWordId = sqlite3_column_int(ppStmt, index++);
visualWords.insert(visualWords.end(), std::make_pair(visualWordId, -1));
rc = sqlite3_step(ppStmt);
}
UASSERT_MSG(rc == SQLITE_DONE, uFormat("DB error (%s): %s", _version.c_str(), sqlite3_errmsg(_ppDb)).c_str());
if(visualWords.size()==0)
{
UDEBUG("Empty signature detected! (id=%d)", (*iter)->id());
}
else
{
(*iter)->setWords(visualWords, std::vector<cv::KeyPoint>(), std::vector<cv::Point3f>(), cv::Mat());
//ULOGGER_DEBUG("Add %d keypoints, %d 3d points and %d descriptors to node %d", (int)visualWords.size(), allWords3NaN?0:(int)visualWords3.size(), (int)descriptors.rows, (*iter)->id());
}
//reset
rc = sqlite3_reset(ppStmt);
UASSERT_MSG(rc == SQLITE_OK, uFormat("DB error (%s): %s", _version.c_str(), sqlite3_errmsg(_ppDb)).c_str());
}
// Finalize (delete) the statement
rc = sqlite3_finalize(ppStmt);
UASSERT_MSG(rc == SQLITE_OK, uFormat("DB error (%s): %s", _version.c_str(), sqlite3_errmsg(_ppDb)).c_str());
}
}
void DBDriverSqlite3::loadWordsQuery(std::list<Signature *> & signatures) const
{
if(_ppDb)
{
int rc = SQLITE_OK;
sqlite3_stmt * ppStmt = 0;
std::stringstream query;
if(uStrNumCmp(_version, "0.13.0") >= 0)
{
query << "SELECT word_id, pos_x, pos_y, size, dir, response, octave, depth_x, depth_y, depth_z, descriptor_size, descriptor "
"FROM Feature "
"WHERE node_id = ? ";
}
else if(uStrNumCmp(_version, "0.12.0") >= 0)
{
query << "SELECT word_id, pos_x, pos_y, size, dir, response, octave, depth_x, depth_y, depth_z, descriptor_size, descriptor "
"FROM Map_Node_Word "
"WHERE node_id = ? ";
}
else if(uStrNumCmp(_version, "0.11.2") >= 0)
{
query << "SELECT word_id, pos_x, pos_y, size, dir, response, depth_x, depth_y, depth_z, descriptor_size, descriptor "
"FROM Map_Node_Word "
"WHERE node_id = ? ";
}
else
{
query << "SELECT word_id, pos_x, pos_y, size, dir, response, depth_x, depth_y, depth_z "
"FROM Map_Node_Word "
"WHERE node_id = ? ";
}
query << " ORDER BY word_id"; // Needed for fast insertion below
query << ";";
rc = sqlite3_prepare_v2(_ppDb, query.str().c_str(), -1, &ppStmt, 0);
UASSERT_MSG(rc == SQLITE_OK, uFormat("DB error (%s): %s", _version.c_str(), sqlite3_errmsg(_ppDb)).c_str());
float nanFloat = std::numeric_limits<float>::quiet_NaN ();
for(std::list<Signature*>::const_iterator iter=signatures.begin(); iter!=signatures.end(); ++iter)
{
//ULOGGER_DEBUG("Loading words of %d...", (*iter)->id());
// bind id
rc = sqlite3_bind_int(ppStmt, 1, (*iter)->id());
UASSERT_MSG(rc == SQLITE_OK, uFormat("DB error (%s): %s", _version.c_str(), sqlite3_errmsg(_ppDb)).c_str());
int visualWordId = 0;
int descriptorSize = 0;
const void * descriptor = 0;
int dRealSize = 0;
cv::KeyPoint kpt;
std::multimap<int, int> visualWords;
std::vector<cv::KeyPoint> visualWordsKpts;
std::vector<cv::Point3f> visualWords3;
cv::Mat descriptors;
bool allWords3NaN = true;
cv::Point3f depth(0,0,0);
// Process the result if one
rc = sqlite3_step(ppStmt);
while(rc == SQLITE_ROW)
{
int index = 0;
visualWordId = sqlite3_column_int(ppStmt, index++);
kpt.pt.x = sqlite3_column_double(ppStmt, index++);
kpt.pt.y = sqlite3_column_double(ppStmt, index++);
kpt.size = sqlite3_column_int(ppStmt, index++);
kpt.angle = sqlite3_column_double(ppStmt, index++);
kpt.response = sqlite3_column_double(ppStmt, index++);
if(uStrNumCmp(_version, "0.12.0") >= 0)
{
kpt.octave = sqlite3_column_int(ppStmt, index++);
}
if(sqlite3_column_type(ppStmt, index) == SQLITE_NULL)
{
depth.x = nanFloat;
++index;
}
else
{
depth.x = sqlite3_column_double(ppStmt, index++);
}
if(sqlite3_column_type(ppStmt, index) == SQLITE_NULL)
{
depth.y = nanFloat;
++index;
}
else
{
depth.y = sqlite3_column_double(ppStmt, index++);
}
if(sqlite3_column_type(ppStmt, index) == SQLITE_NULL)
{
depth.z = nanFloat;
++index;
}
else
{
depth.z = sqlite3_column_double(ppStmt, index++);
}
visualWordsKpts.push_back(kpt);
visualWords.insert(visualWords.end(), std::make_pair(visualWordId, visualWordsKpts.size()-1));
visualWords3.push_back(depth);
if(allWords3NaN && util3d::isFinite(depth))
{
allWords3NaN = false;
}
if(uStrNumCmp(_version, "0.11.2") >= 0)
{
descriptorSize = sqlite3_column_int(ppStmt, index++); // VisualWord descriptor size
descriptor = sqlite3_column_blob(ppStmt, index); // VisualWord descriptor array
dRealSize = sqlite3_column_bytes(ppStmt, index++);
if(descriptor && descriptorSize>0 && dRealSize>0)
{
cv::Mat d;
if(dRealSize == descriptorSize)
{
// CV_8U binary descriptors
d = cv::Mat(1, descriptorSize, CV_8U);
}
else if(dRealSize/int(sizeof(float)) == descriptorSize)
{
// CV_32F
d = cv::Mat(1, descriptorSize, CV_32F);
}
else
{
UFATAL("Saved buffer size (%d bytes) is not the same as descriptor size (%d)", dRealSize, descriptorSize);
}
memcpy(d.data, descriptor, dRealSize);
descriptors.push_back(d);
}
}
rc = sqlite3_step(ppStmt);
}
UASSERT_MSG(rc == SQLITE_DONE, uFormat("DB error (%s): %s", _version.c_str(), sqlite3_errmsg(_ppDb)).c_str());
if(visualWords.size()==0)
{
UDEBUG("Empty signature detected! (id=%d)", (*iter)->id());
}
else
{
if(allWords3NaN)
{
visualWords3.clear();
}
(*iter)->setWords(visualWords, visualWordsKpts, visualWords3, descriptors);
//ULOGGER_DEBUG("Add %d keypoints, %d 3d points and %d descriptors to node %d", (int)visualWords.size(), allWords3NaN?0:(int)visualWords3.size(), (int)descriptors.rows, (*iter)->id());
}
//reset
rc = sqlite3_reset(ppStmt);
UASSERT_MSG(rc == SQLITE_OK, uFormat("DB error (%s): %s", _version.c_str(), sqlite3_errmsg(_ppDb)).c_str());
}
// Finalize (delete) the statement
rc = sqlite3_finalize(ppStmt);
UASSERT_MSG(rc == SQLITE_OK, uFormat("DB error (%s): %s", _version.c_str(), sqlite3_errmsg(_ppDb)).c_str());
}
}
void DBDriverSqlite3::loadLinksQuery( void DBDriverSqlite3::loadLinksQuery(
int signatureId, int signatureId,
std::multimap<int, Link> & links, std::multimap<int, Link> & links,
@@ -4332,7 +4174,7 @@ void DBDriverSqlite3::loadLinksQuery(std::list<Signature *> & signatures) const
//reset //reset
rc = sqlite3_reset(ppStmt); rc = sqlite3_reset(ppStmt);
UASSERT_MSG(rc == SQLITE_OK, uFormat("DB error (%s): %s", _version.c_str(), sqlite3_errmsg(_ppDb)).c_str()); UASSERT_MSG(rc == SQLITE_OK, uFormat("DB error (%s): %s", _version.c_str(), sqlite3_errmsg(_ppDb)).c_str());
//UDEBUG("time=%fs, node=%d, links.size=%d", timer.ticks(), (*iter)->id(), links.size()); UDEBUG("time=%fs, node=%d, links.size=%d", timer.ticks(), (*iter)->id(), links.size());
} }
// Finalize (delete) the statement // Finalize (delete) the statement
@@ -5275,8 +5117,8 @@ std::map<int, Transform> DBDriverSqlite3::loadOptimizedPosesQuery(Transform * la
Transform t(serializedPoses.at<float>(i*12), serializedPoses.at<float>(i*12+1), serializedPoses.at<float>(i*12+2), serializedPoses.at<float>(i*12+3), Transform t(serializedPoses.at<float>(i*12), serializedPoses.at<float>(i*12+1), serializedPoses.at<float>(i*12+2), serializedPoses.at<float>(i*12+3),
serializedPoses.at<float>(i*12+4), serializedPoses.at<float>(i*12+5), serializedPoses.at<float>(i*12+6), serializedPoses.at<float>(i*12+7), serializedPoses.at<float>(i*12+4), serializedPoses.at<float>(i*12+5), serializedPoses.at<float>(i*12+6), serializedPoses.at<float>(i*12+7),
serializedPoses.at<float>(i*12+8), serializedPoses.at<float>(i*12+9), serializedPoses.at<float>(i*12+10), serializedPoses.at<float>(i*12+11)); serializedPoses.at<float>(i*12+8), serializedPoses.at<float>(i*12+9), serializedPoses.at<float>(i*12+10), serializedPoses.at<float>(i*12+11));
poses.insert(poses.end(), std::make_pair(serializedIds.at<int>(i), t)); poses.insert(std::make_pair(serializedIds.at<int>(i), t));
//UDEBUG("Optimized pose %d: %s", serializedIds.at<int>(i), t.prettyPrint().c_str()); UDEBUG("Optimized pose %d: %s", serializedIds.at<int>(i), t.prettyPrint().c_str());
} }
} }
@@ -5684,7 +5526,7 @@ cv::Mat DBDriverSqlite3::loadOptimizedMeshQuery(
materialPolygons[p][i] = serializedPolygons.at<int>(t + p*polygonSize + i); materialPolygons[p][i] = serializedPolygons.at<int>(t + p*polygonSize + i);
} }
} }
t+=materialPolygons.size()*polygonSize-1; t+=materialPolygons.size()*polygonSize;
polygons->push_back(materialPolygons); polygons->push_back(materialPolygons);
} }
} }
@@ -5701,7 +5543,7 @@ cv::Mat DBDriverSqlite3::loadOptimizedMeshQuery(
UASSERT(serializedTexCoords.total()); UASSERT(serializedTexCoords.total());
for(int t=0; t<serializedTexCoords.cols; ++t) for(int t=0; t<serializedTexCoords.cols; ++t)
{ {
UASSERT_MSG(int(serializedTexCoords.at<float>(t)) > 0, uFormat("serializedTexCoords.at<float>(%d)=%f", t, serializedTexCoords.at<float>(t)).c_str()); UASSERT(int(serializedTexCoords.at<float>(t)) > 0);
#if PCL_VERSION_COMPARE(>=, 1, 8, 0) #if PCL_VERSION_COMPARE(>=, 1, 8, 0)
std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > materialtexCoords(int(serializedTexCoords.at<float>(t))); std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > materialtexCoords(int(serializedTexCoords.at<float>(t)));
#else #else
@@ -5714,10 +5556,8 @@ cv::Mat DBDriverSqlite3::loadOptimizedMeshQuery(
{ {
materialtexCoords[p][0] = serializedTexCoords.at<float>(t + p*2); materialtexCoords[p][0] = serializedTexCoords.at<float>(t + p*2);
materialtexCoords[p][1] = serializedTexCoords.at<float>(t + p*2 + 1); materialtexCoords[p][1] = serializedTexCoords.at<float>(t + p*2 + 1);
UASSERT(materialtexCoords[p][0]>=0.0f && materialtexCoords[p][0] <= 1.0f);
UASSERT(materialtexCoords[p][1]>=0.0f && materialtexCoords[p][1] <= 1.0f);
} }
t+=materialtexCoords.size()*2-1; t+=materialtexCoords.size()*2;
texCoords->push_back(materialtexCoords); texCoords->push_back(materialtexCoords);
} }
} }
@@ -5749,47 +5589,6 @@ cv::Mat DBDriverSqlite3::loadOptimizedMeshQuery(
return cloud; return cloud;
} }
void DBDriverSqlite3::saveFlannIndexQuery(const std::vector<unsigned char> & data) const
{
UDEBUG("");
if(_ppDb && uStrNumCmp(_version, "0.23.0") >= 0)
{
UTimer timer;
timer.start();
int rc = SQLITE_OK;
sqlite3_stmt * ppStmt = 0;
std::string query;
// Update table Admin
query = uFormat("UPDATE Admin SET dictionary_index=? WHERE version='%s';", _version.c_str());
rc = sqlite3_prepare_v2(_ppDb, query.c_str(), -1, &ppStmt, 0);
UASSERT_MSG(rc == SQLITE_OK, uFormat("DB error (%s): %s", _version.c_str(), sqlite3_errmsg(_ppDb)).c_str());
int index = 1;
if(data.empty())
{
rc = sqlite3_bind_null(ppStmt, index++);
UASSERT_MSG(rc == SQLITE_OK, uFormat("DB error (%s): %s", _version.c_str(), sqlite3_errmsg(_ppDb)).c_str());
}
else
{
rc = sqlite3_bind_blob(ppStmt, index++, data.data(), data.size(), SQLITE_STATIC);
UASSERT_MSG(rc == SQLITE_OK, uFormat("DB error (%s): %s", _version.c_str(), sqlite3_errmsg(_ppDb)).c_str());
}
//execute query
rc=sqlite3_step(ppStmt);
UASSERT_MSG(rc == SQLITE_DONE, uFormat("DB error (%s): %s", _version.c_str(), sqlite3_errmsg(_ppDb)).c_str());
// Finalize (delete) the statement
rc = sqlite3_finalize(ppStmt);
UASSERT_MSG(rc == SQLITE_OK, uFormat("DB error (%s): %s", _version.c_str(), sqlite3_errmsg(_ppDb)).c_str());
UDEBUG("Time=%fs", timer.ticks());
}
}
std::string DBDriverSqlite3::queryStepNode() const std::string DBDriverSqlite3::queryStepNode() const
{ {
if(uStrNumCmp(_version, "0.18.0") >= 0) if(uStrNumCmp(_version, "0.18.0") >= 0)
@@ -6797,7 +6596,7 @@ void DBDriverSqlite3::stepLink(
{ {
UFATAL(""); UFATAL("");
} }
//UDEBUG("Save link from %d to %d, type=%d", link.from(), link.to(), link.type()); UDEBUG("Save link from %d to %d, type=%d", link.from(), link.to(), link.type());
// Don't save virtual links // Don't save virtual links
if(link.type()==Link::kVirtualClosure) if(link.type()==Link::kVirtualClosure)
+1 -21
View File
@@ -260,7 +260,7 @@ bool DBReader::init(
else else
{ {
Signature * s = _dbDriver->loadSignature(*_ids.begin()); Signature * s = _dbDriver->loadSignature(*_ids.begin());
_dbDriver->loadNodeData(*s); _dbDriver->loadNodeData(s);
if( s->sensorData().imageCompressed().empty() && if( s->sensorData().imageCompressed().empty() &&
s->getWords().empty() && s->getWords().empty() &&
!s->sensorData().laserScanCompressed().empty()) !s->sensorData().laserScanCompressed().empty())
@@ -510,23 +510,6 @@ SensorData DBReader::getNextData(SensorCaptureInfo * info)
} }
else else
{ {
// In case the graph was reduced, look for forward neighbor link from previous id
bool covAdded = false;
if(_currentId != _ids.begin()) {
std::set<int>::iterator previousId = _currentId;
--previousId;
std::multimap<int, Link> previousLinks;
_dbDriver->loadLinks(*previousId, previousLinks, Link::kNeighbor);
if(previousLinks.size() && previousLinks.rbegin()->first == *_currentId)
{
// assume the last is the forward neighbor pointing to current ID, take its covariance
infMatrix = previousLinks.rbegin()->second.infMatrix();
_previousInfMatrix = infMatrix;
covAdded = true;
}
}
if(!covAdded) {
// if localization data saved in database, covariance will be set in a prior link // if localization data saved in database, covariance will be set in a prior link
_dbDriver->loadLinks(*_currentId, links, Link::kPosePrior); _dbDriver->loadLinks(*_currentId, links, Link::kPosePrior);
if(links.size()) if(links.size())
@@ -542,12 +525,10 @@ SensorData DBReader::getNextData(SensorCaptureInfo * info)
_previousInfMatrix = cv::Mat::eye(6,6,CV_64FC1); _previousInfMatrix = cv::Mat::eye(6,6,CV_64FC1);
} }
// we have a node not linked to map, use last variance // we have a node not linked to map, use last variance
UWARN("The node loaded (%d) doesn't have neighbor, re-using the covariance of the previous link for odometry.", s->id());
infMatrix = _previousInfMatrix; infMatrix = _previousInfMatrix;
} }
} }
} }
}
_previousMapId = s->mapId(); _previousMapId = s->mapId();
} }
else else
@@ -856,7 +837,6 @@ SensorData DBReader::getNextData(SensorCaptureInfo * info)
if(info) if(info)
{ {
info->odomPose = pose; info->odomPose = pose;
UASSERT(!infMatrix.empty());
info->odomCovariance = infMatrix.inv(); info->odomCovariance = infMatrix.inv();
info->odomVelocity = s->getVelocity(); info->odomVelocity = s->getVelocity();
UDEBUG("odom variance = %f/%f", info->odomCovariance.at<double>(0,0), info->odomCovariance.at<double>(5,5)); UDEBUG("odom variance = %f/%f", info->odomCovariance.at<double>(0,0), info->odomCovariance.at<double>(5,5));
+117 -328
View File
@@ -27,16 +27,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <rtabmap/core/FlannIndex.h> #include <rtabmap/core/FlannIndex.h>
#include <rtabmap/utilite/ULogger.h> #include <rtabmap/utilite/ULogger.h>
#include <rtabmap/utilite/UTimer.h>
#include <rtabmap/utilite/UConversion.h>
#include <rtabmap/core/Compression.h>
#include <rtabmap/core/Version.h>
#ifdef WIN32
#include <rtabmap/core/Parameters.h>
#endif
#include "rtflann/flann.hpp" #include "rtflann/flann.hpp"
#include <boost/crc.hpp>
namespace rtabmap { namespace rtabmap {
@@ -45,6 +37,7 @@ FlannIndex::FlannIndex():
nextIndex_(0), nextIndex_(0),
featuresType_(0), featuresType_(0),
featuresDim_(0), featuresDim_(0),
isLSH_(false),
useDistanceL1_(false), useDistanceL1_(false),
rebalancingFactor_(2.0f) rebalancingFactor_(2.0f)
{ {
@@ -56,9 +49,9 @@ FlannIndex::~FlannIndex()
void FlannIndex::release() void FlannIndex::release()
{ {
UDEBUG("");
if(index_) if(index_)
{ {
UDEBUG("Clearing flann index...");
if(featuresType_ == CV_8UC1) if(featuresType_ == CV_8UC1)
{ {
delete (rtflann::Index<rtflann::Hamming<unsigned char> >*)index_; delete (rtflann::Index<rtflann::Hamming<unsigned char> >*)index_;
@@ -79,139 +72,12 @@ void FlannIndex::release()
} }
} }
index_ = 0; index_ = 0;
UDEBUG("Clearing flann index... done!");
} }
nextIndex_ = 0; nextIndex_ = 0;
isLSH_ = false;
addedDescriptors_.clear(); addedDescriptors_.clear();
removedIndexes_.clear(); removedIndexes_.clear();
} UDEBUG("");
#define FLANN_INDEX_HEADER_SIZE 12
std::vector<unsigned char> FlannIndex::serializeIndex(bool computeChecksum) const {
if(index_ && !addedDescriptors_.empty())
{
#ifdef WIN32
UERROR("FLANN index serialization is not yet implemented on Windows. Parameter \"%s\" cannot be used.", Parameters::kKpFlannIndexSaved().c_str());
#else
UTimer timer;
const int headerSizeBytes = sizeof(int)*FLANN_INDEX_HEADER_SIZE;
std::vector<unsigned char> indexData(1024*1024*100 + headerSizeBytes); // Max 100 MB
FILE* indexDataPtr = fmemopen(indexData.data()+headerSizeBytes, indexData.size() - headerSizeBytes, "wb");
long bytes_written = 0;
if (indexDataPtr) {
if(featuresType_ == CV_8UC1)
{
((rtflann::Index<rtflann::Hamming<unsigned char> >*)index_)->save(indexDataPtr);
}
else
{
if(useDistanceL1_)
{
((rtflann::Index<rtflann::L1<float> >*)index_)->save(indexDataPtr);;
}
else if(featuresDim_ <= 3)
{
((rtflann::Index<rtflann::L2_Simple<float> >*)index_)->save(indexDataPtr);;
}
else
{
((rtflann::Index<rtflann::L2<float> >*)index_)->save(indexDataPtr);;
}
}
bytes_written = ftell(indexDataPtr);
fclose(indexDataPtr);
}
if(bytes_written < long(indexData.size()-headerSizeBytes))
{
//Expected data size and type
int dataRows = 0;
int dataCols = 0;
int dataType = -1;
cv::Mat dataset;
std::set<int> removedDescriptors;
if(computeChecksum){
removedDescriptors.insert(removedIndexes_.begin(), removedIndexes_.end());
}
for(const auto & iter: addedDescriptors_)
{
UASSERT(!iter.second.empty());
dataRows += iter.second.rows;
if(dataCols <= 0) {
dataCols = iter.second.cols;
}
else {
UASSERT(dataCols == iter.second.cols);
}
if(dataType < 0) {
dataType = iter.second.type();
}
else {
UASSERT(dataType == iter.second.type());
}
if(computeChecksum){
if(removedDescriptors.find(iter.first) == removedDescriptors.end()) {
if(dataset.empty()) {
dataset = iter.second.clone();
}
else {
dataset.push_back(iter.second);
}
}
else {
dataRows -= iter.second.rows;
}
}
}
if(!computeChecksum) {
for(const auto & index: removedIndexes_)
{
dataRows -= addedDescriptors_.at(index).rows;
}
}
unsigned int crcValue = 0;
if(computeChecksum) {
boost::crc_32_type result;
result.process_bytes(dataset.data, dataset.total()*dataset.elemSize());
crcValue = result.checksum();
}
indexData.resize(bytes_written+headerSizeBytes);
indexData.shrink_to_fit();
int rebalancingFactorAsInt;
memcpy(&rebalancingFactorAsInt, &rebalancingFactor_, sizeof(rebalancingFactor_));
int crcValueAsInt;
memcpy(&crcValueAsInt, &crcValue, sizeof(crcValue));
int header[FLANN_INDEX_HEADER_SIZE] = {
RTABMAP_VERSION_MAJOR, RTABMAP_VERSION_MINOR, RTABMAP_VERSION_PATCH, // 0,1,2
algorithm_, // 3,
featuresDim_, // 4,
useDistanceL1_?1:0, // 5,
rebalancingFactorAsInt, // 6,
dataRows, // 7,
dataCols, // 8,
dataType, // 9,
crcValueAsInt, // 10
(int)bytes_written}; // 11
UDEBUG("Header: \"%d.%d.%d\" alg=%d dim=%d L1=%d factor=%f data(%dx%d type=%d, crc=%X) %d",
header[0],header[1],header[2],
header[3],
header[4],
header[5],
rebalancingFactor_,
header[7], header[8], header[9], crcValueAsInt,
header[11]);
memcpy(indexData.data(), header, headerSizeBytes);
return indexData;
}
else {
UERROR("Target buffer too small to serialize index, aborting.");
}
UDEBUG("Flann serialization: %fs", timer.ticks());
#endif
}
return std::vector<unsigned char>();
} }
size_t FlannIndex::indexedFeatures() const size_t FlannIndex::indexedFeatures() const
@@ -273,13 +139,12 @@ size_t FlannIndex::memoryUsed() const
return memoryUsage; return memoryUsage;
} }
void FlannIndex::buildIndex( void FlannIndex::buildLinearIndex(
flann_algorithm_t algorithm,
const cv::Mat & features, const cv::Mat & features,
bool useDistanceL1, bool useDistanceL1,
float rebalancingFactor) float rebalancingFactor)
{ {
UDEBUG("algorithm=%d", (int)algorithm); UDEBUG("");
this->release(); this->release();
UASSERT(index_ == 0); UASSERT(index_ == 0);
UASSERT(features.type() == CV_32FC1 || features.type() == CV_8UC1); UASSERT(features.type() == CV_32FC1 || features.type() == CV_8UC1);
@@ -287,29 +152,8 @@ void FlannIndex::buildIndex(
featuresDim_ = features.cols; featuresDim_ = features.cols;
useDistanceL1_ = useDistanceL1; useDistanceL1_ = useDistanceL1;
rebalancingFactor_ = rebalancingFactor; rebalancingFactor_ = rebalancingFactor;
algorithm_ = algorithm;
rtflann::IndexParams params; rtflann::LinearIndexParams params;
switch (algorithm)
{
case FLANN_INDEX_LINEAR:
params = rtflann::LinearIndexParams();
break;
case FLANN_INDEX_KDTREE:
params = rtflann::KDTreeIndexParams(4);
break;
case FLANN_INDEX_KDTREE_SINGLE:
params = rtflann::KDTreeSingleIndexParams(10, true);
break;
case FLANN_INDEX_LSH:
UASSERT(features.type() == CV_8UC1);
params = rtflann::LshIndexParams(12, 20, 2);
break;
default:
UFATAL("The flann algorithm type %d is not supported!", (int)algorithm);
break;
}
if(featuresType_ == CV_8UC1) if(featuresType_ == CV_8UC1)
{ {
@@ -355,140 +199,13 @@ void FlannIndex::buildIndex(
UDEBUG(""); UDEBUG("");
} }
bool FlannIndex::loadIndex( void FlannIndex::buildKDTreeIndex(
const std::vector<unsigned char> & indexData,
flann_algorithm_t algorithm,
const cv::Mat & features, const cv::Mat & features,
int trees,
bool useDistanceL1, bool useDistanceL1,
float rebalancingFactor, float rebalancingFactor)
std::string * error)
{ {
return loadIndex( UDEBUG("");
indexData.data(),
indexData.size(),
algorithm,
features,
useDistanceL1,
rebalancingFactor),
error;
}
bool FlannIndex::loadIndex(
const unsigned char * indexData,
size_t indexDataSize,
flann_algorithm_t algorithm,
const cv::Mat & features,
bool useDistanceL1,
float rebalancingFactor,
std::string * error)
{
UASSERT(indexData!=NULL);
if(indexDataSize == 0) {
UWARN("Trying to load empty index....");
return false;
}
#ifdef WIN32
UERROR("FLANN index deserialization is not yet implemented on Windows. Index cannot be loaded from memory buffer.");
return false;
#else
// Check if the features match the expected data from the index
size_t headerSizeBytes = sizeof(int)*FLANN_INDEX_HEADER_SIZE;
if(indexDataSize < headerSizeBytes) {
if(error) {
*error = uFormat("Wrong header size detected (%ld vs expected %ld).", indexDataSize, headerSizeBytes);
}
return false;
}
const int * header = (const int *)indexData;
int savedAlgorithm = header[3];
int savedDim = header[4];
bool savedDistanceL1 = header[5]==1;
float savedRebalancingFactor;
memcpy(&savedRebalancingFactor, &header[6], sizeof(header[6]));
int savedRows = header[7];
int savedCols = header[8];
int savedType = header[9];
unsigned int savedCrc;
memcpy(&savedCrc, &header[10], sizeof(header[10]));
int savedIndexSize = header[11];
UDEBUG("Header: \"%d.%d.%d\" alg=%d dim=%d L1=%d factor=%f data(%dx%d type=%d, crc=%X) %d",
header[0],header[1],header[2],
header[3],
header[4],
header[5],
savedRebalancingFactor,
header[7], header[8], header[9], savedCrc,
header[11]);
if(savedAlgorithm != algorithm) {
if(error) {
*error = uFormat("Serialized flann algorithm (%d) doesn't match the expected one (%d).", savedAlgorithm, algorithm);
}
return false;
}
if(savedDim != features.cols) {
if(error) {
*error = uFormat("Serialized feature dimension (%d) doesn't match the expected one (%d).", savedDim, features.cols);
}
return false;
}
if(savedDistanceL1 != useDistanceL1) {
if(error) {
*error = uFormat("Serialized \"use distance L1\" (%s) doesn't match the expected one (%s).", savedDistanceL1?"true":"false", useDistanceL1?"true":"false");
}
return false;
}
if(savedRebalancingFactor != rebalancingFactor) {
if(error) {
*error = uFormat("Serialized \"rebalancing factor\" (%f) doesn't match the expected one (%f).", savedRebalancingFactor, rebalancingFactor);
}
return false;
}
if(savedRows != features.rows) {
if(error) {
*error = uFormat("Serialized feature count (%d) doesn't match the expected one (%d).", savedRows, features.rows);
}
return false;
}
if(savedCols != features.cols) {
if(error) {
*error = uFormat("Serialized feature dimension (%d) doesn't match the expected one (%d).", savedCols, features.cols);
}
return false;
}
if(savedType != features.type()) {
if(error) {
*error = uFormat("Serialized feature type (%d) doesn't match the expected one (%d).", savedType, features.type());
}
return false;
}
if(savedCrc != 0) {
// Compute checksum and compare
boost::crc_32_type result;
result.process_bytes(features.data, features.total()*features.elemSize());
if(savedCrc != result.checksum()) {
if(error) {
*error = uFormat("Serialized feature crc (%X) doesn't match the expected one (%X).", savedCrc, result.checksum());
}
return false;
}
}
if(savedIndexSize != int(indexDataSize - headerSizeBytes)) {
if(error) {
*error = uFormat("Serialized flann index size (%ld) doesn't match the expected one (%ld).", savedIndexSize, indexDataSize - headerSizeBytes);
}
return false;
}
if(savedIndexSize == 0) {
if(error) {
*error = "Serialized flann index is empty.";
}
return false;
}
this->release(); this->release();
UASSERT(index_ == 0); UASSERT(index_ == 0);
UASSERT(features.type() == CV_32FC1 || features.type() == CV_8UC1); UASSERT(features.type() == CV_32FC1 || features.type() == CV_8UC1);
@@ -496,39 +213,14 @@ bool FlannIndex::loadIndex(
featuresDim_ = features.cols; featuresDim_ = features.cols;
useDistanceL1_ = useDistanceL1; useDistanceL1_ = useDistanceL1;
rebalancingFactor_ = rebalancingFactor; rebalancingFactor_ = rebalancingFactor;
algorithm_ = algorithm;
UDEBUG("algorithm=%d", (int)algorithm); rtflann::KDTreeIndexParams params(trees);
rtflann::IndexParams params;
switch (algorithm)
{
case FLANN_INDEX_LINEAR:
params = rtflann::LinearIndexParams();
break;
case FLANN_INDEX_KDTREE:
params = rtflann::KDTreeIndexParams(4);
break;
case FLANN_INDEX_KDTREE_SINGLE:
params = rtflann::KDTreeSingleIndexParams(10, true);
break;
case FLANN_INDEX_LSH:
UASSERT(features.type() == CV_8UC1);
params = rtflann::LshIndexParams(12, 20, 2);
break;
default:
UFATAL("The flann algorithm type %d is not supported!", (int)algorithm);
break;
}
FILE* indexDataPtr = fmemopen((void*)(indexData+headerSizeBytes), indexDataSize - headerSizeBytes, "r");
if(featuresType_ == CV_8UC1) if(featuresType_ == CV_8UC1)
{ {
rtflann::Matrix<unsigned char> dataset(features.data, features.rows, features.cols); rtflann::Matrix<unsigned char> dataset(features.data, features.rows, features.cols);
index_ = new rtflann::Index<rtflann::Hamming<unsigned char> >(dataset, params); index_ = new rtflann::Index<rtflann::Hamming<unsigned char> >(dataset, params);
((rtflann::Index<rtflann::Hamming<unsigned char> >*)index_)->load_saved_index(indexDataPtr); ((rtflann::Index<rtflann::Hamming<unsigned char> >*)index_)->buildIndex();
} }
else else
{ {
@@ -536,24 +228,22 @@ bool FlannIndex::loadIndex(
if(useDistanceL1_) if(useDistanceL1_)
{ {
index_ = new rtflann::Index<rtflann::L1<float> >(dataset, params); index_ = new rtflann::Index<rtflann::L1<float> >(dataset, params);
((rtflann::Index<rtflann::L1<float> >*)index_)->load_saved_index(indexDataPtr); ((rtflann::Index<rtflann::L1<float> >*)index_)->buildIndex();
} }
else if(featuresDim_ <=3) else if(featuresDim_ <=3)
{ {
index_ = new rtflann::Index<rtflann::L2_Simple<float> >(dataset, params); index_ = new rtflann::Index<rtflann::L2_Simple<float> >(dataset, params);
((rtflann::Index<rtflann::L2_Simple<float> >*)index_)->load_saved_index(indexDataPtr); ((rtflann::Index<rtflann::L2_Simple<float> >*)index_)->buildIndex();
} }
else else
{ {
index_ = new rtflann::Index<rtflann::L2<float> >(dataset, params); index_ = new rtflann::Index<rtflann::L2<float> >(dataset, params);
((rtflann::Index<rtflann::L2<float> >*)index_)->load_saved_index(indexDataPtr); ((rtflann::Index<rtflann::L2<float> >*)index_)->buildIndex();
} }
} }
fclose(indexDataPtr);
// incremental FLANN: we should add all headers separately in case we remove // incremental FLANN: we should add all headers separately in case we remove
// some indexes (to keep underlying matrix data allocated) // some indexes (to keep underlying matrix data allocated)
if(rebalancingFactor_ > 1.0f) if(rebalancingFactor_ > 1.0f)
{ {
for(int i=0; i<features.rows; ++i) for(int i=0; i<features.rows; ++i)
@@ -567,8 +257,107 @@ bool FlannIndex::loadIndex(
addedDescriptors_.insert(std::make_pair(nextIndex_, features)); addedDescriptors_.insert(std::make_pair(nextIndex_, features));
nextIndex_ += features.rows; nextIndex_ += features.rows;
} }
return true; UDEBUG("");
#endif }
void FlannIndex::buildKDTreeSingleIndex(
const cv::Mat & features,
int leafMaxSize,
bool reorder,
bool useDistanceL1,
float rebalancingFactor)
{
UDEBUG("");
this->release();
UASSERT(index_ == 0);
UASSERT(features.type() == CV_32FC1 || features.type() == CV_8UC1);
featuresType_ = features.type();
featuresDim_ = features.cols;
useDistanceL1_ = useDistanceL1;
rebalancingFactor_ = rebalancingFactor;
rtflann::KDTreeSingleIndexParams params(leafMaxSize, reorder);
if(featuresType_ == CV_8UC1)
{
rtflann::Matrix<unsigned char> dataset(features.data, features.rows, features.cols);
index_ = new rtflann::Index<rtflann::Hamming<unsigned char> >(dataset, params);
((rtflann::Index<rtflann::Hamming<unsigned char> >*)index_)->buildIndex();
}
else
{
rtflann::Matrix<float> dataset((float*)features.data, features.rows, features.cols);
if(useDistanceL1_)
{
index_ = new rtflann::Index<rtflann::L1<float> >(dataset, params);
((rtflann::Index<rtflann::L1<float> >*)index_)->buildIndex();
}
else if(featuresDim_ <=3)
{
index_ = new rtflann::Index<rtflann::L2_Simple<float> >(dataset, params);
((rtflann::Index<rtflann::L2_Simple<float> >*)index_)->buildIndex();
}
else
{
index_ = new rtflann::Index<rtflann::L2<float> >(dataset, params);
((rtflann::Index<rtflann::L2<float> >*)index_)->buildIndex();
}
}
// incremental FLANN: we should add all headers separately in case we remove
// some indexes (to keep underlying matrix data allocated)
if(rebalancingFactor_ > 1.0f)
{
for(int i=0; i<features.rows; ++i)
{
addedDescriptors_.insert(std::make_pair(nextIndex_++, features.row(i)));
}
}
else
{
// tree won't ever be rebalanced, so just keep only one header for the data
addedDescriptors_.insert(std::make_pair(nextIndex_, features));
nextIndex_ += features.rows;
}
UDEBUG("");
}
void FlannIndex::buildLSHIndex(
const cv::Mat & features,
unsigned int table_number,
unsigned int key_size,
unsigned int multi_probe_level,
float rebalancingFactor)
{
UDEBUG("");
this->release();
UASSERT(index_ == 0);
UASSERT(features.type() == CV_8UC1);
featuresType_ = features.type();
featuresDim_ = features.cols;
useDistanceL1_ = true;
rebalancingFactor_ = rebalancingFactor;
rtflann::Matrix<unsigned char> dataset(features.data, features.rows, features.cols);
index_ = new rtflann::Index<rtflann::Hamming<unsigned char> >(dataset, rtflann::LshIndexParams(12, 20, 2));
((rtflann::Index<rtflann::Hamming<unsigned char> >*)index_)->buildIndex();
// incremental FLANN: we should add all headers separately in case we remove
// some indexes (to keep underlying matrix data allocated)
if(rebalancingFactor_ > 1.0f)
{
for(int i=0; i<features.rows; ++i)
{
addedDescriptors_.insert(std::make_pair(nextIndex_++, features.row(i)));
}
}
else
{
// tree won't ever be rebalanced, so just keep only one header for the data
addedDescriptors_.insert(std::make_pair(nextIndex_, features));
nextIndex_ += features.rows;
}
UDEBUG("");
} }
bool FlannIndex::isBuilt() bool FlannIndex::isBuilt()
+6 -11
View File
@@ -99,12 +99,15 @@ unsigned long GlobalMap::getMemoryUsed() const
return memoryUsage; return memoryUsage;
} }
bool GlobalMap::fullUpdateNeeded(const std::map<int, Transform> & poses) const bool GlobalMap::update(const std::map<int, Transform> & poses)
{ {
UDEBUG("Update (poses=%d addedNodes_=%d)", (int)poses.size(), (int)addedNodes_.size());
// First, check of the graph has changed. If so, re-create the octree by moving all occupied nodes.
bool graphOptimized = false; // If a loop closure happened (e.g., poses are modified) bool graphOptimized = false; // If a loop closure happened (e.g., poses are modified)
bool graphChanged = addedNodes_.size()>0; // If the new map doesn't have any node from the previous map bool graphChanged = addedNodes_.size()>0; // If the new map doesn't have any node from the previous map
float updateErrorSqrd = updateError_*updateError_; float updateErrorSqrd = updateError_*updateError_;
for(std::map<int, Transform>::const_iterator iter=addedNodes_.begin(); iter!=addedNodes_.end(); ++iter) for(std::map<int, Transform>::iterator iter=addedNodes_.begin(); iter!=addedNodes_.end(); ++iter)
{ {
std::map<int, Transform>::const_iterator jter = poses.find(iter->first); std::map<int, Transform>::const_iterator jter = poses.find(iter->first);
if(jter != poses.end()) if(jter != poses.end())
@@ -122,15 +125,7 @@ bool GlobalMap::fullUpdateNeeded(const std::map<int, Transform> & poses) const
} }
} }
return graphOptimized || graphChanged; if(graphOptimized || graphChanged)
}
bool GlobalMap::update(const std::map<int, Transform> & poses)
{
UDEBUG("Update (poses=%d addedNodes_=%d)", (int)poses.size(), (int)addedNodes_.size());
// First, check of the graph has changed. If so, re-create the octree by moving all occupied nodes.
if(fullUpdateNeeded(poses))
{ {
// clear all but keep cache // clear all but keep cache
clear(); clear();
+2 -20
View File
@@ -196,7 +196,7 @@ bool exportPoses(
bool importPoses( bool importPoses(
const std::string & filePath, const std::string & filePath,
int format, // 0=Raw, 1=RGBD-SLAM motion capture (10=without change of coordinate frame, 11=10+ID), 2=KITTI, 3=TORO, 4=g2o, 5=NewCollege(t,x,y), 6=Malaga Urban GPS, 7=St Lucia INS, 8=Karlsruhe, 9=EuRoC MAV, 12=rgbd_bonn int format, // 0=Raw, 1=RGBD-SLAM motion capture (10=without change of coordinate frame, 11=10+ID), 2=KITTI, 3=TORO, 4=g2o, 5=NewCollege(t,x,y), 6=Malaga Urban GPS, 7=St Lucia INS, 8=Karlsruhe, 9=EuRoC MAV
std::map<int, Transform> & poses, std::map<int, Transform> & poses,
std::multimap<int, Link> * constraints, // optional for formats 3 and 4 std::multimap<int, Link> * constraints, // optional for formats 3 and 4
std::map<int, double> * stamps) // optional for format 1 and 9 std::map<int, double> * stamps) // optional for format 1 and 9
@@ -440,15 +440,11 @@ bool importPoses(
UERROR("Error parsing \"%s\" with NewCollege format (should have 3 values: stamp x y, found %d)", str.c_str(), (int)strList.size()); UERROR("Error parsing \"%s\" with NewCollege format (should have 3 values: stamp x y, found %d)", str.c_str(), (int)strList.size());
} }
} }
else if(format == 1 || format==10 || format==11 || format==12) // rgbd-slam format else if(format == 1 || format==10 || format==11) // rgbd-slam format
{ {
std::list<std::string> strList = uSplit(str); std::list<std::string> strList = uSplit(str);
if((strList.size() >= 8 && format!=11) || (strList.size() == 9 && format==11)) if((strList.size() >= 8 && format!=11) || (strList.size() == 9 && format==11))
{ {
if(!uIsNumber(strList.front())) {
UWARN("Skipping \"%s\"", str.c_str());
continue;
}
double stamp = uStr2Double(strList.front()); double stamp = uStr2Double(strList.front());
strList.pop_front(); strList.pop_front();
if(format==11) if(format==11)
@@ -481,20 +477,6 @@ bool importPoses(
1, 0, 0, 0); 1, 0, 0, 0);
pose = t*pose; pose = t*pose;
} }
else if(format == 12)
{
// See https://www.ipb.uni-bonn.de/data/rgbd-dynamic-dataset/index.html
Transform T_ros(-1, 0, 0, 0,
0, 0, 1, 0,
0, 1, 0, 0);
Transform T_m(
1.0157, 0.1828, -0.2389, 0.0113,
0.0009, -0.8431, -0.6413, -0.00980,
-0.3009, 0.6147, -0.8085, 0.0111);
// we remove the optical rotation
pose = T_ros*pose*T_ros*T_m*CameraModel::opticalRotation().inverse();
}
poses.insert(std::make_pair(id, pose)); poses.insert(std::make_pair(id, pose));
} }
} }
+2 -2
View File
@@ -64,8 +64,8 @@ void LocalGridCache::add(int nodeId,
void LocalGridCache::add(int nodeId, const LocalGrid & localGrid) void LocalGridCache::add(int nodeId, const LocalGrid & localGrid)
{ {
//UDEBUG("nodeId=%d (ground=%d/%d obstacles=%d/%d empty=%d/%d)", UDEBUG("nodeId=%d (ground=%d/%d obstacles=%d/%d empty=%d/%d)",
// nodeId, localGrid.groundCells.cols, localGrid.groundCells.channels(), localGrid.obstacleCells.cols, localGrid.obstacleCells.channels(), localGrid.emptyCells.cols, localGrid.emptyCells.channels()); nodeId, localGrid.groundCells.cols, localGrid.groundCells.channels(), localGrid.obstacleCells.cols, localGrid.obstacleCells.channels(), localGrid.emptyCells.cols, localGrid.emptyCells.channels());
if(nodeId < 0) if(nodeId < 0)
{ {
UWARN("Cannot add nodes with negative id (nodeId=%d)", nodeId); UWARN("Cannot add nodes with negative id (nodeId=%d)", nodeId);
+40 -135
View File
@@ -76,7 +76,6 @@ Memory::Memory(const ParametersMap & parameters) :
_similarityThreshold(Parameters::defaultMemRehearsalSimilarity()), _similarityThreshold(Parameters::defaultMemRehearsalSimilarity()),
_binDataKept(Parameters::defaultMemBinDataKept()), _binDataKept(Parameters::defaultMemBinDataKept()),
_rawDescriptorsKept(Parameters::defaultMemRawDescriptorsKept()), _rawDescriptorsKept(Parameters::defaultMemRawDescriptorsKept()),
_loadVisualLocalFeaturesOnInit(Parameters::defaultMemLoadVisualLocalFeaturesOnInit()),
_saveDepth16Format(Parameters::defaultMemSaveDepth16Format()), _saveDepth16Format(Parameters::defaultMemSaveDepth16Format()),
_notLinkedNodesKeptInDb(Parameters::defaultMemNotLinkedNodesKept()), _notLinkedNodesKeptInDb(Parameters::defaultMemNotLinkedNodesKept()),
_saveIntermediateNodeData(Parameters::defaultMemIntermediateNodeDataKept()), _saveIntermediateNodeData(Parameters::defaultMemIntermediateNodeDataKept()),
@@ -84,7 +83,6 @@ Memory::Memory(const ParametersMap & parameters) :
_depthCompressionFormat(Parameters::defaultMemDepthCompressionFormat()), _depthCompressionFormat(Parameters::defaultMemDepthCompressionFormat()),
_incrementalMemory(Parameters::defaultMemIncrementalMemory()), _incrementalMemory(Parameters::defaultMemIncrementalMemory()),
_localizationDataSaved(Parameters::defaultMemLocalizationDataSaved()), _localizationDataSaved(Parameters::defaultMemLocalizationDataSaved()),
_flannIndexSaved(Parameters::defaultKpFlannIndexSaved()),
_reduceGraph(Parameters::defaultMemReduceGraph()), _reduceGraph(Parameters::defaultMemReduceGraph()),
_maxStMemSize(Parameters::defaultMemSTMSize()), _maxStMemSize(Parameters::defaultMemSTMSize()),
_recentWmRatio(Parameters::defaultMemRecentWmRatio()), _recentWmRatio(Parameters::defaultMemRecentWmRatio()),
@@ -131,7 +129,6 @@ Memory::Memory(const ParametersMap & parameters) :
_linksChanged(false), _linksChanged(false),
_signaturesAdded(0), _signaturesAdded(0),
_allNodesInWM(true), _allNodesInWM(true),
_receivingOdometryFeatures(false),
_badSignRatio(Parameters::defaultKpBadSignRatio()), _badSignRatio(Parameters::defaultKpBadSignRatio()),
_tfIdfLikelihoodUsed(Parameters::defaultKpTfIdfLikelihoodUsed()), _tfIdfLikelihoodUsed(Parameters::defaultKpTfIdfLikelihoodUsed()),
_parallelized(Parameters::defaultKpParallelized()), _parallelized(Parameters::defaultKpParallelized()),
@@ -248,13 +245,13 @@ void Memory::loadDataFromDb(bool postInitClosingEvents)
if(postInitClosingEvents) UEventsManager::post(new RtabmapEventInit(std::string("Loading all nodes to WM..."))); if(postInitClosingEvents) UEventsManager::post(new RtabmapEventInit(std::string("Loading all nodes to WM...")));
std::set<int> ids; std::set<int> ids;
_dbDriver->getAllNodeIds(ids, true); _dbDriver->getAllNodeIds(ids, true);
_dbDriver->loadSignatures(std::list<int>(ids.begin(), ids.end()), dbSignatures, 0, !_loadVisualLocalFeaturesOnInit); _dbDriver->loadSignatures(std::list<int>(ids.begin(), ids.end()), dbSignatures);
} }
else else
{ {
// load previous session working memory // load previous session working memory
if(postInitClosingEvents) UEventsManager::post(new RtabmapEventInit(std::string("Loading last nodes to WM..."))); if(postInitClosingEvents) UEventsManager::post(new RtabmapEventInit(std::string("Loading last nodes to WM...")));
_dbDriver->loadLastNodes(dbSignatures, !_loadVisualLocalFeaturesOnInit); _dbDriver->loadLastNodes(dbSignatures);
} }
for(std::list<Signature*>::reverse_iterator iter=dbSignatures.rbegin(); iter!=dbSignatures.rend(); ++iter) for(std::list<Signature*>::reverse_iterator iter=dbSignatures.rbegin(); iter!=dbSignatures.rend(); ++iter)
{ {
@@ -420,22 +417,20 @@ void Memory::loadDataFromDb(bool postInitClosingEvents)
} }
else else
{ {
_dbDriver->load(*_vwd, false); _dbDriver->load(_vwd, false);
} }
} }
else else
{ {
UDEBUG("load words"); UDEBUG("load words");
// load the last dictionary // load the last dictionary
_dbDriver->load(*_vwd, _vwd->isIncremental()); _dbDriver->load(_vwd, _vwd->isIncremental());
} }
UDEBUG("%d words loaded!", _vwd->getUnusedWordsSize()); UDEBUG("%d words loaded!", _vwd->getUnusedWordsSize());
_vwd->update(); _vwd->update();
if(postInitClosingEvents) UEventsManager::post(new RtabmapEventInit(uFormat("Loading dictionary, done! (%d words)", (int)_vwd->getUnusedWordsSize()))); if(postInitClosingEvents) UEventsManager::post(new RtabmapEventInit(uFormat("Loading dictionary, done! (%d words)", (int)_vwd->getUnusedWordsSize())));
if(postInitClosingEvents) UEventsManager::post(new RtabmapEventInit(std::string("Adding word references..."))); if(postInitClosingEvents) UEventsManager::post(new RtabmapEventInit(std::string("Adding word references...")));
UDEBUG("Adding word references...");
UTimer timer;
// Enable loaded signatures // Enable loaded signatures
const std::map<int, Signature *> & signatures = this->getSignatures(); const std::map<int, Signature *> & signatures = this->getSignatures();
for(std::map<int, Signature *>::const_iterator i=signatures.begin(); i!=signatures.end(); ++i) for(std::map<int, Signature *>::const_iterator i=signatures.begin(); i!=signatures.end(); ++i)
@@ -446,7 +441,7 @@ void Memory::loadDataFromDb(bool postInitClosingEvents)
const std::multimap<int, int> & words = s->getWords(); const std::multimap<int, int> & words = s->getWords();
if(words.size()) if(words.size())
{ {
//UDEBUG("node=%d, word references=%d", s->id(), words.size()); UDEBUG("node=%d, word references=%d", s->id(), words.size());
for(std::multimap<int, int>::const_iterator iter = words.begin(); iter!=words.end(); ++iter) for(std::multimap<int, int>::const_iterator iter = words.begin(); iter!=words.end(); ++iter)
{ {
if(iter->first > 0) if(iter->first > 0)
@@ -463,7 +458,7 @@ void Memory::loadDataFromDb(bool postInitClosingEvents)
{ {
UWARN("_vwd->getUnusedWordsSize() must be empty... size=%d", _vwd->getUnusedWordsSize()); UWARN("_vwd->getUnusedWordsSize() must be empty... size=%d", _vwd->getUnusedWordsSize());
} }
UDEBUG("Total word references added = %d (in %f s)", _vwd->getTotalActiveReferences(), timer.ticks()); UDEBUG("Total word references added = %d", _vwd->getTotalActiveReferences());
if(_lastSignature == 0) if(_lastSignature == 0)
{ {
@@ -487,37 +482,6 @@ void Memory::loadDataFromDb(bool postInitClosingEvents)
UDEBUG("map ids start with %d", _idMapCount); UDEBUG("map ids start with %d", _idMapCount);
} }
void Memory::saveFlannIndex(bool postInitClosingEvents)
{
if(!_dbDriver) {
return;
}
if(uStrNumCmp(_dbDriver->getDatabaseVersion(), "0.23.0") >= 0) {
if(_flannIndexSaved && !_incrementalMemory) {
if(_vwd->isModified()) {
UINFO("Saving flann index to database... (%s=true)", Parameters::kKpFlannIndexSaved().c_str());
if(postInitClosingEvents) UEventsManager::post(new RtabmapEventInit("Saving flann index to database..."));
_dbDriver->saveFlannIndex(_vwd->serializeIndex());
if(postInitClosingEvents) UEventsManager::post(new RtabmapEventInit("Saving flann index to database, done!"));
}
else
{
UDEBUG("The dictionary didn't change since loaded, do not need to save again to database.");
}
}
else {
// clear if exists
_dbDriver->saveFlannIndex(std::vector<unsigned char>());
}
}
else if(_flannIndexSaved)
{
UWARN("Parameter %s is enabled, but database version is too old (%s < 0.23). Flann index cannot be saved.",
Parameters::kKpFlannIndexSaved().c_str(),
_dbDriver->getDatabaseVersion().c_str());
}
}
void Memory::close(bool databaseSaved, bool postInitClosingEvents, const std::string & ouputDatabasePath) void Memory::close(bool databaseSaved, bool postInitClosingEvents, const std::string & ouputDatabasePath)
{ {
UINFO("databaseSaved=%d, postInitClosingEvents=%d", databaseSaved?1:0, postInitClosingEvents?1:0); UINFO("databaseSaved=%d, postInitClosingEvents=%d", databaseSaved?1:0, postInitClosingEvents?1:0);
@@ -529,8 +493,6 @@ void Memory::close(bool databaseSaved, bool postInitClosingEvents, const std::st
databaseNameChanged = ouputDatabasePath.size() && _dbDriver->getUrl().size() && _dbDriver->getUrl().compare(ouputDatabasePath) != 0?true:false; databaseNameChanged = ouputDatabasePath.size() && _dbDriver->getUrl().size() && _dbDriver->getUrl().compare(ouputDatabasePath) != 0?true:false;
} }
UDEBUG("_memoryChanged=%d _linksChanged=%d databaseNameChanged=%d", _memoryChanged?1:0, _linksChanged?1:0, databaseNameChanged?1:0);
if(!databaseSaved || (!_memoryChanged && !_linksChanged && !databaseNameChanged)) if(!databaseSaved || (!_memoryChanged && !_linksChanged && !databaseNameChanged))
{ {
if(postInitClosingEvents) UEventsManager::post(new RtabmapEventInit(uFormat("No changes added to database."))); if(postInitClosingEvents) UEventsManager::post(new RtabmapEventInit(uFormat("No changes added to database.")));
@@ -538,7 +500,6 @@ void Memory::close(bool databaseSaved, bool postInitClosingEvents, const std::st
UINFO("No changes added to database."); UINFO("No changes added to database.");
if(_dbDriver) if(_dbDriver)
{ {
saveFlannIndex(postInitClosingEvents);
if(postInitClosingEvents) UEventsManager::post(new RtabmapEventInit(uFormat("Closing database \"%s\"...", _dbDriver->getUrl().c_str()))); if(postInitClosingEvents) UEventsManager::post(new RtabmapEventInit(uFormat("Closing database \"%s\"...", _dbDriver->getUrl().c_str())));
_dbDriver->closeConnection(false, ouputDatabasePath); _dbDriver->closeConnection(false, ouputDatabasePath);
delete _dbDriver; delete _dbDriver;
@@ -553,16 +514,12 @@ void Memory::close(bool databaseSaved, bool postInitClosingEvents, const std::st
{ {
UINFO("Saving memory..."); UINFO("Saving memory...");
if(postInitClosingEvents) UEventsManager::post(new RtabmapEventInit("Saving memory...")); if(postInitClosingEvents) UEventsManager::post(new RtabmapEventInit("Saving memory..."));
if(!_memoryChanged && _dbDriver) if(!_memoryChanged && _linksChanged && _dbDriver)
{ {
saveFlannIndex(postInitClosingEvents);
if(_linksChanged) {
// don't update the time stamps! // don't update the time stamps!
UDEBUG(""); UDEBUG("");
_dbDriver->setTimestampUpdateEnabled(false); _dbDriver->setTimestampUpdateEnabled(false);
} }
}
this->clear(); this->clear();
if(_dbDriver) if(_dbDriver)
{ {
@@ -608,7 +565,6 @@ void Memory::parseParameters(const ParametersMap & parameters)
Parameters::parse(params, Parameters::kMemBinDataKept(), _binDataKept); Parameters::parse(params, Parameters::kMemBinDataKept(), _binDataKept);
Parameters::parse(params, Parameters::kMemRawDescriptorsKept(), _rawDescriptorsKept); Parameters::parse(params, Parameters::kMemRawDescriptorsKept(), _rawDescriptorsKept);
Parameters::parse(params, Parameters::kMemLoadVisualLocalFeaturesOnInit(), _loadVisualLocalFeaturesOnInit);
Parameters::parse(params, Parameters::kMemSaveDepth16Format(), _saveDepth16Format); Parameters::parse(params, Parameters::kMemSaveDepth16Format(), _saveDepth16Format);
Parameters::parse(params, Parameters::kMemReduceGraph(), _reduceGraph); Parameters::parse(params, Parameters::kMemReduceGraph(), _reduceGraph);
Parameters::parse(params, Parameters::kMemNotLinkedNodesKept(), _notLinkedNodesKeptInDb); Parameters::parse(params, Parameters::kMemNotLinkedNodesKept(), _notLinkedNodesKeptInDb);
@@ -662,7 +618,6 @@ void Memory::parseParameters(const ParametersMap & parameters)
Parameters::parse(params, Parameters::kMarkerVarianceAngular(), _markerAngVariance); Parameters::parse(params, Parameters::kMarkerVarianceAngular(), _markerAngVariance);
Parameters::parse(params, Parameters::kMarkerVarianceOrientationIgnored(), _markerOrientationIgnored); Parameters::parse(params, Parameters::kMarkerVarianceOrientationIgnored(), _markerOrientationIgnored);
Parameters::parse(params, Parameters::kMemLocalizationDataSaved(), _localizationDataSaved); Parameters::parse(params, Parameters::kMemLocalizationDataSaved(), _localizationDataSaved);
Parameters::parse(params, Parameters::kKpFlannIndexSaved(), _flannIndexSaved);
if(_markerAngVariance>=9999) if(_markerAngVariance>=9999)
{ {
@@ -699,7 +654,10 @@ void Memory::parseParameters(const ParametersMap & parameters)
} }
// Keypoint stuff // Keypoint stuff
if(_vwd)
{
_vwd->parseParameters(params); _vwd->parseParameters(params);
}
Parameters::parse(params, Parameters::kKpTfIdfLikelihoodUsed(), _tfIdfLikelihoodUsed); Parameters::parse(params, Parameters::kKpTfIdfLikelihoodUsed(), _tfIdfLikelihoodUsed);
Parameters::parse(params, Parameters::kKpParallelized(), _parallelized); Parameters::parse(params, Parameters::kKpParallelized(), _parallelized);
@@ -898,7 +856,7 @@ void Memory::preUpdate()
{ {
this->cleanUnusedWords(); this->cleanUnusedWords();
} }
if(!_parallelized) if(_vwd && !_parallelized)
{ {
//When parallelized, it is done in CreateSignature //When parallelized, it is done in CreateSignature
_vwd->update(); _vwd->update();
@@ -1156,7 +1114,10 @@ void Memory::addSignatureToStm(Signature * signature, const cv::Mat & covariance
} }
++_signaturesAdded; ++_signaturesAdded;
if(_vwd)
{
UDEBUG("%d words ref for the signature %d (weight=%d)", signature->getWords().size(), signature->id(), signature->getWeight()); UDEBUG("%d words ref for the signature %d (weight=%d)", signature->getWords().size(), signature->id(), signature->getWeight());
}
if(signature->getWords().size()) if(signature->getWords().size())
{ {
signature->setEnabled(true); signature->setEnabled(true);
@@ -1263,12 +1224,10 @@ void Memory::moveSignatureToWMFromSTM(int id, int * reducedTo)
std::multimap<int, Link> linksCopy = links; std::multimap<int, Link> linksCopy = links;
for(std::multimap<int, Link>::iterator iter=linksCopy.begin(); iter!=linksCopy.end(); ++iter) for(std::multimap<int, Link>::iterator iter=linksCopy.begin(); iter!=linksCopy.end(); ++iter)
{ {
if(iter->second.type() == Link::kNeighborMerged) if(iter->second.type() == Link::kNeighbor ||
iter->second.type() == Link::kNeighborMerged)
{ {
// Removing only merged neighbor links, we keep original neighbor
// links to be able to reprocess databases with correct odometry covariance.
s->removeLink(iter->first); s->removeLink(iter->first);
}
if(iter->second.type() == Link::kNeighbor) if(iter->second.type() == Link::kNeighbor)
{ {
if(_lastGlobalLoopClosureId == s->id()) if(_lastGlobalLoopClosureId == s->id())
@@ -1277,6 +1236,7 @@ void Memory::moveSignatureToWMFromSTM(int id, int * reducedTo)
} }
} }
} }
}
// Setting true to make sure we save all visual // Setting true to make sure we save all visual
// words that could be referenced in a previously // words that could be referenced in a previously
@@ -1876,26 +1836,15 @@ void Memory::clear()
UDEBUG(""); UDEBUG("");
//Get the tree root (parents) //Get the tree root (parents)
if(!_dbDriver) {
// We are not saving to database anyway, just delete now.
for(std::map<int, Signature *>::iterator iter=_signatures.begin(); iter!=_signatures.end(); ++iter)
{
delete iter->second;
}
_workingMem.clear();
_signatures.clear();
}
else {
std::map<int, Signature*> mem = _signatures; std::map<int, Signature*> mem = _signatures;
for(std::map<int, Signature *>::iterator i=mem.begin(); i!=mem.end(); ++i) for(std::map<int, Signature *>::iterator i=mem.begin(); i!=mem.end(); ++i)
{ {
if(i->second) if(i->second)
{ {
//UDEBUG("deleting from the working and the short-term memory: %d", i->first); UDEBUG("deleting from the working and the short-term memory: %d", i->first);
this->moveToTrash(i->second); this->moveToTrash(i->second);
} }
} }
}
if(_workingMem.size() != 0 && !(_workingMem.size() == 1 && _workingMem.begin()->first == kIdVirtual)) if(_workingMem.size() != 0 && !(_workingMem.size() == 1 && _workingMem.begin()->first == kIdVirtual))
{ {
@@ -1917,7 +1866,6 @@ void Memory::clear()
UDEBUG(""); UDEBUG("");
_lastSignature = 0; _lastSignature = 0;
_lastGlobalLoopClosureId = 0; _lastGlobalLoopClosureId = 0;
_signaturesAdded = 0;
_idCount = kIdStart; _idCount = kIdStart;
_idMapCount = kIdStart; _idMapCount = kIdStart;
_memoryChanged = false; _memoryChanged = false;
@@ -1931,7 +1879,6 @@ void Memory::clear()
_landmarksIndex.clear(); _landmarksIndex.clear();
_landmarksSize.clear(); _landmarksSize.clear();
_allNodesInWM = true; _allNodesInWM = true;
_receivingOdometryFeatures = false;
if(_dbDriver) if(_dbDriver)
{ {
@@ -1939,7 +1886,14 @@ void Memory::clear()
cleanUnusedWords(); cleanUnusedWords();
_dbDriver->emptyTrashes(); _dbDriver->emptyTrashes();
} }
_vwd->clear(_dbDriver!=NULL); else
{
cleanUnusedWords();
}
if(_vwd)
{
_vwd->clear();
}
UDEBUG(""); UDEBUG("");
} }
@@ -2474,7 +2428,7 @@ std::list<Signature *> Memory::getRemovableSignatures(int count, const std::set<
*/ */
void Memory::moveToTrash(Signature * s, bool keepLinkedToGraph, std::list<int> * deletedWords) void Memory::moveToTrash(Signature * s, bool keepLinkedToGraph, std::list<int> * deletedWords)
{ {
//UDEBUG("id=%d", s?s->id():0); UDEBUG("id=%d", s?s->id():0);
if(s) if(s)
{ {
// Cleanup landmark indexes // Cleanup landmark indexes
@@ -2967,37 +2921,6 @@ Transform Memory::computeTransform(
_registrationPipeline->isScanRequired()?&laserBuf:0, _registrationPipeline->isScanRequired()?&laserBuf:0,
_registrationPipeline->isUserDataRequired()?&userBuf:0); _registrationPipeline->isUserDataRequired()?&userBuf:0);
// Load word descriptors and keypoints on-demand if necessary
if( !_reextractLoopClosureFeatures &&
(_registrationPipeline->isImageRequired() || guess.isNull()) &&
!fromS.getWords().empty() && fromS.getWordsKpts().empty() &&
_dbDriver)
{
// We assume "toS" has already features in RAM, so just lookup "fromS"
UDEBUG("Loading local visual features for signature %d", fromS.id());
std::multimap<int, int> words;
std::vector<cv::KeyPoint> keypoints;
std::vector<cv::Point3f> points;
cv::Mat descriptors;
UTimer timer;
_dbDriver->getLocalFeatures(fromS.id(), words, keypoints, points, descriptors);
if(!words.empty() && !keypoints.empty()) {
UASSERT(words.size() == fromS.getWords().size());
std::map<int, int> wordsChanged = fromS.getWordsChanged();
bool wasEnabled = fromS.isEnabled();
fromS.setWords(words, keypoints, points, descriptors);
for(const auto & iter: wordsChanged) {
fromS.changeWordsRef(iter.first, iter.second);
}
fromS.setEnabled(wasEnabled);
UDEBUG("Loaded %ld local visual features for signature %d! (in %f s)", words.size(), fromS.id(), timer.ticks());
}
else
{
UDEBUG("Failed to load local visual features for signature %d.", fromS.id());
}
}
// compute transform fromId -> toId // compute transform fromId -> toId
std::vector<int> inliersV; std::vector<int> inliersV;
@@ -3057,10 +2980,8 @@ Transform Memory::computeTransform(
!_invertedReg && !_invertedReg &&
!tmpTo.getWordsDescriptors().empty() && !tmpTo.getWordsDescriptors().empty() &&
!tmpTo.getWords().empty() && !tmpTo.getWords().empty() &&
!tmpTo.getWordsKpts().empty() &&
!tmpFrom.getWordsDescriptors().empty() && !tmpFrom.getWordsDescriptors().empty() &&
!tmpFrom.getWords().empty() && !tmpFrom.getWords().empty() &&
!tmpFrom.getWordsKpts().empty() &&
!tmpFrom.getWords3().empty() && !tmpFrom.getWords3().empty() &&
fromS.hasLink(0, Link::kNeighbor)) // If doesn't have neighbors, skip bundle fromS.hasLink(0, Link::kNeighbor)) // If doesn't have neighbors, skip bundle
{ {
@@ -3094,12 +3015,8 @@ Transform Memory::computeTransform(
if(id != fromS.id() && iter->second.type() == Link::kNeighbor) // assemble only neighbors for the local feature map if(id != fromS.id() && iter->second.type() == Link::kNeighbor) // assemble only neighbors for the local feature map
{ {
const Signature * s = this->getSignature(id); const Signature * s = this->getSignature(id);
if(s) if(s && !s->getWords3().empty())
{ {
if(s->getWordsKpts().empty() && s->getWords3().empty() && s->getWordsDescriptors().empty()) {
UDEBUG("Signature %d doesn't have features set. Cannot be added in the local feature map.", s->id());
continue;
}
const std::map<int, int> & wordsTo = uMultimapToMapUnique(s->getWords()); const std::map<int, int> & wordsTo = uMultimapToMapUnique(s->getWords());
for(std::map<int, int>::const_iterator jter=wordsTo.begin(); jter!=wordsTo.end(); ++jter) for(std::map<int, int>::const_iterator jter=wordsTo.begin(); jter!=wordsTo.end(); ++jter)
{ {
@@ -3198,11 +3115,6 @@ Transform Memory::computeTransform(
bundlePoses.insert(std::make_pair(id, iter->second.transform())); bundlePoses.insert(std::make_pair(id, iter->second.transform()));
} }
if(s->getWordsKpts().empty())
{
UDEBUG("Signature %d doesn't have features set. Keypoints won't be added in local bundle adjustment.", s->id());
continue;
}
const std::map<int,int> & words = uMultimapToMapUnique(s->getWords()); const std::map<int,int> & words = uMultimapToMapUnique(s->getWords());
for(std::map<int, int>::const_iterator jter=words.begin(); jter!=words.end(); ++jter) for(std::map<int, int>::const_iterator jter=words.begin(); jter!=words.end(); ++jter)
{ {
@@ -3678,7 +3590,7 @@ void Memory::removeAllVirtualLinks()
void Memory::removeVirtualLinks(int signatureId) void Memory::removeVirtualLinks(int signatureId)
{ {
//UDEBUG(""); UDEBUG("");
Signature * s = this->_getSignature(signatureId); Signature * s = this->_getSignature(signatureId);
if(s) if(s)
{ {
@@ -3716,9 +3628,12 @@ void Memory::dumpMemory(std::string directory) const
} }
void Memory::dumpDictionary(const char * fileNameRef, const char * fileNameDesc) const void Memory::dumpDictionary(const char * fileNameRef, const char * fileNameDesc) const
{
if(_vwd)
{ {
_vwd->exportDictionary(fileNameRef, fileNameDesc); _vwd->exportDictionary(fileNameRef, fileNameDesc);
} }
}
void Memory::dumpSignatures(const char * fileNameSign, bool words3D) const void Memory::dumpSignatures(const char * fileNameSign, bool words3D) const
{ {
@@ -3838,7 +3753,10 @@ unsigned long Memory::getMemoryUsed() const
{ {
memoryUsage += iter->second->getMemoryUsed(true); memoryUsage += iter->second->getMemoryUsed(true);
} }
if(_vwd)
{
memoryUsage += _vwd->getMemoryUsed(); memoryUsage += _vwd->getMemoryUsed();
}
memoryUsage += _stMem.size() * (sizeof(int)+sizeof(std::set<int>::iterator)) + sizeof(std::set<int>); memoryUsage += _stMem.size() * (sizeof(int)+sizeof(std::set<int>::iterator)) + sizeof(std::set<int>);
memoryUsage += _workingMem.size() * (sizeof(int)+sizeof(double)+sizeof(std::map<int, double>::iterator)) + sizeof(std::map<int, double>); memoryUsage += _workingMem.size() * (sizeof(int)+sizeof(double)+sizeof(std::map<int, double>::iterator)) + sizeof(std::map<int, double>);
memoryUsage += _groundTruths.size() * (sizeof(int)+sizeof(Transform)+12*sizeof(float) + sizeof(std::map<int, Transform>::iterator)) + sizeof(std::map<int, Transform>); memoryUsage += _groundTruths.size() * (sizeof(int)+sizeof(Transform)+12*sizeof(float) + sizeof(std::map<int, Transform>::iterator)) + sizeof(std::map<int, Transform>);
@@ -4303,11 +4221,6 @@ void Memory::getNodeWordsAndGlobalDescriptors(int nodeId,
} }
} }
} }
if(!words.empty() && wordsKpts.empty() && _dbDriver)
{
std::multimap<int, int> tmpWords;
_dbDriver->getLocalFeatures(nodeId, tmpWords, wordsKpts, words3, wordsDescriptors);
}
} }
void Memory::getNodeCalibration(int nodeId, void Memory::getNodeCalibration(int nodeId,
@@ -4852,11 +4765,6 @@ Signature * Memory::createSignature(const SensorData & inputData, const Transfor
{ {
meanWordsPerLocation = _vwd->getTotalActiveReferences() / (treeSize-1); // ignore virtual signature meanWordsPerLocation = _vwd->getTotalActiveReferences() / (treeSize-1); // ignore virtual signature
} }
else if(_useOdometryFeatures) {
// To not detect first image as bad signature if odometry
// is using less features than feature2D->getMaxFeatures()
meanWordsPerLocation = 0;
}
if(_parallelized && !isIntermediateNode) if(_parallelized && !isIntermediateNode)
{ {
@@ -4960,12 +4868,10 @@ Signature * Memory::createSignature(const SensorData & inputData, const Transfor
SensorData decimatedData; SensorData decimatedData;
UDEBUG("Received kpts=%d kpts3D=%d, descriptors=%d _useOdometryFeatures=%s", UDEBUG("Received kpts=%d kpts3D=%d, descriptors=%d _useOdometryFeatures=%s",
(int)data.keypoints().size(), (int)data.keypoints3D().size(), data.descriptors().rows, _useOdometryFeatures?"true":"false"); (int)data.keypoints().size(), (int)data.keypoints3D().size(), data.descriptors().rows, _useOdometryFeatures?"true":"false");
// TODO: do we still need the third and fouth comparisons?
// TODO: there is significant repetitive code between the if and the else, could we combine them?!
if(!_useOdometryFeatures || if(!_useOdometryFeatures ||
(!_receivingOdometryFeatures && data.keypoints().empty()) || data.keypoints().empty() ||
(int)data.keypoints().size() != data.descriptors().rows || (int)data.keypoints().size() != data.descriptors().rows ||
(!_receivingOdometryFeatures && _feature2D->getType() == Feature2D::kFeatureOrbOctree && data.descriptors().empty())) (_feature2D->getType() == Feature2D::kFeatureOrbOctree && data.descriptors().empty()))
{ {
if(_feature2D->getMaxFeatures() >= 0 && !data.imageRaw().empty() && !isIntermediateNode) if(_feature2D->getMaxFeatures() >= 0 && !data.imageRaw().empty() && !isIntermediateNode)
{ {
@@ -5302,7 +5208,6 @@ Signature * Memory::createSignature(const SensorData & inputData, const Transfor
} }
else if(_feature2D->getMaxFeatures() >= 0 && !isIntermediateNode) else if(_feature2D->getMaxFeatures() >= 0 && !isIntermediateNode)
{ {
_receivingOdometryFeatures = true;
UINFO("Use odometry features: kpts=%d 3d=%d desc=%d (dim=%d, type=%d)", UINFO("Use odometry features: kpts=%d 3d=%d desc=%d (dim=%d, type=%d)",
(int)data.keypoints().size(), (int)data.keypoints().size(),
(int)data.keypoints3D().size(), (int)data.keypoints3D().size(),
@@ -6425,7 +6330,7 @@ Signature * Memory::createSignature(const SensorData & inputData, const Transfor
void Memory::disableWordsRef(int signatureId) void Memory::disableWordsRef(int signatureId)
{ {
//UDEBUG("id=%d", signatureId); UDEBUG("id=%d", signatureId);
Signature * ss = this->_getSignature(signatureId); Signature * ss = this->_getSignature(signatureId);
if(ss && ss->isEnabled()) if(ss && ss->isEnabled())
@@ -6441,7 +6346,7 @@ void Memory::disableWordsRef(int signatureId)
count -= _vwd->getTotalActiveReferences(); count -= _vwd->getTotalActiveReferences();
ss->setEnabled(false); ss->setEnabled(false);
//UDEBUG("%d words total ref removed from signature %d... (total active ref = %d)", count, ss->id(), _vwd->getTotalActiveReferences()); UDEBUG("%d words total ref removed from signature %d... (total active ref = %d)", count, ss->id(), _vwd->getTotalActiveReferences());
} }
} }
@@ -6504,7 +6409,7 @@ void Memory::enableWordsRef(const std::list<int> & signatureIds)
UDEBUG("oldWordIds.size()=%d, getOldIds time=%fs", oldWordIds.size(), timer.ticks()); UDEBUG("oldWordIds.size()=%d, getOldIds time=%fs", oldWordIds.size(), timer.ticks());
// the words were deleted, so try to match it with an active word // the words were deleted, so try to math it with an active word
std::list<VisualWord *> vws; std::list<VisualWord *> vws;
if(oldWordIds.size() && _dbDriver) if(oldWordIds.size() && _dbDriver)
{ {
+6 -25
View File
@@ -36,10 +36,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "rtabmap/core/odometry/OdometryLOAM.h" #include "rtabmap/core/odometry/OdometryLOAM.h"
#include "rtabmap/core/odometry/OdometryFLOAM.h" #include "rtabmap/core/odometry/OdometryFLOAM.h"
#include "rtabmap/core/odometry/OdometryMSCKF.h" #include "rtabmap/core/odometry/OdometryMSCKF.h"
#include "rtabmap/core/odometry/OdometryVINSFusion.h" #include "rtabmap/core/odometry/OdometryVINS.h"
#include "rtabmap/core/odometry/OdometryOpenVINS.h" #include "rtabmap/core/odometry/OdometryOpenVINS.h"
#include "rtabmap/core/odometry/OdometryOpen3D.h" #include "rtabmap/core/odometry/OdometryOpen3D.h"
#include "rtabmap/core/odometry/OdometryCuVSLAM.h"
#include "rtabmap/core/OdometryInfo.h" #include "rtabmap/core/OdometryInfo.h"
#include "rtabmap/core/util3d.h" #include "rtabmap/core/util3d.h"
#include "rtabmap/core/util3d_mapping.h" #include "rtabmap/core/util3d_mapping.h"
@@ -104,8 +103,8 @@ Odometry * Odometry::create(Odometry::Type & type, const ParametersMap & paramet
case Odometry::kTypeMSCKF: case Odometry::kTypeMSCKF:
odometry = new OdometryMSCKF(parameters); odometry = new OdometryMSCKF(parameters);
break; break;
case Odometry::kTypeVINSFusion: case Odometry::kTypeVINS:
odometry = new OdometryVINSFusion(parameters); odometry = new OdometryVINS(parameters);
break; break;
case Odometry::kTypeOpenVINS: case Odometry::kTypeOpenVINS:
odometry = new OdometryOpenVINS(parameters); odometry = new OdometryOpenVINS(parameters);
@@ -113,9 +112,6 @@ Odometry * Odometry::create(Odometry::Type & type, const ParametersMap & paramet
case Odometry::kTypeOpen3D: case Odometry::kTypeOpen3D:
odometry = new OdometryOpen3D(parameters); odometry = new OdometryOpen3D(parameters);
break; break;
case Odometry::kTypeCuVSLAM:
odometry = new OdometryCuVSLAM(parameters);
break;
default: default:
UERROR("Unknown odometry type %d, using F2M instead...", (int)type); UERROR("Unknown odometry type %d, using F2M instead...", (int)type);
odometry = new OdometryF2M(parameters); odometry = new OdometryF2M(parameters);
@@ -326,9 +322,7 @@ Transform Odometry::process(SensorData & data, const Transform & guessIn, Odomet
Transform previous = this->getPose(); Transform previous = this->getPose();
Transform newFramePose = Transform(previous.x(), previous.y(), previous.z(), imuQuat.x(), imuQuat.y(), imuQuat.z(), imuQuat.w()); Transform newFramePose = Transform(previous.x(), previous.y(), previous.z(), imuQuat.x(), imuQuat.y(), imuQuat.z(), imuQuat.w());
UWARN("Updated initial pose from %s to %s with IMU orientation", previous.prettyPrint().c_str(), newFramePose.prettyPrint().c_str()); UWARN("Updated initial pose from %s to %s with IMU orientation", previous.prettyPrint().c_str(), newFramePose.prettyPrint().c_str());
std::map<double, rtabmap::Transform> imus = imus_;
this->reset(newFramePose); this->reset(newFramePose);
imus_ = imus;
} }
imus_.insert(std::make_pair(data.stamp(), imuT)); imus_.insert(std::make_pair(data.stamp(), imuT));
@@ -629,7 +623,6 @@ Transform Odometry::process(SensorData & data, const Transform & guessIn, Odomet
if(!guessIn.isNull()) if(!guessIn.isNull())
{ {
guess = guessIn; guess = guessIn;
UDEBUG("Using provided guess %s", guessIn.prettyPrint().c_str());
} }
else if(!imus_.empty()) else if(!imus_.empty())
{ {
@@ -646,16 +639,12 @@ Transform Odometry::process(SensorData & data, const Transform & guessIn, Odomet
{ {
guess = guess.to3DoF(); guess = guess.to3DoF();
} }
UDEBUG("Adjusting guess from motion with IMU %s", guess.prettyPrint().c_str());
} }
else if(!imuLastTransform_.isNull()) else if(!imuLastTransform_.isNull())
{ {
UWARN("Could not find imu transform at %f", data.stamp()); UWARN("Could not find imu transform at %f", data.stamp());
} }
} }
else if(!guess.isNull()) {
UDEBUG("Using guess from motion %s", guess.prettyPrint().c_str());
}
UTimer time; UTimer time;
@@ -1020,28 +1009,21 @@ Transform Odometry::process(SensorData & data, const Transform & guessIn, Odomet
--_resetCurrentCount; --_resetCurrentCount;
if(_resetCurrentCount == 0) if(_resetCurrentCount == 0)
{ {
if(!guess.isNull() && !guessIn.isNull()) { UWARN("Odometry automatically reset to latest pose!");
UWARN("Odometry automatically reset to latest pose (%s) + guess (%s)!", _pose.prettyPrint().c_str(), guess.prettyPrint().c_str());
this->reset(_pose * guess);
}
else {
UWARN("Odometry automatically reset to latest pose (%s)!", _pose.prettyPrint().c_str());
this->reset(_pose); this->reset(_pose);
}
_resetCurrentCount = _resetCountdown; _resetCurrentCount = _resetCountdown;
if(info) if(info)
{ {
*info = OdometryInfo(); *info = OdometryInfo();
} }
this->computeTransform(data, Transform(), info); return this->computeTransform(data, Transform(), info);
return _pose; }
} }
previousVelocities_.clear(); previousVelocities_.clear();
velocityGuess_.setNull(); velocityGuess_.setNull();
previousStamp_ = 0; previousStamp_ = 0;
}
return Transform(); return Transform();
} }
@@ -1071,7 +1053,6 @@ void Odometry::initKalmanFilter(const Transform & initialPose, float vx, float v
0, 0, 0, 0, 0, 0.17 } }; 0, 0, 0, 0, 0, 0.17 } };
static const boost::array<double, 36> STANDARD_TWIST_COVARIANCE = static const boost::array<double, 36> STANDARD_TWIST_COVARIANCE =
{ { 0.05, 0, 0, 0, 0, 0, { { 0.05, 0, 0, 0, 0, 0,
}
0, 0.05, 0, 0, 0, 0, 0, 0.05, 0, 0, 0, 0,
0, 0, 0.05, 0, 0, 0, 0, 0, 0.05, 0, 0, 0,
0, 0, 0, 0.09, 0, 0, 0, 0, 0, 0.09, 0, 0,
+4 -4
View File
@@ -126,10 +126,10 @@ std::map<std::string, float> OdometryInfo::statistics(const Transform & pose)
stats.insert(std::make_pair("Odometry/ICPStructuralComplexity/", reg.icpStructuralComplexity)); stats.insert(std::make_pair("Odometry/ICPStructuralComplexity/", reg.icpStructuralComplexity));
stats.insert(std::make_pair("Odometry/ICPStructuralDistribution/", reg.icpStructuralDistribution)); stats.insert(std::make_pair("Odometry/ICPStructuralDistribution/", reg.icpStructuralDistribution));
stats.insert(std::make_pair("Odometry/ICPCorrespondences/", reg.icpCorrespondences)); stats.insert(std::make_pair("Odometry/ICPCorrespondences/", reg.icpCorrespondences));
stats.insert(std::make_pair("Odometry/StdDevLin/", reg.covariance.empty()?0:sqrt((float)reg.covariance.at<double>(0,0)))); stats.insert(std::make_pair("Odometry/StdDevLin/", sqrt((float)reg.covariance.at<double>(0,0))));
stats.insert(std::make_pair("Odometry/StdDevAng/", reg.covariance.empty()?0:sqrt((float)reg.covariance.at<double>(5,5)))); stats.insert(std::make_pair("Odometry/StdDevAng/", sqrt((float)reg.covariance.at<double>(5,5))));
stats.insert(std::make_pair("Odometry/VarianceLin/", reg.covariance.empty()?0:(float)reg.covariance.at<double>(0,0))); stats.insert(std::make_pair("Odometry/VarianceLin/", (float)reg.covariance.at<double>(0,0)));
stats.insert(std::make_pair("Odometry/VarianceAng/", reg.covariance.empty()?0:(float)reg.covariance.at<double>(5,5))); stats.insert(std::make_pair("Odometry/VarianceAng/", (float)reg.covariance.at<double>(5,5)));
stats.insert(std::make_pair("Odometry/TimeEstimation/ms", timeEstimation*1000.0f)); stats.insert(std::make_pair("Odometry/TimeEstimation/ms", timeEstimation*1000.0f));
stats.insert(std::make_pair("Odometry/TimeFiltering/ms", timeParticleFiltering*1000.0f)); stats.insert(std::make_pair("Odometry/TimeFiltering/ms", timeParticleFiltering*1000.0f));
stats.insert(std::make_pair("Odometry/LocalMapSize/", localMapSize)); stats.insert(std::make_pair("Odometry/LocalMapSize/", localMapSize));
+30 -67
View File
@@ -32,7 +32,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "rtabmap/core/OdometryInfo.h" #include "rtabmap/core/OdometryInfo.h"
#include "rtabmap/core/OdometryEvent.h" #include "rtabmap/core/OdometryEvent.h"
#include "rtabmap/utilite/ULogger.h" #include "rtabmap/utilite/ULogger.h"
#include "rtabmap/utilite/UTimer.h"
namespace rtabmap { namespace rtabmap {
@@ -41,8 +40,8 @@ OdometryThread::OdometryThread(Odometry * odometry, unsigned int dataBufferMaxSi
_dataBufferMaxSize(dataBufferMaxSize), _dataBufferMaxSize(dataBufferMaxSize),
_resetOdometry(false), _resetOdometry(false),
_resetPose(Transform::getIdentity()), _resetPose(Transform::getIdentity()),
_oldestAsyncImuStamp(0.0), _lastImuStamp(0.0),
_newestAsyncImuStamp(0.0) _imuEstimatedDelay(0.0)
{ {
UASSERT(_odometry != 0); UASSERT(_odometry != 0);
} }
@@ -64,7 +63,7 @@ bool OdometryThread::handleEvent(UEvent * event)
SensorEvent * sensorEvent = (SensorEvent*)event; SensorEvent * sensorEvent = (SensorEvent*)event;
if(sensorEvent->getCode() == SensorEvent::kCodeData) if(sensorEvent->getCode() == SensorEvent::kCodeData)
{ {
this->addData(*sensorEvent); this->addData(sensorEvent->data());
} }
} }
else if(event->getClassName().compare("IMUEvent") == 0) else if(event->getClassName().compare("IMUEvent") == 0)
@@ -111,53 +110,32 @@ void OdometryThread::mainLoop()
UScopeMutex lock(_dataMutex); UScopeMutex lock(_dataMutex);
_dataBuffer.clear(); _dataBuffer.clear();
_imuBuffer.clear(); _imuBuffer.clear();
_oldestAsyncImuStamp = 0.0; _lastImuStamp = 0.0f;
_newestAsyncImuStamp = 0.0;
_previousGuessPose.setNull();
} }
SensorEvent event; SensorData data;
if(getData(event)) if(getData(data))
{ {
OdometryInfo info; OdometryInfo info;
UDEBUG("Processing data..."); UDEBUG("Processing data...");
Transform guess; Transform pose = _odometry->process(data, &info);
UDEBUG("event.info().odomPose=%s", event.info().odomPose.prettyPrint().c_str());
if(!_previousGuessPose.isNull() && !event.info().odomPose.isNull()) {
guess = _previousGuessPose.inverse() * event.info().odomPose;
}
SensorData data = event.data();
Transform pose = _odometry->process(data, guess , &info);
if(!data.imageRaw().empty() || !data.laserScanRaw().empty() || (pose.isNull() && data.imu().empty())) if(!data.imageRaw().empty() || !data.laserScanRaw().empty() || (pose.isNull() && data.imu().empty()))
{ {
UDEBUG("Odom pose = %s", pose.prettyPrint().c_str()); UDEBUG("Odom pose = %s", pose.prettyPrint().c_str());
if(!pose.isNull()) {
_previousGuessPose = event.info().odomPose;
UASSERT(event.info().odomPose.isNull() || !info.reg.covariance.empty());
if(!event.info().odomPose.isNull() && info.reg.covariance.at<double>(0,0) >= 9999 &&
(pose.x() != 0.0f || pose.y() != 0.0f || pose.z() != 0.0f)) // not the first frame
{
// In case of external guess and auto reset, keep reporting lost till we
// process the second frame with valid covariance. This way it
// won't trigger a new map.
pose = Transform();
}
}
// a null pose notify that odometry could not be computed // a null pose notify that odometry could not be computed
this->post(new OdometryEvent(data, pose, info)); this->post(new OdometryEvent(data, pose, info));
} }
} }
} }
void OdometryThread::addData(const SensorEvent & event) void OdometryThread::addData(const SensorData & data)
{ {
if(event.data().imu().empty()) if(data.imu().empty())
{ {
if(dynamic_cast<OdometryMono*>(_odometry) == 0) if(dynamic_cast<OdometryMono*>(_odometry) == 0)
{ {
if((event.data().imageRaw().empty() || event.data().depthOrRightRaw().empty() || (event.data().cameraModels().empty() && event.data().stereoCameraModels().empty())) && if((data.imageRaw().empty() || data.depthOrRightRaw().empty() || (data.cameraModels().empty() && data.stereoCameraModels().empty())) &&
event.data().laserScanRaw().empty()) data.laserScanRaw().empty())
{ {
ULOGGER_ERROR("Missing some information (images/scans empty or missing calibration)!?"); ULOGGER_ERROR("Missing some information (images/scans empty or missing calibration)!?");
return; return;
@@ -166,7 +144,7 @@ void OdometryThread::addData(const SensorEvent & event)
else else
{ {
// Mono can accept RGB only // Mono can accept RGB only
if(event.data().imageRaw().empty() || (event.data().cameraModels().empty() && event.data().stereoCameraModels().empty())) if(data.imageRaw().empty() || (data.cameraModels().empty() && data.stereoCameraModels().empty()))
{ {
ULOGGER_ERROR("Missing some information (image empty or missing calibration)!?"); ULOGGER_ERROR("Missing some information (image empty or missing calibration)!?");
return; return;
@@ -177,32 +155,13 @@ void OdometryThread::addData(const SensorEvent & event)
bool notify = true; bool notify = true;
_dataMutex.lock(); _dataMutex.lock();
{ {
if( !event.data().imageRaw().empty() || if( !data.imageRaw().empty() ||
!event.data().imageCompressed().empty() || !data.imageCompressed().empty() ||
!event.data().laserScanRaw().isEmpty() || !data.laserScanRaw().isEmpty() ||
!event.data().laserScanCompressed().empty() || !data.laserScanCompressed().empty() ||
event.data().imu().empty()) data.imu().empty())
{ {
if(_oldestAsyncImuStamp > 0.0 && event.data().stamp() < _oldestAsyncImuStamp) { _dataBuffer.push_back(data);
UWARN("Received image/lidar with stamp (%f) older than oldest received imu "
"(%f), skipping that frame (imu buffer size=%ld). "
"When using async IMU, make sure IMU is published faster "
"than camera/lidar (assuming IMU latency is very small compared to camera/lidar)."
"Current camera/lidar delay is %fs.",
event.data().stamp(), _oldestAsyncImuStamp, _imuBuffer.size(), UTimer::now() - event.data().stamp());
notify = false;
}
else if(_newestAsyncImuStamp > 0.0 && event.data().stamp()>=_newestAsyncImuStamp) {
UWARN("Received image/lidar with stamp (%f) newer than latest received imu "
"(%f), skipping that frame (imu buffer size=%ld). "
"When using async IMU, make sure IMU is published faster "
"than camera/lidar (assuming IMU latency is very small compared to camera/lidar). "
"Current camera/lidar delay is %fs.",
event.data().stamp(), _newestAsyncImuStamp, _imuBuffer.size(), UTimer::now() - event.data().stamp());
notify = false;
}
else {
_dataBuffer.push_back(event);
while(_dataBufferMaxSize > 0 && _dataBuffer.size() > _dataBufferMaxSize) while(_dataBufferMaxSize > 0 && _dataBuffer.size() > _dataBufferMaxSize)
{ {
UDEBUG("Data buffer is full, the oldest data is removed to add the new one."); UDEBUG("Data buffer is full, the oldest data is removed to add the new one.");
@@ -210,14 +169,14 @@ void OdometryThread::addData(const SensorEvent & event)
notify = false; notify = false;
} }
} }
}
else else
{ {
_imuBuffer.push_back(event.data()); _imuBuffer.push_back(data);
if(_oldestAsyncImuStamp == 0) { if(_lastImuStamp != 0.0 && data.stamp() > _lastImuStamp)
_oldestAsyncImuStamp = event.data().stamp(); {
_imuEstimatedDelay = data.stamp() - _lastImuStamp;
} }
_newestAsyncImuStamp = event.data().stamp(); _lastImuStamp = data.stamp();
} }
} }
_dataMutex.unlock(); _dataMutex.unlock();
@@ -228,13 +187,15 @@ void OdometryThread::addData(const SensorEvent & event)
} }
} }
bool OdometryThread::getData(SensorEvent & event) bool OdometryThread::getData(SensorData & data)
{ {
bool dataFilled = false; bool dataFilled = false;
_dataAdded.acquire(); _dataAdded.acquire();
_dataMutex.lock(); _dataMutex.lock();
{ {
if(!_dataBuffer.empty()) if(!_dataBuffer.empty())
{
if(!_imuBuffer.empty())
{ {
// Send IMU up to stamp greater than image (OpenVINS needs this). // Send IMU up to stamp greater than image (OpenVINS needs this).
while(!_imuBuffer.empty()) while(!_imuBuffer.empty())
@@ -242,12 +203,14 @@ bool OdometryThread::getData(SensorEvent & event)
_odometry->process(_imuBuffer.front()); _odometry->process(_imuBuffer.front());
double stamp = _imuBuffer.front().stamp(); double stamp = _imuBuffer.front().stamp();
_imuBuffer.pop_front(); _imuBuffer.pop_front();
if(stamp > _dataBuffer.front().data().stamp()) { if(stamp > _dataBuffer.front().stamp())
{
break; break;
} }
} }
}
event = _dataBuffer.front(); data = _dataBuffer.front();
_dataBuffer.pop_front(); _dataBuffer.pop_front();
dataFilled = true; dataFilled = true;
} }
+2 -2
View File
@@ -608,8 +608,8 @@ void Optimizer::computeBACorrespondences(
} }
} }
if(sFrom.getWordsKpts().size() && if(sFrom.getWords().size() &&
sTo.getWordsKpts().size() && sTo.getWords().size() &&
sFrom.getWords3().size()) sFrom.getWords3().size())
{ {
if(!rematchFeatures) if(!rematchFeatures)
+1 -4
View File
@@ -236,9 +236,6 @@ const std::map<std::string, std::pair<bool, std::string> > & Parameters::getRemo
{ {
// removed parameters // removed parameters
// 0.23.1
removedParameters_.insert(std::make_pair("OdomVINS/ConfigPath", std::make_pair(true, Parameters::kOdomVINSFusionConfigPath())));
// 0.21.13 // 0.21.13
removedParameters_.insert(std::make_pair("Vis/ForwardEstOnly", std::make_pair(false, ""))); removedParameters_.insert(std::make_pair("Vis/ForwardEstOnly", std::make_pair(false, "")));
@@ -939,7 +936,7 @@ ParametersMap Parameters::parseArguments(int argc, char * argv[], bool onlyParam
std::cout << str << std::setw(spacing - str.size()) << "false" << std::endl; std::cout << str << std::setw(spacing - str.size()) << "false" << std::endl;
#endif #endif
str = "With VINS-Fusion:"; str = "With VINS-Fusion:";
#ifdef RTABMAP_VINS_FUSION #ifdef RTABMAP_VINS
std::cout << str << std::setw(spacing - str.size()) << "true" << std::endl; std::cout << str << std::setw(spacing - str.size()) << "true" << std::endl;
#else #else
std::cout << str << std::setw(spacing - str.size()) << "false" << std::endl; std::cout << str << std::setw(spacing - str.size()) << "false" << std::endl;
+2 -8
View File
@@ -375,9 +375,6 @@ Transform RegistrationVis::computeTransformationImpl(
{ {
UDEBUG(""); UDEBUG("");
// just some checks to make sure that input data are ok // just some checks to make sure that input data are ok
UASSERT(fromSignature.getWords().empty() ||
fromSignature.getWordsKpts().empty() ||
(fromSignature.getWords().size() == fromSignature.getWordsKpts().size()));
UASSERT(fromSignature.getWords().empty() || UASSERT(fromSignature.getWords().empty() ||
fromSignature.getWords3().empty() || fromSignature.getWords3().empty() ||
(fromSignature.getWords().size() == fromSignature.getWords3().size())); (fromSignature.getWords().size() == fromSignature.getWords3().size()));
@@ -385,11 +382,8 @@ Transform RegistrationVis::computeTransformationImpl(
(int)fromSignature.getWords().size() == fromSignature.getWordsDescriptors().rows || (int)fromSignature.getWords().size() == fromSignature.getWordsDescriptors().rows ||
fromSignature.sensorData().descriptors().empty() || fromSignature.sensorData().descriptors().empty() ||
fromSignature.getWordsDescriptors().empty() == 0); fromSignature.getWordsDescriptors().empty() == 0);
UASSERT(toSignature.getWords().empty() || UASSERT((toSignature.getWords().empty() && toSignature.getWords3().empty())||
toSignature.getWordsKpts().empty() || (toSignature.getWords().size() && toSignature.getWords3().empty())||
(toSignature.getWords().size() == toSignature.getWordsKpts().size()));
UASSERT(toSignature.getWords().empty() ||
toSignature.getWords3().empty() ||
(toSignature.getWords().size() == toSignature.getWords3().size())); (toSignature.getWords().size() == toSignature.getWords3().size()));
UASSERT((int)toSignature.sensorData().keypoints().size() == toSignature.sensorData().descriptors().rows || UASSERT((int)toSignature.sensorData().keypoints().size() == toSignature.sensorData().descriptors().rows ||
(int)toSignature.getWords().size() == toSignature.getWordsDescriptors().rows || (int)toSignature.getWords().size() == toSignature.getWordsDescriptors().rows ||
+80 -15
View File
@@ -423,6 +423,32 @@ void Rtabmap::init(const ParametersMap & parameters, const std::string & databas
if(_createGlobalScanMap) if(_createGlobalScanMap)
createGlobalScanMap(); createGlobalScanMap();
if(true)
{
std::string externalLocalizationDataPath = _wDir +"/rtabmap_log.db"; // use parameter to know prefix, then generate timestamp
_externalLocalizationDbDriver = DBDriver::create(allParameters);
if(!_externalLocalizationDbDriver->openConnection(externalLocalizationDataPath)) {
UERROR("Failed to create database \"%s\" to save external localization data!");
}
else
{
float x, y, resolution;
cv::Mat map = _memory->load2DMap(x, y, resolution);
if(!map.empty()) {
_externalLocalizationDbDriver->save2DMap(map, x, y, resolution);
}
if(!_optimizedPoses.empty()) {
_externalLocalizationDbDriver->saveOptimizedPoses(_optimizedPoses, _lastLocalizationPose);
}
if(!allParameters.empty())
{
ParametersMap params = allParameters;
params.erase(Parameters::kRtabmapWorkingDirectory()); // don't save working directory as it is machine dependent
_externalLocalizationDbDriver->addInfoAfterRun(0, 0, 0, 0, 0, params);
}
}
}
} }
else else
{ {
@@ -519,6 +545,9 @@ void Rtabmap::close(bool databaseSaved, const std::string & ouputDatabasePath)
_optimizedPoses.erase(iter->first); _optimizedPoses.erase(iter->first);
} }
} }
if(!_memory->isIncremental() && _externalLocalizationDbDriver) {
_externalLocalizationDbDriver->saveOptimizedPoses(_optimizedPoses, _lastLocalizationPose);
}
_memory->saveOptimizedPoses(_optimizedPoses, _lastLocalizationPose); _memory->saveOptimizedPoses(_optimizedPoses, _lastLocalizationPose);
} }
_memory->close(databaseSaved, true, ouputDatabasePath); _memory->close(databaseSaved, true, ouputDatabasePath);
@@ -528,6 +557,12 @@ void Rtabmap::close(bool databaseSaved, const std::string & ouputDatabasePath)
_optimizedPoses.clear(); _optimizedPoses.clear();
_lastLocalizationPose.setNull(); _lastLocalizationPose.setNull();
if(_externalLocalizationDbDriver) {
_externalLocalizationDbDriver->closeConnection();
delete _externalLocalizationDbDriver;
_externalLocalizationDbDriver = 0;
}
if(_bayesFilter) if(_bayesFilter)
{ {
delete _bayesFilter; delete _bayesFilter;
@@ -1502,8 +1537,8 @@ bool Rtabmap::process(
float angleToClosestNodeInTheGraph = 0; float angleToClosestNodeInTheGraph = 0;
if(_rgbdSlamMode) if(_rgbdSlamMode)
{ {
double linVar = odomCovariance.empty()?0.0f:uMax3(odomCovariance.at<double>(0,0), odomCovariance.at<double>(1,1)>=9999?0:odomCovariance.at<double>(1,1), odomCovariance.at<double>(2,2)>=9999?0:odomCovariance.at<double>(2,2)); double linVar = odomCovariance.empty()?1.0f:uMax3(odomCovariance.at<double>(0,0), odomCovariance.at<double>(1,1)>=9999?0:odomCovariance.at<double>(1,1), odomCovariance.at<double>(2,2)>=9999?0:odomCovariance.at<double>(2,2));
double angVar = odomCovariance.empty()?0.0f:uMax3(odomCovariance.at<double>(3,3)>=9999?0:odomCovariance.at<double>(3,3), odomCovariance.at<double>(4,4)>=9999?0:odomCovariance.at<double>(4,4), odomCovariance.at<double>(5,5)); double angVar = odomCovariance.empty()?1.0f:uMax3(odomCovariance.at<double>(3,3)>=9999?0:odomCovariance.at<double>(3,3), odomCovariance.at<double>(4,4)>=9999?0:odomCovariance.at<double>(4,4), odomCovariance.at<double>(5,5));
statistics_.addStatistic(Statistics::kMemoryOdometry_variance_lin(), (float)linVar); statistics_.addStatistic(Statistics::kMemoryOdometry_variance_lin(), (float)linVar);
statistics_.addStatistic(Statistics::kMemoryOdometry_variance_ang(), (float)angVar); statistics_.addStatistic(Statistics::kMemoryOdometry_variance_ang(), (float)angVar);
@@ -1607,7 +1642,6 @@ bool Rtabmap::process(
Transform t = _memory->computeTransform(oldId, signature->id(), guess, &info); Transform t = _memory->computeTransform(oldId, signature->id(), guess, &info);
if(!t.isNull()) if(!t.isNull())
{ {
UASSERT(!info.covariance.empty() && info.covariance.at<double>(0,0) > 0.0 && info.covariance.at<double>(5,5) > 0.0);
UINFO("Odometry refining: update neighbor link (%d->%d, variance:lin=%f, ang=%f) from %s to %s", UINFO("Odometry refining: update neighbor link (%d->%d, variance:lin=%f, ang=%f) from %s to %s",
oldId, oldId,
signature->id(), signature->id(),
@@ -1615,6 +1649,7 @@ bool Rtabmap::process(
info.covariance.at<double>(5,5), info.covariance.at<double>(5,5),
guess.prettyPrint().c_str(), guess.prettyPrint().c_str(),
t.prettyPrint().c_str()); t.prettyPrint().c_str());
UASSERT(info.covariance.at<double>(0,0) > 0.0 && info.covariance.at<double>(5,5) > 0.0);
_memory->updateLink(Link(oldId, signature->id(), signature->getLinks().begin()->second.type(), t, info.covariance.inv())); _memory->updateLink(Link(oldId, signature->id(), signature->getLinks().begin()->second.type(), t, info.covariance.inv()));
if(_optimizeFromGraphEnd) if(_optimizeFromGraphEnd)
@@ -1894,7 +1929,7 @@ bool Rtabmap::process(
*iter, *iter,
transform.prettyPrint().c_str()); transform.prettyPrint().c_str());
// Add a loop constraint // Add a loop constraint
UASSERT(!info.covariance.empty() && info.covariance.at<double>(0,0) > 0.0 && info.covariance.at<double>(5,5) > 0.0); UASSERT(info.covariance.at<double>(0,0) > 0.0 && info.covariance.at<double>(5,5) > 0.0);
if(_memory->addLink(Link(signature->id(), *iter, Link::kLocalTimeClosure, transform, getInformation(info.covariance)))) if(_memory->addLink(Link(signature->id(), *iter, Link::kLocalTimeClosure, transform, getInformation(info.covariance))))
{ {
++proximityDetectionsInTimeFound; ++proximityDetectionsInTimeFound;
@@ -2395,6 +2430,8 @@ bool Rtabmap::process(
distanceSoFar += _path[i-1].second.getDistance(_path[i].second); distanceSoFar += _path[i-1].second.getDistance(_path[i].second);
} }
if(distanceSoFar <= _localRadius)
{
if(_memory->getSignature(_path[i].first) != 0) if(_memory->getSignature(_path[i].first) != 0)
{ {
if(immunizedLocations.insert(_path[i].first).second) if(immunizedLocations.insert(_path[i].first).second)
@@ -2409,8 +2446,8 @@ bool Rtabmap::process(
retrievalLocalIds.push_back(_path[i].first); retrievalLocalIds.push_back(_path[i].first);
// retrieved locations are automatically immunized // retrieved locations are automatically immunized
} }
}
if(distanceSoFar > _localRadius) else
{ {
UDEBUG("Stop on node %d (dist=%fm > %fm)", UDEBUG("Stop on node %d (dist=%fm > %fm)",
_path[i].first, distanceSoFar, _localRadius); _path[i].first, distanceSoFar, _localRadius);
@@ -2782,7 +2819,7 @@ bool Rtabmap::process(
signature->id(), signature->id(),
nearestId, nearestId,
transform.prettyPrint().c_str()); transform.prettyPrint().c_str());
UASSERT(!info.covariance.empty() && info.covariance.at<double>(0,0) > 0.0 && info.covariance.at<double>(5,5) > 0.0); UASSERT(info.covariance.at<double>(0,0) > 0.0 && info.covariance.at<double>(5,5) > 0.0);
//for statistics //for statistics
loopClosureVisualInliersMeanDist = info.inliersMeanDistance; loopClosureVisualInliersMeanDist = info.inliersMeanDistance;
@@ -2993,7 +3030,7 @@ bool Rtabmap::process(
} }
// set Identify covariance for laser scan matching only // set Identify covariance for laser scan matching only
UASSERT(!info.covariance.empty() && info.covariance.at<double>(0,0) > 0.0 && info.covariance.at<double>(5,5) > 0.0); UASSERT(info.covariance.at<double>(0,0) > 0.0 && info.covariance.at<double>(5,5) > 0.0);
_memory->addLink(Link(signature->id(), nearestId, Link::kLocalSpaceClosure, transform, getInformation(info.covariance)/_proximityMergedScanCovFactor, scanMatchingIds)); _memory->addLink(Link(signature->id(), nearestId, Link::kLocalSpaceClosure, transform, getInformation(info.covariance)/_proximityMergedScanCovFactor, scanMatchingIds));
loopClosureLinksAdded.push_back(std::make_pair(signature->id(), nearestId)); loopClosureLinksAdded.push_back(std::make_pair(signature->id(), nearestId));
@@ -3081,7 +3118,7 @@ bool Rtabmap::process(
if(!rejectedLoopClosure) if(!rejectedLoopClosure)
{ {
// Make the new one the parent of the old one // Make the new one the parent of the old one
UASSERT(!info.covariance.empty() && info.covariance.at<double>(0,0) > 0.0 && info.covariance.at<double>(5,5) > 0.0); UASSERT(info.covariance.at<double>(0,0) > 0.0 && info.covariance.at<double>(5,5) > 0.0);
loopClosureLinearVariance = uMax3(info.covariance.at<double>(0,0), info.covariance.at<double>(1,1)>=9999?0:info.covariance.at<double>(1,1), info.covariance.at<double>(2,2)>=9999?0:info.covariance.at<double>(2,2)); loopClosureLinearVariance = uMax3(info.covariance.at<double>(0,0), info.covariance.at<double>(1,1)>=9999?0:info.covariance.at<double>(1,1), info.covariance.at<double>(2,2)>=9999?0:info.covariance.at<double>(2,2));
loopClosureAngularVariance = uMax3(info.covariance.at<double>(3,3)>=9999?0:info.covariance.at<double>(3,3), info.covariance.at<double>(4,4)>=9999?0:info.covariance.at<double>(4,4), info.covariance.at<double>(5,5)); loopClosureAngularVariance = uMax3(info.covariance.at<double>(3,3)>=9999?0:info.covariance.at<double>(3,3), info.covariance.at<double>(4,4)>=9999?0:info.covariance.at<double>(4,4), info.covariance.at<double>(5,5));
@@ -3156,8 +3193,18 @@ bool Rtabmap::process(
UASSERT(uContains(_optimizedPoses, signature->id())); UASSERT(uContains(_optimizedPoses, signature->id()));
UASSERT_MSG(uContains(_optimizedPoses, _path[_pathCurrentIndex].first), uFormat("id=%d", _path[_pathCurrentIndex].first).c_str()); UASSERT_MSG(uContains(_optimizedPoses, _path[_pathCurrentIndex].first), uFormat("id=%d", _path[_pathCurrentIndex].first).c_str());
Transform virtualLoop = _optimizedPoses.at(signature->id()).inverse() * _optimizedPoses.at(_path[_pathCurrentIndex].first); Transform virtualLoop = _optimizedPoses.at(signature->id()).inverse() * _optimizedPoses.at(_path[_pathCurrentIndex].first);
if(_localRadius == 0.0f || virtualLoop.getNorm() < _localRadius)
{
_memory->addLink(Link(signature->id(), _path[_pathCurrentIndex].first, Link::kVirtualClosure, virtualLoop, cv::Mat::eye(6,6,CV_64FC1)*0.01)); // set high variance _memory->addLink(Link(signature->id(), _path[_pathCurrentIndex].first, Link::kVirtualClosure, virtualLoop, cv::Mat::eye(6,6,CV_64FC1)*0.01)); // set high variance
} }
else
{
UERROR("Virtual link larger than local radius (%fm > %fm). Aborting the plan!",
virtualLoop.getNorm(), _localRadius);
this->clearPath(-1);
}
}
} }
//============================================================ //============================================================
@@ -4253,10 +4300,20 @@ bool Rtabmap::process(
// Localization mode and saving localization data: save odometry covariance in a prior link // Localization mode and saving localization data: save odometry covariance in a prior link
// so that DBReader can republish the covariance of localization data // so that DBReader can republish the covariance of localization data
if(!_memory->isIncremental() && _memory->isLocalizationDataSaved() && !odomCovariance.empty()) if(!_memory->isIncremental())
{
if(_externalLocalizationDbDriver)
{
Signature * cpy = new Signature();
*cpy = *signature;
_externalLocalizationDbDriver->asyncSave(cpy);
}
if(_memory->isLocalizationDataSaved() && !odomCovariance.empty())
{ {
_memory->addLink(Link(signature->id(), signature->id(), Link::kPosePrior, odomPose, odomCovariance.inv())); _memory->addLink(Link(signature->id(), signature->id(), Link::kPosePrior, odomPose, odomCovariance.inv()));
} }
}
// remove last signature if the memory is not incremental or is a bad signature (if bad signatures are ignored) // remove last signature if the memory is not incremental or is a bad signature (if bad signatures are ignored)
int signatureRemoved = _memory->cleanup(); int signatureRemoved = _memory->cleanup();
@@ -4678,6 +4735,11 @@ bool Rtabmap::process(
_memory->saveStatistics(statistics_, _saveWMState); _memory->saveStatistics(statistics_, _saveWMState);
} }
if(_externalLocalizationDbDriver) // external db log
{
_externalLocalizationDbDriver->addStatistics(statistics_, _saveWMState);
}
//Start trashing //Start trashing
UDEBUG("Empty trash..."); UDEBUG("Empty trash...");
_memory->emptyTrash(); _memory->emptyTrash();
@@ -6915,7 +6977,8 @@ void Rtabmap::updateGoalIndex()
{ {
distanceSoFar += _path[i-1].second.getDistance(_path[i].second); distanceSoFar += _path[i-1].second.getDistance(_path[i].second);
} }
if(distanceSoFar <= _localRadius)
{
if(_path[i].first != _path[i-1].first) if(_path[i].first != _path[i-1].first)
{ {
const Signature * s = _memory->getSignature(_path[i].first); const Signature * s = _memory->getSignature(_path[i].first);
@@ -6929,10 +6992,9 @@ void Rtabmap::updateGoalIndex()
} }
} }
} }
}
if(distanceSoFar > _localRadius) else
{ {
UDEBUG("Farthest goal=%d : %f m", _path[i].first, distanceSoFar);
break; break;
} }
} }
@@ -6991,9 +7053,12 @@ void Rtabmap::updateGoalIndex()
if((goalIndex == _pathCurrentIndex && i == _path.size()-1) || if((goalIndex == _pathCurrentIndex && i == _path.size()-1) ||
_pathUnreachableNodes.find(i) == _pathUnreachableNodes.end()) _pathUnreachableNodes.find(i) == _pathUnreachableNodes.end())
{
if(distanceFromCurrentNode <= _localRadius)
{ {
goalIndex = i; goalIndex = i;
if(distanceFromCurrentNode > _localRadius) }
else
{ {
break; break;
} }
-1
View File
@@ -506,7 +506,6 @@ void RtabmapThread::addData(const OdometryEvent & odomEvent)
ignoreFrame = true; ignoreFrame = true;
} }
} }
UASSERT(!odomEvent.info().reg.covariance.empty());
if(!lastPose_.isIdentity() && if(!lastPose_.isIdentity() &&
(odomEvent.pose().isIdentity() || (odomEvent.pose().isIdentity() ||
odomEvent.info().reg.covariance.at<double>(0,0)>=9999)) odomEvent.info().reg.covariance.at<double>(0,0)>=9999))
+3 -3
View File
@@ -548,7 +548,7 @@ void SensorData::setOccupancyGrid(
float cellSize, float cellSize,
const cv::Point3f & viewPoint) const cv::Point3f & viewPoint)
{ {
//UDEBUG("ground=%d obstacles=%d empty=%d", ground.cols, obstacles.cols, empty.cols); UDEBUG("ground=%d obstacles=%d empty=%d", ground.cols, obstacles.cols, empty.cols);
if((!ground.empty() && (!_groundCellsCompressed.empty() || !_groundCellsRaw.empty())) || if((!ground.empty() && (!_groundCellsCompressed.empty() || !_groundCellsRaw.empty())) ||
(!obstacles.empty() && (!_obstacleCellsCompressed.empty() || !_obstacleCellsRaw.empty())) || (!obstacles.empty() && (!_obstacleCellsCompressed.empty() || !_obstacleCellsRaw.empty())) ||
(!empty.empty() && (!_emptyCellsCompressed.empty() || !_emptyCellsRaw.empty()))) (!empty.empty() && (!_emptyCellsCompressed.empty() || !_emptyCellsRaw.empty())))
@@ -649,7 +649,7 @@ void SensorData::uncompressData(
cv::Mat * emptyCellsRaw, cv::Mat * emptyCellsRaw,
cv::Mat * depthConfidenceRaw) cv::Mat * depthConfidenceRaw)
{ {
/*UDEBUG("%d data(%d,%d,%d,%d,%d,%d,%d,%d)", UDEBUG("%d data(%d,%d,%d,%d,%d,%d,%d,%d)",
this->id(), this->id(),
imageRaw?1:0, imageRaw?1:0,
depthRaw?1:0, depthRaw?1:0,
@@ -658,7 +658,7 @@ void SensorData::uncompressData(
groundCellsRaw?1:0, groundCellsRaw?1:0,
obstacleCellsRaw?1:0, obstacleCellsRaw?1:0,
emptyCellsRaw?1:0, emptyCellsRaw?1:0,
depthConfidenceRaw?1:0);*/ depthConfidenceRaw?1:0);
if(imageRaw == 0 && if(imageRaw == 0 &&
depthRaw == 0 && depthRaw == 0 &&
laserScanRaw == 0 && laserScanRaw == 0 &&
+3 -3
View File
@@ -118,7 +118,7 @@ void Signature::addLinks(const std::map<int, Link> & links)
} }
void Signature::addLink(const Link & link) void Signature::addLink(const Link & link)
{ {
//UDEBUG("Add link %d to %d (type=%d/%s var=%f,%f)", link.to(), this->id(), (int)link.type(), link.typeName().c_str(), link.transVariance(), link.rotVariance()); UDEBUG("Add link %d to %d (type=%d/%s var=%f,%f)", link.to(), this->id(), (int)link.type(), link.typeName().c_str(), link.transVariance(), link.rotVariance());
UASSERT_MSG(link.from() == this->id(), uFormat("%d->%d for signature %d (type=%d)", link.from(), link.to(), this->id(), link.type()).c_str()); UASSERT_MSG(link.from() == this->id(), uFormat("%d->%d for signature %d (type=%d)", link.from(), link.to(), this->id(), link.type()).c_str());
UASSERT_MSG((link.to() != this->id()) || link.type()==Link::kPosePrior || link.type()==Link::kGravity, uFormat("%d->%d for signature %d (type=%d)", link.from(), link.to(), this->id(), link.type()).c_str()); UASSERT_MSG((link.to() != this->id()) || link.type()==Link::kPosePrior || link.type()==Link::kGravity, uFormat("%d->%d for signature %d (type=%d)", link.from(), link.to(), this->id(), link.type()).c_str());
UASSERT_MSG(link.to() == this->id() || _links.find(link.to()) == _links.end(), uFormat("Link %d (type=%d) already added to signature %d!", link.to(), link.type(), this->id()).c_str()); UASSERT_MSG(link.to() == this->id() || _links.find(link.to()) == _links.end(), uFormat("Link %d (type=%d) already added to signature %d!", link.to(), link.type(), this->id()).c_str());
@@ -318,7 +318,7 @@ void Signature::setWords(const std::multimap<int, int> & words,
UASSERT_MSG(descriptors.empty() || descriptors.rows == (int)words.size(), uFormat("words=%d, descriptors=%d", (int)words.size(), descriptors.rows).c_str()); UASSERT_MSG(descriptors.empty() || descriptors.rows == (int)words.size(), uFormat("words=%d, descriptors=%d", (int)words.size(), descriptors.rows).c_str());
UASSERT_MSG(points.empty() || points.size() == words.size(), uFormat("words=%d, points=%d", (int)words.size(), (int)points.size()).c_str()); UASSERT_MSG(points.empty() || points.size() == words.size(), uFormat("words=%d, points=%d", (int)words.size(), (int)points.size()).c_str());
UASSERT_MSG(keypoints.empty() || keypoints.size() == words.size(), uFormat("words=%d, descriptors=%d", (int)words.size(), (int)keypoints.size()).c_str()); UASSERT_MSG(keypoints.empty() || keypoints.size() == words.size(), uFormat("words=%d, descriptors=%d", (int)words.size(), (int)keypoints.size()).c_str());
//UASSERT(words.empty() || !keypoints.empty() || !points.empty() || !descriptors.empty()); UASSERT(words.empty() || !keypoints.empty() || !points.empty() || !descriptors.empty());
_invalidWordsCount = 0; _invalidWordsCount = 0;
for(std::multimap<int, int>::const_iterator iter=words.begin(); iter!=words.end(); ++iter) for(std::multimap<int, int>::const_iterator iter=words.begin(); iter!=words.end(); ++iter)
@@ -328,7 +328,7 @@ void Signature::setWords(const std::multimap<int, int> & words,
++_invalidWordsCount; ++_invalidWordsCount;
} }
// make sure indexes are all valid! // make sure indexes are all valid!
UASSERT_MSG(iter->second<0 || iter->second < (int)words.size(), uFormat("iter->second=%d words.size()=%d", iter->second, (int)words.size()).c_str()); UASSERT_MSG(iter->second >=0 && iter->second < (int)words.size(), uFormat("iter->second=%d words.size()=%d", iter->second, (int)words.size()).c_str());
} }
_enabled = false; _enabled = false;
+45 -187
View File
@@ -51,6 +51,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <fstream> #include <fstream>
#include <string> #include <string>
#define KDTREE_SIZE 4
#define KNN_CHECKS 32 #define KNN_CHECKS 32
namespace rtabmap namespace rtabmap
@@ -68,11 +69,9 @@ VWDictionary::VWDictionary(const ParametersMap & parameters) :
_nndrRatio(Parameters::defaultKpNndrRatio()), _nndrRatio(Parameters::defaultKpNndrRatio()),
_newDictionaryPath(Parameters::defaultKpDictionaryPath()), _newDictionaryPath(Parameters::defaultKpDictionaryPath()),
_newWordsComparedTogether(Parameters::defaultKpNewWordsComparedTogether()), _newWordsComparedTogether(Parameters::defaultKpNewWordsComparedTogether()),
_serializeWithChecksum(Parameters::defaultKpSerializeWithChecksum()),
_lastWordId(0), _lastWordId(0),
useDistanceL1_(false), useDistanceL1_(false),
_flannIndex(new FlannIndex()), _flannIndex(new FlannIndex()),
_modified(true),
_strategy(kNNBruteForce) _strategy(kNNBruteForce)
{ {
this->setNNStrategy((NNStrategy)Parameters::defaultKpNNStrategy()); this->setNNStrategy((NNStrategy)Parameters::defaultKpNNStrategy());
@@ -90,7 +89,6 @@ void VWDictionary::parseParameters(const ParametersMap & parameters)
ParametersMap::const_iterator iter; ParametersMap::const_iterator iter;
Parameters::parse(parameters, Parameters::kKpNndrRatio(), _nndrRatio); Parameters::parse(parameters, Parameters::kKpNndrRatio(), _nndrRatio);
Parameters::parse(parameters, Parameters::kKpNewWordsComparedTogether(), _newWordsComparedTogether); Parameters::parse(parameters, Parameters::kKpNewWordsComparedTogether(), _newWordsComparedTogether);
Parameters::parse(parameters, Parameters::kKpSerializeWithChecksum(), _serializeWithChecksum);
Parameters::parse(parameters, Parameters::kKpIncrementalFlann(), _incrementalFlann); Parameters::parse(parameters, Parameters::kKpIncrementalFlann(), _incrementalFlann);
Parameters::parse(parameters, Parameters::kKpFlannRebalancingFactor(), _rebalancingFactor); Parameters::parse(parameters, Parameters::kKpFlannRebalancingFactor(), _rebalancingFactor);
bool byteToFloat = _byteToFloat; bool byteToFloat = _byteToFloat;
@@ -162,7 +160,7 @@ void VWDictionary::setFixedDictionary(const std::string & dictionaryPath)
DBDriver * driver = DBDriver::create(); DBDriver * driver = DBDriver::create();
if(driver->openConnection(dictionaryPath, false)) if(driver->openConnection(dictionaryPath, false))
{ {
driver->load(*this, false); driver->load(this, false);
for(std::map<int, VisualWord*>::iterator iter=_visualWords.begin(); iter!=_visualWords.end(); ++iter) for(std::map<int, VisualWord*>::iterator iter=_visualWords.begin(); iter!=_visualWords.end(); ++iter)
{ {
iter->second->setSaved(true); iter->second->setSaved(true);
@@ -291,11 +289,6 @@ void VWDictionary::setFixedDictionary(const std::string & dictionaryPath)
_newDictionaryPath = dictionaryPath; _newDictionaryPath = dictionaryPath;
} }
bool VWDictionary::isModified() const
{
return _modified;
}
bool VWDictionary::setNNStrategy(NNStrategy strategy) bool VWDictionary::setNNStrategy(NNStrategy strategy)
{ {
#if CV_MAJOR_VERSION < 3 #if CV_MAJOR_VERSION < 3
@@ -491,13 +484,7 @@ void VWDictionary::update()
if(_notIndexedWords.size() || _visualWords.size() == 0 || _removedIndexedWords.size()) if(_notIndexedWords.size() || _visualWords.size() == 0 || _removedIndexedWords.size())
{ {
_modified = true; if(_incrementalFlann &&
bool firstUpdate = _removedIndexedWords.empty() && _visualWords.size() == _notIndexedWords.size();
UDEBUG("firstUpdate=%s (_removedIndexedWords=%ld, _visualWords=%ld, _notIndexedWords=%ld)",
firstUpdate?"true":"false", _removedIndexedWords.size(), _visualWords.size(), _notIndexedWords.size());
if(!firstUpdate &&
_incrementalFlann &&
_strategy < kNNBruteForce && _strategy < kNNBruteForce &&
_visualWords.size()) _visualWords.size())
{ {
@@ -514,9 +501,7 @@ void VWDictionary::update()
if(_notIndexedWords.size()) if(_notIndexedWords.size())
{ {
UTimer timer; ULOGGER_DEBUG("Incremental FLANN: Inserting %d words...", (int)_notIndexedWords.size());
timer.start();
ULOGGER_DEBUG("Incremental FLANN: Inserting %d words...", (int)_notIndexedWords.size(), _byteToFloat?"true":"false");
for(std::set<int>::iterator iter=_notIndexedWords.begin(); iter!=_notIndexedWords.end(); ++iter) for(std::set<int>::iterator iter=_notIndexedWords.begin(); iter!=_notIndexedWords.end(); ++iter)
{ {
VisualWord* w = uValue(_visualWords, *iter, (VisualWord*)0); VisualWord* w = uValue(_visualWords, *iter, (VisualWord*)0);
@@ -543,13 +528,24 @@ void VWDictionary::update()
int index = 0; int index = 0;
if(!_flannIndex->isBuilt()) if(!_flannIndex->isBuilt())
{ {
UDEBUG("Building FLANN index... (strategy=%s, byteToFloat=%s, useDistanceL1=%s, rebalancingFactor=%f)", UDEBUG("Building FLANN index...");
nnStrategyName(_strategy).c_str(), _byteToFloat?"true":"false", useDistanceL1_?"true":"false", _rebalancingFactor); switch(_strategy)
_flannIndex->buildIndex( {
_strategy == kNNFlannNaive ? FlannIndex::FLANN_INDEX_LINEAR: case kNNFlannNaive:
_strategy == kNNFlannLSH ? FlannIndex::FLANN_INDEX_LSH: _flannIndex->buildLinearIndex(descriptor, useDistanceL1_, _rebalancingFactor);
FlannIndex::FLANN_INDEX_KDTREE, // kNNFlannKdTree break;
descriptor, useDistanceL1_, _rebalancingFactor); case kNNFlannKdTree:
UASSERT_MSG(descriptor.type() == CV_32F, "To use KdTree dictionary, float descriptors are required!");
_flannIndex->buildKDTreeIndex(descriptor, KDTREE_SIZE, useDistanceL1_, _rebalancingFactor);
break;
case kNNFlannLSH:
UASSERT_MSG(descriptor.type() == CV_8U, "To use LSH dictionary, binary descriptors are required!");
_flannIndex->buildLSHIndex(descriptor, 12, 20, 2, _rebalancingFactor);
break;
default:
UFATAL("Not supposed to be here!");
break;
}
UDEBUG("Building FLANN index... done!"); UDEBUG("Building FLANN index... done!");
} }
else else
@@ -565,7 +561,7 @@ void VWDictionary::update()
inserted = _mapIdIndex.insert(std::pair<int, int>(w->id(), index)); inserted = _mapIdIndex.insert(std::pair<int, int>(w->id(), index));
UASSERT(inserted.second); UASSERT(inserted.second);
} }
ULOGGER_DEBUG("Incremental FLANN: Inserting %d words... done! (in %f s)", (int)_notIndexedWords.size(), timer.ticks()); ULOGGER_DEBUG("Incremental FLANN: Inserting %d words... done!", (int)_notIndexedWords.size());
} }
} }
else if(_strategy >= kNNBruteForce && else if(_strategy >= kNNBruteForce &&
@@ -661,13 +657,23 @@ void VWDictionary::update()
ULOGGER_DEBUG("_mapIndexId.size() = %d, words.size()=%d, _dim=%d",_mapIndexId.size(), _visualWords.size(), dim); ULOGGER_DEBUG("_mapIndexId.size() = %d, words.size()=%d, _dim=%d",_mapIndexId.size(), _visualWords.size(), dim);
ULOGGER_DEBUG("copying data = %f s", timer.ticks()); ULOGGER_DEBUG("copying data = %f s", timer.ticks());
_flannIndex->buildIndex( switch(_strategy)
_strategy == kNNFlannNaive ? FlannIndex::FLANN_INDEX_LINEAR: {
_strategy == kNNFlannLSH ? FlannIndex::FLANN_INDEX_LSH: case kNNFlannNaive:
FlannIndex::FLANN_INDEX_KDTREE, // kNNFlannKdTree _flannIndex->buildLinearIndex(_dataTree, useDistanceL1_, _incrementalDictionary&&_incrementalFlann?_rebalancingFactor:1);
_dataTree, break;
useDistanceL1_, case kNNFlannKdTree:
_incrementalDictionary&&_incrementalFlann?_rebalancingFactor:1); UASSERT_MSG(type == CV_32F, "To use KdTree dictionary, float descriptors are required!");
_flannIndex->buildKDTreeIndex(_dataTree, KDTREE_SIZE, useDistanceL1_, _incrementalDictionary&&_incrementalFlann?_rebalancingFactor:1);
break;
case kNNFlannLSH:
UASSERT_MSG(type == CV_8U, "To use LSH dictionary, binary descriptors are required!");
_flannIndex->buildLSHIndex(_dataTree, 12, 20, 2, _incrementalDictionary&&_incrementalFlann?_rebalancingFactor:1);
break;
default:
break;
}
ULOGGER_DEBUG("Time to create kd tree = %f s", timer.ticks()); ULOGGER_DEBUG("Time to create kd tree = %f s", timer.ticks());
} }
} }
@@ -683,146 +689,6 @@ void VWDictionary::update()
UDEBUG(""); UDEBUG("");
} }
std::vector<unsigned char> VWDictionary::serializeIndex() const
{
if(_strategy >= kNNBruteForce) {
UINFO("Not flann strategy, ignoring serialization...");
return std::vector<unsigned char>();
}
if(!_flannIndex->isBuilt() || !_removedIndexedWords.empty() || !_notIndexedWords.empty() || _visualWords.empty()) {
UWARN("Flann index is not buit, or there are words not indexed, cannot do serialization.");
return std::vector<unsigned char>();
}
return _flannIndex->serializeIndex(_serializeWithChecksum);
}
void VWDictionary::deserializeIndex(const std::vector<unsigned char> & data)
{
deserializeIndex(data.data(), data.size());
}
void VWDictionary::deserializeIndex(const unsigned char * data, size_t size)
{
if(data== NULL || size == 0)
{
UWARN("Trying to deserialize empty data, aborting.");
return;
}
UDEBUG("Loading flann index... (data size=%ld bytes)", size);
if(_strategy >= kNNBruteForce) {
//ignore
return;
}
if(_flannIndex->isBuilt()) {
UERROR("Flann index is already built, cannot deserialize data!");
return;
}
if(_visualWords.empty()) {
UERROR("Descriptors should be added before deserializing flann index! See VWDictionary::addWord()");
return;
}
if(!(_removedIndexedWords.empty() && _visualWords.size() == _notIndexedWords.size())) {
UERROR("State of dictionary not as expected before deserializing. (removed words=%ld, words=%ld, not indexed=%ld)",
_removedIndexedWords.size(), _visualWords.size(), _notIndexedWords.size());
return;
}
std::map<int, int> mapIndexId;
std::map<int, int> mapIdIndex;
cv::Mat dataTree;
UTimer timer;
timer.start();
int dim = _visualWords.begin()->second->getDescriptor().cols;
int type;
if(_visualWords.begin()->second->getDescriptor().type() == CV_8U)
{
useDistanceL1_ = true;
if(_strategy == kNNFlannKdTree)
{
type = CV_32F;
if(!_byteToFloat)
{
dim *= 8;
}
}
else
{
type = _visualWords.begin()->second->getDescriptor().type();
}
}
else
{
type = _visualWords.begin()->second->getDescriptor().type();
}
UASSERT(type == CV_32F || type == CV_8U);
UASSERT(dim > 0);
// Create the data matrix
dataTree = cv::Mat(_visualWords.size(), dim, type); // SURF descriptors are CV_32F
std::map<int, VisualWord*>::const_iterator iter = _visualWords.begin();
for(unsigned int i=0; i < _visualWords.size(); ++i, ++iter)
{
cv::Mat descriptor;
if(iter->second->getDescriptor().type() == CV_8U)
{
if(_strategy == kNNFlannKdTree)
{
descriptor = convertBinTo32F(iter->second->getDescriptor(), _byteToFloat);
}
else
{
descriptor = iter->second->getDescriptor();
}
}
else
{
descriptor = iter->second->getDescriptor();
}
UASSERT_MSG(descriptor.type() == type, uFormat("%d vs %d", descriptor.type(), type).c_str());
UASSERT_MSG(descriptor.cols == dim, uFormat("%d vs %d", descriptor.cols, dim).c_str());
descriptor.copyTo(dataTree.row(i));
mapIndexId.insert(mapIndexId.end(), std::pair<int, int>(i, iter->second->id()));
mapIdIndex.insert(mapIdIndex.end(), std::pair<int, int>(iter->second->id(), i));
}
ULOGGER_DEBUG("mapIndexId.size() = %d, words.size()=%d, dim=%d", mapIndexId.size(), _visualWords.size(), dim);
ULOGGER_DEBUG("copying data = %f s", timer.ticks());
std::string errorMsg;
if(_flannIndex->loadIndex(
data,
size,
_strategy == kNNFlannNaive ? FlannIndex::FLANN_INDEX_LINEAR:
_strategy == kNNFlannLSH ? FlannIndex::FLANN_INDEX_LSH:
FlannIndex::FLANN_INDEX_KDTREE,
dataTree,
useDistanceL1_,
_incrementalDictionary && _incrementalFlann ? _rebalancingFactor:1,
&errorMsg))
{
_mapIndexId = mapIndexId;
_mapIdIndex = mapIdIndex;
_dataTree = dataTree;
_notIndexedWords.clear();
_modified = false;
}
else {
UWARN("Failed deserializing flann index data (error: %s), the index will be rebuilt on next update.", errorMsg.c_str());
_flannIndex->release(); // reset to initial state
}
ULOGGER_DEBUG("Time to load flann index = %f s", timer.ticks());
}
void VWDictionary::clear(bool printWarningsIfNotEmpty) void VWDictionary::clear(bool printWarningsIfNotEmpty)
{ {
ULOGGER_DEBUG(""); ULOGGER_DEBUG("");
@@ -852,7 +718,6 @@ void VWDictionary::clear(bool printWarningsIfNotEmpty)
_unusedWords.clear(); _unusedWords.clear();
_flannIndex->release(); _flannIndex->release();
useDistanceL1_ = false; useDistanceL1_ = false;
_modified = true;
} }
int VWDictionary::getNextId() int VWDictionary::getNextId()
@@ -919,21 +784,14 @@ std::list<int> VWDictionary::addNewWords(
type = _visualWords.begin()->second->getDescriptor().type(); type = _visualWords.begin()->second->getDescriptor().type();
UASSERT(type == CV_32F || type == CV_8U); UASSERT(type == CV_32F || type == CV_8U);
} }
static std::string moreInfo = uFormat(
"This could happen if the computer doesn't have access to same "
"feature detectors than when the database was created. This could "
"also happen if we enabled \"%s\" but the first frame received "
"was empty, thus features were re-extracted with a different detector "
"than the one used by the odometry.",
Parameters::kMemUseOdomFeatures().c_str());
if(dim && dim != descriptorsIn.cols) if(dim && dim != descriptorsIn.cols)
{ {
UERROR("Descriptors (size=%d) are not the same size as already added words in dictionary (size=%d). %s", descriptorsIn.cols, dim, moreInfo.c_str()); UERROR("Descriptors (size=%d) are not the same size as already added words in dictionary(size=%d)", descriptorsIn.cols, dim);
return wordIds; return wordIds;
} }
if(type>=0 && type != descriptorsIn.type()) if(type>=0 && type != descriptorsIn.type())
{ {
UERROR("Descriptors (type=%d) are not the same type as already added words in dictionary (type=%d). %s", descriptorsIn.type(), type, moreInfo.c_str()); UERROR("Descriptors (type=%d) are not the same type as already added words in dictionary(type=%d)", descriptorsIn.type(), type);
return wordIds; return wordIds;
} }
@@ -1536,15 +1394,15 @@ void VWDictionary::addWord(VisualWord * vw)
{ {
if(vw) if(vw)
{ {
_visualWords.insert(_visualWords.end(), std::pair<int, VisualWord *>(vw->id(), vw)); _visualWords.insert(std::pair<int, VisualWord *>(vw->id(), vw));
_notIndexedWords.insert(_notIndexedWords.end(), vw->id()); _notIndexedWords.insert(vw->id());
if(vw->getReferences().size()) if(vw->getReferences().size())
{ {
_totalActiveReferences += uSum(uValues(vw->getReferences())); _totalActiveReferences += uSum(uValues(vw->getReferences()));
} }
else else
{ {
_unusedWords.insert(_unusedWords.end(), std::pair<int, VisualWord *>(vw->id(), vw)); _unusedWords.insert(std::pair<int, VisualWord *>(vw->id(), vw));
} }
if(_lastWordId < vw->id()) if(_lastWordId < vw->id())
{ {
+1 -1
View File
@@ -57,7 +57,7 @@ void VisualWord::addRef(int signatureId)
} }
else else
{ {
_references.insert(_references.end(), std::pair<int, int>(signatureId, 1)); _references.insert(std::pair<int, int>(signatureId, 1));
} }
++_totalReferences; ++_totalReferences;
} }
+3 -4
View File
@@ -370,10 +370,9 @@ bool CameraDepthAI::init(const std::string & calibrationFolder, const std::strin
matrix[2][0], matrix[2][1], matrix[2][2]); matrix[2][0], matrix[2][1], matrix[2][2]);
std::vector<float> coeffs = calibHandler.getDistortionCoefficients(cameraId); std::vector<float> coeffs = calibHandler.getDistortionCoefficients(cameraId);
if(calibHandler.getDistortionModel(cameraId) == dai::CameraModel::Perspective) { if(calibHandler.getDistortionModel(cameraId) == dai::CameraModel::Perspective)
UASSERT(coeffs.size()>=14); distCoeffs = (cv::Mat_<double>(1,8) << coeffs[0], coeffs[1], coeffs[2], coeffs[3], coeffs[4], coeffs[5], coeffs[6], coeffs[7]);
distCoeffs = (cv::Mat_<double>(1,14) << coeffs[0], coeffs[1], coeffs[2], coeffs[3], coeffs[4], coeffs[5], coeffs[6], coeffs[7], coeffs[8], coeffs[9], coeffs[10], coeffs[11], coeffs[12], coeffs[13]);
}
if(alphaScaling_>-1.0f) if(alphaScaling_>-1.0f)
newCameraMatrix = cv::getOptimalNewCameraMatrix(cameraMatrix, distCoeffs, targetSize_, alphaScaling_); newCameraMatrix = cv::getOptimalNewCameraMatrix(cameraMatrix, distCoeffs, targetSize_, alphaScaling_);
else else
+3 -3
View File
@@ -523,19 +523,19 @@ bool CameraImages::readPoses(
UERROR("Cannot read pose file \"%s\".", filePath.c_str()); UERROR("Cannot read pose file \"%s\".", filePath.c_str());
return false; return false;
} }
else if((format != 1 && format != 10 && format != 12 && format != 5 && format != 6 && format != 7 && format != 9) && poses.size() != this->imagesCount()) else if((format != 1 && format != 10 && format != 5 && format != 6 && format != 7 && format != 9) && poses.size() != this->imagesCount())
{ {
UERROR("The pose count is not the same as the images (%d vs %d)! Please remove " UERROR("The pose count is not the same as the images (%d vs %d)! Please remove "
"the pose file path if you don't want to use it (current file path=%s).", "the pose file path if you don't want to use it (current file path=%s).",
(int)poses.size(), this->imagesCount(), filePath.c_str()); (int)poses.size(), this->imagesCount(), filePath.c_str());
return false; return false;
} }
else if((format == 1 || format == 10 || format == 12 || format == 5 || format == 6 || format == 7 || format == 9) && (inOutStamps.empty() && stamps.size()!=poses.size())) else if((format == 1 || format == 10 || format == 5 || format == 6 || format == 7 || format == 9) && (inOutStamps.empty() && stamps.size()!=poses.size()))
{ {
UERROR("When using RGBD-SLAM, GPS, MALAGA, ST LUCIA and EuRoC MAV formats, images must have timestamps!"); UERROR("When using RGBD-SLAM, GPS, MALAGA, ST LUCIA and EuRoC MAV formats, images must have timestamps!");
return false; return false;
} }
else if(format == 1 || format == 10 || format == 12 || format == 5 || format == 6 || format == 7 || format == 9) else if(format == 1 || format == 10 || format == 5 || format == 6 || format == 7 || format == 9)
{ {
UDEBUG(""); UDEBUG("");
//Match ground truth values with images //Match ground truth values with images
-728
View File
@@ -1,728 +0,0 @@
/*
Copyright (c) 2010-2025, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Universite de Sherbrooke nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <rtabmap/core/camera/CameraOrbbecSDK.h>
#include <rtabmap/core/util2d.h>
#include <rtabmap/utilite/UTimer.h>
#include <rtabmap/utilite/UStl.h>
#include <rtabmap/utilite/UThread.h>
#ifdef RTABMAP_ORBBEC_SDK
#include <libobsensor/ObSensor.hpp>
#endif
namespace rtabmap
{
#ifdef RTABMAP_ORBBEC_SDK
Transform obToRtabmap(const OBExtrinsic & t)
{
return Transform(t.rot[0], t.rot[1], t.rot[2], t.trans[0]/1000.0f,
t.rot[3], t.rot[4], t.rot[5], t.trans[1]/1000.0f,
t.rot[6], t.rot[7], t.rot[8], t.trans[2]/1000.0f);
}
cv::Mat obColorFrameToCv(const ob::VideoFrame & videoFrame)
{
cv::Mat rgb;
switch(videoFrame.getFormat()) {
case OB_FORMAT_MJPG: {
cv::Mat rawMat(1, videoFrame.getDataSize(), CV_8UC1, videoFrame.getData());
rgb = cv::imdecode(rawMat, 1);
} break;
case OB_FORMAT_NV21: {
cv::Mat rawMat(videoFrame.getHeight() * 3 / 2, videoFrame.getWidth(), CV_8UC1, videoFrame.getData());
cv::cvtColor(rawMat, rgb, cv::COLOR_YUV2BGR_NV21);
} break;
case OB_FORMAT_YUYV:
case OB_FORMAT_YUY2: {
cv::Mat rawMat(videoFrame.getHeight(), videoFrame.getWidth(), CV_8UC2, videoFrame.getData());
cv::cvtColor(rawMat, rgb, cv::COLOR_YUV2BGR_YUY2);
} break;
case OB_FORMAT_BGR: {
cv::Mat rawMat(videoFrame.getHeight(), videoFrame.getWidth(), CV_8UC3, videoFrame.getData());
cv::cvtColor(rawMat, rgb, cv::COLOR_BGR2RGB);
} break;
case OB_FORMAT_RGB: {
cv::Mat rawMat(videoFrame.getHeight(), videoFrame.getWidth(), CV_8UC3, videoFrame.getData());
cv::cvtColor(rawMat, rgb, cv::COLOR_RGB2BGR);
} break;
case OB_FORMAT_RGBA: {
cv::Mat rawMat(videoFrame.getHeight(), videoFrame.getWidth(), CV_8UC4, videoFrame.getData());
cv::cvtColor(rawMat, rgb, cv::COLOR_RGBA2BGR);
} break;
case OB_FORMAT_BGRA: {
cv::Mat rawMat(videoFrame.getHeight(), videoFrame.getWidth(), CV_8UC4, videoFrame.getData());
cv::cvtColor(rawMat, rgb, cv::COLOR_BGRA2RGB);
} break;
case OB_FORMAT_UYVY: {
cv::Mat rawMat(videoFrame.getHeight(), videoFrame.getWidth(), CV_8UC2, videoFrame.getData());
cv::cvtColor(rawMat, rgb, cv::COLOR_YUV2BGR_UYVY);
} break;
case OB_FORMAT_I420: {
cv::Mat rawMat(videoFrame.getHeight() * 3 / 2, videoFrame.getWidth(), CV_8UC1, videoFrame.getData());
cv::cvtColor(rawMat, rgb, cv::COLOR_YUV2BGR_I420);
} break;
case OB_FORMAT_Y8: {
rgb = cv::Mat(videoFrame.getHeight(), videoFrame.getWidth(), CV_8UC1, videoFrame.getData()).clone();
} break;
case OB_FORMAT_Y16: {
cv::Mat rawMat(videoFrame.getHeight(), videoFrame.getWidth(), CV_16UC1, videoFrame.getData());
rawMat.convertTo(rgb, CV_8UC1, 255.0 / 65535.0);
} break;
default:
break;
}
return rgb;
}
cv::Mat obDepthFrameToCv(const ob::DepthFrame & depthFrame)
{
cv::Mat depth;
if(depthFrame.getFormat() == OB_FORMAT_Y16 || depthFrame.getFormat() == OB_FORMAT_Z16 || depthFrame.getFormat() == OB_FORMAT_Y12C4) {
cv::Mat rawMat = cv::Mat(depthFrame.getHeight(), depthFrame.getWidth(), CV_16UC1, depthFrame.getData());
float scale = depthFrame.getValueScale() / 1000.0f;
rawMat.convertTo(depth, CV_32F, scale);
}
return depth;
}
cv::Mat obIntrinsicToK(const OBCameraIntrinsic & intrinsics)
{
cv::Mat K = cv::Mat::eye(3,3,CV_64FC1);
K.at<double>(0,0) = intrinsics.fx;
K.at<double>(1,1) = intrinsics.fy;
K.at<double>(0,2) = intrinsics.cx;
K.at<double>(1,2) = intrinsics.cy;
return K;
}
cv::Mat obIntrinsicToP(const OBCameraIntrinsic & intrinsics)
{
cv::Mat P = cv::Mat::eye(3,4,CV_64FC1);
obIntrinsicToK(intrinsics).copyTo(P.colRange(0,3));
return P;
}
cv::Mat obDistortionToD(const OBCameraDistortion & distortion)
{
cv::Mat D = cv::Mat(1,8,CV_64FC1);
D.at<double>(0,0) = distortion.k1;
D.at<double>(0,1) = distortion.k2;
D.at<double>(0,2) = distortion.p1;
D.at<double>(0,3) = distortion.p2;
D.at<double>(0,4) = distortion.k3;
D.at<double>(0,5) = distortion.k4;
D.at<double>(0,6) = distortion.k5;
D.at<double>(0,7) = distortion.k6;
if(distortion.k4 == 0 && distortion.k5 == 0 && distortion.k6 == 0)
{
D = D.colRange(0,5);
}
return D;
}
#endif
bool CameraOrbbecSDK::available()
{
#ifdef RTABMAP_ORBBEC_SDK
return true;
#else
return false;
#endif
}
CameraOrbbecSDK::CameraOrbbecSDK(
std::string deviceId,
int colorWidth,
int colorHeight,
int depthWidth,
int depthHeight,
float imageRate,
const Transform & localTransform) :
Camera(imageRate, localTransform)
#ifdef RTABMAP_ORBBEC_SDK
, deviceId_(deviceId),
colorWidth_(colorWidth),
colorHeight_(colorHeight),
depthWidth_(depthWidth),
depthHeight_(depthHeight),
pipeline_(nullptr),
imuPipeline_(nullptr),
alignFilter_(nullptr),
imuLocalTransformInitialized_(false),
lastAccStamp_(0),
lastImageStamp_(0),
globalTimestampAvailable_(false),
rectifyColor_(false),
convertDepthToMM_(true),
imuPublished_(true)
#endif
{
}
CameraOrbbecSDK::~CameraOrbbecSDK()
{
#ifdef RTABMAP_ORBBEC_SDK
this->close();
#endif
}
void CameraOrbbecSDK::close()
{
#ifdef RTABMAP_ORBBEC_SDK
if(imuPipeline_) {
imuPipeline_->stop();
delete imuPipeline_;
imuPipeline_=nullptr;
}
if(pipeline_) {
pipeline_->stop();
delete pipeline_;
pipeline_=nullptr;
}
delete alignFilter_;
alignFilter_ = nullptr;
imuLocalTransform_ = Transform();
imuLocalTransformInitialized_ = false;
lastAccStamp_ = 0;
lastImageStamp_ = 0;
globalTimestampAvailable_ = false;
model_ = CameraModel();
imuBuffer_.clear();
#endif
}
bool CameraOrbbecSDK::init(const std::string & calibrationFolder, const std::string & cameraName)
{
#ifdef RTABMAP_ORBBEC_SDK
this->close();
std::shared_ptr<ob::Device> device;
ob::Context context;
auto devices = context.queryDeviceList();
UINFO("%d device(s) found", devices->getCount());
for(uint32_t i=0; i<devices->getCount(); ++i)
{
auto currentDevice = devices->getDevice(i);
auto info = currentDevice->getDeviceInfo();
if(deviceId_.find('-') != std::string::npos)
{
// UID
if(deviceId_.compare(info->getUid()) == 0) {
device = currentDevice;
}
}
else if(uSplitNumChar(deviceId_).size() > 1)
{
// Serial
if(deviceId_.compare(info->getSerialNumber()) == 0) {
device = currentDevice;
}
}
else if((deviceId_.empty() && i==0) ||
(!deviceId_.empty() && uStr2Int(deviceId_) == (int)i)) {
// Index
device = currentDevice;
}
std::string type = "Unknown";
switch(info->getDeviceType())
{
case OB_STRUCTURED_LIGHT_MONOCULAR_CAMERA:
type = "Structured Light Monocular Camera";
break;
case OB_STRUCTURED_LIGHT_BINOCULAR_CAMERA:
type = "Structured Light Binocular Camera";
break;
case OB_TOF_CAMERA:
type = "TOF Camera";
break;
default:
break;
}
UINFO("Device %ld:", i);
UINFO(" Name: %s", info->getName());
UINFO(" Type: %s", type.c_str());
UINFO(" Serial: %s", info->getSerialNumber());
UINFO(" UID: %s", info->getUid());
UINFO(" Chip: %s", info->getAsicName());
UINFO(" Hardware version: %s", info->getHardwareVersion());
UINFO(" Firmware version: %s", info->getFirmwareVersion());
}
if(device.get() == nullptr) {
if(deviceId_.empty()) {
UERROR( "Could not find any orbbec compatible devices! Verify that the "
"camera is correctly connected and the udev rules are installed.");
}
else {
UERROR("Could not find an orbbec device with ID \"%s\"! Verify that the "
"camera is correctly connected and the udev rules are installed. "
"Unset the ID to choose the first camera found.");
}
return false;
}
bool hasGyro = false;
bool hasAccel = false;
auto sensors = device->getSensorList();
if(device->isGlobalTimestampSupported())
{
UINFO("Global (host time sync) timestamp is supported.");
device->enableGlobalTimestamp(true);
globalTimestampAvailable_ = true;
}
else
{
UWARN("Global (host time sync) timestamp is not supported! We will use device timestamp, so the camera frames won't be synchronizable with other sensors.");
}
uint32_t maxColorFps = 0;
uint32_t maxDepthFps = 0;
for(uint32_t i=0; i<sensors->getCount(); ++i)
{
if(sensors->getSensorType(i) == OB_SENSOR_GYRO)
{
hasGyro = true;
}
if(sensors->getSensorType(i) == OB_SENSOR_ACCEL)
{
hasAccel = true;
}
if( sensors->getSensorType(i) == OB_SENSOR_DEPTH ||
sensors->getSensorType(i) == OB_SENSOR_COLOR)
{
auto profiles = sensors->getSensor(i)->getStreamProfileList();
UINFO("Supported %s profiles:", sensors->getSensorType(i) == OB_SENSOR_DEPTH?"depth":"color");
for(uint32_t j=0; j<profiles->getCount(); ++j)
{
auto profile = profiles->getProfile(j)->as<ob::VideoStreamProfile>();
UINFO("Resolution: %ldx%ld, FPS: %ld, Format: %d",
profile->getWidth(), profile->getHeight(), profile->getFps(), profile->getFormat(), j==0?" (default)":"");
if(sensors->getSensorType(i) == OB_SENSOR_DEPTH) {
if(profile->getFps() > maxDepthFps) {
maxDepthFps = profile->getFps();
}
}
else
{
if(profile->getFps() > maxColorFps) {
maxColorFps = profile->getFps();
}
}
}
}
}
std::shared_ptr<ob::Config> imuConfig;
if(imuPublished_)
{
if(hasGyro && hasAccel)
{
imuPipeline_ = new ob::Pipeline(device);
imuConfig = std::make_shared<ob::Config>();
imuConfig->enableGyroStream();
imuConfig->enableAccelStream();
try {
UINFO("Starting imu pipeline");
imuPipeline_->start(imuConfig, [&](std::shared_ptr<ob::FrameSet> frameSet) {
if(frameSet->getCount() != 2)
{
return;
}
if(!imuLocalTransformInitialized_)
{
return;
}
UASSERT(frameSet->getFrame(OB_FRAME_ACCEL) != nullptr &&
frameSet->getFrame(OB_FRAME_GYRO) != nullptr);
auto accel = frameSet->getFrame(OB_FRAME_ACCEL)->as<const ob::AccelFrame>();
auto gyro = frameSet->getFrame(OB_FRAME_GYRO)->as<const ob::GyroFrame>();
uint64_t accelStampUs = globalTimestampAvailable_?accel->getGlobalTimeStampUs():accel->getTimeStampUs();
uint64_t gyroStampUs = globalTimestampAvailable_?gyro->getGlobalTimeStampUs():gyro->getTimeStampUs();
if(accelStampUs != gyroStampUs)
{
UWARN("Received accel and gyro frames with different timestamps (%llu vs %llu), skipping.",
accelStampUs, gyroStampUs);
return;
}
double accStamp = double(accelStampUs)/1e6;
if(accelStampUs <= lastAccStamp_) {
return;
}
lastAccStamp_ = accelStampUs;
auto accelValue = accel->getValue();
auto gyroValue = gyro->getValue();
if(isInterIMUPublishing())
{
IMU imu(cv::Vec3f(gyroValue.x, gyroValue.y, gyroValue.z), cv::Mat::eye(3,3,CV_64FC1),
cv::Vec3f(accelValue.x, accelValue.y, accelValue.z), cv::Mat::eye(3,3,CV_64FC1),
imuLocalTransform_);
this->postInterIMU(imu, accStamp);
}
else
{
UScopeMutex lock(imuMutex_);
imuBuffer_.emplace_hint(imuBuffer_.end(), accStamp, cv::Vec6f(gyroValue.x, gyroValue.y, gyroValue.z, accelValue.x, accelValue.y, accelValue.z));
if(imuBuffer_.size()>1000) {
imuBuffer_.erase(imuBuffer_.begin());
}
}
});
}
catch(const ob::Error & e) {
UERROR("Unexpected error when configuring IMU stream: %s", e.what());
}
}
else
{
UWARN("IMU option is enabled but the camera doesn't have an IMU, ignoring.");
}
}
pipeline_ = new ob::Pipeline(device);
auto config = std::make_shared<ob::Config>();
// Set highest frame rate possible to reduce color/depth sync diff
config->enableVideoStream(OB_STREAM_COLOR, colorWidth_, colorHeight_, maxColorFps, OB_FORMAT_RGB);
config->enableVideoStream(OB_STREAM_DEPTH, depthWidth_, depthHeight_, maxDepthFps, OB_FORMAT_Y16);
UINFO("Using color profile: %dx%d", colorWidth_, colorHeight_);
UINFO("Using depth profile: %dx%d", depthWidth_, depthHeight_);
config->setFrameAggregateOutputMode(OB_FRAME_AGGREGATE_OUTPUT_ALL_TYPE_FRAME_REQUIRE);
config->setAlignMode(ALIGN_DISABLE);
config->setDepthScaleRequire(true);
pipeline_->enableFrameSync();
try {
UINFO("Starting camera pipeline");
pipeline_->start(config);
auto enabledStreams = pipeline_->getConfig()->getEnabledStreamProfileList();
if(imuPipeline_ != nullptr) {
for(uint32_t i=0; i<enabledStreams->getCount() && !imuLocalTransformInitialized_; ++i)
{
if(enabledStreams->getProfile(i)->getType() == OB_STREAM_COLOR)
{
auto enabledImuStreams = imuPipeline_->getConfig()->getEnabledStreamProfileList();
for(uint32_t j=0; j<enabledImuStreams->getCount(); ++j)
{
if(enabledImuStreams->getProfile(j)->getType() == OB_STREAM_ACCEL)
{
auto extrinsics = enabledStreams->getProfile(i)->as<ob::VideoStreamProfile>()->getExtrinsicTo(enabledImuStreams->getProfile(j)->as<ob::AccelStreamProfile>());
// base -> color -> imu
imuLocalTransform_ = this->getLocalTransform() * obToRtabmap(extrinsics);
UINFO("IMU local transform: %s", imuLocalTransform_.prettyPrint().c_str());
imuLocalTransformInitialized_ = true;
break;
}
}
}
}
}
std::shared_ptr<ob::StreamProfile> colorProfile;
std::shared_ptr<ob::StreamProfile> depthProfile;
for(uint32_t i=0; i<enabledStreams->getCount(); ++i)
{
if(enabledStreams->getProfile(i)->getType() == OB_STREAM_COLOR) {
colorProfile = enabledStreams->getProfile(i);
}
else if(enabledStreams->getProfile(i)->getType() == OB_STREAM_DEPTH) {
depthProfile = enabledStreams->getProfile(i);
}
}
bool currentSelectionSupportsHwD2C = false;
auto hwD2CSupportedDepthStreamProfiles = pipeline_->getD2CDepthProfileList(colorProfile, ALIGN_D2C_HW_MODE);
if(hwD2CSupportedDepthStreamProfiles->count() == 0) {
UWARN("Current color profile selected doesn't support any hardware depth to color registration. Software registration is done instead.");
}
else
{
auto depthVsp = depthProfile->as<ob::VideoStreamProfile>();
auto count = hwD2CSupportedDepthStreamProfiles->getCount();
for(uint32_t i = 0; i < count; i++) {
auto vsp = hwD2CSupportedDepthStreamProfiles->getProfile(i)->as<ob::VideoStreamProfile>();
UINFO("Supported depth to color format: Resolution: %ldx%ld, FPS: %ld, Format: %d", vsp->getWidth(), vsp->getHeight(), vsp->getFps(), vsp->getFormat(), i==0?" (default)":"");
if(vsp->getWidth() == depthVsp->getWidth() && vsp->getHeight() == depthVsp->getHeight() && vsp->getFormat() == depthVsp->getFormat()
&& vsp->getFps() == depthVsp->getFps()) {
currentSelectionSupportsHwD2C = true;
}
}
}
if(!currentSelectionSupportsHwD2C) {
UWARN("Hardware depth to color registration cannot be done with the selected color and depth profiles. "
"Software registration is done instead, so more CPU will be needed on the host computer. "
"Set logger level to info to see comptible depth formats for the selected color profile.");
alignFilter_ = new ob::Align(OB_STREAM_COLOR);
alignFilter_->setMatchTargetResolution(false);
}
else {
UINFO("Enabling hardware depth to color registration!");
config->setAlignMode(ALIGN_D2C_HW_MODE);
config->setDepthScaleRequire(false);
pipeline_->stop();
pipeline_->start(config);
}
}
catch(const ob::Error & e)
{
UERROR("Configuration not supported! Exception: %s", e.what());
UERROR("Supported formats:");
for(uint32_t i=0; i<sensors->getCount(); ++i)
{
if( sensors->getSensorType(i) == OB_SENSOR_DEPTH ||
sensors->getSensorType(i) == OB_SENSOR_COLOR)
{
auto profiles = sensors->getSensor(i)->getStreamProfileList();
for(uint32_t j=0; j<profiles->getCount(); ++j)
{
auto profile = profiles->getProfile(j)->as<ob::VideoStreamProfile>();
UERROR("%sResolution: %ldx%ld, FPS: %ld, Format: %d",
sensors->getSensorType(i) == OB_SENSOR_DEPTH?"Depth":"Color",
profile->getWidth(),
profile->getHeight(),
profile->getFps(),
profile->getFormat(),
j==0?" (default)":"");
}
}
}
return false;
}
return true;
#else
UERROR("CameraOrbbecSDK: RTAB-Map is not built with Orbbec SDK support!");
return false;
#endif
}
bool CameraOrbbecSDK::isCalibrated() const
{
return true;
}
std::string CameraOrbbecSDK::getSerial() const
{
#ifdef RTABMAP_ORBBEC_SDK
if(pipeline_) {
return pipeline_->getDevice()->getDeviceInfo()->getSerialNumber();
}
#endif
return "";
}
void CameraOrbbecSDK::enableColorRectification(bool enabled)
{
#ifdef RTABMAP_ORBBEC_SDK
rectifyColor_ = enabled;
#endif
}
void CameraOrbbecSDK::enableImu(bool enabled)
{
#ifdef RTABMAP_ORBBEC_SDK
imuPublished_ = enabled;
#endif
}
void CameraOrbbecSDK::enableDepthMM(bool enabled)
{
#ifdef RTABMAP_ORBBEC_SDK
convertDepthToMM_ = enabled;
#endif
}
SensorData CameraOrbbecSDK::captureImage(SensorCaptureInfo * info)
{
SensorData data;
#ifdef RTABMAP_ORBBEC_SDK
if(!pipeline_) {
UERROR("Camera is not initialized!");
return data;
}
auto frameset = pipeline_->waitForFrameset();
if(frameset == nullptr || frameset->getCount() == 0) {
UWARN("No frame received!");
return data;
}
if(frameset->getCount() != 2) {
UWARN("Received %s frames, expecting 2!", frameset->getCount());
return data;
}
if(alignFilter_ != nullptr) {
// Software depth to color registration
frameset = alignFilter_->process(frameset)->as<ob::FrameSet>();
UASSERT(frameset != nullptr);
}
auto colorFrame = frameset->getFrame(OB_FRAME_COLOR);
UASSERT(colorFrame != nullptr);
auto depthFrame = frameset->getFrame(OB_FRAME_DEPTH);
UASSERT(depthFrame != nullptr);
auto colorVideoFrame = colorFrame->as<const ob::VideoFrame>();
auto depthVideoFrame = depthFrame->as<const ob::DepthFrame>();
cv::Mat rgb = obColorFrameToCv(*colorVideoFrame);
cv::Mat depth = obDepthFrameToCv(*depthVideoFrame);
if(rgb.empty()) {
UERROR("Could not convert the color frame! Type=%d Format=%d", colorFrame->getType(), colorVideoFrame->getFormat());
}
else if(depth.empty()) {
UERROR("Could not convert the depth frame! Type=%d Format=%d", depthFrame->getType(), depthVideoFrame->getFormat());
}
else if(!rgb.empty() && !depth.empty())
{
if(!model_.isValidForProjection())
{
auto streamProfile = colorFrame->getStreamProfile();
auto videoStreamProfile = streamProfile->as<ob::VideoStreamProfile>();
auto intrinsics = videoStreamProfile->getIntrinsic();
model_ = CameraModel(
getSerial(),
cv::Size(intrinsics.width, intrinsics.height),
obIntrinsicToK(intrinsics),
obDistortionToD(videoStreamProfile->getDistortion()),
cv::Mat::eye(3,3,CV_64FC1),
obIntrinsicToP(intrinsics),
this->getLocalTransform());
if(rectifyColor_ && !model_.initRectificationMap()) {
UWARN("Could not initialize rectification map, color images won't be rectified.");
}
}
if(rectifyColor_ && model_.isValidForRectification())
{
rgb = model_.rectifyImage(rgb);
}
if(convertDepthToMM_)
{
depth = util2d::cvtDepthFromFloat(depth);
}
uint64_t colorStampUs = globalTimestampAvailable_?colorFrame->getGlobalTimeStampUs():colorFrame->getTimeStampUs();
uint64_t depthStampUs = globalTimestampAvailable_?depthFrame->getGlobalTimeStampUs():depthFrame->getTimeStampUs();
double colorStamp = double(colorStampUs) / 1e6;
double depthStamp = double(depthStampUs) / 1e6;
if(fabs(colorStamp - depthStamp) > 0.018) {
// The difference seems varying between 0 and 17 ms normally
UWARN("Large timestamp difference (%fs) between color (%f) and depth (%f) frames. "
"Depth registration would be wrong on fast motion.",
colorStamp - depthStamp, colorStamp, depthStamp);
}
uint64_t stampUs = colorStampUs < depthStampUs ? colorStampUs : depthStampUs;
#ifdef WIN32
// On Windows, there is an issue that timestamps are not populated by default without following instructions from:
// https://github.com/orbbec/OrbbecSDK_v2/blob/main/scripts/env_setup/obsensor_metadata_win10.md
// Detect if the consecutive timestamps are identical, then send error!
if (stampUs <= lastImageStamp_)
{
UERROR("We detected non-consecutive timestamps, make sure you applied the fix from https://github.com/orbbec/OrbbecSDK_v2/blob/main/scripts/env_setup/obsensor_metadata_win10.md .");
}
lastImageStamp_ = stampUs;
#endif
double stamp = double(stampUs)/1e6;
data = SensorData(rgb, depth, model_, this->getNextSeqID(), stamp);
if(imuPublished_ && !imuBuffer_.empty() && !this->isInterIMUPublishing())
{
cv::Vec6f imuVec;
std::map<double, cv::Vec6f>::const_iterator iterA, iterB;
imuMutex_.lock();
int maximumTries = 10;
while(imuBuffer_.rbegin()->first < stamp && maximumTries-- > 0)
{
imuMutex_.unlock();
uSleep(1);
imuMutex_.lock();
}
if(imuBuffer_.rbegin()->first < stamp)
{
UWARN("Could not get IMU data at request image stamp %f after waiting 10 ms, latest imu stamp is %f", stamp, imuBuffer_.rbegin()->first);
imuMutex_.unlock();
}
else
{
// Interpolate imu data on image stamp
iterB = imuBuffer_.lower_bound(stamp);
iterA = iterB;
if(iterA != imuBuffer_.begin())
iterA = --iterA;
if(iterA == iterB || stamp == iterB->first)
{
imuVec = iterB->second;
}
else if(stamp > iterA->first && stamp < iterB->first)
{
float t = (stamp-iterA->first) / (iterB->first-iterA->first);
imuVec = iterA->second + t*(iterB->second - iterA->second);
}
imuBuffer_.erase(imuBuffer_.begin(), iterB);
imuMutex_.unlock();
data.setIMU(IMU(cv::Vec3d(imuVec[0], imuVec[1], imuVec[2]), cv::Mat::eye(3, 3, CV_64FC1), cv::Vec3d(imuVec[3], imuVec[4], imuVec[5]), cv::Mat::eye(3, 3, CV_64FC1), imuLocalTransform_));
}
}
}
#else
UERROR("CameraOrbbecSDK: RTAB-Map is not built with Orbbec SDK support!");
#endif
return data;
}
} // namespace rtabmap
File diff suppressed because it is too large Load Diff
-2
View File
@@ -176,8 +176,6 @@ Transform OdometryF2F::computeTransform(
if(info && this->isInfoDataFilled()) if(info && this->isInfoDataFilled())
{ {
std::list<std::pair<int, std::pair<int, int> > > pairs; std::list<std::pair<int, std::pair<int, int> > > pairs;
UASSERT(tmpRefFrame.getWords().size() == tmpRefFrame.getWordsKpts().size());
UASSERT(newFrame.getWords().size() == newFrame.getWordsKpts().size());
EpipolarGeometry::findPairsUnique(tmpRefFrame.getWords(), newFrame.getWords(), pairs); EpipolarGeometry::findPairsUnique(tmpRefFrame.getWords(), newFrame.getWords(), pairs);
info->refCorners.resize(pairs.size()); info->refCorners.resize(pairs.size());
info->newCorners.resize(pairs.size()); info->newCorners.resize(pairs.size());
-5
View File
@@ -793,7 +793,6 @@ Transform OdometryF2M::computeTransform(
if(!lastFrameModels.empty()) if(!lastFrameModels.empty())
{ {
UASSERT(lastFrame_->getWordsKpts().size() == lastFrame_->getWords().size());
for(std::multimap<int, int>::const_iterator iter = lastFrame_->getWords().begin(); iter!=lastFrame_->getWords().end(); ++iter) for(std::multimap<int, int>::const_iterator iter = lastFrame_->getWords().begin(); iter!=lastFrame_->getWords().end(); ++iter)
{ {
const cv::Point3f & pt = lastFrame_->getWords3()[iter->second]; const cv::Point3f & pt = lastFrame_->getWords3()[iter->second];
@@ -1560,10 +1559,6 @@ Transform OdometryF2M::computeTransform(
{ {
info->reg = regInfo.copyWithoutData(); info->reg = regInfo.copyWithoutData();
} }
if(output.isNull())
{
info->reg.covariance = cv::Mat::eye(6,6,CV_64FC1)*9999.0; // Lost
}
} }
UINFO("Odom update time = %fs lost=%s features=%d inliers=%d/%d variance:lin=%f, ang=%f local_map=%d local_scan_map=%d", UINFO("Odom update time = %fs lost=%s features=%d inliers=%d/%d variance:lin=%f, ang=%f local_map=%d local_scan_map=%d",
@@ -25,7 +25,7 @@ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include "rtabmap/core/odometry/OdometryVINSFusion.h" #include "rtabmap/core/odometry/OdometryVINS.h"
#include "rtabmap/core/OdometryInfo.h" #include "rtabmap/core/OdometryInfo.h"
#include "rtabmap/core/util3d_transforms.h" #include "rtabmap/core/util3d_transforms.h"
#include "rtabmap/utilite/ULogger.h" #include "rtabmap/utilite/ULogger.h"
@@ -35,7 +35,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "rtabmap/utilite/UDirectory.h" #include "rtabmap/utilite/UDirectory.h"
#include <opencv2/imgproc/types_c.h> #include <opencv2/imgproc/types_c.h>
#ifdef RTABMAP_VINS_FUSION #ifdef RTABMAP_VINS
#include <estimator/estimator.h> #include <estimator/estimator.h>
#include <estimator/parameters.h> #include <estimator/parameters.h>
#include <camodocal/camera_models/PinholeCamera.h> #include <camodocal/camera_models/PinholeCamera.h>
@@ -45,11 +45,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace rtabmap { namespace rtabmap {
#ifdef RTABMAP_VINS_FUSION #ifdef RTABMAP_VINS
class VinsFusionEstimator: public Estimator class VinsEstimator: public Estimator
{ {
public: public:
VinsFusionEstimator( VinsEstimator(
const Transform & imuLocalTransform, const Transform & imuLocalTransform,
const StereoCameraModel & model, const StereoCameraModel & model,
bool rectified) : Estimator() bool rectified) : Estimator()
@@ -57,9 +57,6 @@ public:
MULTIPLE_THREAD = 0; MULTIPLE_THREAD = 0;
setParameter(); setParameter();
ROW=model.left().imageHeight();
COL=model.left().imageWidth();
//overwrite camera calibration only if received model is radtan, otherwise use config //overwrite camera calibration only if received model is radtan, otherwise use config
UASSERT(NUM_OF_CAM >= 1 && NUM_OF_CAM <=2); UASSERT(NUM_OF_CAM >= 1 && NUM_OF_CAM <=2);
@@ -84,15 +81,6 @@ public:
camera->setParameters(params); camera->setParameters(params);
featureTracker.m_camera.push_back(camera); featureTracker.m_camera.push_back(camera);
double originalParalax = MIN_PARALLAX * FOCAL_LENGTH;
// If you have compiler error about FOCAL_LENGTH being const, make sure to use the following patch:
// https://gist.github.com/matlabbe/795ab37067367dca58bbadd8201d986c#file-vins-fusion_pull136-patch
FOCAL_LENGTH = params.fx();
MIN_PARALLAX = originalParalax / FOCAL_LENGTH;
ProjectionTwoFrameOneCamFactor::sqrt_info = FOCAL_LENGTH / 1.5 * Matrix2d::Identity();
ProjectionTwoFrameTwoCamFactor::sqrt_info = FOCAL_LENGTH / 1.5 * Matrix2d::Identity();
ProjectionOneFrameTwoCamFactor::sqrt_info = FOCAL_LENGTH / 1.5 * Matrix2d::Identity();
if(NUM_OF_CAM == 2) if(NUM_OF_CAM == 2)
{ {
camodocal::PinholeCameraPtr camera( new camodocal::PinholeCamera ); camodocal::PinholeCameraPtr camera( new camodocal::PinholeCamera );
@@ -132,8 +120,8 @@ public:
Transform imuCam0 = imuLocalTransform.inverse() * model.localTransform(); Transform imuCam0 = imuLocalTransform.inverse() * model.localTransform();
tic[0] = TIC[0] = Vector3d(imuCam0.x(), imuCam0.y(), imuCam0.z()); tic[0] = Vector3d(imuCam0.x(), imuCam0.y(), imuCam0.z());
ric[0] = RIC[0] = imuCam0.toEigen4d().block<3,3>(0,0); ric[0] = imuCam0.toEigen4d().block<3,3>(0,0);
if(NUM_OF_CAM == 2) if(NUM_OF_CAM == 2)
{ {
@@ -152,41 +140,56 @@ public:
UASSERT(!cam0cam1.isNull()); UASSERT(!cam0cam1.isNull());
Transform imuCam1 = imuCam0 * cam0cam1; Transform imuCam1 = imuCam0 * cam0cam1;
tic[1] = TIC[0] = Vector3d(imuCam1.x(), imuCam1.y(), imuCam1.z()); tic[1] = Vector3d(imuCam1.x(), imuCam1.y(), imuCam1.z());
ric[1] = RIC[0] = imuCam1.toEigen4d().block<3,3>(0,0); ric[1] = imuCam1.toEigen4d().block<3,3>(0,0);
} }
for (int i = 0; i < NUM_OF_CAM; i++) for (int i = 0; i < NUM_OF_CAM; i++)
{ {
cout << " new extrinsic cam " << i << endl << ric[i] << endl << tic[i].transpose() << endl; cout << " exitrinsic cam " << i << endl << ric[i] << endl << tic[i].transpose() << endl;
}
for (int i = 0; i < NUM_OF_CAM; i++)
{
cout << " new intrinsic cam " << i << endl << featureTracker.m_camera[i]->parametersToString() << endl;
} }
f_manager.setRic(ric); f_manager.setRic(ric);
ProjectionTwoFrameOneCamFactor::sqrt_info = FOCAL_LENGTH / 1.5 * Matrix2d::Identity();
ProjectionTwoFrameTwoCamFactor::sqrt_info = FOCAL_LENGTH / 1.5 * Matrix2d::Identity();
ProjectionOneFrameTwoCamFactor::sqrt_info = FOCAL_LENGTH / 1.5 * Matrix2d::Identity();
td = TD;
g = G;
cout << "set g " << g.transpose() << endl;
} }
// Copy of original inputImage() so that overridden processMeasurements() is used and threading is disabled. // Copy of original inputImage() so that overridden processMeasurements() is used and threading is disabled.
void inputImage(double t, const cv::Mat &_img, const cv::Mat &_img1) void inputImage(double t, const cv::Mat &_img, const cv::Mat &_img1)
{ {
TicToc processTime;
inputImageCnt++; inputImageCnt++;
map<int, vector<pair<int, Eigen::Matrix<double, 7, 1>>>> featureFrame; map<int, vector<pair<int, Eigen::Matrix<double, 7, 1>>>> featureFrame;
if(_img1.empty()) { TicToc featureTrackerTime;
if(_img1.empty())
featureFrame = featureTracker.trackImage(t, _img); featureFrame = featureTracker.trackImage(t, _img);
} else
else {
featureFrame = featureTracker.trackImage(t, _img, _img1); featureFrame = featureTracker.trackImage(t, _img, _img1);
} //printf("featureTracker time: %f\n", featureTrackerTime.toc());
//if(MULTIPLE_THREAD)
//{
// if(inputImageCnt % 2 == 0)
// {
// mBuf.lock();
// featureBuf.push(make_pair(t, featureFrame));
// mBuf.unlock();
// }
//}
//else
{
mBuf.lock(); mBuf.lock();
featureBuf.push(make_pair(t, featureFrame)); featureBuf.push(make_pair(t, featureFrame));
mBuf.unlock(); mBuf.unlock();
TicToc processTime;
processMeasurements(); processMeasurements();
UDEBUG("VINS process time: %f", processTime.toc()); UDEBUG("VINS process time: %f", processTime.toc());
} }
}
// Copy of original inputIMU() but with publisher commented // Copy of original inputIMU() but with publisher commented
void inputIMU(double t, const Vector3d &linearAcceleration, const Vector3d &angularVelocity) void inputIMU(double t, const Vector3d &linearAcceleration, const Vector3d &angularVelocity)
{ {
@@ -196,28 +199,37 @@ public:
//printf("input imu with time %f \n", t); //printf("input imu with time %f \n", t);
mBuf.unlock(); mBuf.unlock();
if (solver_flag == NON_LINEAR)
{
mPropagate.lock();
fastPredictIMU(t, linearAcceleration, angularVelocity); fastPredictIMU(t, linearAcceleration, angularVelocity);
mPropagate.unlock(); //if (solver_flag == NON_LINEAR)
} // pubLatestOdometry(latest_P, latest_Q, latest_V, t);
} }
// Copy of original processMeasurements() but with publishers commented and threading disabled // Copy of original processMeasurements() but with publishers commented and threading disabled
void processMeasurements() void processMeasurements()
{ {
//while (1)
{
//printf("process measurments\n");
pair<double, map<int, vector<pair<int, Eigen::Matrix<double, 7, 1> > > > > feature; pair<double, map<int, vector<pair<int, Eigen::Matrix<double, 7, 1> > > > > feature;
vector<pair<double, Eigen::Vector3d>> accVector, gyrVector; vector<pair<double, Eigen::Vector3d>> accVector, gyrVector;
if(!featureBuf.empty()) if(!featureBuf.empty())
{ {
feature = featureBuf.front(); feature = featureBuf.front();
curTime = feature.first + td; curTime = feature.first + td;
if (USE_IMU && !IMUAvailable(feature.first + td)) //while(1)
//{
if (!((!USE_IMU || IMUAvailable(feature.first + td))))
//if ((!USE_IMU || IMUAvailable(feature.first + td)))
// break;
//else
{ {
printf("wait for imu ... \n"); printf("wait for imu ... \n");
//if (! MULTIPLE_THREAD)
return; return;
//std::chrono::milliseconds dura(5);
//std::this_thread::sleep_for(dura);
} }
//}
mBuf.lock(); mBuf.lock();
if(USE_IMU) if(USE_IMU)
getIMUInterval(prevTime, curTime, accVector, gyrVector); getIMUInterval(prevTime, curTime, accVector, gyrVector);
@@ -229,7 +241,7 @@ public:
{ {
if(!initFirstPoseFlag) if(!initFirstPoseFlag)
initFirstIMUPose(accVector); initFirstIMUPose(accVector);
UDEBUG("accVector.size() = %d", accVector.size());
for(size_t i = 0; i < accVector.size(); i++) for(size_t i = 0; i < accVector.size(); i++)
{ {
double dt; double dt;
@@ -242,52 +254,72 @@ public:
processIMU(accVector[i].first, dt, accVector[i].second, gyrVector[i].second); processIMU(accVector[i].first, dt, accVector[i].second, gyrVector[i].second);
} }
} }
mProcess.lock();
processImage(feature.second, feature.first); processImage(feature.second, feature.first);
prevTime = curTime; prevTime = curTime;
mProcess.unlock();
printStatistics(*this, 0);
//std_msgs::Header header;
//header.frame_id = "world";
//header.stamp = ros::Time(feature.first);
//pubOdometry(*this, header);
//pubKeyPoses(*this, header);
//pubCameraPose(*this, header);
//pubPointCloud(*this, header);
//pubKeyframe(*this);
//pubTF(*this, header);
}
//if (! MULTIPLE_THREAD)
// break;
//std::chrono::milliseconds dura(2);
//std::this_thread::sleep_for(dura);
} }
} }
}; };
#endif #endif
OdometryVINSFusion::OdometryVINSFusion(const ParametersMap & parameters) : OdometryVINS::OdometryVINS(const ParametersMap & parameters) :
Odometry(parameters) Odometry(parameters)
#ifdef RTABMAP_VINS_FUSION #ifdef RTABMAP_VINS
, ,
vinsEstimator_(0), vinsEstimator_(0),
initGravity_(false), initGravity_(false),
previousPose_(Transform::getIdentity()) previousPose_(Transform::getIdentity())
#endif #endif
{ {
#ifdef RTABMAP_VINS_FUSION #ifdef RTABMAP_VINS
// intialize // intialize
std::string configFilename; std::string configFilename;
Parameters::parse(parameters, Parameters::kOdomVINSFusionConfigPath(), configFilename); Parameters::parse(parameters, Parameters::kOdomVINSConfigPath(), configFilename);
if(configFilename.empty()) if(configFilename.empty())
{ {
UERROR("VINS config file is empty (%s)!", UERROR("VINS config file is empty (%s=%s)!",
Parameters::kOdomVINSFusionConfigPath().c_str()); Parameters::kOdomVINSConfigPath().c_str(),
Parameters::kOdomVINSConfigPath().c_str());
} }
else else
{ {
UINFO("Using config file %s", configFilename.c_str());
readParameters(uReplaceChar(configFilename, '~', UDirectory::homeDir())); readParameters(uReplaceChar(configFilename, '~', UDirectory::homeDir()));
} }
#endif #endif
} }
OdometryVINSFusion::~OdometryVINSFusion() OdometryVINS::~OdometryVINS()
{ {
#ifdef RTABMAP_VINS_FUSION #ifdef RTABMAP_VINS
delete vinsEstimator_; delete vinsEstimator_;
#endif #endif
} }
void OdometryVINSFusion::reset(const Transform & initialPose) void OdometryVINS::reset(const Transform & initialPose)
{ {
Odometry::reset(initialPose); Odometry::reset(initialPose);
#ifdef RTABMAP_VINS_FUSION #ifdef RTABMAP_VINS
if(!initGravity_) if(!initGravity_)
{ {
delete vinsEstimator_; delete vinsEstimator_;
@@ -301,19 +333,18 @@ void OdometryVINSFusion::reset(const Transform & initialPose)
} }
// return not null transform if odometry is correctly computed // return not null transform if odometry is correctly computed
Transform OdometryVINSFusion::computeTransform( Transform OdometryVINS::computeTransform(
SensorData & data, SensorData & data,
const Transform & guess, const Transform & guess,
OdometryInfo * info) OdometryInfo * info)
{ {
Transform t; Transform t;
#ifdef RTABMAP_VINS_FUSION #ifdef RTABMAP_VINS
UTimer timer; UTimer timer;
bool hasImage = !data.imageRaw().empty() && !data.rightRaw().empty() && data.stereoCameraModels().size() == 1 && data.stereoCameraModels()[0].isValidForProjection();
if(USE_IMU!=0 && !data.imu().empty()) if(USE_IMU!=0 && !data.imu().empty())
{ {
double t = data.stamp();
double dx = data.imu().linearAcceleration().val[0]; double dx = data.imu().linearAcceleration().val[0];
double dy = data.imu().linearAcceleration().val[1]; double dy = data.imu().linearAcceleration().val[1];
double dz = data.imu().linearAcceleration().val[2]; double dz = data.imu().linearAcceleration().val[2];
@@ -327,19 +358,16 @@ Transform OdometryVINSFusion::computeTransform(
if(vinsEstimator_ != 0) if(vinsEstimator_ != 0)
{ {
vinsEstimator_->inputIMU(data.stamp(), acc, gyr); vinsEstimator_->inputIMU(t, acc, gyr);
} }
else else
{ {
lastImu_ = data.imu(); lastImu_ = data.imu();
lastImuStamp_ = data.stamp();
if(!hasImage) {
UWARN("Waiting an image for initialization..."); UWARN("Waiting an image for initialization...");
} }
} }
}
if(hasImage) if(!data.imageRaw().empty() && !data.rightRaw().empty() && data.stereoCameraModels().size() == 1 && data.stereoCameraModels()[0].isValidForProjection())
{ {
if(USE_IMU==1 && lastImu_.localTransform().isNull()) if(USE_IMU==1 && lastImu_.localTransform().isNull())
{ {
@@ -349,23 +377,10 @@ Transform OdometryVINSFusion::computeTransform(
if(vinsEstimator_ == 0) if(vinsEstimator_ == 0)
{ {
// intialize // intialize
UINFO("Initializing with image %f", data.stamp()); vinsEstimator_ = new VinsEstimator(
vinsEstimator_ = new VinsFusionEstimator(
lastImu_.localTransform().isNull()?Transform::getIdentity():lastImu_.localTransform(), lastImu_.localTransform().isNull()?Transform::getIdentity():lastImu_.localTransform(),
data.stereoCameraModels()[0], data.stereoCameraModels()[0],
this->imagesAlreadyRectified()); this->imagesAlreadyRectified());
if(USE_IMU) {
double dx = lastImu_.linearAcceleration().val[0];
double dy = lastImu_.linearAcceleration().val[1];
double dz = lastImu_.linearAcceleration().val[2];
double rx = lastImu_.angularVelocity().val[0];
double ry = lastImu_.angularVelocity().val[1];
double rz = lastImu_.angularVelocity().val[2];
Vector3d acc(dx, dy, dz);
Vector3d gyr(rx, ry, rz);
vinsEstimator_->inputIMU(lastImuStamp_, acc, gyr);
}
} }
UDEBUG("Image update stamp=%f", data.stamp()); UDEBUG("Image update stamp=%f", data.stamp());
@@ -440,45 +455,36 @@ Transform OdometryVINSFusion::computeTransform(
info->reg.covariance = cv::Mat::eye(6,6, CV_64FC1); info->reg.covariance = cv::Mat::eye(6,6, CV_64FC1);
info->reg.covariance *= this->framesProcessed() == 0?9999:0.0001; info->reg.covariance *= this->framesProcessed() == 0?9999:0.0001;
// feature map: based on code from pubPointCloud() of vins's visualization.cpp // feature map
Transform fixT = this->getPose()*previousPoseInv;
for (auto &it_per_id : vinsEstimator_->f_manager.feature) for (auto &it_per_id : vinsEstimator_->f_manager.feature)
{ {
if(it_per_id.feature_per_frame.size() < 2) { int used_num;
// feature just added but not tracked, or old feature not tracked anymore used_num = it_per_id.feature_per_frame.size();
if (!(used_num >= 2 && it_per_id.start_frame < WINDOW_SIZE - 2))
continue;
if (it_per_id.start_frame > WINDOW_SIZE * 3.0 / 4.0 || it_per_id.solve_flag != 1)
continue; continue;
}
int imu_i = it_per_id.start_frame; int imu_i = it_per_id.start_frame;
Vector3d pts_i = it_per_id.feature_per_frame[0].point * it_per_id.estimated_depth; Vector3d pts_i = it_per_id.feature_per_frame[it_per_id.feature_per_frame.size()-1].point * it_per_id.estimated_depth;
Vector3d w_pts_i = vinsEstimator_->Rs[imu_i] * (vinsEstimator_->ric[0] * pts_i + vinsEstimator_->tic[0]) + vinsEstimator_->Ps[imu_i]; Vector3d w_pts_i = vinsEstimator_->Rs[imu_i] * (vinsEstimator_->ric[0] * pts_i + vinsEstimator_->tic[0]) + vinsEstimator_->Ps[imu_i];
cv::Point3f p; cv::Point3f p;
p.x = w_pts_i(0); p.x = w_pts_i(0);
p.y = w_pts_i(1); p.y = w_pts_i(1);
p.z = w_pts_i(2); p.z = w_pts_i(2);
p = util3d::transformPoint(p, fixT);
info->localMap.insert(std::make_pair(it_per_id.feature_id, p));
int featureIndex = info->localMap.size(); if(this->imagesAlreadyRectified())
info->localMap.insert(std::make_pair(featureIndex, p)); {
cv::Point2f pt;
FeaturePerFrame & refFrame = it_per_id.feature_per_frame[0]; // First frame it was seen data.stereoCameraModels()[0].left().reproject(pts_i(0), pts_i(1), pts_i(2), pt.x, pt.y);
FeaturePerFrame & newFrame = it_per_id.feature_per_frame[it_per_id.feature_per_frame.size()-1]; // Last frame it was seen (not necessary in last frame) info->reg.inliersIDs.push_back(info->newCorners.size());
cv::Point2f refUV(refFrame.uv[0], refFrame.uv[1]); info->newCorners.push_back(pt);
cv::Point2f newUV(newFrame.uv[0], newFrame.uv[1]);
info->refCorners.push_back(refUV);
info->newCorners.push_back(newUV);
info->reg.matchesIDs.push_back(featureIndex);
if(it_per_id.solve_flag > 0) {
// Feature correctly tracked
info->words.insert(std::make_pair(featureIndex, cv::KeyPoint(newUV, 3.0f)));
info->cornerInliers.push_back(featureIndex);
info->reg.inliersIDs.push_back(featureIndex);
} }
++featureIndex;
} }
info->features = info->localMap.size(); info->features = info->newCorners.size();
info->reg.inliers = info->reg.inliersIDs.size();
info->localMapSize = info->localMap.size(); info->localMapSize = info->localMap.size();
} }
UINFO("Odom update time = %fs p=%s", timer.elapsed(), p.prettyPrint().c_str()); UINFO("Odom update time = %fs p=%s", timer.elapsed(), p.prettyPrint().c_str());
@@ -486,7 +492,7 @@ Transform OdometryVINSFusion::computeTransform(
} }
else else
{ {
UWARN("VINS-Fusion not yet initialized... needing more data."); UWARN("VINS not yet initialized... waiting to get enough IMU messages");
} }
} }
else if(!data.imageRaw().empty() && !data.depthRaw().empty()) else if(!data.imageRaw().empty() && !data.depthRaw().empty())
+1 -1
View File
@@ -197,7 +197,7 @@ std::map<int, Transform> OptimizerCeres::optimize(
if(angle_local_manifold == NULL) if(angle_local_manifold == NULL)
{ {
angle_local_manifold = ceres::examples::AngleManifold::Create(); angle_local_manifold = ceres::examples::AngleManfold::Create();
} }
SetCeresProblemManifold(problem, &pose_begin_iter->second.yaw_radians, angle_local_manifold); SetCeresProblemManifold(problem, &pose_begin_iter->second.yaw_radians, angle_local_manifold);
SetCeresProblemManifold(problem, &pose_end_iter->second.yaw_radians, angle_local_manifold); SetCeresProblemManifold(problem, &pose_end_iter->second.yaw_radians, angle_local_manifold);
+6 -6
View File
@@ -74,8 +74,8 @@ public:
friend class boost::serialization::access; friend class boost::serialization::access;
template<class ARCHIVE> template<class ARCHIVE>
void serialize(ARCHIVE & ar, const unsigned int /*version*/) { void serialize(ARCHIVE & ar, const unsigned int /*version*/) {
/*ar & boost::serialization::make_nvp("nZ_", const_cast<Unit3&>(nZ_)); ar & boost::serialization::make_nvp("nZ_", const_cast<Unit3&>(nZ_));
ar & boost::serialization::make_nvp("bRef_", const_cast<Unit3&>(bRef_));*/ ar & boost::serialization::make_nvp("bRef_", const_cast<Unit3&>(bRef_));
} }
#endif #endif
}; };
@@ -158,10 +158,10 @@ private:
friend class boost::serialization::access; friend class boost::serialization::access;
template<class ARCHIVE> template<class ARCHIVE>
void serialize(ARCHIVE & ar, const unsigned int /*version*/) { void serialize(ARCHIVE & ar, const unsigned int /*version*/) {
/*ar & boost::serialization::make_nvp("NoiseModelFactor1", ar & boost::serialization::make_nvp("NoiseModelFactor1",
boost::serialization::base_object<Base>(*this)); boost::serialization::base_object<Base>(*this));
ar & boost::serialization::make_nvp("GravityFactor", ar & boost::serialization::make_nvp("GravityFactor",
boost::serialization::base_object<GravityFactor>(*this));*/ boost::serialization::base_object<GravityFactor>(*this));
} }
#endif #endif
@@ -254,10 +254,10 @@ private:
friend class boost::serialization::access; friend class boost::serialization::access;
template<class ARCHIVE> template<class ARCHIVE>
void serialize(ARCHIVE & ar, const unsigned int /*version*/) { void serialize(ARCHIVE & ar, const unsigned int /*version*/) {
/*ar & boost::serialization::make_nvp("NoiseModelFactor1", ar & boost::serialization::make_nvp("NoiseModelFactor1",
boost::serialization::base_object<Base>(*this)); boost::serialization::base_object<Base>(*this));
ar & boost::serialization::make_nvp("GravityFactor", ar & boost::serialization::make_nvp("GravityFactor",
boost::serialization::base_object<GravityFactor>(*this));*/ boost::serialization::base_object<GravityFactor>(*this));
} }
#endif #endif
public: public:
@@ -133,8 +133,6 @@ CREATE TABLE Admin (
opt_map_y_min FLOAT, opt_map_y_min FLOAT,
opt_map_resolution FLOAT, opt_map_resolution FLOAT,
dictionary_index BLOB, -- serialized dictionary index
time_enter DATE time_enter DATE
); );
@@ -1,183 +0,0 @@
-- *******************************************************************
-- DatabaseSchema: Script for creating the database
-- Usage:
-- $ sqlite3 LTM.db < DatabaseSchema.sql
--
-- *******************************************************************
-- *******************************************************************
-- CLEAN
-- *******************************************************************
/*DROP TABLE Node;*/
-- *******************************************************************
-- CREATE
-- *******************************************************************
CREATE TABLE Node (
id INTEGER NOT NULL,
map_id INTEGER NOT NULL,
weight INTEGER,
stamp FLOAT,
pose BLOB, -- 3x4 float
ground_truth_pose BLOB, -- 3x4 float
velocity BLOB, -- 6 float (vx,vy,vz,vroll,vpitch,vyaw) m/s and rad/s
label TEXT,
gps BLOB, -- 1x6 double: stamp, longitude (DD), latitude (DD), altitude (m), accuracy (m), bearing (North 0->360 deg clockwise)
env_sensors BLOB, -- Variable 3xdouble: (sensorId1, value, stamp, sensorId2, value, stamp, ...)
time_enter DATE,
PRIMARY KEY (id)
);
CREATE TABLE Data (
id INTEGER NOT NULL,
image BLOB, -- compressed image (Grayscale or RGB)
depth BLOB, -- compressed image (Depth or Right image)
depth_confidence BLOB, -- compressed data (low=0 high=100)
calibration BLOB, -- fx, fy, cx, cy, [baseline,] width, height, local_transform
scan BLOB, -- compressed data (Laser scan)
scan_info BLOB, -- scan_max_pts, scan_max_range, scan_format, local_transform
ground_cells BLOB, -- compressed data (occupancy grid)
obstacle_cells BLOB, -- compressed data (occupancy grid)
empty_cells BLOB, -- compressed data (occupancy grid)
cell_size FLOAT,
view_point_x FLOAT,
view_point_y FLOAT,
view_point_z FLOAT,
user_data BLOB, -- compressed data (User data)
time_enter DATE,
PRIMARY KEY (id)
);
CREATE TABLE Link (
from_id INTEGER NOT NULL,
to_id INTEGER NOT NULL,
type INTEGER NOT NULL, -- kNeighbor=0, kGlobalClosure=1, kLocalSpaceClosure=2, kLocalTimeClosure=3, kUserClosure=4, kVirtualClosure=5, kNeighborMerged=6, kPosePrior=7, kLandmark=8
information_matrix BLOB NOT NULL, -- 6x6 double (inverse covariance)
transform BLOB, -- 3x4 float
user_data BLOB, -- compressed data (User data)
FOREIGN KEY (from_id) REFERENCES Node(id),
FOREIGN KEY (to_id) REFERENCES Node(id)
);
--
CREATE TABLE Word (
id INTEGER NOT NULL,
descriptor_size INTEGER NOT NULL,
descriptor BLOB NOT NULL,
time_enter DATE,
PRIMARY KEY (id)
);
CREATE TABLE Feature (
node_id INTEGER NOT NULL,
word_id INTEGER NOT NULL,
pos_x FLOAT NOT NULL,
pos_y FLOAT NOT NULL,
size INTEGER NOT NULL,
dir FLOAT NOT NULL,
response FLOAT NOT NULL,
octave INTEGER NOT NULL,
depth_x FLOAT,
depth_y FLOAT,
depth_z FLOAT,
descriptor_size INTEGER,
descriptor BLOB,
FOREIGN KEY (node_id) REFERENCES Node(id)
);
CREATE TABLE GlobalDescriptor (
node_id INTEGER NOT NULL,
type INTEGER NOT NULL,
info BLOB,
data BLOB NOT NULL,
FOREIGN KEY (node_id) REFERENCES Node(id)
);
--
CREATE TABLE Info (
STM_size INTEGER,
last_sign_added INTEGER,
process_mem_used INTEGER,
database_mem_used INTEGER,
dictionary_size INTEGER,
parameters TEXT,
time_enter DATE
);
CREATE TABLE Statistics (
id INTEGER NOT NULL,
stamp FLOAT,
data BLOB, -- compressed string
wm_state BLOB, -- compressed data
FOREIGN KEY (id) REFERENCES Node(id)
);
CREATE TABLE Admin (
version TEXT,
preview_image BLOB, -- compressed image
opt_cloud BLOB, -- compressed data
opt_ids BLOB, -- Node ids used to generate the optimized cloud/mesh
opt_poses BLOB, -- compressed N*3x4 float
opt_last_localization BLOB, -- 3x4 float
opt_polygons_size INTEGER, -- e.g., 3
opt_polygons BLOB, -- compressed data [length_v0, i0,i1,i3, length_v1, i0,i1,i3]
opt_tex_coords BLOB, -- compressed data [length_v0, u0,v0,u1,v1,u2,v2, length_v1, u0,v0,u1,v1,u2,v2]
opt_tex_materials BLOB, -- compressed image
opt_map BLOB, -- compressed CV_8SC1 occupancy grid
opt_map_x_min FLOAT,
opt_map_y_min FLOAT,
opt_map_resolution FLOAT,
time_enter DATE
);
-- *******************************************************************
-- TRIGGERS
-- *******************************************************************
CREATE TRIGGER insert_Feature BEFORE INSERT ON Feature
WHEN NOT EXISTS (SELECT Node.id FROM Node WHERE Node.id = NEW.node_id)
BEGIN
SELECT RAISE(ABORT, 'Foreign key constraint failed in Feature table');
END;
-- Creating a trigger for time_enter
CREATE TRIGGER insert_Node_timeEnter AFTER INSERT ON Node
BEGIN
UPDATE Node SET time_enter = DATETIME('NOW') WHERE rowid = new.rowid;
END;
CREATE TRIGGER insert_Data_timeEnter AFTER INSERT ON Data
BEGIN
UPDATE Node SET time_enter = DATETIME('NOW') WHERE rowid = new.rowid;
END;
CREATE TRIGGER insert_Word_timeEnter AFTER INSERT ON Word
BEGIN
UPDATE Word SET time_enter = DATETIME('NOW') WHERE rowid = new.rowid;
END;
CREATE TRIGGER insert_Info_timeEnter AFTER INSERT ON Info
BEGIN
UPDATE Info SET time_enter = DATETIME('NOW') WHERE rowid = new.rowid;
END;
-- *******************************************************************
-- INDEXES
-- *******************************************************************
CREATE UNIQUE INDEX IDX_Node_id on Node (id);
CREATE INDEX IDX_Feature_node_id on Feature (node_id);
CREATE INDEX IDX_GlobalDescriptor_node_id on GlobalDescriptor (node_id);
CREATE INDEX IDX_Link_from_id on Link (from_id);
CREATE UNIQUE INDEX IDX_node_label on Node (label);
CREATE UNIQUE INDEX IDX_Statistics_id on Statistics (id);
-- *******************************************************************
-- VERSION
-- *******************************************************************
INSERT INTO Admin(version) VALUES('0.22.0');
+2 -31
View File
@@ -103,6 +103,7 @@ public:
{ {
flann_algorithm_t index_type = get_param<flann_algorithm_t>(params,"algorithm"); flann_algorithm_t index_type = get_param<flann_algorithm_t>(params,"algorithm");
loaded_ = false; loaded_ = false;
if (index_type == FLANN_INDEX_SAVED) { if (index_type == FLANN_INDEX_SAVED) {
nnIndex_ = load_saved_index(features, get_param<std::string>(params,"filename"), distance); nnIndex_ = load_saved_index(features, get_param<std::string>(params,"filename"), distance);
loaded_ = true; loaded_ = true;
@@ -179,20 +180,10 @@ public:
if (fout == NULL) { if (fout == NULL) {
throw FLANNException("Cannot open file"); throw FLANNException("Cannot open file");
} }
save(fout); nnIndex_->saveIndex(fout);
fclose(fout); fclose(fout);
} }
/**
* Save index to file stream.
* Caller has to open file stream with "wb" and close it afterwards.
* @param filename
*/
void save(FILE * stream)
{
nnIndex_->saveIndex(stream);
}
/** /**
* \returns number of features in this index. * \returns number of features in this index.
*/ */
@@ -386,26 +377,6 @@ public:
return nnIndex_->radiusSearch(queries, indices, dists, radius, params); return nnIndex_->radiusSearch(queries, indices, dists, radius, params);
} }
void load_saved_index(FILE* fin)
{
if(loaded_) {
throw FLANNException("Index already loaded!");
}
if(nnIndex_->sizeAtBuild() != 0) {
throw FLANNException("Index must not be already built to load data.");
}
if (fin == NULL) {
throw FLANNException("File pointer must be valid!");
}
IndexHeader header = load_header(fin);
if (header.h.data_type != flann_datatype_value<ElementType>::value) {
throw FLANNException("Datatype of saved index is different than of the one to be loaded.");
}
rewind(fin);
nnIndex_->loadIndex(fin);
loaded_ = true;
}
private: private:
IndexType* load_saved_index(const Matrix<ElementType>& dataset, const std::string& filename, Distance distance) IndexType* load_saved_index(const Matrix<ElementType>& dataset, const std::string& filename, Distance distance)
{ {
-206
View File
@@ -1,206 +0,0 @@
# Image: introlab3it/rtabmap:android-noble-deps
FROM ubuntu:24.04
# Install build dependencies
RUN apt-get update && apt-get install -y --no-install-recommends apt-utils
RUN apt-get update && apt-get install -y \
git unzip wget ant cmake \
g++ lib32stdc++6 lib32z1 \
software-properties-common \
freeglut3-dev \
openjdk-8-jdk openjdk-8-jre \
curl
ENV ANDROID_HOME=/opt/android-sdk
ENV PATH=$PATH:/opt/android-sdk/cmdline-tools/latest/bin:/opt/android-sdk/tools:/opt/android-sdk/platform-tools:/opt/android-sdk/ndk/21.4.7075529
ENV ANDROID_NDK=/opt/android-sdk/ndk/21.4.7075529
ENV JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64
WORKDIR /root/
# Setup android sdk
RUN wget -nv https://dl.google.com/android/repository/commandlinetools-linux-7583922_latest.zip && \
unzip -qq commandlinetools-linux-7583922_latest.zip && \
rm commandlinetools-linux-7583922_latest.zip && \
mkdir $ANDROID_HOME && \
mkdir $ANDROID_HOME/cmdline-tools && \
mv cmdline-tools $ANDROID_HOME/cmdline-tools/latest
# We should use build-tools <=30 to avoid dx missing error
RUN echo y | sdkmanager --install "platform-tools" "platforms;android-23" "platforms;android-24" "platforms;android-26" "platforms;android-30" "build-tools;30.0.3" "ndk;21.4.7075529"
# we need <=r25 tools to use "android" command (now deprecated)
RUN wget -nv http://dl-ssl.google.com/android/repository/tools_r25.2.5-linux.zip && \
unzip -qq tools_r25.2.5-linux.zip && \
mv tools $ANDROID_HOME/. && \
rm tools_r25.2.5-linux.zip
##############
# Dependencies (took from docker/bionic/android/deps.bash)
##############
# Install directory for all dependencies
RUN mkdir -p /opt/android/arm64-v8a
# Boost
RUN echo "Install boost..." && \
wget -nv https://downloads.sourceforge.net/project/boost/boost/1.59.0/boost_1_59_0.tar.gz && \
tar -xzf boost_1_59_0.tar.gz && \
cd boost_1_59_0 && \
wget -nv https://gist.github.com/matlabbe/0bce8feeb73a499a76afbbcc5c687221/raw/1733253195bc4d4d9b7f9eda1e60628dc1e51429/BoostConfig.cmake.in && \
wget -nv https://gist.github.com/matlabbe/0bce8feeb73a499a76afbbcc5c687221/raw/1733253195bc4d4d9b7f9eda1e60628dc1e51429/CMakeLists.txt && \
mkdir build && \
cd build && \
cmake -DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK/build/cmake/android.toolchain.cmake -DANDROID_ABI=arm64-v8a -DANDROID_NDK=$ANDROID_NDK -DANDROID_NATIVE_API_LEVEL=23 -DBUILD_SHARED_LIBS=OFF -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/opt/android/arm64-v8a -DCMAKE_FIND_ROOT_PATH="/opt/android/arm64-v8a/bin;/opt/android/arm64-v8a;/opt/android/arm64-v8a/share" .. && \
make -j4 && \
make install && \
cd /root && \
rm -r boost_1_59_0.tar.gz boost_1_59_0
# eigen
RUN echo "Install eigen..." && \
curl -L https://gitlab.com/libeigen/eigen/-/archive/3.3.9/eigen-3.3.9.tar.gz -o 3.3.9.tar.gz && \
tar -xzf 3.3.9.tar.gz && \
cd eigen-3.3.9 && \
mkdir build && \
cd build && \
cmake -DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK/build/cmake/android.toolchain.cmake -DANDROID_ABI=arm64-v8a -DANDROID_NDK=$ANDROID_NDK -DANDROID_NATIVE_API_LEVEL=23 -DBUILD_SHARED_LIBS=OFF -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/opt/android/arm64-v8a -DCMAKE_FIND_ROOT_PATH="/opt/android/arm64-v8a/bin;/opt/android/arm64-v8a;/opt/android/arm64-v8a/share" .. && \
make -j4 && \
make install && \
cd /root && \
rm -r 3.3.9.tar.gz eigen-3.3.9
# FLANN
RUN echo "Install flann..." && \
git clone -b 1.8.4 https://github.com/mariusmuja/flann.git && \
cd flann && \
wget -nv https://gist.githubusercontent.com/matlabbe/cacff9f8271d0c42acd622939a26cab4/raw/85baf4927b32844ebd7f8eccce421bde181cd190/flann_1_8_4_android_fix.patch && \
git apply flann_1_8_4_android_fix.patch && \
mkdir build && \
cd build && \
cmake -DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK/build/cmake/android.toolchain.cmake -DANDROID_ABI=arm64-v8a -DANDROID_NDK=$ANDROID_NDK -DANDROID_NATIVE_API_LEVEL=23 -DBUILD_SHARED_LIBS=OFF -DBUILD_PYTHON_BINDINGS=OFF -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/opt/android/arm64-v8a -DCMAKE_FIND_ROOT_PATH="/opt/android/arm64-v8a/bin;/opt/android/arm64-v8a;/opt/android/arm64-v8a/share" .. && \
make -j4 && \
make install && \
cd /root && \
rm -rf flann
# GTSAM
RUN echo "Install gtsam..." && \
git clone https://bitbucket.org/gtborg/gtsam.git && \
cd gtsam && \
git checkout fbb9d3bdda8b88df51896bc401bfd170573e66f5 && \
wget -nv https://gist.github.com/matlabbe/726b490c658afd3293f4b3f2f501b863/raw/df09fc8e238a495d66b062d92dc1c1fb20a581e8/gtsam_GKlib_android_fix.patch && \
git apply gtsam_GKlib_android_fix.patch && \
mkdir build && \
cd build && \
cmake -DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK/build/cmake/android.toolchain.cmake -DANDROID_ABI=arm64-v8a -DANDROID_NDK=$ANDROID_NDK -DANDROID_NATIVE_API_LEVEL=23 -DBUILD_SHARED_LIBS=OFF -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/opt/android/arm64-v8a -DCMAKE_FIND_ROOT_PATH="/opt/android/arm64-v8a/bin;/opt/android/arm64-v8a;/opt/android/arm64-v8a/share" -DMETIS_SHARED=OFF -DGTSAM_BUILD_STATIC_LIBRARY=ON -DGTSAM_BUILD_TESTS=OFF -DGTSAM_BUILD_EXAMPLES_ALWAYS=OFF -DGTSAM_USE_SYSTEM_EIGEN=ON .. && \
make -j4 && \
make install && \
cd /root && \
rm -rf gtsam
# g2o
RUN echo "Install g2o..." && \
git clone https://github.com/RainerKuemmerle/g2o.git && \
cd g2o && \
git checkout a3f7706bdbb849b2808dc3e1b7aee189f63b498e && \
mkdir build && \
cd build && \
cmake -DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK/build/cmake/android.toolchain.cmake -DANDROID_ABI=arm64-v8a -DANDROID_NDK=$ANDROID_NDK -DANDROID_NATIVE_API_LEVEL=23 -DBUILD_SHARED_LIBS=OFF -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/opt/android/arm64-v8a -DCMAKE_FIND_ROOT_PATH="/opt/android/arm64-v8a/bin;/opt/android/arm64-v8a;/opt/android/arm64-v8a/share" -DBUILD_LGPL_SHARED_LIBS=OFF -DG2O_BUILD_APPS=OFF -DG2O_BUILD_EXAMPLES=OFF -DG2O_USE_OPENGL=OFF .. && \
make -j4 && \
make install && \
cd /root && \
rm -rf g2o
# VTK
RUN echo "Install VTK..." && \
git clone https://github.com/Kitware/VTK.git && \
cd VTK && \
git checkout tags/v8.2.0 && \
wget https://gist.github.com/matlabbe/e217259fb8ece9ee6daf5a8f70e896a0/raw/2214b503a537d6431d764526b5b780f07d6f168d/vtk_8_2_0_android_r21_fix.patch && \
git apply vtk_8_2_0_android_r21_fix.patch && \
mkdir build && \
cd build && \
cmake -DBUILD_EXAMPLES=OFF -DBUILD_TESTING=OFF -DVTK_ANDROID_BUILD=ON -DBUILD_SHARED_LIBS=OFF -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/opt/android/arm64-v8a -DANDROID_ARCH_ABI=arm64-v8a -DCMAKE_FIND_ROOT_PATH="/opt/android/arm64-v8a/bin;/opt/android/arm64-v8a;/opt/android/arm64-v8a/share" .. && \
make -j4 && \
cp -r CMakeExternals/Install/vtk-android/* /opt/android/arm64-v8a/. && \
cd /root && \
rm -rf VTK
# PCL
RUN echo "Install pcl..." && \
git clone https://github.com/PointCloudLibrary/pcl.git && \
cd pcl && \
git checkout tags/pcl-1.8.0 && \
wget https://gist.github.com/matlabbe/41812e50e459b2f27b331a2343569e5d/raw/b2fc0c4d1cfffb3a9f2811abae782e317c539bfb/pcl_1_8_0_vtk_android_support.patch && \
git apply pcl_1_8_0_vtk_android_support.patch && \
mkdir build && \
cd build && \
# do it 2 times because there is a cmake error on the first time and not the second time!?
cmake -DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK/build/cmake/android.toolchain.cmake -DANDROID_ABI=arm64-v8a -DANDROID_NDK=$ANDROID_NDK -DANDROID_NATIVE_API_LEVEL=23 -DBUILD_SHARED_LIBS=OFF -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/opt/android/arm64-v8a -DCMAKE_FIND_ROOT_PATH="/opt/android/arm64-v8a/bin;/opt/android/arm64-v8a;/opt/android/arm64-v8a/share" -DBUILD_apps=OFF -DBUILD_examples=OFF -DBUILD_tools=OFF -DBUILD_visualization=OFF -DBUILD_tracking=OFF -DBUILD_people=OFF -DBUILD_tools=OFF -DBUILD_global_tests=OFF -DWITH_QT=OFF -DWITH_OPENGL=OFF -DWITH_VTK=ON -DPCL_SHARED_LIBS=OFF .. || true && \
cmake -DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK/build/cmake/android.toolchain.cmake -DANDROID_ABI=arm64-v8a -DANDROID_NDK=$ANDROID_NDK -DANDROID_NATIVE_API_LEVEL=23 -DBUILD_SHARED_LIBS=OFF -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/opt/android/arm64-v8a -DCMAKE_FIND_ROOT_PATH="/opt/android/arm64-v8a/bin;/opt/android/arm64-v8a;/opt/android/arm64-v8a/share" -DBUILD_apps=OFF -DBUILD_examples=OFF -DBUILD_tools=OFF -DBUILD_visualization=OFF -DBUILD_tracking=OFF -DBUILD_people=OFF -DBUILD_tools=OFF -DBUILD_global_tests=OFF -DWITH_QT=OFF -DWITH_OPENGL=OFF -DWITH_VTK=ON -DPCL_SHARED_LIBS=OFF .. && \
make -j4 && \
make install && \
cd /root && \
rm -rf pcl
# make sure opencv is using the shared version of zlib
# see https://github.com/android/ndk/issues/1179
RUN mv $ANDROID_NDK/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/aarch64-linux-android/libz.a $ANDROID_NDK/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/aarch64-linux-android/libz.a.back
# OpenCV
RUN echo "Install OpenCV..." && \
git clone https://github.com/opencv/opencv_contrib.git && \
git clone https://github.com/opencv/opencv.git && \
cd opencv_contrib && \
git checkout tags/4.5.5 && \
cd /root && \
cd opencv && \
git checkout tags/4.5.5 && \
mkdir build && \
cd build && \
cmake -DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK/build/cmake/android.toolchain.cmake -DANDROID_ABI=arm64-v8a -DANDROID_NDK=$ANDROID_NDK -DANDROID_NATIVE_API_LEVEL=23 -DBUILD_SHARED_LIBS=OFF -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/opt/android/arm64-v8a -DCMAKE_FIND_ROOT_PATH="/opt/android/arm64-v8a/bin;/opt/android/arm64-v8a;/opt/android/arm64-v8a/share" -DOPENCV_EXTRA_MODULES_PATH=/root/opencv_contrib/modules -DBUILD_TESTS=OFF -DBUILD_PERF_TESTS=OFF -DWITH_CUDA=OFF -DBUILD_opencv_structured_light=OFF -DBUILD_ANDROID_PROJECTS=OFF -DOPENCV_ENABLE_NONFREE=ON -DBUILD_ANDROID_EXAMPLES=OFF -DWITH_PROTOBUF=OFF -DBUILD_opencv_stereo=OFF -DBUILD_JAVA=OFF -DWITH_QUIRC=OFF -DBUILD_opencv_js_bindings_generator=OFF -DBUILD_opencv_objc_bindings_generator=OFF -DBUILD_opencv_objdetect=OFF -DBUILD_opencv_xobjdetect=OFF .. && \
make -j4 && \
make install && \
cd /root && \
rm -rf opencv opencv_contrib
RUN echo "Strip libraries..." && \
$ANDROID_NDK/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android-strip -g -S -d --strip-debug --verbose /opt/android/arm64-v8a/lib/*.a && \
$ANDROID_NDK/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android-strip -g -S -d --strip-debug --verbose /opt/android/arm64-v8a/sdk/native/staticlibs/arm64-v8a/*.a
RUN mkdir /opt/android/lib
# tango
RUN wget 'https://docs.google.com/uc?authuser=0&id=12rHHkYM5k-UnQn-xGXs9JqYWhSXrgJr3&export=download' -O TangoSDK_Ikariotikos_C.zip && \
unzip -qq TangoSDK_Ikariotikos_C.zip && \
rm TangoSDK_Ikariotikos_C.zip && \
cp -r lib_tango_client_api/include/* /opt/android/arm64-v8a/include/. && \
cp -r lib_tango_client_api/lib/arm64-v8a/* /opt/android/arm64-v8a/lib/. && \
rm -r lib_tango_client_api && \
wget 'https://docs.google.com/uc?authuser=0&id=1AqVuEVu5284X6OgrGWu12VTrx4pY99Jb&export=download' -O TangoSupport_Ikariotikos_C.zip && \
unzip -qq TangoSupport_Ikariotikos_C.zip && \
rm TangoSupport_Ikariotikos_C.zip && \
cp -r lib_tango_support_api/include/* /opt/android/arm64-v8a/include/. && \
cp -r lib_tango_support_api/lib/arm64-v8a/* /opt/android/arm64-v8a/lib/. && \
rm -r lib_tango_support_api && \
wget 'https://docs.google.com/uc?authuser=0&id=1s5iPJ7xiridj9Jj--gCy2XiQFniheVm6&export=download' -O TangoSDK_Ikariotikos_Java.jar && \
mv TangoSDK_Ikariotikos_Java.jar /opt/android/lib/
# ARCore
RUN wget 'https://docs.google.com/uc?authuser=0&id=1VsibeqRYpS5pjmrG-vYTXyiPg8kbIfVN&export=download' -O arcore.zip && \
unzip -qq arcore.zip && \
rm arcore.zip && \
cp -r arcore1_18/include/* /opt/android/arm64-v8a/include/. && \
cp -r arcore1_18/arm64-v8a/* /opt/android/arm64-v8a/lib/. && \
cp arcore1_18/*.jar /opt/android/lib/ && \
rm -r arcore1_18
# AREngine
RUN wget 'https://docs.google.com/uc?authuser=0&id=1rdaD2Z1QBv-SUeUy0oBmg3C2odfxTHgR&export=download' -O arengine.zip && \
unzip -qq arengine.zip && \
rm arengine.zip && \
cp -r arengine/include/* /opt/android/arm64-v8a/include/. && \
cp -r arengine/arm64-v8a/* /opt/android/arm64-v8a/lib/. && \
cp arengine/*.jar /opt/android/lib/ && \
rm -r arengine
@@ -1,13 +0,0 @@
# Image: introlab3it/rtabmap:androidXX
FROM introlab3it/rtabmap:android-noble-deps
ARG API_VERSION=23
# Copy current source code
COPY . /root/rtabmap-tango
WORKDIR /root/rtabmap-tango
RUN /bin/bash -c "./docker/noble/android/rtabmap_apiXX/rtabmap.bash /opt/android $API_VERSION"
@@ -1,29 +0,0 @@
#!/bin/bash
set -e
if [ $# -ne 2 ]; then
echo "rtabmap.bash android_install_prefix api_level (23 for tango, 24 for arengine) # Example: build.bash /opt/android 24"
exit 1
fi
prefix=$1
api=$2
# copy required jars
cp /opt/android/lib/*.jar app/android/libs/.
# resource tool
cd build
cmake -DANDROID_PREBUILD=ON ..
make
# rtabmap
mkdir arm64-v8a
cd arm64-v8a
cmake -DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK/build/cmake/android.toolchain.cmake -DANDROID_ABI=arm64-v8a -DANDROID_NDK=$ANDROID_NDK -DANDROID_NATIVE_API_LEVEL=$api -DBUILD_SHARED_LIBS=OFF -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=$prefix/arm64-v8a -DCMAKE_FIND_ROOT_PATH="$prefix/arm64-v8a/bin;$prefix/arm64-v8a;$prefix/arm64-v8a/share" -DBUILD_EXAMPLES=OFF -DBUILD_TOOLS=OFF -DOpenCV_DIR=$prefix/arm64-v8a/sdk/native/jni ../..
make
make clean
+30 -111
View File
@@ -50,24 +50,7 @@ void showUsage()
{ {
printf("\nUsage:\n" printf("\nUsage:\n"
"rtabmap-rgbd_mapping driver\n" "rtabmap-rgbd_mapping driver\n"
" driver Driver number to use: 0=OpenNI-PCL (Kinect)\n" " driver Driver number to use: 0=OpenNI-PCL, 1=OpenNI2, 2=Freenect, 3=OpenNI-CV, 4=OpenNI-CV-ASUS, 5=Freenect2, 6=ZED SDK, 7=RealSense, 8=RealSense2 9=Kinect for Azure SDK 10=MYNT EYE S\n\n");
" 1=OpenNI2 (Kinect and Xtion PRO Live)\n"
" 2=Freenect (Kinect)\n"
" 3=OpenNI-CV (Kinect)\n"
" 4=OpenNI-CV-ASUS (Xtion PRO Live)\n"
" 5=Freenect2 (Kinect v2)\n"
" 6=DC1394 (Bumblebee2)\n"
" 7=FlyCapture2 (Bumblebee2)\n"
" 8=ZED stereo\n"
" 9=RealSense\n"
" 10=Kinect for Windows 2 SDK\n"
" 11=RealSense2\n"
" 12=Kinect for Azure SDK\n"
" 13=MYNT EYE S\n"
" 14=ZED Open Capture\n"
" 15=depthai-core\n"
" 16=XVSDK (SeerSense)\n"
" 17=Orbbec SDK\n\n");
exit(1); exit(1);
} }
@@ -75,7 +58,7 @@ using namespace rtabmap;
int main(int argc, char * argv[]) int main(int argc, char * argv[])
{ {
ULogger::setType(ULogger::kTypeConsole); ULogger::setType(ULogger::kTypeConsole);
ULogger::setLevel(ULogger::kInfo); ULogger::setLevel(ULogger::kWarning);
#ifdef RTABMAP_PYTHON #ifdef RTABMAP_PYTHON
PythonInterface python; // Make sure we initialize python in main thread PythonInterface python; // Make sure we initialize python in main thread
@@ -89,120 +72,92 @@ int main(int argc, char * argv[])
else else
{ {
driver = atoi(argv[argc-1]); driver = atoi(argv[argc-1]);
if(driver < 0 || driver > 17) if(driver < 0 || driver > 10)
{ {
UERROR("driver should be between 0 and 17."); UERROR("driver should be between 0 and 10.");
showUsage(); showUsage();
} }
} }
// Here is the pipeline that we will use: // Here is the pipeline that we will use:
// CameraOpenni -> "SensorEvent" -> OdometryThread -> "OdometryEvent" -> RtabmapThread -> "RtabmapEvent" // CameraOpenni -> "SensorEvent" -> OdometryThread -> "OdometryEvent" -> RtabmapThread -> "RtabmapEvent"
// Create the OpenNI camera, it will send a SensorEvent at the rate specified.
// Set transform to camera so z is up, y is left and x going forward
Camera * camera = 0; Camera * camera = 0;
if (driver == 0) if(driver == 1)
{ {
camera = new rtabmap::CameraOpenni(); if(!CameraOpenNI2::available())
}
else if (driver == 1)
{
if (!rtabmap::CameraOpenNI2::available())
{ {
UERROR("Not built with OpenNI2 support..."); UERROR("Not built with OpenNI2 support...");
exit(-1); exit(-1);
} }
camera = new rtabmap::CameraOpenNI2(); camera = new CameraOpenNI2();
} }
else if(driver == 2) else if(driver == 2)
{ {
if (!rtabmap::CameraFreenect::available()) if(!CameraFreenect::available())
{ {
UERROR("Not built with Freenect support..."); UERROR("Not built with Freenect support...");
exit(-1); exit(-1);
} }
camera = new rtabmap::CameraFreenect(); camera = new CameraFreenect();
} }
else if(driver == 3) else if(driver == 3)
{ {
if (!rtabmap::CameraOpenNICV::available()) if(!CameraOpenNICV::available())
{ {
UERROR("Not built with OpenNI from OpenCV support..."); UERROR("Not built with OpenNI from OpenCV support...");
exit(-1); exit(-1);
} }
camera = new rtabmap::CameraOpenNICV(false); camera = new CameraOpenNICV();
} }
else if(driver == 4) else if(driver == 4)
{ {
if (!rtabmap::CameraOpenNICV::available()) if(!CameraOpenNICV::available())
{ {
UERROR("Not built with OpenNI from OpenCV support..."); UERROR("Not built with OpenNI from OpenCV support...");
exit(-1); exit(-1);
} }
camera = new rtabmap::CameraOpenNICV(true); camera = new CameraOpenNICV(true);
} }
else if (driver == 5) else if (driver == 5)
{ {
if (!rtabmap::CameraFreenect2::available()) if (!CameraFreenect2::available())
{ {
UERROR("Not built with Freenect2 support..."); UERROR("Not built with Freenect2 support...");
exit(-1); exit(-1);
} }
camera = new rtabmap::CameraFreenect2(0, rtabmap::CameraFreenect2::kTypeColor2DepthSD); camera = new CameraFreenect2(0, CameraFreenect2::kTypeColor2DepthSD);
} }
else if (driver == 6) else if (driver == 6)
{ {
if (!rtabmap::CameraStereoDC1394::available()) if (!CameraStereoZed::available())
{ {
UERROR("Not built with DC1394 support..."); UERROR("Not built with ZED SDK support...");
exit(-1); exit(-1);
} }
camera = new rtabmap::CameraStereoDC1394(); camera = new CameraStereoZed(0, -1, 1, 1, 100, false);
} }
else if (driver == 7) else if (driver == 7)
{ {
if (!rtabmap::CameraStereoFlyCapture2::available()) if (!CameraRealSense::available())
{
UERROR("Not built with FlyCapture2/Triclops support...");
exit(-1);
}
camera = new rtabmap::CameraStereoFlyCapture2();
}
else if (driver == 8)
{
if (!rtabmap::CameraStereoZed::available())
{
UERROR("Not built with ZED sdk support...");
exit(-1);
}
camera = new rtabmap::CameraStereoZed(0);
}
else if (driver == 9)
{
if (!rtabmap::CameraRealSense::available())
{ {
UERROR("Not built with RealSense support..."); UERROR("Not built with RealSense support...");
exit(-1); exit(-1);
} }
camera = new rtabmap::CameraRealSense(); camera = new CameraRealSense();
} }
else if (driver == 10) else if (driver == 8)
{ {
if (!rtabmap::CameraK4W2::available()) if (!CameraRealSense2::available())
{ {
UERROR("Not built with Kinect for Windows 2 SDK support..."); UERROR("Not built with RealSense2 support...");
exit(-1); exit(-1);
} }
camera = new rtabmap::CameraK4W2(); camera = new CameraRealSense2();
} }
else if (driver == 11) else if (driver == 9)
{
if (!rtabmap::CameraRealSense2::available())
{
UERROR("Not built with RealSense2 SDK support...");
exit(-1);
}
camera = new rtabmap::CameraRealSense2();
}
else if (driver == 12)
{ {
if (!rtabmap::CameraK4A::available()) if (!rtabmap::CameraK4A::available())
{ {
@@ -211,7 +166,7 @@ int main(int argc, char * argv[])
} }
camera = new rtabmap::CameraK4A(1); camera = new rtabmap::CameraK4A(1);
} }
else if (driver == 13) else if (driver == 10)
{ {
if (!rtabmap::CameraMyntEye::available()) if (!rtabmap::CameraMyntEye::available())
{ {
@@ -220,45 +175,9 @@ int main(int argc, char * argv[])
} }
camera = new rtabmap::CameraMyntEye(); camera = new rtabmap::CameraMyntEye();
} }
else if (driver == 14)
{
if (!rtabmap::CameraStereoZedOC::available())
{
UERROR("Not built with Zed Open Capture support...");
exit(-1);
}
camera = new rtabmap::CameraStereoZedOC(0);
}
else if (driver == 15)
{
if (!rtabmap::CameraDepthAI::available())
{
UERROR("Not built with depthai-core support...");
exit(-1);
}
camera = new rtabmap::CameraDepthAI();
}
else if (driver == 16)
{
if (!rtabmap::CameraSeerSense::available())
{
UERROR("Not built with XVisio SDK support...");
exit(-1);
}
camera = new rtabmap::CameraSeerSense();
}
else if (driver == 17)
{
if (!rtabmap::CameraOrbbecSDK::available())
{
UERROR("Not built with Orbbec SDK support...");
exit(-1);
}
camera = new rtabmap::CameraOrbbecSDK();
}
else else
{ {
UFATAL(""); camera = new rtabmap::CameraOpenni();
} }
if(!camera->init()) if(!camera->init())
-15
View File
@@ -334,9 +334,6 @@ public:
bool getPose(const std::string & id, Transform & pose); //including meshes bool getPose(const std::string & id, Transform & pose); //including meshes
bool getCloudVisibility(const std::string & id); bool getCloudVisibility(const std::string & id);
int getCloudColorIndex(const std::string & id) const;
double getCloudOpacity(const std::string & id) const;
int getCloudPointSize(const std::string & id) const;
const QMap<std::string, Transform> & getAddedClouds() const {return _addedClouds;} //including meshes const QMap<std::string, Transform> & getAddedClouds() const {return _addedClouds;} //including meshes
const QColor & getDefaultBackgroundColor() const; const QColor & getDefaultBackgroundColor() const;
@@ -402,12 +399,6 @@ public:
void setIntensityRedColormap(bool value); void setIntensityRedColormap(bool value);
void setIntensityRainbowColormap(bool value); void setIntensityRainbowColormap(bool value);
void setIntensityMax(float value); void setIntensityMax(float value);
float getCloudColorRangeMin() const;
float getCloudColorRangeMax() const;
bool isCloudColorRangeInverted() const;
void setCloudColorRangeMin(float value);
void setCloudColorRangeMax(float value);
void setCloudColorRangeInverted(bool enabled);
void buildPickingLocator(bool enable); void buildPickingLocator(bool enable);
const std::map<std::string, vtkSmartPointer<vtkOBBTree> > & getLocators() const {return _locators;} const std::map<std::string, vtkSmartPointer<vtkOBBTree> > & getLocators() const {return _locators;}
@@ -463,10 +454,6 @@ private:
QAction * _aSetIntensityRedColormap; QAction * _aSetIntensityRedColormap;
QAction * _aSetIntensityRainbowColormap; QAction * _aSetIntensityRainbowColormap;
QAction * _aSetIntensityMaximum; QAction * _aSetIntensityMaximum;
QAction * _aSetCloudColorRangeMin;
QAction * _aSetCloudColorRangeMax;
QAction * _aCloudColorRangeInverted;
QAction * _aClearCloudColorRanges;
QAction * _aSetBackgroundColor; QAction * _aSetBackgroundColor;
QAction * _aSetRenderingRate; QAction * _aSetRenderingRate;
QAction * _aSetEDLShading; QAction * _aSetEDLShading;
@@ -507,8 +494,6 @@ private:
double _renderingRate; double _renderingRate;
vtkProp * _octomapActor; vtkProp * _octomapActor;
float _intensityAbsMax; float _intensityAbsMax;
float _cloudColorRangeMin;
float _cloudColorRangeMax;
double _coordinateFrameScale; double _coordinateFrameScale;
}; };
-3
View File
@@ -77,7 +77,6 @@ public:
float getDepthColorMapMinRange() const; float getDepthColorMapMinRange() const;
float getDepthColorMapMaxRange() const; float getDepthColorMapMaxRange() const;
uCvQtDepthColorMap getDepthColorMap() const; uCvQtDepthColorMap getDepthColorMap() const;
bool isDepthColorMapInCameraFrame() const;
float viewScale() const; float viewScale() const;
@@ -95,7 +94,6 @@ public:
void setDefaultMatchingLineColor(const QColor & color); void setDefaultMatchingLineColor(const QColor & color);
void setBackgroundColor(const QColor & color); void setBackgroundColor(const QColor & color);
void setDepthColorMapRange(float min, float max); void setDepthColorMapRange(float min, float max);
void setDepthColorMapInCameraFrame(bool enabled);
void setFeatures(const std::multimap<int, cv::KeyPoint> & refWords, const cv::Mat & depth = cv::Mat(), const QColor & color = Qt::yellow); void setFeatures(const std::multimap<int, cv::KeyPoint> & refWords, const cv::Mat & depth = cv::Mat(), const QColor & color = Qt::yellow);
void setFeatures(const std::vector<cv::KeyPoint> & features, const cv::Mat & depth = cv::Mat(), const QColor & color = Qt::yellow); void setFeatures(const std::vector<cv::KeyPoint> & features, const cv::Mat & depth = cv::Mat(), const QColor & color = Qt::yellow);
@@ -169,7 +167,6 @@ private:
QAction * _colorMapBlackToWhite; QAction * _colorMapBlackToWhite;
QAction * _colorMapRedToBlue; QAction * _colorMapRedToBlue;
QAction * _colorMapBlueToRed; QAction * _colorMapBlueToRed;
QAction * _colorMapInCameraFrame;
QAction * _colorMapMinRange; QAction * _colorMapMinRange;
QAction * _colorMapMaxRange; QAction * _colorMapMaxRange;
QAction * _mouseTracking; QAction * _mouseTracking;
-1
View File
@@ -178,7 +178,6 @@ protected Q_SLOTS:
void selectFreenect2(); void selectFreenect2();
void selectK4W2(); void selectK4W2();
void selectK4A(); void selectK4A();
void selectOrbbecSDK();
void selectRealSense(); void selectRealSense();
void selectRealSense2(); void selectRealSense2();
void selectRealSense2L515(); void selectRealSense2L515();
@@ -1,186 +0,0 @@
/*
Copyright (c) 2010-2025, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Universite de Sherbrooke nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef GUILIB_SRC_POINTCLOUDCOLORHANDLEINTENSITYFIELD_H_
#define GUILIB_SRC_POINTCLOUDCOLORHANDLEINTENSITYFIELD_H_
#include <pcl/visualization/point_cloud_color_handlers.h>
#include <pcl/pcl_config.h>
#include <rtabmap/core/util2d.h>
#include <rtabmap/utilite/UMath.h>
namespace rtabmap
{
class PointCloudColorHandlerIntensityField : public pcl::visualization::PointCloudColorHandler<pcl::PCLPointCloud2>
{
typedef pcl::visualization::PointCloudColorHandler<pcl::PCLPointCloud2>::PointCloud PointCloud;
typedef PointCloud::Ptr PointCloudPtr;
typedef PointCloud::ConstPtr PointCloudConstPtr;
public:
/** \brief Constructor. */
PointCloudColorHandlerIntensityField(const PointCloudConstPtr &cloud, float maxAbsIntensity = 0.0f, int colorMap = 0) : pcl::visualization::PointCloudColorHandler<pcl::PCLPointCloud2>::PointCloudColorHandler(cloud),
maxAbsIntensity_(maxAbsIntensity),
colormap_(colorMap)
{
field_idx_ = pcl::getFieldIndex(*cloud, "intensity");
if (field_idx_ != -1)
capable_ = true;
else
capable_ = false;
}
/** \brief Empty destructor */
virtual ~PointCloudColorHandlerIntensityField() {}
/** \brief Obtain the actual color for the input dataset as vtk scalars.
* \param[out] scalars the output scalars containing the color for the dataset
* \return true if the operation was successful (the handler is capable and
* the input cloud was given as a valid pointer), false otherwise
*/
#if PCL_VERSION_COMPARE(>, 1, 11, 1)
virtual vtkSmartPointer<vtkDataArray> getColor() const
{
vtkSmartPointer<vtkDataArray> scalars;
if (!capable_ || !cloud_)
return scalars;
#else
virtual bool getColor(vtkSmartPointer<vtkDataArray> &scalars) const
{
if (!capable_ || !cloud_)
return (false);
#endif
if (!scalars)
scalars = vtkSmartPointer<vtkUnsignedCharArray>::New();
scalars->SetNumberOfComponents(3);
vtkIdType nr_points = cloud_->width * cloud_->height;
// Allocate enough memory to hold all colors
float *intensities = new float[nr_points];
float intensity;
size_t point_offset = cloud_->fields[field_idx_].offset;
size_t j = 0;
// If XYZ present, check if the points are invalid
int x_idx = pcl::getFieldIndex(*cloud_, "x");
if (x_idx != -1)
{
float x_data, y_data, z_data;
size_t x_point_offset = cloud_->fields[x_idx].offset;
// Color every point
for (vtkIdType cp = 0; cp < nr_points; ++cp,
point_offset += cloud_->point_step,
x_point_offset += cloud_->point_step)
{
// Copy the value at the specified field
memcpy(&intensity, &cloud_->data[point_offset], sizeof(float));
memcpy(&x_data, &cloud_->data[x_point_offset], sizeof(float));
memcpy(&y_data, &cloud_->data[x_point_offset + sizeof(float)], sizeof(float));
memcpy(&z_data, &cloud_->data[x_point_offset + 2 * sizeof(float)], sizeof(float));
if (!std::isfinite(x_data) || !std::isfinite(y_data) || !std::isfinite(z_data))
continue;
intensities[j++] = intensity;
}
}
// No XYZ data checks
else
{
// Color every point
for (vtkIdType cp = 0; cp < nr_points; ++cp, point_offset += cloud_->point_step)
{
// Copy the value at the specified field
memcpy(&intensity, &cloud_->data[point_offset], sizeof(float));
intensities[j++] = intensity;
}
}
if (j != 0)
{
// Allocate enough memory to hold all colors
unsigned char *colors = new unsigned char[j * 3];
float min, max;
if (maxAbsIntensity_ > 0.0f)
{
max = maxAbsIntensity_;
}
else
{
uMinMax(intensities, j, min, max);
}
for (size_t k = 0; k < j; ++k)
{
colors[k * 3 + 0] = colors[k * 3 + 1] = colors[k * 3 + 2] = max > 0 ? (unsigned char)(std::min(intensities[k] / max * 255.0f, 255.0f)) : 255;
if (colormap_ == 1)
{
colors[k * 3 + 0] = 255;
colors[k * 3 + 2] = 0;
}
else if (colormap_ == 2)
{
float r, g, b;
util2d::HSVtoRGB(&r, &g, &b, colors[k * 3 + 0] * 299.0f / 255.0f, 1.0f, 1.0f);
colors[k * 3 + 0] = r * 255.0f;
colors[k * 3 + 1] = g * 255.0f;
colors[k * 3 + 2] = b * 255.0f;
}
}
reinterpret_cast<vtkUnsignedCharArray *>(&(*scalars))->SetNumberOfTuples(j);
reinterpret_cast<vtkUnsignedCharArray *>(&(*scalars))->SetArray(colors, j * 3, 0, vtkUnsignedCharArray::VTK_DATA_ARRAY_DELETE);
}
else
reinterpret_cast<vtkUnsignedCharArray *>(&(*scalars))->SetNumberOfTuples(0);
// delete [] colors;
delete[] intensities;
#if PCL_VERSION_COMPARE(>, 1, 11, 1)
return scalars;
#else
return (true);
#endif
}
protected:
/** \brief Get the name of the class. */
virtual std::string
getName() const { return ("PointCloudColorHandlerIntensityField"); }
/** \brief Get the name of the field used. */
virtual std::string
getFieldName() const { return ("intensity"); }
private:
float maxAbsIntensity_;
int colormap_; // 0=grayscale, 1=redYellow, 2=RainbowHSV
};
} /* namespace rtabmap */
#endif /* GUILIB_SRC_POINTCLOUDCOLORHANDLEINTENSITYFIELD_H_ */
@@ -1,187 +0,0 @@
/*
Copyright (c) 2010-2025, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Universite de Sherbrooke nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef GUILIB_SRC_POINTCLOUDCOLORHANDLEMINMAXGENERICFIELD_H_
#define GUILIB_SRC_POINTCLOUDCOLORHANDLEMINMAXGENERICFIELD_H_
#include <limits>
#include <pcl/visualization/point_cloud_color_handlers.h>
#include <pcl/pcl_config.h>
namespace rtabmap
{
/// Same than pcl::visualization::PointCloudColorHandlerGenericField but with min and max parameters
class PointCloudColorHandlerMinMaxGenericField : public pcl::visualization::PointCloudColorHandler<pcl::PCLPointCloud2>
{
using PointCloud = typename PointCloudColorHandler<pcl::PCLPointCloud2>::PointCloud;
using PointCloudPtr = typename PointCloud::Ptr;
using PointCloudConstPtr = typename PointCloud::ConstPtr;
public:
/** \brief Constructor. */
PointCloudColorHandlerMinMaxGenericField(const PointCloudConstPtr &cloud,
const std::string &field_name,
float min = std::numeric_limits<float>::lowest(),
float max = std::numeric_limits<float>::max(),
bool inverted_color_scale = false)
: pcl::visualization::PointCloudColorHandler<pcl::PCLPointCloud2>(cloud),
field_name_(field_name),
min_(min),
max_(max),
inverted_color_scale_(inverted_color_scale)
{
setInputCloud(cloud);
}
/** \brief Destructor. */
virtual ~PointCloudColorHandlerMinMaxGenericField() {}
/** \brief Get the name of the field used. */
virtual std::string getFieldName() const { return (field_name_); }
#if PCL_VERSION_COMPARE(>, 1, 11, 1)
virtual vtkSmartPointer<vtkDataArray> getColor() const
{
vtkSmartPointer<vtkDataArray> scalars;
if (!capable_ || !cloud_)
return scalars;
#else
virtual bool getColor(vtkSmartPointer<vtkDataArray> &scalars) const
{
if (!capable_ || !cloud_)
return (false);
#endif
if (!scalars)
scalars = vtkSmartPointer<vtkFloatArray>::New ();
scalars->SetNumberOfComponents(1);
vtkIdType nr_points = cloud_->width * cloud_->height;
scalars->SetNumberOfTuples(nr_points);
float *colors = new float[nr_points];
float field_data;
int j = 0;
int point_offset = cloud_->fields[field_idx_].offset;
// If XYZ present, check if the points are invalid
int x_idx = pcl::getFieldIndex(*cloud_, "x");
if (x_idx != -1)
{
float x_data, y_data, z_data;
int x_point_offset = cloud_->fields[x_idx].offset;
// Color every point
for (vtkIdType cp = 0; cp < nr_points; ++cp,
point_offset += cloud_->point_step,
x_point_offset += cloud_->point_step)
{
memcpy(&x_data, &cloud_->data[x_point_offset], sizeof(float));
memcpy(&y_data, &cloud_->data[x_point_offset + sizeof(float)], sizeof(float));
memcpy(&z_data, &cloud_->data[x_point_offset + 2 * sizeof(float)], sizeof(float));
if (!std::isfinite(x_data) || !std::isfinite(y_data) || !std::isfinite(z_data))
continue;
// Copy the value at the specified field
memcpy(&field_data, &cloud_->data[point_offset], pcl::getFieldSize(cloud_->fields[field_idx_].datatype));
if(field_data < min_) {
field_data = min_;
}
if(field_data > max_) {
field_data = max_;
}
colors[j] = field_data * (inverted_color_scale_?-1.0f:1.0f);
j++;
}
}
// No XYZ data checks
else
{
// Color every point
for (vtkIdType cp = 0; cp < nr_points; ++cp, point_offset += cloud_->point_step)
{
// Copy the value at the specified field
// memcpy (&field_data, &cloud_->data[point_offset], sizeof (float));
memcpy(&field_data, &cloud_->data[point_offset], pcl::getFieldSize(cloud_->fields[field_idx_].datatype));
if (!std::isfinite(field_data))
continue;
if(field_data < min_) {
field_data = min_;
}
if(field_data > max_) {
field_data = max_;
}
colors[j] = field_data * (inverted_color_scale_?-1.0f:1.0f);
j++;
}
}
reinterpret_cast<vtkFloatArray *>(&(*scalars))->SetArray(colors, j, 0, vtkFloatArray::VTK_DATA_ARRAY_DELETE);
#if PCL_VERSION_COMPARE(>, 1, 11, 1)
return scalars;
#else
return (true);
#endif
}
using PointCloudColorHandler<pcl::PCLPointCloud2>::getColor;
/** \brief Set the input cloud to be used.
* \param[in] cloud the input cloud to be used by the handler
*/
virtual void
setInputCloud(const PointCloudConstPtr &cloud)
{
PointCloudColorHandler<pcl::PCLPointCloud2>::setInputCloud(cloud);
field_idx_ = pcl::getFieldIndex(*cloud, field_name_);
capable_ = field_idx_ != -1;
if (field_idx_ != -1 && cloud_->fields[field_idx_].datatype != pcl::PCLPointField::PointFieldTypes::FLOAT32)
{
capable_ = false;
PCL_ERROR("[pcl::PointCloudColorHandlerGenericField] This currently only works with float32 fields, but field %s has a different type.\n", field_name_.c_str());
}
}
protected:
/** \brief Class getName method. */
virtual std::string
getName() const { return ("PointCloudColorHandlerMinMaxGenericField"); }
private:
/** \brief Name of the field used to create the color handler. */
std::string field_name_;
float min_;
float max_;
bool inverted_color_scale_;
};
} /* namespace rtabmap */
#endif /* GUILIB_SRC_POINTCLOUDCOLORHANDLEMINMAXGENERICFIELD_H_ */
@@ -98,7 +98,6 @@ public:
kSrcRealSense2 = 9, kSrcRealSense2 = 9,
kSrcK4A = 10, kSrcK4A = 10,
kSrcSeerSense = 11, kSrcSeerSense = 11,
kSrcOrbbecSDK = 12,
kSrcStereo = 100, kSrcStereo = 100,
kSrcDC1394 = 100, kSrcDC1394 = 100,
@@ -174,7 +173,6 @@ public:
int getOdomRegistrationApproach() const; int getOdomRegistrationApproach() const;
double getOdomF2MGravitySigma() const; double getOdomF2MGravitySigma() const;
bool isOdomDisabled() const; bool isOdomDisabled() const;
bool isOdomAsGuessEnabled() const;
bool isOdomSensorAsGt() const; bool isOdomSensorAsGt() const;
bool isGroundTruthAligned() const; bool isGroundTruthAligned() const;
@@ -369,7 +367,7 @@ private Q_SLOTS:
void changeDictionaryPath(); void changeDictionaryPath();
void changeOdometryORBSLAMVocabulary(); void changeOdometryORBSLAMVocabulary();
void changeOdometryOKVISConfigPath(); void changeOdometryOKVISConfigPath();
void changeOdometryVINSFusionConfigPath(); void changeOdometryVINSConfigPath();
void changeOdometryOpenVINSLeftMask(); void changeOdometryOpenVINSLeftMask();
void changeOdometryOpenVINSRightMask(); void changeOdometryOpenVINSRightMask();
void changeIcpPMConfigPath(); void changeIcpPMConfigPath();
+12 -12
View File
@@ -117,7 +117,7 @@ inline QImage uCvMat2QImage(
// Assume depth image (float in meters) // Assume depth image (float in meters)
const float * data = (const float *)image.data; const float * data = (const float *)image.data;
float min,max; float min,max;
if(depthMin != 0 && depthMax != 0 && depthMax > depthMin) if(depthMax>depthMin)
{ {
min = depthMin; min = depthMin;
max = depthMax; max = depthMax;
@@ -127,23 +127,23 @@ inline QImage uCvMat2QImage(
min = max = data[0]; min = max = data[0];
for(unsigned int i=1; i<image.total(); ++i) for(unsigned int i=1; i<image.total(); ++i)
{ {
if(uIsFinite(data[i]) && data[i] != 0) if(uIsFinite(data[i]) && data[i] > 0)
{ {
if(!uIsFinite(min) || (data[i] != 0 && data[i]<min)) if(!uIsFinite(min) || (data[i] > 0 && data[i]<min))
{ {
min = data[i]; min = data[i];
} }
if(!uIsFinite(max) || (data[i] != 0 && data[i]>max)) if(!uIsFinite(max) || (data[i] > 0 && data[i]>max))
{ {
max = data[i]; max = data[i];
} }
} }
} }
if(depthMax != 0 && depthMax > depthMin) if(depthMax > 0 && depthMax > depthMin)
{ {
max = depthMax; max = depthMax;
} }
if(depthMin != 0 && (depthMin < depthMax || depthMin < max)) if(depthMin>0 && (depthMin < depthMax || depthMin < max))
{ {
min = depthMin; min = depthMin;
} }
@@ -198,7 +198,7 @@ inline QImage uCvMat2QImage(
// Assume depth image (unsigned short in mm) // Assume depth image (unsigned short in mm)
const unsigned short * data = (const unsigned short *)image.data; const unsigned short * data = (const unsigned short *)image.data;
unsigned short min,max; unsigned short min,max;
if(depthMin != 0 && depthMax != 0 && depthMax > depthMin) if(depthMax>depthMin)
{ {
min = depthMin*1000; min = depthMin*1000;
max = depthMax*1000; max = depthMax*1000;
@@ -208,23 +208,23 @@ inline QImage uCvMat2QImage(
min = max = data[0]; min = max = data[0];
for(unsigned int i=1; i<image.total(); ++i) for(unsigned int i=1; i<image.total(); ++i)
{ {
if(uIsFinite(data[i]) && data[i] != 0) if(uIsFinite(data[i]) && data[i] > 0)
{ {
if(!uIsFinite(min) || (data[i] != 0 && data[i]<min)) if(!uIsFinite(min) || (data[i] > 0 && data[i]<min))
{ {
min = data[i]; min = data[i];
} }
if(!uIsFinite(max) || (data[i] != 0 && data[i]>max)) if(!uIsFinite(max) || (data[i] > 0 && data[i]>max))
{ {
max = data[i]; max = data[i];
} }
} }
} }
if(depthMax != 0 && depthMax > depthMin) if(depthMax > 0 && depthMax > depthMin)
{ {
max = depthMax*1000; max = depthMax*1000;
} }
if(depthMin != 0 && (depthMin < depthMax || depthMin*1000 < max)) if(depthMin>0 && (depthMin < depthMax || depthMin*1000 < max))
{ {
min = depthMin*1000; min = depthMin*1000;
} }
+1 -11
View File
@@ -179,8 +179,6 @@ AboutDialog::AboutDialog(QWidget * parent) :
_ui->label_depthai->setText(CameraDepthAI::available() ? "Yes" : "No"); _ui->label_depthai->setText(CameraDepthAI::available() ? "Yes" : "No");
_ui->label_depthai_license->setEnabled(CameraDepthAI::available()); _ui->label_depthai_license->setEnabled(CameraDepthAI::available());
_ui->label_xvsdk->setText(CameraSeerSense::available() ? "Yes" : "No"); _ui->label_xvsdk->setText(CameraSeerSense::available() ? "Yes" : "No");
_ui->label_orbbec_sdk->setText(CameraOrbbecSDK::available() ? "Yes" : "No");
_ui->label_orbbec_sdk_license->setEnabled(CameraOrbbecSDK::available());
_ui->label_toro->setText(Optimizer::isAvailable(Optimizer::kTypeTORO)?"Yes":"No"); _ui->label_toro->setText(Optimizer::isAvailable(Optimizer::kTypeTORO)?"Yes":"No");
_ui->label_toro_license->setEnabled(Optimizer::isAvailable(Optimizer::kTypeTORO)?true:false); _ui->label_toro_license->setEnabled(Optimizer::isAvailable(Optimizer::kTypeTORO)?true:false);
@@ -283,7 +281,7 @@ AboutDialog::AboutDialog(QWidget * parent) :
_ui->label_msckf_license->setEnabled(false); _ui->label_msckf_license->setEnabled(false);
#endif #endif
#ifdef RTABMAP_VINS_FUSION #ifdef RTABMAP_VINS
_ui->label_vins_fusion->setText("Yes"); _ui->label_vins_fusion->setText("Yes");
_ui->label_vins_fusion_license->setEnabled(true); _ui->label_vins_fusion_license->setEnabled(true);
#else #else
@@ -299,14 +297,6 @@ AboutDialog::AboutDialog(QWidget * parent) :
_ui->label_openvins_license->setEnabled(false); _ui->label_openvins_license->setEnabled(false);
#endif #endif
#ifdef RTABMAP_CUVSLAM
_ui->label_cuvslam->setText("Yes");
_ui->label_cuvslam_license->setEnabled(true);
#else
_ui->label_cuvslam->setText("No");
_ui->label_cuvslam_license->setEnabled(false);
#endif
} }
AboutDialog::~AboutDialog() AboutDialog::~AboutDialog()
+10 -7
View File
@@ -97,7 +97,11 @@ IF(MSVC)
SET(SRC_FILES ${SRC_FILES} ${HEADERS}) SET(SRC_FILES ${SRC_FILES} ${HEADERS})
ENDIF(MSVC) ENDIF(MSVC)
SET(INCLUDE_DIRS "") SET(INCLUDE_DIRS
${CMAKE_CURRENT_SOURCE_DIR}/../include
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_BINARY_DIR} # for qt ui generated in binary dir
)
IF(QT4_FOUND) IF(QT4_FOUND)
INCLUDE(${QT_USE_FILE}) INCLUDE(${QT_USE_FILE})
@@ -168,6 +172,9 @@ IF(VTK_USE_QVTK)
SET(LIBRARIES ${LIBRARIES} ${QVTK_LIBRARY}) SET(LIBRARIES ${LIBRARIES} ${QVTK_LIBRARY})
ENDIF(VTK_USE_QVTK) ENDIF(VTK_USE_QVTK)
#include files
INCLUDE_DIRECTORIES(${INCLUDE_DIRS})
add_definitions(${PCL_DEFINITIONS}) add_definitions(${PCL_DEFINITIONS})
# Include presets # Include presets
@@ -198,12 +205,8 @@ generate_export_header(rtabmap_gui
DEPRECATED_MACRO_NAME RTABMAP_DEPRECATED) DEPRECATED_MACRO_NAME RTABMAP_DEPRECATED)
target_include_directories(rtabmap_gui PUBLIC target_include_directories(rtabmap_gui PUBLIC
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR};${CMAKE_CURRENT_SOURCE_DIR}/../include;${CMAKE_CURRENT_BINARY_DIR};${CMAKE_CURRENT_BINARY_DIR}/include>" "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../include;${CMAKE_CURRENT_BINARY_DIR}/include;${PUBLIC_INCLUDE_DIRS}>"
"$<INSTALL_INTERFACE:${INSTALL_INCLUDE_DIR}>") "$<INSTALL_INTERFACE:${INSTALL_INCLUDE_DIR};${PUBLIC_INCLUDE_DIRS}>")
target_include_directories(rtabmap_gui SYSTEM PUBLIC
"$<BUILD_INTERFACE:${PUBLIC_INCLUDE_DIRS};${INCLUDE_DIRS}>"
"$<INSTALL_INTERFACE:${PUBLIC_INCLUDE_DIRS}>")
TARGET_LINK_LIBRARIES(rtabmap_gui TARGET_LINK_LIBRARIES(rtabmap_gui
PUBLIC PUBLIC
+8 -9
View File
@@ -250,18 +250,17 @@ void CalibrationDialog::resetSettings()
cv::Mat drawChessboard(int squareSize, int boardWidth, int boardHeight, int borderSize) cv::Mat drawChessboard(int squareSize, int boardWidth, int boardHeight, int borderSize)
{ {
int imageWidth = squareSize*(boardWidth+1) + 2*borderSize; int imageWidth = squareSize*boardWidth + borderSize;
int imageHeight = squareSize*(boardHeight+1) + 2*borderSize; int imageHeight = squareSize*boardHeight + borderSize;
cv::Mat chessboard(imageHeight, imageWidth, CV_8UC1, 255); cv::Mat chessboard(imageWidth, imageHeight, CV_8UC1, 255);
unsigned char rowColor = 0; unsigned char color = 0;
for(int i=borderSize;i<imageHeight-borderSize; i=i+squareSize) { for(int i=borderSize;i<imageHeight-borderSize; i=i+squareSize) {
unsigned char colColor = rowColor; color=~color;
for(int j=borderSize;j<imageWidth-borderSize;j=j+squareSize) { for(int j=borderSize;j<imageWidth-borderSize;j=j+squareSize) {
cv::Mat roi=chessboard(cv::Rect(j,i,squareSize,squareSize)); cv::Mat roi=chessboard(cv::Rect(i,j,squareSize,squareSize));
roi.setTo(colColor); roi.setTo(color);
colColor=~colColor; color=~color;
} }
rowColor = ~rowColor;
} }
return chessboard; return chessboard;
} }
+151 -118
View File
@@ -27,8 +27,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "rtabmap/gui/CloudViewer.h" #include "rtabmap/gui/CloudViewer.h"
#include "rtabmap/gui/CloudViewerCellPicker.h" #include "rtabmap/gui/CloudViewerCellPicker.h"
#include "rtabmap/gui/PointCloudColorHandlerIntensityField.h"
#include "rtabmap/gui/PointCloudColorHandlerMinMaxGenericField.h"
#include <rtabmap/core/Version.h> #include <rtabmap/core/Version.h>
#include <rtabmap/core/util3d_transforms.h> #include <rtabmap/core/util3d_transforms.h>
@@ -152,8 +150,6 @@ CloudViewer::CloudViewer(QWidget *parent, CloudViewerInteractorStyle * style) :
_renderingRate(5.0), _renderingRate(5.0),
_octomapActor(0), _octomapActor(0),
_intensityAbsMax(100.0f), _intensityAbsMax(100.0f),
_cloudColorRangeMin(0.0f),
_cloudColorRangeMax(0.0f),
_coordinateFrameScale(1.0) _coordinateFrameScale(1.0)
{ {
this->setMinimumSize(200, 200); this->setMinimumSize(200, 200);
@@ -341,12 +337,6 @@ void CloudViewer::createMenu()
_aSetIntensityRainbowColormap->setCheckable(true); _aSetIntensityRainbowColormap->setCheckable(true);
_aSetIntensityRainbowColormap->setChecked(false); _aSetIntensityRainbowColormap->setChecked(false);
_aSetIntensityMaximum = new QAction("Set maximum absolute intensity...", this); _aSetIntensityMaximum = new QAction("Set maximum absolute intensity...", this);
_aSetCloudColorRangeMin = new QAction("Set minimum color range...", this);
_aSetCloudColorRangeMax = new QAction("Set maximum color range...", this);
_aCloudColorRangeInverted = new QAction("Inverted color scale", this);
_aCloudColorRangeInverted->setCheckable(true);
_aCloudColorRangeInverted->setChecked(false);
_aClearCloudColorRanges = new QAction("Reset ranges", this);
_aSetBackgroundColor = new QAction("Set background color...", this); _aSetBackgroundColor = new QAction("Set background color...", this);
_aSetRenderingRate = new QAction("Set rendering rate...", this); _aSetRenderingRate = new QAction("Set rendering rate...", this);
_aSetEDLShading = new QAction("Eye-Dome Lighting Shading", this); _aSetEDLShading = new QAction("Eye-Dome Lighting Shading", this);
@@ -412,12 +402,6 @@ void CloudViewer::createMenu()
scanMenu->addAction(_aSetIntensityRainbowColormap); scanMenu->addAction(_aSetIntensityRainbowColormap);
scanMenu->addAction(_aSetIntensityMaximum); scanMenu->addAction(_aSetIntensityMaximum);
QMenu * cloudMenu = new QMenu("XYZ color", this);
cloudMenu->addAction(_aSetCloudColorRangeMin);
cloudMenu->addAction(_aSetCloudColorRangeMax);
cloudMenu->addAction(_aCloudColorRangeInverted);
cloudMenu->addAction(_aClearCloudColorRanges);
//menus //menus
_menu = new QMenu(this); _menu = new QMenu(this);
_menu->addMenu(cameraMenu); _menu->addMenu(cameraMenu);
@@ -428,7 +412,6 @@ void CloudViewer::createMenu()
_menu->addMenu(gridMenu); _menu->addMenu(gridMenu);
_menu->addMenu(normalsMenu); _menu->addMenu(normalsMenu);
_menu->addMenu(scanMenu); _menu->addMenu(scanMenu);
_menu->addMenu(cloudMenu);
_menu->addAction(_aSetBackgroundColor); _menu->addAction(_aSetBackgroundColor);
_menu->addAction(_aSetRenderingRate); _menu->addAction(_aSetRenderingRate);
_menu->addAction(_aSetEDLShading); _menu->addAction(_aSetEDLShading);
@@ -482,10 +465,6 @@ void CloudViewer::saveSettings(QSettings & settings, const QString & group) cons
settings.setValue("intensity_rainbow_colormap", this->isIntensityRainbowColormap()); settings.setValue("intensity_rainbow_colormap", this->isIntensityRainbowColormap());
settings.setValue("intensity_max", (double)this->getIntensityMax()); settings.setValue("intensity_max", (double)this->getIntensityMax());
settings.setValue("color_range_min", (double)this->getCloudColorRangeMin());
settings.setValue("color_range_max", (double)this->getCloudColorRangeMax());
settings.setValue("color_range_inverted", (double)this->isCloudColorRangeInverted());
settings.setValue("trajectory_shown", this->isTrajectoryShown()); settings.setValue("trajectory_shown", this->isTrajectoryShown());
settings.setValue("trajectory_size", this->getTrajectorySize()); settings.setValue("trajectory_size", this->getTrajectorySize());
@@ -537,10 +516,6 @@ void CloudViewer::loadSettings(QSettings & settings, const QString & group)
this->setIntensityRainbowColormap(settings.value("intensity_rainbow_colormap", this->isIntensityRainbowColormap()).toBool()); this->setIntensityRainbowColormap(settings.value("intensity_rainbow_colormap", this->isIntensityRainbowColormap()).toBool());
this->setIntensityMax(settings.value("intensity_max", this->getIntensityMax()).toFloat()); this->setIntensityMax(settings.value("intensity_max", this->getIntensityMax()).toFloat());
this->setCloudColorRangeMin(settings.value("color_range_min", this->getCloudColorRangeMin()).toFloat());
this->setCloudColorRangeMax(settings.value("color_range_max", this->getCloudColorRangeMax()).toFloat());
this->setCloudColorRangeInverted(settings.value("color_range_inverted", this->isCloudColorRangeInverted()).toBool());
this->setTrajectoryShown(settings.value("trajectory_shown", this->isTrajectoryShown()).toBool()); this->setTrajectoryShown(settings.value("trajectory_shown", this->isTrajectoryShown()).toBool());
this->setTrajectorySize(settings.value("trajectory_size", this->getTrajectorySize()).toUInt()); this->setTrajectorySize(settings.value("trajectory_size", this->getTrajectorySize()).toUInt());
@@ -631,6 +606,153 @@ bool CloudViewer::updateCloudPose(
return false; return false;
} }
class PointCloudColorHandlerIntensityField : public pcl::visualization::PointCloudColorHandler<pcl::PCLPointCloud2>
{
typedef pcl::visualization::PointCloudColorHandler<pcl::PCLPointCloud2>::PointCloud PointCloud;
typedef PointCloud::Ptr PointCloudPtr;
typedef PointCloud::ConstPtr PointCloudConstPtr;
public:
typedef boost::shared_ptr<PointCloudColorHandlerIntensityField > Ptr;
typedef boost::shared_ptr<const PointCloudColorHandlerIntensityField > ConstPtr;
/** \brief Constructor. */
PointCloudColorHandlerIntensityField (const PointCloudConstPtr &cloud, float maxAbsIntensity = 0.0f, int colorMap = 0) :
pcl::visualization::PointCloudColorHandler<pcl::PCLPointCloud2>::PointCloudColorHandler (cloud),
maxAbsIntensity_(maxAbsIntensity),
colormap_(colorMap)
{
field_idx_ = pcl::getFieldIndex (*cloud, "intensity");
if (field_idx_ != -1)
capable_ = true;
else
capable_ = false;
}
/** \brief Empty destructor */
virtual ~PointCloudColorHandlerIntensityField () {}
/** \brief Obtain the actual color for the input dataset as vtk scalars.
* \param[out] scalars the output scalars containing the color for the dataset
* \return true if the operation was successful (the handler is capable and
* the input cloud was given as a valid pointer), false otherwise
*/
#if PCL_VERSION_COMPARE(>, 1, 11, 1)
virtual vtkSmartPointer<vtkDataArray> getColor () const {
vtkSmartPointer<vtkDataArray> scalars;
if (!capable_ || !cloud_)
return scalars;
#else
virtual bool getColor (vtkSmartPointer<vtkDataArray> &scalars) const {
if (!capable_ || !cloud_)
return (false);
#endif
if (!scalars)
scalars = vtkSmartPointer<vtkUnsignedCharArray>::New ();
scalars->SetNumberOfComponents (3);
vtkIdType nr_points = cloud_->width * cloud_->height;
// Allocate enough memory to hold all colors
float * intensities = new float[nr_points];
float intensity;
size_t point_offset = cloud_->fields[field_idx_].offset;
size_t j = 0;
// If XYZ present, check if the points are invalid
int x_idx = pcl::getFieldIndex (*cloud_, "x");
if (x_idx != -1)
{
float x_data, y_data, z_data;
size_t x_point_offset = cloud_->fields[x_idx].offset;
// Color every point
for (vtkIdType cp = 0; cp < nr_points; ++cp,
point_offset += cloud_->point_step,
x_point_offset += cloud_->point_step)
{
// Copy the value at the specified field
memcpy (&intensity, &cloud_->data[point_offset], sizeof (float));
memcpy (&x_data, &cloud_->data[x_point_offset], sizeof (float));
memcpy (&y_data, &cloud_->data[x_point_offset + sizeof (float)], sizeof (float));
memcpy (&z_data, &cloud_->data[x_point_offset + 2 * sizeof (float)], sizeof (float));
if (!std::isfinite (x_data) || !std::isfinite (y_data) || !std::isfinite (z_data))
continue;
intensities[j++] = intensity;
}
}
// No XYZ data checks
else
{
// Color every point
for (vtkIdType cp = 0; cp < nr_points; ++cp, point_offset += cloud_->point_step)
{
// Copy the value at the specified field
memcpy (&intensity, &cloud_->data[point_offset], sizeof (float));
intensities[j++] = intensity;
}
}
if (j != 0)
{
// Allocate enough memory to hold all colors
unsigned char* colors = new unsigned char[j * 3];
float min, max;
if(maxAbsIntensity_>0.0f)
{
max = maxAbsIntensity_;
}
else
{
uMinMax(intensities, j, min, max);
}
for(size_t k=0; k<j; ++k)
{
colors[k*3+0] = colors[k*3+1] = colors[k*3+2] = max>0?(unsigned char)(std::min(intensities[k]/max*255.0f, 255.0f)):255;
if(colormap_ == 1)
{
colors[k*3+0] = 255;
colors[k*3+2] = 0;
}
else if(colormap_ == 2)
{
float r,g,b;
util2d::HSVtoRGB(&r, &g, &b, colors[k*3+0]*299.0f/255.0f, 1.0f, 1.0f);
colors[k*3+0] = r*255.0f;
colors[k*3+1] = g*255.0f;
colors[k*3+2] = b*255.0f;
}
}
reinterpret_cast<vtkUnsignedCharArray*>(&(*scalars))->SetNumberOfTuples (j);
reinterpret_cast<vtkUnsignedCharArray*>(&(*scalars))->SetArray (colors, j*3, 0, vtkUnsignedCharArray::VTK_DATA_ARRAY_DELETE);
}
else
reinterpret_cast<vtkUnsignedCharArray*>(&(*scalars))->SetNumberOfTuples (0);
//delete [] colors;
delete [] intensities;
#if PCL_VERSION_COMPARE(>, 1, 11, 1)
return scalars;
#else
return (true);
#endif
}
protected:
/** \brief Get the name of the class. */
virtual std::string
getName () const { return ("PointCloudColorHandlerIntensityField"); }
/** \brief Get the name of the field used. */
virtual std::string
getFieldName () const { return ("intensity"); }
private:
float maxAbsIntensity_;
int colormap_; // 0=grayscale, 1=redYellow, 2=RainbowHSV
};
bool CloudViewer::addCloud( bool CloudViewer::addCloud(
const std::string & id, const std::string & id,
const pcl::PCLPointCloud2Ptr & binaryCloud, const pcl::PCLPointCloud2Ptr & binaryCloud,
@@ -677,20 +799,11 @@ bool CloudViewer::addCloud(
_visualizer->addPointCloud (binaryCloud, colorHandler, origin, orientation, id, viewport); _visualizer->addPointCloud (binaryCloud, colorHandler, origin, orientation, id, viewport);
// x,y,z // x,y,z
colorHandler.reset (new PointCloudColorHandlerMinMaxGenericField (binaryCloud, "x", colorHandler.reset (new pcl::visualization::PointCloudColorHandlerGenericField<pcl::PCLPointCloud2> (binaryCloud, "x"));
_cloudColorRangeMin==0.0f?std::numeric_limits<float>::lowest():_cloudColorRangeMin,
_cloudColorRangeMax==0.0f?std::numeric_limits<float>::max():_cloudColorRangeMax,
_aCloudColorRangeInverted->isChecked()));
_visualizer->addPointCloud (binaryCloud, colorHandler, origin, orientation, id, viewport); _visualizer->addPointCloud (binaryCloud, colorHandler, origin, orientation, id, viewport);
colorHandler.reset (new PointCloudColorHandlerMinMaxGenericField (binaryCloud, "y", colorHandler.reset (new pcl::visualization::PointCloudColorHandlerGenericField<pcl::PCLPointCloud2> (binaryCloud, "y"));
_cloudColorRangeMin==0.0f?std::numeric_limits<float>::lowest():_cloudColorRangeMin,
_cloudColorRangeMax==0.0f?std::numeric_limits<float>::max():_cloudColorRangeMax,
_aCloudColorRangeInverted->isChecked()));
_visualizer->addPointCloud (binaryCloud, colorHandler, origin, orientation, id, viewport); _visualizer->addPointCloud (binaryCloud, colorHandler, origin, orientation, id, viewport);
colorHandler.reset (new PointCloudColorHandlerMinMaxGenericField (binaryCloud, "z", colorHandler.reset (new pcl::visualization::PointCloudColorHandlerGenericField<pcl::PCLPointCloud2> (binaryCloud, "z"));
_cloudColorRangeMin==0.0f?std::numeric_limits<float>::lowest():_cloudColorRangeMin,
_cloudColorRangeMax==0.0f?std::numeric_limits<float>::max():_cloudColorRangeMax,
_aCloudColorRangeInverted->isChecked()));
_visualizer->addPointCloud (binaryCloud, colorHandler, origin, orientation, id, viewport); _visualizer->addPointCloud (binaryCloud, colorHandler, origin, orientation, id, viewport);
if(rgb) if(rgb)
@@ -3172,12 +3285,6 @@ bool CloudViewer::getCloudVisibility(const std::string & id)
return false; return false;
} }
int CloudViewer::getCloudColorIndex(const std::string & id) const
{
return _visualizer->getColorHandlerIndex(id);
}
void CloudViewer::setCloudColorIndex(const std::string & id, int index) void CloudViewer::setCloudColorIndex(const std::string & id, int index)
{ {
if(index>0) if(index>0)
@@ -3186,26 +3293,6 @@ void CloudViewer::setCloudColorIndex(const std::string & id, int index)
} }
} }
double CloudViewer::getCloudOpacity(const std::string & id) const
{
double opacity = 1.0;
if(!_visualizer->getPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_OPACITY, opacity, id))
{
#if VTK_MAJOR_VERSION >= 7
pcl::visualization::ShapeActorMap::iterator am_it = _visualizer->getShapeActorMap()->find (id);
if (am_it != _visualizer->getShapeActorMap()->end ())
{
vtkActor* actor = vtkActor::SafeDownCast (am_it->second);
if(actor)
{
opacity = actor->GetProperty ()->GetOpacity ();
}
}
#endif
}
return opacity;
}
void CloudViewer::setCloudOpacity(const std::string & id, double opacity) void CloudViewer::setCloudOpacity(const std::string & id, double opacity)
{ {
double lastOpacity; double lastOpacity;
@@ -3233,12 +3320,6 @@ void CloudViewer::setCloudOpacity(const std::string & id, double opacity)
#endif #endif
} }
int CloudViewer::getCloudPointSize(const std::string & id) const
{
double size = 1.0;
_visualizer->getPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, size, id);
return (int)size;
}
void CloudViewer::setCloudPointSize(const std::string & id, int size) void CloudViewer::setCloudPointSize(const std::string & id, int size)
{ {
double lastSize; double lastSize;
@@ -3530,33 +3611,9 @@ void CloudViewer::setIntensityMax(float value)
} }
else else
{ {
UERROR("Cannot set intensity < 0, value=%f", value); UERROR("Cannot set normals scale < 0, value=%f", value);
} }
} }
float CloudViewer::getCloudColorRangeMin() const
{
return _cloudColorRangeMin;
}
float CloudViewer::getCloudColorRangeMax() const
{
return _cloudColorRangeMax;
}
bool CloudViewer::isCloudColorRangeInverted() const
{
return _aCloudColorRangeInverted->isChecked();
}
void CloudViewer::setCloudColorRangeMin(float value)
{
_cloudColorRangeMin = value;
}
void CloudViewer::setCloudColorRangeMax(float value)
{
_cloudColorRangeMax = value;
}
void CloudViewer::setCloudColorRangeInverted(bool enabled)
{
_aCloudColorRangeInverted->setChecked(enabled);
}
void CloudViewer::buildPickingLocator(bool enable) void CloudViewer::buildPickingLocator(bool enable)
{ {
@@ -3927,30 +3984,6 @@ void CloudViewer::handleAction(QAction * a)
{ {
this->setIntensityRainbowColormap(_aSetIntensityRainbowColormap->isChecked()); this->setIntensityRainbowColormap(_aSetIntensityRainbowColormap->isChecked());
} }
else if(a == _aSetCloudColorRangeMin)
{
bool ok;
double value = QInputDialog::getDouble(this, tr("Set minimum axis color range"), tr("Range (0=auto)"), _cloudColorRangeMin, -99999, 99999, 2, &ok);
if(ok)
{
this->setCloudColorRangeMin(value);
}
}
else if(a == _aSetCloudColorRangeMax)
{
bool ok;
double value = QInputDialog::getDouble(this, tr("Set maximum axis color range"), tr("Range (0=auto)"), _cloudColorRangeMax, -99999, 99999, 2, &ok);
if(ok)
{
this->setCloudColorRangeMax(value);
}
}
else if(a == _aClearCloudColorRanges)
{
_cloudColorRangeMin = 0.0f;
_cloudColorRangeMax = 0.0f;
_aCloudColorRangeInverted->setChecked(false);
}
else if(a == _aSetBackgroundColor) else if(a == _aSetBackgroundColor)
{ {
QColor color = this->getDefaultBackgroundColor(); QColor color = this->getDefaultBackgroundColor();
+9 -50
View File
@@ -445,7 +445,6 @@ DatabaseViewer::DatabaseViewer(const QString & ini, QWidget * parent) :
connect(ui_->graphViewer, SIGNAL(configChanged()), this, SLOT(configModified())); connect(ui_->graphViewer, SIGNAL(configChanged()), this, SLOT(configModified()));
connect(ui_->graphicsView_A, SIGNAL(configChanged()), this, SLOT(configModified())); connect(ui_->graphicsView_A, SIGNAL(configChanged()), this, SLOT(configModified()));
connect(ui_->graphicsView_B, SIGNAL(configChanged()), this, SLOT(configModified())); connect(ui_->graphicsView_B, SIGNAL(configChanged()), this, SLOT(configModified()));
connect(cloudViewer_, SIGNAL(configChanged()), this, SLOT(configModified()));
connect(ui_->comboBox_logger_level, SIGNAL(currentIndexChanged(int)), this, SLOT(configModified())); connect(ui_->comboBox_logger_level, SIGNAL(currentIndexChanged(int)), this, SLOT(configModified()));
connect(ui_->actionVertical_Layout, SIGNAL(toggled(bool)), this, SLOT(configModified())); connect(ui_->actionVertical_Layout, SIGNAL(toggled(bool)), this, SLOT(configModified()));
connect(ui_->actionConcise_Layout, SIGNAL(toggled(bool)), this, SLOT(configModified())); connect(ui_->actionConcise_Layout, SIGNAL(toggled(bool)), this, SLOT(configModified()));
@@ -654,9 +653,6 @@ void DatabaseViewer::readSettings()
ui_->graphicsView_A->loadSettings(settings, "ImageViewA"); ui_->graphicsView_A->loadSettings(settings, "ImageViewA");
ui_->graphicsView_B->loadSettings(settings, "ImageViewB"); ui_->graphicsView_B->loadSettings(settings, "ImageViewB");
// CloudViewer
cloudViewer_->loadSettings(settings, "CloudViewer");
// ICP parameters // ICP parameters
settings.beginGroup("icp"); settings.beginGroup("icp");
ui_->spinBox_icp_decimation->setValue(settings.value("decimation", ui_->spinBox_icp_decimation->value()).toInt()); ui_->spinBox_icp_decimation->setValue(settings.value("decimation", ui_->spinBox_icp_decimation->value()).toInt());
@@ -751,9 +747,6 @@ void DatabaseViewer::writeSettings()
ui_->graphicsView_A->saveSettings(settings, "ImageViewA"); ui_->graphicsView_A->saveSettings(settings, "ImageViewA");
ui_->graphicsView_B->saveSettings(settings, "ImageViewB"); ui_->graphicsView_B->saveSettings(settings, "ImageViewB");
// CloudViewer
cloudViewer_->saveSettings(settings, "CloudViewer");
// save ICP parameters // save ICP parameters
settings.beginGroup("icp"); settings.beginGroup("icp");
settings.setValue("decimation", ui_->spinBox_icp_decimation->value()); settings.setValue("decimation", ui_->spinBox_icp_decimation->value());
@@ -3488,24 +3481,18 @@ void DatabaseViewer::exportOptimizedMesh()
path += ".obj"; path += ".obj";
} }
QString baseName = QFileInfo(path).baseName(); QString baseName = QFileInfo(path).baseName();
UDEBUG("Materials: %d", mesh->tex_materials.size());
if(mesh->tex_materials.size() == 1) if(mesh->tex_materials.size() == 1)
{ {
mesh->tex_materials.at(0).tex_file = baseName.toStdString() + ".png"; mesh->tex_materials.at(0).tex_file = baseName.toStdString() + ".png";
std::string filename = (QFileInfo(path).absoluteDir().absolutePath()+QDir::separator()+baseName).toStdString() + ".png"; cv::imwrite((QFileInfo(path).absoluteDir().absolutePath()+QDir::separator()+baseName).toStdString() + ".png", textures);
cv::imwrite(filename, textures);
UDEBUG("Saved %s", filename.c_str());
} }
else else
{ {
QDir(QFileInfo(path).absoluteDir().absolutePath()).mkdir(baseName);
for(unsigned int i=0; i<mesh->tex_materials.size(); ++i) for(unsigned int i=0; i<mesh->tex_materials.size(); ++i)
{ {
mesh->tex_materials.at(i).tex_file = (baseName+QDir::separator()+QString::number(i)+".png").toStdString(); mesh->tex_materials.at(i).tex_file = (baseName+QDir::separator()+QString::number(i)+".png").toStdString();
UASSERT((i+1)*textures.rows <= (unsigned int)textures.cols); UASSERT((i+1)*textures.rows <= (unsigned int)textures.cols);
std::string filename = (QFileInfo(path).absoluteDir().absolutePath()+QDir::separator()+baseName+QDir::separator()+QString::number(i)+".png").toStdString(); cv::imwrite((QFileInfo(path).absoluteDir().absolutePath()+QDir::separator()+baseName+QDir::separator()+QString::number(i)+".png").toStdString(), textures(cv::Range::all(), cv::Range(i*textures.rows, (i+1)*textures.rows)));
cv::imwrite(filename, textures(cv::Range::all(), cv::Range(i*textures.rows, (i+1)*textures.rows)));
UDEBUG("Saved %s", filename.c_str());
} }
} }
pcl::io::saveOBJFile(path.toStdString(), *mesh); pcl::io::saveOBJFile(path.toStdString(), *mesh);
@@ -5145,15 +5132,6 @@ void DatabaseViewer::update(int value,
cloudViewer_->removeAllLines(); cloudViewer_->removeAllLines();
cloudViewer_->removeAllFrustums(); cloudViewer_->removeAllFrustums();
cloudViewer_->removeOccupancyGridMap(); cloudViewer_->removeOccupancyGridMap();
std::map<std::string, std::pair<int, int> > colorIndexAndPointSizeMap;
for(auto iter=cloudViewer_->getAddedClouds().constBegin(); iter!=cloudViewer_->getAddedClouds().constEnd(); ++iter) {
if(uStrContains(iter.key(), "cloud") || uStrContains(iter.key(), "scan")) {
colorIndexAndPointSizeMap.insert(std::make_pair(iter.key(),
std::make_pair(
cloudViewer_->getCloudColorIndex(iter.key())+1,
cloudViewer_->getCloudPointSize(iter.key()))));
}
}
cloudViewer_->removeAllClouds(); cloudViewer_->removeAllClouds();
cloudViewer_->removeOctomap(); cloudViewer_->removeOctomap();
cloudViewer_->removeElevationMap(); cloudViewer_->removeElevationMap();
@@ -5211,10 +5189,6 @@ void DatabaseViewer::update(int value,
pcl::PointCloud<pcl::PointXYZ>::Ptr scan = util3d::laserScanToPointCloud(laserScanRaw, laserScanRaw.localTransform()); pcl::PointCloud<pcl::PointXYZ>::Ptr scan = util3d::laserScanToPointCloud(laserScanRaw, laserScanRaw.localTransform());
cloudViewer_->addCloud("scan", scan, pose, Qt::yellow); cloudViewer_->addCloud("scan", scan, pose, Qt::yellow);
} }
if(colorIndexAndPointSizeMap.find("scan") != colorIndexAndPointSizeMap.end()) {
cloudViewer_->setCloudColorIndex("scan", colorIndexAndPointSizeMap.at("scan").first);
cloudViewer_->setCloudPointSize("scan", colorIndexAndPointSizeMap.at("scan").second);
}
} }
// add RGB-D cloud // add RGB-D cloud
@@ -5301,10 +5275,6 @@ void DatabaseViewer::update(int value,
} }
cloudViewer_->addCloud("cloud", cloudValidPoints, pose); cloudViewer_->addCloud("cloud", cloudValidPoints, pose);
if(colorIndexAndPointSizeMap.find("cloud") != colorIndexAndPointSizeMap.end()) {
cloudViewer_->setCloudColorIndex("cloud", colorIndexAndPointSizeMap.at("cloud").first);
cloudViewer_->setCloudPointSize("cloud", colorIndexAndPointSizeMap.at("cloud").second);
}
} }
else else
{ {
@@ -5428,12 +5398,7 @@ void DatabaseViewer::update(int value,
} }
if(ui_->checkBox_showCloud->isChecked()) if(ui_->checkBox_showCloud->isChecked())
{ {
std::string cloudName = uFormat("cloud_%d", i); cloudViewer_->addCloud(uFormat("cloud_%d", i), cloud, pose);
cloudViewer_->addCloud(cloudName, cloud, pose);
if(colorIndexAndPointSizeMap.find(cloudName) != colorIndexAndPointSizeMap.end()) {
cloudViewer_->setCloudColorIndex(cloudName, colorIndexAndPointSizeMap.at(cloudName).first);
cloudViewer_->setCloudPointSize(cloudName, colorIndexAndPointSizeMap.at(cloudName).second);
}
} }
} }
} }
@@ -5463,12 +5428,7 @@ void DatabaseViewer::update(int value,
cloud = util3d::voxelize(cloud, indices, ui_->doubleSpinBox_voxelSize->value()); cloud = util3d::voxelize(cloud, indices, ui_->doubleSpinBox_voxelSize->value());
} }
std::string cloudName = uFormat("cloud_%d", i); cloudViewer_->addCloud(uFormat("cloud_%d", i), cloud, pose);
cloudViewer_->addCloud(cloudName, cloud, pose);
if(colorIndexAndPointSizeMap.find(cloudName) != colorIndexAndPointSizeMap.end()) {
cloudViewer_->setCloudColorIndex(cloudName, colorIndexAndPointSizeMap.at(cloudName).first);
cloudViewer_->setCloudPointSize(cloudName, colorIndexAndPointSizeMap.at(cloudName).second);
}
} }
} }
} }
@@ -8361,7 +8321,7 @@ void DatabaseViewer::refineConstraint(int from, int to, Registration * reg, Regi
} }
Transform toPoseInv = filteredScanPoses.at(currentLink.to()).inverse(); Transform toPoseInv = filteredScanPoses.at(currentLink.to()).inverse();
dbDriver_->loadNodeData(*fromS, !silent, true, !silent, !silent); dbDriver_->loadNodeData(fromS, !silent, true, !silent, !silent);
fromS->sensorData().uncompressData(); fromS->sensorData().uncompressData();
LaserScan fromScan = fromS->sensorData().laserScanRaw(); LaserScan fromScan = fromS->sensorData().laserScanRaw();
int maxPoints = fromScan.size(); int maxPoints = fromScan.size();
@@ -8507,8 +8467,8 @@ void DatabaseViewer::refineConstraint(int from, int to, Registration * reg, Regi
reextractVisualFeatures || reextractVisualFeatures ||
!silent) !silent)
{ {
dbDriver_->loadNodeData(*fromS, reextractVisualFeatures || !silent || (reg->isScanRequired() && ui_->checkBox_icp_from_depth->isChecked()), reg->isScanRequired() || !silent, reg->isUserDataRequired() || !silent, !silent); dbDriver_->loadNodeData(fromS, reextractVisualFeatures || !silent || (reg->isScanRequired() && ui_->checkBox_icp_from_depth->isChecked()), reg->isScanRequired() || !silent, reg->isUserDataRequired() || !silent, !silent);
dbDriver_->loadNodeData(*toS, reextractVisualFeatures || !silent || (reg->isScanRequired() && ui_->checkBox_icp_from_depth->isChecked()), reg->isScanRequired() || !silent, reg->isUserDataRequired() || !silent, !silent); dbDriver_->loadNodeData(toS, reextractVisualFeatures || !silent || (reg->isScanRequired() && ui_->checkBox_icp_from_depth->isChecked()), reg->isScanRequired() || !silent, reg->isUserDataRequired() || !silent, !silent);
if(!silent) if(!silent)
{ {
@@ -8603,7 +8563,6 @@ void DatabaseViewer::refineConstraint(int from, int to, Registration * reg, Regi
if(!transform.isNull()) if(!transform.isNull())
{ {
UASSERT(!info.covariance.empty());
if(!transform.isIdentity()) if(!transform.isIdentity())
{ {
if(info.covariance.at<double>(0,0)<=0.0) if(info.covariance.at<double>(0,0)<=0.0)
@@ -8797,9 +8756,9 @@ bool DatabaseViewer::addConstraint(int from, int to, Registration * reg, bool si
!silent) !silent)
{ {
// Add sensor data to generate features // Add sensor data to generate features
dbDriver_->loadNodeData(*fromS, reextractVisualFeatures || !silent || (reg->isScanRequired() && ui_->checkBox_icp_from_depth->isChecked()), reg->isScanRequired() || !silent, reg->isUserDataRequired() || !silent, !silent); dbDriver_->loadNodeData(fromS, reextractVisualFeatures || !silent || (reg->isScanRequired() && ui_->checkBox_icp_from_depth->isChecked()), reg->isScanRequired() || !silent, reg->isUserDataRequired() || !silent, !silent);
fromS->sensorData().uncompressData(); fromS->sensorData().uncompressData();
dbDriver_->loadNodeData(*toS, reextractVisualFeatures || !silent || (reg->isScanRequired() && ui_->checkBox_icp_from_depth->isChecked()), reg->isScanRequired() || !silent, reg->isUserDataRequired() || !silent, !silent); dbDriver_->loadNodeData(toS, reextractVisualFeatures || !silent || (reg->isScanRequired() && ui_->checkBox_icp_from_depth->isChecked()), reg->isScanRequired() || !silent, reg->isUserDataRequired() || !silent, !silent);
toS->sensorData().uncompressData(); toS->sensorData().uncompressData();
if(reextractVisualFeatures) if(reextractVisualFeatures)
{ {
+11 -19
View File
@@ -568,7 +568,7 @@ void GraphViewer::updateGraph(const std::map<int, Transform> & poses,
item->setZValue(iter->first<0?21:20); item->setZValue(iter->first<0?21:20);
item->setColor(color); item->setColor(color);
item->setParentItem(_graphRoot); item->setParentItem(_graphRoot);
item->show(); item->setVisible(_nodeVisible);
_nodeItems.insert(iter->first, item); _nodeItems.insert(iter->first, item);
} }
} }
@@ -577,40 +577,33 @@ void GraphViewer::updateGraph(const std::map<int, Transform> & poses,
for(std::multimap<int, Link>::const_iterator iter=constraints.begin(); iter!=constraints.end(); ++iter) for(std::multimap<int, Link>::const_iterator iter=constraints.begin(); iter!=constraints.end(); ++iter)
{ {
// make the first id the smallest one // make the first id the smallest one
int idFrom = iter->second.from() < iter->second.to() ? iter->second.from() : iter->second.to(); int idFrom = iter->first<iter->second.to()?iter->first:iter->second.to();
int idTo = iter->second.from() < iter->second.to() ? iter->second.to() : iter->second.from(); int idTo = iter->first<iter->second.to()?iter->second.to():iter->first;
if(idFrom == idTo) {
continue;
}
std::map<int, Transform>::const_iterator jterA = poses.find(idFrom); std::map<int, Transform>::const_iterator jterA = poses.find(idFrom);
std::map<int, Transform>::const_iterator jterB = poses.find(idTo); std::map<int, Transform>::const_iterator jterB = poses.find(idTo);
LinkItem * linkItem = 0; LinkItem * linkItem = 0;
if(jterA != poses.end() && jterB != poses.end() && if(jterA != poses.end() && jterB != poses.end() &&
_nodeItems.contains(idFrom) && _nodeItems.contains(idTo)) _nodeItems.contains(iter->first) && _nodeItems.contains(idTo))
{ {
const Transform & poseA = jterA->second; const Transform & poseA = jterA->second;
const Transform & poseB = jterB->second; const Transform & poseB = jterB->second;
QMultiMap<int, LinkItem*>::iterator itemIter = _linkItems.end(); QMultiMap<int, LinkItem*>::iterator itemIter = _linkItems.end();
if(_linkItems.contains(idFrom)) if(_linkItems.contains(idFrom))
{ {
itemIter = _linkItems.find(idFrom); itemIter = _linkItems.find(iter->first);
bool alreadyAdded = false; while(itemIter.key() == idFrom && itemIter != _linkItems.end())
while(itemIter != _linkItems.end() && itemIter.key() == idFrom)
{ {
if(itemIter.value()->to() == idTo && itemIter.value()->isVisible()) if(itemIter.value()->to() == idTo && itemIter.value()->type() == iter->second.type())
{ {
alreadyAdded = true; itemIter.value()->setPoses(poseA, poseB, _viewPlane);
itemIter.value()->show();
linkItem = itemIter.value();
break; break;
} }
++itemIter; ++itemIter;
} }
if(alreadyAdded){
continue;
}
} }
bool interSessionClosure = false; bool interSessionClosure = false;
@@ -749,7 +742,6 @@ void GraphViewer::updateGraph(const std::map<int, Transform> & poses,
} }
else else
{ {
iter.value()->setVisible(_nodeVisible);
++iter; ++iter;
} }
} }
@@ -1193,7 +1185,7 @@ void GraphViewer::setNodeInfo(int id, const QString & info)
} }
else else
{ {
UWARN("Node %d not found in the graph", id); UWARN("Current goal %d not found in the graph", id);
} }
} }
-1
View File
@@ -44,7 +44,6 @@
<file>images/oakd.png</file> <file>images/oakd.png</file>
<file>images/oakd_lite.png</file> <file>images/oakd_lite.png</file>
<file>images/astra.png</file> <file>images/astra.png</file>
<file>images/astra2.png</file>
<file>images/oakdpro.png</file> <file>images/oakdpro.png</file>
<file>images/seer_sense_DS80.png</file> <file>images/seer_sense_DS80.png</file>
</qresource> </qresource>
+10 -91
View File
@@ -266,16 +266,14 @@ ImageView::ImageView(QWidget * parent) :
_colorMapBlueToRed = colorMap->addAction(tr("Blue to red")); _colorMapBlueToRed = colorMap->addAction(tr("Blue to red"));
_colorMapBlueToRed->setCheckable(true); _colorMapBlueToRed->setCheckable(true);
_colorMapBlueToRed->setChecked(false); _colorMapBlueToRed->setChecked(false);
_colorMapInCameraFrame = colorMap->addAction(tr("Camera Frame")); _colorMapMinRange = colorMap->addAction(tr("Min Range..."));
_colorMapInCameraFrame->setCheckable(true); _colorMapMaxRange = colorMap->addAction(tr("Max Range..."));
_colorMapInCameraFrame->setChecked(true);
_colorMapMinRange = colorMap->addAction(tr("Min Z..."));
_colorMapMaxRange = colorMap->addAction(tr("Max Z..."));
group = new QActionGroup(this); group = new QActionGroup(this);
group->addAction(_colorMapWhiteToBlack); group->addAction(_colorMapWhiteToBlack);
group->addAction(_colorMapBlackToWhite); group->addAction(_colorMapBlackToWhite);
group->addAction(_colorMapRedToBlue); group->addAction(_colorMapRedToBlue);
group->addAction(_colorMapBlueToRed); group->addAction(_colorMapBlueToRed);
group->addAction(_colorMapMaxRange);
_mouseTracking = _menu->addAction(tr("Show pixel depth")); _mouseTracking = _menu->addAction(tr("Show pixel depth"));
_mouseTracking->setCheckable(true); _mouseTracking->setCheckable(true);
_mouseTracking->setChecked(false); _mouseTracking->setChecked(false);
@@ -313,7 +311,6 @@ void ImageView::saveSettings(QSettings & settings, const QString & group) const
settings.setValue("graphics_view_scale", this->isGraphicsViewScaled()); settings.setValue("graphics_view_scale", this->isGraphicsViewScaled());
settings.setValue("graphics_view_scale_to_height", this->isGraphicsViewScaledToHeight()); settings.setValue("graphics_view_scale_to_height", this->isGraphicsViewScaledToHeight());
settings.setValue("colormap", _colorMapWhiteToBlack->isChecked()?0:_colorMapBlackToWhite->isChecked()?1:_colorMapRedToBlue->isChecked()?2:3); settings.setValue("colormap", _colorMapWhiteToBlack->isChecked()?0:_colorMapBlackToWhite->isChecked()?1:_colorMapRedToBlue->isChecked()?2:3);
settings.setValue("colormap_camera_frame", this->isDepthColorMapInCameraFrame());
settings.setValue("colormap_min_range", this->getDepthColorMapMinRange()); settings.setValue("colormap_min_range", this->getDepthColorMapMinRange());
settings.setValue("colormap_max_range", this->getDepthColorMapMaxRange()); settings.setValue("colormap_max_range", this->getDepthColorMapMaxRange());
if(!group.isEmpty()) if(!group.isEmpty())
@@ -348,7 +345,6 @@ void ImageView::loadSettings(QSettings & settings, const QString & group)
_colorMapBlackToWhite->setChecked(colorMap==1); _colorMapBlackToWhite->setChecked(colorMap==1);
_colorMapRedToBlue->setChecked(colorMap==2); _colorMapRedToBlue->setChecked(colorMap==2);
_colorMapBlueToRed->setChecked(colorMap==3); _colorMapBlueToRed->setChecked(colorMap==3);
this->setDepthColorMapInCameraFrame(settings.value("colormap_camera_frame", this->isDepthColorMapInCameraFrame()).toBool());
this->setDepthColorMapRange( this->setDepthColorMapRange(
settings.value("colormap_min_range", this->getDepthColorMapMinRange()).toFloat(), settings.value("colormap_min_range", this->getDepthColorMapMinRange()).toFloat(),
settings.value("colormap_max_range", settings.value("colormap_range" /*backward compatibility*/, this->getDepthColorMapMaxRange())).toFloat()); settings.value("colormap_max_range", settings.value("colormap_range" /*backward compatibility*/, this->getDepthColorMapMaxRange())).toFloat());
@@ -767,20 +763,13 @@ void ImageView::setBackgroundColor(const QColor & color)
} }
} }
void ImageView::setDepthColorMapInCameraFrame(bool enabled) {
_colorMapInCameraFrame->setChecked(enabled);
}
bool ImageView::isDepthColorMapInCameraFrame() const {
return _colorMapInCameraFrame->isChecked();
}
void ImageView::setDepthColorMapRange(float min, float max) void ImageView::setDepthColorMapRange(float min, float max)
{ {
_depthColorMapMinRange = min; _depthColorMapMinRange = min;
_depthColorMapMaxRange = max; _depthColorMapMaxRange = max;
} }
void ImageView::computeScaleOffsets(const QRect & targetRect, float & scale, float & offsetX, float & offsetY) const void ImageView::computeScaleOffsets(const QRect & targetRect, float & scale, float & offsetX, float & offsetY) const
{ {
scale = 1.0f; scale = 1.0f;
@@ -1065,17 +1054,10 @@ void ImageView::contextMenuEvent(QContextMenuEvent * e)
} }
Q_EMIT configChanged(); Q_EMIT configChanged();
} }
else if(action == _colorMapInCameraFrame)
{
if(!_imageDepthCv.empty()) {
this->setImageDepth(_imageDepthCv, _imageDepthConfidenceCv);
}
Q_EMIT configChanged();
}
else if(action == _colorMapMinRange) else if(action == _colorMapMinRange)
{ {
bool ok = false; bool ok = false;
double value = QInputDialog::getDouble(this, tr("Set depth colormap min range"), tr("Range (m), 0=no limit"), _depthColorMapMinRange, -9999, 9999, 2, &ok); double value = QInputDialog::getDouble(this, tr("Set depth colormap min range"), tr("Range (m), 0=no limit"), _depthColorMapMinRange, 0, 9999, 1, &ok);
if(ok) if(ok)
{ {
this->setDepthColorMapRange(value, _depthColorMapMaxRange); this->setDepthColorMapRange(value, _depthColorMapMaxRange);
@@ -1088,7 +1070,7 @@ void ImageView::contextMenuEvent(QContextMenuEvent * e)
else if(action == _colorMapMaxRange) else if(action == _colorMapMaxRange)
{ {
bool ok = false; bool ok = false;
double value = QInputDialog::getDouble(this, tr("Set depth colormap max range"), tr("Range (m), 0=no limit"), _depthColorMapMaxRange, -9999, 9999, 2, &ok); double value = QInputDialog::getDouble(this, tr("Set depth colormap max range"), tr("Range (m), 0=no limit"), _depthColorMapMaxRange, 0, 9999, 1, &ok);
if(ok) if(ok)
{ {
this->setDepthColorMapRange(_depthColorMapMinRange, value); this->setDepthColorMapRange(_depthColorMapMinRange, value);
@@ -1148,7 +1130,7 @@ void ImageView::mouseMoveEvent(QMouseEvent * event)
float u = (event->pos().x() - offsetX) / scale; float u = (event->pos().x() - offsetX) / scale;
float v = (event->pos().y() - offsetY) / scale; float v = (event->pos().y() - offsetY) / scale;
float depthScale = 1; float depthScale = 1;
if(_image.width() != _imageDepthCv.cols) if(_image.width() > _imageDepthCv.cols)
{ {
depthScale = float(_imageDepthCv.cols) / float(_image.width()); depthScale = float(_imageDepthCv.cols) / float(_image.width());
} }
@@ -1368,71 +1350,8 @@ void ImageView::setImageDepth(const cv::Mat & imageDepth, const cv::Mat & imageD
{ {
_imageDepthCv = imageDepth; _imageDepthCv = imageDepth;
_imageDepthConfidenceCv = imageDepthConfidence; _imageDepthConfidenceCv = imageDepthConfidence;
QImage depth;
if(!_imageDepthCv.empty() && (_imageDepthCv.type() == CV_16UC1 || _imageDepthCv.type() == CV_32FC1)) {
if(_colorMapInCameraFrame->isChecked() || _models.empty() || !_models[0].isValidForProjection()) {
depth = uCvMat2QImage(_imageDepthCv, true, getDepthColorMap(), _depthColorMapMinRange, _depthColorMapMaxRange);
if(!_colorMapInCameraFrame->isChecked()) {
UWARN("Trying to set depth color map in base frame but the the camera model "
"is not valid for projection, showing depth in camera frame instead.");
}
}
else {
// convert the depth values in height values
cv::Mat depthInBaseFrame = _imageDepthCv.clone();
int subImageWidth = _imageDepthCv.cols / _models.size();
std::vector<CameraModel> models; // scale model to size of depth image if needed
for(const auto & model: _models) {
UASSERT(subImageWidth <= model.imageWidth());
if(subImageWidth < model.imageWidth()) {
models.push_back(model.scaled(float(subImageWidth)/float(model.imageWidth())));
}
else {
models.push_back(model);
}
}
if(depthInBaseFrame.type() == CV_16UC1) {
for(int v=0; v<depthInBaseFrame.rows; ++v){
unsigned short * rowPtr = depthInBaseFrame.ptr<unsigned short>(v);
for(int u=0; u<depthInBaseFrame.cols; ++u){
unsigned short & val = rowPtr[u];
if(val > 0) {
cv::Point3f pt;
int cameraIndex = u/subImageWidth;
UASSERT(cameraIndex>=0 && cameraIndex < (int)models.size() && subImageWidth == models[cameraIndex].imageWidth());
models[cameraIndex].project(u,v,float(val)/1000.0f, pt.x, pt.y, pt.z);
pt = util3d::transformPoint(pt, models[cameraIndex].localTransform());
val = (unsigned short)(pt.z*1000.0f);
}
}
}
}
else { // CV_32FC1
for(int v=0; v<depthInBaseFrame.rows; ++v){
float * rowPtr = depthInBaseFrame.ptr<float>(v);
for(int u=0; u<depthInBaseFrame.cols; ++u){
float & val = rowPtr[u];
if(val > 0) {
cv::Point3f pt;
int cameraIndex = u/subImageWidth;
UASSERT(cameraIndex>=0 && cameraIndex < (int)models.size() && subImageWidth == models[cameraIndex].imageWidth());
models[cameraIndex].project(u,v,val, pt.x, pt.y, pt.z);
pt = util3d::transformPoint(pt, models[cameraIndex].localTransform());
val = pt.z;
}
}
}
}
depth = uCvMat2QImage(depthInBaseFrame, true, getDepthColorMap(), _depthColorMapMinRange, _depthColorMapMaxRange);
}
}
else {
// right image grayscale or color
depth = uCvMat2QImage(_imageDepthCv, true, uCvQtDepthBlackToWhite);
}
setImageDepth( setImageDepth(
depth, uCvMat2QImage(_imageDepthCv, true, getDepthColorMap(), _depthColorMapMinRange, _depthColorMapMaxRange),
uCvMat2QImage(_imageDepthConfidenceCv, true, getDepthColorMap())); uCvMat2QImage(_imageDepthConfidenceCv, true, getDepthColorMap()));
} }
@@ -1448,8 +1367,8 @@ void ImageView::setImageDepth(const QImage & imageDepth, const QImage & imageDep
UASSERT(_imageDepth.width() && _imageDepth.height()); UASSERT(_imageDepth.width() && _imageDepth.height());
if( _image.width() > 0 && if( _image.width() > 0 &&
_image.width() != _imageDepth.width() && _image.width() > _imageDepth.width() &&
_image.height() != _imageDepth.height()) _image.height() > _imageDepth.height())
{ {
// scale depth to rgb // scale depth to rgb
_imageDepth = _imageDepth.scaled(_image.size()); _imageDepth = _imageDepth.scaled(_image.size());
+8 -30
View File
@@ -470,7 +470,6 @@ MainWindow::MainWindow(PreferencesDialog * prefDialog, QWidget * parent, bool sh
connect(_ui->actionDepthAI_oakdlite, SIGNAL(triggered()), this, SLOT(selectDepthAIOAKDLite())); connect(_ui->actionDepthAI_oakdlite, SIGNAL(triggered()), this, SLOT(selectDepthAIOAKDLite()));
connect(_ui->actionDepthAI_oakdpro, SIGNAL(triggered()), this, SLOT(selectDepthAIOAKDPro())); connect(_ui->actionDepthAI_oakdpro, SIGNAL(triggered()), this, SLOT(selectDepthAIOAKDPro()));
connect(_ui->actionXvisio_SeerSense, SIGNAL(triggered()), this, SLOT(selectXvisioSeerSense())); connect(_ui->actionXvisio_SeerSense, SIGNAL(triggered()), this, SLOT(selectXvisioSeerSense()));
connect(_ui->actionOrbbecSDK_astra2, SIGNAL(triggered()), this, SLOT(selectOrbbecSDK()));
connect(_ui->actionVelodyne_VLP_16, SIGNAL(triggered()), this, SLOT(selectVLP16())); connect(_ui->actionVelodyne_VLP_16, SIGNAL(triggered()), this, SLOT(selectVLP16()));
_ui->actionFreenect->setEnabled(CameraFreenect::available()); _ui->actionFreenect->setEnabled(CameraFreenect::available());
_ui->actionOpenNI_PCL->setEnabled(CameraOpenni::available()); _ui->actionOpenNI_PCL->setEnabled(CameraOpenni::available());
@@ -500,7 +499,6 @@ MainWindow::MainWindow(PreferencesDialog * prefDialog, QWidget * parent, bool sh
_ui->actionDepthAI_oakdlite->setEnabled(CameraDepthAI::available()); _ui->actionDepthAI_oakdlite->setEnabled(CameraDepthAI::available());
_ui->actionDepthAI_oakdpro->setEnabled(CameraDepthAI::available()); _ui->actionDepthAI_oakdpro->setEnabled(CameraDepthAI::available());
_ui->actionXvisio_SeerSense->setEnabled(CameraSeerSense::available()); _ui->actionXvisio_SeerSense->setEnabled(CameraSeerSense::available());
_ui->actionOrbbecSDK_astra2->setEnabled(CameraOrbbecSDK::available());
this->updateSelectSourceMenu(); this->updateSelectSourceMenu();
connect(_ui->actionPreferences, SIGNAL(triggered()), this, SLOT(openPreferences())); connect(_ui->actionPreferences, SIGNAL(triggered()), this, SLOT(openPreferences()));
@@ -1677,7 +1675,7 @@ void MainWindow::processOdometry(const rtabmap::OdometryEvent & odom, bool dataI
odom.info().type == (int)Odometry::kTypeViso2 || odom.info().type == (int)Odometry::kTypeViso2 ||
odom.info().type == (int)Odometry::kTypeFovis || odom.info().type == (int)Odometry::kTypeFovis ||
odom.info().type == (int)Odometry::kTypeMSCKF || odom.info().type == (int)Odometry::kTypeMSCKF ||
odom.info().type == (int)Odometry::kTypeVINSFusion || odom.info().type == (int)Odometry::kTypeVINS ||
odom.info().type == (int)Odometry::kTypeOpenVINS) odom.info().type == (int)Odometry::kTypeOpenVINS)
{ {
std::vector<cv::KeyPoint> kpts; std::vector<cv::KeyPoint> kpts;
@@ -1727,6 +1725,7 @@ void MainWindow::processOdometry(const rtabmap::OdometryEvent & odom, bool dataI
if( odom.info().type == (int)Odometry::kTypeF2M || if( odom.info().type == (int)Odometry::kTypeF2M ||
odom.info().type == (int)Odometry::kTypeORBSLAM || odom.info().type == (int)Odometry::kTypeORBSLAM ||
odom.info().type == (int)Odometry::kTypeMSCKF || odom.info().type == (int)Odometry::kTypeMSCKF ||
odom.info().type == (int)Odometry::kTypeVINS ||
odom.info().type == (int)Odometry::kTypeOpenVINS) odom.info().type == (int)Odometry::kTypeOpenVINS)
{ {
if(_ui->imageView_odometry->isFeaturesShown() && !_preferencesDialog->isOdomOnlyInliersShown()) if(_ui->imageView_odometry->isFeaturesShown() && !_preferencesDialog->isOdomOnlyInliersShown())
@@ -1743,7 +1742,6 @@ void MainWindow::processOdometry(const rtabmap::OdometryEvent & odom, bool dataI
} }
if((odom.info().type == (int)Odometry::kTypeF2F || if((odom.info().type == (int)Odometry::kTypeF2F ||
odom.info().type == (int)Odometry::kTypeViso2 || odom.info().type == (int)Odometry::kTypeViso2 ||
odom.info().type == (int)Odometry::kTypeVINSFusion ||
odom.info().type == (int)Odometry::kTypeFovis) && odom.info().refCorners.size()) odom.info().type == (int)Odometry::kTypeFovis) && odom.info().refCorners.size())
{ {
if(_ui->imageView_odometry->isFeaturesShown() || _ui->imageView_odometry->isLinesShown()) if(_ui->imageView_odometry->isFeaturesShown() || _ui->imageView_odometry->isLinesShown())
@@ -1797,7 +1795,6 @@ void MainWindow::processOdometry(const rtabmap::OdometryEvent & odom, bool dataI
//Process info //Process info
if(_preferencesDialog->isCacheSavedInFigures() || _ui->statsToolBox->isVisible()) if(_preferencesDialog->isCacheSavedInFigures() || _ui->statsToolBox->isVisible())
{ {
UASSERT(odom.info().reg.covariance.total() == 36 && odom.info().reg.covariance.type() == CV_64FC1);
double linVar = uMax3(odom.info().reg.covariance.at<double>(0,0), odom.info().reg.covariance.at<double>(1,1)>=9999?0:odom.info().reg.covariance.at<double>(1,1), odom.info().reg.covariance.at<double>(2,2)>=9999?0:odom.info().reg.covariance.at<double>(2,2)); double linVar = uMax3(odom.info().reg.covariance.at<double>(0,0), odom.info().reg.covariance.at<double>(1,1)>=9999?0:odom.info().reg.covariance.at<double>(1,1), odom.info().reg.covariance.at<double>(2,2)>=9999?0:odom.info().reg.covariance.at<double>(2,2));
double angVar = uMax3(odom.info().reg.covariance.at<double>(3,3)>=9999?0:odom.info().reg.covariance.at<double>(3,3), odom.info().reg.covariance.at<double>(4,4)>=9999?0:odom.info().reg.covariance.at<double>(4,4), odom.info().reg.covariance.at<double>(5,5)); double angVar = uMax3(odom.info().reg.covariance.at<double>(3,3)>=9999?0:odom.info().reg.covariance.at<double>(3,3), odom.info().reg.covariance.at<double>(4,4)>=9999?0:odom.info().reg.covariance.at<double>(4,4), odom.info().reg.covariance.at<double>(5,5));
_ui->statsToolBox->updateStat("Odometry/Inliers/", _preferencesDialog->isTimeUsedInFigures()?data->stamp()-_firstStamp:(float)data->id(), (float)odom.info().reg.inliers, _preferencesDialog->isCacheSavedInFigures()); _ui->statsToolBox->updateStat("Odometry/Inliers/", _preferencesDialog->isTimeUsedInFigures()?data->stamp()-_firstStamp:(float)data->id(), (float)odom.info().reg.inliers, _preferencesDialog->isCacheSavedInFigures());
@@ -2397,20 +2394,14 @@ void MainWindow::processStats(const rtabmap::Statistics & stat)
// do it after scaling // do it after scaling
std::multimap<int, cv::KeyPoint> wordsA; std::multimap<int, cv::KeyPoint> wordsA;
std::multimap<int, cv::KeyPoint> wordsB; std::multimap<int, cv::KeyPoint> wordsB;
if(signature.getWords().size() == signature.getWordsKpts().size())
{
for(std::map<int, int>::const_iterator iter=signature.getWords().begin(); iter!=signature.getWords().end(); ++iter) for(std::map<int, int>::const_iterator iter=signature.getWords().begin(); iter!=signature.getWords().end(); ++iter)
{ {
wordsA.insert(wordsA.end(), std::make_pair(iter->first, signature.getWordsKpts()[iter->second])); wordsA.insert(wordsA.end(), std::make_pair(iter->first, signature.getWordsKpts()[iter->second]));
} }
}
if(loopSignature.getWords().size() == loopSignature.getWordsKpts().size())
{
for(std::map<int, int>::const_iterator iter=loopSignature.getWords().begin(); iter!=loopSignature.getWords().end(); ++iter) for(std::map<int, int>::const_iterator iter=loopSignature.getWords().begin(); iter!=loopSignature.getWords().end(); ++iter)
{ {
wordsB.insert(wordsB.end(), std::make_pair(iter->first, loopSignature.getWordsKpts()[iter->second])); wordsB.insert(wordsB.end(), std::make_pair(iter->first, loopSignature.getWordsKpts()[iter->second]));
} }
}
this->drawKeypoints(wordsA, wordsB); this->drawKeypoints(wordsA, wordsB);
UDEBUG("time= %d ms (draw keypoints)", time.restart()); UDEBUG("time= %d ms (draw keypoints)", time.restart());
@@ -4372,7 +4363,7 @@ void MainWindow::createAndAddFeaturesToMap(int nodeId, const Transform & pose, i
UASSERT(iter->getWords().size() == iter->getWords3().size()); UASSERT(iter->getWords().size() == iter->getWords3().size());
float maxDepth = _preferencesDialog->getCloudMaxDepth(0); float maxDepth = _preferencesDialog->getCloudMaxDepth(0);
UDEBUG("rgb.channels()=%d"); UDEBUG("rgb.channels()=%d");
if(!iter->getWords3().empty() && iter->getWords3().size() == iter->getWordsKpts().size()) if(!iter->getWords3().empty() && !iter->getWordsKpts().empty())
{ {
Transform invLocalTransform = Transform::getIdentity(); Transform invLocalTransform = Transform::getIdentity();
if(iter.value().sensorData().cameraModels().size() == 1 && if(iter.value().sensorData().cameraModels().size() == 1 &&
@@ -5340,7 +5331,6 @@ void MainWindow::updateSelectSourceMenu()
_ui->actionDepthAI_oakdlite->setChecked(_preferencesDialog->getSourceDriver() == PreferencesDialog::kSrcStereoDepthAI); _ui->actionDepthAI_oakdlite->setChecked(_preferencesDialog->getSourceDriver() == PreferencesDialog::kSrcStereoDepthAI);
_ui->actionDepthAI_oakdpro->setChecked(_preferencesDialog->getSourceDriver() == PreferencesDialog::kSrcStereoDepthAI); _ui->actionDepthAI_oakdpro->setChecked(_preferencesDialog->getSourceDriver() == PreferencesDialog::kSrcStereoDepthAI);
_ui->actionXvisio_SeerSense->setChecked(_preferencesDialog->getSourceDriver() == PreferencesDialog::kSrcSeerSense); _ui->actionXvisio_SeerSense->setChecked(_preferencesDialog->getSourceDriver() == PreferencesDialog::kSrcSeerSense);
_ui->actionOrbbecSDK_astra2->setChecked(_preferencesDialog->getSourceDriver() == PreferencesDialog::kSrcOrbbecSDK);
_ui->actionVelodyne_VLP_16->setChecked(_preferencesDialog->getLidarSourceDriver() == PreferencesDialog::kSrcLidarVLP16); _ui->actionVelodyne_VLP_16->setChecked(_preferencesDialog->getLidarSourceDriver() == PreferencesDialog::kSrcLidarVLP16);
} }
@@ -5888,10 +5878,7 @@ void MainWindow::startDetection()
} }
} }
if((_preferencesDialog->getSourceDriver() == PreferencesDialog::kSrcDatabase || if(_preferencesDialog->getSourceDriver() == PreferencesDialog::kSrcDatabase &&
_preferencesDialog->getSourceDriver() == PreferencesDialog::kSrcImages ||
_preferencesDialog->getSourceDriver() == PreferencesDialog::kSrcStereoImages ||
_preferencesDialog->getSourceDriver() == PreferencesDialog::kSrcRGBDImages) &&
camera && camera->odomProvided()) camera && camera->odomProvided())
{ {
odomSensor = camera; odomSensor = camera;
@@ -5999,7 +5986,7 @@ void MainWindow::startDetection()
_imuThread = 0; _imuThread = 0;
} }
if((!_sensorCapture->odomProvided() || _preferencesDialog->isOdomAsGuessEnabled()) && !_preferencesDialog->isOdomDisabled()) if(!_sensorCapture->odomProvided() && !_preferencesDialog->isOdomDisabled())
{ {
ParametersMap odomParameters = parameters; ParametersMap odomParameters = parameters;
if(_preferencesDialog->getOdomRegistrationApproach() < 3) if(_preferencesDialog->getOdomRegistrationApproach() < 3)
@@ -6057,7 +6044,7 @@ void MainWindow::startDetection()
} }
} }
if(_dataRecorder && _sensorCapture) if(_dataRecorder && _sensorCapture && _odomThread)
{ {
UEventsManager::createPipe(_sensorCapture, _dataRecorder, "SensorEvent"); UEventsManager::createPipe(_sensorCapture, _dataRecorder, "SensorEvent");
} }
@@ -7217,11 +7204,6 @@ void MainWindow::selectK4A()
_preferencesDialog->selectSourceDriver(PreferencesDialog::kSrcK4A); _preferencesDialog->selectSourceDriver(PreferencesDialog::kSrcK4A);
} }
void MainWindow::selectOrbbecSDK()
{
_preferencesDialog->selectSourceDriver(PreferencesDialog::kSrcOrbbecSDK);
}
void MainWindow::selectRealSense() void MainWindow::selectRealSense()
{ {
_preferencesDialog->selectSourceDriver(PreferencesDialog::kSrcRealSense); _preferencesDialog->selectSourceDriver(PreferencesDialog::kSrcRealSense);
@@ -8708,13 +8690,11 @@ void MainWindow::changeState(MainWindow::State newState)
if(_sensorCapture) if(_sensorCapture)
{ {
_sensorCapture->start();
if(_imuThread) if(_imuThread)
{ {
_imuThread->start(); _imuThread->start();
// give imu thread a head start
uSleep(10);
} }
_sensorCapture->start();
ULogger::setTreadIdFilter(_preferencesDialog->getGeneralLoggerThreads()); ULogger::setTreadIdFilter(_preferencesDialog->getGeneralLoggerThreads());
} }
break; break;
@@ -8746,13 +8726,11 @@ void MainWindow::changeState(MainWindow::State newState)
if(_sensorCapture) if(_sensorCapture)
{ {
_sensorCapture->start();
if(_imuThread) if(_imuThread)
{ {
_imuThread->start(); _imuThread->start();
// give imu thread a head start
uSleep(10);
} }
_sensorCapture->start();
ULogger::setTreadIdFilter(_preferencesDialog->getGeneralLoggerThreads()); ULogger::setTreadIdFilter(_preferencesDialog->getGeneralLoggerThreads());
} }
} }
-2
View File
@@ -149,7 +149,6 @@ void MultiSessionLocWidget::updateView(
Link link = loopLinks.find(nodeId) != loopLinks.end()?loopLinks.find(nodeId)->second:Link(); Link link = loopLinks.find(nodeId) != loopLinks.end()?loopLinks.find(nodeId)->second:Link();
std::multimap<int, cv::KeyPoint> keypoints; std::multimap<int, cv::KeyPoint> keypoints;
if(s.getWords().size() == s.getWordsKpts().size()) {
for(std::multimap<int, int>::const_iterator jter=s.getWords().begin(); jter!=s.getWords().end(); ++jter) for(std::multimap<int, int>::const_iterator jter=s.getWords().begin(); jter!=s.getWords().end(); ++jter)
{ {
if(jter->first>0 && lastSignature.getWords().find(jter->first) != lastSignature.getWords().end()) if(jter->first>0 && lastSignature.getWords().find(jter->first) != lastSignature.getWords().end())
@@ -157,7 +156,6 @@ void MultiSessionLocWidget::updateView(
keypoints.insert(std::make_pair(jter->first, s.getWordsKpts()[jter->second])); keypoints.insert(std::make_pair(jter->first, s.getWordsKpts()[jter->second]));
} }
} }
}
if(!keypoints.empty()) if(!keypoints.empty())
{ {
+18 -93
View File
@@ -226,7 +226,7 @@ PreferencesDialog::PreferencesDialog(QWidget * parent) :
#ifndef RTABMAP_MSCKF_VIO #ifndef RTABMAP_MSCKF_VIO
_ui->odom_strategy->setItemData(8, 0, Qt::UserRole - 1); _ui->odom_strategy->setItemData(8, 0, Qt::UserRole - 1);
#endif #endif
#ifndef RTABMAP_VINS_FUSION #ifndef RTABMAP_VINS
_ui->odom_strategy->setItemData(9, 0, Qt::UserRole - 1); _ui->odom_strategy->setItemData(9, 0, Qt::UserRole - 1);
#endif #endif
#ifndef RTABMAP_OPENVINS #ifndef RTABMAP_OPENVINS
@@ -398,10 +398,6 @@ PreferencesDialog::PreferencesDialog(QWidget * parent) :
{ {
_ui->comboBox_cameraRGBD->setItemData(kSrcK4A - kSrcRGBD, 0, Qt::UserRole - 1); _ui->comboBox_cameraRGBD->setItemData(kSrcK4A - kSrcRGBD, 0, Qt::UserRole - 1);
} }
if (!CameraOrbbecSDK::available())
{
_ui->comboBox_cameraRGBD->setItemData(kSrcOrbbecSDK - kSrcRGBD, 0, Qt::UserRole - 1);
}
if (!CameraRealSense::available()) if (!CameraRealSense::available())
{ {
_ui->comboBox_cameraRGBD->setItemData(kSrcRealSense - kSrcRGBD, 0, Qt::UserRole - 1); _ui->comboBox_cameraRGBD->setItemData(kSrcRealSense - kSrcRGBD, 0, Qt::UserRole - 1);
@@ -771,39 +767,19 @@ PreferencesDialog::PreferencesDialog(QWidget * parent) :
connect(_ui->openni2_hshift, SIGNAL(valueChanged(int)), this, SLOT(makeObsoleteSourcePanel())); connect(_ui->openni2_hshift, SIGNAL(valueChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->openni2_vshift, SIGNAL(valueChanged(int)), this, SLOT(makeObsoleteSourcePanel())); connect(_ui->openni2_vshift, SIGNAL(valueChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->openni2_depth_decimation, SIGNAL(valueChanged(int)), this, SLOT(makeObsoleteSourcePanel())); connect(_ui->openni2_depth_decimation, SIGNAL(valueChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->comboBox_freenect2Format, SIGNAL(currentIndexChanged(int)), this, SLOT(makeObsoleteSourcePanel())); connect(_ui->comboBox_freenect2Format, SIGNAL(currentIndexChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->doubleSpinBox_freenect2MinDepth, SIGNAL(valueChanged(double)), this, SLOT(makeObsoleteSourcePanel())); connect(_ui->doubleSpinBox_freenect2MinDepth, SIGNAL(valueChanged(double)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->doubleSpinBox_freenect2MaxDepth, SIGNAL(valueChanged(double)), this, SLOT(makeObsoleteSourcePanel())); connect(_ui->doubleSpinBox_freenect2MaxDepth, SIGNAL(valueChanged(double)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->checkBox_freenect2BilateralFiltering, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteSourcePanel())); connect(_ui->checkBox_freenect2BilateralFiltering, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->checkBox_freenect2EdgeAwareFiltering, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteSourcePanel())); connect(_ui->checkBox_freenect2EdgeAwareFiltering, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->checkBox_freenect2NoiseFiltering, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteSourcePanel())); connect(_ui->checkBox_freenect2NoiseFiltering, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->lineEdit_freenect2Pipeline, SIGNAL(textChanged(const QString &)), this, SLOT(makeObsoleteSourcePanel())); connect(_ui->lineEdit_freenect2Pipeline, SIGNAL(textChanged(const QString &)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->comboBox_k4w2Format, SIGNAL(currentIndexChanged(int)), this, SLOT(makeObsoleteSourcePanel())); connect(_ui->comboBox_k4w2Format, SIGNAL(currentIndexChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->comboBox_k4a_rgb_resolution, SIGNAL(currentIndexChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->comboBox_k4a_framerate, SIGNAL(currentIndexChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->comboBox_k4a_depth_resolution, SIGNAL(currentIndexChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->checkbox_k4a_irDepth, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->lineEdit_k4a_mkv, SIGNAL(textChanged(const QString &)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->source_checkBox_useMKVStamps, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->spinBox_orbbec_sdk_color_width, SIGNAL(valueChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->spinBox_orbbec_sdk_color_height, SIGNAL(valueChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->spinBox_orbbec_sdk_depth_width, SIGNAL(valueChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->spinBox_orbbec_sdk_depth_height, SIGNAL(valueChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->checkBox_orbbec_sdk_color_rectification, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->checkBox_orbbec_sdk_imu, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->checkBox_orbbec_sdk_depth_mm, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->comboBox_realsensePresetRGB, SIGNAL(currentIndexChanged(int)), this, SLOT(makeObsoleteSourcePanel())); connect(_ui->comboBox_realsensePresetRGB, SIGNAL(currentIndexChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->comboBox_realsensePresetDepth, SIGNAL(currentIndexChanged(int)), this, SLOT(makeObsoleteSourcePanel())); connect(_ui->comboBox_realsensePresetDepth, SIGNAL(currentIndexChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->checkbox_realsenseOdom, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteSourcePanel())); connect(_ui->checkbox_realsenseOdom, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->checkbox_realsenseDepthScaledToRGBSize, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteSourcePanel())); connect(_ui->checkbox_realsenseDepthScaledToRGBSize, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->comboBox_realsenseRGBSource, SIGNAL(currentIndexChanged(int)), this, SLOT(makeObsoleteSourcePanel())); connect(_ui->comboBox_realsenseRGBSource, SIGNAL(currentIndexChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->checkbox_rs2_emitter, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteSourcePanel())); connect(_ui->checkbox_rs2_emitter, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->checkbox_rs2_irMode, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteSourcePanel())); connect(_ui->checkbox_rs2_irMode, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->checkbox_rs2_irDepth, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteSourcePanel())); connect(_ui->checkbox_rs2_irDepth, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
@@ -942,7 +918,6 @@ PreferencesDialog::PreferencesDialog(QWidget * parent) :
connect(_ui->doubleSpinBox_odom_sensor_scale_factor, SIGNAL(valueChanged(double)), this, SLOT(makeObsoleteSourcePanel())); connect(_ui->doubleSpinBox_odom_sensor_scale_factor, SIGNAL(valueChanged(double)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->doubleSpinBox_odom_sensor_wait_time, SIGNAL(valueChanged(double)), this, SLOT(makeObsoleteSourcePanel())); connect(_ui->doubleSpinBox_odom_sensor_wait_time, SIGNAL(valueChanged(double)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->checkBox_odom_sensor_use_as_gt, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteSourcePanel())); connect(_ui->checkBox_odom_sensor_use_as_gt, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->checkbox_passthrough_source_odom, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->comboBox_imuFilter_strategy, SIGNAL(currentIndexChanged(int)), this, SLOT(makeObsoleteSourcePanel())); connect(_ui->comboBox_imuFilter_strategy, SIGNAL(currentIndexChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->comboBox_imuFilter_strategy, SIGNAL(currentIndexChanged(int)), _ui->stackedWidget_imuFilter, SLOT(setCurrentIndex(int))); connect(_ui->comboBox_imuFilter_strategy, SIGNAL(currentIndexChanged(int)), _ui->stackedWidget_imuFilter, SLOT(setCurrentIndex(int)));
@@ -1030,7 +1005,6 @@ PreferencesDialog::PreferencesDialog(QWidget * parent) :
_ui->lineEdit_rgbCompressionFormat->setObjectName(Parameters::kMemImageCompressionFormat().c_str()); _ui->lineEdit_rgbCompressionFormat->setObjectName(Parameters::kMemImageCompressionFormat().c_str());
_ui->lineEdit_depthCompressionFormat->setObjectName(Parameters::kMemDepthCompressionFormat().c_str()); _ui->lineEdit_depthCompressionFormat->setObjectName(Parameters::kMemDepthCompressionFormat().c_str());
_ui->general_checkBox_keepDescriptors->setObjectName(Parameters::kMemRawDescriptorsKept().c_str()); _ui->general_checkBox_keepDescriptors->setObjectName(Parameters::kMemRawDescriptorsKept().c_str());
_ui->general_checkBox_loadVisualLocalFeaturesOnInit->setObjectName(Parameters::kMemLoadVisualLocalFeaturesOnInit().c_str());
_ui->general_checkBox_saveDepth16bits->setObjectName(Parameters::kMemSaveDepth16Format().c_str()); _ui->general_checkBox_saveDepth16bits->setObjectName(Parameters::kMemSaveDepth16Format().c_str());
_ui->general_checkBox_compressionParallelized->setObjectName(Parameters::kMemCompressionParallelized().c_str()); _ui->general_checkBox_compressionParallelized->setObjectName(Parameters::kMemCompressionParallelized().c_str());
_ui->general_checkBox_reduceGraph->setObjectName(Parameters::kMemReduceGraph().c_str()); _ui->general_checkBox_reduceGraph->setObjectName(Parameters::kMemReduceGraph().c_str());
@@ -1105,8 +1079,6 @@ PreferencesDialog::PreferencesDialog(QWidget * parent) :
_ui->lineEdit_dictionaryPath->setObjectName(Parameters::kKpDictionaryPath().c_str()); _ui->lineEdit_dictionaryPath->setObjectName(Parameters::kKpDictionaryPath().c_str());
connect(_ui->toolButton_dictionaryPath, SIGNAL(clicked()), this, SLOT(changeDictionaryPath())); connect(_ui->toolButton_dictionaryPath, SIGNAL(clicked()), this, SLOT(changeDictionaryPath()));
_ui->checkBox_kp_newWordsComparedTogether->setObjectName(Parameters::kKpNewWordsComparedTogether().c_str()); _ui->checkBox_kp_newWordsComparedTogether->setObjectName(Parameters::kKpNewWordsComparedTogether().c_str());
_ui->checkBox_kp_flannIndexSaved->setObjectName(Parameters::kKpFlannIndexSaved().c_str());
_ui->checkBox_kp_serializeWithChecksum->setObjectName(Parameters::kKpSerializeWithChecksum().c_str());
_ui->subpix_winSize_kp->setObjectName(Parameters::kKpSubPixWinSize().c_str()); _ui->subpix_winSize_kp->setObjectName(Parameters::kKpSubPixWinSize().c_str());
_ui->subpix_iterations_kp->setObjectName(Parameters::kKpSubPixIterations().c_str()); _ui->subpix_iterations_kp->setObjectName(Parameters::kKpSubPixIterations().c_str());
_ui->subpix_eps_kp->setObjectName(Parameters::kKpSubPixEps().c_str()); _ui->subpix_eps_kp->setObjectName(Parameters::kKpSubPixEps().c_str());
@@ -1581,8 +1553,8 @@ PreferencesDialog::PreferencesDialog(QWidget * parent) :
_ui->OdomMSCKFInitCovExTrans->setObjectName(Parameters::kOdomMSCKFInitCovExTrans().c_str()); _ui->OdomMSCKFInitCovExTrans->setObjectName(Parameters::kOdomMSCKFInitCovExTrans().c_str());
// Odometry VINS // Odometry VINS
_ui->lineEdit_OdomVinsFusionPath->setObjectName(Parameters::kOdomVINSFusionConfigPath().c_str()); _ui->lineEdit_OdomVinsPath->setObjectName(Parameters::kOdomVINSConfigPath().c_str());
connect(_ui->toolButton_OdomVinsFusionPath, SIGNAL(clicked()), this, SLOT(changeOdometryVINSFusionConfigPath())); connect(_ui->toolButton_OdomVinsPath, SIGNAL(clicked()), this, SLOT(changeOdometryVINSConfigPath()));
// Odometry OpenVINS // Odometry OpenVINS
_ui->checkBox_OdomOpenVINSUseStereo->setObjectName(Parameters::kOdomOpenVINSUseStereo().c_str()); _ui->checkBox_OdomOpenVINSUseStereo->setObjectName(Parameters::kOdomOpenVINSUseStereo().c_str());
@@ -2256,13 +2228,6 @@ void PreferencesDialog::resetSettings(QGroupBox * groupBox)
_ui->comboBox_k4a_depth_resolution->setCurrentIndex(2); _ui->comboBox_k4a_depth_resolution->setCurrentIndex(2);
_ui->checkbox_k4a_irDepth->setChecked(false); _ui->checkbox_k4a_irDepth->setChecked(false);
_ui->lineEdit_k4a_mkv->clear(); _ui->lineEdit_k4a_mkv->clear();
_ui->spinBox_orbbec_sdk_color_width->setValue(800);
_ui->spinBox_orbbec_sdk_color_height->setValue(600);
_ui->spinBox_orbbec_sdk_depth_width->setValue(800);
_ui->spinBox_orbbec_sdk_depth_height->setValue(600);
_ui->checkBox_orbbec_sdk_color_rectification->setChecked(false);
_ui->checkBox_orbbec_sdk_imu->setChecked(true);
_ui->checkBox_orbbec_sdk_depth_mm->setChecked(true);
_ui->source_checkBox_useMKVStamps->setChecked(true); _ui->source_checkBox_useMKVStamps->setChecked(true);
_ui->lineEdit_cameraRGBDImages_path_rgb->setText(""); _ui->lineEdit_cameraRGBDImages_path_rgb->setText("");
_ui->lineEdit_cameraRGBDImages_path_depth->setText(""); _ui->lineEdit_cameraRGBDImages_path_depth->setText("");
@@ -2341,7 +2306,6 @@ void PreferencesDialog::resetSettings(QGroupBox * groupBox)
_ui->doubleSpinBox_odom_sensor_scale_factor->setValue(1); _ui->doubleSpinBox_odom_sensor_scale_factor->setValue(1);
_ui->doubleSpinBox_odom_sensor_wait_time->setValue(100); _ui->doubleSpinBox_odom_sensor_wait_time->setValue(100);
_ui->checkBox_odom_sensor_use_as_gt->setChecked(false); _ui->checkBox_odom_sensor_use_as_gt->setChecked(false);
_ui->checkbox_passthrough_source_odom->setChecked(false);
_ui->comboBox_imuFilter_strategy->setCurrentIndex(2); _ui->comboBox_imuFilter_strategy->setCurrentIndex(2);
_ui->doubleSpinBox_imuFilterMadgwickGain->setValue(Parameters::defaultImuFilterMadgwickGain()); _ui->doubleSpinBox_imuFilterMadgwickGain->setValue(Parameters::defaultImuFilterMadgwickGain());
@@ -2749,16 +2713,6 @@ void PreferencesDialog::readCameraSettings(const QString & filePath)
_ui->source_checkBox_useMKVStamps->setChecked(settings.value("useMkvStamps", _ui->source_checkBox_useMKVStamps->isChecked()).toBool()); _ui->source_checkBox_useMKVStamps->setChecked(settings.value("useMkvStamps", _ui->source_checkBox_useMKVStamps->isChecked()).toBool());
settings.endGroup(); // K4A settings.endGroup(); // K4A
settings.beginGroup("OrbbecSDK");
_ui->spinBox_orbbec_sdk_color_width->setValue(settings.value("color_width", _ui->spinBox_orbbec_sdk_color_width->value()).toInt());
_ui->spinBox_orbbec_sdk_color_height->setValue(settings.value("color_height", _ui->spinBox_orbbec_sdk_color_height->value()).toInt());
_ui->spinBox_orbbec_sdk_depth_width->setValue(settings.value("depth_width", _ui->spinBox_orbbec_sdk_depth_width->value()).toInt());
_ui->spinBox_orbbec_sdk_depth_height->setValue(settings.value("depth_height", _ui->spinBox_orbbec_sdk_depth_height->value()).toInt());
_ui->checkBox_orbbec_sdk_color_rectification->setChecked(settings.value("rectify_color", _ui->checkBox_orbbec_sdk_color_rectification->isChecked()).toBool());
_ui->checkBox_orbbec_sdk_imu->setChecked(settings.value("enable_imu", _ui->checkBox_orbbec_sdk_imu->isChecked()).toBool());
_ui->checkBox_orbbec_sdk_depth_mm->setChecked(settings.value("depth_mm", _ui->checkBox_orbbec_sdk_depth_mm->isChecked()).toBool());
settings.endGroup(); // Orbbec SDK
settings.beginGroup("RealSense"); settings.beginGroup("RealSense");
_ui->comboBox_realsensePresetRGB->setCurrentIndex(settings.value("presetRGB", _ui->comboBox_realsensePresetRGB->currentIndex()).toInt()); _ui->comboBox_realsensePresetRGB->setCurrentIndex(settings.value("presetRGB", _ui->comboBox_realsensePresetRGB->currentIndex()).toInt());
_ui->comboBox_realsensePresetDepth->setCurrentIndex(settings.value("presetDepth", _ui->comboBox_realsensePresetDepth->currentIndex()).toInt()); _ui->comboBox_realsensePresetDepth->setCurrentIndex(settings.value("presetDepth", _ui->comboBox_realsensePresetDepth->currentIndex()).toInt());
@@ -2878,7 +2832,6 @@ void PreferencesDialog::readCameraSettings(const QString & filePath)
_ui->doubleSpinBox_odom_sensor_scale_factor->setValue(settings.value("odom_sensor_scale_factor", _ui->doubleSpinBox_odom_sensor_scale_factor->value()).toDouble()); _ui->doubleSpinBox_odom_sensor_scale_factor->setValue(settings.value("odom_sensor_scale_factor", _ui->doubleSpinBox_odom_sensor_scale_factor->value()).toDouble());
_ui->doubleSpinBox_odom_sensor_wait_time->setValue(settings.value("odom_sensor_wait_time", _ui->doubleSpinBox_odom_sensor_wait_time->value()).toDouble()); _ui->doubleSpinBox_odom_sensor_wait_time->setValue(settings.value("odom_sensor_wait_time", _ui->doubleSpinBox_odom_sensor_wait_time->value()).toDouble());
_ui->checkBox_odom_sensor_use_as_gt->setChecked(settings.value("odom_sensor_odom_as_gt", _ui->checkBox_odom_sensor_use_as_gt->isChecked()).toBool()); _ui->checkBox_odom_sensor_use_as_gt->setChecked(settings.value("odom_sensor_odom_as_gt", _ui->checkBox_odom_sensor_use_as_gt->isChecked()).toBool());
_ui->checkbox_passthrough_source_odom->setChecked(settings.value("odom_sensor_as_guess", _ui->checkbox_passthrough_source_odom->isChecked()).toBool());
settings.endGroup(); // OdomSensor settings.endGroup(); // OdomSensor
settings.beginGroup("UsbCam"); settings.beginGroup("UsbCam");
@@ -3366,16 +3319,6 @@ void PreferencesDialog::writeCameraSettings(const QString & filePath) const
settings.setValue("useMkvStamps", _ui->source_checkBox_useMKVStamps->isChecked()); settings.setValue("useMkvStamps", _ui->source_checkBox_useMKVStamps->isChecked());
settings.endGroup(); // K4A settings.endGroup(); // K4A
settings.beginGroup("OrbbecSDK");
settings.setValue("color_width", _ui->spinBox_orbbec_sdk_color_width->value());
settings.setValue("color_height", _ui->spinBox_orbbec_sdk_color_height->value());
settings.setValue("depth_width", _ui->spinBox_orbbec_sdk_depth_width->value());
settings.setValue("depth_height", _ui->spinBox_orbbec_sdk_depth_height->value());
settings.setValue("rectify_color", _ui->checkBox_orbbec_sdk_color_rectification->isChecked());
settings.setValue("enable_imu", _ui->checkBox_orbbec_sdk_imu->isChecked());
settings.setValue("depth_mm", _ui->checkBox_orbbec_sdk_depth_mm->isChecked());
settings.endGroup(); // Orbbec SDK
settings.beginGroup("RealSense"); settings.beginGroup("RealSense");
settings.setValue("presetRGB", _ui->comboBox_realsensePresetRGB->currentIndex()); settings.setValue("presetRGB", _ui->comboBox_realsensePresetRGB->currentIndex());
settings.setValue("presetDepth", _ui->comboBox_realsensePresetDepth->currentIndex()); settings.setValue("presetDepth", _ui->comboBox_realsensePresetDepth->currentIndex());
@@ -3493,7 +3436,6 @@ void PreferencesDialog::writeCameraSettings(const QString & filePath) const
settings.setValue("odom_sensor_scale_factor", _ui->doubleSpinBox_odom_sensor_scale_factor->value()); settings.setValue("odom_sensor_scale_factor", _ui->doubleSpinBox_odom_sensor_scale_factor->value());
settings.setValue("odom_sensor_wait_time", _ui->doubleSpinBox_odom_sensor_wait_time->value()); settings.setValue("odom_sensor_wait_time", _ui->doubleSpinBox_odom_sensor_wait_time->value());
settings.setValue("odom_sensor_odom_as_gt", _ui->checkBox_odom_sensor_use_as_gt->isChecked()); settings.setValue("odom_sensor_odom_as_gt", _ui->checkBox_odom_sensor_use_as_gt->isChecked());
settings.setValue("odom_sensor_as_guess", _ui->checkbox_passthrough_source_odom->isChecked());
settings.endGroup(); // OdomSensor settings.endGroup(); // OdomSensor
settings.beginGroup("UsbCam"); settings.beginGroup("UsbCam");
@@ -3788,6 +3730,15 @@ bool PreferencesDialog::validateForm()
_ui->odom_f2m_bundleStrategy->setCurrentIndex(0); _ui->odom_f2m_bundleStrategy->setCurrentIndex(0);
} }
// verify that Robust and Reject threshold are not set at the same time
if(_ui->graphOptimization_robust->isChecked() && _ui->graphOptimization_maxError->value()>0.0)
{
QMessageBox::warning(this, tr("Parameter warning"),
tr("Robust graph optimization and maximum optimization error threshold cannot be "
"both used at the same time. Disabling robust optimization."));
_ui->graphOptimization_robust->setChecked(false);
}
//verify binary features and nearest neighbor //verify binary features and nearest neighbor
// BOW dictionary type // BOW dictionary type
if(_ui->comboBox_dictionary_strategy->currentIndex() == VWDictionary::kNNFlannLSH && _ui->comboBox_detector_strategy->currentIndex() <= 1) if(_ui->comboBox_dictionary_strategy->currentIndex() == VWDictionary::kNNFlannLSH && _ui->comboBox_detector_strategy->currentIndex() <= 1)
@@ -5522,7 +5473,7 @@ void PreferencesDialog::updateOdometryStackedIndex(int index)
_ui->groupBox_odomOKVIS->setVisible(index==6); _ui->groupBox_odomOKVIS->setVisible(index==6);
_ui->groupBox_odomLOAM->setVisible(index==7); _ui->groupBox_odomLOAM->setVisible(index==7);
_ui->groupBox_odomMSCKF->setVisible(index==8); _ui->groupBox_odomMSCKF->setVisible(index==8);
_ui->groupBox_odomVINSFusion->setVisible(index==9); _ui->groupBox_odomVINS->setVisible(index==9);
_ui->groupBox_odomOpenVINS->setVisible(index==10); _ui->groupBox_odomOpenVINS->setVisible(index==10);
_ui->groupBox_odomOpen3D->setVisible(index==12); _ui->groupBox_odomOpen3D->setVisible(index==12);
} }
@@ -5613,20 +5564,20 @@ void PreferencesDialog::changeOdometryOKVISConfigPath()
} }
} }
void PreferencesDialog::changeOdometryVINSFusionConfigPath() void PreferencesDialog::changeOdometryVINSConfigPath()
{ {
QString path; QString path;
if(_ui->lineEdit_OdomVinsFusionPath->text().isEmpty()) if(_ui->lineEdit_OdomVinsPath->text().isEmpty())
{ {
path = QFileDialog::getOpenFileName(this, tr("VINS-Fusion Config"), this->getWorkingDirectory(), tr("VINS-Fusion config (*.yaml)")); path = QFileDialog::getOpenFileName(this, tr("VINS-Fusion Config"), this->getWorkingDirectory(), tr("VINS-Fusion config (*.yaml)"));
} }
else else
{ {
path = QFileDialog::getOpenFileName(this, tr("VINS-Fusion Config"), _ui->lineEdit_OdomVinsFusionPath->text(), tr("VINS-Fusion config (*.yaml)")); path = QFileDialog::getOpenFileName(this, tr("VINS-Fusion Config"), _ui->lineEdit_OdomVinsPath->text(), tr("VINS-Fusion config (*.yaml)"));
} }
if(!path.isEmpty()) if(!path.isEmpty())
{ {
_ui->lineEdit_OdomVinsFusionPath->setText(path); _ui->lineEdit_OdomVinsPath->setText(path);
} }
} }
@@ -5780,7 +5731,6 @@ void PreferencesDialog::updateSourceGrpVisibility()
_ui->comboBox_cameraRGBD->currentIndex() == kSrcFreenect2-kSrcRGBD || _ui->comboBox_cameraRGBD->currentIndex() == kSrcFreenect2-kSrcRGBD ||
_ui->comboBox_cameraRGBD->currentIndex() == kSrcK4W2 - kSrcRGBD || _ui->comboBox_cameraRGBD->currentIndex() == kSrcK4W2 - kSrcRGBD ||
_ui->comboBox_cameraRGBD->currentIndex() == kSrcK4A - kSrcRGBD || _ui->comboBox_cameraRGBD->currentIndex() == kSrcK4A - kSrcRGBD ||
_ui->comboBox_cameraRGBD->currentIndex() == kSrcOrbbecSDK - kSrcRGBD ||
_ui->comboBox_cameraRGBD->currentIndex() == kSrcRealSense - kSrcRGBD || _ui->comboBox_cameraRGBD->currentIndex() == kSrcRealSense - kSrcRGBD ||
_ui->comboBox_cameraRGBD->currentIndex() == kSrcRGBDImages-kSrcRGBD || _ui->comboBox_cameraRGBD->currentIndex() == kSrcRGBDImages-kSrcRGBD ||
_ui->comboBox_cameraRGBD->currentIndex() == kSrcOpenNI_PCL-kSrcRGBD || _ui->comboBox_cameraRGBD->currentIndex() == kSrcOpenNI_PCL-kSrcRGBD ||
@@ -5790,7 +5740,6 @@ void PreferencesDialog::updateSourceGrpVisibility()
_ui->groupBox_freenect2->setVisible(_ui->comboBox_sourceType->currentIndex() == 0 && _ui->comboBox_cameraRGBD->currentIndex() == kSrcFreenect2-kSrcRGBD); _ui->groupBox_freenect2->setVisible(_ui->comboBox_sourceType->currentIndex() == 0 && _ui->comboBox_cameraRGBD->currentIndex() == kSrcFreenect2-kSrcRGBD);
_ui->groupBox_k4w2->setVisible(_ui->comboBox_sourceType->currentIndex() == 0 && _ui->comboBox_cameraRGBD->currentIndex() == kSrcK4W2 - kSrcRGBD); _ui->groupBox_k4w2->setVisible(_ui->comboBox_sourceType->currentIndex() == 0 && _ui->comboBox_cameraRGBD->currentIndex() == kSrcK4W2 - kSrcRGBD);
_ui->groupBox_k4a->setVisible(_ui->comboBox_sourceType->currentIndex() == 0 && _ui->comboBox_cameraRGBD->currentIndex() == kSrcK4A - kSrcRGBD); _ui->groupBox_k4a->setVisible(_ui->comboBox_sourceType->currentIndex() == 0 && _ui->comboBox_cameraRGBD->currentIndex() == kSrcK4A - kSrcRGBD);
_ui->groupBox_orbbec_sdk->setVisible(_ui->comboBox_sourceType->currentIndex() == 0 && _ui->comboBox_cameraRGBD->currentIndex() == kSrcOrbbecSDK - kSrcRGBD);
_ui->groupBox_realsense->setVisible(_ui->comboBox_sourceType->currentIndex() == 0 && _ui->comboBox_cameraRGBD->currentIndex() == kSrcRealSense - kSrcRGBD); _ui->groupBox_realsense->setVisible(_ui->comboBox_sourceType->currentIndex() == 0 && _ui->comboBox_cameraRGBD->currentIndex() == kSrcRealSense - kSrcRGBD);
_ui->groupBox_realsense2->setVisible(_ui->comboBox_sourceType->currentIndex() == 0 && _ui->comboBox_cameraRGBD->currentIndex() == kSrcRealSense2 - kSrcRGBD); _ui->groupBox_realsense2->setVisible(_ui->comboBox_sourceType->currentIndex() == 0 && _ui->comboBox_cameraRGBD->currentIndex() == kSrcRealSense2 - kSrcRGBD);
_ui->groupBox_cameraRGBDImages->setVisible(_ui->comboBox_sourceType->currentIndex() == 0 && _ui->comboBox_cameraRGBD->currentIndex() == kSrcRGBDImages-kSrcRGBD); _ui->groupBox_cameraRGBDImages->setVisible(_ui->comboBox_sourceType->currentIndex() == 0 && _ui->comboBox_cameraRGBD->currentIndex() == kSrcRGBDImages-kSrcRGBD);
@@ -5834,7 +5783,7 @@ void PreferencesDialog::updateSourceGrpVisibility()
// Odom Sensor Group // Odom Sensor Group
_ui->frame_visual_odometry_sensor->setVisible(getOdomSourceDriver() != kSrcUndef); // Not Lidar None _ui->frame_visual_odometry_sensor->setVisible(getOdomSourceDriver() != kSrcUndef); // Not Lidar None
_ui->comboBox_odom_sensor->setEnabled(_ui->comboBox_sourceType->currentIndex() != 3); // Don't enable when database is selected _ui->groupBox_odom_sensor->setVisible(_ui->comboBox_sourceType->currentIndex() != 3); // Don't show when database is selected
// Lidar Sensor Group // Lidar Sensor Group
_ui->comboBox_lidar_src->setEnabled(_ui->comboBox_sourceType->currentIndex() != 3); // Disable if database input _ui->comboBox_lidar_src->setEnabled(_ui->comboBox_sourceType->currentIndex() != 3); // Disable if database input
@@ -5860,7 +5809,6 @@ void PreferencesDialog::updateSourceGrpVisibility()
(_ui->comboBox_sourceType->currentIndex() == 2 && _ui->source_comboBox_image_type->currentIndex() == kSrcImages-kSrcRGB) || (_ui->comboBox_sourceType->currentIndex() == 2 && _ui->source_comboBox_image_type->currentIndex() == kSrcImages-kSrcRGB) ||
(_ui->comboBox_sourceType->currentIndex() == 0 && _ui->comboBox_cameraRGBD->currentIndex() == kSrcFreenect - kSrcRGBD) || //Kinect360 (_ui->comboBox_sourceType->currentIndex() == 0 && _ui->comboBox_cameraRGBD->currentIndex() == kSrcFreenect - kSrcRGBD) || //Kinect360
(_ui->comboBox_sourceType->currentIndex() == 0 && _ui->comboBox_cameraRGBD->currentIndex() == kSrcK4A - kSrcRGBD) || //K4A (_ui->comboBox_sourceType->currentIndex() == 0 && _ui->comboBox_cameraRGBD->currentIndex() == kSrcK4A - kSrcRGBD) || //K4A
(_ui->comboBox_sourceType->currentIndex() == 0 && _ui->comboBox_cameraRGBD->currentIndex() == kSrcOrbbecSDK - kSrcRGBD) || //Orbbec SDK
(_ui->comboBox_sourceType->currentIndex() == 0 && _ui->comboBox_cameraRGBD->currentIndex() == kSrcRealSense2 - kSrcRGBD) || //D435i (_ui->comboBox_sourceType->currentIndex() == 0 && _ui->comboBox_cameraRGBD->currentIndex() == kSrcRealSense2 - kSrcRGBD) || //D435i
(_ui->comboBox_sourceType->currentIndex() == 0 && _ui->comboBox_cameraRGBD->currentIndex() == kSrcSeerSense - kSrcRGBD) || (_ui->comboBox_sourceType->currentIndex() == 0 && _ui->comboBox_cameraRGBD->currentIndex() == kSrcSeerSense - kSrcRGBD) ||
(_ui->comboBox_sourceType->currentIndex() == 1 && _ui->comboBox_cameraStereo->currentIndex() == kSrcStereoRealSense2 - kSrcStereo) || //T265 (_ui->comboBox_sourceType->currentIndex() == 1 && _ui->comboBox_cameraStereo->currentIndex() == kSrcStereoRealSense2 - kSrcStereo) || //T265
@@ -5969,10 +5917,6 @@ bool PreferencesDialog::isOdomDisabled() const
{ {
return _ui->checkbox_odomDisabled->isChecked(); return _ui->checkbox_odomDisabled->isChecked();
} }
bool PreferencesDialog::isOdomAsGuessEnabled() const
{
return _ui->checkbox_passthrough_source_odom->isChecked();
}
bool PreferencesDialog::isOdomSensorAsGt() const bool PreferencesDialog::isOdomSensorAsGt() const
{ {
return _ui->checkBox_odom_sensor_use_as_gt->isChecked(); return _ui->checkBox_odom_sensor_use_as_gt->isChecked();
@@ -6693,25 +6637,6 @@ Camera * PreferencesDialog::createCamera(
_ui->comboBox_k4a_framerate->currentIndex(), _ui->comboBox_k4a_framerate->currentIndex(),
_ui->comboBox_k4a_depth_resolution->currentIndex()); _ui->comboBox_k4a_depth_resolution->currentIndex());
} }
else if (driver == kSrcOrbbecSDK)
{
camera = new CameraOrbbecSDK(
device.toStdString(),
_ui->spinBox_orbbec_sdk_color_width->value(),
_ui->spinBox_orbbec_sdk_color_height->value(),
_ui->spinBox_orbbec_sdk_depth_width->value(),
_ui->spinBox_orbbec_sdk_depth_height->value(),
this->getGeneralInputRate(),
this->getSourceLocalTransform());
((CameraOrbbecSDK*)camera)->enableColorRectification(_ui->checkBox_orbbec_sdk_color_rectification->isChecked());
((CameraOrbbecSDK*)camera)->enableImu(_ui->checkBox_orbbec_sdk_imu->isChecked());
((CameraOrbbecSDK*)camera)->enableDepthMM(_ui->checkBox_orbbec_sdk_depth_mm->isChecked());
camera->setInterIMUPublishing(
_ui->checkbox_publishInterIMU->isChecked(),
_ui->checkbox_publishInterIMU->isChecked() && getIMUFilteringStrategy()>0?
IMUFilter::create((IMUFilter::Type)(getIMUFilteringStrategy()-1), this->getAllParameters()):0);
}
else if (driver == kSrcRealSense) else if (driver == kSrcRealSense)
{ {
if(useRawImages && _ui->comboBox_realsenseRGBSource->currentIndex()!=2) if(useRawImages && _ui->comboBox_realsenseRGBSource->currentIndex()!=2)
+1 -1
View File
@@ -101,7 +101,7 @@ void ProgressDialog::setCancelButtonVisible(bool visible)
void ProgressDialog::appendText(const QString & text, const QColor & color) void ProgressDialog::appendText(const QString & text, const QColor & color)
{ {
//UDEBUG(text.toStdString().c_str()); UDEBUG(text.toStdString().c_str());
_text->setText(text); _text->setText(text);
QString html = tr("<html><font color=\"#999999\">%1 </font><font color=\"%2\">%3</font></html>").arg(QTime::currentTime().toString("HH:mm:ss")).arg(color.name()).arg(text); QString html = tr("<html><font color=\"#999999\">%1 </font><font color=\"%2\">%3</font></html>").arg(QTime::currentTime().toString("HH:mm:ss")).arg(color.name()).arg(text);
_detailedText->append(html); _detailedText->append(html);
Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

+998 -1064
View File
File diff suppressed because it is too large Load Diff

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