GCOP  1.0
body3d.h
Go to the documentation of this file.
00001 #ifndef GCOP_BODY3D_H
00002 #define GCOP_BODY3D_H
00003 
00004 #include "system.h"
00005 #include "body3dmanifold.h"
00006 #include "so3.h"
00007 #include "se3.h"
00008 #include <limits>
00009 #include <iostream>
00010 #include <utility>
00011 #include "function.h"
00012 
00013 namespace gcop {
00014   
00015   using namespace std;
00016   using namespace Eigen;
00017   
00018   typedef Matrix<double, 6, 1> Vector6d;
00019   typedef Matrix<double, 6, 6> Matrix6d;
00020   typedef Matrix<double, 12, 1> Vector12d;
00021   typedef Matrix<double, 12, 12> Matrix12d;
00022   typedef Matrix<double, 12, 6> Matrix12x6d;
00023   
00031   template <int c = 6> class Body3d : public System<Body3dState, 12, c> {
00032   protected:
00033   
00034   typedef Matrix<double, c, 1> Vectorcd;
00035   typedef Matrix<double, c, c> Matrixcd;
00036   typedef Matrix<double, 6, c> Matrix6xcd;
00037   typedef Matrix<double, 12, c> Matrix12xcd;
00038   typedef Matrix<double, 12, Dynamic> Matrix12Xd;
00039   
00040   public:
00041   
00042   Body3d();
00043   
00044   Body3d(const Vector3d &ds, double m);
00045   
00046   Body3d(const Vector3d &ds, double m, const Vector3d &J);
00047   
00048   virtual ~Body3d();
00049   
00050   virtual double Step(Body3dState &xb, double t, const Body3dState &xa, 
00051                       const Vectorcd &u, double h, const VectorXd *p = 0,
00052                       Matrix12d *A = 0, Matrix12xcd *B = 0, Matrix12Xd *C = 0);
00053 
00054   virtual bool NoiseMatrix(Matrix12d &Q, double t, const Body3dState &x, 
00055                            const Vectorcd &u, double h, const VectorXd *p = 0);
00056   
00057   
00058   double SympStep(double t, Body3dState &xb, const Body3dState &xa, 
00059                   const Vectorcd &u, double h, const VectorXd *p = 0,
00060                   Matrix12d *A = 0, Matrix12xcd *B = 0, Matrix12Xd *C = 0);
00061   
00062   double EulerStep(double t, Body3dState &xb, const Body3dState &xa, 
00063                    const Vectorcd &u, double h, const VectorXd *p = 0,
00064                    Matrix12d *A = 0, Matrix12xcd *B = 0, Matrix12Xd *C = 0);    
00065   
00066   
00067 
00077   void ID(Vector6d &f,
00078           double t, const Body3dState &xb, const Body3dState &xa,
00079           const Vectorcd &u, double h);
00080   
00081   void StateAndControlsToFlat(VectorXd &y, const Body3dState &x, const Vectorcd &u);
00082   
00083   void FlatToStateAndControls(Body3dState &x, Vectorcd &u, const std::vector<VectorXd> &y);
00084   
00091   static void Compute(Vector3d &J, double m, const Vector3d &ds);
00092   
00099   static void Compute(Vector6d &I, double m, const Vector3d &ds);
00100 
00101   Vector3d ds;    
00102   
00103   double m;      
00104   
00105   Vector3d J;    
00106   
00107   Vector6d I;    
00108 
00109   Vector6d Ii;   
00110   
00111   Vector3d Dw;   
00112   
00113   Vector3d Dv;   
00114     
00115   Vector3d fp;   
00116   
00117   Matrix6xcd Bu; 
00118   
00119   bool symp;     
00120   
00121   string name;   
00122 
00123   double sw;     
00124   double sv;     
00125   
00126   };  
00127   
00128 
00129 
00130   template <int c> 
00131     Body3d<c>::Body3d() : 
00132     System<Body3dState, 12, c>(Body3dManifold::Instance()),
00133     ds(.6, .6, .2), m(1),
00134     Dw(0,0,0),
00135     Dv(0,0,0),
00136     fp(0,0,0),
00137     Bu(Matrix<double, 6, c>::Identity()),
00138     symp(true),
00139     sw(0), sv(0) {
00140     
00141     Compute(J, m, ds);
00142     Compute(I, m, ds);
00143   }
00144   
00145   
00146   template <int c> 
00147     Body3d<c>::Body3d(const Vector3d &ds, double m) : 
00148     System<Body3dState, 12, c>(Body3dManifold::Instance()),
00149     ds(ds), m(m),
00150     Dw(0,0,0),
00151     Dv(0,0,0),
00152     fp(0,0,0),
00153     Bu(Matrix<double, 6, c>::Identity()),
00154     symp(true),
00155     sw(0), sv(0) {
00156 
00157     Compute(J, m, ds);
00158     Compute(I, m, ds);
00159   }
00160 
00161   template <int c> 
00162     Body3d<c>::Body3d(const Vector3d &ds, double m, const Vector3d &J) : 
00163     System<Body3dState, 12, c>(Body3dManifold::Instance()),
00164     ds(ds), m(m), J(J),
00165     Dw(0,0,0),
00166     Dv(0,0,0),
00167     fp(0,0,0),
00168     Bu(Matrix<double, 6, c>::Identity()),
00169     symp(true),
00170     sw(0), sv(0) {
00171     
00172   }
00173 
00174 template<int c>  Body3d<c>::~Body3d()
00175 {
00176 }
00177 
00178   template <int c> 
00179     void Body3d<c>::Compute(Vector3d &J, double m, const Vector3d &ds) {
00180     J[0] = m*(ds[1]*ds[1] + ds[2]*ds[2])/3;
00181     J[1] = m*(ds[0]*ds[0] + ds[2]*ds[2])/3;
00182     J[2] = m*(ds[0]*ds[0] + ds[1]*ds[1])/3;
00183   }
00184 
00185   template <int c> 
00186     void Body3d<c>::Compute(Vector6d &I, double m, const Vector3d &ds) {
00187     I[0] = m*(ds[1]*ds[1] + ds[2]*ds[2])/3;
00188     I[1] = m*(ds[0]*ds[0] + ds[2]*ds[2])/3;
00189     I[2] = m*(ds[0]*ds[0] + ds[1]*ds[1])/3;
00190     I[3] = m; 
00191     I[4] = m;
00192     I[5] = m;
00193   }
00194 
00195 
00196   template <int c> 
00197     bool Body3d<c>::NoiseMatrix(Matrix12d &Q, 
00198                                 double t, const Body3dState &x, 
00199                                 const Vectorcd &u, double dt, 
00200                                 const VectorXd *p) {    
00201     Q.setZero();
00202     double dt2 = dt*dt/2;
00203     Q(0,6) = sw*dt2/J(0);
00204     Q(1,7) = sw*dt2/J(1);
00205     Q(2,8) = sw*dt2/J(2);
00206     Q(3,9) = sv*dt2/m;
00207     Q(4,10) = sv*dt2/m;
00208     Q(5,11) = sv*dt2/m;
00209 
00210     Q(6,6) = sw*dt/J(0);
00211     Q(7,7) = sw*dt/J(1);
00212     Q(8,8) = sw*dt/J(2);
00213     Q(9,9) = sv*dt/m;
00214     Q(10,10) = sv*dt/m;
00215     Q(11,11) = sv*dt/m;
00216     return true;
00217   }
00218 
00219   
00220   
00221   static void Gcay(Matrix3d& m1, const Vector3d &w, const Vector3d &J, double h, bool plus = true) {
00222     SO3 &so3 = SO3::Instance();
00223     Matrix3d wh;
00224     so3.hat(wh, w);
00225     
00226     Matrix3d Jwh;
00227     Vector3d Jw = J.cwiseProduct(w);
00228     so3.hat(Jwh, Jw);
00229     
00230     int s = (plus ? 1 : -1);
00231     
00232     m1 =  (so3.Id + ((h*h/2)*w)*w.transpose())*J.asDiagonal() + (s*h/2)*(-Jwh + wh*J.asDiagonal()) + (h*h/4*w.dot(Jw))*so3.Id;
00233     /*
00234       m << J1*((h^2*v1^2)/4 + 1) + (J1*h^2*v1^2)/2 + (J2*h^2*v2^2)/4 + (J3*h^2*v3^2)/4,  J2*((v1*v2*h^2)/4 + (v3*h)/2) - (J3*h*v3)/2 + (J2*h^2*v1*v2)/4,              (J2*h*v2)/2 - J3*((h*v2)/2 - (h^2*v1*v3)/4) + (J3*h^2*v1*v3)/4]
00235       [              (J3*h*v3)/2 - J1*((h*v3)/2 - (h^2*v1*v2)/4) + (J1*h^2*v1*v2)/4, J2*((h^2*v2^2)/4 + 1) + (J1*h^2*v1^2)/4 + (J2*h^2*v2^2)/2 + (J3*h^2*v3^2)/4,              J3*((v2*v3*h^2)/4 + (v1*h)/2) - (J1*h*v1)/2 + (J3*h^2*v2*v3)/4]
00236       [              J1*((v1*v3*h^2)/4 + (v2*h)/2) - (J2*h*v2)/2 + (J1*h^2*v1*v3)/4,              (J1*h*v1)/2 - J2*((h*v1)/2 - (h^2*v2*v3)/4) + (J2*h^2*v2*v3)/4, J3*((h^2*v3^2)/4 + 1) + (J1*h^2*v1^2)/4 + (J2*h^2*v2^2)/4 + (J3*h^2*v3^2)/2]
00237       
00238     */
00239   }
00240 
00241   template <int c>
00242     double Body3d<c>::Step(Body3dState &xb, double t, const Body3dState &xa, 
00243                            const Matrix<double, c, 1> &u, double h, const VectorXd *p,
00244                            Matrix12d *A, Matrix<double, 12, c> *B, Matrix12Xd *C) {
00245     if (symp)
00246       return SympStep(t, xb, xa, u, h, p, A, B, C);
00247     else
00248       return EulerStep(t, xb, xa, u, h, p, A, B, C);      
00249   }
00250   
00251   template <int c>
00252     double Body3d<c>::SympStep(double t, Body3dState &xb, const Body3dState &xa, 
00253                                const Matrix<double, c, 1> &u, double h, const VectorXd *p,
00254                                Matrix12d *A, Matrix<double, 12, c> *B, Matrix12Xd *C) {
00255     // cwiseProduct
00256     
00257     SO3 &so3 = SO3::Instance();
00258     
00259     const Matrix3d &Ra = xa.first;  
00260     const Vector3d &pa = xa.second.head<3>();
00261     const Vector3d &wa = xa.second.segment<3>(3);
00262     const Vector3d &va = xa.second.tail<3>();
00263     
00264     Matrix3d &Rb = xb.first;
00265     
00266     Matrix3d Da, Db;
00267     
00268     // initialize wb
00269     Vector3d wb = wa;
00270     so3.dcayinv(Da, -h*wa);
00271     so3.dcayinv(Db, h*wb);
00272     
00273     Vector3d Jwa = J.cwiseProduct(wa);
00274     Vector3d Jwb = J.cwiseProduct(wb);
00275     
00276     Vector3d fuw = Bu.topRows(3)*u;
00277     Vector3d fwd = Db.transpose()*Jwb - Da.transpose()*Jwa - h*fuw;
00278     
00279     Matrix3d Gp;
00280     Gcay(Gp, wb, J, h);
00281     
00282     Matrix3d Gm;
00283     Gcay(Gm, wa, J, h, false);
00284     
00285     // Newton step
00286     Matrix3d Gi = Gp.inverse();
00287     wb = wb - Gi*fwd;
00288     //    wb = wa + Jwa.cross(wa) + h*fuw;
00289 
00290     // update Gi
00291     Gcay(Gp, wb, J, h);
00292     Gi = Gp.inverse();
00293     
00294     Matrix3d chwb;
00295     so3.cay(chwb, h*wb);
00296     Rb = Ra*chwb;
00297     
00298     Vector3d fuv = Bu.bottomRows(3)*u;
00299 
00300     const Matrix3d &I3 = Matrix3d::Identity();
00301 
00302     Vector3d vb;
00303     Vector3d pb;
00304 
00305     bool vdamp = (Dv.norm() > 1e-16); // is there linear velocity damping
00306     // modified mass matrix to include damping
00307     Matrix3d Mp;
00308     Matrix3d Mm;    
00309 
00310     if (vdamp) {
00311       Mp = I3*m + h/2*(Ra*Dv.asDiagonal());
00312       Mm = I3*m - h/2*(Ra*Dv.asDiagonal());
00313 
00314       vb = Mp.inverse()*(Mm*va + h*(fp + Ra*fuv));    
00315       pb = pa + h*vb;
00316     } else {
00317       vb = va + h/m*(fp + Ra*fuv);    
00318       pb = pa + h*vb;
00319     }
00320     
00321     xb.second.head<3>() = pb;
00322     xb.second.segment<3>(3) = wb;
00323     xb.second.tail<3>() = vb;
00324 
00325     //    return 1;
00326         
00327     if (A) {
00328       Matrix6d D1;
00329       D1.setZero();
00330       D1.topLeftCorner<3,3>() = -Gm;
00331       D1.bottomRightCorner<3,3>() = -m*I3;
00332       
00333       Matrix6d D2;
00334       D2.setZero();
00335       Matrix3d fuvh; 
00336       so3.hat(fuvh, fuv);
00337       D2.bottomLeftCorner<3,3>() = h*Ra*fuvh;
00338       
00339       Matrix6xcd D3; 
00340       D3.topRows(3) = -h*Bu.topRows(3);
00341       D3.bottomRows(3) = -h*Ra*Bu.bottomRows(3);
00342 
00343       Matrix3d cb;
00344       so3.cay(cb, -h*wb);
00345       
00346       Matrix3d Adcb;
00347       so3.Ad(Adcb, cb);
00348       
00349       Matrix3d dcb;
00350       so3.dcay(dcb, -h*wb);
00351       
00352       Matrix12d A1;
00353       A1.setZero();
00354       A1.topLeftCorner<3,3>() = Adcb;
00355       A1.block<3,3>(3,3) = I3;
00356       A1.block<3,3>(0,6) = h*dcb*Gi;
00357       A1.block<3,3>(3,9) = (h/m)*I3;
00358       
00359       A1.block<3,3>(6,6) = Gi;
00360       A1.block<3,3>(9,9) = I3/m;
00361       
00362       Matrix12d A2;
00363       A2.setIdentity();
00364       A2.block<6,6>(6,0) = -D2;
00365       A2.block<6,6>(6,6) = -D1;
00366       
00367       (*A) = A1*A2;
00368       
00369       if (B) {
00370         (*B) = -A1.rightCols<6>()*D3;
00371       }
00372     }
00373     return 1;
00374   }
00375 
00376   template <int c>
00377     double Body3d<c>::EulerStep(double t, Body3dState &xb, const Body3dState &xa, 
00378                                 const Matrix<double, c, 1> &u, double h, const VectorXd *p,
00379                                 Matrix12d *A, Matrix<double, 12, c> *B, Matrix12Xd *C) {
00380     // cwiseProduct
00381     
00382     SO3 &so3 = SO3::Instance();
00383     
00384     const Matrix3d &Ra = xa.first;  
00385     const Vector3d &pa = xa.second.head<3>();
00386     const Vector3d &wa = xa.second.segment<3>(3);
00387     const Vector3d &va = xa.second.tail<3>();
00388     
00389     Matrix3d &Rb = xb.first;
00390 
00391     Vector3d Jwa = J.cwiseProduct(wa);
00392 
00393     Vector3d wb = wa + h*(Jwa.cross(wa) + Dw.cwiseProduct(wa) + Bu.topRows(3)*u).cwiseQuotient(J);
00394     
00395     Matrix3d chwb;
00396     so3.cay(chwb, h*wb);
00397     Rb = Ra*chwb;
00398     
00399     Vector3d fuv = Dv.cwiseProduct(Ra.transpose()*va) + Bu.bottomRows(3)*u;
00400 
00401     Vector3d vb = va + h/m*(fp + Ra*fuv);
00402     
00403     xb.second.head<3>() = pa + h*vb;
00404     xb.second.segment<3>(3) = wb;
00405     xb.second.tail<3>() = vb;
00406 
00407     Matrix3d Jwah;
00408     so3.hat(Jwah, Jwa);
00409 
00410     Matrix3d wah;
00411     so3.hat(wah, wa);
00412     
00413     const Matrix3d &I3 = Matrix3d::Identity();
00414     
00415     if (A) {
00416       Matrix6d D1;
00417       D1.setZero();
00418       D1.topLeftCorner<3,3>() = -Matrix3d(J.asDiagonal()) - h*(Jwah + Matrix3d(Dw.asDiagonal())) + wah*(J.asDiagonal());
00419       D1.bottomRightCorner<3,3>() = -m*I3;
00420       
00421       Matrix6d D2;
00422       D2.setZero();
00423       Matrix3d fuvh;
00424       so3.hat(fuvh, fuv);
00425       D2.bottomLeftCorner<3,3>() = h*Ra*fuvh;
00426       
00427       Matrix6xcd D3;
00428       D3.topRows(3) = -h*Bu.topRows(3);
00429       D3.bottomRows(3) = -h*Ra*Bu.bottomRows(3);
00430 
00431       Matrix3d cb;
00432       so3.cay(cb, -h*wb);
00433       
00434       Matrix3d Adcb;
00435       so3.Ad(Adcb, cb);
00436       
00437       Matrix3d dcb;
00438       so3.dcay(dcb, -h*wb);
00439       
00440       Matrix12d A1;
00441       A1.setZero();
00442       A1.topLeftCorner<3,3>() = Adcb;
00443       A1.block<3,3>(3,3) = I3;
00444       A1.block<3,3>(0,6) = h*dcb*J.asDiagonal().inverse();
00445       A1.block<3,3>(3,9) = (h/m)*I3;
00446       
00447       A1.block<3,3>(6,6) = J.asDiagonal().inverse();
00448       A1.block<3,3>(9,9) = I3/m;
00449       
00450       Matrix12d A2;
00451       A2.setIdentity();
00452       A2.block<3,3>(0,0).diagonal() -= h*Dw.cwiseQuotient(J);
00453       A2.block<3,3>(3,3) -= (h/m)*Ra*Dv.asDiagonal()*Ra;
00454       A2.block<6,6>(6,0) = -D2;
00455       A2.block<6,6>(6,6) = -D1;
00456       
00457       (*A) = A1*A2;
00458       
00459       if (B) {
00460         (*B) = -A1.rightCols<6>()*D3;
00461       }
00462     }
00463     return 1;
00464   }
00465 
00466 
00467 
00468 
00469   template <int c>   
00470     void Body3d<c>::ID(Vector6d &f,
00471                        double t, const Body3dState &xb, const Body3dState &xa,
00472                        const Vectorcd &u, double h) {
00473   }
00474 
00475   template <int c>
00476     void Body3d<c>::StateAndControlsToFlat(VectorXd &y, const Body3dState &x,
00477                const Vectorcd &u) {
00478     SO3& so3 = SO3::Instance();
00479 
00480     // Flat outputs are x,y,z, and rpy
00481     y.resize(6);
00482     y.head<3>() = x.second.head<3>();
00483     y(3) = so3.roll(x.first);
00484     y(4) = so3.pitch(x.first);
00485     y(5) = so3.yaw(x.first);
00486   }
00487 
00488   template <int c>
00489     void Body3d<c>::FlatToStateAndControls(Body3dState &x, Vectorcd &u,
00490                const std::vector<VectorXd> &y) {
00491     assert(y.size() >= 2);
00492 
00493     SO3& so3 = SO3::Instance();
00494 
00495     VectorXd y0 = y[0];
00496     VectorXd y1 = y[1];
00497 
00498     x.first.setZero();
00499     x.second.setZero();
00500     u.setZero();
00501 
00502     so3.q2g(x.first, y0.tail<3>());
00503 
00504     x.second.head<3>() = y0.head<3>();
00505     x.second.tail<3>() = y1.head<3>();
00506     // TODO: fill in angular velocity and controls
00507     x.second(5) = y1(5);
00508   }
00509 }
00510 #endif
00511 
00512 
00513 
00514 /*
00515 
00516 for reference: properties that ROS uses
00517 
00518 class Geometry
00519 {
00520 public:
00521   enum {SPHERE, BOX, CYLINDER, MESH} type;
00522 };
00523 
00524 class Sphere : public Geometry
00525 {
00526 public:
00527   Sphere() { this->clear(); };
00528   double radius;
00529   void clear()
00530   {
00531     radius = 0;
00532   };
00533 };
00534 
00535 class Box : public Geometry
00536 {
00537 public:
00538   Box() { this->clear(); };
00539   Vector3d dim;
00540 
00541   void clear()
00542   {
00543     dim << 1, 1, 1;
00544   };
00545 };
00546 
00547 class Cylinder : public Geometry
00548 {
00549 public:
00550   Cylinder() { this->clear(); };
00551   double length;
00552   double radius;
00553   
00554   void clear()
00555   {
00556     length = 0;
00557     radius = 0;
00558   };
00559 };
00560 
00561 class Mesh : public Geometry
00562 {
00563 public:
00564   Mesh() { this->clear(); };
00565   std::string filename;
00566   Vector3d scale;
00567 
00568   void clear()
00569   {
00570     filename.clear();
00571     scale << 1,1,1;
00572   };
00573   //  bool initXml(TiXmlElement *);
00574   //  bool fileExists(std::string filename);
00575 };
00576 
00577 
00578 class Material
00579 {
00580 public:
00581   Material() { this->clear(); };
00582   std::string name;
00583   std::string texture_filename;
00584   Vector4d color;
00585 
00586   void clear()
00587   {
00588     color << .5, .5, .5, .5;
00589     texture_filename.clear();
00590     name.clear();
00591   };
00592   //  bool initXml(TiXmlElement* config);
00593 };
00594 class Visual
00595 {
00596 public:
00597   Visual() { this->clear(); };
00598   Matrix4d origin;
00599   boost::shared_ptr<Geometry> geometry;
00600 
00601   std::string material_name;
00602   boost::shared_ptr<Material> material;
00603 
00604   void clear()
00605   {
00606     origin.setIdentity();
00607     material_name.clear();
00608     material.reset();
00609     geometry.reset();
00610     this->group_name.clear();
00611   };
00612   //  bool initXml(TiXmlElement* config);
00613   std::string group_name;
00614 };
00615 
00616 
00617 class Collision
00618 {
00619 public:
00620   Collision() { this->clear(); };
00621   Matrix4d origin;
00622   //  Pose origin;
00623   boost::shared_ptr<Geometry> geometry;
00624 
00625   void clear()
00626   {
00627     origin.setIdentity();
00628     geometry.reset();
00629     this->group_name.clear();
00630   };
00631   //  bool initXml(TiXmlElement* config);
00632   std::string group_name;
00633 };
00634 */