Thursday, April 12, 2012

3D transition animation between Activities

I have got a question in this post on the Sfonge site whether it is possible to create a 3D transition effect between two Activities. There is a sample program that does it among the API Demos but this program plays the transition effect between two views of the same Activity. The adaptation to do the same between two activities is not very complicated but has some tricks, that's why I decided to publish this example program.

Click here to access the example program.

First and foremost, I unashamedly stole the custom 3D animation from the API Demos application, that's what you find in Rotate3dAnimation.java. It is invoked in the landing Activity (Activity3dTransitionActivity) when the user initates transition to the second Activity (Screen2Activity) using the menu. The trick here is to attach an animation listener to the 3D animation object, start the animation in the outgoing Activity and only invoke startActivity() when the animation finishes. Note the overridePendingTransition( 0,0 ) invocation; this ensures that the system itself will not play any activity transition animation.

The incoming Screen2Activity seems simple but there is hidden gem here too. Observe that the top layout of the activity (in screen2.xml) is not a stock LinearLayout but a descendant (aexp.activity3dtransition.AnimatedLinearLayout). Overriding onMeasure() in this subclass makes sure that the incoming animation is started only after the elements of the layout (a single TextView here) have been laid out.

Sunday, April 1, 2012

Stabilizing compass with the accelerometer

Let's explore sensor fusion possibilities of the compass and the accelerometer a bit further. In the previous post we used the compass to calculate the gravity vector when the accelerometer is subject to motion acceleration too. Now let's support the compass with the accelerometer and create a stabilized compass.

As we discussed before, the Earth's magnetic field is a 3D vector which has two components: the horizontal element that points to toward the magnetic North (this is what we use for compass) and the magnetic inclination that has variable degree but points mostly down on the Northern Hemisphere. Now if the magnetic sensor is not parallel to the Earth's surface, the z component (pointing downward) of the Earth's magnetic vector is projected into the x and y axes of the phone's magnetic sensor causing the compass to rotate when the device is tilted. Try for example this great and popular compass application. Point the compass toward the North then tilt the device left and right. You will see that the compass rotates even though the longer axis of the device (the y axis in Android API) still points toward the North Pole.

This is a major problem in normal compasses that have only magnetic sensor, that's why complex mechanical systems are used to keep the compass horizontal e.g. on ships. Fortunately our Android phones have accelerometer beside the magnetic sensor and we can use that accelerometer to figure out of the device's tilt. Note that this time we assume that we don't have motion acceleration present. If we have and the phone is also equipped with gyroscope then we can additionally compensate the motion acceleration with the gyroscope as we discussed previously. This time, however, we play it simple and we assume that the accelerometer measures only the gravity acceleration and points toward the center of the Earth.

The example program can be downloaded from here.

The application is a variation of our previous example where we used the compass to compensate the motion acceleration. The compass calibration logic is the same. After the calibration the data is visualized differently. The red arrow points toward the North as calculated from the x and y components of the magnetic sensor and that's what most of the compass applications out there measures. The white arrow shows the North by the tilt-compensated compass. As the magnetic sensor and the accelerometer measures in the same coordinate system (the device's coordinate system), both vectors are subject to the same roll and pitch. The tilt-compensation algorithm calculates the rotation axis and angle between the gravity vector as measured by the accelerometer and the z (downward) axis. Then it rotates the magnetic vector measured by the magnetic sensor by the same axis and angle.