Statistiques
| Révision :

root / MyDefaultContactManager.cpp @ 1

Historique | Voir | Annoter | Télécharger (15,15 ko)

1 1 rmalgat
/******************************************************************************
2 1 rmalgat
*       SOFA, Simulation Open-Framework Architecture, version 1.0 RC 1        *
3 1 rmalgat
*                (c) 2006-2011 MGH, INRIA, USTL, UJF, CNRS                    *
4 1 rmalgat
*                                                                             *
5 1 rmalgat
* This library is free software; you can redistribute it and/or modify it     *
6 1 rmalgat
* under the terms of the GNU Lesser General Public License as published by    *
7 1 rmalgat
* the Free Software Foundation; either version 2.1 of the License, or (at     *
8 1 rmalgat
* your option) any later version.                                             *
9 1 rmalgat
*                                                                             *
10 1 rmalgat
* This library is distributed in the hope that it will be useful, but WITHOUT *
11 1 rmalgat
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
12 1 rmalgat
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
13 1 rmalgat
* for more details.                                                           *
14 1 rmalgat
*                                                                             *
15 1 rmalgat
* You should have received a copy of the GNU Lesser General Public License    *
16 1 rmalgat
* along with this library; if not, write to the Free Software Foundation,     *
17 1 rmalgat
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.          *
18 1 rmalgat
*******************************************************************************
19 1 rmalgat
*                               SOFA :: Modules                               *
20 1 rmalgat
*                                                                             *
21 1 rmalgat
* Authors: The SOFA Team and external contributors (see Authors.txt)          *
22 1 rmalgat
*                                                                             *
23 1 rmalgat
* Contact information: contact@sofa-framework.org                             *
24 1 rmalgat
******************************************************************************/
25 1 rmalgat
//#include <sofa/component/collision/DefaultContactManager.h>
26 1 rmalgat
27 1 rmalgat
#include "MyDefaultContactManager.h"
28 1 rmalgat
#include <sofa/core/visual/VisualParams.h>
29 1 rmalgat
#include <sofa/core/ObjectFactory.h>
30 1 rmalgat
#include <sofa/core/objectmodel/Tag.h>
31 1 rmalgat
32 1 rmalgat
33 1 rmalgat
namespace sofa
34 1 rmalgat
{
35 1 rmalgat
36 1 rmalgat
namespace component
37 1 rmalgat
{
38 1 rmalgat
39 1 rmalgat
namespace collision
40 1 rmalgat
{
41 1 rmalgat
42 1 rmalgat
SOFA_DECL_CLASS(MyDefaultContactManager)
43 1 rmalgat
44 1 rmalgat
int MyDefaultContactManagerClass = core::RegisterObject("My Default class to create reactions to the collisions")
45 1 rmalgat
        .add< MyDefaultContactManager >()
46 1 rmalgat
        .addAlias("MyCollisionResponse")
47 1 rmalgat
        ;
48 1 rmalgat
49 1 rmalgat
MyDefaultContactManager::MyDefaultContactManager()
50 1 rmalgat
    : response(initData(&response, "response", "contact response class"))
51 1 rmalgat
    , responseParams(initData(&responseParams, "responseParams", "contact response parameters (syntax: name1=value1&name2=value2&...)"))
52 1 rmalgat
    //,deepInMeristem(0.0)
53 1 rmalgat
    ,deepInMeristem(initData(&deepInMeristem,"deepInMeristem","how deep we are in the meristem"))
54 1 rmalgat
    ,aTouche(initData(&aTouche,"aTouche","has there been a collision between the meristem and the indentor"))
55 1 rmalgat
    ,origine(initData(&origine,"origine","origine of collision between the meristem and the indentor"))
56 1 rmalgat
{
57 1 rmalgat
}
58 1 rmalgat
59 1 rmalgat
MyDefaultContactManager::~MyDefaultContactManager()
60 1 rmalgat
{
61 1 rmalgat
    // Contacts are now attached to the graph.
62 1 rmalgat
    // So they will be deleted by the DeleteVisitor
63 1 rmalgat
    // FIX crash on unload bug. -- J. Allard
64 1 rmalgat
    //clear();
65 1 rmalgat
}
66 1 rmalgat
67 1 rmalgat
sofa::helper::OptionsGroup MyDefaultContactManager::initializeResponseOptions(core::collision::Pipeline *pipeline)
68 1 rmalgat
{
69 1 rmalgat
    helper::set<std::string> listResponse;
70 1 rmalgat
    if (pipeline) listResponse=pipeline->getResponseList();
71 1 rmalgat
    else
72 1 rmalgat
    {
73 1 rmalgat
        core::collision::Contact::Factory::iterator it;
74 1 rmalgat
        for (it=core::collision::Contact::Factory::getInstance()->begin(); it!=core::collision::Contact::Factory::getInstance()->end(); ++it)
75 1 rmalgat
        {
76 1 rmalgat
            listResponse.insert(it->first);
77 1 rmalgat
        }
78 1 rmalgat
    }
79 1 rmalgat
    sofa::helper::OptionsGroup responseOptions(listResponse);
80 1 rmalgat
    if (listResponse.find("default") != listResponse.end())
81 1 rmalgat
        responseOptions.setSelectedItem("default");
82 1 rmalgat
    return responseOptions;
83 1 rmalgat
}
84 1 rmalgat
85 1 rmalgat
void MyDefaultContactManager::init()
86 1 rmalgat
{
87 1 rmalgat
88 1 rmalgat
    aTouche.setValue(false);
89 1 rmalgat
90 1 rmalgat
    if (response.getValue().size() == 0)
91 1 rmalgat
    {
92 1 rmalgat
        core::collision::Pipeline *pipeline=static_cast<simulation::Node*>(getContext())->collisionPipeline;
93 1 rmalgat
        response.setValue(initializeResponseOptions(pipeline));
94 1 rmalgat
    }
95 1 rmalgat
}
96 1 rmalgat
97 1 rmalgat
void MyDefaultContactManager::cleanup()
98 1 rmalgat
{
99 1 rmalgat
    for (sofa::helper::vector<core::collision::Contact::SPtr>::iterator it=contacts.begin(); it!=contacts.end(); ++it)
100 1 rmalgat
    {
101 1 rmalgat
        (*it)->removeResponse();
102 1 rmalgat
        (*it)->cleanup();
103 1 rmalgat
        //delete *it;
104 1 rmalgat
        it->reset();
105 1 rmalgat
    }
106 1 rmalgat
    contacts.clear();
107 1 rmalgat
    contactMap.clear();
108 1 rmalgat
}
109 1 rmalgat
110 1 rmalgat
void MyDefaultContactManager::createContacts(const DetectionOutputMap& outputsMap)
111 1 rmalgat
{
112 1 rmalgat
    using core::CollisionModel;
113 1 rmalgat
    using core::collision::Contact;
114 1 rmalgat
115 1 rmalgat
    int nbContact = 0;
116 1 rmalgat
117 1 rmalgat
        double origineActuelle[3];
118 1 rmalgat
119 1 rmalgat
120 1 rmalgat
        // First iterate on the collision detection outputs and look for existing or new contacts
121 1 rmalgat
        for (DetectionOutputMap::const_iterator outputsIt = outputsMap.begin(),
122 1 rmalgat
                outputsItEnd = outputsMap.end(); outputsIt != outputsItEnd ; ++outputsIt)
123 1 rmalgat
        {
124 1 rmalgat
                const helper::set<int>& myGroup_first=outputsIt->first.first->getGroups();
125 1 rmalgat
                const helper::set<int>& myGroup_second=outputsIt->first.second->getGroups();
126 1 rmalgat
        if (aTouche.getValue()){
127 1 rmalgat
                        helper::set<int>::iterator it_first=myGroup_first.begin();
128 1 rmalgat
                        helper::set<int>::iterator it_second=myGroup_second.begin();
129 1 rmalgat
                        if (*it_first == 1){
130 1 rmalgat
                                origineActuelle[0] = outputsIt->first.first->getContext()->getMechanicalState()->getPX(0);
131 1 rmalgat
                                origineActuelle[1] = outputsIt->first.first->getContext()->getMechanicalState()->getPY(0);
132 1 rmalgat
                                origineActuelle[2] = outputsIt->first.first->getContext()->getMechanicalState()->getPZ(0);
133 1 rmalgat
                deepInMeristem.setValue(std::sqrt(pow(origine.getValue()[0]-origineActuelle[0],2)+pow(origine.getValue()[1]-origineActuelle[1],2)+pow(origine.getValue()[2]-origineActuelle[2],2)));
134 1 rmalgat
                        }
135 1 rmalgat
                        else if (*it_second==1){
136 1 rmalgat
                                origineActuelle[0] = outputsIt->first.second->getContext()->getMechanicalState()->getPX(0);
137 1 rmalgat
                                origineActuelle[1] = outputsIt->first.second->getContext()->getMechanicalState()->getPY(0);
138 1 rmalgat
                                origineActuelle[2] = outputsIt->first.second->getContext()->getMechanicalState()->getPZ(0);
139 1 rmalgat
                deepInMeristem.setValue(std::sqrt(pow(origine.getValue()[0]-origineActuelle[0],2)+pow(origine.getValue()[1]-origineActuelle[1],2)+pow(origine.getValue()[2]-origineActuelle[2],2)));
140 1 rmalgat
                        }
141 1 rmalgat
        }
142 1 rmalgat
143 1 rmalgat
144 1 rmalgat
145 1 rmalgat
                std::pair<ContactMap::iterator,bool> contactInsert =
146 1 rmalgat
                        contactMap.insert(ContactMap::value_type(outputsIt->first,Contact::SPtr()));
147 1 rmalgat
                ContactMap::iterator contactIt = contactInsert.first;
148 1 rmalgat
                if (contactInsert.second)
149 1 rmalgat
                {
150 1 rmalgat
            // new contact
151 1 rmalgat
            //sout << "Creation new "<<contacttype<<" contact"<<sendl;
152 1 rmalgat
            CollisionModel* model1 = outputsIt->first.first;
153 1 rmalgat
            CollisionModel* model2 = outputsIt->first.second;
154 1 rmalgat
            std::string responseUsed = getContactResponse(model1, model2);
155 1 rmalgat
156 1 rmalgat
157 1 rmalgat
            if (*model1->getGroups().begin() == 1 && !aTouche.getValue()){
158 1 rmalgat
            if (!aTouche.getValue()){
159 1 rmalgat
                printf("Collision detected\n");
160 1 rmalgat
                                std::fflush(stdout);
161 1 rmalgat
162 1 rmalgat
                aTouche.setValue(true);
163 1 rmalgat
                sofa::helper::vector<double> actuelorigine;
164 1 rmalgat
                actuelorigine.push_back(model1->getContext()->getMechanicalState()->getPX(0));
165 1 rmalgat
                actuelorigine.push_back(model1->getContext()->getMechanicalState()->getPY(0));
166 1 rmalgat
                actuelorigine.push_back(model1->getContext()->getMechanicalState()->getPZ(0));
167 1 rmalgat
                origine.setValue(actuelorigine);
168 1 rmalgat
169 1 rmalgat
            }
170 1 rmalgat
                        }
171 1 rmalgat
            else if(*model2->getGroups().begin() == 1 && !aTouche.getValue()){
172 1 rmalgat
                                printf("Collision detected\n");
173 1 rmalgat
                                std::fflush(stdout);
174 1 rmalgat
175 1 rmalgat
                aTouche.setValue(true);
176 1 rmalgat
                sofa::helper::vector<double> actuelorigine;
177 1 rmalgat
                actuelorigine.push_back(model2->getContext()->getMechanicalState()->getPX(0));
178 1 rmalgat
                actuelorigine.push_back(model2->getContext()->getMechanicalState()->getPY(0));
179 1 rmalgat
                actuelorigine.push_back(model2->getContext()->getMechanicalState()->getPZ(0));
180 1 rmalgat
                origine.setValue(actuelorigine);
181 1 rmalgat
            }
182 1 rmalgat
183 1 rmalgat
                        std::fflush(stdout);
184 1 rmalgat
185 1 rmalgat
186 1 rmalgat
187 1 rmalgat
            // We can create rules in order to not respond to specific collisions
188 1 rmalgat
            if (!responseUsed.compare("null"))
189 1 rmalgat
            {
190 1 rmalgat
                                contactMap.erase(contactIt);
191 1 rmalgat
            }
192 1 rmalgat
                        else
193 1 rmalgat
                        {
194 1 rmalgat
                                Contact::SPtr contact = Contact::Create(responseUsed, model1, model2, intersectionMethod,
195 1 rmalgat
                                        this->f_printLog.getValue());
196 1 rmalgat
197 1 rmalgat
                                if (contact == NULL)
198 1 rmalgat
                                {
199 1 rmalgat
                                        std::string model1class = model1->getClassName();
200 1 rmalgat
                                        std::string model2class = model2->getClassName();
201 1 rmalgat
                                        int count = ++errorMsgCount[std::make_pair(responseUsed,
202 1 rmalgat
                                                std::make_pair(model1class, model2class))];
203 1 rmalgat
                                        if (count <= 10)
204 1 rmalgat
                                        {
205 1 rmalgat
                                                serr << "Contact " << responseUsed << " between " << model1->getClassName()
206 1 rmalgat
                                                        << " and " << model2->getClassName() << " creation failed" << sendl;
207 1 rmalgat
                                                if (count == 1)
208 1 rmalgat
                                                {
209 1 rmalgat
                                                        serr << "Supported models for contact " << responseUsed << ":" << sendl;
210 1 rmalgat
                                                        for (Contact::Factory::const_iterator it =
211 1 rmalgat
                                                                Contact::Factory::getInstance()->begin(),
212 1 rmalgat
                                                                itend = Contact::Factory::getInstance()->end(); it != itend; ++it)
213 1 rmalgat
                                                        {
214 1 rmalgat
                                                                if (it->first != responseUsed) continue;
215 1 rmalgat
                                                                serr << "   " << helper::gettypename(it->second->type()) << sendl;
216 1 rmalgat
                                                        }
217 1 rmalgat
                                                        serr << sendl;
218 1 rmalgat
                                                }
219 1 rmalgat
                                                if (count == 10) serr << "further messages suppressed" << sendl;
220 1 rmalgat
                                        }
221 1 rmalgat
                                        contactMap.erase(contactIt);
222 1 rmalgat
                                }
223 1 rmalgat
                                else
224 1 rmalgat
                                {
225 1 rmalgat
                                        contactIt->second = contact;
226 1 rmalgat
                                        contact->setName(model1->getName() + std::string("-") + model2->getName());
227 1 rmalgat
                                        setContactTags(model1, model2, contact);
228 1 rmalgat
                                        contact->f_printLog.setValue(this->f_printLog.getValue());
229 1 rmalgat
                                        contact->init();
230 1 rmalgat
                                        contact->setDetectionOutputs(outputsIt->second);
231 1 rmalgat
                                        ++nbContact;
232 1 rmalgat
                                }
233 1 rmalgat
                        }
234 1 rmalgat
                }
235 1 rmalgat
                else
236 1 rmalgat
                {
237 1 rmalgat
            // pre-existing and still active contact
238 1 rmalgat
            contactIt->second->setDetectionOutputs(outputsIt->second);
239 1 rmalgat
            ++nbContact;
240 1 rmalgat
                }
241 1 rmalgat
        }
242 1 rmalgat
243 1 rmalgat
        // Then look at previous contacts
244 1 rmalgat
        // and remove inactive contacts
245 1 rmalgat
        std::stack<ContactMap::iterator> deadContacts;
246 1 rmalgat
        for (ContactMap::iterator contactIt = contactMap.begin(), contactItEnd = contactMap.end();
247 1 rmalgat
                contactIt != contactItEnd;)
248 1 rmalgat
        {
249 1 rmalgat
                bool remove = false;
250 1 rmalgat
                DetectionOutputMap::const_iterator outputsIt = outputsMap.find(contactIt->first);
251 1 rmalgat
                if (outputsIt == outputsMap.end())
252 1 rmalgat
                {
253 1 rmalgat
            // inactive contact
254 1 rmalgat
            if (contactIt->second->keepAlive())
255 1 rmalgat
            {
256 1 rmalgat
                                contactIt->second->setDetectionOutputs(NULL);
257 1 rmalgat
                ++nbContact;
258 1 rmalgat
            }
259 1 rmalgat
            else
260 1 rmalgat
            {
261 1 rmalgat
                                remove = true;
262 1 rmalgat
                        }
263 1 rmalgat
                }
264 1 rmalgat
                if (remove)
265 1 rmalgat
                {
266 1 rmalgat
                        if (contactIt->second)
267 1 rmalgat
                        {
268 1 rmalgat
                contactIt->second->removeResponse();
269 1 rmalgat
                contactIt->second->cleanup();
270 1 rmalgat
                contactIt->second.reset();
271 1 rmalgat
                        }
272 1 rmalgat
                        ContactMap::iterator eraseIt = contactIt;
273 1 rmalgat
                        ++contactIt;
274 1 rmalgat
                        contactMap.erase(eraseIt);
275 1 rmalgat
                }
276 1 rmalgat
                else
277 1 rmalgat
                {
278 1 rmalgat
                        ++contactIt;
279 1 rmalgat
                }
280 1 rmalgat
        }
281 1 rmalgat
282 1 rmalgat
    // now update contactVec
283 1 rmalgat
    contacts.clear();
284 1 rmalgat
    contacts.reserve(nbContact);
285 1 rmalgat
    for (ContactMap::const_iterator contactIt = contactMap.begin(), contactItEnd = contactMap.end();
286 1 rmalgat
                contactIt != contactItEnd; ++contactIt)
287 1 rmalgat
    {
288 1 rmalgat
        contacts.push_back(contactIt->second);
289 1 rmalgat
    }
290 1 rmalgat
291 1 rmalgat
    // compute number of contacts attached to each collision model
292 1 rmalgat
    std::map< CollisionModel*, int > nbContactsMap;
293 1 rmalgat
    for (unsigned int i = 0; i < contacts.size(); ++i)
294 1 rmalgat
    {
295 1 rmalgat
        std::pair< CollisionModel*, CollisionModel* > cms = contacts[i]->getCollisionModels();
296 1 rmalgat
        nbContactsMap[cms.first]++;
297 1 rmalgat
        if (cms.second != cms.first)
298 1 rmalgat
            nbContactsMap[cms.second]++;
299 1 rmalgat
    }
300 1 rmalgat
301 1 rmalgat
        // TODO: this is VERY inefficient, should be replaced with a visitor
302 1 rmalgat
    helper::vector< CollisionModel* > collisionModels;
303 1 rmalgat
    simulation::Node* context = dynamic_cast< simulation::Node* >(getContext());
304 1 rmalgat
    context->getTreeObjects< CollisionModel >(&collisionModels);
305 1 rmalgat
306 1 rmalgat
    for (unsigned int i = 0; i < collisionModels.size(); ++i)
307 1 rmalgat
    {
308 1 rmalgat
        collisionModels[i]->setNumberOfContacts(nbContactsMap[collisionModels[i]]);
309 1 rmalgat
    }
310 1 rmalgat
}
311 1 rmalgat
312 1 rmalgat
std::string MyDefaultContactManager::getContactResponse(core::CollisionModel* model1, core::CollisionModel* model2)
313 1 rmalgat
{
314 1 rmalgat
    std::string responseUsed = response.getValue().getSelectedItem();
315 1 rmalgat
    std::string params = responseParams.getValue();
316 1 rmalgat
    if (!params.empty())
317 1 rmalgat
    {
318 1 rmalgat
        responseUsed += '?';
319 1 rmalgat
        responseUsed += params;
320 1 rmalgat
    }
321 1 rmalgat
    std::string response1 = model1->getContactResponse();
322 1 rmalgat
    std::string response2 = model2->getContactResponse();
323 1 rmalgat
324 1 rmalgat
    if (response1.empty()  &&  response2.empty()) return responseUsed;
325 1 rmalgat
    if (response1.empty()  && !response2.empty()) return response2;
326 1 rmalgat
    if (!response1.empty() &&  response2.empty()) return response1;
327 1 rmalgat
328 1 rmalgat
    if (response1 != response2) return responseUsed;
329 1 rmalgat
    else return response1;
330 1 rmalgat
}
331 1 rmalgat
332 1 rmalgat
void MyDefaultContactManager::draw(const core::visual::VisualParams* vparams)
333 1 rmalgat
{
334 1 rmalgat
    for (sofa::helper::vector<core::collision::Contact::SPtr>::iterator it = contacts.begin(); it!=contacts.end(); it++)
335 1 rmalgat
    {
336 1 rmalgat
        if ((*it)!=NULL)
337 1 rmalgat
            (*it)->draw(vparams);
338 1 rmalgat
    }
339 1 rmalgat
}
340 1 rmalgat
341 1 rmalgat
void MyDefaultContactManager::removeContacts(const ContactVector &c)
342 1 rmalgat
{
343 1 rmalgat
    ContactVector::const_iterator remove_it = c.begin();
344 1 rmalgat
    ContactVector::const_iterator remove_itEnd = c.end();
345 1 rmalgat
346 1 rmalgat
    ContactVector::iterator it;
347 1 rmalgat
    ContactVector::iterator itEnd;
348 1 rmalgat
349 1 rmalgat
    ContactMap::iterator map_it;
350 1 rmalgat
    ContactMap::iterator map_itEnd;
351 1 rmalgat
352 1 rmalgat
    while (remove_it != remove_itEnd)
353 1 rmalgat
    {
354 1 rmalgat
        // Whole scene contacts
355 1 rmalgat
        it = contacts.begin();
356 1 rmalgat
        itEnd = contacts.end();
357 1 rmalgat
358 1 rmalgat
        while (it != itEnd)
359 1 rmalgat
        {
360 1 rmalgat
            if (*it == *remove_it)
361 1 rmalgat
            {
362 1 rmalgat
                (*it)->removeResponse();
363 1 rmalgat
                (*it)->cleanup();
364 1 rmalgat
                it->reset();
365 1 rmalgat
                contacts.erase(it);
366 1 rmalgat
                break;
367 1 rmalgat
            }
368 1 rmalgat
369 1 rmalgat
            ++it;
370 1 rmalgat
        }
371 1 rmalgat
372 1 rmalgat
        // Stored contacts (keeping alive)
373 1 rmalgat
        map_it = contactMap.begin();
374 1 rmalgat
        map_itEnd = contactMap.end();
375 1 rmalgat
376 1 rmalgat
        while (map_it != map_itEnd)
377 1 rmalgat
        {
378 1 rmalgat
            if (map_it->second == *remove_it)
379 1 rmalgat
            {
380 1 rmalgat
                ContactMap::iterator erase_it = map_it;
381 1 rmalgat
                ++map_it;
382 1 rmalgat
383 1 rmalgat
                erase_it->second->removeResponse();
384 1 rmalgat
                erase_it->second->cleanup();
385 1 rmalgat
                erase_it->second.reset();
386 1 rmalgat
                contactMap.erase(erase_it);
387 1 rmalgat
            }
388 1 rmalgat
            else
389 1 rmalgat
            {
390 1 rmalgat
                ++map_it;
391 1 rmalgat
            }
392 1 rmalgat
        }
393 1 rmalgat
394 1 rmalgat
        ++remove_it;
395 1 rmalgat
    }
396 1 rmalgat
}
397 1 rmalgat
398 1 rmalgat
void MyDefaultContactManager::setContactTags(core::CollisionModel* model1, core::CollisionModel* model2, core::collision::Contact::SPtr contact)
399 1 rmalgat
{
400 1 rmalgat
    sofa::core::objectmodel::TagSet tagsm1 = model1->getTags();
401 1 rmalgat
    sofa::core::objectmodel::TagSet tagsm2 = model2->getTags();
402 1 rmalgat
    sofa::core::objectmodel::TagSet::iterator it;
403 1 rmalgat
    for(it=tagsm1.begin(); it != tagsm1.end(); it++)
404 1 rmalgat
        contact->addTag(*it);
405 1 rmalgat
    for(it=tagsm2.begin(); it!=tagsm2.end(); it++)
406 1 rmalgat
        contact->addTag(*it);
407 1 rmalgat
}
408 1 rmalgat
409 1 rmalgat
} // namespace collision
410 1 rmalgat
411 1 rmalgat
} // namespace component
412 1 rmalgat
413 1 rmalgat
} // namespace sofa