Simbody
3.4 (development)
|
00001 #ifndef SimTK_SIMBODY_CONTACT_TRACKER_SUBSYSTEM_H_ 00002 #define SimTK_SIMBODY_CONTACT_TRACKER_SUBSYSTEM_H_ 00003 00004 /* -------------------------------------------------------------------------- * 00005 * Simbody(tm) * 00006 * -------------------------------------------------------------------------- * 00007 * This is part of the SimTK biosimulation toolkit originating from * 00008 * Simbios, the NIH National Center for Physics-Based Simulation of * 00009 * Biological Structures at Stanford, funded under the NIH Roadmap for * 00010 * Medical Research, grant U54 GM072970. See https://simtk.org/home/simbody. * 00011 * * 00012 * Portions copyright (c) 2011-12 Stanford University and the Authors. * 00013 * Authors: Michael Sherman, Peter Eastman * 00014 * Contributors: * 00015 * * 00016 * Licensed under the Apache License, Version 2.0 (the "License"); you may * 00017 * not use this file except in compliance with the License. You may obtain a * 00018 * copy of the License at http://www.apache.org/licenses/LICENSE-2.0. * 00019 * * 00020 * Unless required by applicable law or agreed to in writing, software * 00021 * distributed under the License is distributed on an "AS IS" BASIS, * 00022 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * 00023 * See the License for the specific language governing permissions and * 00024 * limitations under the License. * 00025 * -------------------------------------------------------------------------- */ 00026 00027 #include "SimTKmath.h" 00028 #include "simbody/internal/common.h" 00029 #include "simbody/internal/ContactSurface.h" 00030 00031 namespace SimTK { 00032 00033 00034 class MultibodySystem; 00035 class MobilizedBody; 00036 class ContactTracker; 00037 class Contact; 00038 class ContactSnapshot; 00039 00144 //============================================================================== 00145 // CONTACT TRACKER SUBSYSTEM 00146 //============================================================================== 00147 class SimTK_SIMBODY_EXPORT ContactTrackerSubsystem : public Subsystem { 00148 public: 00149 ContactTrackerSubsystem(); 00150 explicit ContactTrackerSubsystem(MultibodySystem&); 00151 00156 int getNumSurfaces() const; 00158 const MobilizedBody& getMobilizedBody(ContactSurfaceIndex surfIx) const; 00161 const ContactSurface& getContactSurface(ContactSurfaceIndex surfIx) const; 00164 const Transform& getContactSurfaceTransform(ContactSurfaceIndex surfIx) const; 00165 00171 void adoptContactTracker(ContactTracker* tracker); 00172 00176 bool hasContactTracker(ContactGeometryTypeId surface1, 00177 ContactGeometryTypeId surface2) const; 00178 00184 const ContactTracker& getContactTracker(ContactGeometryTypeId surface1, 00185 ContactGeometryTypeId surface2, 00186 bool& reverseOrder) const; 00187 00190 const ContactSnapshot& getPreviousActiveContacts(const State& state) const; 00191 00194 const ContactSnapshot& getPreviousPredictedContacts(const State& state) const; 00195 00207 const ContactSnapshot& getActiveContacts(const State& state) const; 00208 00217 const ContactSnapshot& getPredictedContacts(const State& state) const; 00218 00225 bool realizeActiveContacts(const State& state, 00226 bool lastTry, 00227 Real& stepAdvice) const; 00228 00232 bool realizePredictedContacts(const State& state, 00233 bool lastTry, 00234 Real& stepAdvice) const; 00235 00236 SimTK_PIMPL_DOWNCAST(ContactTrackerSubsystem, Subsystem); 00237 00238 //-------------------------------------------------------------------------- 00239 private: 00240 class ContactTrackerSubsystemImpl& updImpl(); 00241 const ContactTrackerSubsystemImpl& getImpl() const; 00242 }; 00243 00244 00245 00246 //============================================================================== 00247 // CONTACT SNAPSHOT 00248 //============================================================================== 00259 class SimTK_SIMBODY_EXPORT ContactSnapshot { 00260 //TODO: replace with fast hash tables 00261 typedef std::map<ContactId,int> ContactMap; 00262 // Note: we always order the key so that the first surface index is less than 00263 // the second (they can't be equal!). 00264 typedef std::map<std::pair<ContactSurfaceIndex,ContactSurfaceIndex>, 00265 ContactId> SurfaceMap; 00266 public: 00268 ContactSnapshot() : m_time(NaN) {} 00269 00271 void clear() { 00272 m_time = NaN; 00273 m_contacts.clear(); 00274 m_id2contact.clear(); 00275 m_surfPair2id.clear(); 00276 } 00277 00279 void setTimestamp(Real time) {m_time=time;} 00281 Real getTimestamp() const {return m_time;} 00282 00288 void adoptContact(Contact& contact) { 00289 const ContactId id = contact.getContactId(); 00290 ContactSurfaceIndex surf1(contact.getSurface1()); 00291 ContactSurfaceIndex surf2(contact.getSurface2()); 00292 assert(id.isValid() && surf1.isValid() && surf2.isValid()); 00293 00294 // Surface pair must be ordered (low,high) for the map. 00295 if (surf1 > surf2) std::swap(surf1,surf2); 00296 00297 assert(!hasContact(id)); 00298 assert(!hasContact(surf1,surf2)); 00299 00300 const int indx = m_contacts.size(); 00301 m_contacts.push_back(contact); // shallow copy 00302 m_id2contact[id] = indx; 00303 m_surfPair2id[std::make_pair(surf1,surf2)] = id; 00304 } 00305 00307 bool hasContact(ContactId id) const 00308 { return m_id2contact.find(id) != m_id2contact.end(); } 00311 bool hasContact(ContactSurfaceIndex surf1, ContactSurfaceIndex surf2) const 00312 { if (surf1 > surf2) std::swap(surf1,surf2); 00313 return m_surfPair2id.find(std::make_pair(surf1,surf2)) 00314 != m_surfPair2id.end(); } 00315 00317 int getNumContacts() const {return m_contacts.size();} 00322 const Contact& getContact(int n) const {return m_contacts[n];} 00326 const Contact& getContactById(ContactId id) const 00327 { static Contact empty; 00328 ContactMap::const_iterator p = m_id2contact.find(id); 00329 return p==m_id2contact.end() ? empty : m_contacts[p->second]; } 00333 ContactId getContactIdForSurfacePair(ContactSurfaceIndex surf1, 00334 ContactSurfaceIndex surf2) const 00335 { if (surf1 > surf2) std::swap(surf1,surf2); 00336 SurfaceMap::const_iterator p = 00337 m_surfPair2id.find(std::make_pair(surf1,surf2)); 00338 return p==m_surfPair2id.end() ? ContactId() : p->second; } 00339 00340 //-------------------------------------------------------------------------- 00341 private: 00342 00343 // Remove a Contact occupying a particular slot in the Contact array. This 00344 // will result in another Contact object being moved to occupy the now-empty 00345 // slot to keep the array compact. 00346 void removeContact(int n) { 00347 assert(0 <= n && n < m_contacts.size()); 00348 if (n+1 == m_contacts.size()) { 00349 m_contacts.pop_back(); // this was the last one 00350 return; 00351 } 00352 // Move the last one to replace this one and update the map. 00353 m_contacts[n] = m_contacts.back(); // shallow copy 00354 m_contacts.pop_back(); // destruct 00355 m_id2contact[m_contacts[n].getContactId()] = n; 00356 } 00357 00358 00359 Real m_time; // when this snapshot was taken 00360 Array_<Contact,int> m_contacts; // all the contact pairs 00361 ContactMap m_id2contact; // the contact pairs by contactId 00362 SurfaceMap m_surfPair2id; // surfacepair -> contactId map 00363 }; 00364 00365 // for debugging 00366 inline std::ostream& operator<<(std::ostream& o, const ContactSnapshot& cs) { 00367 o << "Contact snapshot: time=" << cs.getTimestamp() 00368 << " numContacts=" << cs.getNumContacts() << std::endl; 00369 return o; 00370 } 00371 00372 00373 } // namespace SimTK 00374 00375 #endif // SimTK_SIMBODY_CONTACT_TRACKER_SUBSYSTEM_H_