เซ็นเซอร์ตรวจจับความเคลื่อนไหว

แพลตฟอร์ม Android มีเซ็นเซอร์หลายตัวที่ช่วยให้คุณตรวจสอบการเคลื่อนไหวได้ ของอุปกรณ์

เซ็นเซอร์ สถาปัตยกรรมที่เป็นไปได้จะแตกต่างกันไปตามประเภทเซ็นเซอร์ ดังนี้

  • แรงโน้มถ่วง, ความเร่งเชิงเส้น, เวกเตอร์การหมุน, การเคลื่อนที่ที่สำคัญ, ขั้นตอน เซ็นเซอร์ตรวจจับนับก้าวและเซ็นเซอร์ตรวจจับก้าวเดิน จะทำงานโดยใช้ฮาร์ดแวร์หรือ โดยใช้ซอฟต์แวร์เป็นหลัก
  • ตัวตรวจวัดความเร่งและเซ็นเซอร์เครื่องวัดการหมุนจะทำงานโดยใช้ฮาร์ดแวร์เสมอ

อุปกรณ์ที่ใช้ระบบ Android ส่วนใหญ่มีตัวตรวจวัดความเร่ง และตอนนี้หลายเครื่องมีตัวตรวจวัดความเร่ง เครื่องวัดการหมุน เซ็นเซอร์ที่ใช้ซอฟต์แวร์มีให้บริการมากขึ้น เนื่องจากมักจะอาศัยเซ็นเซอร์ของฮาร์ดแวร์อย่างน้อย 1 ตัวเพื่อสร้างฟังก์ชัน โดยเซ็นเซอร์ที่ใช้ซอฟต์แวร์เหล่านี้จะดึงข้อมูล ข้อมูลจากตัวตรวจวัดความเร่งและเครื่องวัดค่าความเข้มข้นของสนามแม่เหล็ก หรือจากเครื่องวัดการหมุน

เซ็นเซอร์ตรวจจับการเคลื่อนไหวมีประโยชน์สำหรับการตรวจสอบการเคลื่อนไหวของอุปกรณ์ เช่น การเอียง การสั่น การหมุน หรือ แกว่งไกว ซึ่งมักเป็นไปตามข้อมูลจากผู้ใช้โดยตรง (ตัวอย่างเช่น ผู้ใช้บังคับ รถในเกมหรือผู้ใช้ควบคุมลูกบอลในเกม) แต่ก็อาจเป็นภาพสะท้อนของ สภาพแวดล้อมทางกายภาพที่อุปกรณ์นั่งอยู่ (เช่น เคลื่อนที่ไปกับคุณขณะขับรถ รถของคุณ) ในกรณีแรก คุณจะตรวจสอบการเคลื่อนไหวที่สัมพันธ์กับกรอบอ้างอิงของอุปกรณ์ หรือกรอบอ้างอิงของแอปพลิเคชัน ในกรณีที่ 2 คุณกำลังติดตามการเคลื่อนไหว กรอบอ้างอิงของโลกได้ ปกติแล้วเซ็นเซอร์ตรวจจับการเคลื่อนไหวจะไม่นำมาใช้เพื่อตรวจสอบ ตำแหน่งของอุปกรณ์ แต่สามารถใช้กับเซ็นเซอร์อื่นๆ เช่น เซ็นเซอร์สนามแม่เหล็กไฟฟ้า กำหนดตำแหน่งของอุปกรณ์ที่สัมพันธ์กับกรอบอ้างอิงของโลก (ดูข้อมูลเพิ่มเติมที่เซ็นเซอร์ตำแหน่ง ข้อมูล)

เซ็นเซอร์ตรวจจับการเคลื่อนไหวทั้งหมดจะแสดงผลค่าเซ็นเซอร์แบบหลายมิติสำหรับ SensorEvent แต่ละรายการ ตัวอย่างเช่น ในระหว่างเหตุการณ์เซ็นเซอร์ครั้งเดียว ตัวตรวจวัดความเร่งจะกลับมา ข้อมูลแรงเร่งของแกนพิกัด 3 แกน และเครื่องวัดการหมุนแสดงผลอัตราการหมุน ข้อมูลสำหรับแกนพิกัด 3 แกน ค่าข้อมูลเหล่านี้จะแสดงในอาร์เรย์ float (values) รวมถึงSensorEvent อื่นๆ พารามิเตอร์ ตารางที่ 1 สรุปเกี่ยวกับเซ็นเซอร์ตรวจจับการเคลื่อนไหวที่มีในแพลตฟอร์ม Android

ตาราง 1 เซ็นเซอร์ตรวจจับการเคลื่อนไหวที่รองรับบนแพลตฟอร์ม Android

เซ็นเซอร์ ข้อมูลเหตุการณ์เซ็นเซอร์ คำอธิบาย หน่วยวัด
TYPE_ACCELEROMETER SensorEvent.values[0] แรงเร่งตามแกน x (รวมแรงโน้มถ่วง) ม./วินาที2
SensorEvent.values[1] แรงเร่งตามแกน Y (รวมถึงแรงโน้มถ่วง)
SensorEvent.values[2] แรงเร่งตามแกน z (รวมถึงแรงโน้มถ่วง)
TYPE_ACCELEROMETER_UNCALIBRATED SensorEvent.values[0] วัดความเร่งตามแกน X โดยไม่มีการชดเชยการให้น้ำหนักพิเศษ ม./วินาที2
SensorEvent.values[1] วัดความเร่งตามแกน Y โดยไม่มีการชดเชยการให้น้ำหนักพิเศษ
SensorEvent.values[2] วัดความเร่งตามแกน Z โดยไม่มีการชดเชยการให้น้ำหนักพิเศษ
SensorEvent.values[3] ความเร่งที่วัดตามแกน X พร้อมการชดเชยการให้น้ำหนักพิเศษโดยประมาณ
SensorEvent.values[4] ความเร่งที่วัดตามแกน Y พร้อมการชดเชยการให้น้ำหนักพิเศษโดยประมาณ
SensorEvent.values[5] ความเร่งที่วัดได้ตามแกน Z พร้อมการชดเชยการให้น้ำหนักพิเศษโดยประมาณ
TYPE_GRAVITY SensorEvent.values[0] แรงโน้มถ่วงตามแกน x ม./วินาที2
SensorEvent.values[1] แรงโน้มถ่วงตามแกน y
SensorEvent.values[2] แรงโน้มถ่วงตามแกน z
TYPE_GYROSCOPE SensorEvent.values[0] อัตราการหมุนรอบแกน x rad/วินาที
SensorEvent.values[1] อัตราการหมุนรอบแกน y
SensorEvent.values[2] อัตราการหมุนรอบแกน z
TYPE_GYROSCOPE_UNCALIBRATED SensorEvent.values[0] อัตราการหมุน (ไม่มีการชดเชยการเลื่อน) รอบแกน x rad/วินาที
SensorEvent.values[1] อัตราการหมุน (ไม่มีการชดเชยการเลื่อน) รอบแกน Y
SensorEvent.values[2] อัตราการหมุน (ไม่มีการชดเชยการเลื่อน) รอบแกน z
SensorEvent.values[3] การเคลื่อนที่โดยประมาณรอบแกน x
SensorEvent.values[4] การดริฟต์โดยประมาณรอบแกน y
SensorEvent.values[5] การดริฟต์โดยประมาณรอบแกน z
TYPE_LINEAR_ACCELERATION SensorEvent.values[0] แรงเร่งตามแกน x (ไม่รวมแรงโน้มถ่วง) ม./วินาที2
SensorEvent.values[1] แรงเร่งตามแกน Y (ไม่รวมแรงโน้มถ่วง)
SensorEvent.values[2] แรงเร่งตามแกน z (ไม่รวมแรงโน้มถ่วง)
TYPE_ROTATION_VECTOR SensorEvent.values[0] องค์ประกอบเวกเตอร์การหมุนตามแกน x (x * sin(CONFIRM/2)) ไม่มีหน่วย
SensorEvent.values[1] องค์ประกอบเวกเตอร์การหมุนตามแกน y (y * sin(CONFIRM/2))
SensorEvent.values[2] คอมโพเนนต์เวกเตอร์การหมุนตามแกน z (z * sin(การเป็นสมาชิก/2))
SensorEvent.values[3] คอมโพเนนต์ Scalar ของเวกเตอร์การหมุน ((cos(Authorization/2))1
TYPE_SIGNIFICANT_MOTION ไม่มี ไม่มีข้อมูล ไม่มี
TYPE_STEP_COUNTER SensorEvent.values[0] จำนวนก้าวที่ผู้ใช้ทำตั้งแต่รีบูตครั้งล่าสุดขณะเซ็นเซอร์ เปิดใช้งาน แล้ว จำนวนก้าว
TYPE_STEP_DETECTOR ไม่มี ไม่มีข้อมูล ไม่มี

1 คอมโพเนนต์สเกลาร์เป็นค่าที่ไม่บังคับ

เซ็นเซอร์เวกเตอร์การหมุนและเซ็นเซอร์แรงโน้มถ่วงเป็นเซ็นเซอร์สำหรับการเคลื่อนไหวที่ใช้บ่อยที่สุด การตรวจจับและการตรวจสอบ เซ็นเซอร์เวกเตอร์แบบหมุนมีความอเนกประสงค์และสามารถใช้สำหรับ งานต่างๆ ที่เกี่ยวข้องกับการเคลื่อนไหว เช่น การตรวจจับท่าทางสัมผัส การตรวจสอบการเปลี่ยนแปลงของมุม และ การตรวจสอบการเปลี่ยนแปลงการวางแนวแบบสัมพัทธ์ ตัวอย่างเช่น เซ็นเซอร์เวกเตอร์แบบหมุนเหมาะอย่างยิ่งหากคุณ กำลังพัฒนาเกม แอปพลิเคชันเทคโนโลยีความจริงเสริม (AR) เข็มทิศ 2 มิติหรือ 3 มิติ หรือแอปป้องกันภาพสั่นไหว ในกรณีส่วนใหญ่ การใช้เซ็นเซอร์เหล่านี้เป็นทางเลือกที่ดีกว่าการใช้ ตัวตรวจวัดความเร่งและเซ็นเซอร์สนามแม่เหล็ก หรือเซ็นเซอร์การวางแนว

เซ็นเซอร์โครงการโอเพนซอร์ส Android

โครงการโอเพนซอร์ส Android (AOSP) มีเซ็นเซอร์ตรวจจับการเคลื่อนไหวแบบซอฟต์แวร์ 3 ตัว ได้แก่ แรงโน้มถ่วง เซ็นเซอร์ เซ็นเซอร์ความเร่งเชิงเส้น และเซ็นเซอร์เวกเตอร์การหมุน เซ็นเซอร์เหล่านี้ได้รับการอัปเดตใน Android 4.0 และตอนนี้ใช้เครื่องวัดการหมุนของอุปกรณ์ (นอกเหนือจากเซ็นเซอร์อื่นๆ) เพื่อปรับปรุงความเสถียรและ ด้านประสิทธิภาพ หากต้องการลองใช้เซ็นเซอร์เหล่านี้ คุณระบุเซ็นเซอร์ได้โดยใช้เมธอด getVendor() และเมธอด getVersion() (ผู้ให้บริการคือ Google LLC หมายเลขเวอร์ชันคือ 3) ระบุเซ็นเซอร์เหล่านี้โดยผู้ให้บริการและ หมายเลขเวอร์ชันเป็นสิ่งจำเป็นเนื่องจากระบบ Android ถือว่าเซ็นเซอร์ 3 ตัวนี้เป็นเซ็นเซอร์รอง เซ็นเซอร์ ตัวอย่างเช่น หากผู้ผลิตอุปกรณ์มีเซ็นเซอร์แรงโน้มถ่วงเป็นของตัวเอง เซ็นเซอร์ AOSP เซ็นเซอร์แรงโน้มถ่วงจะแสดงเป็นเซ็นเซอร์แรงโน้มถ่วงรอง เซ็นเซอร์ทั้ง 3 ตัวนี้อาศัย เครื่องวัดการหมุน: หากอุปกรณ์ไม่มีเครื่องวัดการหมุน เซ็นเซอร์เหล่านี้จะไม่แสดงขึ้นและไม่ พร้อมให้ใช้งาน

ใช้เซ็นเซอร์แรงโน้มถ่วง

เซ็นเซอร์แรงโน้มถ่วงจะให้เวกเตอร์สามมิติซึ่งระบุถึง ทิศทางและขนาดของแรงโน้มถ่วง โดยปกติแล้ว เซ็นเซอร์นี้จะใช้เพื่อระบุ การวางแนวแบบสัมพัทธ์ของอุปกรณ์ในอวกาศ โค้ดต่อไปนี้จะแสดงวิธีการ รับอินสแตนซ์ของเซ็นเซอร์แรงโน้มถ่วงเริ่มต้น

Kotlin

val sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
val sensor: Sensor? = sensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY)

Java

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

หน่วยจะเหมือนกับหน่วยที่ใช้โดยความเร่ง เซ็นเซอร์ (m/s2) และระบบพิกัดเหมือนกับที่ เซ็นเซอร์การเร่งความเร็ว

หมายเหตุ: เมื่ออุปกรณ์ไม่มีการใช้งาน เอาต์พุตของเซ็นเซอร์แรงโน้มถ่วง ควรเหมือนกับของตัวตรวจวัดความเร่ง

ใช้ตัวตรวจวัดความเร่งเชิงเส้น

เซ็นเซอร์ความเร่งเชิงเส้นจะแสดงเวกเตอร์ 3 มิติ แสดงความเร่งตามแกนอุปกรณ์แต่ละแกน ยกเว้นแรงโน้มถ่วง คุณสามารถใช้ ค่านี้เพื่อดำเนินการตรวจจับท่าทางสัมผัส ค่านี้ยังใช้เป็นอินพุต ระบบนำทางแบบเฉื่อย ซึ่งใช้การคำนวณหาตาย โค้ดต่อไปนี้แสดง วิธีดูอินสแตนซ์ของเซ็นเซอร์การเร่งความเร็วเชิงเส้นที่เป็นค่าเริ่มต้น

Kotlin

val sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
val sensor: Sensor? = sensorManager.getDefaultSensor(Sensor.TYPE_LINEAR_ACCELERATION)

Java

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

โดยหลักการแล้ว เซ็นเซอร์นี้จะให้ข้อมูลการเร่งความเร็วตามปัจจัยต่อไปนี้ ความสัมพันธ์:

linear acceleration = acceleration - acceleration due to gravity

ปกติแล้วคุณจะใช้เซ็นเซอร์นี้เมื่อคุณต้องการรับข้อมูลความเร่งโดยไม่ส่งผลกระทบต่อ แรงโน้มถ่วง ตัวอย่างเช่น คุณสามารถใช้เซ็นเซอร์นี้เพื่อดูว่ารถของคุณวิ่งเร็วแค่ไหน เชิงเส้น เซ็นเซอร์การเร่งความเร็วจะมีออฟเซ็ตเสมอ ซึ่งคุณต้องถอดออก วิธีที่ง่ายที่สุดในการดำเนินการนี้คือ เพื่อสร้างขั้นตอนการปรับเทียบในแอปพลิเคชันของคุณ ระหว่างการปรับเทียบ คุณสามารถขอให้ผู้ใช้ตั้งค่า อุปกรณ์บนโต๊ะ จากนั้นอ่านค่าออฟเซ็ตของแกนทั้ง 3 แกน จากนั้นคุณมาลบค่าดังกล่าว หักลบจากค่าตรงของเซ็นเซอร์ความเร่งที่อ่านได้เพื่อหาเส้นตรง การเร่งความเร็ว

พิกัดของเซ็นเซอร์ ระบบ เหมือนกับที่ระบบใช้โดยเซ็นเซอร์ความเร่ง เช่นเดียวกับหน่วยวัด (m/s2)

ใช้เซ็นเซอร์เวกเตอร์การหมุน

เวกเตอร์การหมุนแสดงการวางแนวของอุปกรณ์โดยเป็นการรวมมุมและ แกน ซึ่งอุปกรณ์หมุนผ่านมุม HIPAA รอบแกน (x, y หรือ z) ดังต่อไปนี้ โค้ดแสดงวิธีขอรับอินสแตนซ์ของเซ็นเซอร์เวกเตอร์การหมุนเริ่มต้น

Kotlin

val sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
val sensor: Sensor? = sensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR)

Java

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

องค์ประกอบ 3 รายการของเวกเตอร์การหมุนแสดงดังนี้

x*sin(DMCA/2), y*sin(เพื่อไม่ให้เป็นความจริง/2), z*sin(มากกว่าช่วงวัยทดลอง)

โดยที่ขนาดของเวกเตอร์การหมุนเท่ากับ sin(Authorization/2) และทิศทางของ เวกเตอร์การหมุนจะเท่ากับทิศทางของแกนของการหมุน

รูปที่ 1 ระบบพิกัดที่ใช้โดยเซ็นเซอร์เวกเตอร์การหมุน

องค์ประกอบสามอย่างของเวกเตอร์การหมุนเท่ากับองค์ประกอบ 3 ส่วนสุดท้ายของหน่วย quaternion (cos(การเป็นสมาชิก/2), x*sin(แข่งช่วงการนัดหมาย/2), y*sin(โปรดไปที่ ฟีเจอร์ใหม่ๆ ในรูปแบบของ z*sin(การเป็นสมาชิกในวันที่ 2) \ องค์ประกอบของเวกเตอร์การหมุนคือ แบบไม่มีหน่วย แกน x, y และ z จะได้รับการกำหนดในลักษณะเดียวกันกับเซ็นเซอร์การเร่งความเร็ว ข้อมูลอ้างอิง ระบบพิกัดได้รับการกำหนดให้เป็นพื้นฐานทางคณิตศาสตร์โดยตรง (ดูรูปที่ 1) ระบบพิกัดนี้ มีลักษณะดังต่อไปนี้

  • X หมายถึงผลคูณของเวกเตอร์ Y x Z ซึ่งเกี่ยวพันกับ ที่ตำแหน่งปัจจุบันของอุปกรณ์และชี้ไปทางทิศตะวันออกโดยประมาณ
  • Y คือเส้นสัมผัสกับพื้นตรงตำแหน่งปัจจุบันของอุปกรณ์และชี้ไปยัง คลื่นแม่เหล็ก ขั้วโลกเหนือ
  • Z ชี้ไปยังท้องฟ้าและตั้งฉากกับระนาบพื้นดิน

สำหรับตัวอย่างแอปพลิเคชันที่แสดงวิธีใช้เซ็นเซอร์เวกเตอร์การหมุน โปรดดู Rotation VectorDemo.java

ใช้เซ็นเซอร์ตรวจจับการเคลื่อนไหวที่มีนัยสำคัญ

เซ็นเซอร์ตรวจจับการเคลื่อนไหวที่มีนัยสำคัญจะทริกเกอร์เหตุการณ์ทุกครั้งที่มีการตรวจพบการเคลื่อนไหวที่มีนัยสำคัญ และ ก็จะปิดใช้งานไปเอง การเคลื่อนไหวที่สำคัญคือ การเคลื่อนไหวที่อาจทำให้เกิดการเปลี่ยนแปลงใน ตำแหน่งที่ตั้งของผู้ใช้ เช่น การเดิน ขี่จักรยาน หรือนั่งในรถที่เคลื่อนที่ โค้ดต่อไปนี้แสดงให้คุณทราบ วิธีรับอินสแตนซ์ของเซ็นเซอร์ตรวจจับการเคลื่อนไหวที่สำคัญเริ่มต้นและวิธีบันทึกเหตุการณ์ Listener:

Kotlin

val sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
val mSensor: Sensor? = sensorManager.getDefaultSensor(Sensor.TYPE_SIGNIFICANT_MOTION)
val triggerEventListener = object : TriggerEventListener() {
    override fun onTrigger(event: TriggerEvent?) {
        // Do work
    }
}
mSensor?.also { sensor ->
    sensorManager.requestTriggerSensor(triggerEventListener, sensor)
}

Java

private SensorManager sensorManager;
private Sensor sensor;
private TriggerEventListener triggerEventListener;
...
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
sensor = sensorManager.getDefaultSensor(Sensor.TYPE_SIGNIFICANT_MOTION);

triggerEventListener = new TriggerEventListener() {
    @Override
    public void onTrigger(TriggerEvent event) {
        // Do work
    }
};

sensorManager.requestTriggerSensor(triggerEventListener, mSensor);

ดูข้อมูลเพิ่มเติมได้ที่ TriggerEventListener

ใช้เซ็นเซอร์นับก้าว

เซ็นเซอร์นับก้าวแสดงจำนวนก้าวที่ผู้ใช้ทำนับตั้งแต่การรีบูตครั้งล่าสุด ขณะเปิดใช้งานเซ็นเซอร์ ตัวนับก้าวมีเวลาในการตอบสนองมากกว่า (สูงสุด 10 วินาที) แต่มากกว่า ความแม่นยำมากกว่าเซ็นเซอร์ตรวจจับก้าวเดิน

หมายเหตุ: คุณต้องประกาศฟิลด์ ACTIVITY_RECOGNITION สิทธิ์เพื่อให้แอปของคุณใช้เซ็นเซอร์นี้ในอุปกรณ์ที่ใช้ Android 10 (API ระดับ 29) ขึ้นไป

โค้ดต่อไปนี้แสดงวิธีรับอินสแตนซ์ของขั้นตอนเริ่มต้น เซ็นเซอร์ตัวนับ:

Kotlin

val sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
val sensor: Sensor? = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER)

Java

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

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

ใช้เซ็นเซอร์ตรวจจับก้าว

เซ็นเซอร์ตรวจจับการก้าวจะทริกเกอร์เหตุการณ์ทุกครั้งที่ผู้ใช้ดำเนินการ เวลาในการตอบสนองคือ ควรต่ำกว่า 2 วินาที

หมายเหตุ: คุณต้องประกาศฟิลด์ ACTIVITY_RECOGNITION สิทธิ์เพื่อให้แอปของคุณใช้เซ็นเซอร์นี้ในอุปกรณ์ที่ใช้ Android 10 (API ระดับ 29) ขึ้นไป

โค้ดต่อไปนี้แสดงวิธีรับอินสแตนซ์ของขั้นตอนเริ่มต้น เซ็นเซอร์ตรวจจับ:

Kotlin

val sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
val sensor: Sensor? = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_DETECTOR)

Java

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

ใช้งานข้อมูลดิบ

เซ็นเซอร์ต่อไปนี้ให้ข้อมูลดิบเกี่ยวกับภาพเชิงเส้นและ แรงหมุนเวียนที่ใช้กับอุปกรณ์ หากต้องการใช้ค่าจาก เซ็นเซอร์เหล่านี้มีประสิทธิภาพ คุณจึงจำเป็นต้องกรองปัจจัยต่างๆ ออกจากสิ่งแวดล้อม เช่น แรงโน้มถ่วง คุณอาจต้องปรับอัลกอริทึมการปรับให้เรียบเนียนกับเทรนด์ด้วย ในการลดสัญญาณรบกวน

ใช้ตัวตรวจวัดความเร่ง

เซ็นเซอร์วัดความเร่งจะวัดความเร่งที่ใช้กับอุปกรณ์ ซึ่งรวมถึงแรงของ แรงโน้มถ่วง โค้ดต่อไปนี้แสดงวิธีรับอินสแตนซ์ของเซ็นเซอร์การเร่งความเร็วเริ่มต้น

Kotlin

val sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
val sensor: Sensor? = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)

Java

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

หมายเหตุ: หากแอปกำหนดเป้าหมายเป็น Android 12 (API ระดับ 31) หรือ สูงกว่า เซ็นเซอร์นี้ ถูกจำกัดอัตรา

โดยหลักการแล้ว เซ็นเซอร์ความเร่งจะเป็นตัวกำหนดความเร่งที่ใช้ กับอุปกรณ์ (Ad) โดยวัดแรงที่กระทำต่อเซ็นเซอร์ (Fs) เองโดยใช้ความสัมพันธ์ต่อไปนี้

A_D=-(1/มวล)∑F_S

อย่างไรก็ตาม แรงโน้มถ่วงจะส่งผลต่อความเร่งที่วัดได้เสมอ โดยอ้างอิงตาม ความสัมพันธ์ต่อไปนี้

A_D=-g-(1/มวล)∑F_S

ด้วยเหตุนี้ เมื่ออุปกรณ์วางอยู่บนโต๊ะ (และไม่เร่งความเร็ว) ตัวตรวจวัดความเร่งอ่านค่าขนาด g = 9.81 ม./วินาที2 ในทำนองเดียวกัน เมื่ออุปกรณ์อยู่ใน การตกแบบอิสระและจะเร่งความเร็วขึ้นสู่พื้นดินอย่างรวดเร็วด้วยความเร็ว 9.81 เมตร/วินาที2 ตัวตรวจวัดความเร่งอ่านค่าขนาด g = 0 ม./วินาที2 ดังนั้น ในการวัดผล ความเร่งที่แท้จริงของอุปกรณ์ การนำการมีส่วนร่วมของแรงโน้มถ่วงออกจาก ข้อมูลจากตัวตรวจวัดความเร่ง ซึ่งทำได้โดยใช้ตัวกรอง High Pass ในทางกลับกัน ถือว่าโลว์พาส สามารถใช้แผ่นกรองเพื่อแยกแรงโน้มถ่วง ตัวอย่างต่อไปนี้จะแสดงสิ่งที่คุณทำได้ ดังนี้

Kotlin

override fun onSensorChanged(event: SensorEvent) {
    // In this example, alpha is calculated as t / (t + dT),
    // where t is the low-pass filter's time-constant and
    // dT is the event delivery rate.

    val alpha: Float = 0.8f

    // Isolate the force of gravity with the low-pass filter.
    gravity[0] = alpha * gravity[0] + (1 - alpha) * event.values[0]
    gravity[1] = alpha * gravity[1] + (1 - alpha) * event.values[1]
    gravity[2] = alpha * gravity[2] + (1 - alpha) * event.values[2]

    // Remove the gravity contribution with the high-pass filter.
    linear_acceleration[0] = event.values[0] - gravity[0]
    linear_acceleration[1] = event.values[1] - gravity[1]
    linear_acceleration[2] = event.values[2] - gravity[2]
}

Java

public void onSensorChanged(SensorEvent event){
    // In this example, alpha is calculated as t / (t + dT),
    // where t is the low-pass filter's time-constant and
    // dT is the event delivery rate.

    final float alpha = 0.8;

    // Isolate the force of gravity with the low-pass filter.
    gravity[0] = alpha * gravity[0] + (1 - alpha) * event.values[0];
    gravity[1] = alpha * gravity[1] + (1 - alpha) * event.values[1];
    gravity[2] = alpha * gravity[2] + (1 - alpha) * event.values[2];

    // Remove the gravity contribution with the high-pass filter.
    linear_acceleration[0] = event.values[0] - gravity[0];
    linear_acceleration[1] = event.values[1] - gravity[1];
    linear_acceleration[2] = event.values[2] - gravity[2];
}

หมายเหตุ: คุณจะใช้เทคนิคต่างๆ เพื่อกรองข้อมูลเซ็นเซอร์ได้ ตัวอย่างโค้ดข้างต้นใช้ค่าคงที่ของตัวกรองแบบง่าย (อัลฟ่า) ในการสร้างตัวกรองโลว์พาส ตัวกรองนี้ ค่าคงที่ได้มาจากค่าคงที่เวลา (t) ซึ่งเป็นการแสดงเวลาคร่าวๆ ของเวลาในการตอบสนองที่ ตัวกรองจะเพิ่มไปยังเหตุการณ์เซ็นเซอร์และอัตราการนำส่งเหตุการณ์ของเซ็นเซอร์ (dt) ตัวอย่างโค้ด ใช้ค่าอัลฟ่า 0.8 เพื่อการสาธิต หากคุณใช้วิธีการกรองนี้ คุณอาจต้อง เพื่อเลือกค่าอัลฟ่าอื่น

ตัวตรวจวัดความเร่งใช้พิกัดเซ็นเซอร์มาตรฐาน ระบบ ในทางปฏิบัติ จะมีการใช้เงื่อนไขต่อไปนี้เมื่ออุปกรณ์วางอยู่ ราบเรียบบนโต๊ะตามแนวที่เป็นธรรมชาติ

  • หากคุณดันอุปกรณ์ทางด้านซ้าย (เพื่อให้อุปกรณ์เลื่อนไปทางขวา) ค่าความเร่ง x เป็นบวก
  • หากคุณดันอุปกรณ์ที่ด้านล่าง (เพื่อให้อุปกรณ์ออกห่างจากตัวคุณ) ค่าความเร่ง y จะเป็น เชิงบวก
  • หากคุณดันอุปกรณ์เข้าหาท้องฟ้าด้วยความเร่งที่ A m/วินาที2 ค่าความเร่งของ z เท่ากับ A + 9.81 ซึ่งตรงกับความเร่งของอุปกรณ์ (+A m/s2) ลบด้วยแรงโน้มถ่วง (-9.81 m/s2)
  • อุปกรณ์อยู่กับที่จะมีค่าความเร่งอยู่ที่ +9.81 ซึ่งสอดคล้องกับ ความเร่งของอุปกรณ์ (0 ม./วินาที2 ลบด้วยแรงโน้มถ่วง ซึ่งก็คือ -9.81 m/s2)

โดยทั่วไปแล้ว ตัวตรวจวัดความเร่งเป็นเซ็นเซอร์ที่ดีที่จะใช้หากคุณกำลังตรวจสอบการเคลื่อนไหวของอุปกรณ์ โทรศัพท์มือถือและแท็บเล็ตที่ใช้ Android เกือบทุกเครื่องจะมีตัวตรวจวัดความเร่ง และใช้ประมาณ 10 ครั้ง กำลังไฟน้อยกว่าเซ็นเซอร์ตรวจจับการเคลื่อนไหวอื่นๆ ข้อเสียประการหนึ่งคือคุณอาจต้องดำเนินการ ตัวกรองโลว์พาสและไฮพาสเพื่อกำจัดแรงโน้มถ่วงและลดเสียงรบกวน

ใช้เครื่องวัดการหมุน

เครื่องวัดการหมุนจะวัดอัตราการหมุนเป็น rad/s รอบ x, y ของอุปกรณ์ และแกน z โค้ดต่อไปนี้แสดงวิธีรับอินสแตนซ์ของเครื่องวัดการหมุนเริ่มต้น

Kotlin

val sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
val sensor: Sensor? = sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE)

Java

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

หมายเหตุ: หากแอปกำหนดเป้าหมายเป็น Android 12 (API ระดับ 31) หรือ สูงกว่า เซ็นเซอร์นี้ ถูกจำกัดอัตรา

ระบบพิกัดของเซ็นเซอร์ จะเหมือนกับที่ใช้สำหรับเซ็นเซอร์ความเร่ง การหมุนเวียนเป็นค่าบวกใน ทิศทางทวนเข็มนาฬิกา ซึ่งก็คือผู้สังเกตการณ์ที่มอง จากตำแหน่งที่เป็นบวกบนแกน x, y หรือ z ที่อุปกรณ์ที่วางตำแหน่งในจุดต้นทางจะรายงาน การหมุนบวกหากดูเหมือนว่าอุปกรณ์หมุนทวนเข็มนาฬิกา นี่คือ คำจำกัดความทางคณิตศาสตร์มาตรฐานของการหมุนเวียนเชิงบวก และไม่เหมือนกับคำนิยามสำหรับ การหมุนที่เซ็นเซอร์การวางแนวใช้

โดยปกติแล้ว เอาต์พุตของเครื่องวัดการหมุนจะรวมอยู่เสมอเพื่อคำนวณหาการหมุนที่อธิบาย การเปลี่ยนแปลงมุมต่างๆ เมื่อเวลาผ่านไป เช่น

Kotlin

// Create a constant to convert nanoseconds to seconds.
private val NS2S = 1.0f / 1000000000.0f
private val deltaRotationVector = FloatArray(4) { 0f }
private var timestamp: Float = 0f

override fun onSensorChanged(event: SensorEvent?) {
    // This timestep's delta rotation to be multiplied by the current rotation
    // after computing it from the gyro sample data.
    if (timestamp != 0f && event != null) {
        val dT = (event.timestamp - timestamp) * NS2S
        // Axis of the rotation sample, not normalized yet.
        var axisX: Float = event.values[0]
        var axisY: Float = event.values[1]
        var axisZ: Float = event.values[2]

        // Calculate the angular speed of the sample
        val omegaMagnitude: Float = sqrt(axisX * axisX + axisY * axisY + axisZ * axisZ)

        // Normalize the rotation vector if it's big enough to get the axis
        // (that is, EPSILON should represent your maximum allowable margin of error)
        if (omegaMagnitude > EPSILON) {
            axisX /= omegaMagnitude
            axisY /= omegaMagnitude
            axisZ /= omegaMagnitude
        }

        // Integrate around this axis with the angular speed by the timestep
        // in order to get a delta rotation from this sample over the timestep
        // We will convert this axis-angle representation of the delta rotation
        // into a quaternion before turning it into the rotation matrix.
        val thetaOverTwo: Float = omegaMagnitude * dT / 2.0f
        val sinThetaOverTwo: Float = sin(thetaOverTwo)
        val cosThetaOverTwo: Float = cos(thetaOverTwo)
        deltaRotationVector[0] = sinThetaOverTwo * axisX
        deltaRotationVector[1] = sinThetaOverTwo * axisY
        deltaRotationVector[2] = sinThetaOverTwo * axisZ
        deltaRotationVector[3] = cosThetaOverTwo
    }
    timestamp = event?.timestamp?.toFloat() ?: 0f
    val deltaRotationMatrix = FloatArray(9) { 0f }
    SensorManager.getRotationMatrixFromVector(deltaRotationMatrix, deltaRotationVector);
    // User code should concatenate the delta rotation we computed with the current rotation
    // in order to get the updated rotation.
    // rotationCurrent = rotationCurrent * deltaRotationMatrix;
}

Java

// Create a constant to convert nanoseconds to seconds.
private static final float NS2S = 1.0f / 1000000000.0f;
private final float[] deltaRotationVector = new float[4]();
private float timestamp;

public void onSensorChanged(SensorEvent event) {
    // This timestep's delta rotation to be multiplied by the current rotation
    // after computing it from the gyro sample data.
    if (timestamp != 0) {
      final float dT = (event.timestamp - timestamp) * NS2S;
      // Axis of the rotation sample, not normalized yet.
      float axisX = event.values[0];
      float axisY = event.values[1];
      float axisZ = event.values[2];

      // Calculate the angular speed of the sample
      float omegaMagnitude = sqrt(axisX*axisX + axisY*axisY + axisZ*axisZ);

      // Normalize the rotation vector if it's big enough to get the axis
      // (that is, EPSILON should represent your maximum allowable margin of error)
      if (omegaMagnitude > EPSILON) {
        axisX /= omegaMagnitude;
        axisY /= omegaMagnitude;
        axisZ /= omegaMagnitude;
      }

      // Integrate around this axis with the angular speed by the timestep
      // in order to get a delta rotation from this sample over the timestep
      // We will convert this axis-angle representation of the delta rotation
      // into a quaternion before turning it into the rotation matrix.
      float thetaOverTwo = omegaMagnitude * dT / 2.0f;
      float sinThetaOverTwo = sin(thetaOverTwo);
      float cosThetaOverTwo = cos(thetaOverTwo);
      deltaRotationVector[0] = sinThetaOverTwo * axisX;
      deltaRotationVector[1] = sinThetaOverTwo * axisY;
      deltaRotationVector[2] = sinThetaOverTwo * axisZ;
      deltaRotationVector[3] = cosThetaOverTwo;
    }
    timestamp = event.timestamp;
    float[] deltaRotationMatrix = new float[9];
    SensorManager.getRotationMatrixFromVector(deltaRotationMatrix, deltaRotationVector);
    // User code should concatenate the delta rotation we computed with the current rotation
    // in order to get the updated rotation.
    // rotationCurrent = rotationCurrent * deltaRotationMatrix;
}

เครื่องวัดการหมุนมาตรฐานให้ข้อมูลการหมุนแบบดิบโดยไม่มีการกรองหรือแก้ไขสัญญาณรบกวนและ ลอยตัว (อคติ) ในทางปฏิบัติ เสียงและการเลื่อนจากเครื่องวัดการหมุนจะก่อให้เกิดข้อผิดพลาดที่จำเป็น ที่ได้รับค่าตอบแทน โดยปกติแล้ว คุณมักจะพิจารณาการลอยตัว (อคติ) และเสียงรบกวนโดยการตรวจสอบเซ็นเซอร์อื่นๆ เช่น เป็นเซ็นเซอร์แรงโน้มถ่วงหรือตัวตรวจวัดความเร่ง

ใช้เครื่องวัดการหมุนที่ไม่ได้ปรับเทียบ

เครื่องวัดการหมุนที่ไม่ได้ปรับเทียบจะคล้ายกับเครื่องวัดการหมุน เว้นแต่ว่าจะไม่มีการใช้การชดเชยไจโรดริฟต์กับอัตราการหมุน การปรับเทียบจากโรงงาน และการชดเชยอุณหภูมิยังคงมีผลกับอัตราการหมุน ที่ไม่ได้ปรับเทียบ เครื่องวัดการหมุนมีประโยชน์สำหรับข้อมูลการวางแนวภายหลังการประมวลผลและการรวม โดยทั่วไปแล้ว gyroscope_event.values[0] จะอยู่ใกล้กับ uncalibrated_gyroscope_event.values[0] - uncalibrated_gyroscope_event.values[3] นั่นคือ

calibrated_x ~= uncalibrated_x - bias_estimate_x

หมายเหตุ: เซ็นเซอร์ที่ไม่ได้ปรับเทียบจะให้ผลดิบมากกว่า และอาจ มีการให้น้ำหนักพิเศษอยู่บ้าง แต่การวัดผลมีการข้ามจากการแก้ไขผ่านการแก้ไขน้อยกว่า การเทียบมาตรฐาน แอปพลิเคชันบางอย่างอาจต้องการให้ผลลัพธ์ที่ไม่มีการปรับเทียบเหล่านี้ราบรื่นและมากกว่า เชื่อถือได้ ตัวอย่างเช่น หากแอปพลิเคชันพยายามดำเนินการฟิวชันเซ็นเซอร์ของตนเอง การเริ่มใช้การปรับเทียบอาจทำให้ผลลัพธ์ผิดเพี้ยนไปได้

นอกจากอัตราการหมุนแล้ว เครื่องวัดการหมุนที่ไม่ได้ปรับยังให้ค่าประมาณ ลอยไปรอบๆ แต่ละแกน โค้ดต่อไปนี้แสดงวิธีรับอินสแตนซ์ของค่าเริ่มต้น เครื่องวัดการหมุนที่ไม่ได้ปรับเทียบ:

Kotlin

val sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
val sensor: Sensor? = sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE_UNCALIBRATED)

Java

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

ตัวอย่างโค้ดเพิ่มเติม

สาธิตเพิ่มเติมเกี่ยวกับตัวอย่าง BatchStepSensor การใช้ API ที่ระบุไว้ในหน้านี้

คุณควรอ่าน