generic_model.cpp
Go to the documentation of this file.
00001 /*
00002  * generic_model.cpp
00003  *
00004  *  Created on: Oct 19, 2009
00005  *      Author: sturm
00006  */
00007 #include <boost/format.hpp>
00008 #include "articulation_models/models/generic_model.h"
00009 
00010 #include "articulation_models/utils.h"
00011 #include "articulation_models/models/factory.h"
00012 #include <gsl/gsl_multimin.h>
00013 #include <gsl/gsl_blas.h>
00014 
00015 using namespace std;
00016 using namespace boost;
00017 
00018 using namespace Eigen;
00019 
00020 using namespace articulation_msgs;
00021 
00022 #include <iomanip>
00023 #define VEC(a) setprecision(5)<<fixed<<a.x()<<" "<<a.y()<<" "<<a.z()<<" "<<a.w()<<" l="<<a.length()
00024 #define VEC2(a) "t=["<<VEC(a.getOrigin())<<"] r=[]"<<VEC(a.getRotation())<<"]"
00025 #define PRINT(a) cout << #a <<"=" << VEC(a)<<endl;
00026 #define PRINT2(a) cout << #a <<"=" << VEC2(a)<<endl;
00027 
00028 namespace articulation_models {
00029 
00030 GenericModel::GenericModel() {
00031         setId(-1);
00032         sigma_position = 0.005;
00033         sigma_orientation = 360 * M_PI/180.0;
00034 
00035         avg_error_position = 0;
00036         avg_error_orientation = 0;
00037         bic = 0;
00038 
00039         last_error_jacobian = 0;
00040         evaluated = false;
00041         supress_similar = true;
00042         outlier_ratio = 0.5;
00043         sac_iterations = 100;
00044         optimizer_iterations = 10;
00045 //      optimizer_iterations = 0;
00046 
00047         prior_outlier_ratio = log(0.01) / (- 0.05); // prior over outlier ratio
00048 
00049         complexity = 0;
00050         jacobian = Eigen::MatrixXd();
00051         hessian = Eigen::MatrixXd();
00052 }
00053 
00054 void GenericModel::setModel(const ModelMsg& model) {
00055         this->model = model;
00056         readParamsFromModel();
00057         prepareChannels();
00058 }
00059 
00060 ModelMsg GenericModel::getModel() {
00061     writeParamsToModel();
00062         model.name = getModelName();
00063         model.header = model.track.header;
00064         model.track.pose_flags.resize(model.track.pose.size(),TrackMsg::POSE_VISIBLE );
00065         if(model.track.pose.size())
00066                 model.track.pose_flags[model.track.pose.size()-1] |= TrackMsg::POSE_END_OF_SEGMENT;
00067         return model;
00068 }
00069 
00070 void GenericModel::setTrack(const TrackMsg& track) {
00071         this->model.track = track;
00072         prepareChannels();
00073 }
00074 
00075 TrackMsg GenericModel::getTrack() {
00076         return model.track;
00077 }
00078 
00079 void GenericModel::setId(int id) {
00080         model.id = id;
00081 }
00082 
00083 int GenericModel::getId() {
00084         return(model.id);
00085 }
00086 
00087 // -- model information
00088 std::string GenericModel::getModelName() {
00089         return MultiModelFactory::instance.getLongName(this);
00090 }
00091 
00092 size_t GenericModel::getDOFs() {
00093         return 0;
00094 }
00095 
00096 size_t GenericModel::getSamples() {
00097         return model.track.pose.size();
00098 }
00099 
00100 // -- params
00101 void GenericModel::readParamsFromModel() {
00102         getParam("sigma_position",sigma_position);
00103         getParam("sigma_orientation",sigma_orientation);
00104         getParam("supress_similar",supress_similar);
00105         getParam("avg_error_position",avg_error_position);
00106         getParam("avg_error_orientation",avg_error_orientation);
00107         getParam("bic",bic);
00108         getParam("last_error_jacobian",last_error_jacobian);
00109         getParam("evaluated",evaluated);
00110 //      getParam("complexity",complexity);//read-only
00111         getParam("jacobian",jacobian);
00112         getParam("hessian",hessian);
00113         getParam("loglikelihood",loglikelihood);
00114         getParam("outlier_ratio",outlier_ratio);
00115         getParam("sac_iterations",sac_iterations);
00116         getParam("prior_outlier_ratio",prior_outlier_ratio);
00117 }
00118 
00119 void GenericModel::writeParamsToModel() {
00120         setParam("sigma_position",sigma_position,ParamMsg::PRIOR);
00121         setParam("sigma_orientation",sigma_orientation,ParamMsg::PRIOR);
00122         setParam("supress_similar",supress_similar,ParamMsg::PRIOR);
00123         setParam("avg_error_position",avg_error_position,ParamMsg::EVAL);
00124         setParam("avg_error_orientation",avg_error_orientation,ParamMsg::EVAL);
00125         setParam("loglikelihood",loglikelihood,ParamMsg::EVAL);
00126         setParam("bic",bic,ParamMsg::EVAL);
00127         setParam("last_error_jacobian",last_error_jacobian,ParamMsg::EVAL);
00128         setParam("evaluated",evaluated,ParamMsg::EVAL);
00129         setParam("complexity",complexity,ParamMsg::PRIOR);
00130         setParam("jacobian",jacobian,ParamMsg::EVAL);
00131         setParam("hessian",hessian,ParamMsg::EVAL);
00132         setParam("dofs",getDOFs(),ParamMsg::EVAL);
00133         setParam("samples",getSamples(),ParamMsg::EVAL);
00134         setParam("outlier_ratio",outlier_ratio,ParamMsg::EVAL);
00135         setParam("sac_iterations",sac_iterations,ParamMsg::PRIOR);
00136         setParam("prior_outlier_ratio",prior_outlier_ratio,ParamMsg::PRIOR);
00137 }
00138 
00139 void GenericModel::prepareChannels() {
00140         channelOutlier = openChannel("outlier");
00141         channelLogLikelihood = openChannel("loglikelihood");
00142         channelInlierLogLikelihood = openChannel("loglikelihood_if_inlier");
00143         channelConfiguration.resize(getDOFs(),0);
00144         for(size_t i=0;i<getDOFs();i++) {
00145                 channelConfiguration[i] = openChannel(str(format("q%d")%i));
00146         }
00147 
00148 }
00149 
00150 double GenericModel::getParam(std::string name) {
00151         for(size_t i=0;i<model.params.size();i++) {
00152                 if(model.params[i].name == name) {
00153                         return(model.params[i].value);
00154                 }
00155         }
00156 //      std::cerr << "WARNING (in GenericModel::getParam): undefined parameter '"<<name<<"'" << std::endl;
00157         return 0.00;
00158 }
00159 
00160 void GenericModel::getParam(std::string name,double& value) {
00161         if(hasParam(name))
00162                 value = getParam(name);
00163 }
00164 
00165 void GenericModel::getParam(std::string name,Eigen::VectorXd &vec) {
00166         for(int i=0;i<vec.rows();i++)
00167                 vec(i) = getParam( str(boost::format( name+"[%1%]") %i ) );
00168 }
00169 
00170 void GenericModel::getParam(std::string name,tf::Vector3 &vec) {
00171         vec.setX( getParam( name+".x" ) );
00172         vec.setY( getParam( name+".y" ) );
00173         vec.setZ( getParam( name+".z" ) );
00174 }
00175 
00176 void GenericModel::getParam(std::string name,tf::Quaternion &quat) {
00177         quat.setX( getParam( name+".x" ) );
00178         quat.setY( getParam( name+".y" ) );
00179         quat.setZ( getParam( name+".z" ) );
00180         quat.setW( getParam( name+".w" ) );
00181 }
00182 
00183 void GenericModel::getParam(std::string name,tf::Transform &t) {
00184         tf::Quaternion q;
00185         tf::Vector3 v;
00186         getParam(name+".orientation",q);
00187         getParam(name+".position",v);
00188         t = tf::Transform(q,v);
00189 }
00190 
00191 void GenericModel::getParam(std::string name,Eigen::MatrixXd &mat) {
00192         for(int r=0;r<mat.rows();r++)
00193                 for(int c=0;c<mat.cols();c++)
00194                         mat(r,c) = getParam( str(boost::format( name+"[%1%][%2%]") %r % c) );
00195 }
00196 
00197 void GenericModel::setParam(std::string name,double value,int type) {
00198         for(size_t i=0;i<model.params.size();i++) {
00199                 if(model.params[i].name == name) {
00200                         model.params[i].value = value;
00201                         return;
00202                 }
00203         }
00204         ParamMsg data;
00205         data.name = name;
00206         data.value = value;
00207         data.type = type;
00208         model.params.push_back(data);
00209 }
00210 
00211 void GenericModel::setParam(std::string name,const Eigen::VectorXd &vec,int type) {
00212         for(int i=0;i<vec.rows();i++)
00213                 setParam( boost::str(boost::format( name+"[%1%]") %i ),vec(i),type );
00214 }
00215 
00216 void GenericModel::setParam(std::string name,const tf::Vector3 &vec,int type) {
00217         setParam( name+".x",vec.x(),type );
00218         setParam( name+".y",vec.y(),type );
00219         setParam( name+".z",vec.z(),type );
00220 }
00221 
00222 void GenericModel::setParam(std::string name,const tf::Quaternion &quat,int type) {
00223         setParam( name+".x",quat.x(),type );
00224         setParam( name+".y",quat.y(),type );
00225         setParam( name+".z",quat.z(),type );
00226         setParam( name+".w",quat.w(),type );
00227 }
00228 
00229 void GenericModel::setParam(std::string name,const tf::Transform &t,int type) {
00230         setParam(name+".position",t.getOrigin(),type);
00231         setParam(name+".orientation",t.getRotation(),type);
00232 }
00233 
00234 void GenericModel::setParam(std::string name,const Eigen::MatrixXd &mat,int type) {
00235         for(int r=0;r<mat.rows();r++)
00236                 for(int c=0;c<mat.cols();c++)
00237                         setParam( str(boost::format( name+"[%1%][%2%]") %r%c ),mat(r,c),type );
00238 }
00239 
00240 bool GenericModel::hasParam(std::string name) {
00241         for(size_t i=0;i<model.params.size();i++) {
00242                 if(model.params[i].name == name)
00243                         return(true);
00244         }
00245         return false;
00246 }
00247 
00248 // -- track data
00249 int GenericModel::openChannel(std::string name,bool autocreate) {
00250         return(articulation_models::openChannel(model.track,name,autocreate));
00251 }
00252 
00253 // -- train model
00254 bool GenericModel::fitModel() {
00255         if(!sampleConsensus()) {
00256 //              if(DEBUG) cout <<"sampleConsesus failed of "<<getModelName()<<endl;
00257                 return false;
00258         }
00259         if(!optimizeParameters()) {
00260 //              if(DEBUG) cout <<"optimizeParameters failed of "<<getModelName()<<endl;
00261                 return false;
00262         }
00263         if(!normalizeParameters()) {
00264                 return false;
00265         }
00266     return true;
00267 }
00268 
00269 bool GenericModel::fitMinMaxConfigurations() {
00270         setParam("q_min",getMinConfigurationObserved(),ParamMsg::PARAM);
00271         setParam("q_max",getMaxConfigurationObserved(),ParamMsg::PARAM);
00272         return true;
00273 }
00274 
00275 
00276 // -- evaluate model
00277 bool GenericModel::evaluateModel() {
00278         // need at least one data point
00279         if(model.track.pose.size() == 0)
00280                 return false;
00281 
00282         // let getLogLikelihood() do the projection
00283         loglikelihood = getLogLikelihood(false);
00284         // evaluate some extra statistics
00285 
00286         // get params
00287         size_t n = model.track.pose.size();
00288 
00289         // compute pose difference and likelihoods
00290         double sum_position2 = 0;
00291         double sum_orientation2 = 0;
00292 
00293         double sum_position = 0;
00294         double sum_orientation = 0;
00295 //      double sum_loglikelihood = 0;
00296 
00297         for(size_t i=0;i<n;i++) {
00298                 tf::Transform p1 = poseToTransform(model.track.pose[i]);
00299                 tf::Transform p2 = poseToTransform(model.track.pose_projected[i]);
00300                 tf::Transform diff = p1.inverseTimes(p2);
00301                 double err_position2 = diff.getOrigin().length2();
00302                 double err_orientation2 = SQR(diff.getRotation().getAngle());
00303 //              sum_loglikelihood += model.track.channels[channelInlierLogLikelihood].values[i];
00304 
00305                 sum_position2 += err_position2;
00306                 sum_orientation2 += err_orientation2;
00307                 sum_position += sqrt(err_position2);
00308                 sum_orientation += sqrt(err_orientation2);
00309         }
00310 
00311         // store into cache
00312         avg_error_position = sum_position/n;
00313         avg_error_orientation = sum_orientation/n;
00314         loglikelihood += - ((double)n)*getDOFs()*log(n);
00315 
00316         bic =
00317                                         -2*(loglikelihood )
00318                                         +complexity
00319                                         * log( n );
00320 
00321         last_error_jacobian = evalLatestJacobian();
00322 
00323         evaluated = true;
00324 
00325         if(model.track.pose.size()>=2) {
00326                 VectorXd q1 = predictConfiguration( model.track.pose.front() );
00327                 VectorXd q2 = predictConfiguration( model.track.pose.back() );
00328 
00329                 jacobian  = predictJacobian( q2 );
00330                 hessian = predictHessian( q2 );
00331                 if(getDOFs()>=1 ) {
00332                         VectorXd p(3);
00333                         for(size_t i=0;i<model.track.pose.size();i++) {
00334                                 p += pointToEigen(model.track.pose[i].position) - pointToEigen(model.track.pose.front().position);
00335                         }
00336                         if(p.dot(jacobian.col(0))<0)    // make Jacobian point into current direction (of dof 1)
00337                                 jacobian *= -1;
00338                                 hessian *= -1;
00339                 }
00340         }
00341         writeParamsToModel();
00342         return true;
00343 }
00344 
00345 double GenericModel::evalLatestJacobian() {
00346         if(model.track.pose.size()<2)
00347                 return 0.00;
00348 
00349         // observed direction of motion
00350         VectorXd p1 = pointToEigen( model.track.pose[model.track.pose.size()-1].position );
00351         VectorXd p2 = pointToEigen( model.track.pose[model.track.pose.size()-2].position );
00352         VectorXd pD_obs = p1-p2;
00353         if(pD_obs.norm() == 0)
00354                 return 0.00;
00355         pD_obs.normalize();
00356 //      cout << "p1="<<p1<<endl;
00357 //      cout << "p2="<<p2<<endl;
00358 //      cout << "pD_obs="<<pD_obs<<endl;
00359 
00360         if(getDOFs()==0)
00361                 return 2*M_PI;
00362 
00363         // predicted direction of motion
00364         VectorXd q1 = predictConfiguration( model.track.pose[model.track.pose.size()-1] );
00365         VectorXd q2 = predictConfiguration( model.track.pose[model.track.pose.size()-2] );
00366 //      cout << "q1="<<q1<<endl;
00367 //      cout << "q2="<<q2<<endl;
00368         MatrixXd J2 = predictJacobian( q2 );
00369 //      cout << "J2="<<J2<<endl;
00370         VectorXd qD = (q1 - q2);
00371 //      cout << "qD="<<qD<<endl;
00372         VectorXd pD_pred = J2 * qD; // reduce Jacobian
00373 //      cout << "pD_pred="<<pD_pred<<endl;
00374         if(pD_pred.norm() == 0)
00375                 return 0.00;
00376         pD_pred.normalize();
00377 //      cout << "qD_pred.normalized="<<pD_pred<<endl;
00378 //
00379 //      cout << "angle_diff="<<acos( pD_obs.dot( pD_pred ) )<<endl;
00380 //
00381 //      // return angle between predicted motion and observed motion
00382         return acos( pD_obs.dot( pD_pred ) );
00383 }
00384 
00385 double GenericModel::getPositionError() {
00386         return avg_error_position;
00387 }
00388 
00389 double GenericModel::getOrientationError() {
00390         return avg_error_orientation;
00391 }
00392 
00393 double GenericModel::getBIC() {
00394         return bic;
00395 }
00396 
00397 // -- cartesian space
00398 geometry_msgs::Pose GenericModel::predictPose(V_Configuration q) {
00399         geometry_msgs::Pose p;
00400         p.orientation.w = 1;
00401         return p;
00402 }
00403 
00404 M_CartesianJacobian GenericModel::predictJacobian(V_Configuration vq,double delta) {
00405         M_CartesianJacobian J;
00406         J.resize(3,getDOFs());
00407         VectorXd p = pointToEigen(predictPose(vq).position);
00408         for(size_t i=0;i<getDOFs();i++) {
00409                 V_Configuration q = vq;
00410                 q(i) += delta;
00411                 J.col(i) = (pointToEigen( predictPose(q).position ) - p)/delta;
00412         }
00413         return J;
00414 }
00415 
00416 M_CartesianJacobian GenericModel::predictHessian(V_Configuration q,double delta) {
00417         M_CartesianJacobian H;
00418         H.resize(3*getDOFs(),getDOFs());
00419 //      cout <<"dofs="<<getDOFs()<<" q.size"<<vq.size()<<endl;
00420         for(size_t i=0;i<getDOFs();i++) {
00421                 V_Configuration qd = q;
00422                 q(i) += delta;
00423                 M_CartesianJacobian H_part;
00424 
00425                 M_CartesianJacobian J = predictJacobian(q);
00426                 M_CartesianJacobian Jd = predictJacobian(qd);
00427 
00428 //              cout << J(0,0) << " "<< J(1,0) << " "<< J(2,0) << endl;
00429 //              cout << "H_part "<<Jd(0,0) << " "<< Jd(1,0) << " "<< Jd(2,0) << endl;
00430 
00431                 H_part = (Jd - J)/delta;
00432 //              cout << "H_part "<<H_part(0,0) << " "<< H_part(1,0) << " "<< H_part(2,0) << endl;
00433                 for(size_t r=0;r<3;r++) {
00434                         for(size_t c=0;c<getDOFs();c++) {
00435                                 H(r+3*i,c) = H_part(r,c);
00436                         }
00437                 }
00438         }
00439         return H;
00440 }
00441 
00442 // -- configuration space
00443 void GenericModel::setConfiguration(size_t index,V_Configuration q) {
00444         std::map<int,int> channel;
00445         // get channel ids and prepare channels
00446         for(size_t ch=0;ch<getDOFs();ch++) {
00447                 std::stringstream s;
00448                 s << "q" << ch;
00449                 channel[ch] = openChannel( s.str() );
00450         }
00451 
00452         for(int j=0;j<q.rows();j++) {
00453                 model.track.channels[ channel[j] ].values[index] = q[j];
00454         }
00455 }
00456 
00457 // -- configuration space
00458 void GenericModel::setJacobian(size_t index,M_CartesianJacobian J) {
00459         std::map<int,std::map<int,int> > channel;
00460         // get channel ids and prepare channels
00461         for(int r=0;r<J.rows();r++)
00462                 for(int c=0;c<J.cols();c++)
00463                 channel[r][c] = openChannel( boost::str(boost::format( "J[%1%][%2%]") %r%c ) );
00464 
00465         for(int r=0;r<J.rows();r++)
00466                 for(int c=0;c<J.cols();c++)
00467                         model.track.channels[ channel[r][c] ].values[index] = J(r,c);
00468 }
00469 
00470 V_Configuration GenericModel::getConfiguration(size_t index) {
00471         std::map<int,int> channel;
00472         // get channel ids and prepare channels
00473         for(size_t ch=0;ch<getDOFs();ch++) {
00474                 std::stringstream s;
00475                 s << "q" << ch;
00476                 channel[ch] = openChannel( s.str() );
00477         }
00478 
00479         V_Configuration q;
00480         if (getDOFs()) q.resize(getDOFs());
00481         for(int j=0;j<q.rows();j++) {
00482                 q[j] = model.track.channels[ channel[j] ].values[index];
00483         }
00484         return(q);
00485 }
00486 
00487 V_Configuration GenericModel::predictConfiguration(geometry_msgs::Pose pose) {
00488         V_Configuration q;
00489         if(getDOFs()>0) q.resize(getDOFs());
00490         return q;
00491 }
00492 
00493 
00494 
00495 V_Configuration GenericModel::getMinConfigurationObserved() {
00496         if(getDOFs()==0) return V_Configuration();
00497         V_Configuration q_min(getDOFs());
00498         for(size_t j=0;j<getDOFs();j++) {
00499                 q_min[j] = FLT_MAX;
00500         }
00501 
00502         for(size_t i=0;i<model.track.pose.size();i++) {
00503                 V_Configuration q = getConfiguration(i);
00504                 for(size_t j=0;j<getDOFs();j++) {
00505                         q_min[j] = MIN( q_min[j], q[j] );
00506                 }
00507         }
00508 
00509         return q_min;
00510 }
00511 
00512 V_Configuration GenericModel::getMaxConfigurationObserved() {
00513         if(getDOFs()==0) return V_Configuration();
00514         V_Configuration q_max(getDOFs());
00515         for(size_t j=0;j<getDOFs();j++) {
00516                 q_max[j] = -FLT_MAX;
00517         }
00518 
00519         for(size_t i=0;i<model.track.pose.size();i++) {
00520                 V_Configuration q = getConfiguration(i);
00521                 for(size_t j=0;j<getDOFs();j++) {
00522                         q_max[j] = MAX( q_max[j], q[j] );
00523                 }
00524         }
00525 
00526         return q_max;
00527 }
00528 
00529 // -- projections of track data
00530 void GenericModel::projectPoseToConfiguration() {
00531         // now estimate configurations, and store in channels q0..qn
00532         for(size_t i=0;i<model.track.pose.size();i++) {
00533                 V_Configuration q;
00534                 q = predictConfiguration( model.track.pose[i] );
00535                 setConfiguration(i,q);
00536         }
00537 }
00538 
00539 void GenericModel::projectConfigurationToPose() {
00540         // now estimate poses
00541         model.track.pose_projected.resize(model.track.pose.size());
00542         for(size_t i=0;i<model.track.pose.size();i++) {
00543                 V_Configuration q = getConfiguration(i);
00544                 model.track.pose_projected[i] = predictPose( q );
00545         }
00546 }
00547 
00548 void GenericModel::projectConfigurationToJacobian() {
00549         // now estimate poses
00550         model.track.pose_projected.resize(model.track.pose.size());
00551         for(size_t i=0;i<model.track.pose.size();i++) {
00552                 V_Configuration q = getConfiguration(i);
00553                 setJacobian(i, predictJacobian( q ));
00554         }
00555 }
00556 
00557 void GenericModel::sampleConfigurationSpace(double resolution) {
00558 //      cout << "resolution="<<resolution<<endl;
00559         // clear all poses
00560         model.track.pose_resampled.clear();
00561 
00562         if(getDOFs() == 0) {
00563                 model.track.pose_resampled.push_back( predictPose(V_Configuration() ) );        // single sample, empty configuration
00564                 return;
00565         }
00566 
00567         V_Configuration q_min(getDOFs());
00568         V_Configuration q_max(getDOFs());
00569         getParam("q_min",q_min);
00570         getParam("q_max",q_max);
00571 
00572         geometry_msgs::Pose p_min = predictPose( q_min );
00573         geometry_msgs::Pose p_max = predictPose( q_max );
00574         double dist =
00575                         (positionToVector(p_min.position) - positionToVector(p_max.position)).length();
00576         if(isnan(dist) || isinf(dist)) return;
00577 
00578         // show all axes..
00579         for(size_t j=0;j<getDOFs();j++) {
00580                 size_t num = MAX(2,1 + (int)( dist /resolution ));
00581                 num = MIN(1000,MAX(num,fabs((double)(q_min[0]-q_max[0])/resolution)));
00582                 double new_res = (q_max[j] - q_min[j]) / (num-1);
00583 
00584                 for(size_t i=0;i<num;i++) {
00585                         V_Configuration q(getDOFs());
00586                         q[j] = q_min[j] + i*new_res;
00587 
00588                         geometry_msgs::Pose pose = predictPose( q );
00589                         model.track.pose_resampled.push_back(pose);
00590                 }
00591         }
00592 }
00593 
00594 void GenericModel::keepLatestPoseOnly() {
00595         if(model.track.pose.size()<=1) return;
00596         model.track.pose.erase( model.track.pose.begin(), model.track.pose.begin() + (model.track.pose.size() -1) );
00597         for(size_t i = 0; i < model.track.channels.size(); i++) {
00598                 model.track.channels[i].values.erase(
00599                                 model.track.channels[i].values.begin(),
00600                                 model.track.channels[i].values.begin() + (model.track.channels[i].values.size() -1)
00601                 );
00602         }
00603 }
00604 
00605 double GenericModel::getInlierLogLikelihood( size_t index ) {
00606         geometry_msgs::Pose &pose_obs = model.track.pose[index];
00607         V_Configuration q_estimated = predictConfiguration(pose_obs);
00608         for(size_t i=0;i<(size_t)q_estimated.rows();i++) {
00609                 model.track.channels[channelConfiguration[i]].values[index] =  q_estimated[i];
00610         }
00611 
00612         geometry_msgs::Pose pose_estimated = predictPose(q_estimated);
00613         model.track.pose_projected[index] = pose_estimated;
00614 
00615         tf::Transform diff = poseToTransform(pose_obs).inverseTimes( poseToTransform(pose_estimated) );
00616         double err_position = diff.getOrigin().length();
00617         double err_orientation = fabs(diff.getRotation().getAngle());
00618 
00619         double loglikelihood =
00620                         - log(2*M_PI * sigma_position*sigma_orientation)
00621                         - 0.5*(
00622                                         ( SQR(err_position) / (SQR(sigma_position)) ) +
00623                                         ( SQR(err_orientation) / SQR(sigma_orientation)) );     // 2-dim multivariate normal distribution
00624         return loglikelihood;
00625 }
00626 
00627 double GenericModel::getOutlierLogLikelihood() {
00628         // outside the 95% ellipsoid
00629         double chi2inv = 1.96;
00630 //      chi2inv = 6.63; //99% ellipsoid
00631 
00632         double err_position = chi2inv * sigma_position;
00633         double err_orientation = chi2inv * sigma_orientation;
00634 
00635         double loglikelihood =
00636                         - log(2*M_PI * sigma_position*sigma_orientation)
00637                         - 0.5*(
00638                                         ( SQR(err_position) / (SQR(sigma_position)) ) +
00639                                         ( SQR(err_orientation) / SQR(sigma_orientation)) );     // 2-dim multivariate normal distribution
00640 
00641         return( loglikelihood );
00642 }
00643 
00644 double GenericModel::getLogLikelihoodForPoseIndex(size_t index) {
00645 //      double gamma_mixing = 0.1;
00646 //      return (1-gamma_mixing)*getInlierLogLikelihood(pose_obs) + gamma_mixing * getOutlierLogLikelihood();
00647         double inlierLikelihood = getInlierLogLikelihood(index);
00648         double outlierLikelihood = getOutlierLogLikelihood();
00649 
00650 //  mle-sac
00651         model.track.channels[channelInlierLogLikelihood].values[index] = inlierLikelihood;
00652         double pi = (1-outlier_ratio) * exp( inlierLikelihood );
00653         double po = outlier_ratio * exp( outlierLikelihood );
00654         model.track.channels[channelOutlier].values[index] =  po / (pi+po);
00655         double p = (log(exp(inlierLikelihood) + exp(outlierLikelihood)));
00656         model.track.channels[channelLogLikelihood].values[index] =  p;
00657         return p;
00658 
00659 //      // ransac
00660 //      return ((1-gamma_mixing)*inlierLikelihood + (gamma_mixing)*outlierLikelihood);
00661 
00662 //      // m-sac
00663 //      return (max(inlierLikelihood,outlierLikelihood));
00664 
00665 
00666 }
00667 
00668 double GenericModel::getLogLikelihood(bool estimate_outlier_ratio) {
00669         model.track.pose_projected.resize(model.track.pose.size());
00670 
00671         model.track.channels[channelInlierLogLikelihood].values.resize(model.track.pose.size());
00672         model.track.channels[channelOutlier].values.resize(model.track.pose.size());
00673         model.track.channels[channelLogLikelihood].values.resize(model.track.pose.size());
00674         for(size_t i=0;i<(size_t)getDOFs();i++) {
00675                 model.track.channels[channelConfiguration[i]].values.resize(model.track.pose.size());
00676         }
00677 
00678         double sum_likelihood = 0;
00679         size_t n = getSamples();
00680         if(estimate_outlier_ratio) {
00681                 outlier_ratio =0.5;
00682                 for(size_t i=0;i<n;i++) {
00683                         model.track.channels[channelOutlier].values[i] = 0.5;   // initial estimate of gamma
00684                 }
00685 
00686                 int iter = 0;
00687                 double diff = 0;
00688                 do{
00689                         sum_likelihood = 0;
00690                         for(size_t i=0;i<n;i++) {
00691                                 sum_likelihood += getLogLikelihoodForPoseIndex(i);
00692                         }
00693 
00694                         double outlier_ratio_new = 0;
00695                         for(size_t i=0;i<n;i++) {
00696                                 outlier_ratio_new += model.track.channels[channelOutlier].values[i]/n;
00697                         }
00698                         diff = fabs(outlier_ratio - outlier_ratio_new);
00699                         iter++;
00700                         outlier_ratio = outlier_ratio_new;
00701 //                      cout <<"EM iter="<<iter<<" outlier_ratio="<<outlier_ratio<<endl;
00702                 } while( diff>0.01 && iter<10 );
00703         } else {
00704                 for(size_t i=0;i<n;i++) {
00705                         sum_likelihood += getLogLikelihoodForPoseIndex(i);
00706                 }
00707         }
00708         sum_likelihood += - prior_outlier_ratio * outlier_ratio * n;
00709         return sum_likelihood;
00710 }
00711 
00712 bool GenericModel::guessParameters() {
00713         // sample a minimum number of samples to compute parameters
00714         return false;
00715 }
00716 
00717 bool GenericModel::sampleConsensus() {
00718         // sample consensus
00719         writeParamsToModel();
00720         vector<articulation_msgs::ParamMsg> bestParams = model.params;
00721         double bestLikelihood = -DBL_MAX;
00722         bool goodGuess = false;
00723         for(size_t it=0;it<sac_iterations;it++) {
00724                 if(!guessParameters()) continue;
00725                 goodGuess = true;
00726                 double likelihood = getLogLikelihood(true);
00727 //              cout <<"RANSAC iteration="<<it<<", likelihood="<<likelihood<<endl;
00728                 if(bestLikelihood < likelihood) {
00729                         writeParamsToModel();
00730                         bestParams = model.params;
00731                         bestLikelihood = likelihood;
00732                 }
00733         }
00734 //      cout <<"RANSAC best likelihood="<<bestLikelihood<<endl;
00735         model.params = bestParams;
00736         readParamsFromModel();
00737 
00738         return goodGuess;
00739 }
00740 
00741 double
00742 my_f (const gsl_vector *v, void *params)
00743 {
00744   GenericModel *p = (GenericModel *)params;
00745 
00746   vector<double> delta( v->size );
00747   for(size_t i=0;i<v->size;i++) {
00748           delta[i] = gsl_vector_get (v, i);
00749 //        cout <<"delta["<<i<<"]="<<delta[i]<<" ";
00750   }
00751 
00752   p->model.params = p->params_initial;
00753   p->readParamsFromModel();
00754   p->updateParameters(delta);
00755   p->writeParamsToModel();
00756   double likelihood = p->getLogLikelihood(true);
00757 //  cout <<"likelihood="<<likelihood<<endl;
00758   return -likelihood;
00759 }
00760 
00761 /* The gradient of f, df = (df/dx, df/dy). */
00762 void
00763 my_df (const gsl_vector *v, void *params,
00764        gsl_vector *df)
00765 {
00766         double likelihood = my_f(v,params);
00767 
00768         gsl_vector * v_delta =gsl_vector_alloc (v->size);
00769 
00770     double DELTA = 1e-3;
00771     for(size_t i=0;i<v->size;i++) {
00772         v_delta = gsl_vector_alloc (v->size);
00773         gsl_vector_memcpy(v_delta,v);
00774         gsl_vector_set(v_delta, i,gsl_vector_get(v, i)+DELTA);
00775 
00776         double likelihood_delta = my_f(v_delta,params);
00777         gsl_vector_set(df, i,(likelihood_delta-likelihood)/DELTA);
00778         }
00779     gsl_vector_free (v_delta);
00780 }
00781 
00782 /* Compute both f and df together. */
00783 void
00784 my_fdf (const gsl_vector *x, void *params,
00785         double *f, gsl_vector *df)
00786 {
00787   *f = my_f(x, params);
00788   my_df(x, params, df);
00789 }
00790 
00791 bool GenericModel::optimizeParameters() {
00792         // using gsl minimizer
00793         // dofs to optimize: complexity
00794         // stores current parameter vector as params_initial
00795         writeParamsToModel();
00796         params_initial = model.params;
00797         // calls updateParameters(..) to set new params vector
00798 
00799     size_t iter = 0;
00800     int status;
00801 
00802     const gsl_multimin_fdfminimizer_type *T;
00803     gsl_multimin_fdfminimizer *s;
00804 
00805     gsl_vector *x;
00806     gsl_multimin_function_fdf my_func;
00807 
00808     my_func.n = (int)complexity;
00809     my_func.f = my_f;
00810     my_func.df = my_df;
00811     my_func.fdf = my_fdf;
00812     my_func.params = this;
00813 
00814     x = gsl_vector_alloc ((int)complexity);
00815     gsl_vector_set_zero (x);
00816 //    double likelihood_initial= -my_f(x,this);
00817 
00818     T = gsl_multimin_fdfminimizer_vector_bfgs2;
00819     s = gsl_multimin_fdfminimizer_alloc (T, (int)complexity);
00820 
00821     gsl_multimin_fdfminimizer_set (s, &my_func, x, 0.01, 0.1);
00822 
00823 //    cout <<"optimizing "<<complexity<<" DOFs"<<endl;
00824 
00825 //    for(size_t i=0;i<model.params.size();i++) {
00826 //      if(model.params[i].type != ParamMsg::PARAM) continue;
00827 //      cout <<" param "<<model.params[i].name<<"="<<model.params[i].value<<endl;
00828 //    }
00829 
00830     if(optimizer_iterations>0) do
00831       {
00832         iter++;
00833 //        cout <<"iter "<<iter<<".."<<endl;
00834         status = gsl_multimin_fdfminimizer_iterate (s);
00835 
00836         if (status)
00837           break;
00838 
00839         status = gsl_multimin_test_gradient (s->gradient, 1e-1);
00840 
00841 //        if (status == GSL_SUCCESS)
00842 //          printf ("Minimum found at:\n");
00843 
00844 //        printf ("i=%5d ", (int)iter);
00845 //        for(size_t i=0;i<s->x->size;i++) {
00846 //            printf ("%5f ", gsl_vector_get(s->x,i));
00847 //        }
00848 //        printf("\n");
00849       }
00850     while (status == GSL_CONTINUE && iter < optimizer_iterations);
00851 
00852 //    double likelihood_final = -my_f(s->x,this);
00853 //    cout <<"likelihood_initial="<<likelihood_initial<<" ";
00854 //    cout <<"likelihood_final="<<likelihood_final<<" ";
00855 //    cout <<"after "<<iter<<" iterations";
00856 //    cout << endl;
00857 
00858     gsl_multimin_fdfminimizer_free (s);
00859     gsl_vector_free (x);
00860 
00861         if(!fitMinMaxConfigurations())
00862                 return false;
00863 
00864 //      cout <<"type="<<getModelName()<<endl;
00865 //    for(size_t i=0;i<model.params.size();i++) {
00866 //      if(model.params[i].type != ParamMsg::PARAM) continue;
00867 //      cout <<" param "<<model.params[i].name<<"="<<model.params[i].value<<endl;
00868 //    }
00869 
00870     return true;
00871 }
00872 
00873 
00874 void GenericModel::updateParameters(std::vector<double> delta) {
00875 }
00876 
00877 bool GenericModel::normalizeParameters() {
00878         return true;
00879 }
00880 
00881 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Properties Friends Defines


articulation_models
Author(s): Juergen Sturm
autogenerated on Wed Dec 26 2012 15:35:18