calib_3d_cbs.cpp
Go to the documentation of this file.
00001 #include "ros/param.h"
00002 #include "arm_3d_cb_calib/calib_3d_cbs.h"
00003 
00004 using namespace std;
00005 using namespace gtsam;
00006 
00007 namespace arm_3d_cb_calib {
00008 
00009 void randomPoses(int num_poses, vector<Pose3>& poses, double radius=1.0)
00010 {
00011   boost::mt19937 rng;
00012   boost::uniform_real<> pt_range(-radius, radius);
00013   boost::uniform_real<> angle_range(0, M_PI);
00014   for(int i=0;i<num_poses;i++) {
00015     poses.push_back(Pose3(Rot3::ypr(angle_range(rng),angle_range(rng),angle_range(rng)),
00016                           Point3(pt_range(rng),pt_range(rng),pt_range(rng))));
00017   }
00018 }
00019 
00021 
00022 void generateCBCalibProblem(CBCalibProblem& prob, CBCalibSolution& sol, int num_ees)
00023 {
00024   size_t num_kinects = prob.kinect_p_points.size();
00025   size_t num_cb_points = prob.cb_p_points.size();
00026   randomPoses(num_kinects, sol.kinect_T_base_poses, 10);
00027   vector<Pose3> offset_pose_;
00028   randomPoses(1, offset_pose_, 0.4);
00029   sol.cb_T_ee_pose = offset_pose_[0];
00030   randomPoses(num_ees, prob.base_T_ee_poses, 1.5);
00031 
00032   for(size_t j=0;j<num_kinects;j++)
00033     for(size_t i=0;i<num_ees;i++) {
00034       prob.kinect_p_points[j].push_back(vector<Point3>());
00035       cout << (sol.kinect_T_base_poses[j] * prob.base_T_ee_poses[i] * 
00036             sol.cb_T_ee_pose.inverse()).inverse().matrix() << endl;
00037       for(size_t l=0;l<num_cb_points;l++)
00038         prob.kinect_p_points[j][i].push_back(
00039             sol.kinect_T_base_poses[j] * prob.base_T_ee_poses[i] * 
00040             sol.cb_T_ee_pose.inverse() * prob.cb_p_points[l]);
00041     }
00042 }
00043 
00044 class CheckerboardArmFactor : public NoiseModelFactor2<Pose3, Pose3>
00045 {
00046   public:
00047     Point3 cb_p_point, kinect_p_point;
00048     Pose3 base_T_ee;
00049     CheckerboardArmFactor(const gtsam::SharedNoiseModel& noiseModel, 
00050                           Key j1, Key j2, Point3 _cb_p_point, Point3 _kinect_p_point, 
00051                           Pose3 _base_T_ee) :
00052       NoiseModelFactor2<Pose3, Pose3>(noiseModel, j1, j2), 
00053         cb_p_point(_cb_p_point), kinect_p_point(_kinect_p_point), base_T_ee(_base_T_ee) {}
00054 
00055     gtsam::Vector evaluateError(const gtsam::Pose3& cb_T_ee,
00056                                 const gtsam::Pose3& kinect_T_base,
00057                                 boost::optional<Matrix&> H_1 = boost::none,
00058                                 boost::optional<Matrix&> H_2 = boost::none) const
00059     {
00060       if(H_1) {
00061         (*H_1) = gtsam::Matrix_(3, 6);
00062         Point3 pt = cb_T_ee.inverse() * cb_p_point;
00063         Matrix cross = Matrix_(3,3,
00064                                0.0,-pt.z(),pt.y(),
00065                                pt.z(),0.0,-pt.x(),
00066                                -pt.y(),pt.x(),0.0);
00067         (*H_1).block<3,3>(0,0) = base_T_ee.rotation().matrix() * cross;
00068         (*H_1).block<3,3>(0,3) = -base_T_ee.rotation().matrix();
00069       }
00070       if(H_2) {
00071         (*H_2) = gtsam::Matrix_(3, 6);
00072         Point3 pt = kinect_T_base.inverse() * kinect_p_point;
00073         Matrix cross = Matrix_(3,3,
00074                                0.0,-pt.z(),pt.y(),
00075                                pt.z(),0.0,-pt.x(),
00076                                -pt.y(),pt.x(),0.0);
00077         (*H_2).block<3,3>(0,0) = -cross;
00078         (*H_2).block<3,3>(0,3) = gtsam::Rot3::yaw(0).matrix();
00079       }
00080       return (base_T_ee * cb_T_ee.inverse() * cb_p_point - 
00081               kinect_T_base.inverse() * kinect_p_point).vector();
00082     }
00083 };
00084 
00085 class PointTransFactor : public NoiseModelFactor1<Pose3>
00086 {
00087   public:
00088     Point3 cb_p_point, kinect_p_point;
00089     PointTransFactor(const gtsam::SharedNoiseModel& noiseModel, 
00090                           Key j1, Point3 _cb_p_point, Point3 _kinect_p_point) :
00091       NoiseModelFactor1<Pose3>(noiseModel, j1), 
00092         cb_p_point(_cb_p_point), kinect_p_point(_kinect_p_point) {}
00093 
00094     gtsam::Vector evaluateError(const gtsam::Pose3& cb_T_kinect,
00095                                 boost::optional<Matrix&> H_1 = boost::none) const
00096     {
00097       if(H_1) {
00098         (*H_1) = gtsam::Matrix_(3, 6);
00099         Point3 pt = cb_T_kinect.inverse() * cb_p_point;
00100         Matrix cross = Matrix_(3,3,
00101                                0.0,-pt.z(),pt.y(),
00102                                pt.z(),0.0,-pt.x(),
00103                                -pt.y(),pt.x(),0.0);
00104         (*H_1).block<3,3>(0,0) = cross;
00105         (*H_1).block<3,3>(0,3) = -eye(3);
00106       }
00107       return (cb_T_kinect.inverse() * cb_p_point - kinect_p_point).vector();
00108     }
00109 };
00110 
00111 class MultiPoseFactor : public NoiseModelFactor3<Pose3, Pose3, Pose3>
00112 {
00113   public:
00114     Pose3 base_T_ee;
00115     MultiPoseFactor(const gtsam::SharedNoiseModel& noiseModel, 
00116                           Key j1, Key j2, Key j3, Pose3 _base_T_ee) :
00117       NoiseModelFactor3<Pose3, Pose3, Pose3>(noiseModel, j1, j2, j3), 
00118         base_T_ee(_base_T_ee) {}
00119 
00120     gtsam::Vector evaluateError(const gtsam::Pose3& ee_T_cb,
00121                                 const gtsam::Pose3& kinect_T_base,
00122                                 const gtsam::Pose3& cb_T_kinect,
00123                                 boost::optional<Matrix&> H_1 = boost::none,
00124                                 boost::optional<Matrix&> H_2 = boost::none,
00125                                 boost::optional<Matrix&> H_3 = boost::none) const
00126     {
00127       if(H_1) {
00128         (*H_1) = (cb_T_kinect * kinect_T_base * base_T_ee * ee_T_cb).adjointMap();
00129       }
00130       if(H_2) {
00131         (*H_2) = (cb_T_kinect * kinect_T_base).adjointMap();
00132       }
00133       if(H_3) {
00134         (*H_3) = cb_T_kinect.adjointMap();
00135       }
00136       return Pose3::Logmap(cb_T_kinect * kinect_T_base * base_T_ee * ee_T_cb);
00137     }
00138 };
00139 
00140 void solveCBCalibProblem(const CBCalibProblem& prob, CBCalibSolution& sol)
00141 {
00142   size_t num_kinects = prob.kinect_p_points.size();
00143   size_t num_cb_points = prob.cb_p_points.size();
00144   // noise terms
00145   double pt_noise, pose_noise;
00146   ros::param::param<double>("~pt_noise", pt_noise, 0.02);
00147   ros::param::param<double>("~pose_noise", pose_noise, 0.02);
00148   noiseModel::Isotropic::shared_ptr pt_fact_noise = noiseModel::Isotropic::Sigma(3, pt_noise);
00149   noiseModel::Isotropic::shared_ptr mp_fact_noise = noiseModel::Isotropic::Sigma(6, pose_noise);
00150   //noiseModel::MEstimator::Base::shared_ptr robust_model = noiseModel::MEstimator::Fair::Create(3.0);
00151   //noiseModel::Robust::shared_ptr robust_ee_fact_noise = noiseModel::Robust::Create(robust_model, ee_fact_noise);
00152 
00153   gtsam::NonlinearFactorGraph graph;
00154   Values init_estimate;
00155 
00156   bool init;
00157   double init_x, init_y, init_z, init_qx, init_qy, init_qz, init_qw;
00158   ros::param::param<bool>("~init", init, 0);
00159   ros::param::param<double>("~init_x", init_x, 0.0);
00160   ros::param::param<double>("~init_y", init_y, 0.0);
00161   ros::param::param<double>("~init_z", init_z, 0.0);
00162   ros::param::param<double>("~init_qx", init_qx, 0.0);
00163   ros::param::param<double>("~init_qy", init_qy, 0.0);
00164   ros::param::param<double>("~init_qz", init_qz, 0.0);
00165   ros::param::param<double>("~init_qw", init_qw, 1.0);
00166   int cb_ind = 0;
00167   Pose3 init_offset = Pose3(Quaternion(init_qw,init_qx,init_qy,init_qz),
00168                                       Point3(init_x,init_y,init_z));
00169   init_estimate.insert(Symbol('o',0), init_offset.inverse());
00170   if(init) {
00171     graph.add(boost::make_shared<PriorFactor<Pose3> >(
00172           Symbol('o',0), init_offset, mp_fact_noise));
00173     printf("*****************************************************\n%f %f %f %f %f %f %f\n", init_x, init_y, init_z, init_qx, init_qy, init_qz, init_qw);
00174   }
00175   for(size_t j=0;j<num_kinects;j++) {
00176     init_estimate.insert(Symbol('k',j), Pose3());
00177     for(size_t i=0;i<prob.kinect_p_points[j].size();i++) {
00178       init_estimate.insert(Symbol('c',cb_ind), Pose3());
00179 
00180       graph.add(boost::make_shared<MultiPoseFactor>(
00181             mp_fact_noise, 
00182             Symbol('o',0), Symbol('k',j), Symbol('c',cb_ind), 
00183             prob.base_T_ee_poses[i]));
00184 
00185       for(size_t l=0;l<num_cb_points;l++) {
00186         Point3 kinect_p = prob.kinect_p_points[j][i][l];
00187         if(kinect_p.x() != kinect_p.x())
00188           continue;
00189         graph.add(boost::make_shared<PointTransFactor>(
00190               pt_fact_noise, 
00191               Symbol('c',cb_ind), 
00192               prob.cb_p_points[l], kinect_p));
00193       }
00194       cb_ind++;
00195     }
00196   }
00197   Values result = DoglegOptimizer(graph, init_estimate).optimize();
00198   result.print();
00199   printf("start error: %f\n", graph.error(init_estimate));
00200   printf("end error: %f\n", graph.error(result));
00201   sol.cb_T_ee_pose = result.at<Pose3>(Symbol('o',0)).inverse();
00202   for(size_t j=0;j<num_kinects;j++) 
00203     sol.kinect_T_base_poses.push_back(result.at<Pose3>(Symbol('k',j)));
00204 }
00205 
00207 
00208 geometry_msgs::Pose gtsamPose3ToGeomPose(const gtsam::Pose3& pose_in)
00209 {
00210   geometry_msgs::Pose pose_out;
00211   pose_out.position.x = pose_in.x();
00212   pose_out.position.y = pose_in.y();
00213   pose_out.position.z = pose_in.z();
00214   Quaternion q = pose_in.rotation().toQuaternion();
00215   pose_out.orientation.w = q.w();
00216   pose_out.orientation.x = q.x();
00217   pose_out.orientation.y = q.y();
00218   pose_out.orientation.z = q.z();
00219   return pose_out;
00220 }
00221 
00222 gtsam::Pose3 geomPoseToGtsamPose3(const geometry_msgs::Pose& pose_in)
00223 {
00224   return gtsam::Pose3(Rot3(Quaternion(pose_in.orientation.w, pose_in.orientation.x, 
00225                                       pose_in.orientation.y, pose_in.orientation.z)), 
00226                       Point3(pose_in.position.x, pose_in.position.y, pose_in.position.z));
00227 }
00228 
00229 }


arm_3d_cb_calib
Author(s): Kelsey
autogenerated on Wed Nov 27 2013 12:04:05