Go to the documentation of this file.00001 #ifndef OPENTISSUE_DYNAMICS_MBD_MBD_BODY_H
00002 #define OPENTISSUE_DYNAMICS_MBD_MBD_BODY_H
00003
00004
00005
00006
00007
00008
00009
00010 #include <OpenTissue/configuration.h>
00011
00012 #include <OpenTissue/dynamics/mbd/mbd_update_inertia_tensor.h>
00013
00014 namespace OpenTissue
00015 {
00016 namespace mbd
00017 {
00018
00019 template< typename mbd_types >
00020 class Body
00021 : public mbd_types::identifier_type
00022 , public mbd_types::node_traits
00023 {
00024 public:
00025
00026 typedef typename mbd_types::math_policy math_policy;
00027 typedef typename mbd_types::math_policy::real_type real_type;
00028 typedef typename mbd_types::math_policy::vector3_type vector3_type;
00029 typedef typename mbd_types::math_policy::matrix3x3_type matrix3x3_type;
00030 typedef typename mbd_types::math_policy::quaternion_type quaternion_type;
00031 typedef typename mbd_types::math_policy::size_type size_type;
00032 typedef typename mbd_types::math_policy::value_traits value_traits;
00033 typedef typename mbd_types::node_traits node_traits;
00034
00035 protected:
00036
00037 typedef typename mbd_types::geometry_type geometry_type;
00038 typedef typename mbd_types::body_type body_type;
00039 typedef typename mbd_types::joint_type joint_type;
00040 typedef typename mbd_types::edge_type edge_type;
00041 typedef typename mbd_types::force_type force_type;
00042 typedef typename mbd_types::scripted_motion_type scripted_motion_type;
00043 typedef typename mbd_types::joint_ptr_container joint_ptr_container;
00044 typedef typename mbd_types::edge_ptr_container edge_ptr_container;
00045 typedef typename mbd_types::force_ptr_container force_ptr_container;
00046
00047 typedef typename edge_ptr_container::iterator edge_ptr_iterator;
00048 typedef typename edge_ptr_container::const_iterator const_edge_ptr_iterator;
00049 typedef typename joint_ptr_container::iterator joint_ptr_iterator;
00050 typedef typename joint_ptr_container::const_iterator const_joint_ptr_iterator;
00051
00052 public:
00053
00054 joint_ptr_container m_joints;
00055 edge_ptr_container m_edges;
00056 size_type m_tag;
00057
00058 protected:
00059
00060 force_ptr_container m_forces;
00061 scripted_motion_type * m_scripted_motion;
00062
00063 public:
00064
00065 typedef typename mbd_types::indirect_joint_iterator indirect_joint_iterator;
00066 typedef typename mbd_types::const_indirect_joint_iterator const_indirect_joint_iterator;
00067 typedef typename mbd_types::indirect_edge_iterator indirect_edge_iterator;
00068 typedef typename mbd_types::indirect_force_iterator indirect_force_iterator;
00069 typedef typename mbd_types::const_indirect_force_iterator const_indirect_force_iterator;
00070
00071 indirect_joint_iterator joint_begin() { return indirect_joint_iterator(m_joints.begin()); }
00072 indirect_joint_iterator joint_end() { return indirect_joint_iterator(m_joints.end()); }
00073 const_indirect_joint_iterator joint_begin() const { return const_indirect_joint_iterator(m_joints.begin()); }
00074 const_indirect_joint_iterator joint_end() const { return const_indirect_joint_iterator(m_joints.end()); }
00075 indirect_edge_iterator edge_begin() { return indirect_edge_iterator(m_edges.begin()); }
00076 indirect_edge_iterator edge_end() { return indirect_edge_iterator(m_edges.end()); }
00077 indirect_force_iterator force_begin() { return indirect_force_iterator(m_forces.begin()); }
00078 indirect_force_iterator force_end() { return indirect_force_iterator(m_forces.end()); }
00079 const_indirect_force_iterator force_begin() const { return const_indirect_force_iterator(m_forces.begin()); }
00080 const_indirect_force_iterator force_end() const { return const_indirect_force_iterator(m_forces.end()); }
00081
00082 protected:
00083
00084 size_type m_material_idx;
00085 bool m_active;
00086
00087
00088 bool m_sleepy;
00089 bool m_fixed;
00090 bool m_scripted;
00091 bool m_finite_rotation_update;
00092
00093 vector3_type m_r_axis;
00094 vector3_type m_r;
00095 quaternion_type m_Q;
00096 vector3_type m_P;
00097 vector3_type m_L;
00098 vector3_type m_V;
00099 vector3_type m_W;
00100 matrix3x3_type m_invI_WCS;
00101 matrix3x3_type m_invI_BF;
00102 matrix3x3_type m_I_WCS;
00103 matrix3x3_type m_I_BF;
00104 real_type m_inv_mass;
00105 real_type m_mass;
00106 matrix3x3_type m_R;
00107
00108 geometry_type * m_geometry;
00109
00110 public:
00111
00112 Body(){ this->clear(); }
00113
00114 ~Body()
00115 {
00116 m_edges.clear();
00117 m_forces.clear();
00118 }
00119
00120
00121 Body (Body const & body)
00122 {
00123 assert(body.m_edges.empty() || !"Body(body): Could not make a copy of a body already in a configuration! It has live edges!");
00124
00125 this->m_joints = body.m_joints;
00126 this->m_edges = body.m_edges;
00127 this->m_tag = body.m_tag;
00128 this->m_forces = body.m_forces;
00129 this->m_scripted_motion = body.m_scripted_motion;
00130
00131 this->m_material_idx = body.m_material_idx;
00132 this->m_active = body.m_active;
00133 this->m_sleepy = body.m_sleepy;
00134 this->m_fixed = body.m_fixed;
00135 this->m_scripted = body.m_scripted;
00136 this->m_finite_rotation_update = body.m_finite_rotation_update;
00137
00138 this->m_r_axis = body.m_r_axis;
00139 this->m_r = body.m_r;
00140 this->m_Q = body.m_Q;
00141 this->m_P = body.m_P;
00142 this->m_L = body.m_L;
00143 this->m_V = body.m_V;
00144 this->m_W = body.m_W;
00145 this->m_invI_WCS = body.m_invI_WCS;
00146 this->m_invI_BF = body.m_invI_BF;
00147 this->m_I_WCS = body.m_I_WCS;
00148 this->m_I_BF = body.m_I_BF;
00149 this->m_inv_mass = body.m_inv_mass;
00150 this->m_mass = body.m_mass;
00151 this->m_R = body.m_R;
00152
00153 this->m_geometry = body.m_geometry;
00154 }
00155
00156 public:
00157
00158 void clear()
00159 {
00160 m_forces.clear();
00161
00162 m_geometry = 0;
00163
00164 m_scripted_motion = 0;
00165 m_scripted = false;
00166
00167 m_active = true;
00168 m_sleepy = false;
00169 m_material_idx = 0;
00170 m_r_axis.clear();
00171 m_finite_rotation_update = false;
00172 m_fixed = false;
00173 m_tag = 0;
00174
00175 m_r.clear();
00176 m_Q.identity();
00177 m_R = OpenTissue::math::diag(value_traits::one());
00178 m_I_WCS = OpenTissue::math::diag(value_traits::one());
00179 m_I_BF = OpenTissue::math::diag(value_traits::one());
00180 m_invI_WCS = OpenTissue::math::diag(value_traits::one());
00181 m_invI_BF = OpenTissue::math::diag(value_traits::one());
00182 m_inv_mass = value_traits::one();
00183 m_mass = value_traits::one();
00184 m_V.clear();
00185 m_W.clear();
00186 m_P.clear();
00187 m_L.clear();
00188
00189 if(!m_edges.empty())
00190 {
00191 std::cout << "Body::clear(): WARNING clear was invoked on a body that still got edges?" << std::endl;
00192 }
00193 }
00194
00202 void compute_forces_and_torques(vector3_type & F,vector3_type & T)const
00203 {
00204
00205 F.clear();
00206 T.clear();
00207
00208 vector3_type f,t;
00209
00210 for(const_indirect_force_iterator force = force_begin();force!=force_end();++force)
00211 {
00212 force->compute(*this,f,t);
00213 F += f;
00214 T += t;
00215 }
00216 }
00217
00226 void attach(force_type * force)
00227 {
00228 assert(force || !"Body::detach(): force_type pointer was null");
00229 if ( find( m_forces.begin( ), m_forces.end( ), force ) == m_forces.end( ) )
00230 {
00231 m_forces.push_back(force);
00232 }
00233 else
00234 {
00235 std::cout << "Body::attach(): Sorry, you already added that force to this body!" << std::endl;
00236 }
00237 }
00238
00244 void detach(force_type * force)
00245 {
00246 assert(force || !"Body::detach(): force_type pointer was null");
00247
00248 if ( find( m_forces.begin( ), m_forces.end( ), force ) == m_forces.end( ) )
00249 {
00250 std::cout << "Body::detach(): Sorry, the force wer not attached to this body!" << std::endl;
00251 }
00252 else
00253 {
00254 m_forces.remove(force);
00255 }
00256
00257 }
00258
00264 void set_position(vector3_type const & r) { m_r = r; }
00265
00272 void set_orientation(quaternion_type const & Q)
00273 {
00274 m_Q = unit(Q);
00275 m_R = Q;
00276
00277 mbd::update_inertia_tensor(m_R,m_I_BF,m_I_WCS);
00278 mbd::update_inertia_tensor(m_R,m_invI_BF,m_invI_WCS);
00279 }
00280
00287 void set_velocity(vector3_type const & V)
00288 {
00289 if(m_fixed)
00290 return;
00291 m_V = V;
00292 m_P = V *m_mass;
00293 }
00294
00301 void set_spin(vector3_type const & W)
00302 {
00303 if(m_fixed)
00304 return;
00305 m_W = W;
00306 m_L = m_I_WCS * m_W;
00307 }
00308
00315 void set_mass(real_type const & mass)
00316 {
00317 assert(mass>value_traits::zero() || !"Body::set_mass(): mass must be positive");
00318 m_mass = mass;
00319 m_inv_mass = value_traits::one() / mass;
00320 m_P = m_V*m_mass;
00321 }
00322
00330 void set_inertia_bf(matrix3x3_type const & I_BF)
00331 {
00332 m_I_BF = I_BF;
00333 m_invI_BF = inverse(I_BF);
00334
00335 mbd::update_inertia_tensor(m_R,m_I_BF,m_I_WCS);
00336 mbd::update_inertia_tensor(m_R,m_invI_BF,m_invI_WCS);
00337
00338 m_L = m_I_WCS * m_W;
00339 }
00340
00348 void get_position(vector3_type & r) const { r = m_r; }
00349
00357 void get_orientation(quaternion_type & Q) const
00358 {
00359 Q = m_Q;
00360 }
00361
00369 void get_orientation(matrix3x3_type & R) const
00370 {
00371 R = m_R;
00372 }
00373
00380 void get_velocity(vector3_type & V) const
00381 {
00382 if(m_fixed)
00383 V.clear();
00384 else
00385 V = m_V;
00386 }
00387
00394 void get_spin(vector3_type & W) const
00395 {
00396 if(m_fixed)
00397 W.clear();
00398 else
00399 W = m_W;
00400 }
00401
00407 real_type get_inverse_mass() const { return (m_fixed || m_scripted) ? value_traits::zero() : m_inv_mass; }
00408
00414 real_type get_mass() const { return (m_fixed || m_scripted) ? value_traits::infinity() : m_mass; }
00415
00421 void get_inverse_inertia_bf(matrix3x3_type & invI_BF) const
00422 {
00423 if(m_fixed || m_scripted)
00424 invI_BF.clear();
00425 else
00426 invI_BF = m_invI_BF;
00427 }
00428
00434 void get_inverse_inertia_wcs(matrix3x3_type & invI_WCS) const
00435 {
00436 if(m_fixed || m_scripted)
00437 invI_WCS.clear();
00438 else
00439 invI_WCS = m_invI_WCS;
00440 }
00441
00447 void get_inertia_wcs(matrix3x3_type & I_WCS) const
00448 {
00449 if(m_fixed || m_scripted)
00450 {
00451 I_WCS = OpenTissue::math::diag( value_traits::infinity() );
00452 }
00453 else
00454 I_WCS = m_I_WCS;
00455 }
00456
00463 bool is_active() const { return m_active; }
00464
00470 void set_active(bool const & active) { this->m_active = active; }
00471
00478 bool is_sleepy() const { return m_sleepy; }
00479
00485 void set_sleepy(bool const & sleepy){ this->m_sleepy = sleepy; }
00486
00500 void set_material_idx(size_type const & idx){ m_material_idx = idx; }
00501
00507 size_type get_material_idx() const { return m_material_idx; }
00508
00516 bool has_finite_rotation_update()const { return m_finite_rotation_update; }
00517
00523 void set_finite_rotation_update(bool const & active) { m_finite_rotation_update = active; }
00524
00531 bool has_finite_rotation_axis() const { return (m_r_axis(0)||m_r_axis(1)||m_r_axis(2)); }
00532
00538 void get_finite_rotation_axis(vector3_type & r_axis) const { r_axis = m_r_axis; }
00539
00549 void set_finite_rotation_axis(vector3_type const & r_axis)
00550 {
00551 m_r_axis.clear();
00552 if(r_axis(0) || r_axis(1) ||r_axis(2) )
00553 {
00554 m_finite_rotation_update = true;
00555 m_r_axis = unit(r_axis);
00556 }
00557 }
00558
00559
00566 bool is_scripted() const { return m_scripted; }
00567
00576 void set_scripted_motion(scripted_motion_type * motion)
00577 {
00578 m_scripted_motion = motion;
00579 if(motion)
00580 m_scripted = true;
00581 else
00582 m_scripted = false;
00583 }
00584
00593 void compute_scripted_motion(real_type const & time)
00594 {
00595 if(m_scripted_motion)
00596 {
00597 vector3_type r,v,w;
00598 quaternion_type q;
00599 m_scripted_motion->compute((*this),time,r,q,v,w);
00600 set_position(r);
00601 set_orientation(q);
00602 set_velocity(v);
00603 set_spin(w);
00604 }
00605 }
00606
00613 bool is_fixed() const { return m_fixed; }
00614
00615
00616
00622 void set_fixed(bool const & fixed) { this->m_fixed = fixed; }
00623
00630 real_type compute_kinetic_energy() const
00631 {
00632 real_type Ekin = value_traits::zero();
00633 if(!m_fixed)
00634 Ekin = (( (m_V*m_V) /m_inv_mass) + m_W*m_L)/value_traits::two();
00635 return Ekin;
00636 }
00637
00643 bool has_joints() const { return (!m_joints.empty()); }
00644
00650 bool has_active_joints() const
00651 {
00652 for(const_indirect_joint_iterator joint = joint_begin();joint!=joint_end();++joint)
00653 {
00654 if(joint->is_active())
00655 return true;
00656 }
00657 return false;
00658 }
00659
00667 bool has_joint_to(body_type const * body) const
00668 {
00669 assert(body || !"Body::has_joint_to(): body was null");
00670 assert(this!=body || !"Body::has_joint_to(): body was the same as this body");
00671 for(const_indirect_joint_iterator joint = joint_begin();joint!=joint_end();++joint)
00672 {
00673 if(joint->get_socket_A()->get_body()==body || joint->get_socket_B()->get_body()==body)
00674 return true;
00675 }
00676 return false;
00677 }
00678
00684 void set_geometry( geometry_type * geometry )
00685 {
00686 assert( geometry || !"Body::set_geometry(): geometry was null?");
00687
00688 m_geometry = geometry;
00689 }
00690
00696 geometry_type * get_geometry() const { return m_geometry; }
00697
00698
00708 void compute_collision_aabb(
00709 vector3_type const & r
00710 , matrix3x3_type const & R
00711 , vector3_type & min_coord
00712 , vector3_type & max_coord
00713 , real_type const & envelope
00714 ) const
00715 {
00716 assert(m_geometry || !"Body::compute_collision_aabb(): Geometry was null!");
00717
00718
00719 min_coord(0) = OpenTissue::math::detail::lowest<real_type>();
00720 min_coord(1) = OpenTissue::math::detail::lowest<real_type>();
00721 min_coord(2) = OpenTissue::math::detail::lowest<real_type>();
00722 max_coord(0) = OpenTissue::math::detail::highest<real_type>();
00723 max_coord(1) = OpenTissue::math::detail::highest<real_type>();
00724 max_coord(2) = OpenTissue::math::detail::highest<real_type>();
00725
00726 m_geometry->compute_collision_aabb( r, R, min_coord, max_coord );
00727
00728
00729 min_coord(0) -= envelope;
00730 min_coord(1) -= envelope;
00731 min_coord(2) -= envelope;
00732 max_coord(0) += envelope;
00733 max_coord(1) += envelope;
00734 max_coord(2) += envelope;
00735 }
00736
00737
00738 };
00739
00740 }
00741 }
00742
00743 #endif