ภาพรวม
ตัวอย่างนี้สาธิตวิธีตรวจสอบการรองรับเซ็นเซอร์ TYPE_GAME_ROTATION_VECTOR ซึ่งให้ค่า Rotation Vector (Quaternion) โดยไม่ใช้ Magnetometer เหมาะสำหรับ Gaming และ VR ที่ไม่ต้องการทิศทางแม่เหล็กโลก
ขั้นตอนการสร้างโปรเจกต์
ขั้นตอนที่ 1: สร้างโปรเจกต์ใหม่
Android Studio → File → New Project → Empty Activity
ขั้นตอนที่ 2: Layout (res/layout/activity_main.xml)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:app="https://schemas.android.com/apk/res-auto"
xmlns:tools="https://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center"
tools:context=".MainActivity">
<TextView
android:id="@+id/actionEvent"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginTop="30dp"
android:textSize="40sp"
android:gravity="center" />
</LinearLayout>
ขั้นตอนที่ 3: โค้ดหลัก (src/MainActivity.java)
package com.example.myapplication;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorManager;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.RequiresApi;
import android.support.v7.app.AppCompatActivity;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
TextView textView;
SensorManager sensorManager;
@RequiresApi(api = Build.VERSION_CODES.N)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView actionEvent = findViewById(R.id.actionEvent);
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
// ตรวจสอบ Game Rotation Vector
Sensor gameRotationVector = sensorManager.getDefaultSensor(Sensor.TYPE_GAME_ROTATION_VECTOR);
if (gameRotationVector != null) {
actionEvent.setText("รองรับ Game Rotation Vector");
String info = String.format(
"Name: %s\nVendor: %s\nVersion: %d\n" +
"Max Range: %.2f\nResolution: %.2f\nPower: %.2f mA\nMin Delay: %d µs",
gameRotationVector.getName(),
gameRotationVector.getVendor(),
gameRotationVector.getVersion(),
gameRotationVector.getMaximumRange(),
gameRotationVector.getResolution(),
gameRotationVector.getPower(),
gameRotationVector.getMinDelay()
);
actionEvent.append("\n\n" + info);
} else {
actionEvent.setText("ไม่รองรับ Game Rotation Vector\n(ต้องมี Gyroscope + Accelerometer)");
}
}
}
ข้อมูลเซ็นเซอร์ TYPE_GAME_ROTATION_VECTOR
| คุณสมบัติ | รายละเอียด |
|---|---|
| API Level | เพิ่มใน API 18 (Android 4.3) |
| ประเภท | Virtual/Composite Sensor (Sensor Fusion) |
| รูปแบบข้อมูล | Quaternion (x, y, z, w) หรือ Rotation Vector (x, y, z) |
| ขึ้นอยู่กับ | Gyroscope + Accelerometer (ไม่ใช้ Magnetometer) |
| Drift | มี Drift น้อยกว่า Gyroscope เพียงอย่างเดียว |
Game Rotation Vector vs Rotation Vector
| คุณสมบัติ | TYPE_GAME_ROTATION_VECTOR | TYPE_ROTATION_VECTOR |
|---|---|---|
| ใช้ Magnetometer | ไม่ใช้ | ใช้ (สำหรับ Absolute heading) |
| Reference Frame | Relative (Device frame) | Absolute (World frame - Magnetic North) |
| Drift (Yaw) | มี Drift ตามเวลา | ไม่มี Drift (Locked to Magnetic North) |
| เหมาะสำหรับ | Gaming, VR, Relative rotation | Navigation, Compass, AR |
| Calibration | ไม่ต้อง Calibrate | ต้อง Calibrate (หมุนรูป 8) |
การใช้งานจริง
- Mobile Gaming: ควบคุมมุมมอง/การเล็งด้วยการหมุนโทรศัพท์
- VR Apps: Head tracking สำหรับ Cardboard/Daydream (ไม่ต้องการ Compass)
- 3D Model Viewer: หมุนโมเดล 3D ด้วยการเคลื่อนไหวอุปกรณ์
- Camera Apps: Stabilization, Panorama stitching
ตัวอย่างการแปลง Quaternion เป็น Euler Angles
// event.values = [x, y, z, w] (Quaternion) หรือ [x, y, z] (Rotation Vector)
float[] quaternion = new float[4];
if (event.values.length == 3) {
// Rotation Vector -> Quaternion
SensorManager.getQuaternionFromVector(quaternion, event.values);
} else {
System.arraycopy(event.values, 0, quaternion, 0, 4);
}
// Quaternion -> Euler Angles (Degrees)
float[] rotationMatrix = new float[9];
SensorManager.getRotationMatrixFromVector(rotationMatrix, quaternion);
float[] orientation = new float[3];
SensorManager.getOrientation(rotationMatrix, orientation);
float azimuth = (float) Math.toDegrees(orientation[0]); // Z-axis rotation
float pitch = (float) Math.toDegrees(orientation[1]); // X-axis rotation
float roll = (float) Math.toDegrees(orientation[2]); // Y-axis rotation
ข้อควรระวัง
- ต้องมี Gyroscope + Accelerometer ทั้งคู่
- Yaw (Azimuth) จะ Drift ตามเวลา เพราะไม่มี Magnetometer Anchor
- เหมาะสำหรับ Relative rotation (การหมุนสัมพัทธ์) ไม่ใช่ Absolute heading
- ใน Manifest:
<uses-feature android:name="android.hardware.sensor.gyroscope" android:required="true" />(โดยนัย)