A while ago I got a question if 3-level expandable list views can be
implemented in Android. Android does not explicitly support it but the
flexibility of Android UI widget framework provides a relatively simple
implementation option: second-level expandable list views are to be
inserted into the first-level expandable list view as child views. There was a blog post with an example program and
everybody was happy. Even then I made a note that I don't agree with
the approach from the UI point of view because the display becomes
unnecessarily messy.
Now there was a comment at that blog post whether 4-level lists are
possible. Of course they are possible, it is just not a good UI design.
But I guess, you better try it yourself if you don't believe me. The
principle is the same (expandable lists embedded as children of
higher-level expandable lists), it is just much more complex to make
sure that everything is recalculated correctly for every event. In
order to follow the operation, I left a good amount of debugging code
in the project.
Click here to access the example program.
Tuesday, March 27, 2012
Saturday, March 10, 2012
Example application for accelerometer/compass processing on Android
I hope you are well prepared by now what you can expect from the compass-accelerometer sensor fusion - if not, please read my thoughts about the limitations. This time we are going to see, how to compensate the accelerometer with the compass.
The idea is very simple. The accelerometer and the compass both measure vectors fixed to the Earth. These vectors are different - gravity and ambient magnetic field - but we hope that their angle is constant because they are both fixed to the same coordinate system. But while the accelerometer is sensitive to the motion acceleration, the compass is not. If we manage to rotate and scale the magnetic field vector into the gravity vector, we have a reference while the accelerometer is subject to motion acceleration and we can extract the motion acceleration. Plus, we have a reliable gravity vector and an "in motion" indication.
So the process is the following:
The steps are:
Let's see the example Android program then that implements all this!
Click here to read the post further.
The idea is very simple. The accelerometer and the compass both measure vectors fixed to the Earth. These vectors are different - gravity and ambient magnetic field - but we hope that their angle is constant because they are both fixed to the same coordinate system. But while the accelerometer is sensitive to the motion acceleration, the compass is not. If we manage to rotate and scale the magnetic field vector into the gravity vector, we have a reference while the accelerometer is subject to motion acceleration and we can extract the motion acceleration. Plus, we have a reliable gravity vector and an "in motion" indication.
So the process is the following:
- Calibrate the compass to the location and figure out the offsets we discussed in the limitation part. Also measure the reference gravity vector length.
- If we find that the acceleration vector's length is close enough
to the reference gravity vector length, we assume that this means "no
motion" (see the discussion of this issue here). Find then the rotation axis and angle to rotate the compass
vector into the acceleration vector. We call these values reference
rotation axis, reference rotation angle, reference magnetic vector and
reference acceleration vector, respectively. Keep updating these values
as long as we are in "no motion" state.
- If we find, that the acceleration vector's length is significantly shorter or longer than the reference gravity vector length, we are in "motion" state. Then we use the previously recorded reference values and the actual magnetic field value measured by the compass to calculate a simulated gravity vector. Using the measured acceleration vector and the simulated gravity vector, we extract the motion acceleration vector.
The steps are:
- Calculate the rotation operation that rotates the reference
magnetic vector to the reference acceleration vector. The rotation
operation has two components: an axis around which one vector is
rotated to the other and a rotation angle. The rotation axis is the vector cross product of the two vectors. The angle can be obtained by resolving the equation of two different representations of the two vectors' dot product. This yields reference rotation axis and reference rotation angle.
- The reference rotation axis nicely rotates the reference magnetic vector to the reference acceleration vector but we need to apply the rotation to the current magnetic vector. We need a new rotation axis for this and we obtain it by rotating the reference rotation axis by the rotation operation that rotates reference magnetic vector to the current magnetic vector. This yields a current rotation axis.
- Then we simply rotate the current magnetic vector around the current rotation axis with the reference rotation angle. This yields a simulated gravity vector. We also have to scale this vector so that its length is equal to the reference gravity.
Let's see the example Android program then that implements all this!
Click here to read the post further.
Saturday, March 3, 2012
PHONE_STATE broadcast and 4.0.3
Anybody out there who has experience with android.intent.action.PHONE_STATE broadcasts and 4.0.3? I wrote this simple application that is just a receiver for this broadcast intent. It works beautifully on 2.2 but does not capture any broadcasts on a Nexus S with the official Google 4.0.3 firmware. The manifest has the permission (XML mangling because of the blog engine):
[uses-permission android:name="android.permission.READ_PHONE_STATE"/]
and the receiver:
Is this a 4.0.3 bug?
[uses-permission android:name="android.permission.READ_PHONE_STATE"/]
and the receiver:
[receiver android:name=".PhoneIntentReceiver"
android:enabled="true"
android:exported="true"]
[intent-filter]
[action android:name="android.intent.action.PHONE_STATE" /]
[/intent-filter]
android:enabled="true"
android:exported="true"]
[intent-filter]
[action android:name="android.intent.action.PHONE_STATE" /]
[/intent-filter]
[/receiver]
Is this a 4.0.3 bug?
Thursday, March 1, 2012
Compensating accelerometer with the compass - the limitations
In the previous parts of our sensor processing series,
we have seen how to use the gyroscope to separate the motion and the
gravity acceleration components measured by the accelerometer. But
gyroscope-equipped phones are rare. Can we have a "poor man's gyroscope"
that is more widely deployed in today's devices?
Let's reiterate the problem. We have an accelerometer that is exposed to two main kinds of accelerations: gravity and motion acceleration. Gravity acceleration is always present. Sadly, its direction is not constant but changes with the direction of the device. If the device is subject to motion acceleration (e.g. the user is walking), motion acceleration is added to the gravity component. Motion acceleration vector changes dynamically due to the movement phases. If we have to assume that motion acceleration is present but we don't know the gravity acceleration vector, separating the gravity and motion acceleration components is impossible. We need another sensor therefore and we made a good use of the gyroscope so far.
The other evident sensor that can be used to determine the Earth's coordinate system relative to the device coordinate system is the compass or magnetic sensor. Compass is attractive because it is widely available in today's devices. Unfortunately it has certain drawbacks that make it more inconvenient to support the accelerometer than gyroscope. In this part I will go through the characteristics of the compass to set the expectations before we start to discuss, how to use it together with the accelerometer.
First the basics. The compass measures the magnetic field the device is exposed to. This magnetic field has many components. We are most interested in the Earth's magnetic field but obviously there are other disturbances, e.g. metal objects, magnets, magnetic fields generated by electric devices. The Earth's magnetic field is not trivial either. Contrary to a belief I hear often, the Earth's magnetic field points mostly downward, toward the center of the Earth. The effect is called magnetic inclination and it means that the Earth's magnetic field has a varying degree relative to the Earth's surface. Where I live, the inclination is about 70 degrees. The component that compasses measure to find the "North" (more exactly: magnetic North) is just the x and y components of the magnetic field which are smaller than the z component.
External magnetic fields can make measuring the Earth's magnetic field virtually impossible. The graph below shows an extreme case when I started compass sampling and walked into an underground train that eventually left the station.
Click here to read the post further.
Let's reiterate the problem. We have an accelerometer that is exposed to two main kinds of accelerations: gravity and motion acceleration. Gravity acceleration is always present. Sadly, its direction is not constant but changes with the direction of the device. If the device is subject to motion acceleration (e.g. the user is walking), motion acceleration is added to the gravity component. Motion acceleration vector changes dynamically due to the movement phases. If we have to assume that motion acceleration is present but we don't know the gravity acceleration vector, separating the gravity and motion acceleration components is impossible. We need another sensor therefore and we made a good use of the gyroscope so far.
The other evident sensor that can be used to determine the Earth's coordinate system relative to the device coordinate system is the compass or magnetic sensor. Compass is attractive because it is widely available in today's devices. Unfortunately it has certain drawbacks that make it more inconvenient to support the accelerometer than gyroscope. In this part I will go through the characteristics of the compass to set the expectations before we start to discuss, how to use it together with the accelerometer.
First the basics. The compass measures the magnetic field the device is exposed to. This magnetic field has many components. We are most interested in the Earth's magnetic field but obviously there are other disturbances, e.g. metal objects, magnets, magnetic fields generated by electric devices. The Earth's magnetic field is not trivial either. Contrary to a belief I hear often, the Earth's magnetic field points mostly downward, toward the center of the Earth. The effect is called magnetic inclination and it means that the Earth's magnetic field has a varying degree relative to the Earth's surface. Where I live, the inclination is about 70 degrees. The component that compasses measure to find the "North" (more exactly: magnetic North) is just the x and y components of the magnetic field which are smaller than the z component.
External magnetic fields can make measuring the Earth's magnetic field virtually impossible. The graph below shows an extreme case when I started compass sampling and walked into an underground train that eventually left the station.
Click here to read the post further.
Subscribe to:
Posts (Atom)



