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 }