00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 #include <labust/simulation/RBModel.hpp>
00038 #include <labust/math/NumberManipulation.hpp>
00039 
00040 using namespace labust::simulation;
00041 
00042 RBModel::RBModel():
00043     ae(0.15),be(0.2),ce(0.2),
00044     B(0),
00045     dT(0.1),
00046     waterLevel(0),
00047     nu0(vector::Zero()),
00048     eta0(vector::Zero()),
00049     nu(vector::Zero()),
00050     eta(vector::Zero()),
00051     g(vector::Zero()),
00052     isCoupled(false),
00053     current(vector3::Zero())
00054         {this->init();};
00055 
00056 RBModel::~RBModel(){};
00057 
00058 void RBModel::calculate_mrb()
00059 {
00060         using namespace labust::math;
00061         Mrb.block<3,3>(0,0) = m*matrix3::Identity();
00062         Mrb.block<3,3>(0,3) = -m*skewSymm3(rg);
00063         Mrb.block<3,3>(3,0) = -m*skewSymm3(rg);
00064         Mrb.block<3,3>(3,3) = Io;
00065 }
00066 
00067 void RBModel::step(const vector& tau)
00068 {
00069         
00070         using namespace Eigen;
00071         matrix3 J1;
00072         J1 = AngleAxisd(eta(psi), Vector3d::UnitZ())
00073                         * AngleAxisd(eta(theta), Vector3d::UnitY())
00074                         * AngleAxisd(eta(phi), Vector3d::UnitX());
00075         double c1 = cos(eta(phi)), s1 = sin(eta(phi));
00076         double c2 = cos(eta(theta)), t2 = tan(eta(theta));
00077         if (!c2) c2 = 0.1;
00078         matrix3 J2;
00079         J2<<1,s1*t2,c1*t2,
00080                         0,c1,-s1,
00081                         0,s1/c2,c1/c2;
00082         
00083         restoring_force(J1);
00084 
00085         matrix M = Ma + Mrb;
00086         vector nu_old(nu);
00087         if (isCoupled)
00088         {
00089                 
00090                 coriolis();
00091                 
00092                 matrix CD = Ca + Crb + Dlin + Dquad*nu.cwiseAbs2().asDiagonal();
00093                 FullPivLU<matrix> decomp(M+dT*CD);
00094                 if (decomp.isInvertible())
00095                 {
00096                         
00097                         nu = decomp.inverse()*(M*nu + dT*(tau-g));
00098                 }
00099                 else
00100                 {
00101                         std::cerr<<"Mass matrix is singular."<<std::endl;
00102                 }
00103         }
00104         else
00105         {
00106                 
00107                 for (size_t i=0; i<nu.size(); ++i)
00108                 {
00109                         double beta = Dlin(i,i) + Dquad(i,i)*fabs(nu(i));
00110                         
00111                         nu(i) = (M(i,i)*nu(i) + dT*(tau(i)- g(i)))/(M(i,i) + dT*beta);
00112                 };
00113         }
00114         nuacc = (nu - nu_old)/dT;
00115 
00116         
00117         eta.block<3,1>(0,0) += dT*(J1*nu.block<3,1>(0,0)+current);
00118         eta.block<3,1>(3,0) += dT*J2*nu.block<3,1>(3,0);
00119 }
00120 
00121 void RBModel::coriolis()
00122 {
00123         using namespace labust::math;
00124         
00125         vector3 nu1 = nu.block<3,1>(0,0);
00126         vector3 nu2 = nu.block<3,1>(3,0);
00127 
00128         Crb.block<3,3>(0,3) = -m*skewSymm3(nu1) - m*skewSymm3(nu2)*skewSymm3(rg);
00129         Crb.block<3,3>(3,0) = -m*skewSymm3(nu1) + m*skewSymm3(rg)*skewSymm3(nu2);
00130         Crb.block<3,3>(3,3) = -skewSymm3(Io*nu2);
00131 
00132         matrix3 M11=Ma.block<3,3>(0,0);
00133         matrix3 M12=Ma.block<3,3>(0,3);
00134         matrix3 M21=Ma.block<3,3>(3,0);
00135         matrix3 M22=Ma.block<3,3>(3,3);
00136 
00137         Ca.block<3,3>(0,3) = -skewSymm3(M11*nu1 + M12*nu2);
00138         Ca.block<3,3>(3,0) = -skewSymm3(M11*nu1 + M21*nu2);
00139         Ca.block<3,3>(3,3) = -skewSymm3(M21*nu1 + M22*nu2);
00140 }
00141 
00142 void RBModel::restoring_force(const matrix3& J1)
00143 {
00144         matrix3 invJ1;
00145         invJ1=J1.inverse();
00146 
00147         
00148         
00149         B=2*labust::math::coerce((eta(z)+waterLevel+rb(z)/2)/ce+1,0,2)*M_PI/3*ae*be*ce*rho*g_acc;
00150 
00151         vector3 fg = invJ1*(m*g_acc*vector3::UnitZ());
00152         vector3 fb = -invJ1*(B*vector3::UnitZ());
00153 
00154         g.block<3,1>(0,0) = -fg-fb;
00155         g.block<3,1>(3,0) = -skewSymm3(rg)*fg-skewSymm3(rb)*fb;
00156 }