I want to detect the movement of the hand dynamically and modify sound accordingly. The phone is in the hand in a fixed orientation which does not change. For Example, I am holding the phone in my stretched hand and as it moves to the right or left, my music volume changes dynamically; If I move up and down the speed of playing changes and moving at some intermediate angle changes both speed and volume accordingly. I charted the accelerometer data while doing these motions and there seems to be some pattern but I am not sure how to filter those. I have looked at a lot of posts - High Pass/Low Pass filters, Kalman Filters, Gesture Recognizers but it is difficult to understand what is the appropriate method. Most of the posts don't seem to detect dynamically - but only when a certain gesture is finished. I only need to use accelerometer and not gyroscope and any other sensor. What is the correct approach here? Are there any existing libraries that do this?
if your activity implements
SensorEventListener
and you use the variables
private SensorManager sensorManager;
private Sensor mAccelerometer;
in your OnCreate() you instantiate them and register the listener like this:
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
mAccelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
sensorManager.registerListener(this, mAccelerometer,
SensorManager.SENSOR_DELAY_FASTEST);
and then use this method to get the accelerometer data
public void onSensorChanged(SensorEvent event) {
double x = event.values[0];
double y = event.values[1];
double z = event.values[2];
}
and you can take it from there depending on the values you get from the accelerometer, make the changes to the volume or whatever
Related
I am doing a demo in which when I move device like on top-left, top-right,top-center and bottom-right, bottom-left, bottom-center, center-right, center-left this type of movement I need to detect so that I am looking for accelerometer and gyroscope sensor. Am I going on the right track or not?
Do you have any demo or any link?
Yes accelerometer would be a good option to detect the motion of the phone
You need to override the onSensorChange even in your activity in order to detect accelerometer values.
public void onSensorChange(SensorEvent sensorEvent) {
Sensor mySensor = sensorEvent.sensor;
if (mySensor.getType() == Sensor.TYPE_ACCELEROMETER) {
float x = sensorEvent.values[0];
float y = sensorEvent.values[1];
float z = sensorEvent.values[2];
}
}
Get started from here
Sensors Overview
Using the Accelerometer on Android
SensorManager
Also check out this page for a collection of android sensors library.
I'm working on an Android device which does not have a Magnetometer but has a Rotation Sensor (Gyro) and Gravity Sensor and GPS. I would like to determine True North / Azimuth from these sensors but can't figure out how. Without a Magnetometer, how do I determine the orientation of this device? Clearly somehow it knows where North is given the Maps app works just fine.
UPDATE:
You can the Rotation Vector Sensor that seems perfect for your situation.
private SensorManager mSensorManager;
private Sensor mSensor;
...
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR);
The system of coordinates you want is as follows:
X is defined as the vector product Y x Z. It is tangential to the ground at the device's current location and points approximately East.
Y is tangential to the ground at the device's current location and points toward the geomagnetic North Pole.
Z points toward the sky and is perpendicular to the ground plane.
Android makes a lot of sensors available
if you specifically wish to use the gyroscope (Sensor.TYPE_GYROSCOPE) you could do it like this (taken from the Google example):
private SensorManager mSensorManager;
private Sensor mSensor;
...
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
public void onSensorChanged(SensorEvent event) {
//...
}
but you could try and check if you can use a higher level API that will leverage more than one sensor
You should have a look at this simple example by JavaCodeGeeks where they leverage the default Sensor.TYPE_ORIENTATION to build an android compass
Just a little more info on the Sensor.TYPE_ORIENTATION. According to Google you can still use device orientation, but by calling getOrientation() instead of acting directly over the sensor.
Instead of using raw data from the orientation sensor, we recommend
that you use the getRotationMatrix() method in conjunction with the
getOrientation() method to compute orientation values, as shown in the
following code sample. As part of this process, you can use the
remapCoordinateSystem() method to translate the orientation values to
your application's frame of reference.
The bad news is that both getOrientation() and the old Sensor.TYPE_ORIENTATION rely at least partially on the magnetometer
Hope this helps!
Hi I am creating an application in which the user holds the phone upright and then rotates it around the y axis (similar to taking a panorama).
(source: apple.com)
I need to detect the angle of rotation. In iOS this was fairly simple with the gyroscope sensor, but I am not finding the same luck with Android. If anyone could point me in the right direction that would be great.
Assuming your Y axis points to the center of earth, the value you are looking for is called azimuth.
To monitor its change you will need to register a listener for TYPE_ACCELEROMETER and TYPE_MAGNETIC_FIELD events:
mngr = (SensorManager)getSystemService(Context.SENSOR_SERVICE);
accelerometer = mngr.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
magneticField = mngr.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
int rate = SensorManager.SENSOR_DELAY_GAME; // or other
mngr.registerListener(sensorListener, accelerometer, rate);
mngr.registerListener(sensorListener, magneticField, rate);
And within the listener, call:
float[] values = new float[3];
SensorManager.getOrientation(R, values);
float current_azimuth_val = values[0]; // <----------
Note that the quality. and latency, if the data you will obtain is highly hardware dependent.
There are various sensors available that can be managed through a SensorManager. Of course, since every device decides whether or not to put a particular sensor on the hardware platform for their model you have to check whether one exists. Some have gyro like iOS, some can be done with accelerometer and magnometer sensors in its place.
You can get started here: http://developer.android.com/guide/topics/sensors/sensors_overview.html
I am developing an AR application on Android and would like to to, regardless of device roll orientation get horizontal and vertical values, much like a spirit level. An example would be a user holds their device in portrait mode and spins their phone, I would like the horizon on the phone to match the natural horizon. I have played with the roll value returned from the sensor manager but it seems to take pitch into account (ie. the device is now in landscape mode, what should be pitch affects roll.)
Also, when reading pitch, I would like the horizon to move up and down, regardless of roll. At the moment, when the device has rolled to 90 degrees, any pitch changes move in the horizontal direction rather than the vertical direction.
Any pointers?
Thanks in advance.
Paul
Yeah, I think your best bet, which I understand has it's flaws is using the accelerometers to determine the direction of the ground.
Use something like this....
mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
accelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
in your onCreate method, then put this
mSensorManager.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_NORMAL);
in your onResume
and this to handle the updates
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
float xAcceleration = event.values[0];
float yAcceleration = event.values[1];
float zAcceleration = event.values[2];
Then, just use those Acceleration values to determine the direction of the ground. :-)
I find that way is a lot more fluid, I hope that helps. :-)
For more info, check out the following for more info:
http://developer.android.com/reference/android/hardware/SensorEvent.html#values
I'm making my first Android application. As a toy problem to learn the system I want to make a simple app that display as text which direction the phone is pointing using the built in compass.
How do I access the compass from my code, and have my code be aware of direction changes?
I believe I'll need the SensorManager class but I'm confused how to use it. How do I tell it I want the compass sensor? How do I tell it to do an action (update text) on a direction change?
// First, get an instance of the SensorManager
SensorManager sMan = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
// Second, get the sensor you're interested in
Sensor magnetField = sMan.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
// Third, implement a SensorEventListener class
SensorEventListener magnetListener = new SensorEventListener() {
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// do things if you're interested in accuracy changes
}
public void onSensorChanged(SensorEvent event) {
// implement what you want to do here
}
};
// Finally, register your listener
sMan.registerListener(magnetListener, magnetField, SensorManager.SENSOR_DELAY_NORMAL);
However, please note that this is actually a magnetic sensor; therefore if you have magnetic interference around you, it may be pointing to the wrong direction. Also, you need to know the difference between True North and Magnetic North. Since this code uses magnetic sensor, you obtain the Magnetic North, but if you need to calculate the True North, you would need to do some adjustments with GeomagneticField.getDeclination().
Have a look at the API demos. There is an application that has already been written which access the compass and accelerometer. Maybe that will give you a better idea on how you can go about your task.
you shall find it in:
/android-sdk-linux_86/samples/android-8/ApiDemos/src/com/example/android/apis/os/sensor.java
hope it helps.
First you should check if a compass sensor is present on the system
PackageManager m = getPackageManager();
if(!m.hasSystemFeature(PackageManager.FEATURE_SENSOR_COMPASS)) {
Log.d("COMPASS_SENSOR", "Device has no compass");
}