[VehicleControl] braking while accelerating

Hi,



I discovered that if an accelerate value is set on a PhysicsVehicle, the physics simulation seems to ignore the brake force.

Is this behavior intended? The vehicle should slow down, if I’m braking, even if I try to accelerate.



Did anyone have similar issues? For quick testing, just open up the TestPhysicsCar example from the jme tests and press forward and back button together.



I think it’s not a problem with jme3, it is a design decision (or bug) in bullet. I had a quick look at the btRaycastVehicle class and found this check in line 609.



The problem that I am facing is, that I tried to simulate a drivetrain and set an engine force on the vehicle on every physics step. Thus, the engine force is never zero and I am not able to brake.



[edit]:

In every physics step, I could check for a brake force, before applying any engine forces, but I think that bullet should handle this. Should I file a issue on the bullet bug tracking system?

The vehicle should not slow down that depends on the brake force. Using brakes and acceleration together works fine. Imagine the brake value as the friction of the wheels turning and the acceleration as the force turning the wheels.

I think I got that.



But if the brake force is high enough, the vehicle should slow down while accelerating, shouldn’t it?

Because the friction of the wheels would be higher than the force that turns the wheels.



For example, if you change the brakeForce in the TestPhysicsCar example to a very high value:

[java]

private final float brakeForce = 1000000.0f;

[/java]

(line 58)

the vehicle should stop if using brakes and acceleration together, but it seems

as if the vehicle just ignores the brake force and accelerates. Or am I still getting this wrong?

Hm, you might want to test around, it looks like the acceleration force itself basically ignores the current brake value as your code finding suggests, so you might want to correlate the brake force and acceleration value. However for the general friction of the wheels (to stop the car from rolling around) you need to set the brake value.

That is exactly the problem that I am facing now with the general friction of the wheels.

My drive train simulation sets an engine force (based on a simple engine simulation) on every physics step,

but if the brake value is ignored if an engine force is set, the simulation will fail, because the engine

never slows down, as the wheels have no friction.



I think I open an issue at bullet, maybe this behavior was intended, then I need to work around this. Otherwise

it’ll be fixed :slight_smile:



[edit]:

issued filed: http://code.google.com/p/bullet/issues/detail?id=590&thanks=590&ts=1326583667

Whats the issue? If you set an acceleration and brake value you know these and can counteract, e.g. “float finalAcceleration = acceleration - brake;”. You won’t see any fixes (especially coming all the way from native bullet) in jme3 any time soon.

Oh ok. I didn’t know that jme3 doesn’t use the latest bullet version :slight_smile:



I know that it is not a big problem to calculate the acceleration that way. I just thought that bullet should do it, instead of working around in the game itself.

Hey,



sorry normen, if I’m annoying you :slight_smile:



Here is what I’ve come up with. I extended the VehicleControl and added a container class WheelState that stores the engine and brake forces.



FrictionVehicleControl.java

[java]

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

import com.jme3.bullet.control.VehicleControl;

import com.jme3.bullet.objects.VehicleWheel;

import com.jme3.math.Vector3f;

import com.jme3.scene.Spatial;

import java.util.ArrayList;



public class FrictionVehicleControl extends VehicleControl {



public FrictionVehicleControl(CollisionShape shape, float mass) {

super(shape, mass);

}



public FrictionVehicleControl(CollisionShape shape) {

super(shape);

}



public FrictionVehicleControl() {

super();

}



protected class WheelState {

public WheelState() {

brakeForce = rollingFriction;

engineForce = 0f;

}

public float brakeForce;

public float engineForce;

}



protected ArrayList<WheelState> wheelStates = new ArrayList<WheelState>();

protected float rollingFriction = 20f;



@Override

public VehicleWheel addWheel(Spatial spat, Vector3f connectionPoint, Vector3f direction, Vector3f axle, float suspensionRestLength, float wheelRadius, boolean isFrontWheel) {

wheelStates.add(new WheelState());

return super.addWheel(spat, connectionPoint, direction, axle, suspensionRestLength, wheelRadius, isFrontWheel);

}



@Override

public void removeWheel(int wheel) {

wheelStates.remove(wheel);

super.removeWheel(wheel);

}



@Override

public void accelerate(float force) {

for (int i = 0; i < wheels.size(); i++) {

accelerate(i, force);

}

}



@Override

public void accelerate(int wheel, float force) {

WheelState ws = wheelStates.get(wheel);

ws.engineForce = force;

applyWheelState(wheel, ws);

}



@Override

public void brake(float force) {

for (int i = 0; i < wheels.size(); i++) {

brake(i, force);

}

}



@Override

public void brake(int wheel, float force) {

WheelState ws = wheelStates.get(wheel);

ws.brakeForce = force < rollingFriction ? rollingFriction : force;

applyWheelState(wheel, ws);

}



protected void applyWheelState(int wheel, WheelState ws) {

float delta = ws.engineForce - ws.brakeForce;



if (delta > 0) {

super.accelerate(wheel, delta);

super.brake(wheel, 0f);

} else {

super.accelerate(wheel, 0f);

super.brake(wheel, -delta);

}

}



}

[/java]



If it would be feasible to change VehicleWheel, I could provide a patch for jme3, that would add brake and engine forces to VehicleWheel class and merge FrictionVehicleControl into VehicleControl or PhysicsVehicle.

Is this extension reasonable, or should we just leave VehicleControl (or PhysicsVehicle) as it is?

No, we won’t change the default behavior of the bullet classes, thanks for posting anyway though, I guess this might be useful for somebody.

Ok, thanks for your help :slight_smile:



One last question though:



At one point in my code I need the delta rotation from the wheel for a calculation.

At the moment I get that value from the wheelInfo:

[java]

float deltaRotation = vehicleWheel.getWheelInfo().deltaRotation;

[/java]



The native bullet implementation of VehicleWheel does not have a getWheelInfo method and thus this won’t work with native bullet.

Could you add a getter method to VehicleWheel for the delta rotation as well (analogous to getSkidInfo) ? So I could write

[java]

float deltaRotation = vehicleWheel.getDeltaRotation();

[/java]

instead.

Or should I provide a patch?

yeah a patch is fine, remember both versions (native and java) need to add this method then, you are not supposed to access the wheelInfo object in java bullet either.

@normen jsut a intresting question,

whould it make sense to make all classes that are in both representations interfaces, and only expose the information/objects/methos through it that are both versions allowed to use. Because currently we have somewhat much duplicate code in both implementations and two classes for the same behaviour, but no generic interface. I think it would mkae sense, since it would also allow to switch between native and purejava without the need to change dozen occurences of those classes and the need to fix imports.

here is the patch, that adds a getDeltaRotation method to VehicleWheel (in native bullet and jbullet implementation):

1 Like

Cool, thanks

@EmpirePhoenix said:
I think it would mkae sense, since it would also allow to switch between native and purejava without the need to change dozen occurences of those classes and the need to fix imports.

No I don't think that would make sense, I thought a lot about this and the basic design of the wrapper already is accounting for the abstraction issue enough. Theres not much doubling in actual jME3 code, the rest is just a wrapper. With the new project structure e.g. all the controls etc. are not being doubled anymore and that is where any of the deeply jME3-specific code will be (rag doll etc). An abstraction layer only adds unnecessary complication as there is no intent in adding any other implementations. The jbullet version will at some point go to a "feature freeze" and kind of mark the "baseline" bullet support in jME3, then anything newly added (softbodys etc) only will work with the native version which will then eventually become the default version.