Skip to content

Commit

Permalink
Merge pull request #1650 from borglab/factor-typecast
Browse files Browse the repository at this point in the history
  • Loading branch information
varunagrawal authored Oct 18, 2023
2 parents 5ffa7f2 + 5a3706c commit b5d19fb
Show file tree
Hide file tree
Showing 26 changed files with 139 additions and 77 deletions.
14 changes: 7 additions & 7 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -36,20 +36,20 @@ set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH}" "${CMAKE_CURRENT_SOURCE_DIR}/cmake"
include(GtsamMakeConfigFile)
include(GNUInstallDirs)

# Load build type flags and default to Debug mode
include(GtsamBuildTypes)

# Use macros for creating tests/timing scripts
include(GtsamTesting)
include(GtsamPrinting)

# guard against in-source builds
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()

include(cmake/HandleGeneralOptions.cmake) # CMake build options

# Load build type flags and default to Debug mode
include(GtsamBuildTypes)

# Use macros for creating tests/timing scripts
include(GtsamTesting)
include(GtsamPrinting)

############### Decide on BOOST ######################################
# Enable or disable serialization with GTSAM_ENABLE_BOOST_SERIALIZATION
option(GTSAM_ENABLE_BOOST_SERIALIZATION "Enable Boost serialization" ON)
Expand Down
18 changes: 14 additions & 4 deletions cmake/GtsamBuildTypes.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,6 @@ if(NOT CMAKE_BUILD_TYPE AND NOT MSVC AND NOT XCODE_VERSION)
"Choose the type of build, options are: None Debug Release Timing Profiling RelWithDebInfo." FORCE)
endif()

# Add option for using build type postfixes to allow installing multiple build modes
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 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)
Expand All @@ -82,6 +79,13 @@ set(GTSAM_COMPILE_DEFINITIONS_PRIVATE_RELWITHDEBINFO "NDEBUG" CACHE STRING "(Us
set(GTSAM_COMPILE_DEFINITIONS_PRIVATE_RELEASE "NDEBUG" CACHE STRING "(User editable) Private preprocessor macros for Release configuration.")
set(GTSAM_COMPILE_DEFINITIONS_PRIVATE_PROFILING "NDEBUG" CACHE STRING "(User editable) Private preprocessor macros for Profiling configuration.")
set(GTSAM_COMPILE_DEFINITIONS_PRIVATE_TIMING "NDEBUG;ENABLE_TIMING" CACHE STRING "(User editable) Private preprocessor macros for Timing configuration.")

mark_as_advanced(GTSAM_COMPILE_DEFINITIONS_PRIVATE_DEBUG)
mark_as_advanced(GTSAM_COMPILE_DEFINITIONS_PRIVATE_RELWITHDEBINFO)
mark_as_advanced(GTSAM_COMPILE_DEFINITIONS_PRIVATE_RELEASE)
mark_as_advanced(GTSAM_COMPILE_DEFINITIONS_PRIVATE_PROFILING)
mark_as_advanced(GTSAM_COMPILE_DEFINITIONS_PRIVATE_TIMING)

if(MSVC)
# Common to all configurations:
list_append_cache(GTSAM_COMPILE_DEFINITIONS_PRIVATE
Expand Down Expand Up @@ -143,6 +147,13 @@ else()
set(GTSAM_COMPILE_OPTIONS_PRIVATE_TIMING -g -O3 CACHE STRING "(User editable) Private compiler flags for Timing configuration.")
endif()

mark_as_advanced(GTSAM_COMPILE_OPTIONS_PRIVATE_COMMON)
mark_as_advanced(GTSAM_COMPILE_OPTIONS_PRIVATE_DEBUG)
mark_as_advanced(GTSAM_COMPILE_OPTIONS_PRIVATE_RELWITHDEBINFO)
mark_as_advanced(GTSAM_COMPILE_OPTIONS_PRIVATE_RELEASE)
mark_as_advanced(GTSAM_COMPILE_OPTIONS_PRIVATE_PROFILING)
mark_as_advanced(GTSAM_COMPILE_OPTIONS_PRIVATE_TIMING)

# Enable C++17:
if (NOT CMAKE_VERSION VERSION_LESS 3.8)
set(GTSAM_COMPILE_FEATURES_PUBLIC "cxx_std_17" CACHE STRING "CMake compile features property for all gtsam targets.")
Expand Down Expand Up @@ -198,7 +209,6 @@ if(${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang")
endif()

if (NOT MSVC)
option(GTSAM_BUILD_WITH_MARCH_NATIVE "Enable/Disable building with all instructions supported by native architecture (binary may not be portable!)" OFF)
if(GTSAM_BUILD_WITH_MARCH_NATIVE)
# Check if Apple OS and compiler is [Apple]Clang
if(APPLE AND (${CMAKE_CXX_COMPILER_ID} MATCHES "^(Apple)?Clang$"))
Expand Down
18 changes: 10 additions & 8 deletions cmake/GtsamTesting.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ endmacro()
# GTSAM_BUILD_EXAMPLES_ALWAYS is enabled. They may also be built with 'make examples'.
#
# Usage example:
# gtsamAddExamplesGlob("*.cpp" "BrokenExample.cpp" "gtsam;GeographicLib")
# gtsamAddExamplesGlob("*.cpp" "BrokenExample.cpp" "gtsam;GeographicLib" ON)
#
# Arguments:
# globPatterns: The list of files or glob patterns from which to create examples, with
Expand All @@ -51,8 +51,9 @@ endmacro()
# excludedFiles: A list of files or globs to exclude, e.g. "C*.cpp;BrokenExample.cpp". Pass
# an empty string "" if nothing needs to be excluded.
# linkLibraries: The list of libraries to link to.
macro(gtsamAddExamplesGlob globPatterns excludedFiles linkLibraries)
gtsamAddExesGlob_impl("${globPatterns}" "${excludedFiles}" "${linkLibraries}" "examples" ${GTSAM_BUILD_EXAMPLES_ALWAYS})
# buildWithAll: Build examples with `make` and/or `make all`
macro(gtsamAddExamplesGlob globPatterns excludedFiles linkLibraries buildWithAll)
gtsamAddExesGlob_impl("${globPatterns}" "${excludedFiles}" "${linkLibraries}" "examples" ${buildWithAll})
endmacro()


Expand All @@ -76,8 +77,9 @@ endmacro()
# excludedFiles: A list of files or globs to exclude, e.g. "C*.cpp;BrokenExample.cpp". Pass
# an empty string "" if nothing needs to be excluded.
# linkLibraries: The list of libraries to link to.
macro(gtsamAddTimingGlob globPatterns excludedFiles linkLibraries)
gtsamAddExesGlob_impl("${globPatterns}" "${excludedFiles}" "${linkLibraries}" "timing" ${GTSAM_BUILD_TIMING_ALWAYS})
# buildWithAll: Build examples with `make` and/or `make all`
macro(gtsamAddTimingGlob globPatterns excludedFiles linkLibraries buildWithAll)
gtsamAddExesGlob_impl("${globPatterns}" "${excludedFiles}" "${linkLibraries}" "timing" ${buildWithAll})
endmacro()


Expand All @@ -86,9 +88,8 @@ endmacro()
# Build macros for using tests
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)
#TODO(Varun) Move to HandlePrintConfiguration.cmake. This will require additional changes.
option(GTSAM_BUILD_TESTS "Enable/Disable building of tests" ON)

# Add option for combining unit tests
if(MSVC OR XCODE_VERSION)
Expand Down Expand Up @@ -123,6 +124,7 @@ add_custom_target(timing)
# Implementations of this file's macros:

macro(gtsamAddTestsGlob_impl groupName globPatterns excludedFiles linkLibraries)
#TODO(Varun) Building of tests should not depend on global gtsam flag
if(GTSAM_BUILD_TESTS)
# Add group target if it doesn't already exist
if(NOT TARGET check.${groupName})
Expand Down
12 changes: 12 additions & 0 deletions cmake/HandleGeneralOptions.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,18 @@ else()
set(GTSAM_UNSTABLE_AVAILABLE 0)
endif()

### GtsamTesting related options
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)
###

# Add option for using build type postfixes to allow installing multiple build modes
option(GTSAM_BUILD_TYPE_POSTFIXES "Enable/Disable appending the build type to the name of compiled libraries" ON)

if (NOT MSVC)
option(GTSAM_BUILD_WITH_MARCH_NATIVE "Enable/Disable building with all instructions supported by native architecture (binary may not be portable!)" OFF)
endif()

# Configurable Options
if(GTSAM_UNSTABLE_AVAILABLE)
option(GTSAM_BUILD_UNSTABLE "Enable/Disable libgtsam_unstable" ON)
Expand Down
5 changes: 3 additions & 2 deletions cmake/README.html
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,9 @@ <h2>GtsamTesting</h2>
</code></pre>
</li>
<li>
<p><code>gtsamAddExamplesGlob(globPatterns excludedFiles linkLibraries)</code> Add scripts that will serve as examples of how to use the library. A list of files or glob patterns is specified, and one executable will be created for each matching .cpp file. These executables will not be installed. They are build with 'make all' if GTSAM_BUILD_EXAMPLES_ALWAYS is enabled. They may also be built with 'make examples'.</p>
<p><code>gtsamAddExamplesGlob(globPatterns excludedFiles linkLibraries buildWithAll)</code> Add scripts that will serve as examples of how to use the library. A list of files or glob patterns is specified, and one executable will be created for each matching .cpp file. These executables will not be installed. They are build with 'make all' if GTSAM_BUILD_EXAMPLES_ALWAYS is enabled. They may also be built with 'make examples'.</p>
<p>Usage example:</p>
<pre><code>gtsamAddExamplesGlob("*.cpp" "BrokenExample.cpp" "gtsam;GeographicLib")
<pre><code>gtsamAddExamplesGlob("*.cpp" "BrokenExample.cpp" "gtsam;GeographicLib" ON)
</code></pre>
<p>Arguments:</p>
<pre><code>globPatterns: The list of files or glob patterns from which to create unit tests, with
Expand All @@ -58,6 +58,7 @@ <h2>GtsamTesting</h2>
excludedFiles: A list of files or globs to exclude, e.g. "C*.cpp;BrokenExample.cpp". Pass
an empty string "" if nothing needs to be excluded.
linkLibraries: The list of libraries to link to.
buildWithAll: Build examples with `make` and/or `make all`
</code></pre>
</li>
</ul>
Expand Down
5 changes: 3 additions & 2 deletions cmake/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,11 @@ Defines two useful functions for creating CTest unit tests. Also immediately cr
Pass an empty string "" if nothing needs to be excluded.
linkLibraries: The list of libraries to link to in addition to CppUnitLite.

* `gtsamAddExamplesGlob(globPatterns excludedFiles linkLibraries)` Add scripts that will serve as examples of how to use the library. A list of files or glob patterns is specified, and one executable will be created for each matching .cpp file. These executables will not be installed. They are build with 'make all' if GTSAM_BUILD_EXAMPLES_ALWAYS is enabled. They may also be built with 'make examples'.
* `gtsamAddExamplesGlob(globPatterns excludedFiles linkLibraries buildWithAll)` Add scripts that will serve as examples of how to use the library. A list of files or glob patterns is specified, and one executable will be created for each matching .cpp file. These executables will not be installed. They are build with 'make all' if GTSAM_BUILD_EXAMPLES_ALWAYS is enabled. They may also be built with 'make examples'.

Usage example:

gtsamAddExamplesGlob("*.cpp" "BrokenExample.cpp" "gtsam;GeographicLib")
gtsamAddExamplesGlob("*.cpp" "BrokenExample.cpp" "gtsam;GeographicLib" ON)

Arguments:

Expand All @@ -66,6 +66,7 @@ Defines two useful functions for creating CTest unit tests. Also immediately cr
excludedFiles: A list of files or globs to exclude, e.g. "C*.cpp;BrokenExample.cpp". Pass
an empty string "" if nothing needs to be excluded.
linkLibraries: The list of libraries to link to.
buildWithAll: Build examples with `make` and/or `make all`

## GtsamMakeConfigFile

Expand Down
2 changes: 1 addition & 1 deletion examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,4 @@ if (NOT GTSAM_USE_BOOST_FEATURES)
)
endif()

gtsamAddExamplesGlob("*.cpp" "${excluded_examples}" "gtsam;${Boost_PROGRAM_OPTIONS_LIBRARY}")
gtsamAddExamplesGlob("*.cpp" "${excluded_examples}" "gtsam;${Boost_PROGRAM_OPTIONS_LIBRARY}" ${GTSAM_BUILD_EXAMPLES_ALWAYS})
6 changes: 3 additions & 3 deletions gtsam/hybrid/tests/testHybridGaussianFactorGraph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@
#include <functional>
#include <iostream>
#include <iterator>
#include <vector>
#include <numeric>
#include <vector>

#include "Switching.h"
#include "TinyHybridExample.h"
Expand Down Expand Up @@ -613,11 +613,11 @@ TEST(HybridGaussianFactorGraph, assembleGraphTree) {
// Create expected decision tree with two factor graphs:

// Get mixture factor:
auto mixture = std::dynamic_pointer_cast<GaussianMixtureFactor>(fg.at(0));
auto mixture = fg.at<GaussianMixtureFactor>(0);
CHECK(mixture);

// Get prior factor:
const auto gf = std::dynamic_pointer_cast<HybridConditional>(fg.at(1));
const auto gf = fg.at<HybridConditional>(1);
CHECK(gf);
using GF = GaussianFactor::shared_ptr;
const GF prior = gf->asGaussian();
Expand Down
15 changes: 15 additions & 0 deletions gtsam/inference/FactorGraph.h
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,21 @@ class FactorGraph {
*/
sharedFactor& at(size_t i) { return factors_.at(i); }

/** Get a specific factor by index and typecast to factor type F
* (this checks array bounds and may throw
* an exception, as opposed to operator[] which does not).
*/
template <typename F>
std::shared_ptr<F> at(size_t i) {
return std::dynamic_pointer_cast<F>(factors_.at(i));
}

/// Const version of templated `at` method.
template <typename F>
const std::shared_ptr<F> at(size_t i) const {
return std::dynamic_pointer_cast<F>(factors_.at(i));
}

/** Get a specific factor by index (this does not check array bounds, as
* opposed to at() which does).
*/
Expand Down
5 changes: 4 additions & 1 deletion gtsam/inference/Key.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
* -------------------------------------------------------------------------- */

/**
* @file Key.h
* @file Key.cpp
* @brief
* @author Richard Roberts
* @author Alex Cunningham
Expand All @@ -26,6 +26,9 @@ using namespace std;

namespace gtsam {

/// Assign default key formatter
KeyFormatter DefaultKeyFormatter = &_defaultKeyFormatter;

/* ************************************************************************* */
string _defaultKeyFormatter(Key key) {
const Symbol asSymbol(key);
Expand Down
18 changes: 10 additions & 8 deletions gtsam/inference/Key.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,16 @@ using KeyFormatter = std::function<std::string(Key)>;
// Helper function for DefaultKeyFormatter
GTSAM_EXPORT std::string _defaultKeyFormatter(Key key);

/// The default KeyFormatter, which is used if no KeyFormatter is passed to
/// a nonlinear 'print' function. Automatically detects plain integer keys
/// and Symbol keys.
static const KeyFormatter DefaultKeyFormatter = &_defaultKeyFormatter;
/**
* The default KeyFormatter, which is used if no KeyFormatter is passed
* to a 'print' function.
*
* Automatically detects plain integer keys and Symbol keys.
*
* Marked as `extern` so that it can be updated by external libraries.
*
*/
extern GTSAM_EXPORT KeyFormatter DefaultKeyFormatter;

// Helper function for Multi-robot Key Formatter
GTSAM_EXPORT std::string _multirobotKeyFormatter(gtsam::Key key);
Expand Down Expand Up @@ -124,7 +130,3 @@ struct traits<Key> {
};

} // namespace gtsam




6 changes: 6 additions & 0 deletions gtsam/linear/JacobianFactor.h
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,12 @@ namespace gtsam {
/** Get a view of the A matrix */
ABlock getA() { return Ab_.range(0, size()); }

/**
* Get a view of the A matrix for the variable
* pointed to by the given key.
*/
ABlock getA(const Key& key) { return Ab_(find(key) - begin()); }

/** Update an information matrix by adding the information corresponding to this factor
* (used internally during elimination).
* @param scatter A mapping from variable index to slot index in this HessianFactor
Expand Down
3 changes: 1 addition & 2 deletions gtsam/linear/tests/testGaussianFactorGraph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -391,8 +391,7 @@ TEST(GaussianFactorGraph, clone) {
EXPECT(assert_equal(init_graph, actCloned)); // Same as the original version

// Apply an in-place change to init_graph and compare
JacobianFactor::shared_ptr jacFactor0 =
std::dynamic_pointer_cast<JacobianFactor>(init_graph.at(0));
JacobianFactor::shared_ptr jacFactor0 = init_graph.at<JacobianFactor>(0);
CHECK(jacFactor0);
jacFactor0->getA(jacFactor0->begin()) *= 7.;
EXPECT(assert_inequal(init_graph, exp_graph));
Expand Down
9 changes: 9 additions & 0 deletions gtsam/linear/tests/testJacobianFactor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,10 @@ TEST(JacobianFactor, constructors_and_accessors)
JacobianFactor actual(terms[0].first, terms[0].second, b, noise);
EXPECT(assert_equal(expected, actual));
LONGS_EQUAL((long)terms[0].first, (long)actual.keys().back());
// Key iterator
EXPECT(assert_equal(terms[0].second, actual.getA(actual.end() - 1)));
// Key
EXPECT(assert_equal(terms[0].second, actual.getA(terms[0].first)));
EXPECT(assert_equal(b, expected.getb()));
EXPECT(assert_equal(b, actual.getb()));
EXPECT(noise == expected.get_model());
Expand All @@ -78,7 +81,10 @@ TEST(JacobianFactor, constructors_and_accessors)
terms[1].first, terms[1].second, b, noise);
EXPECT(assert_equal(expected, actual));
LONGS_EQUAL((long)terms[1].first, (long)actual.keys().back());
// Key iterator
EXPECT(assert_equal(terms[1].second, actual.getA(actual.end() - 1)));
// Key
EXPECT(assert_equal(terms[1].second, actual.getA(terms[1].first)));
EXPECT(assert_equal(b, expected.getb()));
EXPECT(assert_equal(b, actual.getb()));
EXPECT(noise == expected.get_model());
Expand All @@ -91,7 +97,10 @@ TEST(JacobianFactor, constructors_and_accessors)
terms[1].first, terms[1].second, terms[2].first, terms[2].second, b, noise);
EXPECT(assert_equal(expected, actual));
LONGS_EQUAL((long)terms[2].first, (long)actual.keys().back());
// Key iterator
EXPECT(assert_equal(terms[2].second, actual.getA(actual.end() - 1)));
// Key
EXPECT(assert_equal(terms[2].second, actual.getA(terms[2].first)));
EXPECT(assert_equal(b, expected.getb()));
EXPECT(assert_equal(b, actual.getb()));
EXPECT(noise == expected.get_model());
Expand Down
15 changes: 6 additions & 9 deletions gtsam/nonlinear/GncOptimizer.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,9 @@ class GncOptimizer {
nfg_.resize(graph.size());
for (size_t i = 0; i < graph.size(); i++) {
if (graph[i]) {
NoiseModelFactor::shared_ptr factor = std::dynamic_pointer_cast<
NoiseModelFactor>(graph[i]);
auto robust = std::dynamic_pointer_cast<
noiseModel::Robust>(factor->noiseModel());
NoiseModelFactor::shared_ptr factor = graph.at<NoiseModelFactor>(i);
auto robust =
std::dynamic_pointer_cast<noiseModel::Robust>(factor->noiseModel());
// if the factor has a robust loss, we remove the robust loss
nfg_[i] = robust ? factor-> cloneWithNewNoiseModel(robust->noise()) : factor;
}
Expand Down Expand Up @@ -401,11 +400,9 @@ class GncOptimizer {
newGraph.resize(nfg_.size());
for (size_t i = 0; i < nfg_.size(); i++) {
if (nfg_[i]) {
auto factor = std::dynamic_pointer_cast<
NoiseModelFactor>(nfg_[i]);
auto noiseModel =
std::dynamic_pointer_cast<noiseModel::Gaussian>(
factor->noiseModel());
auto factor = nfg_.at<NoiseModelFactor>(i);
auto noiseModel = std::dynamic_pointer_cast<noiseModel::Gaussian>(
factor->noiseModel());
if (noiseModel) {
Matrix newInfo = weights[i] * noiseModel->information();
auto newNoiseModel = noiseModel::Gaussian::Information(newInfo);
Expand Down
Loading

0 comments on commit b5d19fb

Please sign in to comment.