My Algorithm to Calculate Position of Smartphone - GPS and Sensors
As some of you mentioned you got the equations wrong but that is just a part of the error.
Newton - D'Alembert physics for non relativistic speeds dictates this:
// init values
double ax=0.0,ay=0.0,az=0.0; // acceleration [m/s^2]
double vx=0.0,vy=0.0,vz=0.0; // velocity [m/s]
double x=0.0, y=0.0, z=0.0; // position [m]
// iteration inside some timer (dt [seconds] period) ...
ax,ay,az = accelerometer values
vx+=ax*dt; // update speed via integration of acceleration
vy+=ay*dt;
vz+=az*dt;
x+=vx*dt; // update position via integration of velocity
y+=vy*dt;
z+=vz*dt;the sensor can rotate so the direction must be applied:
// init values
double gx=0.0,gy=-9.81,gz=0.0; // [edit1] background gravity in map coordinate system [m/s^2]
double ax=0.0,ay=0.0,az=0.0; // acceleration [m/s^2]
double vx=0.0,vy=0.0,vz=0.0; // velocity [m/s]
double x=0.0, y=0.0, z=0.0; // position [m]
double dev[9]; // actual device transform matrix ... local coordinate system
(x,y,z) <- GPS position;
// iteration inside some timer (dt [seconds] period) ...
dev <- compass direction
ax,ay,az = accelerometer values (measured in device space)
(ax,ay,az) = dev*(ax,ay,az); // transform acceleration from device space to global map space without any translation to preserve vector magnitude
ax-=gx; // [edit1] remove background gravity (in map coordinate system)
ay-=gy;
az-=gz;
vx+=ax*dt; // update speed (in map coordinate system)
vy+=ay*dt;
vz+=az*dt;
x+=vx*dt; // update position (in map coordinate system)
y+=vy*dt;
z+=vz*dt;gx,gy,gz
is the global gravity vector (~9.81 m/s^2
on Earth)- in code my global
Y
axis points up so thegy=-9.81
and the rest are0.0
measure timings are critical
Accelerometer must be checked as often as possible (second is a very long time). I recommend not to use timer period bigger than 10 ms to preserve accuracy also time to time you should override calculated position with GPS value. Compass direction can be checked less often but with proper filtration
compass is not correct all the time
Compass values should be filtered for some peak values. Sometimes it read bad values and also can be off by electro-magnetic polution or metal enviroment. In that case the direction can be checked by GPS during movement and some corrections can be made. For example chech GPS every minute and compare GPS direction with compass and if it is constantly of by some angle then add it or substract it.
why do simple computations on server ???
Hate on-line waste of traffic. Yes you can log data on server (but still i think file on device will be better) but why to heck limit position functionality by internet connection ??? not to mention the delays ...
[Edit 1] additional notes
Edited the code above a little. The orientation must be as precise as it can be to minimize cumulative errors.
Gyros would be better than compass (or even better use them both). Acceleration should be filtered. Some low pass filtering should be OK. After gravity removal I would limit ax,ay,az to usable values and throw away too small values. If near low speed also do full stop (if it is not a train or motion in vacuum). That should lower the drift but increase other errors so an compromise has to be found between them.
Add calibration on the fly. When filtered acceleration = 9.81
or very close to it then the device is probably stand still (unless its a flying machine). Orientation/direction can be corrected by actual gravity direction.
See if the user looks at a GPS position
As per your question, in your case GPS receiver is only collecting absolute location with margin (inaccurate) of 3-10 meter depending on your receiver type.
When your device returns the location of latitude and longitude, it does not know your orientation, if we assume you only use GPS, then the only way to calculate orientation is by movement the receiver (movement mean walking for while constantly).
To get your orientation typically using Magnetic Compass and/or Gyroscopes build in your device.
There are no final rules how to use this or that, what you need to do is to find out what is your requirement and make some tests to find the best results.
One disadvantage of using GPS constantly, is that it is power consuming (it drain the battery) so you need to make a strategy of combining differing sensors and turn on/off GPS programmatically to collecting data periodically.
And make algorithm logic to give the user the orientation regarding to the position.
I have provided some useful links:
- https://www.geolounge.com/absolute-relative-location/
- https://www.quora.com/Sensors/What-is-the-difference-between-accelerometers-gyroscopes-and-magnetometers
- http://www.explainthatstuff.com/howgpsworks.html
- http://www.tracklogs.co.uk/cgi-bin/publ/user.cgi?obj=support&mod=kbase&view=15885925
- How do I programmatically find direction on a blackberry?
GPS/GIS Calculations: Algorithm to predict future position based on movement/mph?
Here is the complete parametric answer :
variables :
heading
: heading (i.e. backwards angle from azimuth 0°, in degrees)speed
: velocity (i.e. norm of the speed vector, in miles/hour)lat0
,lon0
: initial coordinates in degreesdtime
: time interval from the start position, in secondslat
,lon
: predicted coordinates in degreespi
: the pi constant (3.14159...)Rt
: Earth radius in miles (6378137.0 meters which makes 3964.037911746 miles)
In an (East, North) local frame, the position after the time interval is :
x = speed * sin(heading*pi/180) * dtime / 3600;
y = speed * cos(heading*pi/180) * dtime / 3600;
(with coordinates in miles)
From there you can compute the new position in the WGS84 frame (i.e. latitude and longitude) :
lat = lat0 + 180 / pi * y / Rt;
lon = lon0 + 180 / pi / sin(lat0*pi/180) * x / Rt;
Edit : corrected the last line : *sin(phi) to /sin(phi)
The angle of direction without using GPS
If your device is fixed relative to the car, you can extrapolate your coordinates after the last known fix using the previous known speed and input from the magnetometer.
As you updated your question, if the device is not fixed then it's more difficult. You'd have to use some some sensor fusion algorithm that could adjust the speed calculation based on the accelerometer and gyro inputs, and (have a look at how Kalman filters work for example).
The information from that algorithm could be correlated with previous GPS fixes in order to estimate the position of the device in relation to the car (think about what the magnetometer would read during, let's say, a right turn on the road if the phone is in the left pocket vs. if it's in the right pocket). Unfortunately, you don't have the comfort of knowing that the phone is always pointing straight forward through the windshield.
Related Topics
Deserializing Json Data to C# Using Json.Net
If Async-Await Doesn't Create Any Additional Threads, Then How Does It Make Applications Responsive
How to Increase the Max Upload File Size in Asp.Net
Difference Between Shadowing and Overriding in C#
Find Control by Name from Windows Forms Controls
How to Get the Cpu Usage in C#
Is There Any Significant Difference Between Using If/Else and Switch-Case in C#
How to Handle Accessviolationexception
A Generic Error Occurred in Gdi+, Jpeg Image to Memorystream
How to Specify a Custom Location to "Search For Views" in ASP.NET MVC
How to Split CSV Whose Columns May Contain ,
C# Data Connections Best Practice
How to Easily Convert Datareader to List≪T≫
How to Truncate Milliseconds Off of a .Net Datetime
Calculate the Number of Business Days Between Two Dates
How to Get Httpcontext.Current in ASP.NET Core