Bullet Collision Detection & Physics Library: btDeformableMultiBodyConstraintSolver.cpp Source File

Bullet Collision Detection & Physics Library

btDeformableMultiBodyConstraintSolver.cpp
Go to the documentation of this file.
1/*
2 Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
3
4 Bullet Continuous Collision Detection and Physics Library
5 Copyright (c) 2019 Google Inc. http://bulletphysics.org
6 This software is provided 'as-is', without any express or implied warranty.
7 In no event will the authors be held liable for any damages arising from the use of this software.
8 Permission is granted to anyone to use this software for any purpose,
9 including commercial applications, and to alter it and redistribute it freely,
10 subject to the following restrictions:
11 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
12 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
13 3. This notice may not be removed or altered from any source distribution.
14 */
15
16#include "btDeformableMultiBodyConstraintSolver.h"
17#include "BulletReducedDeformableBody/btReducedDeformableBodySolver.h"
18#include <iostream>
19
20// override the iterations method to include deformable/multibody contact
21 btScalar btDeformableMultiBodyConstraintSolver::solveDeformableGroupIterations(btCollisionObject** bodies, int numBodies, btCollisionObject** deformableBodies, int numDeformableBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer)
22{
23 {
24 // pair deformable body with solver body
25 pairDeformableAndSolverBody(bodies, numBodies, numDeformableBodies, infoGlobal);
26
28 solveGroupCacheFriendlySplitImpulseIterations(bodies, numBodies, deformableBodies, numDeformableBodies, manifoldPtr, numManifolds, constraints, numConstraints, infoGlobal, debugDrawer);
29
30 int maxIterations = m_maxOverrideNumSolverIterations > infoGlobal.m_numIterations ? m_maxOverrideNumSolverIterations : infoGlobal.m_numIterations;
31 for (int iteration = 0; iteration < maxIterations; iteration++)
32 {
33 // rigid bodies are solved using solver body velocity, but rigid/deformable contact directly uses the velocity of the actual rigid body. So we have to do the following: Solve one iteration of the rigid/rigid contact, get the updated velocity in the solver body and update the velocity of the underlying rigid body. Then solve the rigid/deformable contact. Finally, grab the (once again) updated rigid velocity and update the velocity of the wrapping solver body
34
35 // solve rigid/rigid in solver body
36 m_leastSquaresResidual = solveSingleIteration(iteration, bodies, numBodies, manifoldPtr, numManifolds, constraints, numConstraints, infoGlobal, debugDrawer);
37 // solver body velocity -> rigid body velocity
38 solverBodyWriteBack(infoGlobal);
39 btScalar deformableResidual = m_deformableSolver->solveContactConstraints(deformableBodies, numDeformableBodies, infoGlobal);
40 // update rigid body velocity in rigid/deformable contact
41 m_leastSquaresResidual = btMax(m_leastSquaresResidual, deformableResidual);
42 // solver body velocity <- rigid body velocity
43 writeToSolverBody(bodies, numBodies, infoGlobal);
44
45
46 // std::cout << "------------Iteration " << iteration << "------------\n";
47 // std::cout << "m_leastSquaresResidual: " << m_leastSquaresResidual << "\n";
48
49 if (m_leastSquaresResidual <= infoGlobal.m_leastSquaresResidualThreshold || (iteration >= (maxIterations - 1)))
50 {
51#ifdef VERBOSE_RESIDUAL_PRINTF
52 if (iteration >= (maxIterations - 1))
53 printf("residual = %f at iteration #%d\n", m_leastSquaresResidual, iteration);
54#endif
55 m_analyticsData.m_numSolverCalls++;
56 m_analyticsData.m_numIterationsUsed = iteration + 1;
57 m_analyticsData.m_islandId = -2;
58 if (numBodies > 0)
59 m_analyticsData.m_islandId = bodies[0]->getCompanionId();
60 m_analyticsData.m_numBodies = numBodies;
61 m_analyticsData.m_numContactManifolds = numManifolds;
62 m_analyticsData.m_remainingLeastSquaresResidual = m_leastSquaresResidual;
63
64 m_deformableSolver->deformableBodyInternalWriteBack();
65 // std::cout << "[===================Next Step===================]\n";
66 break;
67 }
68 }
69 }
70 return 0.f;
71}
72
73 void btDeformableMultiBodyConstraintSolver::solveDeformableBodyGroup(btCollisionObject** bodies, int numBodies, btCollisionObject** deformableBodies, int numDeformableBodies, btPersistentManifold** manifold, int numManifolds, btTypedConstraint** constraints, int numConstraints, btMultiBodyConstraint** multiBodyConstraints, int numMultiBodyConstraints, const btContactSolverInfo& info, btIDebugDraw* debugDrawer, btDispatcher* dispatcher)
74{
75 m_tmpMultiBodyConstraints = multiBodyConstraints;
76 m_tmpNumMultiBodyConstraints = numMultiBodyConstraints;
77
78 // inherited from MultiBodyConstraintSolver
79 solveGroupCacheFriendlySetup(bodies, numBodies, manifold, numManifolds, constraints, numConstraints, info, debugDrawer);
80
81 // overriden
82 solveDeformableGroupIterations(bodies, numBodies, deformableBodies, numDeformableBodies, manifold, numManifolds, constraints, numConstraints, info, debugDrawer);
83
84 // inherited from MultiBodyConstraintSolver
85 solveGroupCacheFriendlyFinish(bodies, numBodies, info);
86
87 m_tmpMultiBodyConstraints = 0;
88 m_tmpNumMultiBodyConstraints = 0;
89}
90
91 void btDeformableMultiBodyConstraintSolver::writeToSolverBody(btCollisionObject** bodies, int numBodies, const btContactSolverInfo& infoGlobal)
92{
93 // reduced soft body solver directly modifies the solver body
94 if (m_deformableSolver->isReducedSolver())
95 {
96 return;
97 }
98
99 for (int i = 0; i < numBodies; i++)
100 {
101 int bodyId = getOrInitSolverBody(*bodies[i], infoGlobal.m_timeStep);
102
103 btRigidBody* body = btRigidBody::upcast(bodies[i]);
104 if (body && body->getInvMass())
105 {
106 btSolverBody& solverBody = m_tmpSolverBodyPool[bodyId];
107 solverBody.m_linearVelocity = body->getLinearVelocity() - solverBody.m_deltaLinearVelocity;
108 solverBody.m_angularVelocity = body->getAngularVelocity() - solverBody.m_deltaAngularVelocity;
109 }
110 }
111}
112
113 void btDeformableMultiBodyConstraintSolver::solverBodyWriteBack(const btContactSolverInfo& infoGlobal)
114{
115 // reduced soft body solver directly modifies the solver body
116 if (m_deformableSolver->isReducedSolver())
117 {
118 return;
119 }
120
121 for (int i = 0; i < m_tmpSolverBodyPool.size(); i++)
122 {
123 btRigidBody* body = m_tmpSolverBodyPool[i].m_originalBody;
124 if (body)
125 {
126 m_tmpSolverBodyPool[i].m_originalBody->setLinearVelocity(m_tmpSolverBodyPool[i].m_linearVelocity + m_tmpSolverBodyPool[i].m_deltaLinearVelocity);
127 m_tmpSolverBodyPool[i].m_originalBody->setAngularVelocity(m_tmpSolverBodyPool[i].m_angularVelocity + m_tmpSolverBodyPool[i].m_deltaAngularVelocity);
128 }
129 }
130}
131
132
133 void btDeformableMultiBodyConstraintSolver::pairDeformableAndSolverBody(btCollisionObject** bodies, int numBodies, int numDeformableBodies, const btContactSolverInfo& infoGlobal)
134{
135 if (!m_deformableSolver->isReducedSolver())
136 {
137 return;
138 }
139
140 btReducedDeformableBodySolver* solver = static_cast<btReducedDeformableBodySolver*>(m_deformableSolver);
141
142 for (int i = 0; i < numDeformableBodies; ++i)
143 {
144 for (int k = 0; k < solver->m_nodeRigidConstraints[i].size(); ++k)
145 {
146 btReducedDeformableNodeRigidContactConstraint& constraint = solver->m_nodeRigidConstraints[i][k];
147
148 if (!constraint.m_contact->m_cti.m_colObj->isStaticObject())
149 {
150 btCollisionObject& col_obj = const_cast<btCollisionObject&>(*constraint.m_contact->m_cti.m_colObj);
151
152 // object index in the solver body pool
153 int bodyId = getOrInitSolverBody(col_obj, infoGlobal.m_timeStep);
154
155 const btRigidBody* body = btRigidBody::upcast(bodies[bodyId]);
156 if (body && body->getInvMass())
157 {
158 // std::cout << "Node: " << constraint.m_node->index << ", body: " << bodyId << "\n";
159 btSolverBody& solverBody = m_tmpSolverBodyPool[bodyId];
160 constraint.setSolverBody(bodyId, solverBody);
161 }
162 }
163 }
164
165 // for (int j = 0; j < numBodies; j++)
166 // {
167 // int bodyId = getOrInitSolverBody(*bodies[j], infoGlobal.m_timeStep);
168
169 // btRigidBody* body = btRigidBody::upcast(bodies[j]);
170 // if (body && body->getInvMass())
171 // {
172 // btSolverBody& solverBody = m_tmpSolverBodyPool[bodyId];
173 // m_deformableSolver->pairConstraintWithSolverBody(i, bodyId, solverBody);
174 // }
175 // }
176 }
177}
178
179 void btDeformableMultiBodyConstraintSolver::solveGroupCacheFriendlySplitImpulseIterations(btCollisionObject** bodies, int numBodies, btCollisionObject** deformableBodies, int numDeformableBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer)
180{
181 BT_PROFILE("solveGroupCacheFriendlySplitImpulseIterations");
182 int iteration;
183 if (infoGlobal.m_splitImpulse)
184 {
185 {
186 for (iteration = 0; iteration < infoGlobal.m_numIterations; iteration++)
187 {
188 btScalar leastSquaresResidual = 0.f;
189 {
190 int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
191 int j;
192 for (j = 0; j < numPoolConstraints; j++)
193 {
194 const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[j]];
195
196 btScalar residual = resolveSplitPenetrationImpulse(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
197 leastSquaresResidual = btMax(leastSquaresResidual, residual * residual);
198 }
199 // solve the position correction between deformable and rigid/multibody
200 // btScalar residual = m_deformableSolver->solveSplitImpulse(infoGlobal);
201 btScalar residual = m_deformableSolver->m_objective->m_projection.solveSplitImpulse(deformableBodies, numDeformableBodies, infoGlobal);
202 leastSquaresResidual = btMax(leastSquaresResidual, residual * residual);
203 }
204 if (leastSquaresResidual <= infoGlobal.m_leastSquaresResidualThreshold || iteration >= (infoGlobal.m_numIterations - 1))
205 {
206#ifdef VERBOSE_RESIDUAL_PRINTF
207 if (iteration >= (infoGlobal.m_numIterations - 1))
208 printf("split impulse residual = %f at iteration #%d\n", leastSquaresResidual, iteration);
209#endif
210 break;
211 }
212 }
213 }
214 }
215}
btDeformableMultiBodyConstraintSolver.h
btMax
const T & btMax(const T &a, const T &b)
Definition: btMinMax.h:27
BT_PROFILE
#define BT_PROFILE(name)
Definition: btQuickprof.h:198
btReducedDeformableBodySolver.h
btScalar
float btScalar
The btScalar type abstracts floating point numbers, to easily switch between double and single floati...
Definition: btScalar.h:314
btAlignedObjectArray::size
int size() const
return the number of elements in the array
Definition: btAlignedObjectArray.h:142
btCollisionObject
btCollisionObject can be used to manage collision detection objects.
Definition: btCollisionObject.h:51
btCollisionObject::isStaticObject
bool isStaticObject() const
Definition: btCollisionObject.h:197
btCollisionObject::getCompanionId
int getCompanionId() const
Definition: btCollisionObject.h:458
btDeformableBackwardEulerObjective::m_projection
btDeformableContactProjection m_projection
Definition: btDeformableBackwardEulerObjective.h:45
btDeformableBodySolver::m_objective
btDeformableBackwardEulerObjective * m_objective
Definition: btDeformableBodySolver.h:52
btDeformableBodySolver::isReducedSolver
virtual bool isReducedSolver()
Definition: btDeformableBodySolver.h:210
btDeformableBodySolver::solveContactConstraints
virtual btScalar solveContactConstraints(btCollisionObject **deformableBodies, int numDeformableBodies, const btContactSolverInfo &infoGlobal)
Definition: btDeformableBodySolver.cpp:257
btDeformableBodySolver::deformableBodyInternalWriteBack
virtual void deformableBodyInternalWriteBack()
Definition: btDeformableBodySolver.h:215
btDeformableContactProjection::solveSplitImpulse
btScalar solveSplitImpulse(btCollisionObject **deformableBodies, int numDeformableBodies, const btContactSolverInfo &infoGlobal)
Definition: btDeformableContactProjection.cpp:61
btDeformableMultiBodyConstraintSolver::writeToSolverBody
void writeToSolverBody(btCollisionObject **bodies, int numBodies, const btContactSolverInfo &infoGlobal)
Definition: btDeformableMultiBodyConstraintSolver.cpp:91
btDeformableMultiBodyConstraintSolver::m_deformableSolver
btDeformableBodySolver * m_deformableSolver
Definition: btDeformableMultiBodyConstraintSolver.h:34
btDeformableMultiBodyConstraintSolver::pairDeformableAndSolverBody
void pairDeformableAndSolverBody(btCollisionObject **bodies, int numBodies, int numDeformableBodies, const btContactSolverInfo &infoGlobal)
Definition: btDeformableMultiBodyConstraintSolver.cpp:133
btDeformableMultiBodyConstraintSolver::solveDeformableBodyGroup
virtual void solveDeformableBodyGroup(btCollisionObject **bodies, int numBodies, btCollisionObject **deformableBodies, int numDeformableBodies, btPersistentManifold **manifold, int numManifolds, btTypedConstraint **constraints, int numConstraints, btMultiBodyConstraint **multiBodyConstraints, int numMultiBodyConstraints, const btContactSolverInfo &info, btIDebugDraw *debugDrawer, btDispatcher *dispatcher)
Definition: btDeformableMultiBodyConstraintSolver.cpp:73
btDeformableMultiBodyConstraintSolver::solveGroupCacheFriendlySplitImpulseIterations
virtual void solveGroupCacheFriendlySplitImpulseIterations(btCollisionObject **bodies, int numBodies, btCollisionObject **deformableBodies, int numDeformableBodies, btPersistentManifold **manifoldPtr, int numManifolds, btTypedConstraint **constraints, int numConstraints, const btContactSolverInfo &infoGlobal, btIDebugDraw *debugDrawer)
Definition: btDeformableMultiBodyConstraintSolver.cpp:179
btDeformableMultiBodyConstraintSolver::solveDeformableGroupIterations
virtual btScalar solveDeformableGroupIterations(btCollisionObject **bodies, int numBodies, btCollisionObject **deformableBodies, int numDeformableBodies, btPersistentManifold **manifoldPtr, int numManifolds, btTypedConstraint **constraints, int numConstraints, const btContactSolverInfo &infoGlobal, btIDebugDraw *debugDrawer)
Definition: btDeformableMultiBodyConstraintSolver.cpp:21
btDeformableMultiBodyConstraintSolver::solverBodyWriteBack
void solverBodyWriteBack(const btContactSolverInfo &infoGlobal)
Definition: btDeformableMultiBodyConstraintSolver.cpp:113
btDeformableRigidContactConstraint::m_contact
const btSoftBody::DeformableRigidContact * m_contact
Definition: btDeformableContactConstraint.h:149
btDispatcher
The btDispatcher interface class can be used in combination with broadphase to dispatch calculations ...
Definition: btDispatcher.h:77
btIDebugDraw
The btIDebugDraw interface class allows hooking up a debug renderer to visually debug simulations.
Definition: btIDebugDraw.h:27
btMultiBodyConstraintSolver::m_tmpMultiBodyConstraints
btMultiBodyConstraint ** m_tmpMultiBodyConstraints
Definition: btMultiBodyConstraintSolver.h:42
btMultiBodyConstraintSolver::m_tmpNumMultiBodyConstraints
int m_tmpNumMultiBodyConstraints
Definition: btMultiBodyConstraintSolver.h:43
btMultiBodyConstraintSolver::solveGroupCacheFriendlyFinish
virtual btScalar solveGroupCacheFriendlyFinish(btCollisionObject **bodies, int numBodies, const btContactSolverInfo &infoGlobal)
Definition: btMultiBodyConstraintSolver.cpp:1588
btMultiBodyConstraintSolver::solveGroupCacheFriendlySetup
virtual btScalar solveGroupCacheFriendlySetup(btCollisionObject **bodies, int numBodies, btPersistentManifold **manifoldPtr, int numManifolds, btTypedConstraint **constraints, int numConstraints, const btContactSolverInfo &infoGlobal, btIDebugDraw *debugDrawer)
Definition: btMultiBodyConstraintSolver.cpp:203
btMultiBodyConstraintSolver::solveSingleIteration
virtual btScalar solveSingleIteration(int iteration, btCollisionObject **bodies, int numBodies, btPersistentManifold **manifoldPtr, int numManifolds, btTypedConstraint **constraints, int numConstraints, const btContactSolverInfo &infoGlobal, btIDebugDraw *debugDrawer)
Definition: btMultiBodyConstraintSolver.cpp:28
btMultiBodyConstraint
Definition: btMultiBodyConstraint.h:57
btPersistentManifold
btPersistentManifold is a contact point cache, it stays persistent as long as objects are overlapping...
Definition: btPersistentManifold.h:65
btReducedDeformableBodySolver
Definition: btReducedDeformableBodySolver.h:10
btReducedDeformableBodySolver::m_nodeRigidConstraints
btAlignedObjectArray< btAlignedObjectArray< btReducedDeformableNodeRigidContactConstraint > > m_nodeRigidConstraints
Definition: btReducedDeformableBodySolver.h:24
btReducedDeformableNodeRigidContactConstraint
Definition: btReducedDeformableContactConstraint.h:122
btReducedDeformableRigidContactConstraint::setSolverBody
void setSolverBody(const int bodyId, btSolverBody &solver_body)
Definition: btReducedDeformableContactConstraint.cpp:81
btRigidBody
The btRigidBody is the main class for rigid body objects.
Definition: btRigidBody.h:60
btRigidBody::getInvMass
btScalar getInvMass() const
Definition: btRigidBody.h:263
btRigidBody::getAngularVelocity
const btVector3 & getAngularVelocity() const
Definition: btRigidBody.h:437
btRigidBody::upcast
static const btRigidBody * upcast(const btCollisionObject *colObj)
to keep collision detection and dynamics separate we don't store a rigidbody pointer but a rigidbody ...
Definition: btRigidBody.h:189
btRigidBody::getLinearVelocity
const btVector3 & getLinearVelocity() const
Definition: btRigidBody.h:433
btSequentialImpulseConstraintSolver::m_tmpSolverContactConstraintPool
btConstraintArray m_tmpSolverContactConstraintPool
Definition: btSequentialImpulseConstraintSolver.h:57
btSequentialImpulseConstraintSolver::m_maxOverrideNumSolverIterations
int m_maxOverrideNumSolverIterations
Definition: btSequentialImpulseConstraintSolver.h:66
btSequentialImpulseConstraintSolver::m_analyticsData
btSolverAnalyticsData m_analyticsData
Definition: btSequentialImpulseConstraintSolver.h:212
btSequentialImpulseConstraintSolver::m_leastSquaresResidual
btScalar m_leastSquaresResidual
Definition: btSequentialImpulseConstraintSolver.h:83
btSequentialImpulseConstraintSolver::m_tmpSolverBodyPool
btAlignedObjectArray< btSolverBody > m_tmpSolverBodyPool
Definition: btSequentialImpulseConstraintSolver.h:56
btSequentialImpulseConstraintSolver::m_orderTmpConstraintPool
btAlignedObjectArray< int > m_orderTmpConstraintPool
Definition: btSequentialImpulseConstraintSolver.h:62
btSequentialImpulseConstraintSolver::getOrInitSolverBody
int getOrInitSolverBody(btCollisionObject &body, btScalar timeStep)
Definition: btSequentialImpulseConstraintSolver.cpp:691
btSequentialImpulseConstraintSolver::resolveSplitPenetrationImpulse
btScalar resolveSplitPenetrationImpulse(btSolverBody &bodyA, btSolverBody &bodyB, const btSolverConstraint &contactConstraint)
Definition: btSequentialImpulseConstraintSolver.h:139
btSoftBody::DeformableRigidContact::m_cti
sCti m_cti
Definition: btSoftBody.h:362
btTypedConstraint
TypedConstraint is the baseclass for Bullet constraints and vehicles.
Definition: btTypedConstraint.h:76
btContactSolverInfoData::m_numIterations
int m_numIterations
Definition: btContactSolverInfo.h:44
btContactSolverInfoData::m_splitImpulse
int m_splitImpulse
Definition: btContactSolverInfo.h:56
btContactSolverInfoData::m_leastSquaresResidualThreshold
btScalar m_leastSquaresResidualThreshold
Definition: btContactSolverInfo.h:67
btContactSolverInfoData::m_timeStep
btScalar m_timeStep
Definition: btContactSolverInfo.h:42
btContactSolverInfo
Definition: btContactSolverInfo.h:76
btSoftBody::sCti::m_colObj
const btCollisionObject * m_colObj
Definition: btSoftBody.h:226
btSolverAnalyticsData::m_numIterationsUsed
int m_numIterationsUsed
Definition: btSequentialImpulseConstraintSolver.h:45
btSolverAnalyticsData::m_numContactManifolds
int m_numContactManifolds
Definition: btSequentialImpulseConstraintSolver.h:43
btSolverAnalyticsData::m_numSolverCalls
int m_numSolverCalls
Definition: btSequentialImpulseConstraintSolver.h:44
btSolverAnalyticsData::m_numBodies
int m_numBodies
Definition: btSequentialImpulseConstraintSolver.h:42
btSolverAnalyticsData::m_islandId
int m_islandId
Definition: btSequentialImpulseConstraintSolver.h:41
btSolverAnalyticsData::m_remainingLeastSquaresResidual
double m_remainingLeastSquaresResidual
Definition: btSequentialImpulseConstraintSolver.h:46
btSolverBody
The btSolverBody is an internal datastructure for the constraint solver. Only necessary data is packe...
Definition: btSolverBody.h:105
btSolverBody::m_angularVelocity
btVector3 m_angularVelocity
Definition: btSolverBody.h:116
btSolverBody::m_deltaLinearVelocity
btVector3 m_deltaLinearVelocity
Definition: btSolverBody.h:108
btSolverBody::m_deltaAngularVelocity
btVector3 m_deltaAngularVelocity
Definition: btSolverBody.h:109
btSolverBody::m_linearVelocity
btVector3 m_linearVelocity
Definition: btSolverBody.h:115
btSolverConstraint
1D constraint along a normal axis between bodyA and bodyB. It can be combined to solve contact and fr...
Definition: btSolverConstraint.h:31
btSolverConstraint::m_solverBodyIdA
int m_solverBodyIdA
Definition: btSolverConstraint.h:62
btSolverConstraint::m_solverBodyIdB
int m_solverBodyIdB
Definition: btSolverConstraint.h:63