Compare commits

..
79 changed files with 47670 additions and 183115 deletions
@@ -1,266 +0,0 @@
name: 'Install macOS Source Dependencies'
description: 'Builds (and per-dependency caches) the source-only deps not available from Homebrew (GTSAM, libnabo+libpointmatcher, OrbbecSDK, depthai) and installs them into /usr/local.'
inputs:
os:
description: 'Runner os label (e.g. matrix.os), used to namespace the per-dependency caches. Required because intel/arm produce different binaries with identical Homebrew version strings.'
required: true
build_type:
description: 'CMake build type.'
required: false
default: 'Release'
runs:
using: "composite"
steps:
- name: Resolve dependency versions
id: depver
shell: bash
# The source deps link against these Homebrew libraries and are compiled
# with Xcode's toolchain, so both are folded into the cache keys: a
# Homebrew bump (e.g. a new Eigen) or an Xcode update forces a rebuild.
run: |
BREW=$(brew list --versions eigen boost yaml-cpp | sort)
XCODE=$(xcodebuild -version 2>/dev/null || clang --version | head -1)
HASH=$(printf '%s\n%s\n' "$BREW" "$XCODE" | shasum | cut -d' ' -f1)
echo "hash=$HASH" >> "$GITHUB_OUTPUT"
# ----------------------------- GTSAM -----------------------------
- name: Cache GTSAM
id: cache-gtsam
uses: actions/cache@v4
with:
path: ${{ runner.temp }}/deps-stage/gtsam
key: gtsam-4.2.1-${{ inputs.os }}-${{ hashFiles('.github/actions/install-macos-source-deps/patches/gtsam-4.2.1-eigen5.patch') }}-${{ steps.depver.outputs.hash }}
- name: Build GTSAM
if: steps.cache-gtsam.outputs.cache-hit != 'true'
shell: bash
run: |
set -e
NPROC=$(sysctl -n hw.logicalcpu)
PATCHES="${{ github.action_path }}/patches"
SRC="${{ runner.temp }}/src-deps/gtsam"
STAGE="${{ runner.temp }}/deps-stage/gtsam"
rm -rf "$SRC"; mkdir -p "$SRC" "$STAGE"
git clone --depth 1 --branch 4.2.1 https://github.com/borglab/gtsam.git "$SRC/gtsam"
cd "$SRC/gtsam"
git apply "$PATCHES/gtsam-4.2.1-eigen5.patch"
cmake -B build \
-DCMAKE_BUILD_TYPE=${{ inputs.build_type }} \
-DGTSAM_BUILD_WITH_MARCH_NATIVE=OFF \
-DGTSAM_WITH_TBB=OFF \
-DGTSAM_BUILD_EXAMPLES_ALWAYS=OFF \
-DGTSAM_BUILD_TESTS=OFF \
-DGTSAM_BUILD_UNSTABLE=OFF \
-DGTSAM_USE_SYSTEM_EIGEN=ON \
-DCMAKE_POLICY_VERSION_MINIMUM=3.5
cmake --build build -j$NPROC
DESTDIR="$STAGE" cmake --install build
# ----------------- libnabo + libpointmatcher --------------------
# Built together: libpointmatcher depends on libnabo, so keeping them in one
# unit keeps the build order internal (lpm finds libnabo in the unit's stage).
- name: Cache pointmatcher
id: cache-pointmatcher
uses: actions/cache@v4
with:
path: ${{ runner.temp }}/deps-stage/pointmatcher
key: pointmatcher-nabo1.1.2-lpm1.4.4-${{ inputs.os }}-${{ hashFiles('.github/actions/install-macos-source-deps/patches/libnabo-1.1.2.patch', '.github/actions/install-macos-source-deps/patches/libpointmatcher-1.4.4-boost.patch') }}-${{ steps.depver.outputs.hash }}
- name: Build pointmatcher
if: steps.cache-pointmatcher.outputs.cache-hit != 'true'
shell: bash
run: |
set -e
NPROC=$(sysctl -n hw.logicalcpu)
PATCHES="${{ github.action_path }}/patches"
SRC="${{ runner.temp }}/src-deps/pointmatcher"
STAGE="${{ runner.temp }}/deps-stage/pointmatcher"
rm -rf "$SRC"; mkdir -p "$SRC" "$STAGE"
# libnabo (required by libpointmatcher)
git clone --depth 1 --branch 1.1.2 https://github.com/ethz-asl/libnabo.git "$SRC/libnabo"
cd "$SRC/libnabo"
git apply "$PATCHES/libnabo-1.1.2.patch"
cmake -B build -DCMAKE_BUILD_TYPE=${{ inputs.build_type }}
cmake --build build -j$NPROC
DESTDIR="$STAGE" cmake --install build
# libpointmatcher (finds libnabo from the unit's staged prefix)
git clone --depth 1 --branch 1.4.4 https://github.com/ethz-asl/libpointmatcher.git "$SRC/libpointmatcher"
cd "$SRC/libpointmatcher"
git apply "$PATCHES/libpointmatcher-1.4.4-boost.patch"
cmake -B build -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DCMAKE_PREFIX_PATH="$STAGE/usr/local" -DBUILD_EVALUATIONS=OFF -DBUILD_EXAMPLES=OFF
cmake --build build -j$NPROC
DESTDIR="$STAGE" cmake --install build
# ----------------------------- OrbbecSDK ------------------------
- name: Cache OrbbecSDK
id: cache-orbbec
uses: actions/cache@v4
with:
path: ${{ runner.temp }}/deps-stage/orbbec
key: orbbec-2.8.7-usrlocal-${{ inputs.os }}-${{ hashFiles('.github/actions/install-macos-source-deps/patches/orbbecsdk-2.8.7-cmake-config-install.patch') }}-${{ steps.depver.outputs.hash }}
- name: Build OrbbecSDK
if: steps.cache-orbbec.outputs.cache-hit != 'true'
shell: bash
run: |
set -e
NPROC=$(sysctl -n hw.logicalcpu)
PATCHES="${{ github.action_path }}/patches"
SRC="${{ runner.temp }}/src-deps/orbbec"
STAGE="${{ runner.temp }}/deps-stage/orbbec"
rm -rf "$SRC"; mkdir -p "$SRC" "$STAGE"
git clone --depth 1 --branch v2.8.7 https://github.com/orbbec/OrbbecSDK_v2.git "$SRC/OrbbecSDK_v2"
cd "$SRC/OrbbecSDK_v2"
git apply "$PATCHES/orbbecsdk-2.8.7-cmake-config-install.patch"
# OrbbecSDK defaults its install prefix to /opt/OrbbecSDK; force /usr/local
# so it stages under usr/local like the other deps and is installed/found.
cmake -B build -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DCMAKE_INSTALL_PREFIX=/usr/local -DOB_BUILD_DOCS=OFF -DOB_BUILD_EXAMPLES=OFF -DOB_BUILD_TOOLS=OFF -DOB_INSTALL_EXAMPLES_SOURCE=OFF
cmake --build build -j$NPROC
DESTDIR="$STAGE" cmake --install build
# ----------------------------- depthai --------------------------
- name: Cache depthai
id: cache-depthai
uses: actions/cache@v4
with:
path: ${{ runner.temp }}/deps-stage/depthai
key: depthai-2.32.0-usrlocal-${{ inputs.os }}-${{ hashFiles('.github/actions/install-macos-source-deps/patches/depthai-2.32.0-hunter-macos.patch') }}-${{ steps.depver.outputs.hash }}
- name: Build depthai
if: steps.cache-depthai.outputs.cache-hit != 'true'
shell: bash
run: |
set -e
NPROC=$(sysctl -n hw.logicalcpu)
PATCHES="${{ github.action_path }}/patches"
SRC="${{ runner.temp }}/src-deps/depthai"
STAGE="${{ runner.temp }}/deps-stage/depthai"
rm -rf "$SRC"; mkdir -p "$SRC" "$STAGE"
# depthai 2.32.0 (Hunter-based; v2 does NOT use vcpkg/CMake presets)
git clone --depth 1 --branch v2.32.0 https://github.com/luxonis/depthai-core.git "$SRC/depthai-core"
cd "$SRC/depthai-core"
git submodule update --init --recursive
# Route zlib to Homebrew: Hunter's pinned zlib fork has a classic
# TARGET_OS_MAC fdopen block that won't compile against the modern macOS SDK.
git apply "$PATCHES/depthai-2.32.0-hunter-macos.patch"
# v2 and its old Hunter deps declare cmake_minimum_required < 3.5, which the
# runner's CMake 4.x rejects, and CMAKE_POLICY_VERSION_MINIMUM does not
# propagate into Hunter's sub-builds. Use a pinned CMake 3.x just for depthai
# (Hunter reuses the same cmake binary for its dependency sub-builds).
python3 -m venv "$SRC/cmake3-venv"
"$SRC/cmake3-venv/bin/pip" install -q "cmake==3.31.6"
CMAKE3="$SRC/cmake3-venv/bin/cmake"
# DEPTHAI_ENABLE_CURL=OFF: Hunter's CURL drags in the broken zlib and also
# fails to configure on this toolchain; rtabmap doesn't need depthai's CURL.
# depthai-core defaults its install prefix to <build>/install; force
# /usr/local so it stages under usr/local like the other deps.
"$CMAKE3" -B build \
-DCMAKE_BUILD_TYPE=${{ inputs.build_type }} \
-DCMAKE_INSTALL_PREFIX=/usr/local \
-DBUILD_SHARED_LIBS=ON \
-DDEPTHAI_ENABLE_CURL=OFF \
-DDEPTHAI_BUILD_TESTS=OFF \
-DDEPTHAI_BUILD_EXAMPLES=OFF \
-DCMAKE_PREFIX_PATH="$(brew --prefix zlib)"
"$CMAKE3" --build build -j$NPROC
DESTDIR="$STAGE" "$CMAKE3" --install build
# ----------------------------- opengv ---------------------------
- name: Cache opengv
id: cache-opengv
uses: actions/cache@v4
with:
path: ${{ runner.temp }}/deps-stage/opengv
key: opengv-91f4b19c-usrlocal-${{ inputs.os }}-${{ hashFiles('.github/actions/install-macos-source-deps/patches/opengv-91f4b19c-macos.patch') }}-${{ steps.depver.outputs.hash }}
- name: Build opengv
if: steps.cache-opengv.outputs.cache-hit != 'true'
shell: bash
run: |
set -e
NPROC=$(sysctl -n hw.logicalcpu)
PATCHES="${{ github.action_path }}/patches"
SRC="${{ runner.temp }}/src-deps/opengv"
STAGE="${{ runner.temp }}/deps-stage/opengv"
rm -rf "$SRC"; mkdir -p "$SRC" "$STAGE"
# opengv pins a commit (not a tag), so clone then checkout.
git clone https://github.com/laurentkneip/opengv.git "$SRC/opengv"
cd "$SRC/opengv"
git checkout 91f4b19c73450833a40e463ad3648aae80b3a7f3
# Disable the -march=native/armv7-a/armv8-a flags so it builds portably on
# both Intel and Apple Silicon runners.
git apply "$PATCHES/opengv-91f4b19c-macos.patch"
# CMAKE_POLICY_VERSION_MINIMUM=3.5: opengv declares an ancient
# cmake_minimum_required that modern CMake rejects. EIGEN_INCLUDE_DIR points
# opengv's bundled FindEigen at Homebrew's eigen (covers /opt/homebrew on arm64).
cmake -B build \
-DCMAKE_BUILD_TYPE=${{ inputs.build_type }} \
-DCMAKE_INSTALL_PREFIX=/usr/local \
-DBUILD_TESTS=OFF \
-DBUILD_SHARED_LIBS=ON \
-DCMAKE_POLICY_VERSION_MINIMUM=3.5 \
-DEIGEN_INCLUDE_DIR="$(brew --prefix eigen)/include/eigen3"
cmake --build build -j$NPROC
DESTDIR="$STAGE" cmake --install build
# ----------------------------- g2o ------------------------------
- name: Cache g2o
id: cache-g2o
uses: actions/cache@v4
with:
path: ${{ runner.temp }}/deps-stage/g2o
key: g2o-67cbe15c-${{ inputs.os }}-${{ steps.depver.outputs.hash }}
- name: Build g2o
if: steps.cache-g2o.outputs.cache-hit != 'true'
shell: bash
run: |
set -e
NPROC=$(sysctl -n hw.logicalcpu)
SRC="${{ runner.temp }}/src-deps/g2o"
STAGE="${{ runner.temp }}/deps-stage/g2o"
rm -rf "$SRC"; mkdir -p "$SRC" "$STAGE"
# g2o pins a commit (not a tag), so clone then checkout.
git clone https://github.com/RainerKuemmerle/g2o.git "$SRC/g2o"
cd "$SRC/g2o"
git checkout 67cbe15c998737ac6705d3cd18201a72be0d073d
# CMAKE_INSTALL_PREFIX=/usr/local so it stages under usr/local like the
# other deps. Homebrew's libomp is keg-only and g2o does not propagate
# OpenMP's include/lib dirs, so with Apple clang <omp.h> isn't found and
# libomp isn't linked; add its include (-I) and lib (-L -lomp) explicitly.
LIBOMP=$(brew --prefix libomp)
cmake -B build \
-DCMAKE_BUILD_TYPE=${{ inputs.build_type }} \
-DCMAKE_INSTALL_PREFIX=/usr/local \
-DCMAKE_PREFIX_PATH="$LIBOMP" \
-DCMAKE_C_FLAGS="-I$LIBOMP/include" \
-DCMAKE_CXX_FLAGS="-I$LIBOMP/include" \
-DCMAKE_EXE_LINKER_FLAGS="-L$LIBOMP/lib -lomp" \
-DCMAKE_SHARED_LINKER_FLAGS="-L$LIBOMP/lib -lomp" \
-DG2O_BUILD_APPS=OFF \
-DG2O_BUILD_EXAMPLES=OFF \
-DG2O_USE_OPENMP=ON \
-DG2O_USE_OPENGL=OFF
cmake --build build -j$NPROC
DESTDIR="$STAGE" cmake --install build
# ------------------- install all units into /usr/local ----------
- name: Install source dependencies into /usr/local
shell: bash
# Copy each (cached or freshly built) staged tree into /usr/local so
# rtabmap's find_package() and the bundle fixup (which search /usr/local)
# pick them up. Runs on both cache hit and miss.
run: |
set -e
STAGE="${{ runner.temp }}/deps-stage"
found=0
for unit in gtsam pointmatcher orbbec depthai opengv g2o; do
if [ -d "$STAGE/$unit/usr/local" ]; then
sudo cp -a "$STAGE/$unit/usr/local/." /usr/local/
found=1
fi
done
if [ "$found" != "1" ]; then
echo "No staged source dependencies found under $STAGE" >&2
exit 1
fi
@@ -1,41 +0,0 @@
diff --git a/cmake/depthaiDependencies.cmake b/cmake/depthaiDependencies.cmake
index 6b0b44f98..672c26402 100644
--- a/cmake/depthaiDependencies.cmake
+++ b/cmake/depthaiDependencies.cmake
@@ -17,7 +17,9 @@ else()
hunter_add_package(FP16)
hunter_add_package(libarchive-luxonis)
hunter_add_package(spdlog)
- hunter_add_package(ZLIB)
+ # ZLIB: use the system/Homebrew copy instead of Hunter's (the old pinned
+ # zlib fork fails to build against the modern macOS SDK). Found below via
+ # the standard FindZLIB module, which provides the same ZLIB::ZLIB target.
if(DEPTHAI_ENABLE_BACKWARD)
hunter_add_package(Backward)
endif()
@@ -45,8 +47,23 @@ if(NOT CONFIG_MODE OR (CONFIG_MODE AND NOT DEPTHAI_SHARED_LIBS))
# libarchive for firmware packages
find_package(archive_static ${_QUIET} CONFIG REQUIRED)
find_package(lzma ${_QUIET} CONFIG REQUIRED)
- # ZLIB for compressing Apps
- find_package(ZLIB CONFIG REQUIRED)
+ # ZLIB for compressing Apps.
+ # Use the system/Homebrew zlib directly instead of Hunter's: Hunter's pinned
+ # zlib fork fails to build against the modern macOS SDK, and Hunter also
+ # intercepts find_package(ZLIB) via its own FindZLIB on the module path, so
+ # we locate it manually and expose the ZLIB::zlib target depthai expects.
+ find_path(SYSTEM_ZLIB_INCLUDE_DIR NAMES zlib.h)
+ find_library(SYSTEM_ZLIB_LIBRARY NAMES z)
+ if(NOT SYSTEM_ZLIB_INCLUDE_DIR OR NOT SYSTEM_ZLIB_LIBRARY)
+ message(FATAL_ERROR "System zlib not found (looked for zlib.h and libz). Install via: brew install zlib")
+ endif()
+ if(NOT TARGET ZLIB::zlib)
+ add_library(ZLIB::zlib UNKNOWN IMPORTED)
+ set_target_properties(ZLIB::zlib PROPERTIES
+ IMPORTED_LOCATION "${SYSTEM_ZLIB_LIBRARY}"
+ INTERFACE_INCLUDE_DIRECTORIES "${SYSTEM_ZLIB_INCLUDE_DIR}"
+ )
+ endif()
# spdlog for library and device logging
find_package(spdlog ${_QUIET} CONFIG REQUIRED)
@@ -1,83 +0,0 @@
diff --git a/cmake/HandleEigen.cmake b/cmake/HandleEigen.cmake
index b3b4f66b6..651cd1009 100644
--- a/cmake/HandleEigen.cmake
+++ b/cmake/HandleEigen.cmake
@@ -59,7 +59,12 @@ else()
endif()
# Detect Eigen version:
-set(EIGEN_VER_H "${GTSAM_EIGEN_INCLUDE_FOR_BUILD}/Eigen/src/Core/util/Macros.h")
+# Since Eigen 5.0.0 the version macros moved from Eigen/src/Core/util/Macros.h
+# to a dedicated Eigen/Version header, so check the new location first.
+set(EIGEN_VER_H "${GTSAM_EIGEN_INCLUDE_FOR_BUILD}/Eigen/Version")
+if (NOT EXISTS ${EIGEN_VER_H})
+ set(EIGEN_VER_H "${GTSAM_EIGEN_INCLUDE_FOR_BUILD}/Eigen/src/Core/util/Macros.h")
+endif()
if (EXISTS ${EIGEN_VER_H})
file(READ "${EIGEN_VER_H}" STR_EIGEN_VERSION)
diff --git a/gtsam/base/Matrix.h b/gtsam/base/Matrix.h
index cfedf6d8c..9c9771407 100644
--- a/gtsam/base/Matrix.h
+++ b/gtsam/base/Matrix.h
@@ -54,7 +54,7 @@ using Matrix7##N = Eigen::Matrix<double, 7, N>; \
using Matrix8##N = Eigen::Matrix<double, 8, N>; \
using Matrix9##N = Eigen::Matrix<double, 9, N>; \
static const Eigen::MatrixBase<Matrix##N>::IdentityReturnType I_##N##x##N = Matrix##N::Identity(); \
-static const Eigen::MatrixBase<Matrix##N>::ConstantReturnType Z_##N##x##N = Matrix##N::Zero();
+static const decltype(Matrix##N::Zero()) Z_##N##x##N = Matrix##N::Zero();
GTSAM_MAKE_MATRIX_DEFS(1)
GTSAM_MAKE_MATRIX_DEFS(2)
diff --git a/gtsam/base/Vector.h b/gtsam/base/Vector.h
index f7923ff88..5410393f6 100644
--- a/gtsam/base/Vector.h
+++ b/gtsam/base/Vector.h
@@ -27,6 +27,7 @@
#include <gtsam/global_includes.h>
#include <Eigen/Core>
+#include <cassert>
#include <iosfwd>
#include <list>
@@ -42,14 +43,14 @@ typedef Eigen::Matrix<double, 1, 1> Vector1;
typedef Eigen::Vector2d Vector2;
typedef Eigen::Vector3d Vector3;
-static const Eigen::MatrixBase<Vector2>::ConstantReturnType Z_2x1 = Vector2::Zero();
-static const Eigen::MatrixBase<Vector3>::ConstantReturnType Z_3x1 = Vector3::Zero();
+static const decltype(Vector2::Zero()) Z_2x1 = Vector2::Zero();
+static const decltype(Vector3::Zero()) Z_3x1 = Vector3::Zero();
// Create handy typedefs and constants for vectors with N>3
// VectorN and Z_Nx1, for N=1..9
#define GTSAM_MAKE_VECTOR_DEFS(N) \
using Vector##N = Eigen::Matrix<double, N, 1>; \
- static const Eigen::MatrixBase<Vector##N>::ConstantReturnType Z_##N##x1 = Vector##N::Zero();
+ static const decltype(Vector##N::Zero()) Z_##N##x1 = Vector##N::Zero();
GTSAM_MAKE_VECTOR_DEFS(4)
GTSAM_MAKE_VECTOR_DEFS(5)
diff --git a/gtsam/linear/iterative.h b/gtsam/linear/iterative.h
index 22f65b8de..20a0c936e 100644
--- a/gtsam/linear/iterative.h
+++ b/gtsam/linear/iterative.h
@@ -61,7 +61,7 @@ namespace gtsam {
/** Apply operator A'*e */
Vector operator^(const Vector& e) const {
- return A_ ^ e;
+ return gtsam::operator^(A_, e);
}
/**
@@ -71,7 +71,7 @@ namespace gtsam {
/** gradient of objective function 0.5*|Ax-b_|^2 at x = A_'*(Ax-b_) */
Vector gradient(const Vector& x) const {
- return A() ^ (A() * x - b());
+ return gtsam::operator^(A(), Vector(A() * x - b()));
}
/** Apply operator A */
@@ -1,87 +0,0 @@
diff --git a/CMakeLists.txt b/CMakeLists.txt
index a5f0c44..69340e4 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -78,18 +78,18 @@ elseif ()
endif ()
endif ()
-# enable C++11 support.
+# enable C++14 support (required by recent Eigen versions).
if (CMAKE_VERSION VERSION_LESS "3.1")
if (MSVC)
message(FATAL_ERROR "CMake version 3.1 or later is required to compile ${PROJECT_NAME} with Microsoft Visual C++")
endif ()
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
- set (CMAKE_CXX_FLAGS "-std=c++0x ${CMAKE_CXX_FLAGS}")
+ set (CMAKE_CXX_FLAGS "-std=c++14 ${CMAKE_CXX_FLAGS}")
else ()
- set (CMAKE_CXX_FLAGS "-std=c++11 ${CMAKE_CXX_FLAGS}")
+ set (CMAKE_CXX_FLAGS "-std=c++14 ${CMAKE_CXX_FLAGS}")
endif ()
else ()
- set (CMAKE_CXX_STANDARD 11)
+ set (CMAKE_CXX_STANDARD 14)
endif ()
#======================== External Dependencies ===============================
diff --git a/experimental/kdtree_cpu.cpp b/experimental/kdtree_cpu.cpp
index 302b672..d63fcd3 100644
--- a/experimental/kdtree_cpu.cpp
+++ b/experimental/kdtree_cpu.cpp
@@ -31,6 +31,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "nabo_experimental.h"
#include "../nabo/index_heap.h"
+#include <cassert>
#include <iostream>
#include <stdexcept>
#include <limits>
diff --git a/nabo/kdtree_cpu.cpp b/nabo/kdtree_cpu.cpp
index cb1f8d1..52a444f 100644
--- a/nabo/kdtree_cpu.cpp
+++ b/nabo/kdtree_cpu.cpp
@@ -37,6 +37,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <queue>
#include <algorithm>
#include <utility>
+#include <cassert>
#ifdef HAVE_OPENMP
#include <omp.h>
#endif
diff --git a/nabo/kdtree_opencl.cpp b/nabo/kdtree_opencl.cpp
index 5a9fee2..fb1345f 100644
--- a/nabo/kdtree_opencl.cpp
+++ b/nabo/kdtree_opencl.cpp
@@ -33,6 +33,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "nabo_private.h"
#include "index_heap.h"
+#include <cassert>
#include <iostream>
#include <sstream>
#include <fstream>
diff --git a/tests/knnshow.cpp b/tests/knnshow.cpp
index 6f4d3fc..c612378 100644
--- a/tests/knnshow.cpp
+++ b/tests/knnshow.cpp
@@ -30,6 +30,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "nabo/nabo.h"
+#include <cassert>
#include <iostream>
#include <fstream>
#include <stdexcept>
diff --git a/tests/knnvalidate.cpp b/tests/knnvalidate.cpp
index 2430249..2a7dcc4 100644
--- a/tests/knnvalidate.cpp
+++ b/tests/knnvalidate.cpp
@@ -32,6 +32,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "nabo/nabo.h"
#include "helpers.h"
//#include "experimental/nabo_experimental.h"
+#include <cassert>
#include <iostream>
#include <fstream>
#include <stdexcept>
@@ -1,32 +0,0 @@
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9dabfd0..7b73418 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -128,9 +128,9 @@ endif()
#--------------------
# DEPENDENCY: boost
#--------------------
-find_package(Boost REQUIRED COMPONENTS thread system program_options date_time)
+find_package(Boost REQUIRED COMPONENTS thread program_options date_time)
if (Boost_MINOR_VERSION GREATER 47)
- find_package(Boost REQUIRED COMPONENTS thread system program_options date_time chrono)
+ find_package(Boost REQUIRED COMPONENTS thread program_options date_time chrono)
endif ()
#--------------------
diff --git a/libpointmatcherConfig.cmake.in b/libpointmatcherConfig.cmake.in
index 6de2c85..7c887fd 100644
--- a/libpointmatcherConfig.cmake.in
+++ b/libpointmatcherConfig.cmake.in
@@ -7,9 +7,9 @@
include(CMakeFindDependencyMacro)
find_dependency(libnabo REQUIRED)
find_dependency(yaml-cpp REQUIRED)
-find_package(Boost COMPONENTS thread system program_options date_time REQUIRED)
+find_package(Boost COMPONENTS thread program_options date_time REQUIRED)
if (Boost_MINOR_VERSION GREATER 47)
- find_package(Boost COMPONENTS thread system program_options date_time chrono REQUIRED)
+ find_package(Boost COMPONENTS thread program_options date_time chrono REQUIRED)
endif ()
include(${CMAKE_CURRENT_LIST_DIR}/libpointmatcher-config.cmake)
@@ -1,309 +0,0 @@
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9660f55..0186da4 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -31,12 +31,12 @@ IF(MSVC)
add_definitions(-D_USE_MATH_DEFINES)
ELSE()
IF (CMAKE_SYSTEM_PROCESSOR MATCHES "(arm64)|(ARM64)|(aarch64)|(AARCH64)")
- add_definitions (-march=armv8-a)
+ #add_definitions (-march=armv8-a)
ELSEIF (CMAKE_SYSTEM_PROCESSOR MATCHES
"(arm)|(ARM)|(armhf)|(ARMHF)|(armel)|(ARMEL)")
- add_definitions (-march=armv7-a)
+ #add_definitions (-march=armv7-a)
ELSE ()
- add_definitions (-march=native) #TODO use correct c++11 def once everybody has moved to gcc 4.7 # for now I even removed std=gnu++0x
+ #add_definitions (-march=native) #TODO use correct c++11 def once everybody has moved to gcc 4.7 # for now I even removed std=gnu++0x
ENDIF()
add_definitions (
-O3
@@ -181,7 +181,7 @@ add_library( random_generators test/random_generators.cpp test/random_generators
set_target_properties( opengv random_generators PROPERTIES
SOVERSION ${PROJECT_VERSION}
VERSION ${PROJECT_VERSION}
- CXX_STANDARD 11
+ CXX_STANDARD 14
CXX_STANDARD_REQUIRED ON
DEBUG_POSTFIX d )
@@ -329,7 +329,7 @@ IF (BUILD_TESTS)
test_Sturm
PROPERTIES
- CXX_STANDARD 11
+ CXX_STANDARD 14
CXX_STANDARD_REQUIRED ON
DEBUG_POSTFIX d )
diff --git a/modules/FindEigen.cmake b/modules/FindEigen.cmake
index 126f4a0..39b5524 100644
--- a/modules/FindEigen.cmake
+++ b/modules/FindEigen.cmake
@@ -30,7 +30,13 @@ if(NOT Eigen_FIND_VERSION)
endif(NOT Eigen_FIND_VERSION)
macro(_eigen3_check_version)
- file(READ "${EIGEN_INCLUDE_DIR}/Eigen/src/Core/util/Macros.h" _eigen3_version_header)
+ # Since Eigen 5.0.0 the version macros moved from Eigen/src/Core/util/Macros.h
+ # to a dedicated Eigen/Version header, so check the new location first.
+ if(EXISTS "${EIGEN_INCLUDE_DIR}/Eigen/Version")
+ file(READ "${EIGEN_INCLUDE_DIR}/Eigen/Version" _eigen3_version_header)
+ else()
+ file(READ "${EIGEN_INCLUDE_DIR}/Eigen/src/Core/util/Macros.h" _eigen3_version_header)
+ endif()
string(REGEX MATCH "define[ \t]+EIGEN_WORLD_VERSION[ \t]+([0-9]+)" _eigen3_world_version_match "${_eigen3_version_header}")
set(EIGEN_WORLD_VERSION "${CMAKE_MATCH_1}")
diff --git a/src/absolute_pose/CentralAbsoluteAdapter.cpp b/src/absolute_pose/CentralAbsoluteAdapter.cpp
index 684fa7e..a4ff2bd 100644
--- a/src/absolute_pose/CentralAbsoluteAdapter.cpp
+++ b/src/absolute_pose/CentralAbsoluteAdapter.cpp
@@ -29,6 +29,7 @@
******************************************************************************/
+#include <cassert>
#include <opengv/absolute_pose/CentralAbsoluteAdapter.hpp>
diff --git a/src/absolute_pose/MACentralAbsolute.cpp b/src/absolute_pose/MACentralAbsolute.cpp
index 6edbabc..1687d45 100644
--- a/src/absolute_pose/MACentralAbsolute.cpp
+++ b/src/absolute_pose/MACentralAbsolute.cpp
@@ -29,6 +29,7 @@
******************************************************************************/
+#include <cassert>
#include <opengv/absolute_pose/MACentralAbsolute.hpp>
diff --git a/src/absolute_pose/MANoncentralAbsolute.cpp b/src/absolute_pose/MANoncentralAbsolute.cpp
index d9b5b09..a7ae689 100644
--- a/src/absolute_pose/MANoncentralAbsolute.cpp
+++ b/src/absolute_pose/MANoncentralAbsolute.cpp
@@ -29,6 +29,7 @@
******************************************************************************/
+#include <cassert>
#include <opengv/absolute_pose/MANoncentralAbsolute.hpp>
opengv::absolute_pose::MANoncentralAbsolute::MANoncentralAbsolute(
diff --git a/src/absolute_pose/NoncentralAbsoluteAdapter.cpp b/src/absolute_pose/NoncentralAbsoluteAdapter.cpp
index 30176aa..6a0e405 100644
--- a/src/absolute_pose/NoncentralAbsoluteAdapter.cpp
+++ b/src/absolute_pose/NoncentralAbsoluteAdapter.cpp
@@ -29,6 +29,7 @@
******************************************************************************/
+#include <cassert>
#include <opengv/absolute_pose/NoncentralAbsoluteAdapter.hpp>
opengv::absolute_pose::NoncentralAbsoluteAdapter::NoncentralAbsoluteAdapter(
diff --git a/src/absolute_pose/NoncentralAbsoluteMultiAdapter.cpp b/src/absolute_pose/NoncentralAbsoluteMultiAdapter.cpp
index 88c237a..58a82f4 100644
--- a/src/absolute_pose/NoncentralAbsoluteMultiAdapter.cpp
+++ b/src/absolute_pose/NoncentralAbsoluteMultiAdapter.cpp
@@ -29,6 +29,7 @@
******************************************************************************/
+#include <cassert>
#include <opengv/absolute_pose/NoncentralAbsoluteMultiAdapter.hpp>
opengv::absolute_pose::NoncentralAbsoluteMultiAdapter::NoncentralAbsoluteMultiAdapter(
diff --git a/src/absolute_pose/methods.cpp b/src/absolute_pose/methods.cpp
index b1f0889..19c4eaf 100644
--- a/src/absolute_pose/methods.cpp
+++ b/src/absolute_pose/methods.cpp
@@ -29,6 +29,7 @@
******************************************************************************/
+#include <cassert>
#include <opengv/absolute_pose/methods.hpp>
#include <opengv/Indices.hpp>
diff --git a/src/absolute_pose/modules/main.cpp b/src/absolute_pose/modules/main.cpp
index ed0c271..99f7f35 100644
--- a/src/absolute_pose/modules/main.cpp
+++ b/src/absolute_pose/modules/main.cpp
@@ -29,6 +29,7 @@
******************************************************************************/
+#include <cassert>
#include <Eigen/NonLinearOptimization>
#include <Eigen/NumericalDiff>
diff --git a/src/math/arun.cpp b/src/math/arun.cpp
index a0d6296..f5c0ac3 100644
--- a/src/math/arun.cpp
+++ b/src/math/arun.cpp
@@ -29,6 +29,7 @@
******************************************************************************/
+#include <cassert>
#include <opengv/math/arun.hpp>
opengv::rotation_t
diff --git a/src/point_cloud/MAPointCloud.cpp b/src/point_cloud/MAPointCloud.cpp
index 81fd5dd..cdccae3 100644
--- a/src/point_cloud/MAPointCloud.cpp
+++ b/src/point_cloud/MAPointCloud.cpp
@@ -29,6 +29,7 @@
******************************************************************************/
+#include <cassert>
#include <opengv/point_cloud/MAPointCloud.hpp>
opengv::point_cloud::MAPointCloud::MAPointCloud(
diff --git a/src/point_cloud/PointCloudAdapter.cpp b/src/point_cloud/PointCloudAdapter.cpp
index f9faaeb..28fbb7e 100644
--- a/src/point_cloud/PointCloudAdapter.cpp
+++ b/src/point_cloud/PointCloudAdapter.cpp
@@ -29,6 +29,7 @@
******************************************************************************/
+#include <cassert>
#include <opengv/point_cloud/PointCloudAdapter.hpp>
opengv::point_cloud::PointCloudAdapter::PointCloudAdapter(
diff --git a/src/point_cloud/methods.cpp b/src/point_cloud/methods.cpp
index 5409eeb..7a26e6a 100644
--- a/src/point_cloud/methods.cpp
+++ b/src/point_cloud/methods.cpp
@@ -29,6 +29,7 @@
******************************************************************************/
+#include <cassert>
#include <opengv/point_cloud/methods.hpp>
#include <opengv/Indices.hpp>
diff --git a/src/relative_pose/CentralRelativeAdapter.cpp b/src/relative_pose/CentralRelativeAdapter.cpp
index 38e9a62..5018bd8 100644
--- a/src/relative_pose/CentralRelativeAdapter.cpp
+++ b/src/relative_pose/CentralRelativeAdapter.cpp
@@ -29,6 +29,7 @@
******************************************************************************/
+#include <cassert>
#include <opengv/relative_pose/CentralRelativeAdapter.hpp>
opengv::relative_pose::CentralRelativeAdapter::CentralRelativeAdapter(
diff --git a/src/relative_pose/CentralRelativeMultiAdapter.cpp b/src/relative_pose/CentralRelativeMultiAdapter.cpp
index 2ab7476..49a3a07 100644
--- a/src/relative_pose/CentralRelativeMultiAdapter.cpp
+++ b/src/relative_pose/CentralRelativeMultiAdapter.cpp
@@ -29,6 +29,7 @@
******************************************************************************/
+#include <cassert>
#include <opengv/relative_pose/CentralRelativeMultiAdapter.hpp>
opengv::relative_pose::CentralRelativeMultiAdapter::CentralRelativeMultiAdapter(
diff --git a/src/relative_pose/CentralRelativeWeightingAdapter.cpp b/src/relative_pose/CentralRelativeWeightingAdapter.cpp
index a6ab478..7684526 100644
--- a/src/relative_pose/CentralRelativeWeightingAdapter.cpp
+++ b/src/relative_pose/CentralRelativeWeightingAdapter.cpp
@@ -29,6 +29,7 @@
******************************************************************************/
+#include <cassert>
#include <opengv/relative_pose/CentralRelativeWeightingAdapter.hpp>
opengv::relative_pose::CentralRelativeWeightingAdapter::CentralRelativeWeightingAdapter(
diff --git a/src/relative_pose/MACentralRelative.cpp b/src/relative_pose/MACentralRelative.cpp
index ec2959f..75e76d5 100644
--- a/src/relative_pose/MACentralRelative.cpp
+++ b/src/relative_pose/MACentralRelative.cpp
@@ -29,6 +29,7 @@
******************************************************************************/
+#include <cassert>
#include <opengv/relative_pose/MACentralRelative.hpp>
opengv::relative_pose::MACentralRelative::MACentralRelative(
diff --git a/src/relative_pose/MANoncentralRelative.cpp b/src/relative_pose/MANoncentralRelative.cpp
index cea9c14..8566aeb 100644
--- a/src/relative_pose/MANoncentralRelative.cpp
+++ b/src/relative_pose/MANoncentralRelative.cpp
@@ -29,6 +29,7 @@
******************************************************************************/
+#include <cassert>
#include <opengv/relative_pose/MANoncentralRelative.hpp>
opengv::relative_pose::MANoncentralRelative::MANoncentralRelative(
diff --git a/src/relative_pose/MANoncentralRelativeMulti.cpp b/src/relative_pose/MANoncentralRelativeMulti.cpp
index 49f8ecf..8b62e07 100644
--- a/src/relative_pose/MANoncentralRelativeMulti.cpp
+++ b/src/relative_pose/MANoncentralRelativeMulti.cpp
@@ -29,6 +29,7 @@
******************************************************************************/
+#include <cassert>
#include <opengv/relative_pose/MANoncentralRelativeMulti.hpp>
opengv::relative_pose::MANoncentralRelativeMulti::MANoncentralRelativeMulti(
diff --git a/src/relative_pose/NoncentralRelativeAdapter.cpp b/src/relative_pose/NoncentralRelativeAdapter.cpp
index 552f180..775d520 100644
--- a/src/relative_pose/NoncentralRelativeAdapter.cpp
+++ b/src/relative_pose/NoncentralRelativeAdapter.cpp
@@ -29,6 +29,7 @@
******************************************************************************/
+#include <cassert>
#include <opengv/relative_pose/NoncentralRelativeAdapter.hpp>
opengv::relative_pose::NoncentralRelativeAdapter::NoncentralRelativeAdapter(
diff --git a/src/relative_pose/NoncentralRelativeMultiAdapter.cpp b/src/relative_pose/NoncentralRelativeMultiAdapter.cpp
index f41edbe..733023c 100644
--- a/src/relative_pose/NoncentralRelativeMultiAdapter.cpp
+++ b/src/relative_pose/NoncentralRelativeMultiAdapter.cpp
@@ -29,6 +29,7 @@
******************************************************************************/
+#include <cassert>
#include <opengv/relative_pose/NoncentralRelativeMultiAdapter.hpp>
opengv::relative_pose::NoncentralRelativeMultiAdapter::NoncentralRelativeMultiAdapter(
diff --git a/src/relative_pose/methods.cpp b/src/relative_pose/methods.cpp
index 0027dae..7678567 100644
--- a/src/relative_pose/methods.cpp
+++ b/src/relative_pose/methods.cpp
@@ -29,6 +29,7 @@
******************************************************************************/
+#include <cassert>
#include <opengv/relative_pose/methods.hpp>
#include <opengv/Indices.hpp>
diff --git a/src/relative_pose/modules/fivept_nister/modules.cpp b/src/relative_pose/modules/fivept_nister/modules.cpp
index 4b134c5..258d416 100644
--- a/src/relative_pose/modules/fivept_nister/modules.cpp
+++ b/src/relative_pose/modules/fivept_nister/modules.cpp
@@ -29,6 +29,7 @@
******************************************************************************/
+#include <cassert>
#include <opengv/relative_pose/modules/fivept_nister/modules.hpp>
#include <Eigen/NonLinearOptimization>
#include <Eigen/NumericalDiff>
@@ -1,29 +0,0 @@
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 261f2cda..644e068f 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -92,17 +92,20 @@ if(OB_IS_MAIN_PROJECT)
)
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/generated/Export.h" DESTINATION include/libobsensor/h)
- install(EXPORT ${OB_SDK_LIB_NAME}Config NAMESPACE ob:: DESTINATION lib)
+ install(EXPORT ${OB_SDK_LIB_NAME}Config NAMESPACE ob:: DESTINATION lib/cmake/${OB_SDK_LIB_NAME})
include(CMakePackageConfigHelpers)
+ # Name the version file <pkg>ConfigVersion.cmake (not <pkg>Version.cmake) and
+ # install it next to the config in lib/cmake/<pkg>, so find_package(OrbbecSDK)
+ # discovers it in config mode and reads its version.
write_basic_package_version_file(
- "${CMAKE_CURRENT_BINARY_DIR}/${OB_SDK_LIB_NAME}Version.cmake"
+ "${CMAKE_CURRENT_BINARY_DIR}/${OB_SDK_LIB_NAME}ConfigVersion.cmake"
VERSION "${PROJECT_VERSION}"
COMPATIBILITY SameMajorVersion
)
install(
- FILES "${CMAKE_CURRENT_BINARY_DIR}/${OB_SDK_LIB_NAME}Version.cmake"
- DESTINATION lib
+ FILES "${CMAKE_CURRENT_BINARY_DIR}/${OB_SDK_LIB_NAME}ConfigVersion.cmake"
+ DESTINATION lib/cmake/${OB_SDK_LIB_NAME}
)
if(MSVC)
install(FILES $<TARGET_PDB_FILE:${OB_SDK_LIB_NAME}> DESTINATION bin OPTIONAL)
@@ -26,7 +26,7 @@ runs:
uses: actions/cache@v4
with:
path: ${{ runner.workspace }}/vcpkg_installed
key: ${{ runner.os }}-vcpkg-export-66c0373d-x64-vs2022-cuda130_v4
key: ${{ runner.os }}-vcpkg-export-66c0373d-x64-vs2022-cuda130_v1
- name: Download and Install vcpkg
if: steps.cache-vcpkg.outputs.cache-hit != 'true'
@@ -35,25 +35,10 @@ runs:
$install_dir = "${{ runner.workspace }}\vcpkg_installed"
$archivePath = "${{ runner.workspace }}\vcpkg-export.7z"
# The 7z is built locally with bundle_windows_deps_cuda.bat and uploaded to a
# GitHub release. Resolve it by filename via the API (authenticated with the
# built-in token) so it works even from a *draft* release and regardless of
# the (changing) asset id. Requires the workflow to run in-repo (github.token
# can't read introlab drafts from a fork PR).
$repo = "introlab/rtabmap"
$releaseTag = "0.23.8"
$assetName = "vcpkg-export-66c0373d-x64-vs2022-cuda130.7z"
$apiHeaders = @{ Authorization = "Bearer ${{ github.token }}"; "User-Agent" = "rtabmap-ci"; Accept = "application/vnd.github+json" }
# Select the release by tag_name (populated on drafts too, and unique), then
# take the asset from THAT release so concurrent releases can't be confused.
$rel = (Invoke-RestMethod -Uri "https://api.github.com/repos/$repo/releases?per_page=100" -Headers $apiHeaders) |
Where-Object { $_.tag_name -eq $releaseTag } | Select-Object -First 1
if (-not $rel) { throw "Release tagged $releaseTag not found (including drafts)" }
$asset = $rel.assets | Where-Object { $_.name -eq $assetName } | Select-Object -First 1
if (-not $asset) { throw "Asset $assetName not found in release $releaseTag" }
Write-Host "Downloading $assetName (asset id $($asset.id)) ..."
$dlHeaders = @{ Authorization = "Bearer ${{ github.token }}"; "User-Agent" = "rtabmap-ci"; Accept = "application/octet-stream" }
Invoke-WebRequest -Uri $asset.url -Headers $dlHeaders -OutFile $archivePath
# The file has been built locally with bundle-windows-deps.bat
$url = "https://github.com/introlab/rtabmap/releases/download/0.23.1/vcpkg-export-66c0373d-x64-vs2022-cuda130.7z"
Invoke-WebRequest -Uri $url -OutFile $archivePath
& 7z x $archivePath "-o$install_dir" -y
- name: Add vcpkg to PATH and env variable
@@ -62,8 +47,6 @@ runs:
$vcpkg_path = "${{ runner.workspace }}\vcpkg_installed"
echo "VCPKG_EXPORT_PATH=$vcpkg_path" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
echo "$vcpkg_path\installed\x64-windows-release\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
# K4A runtime DLLs (k4a.dll, k4arecord.dll) live in the SDK bin; needed on PATH so fixup_bundle resolves them at package time.
echo "$vcpkg_path\installed\x64-windows-release\sdk\windows-desktop\amd64\release\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
echo "${{env.CUDA_PATH}}\bin\x64" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
echo "${{env.CUDA_PATH}}\extras\CUPTI\lib64" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
echo "$vcpkg_path\installed\x64-windows-release\tools\python3\Lib\site-packages\torch\lib" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
@@ -13,7 +13,7 @@ runs:
uses: actions/cache@v4
with:
path: ${{ runner.workspace }}/vcpkg_installed
key: ${{ runner.os }}-vcpkg-export-66c0373d-x64-vs2022-v6
key: ${{ runner.os }}-vcpkg-export-66c0373d-x64-vs2022-v4
- name: Download and Install vcpkg
if: steps.cache-vcpkg.outputs.cache-hit != 'true'
@@ -22,25 +22,10 @@ runs:
$install_dir = "${{ runner.workspace }}\vcpkg_installed"
$archivePath = "${{ runner.workspace }}\vcpkg-export.7z"
# The 7z is built locally with bundle_windows_deps.bat and uploaded to a
# GitHub release. Resolve it by filename via the API (authenticated with the
# built-in token) so it works even from a *draft* release and regardless of
# the (changing) asset id. Requires the workflow to run in-repo (github.token
# can't read introlab drafts from a fork PR).
$repo = "introlab/rtabmap"
$releaseTag = "0.23.8"
$assetName = "vcpkg-export-66c0373d-x64-vs2022.7z"
$apiHeaders = @{ Authorization = "Bearer ${{ github.token }}"; "User-Agent" = "rtabmap-ci"; Accept = "application/vnd.github+json" }
# Select the release by tag_name (populated on drafts too, and unique), then
# take the asset from THAT release so concurrent releases can't be confused.
$rel = (Invoke-RestMethod -Uri "https://api.github.com/repos/$repo/releases?per_page=100" -Headers $apiHeaders) |
Where-Object { $_.tag_name -eq $releaseTag } | Select-Object -First 1
if (-not $rel) { throw "Release tagged $releaseTag not found (including drafts)" }
$asset = $rel.assets | Where-Object { $_.name -eq $assetName } | Select-Object -First 1
if (-not $asset) { throw "Asset $assetName not found in release $releaseTag" }
Write-Host "Downloading $assetName (asset id $($asset.id)) ..."
$dlHeaders = @{ Authorization = "Bearer ${{ github.token }}"; "User-Agent" = "rtabmap-ci"; Accept = "application/octet-stream" }
Invoke-WebRequest -Uri $asset.url -Headers $dlHeaders -OutFile $archivePath
# The file has been built locally with bundle-windows-deps.bat
$url = "https://github.com/introlab/rtabmap/releases/download/0.23.1/vcpkg-export-66c0373d-x64-vs2022.7z"
Invoke-WebRequest -Uri $url -OutFile $archivePath
& 7z x $archivePath "-o$install_dir" -y
- name: Add vcpkg to PATH and env variable
@@ -49,6 +34,4 @@ runs:
$vcpkg_path = "${{ runner.workspace }}\vcpkg_installed"
echo "VCPKG_EXPORT_PATH=$vcpkg_path" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
echo "$vcpkg_path\installed\x64-windows-release\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
# K4A runtime DLLs (k4a.dll, k4arecord.dll) live in the SDK bin; needed on PATH so fixup_bundle resolves them at package time.
echo "$vcpkg_path\installed\x64-windows-release\sdk\windows-desktop\amd64\release\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
echo "$vcpkg_path\installed\x64-windows-release\tools\python3\Lib\site-packages\numpy.libs" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
+23 -36
View File
@@ -26,45 +26,32 @@ jobs:
include:
- build_name: macos-sequoia-intel
os: macos-15-intel
extra_deps: ""
extra_cmake_def: '-DBUILD_AS_BUNDLE=ON'
- build_name: macos-sequoia-apple-silicon
os: macos-15
extra_deps: ""
extra_cmake_def: '-DBUILD_AS_BUNDLE=ON'
- build_name: macos-tahoe-intel
os: macos-26-intel
extra_deps: ""
extra_cmake_def: '-DBUILD_AS_BUNDLE=ON'
- build_name: macos-tahoe-apple-silicon
os: macos-26
extra_deps: ""
extra_cmake_def: '-DBUILD_AS_BUNDLE=ON'
steps:
- uses: actions/checkout@v4
- name: Install Brew Dependencies
run: |
# Update brew and install from Brewfile if present, or specific packages
brew install pcl opencv octomap pdal yaml-cpp librealsense libfreenect libusb zlib libomp suite-sparse ceres-solver
- name: Install Source Dependencies
# Build (and per-dependency cache) the source-only deps not available from
# Homebrew, then install them into /usr/local. See the composite action.
uses: ./.github/actions/install-macos-source-deps
with:
os: ${{ matrix.os }}
build_type: ${{ env.BUILD_TYPE }}
brew install pcl opencv octomap g2o pdal
- name: Configure CMake
run: |
# Apple clang has no built-in OpenMP; point find_package(OpenMP) at
# Homebrew's keg-only libomp so PCL/g2o/rtabmap enable OpenMP instead of
# repeatedly logging "Could NOT find OpenMP".
LIBOMP=$(brew --prefix libomp)
cmake -B ${{github.workspace}}/build \
-DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} \
-DBUILD_AS_BUNDLE=ON \
-DWITH_ORBBEC_SDK=ON \
-DWITH_DEPTHAI=ON \
-DWITH_CERES=ON \
-DOpenMP_C_FLAGS="-Xclang -fopenmp -I$LIBOMP/include" \
-DOpenMP_C_LIB_NAMES=omp \
-DOpenMP_CXX_FLAGS="-Xclang -fopenmp -I$LIBOMP/include" \
-DOpenMP_CXX_LIB_NAMES=omp \
-DOpenMP_omp_LIBRARY="$LIBOMP/lib/libomp.dylib"
cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} ${{ matrix.extra_cmake_def }}
- name: Build
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}
@@ -74,19 +61,19 @@ jobs:
run: |
./rtabmap-console --version
- name: Build MacOS Package
run: |
cmake --build ${{ github.workspace }}/build --config ${{ env.BUILD_TYPE }} --target package
# - name: Build MacOS Package
# run: |
# cmake --build ${{ github.workspace }}/build --config ${{ env.BUILD_TYPE }} --target package
- name: Upload RTABMap Artifacts (DMG)
uses: actions/upload-artifact@v4
with:
name: RTABMap-Binaries-${{ matrix.build_name }}-nonsigned-zip
path: |
build/RTABMap-*.dmg
compression-level: 0
if-no-files-found: warn
retention-days: ${{ github.event_name == 'pull_request' && 1 || 90 }}
# - name: Upload RTABMap Artifacts (DMG)
# uses: actions/upload-artifact@v4
# with:
# name: RTABMap-Binaries-${{ matrix.build_name }}-zip
# path: |
# build/RTABMap-*.dmg
# compression-level: 0
# if-no-files-found: warn
# retention-days: ${{ github.event_name == 'pull_request' && 1 || 90 }}
# - name: Test
# working-directory: ${{github.workspace}}/build
+7 -17
View File
@@ -3,12 +3,13 @@ name: CMake-ROS
on:
push:
branches:
- master
- humble-devel
pull_request:
branches:
- '**'
env:
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
BUILD_TYPE: Release
concurrency:
@@ -17,37 +18,26 @@ concurrency:
jobs:
build:
# The CMake configure and build commands are platform agnostic and should work equally
# well on Windows or Mac. You can convert this to a matrix build if you need
# cross-platform coverage.
# See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix
name: ${{ matrix.ros_distribution }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
ros_distribution: [ humble, jazzy, kilted, lyrical, rolling]
ros_distribution: [ humble ]
include:
- ros_distribution: 'humble'
skip_keys: ""
- ros_distribution: 'jazzy'
skip_keys: ""
- ros_distribution: 'kilted'
skip_keys: ""
- ros_distribution: 'lyrical'
skip_keys: "libpointmatcher"
- ros_distribution: 'rolling'
skip_keys: "libpointmatcher gtsam"
use_ros2_testing: true # Rolling is using ros2-testing (nightly)
container:
image: osrf/ros:${{ matrix.ros_distribution }}-desktop-full
steps:
- uses: actions/checkout@v4
# Newer osrf/ros images (e.g. rolling) ship "ros2-testing-apt-source", which conflicts
# with the "ros2-apt-source" package that setup-ros installs. Remove it first so setup-ros
# can install its apt source cleanly (no-op on images that don't have it).
- name: Remove conflicting ros2 apt source package
run: apt-get remove -y ros2-testing-apt-source || true
- uses: ros-tooling/[email protected]
with:
required-ros-distributions: ${{ matrix.ros_distribution }}
use-ros2-testing: ${{ matrix.use_ros2_testing || false }}
- uses: ros-tooling/[email protected]
with:
package-name: rtabmap
+7 -25
View File
@@ -27,11 +27,11 @@ jobs:
- build_name: windows-2022
os: windows-2022
extra_deps: ""
extra_cmake_def: '-DWITH_TORCH=OFF -DWITH_ZED=OFF'
extra_cmake_def: '-DBUILD_AS_BUNDLE=ON -DWITH_PYTHON=ON -DWITH_TORCH=OFF'
- build_name: windows-2022-cuda
os: windows-2022
extra_deps: ""
extra_cmake_def: '-DWITH_TORCH=ON -DWITH_ZED=ON -DWITH_CUDASIFT=ON'
extra_cmake_def: '-DBUILD_AS_BUNDLE=ON -DWITH_PYTHON=ON -DWITH_TORCH=ON'
steps:
- uses: actions/checkout@v4
@@ -46,24 +46,9 @@ jobs:
- name: Configure CMake
run: |
# K4A, K4W2 and ZED are located via these env vars (FindK4A.cmake / FindKinectSDK2.cmake
# and the install rules), pointing at the export where the bundle staged their SDK files.
$env:K4A_ROOT_DIR = "${{env.VCPKG_EXPORT_PATH}}/installed/x64-windows-release"
$env:KINECTSDK20_DIR = "${{env.VCPKG_EXPORT_PATH}}/installed/x64-windows-release"
$env:ZED_SDK_ROOT_DIR = "${{env.VCPKG_EXPORT_PATH}}/installed/x64-windows-release"
cmake `
-B ${{github.workspace}}/build `
-DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} `
-DBUILD_AS_BUNDLE=ON `
-DWITH_PYTHON=ON `
-DWITH_CERES=ON `
-DWITH_ORBBEC_SDK=ON `
-DWITH_FREENECT2=ON `
-DWITH_K4W2=ON `
-DWITH_K4A=ON `
-DWITH_DEPTHAI=ON `
-DWITH_REALSENSE2=ON `
-DWITH_CCCORELIB=ON `
${{ matrix.extra_cmake_def }} `
-DVCPKG_MANIFEST_INSTALL=OFF `
-DVCPKG_TARGET_TRIPLET=x64-windows-release `
@@ -74,14 +59,6 @@ jobs:
- name: Build
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}
- name: Info
# Skipped for CUDA: the binary links ZED (sl_zed64.dll -> nvcuvid/nvEncodeAPI64),
# which need the NVIDIA driver; the GPU-less runner can't load the exe.
if: matrix.build_name != 'windows-2022-cuda'
working-directory: ${{github.workspace}}/build/bin
run: |
./rtabmap-console --version
- name: Build Windows Package
shell: pwsh
run: |
@@ -96,6 +73,11 @@ jobs:
shell: pwsh
run: Get-ChildItem -Path "build" -Filter "RTABMap-*" | Rename-Item -NewName { $_.BaseName + "_cuda" + $_.Extension }
- name: Info
working-directory: ${{github.workspace}}/build/bin
run: |
./rtabmap-console --version
- name: Upload RTABMap Artifacts (ZIP)
uses: actions/upload-artifact@v4
with:
-6
View File
@@ -12,9 +12,3 @@ compile_flags.txt
tags
build_*
*.bak
# Windows bundle: vcpkg tree, build output, and deps built from source (bundle_windows_deps.bat)
vcpkg/
vcpkg_installed/
vcpkg_binaries/
vcpkg_deps_from_source/
+5 -7
View File
@@ -21,8 +21,8 @@ SET(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake_modules")
# VERSION
#######################
SET(RTABMAP_MAJOR_VERSION 0)
SET(RTABMAP_MINOR_VERSION 24)
SET(RTABMAP_PATCH_VERSION 0)
SET(RTABMAP_MINOR_VERSION 23)
SET(RTABMAP_PATCH_VERSION 7)
SET(RTABMAP_VERSION
${RTABMAP_MAJOR_VERSION}.${RTABMAP_MINOR_VERSION}.${RTABMAP_PATCH_VERSION})
@@ -208,7 +208,7 @@ option(WITH_REALSENSE "Include RealSense support" ON)
option(WITH_REALSENSE_SLAM "Include RealSenseSlam support" ON)
option(WITH_REALSENSE2 "Include RealSense2 support" ON)
option(WITH_MYNTEYE "Include mynteye-s support" ON)
option(WITH_DEPTHAI "Include depthai-core v2 support" OFF)
option(WITH_DEPTHAI "Include depthai-core 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)
@@ -711,9 +711,7 @@ IF(WITH_MYNTEYE)
ENDIF(WITH_MYNTEYE)
IF(WITH_DEPTHAI)
# Force DepthAI major version 2 (>=2.24, <3.0): the v3 API is not yet
# supported (see CameraDepthAI).
FIND_PACKAGE(depthai 2.24...<3.0)
FIND_PACKAGE(depthai 2.24)
IF(depthai_FOUND)
MESSAGE(STATUS "Found depthai-core (targets)")
ENDIF(depthai_FOUND)
@@ -1879,7 +1877,7 @@ MESSAGE(STATUS " With DepthAI ${depthai_VERSION} = YES (License: MIT)")
ELSEIF(NOT WITH_DEPTHAI)
MESSAGE(STATUS " With DepthAI = NO (WITH_DEPTHAI=OFF)")
ELSE()
MESSAGE(STATUS " With DepthAI = NO (depthai-core v2 not found)")
MESSAGE(STATUS " With DepthAI = NO (depthai-core not found)")
ENDIF()
IF(xvsdk_FOUND)
+2 -2
View File
@@ -1078,7 +1078,7 @@
"\"$(SRCROOT)/RTABMapApp/Libraries/include\"",
"\"$(SRCROOT)/RTABMapApp/Libraries/include/eigen3\"",
"\"$(SRCROOT)/RTABMapApp/Libraries/include/pcl-1.15\"",
"\"$(SRCROOT)/RTABMapApp/Libraries/include/rtabmap-latest\"",
"\"$(SRCROOT)/RTABMapApp/Libraries/include/rtabmap-0.23\"",
"\"$(SRCROOT)/../android/jni/tango-gl/include\"",
"\"$(SRCROOT)/../android/jni/third-party/include\"",
"\"$(SRCROOT)/RTABMapApp/Libraries/lib/vtk.framework/Headers\"",
@@ -1139,7 +1139,7 @@
"\"$(SRCROOT)/RTABMapApp/Libraries/include\"",
"\"$(SRCROOT)/RTABMapApp/Libraries/include/eigen3\"",
"\"$(SRCROOT)/RTABMapApp/Libraries/include/pcl-1.15\"",
"\"$(SRCROOT)/RTABMapApp/Libraries/include/rtabmap-latest\"",
"\"$(SRCROOT)/RTABMapApp/Libraries/include/rtabmap-0.23\"",
"\"$(SRCROOT)/../android/jni/tango-gl/include\"",
"\"$(SRCROOT)/../android/jni/third-party/include\"",
"\"$(SRCROOT)/RTABMapApp/Libraries/lib/vtk.framework/Headers\"",
-10
View File
@@ -303,13 +303,3 @@ cd ios
cmake -G Xcode -DCMAKE_SYSTEM_NAME=iOS -DCMAKE_OSX_ARCHITECTURES=arm64 -DCMAKE_OSX_SYSROOT=$sysroot -DBUILD_SHARED_LIBS=OFF -DCMAKE_BUILD_TYPE=Release -DCMAKE_OSX_DEPLOYMENT_TARGET=12.0 -DCMAKE_INSTALL_PREFIX=$prefix -DCMAKE_FIND_ROOT_PATH=$prefix -DWITH_QT=OFF -DBUILD_APP=OFF -DBUILD_TOOLS=OFF -DWITH_TORO=OFF -DWITH_VERTIGO=OFF -DWITH_MADGWICK=OFF -DWITH_ORB_OCTREE=ON -DBUILD_EXAMPLES=OFF -DWITH_LIBLAS=ON -DWITH_OPENGV=OFF ../../../../../..
cmake --build . --config Release
cmake --build . --config Release --target install
# rtabmap installs its headers into a version-stamped "rtabmap-<major>.<minor>" directory.
# Create a version-agnostic "rtabmap-latest" symlink to the just-installed one (newest by
# modification time) so the Xcode project's header search path does not need updating on every
# rtabmap minor-version bump. ls -t is used instead of "sort -V" for BSD/macOS portability.
rtabmap_versioned=$(cd "$prefix/include" && ls -td rtabmap-[0-9]* 2>/dev/null | head -n1)
if [ -n "$rtabmap_versioned" ]; then
ln -sfn "$rtabmap_versioned" "$prefix/include/rtabmap-latest"
echo "Linked $prefix/include/rtabmap-latest -> $rtabmap_versioned"
fi
+9 -124
View File
@@ -33,16 +33,8 @@ ENDIF()
# Add binary
IF(APPLE AND BUILD_AS_BUNDLE)
ADD_EXECUTABLE(rtabmap_app MACOSX_BUNDLE ${SRC_FILES})
# Custom Info.plist providing NSCameraUsageDescription, required by macOS to
# grant the app access to USB/UVC cameras (e.g. Orbbec, RealSense). A bundle
# identifier is also set: macOS ties the camera (TCC) permission to it, so it
# must be non-empty for the permission to be granted/persisted.
SET_TARGET_PROPERTIES(rtabmap_app PROPERTIES
MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist.in
MACOSX_BUNDLE_GUI_IDENTIFIER "com.introlab.rtabmap"
MACOSX_BUNDLE_BUNDLE_NAME "${CMAKE_BUNDLE_NAME}")
ELSEIF(WIN32 AND BUILD_AS_BUNDLE)
ADD_EXECUTABLE(rtabmap_app WIN32 ${SRC_FILES})
ADD_EXECUTABLE(rtabmap_app ${SRC_FILES})
ELSE()
ADD_EXECUTABLE(rtabmap_app ${SRC_FILES})
ENDIF()
@@ -111,26 +103,12 @@ IF(BUILD_AS_BUNDLE AND (APPLE OR WIN32))
ENDIF(OpenNI2_FOUND)
IF(k4a_FOUND)
# Install needed depthengine_2_0.dll. Its location varies by K4A SDK version:
# v1.4.1 ships it under sdk/windows-desktop/amd64/release/bin, or fallback in tools/.
# Install needed depthengine_2_0.dll
IF(WIN32)
file(TO_CMAKE_PATH "$ENV{K4A_ROOT_DIR}" ENV_K4A_ROOT_DIR)
set(DEPTHENGINE_DLL "")
foreach(_depthengine_dir
"${ENV_K4A_ROOT_DIR}/sdk/windows-desktop/amd64/release/bin"
"${ENV_K4A_ROOT_DIR}/tools")
if(EXISTS "${_depthengine_dir}/depthengine_2_0.dll")
set(DEPTHENGINE_DLL "${_depthengine_dir}/depthengine_2_0.dll")
break()
endif()
endforeach()
IF(DEPTHENGINE_DLL)
INSTALL(FILES "${DEPTHENGINE_DLL}"
DESTINATION ${thirdparty_dest_dir}
COMPONENT runtime)
ELSE()
MESSAGE(WARNING "depthengine_2_0.dll not found under $ENV{K4A_ROOT_DIR} (sdk/windows-desktop/amd64/release/bin or tools); Kinect for Azure depth may not work at runtime.")
ENDIF()
INSTALL(FILES "${ENV_K4A_ROOT_DIR}/tools/depthengine_2_0.dll"
DESTINATION ${thirdparty_dest_dir}
COMPONENT runtime)
ENDIF(WIN32)
ENDIF(k4a_FOUND)
@@ -151,30 +129,14 @@ IF(BUILD_AS_BUNDLE AND (APPLE OR WIN32))
IF(NOT OrbbecSDK_BIN_DIR)
MESSAGE(FATAL_ERROR "OrbbecSDK.dll not found! Verify your PATH.")
ENDIF(NOT OrbbecSDK_BIN_DIR)
MESSAGE(STATUS "OrbbecSDK_BIN_DIR=${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 "*")
ELSEIF(APPLE)
# OrbbecSDK loads its extensions (frame processor, filters like
# FrameUnpacker) via dlopen relative to libOrbbecSDK. fixup_bundle puts
# libOrbbecSDK in Contents/Frameworks, so the extensions must sit next to
# it in Frameworks/extensions (they reference @rpath/libOrbbecSDK, which
# resolves via the app executable's @executable_path/../Frameworks rpath).
# Without this the camera is detected but frame processing fails.
get_filename_component(OrbbecSDK_LIB_DIR "${OrbbecSDK_DIR}/../.." ABSOLUTE)
INSTALL(DIRECTORY "${OrbbecSDK_LIB_DIR}/extensions"
DESTINATION Frameworks
COMPONENT runtime)
IF(EXISTS "${OrbbecSDK_LIB_DIR}/OrbbecSDKConfig.xml")
INSTALL(FILES "${OrbbecSDK_LIB_DIR}/OrbbecSDKConfig.xml"
DESTINATION Frameworks
COMPONENT runtime)
ENDIF()
ENDIF(WIN32)
ENDIF(WIN32)
ENDIF(OrbbecSDK_FOUND)
IF(Torch_FOUND)
@@ -279,42 +241,7 @@ IF(BUILD_AS_BUNDLE AND (APPLE OR WIN32))
ENDIF(WIN32)
ENDIF(Python3_FOUND)
IF(Qt6_FOUND AND APPLE)
# On macOS we do NOT use qt_deploy_runtime_dependencies (macdeployqt):
# macdeployqt cannot deploy VTK 9.6+, whose libraries reference each other
# via @rpath relative to "@loader_path/../lib". Instead we install the Qt plugins
# manually and let fixup_bundle() below deploy all libraries.
IF(TARGET Qt6::QCocoaIntegrationPlugin)
get_target_property(_qt_plugin_loc Qt6::QCocoaIntegrationPlugin LOCATION)
get_filename_component(_qt_plugins_dir "${_qt_plugin_loc}" DIRECTORY) # .../plugins/platforms
get_filename_component(_qt_plugins_dir "${_qt_plugins_dir}" DIRECTORY) # .../plugins
FOREACH(_qt_plugin_type platforms styles imageformats iconengines)
IF(EXISTS "${_qt_plugins_dir}/${_qt_plugin_type}")
# Homebrew Qt plugins are symlinks into the Cellar; resolve them to the
# real files so they aren't installed as dangling symlinks (which would
# break fixup_bundle and codesign).
FILE(GLOB _qt_plugin_files "${_qt_plugins_dir}/${_qt_plugin_type}/*${CMAKE_SHARED_LIBRARY_SUFFIX}")
SET(_qt_plugin_real "")
FOREACH(_qt_plugin_file ${_qt_plugin_files})
GET_FILENAME_COMPONENT(_qt_plugin_file "${_qt_plugin_file}" REALPATH)
LIST(APPEND _qt_plugin_real "${_qt_plugin_file}")
ENDFOREACH()
IF(_qt_plugin_real)
INSTALL(FILES ${_qt_plugin_real}
DESTINATION ${plugin_dest_dir}/${_qt_plugin_type}
COMPONENT runtime)
ENDIF()
ENDIF()
ENDFOREACH()
ELSE()
MESSAGE(WARNING "Qt6::QCocoaIntegrationPlugin target not found: Qt plugins may be missing from the bundle")
ENDIF()
# qt.conf so Qt finds the bundled plugins (path is relative to Contents/)
SET(QT_CONF_FILE [Paths]\nPlugins=${plugin_dest_dir})
INSTALL(CODE "
file(WRITE \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${qtconf_dest_dir}/qt.conf\" \"${QT_CONF_FILE}\")
" COMPONENT runtime)
ELSEIF(Qt6_FOUND)
IF(Qt6_FOUND)
# Reference: https://doc-snapshots.qt.io/qt6-6.4/qt-deploy-runtime-dependencies.html
# The following script must only be executed at install time
set(deploy_script "${CMAKE_CURRENT_BINARY_DIR}/deploy_app$<CONFIG>.cmake")
@@ -404,10 +331,7 @@ IF(BUILD_AS_BUNDLE AND (APPLE OR WIN32))
ENDIF()
# directories to look for dependencies
# CMAKE_LIBRARY_OUTPUT_DIRECTORY is where rtabmap's own libraries (e.g.
# librtabmap_core) are built; fixup_bundle needs it to resolve the app's
# @rpath references to them (macdeployqt used to handle this via rpath).
SET(DIRS "${QT_LIBRARY_DIRS}" "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}" "\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/lib")
SET(DIRS "${QT_LIBRARY_DIRS}" "\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/lib")
IF(APPLE)
SET(DIRS ${DIRS} /usr/local /usr/local/lib /opt/homebrew /opt/homebrew/lib /opt/homebrew/lib/gcc/current)
ENDIF(APPLE)
@@ -422,16 +346,6 @@ IF(BUILD_AS_BUNDLE AND (APPLE OR WIN32))
# Glob Qt Plugins
file(GLOB_RECURSE ALL_LIBS \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${plugin_dest_dir}/*${CMAKE_SHARED_LIBRARY_SUFFIX}\")
# OrbbecSDK loads its filter/frame-processor extensions via dlopen, and they
# link @rpath/libOrbbecSDK. Feed them to fixup_bundle so their reference is
# rewritten to the embedded libOrbbecSDK
file(GLOB ORBBEC_EXT_LIBS
\"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/Frameworks/extensions/filters/*${CMAKE_SHARED_LIBRARY_SUFFIX}\"
\"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/Frameworks/extensions/frameprocessor/*${CMAKE_SHARED_LIBRARY_SUFFIX}\")
if(ORBBEC_EXT_LIBS)
list(APPEND ALL_LIBS \${ORBBEC_EXT_LIBS})
endif()
if(NOT \"${python_pyd_dir}\" STREQUAL \"\")
file(GLOB_RECURSE PYD_FILES \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${python_pyd_dir}/*.pyd\")
if(PYD_FILES)
@@ -447,37 +361,8 @@ IF(BUILD_AS_BUNDLE AND (APPLE OR WIN32))
set(BU_CHMOD_BUNDLE_ITEMS ON)
include(\"BundleUtilities\")
# nvcuvid.dll (NVDEC) and nvEncodeAPI64.dll (NVENC), and the CUDA driver API
# nvcuda.dll, ship with the NVIDIA GPU driver (System32), not the CUDA toolkit,
# so they are absent on driver-less CI runners and must never be bundled (they
# are resolved at runtime from the end user's driver). Mark them 'system' so
# fixup_bundle skips them instead of failing to resolve them.
function(gp_resolved_file_type_override resolved_file type_var)
if(resolved_file MATCHES \"(nvcuvid|nvEncodeAPI64|nvcuda)\")
set(\${type_var} \"system\" PARENT_SCOPE)
endif()
endfunction()
fixup_bundle(\"${APPS}\" \"\${ALL_LIBS}\" \"${DIRS}\")
" COMPONENT runtime)
IF(APPLE)
# Re-sign ad-hoc AFTER fixup_bundle has finished all its install_name_tool
# edits.
install(CODE "
set(_contents \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}\")
get_filename_component(_app \"\${_contents}\" DIRECTORY)
file(GLOB_RECURSE _nested \"\${_contents}/*${CMAKE_SHARED_LIBRARY_SUFFIX}\")
foreach(_f \${_nested})
execute_process(COMMAND codesign --force --sign - --timestamp=none \"\${_f}\")
endforeach()
file(GLOB _frameworks \"\${_contents}/Frameworks/*.framework\")
foreach(_f \${_frameworks})
execute_process(COMMAND codesign --force --sign - --timestamp=none \"\${_f}\")
endforeach()
message(STATUS \"Ad-hoc re-signing bundle: \${_app}\")
execute_process(COMMAND codesign --force --sign - --timestamp=none \"\${_app}\")
" COMPONENT runtime)
ENDIF(APPLE)
ENDIF(BUILD_AS_BUNDLE AND (APPLE OR WIN32))
-40
View File
@@ -1,40 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
<key>NSHighResolutionCapable</key>
<string>True</string>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
<string>${MACOSX_BUNDLE_EXECUTABLE_NAME}</string>
<key>CFBundleGetInfoString</key>
<string>${MACOSX_BUNDLE_INFO_STRING}</string>
<key>CFBundleIconFile</key>
<string>${MACOSX_BUNDLE_ICON_FILE}</string>
<key>CFBundleIdentifier</key>
<string>${MACOSX_BUNDLE_GUI_IDENTIFIER}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleLongVersionString</key>
<string>${MACOSX_BUNDLE_LONG_VERSION_STRING}</string>
<key>CFBundleName</key>
<string>${MACOSX_BUNDLE_BUNDLE_NAME}</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>${MACOSX_BUNDLE_SHORT_VERSION_STRING}</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>${MACOSX_BUNDLE_BUNDLE_VERSION}</string>
<key>CSResourcesFileMapped</key>
<true/>
<key>NSHumanReadableCopyright</key>
<string>${MACOSX_BUNDLE_COPYRIGHT}</string>
<key>NSCameraUsageDescription</key>
<string>RTAB-Map needs access to the camera to capture images from connected RGB-D/stereo cameras (e.g. Orbbec, RealSense).</string>
</dict>
</plist>
-10
View File
@@ -52,10 +52,6 @@ int main(int argc, char* argv[])
ULogger::setLevel(ULogger::kWarning);
#ifdef WIN32
// STA (single-threaded apartment) is required for the native file dialogs / File Explorer
// (see commit d75cc04, "Fixed File Explorer hanging (Qt 5.12)"). Do NOT switch to MTA
// (CoInitializeEx COINIT_MULTITHREADED): it deadlocks the
// native file dialogs.
CoInitialize(nullptr);
#endif
@@ -64,12 +60,6 @@ int main(int argc, char* argv[])
QSurfaceFormat::setDefaultFormat(QVTKRenderWidget::defaultFormat());
#endif
// Recommended by VTK when using QVTKOpenGLNativeWidget (a QOpenGLWidget): let all VTK
// render widgets share a single OpenGL context, which is needed for correct rendering
// when render widgets live in / move across multiple top-level windows. Must be set
// before QApplication is constructed.
QApplication::setAttribute(Qt::AA_ShareOpenGLContexts);
/* Create tasks */
QApplication * app = new QApplication(argc, argv);
app->setStyleSheet("QMessageBox { messagebox-text-interaction-flags: 5; }"); // selectable message box
+13 -204
View File
@@ -4,8 +4,6 @@ setlocal enabledelayedexpansion
:: --- CONFIGURATION ---
set "VCPKG_ROOT=%~dp0vcpkg"
set "EXPORT_DIR=%~dp0vcpkg_binaries"
:: All deps downloaded/built from source (git clones + the pinned CMake) live here.
set "SRC_DIR=%~dp0vcpkg_deps_from_source"
set "TRIPLET=x64-windows-release"
set "SEVENZIP_EXE=C:\Program Files\7-Zip\7z.exe"
@@ -45,8 +43,7 @@ echo [+] Installing dependencies via vcpkg manifest...
--x-feature=openni2 ^
--x-feature=gtsam-deps ^
--x-feature=python ^
--x-feature=libpointmatcher-deps ^
--x-feature=libfreenect2-deps || exit /b !errorlevel!
--x-feature=libpointmatcher-deps || exit /b !errorlevel!
:: 3. Export
echo [+] Exporting built binaries to raw folder...
@@ -55,7 +52,13 @@ for /f "usebackq tokens=*" %%i in (`"%VS_LOCATOR%" -latest -property catalog_pro
set TARGET_NAME=vcpkg-export-%VCPKG_COMMIT_SHORT%-x64-%VS_YEAR%
set TARGET_FULL_PATH=%EXPORT_DIR%\%TARGET_NAME%
if exist "%TARGET_FULL_PATH%" rd /s /q "%TARGET_FULL_PATH%"
"%VCPKG_ROOT%\vcpkg.exe" export --raw --output-dir="%EXPORT_DIR%" --output=%TARGET_NAME% --triplet=%TRIPLET% || exit /b !errorlevel!
"%VCPKG_ROOT%\vcpkg.exe" export --raw --output-dir="%EXPORT_DIR%" --triplet=%TRIPLET% || exit /b !errorlevel!
:: Find the actual exported folder name (it usually contains a date/hash)
for /d %%i in ("%EXPORT_DIR%\vcpkg-export-20??????-??????") do set "FINAL_EXPORT_PATH=%%i"
echo [+] Rename folder %FINAL_EXPORT_PATH% to %TARGET_NAME%
ren "%FINAL_EXPORT_PATH%" "%TARGET_NAME%" || exit /b !errorlevel!
set "FINAL_EXPORT_PATH=%TARGET_FULL_PATH%"
echo [+] Add numpy...
@@ -65,72 +68,6 @@ echo [+] Add numpy...
%FINAL_EXPORT_PATH%/installed/%TRIPLET%/tools/python3/python.exe -m pip install "numpy<2" || exit /b !errorlevel!
:: 4. Other dependencies not in vcpkg
:: Everything cloned/downloaded below goes into %SRC_DIR% to keep the repo root clean.
if not exist "%SRC_DIR%" mkdir "%SRC_DIR%"
cd /d "%SRC_DIR%"
:: Kinect for Windows SDK v2 (k4w2): rtabmap's FindKinectSDK2.cmake expects the
:: Microsoft SDK layout (KINECTSDK20_DIR\inc and \Lib\x64), but vcpkg's kinectsdk2
:: port installs vcpkg-style (include\ and lib\). Mirror the bundled headers/lib into
:: the expected layout so it is found with KINECTSDK20_DIR pointing at the export.
if "%KINECTSDK20_DIR%"=="" (
echo Error: KINECTSDK20_DIR environment variable is not set! Install Kinect for Windows SDK v2: https://www.microsoft.com/en-us/download/details.aspx?id=44561
pause
exit /b 1
)
echo [+] Arranging Kinect SDK v2 layout for FindKinectSDK2...
set "K4W2_ROOT=%FINAL_EXPORT_PATH%\installed\%TRIPLET%"
robocopy "%K4W2_ROOT%\include" "%K4W2_ROOT%\inc" Kinect*.h Nui*.h /XO >nul
robocopy "%K4W2_ROOT%\lib" "%K4W2_ROOT%\Lib\x64" Kinect20*.lib /XO >nul
robocopy "%KINECTSDK20_DIR%\bin" "%K4W2_ROOT%\bin" Kinect20.dll /XO >nul
:: Robocopy exit codes under 8 mean successful copies/no changes; 8+ is a failure.
if !errorlevel! GEQ 8 (
echo Error: Robocopy failed with exit code !errorlevel!
pause
exit /b !errorlevel!
)
:: orbbec SDK2
echo [+] Building OrbbecSDK_v2...
if not exist OrbbecSDK_v2 (
echo [+] Downloading and applying patch...
git clone https://github.com/orbbec/OrbbecSDK_v2.git
cd OrbbecSDK_v2
git checkout v2.8.7
:: Install the CMake package config under lib/cmake/<pkg> so find_package(OrbbecSDK) works
git apply "%~dp0patches\orbbecsdk_2.8.7.patch"
cd ..
)
cd OrbbecSDK_v2
cmake -S . -B build -GNinja ^
-DVCPKG_MANIFEST_INSTALL=OFF ^
-DVCPKG_TARGET_TRIPLET=x64-windows-release ^
-DVCPKG_INSTALLED_DIR="%FINAL_EXPORT_PATH%\installed" ^
-DCMAKE_TOOLCHAIN_FILE="%FINAL_EXPORT_PATH%\scripts\buildsystems\vcpkg.cmake" ^
-DCMAKE_INSTALL_PREFIX="%FINAL_EXPORT_PATH%\installed\%TRIPLET%" ^
-DCMAKE_BUILD_TYPE=Release ^
-DOB_BUILD_DOCS=OFF ^
-DOB_BUILD_EXAMPLES=OFF ^
-DOB_BUILD_TOOLS=OFF ^
-DOB_INSTALL_EXAMPLES_SOURCE=OFF || exit /b !errorlevel!
cmake --build build --config Release --target install || exit /b !errorlevel!
cd ..
if "%K4A_ROOT_DIR%"=="" (
echo Error: K4A_ROOT_DIR environment variable is not set! Install K4A: https://github.com/microsoft/Azure-Kinect-Sensor-SDK/blob/develop/docs/usage.md
pause
exit /b 1
)
echo Copying Kinect For Azure components...
robocopy "%K4A_ROOT_DIR%\sdk" "%FINAL_EXPORT_PATH%\installed\%TRIPLET%\sdk" /E /XO
:: Robocopy exit codes under 8 mean successful copies/no changes.
:: 8 or higher means there was a failure.
if !errorlevel! GEQ 8 (
echo Error: Robocopy failed with exit code !errorlevel!
pause
exit /b !errorlevel!
)
:: libnabo
echo [+] Building libnabo...
if not exist libnabo (
@@ -139,7 +76,7 @@ if not exist libnabo (
cd libnabo
:: Jan 27, 2022
git checkout c925c47
git apply "%~dp0patches\libnabo_c925c47.patch"
git apply ../patches/libnabo_c925c47.patch
cd ..
)
cd libnabo
@@ -166,7 +103,7 @@ if not exist libpointmatcher (
cd libpointmatcher
:: Mar 17, 2023
git checkout 7dc58e5
git apply "%~dp0patches\pointmatcher_7dc58e5.patch"
git apply ../patches/pointmatcher_7dc58e5.patch
cd ..
)
cd libpointmatcher
@@ -199,7 +136,7 @@ if not exist gtsam (
:: June 18, 2025
git checkout 4.3a0-ros
git cherry-pick 18af4e6
git apply "%~dp0patches\gtsam_4_3a0-ros.patch"
git apply ../patches/gtsam_4_3a0-ros.patch
cd ..
)
cd gtsam
@@ -230,7 +167,7 @@ if not exist opengv (
cd opengv
:: Aug 6, 2020
git checkout 91f4b19c73450833a40e463ad3648aae80b3a7f3
git apply "%~dp0patches\opengv_91f4b19c.patch"
git apply ../patches/opengv_91f4b19c.patch
cd ..
)
cd opengv
@@ -245,117 +182,6 @@ cmake -S . -B build -GNinja ^
cmake --build build --config Release --target install || exit /b !errorlevel!
cd ..
:: libfreenect2
echo [+] Building libfreenect2...
if not exist libfreenect2 (
echo [+] Downloading and applying patch...
git clone https://github.com/OpenKinect/libfreenect2.git
cd libfreenect2
:: Aug 6, 2021
git checkout v0.2.1
:: Patch makes freenect2Config.cmake relocatable so the prebuilt bundle works
:: after being moved/unzipped, drops cudaDeviceProp::clockRate/computeMode
:: removed in CUDA 13 from the CUDA build, and renames a CL_ICDL_VERSION local
:: that collides with the OpenCL 3.0 macro.
git apply "%~dp0patches\libfreenect2_v0.2.1.patch"
cd ..
)
cd libfreenect2
:: libfreenect2's FindLibUSB.cmake locates libusb via pkg-config. It declares an
:: ancient cmake_minimum_required (2.8.12), which makes FindPkgConfig default
:: PKG_CONFIG_USE_CMAKE_PREFIX_PATH=OFF, so it ignores the vcpkg CMAKE_PREFIX_PATH.
:: Force it ON so the bundle's lib/pkgconfig (libusb-1.0.pc, libturbojpeg.pc) is
:: searched, use the vcpkg-bundled pkgconf, and also set PKG_CONFIG_PATH as a belt.
set "PKG_CONFIG_PATH=%FINAL_EXPORT_PATH%\installed\%TRIPLET%\lib\pkgconfig"
cmake -S . -B build -GNinja ^
-DVCPKG_MANIFEST_INSTALL=OFF ^
-DVCPKG_TARGET_TRIPLET=x64-windows-release ^
-DVCPKG_INSTALLED_DIR="%FINAL_EXPORT_PATH%\installed" ^
-DCMAKE_TOOLCHAIN_FILE="%FINAL_EXPORT_PATH%\scripts\buildsystems\vcpkg.cmake" ^
-DPKG_CONFIG_EXECUTABLE="%FINAL_EXPORT_PATH%\installed\%TRIPLET%\tools\pkgconf\pkgconf.exe" ^
-DPKG_CONFIG_USE_CMAKE_PREFIX_PATH=ON ^
-DCMAKE_BUILD_TYPE=Release ^
-DENABLE_CUDA=OFF ^
-DENABLE_OPENCL=OFF ^
-DBUILD_EXAMPLES=OFF ^
-DCMAKE_INSTALL_PREFIX="%FINAL_EXPORT_PATH%\installed\%TRIPLET%" ^
-DBUILD_SHARED_LIBS=ON || exit /b !errorlevel!
cmake --build build --config Release --target install || exit /b !errorlevel!
cd ..
:: depthai
echo [+] Building depthai...
if not exist depthai-core (
echo [+] Downloading...
git clone https://github.com/luxonis/depthai-core.git
cd depthai-core
:: depthai 2.32.0 (Hunter-based; v2 does NOT use vcpkg/CMake presets)
git checkout v2.32.0
git submodule update --init --recursive
cd ..
)
cd depthai-core
:: v2 and its old Hunter sub-deps declare cmake_minimum_required < 3.5, which
:: CMake 4.x rejects, and CMAKE_POLICY_VERSION_MINIMUM does not propagate into
:: Hunter's sub-builds. Use a pinned CMake 3.x just for depthai (Hunter reuses the
:: same cmake binary for its dependency sub-builds).
set "CMAKE3_VER=3.31.12"
set "CMAKE3_NAME=cmake-%CMAKE3_VER%-windows-x86_64"
set "CMAKE3_DIR=%SRC_DIR%\%CMAKE3_NAME%"
set "CMAKE3=%CMAKE3_DIR%\bin\cmake.exe"
if not exist "%CMAKE3_DIR%" (
echo [+] Downloading CMake %CMAKE3_VER% ...
curl -L -o "%SRC_DIR%\%CMAKE3_NAME%.zip" "https://github.com/Kitware/CMake/releases/download/v%CMAKE3_VER%/%CMAKE3_NAME%.zip" || exit /b !errorlevel!
"%SEVENZIP_EXE%" x "%SRC_DIR%\%CMAKE3_NAME%.zip" -o"%SRC_DIR%" -y || exit /b !errorlevel!
)
:: v2 is fully Hunter-managed (no vcpkg toolchain). depthaiDependencies.cmake
:: unconditionally does find_package(OpenCV 4 QUIET CONFIG) (not gated by
:: DEPTHAI_OPENCV_SUPPORT); if it finds the bundle's OpenCV, OpenCVModules does
:: find_dependency(TIFF) which collides with Hunter's config-less FindTIFF. We don't
:: need depthai's OpenCV at all (CameraDepthAI converts ImgFrame->cv::Mat itself), so
:: hard-disable the lookup. DEPTHAI_ENABLE_CURL=OFF avoids Hunter's old zlib/curl.
"%CMAKE3%" -S . -B build -GNinja ^
-DCMAKE_INSTALL_PREFIX="%FINAL_EXPORT_PATH%\installed\%TRIPLET%" ^
-DCMAKE_BUILD_TYPE=Release ^
-DBUILD_SHARED_LIBS=ON ^
-DDEPTHAI_OPENCV_SUPPORT=OFF ^
-DCMAKE_DISABLE_FIND_PACKAGE_OpenCV=ON ^
-DDEPTHAI_ENABLE_CURL=OFF ^
-DDEPTHAI_BUILD_EXAMPLES=OFF ^
-DDEPTHAI_BUILD_TESTS=OFF || exit /b !errorlevel!
"%CMAKE3%" --build build --config Release --target install || exit /b !errorlevel!
cd ..
:: CCCoreLib
echo [+] Building CCCoreLib...
if not exist CCCoreLib (
echo [+] Downloading...
git clone https://github.com/CloudCompare/CCCoreLib.git
cd CCCoreLib
:: June 20, 2026
git checkout 4095bea6552096cb528c3b8b5cb9505df2aa6002
git submodule update --init --recursive
:: nanoflann is an internal dep (only used in src/Kriging.cpp, no public header),
:: but CCCoreLib links it PUBLIC, leaking nanoflann::nanoflann into the exported
:: interface and breaking find_package(CCCoreLib). Link it PRIVATE instead.
git apply "%~dp0patches\cccorelib_4095bea.patch"
cd ..
)
cd CCCoreLib
cmake -S . -B build -GNinja ^
-DVCPKG_MANIFEST_INSTALL=OFF ^
-DVCPKG_TARGET_TRIPLET=x64-windows-release ^
-DVCPKG_INSTALLED_DIR="%FINAL_EXPORT_PATH%\installed" ^
-DCMAKE_TOOLCHAIN_FILE="%FINAL_EXPORT_PATH%\scripts\buildsystems\vcpkg.cmake" ^
-DCMAKE_INSTALL_PREFIX="%FINAL_EXPORT_PATH%\installed\%TRIPLET%" ^
-DCMAKE_BUILD_TYPE=Release ^
-DCCCORELIB_SHARED=ON ^
-DCCCORELIB_USE_CGAL=OFF ^
-DCCCORELIB_USE_TBB=ON ^
-DCCCORELIB_USE_QT_CONCURRENT=OFF || exit /b !errorlevel!
cmake --build build --config Release --target install || exit /b !errorlevel!
cd ..
:: 5. ZIP the folder
echo [+] Creating final package with 7-Zip...
:: Rip off pdb files
@@ -379,30 +205,13 @@ if !errorlevel! EQU 0 (
:: Example building rtabmap afterwards
goto :EndComment
:: The vcpkg export folder should not be in the rtabmap source directory
:: (otherwise we get some cmake errors about that)
set VCPKG_UNZIPPED_EXPORT_PATH=%USERPROFILE%\Downloads\vcpkg-export-########-x64-vs2022
set PATH=%VCPKG_UNZIPPED_EXPORT_PATH%\installed\x64-windows-release\bin;%PATH%
set PATH=%VCPKG_UNZIPPED_EXPORT_PATH%\installed\x64-windows-release\sdk\windows-desktop\amd64\release\bin;%PATH%
set PATH=%VCPKG_UNZIPPED_EXPORT_PATH%\installed\x64-windows-release\tools\python3\Lib\site-packages\numpy.libs;%PATH%
set K4A_ROOT_DIR=%VCPKG_UNZIPPED_EXPORT_PATH%\installed\x64-windows-release
set KINECTSDK20_DIR=%VCPKG_UNZIPPED_EXPORT_PATH%\installed\x64-windows-release
cmake -B build -GNinja ^
-DCMAKE_BUILD_TYPE=Release ^
-DBUILD_AS_BUNDLE=ON ^
-DWITH_PYTHON=ON ^
-DBUILD_AS_BUNDLE=ON -DWITH_PYTHON=ON ^
-DWITH_ZED=OFF ^
-DWITH_CERES=ON ^
-DWITH_ORBBEC_SDK=ON ^
-DWITH_FREENECT2=ON ^
-DWITH_K4W2=ON ^
-DWITH_K4A=ON ^
-DWITH_DEPTHAI=ON ^
-DWITH_REALSENSE2=ON ^
-DWITH_CCCORELIB=ON ^
-DWITH_PDAL=OFF ^
-DVCPKG_MANIFEST_INSTALL=OFF ^
-DVCPKG_TARGET_TRIPLET=x64-windows-release ^
-DVCPKG_INSTALLED_DIR="%VCPKG_UNZIPPED_EXPORT_PATH%/installed" ^
+17 -116
View File
@@ -34,8 +34,6 @@ echo Installed CUDA Toolkit: %CUDA_VER%
:: --- CONFIGURATION ---
set "VCPKG_ROOT=%~dp0vcpkg"
set "EXPORT_DIR=%~dp0vcpkg_binaries"
:: All deps downloaded/built from source (pytorch, torchvision, opencv, libfreenect2, ...) live here.
set "SRC_DIR=%~dp0vcpkg_deps_from_source"
set "TRIPLET=x64-windows-release"
set "SEVENZIP_EXE=C:\Program Files\7-Zip\7z.exe"
@@ -72,52 +70,11 @@ if not exist "%FINAL_EXPORT_PATH%" (
xcopy "%CUDA_PATH%\bin\x64\cudnn*.dll" "%FINAL_EXPORT_PATH%\installed\%TRIPLET%\bin\" /Y
)
:: ZED: copy the main library + the zed-config.cmake so find_package(ZED) resolves
:: it from the export (the config derives paths from ZED_SDK_ROOT_DIR/CMAKE_PREFIX_PATH).
if "%ZED_SDK_ROOT_DIR%"=="" (
echo Error: ZED_SDK_ROOT_DIR environment variable is not set!
pause
exit /b 1
)
echo Copying ZED main library only...
:: Only the core runtime goes into the bundle; the neural-depth/TensorRT DLLs are
:: shipped separately (see the zed-neural-extra archive below).
robocopy "%ZED_SDK_ROOT_DIR%\bin" "%FINAL_EXPORT_PATH%\installed\%TRIPLET%\bin" sl_zed64.dll zlibwapi.dll /XO
robocopy "%ZED_SDK_ROOT_DIR%\lib" "%FINAL_EXPORT_PATH%\installed\%TRIPLET%\lib" /E /XO
robocopy "%ZED_SDK_ROOT_DIR%\include" "%FINAL_EXPORT_PATH%\installed\%TRIPLET%\include" /E /XO
:: Install ZED's CMake config at the export prefix root so find_package(ZED 2) (config
:: mode, via the vcpkg toolchain CMAKE_PREFIX_PATH) finds it.
robocopy "%ZED_SDK_ROOT_DIR%" "%FINAL_EXPORT_PATH%\installed\%TRIPLET%" zed-config.cmake zed-config-version.cmake /XO
:: Robocopy exit codes under 8 mean successful copies/no changes.
:: 8 or higher means there was a failure.
if !errorlevel! GEQ 8 (
echo Error: Robocopy failed with exit code !errorlevel!
pause
exit /b !errorlevel!
)
:: Archive the remaining ZED runtime DLLs (neural-depth / TensorRT extras) as a
:: separate optional download, kept out of the main bundle to keep it small. Built
:: only once: skipped if the archive already exists. Staged with robocopy /XF
:: (excludes by name; avoids 7z's "!" exclude switch that delayed expansion mangles).
set "ZED_EXTRA_7Z=%EXPORT_DIR%\%TARGET_NAME%-zed-neural-extra.7z"
set "ZED_EXTRA_DIR=%SRC_DIR%\zed-neural-extra"
if not exist "%ZED_EXTRA_7Z%" (
echo [+] Creating ZED neural extra archive...
if exist "%ZED_EXTRA_DIR%" rd /s /q "%ZED_EXTRA_DIR%"
robocopy "%ZED_SDK_ROOT_DIR%\bin" "%ZED_EXTRA_DIR%" *.dll /XF sl_zed64.dll zlibwapi.dll >nul
"%SEVENZIP_EXE%" a -t7z -mx9 "%ZED_EXTRA_7Z%" "%ZED_EXTRA_DIR%\*" || exit /b !errorlevel!
)
:: pytorch deps
%FINAL_EXPORT_PATH%/installed/%TRIPLET%/tools/python3/python.exe -m pip install numpy packaging "setuptools<82" pyyaml typing_extensions
git config --global core.longpaths true
:: All deps cloned/built below go into %SRC_DIR% (incl. libfreenect2 built by
:: bundle_windows_deps.bat) to keep the repo root clean.
if not exist "%SRC_DIR%" mkdir "%SRC_DIR%"
cd /d "%SRC_DIR%"
:: pytorch, build with local cuda libraries to avoid duplicating them when we install rtabmap
echo [+] Building pytorch with cuda support...
if not exist pytorch (
@@ -167,7 +124,6 @@ set TORCHVISION_LIBRARY=%FINAL_EXPORT_PATH%\installed\%TRIPLET%\lib
%FINAL_EXPORT_PATH%/installed/%TRIPLET%/tools/python3/python.exe -m pip install . -v --no-build-isolation || exit /b !errorlevel!
cd ..
:: opencv_cuda
echo [+] Building opencv with cuda support...
if not exist opencv (
@@ -182,7 +138,7 @@ if not exist opencv (
if not exist opencv_contrib (
echo [+] Downloading opencv_contrib...
git clone https://github.com/opencv/opencv_contrib.git || exit /b !errorlevel!
cd opencv_contrib
cd opencv
:: 4.13.0 minimum required to be compatible with cuda 13
:: Dec 31, 2025
git checkout 4.13.0
@@ -205,68 +161,19 @@ cmake -S . -B build -GNinja ^
-DBUILD_PERF_TESTS=OFF ^
-DOPENCV_ENABLE_NONFREE=ON ^
-DBUILD_opencv_apps=OFF ^
-DBUILD_opencv_cudacodec=OFF ^
-DBUILD_opencv_python3=OFF ^
-DBUILD_opencv_python_bindings_generator=OFF ^
-DBUILD_opencv_python_tests=OFF ^
-DBUILD_opencv_python3=ON ^
-DPYTHON3_EXECUTABLE=%FINAL_EXPORT_PATH%/installed/%TRIPLET%/tools/python3/python.exe ^
-DPYTHON3_PACKAGES_PATH=bin/Lib/site-packages ^
-DBUILD_opencv_java_bindings_generator=OFF ^
-DWITH_CUDA=ON ^
-DWITH_VTK=OFF ^
-DWITH_TBB=ON || exit /b !errorlevel!
cmake --build build --config Release --target install || exit /b !errorlevel!
:: move cv2 package under tools/python3
robocopy "%FINAL_EXPORT_PATH%\installed\%TRIPLET%\bin\Lib" "%FINAL_EXPORT_PATH%\installed\%TRIPLET%\tools\python3\Lib" /E /MOVE /NFL /NDL /NJH /NC /NS /NP
cd ..
:: freenect2 with cuda support
:: libfreenect2's CUDA processors include <helper_math.h>, which modern CUDA toolkits
:: no longer ship (it moved to the NVIDIA/cuda-samples repo). Fetch it and point
:: NVCUDASAMPLES_ROOT at it; libfreenect2 adds %NVCUDASAMPLES_ROOT%\common\inc to nvcc.
set "CUDA_SAMPLES_DIR=%SRC_DIR%\cuda-samples"
if not exist "%CUDA_SAMPLES_DIR%\common\inc\helper_math.h" (
mkdir "%CUDA_SAMPLES_DIR%\common\inc"
curl -L -o "%CUDA_SAMPLES_DIR%\common\inc\helper_math.h" "https://raw.githubusercontent.com/NVIDIA/cuda-samples/v12.5/Common/helper_math.h" || exit /b !errorlevel!
)
set "NVCUDASAMPLES_ROOT=%CUDA_SAMPLES_DIR%"
cd libfreenect2
cmake -S . -B build_cuda -GNinja ^
-DVCPKG_MANIFEST_INSTALL=OFF ^
-DVCPKG_TARGET_TRIPLET=x64-windows-release ^
-DVCPKG_INSTALLED_DIR="%FINAL_EXPORT_PATH%\installed" ^
-DCMAKE_TOOLCHAIN_FILE="%FINAL_EXPORT_PATH%\scripts\buildsystems\vcpkg.cmake" ^
-DPKG_CONFIG_EXECUTABLE="%FINAL_EXPORT_PATH%\installed\%TRIPLET%\tools\pkgconf\pkgconf.exe" ^
-DPKG_CONFIG_USE_CMAKE_PREFIX_PATH=ON ^
-DCMAKE_INSTALL_PREFIX="%FINAL_EXPORT_PATH%\installed\%TRIPLET%" ^
-DCMAKE_BUILD_TYPE=Release ^
-DENABLE_CUDA=ON ^
-DENABLE_OPENCL=ON ^
-DENABLE_OPENGL=ON ^
-DBUILD_EXAMPLES=OFF ^
-DBUILD_SHARED_LIBS=ON || exit /b !errorlevel!
cmake --build build_cuda --config Release --target install || exit /b !errorlevel!
cd ..
:: CudaSift (CUDA SIFT/SURF GPU features, matlabbe fork; needs CUDA)
echo [+] Building CudaSift...
if not exist CudaSift (
echo [+] Downloading...
git clone https://github.com/matlabbe/CudaSift.git
cd CudaSift
git checkout f764e14ae59ee78ff5b282d38790301d80faadc3
cd ..
)
cd CudaSift
cmake -S . -B build -GNinja ^
-DVCPKG_MANIFEST_INSTALL=OFF ^
-DVCPKG_TARGET_TRIPLET=%TRIPLET% ^
-DVCPKG_INSTALLED_DIR="%FINAL_EXPORT_PATH%\installed" ^
-DCMAKE_TOOLCHAIN_FILE="%FINAL_EXPORT_PATH%\scripts\buildsystems\vcpkg.cmake" ^
-DCMAKE_INSTALL_PREFIX="%FINAL_EXPORT_PATH%\installed\%TRIPLET%" ^
-DCMAKE_BUILD_TYPE=Release ^
-DVERBOSE=OFF ^
-DBUILD_SHARED_LIBS=ON || exit /b !errorlevel!
cmake --build build --config Release --target install || exit /b !errorlevel!
cd ..
:: 5. ZIP the folder
echo [+] Creating final package with 7-Zip...
:: Rip off pdb files
@@ -288,9 +195,8 @@ if !errorlevel! EQU 0 (
:: Example building rtabmap with opencv cuda and libtorch afterwards
goto :EndComment
:: The vcpkg export folder should not be in the rtabmap source directory
:: (otherwise we get some cmake errors about that)
set VCPKG_UNZIPPED_EXPORT_PATH=%USERPROFILE%\Downloads\vcpkg-export-########-x64-vs2022
:: Set path of unzipped deps
set VCPKG_UNZIPPED_EXPORT_PATH=
set TRIPLET=x64-windows-release
set PATH=%VCPKG_UNZIPPED_EXPORT_PATH%\installed\%TRIPLET%\bin;%PATH%
@@ -300,10 +206,15 @@ set PATH=%CUDA_PATH%\bin\x64;%PATH%
set PATH=%CUDA_PATH%\extras\CUPTI\lib64;%PATH%
set PATH=%VCPKG_UNZIPPED_EXPORT_PATH%\installed\%TRIPLET%\tools\python3\Lib\site-packages\torch\lib;%PATH%
set PATH=%VCPKG_UNZIPPED_EXPORT_PATH%\installed\%TRIPLET%\tools\python3\Lib\site-packages\numpy.libs;%PATH%
set PATH=%VCPKG_UNZIPPED_EXPORT_PATH%\installed\x64-windows-release\sdk\windows-desktop\amd64\release\bin;%PATH%
set K4A_ROOT_DIR=%VCPKG_UNZIPPED_EXPORT_PATH%\installed\%TRIPLET%
set KINECTSDK20_DIR=%VCPKG_UNZIPPED_EXPORT_PATH%\installed\%TRIPLET%
set ZED_SDK_ROOT_DIR=%VCPKG_UNZIPPED_EXPORT_PATH%\installed\%TRIPLET%
:: Other dependencies
:: For ZED, modify zed-config.cmake and remove all dependencies
set PATH=%PATH%;%ZED_SDK_ROOT_DIR%\bin
:: For kinect 4 windows SDK v2, move kinect20.dll from system32 to KINECTSDK20_DIR\bin
:: For kinect 4 windows SDK v1, move kinect10.dll and KinectAudio10.dll to KINECTSDK20_DIR\bin
set PATH=%PATH%;%KINECTSDK20_DIR%\bin
cmake -B build_cuda -GNinja ^
-DCMAKE_BUILD_TYPE=Release ^
@@ -311,16 +222,6 @@ cmake -B build_cuda -GNinja ^
-DWITH_PYTHON=ON ^
-DWITH_TORCH=ON ^
-DWITH_ZED=ON ^
-DWITH_CUDASIFT=ON ^
-DWITH_CERES=ON ^
-DWITH_ORBBEC_SDK=ON ^
-DWITH_FREENECT2=ON ^
-DWITH_K4W2=ON ^
-DWITH_K4A=ON ^
-DWITH_DEPTHAI=ON ^
-DWITH_REALSENSE2=ON ^
-DWITH_CCCORELIB=ON ^
-DWITH_PDAL=OFF ^
-DVCPKG_MANIFEST_INSTALL=OFF ^
-DVCPKG_TARGET_TRIPLET=%TRIPLET% ^
-DVCPKG_INSTALLED_DIR="%VCPKG_UNZIPPED_EXPORT_PATH%/installed" ^
+1 -7
View File
@@ -40,13 +40,7 @@ if(NOT Eigen3_FIND_VERSION)
endif()
macro(_eigen3_check_version)
# Since Eigen 5.0.0 the version macros moved from Eigen/src/Core/util/Macros.h
# to a dedicated Eigen/Version header, so check the new location first.
if(EXISTS "${EIGEN3_INCLUDE_DIR}/Eigen/Version")
file(READ "${EIGEN3_INCLUDE_DIR}/Eigen/Version" _eigen3_version_header)
else()
file(READ "${EIGEN3_INCLUDE_DIR}/Eigen/src/Core/util/Macros.h" _eigen3_version_header)
endif()
file(READ "${EIGEN3_INCLUDE_DIR}/Eigen/src/Core/util/Macros.h" _eigen3_version_header)
string(REGEX MATCH "define[ \t]+EIGEN_WORLD_VERSION[ \t]+([0-9]+)" _eigen3_world_version_match "${_eigen3_version_header}")
set(EIGEN3_WORLD_VERSION "${CMAKE_MATCH_1}")
+2 -4
View File
@@ -126,10 +126,8 @@ public:
double verticalFOV() const; // in degrees
bool isFisheye() const {return D_.cols == 6;}
// Set initRectificationMaps=false to skip building the (potentially large)
// rectification maps when rectification won't be used (saves time and memory).
bool load(const std::string & filePath, bool initRectificationMaps = true);
bool load(const std::string & directory, const std::string & cameraName, bool initRectificationMaps = true);
bool load(const std::string & filePath);
bool load(const std::string & directory, const std::string & cameraName);
bool save(const std::string & directory) const;
std::vector<unsigned char> serialize() const;
unsigned int deserialize(const std::vector<unsigned char>& data);
-8
View File
@@ -72,14 +72,6 @@ public:
const std::string & getUrl() const {return _url;}
const std::string & getTargetVersion() const {return _targetVersion;}
// Start recording changes made to the database until it is closed, then write a compact
// delta of those changes to outputUrl (empty disables). outputUrl MUST use the ".dbu"
// (db update) extension. Returns true if recording is active. Only the SQLite backend
// supports it (session extension + database version >= 0.24); other backends return false.
// NOTE: recorded changes are held in RAM until the database is closed, so only enable
// this when the expected set of changes is small.
virtual bool trackDatabaseChanges(const std::string & outputUrl) {(void)outputUrl; return false;}
void beginTransaction() const;
void commit() const;
@@ -34,7 +34,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
typedef struct sqlite3_stmt sqlite3_stmt;
typedef struct sqlite3 sqlite3;
typedef struct sqlite3_session sqlite3_session;
namespace rtabmap {
@@ -50,29 +49,6 @@ public:
void setCacheSize(unsigned int cacheSize);
void setSynchronous(int synchronous);
void setTempStore(int tempStore);
// Start recording changes made to the database from now until it is closed, then write
// a compact changeset delta to outputUrl (empty disables). outputUrl MUST use the ".dbu"
// (db update) extension. Can be called before the connection is opened or on an already-open
// connection (e.g. after init(), so the baseline is the current content). Returns true if
// recording is active. Only effective if the build/runtime SQLite has the session extension
// and the database is version >= 0.24.
// NOTE: the SQLite session extension holds ALL recorded changes in RAM until the database
// is closed (there is no incremental spill to disk), so only enable this when the expected
// set of changes is small (e.g. appending a few sessions), not for rewriting a whole map.
virtual bool trackDatabaseChanges(const std::string & outputUrl);
// Apply a ".dbu" change delta previously written by trackDatabaseChanges() onto the database
// at databasePath. The file (which must have the ".dbu" extension) is decompressed (same codec
// as the other rtabmap blobs) then applied with the SQLite session extension. With rewind=false,
// databasePath must be at the same state the delta was recorded from; with rewind=true, the
// delta is inverted first to undo it, so databasePath must be at the post-update state. Returns
// true on success; on failure returns false and, if errorMsg is not null, sets a human-readable
// message. Requires a SQLite library built with the session extension (both build and runtime).
static bool applyChangesFromFile(
const std::string & databasePath,
const std::string & changesetPath,
bool rewind = false,
std::string * errorMsg = 0);
protected:
virtual bool connectDatabaseQuery(const std::string & url, bool overwritten = false, bool readOnly = false);
@@ -221,7 +197,6 @@ private:
void loadWordIdsQuery(std::list<Signature *> & signatures) const;
void loadLinksQuery(std::list<Signature *> & signatures) const;
int loadOrSaveDb(sqlite3 *pInMemory, const std::string & fileName, int isSave) const;
void startChangeTracking(); // attach the change-tracking session on the open connection
protected:
sqlite3 * _ppDb;
@@ -234,12 +209,6 @@ private:
int _journalMode;
int _synchronous;
int _tempStore;
// DB change tracking (SQLite session extension). Members are always present to keep
// the class layout stable regardless of RTABMAP_WITH_SQLITE3_SESSION; the session is
// only created/used when the feature is compiled in and enabled.
sqlite3_session * _session;
std::string _trackChangesOutput;
};
}
-4
View File
@@ -182,10 +182,6 @@ public:
int getDatabaseMemoryUsed() const; // in bytes
std::string getDatabaseVersion() const;
std::string getDatabaseUrl() const;
// Record changes made to the database until it is closed, then write a compact delta
// to outputUrl (empty disables). outputUrl MUST use the ".dbu" (db update) extension.
// Returns true if recording started. See DBDriver.
bool trackDatabaseChanges(const std::string & outputUrl);
double getDbSavingTime() const;
int getMapId(int id, bool lookInDatabase = false) const;
Transform getOdomPose(int signatureId, bool lookInDatabase = false) const;
-8
View File
@@ -146,14 +146,6 @@ public:
Transform getPose(int locationId) const;
Transform getMapCorrection() const {return _mapCorrection;}
const Memory * getMemory() const {return _memory;}
// Record changes made to the working database from now until it is closed, then write a
// compact delta to outputUrl (empty disables). outputUrl MUST use the ".dbu" (db update)
// extension. Call after init(), so the delta reflects only what is added/modified afterwards.
// Returns true if recording started (requires the SQLite session extension and a database
// version >= 0.24). See DBDriver.
// NOTE: recorded changes are held in RAM until the database is closed, so only enable this
// when the expected set of changes is small (e.g. appending a few sessions).
bool trackDatabaseChanges(const std::string & outputUrl);
float getGoalReachedRadius() const {return _goalReachedRadius;}
float getLocalRadius() const {return _localRadius;}
const Transform & getLastLocalizationPose() const {return _lastLocalizationPose;}
+1 -1
View File
@@ -344,7 +344,7 @@ public:
void setGPS(const GPS & gps) {gps_ = gps;}
const GPS & gps() const {return gps_;}
void setIMU(const IMU & imu);
void setIMU(const IMU & imu) {imu_ = imu; }
const IMU & imu() const {return imu_;}
void setEnvSensors(const EnvSensors & sensors) {_envSensors = sensors;}
@@ -94,9 +94,7 @@ public:
// backward compatibility
void setImageSize(const cv::Size & size) {left_.setImageSize(size); right_.setImageSize(size);}
// Set initRectificationMaps=false to skip building the (potentially large) left/right
// rectification maps when rectification won't be used (saves time and memory).
bool load(const std::string & directory, const std::string & cameraName, bool ignoreStereoTransform = true, bool initRectificationMaps = true);
bool load(const std::string & directory, const std::string & cameraName, bool ignoreStereoTransform = true);
bool save(const std::string & directory, bool ignoreStereoTransform = true) const;
bool saveStereoTransform(const std::string & directory) const;
std::vector<unsigned char> serialize() const;
@@ -76,28 +76,6 @@ public:
{
_hasConfigForEachFrame = value;
}
bool isConfigForEachFrame() const {return _hasConfigForEachFrame;}
// Enable multi-camera mode. Each image in the folder is expected to be the
// horizontal concatenation of N sub-camera images of a rig, sharing the same
// base name (timestamp or node id), e.g. "1780687370.031791.jpg" or "1.jpg".
// One calibration file per sub-camera must exist in the calibrationFolder
// passed to init(), named "<prefix>_<index>.yaml" with index starting at 0
// (e.g. "1_0.yaml", "1_1.yaml", ...). The number of cameras is auto-detected.
// Each sub-image width is taken from the corresponding model's calibrated image
// size; if a model has no size, a uniform split (stackedWidth / N) is assumed.
// If setConfigForEachFrame() is enabled, one calibration set is loaded per frame
// using each image's base name as prefix. Otherwise a single calibration set is
// loaded and reused for all frames, using the cameraName passed to init() as
// prefix (it may differ from any image name), falling back to the first image's
// base name when cameraName is empty.
// Note that it is not recommended to use setConfigForEachFrame() if images have
// to be rectified, a rectification matrix would need to be re-initilaized for
// each frame.
void setMultiCameraCalibration(bool enabled)
{
_multiCameraCalib = enabled;
}
void setScanPath(
const std::string & dir,
@@ -143,22 +121,6 @@ public:
protected:
virtual SensorData captureImage(SensorCaptureInfo * info = 0);
// File name (with extension, no directory) of the image returned by the last
// captureImage() call. Used by subclasses (e.g. stereo) to key per-frame
// calibration loaded on demand. Empty if no image was read.
const std::string & lastImageFileName() const {return _lastImageFileName;}
// Calibration folder passed to init(), kept to load per-frame calibration on
// demand. Shared with subclasses (e.g. stereo) that load calibration themselves.
std::string _calibrationFolder;
// Multi-camera mode state, shared with subclasses (e.g. stereo) that layer their
// own multi-camera handling over the base reader. Such subclasses temporarily set
// _multiCameraCalib to false while delegating to base init()/captureImage() so the
// base returns the raw stacked image instead of doing its own split, then restore it.
bool _multiCameraCalib;
int _multiCameraCount; // number of sub-cameras detected in multi-camera mode
private:
bool readPoses(
std::list<Transform> & outputPoses,
@@ -167,16 +129,6 @@ private:
int format,
double maxTimeDiff) const;
// Load the sub-camera models of a multi-camera rig from calibration files named
// "<baseName>_<index>.yaml" (index 0.._multiCameraCount-1) in _calibrationFolder.
// Returns an empty vector (and logs an error) if any model is missing or invalid.
std::vector<CameraModel> loadMultiCameraModels(const std::string & baseName) const;
// Load the single-camera model for one frame from a per-frame config file (RTAB-Map
// calibration or 3DScannerApp format). Returns an invalid model (and logs an error)
// on failure.
CameraModel loadConfigModel(const std::string & filePath);
private:
std::string _path;
int _startAt;
@@ -192,7 +144,6 @@ private:
int _framesPublished;
UDirectory * _dir;
std::string _lastFileName;
std::string _lastImageFileName; // file name of the image returned by the last captureImage()
int _countScan;
UDirectory * _scanDir;
@@ -222,9 +173,7 @@ private:
std::list<cv::Mat> covariances_;
std::list<Transform> groundTruth_;
CameraModel _model;
std::list<std::string> _modelFileNames; // per-frame single-camera config file paths (config-for-each-frame)
bool _configLocalTransformWarned; // warn only once when a per-frame config has no local_transform
std::vector<CameraModel> _multiModels; // sub-camera models, shared by all frames (multi-camera mode); empty when loaded per-frame
std::list<CameraModel> _models;
UTimer _captureTimer;
double _captureDelay;
@@ -58,24 +58,6 @@ public:
void setRightGrayScale(bool enabled = true) {rightGrayScale_ = enabled;}
// Enable multi-camera stereo mode. Each left/right image in the folders is
// expected to be the horizontal concatenation of N sub-camera images of a
// stereo rig, all sharing the same base name (timestamp or node id), e.g.
// "1779318290.502227.jpg". Two calibration files per sub-camera must exist in
// the calibrationFolder passed to init(), named "<prefix>_<index>_left.yaml"
// and "<prefix>_<index>_right.yaml" with index starting at 0. The number of
// cameras is auto-detected. Sub-images are split using a uniform width
// (stackedWidth / N).
// If setConfigForEachFrame() is enabled, one calibration set is loaded per frame
// using each image's base name as prefix. Otherwise a single calibration set is
// loaded and reused for all frames, using the cameraName passed to init() as
// prefix (it may differ from any image name), falling back to the first image's
// base name when cameraName is empty.
// Note that it is not recommended to use setConfigForEachFrame() if images have
// to be rectified, a rectification matrix would need to be re-initilaized for each
// frame.
void setMultiCameraCalibration(bool enabled) {CameraImages::setMultiCameraCalibration(enabled);}
virtual bool init(const std::string & calibrationFolder = ".", const std::string & cameraName = "");
virtual bool isCalibrated() const;
virtual std::string getSerial() const;
@@ -86,17 +68,10 @@ public:
protected:
virtual SensorData captureImage(SensorCaptureInfo * info = 0);
private:
// Load the sub-camera stereo models of a frame from calibration files named
// "<baseName>_<index>_{left,right}.yaml" (index 0.._multiCameraCount-1) in
// _calibrationFolder. Returns an empty vector (and logs an error) on failure.
std::vector<StereoCameraModel> loadStereoCameraModels(const std::string & baseName, bool rectify) const;
private:
CameraImages * camera2_;
StereoCameraModel stereoModel_;
bool rightGrayScale_;
std::vector<StereoCameraModel> multiStereoModels_; // sub-camera stereo models shared by all frames (multi-camera mode); empty when loaded per-frame
};
@@ -49,8 +49,8 @@ public:
public:
CameraStereoZed(
int deviceId,
int resolution = -1, // -1 = AUTO, 0=HD4K 1=QHDPLUS 2=HD2K 3=HD1536 4=HD1080 5=HD1200 6=HD720 7=SVGA 8=VGA 9=XVGA 10=TXVGA
int quality = 1, // 0=NONE, 1=PERFORMANCE, 2=QUALITY, 3=ULTRA, 4=NEURAL_LIGHT, 5=NEURAL, 6=NEURAL_ULTRA
int resolution = -1, // -1 = AUTO, 0=HD4K 1=HD2K 2=HD1080 3=HD1200 4=HD720 5=SVGA 6=VGA
int quality = 1, // 0=NONE, 1=PERFORMANCE, 2=QUALITY
int sensingMode = 0,// 0=STANDARD, 1=FILL
int confidenceThr = 100,
bool computeOdometry = false,
@@ -61,7 +61,7 @@ public:
int texturenessConfidenceThr = 90); // introduced with ZED SDK 3
CameraStereoZed(
const std::string & svoFilePath,
int quality = 1, // 0=NONE, 1=PERFORMANCE, 2=QUALITY, 3=ULTRA, 4=NEURAL_LIGHT, 5=NEURAL, 6=NEURAL_ULTRA
int quality = 1, // 0=NONE, 1=PERFORMANCE, 2=QUALITY, 3=NEURAL
int sensingMode = 0,// 0=STANDARD, 1=FILL
int confidenceThr = 100,
bool computeOdometry = false,
@@ -81,15 +81,6 @@ public:
void postInterIMUPublic(const IMU & imu, double stamp);
void setRightGrayScale(bool enabled = true);
/**
* If the given ZED depth mode (quality: same encoding as the constructor) is a NEURAL mode
* whose AI model isn't yet downloaded/optimized for the GPU, returns a human-readable warning
* that the first start will be slower (the ZED SDK downloads/optimizes the model during
* init()). Returns an empty string when the model is ready, the mode isn't neural, or the
* SDK/build doesn't support the check.
*/
static std::string getNeuralModelWarning(int quality);
protected:
virtual SensorData captureImage(SensorCaptureInfo * info = 0);
@@ -29,25 +29,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Should be first on windows to avoid "WinSock.h has already been included" error
#include <pcl/io/vlp_grabber.h>
#include <boost/version.hpp>
#include <boost/asio.hpp>
#include <rtabmap/core/Lidar.h>
#include <rtabmap/utilite/USemaphore.h>
#include <thread>
#include <atomic>
// On Apple, closing pcl::HDLGrabber's UDP socket while its read thread is blocked
// in receive_from returns EBADF, which pcl::HDLGrabber::readPacketsFromSocket()
// rethrows uncaught in its own thread, aborting the process on shutdown. There we
// run our own single-threaded UDP receive loop and own the socket lifecycle.
// Other platforms use the base pcl::VLPGrabber path (which also avoids needing
// boost::asio::io_context, absent from the Boost 1.65 on e.g. Ubuntu Bionic).
// Comment this out to force the base path everywhere (e.g. A/B testing on macOS).
#if defined(__APPLE__)
#define RTABMAP_VLP16_USE_CUSTOM_SOCKET
#endif
namespace rtabmap {
struct PointXYZIT {
@@ -83,28 +68,9 @@ public:
void setOrganized(bool enable);
#ifdef RTABMAP_VLP16_USE_CUSTOM_SOCKET
// Overridden only on Apple: in network mode we run our own UDP receive loop
// instead of pcl::HDLGrabber's, because on macOS/BSD closing the grabber's
// socket while its read thread is blocked in receive_from returns EBADF, a
// code that pcl::HDLGrabber::readPacketsFromSocket() rethrows uncaught (in
// its own thread), aborting the process on shutdown. Owning the socket lets
// us tear it down with the non-throwing receive_from overload. Like
// pcl::HDLGrabber, we bind to the given LOCAL interface address (to scope
// reception on a multi-homed host) and fall back to all interfaces (0.0.0.0)
// when it is unspecified or not a local address. In PCAP mode we delegate to
// the base grabber. On other platforms we inherit pcl::VLPGrabber directly.
virtual void start() override;
virtual void stop() override;
virtual bool isRunning() const override;
#endif
private:
void buildTimings(bool dualMode);
virtual void toPointClouds (HDLDataPacket *dataPacket) override;
#ifdef RTABMAP_VLP16_USE_CUSTOM_SOCKET
void readPackets();
#endif
protected:
virtual SensorData captureData(SensorCaptureInfo * info = 0) override;
@@ -122,18 +88,6 @@ private:
std::vector<std::vector<PointXYZIT> > accumulatedScans_;
USemaphore scanReady_;
UMutex lastScanMutex_;
// Own UDP receive path (network mode only).
bool networkMode_;
boost::asio::ip::address ipAddress_;
std::uint16_t port_;
bool receivedScan_; // set once the first scan is received
#ifdef RTABMAP_VLP16_USE_CUSTOM_SOCKET
boost::asio::io_context ioContext_;
boost::asio::ip::udp::socket * socket_;
std::thread * readThread_;
std::atomic<bool> terminate_;
#endif
};
} /* namespace rtabmap */
+1 -46
View File
@@ -196,33 +196,6 @@ IF(SQLite3_FOUND)
${LIBRARIES}
${SQLite3_LIBRARIES}
)
# The SQLite session extension (used to track DB changes) needs a SQLite built with
# SQLITE_ENABLE_SESSION. Check if sqlite is built with it.
INCLUDE(CheckCXXSourceCompiles)
SET(CMAKE_REQUIRED_INCLUDES ${SQLite3_INCLUDE_DIRS})
SET(CMAKE_REQUIRED_LIBRARIES ${SQLite3_LIBRARIES})
SET(CMAKE_REQUIRED_DEFINITIONS -DSQLITE_ENABLE_SESSION -DSQLITE_ENABLE_PREUPDATE_HOOK)
CHECK_CXX_SOURCE_COMPILES("
#include <sqlite3.h>
int main() {
sqlite3_session * s = 0;
sqlite3session_create((sqlite3*)0, \"main\", &s);
sqlite3session_attach(s, 0);
int n = 0; void * p = 0;
sqlite3session_changeset(s, &n, &p);
sqlite3changeset_invert(n, p, &n, &p);
sqlite3session_delete(s);
return 0;
}" RTABMAP_SQLITE3_SESSION_AVAILABLE)
UNSET(CMAKE_REQUIRED_INCLUDES)
UNSET(CMAKE_REQUIRED_LIBRARIES)
UNSET(CMAKE_REQUIRED_DEFINITIONS)
IF(RTABMAP_SQLITE3_SESSION_AVAILABLE)
SET(SQLITE3_SESSION_DEFINITIONS SQLITE_ENABLE_SESSION SQLITE_ENABLE_PREUPDATE_HOOK RTABMAP_WITH_SQLITE3_SESSION)
MESSAGE(STATUS " With SQLite3 session ext = YES (system SQLite3 ${SQLite3_VERSION})")
ELSE()
MESSAGE(STATUS " With SQLite3 session ext = NO (system SQLite3 ${SQLite3_VERSION} has no session extension)")
ENDIF()
ELSE()
SET(SRC_FILES
${SRC_FILES}
@@ -232,17 +205,6 @@ ELSE()
${CMAKE_CURRENT_SOURCE_DIR}/sqlite3
${INCLUDE_DIRS}
)
FILE(READ ${CMAKE_CURRENT_SOURCE_DIR}/sqlite3/sqlite3.h RTABMAP_BUNDLED_SQLITE3_HEADER)
IF(RTABMAP_BUNDLED_SQLITE3_HEADER MATCHES "sqlite3session_create")
SET(SQLITE3_SESSION_DEFINITIONS SQLITE_ENABLE_SESSION SQLITE_ENABLE_PREUPDATE_HOOK RTABMAP_WITH_SQLITE3_SESSION)
MESSAGE(STATUS " With SQLite3 session ext = YES (bundled SQLite3)")
ELSE()
MESSAGE(FATAL_ERROR "The bundled SQLite amalgamation (corelib/src/sqlite3/sqlite3.h) does not contain "
"the session extension (sqlite3session_create not found). It must be a session-enabled "
"amalgamation, as the standard sqlite.org amalgamation does NOT include the session extension "
"by default. Please vendor a session-enabled SQLite amalgamation.")
ENDIF()
UNSET(RTABMAP_BUNDLED_SQLITE3_HEADER)
ENDIF()
IF(TORCH_FOUND)
@@ -430,6 +392,7 @@ IF(depthai_FOUND)
SET(PUBLIC_LIBRARIES
${PUBLIC_LIBRARIES}
depthai::core
depthai::opencv
)
ENDIF(depthai_FOUND)
@@ -868,7 +831,6 @@ CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/resources/DatabaseSchema.sql.in ${CMA
SET(RESOURCES
${CMAKE_CURRENT_SOURCE_DIR}/resources/DatabaseSchema.sql
${CMAKE_CURRENT_SOURCE_DIR}/resources/backward_compatibility/DatabaseSchema_0_23_0.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_18_3.sql
@@ -932,13 +894,6 @@ TARGET_LINK_LIBRARIES(rtabmap_core
PRIVATE
${LIBRARIES})
# Enable the SQLite session extension for the core sources (bundled sqlite3.c and
# DBDriverSqlite3.cpp). Kept PRIVATE so it only affects rtabmap_core's own TUs and
# never changes the public header layout for downstream consumers.
IF(SQLITE3_SESSION_DEFINITIONS)
target_compile_definitions(rtabmap_core PRIVATE ${SQLITE3_SESSION_DEFINITIONS})
ENDIF()
SET_TARGET_PROPERTIES(
rtabmap_core
PROPERTIES
+4 -4
View File
@@ -212,7 +212,7 @@ void CameraModel::setImageSize(const cv::Size & size)
}
}
bool CameraModel::load(const std::string & filePath, bool initRectificationMaps)
bool CameraModel::load(const std::string & filePath)
{
K_ = cv::Mat();
D_ = cv::Mat();
@@ -377,7 +377,7 @@ bool CameraModel::load(const std::string & filePath, bool initRectificationMaps)
fs.release();
if(initRectificationMaps && isValidForRectification())
if(isValidForRectification())
{
initRectificationMap();
}
@@ -396,9 +396,9 @@ bool CameraModel::load(const std::string & filePath, bool initRectificationMaps)
return false;
}
bool CameraModel::load(const std::string & directory, const std::string & cameraName, bool initRectificationMaps)
bool CameraModel::load(const std::string & directory, const std::string & cameraName)
{
return load(directory+"/"+cameraName+".yaml", initRectificationMaps);
return load(directory+"/"+cameraName+".yaml");
}
bool CameraModel::save(const std::string & directory) const
+1 -244
View File
@@ -34,7 +34,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "rtabmap/core/util3d.h"
#include "rtabmap/core/Compression.h"
#include "DatabaseSchema_sql.h"
#include "DatabaseSchema_0_23_0_sql.h"
#include "DatabaseSchema_0_22_0_sql.h"
#include "DatabaseSchema_0_20_0_sql.h"
#include "DatabaseSchema_0_18_3_sql.h"
@@ -46,7 +45,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <set>
#include <cstdio>
#include "rtabmap/utilite/UtiLite.h"
@@ -61,8 +59,7 @@ DBDriverSqlite3::DBDriverSqlite3(const ParametersMap & parameters) :
_cacheSize(Parameters::defaultDbSqlite3CacheSize()),
_journalMode(Parameters::defaultDbSqlite3JournalMode()),
_synchronous(Parameters::defaultDbSqlite3Synchronous()),
_tempStore(Parameters::defaultDbSqlite3TempStore()),
_session(0)
_tempStore(Parameters::defaultDbSqlite3TempStore())
{
ULOGGER_DEBUG("treadSafe=%d", sqlite3_threadsafe());
this->parseParameters(parameters);
@@ -221,185 +218,6 @@ void DBDriverSqlite3::setDbInMemory(bool dbInMemory)
}
}
void DBDriverSqlite3::startChangeTracking()
{
#ifdef RTABMAP_WITH_SQLITE3_SESSION
if(_session != 0 || _trackChangesOutput.empty() || _ppDb == 0)
{
// Already tracking, nothing requested, or not connected yet.
return;
}
if(uStrNumCmp(_version, "0.24.0") < 0)
{
UERROR("Database change tracking to \"%s\" was requested but the database "
"version is %s (< 0.24.0). Older schemas lack the primary keys required "
"by the SQLite session extension, so change tracking is disabled.",
_trackChangesOutput.c_str(), _version.c_str());
}
else if(!sqlite3_compileoption_used("ENABLE_SESSION"))
{
UERROR("Database change tracking to \"%s\" was requested but the linked SQLite "
"library was not built with the session extension (ENABLE_SESSION); "
"change tracking is disabled.", _trackChangesOutput.c_str());
}
else if(sqlite3session_create(_ppDb, "main", &_session) == SQLITE_OK)
{
sqlite3session_attach(_session, 0); // 0 = track all tables
UINFO("Tracking database changes; a changeset will be written to \"%s\" on close.",
_trackChangesOutput.c_str());
}
else
{
UERROR("Could not create a SQLite session to track database changes to \"%s\".",
_trackChangesOutput.c_str());
_session = 0;
}
#endif
}
bool DBDriverSqlite3::trackDatabaseChanges(const std::string & outputUrl)
{
UDEBUG("outputUrl=%s", outputUrl.c_str());
// The delta file must use the ".dbu" (db update) extension so it is clearly identifiable
// and can be applied/rewound with rtabmap-dbupdate.
if(!outputUrl.empty() && UFile::getExtension(outputUrl).compare("dbu") != 0)
{
UERROR("Database change tracking output \"%s\" must have a \".dbu\" (db update) extension; "
"change tracking is disabled.", outputUrl.c_str());
return false;
}
_trackChangesOutput = outputUrl;
#ifdef RTABMAP_WITH_SQLITE3_SESSION
// If the connection is already open (e.g. set after connect(), as rtabmap-reprocess
// does after init()), start tracking now on the current baseline state. Otherwise it
// will start automatically when the connection is opened.
if(!outputUrl.empty() && _ppDb != 0)
{
this->startChangeTracking();
}
return _session != 0;
#else
if(!outputUrl.empty())
{
UERROR("Database change tracking to \"%s\" was requested but rtabmap was built "
"against a SQLite library without the session extension; it is disabled.",
outputUrl.c_str());
}
return false;
#endif
}
#ifdef RTABMAP_WITH_SQLITE3_SESSION
static int rtabmapChangesetConflict(void * pCtx, int eConflict, sqlite3_changeset_iter * pIter)
{
// A patchset upgrade must apply cleanly onto the exact database it was generated from.
// Any conflict means the wrong base database (or an already-applied delta), so abort
// rather than silently produce an inconsistent result.
return SQLITE_CHANGESET_ABORT;
}
#endif
bool DBDriverSqlite3::applyChangesFromFile(
const std::string & databasePath,
const std::string & changesetPath,
bool rewind,
std::string * errorMsg)
{
if(UFile::getExtension(changesetPath).compare("dbu") != 0)
{
if(errorMsg) *errorMsg = uFormat("Update file \"%s\" must have a \".dbu\" (db update) extension.", changesetPath.c_str());
return false;
}
#ifdef RTABMAP_WITH_SQLITE3_SESSION
if(!sqlite3_compileoption_used("ENABLE_SESSION"))
{
if(errorMsg) *errorMsg = "The linked SQLite library was not built with the session extension.";
return false;
}
// Read the compressed changeset file.
FILE * fp = fopen(changesetPath.c_str(), "rb");
if(!fp)
{
if(errorMsg) *errorMsg = uFormat("Could not open changeset file \"%s\".", changesetPath.c_str());
return false;
}
fseek(fp, 0, SEEK_END);
long fileSize = ftell(fp);
fseek(fp, 0, SEEK_SET);
if(fileSize <= 0)
{
fclose(fp);
if(errorMsg) *errorMsg = uFormat("Changeset file \"%s\" is empty or unreadable.", changesetPath.c_str());
return false;
}
std::vector<unsigned char> fileBytes((size_t)fileSize);
size_t bytesRead = fread(fileBytes.data(), 1, (size_t)fileSize, fp);
fclose(fp);
if((long)bytesRead != fileSize)
{
if(errorMsg) *errorMsg = uFormat("Could not read changeset file \"%s\".", changesetPath.c_str());
return false;
}
// Decompress to the raw changeset (same codec used to write it).
cv::Mat changes = uncompressData(fileBytes.data(), (unsigned long)fileSize);
if(changes.empty())
{
if(errorMsg) *errorMsg = uFormat("Could not decompress changeset file \"%s\".", changesetPath.c_str());
return false;
}
int nChanges = (int)(changes.total()*changes.elemSize());
void * pApply = changes.data;
int nApply = nChanges;
void * pInverted = 0;
if(rewind)
{
// Invert the changeset so applying it undoes the recorded update (INSERT<->DELETE,
// UPDATE reversed). This is why the emit records a changeset, not a patchset: only
// changesets carry the old values needed to reverse a change.
int nInverted = 0;
int rcInv = sqlite3changeset_invert(nChanges, changes.data, &nInverted, &pInverted);
if(rcInv != SQLITE_OK || pInverted == 0)
{
if(errorMsg) *errorMsg = uFormat("Could not invert changeset \"%s\" for rewind (SQLite error %d: %s).",
changesetPath.c_str(), rcInv, sqlite3_errstr(rcInv));
return false;
}
pApply = pInverted;
nApply = nInverted;
}
// Apply onto the target database.
sqlite3 * db = 0;
int rc = sqlite3_open_v2(databasePath.c_str(), &db, SQLITE_OPEN_READWRITE, 0);
if(rc != SQLITE_OK)
{
if(errorMsg) *errorMsg = uFormat("Could not open database \"%s\": %s", databasePath.c_str(), sqlite3_errmsg(db));
sqlite3_close(db);
if(pInverted) sqlite3_free(pInverted);
return false;
}
rc = sqlite3changeset_apply(db, nApply, pApply, 0, rtabmapChangesetConflict, 0);
sqlite3_close(db);
if(pInverted) sqlite3_free(pInverted);
if(rc != SQLITE_OK)
{
if(errorMsg) *errorMsg = uFormat("Failed to %s \"%s\" (SQLite error %d: %s). Make sure it is applied to the "
"exact database state the delta %s.",
rewind?"rewind":"update", databasePath.c_str(), rc, sqlite3_errstr(rc),
rewind?"was previously applied to":"was recorded from");
return false;
}
return true;
#else
if(errorMsg) *errorMsg = "rtabmap was built without SQLite session support.";
return false;
#endif
}
/*
** This function is used to load the contents of a database file on disk
** into the "main" database of open database connection pInMemory, or
@@ -588,7 +406,6 @@ bool DBDriverSqlite3::connectDatabaseQuery(const std::string & url, bool overwri
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.22.0", DATABASESCHEMA_0_22_0_SQL));
schemas.push_back(std::make_pair("0.23.0", DATABASESCHEMA_0_23_0_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)
{
@@ -629,14 +446,6 @@ bool DBDriverSqlite3::connectDatabaseQuery(const std::string & url, bool overwri
this->setSynchronous(_synchronous); // this will call the SQL
this->setTempStore(_tempStore); // this will call the SQL
// Start tracking database changes if a recording path was already set (before the
// connection was opened). Done here, after any initial load and once the version is
// known, so the delta reflects only the changes made between open and close.
if(!readOnly)
{
this->startChangeTracking();
}
return true;
}
void DBDriverSqlite3::disconnectDatabaseQuery(bool save, const std::string & outputUrl)
@@ -680,58 +489,6 @@ void DBDriverSqlite3::disconnectDatabaseQuery(bool save, const std::string & out
}
}
#ifdef RTABMAP_WITH_SQLITE3_SESSION
// If change tracking is active, emit the accumulated changeset before closing.
// A changeset (not a patchset) is used so it carries the old values too and can be
// inverted with sqlite3changeset_invert() to undo the update (see applyChangesFromFile).
if(_session)
{
int nBuf = 0;
void * pBuf = 0;
int rcp = sqlite3session_changeset(_session, &nBuf, &pBuf);
if(rcp == SQLITE_OK && pBuf && nBuf > 0)
{
// Compress the changeset with the same zlib-based codec used for every other
// rtabmap blob, so the delta is compact for transfer. To apply it later,
// uncompressData() the file and pass the bytes to sqlite3changeset_apply().
cv::Mat compressed = compressData2(cv::Mat(1, nBuf, CV_8UC1, pBuf));
FILE * fp = fopen(_trackChangesOutput.c_str(), "wb");
if(fp)
{
size_t toWrite = compressed.total()*compressed.elemSize();
size_t written = fwrite(compressed.data, 1, toWrite, fp);
fclose(fp);
if(written == toWrite)
{
UINFO("Wrote compressed database changeset (%d -> %d bytes) to \"%s\".",
nBuf, (int)toWrite, _trackChangesOutput.c_str());
}
else
{
UERROR("Could only write %d/%d bytes of the database changeset to \"%s\".",
(int)written, (int)toWrite, _trackChangesOutput.c_str());
}
}
else
{
UERROR("Could not open \"%s\" to write the database changeset.", _trackChangesOutput.c_str());
}
}
else if(rcp != SQLITE_OK)
{
UERROR("Could not generate the database changeset for \"%s\" (SQLite error %d).",
_trackChangesOutput.c_str(), rcp);
}
else
{
UINFO("No database changes to write; \"%s\" was not created.", _trackChangesOutput.c_str());
}
sqlite3_free(pBuf);
sqlite3session_delete(_session);
_session = 0;
}
#endif
// Then close (delete) the database connection
UINFO("Disconnecting database %s...", this->getUrl().c_str());
sqlite3_close(_ppDb);
-5
View File
@@ -1994,11 +1994,6 @@ double Memory::getDbSavingTime() const
return _dbDriver?_dbDriver->getEmptyTrashesTime():0;
}
bool Memory::trackDatabaseChanges(const std::string & outputUrl)
{
return _dbDriver?_dbDriver->trackDatabaseChanges(outputUrl):false;
}
std::set<int> Memory::getAllSignatureIds(bool ignoreChildren) const
{
std::set<int> ids;
+1 -6
View File
@@ -1247,12 +1247,7 @@ void readINIImpl(const CSimpleIniA & ini, const std::string & configFilePath, Pa
{
if(RTABMAP_VERSION_COMPARE(<, std::atoi(version[0].c_str()), std::atoi(version[1].c_str()), std::atoi(version[2].c_str())))
{
// Detect the user's private config - matches both the legacy
// ~/.rtabmap/rtabmap.ini and the Windows %LOCALAPPDATA%/rtabmap/rtabmap.ini
// (".rtabmap/rtabmap.ini" also contains "rtabmap/rtabmap.ini"): downgrade-on-save is fine there.
// Accept both forward and backward slashes (native Windows paths).
if(configFilePath.find("rtabmap/rtabmap.ini") != std::string::npos ||
configFilePath.find("rtabmap\\rtabmap.ini") != std::string::npos)
if(configFilePath.find(".rtabmap") != std::string::npos)
{
UWARN("Version in the config file \"%s\" is more recent (\"%s\") than "
"current RTAB-Map version used (\"%s\"). The config file will be downgraded "
-5
View File
@@ -885,11 +885,6 @@ Transform Rtabmap::getPose(int locationId) const
return uValue(_optimizedPoses, locationId, Transform());
}
bool Rtabmap::trackDatabaseChanges(const std::string & outputUrl)
{
return _memory?_memory->trackDatabaseChanges(outputUrl):false;
}
void Rtabmap::setInitialPose(const Transform & initialPose)
{
if(_memory)
+13 -28
View File
@@ -114,6 +114,7 @@ SensorCaptureThread::SensorCaptureThread(
_camera(camera),
_odomSensor(odomSensor),
_lidar(lidar),
_extrinsicsOdomToCamera(extrinsics * CameraModel::opticalRotation()),
_odomAsGt(false),
_poseTimeOffset(poseTimeOffset),
_poseScaleFactor(poseScaleFactor),
@@ -152,14 +153,10 @@ SensorCaptureThread::SensorCaptureThread(
{
if(_camera)
{
if(_odomSensor == _camera && extrinsics.isNull())
if(_odomSensor == _camera && _extrinsicsOdomToCamera.isNull())
{
_extrinsicsOdomToCamera.setIdentity();
}
else
{
_extrinsicsOdomToCamera = extrinsics * CameraModel::opticalRotation();
}
UASSERT(!_extrinsicsOdomToCamera.isNull());
UDEBUG("_extrinsicsOdomToCamera=%s", _extrinsicsOdomToCamera.prettyPrint().c_str());
}
@@ -495,26 +492,20 @@ void SensorCaptureThread::mainLoop()
}
}
// Adjust local transform of the camera(s) based on the pose frame. The correction
// and odom->camera extrinsics are frame-level, so apply the same prefix to each
// camera while keeping its own local transform (multi-camera supported).
// Adjust local transform of the camera based on the pose frame
if(!data.cameraModels().empty())
{
std::vector<CameraModel> models = data.cameraModels();
for(size_t i=0; i<models.size(); ++i)
{
models[i].setLocalTransform(cameraCorrection*_extrinsicsOdomToCamera*models[i].localTransform());
}
data.setCameraModels(models);
UASSERT(data.cameraModels().size()==1);
CameraModel model = data.cameraModels()[0];
model.setLocalTransform(cameraCorrection*_extrinsicsOdomToCamera);
data.setCameraModel(model);
}
else if(!data.stereoCameraModels().empty())
{
std::vector<StereoCameraModel> models = data.stereoCameraModels();
for(size_t i=0; i<models.size(); ++i)
{
models[i].setLocalTransform(cameraCorrection*_extrinsicsOdomToCamera*models[i].localTransform());
}
data.setStereoCameraModels(models);
UASSERT(data.stereoCameraModels().size()==1);
StereoCameraModel model = data.stereoCameraModels()[0];
model.setLocalTransform(cameraCorrection*_extrinsicsOdomToCamera);
data.setStereoCameraModel(model);
}
}
@@ -539,21 +530,15 @@ void SensorCaptureThread::mainLoop()
info.odomPose.setNull();
}
if(this->isKilled())
{
// A kill was requested (e.g. while we were blocked capturing this frame): don't
// publish anything so we never deliver events to handlers that are being torn down.
}
else if(!data.imageCompressed().empty() || !data.imageRaw().empty() || !data.laserScanRaw().empty() || (dynamic_cast<DBReader*>(_camera) != 0 && data.id()>0)) // intermediate nodes could not have image set
if(!data.imageCompressed().empty() || !data.imageRaw().empty() || !data.laserScanRaw().empty() || (dynamic_cast<DBReader*>(_camera) != 0 && data.id()>0)) // intermediate nodes could not have image set
{
postUpdate(&data, &info);
info.cameraName = _lidar?_lidar->getSerial():_camera->getSerial();
info.timeTotal = totalTime.ticks();
this->post(new SensorEvent(data, info));
}
else
else if(!this->isKilled())
{
// Not killed but no data: end of stream. Signal consumers once, then stop.
UWARN("no more data...");
this->kill();
this->post(new SensorEvent());
-16
View File
@@ -952,22 +952,6 @@ void SensorData::setFeatures(const std::vector<cv::KeyPoint> & keypoints, const
_descriptors = descriptors;
}
void SensorData::setIMU(const IMU & imu)
{
UASSERT(
uIsFinite(imu.orientation()[0]) &&
uIsFinite(imu.orientation()[1]) &&
uIsFinite(imu.orientation()[2]) &&
uIsFinite(imu.orientation()[3]) &&
uIsFinite(imu.angularVelocity()[0]) &&
uIsFinite(imu.angularVelocity()[1]) &&
uIsFinite(imu.angularVelocity()[2]) &&
uIsFinite(imu.linearAcceleration()[0]) &&
uIsFinite(imu.linearAcceleration()[1]) &&
uIsFinite(imu.linearAcceleration()[2]));
imu_ = imu;
}
unsigned long SensorData::getMemoryUsed() const // Return memory usage in Bytes
{
return sizeof(SensorData) +
+3 -3
View File
@@ -220,11 +220,11 @@ void StereoCameraModel::updateStereoRectification()
right_ = CameraModel(right_.name(), right_.imageSize(), right_.K_raw(), right_.D_raw(), R2, P2, right_.localTransform());
}
bool StereoCameraModel::load(const std::string & directory, const std::string & cameraName, bool ignoreStereoTransform, bool initRectificationMaps)
bool StereoCameraModel::load(const std::string & directory, const std::string & cameraName, bool ignoreStereoTransform)
{
name_ = cameraName;
bool leftLoaded = left_.load(directory, cameraName+"_"+getLeftSuffix(), initRectificationMaps);
bool rightLoaded = right_.load(directory, cameraName+"_"+getRightSuffix(), initRectificationMaps);
bool leftLoaded = left_.load(directory, cameraName+"_"+getLeftSuffix());
bool rightLoaded = right_.load(directory, cameraName+"_"+getRightSuffix());
if(leftLoaded && rightLoaded)
{
if(ignoreStereoTransform)
+1 -16
View File
@@ -729,21 +729,6 @@ std::string CameraDepthAI::getSerial() const
return "";
}
#ifdef RTABMAP_DEPTHAI
namespace {
// Convert the depthai depth ImgFrame to cv::Mat (similar to dai::ImgFrame::getCvFrame())
cv::Mat depthImgFrameToCvMat(const std::shared_ptr<dai::ImgFrame> & frame)
{
if(frame->getType() != dai::ImgFrame::Type::RAW16)
{
UERROR("Expected RAW16 depth ImgFrame but got type %d", (int)frame->getType());
return cv::Mat();
}
return cv::Mat((int)frame->getHeight(), (int)frame->getWidth(), CV_16UC1, frame->getData().data()).clone();
}
}
#endif
SensorData CameraDepthAI::captureImage(SensorCaptureInfo * info)
{
SensorData data;
@@ -755,7 +740,7 @@ SensorData CameraDepthAI::captureImage(SensorCaptureInfo * info)
double stamp = std::chrono::duration<double>(depthOrRight->getTimestampDevice(dai::CameraExposureOffset::MIDDLE).time_since_epoch()).count();
if(outputMode_)
data = SensorData(cv::imdecode(rgbOrLeft->getData(), cv::IMREAD_ANYCOLOR), depthImgFrameToCvMat(depthOrRight), stereoModel_.left(), this->getNextSeqID(), stamp);
data = SensorData(cv::imdecode(rgbOrLeft->getData(), cv::IMREAD_ANYCOLOR), depthOrRight->getCvFrame(), stereoModel_.left(), this->getNextSeqID(), stamp);
else
data = SensorData(cv::imdecode(rgbOrLeft->getData(), cv::IMREAD_GRAYSCALE), cv::imdecode(depthOrRight->getData(), cv::IMREAD_GRAYSCALE), stereoModel_, this->getNextSeqID(), stamp);
+122 -366
View File
@@ -41,8 +41,6 @@ namespace rtabmap
{
CameraImages::CameraImages() :
_multiCameraCalib(false),
_multiCameraCount(0),
_startAt(0),
_maxFrames(0),
_refreshDir(false),
@@ -73,8 +71,6 @@ CameraImages::CameraImages(const std::string & path,
float imageRate,
const Transform & localTransform) :
Camera(imageRate, localTransform),
_multiCameraCalib(false),
_multiCameraCount(0),
_path(path),
_startAt(0),
_maxFrames(0),
@@ -115,22 +111,14 @@ CameraImages::~CameraImages()
bool CameraImages::init(const std::string & calibrationFolder, const std::string & cameraName)
{
_lastFileName.clear();
_lastImageFileName.clear();
_lastScanFileName.clear();
_count = 0;
_countScan = 0;
_captureDelay = 0.0;
_framesPublished=0;
_model = cameraModel();
_modelFileNames.clear();
_configLocalTransformWarned = false;
_multiModels.clear();
_calibrationFolder.clear();
_multiCameraCount = 0;
_models.clear();
covariances_.clear();
_stamps.clear();
odometry_.clear();
groundTruth_.clear();
UDEBUG("");
if(_dir)
@@ -211,117 +199,107 @@ bool CameraImages::init(const std::string & calibrationFolder, const std::string
return false;
}
bool success = _dir|| _scanDir;
if(_dir)
{
if(_multiCameraCalib)
// look for calibration files
UINFO("calibration folder=%s name=%s", calibrationFolder.c_str(), cameraName.c_str());
if(!calibrationFolder.empty() && !cameraName.empty())
{
// Multi-camera mode: each image is a horizontal stack of N sub-camera
// images. Load one CameraModel per sub-camera from calibration files
// named "<prefix>_<index>.yaml" (index starting at 0). In config-for-each-frame
// mode the prefix is each image's base name (one calibration set per frame);
// otherwise a single calibration set is shared by all frames, using cameraName
// as the prefix when provided (it may differ from any image name), falling back
// to the first image's base name.
if(calibrationFolder.empty())
if(!_model.load(calibrationFolder, cameraName))
{
UERROR("Multi-camera calibration is enabled but no calibration folder was provided.");
return false;
}
const std::list<std::string> & imageFiles = _dir->getFileNames();
std::string firstBase = imageFiles.front().substr(0, imageFiles.front().find_last_of('.'));
// In config-for-each-frame mode the prefix is each image's base name. Otherwise
// the shared prefix is cameraName when provided. cameraName may point to a specific
// sub-camera calibration "<rig>_<index>" (e.g. when a single calibration file is
// selected); in that case strip the trailing "_<index>" to recover the rig prefix
// shared by all sub-cameras. Fall back to the first image's base name if empty.
std::string sharedBase = cameraName;
if(!sharedBase.empty() && !UFile::exists(calibrationFolder + "/" + sharedBase + "_0.yaml"))
{
std::size_t us = sharedBase.find_last_of('_');
if(us != std::string::npos && us+1 < sharedBase.size() &&
sharedBase.find_first_not_of("0123456789", us+1) == std::string::npos &&
UFile::exists(calibrationFolder + "/" + sharedBase.substr(0, us) + "_0.yaml"))
{
sharedBase = sharedBase.substr(0, us);
}
}
if(sharedBase.empty())
{
sharedBase = firstBase;
}
// auto-detect the number of cameras
int numCameras = 0;
std::string detectBase = _hasConfigForEachFrame ? firstBase : sharedBase;
while(UFile::exists(calibrationFolder + "/" + detectBase + "_" + uNumber2Str(numCameras) + ".yaml"))
{
++numCameras;
}
if(numCameras == 0)
{
UERROR("Multi-camera calibration is enabled but no calibration file matching "
"\"%s/%s_<index>.yaml\" was found.",
calibrationFolder.c_str(), detectBase.c_str());
return false;
}
UINFO("Multi-camera mode: %d sub-cameras detected from \"%s\" (%s).", numCameras, calibrationFolder.c_str(),
_hasConfigForEachFrame?"one calibration per frame, loaded on demand":
uFormat("calibration \"%s_<index>\" reused for all frames", sharedBase.c_str()).c_str());
_calibrationFolder = calibrationFolder;
_multiCameraCount = numCameras;
if(_hasConfigForEachFrame)
{
// Validate the first frame now; the per-frame sub-camera models are loaded
// on demand in captureImage() (keyed by each image's base name) so we don't
// keep every frame's models - and their rectification maps - in memory.
if(loadMultiCameraModels(firstBase).empty())
{
return false;
}
UWARN("Missing calibration files for camera \"%s\" in \"%s\" folder, you should calibrate the camera!",
cameraName.c_str(), calibrationFolder.c_str());
}
else
{
// A single calibration set is shared by all frames: load it once.
std::vector<CameraModel> models = loadMultiCameraModels(sharedBase);
if(models.empty())
UINFO("Camera parameters: fx=%f fy=%f cx=%f cy=%f",
_model.fx(),
_model.fy(),
_model.cx(),
_model.cy());
cv::FileStorage fs(calibrationFolder+"/"+cameraName+".yaml", 0);
cv::FileNode poseNode = fs["local_transform"];
if(!poseNode.isNone())
{
return false;
UWARN("Using local transform from calibration file (%s) instead of the parameter one (%s).",
_model.localTransform().prettyPrint().c_str(),
this->getLocalTransform().prettyPrint().c_str());
this->setLocalTransform(_model.localTransform());
}
_multiModels = models;
}
}
else if(_hasConfigForEachFrame)
_model.setName(cameraName);
_model.setLocalTransform(this->getLocalTransform());
if(_rectifyImages && !_model.isValidForRectification())
{
UERROR("Parameter \"rectifyImages\" is set, but no camera model is loaded or valid.");
return false;
}
}
bool success = _dir|| _scanDir;
_stamps.clear();
odometry_.clear();
groundTruth_.clear();
if(success)
{
if(_dir && _hasConfigForEachFrame)
{
// Per-frame calibration: one config file per image, taken from the
// calibration folder (same convention as the single/multi-camera cases).
// If the config files are in the same folder than the images, just set the
// calibration folder to the images folder.
#if CV_MAJOR_VERSION < 3 || (CV_MAJOR_VERSION == 3 && CV_MAJOR_VERSION < 2)
UDirectory dirJson(calibrationFolder, "yaml xml");
UDirectory dirJson(_path, "yaml xml");
#else
UDirectory dirJson(calibrationFolder, "yaml xml json");
UDirectory dirJson(_path, "yaml xml json");
#endif
if(dirJson.getFileNames().size() == _dir->getFileNames().size())
{
// The per-frame models are loaded on demand in captureImage() (see
// loadConfigModel) so we don't keep every frame's model - and its
// rectification map - in memory. Only the stamps and poses of the
// 3DScannerApp format are read eagerly here (needed for synchronization).
bool modelsWarned = false;
bool localTWarned = false;
for(std::list<std::string>::const_iterator iter=dirJson.getFileNames().begin(); iter!=dirJson.getFileNames().end() && success; ++iter)
{
std::string filePath = calibrationFolder+"/"+*iter;
std::string filePath = _path+"/"+*iter;
cv::FileStorage fs(filePath, 0);
cv::FileNode poseNode = fs["cameraPoseARFrame"]; // Check if it is 3DScannerApp(iOS) format
if(!poseNode.isNone())
if(poseNode.isNone())
{
cv::FileNode n = fs["local_transform"];
bool hasLocalTransform = !n.isNone();
fs.release();
if(_model.isValidForProjection() && !modelsWarned)
{
UWARN("Camera model loaded for each frame is overridden by "
"general calibration file provided. Remove general calibration "
"file to use camera model of each frame. This warning will "
"be shown only one time.");
modelsWarned = true;
}
else
{
CameraModel model;
model.load(filePath);
if(!hasLocalTransform)
{
if(!localTWarned)
{
UWARN("Loaded calibration file doesn't have local_transform field, "
"the global local_transform parameter is used by default (%s).",
this->getLocalTransform().prettyPrint().c_str());
localTWarned = true;
}
model.setLocalTransform(this->getLocalTransform());
}
_models.push_back(model);
}
}
else
{
cv::FileNode timeNode = fs["time"];
cv::FileNode intrinsicsNode = fs["intrinsics"];
if(poseNode.size() != 16)
if(poseNode.isNone() || poseNode.size() != 16)
{
UERROR("Failed reading \"cameraPoseARFrame\" parameter, it should have 16 values (file=%s)", filePath.c_str());
success = false;
@@ -342,6 +320,23 @@ bool CameraImages::init(const std::string & calibrationFolder, const std::string
else
{
_stamps.push_back((double)timeNode);
if(_model.isValidForProjection() && !modelsWarned)
{
UWARN("Camera model loaded for each frame is overridden by "
"general calibration file provided. Remove general calibration "
"file to use camera model of each frame. This warning will "
"be shown only one time.");
modelsWarned = true;
}
else
{
_models.push_back(CameraModel(
(double)intrinsicsNode[0], //fx
(double)intrinsicsNode[4], //fy
(double)intrinsicsNode[2], //cx
(double)intrinsicsNode[5], //cy
CameraModel::opticalRotation()));
}
// we need to rotate from opengl world to rtabmap world
Transform pose(
(float)poseNode[0], (float)poseNode[1], (float)poseNode[2], (float)poseNode[3],
@@ -351,18 +346,12 @@ bool CameraImages::init(const std::string & calibrationFolder, const std::string
odometry_.push_back(pose);
}
}
_modelFileNames.push_back(filePath);
}
// Validate the first frame's calibration now to fail early.
if(success && !_modelFileNames.empty() && !loadConfigModel(_modelFileNames.front()).isValidForProjection())
{
success = false;
}
if(!success)
{
odometry_.clear();
_stamps.clear();
_modelFileNames.clear();
_models.clear();
}
}
else
@@ -376,60 +365,12 @@ bool CameraImages::init(const std::string & calibrationFolder, const std::string
"of images (%d) in this directory \"%s\".%s",
(int)dirJson.getFileNames().size(),
(int)_dir->getFileNames().size(),
calibrationFolder.c_str(),
_path.c_str(),
opencv32warn.c_str());
success = false;
}
}
else
{
// Config-for-each-frame is disabled: load a single general calibration
// model (the per-frame branch above handles the config-for-each-frame case).
// look for calibration files
UINFO("calibration folder=%s name=%s", calibrationFolder.c_str(), cameraName.c_str());
if(!calibrationFolder.empty() && !cameraName.empty())
{
if(!_model.load(calibrationFolder, cameraName, _rectifyImages))
{
UWARN("Missing calibration files for camera \"%s\" in \"%s\" folder, you should calibrate the camera!",
cameraName.c_str(), calibrationFolder.c_str());
}
else
{
UINFO("Camera parameters: fx=%f fy=%f cx=%f cy=%f",
_model.fx(),
_model.fy(),
_model.cx(),
_model.cy());
cv::FileStorage fs(calibrationFolder+"/"+cameraName+".yaml", 0);
cv::FileNode poseNode = fs["local_transform"];
if(!poseNode.isNone())
{
UWARN("Using local transform from calibration file (%s) instead of the parameter one (%s).",
_model.localTransform().prettyPrint().c_str(),
this->getLocalTransform().prettyPrint().c_str());
this->setLocalTransform(_model.localTransform());
}
}
// Only validate rectification when a general calibration was requested.
// Without it (e.g. images that are already rectified) the single model is
// expected to be empty and must not fail init here.
if(_rectifyImages && !_model.isValidForRectification())
{
UERROR("Parameter \"rectifyImages\" is set, but no camera model is loaded or valid.");
return false;
}
}
_model.setName(cameraName);
_model.setLocalTransform(this->getLocalTransform());
}
}
if(success)
{
if(_stamps.empty())
{
if(_filenamesAreTimestamps)
@@ -712,97 +653,10 @@ bool CameraImages::readPoses(
bool CameraImages::isCalibrated() const
{
return (_dir && (_model.isValidForProjection() ||
_modelFileNames.size() || // per-frame single-camera models loaded on demand (validated in init)
(!_multiModels.empty() && _multiModels.front().isValidForProjection()) ||
(_multiCameraCalib && _hasConfigForEachFrame && _multiCameraCount > 0))) || // per-frame multi-camera models loaded on demand
return (_dir && (_model.isValidForProjection() || (_models.size() && _models.front().isValidForProjection()))) ||
_scanDir;
}
std::vector<CameraModel> CameraImages::loadMultiCameraModels(const std::string & baseName) const
{
std::vector<CameraModel> models(_multiCameraCount);
for(int i=0; i<_multiCameraCount; ++i)
{
std::string name = baseName + "_" + uNumber2Str(i);
if(!models[i].load(_calibrationFolder, name, _rectifyImages) || !models[i].isValidForProjection())
{
UERROR("Failed to load a valid calibration \"%s/%s.yaml\" for multi-camera frame base \"%s\".",
_calibrationFolder.c_str(), name.c_str(), baseName.c_str());
return std::vector<CameraModel>();
}
if(models[i].localTransform().isNull())
{
// In multi-camera mode the rig extrinsics are required: each
// sub-camera calibration must provide a "local_transform".
UERROR("Calibration \"%s/%s.yaml\" has no \"local_transform\"; it is "
"required in multi-camera mode (rig extrinsics).",
_calibrationFolder.c_str(), name.c_str());
return std::vector<CameraModel>();
}
if(_rectifyImages && !models[i].isValidForRectification())
{
UERROR("Parameter \"rectifyImages\" is set, but calibration \"%s/%s.yaml\" is not valid for rectification.",
_calibrationFolder.c_str(), name.c_str());
return std::vector<CameraModel>();
}
}
return models;
}
CameraModel CameraImages::loadConfigModel(const std::string & filePath)
{
cv::FileStorage fs(filePath, 0);
cv::FileNode poseNode = fs["cameraPoseARFrame"]; // Check if it is 3DScannerApp(iOS) format
CameraModel model;
if(poseNode.isNone())
{
// RTAB-Map calibration format
bool hasLocalTransform = !fs["local_transform"].isNone();
fs.release();
model.load(filePath, _rectifyImages);
if(!hasLocalTransform)
{
if(!_configLocalTransformWarned)
{
UWARN("Loaded calibration file doesn't have local_transform field, "
"the global local_transform parameter is used by default (%s).",
this->getLocalTransform().prettyPrint().c_str());
_configLocalTransformWarned = true;
}
model.setLocalTransform(this->getLocalTransform());
}
}
else
{
// 3DScannerApp(iOS) format
cv::FileNode intrinsicsNode = fs["intrinsics"];
if(intrinsicsNode.isNone() || intrinsicsNode.size()!=9)
{
UERROR("Failed reading \"intrinsics\" parameter (file=%s)", filePath.c_str());
return CameraModel();
}
model = CameraModel(
(double)intrinsicsNode[0], //fx
(double)intrinsicsNode[4], //fy
(double)intrinsicsNode[2], //cx
(double)intrinsicsNode[5], //cy
CameraModel::opticalRotation());
}
if(!model.isValidForProjection())
{
UERROR("Camera model loaded from \"%s\" is not valid for projection.", filePath.c_str());
return CameraModel();
}
if(_rectifyImages && !model.isValidForRectification())
{
UERROR("Parameter \"rectifyImages\" is set, but camera model loaded from \"%s\" is not valid for rectification.",
filePath.c_str());
return CameraModel();
}
return model;
}
std::string CameraImages::getSerial() const
{
return _model.name();
@@ -874,13 +728,7 @@ SensorData CameraImages::captureImage(SensorCaptureInfo * info)
cv::Mat covariance;
Transform groundTruthPose;
cv::Mat depthFromScan;
std::vector<CameraModel> models; // one entry per camera (single entry in single-camera mode)
if(!_multiCameraCalib)
{
// Single-camera mode keeps exactly one model in the vector; in multi-camera
// mode the per-frame vector is taken from _multiModels below.
models.push_back(_model);
}
CameraModel model = _model;
UDEBUG("");
if(_dir || _scanDir)
{
@@ -936,8 +784,7 @@ SensorData CameraImages::captureImage(SensorCaptureInfo * info)
{
UERROR("groundTruth cannot be used when startAt < 0");
}
if(_modelFileNames.size() || !_multiModels.empty() ||
(_multiCameraCalib && _hasConfigForEachFrame))
if(_models.size() && !model.isValidForProjection())
{
UERROR("models cannot be used when startAt < 0");
}
@@ -979,24 +826,12 @@ SensorData CameraImages::captureImage(SensorCaptureInfo * info)
groundTruthPose = groundTruth_.front();
groundTruth_.pop_front();
}
if(_modelFileNames.size())
if(_models.size() && !model.isValidForProjection())
{
UASSERT_MSG(stampsSize==0 || stampsSize == _modelFileNames.size(),
uFormat("Stamps=%ld models=%ld", _stamps.size(), _modelFileNames.size()).c_str());
// per-frame calibration loaded on demand (not kept in memory)
models.back() = loadConfigModel(_modelFileNames.front());
_modelFileNames.pop_front();
}
if(_multiCameraCalib && _hasConfigForEachFrame)
{
// Per-frame calibration loaded on demand (not kept in memory),
// keyed by the current image's base name.
models = loadMultiCameraModels(imageFileName.substr(0, imageFileName.find_last_of('.')));
}
else if(!_multiModels.empty())
{
// calibration is shared across all frames
models = _multiModels;
UASSERT_MSG(stampsSize==0 || stampsSize == _models.size(),
uFormat("Stamps=%ld models=%ld", _stamps.size(), _models.size()).c_str());
model = _models.front();
_models.pop_front();
}
while(_count++ < _startAt)
@@ -1040,27 +875,14 @@ SensorData CameraImages::captureImage(SensorCaptureInfo * info)
groundTruthPose = groundTruth_.front();
groundTruth_.pop_front();
}
if(_modelFileNames.size())
if(_models.size() && !model.isValidForProjection())
{
UASSERT_MSG(stampsSize==0 || stampsSize == _modelFileNames.size(),
uFormat("Stamps=%ld models=%ld", _stamps.size(), _modelFileNames.size()).c_str());
// per-frame calibration loaded on demand (not kept in memory)
models.back() = loadConfigModel(_modelFileNames.front());
_modelFileNames.pop_front();
}
if(_multiCameraCalib && _hasConfigForEachFrame)
{
// Per-frame calibration loaded on demand (not kept in memory),
// keyed by the current image's base name.
models = loadMultiCameraModels(imageFileName.substr(0, imageFileName.find_last_of('.')));
}
else if(!_multiModels.empty())
{
// calibration is shared across all frames
models = _multiModels;
UASSERT_MSG(stampsSize==0 || stampsSize == _models.size(),
uFormat("Stamps=%ld models=%ld", _stamps.size(), _models.size()).c_str());
model = _models.front();
_models.pop_front();
}
}
_lastImageFileName = imageFileName; // expose the current frame name to subclasses
}
}
@@ -1129,67 +951,9 @@ SensorData CameraImages::captureImage(SensorCaptureInfo * info)
}
}
if(!img.empty() && !models.empty())
if(!img.empty() && model.isValidForRectification() && _rectifyImages)
{
// The image is a horizontal stack of N sub-images (N==1 in
// single-camera mode). Each sub-camera's width comes from its
// calibrated image size; if a model has no size (==0), assume a
// uniform split (stackedWidth / N) and set it. If requested, each
// sub-image is rectified independently with its model and written
// into a new stacked image of the same layout.
cv::Mat rectified;
int offset = 0;
bool rectifyAborted = false;
for(size_t i=0; i<models.size(); ++i)
{
if(models[i].imageWidth()==0 || models[i].imageHeight()==0)
{
models[i].setImageSize(cv::Size(img.cols/(int)models.size(), img.rows));
}
int subWidth = models[i].imageWidth();
if(offset+subWidth > img.cols)
{
UERROR("Multi-camera: sum of sub-image widths (%d) exceeds the stacked "
"image width (%d) at camera %d.", offset+subWidth, img.cols, (int)i);
rectified = cv::Mat();
rectifyAborted = true;
break;
}
if(_rectifyImages)
{
if(!models[i].isValidForRectification())
{
// In multi-camera mode a valid calibration is expected for each
// sub-camera. In single-camera mode this is a passthrough (e.g. the
// base reader of a stereo/RGBD subclass that rectifies itself, or
// images that are already rectified): skip silently to keep the
// backward-compatible behavior.
if(_multiCameraCalib)
{
UERROR("Parameter \"rectifyImages\" is set, but camera model %d is not valid for rectification.", (int)i);
}
rectified = cv::Mat();
rectifyAborted = true;
break;
}
if(rectified.empty())
{
rectified = cv::Mat::zeros(img.rows, img.cols, img.type());
}
cv::Rect roi(offset, 0, subWidth, img.rows);
models[i].rectifyImage(img(roi)).copyTo(rectified(roi));
}
offset += subWidth;
}
if(!rectifyAborted && offset != img.cols)
{
UWARN("Multi-camera: sum of sub-image widths (%d) does not match the "
"stacked image width (%d).", offset, img.cols);
}
if(!rectified.empty())
{
img = rectified;
}
img = model.rectifyImage(img);
}
}
@@ -1202,7 +966,7 @@ SensorData CameraImages::captureImage(SensorCaptureInfo * info)
if(_depthFromScan && !img.empty())
{
UDEBUG("Computing depth from scan...");
if(models.empty() || !models.front().isValidForProjection())
if(!model.isValidForProjection())
{
UWARN("Depth from laser scan: Camera model should be valid.");
}
@@ -1213,23 +977,10 @@ SensorData CameraImages::captureImage(SensorCaptureInfo * info)
else
{
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud = util3d::laserScanToPointCloud(scan, scan.localTransform());
// There is no multi-camera version of projectCloudToCamera(): project
// the scan into each (sub-)camera and stack the registered depth images
// horizontally, matching the RGB layout (single iteration in single-camera
// mode). Sub-image widths come from each model's (already set) image size.
// Holes are filled per sub-image so they don't bleed across cameras.
depthFromScan = cv::Mat::zeros(img.rows, img.cols, CV_32FC1);
int offset = 0;
for(size_t i=0; i<models.size() && offset+models[i].imageWidth()<=img.cols; ++i)
depthFromScan = util3d::projectCloudToCamera(img.size(), model.K(), cloud, model.localTransform());
if(_depthFromScanFillHoles!=0)
{
int subWidth = models[i].imageWidth();
cv::Mat subDepth = util3d::projectCloudToCamera(cv::Size(subWidth, img.rows), models[i].K(), cloud, models[i].localTransform());
if(_depthFromScanFillHoles!=0)
{
util3d::fillProjectedCloudHoles(subDepth, _depthFromScanFillHoles>0, _depthFromScanFillHolesFromBorder);
}
subDepth.copyTo(depthFromScan(cv::Rect(offset, 0, subWidth, img.rows)));
offset += subWidth;
util3d::fillProjectedCloudHoles(depthFromScan, _depthFromScanFillHoles>0, _depthFromScanFillHolesFromBorder);
}
}
}
@@ -1241,10 +992,15 @@ SensorData CameraImages::captureImage(SensorCaptureInfo * info)
UWARN("Directory is not set, camera must be initialized.");
}
if(model.imageHeight() == 0 || model.imageWidth() == 0)
{
model.setImageSize(img.size());
}
SensorData data;
if(!img.empty() || !scan.empty())
{
data = SensorData(scan, _isDepth?cv::Mat():img, _isDepth?img:depthFromScan, models, this->getNextSeqID(), stamp);
data = SensorData(scan, _isDepth?cv::Mat():img, _isDepth?img:depthFromScan, model, this->getNextSeqID(), stamp);
data.setGroundTruth(groundTruthPose);
}
+6 -45
View File
@@ -220,12 +220,6 @@ bool CameraOrbbecSDK::init(const std::string & calibrationFolder, const std::str
#ifdef RTABMAP_ORBBEC_SDK
this->close();
// The Orbbec SDK reports failures by throwing ob::Error (e.g. uvc_open
// access denied on macOS without camera permission, or unsupported config).
// Catch them here so init() logs the error and returns false instead of
// letting the exception propagate and abort the whole process.
try {
std::shared_ptr<ob::Device> device;
ob::Context context;
@@ -282,18 +276,14 @@ bool CameraOrbbecSDK::init(const std::string & calibrationFolder, const std::str
}
if(device.get() == nullptr) {
#ifdef __APPLE__
const std::string connectHint = "camera is correctly connected. On macOS the Orbbec "
"camera can only be accessed with root privileges, so run the application with sudo.";
#else
const std::string connectHint = "camera is correctly connected and the udev rules are installed.";
#endif
if(deviceId_.empty()) {
UERROR("Could not find any orbbec compatible devices! Verify that the %s", connectHint.c_str());
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 %s "
"Unset the ID to choose the first camera found.", deviceId_.c_str(), connectHint.c_str());
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;
@@ -556,22 +546,6 @@ bool CameraOrbbecSDK::init(const std::string & calibrationFolder, const std::str
return false;
}
}
catch(const ob::Error & e)
{
#ifdef __APPLE__
UERROR("Failed to initialize Orbbec camera: %s. On macOS the Orbbec SDK accesses "
"the camera through libusb, which must take the USB interface from the system "
"UVC driver; this requires root privileges. If this is a USB access error "
"(e.g. \"uvc_open failed ... Return Code: -3\"), run the application with sudo.",
e.what());
#else
UERROR("Failed to initialize Orbbec camera: %s", e.what());
#endif
this->close();
return false;
}
return true;
#else
UERROR("CameraOrbbecSDK: RTAB-Map is not built with Orbbec SDK support!");
@@ -624,19 +598,13 @@ SensorData CameraOrbbecSDK::captureImage(SensorCaptureInfo * info)
UERROR("Camera is not initialized!");
return data;
}
// The streaming calls below can throw ob::Error (transient frame/USB
// errors, filter or profile failures). Catch them so a bad frame is logged
// and skipped (empty SensorData) instead of aborting the whole process.
try {
auto frameset = pipeline_->waitForFrameset();
if(frameset == nullptr || frameset->getCount() == 0) {
UWARN("No frame received!");
return data;
}
if(frameset->getCount() != 2) {
UWARN("Received %u frames, expecting 2!", frameset->getCount());
UWARN("Received %s frames, expecting 2!", frameset->getCount());
return data;
}
@@ -765,13 +733,6 @@ SensorData CameraOrbbecSDK::captureImage(SensorCaptureInfo * info)
}
}
}
catch(const ob::Error & e)
{
UERROR("Error capturing Orbbec camera frame: %s", e.what());
return data;
}
#else
UERROR("CameraOrbbecSDK: RTAB-Map is not built with Orbbec SDK support!");
#endif
+1 -20
View File
@@ -107,14 +107,10 @@ void CameraRealSense2::close()
{
if(!_sensor.get_active_streams().empty())
{
std::string sensorName = _sensor.supports(RS2_CAMERA_INFO_NAME) ? _sensor.get_info(RS2_CAMERA_INFO_NAME) : "?";
try
{
UDEBUG("stop() sensor \"%s\"...", sensorName.c_str());
_sensor.stop();
UDEBUG("stop() sensor \"%s\" done; close()...", sensorName.c_str());
_sensor.close();
UDEBUG("close() sensor \"%s\" done", sensorName.c_str());
}
catch(const rs2::error & error)
{
@@ -123,15 +119,12 @@ void CameraRealSense2::close()
}
}
#ifdef WIN32
UDEBUG("Windows-only: Hardware reset (to avoid freezing when clearing devices)...");
dev_[i].hardware_reset(); // To avoid freezing on some Windows computers in the following destructor
// Don't do this on linux (tested on Ubuntu 18.04, realsense v2.41.0): T265 cannot be restarted
UDEBUG("Windows-only: Hardware reset... done");
#endif
}
UDEBUG("Clearing devices...");
dev_.clear();
UDEBUG("Clearing devices... done!");
}
catch(const rs2::error & error)
{
@@ -515,14 +508,7 @@ bool CameraRealSense2::init(const std::string & calibrationFolder, const std::st
rs2::device_list list = ctx_.query_devices();
if (0 == list.size())
{
#ifdef __APPLE__
UERROR("No RealSense2 devices were found! On macOS the RealSense SDK accesses "
"the camera through libusb, which must take the USB interface from the "
"system driver; this requires root privileges. If a device is connected "
"but not detected, run the application with sudo.");
#else
UERROR("No RealSense2 devices were found!");
#endif
return false;
}
@@ -560,12 +546,7 @@ bool CameraRealSense2::init(const std::string & calibrationFolder, const std::st
}
catch(const rs2::error & error)
{
#ifdef __APPLE__
UERROR("%s. Is the camera already used with another app? On macOS, accessing a "
"RealSense camera requires root privileges, so try running with sudo.", error.what());
#else
UERROR("%s. Is the camera already used with another app?", error.what());
#endif
UWARN("%s. Is the camera already used with another app?", error.what());
}
if (!found)
+15 -236
View File
@@ -27,8 +27,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <rtabmap/core/camera/CameraStereoImages.h>
#include <rtabmap/utilite/UStl.h>
#include <rtabmap/utilite/UFile.h>
#include <rtabmap/utilite/UConversion.h>
#include <opencv2/imgproc/types_c.h>
namespace rtabmap
@@ -89,12 +87,10 @@ bool CameraStereoImages::init(const std::string & calibrationFolder, const std::
{
UINFO("Calibration folder: \"%s\", name=\"%s\"", calibrationFolder.c_str(), cameraName.c_str());
multiStereoModels_.clear();
// look for calibration files
if(!_multiCameraCalib && !calibrationFolder.empty() && !cameraName.empty())
if(!calibrationFolder.empty() && !cameraName.empty())
{
if(!stereoModel_.load(calibrationFolder, cameraName, false, this->isImagesRectified()) && !stereoModel_.isValidForProjection())
if(!stereoModel_.load(calibrationFolder, cameraName, false) && !stereoModel_.isValidForProjection())
{
UWARN("Missing calibration files for camera \"%s\" in \"%s\" folder, you should calibrate the camera!",
cameraName.c_str(), calibrationFolder.c_str());
@@ -109,32 +105,16 @@ bool CameraStereoImages::init(const std::string & calibrationFolder, const std::
}
}
if(!_multiCameraCalib)
stereoModel_.setLocalTransform(this->getLocalTransform());
stereoModel_.setName(cameraName);
if(this->isImagesRectified() && !stereoModel_.isValidForRectification())
{
stereoModel_.setLocalTransform(this->getLocalTransform());
stereoModel_.setName(cameraName);
if(this->isImagesRectified() && !stereoModel_.isValidForRectification())
{
UWARN("Parameter \"rectifyImages\" is set, but no stereo model is loaded or valid for rectification. This can be ignored if input images are already rectified.");
}
UWARN("Parameter \"rectifyImages\" is set, but no stereo model is loaded or valid for rectification. This can be ignored if input images are already rectified.");
}
//desactivate before init as we will do it in this class instead for convenience
bool rectify = this->isImagesRectified();
this->setImagesRectified(false);
// The base reader is used here only to enumerate/read the left images; in
// multi-camera mode this class loads the calibration and splits the images
// itself, so prevent the base from doing its own multi-camera handling and
// per-frame config loading (which would look for config files inside the image
// directory). Both flags are restored below: _multiCameraCalib still drives the
// per-frame vs. shared calibration loading in this class.
bool configForEachFrame = this->isConfigForEachFrame();
bool multiCameraCalib = _multiCameraCalib;
if(multiCameraCalib)
{
this->setConfigForEachFrame(false);
}
_multiCameraCalib = false;
bool success = false;
if(CameraImages::init())
@@ -164,141 +144,13 @@ bool CameraStereoImages::init(const std::string & calibrationFolder, const std::
success = true;
}
}
// restore the flags: _multiCameraCalib drives the per-frame vs. shared calibration loading below
this->setConfigForEachFrame(configForEachFrame);
_multiCameraCalib = multiCameraCalib;
if(success && _multiCameraCalib)
{
// Multi-camera stereo mode: each left/right image is a horizontal stack of N
// sub-camera images. Load one StereoCameraModel per sub-camera from calibration
// files named "<imageBaseName>_<index>_left.yaml" and "<imageBaseName>_<index>_right.yaml"
// (index starting at 0).
if(calibrationFolder.empty())
{
UERROR("Multi-camera calibration is enabled but no calibration folder was provided.");
success = false;
}
else
{
const std::vector<std::string> imageFiles = this->filenames();
std::string firstBase = imageFiles.front().substr(0, imageFiles.front().find_last_of('.'));
// In config-for-each-frame mode the prefix is each image's base name (one
// calibration set per frame). Otherwise a single calibration set is shared by all
// frames, using cameraName as the prefix when provided. cameraName may point to a
// specific sub-camera calibration "<rig>_<index>" (e.g. when a single calibration
// file is selected); in that case strip the trailing "_<index>" to recover the rig
// prefix shared by all sub-cameras. Fall back to the first image's base name if empty.
std::string leftSuffix = "_0_" + stereoModel_.getLeftSuffix() + ".yaml";
std::string sharedBase = cameraName;
if(!sharedBase.empty() && !UFile::exists(calibrationFolder + "/" + sharedBase + leftSuffix))
{
std::size_t us = sharedBase.find_last_of('_');
if(us != std::string::npos && us+1 < sharedBase.size() &&
sharedBase.find_first_not_of("0123456789", us+1) == std::string::npos &&
UFile::exists(calibrationFolder + "/" + sharedBase.substr(0, us) + leftSuffix))
{
sharedBase = sharedBase.substr(0, us);
}
}
if(sharedBase.empty())
{
sharedBase = firstBase;
}
// auto-detect the number of cameras
int numCameras = 0;
std::string detectBase = this->isConfigForEachFrame() ? firstBase : sharedBase;
while(UFile::exists(calibrationFolder + "/" + detectBase + "_" + uNumber2Str(numCameras) + "_" + stereoModel_.getLeftSuffix() + ".yaml"))
{
++numCameras;
}
if(numCameras == 0)
{
UERROR("Multi-camera calibration is enabled but no calibration file matching "
"\"%s/%s_<index>_%s.yaml\" was found.",
calibrationFolder.c_str(), detectBase.c_str(), stereoModel_.getLeftSuffix().c_str());
success = false;
}
else
{
UINFO("Multi-camera stereo mode: %d sub-cameras detected from \"%s\" (%s).", numCameras, calibrationFolder.c_str(),
this->isConfigForEachFrame()?"one calibration per frame, loaded on demand":
uFormat("calibration \"%s_<index>\" reused for all frames", sharedBase.c_str()).c_str());
_calibrationFolder = calibrationFolder;
_multiCameraCount = numCameras;
if(this->isConfigForEachFrame())
{
// Validate the first frame now; the per-frame sub-camera stereo models are
// loaded on demand in captureImage() (keyed by each image's base name) so we
// don't keep every frame's models - and their rectification maps - in memory.
if(loadStereoCameraModels(firstBase, rectify).empty())
{
success = false;
}
}
else
{
// A single calibration set is shared by all frames: load it once.
std::vector<StereoCameraModel> models = loadStereoCameraModels(sharedBase, rectify);
if(models.empty())
{
success = false;
}
else
{
multiStereoModels_ = models;
}
}
}
}
}
this->setImagesRectified(rectify); // reset the flag
return success;
}
bool CameraStereoImages::isCalibrated() const
{
return stereoModel_.isValidForProjection() ||
(!multiStereoModels_.empty() && multiStereoModels_.front().isValidForProjection()) ||
(_multiCameraCalib && this->isConfigForEachFrame() && _multiCameraCount > 0); // per-frame models loaded on demand
}
std::vector<StereoCameraModel> CameraStereoImages::loadStereoCameraModels(const std::string & baseName, bool rectify) const
{
std::vector<StereoCameraModel> models(_multiCameraCount);
for(int i=0; i<_multiCameraCount; ++i)
{
std::string name = baseName + "_" + uNumber2Str(i);
if(!models[i].load(_calibrationFolder, name, true /*ignoreStereoTransform*/, rectify) || !models[i].isValidForProjection())
{
UERROR("Failed to load a valid stereo calibration \"%s/%s_{%s,%s}.yaml\" for multi-camera frame base \"%s\".",
_calibrationFolder.c_str(), name.c_str(),
models[i].getLeftSuffix().c_str(), models[i].getRightSuffix().c_str(), baseName.c_str());
return std::vector<StereoCameraModel>();
}
if(models[i].localTransform().isNull())
{
// In multi-camera mode the rig extrinsics are required: each
// sub-camera calibration must provide a "local_transform".
UERROR("Stereo calibration \"%s/%s_%s.yaml\" has no \"local_transform\"; it is "
"required in multi-camera mode (rig extrinsics).",
_calibrationFolder.c_str(), name.c_str(), models[i].getLeftSuffix().c_str());
return std::vector<StereoCameraModel>();
}
if(rectify && !models[i].isValidForRectification())
{
UERROR("Parameter \"rectifyImages\" is set, but stereo calibration \"%s/%s_{%s,%s}.yaml\" is not valid for rectification.",
_calibrationFolder.c_str(), name.c_str(),
models[i].getLeftSuffix().c_str(), models[i].getRightSuffix().c_str());
return std::vector<StereoCameraModel>();
}
}
return models;
return stereoModel_.isValidForProjection();
}
std::string CameraStereoImages::getSerial() const
@@ -311,11 +163,6 @@ SensorData CameraStereoImages::captureImage(SensorCaptureInfo * info)
SensorData data;
SensorData left, right;
// Disable the base reader's own multi-camera handling while reading the stacked
// left/right images: this class splits and rectifies them itself below. Restored
// before the multi-camera branch, which relies on the real flag value.
bool multiCameraCalib = _multiCameraCalib;
_multiCameraCalib = false;
left = CameraImages::captureImage(info);
if(!left.imageRaw().empty())
{
@@ -328,86 +175,18 @@ SensorData CameraStereoImages::captureImage(SensorCaptureInfo * info)
{
right = this->takeImage(info);
}
}
_multiCameraCalib = multiCameraCalib;
if(!left.imageRaw().empty() && !right.imageRaw().empty())
{
// Rectification
cv::Mat leftImage = left.imageRaw();
cv::Mat rightImage = right.imageRaw();
if(rightImage.type() != CV_8UC1 && rightGrayScale_)
if(!right.imageRaw().empty())
{
cv::Mat tmp;
cv::cvtColor(rightImage, tmp, CV_BGR2GRAY);
rightImage = tmp;
}
if(multiCameraCalib)
{
// Multi-camera stereo mode: left and right images are horizontal stacks
// of N sub-images (one stereo pair per sub-camera). Each pair is rectified
// independently with its own model and written back into a stacked image of
// the same layout. Sub-images are split using a uniform width (cols / N),
// matching the convention used downstream to de-stack the images.
std::vector<StereoCameraModel> models;
if(this->isConfigForEachFrame())
// Rectification
cv::Mat leftImage = left.imageRaw();
cv::Mat rightImage = right.imageRaw();
if(rightImage.type() != CV_8UC1 && rightGrayScale_)
{
// Per-frame calibration loaded on demand (not kept in memory),
// keyed by the current image's base name.
std::string base = this->lastImageFileName();
base = base.substr(0, base.find_last_of('.'));
models = loadStereoCameraModels(base, this->isImagesRectified());
cv::Mat tmp;
cv::cvtColor(rightImage, tmp, CV_BGR2GRAY);
rightImage = tmp;
}
else
{
// a single calibration set is shared by all frames
UASSERT(!multiStereoModels_.empty());
models = multiStereoModels_;
}
if(models.empty())
{
return data;
}
int n = (int)models.size();
if(leftImage.cols % n != 0 || rightImage.cols % n != 0)
{
UERROR("Multi-camera stereo: stacked image width (left=%d, right=%d) is not "
"divisible by the number of cameras (%d).", leftImage.cols, rightImage.cols, n);
return data;
}
int subWidthLeft = leftImage.cols/n;
int subWidthRight = rightImage.cols/n;
if(this->isImagesRectified())
{
cv::Mat leftRect(leftImage.rows, leftImage.cols, leftImage.type());
cv::Mat rightRect(rightImage.rows, rightImage.cols, rightImage.type());
for(int i=0; i<n; ++i)
{
cv::Rect roiL(subWidthLeft*i, 0, subWidthLeft, leftImage.rows);
cv::Rect roiR(subWidthRight*i, 0, subWidthRight, rightImage.rows);
models[i].left().rectifyImage(leftImage(roiL)).copyTo(leftRect(roiL));
models[i].right().rectifyImage(rightImage(roiR)).copyTo(rightRect(roiR));
}
leftImage = leftRect;
rightImage = rightRect;
}
for(int i=0; i<n; ++i)
{
if(models[i].left().imageHeight() == 0 || models[i].left().imageWidth() == 0)
{
models[i].setImageSize(cv::Size(subWidthLeft, leftImage.rows));
}
}
data = SensorData(left.laserScanRaw(), leftImage, rightImage, models, left.id()/(camera2_?1:2), left.stamp());
data.setGroundTruth(left.groundTruth());
}
else
{
if(this->isImagesRectified() && stereoModel_.isValidForRectification())
{
leftImage = stereoModel_.left().rectifyImage(leftImage);
+31 -148
View File
@@ -29,7 +29,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <rtabmap/utilite/UTimer.h>
#include <rtabmap/utilite/UThread.h>
#include <rtabmap/utilite/UConversion.h>
#include <rtabmap/utilite/UMath.h>
#ifdef RTABMAP_ZED
#include <sl/Camera.hpp>
@@ -78,7 +77,7 @@ static cv::Mat slMat2cvMat(sl::Mat& input) {
#endif
}
static Transform zedPoseToTransform(const sl::Pose & pose)
Transform zedPoseToTransform(const sl::Pose & pose)
{
return Transform(
pose.pose_data.m[0], pose.pose_data.m[1], pose.pose_data.m[2], pose.pose_data.m[3],
@@ -87,7 +86,7 @@ static Transform zedPoseToTransform(const sl::Pose & pose)
}
#if ZED_SDK_MAJOR_VERSION < 3
static IMU zedIMUtoIMU(const sl::IMUData & imuData, const Transform & imuLocalTransform)
IMU zedIMUtoIMU(const sl::IMUData & imuData, const Transform & imuLocalTransform)
{
sl::Orientation orientation = imuData.pose_data.getOrientation();
@@ -125,7 +124,7 @@ static IMU zedIMUtoIMU(const sl::IMUData & imuData, const Transform & imuLocalTr
imuLocalTransform);
}
#else
static IMU zedIMUtoIMU(const sl::SensorsData & sensorData, const Transform & imuLocalTransform)
IMU zedIMUtoIMU(const sl::SensorsData & sensorData, const Transform & imuLocalTransform)
{
sl::Orientation orientation = sensorData.imu.pose.getOrientation();
@@ -162,23 +161,6 @@ static IMU zedIMUtoIMU(const sl::SensorsData & sensorData, const Transform & imu
accCov,
imuLocalTransform);
}
// sl::SensorsData::imu.is_available only means the camera has an IMU; a returned
// sample can still contain NaN pose/accel/gyro (e.g. before the IMU fusion has
// initialized, or in SVO/STREAM mode). Validate the actual measurements.
static bool isImuValid(const sl::SensorsData & sensorData)
{
if(!sensorData.imu.is_available)
{
return false;
}
const sl::float3 & acc = sensorData.imu.linear_acceleration;
const sl::float3 & gyr = sensorData.imu.angular_velocity;
const sl::Orientation ori = sensorData.imu.pose.getOrientation();
return uIsFinite(acc.v[0]) && uIsFinite(acc.v[1]) && uIsFinite(acc.v[2]) &&
uIsFinite(gyr.v[0]) && uIsFinite(gyr.v[1]) && uIsFinite(gyr.v[2]) &&
uIsFinite(ori.ox) && uIsFinite(ori.oy) && uIsFinite(ori.oz) && uIsFinite(ori.ow);
}
#endif
class ZedIMUThread: public UThread
@@ -235,7 +217,7 @@ private:
#else
sl::SensorsData sensordata;
sl::ERROR_CODE res = zed_->getSensorsData(sensordata, sl::TIME_REFERENCE::CURRENT);
if(res == sl::ERROR_CODE::SUCCESS && isImuValid(sensordata))
if(res == sl::ERROR_CODE::SUCCESS && sensordata.imu.is_available)
{
camera_->postInterIMUPublic(zedIMUtoIMU(sensordata, imuLocalTransform_), double(sensordata.imu.timestamp.getNanoseconds())/10e8);
}
@@ -269,56 +251,6 @@ int CameraStereoZed::sdkVersion()
#endif
}
#ifdef RTABMAP_ZED
static void backwardCompatibility(int & resolution, int & quality)
{
// -1 = AUTO, 0=HD4K 1=QHDPLUS 2=HD2K 3=HD1536 4=HD1080 5=HD1200 6=HD720 7=SVGA 8=VGA 9=XVGA 10=TXVGA
#if ZED_SDK_MAJOR_VERSION < 4
// Zed3 Supported: 2=HD2K 4=HD1080 6=HD720 8=VGA
if(resolution == 0 || resolution == 1) // 0=HD4K 1=QHDPLUS
{
UWARN("Zed SDK v3 doesn't support HD4K and QHDPLUS, setting HD2K.");
resolution = 2; // 2=HD2K
}
if(resolution == 3 || resolution == 5) // 3=HD1536 5=HD1200
{
UWARN("Zed SDK v3 doesn't support HD1536 and HD1200, setting HD1080.");
resolution = 4; // 4=HD1080
}
if(resolution == 7 || resolution >=9) // 7=SVGA 9=XVGA 10=TXVGA
{
UWARN("Zed SDK v3 doesn't support SVGA, XVGA and TXVGA, setting VGA.");
resolution = 8; // 8=VGA
}
if(quality == 4) { // 4=NEURAL_LIGHT 6=NEURAL_PLUS
UWARN("Zed SDK v3 doesn't support NEURAL_LIGHT and NEURAL PLUS, setting NEURAL.");
quality = 5; // NEURAL
}
#else
if(resolution == -1)
{
resolution = int(sl::RESOLUTION::AUTO); // AUTO
}
#if ZED_SDK_MAJOR_VERSION < 5
// Zed4 Supported: 0=HD4K 1=QHDPLUS 2=HD2K 4=HD1080 5=HD1200 6=HD720 7=SVGA 8=VGA
if(resolution == 3) // 3=HD1536
{
UWARN("Zed SDK v4 doesn't support HD1536, setting HD1200.");
resolution_ = 5; // 5=HD1200
}
if(resolution >=9) // 9=XVGA 10=TXVGA
{
UWARN("Zed SDK v4 doesn't support XVGA and TXVGA, setting VGA.");
resolution = 8; // 8=VGA
}
if(quality > 5) { // NEURAL_PLUS
UWARN("Zed SDK v4 doesn't support NEURAL_LIGHT and NEURAL PLUS, setting NEURAL.");
quality = 5; // NEURAL
}
#endif
#endif
}
#endif
CameraStereoZed::CameraStereoZed(
int deviceId,
@@ -353,8 +285,29 @@ CameraStereoZed::CameraStereoZed(
{
UDEBUG("");
#ifdef RTABMAP_ZED
backwardCompatibility(resolution_, quality_);
#if ZED_SDK_MAJOR_VERSION < 4
if(resolution_ == 1 || resolution_ == 2) // HD2K, HD1080
{
resolution_ -= 1; // HD2K=0, HD1080=1
}
if(resolution_ == 3) // HD1200
{
resolution_ = 1; // HD1080=1
}
if(resolution_ == 4 || resolution_ == -1)
{
resolution_ = 2; // HD720=2
}
else if(resolution_ == 5 || resolution_ == 6) // SVGA, VGA
{
resolution_ = 3; // VGA=3
}
#else // ZED=4
if(resolution_ == -1)
{
resolution_ = int(sl::RESOLUTION::AUTO); // AUTO
}
#endif
#if ZED_SDK_MAJOR_VERSION < 3
UASSERT(resolution_ >= sl::RESOLUTION_HD2K && resolution_ <sl::RESOLUTION_LAST);
@@ -418,7 +371,6 @@ CameraStereoZed::CameraStereoZed(
{
UDEBUG("");
#ifdef RTABMAP_ZED
backwardCompatibility(resolution_, quality_);
#if ZED_SDK_MAJOR_VERSION < 3
UASSERT(resolution_ >= sl::RESOLUTION_HD2K && resolution_ <sl::RESOLUTION_LAST);
UASSERT(quality_ >= sl::DEPTH_MODE_NONE && quality_ <sl::DEPTH_MODE_LAST);
@@ -454,33 +406,6 @@ CameraStereoZed::~CameraStereoZed()
#endif
}
std::string CameraStereoZed::getNeuralModelWarning(int quality)
{
(void)quality;
#if defined(RTABMAP_ZED) && ZED_SDK_MAJOR_VERSION >= 5
sl::DEPTH_MODE depthMode = (sl::DEPTH_MODE)quality;
if(depthMode == sl::DEPTH_MODE::NEURAL_LIGHT ||
depthMode == sl::DEPTH_MODE::NEURAL ||
depthMode == sl::DEPTH_MODE::NEURAL_PLUS)
{
sl::AI_MODELS aiModel =
depthMode == sl::DEPTH_MODE::NEURAL_LIGHT ? sl::AI_MODELS::NEURAL_LIGHT_DEPTH :
depthMode == sl::DEPTH_MODE::NEURAL_PLUS ? sl::AI_MODELS::NEURAL_PLUS_DEPTH :
sl::AI_MODELS::NEURAL_DEPTH;
sl::AI_Model_status status = sl::checkAIModelStatus(aiModel);
if(!status.downloaded || !status.optimized)
{
return uFormat("The selected ZED NEURAL depth model is not ready yet (downloaded=%s, "
"optimized=%s): the first start may take significantly longer while the "
"ZED SDK downloads and/or optimizes the model for your GPU. Subsequent "
"starts will be faster.",
status.downloaded?"true":"false", status.optimized?"true":"false");
}
}
#endif
return std::string();
}
bool CameraStereoZed::init(const std::string & calibrationFolder, const std::string & cameraName)
{
UDEBUG("");
@@ -538,35 +463,9 @@ bool CameraStereoZed::init(const std::string & calibrationFolder, const std::str
r = zed_->open(param);
}
#if ZED_SDK_MAJOR_VERSION >= 3
// CORRUPTED_SDK_INSTALLATION on open() is typically a NEURAL depth mode whose optional
// neural/TensorRT runtime files aren't installed. Give a clear, actionable error.
if(r == sl::ERROR_CODE::CORRUPTED_SDK_INSTALLATION &&
#if ZED_SDK_MAJOR_VERSION >= 5
param.depth_mode >= sl::DEPTH_MODE::NEURAL_LIGHT)
#else
param.depth_mode >= sl::DEPTH_MODE::NEURAL)
#endif
{
UERROR("ZED open() returned \"%s\": the optional NEURAL/TensorRT runtime files are "
"likely missing. Install ZED SDK %d.%d, or select a non-NEURAL depth mode "
"(e.g. PERFORMANCE).", toString(r).c_str(), ZED_SDK_MAJOR_VERSION, ZED_SDK_MINOR_VERSION);
// Do NOT delete zed_ here: after a CORRUPTED_SDK_INSTALLATION open failure (NEURAL depth
// mode selected but the TensorRT/neural runtime isn't installed) the ZED SDK is left in a
// bad state and ~sl::Camera() crashes inside sl_zed64.dll. Leak the object (one-time,
// terminal error path) so we fail gracefully with the message above instead of crashing.
zed_ = 0;
return false;
}
#endif
if(r!=sl::ERROR_CODE::SUCCESS)
{
#if ZED_SDK_MAJOR_VERSION >= 4
UERROR("Camera initialization failed: \"%s\": %s", toString(r).c_str(), toVerbose(r).c_str());
#else
UERROR("Camera initialization failed: \"%s\"", toString(r).c_str());
#endif
delete zed_;
zed_ = 0;
return false;
@@ -603,11 +502,7 @@ bool CameraStereoZed::init(const std::string & calibrationFolder, const std::str
#endif
if(r!=sl::ERROR_CODE::SUCCESS)
{
#if ZED_SDK_MAJOR_VERSION >= 4
UERROR("Camera tracking initialization failed: \"%s\": %s", toString(r).c_str(), toVerbose(r).c_str());
#else
UERROR("Camera tracking initialization failed: \"%s\"", toString(r).c_str());
#endif
}
}
@@ -836,24 +731,16 @@ SensorData CameraStereoZed::captureImage(SensorCaptureInfo * info)
res = zed_->grab(rparam);
timestamp = zed_->getTimestamp(sl::TIME_REFERENCE::IMAGE);
// If the sensor supports IMU, wait for IMU to be available before sending data.
// If the sensor supports IMU, wait IMU to be available before sending data.
if(imuPublishingThread_ == 0 && !imuLocalTransform_.isNull())
{
sl::SensorsData imudatatmp;
res = zed_->getSensorsData(imudatatmp, sl::TIME_REFERENCE::IMAGE);
imuReceived = res == sl::ERROR_CODE::SUCCESS && isImuValid(imudatatmp) && imudatatmp.imu.timestamp.getNanoseconds() != 0;
imuReceived = res == sl::ERROR_CODE::SUCCESS && imudatatmp.imu.is_available && imudatatmp.imu.timestamp.getNanoseconds() != 0;
}
}
while(src_ == CameraVideo::kUsbDevice && (res!=sl::ERROR_CODE::SUCCESS || !imuReceived) && timer.elapsed() < 2.0);
// If no valid IMU arrived within the 2 sec startup window, null the IMU transform so
// we don't re-wait 2 sec on every subsequent frame (camera likely has no working IMU).
if(imuPublishingThread_ == 0 && !imuLocalTransform_.isNull() && !imuReceived)
{
UWARN("No valid IMU received within 2 sec; ignoring IMU for the rest of this session.");
imuLocalTransform_.setNull();
}
if(res==sl::ERROR_CODE::SUCCESS)
#endif
{
@@ -907,7 +794,7 @@ SensorData CameraStereoZed::captureImage(SensorCaptureInfo * info)
#endif
}
if(imuPublishingThread_ == 0 && !imuLocalTransform_.isNull())
if(imuPublishingThread_ == 0)
{
#if ZED_SDK_MAJOR_VERSION < 3
sl::IMUData imudata;
@@ -916,7 +803,7 @@ SensorData CameraStereoZed::captureImage(SensorCaptureInfo * info)
#else
sl::SensorsData imudata;
res = zed_->getSensorsData(imudata, sl::TIME_REFERENCE::IMAGE);
if(res == sl::ERROR_CODE::SUCCESS && isImuValid(imudata))
if(res == sl::ERROR_CODE::SUCCESS && imudata.imu.is_available)
#endif
{
//ZED-Mini
@@ -989,11 +876,7 @@ SensorData CameraStereoZed::captureImage(SensorCaptureInfo * info)
}
else if(src_ == CameraVideo::kUsbDevice)
{
#if ZED_SDK_MAJOR_VERSION >= 4
UERROR("CameraStereoZed: Failed to grab images after 2 seconds! (%s: %s)", toString(res).c_str(), toVerbose(res).c_str());
#else
UERROR("CameraStereoZed: Failed to grab images after 2 seconds!");
#endif
}
else
{
+2 -167
View File
@@ -34,10 +34,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define VLP_DUAL_MODE 0x39
#endif
// RTABMAP_VLP16_USE_CUSTOM_SOCKET is defined (Apple only, and toggleable) in
// LidarVLP16.h. When set, network mode uses our own single-threaded UDP receive
// loop; otherwise start()/stop()/isRunning() delegate to pcl::VLPGrabber.
namespace rtabmap {
/** @brief Function used to check that hour assigned to timestamp in conversion is
@@ -96,17 +92,8 @@ LidarVLP16::LidarVLP16(
startSweepTimeHost_(0),
organized_(organized),
useHostTime_(false),
stampLast_(stampLast),
networkMode_(false),
port_(0),
receivedScan_(false)
#ifdef RTABMAP_VLP16_USE_CUSTOM_SOCKET
,socket_(0)
,readThread_(0)
,terminate_(false)
#endif
stampLast_(stampLast)
{
// ipAddress_ unused in PCAP mode (default-constructed / unspecified).
UDEBUG("Using PCAP file \"%s\"", pcapFile.c_str());
}
LidarVLP16::LidarVLP16(
@@ -124,19 +111,7 @@ LidarVLP16::LidarVLP16(
startSweepTimeHost_(0),
organized_(organized),
useHostTime_(useHostTime),
stampLast_(stampLast),
// networkMode_ = live network capture (vs PCAP playback), on all platforms;
// it drives the "no data received" warning below. The custom socket path it
// also selects in start()/stop() is Apple-only (RTABMAP_VLP16_USE_CUSTOM_SOCKET).
networkMode_(true),
ipAddress_(ipAddress),
port_(port),
receivedScan_(false)
#ifdef RTABMAP_VLP16_USE_CUSTOM_SOCKET
,socket_(0)
,readThread_(0)
,terminate_(false)
#endif
stampLast_(stampLast)
{
UDEBUG("Using network lidar with IP=%s port=%d", ipAddress.to_string().c_str(), port);
}
@@ -154,132 +129,6 @@ void LidarVLP16::setOrganized(bool enable)
organized_ = true;
}
#ifdef RTABMAP_VLP16_USE_CUSTOM_SOCKET
void LidarVLP16::start()
{
if(networkMode_)
{
if(readThread_ != 0)
{
// already running
return;
}
terminate_ = false;
// ipAddress_ is the LOCAL interface to listen on (as in pcl::HDLGrabber),
// not the sensor's address. Binding to a specific local IP scopes
// reception to that NIC on a multi-homed host. If it is unspecified
// (0.0.0.0) or not a local address (e.g. the sensor's IP was entered by
// mistake), fall back to listening on all interfaces, like pcl::HDLGrabber.
try
{
boost::asio::ip::udp::endpoint endpoint(
ipAddress_.is_unspecified() ? boost::asio::ip::address(boost::asio::ip::address_v4::any()) : ipAddress_,
port_);
// Unlike pcl::HDLGrabber, we read and process packets in a single
// thread instead of a producer/consumer queue. A large receive buffer
// lets the kernel hold a backlog (~800 VLP16 packets here) so a brief
// stall in toPointClouds() doesn't drop packets.
const int receiveBufferSize = 1024 * 1024; // 1 MB
try
{
socket_ = new boost::asio::ip::udp::socket(ioContext_);
socket_->open(boost::asio::ip::udp::v4());
socket_->set_option(boost::asio::socket_base::reuse_address(true));
socket_->set_option(boost::asio::socket_base::receive_buffer_size(receiveBufferSize));
socket_->bind(endpoint);
}
catch(const std::exception & e)
{
UWARN("Could not bind VLP16 socket to local address %s (%s); "
"falling back to listening on all interfaces (0.0.0.0).",
endpoint.address().to_string().c_str(), e.what());
delete socket_;
socket_ = new boost::asio::ip::udp::socket(ioContext_);
socket_->open(boost::asio::ip::udp::v4());
socket_->set_option(boost::asio::socket_base::reuse_address(true));
socket_->set_option(boost::asio::socket_base::receive_buffer_size(receiveBufferSize));
socket_->bind(boost::asio::ip::udp::endpoint(boost::asio::ip::address_v4::any(), port_));
}
}
catch(const std::exception & e)
{
UERROR("Failed to bind to VLP16 UDP port %d: %s", (int)port_, e.what());
delete socket_;
socket_ = 0;
return;
}
receivedScan_ = false;
readThread_ = new std::thread(&LidarVLP16::readPackets, this);
return;
}
// PCAP mode: use the base grabber.
pcl::VLPGrabber::start();
}
void LidarVLP16::stop()
{
if(networkMode_)
{
terminate_ = true;
if(socket_ != 0)
{
// Closing the socket unblocks receive_from in the read thread. Because
// that call uses the non-throwing (error_code) overload, the EBADF that
// BSD/macOS returns here surfaces as an error code instead of an
// exception, so the thread exits cleanly rather than aborting.
boost::system::error_code ec;
socket_->close(ec);
}
if(readThread_ != 0)
{
readThread_->join();
delete readThread_;
readThread_ = 0;
}
delete socket_;
socket_ = 0;
return;
}
pcl::VLPGrabber::stop();
}
bool LidarVLP16::isRunning() const
{
if(networkMode_)
{
return readThread_ != 0;
}
return pcl::VLPGrabber::isRunning();
}
void LidarVLP16::readPackets()
{
std::uint8_t data[1500];
boost::asio::ip::udp::endpoint sender;
while(!terminate_)
{
boost::system::error_code ec;
std::size_t length = socket_->receive_from(boost::asio::buffer(data, sizeof(data)), sender, 0, ec);
if(ec)
{
// On stop() the socket is closed under us (bad_descriptor /
// operation_aborted); only warn if it wasn't an expected shutdown.
if(!terminate_)
{
UWARN("VLP16 socket receive error: %s", ec.message().c_str());
}
break;
}
// VLP-16 data packets are 1206 bytes; ignore anything shorter.
if(length >= 1206)
{
toPointClouds(reinterpret_cast<HDLDataPacket*>(data));
}
}
}
#endif // RTABMAP_VLP16_USE_CUSTOM_SOCKET
bool LidarVLP16::init(const std::string &, const std::string &)
{
UDEBUG("Init lidar");
@@ -516,22 +365,8 @@ SensorData LidarVLP16::captureData(SensorCaptureInfo * info)
{
data = lastScan_;
lastScan_ = SensorData();
receivedScan_ = true;
}
}
else if(networkMode_ && !receivedScan_)
{
// No packet has ever arrived: most likely the sensor isn't sending data
// to this computer. Point the user at the configured listening endpoint.
UWARN("Did not receive any VLP16 data packets for the past 5 seconds. "
"This computer is listening on %s:%d (%s). Make sure the LiDAR is "
"powered on and configured to send its data to this computer's IP "
"address on UDP port %d (set the data destination host in the "
"LiDAR's own web/configuration interface).",
ipAddress_.to_string().c_str(), (int)port_,
ipAddress_.is_unspecified() ? "all local interfaces" : "this interface only",
(int)port_);
}
else
{
UWARN("Did not receive any scans for the past 5 seconds.");
+2 -6
View File
@@ -52,7 +52,6 @@ CREATE TABLE Data (
);
CREATE TABLE Link (
id INTEGER PRIMARY KEY, -- required by the SQLite session extension (DB diff tracking); (from_id,to_id) is not unique (a node pair can have several links)
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
@@ -73,7 +72,6 @@ CREATE TABLE Word (
);
CREATE TABLE Feature (
id INTEGER PRIMARY KEY, -- required by the SQLite session extension (DB diff tracking)
node_id INTEGER NOT NULL,
word_id INTEGER NOT NULL,
pos_x FLOAT NOT NULL,
@@ -91,7 +89,6 @@ CREATE TABLE Feature (
);
CREATE TABLE GlobalDescriptor (
id INTEGER PRIMARY KEY, -- required by the SQLite session extension (DB diff tracking)
node_id INTEGER NOT NULL,
type INTEGER NOT NULL,
info BLOB,
@@ -102,7 +99,6 @@ CREATE TABLE GlobalDescriptor (
--
CREATE TABLE Info (
id INTEGER PRIMARY KEY, -- required by the SQLite session extension (DB diff tracking)
STM_size INTEGER,
last_sign_added INTEGER,
process_mem_used INTEGER,
@@ -117,12 +113,11 @@ CREATE TABLE Statistics (
stamp FLOAT,
data BLOB, -- compressed string
wm_state BLOB, -- compressed data
PRIMARY KEY (id),
FOREIGN KEY (id) REFERENCES Node(id)
);
CREATE TABLE Admin (
version TEXT PRIMARY KEY,
version TEXT,
preview_image BLOB, -- compressed image
opt_cloud BLOB, -- compressed data
@@ -181,6 +176,7 @@ 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
@@ -1,184 +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,
dictionary_index BLOB, -- serialized dictionary index
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.23.0');
+1 -1
View File
@@ -1,3 +1,3 @@
Version 3.53.3
Info: https://www.sqlite.org/
License: Public domain (https://www.sqlite.org/copyright.html)
+41995 -166312
View File
File diff suppressed because it is too large Load Diff
+1183 -8194
View File
File diff suppressed because it is too large Load Diff
+14 -266
View File
@@ -15,10 +15,12 @@
** as extensions by SQLite should #include this file instead of
** sqlite3.h.
*/
#ifndef SQLITE3EXT_H
#define SQLITE3EXT_H
#ifndef _SQLITE3EXT_H_
#define _SQLITE3EXT_H_
#include "sqlite3.h"
typedef struct sqlite3_api_routines sqlite3_api_routines;
/*
** The following structure holds pointers to all of the SQLite API
** routines.
@@ -26,7 +28,7 @@
** WARNING: In order to maintain backwards compatibility, add new
** interfaces to the end of this structure only. If you insert new
** interfaces in the middle of this structure, then older different
** versions of SQLite will not be able to load each other's shared
** versions of SQLite will not be able to load each others' shared
** libraries!
*/
struct sqlite3_api_routines {
@@ -134,7 +136,7 @@ struct sqlite3_api_routines {
int (*set_authorizer)(sqlite3*,int(*)(void*,int,const char*,const char*,
const char*,const char*),void*);
void (*set_auxdata)(sqlite3_context*,int,void*,void (*)(void*));
char * (*xsnprintf)(int,char*,const char*,...);
char * (*snprintf)(int,char*,const char*,...);
int (*step)(sqlite3_stmt*);
int (*table_column_metadata)(sqlite3*,const char*,const char*,const char*,
char const**,char const**,int*,int*,int*);
@@ -246,151 +248,13 @@ struct sqlite3_api_routines {
int (*uri_boolean)(const char*,const char*,int);
sqlite3_int64 (*uri_int64)(const char*,const char*,sqlite3_int64);
const char *(*uri_parameter)(const char*,const char*);
char *(*xvsnprintf)(int,char*,const char*,va_list);
char *(*vsnprintf)(int,char*,const char*,va_list);
int (*wal_checkpoint_v2)(sqlite3*,const char*,int,int*,int*);
/* Version 3.8.7 and later */
int (*auto_extension)(void(*)(void));
int (*bind_blob64)(sqlite3_stmt*,int,const void*,sqlite3_uint64,
void(*)(void*));
int (*bind_text64)(sqlite3_stmt*,int,const char*,sqlite3_uint64,
void(*)(void*),unsigned char);
int (*cancel_auto_extension)(void(*)(void));
int (*load_extension)(sqlite3*,const char*,const char*,char**);
void *(*malloc64)(sqlite3_uint64);
sqlite3_uint64 (*msize)(void*);
void *(*realloc64)(void*,sqlite3_uint64);
void (*reset_auto_extension)(void);
void (*result_blob64)(sqlite3_context*,const void*,sqlite3_uint64,
void(*)(void*));
void (*result_text64)(sqlite3_context*,const char*,sqlite3_uint64,
void(*)(void*), unsigned char);
int (*strglob)(const char*,const char*);
/* Version 3.8.11 and later */
sqlite3_value *(*value_dup)(const sqlite3_value*);
void (*value_free)(sqlite3_value*);
int (*result_zeroblob64)(sqlite3_context*,sqlite3_uint64);
int (*bind_zeroblob64)(sqlite3_stmt*, int, sqlite3_uint64);
/* Version 3.9.0 and later */
unsigned int (*value_subtype)(sqlite3_value*);
void (*result_subtype)(sqlite3_context*,unsigned int);
/* Version 3.10.0 and later */
int (*status64)(int,sqlite3_int64*,sqlite3_int64*,int);
int (*strlike)(const char*,const char*,unsigned int);
int (*db_cacheflush)(sqlite3*);
/* Version 3.12.0 and later */
int (*system_errno)(sqlite3*);
/* Version 3.14.0 and later */
int (*trace_v2)(sqlite3*,unsigned,int(*)(unsigned,void*,void*,void*),void*);
char *(*expanded_sql)(sqlite3_stmt*);
/* Version 3.18.0 and later */
void (*set_last_insert_rowid)(sqlite3*,sqlite3_int64);
/* Version 3.20.0 and later */
int (*prepare_v3)(sqlite3*,const char*,int,unsigned int,
sqlite3_stmt**,const char**);
int (*prepare16_v3)(sqlite3*,const void*,int,unsigned int,
sqlite3_stmt**,const void**);
int (*bind_pointer)(sqlite3_stmt*,int,void*,const char*,void(*)(void*));
void (*result_pointer)(sqlite3_context*,void*,const char*,void(*)(void*));
void *(*value_pointer)(sqlite3_value*,const char*);
int (*vtab_nochange)(sqlite3_context*);
int (*value_nochange)(sqlite3_value*);
const char *(*vtab_collation)(sqlite3_index_info*,int);
/* Version 3.24.0 and later */
int (*keyword_count)(void);
int (*keyword_name)(int,const char**,int*);
int (*keyword_check)(const char*,int);
sqlite3_str *(*str_new)(sqlite3*);
char *(*str_finish)(sqlite3_str*);
void (*str_appendf)(sqlite3_str*, const char *zFormat, ...);
void (*str_vappendf)(sqlite3_str*, const char *zFormat, va_list);
void (*str_append)(sqlite3_str*, const char *zIn, int N);
void (*str_appendall)(sqlite3_str*, const char *zIn);
void (*str_appendchar)(sqlite3_str*, int N, char C);
void (*str_reset)(sqlite3_str*);
int (*str_errcode)(sqlite3_str*);
int (*str_length)(sqlite3_str*);
char *(*str_value)(sqlite3_str*);
/* Version 3.25.0 and later */
int (*create_window_function)(sqlite3*,const char*,int,int,void*,
void (*xStep)(sqlite3_context*,int,sqlite3_value**),
void (*xFinal)(sqlite3_context*),
void (*xValue)(sqlite3_context*),
void (*xInv)(sqlite3_context*,int,sqlite3_value**),
void(*xDestroy)(void*));
/* Version 3.26.0 and later */
const char *(*normalized_sql)(sqlite3_stmt*);
/* Version 3.28.0 and later */
int (*stmt_isexplain)(sqlite3_stmt*);
int (*value_frombind)(sqlite3_value*);
/* Version 3.30.0 and later */
int (*drop_modules)(sqlite3*,const char**);
/* Version 3.31.0 and later */
sqlite3_int64 (*hard_heap_limit64)(sqlite3_int64);
const char *(*uri_key)(const char*,int);
const char *(*filename_database)(const char*);
const char *(*filename_journal)(const char*);
const char *(*filename_wal)(const char*);
/* Version 3.32.0 and later */
const char *(*create_filename)(const char*,const char*,const char*,
int,const char**);
void (*free_filename)(const char*);
sqlite3_file *(*database_file_object)(const char*);
/* Version 3.34.0 and later */
int (*txn_state)(sqlite3*,const char*);
/* Version 3.36.1 and later */
sqlite3_int64 (*changes64)(sqlite3*);
sqlite3_int64 (*total_changes64)(sqlite3*);
/* Version 3.37.0 and later */
int (*autovacuum_pages)(sqlite3*,
unsigned int(*)(void*,const char*,unsigned int,unsigned int,unsigned int),
void*, void(*)(void*));
/* Version 3.38.0 and later */
int (*error_offset)(sqlite3*);
int (*vtab_rhs_value)(sqlite3_index_info*,int,sqlite3_value**);
int (*vtab_distinct)(sqlite3_index_info*);
int (*vtab_in)(sqlite3_index_info*,int,int);
int (*vtab_in_first)(sqlite3_value*,sqlite3_value**);
int (*vtab_in_next)(sqlite3_value*,sqlite3_value**);
/* Version 3.39.0 and later */
int (*deserialize)(sqlite3*,const char*,unsigned char*,
sqlite3_int64,sqlite3_int64,unsigned);
unsigned char *(*serialize)(sqlite3*,const char *,sqlite3_int64*,
unsigned int);
const char *(*db_name)(sqlite3*,int);
/* Version 3.40.0 and later */
int (*value_encoding)(sqlite3_value*);
/* Version 3.41.0 and later */
int (*is_interrupted)(sqlite3*);
/* Version 3.43.0 and later */
int (*stmt_explain)(sqlite3_stmt*,int);
/* Version 3.44.0 and later */
void *(*get_clientdata)(sqlite3*,const char*);
int (*set_clientdata)(sqlite3*, const char*, void*, void(*)(void*));
/* Version 3.50.0 and later */
int (*setlk_timeout)(sqlite3*,int,int);
/* Version 3.51.0 and later */
int (*set_errmsg)(sqlite3*,int,const char*);
int (*db_status64)(sqlite3*,int,sqlite3_int64*,sqlite3_int64*,int);
/* Version 3.52.0 and later */
void (*str_truncate)(sqlite3_str*,int);
void (*str_free)(sqlite3_str*);
int (*carray_bind)(sqlite3_stmt*,int,void*,int,int,void(*)(void*));
int (*carray_bind_v2)(sqlite3_stmt*,int,void*,int,int,void(*)(void*),void*);
};
/*
** This is the function signature used for all extension entry points. It
** is also defined in the file "loadext.c".
*/
typedef int (*sqlite3_loadext_entry)(
sqlite3 *db, /* Handle to the database. */
char **pzErrMsg, /* Used to set error string on failure. */
const sqlite3_api_routines *pThunk /* Extension API function pointers. */
);
/*
** The following macros redefine the API routines so that they are
** redirected through the global sqlite3_api structure.
** redirected throught the global sqlite3_api structure.
**
** This header file is also used by the loadext.c source file
** (part of the main SQLite library - not an extension) so that
@@ -399,7 +263,7 @@ typedef int (*sqlite3_loadext_entry)(
** the API. So the redefinition macros are only valid if the
** SQLITE_CORE macros is undefined.
*/
#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
#ifndef SQLITE_CORE
#define sqlite3_aggregate_context sqlite3_api->aggregate_context
#ifndef SQLITE_OMIT_DEPRECATED
#define sqlite3_aggregate_count sqlite3_api->aggregate_count
@@ -502,7 +366,7 @@ typedef int (*sqlite3_loadext_entry)(
#define sqlite3_rollback_hook sqlite3_api->rollback_hook
#define sqlite3_set_authorizer sqlite3_api->set_authorizer
#define sqlite3_set_auxdata sqlite3_api->set_auxdata
#define sqlite3_snprintf sqlite3_api->xsnprintf
#define sqlite3_snprintf sqlite3_api->snprintf
#define sqlite3_step sqlite3_api->step
#define sqlite3_table_column_metadata sqlite3_api->table_column_metadata
#define sqlite3_thread_cleanup sqlite3_api->thread_cleanup
@@ -526,7 +390,6 @@ typedef int (*sqlite3_loadext_entry)(
#define sqlite3_value_text16le sqlite3_api->value_text16le
#define sqlite3_value_type sqlite3_api->value_type
#define sqlite3_vmprintf sqlite3_api->vmprintf
#define sqlite3_vsnprintf sqlite3_api->xvsnprintf
#define sqlite3_overload_function sqlite3_api->overload_function
#define sqlite3_prepare_v2 sqlite3_api->prepare_v2
#define sqlite3_prepare16_v2 sqlite3_api->prepare16_v2
@@ -602,126 +465,11 @@ typedef int (*sqlite3_loadext_entry)(
#define sqlite3_uri_boolean sqlite3_api->uri_boolean
#define sqlite3_uri_int64 sqlite3_api->uri_int64
#define sqlite3_uri_parameter sqlite3_api->uri_parameter
#define sqlite3_uri_vsnprintf sqlite3_api->xvsnprintf
#define sqlite3_uri_vsnprintf sqlite3_api->vsnprintf
#define sqlite3_wal_checkpoint_v2 sqlite3_api->wal_checkpoint_v2
/* Version 3.8.7 and later */
#define sqlite3_auto_extension sqlite3_api->auto_extension
#define sqlite3_bind_blob64 sqlite3_api->bind_blob64
#define sqlite3_bind_text64 sqlite3_api->bind_text64
#define sqlite3_cancel_auto_extension sqlite3_api->cancel_auto_extension
#define sqlite3_load_extension sqlite3_api->load_extension
#define sqlite3_malloc64 sqlite3_api->malloc64
#define sqlite3_msize sqlite3_api->msize
#define sqlite3_realloc64 sqlite3_api->realloc64
#define sqlite3_reset_auto_extension sqlite3_api->reset_auto_extension
#define sqlite3_result_blob64 sqlite3_api->result_blob64
#define sqlite3_result_text64 sqlite3_api->result_text64
#define sqlite3_strglob sqlite3_api->strglob
/* Version 3.8.11 and later */
#define sqlite3_value_dup sqlite3_api->value_dup
#define sqlite3_value_free sqlite3_api->value_free
#define sqlite3_result_zeroblob64 sqlite3_api->result_zeroblob64
#define sqlite3_bind_zeroblob64 sqlite3_api->bind_zeroblob64
/* Version 3.9.0 and later */
#define sqlite3_value_subtype sqlite3_api->value_subtype
#define sqlite3_result_subtype sqlite3_api->result_subtype
/* Version 3.10.0 and later */
#define sqlite3_status64 sqlite3_api->status64
#define sqlite3_strlike sqlite3_api->strlike
#define sqlite3_db_cacheflush sqlite3_api->db_cacheflush
/* Version 3.12.0 and later */
#define sqlite3_system_errno sqlite3_api->system_errno
/* Version 3.14.0 and later */
#define sqlite3_trace_v2 sqlite3_api->trace_v2
#define sqlite3_expanded_sql sqlite3_api->expanded_sql
/* Version 3.18.0 and later */
#define sqlite3_set_last_insert_rowid sqlite3_api->set_last_insert_rowid
/* Version 3.20.0 and later */
#define sqlite3_prepare_v3 sqlite3_api->prepare_v3
#define sqlite3_prepare16_v3 sqlite3_api->prepare16_v3
#define sqlite3_bind_pointer sqlite3_api->bind_pointer
#define sqlite3_result_pointer sqlite3_api->result_pointer
#define sqlite3_value_pointer sqlite3_api->value_pointer
/* Version 3.22.0 and later */
#define sqlite3_vtab_nochange sqlite3_api->vtab_nochange
#define sqlite3_value_nochange sqlite3_api->value_nochange
#define sqlite3_vtab_collation sqlite3_api->vtab_collation
/* Version 3.24.0 and later */
#define sqlite3_keyword_count sqlite3_api->keyword_count
#define sqlite3_keyword_name sqlite3_api->keyword_name
#define sqlite3_keyword_check sqlite3_api->keyword_check
#define sqlite3_str_new sqlite3_api->str_new
#define sqlite3_str_finish sqlite3_api->str_finish
#define sqlite3_str_appendf sqlite3_api->str_appendf
#define sqlite3_str_vappendf sqlite3_api->str_vappendf
#define sqlite3_str_append sqlite3_api->str_append
#define sqlite3_str_appendall sqlite3_api->str_appendall
#define sqlite3_str_appendchar sqlite3_api->str_appendchar
#define sqlite3_str_reset sqlite3_api->str_reset
#define sqlite3_str_errcode sqlite3_api->str_errcode
#define sqlite3_str_length sqlite3_api->str_length
#define sqlite3_str_value sqlite3_api->str_value
/* Version 3.25.0 and later */
#define sqlite3_create_window_function sqlite3_api->create_window_function
/* Version 3.26.0 and later */
#define sqlite3_normalized_sql sqlite3_api->normalized_sql
/* Version 3.28.0 and later */
#define sqlite3_stmt_isexplain sqlite3_api->stmt_isexplain
#define sqlite3_value_frombind sqlite3_api->value_frombind
/* Version 3.30.0 and later */
#define sqlite3_drop_modules sqlite3_api->drop_modules
/* Version 3.31.0 and later */
#define sqlite3_hard_heap_limit64 sqlite3_api->hard_heap_limit64
#define sqlite3_uri_key sqlite3_api->uri_key
#define sqlite3_filename_database sqlite3_api->filename_database
#define sqlite3_filename_journal sqlite3_api->filename_journal
#define sqlite3_filename_wal sqlite3_api->filename_wal
/* Version 3.32.0 and later */
#define sqlite3_create_filename sqlite3_api->create_filename
#define sqlite3_free_filename sqlite3_api->free_filename
#define sqlite3_database_file_object sqlite3_api->database_file_object
/* Version 3.34.0 and later */
#define sqlite3_txn_state sqlite3_api->txn_state
/* Version 3.36.1 and later */
#define sqlite3_changes64 sqlite3_api->changes64
#define sqlite3_total_changes64 sqlite3_api->total_changes64
/* Version 3.37.0 and later */
#define sqlite3_autovacuum_pages sqlite3_api->autovacuum_pages
/* Version 3.38.0 and later */
#define sqlite3_error_offset sqlite3_api->error_offset
#define sqlite3_vtab_rhs_value sqlite3_api->vtab_rhs_value
#define sqlite3_vtab_distinct sqlite3_api->vtab_distinct
#define sqlite3_vtab_in sqlite3_api->vtab_in
#define sqlite3_vtab_in_first sqlite3_api->vtab_in_first
#define sqlite3_vtab_in_next sqlite3_api->vtab_in_next
/* Version 3.39.0 and later */
#ifndef SQLITE_OMIT_DESERIALIZE
#define sqlite3_deserialize sqlite3_api->deserialize
#define sqlite3_serialize sqlite3_api->serialize
#endif
#define sqlite3_db_name sqlite3_api->db_name
/* Version 3.40.0 and later */
#define sqlite3_value_encoding sqlite3_api->value_encoding
/* Version 3.41.0 and later */
#define sqlite3_is_interrupted sqlite3_api->is_interrupted
/* Version 3.43.0 and later */
#define sqlite3_stmt_explain sqlite3_api->stmt_explain
/* Version 3.44.0 and later */
#define sqlite3_get_clientdata sqlite3_api->get_clientdata
#define sqlite3_set_clientdata sqlite3_api->set_clientdata
/* Version 3.50.0 and later */
#define sqlite3_setlk_timeout sqlite3_api->setlk_timeout
/* Version 3.51.0 and later */
#define sqlite3_set_errmsg sqlite3_api->set_errmsg
#define sqlite3_db_status64 sqlite3_api->db_status64
/* Version 3.52.0 and later */
#define sqlite3_str_truncate sqlite3_api->str_truncate
#define sqlite3_str_free sqlite3_api->str_free
#define sqlite3_carray_bind sqlite3_api->carray_bind
#define sqlite3_carray_bind_v2 sqlite3_api->carray_bind_v2
#endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */
#endif /* SQLITE_CORE */
#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
#ifndef SQLITE_CORE
/* This case when the file really is being compiled as a loadable
** extension */
# define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api=0;
@@ -736,4 +484,4 @@ typedef int (*sqlite3_loadext_entry)(
# define SQLITE_EXTENSION_INIT3 /*no-op*/
#endif
#endif /* SQLITE3EXT_H */
#endif /* _SQLITE3EXT_H_ */
+1 -13
View File
@@ -33,8 +33,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <QGraphicsView>
#include <QtCore/QMap>
#include <QtCore/QSettings>
#include <QTimer>
#include <QGraphicsPixmapItem>
#include <rtabmap/core/Link.h>
#include <rtabmap/core/GPS.h>
#include <opencv2/opencv.hpp>
@@ -132,7 +130,6 @@ public:
bool isOrientationENU() const;
ViewPlane getViewPlane() const;
bool isEnsureFrameVisible() const;
int getFastZoomMinNodes() const;
// setters
void setWorkingDirectory(const QString & path);
@@ -173,7 +170,6 @@ public:
void setOrientationENU(bool enabled);
void setViewPlane(ViewPlane plane);
void setEnsureFrameVisible(bool visible);
void setFastZoomMinNodes(int value);
Q_SIGNALS:
void configChanged();
@@ -188,14 +184,11 @@ protected:
virtual void wheelEvent ( QWheelEvent * event );
virtual void mouseMoveEvent(QMouseEvent * event);
virtual void mousePressEvent(QMouseEvent * event);
virtual void mouseReleaseEvent(QMouseEvent * event);
virtual void contextMenuEvent(QContextMenuEvent * event);
private:
void setupGraphicsScene();
void startZoomOverlay();
void updateZoomOverlay();
void stopZoomOverlay();
private:
QString _workingDirectory;
QColor _nodeColor;
@@ -255,11 +248,6 @@ private:
ViewPlane _viewPlane;
bool _ensureFrameVisible;
QPoint _previousMousePos;
QPoint _initialMousePos;
QTimer _zoomDebounceTimer;
QGraphicsPixmapItem * _zoomOverlayItem;
bool _zoomOverlayActive;
int _fastZoomMinNodes;
};
} /* namespace rtabmap */
@@ -130,12 +130,6 @@ public:
virtual QString getIniFilePath() const;
virtual QString getTmpIniFilePath() const;
// When running under sudo, Qt's QSettings replaces the ini with a
// root-owned file (write-temp + rename), so later non-root runs can no
// longer save preferences. Restore the invoking user's ownership (from
// SUDO_UID/SUDO_GID) on the config file and its directory. No-op on Windows
// and when not running as root. Best-effort (ignores failures).
static void restoreConfigOwnership(const QString & filePath);
void init(const QString & iniFilePath = "");
void setCurrentPanelToSource();
virtual QString getDefaultWorkingDirectory() const;
@@ -269,9 +263,6 @@ public:
PreferencesDialog::Src getSourceDriver() const;
QString getSourceDriverStr() const;
QString getSourceDevice() const;
// Non-empty warning to show before opening the selected source when init() is expected to be
// unusually slow; empty otherwise.
QString getSourceInitWarningMsg() const;
PreferencesDialog::Src getLidarSourceDriver() const;
PreferencesDialog::Src getOdomSourceDriver() const;
+5 -29
View File
@@ -39,9 +39,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <QtCore/QTextStream>
#include <QtCore/QDateTime>
#include <QtCore/QSettings>
#include <QtCore/QDir>
#include <QtCore/QFile>
#include <QtCore/QStandardPaths>
#include <QThread>
#include <rtabmap/utilite/ULogger.h>
#include <rtabmap/utilite/UDirectory.h>
@@ -586,33 +583,12 @@ QString DatabaseViewer::getIniFilePath() const
{
return iniFilePath_;
}
#ifdef WIN32
// Windows: store settings in the standard per-user config location (%LOCALAPPDATA%\rtabmap)
// instead of a Unix-style dotfile in the home root. A fixed "rtabmap" folder (not the app name)
// is used so the main GUI and DatabaseViewer share the same rtabmap.ini. Other platforms keep
// ~/.rtabmap for consistency.
QString privatePath = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + "/rtabmap";
#else
QString privatePath = QDir::homePath() + "/.rtabmap";
#endif
if(!QDir(privatePath).exists())
{
QDir().mkpath(privatePath);
QDir::home().mkdir(".rtabmap");
}
QString iniPath = privatePath + "/rtabmap.ini";
#ifdef WIN32
// One-time migration: if there's no ini at the new location but the legacy ~/.rtabmap/rtabmap.ini
// exists, copy it over so users keep their existing settings.
if(!QFile::exists(iniPath))
{
QString legacyIni = QDir::homePath() + "/.rtabmap/rtabmap.ini";
if(QFile::exists(legacyIni))
{
QFile::copy(legacyIni, iniPath);
}
}
#endif
return iniPath;
return privatePath + "/rtabmap.ini";
}
void DatabaseViewer::readSettings()
@@ -1689,12 +1665,12 @@ void DatabaseViewer::extractImages()
}
StereoCameraModel model(
cameraName,
data.stereoCameraModels()[i].left().imageSize(),
data.imageRaw().size(),
data.stereoCameraModels()[i].left().K_raw(),
data.stereoCameraModels()[i].left().D_raw(),
data.stereoCameraModels()[i].left().R(),
data.stereoCameraModels()[i].left().P(),
data.stereoCameraModels()[i].right().imageSize(),
data.rightRaw().size(),
data.stereoCameraModels()[i].right().K_raw(),
data.stereoCameraModels()[i].right().D_raw(),
data.stereoCameraModels()[i].right().R(),
@@ -1754,7 +1730,7 @@ void DatabaseViewer::extractImages()
cameraName+="_"+uNumber2Str((int)i);
}
CameraModel model(cameraName,
data.cameraModels()[i].imageSize(),
data.imageRaw().size(),
data.cameraModels()[i].K_raw(),
data.cameraModels()[i].D_raw(),
data.cameraModels()[i].R(),
+19 -152
View File
@@ -32,7 +32,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <QGraphicsScene>
#include <QGraphicsEllipseItem>
#include <QGraphicsRectItem>
#include <QGraphicsPixmapItem>
#include <QtGui/QWheelEvent>
#include <QGraphicsSceneHoverEvent>
#include <QMenu>
@@ -342,18 +341,10 @@ GraphViewer::GraphViewer(QWidget * parent) :
_orientationENU(false),
_mouseTracking(false),
_viewPlane(XY),
_ensureFrameVisible(true),
_previousMousePos(-1,-1),
_initialMousePos(-1,-1),
_zoomDebounceTimer(this),
_zoomOverlayItem(0),
_zoomOverlayActive(false),
_fastZoomMinNodes(0)
_ensureFrameVisible(true)
{
this->setDragMode(QGraphicsView::ScrollHandDrag);
_workingDirectory = QDir::homePath();
_zoomDebounceTimer.setSingleShot(true);
connect(&_zoomDebounceTimer, &QTimer::timeout, this, &GraphViewer::stopZoomOverlay);
setupGraphicsScene();
@@ -364,9 +355,6 @@ GraphViewer::GraphViewer(QWidget * parent) :
this->restoreDefaults();
this->fitInView(this->sceneRect(), Qt::KeepAspectRatio);
setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
setResizeAnchor(QGraphicsView::AnchorUnderMouse);
}
GraphViewer::~GraphViewer()
@@ -375,20 +363,11 @@ GraphViewer::~GraphViewer()
void GraphViewer::setupGraphicsScene()
{
_zoomDebounceTimer.stop();
_zoomOverlayActive = false;
_zoomOverlayItem = 0;
if(this->scene())
{
delete this->scene();
}
this->setScene(new QGraphicsScene(this));
_zoomOverlayItem = this->scene()->addPixmap(QPixmap());
_zoomOverlayItem->setZValue(1000000);
_zoomOverlayItem->setVisible(false);
_zoomOverlayItem->setAcceptedMouseButtons(Qt::NoButton);
_zoomOverlayItem->setAcceptHoverEvents(false);
_world = (QGraphicsItem *)this->scene()->addEllipse(QRectF(-0.0001,-0.0001,0.0001,0.0001));
_root = (QGraphicsItem *)this->scene()->addEllipse(QRectF(-0.0001,-0.0001,0.0001,0.0001));
_root->setParentItem(_world);
@@ -528,62 +507,6 @@ void GraphViewer::setupGraphicsScene()
}
void GraphViewer::startZoomOverlay()
{
if(_fastZoomMinNodes==0 || _nodeItems.size() < _fastZoomMinNodes)
{
return;
}
if(_zoomOverlayActive || !_zoomOverlayItem)
{
return;
}
const QRect viewportRect = this->viewport()->rect();
if(viewportRect.isEmpty())
{
return;
}
const QPixmap snapshot = this->viewport()->grab();
if(snapshot.isNull())
{
return;
}
const QRectF sourceRect = this->mapToScene(viewportRect).boundingRect();
const qreal sx = sourceRect.width() / qreal(snapshot.width());
const qreal sy = sourceRect.height() / qreal(snapshot.height());
_zoomOverlayItem->setPixmap(snapshot);
_zoomOverlayItem->setTransform(QTransform::fromScale(sx, sy));
_zoomOverlayItem->setPos(sourceRect.topLeft());
_zoomOverlayItem->show();
_world->setVisible(false);
_zoomOverlayActive = true;
}
void GraphViewer::stopZoomOverlay()
{
_zoomDebounceTimer.stop();
if(!_zoomOverlayActive)
{
return;
}
_zoomOverlayActive = false;
if(_zoomOverlayItem)
{
_zoomOverlayItem->hide();
}
if(_world)
{
_world->setVisible(true);
}
this->viewport()->update();
}
void GraphViewer::setWorldMapRotation(const float & theta)
{
_worldMapRotation = theta;
@@ -1509,7 +1432,6 @@ void GraphViewer::clearNodeColorByValue()
void GraphViewer::clearAll()
{
stopZoomOverlay();
clearMap();
clearGraph();
@@ -1567,7 +1489,6 @@ void GraphViewer::saveSettings(QSettings & settings, const QString & group) cons
settings.setValue("orientation_ENU", this->isOrientationENU());
settings.setValue("view_plane", (int)this->getViewPlane());
settings.setValue("ensure_frame_visible", (int)this->isEnsureFrameVisible());
settings.setValue("fast_zoom_min_nodes", this->getFastZoomMinNodes());
if(!group.isEmpty())
{
settings.endGroup();
@@ -1619,7 +1540,6 @@ void GraphViewer::loadSettings(QSettings & settings, const QString & group)
this->setOrientationENU(settings.value("orientation_ENU", this->isOrientationENU()).toBool());
this->setViewPlane((ViewPlane)settings.value("view_plane", (int)this->getViewPlane()).toInt());
this->setEnsureFrameVisible(settings.value("ensure_frame_visible", this->isEnsureFrameVisible()).toBool());
this->setFastZoomMinNodes(settings.value("fast_zoom_min_nodes", this->getFastZoomMinNodes()).toInt());
if(!group.isEmpty())
{
settings.endGroup();
@@ -1682,10 +1602,6 @@ bool GraphViewer::isEnsureFrameVisible() const
{
return _ensureFrameVisible;
}
int GraphViewer::getFastZoomMinNodes() const
{
return _fastZoomMinNodes;
}
void GraphViewer::setWorkingDirectory(const QString & path)
{
@@ -2051,11 +1967,6 @@ void GraphViewer::setEnsureFrameVisible(bool visible)
_ensureFrameVisible = visible;
}
void GraphViewer::setFastZoomMinNodes(int value)
{
_fastZoomMinNodes = value;
}
void GraphViewer::restoreDefaults()
{
@@ -2086,26 +1997,18 @@ void GraphViewer::restoreDefaults()
setGlobalPathVisible(true);
setLocalPathVisible(true);
setGtGraphVisible(true);
setFastZoomMinNodes(0);
}
void GraphViewer::wheelEvent(QWheelEvent * event)
void GraphViewer::wheelEvent ( QWheelEvent * event )
{
if(event->angleDelta().y() == 0)
if(event->angleDelta().y() < 0)
{
event->ignore();
return;
this->scale(0.95, 0.95);
}
else
{
this->scale(1.05, 1.05);
}
// Start buffering zoom interaction with a raster snapshot.
startZoomOverlay();
const qreal factor = event->angleDelta().y() < 0 ? 0.95 : 1.05;
this->scale(factor, factor);
// When wheel stops for 400 ms, restore the real scene and let it redraw once.
_zoomDebounceTimer.start(400);
event->accept();
}
void GraphViewer::mouseMoveEvent(QMouseEvent * event)
@@ -2126,16 +2029,14 @@ void GraphViewer::mouseMoveEvent(QMouseEvent * event)
if (event->modifiers() & (Qt::ShiftModifier | Qt::ControlModifier) && event->buttons() & Qt::LeftButton) {
// same modifiers than 3D view, change zoom
if(_previousMousePos.y()!=0) {
qreal factor = (event->pos().y() - _previousMousePos.y() > 0) ? 0.98 : 1.02;
QGraphicsView::ViewportAnchor oldAnchor = this->transformationAnchor();
this->setTransformationAnchor(QGraphicsView::NoAnchor);
QPointF scenePointBefore = this->mapToScene(_initialMousePos);
this->scale(factor, factor);
QPointF scenePointAfter = this->mapToScene(_initialMousePos);
QPointF delta = scenePointAfter - scenePointBefore;
this->translate(delta.x(), delta.y());
this->setTransformationAnchor(oldAnchor);
if(event->pos().y() - _previousMousePos.y() > 0)
{
this->scale(0.98, 0.98);
}
else
{
this->scale(1.02, 1.02);
}
}
_previousMousePos = event->pos();
return;
@@ -2146,21 +2047,11 @@ void GraphViewer::mouseMoveEvent(QMouseEvent * event)
void GraphViewer::mousePressEvent(QMouseEvent * event)
{
if((event->button() == Qt::LeftButton) &&
(event->modifiers() & (Qt::ShiftModifier | Qt::ControlModifier)))
{
startZoomOverlay();
_previousMousePos = event->pos();
_initialMousePos = event->pos();
event->accept();
return;
}
QGraphicsItem * item = this->scene()->itemAt(mapToScene(event->pos()), QTransform());
QGraphicsItem *item = this->scene()->itemAt(mapToScene(event->pos()), QTransform());
if(item)
{
NodeItem * nodeItem = qgraphicsitem_cast<NodeItem*>(item);
LinkItem * linkItem = qgraphicsitem_cast<LinkItem*>(item);
NodeItem *nodeItem = qgraphicsitem_cast<NodeItem*>(item);
LinkItem *linkItem = qgraphicsitem_cast<LinkItem*>(item);
if(nodeItem && nodeItem->parentItem() == _graphRoot && nodeItem->id() != 0)
{
Q_EMIT nodeSelected(nodeItem->id());
@@ -2180,19 +2071,6 @@ void GraphViewer::mousePressEvent(QMouseEvent * event)
}
}
void GraphViewer::mouseReleaseEvent(QMouseEvent * event)
{
_previousMousePos = QPoint(-1, -1);
_initialMousePos = QPoint(-1, -1);
if(_zoomOverlayActive)
{
stopZoomOverlay();
}
QGraphicsView::mouseReleaseEvent(event);
}
QIcon createIcon(const QColor & color)
{
QPixmap pixmap(50, 50);
@@ -2289,7 +2167,6 @@ void GraphViewer::contextMenuEvent(QContextMenuEvent * event)
QAction * aShowHideOdomCacheOverlay;
QAction * aOrientationENU;
QAction * aMouseTracking;
QAction * aFastZooming;
QAction * aViewPlaneXY;
QAction * aViewPlaneXZ;
QAction * aViewPlaneYZ;
@@ -2392,7 +2269,6 @@ void GraphViewer::contextMenuEvent(QContextMenuEvent * event)
aMouseTracking->setCheckable(true);
aMouseTracking->setChecked(_mouseTracking);
aMouseTracking->setEnabled(_viewPlane == XY);
aFastZooming = menu.addAction(tr("Fast Zooming..."));
aShowHideGraph->setEnabled(_viewPlane == XY);
aShowHideGlobalPath->setEnabled(_globalPathLinkItems.size());
aShowHideLocalPath->setEnabled(_localPathLinkItems.size());
@@ -2838,15 +2714,6 @@ void GraphViewer::contextMenuEvent(QContextMenuEvent * event)
{
_mouseTracking = aMouseTracking->isChecked();
}
else if(r == aFastZooming)
{
bool ok;
double value = QInputDialog::getInt(this, tr("Fast Zooming"), tr("Minimum number of nodes to raster the graph\nwhile zooming (0=disabled):"), _fastZoomMinNodes, 0, 2147483647, 100, &ok);
if(ok)
{
setFastZoomMinNodes(value);
}
}
else if(r == aViewPlaneXY)
{
this->setViewPlane(XY);
+1 -52
View File
@@ -78,8 +78,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <QtCore/QFileInfo>
#include <QMessageBox>
#include <QFileDialog>
#include <QProgressDialog>
#include <QLabel>
#include <QGraphicsEllipseItem>
#include <QDockWidget>
#include <QtCore/QBuffer>
@@ -960,7 +958,7 @@ bool MainWindow::handleEvent(UEvent* anEvent)
else
{
Q_EMIT cameraInfoReceived(sensorEvent->info());
if (_odomThread == 0 && _sensorCapture && _sensorCapture->odomProvided() && _preferencesDialog->isRGBDMode())
if (_odomThread == 0 && (_sensorCapture->odomProvided()) && _preferencesDialog->isRGBDMode())
{
OdometryInfo odomInfo;
odomInfo.reg.covariance = sensorEvent->info().odomCovariance;
@@ -5530,10 +5528,6 @@ void MainWindow::saveConfigGUI()
_preferencesDialog->saveSettings();
this->saveFigures();
this->setWindowModified(false);
// If running under sudo, the above writes recreate rtabmap.ini as root;
// restore ownership so non-root runs can still save preferences.
PreferencesDialog::restoreConfigOwnership(_preferencesDialog->getIniFilePath());
}
void MainWindow::newDatabase()
@@ -5938,31 +5932,6 @@ void MainWindow::startDetection()
Camera * camera = 0;
Lidar * lidar = 0;
// Creating the sensors below opens the devices (createLidar/createCamera/createOdomSensor ->
// init(), a few seconds for ZED/RealSense) on the GUI thread; show a busy dialog (min==max==0
// => indeterminate) so the window isn't just frozen. Hidden once all sensors are created below.
QString startLabel = tr("Starting sensor...");
QString initWarn = _preferencesDialog->getSourceInitWarningMsg();
if(!initWarn.isEmpty())
{
startLabel += "\n\n" + initWarn;
}
QProgressDialog progress(startLabel, QString(), 0, 0, this);
if(!initWarn.isEmpty())
{
QLabel * wrapLabel = new QLabel(startLabel);
wrapLabel->setWordWrap(true);
progress.setLabel(wrapLabel); // QProgressDialog takes ownership
progress.setMinimumWidth(450);
}
progress.setWindowModality(Qt::ApplicationModal);
progress.setCancelButton(0);
progress.setMinimumDuration(0);
progress.setValue(0);
progress.show();
QApplication::processEvents();
QApplication::processEvents(); // make sure it is drawn
if(_preferencesDialog->getLidarSourceDriver() != PreferencesDialog::kSrcUndef)
{
lidar = _preferencesDialog->createLidar();
@@ -6020,8 +5989,6 @@ void MainWindow::startDetection()
}
}
progress.hide(); // all sensors created/opened
_sensorCapture = new SensorCaptureThread(lidar, camera, odomSensor, extrinsics, poseTimeOffset, scaleFactor, waitTime, parameters);
_sensorCapture->setOdomAsGroundTruth(_preferencesDialog->isOdomSensorAsGt());
@@ -6262,24 +6229,6 @@ void MainWindow::stopDetection()
}
ULOGGER_DEBUG("");
// Closing the camera runs on the GUI thread in "delete _sensorCapture" below (via
// ~SensorCaptureThread -> ~Camera::close()) and can block for a while - e.g. the first 2-3
// RealSense closes per launch stall ~20s in the Motion Module stop() (librealsense warm-up).
// Show a busy dialog (min==max==0 => indeterminate) so the window isn't just frozen. It is
// declared here so it stays visible across the joins/deletes and closes on scope exit.
QProgressDialog progress(tr("Stopping sensor..."), QString(), 0, 0, this);
if(_sensorCapture)
{
progress.setWindowModality(Qt::ApplicationModal);
progress.setCancelButton(0);
progress.setMinimumDuration(0);
progress.setValue(0);
progress.show();
QApplication::processEvents();
QApplication::processEvents(); // make sure it is drawn
}
// kill the processes
if(_imuThread)
{
+26 -253
View File
@@ -39,20 +39,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <QtCore/QSettings>
#include <QtCore/QDir>
#include <QtCore/QFile>
#include <QtCore/QFileInfo>
#include <QtCore/QStandardPaths>
#include <QtCore/QTimer>
#include <QUrl>
#ifndef _WIN32
#include <unistd.h> // geteuid, chown
#include <sys/types.h>
#include <cstdlib> // atoi, getenv
#include <cerrno>
#include <cstring> // strerror
#endif
#include <QButtonGroup>
#include <QFileDialog>
#include <QInputDialog>
@@ -60,9 +49,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <QtGui/QStandardItemModel>
#include <QMainWindow>
#include <QProgressDialog>
#include <QApplication>
#include <QLabel>
#include <functional>
#include <QScrollBar>
#include <QStatusBar>
#include <QFormLayout>
@@ -451,29 +437,12 @@ PreferencesDialog::PreferencesDialog(QWidget * parent) :
_ui->comboBox_cameraStereo->setItemData(kSrcStereoZed - kSrcStereo, 0, Qt::UserRole - 1);
_ui->comboBox_odom_sensor->setItemData(2, 0, Qt::UserRole - 1);
}
else
else if(CameraStereoZed::sdkVersion() < 4)
{
if(CameraStereoZed::sdkVersion() < 5)
{
// SDK 4.X
_ui->comboBox_stereoZed_quality->setItemData(5, 0, Qt::UserRole - 1); // NEURAL_ULTRA
_ui->comboBox_stereoZed_resolution->setItemData(4, 0, Qt::UserRole - 1); //HD1536
_ui->comboBox_stereoZed_resolution->setItemData(10, 0, Qt::UserRole - 1); //XVGA
_ui->comboBox_stereoZed_resolution->setItemData(11, 0, Qt::UserRole - 1); //TXGA
}
if(CameraStereoZed::sdkVersion() < 4)
{
// SDK 3.X
_ui->comboBox_stereoZed_quality->setItemData(3, 0, Qt::UserRole - 1); // NEURAL_LIGHT
_ui->comboBox_stereoZed_resolution->setItemData(1, 0, Qt::UserRole - 1); // HD4K
_ui->comboBox_stereoZed_resolution->setItemData(2, 0, Qt::UserRole - 1); // QHDPLUS
_ui->comboBox_stereoZed_resolution->setItemData(6, 0, Qt::UserRole - 1); // HD1200
_ui->comboBox_stereoZed_resolution->setItemData(8, 0, Qt::UserRole - 1); // SVGA
}
if(CameraStereoZed::sdkVersion() < 3)
{
_ui->comboBox_stereoZed_quality->setItemData(4, 0, Qt::UserRole - 1); // NEURAL
}
_ui->comboBox_stereoZed_resolution->setItemData(1, 0, Qt::UserRole - 1);
_ui->comboBox_stereoZed_resolution->setItemData(4, 0, Qt::UserRole - 1);
_ui->comboBox_stereoZed_resolution->setItemData(6, 0, Qt::UserRole - 1);
_ui->comboBox_stereoZed_quality->setItemData(3, 0, Qt::UserRole - 1);
}
if (!CameraStereoTara::available())
{
@@ -874,7 +843,6 @@ PreferencesDialog::PreferencesDialog(QWidget * parent) :
connect(_ui->lineEdit_cameraRGBDImages_path_rgb, SIGNAL(textChanged(const QString &)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->lineEdit_cameraRGBDImages_path_depth, SIGNAL(textChanged(const QString &)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->checkBox_cameraImages_configForEachFrame, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->checkBox_cameraImages_multiCameraCalibration, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->checkBox_cameraImages_timestamps, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->checkBox_cameraImages_syncTimeStamps, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->doubleSpinBox_cameraRGBDImages_scale, SIGNAL(valueChanged(double)), this, SLOT(makeObsoleteSourcePanel()));
@@ -1016,7 +984,7 @@ PreferencesDialog::PreferencesDialog(QWidget * parent) :
connect(_ui->lineEdit_vlp16_pcap_path, SIGNAL(textChanged(const QString &)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->spinBox_vlp16_ip1, SIGNAL(valueChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->spinBox_vlp16_ip2, SIGNAL(valueChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->spinBox_vlp16_ip3, SIGNAL(valueChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->spinBox_vlp16_ip2, SIGNAL(valueChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->spinBox_vlp16_ip4, SIGNAL(valueChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->spinBox_vlp16_port, SIGNAL(valueChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->checkBox_vlp16_organized, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
@@ -2421,7 +2389,6 @@ void PreferencesDialog::resetSettings(QGroupBox * groupBox)
_ui->lineEdit_depthai_blob_path->clear();
_ui->checkBox_cameraImages_configForEachFrame->setChecked(false);
_ui->checkBox_cameraImages_multiCameraCalibration->setChecked(false);
_ui->checkBox_cameraImages_timestamps->setChecked(false);
_ui->checkBox_cameraImages_syncTimeStamps->setChecked(true);
_ui->lineEdit_cameraImages_timestamps->setText("");
@@ -2471,10 +2438,10 @@ void PreferencesDialog::resetSettings(QGroupBox * groupBox)
_ui->lineEdit_lidar_local_transform->setText("0 0 0 0 0 0");
_ui->lineEdit_vlp16_pcap_path->clear();
_ui->spinBox_vlp16_ip1->setValue(0);
_ui->spinBox_vlp16_ip2->setValue(0);
_ui->spinBox_vlp16_ip3->setValue(0);
_ui->spinBox_vlp16_ip4->setValue(0);
_ui->spinBox_vlp16_ip1->setValue(192);
_ui->spinBox_vlp16_ip2->setValue(168);
_ui->spinBox_vlp16_ip3->setValue(1);
_ui->spinBox_vlp16_ip4->setValue(201);
_ui->spinBox_vlp16_port->setValue(2368);
_ui->checkBox_vlp16_organized->setChecked(false);
_ui->checkBox_vlp16_hostTime->setChecked(true);
@@ -2590,33 +2557,12 @@ QString PreferencesDialog::getWorkingDirectory() const
QString PreferencesDialog::getIniFilePath() const
{
#ifdef WIN32
// Windows: store settings in the standard per-user config location (%LOCALAPPDATA%\rtabmap)
// instead of a Unix-style dotfile in the home root. A fixed "rtabmap" folder (not the app name)
// is used so the main GUI and DatabaseViewer share the same rtabmap.ini. Other platforms keep
// ~/.rtabmap for consistency.
QString privatePath = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + "/rtabmap";
#else
QString privatePath = QDir::homePath() + "/.rtabmap";
#endif
if(!QDir(privatePath).exists())
{
QDir().mkpath(privatePath);
QDir::home().mkdir(".rtabmap");
}
QString iniPath = privatePath + "/rtabmap.ini";
#ifdef WIN32
// One-time migration: if there's no ini at the new location but the legacy ~/.rtabmap/rtabmap.ini
// exists, copy it over so users keep their existing settings.
if(!QFile::exists(iniPath))
{
QString legacyIni = QDir::homePath() + "/.rtabmap/rtabmap.ini";
if(QFile::exists(legacyIni))
{
QFile::copy(legacyIni, iniPath);
}
}
#endif
return iniPath;
return privatePath + "/rtabmap.ini";
}
QString PreferencesDialog::getTmpIniFilePath() const
@@ -2624,41 +2570,6 @@ QString PreferencesDialog::getTmpIniFilePath() const
return getIniFilePath()+".tmp";
}
void PreferencesDialog::restoreConfigOwnership(const QString & filePath)
{
#ifndef _WIN32
// Only relevant when the process is effectively root (e.g. launched with
// sudo). getenv("SUDO_UID"/"SUDO_GID") give the invoking user.
if(geteuid() == 0)
{
const char * sudoUid = getenv("SUDO_UID");
const char * sudoGid = getenv("SUDO_GID");
if(sudoUid && sudoGid)
{
uid_t uid = (uid_t)atoi(sudoUid);
gid_t gid = (gid_t)atoi(sudoGid);
// Restore the config file and its containing directory so the user
// can still write preferences without sudo afterwards.
if(!filePath.isEmpty() && QFile::exists(filePath))
{
if(chown(filePath.toStdString().c_str(), uid, gid) != 0)
{
UWARN("Could not restore ownership of \"%s\" to uid=%d (%s).",
filePath.toStdString().c_str(), (int)uid, strerror(errno));
}
}
QString dir = QFileInfo(filePath).absolutePath();
if(!dir.isEmpty())
{
chown(dir.toStdString().c_str(), uid, gid);
}
}
}
#else
Q_UNUSED(filePath);
#endif
}
void PreferencesDialog::loadConfigFrom()
{
QString path = QFileDialog::getOpenFileName(this, tr("Load settings..."), this->getWorkingDirectory(), "*.ini");
@@ -3013,7 +2924,6 @@ void PreferencesDialog::readCameraSettings(const QString & filePath)
_ui->comboBox_cameraImages_bayerMode->setCurrentIndex(settings.value("bayerMode",_ui->comboBox_cameraImages_bayerMode->currentIndex()).toInt());
_ui->checkBox_cameraImages_configForEachFrame->setChecked(settings.value("config_each_frame",_ui->checkBox_cameraImages_configForEachFrame->isChecked()).toBool());
_ui->checkBox_cameraImages_multiCameraCalibration->setChecked(settings.value("multi_camera_calibration",_ui->checkBox_cameraImages_multiCameraCalibration->isChecked()).toBool());
_ui->checkBox_cameraImages_timestamps->setChecked(settings.value("filenames_as_stamps",_ui->checkBox_cameraImages_timestamps->isChecked()).toBool());
_ui->checkBox_cameraImages_syncTimeStamps->setChecked(settings.value("sync_stamps",_ui->checkBox_cameraImages_syncTimeStamps->isChecked()).toBool());
_ui->lineEdit_cameraImages_timestamps->setText(settings.value("stamps", _ui->lineEdit_cameraImages_timestamps->text()).toString());
@@ -3329,9 +3239,6 @@ void PreferencesDialog::writeSettings(const QString & filePath)
uInsert(_parameters, _modifiedParameters); // update cached parameters
_modifiedParameters.clear();
_obsoletePanels = kPanelDummy;
// Keep the ini writable by the invoking user even if we are running as root.
restoreConfigOwnership(filePath.isEmpty() ? getIniFilePath() : filePath);
}
void PreferencesDialog::writeGuiSettings(const QString & filePath) const
@@ -3639,7 +3546,6 @@ void PreferencesDialog::writeCameraSettings(const QString & filePath) const
settings.setValue("maxFrames", _ui->source_images_spinBox_maxFrames->value());
settings.setValue("bayerMode", _ui->comboBox_cameraImages_bayerMode->currentIndex());
settings.setValue("config_each_frame", _ui->checkBox_cameraImages_configForEachFrame->isChecked());
settings.setValue("multi_camera_calibration", _ui->checkBox_cameraImages_multiCameraCalibration->isChecked());
settings.setValue("filenames_as_stamps", _ui->checkBox_cameraImages_timestamps->isChecked());
settings.setValue("sync_stamps", _ui->checkBox_cameraImages_syncTimeStamps->isChecked());
settings.setValue("stamps", _ui->lineEdit_cameraImages_timestamps->text());
@@ -4716,12 +4622,7 @@ void PreferencesDialog::selectCalibrationPath()
{
dir = getWorkingDirectory()+"/camera_info/"+dir;
}
#if CV_MAJOR_VERSION < 3 || (CV_MAJOR_VERSION == 3 && CV_MAJOR_VERSION < 2)
QString path = QFileDialog::getOpenFileName(this, tr("Select file"), dir, tr("Calibration file (*.yaml *.xml)"));
#else
QString path = QFileDialog::getOpenFileName(this, tr("Select file"), dir, tr("Calibration file (*.yaml *.xml *.json)"));
#endif
QString path = QFileDialog::getOpenFileName(this, tr("Select file"), dir, tr("Calibration file (*.yaml)"));
if(path.size())
{
_ui->lineEdit_calibrationFile->setText(path);
@@ -6725,16 +6626,6 @@ QString PreferencesDialog::getSourceDriverStr() const
return "";
}
QString PreferencesDialog::getSourceInitWarningMsg() const
{
if(getSourceDriver() == kSrcStereoZed)
{
return QString::fromStdString(
CameraStereoZed::getNeuralModelWarning(_ui->comboBox_stereoZed_quality->currentIndex()));
}
return QString();
}
QString PreferencesDialog::getSourceDevice() const
{
return _ui->lineEdit_sourceDevice->text();
@@ -7178,7 +7069,6 @@ Camera * PreferencesDialog::createCamera(
_ui->lineEdit_cameraImages_timestamps->text().toStdString(),
_ui->checkBox_cameraImages_syncTimeStamps->isChecked());
((CameraRGBDImages*)camera)->setConfigForEachFrame(_ui->checkBox_cameraImages_configForEachFrame->isChecked());
((CameraRGBDImages*)camera)->setMultiCameraCalibration(_ui->checkBox_cameraImages_multiCameraCalibration->isChecked());
}
else if(driver == kSrcDC1394)
{
@@ -7225,7 +7115,6 @@ Camera * PreferencesDialog::createCamera(
_ui->lineEdit_cameraImages_timestamps->text().toStdString(),
_ui->checkBox_cameraImages_syncTimeStamps->isChecked());
((CameraStereoImages*)camera)->setConfigForEachFrame(_ui->checkBox_cameraImages_configForEachFrame->isChecked());
((CameraStereoImages*)camera)->setMultiCameraCalibration(_ui->checkBox_cameraImages_multiCameraCalibration->isChecked());
((CameraStereoImages*)camera)->setRightGrayScale(_ui->checkBox_stereo_rightGrayScale->isChecked());
}
else if (driver == kSrcStereoUsb)
@@ -7430,8 +7319,7 @@ Camera * PreferencesDialog::createCamera(
_ui->checkBox_cameraImages_timestamps->isChecked(),
_ui->lineEdit_cameraImages_timestamps->text().toStdString(),
_ui->checkBox_cameraImages_syncTimeStamps->isChecked());
((CameraImages*)camera)->setConfigForEachFrame(_ui->checkBox_cameraImages_configForEachFrame->isChecked());
((CameraImages*)camera)->setMultiCameraCalibration(_ui->checkBox_cameraImages_multiCameraCalibration->isChecked());
((CameraRGBDImages*)camera)->setConfigForEachFrame(_ui->checkBox_cameraImages_configForEachFrame->isChecked());
}
else if(driver == kSrcDatabase)
{
@@ -7828,30 +7716,7 @@ void PreferencesDialog::setSLAMMode(bool enabled)
void PreferencesDialog::testOdometry()
{
QString startLabel = tr("Starting camera...");
QString initWarn = getSourceInitWarningMsg();
if(!initWarn.isEmpty())
{
startLabel += "\n\n" + initWarn;
}
QProgressDialog progress(startLabel, QString(), 0, 0, this);
if(!initWarn.isEmpty())
{
QLabel * wrapLabel = new QLabel(startLabel);
wrapLabel->setWordWrap(true);
progress.setLabel(wrapLabel); // QProgressDialog takes ownership
progress.setMinimumWidth(450);
}
progress.setWindowModality(Qt::ApplicationModal);
progress.setCancelButton(0);
progress.setMinimumDuration(0);
progress.setValue(0);
progress.show();
QApplication::processEvents();
QApplication::processEvents(); // make sure it is drawn
Camera * camera = this->createCamera();
progress.hide();
if(!camera)
{
return;
@@ -7899,13 +7764,12 @@ void PreferencesDialog::testOdometry()
_ui->odom_dataBufferSize->value());
odomThread.registerToEventsManager();
// parent = 0 (not 'this'): see testCamera() - avoids the nested-modality crash.
OdometryViewer * odomViewer = new OdometryViewer(10,
_ui->spinBox_decimation_odom->value(),
0.0f,
_ui->doubleSpinBox_maxDepth_odom->value(),
this->getOdomQualityWarnThr(),
0,
this,
this->getAllParameters());
odomViewer->setWindowTitle(tr("Odometry viewer"));
odomViewer->resize(1280, 480+QPushButton().minimumHeight());
@@ -7967,79 +7831,25 @@ void PreferencesDialog::testOdometry()
}
odomViewer->exec();
UDEBUG("Dialog closed, stopping sensor...");
// Tear down the pipes first so no more events are routed to the threads/viewer being
// destroyed, then stop the threads, then delete the viewer. This avoids delivering
// events to a handler that is being torn down.
UEventsManager::removePipe(&cameraThread, &odomThread, "SensorEvent");
if(imuThread)
{
UEventsManager::removePipe(imuThread, &odomThread, "IMUEvent");
}
UEventsManager::removePipe(&odomThread, odomViewer, "OdometryEvent");
UEventsManager::removePipe(odomViewer, &odomThread, "OdometryResetEvent");
delete odomViewer;
if(imuThread)
{
imuThread->join(true);
}
// Reuse the same dialog for the close. The device close() runs in cameraThread's destructor
// at function scope end (not in join()), so 'progress' stays visible across it. On Windows
// the first 2-3 RealSense closes per launch stall ~20s in the Motion Module stop().
progress.setLabelText(tr("Closing camera..."));
progress.show();
QApplication::processEvents();
QApplication::processEvents(); // make sure it is drawn
cameraThread.join(true);
odomThread.join(true);
// deleteLater() (not delete): see testCamera() - avoids a dangling OpenGL platform
// window that crashes in QWindowsWindow::alertWindow when Preferences later closes.
odomViewer->deleteLater();
if(imuThread)
{
delete imuThread;
}
cameraThread.join(true);
odomThread.join(true);
}
void PreferencesDialog::testCamera()
{
// Not parented to 'this': the Preferences dialog is itself application-modal, and making
// the viewer a modal *child* of it (nested modality) with an OpenGL/VTK native window
// crashes Qt (QWindowsWindow::alertWindow, this==nullptr) when Preferences later closes.
// exec() below still makes the viewer application-modal, so interaction stays blocked.
CameraViewer * window = new CameraViewer(nullptr, this->getAllParameters());
CameraViewer * window = new CameraViewer(this, this->getAllParameters());
window->setWindowTitle(tr("Camera viewer"));
window->resize(1280, 480+QPushButton().minimumHeight());
window->registerToEventsManager();
QString startLabel = tr("Starting camera...");
QString initWarn = getSourceInitWarningMsg();
if(!initWarn.isEmpty())
{
startLabel += "\n\n" + initWarn;
}
QProgressDialog progress(startLabel, QString(), 0, 0, this);
if(!initWarn.isEmpty())
{
QLabel * wrapLabel = new QLabel(startLabel);
wrapLabel->setWordWrap(true);
progress.setLabel(wrapLabel); // QProgressDialog takes ownership
progress.setMinimumWidth(450);
}
progress.setWindowModality(Qt::ApplicationModal);
progress.setCancelButton(0);
progress.setMinimumDuration(0);
progress.setValue(0);
progress.show();
QApplication::processEvents();
QApplication::processEvents(); // make sure it is drawn
// createCamera() init()s the device on the GUI thread (required by ZED) and takes a few seconds.
Camera * camera = this->createCamera();
progress.hide();
if(camera)
{
SensorCaptureThread cameraThread(camera, this->getAllParameters());
@@ -8084,26 +7894,12 @@ void PreferencesDialog::testCamera()
cameraThread.start();
window->exec();
UDEBUG("Dialog closed, stopping sensor...");
UEventsManager::removePipe(&cameraThread, window, "SensorEvent");
// Reuse the same dialog for the close. The device close() runs in cameraThread's
// destructor at scope end (not in join()), so 'progress' - declared in the outer scope -
// stays visible across it. On Windows the first 2-3 RealSense closes per launch stall
// ~20s in the Motion Module stop() (librealsense warm-up); this keeps the user informed.
progress.setLabelText(tr("Closing camera..."));
progress.show();
QApplication::processEvents();
QApplication::processEvents(); // make sure it is drawn
cameraThread.join(true); // cameraThread's destructor (scope end) closes the device
// deleteLater() (not delete): defer destruction to the event loop so Qt finishes
// tearing down the OpenGL widget's context and window-proc subclass and drains
// pending activation messages first.
window->deleteLater();
delete window;
cameraThread.join(true);
}
else
{
window->deleteLater();
delete window;
}
}
@@ -8569,25 +8365,14 @@ void PreferencesDialog::calibrateOdomSensorExtrinsics()
void PreferencesDialog::testLidar()
{
// Not parented to 'this': see testCamera() - avoids the nested-modality crash.
CameraViewer * window = new CameraViewer(nullptr, this->getAllParameters());
CameraViewer * window = new CameraViewer(this, this->getAllParameters());
window->setWindowTitle(tr("Lidar viewer"));
window->setWindowFlags(Qt::Window);
window->resize(1280, 480+QPushButton().minimumHeight());
window->registerToEventsManager();
window->setDecimation(1);
QProgressDialog progress(tr("Starting lidar..."), QString(), 0, 0, this);
progress.setWindowModality(Qt::ApplicationModal);
progress.setCancelButton(0);
progress.setMinimumDuration(0);
progress.setValue(0);
progress.show();
QApplication::processEvents();
QApplication::processEvents(); // make sure it is drawn
Lidar * lidar = this->createLidar();
progress.hide();
if(lidar)
{
SensorCaptureThread lidarThread(lidar, this->getAllParameters());
@@ -8606,24 +8391,12 @@ void PreferencesDialog::testLidar()
lidarThread.start();
window->exec();
UDEBUG("Dialog closed, stopping sensor...");
UEventsManager::removePipe(&lidarThread, window, "SensorEvent");
// Reuse the same dialog for the close. The device close() runs in lidarThread's
// destructor at scope end (not in join()), so 'progress' - declared in the outer
// scope - stays visible across it.
progress.setLabelText(tr("Closing sensor..."));
progress.show();
QApplication::processEvents();
QApplication::processEvents(); // make sure it is drawn
lidarThread.join(true); // lidarThread's destructor (scope end) closes the device
// deleteLater() (not delete): see testCamera() - avoids a dangling OpenGL platform
// window that crashes in QWindowsWindow::alertWindow when Preferences later closes.
window->deleteLater();
delete window;
lidarThread.join(true);
}
else
{
window->deleteLater();
delete window;
}
}
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -1,7 +1,7 @@
<?xml version="1.0"?>
<package format="2">
<name>rtabmap</name>
<version>0.23.8</version>
<version>0.23.7</version>
<description>RTAB-Map's standalone library. RTAB-Map is a RGB-D SLAM approach with real-time constraints.</description>
<maintainer email="[email protected]">Mathieu Labbe</maintainer>
<author>Mathieu Labbe</author>
-21
View File
@@ -1,21 +0,0 @@
diff --git a/CMakeLists.txt b/CMakeLists.txt
index e671b87..2e2538e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -121,7 +121,7 @@ set( NANOFLANN_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE )
set( NANOFLANN_BUILD_TESTS OFF CACHE BOOL "" FORCE )
add_subdirectory( extern/nanoflann EXCLUDE_FROM_ALL )
target_link_libraries( CCCoreLib
- PUBLIC
+ PRIVATE
nanoflann::nanoflann
)
@@ -236,6 +236,7 @@ install(
CCCoreLib
EXPORT
CCCoreLib-targets
+ RUNTIME DESTINATION bin
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
INCLUDES DESTINATION include
-102
View File
@@ -1,102 +0,0 @@
diff --git a/freenect2.cmake.in b/freenect2.cmake.in
index 05df1af..2195bb4 100644
--- a/freenect2.cmake.in
+++ b/freenect2.cmake.in
@@ -1,10 +1,15 @@
+# Resolve paths relative to this config file (<prefix>/lib/cmake/freenect2/) so the
+# install tree stays relocatable (e.g. when shipped/unzipped as a prebuilt bundle).
+get_filename_component(_freenect2_prefix "${CMAKE_CURRENT_LIST_DIR}" DIRECTORY)
+get_filename_component(_freenect2_prefix "${_freenect2_prefix}" DIRECTORY)
+get_filename_component(_freenect2_prefix "${_freenect2_prefix}" DIRECTORY)
FIND_LIBRARY(freenect2_LIBRARY freenect2
- PATHS @CMAKE_INSTALL_PREFIX@/lib
+ PATHS "${_freenect2_prefix}/lib"
NO_DEFAULT_PATH
)
SET(freenect2_LIBRARIES ${freenect2_LIBRARY} @LIBFREENECT2_THREADING_LIBRARIES@)
FIND_PATH(freenect2_INCLUDE_DIR @PROJECT_NAME@/libfreenect2.hpp
- PATHS @CMAKE_INSTALL_PREFIX@/include
+ PATHS "${_freenect2_prefix}/include"
NO_DEFAULT_PATH
)
SET(freenect2_INCLUDE_DIRS ${freenect2_INCLUDE_DIR})
diff --git a/src/cuda_depth_packet_processor.cu b/src/cuda_depth_packet_processor.cu
index 7ca5974..95c8e11 100644
--- a/src/cuda_depth_packet_processor.cu
+++ b/src/cuda_depth_packet_processor.cu
@@ -779,12 +779,7 @@ public:
cudaDeviceProp prop;
CHECK_CUDA(cudaGetDeviceProperties(&prop, i));
- LOG_INFO << "device " << i << ": " << prop.name << " @ " << (prop.clockRate / 1000) << "MHz Memory " << (prop.totalGlobalMem >> 20) << "MB";
-
- if (prop.computeMode == cudaComputeModeProhibited) {
- LOG_INFO << " Compute Mode Prohibited";
- continue;
- }
+ LOG_INFO << "device " << i << ": " << prop.name << " Memory " << (prop.totalGlobalMem >> 20) << "MB";
if (prop.major < 1) {
LOG_INFO << " does not support CUDA";
diff --git a/src/cuda_kde_depth_packet_processor.cu b/src/cuda_kde_depth_packet_processor.cu
index 0a16f55..bca00cc 100644
--- a/src/cuda_kde_depth_packet_processor.cu
+++ b/src/cuda_kde_depth_packet_processor.cu
@@ -1192,12 +1192,7 @@ public:
cudaDeviceProp prop;
CHECK_CUDA(cudaGetDeviceProperties(&prop, i));
- LOG_INFO << "device " << i << ": " << prop.name << " @ " << (prop.clockRate / 1000) << "MHz Memory " << (prop.totalGlobalMem >> 20) << "MB";
-
- if (prop.computeMode == cudaComputeModeProhibited) {
- LOG_INFO << " Compute Mode Prohibited";
- continue;
- }
+ LOG_INFO << "device " << i << ": " << prop.name << " Memory " << (prop.totalGlobalMem >> 20) << "MB";
if (prop.major < 1) {
LOG_INFO << " does not support CUDA";
diff --git a/src/opencl_depth_packet_processor.cpp b/src/opencl_depth_packet_processor.cpp
index d8db14d..51d0883 100644
--- a/src/opencl_depth_packet_processor.cpp
+++ b/src/opencl_depth_packet_processor.cpp
@@ -251,7 +251,7 @@ public:
newIrFrame();
newDepthFrame();
- const int CL_ICDL_VERSION = 2;
+ const int clIcdlVersion = 2;
typedef cl_int (*icdloader_func)(int, size_t, void*, size_t*);
#ifdef _MSC_VER
#pragma warning(push)
@@ -269,7 +269,7 @@ public:
if (clGetICDLoaderInfoOCLICD != NULL)
{
char buf[16];
- if (clGetICDLoaderInfoOCLICD(CL_ICDL_VERSION, sizeof(buf), buf, NULL) == CL_SUCCESS)
+ if (clGetICDLoaderInfoOCLICD(clIcdlVersion, sizeof(buf), buf, NULL) == CL_SUCCESS)
{
if (strcmp(buf, "2.2.4") < 0 && strlen(buf) <= 5)
LOG_WARNING << "Your ocl-icd has deadlock bugs. Update to 2.2.4+ is recommended.";
diff --git a/src/opencl_kde_depth_packet_processor.cpp b/src/opencl_kde_depth_packet_processor.cpp
index 98dbdff..97fbc6d 100644
--- a/src/opencl_kde_depth_packet_processor.cpp
+++ b/src/opencl_kde_depth_packet_processor.cpp
@@ -259,7 +259,7 @@ public:
newIrFrame();
newDepthFrame();
- const int CL_ICDL_VERSION = 2;
+ const int clIcdlVersion = 2;
typedef cl_int (*icdloader_func)(int, size_t, void*, size_t*);
#ifdef _MSC_VER
#pragma warning(push)
@@ -277,7 +277,7 @@ public:
if (clGetICDLoaderInfoOCLICD != NULL)
{
char buf[16];
- if (clGetICDLoaderInfoOCLICD(CL_ICDL_VERSION, sizeof(buf), buf, NULL) == CL_SUCCESS)
+ if (clGetICDLoaderInfoOCLICD(clIcdlVersion, sizeof(buf), buf, NULL) == CL_SUCCESS)
{
if (strcmp(buf, "2.2.4") < 0)
LOG_WARNING << "Your ocl-icd has deadlock bugs. Update to 2.2.4+ is recommended.";
-29
View File
@@ -1,29 +0,0 @@
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 261f2cda..644e068f 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -92,17 +92,20 @@ if(OB_IS_MAIN_PROJECT)
)
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/generated/Export.h" DESTINATION include/libobsensor/h)
- install(EXPORT ${OB_SDK_LIB_NAME}Config NAMESPACE ob:: DESTINATION lib)
+ install(EXPORT ${OB_SDK_LIB_NAME}Config NAMESPACE ob:: DESTINATION lib/cmake/${OB_SDK_LIB_NAME})
include(CMakePackageConfigHelpers)
+ # Name the version file <pkg>ConfigVersion.cmake (not <pkg>Version.cmake) and
+ # install it next to the config in lib/cmake/<pkg>, so find_package(OrbbecSDK)
+ # discovers it in config mode and reads its version.
write_basic_package_version_file(
- "${CMAKE_CURRENT_BINARY_DIR}/${OB_SDK_LIB_NAME}Version.cmake"
+ "${CMAKE_CURRENT_BINARY_DIR}/${OB_SDK_LIB_NAME}ConfigVersion.cmake"
VERSION "${PROJECT_VERSION}"
COMPATIBILITY SameMajorVersion
)
install(
- FILES "${CMAKE_CURRENT_BINARY_DIR}/${OB_SDK_LIB_NAME}Version.cmake"
- DESTINATION lib
+ FILES "${CMAKE_CURRENT_BINARY_DIR}/${OB_SDK_LIB_NAME}ConfigVersion.cmake"
+ DESTINATION lib/cmake/${OB_SDK_LIB_NAME}
)
if(MSVC)
install(FILES $<TARGET_PDB_FILE:${OB_SDK_LIB_NAME}> DESTINATION bin OPTIONAL)
-1
View File
@@ -10,7 +10,6 @@ ADD_SUBDIRECTORY( EurocDataset )
ADD_SUBDIRECTORY( CidSimsDataset )
ADD_SUBDIRECTORY( Recovery )
ADD_SUBDIRECTORY( Reprocess )
ADD_SUBDIRECTORY( DatabaseUpdate )
ADD_SUBDIRECTORY( DetectMoreLoopClosures )
ADD_SUBDIRECTORY( Export )
ADD_SUBDIRECTORY( Report )
+3 -28
View File
@@ -48,11 +48,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <stdio.h>
#include <signal.h>
#include <QApplication>
#include <QSurfaceFormat>
#include <vtkVersionMacros.h>
#if VTK_MAJOR_VERSION > 9 || (VTK_MAJOR_VERSION==9 && VTK_MINOR_VERSION >= 1)
#include <QVTKRenderWidget.h>
#endif
void showUsage(const char * executableName)
{
@@ -97,7 +92,7 @@ void sighandler(int sig)
int main(int argc, char * argv[])
{
ULogger::setType(ULogger::kTypeConsole);
ULogger::setLevel(ULogger::kDebug);
ULogger::setLevel(ULogger::kInfo);
//ULogger::setPrintTime(false);
//ULogger::setPrintWhere(false);
@@ -173,6 +168,7 @@ int main(int argc, char * argv[])
}
if (strcmp(argv[i], "-pcl") == 0)
{
++i;
usePCLViz = true;
continue;
}
@@ -272,7 +268,7 @@ int main(int argc, char * argv[])
UERROR("Not built with ZED sdk support...");
exit(-1);
}
camera = new rtabmap::CameraStereoZed(deviceId.empty()?0:uStr2Int(deviceId), -1, 1, 0, 100, false, rate);
camera = new rtabmap::CameraStereoZed(deviceId.empty()?0:uStr2Int(deviceId), -1, 1, 100, false, rate);
}
else if (driver == 9)
{
@@ -374,18 +370,6 @@ int main(int argc, char * argv[])
exit(1);
}
#ifdef __APPLE__
if(usePCLViz)
{
// pcl::visualization::CloudViewer creates its render window on its own
// background thread, but macOS only allows NSWindow creation on the main
// thread, so it aborts. Fall back to the default (Qt) viewer.
printf("-pcl is not supported on macOS (pcl::visualization::CloudViewer creates its "
"window on a background thread, which macOS forbids). Using the default viewer instead.\n");
usePCLViz = false;
}
#endif
if(usePCLViz)
{
rtabmap::SensorData data = camera->takeData();
@@ -501,14 +485,6 @@ int main(int argc, char * argv[])
}
else // Use our own visualizer
{
#if VTK_MAJOR_VERSION > 9 || (VTK_MAJOR_VERSION==9 && VTK_MINOR_VERSION >= 1)
// Needed to ensure the appropriate OpenGL context is created for VTK
// rendering (QVTKOpenGLNativeWidget). Without it the embedded VTK widget
// gets an incompatible context and VTK calls a null GL function pointer
// (crash in vtkOpenGLVertexArrayObject::Bind on first paint). Must be set
// before QApplication is constructed.
QSurfaceFormat::setDefaultFormat(QVTKRenderWidget::defaultFormat());
#endif
QApplication app(argc, argv);
rtabmap::CameraViewer cameraViewer;
@@ -523,6 +499,5 @@ int main(int argc, char * argv[])
cameraViewer.exec();
cameraThread.join(true);
}
printf("Exiting cleanly.\n");
return 0;
}
-11
View File
@@ -1,11 +0,0 @@
ADD_EXECUTABLE(dbupdate main.cpp)
TARGET_LINK_LIBRARIES(dbupdate rtabmap_core)
SET_TARGET_PROPERTIES( dbupdate
PROPERTIES OUTPUT_NAME ${PROJECT_PREFIX}-dbupdate)
INSTALL(TARGETS dbupdate
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT runtime
BUNDLE DESTINATION "${CMAKE_BUNDLE_LOCATION}" COMPONENT runtime)
-109
View File
@@ -1,109 +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.
*/
#include <rtabmap/core/DBDriverSqlite3.h>
#include <rtabmap/utilite/ULogger.h>
#include <rtabmap/utilite/UFile.h>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <cstring>
using namespace rtabmap;
void showUsage()
{
printf("\nUpdate a database with a set of changes recorded in a \".dbu\" (db update) file, produced with\n"
"the --track-changes option of used by other tools. This applies the data changes only; it does NOT upgrade the database\n"
"schema/version.\n"
"\n"
"Usage:\n"
" rtabmap-dbupdate [--rewind] \"database.db\" \"changes.dbu\"\n"
"\n"
"Options:\n"
" --rewind Undo a previously applied update instead of applying it (the changeset is\n"
" inverted). The database must be in the state right after the update was applied.\n"
"\n"
"The changes must be applied to the exact database state they were recorded from (or, with\n"
"--rewind, the state right after they were applied); otherwise the operation is aborted and\n"
"the database is left unchanged.\n"
"\n");
exit(1);
}
int main(int argc, char * argv[])
{
ULogger::setType(ULogger::kTypeConsole);
ULogger::setLevel(ULogger::kWarning);
if(argc < 3)
{
showUsage();
}
bool rewind = false;
for(int i=1; i<argc-2; ++i)
{
if(std::strcmp(argv[i], "--rewind") == 0)
{
rewind = true;
}
else
{
printf("Unknown option \"%s\".\n", argv[i]);
showUsage();
}
}
std::string databasePath = argv[argc-2];
std::string updatePath = argv[argc-1];
if(!UFile::exists(databasePath))
{
printf("Database \"%s\" does not exist.\n", databasePath.c_str());
return 1;
}
if(!UFile::exists(updatePath))
{
printf("Update file \"%s\" does not exist.\n", updatePath.c_str());
return 1;
}
printf("%s database \"%s\" with changes from \"%s\"...\n",
rewind?"Rewinding":"Updating", databasePath.c_str(), updatePath.c_str());
std::string error;
if(DBDriverSqlite3::applyChangesFromFile(databasePath, updatePath, rewind, &error))
{
printf("Done! Database \"%s\" was %s successfully.\n",
databasePath.c_str(), rewind?"rewound":"updated");
return 0;
}
printf("Error: %s\n", error.c_str());
return 1;
}
-6
View File
@@ -53,12 +53,6 @@ int main(int argc, char * argv[])
QSurfaceFormat::setDefaultFormat(QVTKRenderWidget::defaultFormat());
#endif
// Recommended by VTK when using QVTKOpenGLNativeWidget (a QOpenGLWidget): let all VTK
// render widgets share a single OpenGL context, which is needed for correct rendering
// when render widgets live in / move across multiple top-level windows. Must be set
// before QApplication is constructed.
QApplication::setAttribute(Qt::AA_ShareOpenGLContexts);
#ifdef RTABMAP_PYTHON
rtabmap::PythonInterface pythonInterface;
#endif
-34
View File
@@ -59,11 +59,6 @@ void showUsage()
" --intra Add only intra-session loop closures.\n"
" --inter Add only inter-session loop closures.\n"
" --session # Add loop closures only from/to that map session ID (use -1 for last session).\n"
" --track-changes \"changes.dbu\"\n"
" Record the changes made to the database (added loop closures) and write a compact\n"
" delta to the given file. Apply it later on another copy with rtabmap-dbupdate, or\n"
" revert the loop closures added to this database with \"rtabmap-dbupdate --rewind\".\n"
" Requires the database to be version 0.24 or newer.\n"
"\n%s", Parameters::showUsage());
exit(1);
}
@@ -115,30 +110,12 @@ int main(int argc, char * argv[])
bool intraSession = false;
bool interSession = false;
int fromToMapId = -2;
std::string trackChangesOutput;
for(int i=1; i<argc-1; ++i)
{
if(std::strcmp(argv[i], "--help") == 0)
{
showUsage();
}
else if(std::strcmp(argv[i], "--track-changes") == 0)
{
++i;
if(i<argc-1)
{
trackChangesOutput = argv[i];
if(UFile::getExtension(trackChangesOutput).compare("dbu") != 0)
{
printf("--track-changes file \"%s\" must have a \".dbu\" (db update) extension!\n", trackChangesOutput.c_str());
showUsage();
}
}
else
{
showUsage();
}
}
else if(std::strcmp(argv[i], "--intra") == 0)
{
intraSession = true;
@@ -240,10 +217,6 @@ int main(int argc, char * argv[])
{
printf("Inter-session only\n");
}
if(!trackChangesOutput.empty())
{
printf("Track changes = %s\n", trackChangesOutput.c_str());
}
if(!intraSession && !interSession)
{
@@ -279,13 +252,6 @@ int main(int argc, char * argv[])
rtabmap.init(parameters, dbPath);
printf("Initialization... done! (%f sec)\n", timer.ticks());
// Record the changes made below (added loop closures) into a delta, applied later with
// rtabmap-dbupdate. Started after init so the delta reflects only what this tool changes.
if(!trackChangesOutput.empty())
{
rtabmap.trackDatabaseChanges(trackChangesOutput);
}
float xMin, yMin, cellSize;
bool haveOptimizedMap = !rtabmap.getMemory()->load2DMap(xMin, yMin, cellSize).empty();
+1 -1
View File
@@ -58,7 +58,7 @@ void showUsage()
{
printf("\nUsage:\n"
"rtabmap-lidar_viewer IP PORT driver\n"
" driver Driver number to use: 0=VLP16 (default IP and port are 0.0.0.0 2368)\n");
" driver Driver number to use: 0=VLP16 (default IP and port are 192.168.1.201 2368)\n");
exit(1);
}
-3
View File
@@ -404,16 +404,13 @@ int main (int argc, char * argv[])
{
printf("The camera is not calibrated! You should calibrate the camera first.\n");
delete camera;
return 1;
}
}
else
{
printf("Failed to initialize the camera! Please select another driver (see \"--help\").\n");
delete camera;
return 1;
}
printf("Exiting cleanly.\n");
return 0;
}
-35
View File
@@ -59,11 +59,6 @@ void showUsage(const char * exec)
" --keep_linked Keep reduced nodes linked to graph.\n"
" --pre_cleanup Remove all user loop closures linking nodes closer than %s in the graph before reducing the graph.\n"
" --radius #.# Maximum loop closure distance that can be merged. Default is 1 m. Should be > 0.\n"
" --track-changes \"changes.dbu\"\n"
" Record the changes made to the database (reduced nodes, removed links) and write a\n"
" compact delta to the given file. Apply it later on another copy with\n"
" rtabmap-dbupdate, or revert the reduction done to this database with\n"
" \"rtabmap-dbupdate --rewind\". Requires the database to be version 0.24 or newer.\n"
" --udebug/--uinfo/--warn can also be used to change verbosity.\n"
"\n", exec, Parameters::kMemSTMSize().c_str());
exit(1);
@@ -83,30 +78,12 @@ int main(int argc, char * argv[])
bool keepLinked = false;
float radius = 1.0f;
bool preCleanup = false;
std::string trackChangesOutput;
for(int i=1; i<argc; ++i)
{
if(std::strcmp(argv[i], "--help") == 0)
{
showUsage(argv[0]);
}
else if(std::strcmp(argv[i], "--track-changes") == 0)
{
++i;
if(i < argc-1)
{
trackChangesOutput = argv[i];
if(UFile::getExtension(trackChangesOutput).compare("dbu") != 0)
{
printf("--track-changes file \"%s\" must have a \".dbu\" (db update) extension!\n", trackChangesOutput.c_str());
showUsage(argv[0]);
}
}
else
{
showUsage(argv[0]);
}
}
else if(std::strcmp(argv[i], "--keep_latest") == 0)
{
keepLatest = true;
@@ -141,10 +118,6 @@ int main(int argc, char * argv[])
printf(" keep_latest = %s\n", keepLatest?"true":"false");
printf(" keep_linked = %s\n", keepLinked?"true":"false");
printf(" pre_cleanup = %s\n", preCleanup?"true":"false");
if(!trackChangesOutput.empty())
{
printf(" track-changes = %s\n", trackChangesOutput.c_str());
}
#ifdef RTABMAP_PYTHON
rtabmap::PythonInterface pythonInterface;
@@ -194,14 +167,6 @@ int main(int argc, char * argv[])
std::set<int> ids = memory.getAllSignatureIds();
printf("Initialization... done! %ld nodes loaded. (%f sec)\n", ids.size(), timer.ticks());
// Record the changes made below (reduced/merged nodes and removed links) into a delta,
// applied later on another copy with rtabmap-dbupdate. Started after init so the delta
// reflects only what this tool changes.
if(!trackChangesOutput.empty())
{
memory.trackDatabaseChanges(trackChangesOutput);
}
if(ids.empty())
{
printf("IDs are empty?! Aborting.\n");
+1 -4
View File
@@ -11,12 +11,9 @@ TARGET_LINK_LIBRARIES(report ${LIBRARIES})
SET_TARGET_PROPERTIES(report PROPERTIES
OUTPUT_NAME ${PROJECT_PREFIX}-report
COMPILE_DEFINITIONS "WITH_QT"
)
IF(WITH_QT AND (QT4_FOUND OR Qt5_FOUND OR Qt6_FOUND))
SET_TARGET_PROPERTIES(report PROPERTIES COMPILE_DEFINITIONS "WITH_QT")
ENDIF(WITH_QT AND (QT4_FOUND OR Qt5_FOUND OR Qt6_FOUND))
INSTALL(TARGETS report
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT runtime
BUNDLE DESTINATION "${CMAKE_BUNDLE_LOCATION}" COMPONENT runtime)
-42
View File
@@ -85,12 +85,6 @@ void showUsage()
" -stop_loop Stop after the first loop closure is detected.\n"
" -a Append mode: if Mem/IncrementalMemory is true, RTAB-Map is initialized with the first input database,\n"
" then next databases are reprocessed on top of the first one.\n"
" --track-changes \"changes.dbu\"\n"
" Only with append mode (-a): record the changes made on top of the first (copied) database and\n"
" write a compact delta to the given file. Apply\n"
" it later on the original database with rtabmap-dbupdate. Requires the database to be version\n"
" 0.24 or newer. Note: the recorded changes are held in memory until closing, so use this only\n"
" when appending a small amount.\n"
" -cam # Camera index to stream. Ignored if a database doesn't contain multi-camera data. Can also be multiple \n"
" indices split by spaces in a string like \"0 2\" to stream cameras 0 and 2 only.\n"
" -cam_tf \"x y z roll pitch yaw\" Camera local transform override(s) without optical rotation. For multi-cameras, \n"
@@ -280,7 +274,6 @@ int main(int argc, char * argv[])
int stopMapId = -1;
bool stopOnLoopClosure = false;
bool appendMode = false;
std::string trackChangesOutput;
std::vector<unsigned int> cameraIndices;
std::vector<Transform> cameraLocalTransformOverrides;
std::vector<float> cameraLocalTransformOffsetOverrides;
@@ -437,25 +430,6 @@ int main(int argc, char * argv[])
appendMode = true;
printf("Append mode enabled (initialize with first database then reprocess next ones)\n");
}
else if (strcmp(argv[i], "--track-changes") == 0)
{
++i;
if(i < argc - 2)
{
trackChangesOutput = argv[i];
if(UFile::getExtension(trackChangesOutput).compare("dbu") != 0)
{
printf("--track-changes file \"%s\" must have a \".dbu\" (db update) extension!\n", trackChangesOutput.c_str());
showUsage();
}
printf("Change tracking enabled, delta will be written to \"%s\" (apply later with rtabmap-dbupdate).\n", trackChangesOutput.c_str());
}
else
{
printf("Missing value for --track-changes option!\n");
showUsage();
}
}
else if (strcmp(argv[i], "-cam") == 0 || strcmp(argv[i], "--cam") == 0)
{
++i;
@@ -912,22 +886,6 @@ int main(int argc, char * argv[])
Rtabmap rtabmap;
rtabmap.init(parameters, outputDatabasePath);
// Start change tracking now, after init loaded the copied baseline database, so the
// delta captures only what reprocessing appends. Only meaningful in append mode, where
// the output starts as a copy of the first input database.
if(!trackChangesOutput.empty())
{
if(appendMode)
{
rtabmap.trackDatabaseChanges(trackChangesOutput);
}
else
{
printf("Warning: --track-changes requires append mode (-a); it is ignored because "
"append mode is not enabled.\n");
}
}
if(!incrementalMemory && locNull)
{
rtabmap.setInitialPose(Transform());
+2 -5
View File
@@ -139,13 +139,10 @@ protected:
fileToClear.close();
}
// Open in binary mode: the log formatter already emits "\r\n" line endings explicitly.
// On Windows, text mode ("a") would translate the "\n" of that "\r\n" into "\r\n" again,
// producing "\r\r\n" on disk - i.e. an extra blank line between entries.
#ifdef _MSC_VER
fopen_s(&fout_, fileName_.c_str(), "ab");
fopen_s(&fout_, fileName_.c_str(), "a");
#else
fout_ = fopen(fileName_.c_str(), "ab");
fout_ = fopen(fileName_.c_str(), "a");
#endif
if(!fout_) {
-12
View File
@@ -113,18 +113,6 @@
"kinectsdk2"
]
},
"libfreenect2-deps": {
"description": "Build libfreenect2's dependencies",
"dependencies": [
"libusb",
"libjpeg-turbo",
"glfw3",
{
"name": "pkgconf",
"host": true
}
]
},
"libpointmatcher-deps": {
"description": "Build libpointmatcher's dependencies",
"dependencies": [