00001 #include "rgrl_trans_rigid.h"
00002
00003
00004
00005
00006
00007 #include <vcl_cassert.h>
00008 #include <vnl/algo/vnl_svd.h>
00009 #include <vnl/vnl_math.h>
00010 #include <rgrl/rgrl_util.h>
00011
00012 rgrl_trans_rigid::
00013 rgrl_trans_rigid( unsigned int dimension )
00014 : R_( vnl_matrix<double>( dimension, dimension, vnl_matrix_identity ) ),
00015 trans_( vnl_vector<double>( dimension, 0.0 ) )
00016 {
00017
00018 assert (dimension==0 || dimension==2 || dimension==3);
00019 }
00020
00021 rgrl_trans_rigid::
00022 rgrl_trans_rigid( vnl_matrix<double> const& rot,
00023 vnl_vector<double> const& in_trans )
00024 : R_( rot ),
00025 trans_( in_trans )
00026 {
00027 assert ( R_.rows() == R_.cols() );
00028 assert ( R_.rows() == trans_.size() );
00029 }
00030
00031 rgrl_trans_rigid::
00032 rgrl_trans_rigid( vnl_matrix<double> const& rot,
00033 vnl_vector<double> const& in_trans,
00034 vnl_matrix<double> const& in_covar )
00035 : rgrl_transformation( in_covar ),
00036 R_( rot ),
00037 trans_( in_trans )
00038 {
00039 assert ( R_.rows() == R_.cols() );
00040 assert ( R_.rows() == trans_.size() );
00041 if ( is_covar_set() ) {
00042 assert ( covar_.rows() == covar_.cols() );
00043 assert ( ( R_.rows() != 2 || covar_.rows() == 3 ) );
00044 assert ( ( R_.rows() != 3 || covar_.rows() == 6 ) );
00045 }
00046 }
00047
00048 void rgrl_trans_rigid::set_translation(double tx, double ty, double tz)
00049 {
00050 assert ( trans_.size() == 3);
00051 trans_[0]=tx;
00052 trans_[1]=ty;
00053 trans_[2]=tz;
00054 }
00055
00056 void rgrl_trans_rigid::set_translation(double tx, double ty)
00057 {
00058 assert ( trans_.size() == 2);
00059 trans_[0]=tx;
00060 trans_[1]=ty;
00061 }
00062
00063 void rgrl_trans_rigid::set_rotation(double theta, double alpha, double phi)
00064 {
00065 assert ( trans_.size() == 3);
00066
00067 double cos_a = vcl_cos(alpha), sin_a = vcl_sin(alpha),
00068 cos_t = vcl_cos(theta), sin_t = vcl_sin(theta),
00069 cos_p = vcl_cos(phi), sin_p = vcl_sin(phi);
00070 R_(0,0) =cos_a*cos_t ; R_(0,1) = -cos_a*sin_t; R_(0,2)=sin_a;
00071 R_(1,0) =cos_t*sin_a*sin_p+cos_p*sin_t; R_(1,1) = -sin_a*sin_p*sin_t+cos_p*cos_t; R_(1,2)=-cos_a*sin_p;
00072 R_(2,0)=-cos_p*cos_t*sin_a+sin_p*sin_t; R_(2,1) = cos_p*sin_a*sin_t+cos_t*sin_p; R_(2,2)=cos_a*cos_p;
00073 }
00074
00075 void rgrl_trans_rigid::set_rotation(double theta)
00076 {
00077 assert ( trans_.size() == 2);
00078
00079 R_(0,0) = vcl_cos(theta); R_(0,1) = vcl_sin(theta);
00080 R_(1,0) = -vcl_sin(theta); R_(1,1) = vcl_cos(theta);
00081 }
00082
00083 void rgrl_trans_rigid::determine_angles(double& phi, double& alpha, double& theta) const
00084 {
00085 assert (trans_.size() == 3);
00086
00087 alpha = vcl_asin( R_(0,2) );
00088
00089 if (R_(0,0) * vcl_cos(alpha) > 0)
00090 {
00091 theta = vcl_atan( -1 * R_(0,1)/R_(0,0) );
00092 }
00093 else
00094 {
00095 theta = vcl_atan( -1 * R_(0,1)/R_(0,0) ) + vnl_math::pi;
00096 }
00097
00098 if (R_(2,2) * vcl_cos(alpha) > 0 )
00099 {
00100 phi = vcl_atan( -1 * R_(1,2) / R_(2,2) );
00101 }
00102 else
00103 {
00104 phi = vcl_atan( -1 * R_(1,2) / R_(2,2) ) + vnl_math::pi;
00105 }
00106 }
00107
00108 void rgrl_trans_rigid::determine_angles( double& theta ) const
00109 {
00110 assert (trans_.size() == 2);
00111 theta = vcl_asin( R_(0,1) );
00112 }
00113
00114 void
00115 rgrl_trans_rigid::
00116 map_loc( vnl_vector<double> const& from,
00117 vnl_vector<double> & to ) const
00118 {
00119 assert ( from.size() == R_.rows() );
00120 to = R_ * from + trans_;
00121 }
00122
00123 void
00124 rgrl_trans_rigid::
00125 map_dir( vnl_vector<double> const& from_loc,
00126 vnl_vector<double> const& from_dir,
00127 vnl_vector<double> & to_dir ) const
00128 {
00129 assert ( from_loc.size() == R_.cols() );
00130 assert ( from_dir.size() == R_.cols() );
00131 to_dir = R_ * from_dir;
00132 to_dir.normalize();
00133 }
00134
00135 vnl_matrix<double>
00136 rgrl_trans_rigid::
00137 transfer_error_covar( vnl_vector<double> const& p ) const
00138 {
00139 assert ( is_covar_set() );
00140 assert ( p.size() == trans_.size() );
00141 vnl_matrix<double> jacobian(3,6,0.0);
00142
00143 double phi,alpha,theta;
00144
00145 determine_angles(phi,alpha,theta);
00146
00147 vnl_matrix<double> Rphid(3,3,0.0);
00148 vnl_matrix<double> Ralphad(3,3,0.0);
00149 vnl_matrix<double> Rthetad(3,3,0.0);
00150
00151
00152 Rthetad(0,0) = -vcl_sin(theta);
00153 Rthetad(0,1) = -vcl_cos(theta);
00154 Rthetad(1,0) = vcl_cos(theta);
00155 Rthetad(1,1) = -vcl_sin(theta);
00156
00157 Ralphad(0,0) = -vcl_sin(alpha);
00158 Ralphad(0,2) = vcl_cos(alpha);
00159 Ralphad(2,0) = -vcl_cos(alpha);
00160 Ralphad(2,2) = -vcl_sin(alpha);
00161
00162 Rphid(1,1) = -vcl_sin(phi);
00163 Rphid(1,2) = -vcl_cos(phi);
00164 Rphid(2,1) = vcl_cos(phi);
00165 Rphid(2,2) = -vcl_sin(phi);
00166
00167 jacobian.set_column(0,Rthetad*p);
00168 jacobian.set_column(1,Ralphad*p);
00169 jacobian.set_column(2,Rphid*p);
00170 jacobian.update(vnl_matrix<double>(3,3,vnl_matrix_identity),0,3);
00171
00172 return jacobian * covar_ * jacobian.transpose();
00173 }
00174
00175 vnl_matrix<double> const&
00176 rgrl_trans_rigid::
00177 R() const
00178 {
00179 return R_;
00180 }
00181
00182 vnl_vector<double>
00183 rgrl_trans_rigid::
00184 t() const
00185 {
00186 return trans_;
00187 }
00188
00189 void
00190 rgrl_trans_rigid::
00191 inv_map( const vnl_vector<double>& to,
00192 bool initialize_next,
00193 const vnl_vector<double>& to_delta,
00194 vnl_vector<double>& from,
00195 vnl_vector<double>& from_next_est) const
00196 {
00197 const double epsilon = 0.01;
00198 vnl_vector<double> to_est = this->map_location(from);
00199
00200
00201 vnl_svd<double> svd( R_ );
00202 vnl_matrix<double> J_inv = svd.inverse();
00203
00204
00205 if (vnl_vector_ssd(to, to_est) > epsilon*epsilon) {
00206 from += J_inv * (to - to_est);
00207 }
00208 if ( initialize_next ) {
00209 from_next_est = from + (J_inv * to_delta);
00210 }
00211 }
00212
00213 void
00214 rgrl_trans_rigid::
00215 jacobian_wrt_loc( vnl_matrix<double>& jac, vnl_vector<double> const& ) const
00216 {
00217 jac = R_;
00218 }
00219
00220 void
00221 rgrl_trans_rigid::
00222 inv_map( const vnl_vector<double>& to,
00223 vnl_vector<double>& from ) const
00224 {
00225 vnl_svd<double> svd( R_ );
00226 from = svd.inverse()*to - svd.inverse()*trans_;
00227 }
00228
00229 rgrl_transformation_sptr
00230 rgrl_trans_rigid::
00231 inverse_transform( ) const
00232 {
00233 vnl_matrix<double> invR = R().transpose();
00234 rgrl_transformation_sptr result = new rgrl_trans_rigid( invR, -invR * t() );
00235
00236 const unsigned m = scaling_factors_.size();
00237 if ( m > 0 ) {
00238 vnl_vector<double> scaling( m );
00239 for ( unsigned int i=0; i<m; ++i )
00240 scaling[i] = 1.0 / scaling_factors_[i];
00241 result->set_scaling_factors( scaling );
00242 }
00243
00244 return result;
00245 }
00246
00247 rgrl_transformation_sptr
00248 rgrl_trans_rigid::
00249 scale_by( double scale ) const
00250 {
00251 rgrl_transformation_sptr xform
00252 = new rgrl_trans_rigid( R_, trans_ * scale,
00253 covar_ );
00254 xform->set_scaling_factors( this->scaling_factors() );
00255 return xform;
00256 }
00257
00258 void
00259 rgrl_trans_rigid::
00260 write( vcl_ostream& os ) const
00261 {
00262
00263 os << "RIGID\n"
00264
00265 << trans_.size() << vcl_endl
00266 << R_ << trans_ << vcl_endl;
00267
00268
00269 rgrl_transformation::write( os );
00270 }
00271
00272 bool
00273 rgrl_trans_rigid::
00274 read( vcl_istream& is )
00275 {
00276 int dim;
00277
00278
00279 rgrl_util_skip_empty_lines( is );
00280
00281 vcl_string str;
00282 vcl_getline( is, str );
00283
00284
00285 if ( str.find( "RIGID" ) != 0 ) {
00286 WarningMacro( "The tag is not RIGID. reading is aborted.\n" );
00287 return false;
00288 }
00289
00290
00291 dim=-1;
00292 is >> dim;
00293 if ( dim > 0 ) {
00294 R_.set_size( dim, dim );
00295 trans_.set_size( dim );
00296 is >> R_ >> trans_;
00297 }
00298
00299
00300 return is.good() && rgrl_transformation::read( is );
00301 }
00302
00303
00304 rgrl_transformation_sptr
00305 rgrl_trans_rigid::
00306 clone() const
00307 {
00308 return new rgrl_trans_rigid( *this );
00309 }