Merge branch 'develop' of https://github.com/borglab/gtsam into feature/wrap_camVector
commit
a524b17cde
|
@ -66,6 +66,8 @@ function configure()
|
||||||
-DGTSAM_BUILD_EXAMPLES_ALWAYS=${GTSAM_BUILD_EXAMPLES_ALWAYS:-ON} \
|
-DGTSAM_BUILD_EXAMPLES_ALWAYS=${GTSAM_BUILD_EXAMPLES_ALWAYS:-ON} \
|
||||||
-DGTSAM_ALLOW_DEPRECATED_SINCE_V41=${GTSAM_ALLOW_DEPRECATED_SINCE_V41:-OFF} \
|
-DGTSAM_ALLOW_DEPRECATED_SINCE_V41=${GTSAM_ALLOW_DEPRECATED_SINCE_V41:-OFF} \
|
||||||
-DGTSAM_USE_QUATERNIONS=${GTSAM_USE_QUATERNIONS:-OFF} \
|
-DGTSAM_USE_QUATERNIONS=${GTSAM_USE_QUATERNIONS:-OFF} \
|
||||||
|
-DGTSAM_ROT3_EXPMAP=${GTSAM_ROT3_EXPMAP:-ON} \
|
||||||
|
-DGTSAM_POSE3_EXPMAP=${GTSAM_POSE3_EXPMAP:-ON} \
|
||||||
-DGTSAM_BUILD_WITH_MARCH_NATIVE=OFF \
|
-DGTSAM_BUILD_WITH_MARCH_NATIVE=OFF \
|
||||||
-DBOOST_ROOT=$BOOST_ROOT \
|
-DBOOST_ROOT=$BOOST_ROOT \
|
||||||
-DBoost_NO_SYSTEM_PATHS=ON \
|
-DBoost_NO_SYSTEM_PATHS=ON \
|
||||||
|
|
|
@ -48,25 +48,32 @@ jobs:
|
||||||
- name: Install (Linux)
|
- name: Install (Linux)
|
||||||
if: runner.os == 'Linux'
|
if: runner.os == 'Linux'
|
||||||
run: |
|
run: |
|
||||||
# LLVM 9 is not in Bionic's repositories so we add the official LLVM repository.
|
# LLVM (clang) 9 is not in Bionic's repositories so we add the official LLVM repository.
|
||||||
if [ "${{ matrix.compiler }}" = "clang" ] && [ "${{ matrix.version }}" = "9" ]; then
|
if [ "${{ matrix.compiler }}" = "clang" ] && [ "${{ matrix.version }}" = "9" ]; then
|
||||||
|
# (ipv4|ha).pool.sks-keyservers.net is the SKS GPG global keyserver pool
|
||||||
|
# ipv4 avoids potential timeouts because of crappy IPv6 infrastructure
|
||||||
|
# 15CF4D18AF4F7421 is the GPG key for the LLVM apt repository
|
||||||
|
# This key is not in the keystore by default for Ubuntu so we need to add it.
|
||||||
|
LLVM_KEY=15CF4D18AF4F7421
|
||||||
|
gpg --keyserver ipv4.pool.sks-keyservers.net --recv-key $LLVM_KEY || gpg --keyserver ha.pool.sks-keyservers.net --recv-key $LLVM_KEY
|
||||||
|
gpg -a --export $LLVM_KEY | sudo apt-key add -
|
||||||
sudo add-apt-repository "deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-9 main"
|
sudo add-apt-repository "deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-9 main"
|
||||||
fi
|
fi
|
||||||
sudo apt-get -y update
|
sudo apt-get -y update
|
||||||
|
|
||||||
sudo apt install cmake build-essential pkg-config libpython-dev python-numpy
|
sudo apt install cmake build-essential pkg-config libpython-dev python-numpy
|
||||||
|
|
||||||
echo "::set-env name=BOOST_ROOT::$(echo $BOOST_ROOT_1_69_0)"
|
echo "BOOST_ROOT=$(echo $BOOST_ROOT_1_72_0)" >> $GITHUB_ENV
|
||||||
echo "::set-env name=LD_LIBRARY_PATH::$(echo $BOOST_ROOT_1_69_0/lib)"
|
echo "LD_LIBRARY_PATH=$(echo $BOOST_ROOT_1_72_0/lib)" >> $GITHUB_ENV
|
||||||
|
|
||||||
if [ "${{ matrix.compiler }}" = "gcc" ]; then
|
if [ "${{ matrix.compiler }}" = "gcc" ]; then
|
||||||
sudo apt-get install -y g++-${{ matrix.version }} g++-${{ matrix.version }}-multilib
|
sudo apt-get install -y g++-${{ matrix.version }} g++-${{ matrix.version }}-multilib
|
||||||
echo "::set-env name=CC::gcc-${{ matrix.version }}"
|
echo "CC=gcc-${{ matrix.version }}" >> $GITHUB_ENV
|
||||||
echo "::set-env name=CXX::g++-${{ matrix.version }}"
|
echo "CXX=g++-${{ matrix.version }}" >> $GITHUB_ENV
|
||||||
else
|
else
|
||||||
sudo apt-get install -y clang-${{ matrix.version }} g++-multilib
|
sudo apt-get install -y clang-${{ matrix.version }} g++-multilib
|
||||||
echo "::set-env name=CC::clang-${{ matrix.version }}"
|
echo "CC=clang-${{ matrix.version }}" >> $GITHUB_ENV
|
||||||
echo "::set-env name=CXX::clang++-${{ matrix.version }}"
|
echo "CXX=clang++-${{ matrix.version }}" >> $GITHUB_ENV
|
||||||
fi
|
fi
|
||||||
- name: Check Boost version
|
- name: Check Boost version
|
||||||
if: runner.os == 'Linux'
|
if: runner.os == 'Linux'
|
||||||
|
@ -75,4 +82,10 @@ jobs:
|
||||||
- name: Build and Test (Linux)
|
- name: Build and Test (Linux)
|
||||||
if: runner.os == 'Linux'
|
if: runner.os == 'Linux'
|
||||||
run: |
|
run: |
|
||||||
bash .github/scripts/unix.sh -t
|
bash .github/scripts/unix.sh -t
|
||||||
|
- name: Upload build directory
|
||||||
|
uses: actions/upload-artifact@v2
|
||||||
|
if: matrix.build_type == 'Release'
|
||||||
|
with:
|
||||||
|
name: gtsam-${{ matrix.name }}-${{ matrix.build_type }}
|
||||||
|
path: ${{ github.workspace }}/build/
|
||||||
|
|
|
@ -35,17 +35,25 @@ jobs:
|
||||||
- name: Install (macOS)
|
- name: Install (macOS)
|
||||||
if: runner.os == 'macOS'
|
if: runner.os == 'macOS'
|
||||||
run: |
|
run: |
|
||||||
brew install cmake ninja boost
|
brew tap ProfFan/robotics
|
||||||
|
brew install cmake ninja
|
||||||
|
brew install ProfFan/robotics/boost
|
||||||
if [ "${{ matrix.compiler }}" = "gcc" ]; then
|
if [ "${{ matrix.compiler }}" = "gcc" ]; then
|
||||||
brew install gcc@${{ matrix.version }}
|
brew install gcc@${{ matrix.version }}
|
||||||
echo "::set-env name=CC::gcc-${{ matrix.version }}"
|
echo "CC=gcc-${{ matrix.version }}" >> $GITHUB_ENV
|
||||||
echo "::set-env name=CXX::g++-${{ matrix.version }}"
|
echo "CXX=g++-${{ matrix.version }}" >> $GITHUB_ENV
|
||||||
else
|
else
|
||||||
sudo xcode-select -switch /Applications/Xcode_${{ matrix.version }}.app
|
sudo xcode-select -switch /Applications/Xcode_${{ matrix.version }}.app
|
||||||
echo "::set-env name=CC::clang"
|
echo "CC=clang" >> $GITHUB_ENV
|
||||||
echo "::set-env name=CXX::clang++"
|
echo "CXX=clang++" >> $GITHUB_ENV
|
||||||
fi
|
fi
|
||||||
- name: Build and Test (macOS)
|
- name: Build and Test (macOS)
|
||||||
if: runner.os == 'macOS'
|
if: runner.os == 'macOS'
|
||||||
run: |
|
run: |
|
||||||
bash .github/scripts/unix.sh -t
|
bash .github/scripts/unix.sh -t
|
||||||
|
- name: Upload build directory
|
||||||
|
uses: actions/upload-artifact@v2
|
||||||
|
if: matrix.build_type == 'Release'
|
||||||
|
with:
|
||||||
|
name: gtsam-${{ matrix.name }}-${{ matrix.build_type }}
|
||||||
|
path: ${{ github.workspace }}/build/
|
||||||
|
|
|
@ -19,7 +19,7 @@ jobs:
|
||||||
# See https://help.github.com/en/articles/workflow-syntax-for-github-actions.
|
# See https://help.github.com/en/articles/workflow-syntax-for-github-actions.
|
||||||
name: [
|
name: [
|
||||||
ubuntu-18.04-gcc-5,
|
ubuntu-18.04-gcc-5,
|
||||||
# ubuntu-18.04-gcc-9, # TODO Disabled for now because of timeouts
|
ubuntu-18.04-gcc-9,
|
||||||
ubuntu-18.04-clang-9,
|
ubuntu-18.04-clang-9,
|
||||||
macOS-10.15-xcode-11.3.1,
|
macOS-10.15-xcode-11.3.1,
|
||||||
ubuntu-18.04-gcc-5-tbb,
|
ubuntu-18.04-gcc-5-tbb,
|
||||||
|
@ -33,11 +33,10 @@ jobs:
|
||||||
compiler: gcc
|
compiler: gcc
|
||||||
version: "5"
|
version: "5"
|
||||||
|
|
||||||
# TODO Disabled for now because of timeouts
|
- name: ubuntu-18.04-gcc-9
|
||||||
# - name: ubuntu-18.04-gcc-9
|
os: ubuntu-18.04
|
||||||
# os: ubuntu-18.04
|
compiler: gcc
|
||||||
# compiler: gcc
|
version: "9"
|
||||||
# version: "9"
|
|
||||||
|
|
||||||
- name: ubuntu-18.04-clang-9
|
- name: ubuntu-18.04-clang-9
|
||||||
os: ubuntu-18.04
|
os: ubuntu-18.04
|
||||||
|
@ -61,8 +60,14 @@ jobs:
|
||||||
- name: Install (Linux)
|
- name: Install (Linux)
|
||||||
if: runner.os == 'Linux'
|
if: runner.os == 'Linux'
|
||||||
run: |
|
run: |
|
||||||
# LLVM 9 is not in Bionic's repositories so we add the official LLVM repository.
|
|
||||||
if [ "${{ matrix.compiler }}" = "clang" ] && [ "${{ matrix.version }}" = "9" ]; then
|
if [ "${{ matrix.compiler }}" = "clang" ] && [ "${{ matrix.version }}" = "9" ]; then
|
||||||
|
# (ipv4|ha).pool.sks-keyservers.net is the SKS GPG global keyserver pool
|
||||||
|
# ipv4 avoids potential timeouts because of crappy IPv6 infrastructure
|
||||||
|
# 15CF4D18AF4F7421 is the GPG key for the LLVM apt repository
|
||||||
|
# This key is not in the keystore by default for Ubuntu so we need to add it.
|
||||||
|
LLVM_KEY=15CF4D18AF4F7421
|
||||||
|
gpg --keyserver ipv4.pool.sks-keyservers.net --recv-key $LLVM_KEY || gpg --keyserver ha.pool.sks-keyservers.net --recv-key $LLVM_KEY
|
||||||
|
gpg -a --export $LLVM_KEY | sudo apt-key add -
|
||||||
sudo add-apt-repository "deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-9 main"
|
sudo add-apt-repository "deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-9 main"
|
||||||
fi
|
fi
|
||||||
sudo apt-get -y update
|
sudo apt-get -y update
|
||||||
|
@ -71,30 +76,32 @@ jobs:
|
||||||
|
|
||||||
if [ "${{ matrix.compiler }}" = "gcc" ]; then
|
if [ "${{ matrix.compiler }}" = "gcc" ]; then
|
||||||
sudo apt-get install -y g++-${{ matrix.version }} g++-${{ matrix.version }}-multilib
|
sudo apt-get install -y g++-${{ matrix.version }} g++-${{ matrix.version }}-multilib
|
||||||
echo "::set-env name=CC::gcc-${{ matrix.version }}"
|
echo "CC=gcc-${{ matrix.version }}" >> $GITHUB_ENV
|
||||||
echo "::set-env name=CXX::g++-${{ matrix.version }}"
|
echo "CXX=g++-${{ matrix.version }}" >> $GITHUB_ENV
|
||||||
else
|
else
|
||||||
sudo apt-get install -y clang-${{ matrix.version }} g++-multilib
|
sudo apt-get install -y clang-${{ matrix.version }} g++-multilib
|
||||||
echo "::set-env name=CC::clang-${{ matrix.version }}"
|
echo "CC=clang-${{ matrix.version }}" >> $GITHUB_ENV
|
||||||
echo "::set-env name=CXX::clang++-${{ matrix.version }}"
|
echo "CXX=clang++-${{ matrix.version }}" >> $GITHUB_ENV
|
||||||
fi
|
fi
|
||||||
- name: Install (macOS)
|
- name: Install (macOS)
|
||||||
if: runner.os == 'macOS'
|
if: runner.os == 'macOS'
|
||||||
run: |
|
run: |
|
||||||
brew install cmake ninja boost
|
brew tap ProfFan/robotics
|
||||||
|
brew install cmake ninja
|
||||||
|
brew install ProfFan/robotics/boost
|
||||||
if [ "${{ matrix.compiler }}" = "gcc" ]; then
|
if [ "${{ matrix.compiler }}" = "gcc" ]; then
|
||||||
brew install gcc@${{ matrix.version }}
|
brew install gcc@${{ matrix.version }}
|
||||||
echo "::set-env name=CC::gcc-${{ matrix.version }}"
|
echo "CC=gcc-${{ matrix.version }}" >> $GITHUB_ENV
|
||||||
echo "::set-env name=CXX::g++-${{ matrix.version }}"
|
echo "CXX=g++-${{ matrix.version }}" >> $GITHUB_ENV
|
||||||
else
|
else
|
||||||
sudo xcode-select -switch /Applications/Xcode_${{ matrix.version }}.app
|
sudo xcode-select -switch /Applications/Xcode_${{ matrix.version }}.app
|
||||||
echo "::set-env name=CC::clang"
|
echo "CC=clang" >> $GITHUB_ENV
|
||||||
echo "::set-env name=CXX::clang++"
|
echo "CXX=clang++" >> $GITHUB_ENV
|
||||||
fi
|
fi
|
||||||
- name: Set GTSAM_WITH_TBB Flag
|
- name: Set GTSAM_WITH_TBB Flag
|
||||||
if: matrix.flag == 'tbb'
|
if: matrix.flag == 'tbb'
|
||||||
run: |
|
run: |
|
||||||
echo "::set-env name=GTSAM_WITH_TBB::ON"
|
echo "GTSAM_WITH_TBB=ON" >> $GITHUB_ENV
|
||||||
echo "GTSAM Uses TBB"
|
echo "GTSAM Uses TBB"
|
||||||
- name: Build (Linux)
|
- name: Build (Linux)
|
||||||
if: runner.os == 'Linux'
|
if: runner.os == 'Linux'
|
||||||
|
@ -103,4 +110,4 @@ jobs:
|
||||||
- name: Build (macOS)
|
- name: Build (macOS)
|
||||||
if: runner.os == 'macOS'
|
if: runner.os == 'macOS'
|
||||||
run: |
|
run: |
|
||||||
bash .github/scripts/python.sh
|
bash .github/scripts/python.sh
|
||||||
|
|
|
@ -24,6 +24,7 @@ jobs:
|
||||||
ubuntu-gcc-deprecated,
|
ubuntu-gcc-deprecated,
|
||||||
ubuntu-gcc-quaternions,
|
ubuntu-gcc-quaternions,
|
||||||
ubuntu-gcc-tbb,
|
ubuntu-gcc-tbb,
|
||||||
|
ubuntu-cayleymap,
|
||||||
]
|
]
|
||||||
|
|
||||||
build_type: [Debug, Release]
|
build_type: [Debug, Release]
|
||||||
|
@ -47,6 +48,12 @@ jobs:
|
||||||
version: "9"
|
version: "9"
|
||||||
flag: tbb
|
flag: tbb
|
||||||
|
|
||||||
|
- name: ubuntu-cayleymap
|
||||||
|
os: ubuntu-18.04
|
||||||
|
compiler: gcc
|
||||||
|
version: "9"
|
||||||
|
flag: cayley
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@master
|
uses: actions/checkout@master
|
||||||
|
@ -56,23 +63,25 @@ jobs:
|
||||||
run: |
|
run: |
|
||||||
# LLVM 9 is not in Bionic's repositories so we add the official LLVM repository.
|
# LLVM 9 is not in Bionic's repositories so we add the official LLVM repository.
|
||||||
if [ "${{ matrix.compiler }}" = "clang" ] && [ "${{ matrix.version }}" = "9" ]; then
|
if [ "${{ matrix.compiler }}" = "clang" ] && [ "${{ matrix.version }}" = "9" ]; then
|
||||||
|
gpg --keyserver pool.sks-keyservers.net --recv-key 15CF4D18AF4F7421
|
||||||
|
gpg -a --export 15CF4D18AF4F7421 | sudo apt-key add -
|
||||||
sudo add-apt-repository "deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-9 main"
|
sudo add-apt-repository "deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-9 main"
|
||||||
fi
|
fi
|
||||||
sudo apt-get -y update
|
sudo apt-get -y update
|
||||||
|
|
||||||
sudo apt install cmake build-essential pkg-config libpython-dev python-numpy
|
sudo apt install cmake build-essential pkg-config libpython-dev python-numpy
|
||||||
|
|
||||||
echo "::set-env name=BOOST_ROOT::$(echo $BOOST_ROOT_1_69_0)"
|
echo "BOOST_ROOT=$(echo $BOOST_ROOT_1_72_0)" >> $GITHUB_ENV
|
||||||
echo "::set-env name=LD_LIBRARY_PATH::$(echo $BOOST_ROOT_1_69_0/lib)"
|
echo "LD_LIBRARY_PATH=$(echo $BOOST_ROOT_1_72_0/lib)" >> $GITHUB_ENV
|
||||||
|
|
||||||
if [ "${{ matrix.compiler }}" = "gcc" ]; then
|
if [ "${{ matrix.compiler }}" = "gcc" ]; then
|
||||||
sudo apt-get install -y g++-${{ matrix.version }} g++-${{ matrix.version }}-multilib
|
sudo apt-get install -y g++-${{ matrix.version }} g++-${{ matrix.version }}-multilib
|
||||||
echo "::set-env name=CC::gcc-${{ matrix.version }}"
|
echo "CC=gcc-${{ matrix.version }}" >> $GITHUB_ENV
|
||||||
echo "::set-env name=CXX::g++-${{ matrix.version }}"
|
echo "CXX=g++-${{ matrix.version }}" >> $GITHUB_ENV
|
||||||
else
|
else
|
||||||
sudo apt-get install -y clang-${{ matrix.version }} g++-multilib
|
sudo apt-get install -y clang-${{ matrix.version }} g++-multilib
|
||||||
echo "::set-env name=CC::clang-${{ matrix.version }}"
|
echo "CC=clang-${{ matrix.version }}" >> $GITHUB_ENV
|
||||||
echo "::set-env name=CXX::clang++-${{ matrix.version }}"
|
echo "CXX=clang++-${{ matrix.version }}" >> $GITHUB_ENV
|
||||||
fi
|
fi
|
||||||
|
|
||||||
- name: Install (macOS)
|
- name: Install (macOS)
|
||||||
|
@ -81,32 +90,39 @@ jobs:
|
||||||
brew install cmake ninja boost
|
brew install cmake ninja boost
|
||||||
if [ "${{ matrix.compiler }}" = "gcc" ]; then
|
if [ "${{ matrix.compiler }}" = "gcc" ]; then
|
||||||
brew install gcc@${{ matrix.version }}
|
brew install gcc@${{ matrix.version }}
|
||||||
echo "::set-env name=CC::gcc-${{ matrix.version }}"
|
echo "CC=gcc-${{ matrix.version }}" >> $GITHUB_ENV
|
||||||
echo "::set-env name=CXX::g++-${{ matrix.version }}"
|
echo "CXX=g++-${{ matrix.version }}" >> $GITHUB_ENV
|
||||||
else
|
else
|
||||||
sudo xcode-select -switch /Applications/Xcode_${{ matrix.version }}.app
|
sudo xcode-select -switch /Applications/Xcode_${{ matrix.version }}.app
|
||||||
echo "::set-env name=CC::clang"
|
echo "CC=clang" >> $GITHUB_ENV
|
||||||
echo "::set-env name=CXX::clang++"
|
echo "CXX=clang++" >> $GITHUB_ENV
|
||||||
fi
|
fi
|
||||||
|
|
||||||
- name: Set Allow Deprecated Flag
|
- name: Set Allow Deprecated Flag
|
||||||
if: matrix.flag == 'deprecated'
|
if: matrix.flag == 'deprecated'
|
||||||
run: |
|
run: |
|
||||||
echo "::set-env name=GTSAM_ALLOW_DEPRECATED_SINCE_V41::ON"
|
echo "GTSAM_ALLOW_DEPRECATED_SINCE_V41=ON" >> $GITHUB_ENV
|
||||||
echo "Allow deprecated since version 4.1"
|
echo "Allow deprecated since version 4.1"
|
||||||
|
|
||||||
- name: Set Use Quaternions Flag
|
- name: Set Use Quaternions Flag
|
||||||
if: matrix.flag == 'quaternions'
|
if: matrix.flag == 'quaternions'
|
||||||
run: |
|
run: |
|
||||||
echo "::set-env name=GTSAM_USE_QUATERNIONS::ON"
|
echo "GTSAM_USE_QUATERNIONS=ON" >> $GITHUB_ENV
|
||||||
echo "Use Quaternions for rotations"
|
echo "Use Quaternions for rotations"
|
||||||
|
|
||||||
- name: Set GTSAM_WITH_TBB Flag
|
- name: Set GTSAM_WITH_TBB Flag
|
||||||
if: matrix.flag == 'tbb'
|
if: matrix.flag == 'tbb'
|
||||||
run: |
|
run: |
|
||||||
echo "::set-env name=GTSAM_WITH_TBB::ON"
|
echo "GTSAM_WITH_TBB=ON" >> $GITHUB_ENV
|
||||||
echo "GTSAM Uses TBB"
|
echo "GTSAM Uses TBB"
|
||||||
|
|
||||||
|
- name: Use Cayley Transform for Rot3
|
||||||
|
if: matrix.flag == 'cayley'
|
||||||
|
run: |
|
||||||
|
echo "GTSAM_POSE3_EXPMAP=OFF" >> $GITHUB_ENV
|
||||||
|
echo "GTSAM_ROT3_EXPMAP=OFF" >> $GITHUB_ENV
|
||||||
|
echo "GTSAM Uses Cayley map for Rot3"
|
||||||
|
|
||||||
- name: Build & Test
|
- name: Build & Test
|
||||||
run: |
|
run: |
|
||||||
bash .github/scripts/unix.sh -t
|
bash .github/scripts/unix.sh -t
|
||||||
|
|
|
@ -18,16 +18,19 @@ jobs:
|
||||||
# Github Actions requires a single row to be added to the build matrix.
|
# Github Actions requires a single row to be added to the build matrix.
|
||||||
# See https://help.github.com/en/articles/workflow-syntax-for-github-actions.
|
# See https://help.github.com/en/articles/workflow-syntax-for-github-actions.
|
||||||
name: [
|
name: [
|
||||||
windows-2016-cl,
|
#TODO This build keeps timing out, need to understand why.
|
||||||
|
# windows-2016-cl,
|
||||||
windows-2019-cl,
|
windows-2019-cl,
|
||||||
]
|
]
|
||||||
|
|
||||||
build_type: [Debug, Release]
|
build_type: [Debug, Release]
|
||||||
build_unstable: [ON]
|
build_unstable: [ON]
|
||||||
include:
|
include:
|
||||||
- name: windows-2016-cl
|
|
||||||
os: windows-2016
|
#TODO This build keeps timing out, need to understand why.
|
||||||
compiler: cl
|
# - name: windows-2016-cl
|
||||||
|
# os: windows-2016
|
||||||
|
# compiler: cl
|
||||||
|
|
||||||
- name: windows-2019-cl
|
- name: windows-2019-cl
|
||||||
os: windows-2019
|
os: windows-2019
|
||||||
|
@ -50,17 +53,17 @@ jobs:
|
||||||
# See: https://github.com/DaanDeMeyer/doctest/runs/231595515
|
# See: https://github.com/DaanDeMeyer/doctest/runs/231595515
|
||||||
# See: https://github.community/t5/GitHub-Actions/Something-is-wrong-with-the-chocolatey-installed-version-of-gcc/td-p/32413
|
# See: https://github.community/t5/GitHub-Actions/Something-is-wrong-with-the-chocolatey-installed-version-of-gcc/td-p/32413
|
||||||
scoop install gcc --global
|
scoop install gcc --global
|
||||||
echo "::set-env name=CC::gcc"
|
echo "CC=gcc" >> $GITHUB_ENV
|
||||||
echo "::set-env name=CXX::g++"
|
echo "CXX=g++" >> $GITHUB_ENV
|
||||||
} elseif ("${{ matrix.compiler }}" -eq "clang") {
|
} elseif ("${{ matrix.compiler }}" -eq "clang") {
|
||||||
echo "::set-env name=CC::clang"
|
echo "CC=clang" >> $GITHUB_ENV
|
||||||
echo "::set-env name=CXX::clang++"
|
echo "CXX=clang++" >> $GITHUB_ENV
|
||||||
} else {
|
} else {
|
||||||
echo "::set-env name=CC::${{ matrix.compiler }}"
|
echo "CC=${{ matrix.compiler }}" >> $GITHUB_ENV
|
||||||
echo "::set-env name=CXX::${{ matrix.compiler }}"
|
echo "CXX=${{ matrix.compiler }}" >> $GITHUB_ENV
|
||||||
}
|
}
|
||||||
# Scoop modifies the PATH so we make the modified PATH global.
|
# Scoop modifies the PATH so we make the modified PATH global.
|
||||||
echo "::set-env name=PATH::$env:PATH"
|
echo "$env:PATH" >> $GITHUB_PATH
|
||||||
- name: Build (Windows)
|
- name: Build (Windows)
|
||||||
if: runner.os == 'Windows'
|
if: runner.os == 'Windows'
|
||||||
run: |
|
run: |
|
||||||
|
@ -72,4 +75,10 @@ jobs:
|
||||||
cmake --build build --config ${{ matrix.build_type }} --target wrap
|
cmake --build build --config ${{ matrix.build_type }} --target wrap
|
||||||
cmake --build build --config ${{ matrix.build_type }} --target check.base
|
cmake --build build --config ${{ matrix.build_type }} --target check.base
|
||||||
cmake --build build --config ${{ matrix.build_type }} --target check.base_unstable
|
cmake --build build --config ${{ matrix.build_type }} --target check.base_unstable
|
||||||
cmake --build build --config ${{ matrix.build_type }} --target check.linear
|
cmake --build build --config ${{ matrix.build_type }} --target check.linear
|
||||||
|
- name: Upload build directory
|
||||||
|
uses: actions/upload-artifact@v2
|
||||||
|
if: matrix.build_type == 'Release'
|
||||||
|
with:
|
||||||
|
name: gtsam-${{ matrix.name }}-${{ matrix.build_type }}
|
||||||
|
path: ${{ github.workspace }}/build/
|
||||||
|
|
551
CMakeLists.txt
551
CMakeLists.txt
|
@ -22,17 +22,10 @@ set (CMAKE_PROJECT_VERSION_PATCH ${GTSAM_VERSION_PATCH})
|
||||||
###############################################################################
|
###############################################################################
|
||||||
# Gather information, perform checks, set defaults
|
# Gather information, perform checks, set defaults
|
||||||
|
|
||||||
# Set the default install path to home
|
|
||||||
#set (CMAKE_INSTALL_PREFIX ${HOME} CACHE PATH "Install prefix for library")
|
|
||||||
|
|
||||||
set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH}" "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH}" "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
||||||
include(GtsamMakeConfigFile)
|
include(GtsamMakeConfigFile)
|
||||||
include(GNUInstallDirs)
|
include(GNUInstallDirs)
|
||||||
|
|
||||||
# Record the root dir for gtsam - needed during external builds, e.g., ROS
|
|
||||||
set(GTSAM_SOURCE_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR})
|
|
||||||
message(STATUS "GTSAM_SOURCE_ROOT_DIR: [${GTSAM_SOURCE_ROOT_DIR}]")
|
|
||||||
|
|
||||||
# Load build type flags and default to Debug mode
|
# Load build type flags and default to Debug mode
|
||||||
include(GtsamBuildTypes)
|
include(GtsamBuildTypes)
|
||||||
|
|
||||||
|
@ -45,399 +38,21 @@ if(${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_BINARY_DIR})
|
||||||
message(FATAL_ERROR "In-source builds not allowed. Please make a new directory (called a build directory) and run CMake from there. You may need to remove CMakeCache.txt. ")
|
message(FATAL_ERROR "In-source builds not allowed. Please make a new directory (called a build directory) and run CMake from there. You may need to remove CMakeCache.txt. ")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# See whether gtsam_unstable is available (it will be present only if we're using a git checkout)
|
include(cmake/HandleBoost.cmake) # Boost
|
||||||
if(EXISTS "${PROJECT_SOURCE_DIR}/gtsam_unstable" AND IS_DIRECTORY "${PROJECT_SOURCE_DIR}/gtsam_unstable")
|
include(cmake/HandleCCache.cmake) # ccache
|
||||||
set(GTSAM_UNSTABLE_AVAILABLE 1)
|
include(cmake/HandleCPack.cmake) # CPack
|
||||||
else()
|
include(cmake/HandleEigen.cmake) # Eigen3
|
||||||
set(GTSAM_UNSTABLE_AVAILABLE 0)
|
include(cmake/HandleGeneralOptions.cmake) # CMake build options
|
||||||
endif()
|
include(cmake/HandleMKL.cmake) # MKL
|
||||||
|
include(cmake/HandleOpenMP.cmake) # OpenMP
|
||||||
|
include(cmake/HandlePerfTools.cmake) # Google perftools
|
||||||
|
include(cmake/HandlePython.cmake) # Python options and commands
|
||||||
|
include(cmake/HandleTBB.cmake) # TBB
|
||||||
|
include(cmake/HandleUninstall.cmake) # for "make uninstall"
|
||||||
|
|
||||||
# ----------------------------------------------------------------------------
|
include(cmake/HandleAllocators.cmake) # Must be after tbb, pertools
|
||||||
# Uninstall target, for "make uninstall"
|
|
||||||
# ----------------------------------------------------------------------------
|
|
||||||
configure_file(
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in"
|
|
||||||
"${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
|
|
||||||
IMMEDIATE @ONLY)
|
|
||||||
|
|
||||||
add_custom_target(uninstall
|
include(cmake/HandleGlobalBuildFlags.cmake) # Build flags
|
||||||
"${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake")
|
|
||||||
|
|
||||||
|
|
||||||
###############################################################################
|
|
||||||
# Set up options
|
|
||||||
|
|
||||||
# Configurable Options
|
|
||||||
if(GTSAM_UNSTABLE_AVAILABLE)
|
|
||||||
option(GTSAM_BUILD_UNSTABLE "Enable/Disable libgtsam_unstable" ON)
|
|
||||||
option(GTSAM_UNSTABLE_BUILD_PYTHON "Enable/Disable Python wrapper for libgtsam_unstable" ON)
|
|
||||||
option(GTSAM_UNSTABLE_INSTALL_MATLAB_TOOLBOX "Enable/Disable MATLAB wrapper for libgtsam_unstable" OFF)
|
|
||||||
endif()
|
|
||||||
option(BUILD_SHARED_LIBS "Build shared gtsam library, instead of static" ON)
|
|
||||||
option(GTSAM_USE_QUATERNIONS "Enable/Disable using an internal Quaternion representation for rotations instead of rotation matrices. If enable, Rot3::EXPMAP is enforced by default." OFF)
|
|
||||||
option(GTSAM_POSE3_EXPMAP "Enable/Disable using Pose3::EXPMAP as the default mode. If disabled, Pose3::FIRST_ORDER will be used." ON)
|
|
||||||
option(GTSAM_ROT3_EXPMAP "Ignore if GTSAM_USE_QUATERNIONS is OFF (Rot3::EXPMAP by default). Otherwise, enable Rot3::EXPMAP, or if disabled, use Rot3::CAYLEY." ON)
|
|
||||||
option(GTSAM_ENABLE_CONSISTENCY_CHECKS "Enable/Disable expensive consistency checks" OFF)
|
|
||||||
option(GTSAM_WITH_TBB "Use Intel Threaded Building Blocks (TBB) if available" ON)
|
|
||||||
option(GTSAM_WITH_EIGEN_MKL "Eigen will use Intel MKL if available" OFF)
|
|
||||||
option(GTSAM_WITH_EIGEN_MKL_OPENMP "Eigen, when using Intel MKL, will also use OpenMP for multithreading if available" OFF)
|
|
||||||
option(GTSAM_THROW_CHEIRALITY_EXCEPTION "Throw exception when a triangulated point is behind a camera" ON)
|
|
||||||
option(GTSAM_BUILD_PYTHON "Enable/Disable building & installation of Python module with pybind11" OFF)
|
|
||||||
option(GTSAM_ALLOW_DEPRECATED_SINCE_V41 "Allow use of methods/functions deprecated in GTSAM 4.1" ON)
|
|
||||||
option(GTSAM_SUPPORT_NESTED_DISSECTION "Support Metis-based nested dissection" ON)
|
|
||||||
option(GTSAM_TANGENT_PREINTEGRATION "Use new ImuFactor with integration on tangent space" ON)
|
|
||||||
if(NOT MSVC AND NOT XCODE_VERSION)
|
|
||||||
option(GTSAM_BUILD_WITH_CCACHE "Use ccache compiler cache" ON)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT MSVC AND NOT XCODE_VERSION)
|
|
||||||
# Set the build type to upper case for downstream use
|
|
||||||
string(TOUPPER "${CMAKE_BUILD_TYPE}" CMAKE_BUILD_TYPE_UPPER)
|
|
||||||
|
|
||||||
# Set the GTSAM_BUILD_TAG variable.
|
|
||||||
# If build type is Release, set to blank (""), else set to the build type.
|
|
||||||
if(${CMAKE_BUILD_TYPE_UPPER} STREQUAL "RELEASE")
|
|
||||||
set(GTSAM_BUILD_TAG "") # Don't create release mode tag on installed directory
|
|
||||||
else()
|
|
||||||
set(GTSAM_BUILD_TAG "${CMAKE_BUILD_TYPE}")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Options relating to MATLAB wrapper
|
|
||||||
# TODO: Check for matlab mex binary before handling building of binaries
|
|
||||||
option(GTSAM_INSTALL_MATLAB_TOOLBOX "Enable/Disable installation of matlab toolbox" OFF)
|
|
||||||
set(GTSAM_PYTHON_VERSION "Default" CACHE STRING "The version of Python to build the wrappers against.")
|
|
||||||
|
|
||||||
# Check / set dependent variables for MATLAB wrapper
|
|
||||||
if(GTSAM_INSTALL_MATLAB_TOOLBOX AND GTSAM_BUILD_TYPE_POSTFIXES)
|
|
||||||
set(CURRENT_POSTFIX ${CMAKE_${CMAKE_BUILD_TYPE_UPPER}_POSTFIX})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(GTSAM_INSTALL_MATLAB_TOOLBOX AND NOT BUILD_SHARED_LIBS)
|
|
||||||
message(FATAL_ERROR "GTSAM_INSTALL_MATLAB_TOOLBOX and BUILD_SHARED_LIBS=OFF. The MATLAB wrapper cannot be compiled with a static GTSAM library because mex modules are themselves shared libraries. If you want a self-contained mex module, enable GTSAM_MEX_BUILD_STATIC_MODULE instead of BUILD_SHARED_LIBS=OFF.")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(GTSAM_BUILD_PYTHON)
|
|
||||||
if(${GTSAM_PYTHON_VERSION} STREQUAL "Default")
|
|
||||||
# Get info about the Python3 interpreter
|
|
||||||
# https://cmake.org/cmake/help/latest/module/FindPython3.html#module:FindPython3
|
|
||||||
find_package(Python3 COMPONENTS Interpreter Development)
|
|
||||||
|
|
||||||
if(NOT ${Python3_FOUND})
|
|
||||||
message(FATAL_ERROR "Cannot find Python3 interpreter. Please install Python >= 3.6.")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(GTSAM_PYTHON_VERSION "${Python3_VERSION_MAJOR}.${Python3_VERSION_MINOR}"
|
|
||||||
CACHE
|
|
||||||
STRING
|
|
||||||
"The version of Python to build the wrappers against."
|
|
||||||
FORCE)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(GTSAM_UNSTABLE_BUILD_PYTHON)
|
|
||||||
if (NOT GTSAM_BUILD_UNSTABLE)
|
|
||||||
message(WARNING "GTSAM_UNSTABLE_BUILD_PYTHON requires the unstable module to be enabled.")
|
|
||||||
set(GTSAM_UNSTABLE_BUILD_PYTHON OFF)
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(GTSAM_PY_INSTALL_PATH "${CMAKE_INSTALL_PREFIX}/python")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Flags for choosing default packaging tools
|
|
||||||
set(CPACK_SOURCE_GENERATOR "TGZ" CACHE STRING "CPack Default Source Generator")
|
|
||||||
set(CPACK_GENERATOR "TGZ" CACHE STRING "CPack Default Binary Generator")
|
|
||||||
|
|
||||||
if (CMAKE_GENERATOR STREQUAL "Ninja" AND
|
|
||||||
((CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.9) OR
|
|
||||||
(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.5)))
|
|
||||||
# Force colored warnings in Ninja's output, if the compiler has -fdiagnostics-color support.
|
|
||||||
# Rationale in https://github.com/ninja-build/ninja/issues/814
|
|
||||||
add_compile_options(-fdiagnostics-color=always)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
###############################################################################
|
|
||||||
# Find boost
|
|
||||||
|
|
||||||
# To change the path for boost, you will need to set:
|
|
||||||
# BOOST_ROOT: path to install prefix for boost
|
|
||||||
# Boost_NO_SYSTEM_PATHS: set to true to keep the find script from ignoring BOOST_ROOT
|
|
||||||
|
|
||||||
if(MSVC)
|
|
||||||
# By default, boost only builds static libraries on windows
|
|
||||||
set(Boost_USE_STATIC_LIBS ON) # only find static libs
|
|
||||||
# If we ever reset above on windows and, ...
|
|
||||||
# If we use Boost shared libs, disable auto linking.
|
|
||||||
# Some libraries, at least Boost Program Options, rely on this to export DLL symbols.
|
|
||||||
if(NOT Boost_USE_STATIC_LIBS)
|
|
||||||
list_append_cache(GTSAM_COMPILE_DEFINITIONS_PUBLIC BOOST_ALL_NO_LIB BOOST_ALL_DYN_LINK)
|
|
||||||
endif()
|
|
||||||
# Virtual memory range for PCH exceeded on VS2015
|
|
||||||
if(MSVC_VERSION LESS 1910) # older than VS2017
|
|
||||||
list_append_cache(GTSAM_COMPILE_OPTIONS_PRIVATE -Zm295)
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# If building DLLs in MSVC, we need to avoid EIGEN_STATIC_ASSERT()
|
|
||||||
# or explicit instantiation will generate build errors.
|
|
||||||
# See: https://bitbucket.org/gtborg/gtsam/issues/417/fail-to-build-on-msvc-2017
|
|
||||||
#
|
|
||||||
if(MSVC AND BUILD_SHARED_LIBS)
|
|
||||||
list_append_cache(GTSAM_COMPILE_DEFINITIONS_PUBLIC EIGEN_NO_STATIC_ASSERT)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Store these in variables so they are automatically replicated in GTSAMConfig.cmake and such.
|
|
||||||
set(BOOST_FIND_MINIMUM_VERSION 1.58)
|
|
||||||
set(BOOST_FIND_MINIMUM_COMPONENTS serialization system filesystem thread program_options date_time timer chrono regex)
|
|
||||||
|
|
||||||
find_package(Boost ${BOOST_FIND_MINIMUM_VERSION} COMPONENTS ${BOOST_FIND_MINIMUM_COMPONENTS})
|
|
||||||
|
|
||||||
# Required components
|
|
||||||
if(NOT Boost_SERIALIZATION_LIBRARY OR NOT Boost_SYSTEM_LIBRARY OR NOT Boost_FILESYSTEM_LIBRARY OR
|
|
||||||
NOT Boost_THREAD_LIBRARY OR NOT Boost_DATE_TIME_LIBRARY)
|
|
||||||
message(FATAL_ERROR "Missing required Boost components >= v1.58, please install/upgrade Boost or configure your search paths.")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
option(GTSAM_DISABLE_NEW_TIMERS "Disables using Boost.chrono for timing" OFF)
|
|
||||||
# Allow for not using the timer libraries on boost < 1.48 (GTSAM timing code falls back to old timer library)
|
|
||||||
set(GTSAM_BOOST_LIBRARIES
|
|
||||||
Boost::serialization
|
|
||||||
Boost::system
|
|
||||||
Boost::filesystem
|
|
||||||
Boost::thread
|
|
||||||
Boost::date_time
|
|
||||||
Boost::regex
|
|
||||||
)
|
|
||||||
if (GTSAM_DISABLE_NEW_TIMERS)
|
|
||||||
message("WARNING: GTSAM timing instrumentation manually disabled")
|
|
||||||
list_append_cache(GTSAM_COMPILE_DEFINITIONS_PUBLIC DGTSAM_DISABLE_NEW_TIMERS)
|
|
||||||
else()
|
|
||||||
if(Boost_TIMER_LIBRARY)
|
|
||||||
list(APPEND GTSAM_BOOST_LIBRARIES Boost::timer Boost::chrono)
|
|
||||||
else()
|
|
||||||
list(APPEND GTSAM_BOOST_LIBRARIES rt) # When using the header-only boost timer library, need -lrt
|
|
||||||
message("WARNING: GTSAM timing instrumentation will use the older, less accurate, Boost timer library because boost older than 1.48 was found.")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
###############################################################################
|
|
||||||
# Find TBB
|
|
||||||
find_package(TBB 4.4 COMPONENTS tbb tbbmalloc)
|
|
||||||
|
|
||||||
# Set up variables if we're using TBB
|
|
||||||
if(TBB_FOUND AND GTSAM_WITH_TBB)
|
|
||||||
set(GTSAM_USE_TBB 1) # This will go into config.h
|
|
||||||
if ((${TBB_VERSION_MAJOR} GREATER 2020) OR (${TBB_VERSION_MAJOR} EQUAL 2020))
|
|
||||||
set(TBB_GREATER_EQUAL_2020 1)
|
|
||||||
else()
|
|
||||||
set(TBB_GREATER_EQUAL_2020 0)
|
|
||||||
endif()
|
|
||||||
# all definitions and link requisites will go via imported targets:
|
|
||||||
# tbb & tbbmalloc
|
|
||||||
list(APPEND GTSAM_ADDITIONAL_LIBRARIES tbb tbbmalloc)
|
|
||||||
else()
|
|
||||||
set(GTSAM_USE_TBB 0) # This will go into config.h
|
|
||||||
endif()
|
|
||||||
|
|
||||||
###############################################################################
|
|
||||||
# Prohibit Timing build mode in combination with TBB
|
|
||||||
if(GTSAM_USE_TBB AND (CMAKE_BUILD_TYPE STREQUAL "Timing"))
|
|
||||||
message(FATAL_ERROR "Timing build mode cannot be used together with TBB. Use a sampling profiler such as Instruments or Intel VTune Amplifier instead.")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
|
|
||||||
###############################################################################
|
|
||||||
# Find Google perftools
|
|
||||||
find_package(GooglePerfTools)
|
|
||||||
|
|
||||||
###############################################################################
|
|
||||||
# Support ccache, if installed
|
|
||||||
if(NOT MSVC AND NOT XCODE_VERSION)
|
|
||||||
find_program(CCACHE_FOUND ccache)
|
|
||||||
if(CCACHE_FOUND)
|
|
||||||
if(GTSAM_BUILD_WITH_CCACHE)
|
|
||||||
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache)
|
|
||||||
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ccache)
|
|
||||||
else()
|
|
||||||
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "")
|
|
||||||
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK "")
|
|
||||||
endif()
|
|
||||||
endif(CCACHE_FOUND)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
###############################################################################
|
|
||||||
# Find MKL
|
|
||||||
find_package(MKL)
|
|
||||||
|
|
||||||
if(MKL_FOUND AND GTSAM_WITH_EIGEN_MKL)
|
|
||||||
set(GTSAM_USE_EIGEN_MKL 1) # This will go into config.h
|
|
||||||
set(EIGEN_USE_MKL_ALL 1) # This will go into config.h - it makes Eigen use MKL
|
|
||||||
list(APPEND GTSAM_ADDITIONAL_LIBRARIES ${MKL_LIBRARIES})
|
|
||||||
|
|
||||||
# --no-as-needed is required with gcc according to the MKL link advisor
|
|
||||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
|
||||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--no-as-needed")
|
|
||||||
endif()
|
|
||||||
else()
|
|
||||||
set(GTSAM_USE_EIGEN_MKL 0)
|
|
||||||
set(EIGEN_USE_MKL_ALL 0)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
###############################################################################
|
|
||||||
# Find OpenMP (if we're also using MKL)
|
|
||||||
find_package(OpenMP) # do this here to generate correct message if disabled
|
|
||||||
|
|
||||||
if(GTSAM_WITH_EIGEN_MKL AND GTSAM_WITH_EIGEN_MKL_OPENMP AND GTSAM_USE_EIGEN_MKL)
|
|
||||||
if(OPENMP_FOUND AND GTSAM_USE_EIGEN_MKL AND GTSAM_WITH_EIGEN_MKL_OPENMP)
|
|
||||||
set(GTSAM_USE_EIGEN_MKL_OPENMP 1) # This will go into config.h
|
|
||||||
list_append_cache(GTSAM_COMPILE_OPTIONS_PUBLIC ${OpenMP_CXX_FLAGS})
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
|
|
||||||
###############################################################################
|
|
||||||
# Option for using system Eigen or GTSAM-bundled Eigen
|
|
||||||
### These patches only affect usage of MKL. If you want to enable MKL, you *must*
|
|
||||||
### use our patched version of Eigen
|
|
||||||
### See: http://eigen.tuxfamily.org/bz/show_bug.cgi?id=704 (Householder QR MKL selection)
|
|
||||||
### http://eigen.tuxfamily.org/bz/show_bug.cgi?id=705 (Fix MKL LLT return code)
|
|
||||||
option(GTSAM_USE_SYSTEM_EIGEN "Find and use system-installed Eigen. If 'off', use the one bundled with GTSAM" OFF)
|
|
||||||
option(GTSAM_WITH_EIGEN_UNSUPPORTED "Install Eigen's unsupported modules" OFF)
|
|
||||||
|
|
||||||
# Switch for using system Eigen or GTSAM-bundled Eigen
|
|
||||||
if(GTSAM_USE_SYSTEM_EIGEN)
|
|
||||||
find_package(Eigen3 REQUIRED)
|
|
||||||
|
|
||||||
# Use generic Eigen include paths e.g. <Eigen/Core>
|
|
||||||
set(GTSAM_EIGEN_INCLUDE_FOR_INSTALL "${EIGEN3_INCLUDE_DIR}")
|
|
||||||
|
|
||||||
# check if MKL is also enabled - can have one or the other, but not both!
|
|
||||||
# Note: Eigen >= v3.2.5 includes our patches
|
|
||||||
if(EIGEN_USE_MKL_ALL AND (EIGEN3_VERSION VERSION_LESS 3.2.5))
|
|
||||||
message(FATAL_ERROR "MKL requires at least Eigen 3.2.5, and your system appears to have an older version. Disable GTSAM_USE_SYSTEM_EIGEN to use GTSAM's copy of Eigen, or disable GTSAM_WITH_EIGEN_MKL")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Check for Eigen version which doesn't work with MKL
|
|
||||||
# See http://eigen.tuxfamily.org/bz/show_bug.cgi?id=1527 for details.
|
|
||||||
if(EIGEN_USE_MKL_ALL AND (EIGEN3_VERSION VERSION_EQUAL 3.3.4))
|
|
||||||
message(FATAL_ERROR "MKL does not work with Eigen 3.3.4 because of a bug in Eigen. See http://eigen.tuxfamily.org/bz/show_bug.cgi?id=1527. Disable GTSAM_USE_SYSTEM_EIGEN to use GTSAM's copy of Eigen, disable GTSAM_WITH_EIGEN_MKL, or upgrade/patch your installation of Eigen.")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# The actual include directory (for BUILD cmake target interface):
|
|
||||||
set(GTSAM_EIGEN_INCLUDE_FOR_BUILD "${EIGEN3_INCLUDE_DIR}")
|
|
||||||
else()
|
|
||||||
# Use bundled Eigen include path.
|
|
||||||
# Clear any variables set by FindEigen3
|
|
||||||
if(EIGEN3_INCLUDE_DIR)
|
|
||||||
set(EIGEN3_INCLUDE_DIR NOTFOUND CACHE STRING "" FORCE)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# set full path to be used by external projects
|
|
||||||
# this will be added to GTSAM_INCLUDE_DIR by gtsam_extra.cmake.in
|
|
||||||
set(GTSAM_EIGEN_INCLUDE_FOR_INSTALL "include/gtsam/3rdparty/Eigen/")
|
|
||||||
|
|
||||||
# The actual include directory (for BUILD cmake target interface):
|
|
||||||
set(GTSAM_EIGEN_INCLUDE_FOR_BUILD "${CMAKE_SOURCE_DIR}/gtsam/3rdparty/Eigen/")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Detect Eigen version:
|
|
||||||
set(EIGEN_VER_H "${GTSAM_EIGEN_INCLUDE_FOR_BUILD}/Eigen/src/Core/util/Macros.h")
|
|
||||||
if (EXISTS ${EIGEN_VER_H})
|
|
||||||
file(READ "${EIGEN_VER_H}" STR_EIGEN_VERSION)
|
|
||||||
|
|
||||||
# Extract the Eigen version from the Macros.h file, lines "#define EIGEN_WORLD_VERSION XX", etc...
|
|
||||||
|
|
||||||
string(REGEX MATCH "EIGEN_WORLD_VERSION[ ]+[0-9]+" GTSAM_EIGEN_VERSION_WORLD "${STR_EIGEN_VERSION}")
|
|
||||||
string(REGEX MATCH "[0-9]+" GTSAM_EIGEN_VERSION_WORLD "${GTSAM_EIGEN_VERSION_WORLD}")
|
|
||||||
|
|
||||||
string(REGEX MATCH "EIGEN_MAJOR_VERSION[ ]+[0-9]+" GTSAM_EIGEN_VERSION_MAJOR "${STR_EIGEN_VERSION}")
|
|
||||||
string(REGEX MATCH "[0-9]+" GTSAM_EIGEN_VERSION_MAJOR "${GTSAM_EIGEN_VERSION_MAJOR}")
|
|
||||||
|
|
||||||
string(REGEX MATCH "EIGEN_MINOR_VERSION[ ]+[0-9]+" GTSAM_EIGEN_VERSION_MINOR "${STR_EIGEN_VERSION}")
|
|
||||||
string(REGEX MATCH "[0-9]+" GTSAM_EIGEN_VERSION_MINOR "${GTSAM_EIGEN_VERSION_MINOR}")
|
|
||||||
|
|
||||||
set(GTSAM_EIGEN_VERSION "${GTSAM_EIGEN_VERSION_WORLD}.${GTSAM_EIGEN_VERSION_MAJOR}.${GTSAM_EIGEN_VERSION_MINOR}")
|
|
||||||
|
|
||||||
message(STATUS "Found Eigen version: ${GTSAM_EIGEN_VERSION}")
|
|
||||||
else()
|
|
||||||
message(WARNING "Cannot determine Eigen version, missing file: `${EIGEN_VER_H}`")
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
if (MSVC)
|
|
||||||
if (BUILD_SHARED_LIBS)
|
|
||||||
# mute eigen static assert to avoid errors in shared lib
|
|
||||||
list_append_cache(GTSAM_COMPILE_DEFINITIONS_PUBLIC EIGEN_NO_STATIC_ASSERT)
|
|
||||||
endif()
|
|
||||||
list_append_cache(GTSAM_COMPILE_OPTIONS_PRIVATE "/wd4244") # Disable loss of precision which is thrown all over our Eigen
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (APPLE AND BUILD_SHARED_LIBS)
|
|
||||||
# Set the default install directory on macOS
|
|
||||||
set(CMAKE_INSTALL_NAME_DIR "${CMAKE_INSTALL_PREFIX}/lib")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
###############################################################################
|
|
||||||
# Global compile options
|
|
||||||
|
|
||||||
# Build list of possible allocators
|
|
||||||
set(possible_allocators "")
|
|
||||||
if(GTSAM_USE_TBB)
|
|
||||||
list(APPEND possible_allocators TBB)
|
|
||||||
set(preferred_allocator TBB)
|
|
||||||
else()
|
|
||||||
list(APPEND possible_allocators BoostPool STL)
|
|
||||||
set(preferred_allocator STL)
|
|
||||||
endif()
|
|
||||||
if(GOOGLE_PERFTOOLS_FOUND)
|
|
||||||
list(APPEND possible_allocators tcmalloc)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Check if current allocator choice is valid and set cache option
|
|
||||||
list(FIND possible_allocators "${GTSAM_DEFAULT_ALLOCATOR}" allocator_valid)
|
|
||||||
if(allocator_valid EQUAL -1)
|
|
||||||
set(GTSAM_DEFAULT_ALLOCATOR ${preferred_allocator} CACHE STRING "Default allocator" FORCE)
|
|
||||||
else()
|
|
||||||
set(GTSAM_DEFAULT_ALLOCATOR ${preferred_allocator} CACHE STRING "Default allocator")
|
|
||||||
endif()
|
|
||||||
set_property(CACHE GTSAM_DEFAULT_ALLOCATOR PROPERTY STRINGS ${possible_allocators})
|
|
||||||
mark_as_advanced(GTSAM_DEFAULT_ALLOCATOR)
|
|
||||||
|
|
||||||
# Define compile flags depending on allocator
|
|
||||||
if("${GTSAM_DEFAULT_ALLOCATOR}" STREQUAL "BoostPool")
|
|
||||||
set(GTSAM_ALLOCATOR_BOOSTPOOL 1)
|
|
||||||
elseif("${GTSAM_DEFAULT_ALLOCATOR}" STREQUAL "STL")
|
|
||||||
set(GTSAM_ALLOCATOR_STL 1)
|
|
||||||
elseif("${GTSAM_DEFAULT_ALLOCATOR}" STREQUAL "TBB")
|
|
||||||
set(GTSAM_ALLOCATOR_TBB 1)
|
|
||||||
elseif("${GTSAM_DEFAULT_ALLOCATOR}" STREQUAL "tcmalloc")
|
|
||||||
set(GTSAM_ALLOCATOR_STL 1) # tcmalloc replaces malloc, so to use it we use the STL allocator
|
|
||||||
list(APPEND GTSAM_ADDITIONAL_LIBRARIES "tcmalloc")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(MSVC)
|
|
||||||
list_append_cache(GTSAM_COMPILE_DEFINITIONS_PRIVATE _CRT_SECURE_NO_WARNINGS _SCL_SECURE_NO_WARNINGS)
|
|
||||||
list_append_cache(GTSAM_COMPILE_OPTIONS_PRIVATE /wd4251 /wd4275 /wd4251 /wd4661 /wd4344 /wd4503) # Disable non-DLL-exported base class and other warnings
|
|
||||||
list_append_cache(GTSAM_COMPILE_OPTIONS_PRIVATE /bigobj) # Allow large object files for template-based code
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# GCC 4.8+ complains about local typedefs which we use for shared_ptr etc.
|
|
||||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
|
||||||
if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.8)
|
|
||||||
list_append_cache(GTSAM_COMPILE_OPTIONS_PRIVATE -Wno-unused-local-typedefs)
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# As of XCode 7, clang also complains about this
|
|
||||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
|
||||||
if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 7.0)
|
|
||||||
list_append_cache(GTSAM_COMPILE_OPTIONS_PRIVATE -Wno-unused-local-typedefs)
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(GTSAM_ENABLE_CONSISTENCY_CHECKS)
|
|
||||||
# This should be made PUBLIC if GTSAM_EXTRA_CONSISTENCY_CHECKS is someday used in a public .h
|
|
||||||
list_append_cache(GTSAM_COMPILE_DEFINITIONS_PRIVATE GTSAM_EXTRA_CONSISTENCY_CHECKS)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
# Add components
|
# Add components
|
||||||
|
@ -477,7 +92,6 @@ endif()
|
||||||
GtsamMakeConfigFile(GTSAM "${CMAKE_CURRENT_SOURCE_DIR}/gtsam_extra.cmake.in")
|
GtsamMakeConfigFile(GTSAM "${CMAKE_CURRENT_SOURCE_DIR}/gtsam_extra.cmake.in")
|
||||||
export(TARGETS ${GTSAM_EXPORTED_TARGETS} FILE GTSAM-exports.cmake)
|
export(TARGETS ${GTSAM_EXPORTED_TARGETS} FILE GTSAM-exports.cmake)
|
||||||
|
|
||||||
|
|
||||||
# Check for doxygen availability - optional dependency
|
# Check for doxygen availability - optional dependency
|
||||||
find_package(Doxygen)
|
find_package(Doxygen)
|
||||||
|
|
||||||
|
@ -489,146 +103,11 @@ endif()
|
||||||
# CMake Tools
|
# CMake Tools
|
||||||
add_subdirectory(cmake)
|
add_subdirectory(cmake)
|
||||||
|
|
||||||
|
|
||||||
###############################################################################
|
|
||||||
# Set up CPack
|
|
||||||
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "GTSAM")
|
|
||||||
set(CPACK_PACKAGE_VENDOR "Frank Dellaert, Georgia Institute of Technology")
|
|
||||||
set(CPACK_PACKAGE_CONTACT "Frank Dellaert, dellaert@cc.gatech.edu")
|
|
||||||
set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/README.md")
|
|
||||||
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE")
|
|
||||||
set(CPACK_PACKAGE_VERSION_MAJOR ${GTSAM_VERSION_MAJOR})
|
|
||||||
set(CPACK_PACKAGE_VERSION_MINOR ${GTSAM_VERSION_MINOR})
|
|
||||||
set(CPACK_PACKAGE_VERSION_PATCH ${GTSAM_VERSION_PATCH})
|
|
||||||
set(CPACK_PACKAGE_INSTALL_DIRECTORY "CMake ${CMake_VERSION_MAJOR}.${CMake_VERSION_MINOR}")
|
|
||||||
#set(CPACK_INSTALLED_DIRECTORIES "doc;.") # Include doc directory
|
|
||||||
#set(CPACK_INSTALLED_DIRECTORIES ".") # FIXME: throws error
|
|
||||||
set(CPACK_SOURCE_IGNORE_FILES "/build*;/\\\\.;/makestats.sh$")
|
|
||||||
set(CPACK_SOURCE_IGNORE_FILES "${CPACK_SOURCE_IGNORE_FILES}" "/gtsam_unstable/")
|
|
||||||
set(CPACK_SOURCE_IGNORE_FILES "${CPACK_SOURCE_IGNORE_FILES}" "/package_scripts/")
|
|
||||||
set(CPACK_SOURCE_PACKAGE_FILE_NAME "gtsam-${GTSAM_VERSION_MAJOR}.${GTSAM_VERSION_MINOR}.${GTSAM_VERSION_PATCH}")
|
|
||||||
#set(CPACK_SOURCE_PACKAGE_FILE_NAME "gtsam-aspn${GTSAM_VERSION_PATCH}") # Used for creating ASPN tarballs
|
|
||||||
|
|
||||||
# Deb-package specific cpack
|
|
||||||
set(CPACK_DEBIAN_PACKAGE_NAME "libgtsam-dev")
|
|
||||||
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libboost-dev (>= 1.58)") #Example: "libc6 (>= 2.3.1-6), libgcc1 (>= 1:3.4.2-12)")
|
|
||||||
|
|
||||||
|
|
||||||
###############################################################################
|
|
||||||
# Print configuration variables
|
# Print configuration variables
|
||||||
message(STATUS "===============================================================")
|
include(cmake/HandlePrintConfiguration.cmake)
|
||||||
message(STATUS "================ Configuration Options ======================")
|
|
||||||
print_config("CMAKE_CXX_COMPILER_ID type" "${CMAKE_CXX_COMPILER_ID}")
|
|
||||||
print_config("CMAKE_CXX_COMPILER_VERSION" "${CMAKE_CXX_COMPILER_VERSION}")
|
|
||||||
print_config("CMake version" "${CMAKE_VERSION}")
|
|
||||||
print_config("CMake generator" "${CMAKE_GENERATOR}")
|
|
||||||
print_config("CMake build tool" "${CMAKE_BUILD_TOOL}")
|
|
||||||
message(STATUS "Build flags ")
|
|
||||||
print_enabled_config(${GTSAM_BUILD_TESTS} "Build Tests")
|
|
||||||
print_enabled_config(${GTSAM_BUILD_EXAMPLES_ALWAYS} "Build examples with 'make all'")
|
|
||||||
print_enabled_config(${GTSAM_BUILD_TIMING_ALWAYS} "Build timing scripts with 'make all'")
|
|
||||||
if (DOXYGEN_FOUND)
|
|
||||||
print_enabled_config(${GTSAM_BUILD_DOCS} "Build Docs")
|
|
||||||
endif()
|
|
||||||
print_enabled_config(${BUILD_SHARED_LIBS} "Build shared GTSAM libraries")
|
|
||||||
print_enabled_config(${GTSAM_BUILD_TYPE_POSTFIXES} "Put build type in library name")
|
|
||||||
if(GTSAM_UNSTABLE_AVAILABLE)
|
|
||||||
print_enabled_config(${GTSAM_BUILD_UNSTABLE} "Build libgtsam_unstable ")
|
|
||||||
print_enabled_config(${GTSAM_UNSTABLE_BUILD_PYTHON} "Build GTSAM unstable Python ")
|
|
||||||
print_enabled_config(${GTSAM_UNSTABLE_INSTALL_MATLAB_TOOLBOX} "Build MATLAB Toolbox for unstable")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT MSVC AND NOT XCODE_VERSION)
|
|
||||||
print_enabled_config(${GTSAM_BUILD_WITH_MARCH_NATIVE} "Build for native architecture ")
|
|
||||||
print_config("Build type" "${CMAKE_BUILD_TYPE}")
|
|
||||||
print_config("C compilation flags" "${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_${CMAKE_BUILD_TYPE_UPPER}}")
|
|
||||||
print_config("C++ compilation flags" "${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_${CMAKE_BUILD_TYPE_UPPER}}")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
print_build_options_for_target(gtsam)
|
|
||||||
|
|
||||||
print_config("Use System Eigen" "${GTSAM_USE_SYSTEM_EIGEN} (Using version: ${GTSAM_EIGEN_VERSION})")
|
|
||||||
|
|
||||||
if(GTSAM_USE_TBB)
|
|
||||||
print_config("Use Intel TBB" "Yes (Version: ${TBB_VERSION})")
|
|
||||||
elseif(TBB_FOUND)
|
|
||||||
print_config("Use Intel TBB" "TBB (Version: ${TBB_VERSION}) found but GTSAM_WITH_TBB is disabled")
|
|
||||||
else()
|
|
||||||
print_config("Use Intel TBB" "TBB not found")
|
|
||||||
endif()
|
|
||||||
if(GTSAM_USE_EIGEN_MKL)
|
|
||||||
print_config("Eigen will use MKL" "Yes")
|
|
||||||
elseif(MKL_FOUND)
|
|
||||||
print_config("Eigen will use MKL" "MKL found but GTSAM_WITH_EIGEN_MKL is disabled")
|
|
||||||
else()
|
|
||||||
print_config("Eigen will use MKL" "MKL not found")
|
|
||||||
endif()
|
|
||||||
if(GTSAM_USE_EIGEN_MKL_OPENMP)
|
|
||||||
print_config("Eigen will use MKL and OpenMP" "Yes")
|
|
||||||
elseif(OPENMP_FOUND AND NOT GTSAM_WITH_EIGEN_MKL)
|
|
||||||
print_config("Eigen will use MKL and OpenMP" "OpenMP found but GTSAM_WITH_EIGEN_MKL is disabled")
|
|
||||||
elseif(OPENMP_FOUND AND NOT MKL_FOUND)
|
|
||||||
print_config("Eigen will use MKL and OpenMP" "OpenMP found but MKL not found")
|
|
||||||
elseif(OPENMP_FOUND)
|
|
||||||
print_config("Eigen will use MKL and OpenMP" "OpenMP found but GTSAM_WITH_EIGEN_MKL_OPENMP is disabled")
|
|
||||||
else()
|
|
||||||
print_config("Eigen will use MKL and OpenMP" "OpenMP not found")
|
|
||||||
endif()
|
|
||||||
print_config("Default allocator" "${GTSAM_DEFAULT_ALLOCATOR}")
|
|
||||||
|
|
||||||
if(GTSAM_THROW_CHEIRALITY_EXCEPTION)
|
|
||||||
print_config("Cheirality exceptions enabled" "YES")
|
|
||||||
else()
|
|
||||||
print_config("Cheirality exceptions enabled" "NO")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT MSVC AND NOT XCODE_VERSION)
|
|
||||||
if(CCACHE_FOUND AND GTSAM_BUILD_WITH_CCACHE)
|
|
||||||
print_config("Build with ccache" "Yes")
|
|
||||||
elseif(CCACHE_FOUND)
|
|
||||||
print_config("Build with ccache" "ccache found but GTSAM_BUILD_WITH_CCACHE is disabled")
|
|
||||||
else()
|
|
||||||
print_config("Build with ccache" "No")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
message(STATUS "Packaging flags")
|
|
||||||
print_config("CPack Source Generator" "${CPACK_SOURCE_GENERATOR}")
|
|
||||||
print_config("CPack Generator" "${CPACK_GENERATOR}")
|
|
||||||
|
|
||||||
message(STATUS "GTSAM flags ")
|
|
||||||
print_enabled_config(${GTSAM_USE_QUATERNIONS} "Quaternions as default Rot3 ")
|
|
||||||
print_enabled_config(${GTSAM_ENABLE_CONSISTENCY_CHECKS} "Runtime consistency checking ")
|
|
||||||
print_enabled_config(${GTSAM_ROT3_EXPMAP} "Rot3 retract is full ExpMap ")
|
|
||||||
print_enabled_config(${GTSAM_POSE3_EXPMAP} "Pose3 retract is full ExpMap ")
|
|
||||||
print_enabled_config(${GTSAM_ALLOW_DEPRECATED_SINCE_V41} "Allow features deprecated in GTSAM 4.1")
|
|
||||||
print_enabled_config(${GTSAM_SUPPORT_NESTED_DISSECTION} "Metis-based Nested Dissection ")
|
|
||||||
print_enabled_config(${GTSAM_TANGENT_PREINTEGRATION} "Use tangent-space preintegration")
|
|
||||||
|
|
||||||
message(STATUS "MATLAB toolbox flags")
|
|
||||||
print_enabled_config(${GTSAM_INSTALL_MATLAB_TOOLBOX} "Install MATLAB toolbox ")
|
|
||||||
if (${GTSAM_INSTALL_MATLAB_TOOLBOX})
|
|
||||||
print_config("MATLAB root" "${MATLAB_ROOT}")
|
|
||||||
print_config("MEX binary" "${MEX_COMMAND}")
|
|
||||||
endif()
|
|
||||||
message(STATUS "Python toolbox flags ")
|
|
||||||
print_enabled_config(${GTSAM_BUILD_PYTHON} "Build Python module with pybind ")
|
|
||||||
if(GTSAM_BUILD_PYTHON)
|
|
||||||
print_config("Python version" ${GTSAM_PYTHON_VERSION})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
message(STATUS "===============================================================")
|
|
||||||
|
|
||||||
# Print warnings at the end
|
# Print warnings at the end
|
||||||
if(GTSAM_WITH_TBB AND NOT TBB_FOUND)
|
include(cmake/HandleFinalChecks.cmake)
|
||||||
message(WARNING "TBB 4.4 or newer was not found - this is ok, but note that GTSAM parallelization will be disabled. Set GTSAM_WITH_TBB to 'Off' to avoid this warning.")
|
|
||||||
endif()
|
|
||||||
if(GTSAM_WITH_EIGEN_MKL AND NOT MKL_FOUND)
|
|
||||||
message(WARNING "MKL was not found - this is ok, but note that MKL will be disabled. Set GTSAM_WITH_EIGEN_MKL to 'Off' to disable this warning. See INSTALL.md for notes on performance.")
|
|
||||||
endif()
|
|
||||||
if(GTSAM_WITH_EIGEN_MKL_OPENMP AND NOT OPENMP_FOUND AND MKL_FOUND)
|
|
||||||
message(WARNING "Your compiler does not support OpenMP. Set GTSAM_WITH_EIGEN_MKL_OPENMP to 'Off' to avoid this warning. See INSTALL.md for notes on performance.")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Include CPack *after* all flags
|
# Include CPack *after* all flags
|
||||||
include(CPack)
|
include(CPack)
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
include(CheckCXXCompilerFlag) # for check_cxx_compiler_flag()
|
||||||
|
|
||||||
# Set cmake policy to recognize the AppleClang compiler
|
# Set cmake policy to recognize the AppleClang compiler
|
||||||
# independently from the Clang compiler.
|
# independently from the Clang compiler.
|
||||||
if(POLICY CMP0025)
|
if(POLICY CMP0025)
|
||||||
|
@ -105,11 +107,14 @@ if(MSVC)
|
||||||
else()
|
else()
|
||||||
# Common to all configurations, next for each configuration:
|
# Common to all configurations, next for each configuration:
|
||||||
|
|
||||||
if (
|
if (NOT MSVC)
|
||||||
((CMAKE_CXX_COMPILER_ID MATCHES "Clang") AND (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 12.0.0)) OR
|
check_cxx_compiler_flag(-Wsuggest-override COMPILER_HAS_WSUGGEST_OVERRIDE)
|
||||||
(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
|
check_cxx_compiler_flag(-Wmissing COMPILER_HAS_WMISSING_OVERRIDE)
|
||||||
)
|
if (COMPILER_HAS_WSUGGEST_OVERRIDE)
|
||||||
set(flag_override_ -Wsuggest-override) # -Werror=suggest-override: Add again someday
|
set(flag_override_ -Wsuggest-override) # -Werror=suggest-override: Add again someday
|
||||||
|
elseif(COMPILER_HAS_WMISSING_OVERRIDE)
|
||||||
|
set(flag_override_ -Wmissing-override) # -Werror=missing-override: Add again someday
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(GTSAM_COMPILE_OPTIONS_PRIVATE_COMMON
|
set(GTSAM_COMPILE_OPTIONS_PRIVATE_COMMON
|
||||||
|
@ -263,3 +268,17 @@ function(gtsam_apply_build_flags target_name_)
|
||||||
target_compile_options(${target_name_} PRIVATE ${GTSAM_COMPILE_OPTIONS_PRIVATE})
|
target_compile_options(${target_name_} PRIVATE ${GTSAM_COMPILE_OPTIONS_PRIVATE})
|
||||||
|
|
||||||
endfunction(gtsam_apply_build_flags)
|
endfunction(gtsam_apply_build_flags)
|
||||||
|
|
||||||
|
|
||||||
|
if(NOT MSVC AND NOT XCODE_VERSION)
|
||||||
|
# Set the build type to upper case for downstream use
|
||||||
|
string(TOUPPER "${CMAKE_BUILD_TYPE}" CMAKE_BUILD_TYPE_UPPER)
|
||||||
|
|
||||||
|
# Set the GTSAM_BUILD_TAG variable.
|
||||||
|
# If build type is Release, set to blank (""), else set to the build type.
|
||||||
|
if(${CMAKE_BUILD_TYPE_UPPER} STREQUAL "RELEASE")
|
||||||
|
set(GTSAM_BUILD_TAG "") # Don't create release mode tag on installed directory
|
||||||
|
else()
|
||||||
|
set(GTSAM_BUILD_TAG "${CMAKE_BUILD_TYPE}")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
# Build list of possible allocators
|
||||||
|
set(possible_allocators "")
|
||||||
|
if(GTSAM_USE_TBB)
|
||||||
|
list(APPEND possible_allocators TBB)
|
||||||
|
set(preferred_allocator TBB)
|
||||||
|
else()
|
||||||
|
list(APPEND possible_allocators BoostPool STL)
|
||||||
|
set(preferred_allocator STL)
|
||||||
|
endif()
|
||||||
|
if(GOOGLE_PERFTOOLS_FOUND)
|
||||||
|
list(APPEND possible_allocators tcmalloc)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Check if current allocator choice is valid and set cache option
|
||||||
|
list(FIND possible_allocators "${GTSAM_DEFAULT_ALLOCATOR}" allocator_valid)
|
||||||
|
if(allocator_valid EQUAL -1)
|
||||||
|
set(GTSAM_DEFAULT_ALLOCATOR ${preferred_allocator} CACHE STRING "Default allocator" FORCE)
|
||||||
|
else()
|
||||||
|
set(GTSAM_DEFAULT_ALLOCATOR ${preferred_allocator} CACHE STRING "Default allocator")
|
||||||
|
endif()
|
||||||
|
set_property(CACHE GTSAM_DEFAULT_ALLOCATOR PROPERTY STRINGS ${possible_allocators})
|
||||||
|
mark_as_advanced(GTSAM_DEFAULT_ALLOCATOR)
|
||||||
|
|
||||||
|
# Define compile flags depending on allocator
|
||||||
|
if("${GTSAM_DEFAULT_ALLOCATOR}" STREQUAL "BoostPool")
|
||||||
|
set(GTSAM_ALLOCATOR_BOOSTPOOL 1)
|
||||||
|
elseif("${GTSAM_DEFAULT_ALLOCATOR}" STREQUAL "STL")
|
||||||
|
set(GTSAM_ALLOCATOR_STL 1)
|
||||||
|
elseif("${GTSAM_DEFAULT_ALLOCATOR}" STREQUAL "TBB")
|
||||||
|
set(GTSAM_ALLOCATOR_TBB 1)
|
||||||
|
elseif("${GTSAM_DEFAULT_ALLOCATOR}" STREQUAL "tcmalloc")
|
||||||
|
set(GTSAM_ALLOCATOR_STL 1) # tcmalloc replaces malloc, so to use it we use the STL allocator
|
||||||
|
list(APPEND GTSAM_ADDITIONAL_LIBRARIES "tcmalloc")
|
||||||
|
endif()
|
|
@ -0,0 +1,56 @@
|
||||||
|
###############################################################################
|
||||||
|
# Find boost
|
||||||
|
|
||||||
|
# To change the path for boost, you will need to set:
|
||||||
|
# BOOST_ROOT: path to install prefix for boost
|
||||||
|
# Boost_NO_SYSTEM_PATHS: set to true to keep the find script from ignoring BOOST_ROOT
|
||||||
|
|
||||||
|
if(MSVC)
|
||||||
|
# By default, boost only builds static libraries on windows
|
||||||
|
set(Boost_USE_STATIC_LIBS ON) # only find static libs
|
||||||
|
# If we ever reset above on windows and, ...
|
||||||
|
# If we use Boost shared libs, disable auto linking.
|
||||||
|
# Some libraries, at least Boost Program Options, rely on this to export DLL symbols.
|
||||||
|
if(NOT Boost_USE_STATIC_LIBS)
|
||||||
|
list_append_cache(GTSAM_COMPILE_DEFINITIONS_PUBLIC BOOST_ALL_NO_LIB BOOST_ALL_DYN_LINK)
|
||||||
|
endif()
|
||||||
|
# Virtual memory range for PCH exceeded on VS2015
|
||||||
|
if(MSVC_VERSION LESS 1910) # older than VS2017
|
||||||
|
list_append_cache(GTSAM_COMPILE_OPTIONS_PRIVATE -Zm295)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
# Store these in variables so they are automatically replicated in GTSAMConfig.cmake and such.
|
||||||
|
set(BOOST_FIND_MINIMUM_VERSION 1.58)
|
||||||
|
set(BOOST_FIND_MINIMUM_COMPONENTS serialization system filesystem thread program_options date_time timer chrono regex)
|
||||||
|
|
||||||
|
find_package(Boost ${BOOST_FIND_MINIMUM_VERSION} COMPONENTS ${BOOST_FIND_MINIMUM_COMPONENTS})
|
||||||
|
|
||||||
|
# Required components
|
||||||
|
if(NOT Boost_SERIALIZATION_LIBRARY OR NOT Boost_SYSTEM_LIBRARY OR NOT Boost_FILESYSTEM_LIBRARY OR
|
||||||
|
NOT Boost_THREAD_LIBRARY OR NOT Boost_DATE_TIME_LIBRARY)
|
||||||
|
message(FATAL_ERROR "Missing required Boost components >= v1.58, please install/upgrade Boost or configure your search paths.")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
option(GTSAM_DISABLE_NEW_TIMERS "Disables using Boost.chrono for timing" OFF)
|
||||||
|
# Allow for not using the timer libraries on boost < 1.48 (GTSAM timing code falls back to old timer library)
|
||||||
|
set(GTSAM_BOOST_LIBRARIES
|
||||||
|
Boost::serialization
|
||||||
|
Boost::system
|
||||||
|
Boost::filesystem
|
||||||
|
Boost::thread
|
||||||
|
Boost::date_time
|
||||||
|
Boost::regex
|
||||||
|
)
|
||||||
|
if (GTSAM_DISABLE_NEW_TIMERS)
|
||||||
|
message("WARNING: GTSAM timing instrumentation manually disabled")
|
||||||
|
list_append_cache(GTSAM_COMPILE_DEFINITIONS_PUBLIC DGTSAM_DISABLE_NEW_TIMERS)
|
||||||
|
else()
|
||||||
|
if(Boost_TIMER_LIBRARY)
|
||||||
|
list(APPEND GTSAM_BOOST_LIBRARIES Boost::timer Boost::chrono)
|
||||||
|
else()
|
||||||
|
list(APPEND GTSAM_BOOST_LIBRARIES rt) # When using the header-only boost timer library, need -lrt
|
||||||
|
message("WARNING: GTSAM timing instrumentation will use the older, less accurate, Boost timer library because boost older than 1.48 was found.")
|
||||||
|
endif()
|
||||||
|
endif()
|
|
@ -0,0 +1,14 @@
|
||||||
|
###############################################################################
|
||||||
|
# Support ccache, if installed
|
||||||
|
if(NOT MSVC AND NOT XCODE_VERSION)
|
||||||
|
find_program(CCACHE_FOUND ccache)
|
||||||
|
if(CCACHE_FOUND)
|
||||||
|
if(GTSAM_BUILD_WITH_CCACHE)
|
||||||
|
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache)
|
||||||
|
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ccache)
|
||||||
|
else()
|
||||||
|
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "")
|
||||||
|
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK "")
|
||||||
|
endif()
|
||||||
|
endif(CCACHE_FOUND)
|
||||||
|
endif()
|
|
@ -0,0 +1,28 @@
|
||||||
|
#JLBC: is all this actually used by someone? could it be removed?
|
||||||
|
|
||||||
|
# Flags for choosing default packaging tools
|
||||||
|
set(CPACK_SOURCE_GENERATOR "TGZ" CACHE STRING "CPack Default Source Generator")
|
||||||
|
set(CPACK_GENERATOR "TGZ" CACHE STRING "CPack Default Binary Generator")
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# Set up CPack
|
||||||
|
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "GTSAM")
|
||||||
|
set(CPACK_PACKAGE_VENDOR "Frank Dellaert, Georgia Institute of Technology")
|
||||||
|
set(CPACK_PACKAGE_CONTACT "Frank Dellaert, dellaert@cc.gatech.edu")
|
||||||
|
set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/README.md")
|
||||||
|
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE")
|
||||||
|
set(CPACK_PACKAGE_VERSION_MAJOR ${GTSAM_VERSION_MAJOR})
|
||||||
|
set(CPACK_PACKAGE_VERSION_MINOR ${GTSAM_VERSION_MINOR})
|
||||||
|
set(CPACK_PACKAGE_VERSION_PATCH ${GTSAM_VERSION_PATCH})
|
||||||
|
set(CPACK_PACKAGE_INSTALL_DIRECTORY "CMake ${CMake_VERSION_MAJOR}.${CMake_VERSION_MINOR}")
|
||||||
|
#set(CPACK_INSTALLED_DIRECTORIES "doc;.") # Include doc directory
|
||||||
|
#set(CPACK_INSTALLED_DIRECTORIES ".") # FIXME: throws error
|
||||||
|
set(CPACK_SOURCE_IGNORE_FILES "/build*;/\\\\.;/makestats.sh$")
|
||||||
|
set(CPACK_SOURCE_IGNORE_FILES "${CPACK_SOURCE_IGNORE_FILES}" "/gtsam_unstable/")
|
||||||
|
set(CPACK_SOURCE_IGNORE_FILES "${CPACK_SOURCE_IGNORE_FILES}" "/package_scripts/")
|
||||||
|
set(CPACK_SOURCE_PACKAGE_FILE_NAME "gtsam-${GTSAM_VERSION_MAJOR}.${GTSAM_VERSION_MINOR}.${GTSAM_VERSION_PATCH}")
|
||||||
|
#set(CPACK_SOURCE_PACKAGE_FILE_NAME "gtsam-aspn${GTSAM_VERSION_PATCH}") # Used for creating ASPN tarballs
|
||||||
|
|
||||||
|
# Deb-package specific cpack
|
||||||
|
set(CPACK_DEBIAN_PACKAGE_NAME "libgtsam-dev")
|
||||||
|
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libboost-dev (>= 1.58)") #Example: "libc6 (>= 2.3.1-6), libgcc1 (>= 1:3.4.2-12)")
|
|
@ -0,0 +1,77 @@
|
||||||
|
###############################################################################
|
||||||
|
# Option for using system Eigen or GTSAM-bundled Eigen
|
||||||
|
|
||||||
|
option(GTSAM_USE_SYSTEM_EIGEN "Find and use system-installed Eigen. If 'off', use the one bundled with GTSAM" OFF)
|
||||||
|
|
||||||
|
if(NOT GTSAM_USE_SYSTEM_EIGEN)
|
||||||
|
# This option only makes sense if using the embedded copy of Eigen, it is
|
||||||
|
# used to decide whether to *install* the "unsupported" module:
|
||||||
|
option(GTSAM_WITH_EIGEN_UNSUPPORTED "Install Eigen's unsupported modules" OFF)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Switch for using system Eigen or GTSAM-bundled Eigen
|
||||||
|
if(GTSAM_USE_SYSTEM_EIGEN)
|
||||||
|
find_package(Eigen3 REQUIRED)
|
||||||
|
|
||||||
|
# Use generic Eigen include paths e.g. <Eigen/Core>
|
||||||
|
set(GTSAM_EIGEN_INCLUDE_FOR_INSTALL "${EIGEN3_INCLUDE_DIR}")
|
||||||
|
|
||||||
|
# check if MKL is also enabled - can have one or the other, but not both!
|
||||||
|
# Note: Eigen >= v3.2.5 includes our patches
|
||||||
|
if(EIGEN_USE_MKL_ALL AND (EIGEN3_VERSION VERSION_LESS 3.2.5))
|
||||||
|
message(FATAL_ERROR "MKL requires at least Eigen 3.2.5, and your system appears to have an older version. Disable GTSAM_USE_SYSTEM_EIGEN to use GTSAM's copy of Eigen, or disable GTSAM_WITH_EIGEN_MKL")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Check for Eigen version which doesn't work with MKL
|
||||||
|
# See http://eigen.tuxfamily.org/bz/show_bug.cgi?id=1527 for details.
|
||||||
|
if(EIGEN_USE_MKL_ALL AND (EIGEN3_VERSION VERSION_EQUAL 3.3.4))
|
||||||
|
message(FATAL_ERROR "MKL does not work with Eigen 3.3.4 because of a bug in Eigen. See http://eigen.tuxfamily.org/bz/show_bug.cgi?id=1527. Disable GTSAM_USE_SYSTEM_EIGEN to use GTSAM's copy of Eigen, disable GTSAM_WITH_EIGEN_MKL, or upgrade/patch your installation of Eigen.")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# The actual include directory (for BUILD cmake target interface):
|
||||||
|
set(GTSAM_EIGEN_INCLUDE_FOR_BUILD "${EIGEN3_INCLUDE_DIR}")
|
||||||
|
else()
|
||||||
|
# Use bundled Eigen include path.
|
||||||
|
# Clear any variables set by FindEigen3
|
||||||
|
if(EIGEN3_INCLUDE_DIR)
|
||||||
|
set(EIGEN3_INCLUDE_DIR NOTFOUND CACHE STRING "" FORCE)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# set full path to be used by external projects
|
||||||
|
# this will be added to GTSAM_INCLUDE_DIR by gtsam_extra.cmake.in
|
||||||
|
set(GTSAM_EIGEN_INCLUDE_FOR_INSTALL "include/gtsam/3rdparty/Eigen/")
|
||||||
|
|
||||||
|
# The actual include directory (for BUILD cmake target interface):
|
||||||
|
set(GTSAM_EIGEN_INCLUDE_FOR_BUILD "${CMAKE_SOURCE_DIR}/gtsam/3rdparty/Eigen/")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Detect Eigen version:
|
||||||
|
set(EIGEN_VER_H "${GTSAM_EIGEN_INCLUDE_FOR_BUILD}/Eigen/src/Core/util/Macros.h")
|
||||||
|
if (EXISTS ${EIGEN_VER_H})
|
||||||
|
file(READ "${EIGEN_VER_H}" STR_EIGEN_VERSION)
|
||||||
|
|
||||||
|
# Extract the Eigen version from the Macros.h file, lines "#define EIGEN_WORLD_VERSION XX", etc...
|
||||||
|
|
||||||
|
string(REGEX MATCH "EIGEN_WORLD_VERSION[ ]+[0-9]+" GTSAM_EIGEN_VERSION_WORLD "${STR_EIGEN_VERSION}")
|
||||||
|
string(REGEX MATCH "[0-9]+" GTSAM_EIGEN_VERSION_WORLD "${GTSAM_EIGEN_VERSION_WORLD}")
|
||||||
|
|
||||||
|
string(REGEX MATCH "EIGEN_MAJOR_VERSION[ ]+[0-9]+" GTSAM_EIGEN_VERSION_MAJOR "${STR_EIGEN_VERSION}")
|
||||||
|
string(REGEX MATCH "[0-9]+" GTSAM_EIGEN_VERSION_MAJOR "${GTSAM_EIGEN_VERSION_MAJOR}")
|
||||||
|
|
||||||
|
string(REGEX MATCH "EIGEN_MINOR_VERSION[ ]+[0-9]+" GTSAM_EIGEN_VERSION_MINOR "${STR_EIGEN_VERSION}")
|
||||||
|
string(REGEX MATCH "[0-9]+" GTSAM_EIGEN_VERSION_MINOR "${GTSAM_EIGEN_VERSION_MINOR}")
|
||||||
|
|
||||||
|
set(GTSAM_EIGEN_VERSION "${GTSAM_EIGEN_VERSION_WORLD}.${GTSAM_EIGEN_VERSION_MAJOR}.${GTSAM_EIGEN_VERSION_MINOR}")
|
||||||
|
|
||||||
|
message(STATUS "Found Eigen version: ${GTSAM_EIGEN_VERSION}")
|
||||||
|
else()
|
||||||
|
message(WARNING "Cannot determine Eigen version, missing file: `${EIGEN_VER_H}`")
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
if (MSVC)
|
||||||
|
if (BUILD_SHARED_LIBS)
|
||||||
|
# mute eigen static assert to avoid errors in shared lib
|
||||||
|
list_append_cache(GTSAM_COMPILE_DEFINITIONS_PUBLIC EIGEN_NO_STATIC_ASSERT)
|
||||||
|
endif()
|
||||||
|
list_append_cache(GTSAM_COMPILE_OPTIONS_PRIVATE "/wd4244") # Disable loss of precision which is thrown all over our Eigen
|
||||||
|
endif()
|
|
@ -0,0 +1,10 @@
|
||||||
|
# Print warnings at the end
|
||||||
|
if(GTSAM_WITH_TBB AND NOT TBB_FOUND)
|
||||||
|
message(WARNING "TBB 4.4 or newer was not found - this is ok, but note that GTSAM parallelization will be disabled. Set GTSAM_WITH_TBB to 'Off' to avoid this warning.")
|
||||||
|
endif()
|
||||||
|
if(GTSAM_WITH_EIGEN_MKL AND NOT MKL_FOUND)
|
||||||
|
message(WARNING "MKL was not found - this is ok, but note that MKL will be disabled. Set GTSAM_WITH_EIGEN_MKL to 'Off' to disable this warning. See INSTALL.md for notes on performance.")
|
||||||
|
endif()
|
||||||
|
if(GTSAM_WITH_EIGEN_MKL_OPENMP AND NOT OPENMP_FOUND AND MKL_FOUND)
|
||||||
|
message(WARNING "Your compiler does not support OpenMP. Set GTSAM_WITH_EIGEN_MKL_OPENMP to 'Off' to avoid this warning. See INSTALL.md for notes on performance.")
|
||||||
|
endif()
|
|
@ -0,0 +1,55 @@
|
||||||
|
###############################################################################
|
||||||
|
# Set up options
|
||||||
|
|
||||||
|
# See whether gtsam_unstable is available (it will be present only if we're using a git checkout)
|
||||||
|
if(EXISTS "${PROJECT_SOURCE_DIR}/gtsam_unstable" AND IS_DIRECTORY "${PROJECT_SOURCE_DIR}/gtsam_unstable")
|
||||||
|
set(GTSAM_UNSTABLE_AVAILABLE 1)
|
||||||
|
else()
|
||||||
|
set(GTSAM_UNSTABLE_AVAILABLE 0)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Configurable Options
|
||||||
|
if(GTSAM_UNSTABLE_AVAILABLE)
|
||||||
|
option(GTSAM_BUILD_UNSTABLE "Enable/Disable libgtsam_unstable" ON)
|
||||||
|
option(GTSAM_UNSTABLE_BUILD_PYTHON "Enable/Disable Python wrapper for libgtsam_unstable" ON)
|
||||||
|
option(GTSAM_UNSTABLE_INSTALL_MATLAB_TOOLBOX "Enable/Disable MATLAB wrapper for libgtsam_unstable" OFF)
|
||||||
|
endif()
|
||||||
|
option(BUILD_SHARED_LIBS "Build shared gtsam library, instead of static" ON)
|
||||||
|
option(GTSAM_USE_QUATERNIONS "Enable/Disable using an internal Quaternion representation for rotations instead of rotation matrices. If enable, Rot3::EXPMAP is enforced by default." OFF)
|
||||||
|
option(GTSAM_POSE3_EXPMAP "Enable/Disable using Pose3::EXPMAP as the default mode. If disabled, Pose3::FIRST_ORDER will be used." ON)
|
||||||
|
option(GTSAM_ROT3_EXPMAP "Ignore if GTSAM_USE_QUATERNIONS is OFF (Rot3::EXPMAP by default). Otherwise, enable Rot3::EXPMAP, or if disabled, use Rot3::CAYLEY." ON)
|
||||||
|
option(GTSAM_ENABLE_CONSISTENCY_CHECKS "Enable/Disable expensive consistency checks" OFF)
|
||||||
|
option(GTSAM_WITH_TBB "Use Intel Threaded Building Blocks (TBB) if available" ON)
|
||||||
|
option(GTSAM_WITH_EIGEN_MKL "Eigen will use Intel MKL if available" OFF)
|
||||||
|
option(GTSAM_WITH_EIGEN_MKL_OPENMP "Eigen, when using Intel MKL, will also use OpenMP for multithreading if available" OFF)
|
||||||
|
option(GTSAM_THROW_CHEIRALITY_EXCEPTION "Throw exception when a triangulated point is behind a camera" ON)
|
||||||
|
option(GTSAM_BUILD_PYTHON "Enable/Disable building & installation of Python module with pybind11" OFF)
|
||||||
|
option(GTSAM_ALLOW_DEPRECATED_SINCE_V41 "Allow use of methods/functions deprecated in GTSAM 4.1" ON)
|
||||||
|
option(GTSAM_SUPPORT_NESTED_DISSECTION "Support Metis-based nested dissection" ON)
|
||||||
|
option(GTSAM_TANGENT_PREINTEGRATION "Use new ImuFactor with integration on tangent space" ON)
|
||||||
|
if(NOT MSVC AND NOT XCODE_VERSION)
|
||||||
|
option(GTSAM_BUILD_WITH_CCACHE "Use ccache compiler cache" ON)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Enable GTSAM_ROT3_EXPMAP if GTSAM_POSE3_EXPMAP is enabled, and vice versa.
|
||||||
|
if(GTSAM_POSE3_EXPMAP)
|
||||||
|
message(STATUS "GTSAM_POSE3_EXPMAP=ON, enabling GTSAM_ROT3_EXPMAP as well")
|
||||||
|
set(GTSAM_ROT3_EXPMAP 1 CACHE BOOL "" FORCE)
|
||||||
|
elseif(GTSAM_ROT3_EXPMAP)
|
||||||
|
message(STATUS "GTSAM_ROT3_EXPMAP=ON, enabling GTSAM_POSE3_EXPMAP as well")
|
||||||
|
set(GTSAM_POSE3_EXPMAP 1 CACHE BOOL "" FORCE)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Options relating to MATLAB wrapper
|
||||||
|
# TODO: Check for matlab mex binary before handling building of binaries
|
||||||
|
option(GTSAM_INSTALL_MATLAB_TOOLBOX "Enable/Disable installation of matlab toolbox" OFF)
|
||||||
|
set(GTSAM_PYTHON_VERSION "Default" CACHE STRING "The version of Python to build the wrappers against.")
|
||||||
|
|
||||||
|
# Check / set dependent variables for MATLAB wrapper
|
||||||
|
if(GTSAM_INSTALL_MATLAB_TOOLBOX AND GTSAM_BUILD_TYPE_POSTFIXES)
|
||||||
|
set(CURRENT_POSTFIX ${CMAKE_${CMAKE_BUILD_TYPE_UPPER}_POSTFIX})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(GTSAM_INSTALL_MATLAB_TOOLBOX AND NOT BUILD_SHARED_LIBS)
|
||||||
|
message(FATAL_ERROR "GTSAM_INSTALL_MATLAB_TOOLBOX and BUILD_SHARED_LIBS=OFF. The MATLAB wrapper cannot be compiled with a static GTSAM library because mex modules are themselves shared libraries. If you want a self-contained mex module, enable GTSAM_MEX_BUILD_STATIC_MODULE instead of BUILD_SHARED_LIBS=OFF.")
|
||||||
|
endif()
|
|
@ -0,0 +1,52 @@
|
||||||
|
# JLBC: These should ideally be ported to "modern cmake" via target properties.
|
||||||
|
#
|
||||||
|
|
||||||
|
if (CMAKE_GENERATOR STREQUAL "Ninja" AND
|
||||||
|
((CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.9) OR
|
||||||
|
(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.5)))
|
||||||
|
# Force colored warnings in Ninja's output, if the compiler has -fdiagnostics-color support.
|
||||||
|
# Rationale in https://github.com/ninja-build/ninja/issues/814
|
||||||
|
add_compile_options(-fdiagnostics-color=always)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
# If building DLLs in MSVC, we need to avoid EIGEN_STATIC_ASSERT()
|
||||||
|
# or explicit instantiation will generate build errors.
|
||||||
|
# See: https://bitbucket.org/gtborg/gtsam/issues/417/fail-to-build-on-msvc-2017
|
||||||
|
#
|
||||||
|
if(MSVC AND BUILD_SHARED_LIBS)
|
||||||
|
list_append_cache(GTSAM_COMPILE_DEFINITIONS_PUBLIC EIGEN_NO_STATIC_ASSERT)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (APPLE AND BUILD_SHARED_LIBS)
|
||||||
|
# Set the default install directory on macOS
|
||||||
|
set(CMAKE_INSTALL_NAME_DIR "${CMAKE_INSTALL_PREFIX}/lib")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# Global compile options
|
||||||
|
|
||||||
|
if(MSVC)
|
||||||
|
list_append_cache(GTSAM_COMPILE_DEFINITIONS_PRIVATE _CRT_SECURE_NO_WARNINGS _SCL_SECURE_NO_WARNINGS)
|
||||||
|
list_append_cache(GTSAM_COMPILE_OPTIONS_PRIVATE /wd4251 /wd4275 /wd4251 /wd4661 /wd4344 /wd4503) # Disable non-DLL-exported base class and other warnings
|
||||||
|
list_append_cache(GTSAM_COMPILE_OPTIONS_PRIVATE /bigobj) # Allow large object files for template-based code
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# GCC 4.8+ complains about local typedefs which we use for shared_ptr etc.
|
||||||
|
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||||
|
if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.8)
|
||||||
|
list_append_cache(GTSAM_COMPILE_OPTIONS_PRIVATE -Wno-unused-local-typedefs)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# As of XCode 7, clang also complains about this
|
||||||
|
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||||
|
if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 7.0)
|
||||||
|
list_append_cache(GTSAM_COMPILE_OPTIONS_PRIVATE -Wno-unused-local-typedefs)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(GTSAM_ENABLE_CONSISTENCY_CHECKS)
|
||||||
|
# This should be made PUBLIC if GTSAM_EXTRA_CONSISTENCY_CHECKS is someday used in a public .h
|
||||||
|
list_append_cache(GTSAM_COMPILE_DEFINITIONS_PRIVATE GTSAM_EXTRA_CONSISTENCY_CHECKS)
|
||||||
|
endif()
|
|
@ -0,0 +1,17 @@
|
||||||
|
###############################################################################
|
||||||
|
# Find MKL
|
||||||
|
find_package(MKL)
|
||||||
|
|
||||||
|
if(MKL_FOUND AND GTSAM_WITH_EIGEN_MKL)
|
||||||
|
set(GTSAM_USE_EIGEN_MKL 1) # This will go into config.h
|
||||||
|
set(EIGEN_USE_MKL_ALL 1) # This will go into config.h - it makes Eigen use MKL
|
||||||
|
list(APPEND GTSAM_ADDITIONAL_LIBRARIES ${MKL_LIBRARIES})
|
||||||
|
|
||||||
|
# --no-as-needed is required with gcc according to the MKL link advisor
|
||||||
|
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||||
|
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--no-as-needed")
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
set(GTSAM_USE_EIGEN_MKL 0)
|
||||||
|
set(EIGEN_USE_MKL_ALL 0)
|
||||||
|
endif()
|
|
@ -0,0 +1,11 @@
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# Find OpenMP (if we're also using MKL)
|
||||||
|
find_package(OpenMP) # do this here to generate correct message if disabled
|
||||||
|
|
||||||
|
if(GTSAM_WITH_EIGEN_MKL AND GTSAM_WITH_EIGEN_MKL_OPENMP AND GTSAM_USE_EIGEN_MKL)
|
||||||
|
if(OPENMP_FOUND AND GTSAM_USE_EIGEN_MKL AND GTSAM_WITH_EIGEN_MKL_OPENMP)
|
||||||
|
set(GTSAM_USE_EIGEN_MKL_OPENMP 1) # This will go into config.h
|
||||||
|
list_append_cache(GTSAM_COMPILE_OPTIONS_PUBLIC ${OpenMP_CXX_FLAGS})
|
||||||
|
endif()
|
||||||
|
endif()
|
|
@ -0,0 +1,4 @@
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# Find Google perftools
|
||||||
|
find_package(GooglePerfTools)
|
|
@ -0,0 +1,104 @@
|
||||||
|
###############################################################################
|
||||||
|
# Print configuration variables
|
||||||
|
message(STATUS "===============================================================")
|
||||||
|
message(STATUS "================ Configuration Options ======================")
|
||||||
|
print_config("CMAKE_CXX_COMPILER_ID type" "${CMAKE_CXX_COMPILER_ID}")
|
||||||
|
print_config("CMAKE_CXX_COMPILER_VERSION" "${CMAKE_CXX_COMPILER_VERSION}")
|
||||||
|
print_config("CMake version" "${CMAKE_VERSION}")
|
||||||
|
print_config("CMake generator" "${CMAKE_GENERATOR}")
|
||||||
|
print_config("CMake build tool" "${CMAKE_BUILD_TOOL}")
|
||||||
|
message(STATUS "Build flags ")
|
||||||
|
print_enabled_config(${GTSAM_BUILD_TESTS} "Build Tests")
|
||||||
|
print_enabled_config(${GTSAM_BUILD_EXAMPLES_ALWAYS} "Build examples with 'make all'")
|
||||||
|
print_enabled_config(${GTSAM_BUILD_TIMING_ALWAYS} "Build timing scripts with 'make all'")
|
||||||
|
if (DOXYGEN_FOUND)
|
||||||
|
print_enabled_config(${GTSAM_BUILD_DOCS} "Build Docs")
|
||||||
|
endif()
|
||||||
|
print_enabled_config(${BUILD_SHARED_LIBS} "Build shared GTSAM libraries")
|
||||||
|
print_enabled_config(${GTSAM_BUILD_TYPE_POSTFIXES} "Put build type in library name")
|
||||||
|
if(GTSAM_UNSTABLE_AVAILABLE)
|
||||||
|
print_enabled_config(${GTSAM_BUILD_UNSTABLE} "Build libgtsam_unstable ")
|
||||||
|
print_enabled_config(${GTSAM_UNSTABLE_BUILD_PYTHON} "Build GTSAM unstable Python ")
|
||||||
|
print_enabled_config(${GTSAM_UNSTABLE_INSTALL_MATLAB_TOOLBOX} "Build MATLAB Toolbox for unstable")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT MSVC AND NOT XCODE_VERSION)
|
||||||
|
print_enabled_config(${GTSAM_BUILD_WITH_MARCH_NATIVE} "Build for native architecture ")
|
||||||
|
print_config("Build type" "${CMAKE_BUILD_TYPE}")
|
||||||
|
print_config("C compilation flags" "${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_${CMAKE_BUILD_TYPE_UPPER}}")
|
||||||
|
print_config("C++ compilation flags" "${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_${CMAKE_BUILD_TYPE_UPPER}}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
print_build_options_for_target(gtsam)
|
||||||
|
|
||||||
|
print_config("Use System Eigen" "${GTSAM_USE_SYSTEM_EIGEN} (Using version: ${GTSAM_EIGEN_VERSION})")
|
||||||
|
|
||||||
|
if(GTSAM_USE_TBB)
|
||||||
|
print_config("Use Intel TBB" "Yes (Version: ${TBB_VERSION})")
|
||||||
|
elseif(TBB_FOUND)
|
||||||
|
print_config("Use Intel TBB" "TBB (Version: ${TBB_VERSION}) found but GTSAM_WITH_TBB is disabled")
|
||||||
|
else()
|
||||||
|
print_config("Use Intel TBB" "TBB not found")
|
||||||
|
endif()
|
||||||
|
if(GTSAM_USE_EIGEN_MKL)
|
||||||
|
print_config("Eigen will use MKL" "Yes")
|
||||||
|
elseif(MKL_FOUND)
|
||||||
|
print_config("Eigen will use MKL" "MKL found but GTSAM_WITH_EIGEN_MKL is disabled")
|
||||||
|
else()
|
||||||
|
print_config("Eigen will use MKL" "MKL not found")
|
||||||
|
endif()
|
||||||
|
if(GTSAM_USE_EIGEN_MKL_OPENMP)
|
||||||
|
print_config("Eigen will use MKL and OpenMP" "Yes")
|
||||||
|
elseif(OPENMP_FOUND AND NOT GTSAM_WITH_EIGEN_MKL)
|
||||||
|
print_config("Eigen will use MKL and OpenMP" "OpenMP found but GTSAM_WITH_EIGEN_MKL is disabled")
|
||||||
|
elseif(OPENMP_FOUND AND NOT MKL_FOUND)
|
||||||
|
print_config("Eigen will use MKL and OpenMP" "OpenMP found but MKL not found")
|
||||||
|
elseif(OPENMP_FOUND)
|
||||||
|
print_config("Eigen will use MKL and OpenMP" "OpenMP found but GTSAM_WITH_EIGEN_MKL_OPENMP is disabled")
|
||||||
|
else()
|
||||||
|
print_config("Eigen will use MKL and OpenMP" "OpenMP not found")
|
||||||
|
endif()
|
||||||
|
print_config("Default allocator" "${GTSAM_DEFAULT_ALLOCATOR}")
|
||||||
|
|
||||||
|
if(GTSAM_THROW_CHEIRALITY_EXCEPTION)
|
||||||
|
print_config("Cheirality exceptions enabled" "YES")
|
||||||
|
else()
|
||||||
|
print_config("Cheirality exceptions enabled" "NO")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT MSVC AND NOT XCODE_VERSION)
|
||||||
|
if(CCACHE_FOUND AND GTSAM_BUILD_WITH_CCACHE)
|
||||||
|
print_config("Build with ccache" "Yes")
|
||||||
|
elseif(CCACHE_FOUND)
|
||||||
|
print_config("Build with ccache" "ccache found but GTSAM_BUILD_WITH_CCACHE is disabled")
|
||||||
|
else()
|
||||||
|
print_config("Build with ccache" "No")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
message(STATUS "Packaging flags")
|
||||||
|
print_config("CPack Source Generator" "${CPACK_SOURCE_GENERATOR}")
|
||||||
|
print_config("CPack Generator" "${CPACK_GENERATOR}")
|
||||||
|
|
||||||
|
message(STATUS "GTSAM flags ")
|
||||||
|
print_enabled_config(${GTSAM_USE_QUATERNIONS} "Quaternions as default Rot3 ")
|
||||||
|
print_enabled_config(${GTSAM_ENABLE_CONSISTENCY_CHECKS} "Runtime consistency checking ")
|
||||||
|
print_enabled_config(${GTSAM_ROT3_EXPMAP} "Rot3 retract is full ExpMap ")
|
||||||
|
print_enabled_config(${GTSAM_POSE3_EXPMAP} "Pose3 retract is full ExpMap ")
|
||||||
|
print_enabled_config(${GTSAM_ALLOW_DEPRECATED_SINCE_V41} "Allow features deprecated in GTSAM 4.1")
|
||||||
|
print_enabled_config(${GTSAM_SUPPORT_NESTED_DISSECTION} "Metis-based Nested Dissection ")
|
||||||
|
print_enabled_config(${GTSAM_TANGENT_PREINTEGRATION} "Use tangent-space preintegration")
|
||||||
|
|
||||||
|
message(STATUS "MATLAB toolbox flags")
|
||||||
|
print_enabled_config(${GTSAM_INSTALL_MATLAB_TOOLBOX} "Install MATLAB toolbox ")
|
||||||
|
if (${GTSAM_INSTALL_MATLAB_TOOLBOX})
|
||||||
|
print_config("MATLAB root" "${MATLAB_ROOT}")
|
||||||
|
print_config("MEX binary" "${MEX_COMMAND}")
|
||||||
|
endif()
|
||||||
|
message(STATUS "Python toolbox flags ")
|
||||||
|
print_enabled_config(${GTSAM_BUILD_PYTHON} "Build Python module with pybind ")
|
||||||
|
if(GTSAM_BUILD_PYTHON)
|
||||||
|
print_config("Python version" ${GTSAM_PYTHON_VERSION})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
message(STATUS "===============================================================")
|
|
@ -0,0 +1,29 @@
|
||||||
|
# Set Python version if either Python or MATLAB wrapper is requested.
|
||||||
|
if(GTSAM_BUILD_PYTHON OR GTSAM_INSTALL_MATLAB_TOOLBOX)
|
||||||
|
if(${GTSAM_PYTHON_VERSION} STREQUAL "Default")
|
||||||
|
# Get info about the Python3 interpreter
|
||||||
|
# https://cmake.org/cmake/help/latest/module/FindPython3.html#module:FindPython3
|
||||||
|
find_package(Python3 COMPONENTS Interpreter Development)
|
||||||
|
|
||||||
|
if(NOT ${Python3_FOUND})
|
||||||
|
message(FATAL_ERROR "Cannot find Python3 interpreter. Please install Python >= 3.6.")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(GTSAM_PYTHON_VERSION "${Python3_VERSION_MAJOR}.${Python3_VERSION_MINOR}"
|
||||||
|
CACHE
|
||||||
|
STRING
|
||||||
|
"The version of Python to build the wrappers against."
|
||||||
|
FORCE)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(GTSAM_BUILD_PYTHON)
|
||||||
|
if(GTSAM_UNSTABLE_BUILD_PYTHON)
|
||||||
|
if (NOT GTSAM_BUILD_UNSTABLE)
|
||||||
|
message(WARNING "GTSAM_UNSTABLE_BUILD_PYTHON requires the unstable module to be enabled.")
|
||||||
|
set(GTSAM_UNSTABLE_BUILD_PYTHON OFF)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(GTSAM_PY_INSTALL_PATH "${CMAKE_INSTALL_PREFIX}/python")
|
||||||
|
endif()
|
|
@ -0,0 +1,24 @@
|
||||||
|
###############################################################################
|
||||||
|
# Find TBB
|
||||||
|
find_package(TBB 4.4 COMPONENTS tbb tbbmalloc)
|
||||||
|
|
||||||
|
# Set up variables if we're using TBB
|
||||||
|
if(TBB_FOUND AND GTSAM_WITH_TBB)
|
||||||
|
set(GTSAM_USE_TBB 1) # This will go into config.h
|
||||||
|
if ((${TBB_VERSION_MAJOR} GREATER 2020) OR (${TBB_VERSION_MAJOR} EQUAL 2020))
|
||||||
|
set(TBB_GREATER_EQUAL_2020 1)
|
||||||
|
else()
|
||||||
|
set(TBB_GREATER_EQUAL_2020 0)
|
||||||
|
endif()
|
||||||
|
# all definitions and link requisites will go via imported targets:
|
||||||
|
# tbb & tbbmalloc
|
||||||
|
list(APPEND GTSAM_ADDITIONAL_LIBRARIES tbb tbbmalloc)
|
||||||
|
else()
|
||||||
|
set(GTSAM_USE_TBB 0) # This will go into config.h
|
||||||
|
endif()
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# Prohibit Timing build mode in combination with TBB
|
||||||
|
if(GTSAM_USE_TBB AND (CMAKE_BUILD_TYPE STREQUAL "Timing"))
|
||||||
|
message(FATAL_ERROR "Timing build mode cannot be used together with TBB. Use a sampling profiler such as Instruments or Intel VTune Amplifier instead.")
|
||||||
|
endif()
|
|
@ -0,0 +1,10 @@
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
# Uninstall target, for "make uninstall"
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
configure_file(
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in"
|
||||||
|
"${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
|
||||||
|
IMMEDIATE @ONLY)
|
||||||
|
|
||||||
|
add_custom_target(uninstall
|
||||||
|
"${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake")
|
|
@ -1188,7 +1188,7 @@ USE_MATHJAX = YES
|
||||||
# MathJax, but it is strongly recommended to install a local copy of MathJax
|
# MathJax, but it is strongly recommended to install a local copy of MathJax
|
||||||
# before deployment.
|
# before deployment.
|
||||||
|
|
||||||
MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
|
MATHJAX_RELPATH = https://cdn.mathjax.org/mathjax/latest
|
||||||
|
|
||||||
# The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension
|
# The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension
|
||||||
# names that should be enabled during MathJax rendering.
|
# names that should be enabled during MathJax rendering.
|
||||||
|
|
|
@ -90,7 +90,7 @@ bool equal_with_abs_tol(const Eigen::DenseBase<MATRIX>& A, const Eigen::DenseBas
|
||||||
|
|
||||||
for(size_t i=0; i<m1; i++)
|
for(size_t i=0; i<m1; i++)
|
||||||
for(size_t j=0; j<n1; j++) {
|
for(size_t j=0; j<n1; j++) {
|
||||||
if(!fpEqual(A(i,j), B(i,j), tol)) {
|
if(!fpEqual(A(i,j), B(i,j), tol, false)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#include <boost/optional.hpp>
|
#include <boost/optional.hpp>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace gtsam {
|
namespace gtsam {
|
||||||
|
@ -349,4 +350,44 @@ bool assert_inequal(const V& expected, const V& actual, double tol = 1e-9) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Capture std out via cout stream and compare against string.
|
||||||
|
*/
|
||||||
|
template<class V>
|
||||||
|
bool assert_stdout_equal(const std::string& expected, const V& actual) {
|
||||||
|
// Redirect output to buffer so we can compare
|
||||||
|
std::stringstream buffer;
|
||||||
|
// Save the original output stream so we can reset later
|
||||||
|
std::streambuf* old = std::cout.rdbuf(buffer.rdbuf());
|
||||||
|
|
||||||
|
// We test against actual std::cout for faithful reproduction
|
||||||
|
std::cout << actual;
|
||||||
|
|
||||||
|
// Get output string and reset stdout
|
||||||
|
std::string actual_ = buffer.str();
|
||||||
|
std::cout.rdbuf(old);
|
||||||
|
|
||||||
|
return assert_equal(expected, actual_);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Capture print function output and compare against string.
|
||||||
|
*/
|
||||||
|
template<class V>
|
||||||
|
bool assert_print_equal(const std::string& expected, const V& actual) {
|
||||||
|
// Redirect output to buffer so we can compare
|
||||||
|
std::stringstream buffer;
|
||||||
|
// Save the original output stream so we can reset later
|
||||||
|
std::streambuf* old = std::cout.rdbuf(buffer.rdbuf());
|
||||||
|
|
||||||
|
// We test against actual std::cout for faithful reproduction
|
||||||
|
actual.print();
|
||||||
|
|
||||||
|
// Get output string and reset stdout
|
||||||
|
std::string actual_ = buffer.str();
|
||||||
|
std::cout.rdbuf(old);
|
||||||
|
|
||||||
|
return assert_equal(expected, actual_);
|
||||||
|
}
|
||||||
|
|
||||||
} // \namespace gtsam
|
} // \namespace gtsam
|
||||||
|
|
|
@ -39,7 +39,7 @@ namespace gtsam {
|
||||||
* 1. https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/
|
* 1. https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/
|
||||||
* 2. https://floating-point-gui.de/errors/comparison/
|
* 2. https://floating-point-gui.de/errors/comparison/
|
||||||
* ************************************************************************* */
|
* ************************************************************************* */
|
||||||
bool fpEqual(double a, double b, double tol) {
|
bool fpEqual(double a, double b, double tol, bool check_relative_also) {
|
||||||
using std::abs;
|
using std::abs;
|
||||||
using std::isnan;
|
using std::isnan;
|
||||||
using std::isinf;
|
using std::isinf;
|
||||||
|
@ -48,7 +48,7 @@ bool fpEqual(double a, double b, double tol) {
|
||||||
double larger = (abs(b) > abs(a)) ? abs(b) : abs(a);
|
double larger = (abs(b) > abs(a)) ? abs(b) : abs(a);
|
||||||
|
|
||||||
// handle NaNs
|
// handle NaNs
|
||||||
if(std::isnan(a) || isnan(b)) {
|
if(isnan(a) || isnan(b)) {
|
||||||
return isnan(a) && isnan(b);
|
return isnan(a) && isnan(b);
|
||||||
}
|
}
|
||||||
// handle inf
|
// handle inf
|
||||||
|
@ -60,13 +60,15 @@ bool fpEqual(double a, double b, double tol) {
|
||||||
else if(a == 0 || b == 0 || (abs(a) + abs(b)) < DOUBLE_MIN_NORMAL) {
|
else if(a == 0 || b == 0 || (abs(a) + abs(b)) < DOUBLE_MIN_NORMAL) {
|
||||||
return abs(a-b) <= tol * DOUBLE_MIN_NORMAL;
|
return abs(a-b) <= tol * DOUBLE_MIN_NORMAL;
|
||||||
}
|
}
|
||||||
// Check if the numbers are really close
|
// Check if the numbers are really close.
|
||||||
// Needed when comparing numbers near zero or tol is in vicinity
|
// Needed when comparing numbers near zero or tol is in vicinity.
|
||||||
else if(abs(a-b) <= tol) {
|
else if (abs(a - b) <= tol) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// Use relative error
|
// Check for relative error
|
||||||
else if(abs(a-b) <= tol * min(larger, std::numeric_limits<double>::max())) {
|
else if (abs(a - b) <=
|
||||||
|
tol * min(larger, std::numeric_limits<double>::max()) &&
|
||||||
|
check_relative_also) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -85,9 +85,15 @@ static_assert(
|
||||||
* respectively for the comparison to be true.
|
* respectively for the comparison to be true.
|
||||||
* If one is NaN/Inf and the other is not, returns false.
|
* If one is NaN/Inf and the other is not, returns false.
|
||||||
*
|
*
|
||||||
|
* @param check_relative_also is a flag which toggles additional checking for
|
||||||
|
* relative error. This means that if either the absolute error or the relative
|
||||||
|
* error is within the tolerance, the result will be true.
|
||||||
|
* By default, the flag is true.
|
||||||
|
*
|
||||||
* Return true if two numbers are close wrt tol.
|
* Return true if two numbers are close wrt tol.
|
||||||
*/
|
*/
|
||||||
GTSAM_EXPORT bool fpEqual(double a, double b, double tol);
|
GTSAM_EXPORT bool fpEqual(double a, double b, double tol,
|
||||||
|
bool check_relative_also = true);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* print without optional string, must specify cout yourself
|
* print without optional string, must specify cout yourself
|
||||||
|
|
|
@ -1163,6 +1163,19 @@ TEST(Matrix , IsVectorSpace) {
|
||||||
BOOST_CONCEPT_ASSERT((IsVectorSpace<Vector5>));
|
BOOST_CONCEPT_ASSERT((IsVectorSpace<Vector5>));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(Matrix, AbsoluteError) {
|
||||||
|
double a = 2000, b = 1997, tol = 1e-1;
|
||||||
|
bool isEqual;
|
||||||
|
|
||||||
|
// Test only absolute error
|
||||||
|
isEqual = fpEqual(a, b, tol, false);
|
||||||
|
EXPECT(!isEqual);
|
||||||
|
|
||||||
|
// Test relative error as well
|
||||||
|
isEqual = fpEqual(a, b, tol);
|
||||||
|
EXPECT(isEqual);
|
||||||
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
int main() {
|
int main() {
|
||||||
TestResult tr;
|
TestResult tr;
|
||||||
|
|
|
@ -98,6 +98,17 @@ public:
|
||||||
return k2_;
|
return k2_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// image center in x
|
||||||
|
inline double px() const {
|
||||||
|
return u0_;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// image center in y
|
||||||
|
inline double py() const {
|
||||||
|
return v0_;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef GTSAM_ALLOW_DEPRECATED_SINCE_V41
|
||||||
/// get parameter u0
|
/// get parameter u0
|
||||||
inline double u0() const {
|
inline double u0() const {
|
||||||
return u0_;
|
return u0_;
|
||||||
|
@ -107,6 +118,7 @@ public:
|
||||||
inline double v0() const {
|
inline double v0() const {
|
||||||
return v0_;
|
return v0_;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -262,9 +262,29 @@ namespace gtsam {
|
||||||
static Rot3 AlignTwoPairs(const Unit3& a_p, const Unit3& b_p, //
|
static Rot3 AlignTwoPairs(const Unit3& a_p, const Unit3& b_p, //
|
||||||
const Unit3& a_q, const Unit3& b_q);
|
const Unit3& a_q, const Unit3& b_q);
|
||||||
|
|
||||||
/// Static, named constructor that finds Rot3 element closest to M in Frobenius norm.
|
/**
|
||||||
|
* Static, named constructor that finds Rot3 element closest to M in Frobenius norm.
|
||||||
|
*
|
||||||
|
* Uses Full SVD to compute the orthogonal matrix, thus is highly accurate and robust.
|
||||||
|
*
|
||||||
|
* N. J. Higham. Matrix nearness problems and applications.
|
||||||
|
* In M. J. C. Gover and S. Barnett, editors, Applications of Matrix Theory, pages 1–27.
|
||||||
|
* Oxford University Press, 1989.
|
||||||
|
*/
|
||||||
static Rot3 ClosestTo(const Matrix3& M) { return Rot3(SO3::ClosestTo(M)); }
|
static Rot3 ClosestTo(const Matrix3& M) { return Rot3(SO3::ClosestTo(M)); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Normalize rotation so that its determinant is 1.
|
||||||
|
* This means either re-orthogonalizing the Matrix representation or
|
||||||
|
* normalizing the quaternion representation.
|
||||||
|
*
|
||||||
|
* This method is akin to `ClosestTo` but uses a computationally cheaper
|
||||||
|
* algorithm.
|
||||||
|
*
|
||||||
|
* Ref: https://drive.google.com/file/d/0B9rLLz1XQKmaZTlQdV81QjNoZTA/view
|
||||||
|
*/
|
||||||
|
Rot3 normalized() const;
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
/// @name Testable
|
/// @name Testable
|
||||||
/// @{
|
/// @{
|
||||||
|
@ -506,7 +526,7 @@ namespace gtsam {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Spherical Linear intERPolation between *this and other
|
* @brief Spherical Linear intERPolation between *this and other
|
||||||
* @param s a value between 0 and 1
|
* @param t a value between 0 and 1
|
||||||
* @param other final point of iterpolation geodesic on manifold
|
* @param other final point of iterpolation geodesic on manifold
|
||||||
*/
|
*/
|
||||||
Rot3 slerp(double t, const Rot3& other) const;
|
Rot3 slerp(double t, const Rot3& other) const;
|
||||||
|
|
|
@ -108,6 +108,33 @@ Rot3 Rot3::RzRyRx(double x, double y, double z, OptionalJacobian<3, 1> Hx,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
Rot3 Rot3::normalized() const {
|
||||||
|
/// Implementation from here: https://stackoverflow.com/a/23082112/1236990
|
||||||
|
|
||||||
|
/// Essentially, this computes the orthogonalization error, distributes the
|
||||||
|
/// error to the x and y rows, and then performs a Taylor expansion to
|
||||||
|
/// orthogonalize.
|
||||||
|
|
||||||
|
Matrix3 rot = rot_.matrix(), rot_orth;
|
||||||
|
|
||||||
|
// Check if determinant is already 1.
|
||||||
|
// If yes, then return the current Rot3.
|
||||||
|
if (std::fabs(rot.determinant()-1) < 1e-12) return Rot3(rot_);
|
||||||
|
|
||||||
|
Vector3 x = rot.block<1, 3>(0, 0), y = rot.block<1, 3>(1, 0);
|
||||||
|
double error = x.dot(y);
|
||||||
|
|
||||||
|
Vector3 x_ort = x - (error / 2) * y, y_ort = y - (error / 2) * x;
|
||||||
|
Vector3 z_ort = x_ort.cross(y_ort);
|
||||||
|
|
||||||
|
rot_orth.block<1, 3>(0, 0) = 0.5 * (3 - x_ort.dot(x_ort)) * x_ort;
|
||||||
|
rot_orth.block<1, 3>(1, 0) = 0.5 * (3 - y_ort.dot(y_ort)) * y_ort;
|
||||||
|
rot_orth.block<1, 3>(2, 0) = 0.5 * (3 - z_ort.dot(z_ort)) * z_ort;
|
||||||
|
|
||||||
|
return Rot3(rot_orth);
|
||||||
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
Rot3 Rot3::operator*(const Rot3& R2) const {
|
Rot3 Rot3::operator*(const Rot3& R2) const {
|
||||||
return Rot3(rot_*R2.rot_);
|
return Rot3(rot_*R2.rot_);
|
||||||
|
@ -149,7 +176,17 @@ Vector3 Rot3::CayleyChart::Local(const Rot3& R, OptionalJacobian<3,3> H) {
|
||||||
if (H) throw std::runtime_error("Rot3::CayleyChart::Local Derivative");
|
if (H) throw std::runtime_error("Rot3::CayleyChart::Local Derivative");
|
||||||
// Create a fixed-size matrix
|
// Create a fixed-size matrix
|
||||||
Matrix3 A = R.matrix();
|
Matrix3 A = R.matrix();
|
||||||
// Mathematica closed form optimization (procrastination?) gone wild:
|
|
||||||
|
// Check if (A+I) is invertible. Same as checking for -1 eigenvalue.
|
||||||
|
if ((A + I_3x3).determinant() == 0.0) {
|
||||||
|
throw std::runtime_error("Rot3::CayleyChart::Local Invalid Rotation");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mathematica closed form optimization.
|
||||||
|
// The following are the essential computations for the following algorithm
|
||||||
|
// 1. Compute the inverse of P = (A+I), using a closed-form formula since P is 3x3
|
||||||
|
// 2. Compute the Cayley transform C = 2 * P^{-1} * (A-I)
|
||||||
|
// 3. C is skew-symmetric, so we pick out the computations corresponding only to x, y, and z.
|
||||||
const double a = A(0, 0), b = A(0, 1), c = A(0, 2);
|
const double a = A(0, 0), b = A(0, 1), c = A(0, 2);
|
||||||
const double d = A(1, 0), e = A(1, 1), f = A(1, 2);
|
const double d = A(1, 0), e = A(1, 1), f = A(1, 2);
|
||||||
const double g = A(2, 0), h = A(2, 1), i = A(2, 2);
|
const double g = A(2, 0), h = A(2, 1), i = A(2, 2);
|
||||||
|
|
|
@ -86,6 +86,10 @@ namespace gtsam {
|
||||||
gtsam::Quaternion(Eigen::AngleAxisd(x, Eigen::Vector3d::UnitX())));
|
gtsam::Quaternion(Eigen::AngleAxisd(x, Eigen::Vector3d::UnitX())));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
Rot3 Rot3::normalized() const {
|
||||||
|
return Rot3(quaternion_.normalized());
|
||||||
|
}
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
Rot3 Rot3::operator*(const Rot3& R2) const {
|
Rot3 Rot3::operator*(const Rot3& R2) const {
|
||||||
return Rot3(quaternion_ * R2.quaternion_);
|
return Rot3(quaternion_ * R2.quaternion_);
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
#include <CppUnitLite/TestHarness.h>
|
#include <CppUnitLite/TestHarness.h>
|
||||||
#include <gtsam/base/Testable.h>
|
#include <gtsam/base/Testable.h>
|
||||||
|
#include <gtsam/base/TestableAssertions.h>
|
||||||
#include <gtsam/base/numericalDerivative.h>
|
#include <gtsam/base/numericalDerivative.h>
|
||||||
#include <gtsam/geometry/Cal3_S2.h>
|
#include <gtsam/geometry/Cal3_S2.h>
|
||||||
|
|
||||||
|
@ -127,6 +128,16 @@ TEST(Cal3_S2, between) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
TEST(Cal3_S2, Print) {
|
||||||
|
Cal3_S2 cal(5, 5, 5, 5, 5);
|
||||||
|
std::stringstream os;
|
||||||
|
os << "{fx: " << cal.fx() << ", fy: " << cal.fy() << ", s:" << cal.skew() << ", px:" << cal.px()
|
||||||
|
<< ", py:" << cal.py() << "}";
|
||||||
|
|
||||||
|
EXPECT(assert_stdout_equal(os.str(), cal));
|
||||||
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
int main() {
|
int main() {
|
||||||
TestResult tr;
|
TestResult tr;
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include <gtsam/geometry/Pose2.h>
|
#include <gtsam/geometry/Pose2.h>
|
||||||
#include <gtsam/base/testLie.h>
|
#include <gtsam/base/testLie.h>
|
||||||
#include <gtsam/base/lieProxies.h>
|
#include <gtsam/base/lieProxies.h>
|
||||||
|
#include <gtsam/base/TestableAssertions.h>
|
||||||
|
|
||||||
#include <boost/assign/std/vector.hpp> // for operator +=
|
#include <boost/assign/std/vector.hpp> // for operator +=
|
||||||
using namespace boost::assign;
|
using namespace boost::assign;
|
||||||
|
@ -906,9 +907,9 @@ TEST(Pose3 , ChartDerivatives) {
|
||||||
Pose3 id;
|
Pose3 id;
|
||||||
if (ROT3_DEFAULT_COORDINATES_MODE == Rot3::EXPMAP) {
|
if (ROT3_DEFAULT_COORDINATES_MODE == Rot3::EXPMAP) {
|
||||||
CHECK_CHART_DERIVATIVES(id,id);
|
CHECK_CHART_DERIVATIVES(id,id);
|
||||||
// CHECK_CHART_DERIVATIVES(id,T2);
|
CHECK_CHART_DERIVATIVES(id,T2);
|
||||||
// CHECK_CHART_DERIVATIVES(T2,id);
|
CHECK_CHART_DERIVATIVES(T2,id);
|
||||||
// CHECK_CHART_DERIVATIVES(T2,T3);
|
CHECK_CHART_DERIVATIVES(T2,T3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1028,32 +1029,13 @@ TEST(Pose3, Create) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
TEST(Pose3, print) {
|
TEST(Pose3, Print) {
|
||||||
std::stringstream redirectStream;
|
|
||||||
std::streambuf* ssbuf = redirectStream.rdbuf();
|
|
||||||
std::streambuf* oldbuf = std::cout.rdbuf();
|
|
||||||
// redirect cout to redirectStream
|
|
||||||
std::cout.rdbuf(ssbuf);
|
|
||||||
|
|
||||||
Pose3 pose(Rot3::identity(), Point3(1, 2, 3));
|
Pose3 pose(Rot3::identity(), Point3(1, 2, 3));
|
||||||
// output is captured to redirectStream
|
|
||||||
pose.print();
|
|
||||||
|
|
||||||
// Generate the expected output
|
// Generate the expected output
|
||||||
std::stringstream expected;
|
std::string expected = "R: [\n\t1, 0, 0;\n\t0, 1, 0;\n\t0, 0, 1\n]\nt: 1 2 3\n";
|
||||||
Point3 translation(1, 2, 3);
|
|
||||||
|
|
||||||
// Add expected rotation
|
EXPECT(assert_print_equal(expected, pose));
|
||||||
expected << "R: [\n\t1, 0, 0;\n\t0, 1, 0;\n\t0, 0, 1\n]\n";
|
|
||||||
expected << "t: 1 2 3\n";
|
|
||||||
|
|
||||||
// reset cout to the original stream
|
|
||||||
std::cout.rdbuf(oldbuf);
|
|
||||||
|
|
||||||
// Get substring corresponding to translation part
|
|
||||||
std::string actual = redirectStream.str();
|
|
||||||
|
|
||||||
CHECK_EQUAL(expected.str(), actual);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
|
|
|
@ -807,15 +807,15 @@ TEST(Rot3, RQ_derivative) {
|
||||||
test_xyz.push_back(VecAndErr{{0, 0, 0}, error});
|
test_xyz.push_back(VecAndErr{{0, 0, 0}, error});
|
||||||
test_xyz.push_back(VecAndErr{{0, 0.5, -0.5}, error});
|
test_xyz.push_back(VecAndErr{{0, 0.5, -0.5}, error});
|
||||||
test_xyz.push_back(VecAndErr{{0.3, 0, 0.2}, error});
|
test_xyz.push_back(VecAndErr{{0.3, 0, 0.2}, error});
|
||||||
test_xyz.push_back(VecAndErr{{-0.6, 1.3, 0}, error});
|
test_xyz.push_back(VecAndErr{{-0.6, 1.3, 0}, 1e-8});
|
||||||
test_xyz.push_back(VecAndErr{{1.0, 0.7, 0.8}, error});
|
test_xyz.push_back(VecAndErr{{1.0, 0.7, 0.8}, error});
|
||||||
test_xyz.push_back(VecAndErr{{3.0, 0.7, -0.6}, error});
|
test_xyz.push_back(VecAndErr{{3.0, 0.7, -0.6}, error});
|
||||||
test_xyz.push_back(VecAndErr{{M_PI / 2, 0, 0}, error});
|
test_xyz.push_back(VecAndErr{{M_PI / 2, 0, 0}, error});
|
||||||
test_xyz.push_back(VecAndErr{{0, 0, M_PI / 2}, error});
|
test_xyz.push_back(VecAndErr{{0, 0, M_PI / 2}, error});
|
||||||
|
|
||||||
// Test close to singularity
|
// Test close to singularity
|
||||||
test_xyz.push_back(VecAndErr{{0, M_PI / 2 - 1e-1, 0}, 1e-8});
|
test_xyz.push_back(VecAndErr{{0, M_PI / 2 - 1e-1, 0}, 1e-7});
|
||||||
test_xyz.push_back(VecAndErr{{0, 3 * M_PI / 2 + 1e-1, 0}, 1e-8});
|
test_xyz.push_back(VecAndErr{{0, 3 * M_PI / 2 + 1e-1, 0}, 1e-7});
|
||||||
test_xyz.push_back(VecAndErr{{0, M_PI / 2 - 1.1e-2, 0}, 1e-4});
|
test_xyz.push_back(VecAndErr{{0, M_PI / 2 - 1.1e-2, 0}, 1e-4});
|
||||||
test_xyz.push_back(VecAndErr{{0, 3 * M_PI / 2 + 1.1e-2, 0}, 1e-4});
|
test_xyz.push_back(VecAndErr{{0, 3 * M_PI / 2 + 1.1e-2, 0}, 1e-4});
|
||||||
|
|
||||||
|
@ -910,6 +910,26 @@ TEST(Rot3, yaw_derivative) {
|
||||||
CHECK(assert_equal(num, calc));
|
CHECK(assert_equal(num, calc));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
TEST(Rot3, determinant) {
|
||||||
|
size_t degree = 1;
|
||||||
|
Rot3 R_w0; // Zero rotation
|
||||||
|
Rot3 R_w1 = Rot3::Ry(degree * M_PI / 180);
|
||||||
|
|
||||||
|
Rot3 R_01, R_w2;
|
||||||
|
double actual, expected = 1.0;
|
||||||
|
|
||||||
|
for (size_t i = 2; i < 360; ++i) {
|
||||||
|
R_01 = R_w0.between(R_w1);
|
||||||
|
R_w2 = R_w1 * R_01;
|
||||||
|
R_w0 = R_w1;
|
||||||
|
R_w1 = R_w2.normalized();
|
||||||
|
actual = R_w2.matrix().determinant();
|
||||||
|
|
||||||
|
EXPECT_DOUBLES_EQUAL(expected, actual, 1e-7);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
int main() {
|
int main() {
|
||||||
TestResult tr;
|
TestResult tr;
|
||||||
|
|
|
@ -57,7 +57,7 @@ static StereoCamera cam2(pose3, cal4ptr);
|
||||||
static StereoPoint2 spt(1.0, 2.0, 3.0);
|
static StereoPoint2 spt(1.0, 2.0, 3.0);
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
TEST_DISABLED (Serialization, text_geometry) {
|
TEST (Serialization, text_geometry) {
|
||||||
EXPECT(equalsObj<gtsam::Point2>(Point2(1.0, 2.0)));
|
EXPECT(equalsObj<gtsam::Point2>(Point2(1.0, 2.0)));
|
||||||
EXPECT(equalsObj<gtsam::Pose2>(Pose2(1.0, 2.0, 0.3)));
|
EXPECT(equalsObj<gtsam::Pose2>(Pose2(1.0, 2.0, 0.3)));
|
||||||
EXPECT(equalsObj<gtsam::Rot2>(Rot2::fromDegrees(30.0)));
|
EXPECT(equalsObj<gtsam::Rot2>(Rot2::fromDegrees(30.0)));
|
||||||
|
@ -82,7 +82,7 @@ TEST_DISABLED (Serialization, text_geometry) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
TEST_DISABLED (Serialization, xml_geometry) {
|
TEST (Serialization, xml_geometry) {
|
||||||
EXPECT(equalsXML<gtsam::Point2>(Point2(1.0, 2.0)));
|
EXPECT(equalsXML<gtsam::Point2>(Point2(1.0, 2.0)));
|
||||||
EXPECT(equalsXML<gtsam::Pose2>(Pose2(1.0, 2.0, 0.3)));
|
EXPECT(equalsXML<gtsam::Pose2>(Pose2(1.0, 2.0, 0.3)));
|
||||||
EXPECT(equalsXML<gtsam::Rot2>(Rot2::fromDegrees(30.0)));
|
EXPECT(equalsXML<gtsam::Rot2>(Rot2::fromDegrees(30.0)));
|
||||||
|
@ -106,7 +106,7 @@ TEST_DISABLED (Serialization, xml_geometry) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
TEST_DISABLED (Serialization, binary_geometry) {
|
TEST (Serialization, binary_geometry) {
|
||||||
EXPECT(equalsBinary<gtsam::Point2>(Point2(1.0, 2.0)));
|
EXPECT(equalsBinary<gtsam::Point2>(Point2(1.0, 2.0)));
|
||||||
EXPECT(equalsBinary<gtsam::Pose2>(Pose2(1.0, 2.0, 0.3)));
|
EXPECT(equalsBinary<gtsam::Pose2>(Pose2(1.0, 2.0, 0.3)));
|
||||||
EXPECT(equalsBinary<gtsam::Rot2>(Rot2::fromDegrees(30.0)));
|
EXPECT(equalsBinary<gtsam::Rot2>(Rot2::fromDegrees(30.0)));
|
||||||
|
|
|
@ -597,6 +597,7 @@ class Rot3 {
|
||||||
Rot3(double R11, double R12, double R13,
|
Rot3(double R11, double R12, double R13,
|
||||||
double R21, double R22, double R23,
|
double R21, double R22, double R23,
|
||||||
double R31, double R32, double R33);
|
double R31, double R32, double R33);
|
||||||
|
Rot3(double w, double x, double y, double z);
|
||||||
|
|
||||||
static gtsam::Rot3 Rx(double t);
|
static gtsam::Rot3 Rx(double t);
|
||||||
static gtsam::Rot3 Ry(double t);
|
static gtsam::Rot3 Ry(double t);
|
||||||
|
@ -980,8 +981,8 @@ class Cal3Bundler {
|
||||||
double fy() const;
|
double fy() const;
|
||||||
double k1() const;
|
double k1() const;
|
||||||
double k2() const;
|
double k2() const;
|
||||||
double u0() const;
|
double px() const;
|
||||||
double v0() const;
|
double py() const;
|
||||||
Vector vector() const;
|
Vector vector() const;
|
||||||
Vector k() const;
|
Vector k() const;
|
||||||
Matrix K() const;
|
Matrix K() const;
|
||||||
|
@ -2100,7 +2101,7 @@ class NonlinearFactorGraph {
|
||||||
gtsam::KeySet keys() const;
|
gtsam::KeySet keys() const;
|
||||||
gtsam::KeyVector keyVector() const;
|
gtsam::KeyVector keyVector() const;
|
||||||
|
|
||||||
template<T = {Vector, gtsam::Point2, gtsam::StereoPoint2, gtsam::Point3, gtsam::Rot2, gtsam::SO3, gtsam::SO4, gtsam::Rot3, gtsam::Pose2, gtsam::Pose3, gtsam::Cal3_S2,gtsam::CalibratedCamera, gtsam::SimpleCamera, gtsam::PinholeCameraCal3_S2, gtsam::imuBias::ConstantBias}>
|
template<T = {Vector, gtsam::Point2, gtsam::StereoPoint2, gtsam::Point3, gtsam::Rot2, gtsam::SO3, gtsam::SO4, gtsam::Rot3, gtsam::Pose2, gtsam::Pose3, gtsam::Cal3_S2,gtsam::CalibratedCamera, gtsam::SimpleCamera, gtsam::PinholeCameraCal3_S2, gtsam::PinholeCamera<gtsam::Cal3Bundler>, gtsam::imuBias::ConstantBias}>
|
||||||
void addPrior(size_t key, const T& prior, const gtsam::noiseModel::Base* noiseModel);
|
void addPrior(size_t key, const T& prior, const gtsam::noiseModel::Base* noiseModel);
|
||||||
|
|
||||||
// NonlinearFactorGraph
|
// NonlinearFactorGraph
|
||||||
|
@ -2189,12 +2190,13 @@ class Values {
|
||||||
void insert(size_t j, const gtsam::SOn& P);
|
void insert(size_t j, const gtsam::SOn& P);
|
||||||
void insert(size_t j, const gtsam::Rot3& rot3);
|
void insert(size_t j, const gtsam::Rot3& rot3);
|
||||||
void insert(size_t j, const gtsam::Pose3& pose3);
|
void insert(size_t j, const gtsam::Pose3& pose3);
|
||||||
|
void insert(size_t j, const gtsam::Unit3& unit3);
|
||||||
void insert(size_t j, const gtsam::Cal3_S2& cal3_s2);
|
void insert(size_t j, const gtsam::Cal3_S2& cal3_s2);
|
||||||
void insert(size_t j, const gtsam::Cal3DS2& cal3ds2);
|
void insert(size_t j, const gtsam::Cal3DS2& cal3ds2);
|
||||||
void insert(size_t j, const gtsam::Cal3Bundler& cal3bundler);
|
void insert(size_t j, const gtsam::Cal3Bundler& cal3bundler);
|
||||||
void insert(size_t j, const gtsam::EssentialMatrix& essential_matrix);
|
void insert(size_t j, const gtsam::EssentialMatrix& essential_matrix);
|
||||||
void insert(size_t j, const gtsam::PinholeCameraCal3_S2& simple_camera);
|
void insert(size_t j, const gtsam::PinholeCameraCal3_S2& simple_camera);
|
||||||
// void insert(size_t j, const gtsam::PinholeCameraCal3Bundler& camera);
|
void insert(size_t j, const gtsam::PinholeCamera<gtsam::Cal3Bundler>& camera);
|
||||||
void insert(size_t j, const gtsam::imuBias::ConstantBias& constant_bias);
|
void insert(size_t j, const gtsam::imuBias::ConstantBias& constant_bias);
|
||||||
void insert(size_t j, const gtsam::NavState& nav_state);
|
void insert(size_t j, const gtsam::NavState& nav_state);
|
||||||
|
|
||||||
|
@ -2207,18 +2209,19 @@ class Values {
|
||||||
void update(size_t j, const gtsam::SOn& P);
|
void update(size_t j, const gtsam::SOn& P);
|
||||||
void update(size_t j, const gtsam::Rot3& rot3);
|
void update(size_t j, const gtsam::Rot3& rot3);
|
||||||
void update(size_t j, const gtsam::Pose3& pose3);
|
void update(size_t j, const gtsam::Pose3& pose3);
|
||||||
|
void update(size_t j, const gtsam::Unit3& unit3);
|
||||||
void update(size_t j, const gtsam::Cal3_S2& cal3_s2);
|
void update(size_t j, const gtsam::Cal3_S2& cal3_s2);
|
||||||
void update(size_t j, const gtsam::Cal3DS2& cal3ds2);
|
void update(size_t j, const gtsam::Cal3DS2& cal3ds2);
|
||||||
void update(size_t j, const gtsam::Cal3Bundler& cal3bundler);
|
void update(size_t j, const gtsam::Cal3Bundler& cal3bundler);
|
||||||
void update(size_t j, const gtsam::EssentialMatrix& essential_matrix);
|
void update(size_t j, const gtsam::EssentialMatrix& essential_matrix);
|
||||||
void update(size_t j, const gtsam::PinholeCameraCal3_S2& simple_camera);
|
void update(size_t j, const gtsam::PinholeCameraCal3_S2& simple_camera);
|
||||||
// void update(size_t j, const gtsam::PinholeCameraCal3Bundler& camera);
|
void update(size_t j, const gtsam::PinholeCamera<gtsam::Cal3Bundler>& camera);
|
||||||
void update(size_t j, const gtsam::imuBias::ConstantBias& constant_bias);
|
void update(size_t j, const gtsam::imuBias::ConstantBias& constant_bias);
|
||||||
void update(size_t j, const gtsam::NavState& nav_state);
|
void update(size_t j, const gtsam::NavState& nav_state);
|
||||||
void update(size_t j, Vector vector);
|
void update(size_t j, Vector vector);
|
||||||
void update(size_t j, Matrix matrix);
|
void update(size_t j, Matrix matrix);
|
||||||
|
|
||||||
template<T = {gtsam::Point2, gtsam::Point3, gtsam::Rot2, gtsam::Pose2, gtsam::SO3, gtsam::SO4, gtsam::SOn, gtsam::Rot3, gtsam::Pose3, gtsam::Cal3_S2, gtsam::Cal3DS2, gtsam::Cal3Bundler, gtsam::EssentialMatrix, gtsam::PinholeCameraCal3_S2, gtsam::imuBias::ConstantBias, gtsam::NavState, Vector, Matrix}>
|
template<T = {gtsam::Point2, gtsam::Point3, gtsam::Rot2, gtsam::Pose2, gtsam::SO3, gtsam::SO4, gtsam::SOn, gtsam::Rot3, gtsam::Pose3, gtsam::Unit3, gtsam::Cal3_S2, gtsam::Cal3DS2, gtsam::Cal3Bundler, gtsam::EssentialMatrix, gtsam::PinholeCameraCal3_S2, gtsam::PinholeCamera<gtsam::Cal3Bundler>, gtsam::imuBias::ConstantBias, gtsam::NavState, Vector, Matrix}>
|
||||||
T at(size_t j);
|
T at(size_t j);
|
||||||
|
|
||||||
/// version for double
|
/// version for double
|
||||||
|
@ -2522,7 +2525,8 @@ class ISAM2 {
|
||||||
template <VALUE = {gtsam::Point2, gtsam::Rot2, gtsam::Pose2, gtsam::Point3,
|
template <VALUE = {gtsam::Point2, gtsam::Rot2, gtsam::Pose2, gtsam::Point3,
|
||||||
gtsam::Rot3, gtsam::Pose3, gtsam::Cal3_S2, gtsam::Cal3DS2,
|
gtsam::Rot3, gtsam::Pose3, gtsam::Cal3_S2, gtsam::Cal3DS2,
|
||||||
gtsam::Cal3Bundler, gtsam::EssentialMatrix,
|
gtsam::Cal3Bundler, gtsam::EssentialMatrix,
|
||||||
gtsam::SimpleCamera, gtsam::PinholeCameraCal3_S2, Vector, Matrix}>
|
gtsam::SimpleCamera, gtsam::PinholeCameraCal3_S2, gtsam::PinholeCamera<gtsam::Cal3Bundler>,
|
||||||
|
Vector, Matrix}>
|
||||||
VALUE calculateEstimate(size_t key) const;
|
VALUE calculateEstimate(size_t key) const;
|
||||||
gtsam::Values calculateBestEstimate() const;
|
gtsam::Values calculateBestEstimate() const;
|
||||||
Matrix marginalCovariance(size_t key) const;
|
Matrix marginalCovariance(size_t key) const;
|
||||||
|
@ -2560,7 +2564,7 @@ class NonlinearISAM {
|
||||||
#include <gtsam/geometry/StereoPoint2.h>
|
#include <gtsam/geometry/StereoPoint2.h>
|
||||||
|
|
||||||
#include <gtsam/nonlinear/PriorFactor.h>
|
#include <gtsam/nonlinear/PriorFactor.h>
|
||||||
template<T = {Vector, gtsam::Point2, gtsam::StereoPoint2, gtsam::Point3, gtsam::Rot2, gtsam::SO3, gtsam::SO4, gtsam::SOn, gtsam::Rot3, gtsam::Pose2, gtsam::Pose3, gtsam::Cal3_S2,gtsam::CalibratedCamera, gtsam::SimpleCamera, gtsam::PinholeCameraCal3_S2, gtsam::imuBias::ConstantBias}>
|
template<T = {Vector, gtsam::Point2, gtsam::StereoPoint2, gtsam::Point3, gtsam::Rot2, gtsam::SO3, gtsam::SO4, gtsam::SOn, gtsam::Rot3, gtsam::Pose2, gtsam::Pose3, gtsam::Unit3, gtsam::Cal3_S2,gtsam::CalibratedCamera, gtsam::SimpleCamera, gtsam::PinholeCameraCal3_S2, gtsam::imuBias::ConstantBias, gtsam::PinholeCamera<gtsam::Cal3Bundler>}>
|
||||||
virtual class PriorFactor : gtsam::NoiseModelFactor {
|
virtual class PriorFactor : gtsam::NoiseModelFactor {
|
||||||
PriorFactor(size_t key, const T& prior, const gtsam::noiseModel::Base* noiseModel);
|
PriorFactor(size_t key, const T& prior, const gtsam::noiseModel::Base* noiseModel);
|
||||||
T prior() const;
|
T prior() const;
|
||||||
|
@ -2705,6 +2709,7 @@ virtual class GeneralSFMFactor : gtsam::NoiseModelFactor {
|
||||||
typedef gtsam::GeneralSFMFactor<gtsam::PinholeCameraCal3_S2, gtsam::Point3> GeneralSFMFactorCal3_S2;
|
typedef gtsam::GeneralSFMFactor<gtsam::PinholeCameraCal3_S2, gtsam::Point3> GeneralSFMFactorCal3_S2;
|
||||||
//TODO (Issue 237) due to lack of jacobians of Cal3DS2_Base::calibrate, GeneralSFMFactor does not apply to Cal3DS2
|
//TODO (Issue 237) due to lack of jacobians of Cal3DS2_Base::calibrate, GeneralSFMFactor does not apply to Cal3DS2
|
||||||
//typedef gtsam::GeneralSFMFactor<gtsam::PinholeCameraCal3DS2, gtsam::Point3> GeneralSFMFactorCal3DS2;
|
//typedef gtsam::GeneralSFMFactor<gtsam::PinholeCameraCal3DS2, gtsam::Point3> GeneralSFMFactorCal3DS2;
|
||||||
|
typedef gtsam::GeneralSFMFactor<gtsam::PinholeCamera<gtsam::Cal3Bundler>, gtsam::Point3> GeneralSFMFactorCal3Bundler;
|
||||||
|
|
||||||
template<CALIBRATION = {gtsam::Cal3_S2}>
|
template<CALIBRATION = {gtsam::Cal3_S2}>
|
||||||
virtual class GeneralSFMFactor2 : gtsam::NoiseModelFactor {
|
virtual class GeneralSFMFactor2 : gtsam::NoiseModelFactor {
|
||||||
|
@ -2791,21 +2796,36 @@ virtual class EssentialMatrixFactor : gtsam::NoiseModelFactor {
|
||||||
};
|
};
|
||||||
|
|
||||||
#include <gtsam/slam/dataset.h>
|
#include <gtsam/slam/dataset.h>
|
||||||
|
|
||||||
class SfmTrack {
|
class SfmTrack {
|
||||||
Point3 point3() const;
|
SfmTrack();
|
||||||
|
SfmTrack(const gtsam::Point3& pt);
|
||||||
|
const Point3& point3() const;
|
||||||
|
|
||||||
|
double r;
|
||||||
|
double g;
|
||||||
|
double b;
|
||||||
|
// TODO Need to close wrap#10 to allow this to work.
|
||||||
|
// std::vector<pair<size_t, gtsam::Point2>> measurements;
|
||||||
|
|
||||||
size_t number_measurements() const;
|
size_t number_measurements() const;
|
||||||
pair<size_t, gtsam::Point2> measurement(size_t idx) const;
|
pair<size_t, gtsam::Point2> measurement(size_t idx) const;
|
||||||
pair<size_t, size_t> siftIndex(size_t idx) const;
|
pair<size_t, size_t> siftIndex(size_t idx) const;
|
||||||
|
void add_measurement(size_t idx, const gtsam::Point2& m);
|
||||||
};
|
};
|
||||||
|
|
||||||
class SfmData {
|
class SfmData {
|
||||||
|
SfmData();
|
||||||
size_t number_cameras() const;
|
size_t number_cameras() const;
|
||||||
size_t number_tracks() const;
|
size_t number_tracks() const;
|
||||||
gtsam::PinholeCamera<gtsam::Cal3Bundler> camera(size_t idx) const;
|
gtsam::PinholeCamera<gtsam::Cal3Bundler> camera(size_t idx) const;
|
||||||
gtsam::SfmTrack track(size_t idx) const;
|
gtsam::SfmTrack track(size_t idx) const;
|
||||||
|
void add_track(const gtsam::SfmTrack& t) ;
|
||||||
|
void add_camera(const gtsam::SfmCamera& cam);
|
||||||
};
|
};
|
||||||
|
|
||||||
gtsam::SfmData readBal(string filename);
|
gtsam::SfmData readBal(string filename);
|
||||||
|
bool writeBAL(string filename, gtsam::SfmData& data);
|
||||||
gtsam::Values initialCamerasEstimate(const gtsam::SfmData& db);
|
gtsam::Values initialCamerasEstimate(const gtsam::SfmData& db);
|
||||||
gtsam::Values initialCamerasAndPointsEstimate(const gtsam::SfmData& db);
|
gtsam::Values initialCamerasAndPointsEstimate(const gtsam::SfmData& db);
|
||||||
|
|
||||||
|
|
|
@ -164,8 +164,16 @@ inline Key Y(std::uint64_t j) { return Symbol('y', j); }
|
||||||
inline Key Z(std::uint64_t j) { return Symbol('z', j); }
|
inline Key Z(std::uint64_t j) { return Symbol('z', j); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Generates symbol shorthands with alternative names different than the
|
||||||
|
* one-letter predefined ones. */
|
||||||
|
class SymbolGenerator {
|
||||||
|
const char c_;
|
||||||
|
public:
|
||||||
|
SymbolGenerator(const char c) : c_(c) {}
|
||||||
|
Symbol operator()(const std::uint64_t j) const { return Symbol(c_, j); }
|
||||||
|
};
|
||||||
|
|
||||||
/// traits
|
/// traits
|
||||||
template<> struct traits<Symbol> : public Testable<Symbol> {};
|
template<> struct traits<Symbol> : public Testable<Symbol> {};
|
||||||
|
|
||||||
} // \ namespace gtsam
|
} // \ namespace gtsam
|
||||||
|
|
||||||
|
|
|
@ -40,6 +40,25 @@ TEST(Key, KeySymbolConversion) {
|
||||||
EXPECT(assert_equal(original, actual))
|
EXPECT(assert_equal(original, actual))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
TEST(Key, SymbolGenerator) {
|
||||||
|
const auto x1 = gtsam::symbol_shorthand::X(1);
|
||||||
|
const auto v1 = gtsam::symbol_shorthand::V(1);
|
||||||
|
const auto a1 = gtsam::symbol_shorthand::A(1);
|
||||||
|
|
||||||
|
const auto Z = gtsam::SymbolGenerator('x');
|
||||||
|
const auto DZ = gtsam::SymbolGenerator('v');
|
||||||
|
const auto DDZ = gtsam::SymbolGenerator('a');
|
||||||
|
|
||||||
|
const auto z1 = Z(1);
|
||||||
|
const auto dz1 = DZ(1);
|
||||||
|
const auto ddz1 = DDZ(1);
|
||||||
|
|
||||||
|
EXPECT(assert_equal(x1, z1));
|
||||||
|
EXPECT(assert_equal(v1, dz1));
|
||||||
|
EXPECT(assert_equal(a1, ddz1));
|
||||||
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
template<int KeySize>
|
template<int KeySize>
|
||||||
Key KeyTestValue();
|
Key KeyTestValue();
|
||||||
|
@ -106,4 +125,3 @@ int main() {
|
||||||
return TestRegistry::runAllTests(tr);
|
return TestRegistry::runAllTests(tr);
|
||||||
}
|
}
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
|
|
||||||
|
|
|
@ -200,6 +200,10 @@ boost::tuple<V, int> nonlinearConjugateGradient(const S &system,
|
||||||
currentValues = system.advance(prevValues, alpha, direction);
|
currentValues = system.advance(prevValues, alpha, direction);
|
||||||
currentError = system.error(currentValues);
|
currentError = system.error(currentValues);
|
||||||
|
|
||||||
|
// User hook:
|
||||||
|
if (params.iterationHook)
|
||||||
|
params.iterationHook(iteration, prevError, currentError);
|
||||||
|
|
||||||
// Maybe show output
|
// Maybe show output
|
||||||
if (params.verbosity >= NonlinearOptimizerParams::ERROR)
|
if (params.verbosity >= NonlinearOptimizerParams::ERROR)
|
||||||
std::cout << "iteration: " << iteration << ", currentError: " << currentError << std::endl;
|
std::cout << "iteration: " << iteration << ", currentError: " << currentError << std::endl;
|
||||||
|
|
|
@ -88,20 +88,28 @@ void NonlinearOptimizer::defaultOptimize() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Iterative loop
|
// Iterative loop
|
||||||
|
double newError = currentError; // used to avoid repeated calls to error()
|
||||||
do {
|
do {
|
||||||
// Do next iteration
|
// Do next iteration
|
||||||
currentError = error(); // TODO(frank): don't do this twice at first !? Computed above!
|
currentError = newError;
|
||||||
iterate();
|
iterate();
|
||||||
tictoc_finishedIteration();
|
tictoc_finishedIteration();
|
||||||
|
|
||||||
|
// Update newError for either printouts or conditional-end checks:
|
||||||
|
newError = error();
|
||||||
|
|
||||||
|
// User hook:
|
||||||
|
if (params.iterationHook)
|
||||||
|
params.iterationHook(iterations(), currentError, newError);
|
||||||
|
|
||||||
// Maybe show output
|
// Maybe show output
|
||||||
if (params.verbosity >= NonlinearOptimizerParams::VALUES)
|
if (params.verbosity >= NonlinearOptimizerParams::VALUES)
|
||||||
values().print("newValues");
|
values().print("newValues");
|
||||||
if (params.verbosity >= NonlinearOptimizerParams::ERROR)
|
if (params.verbosity >= NonlinearOptimizerParams::ERROR)
|
||||||
cout << "newError: " << error() << endl;
|
cout << "newError: " << newError << endl;
|
||||||
} while (iterations() < params.maxIterations &&
|
} while (iterations() < params.maxIterations &&
|
||||||
!checkConvergence(params.relativeErrorTol, params.absoluteErrorTol, params.errorTol,
|
!checkConvergence(params.relativeErrorTol, params.absoluteErrorTol, params.errorTol,
|
||||||
currentError, error(), params.verbosity) && std::isfinite(currentError));
|
currentError, newError, params.verbosity) && std::isfinite(currentError));
|
||||||
|
|
||||||
// Printing if verbose
|
// Printing if verbose
|
||||||
if (params.verbosity >= NonlinearOptimizerParams::TERMINATION) {
|
if (params.verbosity >= NonlinearOptimizerParams::TERMINATION) {
|
||||||
|
|
|
@ -81,7 +81,7 @@ protected:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/** A shared pointer to this class */
|
/** A shared pointer to this class */
|
||||||
typedef boost::shared_ptr<const NonlinearOptimizer> shared_ptr;
|
using shared_ptr = boost::shared_ptr<const NonlinearOptimizer>;
|
||||||
|
|
||||||
/// @name Standard interface
|
/// @name Standard interface
|
||||||
/// @{
|
/// @{
|
||||||
|
|
|
@ -38,21 +38,12 @@ public:
|
||||||
SILENT, TERMINATION, ERROR, VALUES, DELTA, LINEAR
|
SILENT, TERMINATION, ERROR, VALUES, DELTA, LINEAR
|
||||||
};
|
};
|
||||||
|
|
||||||
size_t maxIterations; ///< The maximum iterations to stop iterating (default 100)
|
size_t maxIterations = 100; ///< The maximum iterations to stop iterating (default 100)
|
||||||
double relativeErrorTol; ///< The maximum relative error decrease to stop iterating (default 1e-5)
|
double relativeErrorTol = 1e-5; ///< The maximum relative error decrease to stop iterating (default 1e-5)
|
||||||
double absoluteErrorTol; ///< The maximum absolute error decrease to stop iterating (default 1e-5)
|
double absoluteErrorTol = 1e-5; ///< The maximum absolute error decrease to stop iterating (default 1e-5)
|
||||||
double errorTol; ///< The maximum total error to stop iterating (default 0.0)
|
double errorTol = 0.0; ///< The maximum total error to stop iterating (default 0.0)
|
||||||
Verbosity verbosity; ///< The printing verbosity during optimization (default SILENT)
|
Verbosity verbosity = SILENT; ///< The printing verbosity during optimization (default SILENT)
|
||||||
Ordering::OrderingType orderingType; ///< The method of ordering use during variable elimination (default COLAMD)
|
Ordering::OrderingType orderingType = Ordering::COLAMD; ///< The method of ordering use during variable elimination (default COLAMD)
|
||||||
|
|
||||||
NonlinearOptimizerParams() :
|
|
||||||
maxIterations(100), relativeErrorTol(1e-5), absoluteErrorTol(1e-5), errorTol(
|
|
||||||
0.0), verbosity(SILENT), orderingType(Ordering::COLAMD),
|
|
||||||
linearSolverType(MULTIFRONTAL_CHOLESKY) {}
|
|
||||||
|
|
||||||
virtual ~NonlinearOptimizerParams() {
|
|
||||||
}
|
|
||||||
virtual void print(const std::string& str = "") const;
|
|
||||||
|
|
||||||
size_t getMaxIterations() const { return maxIterations; }
|
size_t getMaxIterations() const { return maxIterations; }
|
||||||
double getRelativeErrorTol() const { return relativeErrorTol; }
|
double getRelativeErrorTol() const { return relativeErrorTol; }
|
||||||
|
@ -71,6 +62,37 @@ public:
|
||||||
static Verbosity verbosityTranslator(const std::string &s) ;
|
static Verbosity verbosityTranslator(const std::string &s) ;
|
||||||
static std::string verbosityTranslator(Verbosity value) ;
|
static std::string verbosityTranslator(Verbosity value) ;
|
||||||
|
|
||||||
|
/** Type for an optional user-provided hook to be called after each
|
||||||
|
* internal optimizer iteration. See iterationHook below. */
|
||||||
|
using IterationHook = std::function<
|
||||||
|
void(size_t /*iteration*/, double/*errorBefore*/, double/*errorAfter*/)>;
|
||||||
|
|
||||||
|
/** Optional user-provided iteration hook to be called after each
|
||||||
|
* optimization iteration (Default: none).
|
||||||
|
* Note that `IterationHook` is defined as a std::function<> with this
|
||||||
|
* signature:
|
||||||
|
* \code
|
||||||
|
* void(size_t iteration, double errorBefore, double errorAfter)
|
||||||
|
* \endcode
|
||||||
|
* which allows binding by means of a reference to a regular function:
|
||||||
|
* \code
|
||||||
|
* void foo(size_t iteration, double errorBefore, double errorAfter);
|
||||||
|
* // ...
|
||||||
|
* lmOpts.iterationHook = &foo;
|
||||||
|
* \endcode
|
||||||
|
* or to a C++11 lambda (preferred if you need to capture additional
|
||||||
|
* context variables, such that the optimizer object itself, the factor graph,
|
||||||
|
* etc.):
|
||||||
|
* \code
|
||||||
|
* lmOpts.iterationHook = [&](size_t iter, double oldError, double newError)
|
||||||
|
* {
|
||||||
|
* // ...
|
||||||
|
* };
|
||||||
|
* \endcode
|
||||||
|
* or to the result of a properly-formed `std::bind` call.
|
||||||
|
*/
|
||||||
|
IterationHook iterationHook;
|
||||||
|
|
||||||
/** See NonlinearOptimizerParams::linearSolverType */
|
/** See NonlinearOptimizerParams::linearSolverType */
|
||||||
enum LinearSolverType {
|
enum LinearSolverType {
|
||||||
MULTIFRONTAL_CHOLESKY,
|
MULTIFRONTAL_CHOLESKY,
|
||||||
|
@ -81,10 +103,16 @@ public:
|
||||||
CHOLMOD, /* Experimental Flag */
|
CHOLMOD, /* Experimental Flag */
|
||||||
};
|
};
|
||||||
|
|
||||||
LinearSolverType linearSolverType; ///< The type of linear solver to use in the nonlinear optimizer
|
LinearSolverType linearSolverType = MULTIFRONTAL_CHOLESKY; ///< The type of linear solver to use in the nonlinear optimizer
|
||||||
boost::optional<Ordering> ordering; ///< The optional variable elimination ordering, or empty to use COLAMD (default: empty)
|
boost::optional<Ordering> ordering; ///< The optional variable elimination ordering, or empty to use COLAMD (default: empty)
|
||||||
IterativeOptimizationParameters::shared_ptr iterativeParams; ///< The container for iterativeOptimization parameters. used in CG Solvers.
|
IterativeOptimizationParameters::shared_ptr iterativeParams; ///< The container for iterativeOptimization parameters. used in CG Solvers.
|
||||||
|
|
||||||
|
NonlinearOptimizerParams() = default;
|
||||||
|
virtual ~NonlinearOptimizerParams() {
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void print(const std::string& str = "") const;
|
||||||
|
|
||||||
inline bool isMultifrontal() const {
|
inline bool isMultifrontal() const {
|
||||||
return (linearSolverType == MULTIFRONTAL_CHOLESKY)
|
return (linearSolverType == MULTIFRONTAL_CHOLESKY)
|
||||||
|| (linearSolverType == MULTIFRONTAL_QR);
|
|| (linearSolverType == MULTIFRONTAL_QR);
|
||||||
|
|
|
@ -41,7 +41,7 @@ struct Cal3Bundler0 : public Cal3Bundler {
|
||||||
double v0 = 0)
|
double v0 = 0)
|
||||||
: Cal3Bundler(f, k1, k2, u0, v0) {}
|
: Cal3Bundler(f, k1, k2, u0, v0) {}
|
||||||
Cal3Bundler0 retract(const Vector& d) const {
|
Cal3Bundler0 retract(const Vector& d) const {
|
||||||
return Cal3Bundler0(fx() + d(0), k1() + d(1), k2() + d(2), u0(), v0());
|
return Cal3Bundler0(fx() + d(0), k1() + d(1), k2() + d(2), px(), py());
|
||||||
}
|
}
|
||||||
Vector3 localCoordinates(const Cal3Bundler0& T2) const {
|
Vector3 localCoordinates(const Cal3Bundler0& T2) const {
|
||||||
return T2.vector() - vector();
|
return T2.vector() - vector();
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
#include <CppUnitLite/TestHarness.h>
|
#include <CppUnitLite/TestHarness.h>
|
||||||
#include <gtsam/base/Testable.h>
|
#include <gtsam/base/Testable.h>
|
||||||
|
#include <gtsam/base/TestableAssertions.h>
|
||||||
#include <gtsam/inference/Symbol.h>
|
#include <gtsam/inference/Symbol.h>
|
||||||
#include <gtsam/nonlinear/FunctorizedFactor.h>
|
#include <gtsam/nonlinear/FunctorizedFactor.h>
|
||||||
#include <gtsam/nonlinear/factorTesting.h>
|
#include <gtsam/nonlinear/factorTesting.h>
|
||||||
|
@ -115,16 +116,6 @@ TEST(FunctorizedFactor, Print) {
|
||||||
auto factor =
|
auto factor =
|
||||||
MakeFunctorizedFactor<Matrix>(key, X, model, MultiplyFunctor(multiplier));
|
MakeFunctorizedFactor<Matrix>(key, X, model, MultiplyFunctor(multiplier));
|
||||||
|
|
||||||
// redirect output to buffer so we can compare
|
|
||||||
stringstream buffer;
|
|
||||||
streambuf *old = cout.rdbuf(buffer.rdbuf());
|
|
||||||
|
|
||||||
factor.print();
|
|
||||||
|
|
||||||
// get output string and reset stdout
|
|
||||||
string actual = buffer.str();
|
|
||||||
cout.rdbuf(old);
|
|
||||||
|
|
||||||
string expected =
|
string expected =
|
||||||
" keys = { X0 }\n"
|
" keys = { X0 }\n"
|
||||||
" noise model: unit (9) \n"
|
" noise model: unit (9) \n"
|
||||||
|
@ -135,7 +126,7 @@ TEST(FunctorizedFactor, Print) {
|
||||||
"]\n"
|
"]\n"
|
||||||
" noise model sigmas: 1 1 1 1 1 1 1 1 1\n";
|
" noise model sigmas: 1 1 1 1 1 1 1 1 1\n";
|
||||||
|
|
||||||
CHECK_EQUAL(expected, actual);
|
EXPECT(assert_print_equal(expected, factor));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
|
|
|
@ -595,15 +595,7 @@ TEST(Values, Demangle) {
|
||||||
values.insert(key1, v);
|
values.insert(key1, v);
|
||||||
string expected = "Values with 1 values:\nValue v1: (Eigen::Matrix<double, 1, 3, 1, 1, 3>)\n[\n 5, 6, 7\n]\n\n";
|
string expected = "Values with 1 values:\nValue v1: (Eigen::Matrix<double, 1, 3, 1, 1, 3>)\n[\n 5, 6, 7\n]\n\n";
|
||||||
|
|
||||||
stringstream buffer;
|
EXPECT(assert_print_equal(expected, values));
|
||||||
streambuf * old = cout.rdbuf(buffer.rdbuf());
|
|
||||||
|
|
||||||
values.print();
|
|
||||||
|
|
||||||
string actual = buffer.str();
|
|
||||||
cout.rdbuf(old);
|
|
||||||
|
|
||||||
EXPECT(assert_equal(expected, actual));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
|
|
|
@ -121,8 +121,8 @@ MFAS::MFAS(const TranslationEdges& relativeTranslations,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<Key> MFAS::computeOrdering() const {
|
KeyVector MFAS::computeOrdering() const {
|
||||||
vector<Key> ordering; // Nodes in MFAS order (result).
|
KeyVector ordering; // Nodes in MFAS order (result).
|
||||||
|
|
||||||
// A graph is an unordered map from keys to nodes. Each node contains a list
|
// A graph is an unordered map from keys to nodes. Each node contains a list
|
||||||
// of its adjacent nodes. Create the graph from the edgeWeights.
|
// of its adjacent nodes. Create the graph from the edgeWeights.
|
||||||
|
@ -140,7 +140,7 @@ vector<Key> MFAS::computeOrdering() const {
|
||||||
|
|
||||||
map<MFAS::KeyPair, double> MFAS::computeOutlierWeights() const {
|
map<MFAS::KeyPair, double> MFAS::computeOutlierWeights() const {
|
||||||
// Find the ordering.
|
// Find the ordering.
|
||||||
vector<Key> ordering = computeOrdering();
|
KeyVector ordering = computeOrdering();
|
||||||
|
|
||||||
// Create a map from the node key to its position in the ordering. This makes
|
// Create a map from the node key to its position in the ordering. This makes
|
||||||
// it easier to lookup positions of different nodes.
|
// it easier to lookup positions of different nodes.
|
||||||
|
|
|
@ -84,7 +84,7 @@ class MFAS {
|
||||||
* @brief Computes the 1D MFAS ordering of nodes in the graph
|
* @brief Computes the 1D MFAS ordering of nodes in the graph
|
||||||
* @return orderedNodes: vector of nodes in the obtained order
|
* @return orderedNodes: vector of nodes in the obtained order
|
||||||
*/
|
*/
|
||||||
std::vector<Key> computeOrdering() const;
|
KeyVector computeOrdering() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Computes the outlier weights of the graph. We define the outlier
|
* @brief Computes the outlier weights of the graph. We define the outlier
|
||||||
|
|
|
@ -25,7 +25,7 @@ using namespace gtsam;
|
||||||
vector<MFAS::KeyPair> edges = {make_pair(3, 2), make_pair(0, 1), make_pair(3, 1),
|
vector<MFAS::KeyPair> edges = {make_pair(3, 2), make_pair(0, 1), make_pair(3, 1),
|
||||||
make_pair(1, 2), make_pair(0, 2), make_pair(3, 0)};
|
make_pair(1, 2), make_pair(0, 2), make_pair(3, 0)};
|
||||||
// nodes in the graph
|
// nodes in the graph
|
||||||
vector<Key> nodes = {Key(0), Key(1), Key(2), Key(3)};
|
KeyVector nodes = {Key(0), Key(1), Key(2), Key(3)};
|
||||||
// weights from projecting in direction-1 (bad direction, outlier accepted)
|
// weights from projecting in direction-1 (bad direction, outlier accepted)
|
||||||
vector<double> weights1 = {2, 1.5, 0.5, 0.25, 1, 0.75};
|
vector<double> weights1 = {2, 1.5, 0.5, 0.25, 1, 0.75};
|
||||||
// weights from projecting in direction-2 (good direction, outlier rejected)
|
// weights from projecting in direction-2 (good direction, outlier rejected)
|
||||||
|
@ -47,10 +47,10 @@ map<MFAS::KeyPair, double> getEdgeWeights(const vector<MFAS::KeyPair> &edges,
|
||||||
TEST(MFAS, OrderingWeights2) {
|
TEST(MFAS, OrderingWeights2) {
|
||||||
MFAS mfas_obj(getEdgeWeights(edges, weights2));
|
MFAS mfas_obj(getEdgeWeights(edges, weights2));
|
||||||
|
|
||||||
vector<Key> ordered_nodes = mfas_obj.computeOrdering();
|
KeyVector ordered_nodes = mfas_obj.computeOrdering();
|
||||||
|
|
||||||
// ground truth (expected) ordering in this example
|
// ground truth (expected) ordering in this example
|
||||||
vector<Key> gt_ordered_nodes = {0, 1, 3, 2};
|
KeyVector gt_ordered_nodes = {0, 1, 3, 2};
|
||||||
|
|
||||||
// check if the expected ordering is obtained
|
// check if the expected ordering is obtained
|
||||||
for (size_t i = 0; i < ordered_nodes.size(); i++) {
|
for (size_t i = 0; i < ordered_nodes.size(); i++) {
|
||||||
|
@ -77,10 +77,10 @@ TEST(MFAS, OrderingWeights2) {
|
||||||
TEST(MFAS, OrderingWeights1) {
|
TEST(MFAS, OrderingWeights1) {
|
||||||
MFAS mfas_obj(getEdgeWeights(edges, weights1));
|
MFAS mfas_obj(getEdgeWeights(edges, weights1));
|
||||||
|
|
||||||
vector<Key> ordered_nodes = mfas_obj.computeOrdering();
|
KeyVector ordered_nodes = mfas_obj.computeOrdering();
|
||||||
|
|
||||||
// "ground truth" expected ordering in this example
|
// "ground truth" expected ordering in this example
|
||||||
vector<Key> gt_ordered_nodes = {3, 0, 1, 2};
|
KeyVector gt_ordered_nodes = {3, 0, 1, 2};
|
||||||
|
|
||||||
// check if the expected ordering is obtained
|
// check if the expected ordering is obtained
|
||||||
for (size_t i = 0; i < ordered_nodes.size(); i++) {
|
for (size_t i = 0; i < ordered_nodes.size(); i++) {
|
||||||
|
|
|
@ -1164,8 +1164,8 @@ bool writeBAL(const string &filename, SfmData &data) {
|
||||||
for (size_t k = 0; k < track.number_measurements();
|
for (size_t k = 0; k < track.number_measurements();
|
||||||
k++) { // for each observation of the 3D point j
|
k++) { // for each observation of the 3D point j
|
||||||
size_t i = track.measurements[k].first; // camera id
|
size_t i = track.measurements[k].first; // camera id
|
||||||
double u0 = data.cameras[i].calibration().u0();
|
double u0 = data.cameras[i].calibration().px();
|
||||||
double v0 = data.cameras[i].calibration().v0();
|
double v0 = data.cameras[i].calibration().py();
|
||||||
|
|
||||||
if (u0 != 0 || v0 != 0) {
|
if (u0 != 0 || v0 != 0) {
|
||||||
cout << "writeBAL has not been tested for calibration with nonzero "
|
cout << "writeBAL has not been tested for calibration with nonzero "
|
||||||
|
|
|
@ -211,16 +211,18 @@ GTSAM_EXPORT GraphAndValues load3D(const std::string& filename);
|
||||||
/// A measurement with its camera index
|
/// A measurement with its camera index
|
||||||
typedef std::pair<size_t, Point2> SfmMeasurement;
|
typedef std::pair<size_t, Point2> SfmMeasurement;
|
||||||
|
|
||||||
/// SfmTrack
|
/// Sift index for SfmTrack
|
||||||
typedef std::pair<size_t, size_t> SiftIndex;
|
typedef std::pair<size_t, size_t> SiftIndex;
|
||||||
|
|
||||||
/// Define the structure for the 3D points
|
/// Define the structure for the 3D points
|
||||||
struct SfmTrack {
|
struct SfmTrack {
|
||||||
SfmTrack(): p(0,0,0) {}
|
SfmTrack(): p(0,0,0) {}
|
||||||
|
SfmTrack(const gtsam::Point3& pt) : p(pt) {}
|
||||||
Point3 p; ///< 3D position of the point
|
Point3 p; ///< 3D position of the point
|
||||||
float r, g, b; ///< RGB color of the 3D point
|
float r, g, b; ///< RGB color of the 3D point
|
||||||
std::vector<SfmMeasurement> measurements; ///< The 2D image projections (id,(u,v))
|
std::vector<SfmMeasurement> measurements; ///< The 2D image projections (id,(u,v))
|
||||||
std::vector<SiftIndex> siftIndices;
|
std::vector<SiftIndex> siftIndices;
|
||||||
|
|
||||||
/// Total number of measurements in this track
|
/// Total number of measurements in this track
|
||||||
size_t number_measurements() const {
|
size_t number_measurements() const {
|
||||||
return measurements.size();
|
return measurements.size();
|
||||||
|
@ -233,11 +235,17 @@ struct SfmTrack {
|
||||||
SiftIndex siftIndex(size_t idx) const {
|
SiftIndex siftIndex(size_t idx) const {
|
||||||
return siftIndices[idx];
|
return siftIndices[idx];
|
||||||
}
|
}
|
||||||
Point3 point3() const {
|
/// Get 3D point
|
||||||
|
const Point3& point3() const {
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
/// Add measurement (camera_idx, Point2) to track
|
||||||
|
void add_measurement(size_t idx, const gtsam::Point2& m) {
|
||||||
|
measurements.emplace_back(idx, m);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/// Define the structure for the camera poses
|
/// Define the structure for the camera poses
|
||||||
typedef PinholeCamera<Cal3Bundler> SfmCamera;
|
typedef PinholeCamera<Cal3Bundler> SfmCamera;
|
||||||
|
|
||||||
|
@ -260,6 +268,14 @@ struct SfmData {
|
||||||
SfmTrack track(size_t idx) const {
|
SfmTrack track(size_t idx) const {
|
||||||
return tracks[idx];
|
return tracks[idx];
|
||||||
}
|
}
|
||||||
|
/// Add a track to SfmData
|
||||||
|
void add_track(const SfmTrack& t) {
|
||||||
|
tracks.push_back(t);
|
||||||
|
}
|
||||||
|
/// Add a camera to SfmData
|
||||||
|
void add_camera(const SfmCamera& cam){
|
||||||
|
cameras.push_back(cam);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -361,8 +361,12 @@ TEST(Similarity3, AlignPose3) {
|
||||||
|
|
||||||
vector<Pose3Pair> correspondences{bTa1, bTa2};
|
vector<Pose3Pair> correspondences{bTa1, bTa2};
|
||||||
|
|
||||||
|
// Cayley transform cannot accommodate 180 degree rotations,
|
||||||
|
// hence we only test for Expmap
|
||||||
|
#ifdef GTSAM_ROT3_EXPMAP
|
||||||
Similarity3 actual_aSb = Similarity3::Align(correspondences);
|
Similarity3 actual_aSb = Similarity3::Align(correspondences);
|
||||||
EXPECT(assert_equal(expected_aSb, actual_aSb));
|
EXPECT(assert_equal(expected_aSb, actual_aSb));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
//******************************************************************************
|
//******************************************************************************
|
||||||
|
|
|
@ -81,7 +81,7 @@ class QPSVisitor {
|
||||||
varname_to_key; // Variable QPS string name to key
|
varname_to_key; // Variable QPS string name to key
|
||||||
std::unordered_map<Key, std::unordered_map<Key, Matrix11>>
|
std::unordered_map<Key, std::unordered_map<Key, Matrix11>>
|
||||||
H; // H from hessian
|
H; // H from hessian
|
||||||
double f; // Constant term of quadratic cost
|
double f = 0; // Constant term of quadratic cost
|
||||||
std::string obj_name; // the objective function has a name in the QPS
|
std::string obj_name; // the objective function has a name in the QPS
|
||||||
std::string name_; // the quadratic program has a name in the QPS
|
std::string name_; // the quadratic program has a name in the QPS
|
||||||
std::unordered_map<Key, double>
|
std::unordered_map<Key, double>
|
||||||
|
@ -175,10 +175,11 @@ class QPSVisitor {
|
||||||
string var_ = fromChars<1>(vars);
|
string var_ = fromChars<1>(vars);
|
||||||
string row_ = fromChars<3>(vars);
|
string row_ = fromChars<3>(vars);
|
||||||
double coefficient = at_c<5>(vars);
|
double coefficient = at_c<5>(vars);
|
||||||
if (row_ == obj_name)
|
if (row_ == obj_name) {
|
||||||
f = -coefficient;
|
f = -coefficient;
|
||||||
else
|
} else {
|
||||||
b[row_] = coefficient;
|
b[row_] = coefficient;
|
||||||
|
}
|
||||||
|
|
||||||
if (debug) {
|
if (debug) {
|
||||||
cout << "Added RHS for Var: " << var_ << " Row: " << row_
|
cout << "Added RHS for Var: " << var_ << " Row: " << row_
|
||||||
|
@ -194,15 +195,17 @@ class QPSVisitor {
|
||||||
string row2_ = fromChars<7>(vars);
|
string row2_ = fromChars<7>(vars);
|
||||||
double coefficient1 = at_c<5>(vars);
|
double coefficient1 = at_c<5>(vars);
|
||||||
double coefficient2 = at_c<9>(vars);
|
double coefficient2 = at_c<9>(vars);
|
||||||
if (row1_ == obj_name)
|
if (row1_ == obj_name) {
|
||||||
f = -coefficient1;
|
f = -coefficient1;
|
||||||
else
|
} else {
|
||||||
b[row1_] = coefficient1;
|
b[row1_] = coefficient1;
|
||||||
|
}
|
||||||
|
|
||||||
if (row2_ == obj_name)
|
if (row2_ == obj_name) {
|
||||||
f = -coefficient2;
|
f = -coefficient2;
|
||||||
else
|
} else {
|
||||||
b[row2_] = coefficient2;
|
b[row2_] = coefficient2;
|
||||||
|
}
|
||||||
|
|
||||||
if (debug) {
|
if (debug) {
|
||||||
cout << "Added RHS for Var: " << var_ << " Row: " << row1_
|
cout << "Added RHS for Var: " << var_ << " Row: " << row1_
|
||||||
|
|
|
@ -2,6 +2,10 @@
|
||||||
|
|
||||||
include(GtsamMatlabWrap)
|
include(GtsamMatlabWrap)
|
||||||
|
|
||||||
|
# Record the root dir for gtsam - needed during external builds, e.g., ROS
|
||||||
|
set(GTSAM_SOURCE_ROOT_DIR ${GTSAM_SOURCE_DIR})
|
||||||
|
message(STATUS "GTSAM_SOURCE_ROOT_DIR: [${GTSAM_SOURCE_ROOT_DIR}]")
|
||||||
|
|
||||||
# Tests
|
# Tests
|
||||||
#message(STATUS "Installing Matlab Toolbox")
|
#message(STATUS "Installing Matlab Toolbox")
|
||||||
install_matlab_scripts("${GTSAM_SOURCE_ROOT_DIR}/matlab/" "*.m;*.fig")
|
install_matlab_scripts("${GTSAM_SOURCE_ROOT_DIR}/matlab/" "*.m;*.fig")
|
||||||
|
@ -21,7 +25,7 @@ install_matlab_scripts("${GTSAM_SOURCE_ROOT_DIR}/matlab/" "README-gtsam-toolbox.
|
||||||
file(GLOB matlab_examples_data_graph "${GTSAM_SOURCE_ROOT_DIR}/examples/Data/*.graph")
|
file(GLOB matlab_examples_data_graph "${GTSAM_SOURCE_ROOT_DIR}/examples/Data/*.graph")
|
||||||
file(GLOB matlab_examples_data_mat "${GTSAM_SOURCE_ROOT_DIR}/examples/Data/*.mat")
|
file(GLOB matlab_examples_data_mat "${GTSAM_SOURCE_ROOT_DIR}/examples/Data/*.mat")
|
||||||
file(GLOB matlab_examples_data_txt "${GTSAM_SOURCE_ROOT_DIR}/examples/Data/*.txt")
|
file(GLOB matlab_examples_data_txt "${GTSAM_SOURCE_ROOT_DIR}/examples/Data/*.txt")
|
||||||
set(matlab_examples_data ${matlab_examples_data_graph} ${matlab_examples_data_mat} ${matlab_examples_data_txt})
|
set(matlab_examples_data ${matlab_examples_data_graph} ${matlab_examples_data_mat} ${matlab_examples_data_txt})
|
||||||
if(GTSAM_BUILD_TYPE_POSTFIXES)
|
if(GTSAM_BUILD_TYPE_POSTFIXES)
|
||||||
foreach(build_type ${CMAKE_CONFIGURATION_TYPES})
|
foreach(build_type ${CMAKE_CONFIGURATION_TYPES})
|
||||||
string(TOUPPER "${build_type}" build_type_upper)
|
string(TOUPPER "${build_type}" build_type_upper)
|
||||||
|
@ -38,4 +42,3 @@ if(GTSAM_BUILD_TYPE_POSTFIXES)
|
||||||
else()
|
else()
|
||||||
install(FILES ${matlab_examples_data} DESTINATION ${GTSAM_TOOLBOX_INSTALL_PATH}/gtsam_examples/Data)
|
install(FILES ${matlab_examples_data} DESTINATION ${GTSAM_TOOLBOX_INSTALL_PATH}/gtsam_examples/Data)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,7 @@
|
||||||
| SelfCalibrationExample | |
|
| SelfCalibrationExample | |
|
||||||
| SFMdata | |
|
| SFMdata | |
|
||||||
| SFMExample_bal_COLAMD_METIS | |
|
| SFMExample_bal_COLAMD_METIS | |
|
||||||
| SFMExample_bal | |
|
| SFMExample_bal | :heavy_check_mark: |
|
||||||
| SFMExample | :heavy_check_mark: |
|
| SFMExample | :heavy_check_mark: |
|
||||||
| SFMExampleExpressions_bal | |
|
| SFMExampleExpressions_bal | |
|
||||||
| SFMExampleExpressions | |
|
| SFMExampleExpressions | |
|
||||||
|
|
|
@ -0,0 +1,118 @@
|
||||||
|
"""
|
||||||
|
GTSAM Copyright 2010, Georgia Tech Research Corporation,
|
||||||
|
Atlanta, Georgia 30332-0415
|
||||||
|
All Rights Reserved
|
||||||
|
Authors: Frank Dellaert, et al. (see THANKS for the full author list)
|
||||||
|
|
||||||
|
See LICENSE for the license information
|
||||||
|
|
||||||
|
Solve a structure-from-motion problem from a "Bundle Adjustment in the Large" file
|
||||||
|
Author: Frank Dellaert (Python: Akshay Krishnan, John Lambert)
|
||||||
|
"""
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import logging
|
||||||
|
import sys
|
||||||
|
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
import gtsam
|
||||||
|
from gtsam import (
|
||||||
|
GeneralSFMFactorCal3Bundler,
|
||||||
|
PinholeCameraCal3Bundler,
|
||||||
|
PriorFactorPinholeCameraCal3Bundler,
|
||||||
|
readBal,
|
||||||
|
symbol_shorthand
|
||||||
|
)
|
||||||
|
|
||||||
|
C = symbol_shorthand.C
|
||||||
|
P = symbol_shorthand.P
|
||||||
|
|
||||||
|
|
||||||
|
logging.basicConfig(stream=sys.stdout, level=logging.DEBUG)
|
||||||
|
|
||||||
|
def run(args):
|
||||||
|
""" Run LM optimization with BAL input data and report resulting error """
|
||||||
|
input_file = gtsam.findExampleDataFile(args.input_file)
|
||||||
|
|
||||||
|
# Load the SfM data from file
|
||||||
|
scene_data = readBal(input_file)
|
||||||
|
logging.info(f"read {scene_data.number_tracks()} tracks on {scene_data.number_cameras()} cameras\n")
|
||||||
|
|
||||||
|
# Create a factor graph
|
||||||
|
graph = gtsam.NonlinearFactorGraph()
|
||||||
|
|
||||||
|
# We share *one* noiseModel between all projection factors
|
||||||
|
noise = gtsam.noiseModel.Isotropic.Sigma(2, 1.0) # one pixel in u and v
|
||||||
|
|
||||||
|
# Add measurements to the factor graph
|
||||||
|
j = 0
|
||||||
|
for t_idx in range(scene_data.number_tracks()):
|
||||||
|
track = scene_data.track(t_idx) # SfmTrack
|
||||||
|
# retrieve the SfmMeasurement objects
|
||||||
|
for m_idx in range(track.number_measurements()):
|
||||||
|
# i represents the camera index, and uv is the 2d measurement
|
||||||
|
i, uv = track.measurement(m_idx)
|
||||||
|
# note use of shorthand symbols C and P
|
||||||
|
graph.add(GeneralSFMFactorCal3Bundler(uv, noise, C(i), P(j)))
|
||||||
|
j += 1
|
||||||
|
|
||||||
|
# Add a prior on pose x1. This indirectly specifies where the origin is.
|
||||||
|
graph.push_back(
|
||||||
|
gtsam.PriorFactorPinholeCameraCal3Bundler(
|
||||||
|
C(0), scene_data.camera(0), gtsam.noiseModel.Isotropic.Sigma(9, 0.1)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
# Also add a prior on the position of the first landmark to fix the scale
|
||||||
|
graph.push_back(
|
||||||
|
gtsam.PriorFactorPoint3(
|
||||||
|
P(0), scene_data.track(0).point3(), gtsam.noiseModel.Isotropic.Sigma(3, 0.1)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
# Create initial estimate
|
||||||
|
initial = gtsam.Values()
|
||||||
|
|
||||||
|
i = 0
|
||||||
|
# add each PinholeCameraCal3Bundler
|
||||||
|
for cam_idx in range(scene_data.number_cameras()):
|
||||||
|
camera = scene_data.camera(cam_idx)
|
||||||
|
initial.insert(C(i), camera)
|
||||||
|
i += 1
|
||||||
|
|
||||||
|
j = 0
|
||||||
|
# add each SfmTrack
|
||||||
|
for t_idx in range(scene_data.number_tracks()):
|
||||||
|
track = scene_data.track(t_idx)
|
||||||
|
initial.insert(P(j), track.point3())
|
||||||
|
j += 1
|
||||||
|
|
||||||
|
# Optimize the graph and print results
|
||||||
|
try:
|
||||||
|
params = gtsam.LevenbergMarquardtParams()
|
||||||
|
params.setVerbosityLM("ERROR")
|
||||||
|
lm = gtsam.LevenbergMarquardtOptimizer(graph, initial, params)
|
||||||
|
result = lm.optimize()
|
||||||
|
except Exception as e:
|
||||||
|
logging.exception("LM Optimization failed")
|
||||||
|
return
|
||||||
|
# Error drops from ~2764.22 to ~0.046
|
||||||
|
logging.info(f"final error: {graph.error(result)}")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument(
|
||||||
|
'-i',
|
||||||
|
'--input_file',
|
||||||
|
type=str,
|
||||||
|
default="dubrovnik-3-7-pre",
|
||||||
|
help='Read SFM data from the specified BAL file'
|
||||||
|
'The data format is described here: https://grail.cs.washington.edu/projects/bal/.'
|
||||||
|
'BAL files contain (nrPoses, nrPoints, nrObservations), followed by (i,j,u,v) tuples, '
|
||||||
|
'then (wx,wy,wz,tx,ty,tz,f,k1,k1) as Bundler camera calibrations w/ Rodrigues vector'
|
||||||
|
'and (x,y,z) 3d point initializations.'
|
||||||
|
)
|
||||||
|
run(parser.parse_args())
|
||||||
|
|
|
@ -65,6 +65,14 @@ class TestPose3(GtsamTestCase):
|
||||||
actual = Pose3.adjoint_(xi, xi)
|
actual = Pose3.adjoint_(xi, xi)
|
||||||
np.testing.assert_array_equal(actual, expected)
|
np.testing.assert_array_equal(actual, expected)
|
||||||
|
|
||||||
|
def test_serialization(self):
|
||||||
|
"""Test if serialization is working normally"""
|
||||||
|
expected = Pose3(Rot3.Ypr(0.0, 1.0, 0.0), Point3(1, 1, 0))
|
||||||
|
actual = Pose3()
|
||||||
|
serialized = expected.serialize()
|
||||||
|
actual.deserialize(serialized)
|
||||||
|
self.gtsamAssertEquals(expected, actual, 1e-10)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
|
@ -0,0 +1,79 @@
|
||||||
|
"""
|
||||||
|
GTSAM Copyright 2010-2019, Georgia Tech Research Corporation,
|
||||||
|
Atlanta, Georgia 30332-0415
|
||||||
|
All Rights Reserved
|
||||||
|
|
||||||
|
See LICENSE for the license information
|
||||||
|
|
||||||
|
Unit tests for testing dataset access.
|
||||||
|
Author: Frank Dellaert (Python: Sushmita Warrier)
|
||||||
|
"""
|
||||||
|
# pylint: disable=invalid-name, no-name-in-module, no-member
|
||||||
|
|
||||||
|
from __future__ import print_function
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
import gtsam
|
||||||
|
from gtsam.utils.test_case import GtsamTestCase
|
||||||
|
|
||||||
|
|
||||||
|
class TestSfmData(GtsamTestCase):
|
||||||
|
"""Tests for SfmData and SfmTrack modules."""
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
"""Initialize SfmData and SfmTrack"""
|
||||||
|
self.data = gtsam.SfmData()
|
||||||
|
# initialize SfmTrack with 3D point
|
||||||
|
self.tracks = gtsam.SfmTrack()
|
||||||
|
|
||||||
|
def test_tracks(self):
|
||||||
|
"""Test functions in SfmTrack"""
|
||||||
|
# measurement is of format (camera_idx, imgPoint)
|
||||||
|
# create arbitrary camera indices for two cameras
|
||||||
|
i1, i2 = 4,5
|
||||||
|
# create arbitrary image measurements for cameras i1 and i2
|
||||||
|
uv_i1 = gtsam.Point2(12.6, 82)
|
||||||
|
# translating point uv_i1 along X-axis
|
||||||
|
uv_i2 = gtsam.Point2(24.88, 82)
|
||||||
|
# add measurements to the track
|
||||||
|
self.tracks.add_measurement(i1, uv_i1)
|
||||||
|
self.tracks.add_measurement(i2, uv_i2)
|
||||||
|
# Number of measurements in the track is 2
|
||||||
|
self.assertEqual(self.tracks.number_measurements(), 2)
|
||||||
|
# camera_idx in the first measurement of the track corresponds to i1
|
||||||
|
cam_idx, img_measurement = self.tracks.measurement(0)
|
||||||
|
self.assertEqual(cam_idx, i1)
|
||||||
|
np.testing.assert_array_almost_equal(
|
||||||
|
gtsam.Point3(0.,0.,0.),
|
||||||
|
self.tracks.point3()
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_data(self):
|
||||||
|
"""Test functions in SfmData"""
|
||||||
|
# Create new track with 3 measurements
|
||||||
|
i1, i2, i3 = 3,5,6
|
||||||
|
uv_i1 = gtsam.Point2(21.23, 45.64)
|
||||||
|
# translating along X-axis
|
||||||
|
uv_i2 = gtsam.Point2(45.7, 45.64)
|
||||||
|
uv_i3 = gtsam.Point2(68.35, 45.64)
|
||||||
|
# add measurements and arbitrary point to the track
|
||||||
|
measurements = [(i1, uv_i1), (i2, uv_i2), (i3, uv_i3)]
|
||||||
|
pt = gtsam.Point3(1.0, 6.0, 2.0)
|
||||||
|
track2 = gtsam.SfmTrack(pt)
|
||||||
|
track2.add_measurement(i1, uv_i1)
|
||||||
|
track2.add_measurement(i2, uv_i2)
|
||||||
|
track2.add_measurement(i3, uv_i3)
|
||||||
|
self.data.add_track(self.tracks)
|
||||||
|
self.data.add_track(track2)
|
||||||
|
# Number of tracks in SfmData is 2
|
||||||
|
self.assertEqual(self.data.number_tracks(), 2)
|
||||||
|
# camera idx of first measurement of second track corresponds to i1
|
||||||
|
cam_idx, img_measurement = self.data.track(1).measurement(0)
|
||||||
|
self.assertEqual(cam_idx, i1)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
|
@ -566,6 +566,58 @@ TEST( NonlinearOptimizer, logfile )
|
||||||
// EXPECT(actual.str()==expected.str());
|
// EXPECT(actual.str()==expected.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
TEST( NonlinearOptimizer, iterationHook_LM )
|
||||||
|
{
|
||||||
|
NonlinearFactorGraph fg(example::createReallyNonlinearFactorGraph());
|
||||||
|
|
||||||
|
Point2 x0(3,3);
|
||||||
|
Values c0;
|
||||||
|
c0.insert(X(1), x0);
|
||||||
|
|
||||||
|
// Levenberg-Marquardt
|
||||||
|
LevenbergMarquardtParams lmParams;
|
||||||
|
size_t lastIterCalled = 0;
|
||||||
|
lmParams.iterationHook = [&](size_t iteration, double oldError, double newError)
|
||||||
|
{
|
||||||
|
// Tests:
|
||||||
|
lastIterCalled = iteration;
|
||||||
|
EXPECT(newError<oldError);
|
||||||
|
|
||||||
|
// Example of evolution printout:
|
||||||
|
//std::cout << "iter: " << iteration << " error: " << oldError << " => " << newError <<"\n";
|
||||||
|
};
|
||||||
|
LevenbergMarquardtOptimizer(fg, c0, lmParams).optimize();
|
||||||
|
|
||||||
|
EXPECT(lastIterCalled>5);
|
||||||
|
}
|
||||||
|
/* ************************************************************************* */
|
||||||
|
TEST( NonlinearOptimizer, iterationHook_CG )
|
||||||
|
{
|
||||||
|
NonlinearFactorGraph fg(example::createReallyNonlinearFactorGraph());
|
||||||
|
|
||||||
|
Point2 x0(3,3);
|
||||||
|
Values c0;
|
||||||
|
c0.insert(X(1), x0);
|
||||||
|
|
||||||
|
// Levenberg-Marquardt
|
||||||
|
NonlinearConjugateGradientOptimizer::Parameters cgParams;
|
||||||
|
size_t lastIterCalled = 0;
|
||||||
|
cgParams.iterationHook = [&](size_t iteration, double oldError, double newError)
|
||||||
|
{
|
||||||
|
// Tests:
|
||||||
|
lastIterCalled = iteration;
|
||||||
|
EXPECT(newError<oldError);
|
||||||
|
|
||||||
|
// Example of evolution printout:
|
||||||
|
//std::cout << "iter: " << iteration << " error: " << oldError << " => " << newError <<"\n";
|
||||||
|
};
|
||||||
|
NonlinearConjugateGradientOptimizer(fg, c0, cgParams).optimize();
|
||||||
|
|
||||||
|
EXPECT(lastIterCalled>5);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
//// Minimal traits example
|
//// Minimal traits example
|
||||||
struct MyType : public Vector3 {
|
struct MyType : public Vector3 {
|
||||||
|
|
|
@ -146,7 +146,7 @@ function(install_python_scripts
|
||||||
else()
|
else()
|
||||||
set(build_type_tag "")
|
set(build_type_tag "")
|
||||||
endif()
|
endif()
|
||||||
# Split up filename to strip trailing '/' in WRAP_CYTHON_INSTALL_PATH if
|
# Split up filename to strip trailing '/' in GTSAM_PY_INSTALL_PATH if
|
||||||
# there is one
|
# there is one
|
||||||
get_filename_component(location "${dest_directory}" PATH)
|
get_filename_component(location "${dest_directory}" PATH)
|
||||||
get_filename_component(name "${dest_directory}" NAME)
|
get_filename_component(name "${dest_directory}" NAME)
|
||||||
|
|
|
@ -69,13 +69,13 @@ class PybindWrapper(object):
|
||||||
return textwrap.dedent('''
|
return textwrap.dedent('''
|
||||||
.def("serialize",
|
.def("serialize",
|
||||||
[]({class_inst} self){{
|
[]({class_inst} self){{
|
||||||
return gtsam::serialize(self);
|
return gtsam::serialize(*self);
|
||||||
}}
|
}}
|
||||||
)
|
)
|
||||||
.def("deserialize",
|
.def("deserialize",
|
||||||
[]({class_inst} self, string serialized){{
|
[]({class_inst} self, string serialized){{
|
||||||
return gtsam::deserialize(serialized, self);
|
gtsam::deserialize(serialized, *self);
|
||||||
}})
|
}}, py::arg("serialized"))
|
||||||
'''.format(class_inst=cpp_class + '*'))
|
'''.format(class_inst=cpp_class + '*'))
|
||||||
|
|
||||||
is_method = isinstance(method, instantiator.InstantiatedMethod)
|
is_method = isinstance(method, instantiator.InstantiatedMethod)
|
||||||
|
|
|
@ -40,13 +40,13 @@ PYBIND11_MODULE(geometry_py, m_) {
|
||||||
.def("vectorConfusion",[](gtsam::Point2* self){return self->vectorConfusion();})
|
.def("vectorConfusion",[](gtsam::Point2* self){return self->vectorConfusion();})
|
||||||
.def("serialize",
|
.def("serialize",
|
||||||
[](gtsam::Point2* self){
|
[](gtsam::Point2* self){
|
||||||
return gtsam::serialize(self);
|
return gtsam::serialize(*self);
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.def("deserialize",
|
.def("deserialize",
|
||||||
[](gtsam::Point2* self, string serialized){
|
[](gtsam::Point2* self, string serialized){
|
||||||
return gtsam::deserialize(serialized, self);
|
gtsam::deserialize(serialized, *self);
|
||||||
})
|
}, py::arg("serialized"))
|
||||||
;
|
;
|
||||||
|
|
||||||
py::class_<gtsam::Point3, std::shared_ptr<gtsam::Point3>>(m_gtsam, "Point3")
|
py::class_<gtsam::Point3, std::shared_ptr<gtsam::Point3>>(m_gtsam, "Point3")
|
||||||
|
@ -54,13 +54,13 @@ PYBIND11_MODULE(geometry_py, m_) {
|
||||||
.def("norm",[](gtsam::Point3* self){return self->norm();})
|
.def("norm",[](gtsam::Point3* self){return self->norm();})
|
||||||
.def("serialize",
|
.def("serialize",
|
||||||
[](gtsam::Point3* self){
|
[](gtsam::Point3* self){
|
||||||
return gtsam::serialize(self);
|
return gtsam::serialize(*self);
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.def("deserialize",
|
.def("deserialize",
|
||||||
[](gtsam::Point3* self, string serialized){
|
[](gtsam::Point3* self, string serialized){
|
||||||
return gtsam::deserialize(serialized, self);
|
gtsam::deserialize(serialized, *self);
|
||||||
})
|
}, py::arg("serialized"))
|
||||||
|
|
||||||
.def_static("staticFunction",[](){return gtsam::Point3::staticFunction();})
|
.def_static("staticFunction",[](){return gtsam::Point3::staticFunction();})
|
||||||
.def_static("StaticFunctionRet",[]( double z){return gtsam::Point3::StaticFunctionRet(z);}, py::arg("z"));
|
.def_static("StaticFunctionRet",[]( double z){return gtsam::Point3::StaticFunctionRet(z);}, py::arg("z"));
|
||||||
|
|
Loading…
Reference in New Issue