RotationalLimitMotor stops working. Bug?

Hi,



while playing around with my PD-Controller I stumbled over a strange behavior of the RotationalLimitMotor I am using. When a motor-controlled node slows down, the motor stops working and the node is not moving anymore, even when a higher targetVelocity is applied later. I wrote a small program that reproduces the behaviour.



I am using jbullet. Don’t know about native bullet, does not work for me atm. If I set minimumVelocity to 0.6 or higher the motor will not stop anymore.

Any ideas why this is happening? Bug or am I getting something wrong? Cannot really investigate that much, I don’t know where to get the jbullet source. Original jbullet is different from the one used in jme.



[java]

package com.jme3test.motor;



import static com.jme3.math.FastMath.*;



import java.util.logging.Logger;



import jme3test.bullet.PhysicsTestHelper;



import com.bulletphysics.dynamics.constraintsolver.Generic6DofConstraint;

import com.bulletphysics.dynamics.constraintsolver.RotationalLimitMotor;

import com.jme3.app.SimpleApplication;

import com.jme3.bullet.BulletAppState;

import com.jme3.bullet.PhysicsSpace;

import com.jme3.bullet.collision.shapes.BoxCollisionShape;

import com.jme3.bullet.control.RigidBodyControl;

import com.jme3.bullet.joints.SixDofJoint;

import com.jme3.math.FastMath;

import com.jme3.math.Vector3f;

import com.jme3.scene.Node;



public class TestMotorBug extends SimpleApplication {

private static final Logger logger =

Logger.getLogger(TestMotorBug.class.getName());



private final float minimumVelocity = 0.5f;



private BulletAppState bulletAppState;



protected Generic6DofConstraint constraint;

protected RotationalLimitMotor motor2;



private float timePassed = 0;

private float lastFrameAngle;



public static void main(String[] args) {

TestMotorBug app = new TestMotorBug();

app.start();

}



@Override

public void simpleInitApp() {

bulletAppState = new BulletAppState();

stateManager.attach(bulletAppState);

bulletAppState.getPhysicsSpace().enableDebug(assetManager);

setupJoint();

}



private PhysicsSpace getPhysicsSpace() {

return bulletAppState.getPhysicsSpace();

}



private void setupJoint() {

Node holderNode =

PhysicsTestHelper.createPhysicsTestNode(assetManager,

new BoxCollisionShape(new Vector3f(.1f, .1f, .1f)), 0);

holderNode.getControl(RigidBodyControl.class).setPhysicsLocation(

new Vector3f(0f, 0, 0f));

rootNode.attachChild(holderNode);

getPhysicsSpace().add(holderNode);



Node hammerNode =

PhysicsTestHelper.createPhysicsTestNode(assetManager,

new BoxCollisionShape(new Vector3f(.3f, .3f, .3f)), 1);

hammerNode.getControl(RigidBodyControl.class).setPhysicsLocation(

new Vector3f(0f, 1, 0f));

rootNode.attachChild(hammerNode);

getPhysicsSpace().add(hammerNode);



SixDofJoint joint =

new SixDofJoint(holderNode.getControl(RigidBodyControl.class),

hammerNode.getControl(RigidBodyControl.class),

Vector3f.ZERO, new Vector3f(0f, 1, 0f), true);

getPhysicsSpace().add(joint);



constraint = (Generic6DofConstraint) joint.getObjectId();



joint.getRotationalLimitMotor(0).setEnableMotor(true);

joint.getRotationalLimitMotor(1).setEnableMotor(true);

motor2 = joint.getRotationalLimitMotor(2).getMotor();

motor2.enableMotor = true;



lastFrameAngle = constraint.getAngle(2);



motor2.maxMotorForce = 3;

}



@Override

public void simpleUpdate(float tpf) {

super.simpleUpdate(tpf);



timePassed += tpf;

float currentAngle = constraint.getAngle(2);

float angularVelocity = angleDistance(currentAngle, lastFrameAngle);



motor2.targetVelocity = 1 + minimumVelocity + FastMath.sin(timePassed);



logger.info("motorVel: " + motor2.targetVelocity + ", angleVel: " + angularVelocity);



lastFrameAngle = currentAngle;

}



private float angleDistance(float target, float source) {

float result = target - source;



if (result > PI) {

return result - TWO_PI;

}

else if (result < -PI) {

return result + TWO_PI;

}

else {

return result;

}

}

}



[/java]

@cmeyer said:
Hi,

while playing around with my PD-Controller I stumbled over a strange behavior of the RotationalLimitMotor I am using. When a motor-controlled node slows down, the motor stops working and the node is not moving anymore, even when a higher targetVelocity is applied later. I wrote a small program that reproduces the behaviour.

I am using jbullet. Don't know about native bullet, does not work for me atm. If I set minimumVelocity to 0.6 or higher the motor will not stop anymore.
Any ideas why this is happening? Bug or am I getting something wrong? Cannot really investigate that much, I don't know where to get the jbullet source. Original jbullet is different from the one used in jme.

Check if thats also the case in native bullet (just replace the libs). The used jbullet version only differs slightly from the main branch as the jbullet developer apparently isn't approachable and it will not be developed further.

Wow, this is weird. If I use native bullet from the current nightly build (http://jmonkeyengine.com/nightly/jME3_2012-07-07.zip) I get this error:

[java]

SEVERE: Uncaught exception thrown in Thread[LWJGL Renderer Thread,5,main]

java.lang.UnsatisfiedLinkError: com.jme3.bullet.PhysicsSpace.addConstraintC(JJZ)V

at com.jme3.bullet.PhysicsSpace.addConstraintC(Native Method)

at com.jme3.bullet.PhysicsSpace.addJoint(PhysicsSpace.java:631)

at com.jme3.bullet.PhysicsSpace.add(PhysicsSpace.java:401)

at com.jme3test.motor.TestMotorBug.setupJoint(TestMotorBug.java:68)

at com.jme3test.motor.TestMotorBug.simpleInitApp(TestMotorBug.java:40)

at com.jme3.app.SimpleApplication.initialize(SimpleApplication.java:225)

at com.jme3.system.lwjgl.LwjglAbstractDisplay.initInThread(LwjglAbstractDisplay.java:130)

at com.jme3.system.lwjgl.LwjglAbstractDisplay.run(LwjglAbstractDisplay.java:207)

at java.lang.Thread.run(Thread.java:722)

[/java]



Using an older build (jME3_2012-02-15) I will not get that error. But the problem occurs in the same way as with jbullet: If node slows down it stops and will not move again. Here is the new code. I had to change it a little because I used the jbullet classes before.

[java]

package com.jme3test.motor;



import java.util.logging.Logger;



import jme3test.bullet.PhysicsTestHelper;



import com.jme3.app.SimpleApplication;

import com.jme3.bullet.BulletAppState;

import com.jme3.bullet.PhysicsSpace;

import com.jme3.bullet.collision.shapes.BoxCollisionShape;

import com.jme3.bullet.control.RigidBodyControl;

import com.jme3.bullet.joints.SixDofJoint;

import com.jme3.bullet.joints.motors.RotationalLimitMotor;

import com.jme3.math.FastMath;

import com.jme3.math.Vector3f;

import com.jme3.scene.Node;



public class TestMotorBug extends SimpleApplication {

private static final Logger logger =

Logger.getLogger(TestMotorBug.class.getName());



private final float minimumVelocity = 0.3f;



private BulletAppState bulletAppState;



protected SixDofJoint constraint;

protected RotationalLimitMotor motor2;



private float timePassed = 0;



public static void main(String[] args) {

TestMotorBug app = new TestMotorBug();

app.start();

}



@Override

public void simpleInitApp() {

bulletAppState = new BulletAppState();

stateManager.attach(bulletAppState);

bulletAppState.getPhysicsSpace().enableDebug(assetManager);

setupJoint();

}



private PhysicsSpace getPhysicsSpace() {

return bulletAppState.getPhysicsSpace();

}



private void setupJoint() {

Node holderNode =

PhysicsTestHelper.createPhysicsTestNode(assetManager,

new BoxCollisionShape(new Vector3f(.1f, .1f, .1f)), 0);

holderNode.getControl(RigidBodyControl.class).setPhysicsLocation(

new Vector3f(0f, 0, 0f));

rootNode.attachChild(holderNode);

getPhysicsSpace().add(holderNode);



Node hammerNode =

PhysicsTestHelper.createPhysicsTestNode(assetManager,

new BoxCollisionShape(new Vector3f(.3f, .3f, .3f)), 1);

hammerNode.getControl(RigidBodyControl.class).setPhysicsLocation(

new Vector3f(0f, -1, 0f));

rootNode.attachChild(hammerNode);

getPhysicsSpace().add(hammerNode);



constraint =

new SixDofJoint(holderNode.getControl(RigidBodyControl.class),

hammerNode.getControl(RigidBodyControl.class),

Vector3f.ZERO, new Vector3f(0f, 1, 0f), true);

getPhysicsSpace().add(constraint);



motor2 = constraint.getRotationalLimitMotor(2);

motor2.setEnableMotor(true);



motor2.setMaxMotorForce(3);

}



@Override

public void simpleUpdate(float tpf) {

super.simpleUpdate(tpf);



timePassed += tpf;



motor2.setTargetVelocity(1 + minimumVelocity + FastMath.sin(timePassed));



logger.info("motorVel: " + motor2.getTargetVelocity());

}

}

[/java]

You are using an old version of the binaries. Use the updates in the SDK or the nightly version, for svn you have to build the binaries yourself.

Sorry, I did use the most current nightly version (jME3_2012-07-07.zip) and got the UnsatisfiedLinkError with native bullet. So I cannot test it with the current build :frowning:

I didn’t get that error with the old version (jME3_2012-02-15). Using the old version, the motor stops working as in jbullet.

Yay, finally managed to build the native bullet binaries myself… used revision 9540. UnsatisfiedLinkError is gone. The motor still stops working similar to jbullet.

I see. Then I guess the issue is that the body gets deactivated. Activate it before using the joint. Also why didn’t you just download the nightly like I said :?

You are right. It gets deactivated. If I activate it again it works. It seems to get deactivated when it is not moving anymore or just barely moving. Just stumbled over setSleepingThreshold. Probably I can prevent the deactivation if I put in some new values there.

So there is no bug and everything is working fine. Thank you for helping me with that issue :slight_smile:



Sorry, I did use the most current nightly version (jME3_2012-07-07.zip) and got the UnsatisfiedLinkError with native bullet.