00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00026 #include "inertia_util.hpp"
00027 #include "tao_dump.hpp"
00028 #include <tao/dynamics/tao.h>
00029 #include <sstream>
00030
00031 using namespace std;
00032
00033 namespace jspace {
00034
00035
00036 void inertia_parallel_axis_transform(double in_ixx, double in_ixy, double in_ixz,
00037 double in_iyy, double in_iyz, double in_izz,
00038 double trans_x, double trans_y, double trans_z, double mass,
00039 double & out_ixx, double & out_ixy, double & out_ixz,
00040 double & out_iyy, double & out_iyz, double & out_izz)
00041 {
00042 double const xx(trans_x * trans_x);
00043 double const yy(trans_y * trans_y);
00044 double const zz(trans_z * trans_z);
00045
00046 out_ixx = in_ixx + mass * (yy + zz);
00047 out_iyy = in_iyy + mass * (xx + zz);
00048 out_izz = in_izz + mass * (xx + yy);
00049
00050 out_ixy = in_ixy - mass * (trans_x * trans_y);
00051 out_ixz = in_ixz - mass * (trans_x * trans_z);
00052 out_iyz = in_iyz - mass * (trans_y * trans_z);
00053 }
00054
00055
00056 void inertia_parallel_axis_transform(deMatrix3 const & in_inertia,
00057 deVector3 const & translation, double mass,
00058 deMatrix3 & out_inertia)
00059 {
00060 inertia_parallel_axis_transform(in_inertia.elementAt(0, 0),
00061 in_inertia.elementAt(0, 1),
00062 in_inertia.elementAt(0, 2),
00063 in_inertia.elementAt(1, 1),
00064 in_inertia.elementAt(1, 2),
00065 in_inertia.elementAt(2, 2),
00066 translation[0],
00067 translation[1],
00068 translation[2],
00069 mass,
00070 out_inertia.elementAt(0, 0),
00071 out_inertia.elementAt(0, 1),
00072 out_inertia.elementAt(0, 2),
00073 out_inertia.elementAt(1, 1),
00074 out_inertia.elementAt(1, 2),
00075 out_inertia.elementAt(2, 2));
00076 }
00077
00078
00079 void inertia_similarity_transform(double in_ixx, double in_ixy, double in_ixz,
00080 double in_iyy, double in_iyz, double in_izz,
00081 deQuaternion const & rotation,
00082 deMatrix3 & out_inertia)
00083 {
00084 out_inertia.set(in_ixx, in_ixy, in_ixz,
00085 in_ixy, in_iyy, in_iyz,
00086 in_ixz, in_iyz, in_izz);
00087 deMatrix3 aa, bb, cc;
00088 aa.set(rotation);
00089 bb.transpose(aa);
00090 cc.multiply(aa, out_inertia);
00091 aa.multiply(cc, bb);
00092
00093 out_inertia = aa;
00094 }
00095
00096
00097 void inertia_similarity_transform(deMatrix3 const & in_inertia,
00098 deQuaternion const & rotation,
00100 deMatrix3 & out_inertia)
00101 {
00102 inertia_similarity_transform(in_inertia.elementAt(0, 0), in_inertia.elementAt(0, 1), in_inertia.elementAt(0, 2),
00103 in_inertia.elementAt(1, 1), in_inertia.elementAt(1, 2), in_inertia.elementAt(2, 2),
00104 rotation, out_inertia);
00105 }
00106
00107
00108 void inertia_similarity_transform(double in_ixx, double in_ixy, double in_ixz,
00109 double in_iyy, double in_iyz, double in_izz,
00110 double rot_qx, double rot_qy, double rot_qz, double rot_qw,
00111 double & out_ixx, double & out_ixy, double & out_ixz,
00112 double & out_iyy, double & out_iyz, double & out_izz)
00113 {
00114 deQuaternion quat;
00115 quat.set(rot_qx, rot_qy, rot_qz, rot_qw);
00116 deMatrix3 out;
00117 inertia_similarity_transform(in_ixx, in_ixy, in_ixz, in_iyy, in_iyz, in_izz, quat, out);
00118 out_ixx = out.elementAt(0, 0);
00119 out_ixy = out.elementAt(0, 1);
00120 out_ixz = out.elementAt(0, 2);
00121 out_iyy = out.elementAt(1, 1);
00122 out_iyz = out.elementAt(1, 2);
00123 out_izz = out.elementAt(2, 2);
00124 }
00125
00126
00127 void fuse_mass_properties(double orig_mass, deMatrix3 const & orig_inertia, deFrame const & orig_com,
00128 double adtl_mass, deMatrix3 const & adtl_inertia, deFrame const & adtl_com,
00129 deFrame const & home_of_adtl_wrt_orig,
00130 double & fused_mass, deMatrix3 & fused_inertia, deFrame & fused_com)
00131 {
00139
00141
00142
00144 fused_mass = orig_mass + adtl_mass;
00148
00150
00151
00153 deFrame adtl_com_wrt_o;
00154 adtl_com_wrt_o.multiply(home_of_adtl_wrt_orig, deFrame(adtl_com));
00155 fused_com.translation() = orig_com.translation();
00156 fused_com.translation() *= orig_mass / fused_mass;
00157 {
00158 deVector3 bar;
00159 bar = adtl_com_wrt_o.translation();
00160 bar *= adtl_mass / fused_mass;
00161 fused_com.translation() += bar;
00162 }
00163 fused_com.rotation() = orig_com.rotation();
00167
00169
00170
00172 deVector3 orig_to_new_com;
00173 orig_to_new_com = fused_com.translation();
00174 orig_to_new_com -= orig_com.translation();
00175 deMatrix3 orig_inertia_at_new_com;
00176 inertia_parallel_axis_transform(orig_inertia, orig_to_new_com, orig_mass, orig_inertia_at_new_com);
00180
00182
00183
00185 deMatrix3 adtl_inertia_at_new_com;
00186 inertia_similarity_transform(adtl_inertia,
00187 home_of_adtl_wrt_orig.rotation(),
00188 adtl_inertia_at_new_com);
00193
00195
00196
00197
00199 deVector3 adtl_to_new_com;
00200 adtl_to_new_com = adtl_com_wrt_o.translation();
00201 adtl_to_new_com -= fused_com.translation();
00202 inertia_parallel_axis_transform(adtl_inertia, adtl_to_new_com, adtl_mass, adtl_inertia_at_new_com);
00207
00209
00210
00211
00212
00214 fused_inertia = orig_inertia_at_new_com;
00215 fused_inertia += adtl_inertia_at_new_com;
00217 }
00218
00219
00220 void fuse_mass_properties(deMassProp & original,
00221 deMassProp & additional,
00222 deFrame const & home_of_additional_wrt_original,
00224 deMassProp & fused)
00225 {
00226 deFrame orig_com, adtl_com;
00227 orig_com.translation() = *original.center();
00228 adtl_com.translation() = *additional.center();
00229 double fused_mass;
00230 deMatrix3 fused_inertia;
00231 deFrame fused_com;
00232 fuse_mass_properties(*original.mass(), *original.inertia(), orig_com,
00233 *additional.mass(), *additional.inertia(), adtl_com,
00234 home_of_additional_wrt_original,
00235 fused_mass, fused_inertia, fused_com);
00236 fused.set(&fused_mass, &fused_com.translation(), &fused_inertia);
00237 }
00238
00239
00240 void mass_inertia_explicit_form(Model const & model, Matrix & mass_inertia,
00241 std::ostream * dbgos)
00242 throw(std::runtime_error)
00243 {
00244 size_t const ndof(model.getNDOF());
00245 mass_inertia = Matrix::Zero(ndof, ndof);
00246
00247 if (dbgos) {
00248 *dbgos << "jspace::mass_inertia_explicit_form()\n"
00249 << " ndof = " << ndof << "\n";
00250 }
00251
00252 for (size_t ii(0); ii < ndof; ++ii) {
00253
00254 if (dbgos) {
00255 *dbgos << " computing contributions of node " << ii << "\n";
00256 }
00257
00258 taoDNode * node(model.getNode(ii));
00259 if ( ! node) {
00260 ostringstream msg;
00261 msg << "jspace::mass_inertia_explicit_form(): no node for index " << ii;
00262 throw runtime_error(msg.str());
00263 }
00264
00265 Transform global_com;
00266 Matrix Jacobian;
00267 deVector3 const * com(node->center());
00268 if (com) {
00269 if ( ! model.computeGlobalFrame(node, com->elementAt(0), com->elementAt(1), com->elementAt(2), global_com)) {
00270 ostringstream msg;
00271 msg << "jspace::mass_inertia_explicit_form(): computeGlobalFrame() of COM failed for index " << ii;
00272 throw runtime_error(msg.str());
00273 }
00274 }
00275 else {
00276
00277 if ( ! model.getGlobalFrame(node, global_com)) {
00278 ostringstream msg;
00279 msg << "jspace::mass_inertia_explicit_form(): getGlobalFrame() failed for index " << ii;
00280 throw runtime_error(msg.str());
00281 }
00282 }
00283 if ( ! model.computeJacobian(node, global_com.translation(), Jacobian)) {
00284 ostringstream msg;
00285 msg << "jspace::mass_inertia_explicit_form(): computeJacobian() of COM failed for index " << ii;
00286 throw runtime_error(msg.str());
00287 }
00288
00289 if (dbgos) {
00290 if (com) {
00291 *dbgos << " local COM: " << *com << "\n";
00292 }
00293 else {
00294 *dbgos << " local COM: null\n";
00295 }
00296 *dbgos << " global COM: " << pretty_string(global_com.translation()) << "\n"
00297 << " Jacobian:\n" << pretty_string(Jacobian, " ");
00298 }
00299
00300 if (Jacobian.rows() != 6) {
00301 ostringstream msg;
00302 msg << "jspace::mass_inertia_explicit_form(): Jacobian of node " << ii
00303 << " has " << Jacobian.rows() << " rows instead of 6";
00304 throw runtime_error(msg.str());
00305 }
00306 if (static_cast<size_t>(Jacobian.cols()) != ndof) {
00307 ostringstream msg;
00308 msg << "jspace::mass_inertia_explicit_form(): Jacobian of node " << ii
00309 << " has " << Jacobian.cols() << " columns instead of " << ndof;
00310 throw runtime_error(msg.str());
00311 }
00312
00313
00314
00315
00316
00317
00318
00319 Eigen::Matrix3d Im(Eigen::Matrix3d::Zero());
00320 deFloat const * mass(node->mass());
00321 if (mass) {
00322 Matrix const mass_contrib(Jacobian.block(0, 0, 3, ndof).transpose() * Jacobian.block(0, 0, 3, ndof));
00323 mass_inertia += *mass * mass_contrib;
00324 if (com) {
00325 double const xx(pow(com->elementAt(0), 2));
00326 double const yy(pow(com->elementAt(1), 2));
00327 double const zz(pow(com->elementAt(2), 2));
00328 double const xy(com->elementAt(0) * com->elementAt(1));
00329 double const xz(com->elementAt(0) * com->elementAt(2));
00330 double const yz(com->elementAt(1) * com->elementAt(2));
00331 Im <<
00332 yy+zz, -xy, -xz,
00333 -xy, zz+xx, -yz,
00334 -xz, -yz, xx+yy;
00335 Im *= *mass;
00336 }
00337 if (dbgos) {
00338 *dbgos << " mass: " << *mass << "\n"
00339 << " JvT x Jv:\n" << pretty_string(mass_contrib, " ")
00340 << " contribution of mass:\n" << pretty_string(*mass * mass_contrib, " ")
00341 << " Im (for subsequent use):\n" << pretty_string(Im, " ");
00342 }
00343 }
00344 else if (dbgos) {
00345 *dbgos << " no mass\n";
00346 }
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356 deMatrix3 const * inertia(node->inertia());
00357 if (inertia) {
00358
00359
00360
00361
00362
00363
00364
00365
00366 Matrix const J_omega(global_com.linear().transpose() * Jacobian.block(3, 0, 3, ndof));
00367
00368 Eigen::Matrix3d Ic;
00369 Ic <<
00370 inertia->elementAt(0, 0), inertia->elementAt(0, 1), inertia->elementAt(0, 2),
00371 inertia->elementAt(1, 0), inertia->elementAt(1, 1), inertia->elementAt(1, 2),
00372 inertia->elementAt(2, 0), inertia->elementAt(2, 1), inertia->elementAt(2, 2);
00373 mass_inertia += J_omega.transpose() * (Ic - Im) * J_omega;
00374 if (dbgos) {
00375 *dbgos << " Ic:\n" << pretty_string(Ic, " ")
00376 << " Ic - Im:\n" << pretty_string(Ic - Im, " ")
00377 << " J_omega:\n" << pretty_string(J_omega, " ")
00378 << " JoT x (Ic-Im) x Jo:\n"
00379 << pretty_string(J_omega.transpose() * (Ic - Im) * J_omega, " ");
00380 }
00381 }
00382 else if (dbgos) {
00383 *dbgos << " no inertia\n";
00384 }
00385
00386 if (dbgos) {
00387 *dbgos << " mass_inertia so far:\n" << pretty_string(mass_inertia, " ");
00388 }
00389 }
00390 }
00391
00392 }