views:

1125

answers:

5

Hello,

I am working on an iPhone app where we are trying to calculate the acceleration of a moving car. Similar apps have accomplished this (Dynolicious), but the difference is that this app is designed to be used during general city driving, not on a drag strip.

This leads us to one big concern that Dynolicious was luckily able to avoid: hills. Yes, hills.

There are two important stages to this: calibration, and actual driving.

Our initial run was simple and suffered the consequences. During the calibration stage, I took the average force on the phone, and during running, I just subtracted the average force from the current force to get the current acceleration this frame. The problem with this is that the typical car receives much more force than just the forward force - everything from turning to potholes was causing the values to go out of sync with what was really happening.

The next run was to add the condition that the iPhone must be oriented in such a way that the screen was facing toward the back of the car. Using this method, I attempted to follow only force on the z-axis, but this obviously lead to problems unless the iPhone was oriented directly upright, because of gravity.

Some trigonometry later, and I had managed to work gravity out of the equation, so that the car was actually being read very, very well by the iPhone.

Until I hit a slope. As soon as the angle of the car changed, suddenly I was receiving accelerations and decelerations that didn't make sense, and we were once again going out of sync.

Talking with someone a lot smarter than me at math lead to a solution that I have been trying to implement for longer than I would like to admit. It's steps are as follows:

1) During calibration, measure gravity as a vector instead of a size. Store that vector. 2) When the car initially moves forward, take the vector of motion and subtract gravity. Use this as the forward momentum. (Ignore, for now, the user cases where this will be difficult and let's concentrate on the math :) 3) From the forward vector and the gravity vector, construct a plane. 4) Whenever a force is received, project it onto said plane to get rid of sideways force/etc. 5) Then, use that force, the known magnitude of gravity, and the known direction of forward motion to essentially solve a triangle to get the forward vector.

The problem that is causing the most difficulty in this new system is not step 5, which I have gotten to the point where all the numbers look as they should. The difficult part is actually the detection of the forward vector. I am selecting vectors whose magnitude exceeds gravity, and from there, averaging them and subtracting gravity. (I am doing some error checking to make sure that I am not using a force just because the iPhone accelerometer was off by a bit, which happens more frequently than I would like). But if I plot these vectors that I am using, they actually vary by an angle of about 20-30 degrees, which can lead to some strong inaccuracies. The end result is that the app is even more inaccurate now than before.

So basically - all you math and iPhone brains out there - any glaring errors? Any potentially better solutions? Any experience that could be useful at all?

Award: offering a bounty of $250 to the first answer that leads to a solution.

+5  A: 

You need a gyro. Otherwise there are multiple configurations of an accelerating car on a hill that can give rise to exactly the same readings on an accelerometer. They will be completely impossible to distinguish. That's why inertial navigation systems combine a gyro and accelerometer.

The reason you can't do this was given by Einstein! Using a local measurement, you can't distinguish between gravity and acceleration. You do have some useful non-local information - the assumption that gravity here, and gravity a few yards over there, have the same value. But you can't compare gravity in two different locations without a means to carry out what's called "parallel transport". This is what a gyro does.

Forget the $250, but I think you should give me a beer for the amount of R&D time I'm saving you. :-)

You don't have a gyro but on the 3GS you do have a compass. A 3d magnetometer to be more precise. You can detect the rotation of the phone in 3d and know the relative direction of the acceleration vector. That could substitue for the gyro, couldn't it? You can calibrate the magnetometer to have a horizontal reference just like a gyro.See Teslameter: http://developer.apple.com/iphone/library/samplecode/Teslameter/Introduction/Intro.html#//apple_ref/doc/uid/DTS40008931-Intro-DontLinkElementID_2
progrmr
In principle a compass would work well. At a guess I'd say that assuming accuracy, it might work on hills but not if you also allow banked curves. But my experience with the compass has been that it's only good for generating random numbers. :-) It could be that I'm unlucky and I have a bad one.
There's no need to invoke General Relativity when Newton's laws of gravity is enough. The equivalence principle is much older than Einstein.
KennyTM
Einstein said "we [...] assume the complete physical equivalence of a gravitational field and a corresponding acceleration of the reference system." Why exactly shouldn't I mention this? It's a clear statement of exactly what I need. Newton doesn't say it anywhere. It could be deduced, in a limited form from Newton. But Einstein said it. And I didn't mention GR, you did.
Holy moly, you guys are clever
willcodejavaforfood
+1  A: 

Some thoughts:

  • Gravity is a vector quantity, not a magnitude.
  • Acceleration due to gravity and acceleration due to some other force are not distinguishable (you also can't able to tell the difference between going around a corner and rolling your car).
  • You might have better luck with two accelerometers, but then you'd need two phones.

If it were me, I'd write up a disclaimer that says "This doesn't work on hills, use a straight, level road for testing."

P.S.: I like the cash reward for answers, I'll be sure and post that as a suggestion on meta.stackoverflow.com :P

Seth
+2  A: 

To solve this, if possible, you would need to reference something external to the car. Probably using the GPS to measure elevation gain is the most direct approach. That is, calculate the slope of the hill using the measured elevation gain, and use this to compensate the acceleration measurement.

As others have mentioned, at a very deep level, there's no way to distinguish between gravity and acceleration; this is known as the Equivalence Principle (and was one of Einstein's most important insights). So one would need to know more than the accelerometer's output to solve this problem, and this makes the problem difficult. For various approaches to the problem, see here.

Your best hope is to reference something external to the car, like a GPS signal, or pictures to measure the change in the location of something outside the car, or the earth's magnetic field, etc. Since this will take place near a lot of metal (the car) the earth's field will likely be difficult to measure, and continuous photos of some reference object (like the sun) is obviously difficult, so it seems that the GPS is your best bet.

More on why you need an external reference:

It's worth considering whether you could use the unique features of gravity that 1) it's always “on”, 2) it always has the same magnitude (for this situation). But when all you know is the total acceleration, you can't reliably separate the two contributions. As the picture below shows, just knowing the magnitude of gravity isn't enough... the picture below is drawn in the phone's frame of reference where it measures the resultant acceleration (black vector), and the larger colored arrows are possible gravity vectors, while the matching color smaller arrows are the corresponding acceleration vectors. So you can see, without knowing and angle, you don't have enough information to solve the problem.

alt text

The other thing you might be able to do is integrate the output from a gyro to find the angle of the gravity vector. That is, assuming that you start on the flat, and then you always keep track of the where you think gravity would be based on the accumulated small changes. But this is highly error prone, and your error in the calculation will accumulate quickly with time; and it also assumes that you have access to a gyro.

Therefore, the only good solution is to use external information.

tom10
Tom, gravity *is* acceleration.. no need to bring in Equivalence Principle or so...
Soham
@Soham – Gravity is acceleration *because* of the equivalence principle. If this weren't the case, then one could distinguish between the two using, for example, two accelerometers with two different masses on the springs, and probably all accelerometers would be built this way, and the OP's question wouldn't have been asked. It's only that inertial mass and gravitational mass are the same that you say “is” with such confidence. (Before the equivalence principle people used to think gravity was a force that caused acceleration, not that it was one.)
tom10
Does inertial and gravitational mass ever differ? I just felt, that quoting EP in such a situation was tantamount to overkill
Soham
The *point* of the original question is asking for *a way to separate gravitational and motion accelerations*, so it's clearly relevant to point out that there is fundamentally *no single local measurement that can do this*. EP is a simple and clear statement of this, and is the major issue in defining this problem, and constraining possible solutions.
tom10
A: 

@The Gazzardian,

So your essential problem as I understand is to detect the forward vector. You can opt these:

  1. You sample the speed at say every 0.2 seconds for 5 seconds and switch the sampling off for the next n seconds,so that resource is not hogged. Now what you can do from those datapoints is, you will be able to discern the rate of change of speed(there are simple numerical methods to find the derivative using data points). But this wont give you acceleration in the truest sense, because it wont give you the direction. AFAIK, the accelerometer yields the direction as well, i.e how much inclined it is to one of the axis/gravity.

Consult this figure to detect the angle: Angles and Hills

Another possible method, is to find the extra force during the climbing of the hill. Given the extra force, you might be able to find the angle. The vertical component of the extra force is to counter, the vertical component in opposite direction, g.

Soham
Extending on tom's idea of taking photograph/gps etc, I am not sure if iphone has gps ability(heck I dont even own an iphone), but I surely believe it will be possible to take a photograph of the road ahead and decide from that(using image processing) the perception of depth or elevation? Perhaps, too long a shot? I dont know
Soham
A: 

This doesn't solve your problem completely, but hopefully it clears up what you've been trying to do. I do believe that ultimately you will need some other instrument to be able to fully do this. GPS as tom10 suggested sounds like the best option to me (since there isn't a gyro available), but I foresee problems with that such as lag time and inaccuracy in the GPS coordinates (I don't know how accurate the iPhone GPS is).

First, I assume that the iPhone is firmly attached to the car throughout. For a slope that is up or down with no curve left or right, you can do the following for calibration.

Calibration

  1. Find a surface such that its degree of inclement is not appreciably changing.
  2. Find the acceleration vector when the car isn't moving with respect to the road. Record this full vector (x,y, and z components) as v1. g = |v1| is the magnitude of gravity which should stay the same throughout.
  3. Start to drive straight forward on the slope (up or down it, not to the side and of course a flat surface is great too).
  4. Record this full acceleration vector as v2.
  5. Find v3, the vector indicating forward motion, by taking v2 - v1 (subtracting off gravity).
  6. Find v4 = v3 x (v1 x v3) where x is the vector cross product.
  7. Find the unit vector of v4, v5 = v4 / |v4|

v5 points in the direction that gravity will point when the car is on a perfectly flat surface. You can now at least tell if you are on a slope of some sort and what the angle is of that slope. This can be done in the following manner:

  1. Record the current acceleration vector, a.
  2. Find the dot product of a and v1, c = a . v1
  3. If c is less than g (as opposed to being equal to g), the car is on a slope. The angle of the slope is theta = arccos(c/g).

However, this is where we run into problems. Even if we limit ourselves to slopes that are up and down rather than curving/banking left or right, we still can't tell for sure if the slope is going down or up - just the angle of it. We can find initially if the car is going up or down a slope by taking the dot product of v1 and v3 (a positive value indicates a downward slope, and a negative value an upward slope).

You might however be able to use the fact of whether the magnitude of the total acceleration vector is decreasing or increasing as the slope increases or decreases to make a guess at this, but it won't be for sure. For instance, if the angle (theta) of the slope has been 0 degrees (or close enough to it) and now it isn't, and the projection (dot product) of the overall acceleration onto the unit vector of v3 is decreasing, then we might infer that the car is going up a slope. Again, this would just be a guess which could very well be wrong. I say could, but what I mean is that it will be wrong sometimes.

That's about as much information as I can envision getting out of a system that just uses the accelerometer. Good luck!

Justin Peel