Rotation for Motorbike Handle

Hi,



I'm currently implementing the basic physics for a cross motorbike. It has 9 dynamic parts some joints, 2 translationals (suspension) and 3 rotaional axis (wheels and handle). I have no visualization atm but that will be added (I already have a model and all parts of it for that)



My problem is that the handle is not rotating . It should rotate about the y-axis which should diretly steer the whole front handle with the wheels included.



How can I reach a rotation so that the parts below do rotate likewise? This would mean the link between the joints (handle,wheel) is a bar which rotates about itself (top down bar rotationg about the y-axis). But it seem that the rotational axis is only rotating a physics geometry about it ?



I know that it's impossible to define two different kinds of axis for one joint. Therefore I use a ghostWheelFront Joint which is at the same position as the wheel itself… acceleration and suspension already works, but steering and balancing^^!



By the way I don't understand the concept of .setRelativeToSecondObject(true) as get errors everywhere I set this value to true. (…problematic joint error… it must be relative to the first object).



Thanks for support and ideas about balancing a fully dynamic motorbike.

I don’t get the actual problem. Joints attach two dynamic nodes. So it’s not a single geometry but multiple geometries on one ‘side’ of the joint.



Balancing might be tough. The ODE version used should be compiled with gyroscopic inertia turned on, so probably spinning the wheels already helps…

Ok I try to explain my problem in other words:



The rotational axis is between two dynamic nodes: wheel, handlebar.



Problem: The rotation axis only lets the handlebar rotate and the wheel is not affected (this is unnaturally as the wheels are usually part of the front handle and should steer to the same direction). So there seems to be no dependeny between the wheel and the handlebar.



How can a rotation of one dynamicNode affect the rotation of the other dynamic node?

Ah, so your rotational axis does not change direction when the handlebar is rotating, right? Try attaching that joint the other way round (joint.attach(wheel. handlebar) instead of joint.attach(handlebar, wheel) or vice versa). If that does not help post again, please.



edit: wording

Thanks, I'll try that today. Unfortunately I am at work atm and can't test it now.

Well I testet some combinations an still see no movement of the rotational axis (big green line in the debug mode).



So, as I stuck at my work I give you everything to identify the problem.



Image:





TestPhysics3.java:


import mce.test.motorbike.MotorbikeInputHandler;

import com.jme.input.MouseInput;
import com.jme.math.Vector3f;
import com.jme.scene.shape.Box;
import com.jmex.physics.DynamicPhysicsNode;
import com.jmex.physics.Joint;
import com.jmex.physics.RotationalJointAxis;
import com.jmex.physics.StaticPhysicsNode;
import com.jmex.physics.TranslationalJointAxis;
import com.jmex.physics.material.Material;
import com.jmex.physics.util.SimplePhysicsGame;

public class TestPhysics3 extends SimplePhysicsGame
{
//    Bike data
   private static final float MAX_TURN_ANGLE=0.25f;
   private static final float TURN_SPEED=150;
   private static final float TURN_ACCEL=120;
   public static final float WHEEL_SPEED = 100;
   public static final float WHEEL_ACCEL = 25;

   public static final float CHASSIS_MASS=1.5f;
   public static final Vector3f CHASSIS_LOCATION=new Vector3f(15, 2, 0);
   public static final Vector3f OFFSET_FIX_FRONT=new Vector3f(14, 1.5f, 0);
   public static final Vector3f OFFSET_FIX_REAR=new Vector3f(16, 1.5f, 0); // = Supensionbase rear

   public static final Vector3f OFFSET_GHOSTHANDEL=new Vector3f(13.5f, 1, 0);
   public static final Vector3f OFFSET_SUSPENSIONBASE_FRONT=OFFSET_GHOSTHANDEL;

   public static final Vector3f OFFSET_GHOSTWHEEL_REAR=new Vector3f(18, 0, 0);
   public static final Vector3f OFFSET_WHEEL_REAR=OFFSET_GHOSTWHEEL_REAR;

   public static final Vector3f OFFSET_GHOSTWHEEL_FRONT=new Vector3f(12, 0, 0);
   public static final Vector3f OFFSET_WHEEL_FRONT=OFFSET_GHOSTWHEEL_FRONT;

   // 9 Dynamic parts of the bike
   public DynamicPhysicsNode chassis;
   private DynamicPhysicsNode wheelFront;
   private DynamicPhysicsNode wheelRear;
   private DynamicPhysicsNode ghostWheelFront;
   private DynamicPhysicsNode ghostWheelRear;
   private DynamicPhysicsNode chassisFixRear;
   private DynamicPhysicsNode chassisFixFront; // = handle base
   private DynamicPhysicsNode ghostHandle;
   private DynamicPhysicsNode suspensionBaseFront;

   // 5 joints front
   Joint jointChassis_chassisFixFront;             // Fix joint
   Joint jointChassisFixFront_ghostHandle;          // Rotational 90 degree
   Joint jointGhostHandle_suspensionBaseFront;       // Fix
   Joint jointSuspensionBaseFront_ghostWheelFront;    // Tanslational sup freedom
   Joint jointGhostWheelFront_wheelFront;             // Rotaional 360

   // 3 joints rear
   Joint jointChassis_chassisFixRear;                // Fix joint
   Joint jointChassisFixRear_ghostWheelRear;          // Translational susp freedom
   Joint jointGhostWheelRear_wheelRear;             // Rotational 360

   // Rotational Axis
   RotationalJointAxis rotFrontWheel;
   public RotationalJointAxis rotRearWheel;
   public RotationalJointAxis rotHandle;

   // Translational Axis
   TranslationalJointAxis translationSuspensionFront;
   TranslationalJointAxis translationSuspensionRear;

   @Override
   protected void simpleInitGame()
   {
      showPhysics=true;
      pause=true;
      createFloor();
      createInputHandler();

      /** ****Dynamic Nodes**************** */
      chassis=getPhysicsSpace().createDynamicNode();
      wheelFront=getPhysicsSpace().createDynamicNode();
      wheelRear=getPhysicsSpace().createDynamicNode();
      ghostWheelFront=getPhysicsSpace().createDynamicNode();
      ghostWheelRear=getPhysicsSpace().createDynamicNode();
      chassisFixRear=getPhysicsSpace().createDynamicNode();
      chassisFixFront=getPhysicsSpace().createDynamicNode();
      ghostHandle=getPhysicsSpace().createDynamicNode();
      suspensionBaseFront=getPhysicsSpace().createDynamicNode();

      // Offsets
      chassis.setLocalTranslation(CHASSIS_LOCATION);
      chassisFixFront.setLocalTranslation(OFFSET_FIX_FRONT);
      ghostHandle.setLocalTranslation(OFFSET_GHOSTHANDEL);
      suspensionBaseFront.setLocalTranslation(OFFSET_SUSPENSIONBASE_FRONT);
      ghostWheelFront.setLocalTranslation(OFFSET_GHOSTWHEEL_FRONT);
      wheelFront.setLocalTranslation(OFFSET_WHEEL_FRONT);
      chassisFixRear.setLocalTranslation(OFFSET_FIX_REAR);
      ghostWheelRear.setLocalTranslation(OFFSET_GHOSTWHEEL_REAR);
      wheelRear.setLocalTranslation(OFFSET_WHEEL_REAR);

      // Visualizations
      chassis.createBox("chassis");
      chassis.setMaterial(Material.IRON);
      chassis.setMass(CHASSIS_MASS);
      chassis.generatePhysicsGeometry();
      chassis.computeMass();

      wheelFront.createSphere("wheelFront");
      wheelFront.setMaterial(Material.RUBBER);
      wheelFront.generatePhysicsGeometry();
      wheelFront.computeMass();

      wheelRear.createSphere("wheelRear");
      wheelRear.setMaterial(Material.RUBBER);
      wheelRear.generatePhysicsGeometry();
      wheelRear.computeMass();

//      chassisFixFront.createBox("fixFront");
//      chassisFixFront.setMaterial(Material.IRON);
//      chassisFixFront.generatePhysicsGeometry();
//      chassisFixFront.computeMass();

      rootNode.attachChild(chassis);
      rootNode.attachChild(wheelFront);
      rootNode.attachChild(wheelRear);
//      rootNode.attachChild(chassisFixFront);

      // Joints init
      jointChassis_chassisFixFront=getPhysicsSpace().createJoint();
      jointChassis_chassisFixRear=getPhysicsSpace().createJoint();
      jointChassisFixFront_ghostHandle=getPhysicsSpace().createJoint();
      jointChassisFixRear_ghostWheelRear=getPhysicsSpace().createJoint();
      jointGhostHandle_suspensionBaseFront=getPhysicsSpace().createJoint();
      jointGhostWheelFront_wheelFront=getPhysicsSpace().createJoint();
      jointGhostWheelRear_wheelRear=getPhysicsSpace().createJoint();
      jointSuspensionBaseFront_ghostWheelFront=getPhysicsSpace().createJoint();

      // Joints attaching dynamic parts
      jointChassis_chassisFixFront.attach(chassisFixFront, chassis);
      jointChassis_chassisFixRear.attach(chassisFixRear, chassis);
      jointChassisFixFront_ghostHandle.attach(chassisFixFront,ghostHandle);
      jointChassisFixRear_ghostWheelRear.attach(ghostWheelRear, chassisFixRear);
      jointGhostHandle_suspensionBaseFront.attach(suspensionBaseFront, ghostHandle);
      jointGhostWheelFront_wheelFront.attach(wheelFront, ghostWheelFront);
      jointGhostWheelRear_wheelRear.attach(wheelRear, ghostWheelRear);
      jointSuspensionBaseFront_ghostWheelFront.attach(ghostWheelFront, suspensionBaseFront);

      // Translational Axis init
      translationSuspensionFront=jointSuspensionBaseFront_ghostWheelFront.createTranslationalAxis();
      translationSuspensionRear=jointChassisFixRear_ghostWheelRear.createTranslationalAxis();

      // Rotational Axis init
      rotFrontWheel=jointGhostWheelFront_wheelFront.createRotationalAxis();
      rotRearWheel=jointGhostWheelRear_wheelRear.createRotationalAxis();
      rotHandle=jointChassisFixFront_ghostHandle.createRotationalAxis();

      // Setting freedoms/degrees
      translationSuspensionFront.setPositionMinimum(1);
      translationSuspensionFront.setPositionMaximum(2);
      translationSuspensionFront.setDesiredVelocity(-8);
      translationSuspensionFront.setAvailableAcceleration(3);
      translationSuspensionFront.setDirection(new Vector3f(0, -1, 0));
      translationSuspensionFront.setRelativeToSecondObject(false);

      translationSuspensionRear.setPositionMinimum(1);
      translationSuspensionRear.setPositionMaximum(2);
      translationSuspensionRear.setDesiredVelocity(-8);
      translationSuspensionRear.setAvailableAcceleration(3);
      translationSuspensionRear.setDirection(new Vector3f(0, -1, 0));

      rotFrontWheel.setAvailableAcceleration(10);
      rotFrontWheel.setDirection(new Vector3f(0, 0, 1));
      rotRearWheel.setAvailableAcceleration(WHEEL_ACCEL);
      rotRearWheel.setDirection(new Vector3f(0, 0, 1));
      rotFrontWheel.setRelativeToSecondObject(false);
      rotHandle.setDirection(new Vector3f(0.5f, 0.4f, 0));
      rotHandle.setAvailableAcceleration(TURN_ACCEL);      

      MouseInput.get().setCursorVisible(true);
   }
   
   public void createInputHandler()
   {
      MotorbikeInputHandler minput = new MotorbikeInputHandler(this);
      input.addToAttachedHandlers(minput);
   }

   public void steer(final float direction)
   {
      rotHandle.setDesiredVelocity(direction * TURN_SPEED);
      rotHandle.setPositionMaximum(MAX_TURN_ANGLE);
      rotHandle.setPositionMinimum(-MAX_TURN_ANGLE);
   }

   public void unsteer()
   {
      rotHandle.setDesiredVelocity(0);
      rotHandle.setPositionMaximum(0);
      rotHandle.setPositionMinimum(0);
   }
   
   public void accelerate( final int direction ) {
      rotRearWheel.setDesiredVelocity( direction * WHEEL_SPEED );
    }

    public void releaseAccel() {
       rotRearWheel.setDesiredVelocity( 0 );
    }
   
    public void clearAllDynamics()
    {
       chassis.clearDynamics();
      wheelFront.clearDynamics();
      wheelRear.clearDynamics();
      wheelFront.clearDynamics();
      ghostWheelRear.clearDynamics();
      chassisFixRear.clearDynamics();
      chassisFixFront.clearDynamics();
      ghostHandle.clearDynamics();
      suspensionBaseFront.clearDynamics();
    }

   private void createFloor()
   {
      StaticPhysicsNode staticNode=getPhysicsSpace().createStaticNode();
      rootNode.attachChild(staticNode);
      final Box visualFloorBox=new Box("floor", new Vector3f(), 10, 0.25f, 10);
      staticNode.attachChild(visualFloorBox);
      visualFloorBox.getLocalRotation().fromAngleNormalAxis(0.3f, new Vector3f(0, 0, -1));

      final Box visualFloorBox2=new Box("floor", new Vector3f(), 10, 0.25f, 10);
      staticNode.attachChild(visualFloorBox2);
      visualFloorBox2.getLocalTranslation().set(19.6f, -2.95f, 0);
      staticNode.generatePhysicsGeometry();
   }

   public static void main(String[] args)
   {
      TestPhysics3 t= new TestPhysics3();
      t.start();
   }

}



MotorbikeInputHandler.java:


public class MotorbikeInputHandler extends InputHandler
{
   // KeyBinding Handel
   KeyBindingManager keyboard;

   // Motorbike

   private TestPhysics3 parentGame;

   private AccelAction accelActionUp;
   private AccelAction accelActionDown;
   private SteerAction steerActionLeft;
   private SteerAction steerActionRight;
   private ResetAction resetAction;

   public MotorbikeInputHandler(TestPhysics3 parentGame)
   {
      this.parentGame=parentGame;
      setKeyBindings();
      setActions();
   }

   private void setKeyBindings()
   {
      keyboard=KeyBindingManager.getKeyBindingManager();

      keyboard.set("bike_forward", KeyInput.KEY_U);
      keyboard.set("bike_backward", KeyInput.KEY_J);
      keyboard.set("bike_left", KeyInput.KEY_H);
      keyboard.set("bike_right", KeyInput.KEY_K);
      keyboard.set("bike_reset", KeyInput.KEY_R);
   }

   private void setActions()
   {
      // Init Actions
      accelActionUp=new AccelAction(1);
      accelActionDown=new AccelAction(-1);
      steerActionLeft=new SteerAction(-1);
      steerActionRight=new SteerAction(1);
      resetAction=new ResetAction();

      // Attaching the custom input actions (and its respective events) to the Input handler.
      this.addAction(accelActionUp, "bike_forward", true);
      this.addAction(accelActionDown, "bike_backward", true);
      this.addAction(steerActionLeft, "bike_left", true);
      this.addAction(steerActionRight, "bike_right", true);
      this.addAction(resetAction, "bike_reset", false);
   }

   public class SteerAction extends InputAction
   {
      int direction;

      public SteerAction(int direction)
      {         
         this.direction=direction;
      }

      public void performAction(InputActionEvent e)
      {
         parentGame.steer(direction);
      }
   }

   /**
    * Simple input action for accelerating and braking the car.
    */
   public class AccelAction extends InputAction
   {
      int direction;

      public AccelAction(int direction)
      {         
         this.direction=direction;
      }

      public void performAction(InputActionEvent e)
      {
         parentGame.accelerate(direction);
      }
   }

   public class ResetAction extends InputAction
   {
      
      public ResetAction()
      {      
      }
      public void performAction(InputActionEvent evt)
      {
         parentGame.clearAllDynamics();
         parentGame.chassis.setLocalTranslation(parentGame.CHASSIS_LOCATION);
         parentGame.chassis.getLocalRotation().loadIdentity();
      }
   }

   private void checkValidCommand()
   {      
      
      // if no acceleration key was pressed slow down the car
      if ((!keyboard.isValidCommand("bike_forward"))&&(!keyboard.isValidCommand("bike_backward")))
      {
         parentGame.releaseAccel();
      }
      // if no steer key was pressed slow down the car
      if ((!keyboard.isValidCommand("bike_turnRight"))&&(!keyboard.isValidCommand("bike_turnLeft")))
      {
         parentGame.unsteer();
      }
   }

   @Override
   public void update(float time)
   {
      super.update(time);
      checkValidCommand();
   }
}



I guess I'm doing the wrong joins but I hope you are able to fix that.

How can a rotation of one dynamicNode affect the rotation of another dynamic node?

Hmm, I just tested it and works over here (in a simpler example; beware handling is crappy). See this code:

/*
 * Copyright (c) 2005-2007 jME Physics 2
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *  * Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 *  * Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 *  * Neither the name of 'jME Physics 2' nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package com.jmetest.physics.vehicle;

import java.util.logging.Level;
import java.util.logging.Logger;

import com.jme.input.InputHandler;
import com.jme.input.KeyInput;
import com.jme.input.ChaseCamera;
import com.jme.input.action.InputAction;
import com.jme.input.action.InputActionEvent;
import com.jme.math.Vector3f;
import com.jme.scene.Text;
import com.jme.scene.shape.Box;
import com.jmex.physics.DynamicPhysicsNode;
import com.jmex.physics.Joint;
import com.jmex.physics.JointAxis;
import com.jmex.physics.StaticPhysicsNode;
import com.jmex.physics.geometry.PhysicsBox;
import com.jmex.physics.material.Material;
import com.jmex.physics.util.SimplePhysicsGame;

/**
 * Very simple bicycle. Steering behaviour is quite crappy.
 */
public class TestBicycle extends SimplePhysicsGame {
    private ChaseCamera chaseCamera;

    protected void simpleInitGame() {
        createFloor();

        // create chassis
        final DynamicPhysicsNode chassis = getPhysicsSpace().createDynamicNode();
        chassis.createBox( "chassis" );
        chassis.setLocalScale( new Vector3f( 2, 0.8f, 0.1f ) );
        chassis.getLocalTranslation().set( 0, 1, 0 );
        rootNode.attachChild( chassis );

        // create rear tire
        DynamicPhysicsNode tire = getPhysicsSpace().createDynamicNode();
        tire.createCylinder( "tire geom" );
        tire.setMaterial( Material.RUBBER );
        tire.getLocalScale().set( 0.5f, 0.1f, 0.1f );
        tire.getLocalTranslation().set( -1, 0, 0 );
        tire.computeMass();
        tire.setMass( 100 );
        rootNode.attachChild( tire );

        // connect chassis and rear tire, including motor
        Joint joint = getPhysicsSpace().createJoint();
        joint.attach( tire, chassis );
        final JointAxis rotationAxis = joint.createRotationalAxis();
        rotationAxis.setDirection( new Vector3f( 0, 0, 1 ) );
        rotationAxis.setAvailableAcceleration( 2000 );

        input.addAction( new SteerAction( rotationAxis, -500 ), InputHandler.DEVICE_KEYBOARD, KeyInput.KEY_NUMPAD8, InputHandler.AXIS_NONE, false );
        input.addAction( new SteerAction( rotationAxis, 500 ), InputHandler.DEVICE_KEYBOARD, KeyInput.KEY_NUMPAD2, InputHandler.AXIS_NONE, false );

        // create handle
        DynamicPhysicsNode handle = getPhysicsSpace().createDynamicNode();
        PhysicsBox handlePart1 = handle.createBox( "handleG1" );
        handlePart1.getLocalScale().set( 0.1f, 1f, 0.1f  );
        handle.getLocalTranslation().set( 1.1f, 1, 0 );
        PhysicsBox handlePart2 = handle.createBox( "handleG2" );
        handlePart2.getLocalScale().set( 0.1f, 0.1f, 1  );
        handlePart2.getLocalTranslation().set( 0, 1, 0  );

        // join handle and chassis, including steering
        Joint handleJoint = getPhysicsSpace().createJoint();
        handleJoint.attach( handle, chassis );
        final JointAxis handleAxis = handleJoint.createRotationalAxis();
        handleAxis.setDirection( new Vector3f( 0, 1, 0 ) );
        handleAxis.setAvailableAcceleration( 500 );
       
        input.addAction( new SteerAction( handleAxis, 1 ), InputHandler.DEVICE_KEYBOARD, KeyInput.KEY_NUMPAD4, InputHandler.AXIS_NONE, false );
        input.addAction( new SteerAction( handleAxis, -1 ), InputHandler.DEVICE_KEYBOARD, KeyInput.KEY_NUMPAD6, InputHandler.AXIS_NONE, false );

        // create front tire
        DynamicPhysicsNode tire2 = getPhysicsSpace().createDynamicNode();
        tire2.createCylinder( "tire2 geom" );
        tire2.setMaterial( Material.RUBBER );
        tire2.getLocalScale().set( 0.5f, 0.1f, 0.1f );
        tire2.getLocalTranslation().set( 1, 0, 0 );
        tire2.computeMass();
        tire2.setMass( 200 );
        rootNode.attachChild( tire2 );

        // join front tire and handle
        Joint joint2 = getPhysicsSpace().createJoint();
        joint2.attach( tire2, handle );
        final JointAxis rotationAxis2 = joint2.createRotationalAxis();
        rotationAxis2.setDirection( new Vector3f( 0, 0, 1 ) );

        // some visual stuff
        Text label = Text.createDefaultTextLabel( "instructions", "Use Numpad to steer the bicycle." );
        label.setLocalTranslation( 0, 20, 0 );
        statNode.attachChild( label );

        chaseCamera = new ChaseCamera(cam, chassis);
        showPhysics = true;
    }

    private void createFloor() {
        final StaticPhysicsNode staticNode = getPhysicsSpace().createStaticNode();
        staticNode.attachChild( new Box("", new Vector3f(0, -2, 0), 250, 0.1f, 250 ) );
        staticNode.generatePhysicsGeometry();
        staticNode.setMaterial( Material.CONCRETE );
        rootNode.attachChild( staticNode );
    }

    protected void simpleRender() {
        chaseCamera.update( tpf );
    }

    public static void main( String[] args ) {
        Logger.getLogger( "" ).setLevel( Level.WARNING ); // to see the important stuff
        new TestBicycle().start();
    }

    private static class SteerAction extends InputAction {
        private final JointAxis axis1;
        private float velocity;

        public SteerAction( JointAxis axis1, float velocity ) {
            this.axis1 = axis1;
            this.velocity = velocity;
        }

        public void performAction( InputActionEvent evt ) {
            if ( evt.getTriggerPressed() ) {
                axis1.setDesiredVelocity( velocity );
            }
            else {
                axis1.setDesiredVelocity( 0 );
            }
        }
    }
}


You'll need to add suspension and a rake angle != 0, of course.

Thank you for this nice example.

It has everything I need.

The example worked but my work doesn't. Anyhow I change to a Quadbike with 4 wheels to avoid complicated balancing techniques for the motorbike^^.



I have a new problem, but a very similar one: the Rotational axis for steering (y) does not move.



I 've done many attemptions, even a new dynamic node just to do the  steer rotation thing, but nothing works when I write my own code although they are comapreable to working examples except for the suspensoin (translational axis before the 2 rotational axes of the front wheels) which only I have.



I try to give a sketch of my current problem as code is time consuming to build the joints in the head :stuck_out_tongue:



In the next post I will provide images 2 therefore.

image1:





image2:





I only know two ways to implement a front wheel which should have 2 rotational freedoms:

  1. create from the wheeljoint (joint3) 2 rotational axis: first a steer axis, than a accalerate; after that set the accalerate axis relative to second object (which is wheel)
  2. create 2 joints, each defining one of the rotational axis (one for y, one for z)



    I tried out both, but they don’t work,damned :evil:



    Any idea where the failure could be or any other solutions for that? TestVehicle exmple works and I did exactly the same, oder of joints attachment, setting relative to second object… it won’t steer :x



    If image2 is not enough i could also post the code. However I need help out there. :’(

TestAdvancedVehicle does what you're trying to achieve, I believe (at least it has suspension). Maybe you can have a look at that?

TestAdvancedVehicle does what you're trying to achieve, I believe (at least it has suspension). Maybe you can have a look at that?


Yes, that's what I looked at intensively and I finished to change the visualizations to a quad bike, but I could not get it working properly, although I reached a good performance by reducing the amount of bouncing boxes and used simple collision geometry (a box).

I gave up that implementation because it's a too complicated solution and there are much too much dependencies between the joints and relative positions. The most hardest part of TestAdvancedVehicle is that everything is reseted in position during initialization which kills all dependencies in my head. Other parts are very confusing like the wheelJoint which gets attached TWO dynamicNodes AND has set an anchor to some strange worldPoint after a also dependend offset...postition calculation.

I thought I understood the basic concpets of joints and could define axes on them (under consideration of the restrictations), but only one of them (rotational axis with direction y) would absolutely not work. WHY is it working in a example A and not in example B iff the only difference should be that B has one dynamic Node and some WORKINK joint+ translational axis more above the magically working example A??  :? :x :?

May somone who knows the possibilities of jme physics tell me what should work of that which can be seen in image1?



I already said that only the rotation about the y-axis does not even think about what it is supposed to do.



Thanks i.A.

I don't see why it should not work. And it works in the examples I have seen/written. The only thing I would not do is using a fixed joint.

Thank you so much for this answer! (really) . You gave up beating about the bush :D.


The only thing I would not do is using a fixed joint.



Why? I know you have  a reason and that's what I'm asking you for. Thank you, you made me happy for a while.
mathias4u said:

You gave up beating about the bush

??? I did not intend to in the first place. Hmm, whatever.

mathias4u said:

The only thing I would not do is using a fixed joint.


Why? I know you have  a reason and that's what I'm asking you for. Thank you, you made me happy for a while.

Because you get quite the same with using a single DynamicPhysicsNode (probably with multiple collision geometries) instead of multiple DPNs joined with fixed joints, but with better performance and stability.

I have extended the TestBicycle example to a even more simple example. As you already know I’am still learning basics.



Here it is:





As you can see in the image the joints have an unwanted elastic behaviour. What can I do to prevent them?

Further I really like to know where this joint behaviour emerges from.



Is it related to the physics accuracy or the spring/damper of the joint (by the way what are their default values?).



One thing to my long lasting problem of steering:

Currently I must suppose that the steering in my ohter examples do work. I suppose it becaouse this example here is implemented the same way but also has a very slow steering (but visibly enough to say: yes, there is some moving). They are so slow and weak that they actually don’t steer.



Direct Question: What sould I use to achieve an accaptable steering?


  • Torque

  • y-rotational axis together with z-rotational axis (z relativeToSecondObject(true)) or

  • y-rotational axis on first joint and z-rotational axis on second joint or

  • forces

  • better is the enemy of best way



At least it should be cabable of doing a steering simulation for a motorbike (Motorcross).
mathias4u said:

As you can see in the image the joints have an unwanted elastic behaviour. What can I do to prevent them?
Further I really like to know where this joint behaviour emerges from.

It probably accuracy, yes, you can try to increase it with the physics space parameter. You can prevent it with different joint configuration and anchor points as well.

mathias4u said:

Direct Question: What sould I use to achieve an accaptable steering?

Powered rotational joint axis. Just change desiredVelocity and availableAcceleration to fit your needs.

Put the the whole bike into a collision group and configure it without collision checks with the group itself.



Another note: don't use trimesh accuracy for the wheels! With cylinders it's more stable and much faster.