diff --git a/.github/workflows/build-linux.yml b/.github/workflows/build-linux.yml index c699db0d3..b678a71db 100644 --- a/.github/workflows/build-linux.yml +++ b/.github/workflows/build-linux.yml @@ -26,7 +26,7 @@ jobs: ubuntu-22.04-clang-14, ] - build_type: [Debug, Release] + build_type: [Release] build_unstable: [ON] include: - name: ubuntu-20.04-gcc-9 diff --git a/cmake/GtsamBuildTypes.cmake b/cmake/GtsamBuildTypes.cmake index 3a2826ec6..3e8cf7192 100644 --- a/cmake/GtsamBuildTypes.cmake +++ b/cmake/GtsamBuildTypes.cmake @@ -129,7 +129,6 @@ else() -fPIC # ensure proper code generation for shared libraries $<$:-Wreturn-local-addr -Werror=return-local-addr> # Error: return local address $<$:-Wreturn-stack-address -Werror=return-stack-address> # Error: return local address - $<$:-Wno-misleading-indentation> # Eigen triggers a ton! $<$:-Wno-weak-template-vtables> # TODO(dellaert): don't know how to resolve $<$:-Wno-weak-vtables> # TODO(dellaert): don't know how to resolve -Wreturn-type -Werror=return-type # Error on missing return() diff --git a/gtsam_unstable/examples/FixedLagSmootherExample.cpp b/examples/FixedLagSmootherExample.cpp similarity index 99% rename from gtsam_unstable/examples/FixedLagSmootherExample.cpp rename to examples/FixedLagSmootherExample.cpp index d0cd918f8..7b6a7d57f 100644 --- a/gtsam_unstable/examples/FixedLagSmootherExample.cpp +++ b/examples/FixedLagSmootherExample.cpp @@ -23,7 +23,7 @@ */ // This example demonstrates the use of the Fixed-Lag Smoothers in GTSAM unstable -#include +#include #include // In GTSAM, measurement functions are represented as 'factors'. Several common factors diff --git a/gtsam/base/VectorSpace.h b/gtsam/base/VectorSpace.h index f4e3d3020..a9e9ca106 100644 --- a/gtsam/base/VectorSpace.h +++ b/gtsam/base/VectorSpace.h @@ -185,7 +185,7 @@ template struct VectorSpaceTraits: VectorSpaceImpl { // Check that Class has the necessary machinery - GTSAM_CONCEPT_ASSERT(HasVectorSpacePrereqs); +GTSAM_CONCEPT_ASSERT(HasVectorSpacePrereqs); typedef vector_space_tag structure_category; diff --git a/gtsam/base/concepts.h b/gtsam/base/concepts.h index 5159d6f9b..f951329a7 100644 --- a/gtsam/base/concepts.h +++ b/gtsam/base/concepts.h @@ -19,7 +19,7 @@ // This does something sensible: #define BOOST_CONCEPT_USAGE(concept) void check##concept() // These just ignore the concept checking for now: -#define GTSAM_CONCEPT_ASSERT(concept) +#define GTSAM_CONCEPT_ASSERT(concept) void*(concept) #define GTSAM_CONCEPT_REQUIRES(concept, return_type) return_type #endif diff --git a/gtsam_unstable/nonlinear/BatchFixedLagSmoother.cpp b/gtsam/nonlinear/BatchFixedLagSmoother.cpp similarity index 99% rename from gtsam_unstable/nonlinear/BatchFixedLagSmoother.cpp rename to gtsam/nonlinear/BatchFixedLagSmoother.cpp index f5280ceff..4545c1540 100644 --- a/gtsam_unstable/nonlinear/BatchFixedLagSmoother.cpp +++ b/gtsam/nonlinear/BatchFixedLagSmoother.cpp @@ -17,7 +17,7 @@ * @date Oct 14, 2012 */ -#include +#include #include #include #include diff --git a/gtsam/nonlinear/BatchFixedLagSmoother.h b/gtsam/nonlinear/BatchFixedLagSmoother.h new file mode 100644 index 000000000..8dde520a7 --- /dev/null +++ b/gtsam/nonlinear/BatchFixedLagSmoother.h @@ -0,0 +1,182 @@ +/* ---------------------------------------------------------------------------- + + * 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 BatchFixedLagSmoother.h + * @brief An LM-based fixed-lag smoother. + * + * @author Michael Kaess, Stephen Williams + * @date Oct 14, 2012 + */ + +// \callgraph +#pragma once + +#include +#include +#include + +namespace gtsam { + +class GTSAM_EXPORT BatchFixedLagSmoother : public FixedLagSmoother { + +public: + + /// Typedef for a shared pointer to an Incremental Fixed-Lag Smoother + typedef std::shared_ptr shared_ptr; + + /** default constructor */ + BatchFixedLagSmoother(double smootherLag = 0.0, const LevenbergMarquardtParams& parameters = LevenbergMarquardtParams(), bool enforceConsistency = true) : + FixedLagSmoother(smootherLag), parameters_(parameters), enforceConsistency_(enforceConsistency) { } + + /** destructor */ + ~BatchFixedLagSmoother() override {} + + /** Print the factor for debugging and testing (implementing Testable) */ + void print(const std::string& s = "BatchFixedLagSmoother:\n", const KeyFormatter& keyFormatter = DefaultKeyFormatter) const override; + + /** Check if two IncrementalFixedLagSmoother Objects are equal */ + bool equals(const FixedLagSmoother& rhs, double tol = 1e-9) const override; + + /** Add new factors, updating the solution and relinearizing as needed. */ + Result update(const NonlinearFactorGraph& newFactors = NonlinearFactorGraph(), + const Values& newTheta = Values(), + const KeyTimestampMap& timestamps = KeyTimestampMap(), + const FactorIndices& factorsToRemove = FactorIndices()) override; + + /** Compute an estimate from the incomplete linear delta computed during the last update. + * This delta is incomplete because it was not updated below wildfire_threshold. If only + * a single variable is needed, it is faster to call calculateEstimate(const KEY&). + */ + Values calculateEstimate() const override { + return theta_.retract(delta_); + } + + /** Compute an estimate for a single variable using its incomplete linear delta computed + * during the last update. This is faster than calling the no-argument version of + * calculateEstimate, which operates on all variables. + * @param key + * @return + */ + template + VALUE calculateEstimate(Key key) const { + const Vector delta = delta_.at(key); + return traits::Retract(theta_.at(key), delta); + } + + /** read the current set of optimizer parameters */ + const LevenbergMarquardtParams& params() const { + return parameters_; + } + + /** update the current set of optimizer parameters */ + LevenbergMarquardtParams& params() { + return parameters_; + } + + /** Access the current set of factors */ + const NonlinearFactorGraph& getFactors() const { + return factors_; + } + + /** Access the current linearization point */ + const Values& getLinearizationPoint() const { + return theta_; + } + + /** Access the current ordering */ + const Ordering& getOrdering() const { + return ordering_; + } + + /** Access the current set of deltas to the linearization point */ + const VectorValues& getDelta() const { + return delta_; + } + + /// Calculate marginal covariance on given variable + Matrix marginalCovariance(Key key) const; + + /// Marginalize specific keys from a linear graph. + /// Does not check whether keys actually exist in graph. + /// In that case will fail somewhere deep within elimination + static GaussianFactorGraph CalculateMarginalFactors( + const GaussianFactorGraph& graph, const KeyVector& keys, + const GaussianFactorGraph::Eliminate& eliminateFunction = EliminatePreferCholesky); + + /// Marginalize specific keys from a nonlinear graph, wrap in LinearContainers + static NonlinearFactorGraph CalculateMarginalFactors( + const NonlinearFactorGraph& graph, const Values& theta, const KeyVector& keys, + const GaussianFactorGraph::Eliminate& eliminateFunction = EliminatePreferCholesky); + +protected: + + /** A typedef defining an Key-Factor mapping **/ + typedef std::map > FactorIndex; + + /** The L-M optimization parameters **/ + LevenbergMarquardtParams parameters_; + + /** A flag indicating if the optimizer should enforce probabilistic consistency by maintaining the + * linearization point of all variables involved in linearized/marginal factors at the edge of the + * smoothing window. This idea is from ??? TODO: Look up paper reference **/ + bool enforceConsistency_; + + /** The nonlinear factors **/ + NonlinearFactorGraph factors_; + + /** The current linearization point **/ + Values theta_; + + /** The set of values involved in current linear factors. **/ + Values linearValues_; + + /** The current ordering */ + Ordering ordering_; + + /** The current set of linear deltas */ + VectorValues delta_; + + /** The set of available factor graph slots. These occur because we are constantly deleting factors, leaving holes. **/ + std::queue availableSlots_; + + /** A cross-reference structure to allow efficient factor lookups by key **/ + FactorIndex factorIndex_; + + /** Augment the list of factors with a set of new factors */ + void insertFactors(const NonlinearFactorGraph& newFactors); + + /** Remove factors from the list of factors by slot index */ + void removeFactors(const std::set& deleteFactors); + + /** Erase any keys associated with timestamps before the provided time */ + void eraseKeys(const KeyVector& keys); + + /** Use colamd to update into an efficient ordering */ + void reorder(const KeyVector& marginalizeKeys = KeyVector()); + + /** Optimize the current graph using a modified version of L-M */ + Result optimize(); + + /** Marginalize out selected variables */ + void marginalize(const KeyVector& marginalizableKeys); + +private: + /** Private methods for printing debug information */ + static void PrintKeySet(const std::set& keys, const std::string& label); + static void PrintKeySet(const gtsam::KeySet& keys, const std::string& label); + static void PrintSymbolicFactor(const NonlinearFactor::shared_ptr& factor); + static void PrintSymbolicFactor(const GaussianFactor::shared_ptr& factor); + static void PrintSymbolicGraph(const NonlinearFactorGraph& graph, const std::string& label); + static void PrintSymbolicGraph(const GaussianFactorGraph& graph, const std::string& label); +}; // BatchFixedLagSmoother + +} /// namespace gtsam diff --git a/gtsam/nonlinear/Expression.h b/gtsam/nonlinear/Expression.h index 1e977ade1..e5017390d 100644 --- a/gtsam/nonlinear/Expression.h +++ b/gtsam/nonlinear/Expression.h @@ -218,7 +218,7 @@ protected: template class ScalarMultiplyExpression : public Expression { // Check that T is a vector space - GTSAM_CONCEPT_ASSERT(gtsam::IsVectorSpace); + GTSAM_CONCEPT_ASSERT(IsVectorSpace); public: explicit ScalarMultiplyExpression(double s, const Expression& e); @@ -231,7 +231,7 @@ class ScalarMultiplyExpression : public Expression { template class BinarySumExpression : public Expression { // Check that T is a vector space - GTSAM_CONCEPT_ASSERT(gtsam::IsVectorSpace); + GTSAM_CONCEPT_ASSERT(IsVectorSpace); public: explicit BinarySumExpression(const Expression& e1, const Expression& e2); diff --git a/gtsam_unstable/nonlinear/FixedLagSmoother.cpp b/gtsam/nonlinear/FixedLagSmoother.cpp similarity index 98% rename from gtsam_unstable/nonlinear/FixedLagSmoother.cpp rename to gtsam/nonlinear/FixedLagSmoother.cpp index 34a23982f..ce3242257 100644 --- a/gtsam_unstable/nonlinear/FixedLagSmoother.cpp +++ b/gtsam/nonlinear/FixedLagSmoother.cpp @@ -17,7 +17,7 @@ * @date Feb 27, 2013 */ -#include +#include namespace gtsam { diff --git a/gtsam/nonlinear/FixedLagSmoother.h b/gtsam/nonlinear/FixedLagSmoother.h new file mode 100644 index 000000000..cb657f141 --- /dev/null +++ b/gtsam/nonlinear/FixedLagSmoother.h @@ -0,0 +1,138 @@ +/* ---------------------------------------------------------------------------- + + * 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 FixedLagSmoother.h + * @brief Base class for a fixed-lag smoother. This mimics the basic interface to iSAM2. + * + * @author Stephen Williams + * @date Feb 27, 2013 + */ + +// \callgraph +#pragma once + +#include +#include +#include +#include + +#include +#include + +namespace gtsam { + +class GTSAM_EXPORT FixedLagSmoother { + +public: + + /// Typedef for a shared pointer to an Incremental Fixed-Lag Smoother + typedef std::shared_ptr shared_ptr; + + /// Typedef for a Key-Timestamp map/database + typedef std::map KeyTimestampMap; + typedef std::multimap TimestampKeyMap; + + /** + * Meta information returned about the update + */ + // TODO: Think of some more things to put here + struct Result { + size_t iterations; ///< The number of optimizer iterations performed + size_t intermediateSteps; ///< The number of intermediate steps performed within the optimization. For L-M, this is the number of lambdas tried. + size_t nonlinearVariables; ///< The number of variables that can be relinearized + size_t linearVariables; ///< The number of variables that must keep a constant linearization point + double error; ///< The final factor graph error + Result() : iterations(0), intermediateSteps(0), nonlinearVariables(0), linearVariables(0), error(0) {} + + /// Getter methods + size_t getIterations() const { return iterations; } + size_t getIntermediateSteps() const { return intermediateSteps; } + size_t getNonlinearVariables() const { return nonlinearVariables; } + size_t getLinearVariables() const { return linearVariables; } + double getError() const { return error; } + void print() const; + }; + + /** default constructor */ + FixedLagSmoother(double smootherLag = 0.0) : smootherLag_(smootherLag) { } + + /** destructor */ + virtual ~FixedLagSmoother() { } + + /** Print the factor for debugging and testing (implementing Testable) */ + virtual void print( + const std::string& s = "FixedLagSmoother:\n", + const KeyFormatter& keyFormatter = DefaultKeyFormatter) const; + + /** Check if two IncrementalFixedLagSmoother Objects are equal */ + virtual bool equals(const FixedLagSmoother& rhs, double tol = 1e-9) const; + + /** read the current smoother lag */ + double smootherLag() const { + return smootherLag_; + } + + /** write to the current smoother lag */ + double& smootherLag() { + return smootherLag_; + } + + /** Access the current set of timestamps associated with each variable */ + const KeyTimestampMap& timestamps() const { + return keyTimestampMap_; + } + + /** Add new factors, updating the solution and relinearizing as needed. */ + virtual Result update(const NonlinearFactorGraph& newFactors = NonlinearFactorGraph(), + const Values& newTheta = Values(), + const KeyTimestampMap& timestamps = KeyTimestampMap(), + const FactorIndices& factorsToRemove = FactorIndices()) = 0; + + /** Compute an estimate from the incomplete linear delta computed during the last update. + * This delta is incomplete because it was not updated below wildfire_threshold. If only + * a single variable is needed, it is faster to call calculateEstimate(const KEY&). + */ + virtual Values calculateEstimate() const = 0; + + +protected: + + /** The length of the smoother lag. Any variable older than this amount will be marginalized out. */ + double smootherLag_; + + /** The current timestamp associated with each tracked key */ + TimestampKeyMap timestampKeyMap_; + KeyTimestampMap keyTimestampMap_; + + /** Update the Timestamps associated with the keys */ + void updateKeyTimestampMap(const KeyTimestampMap& newTimestamps); + + /** Erase keys from the Key-Timestamps database */ + void eraseKeyTimestampMap(const KeyVector& keys); + + /** Find the most recent timestamp of the system */ + double getCurrentTimestamp() const; + + /** Find all of the keys associated with timestamps before the provided time */ + KeyVector findKeysBefore(double timestamp) const; + + /** Find all of the keys associated with timestamps before the provided time */ + KeyVector findKeysAfter(double timestamp) const; + +}; // FixedLagSmoother + +/// Typedef for matlab wrapping +typedef FixedLagSmoother::KeyTimestampMap FixedLagSmootherKeyTimestampMap; +typedef FixedLagSmootherKeyTimestampMap::value_type FixedLagSmootherKeyTimestampMapValue; +typedef FixedLagSmoother::Result FixedLagSmootherResult; + +} /// namespace gtsam diff --git a/gtsam/nonlinear/internal/ExpressionNode.h b/gtsam/nonlinear/internal/ExpressionNode.h index 1f45f7a87..de0c9721e 100644 --- a/gtsam/nonlinear/internal/ExpressionNode.h +++ b/gtsam/nonlinear/internal/ExpressionNode.h @@ -561,7 +561,7 @@ public: template class ScalarMultiplyNode : public ExpressionNode { // Check that T is a vector space - GTSAM_CONCEPT_ASSERT(gtsam::IsVectorSpace); + GTSAM_CONCEPT_ASSERT(IsVectorSpace); double scalar_; std::shared_ptr > expression_; diff --git a/gtsam/nonlinear/nonlinear.i b/gtsam/nonlinear/nonlinear.i index e7a05cf62..19f4ae588 100644 --- a/gtsam/nonlinear/nonlinear.i +++ b/gtsam/nonlinear/nonlinear.i @@ -650,4 +650,65 @@ virtual class NonlinearEquality2 : gtsam::NoiseModelFactor { gtsam::Vector evaluateError(const T& x1, const T& x2); }; +#include +class FixedLagSmootherKeyTimestampMapValue { + FixedLagSmootherKeyTimestampMapValue(size_t key, double timestamp); + FixedLagSmootherKeyTimestampMapValue(const gtsam::FixedLagSmootherKeyTimestampMapValue& other); +}; + +class FixedLagSmootherKeyTimestampMap { + FixedLagSmootherKeyTimestampMap(); + FixedLagSmootherKeyTimestampMap(const gtsam::FixedLagSmootherKeyTimestampMap& other); + + // Note: no print function + + // common STL methods + size_t size() const; + bool empty() const; + void clear(); + + double at(const size_t key) const; + void insert(const gtsam::FixedLagSmootherKeyTimestampMapValue& value); +}; + +class FixedLagSmootherResult { + size_t getIterations() const; + size_t getNonlinearVariables() const; + size_t getLinearVariables() const; + double getError() const; +}; + +virtual class FixedLagSmoother { + void print(string s) const; + bool equals(const gtsam::FixedLagSmoother& rhs, double tol) const; + + gtsam::FixedLagSmootherKeyTimestampMap timestamps() const; + double smootherLag() const; + + gtsam::FixedLagSmootherResult update(const gtsam::NonlinearFactorGraph &newFactors, + const gtsam::Values &newTheta, + const gtsam::FixedLagSmootherKeyTimestampMap ×tamps); + gtsam::FixedLagSmootherResult update(const gtsam::NonlinearFactorGraph &newFactors, + const gtsam::Values &newTheta, + const gtsam::FixedLagSmootherKeyTimestampMap ×tamps, + const gtsam::FactorIndices &factorsToRemove); + gtsam::Values calculateEstimate() const; +}; + +#include +virtual class BatchFixedLagSmoother : gtsam::FixedLagSmoother { + BatchFixedLagSmoother(); + BatchFixedLagSmoother(double smootherLag); + BatchFixedLagSmoother(double smootherLag, const gtsam::LevenbergMarquardtParams& params); + + void print(string s = "BatchFixedLagSmoother:\n") const; + + gtsam::LevenbergMarquardtParams params() const; + template + VALUE calculateEstimate(size_t key) const; +}; + + } // namespace gtsam diff --git a/gtsam_unstable/nonlinear/tests/testBatchFixedLagSmoother.cpp b/gtsam/nonlinear/tests/testBatchFixedLagSmoother.cpp similarity index 99% rename from gtsam_unstable/nonlinear/tests/testBatchFixedLagSmoother.cpp rename to gtsam/nonlinear/tests/testBatchFixedLagSmoother.cpp index a708c57cc..23d569c28 100644 --- a/gtsam_unstable/nonlinear/tests/testBatchFixedLagSmoother.cpp +++ b/gtsam/nonlinear/tests/testBatchFixedLagSmoother.cpp @@ -17,7 +17,7 @@ */ #include -#include +#include #include #include #include diff --git a/gtsam/nonlinear/utilities.h b/gtsam/nonlinear/utilities.h index 2997ed7d7..0a0ceb849 100644 --- a/gtsam/nonlinear/utilities.h +++ b/gtsam/nonlinear/utilities.h @@ -328,12 +328,12 @@ Values localToWorld(const Values& local, const Pose2& base, // if value is a Pose2, compose it with base pose Pose2 pose = local.at(key); world.insert(key, base.compose(pose)); - } catch (const std::exception& e1) { + } catch ([[maybe_unused]] const std::exception& e1) { try { // if value is a Point2, transform it from base pose Point2 point = local.at(key); world.insert(key, base.transformFrom(point)); - } catch (const std::exception& e2) { + } catch ([[maybe_unused]] const std::exception& e2) { // if not Pose2 or Point2, do nothing #ifndef NDEBUG std::cerr << "Values[key] is neither Pose2 nor Point2, so skip" << std::endl; diff --git a/gtsam_unstable/examples/ConcurrentFilteringAndSmoothingExample.cpp b/gtsam_unstable/examples/ConcurrentFilteringAndSmoothingExample.cpp index 52a45b6d0..502c23765 100644 --- a/gtsam_unstable/examples/ConcurrentFilteringAndSmoothingExample.cpp +++ b/gtsam_unstable/examples/ConcurrentFilteringAndSmoothingExample.cpp @@ -28,7 +28,7 @@ #include // We will compare the results to a similar Fixed-Lag Smoother -#include +#include // In GTSAM, measurement functions are represented as 'factors'. Several common factors // have been provided with the library for solving robotics/SLAM/Bundle Adjustment problems. diff --git a/gtsam_unstable/gtsam_unstable.i b/gtsam_unstable/gtsam_unstable.i index 5cd7e0da2..f36118873 100644 --- a/gtsam_unstable/gtsam_unstable.i +++ b/gtsam_unstable/gtsam_unstable.i @@ -40,6 +40,7 @@ class gtsam::LevenbergMarquardtParams; class gtsam::ISAM2Params; class gtsam::GaussianDensity; class gtsam::LevenbergMarquardtOptimizer; +class gtsam::FixedLagSmoother; namespace gtsam { @@ -530,67 +531,7 @@ virtual class DiscreteEulerPoincareHelicopter : gtsam::NoiseModelFactor { //************************************************************************* // nonlinear //************************************************************************* -#include -class FixedLagSmootherKeyTimestampMapValue { - FixedLagSmootherKeyTimestampMapValue(size_t key, double timestamp); - FixedLagSmootherKeyTimestampMapValue(const gtsam::FixedLagSmootherKeyTimestampMapValue& other); -}; - -class FixedLagSmootherKeyTimestampMap { - FixedLagSmootherKeyTimestampMap(); - FixedLagSmootherKeyTimestampMap(const gtsam::FixedLagSmootherKeyTimestampMap& other); - - // Note: no print function - - // common STL methods - size_t size() const; - bool empty() const; - void clear(); - - double at(const size_t key) const; - void insert(const gtsam::FixedLagSmootherKeyTimestampMapValue& value); -}; - -class FixedLagSmootherResult { - size_t getIterations() const; - size_t getNonlinearVariables() const; - size_t getLinearVariables() const; - double getError() const; -}; - -#include -virtual class FixedLagSmoother { - void print(string s) const; - bool equals(const gtsam::FixedLagSmoother& rhs, double tol) const; - - gtsam::FixedLagSmootherKeyTimestampMap timestamps() const; - double smootherLag() const; - - gtsam::FixedLagSmootherResult update(const gtsam::NonlinearFactorGraph &newFactors, - const gtsam::Values &newTheta, - const gtsam::FixedLagSmootherKeyTimestampMap ×tamps); - gtsam::FixedLagSmootherResult update(const gtsam::NonlinearFactorGraph &newFactors, - const gtsam::Values &newTheta, - const gtsam::FixedLagSmootherKeyTimestampMap ×tamps, - const gtsam::FactorIndices &factorsToRemove); - gtsam::Values calculateEstimate() const; -}; - -#include -virtual class BatchFixedLagSmoother : gtsam::FixedLagSmoother { - BatchFixedLagSmoother(); - BatchFixedLagSmoother(double smootherLag); - BatchFixedLagSmoother(double smootherLag, const gtsam::LevenbergMarquardtParams& params); - - void print(string s = "BatchFixedLagSmoother:\n") const; - - gtsam::LevenbergMarquardtParams params() const; - template - VALUE calculateEstimate(size_t key) const; -}; - +#include #include virtual class IncrementalFixedLagSmoother : gtsam::FixedLagSmoother { IncrementalFixedLagSmoother(); diff --git a/gtsam_unstable/linear/InfeasibleInitialValues.h b/gtsam_unstable/linear/InfeasibleInitialValues.h index dbd1b3940..4e05c75d4 100644 --- a/gtsam_unstable/linear/InfeasibleInitialValues.h +++ b/gtsam_unstable/linear/InfeasibleInitialValues.h @@ -33,13 +33,10 @@ public: } const char *what() const noexcept override { - if (description_.empty()) + if (description_->empty()) description_ = "An infeasible initial value was provided for the solver.\n"; - return description_.c_str(); + return description_->c_str(); } - -private: - mutable std::string description_; }; } diff --git a/gtsam_unstable/linear/InfeasibleOrUnboundedProblem.h b/gtsam_unstable/linear/InfeasibleOrUnboundedProblem.h index 5f9b9f5b3..0f4021019 100644 --- a/gtsam_unstable/linear/InfeasibleOrUnboundedProblem.h +++ b/gtsam_unstable/linear/InfeasibleOrUnboundedProblem.h @@ -29,12 +29,9 @@ public: } const char* what() const noexcept override { - if (description_.empty()) + if (description_->empty()) description_ = "The problem is either infeasible or unbounded.\n"; - return description_.c_str(); + return description_->c_str(); } - -private: - mutable std::string description_; }; } diff --git a/gtsam_unstable/nonlinear/BatchFixedLagSmoother.h b/gtsam_unstable/nonlinear/BatchFixedLagSmoother.h index e1206d942..52ffe7a70 100644 --- a/gtsam_unstable/nonlinear/BatchFixedLagSmoother.h +++ b/gtsam_unstable/nonlinear/BatchFixedLagSmoother.h @@ -9,174 +9,13 @@ * -------------------------------------------------------------------------- */ -/** - * @file BatchFixedLagSmoother.h - * @brief An LM-based fixed-lag smoother. - * - * @author Michael Kaess, Stephen Williams - * @date Oct 14, 2012 - */ - -// \callgraph #pragma once -#include -#include -#include +#ifdef _MSC_VER +#pragma message("BatchFixedLagSmoother was moved to the gtsam/nonlinear directory") +#else +#warning "BatchFixedLagSmoother was moved to the gtsam/nonlinear directory" +#endif -namespace gtsam { -class GTSAM_UNSTABLE_EXPORT BatchFixedLagSmoother : public FixedLagSmoother { - -public: - - /// Typedef for a shared pointer to an Incremental Fixed-Lag Smoother - typedef std::shared_ptr shared_ptr; - - /** default constructor */ - BatchFixedLagSmoother(double smootherLag = 0.0, const LevenbergMarquardtParams& parameters = LevenbergMarquardtParams(), bool enforceConsistency = true) : - FixedLagSmoother(smootherLag), parameters_(parameters), enforceConsistency_(enforceConsistency) { }; - - /** destructor */ - ~BatchFixedLagSmoother() override { }; - - /** Print the factor for debugging and testing (implementing Testable) */ - void print(const std::string& s = "BatchFixedLagSmoother:\n", const KeyFormatter& keyFormatter = DefaultKeyFormatter) const override; - - /** Check if two IncrementalFixedLagSmoother Objects are equal */ - bool equals(const FixedLagSmoother& rhs, double tol = 1e-9) const override; - - /** Add new factors, updating the solution and relinearizing as needed. */ - Result update(const NonlinearFactorGraph& newFactors = NonlinearFactorGraph(), - const Values& newTheta = Values(), - const KeyTimestampMap& timestamps = KeyTimestampMap(), - const FactorIndices& factorsToRemove = FactorIndices()) override; - - /** Compute an estimate from the incomplete linear delta computed during the last update. - * This delta is incomplete because it was not updated below wildfire_threshold. If only - * a single variable is needed, it is faster to call calculateEstimate(const KEY&). - */ - Values calculateEstimate() const override { - return theta_.retract(delta_); - } - - /** Compute an estimate for a single variable using its incomplete linear delta computed - * during the last update. This is faster than calling the no-argument version of - * calculateEstimate, which operates on all variables. - * @param key - * @return - */ - template - VALUE calculateEstimate(Key key) const { - const Vector delta = delta_.at(key); - return traits::Retract(theta_.at(key), delta); - } - - /** read the current set of optimizer parameters */ - const LevenbergMarquardtParams& params() const { - return parameters_; - } - - /** update the current set of optimizer parameters */ - LevenbergMarquardtParams& params() { - return parameters_; - } - - /** Access the current set of factors */ - const NonlinearFactorGraph& getFactors() const { - return factors_; - } - - /** Access the current linearization point */ - const Values& getLinearizationPoint() const { - return theta_; - } - - /** Access the current ordering */ - const Ordering& getOrdering() const { - return ordering_; - } - - /** Access the current set of deltas to the linearization point */ - const VectorValues& getDelta() const { - return delta_; - } - - /// Calculate marginal covariance on given variable - Matrix marginalCovariance(Key key) const; - - /// Marginalize specific keys from a linear graph. - /// Does not check whether keys actually exist in graph. - /// In that case will fail somewhere deep within elimination - static GaussianFactorGraph CalculateMarginalFactors( - const GaussianFactorGraph& graph, const KeyVector& keys, - const GaussianFactorGraph::Eliminate& eliminateFunction = EliminatePreferCholesky); - - /// Marginalize specific keys from a nonlinear graph, wrap in LinearContainers - static NonlinearFactorGraph CalculateMarginalFactors( - const NonlinearFactorGraph& graph, const Values& theta, const KeyVector& keys, - const GaussianFactorGraph::Eliminate& eliminateFunction = EliminatePreferCholesky); - -protected: - - /** A typedef defining an Key-Factor mapping **/ - typedef std::map > FactorIndex; - - /** The L-M optimization parameters **/ - LevenbergMarquardtParams parameters_; - - /** A flag indicating if the optimizer should enforce probabilistic consistency by maintaining the - * linearization point of all variables involved in linearized/marginal factors at the edge of the - * smoothing window. This idea is from ??? TODO: Look up paper reference **/ - bool enforceConsistency_; - - /** The nonlinear factors **/ - NonlinearFactorGraph factors_; - - /** The current linearization point **/ - Values theta_; - - /** The set of values involved in current linear factors. **/ - Values linearValues_; - - /** The current ordering */ - Ordering ordering_; - - /** The current set of linear deltas */ - VectorValues delta_; - - /** The set of available factor graph slots. These occur because we are constantly deleting factors, leaving holes. **/ - std::queue availableSlots_; - - /** A cross-reference structure to allow efficient factor lookups by key **/ - FactorIndex factorIndex_; - - /** Augment the list of factors with a set of new factors */ - void insertFactors(const NonlinearFactorGraph& newFactors); - - /** Remove factors from the list of factors by slot index */ - void removeFactors(const std::set& deleteFactors); - - /** Erase any keys associated with timestamps before the provided time */ - void eraseKeys(const KeyVector& keys); - - /** Use colamd to update into an efficient ordering */ - void reorder(const KeyVector& marginalizeKeys = KeyVector()); - - /** Optimize the current graph using a modified version of L-M */ - Result optimize(); - - /** Marginalize out selected variables */ - void marginalize(const KeyVector& marginalizableKeys); - -private: - /** Private methods for printing debug information */ - static void PrintKeySet(const std::set& keys, const std::string& label); - static void PrintKeySet(const gtsam::KeySet& keys, const std::string& label); - static void PrintSymbolicFactor(const NonlinearFactor::shared_ptr& factor); - static void PrintSymbolicFactor(const GaussianFactor::shared_ptr& factor); - static void PrintSymbolicGraph(const NonlinearFactorGraph& graph, const std::string& label); - static void PrintSymbolicGraph(const GaussianFactorGraph& graph, const std::string& label); -}; // BatchFixedLagSmoother - -} /// namespace gtsam +#include diff --git a/gtsam_unstable/nonlinear/ConcurrentBatchFilter.h b/gtsam_unstable/nonlinear/ConcurrentBatchFilter.h index b9e0f59ff..6a69871e1 100644 --- a/gtsam_unstable/nonlinear/ConcurrentBatchFilter.h +++ b/gtsam_unstable/nonlinear/ConcurrentBatchFilter.h @@ -50,7 +50,7 @@ public: double error; ///< The final factor graph error /// Constructor - Result() : iterations(0), lambdas(0), nonlinearVariables(0), linearVariables(0), error(0) {}; + Result() : iterations(0), lambdas(0), nonlinearVariables(0), linearVariables(0), error(0) {} /// Getter methods size_t getIterations() const { return iterations; } @@ -61,10 +61,10 @@ public: }; /** Default constructor */ - ConcurrentBatchFilter(const LevenbergMarquardtParams& parameters = LevenbergMarquardtParams()) : parameters_(parameters) {}; + ConcurrentBatchFilter(const LevenbergMarquardtParams& parameters = LevenbergMarquardtParams()) : parameters_(parameters) {} /** Default destructor */ - ~ConcurrentBatchFilter() override {}; + ~ConcurrentBatchFilter() override = default; /** Implement a GTSAM standard 'print' function */ void print(const std::string& s = "Concurrent Batch Filter:\n", const KeyFormatter& keyFormatter = DefaultKeyFormatter) const override; diff --git a/gtsam_unstable/nonlinear/ConcurrentFilteringAndSmoothing.h b/gtsam_unstable/nonlinear/ConcurrentFilteringAndSmoothing.h index 80c10aa66..2e3c34361 100644 --- a/gtsam_unstable/nonlinear/ConcurrentFilteringAndSmoothing.h +++ b/gtsam_unstable/nonlinear/ConcurrentFilteringAndSmoothing.h @@ -41,10 +41,10 @@ public: typedef std::shared_ptr shared_ptr; /** Default constructor */ - ConcurrentFilter() {}; + ConcurrentFilter() = default; /** Default destructor */ - virtual ~ConcurrentFilter() {}; + virtual ~ConcurrentFilter() = default; /** Implement a standard 'print' function */ virtual void print( @@ -58,7 +58,7 @@ public: * Perform any required operations before the synchronization process starts. * Called by 'synchronize' */ - virtual void presync() {}; + virtual void presync() {} /** * Populate the provided containers with factors that constitute the filter branch summarization @@ -91,7 +91,7 @@ public: * Perform any required operations after the synchronization process finishes. * Called by 'synchronize' */ - virtual void postsync() {}; + virtual void postsync() {} }; // ConcurrentFilter @@ -103,10 +103,10 @@ public: typedef std::shared_ptr shared_ptr; /** Default constructor */ - ConcurrentSmoother() {}; + ConcurrentSmoother() {} /** Default destructor */ - virtual ~ConcurrentSmoother() {}; + virtual ~ConcurrentSmoother() = default; /** Implement a standard 'print' function */ virtual void print( @@ -120,7 +120,7 @@ public: * Perform any required operations before the synchronization process starts. * Called by 'synchronize' */ - virtual void presync() {}; + virtual void presync() {} /** * Populate the provided containers with factors that constitute the smoother branch summarization @@ -147,7 +147,7 @@ public: * Perform any required operations after the synchronization process finishes. * Called by 'synchronize' */ - virtual void postsync() {}; + virtual void postsync() {} }; // ConcurrentSmoother diff --git a/gtsam_unstable/nonlinear/FixedLagSmoother.h b/gtsam_unstable/nonlinear/FixedLagSmoother.h index 10e13271d..ae4fa874f 100644 --- a/gtsam_unstable/nonlinear/FixedLagSmoother.h +++ b/gtsam_unstable/nonlinear/FixedLagSmoother.h @@ -9,130 +9,13 @@ * -------------------------------------------------------------------------- */ -/** - * @file FixedLagSmoother.h - * @brief Base class for a fixed-lag smoother. This mimics the basic interface to iSAM2. - * - * @author Stephen Williams - * @date Feb 27, 2013 - */ - -// \callgraph #pragma once -#include -#include -#include -#include - -#include -#include - -namespace gtsam { - -class GTSAM_UNSTABLE_EXPORT FixedLagSmoother { - -public: - - /// Typedef for a shared pointer to an Incremental Fixed-Lag Smoother - typedef std::shared_ptr shared_ptr; - - /// Typedef for a Key-Timestamp map/database - typedef std::map KeyTimestampMap; - typedef std::multimap TimestampKeyMap; - - /** - * Meta information returned about the update - */ - // TODO: Think of some more things to put here - struct Result { - size_t iterations; ///< The number of optimizer iterations performed - size_t intermediateSteps; ///< The number of intermediate steps performed within the optimization. For L-M, this is the number of lambdas tried. - size_t nonlinearVariables; ///< The number of variables that can be relinearized - size_t linearVariables; ///< The number of variables that must keep a constant linearization point - double error; ///< The final factor graph error - Result() : iterations(0), intermediateSteps(0), nonlinearVariables(0), linearVariables(0), error(0) {}; - - /// Getter methods - size_t getIterations() const { return iterations; } - size_t getIntermediateSteps() const { return intermediateSteps; } - size_t getNonlinearVariables() const { return nonlinearVariables; } - size_t getLinearVariables() const { return linearVariables; } - double getError() const { return error; } - void print() const; - }; - - /** default constructor */ - FixedLagSmoother(double smootherLag = 0.0) : smootherLag_(smootherLag) { } - - /** destructor */ - virtual ~FixedLagSmoother() { } - - /** Print the factor for debugging and testing (implementing Testable) */ - virtual void print( - const std::string& s = "FixedLagSmoother:\n", - const KeyFormatter& keyFormatter = DefaultKeyFormatter) const; - - /** Check if two IncrementalFixedLagSmoother Objects are equal */ - virtual bool equals(const FixedLagSmoother& rhs, double tol = 1e-9) const; - - /** read the current smoother lag */ - double smootherLag() const { - return smootherLag_; - } - - /** write to the current smoother lag */ - double& smootherLag() { - return smootherLag_; - } - - /** Access the current set of timestamps associated with each variable */ - const KeyTimestampMap& timestamps() const { - return keyTimestampMap_; - } - - /** Add new factors, updating the solution and relinearizing as needed. */ - virtual Result update(const NonlinearFactorGraph& newFactors = NonlinearFactorGraph(), - const Values& newTheta = Values(), - const KeyTimestampMap& timestamps = KeyTimestampMap(), - const FactorIndices& factorsToRemove = FactorIndices()) = 0; - - /** Compute an estimate from the incomplete linear delta computed during the last update. - * This delta is incomplete because it was not updated below wildfire_threshold. If only - * a single variable is needed, it is faster to call calculateEstimate(const KEY&). - */ - virtual Values calculateEstimate() const = 0; +#ifdef _MSC_VER +#pragma message("FixedLagSmoother was moved to the gtsam/nonlinear directory") +#else +#warning "FixedLagSmoother was moved to the gtsam/nonlinear directory" +#endif -protected: - - /** The length of the smoother lag. Any variable older than this amount will be marginalized out. */ - double smootherLag_; - - /** The current timestamp associated with each tracked key */ - TimestampKeyMap timestampKeyMap_; - KeyTimestampMap keyTimestampMap_; - - /** Update the Timestamps associated with the keys */ - void updateKeyTimestampMap(const KeyTimestampMap& newTimestamps); - - /** Erase keys from the Key-Timestamps database */ - void eraseKeyTimestampMap(const KeyVector& keys); - - /** Find the most recent timestamp of the system */ - double getCurrentTimestamp() const; - - /** Find all of the keys associated with timestamps before the provided time */ - KeyVector findKeysBefore(double timestamp) const; - - /** Find all of the keys associated with timestamps before the provided time */ - KeyVector findKeysAfter(double timestamp) const; - -}; // FixedLagSmoother - -/// Typedef for matlab wrapping -typedef FixedLagSmoother::KeyTimestampMap FixedLagSmootherKeyTimestampMap; -typedef FixedLagSmootherKeyTimestampMap::value_type FixedLagSmootherKeyTimestampMapValue; -typedef FixedLagSmoother::Result FixedLagSmootherResult; - -} /// namespace gtsam +#include diff --git a/gtsam_unstable/nonlinear/IncrementalFixedLagSmoother.h b/gtsam_unstable/nonlinear/IncrementalFixedLagSmoother.h index beef95c1b..bc1c48524 100644 --- a/gtsam_unstable/nonlinear/IncrementalFixedLagSmoother.h +++ b/gtsam_unstable/nonlinear/IncrementalFixedLagSmoother.h @@ -20,7 +20,7 @@ // \callgraph #pragma once -#include +#include #include namespace gtsam { diff --git a/gtsam_unstable/nonlinear/LinearizedFactor.h b/gtsam_unstable/nonlinear/LinearizedFactor.h index 689c97c3a..1ff45ef5f 100644 --- a/gtsam_unstable/nonlinear/LinearizedFactor.h +++ b/gtsam_unstable/nonlinear/LinearizedFactor.h @@ -45,7 +45,7 @@ protected: public: /** default constructor for serialization */ - LinearizedGaussianFactor() {}; + LinearizedGaussianFactor() = default; /** * @param gaussian: A jacobian or hessian factor @@ -53,7 +53,7 @@ public: */ LinearizedGaussianFactor(const GaussianFactor::shared_ptr& gaussian, const Values& lin_points); - ~LinearizedGaussianFactor() override {}; + ~LinearizedGaussianFactor() override = default; // access functions const Values& linearizationPoint() const { return lin_points_; } @@ -128,11 +128,11 @@ public: // access functions const constBVector b() const { return Ab_(size()).col(0); } - const constABlock A() const { return Ab_.range(0, size()); }; + const constABlock A() const { return Ab_.range(0, size()); } const constABlock A(Key key) const { return Ab_(std::find(begin(), end(), key) - begin()); } /** get the dimension of the factor (number of rows on linearization) */ - size_t dim() const override { return Ab_.rows(); }; + size_t dim() const override { return Ab_.rows(); } /** Calculate the error of the factor */ double error(const Values& c) const override; diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt index 675fef4c3..c5c3aa5c8 100644 --- a/python/CMakeLists.txt +++ b/python/CMakeLists.txt @@ -40,6 +40,7 @@ set(ignore gtsam::IndexPairVector gtsam::BetweenFactorPose2s gtsam::BetweenFactorPose3s + gtsam::FixedLagSmootherKeyTimestampMapValue gtsam::Point2Vector gtsam::Point2Pairs gtsam::Point3Pairs @@ -144,7 +145,6 @@ if(GTSAM_UNSTABLE_BUILD_PYTHON) gtsam::Point2Vector gtsam::Pose3Vector gtsam::KeyVector - gtsam::FixedLagSmootherKeyTimestampMapValue gtsam::BinaryMeasurementsPoint3 gtsam::BinaryMeasurementsUnit3 gtsam::BinaryMeasurementsRot3 diff --git a/python/gtsam_unstable/examples/FixedLagSmootherExample.py b/python/gtsam/examples/FixedLagSmootherExample.py similarity index 95% rename from python/gtsam_unstable/examples/FixedLagSmootherExample.py rename to python/gtsam/examples/FixedLagSmootherExample.py index 7d2cea8ae..99af0edcf 100644 --- a/python/gtsam_unstable/examples/FixedLagSmootherExample.py +++ b/python/gtsam/examples/FixedLagSmootherExample.py @@ -25,13 +25,13 @@ def BatchFixedLagSmootherExample(): # Define a batch fixed lag smoother, which uses # Levenberg-Marquardt to perform the nonlinear optimization lag = 2.0 - smoother_batch = gtsam_unstable.BatchFixedLagSmoother(lag) + smoother_batch = gtsam.BatchFixedLagSmoother(lag) # Create containers to store the factors and linearization points # that will be sent to the smoothers new_factors = gtsam.NonlinearFactorGraph() new_values = gtsam.Values() - new_timestamps = gtsam_unstable.FixedLagSmootherKeyTimestampMap() + new_timestamps = gtsam.FixedLagSmootherKeyTimestampMap() # Create a prior on the first pose, placing it at the origin prior_mean = gtsam.Pose2(0, 0, 0) diff --git a/python/gtsam_unstable/tests/test_FixedLagSmootherExample.py b/python/gtsam/tests/test_FixedLagSmootherExample.py similarity index 96% rename from python/gtsam_unstable/tests/test_FixedLagSmootherExample.py rename to python/gtsam/tests/test_FixedLagSmootherExample.py index c1ccd1ea1..ddd2d49e4 100644 --- a/python/gtsam_unstable/tests/test_FixedLagSmootherExample.py +++ b/python/gtsam/tests/test_FixedLagSmootherExample.py @@ -30,13 +30,13 @@ class TestFixedLagSmootherExample(GtsamTestCase): # Define a batch fixed lag smoother, which uses # Levenberg-Marquardt to perform the nonlinear optimization lag = 2.0 - smoother_batch = gtsam_unstable.BatchFixedLagSmoother(lag) + smoother_batch = gtsam.BatchFixedLagSmoother(lag) # Create containers to store the factors and linearization points # that will be sent to the smoothers new_factors = gtsam.NonlinearFactorGraph() new_values = gtsam.Values() - new_timestamps = gtsam_unstable.FixedLagSmootherKeyTimestampMap() + new_timestamps = gtsam.FixedLagSmootherKeyTimestampMap() # Create a prior on the first pose, placing it at the origin prior_mean = gtsam.Pose2(0, 0, 0)