Panda Bullet

Wow, that was fast. I have downloaded the code and log, but it is past midnight already. So I will have a look at it tomorrow evening.

here is graph :slight_smile:
tinyurl.com/3prhkgv

and here is new code, if it complains, just make x.txt in same dir as script
pastie.org/2505321

press Esc to save new data to file (it wont exit script, you have to click on Exit button)

You can use this to generate graphs, just copy paste into data

code.google.com/apis/chart/image … izard.html

enn0x, many thanks for the clarifications! :smiley:
I suppose they should be included in the manual… I can try writing that bit, if you’re busy ^_^"

Yup, I assumed that Panda had such hooks… Since it’s not, it’s really easier to do in Python.

That’s a natural solution… However, I’m afraid that joint will not hold bodies in exactly same position/orientation to each other, especially when big forces are applied.
Also, I suppose solving several constrained bodies is less effective than using one body with several collision shapes?

Oops! :blush: Somewhy I overlooked removeShape() even though I read through the method list several times… Sorry ^^

Then, I guess, I’ll just have to transform primitives to convex shapes if they have scale/shear :wink:

x = str(disty*dt*1000)

The quantity you collect is elapsed time (dt) times the distance moved. To get the speed you would have to divide: v = disty / dt.
I modified you code a little bit to collect some more data:

    def processInput(self): #@IndentOk
        speed = Vec3(0, 3, 0)
        omega = 0.0
        
        self.player.setAngularVelocity(omega)
        self.player.setLinearVelocity(speed, True)
    
    def update(self, task):
        dt = globalClock.getDt()
        self.processInput()

        pos = self.playerNP.getPos()
        t1 = time.clock()
        self.world.doPhysics(dt, 10, 0.008)
        t2 = time.clock()
        pos2 = self.playerNP.getPos()

        t = time.clock()
        t12 = t2 - t1
        dy = pos2[1]-pos[1]
        vy = dy / dt

        line = '\t'.join(['%.6f' % x for x in [t, dt, t12, dy, vy]]) + '\n'
        self.strings.append(line)
    
        return task.cont

Here is what I get:
http://enn0x.p3dp.com/lag.png
The first graph is the elapsed time (dt).
The second one is the distance moved.
The thrid one the calculated speed (dy/dt)
The last one is the time spent within doPhysics.

Looking at the last graph it seem like the drops in speed are not related to very long doPhysics calls. But it seems like the drops in speed are related to unusual long frames: every drop in speed is aligned with a high value for dt. Funny thing, on every long frame follows a short frame.

I don’t know yet what this means, but it is a first hint.

Ok, something really weird, i just tried running sample, and i got fluid movement…?
I just restarted my computer couple of hours ago, and this is first time i run python since restart, altough i have no idea why i would not see that bug again…
and judgin from your graph and my data, it looks like we both get(i dont anymore, but earlier tests) spikes at rougly same interval…

Ok, i am obviously doing something wrong, maybe its not even bug, only my wrongdoing…

Character moves at different speeds with frame limit on and off.
When i run sample at 60 FPS, char is fast, and when i run it 800 its slow…

i tried passing this argument to setLinearVelocity(speed/dt) it seems that now char is moving steady and does not care about framerate.
Maybe you dont need to pass dt in wrapper function? because bullet takes care of it automatically?
I took a look at sources, and everything seemed fine, but i was tired at that moment, and i am too tired to look at it now

Sure. Contributions to the documentation are always appreciated. Maybe it’s a good idea to add a “FAQ” or “tips and tricks” page at the end of the Bullet section.

Umm… at 800 FPS the elapsed time is probably smaller than the value you pass for the fixed stepsize (that last of the three parameters in doPhysics. This means that Bullet won’t simulate, but only interpolate. Try something like this: doPhysics(dt, 5, 0.001).

Still, something is wrong on the C++ side. I try to investigate some more.

Yeah, i tried playing with those arguments, i go for 10 substeps when testing, and time around 1 milisecond too.

Only thing that helps is dividing speed vector with delta time…

But deal is that i took a look at bullet source(kinematic character controller), and i had no idea how it would work if speed is not multiplied with deltatime.

And please, verify what i write here by yourself, there is good chance that i am doing something wrong.

this works perfectly, no lag at all.

    def processInput(self):
        speed = Vec3(0, 0, 0)
        omega = 0.0
        dt = globalClock.getDt()
        s = 0.005
        if inputState.isSet('forward'): speed.setY( s)
        if inputState.isSet('reverse'): speed.setY(-s)
        if inputState.isSet('left'):    speed.setX(-s)
        if inputState.isSet('right'):   speed.setX( s)
        if inputState.isSet('turnLeft'):  omega =  120.0
        if inputState.isSet('turnRight'): omega = -120.0
        x = speed/dt
        
        self.player.setAngularVelocity(omega)
        self.player.setLinearVelocity(x, True)

Ok, it seems that problem is in “simulation?”.
If i define stepSize (third argument), form you explanation this makes bullet simulate instead of interpolate? Changing stepsize effectively changes speed of simulation.

Could you throw a quick explanation, or maybe link to some article explaining how stepSize works? I thought only first argument has impact on speed of simulation (dt), and i was kind of thinking that other 2 are only for controlling “quality” of simulation.

This article explains the stepping quite well:
http://bulletphysics.org/mediawiki-1.5.8/index.php/Stepping_The_World

Thanks for link ennox, i have somewhat better understanding.

New bug discovered, i create some “level” in blender, it has Plane for ground, and some totally random mesh to serve as test for obstacles.
Exported with chicken.

When i load that mesh in panda with

        geom = loader.loadModel('models/lv.egg').findAllMatches('**/+GeomNode').getPath(0).node().getGeom(0)
        mesh = BulletTriangleMesh()
        mesh.addGeom(geom)
        shape = BulletTriangleMeshShape(mesh, dynamic=False)

ground plane is is shown as 2 triangles with debug drawing, and at that diagonal line character stutters, or is even COMPLETELY blocked by it in some cases.

EDIT1: What is your preffered way of reporting bugs?
It’s kind of easy to loose track of things if all is posted in this topic. Are you fine with us reporting bullet bugs to launchpad?

Yes, it is easy to loose track of things. On the other hand, 90 percent of all so-called bugs from this thread have not been bugs at all. For the remaining 10 percent the bug showed up only after exchanging several posts. Anyway, I don’t mind you using the launchpad bugtracker.

About your plane problem: please upload this lv.egg model somewhere.

By the way: if you would have reported this using a bugtracker I would have set the bug to “INVALID/WORKS FOR ME”, since it is not possible to reproduce your problem with the information given and I already have a sample where a character walks over a triangle mesh quad. Hence not a bug. A bugtracker is not the right medium to explain software usage, so the bug is closed immediately. Mind you, I don’t say that there is no bug - it’s just you don’t have been able to describe it properly yet.

Here is sample, run main.py to see it, lv.egg is in archive too, so you can test it in its pure form.

dl.dropbox.com/u/14000546/x.7z

Oh, and please ignore fact that ralph is facing in wrong direction, i started working on camera, so removed Heading fix.

Your problems are in Game.py, the update method:

        self.world.btWorld.doPhysics(dt,10,0.001)
        self.world.processInput()

Two things to do better:

1.) You step the simulation first, and then process the input. You should do it the other way round.

2.) The game runs at 60 FPS, so dt is about 0.016 seconds. You tell Bullet to use a substep size of 0.001 seconds (1/1000, which is really small!), and do a maximum of 10 substeps. 10 substeps, each 0.001 seconds, is 0.01 seconds, right? Less than 1/60 seconds.

Try this:

        self.world.processInput()
        self.world.btWorld.doPhysics(dt, 5, 0.005)

You will notice a slight hickup when the character passes over the diagonal edge, but it will pass over it. The hickup can be reduced by using smaller triangles. Subdivide the plane a few times in blender.

Thanks :slight_smile:

Ok, I think the “blocked character” problem is solved.

I took a few long-term measurements of the characters speed, meaning I did compute the characters speed from it’s position every 2 seconds. I turns out that for me the character movement is no independent from the framerate. No matter if I pass speed, speed/dt or speed*dt to setLinearSpeed.

This is not the way it should be. The value passed to setLinearSpeed should be a velocity, and not dependent of elapsed time or frame rate. I have neither an explanation nor solution so far, but will keep investigating.

Hi,
I just renewed some Panda activities I left in sleeping mode for the last couple of month.
Now trying and running my bullet code I’m getting the surprise to experience a scale change in BulletSphereShape attached to hands of my character.

Using the same code, I’m now getting a ‘shrink’ of the nodes by roughly a factor of 10?!

This is the way I’m attaching kinematic bullet nodes to my exposed joints

void attach_hit_sphere_to_node(NodePath node, int radius, char *name) {
    PT(BulletSphereShape) shapeS = new BulletSphereShape(radius);
    PT(BulletRigidBodyNode) hitRigidBody = new BulletRigidBodyNode(name);

    NodePath hitNP = worldNP.attach_new_node(hitRigidBody);
    hitRigidBody->set_kinematic(true);
    hitRigidBody->set_mass(0);
    hitRigidBody->add_shape(shapeS);

    hitRigidBody->set_restitution(0.25);
    hitRigidBody->set_friction(0.2);

    hitNP.set_collide_mask(BitMask32::all_on());

    hitRigidBody->set_deactivation_enabled(false);
    hitRigidBody->set_debug_enabled(true);
    mgr->attach_rigid_body(hitRigidBody);

    hitNP.reparent_to(node);
 hitRigidBody->set_active(true);         
}

// call sequence
...
attach_hit_sphere_to_node(pantin.exposed_LFoot,1,"bullet_lfoot");
   attach_hit_sphere_to_node(pantin.exposed_RFoot,1,"bullet_rfoot");
   attach_hit_sphere_to_node(pantin.exposed_LHand,1,"bullet_lhand");
   attach_hit_sphere_to_node(pantin.exposed_RHand,1,"bullet_rhand");
...

I don’t see this phenomenon on bullet nodes other than these kinematic nodes attached to my character joints.

Has anything related to scale changed in the recent past?

BTW. On top of that, I’m still getting the lag issue already mentionned several times. I’ve not had the opportunity and time to dig into the problem, but it is still there.

Yes, there has been a change in the scene graph synchronization. It has been discussed in several posts here in this thread. Might be there are still bugs in the new code. I need at least the following information:

  • The scale of the parent of your RigidBodyNode
  • The scale of your RigidBodyNode
  • The initial size of your object
  • The effective size of your object
    Not at the time of creation, but during simulation. That is, right before the world->do_physics call.

Please dig further. I’d like to know where it comes from. Oh, and if you have time try to slap up a sample which (1) reproduces this problem, and (2) measures the lag. Can be a C++ sample.

By the way, why do you initially create hitNP as a child of worldNP, and then reparent to node?

Hi,
Sorry for the delay in answering, I don’t have spare time to dedicate to Panda these days…

Ok, here it is :

NodePath hitNP = node.attach_new_node(hitRigidBody);
std::cout << "hitNP scale: " << hitNP.get_scale() << " parent scale: " << node.get_scale() << "\n";
std::cout << "hitNP scale (wrt render): " << hitNP.get_scale(render) << " parent scale (wrt render): " << node.get_scale(render) << "\n";
std::cout << "actor scale (wrt render): " << Actor.get_scale(render) << "\n";

gives:

hitNP scale: 1 1 1 parent scale: 1 1 1
hitNP scale (wrt render): 0.1 0.1 0.1  parent scale (wrt render): 0.1 0.1 0.1
actor scale (wrt render): 0.1 0.1 0.1

With :

Actor = window->load_model(pframework->get_models(), "model.egg");
Actor.set_scale(0.1);
Actor.set_effect(CompassEffect::make(window->get_render(), CompassEffect::P_scale));
exposed_LHand = Actor.attach_new_node("exposed_LHand");
extract_exposed_joint(&exposed_LHand, "LHand");

I think I got it: seems that shape geometry is scaled wrt to the node it is attached to, so:
PT(BulletSphereShape) shapeS = new BulletSphereShape(radius);
hitRigidBody->add_shape(shapeS);

radius is actually radius*hitNP.get_scale(render)*render_unit , correct?

So assuming my render unit is 10cm, if I want to get a 10cm bullet collision sphere attached
to the hand joint of the actor I have to choose radius = 10 ie 10*(0.1*10cm) = 10cm

Now the question is: what about the mass and velocity, are they influenced by the scale of the parent node??

One issue clarifyied!
When I have some time I’ll try and dig into the “lag phenomenon”. I’m afraid this one is not easy!

Cheers
Jean-Claude