euler_converter.cc
Go to the documentation of this file.
00001 /******************************************************************************
00002 Copyright (c) 2018, Alexander W. Winkler. All rights reserved.
00003 
00004 Redistribution and use in source and binary forms, with or without
00005 modification, are permitted provided that the following conditions are met:
00006 
00007 * Redistributions of source code must retain the above copyright notice, this
00008   list of conditions and the following disclaimer.
00009 
00010 * Redistributions in binary form must reproduce the above copyright notice,
00011   this list of conditions and the following disclaimer in the documentation
00012   and/or other materials provided with the distribution.
00013 
00014 * Neither the name of the copyright holder nor the names of its
00015   contributors may be used to endorse or promote products derived from
00016   this software without specific prior written permission.
00017 
00018 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00019 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00020 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00021 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
00022 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00023 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
00024 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00025 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00026 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00027 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
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   // convert to sparse, but also regard 0.0 as non-zero element, because
00092   // could turn nonzero during the course of the program
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   // convert to sparse, but also regard 0.0 as non-zero element, because
00112   // could turn nonzero during the course of the program
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   // Euler ZYX rates to angular velocity
00141   // http://docs.leggedrobotics.com/kindr/cheatsheet_latest.pdf
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: // basically derivative of top row (3 elements) of matrix M
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: // middle row of M
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: // bottom row of M
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   //  http://docs.leggedrobotics.com/kindr/cheatsheet_latest.pdf (Euler ZYX)
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       // since for every rotation matrix R^(-1) = R^T, just swap rows and
00234       // columns for calculation of derivative of inverse rotation matrix
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: // derivative of top row (3 elements) of matrix M-dot
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: // middle row of M
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: // bottom Row of M
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 } /* namespace towr */


towr_core
Author(s): Alexander W. Winkler
autogenerated on Mon Apr 9 2018 03:12:44