Gyroscope handset (e.g. mobile phone): Method to control player using Gyroscope

| | August 5, 2015

I am using gyroscope data (pitch, rool) to move the player space ship. It works perfectly until you play in a standard position (e.g. sitting down). Once you start using it lying (e.g. in the bed) the control does not work anymore as the pitch, roll values I used become too big.

Here is the code I use written in Objective-C. Any idea on how to improve/fix this?

-(void) gyroUpdate:(ccTime) delta
{
    CMAttitude * attitude;
    CMDeviceMotion * motion = [GameController sharedGameController].motionManager.deviceMotion;
    attitude = motion.attitude;

    float pitch =  attitude.pitch;
    float roll =  attitude.roll;

    ShooterScene * shooterScene = (ShooterScene *) [self parent];
    ShipEntity *playerSprite = [shooterScene playerShip];

    const float roolSpeed = 1000.0f;
    const float pitchSpeed = 1000.0f;

    //Midpoint of pitch is 0.5f, here the Player ship is NOT supposed to move.
    //Moving "forward" is equal to values towards 0.0f-
    //Moving "backwards" is equal to values towards 1.0f+


    float pitchProgression = 0.5f - pitch;

     CGPoint newPosition = CGPointMake(playerSprite.position.x + roll * delta * roolSpeed, playerSprite.position.y   + delta * pitchSpeed * pitchProgression );

    [playerSprite setPosition:newPosition];
}

One Response to “Gyroscope handset (e.g. mobile phone): Method to control player using Gyroscope”

  1. I solved a similar problem once with the Wii remote – but we didn’t have the gyroscopes & magnetometers common in mobile devices today (the Wii Motion Plus was just coming out at the time), just accelerometer. Here’s a modified version of the approach…

    1. Keep track of a reference frame – say, a current “up” and “right” vector, or a quaternion. Initialize it to something like an identity matrix.

    2. Estimate how still the device is being held – by checking whether total acceleration is close to 1G for instance, or that all gyroscope axes are reporting close to zero.

    3. Use this estimate to gradually increase or (more sharply) decrease a “learning factor” – a coefficient that’s zero when the player is moving and approaches 1 when they’ve been still for a period of time.

    4. Blend your reference frame toward the current “up” and “right” vectors or quaternion reported by the device’s sensors, at a slow rate proportionate to your learning factor. (So when the learning factor is small during movement, you remain locked in your old coordinate system)

    5. When reading motion data, transform it into your reference frame, and do all your gameplay calculations in that frame.

    So now if the player holds the device on its side, they’ll steer sharply to one side for a few seconds, but then the control input will gradually neutralize as they keep the new position, and input will be relative to this new position from then on.

    Note that depending on the device, you might not have the ability to discern all axes of movement. For instance, if your device lacks a magnetometer, you won’t have an absolute measure of yaw. If the player lays down sideways, what was formerly an axis you could measure absolutely (pitch) becomes one you can’t (yaw), and you may get some drift. Working with relative values may help, or you can fake one axis of sensor input to keep it from drifting too far.

Leave a Reply