Using Vive Controllers to Set Velocities

Hello,

I’m working on a Unity SteamVR project for Vive and I’m having an issue with velocity. My project is a racquetball game of sorts and I’m trying to create a handler for when the ball hits the racket.

The setup is as follows.

  • The ball is a prefab that instantiates 10 seconds after runtime begins.
  • The ball and the racket both contain Colliders and RigidBody components that are set to Continuous Dynamic.
  • The racket inherits it’s position and rotation from the SteamVR tracked motion controller.
  • The racket contains a script component with an OnTriggerEnter method that sets a bool named “rightRacketCollision” to true when it collides with the ball.
  • The SteamVR tracked motion controller object contains a script that checks if “rightRacketCollision” is true, and if so, it needs to set the velocity of the ball to the velocity of the tracked motion controllers. It doesn’t :frowning:
  • The script on the SteamVR tracked motion controller also holds a public reference to the ball prefab. I’ve assigned the ball prefab to it’s variable in the editor via drag and drop.

That’s pretty much it, but the Ball velocity does not change when it collides with the racket. As you’ll see in my script (below) I’ve tried using Debug.Log at several junctures and everything checks out (see the screen capture).

Here is my script.

using UnityEngine;
using System.Collections;
using System;

[RequireComponent(typeof(SteamVR_TrackedObject))]
public class SetRightVelocityBall : MonoBehaviour
{

    private BoolKeeper _refBoolKeeper;
    public GameObject _refBall;
    SteamVR_TrackedObject trackedObj;
    SteamVR_Controller.Device device;

    void Awake ()
    {
        trackedObj = GetComponent<SteamVR_TrackedObject>();
    }

    void Start ()
    {
        _refBoolKeeper = GameObject.Find("BoolKeeper").GetComponent<BoolKeeper>();
    }

    void FixedUpdate ()
    {
        device = SteamVR_Controller.Input((int)trackedObj.index);

        if (_refBall)
        {
            Debug.Log("_refBall is not null");
        }

        if (_refBoolKeeper.rightRacketCollision == true)
        {
            bounceBall(_refBall.GetComponent<Rigidbody>());
        }
    }

    void bounceBall (Rigidbody rigidbody)
    {
        rigidbody.velocity = device.velocity;
        rigidbody.angularVelocity = device.angularVelocity;
        Debug.Log ("GOT IT!");
    }
}

Does anyone have any idea as to why the ball velocity isn’t changing? Many thanks in advance!

Well I think I found a solution. It will require me to re-work my setup but at least my script is functioning now.

The working setup is as follows:

  • The ball has a Rigidbody set to continuous dynamic and a collider component
  • The SteamVR Controller object contains a collider component set to isTrigger (no Rigidbody)
  • The SteamVR Controller object contains my new script which transfers velocity to the ball if the grip is being pressed.

Here is the new script:

using UnityEngine;
using System.Collections;
using System;

[RequireComponent(typeof(SteamVR_TrackedObject))]
public class InteractionManager : MonoBehaviour

{

    SteamVR_TrackedObject trackedObj;
    SteamVR_Controller.Device device;

    void Awake ()
    {
        trackedObj = GetComponent<SteamVR_TrackedObject>();
    }

    void FixedUpdate()
    {
        device = SteamVR_Controller.Input((int)trackedObj.index);
    }

    void OnTriggerStay (Collider col)
    {
        if (device.GetTouch(SteamVR_Controller.ButtonMask.Trigger))
        {
            col.attachedRigidbody.isKinematic = true;
            col.gameObject.transform.SetParent(this.gameObject.transform);
        }

        if (device.GetTouchUp(SteamVR_Controller.ButtonMask.Trigger))
        {
            col.gameObject.transform.SetParent(null);
            col.attachedRigidbody.isKinematic = false;

            tossObject(col.attachedRigidbody);
        }

        if (device.GetPress (SteamVR_Controller.ButtonMask.Grip))
        {
            hitObject (col.attachedRigidbody);
        }
    }

    void tossObject(Rigidbody rigidbody)
    {
        rigidbody.velocity = device.velocity;
        rigidbody.angularVelocity = device.angularVelocity;
    }


    void hitObject (Rigidbody rigidbody)
    {
        rigidbody.velocity = device.velocity * 5;
        rigidbody.angularVelocity = device.angularVelocity * 5;
    }
}
1 Like

Hello JK_Designer, Do you know the Units of velocity and angularVelocity that you are getting from controllers.I haven’t found any documentation on them for more details.

The documentation is a big sparse. But looking at the data from the tracking system the dimension of the position is in [m], the velocity is in [m/s] and the acceleration is [radians / s]. The header file documentation has a question mark after the vAngularVelocity variable:

/** describes a single pose for a tracked object */
struct TrackedDevicePose_t
{
HmdMatrix34_t mDeviceToAbsoluteTracking;
HmdVector3_t vVelocity; // velocity in tracker space in m/s
HmdVector3_t vAngularVelocity; // angular velocity in radians/s (?)
ETrackingResult eTrackingResult;
bool bPoseIsValid;

// This indicates that there is a device connected for this spot in the pose array.
// It could go from true to false if the user unplugs the device.
bool bDeviceIsConnected;
};

This is the base code I am using to verify this:
https://github.com/Omnifinity/OpenVR-Tracking-Example
(with some additional modifications to print the pos/rot/angular velocity in only one axis).

Rotating the headset for a second around one axis gives a reading of 1 radian, which is a ~57.29 degrees rotation.
Cheers