Problem with linear Velocity and linear Damping

Hey monkeys,

I try to write helicopter flight program. The helicopter shoud collide and accelerate with WASD into the chosen direction. Rotation around Y-axis and the UP/DOWN movement is realized with the arrow keys. The helicopter is build with 3 spatials. Body, mainrotor and rearrotor. These three spatials are attached to one “PlayerNode”. PlayerNode has a RigidBodyControl so the acceleration works with the setLinearVelocity(). If the key, which was pressed, is released, the model is flying into the last chosen direction. For that I use the setLinearDamping(). It slows down and stands on one place.

Now my problem. If I press a key into another direction the model “jumps” in the old direction and after that it accelerates into the new direction. For example: W is pressed for forward. W is released, heli slows down. S is pressed for backward. heli jumps forward, slows down and accelerates backwards. How can I avoid this jump?

Here is my steering code:

public class KeyBehavior implements ActionListener,AnalogListener{
    static boolean forward, backward, leftward,rightward,upward,downward, rotateR, rotateL = false;
    static float speed;
    static boolean Engine;
    static final Quaternion DEG1dot25p   = new Quaternion().fromAngleAxis(FastMath.PI/144,   new Vector3f(0,1,0));
    static final Quaternion DEG1dot25m   = new Quaternion().fromAngleAxis(-FastMath.PI/144,   new Vector3f(0,1,0));
   
    static Vector3f walkdir;
    Camera cam;
    InputManager inputManager;
    static Vector3f xAxisMovement;
    static Vector3f yAxisMovement;
    static Vector3f zAxisMovement;
    
        
    public KeyBehavior(InputManager inputManager, Camera cam){
        this.cam = cam;
        this.inputManager = inputManager;
        walkdir=new Vector3f();
        setupKeys();
        speed = 0.5f;
    }
    
    private void setupKeys() {
        inputManager.addMapping("Left", new KeyTrigger(KeyInput.KEY_A));
        inputManager.addMapping("Right", new KeyTrigger(KeyInput.KEY_D));
        inputManager.addMapping("Forward", new KeyTrigger(KeyInput.KEY_W));
        inputManager.addMapping("Backward", new KeyTrigger(KeyInput.KEY_S));
        inputManager.addMapping("Up", new KeyTrigger(KeyInput.KEY_UP));
        inputManager.addMapping("Down", new KeyTrigger(KeyInput.KEY_DOWN));
        inputManager.addMapping("RotLeft", new KeyTrigger(KeyInput.KEY_LEFT));
        inputManager.addMapping("RotRight", new KeyTrigger(KeyInput.KEY_RIGHT));
        inputManager.addMapping("Space", new KeyTrigger(KeyInput.KEY_SPACE));
        inputManager.addMapping("Reset", new KeyTrigger(KeyInput.KEY_RETURN));
        inputManager.addMapping("Camera", new KeyTrigger(KeyInput.KEY_K));
        inputManager.addMapping("Engine", new KeyTrigger(KeyInput.KEY_E));
        
        inputManager.addListener(this, "Left");
        inputManager.addListener(this, "Right");
        inputManager.addListener(this, "Forward");
        inputManager.addListener(this, "Backward");
        inputManager.addListener(this, "Up");
        inputManager.addListener(this, "Down");
        inputManager.addListener(this, "RotLeft");
        inputManager.addListener(this, "RotRight");
        inputManager.addListener(this, "Space");
        inputManager.addListener(this, "Reset");
        inputManager.addListener(this, "Camera");
        inputManager.addListener(this, "Engine");
    }
    
    public void onAction(String binding, boolean value, float tpf) {
        System.out.println(binding);
         
        /**
        * Helicoptermovement
        */
        if(TerrainFlight3D.player){
                    if(Player.PlayerNode.getName().equals("HELICOPTER")){
            if (binding.equals("Reset")) {
                if (value) {
                    System.out.println("Reset");
                    Player.FlyControl.setPhysicsLocation(Vector3f.ZERO);
                    Player.FlyControl.setPhysicsRotation(new Matrix3f());
                    Player.FlyControl.setLinearVelocity(Vector3f.ZERO);
                    Player.FlyControl.setAngularVelocity(Vector3f.ZERO);
                }
            } else if (binding.equals("Engine") && !value ) {
                        if(!Engine && (AudioEffects.audio_helicopter_stop.getStatus() == AudioSource.Status.Stopped)){
                            System.out.println("Start Engine");
                            Engine = true;
                            AudioEffects.audio_helicopter_start.play();
                        } else if ((AudioEffects.audio_helicopter_fly.getStatus() == AudioSource.Status.Playing)){
                            System.out.println("Stop Engine");
                            AudioEffects.audio_helicopter_start.stop();
                            AudioEffects.audio_helicopter_fly.stop(); 
                            AudioEffects.audio_helicopter_stop.play();
                            Engine = false;
                        }
                } 
           
            if (binding.equals("Left")) {
                if (value) {
                    leftward = true;
                } 
                else {
                    leftward = false;                   
                }
            } else if (binding.equals("Right")) {
                if (value) {
                   rightward = true;
                } else {
                    rightward = false;
                } 
            } else if (binding.equals("Forward")) {
                if (value) {
                    forward = true;
                   
                } else {
                    forward = false;
                   
                } 
            } else if (binding.equals("Backward")) {
                if (value) {
                 backward = true;
              
                } else {
                    backward = false;
                    
                   
                }
            } else if (binding.equals("Up") ) {
                System.out.println(binding);
                if (value) {
                 upward = true;
                } else {
                    upward = false;
                }
            } else if (binding.equals("Down") ) {
                System.out.println(binding);
                 if (value) {
                 downward = true; 
               
                 } else {
                     downward = false;
                    
                 }
            }
           
    }
if (binding.equals("Camera") && !value ){
            if (Player.FPC){ 
                System.out.println("Chase Camera");
                Player.camNode.setEnabled(false);
                Player.chaseCam.setEnabled(true);
                Player.FPC = false;
            }
            else if (!Player.FPC){
                System.out.println("3rd-Person Camera");
                Player.chaseCam.setEnabled(false);
                Player.camNode.setEnabled(true);
                Player.FPC = true;
            }
        }
      }

    }
   
    public void onAnalog(String binding, float value, float tpf) {
        if(TerrainFlight3D.player){
             if(Player.PlayerNode.getName().equals("HELICOPTER")){
                xAxisMovement = Player.FlyControl.getPhysicsRotation().getRotationColumn(0).mult(speed);
                yAxisMovement = Player.FlyControl.getPhysicsRotation().getRotationColumn(1).mult(speed/2);
                zAxisMovement = Player.FlyControl.getPhysicsRotation().getRotationColumn(2).mult(speed);
                                 
                if (binding.equals("RotLeft")) {
                    System.out.println(binding);
                    Player.FlyControl.setPhysicsRotation(Player.FlyControl.getPhysicsRotation().mult(DEG1dot25p));
                } else if (binding.equals("RotRight")) {
                    System.out.println(binding);
                    Player.FlyControl.setPhysicsRotation(Player.FlyControl.getPhysicsRotation().mult(DEG1dot25m));
                } 
                
                if (binding.equals("Left")) {
                    if (leftward) {
                       walkdir = new Vector3f(walkdir.x-xAxisMovement.x, walkdir.y-xAxisMovement.y, walkdir.z-xAxisMovement.z);
                    } else {
                       walkdir = new Vector3f(walkdir.x+xAxisMovement.x, walkdir.y+xAxisMovement.y, walkdir.z+xAxisMovement.z);
                    }
                } else if (binding.equals("Right")) {
                    if (rightward) {
                       walkdir = new Vector3f(walkdir.x+xAxisMovement.x, walkdir.y+xAxisMovement.y, walkdir.z+xAxisMovement.z);
                    } else {
                       walkdir = new Vector3f(walkdir.x-xAxisMovement.x, walkdir.y-xAxisMovement.y, walkdir.z-xAxisMovement.z);
                    }
                }
                
                if (binding.equals("Forward")) {
                    if (forward) {
                       walkdir = new Vector3f(walkdir.x-zAxisMovement.x, walkdir.y-zAxisMovement.y, walkdir.z-zAxisMovement.z);
                    } else {
                       walkdir = new Vector3f(walkdir.x+zAxisMovement.x, walkdir.y+zAxisMovement.y, walkdir.z+zAxisMovement.z);
                    }
                } else if (binding.equals("Backward")) {
                    if (backward) {
                       walkdir = new Vector3f(walkdir.x+zAxisMovement.x, walkdir.y+zAxisMovement.y, walkdir.z+zAxisMovement.z);
                    } else {
                       walkdir = new Vector3f(walkdir.x-zAxisMovement.x, walkdir.y-zAxisMovement.y, walkdir.z-zAxisMovement.z);
                    }
                }

                if (binding.equals("Down") ) {
                    if (downward) {
                        walkdir = new Vector3f(walkdir.x-yAxisMovement.x, walkdir.y-yAxisMovement.y, walkdir.z-yAxisMovement.z);
                    } else {
                        walkdir = new Vector3f(walkdir.x+yAxisMovement.x, walkdir.y+yAxisMovement.y, walkdir.z+yAxisMovement.z);
                    }
                } else if (binding.equals("Up") ) {
                    if (upward) {
                        walkdir = new Vector3f(walkdir.x+yAxisMovement.x, walkdir.y+yAxisMovement.y, walkdir.z+yAxisMovement.z);
                    } else {
                       walkdir = new Vector3f(walkdir.x-yAxisMovement.x, walkdir.y-yAxisMovement.y, walkdir.z-yAxisMovement.z);
                    }
                }
                
//                System.out.println("walkdir:"+walkdir);
//                System.out.println("Velocity:"+ Player.FlyControl.getLinearVelocity());
//                System.out.println("Damping:"+ Player.FlyControl.getLinearDamping());
                Player.FlyControl.setLinearDamping(speed*1.9f);
                Player.FlyControl.setLinearVelocity(walkdir); 
          }
        }
    }       
}

and here is a video. I hope it shows my problem good enough.

You should not be using setPhysicsRotation and setLinearVelocity. Use applyTorque and applyCentralForce instead.

Here is some code I used. I was flying a phycis camera around instead, but same idea.


    private AnalogListener analogListener = new AnalogListener() {
        public void onAnalog(String name, float value, float tpf) {
            
            if (name.equals("MoveLeft"))
                cameraNodePhysicsControl.applyCentralForce(getCamera().getLeft().mult(linearSpeed));
            if (name.equals("MoveRight"))
                cameraNodePhysicsControl.applyCentralForce(getCamera().getLeft().mult(-linearSpeed));
            if (name.equals("MoveForward"))
                cameraNodePhysicsControl.applyCentralForce(getCamera().getDirection().mult(linearSpeed));
            if (name.equals("MoveBackward"))
                cameraNodePhysicsControl.applyCentralForce(getCamera().getDirection().mult(-linearSpeed));
            
            Vector3f xRotation = cameraNodePhysicsControl.getPhysicsRotation().getRotationColumn(0).normalize();
            Vector3f yRotation = cameraNodePhysicsControl.getPhysicsRotation().getRotationColumn(1).normalize();
            Vector3f zRotation = cameraNodePhysicsControl.getPhysicsRotation().getRotationColumn(2).normalize();

            if (name.equals("RotateLeft"))
                cameraNodePhysicsControl.applyTorque(yRotation.mult(angularSpeed));
            if (name.equals("RotateRight"))
                cameraNodePhysicsControl.applyTorque(yRotation.mult(-angularSpeed));
            if (name.equals("RotateUp"))
                cameraNodePhysicsControl.applyTorque(xRotation.mult(angularSpeed));
            if (name.equals("RotateDown"))
                cameraNodePhysicsControl.applyTorque(xRotation.mult(-angularSpeed));
            if (name.equals("SpinLeft"))
                cameraNodePhysicsControl.applyTorque(zRotation.mult(-angularSpeed));
            if (name.equals("SpinRight"))
                cameraNodePhysicsControl.applyTorque(zRotation.mult(angularSpeed));

        }   
    };

Ok, thank you for your idea. I’ll try to write your code to my structure. Can I replace the CameraNodePhysicsControl with my FlyControl(RigidBodyControl)? Have a nice Sunday!

Hey, thanks for this tipp. I changed my steering to applyImpulse() and when key is released I clearForces() and set my vector walkdir to zero. This is a acceptable steering for a helicopter.

Thanks for help

Greets from Germany

Taros