# Use quaternions to rotate a GO to match iPhone orientation?

I am a total Quaternionoob.

Is there anything that can be done with Quaternions, to, say, set a Game Object’s rotation to match that of the device itself?

If not, is LookAt(iPhoneInput.acceleration) the way to go?

I know that this is not a practical thing to do in a game, considering the controller and the screen are the same thing. This is just an exercise I’m taking on to educate myself for practical applications.

(I also know that the accelerometer doesn’t actually reflect rotation, but if you’re not shaking the device around, it’s close enough for me.)

AFAIK it should work ← Quaternion noob as well

Here’s a bit of code I came up with, which causes a game object to point its local negative Y to the direction gravity is pointing (if the device is held still). It is best experienced if you model an arrow. (I used a cylinder, with a cube at the bottom end, and parented those two things to an empty. I then applied this script to the empty.)

``````Vector3 gravity = new Vector3(0, -1, 0);

void Update()
{
Vector3 acceleration = iPhoneInput.acceleration;
acceleration.z *= -1;
transform.rotation = Quaternion.FromToRotation(gravity, acceleration);
}
``````

As the aforementioned noob, I am totally thrilled!

Much thanks to dawvee for pointing me in the right direction a while ago.

I’m not having any luck with getting proper rotations if I try to use an offset. Here’s the basic code I use to rotate a game object, which is what I was asking about in the first post. It uses the inverse of the quaternion from the previous code:

``````Vector3 gravity = new Vector3(0, -1, 0);

void Update ()
{
Vector3 acceleration = iPhoneInput.acceleration;
acceleration.z *= -1;
transform.rotation = Quaternion.FromToRotation(acceleration, gravity);
}
``````

Here is an example related that illustrates one case for my goal:

If the “rest position” of the iPhone were offset to be tilted 45 degrees forward

{acceleration = (0, -sqrtOfOneHalf, -sqrtOfOneHalf)},

then I want my adjusted rotation to have the X vector pointing toward the negative Y axis when you then tilt the device to the right by 90 degrees

{acceleration = (sqrtOfOneHalf, -sqrtOfOneHalf, 0)}.

Here’s some code that I thought should be helpful, but try as I might, I can’t get that X arrow pointing to the floor unless it is pointed directly at the floor, in physical space. I’ve tried a few things, such as multiplying various quaternions together, or multiplying a vector by a quaternion, but as I said, without success. Any help/correction will be extremely appreciated:

``````Quaternion rotationAdjustment;

void Start ()
{
Vector3 acceleration = iPhoneInput.acceleration;
acceleration.z *= -1;
}
``````

Hello Jessy…

I was curious to know if you’ve conquered this problem. I’m just now working on the same solution, essentially. I’d like a game object to rotate 1:1 with the tilt of the iPhone. I’ve gotten some results but working on a few other ideas to smooth it out. (I need to figure the up vector from the iPhone’s x and z tilt numbers… it should work.)

I’ll post what I end up with.

Thanks!

The code that I’m using now, which the code in this thread helped me achieve, didn’t actually require me to figure out whatever it was I was trying to figure out here. So I guess that’s a no, but I’m hopefully better prepared now to tackle relevant problems.

If you could clarify, perhaps I can help. Because the way I read what you need, you’re just talking about what any rotated screen does, without the aid of an accelerometer. That can’t be what you mean.

Heheh… no no… I wasn’t talking about physically rotating a screen so the object is now rotated in my world. LOL! Anyway… what I meant by “1:1” was the whole 0.0 - 1.0 nature of the device’s tilt and a game object’s rotation vectors. So what I’m after is if I tilt the device left 90 degrees, then the object on the screen would be rotated left 90 degrees (if I can tie those numbers together to work). It’s not very practical, but it’s where I’d like to start. I can multiply (scale) that to my flavor later, but I just wanted to get the raw numbers to equate one with the other so I could mess with it after. The device’s accelerometer gives me numbers that are similar to a game object’s vector rotations, except z and y seem to be swapped, and a perfectly calibrated device resting on a flat surface seems to register (0, 0, -1). (instead of a GO’s Vector3(0, 1, 0) … or something like that.)

If I use:

thisTransform.rotation *= Quaternion.FromToRotation(transform.up, iPhoneTilt);

then it gets close to working… but not quite there. The transform gets very jittery even if I set the device flat on the desk. It also completely spazzes out on me if I rotate the device in some more extreme directions.

I’m still fairly new to Unity and I’m just trying to mess with all of the rotation tools to see how they work and when some should be used over others. Not all documentation of these tools makes it clear of what exactly they do unless you test them out fully… or if you have a degree in “rocket surgery”.

Thanks Jessy!

Like I said, any screen already does one-to-one mapping just by virtue of displaying a static image, even when you rotate it. It’s not like the iPhone is a controller; the hardware is tied to the screen. It’s not a Wii Remote. You could watch something happen in the Editor, but that’s not something you can build for others to use.

So keeping that in mind, what orientations are you trying to match? Please be very specific. There isn’t a correlation between the iPhone and a GameObject’s axes until you invent one for some purpose. It can never be 1-to-1, because when you rotate the iPhone along the axis of gravity, the accelerometer doesn’t give you different readings. Without a gyroscope, you need to temper your expectations.

Sorry, that’s still not what I’m talking about. I’m not looking to change the object’s y-axis rotation because you’re right… that’s impossible without a gyro. I just want the x and z axes to be affected, which is, of course, entirely possible.

If I can get this to work then the end result will be me tilting (not turning) my phone left/right/forward/back in n degrees then the object will tilt, local to itself, to the left/right/forward/back in n degrees.

There are other ways to do it but I was trying to equate the data from the accelerometer with a normalized vector… 1:1. The vector would help orient the object on screen. The problem was getting the y vector to reflect what x and z were doing so the rotation vector would be correct.

This isn’t exactly what I did, I actually had a separate object that tracked the accelerometer and averaged the samples over time and gave me an average angle.

I also had additional constraints on the rotation and other such things.

What you see below is a slimmed down, untested version of my code.

``````public Vector3 center;
Vector3 position;
float lastAngle = 0;
void Start()
{
position = transform.position;
}
void FixedUpdate()
{
angle = Vector3.Angle(
iPhoneInput.acceleration,
Vector3.up*-1);
Vector3 cross = Vector3.Cross(
iPhoneInput.acceleration,
Vector3.up*-1);
cross.Normalize();
angle *= -cross.z;
if(Mathf.Abs(lastAngle-angle)>1)
{
transform.rotation = Quaternion.identity;
xform.position = position;
transform.RotateAround(
center.position,
Vector3.forward,
angle);
lastAngle = angle;
}
}
``````