mirror of
https://github.com/introlab/rtabmap.git
synced 2026-10-03 16:47:47 +08:00
Merge 6aab607a3c into 9ed83a71db
This commit is contained in:
@@ -1,2 +1,10 @@
|
||||
build/*
|
||||
build_*
|
||||
|
||||
data/tests/*.db
|
||||
data/tests/*.7z
|
||||
data/tests/*.zip
|
||||
data/tests/*.pt
|
||||
data/tests/*.pth
|
||||
data/tests/*.py
|
||||
data/tests/__pycache__/
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
name: android
|
||||
|
||||
# Android build environments (docker/noble/android/rtabmap_apiXX).
|
||||
# amd64 only, so a single native runner and no manifest juggling.
|
||||
# Note: these build FROM introlab3it/rtabmap:android-noble-deps, which is not
|
||||
# produced by any workflow; it is still built and pushed by hand.
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- 'master'
|
||||
paths: &android_paths
|
||||
# What an Android build actually compiles: CMakeLists.txt adds only
|
||||
# utilite, corelib and app under IF(ANDROID), and rtabmap.bash builds with
|
||||
# WITH_OPENGV=OFF, BUILD_EXAMPLES=OFF, BUILD_TOOLS=OFF.
|
||||
- 'CMakeLists.txt'
|
||||
- 'Version.h.in'
|
||||
- 'RTABMapConfig.cmake.in'
|
||||
- 'cmake_uninstall.cmake.in'
|
||||
- 'cmake_modules/**'
|
||||
- 'utilite/**'
|
||||
- 'corelib/**'
|
||||
- 'app/**'
|
||||
- 'docker/noble/android/**'
|
||||
- '.github/workflows/android.yml'
|
||||
pull_request:
|
||||
branches:
|
||||
- '**'
|
||||
paths: *android_paths
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
||||
|
||||
jobs:
|
||||
docker:
|
||||
# A manual dispatch is honored only on master, the only ref we push from.
|
||||
if: ${{ github.event_name != 'workflow_dispatch' || github.ref == 'refs/heads/master' }}
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
docker_tag: [android23, android24, android26, android30]
|
||||
include:
|
||||
- docker_tag: android23
|
||||
docker_tags: |
|
||||
introlab3it/rtabmap:android23
|
||||
introlab3it/rtabmap:tango
|
||||
api_version: 23
|
||||
- docker_tag: android24
|
||||
docker_tags: |
|
||||
introlab3it/rtabmap:android24
|
||||
api_version: 24
|
||||
- docker_tag: android26
|
||||
docker_tags: |
|
||||
introlab3it/rtabmap:android26
|
||||
api_version: 26
|
||||
- docker_tag: android30
|
||||
docker_tags: |
|
||||
introlab3it/rtabmap:android30
|
||||
api_version: 30
|
||||
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
-
|
||||
name: Login to DockerHub
|
||||
# Only needed when pushing; skipped on pull requests (secrets are
|
||||
# unavailable for fork PRs and we don't push there anyway).
|
||||
if: github.event_name != 'pull_request'
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
-
|
||||
name: Build and push
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
platforms: linux/amd64
|
||||
file: ./docker/noble/android/rtabmap_apiXX/Dockerfile
|
||||
build-args: |
|
||||
API_VERSION=${{ matrix.api_version }}
|
||||
tags: ${{ matrix.docker_tags }}
|
||||
cache-from: type=registry,ref=introlab3it/rtabmap:${{ matrix.docker_tag }}
|
||||
cache-to: type=inline
|
||||
@@ -4,9 +4,16 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
paths-ignore: &platform_only
|
||||
- '.github/workflows/android.yml'
|
||||
- '.github/workflows/ios.yml'
|
||||
- 'app/android/**'
|
||||
- 'app/ios/**'
|
||||
- 'docker/noble/android/**'
|
||||
pull_request:
|
||||
branches:
|
||||
- '**'
|
||||
paths-ignore: *platform_only
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
|
||||
@@ -4,9 +4,16 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
paths-ignore: &platform_only
|
||||
- '.github/workflows/android.yml'
|
||||
- '.github/workflows/ios.yml'
|
||||
- 'app/android/**'
|
||||
- 'app/ios/**'
|
||||
- 'docker/noble/android/**'
|
||||
pull_request:
|
||||
branches:
|
||||
- '**'
|
||||
paths-ignore: *platform_only
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
|
||||
@@ -4,9 +4,16 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
paths-ignore: &platform_only
|
||||
- '.github/workflows/android.yml'
|
||||
- '.github/workflows/ios.yml'
|
||||
- 'app/android/**'
|
||||
- 'app/ios/**'
|
||||
- 'docker/noble/android/**'
|
||||
pull_request:
|
||||
branches:
|
||||
- '**'
|
||||
paths-ignore: *platform_only
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
|
||||
@@ -4,9 +4,16 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
paths-ignore: &platform_only
|
||||
- '.github/workflows/android.yml'
|
||||
- '.github/workflows/ios.yml'
|
||||
- 'app/android/**'
|
||||
- 'app/ios/**'
|
||||
- 'docker/noble/android/**'
|
||||
pull_request:
|
||||
branches:
|
||||
- '**'
|
||||
paths-ignore: *platform_only
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
|
||||
@@ -4,9 +4,16 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
paths-ignore: &platform_only
|
||||
- '.github/workflows/android.yml'
|
||||
- '.github/workflows/ios.yml'
|
||||
- 'app/android/**'
|
||||
- 'app/ios/**'
|
||||
- 'docker/noble/android/**'
|
||||
pull_request:
|
||||
branches:
|
||||
- '**'
|
||||
paths-ignore: *platform_only
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
|
||||
@@ -0,0 +1,227 @@
|
||||
name: docker-ros
|
||||
|
||||
# ROS images: focal/noetic (ROS1) and jammy/humble, noble/jazzy, noble-kilted,
|
||||
# resolute (ROS2). Android images live in android.yml.
|
||||
#
|
||||
# Every arch is built natively: amd64 on an x86 runner, arm64 on a GitHub
|
||||
# arm64 runner, so no QEMU emulation is involved. Because a single Docker Hub
|
||||
# tag cannot hold two independently pushed architectures, each build pushes an
|
||||
# arch-suffixed tag (e.g. :resolute-amd64 / :resolute-arm64) and a final job
|
||||
# joins them into the real multi-arch tag (:resolute) with `imagetools create`.
|
||||
#
|
||||
# The runner image only hosts the build; it does not have to match the Ubuntu
|
||||
# release inside the image, so ubuntu-26.04{,-arm} is used for all of them
|
||||
# (ubuntu-22.04{,-arm} and ubuntu-24.04{,-arm} also exist, if ever needed).
|
||||
# That is also why focal can sit in this matrix: a 20.04 userland runs fine on
|
||||
# a newer host kernel, and ros:noetic-perception publishes a native arm64 image.
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- 'master'
|
||||
paths-ignore: &platform_only
|
||||
- '.github/workflows/android.yml'
|
||||
- '.github/workflows/ios.yml'
|
||||
- 'app/android/**'
|
||||
- 'app/ios/**'
|
||||
- 'docker/noble/android/**'
|
||||
pull_request:
|
||||
branches:
|
||||
- '**'
|
||||
paths-ignore: *platform_only
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
||||
|
||||
jobs:
|
||||
docker_deps:
|
||||
|
||||
# The ###-deps images used to be too flaky to build here at all (seg faults,
|
||||
# arm64 build timeouts under QEMU -- see
|
||||
# https://github.com/introlab/rtabmap/issues/1454) and had to be built by
|
||||
# hand from a 20.04 box with an upgraded qemu-user-static. Building each
|
||||
# arch natively removes that cause.
|
||||
# Skipped on pull requests; built and pushed only from master (push or
|
||||
# manual dispatch), since it pushes the :*-deps tags to Docker Hub.
|
||||
#
|
||||
# focal is deliberately absent: its ROS1/noetic deps are frozen, so
|
||||
# :focal-deps is built by hand on the rare occasion it changes. The focal
|
||||
# runtime image below still builds here, FROM the published :focal-deps.
|
||||
if: github.ref == 'refs/heads/master'
|
||||
|
||||
runs-on: ${{ matrix.runner }}
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
docker_dir: [jammy, noble, noble-kilted, resolute]
|
||||
arch: [amd64, arm64]
|
||||
include:
|
||||
- arch: amd64
|
||||
runner: ubuntu-26.04
|
||||
docker_platform: linux/amd64
|
||||
- arch: arm64
|
||||
runner: ubuntu-26.04-arm
|
||||
docker_platform: linux/arm64
|
||||
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
-
|
||||
name: Login to DockerHub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
-
|
||||
name: Build and push
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
push: true
|
||||
platforms: ${{ matrix.docker_platform }}
|
||||
file: ./docker/${{ matrix.docker_dir }}/deps/Dockerfile
|
||||
tags: introlab3it/rtabmap:${{ matrix.docker_dir }}-deps-${{ matrix.arch }}
|
||||
cache-from: type=registry,ref=introlab3it/rtabmap:${{ matrix.docker_dir }}-deps-${{ matrix.arch }}
|
||||
cache-to: type=inline
|
||||
|
||||
docker_deps_manifest:
|
||||
needs: docker_deps
|
||||
# Same gate as docker_deps, so both are skipped together on pull requests
|
||||
# (github.ref is refs/pull/<n>/merge there): the per-arch -deps tags this
|
||||
# joins are only ever pushed from master.
|
||||
if: ${{ !cancelled() && !failure() && github.ref == 'refs/heads/master' }}
|
||||
runs-on: ubuntu-26.04
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
docker_dir: [jammy, noble, noble-kilted, resolute]
|
||||
|
||||
steps:
|
||||
-
|
||||
name: Login to DockerHub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
-
|
||||
name: Create multi-arch manifest
|
||||
run: |
|
||||
docker buildx imagetools create \
|
||||
-t introlab3it/rtabmap:${{ matrix.docker_dir }}-deps \
|
||||
introlab3it/rtabmap:${{ matrix.docker_dir }}-deps-amd64 \
|
||||
introlab3it/rtabmap:${{ matrix.docker_dir }}-deps-arm64
|
||||
|
||||
docker:
|
||||
needs: docker_deps_manifest
|
||||
# Run even when the deps jobs are skipped (they are, on pull requests):
|
||||
# the runtime Dockerfiles then pull the :*-deps manifest already on Docker Hub.
|
||||
# A manual dispatch is honored only on master, the only ref we push from.
|
||||
if: ${{ !cancelled() && !failure() && (github.event_name != 'workflow_dispatch' || github.ref == 'refs/heads/master') }}
|
||||
runs-on: ${{ matrix.runner }}
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
docker_dir: [focal, jammy, noble, noble-kilted, resolute]
|
||||
arch: [amd64, arm64]
|
||||
include:
|
||||
- arch: amd64
|
||||
runner: ubuntu-26.04
|
||||
docker_platform: linux/amd64
|
||||
- arch: arm64
|
||||
runner: ubuntu-26.04-arm
|
||||
docker_platform: linux/arm64
|
||||
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
-
|
||||
name: Login to DockerHub
|
||||
# Only needed when pushing; skipped on pull requests (secrets are
|
||||
# unavailable for fork PRs and we don't push there anyway).
|
||||
if: github.event_name != 'pull_request'
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
-
|
||||
name: Build and push
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
platforms: ${{ matrix.docker_platform }}
|
||||
file: ./docker/${{ matrix.docker_dir }}/Dockerfile
|
||||
build-args: |
|
||||
RUN_TESTS=1
|
||||
tags: introlab3it/rtabmap:${{ matrix.docker_dir }}-${{ matrix.arch }}
|
||||
cache-from: type=registry,ref=introlab3it/rtabmap:${{ matrix.docker_dir }}-${{ matrix.arch }}
|
||||
cache-to: type=inline
|
||||
|
||||
docker_manifest:
|
||||
needs: docker
|
||||
# Nothing to join on pull requests, where the per-arch tags are never pushed.
|
||||
if: ${{ !cancelled() && !failure() && github.event_name != 'pull_request' && (github.event_name != 'workflow_dispatch' || github.ref == 'refs/heads/master') }}
|
||||
runs-on: ubuntu-26.04
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
docker_dir: [focal, jammy, noble, noble-kilted, resolute]
|
||||
include:
|
||||
- docker_dir: focal
|
||||
docker_tags: |
|
||||
introlab3it/rtabmap:focal
|
||||
introlab3it/rtabmap:20.04
|
||||
- docker_dir: jammy
|
||||
docker_tags: |
|
||||
introlab3it/rtabmap:jammy
|
||||
introlab3it/rtabmap:22.04
|
||||
- docker_dir: noble
|
||||
docker_tags: |
|
||||
introlab3it/rtabmap:noble
|
||||
introlab3it/rtabmap:24.04
|
||||
- docker_dir: noble-kilted
|
||||
docker_tags: |
|
||||
introlab3it/rtabmap:noble-kilted
|
||||
# :latest tracks the newest ROS2 image (currently resolute, ROS2 lyrical
|
||||
# on ubuntu 26.04) -- move it along with the next distro bump.
|
||||
- docker_dir: resolute
|
||||
docker_tags: |
|
||||
introlab3it/rtabmap:resolute
|
||||
introlab3it/rtabmap:26.04
|
||||
introlab3it/rtabmap:latest
|
||||
|
||||
steps:
|
||||
-
|
||||
name: Login to DockerHub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
-
|
||||
name: Create multi-arch manifest
|
||||
env:
|
||||
DOCKER_TAGS: ${{ matrix.docker_tags }}
|
||||
run: |
|
||||
tag_args=()
|
||||
while read -r tag; do
|
||||
if [ -n "$tag" ]; then
|
||||
tag_args+=(-t "$tag")
|
||||
fi
|
||||
done <<< "$DOCKER_TAGS"
|
||||
docker buildx imagetools create "${tag_args[@]}" \
|
||||
introlab3it/rtabmap:${{ matrix.docker_dir }}-amd64 \
|
||||
introlab3it/rtabmap:${{ matrix.docker_dir }}-arm64
|
||||
@@ -1,243 +0,0 @@
|
||||
name: docker
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- 'master'
|
||||
pull_request:
|
||||
branches:
|
||||
- '**'
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
||||
|
||||
jobs:
|
||||
docker_deps:
|
||||
|
||||
# Disabling ###-deps step from CI because it is too flaky (seg faults, arm64 build timeout...)
|
||||
# Only way I was able to build all images is to do it from a ubuntu 20.04 computer with:
|
||||
# $ sudo add-apt-repository ppa:canonical-server/server-backports
|
||||
# $ sudo apt-get update
|
||||
# $ sudo apt-get upgrade qemu-user-static
|
||||
# $ docker run --rm --privileged multiarch/qemu-user-static --reset -p yes -c yes
|
||||
# More info: https://github.com/introlab/rtabmap/issues/1454
|
||||
# Skipped on pull requests; built and pushed only from master (push or
|
||||
# manual dispatch), since it pushes the :*-deps tags to Docker Hub.
|
||||
if: github.ref == 'refs/heads/master'
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
docker_tag: [focal-deps, jammy-deps, noble-deps, noble-kilted-deps, resolute-deps]
|
||||
include:
|
||||
- docker_tag: focal-deps
|
||||
docker_tags: |
|
||||
introlab3it/rtabmap:focal-deps
|
||||
docker_platforms: |
|
||||
linux/amd64
|
||||
linux/arm64
|
||||
docker_path: 'focal/deps'
|
||||
- docker_tag: jammy-deps
|
||||
docker_tags: |
|
||||
introlab3it/rtabmap:jammy-deps
|
||||
docker_platforms: |
|
||||
linux/amd64
|
||||
linux/arm64
|
||||
docker_path: 'jammy/deps'
|
||||
- docker_tag: noble-deps
|
||||
docker_tags: |
|
||||
introlab3it/rtabmap:noble-deps
|
||||
docker_platforms: |
|
||||
linux/amd64
|
||||
linux/arm64
|
||||
docker_path: 'noble/deps'
|
||||
- docker_tag: noble-kilted-deps
|
||||
docker_tags: |
|
||||
introlab3it/rtabmap:noble-kilted-deps
|
||||
docker_platforms: |
|
||||
linux/amd64
|
||||
linux/arm64
|
||||
docker_path: 'noble-kilted/deps'
|
||||
- docker_tag: resolute-deps
|
||||
docker_tags: |
|
||||
introlab3it/rtabmap:resolute-deps
|
||||
docker_platforms: |
|
||||
linux/amd64
|
||||
linux/arm64
|
||||
docker_path: 'resolute/deps'
|
||||
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
-
|
||||
name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
with:
|
||||
platforms: all
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
-
|
||||
name: Login to DockerHub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
-
|
||||
name: Build and push
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
push: true
|
||||
platforms: ${{ matrix.docker_platforms }}
|
||||
file: ./docker/${{ matrix.docker_path }}/Dockerfile
|
||||
tags: ${{ matrix.docker_tags }}
|
||||
cache-from: type=registry,ref=introlab3it/rtabmap:${{ matrix.docker_tag }}
|
||||
cache-to: type=inline
|
||||
|
||||
docker:
|
||||
needs: docker_deps
|
||||
# Run even when docker_deps is skipped (it is, on pull requests).
|
||||
# A manual dispatch is honored only on master, the only ref we push from.
|
||||
if: ${{ !cancelled() && !failure() && (github.event_name != 'workflow_dispatch' || github.ref == 'refs/heads/master') }}
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
docker_tag: [bionic, focal, jammy, noble, noble-kilted, resolute, android23, android24, android26, android30]
|
||||
include:
|
||||
- docker_tag: bionic
|
||||
docker_tags: |
|
||||
introlab3it/rtabmap:bionic
|
||||
introlab3it/rtabmap:18.04
|
||||
docker_args: |
|
||||
NOT_USED=0
|
||||
docker_platforms: |
|
||||
linux/amd64
|
||||
linux/arm64
|
||||
docker_path: 'bionic'
|
||||
- docker_tag: focal
|
||||
docker_tags: |
|
||||
introlab3it/rtabmap:focal
|
||||
introlab3it/rtabmap:20.04
|
||||
introlab3it/rtabmap:latest
|
||||
docker_args: |
|
||||
NOT_USED=0
|
||||
docker_platforms: |
|
||||
linux/amd64
|
||||
linux/arm64
|
||||
docker_path: 'focal'
|
||||
- docker_tag: jammy
|
||||
docker_tags: |
|
||||
introlab3it/rtabmap:jammy
|
||||
introlab3it/rtabmap:22.04
|
||||
docker_args: |
|
||||
NOT_USED=0
|
||||
docker_platforms: |
|
||||
linux/amd64
|
||||
linux/arm64
|
||||
docker_path: 'jammy'
|
||||
- docker_tag: noble
|
||||
docker_tags: |
|
||||
introlab3it/rtabmap:noble
|
||||
introlab3it/rtabmap:24.04
|
||||
docker_args: |
|
||||
NOT_USED=0
|
||||
docker_platforms: |
|
||||
linux/amd64
|
||||
linux/arm64
|
||||
docker_path: 'noble'
|
||||
- docker_tag: noble-kilted
|
||||
docker_tags: |
|
||||
introlab3it/rtabmap:noble-kilted
|
||||
docker_args: |
|
||||
NOT_USED=0
|
||||
docker_platforms: |
|
||||
linux/amd64
|
||||
linux/arm64
|
||||
docker_path: 'noble-kilted'
|
||||
- docker_tag: resolute
|
||||
docker_tags: |
|
||||
introlab3it/rtabmap:resolute
|
||||
introlab3it/rtabmap:26.04
|
||||
docker_args: |
|
||||
NOT_USED=0
|
||||
docker_platforms: |
|
||||
linux/amd64
|
||||
linux/arm64
|
||||
docker_path: 'resolute'
|
||||
- docker_tag: android23
|
||||
docker_tags: |
|
||||
introlab3it/rtabmap:android23
|
||||
introlab3it/rtabmap:tango
|
||||
docker_args: |
|
||||
API_VERSION=23
|
||||
docker_platforms: |
|
||||
linux/amd64
|
||||
docker_path: 'noble/android/rtabmap_apiXX'
|
||||
- docker_tag: android24
|
||||
docker_tags: |
|
||||
introlab3it/rtabmap:android24
|
||||
docker_args: |
|
||||
API_VERSION=24
|
||||
docker_platforms: |
|
||||
linux/amd64
|
||||
docker_path: 'noble/android/rtabmap_apiXX'
|
||||
- docker_tag: android26
|
||||
docker_tags: |
|
||||
introlab3it/rtabmap:android26
|
||||
docker_args: |
|
||||
API_VERSION=26
|
||||
docker_platforms: |
|
||||
linux/amd64
|
||||
docker_path: 'noble/android/rtabmap_apiXX'
|
||||
- docker_tag: android30
|
||||
docker_tags: |
|
||||
introlab3it/rtabmap:android30
|
||||
docker_args: |
|
||||
API_VERSION=30
|
||||
docker_platforms: |
|
||||
linux/amd64
|
||||
docker_path: 'noble/android/rtabmap_apiXX'
|
||||
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
-
|
||||
name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
with:
|
||||
platforms: all
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
-
|
||||
name: Login to DockerHub
|
||||
# Only needed when pushing; skipped on pull requests (secrets are
|
||||
# unavailable for fork PRs and we don't push there anyway).
|
||||
if: github.event_name != 'pull_request'
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
-
|
||||
name: Build and push
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
platforms: ${{ github.event_name == 'pull_request' && 'linux/amd64' || matrix.docker_platforms }}
|
||||
file: ./docker/${{ matrix.docker_path }}/Dockerfile
|
||||
build-args: |
|
||||
${{ matrix.docker_args }}
|
||||
tags: ${{ matrix.docker_tags }}
|
||||
cache-from: type=registry,ref=introlab3it/rtabmap:${{ matrix.docker_tag }}
|
||||
cache-to: type=inline
|
||||
|
||||
@@ -42,7 +42,8 @@ This project is supported by [IntRoLab - Intelligent / Interactive / Integrated
|
||||
<a href="https://github.com/introlab/rtabmap/actions/workflows/cmake-windows.yml"><img src="https://github.com/introlab/rtabmap/actions/workflows/cmake-windows.yml/badge.svg" alt="CMake Windows Build Status"/> <br>
|
||||
<a href="https://github.com/introlab/rtabmap/actions/workflows/cmake-macos.yml"><img src="https://github.com/introlab/rtabmap/actions/workflows/cmake-macos.yml/badge.svg" alt="CMake MaCOS Build Status"/> <br>
|
||||
<a href="https://github.com/introlab/rtabmap/actions/workflows/cmake-ros.yml"><img src="https://github.com/introlab/rtabmap/actions/workflows/cmake-ros.yml/badge.svg" alt="CMake ROS Build Status"/> <br>
|
||||
<a href="https://github.com/introlab/rtabmap/actions/workflows/docker.yml"><img src="https://github.com/introlab/rtabmap/actions/workflows/docker.yml/badge.svg" alt="Docker Build Status"/>
|
||||
<a href="https://github.com/introlab/rtabmap/actions/workflows/docker-ros.yml"><img src="https://github.com/introlab/rtabmap/actions/workflows/docker-ros.yml/badge.svg" alt="Docker ROS Build Status"/> <br>
|
||||
<a href="https://github.com/introlab/rtabmap/actions/workflows/android.yml"><img src="https://github.com/introlab/rtabmap/actions/workflows/android.yml/badge.svg" alt="Android Build Status"/>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
@@ -427,6 +427,51 @@ public:
|
||||
*/
|
||||
float computeDisparity(unsigned short depth) const; // mm
|
||||
|
||||
/**
|
||||
* @brief Reprojects a 3D point of the left camera frame into both image planes (floating-point).
|
||||
*
|
||||
* The point is given in the rectified left camera frame (/camera_link), the same frame used
|
||||
* by CameraModel::reproject() of left(). The baseline is taken from the Tx of the rectified
|
||||
* projection matrices, so the horizontal shift between uLeft and uRight is the disparity of
|
||||
* that point. On a rectified stereo pair the rows are aligned, thus vRight equals vLeft.
|
||||
*
|
||||
* @note Unlike this function, CameraModel::reproject() ignores Tx, because a Tx set on a
|
||||
* single camera model is also used to tag a left camera having stereo observations
|
||||
* (see the stereo edges built by the BA optimizers).
|
||||
*
|
||||
* @param x X coordinate in the left camera space.
|
||||
* @param y Y coordinate in the left camera space.
|
||||
* @param z Z coordinate in the left camera space (must be non-zero).
|
||||
* @param[out] uLeft Output horizontal image coordinate in the left image (float).
|
||||
* @param[out] vLeft Output vertical image coordinate in the left image (float).
|
||||
* @param[out] uRight Output horizontal image coordinate in the right image (float).
|
||||
* @param[out] vRight Output vertical image coordinate in the right image (float).
|
||||
*
|
||||
* @pre `z != 0`
|
||||
*
|
||||
* @see CameraModel::reproject(), reproject(int&, int&, int&, int&)
|
||||
*/
|
||||
void reproject(float x, float y, float z, float & uLeft, float & vLeft, float & uRight, float & vRight) const;
|
||||
|
||||
/**
|
||||
* @brief Reprojects a 3D point of the left camera frame into both image planes (rounded to int).
|
||||
*
|
||||
* This version of `reproject()` returns integer pixel indices, computed from the 3D position.
|
||||
*
|
||||
* @param x X coordinate in the left camera space.
|
||||
* @param y Y coordinate in the left camera space.
|
||||
* @param z Z coordinate in the left camera space (must be non-zero).
|
||||
* @param[out] uLeft Output horizontal image coordinate in the left image (integer pixel).
|
||||
* @param[out] vLeft Output vertical image coordinate in the left image (integer pixel).
|
||||
* @param[out] uRight Output horizontal image coordinate in the right image (integer pixel).
|
||||
* @param[out] vRight Output vertical image coordinate in the right image (integer pixel).
|
||||
*
|
||||
* @pre `z != 0`
|
||||
*
|
||||
* @see CameraModel::reproject(), reproject(float&, float&, float&, float&)
|
||||
*/
|
||||
void reproject(float x, float y, float z, int & uLeft, int & vLeft, int & uRight, int & vRight) const;
|
||||
|
||||
const cv::Mat & R() const {return R_;} ///< Stereo extrinsic rotation matrix.
|
||||
const cv::Mat & T() const {return T_;} ///< Stereo extrinsic translation vector.
|
||||
const cv::Mat & E() const {return E_;} ///< Essential matrix.
|
||||
|
||||
@@ -2282,20 +2282,6 @@ std::vector<cv::KeyPoint> GFTT::generateKeypointsImpl(const cv::Mat & image, con
|
||||
_gftt->detect(imgRoi, keypoints, maskRoi); // Opencv keypoints
|
||||
}
|
||||
|
||||
if(!_useHarrisDetector && _qualityLevel>0.0)
|
||||
{
|
||||
std::vector<cv::KeyPoint> bestKeypoints;
|
||||
bestKeypoints.reserve(keypoints.size());
|
||||
for(size_t i=0; i<keypoints.size(); ++i)
|
||||
{
|
||||
if(keypoints[i].response > _qualityLevel)
|
||||
{
|
||||
bestKeypoints.push_back(keypoints[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return bestKeypoints;
|
||||
}
|
||||
return keypoints;
|
||||
}
|
||||
|
||||
|
||||
@@ -598,6 +598,30 @@ float StereoCameraModel::computeDisparity(unsigned short depth) const
|
||||
return baseline() * left().fx() / (float(depth)/1000.0f) - right().cx() + left().cx();
|
||||
}
|
||||
|
||||
void StereoCameraModel::reproject(float x, float y, float z, float & uLeft, float & vLeft, float & uRight, float & vRight) const
|
||||
{
|
||||
UASSERT(z!=0.0f);
|
||||
float invZ = 1.0f/z;
|
||||
// CameraModel::reproject() doesn't apply Tx, as a camera model with a Tx set is
|
||||
// also used to tag a left camera having stereo observations (see the stereo edges
|
||||
// of the BA optimizers). Here Tx is the baseline of the rectified projection
|
||||
// matrices (0 for the left camera, -fx*baseline for the right one), so that
|
||||
// (uLeft-uRight) is the disparity of the point.
|
||||
uLeft = (left_.fx()*x + left_.Tx())*invZ + left_.cx();
|
||||
vLeft = (left_.fy()*y)*invZ + left_.cy();
|
||||
uRight = (right_.fx()*x + right_.Tx())*invZ + right_.cx();
|
||||
vRight = (right_.fy()*y)*invZ + right_.cy();
|
||||
}
|
||||
void StereoCameraModel::reproject(float x, float y, float z, int & uLeft, int & vLeft, int & uRight, int & vRight) const
|
||||
{
|
||||
float uLeftF, vLeftF, uRightF, vRightF;
|
||||
this->reproject(x, y, z, uLeftF, vLeftF, uRightF, vRightF);
|
||||
uLeft = uLeftF;
|
||||
vLeft = vLeftF;
|
||||
uRight = uRightF;
|
||||
vRight = vRightF;
|
||||
}
|
||||
|
||||
Transform StereoCameraModel::stereoTransform() const
|
||||
{
|
||||
if(!R_.empty() && !T_.empty())
|
||||
|
||||
@@ -169,6 +169,12 @@ target_link_libraries(test_rtabmap_integration gtest_main rtabmap_core)
|
||||
# `ctest -L long`.
|
||||
add_test(NAME test_rtabmap_integration COMMAND test_rtabmap_integration)
|
||||
math(EXPR _integration_timeout "1800 * ${_test_timeout_scale}")
|
||||
# The Windows runners replay the sample DBs far slower than the Linux and macOS
|
||||
# ones (the rest of the suite takes ~3 min there, this test alone went over 30),
|
||||
# so they get twice the budget rather than lowering the bar for every platform.
|
||||
IF(WIN32)
|
||||
math(EXPR _integration_timeout "${_integration_timeout} * 2")
|
||||
ENDIF(WIN32)
|
||||
set_tests_properties(test_rtabmap_integration PROPERTIES
|
||||
TIMEOUT ${_integration_timeout}
|
||||
LABELS "long")
|
||||
|
||||
@@ -298,6 +298,45 @@ TEST_F(CameraModelTest, ReprojectInt)
|
||||
EXPECT_NEAR(v, static_cast<int>(cy_), 1);
|
||||
}
|
||||
|
||||
TEST_F(CameraModelTest, ReprojectIgnoresTx)
|
||||
{
|
||||
// A Tx set on a single camera model tags a left camera having stereo
|
||||
// observations (the BA optimizers read the baseline from it to build their
|
||||
// stereo edges), so reprojection stays that of the camera itself. Use
|
||||
// StereoCameraModel::reproject() to get both images of a stereo pair.
|
||||
double baseline = 0.12;
|
||||
CameraModel withTx(fx_, fy_, cx_, cy_, CameraModel::opticalRotation(), -baseline*fx_, imageSize_);
|
||||
CameraModel withoutTx(fx_, fy_, cx_, cy_, CameraModel::opticalRotation(), 0.0, imageSize_);
|
||||
EXPECT_DOUBLE_EQ(withTx.Tx(), -baseline*fx_);
|
||||
|
||||
float x = 0.3f, y = -0.2f, z = 2.0f;
|
||||
|
||||
float u, v, uNoTx, vNoTx;
|
||||
withTx.reproject(x, y, z, u, v);
|
||||
withoutTx.reproject(x, y, z, uNoTx, vNoTx);
|
||||
|
||||
EXPECT_FLOAT_EQ(u, uNoTx);
|
||||
EXPECT_FLOAT_EQ(v, vNoTx);
|
||||
EXPECT_FLOAT_EQ(u, static_cast<float>(fx_*x/z + cx_));
|
||||
EXPECT_FLOAT_EQ(v, static_cast<float>(fy_*y/z + cy_));
|
||||
}
|
||||
|
||||
TEST_F(CameraModelTest, ReprojectProjectRoundTripNoTx)
|
||||
{
|
||||
CameraModel model(fx_, fy_, cx_, cy_, CameraModel::opticalRotation(), 0.0, imageSize_);
|
||||
|
||||
float x = 0.35f, y = -0.15f, z = 2.5f;
|
||||
|
||||
float u, v;
|
||||
model.reproject(x, y, z, u, v);
|
||||
|
||||
float x2, y2, z2;
|
||||
model.project(u, v, z, x2, y2, z2);
|
||||
EXPECT_NEAR(x2, x, 0.001f);
|
||||
EXPECT_NEAR(y2, y, 0.001f);
|
||||
EXPECT_FLOAT_EQ(z2, z);
|
||||
}
|
||||
|
||||
// Field of View Tests
|
||||
|
||||
TEST_F(CameraModelTest, FieldOfView)
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "rtabmap/utilite/UDirectory.h"
|
||||
#include "rtabmap/utilite/UFile.h"
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
|
||||
using namespace rtabmap;
|
||||
|
||||
@@ -236,6 +237,94 @@ TEST_F(StereoCameraModelTest, ComputeDisparityZeroDepth)
|
||||
EXPECT_EQ(disparityMM, 0.0f);
|
||||
}
|
||||
|
||||
// Reprojection Tests
|
||||
|
||||
TEST_F(StereoCameraModelTest, Reproject)
|
||||
{
|
||||
StereoCameraModel model(fx_, fy_, cx_, cy_, baseline_);
|
||||
|
||||
// a point 2 m in front of the left camera, off its optical axis
|
||||
float x = 0.3f, y = -0.2f, z = 2.0f;
|
||||
|
||||
float uLeft, vLeft, uRight, vRight;
|
||||
model.reproject(x, y, z, uLeft, vLeft, uRight, vRight);
|
||||
|
||||
// the left camera has no Tx, so its image point is the one of the left model alone
|
||||
float u, v;
|
||||
model.left().reproject(x, y, z, u, v);
|
||||
EXPECT_DOUBLE_EQ(model.left().Tx(), 0.0);
|
||||
EXPECT_FLOAT_EQ(uLeft, u);
|
||||
EXPECT_FLOAT_EQ(vLeft, v);
|
||||
EXPECT_FLOAT_EQ(uLeft, static_cast<float>(fx_*x/z + cx_));
|
||||
EXPECT_FLOAT_EQ(vLeft, static_cast<float>(fy_*y/z + cy_));
|
||||
|
||||
// rectified pair: same row in both images, right point shifted by the disparity
|
||||
EXPECT_FLOAT_EQ(vRight, vLeft);
|
||||
EXPECT_NEAR(uLeft - uRight, model.computeDisparity(z), 0.001f);
|
||||
EXPECT_NEAR(uLeft - uRight, static_cast<float>(baseline_*fx_/z), 0.001f);
|
||||
}
|
||||
|
||||
TEST_F(StereoCameraModelTest, ReprojectDisparityDecreasesWithDepth)
|
||||
{
|
||||
StereoCameraModel model(fx_, fy_, cx_, cy_, baseline_);
|
||||
|
||||
float previousDisparity = std::numeric_limits<float>::max();
|
||||
for(float z=1.0f; z<=10.0f; z+=1.0f)
|
||||
{
|
||||
float uLeft, vLeft, uRight, vRight;
|
||||
model.reproject(0.0f, 0.0f, z, uLeft, vLeft, uRight, vRight);
|
||||
|
||||
// on the optical axis, the left point is the principal point
|
||||
EXPECT_FLOAT_EQ(uLeft, static_cast<float>(cx_));
|
||||
EXPECT_FLOAT_EQ(vLeft, static_cast<float>(cy_));
|
||||
|
||||
float disparity = uLeft - uRight;
|
||||
EXPECT_GT(disparity, 0.0f); // right camera on the right of the left one
|
||||
EXPECT_LT(disparity, previousDisparity);
|
||||
EXPECT_NEAR(model.computeDepth(disparity), z, 0.001f);
|
||||
previousDisparity = disparity;
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(StereoCameraModelTest, ReprojectInt)
|
||||
{
|
||||
StereoCameraModel model(fx_, fy_, cx_, cy_, baseline_);
|
||||
|
||||
float x = 0.3f, y = -0.2f, z = 2.0f;
|
||||
|
||||
float uLeftF, vLeftF, uRightF, vRightF;
|
||||
model.reproject(x, y, z, uLeftF, vLeftF, uRightF, vRightF);
|
||||
|
||||
int uLeft, vLeft, uRight, vRight;
|
||||
model.reproject(x, y, z, uLeft, vLeft, uRight, vRight);
|
||||
|
||||
EXPECT_EQ(uLeft, static_cast<int>(uLeftF));
|
||||
EXPECT_EQ(vLeft, static_cast<int>(vLeftF));
|
||||
EXPECT_EQ(uRight, static_cast<int>(uRightF));
|
||||
EXPECT_EQ(vRight, static_cast<int>(vRightF));
|
||||
}
|
||||
|
||||
TEST_F(StereoCameraModelTest, ReprojectProjectRoundTrip)
|
||||
{
|
||||
StereoCameraModel model(fx_, fy_, cx_, cy_, baseline_);
|
||||
|
||||
float x = -0.45f, y = 0.25f, z = 3.7f;
|
||||
|
||||
float uLeft, vLeft, uRight, vRight;
|
||||
model.reproject(x, y, z, uLeft, vLeft, uRight, vRight);
|
||||
|
||||
// the disparity of the reprojected pair gives the depth back...
|
||||
float depth = model.computeDepth(uLeft - uRight);
|
||||
EXPECT_NEAR(depth, z, 0.001f);
|
||||
|
||||
// ... and the left image point gives the 3D point back
|
||||
float x2, y2, z2;
|
||||
model.left().project(uLeft, vLeft, depth, x2, y2, z2);
|
||||
EXPECT_NEAR(x2, x, 0.001f);
|
||||
EXPECT_NEAR(y2, y, 0.001f);
|
||||
EXPECT_NEAR(z2, z, 0.001f);
|
||||
}
|
||||
|
||||
// Getter Tests
|
||||
|
||||
TEST_F(StereoCameraModelTest, Baseline)
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "rtabmap/core/util3d.h"
|
||||
#include "rtabmap/core/util3d_correspondences.h"
|
||||
#include "rtabmap/core/CameraModel.h"
|
||||
#include "rtabmap/core/StereoCameraModel.h"
|
||||
#include "rtabmap/utilite/UException.h"
|
||||
#include "rtabmap/utilite/UConversion.h"
|
||||
#include <pcl/io/pcd_io.h>
|
||||
@@ -82,44 +83,93 @@ TEST(Util3dCorrespondencesTest, ExtractXYZCorrespondencesNoCommonIDs) {
|
||||
EXPECT_TRUE(cloud2.empty());
|
||||
}
|
||||
|
||||
// Reprojects a fixed non-planar 3D scene in both images of a rectified stereo
|
||||
// camera. The two-view geometry must be generic: with a planar scene or a pure
|
||||
// image translation, all correspondences are related by a homography and the
|
||||
// fundamental matrix is then only defined up to a 1-parameter family
|
||||
// (F = [e']x * H for any epipole e'). RANSAC can pick a member of that family
|
||||
// which also fits an outlier, making the inlier count depend on floating-point
|
||||
// details of the platform and of the OpenCV version. Here the points span a
|
||||
// range of depths, so their disparities differ and the geometry is well
|
||||
// constrained.
|
||||
static void reprojectStereoPair(int index, pcl::PointXYZ & left, pcl::PointXYZ & right)
|
||||
{
|
||||
static const float points3d[12][3] = {
|
||||
{-0.50f, -0.40f, 2.0f}, { 0.40f, -0.30f, 3.5f}, {-0.20f, 0.50f, 2.8f},
|
||||
{ 0.60f, 0.20f, 5.0f}, {-0.60f, 0.10f, 4.2f}, { 0.10f, -0.50f, 6.5f},
|
||||
{ 0.30f, 0.45f, 3.0f}, {-0.35f, -0.15f, 7.5f}, { 0.50f, -0.05f, 2.2f},
|
||||
{-0.10f, 0.30f, 5.8f}, { 0.25f, 0.35f, 4.6f}, {-0.45f, 0.20f, 3.3f}};
|
||||
|
||||
static const StereoCameraModel model(500.0, 500.0, 320.0, 240.0, 0.12);
|
||||
|
||||
float uLeft, vLeft, uRight, vRight;
|
||||
model.reproject(points3d[index][0], points3d[index][1], points3d[index][2],
|
||||
uLeft, vLeft, uRight, vRight);
|
||||
|
||||
// extractXYZCorrespondencesRANSAC() only uses x and y, as image coordinates
|
||||
left = pcl::PointXYZ(uLeft, vLeft, 0.0f);
|
||||
right = pcl::PointXYZ(uRight, vRight, 0.0f);
|
||||
}
|
||||
|
||||
TEST(Util3dCorrespondencesTest, ExtractXYZCorrespondencesRANSACAcceptsCleanMatches) {
|
||||
std::multimap<int, pcl::PointXYZ> words1;
|
||||
std::multimap<int, pcl::PointXYZ> words2;
|
||||
|
||||
// 10 consistent matches
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
words1.insert({i, pcl::PointXYZ(i * 1.0f, exp2(i)/10.0f, 0.0f)});
|
||||
words2.insert({i, pcl::PointXYZ(i * 1.0f + 1.1f, exp2(i)/10.0f + 1.1f, 0.0f)}); // Slight noise
|
||||
// 12 consistent matches
|
||||
for (int i = 0; i < 12; ++i) {
|
||||
pcl::PointXYZ left, right;
|
||||
reprojectStereoPair(i, left, right);
|
||||
words1.insert({i, left});
|
||||
words2.insert({i, right});
|
||||
}
|
||||
|
||||
pcl::PointCloud<pcl::PointXYZ> cloud1, cloud2;
|
||||
util3d::extractXYZCorrespondencesRANSAC(words1, words2, cloud1, cloud2);
|
||||
|
||||
EXPECT_EQ(cloud1.size(), cloud2.size());
|
||||
EXPECT_GE(cloud1.size(), 8); // At least 8 inliers from 10 consistent matches
|
||||
EXPECT_EQ(cloud1.size(), 12); // every match is on its epipolar line
|
||||
}
|
||||
|
||||
TEST(Util3dCorrespondencesTest, ExtractXYZCorrespondencesRANSACRejectsOutliers) {
|
||||
std::multimap<int, pcl::PointXYZ> words1;
|
||||
std::multimap<int, pcl::PointXYZ> words2;
|
||||
|
||||
// 8 inliers
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
words1.insert({i, pcl::PointXYZ(i * 1.0f, exp2(i)/10.0f, 0.0f)});
|
||||
words2.insert({i, pcl::PointXYZ(i * 1.0f + 1.1f, exp2(i)/10.0f + 1.1f, 0.0f)}); // Slight noise
|
||||
// 12 inliers
|
||||
for (int i = 0; i < 12; ++i) {
|
||||
pcl::PointXYZ left, right;
|
||||
reprojectStereoPair(i, left, right);
|
||||
words1.insert({i, left});
|
||||
words2.insert({i, right});
|
||||
}
|
||||
|
||||
// 2 outliers
|
||||
words1.insert({100, pcl::PointXYZ(0.0f, 0.0f, 0.0f)});
|
||||
words2.insert({100, pcl::PointXYZ(100.0f, 100.0f, 0.0f)});
|
||||
words1.insert({101, pcl::PointXYZ(1.0f, 1.0f, 0.0f)});
|
||||
words2.insert({101, pcl::PointXYZ(200.0f, -50.0f, 0.0f)});
|
||||
// 3 outliers: correct point in the left image, right point moved far away from
|
||||
// the corresponding epipolar line (horizontal on a rectified stereo camera)
|
||||
const int outlierSources[3] = {0, 4, 8};
|
||||
const float outlierOffsets[3][2] = {{0.0f, 120.0f}, {0.0f, -150.0f}, {40.0f, 90.0f}};
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
pcl::PointXYZ left, right;
|
||||
reprojectStereoPair(outlierSources[i], left, right);
|
||||
right.x += outlierOffsets[i][0];
|
||||
right.y += outlierOffsets[i][1];
|
||||
words1.insert({100+i, left});
|
||||
words2.insert({100+i, right});
|
||||
}
|
||||
|
||||
pcl::PointCloud<pcl::PointXYZ> cloud1, cloud2;
|
||||
util3d::extractXYZCorrespondencesRANSAC(words1, words2, cloud1, cloud2);
|
||||
|
||||
EXPECT_EQ(cloud1.size(), cloud2.size());
|
||||
EXPECT_EQ(cloud1.size(), 8); // RANSAC should reject 2 outliers
|
||||
EXPECT_EQ(cloud1.size(), 12); // RANSAC should reject the 3 outliers
|
||||
|
||||
// none of the outliers should have survived
|
||||
for (unsigned int i = 0; i < cloud2.size(); ++i) {
|
||||
for (int j = 0; j < 3; ++j) {
|
||||
pcl::PointXYZ left, right;
|
||||
reprojectStereoPair(outlierSources[j], left, right);
|
||||
EXPECT_FALSE(cloud2[i].x == right.x + outlierOffsets[j][0] &&
|
||||
cloud2[i].y == right.y + outlierOffsets[j][1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Util3dCorrespondencesTest, ExtractXYZCorrespondencesRANSACFailsGracefullyOnTooFewMatches) {
|
||||
|
||||
@@ -1,3 +1,36 @@
|
||||
### Docker
|
||||
|
||||
* Go to the [wiki](https://github.com/introlab/rtabmap/wiki/Installation#docker) for usage examples and how to build locally the images.
|
||||
|
||||
#### Tags
|
||||
|
||||
All images are published to [introlab3it/rtabmap](https://hub.docker.com/r/introlab3it/rtabmap) as
|
||||
multi-arch manifests (`linux/amd64` and `linux/arm64`).
|
||||
|
||||
| Tag | Alias | Base | ROS |
|
||||
| --- | --- | --- | --- |
|
||||
| `resolute` | `26.04`, `latest` | Ubuntu 26.04 | ROS2 Lyrical |
|
||||
| `noble-kilted` | | Ubuntu 24.04 | ROS2 Kilted |
|
||||
| `noble` | `24.04` | Ubuntu 24.04 | ROS2 Jazzy |
|
||||
| `jammy` | `22.04` | Ubuntu 22.04 | ROS2 Humble |
|
||||
| `focal` | `20.04` | Ubuntu 20.04 | ROS1 Noetic |
|
||||
|
||||
Each image is built on top of a matching `<tag>-deps` image holding the third-party
|
||||
dependencies, so that a source change only rebuilds the top layer.
|
||||
|
||||
> [!IMPORTANT]
|
||||
> **`latest` now points to the newest ROS2 image** (`resolute`), where it used to point
|
||||
> to `focal` (ROS1 Noetic). Pulling `introlab3it/rtabmap` without a tag therefore gets you
|
||||
> a different ROS version than before. Use `introlab3it/rtabmap:focal` to stay on ROS1, or
|
||||
> pin an explicit tag in general rather than relying on `latest`.
|
||||
|
||||
`bionic` / `18.04` (ROS1 Melodic) is no longer built; the last published image stays on
|
||||
Docker Hub but will not be updated. Its Dockerfile is kept in [bionic/](bionic) for reference.
|
||||
|
||||
The `<tag>-amd64` / `<tag>-arm64` tags are per-architecture build outputs that CI joins into
|
||||
the manifests above (see [.github/workflows/docker-ros.yml](../.github/workflows/docker-ros.yml));
|
||||
use the plain tags instead.
|
||||
|
||||
Android build environments (`android23`, `android24`, `android26`, `android30`, `tango`) are
|
||||
`linux/amd64` only and are built by
|
||||
[.github/workflows/android.yml](../.github/workflows/android.yml).
|
||||
|
||||
@@ -165,6 +165,10 @@ RUN git clone --branch 4.2.0 https://github.com/opencv/opencv.git && \
|
||||
cd ../.. && \
|
||||
rm -rf opencv opencv_contrib
|
||||
|
||||
# ld.so.conf.d is read in filename order: <arch>-linux-gnu.conf sorts before
|
||||
# libc.conf (/usr/local/lib) on arm64, so source builds lose to the distro ones.
|
||||
RUN echo /usr/local/lib > /etc/ld.so.conf.d/00-usr-local.conf && ldconfig
|
||||
|
||||
RUN rm /bin/sh && ln -s /bin/bash /bin/sh
|
||||
|
||||
COPY ./docker/focal-foxy/deps/ros_entrypoint.sh /ros_entrypoint.sh
|
||||
|
||||
@@ -8,11 +8,15 @@ RUN mkdir -p /root/Documents/RTAB-Map && chmod 777 /root/Documents/RTAB-Map
|
||||
# Copy current source code
|
||||
COPY . /root/rtabmap
|
||||
|
||||
ARG RUN_TESTS=0
|
||||
|
||||
# Build RTAB-Map project
|
||||
RUN source /ros_entrypoint.sh && \
|
||||
cd rtabmap/build && \
|
||||
cmake -DWITH_ALICE_VISION=ON -DWITH_OPENGV=ON .. && \
|
||||
cmake -DWITH_ALICE_VISION=ON -DWITH_OPENGV=ON -DBUILD_TESTING=$RUN_TESTS .. && \
|
||||
make -j4 && \
|
||||
# ldconfig first: source-installed deps (GTSAM) are not yet in the loader cache.
|
||||
if [ "$RUN_TESTS" = "1" ]; then ldconfig && ctest --output-on-failure -LE "long|performance"; fi && \
|
||||
make install && \
|
||||
cd ../.. && \
|
||||
rm -rf rtabmap && \
|
||||
|
||||
@@ -190,6 +190,10 @@ RUN git clone https://github.com/laurentkneip/opengv.git && \
|
||||
cd && \
|
||||
rm -r opengv
|
||||
|
||||
# ld.so.conf.d is read in filename order: <arch>-linux-gnu.conf sorts before
|
||||
# libc.conf (/usr/local/lib) on arm64, so source builds lose to the distro ones.
|
||||
RUN echo /usr/local/lib > /etc/ld.so.conf.d/00-usr-local.conf && ldconfig
|
||||
|
||||
RUN rm /bin/sh && ln -s /bin/bash /bin/sh
|
||||
|
||||
# for jetson (https://github.com/introlab/rtabmap/issues/776)
|
||||
|
||||
@@ -74,6 +74,10 @@ RUN git clone --branch 4.5.4 https://github.com/opencv/opencv.git && \
|
||||
cd ../.. && \
|
||||
rm -rf opencv opencv_contrib
|
||||
|
||||
# ld.so.conf.d is read in filename order: <arch>-linux-gnu.conf sorts before
|
||||
# libc.conf (/usr/local/lib) on arm64, so source builds lose to the distro ones.
|
||||
RUN echo /usr/local/lib > /etc/ld.so.conf.d/00-usr-local.conf && ldconfig
|
||||
|
||||
RUN rm /bin/sh && ln -s /bin/bash /bin/sh
|
||||
|
||||
COPY ./docker/jammy-iron/deps/ros_entrypoint.sh /ros_entrypoint.sh
|
||||
|
||||
@@ -8,11 +8,15 @@ RUN mkdir -p /root/Documents/RTAB-Map && chmod 777 /root/Documents/RTAB-Map
|
||||
# Copy current source code
|
||||
COPY . /root/rtabmap
|
||||
|
||||
ARG RUN_TESTS=0
|
||||
|
||||
# Build RTAB-Map project
|
||||
RUN source /ros_entrypoint.sh && \
|
||||
cd rtabmap/build && \
|
||||
cmake -DWITH_OPENGV=ON .. && \
|
||||
cmake -DWITH_OPENGV=ON -DBUILD_TESTING=$RUN_TESTS .. && \
|
||||
make -j4 && \
|
||||
# ldconfig first: source-installed deps (GTSAM) are not yet in the loader cache.
|
||||
if [ "$RUN_TESTS" = "1" ]; then ldconfig && ctest --output-on-failure -LE "long|performance"; fi && \
|
||||
make install && \
|
||||
cd ../.. && \
|
||||
rm -rf rtabmap && \
|
||||
|
||||
@@ -98,6 +98,10 @@ RUN git clone https://github.com/laurentkneip/opengv.git && \
|
||||
cd && \
|
||||
rm -r opengv
|
||||
|
||||
# ld.so.conf.d is read in filename order: <arch>-linux-gnu.conf sorts before
|
||||
# libc.conf (/usr/local/lib) on arm64, so source builds lose to the distro ones.
|
||||
RUN echo /usr/local/lib > /etc/ld.so.conf.d/00-usr-local.conf && ldconfig
|
||||
|
||||
RUN rm /bin/sh && ln -s /bin/bash /bin/sh
|
||||
|
||||
RUN echo -e '#!/bin/bash\nset -e\n\n# setup ros2 environment\nsource "/opt/ros/humble/setup.bash" --\nexec "$@"' > /ros_entrypoint.sh
|
||||
|
||||
@@ -8,11 +8,15 @@ RUN mkdir -p /root/Documents/RTAB-Map && chmod 777 /root/Documents/RTAB-Map
|
||||
# Copy current source code
|
||||
COPY . /root/rtabmap
|
||||
|
||||
ARG RUN_TESTS=0
|
||||
|
||||
# Build RTAB-Map project
|
||||
RUN source /ros_entrypoint.sh && \
|
||||
cd rtabmap/build && \
|
||||
cmake -DWITH_OPENGV=ON .. && \
|
||||
cmake -DWITH_OPENGV=ON -DBUILD_TESTING=$RUN_TESTS .. && \
|
||||
make -j4 && \
|
||||
# ldconfig first: source-installed deps (GTSAM) are not yet in the loader cache.
|
||||
if [ "$RUN_TESTS" = "1" ]; then ldconfig && ctest --output-on-failure -LE "long|performance"; fi && \
|
||||
make install && \
|
||||
cd ../.. && \
|
||||
rm -rf rtabmap && \
|
||||
|
||||
@@ -118,6 +118,10 @@ RUN git clone https://github.com/laurentkneip/opengv.git && \
|
||||
cd && \
|
||||
rm -r opengv
|
||||
|
||||
# ld.so.conf.d is read in filename order: <arch>-linux-gnu.conf sorts before
|
||||
# libc.conf (/usr/local/lib) on arm64, so source builds lose to the distro ones.
|
||||
RUN echo /usr/local/lib > /etc/ld.so.conf.d/00-usr-local.conf && ldconfig
|
||||
|
||||
RUN rm /bin/sh && ln -s /bin/bash /bin/sh
|
||||
|
||||
RUN echo -e '#!/bin/bash\nset -e\n\n# setup ros2 environment\nsource "/opt/ros/kilted/setup.bash" --\nexec "$@"' > /ros_entrypoint.sh
|
||||
|
||||
@@ -8,11 +8,15 @@ RUN mkdir -p /root/Documents/RTAB-Map && chmod 777 /root/Documents/RTAB-Map
|
||||
# Copy current source code
|
||||
COPY . /root/rtabmap
|
||||
|
||||
ARG RUN_TESTS=0
|
||||
|
||||
# Build RTAB-Map project
|
||||
RUN source /ros_entrypoint.sh && \
|
||||
cd rtabmap/build && \
|
||||
cmake -DWITH_OPENGV=ON .. && \
|
||||
cmake -DWITH_OPENGV=ON -DBUILD_TESTING=$RUN_TESTS .. && \
|
||||
make -j4 && \
|
||||
# ldconfig first: source-installed deps (GTSAM) are not yet in the loader cache.
|
||||
if [ "$RUN_TESTS" = "1" ]; then ldconfig && ctest --output-on-failure -LE "long|performance"; fi && \
|
||||
make install && \
|
||||
cd ../.. && \
|
||||
rm -rf rtabmap && \
|
||||
|
||||
@@ -117,6 +117,10 @@ RUN git clone https://github.com/laurentkneip/opengv.git && \
|
||||
cd && \
|
||||
rm -r opengv
|
||||
|
||||
# ld.so.conf.d is read in filename order: <arch>-linux-gnu.conf sorts before
|
||||
# libc.conf (/usr/local/lib) on arm64, so source builds lose to the distro ones.
|
||||
RUN echo /usr/local/lib > /etc/ld.so.conf.d/00-usr-local.conf && ldconfig
|
||||
|
||||
RUN rm /bin/sh && ln -s /bin/bash /bin/sh
|
||||
|
||||
RUN echo -e '#!/bin/bash\nset -e\n\n# setup ros2 environment\nsource "/opt/ros/jazzy/setup.bash" --\nexec "$@"' > /ros_entrypoint.sh
|
||||
|
||||
@@ -8,11 +8,15 @@ RUN mkdir -p /root/Documents/RTAB-Map && chmod 777 /root/Documents/RTAB-Map
|
||||
# Copy current source code
|
||||
COPY . /root/rtabmap
|
||||
|
||||
ARG RUN_TESTS=0
|
||||
|
||||
# Build RTAB-Map project
|
||||
RUN source /ros_entrypoint.sh && \
|
||||
cd rtabmap/build && \
|
||||
cmake -DWITH_OPENGV=ON .. && \
|
||||
cmake -DWITH_OPENGV=ON -DBUILD_TESTING=$RUN_TESTS .. && \
|
||||
make -j4 && \
|
||||
# ldconfig first: source-installed deps (GTSAM) are not yet in the loader cache.
|
||||
if [ "$RUN_TESTS" = "1" ]; then ldconfig && ctest --output-on-failure -LE "long|performance"; fi && \
|
||||
make install && \
|
||||
cd ../.. && \
|
||||
rm -rf rtabmap && \
|
||||
|
||||
@@ -107,6 +107,10 @@ RUN git clone https://github.com/laurentkneip/opengv.git && \
|
||||
cd && \
|
||||
rm -r opengv
|
||||
|
||||
# ld.so.conf.d is read in filename order: <arch>-linux-gnu.conf sorts before
|
||||
# libc.conf (/usr/local/lib) on arm64, so source builds lose to the distro ones.
|
||||
RUN echo /usr/local/lib > /etc/ld.so.conf.d/00-usr-local.conf && ldconfig
|
||||
|
||||
RUN rm /bin/sh && ln -s /bin/bash /bin/sh
|
||||
|
||||
RUN echo -e '#!/bin/bash\nset -e\n\n# setup ros2 environment\nsource "/opt/ros/lyrical/setup.bash" --\nexec "$@"' > /ros_entrypoint.sh
|
||||
|
||||
Reference in New Issue
Block a user