Check if device is really moving - android

I am working on an application where I need to get the speed of a car. To get the speed, I know I can use something like double speed =locationB.getSpeed();` however when I am testing, the speed varies between 0.0 and 40 km/h when I am just sitting right behind my laptop not moving at all. In the car, the speed actually comes close to the cars speed, so that shouldn't be a problem.
What would be the best way to check if the device is really moving? I've already tried to get the distance between locationA and locationB and use that with the time it took to get the 2 locations, to get the speed.
double distance = locationA.distanceTo(locationB);
double speed = (distance / time) * 3600 / 1000;
However this seems to be not stable at all, like the getSpeed() method.
Is there a way to only display the speed if the device is moving? And would it be reliable?
Any help is appreciated,
Thanks.

Check the horicontal accuracy attribute of Location.
If it is under 30m you can ignore the location.
If you are sitting on your laptop and get speed = 40km/h (which I never saw in good GPS devices), then look what the hor. accuracy is.
It probably is much over 30m.
In GPS based systems, never ever calculate the speed by positional change in time,
just use the location.getSpeed().
The reason is that the GPS chip internally calculates the speed via physical doppler effect, not via positional change.
While standing still, or at very low speeds this does not work well, so you have to filter out very low speeds, and bad gps signal. (via horicontal accuracy estimate)

I think you should limit the distance between A and B to be a minimum length. Small distances will introduce more error into your speed calculations.
Boolean moving - false;
double distance = locationA.distanceTo(locationB);
double speed = (distance / time) * 3600 / 1000;
if (distance > SOME_THRESHOLD) {
moving = true
}

Related

How can i change step of speed to be 0.1 km/h

I've created a simple application for measuring speed. Problem is that speed updates from ie. 0.0 km/m to 0.9 km/h and 1.8 km/h and so on. What can be done, so step is reduced to 0.1 km/h.
public void onGPSUpdate(Location location)
{
location.getLatitude();
location.getLongitude();
speed = location.getSpeed();
String speedString = "" + roundDecimal(convertSpeed(speed),2);
String unitString = measurementUnitString(measurement_index);
setSpeedText(R.id.info_message,speedString + " " + unitString);
}
Since your application seems to display a speed text value in real time, it is to late to interpolate.
You have to show the current speed value and if that jumped, this is a typical situatin for a digital device.
To interploate you would have delay the display of the text.
An easy solution would be to delay by 1s, and just do an linear interpolation with n steps.
n = (speedNew - speedOld / 0.1;
This gives the number of steps use in the interpolation.
The time delay between each step = 1/n seconds.
Once that works, and since 1s is to much delay when wanting to have the current speed, you coud try with 0,5s delay. This gives time to interploat.
But it gets more difficult.
Another more advanced solution is to estimate the current velocity, each tenth of a second.
You can measure the accelaration (m/(s*s)) and extrapolate asuming the vehicle does not change the acceleration for the next second.

How to find distance of displacement using accelerometer sensor in android smartphone?

I am having one android smart phone containing accelerator sensor, compass sensor and gyroscope sensor . i want to calculate the distance of displacement using this sensors.
I already tried with the basic method ie.,
final velocity = initial velocity + ( acceleration * time taken)
distance = time taken * speed
But i am unable to get the correct displacement. Every time i tried for same displacement i am gettng diffrent results.
The equation you may be looking for looking for is:
Velocity = (Gravity*Acceleration)/(2*PI*freq)
A correct use of units for this equation (metric) would be
Gravity = mm/s squared = 9806.65
Acceleration = average acceleration over 1 second
Frequency = Hz (of the acceleration waveform over 1 second)
For example, if you gathered data from all 3 axes of the accelerometer, you would do the following to get a acceleration waveform (in raw values) for a 3D space:
inputArray[i] = sqrt(X*X + Y*Y + Z*Z);
Once the data is collected, only use the amount of samples in the waveform that would have been collected (if there is a 1ms delay between values only use 1000 values).
Add the values together and divide by the amount of samples to get your average (you may need to make all values positive if the accelerometer data have minus values) you could use this algorithm to do this before finding the average.
for(i = 0; i < 1000; i++){
if(inputArray[i] < 0){
inputArray[i] = inputArray[i] - (inputArray[i]*2);
}
}
Once you have the acceleration average output you need to perform the equation above.
static double PI = 3.1415926535897932384626433832795;
static double gravity = 9806.65;
double Accel2mms(double accel, double freq){
double result = 0;
result = (gravity*accel)/(2*PI*freq);
return result;
}
An example could be that the average acceleration is 3 gs over 1 second in a swing:
NOTE: This calculation is based on a sinusoidal waveform, so the frequency would be representative of the physical movement of the accelerometer not the frequency of the sampling rate
Accel2mms(3, 1);
3 gs over 1 second with a frequency of 1 (1 swing in one direction) = 4682.330468 mm/s or 4.7 meters.
Hope this is something like what you're looking for.
Bear in mind this calculation is based on a sinusoidal waveform but is being adapted to calculate based on a single movement (frequency 1) so it may not be very accurate. But in theory should work.
As #rIHaNJiTHiN mentioned in the comments, there is no reliable way to get displacement from 2nd and 3rd order sensors (sensors that measure derivatives of displacement like velocity and acceleration).
GPS is the only way to measure absolute displacement, though its precision and accuracy are not so high at short distances and short time periods (an in certain places with a bad signal).

gps speed compensation of location

I am using GPS with Android and need to have the location compensated for speed to remove the error due to the lag of the calculation of location. My speeds of interest are in the 5 to 10 mph range as this is for a sailboat.
Here is my code:
public double[] correctLocation(double pLat,double pLong,double pAngle,double pSpeed, double factor){
double[] latLong = new double[2];
latLong[0] = pLat + factor * pSpeed * Math.cos(pAngle * Math.PI / 180);
latLong[1] = pLong + factor * pSpeed * Math.sin(pAngle * Math.PI / 180) / Math.cos(pLat * Math.PI / 180);
return latLong;
}
I did a test run at 25mph in a car and calculated that the factor should be 3E-6 but in trying it out at running and walking speed it is clear that a factor more like 6E-6 is needed. I can't find any references to this through Google although I know people do this for example in the Google self driving car. I assume others do these kind of corrections.
Can anyone help me out here? The GPS is a Qstarz A1000XT with a MTK chipset. There are probable things I am missing with this simplistic approach. (I am assuming I don't need acceleration as this is a heavy boat with a 1 minute time constant for acceleration).
The 6E-6 was correct. I had a couple of errors and was confused for some time on this. I ended up testing by traveling at a spot from both directions at 25MPH and pinging the spot. I interpolated between GPS readings so that the timing and update rate were not a factor. I did this 10 times. That gave me two clusters of points and using a graphical method I adjusted the correction factor until the clusters overlapped. An alternate method is to use the difference in latitude and longitude between the last two readings, which are 1 second apart, and apply a correction factor in seconds. In my case that was 1.25 seconds. Both methods produced the same result in terms of the clusters. The speed correction was a tad closer in the scatter but not by much. Speed on GPS is measured off the carrier and not derived from differences in position and is more accurate.

Calculate distance between two points

I'm making an application for tracking a user as they run, cycle or walk and display it to the screen.
I know that there is distanceBetween function built into android but is this accurate enough for a fittness application?
I was considering using Haversine formula or other such formula for calculating distances between points the only problem I see about these formulas is that it usually is straight line or as the crow flys distances.
Does anyone have an idea about this?
The Haversine formula is accurate for most distances, but it suffers from rounding errors when the points are (nearly) antipodal. The following formula is accurate for all distances.
> double delta = G1 - G2;
> double p1 = cos(L2) * sin(delta);
> double p2 = cos(L1) * sin(L2) - sin(L1) * cos(L2) * cos(delta);
> double p3 = sin(L1) * sin(L2) + cos(L1) * cos(L2) * cos(delta);
> distance = 60 * Math.atan2(Math.sqrt(p1*p1 + p2*p2), p3);
Here's an example and the implementation.
resource : Here
Tracking their route as they walk is going to involve a series of way points. If you sample at say 1 way point every 10 seconds then you can calculate the distance between the previous point and the new point using either a crow-flys technique like haversine or just make some webservice requests to an external service like google maps and their distance matrix which can give you the snapped-to-streets distance between 2 points using suggested best path.
http://code.google.com/apis/maps/documentation/distancematrix/
You just have to make sure that your sample rate isn't too high or you can go over the 2500 API calls/24-hour-period rate limiter (which is per IP I believe). But 2500 will give you 7 hours at 1 sample per 10 seconds, or you can try a lower rate like 1 per 35 seconds and risk having the route be guessed wrong, but guarantee that your device won't go over 2500 samples.
Personally, if location polling is free, I would just go with distanceBetween and poll every 1-2 seconds. That should be short enough that the accuracy of GPS becomes your biggest source of error.

How to detect walking with Android accelerometer

I'm writing an application and my aim is to detect when a user is walking.
I'm using a Kalman filter like this:
float kFilteringFactor=0.6f;
gravity[0] = (accelerometer_values[0] * kFilteringFactor) + (gravity[0] * (1.0f - kFilteringFactor));
gravity[1] = (accelerometer_values[1] * kFilteringFactor) + (gravity[1] * (1.0f - kFilteringFactor));
gravity[2] = (accelerometer_values[2] * kFilteringFactor) + (gravity[2] * (1.0f - kFilteringFactor));
linear_acceleration[0] = (accelerometer_values[0] - gravity[0]);
linear_acceleration[1] = (accelerometer_values[1] - gravity[1]);
linear_acceleration[2] = (accelerometer_values[2] - gravity[2]);
float magnitude = 0.0f;
magnitude = (float)Math.sqrt(linear_acceleration[0]*linear_acceleration[0]+linear_acceleration[1]*linear_acceleration[1]+linear_acceleration[2]*linear_acceleration[2]);
magnitude = Math.abs(magnitude);
if(magnitude>0.2)
//walking
The array gravity[] is initialized with 0s.
I can detect when a user is walking or not (looking at the value of the magnitude of the acceleration vector), but my problem is that when a user is not walking and he moves the phones, it seems that he is walking.
Am I using the right filter?
Is it right to watch only the magnitude of the vector or have I to look at the single values ??
Google provides an API for this called DetectedActivity that can be obtained using the ActivityRecognitionApi. Those docs can be accessed here and here.
DetectedActivity has the method public int getType() to get the current activity of the user and also public int getConfidence() which returns a value from 0 to 100. The higher the value returned by getConfidence(), the more certain the API is that the user is performing the returned activity.
Here is a constant summary of what is returned by getType():
int IN_VEHICLE The device is in a vehicle, such as a car.
int ON_BICYCLE The device is on a bicycle.
int ON_FOOT The device is on a user who is walking or running.
int RUNNING The device is on a user who is running.
int STILL The device is still (not moving).
int TILTING The device angle relative to gravity changed significantly.
int UNKNOWN Unable to detect the current activity.
int WALKING The device is on a user who is walking.
My first intuition would be to run an FFT analysis on the sensor history, and see what frequencies have high magnitudes when walking.
It's essentially seeing what walking "sounds like", treating the accelerometer sensor inputs like a microphone and seeing the frequencies that are loud when walking (in other words, at what frequency is the biggest acceleration happening).
I'd guess you'd be looking for a high magnitude at some low frequency (like footstep rate) or maybe something else. It would be interesting to see the data.
My guess is you run the FFT and look for the magnitude at some frequency to be greater than some threshold, or the difference between magnitudes of two of the frequencies is more than some amount. Again, the actual data would determine how you attempt to detect it.
For walking detection I use the derivative applied to the smoothed signal from accelerometer. When the derivative is greater than threshold value I can suggest that it was a step. But I guess that it's not best practise, furthermore it only works when the phone is placed in a pants pocket.
The following code was used in this app https://play.google.com/store/apps/details?id=com.tartakynov.robotnoise
#Override
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() != Sensor.TYPE_ACCELEROMETER){
return;
}
final float z = smooth(event.values[2]); // scalar kalman filter
if (Math.abs(z - mLastZ) > LEG_THRSHOLD_AMPLITUDE)
{
mInactivityCount = 0;
int currentActivity = (z > mLastZ) ? LEG_MOVEMENT_FORWARD : LEG_MOVEMENT_BACKWARD;
if (currentActivity != mLastActivity){
mLastActivity = currentActivity;
notifyListeners(currentActivity);
}
} else {
if (mInactivityCount > LEG_THRSHOLD_INACTIVITY) {
if (mLastActivity != LEG_MOVEMENT_NONE){
mLastActivity = LEG_MOVEMENT_NONE;
notifyListeners(LEG_MOVEMENT_NONE);
}
} else {
mInactivityCount++;
}
}
mLastZ = z;
}
EDIT: I don't think it's accurate enough since when walking normally the average acceleration would be near 0. The most you could do measuring acceleration is detect when someone starts walking or stops (But as you said, it's difficult to filter it from the device moved by someone standing at one place)
So... what I wrote earlier, probably wouldn't work anyway:
You can "predict" whether the user is moving by discarding when the user is not moving (obvious), And first two options coming to my mind are:
Check whether the phone is "hidden", using proximity and light sensor (optional). This method is less accurate but easier.
Controlling the continuity of the movement, if the phone is moving for more than... 10 seconds and the movement is not despicable, then you consider he is walking. I know is not perfet either, but it's difficult wihout using any kind of positioning, by the way... why don't you just use LocationManager?
Try detecting the up and down oscillations, the fore and aft oscillations and the frequency of each and make sure they stay aligned within bounds on average, because you would detect walking and specifically that person's gait style which should remain relatively constant for several steps at once to qualify as moving.
As long as the last 3 oscillations line up within reason then conclude walking is occurring as long as this also is true:-
You measure horizontal acceleration and update a velocity value with it. Velocity will drift with time, but you need to keep a moving average of velocity smoothed over the time of a step, and as long as it doesn't drift more than say half of walking speed per 3 oscillations then it's walking but only if it initially rose to walking speed within a short time ie half a second or 2 oscillations perhaps.
All of that should just about cover it.
Of course, a little ai would help make things simpler or just as complex but amazingly accurate if you considered all of these as inputs to a NN. Ie preprocessing.

Categories

Resources