Hinge with damping and friction

Hi folks,



does anybody of you have a suggestion how to create an actuatued hinge joint that has damping and friction? I currently try to make an implementation using the odeJava's JointAMotor class (which I know one can use to implement these things) but this bypasses the jme classes and seems not to work at all in jme.



Any ideas would be great…



Thanks,

Marcus

Just a comment on ODE's JointAMotor:



I'm using JointAMotor:s to control ragdolls. (I bypass jME-Physics for this.) Below is an excerpt from a ragdoll-creation-class that shows how I create those JointAMotor:s.



(This only concerns JointAMotor, not friction and dampening. I'm sorry if it's a bit much code, but I don't know what to remove; anyway, I hope it gets you on the right track if JointAMotor:s are indeed what is appropriate in your case.)



      //...

      World odeWorld = ((OdePhysicsSpace) game.getPhysicsSpace()).getODEJavaWorld();

      // ===== Create motors

      // (The limbs have already been anchored together via hinge joints or ball joints.
      // Those motors for which 3 axis are defined control ball joints; those with 1 axis
      // control hinge joints.)

      torsoMotor = _addMotor(odeWorld, torsoNode, null, 3);
      rightLegMotor = _addMotor(odeWorld, rightLegNode, torsoNode, 3);
      leftLegMotor = _addMotor(odeWorld, leftLegNode, torsoNode, 3);
      rightTibiaMotor = _addMotor(odeWorld, rightTibiaNode, rightLegNode, 1);
      leftTibiaMotor = _addMotor(odeWorld, leftTibiaNode, leftLegNode, 1);
      rightArmMotor = _addMotor(odeWorld, rightArmNode, torsoNode, 3);
      leftArmMotor = _addMotor(odeWorld, leftArmNode, torsoNode, 3);
      rightForearmMotor = _addMotor(odeWorld, rightForearmNode, rightArmNode, 1);
      leftForearmMotor = _addMotor(odeWorld, leftForearmNode, leftArmNode, 1);
      rightWristMotor = _addMotor(odeWorld, null, rightArmNode, 2);
      leftWristMotor = _addMotor(odeWorld, null, leftArmNode, 2);
   }


   /**
    * Axis 0 is always the one that moves the node towards where it's supposed to be
    * Axis 1 is aligned in such a way that rotation around it is never desired.
    * So, the desired angular velocity is set to 0 for this axis.
    * Axis 2 controls twist around node's own axis.
    */
   private JointAMotor _addMotor(World odeWorld, DynamicPhysicsNode nodeA,
         DynamicPhysicsNode nodeB, int numAxes) {

      JointAMotor motor = new JointAMotor(odeWorld);
      motor.attach(nodeA == null ? null : ((DynamicPhysicsNodeImpl) nodeA).getBody(),
            nodeB == null ? null : ((DynamicPhysicsNodeImpl) nodeB).getBody());
      motor.setMode(Ode.dAMotorUser);
      motor.setNumAxes(numAxes);

      // (Below, "parent limb" is the torso, for arms and legs,
      // and legs/arms for shin_legs/forearms.)

      // Axis 0 anchored to nodeA, roteates along +X axis (= to the right, in my game) of parent limb.
      // (However, for ball joints, this axis is adjusted each time step; initial value does not really matter in my particular game.)
      motor.setAxis(0, 2, 1, 0, 0);
      motor.setParam(Ode.dParamVel, 0);
      motor.setParam(Ode.dParamFMax, 0); /* 100000); */

      // Axis 1 anchored to nodeA, roteates along +Y axis (= forwards, in my game) of parent limb.
      // (However, for ball joints, this axis is adjusted each time step; initial value does not really matter in my particular game.)
      if (numAxes > 1) {
         motor.setAxis(1, 2, 0, 1, 0);
         motor.setParam(Ode.dParamVel2, 0);
         motor.setParam(Ode.dParamFMax2, 0);
      }

      // Axis 2 anchored to nodeB, roteates along +Z axis  (= up, in my game) of child limb.
      // (This axis is kept as is throughout the game, since it's relative to the child limb and is supposed to be that all the time.)
      if (numAxes > 2) {
         motor.setAxis(2, 1, 0, 0, 1);
         motor.setParam(Ode.dParamVel3, 0);
         motor.setParam(Ode.dParamFMax3, 0);
      }

      return motor;
   }



Below is some more code that shows how I update the motor's axes to rotate the ragdoll's limbs to match the ragdoll's intended posture.



      // (__goodAxis and __evilAxis are updated each time step, as appropriate, for each ragdoll limb.
      // I suppose you need not do this more than once though.)

      // Align the node's motor's axis 0 so the motor rotates the node towards
      // its desired direction.
      nodeState.motor.setAxis(0, 1, __goodAxis.x, __goodAxis.y, __goodAxis.z);

      // Align the motor's axis 1 so the motor reduces undesired rotation.
      __actualDown.cross(__goodAxis, __evilAxis);
      nodeState.motor.setAxis(1, 1, -__evilAxis.x, -__evilAxis.y, -__evilAxis.z);

      // Update the angular velocity and max torque the motor applies around the two axes.
      nodeState.motor.setParam(Ode.dParamVel, nodeState.maxAngVel); // rotate towards desired orientation
      nodeState.motor.setParam(Ode.dParamFMax, nodeState.torque);
      nodeState.motor.setParam(Ode.dParamVel2, 0); // elliminate undesired angular velocity, reduce it to 0
      nodeState.motor.setParam(Ode.dParamFMax2, 1000);




Hope this helps,
Magnus

I don't know it from the top of my head… what's missing in the jME Physics joints? Friction? Should be easy to add, no?

sancho-fx1,



You could probably use the Hinge joint's built in engine and add friction via

JointAxis.setDesiredVelocity(0), and

JointAxis.setAvailableAcceleration( your-cohice-of-max-friction-force ).



If you, as you said, want to apply some additional_torque to this hinge joint (in addition to friction torque), I suppose you should

  1. if the additional_torque applied is greater than the friction force, subtract the friction force from the additional_torque, and set the desired angular speed to whatever that additional_torque tries to achieve, or
  2. if the additional_torque applied is less than the friction force, set the force to the friction force minus the additional_torque, and the desired angular speed to 0 (since the additional_torque won't be able to rotate the axis, because of the friction force).



    So, friction, that's relatively straight forward. However, when it comes to dampening, you might need to specify dContactSoftCFM for the hinge joint, but as far as I can see jME-Physics doesn't expose these hinge joint axis parameters. Perhaps worse, according to the ODEJava docs (see function in code snippet below), dampening isn't supposed to be used together with powered joints.



    Anyway, to add dampening, I believe you could cast your joint to com.jmex.physics.impl.ode.joints.OdeJoint and access its private Joint ode; member (thus, since it's private, you have to modify the jME-Physics source code), and cast that ode member to org.odejava.JointHinge, and use the below function.



    Or, probably better, bypass jME-Physics and create a org.odejava.JointHinge directly, and attach it to the appropriate ODE bodies, and use the below function.



    (Hmm, I really hope I didn't miss some piece of code that exposes those ODE CMF and ERP parameters; if so, I'd really be rambling about nothing right now. But it seems reasonable that those parameters aren't exposed, they might be ODE specific. )



     // (in org.odejava.JointHinge.)

    /**
     * Set the amount of stop constant force to mix into the system when the
     * bodies reach a stop. This value has no effect when the bodies are not at
     * the stops. Together with the ERP value, this can be used to get spongy
     * or soft stops. Note that this is inteded for unpowered joints, it does
     * not work as expected on powered joints.
     *
     * @param force The amount of force to use
     */
    public void setStopCFM( float force ) {
        Ode.dJointSetSliderParam( jointId, OdeConstants.dParamStopCFM, force );
    }



Possibly, you need to tweak setStopERP and setStopBounce as well.

LeoMaheo said:

Or, probably better, bypass jME-Physics and create a org.odejava.JointHinge directly, and attach it to the appropriate ODE bodies, and use the below function.

cmon, this is an open source project - don't bypass it but improve it to fit your needs!! So everyone can benefit from your additions.

Well, I agree of course. I actually first wrote that he could write a jME patch and submit it, but then I removed that piece of text because I thought perhaps that'd be a rather lot more work than he had intended. Well, the next time, if any, I'll suggest contributing improvements back to jME :slight_smile: