diff --git a/docs/source/nnls_modeling.rst b/docs/source/nnls_modeling.rst index d30df1c5d..5018579e4 100644 --- a/docs/source/nnls_modeling.rst +++ b/docs/source/nnls_modeling.rst @@ -152,9 +152,7 @@ the corresponding accessors. This information will be verified by the .. code-block:: c++ - template + template class SizedCostFunction : public CostFunction { public: virtual bool Evaluate(double const* const* parameters, @@ -177,23 +175,16 @@ the corresponding accessors. This information will be verified by the template // Number of parameters in block 9. + int... Ns> // Size of each parameter block class AutoDiffCostFunction : public - SizedCostFunction { + SizedCostFunction { public: - explicit AutoDiffCostFunction(CostFunctor* functor); + AutoDiffCostFunction(CostFunctor* functor, ownership = TAKE_OWNERSHIP); // Ignore the template parameter kNumResiduals and use // num_residuals instead. - AutoDiffCostFunction(CostFunctor* functor, int num_residuals); + AutoDiffCostFunction(CostFunctor* functor, + int num_residuals, + ownership = TAKE_OWNERSHIP); }; To get an auto differentiated cost function, you must define a @@ -299,10 +290,6 @@ the corresponding accessors. This information will be verified by the Dimension of x ------------------------------------+ | Dimension of y ---------------------------------------+ - The framework can currently accommodate cost functions of up to 10 - independent variables, and there is no limit on the dimensionality - of each of them. - **WARNING 1** A common beginner's error when first using :class:`AutoDiffCostFunction` is to get the sizing wrong. In particular, there is a tendency to set the template parameters to (dimension of @@ -318,10 +305,9 @@ the corresponding accessors. This information will be verified by the .. class:: DynamicAutoDiffCostFunction :class:`AutoDiffCostFunction` requires that the number of parameter - blocks and their sizes be known at compile time. It also has an - upper limit of 10 parameter blocks. In a number of applications, - this is not enough e.g., Bezier curve fitting, Neural Network - training etc. + blocks and their sizes be known at compile time. In a number of + applications, this is not enough e.g., Bezier curve fitting, Neural + Network training etc. .. code-block:: c++ @@ -386,9 +372,6 @@ the corresponding accessors. This information will be verified by the NumericDiffOptions. Update DynamicNumericDiffOptions in a similar manner. - TODO(sameeragarwal): Update AutoDiffCostFunction and - NumericDiffCostFunction documentation to point to variadic impl. - TODO(sameeragarwal): Check that Problem documentation for AddResidualBlock can deal with the variadic impl. @@ -397,18 +380,9 @@ the corresponding accessors. This information will be verified by the template // Number of parameters in block 9. + int.. Ns> // Size of each parameter block. class NumericDiffCostFunction : public - SizedCostFunction { + SizedCostFunction { }; To get a numerically differentiated :class:`CostFunction`, you must @@ -505,10 +479,6 @@ the corresponding accessors. This information will be verified by the Dimension of y ---------------------------------------------------+ - The framework can currently accommodate cost functions of up to 10 - independent variables, and there is no limit on the dimensionality - of each of them. - There are three available numeric differentiation schemes in ceres-solver: The ``FORWARD`` difference method, which approximates :math:`f'(x)` @@ -616,8 +586,7 @@ Numeric Differentiation & LocalParameterization Like :class:`AutoDiffCostFunction` :class:`NumericDiffCostFunction` requires that the number of parameter blocks and their sizes be - known at compile time. It also has an upper limit of 10 parameter - blocks. In a number of applications, this is not enough. + known at compile time. In a number of applications, this is not enough. .. code-block:: c++ @@ -1578,7 +1547,7 @@ quaternion, a local parameterization can be constructed as :class:`Problem` holds the robustified bounds constrained non-linear least squares problem :eq:`ceresproblem_modeling`. To create a least squares problem, use the - :func:`Problem::AddResidualBlock` and + :func:`Problem::AddResiualBlock` and :func:`Problem::AddParameterBlock` methods. For example a problem containing 3 parameter blocks of sizes 3, 4 @@ -1764,7 +1733,10 @@ quaternion, a local parameterization can be constructed as error. .. function:: ResidualBlockId Problem::AddResidualBlock(CostFunction* cost_function, LossFunction* loss_function, const vector parameter_blocks) -.. function:: ResidualBlockId Problem::AddResidualBlock(CostFunction* cost_function, LossFunction* loss_function, double *x0, double *x1, ...) + +.. function:: template ResidualBlockId + Problem::AddResidualBlock(CostFunction* cost_function, + LossFunction* loss_function, double* x0, Ts... xs) Add a residual block to the overall cost function. The cost function carries with it information about the sizes of the @@ -1775,7 +1747,7 @@ quaternion, a local parameterization can be constructed as norm of the residuals. The parameter blocks may be passed together as a - ``vector``, or as up to ten separate ``double*`` pointers. + ``vector``, or ``double*`` pointers. The user has the option of explicitly adding the parameter blocks using AddParameterBlock. This causes additional correctness diff --git a/include/ceres/autodiff_cost_function.h b/include/ceres/autodiff_cost_function.h index 8a225381d..207f0a416 100644 --- a/include/ceres/autodiff_cost_function.h +++ b/include/ceres/autodiff_cost_function.h @@ -153,8 +153,8 @@ template // Number of parameters in each parameter block. class AutoDiffCostFunction : public SizedCostFunction { public: - // Takes ownership of functor by default. Uses the template-provided value for - // the number of residuals ("kNumResiduals"). + // Takes ownership of functor by default. Uses the template-provided + // value for the number of residuals ("kNumResiduals"). explicit AutoDiffCostFunction(CostFunctor* functor, Ownership ownership = TAKE_OWNERSHIP) : functor_(functor), ownership_(ownership) { @@ -168,9 +168,9 @@ class AutoDiffCostFunction : public SizedCostFunction { // // This allows for having autodiff cost functions which return varying // numbers of residuals at runtime. - explicit AutoDiffCostFunction(CostFunctor* functor, - int num_residuals, - Ownership ownership = TAKE_OWNERSHIP) + AutoDiffCostFunction(CostFunctor* functor, + int num_residuals, + Ownership ownership = TAKE_OWNERSHIP) : functor_(functor), ownership_(ownership) { static_assert(kNumResiduals == DYNAMIC, "Can't run the dynamic-size constructor if the number of " diff --git a/include/ceres/dynamic_autodiff_cost_function.h b/include/ceres/dynamic_autodiff_cost_function.h index 10270643b..76ca4f2c7 100644 --- a/include/ceres/dynamic_autodiff_cost_function.h +++ b/include/ceres/dynamic_autodiff_cost_function.h @@ -40,6 +40,7 @@ #include "ceres/dynamic_cost_function.h" #include "ceres/internal/fixed_array.h" #include "ceres/jet.h" +#include "ceres/types.h" #include "glog/logging.h" namespace ceres { @@ -78,10 +79,25 @@ namespace ceres { template class DynamicAutoDiffCostFunction : public DynamicCostFunction { public: - explicit DynamicAutoDiffCostFunction(CostFunctor* functor) - : functor_(functor) {} - virtual ~DynamicAutoDiffCostFunction() {} + // Takes ownership by default. + DynamicAutoDiffCostFunction(CostFunctor* functor, + Ownership ownership = TAKE_OWNERSHIP) + : functor_(functor), ownership_(ownership) {} + + explicit DynamicAutoDiffCostFunction(DynamicAutoDiffCostFunction&& other) + : functor_(std::move(other.functor_)), ownership_(other.ownership_) {} + + virtual ~DynamicAutoDiffCostFunction() { + // Manually release pointer if configured to not take ownership + // rather than deleting only if ownership is taken. This is to + // stay maximally compatible to old user code which may have + // forgotten to implement a virtual destructor, from when the + // AutoDiffCostFunction always took ownership. + if (ownership_ == DO_NOT_TAKE_OWNERSHIP) { + functor_.release(); + } + } bool Evaluate(double const* const* parameters, double* residuals, @@ -251,6 +267,7 @@ class DynamicAutoDiffCostFunction : public DynamicCostFunction { private: std::unique_ptr functor_; + Ownership ownership_; }; } // namespace ceres diff --git a/include/ceres/dynamic_numeric_diff_cost_function.h b/include/ceres/dynamic_numeric_diff_cost_function.h index 119b3f85e..ccc8f66db 100644 --- a/include/ceres/dynamic_numeric_diff_cost_function.h +++ b/include/ceres/dynamic_numeric_diff_cost_function.h @@ -44,6 +44,7 @@ #include "ceres/internal/numeric_diff.h" #include "ceres/internal/parameter_dims.h" #include "ceres/numeric_diff_options.h" +#include "ceres/types.h" #include "glog/logging.h" namespace ceres { @@ -84,6 +85,10 @@ class DynamicNumericDiffCostFunction : public DynamicCostFunction { const NumericDiffOptions& options = NumericDiffOptions()) : functor_(functor), ownership_(ownership), options_(options) {} + explicit DynamicNumericDiffCostFunction( + DynamicNumericDiffCostFunction&& other) + : functor_(std::move(other.functor_)), ownership_(other.ownership_) {} + virtual ~DynamicNumericDiffCostFunction() { if (ownership_ != TAKE_OWNERSHIP) { functor_.release(); diff --git a/include/ceres/numeric_diff_cost_function.h b/include/ceres/numeric_diff_cost_function.h index c69f262f5..cf7971cde 100644 --- a/include/ceres/numeric_diff_cost_function.h +++ b/include/ceres/numeric_diff_cost_function.h @@ -192,7 +192,10 @@ class NumericDiffCostFunction : public SizedCostFunction { } } - ~NumericDiffCostFunction() { + explicit NumericDiffCostFunction(NumericDiffCostFunction&& other) + : functor_(std::move(other.functor_)), ownership_(other.ownership_) {} + + virtual ~NumericDiffCostFunction() { if (ownership_ != TAKE_OWNERSHIP) { functor_.release(); }