Problem When Using DynamicCostFunctionToFunctor

111 views
Skip to first unread message

Adam Hartshorne

unread,
Jan 15, 2018, 3:31:43 PM1/15/18
to Ceres Solver
Using the follow simple example, based upon http://ceres-solver.org/nnls_modeling.html?highlight=dynamiccostfunctiontofunctor#dynamiccostfunctiontofunctor the parameter blocks are correctly passed to the DynCostFunctor, but when the Evaluate method of DynCostFunction is called, the memory supposedly holding the parameters is "unreadable". Perhaps I am missing something?


class DynCostFunction : public ceres::CostFunction {

public:
 
DynCostFunction() {}

 
virtual bool Evaluate(double const* const* parameters,
 
double* residuals,
 
double** jacobians) const {

  // NOT POINTING TO ANYWHERE
 
const double* sample_params_1 = parameters[0];
 
const double* sample_params_2 = parameters[1];

 
// FAILS AS CAN'T READ MEMORY STORING PARAMETERS

 std
::cout << "(" << sample_params_1[0] << "," << sample_params_1[1] << "," << ")" << "\t (" << sample_params_2[0] << "," << sample_params_2[1] << ")" << std::endl;

 
// IN REAL APP, RESIDUAL AND JACOBIAN CALCULATED HERE
 
// ...

 
return true;
 
}

};


class DynCostFunctor {

public:

 std
::unique_ptr<ceres::DynamicCostFunctionToFunctor> _compute_via_dyn_cost;

 
DynCostFunctor()
 
{
 _compute_via_dyn_cost
.reset(new ceres::DynamicCostFunctionToFunctor(new DynCostFunction()));
 
}


 
template<typename T>
 
bool operator()(T const* const* parameters, T* residual) const {

 
const T* sample_params_1 = parameters[0];
 
const T* sample_params_2 = parameters[1];

 
// CORRECTLY DISPLAYS THE PARAMETERS STORED IN PARAMETER BLOCKS AS EXPECTED
 std
::cout << "(" << sample_params_1[0] << "," << sample_params_1[1] << "," << ")" << "\t (" << sample_params_2[0] << "," << sample_params_2[1] << ")" << std::endl;

 
(*_compute_via_dyn_cost)(parameters, residual);

 
return true;
 
}

};


int main()
{

Problem problem;

const int parameter_1_block_size = 5 ;
const int n_samples = 100 ;
const int n_verts = 8;
const int parameter_2_block_size = n_verts *3 ;

MatrixXd X(parameter_1_block_size, n_samples);
X
.setZero();

double lower_bound = 0;
double upper_bound = 1.0;
std
::uniform_real_distribution<double> unif(lower_bound, upper_bound);
std
::default_random_engine re;

for (auto v : range(0, n_samples)) {
 X
(0, v) = v;
 X
(1, v) = unif(re);
 X
(2, v) = unif(re);
 X
(3, v) = unif(re);
 X
(4, v) = unif(re);
}


MatrixXd Y(parameter_2_block_size, 1);
Y
.setZero();

for (auto v : range(0, parameter_2_block_size)) {
 Y
(v) = unif(re);
}

std
::vector<double*> parameter_blocks(n_samples+1);

for (auto v : range(0, n_samples)) {
parameter_blocks
[v] = X.data() + (parameter_1_block_size * v);
problem
.AddParameterBlock(parameter_blocks[v], parameter_1_block_size);
}

parameter_blocks
[n_samples] = &Y(0);
problem
.AddParameterBlock(parameter_blocks[n_samples], parameter_2_block_size);

ceres
::DynamicAutoDiffCostFunction<DynCostFunctor>*
dynamic_sized_cost_function
(
new ceres::DynamicAutoDiffCostFunction<DynCostFunctor>(
new DynCostFunctor()));

dynamic_sized_cost_function
->AddParameterBlock(parameter_1_block_size);
dynamic_sized_cost_function
->AddParameterBlock(parameter_2_block_size);
dynamic_sized_cost_function
->SetNumResiduals(3);

for (auto s : range(0, n_samples)) {
problem
.AddResidualBlock(
 dynamic_sized_cost_function
,
NULL
,
parameter_blocks
[s],
parameter_blocks
[n_samples]);
}

Solver::Options options;
options
.max_num_iterations = 50;
options
.minimizer_progress_to_stdout = true;
options
.function_tolerance = 1e-100;
Solver::Summary summary;

ceres
::Solve(options, &problem, &summary);

std
::cout << summary.FullReport() << std::endl;

}




Sameer Agarwal

unread,
Jan 15, 2018, 7:19:24 PM1/15/18
to ceres-...@googlegroups.com
Adam,
DynCostFunction does not know its size. You need to call set_num_residuals() and add the size of the parameter blocks to the parameter_block_sizes_ array in its constructor.
Sameer


--
You received this message because you are subscribed to the Google Groups "Ceres Solver" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ceres-solver...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/ceres-solver/323db2ca-1422-4495-85de-b1820660afa7%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Adam Hartshorne

unread,
Jan 15, 2018, 7:42:22 PM1/15/18
to Ceres Solver
Thank you, that did the trick.

FYI anybody finding this thread in the future, see  class CallbackCostFunction : public ceres::CostFunction in /internal/ceres/c_api.cc for an example of how to do it.

Regards,

Adam
Reply all
Reply to author
Forward
0 new messages