Compute Altitude and Azimuth from CMAttitude using either Roll, pitch and Yaw or Quaternion or Rotation Matrix - iphone

I am struck with a problem. I want to convert the CMAttitude information of an iPhone to Altitude (0 to 90deg) and Azimuth (0 to 360 deg). I have googled around and hit some threads which discuss about it, but none of threads turn out with a positive answer and most of the articles discussing Quaternion and Euler angles are too much mathematics to stuff into my brain!
Is there some open source material which does this task easy? Or someone has written code to perform this conversion?
Edit:
First off, sorry for being so abstract!
Azimuth is the direction on the surface of the earth towards which the device is pointing. Like North = 0 deg, North East = 45deg, East = 90 deg, South = 180 deg and so on. Ranges between 0 deg to 360 deg:
Altitude is the angle made from the plane of the earth to an object in the sky:
Thanks,
Raj

Using CMDeviceMotion, you can get a CMAttitude object with "roll, pitch and yaw" - where for example, given a phone held in portrait mode "yaw" is "azimuth", "pitch" is the tilt of the phone with respect to ground, or zenith, and "roll" is about the vector pointing through the screen and not what you're interested in.
Things get a bit tricky because "azimuth" is a projection of the 3D magnetic vector (pointing towards the magnetic north pole) on to the flat "ground" plane, which changes depending on device orientation, but given this understanding of the terms, threads like this one should be much more understandable. If you only need your application to work in one orientation things get much simpler.
P.S. "altitude" is almost exclusively used to refer to elevation or height about a given reference (sea level, geodetic height etc). "Zenith" or "pitch" are preferable, and since you're on iOS, you should stick to their coordinate scheme: (lat, lon, alt), (pitch, yaw, roll).

Related

Madgwick IMU 90 Degrees Angles

I'm using the C++ implementation of the Madgwick Algorithim, having my sensors (accelerometer, magnetometer and gyroscope) calibrated. Everything seems to work well, but when I put the sensor in vertical position (pitch to 90 degrees) the other angles start doing weird things. This is what I get:
Matlab plot problem
In fact, the angles I get are correct, but expressed in a different way. I should get only:
Roll: 0
Pitch: 90
Yaw: -150
But I get:
Roll: -180
Pitch: 90
Yaw: 50
Both results are the same, right? My questions are:
Is this the Gimbal Lock problem?
As far as I know, Gimbal Lock should get errors in the angles, but I'm getting them OK. Is the Madgwick algorithm trying to avoid that Gimbal Lock?
No, you can not Gimbal lock a sensor, as it is a physical object that you moved.
Gimbal lock refers to a state on where if you where to move 2 angles, they would have the same effect on the rotation. It is not an error, but an specific rotation state. But if you are personally moving the object by hand, Gimbal lock is impossible. Wikipedia has a brilliant gif:
Gimbal locked airplane. When the pitch (green) and yaw (magenta) gimbals become aligned, changes to roll (blue) and yaw apply the same rotation to the airplane.
However, note that the cause of Gimbal lock may be the cause of your data: In euler angles, there are multiple sets of angles that give the exact same end point. Which one does your system gives you? you cant know. Depends on the sensor and algorithm used to give you the data.
A good way of ensuring your further maths are consistent and knowing that 2 rotations are the same is to convert your measurements into quaternions. These are unique to every rotation, and will help you better understand what rotation has happened.

Using the iPhone accelerometer in a car

I want to use the iPhones's accelerometer to detect motions while driving. I'm a bit confused what the accelerometer actually measures, especially when driving a curve.
As you can see in the picture, a car driving a curve causes two forces. One is the centripetal force and one is the velocity. Imagine the iPhone is placed on the dashboard with +y-axis is pointing to the front, +x-axis to the right and +z-axis to the top.
My Question is now what acceleration will be measured when the car drives this curve. Will it measure g-force on the -x-axis or will the g-force appear on the +y axis?
Thanks for helping!
UPDATE!
For thoses interested, as one of the answers suggested it measures both. The accelerometer is effected by centrifugal force and velocity resulting in an acceleration vector that is a combination of these two.
I think it will measure both. But don't forget that the sensor will measure gravity as well. So when your car is not moving, you will still get accelerometer readings. A nice talk on sensors in smartphones http://www.youtube.com/watch?v=C7JQ7Rpwn2k&feature=results_main&playnext=1&list=PL29AD66D8C4372129 (it's on android, but the same type of sensors are used in iphone).
Accelerometer measures acceleration of resultant force applied to it (velocity is not a force by the way). In this case force is F = g + w + c i.e. vector sum of gravity, centrifugal force (reaction to steering centripetal force, points from the center of the turn) and car acceleration force (a force changing absolute value of instantaneous velocity, points along the velocity vector). Providing Z axis of accelerometer always points along the gravity vector (which is rare case for actual car) values of g, w and c accelerations can be accessed in Z, X and Y coordinates respectively.
Unless you are in free fall the g-force (gravity) is always measured. If I understand your setup correctly, the g-force will appear on the z axis, the axis that is vertical in the Earth frame of reference. I cannot tell whether it will be +z or -z, it is partly convention so you will have to check it for yourself.
UPDATE: If the car is also going up/downhill then you have to take the rotation into account. In other words, there are two frames of reference: the iPhone's frame of reference and the Earth frame of reference. If you would like to deal with this situation, then please ask a new question.

iPhone compass presents the wrong heading pitch angle is > about 45°

This might be hard to explain the geometry so I will be careful in spelling it out. This is visible in the standard compas app and from the data in CLLocationManager.
1) When holding the phone in portrait orientation, consider the pitch angle to be 0°
2) When pointing the camera up into the sky (such as taking a picture of a cloud) the pitch angle goes from 0° -> 90° where 90 degrees is straight up.
3) when the phone is tilted upward (> 0 degrees and rotating on the "X" magnetometer axis) and when the phone is at about (but not exactly) 45 degrees, the compass heading rotates 180 degrees. So while the camera is still point "N", the compass will report "S".
4) for the next (roughly) 90 degrees, the compass heading is rotated 180 degrees.
This rotation of the heading is destructive for me and it does not align perfectly with the accelerometers. Is there a good tutorial (I did not find one off the bat) on using the the RAW data (X, Y, Z) from the CLHeading data to calculate heading data?
The end result is I want the heading of the compass to always match the heading of the camera.
You can't rely on solely the compass heading. See this answer for what you're looking for, and in particular the CMAttitude object's yaw property to compensate for the pitch angle you're talking about:
Compensating compass lag with the gyroscope on iPhone 4

Where the iPhone compass points? (math question, not geography)

I noticed a really puzzling behavior on iPhone:
If I hold the phone in the vertical, and tilt it, the compass change.
I already figured the amount it changes is the same amount it would change for the same amount of tilting if it was in horizontal (ie: suppose that a vector coming from the screen is called Y, turning around Y does not matter the attitude of the iPhone results in a compass change).
I want to compensate that, my app was not made to you hold the phone in the horizontal (although I do plan also to allow some tilting in the X axis let's call it, from like 10 degrees to 135)
But I really could not figure how iPhone calculate the heading, thus where the heading vector actually points...
After some scientific style experiments, I found:
The iPhone has magnetometer, it has 3 axis, X, that goes from left to right from the screen. Y, that goes from bottom to up. And Z, that comes from behind the phone and comes to the front.
Earth magnetic field is as expected by the laws of physics not a sphere, in the location I am (brazil), it is slanted about 30 degrees. (meaning that I have to hold the phone in a 30 degrees angle to zero 2 axis).
One possible technique to calculate north, is use cross product of a vector tangential to the magnetic field (ie: the vector the magnetometer reports to you), and gravity. The result will be a vector that points east. If you wish you can make another cross product between east and gravity, resulting in a vector that points north.
Know that iPhone sensors are quite good, and every minor fluctuation and vibration is caught, thus it is good idea to use a lowpass filter, to remove the noise from the signal.
The iPhone itself, has a complex routine to determine the "true heading", I don't figured it completely, but it uses the accelerometer in some way to compensate for tilt. You can use the accelerometer and compensate back if that is your wish, for example if the phone is tilted 70 degrees, you can change the true heading by 70 degrees too, and the result will be the phone ignoring tilting.
Also the routine of true heading, verify if the iPhone is upside down or not. If we consider it in horizontal, in front of you as 0, then more or less at 135 degrees it decides that it is upside down, flipping the results.
Note the same coordinate system also apply to the accelerometer, allowing the use of vectors operations between accelerometer and magnetometer data without much fiddling.

iPhone - CLHeading: how can I transform the trueHeading to a vector

I know how to get the coordinates of the magnetic heading: heading.x, heading.y, heading.z
The thing is that I'd need the (x, y, z)-vector of the trueHeading. How can I create this vector?
Thank you!
Edit: I have changed my answer quite a bit...
Basically you need to rotate the magnetic north vector in the opposite direction to the Magnetic Declination angle.
The hard part is that you need to rotate the vector on a horizontal plane. For that you need to know the orientation of the phone.
Here is what you need to do:
Get the magnetic north vector.
Get the gravity vector from the accelerometer.
Now calculate / look up the Magnetic Declination (it depends where you are in the world and it also varies slowly with time).
Rotate the magnetic north vector X degrees about the gravity vector (where -X = Magnetic Declination). This will be the tricky part, you will need to brush up on some 3d trig.
Thank's for the edit...funny, that's exactly what I did then. I took the magnetic north vector and rotated it with a rotation matrix around the gravity vector with the variation between the magneticHeading and the trueHeading.
The thing is that I'm dependent on the magnetic vector in this case.
In some situations I noticed that the magnetic vector was going absolutely crazy and the sensor delivered weird values.
So what I wanted is to get the vector of the trueHeading which is independent from the magnetic vector. Ok, what a silly thought - the true heading is most probably anyway dependent on the magnetic heading already.
However - thank's for the answer :)