00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <sofa/component/collision/DefaultCollisionGroupManager.h>
00026 #include <sofa/core/CollisionModel.h>
00027 #include <sofa/helper/system/config.h>
00028 #include <sofa/helper/FnDispatcher.h>
00029 #include <sofa/helper/FnDispatcher.inl>
00030 #include <sofa/component/collision/DefaultCollisionGroupManager.h>
00031 #include <sofa/component/odesolver/EulerSolver.h>
00032 #include <sofa/component/odesolver/RungeKutta4Solver.h>
00033 #include <sofa/component/odesolver/CGImplicitSolver.h>
00034 #include <sofa/component/odesolver/StaticSolver.h>
00035 #include <sofa/component/odesolver/EulerImplicitSolver.h>
00036 #include <sofa/component/linearsolver/CGLinearSolver.h>
00037 #include <sofa/core/ObjectFactory.h>
00038 #include <string.h>
00039 #include <sofa/simulation/tree/GNode.h>
00040
00041
00042 namespace sofa
00043 {
00044
00045 namespace component
00046 {
00047
00048 namespace collision
00049 {
00050
00051 using namespace sofa::defaulttype;
00052 using namespace sofa::helper;
00053 using namespace core::componentmodel::behavior;
00054 using namespace core::componentmodel::collision;
00055
00056 SOFA_DECL_CLASS(DefaultCollisionGroupManager);
00057
00058 int DefaultCollisionGroupManagerClass = core::RegisterObject("Responsible for gathering colliding objects in the same group, for consistent time integration")
00059 .add< DefaultCollisionGroupManager >()
00060 .addAlias("CollisionGroup")
00061 ;
00062
00063 typedef std::pair<OdeSolver*,LinearSolver*> SolverSet;
00064
00065 class SolverMerger
00066 {
00067 public:
00068 static SolverSet merge(core::componentmodel::behavior::OdeSolver* solver1, core::componentmodel::behavior::OdeSolver* solver2);
00069
00070 protected:
00071
00072 FnDispatcher<core::componentmodel::behavior::OdeSolver, SolverSet> solverDispatcher;
00073
00074 SolverMerger ();
00075 };
00076
00077 DefaultCollisionGroupManager::DefaultCollisionGroupManager()
00078 {
00079 }
00080
00081 DefaultCollisionGroupManager::~DefaultCollisionGroupManager()
00082 {
00083 }
00084
00085 simulation::tree::GNode* DefaultCollisionGroupManager::buildCollisionGroup() {
00086 return new simulation::tree::GNode;
00087 }
00088
00089 void DefaultCollisionGroupManager::createGroups(core::objectmodel::BaseContext* scene, const sofa::helper::vector<Contact*>& contacts)
00090 {
00091 int groupIndex = 1;
00092 simulation::tree::GNode* groot = dynamic_cast<simulation::tree::GNode*>(scene);
00093 if (groot==NULL)
00094 {
00095 std::cerr << "DefaultCollisionGroupManager only support graph-based scenes.\n";
00096 return;
00097 }
00098
00099 simulation::tree::GNode* node = groot;
00100 if (node && !node->getLogTime()) node=NULL;
00101 simulation::tree::GNode::ctime_t t0 = 0;
00102
00103 if (node) t0 = node->startTime();
00104
00105
00106 std::map<simulation::tree::GNode*, simulation::tree::GNode*> mergedGroups;
00107 sofa::helper::vector<simulation::tree::GNode*> contactGroup;
00108 sofa::helper::vector<simulation::tree::GNode*> removedGroup;
00109 contactGroup.reserve(contacts.size());
00110 for(sofa::helper::vector<Contact*>::const_iterator cit = contacts.begin(); cit != contacts.end(); cit++)
00111 {
00112 Contact* contact = *cit;
00113 simulation::tree::GNode* group1 = getIntegrationNode(contact->getCollisionModels().first);
00114 simulation::tree::GNode* group2 = getIntegrationNode(contact->getCollisionModels().second);
00115 simulation::tree::GNode* group = NULL;
00116 if (group1==NULL || group2==NULL)
00117 {
00118 }
00119 else if (group1 == group2)
00120 {
00121
00122 group = group1;
00123 }
00124 else if (group1->getParent()!=NULL && group1->getParent() == group2->getParent())
00125 {
00126
00127
00128 SolverSet solver = SolverMerger::merge(group1->solver[0], group2->solver[0]);
00129 if (solver.first!=NULL)
00130 {
00131 simulation::tree::GNode* parent = group1->parent;
00132 bool group1IsColl = groupSet.find(group1)!=groupSet.end();
00133 bool group2IsColl = groupSet.find(group2)!=groupSet.end();
00134 if (!group1IsColl && !group2IsColl)
00135 {
00136 char groupName[32];
00137 snprintf(groupName,sizeof(groupName),"collision%d",groupIndex++);
00138
00139 group = buildCollisionGroup();
00140 group->setName(groupName);
00141 parent->addChild(group);
00142
00143 core::objectmodel::Context *current_context = dynamic_cast< core::objectmodel::Context *>(parent->getContext());
00144 group->copyVisualContext( (*current_context));
00145
00146 group->updateSimulationContext();
00147 group->moveChild(group1);
00148 group->moveChild(group2);
00149 groupSet.insert(group);
00150 }
00151 else if (group1IsColl)
00152 {
00153 group = group1;
00154
00155 if (!group2IsColl)
00156 {
00157 group->moveChild(group2);
00158 }
00159 else
00160 {
00161
00162 SolverSet solver2;
00163 solver2.first = group2->solver[0];
00164 group2->removeObject(solver2.first);
00165 if (!group2->linearSolver.empty())
00166 {
00167 solver2.second = group2->linearSolver[0];
00168 group2->removeObject(solver2.second);
00169 }
00170 else
00171 solver2.second = NULL;
00172 while(!group2->object.empty())
00173 group->moveObject(*group2->object.begin());
00174 while(!group2->child.empty())
00175 group->moveChild(*group2->child.begin());
00176 parent->removeChild(group2);
00177 groupSet.erase(group2);
00178 mergedGroups[group2] = group;
00179 delete solver2.first;
00180 if (solver2.second) delete solver2.second;
00181
00182 removedGroup.push_back(group2);
00183
00184 }
00185 }
00186 else
00187 {
00188
00189 group = group2;
00190 group->moveChild(group1);
00191 }
00192 if (!group->solver.empty())
00193 {
00194 OdeSolver* solver2 = group->solver[0];
00195 group->removeObject(solver2);
00196 delete solver2;
00197 }
00198 if (!group->linearSolver.empty())
00199 {
00200 LinearSolver* solver2 = group->linearSolver[0];
00201 group->removeObject(solver2);
00202 delete solver2;
00203 }
00204 group->addObject(solver.first);
00205 if (solver.second)
00206 group->addObject(solver.second);
00207 }
00208 }
00209 contactGroup.push_back(group);
00210 }
00211
00212 if (node) t0 = node->endTime(t0, "collision/groups", this);
00213
00214
00215 for(unsigned int i=0;i<contacts.size();i++)
00216 {
00217 Contact* contact = contacts[i];
00218 simulation::tree::GNode* group = contactGroup[i];
00219 while (group!=NULL && mergedGroups.find(group)!=mergedGroups.end())
00220 group = mergedGroups[group];
00221 if (group!=NULL)
00222 contact->createResponse(group);
00223 else
00224 contact->createResponse(scene);
00225 }
00226
00227 if (node) t0 = node->endTime(t0, "collision/contacts", this);
00228
00229
00230 for (sofa::helper::vector<simulation::tree::GNode*>::iterator it = removedGroup.begin(); it!=removedGroup.end(); ++it)
00231 delete *it;
00232 removedGroup.clear();
00233
00234
00235 groups.clear();
00236 for (std::set<simulation::tree::GNode*>::iterator it = groupSet.begin(); it!=groupSet.end(); ++it)
00237 groups.push_back(*it);
00238
00239
00240 }
00241
00242 void DefaultCollisionGroupManager::clearGroups(core::objectmodel::BaseContext* )
00243 {
00244 for (std::set<simulation::tree::GNode*>::iterator it = groupSet.begin(); it!=groupSet.end(); ++it)
00245 {
00246 simulation::tree::GNode* group = *it;
00247 simulation::tree::GNode* parent = group->parent;
00248 while(!group->child.empty())
00249 parent->moveChild(*group->child.begin());
00250 while(!group->object.empty())
00251 {
00252 core::objectmodel::BaseObject* obj = *group->object.begin();
00253 group->removeObject(obj);
00254 delete obj;
00255 }
00256 parent->removeChild(group);
00257 delete group;
00258 }
00259
00260 groupSet.clear();
00261 groups.clear();
00262 }
00263
00264 simulation::tree::GNode* DefaultCollisionGroupManager::getIntegrationNode(core::CollisionModel* model)
00265 {
00266 simulation::tree::GNode* node = dynamic_cast<simulation::tree::GNode*>(model->getContext());
00267 simulation::tree::GNode* lastSolver = NULL;
00268 while (node!=NULL)
00269 {
00270 if (!node->solver.empty()) lastSolver = node;
00271 node = node->parent;
00272 }
00273 return lastSolver;
00274 }
00275
00276
00277
00278
00279
00280
00281 namespace SolverMergers
00282 {
00283
00284
00285
00286 SolverSet createSolverEulerEuler(odesolver::EulerSolver& solver1, odesolver::EulerSolver& )
00287 {
00288 return SolverSet(new odesolver::EulerSolver(solver1), NULL);
00289 }
00290
00291 SolverSet createSolverRungeKutta4RungeKutta4(odesolver::RungeKutta4Solver& solver1, odesolver::RungeKutta4Solver& )
00292 {
00293 return SolverSet(new odesolver::RungeKutta4Solver(solver1), NULL);
00294 }
00295
00296 SolverSet createSolverCGImplicitCGImplicit(odesolver::CGImplicitSolver& solver1, odesolver::CGImplicitSolver& solver2)
00297 {
00298 odesolver::CGImplicitSolver* solver = new odesolver::CGImplicitSolver;
00299 solver->f_maxIter.setValue( solver1.f_maxIter.getValue() > solver2.f_maxIter.getValue() ? solver1.f_maxIter.getValue() : solver2.f_maxIter.getValue() );
00300 solver->f_tolerance.setValue( solver1.f_tolerance.getValue() < solver2.f_tolerance.getValue() ? solver1.f_tolerance.getValue() : solver2.f_tolerance.getValue());
00301 solver->f_smallDenominatorThreshold.setValue( solver1.f_smallDenominatorThreshold.getValue() < solver2.f_smallDenominatorThreshold.getValue() ? solver1.f_smallDenominatorThreshold.getValue() : solver2.f_smallDenominatorThreshold.getValue());
00302
00303 solver->f_rayleighStiffness.setValue( solver1.f_rayleighStiffness.getValue() < solver2.f_rayleighStiffness.getValue() ? solver1.f_rayleighStiffness.getValue() : solver2.f_rayleighStiffness.getValue() );
00304
00305 solver->f_rayleighMass.setValue( solver1.f_rayleighMass.getValue() < solver2.f_rayleighMass.getValue() ? solver1.f_rayleighMass.getValue() : solver2.f_rayleighMass.getValue() );
00306 solver->f_velocityDamping.setValue( solver1.f_velocityDamping.getValue() > solver2.f_velocityDamping.getValue() ? solver1.f_velocityDamping.getValue() : solver2.f_velocityDamping.getValue());
00307 return SolverSet(solver, NULL);
00308 }
00309
00310 typedef linearsolver::CGLinearSolver<simulation::GraphScatteredMatrix,simulation::GraphScatteredVector> DefaultCGLinearSolver;
00311
00312 LinearSolver* createLinearSolver(OdeSolver* solver1, OdeSolver* solver2)
00313 {
00314 DefaultCGLinearSolver* lsolver = new DefaultCGLinearSolver;
00315 DefaultCGLinearSolver* lsolver1 = NULL; if (solver1!=NULL) solver1->getContext()->get(lsolver1, core::objectmodel::BaseContext::SearchDown);
00316 DefaultCGLinearSolver* lsolver2 = NULL; if (solver2!=NULL) solver2->getContext()->get(lsolver2, core::objectmodel::BaseContext::SearchDown);
00317 unsigned int maxIter = 0;
00318 double tolerance = 1.0e10;
00319 double smallDenominatorThreshold = 1.0e10;
00320 if (lsolver1)
00321 {
00322 if (lsolver1->f_maxIter.getValue() > maxIter) maxIter = lsolver1->f_maxIter.getValue();
00323 if (lsolver1->f_tolerance.getValue() < tolerance) tolerance = lsolver1->f_tolerance.getValue();
00324 if (lsolver1->f_smallDenominatorThreshold.getValue() > smallDenominatorThreshold) smallDenominatorThreshold = lsolver1->f_smallDenominatorThreshold.getValue();
00325 }
00326 if (lsolver2)
00327 {
00328 if (lsolver2->f_maxIter.getValue() > maxIter) maxIter = lsolver2->f_maxIter.getValue();
00329 if (lsolver2->f_tolerance.getValue() < tolerance) tolerance = lsolver2->f_tolerance.getValue();
00330 if (lsolver2->f_smallDenominatorThreshold.getValue() > smallDenominatorThreshold) smallDenominatorThreshold = lsolver2->f_smallDenominatorThreshold.getValue();
00331 }
00332 if (maxIter > 0) lsolver->f_maxIter.setValue( maxIter );
00333 if (tolerance < 1.0e10) lsolver->f_tolerance.setValue( tolerance );
00334 if (smallDenominatorThreshold < 1.0e10) lsolver->f_smallDenominatorThreshold.setValue( smallDenominatorThreshold );
00335 return lsolver;
00336 }
00337
00338 SolverSet createSolverEulerImplicitEulerImplicit(odesolver::EulerImplicitSolver& solver1, odesolver::EulerImplicitSolver& solver2)
00339 {
00340 odesolver::EulerImplicitSolver* solver = new odesolver::EulerImplicitSolver;
00341 solver->f_rayleighStiffness.setValue( solver1.f_rayleighStiffness.getValue() < solver2.f_rayleighStiffness.getValue() ? solver1.f_rayleighStiffness.getValue() : solver2.f_rayleighStiffness.getValue() );
00342
00343 solver->f_rayleighMass.setValue( solver1.f_rayleighMass.getValue() < solver2.f_rayleighMass.getValue() ? solver1.f_rayleighMass.getValue() : solver2.f_rayleighMass.getValue() );
00344 solver->f_velocityDamping.setValue( solver1.f_velocityDamping.getValue() > solver2.f_velocityDamping.getValue() ? solver1.f_velocityDamping.getValue() : solver2.f_velocityDamping.getValue());
00345 return SolverSet(solver, createLinearSolver(&solver1, &solver2));
00346 }
00347
00348 SolverSet createSolverStaticSolver(odesolver::StaticSolver& solver1, odesolver::StaticSolver& solver2)
00349 {
00350 return SolverSet(new odesolver::StaticSolver(solver1), createLinearSolver(&solver1, &solver2));
00351 }
00352
00353
00354
00355 SolverSet createSolverRungeKutta4Euler(odesolver::RungeKutta4Solver& solver1, odesolver::EulerSolver& )
00356 {
00357 return SolverSet(new odesolver::RungeKutta4Solver(solver1), NULL);
00358 }
00359
00360 SolverSet createSolverCGImplicitEuler(odesolver::CGImplicitSolver& solver1, odesolver::EulerSolver& )
00361 {
00362 return SolverSet(new odesolver::CGImplicitSolver(solver1), NULL);
00363 }
00364
00365 SolverSet createSolverCGImplicitRungeKutta4(odesolver::CGImplicitSolver& solver1, odesolver::RungeKutta4Solver& )
00366 {
00367 return SolverSet(new odesolver::CGImplicitSolver(solver1), NULL);
00368 }
00369
00370 SolverSet createSolverEulerImplicitEuler(odesolver::EulerImplicitSolver& solver1, odesolver::EulerSolver& )
00371 {
00372 return SolverSet(new odesolver::EulerImplicitSolver(solver1), createLinearSolver(&solver1, NULL));
00373 }
00374
00375 SolverSet createSolverEulerImplicitRungeKutta4(odesolver::EulerImplicitSolver& solver1, odesolver::RungeKutta4Solver& )
00376 {
00377 return SolverSet(new odesolver::EulerImplicitSolver(solver1), createLinearSolver(&solver1, NULL));
00378 }
00379
00380 SolverSet createSolverEulerImplicitCGImplicit(odesolver::EulerImplicitSolver& solver1, odesolver::CGImplicitSolver& )
00381 {
00382 return SolverSet(new odesolver::EulerImplicitSolver(solver1), createLinearSolver(&solver1, NULL));
00383 }
00384
00385 }
00386
00387
00388 using namespace SolverMergers;
00389
00390 SolverSet SolverMerger::merge(core::componentmodel::behavior::OdeSolver* solver1, core::componentmodel::behavior::OdeSolver* solver2)
00391 {
00392 static SolverMerger instance;
00393 return instance.solverDispatcher.go(*solver1, *solver2);
00394 }
00395
00396 SolverMerger::SolverMerger()
00397 {
00398 solverDispatcher.add<odesolver::EulerSolver,odesolver::EulerSolver,createSolverEulerEuler,false>();
00399 solverDispatcher.add<odesolver::RungeKutta4Solver,odesolver::RungeKutta4Solver,createSolverRungeKutta4RungeKutta4,false>();
00400 solverDispatcher.add<odesolver::CGImplicitSolver,odesolver::CGImplicitSolver,createSolverCGImplicitCGImplicit,false>();
00401 solverDispatcher.add<odesolver::EulerImplicitSolver,odesolver::EulerImplicitSolver,createSolverEulerImplicitEulerImplicit,false>();
00402 solverDispatcher.add<odesolver::RungeKutta4Solver,odesolver::EulerSolver,createSolverRungeKutta4Euler,true>();
00403 solverDispatcher.add<odesolver::CGImplicitSolver,odesolver::EulerSolver,createSolverCGImplicitEuler,true>();
00404 solverDispatcher.add<odesolver::CGImplicitSolver,odesolver::RungeKutta4Solver,createSolverCGImplicitRungeKutta4,true>();
00405 solverDispatcher.add<odesolver::EulerImplicitSolver,odesolver::EulerSolver,createSolverEulerImplicitEuler,true>();
00406 solverDispatcher.add<odesolver::EulerImplicitSolver,odesolver::RungeKutta4Solver,createSolverEulerImplicitRungeKutta4,true>();
00407 solverDispatcher.add<odesolver::EulerImplicitSolver,odesolver::CGImplicitSolver,createSolverEulerImplicitCGImplicit,true>();
00408 solverDispatcher.add<odesolver::StaticSolver,odesolver::StaticSolver,createSolverStaticSolver,true>();
00409 }
00410
00411 }
00412
00413 }
00414
00415 }