Merge branch 'release/4.1.1'
commit
69a3a75195
|
|
@ -0,0 +1,18 @@
|
|||
### Script to install Boost
|
||||
BOOST_FOLDER=boost_${BOOST_VERSION//./_}
|
||||
|
||||
# Download Boost
|
||||
wget https://boostorg.jfrog.io/artifactory/main/release/${BOOST_VERSION}/source/${BOOST_FOLDER}.tar.gz
|
||||
|
||||
# Unzip
|
||||
tar -zxf ${BOOST_FOLDER}.tar.gz
|
||||
|
||||
# Bootstrap
|
||||
cd ${BOOST_FOLDER}/
|
||||
./bootstrap.sh --with-libraries=serialization,filesystem,thread,system,atomic,date_time,timer,chrono,program_options,regex
|
||||
|
||||
# Build and install
|
||||
sudo ./b2 -j$(nproc) install
|
||||
|
||||
# Rebuild ld cache
|
||||
sudo ldconfig
|
||||
|
|
@ -43,11 +43,6 @@ if [ -z ${PYTHON_VERSION+x} ]; then
|
|||
exit 127
|
||||
fi
|
||||
|
||||
if [ -z ${WRAPPER+x} ]; then
|
||||
echo "Please provide the wrapper to build!"
|
||||
exit 126
|
||||
fi
|
||||
|
||||
PYTHON="python${PYTHON_VERSION}"
|
||||
|
||||
if [[ $(uname) == "Darwin" ]]; then
|
||||
|
|
@ -61,67 +56,33 @@ PATH=$PATH:$($PYTHON -c "import site; print(site.USER_BASE)")/bin
|
|||
|
||||
[ "${GTSAM_WITH_TBB:-OFF}" = "ON" ] && install_tbb
|
||||
|
||||
case $WRAPPER in
|
||||
"cython")
|
||||
BUILD_CYTHON="ON"
|
||||
BUILD_PYBIND="OFF"
|
||||
TYPEDEF_POINTS_TO_VECTORS="OFF"
|
||||
|
||||
sudo $PYTHON -m pip install -r $GITHUB_WORKSPACE/cython/requirements.txt
|
||||
;;
|
||||
"pybind")
|
||||
BUILD_CYTHON="OFF"
|
||||
BUILD_PYBIND="ON"
|
||||
TYPEDEF_POINTS_TO_VECTORS="ON"
|
||||
BUILD_PYBIND="ON"
|
||||
|
||||
sudo $PYTHON -m pip install -r $GITHUB_WORKSPACE/python/requirements.txt
|
||||
;;
|
||||
*)
|
||||
exit 126
|
||||
;;
|
||||
esac
|
||||
sudo $PYTHON -m pip install -r $GITHUB_WORKSPACE/python/requirements.txt
|
||||
|
||||
mkdir $GITHUB_WORKSPACE/build
|
||||
cd $GITHUB_WORKSPACE/build
|
||||
|
||||
cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=Release \
|
||||
-DGTSAM_BUILD_TESTS=OFF -DGTSAM_BUILD_UNSTABLE=ON \
|
||||
cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} \
|
||||
-DGTSAM_BUILD_TESTS=OFF \
|
||||
-DGTSAM_BUILD_UNSTABLE=${GTSAM_BUILD_UNSTABLE:-ON} \
|
||||
-DGTSAM_USE_QUATERNIONS=OFF \
|
||||
-DGTSAM_WITH_TBB=${GTSAM_WITH_TBB:-OFF} \
|
||||
-DGTSAM_BUILD_EXAMPLES_ALWAYS=OFF \
|
||||
-DGTSAM_BUILD_WITH_MARCH_NATIVE=OFF \
|
||||
-DGTSAM_INSTALL_CYTHON_TOOLBOX=${BUILD_CYTHON} \
|
||||
-DGTSAM_BUILD_PYTHON=${BUILD_PYBIND} \
|
||||
-DGTSAM_TYPEDEF_POINTS_TO_VECTORS=${TYPEDEF_POINTS_TO_VECTORS} \
|
||||
-DGTSAM_UNSTABLE_BUILD_PYTHON=${GTSAM_BUILD_UNSTABLE:-ON} \
|
||||
-DGTSAM_PYTHON_VERSION=$PYTHON_VERSION \
|
||||
-DPYTHON_EXECUTABLE:FILEPATH=$(which $PYTHON) \
|
||||
-DGTSAM_ALLOW_DEPRECATED_SINCE_V41=OFF \
|
||||
-DCMAKE_INSTALL_PREFIX=$GITHUB_WORKSPACE/gtsam_install
|
||||
|
||||
make -j$(nproc) install &
|
||||
|
||||
while ps -p $! > /dev/null
|
||||
do
|
||||
sleep 60
|
||||
now=$(date +%s)
|
||||
printf "%d seconds have elapsed\n" $(( (now - start) ))
|
||||
done
|
||||
# Set to 2 cores so that Actions does not error out during resource provisioning.
|
||||
make -j2 install
|
||||
|
||||
case $WRAPPER in
|
||||
"cython")
|
||||
cd $GITHUB_WORKSPACE/build/cython
|
||||
$PYTHON setup.py install --user --prefix=
|
||||
cd $GITHUB_WORKSPACE/build/cython/gtsam/tests
|
||||
$PYTHON -m unittest discover
|
||||
;;
|
||||
"pybind")
|
||||
cd $GITHUB_WORKSPACE/build/python
|
||||
$PYTHON setup.py install --user --prefix=
|
||||
cd $GITHUB_WORKSPACE/python/gtsam/tests
|
||||
$PYTHON -m unittest discover
|
||||
;;
|
||||
*)
|
||||
echo "THIS SHOULD NEVER HAPPEN!"
|
||||
exit 125
|
||||
;;
|
||||
esac
|
||||
cd $GITHUB_WORKSPACE/build/python
|
||||
$PYTHON setup.py install --user --prefix=
|
||||
cd $GITHUB_WORKSPACE/python/gtsam/tests
|
||||
$PYTHON -m unittest discover -v
|
||||
|
|
|
|||
|
|
@ -66,6 +66,10 @@ function configure()
|
|||
-DGTSAM_BUILD_EXAMPLES_ALWAYS=${GTSAM_BUILD_EXAMPLES_ALWAYS:-ON} \
|
||||
-DGTSAM_ALLOW_DEPRECATED_SINCE_V41=${GTSAM_ALLOW_DEPRECATED_SINCE_V41:-OFF} \
|
||||
-DGTSAM_USE_QUATERNIONS=${GTSAM_USE_QUATERNIONS:-OFF} \
|
||||
-DGTSAM_ROT3_EXPMAP=${GTSAM_ROT3_EXPMAP:-ON} \
|
||||
-DGTSAM_POSE3_EXPMAP=${GTSAM_POSE3_EXPMAP:-ON} \
|
||||
-DGTSAM_USE_SYSTEM_EIGEN=${GTSAM_USE_SYSTEM_EIGEN:-OFF} \
|
||||
-DGTSAM_USE_SYSTEM_METIS=${GTSAM_USE_SYSTEM_METIS:-OFF} \
|
||||
-DGTSAM_BUILD_WITH_MARCH_NATIVE=OFF \
|
||||
-DBOOST_ROOT=$BOOST_ROOT \
|
||||
-DBoost_NO_SYSTEM_PATHS=ON \
|
||||
|
|
@ -90,7 +94,11 @@ function build ()
|
|||
|
||||
configure
|
||||
|
||||
make -j2
|
||||
if [ "$(uname)" == "Linux" ]; then
|
||||
make -j$(nproc)
|
||||
elif [ "$(uname)" == "Darwin" ]; then
|
||||
make -j$(sysctl -n hw.physicalcpu)
|
||||
fi
|
||||
|
||||
finish
|
||||
}
|
||||
|
|
@ -103,8 +111,12 @@ function test ()
|
|||
|
||||
configure
|
||||
|
||||
# Actual build:
|
||||
make -j2 check
|
||||
# Actual testing
|
||||
if [ "$(uname)" == "Linux" ]; then
|
||||
make -j$(nproc) check
|
||||
elif [ "$(uname)" == "Darwin" ]; then
|
||||
make -j$(sysctl -n hw.physicalcpu) check
|
||||
fi
|
||||
|
||||
finish
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ jobs:
|
|||
CTEST_PARALLEL_LEVEL: 2
|
||||
CMAKE_BUILD_TYPE: ${{ matrix.build_type }}
|
||||
GTSAM_BUILD_UNSTABLE: ${{ matrix.build_unstable }}
|
||||
BOOST_VERSION: 1.67.0
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
|
|
@ -44,35 +45,38 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@master
|
||||
- name: Install (Linux)
|
||||
if: runner.os == 'Linux'
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Install Dependencies
|
||||
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
|
||||
# (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 keyserver.ubuntu.com --recv-key $LLVM_KEY || gpg --keyserver hkp://keyserver.ubuntu.com:80 --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"
|
||||
fi
|
||||
sudo apt-get -y update
|
||||
|
||||
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 "::set-env name=LD_LIBRARY_PATH::$(echo $BOOST_ROOT_1_69_0/lib)"
|
||||
|
||||
sudo apt-get -y install cmake build-essential pkg-config libpython-dev python-numpy libicu-dev
|
||||
|
||||
if [ "${{ matrix.compiler }}" = "gcc" ]; then
|
||||
sudo apt-get install -y g++-${{ matrix.version }} g++-${{ matrix.version }}-multilib
|
||||
echo "::set-env name=CC::gcc-${{ matrix.version }}"
|
||||
echo "::set-env name=CXX::g++-${{ matrix.version }}"
|
||||
echo "CC=gcc-${{ matrix.version }}" >> $GITHUB_ENV
|
||||
echo "CXX=g++-${{ matrix.version }}" >> $GITHUB_ENV
|
||||
else
|
||||
sudo apt-get install -y clang-${{ matrix.version }} g++-multilib
|
||||
echo "::set-env name=CC::clang-${{ matrix.version }}"
|
||||
echo "::set-env name=CXX::clang++-${{ matrix.version }}"
|
||||
echo "CC=clang-${{ matrix.version }}" >> $GITHUB_ENV
|
||||
echo "CXX=clang++-${{ matrix.version }}" >> $GITHUB_ENV
|
||||
fi
|
||||
- name: Check Boost version
|
||||
if: runner.os == 'Linux'
|
||||
|
||||
- name: Install Boost
|
||||
run: |
|
||||
echo "BOOST_ROOT = $BOOST_ROOT"
|
||||
- name: Build and Test (Linux)
|
||||
if: runner.os == 'Linux'
|
||||
run: |
|
||||
bash .github/scripts/unix.sh -t
|
||||
bash .github/scripts/boost.sh
|
||||
|
||||
- name: Build and Test
|
||||
run: bash .github/scripts/unix.sh -t
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ jobs:
|
|||
CTEST_PARALLEL_LEVEL: 2
|
||||
CMAKE_BUILD_TYPE: ${{ matrix.build_type }}
|
||||
GTSAM_BUILD_UNSTABLE: ${{ matrix.build_unstable }}
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
|
|
@ -31,21 +32,20 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@master
|
||||
- name: Install (macOS)
|
||||
if: runner.os == 'macOS'
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Install Dependencies
|
||||
run: |
|
||||
brew install cmake ninja boost
|
||||
brew install cmake ninja
|
||||
brew install boost
|
||||
if [ "${{ matrix.compiler }}" = "gcc" ]; then
|
||||
brew install gcc@${{ matrix.version }}
|
||||
echo "::set-env name=CC::gcc-${{ matrix.version }}"
|
||||
echo "::set-env name=CXX::g++-${{ matrix.version }}"
|
||||
echo "CC=gcc-${{ matrix.version }}" >> $GITHUB_ENV
|
||||
echo "CXX=g++-${{ matrix.version }}" >> $GITHUB_ENV
|
||||
else
|
||||
sudo xcode-select -switch /Applications/Xcode_${{ matrix.version }}.app
|
||||
echo "::set-env name=CC::clang"
|
||||
echo "::set-env name=CXX::clang++"
|
||||
echo "CC=clang" >> $GITHUB_ENV
|
||||
echo "CXX=clang++" >> $GITHUB_ENV
|
||||
fi
|
||||
- name: Build and Test (macOS)
|
||||
if: runner.os == 'macOS'
|
||||
run: |
|
||||
bash .github/scripts/unix.sh -t
|
||||
- name: Build and Test
|
||||
run: bash .github/scripts/unix.sh -t
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ jobs:
|
|||
CTEST_PARALLEL_LEVEL: 2
|
||||
CMAKE_BUILD_TYPE: ${{ matrix.build_type }}
|
||||
PYTHON_VERSION: ${{ matrix.python_version }}
|
||||
WRAPPER: ${{ matrix.wrapper }}
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
|
|
@ -20,7 +20,7 @@ jobs:
|
|||
# See https://help.github.com/en/articles/workflow-syntax-for-github-actions.
|
||||
name: [
|
||||
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,
|
||||
macOS-10.15-xcode-11.3.1,
|
||||
ubuntu-18.04-gcc-5-tbb,
|
||||
|
|
@ -28,24 +28,30 @@ jobs:
|
|||
|
||||
build_type: [Debug, Release]
|
||||
python_version: [3]
|
||||
wrapper: [pybind]
|
||||
include:
|
||||
- name: ubuntu-18.04-gcc-5
|
||||
os: ubuntu-18.04
|
||||
compiler: gcc
|
||||
version: "5"
|
||||
|
||||
# TODO Disabled for now because of timeouts
|
||||
# - name: ubuntu-18.04-gcc-9
|
||||
# os: ubuntu-18.04
|
||||
# compiler: gcc
|
||||
# version: "9"
|
||||
- name: ubuntu-18.04-gcc-9
|
||||
os: ubuntu-18.04
|
||||
compiler: gcc
|
||||
version: "9"
|
||||
|
||||
- name: ubuntu-18.04-clang-9
|
||||
os: ubuntu-18.04
|
||||
compiler: clang
|
||||
version: "9"
|
||||
|
||||
# NOTE temporarily added this as it is a required check.
|
||||
- name: ubuntu-18.04-clang-9
|
||||
os: ubuntu-18.04
|
||||
compiler: clang
|
||||
version: "9"
|
||||
build_type: Debug
|
||||
python_version: "3"
|
||||
|
||||
- name: macOS-10.15-xcode-11.3.1
|
||||
os: macOS-10.15
|
||||
compiler: xcode
|
||||
|
|
@ -59,44 +65,52 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@master
|
||||
uses: actions/checkout@v2
|
||||
- name: Install (Linux)
|
||||
if: runner.os == 'Linux'
|
||||
run: |
|
||||
# LLVM 9 is not in Bionic's repositories so we add the official LLVM repository.
|
||||
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 keyserver.ubuntu.com --recv-key $LLVM_KEY || gpg --keyserver hkp://keyserver.ubuntu.com:80 --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"
|
||||
fi
|
||||
sudo apt-get -y update
|
||||
|
||||
sudo apt install cmake build-essential pkg-config libpython-dev python-numpy libboost-all-dev
|
||||
sudo apt-get -y install cmake build-essential pkg-config libpython-dev python-numpy libboost-all-dev
|
||||
|
||||
if [ "${{ matrix.compiler }}" = "gcc" ]; then
|
||||
sudo apt-get install -y g++-${{ matrix.version }} g++-${{ matrix.version }}-multilib
|
||||
echo "::set-env name=CC::gcc-${{ matrix.version }}"
|
||||
echo "::set-env name=CXX::g++-${{ matrix.version }}"
|
||||
echo "CC=gcc-${{ matrix.version }}" >> $GITHUB_ENV
|
||||
echo "CXX=g++-${{ matrix.version }}" >> $GITHUB_ENV
|
||||
else
|
||||
sudo apt-get install -y clang-${{ matrix.version }} g++-multilib
|
||||
echo "::set-env name=CC::clang-${{ matrix.version }}"
|
||||
echo "::set-env name=CXX::clang++-${{ matrix.version }}"
|
||||
echo "CC=clang-${{ matrix.version }}" >> $GITHUB_ENV
|
||||
echo "CXX=clang++-${{ matrix.version }}" >> $GITHUB_ENV
|
||||
fi
|
||||
- name: Install (macOS)
|
||||
if: runner.os == 'macOS'
|
||||
run: |
|
||||
brew install cmake ninja boost
|
||||
brew tap ProfFan/robotics
|
||||
brew install cmake ninja
|
||||
brew install boost
|
||||
if [ "${{ matrix.compiler }}" = "gcc" ]; then
|
||||
brew install gcc@${{ matrix.version }}
|
||||
echo "::set-env name=CC::gcc-${{ matrix.version }}"
|
||||
echo "::set-env name=CXX::g++-${{ matrix.version }}"
|
||||
echo "CC=gcc-${{ matrix.version }}" >> $GITHUB_ENV
|
||||
echo "CXX=g++-${{ matrix.version }}" >> $GITHUB_ENV
|
||||
else
|
||||
sudo xcode-select -switch /Applications/Xcode_${{ matrix.version }}.app
|
||||
echo "::set-env name=CC::clang"
|
||||
echo "::set-env name=CXX::clang++"
|
||||
echo "CC=clang" >> $GITHUB_ENV
|
||||
echo "CXX=clang++" >> $GITHUB_ENV
|
||||
fi
|
||||
- name: Set GTSAM_WITH_TBB Flag
|
||||
if: matrix.flag == 'tbb'
|
||||
run: |
|
||||
echo "::set-env name=GTSAM_WITH_TBB::ON"
|
||||
echo "GTSAM_WITH_TBB=ON" >> $GITHUB_ENV
|
||||
echo "GTSAM Uses TBB"
|
||||
- name: Build (Linux)
|
||||
if: runner.os == 'Linux'
|
||||
|
|
@ -105,4 +119,4 @@ jobs:
|
|||
- name: Build (macOS)
|
||||
if: runner.os == 'macOS'
|
||||
run: |
|
||||
bash .github/scripts/python.sh
|
||||
bash .github/scripts/python.sh
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ jobs:
|
|||
CTEST_PARALLEL_LEVEL: 2
|
||||
CMAKE_BUILD_TYPE: ${{ matrix.build_type }}
|
||||
GTSAM_BUILD_UNSTABLE: ON
|
||||
BOOST_VERSION: 1.67.0
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
|
|
@ -24,6 +25,7 @@ jobs:
|
|||
ubuntu-gcc-deprecated,
|
||||
ubuntu-gcc-quaternions,
|
||||
ubuntu-gcc-tbb,
|
||||
ubuntu-cayleymap,
|
||||
]
|
||||
|
||||
build_type: [Debug, Release]
|
||||
|
|
@ -47,66 +49,95 @@ jobs:
|
|||
version: "9"
|
||||
flag: tbb
|
||||
|
||||
- name: ubuntu-cayleymap
|
||||
os: ubuntu-18.04
|
||||
compiler: gcc
|
||||
version: "9"
|
||||
flag: cayley
|
||||
|
||||
- name: ubuntu-system-libs
|
||||
os: ubuntu-18.04
|
||||
compiler: gcc
|
||||
version: "9"
|
||||
flag: system-libs
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@master
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Install (Linux)
|
||||
if: runner.os == 'Linux'
|
||||
run: |
|
||||
# LLVM 9 is not in Bionic's repositories so we add the official LLVM repository.
|
||||
if [ "${{ matrix.compiler }}" = "clang" ] && [ "${{ matrix.version }}" = "9" ]; then
|
||||
gpg --keyserver keyserver.ubuntu.com --recv-key $LLVM_KEY || gpg --keyserver hkp://keyserver.ubuntu.com:80 --recv-key $LLVM_KEY
|
||||
gpg -a --export 15CF4D18AF4F7421 | sudo apt-key add -
|
||||
sudo add-apt-repository "deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-9 main"
|
||||
fi
|
||||
sudo apt-get -y update
|
||||
|
||||
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 "::set-env name=LD_LIBRARY_PATH::$(echo $BOOST_ROOT_1_69_0/lib)"
|
||||
sudo apt-get -y install cmake build-essential pkg-config libpython-dev python-numpy libicu-dev
|
||||
|
||||
if [ "${{ matrix.compiler }}" = "gcc" ]; then
|
||||
sudo apt-get install -y g++-${{ matrix.version }} g++-${{ matrix.version }}-multilib
|
||||
echo "::set-env name=CC::gcc-${{ matrix.version }}"
|
||||
echo "::set-env name=CXX::g++-${{ matrix.version }}"
|
||||
echo "CC=gcc-${{ matrix.version }}" >> $GITHUB_ENV
|
||||
echo "CXX=g++-${{ matrix.version }}" >> $GITHUB_ENV
|
||||
else
|
||||
sudo apt-get install -y clang-${{ matrix.version }} g++-multilib
|
||||
echo "::set-env name=CC::clang-${{ matrix.version }}"
|
||||
echo "::set-env name=CXX::clang++-${{ matrix.version }}"
|
||||
echo "CC=clang-${{ matrix.version }}" >> $GITHUB_ENV
|
||||
echo "CXX=clang++-${{ matrix.version }}" >> $GITHUB_ENV
|
||||
fi
|
||||
|
||||
- name: Install Boost
|
||||
if: runner.os == 'Linux'
|
||||
run: |
|
||||
bash .github/scripts/boost.sh
|
||||
|
||||
- name: Install (macOS)
|
||||
if: runner.os == 'macOS'
|
||||
run: |
|
||||
brew install cmake ninja boost
|
||||
if [ "${{ matrix.compiler }}" = "gcc" ]; then
|
||||
brew install gcc@${{ matrix.version }}
|
||||
echo "::set-env name=CC::gcc-${{ matrix.version }}"
|
||||
echo "::set-env name=CXX::g++-${{ matrix.version }}"
|
||||
echo "CC=gcc-${{ matrix.version }}" >> $GITHUB_ENV
|
||||
echo "CXX=g++-${{ matrix.version }}" >> $GITHUB_ENV
|
||||
else
|
||||
sudo xcode-select -switch /Applications/Xcode_${{ matrix.version }}.app
|
||||
echo "::set-env name=CC::clang"
|
||||
echo "::set-env name=CXX::clang++"
|
||||
echo "CC=clang" >> $GITHUB_ENV
|
||||
echo "CXX=clang++" >> $GITHUB_ENV
|
||||
fi
|
||||
|
||||
- name: Set Allow Deprecated Flag
|
||||
if: matrix.flag == 'deprecated'
|
||||
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"
|
||||
|
||||
- name: Set Use Quaternions Flag
|
||||
if: matrix.flag == 'quaternions'
|
||||
run: |
|
||||
echo "::set-env name=GTSAM_USE_QUATERNIONS::ON"
|
||||
echo "GTSAM_USE_QUATERNIONS=ON" >> $GITHUB_ENV
|
||||
echo "Use Quaternions for rotations"
|
||||
|
||||
- name: Set GTSAM_WITH_TBB Flag
|
||||
if: matrix.flag == 'tbb'
|
||||
run: |
|
||||
echo "::set-env name=GTSAM_WITH_TBB::ON"
|
||||
echo "GTSAM_WITH_TBB=ON" >> $GITHUB_ENV
|
||||
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: Use system versions of 3rd party libraries
|
||||
if: matrix.flag == 'system'
|
||||
run: |
|
||||
echo "GTSAM_USE_SYSTEM_EIGEN=ON" >> $GITHUB_ENV
|
||||
echo "GTSAM_USE_SYSTEM_METIS=ON" >> $GITHUB_ENV
|
||||
|
||||
- name: Build & Test
|
||||
run: |
|
||||
bash .github/scripts/unix.sh -t
|
||||
|
|
|
|||
|
|
@ -12,64 +12,91 @@ jobs:
|
|||
CTEST_PARALLEL_LEVEL: 2
|
||||
CMAKE_BUILD_TYPE: ${{ matrix.build_type }}
|
||||
GTSAM_BUILD_UNSTABLE: ${{ matrix.build_unstable }}
|
||||
BOOST_VERSION: 1.72.0
|
||||
BOOST_EXE: boost_1_72_0-msvc-14.2
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
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.
|
||||
name: [
|
||||
windows-2016-cl,
|
||||
windows-2019-cl,
|
||||
]
|
||||
#TODO This build fails, need to understand why.
|
||||
# windows-2016-cl,
|
||||
windows-2019-cl,
|
||||
]
|
||||
|
||||
build_type: [Debug, Release]
|
||||
build_unstable: [ON]
|
||||
include:
|
||||
- name: windows-2016-cl
|
||||
os: windows-2016
|
||||
compiler: cl
|
||||
#TODO This build fails, need to understand why.
|
||||
# - name: windows-2016-cl
|
||||
# os: windows-2016
|
||||
# compiler: cl
|
||||
# platform: 32
|
||||
|
||||
- name: windows-2019-cl
|
||||
os: windows-2019
|
||||
compiler: cl
|
||||
platform: 64
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@master
|
||||
- name: Install (Windows)
|
||||
if: runner.os == 'Windows'
|
||||
- name: Install Dependencies
|
||||
shell: powershell
|
||||
run: |
|
||||
Invoke-Expression (New-Object System.Net.WebClient).DownloadString('https://get.scoop.sh')
|
||||
scoop install cmake --global # So we don't get issues with CMP0074 policy
|
||||
scoop install ninja --global
|
||||
|
||||
if ("${{ matrix.compiler }}".StartsWith("clang")) {
|
||||
scoop install llvm --global
|
||||
}
|
||||
|
||||
if ("${{ matrix.compiler }}" -eq "gcc") {
|
||||
# Chocolatey GCC is broken on the windows-2019 image.
|
||||
# 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
|
||||
scoop install gcc --global
|
||||
echo "::set-env name=CC::gcc"
|
||||
echo "::set-env name=CXX::g++"
|
||||
echo "CC=gcc" >> $GITHUB_ENV
|
||||
echo "CXX=g++" >> $GITHUB_ENV
|
||||
|
||||
} elseif ("${{ matrix.compiler }}" -eq "clang") {
|
||||
echo "::set-env name=CC::clang"
|
||||
echo "::set-env name=CXX::clang++"
|
||||
echo "CC=clang" >> $GITHUB_ENV
|
||||
echo "CXX=clang++" >> $GITHUB_ENV
|
||||
|
||||
} else {
|
||||
echo "::set-env name=CC::${{ matrix.compiler }}"
|
||||
echo "::set-env name=CXX::${{ matrix.compiler }}"
|
||||
echo "CC=${{ matrix.compiler }}" >> $env:GITHUB_ENV
|
||||
echo "CXX=${{ matrix.compiler }}" >> $env:GITHUB_ENV
|
||||
|
||||
}
|
||||
|
||||
# Scoop modifies the PATH so we make the modified PATH global.
|
||||
echo "::set-env name=PATH::$env:PATH"
|
||||
- name: Build (Windows)
|
||||
if: runner.os == 'Windows'
|
||||
echo "$env:PATH" >> $env:GITHUB_PATH
|
||||
|
||||
- name: Install Boost
|
||||
shell: powershell
|
||||
run: |
|
||||
# Snippet from: https://github.com/actions/virtual-environments/issues/2667
|
||||
$BOOST_PATH = "C:\hostedtoolcache\windows\Boost\$env:BOOST_VERSION\x86_64"
|
||||
|
||||
# Use the prebuilt binary for Windows
|
||||
$Url = "https://sourceforge.net/projects/boost/files/boost-binaries/$env:BOOST_VERSION/$env:BOOST_EXE-${{matrix.platform}}.exe"
|
||||
(New-Object System.Net.WebClient).DownloadFile($Url, "$env:TEMP\boost.exe")
|
||||
Start-Process -Wait -FilePath "$env:TEMP\boost.exe" "/SILENT","/SP-","/SUPPRESSMSGBOXES","/DIR=$BOOST_PATH"
|
||||
|
||||
# Set the BOOST_ROOT variable
|
||||
echo "BOOST_ROOT=$BOOST_PATH" >> $env:GITHUB_ENV
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
cmake -E remove_directory build
|
||||
echo "BOOST_ROOT_1_72_0: ${env:BOOST_ROOT_1_72_0}"
|
||||
cmake -B build -S . -DGTSAM_BUILD_EXAMPLES_ALWAYS=OFF -DBOOST_ROOT="${env:BOOST_ROOT_1_72_0}" -DBOOST_INCLUDEDIR="${env:BOOST_ROOT_1_72_0}\boost\include" -DBOOST_LIBRARYDIR="${env:BOOST_ROOT_1_72_0}\lib"
|
||||
cmake -B build -S . -DGTSAM_BUILD_EXAMPLES_ALWAYS=OFF -DBOOST_ROOT="${env:BOOST_ROOT}" -DBOOST_INCLUDEDIR="${env:BOOST_ROOT}\boost\include" -DBOOST_LIBRARYDIR="${env:BOOST_ROOT}\lib"
|
||||
cmake --build build --config ${{ matrix.build_type }} --target gtsam
|
||||
cmake --build build --config ${{ matrix.build_type }} --target gtsam_unstable
|
||||
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_unstable
|
||||
cmake --build build --config ${{ matrix.build_type }} --target check.linear
|
||||
cmake --build build --config ${{ matrix.build_type }} --target check.linear
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
# This triggers Cython builds on `gtsam-manylinux-build`
|
||||
# This triggers Python builds on `gtsam-manylinux-build`
|
||||
name: Trigger Python Builds
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- develop
|
||||
jobs:
|
||||
triggerCython:
|
||||
triggerPython:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Repository Dispatch
|
||||
|
|
@ -13,5 +13,5 @@ jobs:
|
|||
with:
|
||||
token: ${{ secrets.PYTHON_CI_REPO_ACCESS_TOKEN }}
|
||||
repository: borglab/gtsam-manylinux-build
|
||||
event-type: cython-wrapper
|
||||
event-type: python-wrapper
|
||||
client-payload: '{"ref": "${{ github.ref }}", "sha": "${{ github.sha }}"}'
|
||||
|
|
|
|||
|
|
@ -3,18 +3,13 @@
|
|||
.idea
|
||||
*.pyc
|
||||
*.DS_Store
|
||||
*.swp
|
||||
/examples/Data/dubrovnik-3-7-pre-rewritten.txt
|
||||
/examples/Data/pose2example-rewritten.txt
|
||||
/examples/Data/pose3example-rewritten.txt
|
||||
*.txt.user
|
||||
*.txt.user.6d59f0c
|
||||
*.pydevproject
|
||||
cython/venv
|
||||
cython/gtsam.cpp
|
||||
cython/gtsam.cpython-35m-darwin.so
|
||||
cython/gtsam.pyx
|
||||
cython/gtsam.so
|
||||
cython/gtsam_wrapper.pxd
|
||||
.vscode
|
||||
.env
|
||||
/.vs/
|
||||
|
|
|
|||
572
CMakeLists.txt
572
CMakeLists.txt
|
|
@ -10,24 +10,22 @@ endif()
|
|||
# Set the version number for the library
|
||||
set (GTSAM_VERSION_MAJOR 4)
|
||||
set (GTSAM_VERSION_MINOR 1)
|
||||
set (GTSAM_VERSION_PATCH 0)
|
||||
set (GTSAM_VERSION_PATCH 1)
|
||||
math (EXPR GTSAM_VERSION_NUMERIC "10000 * ${GTSAM_VERSION_MAJOR} + 100 * ${GTSAM_VERSION_MINOR} + ${GTSAM_VERSION_PATCH}")
|
||||
set (GTSAM_VERSION_STRING "${GTSAM_VERSION_MAJOR}.${GTSAM_VERSION_MINOR}.${GTSAM_VERSION_PATCH}")
|
||||
|
||||
set (CMAKE_PROJECT_VERSION ${GTSAM_VERSION_STRING})
|
||||
set (CMAKE_PROJECT_VERSION_MAJOR ${GTSAM_VERSION_MAJOR})
|
||||
set (CMAKE_PROJECT_VERSION_MINOR ${GTSAM_VERSION_MINOR})
|
||||
set (CMAKE_PROJECT_VERSION_PATCH ${GTSAM_VERSION_PATCH})
|
||||
|
||||
###############################################################################
|
||||
# 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")
|
||||
include(GtsamMakeConfigFile)
|
||||
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
|
||||
include(GtsamBuildTypes)
|
||||
|
||||
|
|
@ -36,387 +34,28 @@ include(GtsamTesting)
|
|||
include(GtsamPrinting)
|
||||
|
||||
# guard against in-source builds
|
||||
if(${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_BINARY_DIR})
|
||||
if(${GTSAM_SOURCE_DIR} STREQUAL ${GTSAM_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. ")
|
||||
endif()
|
||||
|
||||
# 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()
|
||||
include(cmake/HandleGeneralOptions.cmake) # CMake build options
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# 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)
|
||||
# Libraries:
|
||||
include(cmake/HandleBoost.cmake) # Boost
|
||||
include(cmake/HandleCCache.cmake) # ccache
|
||||
include(cmake/HandleCPack.cmake) # CPack
|
||||
include(cmake/HandleEigen.cmake) # Eigen3
|
||||
include(cmake/HandleMetis.cmake) # metis
|
||||
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"
|
||||
|
||||
add_custom_target(uninstall
|
||||
"${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake")
|
||||
include(cmake/HandleAllocators.cmake) # Must be after tbb, pertools
|
||||
|
||||
|
||||
###############################################################################
|
||||
# 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_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.43)
|
||||
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.43, 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()
|
||||
include(cmake/HandleGlobalBuildFlags.cmake) # Build flags
|
||||
|
||||
###############################################################################
|
||||
# Add components
|
||||
|
|
@ -424,12 +63,6 @@ endif()
|
|||
# Build CppUnitLite
|
||||
add_subdirectory(CppUnitLite)
|
||||
|
||||
# This is the new wrapper
|
||||
if(GTSAM_BUILD_PYTHON)
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/wrap/cmake")
|
||||
add_subdirectory(python)
|
||||
endif()
|
||||
|
||||
# Build GTSAM library
|
||||
add_subdirectory(gtsam)
|
||||
|
||||
|
|
@ -447,8 +80,24 @@ if (GTSAM_BUILD_UNSTABLE)
|
|||
add_subdirectory(gtsam_unstable)
|
||||
endif()
|
||||
|
||||
# This is the new wrapper
|
||||
if(GTSAM_BUILD_PYTHON OR GTSAM_INSTALL_MATLAB_TOOLBOX)
|
||||
# Need to set this for the wrap package so we don't use the default value.
|
||||
set(WRAP_PYTHON_VERSION ${GTSAM_PYTHON_VERSION}
|
||||
CACHE STRING "The Python version to use for wrapping")
|
||||
# Set the include directory for matlab.h
|
||||
set(GTWRAP_INCLUDE_NAME "wrap")
|
||||
add_subdirectory(wrap)
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/wrap/cmake")
|
||||
endif()
|
||||
|
||||
# Python toolbox
|
||||
if(GTSAM_BUILD_PYTHON)
|
||||
add_subdirectory(python)
|
||||
endif()
|
||||
|
||||
# Matlab toolbox
|
||||
if (GTSAM_INSTALL_MATLAB_TOOLBOX)
|
||||
if(GTSAM_INSTALL_MATLAB_TOOLBOX)
|
||||
add_subdirectory(matlab)
|
||||
endif()
|
||||
|
||||
|
|
@ -456,6 +105,10 @@ endif()
|
|||
GtsamMakeConfigFile(GTSAM "${CMAKE_CURRENT_SOURCE_DIR}/gtsam_extra.cmake.in")
|
||||
export(TARGETS ${GTSAM_EXPORTED_TARGETS} FILE GTSAM-exports.cmake)
|
||||
|
||||
if (GTSAM_BUILD_UNSTABLE)
|
||||
GtsamMakeConfigFile(GTSAM_UNSTABLE "${CMAKE_CURRENT_SOURCE_DIR}/gtsam_extra.cmake.in")
|
||||
export(TARGETS ${GTSAM_UNSTABLE_EXPORTED_TARGETS} FILE GTSAM_UNSTABLE-exports.cmake)
|
||||
endif()
|
||||
|
||||
# Check for doxygen availability - optional dependency
|
||||
find_package(Doxygen)
|
||||
|
|
@ -468,146 +121,11 @@ endif()
|
|||
# CMake Tools
|
||||
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.43)") #Example: "libc6 (>= 2.3.1-6), libgcc1 (>= 1:3.4.2-12)")
|
||||
|
||||
|
||||
###############################################################################
|
||||
# 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")
|
||||
elseif(TBB_FOUND)
|
||||
print_config("Use Intel TBB" "TBB 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 "===============================================================")
|
||||
include(cmake/HandlePrintConfiguration.cmake)
|
||||
|
||||
# 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()
|
||||
include(cmake/HandleFinalChecks.cmake)
|
||||
|
||||
# Include CPack *after* all flags
|
||||
include(CPack)
|
||||
|
|
|
|||
|
|
@ -17,3 +17,5 @@ class GTSAM_EXPORT MyClass { ... };
|
|||
|
||||
GTSAM_EXPORT myFunction();
|
||||
```
|
||||
|
||||
More details [here](Using-GTSAM-EXPORT.md).
|
||||
|
|
|
|||
61
INSTALL.md
61
INSTALL.md
|
|
@ -13,16 +13,18 @@ $ make install
|
|||
## Important Installation Notes
|
||||
|
||||
1. GTSAM requires the following libraries to be installed on your system:
|
||||
- BOOST version 1.43 or greater (install through Linux repositories or MacPorts)
|
||||
- BOOST version 1.65 or greater (install through Linux repositories or MacPorts). Please see [Boost Notes](#boost-notes).
|
||||
|
||||
- Cmake version 3.0 or higher
|
||||
- Support for XCode 4.3 command line tools on Mac requires CMake 2.8.8 or higher
|
||||
|
||||
Optional dependent libraries:
|
||||
- If TBB is installed and detectable by CMake GTSAM will use it automatically.
|
||||
Ensure that CMake prints "Use Intel TBB : Yes". To disable the use of TBB,
|
||||
disable the CMake flag GTSAM_WITH_TBB (enabled by default). On Ubuntu, TBB
|
||||
may be installed from the Ubuntu repositories, and for other platforms it
|
||||
may be downloaded from https://www.threadingbuildingblocks.org/
|
||||
disable the CMake flag `GTSAM_WITH_TBB` (enabled by default) by providing
|
||||
the argument `-DGTSAM_WITH_TBB=OFF` to `cmake`. On Ubuntu, TBB may be
|
||||
installed from the Ubuntu repositories, and for other platforms it may be
|
||||
downloaded from https://www.threadingbuildingblocks.org/
|
||||
- GTSAM may be configured to use MKL by toggling `GTSAM_WITH_EIGEN_MKL` and
|
||||
`GTSAM_WITH_EIGEN_MKL_OPENMP` to `ON`; however, best performance is usually
|
||||
achieved with MKL disabled. We therefore advise you to benchmark your problem
|
||||
|
|
@ -41,11 +43,6 @@ $ make install
|
|||
- MacOS 10.6 - 10.14
|
||||
- Windows 7, 8, 8.1, 10
|
||||
|
||||
Known issues:
|
||||
|
||||
- MSVC 2013 is not yet supported because it cannot build the serialization module
|
||||
of Boost 1.55 (or earlier).
|
||||
|
||||
2. GTSAM makes extensive use of debug assertions, and we highly recommend you work
|
||||
in Debug mode while developing (enabled by default). Likewise, it is imperative
|
||||
that you switch to release mode when running finished code and for timing. GTSAM
|
||||
|
|
@ -70,7 +67,45 @@ execute commands as follows for an out-of-source build:
|
|||
This will build the library and unit tests, run all of the unit tests,
|
||||
and then install the library itself.
|
||||
|
||||
## CMake Configuration Options and Details
|
||||
## Boost Notes
|
||||
|
||||
Versions of Boost prior to 1.65 have a known bug that prevents proper "deep" serialization of objects, which means that objects encapsulated inside other objects don't get serialized.
|
||||
This is particularly seen when using `clang` as the C++ compiler.
|
||||
|
||||
For this reason we require Boost>=1.65, and recommend installing it through alternative channels when it is not available through your operating system's primary package manager.
|
||||
|
||||
## Known Issues
|
||||
|
||||
- MSVC 2013 is not yet supported because it cannot build the serialization module of Boost 1.55 (or earlier).
|
||||
|
||||
# Windows Installation
|
||||
|
||||
This section details how to build a GTSAM `.sln` file using Visual Studio.
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- Visual Studio with C++ CMake tools for Windows
|
||||
- All the other pre-requisites listed above.
|
||||
|
||||
### Steps
|
||||
|
||||
1. Open Visual Studio.
|
||||
2. Select `Open a local folder` and select the GTSAM source directory.
|
||||
3. Go to `Project -> CMake Settings`.
|
||||
- (Optional) Set `Configuration name`.
|
||||
- (Optional) Set `Configuration type`.
|
||||
- Set the `Toolset` to `msvc_x64_x64`. If you know what toolset you require, then skip this step.
|
||||
- Update the `Build root` to `${projectDir}\build\${name}`.
|
||||
- You can optionally create a new configuration for a `Release` build.
|
||||
- Set the necessary CMake variables for your use case.
|
||||
- Click on `Show advanced settings`.
|
||||
- For `CMake generator`, select a version which matches `Visual Studio <Version> <Year> Win64`, e.g. `Visual Studio 16 2019 Win64`.
|
||||
- Save the settings (Ctrl + S).
|
||||
4. Click on `Project -> Generate Cache`. This will generate the CMake build files (as seen in the Output window).
|
||||
5. The last step will generate a `GTSAM.sln` file in the `build` directory. At this point, GTSAM can be used as a regular Visual Studio project.
|
||||
|
||||
|
||||
# CMake Configuration Options and Details
|
||||
|
||||
GTSAM has a number of options that can be configured, which is best done with
|
||||
one of the following:
|
||||
|
|
@ -78,7 +113,7 @@ one of the following:
|
|||
- ccmake the curses GUI for cmake
|
||||
- cmake-gui a real GUI for cmake
|
||||
|
||||
### Important Options:
|
||||
## Important Options:
|
||||
|
||||
#### CMAKE_BUILD_TYPE
|
||||
We support several build configurations for GTSAM (case insensitive)
|
||||
|
|
@ -173,7 +208,7 @@ NOTE: If _GLIBCXX_DEBUG is used to compile gtsam, anything that links against g
|
|||
Intel has a guide for installing MKL on Linux through APT repositories at <https://software.intel.com/en-us/articles/installing-intel-free-libs-and-python-apt-repo>.
|
||||
|
||||
After following the instructions, add the following to your `~/.bashrc` (and afterwards, open a new terminal before compiling GTSAM):
|
||||
`LD_PRELOAD` need only be set if you are building the cython wrapper to use GTSAM from python.
|
||||
`LD_PRELOAD` need only be set if you are building the python wrapper to use GTSAM from python.
|
||||
```sh
|
||||
source /opt/intel/mkl/bin/mklvars.sh intel64
|
||||
export LD_PRELOAD="$LD_PRELOAD:/opt/intel/mkl/lib/intel64/libmkl_core.so:/opt/intel/mkl/lib/intel64/libmkl_sequential.so"
|
||||
|
|
@ -190,6 +225,6 @@ Failing to specify `LD_PRELOAD` may lead to errors such as:
|
|||
`ImportError: /opt/intel/mkl/lib/intel64/libmkl_vml_avx2.so: undefined symbol: mkl_serv_getenv`
|
||||
or
|
||||
`Intel MKL FATAL ERROR: Cannot load libmkl_avx2.so or libmkl_def.so.`
|
||||
when importing GTSAM using the cython wrapper in python.
|
||||
when importing GTSAM using the python wrapper.
|
||||
|
||||
|
||||
|
|
|
|||
14
README.md
14
README.md
|
|
@ -40,7 +40,7 @@ $ make install
|
|||
|
||||
Prerequisites:
|
||||
|
||||
- [Boost](http://www.boost.org/users/download/) >= 1.43 (Ubuntu: `sudo apt-get install libboost-all-dev`)
|
||||
- [Boost](http://www.boost.org/users/download/) >= 1.65 (Ubuntu: `sudo apt-get install libboost-all-dev`)
|
||||
- [CMake](http://www.cmake.org/cmake/resources/software.html) >= 3.0 (Ubuntu: `sudo apt-get install cmake`)
|
||||
- A modern compiler, i.e., at least gcc 4.7.3 on Linux.
|
||||
|
||||
|
|
@ -55,29 +55,29 @@ Optional prerequisites - used automatically if findable by CMake:
|
|||
|
||||
GTSAM 4 introduces several new features, most notably Expressions and a Python toolbox. It also introduces traits, a C++ technique that allows optimizing with non-GTSAM types. That opens the door to retiring geometric types such as Point2 and Point3 to pure Eigen types, which we also do. A significant change which will not trigger a compile error is that zero-initializing of Point2 and Point3 is deprecated, so please be aware that this might render functions using their default constructor incorrect.
|
||||
|
||||
GTSAM 4 also deprecated some legacy functionality and wrongly named methods. If you are on a 4.0.X release, you can define the flag GTSAM_ALLOW_DEPRECATED_SINCE_V4 to use the deprecated methods.
|
||||
GTSAM 4 also deprecated some legacy functionality and wrongly named methods. If you are on a 4.0.X release, you can define the flag `GTSAM_ALLOW_DEPRECATED_SINCE_V4` to use the deprecated methods.
|
||||
|
||||
GTSAM 4.1 added a new pybind wrapper, and **removed** the deprecated functionality. There is a flag GTSAM_ALLOW_DEPRECATED_SINCE_V41 for newly deprecated methods since the 4.1 release, which is on by default, allowing anyone to just pull version 4.1 and compile.
|
||||
GTSAM 4.1 added a new pybind wrapper, and **removed** the deprecated functionality. There is a flag `GTSAM_ALLOW_DEPRECATED_SINCE_V41` for newly deprecated methods since the 4.1 release, which is on by default, allowing anyone to just pull version 4.1 and compile.
|
||||
|
||||
|
||||
## Wrappers
|
||||
|
||||
We provide support for [MATLAB](matlab/README.md) and [Python](cython/README.md) wrappers for GTSAM. Please refer to the linked documents for more details.
|
||||
We provide support for [MATLAB](matlab/README.md) and [Python](python/README.md) wrappers for GTSAM. Please refer to the linked documents for more details.
|
||||
|
||||
## The Preintegrated IMU Factor
|
||||
|
||||
GTSAM includes a state of the art IMU handling scheme based on
|
||||
|
||||
- Todd Lupton and Salah Sukkarieh, "Visual-Inertial-Aided Navigation for High-Dynamic Motion in Built Environments Without Initial Conditions", TRO, 28(1):61-76, 2012. [[link]](https://ieeexplore.ieee.org/document/6092505)
|
||||
- Todd Lupton and Salah Sukkarieh, _"Visual-Inertial-Aided Navigation for High-Dynamic Motion in Built Environments Without Initial Conditions"_, TRO, 28(1):61-76, 2012. [[link]](https://ieeexplore.ieee.org/document/6092505)
|
||||
|
||||
Our implementation improves on this using integration on the manifold, as detailed in
|
||||
|
||||
- Luca Carlone, Zsolt Kira, Chris Beall, Vadim Indelman, and Frank Dellaert, "Eliminating conditionally independent sets in factor graphs: a unifying perspective based on smart factors", Int. Conf. on Robotics and Automation (ICRA), 2014. [[link]](https://ieeexplore.ieee.org/abstract/document/6907483)
|
||||
- Luca Carlone, Zsolt Kira, Chris Beall, Vadim Indelman, and Frank Dellaert, _"Eliminating conditionally independent sets in factor graphs: a unifying perspective based on smart factors"_, Int. Conf. on Robotics and Automation (ICRA), 2014. [[link]](https://ieeexplore.ieee.org/abstract/document/6907483)
|
||||
- Christian Forster, Luca Carlone, Frank Dellaert, and Davide Scaramuzza, "IMU Preintegration on Manifold for Efficient Visual-Inertial Maximum-a-Posteriori Estimation", Robotics: Science and Systems (RSS), 2015. [[link]](http://www.roboticsproceedings.org/rss11/p06.pdf)
|
||||
|
||||
If you are using the factor in academic work, please cite the publications above.
|
||||
|
||||
In GTSAM 4 a new and more efficient implementation, based on integrating on the NavState tangent space and detailed in [this document](doc/ImuFactor.pdf), is enabled by default. To switch to the RSS 2015 version, set the flag **GTSAM_TANGENT_PREINTEGRATION** to OFF.
|
||||
In GTSAM 4 a new and more efficient implementation, based on integrating on the NavState tangent space and detailed in [this document](doc/ImuFactor.pdf), is enabled by default. To switch to the RSS 2015 version, set the flag `GTSAM_TANGENT_PREINTEGRATION` to OFF.
|
||||
|
||||
|
||||
## Additional Information
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ To create a DLL in windows, the `GTSAM_EXPORT` keyword has been created and need
|
|||
3. If you have defined a class using `GTSAM_EXPORT`, do not use `GTSAM_EXPORT` in any of its individual function declarations. (Note that you _can_ put `GTSAM_EXPORT` in the definition of individual functions within a class as long as you don't put `GTSAM_EXPORT` in the class definition.)
|
||||
|
||||
## When is GTSAM_EXPORT being used incorrectly
|
||||
Unfortunately, using `GTSAM_EXPORT` incorrectly often does not cause a compiler or linker error in the library that is being compiled, but only when you try to use that DLL in a different library. For example, an error in gtsam/base will often show up when compiling the check_base_program or the MATLAB wrapper, but not when compiling/linking gtsam itself. The most common errors will say something like:
|
||||
Unfortunately, using `GTSAM_EXPORT` incorrectly often does not cause a compiler or linker error in the library that is being compiled, but only when you try to use that DLL in a different library. For example, an error in `gtsam/base` will often show up when compiling the `check_base_program` or the MATLAB wrapper, but not when compiling/linking gtsam itself. The most common errors will say something like:
|
||||
|
||||
```
|
||||
Error LNK2019 unresolved external symbol "public: void __cdecl gtsam::SO3::print(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &)const " (?print@SO3@gtsam@@QEBAXAEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z) referenced in function "public: static void __cdecl gtsam::Testable<class gtsam::SO3>::Print(class gtsam::SO3 const &,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &)" (?Print@?$Testable@VSO3@gtsam@@@gtsam@@SAXAEBVSO3@2@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z) check_geometry_program C:\AFIT\lib\gtsam\build\gtsam\geometry\tests\testSO3.obj
|
||||
|
|
|
|||
|
|
@ -16,12 +16,8 @@ install(FILES
|
|||
dllexport.h.in
|
||||
GtsamBuildTypes.cmake
|
||||
GtsamMakeConfigFile.cmake
|
||||
GtsamMatlabWrap.cmake
|
||||
GtsamTesting.cmake
|
||||
GtsamPrinting.cmake
|
||||
FindCython.cmake
|
||||
FindNumPy.cmake
|
||||
README.html
|
||||
DESTINATION "${SCRIPT_INSTALL_DIR}/GTSAMCMakeTools")
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
get_filename_component(OUR_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
|
||||
if(EXISTS "${OUR_CMAKE_DIR}/CMakeCache.txt")
|
||||
# In build tree
|
||||
set(@PACKAGE_NAME@_INCLUDE_DIR @CMAKE_SOURCE_DIR@ CACHE PATH "@PACKAGE_NAME@ include directory")
|
||||
set(@PACKAGE_NAME@_INCLUDE_DIR @GTSAM_SOURCE_DIR@ CACHE PATH "@PACKAGE_NAME@ include directory")
|
||||
else()
|
||||
# Find installed library
|
||||
set(@PACKAGE_NAME@_INCLUDE_DIR "${OUR_CMAKE_DIR}/@CONF_REL_INCLUDE_DIR@" CACHE PATH "@PACKAGE_NAME@ include directory")
|
||||
|
|
@ -15,7 +15,7 @@ endif()
|
|||
# Find dependencies, required by cmake exported targets:
|
||||
include(CMakeFindDependencyMacro)
|
||||
# Allow using cmake < 3.8
|
||||
if(${CMAKE_VERSION} VERSION_LESS "3.8.0")
|
||||
if(${CMAKE_VERSION} VERSION_LESS "3.8.0")
|
||||
find_package(Boost @BOOST_FIND_MINIMUM_VERSION@ COMPONENTS @BOOST_FIND_MINIMUM_COMPONENTS@)
|
||||
else()
|
||||
find_dependency(Boost @BOOST_FIND_MINIMUM_VERSION@ COMPONENTS @BOOST_FIND_MINIMUM_COMPONENTS@)
|
||||
|
|
|
|||
|
|
@ -1,81 +0,0 @@
|
|||
# Modifed from: https://github.com/nest/nest-simulator/blob/master/cmake/FindCython.cmake
|
||||
#
|
||||
# Find the Cython compiler.
|
||||
#
|
||||
# This code sets the following variables:
|
||||
#
|
||||
# CYTHON_FOUND
|
||||
# CYTHON_PATH
|
||||
# CYTHON_EXECUTABLE
|
||||
# CYTHON_VERSION
|
||||
#
|
||||
# See also UseCython.cmake
|
||||
|
||||
#=============================================================================
|
||||
# Copyright 2011 Kitware, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#=============================================================================
|
||||
|
||||
# Use the Cython executable that lives next to the Python executable
|
||||
# if it is a local installation.
|
||||
if(GTSAM_PYTHON_VERSION STREQUAL "Default")
|
||||
find_package(PythonInterp)
|
||||
else()
|
||||
find_package(PythonInterp ${GTSAM_PYTHON_VERSION} EXACT)
|
||||
endif()
|
||||
|
||||
if ( PYTHONINTERP_FOUND )
|
||||
execute_process( COMMAND "${PYTHON_EXECUTABLE}" "-c"
|
||||
"import Cython; print(Cython.__path__[0])"
|
||||
RESULT_VARIABLE RESULT
|
||||
OUTPUT_VARIABLE CYTHON_PATH
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
endif ()
|
||||
|
||||
# RESULT=0 means ok
|
||||
if ( NOT RESULT )
|
||||
get_filename_component( _python_path ${PYTHON_EXECUTABLE} PATH )
|
||||
find_program( CYTHON_EXECUTABLE
|
||||
NAMES cython cython.bat cython3
|
||||
HINTS ${_python_path}
|
||||
)
|
||||
endif ()
|
||||
|
||||
# RESULT=0 means ok
|
||||
if ( NOT RESULT )
|
||||
execute_process( COMMAND "${PYTHON_EXECUTABLE}" "-c"
|
||||
"import Cython; print(Cython.__version__)"
|
||||
RESULT_VARIABLE RESULT
|
||||
OUTPUT_VARIABLE CYTHON_VAR_OUTPUT
|
||||
ERROR_VARIABLE CYTHON_VAR_OUTPUT
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
if ( RESULT EQUAL 0 )
|
||||
string( REGEX REPLACE ".* ([0-9]+\\.[0-9]+(\\.[0-9]+)?).*" "\\1"
|
||||
CYTHON_VERSION "${CYTHON_VAR_OUTPUT}" )
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
include( FindPackageHandleStandardArgs )
|
||||
find_package_handle_standard_args( Cython
|
||||
FOUND_VAR
|
||||
CYTHON_FOUND
|
||||
REQUIRED_VARS
|
||||
CYTHON_PATH
|
||||
CYTHON_EXECUTABLE
|
||||
VERSION_VAR
|
||||
CYTHON_VERSION
|
||||
)
|
||||
|
||||
|
|
@ -40,17 +40,9 @@
|
|||
|
||||
# Finding NumPy involves calling the Python interpreter
|
||||
if(NumPy_FIND_REQUIRED)
|
||||
if(GTSAM_PYTHON_VERSION STREQUAL "Default")
|
||||
find_package(PythonInterp REQUIRED)
|
||||
else()
|
||||
find_package(PythonInterp ${GTSAM_PYTHON_VERSION} EXACT REQUIRED)
|
||||
endif()
|
||||
find_package(PythonInterp ${GTSAM_PYTHON_VERSION} EXACT REQUIRED)
|
||||
else()
|
||||
if(GTSAM_PYTHON_VERSION STREQUAL "Default")
|
||||
find_package(PythonInterp)
|
||||
else()
|
||||
find_package(PythonInterp ${GTSAM_PYTHON_VERSION} EXACT)
|
||||
endif()
|
||||
find_package(PythonInterp ${GTSAM_PYTHON_VERSION} EXACT)
|
||||
endif()
|
||||
|
||||
if(NOT PYTHONINTERP_FOUND)
|
||||
|
|
|
|||
|
|
@ -99,11 +99,8 @@ if(NOT TBB_FOUND)
|
|||
##################################
|
||||
|
||||
if(NOT DEFINED TBB_USE_DEBUG_BUILD)
|
||||
if(CMAKE_BUILD_TYPE MATCHES "(Debug|DEBUG|debug|RelWithDebInfo|RELWITHDEBINFO|relwithdebinfo)")
|
||||
set(TBB_BUILD_TYPE DEBUG)
|
||||
else()
|
||||
set(TBB_BUILD_TYPE RELEASE)
|
||||
endif()
|
||||
# Set build type to RELEASE by default for optimization.
|
||||
set(TBB_BUILD_TYPE RELEASE)
|
||||
elseif(TBB_USE_DEBUG_BUILD)
|
||||
set(TBB_BUILD_TYPE DEBUG)
|
||||
else()
|
||||
|
|
@ -147,7 +144,8 @@ if(NOT TBB_FOUND)
|
|||
|
||||
elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
|
||||
# OS X
|
||||
set(TBB_DEFAULT_SEARCH_DIR "/opt/intel/tbb")
|
||||
set(TBB_DEFAULT_SEARCH_DIR "/opt/intel/tbb"
|
||||
"/usr/local/opt/tbb")
|
||||
|
||||
# TODO: Check to see which C++ library is being used by the compiler.
|
||||
if(NOT ${CMAKE_SYSTEM_VERSION} VERSION_LESS 13.0)
|
||||
|
|
@ -184,7 +182,18 @@ if(NOT TBB_FOUND)
|
|||
##################################
|
||||
|
||||
if(TBB_INCLUDE_DIRS)
|
||||
file(READ "${TBB_INCLUDE_DIRS}/tbb/tbb_stddef.h" _tbb_version_file)
|
||||
set(_tbb_version_file_prior_to_tbb_2021_1 "${TBB_INCLUDE_DIRS}/tbb/tbb_stddef.h")
|
||||
set(_tbb_version_file_after_tbb_2021_1 "${TBB_INCLUDE_DIRS}/oneapi/tbb/version.h")
|
||||
|
||||
if (EXISTS "${_tbb_version_file_prior_to_tbb_2021_1}")
|
||||
file(READ "${_tbb_version_file_prior_to_tbb_2021_1}" _tbb_version_file )
|
||||
elseif (EXISTS "${_tbb_version_file_after_tbb_2021_1}")
|
||||
file(READ "${_tbb_version_file_after_tbb_2021_1}" _tbb_version_file )
|
||||
else()
|
||||
message(FATAL_ERROR "Found TBB installation: ${TBB_INCLUDE_DIRS} "
|
||||
"missing version header.")
|
||||
endif()
|
||||
|
||||
string(REGEX REPLACE ".*#define TBB_VERSION_MAJOR ([0-9]+).*" "\\1"
|
||||
TBB_VERSION_MAJOR "${_tbb_version_file}")
|
||||
string(REGEX REPLACE ".*#define TBB_VERSION_MINOR ([0-9]+).*" "\\1"
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
include(CheckCXXCompilerFlag) # for check_cxx_compiler_flag()
|
||||
|
||||
# Set cmake policy to recognize the AppleClang compiler
|
||||
# independently from the Clang compiler.
|
||||
if(POLICY CMP0025)
|
||||
|
|
@ -57,10 +59,10 @@ endif()
|
|||
option(GTSAM_BUILD_TYPE_POSTFIXES "Enable/Disable appending the build type to the name of compiled libraries" ON)
|
||||
|
||||
# Define all cache variables, to be populated below depending on the OS/compiler:
|
||||
set(GTSAM_COMPILE_OPTIONS_PRIVATE "" CACHE STRING "(Do not edit) Private compiler flags for all build configurations." FORCE)
|
||||
set(GTSAM_COMPILE_OPTIONS_PUBLIC "" CACHE STRING "(Do not edit) Public compiler flags (exported to user projects) for all build configurations." FORCE)
|
||||
set(GTSAM_COMPILE_DEFINITIONS_PRIVATE "" CACHE STRING "(Do not edit) Private preprocessor macros for all build configurations." FORCE)
|
||||
set(GTSAM_COMPILE_DEFINITIONS_PUBLIC "" CACHE STRING "(Do not edit) Public preprocessor macros for all build configurations." FORCE)
|
||||
set(GTSAM_COMPILE_OPTIONS_PRIVATE "" CACHE INTERNAL "(Do not edit) Private compiler flags for all build configurations." FORCE)
|
||||
set(GTSAM_COMPILE_OPTIONS_PUBLIC "" CACHE INTERNAL "(Do not edit) Public compiler flags (exported to user projects) for all build configurations." FORCE)
|
||||
set(GTSAM_COMPILE_DEFINITIONS_PRIVATE "" CACHE INTERNAL "(Do not edit) Private preprocessor macros for all build configurations." FORCE)
|
||||
set(GTSAM_COMPILE_DEFINITIONS_PUBLIC "" CACHE INTERNAL "(Do not edit) Public preprocessor macros for all build configurations." FORCE)
|
||||
mark_as_advanced(GTSAM_COMPILE_OPTIONS_PRIVATE)
|
||||
mark_as_advanced(GTSAM_COMPILE_OPTIONS_PUBLIC)
|
||||
mark_as_advanced(GTSAM_COMPILE_DEFINITIONS_PRIVATE)
|
||||
|
|
@ -69,7 +71,7 @@ mark_as_advanced(GTSAM_COMPILE_DEFINITIONS_PUBLIC)
|
|||
foreach(build_type ${GTSAM_CMAKE_CONFIGURATION_TYPES})
|
||||
string(TOUPPER "${build_type}" build_type_toupper)
|
||||
|
||||
# Define empty cache variables for "public". "private" are creaed below.
|
||||
# Define empty cache variables for "public". "private" are created below.
|
||||
set(GTSAM_COMPILE_OPTIONS_PUBLIC_${build_type_toupper} "" CACHE STRING "(User editable) Public compiler flags (exported to user projects) for `${build_type_toupper}` configuration.")
|
||||
set(GTSAM_COMPILE_DEFINITIONS_PUBLIC_${build_type_toupper} "" CACHE STRING "(User editable) Public preprocessor macros for `${build_type_toupper}` configuration.")
|
||||
endforeach()
|
||||
|
|
@ -105,11 +107,14 @@ if(MSVC)
|
|||
else()
|
||||
# Common to all configurations, next for each configuration:
|
||||
|
||||
if (
|
||||
((CMAKE_CXX_COMPILER_ID MATCHES "Clang") AND (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 12.0.0)) OR
|
||||
(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
|
||||
)
|
||||
set(flag_override_ -Wsuggest-override) # -Werror=suggest-override: Add again someday
|
||||
if (NOT MSVC)
|
||||
check_cxx_compiler_flag(-Wsuggest-override COMPILER_HAS_WSUGGEST_OVERRIDE)
|
||||
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
|
||||
elseif(COMPILER_HAS_WMISSING_OVERRIDE)
|
||||
set(flag_override_ -Wmissing-override) # -Werror=missing-override: Add again someday
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(GTSAM_COMPILE_OPTIONS_PRIVATE_COMMON
|
||||
|
|
@ -199,9 +204,9 @@ endif()
|
|||
|
||||
# Make common binary output directory when on Windows
|
||||
if(WIN32)
|
||||
set(RUNTIME_OUTPUT_PATH "${CMAKE_BINARY_DIR}/bin")
|
||||
set(EXECUTABLE_OUTPUT_PATH "${CMAKE_BINARY_DIR}/bin")
|
||||
set(LIBRARY_OUTPUT_PATH "${CMAKE_BINARY_DIR}/lib")
|
||||
set(RUNTIME_OUTPUT_PATH "${GTSAM_BINARY_DIR}/bin")
|
||||
set(EXECUTABLE_OUTPUT_PATH "${GTSAM_BINARY_DIR}/bin")
|
||||
set(LIBRARY_OUTPUT_PATH "${GTSAM_BINARY_DIR}/lib")
|
||||
endif()
|
||||
|
||||
# Set up build type list for cmake-gui
|
||||
|
|
@ -263,3 +268,17 @@ function(gtsam_apply_build_flags target_name_)
|
|||
target_compile_options(${target_name_} PRIVATE ${GTSAM_COMPILE_OPTIONS_PRIVATE})
|
||||
|
||||
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()
|
||||
|
|
|
|||
|
|
@ -27,6 +27,8 @@ function(GtsamMakeConfigFile PACKAGE_NAME)
|
|||
# here.
|
||||
if(NOT DEFINED ${PACKAGE_NAME}_VERSION AND DEFINED ${PACKAGE_NAME}_VERSION_STRING)
|
||||
set(${PACKAGE_NAME}_VERSION ${${PACKAGE_NAME}_VERSION_STRING})
|
||||
elseif(NOT DEFINED ${PACKAGE_NAME}_VERSION_STRING)
|
||||
set(${PACKAGE_NAME}_VERSION ${GTSAM_VERSION_STRING})
|
||||
endif()
|
||||
|
||||
# Version file
|
||||
|
|
|
|||
|
|
@ -1,425 +0,0 @@
|
|||
# Set up cache options
|
||||
option(GTSAM_MEX_BUILD_STATIC_MODULE "Build MATLAB wrapper statically (increases build time)" OFF)
|
||||
set(GTSAM_BUILD_MEX_BINARY_FLAGS "" CACHE STRING "Extra flags for running Matlab MEX compilation")
|
||||
set(GTSAM_TOOLBOX_INSTALL_PATH "" CACHE PATH "Matlab toolbox destination, blank defaults to CMAKE_INSTALL_PREFIX/gtsam_toolbox")
|
||||
if(NOT GTSAM_TOOLBOX_INSTALL_PATH)
|
||||
set(GTSAM_TOOLBOX_INSTALL_PATH "${CMAKE_INSTALL_PREFIX}/gtsam_toolbox")
|
||||
endif()
|
||||
|
||||
# GTSAM_MEX_BUILD_STATIC_MODULE is not for Windows - on Windows any static
|
||||
# are already compiled into the library by the linker
|
||||
if(GTSAM_MEX_BUILD_STATIC_MODULE AND WIN32)
|
||||
message(FATAL_ERROR "GTSAM_MEX_BUILD_STATIC_MODULE should not be set on Windows - the linker already automatically compiles in any dependent static libraries. To create a standalone toolbox pacakge, simply ensure that CMake finds the static versions of all dependent libraries (Boost, etc).")
|
||||
endif()
|
||||
|
||||
# Try to automatically configure mex path
|
||||
if(APPLE)
|
||||
file(GLOB matlab_bin_directories "/Applications/MATLAB*/bin")
|
||||
set(mex_program_name "mex")
|
||||
elseif(WIN32)
|
||||
file(GLOB matlab_bin_directories "C:/Program Files*/MATLAB/*/bin")
|
||||
set(mex_program_name "mex.bat")
|
||||
else()
|
||||
file(GLOB matlab_bin_directories "/usr/local/MATLAB/*/bin")
|
||||
set(mex_program_name "mex")
|
||||
endif()
|
||||
|
||||
if(GTSAM_CUSTOM_MATLAB_PATH)
|
||||
set(matlab_bin_directories ${GTSAM_CUSTOM_MATLAB_PATH})
|
||||
endif()
|
||||
|
||||
# Run find_program explicitly putting $PATH after our predefined program
|
||||
# directories using 'ENV PATH' and 'NO_SYSTEM_ENVIRONMENT_PATH' - this prevents
|
||||
# finding the LaTeX mex program (totally unrelated to MATLAB Mex) when LaTeX is
|
||||
# on the system path.
|
||||
list(REVERSE matlab_bin_directories) # Reverse list so the highest version (sorted alphabetically) is preferred
|
||||
find_program(MEX_COMMAND ${mex_program_name}
|
||||
PATHS ${matlab_bin_directories} ENV PATH
|
||||
NO_DEFAULT_PATH)
|
||||
mark_as_advanced(FORCE MEX_COMMAND)
|
||||
# Now that we have mex, trace back to find the Matlab installation root
|
||||
get_filename_component(MEX_COMMAND "${MEX_COMMAND}" REALPATH)
|
||||
get_filename_component(mex_path "${MEX_COMMAND}" PATH)
|
||||
if(mex_path MATCHES ".*/win64$")
|
||||
get_filename_component(MATLAB_ROOT "${mex_path}/../.." ABSOLUTE)
|
||||
else()
|
||||
get_filename_component(MATLAB_ROOT "${mex_path}/.." ABSOLUTE)
|
||||
endif()
|
||||
set(MATLAB_ROOT "${MATLAB_ROOT}" CACHE PATH "Path to MATLAB installation root (e.g. /usr/local/MATLAB/R2012a)")
|
||||
|
||||
|
||||
# User-friendly wrapping function. Builds a mex module from the provided
|
||||
# interfaceHeader. For example, for the interface header gtsam.h,
|
||||
# this will build the wrap module 'gtsam'.
|
||||
#
|
||||
# Arguments:
|
||||
#
|
||||
# interfaceHeader: The relative path to the wrapper interface definition file.
|
||||
# linkLibraries: Any *additional* libraries to link. Your project library
|
||||
# (e.g. `lba`), libraries it depends on, and any necessary
|
||||
# MATLAB libraries will be linked automatically. So normally,
|
||||
# leave this empty.
|
||||
# extraIncludeDirs: Any *additional* include paths required by dependent
|
||||
# libraries that have not already been added by
|
||||
# include_directories. Again, normally, leave this empty.
|
||||
# extraMexFlags: Any *additional* flags to pass to the compiler when building
|
||||
# the wrap code. Normally, leave this empty.
|
||||
function(wrap_and_install_library interfaceHeader linkLibraries extraIncludeDirs extraMexFlags)
|
||||
wrap_library_internal("${interfaceHeader}" "${linkLibraries}" "${extraIncludeDirs}" "${mexFlags}")
|
||||
install_wrapped_library_internal("${interfaceHeader}")
|
||||
endfunction()
|
||||
|
||||
|
||||
# Internal function that wraps a library and compiles the wrapper
|
||||
function(wrap_library_internal interfaceHeader linkLibraries extraIncludeDirs extraMexFlags)
|
||||
if(UNIX AND NOT APPLE)
|
||||
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
set(mexModuleExt mexa64)
|
||||
else()
|
||||
set(mexModuleExt mexglx)
|
||||
endif()
|
||||
elseif(APPLE)
|
||||
set(mexModuleExt mexmaci64)
|
||||
elseif(MSVC)
|
||||
if(CMAKE_CL_64)
|
||||
set(mexModuleExt mexw64)
|
||||
else()
|
||||
set(mexModuleExt mexw32)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Wrap codegen interface
|
||||
#usage: wrap interfacePath moduleName toolboxPath headerPath
|
||||
# interfacePath : *absolute* path to directory of module interface file
|
||||
# moduleName : the name of the module, interface file must be called moduleName.h
|
||||
# toolboxPath : the directory in which to generate the wrappers
|
||||
# headerPath : path to matlab.h
|
||||
|
||||
# Extract module name from interface header file name
|
||||
get_filename_component(interfaceHeader "${interfaceHeader}" ABSOLUTE)
|
||||
get_filename_component(modulePath "${interfaceHeader}" PATH)
|
||||
get_filename_component(moduleName "${interfaceHeader}" NAME_WE)
|
||||
|
||||
# Paths for generated files
|
||||
set(generated_files_path "${PROJECT_BINARY_DIR}/wrap/${moduleName}")
|
||||
set(generated_cpp_file "${generated_files_path}/${moduleName}_wrapper.cpp")
|
||||
set(compiled_mex_modules_root "${PROJECT_BINARY_DIR}/wrap/${moduleName}_mex")
|
||||
|
||||
message(STATUS "Building wrap module ${moduleName}")
|
||||
|
||||
# Find matlab.h in GTSAM
|
||||
if(("${PROJECT_NAME}" STREQUAL "gtsam") OR
|
||||
("${PROJECT_NAME}" STREQUAL "gtsam_unstable"))
|
||||
set(matlab_h_path "${PROJECT_SOURCE_DIR}")
|
||||
else()
|
||||
if(NOT GTSAM_INCLUDE_DIR)
|
||||
message(FATAL_ERROR "You must call find_package(GTSAM) before using wrap")
|
||||
endif()
|
||||
list(GET GTSAM_INCLUDE_DIR 0 installed_includes_path)
|
||||
set(matlab_h_path "${installed_includes_path}/wrap")
|
||||
endif()
|
||||
|
||||
# If building a static mex module, add all cmake-linked libraries to the
|
||||
# explicit link libraries list so that the next block of code can unpack
|
||||
# any static libraries
|
||||
set(automaticDependencies "")
|
||||
foreach(lib ${moduleName} ${linkLibraries})
|
||||
#message("MODULE NAME: ${moduleName}")
|
||||
if(TARGET "${lib}")
|
||||
get_target_property(dependentLibraries ${lib} INTERFACE_LINK_LIBRARIES)
|
||||
# message("DEPENDENT LIBRARIES: ${dependentLibraries}")
|
||||
if(dependentLibraries)
|
||||
list(APPEND automaticDependencies ${dependentLibraries})
|
||||
endif()
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
## CHRIS: Temporary fix. On my system the get_target_property above returned Not-found for gtsam module
|
||||
## This needs to be fixed!!
|
||||
if(UNIX AND NOT APPLE)
|
||||
list(APPEND automaticDependencies ${Boost_SERIALIZATION_LIBRARY_RELEASE} ${Boost_FILESYSTEM_LIBRARY_RELEASE}
|
||||
${Boost_SYSTEM_LIBRARY_RELEASE} ${Boost_THREAD_LIBRARY_RELEASE} ${Boost_DATE_TIME_LIBRARY_RELEASE})
|
||||
if(Boost_TIMER_LIBRARY_RELEASE AND NOT GTSAM_DISABLE_NEW_TIMERS) # Only present in Boost >= 1.48.0
|
||||
list(APPEND automaticDependencies ${Boost_TIMER_LIBRARY_RELEASE} ${Boost_CHRONO_LIBRARY_RELEASE})
|
||||
if(GTSAM_MEX_BUILD_STATIC_MODULE)
|
||||
#list(APPEND automaticDependencies -Wl,--no-as-needed -lrt)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
#message("AUTOMATIC DEPENDENCIES: ${automaticDependencies}")
|
||||
## CHRIS: End temporary fix
|
||||
|
||||
# Separate dependencies
|
||||
set(correctedOtherLibraries "")
|
||||
set(otherLibraryTargets "")
|
||||
set(otherLibraryNontargets "")
|
||||
set(otherSourcesAndObjects "")
|
||||
foreach(lib ${moduleName} ${linkLibraries} ${automaticDependencies})
|
||||
if(TARGET "${lib}")
|
||||
if(GTSAM_MEX_BUILD_STATIC_MODULE)
|
||||
get_target_property(target_sources ${lib} SOURCES)
|
||||
list(APPEND otherSourcesAndObjects ${target_sources})
|
||||
else()
|
||||
list(APPEND correctedOtherLibraries ${lib})
|
||||
list(APPEND otherLibraryTargets ${lib})
|
||||
endif()
|
||||
else()
|
||||
get_filename_component(file_extension "${lib}" EXT)
|
||||
get_filename_component(lib_name "${lib}" NAME_WE)
|
||||
if(file_extension STREQUAL ".a" AND GTSAM_MEX_BUILD_STATIC_MODULE)
|
||||
# For building a static MEX module, unpack the static library
|
||||
# and compile its object files into our module
|
||||
file(MAKE_DIRECTORY "${generated_files_path}/${lib_name}_objects")
|
||||
execute_process(COMMAND ar -x "${lib}"
|
||||
WORKING_DIRECTORY "${generated_files_path}/${lib_name}_objects"
|
||||
RESULT_VARIABLE ar_result)
|
||||
if(NOT ar_result EQUAL 0)
|
||||
message(FATAL_ERROR "Failed extracting ${lib}")
|
||||
endif()
|
||||
|
||||
# Get list of object files
|
||||
execute_process(COMMAND ar -t "${lib}"
|
||||
OUTPUT_VARIABLE object_files
|
||||
RESULT_VARIABLE ar_result)
|
||||
if(NOT ar_result EQUAL 0)
|
||||
message(FATAL_ERROR "Failed listing ${lib}")
|
||||
endif()
|
||||
|
||||
# Add directory to object files
|
||||
string(REPLACE "\n" ";" object_files_list "${object_files}")
|
||||
foreach(object_file ${object_files_list})
|
||||
get_filename_component(file_extension "${object_file}" EXT)
|
||||
if(file_extension STREQUAL ".o")
|
||||
list(APPEND otherSourcesAndObjects "${generated_files_path}/${lib_name}_objects/${object_file}")
|
||||
endif()
|
||||
endforeach()
|
||||
else()
|
||||
list(APPEND correctedOtherLibraries ${lib})
|
||||
list(APPEND otherLibraryNontargets ${lib})
|
||||
endif()
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# Check libraries for conflicting versions built-in to MATLAB
|
||||
set(dependentLibraries "")
|
||||
if(NOT "${otherLibraryTargets}" STREQUAL "")
|
||||
foreach(target ${otherLibraryTargets})
|
||||
get_target_property(dependentLibrariesOne ${target} INTERFACE_LINK_LIBRARIES)
|
||||
list(APPEND dependentLibraries ${dependentLibrariesOne})
|
||||
endforeach()
|
||||
endif()
|
||||
list(APPEND dependentLibraries ${otherLibraryNontargets})
|
||||
check_conflicting_libraries_internal("${dependentLibraries}")
|
||||
|
||||
# Set up generation of module source file
|
||||
file(MAKE_DIRECTORY "${generated_files_path}")
|
||||
|
||||
if(GTSAM_PYTHON_VERSION STREQUAL "Default")
|
||||
find_package(PythonInterp REQUIRED)
|
||||
find_package(PythonLibs REQUIRED)
|
||||
else()
|
||||
find_package(PythonInterp
|
||||
${GTSAM_PYTHON_VERSION}
|
||||
EXACT
|
||||
REQUIRED)
|
||||
find_package(PythonLibs
|
||||
${GTSAM_PYTHON_VERSION}
|
||||
EXACT
|
||||
REQUIRED)
|
||||
endif()
|
||||
|
||||
set(_ignore gtsam::Point2
|
||||
gtsam::Point3)
|
||||
add_custom_command(
|
||||
OUTPUT ${generated_cpp_file}
|
||||
DEPENDS ${interfaceHeader} ${module_library_target} ${otherLibraryTargets} ${otherSourcesAndObjects}
|
||||
COMMAND
|
||||
${PYTHON_EXECUTABLE}
|
||||
${CMAKE_SOURCE_DIR}/wrap/matlab_wrapper.py
|
||||
--src ${interfaceHeader}
|
||||
--module_name ${moduleName}
|
||||
--out ${generated_files_path}
|
||||
--top_module_namespaces ${moduleName}
|
||||
--ignore ${_ignore}
|
||||
VERBATIM
|
||||
WORKING_DIRECTORY ${generated_files_path})
|
||||
|
||||
# Set up building of mex module
|
||||
string(REPLACE ";" " " extraMexFlagsSpaced "${extraMexFlags}")
|
||||
string(REPLACE ";" " " mexFlagsSpaced "${GTSAM_BUILD_MEX_BINARY_FLAGS}")
|
||||
add_library(${moduleName}_matlab_wrapper MODULE ${generated_cpp_file} ${interfaceHeader} ${otherSourcesAndObjects})
|
||||
target_link_libraries(${moduleName}_matlab_wrapper ${correctedOtherLibraries})
|
||||
target_link_libraries(${moduleName}_matlab_wrapper ${moduleName})
|
||||
set_target_properties(${moduleName}_matlab_wrapper PROPERTIES
|
||||
OUTPUT_NAME "${moduleName}_wrapper"
|
||||
PREFIX ""
|
||||
SUFFIX ".${mexModuleExt}"
|
||||
LIBRARY_OUTPUT_DIRECTORY "${compiled_mex_modules_root}"
|
||||
ARCHIVE_OUTPUT_DIRECTORY "${compiled_mex_modules_root}"
|
||||
RUNTIME_OUTPUT_DIRECTORY "${compiled_mex_modules_root}"
|
||||
CLEAN_DIRECT_OUTPUT 1)
|
||||
set_property(TARGET ${moduleName}_matlab_wrapper APPEND_STRING PROPERTY COMPILE_FLAGS " ${extraMexFlagsSpaced} ${mexFlagsSpaced} \"-I${MATLAB_ROOT}/extern/include\" -DMATLAB_MEX_FILE -DMX_COMPAT_32")
|
||||
set_property(TARGET ${moduleName}_matlab_wrapper APPEND PROPERTY INCLUDE_DIRECTORIES ${extraIncludeDirs})
|
||||
# Disable build type postfixes for the mex module - we install in different directories for each build type instead
|
||||
foreach(build_type ${CMAKE_CONFIGURATION_TYPES})
|
||||
string(TOUPPER "${build_type}" build_type_upper)
|
||||
set_target_properties(${moduleName}_matlab_wrapper PROPERTIES ${build_type_upper}_POSTFIX "")
|
||||
endforeach()
|
||||
# Set up platform-specific flags
|
||||
if(MSVC)
|
||||
if(CMAKE_CL_64)
|
||||
set(mxLibPath "${MATLAB_ROOT}/extern/lib/win64/microsoft")
|
||||
else()
|
||||
set(mxLibPath "${MATLAB_ROOT}/extern/lib/win32/microsoft")
|
||||
endif()
|
||||
target_link_libraries(${moduleName}_matlab_wrapper "${mxLibPath}/libmex.lib" "${mxLibPath}/libmx.lib" "${mxLibPath}/libmat.lib")
|
||||
set_target_properties(${moduleName}_matlab_wrapper PROPERTIES LINK_FLAGS "/export:mexFunction")
|
||||
set_property(SOURCE "${generated_cpp_file}" APPEND PROPERTY COMPILE_FLAGS "/bigobj")
|
||||
elseif(APPLE)
|
||||
set(mxLibPath "${MATLAB_ROOT}/bin/maci64")
|
||||
target_link_libraries(${moduleName}_matlab_wrapper "${mxLibPath}/libmex.dylib" "${mxLibPath}/libmx.dylib" "${mxLibPath}/libmat.dylib")
|
||||
endif()
|
||||
|
||||
# Hacking around output issue with custom command
|
||||
# Deletes generated build folder
|
||||
add_custom_target(wrap_${moduleName}_matlab_distclean
|
||||
COMMAND cmake -E remove_directory ${generated_files_path}
|
||||
COMMAND cmake -E remove_directory ${compiled_mex_modules_root})
|
||||
endfunction()
|
||||
|
||||
# Internal function that installs a wrap toolbox
|
||||
function(install_wrapped_library_internal interfaceHeader)
|
||||
get_filename_component(moduleName "${interfaceHeader}" NAME_WE)
|
||||
set(generated_files_path "${PROJECT_BINARY_DIR}/wrap/${moduleName}")
|
||||
|
||||
# NOTE: only installs .m and mex binary files (not .cpp) - the trailing slash on the directory name
|
||||
# here prevents creating the top-level module name directory in the destination.
|
||||
message(STATUS "Installing Matlab Toolbox to ${GTSAM_TOOLBOX_INSTALL_PATH}")
|
||||
if(GTSAM_BUILD_TYPE_POSTFIXES)
|
||||
foreach(build_type ${CMAKE_CONFIGURATION_TYPES})
|
||||
string(TOUPPER "${build_type}" build_type_upper)
|
||||
if(${build_type_upper} STREQUAL "RELEASE")
|
||||
set(build_type_tag "") # Don't create release mode tag on installed directory
|
||||
else()
|
||||
set(build_type_tag "${build_type}")
|
||||
endif()
|
||||
# Split up filename to strip trailing '/' in GTSAM_TOOLBOX_INSTALL_PATH if there is one
|
||||
get_filename_component(location "${GTSAM_TOOLBOX_INSTALL_PATH}" PATH)
|
||||
get_filename_component(name "${GTSAM_TOOLBOX_INSTALL_PATH}" NAME)
|
||||
install(DIRECTORY "${generated_files_path}/" DESTINATION "${location}/${name}${build_type_tag}" CONFIGURATIONS "${build_type}" FILES_MATCHING PATTERN "*.m")
|
||||
install(TARGETS ${moduleName}_matlab_wrapper
|
||||
LIBRARY DESTINATION "${location}/${name}${build_type_tag}" CONFIGURATIONS "${build_type}"
|
||||
RUNTIME DESTINATION "${location}/${name}${build_type_tag}" CONFIGURATIONS "${build_type}")
|
||||
endforeach()
|
||||
else()
|
||||
install(DIRECTORY "${generated_files_path}/" DESTINATION ${GTSAM_TOOLBOX_INSTALL_PATH} FILES_MATCHING PATTERN "*.m")
|
||||
install(TARGETS ${moduleName}_matlab_wrapper
|
||||
LIBRARY DESTINATION ${GTSAM_TOOLBOX_INSTALL_PATH}
|
||||
RUNTIME DESTINATION ${GTSAM_TOOLBOX_INSTALL_PATH})
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# Internal function to check for libraries installed with MATLAB that may conflict
|
||||
# and prints a warning to move them if problems occur.
|
||||
function(check_conflicting_libraries_internal libraries)
|
||||
if(UNIX)
|
||||
# Set path for matlab's built-in libraries
|
||||
if(APPLE)
|
||||
set(mxLibPath "${MATLAB_ROOT}/bin/maci64")
|
||||
else()
|
||||
if(CMAKE_CL_64)
|
||||
set(mxLibPath "${MATLAB_ROOT}/bin/glnxa64")
|
||||
else()
|
||||
set(mxLibPath "${MATLAB_ROOT}/bin/glnx86")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# List matlab's built-in libraries
|
||||
file(GLOB matlabLibs RELATIVE "${mxLibPath}" "${mxLibPath}/lib*")
|
||||
|
||||
# Convert to base names
|
||||
set(matlabLibNames "")
|
||||
foreach(lib ${matlabLibs})
|
||||
get_filename_component(libName "${lib}" NAME_WE)
|
||||
list(APPEND matlabLibNames "${libName}")
|
||||
endforeach()
|
||||
|
||||
# Get names of link libraries
|
||||
set(linkLibNames "")
|
||||
foreach(lib ${libraries})
|
||||
string(FIND "${lib}" "/" slashPos)
|
||||
if(NOT slashPos EQUAL -1)
|
||||
# If the name is a path, just get the library name
|
||||
get_filename_component(libName "${lib}" NAME_WE)
|
||||
list(APPEND linkLibNames "${libName}")
|
||||
else()
|
||||
# It's not a path, so see if it looks like a filename
|
||||
get_filename_component(ext "${lib}" EXT)
|
||||
if(NOT "${ext}" STREQUAL "")
|
||||
# It's a filename, so get the base name
|
||||
get_filename_component(libName "${lib}" NAME_WE)
|
||||
list(APPEND linkLibNames "${libName}")
|
||||
else()
|
||||
# It's not a filename so it must be a short name, add the "lib" prefix
|
||||
list(APPEND linkLibNames "lib${lib}")
|
||||
endif()
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# Remove duplicates
|
||||
list(REMOVE_DUPLICATES linkLibNames)
|
||||
|
||||
set(conflictingLibs "")
|
||||
foreach(lib ${linkLibNames})
|
||||
list(FIND matlabLibNames "${lib}" libPos)
|
||||
if(NOT libPos EQUAL -1)
|
||||
if(NOT conflictingLibs STREQUAL "")
|
||||
set(conflictingLibs "${conflictingLibs}, ")
|
||||
endif()
|
||||
set(conflictingLibs "${conflictingLibs}${lib}")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
if(NOT "${conflictingLibs}" STREQUAL "")
|
||||
message(WARNING "GTSAM links to the libraries [ ${conflictingLibs} ] on your system, but "
|
||||
"MATLAB is distributed with its own versions of these libraries which may conflict. "
|
||||
"If you get strange errors or crashes with the GTSAM MATLAB wrapper, move these "
|
||||
"libraries out of MATLAB's built-in library directory, which is ${mxLibPath} on "
|
||||
"your system. MATLAB will usually still work with these libraries moved away, but "
|
||||
"if not, you'll have to compile the static GTSAM MATLAB wrapper module.")
|
||||
endif()
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# Helper function to install MATLAB scripts and handle multiple build types where the scripts
|
||||
# should be installed to all build type toolboxes
|
||||
function(install_matlab_scripts source_directory patterns)
|
||||
set(patterns_args "")
|
||||
set(exclude_patterns "")
|
||||
if(NOT GTSAM_WRAP_SERIALIZATION)
|
||||
set(exclude_patterns "testSerialization.m")
|
||||
endif()
|
||||
|
||||
foreach(pattern ${patterns})
|
||||
list(APPEND patterns_args PATTERN "${pattern}")
|
||||
endforeach()
|
||||
if(GTSAM_BUILD_TYPE_POSTFIXES)
|
||||
foreach(build_type ${CMAKE_CONFIGURATION_TYPES})
|
||||
string(TOUPPER "${build_type}" build_type_upper)
|
||||
if(${build_type_upper} STREQUAL "RELEASE")
|
||||
set(build_type_tag "") # Don't create release mode tag on installed directory
|
||||
else()
|
||||
set(build_type_tag "${build_type}")
|
||||
endif()
|
||||
# Split up filename to strip trailing '/' in GTSAM_TOOLBOX_INSTALL_PATH if there is one
|
||||
get_filename_component(location "${GTSAM_TOOLBOX_INSTALL_PATH}" PATH)
|
||||
get_filename_component(name "${GTSAM_TOOLBOX_INSTALL_PATH}" NAME)
|
||||
install(DIRECTORY "${source_directory}" DESTINATION "${location}/${name}${build_type_tag}" CONFIGURATIONS "${build_type}" FILES_MATCHING ${patterns_args} PATTERN "${exclude_patterns}" EXCLUDE)
|
||||
endforeach()
|
||||
else()
|
||||
install(DIRECTORY "${source_directory}" DESTINATION "${GTSAM_TOOLBOX_INSTALL_PATH}" FILES_MATCHING ${patterns_args} PATTERN "${exclude_patterns}" EXCLUDE)
|
||||
endif()
|
||||
|
||||
endfunction()
|
||||
|
||||
|
|
@ -46,16 +46,16 @@ endfunction()
|
|||
# Prints all the relevant CMake build options for a given target:
|
||||
function(print_build_options_for_target target_name_)
|
||||
print_padded(GTSAM_COMPILE_FEATURES_PUBLIC)
|
||||
print_padded(GTSAM_COMPILE_OPTIONS_PRIVATE)
|
||||
# print_padded(GTSAM_COMPILE_OPTIONS_PRIVATE)
|
||||
print_padded(GTSAM_COMPILE_OPTIONS_PUBLIC)
|
||||
print_padded(GTSAM_COMPILE_DEFINITIONS_PRIVATE)
|
||||
# print_padded(GTSAM_COMPILE_DEFINITIONS_PRIVATE)
|
||||
print_padded(GTSAM_COMPILE_DEFINITIONS_PUBLIC)
|
||||
|
||||
foreach(build_type ${GTSAM_CMAKE_CONFIGURATION_TYPES})
|
||||
string(TOUPPER "${build_type}" build_type_toupper)
|
||||
print_padded(GTSAM_COMPILE_OPTIONS_PRIVATE_${build_type_toupper})
|
||||
# print_padded(GTSAM_COMPILE_OPTIONS_PRIVATE_${build_type_toupper})
|
||||
print_padded(GTSAM_COMPILE_OPTIONS_PUBLIC_${build_type_toupper})
|
||||
print_padded(GTSAM_COMPILE_DEFINITIONS_PRIVATE_${build_type_toupper})
|
||||
# print_padded(GTSAM_COMPILE_DEFINITIONS_PRIVATE_${build_type_toupper})
|
||||
print_padded(GTSAM_COMPILE_DEFINITIONS_PUBLIC_${build_type_toupper})
|
||||
endforeach()
|
||||
endfunction()
|
||||
|
|
|
|||
|
|
@ -88,36 +88,36 @@ enable_testing()
|
|||
|
||||
option(GTSAM_BUILD_TESTS "Enable/Disable building of tests" ON)
|
||||
option(GTSAM_BUILD_EXAMPLES_ALWAYS "Build examples with 'make all' (build with 'make examples' if not)" ON)
|
||||
option(GTSAM_BUILD_TIMING_ALWAYS "Build timing scripts with 'make all' (build with 'make timing' if not" OFF)
|
||||
option(GTSAM_BUILD_TIMING_ALWAYS "Build timing scripts with 'make all' (build with 'make timing' if not" OFF)
|
||||
|
||||
# Add option for combining unit tests
|
||||
if(MSVC OR XCODE_VERSION)
|
||||
option(GTSAM_SINGLE_TEST_EXE "Combine unit tests into single executable (faster compile)" ON)
|
||||
else()
|
||||
option(GTSAM_SINGLE_TEST_EXE "Combine unit tests into single executable (faster compile)" OFF)
|
||||
endif()
|
||||
mark_as_advanced(GTSAM_SINGLE_TEST_EXE)
|
||||
# Add option for combining unit tests
|
||||
if(MSVC OR XCODE_VERSION)
|
||||
option(GTSAM_SINGLE_TEST_EXE "Combine unit tests into single executable (faster compile)" ON)
|
||||
else()
|
||||
option(GTSAM_SINGLE_TEST_EXE "Combine unit tests into single executable (faster compile)" OFF)
|
||||
endif()
|
||||
mark_as_advanced(GTSAM_SINGLE_TEST_EXE)
|
||||
|
||||
# Enable make check (http://www.cmake.org/Wiki/CMakeEmulateMakeCheck)
|
||||
if(GTSAM_BUILD_TESTS)
|
||||
add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION> --output-on-failure)
|
||||
# Also add alternative checks using valgrind.
|
||||
# We don't look for valgrind being installed in the system, since these
|
||||
# targets are not invoked unless directly instructed by the user.
|
||||
if (UNIX)
|
||||
# Run all tests using valgrind:
|
||||
add_custom_target(check_valgrind)
|
||||
endif()
|
||||
# Enable make check (http://www.cmake.org/Wiki/CMakeEmulateMakeCheck)
|
||||
if(GTSAM_BUILD_TESTS)
|
||||
add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION> --output-on-failure)
|
||||
# Also add alternative checks using valgrind.
|
||||
# We don't look for valgrind being installed in the system, since these
|
||||
# targets are not invoked unless directly instructed by the user.
|
||||
if (UNIX)
|
||||
# Run all tests using valgrind:
|
||||
add_custom_target(check_valgrind)
|
||||
endif()
|
||||
|
||||
# Add target to build tests without running
|
||||
add_custom_target(all.tests)
|
||||
endif()
|
||||
# Add target to build tests without running
|
||||
add_custom_target(all.tests)
|
||||
endif()
|
||||
|
||||
# Add examples target
|
||||
add_custom_target(examples)
|
||||
# Add examples target
|
||||
add_custom_target(examples)
|
||||
|
||||
# Add timing target
|
||||
add_custom_target(timing)
|
||||
# Add timing target
|
||||
add_custom_target(timing)
|
||||
|
||||
|
||||
# Implementations of this file's macros:
|
||||
|
|
|
|||
|
|
@ -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.65)
|
||||
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.65, 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.65)") #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 "${GTSAM_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,46 @@
|
|||
###############################################################################
|
||||
# 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_INSTALL_MATLAB_TOOLBOX "Enable/Disable installation of matlab toolbox" 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)
|
||||
option(GTSAM_SLOW_BUT_CORRECT_BETWEENFACTOR "Use the slower but correct version of BetweenFactor" OFF)
|
||||
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()
|
||||
|
||||
# Set the default Python version. This is later updated in HandlePython.cmake.
|
||||
set(GTSAM_PYTHON_VERSION "Default" CACHE STRING "The version of Python to build the wrappers against.")
|
||||
|
|
@ -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,44 @@
|
|||
###############################################################################
|
||||
# Metis library
|
||||
|
||||
# For both system or bundle version, a cmake target "metis-gtsam-if" is defined (interface library)
|
||||
|
||||
# Dont try to use metis if GTSAM_SUPPORT_NESTED_DISSECTION is disabled:
|
||||
if (NOT GTSAM_SUPPORT_NESTED_DISSECTION)
|
||||
return()
|
||||
endif()
|
||||
|
||||
option(GTSAM_USE_SYSTEM_METIS "Find and use system-installed libmetis. If 'off', use the one bundled with GTSAM" OFF)
|
||||
|
||||
if(GTSAM_USE_SYSTEM_METIS)
|
||||
# Debian package: libmetis-dev
|
||||
|
||||
find_path(METIS_INCLUDE_DIR metis.h REQUIRED)
|
||||
find_library(METIS_LIBRARY metis REQUIRED)
|
||||
|
||||
if(METIS_INCLUDE_DIR AND METIS_LIBRARY)
|
||||
mark_as_advanced(METIS_INCLUDE_DIR)
|
||||
mark_as_advanced(METIS_LIBRARY)
|
||||
|
||||
add_library(metis-gtsam-if INTERFACE)
|
||||
target_include_directories(metis-gtsam-if BEFORE INTERFACE ${METIS_INCLUDE_DIR})
|
||||
target_link_libraries(metis-gtsam-if INTERFACE ${METIS_LIBRARY})
|
||||
endif()
|
||||
else()
|
||||
# Bundled version:
|
||||
option(GTSAM_BUILD_METIS_EXECUTABLES "Build metis library executables" OFF)
|
||||
add_subdirectory(${GTSAM_SOURCE_DIR}/gtsam/3rdparty/metis)
|
||||
|
||||
target_include_directories(metis-gtsam BEFORE PUBLIC
|
||||
$<BUILD_INTERFACE:${GTSAM_SOURCE_DIR}/gtsam/3rdparty/metis/include>
|
||||
$<BUILD_INTERFACE:${GTSAM_SOURCE_DIR}/gtsam/3rdparty/metis/libmetis>
|
||||
$<BUILD_INTERFACE:${GTSAM_SOURCE_DIR}/gtsam/3rdparty/metis/GKlib>
|
||||
$<INSTALL_INTERFACE:include/gtsam/3rdparty/metis/>
|
||||
)
|
||||
|
||||
add_library(metis-gtsam-if INTERFACE)
|
||||
target_link_libraries(metis-gtsam-if INTERFACE metis-gtsam)
|
||||
endif()
|
||||
|
||||
list(APPEND GTSAM_EXPORTED_TARGETS metis-gtsam-if)
|
||||
install(TARGETS metis-gtsam-if EXPORT GTSAM-exports ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||
|
|
@ -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,105 @@
|
|||
###############################################################################
|
||||
# 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})")
|
||||
print_config("Use System Metis" "${GTSAM_USE_SYSTEM_METIS}")
|
||||
|
||||
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,55 @@
|
|||
# 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")
|
||||
|
||||
if(${CMAKE_VERSION} VERSION_LESS "3.12.0")
|
||||
# Use older version of cmake's find_python
|
||||
find_package(PythonInterp)
|
||||
|
||||
if(NOT ${PYTHONINTERP_FOUND})
|
||||
message(
|
||||
FATAL_ERROR
|
||||
"Cannot find Python interpreter. Please install Python >= 3.6.")
|
||||
endif()
|
||||
|
||||
find_package(PythonLibs ${PYTHON_VERSION_STRING})
|
||||
|
||||
set(Python_VERSION_MAJOR ${PYTHON_VERSION_MAJOR})
|
||||
set(Python_VERSION_MINOR ${PYTHON_VERSION_MINOR})
|
||||
set(Python_EXECUTABLE ${PYTHON_EXECUTABLE})
|
||||
|
||||
else()
|
||||
# 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(Python_VERSION_MAJOR ${Python3_VERSION_MAJOR})
|
||||
set(Python_VERSION_MINOR ${Python3_VERSION_MINOR})
|
||||
|
||||
endif()
|
||||
|
||||
set(GTSAM_PYTHON_VERSION
|
||||
"${Python_VERSION_MAJOR}.${Python_VERSION_MINOR}"
|
||||
CACHE STRING "The version of Python to build the wrappers against."
|
||||
FORCE)
|
||||
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Check for build of Unstable modules
|
||||
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,32 @@
|
|||
###############################################################################
|
||||
if (GTSAM_WITH_TBB)
|
||||
# Find TBB
|
||||
find_package(TBB 4.4 COMPONENTS tbb tbbmalloc)
|
||||
|
||||
# Set up variables if we're using TBB
|
||||
if(TBB_FOUND)
|
||||
set(GTSAM_USE_TBB 1) # This will go into config.h
|
||||
|
||||
# if ((${TBB_VERSION} VERSION_GREATER "2021.1") OR (${TBB_VERSION} VERSION_EQUAL "2021.1"))
|
||||
# message(FATAL_ERROR "TBB version greater than 2021.1 (oneTBB API) is not yet supported. Use an older version instead.")
|
||||
# endif()
|
||||
|
||||
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()
|
||||
|
||||
endif()
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
# ----------------------------------------------------------------------------
|
||||
# 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)
|
||||
|
||||
if (NOT TARGET uninstall) # avoid duplicating this target
|
||||
add_custom_target(uninstall
|
||||
"${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake")
|
||||
else()
|
||||
add_custom_target(uninstall_gtsam
|
||||
"${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake")
|
||||
add_dependencies(uninstall uninstall_gtsam)
|
||||
endif()
|
||||
|
|
@ -67,32 +67,6 @@ Defines two useful functions for creating CTest unit tests. Also immediately cr
|
|||
an empty string "" if nothing needs to be excluded.
|
||||
linkLibraries: The list of libraries to link to.
|
||||
|
||||
## GtsamMatlabWrap
|
||||
|
||||
include(GtsamMatlabWrap)
|
||||
|
||||
Defines functions for generating MATLAB wrappers. Also immediately creates several CMake options for configuring the wrapper.
|
||||
|
||||
* `wrap_and_install_library(interfaceHeader linkLibraries extraIncludeDirs extraMexFlags)` Generates wrap code and compiles the wrapper.
|
||||
|
||||
Usage example:
|
||||
|
||||
`wrap_and_install_library("lba.h" "" "" "")`
|
||||
|
||||
Arguments:
|
||||
|
||||
interfaceHeader: The relative or absolute path to the wrapper interface
|
||||
definition file.
|
||||
linkLibraries: Any *additional* libraries to link. Your project library
|
||||
(e.g. `lba`), libraries it depends on, and any necessary
|
||||
MATLAB libraries will be linked automatically. So normally,
|
||||
leave this empty.
|
||||
extraIncludeDirs: Any *additional* include paths required by dependent
|
||||
libraries that have not already been added by
|
||||
include_directories. Again, normally, leave this empty.
|
||||
extraMexFlags: Any *additional* flags to pass to the compiler when building
|
||||
the wrap code. Normally, leave this empty.
|
||||
|
||||
## GtsamMakeConfigFile
|
||||
|
||||
include(GtsamMakeConfigFile)
|
||||
|
|
|
|||
|
|
@ -1,49 +0,0 @@
|
|||
# This file should be used as a template for creating new projects using the CMake tools
|
||||
# This project has the following features
|
||||
# - GTSAM linking
|
||||
# - Unit tests via CppUnitLite
|
||||
# - Scripts
|
||||
# - Automatic MATLAB wrapper generation
|
||||
|
||||
###################################################################################
|
||||
# To create your own project, replace "example" with the actual name of your project
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
project(example CXX C)
|
||||
|
||||
# Include GTSAM CMake tools
|
||||
find_package(GTSAMCMakeTools)
|
||||
include(GtsamBuildTypes) # Load build type flags and default to Debug mode
|
||||
include(GtsamTesting) # Easy functions for creating unit tests and scripts
|
||||
include(GtsamMatlabWrap) # Automatic MATLAB wrapper generation
|
||||
|
||||
# Ensure that local folder is searched before library folders
|
||||
include_directories(BEFORE "${PROJECT_SOURCE_DIR}")
|
||||
|
||||
###################################################################################
|
||||
# Find GTSAM components
|
||||
find_package(GTSAM REQUIRED) # Uses installed package
|
||||
# Note: Since Jan-2019, GTSAMConfig.cmake defines exported CMake targets
|
||||
# that automatically do include the include_directories() without the need
|
||||
# to call include_directories(), just target_link_libraries(NAME gtsam)
|
||||
#include_directories(${GTSAM_INCLUDE_DIR})
|
||||
|
||||
###################################################################################
|
||||
# Build static library from common sources
|
||||
set(CONVENIENCE_LIB_NAME ${PROJECT_NAME})
|
||||
add_library(${CONVENIENCE_LIB_NAME} SHARED example/PrintExamples.h example/PrintExamples.cpp)
|
||||
target_link_libraries(${CONVENIENCE_LIB_NAME} gtsam)
|
||||
|
||||
# Install library
|
||||
install(TARGETS ${CONVENIENCE_LIB_NAME} LIBRARY DESTINATION lib ARCHIVE DESTINATION lib RUNTIME DESTINATION bin)
|
||||
|
||||
###################################################################################
|
||||
# Build tests (CMake tracks the dependecy to link with GTSAM through our project's static library)
|
||||
gtsamAddTestsGlob("example" "tests/test*.cpp" "" "${CONVENIENCE_LIB_NAME}")
|
||||
|
||||
###################################################################################
|
||||
# Build scripts (CMake tracks the dependecy to link with GTSAM through our project's static library)
|
||||
gtsamAddExamplesGlob("*.cpp" "" "${CONVENIENCE_LIB_NAME}")
|
||||
|
||||
###################################################################################
|
||||
# Build MATLAB wrapper (CMake tracks the dependecy to link with GTSAM through our project's static library)
|
||||
wrap_and_install_library("example.h" "${CONVENIENCE_LIB_NAME}" "" "")
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
# MATLAB Wrapper Example Project
|
||||
|
||||
This project serves as a lightweight example for demonstrating how to wrap C++ code in MATLAB using GTSAM.
|
||||
|
||||
## Compiling
|
||||
|
||||
We follow the regular build procedure inside the `example_project` directory:
|
||||
|
||||
```sh
|
||||
mkdir build && cd build
|
||||
cmake ..
|
||||
make -j8
|
||||
sudo make install
|
||||
|
||||
sudo ldconfig # ensures the shared object file generated is correctly loaded
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
Now you can open MATLAB and add the `gtsam_toolbox` to the MATLAB path
|
||||
|
||||
```matlab
|
||||
addpath('/usr/local/gtsam_toolbox')
|
||||
```
|
||||
|
||||
At this point you are ready to run the example project. Starting from the `example_project` directory inside MATLAB, simply run code like regular MATLAB, e.g.
|
||||
|
||||
```matlab
|
||||
pe = example.PrintExamples();
|
||||
pe.sayHello();
|
||||
pe.sayGoodbye();
|
||||
```
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
|
||||
* 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
|
||||
|
||||
* -------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* @file SayGoodbye.cpp
|
||||
* @brief Example script for example project
|
||||
* @author Richard Roberts
|
||||
*/
|
||||
|
||||
#include <example/PrintExamples.h>
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
example::PrintExamples().sayGoodbye();
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
|
||||
* 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
|
||||
|
||||
* -------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* @file SayHello.cpp
|
||||
* @brief Example script for example project
|
||||
* @author Richard Roberts
|
||||
*/
|
||||
|
||||
#include <example/PrintExamples.h>
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
example::PrintExamples().sayHello();
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
|
||||
* 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
|
||||
|
||||
* -------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* @file example.h
|
||||
* @brief Example wrapper interface file
|
||||
* @author Richard Roberts
|
||||
*/
|
||||
|
||||
// This is an interface file for automatic MATLAB wrapper generation. See
|
||||
// gtsam.h for full documentation and more examples.
|
||||
|
||||
#include <example/PrintExamples.h>
|
||||
|
||||
namespace example {
|
||||
|
||||
class PrintExamples {
|
||||
PrintExamples();
|
||||
void sayHello() const;
|
||||
void sayGoodbye() const;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
|
||||
* 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
|
||||
|
||||
* -------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* @file print_examples.cpp
|
||||
* @brief Example library file
|
||||
* @author Richard Roberts
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <example/PrintExamples.h>
|
||||
|
||||
namespace example {
|
||||
|
||||
void PrintExamples::sayHello() const {
|
||||
std::cout << internal::getHelloString() << std::endl;
|
||||
}
|
||||
|
||||
void PrintExamples::sayGoodbye() const {
|
||||
std::cout << internal::getGoodbyeString() << std::endl;
|
||||
}
|
||||
|
||||
namespace internal {
|
||||
|
||||
std::string getHelloString() {
|
||||
return "Hello!";
|
||||
}
|
||||
|
||||
std::string getGoodbyeString() {
|
||||
return "See you soon!";
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
||||
} // namespace example
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
|
||||
* 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
|
||||
|
||||
* -------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* @file print_examples.h
|
||||
* @brief Example library file
|
||||
* @author Richard Roberts
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
namespace example {
|
||||
|
||||
class PrintExamples {
|
||||
public:
|
||||
/// Print a greeting
|
||||
void sayHello() const;
|
||||
|
||||
/// Print a farewell
|
||||
void sayGoodbye() const;
|
||||
};
|
||||
|
||||
namespace internal {
|
||||
|
||||
std::string getHelloString();
|
||||
|
||||
std::string getGoodbyeString();
|
||||
|
||||
} // namespace internal
|
||||
|
||||
} // namespace example
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
|
||||
* 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
|
||||
|
||||
* -------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* @file testExample.cpp
|
||||
* @brief Unit tests for example
|
||||
* @author Richard Roberts
|
||||
*/
|
||||
|
||||
#include <CppUnitLite/TestHarness.h>
|
||||
|
||||
#include <gtsam/base/TestableAssertions.h>
|
||||
|
||||
#include <example/PrintExamples.h>
|
||||
|
||||
using namespace gtsam;
|
||||
|
||||
TEST(Example, HelloString) {
|
||||
const std::string expectedString = "Hello!";
|
||||
EXPECT(assert_equal(expectedString, example::internal::getHelloString()));
|
||||
}
|
||||
|
||||
TEST(Example, GoodbyeString) {
|
||||
const std::string expectedString = "See you soon!";
|
||||
EXPECT(assert_equal(expectedString, example::internal::getGoodbyeString()));
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
int main() {
|
||||
TestResult tr;
|
||||
return TestRegistry::runAllTests(tr);
|
||||
}
|
||||
/* ************************************************************************* */
|
||||
|
||||
|
||||
|
|
@ -22,18 +22,19 @@ if (GTSAM_BUILD_DOCS)
|
|||
|
||||
# GTSAM core subfolders
|
||||
set(gtsam_doc_subdirs
|
||||
gtsam/base
|
||||
gtsam/discrete
|
||||
gtsam/geometry
|
||||
gtsam/inference
|
||||
gtsam/linear
|
||||
gtsam/navigation
|
||||
gtsam/nonlinear
|
||||
gtsam/sam
|
||||
gtsam/sfm
|
||||
gtsam/slam
|
||||
gtsam/smart
|
||||
gtsam/symbolic
|
||||
gtsam/base
|
||||
gtsam/basis
|
||||
gtsam/discrete
|
||||
gtsam/geometry
|
||||
gtsam/inference
|
||||
gtsam/linear
|
||||
gtsam/navigation
|
||||
gtsam/nonlinear
|
||||
gtsam/sam
|
||||
gtsam/sfm
|
||||
gtsam/slam
|
||||
gtsam/smart
|
||||
gtsam/symbolic
|
||||
gtsam
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,10 @@ public:
|
|||
Vector evaluateError(const Pose2& q,
|
||||
boost::optional<Matrix&> H = boost::none) const
|
||||
{
|
||||
if (H) (*H) = (Matrix(2,3)<< 1.0,0.0,0.0, 0.0,1.0,0.0).finished();
|
||||
const Rot2& R = q.rotation();
|
||||
if (H) (*H) = (gtsam::Matrix(2, 3) <<
|
||||
R.c(), -R.s(), 0.0,
|
||||
R.s(), R.c(), 0.0).finished();
|
||||
return (Vector(2) << q.x() - mx_, q.y() - my_).finished();
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1188,7 +1188,7 @@ USE_MATHJAX = YES
|
|||
# MathJax, but it is strongly recommended to install a local copy of MathJax
|
||||
# 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
|
||||
# names that should be enabled during MathJax rendering.
|
||||
|
|
|
|||
|
|
@ -2452,7 +2452,7 @@ First transform
|
|||
, and then rotate back:
|
||||
\begin_inset Formula
|
||||
\[
|
||||
q=Re^{\Skew{\omega}}R^{T}
|
||||
q=Re^{\Skew{\omega}}R^{T}p
|
||||
\]
|
||||
|
||||
\end_inset
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -1,7 +1,9 @@
|
|||
#LyX 2.1 created this file. For more info see http://www.lyx.org/
|
||||
\lyxformat 474
|
||||
#LyX 2.2 created this file. For more info see http://www.lyx.org/
|
||||
\lyxformat 508
|
||||
\begin_document
|
||||
\begin_header
|
||||
\save_transient_properties true
|
||||
\origin unavailable
|
||||
\textclass article
|
||||
\begin_preamble
|
||||
\usepackage{times}
|
||||
|
|
@ -50,16 +52,16 @@
|
|||
\language_package default
|
||||
\inputencoding auto
|
||||
\fontencoding T1
|
||||
\font_roman ae
|
||||
\font_sans default
|
||||
\font_typewriter default
|
||||
\font_math auto
|
||||
\font_roman "ae" "default"
|
||||
\font_sans "default" "default"
|
||||
\font_typewriter "default" "default"
|
||||
\font_math "auto" "auto"
|
||||
\font_default_family rmdefault
|
||||
\use_non_tex_fonts false
|
||||
\font_sc false
|
||||
\font_osf false
|
||||
\font_sf_scale 100
|
||||
\font_tt_scale 100
|
||||
\font_sf_scale 100 100
|
||||
\font_tt_scale 100 100
|
||||
\graphics default
|
||||
\default_output_format default
|
||||
\output_sync 0
|
||||
|
|
@ -1061,7 +1063,7 @@ noindent
|
|||
\begin_layout Subsection
|
||||
\begin_inset CommandInset label
|
||||
LatexCommand label
|
||||
name "sub:Full-Posterior-Inference"
|
||||
name "subsec:Full-Posterior-Inference"
|
||||
|
||||
\end_inset
|
||||
|
||||
|
|
@ -1272,7 +1274,7 @@ ing to odometry measurements.
|
|||
(see Section
|
||||
\begin_inset CommandInset ref
|
||||
LatexCommand ref
|
||||
reference "sub:Full-Posterior-Inference"
|
||||
reference "subsec:Full-Posterior-Inference"
|
||||
|
||||
\end_inset
|
||||
|
||||
|
|
@ -1469,7 +1471,7 @@ GPS-like
|
|||
\begin_inset CommandInset include
|
||||
LatexCommand lstinputlisting
|
||||
filename "Code/LocalizationFactor.cpp"
|
||||
lstparams "aboveskip=10pt,basicstyle={\\ttfamily\\small},caption={Excerpt from examples/LocalizationExample.cpp},captionpos=b,frame=single,identifierstyle={\\bfseries},label={listing:LocalizationFactor},language={C++},numbers=left"
|
||||
lstparams "aboveskip=10pt,basicstyle={\\ttfamily\\small},captionpos=b,frame=single,identifierstyle={\\bfseries},language={C++},numbers=left,caption={Excerpt from examples/LocalizationExample.cpp},label={listing:LocalizationFactor}"
|
||||
|
||||
\end_inset
|
||||
|
||||
|
|
@ -1590,15 +1592,15 @@ q_{y}
|
|||
\begin_inset Formula $2\times3$
|
||||
\end_inset
|
||||
|
||||
matrix:
|
||||
matrix in tangent space which is the same the as the rotation matrix:
|
||||
\end_layout
|
||||
|
||||
\begin_layout Standard
|
||||
\begin_inset Formula
|
||||
\[
|
||||
H=\left[\begin{array}{ccc}
|
||||
1 & 0 & 0\\
|
||||
0 & 1 & 0
|
||||
\cos(q_{\theta}) & -\sin(q_{\theta}) & 0\\
|
||||
\sin(q_{\theta}) & \cos(q_{\theta}) & 0
|
||||
\end{array}\right]
|
||||
\]
|
||||
|
||||
|
|
@ -1750,7 +1752,7 @@ global
|
|||
The marginals can be recovered exactly as in Section
|
||||
\begin_inset CommandInset ref
|
||||
LatexCommand ref
|
||||
reference "sub:Full-Posterior-Inference"
|
||||
reference "subsec:Full-Posterior-Inference"
|
||||
|
||||
\end_inset
|
||||
|
||||
|
|
@ -1770,7 +1772,7 @@ filename "Code/LocalizationOutput5.txt"
|
|||
Comparing this with the covariance matrices in Section
|
||||
\begin_inset CommandInset ref
|
||||
LatexCommand ref
|
||||
reference "sub:Full-Posterior-Inference"
|
||||
reference "subsec:Full-Posterior-Inference"
|
||||
|
||||
\end_inset
|
||||
|
||||
|
|
|
|||
BIN
doc/gtsam.pdf
BIN
doc/gtsam.pdf
Binary file not shown.
388
doc/math.lyx
388
doc/math.lyx
|
|
@ -5082,6 +5082,394 @@ reference "ex:projection"
|
|||
\end_inset
|
||||
|
||||
|
||||
\end_layout
|
||||
|
||||
\begin_layout Subsection
|
||||
Derivative of Adjoint
|
||||
\begin_inset CommandInset label
|
||||
LatexCommand label
|
||||
name "subsec:pose3_adjoint_deriv"
|
||||
|
||||
\end_inset
|
||||
|
||||
|
||||
\end_layout
|
||||
|
||||
\begin_layout Standard
|
||||
Consider
|
||||
\begin_inset Formula $f:SE(3)\times\mathbb{R}^{6}\rightarrow\mathbb{R}^{6}$
|
||||
\end_inset
|
||||
|
||||
is defined as
|
||||
\begin_inset Formula $f(T,\xi_{b})=Ad_{T}\hat{\xi}_{b}$
|
||||
\end_inset
|
||||
|
||||
.
|
||||
The derivative is notated (see Section
|
||||
\begin_inset CommandInset ref
|
||||
LatexCommand ref
|
||||
reference "sec:Derivatives-of-Actions"
|
||||
plural "false"
|
||||
caps "false"
|
||||
noprefix "false"
|
||||
|
||||
\end_inset
|
||||
|
||||
):
|
||||
\end_layout
|
||||
|
||||
\begin_layout Standard
|
||||
\begin_inset Formula
|
||||
\[
|
||||
Df_{(T,\xi_{b})}(\xi,\delta\xi_{b})=D_{1}f_{(T,\xi_{b})}(\xi)+D_{2}f_{(T,\xi_{b})}(\delta\xi_{b})
|
||||
\]
|
||||
|
||||
\end_inset
|
||||
|
||||
First, computing
|
||||
\begin_inset Formula $D_{2}f_{(T,\xi_{b})}(\xi_{b})$
|
||||
\end_inset
|
||||
|
||||
is easy, as its matrix is simply
|
||||
\begin_inset Formula $Ad_{T}$
|
||||
\end_inset
|
||||
|
||||
:
|
||||
\end_layout
|
||||
|
||||
\begin_layout Standard
|
||||
\begin_inset Formula
|
||||
\[
|
||||
f(T,\xi_{b}+\delta\xi_{b})=Ad_{T}(\widehat{\xi_{b}+\delta\xi_{b}})=Ad_{T}(\hat{\xi}_{b})+Ad_{T}(\delta\hat{\xi}_{b})
|
||||
\]
|
||||
|
||||
\end_inset
|
||||
|
||||
|
||||
\end_layout
|
||||
|
||||
\begin_layout Standard
|
||||
\begin_inset Formula
|
||||
\[
|
||||
D_{2}f_{(T,\xi_{b})}(\xi_{b})=Ad_{T}
|
||||
\]
|
||||
|
||||
\end_inset
|
||||
|
||||
We will derive
|
||||
\begin_inset Formula $D_{1}f_{(T,\xi_{b})}(\xi)$
|
||||
\end_inset
|
||||
|
||||
using two approaches.
|
||||
In the first, we'll define
|
||||
\begin_inset Formula $g(T,\xi)\triangleq T\exp\hat{\xi}$
|
||||
\end_inset
|
||||
|
||||
.
|
||||
From Section
|
||||
\begin_inset CommandInset ref
|
||||
LatexCommand ref
|
||||
reference "sec:Derivatives-of-Actions"
|
||||
plural "false"
|
||||
caps "false"
|
||||
noprefix "false"
|
||||
|
||||
\end_inset
|
||||
|
||||
,
|
||||
\end_layout
|
||||
|
||||
\begin_layout Standard
|
||||
\begin_inset Formula
|
||||
\begin{align*}
|
||||
D_{2}g_{(T,\xi)}(\xi) & =T\hat{\xi}\\
|
||||
D_{2}g_{(T,\xi)}^{-1}(\xi) & =-\hat{\xi}T^{-1}
|
||||
\end{align*}
|
||||
|
||||
\end_inset
|
||||
|
||||
Now we can use the definition of the Adjoint representation
|
||||
\begin_inset Formula $Ad_{g}\hat{\xi}=g\hat{\xi}g^{-1}$
|
||||
\end_inset
|
||||
|
||||
(aka conjugation by
|
||||
\begin_inset Formula $g$
|
||||
\end_inset
|
||||
|
||||
) then apply product rule and simplify:
|
||||
\end_layout
|
||||
|
||||
\begin_layout Standard
|
||||
\begin_inset Formula
|
||||
\begin{align*}
|
||||
D_{1}f_{(T,\xi_{b})}(\xi)=D_{1}\left(Ad_{T\exp(\hat{\xi})}\hat{\xi}_{b}\right)(\xi) & =D_{1}\left(g\hat{\xi}_{b}g^{-1}\right)(\xi)\\
|
||||
& =\left(D_{2}g_{(T,\xi)}(\xi)\right)\hat{\xi}_{b}g^{-1}(T,0)+g(T,0)\hat{\xi}_{b}\left(D_{2}g_{(T,\xi)}^{-1}(\xi)\right)\\
|
||||
& =T\hat{\xi}\hat{\xi}_{b}T^{-1}-T\hat{\xi}_{b}\hat{\xi}T^{-1}\\
|
||||
& =T\left(\hat{\xi}\hat{\xi}_{b}-\hat{\xi}_{b}\hat{\xi}\right)T^{-1}\\
|
||||
& =Ad_{T}(ad_{\hat{\xi}}\hat{\xi}_{b})\\
|
||||
& =-Ad_{T}(ad_{\hat{\xi}_{b}}\hat{\xi})\\
|
||||
D_{1}F_{(T,\xi_{b})} & =-(Ad_{T})(ad_{\hat{\xi}_{b}})
|
||||
\end{align*}
|
||||
|
||||
\end_inset
|
||||
|
||||
Where
|
||||
\begin_inset Formula $ad_{\hat{\xi}}:\mathfrak{g}\rightarrow\mathfrak{g}$
|
||||
\end_inset
|
||||
|
||||
is the adjoint map of the lie algebra.
|
||||
\end_layout
|
||||
|
||||
\begin_layout Standard
|
||||
The second, perhaps more intuitive way of deriving
|
||||
\begin_inset Formula $D_{1}f_{(T,\xi_{b})}(\xi_{b})$
|
||||
\end_inset
|
||||
|
||||
, would be to use the fact that the derivative at the origin
|
||||
\begin_inset Formula $D_{1}Ad_{I}\hat{\xi}_{b}=ad_{\hat{\xi}_{b}}$
|
||||
\end_inset
|
||||
|
||||
by definition of the adjoint
|
||||
\begin_inset Formula $ad_{\xi}$
|
||||
\end_inset
|
||||
|
||||
.
|
||||
Then applying the property
|
||||
\begin_inset Formula $Ad_{AB}=Ad_{A}Ad_{B}$
|
||||
\end_inset
|
||||
|
||||
,
|
||||
\end_layout
|
||||
|
||||
\begin_layout Standard
|
||||
\begin_inset Formula
|
||||
\[
|
||||
D_{1}Ad_{T}\hat{\xi}_{b}(\xi)=D_{1}Ad_{T*I}\hat{\xi}_{b}(\xi)=Ad_{T}\left(D_{1}Ad_{I}\hat{\xi}_{b}(\xi)\right)=Ad_{T}\left(ad_{\hat{\xi}}(\hat{\xi}_{b})\right)=-Ad_{T}\left(ad_{\hat{\xi}_{b}}(\hat{\xi})\right)
|
||||
\]
|
||||
|
||||
\end_inset
|
||||
|
||||
|
||||
\end_layout
|
||||
|
||||
\begin_layout Subsection
|
||||
Derivative of AdjointTranspose
|
||||
\end_layout
|
||||
|
||||
\begin_layout Standard
|
||||
The transpose of the Adjoint,
|
||||
\family roman
|
||||
\series medium
|
||||
\shape up
|
||||
\size normal
|
||||
\emph off
|
||||
\bar no
|
||||
\strikeout off
|
||||
\xout off
|
||||
\uuline off
|
||||
\uwave off
|
||||
\noun off
|
||||
\color none
|
||||
|
||||
\begin_inset Formula $Ad_{T}^{T}:\mathfrak{g^{*}\rightarrow g^{*}}$
|
||||
\end_inset
|
||||
|
||||
, is useful as a way to change the reference frame of vectors in the dual
|
||||
space
|
||||
\family default
|
||||
\series default
|
||||
\shape default
|
||||
\size default
|
||||
\emph default
|
||||
\bar default
|
||||
\strikeout default
|
||||
\xout default
|
||||
\uuline default
|
||||
\uwave default
|
||||
\noun default
|
||||
\color inherit
|
||||
(note the
|
||||
\begin_inset Formula $^{*}$
|
||||
\end_inset
|
||||
|
||||
denoting that we are now in the dual space)
|
||||
\family roman
|
||||
\series medium
|
||||
\shape up
|
||||
\size normal
|
||||
\emph off
|
||||
\bar no
|
||||
\strikeout off
|
||||
\xout off
|
||||
\uuline off
|
||||
\uwave off
|
||||
\noun off
|
||||
\color none
|
||||
.
|
||||
To be more concrete, where
|
||||
\family default
|
||||
\series default
|
||||
\shape default
|
||||
\size default
|
||||
\emph default
|
||||
\bar default
|
||||
\strikeout default
|
||||
\xout default
|
||||
\uuline default
|
||||
\uwave default
|
||||
\noun default
|
||||
\color inherit
|
||||
as
|
||||
\begin_inset Formula $Ad_{T}\hat{\xi}_{b}$
|
||||
\end_inset
|
||||
|
||||
converts the
|
||||
\emph on
|
||||
twist
|
||||
\emph default
|
||||
|
||||
\family roman
|
||||
\series medium
|
||||
\shape up
|
||||
\size normal
|
||||
\emph off
|
||||
\bar no
|
||||
\strikeout off
|
||||
\xout off
|
||||
\uuline off
|
||||
\uwave off
|
||||
\noun off
|
||||
\color none
|
||||
|
||||
\begin_inset Formula $\xi_{b}$
|
||||
\end_inset
|
||||
|
||||
from the
|
||||
\begin_inset Formula $T$
|
||||
\end_inset
|
||||
|
||||
frame,
|
||||
\family default
|
||||
\series default
|
||||
\shape default
|
||||
\size default
|
||||
\emph default
|
||||
\bar default
|
||||
\strikeout default
|
||||
\xout default
|
||||
\uuline default
|
||||
\uwave default
|
||||
\noun default
|
||||
\color inherit
|
||||
|
||||
\family roman
|
||||
\series medium
|
||||
\shape up
|
||||
\size normal
|
||||
\emph off
|
||||
\bar no
|
||||
\strikeout off
|
||||
\xout off
|
||||
\uuline off
|
||||
\uwave off
|
||||
\noun off
|
||||
\color none
|
||||
|
||||
\begin_inset Formula $Ad_{T}^{T}\hat{\xi}_{b}^{*}$
|
||||
\end_inset
|
||||
|
||||
converts the
|
||||
\family default
|
||||
\series default
|
||||
\shape default
|
||||
\size default
|
||||
\emph on
|
||||
\bar default
|
||||
\strikeout default
|
||||
\xout default
|
||||
\uuline default
|
||||
\uwave default
|
||||
\noun default
|
||||
\color inherit
|
||||
wrench
|
||||
\emph default
|
||||
|
||||
\family roman
|
||||
\series medium
|
||||
\shape up
|
||||
\size normal
|
||||
\emph off
|
||||
\bar no
|
||||
\strikeout off
|
||||
\xout off
|
||||
\uuline off
|
||||
\uwave off
|
||||
\noun off
|
||||
\color none
|
||||
|
||||
\begin_inset Formula $\xi_{b}^{*}$
|
||||
\end_inset
|
||||
|
||||
from the
|
||||
\begin_inset Formula $T$
|
||||
\end_inset
|
||||
|
||||
frame
|
||||
\family default
|
||||
\series default
|
||||
\shape default
|
||||
\size default
|
||||
\emph default
|
||||
\bar default
|
||||
\strikeout default
|
||||
\xout default
|
||||
\uuline default
|
||||
\uwave default
|
||||
\noun default
|
||||
\color inherit
|
||||
.
|
||||
It's difficult to apply a similar derivation as in Section
|
||||
\begin_inset CommandInset ref
|
||||
LatexCommand ref
|
||||
reference "subsec:pose3_adjoint_deriv"
|
||||
plural "false"
|
||||
caps "false"
|
||||
noprefix "false"
|
||||
|
||||
\end_inset
|
||||
|
||||
for the derivative of
|
||||
\begin_inset Formula $Ad_{T}^{T}\hat{\xi}_{b}^{*}$
|
||||
\end_inset
|
||||
|
||||
because
|
||||
\begin_inset Formula $Ad_{T}^{T}$
|
||||
\end_inset
|
||||
|
||||
cannot be naturally defined as a conjugation, so we resort to crunching
|
||||
through the algebra.
|
||||
The details are omitted but the result is a form that vaguely resembles
|
||||
(but does not exactly match)
|
||||
\begin_inset Formula $ad(Ad_{T}^{T}\hat{\xi}_{b}^{*})$
|
||||
\end_inset
|
||||
|
||||
:
|
||||
\end_layout
|
||||
|
||||
\begin_layout Standard
|
||||
\begin_inset Formula
|
||||
\begin{align*}
|
||||
\begin{bmatrix}\omega_{T}\\
|
||||
v_{T}
|
||||
\end{bmatrix}^{*} & \triangleq Ad_{T}^{T}\hat{\xi}_{b}^{*}\\
|
||||
D_{1}Ad_{T}^{T}\hat{\xi}_{b}^{*}(\xi) & =\begin{bmatrix}\hat{\omega}_{T} & \hat{v}_{T}\\
|
||||
\hat{v}_{T} & 0
|
||||
\end{bmatrix}
|
||||
\end{align*}
|
||||
|
||||
\end_inset
|
||||
|
||||
|
||||
\end_layout
|
||||
|
||||
\begin_layout Subsection
|
||||
|
|
|
|||
BIN
doc/math.pdf
BIN
doc/math.pdf
Binary file not shown.
|
|
@ -1,6 +1,57 @@
|
|||
# Instructions
|
||||
|
||||
Build all docker images, in order:
|
||||
# Images on Docker Hub
|
||||
|
||||
There are 4 images available on https://hub.docker.com/orgs/borglab/repositories:
|
||||
|
||||
- `borglab/ubuntu-boost-tbb`: 18.06 Linux (nicknamed `bionic`) base image, with Boost and TBB installed.
|
||||
- `borglab/ubuntu-gtsam`: GTSAM Release version installed in `/usr/local`.
|
||||
- `borglab/ubuntu-gtsam-python`: installed GTSAM with python wrapper.
|
||||
- `borglab/ubuntu-gtsam-python-vnc`: image with GTSAM+python wrapper that will run a VNC server to connect to.
|
||||
|
||||
# Using the images
|
||||
|
||||
## Just GTSAM
|
||||
|
||||
To start the Docker image, execute
|
||||
```bash
|
||||
docker run -it borglab/ubuntu-gtsam:bionic
|
||||
```
|
||||
after you will find yourself in a bash shell, in the directory `/usr/src/gtsam/build`.
|
||||
## GTSAM with Python wrapper
|
||||
|
||||
To use GTSAM via the python wrapper, similarly execute
|
||||
```bash
|
||||
docker run -it borglab/ubuntu-gtsam-python:bionic
|
||||
```
|
||||
and then launch `python3`:
|
||||
```bash
|
||||
python3
|
||||
>>> import gtsam
|
||||
>>> gtsam.Pose2(1,2,3)
|
||||
(1, 2, 3)
|
||||
```
|
||||
|
||||
## GTSAM with Python wrapper and VNC
|
||||
|
||||
First, start the docker image, which will run a VNC server on port 5900:
|
||||
```bash
|
||||
docker run -p 5900:5900 borglab/ubuntu-gtsam-python-vnc:bionic
|
||||
```
|
||||
|
||||
Then open a remote VNC X client, for example:
|
||||
|
||||
### Linux
|
||||
```bash
|
||||
sudo apt-get install tigervnc-viewer
|
||||
xtigervncviewer :5900
|
||||
```
|
||||
### Mac
|
||||
The Finder's "Connect to Server..." with `vnc://127.0.0.1` does not work, for some reason. Using the free [VNC Viewer](https://www.realvnc.com/en/connect/download/viewer/), enter `0.0.0.0:5900` as the server.
|
||||
|
||||
# Re-building the images locally
|
||||
|
||||
To build all docker images, in order:
|
||||
|
||||
```bash
|
||||
(cd ubuntu-boost-tbb && ./build.sh)
|
||||
|
|
@ -9,13 +60,4 @@ Build all docker images, in order:
|
|||
(cd ubuntu-gtsam-python-vnc && ./build.sh)
|
||||
```
|
||||
|
||||
Then launch with:
|
||||
|
||||
docker run -p 5900:5900 dellaert/ubuntu-gtsam-python-vnc:bionic
|
||||
|
||||
Then open a remote VNC X client, for example:
|
||||
|
||||
sudo apt-get install tigervnc-viewer
|
||||
xtigervncviewer :5900
|
||||
|
||||
|
||||
Note: building GTSAM can take a lot of memory because of the heavy templating. It is advisable to give Docker enough resources, e.g., 8GB, to avoid OOM errors while compiling.
|
||||
|
|
@ -1,3 +1,3 @@
|
|||
# Build command for Docker image
|
||||
# TODO(dellaert): use docker compose and/or cmake
|
||||
docker build --no-cache -t dellaert/ubuntu-boost-tbb:bionic .
|
||||
docker build --no-cache -t borglab/ubuntu-boost-tbb:bionic .
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# This GTSAM image connects to the host X-server via VNC to provide a Graphical User Interface for interaction.
|
||||
|
||||
# Get the base Ubuntu/GTSAM image from Docker Hub
|
||||
FROM dellaert/ubuntu-gtsam-python:bionic
|
||||
FROM borglab/ubuntu-gtsam-python:bionic
|
||||
|
||||
# Things needed to get a python GUI
|
||||
ENV DEBIAN_FRONTEND noninteractive
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
# Build command for Docker image
|
||||
# TODO(dellaert): use docker compose and/or cmake
|
||||
# Needs to be run in docker/ubuntu-gtsam-python-vnc directory
|
||||
docker build -t dellaert/ubuntu-gtsam-python-vnc:bionic .
|
||||
docker build -t borglab/ubuntu-gtsam-python-vnc:bionic .
|
||||
|
|
|
|||
|
|
@ -2,4 +2,4 @@
|
|||
docker run -it \
|
||||
--workdir="/usr/src/gtsam" \
|
||||
-p 5900:5900 \
|
||||
dellaert/ubuntu-gtsam-python-vnc:bionic
|
||||
borglab/ubuntu-gtsam-python-vnc:bionic
|
||||
|
|
@ -1,15 +1,15 @@
|
|||
# GTSAM Ubuntu image with Python wrapper support.
|
||||
|
||||
# Get the base Ubuntu/GTSAM image from Docker Hub
|
||||
FROM dellaert/ubuntu-gtsam:bionic
|
||||
FROM borglab/ubuntu-gtsam:bionic
|
||||
|
||||
# Install pip
|
||||
RUN apt-get install -y python3-pip python3-dev
|
||||
|
||||
# Install python wrapper requirements
|
||||
RUN python3 -m pip install -U -r /usr/src/gtsam/cython/requirements.txt
|
||||
RUN python3 -m pip install -U -r /usr/src/gtsam/python/requirements.txt
|
||||
|
||||
# Run cmake again, now with cython toolbox on
|
||||
# Run cmake again, now with python toolbox on
|
||||
WORKDIR /usr/src/gtsam/build
|
||||
RUN cmake \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
|
|
@ -17,15 +17,17 @@ RUN cmake \
|
|||
-DGTSAM_BUILD_EXAMPLES_ALWAYS=OFF \
|
||||
-DGTSAM_BUILD_TIMING_ALWAYS=OFF \
|
||||
-DGTSAM_BUILD_TESTS=OFF \
|
||||
-DGTSAM_INSTALL_CYTHON_TOOLBOX=ON \
|
||||
-DGTSAM_BUILD_PYTHON=ON \
|
||||
-DGTSAM_PYTHON_VERSION=3\
|
||||
..
|
||||
|
||||
# Build again, as ubuntu-gtsam image cleaned
|
||||
RUN make -j4 install && make clean
|
||||
RUN make -j4 install
|
||||
RUN make python-install
|
||||
RUN make clean
|
||||
|
||||
# Needed to run python wrapper:
|
||||
RUN echo 'export PYTHONPATH=/usr/local/cython/:$PYTHONPATH' >> /root/.bashrc
|
||||
RUN echo 'export PYTHONPATH=/usr/local/python/:$PYTHONPATH' >> /root/.bashrc
|
||||
|
||||
# Run bash
|
||||
CMD ["bash"]
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
# Build command for Docker image
|
||||
# TODO(dellaert): use docker compose and/or cmake
|
||||
docker build --no-cache -t dellaert/ubuntu-gtsam-python:bionic .
|
||||
docker build --no-cache -t borglab/ubuntu-gtsam-python:bionic .
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# Ubuntu image with GTSAM installed. Configured with Boost and TBB support.
|
||||
|
||||
# Get the base Ubuntu image from Docker Hub
|
||||
FROM dellaert/ubuntu-boost-tbb:bionic
|
||||
FROM borglab/ubuntu-boost-tbb:bionic
|
||||
|
||||
# Install git
|
||||
RUN apt-get update && \
|
||||
|
|
@ -23,7 +23,6 @@ RUN cmake \
|
|||
-DGTSAM_BUILD_EXAMPLES_ALWAYS=OFF \
|
||||
-DGTSAM_BUILD_TIMING_ALWAYS=OFF \
|
||||
-DGTSAM_BUILD_TESTS=OFF \
|
||||
-DGTSAM_INSTALL_CYTHON_TOOLBOX=OFF \
|
||||
..
|
||||
|
||||
# Build
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
# Build command for Docker image
|
||||
# TODO(dellaert): use docker compose and/or cmake
|
||||
docker build --no-cache -t dellaert/ubuntu-gtsam:bionic .
|
||||
docker build --no-cache -t borglab/ubuntu-gtsam:bionic .
|
||||
|
|
|
|||
|
|
@ -0,0 +1,304 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
|
||||
* 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
|
||||
|
||||
* -------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* @file CombinedImuFactorsExample
|
||||
* @brief Test example for using GTSAM ImuCombinedFactor
|
||||
* navigation code.
|
||||
* @author Varun Agrawal
|
||||
*/
|
||||
|
||||
/**
|
||||
* Example of use of the CombinedImuFactor in
|
||||
* conjunction with GPS
|
||||
* - we read IMU and GPS data from a CSV file, with the following format:
|
||||
* A row starting with "i" is the first initial position formatted with
|
||||
* N, E, D, qx, qY, qZ, qW, velN, velE, velD
|
||||
* A row starting with "0" is an imu measurement
|
||||
* (body frame - Forward, Right, Down)
|
||||
* linAccX, linAccY, linAccZ, angVelX, angVelY, angVelX
|
||||
* A row starting with "1" is a gps correction formatted with
|
||||
* N, E, D, qX, qY, qZ, qW
|
||||
* Note that for GPS correction, we're only using the position not the
|
||||
* rotation. The rotation is provided in the file for ground truth comparison.
|
||||
*
|
||||
* See usage: ./CombinedImuFactorsExample --help
|
||||
*/
|
||||
|
||||
#include <boost/program_options.hpp>
|
||||
|
||||
// GTSAM related includes.
|
||||
#include <gtsam/inference/Symbol.h>
|
||||
#include <gtsam/navigation/CombinedImuFactor.h>
|
||||
#include <gtsam/navigation/GPSFactor.h>
|
||||
#include <gtsam/navigation/ImuFactor.h>
|
||||
#include <gtsam/nonlinear/LevenbergMarquardtOptimizer.h>
|
||||
#include <gtsam/nonlinear/NonlinearFactorGraph.h>
|
||||
#include <gtsam/slam/BetweenFactor.h>
|
||||
#include <gtsam/slam/dataset.h>
|
||||
|
||||
#include <cstring>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
|
||||
using namespace gtsam;
|
||||
using namespace std;
|
||||
|
||||
using symbol_shorthand::B; // Bias (ax,ay,az,gx,gy,gz)
|
||||
using symbol_shorthand::V; // Vel (xdot,ydot,zdot)
|
||||
using symbol_shorthand::X; // Pose3 (x,y,z,r,p,y)
|
||||
|
||||
namespace po = boost::program_options;
|
||||
|
||||
po::variables_map parseOptions(int argc, char* argv[]) {
|
||||
po::options_description desc;
|
||||
desc.add_options()("help,h", "produce help message")(
|
||||
"data_csv_path", po::value<string>()->default_value("imuAndGPSdata.csv"),
|
||||
"path to the CSV file with the IMU data")(
|
||||
"output_filename",
|
||||
po::value<string>()->default_value("imuFactorExampleResults.csv"),
|
||||
"path to the result file to use")("use_isam", po::bool_switch(),
|
||||
"use ISAM as the optimizer");
|
||||
|
||||
po::variables_map vm;
|
||||
po::store(po::parse_command_line(argc, argv, desc), vm);
|
||||
|
||||
if (vm.count("help")) {
|
||||
cout << desc << "\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return vm;
|
||||
}
|
||||
|
||||
Vector10 readInitialState(ifstream& file) {
|
||||
string value;
|
||||
// Format is (N,E,D,qX,qY,qZ,qW,velN,velE,velD)
|
||||
Vector10 initial_state;
|
||||
getline(file, value, ','); // i
|
||||
for (int i = 0; i < 9; i++) {
|
||||
getline(file, value, ',');
|
||||
initial_state(i) = stof(value.c_str());
|
||||
}
|
||||
getline(file, value, '\n');
|
||||
initial_state(9) = stof(value.c_str());
|
||||
|
||||
return initial_state;
|
||||
}
|
||||
|
||||
boost::shared_ptr<PreintegratedCombinedMeasurements::Params> imuParams() {
|
||||
// We use the sensor specs to build the noise model for the IMU factor.
|
||||
double accel_noise_sigma = 0.0003924;
|
||||
double gyro_noise_sigma = 0.000205689024915;
|
||||
double accel_bias_rw_sigma = 0.004905;
|
||||
double gyro_bias_rw_sigma = 0.000001454441043;
|
||||
Matrix33 measured_acc_cov = I_3x3 * pow(accel_noise_sigma, 2);
|
||||
Matrix33 measured_omega_cov = I_3x3 * pow(gyro_noise_sigma, 2);
|
||||
Matrix33 integration_error_cov =
|
||||
I_3x3 * 1e-8; // error committed in integrating position from velocities
|
||||
Matrix33 bias_acc_cov = I_3x3 * pow(accel_bias_rw_sigma, 2);
|
||||
Matrix33 bias_omega_cov = I_3x3 * pow(gyro_bias_rw_sigma, 2);
|
||||
Matrix66 bias_acc_omega_int =
|
||||
I_6x6 * 1e-5; // error in the bias used for preintegration
|
||||
|
||||
auto p = PreintegratedCombinedMeasurements::Params::MakeSharedD(0.0);
|
||||
// PreintegrationBase params:
|
||||
p->accelerometerCovariance =
|
||||
measured_acc_cov; // acc white noise in continuous
|
||||
p->integrationCovariance =
|
||||
integration_error_cov; // integration uncertainty continuous
|
||||
// should be using 2nd order integration
|
||||
// PreintegratedRotation params:
|
||||
p->gyroscopeCovariance =
|
||||
measured_omega_cov; // gyro white noise in continuous
|
||||
// PreintegrationCombinedMeasurements params:
|
||||
p->biasAccCovariance = bias_acc_cov; // acc bias in continuous
|
||||
p->biasOmegaCovariance = bias_omega_cov; // gyro bias in continuous
|
||||
p->biasAccOmegaInt = bias_acc_omega_int;
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
string data_filename, output_filename;
|
||||
po::variables_map var_map = parseOptions(argc, argv);
|
||||
|
||||
data_filename = findExampleDataFile(var_map["data_csv_path"].as<string>());
|
||||
output_filename = var_map["output_filename"].as<string>();
|
||||
|
||||
// Set up output file for plotting errors
|
||||
FILE* fp_out = fopen(output_filename.c_str(), "w+");
|
||||
fprintf(fp_out,
|
||||
"#time(s),x(m),y(m),z(m),qx,qy,qz,qw,gt_x(m),gt_y(m),gt_z(m),gt_qx,"
|
||||
"gt_qy,gt_qz,gt_qw\n");
|
||||
|
||||
// Begin parsing the CSV file. Input the first line for initialization.
|
||||
// From there, we'll iterate through the file and we'll preintegrate the IMU
|
||||
// or add in the GPS given the input.
|
||||
ifstream file(data_filename.c_str());
|
||||
|
||||
Vector10 initial_state = readInitialState(file);
|
||||
cout << "initial state:\n" << initial_state.transpose() << "\n\n";
|
||||
|
||||
// Assemble initial quaternion through GTSAM constructor
|
||||
// ::Quaternion(w,x,y,z);
|
||||
Rot3 prior_rotation = Rot3::Quaternion(initial_state(6), initial_state(3),
|
||||
initial_state(4), initial_state(5));
|
||||
Point3 prior_point(initial_state.head<3>());
|
||||
Pose3 prior_pose(prior_rotation, prior_point);
|
||||
Vector3 prior_velocity(initial_state.tail<3>());
|
||||
|
||||
imuBias::ConstantBias prior_imu_bias; // assume zero initial bias
|
||||
|
||||
int index = 0;
|
||||
|
||||
Values initial_values;
|
||||
|
||||
// insert pose at initialization
|
||||
initial_values.insert(X(index), prior_pose);
|
||||
initial_values.insert(V(index), prior_velocity);
|
||||
initial_values.insert(B(index), prior_imu_bias);
|
||||
|
||||
// Assemble prior noise model and add it the graph.`
|
||||
auto pose_noise_model = noiseModel::Diagonal::Sigmas(
|
||||
(Vector(6) << 0.01, 0.01, 0.01, 0.5, 0.5, 0.5)
|
||||
.finished()); // rad,rad,rad,m, m, m
|
||||
auto velocity_noise_model = noiseModel::Isotropic::Sigma(3, 0.1); // m/s
|
||||
auto bias_noise_model = noiseModel::Isotropic::Sigma(6, 1e-3);
|
||||
|
||||
// Add all prior factors (pose, velocity, bias) to the graph.
|
||||
NonlinearFactorGraph graph;
|
||||
graph.addPrior<Pose3>(X(index), prior_pose, pose_noise_model);
|
||||
graph.addPrior<Vector3>(V(index), prior_velocity, velocity_noise_model);
|
||||
graph.addPrior<imuBias::ConstantBias>(B(index), prior_imu_bias,
|
||||
bias_noise_model);
|
||||
|
||||
auto p = imuParams();
|
||||
|
||||
std::shared_ptr<PreintegrationType> preintegrated =
|
||||
std::make_shared<PreintegratedCombinedMeasurements>(p, prior_imu_bias);
|
||||
|
||||
assert(preintegrated);
|
||||
|
||||
// Store previous state for imu integration and latest predicted outcome.
|
||||
NavState prev_state(prior_pose, prior_velocity);
|
||||
NavState prop_state = prev_state;
|
||||
imuBias::ConstantBias prev_bias = prior_imu_bias;
|
||||
|
||||
// Keep track of total error over the entire run as simple performance metric.
|
||||
double current_position_error = 0.0, current_orientation_error = 0.0;
|
||||
|
||||
double output_time = 0.0;
|
||||
double dt = 0.005; // The real system has noise, but here, results are nearly
|
||||
// exactly the same, so keeping this for simplicity.
|
||||
|
||||
// All priors have been set up, now iterate through the data file.
|
||||
while (file.good()) {
|
||||
// Parse out first value
|
||||
string value;
|
||||
getline(file, value, ',');
|
||||
int type = stoi(value.c_str());
|
||||
|
||||
if (type == 0) { // IMU measurement
|
||||
Vector6 imu;
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
getline(file, value, ',');
|
||||
imu(i) = stof(value.c_str());
|
||||
}
|
||||
getline(file, value, '\n');
|
||||
imu(5) = stof(value.c_str());
|
||||
|
||||
// Adding the IMU preintegration.
|
||||
preintegrated->integrateMeasurement(imu.head<3>(), imu.tail<3>(), dt);
|
||||
|
||||
} else if (type == 1) { // GPS measurement
|
||||
Vector7 gps;
|
||||
for (int i = 0; i < 6; ++i) {
|
||||
getline(file, value, ',');
|
||||
gps(i) = stof(value.c_str());
|
||||
}
|
||||
getline(file, value, '\n');
|
||||
gps(6) = stof(value.c_str());
|
||||
|
||||
index++;
|
||||
|
||||
// Adding IMU factor and GPS factor and optimizing.
|
||||
auto preint_imu_combined =
|
||||
dynamic_cast<const PreintegratedCombinedMeasurements&>(
|
||||
*preintegrated);
|
||||
CombinedImuFactor imu_factor(X(index - 1), V(index - 1), X(index),
|
||||
V(index), B(index - 1), B(index),
|
||||
preint_imu_combined);
|
||||
graph.add(imu_factor);
|
||||
|
||||
auto correction_noise = noiseModel::Isotropic::Sigma(3, 1.0);
|
||||
GPSFactor gps_factor(X(index),
|
||||
Point3(gps(0), // N,
|
||||
gps(1), // E,
|
||||
gps(2)), // D,
|
||||
correction_noise);
|
||||
graph.add(gps_factor);
|
||||
|
||||
// Now optimize and compare results.
|
||||
prop_state = preintegrated->predict(prev_state, prev_bias);
|
||||
initial_values.insert(X(index), prop_state.pose());
|
||||
initial_values.insert(V(index), prop_state.v());
|
||||
initial_values.insert(B(index), prev_bias);
|
||||
|
||||
LevenbergMarquardtParams params;
|
||||
params.setVerbosityLM("SUMMARY");
|
||||
LevenbergMarquardtOptimizer optimizer(graph, initial_values, params);
|
||||
Values result = optimizer.optimize();
|
||||
|
||||
// Overwrite the beginning of the preintegration for the next step.
|
||||
prev_state =
|
||||
NavState(result.at<Pose3>(X(index)), result.at<Vector3>(V(index)));
|
||||
prev_bias = result.at<imuBias::ConstantBias>(B(index));
|
||||
|
||||
// Reset the preintegration object.
|
||||
preintegrated->resetIntegrationAndSetBias(prev_bias);
|
||||
|
||||
// Print out the position and orientation error for comparison.
|
||||
Vector3 result_position = prev_state.pose().translation();
|
||||
Vector3 position_error = result_position - gps.head<3>();
|
||||
current_position_error = position_error.norm();
|
||||
|
||||
Quaternion result_quat = prev_state.pose().rotation().toQuaternion();
|
||||
Quaternion gps_quat(gps(6), gps(3), gps(4), gps(5));
|
||||
Quaternion quat_error = result_quat * gps_quat.inverse();
|
||||
quat_error.normalize();
|
||||
Vector3 euler_angle_error(quat_error.x() * 2, quat_error.y() * 2,
|
||||
quat_error.z() * 2);
|
||||
current_orientation_error = euler_angle_error.norm();
|
||||
|
||||
// display statistics
|
||||
cout << "Position error:" << current_position_error << "\t "
|
||||
<< "Angular error:" << current_orientation_error << "\n"
|
||||
<< endl;
|
||||
|
||||
fprintf(fp_out, "%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f\n",
|
||||
output_time, result_position(0), result_position(1),
|
||||
result_position(2), result_quat.x(), result_quat.y(),
|
||||
result_quat.z(), result_quat.w(), gps(0), gps(1), gps(2),
|
||||
gps_quat.x(), gps_quat.y(), gps_quat.z(), gps_quat.w());
|
||||
|
||||
output_time += 1.0;
|
||||
|
||||
} else {
|
||||
cerr << "ERROR parsing file\n";
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
fclose(fp_out);
|
||||
cout << "Complete, results written to " << output_filename << "\n\n";
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -15,8 +15,8 @@
|
|||
* @author Frank Dellaert
|
||||
*/
|
||||
|
||||
#include <gtsam/slam/dataset.h>
|
||||
#include <gtsam/geometry/CalibratedCamera.h>
|
||||
#include <gtsam/slam/dataset.h>
|
||||
|
||||
#include <boost/assign/std/vector.hpp>
|
||||
|
||||
|
|
@ -26,22 +26,16 @@ using namespace gtsam;
|
|||
|
||||
/* ************************************************************************* */
|
||||
|
||||
void createExampleBALFile(const string& filename, const vector<Point3>& P,
|
||||
const Pose3& pose1, const Pose3& pose2, const Cal3Bundler& K =
|
||||
Cal3Bundler()) {
|
||||
|
||||
void createExampleBALFile(const string& filename, const vector<Point3>& points,
|
||||
const Pose3& pose1, const Pose3& pose2,
|
||||
const Cal3Bundler& K = Cal3Bundler()) {
|
||||
// Class that will gather all data
|
||||
SfmData data;
|
||||
|
||||
// Create two cameras
|
||||
Rot3 aRb = Rot3::Yaw(M_PI_2);
|
||||
Point3 aTb(0.1, 0, 0);
|
||||
Pose3 identity, aPb(aRb, aTb);
|
||||
// Create two cameras and add them to data
|
||||
data.cameras.push_back(SfmCamera(pose1, K));
|
||||
data.cameras.push_back(SfmCamera(pose2, K));
|
||||
|
||||
for(const Point3& p: P) {
|
||||
|
||||
for (const Point3& p : points) {
|
||||
// Create the track
|
||||
SfmTrack track;
|
||||
track.p = p;
|
||||
|
|
@ -51,7 +45,7 @@ void createExampleBALFile(const string& filename, const vector<Point3>& P,
|
|||
|
||||
// Project points in both cameras
|
||||
for (size_t i = 0; i < 2; i++)
|
||||
track.measurements.push_back(make_pair(i, data.cameras[i].project(p)));
|
||||
track.measurements.push_back(make_pair(i, data.cameras[i].project(p)));
|
||||
|
||||
// Add track to data
|
||||
data.tracks.push_back(track);
|
||||
|
|
@ -63,49 +57,66 @@ void createExampleBALFile(const string& filename, const vector<Point3>& P,
|
|||
/* ************************************************************************* */
|
||||
|
||||
void create5PointExample1() {
|
||||
|
||||
// Create two cameras poses
|
||||
Rot3 aRb = Rot3::Yaw(M_PI_2);
|
||||
Point3 aTb(0.1, 0, 0);
|
||||
Pose3 pose1, pose2(aRb, aTb);
|
||||
|
||||
// Create test data, we need at least 5 points
|
||||
vector<Point3> P;
|
||||
P += Point3(0, 0, 1), Point3(-0.1, 0, 1), Point3(0.1, 0, 1), //
|
||||
Point3(0, 0.5, 0.5), Point3(0, -0.5, 0.5);
|
||||
vector<Point3> points = {
|
||||
{0, 0, 1}, {-0.1, 0, 1}, {0.1, 0, 1}, {0, 0.5, 0.5}, {0, -0.5, 0.5}};
|
||||
|
||||
// Assumes example is run in ${GTSAM_TOP}/build/examples
|
||||
const string filename = "../../examples/data/5pointExample1.txt";
|
||||
createExampleBALFile(filename, P, pose1, pose2);
|
||||
const string filename = "../../examples/Data/5pointExample1.txt";
|
||||
createExampleBALFile(filename, points, pose1, pose2);
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
|
||||
void create5PointExample2() {
|
||||
|
||||
// Create two cameras poses
|
||||
Rot3 aRb = Rot3::Yaw(M_PI_2);
|
||||
Point3 aTb(10, 0, 0);
|
||||
Pose3 pose1, pose2(aRb, aTb);
|
||||
|
||||
// Create test data, we need at least 5 points
|
||||
vector<Point3> P;
|
||||
P += Point3(0, 0, 100), Point3(-10, 0, 100), Point3(10, 0, 100), //
|
||||
Point3(0, 50, 50), Point3(0, -50, 50), Point3(-20, 0, 80), Point3(20, -50, 80);
|
||||
vector<Point3> points = {{0, 0, 100}, {-10, 0, 100}, {10, 0, 100}, //
|
||||
{0, 50, 50}, {0, -50, 50}, {-20, 0, 80}, //
|
||||
{20, -50, 80}};
|
||||
|
||||
// Assumes example is run in ${GTSAM_TOP}/build/examples
|
||||
const string filename = "../../examples/data/5pointExample2.txt";
|
||||
const string filename = "../../examples/Data/5pointExample2.txt";
|
||||
Cal3Bundler K(500, 0, 0);
|
||||
createExampleBALFile(filename, P, pose1, pose2,K);
|
||||
createExampleBALFile(filename, points, pose1, pose2, K);
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
|
||||
void create18PointExample1() {
|
||||
// Create two cameras poses
|
||||
Rot3 aRb = Rot3::Yaw(M_PI_2);
|
||||
Point3 aTb(0.1, 0, 0);
|
||||
Pose3 pose1, pose2(aRb, aTb);
|
||||
|
||||
// Create test data, we need 15 points
|
||||
vector<Point3> points = {
|
||||
{0, 0, 1}, {-0.1, 0, 1}, {0.1, 0, 1}, //
|
||||
{0, 0.5, 0.5}, {0, -0.5, 0.5}, {-1, -0.5, 2}, //
|
||||
{-1, 0.5, 2}, {0.25, -0.5, 1.5}, {0.25, 0.5, 1.5}, //
|
||||
{-0.1, -0.5, 0.5}, {0.1, -0.5, 1}, {0.1, 0.5, 1}, //
|
||||
{-0.1, 0, 0.5}, {-0.1, 0.5, 0.5}, {0, 0, 0.5}, //
|
||||
{0.1, -0.5, 0.5}, {0.1, 0, 0.5}, {0.1, 0.5, 0.5}};
|
||||
|
||||
// Assumes example is run in ${GTSAM_TOP}/build/examples
|
||||
const string filename = "../../examples/Data/18pointExample1.txt";
|
||||
createExampleBALFile(filename, points, pose1, pose2);
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
create5PointExample1();
|
||||
create5PointExample2();
|
||||
create18PointExample1();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,131 @@
|
|||
2 18 36
|
||||
|
||||
0 0 0 -0
|
||||
1 0 -6.123233995736766344e-18 -0.10000000000000000555
|
||||
0 1 -0.10000000000000000555 -0
|
||||
1 1 -1.2246467991473532688e-17 -0.2000000000000000111
|
||||
0 2 0.10000000000000000555 -0
|
||||
1 2 0 -0
|
||||
0 3 0 -1
|
||||
1 3 1 -0.20000000000000006661
|
||||
0 4 0 1
|
||||
1 4 -1 -0.19999999999999995559
|
||||
0 5 -0.5 0.25
|
||||
1 5 -0.25000000000000005551 -0.55000000000000004441
|
||||
0 6 -0.5 -0.25
|
||||
1 6 0.24999999999999997224 -0.55000000000000004441
|
||||
0 7 0.16666666666666665741 0.33333333333333331483
|
||||
1 7 -0.33333333333333331483 0.10000000000000000555
|
||||
0 8 0.16666666666666665741 -0.33333333333333331483
|
||||
1 8 0.33333333333333331483 0.099999999999999977796
|
||||
0 9 -0.2000000000000000111 1
|
||||
1 9 -1 -0.39999999999999996669
|
||||
0 10 0.10000000000000000555 0.5
|
||||
1 10 -0.5 3.0616169978683830179e-17
|
||||
0 11 0.10000000000000000555 -0.5
|
||||
1 11 0.5 -3.0616169978683830179e-17
|
||||
0 12 -0.2000000000000000111 -0
|
||||
1 12 -2.4492935982947065376e-17 -0.4000000000000000222
|
||||
0 13 -0.2000000000000000111 -1
|
||||
1 13 1 -0.40000000000000007772
|
||||
0 14 0 -0
|
||||
1 14 -1.2246467991473532688e-17 -0.2000000000000000111
|
||||
0 15 0.2000000000000000111 1
|
||||
1 15 -1 6.1232339957367660359e-17
|
||||
0 16 0.2000000000000000111 -0
|
||||
1 16 0 -0
|
||||
0 17 0.2000000000000000111 -1
|
||||
1 17 1 -6.1232339957367660359e-17
|
||||
|
||||
3.141592653589793116
|
||||
0
|
||||
0
|
||||
-0
|
||||
0
|
||||
0
|
||||
1
|
||||
0
|
||||
0
|
||||
|
||||
2.2214414690791830509
|
||||
2.2214414690791826068
|
||||
0
|
||||
-6.123233995736766344e-18
|
||||
-0.10000000000000000555
|
||||
0
|
||||
1
|
||||
0
|
||||
0
|
||||
|
||||
0
|
||||
0
|
||||
1
|
||||
|
||||
-0.10000000000000000555
|
||||
0
|
||||
1
|
||||
|
||||
0.10000000000000000555
|
||||
0
|
||||
1
|
||||
|
||||
0
|
||||
0.5
|
||||
0.5
|
||||
|
||||
0
|
||||
-0.5
|
||||
0.5
|
||||
|
||||
-1
|
||||
-0.5
|
||||
2
|
||||
|
||||
-1
|
||||
0.5
|
||||
2
|
||||
|
||||
0.25
|
||||
-0.5
|
||||
1.5
|
||||
|
||||
0.25
|
||||
0.5
|
||||
1.5
|
||||
|
||||
-0.10000000000000000555
|
||||
-0.5
|
||||
0.5
|
||||
|
||||
0.10000000000000000555
|
||||
-0.5
|
||||
1
|
||||
|
||||
0.10000000000000000555
|
||||
0.5
|
||||
1
|
||||
|
||||
-0.10000000000000000555
|
||||
0
|
||||
0.5
|
||||
|
||||
-0.10000000000000000555
|
||||
0.5
|
||||
0.5
|
||||
|
||||
0
|
||||
0
|
||||
0.5
|
||||
|
||||
0.10000000000000000555
|
||||
-0.5
|
||||
0.5
|
||||
|
||||
0.10000000000000000555
|
||||
0
|
||||
0.5
|
||||
|
||||
0.10000000000000000555
|
||||
0.5
|
||||
0.5
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -11,21 +11,23 @@
|
|||
|
||||
/**
|
||||
* @file IMUKittiExampleGPS
|
||||
* @brief Example of application of ISAM2 for GPS-aided navigation on the KITTI VISION BENCHMARK SUITE
|
||||
* @author Ported by Thomas Jespersen (thomasj@tkjelectronics.dk), TKJ Electronics
|
||||
* @brief Example of application of ISAM2 for GPS-aided navigation on the KITTI
|
||||
* VISION BENCHMARK SUITE
|
||||
* @author Ported by Thomas Jespersen (thomasj@tkjelectronics.dk), TKJ
|
||||
* Electronics
|
||||
*/
|
||||
|
||||
// GTSAM related includes.
|
||||
#include <gtsam/inference/Symbol.h>
|
||||
#include <gtsam/navigation/CombinedImuFactor.h>
|
||||
#include <gtsam/navigation/GPSFactor.h>
|
||||
#include <gtsam/navigation/ImuFactor.h>
|
||||
#include <gtsam/slam/dataset.h>
|
||||
#include <gtsam/slam/BetweenFactor.h>
|
||||
#include <gtsam/slam/PriorFactor.h>
|
||||
#include <gtsam/nonlinear/ISAM2.h>
|
||||
#include <gtsam/nonlinear/ISAM2Params.h>
|
||||
#include <gtsam/nonlinear/NonlinearFactorGraph.h>
|
||||
#include <gtsam/inference/Symbol.h>
|
||||
#include <gtsam/slam/BetweenFactor.h>
|
||||
#include <gtsam/slam/PriorFactor.h>
|
||||
#include <gtsam/slam/dataset.h>
|
||||
|
||||
#include <cstring>
|
||||
#include <fstream>
|
||||
|
|
@ -34,35 +36,35 @@
|
|||
using namespace std;
|
||||
using namespace gtsam;
|
||||
|
||||
using symbol_shorthand::X; // Pose3 (x,y,z,r,p,y)
|
||||
using symbol_shorthand::V; // Vel (xdot,ydot,zdot)
|
||||
using symbol_shorthand::B; // Bias (ax,ay,az,gx,gy,gz)
|
||||
using symbol_shorthand::V; // Vel (xdot,ydot,zdot)
|
||||
using symbol_shorthand::X; // Pose3 (x,y,z,r,p,y)
|
||||
|
||||
struct KittiCalibration {
|
||||
double body_ptx;
|
||||
double body_pty;
|
||||
double body_ptz;
|
||||
double body_prx;
|
||||
double body_pry;
|
||||
double body_prz;
|
||||
double accelerometer_sigma;
|
||||
double gyroscope_sigma;
|
||||
double integration_sigma;
|
||||
double accelerometer_bias_sigma;
|
||||
double gyroscope_bias_sigma;
|
||||
double average_delta_t;
|
||||
double body_ptx;
|
||||
double body_pty;
|
||||
double body_ptz;
|
||||
double body_prx;
|
||||
double body_pry;
|
||||
double body_prz;
|
||||
double accelerometer_sigma;
|
||||
double gyroscope_sigma;
|
||||
double integration_sigma;
|
||||
double accelerometer_bias_sigma;
|
||||
double gyroscope_bias_sigma;
|
||||
double average_delta_t;
|
||||
};
|
||||
|
||||
struct ImuMeasurement {
|
||||
double time;
|
||||
double dt;
|
||||
Vector3 accelerometer;
|
||||
Vector3 gyroscope; // omega
|
||||
double time;
|
||||
double dt;
|
||||
Vector3 accelerometer;
|
||||
Vector3 gyroscope; // omega
|
||||
};
|
||||
|
||||
struct GpsMeasurement {
|
||||
double time;
|
||||
Vector3 position; // x,y,z
|
||||
double time;
|
||||
Vector3 position; // x,y,z
|
||||
};
|
||||
|
||||
const string output_filename = "IMUKittiExampleGPSResults.csv";
|
||||
|
|
@ -70,290 +72,313 @@ const string output_filename = "IMUKittiExampleGPSResults.csv";
|
|||
void loadKittiData(KittiCalibration& kitti_calibration,
|
||||
vector<ImuMeasurement>& imu_measurements,
|
||||
vector<GpsMeasurement>& gps_measurements) {
|
||||
string line;
|
||||
string line;
|
||||
|
||||
// Read IMU metadata and compute relative sensor pose transforms
|
||||
// BodyPtx BodyPty BodyPtz BodyPrx BodyPry BodyPrz AccelerometerSigma GyroscopeSigma IntegrationSigma
|
||||
// AccelerometerBiasSigma GyroscopeBiasSigma AverageDeltaT
|
||||
string imu_metadata_file = findExampleDataFile("KittiEquivBiasedImu_metadata.txt");
|
||||
ifstream imu_metadata(imu_metadata_file.c_str());
|
||||
// Read IMU metadata and compute relative sensor pose transforms
|
||||
// BodyPtx BodyPty BodyPtz BodyPrx BodyPry BodyPrz AccelerometerSigma
|
||||
// GyroscopeSigma IntegrationSigma AccelerometerBiasSigma GyroscopeBiasSigma
|
||||
// AverageDeltaT
|
||||
string imu_metadata_file =
|
||||
findExampleDataFile("KittiEquivBiasedImu_metadata.txt");
|
||||
ifstream imu_metadata(imu_metadata_file.c_str());
|
||||
|
||||
printf("-- Reading sensor metadata\n");
|
||||
printf("-- Reading sensor metadata\n");
|
||||
|
||||
getline(imu_metadata, line, '\n'); // ignore the first line
|
||||
getline(imu_metadata, line, '\n'); // ignore the first line
|
||||
|
||||
// Load Kitti calibration
|
||||
getline(imu_metadata, line, '\n');
|
||||
sscanf(line.c_str(), "%lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf",
|
||||
&kitti_calibration.body_ptx,
|
||||
&kitti_calibration.body_pty,
|
||||
&kitti_calibration.body_ptz,
|
||||
&kitti_calibration.body_prx,
|
||||
&kitti_calibration.body_pry,
|
||||
&kitti_calibration.body_prz,
|
||||
&kitti_calibration.accelerometer_sigma,
|
||||
&kitti_calibration.gyroscope_sigma,
|
||||
&kitti_calibration.integration_sigma,
|
||||
&kitti_calibration.accelerometer_bias_sigma,
|
||||
&kitti_calibration.gyroscope_bias_sigma,
|
||||
&kitti_calibration.average_delta_t);
|
||||
printf("IMU metadata: %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf\n",
|
||||
kitti_calibration.body_ptx,
|
||||
kitti_calibration.body_pty,
|
||||
kitti_calibration.body_ptz,
|
||||
kitti_calibration.body_prx,
|
||||
kitti_calibration.body_pry,
|
||||
kitti_calibration.body_prz,
|
||||
kitti_calibration.accelerometer_sigma,
|
||||
kitti_calibration.gyroscope_sigma,
|
||||
kitti_calibration.integration_sigma,
|
||||
kitti_calibration.accelerometer_bias_sigma,
|
||||
kitti_calibration.gyroscope_bias_sigma,
|
||||
kitti_calibration.average_delta_t);
|
||||
// Load Kitti calibration
|
||||
getline(imu_metadata, line, '\n');
|
||||
sscanf(line.c_str(), "%lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf",
|
||||
&kitti_calibration.body_ptx, &kitti_calibration.body_pty,
|
||||
&kitti_calibration.body_ptz, &kitti_calibration.body_prx,
|
||||
&kitti_calibration.body_pry, &kitti_calibration.body_prz,
|
||||
&kitti_calibration.accelerometer_sigma,
|
||||
&kitti_calibration.gyroscope_sigma,
|
||||
&kitti_calibration.integration_sigma,
|
||||
&kitti_calibration.accelerometer_bias_sigma,
|
||||
&kitti_calibration.gyroscope_bias_sigma,
|
||||
&kitti_calibration.average_delta_t);
|
||||
printf("IMU metadata: %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf\n",
|
||||
kitti_calibration.body_ptx, kitti_calibration.body_pty,
|
||||
kitti_calibration.body_ptz, kitti_calibration.body_prx,
|
||||
kitti_calibration.body_pry, kitti_calibration.body_prz,
|
||||
kitti_calibration.accelerometer_sigma,
|
||||
kitti_calibration.gyroscope_sigma, kitti_calibration.integration_sigma,
|
||||
kitti_calibration.accelerometer_bias_sigma,
|
||||
kitti_calibration.gyroscope_bias_sigma,
|
||||
kitti_calibration.average_delta_t);
|
||||
|
||||
// Read IMU data
|
||||
// Time dt accelX accelY accelZ omegaX omegaY omegaZ
|
||||
string imu_data_file = findExampleDataFile("KittiEquivBiasedImu.txt");
|
||||
printf("-- Reading IMU measurements from file\n");
|
||||
{
|
||||
ifstream imu_data(imu_data_file.c_str());
|
||||
getline(imu_data, line, '\n'); // ignore the first line
|
||||
// Read IMU data
|
||||
// Time dt accelX accelY accelZ omegaX omegaY omegaZ
|
||||
string imu_data_file = findExampleDataFile("KittiEquivBiasedImu.txt");
|
||||
printf("-- Reading IMU measurements from file\n");
|
||||
{
|
||||
ifstream imu_data(imu_data_file.c_str());
|
||||
getline(imu_data, line, '\n'); // ignore the first line
|
||||
|
||||
double time = 0, dt = 0, acc_x = 0, acc_y = 0, acc_z = 0, gyro_x = 0, gyro_y = 0, gyro_z = 0;
|
||||
while (!imu_data.eof()) {
|
||||
getline(imu_data, line, '\n');
|
||||
sscanf(line.c_str(), "%lf %lf %lf %lf %lf %lf %lf %lf",
|
||||
&time, &dt,
|
||||
&acc_x, &acc_y, &acc_z,
|
||||
&gyro_x, &gyro_y, &gyro_z);
|
||||
double time = 0, dt = 0, acc_x = 0, acc_y = 0, acc_z = 0, gyro_x = 0,
|
||||
gyro_y = 0, gyro_z = 0;
|
||||
while (!imu_data.eof()) {
|
||||
getline(imu_data, line, '\n');
|
||||
sscanf(line.c_str(), "%lf %lf %lf %lf %lf %lf %lf %lf", &time, &dt,
|
||||
&acc_x, &acc_y, &acc_z, &gyro_x, &gyro_y, &gyro_z);
|
||||
|
||||
ImuMeasurement measurement;
|
||||
measurement.time = time;
|
||||
measurement.dt = dt;
|
||||
measurement.accelerometer = Vector3(acc_x, acc_y, acc_z);
|
||||
measurement.gyroscope = Vector3(gyro_x, gyro_y, gyro_z);
|
||||
imu_measurements.push_back(measurement);
|
||||
}
|
||||
ImuMeasurement measurement;
|
||||
measurement.time = time;
|
||||
measurement.dt = dt;
|
||||
measurement.accelerometer = Vector3(acc_x, acc_y, acc_z);
|
||||
measurement.gyroscope = Vector3(gyro_x, gyro_y, gyro_z);
|
||||
imu_measurements.push_back(measurement);
|
||||
}
|
||||
}
|
||||
|
||||
// Read GPS data
|
||||
// Time,X,Y,Z
|
||||
string gps_data_file = findExampleDataFile("KittiGps_converted.txt");
|
||||
printf("-- Reading GPS measurements from file\n");
|
||||
{
|
||||
ifstream gps_data(gps_data_file.c_str());
|
||||
getline(gps_data, line, '\n'); // ignore the first line
|
||||
// Read GPS data
|
||||
// Time,X,Y,Z
|
||||
string gps_data_file = findExampleDataFile("KittiGps_converted.txt");
|
||||
printf("-- Reading GPS measurements from file\n");
|
||||
{
|
||||
ifstream gps_data(gps_data_file.c_str());
|
||||
getline(gps_data, line, '\n'); // ignore the first line
|
||||
|
||||
double time = 0, gps_x = 0, gps_y = 0, gps_z = 0;
|
||||
while (!gps_data.eof()) {
|
||||
getline(gps_data, line, '\n');
|
||||
sscanf(line.c_str(), "%lf,%lf,%lf,%lf", &time, &gps_x, &gps_y, &gps_z);
|
||||
double time = 0, gps_x = 0, gps_y = 0, gps_z = 0;
|
||||
while (!gps_data.eof()) {
|
||||
getline(gps_data, line, '\n');
|
||||
sscanf(line.c_str(), "%lf,%lf,%lf,%lf", &time, &gps_x, &gps_y, &gps_z);
|
||||
|
||||
GpsMeasurement measurement;
|
||||
measurement.time = time;
|
||||
measurement.position = Vector3(gps_x, gps_y, gps_z);
|
||||
gps_measurements.push_back(measurement);
|
||||
}
|
||||
GpsMeasurement measurement;
|
||||
measurement.time = time;
|
||||
measurement.position = Vector3(gps_x, gps_y, gps_z);
|
||||
gps_measurements.push_back(measurement);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
KittiCalibration kitti_calibration;
|
||||
vector<ImuMeasurement> imu_measurements;
|
||||
vector<GpsMeasurement> gps_measurements;
|
||||
loadKittiData(kitti_calibration, imu_measurements, gps_measurements);
|
||||
KittiCalibration kitti_calibration;
|
||||
vector<ImuMeasurement> imu_measurements;
|
||||
vector<GpsMeasurement> gps_measurements;
|
||||
loadKittiData(kitti_calibration, imu_measurements, gps_measurements);
|
||||
|
||||
Vector6 BodyP = (Vector6() << kitti_calibration.body_ptx, kitti_calibration.body_pty, kitti_calibration.body_ptz,
|
||||
kitti_calibration.body_prx, kitti_calibration.body_pry, kitti_calibration.body_prz)
|
||||
.finished();
|
||||
auto body_T_imu = Pose3::Expmap(BodyP);
|
||||
if (!body_T_imu.equals(Pose3(), 1e-5)) {
|
||||
printf("Currently only support IMUinBody is identity, i.e. IMU and body frame are the same");
|
||||
exit(-1);
|
||||
}
|
||||
Vector6 BodyP =
|
||||
(Vector6() << kitti_calibration.body_ptx, kitti_calibration.body_pty,
|
||||
kitti_calibration.body_ptz, kitti_calibration.body_prx,
|
||||
kitti_calibration.body_pry, kitti_calibration.body_prz)
|
||||
.finished();
|
||||
auto body_T_imu = Pose3::Expmap(BodyP);
|
||||
if (!body_T_imu.equals(Pose3(), 1e-5)) {
|
||||
printf(
|
||||
"Currently only support IMUinBody is identity, i.e. IMU and body frame "
|
||||
"are the same");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
// Configure different variables
|
||||
// double t_offset = gps_measurements[0].time;
|
||||
size_t first_gps_pose = 1;
|
||||
size_t gps_skip = 10; // Skip this many GPS measurements each time
|
||||
double g = 9.8;
|
||||
auto w_coriolis = Vector3::Zero(); // zero vector
|
||||
// Configure different variables
|
||||
// double t_offset = gps_measurements[0].time;
|
||||
size_t first_gps_pose = 1;
|
||||
size_t gps_skip = 10; // Skip this many GPS measurements each time
|
||||
double g = 9.8;
|
||||
auto w_coriolis = Vector3::Zero(); // zero vector
|
||||
|
||||
// Configure noise models
|
||||
auto noise_model_gps = noiseModel::Diagonal::Precisions((Vector6() << Vector3::Constant(0),
|
||||
Vector3::Constant(1.0/0.07))
|
||||
.finished());
|
||||
// Configure noise models
|
||||
auto noise_model_gps = noiseModel::Diagonal::Precisions(
|
||||
(Vector6() << Vector3::Constant(0), Vector3::Constant(1.0 / 0.07))
|
||||
.finished());
|
||||
|
||||
// Set initial conditions for the estimated trajectory
|
||||
// initial pose is the reference frame (navigation frame)
|
||||
auto current_pose_global = Pose3(Rot3(), gps_measurements[first_gps_pose].position);
|
||||
// the vehicle is stationary at the beginning at position 0,0,0
|
||||
Vector3 current_velocity_global = Vector3::Zero();
|
||||
auto current_bias = imuBias::ConstantBias(); // init with zero bias
|
||||
// Set initial conditions for the estimated trajectory
|
||||
// initial pose is the reference frame (navigation frame)
|
||||
auto current_pose_global =
|
||||
Pose3(Rot3(), gps_measurements[first_gps_pose].position);
|
||||
// the vehicle is stationary at the beginning at position 0,0,0
|
||||
Vector3 current_velocity_global = Vector3::Zero();
|
||||
auto current_bias = imuBias::ConstantBias(); // init with zero bias
|
||||
|
||||
auto sigma_init_x = noiseModel::Diagonal::Precisions((Vector6() << Vector3::Constant(0),
|
||||
Vector3::Constant(1.0))
|
||||
.finished());
|
||||
auto sigma_init_v = noiseModel::Diagonal::Sigmas(Vector3::Constant(1000.0));
|
||||
auto sigma_init_b = noiseModel::Diagonal::Sigmas((Vector6() << Vector3::Constant(0.100),
|
||||
Vector3::Constant(5.00e-05))
|
||||
.finished());
|
||||
auto sigma_init_x = noiseModel::Diagonal::Precisions(
|
||||
(Vector6() << Vector3::Constant(0), Vector3::Constant(1.0)).finished());
|
||||
auto sigma_init_v = noiseModel::Diagonal::Sigmas(Vector3::Constant(1000.0));
|
||||
auto sigma_init_b = noiseModel::Diagonal::Sigmas(
|
||||
(Vector6() << Vector3::Constant(0.100), Vector3::Constant(5.00e-05))
|
||||
.finished());
|
||||
|
||||
// Set IMU preintegration parameters
|
||||
Matrix33 measured_acc_cov = I_3x3 * pow(kitti_calibration.accelerometer_sigma, 2);
|
||||
Matrix33 measured_omega_cov = I_3x3 * pow(kitti_calibration.gyroscope_sigma, 2);
|
||||
// error committed in integrating position from velocities
|
||||
Matrix33 integration_error_cov = I_3x3 * pow(kitti_calibration.integration_sigma, 2);
|
||||
// Set IMU preintegration parameters
|
||||
Matrix33 measured_acc_cov =
|
||||
I_3x3 * pow(kitti_calibration.accelerometer_sigma, 2);
|
||||
Matrix33 measured_omega_cov =
|
||||
I_3x3 * pow(kitti_calibration.gyroscope_sigma, 2);
|
||||
// error committed in integrating position from velocities
|
||||
Matrix33 integration_error_cov =
|
||||
I_3x3 * pow(kitti_calibration.integration_sigma, 2);
|
||||
|
||||
auto imu_params = PreintegratedImuMeasurements::Params::MakeSharedU(g);
|
||||
imu_params->accelerometerCovariance = measured_acc_cov; // acc white noise in continuous
|
||||
imu_params->integrationCovariance = integration_error_cov; // integration uncertainty continuous
|
||||
imu_params->gyroscopeCovariance = measured_omega_cov; // gyro white noise in continuous
|
||||
imu_params->omegaCoriolis = w_coriolis;
|
||||
auto imu_params = PreintegratedImuMeasurements::Params::MakeSharedU(g);
|
||||
imu_params->accelerometerCovariance =
|
||||
measured_acc_cov; // acc white noise in continuous
|
||||
imu_params->integrationCovariance =
|
||||
integration_error_cov; // integration uncertainty continuous
|
||||
imu_params->gyroscopeCovariance =
|
||||
measured_omega_cov; // gyro white noise in continuous
|
||||
imu_params->omegaCoriolis = w_coriolis;
|
||||
|
||||
std::shared_ptr<PreintegratedImuMeasurements> current_summarized_measurement = nullptr;
|
||||
std::shared_ptr<PreintegratedImuMeasurements> current_summarized_measurement =
|
||||
nullptr;
|
||||
|
||||
// Set ISAM2 parameters and create ISAM2 solver object
|
||||
ISAM2Params isam_params;
|
||||
isam_params.factorization = ISAM2Params::CHOLESKY;
|
||||
isam_params.relinearizeSkip = 10;
|
||||
// Set ISAM2 parameters and create ISAM2 solver object
|
||||
ISAM2Params isam_params;
|
||||
isam_params.factorization = ISAM2Params::CHOLESKY;
|
||||
isam_params.relinearizeSkip = 10;
|
||||
|
||||
ISAM2 isam(isam_params);
|
||||
ISAM2 isam(isam_params);
|
||||
|
||||
// Create the factor graph and values object that will store new factors and values to add to the incremental graph
|
||||
NonlinearFactorGraph new_factors;
|
||||
Values new_values; // values storing the initial estimates of new nodes in the factor graph
|
||||
// Create the factor graph and values object that will store new factors and
|
||||
// values to add to the incremental graph
|
||||
NonlinearFactorGraph new_factors;
|
||||
Values new_values; // values storing the initial estimates of new nodes in
|
||||
// the factor graph
|
||||
|
||||
/// Main loop:
|
||||
/// (1) we read the measurements
|
||||
/// (2) we create the corresponding factors in the graph
|
||||
/// (3) we solve the graph to obtain and optimal estimate of robot trajectory
|
||||
printf("-- Starting main loop: inference is performed at each time step, but we plot trajectory every 10 steps\n");
|
||||
size_t j = 0;
|
||||
for (size_t i = first_gps_pose; i < gps_measurements.size() - 1; i++) {
|
||||
// At each non=IMU measurement we initialize a new node in the graph
|
||||
auto current_pose_key = X(i);
|
||||
auto current_vel_key = V(i);
|
||||
auto current_bias_key = B(i);
|
||||
double t = gps_measurements[i].time;
|
||||
/// Main loop:
|
||||
/// (1) we read the measurements
|
||||
/// (2) we create the corresponding factors in the graph
|
||||
/// (3) we solve the graph to obtain and optimal estimate of robot trajectory
|
||||
printf(
|
||||
"-- Starting main loop: inference is performed at each time step, but we "
|
||||
"plot trajectory every 10 steps\n");
|
||||
size_t j = 0;
|
||||
size_t included_imu_measurement_count = 0;
|
||||
|
||||
if (i == first_gps_pose) {
|
||||
// Create initial estimate and prior on initial pose, velocity, and biases
|
||||
new_values.insert(current_pose_key, current_pose_global);
|
||||
new_values.insert(current_vel_key, current_velocity_global);
|
||||
new_values.insert(current_bias_key, current_bias);
|
||||
new_factors.emplace_shared<PriorFactor<Pose3>>(current_pose_key, current_pose_global, sigma_init_x);
|
||||
new_factors.emplace_shared<PriorFactor<Vector3>>(current_vel_key, current_velocity_global, sigma_init_v);
|
||||
new_factors.emplace_shared<PriorFactor<imuBias::ConstantBias>>(current_bias_key, current_bias, sigma_init_b);
|
||||
} else {
|
||||
double t_previous = gps_measurements[i-1].time;
|
||||
for (size_t i = first_gps_pose; i < gps_measurements.size() - 1; i++) {
|
||||
// At each non=IMU measurement we initialize a new node in the graph
|
||||
auto current_pose_key = X(i);
|
||||
auto current_vel_key = V(i);
|
||||
auto current_bias_key = B(i);
|
||||
double t = gps_measurements[i].time;
|
||||
|
||||
// Summarize IMU data between the previous GPS measurement and now
|
||||
current_summarized_measurement = std::make_shared<PreintegratedImuMeasurements>(imu_params, current_bias);
|
||||
static size_t included_imu_measurement_count = 0;
|
||||
while (j < imu_measurements.size() && imu_measurements[j].time <= t) {
|
||||
if (imu_measurements[j].time >= t_previous) {
|
||||
current_summarized_measurement->integrateMeasurement(imu_measurements[j].accelerometer,
|
||||
imu_measurements[j].gyroscope,
|
||||
imu_measurements[j].dt);
|
||||
included_imu_measurement_count++;
|
||||
}
|
||||
j++;
|
||||
}
|
||||
if (i == first_gps_pose) {
|
||||
// Create initial estimate and prior on initial pose, velocity, and biases
|
||||
new_values.insert(current_pose_key, current_pose_global);
|
||||
new_values.insert(current_vel_key, current_velocity_global);
|
||||
new_values.insert(current_bias_key, current_bias);
|
||||
new_factors.emplace_shared<PriorFactor<Pose3>>(
|
||||
current_pose_key, current_pose_global, sigma_init_x);
|
||||
new_factors.emplace_shared<PriorFactor<Vector3>>(
|
||||
current_vel_key, current_velocity_global, sigma_init_v);
|
||||
new_factors.emplace_shared<PriorFactor<imuBias::ConstantBias>>(
|
||||
current_bias_key, current_bias, sigma_init_b);
|
||||
} else {
|
||||
double t_previous = gps_measurements[i - 1].time;
|
||||
|
||||
// Create IMU factor
|
||||
auto previous_pose_key = X(i-1);
|
||||
auto previous_vel_key = V(i-1);
|
||||
auto previous_bias_key = B(i-1);
|
||||
// Summarize IMU data between the previous GPS measurement and now
|
||||
current_summarized_measurement =
|
||||
std::make_shared<PreintegratedImuMeasurements>(imu_params,
|
||||
current_bias);
|
||||
|
||||
new_factors.emplace_shared<ImuFactor>(previous_pose_key, previous_vel_key,
|
||||
current_pose_key, current_vel_key,
|
||||
previous_bias_key, *current_summarized_measurement);
|
||||
|
||||
// Bias evolution as given in the IMU metadata
|
||||
auto sigma_between_b = noiseModel::Diagonal::Sigmas((Vector6() <<
|
||||
Vector3::Constant(sqrt(included_imu_measurement_count) * kitti_calibration.accelerometer_bias_sigma),
|
||||
Vector3::Constant(sqrt(included_imu_measurement_count) * kitti_calibration.gyroscope_bias_sigma))
|
||||
.finished());
|
||||
new_factors.emplace_shared<BetweenFactor<imuBias::ConstantBias>>(previous_bias_key,
|
||||
current_bias_key,
|
||||
imuBias::ConstantBias(),
|
||||
sigma_between_b);
|
||||
|
||||
// Create GPS factor
|
||||
auto gps_pose = Pose3(current_pose_global.rotation(), gps_measurements[i].position);
|
||||
if ((i % gps_skip) == 0) {
|
||||
new_factors.emplace_shared<PriorFactor<Pose3>>(current_pose_key, gps_pose, noise_model_gps);
|
||||
new_values.insert(current_pose_key, gps_pose);
|
||||
|
||||
printf("################ POSE INCLUDED AT TIME %lf ################\n", t);
|
||||
cout << gps_pose.translation();
|
||||
printf("\n\n");
|
||||
} else {
|
||||
new_values.insert(current_pose_key, current_pose_global);
|
||||
}
|
||||
|
||||
// Add initial values for velocity and bias based on the previous estimates
|
||||
new_values.insert(current_vel_key, current_velocity_global);
|
||||
new_values.insert(current_bias_key, current_bias);
|
||||
|
||||
// Update solver
|
||||
// =======================================================================
|
||||
// We accumulate 2*GPSskip GPS measurements before updating the solver at
|
||||
// first so that the heading becomes observable.
|
||||
if (i > (first_gps_pose + 2*gps_skip)) {
|
||||
printf("################ NEW FACTORS AT TIME %lf ################\n", t);
|
||||
new_factors.print();
|
||||
|
||||
isam.update(new_factors, new_values);
|
||||
|
||||
// Reset the newFactors and newValues list
|
||||
new_factors.resize(0);
|
||||
new_values.clear();
|
||||
|
||||
// Extract the result/current estimates
|
||||
Values result = isam.calculateEstimate();
|
||||
|
||||
current_pose_global = result.at<Pose3>(current_pose_key);
|
||||
current_velocity_global = result.at<Vector3>(current_vel_key);
|
||||
current_bias = result.at<imuBias::ConstantBias>(current_bias_key);
|
||||
|
||||
printf("\n################ POSE AT TIME %lf ################\n", t);
|
||||
current_pose_global.print();
|
||||
printf("\n\n");
|
||||
}
|
||||
while (j < imu_measurements.size() && imu_measurements[j].time <= t) {
|
||||
if (imu_measurements[j].time >= t_previous) {
|
||||
current_summarized_measurement->integrateMeasurement(
|
||||
imu_measurements[j].accelerometer, imu_measurements[j].gyroscope,
|
||||
imu_measurements[j].dt);
|
||||
included_imu_measurement_count++;
|
||||
}
|
||||
j++;
|
||||
}
|
||||
|
||||
// Create IMU factor
|
||||
auto previous_pose_key = X(i - 1);
|
||||
auto previous_vel_key = V(i - 1);
|
||||
auto previous_bias_key = B(i - 1);
|
||||
|
||||
new_factors.emplace_shared<ImuFactor>(
|
||||
previous_pose_key, previous_vel_key, current_pose_key,
|
||||
current_vel_key, previous_bias_key, *current_summarized_measurement);
|
||||
|
||||
// Bias evolution as given in the IMU metadata
|
||||
auto sigma_between_b = noiseModel::Diagonal::Sigmas(
|
||||
(Vector6() << Vector3::Constant(
|
||||
sqrt(included_imu_measurement_count) *
|
||||
kitti_calibration.accelerometer_bias_sigma),
|
||||
Vector3::Constant(sqrt(included_imu_measurement_count) *
|
||||
kitti_calibration.gyroscope_bias_sigma))
|
||||
.finished());
|
||||
new_factors.emplace_shared<BetweenFactor<imuBias::ConstantBias>>(
|
||||
previous_bias_key, current_bias_key, imuBias::ConstantBias(),
|
||||
sigma_between_b);
|
||||
|
||||
// Create GPS factor
|
||||
auto gps_pose =
|
||||
Pose3(current_pose_global.rotation(), gps_measurements[i].position);
|
||||
if ((i % gps_skip) == 0) {
|
||||
new_factors.emplace_shared<PriorFactor<Pose3>>(
|
||||
current_pose_key, gps_pose, noise_model_gps);
|
||||
new_values.insert(current_pose_key, gps_pose);
|
||||
|
||||
printf("############ POSE INCLUDED AT TIME %.6lf ############\n",
|
||||
t);
|
||||
cout << gps_pose.translation();
|
||||
printf("\n\n");
|
||||
} else {
|
||||
new_values.insert(current_pose_key, current_pose_global);
|
||||
}
|
||||
|
||||
// Add initial values for velocity and bias based on the previous
|
||||
// estimates
|
||||
new_values.insert(current_vel_key, current_velocity_global);
|
||||
new_values.insert(current_bias_key, current_bias);
|
||||
|
||||
// Update solver
|
||||
// =======================================================================
|
||||
// We accumulate 2*GPSskip GPS measurements before updating the solver at
|
||||
// first so that the heading becomes observable.
|
||||
if (i > (first_gps_pose + 2 * gps_skip)) {
|
||||
printf("############ NEW FACTORS AT TIME %.6lf ############\n",
|
||||
t);
|
||||
new_factors.print();
|
||||
|
||||
isam.update(new_factors, new_values);
|
||||
|
||||
// Reset the newFactors and newValues list
|
||||
new_factors.resize(0);
|
||||
new_values.clear();
|
||||
|
||||
// Extract the result/current estimates
|
||||
Values result = isam.calculateEstimate();
|
||||
|
||||
current_pose_global = result.at<Pose3>(current_pose_key);
|
||||
current_velocity_global = result.at<Vector3>(current_vel_key);
|
||||
current_bias = result.at<imuBias::ConstantBias>(current_bias_key);
|
||||
|
||||
printf("\n############ POSE AT TIME %lf ############\n", t);
|
||||
current_pose_global.print();
|
||||
printf("\n\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Save results to file
|
||||
printf("\nWriting results to file...\n");
|
||||
FILE* fp_out = fopen(output_filename.c_str(), "w+");
|
||||
fprintf(fp_out, "#time(s),x(m),y(m),z(m),qx,qy,qz,qw,gt_x(m),gt_y(m),gt_z(m)\n");
|
||||
// Save results to file
|
||||
printf("\nWriting results to file...\n");
|
||||
FILE* fp_out = fopen(output_filename.c_str(), "w+");
|
||||
fprintf(fp_out,
|
||||
"#time(s),x(m),y(m),z(m),qx,qy,qz,qw,gt_x(m),gt_y(m),gt_z(m)\n");
|
||||
|
||||
Values result = isam.calculateEstimate();
|
||||
for (size_t i = first_gps_pose; i < gps_measurements.size() - 1; i++) {
|
||||
auto pose_key = X(i);
|
||||
auto vel_key = V(i);
|
||||
auto bias_key = B(i);
|
||||
Values result = isam.calculateEstimate();
|
||||
for (size_t i = first_gps_pose; i < gps_measurements.size() - 1; i++) {
|
||||
auto pose_key = X(i);
|
||||
auto vel_key = V(i);
|
||||
auto bias_key = B(i);
|
||||
|
||||
auto pose = result.at<Pose3>(pose_key);
|
||||
auto velocity = result.at<Vector3>(vel_key);
|
||||
auto bias = result.at<imuBias::ConstantBias>(bias_key);
|
||||
auto pose = result.at<Pose3>(pose_key);
|
||||
auto velocity = result.at<Vector3>(vel_key);
|
||||
auto bias = result.at<imuBias::ConstantBias>(bias_key);
|
||||
|
||||
auto pose_quat = pose.rotation().toQuaternion();
|
||||
auto gps = gps_measurements[i].position;
|
||||
auto pose_quat = pose.rotation().toQuaternion();
|
||||
auto gps = gps_measurements[i].position;
|
||||
|
||||
cout << "State at #" << i << endl;
|
||||
cout << "Pose:" << endl << pose << endl;
|
||||
cout << "Velocity:" << endl << velocity << endl;
|
||||
cout << "Bias:" << endl << bias << endl;
|
||||
cout << "State at #" << i << endl;
|
||||
cout << "Pose:" << endl << pose << endl;
|
||||
cout << "Velocity:" << endl << velocity << endl;
|
||||
cout << "Bias:" << endl << bias << endl;
|
||||
|
||||
fprintf(fp_out, "%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f\n",
|
||||
gps_measurements[i].time,
|
||||
pose.x(), pose.y(), pose.z(),
|
||||
pose_quat.x(), pose_quat.y(), pose_quat.z(), pose_quat.w(),
|
||||
gps(0), gps(1), gps(2));
|
||||
}
|
||||
fprintf(fp_out, "%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f\n",
|
||||
gps_measurements[i].time, pose.x(), pose.y(), pose.z(),
|
||||
pose_quat.x(), pose_quat.y(), pose_quat.z(), pose_quat.w(), gps(0),
|
||||
gps(1), gps(2));
|
||||
}
|
||||
|
||||
fclose(fp_out);
|
||||
fclose(fp_out);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
* -------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* @file imuFactorsExample
|
||||
* @file ImuFactorsExample
|
||||
* @brief Test example for using GTSAM ImuFactor and ImuCombinedFactor
|
||||
* navigation code.
|
||||
* @author Garrett (ghemann@gmail.com), Luca Carlone
|
||||
|
|
@ -25,38 +25,33 @@
|
|||
* A row starting with "i" is the first initial position formatted with
|
||||
* N, E, D, qx, qY, qZ, qW, velN, velE, velD
|
||||
* A row starting with "0" is an imu measurement
|
||||
* linAccN, linAccE, linAccD, angVelN, angVelE, angVelD
|
||||
* (body frame - Forward, Right, Down)
|
||||
* linAccX, linAccY, linAccZ, angVelX, angVelY, angVelX
|
||||
* A row starting with "1" is a gps correction formatted with
|
||||
* N, E, D, qX, qY, qZ, qW
|
||||
* Note that for GPS correction, we're only using the position not the
|
||||
* rotation. The rotation is provided in the file for ground truth comparison.
|
||||
*
|
||||
* Usage: ./ImuFactorsExample [data_csv_path] [-c]
|
||||
* optional arguments:
|
||||
* data_csv_path path to the CSV file with the IMU data.
|
||||
* -c use CombinedImuFactor
|
||||
* Note: Define USE_LM to use Levenberg Marquardt Optimizer
|
||||
* By default ISAM2 is used
|
||||
* See usage: ./ImuFactorsExample --help
|
||||
*/
|
||||
|
||||
#include <boost/program_options.hpp>
|
||||
|
||||
// GTSAM related includes.
|
||||
#include <gtsam/inference/Symbol.h>
|
||||
#include <gtsam/navigation/CombinedImuFactor.h>
|
||||
#include <gtsam/navigation/GPSFactor.h>
|
||||
#include <gtsam/navigation/ImuFactor.h>
|
||||
#include <gtsam/slam/BetweenFactor.h>
|
||||
#include <gtsam/slam/dataset.h>
|
||||
#include <gtsam/nonlinear/ISAM2.h>
|
||||
#include <gtsam/nonlinear/LevenbergMarquardtOptimizer.h>
|
||||
#include <gtsam/nonlinear/NonlinearFactorGraph.h>
|
||||
#include <gtsam/nonlinear/ISAM2.h>
|
||||
#include <gtsam/inference/Symbol.h>
|
||||
#include <gtsam/slam/BetweenFactor.h>
|
||||
#include <gtsam/slam/dataset.h>
|
||||
|
||||
#include <cstring>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
|
||||
// Uncomment the following to use Levenberg Marquardt Optimizer
|
||||
// #define USE_LM
|
||||
|
||||
using namespace gtsam;
|
||||
using namespace std;
|
||||
|
||||
|
|
@ -64,45 +59,87 @@ using symbol_shorthand::B; // Bias (ax,ay,az,gx,gy,gz)
|
|||
using symbol_shorthand::V; // Vel (xdot,ydot,zdot)
|
||||
using symbol_shorthand::X; // Pose3 (x,y,z,r,p,y)
|
||||
|
||||
static const char output_filename[] = "imuFactorExampleResults.csv";
|
||||
static const char use_combined_imu_flag[3] = "-c";
|
||||
namespace po = boost::program_options;
|
||||
|
||||
po::variables_map parseOptions(int argc, char* argv[]) {
|
||||
po::options_description desc;
|
||||
desc.add_options()("help,h", "produce help message")(
|
||||
"data_csv_path", po::value<string>()->default_value("imuAndGPSdata.csv"),
|
||||
"path to the CSV file with the IMU data")(
|
||||
"output_filename",
|
||||
po::value<string>()->default_value("imuFactorExampleResults.csv"),
|
||||
"path to the result file to use")("use_isam", po::bool_switch(),
|
||||
"use ISAM as the optimizer");
|
||||
|
||||
po::variables_map vm;
|
||||
po::store(po::parse_command_line(argc, argv, desc), vm);
|
||||
|
||||
if (vm.count("help")) {
|
||||
cout << desc << "\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return vm;
|
||||
}
|
||||
|
||||
boost::shared_ptr<PreintegratedCombinedMeasurements::Params> imuParams() {
|
||||
// We use the sensor specs to build the noise model for the IMU factor.
|
||||
double accel_noise_sigma = 0.0003924;
|
||||
double gyro_noise_sigma = 0.000205689024915;
|
||||
double accel_bias_rw_sigma = 0.004905;
|
||||
double gyro_bias_rw_sigma = 0.000001454441043;
|
||||
Matrix33 measured_acc_cov = I_3x3 * pow(accel_noise_sigma, 2);
|
||||
Matrix33 measured_omega_cov = I_3x3 * pow(gyro_noise_sigma, 2);
|
||||
Matrix33 integration_error_cov =
|
||||
I_3x3 * 1e-8; // error committed in integrating position from velocities
|
||||
Matrix33 bias_acc_cov = I_3x3 * pow(accel_bias_rw_sigma, 2);
|
||||
Matrix33 bias_omega_cov = I_3x3 * pow(gyro_bias_rw_sigma, 2);
|
||||
Matrix66 bias_acc_omega_int =
|
||||
I_6x6 * 1e-5; // error in the bias used for preintegration
|
||||
|
||||
auto p = PreintegratedCombinedMeasurements::Params::MakeSharedD(0.0);
|
||||
// PreintegrationBase params:
|
||||
p->accelerometerCovariance =
|
||||
measured_acc_cov; // acc white noise in continuous
|
||||
p->integrationCovariance =
|
||||
integration_error_cov; // integration uncertainty continuous
|
||||
// should be using 2nd order integration
|
||||
// PreintegratedRotation params:
|
||||
p->gyroscopeCovariance =
|
||||
measured_omega_cov; // gyro white noise in continuous
|
||||
// PreintegrationCombinedMeasurements params:
|
||||
p->biasAccCovariance = bias_acc_cov; // acc bias in continuous
|
||||
p->biasOmegaCovariance = bias_omega_cov; // gyro bias in continuous
|
||||
p->biasAccOmegaInt = bias_acc_omega_int;
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
string data_filename;
|
||||
bool use_combined_imu = false;
|
||||
string data_filename, output_filename;
|
||||
|
||||
#ifndef USE_LM
|
||||
printf("Using ISAM2\n");
|
||||
ISAM2Params parameters;
|
||||
parameters.relinearizeThreshold = 0.01;
|
||||
parameters.relinearizeSkip = 1;
|
||||
ISAM2 isam2(parameters);
|
||||
#else
|
||||
printf("Using Levenberg Marquardt Optimizer\n");
|
||||
#endif
|
||||
bool use_isam = false;
|
||||
|
||||
po::variables_map var_map = parseOptions(argc, argv);
|
||||
|
||||
data_filename = findExampleDataFile(var_map["data_csv_path"].as<string>());
|
||||
output_filename = var_map["output_filename"].as<string>();
|
||||
use_isam = var_map["use_isam"].as<bool>();
|
||||
|
||||
ISAM2* isam2 = 0;
|
||||
if (use_isam) {
|
||||
printf("Using ISAM2\n");
|
||||
ISAM2Params parameters;
|
||||
parameters.relinearizeThreshold = 0.01;
|
||||
parameters.relinearizeSkip = 1;
|
||||
isam2 = new ISAM2(parameters);
|
||||
|
||||
if (argc < 2) {
|
||||
printf("using default CSV file\n");
|
||||
data_filename = findExampleDataFile("imuAndGPSdata.csv");
|
||||
} else if (argc < 3) {
|
||||
if (strcmp(argv[1], use_combined_imu_flag) == 0) {
|
||||
printf("using CombinedImuFactor\n");
|
||||
use_combined_imu = true;
|
||||
printf("using default CSV file\n");
|
||||
data_filename = findExampleDataFile("imuAndGPSdata.csv");
|
||||
} else {
|
||||
data_filename = argv[1];
|
||||
}
|
||||
} else {
|
||||
data_filename = argv[1];
|
||||
if (strcmp(argv[2], use_combined_imu_flag) == 0) {
|
||||
printf("using CombinedImuFactor\n");
|
||||
use_combined_imu = true;
|
||||
}
|
||||
printf("Using Levenberg Marquardt Optimizer\n");
|
||||
}
|
||||
|
||||
// Set up output file for plotting errors
|
||||
FILE* fp_out = fopen(output_filename, "w+");
|
||||
FILE* fp_out = fopen(output_filename.c_str(), "w+");
|
||||
fprintf(fp_out,
|
||||
"#time(s),x(m),y(m),z(m),qx,qy,qz,qw,gt_x(m),gt_y(m),gt_z(m),gt_qx,"
|
||||
"gt_qy,gt_qz,gt_qw\n");
|
||||
|
|
@ -118,10 +155,10 @@ int main(int argc, char* argv[]) {
|
|||
getline(file, value, ','); // i
|
||||
for (int i = 0; i < 9; i++) {
|
||||
getline(file, value, ',');
|
||||
initial_state(i) = atof(value.c_str());
|
||||
initial_state(i) = stof(value.c_str());
|
||||
}
|
||||
getline(file, value, '\n');
|
||||
initial_state(9) = atof(value.c_str());
|
||||
initial_state(9) = stof(value.c_str());
|
||||
cout << "initial state:\n" << initial_state.transpose() << "\n\n";
|
||||
|
||||
// Assemble initial quaternion through GTSAM constructor
|
||||
|
|
@ -152,43 +189,11 @@ int main(int argc, char* argv[]) {
|
|||
graph->addPrior(V(correction_count), prior_velocity, velocity_noise_model);
|
||||
graph->addPrior(B(correction_count), prior_imu_bias, bias_noise_model);
|
||||
|
||||
// We use the sensor specs to build the noise model for the IMU factor.
|
||||
double accel_noise_sigma = 0.0003924;
|
||||
double gyro_noise_sigma = 0.000205689024915;
|
||||
double accel_bias_rw_sigma = 0.004905;
|
||||
double gyro_bias_rw_sigma = 0.000001454441043;
|
||||
Matrix33 measured_acc_cov = I_3x3 * pow(accel_noise_sigma, 2);
|
||||
Matrix33 measured_omega_cov = I_3x3 * pow(gyro_noise_sigma, 2);
|
||||
Matrix33 integration_error_cov =
|
||||
I_3x3 * 1e-8; // error committed in integrating position from velocities
|
||||
Matrix33 bias_acc_cov = I_3x3 * pow(accel_bias_rw_sigma, 2);
|
||||
Matrix33 bias_omega_cov = I_3x3 * pow(gyro_bias_rw_sigma, 2);
|
||||
Matrix66 bias_acc_omega_int =
|
||||
I_6x6 * 1e-5; // error in the bias used for preintegration
|
||||
auto p = imuParams();
|
||||
|
||||
auto p = PreintegratedCombinedMeasurements::Params::MakeSharedD(0.0);
|
||||
// PreintegrationBase params:
|
||||
p->accelerometerCovariance =
|
||||
measured_acc_cov; // acc white noise in continuous
|
||||
p->integrationCovariance =
|
||||
integration_error_cov; // integration uncertainty continuous
|
||||
// should be using 2nd order integration
|
||||
// PreintegratedRotation params:
|
||||
p->gyroscopeCovariance =
|
||||
measured_omega_cov; // gyro white noise in continuous
|
||||
// PreintegrationCombinedMeasurements params:
|
||||
p->biasAccCovariance = bias_acc_cov; // acc bias in continuous
|
||||
p->biasOmegaCovariance = bias_omega_cov; // gyro bias in continuous
|
||||
p->biasAccOmegaInt = bias_acc_omega_int;
|
||||
std::shared_ptr<PreintegrationType> preintegrated =
|
||||
std::make_shared<PreintegratedImuMeasurements>(p, prior_imu_bias);
|
||||
|
||||
std::shared_ptr<PreintegrationType> preintegrated = nullptr;
|
||||
if (use_combined_imu) {
|
||||
preintegrated =
|
||||
std::make_shared<PreintegratedCombinedMeasurements>(p, prior_imu_bias);
|
||||
} else {
|
||||
preintegrated =
|
||||
std::make_shared<PreintegratedImuMeasurements>(p, prior_imu_bias);
|
||||
}
|
||||
assert(preintegrated);
|
||||
|
||||
// Store previous state for imu integration and latest predicted outcome.
|
||||
|
|
@ -207,16 +212,16 @@ int main(int argc, char* argv[]) {
|
|||
while (file.good()) {
|
||||
// Parse out first value
|
||||
getline(file, value, ',');
|
||||
int type = atoi(value.c_str());
|
||||
int type = stoi(value.c_str());
|
||||
|
||||
if (type == 0) { // IMU measurement
|
||||
Vector6 imu;
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
getline(file, value, ',');
|
||||
imu(i) = atof(value.c_str());
|
||||
imu(i) = stof(value.c_str());
|
||||
}
|
||||
getline(file, value, '\n');
|
||||
imu(5) = atof(value.c_str());
|
||||
imu(5) = stof(value.c_str());
|
||||
|
||||
// Adding the IMU preintegration.
|
||||
preintegrated->integrateMeasurement(imu.head<3>(), imu.tail<3>(), dt);
|
||||
|
|
@ -225,35 +230,24 @@ int main(int argc, char* argv[]) {
|
|||
Vector7 gps;
|
||||
for (int i = 0; i < 6; ++i) {
|
||||
getline(file, value, ',');
|
||||
gps(i) = atof(value.c_str());
|
||||
gps(i) = stof(value.c_str());
|
||||
}
|
||||
getline(file, value, '\n');
|
||||
gps(6) = atof(value.c_str());
|
||||
gps(6) = stof(value.c_str());
|
||||
|
||||
correction_count++;
|
||||
|
||||
// Adding IMU factor and GPS factor and optimizing.
|
||||
if (use_combined_imu) {
|
||||
auto preint_imu_combined =
|
||||
dynamic_cast<const PreintegratedCombinedMeasurements&>(
|
||||
*preintegrated);
|
||||
CombinedImuFactor imu_factor(
|
||||
X(correction_count - 1), V(correction_count - 1),
|
||||
X(correction_count), V(correction_count), B(correction_count - 1),
|
||||
B(correction_count), preint_imu_combined);
|
||||
graph->add(imu_factor);
|
||||
} else {
|
||||
auto preint_imu =
|
||||
dynamic_cast<const PreintegratedImuMeasurements&>(*preintegrated);
|
||||
ImuFactor imu_factor(X(correction_count - 1), V(correction_count - 1),
|
||||
X(correction_count), V(correction_count),
|
||||
B(correction_count - 1), preint_imu);
|
||||
graph->add(imu_factor);
|
||||
imuBias::ConstantBias zero_bias(Vector3(0, 0, 0), Vector3(0, 0, 0));
|
||||
graph->add(BetweenFactor<imuBias::ConstantBias>(
|
||||
B(correction_count - 1), B(correction_count), zero_bias,
|
||||
bias_noise_model));
|
||||
}
|
||||
auto preint_imu =
|
||||
dynamic_cast<const PreintegratedImuMeasurements&>(*preintegrated);
|
||||
ImuFactor imu_factor(X(correction_count - 1), V(correction_count - 1),
|
||||
X(correction_count), V(correction_count),
|
||||
B(correction_count - 1), preint_imu);
|
||||
graph->add(imu_factor);
|
||||
imuBias::ConstantBias zero_bias(Vector3(0, 0, 0), Vector3(0, 0, 0));
|
||||
graph->add(BetweenFactor<imuBias::ConstantBias>(
|
||||
B(correction_count - 1), B(correction_count), zero_bias,
|
||||
bias_noise_model));
|
||||
|
||||
auto correction_noise = noiseModel::Isotropic::Sigma(3, 1.0);
|
||||
GPSFactor gps_factor(X(correction_count),
|
||||
|
|
@ -270,18 +264,21 @@ int main(int argc, char* argv[]) {
|
|||
initial_values.insert(B(correction_count), prev_bias);
|
||||
|
||||
Values result;
|
||||
#ifdef USE_LM
|
||||
LevenbergMarquardtOptimizer optimizer(*graph, initial_values);
|
||||
result = optimizer.optimize();
|
||||
#else
|
||||
isam2.update(*graph, initial_values);
|
||||
isam2.update();
|
||||
result = isam2.calculateEstimate();
|
||||
|
||||
// reset the graph
|
||||
graph->resize(0);
|
||||
initial_values.clear();
|
||||
#endif
|
||||
if (use_isam) {
|
||||
isam2->update(*graph, initial_values);
|
||||
isam2->update();
|
||||
result = isam2->calculateEstimate();
|
||||
|
||||
// reset the graph
|
||||
graph->resize(0);
|
||||
initial_values.clear();
|
||||
|
||||
} else {
|
||||
LevenbergMarquardtOptimizer optimizer(*graph, initial_values);
|
||||
result = optimizer.optimize();
|
||||
}
|
||||
|
||||
// Overwrite the beginning of the preintegration for the next step.
|
||||
prev_state = NavState(result.at<Pose3>(X(correction_count)),
|
||||
result.at<Vector3>(V(correction_count)));
|
||||
|
|
|
|||
|
|
@ -1,3 +1,19 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
|
||||
* 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
|
||||
|
||||
* -------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* @file ImuFactorExample2
|
||||
* @brief Test example for using GTSAM ImuFactor and ImuCombinedFactor with ISAM2.
|
||||
* @author Robert Truax
|
||||
*/
|
||||
|
||||
#include <gtsam/geometry/PinholeCamera.h>
|
||||
#include <gtsam/geometry/Cal3_S2.h>
|
||||
|
|
@ -78,21 +78,22 @@ class UnaryFactor: public NoiseModelFactor1<Pose2> {
|
|||
UnaryFactor(Key j, double x, double y, const SharedNoiseModel& model):
|
||||
NoiseModelFactor1<Pose2>(model, j), mx_(x), my_(y) {}
|
||||
|
||||
virtual ~UnaryFactor() {}
|
||||
~UnaryFactor() override {}
|
||||
|
||||
// Using the NoiseModelFactor1 base class there are two functions that must be overridden.
|
||||
// The first is the 'evaluateError' function. This function implements the desired measurement
|
||||
// function, returning a vector of errors when evaluated at the provided variable value. It
|
||||
// must also calculate the Jacobians for this measurement function, if requested.
|
||||
Vector evaluateError(const Pose2& q,
|
||||
boost::optional<Matrix&> H = boost::none) const override {
|
||||
// The measurement function for a GPS-like measurement is simple:
|
||||
// error_x = pose.x - measurement.x
|
||||
// error_y = pose.y - measurement.y
|
||||
// Consequently, the Jacobians are:
|
||||
// [ derror_x/dx derror_x/dy derror_x/dtheta ] = [1 0 0]
|
||||
// [ derror_y/dx derror_y/dy derror_y/dtheta ] = [0 1 0]
|
||||
if (H) (*H) = (Matrix(2, 3) << 1.0, 0.0, 0.0, 0.0, 1.0, 0.0).finished();
|
||||
Vector evaluateError(const Pose2& q, boost::optional<Matrix&> H = boost::none) const override {
|
||||
// The measurement function for a GPS-like measurement h(q) which predicts the measurement (m) is h(q) = q, q = [qx qy qtheta]
|
||||
// The error is then simply calculated as E(q) = h(q) - m:
|
||||
// error_x = q.x - mx
|
||||
// error_y = q.y - my
|
||||
// Node's orientation reflects in the Jacobian, in tangent space this is equal to the right-hand rule rotation matrix
|
||||
// H = [ cos(q.theta) -sin(q.theta) 0 ]
|
||||
// [ sin(q.theta) cos(q.theta) 0 ]
|
||||
const Rot2& R = q.rotation();
|
||||
if (H) (*H) = (gtsam::Matrix(2, 3) << R.c(), -R.s(), 0.0, R.s(), R.c(), 0.0).finished();
|
||||
return (Vector(2) << q.x() - mx_, q.y() - my_).finished();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ int main(const int argc, const char* argv[]) {
|
|||
auto priorModel = noiseModel::Diagonal::Variances(
|
||||
(Vector(6) << 1e-6, 1e-6, 1e-6, 1e-4, 1e-4, 1e-4).finished());
|
||||
Key firstKey = 0;
|
||||
for (const Values::ConstKeyValuePair& key_value : *initial) {
|
||||
for (const auto key_value : *initial) {
|
||||
std::cout << "Adding prior to g2o file " << std::endl;
|
||||
firstKey = key_value.key;
|
||||
graph->addPrior(firstKey, Pose3(), priorModel);
|
||||
|
|
@ -74,7 +74,7 @@ int main(const int argc, const char* argv[]) {
|
|||
|
||||
// Calculate and print marginal covariances for all variables
|
||||
Marginals marginals(*graph, result);
|
||||
for (const auto& key_value : result) {
|
||||
for (const auto key_value : result) {
|
||||
auto p = dynamic_cast<const GenericValue<Pose3>*>(&key_value.value);
|
||||
if (!p) continue;
|
||||
std::cout << marginals.marginalCovariance(key_value.key) << endl;
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ int main(const int argc, const char *argv[]) {
|
|||
std::cout << "Rewriting input to file: " << inputFileRewritten << std::endl;
|
||||
// Additional: rewrite input with simplified keys 0,1,...
|
||||
Values simpleInitial;
|
||||
for(const Values::ConstKeyValuePair& key_value: *initial) {
|
||||
for(const auto key_value: *initial) {
|
||||
Key key;
|
||||
if(add)
|
||||
key = key_value.key + firstKey;
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ int main(const int argc, const char* argv[]) {
|
|||
auto priorModel = noiseModel::Diagonal::Variances(
|
||||
(Vector(6) << 1e-6, 1e-6, 1e-6, 1e-4, 1e-4, 1e-4).finished());
|
||||
Key firstKey = 0;
|
||||
for (const Values::ConstKeyValuePair& key_value : *initial) {
|
||||
for (const auto key_value : *initial) {
|
||||
std::cout << "Adding prior to g2o file " << std::endl;
|
||||
firstKey = key_value.key;
|
||||
graph->addPrior(firstKey, Pose3(), priorModel);
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ int main(const int argc, const char* argv[]) {
|
|||
auto priorModel = noiseModel::Diagonal::Variances(
|
||||
(Vector(6) << 1e-6, 1e-6, 1e-6, 1e-4, 1e-4, 1e-4).finished());
|
||||
Key firstKey = 0;
|
||||
for (const Values::ConstKeyValuePair& key_value : *initial) {
|
||||
for (const auto key_value : *initial) {
|
||||
std::cout << "Adding prior to g2o file " << std::endl;
|
||||
firstKey = key_value.key;
|
||||
graph->addPrior(firstKey, Pose3(), priorModel);
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ int main(const int argc, const char* argv[]) {
|
|||
auto priorModel = noiseModel::Diagonal::Variances(
|
||||
(Vector(6) << 1e-6, 1e-6, 1e-6, 1e-4, 1e-4, 1e-4).finished());
|
||||
Key firstKey = 0;
|
||||
for (const Values::ConstKeyValuePair& key_value : *initial) {
|
||||
for (const auto key_value : *initial) {
|
||||
std::cout << "Adding prior to g2o file " << std::endl;
|
||||
firstKey = key_value.key;
|
||||
graph->addPrior(firstKey, Pose3(), priorModel);
|
||||
|
|
|
|||
|
|
@ -51,13 +51,13 @@ The directory **vSLAMexample** includes 2 simple examples using GTSAM:
|
|||
|
||||
See the separate README file there.
|
||||
|
||||
##Undirected Graphical Models (UGM)
|
||||
## Undirected Graphical Models (UGM)
|
||||
The best representation for a Markov Random Field is a factor graph :-) This is illustrated with some discrete examples from the UGM MATLAB toolbox, which
|
||||
can be found at <http://www.di.ens.fr/~mschmidt/Software/UGM>
|
||||
|
||||
|
||||
##Building and Running
|
||||
To build, cd into the directory and do:
|
||||
## Building and Running
|
||||
To build, cd into the top-level gtsam directory and do:
|
||||
|
||||
```
|
||||
mkdir build
|
||||
|
|
|
|||
|
|
@ -25,6 +25,9 @@
|
|||
* Read 3D dataset sphere25000.txt and output to shonan.g2o (default)
|
||||
* ./ShonanAveragingCLI -i spere2500.txt
|
||||
*
|
||||
* If you prefer using a robust Huber loss, you can add the option "-h true",
|
||||
* for instance
|
||||
* ./ShonanAveragingCLI -i spere2500.txt -h true
|
||||
*/
|
||||
|
||||
#include <gtsam/base/timing.h>
|
||||
|
|
@ -43,7 +46,8 @@ int main(int argc, char* argv[]) {
|
|||
string datasetName;
|
||||
string inputFile;
|
||||
string outputFile;
|
||||
int d, seed;
|
||||
int d, seed, pMin;
|
||||
bool useHuberLoss;
|
||||
po::options_description desc(
|
||||
"Shonan Rotation Averaging CLI reads a *pose* graph, extracts the "
|
||||
"rotation constraints, and runs the Shonan algorithm.");
|
||||
|
|
@ -58,6 +62,10 @@ int main(int argc, char* argv[]) {
|
|||
"Write solution to the specified file")(
|
||||
"dimension,d", po::value<int>(&d)->default_value(3),
|
||||
"Optimize over 2D or 3D rotations")(
|
||||
"useHuberLoss,h", po::value<bool>(&useHuberLoss)->default_value(false),
|
||||
"set True to use Huber loss")("pMin,p",
|
||||
po::value<int>(&pMin)->default_value(3),
|
||||
"set to use desired rank pMin")(
|
||||
"seed,s", po::value<int>(&seed)->default_value(42),
|
||||
"Random seed for initial estimate");
|
||||
po::variables_map vm;
|
||||
|
|
@ -85,11 +93,14 @@ int main(int argc, char* argv[]) {
|
|||
NonlinearFactorGraph::shared_ptr inputGraph;
|
||||
Values::shared_ptr posesInFile;
|
||||
Values poses;
|
||||
auto lmParams = LevenbergMarquardtParams::CeresDefaults();
|
||||
if (d == 2) {
|
||||
cout << "Running Shonan averaging for SO(2) on " << inputFile << endl;
|
||||
ShonanAveraging2 shonan(inputFile);
|
||||
ShonanAveraging2::Parameters parameters(lmParams);
|
||||
parameters.setUseHuber(useHuberLoss);
|
||||
ShonanAveraging2 shonan(inputFile, parameters);
|
||||
auto initial = shonan.initializeRandomly(rng);
|
||||
auto result = shonan.run(initial);
|
||||
auto result = shonan.run(initial, pMin);
|
||||
|
||||
// Parse file again to set up translation problem, adding a prior
|
||||
boost::tie(inputGraph, posesInFile) = load2D(inputFile);
|
||||
|
|
@ -101,9 +112,11 @@ int main(int argc, char* argv[]) {
|
|||
poses = initialize::computePoses<Pose2>(result.first, &poseGraph);
|
||||
} else if (d == 3) {
|
||||
cout << "Running Shonan averaging for SO(3) on " << inputFile << endl;
|
||||
ShonanAveraging3 shonan(inputFile);
|
||||
ShonanAveraging3::Parameters parameters(lmParams);
|
||||
parameters.setUseHuber(useHuberLoss);
|
||||
ShonanAveraging3 shonan(inputFile, parameters);
|
||||
auto initial = shonan.initializeRandomly(rng);
|
||||
auto result = shonan.run(initial);
|
||||
auto result = shonan.run(initial, pMin);
|
||||
|
||||
// Parse file again to set up translation problem, adding a prior
|
||||
boost::tie(inputGraph, posesInFile) = load3D(inputFile);
|
||||
|
|
@ -118,7 +131,7 @@ int main(int argc, char* argv[]) {
|
|||
return 1;
|
||||
}
|
||||
cout << "Writing result to " << outputFile << endl;
|
||||
writeG2o(NonlinearFactorGraph(), poses, outputFile);
|
||||
writeG2o(*inputGraph, poses, outputFile);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -559,7 +559,7 @@ void runPerturb()
|
|||
|
||||
// Perturb values
|
||||
VectorValues noise;
|
||||
for(const Values::KeyValuePair& key_val: initial)
|
||||
for(const Values::KeyValuePair key_val: initial)
|
||||
{
|
||||
Vector noisev(key_val.value.dim());
|
||||
for(Vector::Index i = 0; i < noisev.size(); ++i)
|
||||
|
|
|
|||
|
|
@ -49,10 +49,7 @@ if(NOT GTSAM_USE_SYSTEM_EIGEN)
|
|||
|
||||
endif()
|
||||
|
||||
option(GTSAM_BUILD_METIS_EXECUTABLES "Build metis library executables" OFF)
|
||||
if(GTSAM_SUPPORT_NESTED_DISSECTION)
|
||||
add_subdirectory(metis)
|
||||
endif()
|
||||
# metis: already handled in ROOT/cmake/HandleMetis.cmake
|
||||
|
||||
add_subdirectory(ceres)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
cmake_minimum_required(VERSION 2.8)
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
project(METIS)
|
||||
|
||||
# Add flags for currect directory and below
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ endif()
|
|||
if(WIN32)
|
||||
set_target_properties(metis-gtsam PROPERTIES
|
||||
PREFIX ""
|
||||
COMPILE_FLAGS /w
|
||||
RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/../../../bin")
|
||||
endif()
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ project(gtsam LANGUAGES CXX)
|
|||
# The following variable is the master list of subdirs to add
|
||||
set (gtsam_subdirs
|
||||
base
|
||||
basis
|
||||
geometry
|
||||
inference
|
||||
symbolic
|
||||
|
|
@ -88,7 +89,8 @@ list(APPEND gtsam_srcs "${PROJECT_BINARY_DIR}/config.h" "${PROJECT_BINARY_DIR}/d
|
|||
install(FILES "${PROJECT_BINARY_DIR}/config.h" "${PROJECT_BINARY_DIR}/dllexport.h" DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/gtsam)
|
||||
|
||||
if(GTSAM_SUPPORT_NESTED_DISSECTION)
|
||||
list(APPEND GTSAM_ADDITIONAL_LIBRARIES metis-gtsam)
|
||||
# target metis-gtsam-if is defined in both cases: embedded metis or system version:
|
||||
list(APPEND GTSAM_ADDITIONAL_LIBRARIES metis-gtsam-if)
|
||||
endif()
|
||||
|
||||
# Versions
|
||||
|
|
@ -134,15 +136,15 @@ endif()
|
|||
# of any previously installed GTSAM headers.
|
||||
target_include_directories(gtsam BEFORE PUBLIC
|
||||
# main gtsam includes:
|
||||
$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}>
|
||||
$<BUILD_INTERFACE:${GTSAM_SOURCE_DIR}>
|
||||
$<INSTALL_INTERFACE:include/>
|
||||
# config.h
|
||||
$<BUILD_INTERFACE:${CMAKE_BINARY_DIR}>
|
||||
$<BUILD_INTERFACE:${GTSAM_BINARY_DIR}>
|
||||
# unit tests:
|
||||
$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/CppUnitLite>
|
||||
$<BUILD_INTERFACE:${GTSAM_SOURCE_DIR}/CppUnitLite>
|
||||
)
|
||||
# 3rdparty libraries: use the "system" flag so they are included via "-isystem"
|
||||
# and warnings (and warnings-considered-errors) in those headers are not
|
||||
# and warnings (and warnings-considered-errors) in those headers are not
|
||||
# reported as warnings/errors in our targets:
|
||||
target_include_directories(gtsam SYSTEM BEFORE PUBLIC
|
||||
# SuiteSparse_config
|
||||
|
|
@ -154,16 +156,6 @@ target_include_directories(gtsam SYSTEM BEFORE PUBLIC
|
|||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/CCOLAMD/Include>
|
||||
$<INSTALL_INTERFACE:include/gtsam/3rdparty/CCOLAMD>
|
||||
)
|
||||
if(GTSAM_SUPPORT_NESTED_DISSECTION)
|
||||
target_include_directories(gtsam BEFORE PUBLIC
|
||||
$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/gtsam/3rdparty/metis/include>
|
||||
$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/gtsam/3rdparty/metis/libmetis>
|
||||
$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/gtsam/3rdparty/metis/GKlib>
|
||||
$<INSTALL_INTERFACE:include/gtsam/3rdparty/metis/>
|
||||
)
|
||||
endif()
|
||||
|
||||
|
||||
|
||||
if(WIN32) # Add 'lib' prefix to static library to avoid filename collision with shared library
|
||||
if (NOT BUILD_SHARED_LIBS)
|
||||
|
|
@ -199,23 +191,8 @@ if(WIN32)
|
|||
else()
|
||||
if("${CMAKE_BUILD_TYPE}" STREQUAL "Release")
|
||||
# Suppress all warnings from 3rd party sources.
|
||||
set_source_files_properties(${3rdparty_srcs} PROPERTIES COMPILE_FLAGS "-w")
|
||||
set_source_files_properties(${3rdparty_srcs} PROPERTIES COMPILE_FLAGS "-w -Wno-everything")
|
||||
else()
|
||||
set_source_files_properties(${3rdparty_srcs} PROPERTIES COMPILE_FLAGS "-Wno-error")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Create the matlab toolbox for the gtsam library
|
||||
if (GTSAM_INSTALL_MATLAB_TOOLBOX)
|
||||
# Set up codegen
|
||||
include(GtsamMatlabWrap)
|
||||
|
||||
# Generate, build and install toolbox
|
||||
set(mexFlags "${GTSAM_BUILD_MEX_BINARY_FLAGS}")
|
||||
if(NOT BUILD_SHARED_LIBS)
|
||||
list(APPEND mexFlags -DGTSAM_IMPORT_STATIC)
|
||||
endif()
|
||||
|
||||
# Wrap
|
||||
wrap_and_install_library(gtsam.i "${GTSAM_ADDITIONAL_LIBRARIES}" "" "${mexFlags}")
|
||||
endif ()
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
#include <cstdlib> // Provides size_t
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
namespace gtsam {
|
||||
|
||||
|
|
@ -120,4 +121,12 @@ class IndexPair : public std::pair<size_t,size_t> {
|
|||
inline size_t i() const { return first; };
|
||||
inline size_t j() const { return second; };
|
||||
};
|
||||
|
||||
typedef std::vector<IndexPair> IndexPairVector;
|
||||
typedef std::set<IndexPair> IndexPairSet;
|
||||
|
||||
inline IndexPairVector IndexPairSetAsArray(IndexPairSet& set) { return IndexPairVector(set.begin(), set.end()); }
|
||||
|
||||
typedef std::map<IndexPair, IndexPairSet> IndexPairSetMap;
|
||||
typedef DSFMap<IndexPair> DSFMapIndexPair;
|
||||
} // namespace gtsam
|
||||
|
|
|
|||
|
|
@ -22,6 +22,8 @@
|
|||
#include <list>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/serialization/nvp.hpp>
|
||||
#include <boost/serialization/version.hpp>
|
||||
#include <boost/serialization/optional.hpp>
|
||||
#include <boost/serialization/list.hpp>
|
||||
|
||||
namespace gtsam {
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ public:
|
|||
}
|
||||
|
||||
/// Destructor
|
||||
virtual ~GenericValue() {
|
||||
~GenericValue() override {
|
||||
}
|
||||
|
||||
/// equals implementing generic Value interface
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
* @author Frank Dellaert
|
||||
* @author Mike Bosse
|
||||
* @author Duy Nguyen Ta
|
||||
* @author Yotam Stern
|
||||
*/
|
||||
|
||||
|
||||
|
|
@ -319,12 +320,28 @@ T expm(const Vector& x, int K=7) {
|
|||
}
|
||||
|
||||
/**
|
||||
* Linear interpolation between X and Y by coefficient t in [0, 1].
|
||||
* Linear interpolation between X and Y by coefficient t. Typically t \in [0,1],
|
||||
* but can also be used to extrapolate before pose X or after pose Y.
|
||||
*/
|
||||
template <typename T>
|
||||
T interpolate(const T& X, const T& Y, double t) {
|
||||
assert(t >= 0 && t <= 1);
|
||||
return traits<T>::Compose(X, traits<T>::Expmap(t * traits<T>::Logmap(traits<T>::Between(X, Y))));
|
||||
T interpolate(const T& X, const T& Y, double t,
|
||||
typename MakeOptionalJacobian<T, T>::type Hx = boost::none,
|
||||
typename MakeOptionalJacobian<T, T>::type Hy = boost::none) {
|
||||
if (Hx || Hy) {
|
||||
typename MakeJacobian<T, T>::type between_H_x, log_H, exp_H, compose_H_x;
|
||||
const T between =
|
||||
traits<T>::Between(X, Y, between_H_x); // between_H_y = identity
|
||||
typename traits<T>::TangentVector delta = traits<T>::Logmap(between, log_H);
|
||||
const T Delta = traits<T>::Expmap(t * delta, exp_H);
|
||||
const T result = traits<T>::Compose(
|
||||
X, Delta, compose_H_x); // compose_H_xinv_y = identity
|
||||
|
||||
if (Hx) *Hx = compose_H_x + t * exp_H * log_H * between_H_x;
|
||||
if (Hy) *Hy = t * exp_H * log_H;
|
||||
return result;
|
||||
}
|
||||
return traits<T>::Compose(
|
||||
X, traits<T>::Expmap(t * traits<T>::Logmap(traits<T>::Between(X, Y))));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -353,4 +370,4 @@ public:
|
|||
* the gtsam namespace to be more easily enforced as testable
|
||||
*/
|
||||
#define GTSAM_CONCEPT_LIE_INST(T) template class gtsam::IsLieGroup<T>;
|
||||
#define GTSAM_CONCEPT_LIE_TYPE(T) typedef gtsam::IsLieGroup<T> _gtsam_IsLieGroup_##T;
|
||||
#define GTSAM_CONCEPT_LIE_TYPE(T) using _gtsam_IsLieGroup_##T = gtsam::IsLieGroup<T>;
|
||||
|
|
|
|||
|
|
@ -178,4 +178,4 @@ struct FixedDimension {
|
|||
// * the gtsam namespace to be more easily enforced as testable
|
||||
// */
|
||||
#define GTSAM_CONCEPT_MANIFOLD_INST(T) template class gtsam::IsManifold<T>;
|
||||
#define GTSAM_CONCEPT_MANIFOLD_TYPE(T) typedef gtsam::IsManifold<T> _gtsam_IsManifold_##T;
|
||||
#define GTSAM_CONCEPT_MANIFOLD_TYPE(T) using _gtsam_IsManifold_##T = gtsam::IsManifold<T>;
|
||||
|
|
|
|||
|
|
@ -153,7 +153,7 @@ const Eigen::IOFormat& matlabFormat() {
|
|||
/* ************************************************************************* */
|
||||
//3 argument call
|
||||
void print(const Matrix& A, const string &s, ostream& stream) {
|
||||
cout << s << A.format(matlabFormat()) << endl;
|
||||
stream << s << A.format(matlabFormat()) << endl;
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@
|
|||
#include <gtsam/config.h>
|
||||
|
||||
#include <boost/format.hpp>
|
||||
#include <boost/function.hpp>
|
||||
#include <functional>
|
||||
#include <boost/tuple/tuple.hpp>
|
||||
#include <boost/math/special_functions/fpclassify.hpp>
|
||||
|
||||
|
|
@ -46,28 +46,28 @@ typedef Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> M
|
|||
// Create handy typedefs and constants for square-size matrices
|
||||
// MatrixMN, MatrixN = MatrixNN, I_NxN, and Z_NxN, for M,N=1..9
|
||||
#define GTSAM_MAKE_MATRIX_DEFS(N) \
|
||||
typedef Eigen::Matrix<double, N, N> Matrix##N; \
|
||||
typedef Eigen::Matrix<double, 1, N> Matrix1##N; \
|
||||
typedef Eigen::Matrix<double, 2, N> Matrix2##N; \
|
||||
typedef Eigen::Matrix<double, 3, N> Matrix3##N; \
|
||||
typedef Eigen::Matrix<double, 4, N> Matrix4##N; \
|
||||
typedef Eigen::Matrix<double, 5, N> Matrix5##N; \
|
||||
typedef Eigen::Matrix<double, 6, N> Matrix6##N; \
|
||||
typedef Eigen::Matrix<double, 7, N> Matrix7##N; \
|
||||
typedef Eigen::Matrix<double, 8, N> Matrix8##N; \
|
||||
typedef Eigen::Matrix<double, 9, N> Matrix9##N; \
|
||||
using Matrix##N = Eigen::Matrix<double, N, N>; \
|
||||
using Matrix1##N = Eigen::Matrix<double, 1, N>; \
|
||||
using Matrix2##N = Eigen::Matrix<double, 2, N>; \
|
||||
using Matrix3##N = Eigen::Matrix<double, 3, N>; \
|
||||
using Matrix4##N = Eigen::Matrix<double, 4, N>; \
|
||||
using Matrix5##N = Eigen::Matrix<double, 5, N>; \
|
||||
using Matrix6##N = Eigen::Matrix<double, 6, N>; \
|
||||
using Matrix7##N = Eigen::Matrix<double, 7, N>; \
|
||||
using Matrix8##N = Eigen::Matrix<double, 8, N>; \
|
||||
using Matrix9##N = Eigen::Matrix<double, 9, N>; \
|
||||
static const Eigen::MatrixBase<Matrix##N>::IdentityReturnType I_##N##x##N = Matrix##N::Identity(); \
|
||||
static const Eigen::MatrixBase<Matrix##N>::ConstantReturnType Z_##N##x##N = Matrix##N::Zero();
|
||||
|
||||
GTSAM_MAKE_MATRIX_DEFS(1);
|
||||
GTSAM_MAKE_MATRIX_DEFS(2);
|
||||
GTSAM_MAKE_MATRIX_DEFS(3);
|
||||
GTSAM_MAKE_MATRIX_DEFS(4);
|
||||
GTSAM_MAKE_MATRIX_DEFS(5);
|
||||
GTSAM_MAKE_MATRIX_DEFS(6);
|
||||
GTSAM_MAKE_MATRIX_DEFS(7);
|
||||
GTSAM_MAKE_MATRIX_DEFS(8);
|
||||
GTSAM_MAKE_MATRIX_DEFS(9);
|
||||
GTSAM_MAKE_MATRIX_DEFS(1)
|
||||
GTSAM_MAKE_MATRIX_DEFS(2)
|
||||
GTSAM_MAKE_MATRIX_DEFS(3)
|
||||
GTSAM_MAKE_MATRIX_DEFS(4)
|
||||
GTSAM_MAKE_MATRIX_DEFS(5)
|
||||
GTSAM_MAKE_MATRIX_DEFS(6)
|
||||
GTSAM_MAKE_MATRIX_DEFS(7)
|
||||
GTSAM_MAKE_MATRIX_DEFS(8)
|
||||
GTSAM_MAKE_MATRIX_DEFS(9)
|
||||
|
||||
// Matrix expressions for accessing parts of matrices
|
||||
typedef Eigen::Block<Matrix> SubMatrix;
|
||||
|
|
@ -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 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;
|
||||
}
|
||||
}
|
||||
|
|
@ -489,7 +489,7 @@ struct MultiplyWithInverseFunction {
|
|||
|
||||
// The function phi should calculate f(a)*b, with derivatives in a and b.
|
||||
// Naturally, the derivative in b is f(a).
|
||||
typedef boost::function<VectorN(
|
||||
typedef std::function<VectorN(
|
||||
const T&, const VectorN&, OptionalJacobian<N, M>, OptionalJacobian<N, N>)>
|
||||
Operator;
|
||||
|
||||
|
|
|
|||
|
|
@ -89,6 +89,13 @@ public:
|
|||
usurp(dynamic.data());
|
||||
}
|
||||
|
||||
/// Constructor that will resize a dynamic matrix (unless already correct)
|
||||
OptionalJacobian(Eigen::MatrixXd* dynamic) :
|
||||
map_(nullptr) {
|
||||
dynamic->resize(Rows, Cols); // no malloc if correct size
|
||||
usurp(dynamic->data());
|
||||
}
|
||||
|
||||
#ifndef OPTIONALJACOBIAN_NOBOOST
|
||||
|
||||
/// Constructor with boost::none just makes empty
|
||||
|
|
@ -112,7 +119,7 @@ public:
|
|||
// template <typename Derived, bool InnerPanel>
|
||||
// OptionalJacobian(Eigen::Block<Derived,Rows,Cols,InnerPanel> block) : map_(nullptr) { ?? }
|
||||
|
||||
/// Return true is allocated, false if default constructor was used
|
||||
/// Return true if allocated, false if default constructor was used
|
||||
operator bool() const {
|
||||
return map_.data() != nullptr;
|
||||
}
|
||||
|
|
@ -197,7 +204,7 @@ public:
|
|||
|
||||
#endif
|
||||
|
||||
/// Return true is allocated, false if default constructor was used
|
||||
/// Return true if allocated, false if default constructor was used
|
||||
operator bool() const {
|
||||
return pointer_!=nullptr;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -161,6 +161,9 @@ public:
|
|||
}
|
||||
return v;
|
||||
}
|
||||
static TangentVector LocalCoordinates(const ProductLieGroup& p, ChartJacobian Hp = boost::none) {
|
||||
return Logmap(p, Hp);
|
||||
}
|
||||
ProductLieGroup expmap(const TangentVector& v) const {
|
||||
return compose(ProductLieGroup::Expmap(v));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,9 +33,10 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/concept_check.hpp>
|
||||
#include <stdio.h>
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#define GTSAM_PRINT(x)((x).print(#x))
|
||||
|
|
@ -72,10 +73,10 @@ namespace gtsam {
|
|||
}; // \ Testable
|
||||
|
||||
inline void print(float v, const std::string& s = "") {
|
||||
printf("%s%f\n",s.c_str(),v);
|
||||
std::cout << (s.empty() ? s : s + " ") << v << std::endl;
|
||||
}
|
||||
inline void print(double v, const std::string& s = "") {
|
||||
printf("%s%lf\n",s.c_str(),v);
|
||||
std::cout << (s.empty() ? s : s + " ") << v << std::endl;
|
||||
}
|
||||
|
||||
/** Call equal on the object */
|
||||
|
|
@ -119,10 +120,10 @@ namespace gtsam {
|
|||
* Binary predicate on shared pointers
|
||||
*/
|
||||
template<class V>
|
||||
struct equals_star : public std::function<bool(const boost::shared_ptr<V>&, const boost::shared_ptr<V>&)> {
|
||||
struct equals_star : public std::function<bool(const std::shared_ptr<V>&, const std::shared_ptr<V>&)> {
|
||||
double tol_;
|
||||
equals_star(double tol = 1e-9) : tol_(tol) {}
|
||||
bool operator()(const boost::shared_ptr<V>& expected, const boost::shared_ptr<V>& actual) {
|
||||
bool operator()(const std::shared_ptr<V>& expected, const std::shared_ptr<V>& actual) {
|
||||
if (!actual && !expected) return true;
|
||||
return actual && expected && traits<V>::Equals(*actual,*expected, tol_);
|
||||
}
|
||||
|
|
@ -172,4 +173,4 @@ namespace gtsam {
|
|||
* @deprecated please use BOOST_CONCEPT_ASSERT and
|
||||
*/
|
||||
#define GTSAM_CONCEPT_TESTABLE_INST(T) template class gtsam::IsTestable<T>;
|
||||
#define GTSAM_CONCEPT_TESTABLE_TYPE(T) typedef gtsam::IsTestable<T> _gtsam_Testable_##T;
|
||||
#define GTSAM_CONCEPT_TESTABLE_TYPE(T) using _gtsam_Testable_##T = gtsam::IsTestable<T>;
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
#include <boost/optional.hpp>
|
||||
#include <map>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
|
||||
namespace gtsam {
|
||||
|
|
@ -84,7 +85,7 @@ bool assert_equal(const V& expected, const boost::optional<const V&>& actual, do
|
|||
* \deprecated: use container equals instead
|
||||
*/
|
||||
template<class V>
|
||||
bool assert_equal(const std::vector<V>& expected, const std::vector<V>& actual, double tol = 1e-9) {
|
||||
bool GTSAM_DEPRECATED assert_equal(const std::vector<V>& expected, const std::vector<V>& actual, double tol = 1e-9) {
|
||||
bool match = true;
|
||||
if (expected.size() != actual.size())
|
||||
match = false;
|
||||
|
|
@ -349,4 +350,47 @@ bool assert_inequal(const V& expected, const V& actual, double tol = 1e-9) {
|
|||
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.
|
||||
*
|
||||
* @param s: Optional string to pass to the print() method.
|
||||
*/
|
||||
template <class V>
|
||||
bool assert_print_equal(const std::string& expected, const V& actual,
|
||||
const std::string& s = "") {
|
||||
// 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(s);
|
||||
|
||||
// Get output string and reset stdout
|
||||
std::string actual_ = buffer.str();
|
||||
std::cout.rdbuf(old);
|
||||
|
||||
return assert_equal(expected, actual_);
|
||||
}
|
||||
|
||||
} // \namespace gtsam
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue