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 #include <towr/variables/euler_converter.h>
00031 
00032 #include <cassert>
00033 #include <cmath>
00034 
00035 namespace towr {
00036 
00037 
00038 EulerConverter::EulerConverter (const NodeSpline::Ptr& euler)
00039 {
00040   euler_ = euler;
00041   jac_wrt_nodes_structure_ = Jacobian(k3D, euler->GetNodeVariablesCount());
00042 }
00043 
00044 Eigen::Quaterniond
00045 EulerConverter::GetQuaternionBaseToWorld (double t) const
00046 {
00047   State ori = euler_->GetPoint(t);
00048   return GetQuaternionBaseToWorld(ori.p());
00049 }
00050 
00051 Eigen::Quaterniond
00052 EulerConverter::GetQuaternionBaseToWorld (const EulerAngles& pos)
00053 {
00054   Eigen::Matrix3d R_WB = GetRotationMatrixBaseToWorld(pos);
00055   return Eigen::Quaterniond(R_WB);
00056 }
00057 
00058 Eigen::Vector3d
00059 EulerConverter::GetAngularVelocityInWorld (double t) const
00060 {
00061   State ori = euler_->GetPoint(t);
00062   return GetAngularVelocityInWorld(ori.p(), ori.v());
00063 }
00064 
00065 Eigen::Vector3d
00066 EulerConverter::GetAngularVelocityInWorld (const EulerAngles& pos,
00067                                            const EulerRates& vel)
00068 {
00069   return GetM(pos)*vel;
00070 }
00071 
00072 Eigen::Vector3d
00073 EulerConverter::GetAngularAccelerationInWorld (double t) const
00074 {
00075   State ori = euler_->GetPoint(t);
00076   return GetAngularAccelerationInWorld(ori);
00077 }
00078 
00079 Eigen::Vector3d
00080 EulerConverter::GetAngularAccelerationInWorld (State ori)
00081 {
00082   return GetMdot(ori.p(), ori.v())*ori.v() + GetM(ori.p())*ori.a();
00083 }
00084 
00085 EulerConverter::Jacobian
00086 EulerConverter::GetDerivOfAngVelWrtEulerNodes(double t) const
00087 {
00088   Jacobian jac = jac_wrt_nodes_structure_;
00089 
00090   State ori = euler_->GetPoint(t);
00091   
00092   
00093   JacobianRow vel = ori.v().transpose().sparseView(1.0, -1.0);
00094   Jacobian dVel_du  = euler_->GetJacobianWrtNodes(t, kVel);
00095 
00096   for (auto dim : {X,Y,Z}) {
00097     Jacobian dM_du = GetDerivMwrtNodes(t,dim);
00098     jac.row(dim) = vel*dM_du + GetM(ori.p()).row(dim)*dVel_du;
00099   }
00100 
00101   return jac;
00102 }
00103 
00104 EulerConverter::Jacobian
00105 EulerConverter::GetDerivOfAngAccWrtEulerNodes (double t) const
00106 {
00107   Jacobian jac = jac_wrt_nodes_structure_;
00108 
00109 
00110   State ori = euler_->GetPoint(t);
00111   
00112   
00113   JacobianRow vel = ori.v().transpose().sparseView(1.0, -1.0);
00114   JacobianRow acc = ori.a().transpose().sparseView(1.0, -1.0);
00115 
00116   Jacobian dVel_du  = euler_->GetJacobianWrtNodes(t, kVel);
00117   Jacobian dAcc_du  = euler_->GetJacobianWrtNodes(t, kAcc);
00118 
00119 
00120   for (auto dim : {X,Y,Z}) {
00121 
00122     Jacobian dMdot_du = GetDerivMdotwrtNodes(t,dim);
00123     Jacobian dM_du    = GetDerivMwrtNodes(t,dim);
00124 
00125     jac.row(dim) = vel                               * dMdot_du
00126                    + GetMdot(ori.p(), ori.v()).row(dim)* dVel_du
00127                    + acc                             * dM_du
00128                    + GetM(ori.p()).row(dim)           * dAcc_du;
00129   }
00130 
00131   return jac;
00132 }
00133 
00134 EulerConverter::MatrixSXd
00135 EulerConverter::GetM (const EulerAngles& xyz)
00136 {
00137   double z = xyz(Z);
00138   double y = xyz(Y);
00139 
00140   
00141   
00142   Jacobian M(k3D, k3D);
00143 
00144                   M.coeffRef(0,Y) = -sin(z);  M.coeffRef(0,X) =  cos(y)*cos(z);
00145                   M.coeffRef(1,Y) =  cos(z);  M.coeffRef(1,X) =  cos(y)*sin(z);
00146   M.coeffRef(2,Z) = 1.0;                      M.coeffRef(2,X) =  -sin(y);
00147 
00148   return M;
00149 }
00150 
00151 EulerConverter::MatrixSXd
00152 EulerConverter::GetMdot (const EulerAngles& xyz,
00153                          const EulerRates& xyz_d)
00154 {
00155   double z  = xyz(Z);
00156   double zd = xyz_d(Z);
00157   double y  = xyz(Y);
00158   double yd = xyz_d(Y);
00159 
00160   Jacobian Mdot(k3D, k3D);
00161 
00162   Mdot.coeffRef(0,Y) = -cos(z)*zd; Mdot.coeffRef(0,X) = -cos(z)*sin(y)*yd - cos(y)*sin(z)*zd;
00163   Mdot.coeffRef(1,Y) = -sin(z)*zd; Mdot.coeffRef(1,X) =  cos(y)*cos(z)*zd - sin(y)*sin(z)*yd;
00164                             Mdot.coeffRef(2,X) = -cos(y)*yd;
00165 
00166  return Mdot;
00167 }
00168 
00169 EulerConverter::Jacobian
00170 EulerConverter::GetDerivMwrtNodes (double t, Dim3D ang_acc_dim) const
00171 {
00172   State ori = euler_->GetPoint(t);
00173 
00174   double z = ori.p()(Z);
00175   double y = ori.p()(Y);
00176   JacobianRow jac_z = GetJac(t, kPos, Z);
00177   JacobianRow jac_y = GetJac(t, kPos, Y);
00178 
00179   Jacobian jac = jac_wrt_nodes_structure_;
00180 
00181   switch (ang_acc_dim) {
00182     case X: 
00183       jac.row(Y) = -cos(z)*jac_z;
00184       jac.row(X) = -cos(z)*sin(y)*jac_y - cos(y)*sin(z)*jac_z;
00185       break;
00186     case Y: 
00187       jac.row(Y) = -sin(z)*jac_z;
00188       jac.row(X) = cos(y)*cos(z)*jac_z - sin(y)*sin(z)*jac_y;
00189       break;
00190     case Z: 
00191       jac.row(X) = -cos(y)*jac_y;
00192       break;
00193     default:
00194       assert(false);
00195       break;
00196   }
00197 
00198   return jac;
00199 }
00200 
00201 EulerConverter::MatrixSXd
00202 EulerConverter::GetRotationMatrixBaseToWorld (double t) const
00203 {
00204   State ori = euler_->GetPoint(t);
00205   return GetRotationMatrixBaseToWorld(ori.p());
00206 }
00207 
00208 EulerConverter::MatrixSXd
00209 EulerConverter::GetRotationMatrixBaseToWorld (const EulerAngles& xyz)
00210 {
00211   double x = xyz(X);
00212   double y = xyz(Y);
00213   double z = xyz(Z);
00214 
00215   Eigen::Matrix3d M;
00216   
00217   M << cos(y)*cos(z), cos(z)*sin(x)*sin(y) - cos(x)*sin(z), sin(x)*sin(z) + cos(x)*cos(z)*sin(y),
00218        cos(y)*sin(z), cos(x)*cos(z) + sin(x)*sin(y)*sin(z), cos(x)*sin(y)*sin(z) - cos(z)*sin(x),
00219              -sin(y),                        cos(y)*sin(x),                        cos(x)*cos(y);
00220 
00221   return M.sparseView(1.0, -1.0);
00222 }
00223 
00224 EulerConverter::Jacobian
00225 EulerConverter::DerivOfRotVecMult (double t, const Vector3d& v, bool inverse) const
00226 {
00227   JacRowMatrix Rd = GetDerivativeOfRotationMatrixWrtNodes(t);
00228   Jacobian jac = jac_wrt_nodes_structure_;
00229 
00230   for (int row : {X,Y,Z}) {
00231     for (int col : {X, Y, Z}) {
00232 
00233       
00234       
00235       JacobianRow jac_row = inverse? Rd.at(col).at(row) : Rd.at(row).at(col);
00236       jac.row(row) += v(col)*jac_row;
00237     }
00238   }
00239 
00240   return jac;
00241 }
00242 
00243 EulerConverter::JacRowMatrix
00244 EulerConverter::GetDerivativeOfRotationMatrixWrtNodes (double t) const
00245 {
00246   JacRowMatrix jac;
00247 
00248   State ori = euler_->GetPoint(t);
00249   double x = ori.p()(X);
00250   double y = ori.p()(Y);
00251   double z = ori.p()(Z);
00252 
00253   JacobianRow jac_x = GetJac(t, kPos, X);
00254   JacobianRow jac_y = GetJac(t, kPos, Y);
00255   JacobianRow jac_z = GetJac(t, kPos, Z);
00256 
00257   jac.at(X).at(X) = -cos(z)*sin(y)*jac_y - cos(y)*sin(z)*jac_z;
00258   jac.at(X).at(Y) =  sin(x)*sin(z)*jac_x - cos(x)*cos(z)*jac_z - sin(x)*sin(y)*sin(z)*jac_z + cos(x)*cos(z)*sin(y)*jac_x + cos(y)*cos(z)*sin(x)*jac_y;
00259   jac.at(X).at(Z) =  cos(x)*sin(z)*jac_x + cos(z)*sin(x)*jac_z - cos(z)*sin(x)*sin(y)*jac_x - cos(x)*sin(y)*sin(z)*jac_z + cos(x)*cos(y)*cos(z)*jac_y;
00260 
00261   jac.at(Y).at(X) = cos(y)*cos(z)*jac_z - sin(y)*sin(z)*jac_y;
00262   jac.at(Y).at(Y) = cos(x)*sin(y)*sin(z)*jac_x - cos(x)*sin(z)*jac_z - cos(z)*sin(x)*jac_x + cos(y)*sin(x)*sin(z)*jac_y + cos(z)*sin(x)*sin(y)*jac_z;
00263   jac.at(Y).at(Z) = sin(x)*sin(z)*jac_z - cos(x)*cos(z)*jac_x - sin(x)*sin(y)*sin(z)*jac_x + cos(x)*cos(y)*sin(z)*jac_y + cos(x)*cos(z)*sin(y)*jac_z;
00264 
00265   jac.at(Z).at(X) = -cos(y)*jac_y;
00266   jac.at(Z).at(Y) =  cos(x)*cos(y)*jac_x - sin(x)*sin(y)*jac_y;
00267   jac.at(Z).at(Z) = -cos(y)*sin(x)*jac_x - cos(x)*sin(y)*jac_y;
00268 
00269   return jac;
00270 }
00271 
00272 EulerConverter::Jacobian
00273 EulerConverter::GetDerivMdotwrtNodes (double t, Dim3D ang_acc_dim) const
00274 {
00275   State ori = euler_->GetPoint(t);
00276 
00277   double z  = ori.p()(Z);
00278   double zd = ori.v()(Z);
00279   double y  = ori.p()(Y);
00280   double yd = ori.v()(Y);
00281 
00282   JacobianRow jac_z  = GetJac(t, kPos, Z);
00283   JacobianRow jac_y  = GetJac(t, kPos, Y);
00284   JacobianRow jac_zd = GetJac(t, kVel, Z);
00285   JacobianRow jac_yd = GetJac(t, kVel, Y);
00286 
00287   Jacobian jac = jac_wrt_nodes_structure_;
00288   switch (ang_acc_dim) {
00289     case X: 
00290       jac.row(Y) = sin(z)*zd*jac_z - cos(z)*jac_zd;
00291       jac.row(X) = sin(y)*sin(z)*yd*jac_z - cos(y)*sin(z)*jac_zd - cos(y)*cos(z)*yd*jac_y - cos(y)*cos(z)*zd*jac_z - cos(z)*sin(y)*jac_yd + sin(y)*sin(z)*jac_y*zd;
00292       break;
00293     case Y: 
00294       jac.row(Y) = - sin(z)*jac_zd - cos(z)*zd*jac_z;
00295       jac.row(X) = cos(y)*cos(z)*jac_zd - sin(y)*sin(z)*jac_yd - cos(y)*sin(z)*yd*jac_y - cos(z)*sin(y)*yd*jac_z - cos(z)*sin(y)*jac_y*zd - cos(y)*sin(z)*zd*jac_z;
00296       break;
00297     case Z: 
00298       jac.row(X) = sin(y)*yd*jac_y - cos(y)*jac_yd;
00299       break;
00300     default:
00301       assert(false);
00302       break;
00303   }
00304 
00305   return jac;
00306 }
00307 
00308 EulerConverter::JacobianRow
00309 EulerConverter::GetJac (double t, Dx deriv, Dim3D dim) const
00310 {
00311   return euler_->GetJacobianWrtNodes(t, deriv).row(dim);
00312 }
00313 
00314 }