# Accelerometer-Based Rotation

I need to create an object that rotates with the iPad. Think of it as a pendulum hanging from the center of the screen that always points down. Tilt left or right and it swings the opposite direction to remain pointing at the ground. If the iPad is lying face up, it points away from the screen, face down and it points toward the screen.

Here’s the code I adapted from another post in this forum:

``````var upD: float;
var leftD: float;
var rotZ: float;
var rotX: float;
var smoothTime = 0.3;
var smoothVelocity = 0.3;

//------------------------------------------------

function Start () {
rotZ = 0.0;
rotX = 0.0;
upD = Mathf.Atan2(-iPhoneInput.acceleration.y, -iPhoneInput.acceleration.x) * Mathf.Rad2Deg;
leftD = Mathf.Atan2(iPhoneInput.acceleration.y, iPhoneInput.acceleration.z)  * Mathf.Rad2Deg;
}

//------------------------------------------------

function Update () {

upD = Mathf.Atan2(-iPhoneInput.acceleration.y, -iPhoneInput.acceleration.x)  * Mathf.Rad2Deg;
rotZ = Mathf.SmoothDampAngle(rotZ, upD, smoothVelocity, smoothTime);

leftD = Mathf.Atan2(iPhoneInput.acceleration.x, iPhoneInput.acceleration.z)  * Mathf.Rad2Deg;
rotX = Mathf.SmoothDampAngle(rotX, leftD, smoothVelocity, smoothTime);

transform.eulerAngles = Vector3(rotX + 90, 0.0, rotZ);
}
``````

If I comment out the first two lines in Update and just translate along the X axis, it works correctly. If I comment out the next two lines and just translate along the Z axis it works correctly. But when all the code is in and it translates on both the X and Z axes, it does not work at all, swinging wildly in all directions.

Am I doing something wrong? I don’t really understand the Atan function or why it’s necessary, so that could be my problem.

You’re making it really hard on yourself.

http://forum.unity3d.com/viewtopic.php?p=198096#198096

I’m not sure exactly what you are talking about. I see several examples of code that doesn’t work, but have tried all the code snippets and there are none that do work. The closest is the first code snippet in the third post, but it always points left (works in z and 90 deg off in x). What specifically are you referring to in that thread?

That’s not a link to a thread. That’s a link to a post. I described how to do exactly what you’re talking about, and, as I said, came up with and verified that it works myself.

This code does not work for me:

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

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

It I make the gravity value positive or if I swap gravity and acceleration, it works for rotation along the z axis, but is 90 deg off on the x axis. It points to the right instead of down. If I leave the gravity value at -1, it is backwards along the z axis (pointing in instead of out) and points to the left. I can’t figure out how to compensate for that x axis shift.

I think you’re asking too much out of the accelerometer; the iPhones previous to version 4 don’t know which way they’re facing, so I don’t think you can use these concepts of forward, right, etc., like you seem to be describing. What I showed you works for something that is radially symmetrical (like a pendulum that is a ball on a string).

That’s exactly what I have, a pendulum (a sphere primitive at the end of a cylinder primitive) that I want to appear to be hanging from the center of the screen and always point down. I know it can be done, because I can do it it one axis or the other, so the accelerometer data are sufficient. The thing that’s got me stumped is how to get it working in both axes at the same time. I’m missing something.

Up and down are not arbitrary concepts. If you are holding the device in portrait orientation with the home button at the bottom, down is toward the home button and left is to my left. In this case, the pendulum should point toward the home button. If I flip it so the home button is on top, the pendulum should point away from the home button.

I just tested the code again. It does exactly what you just said. Are you sure you’re not applying this to a mesh that was imported from Blender or something? The rotation would be off in that case; I use Blender myself, and have to deal with the weird rotation issue, but you could just apply this script to the parent of the mesh (the parent represents the .blend itself). Otherwise, I don’t see why you’re having a problem.

Nothing was imported. To get this code figured out, I created a sphere and a cylinder primitive in Unity, then used an empty object parent as the pivot point. The script is attached to the parent object. Eventually, I will use an imported model.

When you say it does what I just said, you mean it’s not working for you either?

So maybe we are just misunderstanding each other. Your code works for me in one dimension. It’s adapting it so it works in two dimensions that is the problem for me. I can get it to work in only one dimension at a time. There’s some interaction going on when I try to do both that I can’t figure out.

I’m thinking this should be a really simple thing to do, but my lack of math skills is making me miss something obvious that I’m doing wrong.

No, it works perfectly as I see it. If you want to post a video or come up with some other method of comparison, perhaps I can help you fix whatever is wrong on your end.

There’s not much to show in a video. My pendulum points left instead of down. It’s correct for z axis rotation, but with x axis rotation it is off by 90 deg.

And here’s something interesting I’ve discovered. If I put this code in Update, I have to multiply the Z value by -1, but if I put it in LateUpdate I do not.

That sounds completely broken. Import this. Update or LateUpdate, makes no difference. You’ll need to change Input.acceleration back to iPhoneInput.acceleration if you’re not using the Unity 3 beta.

I figured out the problem. Depends on what the iPod orientation is set at to begin with. I had Unity set to landscape (iPhone Wide), and that caused the 90 deg shift. If I start in portrait (iPhone Tall), it works.

Now I just need to figure out how to smooth out the jittery motion.

I don’t believe in or support using the accelerometer in Wide mode. Sorry I didn’t think of that.

The “iPhone unique Input system” page provides a method for lowpass filtering the accelerometer.

Thanks. I saw that and tried it. That code has several bugs in it, and does not work as is. Maybe it was written for an older version of Unity.

But even after correcting the code and tweaking the parameters, it doesn’t have much of an effect. With the iPod sitting still on the table, the pendulum still jerks around continuously.