Track user speed with CoreMotion without GPS - ios

I want to track user's position and update it in the offline map based on his movement without using GPS and having to rely on location updates.
I have tried CMMotionManager and got acceleration in G's. However, this is acceleration rather than valocity. The manager also allows to get gravity, rotation and attitude.
Is there a way to calculate the user's speed in m/s ? If so, how would I go about it? Any formulas / code samples?

The only way to do this is to assume that the phone is at rest when the app starts. With an accelerometer there's no way to tell the difference between being at rest and moving at a constant rate. For example if you were on a jet plane you'd have no way to tell that you were traveling at 800 kph and not sitting still.
If you do assume that you are at rest when you start it's possible to come up with very crude estimates of speed by tracking acceleration, but in practice, the results are prone to large amounts of "drift error", were small measurement errors quickly add up to a completely wrong current speed result, and so your position drifts around hopelessly.
So in practice, the answer to your question is "no, not really."
Edit:
Thinking about this a little more, you might be able to get usable results if you can impose some assumptions.
Say we assume that the user is on foot. We rule out traveling on a bike/in a car/train/plane. On foot, you really don't "drift". You move in fits and starts as the user takes steps. In fact, you could likely use the accelerometer to recognize the characteristic bounce of a person walking. There are pedometer apps that already do that. For walking, you could probably assume that in the absence of acceleration (ignoring gravity, which is constant), the phone is stationary, so zero out the speed and keep it at zero until there is an acceleration above a certain threshold. That would enable you to reduce drift error.

Related

Get distance from coreMotion data

I have an arduino controlling an led light strip, and an iphone connected to the arduino via bluetooth. so the number of lights that are turned on correspond to the phones position along an x axis
Is it possible to use the accelerometer to estimate the distance the phone has traveled. i'm currently polling the accelerometer at 0.01 second intervals. so in 0.5 seconds i'll have an array of 50 values. I believe each value represents the g force at the instance it was measured, so 1.0 = 9.8 meters/second. What would be the formula to take this array and the time interval to calculate the distance? Am i reinventing the wheel here? i feel like arKit has to use some kind of position tracking similar to this. Is there anything in coreMotion that could accomplish this for me.
Obligatory apology for not knowing what i'm doing. also similar questions have been asked before but they are >2 years old and the answer then was its possible but not accurate. i assume it could be more accurate now because arkit wouldn't work without doing something like
No, this isn't practical. The problem is drift. You can't tell if the phone is still or moving at a constant velocity, and the accelerometer isn't accurate enough to "zero out" the velocity of the phone. Minor errors in your calculations almost immediately swamp your results and you can't tell if the phone is sitting still or moving at a constant speed.
Acceleration is the second derivative of position. To start with acceleration you have to integrate twice, which will magnify errors.
To do this you could have two bluetooth sensors (one at each end of the bar) and use triangulation to calculate position. I haven't done this calculation myself to know all the details of it, but it's the same idea as those bluetooth tags you can have on a bunch of items to help you locate your keys, etc.

How do I 'fuse' together two different kinds of data to get a final result?

I am building a robot (2 powered wheels and one ball bearing). The problem is that I can't seem to make it drive straight. I literally find it impossible, I have been trying for weeks.
Currently I am able to rely on rotations (of both motors) or the gyro readings(I also have two gyros, each near the two tyres)
Is there a way I can fuse those together, giving me a more accurate way to determine which motor I need to speed up?
My motors accept a value from 0-900 (although the speed should be determined by me and not fixed). Also if an algorithm exists, I'd like some directions of what I'd need to swap if I make the motors go backwards.
The problem of the robot not going straight because the rotation speeds of the two motors might be different. E.g one might be completing 30 rotations per second and the other 31. Trivially this is solved using a wheel encoder. Using that you get the difference of rotation of two wheels and then change the motor speeds accordingly. Gyro can give you angular error per unit time, e.g if robot is moving 5 degree on the left after 2 seconds,then the right motor speed is to be decreased. But how much it needs to be decreased is not a trivial problem, because ultimately it happens because of hardware error. So what you can do is collect some data of the gyro angles, maybe 10 readings per second and analyze the data to find just how much you need to decrease the speed of one motor.

IMU Orientation constantly changing

We have XSENS MTi IMU-Device and use the ROS-Framework (Ubuntu / Fuerte).
We subscribe to the IMU-Data and all data looks good except orientation.
In Euler-Outputmode like in Quaternion-Outputmode the values are constantly changing. Not randomly, they increase or decrease slowly at a more or less constant rate, and sometimes I observed the change to flatten out and then change it's direction.
When the Value at Second X may be:
x: 7.79210457616
y: -6.58661204898
z: 41.2841955308
the Z value changes in a range of about 10 within a few seconds (10-20 seconds I think).
What can cause this behaviour? Do we misinterpret the data or is there something wrong with the driver? The strange thing is, this also happend with 2 other drivers, and one other IMU device (we have 2). Same results in each combination.
Feel free to ask for more precise data or whatever you'd like to know that may be able to help us out. We are participating at the Spacebot-Cup in November, so it would be quite a relief to get the IMU done. :)
Perfectly normal if you have no magnetometer to give a corrected heading.
Gyroscope alone measures rate of turn only, and has no idea of orientation at any given time on any axis. Integrating the rate of turn gives the heading if you know the initial heading and the gyro is 100% accurate. It drifts anyway, even if it's perfectly calibrated, as you are sampling at discrete intervals rather than continuously.
Adding an accelerometer will at least fix the downward direction (because it measures gravity, which is towards the Earth's centre). This will keep the Z axis solution aligned with vertical, but it won't fix the horizontal direction (the heading or yaw). That will continue to drift, as you are seeing.
Adding a magnetometer will fix the heading relative to the Earth's magnetic field. This will give you a heading relative to magnetic North. You will need to apply a shift for local magnetic declination to get True North. These are generally available on line and reasonably constant over tens of km. Google ITREF.
Some integrated sensors don't have a magnetometer. That's why the heading drifts. Units like the MPU6050 have firmware built in, and can access a magnetometer, but the usual firmware doesn't use it, so you have to implement Madgwick, etc., on your micro controller or a connected PC anyway. Bosch have a new single module with a processing unit built in. Hopefully, it uses 9 DOF rather than the 6 you get with the DMP on the MPU6050.
Magnetic sensors are accurate to about 2 degrees. Local magnetic declination corrections also have an error. You may be able to perform additional calibrations by using a GPS on a long base line to get better results. It's also worth noting that heading and course made good are often different, due to crosswind / cross currents.
The Madgwick algorithm is fairly stable and easy to implement, and uses fewer resources than a Kalman filter, which needs to perform matrix inversion. It still gives minor jitter, but minor smoothing of results shouldn't induce too much lag.
If you have the IMU version, I assume that no signal processing has been done on the device. (but I don't know the product). So the data you get for the orientation should be only the integral of the gyroscope data.
The drift you can see is normal and can come from the integration of the noise, a bad zero rate calibration, or the bias of the gyroscope.
To correct this drift, we usually use an AHRS or a VRU algorithm (depending the need of a corrected yaw). It's a fusion sensor algorithm which take the gravity from the accelerometer and the magnetometer data (for AHRS) to correct this drift.
The algorithms often used are the Kalman filter and the complementary filter (Madgwick/Mahony).
It's not an easy job and request a bit of reading and experimenting on matlab/python to configure these filters :)

Finding the cardinal direction accelerated with an Algorithm for using the magnetometer, accelerometer, and gyro readings

I want to find the cardinal direction accelerated by an iphone. I thought I could just use the accelerometer to do this, however, as you can see from the picture below the accelerometers axes are defined by the device orientation.
I figured that if i used the gyroscope to correct for yaw, spin, rotation then I could get a more accurate reading and not have to hold the phone in the same orientation during movement.
But this still does not tell me what cardinal direction the iphone is moving in. For that I would also have to use the the magnetometer.
Can anybody tell me how to use a three sensor readings to find the cardinal direction accelerated in? I dont even know where to start. I dont even know if the phone takes these measurements at the same rates of time either.
Taking the cross product of the magnetometer vector with the "down" vector will give you a horizontal magnetic east/west vector; from that, a second cross product gets the magnetic north/south vector. That's the easy part.
The harder problem is tracking the "down" vector effectively. If you integrate the accelerometers over time, you can filter out the motion of a hand-held mobile device, to get the persistent direction of gravity. Or, you could, if your device weren't rotating at the same time...
That's where the rate gyros come in: the gyros can let you compensate for the dynamic rotation of the hand-held device, so you can track your gravity in real-time. The classic way to do this is called a Kalman filter, which can integrate (both literally and figuratively) multiple data sources in order to evaluate the most likely state of your system.
A Kalman filter requires a mathematical model both of your physical system, and of the sensors that observe it; each of these models must be both accurate and "sufficiently linear" for the Kalman filter to work properly. As it happens, the iphone/accelerometer/gyro system is in fact sufficiently linear.
The Kalman filter uses both calculus and linear algebra, so if you're rolling your own, you will need a certain amount of math.
Also, as a practical matter, you should understand that physical sensors typically have offsets that need to be compensated for -- in particular, you need to pay attention to the rate gyro offsets in this kind of inertial navigation system, or your tracker will never stabilize. This means you will need to add your rate gyro offsets to your Kalman state vector and system model.

iOS Calculating the vertical movement distance of the device

I'm looking to create a function for my app which records the distance travelled in the vertical plane. More specifically, I want to record how far the device has been 'dropped' - this could mean dropped at arm's length onto the floor or dropped slowly with the user as they go down ten floors in an elevator. I'm looking for advice on the best way to calculate this with a relatively high level of accuracy.
I've read a little on the difficulty in accurately measuring distance travelled using core motion - especially as I need it to work even if the device rotates during the movement. From what I've researched it seems as though it would be impossible, or at least very difficult, to achieve this using core motion.
Would I be able to achieve this effect with Core Location instead? I've seen posts about calculating lateral distance, as in during a car journey, but nothing about vertical distance.
Is it as simple as 'startingAltitude - endingAltitude = distanceTravelled?
If so - how accurate is the altitude measurement of Core Location and how could I get started with this behaviour? I'm fairly new to iOS programming and would appreciate any pointers on the most appropriate method of achieving the function I want.
Thanks
There are serious limitations to both approaches.
Using an accelerometer to measure distance travelled requires very precise and accurate real-time measurement of acceleration. Any error in acceleration reading leads to error in your velocity calculation, which makes your location reading drift from the real location. Drift gets worse over time, to the point where the error swamps the actual location reading.
Based on my testing the altitude reading in iOS GPS devices is really bad. +/- 100 or more meters is not uncommon. Indoors GPS readings tend to get really bad, and the altitude reading is bad enough to start.

Resources