blob: e9d23ece079ea6232d45b710a96d691634aa2b70 [file] [log] [blame]
Keir Mierle8ebb0732012-04-30 23:09:08 -07001// Ceres Solver - A fast non-linear least squares minimizer
2// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
3// http://code.google.com/p/ceres-solver/
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_impl.h"
33
34#include <algorithm>
35#include <cstddef>
36#include <set>
37#include <string>
38#include <utility>
39#include <vector>
Sameer Agarwal0beab862012-08-13 15:12:01 -070040#include "ceres/cost_function.h"
41#include "ceres/loss_function.h"
42#include "ceres/map_util.h"
Keir Mierle8ebb0732012-04-30 23:09:08 -070043#include "ceres/parameter_block.h"
44#include "ceres/program.h"
45#include "ceres/residual_block.h"
46#include "ceres/stl_util.h"
Keir Mierle8ebb0732012-04-30 23:09:08 -070047#include "ceres/stringprintf.h"
Sameer Agarwal0beab862012-08-13 15:12:01 -070048#include "glog/logging.h"
Keir Mierle8ebb0732012-04-30 23:09:08 -070049
50namespace ceres {
51namespace internal {
52
53typedef map<double*, internal::ParameterBlock*> ParameterMap;
54
55// Returns true if two regions of memory, a and b, with sizes size_a and size_b
56// respectively, overlap.
57static bool RegionsAlias(const double* a, int size_a,
58 const double* b, int size_b) {
59 return (a < b) ? b < (a + size_a)
60 : a < (b + size_b);
61}
62
63static void CheckForNoAliasing(double* existing_block,
64 int existing_block_size,
65 double* new_block,
66 int new_block_size) {
67 CHECK(!RegionsAlias(existing_block, existing_block_size,
68 new_block, new_block_size))
69 << "Aliasing detected between existing parameter block at memory "
70 << "location " << existing_block
71 << " and has size " << existing_block_size << " with new parameter "
72 << "block that has memory adderss " << new_block << " and would have "
73 << "size " << new_block_size << ".";
74}
75
Sameer Agarwal8e1f83c2013-02-15 08:35:40 -080076ParameterBlock* ProblemImpl::InternalAddParameterBlock(double* values,
77 int size) {
78 CHECK(values != NULL) << "Null pointer passed to AddParameterBlock "
79 << "for a parameter with size " << size;
Keir Mierle8ebb0732012-04-30 23:09:08 -070080
81 // Ignore the request if there is a block for the given pointer already.
Sameer Agarwal8e1f83c2013-02-15 08:35:40 -080082 ParameterMap::iterator it = parameter_block_map_.find(values);
83 if (it != parameter_block_map_.end()) {
84 if (!options_.disable_all_safety_checks) {
85 int existing_size = it->second->Size();
86 CHECK(size == existing_size)
87 << "Tried adding a parameter block with the same double pointer, "
88 << values << ", twice, but with different block sizes. Original "
89 << "size was " << existing_size << " but new size is "
90 << size;
91 }
Keir Mierle8ebb0732012-04-30 23:09:08 -070092 return it->second;
93 }
Keir Mierle8ebb0732012-04-30 23:09:08 -070094
Sameer Agarwal8e1f83c2013-02-15 08:35:40 -080095 if (!options_.disable_all_safety_checks) {
96 // Before adding the parameter block, also check that it doesn't alias any
97 // other parameter blocks.
98 if (!parameter_block_map_.empty()) {
99 ParameterMap::iterator lb = parameter_block_map_.lower_bound(values);
Keir Mierle8ebb0732012-04-30 23:09:08 -0700100
Sameer Agarwal8e1f83c2013-02-15 08:35:40 -0800101 // If lb is not the first block, check the previous block for aliasing.
102 if (lb != parameter_block_map_.begin()) {
103 ParameterMap::iterator previous = lb;
104 --previous;
105 CheckForNoAliasing(previous->first,
106 previous->second->Size(),
107 values,
108 size);
109 }
110
111 // If lb is not off the end, check lb for aliasing.
112 if (lb != parameter_block_map_.end()) {
113 CheckForNoAliasing(lb->first,
114 lb->second->Size(),
115 values,
116 size);
117 }
Keir Mierle8ebb0732012-04-30 23:09:08 -0700118 }
119 }
Sameer Agarwal8e1f83c2013-02-15 08:35:40 -0800120
Keir Mierle8ebb0732012-04-30 23:09:08 -0700121 ParameterBlock* new_parameter_block = new ParameterBlock(values, size);
Sameer Agarwal8e1f83c2013-02-15 08:35:40 -0800122 parameter_block_map_[values] = new_parameter_block;
123 program_->parameter_blocks_.push_back(new_parameter_block);
Keir Mierle8ebb0732012-04-30 23:09:08 -0700124 return new_parameter_block;
125}
126
127ProblemImpl::ProblemImpl() : program_(new internal::Program) {}
128ProblemImpl::ProblemImpl(const Problem::Options& options)
129 : options_(options),
130 program_(new internal::Program) {}
131
132ProblemImpl::~ProblemImpl() {
133 // Collect the unique cost/loss functions and delete the residuals.
Sameer Agarwal8e1f83c2013-02-15 08:35:40 -0800134 const int num_residual_blocks = program_->residual_blocks_.size();
135
136 vector<CostFunction*> cost_functions;
137 cost_functions.reserve(num_residual_blocks);
138
139 vector<LossFunction*> loss_functions;
140 loss_functions.reserve(num_residual_blocks);
141
Keir Mierle8ebb0732012-04-30 23:09:08 -0700142 for (int i = 0; i < program_->residual_blocks_.size(); ++i) {
143 ResidualBlock* residual_block = program_->residual_blocks_[i];
144
145 // The const casts here are legit, since ResidualBlock holds these
146 // pointers as const pointers but we have ownership of them and
147 // have the right to destroy them when the destructor is called.
148 if (options_.cost_function_ownership == TAKE_OWNERSHIP) {
Sameer Agarwal8e1f83c2013-02-15 08:35:40 -0800149 cost_functions.push_back(
Keir Mierle8ebb0732012-04-30 23:09:08 -0700150 const_cast<CostFunction*>(residual_block->cost_function()));
151 }
152 if (options_.loss_function_ownership == TAKE_OWNERSHIP) {
Sameer Agarwal8e1f83c2013-02-15 08:35:40 -0800153 loss_functions.push_back(
Keir Mierle8ebb0732012-04-30 23:09:08 -0700154 const_cast<LossFunction*>(residual_block->loss_function()));
155 }
156
157 delete residual_block;
158 }
159
160 // Collect the unique parameterizations and delete the parameters.
Sameer Agarwal8e1f83c2013-02-15 08:35:40 -0800161 vector<LocalParameterization*> local_parameterizations;
Keir Mierle8ebb0732012-04-30 23:09:08 -0700162 for (int i = 0; i < program_->parameter_blocks_.size(); ++i) {
163 ParameterBlock* parameter_block = program_->parameter_blocks_[i];
164
165 if (options_.local_parameterization_ownership == TAKE_OWNERSHIP) {
Sameer Agarwal8e1f83c2013-02-15 08:35:40 -0800166 local_parameterizations.push_back(
167 parameter_block->local_parameterization_);
Keir Mierle8ebb0732012-04-30 23:09:08 -0700168 }
169
170 delete parameter_block;
171 }
172
173 // Delete the owned cost/loss functions and parameterizations.
Sameer Agarwal8e1f83c2013-02-15 08:35:40 -0800174 STLDeleteUniqueContainerPointers(local_parameterizations.begin(),
175 local_parameterizations.end());
176 STLDeleteUniqueContainerPointers(cost_functions.begin(),
177 cost_functions.end());
178 STLDeleteUniqueContainerPointers(loss_functions.begin(),
179 loss_functions.end());
Keir Mierle8ebb0732012-04-30 23:09:08 -0700180}
181
182const ResidualBlock* ProblemImpl::AddResidualBlock(
183 CostFunction* cost_function,
184 LossFunction* loss_function,
185 const vector<double*>& parameter_blocks) {
186 CHECK_NOTNULL(cost_function);
187 CHECK_EQ(parameter_blocks.size(),
188 cost_function->parameter_block_sizes().size());
189
190 // Check the sizes match.
191 const vector<int16>& parameter_block_sizes =
192 cost_function->parameter_block_sizes();
Keir Mierle8ebb0732012-04-30 23:09:08 -0700193
Sameer Agarwal8e1f83c2013-02-15 08:35:40 -0800194 if (!options_.disable_all_safety_checks) {
195 CHECK_EQ(parameter_block_sizes.size(), parameter_blocks.size())
196 << "Number of blocks input is different than the number of blocks "
197 << "that the cost function expects.";
198
199 // Check for duplicate parameter blocks.
200 vector<double*> sorted_parameter_blocks(parameter_blocks);
201 sort(sorted_parameter_blocks.begin(), sorted_parameter_blocks.end());
202 vector<double*>::const_iterator duplicate_items =
203 unique(sorted_parameter_blocks.begin(),
204 sorted_parameter_blocks.end());
205 if (duplicate_items != sorted_parameter_blocks.end()) {
206 string blocks;
207 for (int i = 0; i < parameter_blocks.size(); ++i) {
208 blocks += internal::StringPrintf(" %p ", parameter_blocks[i]);
209 }
210
211 LOG(FATAL) << "Duplicate parameter blocks in a residual parameter "
212 << "are not allowed. Parameter block pointers: ["
213 << blocks << "]";
Keir Mierle8ebb0732012-04-30 23:09:08 -0700214 }
Keir Mierle8ebb0732012-04-30 23:09:08 -0700215 }
216
217 // Add parameter blocks and convert the double*'s to parameter blocks.
218 vector<ParameterBlock*> parameter_block_ptrs(parameter_blocks.size());
219 for (int i = 0; i < parameter_blocks.size(); ++i) {
220 parameter_block_ptrs[i] =
221 InternalAddParameterBlock(parameter_blocks[i],
Sameer Agarwal8e1f83c2013-02-15 08:35:40 -0800222 parameter_block_sizes[i]);
Keir Mierle8ebb0732012-04-30 23:09:08 -0700223 }
224
Sameer Agarwal8e1f83c2013-02-15 08:35:40 -0800225 if (!options_.disable_all_safety_checks) {
226 // Check that the block sizes match the block sizes expected by the
227 // cost_function.
228 for (int i = 0; i < parameter_block_ptrs.size(); ++i) {
229 CHECK_EQ(cost_function->parameter_block_sizes()[i],
230 parameter_block_ptrs[i]->Size())
231 << "The cost function expects parameter block " << i
232 << " of size " << cost_function->parameter_block_sizes()[i]
233 << " but was given a block of size "
234 << parameter_block_ptrs[i]->Size();
235 }
Keir Mierle8ebb0732012-04-30 23:09:08 -0700236 }
237
238 ResidualBlock* new_residual_block =
239 new ResidualBlock(cost_function,
240 loss_function,
241 parameter_block_ptrs);
242 program_->residual_blocks_.push_back(new_residual_block);
243 return new_residual_block;
244}
245
246// Unfortunately, macros don't help much to reduce this code, and var args don't
247// work because of the ambiguous case that there is no loss function.
248const ResidualBlock* ProblemImpl::AddResidualBlock(
249 CostFunction* cost_function,
250 LossFunction* loss_function,
251 double* x0) {
252 vector<double*> residual_parameters;
253 residual_parameters.push_back(x0);
254 return AddResidualBlock(cost_function, loss_function, residual_parameters);
255}
256
257const ResidualBlock* ProblemImpl::AddResidualBlock(
258 CostFunction* cost_function,
259 LossFunction* loss_function,
260 double* x0, double* x1) {
261 vector<double*> residual_parameters;
262 residual_parameters.push_back(x0);
263 residual_parameters.push_back(x1);
264 return AddResidualBlock(cost_function, loss_function, residual_parameters);
265}
266
267const ResidualBlock* ProblemImpl::AddResidualBlock(
268 CostFunction* cost_function,
269 LossFunction* loss_function,
270 double* x0, double* x1, double* x2) {
271 vector<double*> residual_parameters;
272 residual_parameters.push_back(x0);
273 residual_parameters.push_back(x1);
274 residual_parameters.push_back(x2);
275 return AddResidualBlock(cost_function, loss_function, residual_parameters);
276}
277
278const ResidualBlock* ProblemImpl::AddResidualBlock(
279 CostFunction* cost_function,
280 LossFunction* loss_function,
281 double* x0, double* x1, double* x2, double* x3) {
282 vector<double*> residual_parameters;
283 residual_parameters.push_back(x0);
284 residual_parameters.push_back(x1);
285 residual_parameters.push_back(x2);
286 residual_parameters.push_back(x3);
287 return AddResidualBlock(cost_function, loss_function, residual_parameters);
288}
289
290const ResidualBlock* ProblemImpl::AddResidualBlock(
291 CostFunction* cost_function,
292 LossFunction* loss_function,
293 double* x0, double* x1, double* x2, double* x3, double* x4) {
294 vector<double*> residual_parameters;
295 residual_parameters.push_back(x0);
296 residual_parameters.push_back(x1);
297 residual_parameters.push_back(x2);
298 residual_parameters.push_back(x3);
299 residual_parameters.push_back(x4);
300 return AddResidualBlock(cost_function, loss_function, residual_parameters);
301}
302
303const ResidualBlock* ProblemImpl::AddResidualBlock(
304 CostFunction* cost_function,
305 LossFunction* loss_function,
306 double* x0, double* x1, double* x2, double* x3, double* x4, double* x5) {
307 vector<double*> residual_parameters;
308 residual_parameters.push_back(x0);
309 residual_parameters.push_back(x1);
310 residual_parameters.push_back(x2);
311 residual_parameters.push_back(x3);
312 residual_parameters.push_back(x4);
313 residual_parameters.push_back(x5);
314 return AddResidualBlock(cost_function, loss_function, residual_parameters);
315}
316
Fisher12626e82012-10-21 14:12:04 -0400317const ResidualBlock* ProblemImpl::AddResidualBlock(
318 CostFunction* cost_function,
319 LossFunction* loss_function,
320 double* x0, double* x1, double* x2, double* x3, double* x4, double* x5,
321 double* x6) {
322 vector<double*> residual_parameters;
323 residual_parameters.push_back(x0);
324 residual_parameters.push_back(x1);
325 residual_parameters.push_back(x2);
326 residual_parameters.push_back(x3);
327 residual_parameters.push_back(x4);
328 residual_parameters.push_back(x5);
329 residual_parameters.push_back(x6);
330 return AddResidualBlock(cost_function, loss_function, residual_parameters);
331}
332
333const ResidualBlock* ProblemImpl::AddResidualBlock(
334 CostFunction* cost_function,
335 LossFunction* loss_function,
336 double* x0, double* x1, double* x2, double* x3, double* x4, double* x5,
337 double* x6, double* x7) {
338 vector<double*> residual_parameters;
339 residual_parameters.push_back(x0);
340 residual_parameters.push_back(x1);
341 residual_parameters.push_back(x2);
342 residual_parameters.push_back(x3);
343 residual_parameters.push_back(x4);
344 residual_parameters.push_back(x5);
345 residual_parameters.push_back(x6);
346 residual_parameters.push_back(x7);
347 return AddResidualBlock(cost_function, loss_function, residual_parameters);
348}
349
350const ResidualBlock* ProblemImpl::AddResidualBlock(
351 CostFunction* cost_function,
352 LossFunction* loss_function,
353 double* x0, double* x1, double* x2, double* x3, double* x4, double* x5,
354 double* x6, double* x7, double* x8) {
355 vector<double*> residual_parameters;
356 residual_parameters.push_back(x0);
357 residual_parameters.push_back(x1);
358 residual_parameters.push_back(x2);
359 residual_parameters.push_back(x3);
360 residual_parameters.push_back(x4);
361 residual_parameters.push_back(x5);
362 residual_parameters.push_back(x6);
363 residual_parameters.push_back(x7);
364 residual_parameters.push_back(x8);
365 return AddResidualBlock(cost_function, loss_function, residual_parameters);
366}
367
368const ResidualBlock* ProblemImpl::AddResidualBlock(
369 CostFunction* cost_function,
370 LossFunction* loss_function,
371 double* x0, double* x1, double* x2, double* x3, double* x4, double* x5,
372 double* x6, double* x7, double* x8, double* x9) {
373 vector<double*> residual_parameters;
374 residual_parameters.push_back(x0);
375 residual_parameters.push_back(x1);
376 residual_parameters.push_back(x2);
377 residual_parameters.push_back(x3);
378 residual_parameters.push_back(x4);
379 residual_parameters.push_back(x5);
380 residual_parameters.push_back(x6);
381 residual_parameters.push_back(x7);
382 residual_parameters.push_back(x8);
383 residual_parameters.push_back(x9);
384 return AddResidualBlock(cost_function, loss_function, residual_parameters);
385}
Keir Mierle8ebb0732012-04-30 23:09:08 -0700386
387void ProblemImpl::AddParameterBlock(double* values, int size) {
Sameer Agarwal8e1f83c2013-02-15 08:35:40 -0800388 InternalAddParameterBlock(values, size);
Keir Mierle8ebb0732012-04-30 23:09:08 -0700389}
390
391void ProblemImpl::AddParameterBlock(
392 double* values,
393 int size,
394 LocalParameterization* local_parameterization) {
395 ParameterBlock* parameter_block =
Sameer Agarwal8e1f83c2013-02-15 08:35:40 -0800396 InternalAddParameterBlock(values, size);
Keir Mierle8ebb0732012-04-30 23:09:08 -0700397 if (local_parameterization != NULL) {
398 parameter_block->SetParameterization(local_parameterization);
399 }
400}
401
402void ProblemImpl::SetParameterBlockConstant(double* values) {
403 FindOrDie(parameter_block_map_, values)->SetConstant();
404}
405
406void ProblemImpl::SetParameterBlockVariable(double* values) {
407 FindOrDie(parameter_block_map_, values)->SetVarying();
408}
409
410void ProblemImpl::SetParameterization(
411 double* values,
412 LocalParameterization* local_parameterization) {
413 FindOrDie(parameter_block_map_, values)
414 ->SetParameterization(local_parameterization);
415}
416
417int ProblemImpl::NumParameterBlocks() const {
418 return program_->NumParameterBlocks();
419}
420
421int ProblemImpl::NumParameters() const {
422 return program_->NumParameters();
423}
424
425int ProblemImpl::NumResidualBlocks() const {
426 return program_->NumResidualBlocks();
427}
428
429int ProblemImpl::NumResiduals() const {
430 return program_->NumResiduals();
431}
432
433} // namespace internal
434} // namespace ceres