Home Tutorials Hands on Sensor arrow - Handling the sensor values
Sensor arrow - Handling the sensor values
Sunday, 08 March 2009 18:54
Article Index
Sensor arrow
Co-ordinate maths
Handling the sensor values
Simulation
All Pages
When  onSensorChanged() fires we have values for the Azimuth, Pitch and Roll. We're trying to get the tilt, which is the direction, and the angle, or the steepness, from these. When you think about it, the Azimuth value isn't needed for this as you can in fact treat the pitch and roll values as the x and y co-ordinates of the point in a rectangular co-ordinate system.


In the above diagram point P can be expressed as (x, y) when using rectangular co-ordinates, or (R, t) using polar ones. This is where the java Math package comes to the rescue. A quick read of the api shows us there are exactly the functions we need for this, using the orientation values we just read. From the calcAngle() method:

mAngle = (int) ( Math.toDegrees(Math.atan( mOrientationValues[2] / mOrientationValues[1] )));
mTilt = (int) Math.sqrt(( Math.pow(mOrientationValues[2], 2))
    + (Math.pow(mOrientationValues[1], 2)));

Some more adjustments must be made to the angle according to the quadrant the point is positioned in, but after that we're done. At any time in our app, the mAngle value will show which way the handset is tilted, and the mTilt value how steep the tilt is.

In this application we will make use of these just by showing a radar type display with an arrow at the centre. The arrow will point in the tilts direction, and its length will show the steepness. So if the handset is perfectly flat there should be no arrow.

The applications onDraw() method draws the background, then the circle, centre and markers and calls drawArrow() to show the arrow:

private void drawArrow(Canvas canvas, Paint paint) {
    if (mTilt == 0) return;

    int length = ((mRadius - 30) * mTilt) / 100;

    if (length < 0) length = 0;
    if (length > (mRadius - 30)) length = mRadius - 30;

    Path mPath = new Path();
    mPath.moveTo(mCenterX, mCenterY);
    mPath.rLineTo(10, 0);
    mPath.rLineTo(0, -length);
    mPath.rLineTo(10, 0);
    mPath.rLineTo(-20, -30);
    mPath.rLineTo(-20, 30);
    mPath.rLineTo(10, 0);
    mPath.rLineTo(0, length);
    mPath.rLineTo(10, 0);
    mPaint.setStyle(Paint.Style.FILL);
    canvas.rotate(mAngle, mCenterX, mCenterY);
    canvas.drawPath(mPath, mPaint);
    canvas.rotate(-mAngle, mCenterX, mCenterY);
}

We're using Androids Path mechanism here to construct an outline in memory, then call drawPath() on it to get it to appear immediately. We are also rotating the whole canvas by the amount in mAngle, just for the duration of this draw, so it appears the arrow itself has been rotated correctly.



 

Add comment


Security code
Refresh

Portions are modifications based on work created and shared by Google and used according to terms described in the Creative Commons 3.0 Attribution License. Android Academy is independent from Google. All trademarks acknowledged.
 
Glossary
We have 52 guests online