Go to the documentation of this file.00001 #ifndef OPENTISSUE_DYNAMICS_MBD_UTIL_COLLISION_RESOLVERS_MBD_SEQUENTIAL_TRUNCATING_COLLISION_RESOLVER_H
00002 #define OPENTISSUE_DYNAMICS_MBD_UTIL_COLLISION_RESOLVERS_MBD_SEQUENTIAL_TRUNCATING_COLLISION_RESOLVER_H
00003
00004
00005
00006
00007
00008
00009
00010 #include <OpenTissue/configuration.h>
00011
00012 #include <OpenTissue/dynamics/mbd/interfaces/mbd_collision_resolver_interface.h>
00013 #include <OpenTissue/dynamics/mbd/mbd_apply_impulse.h>
00014 #include <OpenTissue/dynamics/mbd/mbd_compute_relative_contact_velocity.h>
00015 #include <OpenTissue/core/math/math_precision.h>
00016
00017 namespace OpenTissue
00018 {
00019 namespace mbd
00020 {
00047 template< typename mbd_types, typename collision_law_policy >
00048 class SequentialTruncatingCollisionResolver
00049 : public CollisionResolverInterface<mbd_types>
00050 , public collision_law_policy
00051 {
00052 public:
00053
00054 typedef typename mbd_types::math_policy::index_type size_type;
00055 typedef typename mbd_types::math_policy::real_type real_type;
00056 typedef typename mbd_types::math_policy::vector3_type vector3_type;
00057 typedef typename mbd_types::math_policy::value_traits value_traits;
00058 typedef typename mbd_types::group_type group_type;
00059 typedef typename mbd_types::body_type body_type;
00060 typedef typename mbd_types::edge_type edge_type;
00061 typedef typename mbd_types::contact_type contact_type;
00062 typedef typename mbd_types::material_type material_type;
00063 typedef typename std::vector<contact_type*> contact_ptr_heap;
00064
00065 public:
00066
00067 class node_traits{};
00068
00069 class edge_traits{};
00070
00071 class constraint_traits
00072 {
00073 public:
00074
00075 bool m_stcr_truncated;
00076 size_type m_stcr_resolved;
00077
00078 public:
00079
00080 constraint_traits()
00081 : m_stcr_truncated(false)
00082 , m_stcr_resolved(0)
00083 {}
00084
00085 };
00086
00087 protected:
00088
00096 struct ContactPointComparision
00097 {
00098 bool operator()(contact_type const * x, contact_type const * y) const
00099 {
00100 if(x->m_un < y->m_un)
00101 return true;
00102 return false;
00103 }
00104 };
00105
00106 protected:
00107
00108 size_type m_resolve_limit;
00109 real_type m_truncation_fraction;
00110
00111 public:
00112
00113 SequentialTruncatingCollisionResolver()
00114 : m_resolve_limit(20)
00115 , m_truncation_fraction(1000.)
00116 {}
00117
00118 virtual ~SequentialTruncatingCollisionResolver() {}
00119
00120 public:
00121
00122 real_type const & truncation_fraction() const {return m_truncation_fraction;}
00123
00133 void set_truncation_fraction(real_type const & value)
00134 {
00135 if(value>0)
00136 m_truncation_fraction = value;
00137 }
00138
00139 size_type const & truncation_limit() const {return this->m_truncation_limit;}
00140 size_type & truncation_limit() {return this->m_truncation_limit;}
00141
00142 public:
00143
00149 void resolve_collisions(group_type & group)
00150 {
00151 if(group.size_contacts()==0)
00152 {
00153 return;
00154 }
00155 typename group_type::indirect_contact_iterator cbegin = group.contact_begin();
00156 typename group_type::indirect_contact_iterator cend = group.contact_end();
00157
00158 contact_ptr_heap S;
00159 init_heap(cbegin,cend,S);
00160 contact_type * cp = minimum(S);
00161 assert(cp);
00162 real_type truncation_threshold = 0;
00163 assert(m_truncation_fraction>0);
00164 truncation_threshold = cp->m_un/m_truncation_fraction;
00165 if(truncation_threshold>0)
00166 return;
00167 assert(m_resolve_limit>0);
00168 vector3_type J_a,J_b;
00169 while(true)
00170 {
00171 cp = minimum(S);
00172
00173 real_type epsilon = OpenTissue::math::working_precision<real_type>();
00174 if(cp->m_un >= -epsilon)
00175 return;
00176 ++(cp->m_stcr_resolved);
00177 if(((cp->m_stcr_resolved > m_resolve_limit) || (cp->m_un > truncation_threshold)))
00178 {
00179 real_type e_n = cp->m_material->normal_restitution();
00180 cp->m_material->normal_restitution() = value_traits::zero();
00181 J_b = compute_impulse(cp);
00182 cp->m_material->normal_restitution() = e_n;
00183 cp->m_stcr_truncated = true;
00184 }
00185 else
00186 {
00187 J_b = compute_impulse(cp);
00188 }
00189 J_a = - J_b;
00190 mbd::apply_impulse(cp->get_body_A(),cp->m_rA,J_a);
00191 mbd::apply_impulse(cp->get_body_B(),cp->m_rB,J_b);
00192 update_all_dependent_contacts(cp);
00193 update_heap(S);
00194 }
00195 }
00196
00197 protected:
00198
00206 template<typename iterator>
00207 void init_heap(iterator const & cbegin,iterator const & cend,contact_ptr_heap & S)
00208 {
00209 for(iterator contact=cbegin;contact!=cend;++contact)
00210 {
00211 contact->m_stcr_resolved = 0;
00212 contact->m_stcr_truncated = false;
00213 update(&(*contact));
00214 S.push_back(&(*contact));
00215 }
00216 update_heap(S);
00217 }
00218
00224 void update_heap(contact_ptr_heap & S)
00225 {
00226
00227
00228
00229
00230 make_heap(S.begin(),S.end(),ContactPointComparision());
00231 sort_heap(S.begin(),S.end(),ContactPointComparision());
00232 }
00233
00241 contact_type * minimum(contact_ptr_heap & S)
00242 {
00243 return S.front();
00244 }
00245
00254 void update_all_dependent_contacts(contact_type * cp)
00255 {
00256 body_type * A = cp->get_body_A();
00257 body_type * B = cp->get_body_B();
00258 typename body_type::indirect_edge_iterator ebegin,eend,edge;
00259 typename edge_type::contact_iterator cbegin,cend,contact;
00260 ebegin = A->edge_begin();
00261 eend = A->edge_end();
00262 for(edge=ebegin;edge!=eend;++edge)
00263 {
00264 if(!edge->is_up_to_date())
00265 continue;
00266 cbegin = edge->contact_begin();
00267 cend = edge->contact_end();
00268 for(contact=cbegin;contact!=cend;++contact)
00269 {
00270 update(&(*contact));
00271 }
00272 }
00273 ebegin = B->edge_begin();
00274 eend = B->edge_end();
00275 for(edge=ebegin;edge!=eend;++edge)
00276 {
00277 if(!edge->is_up_to_date())
00278 continue;
00279
00280 if(edge->get_body_A()==A)
00281 continue;
00282 cbegin = edge->contact_begin();
00283 cend = edge->contact_end();
00284 for(contact=cbegin;contact!=cend;++contact)
00285 {
00286 update(&(*contact));
00287 }
00288 }
00289 }
00290
00298 void update(contact_type * cp)
00299 {
00300 assert(cp);
00301 body_type * A = cp->get_body_A();
00302 body_type * B = cp->get_body_B();
00303 assert(A);
00304 assert(B);
00305 if(cp->m_stcr_truncated)
00306 {
00307 cp->m_un = value_traits::zero();
00308 vector3_type tmp;
00309 A->get_velocity(tmp);
00310 truncate(tmp);
00311 A->set_velocity(tmp);
00312 A->get_spin(tmp);
00313 truncate(tmp);
00314 A->set_spin(tmp);
00315 B->get_velocity(tmp);
00316 truncate(tmp);
00317 B->set_velocity(tmp);
00318 B->get_spin(tmp);
00319 truncate(tmp);
00320 B->set_spin(tmp);
00321 cp->m_stcr_truncated = false;
00322 }
00323 else
00324 {
00325 vector3_type v_a,v_b,w_a,w_b;
00326 A->get_velocity(v_a);
00327 A->get_spin(w_a);
00328 B->get_velocity(v_b);
00329 B->get_spin(w_b);
00330 vector3_type u = mbd::compute_relative_contact_velocity(v_a,w_a,cp->m_rA,v_b,w_b,cp->m_rB);
00331
00332
00333 cp->m_un = cp->m_n*u;
00334 }
00335 }
00336
00337 };
00338
00339 }
00340 }
00341
00342 #endif