Compare commits

..

No commits in common. "f64ebfd4d8e59ec3c0d3a63ce4a23acbf0019858" and "cc4a0e18048354a2dad3492b0c220a00019277ef" have entirely different histories.

27 changed files with 148 additions and 328 deletions

View File

@ -1,7 +1,7 @@
# This workflow builds the Python wheels using cibuildwheel and uploads them to TestPyPI.
# It can be triggered on push to the develop branch or manually via Github Actions.
name: Build Wheels for Develop
name: Build Wheels (cibuildwheel)
on:
push:

View File

@ -1,188 +0,0 @@
# This workflow builds the Python wheels using cibuildwheel and uploads them to TestPyPI.
# It can be triggered on push to the develop branch or manually via Github Actions.
name: Build Wheels for Release
on:
release:
types: [published]
workflow_dispatch:
jobs:
build_wheels:
name: Build Wheels
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
# Linux x86_64
- os: ubuntu-latest
python_version: "3.10"
cibw_python_version: 310
platform_id: manylinux_x86_64
manylinux_image: manylinux2014
- os: ubuntu-latest
python_version: "3.11"
cibw_python_version: 311
platform_id: manylinux_x86_64
manylinux_image: manylinux2014
- os: ubuntu-latest
python_version: "3.12"
cibw_python_version: 312
platform_id: manylinux_x86_64
manylinux_image: manylinux2014
- os: ubuntu-latest
python_version: "3.13"
cibw_python_version: 313
platform_id: manylinux_x86_64
manylinux_image: manylinux2014
# Linux aarch64
- os: ubuntu-24.04-arm
python_version: "3.10"
cibw_python_version: 310
platform_id: manylinux_aarch64
manylinux_image: manylinux2014
- os: ubuntu-24.04-arm
python_version: "3.11"
cibw_python_version: 311
platform_id: manylinux_aarch64
manylinux_image: manylinux2014
- os: ubuntu-24.04-arm
python_version: "3.12"
cibw_python_version: 312
platform_id: manylinux_aarch64
manylinux_image: manylinux2014
- os: ubuntu-24.04-arm
python_version: "3.13"
cibw_python_version: 313
platform_id: manylinux_aarch64
manylinux_image: manylinux2014
# MacOS x86_64
- os: macos-13
python_version: "3.10"
cibw_python_version: 310
platform_id: macosx_x86_64
- os: macos-13
python_version: "3.11"
cibw_python_version: 311
platform_id: macosx_x86_64
- os: macos-13
python_version: "3.12"
cibw_python_version: 312
platform_id: macosx_x86_64
- os: macos-13
python_version: "3.13"
cibw_python_version: 313
platform_id: macosx_x86_64
# MacOS arm64
- os: macos-14
python_version: "3.10"
cibw_python_version: 310
platform_id: macosx_arm64
- os: macos-14
python_version: "3.11"
cibw_python_version: 311
platform_id: macosx_arm64
- os: macos-14
python_version: "3.12"
cibw_python_version: 312
platform_id: macosx_arm64
- os: macos-14
python_version: "3.13"
cibw_python_version: 313
platform_id: macosx_arm64
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
ref: ${{ github.sha }}
- name: Set up Python ${{ matrix.python_version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python_version }}
- name: Install Dependencies
run: |
python3 -m pip install -r python/dev_requirements.txt
if [ "$RUNNER_OS" == "Linux" ]; then
sudo apt-get install -y wget libicu-dev python3-pip python3-setuptools libboost-all-dev ninja-build
elif [ "$RUNNER_OS" == "macOS" ]; then
brew install boost ninja python-setuptools
else
echo "$RUNNER_OS not supported"
exit 1
fi
# We first build the Python wrapper module on the host machine. This is done because cibuildwheel
# expects a setup.py file to be present in the project directory.
#
# The Python wrapper module is then rebuilt within the cibuildwheel container before building
# the wheels to ensure platform compatibility.
- name: Run CMake
run: |
cmake . -B build -DGTSAM_BUILD_PYTHON=1 -DGTSAM_PYTHON_VERSION=${{ matrix.python_version }}
# If on macOS, we previously installed boost using homebrew for the first build.
# We need to uninstall it before building the wheels with cibuildwheel, which will
# install boost from source.
- name: Uninstall Boost (MacOS)
if: runner.os == 'macOS'
run: |
brew uninstall boost
- name: Build and test wheels
env:
# Generate the platform identifier. See https://cibuildwheel.pypa.io/en/stable/options/#build-skip.
CIBW_BUILD: cp${{ matrix.cibw_python_version }}-${{ matrix.platform_id }}
CIBW_MANYLINUX_X86_64_IMAGE: ${{ matrix.manylinux_image }}
CIBW_MANYLINUX_AARCH64_IMAGE: ${{ matrix.manylinux_image }}
CIBW_ARCHS: all
# Set the minimum required MacOS version for the wheels.
MACOSX_DEPLOYMENT_TARGET: 10.15
# Set DYLD_LIBRARY_PATH to REPAIR_LIBRARY_PATH, which is set in cibw_before_all.sh. REPAIR_LIBRARY_PATH
# simply appends BOOST_LIBRARYDIR to the path, which is required during during link-time repair.
CIBW_REPAIR_WHEEL_COMMAND_MACOS: DYLD_LIBRARY_PATH=$REPAIR_LIBRARY_PATH delocate-wheel --require-archs {delocate_archs} -w {dest_dir} -v {wheel}
# Use build instead of pip wheel to build the wheels. This is recommended by PyPA.
# See https://cibuildwheel.pypa.io/en/stable/options/#build-frontend.
CIBW_BUILD_FRONTEND: "build"
CIBW_BEFORE_ALL: bash .github/scripts/python_wheels/cibw_before_all.sh ${{ matrix.python_version }} {project}
CIBW_BUILD_VERBOSITY: 1
run: bash .github/scripts/python_wheels/build_wheels.sh
- name: Store artifacts
uses: actions/upload-artifact@v4
with:
name: cibw-wheels-cp${{ matrix.cibw_python_version }}-${{ matrix.platform_id }}
path: wheelhouse/*.whl
upload_all:
name: Upload All
needs: build_wheels
runs-on: ubuntu-latest
permissions:
id-token: write
steps:
- name: Download Artifacts
uses: actions/download-artifact@v4
with:
path: dist/
merge-multiple: true
- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
verbose: true
packages-dir: dist/
repository-url: https://test.pypi.org/legacy/

View File

@ -55,9 +55,6 @@ 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.
There is a flag `GTSAM_ALLOW_DEPRECATED_SINCE_V43` for newly deprecated methods since the 4.3 release, which is on by default, allowing anyone to just pull version 4.3 and compile.
## Wrappers
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.

View File

@ -6,88 +6,51 @@
# Boost_NO_SYSTEM_PATHS: set to true to keep the find script from ignoring BOOST_ROOT
if(MSVC)
set(Boost_USE_STATIC_LIBS ON)
# 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()
if(MSVC_VERSION LESS 1910)
list_append_cache(GTSAM_COMPILE_OPTIONS_PRIVATE -Zm295)
# 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()
# ---- 使 FindBoost CONFIG ----
set(Boost_NO_BOOST_CMAKE ON CACHE BOOL "Use FindBoost module mode" FORCE)
# 线
set(Boost_USE_MULTITHREADED ON)
#
# 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)
# ---- system ----
set(BOOST_FIND_MINIMUM_COMPONENTS
serialization filesystem thread program_options date_time timer chrono regex
)
find_package(Boost ${BOOST_FIND_MINIMUM_VERSION} COMPONENTS ${BOOST_FIND_MINIMUM_COMPONENTS} REQUIRED)
# Boost (< 1.69) system>=1.69 header-only
# Boost_VERSION find_package
# system system
# Boost_VERSION
# system Boost>=1.69
message(STATUS "Trying Boost without 'system' component first (>=1.69 header-only)...")
set(_boost_try_components ${BOOST_FIND_MINIMUM_COMPONENTS})
set(_boost_found FALSE)
find_package(Boost ${BOOST_FIND_MINIMUM_VERSION} COMPONENTS ${_boost_try_components} QUIET)
if(Boost_FOUND)
set(_boost_found TRUE)
else()
# system Boost<1.69
message(STATUS "Retrying Boost with 'system' component for older Boost (<1.69)...")
list(APPEND _boost_try_components system)
find_package(Boost ${BOOST_FIND_MINIMUM_VERSION} COMPONENTS ${_boost_try_components} REQUIRED)
# 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()
#
set(BOOST_FIND_MINIMUM_COMPONENTS ${_boost_try_components})
# ---- Boost_SYSTEM_LIBRARY ----
set(_missing_required FALSE)
foreach(_comp IN LISTS BOOST_FIND_MINIMUM_COMPONENTS)
string(TOUPPER "${_comp}" _COMP_UP)
if(NOT DEFINED "Boost_${_COMP_UP}_LIBRARY" AND NOT TARGET "Boost::${_comp}")
# header-only *_LIBRARY
# header-only system>=1.69
message(STATUS "Note: Boost component '${_comp}' has no explicit *_LIBRARY var; relying on imported target or headers.")
endif()
endforeach()
# ---- ----
option(GTSAM_DISABLE_NEW_TIMERS "Disables using Boost.chrono for timing" OFF)
# ---- Boost::system----
# 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::filesystem
Boost::thread
Boost::date_time
Boost::regex
Boost::serialization
Boost::system
Boost::filesystem
Boost::thread
Boost::date_time
Boost::regex
)
# chrono/timer
if(TARGET Boost::chrono)
list(APPEND GTSAM_BOOST_LIBRARIES Boost::chrono)
endif()
if(TARGET Boost::timer)
list(APPEND GTSAM_BOOST_LIBRARIES Boost::timer)
endif()
# system Boost Boost::system
if("system" IN_LIST BOOST_FIND_MINIMUM_COMPONENTS AND TARGET Boost::system)
list(APPEND GTSAM_BOOST_LIBRARIES Boost::system)
endif()
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()

View File

@ -1,17 +1,10 @@
#pragma once
#include <gtsam/dllexport.h>
#include <iostream>
#include <random>
#include <sstream>
#include <string>
#include <iostream>
#include <sstream>
/**
* @brief Global default pseudo-random number generator object.
* In wrappers we can access std::mt19937_64 via gtsam.MT19937
*/
static std::mt19937_64 kRandomNumberGenerator(42);
#include <gtsam/dllexport.h>
namespace gtsam {
/**
@ -35,7 +28,7 @@ private:
std::streambuf* coutBuffer_;
};
} // namespace gtsam
}
namespace gtsam {
// Adapted from https://stackoverflow.com/a/32223343/9151520

View File

@ -18,7 +18,6 @@
#include <gtsam/base/Testable.h>
#include <gtsam/base/debug.h>
#include <gtsam/base/utilities.h>
#include <gtsam/discrete/DiscreteConditional.h>
#include <gtsam/discrete/Ring.h>
#include <gtsam/discrete/Signature.h>

View File

@ -27,6 +27,9 @@
#include <string>
#include <vector>
// In wrappers we can access std::mt19937_64 via gtsam.MT19937
static std::mt19937_64 kRandomNumberGenerator(42);
namespace gtsam {
/**

View File

@ -127,9 +127,6 @@ class GTSAM_EXPORT DiscreteFactorGraph
template <class DERIVED_FACTOR>
DiscreteFactorGraph(const FactorGraph<DERIVED_FACTOR>& graph) : Base(graph) {}
/// Destructor
virtual ~DiscreteFactorGraph() {}
/// @name Testable
/// @{

View File

@ -17,7 +17,6 @@
#include <gtsam/base/Testable.h>
#include <gtsam/base/debug.h>
#include <gtsam/base/utilities.h>
#include <gtsam/discrete/Ring.h>
#include <gtsam/discrete/Signature.h>
#include <gtsam/discrete/TableDistribution.h>

View File

@ -202,6 +202,16 @@ HybridValues HybridBayesNet::sample(std::mt19937_64 *rng) const {
return sample(given, rng);
}
/* ************************************************************************* */
HybridValues HybridBayesNet::sample(const HybridValues &given) const {
return sample(given, &kRandomNumberGenerator);
}
/* ************************************************************************* */
HybridValues HybridBayesNet::sample() const {
return sample(&kRandomNumberGenerator);
}
/* ************************************************************************* */
AlgebraicDecisionTree<Key> HybridBayesNet::errorTree(
const VectorValues &continuousValues) const {

View File

@ -181,11 +181,10 @@ class GTSAM_EXPORT HybridBayesNet : public BayesNet<HybridConditional> {
* auto sample = bn.sample(given, &rng);
*
* @param given Values of missing variables.
* @param rng The optional pseudo-random number generator.
* @param rng The pseudo-random number generator.
* @return HybridValues
*/
HybridValues sample(const HybridValues &given,
std::mt19937_64 *rng = nullptr) const;
HybridValues sample(const HybridValues &given, std::mt19937_64 *rng) const;
/**
* @brief Sample using ancestral sampling.
@ -194,10 +193,25 @@ class GTSAM_EXPORT HybridBayesNet : public BayesNet<HybridConditional> {
* std::mt19937_64 rng(42);
* auto sample = bn.sample(&rng);
*
* @param rng The optional pseudo-random number generator.
* @param rng The pseudo-random number generator.
* @return HybridValues
*/
HybridValues sample(std::mt19937_64 *rng = nullptr) const;
HybridValues sample(std::mt19937_64 *rng) const;
/**
* @brief Sample from an incomplete BayesNet, use default rng.
*
* @param given Values of missing variables.
* @return HybridValues
*/
HybridValues sample(const HybridValues &given) const;
/**
* @brief Sample using ancestral sampling, use default rng.
*
* @return HybridValues
*/
HybridValues sample() const;
/**
* @brief Prune the Bayes Net such that we have at most maxNrLeaves leaves.

View File

@ -158,8 +158,10 @@ class HybridBayesNet {
gtsam::HybridValues optimize() const;
gtsam::VectorValues optimize(const gtsam::DiscreteValues& assignment) const;
gtsam::HybridValues sample(const gtsam::HybridValues& given, std::mt19937_64@ rng = nullptr) const;
gtsam::HybridValues sample(std::mt19937_64@ rng = nullptr) const;
gtsam::HybridValues sample(const gtsam::HybridValues& given, std::mt19937_64@ rng) const;
gtsam::HybridValues sample(std::mt19937_64@ rng) const;
gtsam::HybridValues sample(const gtsam::HybridValues& given) const;
gtsam::HybridValues sample() const;
void print(string s = "HybridBayesNet\n",
const gtsam::KeyFormatter& keyFormatter =

View File

@ -28,7 +28,6 @@ namespace gtsam {
/// Assign default key formatter
KeyFormatter DefaultKeyFormatter = &_defaultKeyFormatter;
KeyFormatter MultiRobotKeyFormatter = &_multirobotKeyFormatter;
/* ************************************************************************* */
string _defaultKeyFormatter(Key key) {

View File

@ -57,7 +57,8 @@ GTSAM_EXPORT std::string _multirobotKeyFormatter(gtsam::Key key);
/// formatter in print functions.
///
/// Checks for LabeledSymbol, Symbol and then plain keys, in order.
extern GTSAM_EXPORT KeyFormatter MultiRobotKeyFormatter;
static const gtsam::KeyFormatter MultiRobotKeyFormatter =
&_multirobotKeyFormatter;
/// To use the key_formatter on Keys, they must be wrapped in a StreamedKey.
struct StreamedKey {

View File

@ -26,6 +26,9 @@
using namespace std;
using namespace gtsam;
// In Wrappers we have no access to this so have a default ready
static std::mt19937_64 kRandomNumberGenerator(42);
namespace gtsam {
// Instantiate base class
@ -73,6 +76,15 @@ namespace gtsam {
return result;
}
/* ************************************************************************ */
VectorValues GaussianBayesNet::sample() const {
return sample(&kRandomNumberGenerator);
}
VectorValues GaussianBayesNet::sample(const VectorValues& given) const {
return sample(given, &kRandomNumberGenerator);
}
/* ************************************************************************ */
VectorValues GaussianBayesNet::optimizeGradientSearch() const
{

View File

@ -131,7 +131,7 @@ namespace gtsam {
* std::mt19937_64 rng(42);
* auto sample = gbn.sample(&rng);
*/
VectorValues sample(std::mt19937_64* rng = nullptr) const;
VectorValues sample(std::mt19937_64* rng) const;
/**
* Sample from an incomplete BayesNet, given missing variables
@ -140,7 +140,13 @@ namespace gtsam {
* VectorValues given = ...;
* auto sample = gbn.sample(given, &rng);
*/
VectorValues sample(const VectorValues& given, std::mt19937_64* rng = nullptr) const;
VectorValues sample(const VectorValues& given, std::mt19937_64* rng) const;
/// Sample using ancestral sampling, use default rng
VectorValues sample() const;
/// Sample from an incomplete BayesNet, use default rng
VectorValues sample(const VectorValues& given) const;
/**
* Return ordering corresponding to a topological sort.

View File

@ -15,12 +15,11 @@
* @author Christian Potthast, Frank Dellaert
*/
#include <gtsam/base/utilities.h>
#include <gtsam/hybrid/HybridValues.h>
#include <gtsam/linear/GaussianConditional.h>
#include <gtsam/linear/Sampler.h>
#include <gtsam/linear/VectorValues.h>
#include <gtsam/linear/linearExceptions.h>
#include <gtsam/hybrid/HybridValues.h>
#ifdef __GNUC__
#pragma GCC diagnostic push
@ -35,6 +34,9 @@
#include <string>
#include <cmath>
// In wrappers we can access std::mt19937_64 via gtsam.MT19937
static std::mt19937_64 kRandomNumberGenerator(42);
using namespace std;
namespace gtsam {
@ -345,10 +347,6 @@ namespace gtsam {
VectorValues solution = solve(parentsValues);
Key key = firstFrontalKey();
// Check if rng is nullptr, then assign default
rng = (rng == nullptr) ? &kRandomNumberGenerator : rng;
// The vector of sigma values for sampling.
// If no model, initialize sigmas to 1, else to model sigmas
const Vector& sigmas = (!model_) ? Vector::Ones(rows()) : model_->sigmas();
@ -361,7 +359,16 @@ namespace gtsam {
throw std::invalid_argument(
"sample() can only be invoked on no-parent prior");
VectorValues values;
return sample(values, rng);
return sample(values);
}
/* ************************************************************************ */
VectorValues GaussianConditional::sample() const {
return sample(&kRandomNumberGenerator);
}
VectorValues GaussianConditional::sample(const VectorValues& given) const {
return sample(given, &kRandomNumberGenerator);
}
/* ************************************************************************ */

View File

@ -217,7 +217,7 @@ namespace gtsam {
* std::mt19937_64 rng(42);
* auto sample = gc.sample(&rng);
*/
VectorValues sample(std::mt19937_64* rng = nullptr) const;
VectorValues sample(std::mt19937_64* rng) const;
/**
* Sample from conditional, given missing variables
@ -227,7 +227,13 @@ namespace gtsam {
* auto sample = gc.sample(given, &rng);
*/
VectorValues sample(const VectorValues& parentsValues,
std::mt19937_64* rng = nullptr) const;
std::mt19937_64* rng) const;
/// Sample, use default rng
VectorValues sample() const;
/// Sample with given values, use default rng
VectorValues sample(const VectorValues& parentsValues) const;
/// @}
/// @name Linear algebra.

View File

@ -560,9 +560,10 @@ virtual class GaussianConditional : gtsam::JacobianFactor {
const gtsam::VectorValues& frontalValues) const;
gtsam::JacobianFactor* likelihood(gtsam::Vector frontal) const;
gtsam::VectorValues sample(std::mt19937_64 @rng = nullptr) const;
gtsam::VectorValues sample(const gtsam::VectorValues& parents,
std::mt19937_64 @rng = nullptr) const;
gtsam::VectorValues sample(std::mt19937_64@ rng) const;
gtsam::VectorValues sample(const gtsam::VectorValues& parents, std::mt19937_64@ rng) const;
gtsam::VectorValues sample() const;
gtsam::VectorValues sample(const gtsam::VectorValues& parents) const;
// Advanced Interface
gtsam::VectorValues solveOtherRHS(const gtsam::VectorValues& parents,
@ -628,10 +629,9 @@ virtual class GaussianBayesNet {
gtsam::VectorValues optimize() const;
gtsam::VectorValues optimize(const gtsam::VectorValues& given) const;
gtsam::VectorValues optimizeGradientSearch() const;
gtsam::VectorValues sample(const gtsam::VectorValues& given,
std::mt19937_64 @rng = nullptr) const;
gtsam::VectorValues sample(std::mt19937_64 @rng = nullptr) const;
gtsam::VectorValues sample(const gtsam::VectorValues& given) const;
gtsam::VectorValues sample() const;
gtsam::VectorValues backSubstitute(const gtsam::VectorValues& gx) const;
gtsam::VectorValues backSubstituteTranspose(const gtsam::VectorValues& gx) const;

View File

@ -441,7 +441,7 @@ TEST(GaussianConditional, likelihood) {
/* ************************************************************************* */
// Test sampling
TEST(GaussianConditional, Sample) {
TEST(GaussianConditional, sample) {
Matrix A1 = (Matrix(2, 2) << 1., 2., 3., 4.).finished();
const Vector2 b(20, 40), x1(3, 4);
const double sigma = 0.01;
@ -465,10 +465,8 @@ TEST(GaussianConditional, Sample) {
auto actual3 = conditional.sample(given, &rng);
EXPECT_LONGS_EQUAL(1, actual2.size());
// regressions
#if __APPLE__
EXPECT(assert_equal(Vector2(31.0111856, 64.9850775), actual2[X(0)], 1e-5));
#elif _WIN32
EXPECT(assert_equal(Vector2(30.995317, 64.9943165), actual2[X(0)], 1e-5));
#if __APPLE__ || _WIN32
EXPECT(assert_equal(Vector2(31.0111856, 64.9850775), actual2[X(0)], 1e-5));
#elif __linux__
EXPECT(assert_equal(Vector2(30.9809331, 64.9927588), actual2[X(0)], 1e-5));
#endif

View File

@ -27,6 +27,8 @@
#include <utility>
#include <gtsam/nonlinear/Values.h>
#include <gtsam/nonlinear/Values.h> // Only so Eclipse finds class definition
namespace gtsam {

View File

@ -81,12 +81,13 @@ struct GTSAM_EXPORT SfmTrack2d {
* @returns boolean result of the validation.
*/
bool hasUniqueCameras() const {
std::vector<size_t> cameraIndices;
std::vector<int> track_cam_indices;
for (auto& measurement : measurements) {
cameraIndices.emplace_back(measurement.first);
track_cam_indices.emplace_back(measurement.first);
}
auto i = std::adjacent_find(cameraIndices.begin(), cameraIndices.end());
bool all_cameras_unique = (i == cameraIndices.end());
auto i =
std::adjacent_find(track_cam_indices.begin(), track_cam_indices.end());
bool all_cameras_unique = (i == track_cam_indices.end());
return all_cameras_unique;
}

View File

@ -42,7 +42,7 @@
namespace gtsam {
// In Wrappers we have no access to this so have a default ready
static std::mt19937 kPRNG(42);
static std::mt19937 kRandomNumberGenerator(42);
using Sparse = Eigen::SparseMatrix<double>;
@ -869,7 +869,7 @@ Values ShonanAveraging<d>::initializeRandomly(std::mt19937 &rng) const {
/* ************************************************************************* */
template <size_t d>
Values ShonanAveraging<d>::initializeRandomly() const {
return initializeRandomly(kPRNG);
return initializeRandomly(kRandomNumberGenerator);
}
/* ************************************************************************* */
@ -883,7 +883,7 @@ Values ShonanAveraging<d>::initializeRandomlyAt(size_t p,
/* ************************************************************************* */
template <size_t d>
Values ShonanAveraging<d>::initializeRandomlyAt(size_t p) const {
return initializeRandomlyAt(p, kPRNG);
return initializeRandomlyAt(p, kRandomNumberGenerator);
}
/* ************************************************************************* */

View File

@ -39,7 +39,7 @@ using namespace gtsam;
using namespace std;
// In Wrappers we have no access to this so have a default ready.
static std::mt19937 kPRNG(42);
static std::mt19937 kRandomNumberGenerator(42);
// Some relative translations may be zero. We treat nodes that have a zero
// relativeTranslation as a single node.
@ -185,7 +185,7 @@ Values TranslationRecovery::initializeRandomly(
const std::vector<BinaryMeasurement<Point3>> &betweenTranslations,
const Values &initialValues) const {
return initializeRandomly(relativeTranslations, betweenTranslations,
&kPRNG, initialValues);
&kRandomNumberGenerator, initialValues);
}
Values TranslationRecovery::run(

View File

@ -45,7 +45,7 @@ ShonanAveraging3 fromExampleName(
static const ShonanAveraging3 kShonan = fromExampleName("toyExample.g2o");
static std::mt19937 kPRNG(42);
static std::mt19937 kRandomNumberGenerator(42);
/* ************************************************************************* */
TEST(ShonanAveraging3, checkConstructor) {
@ -78,7 +78,7 @@ TEST(ShonanAveraging3, buildGraphAt) {
/* ************************************************************************* */
TEST(ShonanAveraging3, checkOptimality) {
const Values randomRotations = kShonan.initializeRandomly(kPRNG);
const Values randomRotations = kShonan.initializeRandomly(kRandomNumberGenerator);
Values random = ShonanAveraging3::LiftTo<Rot3>(4, randomRotations); // lift to 4!
auto Lambda = kShonan.computeLambda(random);
EXPECT_LONGS_EQUAL(15, Lambda.rows());
@ -106,7 +106,7 @@ TEST(ShonanAveraging3, checkSubgraph) {
// Create initial random estimation
Values initial;
initial = subgraphShonan.initializeRandomly(kPRNG);
initial = subgraphShonan.initializeRandomly(kRandomNumberGenerator);
// Run Shonan with SUBGRAPH solver
auto result = subgraphShonan.run(initial, 3, 3);
@ -115,7 +115,7 @@ TEST(ShonanAveraging3, checkSubgraph) {
/* ************************************************************************* */
TEST(ShonanAveraging3, tryOptimizingAt3) {
const Values randomRotations = kShonan.initializeRandomly(kPRNG);
const Values randomRotations = kShonan.initializeRandomly(kRandomNumberGenerator);
Values initial = ShonanAveraging3::LiftTo<Rot3>(3, randomRotations); // convert to SOn
EXPECT(!kShonan.checkOptimality(initial));
const Values result = kShonan.tryOptimizingAt(3, initial);
@ -130,7 +130,7 @@ TEST(ShonanAveraging3, tryOptimizingAt3) {
/* ************************************************************************* */
TEST(ShonanAveraging3, tryOptimizingAt4) {
const Values randomRotations = kShonan.initializeRandomly(kPRNG);
const Values randomRotations = kShonan.initializeRandomly(kRandomNumberGenerator);
Values random = ShonanAveraging3::LiftTo<Rot3>(4, randomRotations); // lift to 4!
const Values result = kShonan.tryOptimizingAt(4, random);
EXPECT(kShonan.checkOptimality(result));
@ -228,7 +228,7 @@ TEST(ShonanAveraging3, CheckWithEigen) {
/* ************************************************************************* */
TEST(ShonanAveraging3, initializeWithDescent) {
const Values randomRotations = kShonan.initializeRandomly(kPRNG);
const Values randomRotations = kShonan.initializeRandomly(kRandomNumberGenerator);
Values random = ShonanAveraging3::LiftTo<Rot3>(3, randomRotations);
const Values Qstar3 = kShonan.tryOptimizingAt(3, random);
Vector minEigenVector;
@ -240,7 +240,7 @@ TEST(ShonanAveraging3, initializeWithDescent) {
/* ************************************************************************* */
TEST(ShonanAveraging3, run) {
auto initial = kShonan.initializeRandomly(kPRNG);
auto initial = kShonan.initializeRandomly(kRandomNumberGenerator);
auto result = kShonan.run(initial, 5);
EXPECT_DOUBLES_EQUAL(0, kShonan.cost(result.first), 1e-3);
EXPECT_DOUBLES_EQUAL(-5.427688831332745e-07, result.second,
@ -295,7 +295,7 @@ TEST(ShonanAveraging3, runKlaus) {
EXPECT(assert_equal(R02, wR0.between(wR2), 0.1));
// Run Shonan (with prior on first rotation)
auto initial = shonan.initializeRandomly(kPRNG);
auto initial = shonan.initializeRandomly(kRandomNumberGenerator);
auto result = shonan.run(initial, 5);
EXPECT_DOUBLES_EQUAL(0, shonan.cost(result.first), 1e-2);
EXPECT_DOUBLES_EQUAL(-9.2259161494467889e-05, result.second,
@ -323,7 +323,7 @@ TEST(ShonanAveraging3, runKlausKarcher) {
static const ShonanAveraging3 shonan = fromExampleName("Klaus3.g2o");
// Run Shonan (with Karcher mean prior)
auto initial = shonan.initializeRandomly(kPRNG);
auto initial = shonan.initializeRandomly(kRandomNumberGenerator);
auto result = shonan.run(initial, 5);
EXPECT_DOUBLES_EQUAL(0, shonan.cost(result.first), 1e-2);
EXPECT_DOUBLES_EQUAL(-1.361402670507772e-05, result.second,
@ -353,7 +353,7 @@ TEST(ShonanAveraging2, noisyToyGraph) {
// Check graph building
NonlinearFactorGraph graph = shonan.buildGraphAt(2);
EXPECT_LONGS_EQUAL(6, graph.size());
auto initial = shonan.initializeRandomly(kPRNG);
auto initial = shonan.initializeRandomly(kRandomNumberGenerator);
auto result = shonan.run(initial, 2);
EXPECT_DOUBLES_EQUAL(0.0008211, shonan.cost(result.first), 1e-6);
EXPECT_DOUBLES_EQUAL(0, result.second, 1e-10); // certificate!
@ -391,7 +391,7 @@ TEST(ShonanAveraging2, noisyToyGraphWithHuber) {
}
// test result
auto initial = shonan.initializeRandomly(kPRNG);
auto initial = shonan.initializeRandomly(kRandomNumberGenerator);
auto result = shonan.run(initial, 2,2);
EXPECT_DOUBLES_EQUAL(0.0008211, shonan.cost(result.first), 1e-6);
EXPECT_DOUBLES_EQUAL(0, result.second, 1e-10); // certificate!

View File

@ -23,6 +23,7 @@
<buildtool_depend>cmake</buildtool_depend>
<depend>boost</depend>
<depend>eigen</depend>
<depend>tbb</depend>

View File

@ -10,5 +10,3 @@
* Without this they will be automatically converted to a Python object, and all
* mutations on Python side will not be reflected on C++.
*/
#include <pybind11/stl.h>