27 July 2020 at 21 h 50 min #16967billParticipant
I would like to execute a piece of code when a collision is detected, using SofaPython. From what I can tell from the API, I would want to call getCollisionPipeline() on the rootNode and then I should be able to poll getResponseList() to find out if a collision has occurred (or something along those lines).
However, to my knowledge, this can’t be done using SofaPython because the getCollisionPipeline() api call is not implemented. Is there another way to do this?
Thank you10 August 2020 at 16 h 24 min #17015fedevParticipant
- University of Rome \"La Sapienza\"
Interested as well14 September 2020 at 23 h 13 min #17137HugoKeymaster
- SOFA Consortium
Two possible solutions, but at my best knowledge none have been yet implemented:
– creating a dedicated Event captured by Python when a contact really occurs (saved after the Narrow phase)
– calling a specific C++ function when a contact really occurs and binding this function in Python
@bmarques does such a question ring a bell?
Hugo9 December 2020 at 14 h 42 min #17988tschueliaParticipant
19 December 2020 at 0 h 25 min #18061HugoKeymaster
- Karlsruhe Institute of Technology
- SOFA Consortium
I do not think a function can be directly called from Python. This I will need to check.
However, you could add a ContactListener in your simulation and at each time step using your python script read into the collision information stored in this listener.
I could create a dedicated example in the SofaPython3 plugin in the first week of 2021.
Hugo22 January 2021 at 9 h 40 min #18375tschueliaParticipant
- Karlsruhe Institute of Technology
Hi Hugo, sorry for the very late response.
Using a ContactListener works perfectly, thank you 🙂28 April 2021 at 5 h 07 min #1932928 April 2021 at 9 h 03 min #19330
please note, that there is a difference between SofaPython and the Plugin SofaPython3.
If you are using SofaPython3, you can add a ContactListener with
listener = scene_node.addObject( "ContactListener", name="TestContactListener", collisionModel1=body1.collision.PointCollisionModel.getLinkPath(), collisionModel2=body2.collision.TriangleCollisionModel.getLinkPath(), )
This one will listen for contacts between PointCollisionModels on body1 and TriangleCollisionModels on body2.
Paul28 April 2021 at 17 h 41 min #19341
Thank you @scheikl, my simulation is built up using python2. So, it would be more convenient for me if your code can be converted to python2. I tried with this line but not success:
contactlistener.createObject('ContactListener', collisionModel1 = '@SkinCollision.LineCollisionModel', collisionModel2 = '@collisionFinger.LineCollisionModel')28 April 2021 at 18 h 23 min #19342
sadly I started using Sofa with SofaPython3 directly so I’ve never really used SofaPython2.
Is there an error message you could post?
Is the relative path to
Paul14 May 2021 at 7 h 47 min #19441
Thank you @scheikl for following up my problem, the general structure of my scene is shown below:
def createScene(rootNode): ... # Finger node finger = rootNode.createChild('finger') #collision collisionFinger = finger.createChild('collisionFinger') collisionFinger.createObject('MeshTopology', src='@loader', name='topo') collisionFinger.createObject('MechanicalObject', name='collisMech') collisionFinger.createObject('TriangleCollisionModel', name = 'triangle', selfCollision=0) collisionFinger.createObject('LineCollisionModel', name = 'line', selfCollision=False) collisionFinger.createObject('PointCollisionModel', name = 'point', selfCollision=False) # Skin node skin = rootNode.createChild('skin') # Collision skinCollision = skin.createChild('SkinCollision') skinCollision.createObject('MeshTopology', src='@loader', name='topology') skinCollision.createObject('MechanicalObject', name='collisMech') skinCollision.createObject('TriangleCollisionModel', name = 'triangle', selfCollision=0) skinCollision.createObject('LineCollisionModel', name = 'line', selfCollision=0) skinCollision.createObject('PointCollisionModel', name = 'point', selfCollision=0) # Contact listener contactlistener = rootNode.createChild('contactlistener') contactlistener.createObject('ContactListener', collisionModel1 = '@skin.SkinCollision', collisionModel2 = '@finger.collisionFinger')
However, an error message popped up when I loaded this scene:
[ERROR] [DAGNode(contactlistener)] Parsing Link "@skin.SkinCollision": a Data field name is specified while an object was expected. [ERROR] [DAGNode(contactlistener)] Parsing Link "@finger.collisionFinger": a Data field name is specified while an object was expected. [ERROR] [PythonScript] RuntimeError: Unable to create 'ContactListener' of type 'ContactListener' in node 'contactlistener'. Object type ContactListener<> was not created The object is in the factory but cannot be created. Requested template : None Used template : None Reason(s) : Data attributes 'collisionModel1' and 'collisionModel2' are not pointing to valid collision models.
It seems I did not set the paths for two propoerties ‘collisionModel1’ and ‘collisionModel2’. Could you (or any other suggestion will be appreciated) please point out what I did wrong? Thank you very much
btt14 May 2021 at 9 h 16 min #19444
collisionModel1 = '@skin.SkinCollision'you are not pointing to an actual collision model, but to a SofaNode that contains multiple collision models.
Try changing that to
contactlistener.createObject('ContactListener', collisionModel1 = '@skin.SkinCollision.TriangleCollisionModel', collisionModel2 = '@finger.collisionFinger.PointCollisionModel')
The object should now listen for collisions between the
TriangleCollisionModelof the skin and the
Paul14 May 2021 at 10 h 28 min #19445
Hi @Scheikl, I did follow your construction but the same error has appeared. Hope you have another idea. Anyway, I appreciate your kind support.
Nhan14 May 2021 at 12 h 32 min #19446
ContactListeneris not in the root node, so your path misses going up one step in the tree.
You could try
contactlistener.createObject('ContactListener', collisionModel1 = '@../skin.SkinCollision.TriangleCollisionModel', collisionModel2 = '@../finger.collisionFinger.PointCollisionModel')
Paul14 May 2021 at 14 h 59 min #1944714 May 2021 at 15 h 10 min #19448
I totally missed the fact, that you gave the models a specific name, sorry. 😀
Try replacing the type of Object (TriangleCollisionModel) with the name you gave it (triangle). Same for the PointCollisionModel.
Paul14 May 2021 at 15 h 14 min #19449
Hi @Scheikl, in fact, I did it already but nothing changed :). I tried to play around with this component for the last couple of days but it is still not successful :D.14 May 2021 at 18 h 44 min #19452
I just tested the scene, and the following works fine for me:
contactlistener.addObject( "ContactListener", collisionModel1="@/finger/collisionFinger/triangle", collisionModel2="@/skin/SkinCollision/point", )
Paul15 May 2021 at 15 h 36 min #19456
Hi @Scheikl, it is successfully added in SOFA scene. Now I am curious how to extract contact information by using python. I open up the property table of this component and see nothing (it seems wrong). Thank you for your patient.
btt16 May 2021 at 17 h 18 min #19458
you might want to check out SofaPython3.
There is a binding for the ContactListener, so you can create a ContactListener object with
listener = contactlistener.addObject( “ContactListener”, collisionModel1=”@/finger/collisionFinger/triangle”, collisionModel2=”@/skin/SkinCollision/point”, )
Now you can add any functions from the c++ code to create bindings for it.
Sadly I really do not know how to do that with SofaPython2.
- You must be logged in to reply to this topic.