I was trying to port Sebastian Madgwich's sensor fusion algorithm ( http://www.x-io.co.uk/node/8 ) to Android, but the first results seem not to be correct, and the resulting quaternion is moving everywhere when the phone is steady. One of the problem might be that I'm not able to sample at the same time the three sensors (gyro, accelerometer and magnetometer), but it looks like Android sensor manager doesn't allow to do so.
Did anybody succeeded in porting the algorithm with more success?
thanks in advance
I haven't implemented this in Android, but I have it working on an iPad 2 for an augmented reality application i'm working on for my MSc thesis. To get it working smoothly I found that it's best to set the update rate for the sensors inline with the frame rate (so, 30hz for me), but it's probably worth experimenting to see what's best for your device.
I'm not sure exactly what you mean by flying everywhere, but sensor drift will probably cause a noticeable amount of error - my objects slowly rotate randomly when the device is at rest. Very annoying, but something you have to accept when using IMUs.
Also, make sure you update the quaternion after you have a new reading from all of the sensors, instead of ofter each sensor gets a new reading separately.
Related
I've been doing a bit of research on a problem we are trying to solve. I think this is the best approach but please add in your opinions
We are trying to calculate reaction times in a real world driving scenario and would like to use a mobile phone as the data collection device. What we are trying to accomplish is how much acceleration and more importantly deceleration a driver exerts when exposed to certain prompts.
I found this paper that has allot of useful information Accelerometer physics
The problem is that we most likely will not have a calibration time to start at zero.. however it is assumed that the driver is starting at 0. We will use GPS positioning to locate the vehicle, tracking the time stamped location data we should calculate the time when the prompt took place then using the time stamped accelerometer data we should be able to calculate their reaction to the prompt.
This is the best way I have found to solve the problem however I'm not sure if the accelerometer data will be rendered useless because of not being able to calibrate it and also the noise seen from vibrations may be too great to use the data... Has anyone tried or used these types of methods before?
Interesting application.
You are missing an important point. You either have to implement the so-called sensor fusion yourself or use the sensor fusion provided on the platform you are using. Both Android and iPhone have one.
The TYPE_LINEAR_ACCELERATION (Android, SensorManager) or userAcceleration (iPhone) should be sufficient for you.
As for the linked PDF, don't try integrating the acceleration, you will get very poor results. Even though that answer is about position, the velocity will already be inaccurate. I would try the GPS instead.
I know it's very old question but since I am recently working on a similar project let me share what we did in our company. We simply used OBD-II dongle to get velocity of car. There are many API's that return information about vehicle.
PID010D returns speed of vehicle. I'm using this PID to calculate distance between points A and B since there is no PID to return Odometer :(
There are few libraries on github that you can find easily by search. This mine. This is not library but after run on your device you can see how it works.
I've been doing a bit of research on a problem we are trying to solve. I think this is the best approach but please add in your opinions
We are trying to calculate reaction times in a real world driving scenario and would like to use a mobile phone as the data collection device. What we are trying to accomplish is how much acceleration and more importantly deceleration a driver exerts when exposed to certain prompts.
I found this paper that has allot of useful information Accelerometer physics
The problem is that we most likely will not have a calibration time to start at zero.. however it is assumed that the driver is starting at 0. We will use GPS positioning to locate the vehicle, tracking the time stamped location data we should calculate the time when the prompt took place then using the time stamped accelerometer data we should be able to calculate their reaction to the prompt.
This is the best way I have found to solve the problem however I'm not sure if the accelerometer data will be rendered useless because of not being able to calibrate it and also the noise seen from vibrations may be too great to use the data... Has anyone tried or used these types of methods before?
Interesting application.
You are missing an important point. You either have to implement the so-called sensor fusion yourself or use the sensor fusion provided on the platform you are using. Both Android and iPhone have one.
The TYPE_LINEAR_ACCELERATION (Android, SensorManager) or userAcceleration (iPhone) should be sufficient for you.
As for the linked PDF, don't try integrating the acceleration, you will get very poor results. Even though that answer is about position, the velocity will already be inaccurate. I would try the GPS instead.
I know it's very old question but since I am recently working on a similar project let me share what we did in our company. We simply used OBD-II dongle to get velocity of car. There are many API's that return information about vehicle.
PID010D returns speed of vehicle. I'm using this PID to calculate distance between points A and B since there is no PID to return Odometer :(
There are few libraries on github that you can find easily by search. This mine. This is not library but after run on your device you can see how it works.
I'm working with android sensor data. My application use
SensorManager.getRotationMatrixFromVector(
mRotationMatrix , event.values);
and it has been working well until this morning, when the rotation matrix started to send a lot of noise data (Change N to W in a second).
It's not a problem with my code, because on friday was working and no changes have been done. I have used a compass app from the market, and the compass is giving random data.
I have tested my app on another tablet, and it is working well.
Does someone know why is this happening? A problem with the sensor? Does it need a calibration?
I've worked quite a lot with these electronic compasses on mobile phones and its quite possible that there is nothing wrong with your code or sensor.
Instead it could very well be a problem with your environment. There are magnetic fields interfering with the earth's magnetic fields all the time. From electrical equipment interference to the metal structure holding up a building. At the end of the day a compass is just a magnet. If you stand beside a large lump of metal the compass will be attracted to it and point to it rather than the magnetic north pole.
Try this:
Install GPS status
then turn off all filtering (settings... gps & sensors...sensor filtering... no filtering).
Do the calibration (figure of 8 wavy stuff) and then move the phone around your desk.. near monitors, cables, etc. You'll see it go crazy. The information is completely unreliable. I found in the past that moving the phone a few inches to the right completely changed its reading. The same happens with a real compass. Strictly speaking there is no "problem". The device's compass is assigning itself with the strongest magnetic field. Even the magnetic content of nearby rocks can interfere with the compass.
As a further test I've just placed a real (orienteering) compass over my phone which has a compass app installed. The real compass is now pointing everywhere but magnetic North. The two devices are interfering with each other.
So my advice is.. go somewhere in the open, like a park or field, away from any potential interference and power lines, (if you have one bring a real compass to check that the GPS status app is pointing the right way), and see if your compass works as you'd expect.
Extra: The answer from #resus is also important when calibrating. Rotate the phone a few times in each axis. Looks silly but it does calibrate it properly.
Extra 2: Would it be possible/practical to use the compass bearing of your GPS? It would require that the device be moving (walking speed should be fine) but you would not need to worry about any interference. It should give an accurate reading provided your GPS signal is good.
Extra 3: Another thought just occurred to me.. You could try apply a low pass filter to the sensor. This means that the sudden changes in the sensor reading are filtered out .. have a look at this answer. And if that doesn't do a good job there are lots of algorithms on the web for you to choose from.
If you definitely haven't changed anything in your code, and it still works fine on other devices, it would suggest a problem with that particular device.
While your app is running (i.e. the compass is in use), you should be able to wave it in a figure of 8 in order to automatically recalibrate the compass. You should also make sure you aren't standing next to any large lumps of metal etc. that might interfere with readings.
You can override the onAccuracyChanged() method of SensorEventListener to flash up a message to the user when the compass requires recalibration (probably when accuracy drops to SENSOR_STATUS_ACCURACY_LOW).
In my experience of playing with the compass on android phones, they can be pretty unreliable...
If your application work on another tablet and other compass application do not work on your device, this is probably due to a bad calibration.
As said in the post above, to make the calibration, wave your device in a figure of 8. I just want to add that you should do it for EACH axis. This should fix your problem.
If it is not a calibration error, as some people have already answered, it is possible that the compass had gone through a magnetic field and now it is desmagnetized, so it is not working properly.
Where do you usually keep the tablet? Could it be that it was near big servers or magnets?
You should check the compass just in case, talk to to android's tech support.
Hope it helps.
I think the question was if calibration could be done without sending any data to compass. Because not everybody says that the compass is calibrated as shown in this video: https://support.google.com/maps/answer/6145351?hl=en and obviously you can not do anything else than advise the user to calibrate before using the program or when you get too much changes.
For example going left and right 90 degrees in about 25 ms.
Anyway I think it's good to give some seconds to the app before start taking data, because it gives some unstable values (too high and low in short time without movement) at the app loading moment.
Just let the handler onSensorChanged() coded with a conditional, and start a thread on the onCreate() handler, which will set a boolean to true, after some seconds.
Then you start to capture data on the onSensorChanged() handler.
Also this thread can help to detect the sensor accuracy, and then you can popup: In Android can I programmatically detect that the compass is not yet calibrated?
I know because I am building a robot using the compass of the smartphone, and I'm having this experience. So, if you are making a robot, make sure to give an spaced place between electronics and hardware to the smartphone, but remember that it's on any compass: electromagnetic fields can be altered by metals so heavily.
Nowadays I have the luck of developing a robot with an HMC-5983 and an MPU-6050, which can be calibrated by using its libraries with Arduino.
That code is compatible/portable to other uController but for not also so easy for smartphones, I guess that the offsets needed for calibrating the compass, the gyro and the accelerometer are inside some internals of Android, not available in the SDK.
I answered before thinking that maybe calibration was only for some devices, but realized that must be as I said before.
So, if playing with robots its possible, I mean it's also easy, but when using an smartphone maybe some custom firmware as CyanogenMod would bring the possibility of investigating the way of setting that offsets, but more important to run some program ported from sketch (following its concept only) to get them first ...
So, good luck ! What is also true, is that in both devices (smartphone and my robot) it's need to move them for them to get working well, as I showed you in the video of latest answer, also helpful on robots.
Good luck and a lot of fun with those things, are very powerful.
I've been researching for a bit now and now I have to decide which road to take.
Mine requirements: Need to know device's orientation relative to the true heading (geographic north pole, not magnetic pole).
For that I must use compass and now I have to decide which other thing, accelerometer or gyroscope.
Since this is a new thing to me I've spent last few hours reading stacks and wikipedia articles and still I am confused.
I am targeting both platforms (iOS and Android) and I am developing them with Appcelerator Titanium. With Titanium I can easily get accelerometer's values (x,y,z) and trueHeading.
Since iPhone 3GS does not have gyroscope obviously I can't use it on that device. Newer iPhones and Android devices have it.
So the questions are:
Is accelerometer's XYZ and compas's TrueHeading data enough for me to calculate device pitch, roll and yaw? But it has to be accurate.
Is it more accurate to use TrueHeading from compas and use gyroscope's values instead of accelerometer's?
Is it clever to combine both accelerometer and gyroscope with TrueHeading?
If I take the first road I don't have to write Titanium module for fetching the gyroscope data since it gives me only accelerometer data and I can use this on 3GS iPhone also.
If I take the second road I have to write two modules (iOS and Android) to fetch me gyroscope data and I lose 3GS support.
If I take the third road I again have to write Titanium modules and I lose 3GS support.
First of all if you don't have a huge installed base of 3GS users but write a new app, don't care about old hardware. IMO it doesn't make sense from an economical point of view but will shrink your number of alternatives in system architecture.
What you are looking for is called sensor fusion. Doing this consequently requires some heavy math like Kalman Filters etc. The good news is that it exists on iPhone (Core Motion) and AFAIK on Andriod as well (sounds like it is in Sensor fusion implemented on Android?).
I don't know much about appcelerator aside from the name and thus cannot say anything about an easy way to use it. Anyway if not implemtented on an abstract layer, I assume appcelerator provides you with the possibility to do native API calls. Thus you should be able to embed the native API (after fiddling around some time;-).
In general it depends on your requirements. The faster you need to have an exact result the more I'd recommend real sensor fusion including all 3 sensors. If you are fine with a slower response time, a combination of compass and accelerometer will do.
I'm making an application that works as a compass..
I'm using the accelerometer and the magnetic field sensors to compute the azimuth angle through, sensor.getOrientation().
I'm searching for something that can improve the magnetic field sensor accuracy, since I'm getting it state of accuracy as UNRELIABLE!
Any one knows anything about this?I'm looking for something that can be either hardcoded or for instance just physically moving the phone until it gets calibrated!
This is not a final answer (I don't know anything for sure), but my understanding from online posts is that waving the phone around in a figure of 8 a few times while the compass is in use is supposed to trigger automatic recalibration. This is what the google maps app suggests, for example. I don't know whether this is dependent on application functionality (something in maps that detects the waving by accelerometer and triggers a recalibration), or something in the android stack, or something specific to per-phone implementations. Try it and see!
Eg discussion: http://androidforums.com/epic-4g-support-troubleshooting/217317-cant-get-compass-calibrate.html
This reference appears to suggest this per-axis / figure-8 rotation process is built-in functionality: http://m.eclipsim.com/gpsstatus/
And here another article that claims this is built-in functionality, and that you don't even need to be running a compass-consuming app for the recalibration to work: http://www.ichimusai.org/2009/06/20/how-to-calibrate-the-htc-magic-compass/
Just a few points
The figure 8 motion works sometimes and not others, I have no idea why, they really need to have some kind of code based way to check if the 8 motion worked (Assuming that the physical motion is actually required)
They also need a way to detect that calibration is required, I looked at the code for the accuracy output (the unreliable constant) and once they send it to you they will not send it again, so for instance if you calibrate but then come within a strong magnetic field it will not resend (not sure why they did that)
One not completely reliable way to detect ongoing issues is that you can also use the magnetic sensor output and do something like field=sqrt(x*x+y*y+z*z) and check that field falls between say 25 and 65 and then ask the user to calibrate if it does not.
The bottom line after testing 18 phones is that I would never depend on a Android based compass with the current crop of phones, accuracy would always be in question.
I have also found even if you are lucky and have a fairly reliable phone you can never be sure that it's calibrated without checking it against a real compass, which kind of defeats the purpose.
NOTE: On a lot of the mis-behaving phones we have found that the sensor writes a calibration file and a tmp file with the same name. If you delete those files and re-boot the phones the calibration file is recreated with zero'd values and the cold start and general calibration problems resolve themselves.
The bad news is that they are stored in /data/misc and require root privileges to get at (thanks Google & Sensor mfg!) so even though I suspect this would solve a lot of problems for a lot of developers it just is not viable from a marketplace app perspective.
I am developing for Android. I'm using Titanium Alloy as development tool with the Titanium Geolocation module.
I have only tested 2 devices [Galaxy Note and S4] against a commercial magnetic compass. Following a calibration process [tilt along the 3 axis] and using 2 different compass apps and the app I'm working on, the Android compass seems accurate enough for basic use ... correlation was good enough for my purpose anyway. I also found the device compass reading to be very sensitive to other magnetic and electrical field interference ... initial mistake I made was to use the compass feature whilst device was in a device protector with a magnetic closure facility [quite common on tabs] ... this interference is particularly strong. I thus need to suggest to users of my app to remove device protectors, keep device free of other electronics and then do standard calibration before initializing the app.
Another option is:
Go To sensors menu: #*0#*
Then if you see a red line in Magnetic Sensor section and a Need for Calibration you should recalibrate your compass.
How;
According those guys;
Turn the Samsung Galaxy Mini S5 around all of its axes until the red
line in the black circle changes color from red to blue. You can also
run through a motion that follows the shape of an 8. It may be that
several attempts are needed to calibrate the compass...