protected void update_ik(float delta) {
    boolean changed = false;
    motion_future.set(motion_now);

    // speeds
    final float vtranslate = 10.0f * delta;
    final float vrotate = 100.0f * delta;

    // lateral moves
    if (rDown) {
      motion_future.finger_tip.x -= vtranslate;
    }
    if (fDown) {
      motion_future.finger_tip.x += vtranslate;
    }
    if (tDown) {
      motion_future.finger_tip.y += vtranslate;
    }
    if (gDown) {
      motion_future.finger_tip.y -= vtranslate;
    }
    if (yDown) {
      motion_future.finger_tip.z += vtranslate;
    }
    if (hDown) {
      motion_future.finger_tip.z -= vtranslate;
    }
    if (!motion_now.finger_tip.epsilonEquals(motion_future.finger_tip, vtranslate / 2.0f)) {
      changed = true;
    }

    // rotation
    float ru = 0, rv = 0, rw = 0;
    if (uDown) rw = 0.1f;
    if (jDown) rw = -0.1f;
    if (iDown) rv = 0.1f;
    if (kDown) rv = -0.1f;
    if (oDown) ru = 0.1f;
    if (lDown) ru = -0.1f;

    if (rw != 0 || rv != 0 || ru != 0) {
      motion_future.iku += ru * vrotate;
      motion_future.ikv += rv * vrotate;
      motion_future.ikw += rw * vrotate;

      changed = true;
    }

    if (changed == true) {
      moveIfAble();
    }
  }