Collisions not working without screen render

I am fairly new to this but am trying to make my own open AI gym environment. For this I would like to be able to run my simulation without rendering, so as to speed up the training process.

I have no issues running the programme without rendering but the collisions detection stops working when the window is not rendered. When the render function (within my code) is run the collision detection works fine.

Is it possible to make the collision detection work without the render?

I used loadPrcFileData("", “window-type none” ) to prevent a window opening. A snippet of my code is below:

class Collision(DirectObject):
    def __init__(self):
        self.basenode = render.attachNewNode('base node')
        self.PayloadNode = self.basenode.attachNewNode('Payload')
        self.PayloadNode.setHpr(self.rad_2_deg(payload[0]), self.rad_2_deg(payload[1]), self.rad_2_deg(payload[2]))
        self.PayloadNode.setPos(payload[3], payload[4], pay0load[5]
        self.eenode = self.link3node.attachNewNode("End Effector")
        self.eenode.setZ(np.amax(l[3]))
        self.eenode.setHpr(self.rad_2_deg(state[9]), 0, 0)

    def contact(self, base_dim, links, payload_size):
        self.collhandevent = CollisionHandlerEvent()
        self.collhandqueue = CollisionHandlerQueue()
        trav = CollisionTraverser('traverser')
        base.cTrav = trav

        colliderNode1 = CollisionNode("payload")
        position = LPoint3f(0,0,0)
        colliderNode1.addSolid(CollisionBox(position, payload_size[0]/2, payload_size[1]/2, payload_size[2]/2))
        payload_collision = self.PayloadNode.attachNewNode(colliderNode1)

        colliderNode2 = CollisionNode("gripper")
        colliderNode2.addSolid(CollisionSphere(0,0,0.15,0.05))
        end_effector_collision = self.eenode.attachNewNode(colliderNode2)
        end_effector_collision.show()

        self.collhandevent.addInPattern("payload-into-gripper")
        trav.addCollider(payload_collision, self.collhandevent)
        self.accept("payload-into-gripper", self.collide)

    def collide(self, event):
        print(1)
        self.done = True

There is a full node path between the base node and link3node. If I run the same code without window-type none, the collisions are detected.

Any help at all would be greatly appreciated!
Thanks so much

I’m not very familiar with the integrated collision handling of Panda3D and do not know why it would behave differently with or without a window. I do recall someone though, creating something rather similar, but used Bullet Physics instead, for handling the physics/collision part. Bullet let’s you run the do_physics(dt, ...) method, where the dt argument specifies the passed time since the last call, so you could set your step resolution and then run it as fast as your CPU can go, without rendering to screen/window.

On the above note, have you tried running a task and in that task calling “base.cTrav.traverse()”?

(It may be that the automatic calling of this method is done in some manner that relies on rendering, thus resulting in manual calling being required when attempting to work without rendering.)

No, I have not manually called that in the render class. Might be a silly question, but why does it need to be in a task and not just in the contact function?

Thanks

Not a silly question, I think. :slight_smile:

I’m not seeing from your code-snipped what calls the “contact” function. I’m guessing from the content that it’s some sort of initialisation function?

If so, and presuming that it’s called only once, then calling “traverse” inside it would update the physics only once.

In short, “traverse” orders the collision system to examine the current state of the system and respond to it. Thus it’s something that one (presumably) wants to have happen repeatedly, so that the system keeps updating and keeps responding. Hence the idea of placing it in a task, which might be made to continuously run it, once per frame.

Brilliant - thank you!! That does make sense. Only problem now is that it still doesn’t detect collisions. I did experiment however and using taskMgr.step() does the job, however it renders a window. Is there anyway to achieve the same functionality without the render?

Hm, odd–I’m surprised that using “traverse” alone didn’t work! In that case I don’t know, I’m afraid–perhaps one of the engine devs will have some insight!

No problem! Thank you for your help anyway! Although, just to check I am not missing something, will the system check for events from all nodes attached to the dummy node in the case of:

base.cTrav.traverse(dummy)

?

It should, I believe. If I’m not much mistaken, it would traverse from “dummy” down through the full scene-graph below that node.