iOSMotion Rotation problem

My iPhone and iPad screens support only the Portrait orientation (with home button down).
So when I rotate the device, the orientation stays the same.

What I want to achieve is that whether I lay the phone flat on my desk, or hold it straight up, detect the rotation of the axis that goes through the glass to the back of the phone. That is the Z-axis, right?
I want to draw a background image that stays level, no matter how I rotate my device.

But what happens when I check the Yaw value, it is different when I hold the phone straight from when I have the phone laying flat.
I’ve found a thread in the forum where Richard talks about a rotation matrix. I plotted the values on my screen, but I have no clue what to do with it, or even how to read them.
Are there other values or formulas I have to look at?

Thanks in advance! :smiley:

Here is an iOS Swift/Objective C programming blog that show you how to do what I think is exactly what you want using Apple’s tools using the accelerometer and gyro:

http://nshipster.com/cmdevicemotion/

This probably wouldn’t be that hard to implement in Xojo as it appears that iOSMotion can do except maybe the CGAffineTransform which you would have to hardcode in…

[quote=309439:@Richard Allmendinger]Here is an iOS Swift/Objective C programming blog that show you how to do what I think is exactly what you want using Apple’s tools using the accelerometer and gyro:

http://nshipster.com/cmdevicemotion/ [/quote]

Wow! looks promising. I will dive into that right away! It explains the Motion techniques very well. And I am sure it is doable to implement it in Xojo.
I will try to remind myself to document my findings here on the forum. Just in case somebody in the future needs it…
(I love this community)

I have an implementation of CMDeviceMotion in iOSKit. Looking at it now, it seems I may not have all of the properties which are available, but if you take a look and see some are missing let me know and it shouldn’t take me very long to add them.

I’d love to take a look at it, Jason. Would that be in your GitHub archive? Which file should one download?

Yes its on github. Download the whole thing, open iOSKit.xojo_project then copy the Modules folder into a new project. It’s in the CoreMotion module. Let me know if you have any more questions!

Hi Jason – I had a chance to go through your iOSKit project. Lots of really useful stuff in there. Unless I missed it, I didn’t see anything to do with the magnetometer. In particular, I’m looking for a way to determine if the magnetometer needs calibrating and what the accuracy level and heading error of the magnetometer are. Did I miss something?

Thanks for all your help!

Hi Richard, I don’t current have a complete implementation for the magnetometer aspects of CoreMotion (because no one else has ever needed it) although it shouldn’t be very difficult to add. Please give me a few days and I will add them to the repository.

Is it possible to see an example to clarify some of these motion principals? For example if we put an object in the middle of a view and tilt the screen the object slides in that direction.

An object on the screen should slide in the direction of the maximum acceleration due to gravity, resolved into the plane of the screen. Without thinking about it too much, I would think that this direction would be given by the vector sum of the gravity.X and gravity.Y components (which lie in the plane of the screen). If you were to place a canvas the size of the screen on the view, the Y direction of the canvas will be the same as the y direction of the device. One would use gravity.X and gravity.Y to calculate the angle you want your object in the canvas to move. Although tangent comes to mind first; that will blow up at 90 and 270°.

Hi Richard,

Is Gravity.x and Gravity.y the same as Roll and Pitch?

Can you give an example of the angle calculation? If I tilt the phone towards my toes
gravity.x = -0.018 (slight left tilt)
gravity.y = 0.4 (steep down tilt)

??

[quote=312373:@Martin Fitzgibbons]Is Gravity.x and Gravity.y the same as Roll and Pitch?

Can you give an example of the angle calculation? If I tilt the phone towards my toes
gravity.x = -0.018 (slight left tilt)
gravity.y = 0.4 (steep down tilt)[/quote]

Not exactly, roll and pitch are angles of rotation about an axis whereas the units of gravity are g (i.e., the acceleration due to gravity where 1 g = 9.81 m/s^2). When you lay the phone flat on a horizontal table gravity.x and gravity.y should be essentially zero and gravity.z should be one – well, actually -1 because the Z axis is positive upwards and gravity is pulling in the direction of the negative direction, i.e., downwards. Because gravity is 1 g (at sea level, at least), you can think of it as a unit vector pointing towards the center of the earth. The x, y and z components should behave like direction cosines.

In your example, one could calculate the maximum acceleration due to gravity in the plant of the phone as

Accel = sqrt(g.x^2 + g.y^2) [very slightly more than 0.4

And the angle with respect to the Y axis as:

Angle = atan(g.x/g.y) =-2.58 degrees (i.e., counterclockwise from +Y)

That would be the direction that a virtual object on the screen would slide as you tilt the phone. To make it physically realistic, the rate of the sliding on the screen would be proportional to the Acceleration in the plane. The steeper you tilted the phone, the faster the object would slide.

Note that the tilt of the phone is given by the gravity.z component: tilt = pi/2 - acos(gravity.z) where 90 degrees = pi/2 radians.

Thanks Richard for the detailed explanation that has given me a bit to think on and looks like it will yield a better result.

I had fairly simple movement working with
UpdateTimer
R = R + 10 * MyiOSMotion.roll
P = P + 10 * MyiOSMotion.Pitch
MainCanvas.Invalidate
MainCanvas
g.DrawImage(Ball,LastTouchPoint.X+R, LastTouchPoint.Y+P-40,Ball.Width,Ball.height)

Question…
With the GravityAccelerationZ I can detect if my iPhone is laying flat on my desk or holding it up.

With the Yaw, I can see how I rotate around the Z-axis.
But when holding my iPhone up, it seems that the Yaw value is larger. Only laying my iPhone flat results in the desired values.

As I said before. I want to display an image a lot like this one:

But I want to be able to rotate my phone around the Z-axis and have the image rotate accordingly. And holding it up or having it flat should not make a difference.

in Richard’s matrix the value R21 seems to work pretty well. At least, this value changes the right way. No matter how I hold my device. The R21 value changes the same way, while I rotate over the Z-Axis.

But I can’t rotate a full 360º. The value seems to go between 0º and 180º and back to 0º.

I just can’t wrap my head around it…

I think I found a solution for my problem.
I noticed that laying the phone flat I could use the Yaw value. When holding it up I could use the Atan2 formula as mentioned on THIS site.
I only needed to get some kind of up/flat factor to see how much of the Yaw and Atan2 values I needed.
I can use the myRotation value in the rotate property of the iosGraphics object. I tested it, and it works!

Below an extraction of the code I used in my test. Just in case I look for it in the future… or, of course, to help others that might be looking for a solution to the same problem.

[code]dim flatFactor as Double = 1 - pitch
if flatFactor < 0 then flatFactor = 0
if flatFactor > 1 then flatFactor = 1
dim upFactor as Double = 1 - flatFactor

dim rotationUpright as Double
rotationUpright = xojo.Math.ATan2( gx, gy ) - Pi

dim myRotation as Double
myRotation = ((upFactor) * rotationUpright) + ( (flatFactor) * yaw )[/code]