03 March 2013

Sensor API in Android - การใช้งาน Gyroscope

Updated on

        บทความนี้ก็จะยังคงต่อเนื่องกันอยู่ที่เรื่องเซนเซอร์กันต่อ คราวก่อนเป็นเรื่อง Accelerometer คราวนี้เป็น Gyroscope บ้าง สำหรับ Gyroscope ก็จะคล้ายๆกับ Acclerometer นั่นแหละ คือวัดความเร่งของการเอียงเครื่อง แต่ว่าจะแตกต่างกันออกไป โดยที่ Accelerometer จะวัดความเร่งตามแนวแกน XYZ แต่ว่าสำหรับ Gyroscope จะเป็นความเร่งเชิงมุมของแกน XYZ




        สำหรับแกน XYZ บนอุปกรณ์แอนดรอยด์ใดๆ จะมีตำแหน่งดังนี้

        สำหรับแกน X กับ Y จะขึ้นอยู่กับตัวอุปกรณ์แอนดรอยด์ ในภาพข้างบนนี้จะเป็นแกน XYZ บนเครื่องที่เป็นแทบเลตมีแกน X ตามแนวกว้างของจอ และแกน Y ตามแนวสูง


        ส่วนภาพข้างบนนี้คือแกน XYZ บนเครื่องที่เป็นมือถือจะเห็นว่าแนวแกน X กับ Y ไม่เหมือนกับบนแทบเลต ดังนั้นเวลาใช้ Gyroscope ก็ให้คำนึงถึงเรื่องนี้ด้วย

        ทีนี้มาดูกันต่อว่าความเร่งเชิงมุมของแกน XYZ กันบ้าง เพราะมันจะต่างจากของ Accelerometer ที่เป็นแนวแกน สำหรับความเร่งเชิงมุม มองภาพง่ายๆก็คือการหมุนเครื่อง ซึ่งเป็นการหมุนเครื่องในแต่ละแกน ดูตามภาพข้างล่างเลย


        ถ้าดูจากภาพข้างบนนี้แล้ว ลองสังเกตแกน X และ Y ดู จะพบว่าการหมุนในแกน Y ก็คือการเอียงเครื่องในแกน X และการหมุนในแกน X ก็คือการเอียงเครื่องในแกน Y แต่ความแตกต่างอยู่ที่แกน Z ถ้าเป็นของ Accelerometer แกน Z จะมีการเปลี่ยนแปลงไปตามแกน X และแกน Y แต่ Gyroscope การหมุนแกน Z จะเป็นอิสระจากแกนอื่น


        จากวีดีโอจะเห็นว่าหมดปัญหาเรื่องหมุนในแนวระนาบกับพื้นโลก เนื่องมาจากการที่ Gyroscope ใช้หลักการวัดความเร่งเชิงมุม


        สำหรับการใช้งาน Gyroscope จะให้ใช้เฉพาะบางเครื่องเท่านั้น ไม่เหมือนกับ Accelerometer ที่มีอยู่บนแอนดรอยด์ทุกเครื่อง ดังนั้นก่อนจะเริ่มทำตามตัวอย่างในบทความนี้ให้เช็คก่อนว่าเครื่องที่ใช้ทดสอบอยู่นั้น มี Gyroscope ให้ใช้หรือไม่ สามารถเช็คง่ายๆได้จากแอปพลิเคชันที่ชื่อว่า Sensor Checker [Google Play] ในการใช้งาน Gyroscope นิยมใช้กับการหมุนเครื่อง

        สำหรับคำสั่งพื้นฐานในการเริ่มใช้งานเซนเซอร์ให้อ่านจากบทความของ Accelerometer แทน [Android Code] การใช้งาน Accelerometer

        เวลาใช้ประกาศใช้งาน Gyroscope ก็เปลี่ยนคำสั่งจากเดิมเป็น

SensorManager sensorManager = (SensorManager)getSystemService(Context.SENSOR_SERVICE); Sensor sensor = sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE); 

        สำหรับการอ่านค่าจาก Gyroscope ก็เหมือนกับ Accelerometer โดยจะได้ค่าออกมาเป็นแกน XYZ โดยมีหน่วยเป็น Rad/s ซึ่งก็คือมุม Radian ที่กวาดไปในหนึ่งวินาทีนั่นเอง จะเห็นว่าค่าที่อ่านจาก Gyroscope เป็นความเร่งจริงๆเลย ไม่เหมือนกับ Accelerometer ที่ระบบแปลงค่าเป็นค่าความเอียง

public SensorEventListener gyroListener = new SensorEventListener() { public void onAccuracyChanged(Sensor sensor, int acc) { } public void onSensorChanged(SensorEvent event) { float x = event.values[0]; float y = event.values[1]; float z = event.values[2]; textX.setText("X : " + (int)x + " rad/s"); textY.setText("Y : " + (int)y + " rad/s"); textZ.setText("Z : " + (int)z + " rad/s"); } };


        ทีนี้มาดูตัวอย่างในบทความนี้กันเลยดีกว่า

Main.java
package app.akexorcist.sensor_gyroscope;

import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.app.Activity;
import android.content.Context;
import android.widget.TextView;

public class Main extends Activity {
    TextView textX, textY, textZ;
    SensorManager sensorManager;
    Sensor sensor;
 
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
 
        sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
        sensor = sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
        
        textX = (TextView)findViewById(R.id.textX);
        textY = (TextView)findViewById(R.id.textY);
        textZ = (TextView)findViewById(R.id.textZ);
    }
 
    public void onResume() {
        super.onResume();
        sensorManager.registerListener(gyroListener, sensor, SensorManager.SENSOR_DELAY_NORMAL);
    }
 
    public void onStop() {
        super.onStop();
        sensorManager.unregisterListener(gyroListener);
    }

    public SensorEventListener gyroListener = new SensorEventListener() {
        public void onAccuracyChanged(Sensor sensor, int acc) { }
 
        public void onSensorChanged(SensorEvent event) {
            float x = event.values[0];
            float y = event.values[1];
            float z = event.values[2];

            textX.setText("X : " + (int)x + " rad/s");
            textY.setText("Y : " + (int)y + " rad/s");
            textZ.setText("Z : " + (int)z + " rad/s");
        }
    };
}

        ไม่ขออธิบายอะไรมาก เพราะเหมือนกับของ Accelerometer ดังนั้นให้ไปอ่านบทความ [Android Code] การใช้งาน Accelerometer แทนละกัน


main.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" > <TextView android:id="@+id/textX" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="30sp" android:text="" /> <TextView android:id="@+id/textY" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="20sp" android:textSize="30sp" android:text="" /> <TextView android:id="@+id/textZ" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="20sp" android:textSize="30sp" android:text="" /> </LinearLayout>


AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="app.akexorcist.sensor_gyroscope" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="8" /> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name="app.akexorcist.sensor_gyroscope.Main" android:label="@string/app_name" android:screenOrientation="portrait" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>

        ตอนทดสอบ Gyroscope ต้องลองหมุนเครื่องไปมาดู เพราะค่าที่ได้เป็นค่าความเร่งเชิงมุม ดังนั้นถ้าหยุดหมุน ค่าที่ได้ก็จะเป็น 0 นั่นเอง อาจจะทดสอบลำบากไปหน่อย      

        สำหรับผู้ที่หลงเข้ามาอ่านคนไหนต้องการไฟล์ตัวอย่างสามารถดาวน์โหลดได้จาก

                Sensor-Gyroscope [Google Drive]

                Sensor-Gyroscope [GitHub]

                Sensor-Gyroscope [Sleeping For Less]