I would like to develop a personal app for this i need to detect my car's rotation.
In a previous thread i got an answert to which sensors are good for that it's okay.
Now i would like to ask you to please summerize the essential/needed mathematical relationship.
What i would like to see in my app:
- The car rotation in degrees
- The car actual speed (in general this app will be used in slow speed situation like 3-5km/h)
I think the harder part of this is the rotation detect in real time. It will be good to the app could work when i place the phone in a car holder in landscape or portrait mode.
So please summerize me which equations,formulas,realtionships are needed to calculate the car rotation. And please tell me your recomendation to which motion/position sensor are best for this purpuse (gravity,accelerometer,gyro,..)
First i thought that i will use Android 2.2 for better compatibility with my phones but for me 2.3.3 is okay too. In this case i can use TYPE_ROTATION_VECTOR which looks like a good thing but i don't really know that it can be a useful for me or not?
I don't want full source codes i would like to develop it myself but i need to know where can i start, what deep math knowlegde needed and what part of math are needed. And for sensor question: i'am a bit confused there are many sensors which are possible ok for me.
Thanks,
There is no deep math that you need. You should use TYPE_MAGNETIC_FIELD and TYPE_GRAVITY if it is available. Otherwise use TYPE_ACCELEROMETER but you need to filter the accelerometer values using Kalman filter or low pass filter. You should use the direction of the back camera as the reference. This direction is the azimuth returned by calling getOrientation, but before calling getOrientation you need to call remapCoordinateSystem(inR, AXIS_X, AXIS_Z, outR) to get the correct azimuth. Then along as the device is not laying flat, it does not matter what the device orientation is (landscape or portrait). Just make sure that the phone screen is facing the opposite direction of the car direction.
Now declare two class members startDirection and endDirection. In the beginning, startDirection and endDirection have the same values, now if the azimuth change by more than say 3 degrees, there is always a little fluctuation, then change the endDirection to this value and continue to change until say 20 returned azimuth have the same values (you have to experiment with this number). This mean that the car stop turning and then you calculate the difference between startDirection and endDirection, this gives you the degree of rotation. Now set startDirection and endDirection to this new azimuth and wait for next turn.
Related
I am working on an application which uses compass although I successfully implemented it but there is no such brief explanation that how it works. Like how the TYPE_ACCELEROMETER and TYPE_MAGNETIC_FIELD was used to get the orientation. I know we did get it and the zero index of the array we got is the azimuth from which we get the degree and came to know where north is. But how it get to this all. Can anyone explain please?
Secondly what if I place my mobile on the floor suppose it points in the direction of north when it is placed on ground now I take up my mobile and hold I upside down what will happen and why?
According to my understanding the direction shouldn't changed. I might be wrong, can anyone please guide to me on this. Thanks a lot.
You need both the Magnectic field and Accelerometer to calculate the compass direction. You can see why if you read the source code of the getRotationMatrix or for a more verbose explanation see Convert magnetic field X, Y, Z values from device into global reference frame
If you stand at the same place, the magnetic field does not change. That is the magnetic field vector returned in onSensorChanged should change very little. It is not the vector that change but the coordinates of the device that change. It is the meaning of what is being calculate and call the "compass direction" that confuses you. In this case the direction to be used as the "compass direction" is the direction of the y coordinate. Thus when you hold the phone vertically, the y coordinate points to the sky or the ground and it does not make sense to talk about "compass direction"
I'm taking a free online Android course, and this is the example code he uses to make a simple compass, you can look at that: https://github.com/aporter/coursera-android/tree/master/Examples/SensorCompass.
The way is works is that the phone senses the strongest "north" magnetic field, and points the arrow north, and then when the accelerometer moves, it changes the arrow according to that.
Also, if you hold the phone vertically above your head, the display will not be pointing north because the phone is not parallel to the ground.
Which sensor is needed to make an app where an arrow on the display is always pointing to the ground?
My app is always in landscape. Ive tried to use the Orientation sensor but it only works if Im holding my smartphone in portrait mode. The more I move my device to landscape values become instable und doesnt point to the ground anymore.
To be more specific, in portrait mode I can use y-axis (roll) to find out the angle, but the more Im rotating my device to landscape mode it doesnt work anymore with the y-axis.
Maybe its the wrong sensor or its a question of some trigonometry functions?
Any ideas? Please help me.
Ive found the solution.
The problem described is also known as Gimbbal Lock.
See here and here.
For me the solution can be found here and is the trivial sentence:
Using the camera (Y axis along the camera's axis) for an augmented
reality application where the rotation angles are needed:
remapCoordinateSystem(inR, AXIS_X, AXIS_Z, outR);
This way I can do what I want to do because the Gimbbal Lock is lying in a position where it doesnt argue me.
I'm trying to detect the direction of motion of an android device using the accelerometer. I've removed the gravity components from the accelerometer output values and deducted the angles.
So I am able to get the direction of motion but I also get arbitrary angles momentarily. Like when I stop moving the device.
Any suggestions how I could filter those angles out?
EDIT: I've somewhat been able to solve this by taking the mean of the current and past values.
Another problem that persists is that initially for a few moments, the accelerometer reports values in the opposite direction of motion.
That's a typical trouble with accelerometers... Initially there's no any solution because of the inertia, etc... But You can try using some kind of "integer controller".
Another possible solution is detecting abrupt changes on the acceleration and interpret them as changes of direction, I mean, for example if you have the acceleration on the X edge (Ax).
while(1){
Ax = readAx();
if(changeSign(Ax)){ //From + to - or - to +.
//Do what ever you need, for example if sign is changed and keep on it then is that the mobilephone is been moved in the other direction. Else if it's acceleration is close to 0 it means that the device has stopped
}else{
//The device keep moving on the same direction.
}
}
Feel free to be creative. There are many ways to manage a solution depends on your target.
I hope it helps.
I am getting start sensor. I want to know which sensor in android will help me. and how? If I want to know when my phone moves like this.. Anim Video .
Can any one please help me?
You need Acceleration sensor and Orientation sensor as well to accuratelly recognize the move described in your video.
So, I would recommend to collect the data from mentioned sensors and describe movement (acceleration and orientation should have separate 3D functions) with few mathematical functions/graphs. Then , within certain accuracy, check whether repeated move matches expected behaviour on all axis.
You will need this for reference on the axis:
http://developer.android.com/reference/android/hardware/SensorEvent.html
Looks like no change (or very small) should occur on Y-axis to describe move from your video.
I've been playing around with the Android Accelerometer of late using the Android SDK and the Adobe AIR for Android SDK on my Motorola Droid. What I've noticed is that the accelerometer works just fine, but I was wondering if it is possible to compensate in some fashion so that I don't have to use the device in a horizontal position. In other words, I want to use the accelerometer to control my visual display, but initialize it(or modify in some way) so that I don't have to hold it perfectly flat (not much fun having to lean over the phone).
Does anyone know how I can hold the device comfortably in my hand, say 45 degrees, and still utilize the accelerometer to provide forward/backwards readings? Is this possible? Any examples of this this available?
You'll need some simple matrix multiplication math for that. "Calibrate" the rotation by taking the current matrix when you start the app and invert it, then multiply all subsequent matrices with it - that will give you the delta to the starting position.
I had written an application long long ago which dealt with relative rotations. I've forgotten what the code did, but from what I can see, it seems like -
1) I get the initial rotation matrix using - SensorManager.getRotationMatrix(R, I, gravity.clone(), geomagnetic.clone()); (gravity and geomagnetic are the respective accleration and geomagnetic matrices. Dunno why I use clones but there must be some reason.)
2) Now at any stage, get the current rotation matrix and call it R.
3)Calculate the inverse of the initial matrix and call it "initialInverse".
4)Multiply R with initialInverse (or the other way round, you'll have to figure it out).
5) Get your final orientation using SensorManager.getOrientation(delta, values)
I'm sorry but I've totally forgotten what the above code does. I think I remember reading the words Euler Transform somewhere when I wrote this app, so thats what it might be doing. Unfortunately I cannot give you the complete code since I'll probably release this app in the market. However, if you need some more information, please let me know - I'll look into the code and get back to you.
I am working in a project with similar nature where the accelerometer function is not restricted by the position. My way of handling it is very simple, initialize the accelerometer with the current reading as the default. In other words, you have a button that you press once you have the phone in the proper position, upon pressing the button, the current readings of the accelerometer (measures of G) will be your reference (zero values), and make changes when you go above or below those readings... Hope this helps anyone... cheers