Austin Schuh | 70cc955 | 2019-01-21 19:46:48 -0800 | [diff] [blame] | 1 | // Ceres Solver - A fast non-linear least squares minimizer |
Austin Schuh | 3de38b0 | 2024-06-25 18:25:10 -0700 | [diff] [blame^] | 2 | // Copyright 2023 Google Inc. All rights reserved. |
Austin Schuh | 70cc955 | 2019-01-21 19:46:48 -0800 | [diff] [blame] | 3 | // http://ceres-solver.org/ |
| 4 | // |
| 5 | // Redistribution and use in source and binary forms, with or without |
| 6 | // modification, are permitted provided that the following conditions are met: |
| 7 | // |
| 8 | // * Redistributions of source code must retain the above copyright notice, |
| 9 | // this list of conditions and the following disclaimer. |
| 10 | // * Redistributions in binary form must reproduce the above copyright notice, |
| 11 | // this list of conditions and the following disclaimer in the documentation |
| 12 | // and/or other materials provided with the distribution. |
| 13 | // * Neither the name of Google Inc. nor the names of its contributors may be |
| 14 | // used to endorse or promote products derived from this software without |
| 15 | // specific prior written permission. |
| 16 | // |
| 17 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
| 18 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| 19 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| 20 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
| 21 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| 22 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| 23 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| 24 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| 25 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| 26 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| 27 | // POSSIBILITY OF SUCH DAMAGE. |
| 28 | // |
| 29 | // Author: sameeragarwal@google.com (Sameer Agarwal) |
| 30 | // keir@google.com (Keir Mierle) |
| 31 | |
| 32 | #include "ceres/problem.h" |
| 33 | |
Austin Schuh | 3de38b0 | 2024-06-25 18:25:10 -0700 | [diff] [blame^] | 34 | #include <memory> |
Austin Schuh | 70cc955 | 2019-01-21 19:46:48 -0800 | [diff] [blame] | 35 | #include <vector> |
Austin Schuh | 1d1e6ea | 2020-12-23 21:56:30 -0800 | [diff] [blame] | 36 | |
Austin Schuh | 70cc955 | 2019-01-21 19:46:48 -0800 | [diff] [blame] | 37 | #include "ceres/crs_matrix.h" |
| 38 | #include "ceres/problem_impl.h" |
| 39 | |
| 40 | namespace ceres { |
| 41 | |
Austin Schuh | 1d1e6ea | 2020-12-23 21:56:30 -0800 | [diff] [blame] | 42 | Problem::Problem() : impl_(new internal::ProblemImpl) {} |
Austin Schuh | 70cc955 | 2019-01-21 19:46:48 -0800 | [diff] [blame] | 43 | Problem::Problem(const Problem::Options& options) |
Austin Schuh | 1d1e6ea | 2020-12-23 21:56:30 -0800 | [diff] [blame] | 44 | : impl_(new internal::ProblemImpl(options)) {} |
| 45 | // Not inline defaulted in declaration due to use of std::unique_ptr. |
| 46 | Problem::Problem(Problem&&) = default; |
| 47 | Problem& Problem::operator=(Problem&&) = default; |
Austin Schuh | 3de38b0 | 2024-06-25 18:25:10 -0700 | [diff] [blame^] | 48 | Problem::~Problem() = default; |
Austin Schuh | 70cc955 | 2019-01-21 19:46:48 -0800 | [diff] [blame] | 49 | |
| 50 | ResidualBlockId Problem::AddResidualBlock( |
| 51 | CostFunction* cost_function, |
| 52 | LossFunction* loss_function, |
Austin Schuh | 3de38b0 | 2024-06-25 18:25:10 -0700 | [diff] [blame^] | 53 | const std::vector<double*>& parameter_blocks) { |
Austin Schuh | 1d1e6ea | 2020-12-23 21:56:30 -0800 | [diff] [blame] | 54 | return impl_->AddResidualBlock(cost_function, |
| 55 | loss_function, |
| 56 | parameter_blocks.data(), |
| 57 | static_cast<int>(parameter_blocks.size())); |
Austin Schuh | 70cc955 | 2019-01-21 19:46:48 -0800 | [diff] [blame] | 58 | } |
| 59 | |
Austin Schuh | 1d1e6ea | 2020-12-23 21:56:30 -0800 | [diff] [blame] | 60 | ResidualBlockId Problem::AddResidualBlock(CostFunction* cost_function, |
| 61 | LossFunction* loss_function, |
| 62 | double* const* const parameter_blocks, |
| 63 | int num_parameter_blocks) { |
| 64 | return impl_->AddResidualBlock( |
| 65 | cost_function, loss_function, parameter_blocks, num_parameter_blocks); |
Austin Schuh | 70cc955 | 2019-01-21 19:46:48 -0800 | [diff] [blame] | 66 | } |
| 67 | |
| 68 | void Problem::AddParameterBlock(double* values, int size) { |
Austin Schuh | 1d1e6ea | 2020-12-23 21:56:30 -0800 | [diff] [blame] | 69 | impl_->AddParameterBlock(values, size); |
Austin Schuh | 70cc955 | 2019-01-21 19:46:48 -0800 | [diff] [blame] | 70 | } |
| 71 | |
Austin Schuh | 3de38b0 | 2024-06-25 18:25:10 -0700 | [diff] [blame^] | 72 | void Problem::AddParameterBlock(double* values, int size, Manifold* manifold) { |
| 73 | impl_->AddParameterBlock(values, size, manifold); |
Austin Schuh | 70cc955 | 2019-01-21 19:46:48 -0800 | [diff] [blame] | 74 | } |
| 75 | |
| 76 | void Problem::RemoveResidualBlock(ResidualBlockId residual_block) { |
Austin Schuh | 1d1e6ea | 2020-12-23 21:56:30 -0800 | [diff] [blame] | 77 | impl_->RemoveResidualBlock(residual_block); |
Austin Schuh | 70cc955 | 2019-01-21 19:46:48 -0800 | [diff] [blame] | 78 | } |
| 79 | |
Austin Schuh | 1d1e6ea | 2020-12-23 21:56:30 -0800 | [diff] [blame] | 80 | void Problem::RemoveParameterBlock(const double* values) { |
| 81 | impl_->RemoveParameterBlock(values); |
Austin Schuh | 70cc955 | 2019-01-21 19:46:48 -0800 | [diff] [blame] | 82 | } |
| 83 | |
Austin Schuh | 1d1e6ea | 2020-12-23 21:56:30 -0800 | [diff] [blame] | 84 | void Problem::SetParameterBlockConstant(const double* values) { |
| 85 | impl_->SetParameterBlockConstant(values); |
Austin Schuh | 70cc955 | 2019-01-21 19:46:48 -0800 | [diff] [blame] | 86 | } |
| 87 | |
| 88 | void Problem::SetParameterBlockVariable(double* values) { |
Austin Schuh | 1d1e6ea | 2020-12-23 21:56:30 -0800 | [diff] [blame] | 89 | impl_->SetParameterBlockVariable(values); |
Austin Schuh | 70cc955 | 2019-01-21 19:46:48 -0800 | [diff] [blame] | 90 | } |
| 91 | |
Austin Schuh | 1d1e6ea | 2020-12-23 21:56:30 -0800 | [diff] [blame] | 92 | bool Problem::IsParameterBlockConstant(const double* values) const { |
| 93 | return impl_->IsParameterBlockConstant(values); |
Austin Schuh | 70cc955 | 2019-01-21 19:46:48 -0800 | [diff] [blame] | 94 | } |
| 95 | |
Austin Schuh | 3de38b0 | 2024-06-25 18:25:10 -0700 | [diff] [blame^] | 96 | void Problem::SetManifold(double* values, Manifold* manifold) { |
| 97 | impl_->SetManifold(values, manifold); |
Austin Schuh | 70cc955 | 2019-01-21 19:46:48 -0800 | [diff] [blame] | 98 | } |
| 99 | |
Austin Schuh | 3de38b0 | 2024-06-25 18:25:10 -0700 | [diff] [blame^] | 100 | const Manifold* Problem::GetManifold(const double* values) const { |
| 101 | return impl_->GetManifold(values); |
| 102 | } |
| 103 | |
| 104 | bool Problem::HasManifold(const double* values) const { |
| 105 | return impl_->HasManifold(values); |
Austin Schuh | 70cc955 | 2019-01-21 19:46:48 -0800 | [diff] [blame] | 106 | } |
| 107 | |
| 108 | void Problem::SetParameterLowerBound(double* values, |
| 109 | int index, |
| 110 | double lower_bound) { |
Austin Schuh | 1d1e6ea | 2020-12-23 21:56:30 -0800 | [diff] [blame] | 111 | impl_->SetParameterLowerBound(values, index, lower_bound); |
Austin Schuh | 70cc955 | 2019-01-21 19:46:48 -0800 | [diff] [blame] | 112 | } |
| 113 | |
| 114 | void Problem::SetParameterUpperBound(double* values, |
| 115 | int index, |
| 116 | double upper_bound) { |
Austin Schuh | 1d1e6ea | 2020-12-23 21:56:30 -0800 | [diff] [blame] | 117 | impl_->SetParameterUpperBound(values, index, upper_bound); |
Austin Schuh | 70cc955 | 2019-01-21 19:46:48 -0800 | [diff] [blame] | 118 | } |
| 119 | |
Austin Schuh | 1d1e6ea | 2020-12-23 21:56:30 -0800 | [diff] [blame] | 120 | double Problem::GetParameterUpperBound(const double* values, int index) const { |
| 121 | return impl_->GetParameterUpperBound(values, index); |
Austin Schuh | 70cc955 | 2019-01-21 19:46:48 -0800 | [diff] [blame] | 122 | } |
| 123 | |
Austin Schuh | 1d1e6ea | 2020-12-23 21:56:30 -0800 | [diff] [blame] | 124 | double Problem::GetParameterLowerBound(const double* values, int index) const { |
| 125 | return impl_->GetParameterLowerBound(values, index); |
Austin Schuh | 70cc955 | 2019-01-21 19:46:48 -0800 | [diff] [blame] | 126 | } |
| 127 | |
| 128 | bool Problem::Evaluate(const EvaluateOptions& evaluate_options, |
| 129 | double* cost, |
Austin Schuh | 3de38b0 | 2024-06-25 18:25:10 -0700 | [diff] [blame^] | 130 | std::vector<double>* residuals, |
| 131 | std::vector<double>* gradient, |
Austin Schuh | 70cc955 | 2019-01-21 19:46:48 -0800 | [diff] [blame] | 132 | CRSMatrix* jacobian) { |
Austin Schuh | 1d1e6ea | 2020-12-23 21:56:30 -0800 | [diff] [blame] | 133 | return impl_->Evaluate(evaluate_options, cost, residuals, gradient, jacobian); |
Austin Schuh | 70cc955 | 2019-01-21 19:46:48 -0800 | [diff] [blame] | 134 | } |
| 135 | |
Austin Schuh | 1d1e6ea | 2020-12-23 21:56:30 -0800 | [diff] [blame] | 136 | bool Problem::EvaluateResidualBlock(ResidualBlockId residual_block_id, |
| 137 | bool apply_loss_function, |
| 138 | double* cost, |
| 139 | double* residuals, |
| 140 | double** jacobians) const { |
| 141 | return impl_->EvaluateResidualBlock(residual_block_id, |
| 142 | apply_loss_function, |
| 143 | /* new_point = */ true, |
| 144 | cost, |
| 145 | residuals, |
| 146 | jacobians); |
Austin Schuh | 70cc955 | 2019-01-21 19:46:48 -0800 | [diff] [blame] | 147 | } |
| 148 | |
Austin Schuh | 1d1e6ea | 2020-12-23 21:56:30 -0800 | [diff] [blame] | 149 | bool Problem::EvaluateResidualBlockAssumingParametersUnchanged( |
| 150 | ResidualBlockId residual_block_id, |
| 151 | bool apply_loss_function, |
| 152 | double* cost, |
| 153 | double* residuals, |
| 154 | double** jacobians) const { |
| 155 | return impl_->EvaluateResidualBlock(residual_block_id, |
| 156 | apply_loss_function, |
| 157 | /* new_point = */ false, |
| 158 | cost, |
| 159 | residuals, |
| 160 | jacobians); |
Austin Schuh | 70cc955 | 2019-01-21 19:46:48 -0800 | [diff] [blame] | 161 | } |
| 162 | |
Austin Schuh | 1d1e6ea | 2020-12-23 21:56:30 -0800 | [diff] [blame] | 163 | int Problem::NumParameterBlocks() const { return impl_->NumParameterBlocks(); } |
Austin Schuh | 70cc955 | 2019-01-21 19:46:48 -0800 | [diff] [blame] | 164 | |
Austin Schuh | 1d1e6ea | 2020-12-23 21:56:30 -0800 | [diff] [blame] | 165 | int Problem::NumParameters() const { return impl_->NumParameters(); } |
| 166 | |
| 167 | int Problem::NumResidualBlocks() const { return impl_->NumResidualBlocks(); } |
| 168 | |
| 169 | int Problem::NumResiduals() const { return impl_->NumResiduals(); } |
Austin Schuh | 70cc955 | 2019-01-21 19:46:48 -0800 | [diff] [blame] | 170 | |
Austin Schuh | 3de38b0 | 2024-06-25 18:25:10 -0700 | [diff] [blame^] | 171 | int Problem::ParameterBlockSize(const double* values) const { |
| 172 | return impl_->ParameterBlockSize(values); |
Austin Schuh | 70cc955 | 2019-01-21 19:46:48 -0800 | [diff] [blame] | 173 | } |
| 174 | |
Austin Schuh | 3de38b0 | 2024-06-25 18:25:10 -0700 | [diff] [blame^] | 175 | int Problem::ParameterBlockTangentSize(const double* values) const { |
| 176 | return impl_->ParameterBlockTangentSize(values); |
Austin Schuh | 70cc955 | 2019-01-21 19:46:48 -0800 | [diff] [blame] | 177 | } |
| 178 | |
| 179 | bool Problem::HasParameterBlock(const double* values) const { |
Austin Schuh | 1d1e6ea | 2020-12-23 21:56:30 -0800 | [diff] [blame] | 180 | return impl_->HasParameterBlock(values); |
Austin Schuh | 70cc955 | 2019-01-21 19:46:48 -0800 | [diff] [blame] | 181 | } |
| 182 | |
Austin Schuh | 3de38b0 | 2024-06-25 18:25:10 -0700 | [diff] [blame^] | 183 | void Problem::GetParameterBlocks(std::vector<double*>* parameter_blocks) const { |
Austin Schuh | 1d1e6ea | 2020-12-23 21:56:30 -0800 | [diff] [blame] | 184 | impl_->GetParameterBlocks(parameter_blocks); |
Austin Schuh | 70cc955 | 2019-01-21 19:46:48 -0800 | [diff] [blame] | 185 | } |
| 186 | |
| 187 | void Problem::GetResidualBlocks( |
Austin Schuh | 3de38b0 | 2024-06-25 18:25:10 -0700 | [diff] [blame^] | 188 | std::vector<ResidualBlockId>* residual_blocks) const { |
Austin Schuh | 1d1e6ea | 2020-12-23 21:56:30 -0800 | [diff] [blame] | 189 | impl_->GetResidualBlocks(residual_blocks); |
Austin Schuh | 70cc955 | 2019-01-21 19:46:48 -0800 | [diff] [blame] | 190 | } |
| 191 | |
| 192 | void Problem::GetParameterBlocksForResidualBlock( |
| 193 | const ResidualBlockId residual_block, |
Austin Schuh | 3de38b0 | 2024-06-25 18:25:10 -0700 | [diff] [blame^] | 194 | std::vector<double*>* parameter_blocks) const { |
Austin Schuh | 1d1e6ea | 2020-12-23 21:56:30 -0800 | [diff] [blame] | 195 | impl_->GetParameterBlocksForResidualBlock(residual_block, parameter_blocks); |
Austin Schuh | 70cc955 | 2019-01-21 19:46:48 -0800 | [diff] [blame] | 196 | } |
| 197 | |
| 198 | const CostFunction* Problem::GetCostFunctionForResidualBlock( |
| 199 | const ResidualBlockId residual_block) const { |
Austin Schuh | 1d1e6ea | 2020-12-23 21:56:30 -0800 | [diff] [blame] | 200 | return impl_->GetCostFunctionForResidualBlock(residual_block); |
Austin Schuh | 70cc955 | 2019-01-21 19:46:48 -0800 | [diff] [blame] | 201 | } |
| 202 | |
| 203 | const LossFunction* Problem::GetLossFunctionForResidualBlock( |
| 204 | const ResidualBlockId residual_block) const { |
Austin Schuh | 1d1e6ea | 2020-12-23 21:56:30 -0800 | [diff] [blame] | 205 | return impl_->GetLossFunctionForResidualBlock(residual_block); |
Austin Schuh | 70cc955 | 2019-01-21 19:46:48 -0800 | [diff] [blame] | 206 | } |
| 207 | |
| 208 | void Problem::GetResidualBlocksForParameterBlock( |
Austin Schuh | 3de38b0 | 2024-06-25 18:25:10 -0700 | [diff] [blame^] | 209 | const double* values, std::vector<ResidualBlockId>* residual_blocks) const { |
Austin Schuh | 1d1e6ea | 2020-12-23 21:56:30 -0800 | [diff] [blame] | 210 | impl_->GetResidualBlocksForParameterBlock(values, residual_blocks); |
Austin Schuh | 70cc955 | 2019-01-21 19:46:48 -0800 | [diff] [blame] | 211 | } |
| 212 | |
Austin Schuh | 3de38b0 | 2024-06-25 18:25:10 -0700 | [diff] [blame^] | 213 | const Problem::Options& Problem::options() const { return impl_->options(); } |
| 214 | |
| 215 | internal::ProblemImpl* Problem::mutable_impl() { return impl_.get(); } |
| 216 | |
Austin Schuh | 70cc955 | 2019-01-21 19:46:48 -0800 | [diff] [blame] | 217 | } // namespace ceres |