contrib/brl/bbas/bvgl/bvgl_articulated_poly.cxx
Go to the documentation of this file.
00001 #include "bvgl_articulated_poly.h"
00002 //:
00003 // \file
00004 #include <vcl_iostream.h>
00005 #include <vcl_cassert.h>
00006 #include <vcl_vector.h>
00007 #include <vcl_cmath.h>
00008 #include <vnl/vnl_math.h>
00009 #include <vnl/vnl_numeric_traits.h>
00010 #include <vgl/vgl_homg_point_2d.h>
00011 #include <vgl/vgl_point_2d.h>
00012 #include <vsol/vsol_point_2d.h>
00013 
00014 //empty constructor
00015 bvgl_articulated_poly::bvgl_articulated_poly(const unsigned n_joints)
00016 {
00017   joint_transforms_.resize(n_joints);
00018   //make the transforms identity with unit length joints
00019   for (unsigned i = 0; i<n_joints; ++i)
00020   {
00021     joint_transforms_[i].set_identity();
00022     if (i>0)
00023       joint_transforms_[i].set_translation(1.0, 0.0);
00024   }
00025   for (unsigned i = 0; i<n_joints; ++i)
00026   {
00027     vsol_point_2d_sptr p = this->joint_position(i);
00028     this->add_vertex(p);
00029   }
00030 }
00031 
00032 //link lengths are specified. For n joints there are n-1 links
00033 bvgl_articulated_poly::
00034 bvgl_articulated_poly(const unsigned n_joints,
00035                       vcl_vector<double> const& link_lengths)
00036 {
00037   assert(n_joints==link_lengths.size()+1);
00038 
00039   joint_transforms_.resize(n_joints);
00040   //make the transforms identity with unit length joints
00041   for (unsigned i = 0; i<n_joints; ++i)
00042   {
00043     joint_transforms_[i].set_identity();
00044     if (i>0)
00045       joint_transforms_[i].set_translation(link_lengths[i-1], 0.0);
00046   }
00047   for (unsigned i = 0; i<n_joints; ++i)
00048   {
00049     vsol_point_2d_sptr p = this->joint_position(i);
00050     this->add_vertex(p);
00051   }
00052 }
00053 
00054 bvgl_articulated_poly::bvgl_articulated_poly(const bvgl_articulated_poly& poly)
00055 : vsol_polyline_2d(poly)
00056 {
00057   unsigned n = poly.size();
00058   joint_transforms_.resize(n);
00059   for (unsigned i = 0; i<n; ++i)
00060   {
00061     this->add_vertex(poly.joint_position(i));
00062     joint_transforms_[i]=poly.joint_transform(i);
00063   }
00064 }
00065 
00066 //Transform the joint position to world coordinates
00067 vsol_point_2d_sptr
00068 bvgl_articulated_poly::joint_position(const unsigned joint) const
00069 {
00070   if (joint == 0)
00071     return new vsol_point_2d(0.0, 0.0);
00072 
00073   vgl_h_matrix_2d<double> T = joint_transforms_[0];
00074   for (unsigned i=1; i<=joint; ++i)
00075   {
00076     vgl_h_matrix_2d<double> Tp = joint_transforms_[i];
00077     T = T*Tp;
00078   }
00079   //The last joint has local coordinates (0,0) at the joint
00080   vgl_homg_point_2d<double> zero(0.0,0.0,1.0);
00081   vgl_homg_point_2d<double> homg_wp = T(zero);
00082   vgl_point_2d<double> wp(homg_wp);
00083   return new vsol_point_2d(wp.x(), wp.y());
00084 }
00085 
00086 void bvgl_articulated_poly::update()
00087 {
00088   unsigned n = this->size();
00089   for (unsigned i = 0; i<n; ++i)
00090   {
00091     vsol_point_2d_sptr p = this->joint_position(i);
00092     (*storage_)[i]->set_x(p->x());
00093     (*storage_)[i]->set_y(p->y());
00094   }
00095 }
00096 
00097 void bvgl_articulated_poly::
00098 transform(vcl_vector<double > const& delta_joint_angle)
00099 {
00100   unsigned n = delta_joint_angle.size();
00101   assert(n==joint_transforms_.size());
00102   for (unsigned i = 0; i<n; ++i)
00103   {
00104     vgl_h_matrix_2d<double> r;
00105     r.set_identity();
00106     r.set_rotation(delta_joint_angle[i]);
00107     joint_transforms_[i]=joint_transforms_[i]*r;
00108   }
00109   this->update();
00110 }
00111 
00112 void bvgl_articulated_poly::
00113 sub_manifold_transform(const double t,
00114                        vcl_vector<double > const& basis_angles)
00115 {
00116   vcl_vector<double > angles;
00117   for (vcl_vector<double >::const_iterator ait = basis_angles.begin();
00118        ait != basis_angles.end(); ++ait)
00119     angles.push_back(t*(*ait));
00120   this->transform(angles);
00121   this->update();
00122 }
00123 
00124 //only works up to equiform
00125 static double angle_from_rotation_matrix(vgl_h_matrix_2d<double> const& r)
00126 {
00127   double c = r.get(0,0);
00128   double s = r.get(1,0);
00129   double ang = vcl_atan2(s,c);
00130   if (ang>vnl_math::pi)
00131     ang = 2*vnl_math::pi - ang;
00132   return ang;
00133 }
00134 
00135 double bvgl_articulated_poly::joint_angle(unsigned joint) const
00136 {
00137   return angle_from_rotation_matrix(this->joint_transform(joint));
00138 }
00139 
00140 double bvgl_articulated_poly::link_length(unsigned joint) const
00141 {
00142   unsigned n = this->size();
00143   if (joint>=n-1)
00144     return 0;
00145   vgl_h_matrix_2d<double> T = this->joint_transform(joint+1);
00146   double tx = T.get(0,2), ty = T.get(1,2);
00147   return vcl_sqrt(tx*tx + ty*ty);
00148 }
00149 
00150 //The earlier joints in the chain are weighted more since they appear in more
00151 //backward chain matrices.
00152 double bvgl_articulated_poly::
00153 lie_distance(bvgl_articulated_poly const& apa,
00154              bvgl_articulated_poly const& apb)
00155 {
00156   assert(apa.size()==apb.size());
00157   unsigned na = apa.size();
00158   double d = 0;//distance
00159   //note that there is no effect of the angle of the last joint
00160   //The weight is N-(joint+1)
00161   for (unsigned i =0; i+1<na; ++i)
00162   {
00163     vgl_h_matrix_2d<double> Ta = apa.joint_transform(i);
00164     vgl_h_matrix_2d<double> Tb = apb.joint_transform(i);
00165     double ra = angle_from_rotation_matrix(Ta);
00166     double rb = angle_from_rotation_matrix(Tb);
00167     d += (na-i-1)*(ra-rb)*(ra-rb);
00168   }
00169   return vcl_sqrt(d);
00170 }
00171 
00172 void bvgl_articulated_poly::print()
00173 {
00174   for (unsigned i = 0; i<joint_transforms_.size(); ++i)
00175   {
00176     vsol_point_2d_sptr p = this->joint_position(i);
00177     vcl_cout << "Joint[" << i << "](" << p->x() << ' ' << p->y()
00178              << ")| " << this->joint_angle(i) << "|\n";
00179   }
00180 }
00181 
00182 
00183 void bvgl_articulated_poly::print_xforms()
00184 {
00185   for (unsigned i = 0; i<joint_transforms_.size(); ++i)
00186     vcl_cout << "T[" << i << "]=>\n" <<  joint_transforms_[i] << '\n';
00187 }
00188 
00189 bvgl_articulated_poly_sptr bvgl_articulated_poly::
00190 projection(bvgl_articulated_poly_sptr const& target,
00191            vcl_vector<double > const& manifold_basis)
00192 {
00193   //copy the target
00194   unsigned n = target->size();
00195   vcl_vector<double> links(n-1);
00196   for (unsigned i = 0; i+1<n; ++i)
00197     links[i]=target->link_length(i);
00198   //search for the projection.
00199   bvgl_articulated_poly_sptr manifold = new bvgl_articulated_poly(n, links);
00200   double d = vnl_numeric_traits<double>::maxval, tmin=0;
00201   for (double t = - 3.0; t<=3.0; t+=0.05)
00202   {
00203     manifold->sub_manifold_transform(t, manifold_basis);
00204     double dt = bvgl_articulated_poly::lie_distance(*manifold, *target);
00205     if (dt<d)
00206     {
00207       d = dt;
00208       tmin = t;
00209     }
00210     //undo the transform
00211     manifold->sub_manifold_transform(-t, manifold_basis);
00212   }
00213   manifold->sub_manifold_transform(tmin, manifold_basis);
00214   return manifold;
00215 }