- Home /
Gyro quaternion offset
I currently am designing an app that tweens a unity camera around the screen, both positionally and rotationally. At one point, when the user goes to a specific location, I want them to be able to look around the scene through their iDevice using the gyro. I have this working fine. The problem is that the unity camera snaps to whatever position Input.gyro is returning on update. I know this is because I am setting my current transform.rotation to the attitude on the gyro on every frame. What I want to happen is whatever position and rotation the unity camera is at, I want to be the starting point for the gyro. So lets say I get into a car and I'm in the drivers seat, i want the camera to start looking out the windshield and then if the gyro turns right, turn to the right. Right now it rotates to the drivers seat and looks out the windshield, but as soon as the tween is over, it snaps to the gyro. So if the gyro is looking down and right, I go from staring out the windshield to looking at the cupholders in one frame. What I would want to happen in that situation is for this down right position of my iPad to be the looking straight out the window position of the unity camera, and then any adjustments from there are offset from the "looking out windshield position."
Hope this is clear and not ultra confusing. I have the gyro working just fine, I just want whatever position the gyro is in when i start checking its attitude to be a stock position/rotation for a unity camera, and then as I move the iDevice it moves the camera relative to the stock position/rotation. Right now it's not, I'm looking at the true gyro of the device. I don't know enough about Quaternions or the Input.gyro to really know where to begin. Any advice? Has anyone implemented something like this before? Any Quaternion experts out there?
Thanks.
Answer by m.alekseev · Jul 23, 2012 at 09:00 PM
Yeah! As I understand you assign the raw output of gyro to transform of the player. It looks like that I think:
transform.rotation = Input.gyro.attitude;
So you need to set initial rotation for your player's rotation and another initial rotation for gyro attitude. For example in Start():
initialRotation = transform.rotation;
gyroInitialRotation = Input.gyro.attitude;
And then In Update():
Quaternioun offsetRotation = Quaternion.Inverse(gyroInitialRotation) * Input.gyro.attitude;
transform.rotation = initialRotation * offsetRotation;
In this case I have a point in space that I am tweening to, so I used that points rotation for my initial rotation. Right as I get to the point, but before I start basing my transform on the gyro, I get the gyroInitialRotation. $$anonymous$$y update looks just like yours, except i have a small offset built in to stop the gyro form drifting, but I can't see that affecting it too much. As soon as I switch over to using that update my guy immediately snaps to the right, as opposed to looking out the windshield as is the initial rotation. Any thoughts?
The initialization has to be done right before you switch this behaviour on. If it's a seperate script, you can use Start so it get executed when you enable the script. If you use another logic that makes this code "active" you have to find a way to do the initialization manually when you switch this on.
@Just$$anonymous$$ax:
It's more convenient to do the Quaternion.Inverse also in Start, since it will be a constant value, so you don't have to calculate the inverse each frame. It should also be possible to combine the Transforms initial rotation with the gyro initial rotation, so you get a rotation that just fixes the initial offset. However, i don't dare to write it down from scratch ;) You would have to try it.
Yeah, you are right. It's done this way (in Update()) in case if you need to change initial rotation of gyro sometimes, for example to reset it after pause to prevent camera's snap. I do this way in my app.
How would you apply that to this Script and have it active upon 2 fingers touching the screen?
using UnityEngine;
public class GyroController : $$anonymous$$onoBehaviour
{
private bool gyroEnabled;
private Gyroscope gyro;
private GameObject GyroControl;
private Quaternion rot;
private void Start ()
{
GyroControl = new GameObject ("Gyro Control");
GyroControl.transform.position = transform.position;
transform.SetParent (GyroControl.transform);
gyroEnabled = EnableGyro();
}
private bool EnableGyro()
{
if (SystemInfo.supportsGyroscope)
{
gyro = Input.gyro;
gyro.enabled = true;
GyroControl.transform.rotation = Quaternion.Euler(90f, -90f, 0f);
rot = new Quaternion(0, 0, 1, 0);
return true;
}
return false;
}
private void Update ()
{
if (gyroEnabled)
{
transform.localRotation = gyro.attitude * rot;
}
}
}
Your answer
Follow this Question
Related Questions
Given a quaternion, how do I modify it to zero rotations about certain axes? 1 Answer
3D camera relatively using gyro a la N.O.V.A. 2 0 Answers
Limit Rotation of Camera around a player using keyboard 1 Answer
Quaternion partial offset, need help badly 0 Answers
allows users to view 360º content without a VR headset 0 Answers