Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <robot_calibration/ceres/optimizer.h>
00021
00022 #include <ceres/ceres.h>
00023
00024 #include <urdf/model.h>
00025 #include <kdl_parser/kdl_parser.hpp>
00026 #include <robot_calibration_msgs/CalibrationData.h>
00027
00028 #include <robot_calibration/calibration_offset_parser.h>
00029 #include <robot_calibration/ceres/camera3d_to_arm_error.h>
00030 #include <robot_calibration/ceres/ground_plane_error.h>
00031 #include <robot_calibration/ceres/data_functions.h>
00032 #include <robot_calibration/ceres/outrageous_error.h>
00033 #include <robot_calibration/models/camera3d.h>
00034 #include <robot_calibration/models/chain.h>
00035 #include <boost/shared_ptr.hpp>
00036 #include <string>
00037 #include <map>
00038
00039 namespace robot_calibration
00040 {
00041
00042 Optimizer::Optimizer(const std::string& robot_description)
00043 {
00044 if (!model_.initString(robot_description))
00045 std::cerr << "Failed to parse URDF." << std::endl;
00046 }
00047
00048 Optimizer::~Optimizer()
00049 {
00050 }
00051
00052
00053
00054 bool hasSensor(
00055 const robot_calibration_msgs::CalibrationData& msg,
00056 const std::string& sensor)
00057 {
00058 for (size_t i = 0; i < msg.observations.size(); i++)
00059 {
00060 if (msg.observations[i].sensor_name == sensor)
00061 return true;
00062 }
00063 return false;
00064 }
00065
00066 int Optimizer::optimize(OptimizationParams& params,
00067 std::vector<robot_calibration_msgs::CalibrationData> data,
00068 bool progress_to_stdout)
00069 {
00070
00071 if (!kdl_parser::treeFromUrdfModel(model_, tree_))
00072 {
00073 std::cerr << "Failed to construct KDL tree" << std::endl;
00074 return -1;
00075 }
00076
00077
00078 for (size_t i = 0; i < params.models.size(); ++i)
00079 {
00080 if (params.models[i].type == "chain")
00081 {
00082 ROS_INFO_STREAM("Creating chain '" << params.models[i].name << "' from " <<
00083 params.base_link << " to " <<
00084 params.models[i].params["frame"]);
00085 ChainModel* model = new ChainModel(params.models[i].name, tree_, params.base_link, params.models[i].params["frame"]);
00086 models_[params.models[i].name] = model;
00087 }
00088 else if (params.models[i].type == "camera3d")
00089 {
00090 ROS_INFO_STREAM("Creating camera3d '" << params.models[i].name << "' in frame " <<
00091 params.models[i].params["frame"]);
00092 Camera3dModel* model = new Camera3dModel(params.models[i].name, tree_, params.base_link, params.models[i].params["frame"]);
00093 models_[params.models[i].name] = model;
00094 }
00095 else
00096 {
00097
00098 }
00099 }
00100
00101
00102 offsets_.reset(new CalibrationOffsetParser());
00103 for (size_t i = 0; i < params.free_params.size(); ++i)
00104 {
00105 offsets_->add(params.free_params[i]);
00106 }
00107 for (size_t i = 0; i < params.free_frames.size(); ++i)
00108 {
00109 offsets_->addFrame(params.free_frames[i].name,
00110 params.free_frames[i].x,
00111 params.free_frames[i].y,
00112 params.free_frames[i].z,
00113 params.free_frames[i].roll,
00114 params.free_frames[i].pitch,
00115 params.free_frames[i].yaw);
00116 }
00117
00118
00119 double* free_params = new double[offsets_->size()];
00120 for (int i = 0; i < offsets_->size(); ++i)
00121 free_params[i] = 0.0;
00122
00123 double z_ = 0;
00124
00125 ceres::Problem* problem = new ceres::Problem();
00126
00127
00128 for (size_t i = 0; i < data.size(); ++i)
00129 {
00130 for (size_t j = 0; j < params.error_blocks.size(); ++j)
00131 {
00132 if (params.error_blocks[j].type == "camera3d_to_arm")
00133 {
00134
00135
00136
00137
00138
00139
00140 std::string camera_name = static_cast<std::string>(params.error_blocks[j].params["camera"]);
00141 std::string arm_name = static_cast<std::string>(params.error_blocks[j].params["arm"]);
00142
00143
00144 if (!hasSensor(data[i], camera_name) || !hasSensor(data[i], arm_name))
00145 continue;
00146
00147
00148 ceres::CostFunction * cost = Camera3dToArmError::Create(
00149 dynamic_cast<Camera3dModel*>(models_[camera_name]),
00150 models_[arm_name],
00151 offsets_.get(), data[i]);
00152
00153 int index = -1;
00154 for (size_t k = 0; k < data[i].observations.size(); k++)
00155 {
00156 if (data[i].observations[k].sensor_name == camera_name)
00157 {
00158 index = k;
00159 break;
00160 }
00161 }
00162
00163 if (index == -1)
00164 {
00165 std::cerr << "Sensor name doesn't exist" << std::endl;
00166 return 0;
00167 }
00168
00169 if (progress_to_stdout)
00170 {
00171 double ** params = new double*[1];
00172 params[0] = free_params;
00173 double * residuals = new double[data[i].observations[index].features.size() * 3];
00174
00175 cost->Evaluate(params, residuals, NULL);
00176 std::cout << "INITIAL COST (" << i << ")" << std::endl << " x: ";
00177 for (size_t k = 0; k < data[i].observations[index].features.size(); ++k)
00178 std::cout << " " << std::setw(10) << std::fixed << residuals[(3*k + 0)];
00179 std::cout << std::endl << " y: ";
00180 for (size_t k = 0; k < data[i].observations[index].features.size(); ++k)
00181 std::cout << " " << std::setw(10) << std::fixed << residuals[(3*k + 1)];
00182 std::cout << std::endl << " z: ";
00183 for (size_t k = 0; k < data[i].observations[index].features.size(); ++k)
00184 std::cout << " " << std::setw(10) << std::fixed << residuals[(3*k + 2)];
00185 std::cout << std::endl << std::endl;
00186 }
00187
00188 problem->AddResidualBlock(cost,
00189 NULL,
00190 free_params);
00191 }
00192 else if (params.error_blocks[j].type =="camera3d_to_ground")
00193 {
00194 std::string camera_name = static_cast<std::string>(params.error_blocks[j].params["camera"]);
00195 std::string ground_name = static_cast<std::string>(params.error_blocks[j].params["ground"]);
00196
00197
00198 if (!hasSensor(data[i], camera_name) || !hasSensor(data[i], ground_name))
00199 continue;
00200
00201
00202 ceres::CostFunction * cost = GroundPlaneError::Create(
00203 dynamic_cast<Camera3dModel*>(models_[camera_name]),
00204 z_,
00205 offsets_.get(), data[i]);
00206
00207 int index = -1;
00208 for (size_t k =0; k < data[i].observations.size(); k++)
00209 {
00210 if (data[i].observations[k].sensor_name == camera_name)
00211 {
00212 index = k;
00213 break;
00214 }
00215 }
00216
00217 if(index == -1)
00218 {
00219 std::cerr << "Sensor name doesn't exist" << std::endl;
00220 return 0;
00221 }
00222
00223 if (progress_to_stdout)
00224 {
00225 double ** params = new double*[1];
00226 params[0] = free_params;
00227 double * residuals = new double[data[i].observations[index].features.size()];
00228
00229 cost->Evaluate(params, residuals, NULL);
00230
00231 std::cout << std::endl << " z: ";
00232 for (size_t k = 0; k < data[i].observations[index].features.size(); ++k)
00233 std::cout << " " << std::setw(10) << std::fixed << residuals[(k)];
00234 std::cout << std::endl << std::endl;
00235 }
00236
00237 problem->AddResidualBlock(cost,
00238 NULL ,
00239 free_params);
00240 }
00241 else if (params.error_blocks[j].type == "outrageous")
00242 {
00243
00244 problem->AddResidualBlock(
00245 OutrageousError::Create(offsets_.get(),
00246 params.error_blocks[j].name,
00247 static_cast<double>(params.error_blocks[j].params["joint_scale"]),
00248 static_cast<double>(params.error_blocks[j].params["position_scale"]),
00249 static_cast<double>(params.error_blocks[j].params["rotation_scale"])),
00250 NULL,
00251 free_params);
00252 }
00253 else
00254 {
00255
00256 }
00257 }
00258 }
00259
00260
00261 ceres::Solver::Options options;
00262 options.use_nonmonotonic_steps = true;
00263 options.function_tolerance = 1e-10;
00264 options.linear_solver_type = ceres::DENSE_QR;
00265 options.max_num_iterations = 1000;
00266 options.minimizer_progress_to_stdout = progress_to_stdout;
00267
00268
00269 if (progress_to_stdout)
00270 std::cout << "\nSolver output:" << std::endl;
00271 summary_.reset(new ceres::Solver::Summary());
00272 ceres::Solve(options, problem, summary_.get());
00273 if (progress_to_stdout)
00274 std::cout << "\n" << summary_->BriefReport() << std::endl;
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293 delete[] free_params;
00294 delete problem;
00295
00296 return 0;
00297 }
00298
00299 }