calibration_job.cpp
Go to the documentation of this file.
00001 /*
00002  * Software License Agreement (Apache License)
00003  *
00004  * Copyright (c) 2013, Southwest Research Institute
00005  *
00006  * Licensed under the Apache License, Version 2.0 (the "License");
00007  * you may not use this file except in compliance with the License.
00008  * You may obtain a copy of the License at
00009  *
00010  *   http://www.apache.org/licenses/LICENSE-2.0
00011  *
00012  * Unless required by applicable law or agreed to in writing, software
00013  * distributed under the License is distributed on an "AS IS" BASIS,
00014  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00015  * See the License for the specific language governing permissions and
00016  * limitations under the License.
00017  */
00018 
00019 #include <ostream>
00020 #include <stdio.h>
00021 #include <fstream>
00022 #include <yaml-cpp/yaml.h>
00023 #include <boost/foreach.hpp>
00024 #include "ceres/ceres.h"
00025 #include "ceres/rotation.h"
00026 #include <industrial_extrinsic_cal/basic_types.h>
00027 #include <industrial_extrinsic_cal/calibration_job.hpp>
00028 #include <industrial_extrinsic_cal/camera_observer.hpp>
00029 #include <industrial_extrinsic_cal/ceres_costs_utils.hpp>
00030 
00031 // ROS includes
00032 #include <ros/ros.h>
00033 #include <camera_info_manager/camera_info_manager.h>
00034 
00035 namespace industrial_extrinsic_cal
00036 {
00037 
00038 using std::string;
00039 using boost::shared_ptr;
00040 using boost::make_shared;
00041 using ceres::CostFunction;
00042 Camera::Camera()
00043 {
00044   camera_name_ = "NONE";
00045   is_moving_ = false;
00046 }
00047 
00048 Camera::Camera(string name, CameraParameters camera_parameters, bool is_moving) :
00049     camera_name_(name), camera_parameters_(camera_parameters_), is_moving_(is_moving)
00050 {
00051 }
00052 
00053 Camera::~Camera()
00054 {
00055 }
00056 
00057 bool Camera::isMoving()
00058 {
00059   return (is_moving_);
00060 }
00061 
00062 void ObservationScene::addObservationToScene(ObservationCmd new_obs_cmd)
00063 {
00064   // this next block of code maintains a list of the cameras in a scene
00065   bool camera_already_in_scene = false;
00066   BOOST_FOREACH(ObservationCmd command, observation_command_list_)
00067   {
00068     BOOST_FOREACH(shared_ptr<Camera> camera, cameras_in_scene_)
00069     {
00070       if (camera->camera_name_ == new_obs_cmd.camera->camera_name_)
00071       {
00072         camera_already_in_scene = true;
00073       }
00074     }
00075   }
00076   if (!camera_already_in_scene)
00077   {
00078     cameras_in_scene_.push_back(new_obs_cmd.camera);
00079   }
00080   // end of code block to maintain list of cameras in scene
00081 
00082   // add observation
00083   observation_command_list_.push_back(new_obs_cmd);
00084 }
00085 CeresBlocks::CeresBlocks()
00086 {
00087 }
00088 CeresBlocks::~CeresBlocks()
00089 {
00090   clearCamerasTargets();
00091 }
00092 void CeresBlocks::clearCamerasTargets()
00093 {
00094   static_cameras_.clear();
00095   static_targets_.clear();
00096   moving_cameras_.clear();
00097   moving_targets_.clear();
00098 }
00099 P_BLOCK CeresBlocks::getStaticCameraParameterBlockIntrinsics(string camera_name)
00100 {
00101   // static cameras should have unique name
00102   BOOST_FOREACH(shared_ptr<Camera> camera, static_cameras_)
00103   {
00104     if (camera_name == camera->camera_name_)
00105     {
00106       P_BLOCK intrinsics = &(camera->camera_parameters_.pb_intrinsics[0]);
00107       return (intrinsics);
00108     }
00109   }
00110   return (NULL);
00111 }
00112 P_BLOCK CeresBlocks::getMovingCameraParameterBlockIntrinsics(string camera_name)
00113 {
00114   // we use the intrinsic parameters from the first time the camera appears in the list
00115   // subsequent cameras with this name also have intrinsic parameters, but these are
00116   // never used as parameter blocks, only their extrinsics are used
00117   BOOST_FOREACH(shared_ptr<MovingCamera> moving_camera, moving_cameras_)
00118   {
00119     if (camera_name == moving_camera->cam->camera_name_)
00120     {
00121       P_BLOCK intrinsics = &(moving_camera->cam->camera_parameters_.pb_intrinsics[0]);
00122       return (intrinsics);
00123     }
00124   }
00125   return (NULL);
00126 }
00127 P_BLOCK CeresBlocks::getStaticCameraParameterBlockExtrinsics(string camera_name)
00128 {
00129   // static cameras should have unique name
00130   BOOST_FOREACH(shared_ptr<Camera> camera, static_cameras_)
00131   {
00132     if (camera_name == camera->camera_name_)
00133     {
00134       P_BLOCK extrinsics = &(camera->camera_parameters_.pb_extrinsics[0]);
00135       return (extrinsics);
00136     }
00137   }
00138   return (NULL);
00139 
00140 }
00141 P_BLOCK CeresBlocks::getMovingCameraParameterBlockExtrinsics(string camera_name, int scene_id)
00142 {
00143   BOOST_FOREACH(shared_ptr<MovingCamera> camera, moving_cameras_)
00144   {
00145     if (camera_name == camera->cam->camera_name_ && scene_id == camera->scene_id)
00146     {
00147       P_BLOCK extrinsics = &(camera->cam->camera_parameters_.pb_extrinsics[0]);
00148       return (extrinsics);
00149     }
00150   }
00151   return (NULL);
00152 
00153 }
00154 P_BLOCK CeresBlocks::getStaticTargetPoseParameterBlock(string target_name)
00155 {
00156   BOOST_FOREACH(shared_ptr<Target> target, static_targets_)
00157   {
00158     if (target_name == target->target_name)
00159     {
00160       P_BLOCK pose = &(target->pose.pb_pose[0]);
00161       return (pose);
00162     }
00163   }
00164   return (NULL);
00165 }
00166 P_BLOCK CeresBlocks::getStaticTargetPointParameterBlock(string target_name, int point_id)
00167 {
00168   BOOST_FOREACH(shared_ptr<Target> target, static_targets_)
00169   {
00170     if (target_name == target->target_name)
00171     {
00172       P_BLOCK point_position = &(target->pts[point_id].pb[0]);
00173       return (point_position);
00174     }
00175   }
00176   return (NULL);
00177 }
00178 P_BLOCK CeresBlocks::getMovingTargetPoseParameterBlock(string target_name, int scene_id)
00179 {
00180   BOOST_FOREACH(shared_ptr<MovingTarget> moving_target, moving_targets_)
00181   {
00182     if (target_name == moving_target->targ->target_name && scene_id == moving_target->scene_id)
00183     {
00184       P_BLOCK pose = &(moving_target->targ->pose.pb_pose[0]);
00185       return (pose);
00186     }
00187   }
00188   return (NULL);
00189 }
00190 P_BLOCK CeresBlocks::getMovingTargetPointParameterBlock(string target_name, int pnt_id)
00191 {
00192   // note scene_id unnecessary here since regarless of scene th point's location relative to
00193   // the target frame does not change
00194   BOOST_FOREACH(shared_ptr<MovingTarget> moving_target, moving_targets_)
00195   {
00196     if (target_name == moving_target->targ->target_name)
00197     {
00198       P_BLOCK point_position = &(moving_target->targ->pts[pnt_id].pb[0]);
00199       return (point_position);
00200     }
00201   }
00202   return (NULL);
00203 }
00204 
00205 ObservationDataPointList::ObservationDataPointList()
00206 {
00207 }
00208 ;
00209 
00210 ObservationDataPointList::~ObservationDataPointList()
00211 {
00212 }
00213 ;
00214 
00215 void ObservationDataPointList::addObservationPoint(ObservationDataPoint new_data_point)
00216 {
00217   items.push_back(new_data_point);
00218 }
00219 
00220 bool CalibrationJob::run()
00221 {
00222   runObservations();
00223   runOptimization();
00224 }
00225 
00226 bool CalibrationJob::runObservations()
00227 {
00228   this->ceres_blocks_.clearCamerasTargets();
00229   // For each scene
00230   BOOST_FOREACH(ObservationScene current_scene, scene_list_)
00231   {
00232     int scene_id = current_scene.get_id();
00233 
00234     // clear all observations from every camera
00235     ROS_INFO_STREAM("Processing Scene " << scene_id);
00236 
00237     // add observations to every camera
00238     BOOST_FOREACH(shared_ptr<Camera> current_camera, current_scene.cameras_in_scene_)
00239     {
00240       current_camera->camera_observer_->clearObservations(); // clear any recorded data
00241       current_camera->camera_observer_->clearTargets(); // clear all targets
00242     }
00243 
00244     // add each target to each cameras observations
00245     BOOST_FOREACH(ObservationCmd o_command, current_scene.observation_command_list_)
00246     {
00247       // configure to find target in roi
00248       o_command.camera->camera_observer_->addTarget(o_command.target, o_command.roi);
00249     }
00250     // trigger the cameras
00251     BOOST_FOREACH( shared_ptr<Camera> current_camera, current_scene.cameras_in_scene_)
00252     {
00253       current_camera->camera_observer_->triggerCamera();
00254     }
00255     // collect results
00256     P_BLOCK intrinsics;
00257     P_BLOCK extrinsics;
00258     P_BLOCK target_pose;
00259     P_BLOCK pnt_pos;
00260     std::string camera_name;
00261     std::string target_name;
00262 
00263     // for each camera in scene
00264     BOOST_FOREACH( shared_ptr<Camera> camera, current_scene.cameras_in_scene_)
00265     {
00266       // wait until observation is done
00267       while (!camera->camera_observer_->observationsDone())
00268         ;
00269 
00270       camera_name = camera->camera_name_;
00271       if (camera->isMoving())
00272       {
00273         // next line does nothing if camera already exist in blocks
00274         ceres_blocks_.addMovingCamera(camera, scene_id);
00275         intrinsics = ceres_blocks_.getMovingCameraParameterBlockIntrinsics(camera_name);
00276         extrinsics = ceres_blocks_.getMovingCameraParameterBlockExtrinsics(camera_name, scene_id);
00277       }
00278       else
00279       {
00280         // next line does nothing if camera already exist in blocks
00281         ceres_blocks_.addStaticCamera(camera);
00282         intrinsics = ceres_blocks_.getStaticCameraParameterBlockIntrinsics(camera_name);
00283         extrinsics = ceres_blocks_.getStaticCameraParameterBlockExtrinsics(camera_name);
00284       }
00285 
00286       // Get the observations
00287       CameraObservations camera_observations;
00288       int number_returned;
00289       number_returned = camera->camera_observer_->getObservations(camera_observations);
00290 
00291       BOOST_FOREACH(Observation observation, camera_observations.observations)
00292       {
00293         target_name = observation.target->target_name;
00294         int pnt_id = observation.point_id;
00295         double observation_x = observation.image_loc_x;
00296         double observation_y = observation.image_loc_y;
00297         if (observation.target->is_moving)
00298         {
00299           ceres_blocks_.addMovingTarget(observation.target, scene_id);
00300           target_pose = ceres_blocks_.getMovingTargetPoseParameterBlock(target_name, scene_id);
00301           pnt_pos = ceres_blocks_.getMovingTargetPointParameterBlock(target_name, pnt_id);
00302         }
00303         else
00304         {
00305           ceres_blocks_.addStaticTarget(observation.target); // if exist, does nothing
00306           target_pose = ceres_blocks_.getStaticTargetPoseParameterBlock(target_name);
00307           pnt_pos = ceres_blocks_.getStaticTargetPointParameterBlock(target_name, pnt_id);
00308         }
00309         ObservationDataPoint temp_ODP(camera_name, target_name, scene_id, intrinsics, extrinsics, pnt_id, target_pose,
00310                                       pnt_pos, observation_x, observation_y);
00311         observation_data_point_list_.addObservationPoint(temp_ODP);
00312       }
00313     }
00314   } // end for each scene
00315 }
00316 
00317 bool CalibrationJob::load()
00318 {
00319   std::ifstream camera_input_file(camera_def_file_name_.c_str());
00320   std::ifstream target_input_file(target_def_file_name_.c_str());
00321   std::ifstream caljob_input_file(caljob_def_file_name_.c_str());
00322   if (camera_input_file.fail())
00323   {
00324     ROS_ERROR_STREAM(
00325         "ERROR CalibrationJob::load(), couldn't open camera_input_file:    "<< camera_def_file_name_.c_str());
00326     return (false);
00327   }
00328   if (target_input_file.fail())
00329   {
00330     ROS_ERROR_STREAM(
00331         "ERROR CalibrationJob::load(), couldn't open target_input_file:    "<< target_def_file_name_.c_str());
00332     return (false);
00333   }
00334   if (caljob_input_file.fail())
00335   {
00336     ROS_ERROR_STREAM(
00337         "ERROR CalibrationJob::load(), couldn't open caljob_input_file:    "<< caljob_def_file_name_.c_str());
00338     return (false);
00339   }
00340 
00341   string temp_name;
00342   CameraParameters temp_parameters;
00343   unsigned int scene_id;
00344   try
00345   {
00346     YAML::Parser camera_parser(camera_input_file);
00347     YAML::Node camera_doc;
00348     camera_parser.GetNextDocument(camera_doc);
00349 
00350     // read in all static cameras
00351     if (const YAML::Node *camera_parameters = camera_doc.FindValue("static_cameras"))
00352     {
00353       ROS_INFO_STREAM("Found "<<camera_parameters->size()<<" static cameras ");
00354       for (unsigned int i = 0; i < camera_parameters->size(); i++)
00355       {
00356         (*camera_parameters)[i]["camera_name"] >> temp_name;
00357         (*camera_parameters)[i]["angle_axis_ax"] >> temp_parameters.angle_axis[0];
00358         (*camera_parameters)[i]["angle_axis_ay"] >> temp_parameters.angle_axis[1];
00359         (*camera_parameters)[i]["angle_axis_az"] >> temp_parameters.angle_axis[2];
00360         (*camera_parameters)[i]["position_x"] >> temp_parameters.position[0];
00361         (*camera_parameters)[i]["position_y"] >> temp_parameters.position[1];
00362         (*camera_parameters)[i]["position_z"] >> temp_parameters.position[2];
00363         (*camera_parameters)[i]["focal_length_x"] >> temp_parameters.focal_length_x;
00364         (*camera_parameters)[i]["focal_length_y"] >> temp_parameters.focal_length_y;
00365         (*camera_parameters)[i]["center_x"] >> temp_parameters.center_x;
00366         (*camera_parameters)[i]["center_y"] >> temp_parameters.center_y;
00367         (*camera_parameters)[i]["distortion_k1"] >> temp_parameters.distortion_k1;
00368         (*camera_parameters)[i]["distortion_k2"] >> temp_parameters.distortion_k2;
00369         (*camera_parameters)[i]["distortion_k3"] >> temp_parameters.distortion_k3;
00370         (*camera_parameters)[i]["distortion_p1"] >> temp_parameters.distortion_p1;
00371         (*camera_parameters)[i]["distortion_p2"] >> temp_parameters.distortion_p2;
00372         // create a static camera
00373         shared_ptr<Camera> temp_camera = make_shared<Camera>(temp_name, temp_parameters, false);
00374 
00375         ceres_blocks_.addStaticCamera(temp_camera);
00376       }
00377     }
00378 
00379     // read in all moving cameras
00380     if (const YAML::Node *camera_parameters = camera_doc.FindValue("moving_cameras"))
00381     {
00382       ROS_INFO_STREAM("Found "<<camera_parameters->size() << " moving cameras ");
00383       for (unsigned int i = 0; i < camera_parameters->size(); i++)
00384       {
00385         (*camera_parameters)[i]["camera_name"] >> temp_name;
00386         (*camera_parameters)[i]["angle_axis_ax"] >> temp_parameters.angle_axis[0];
00387         (*camera_parameters)[i]["angle_axis_ay"] >> temp_parameters.angle_axis[1];
00388         (*camera_parameters)[i]["angle_axis_az"] >> temp_parameters.angle_axis[2];
00389         (*camera_parameters)[i]["position_x"] >> temp_parameters.position[0];
00390         (*camera_parameters)[i]["position_y"] >> temp_parameters.position[1];
00391         (*camera_parameters)[i]["position_z"] >> temp_parameters.position[2];
00392         (*camera_parameters)[i]["focal_length_x"] >> temp_parameters.focal_length_x;
00393         (*camera_parameters)[i]["focal_length_y"] >> temp_parameters.focal_length_y;
00394         (*camera_parameters)[i]["center_x"] >> temp_parameters.center_x;
00395         (*camera_parameters)[i]["center_y"] >> temp_parameters.center_y;
00396         (*camera_parameters)[i]["distortion_k1"] >> temp_parameters.distortion_k1;
00397         (*camera_parameters)[i]["distortion_k2"] >> temp_parameters.distortion_k2;
00398         (*camera_parameters)[i]["distortion_k3"] >> temp_parameters.distortion_k3;
00399         (*camera_parameters)[i]["distortion_p1"] >> temp_parameters.distortion_p1;
00400         (*camera_parameters)[i]["distortion_p2"] >> temp_parameters.distortion_p2;
00401         (*camera_parameters)[i]["scene_id"] >> scene_id;
00402         shared_ptr<Camera> temp_camera = make_shared<Camera>(temp_name, temp_parameters, true);
00403         ceres_blocks_.addMovingCamera(temp_camera, scene_id);
00404       }
00405     }
00406   } // end try
00407   catch (YAML::ParserException& e)
00408   {
00409     ROS_INFO_STREAM("load() Failed to read in moving cameras from  yaml file ");
00410     ROS_INFO_STREAM("camera name =     "<<temp_name.c_str());
00411     ROS_INFO_STREAM("angle_axis_ax =  "<<temp_parameters.angle_axis[0]);
00412     ROS_INFO_STREAM("angle_axis_ay = "<<temp_parameters.angle_axis[1]);
00413     ROS_INFO_STREAM("angle_axis_az =  "<<temp_parameters.angle_axis[2]);
00414     ROS_INFO_STREAM("position_x =  "<<temp_parameters.position[0]);
00415     ROS_INFO_STREAM("position_y =  "<<temp_parameters.position[1]);
00416     ROS_INFO_STREAM("position_z =  "<<temp_parameters.position[2]);
00417     ROS_INFO_STREAM("focal_length_x =  "<<temp_parameters.focal_length_x);
00418     ROS_INFO_STREAM("focal_length_y =  "<<temp_parameters.focal_length_y);
00419     ROS_INFO_STREAM("center_x = "<<temp_parameters.center_x);
00420     ROS_INFO_STREAM("center_y =  "<<temp_parameters.center_y);
00421     ROS_INFO_STREAM("distortion_k1 =  "<<temp_parameters.distortion_k1);
00422     ROS_INFO_STREAM("distortion_k2 =  "<<temp_parameters.distortion_k2);
00423     ROS_INFO_STREAM("distortion_k3 =  "<<temp_parameters.distortion_k3);
00424     ROS_INFO_STREAM("distortion_p1 =  "<<temp_parameters.distortion_p1);
00425     ROS_INFO_STREAM("distortion_p2 =  "<<temp_parameters.distortion_p2);
00426     ROS_INFO_STREAM("scene_id = "<<scene_id);
00427     ROS_ERROR("load() Failed to read in cameras yaml file");
00428     ROS_ERROR_STREAM("Failed with exception "<< e.what());
00429     return (false);
00430   }
00431   ROS_INFO_STREAM("Successfully read in cameras ");
00432 
00433   Target temp_target;
00434   try
00435   {
00436     YAML::Parser target_parser(target_input_file);
00437     YAML::Node target_doc;
00438     target_parser.GetNextDocument(target_doc);
00439 
00440     // read in all static targets
00441     if (const YAML::Node *target_parameters = target_doc.FindValue("static_targets"))
00442     {
00443       ROS_INFO_STREAM("Found "<<target_parameters->size() <<" targets ");
00444       shared_ptr<Target> temp_target = make_shared<Target>();
00445       temp_target->is_moving = false;
00446       for (unsigned int i = 0; i < target_parameters->size(); i++)
00447       {
00448         (*target_parameters)[i]["target_name"] >> temp_target->target_name;
00449         (*target_parameters)[i]["angle_axis_ax"] >> temp_target->pose.ax;
00450         (*target_parameters)[i]["angle_axis_ay"] >> temp_target->pose.ay;
00451         (*target_parameters)[i]["angle_axis_az"] >> temp_target->pose.az;
00452         (*target_parameters)[i]["position_x"] >> temp_target->pose.x;
00453         (*target_parameters)[i]["position_y"] >> temp_target->pose.y;
00454         (*target_parameters)[i]["position_z"] >> temp_target->pose.z;
00455         (*target_parameters)[i]["num_points"] >> temp_target->num_points;
00456         const YAML::Node *points_node = (*target_parameters)[i].FindValue("points");
00457         for (int j = 0; j < points_node->size(); j++)
00458         {
00459           const YAML::Node *pnt_node = (*points_node)[j].FindValue("pnt");
00460           std::vector<float> temp_pnt;
00461           (*pnt_node) >> temp_pnt;
00462           Point3d temp_pnt3d;
00463           temp_pnt3d.x = temp_pnt[0];
00464           temp_pnt3d.y = temp_pnt[1];
00465           temp_pnt3d.z = temp_pnt[2];
00466           temp_target->pts.push_back(temp_pnt3d);
00467         }
00468         ceres_blocks_.addStaticTarget(temp_target);
00469       }
00470     }
00471 
00472     // read in all moving targets
00473     if (const YAML::Node *target_parameters = target_doc.FindValue("moving_targets"))
00474     {
00475       ROS_INFO_STREAM("Found "<<target_parameters->size() <<"  moving targets ");
00476       shared_ptr<Target> temp_target = make_shared<Target>();
00477       unsigned int scene_id;
00478       temp_target->is_moving = true;
00479       for (unsigned int i = 0; i < target_parameters->size(); i++)
00480       {
00481         (*target_parameters)[i]["target_name"] >> temp_target->target_name;
00482         (*target_parameters)[i]["angle_axis_ax"] >> temp_target->pose.ax;
00483         (*target_parameters)[i]["angle_axis_ax"] >> temp_target->pose.ay;
00484         (*target_parameters)[i]["angle_axis_ay"] >> temp_target->pose.az;
00485         (*target_parameters)[i]["position_x"] >> temp_target->pose.x;
00486         (*target_parameters)[i]["position_y"] >> temp_target->pose.y;
00487         (*target_parameters)[i]["position_z"] >> temp_target->pose.z;
00488         (*target_parameters)[i]["scene_id"] >> scene_id;
00489         (*target_parameters)[i]["num_points"] >> temp_target->num_points;
00490         const YAML::Node *points_node = (*target_parameters)[i].FindValue("points");
00491         for (int j = 0; j < points_node->size(); j++)
00492         {
00493           const YAML::Node *pnt_node = (*points_node)[j].FindValue("pnt");
00494           std::vector<float> temp_pnt;
00495           (*pnt_node) >> temp_pnt;
00496           Point3d temp_pnt3d;
00497           temp_pnt3d.x = temp_pnt[0];
00498           temp_pnt3d.y = temp_pnt[1];
00499           temp_pnt3d.z = temp_pnt[2];
00500           temp_target->pts.push_back(temp_pnt3d);
00501         }
00502         ceres_blocks_.addMovingTarget(temp_target, scene_id);
00503       }
00504     }
00505     ROS_INFO_STREAM("Successfully read targets ");
00506   } // end try
00507   catch (YAML::ParserException& e)
00508   {
00509     ROS_ERROR("load() Failed to read in target yaml file");
00510     ROS_ERROR_STREAM("Failed with exception "<< e.what());
00511     return (false);
00512   }
00513   //    ROS_ERROR("load() Failed to read in cameras yaml file");
00514   //Target temp_target;
00515   //Read in cal job parameters
00516   try
00517   {
00518     YAML::Parser caljob_parser(caljob_input_file);
00519     YAML::Node caljob_doc;
00520     caljob_parser.GetNextDocument(caljob_doc);
00521 
00522     shared_ptr<Target> temp_target = make_shared<Target>();
00523 
00524     caljob_doc["reference_frame"] >> temp_target->target_name;
00525     caljob_doc["optimization_parameters"] >> temp_target->target_name;
00526     // read in all scenes
00527     if (const YAML::Node *caljob_scenes = caljob_doc.FindValue("scenes"))
00528     {
00529       ROS_INFO_STREAM("Found "<<caljob_scenes->size() <<" scenes");
00530       for (unsigned int i = 0; i < caljob_scenes->size(); i++)
00531       {
00532         (*caljob_scenes)[i]["scene_id"] >> temp_target->target_name;
00533         //ROS_INFO_STREAM("scene "<<temp_target->target_name);
00534         (*caljob_scenes)[i]["trigger_type"] >> temp_target->target_name;
00535         //ROS_INFO_STREAM("trig type "<<temp_target->target_name);
00536         const YAML::Node *obs_node = (*caljob_scenes)[i].FindValue("observations");
00537         ROS_INFO_STREAM("Found "<<obs_node->size() <<" observations within scene "<<i);
00538         for (unsigned int j = 0; j < obs_node->size(); j++)
00539         {
00540           ROS_INFO_STREAM("For obs "<<j);
00541           (*obs_node)[j]["camera"] >> temp_target->target_name;
00542           (*obs_node)[j]["target"] >> temp_target->target_name;
00543         }
00544       }
00545     }
00546     ROS_INFO_STREAM("Successfully read caljob  ");
00547   } // end try
00548   catch (YAML::ParserException& e)
00549   {
00550     ROS_ERROR("load() Failed to read in caljob yaml file");
00551     ROS_ERROR_STREAM("Failed with exception "<< e.what());
00552     return (false);
00553   }
00554   //    ROS_INFO("successfuly read in cameras");
00555   return (true);
00556 } // end load()
00557 
00558 bool CeresBlocks::addStaticCamera(shared_ptr<Camera> camera_to_add)
00559 {
00560   BOOST_FOREACH(shared_ptr<Camera> cam, static_cameras_)
00561   {
00562     if (cam->camera_name_ == camera_to_add->camera_name_)
00563       return (false); // camera already exists
00564   }
00565   static_cameras_.push_back(camera_to_add);
00566   return (true);
00567 }
00568 bool CeresBlocks::addStaticTarget(shared_ptr<Target> target_to_add)
00569 {
00570   BOOST_FOREACH(shared_ptr<Target> targ, static_targets_)
00571   {
00572     if (targ->target_name == target_to_add->target_name)
00573       return (false); // target already exists
00574   }
00575   static_targets_.push_back(target_to_add);
00576   return (true);
00577 }
00578 bool CeresBlocks::addMovingCamera(shared_ptr<Camera> camera_to_add, int scene_id)
00579 {
00580   BOOST_FOREACH(shared_ptr<MovingCamera> cam, moving_cameras_)
00581   {
00582     if (cam->cam->camera_name_ == camera_to_add->camera_name_ && cam->scene_id == scene_id)
00583       return (false); // camera already exists
00584   }
00585   // this next line allocates the memory for a moving camera
00586   shared_ptr<MovingCamera> temp_moving_camera = make_shared<MovingCamera>();
00587   // this next line allocates the memory for the actual camera
00588   shared_ptr<Camera> temp_camera = make_shared<Camera>(camera_to_add->camera_name_, camera_to_add->camera_parameters_,
00589                                                        true);
00590   temp_moving_camera->cam = temp_camera;
00591   temp_moving_camera->scene_id = scene_id;
00592   moving_cameras_.push_back(temp_moving_camera);
00593   return (true);
00594 }
00595 bool CeresBlocks::addMovingTarget(shared_ptr<Target> target_to_add, int scene_id)
00596 {
00597   BOOST_FOREACH(shared_ptr<MovingTarget> targ, moving_targets_)
00598   {
00599     if (targ->targ->target_name == target_to_add->target_name && targ->scene_id == scene_id)
00600       return (false); // target already exists
00601   }
00602   shared_ptr<MovingTarget> temp_moving_target = make_shared<MovingTarget>();
00603   shared_ptr<Target> temp_camera = make_shared<Target>();
00604   temp_moving_target->targ = target_to_add;
00605   temp_moving_target->scene_id = scene_id;
00606   moving_targets_.push_back(temp_moving_target);
00607   return (true);
00608 }
00609 
00610 bool CalibrationJob::runOptimization()
00611 {
00612   // take all the data collected and create a Ceres optimization problem and run it
00613 
00614   BOOST_FOREACH(ObservationDataPoint ODP, observation_data_point_list_.items)
00615   {
00616     // take all the data collected and create a Ceres optimization problem and run it
00617 
00618     BOOST_FOREACH(ObservationDataPoint ODP, observation_data_point_list_.items){
00619       // create cost function
00620       // there are several options
00621       // 1. the complete reprojection error cost function "Create(obs_x,obs_y)"
00622       //    this cost function has the following parameters:
00623       //      a. camera intrinsics
00624       //      b. camera extrinsics
00625       //      c. target pose
00626       //      d. point location in target frame
00627       // 2. the same as 1, but without d  "Create(obs_x,obs_y,t_pnt_x, t_pnt_y, t_pnt_z)
00628       // 3. the same as 1, but without a  "Create(obs_x,obs_y,fx,fy,cx,cy,cz)"
00629       //    Note that this one assumes we are using rectified images to compute the observations
00630       // 4. the same as 3, point location fixed too "Create(obs_x,obs_y,fx,fy,cx,cy,cz,t_x,t_y,t_z)"
00631       // 5. the same as 4, but with target in known location
00632       //    "Create(obs_x,obs_y,fx,fy,cx,cy,cz,t_x,t_y,t_z,p_tx,p_ty,p_tz,p_ax,p_ay,p_az)"
00633 
00634       // pull out the constants from the observation point data
00635       double focal_length_x = ODP.camera_intrinsics_[0]; // TODO, make this not so ugly
00636       double focal_length_y = ODP.camera_intrinsics_[1];
00637       double center_pnt_x   = ODP.camera_intrinsics_[2];
00638       double center_pnt_y   = ODP.camera_intrinsics_[3];
00639       double image_x        = ODP.image_x_;
00640       double image_y        = ODP.image_y_;
00641       double point_x        = ODP.point_position_[0];// location of point within target frame
00642       double point_y        = ODP.point_position_[1];
00643       double point_z        = ODP.point_position_[2];
00644       
00645       // create the cost function
00646       CostFunction* cost_function = TargetCameraReprjErrorNoDistortion::Create(image_x, image_y,
00647                                                                                focal_length_x, 
00648                                                                                focal_length_y,
00649                                                                                center_pnt_x,
00650                                                                                center_pnt_y,
00651                                                                                point_x,
00652                                                                                point_y,
00653                                                                                point_z);
00654 
00655       // pull out pointers to the parameter blocks in the observation point data
00656       P_BLOCK extrinsics    = ODP.camera_extrinsics_;
00657       P_BLOCK target_pose   = ODP.target_pose_;
00658 
00659       // add it as a residual using parameter blocks
00660       problem_.AddResidualBlock(cost_function, NULL , extrinsics, target_pose);
00661 
00662     }
00663 
00664     //    ceres::CostFunction* cost_function =  Camera_reprj_error::Create(Ob[i].x,Ob[i].y);
00665 
00666     //    problem_.AddResidualBlock(cost_function, NULL ,
00667     //    C.PB_extrinsics,
00668     //    C.PB_intrinsics,
00669     //    Pts[i].PB);
00670     //    problem.SetParameterBlockConstant(C.PB_intrinsics);
00671     //    problem.SetParameterBlockConstant(Pts[i].PB);
00672 
00673 
00674     // Make Ceres automatically detect the bundle structure. Note that the
00675     // standard solver, SPARSE_NORMAL_CHOLESKY, also works fine but it is slower
00676     // for standard bundle adjustment problems.
00677     ceres::Solver::Options options;
00678     options.linear_solver_type = ceres::DENSE_SCHUR;
00679     options.minimizer_progress_to_stdout = true;
00680     options.max_num_iterations = 1000;
00681 
00682     ceres::Solver::Summary summary;
00683     //    ceres::Solve(options, &problem, &summary);
00684 
00685 
00686     return true;
00687   }
00688   return true;
00689 }
00690 } // end of namespace
00691 
00692 using industrial_extrinsic_cal::CalibrationJob;
00693 using std::string;
00694 int main()
00695 {
00696   string camera_file_name("camera_def.yaml");
00697   string target_file_name("target_def.yaml");
00698   string caljob_file_name("caljob_def.yaml");
00699   CalibrationJob Cal_job(camera_file_name, target_file_name, caljob_file_name);
00700   printf("hello world\n");
00701   Cal_job.load();
00702 }


industrial_extrinsic_cal
Author(s): Chris Lewis
autogenerated on Wed Aug 26 2015 12:00:27