안드로이드에서 제공하는 가속도 센서는 2개가 있습니다.
이 센서들에 대해서 간단하게 테스트를 해보았습니다.
1. 가속도 센서
가속도 센서(TYPE_ACCELEROMETER)는 중력 가속도와 관계가 있습니다.
이를 확인 하려면 가속도 센서를 켜고 핸드폰을 이리저리 굴려보면 알 수 있습니다.
1.1 좌표에 맞추어 핸드폰 기울이기
간단히 테스트를 해보면 아래 그림과 같은 값을 얻을 수 있습니다.
아주 안정적인 상태에서 테스트 하면 Total Gravity가 9.8m/s² 값이겠지만 캡처 사진은 오차가 많네요. 수전증인가
그림 |
좌표 값 |
설명 |
z |
x:0, y:0, z:9.8 |
- 책상위에 핸드폰을 놓은 경우, 중력가속도 작용 |
-z |
x:0, y:0, z:-9.8 |
- 핸드폰을 책상 위에 뒤집어 놓은 경우, 마이너스(-)중력 가속도 |
x |
x:-9.8, y:0, z:0 |
- 핸드폰 우측 면을 기준으로 90도 세운경우, 중력가속도 x축 적용. - 핸드폰 좌측 면을 기준으로 90도 세우면 값은 양수(+) 중력가속도 |
y |
x:0, y:0-9.8 z:0 |
- 핸드폰을 상단면을 기준으로 90도 세운경우, 중력가속도 y축 적용. - 핸드폰을 하단면을 기준으로 90도 세운경우, 양수(+) 중력가속도. |
핸드폰을 x, y축을 기준으로 했을 경우의 반대 방향에 대한 그림은 생략 했습니다.
1.2 임의 방향으로 핸드폰 기울이기
지금까지는 직각 방향에 대한 내용이고 만일 핸드폰을 비스듬하게 놓으면 어떤 값을 나타 낼까요?
중력가속도는 9.8로 일정하게 작용하기 때문에 기울어진 각도 만큼
z축이 가지고 있던 9.8의 값을
x축과 y축이 나누어 받게 됩니다.
어째든 결과는 총 가속도 값이 9.8로 항상 동일 합니다.
피타고라스의 정리에 의해 직각삼각형의 빗변의 길이를 구하는 공식을 참고하면
직각 사각형의 크기도 구할 수 있습니다.
그러면 기울어진 핸드폰의 총 가속도 크기는 각 변의 제곱을 더한 값을 제곱근 하면 됩니다.
핸드폰 좌표 그림에서 보듯이 중력가속도는 지구 중심을 향하기 때문에 양(+)의 좌표 값이 반대로 됩니다.
2. 가속도 센서 중력 영향 제거
가속도 센서가 중력의 영향을 받기 때문에 실제 응용 프로그램을 만들려면 중력가속도에 대한
값을 상쇄시켜줘야 합니다.
우리가 생활 하는데 마치 중력이 없는 것 처럼 해야 한다는 것이지요.
게임을 만들때는 중력값을 달처럼 해서 작업한다고 하는데 안해봐서 모르겠지만 잼있겠네요.
private float accX, accY, accZ, tempX, tempY, tempZ; private float alpha = 0.8f; tempX = alpha * tempX + (1 - alpha) * event.values[0]; tempY = alpha * tempY + (1 - alpha) * event.values[1]; tempZ = alpha * tempZ + (1 - alpha) * event.values[2]; accX = event.values[0] - tempX; accY = event.values[1] - tempY; accZ = event.values[2] - tempZ;
이렇게 하면 x축, y축, z축의 값이 0가 되어 속도계나 다른 작업에 사용할 수 있습니다.
3. 선형 가속도 센서
그런데 구글에서는 중력가속도를 제거한 가속도 센서를 제공하고 있습니다.
그 센서는 TYPE_LINEAR_ACCELERATION 이것 입니다.
TYPE_LINEAR_ACCELERATION 센서에 대한 구글의 설명을 살펴볼까요?
구글 사이트에서 그대로 일부를 뜯어와서 밑줄만 그어봤습니다.
TYPE_ACCELEROMETER는 중력가속도가 포함되어 있고
TYPE_LINEAR_ACCELERATION는 중력가속도를 제거한 값이라는 군요.
4. 가속도 센서 비교
그럼 이 3가지 경우에 대해서 한번에 다 몰아서 비교를 해보도록 하겠습니다.
우선 결과를 보도록 하겠습니다.
제일 상단이 TYPE_ACCELEROMETER 센서 값을 그대로 보여주는 것이고
두번째 값이 TYPE_ACCELEROMETER 센서 값에서 중력을 제거한 경우
마지막이 TYPE_LINEAR_ACCELERATION 센서 값입니다.
두번째와 세번째 값이 동일(제 핸드폰기준)한 것을 알 수 있습니다.
5. 가속도 센서 프로젝트
이번에도 activity_main.xml 과 MainActivity.java 두개의 파일로 구성되어 있습니다.
프로젝트를 적당히 하나 만드시고 작업하면 됩니다.
만들기 싫으면 소스를 받아서 테스트 하거나 APK 파일을 받아 사용해도 됩니다.
5.1 Layout
결과들을 보여줄 TexvView를 13개
만들어 줍니다.
쓸데없이 소스만 깁니다.
activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <TextView android:id="@+id/tvTitle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Accelerometer Compare" android:layout_marginTop="10dp" android:textSize="30dp" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" /> <TextView android:id="@+id/tvgXaxis" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintTop_toBottomOf="@+id/tvTitle" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" android:textSize="25dp" android:text="X axis : 0" /> <TextView android:id="@+id/tvgYaxis" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintTop_toBottomOf="@+id/tvgXaxis" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" android:textSize="25dp" android:text="Y axis : 0" /> <TextView android:id="@+id/tvgZaxis" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintTop_toBottomOf="@+id/tvgYaxis" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" android:textSize="25dp" android:text="Z axis : 0" /> <TextView android:id="@+id/tvgTotal" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintTop_toBottomOf="@+id/tvgZaxis" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" android:textSize="25dp" android:text="Speed : 0" /> <TextView android:id="@+id/tvXaxis" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintTop_toBottomOf="@+id/tvgTotal" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" android:textSize="25dp" android:text="X axis : 0" /> <TextView android:id="@+id/tvYaxis" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintTop_toBottomOf="@+id/tvXaxis" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" android:textSize="25dp" android:text="Y axis : 0" /> <TextView android:id="@+id/tvZaxis" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintTop_toBottomOf="@+id/tvYaxis" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" android:textSize="25dp" android:text="Z axis : 0" /> <TextView android:id="@+id/tvTotal" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintTop_toBottomOf="@+id/tvZaxis" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" android:textSize="25dp" android:text="Speed : 0" /> <TextView android:id="@+id/tvlXaxis" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintTop_toBottomOf="@+id/tvTotal" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" android:textSize="25dp" android:text="X axis : 0" /> <TextView android:id="@+id/tvlYaxis" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintTop_toBottomOf="@+id/tvlXaxis" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" android:textSize="25dp" android:text="Y axis : 0" /> <TextView android:id="@+id/tvlZaxis" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintTop_toBottomOf="@+id/tvlYaxis" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" android:textSize="25dp" android:text="Z axis : 0" /> <TextView android:id="@+id/tvlTotal" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintTop_toBottomOf="@+id/tvlZaxis" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" android:textSize="25dp" android:text="Speed : 0" /> </android.support.constraint.ConstraintLayout>
5.2 Java Source
MainActivity.java
가속도 센서 2개의 값을 구하고 중력가속도를 제거하는 값을 구하는 프로그램 입니다.
위에서 설명을 하여 추가적인 설명이 필요없이 보시면 알 수 있습니다.
package com.example.desk.accelercompare; import android.content.Context; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.widget.TextView; public class MainActivity extends AppCompatActivity implements SensorEventListener { private SensorManager sensorManager; private Sensor accelerSensor; private Sensor linearAccelerSensor; private float gAccX, gAccY, gAccZ, accX, accY, accZ, lAccX, lAccY, lAccZ ; private float tempX, tempY, tempZ; private double gTotal, total, lTotal; private long lastUpdate = 0; private float alpha = 0.8f; TextView tvgXaxis, tvgYaxis, tvgZaxis, tvXaxis, tvYaxis, tvZaxis, tvlXaxis, tvlYaxis, tvlZaxis, tvgTotal, tvTotal, tvlTotal; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tvgXaxis = (TextView)findViewById(R.id.tvgXaxis); tvgYaxis = (TextView)findViewById(R.id.tvgYaxis); tvgZaxis = (TextView)findViewById(R.id.tvgZaxis); tvXaxis = (TextView)findViewById(R.id.tvXaxis); tvYaxis = (TextView)findViewById(R.id.tvYaxis); tvZaxis = (TextView)findViewById(R.id.tvZaxis); tvlXaxis = (TextView)findViewById(R.id.tvlXaxis); tvlYaxis = (TextView)findViewById(R.id.tvlYaxis); tvlZaxis = (TextView)findViewById(R.id.tvlZaxis); tvgTotal = (TextView)findViewById(R.id.tvgTotal); tvTotal = (TextView)findViewById(R.id.tvTotal); tvlTotal = (TextView)findViewById(R.id.tvlTotal); sensorManager = (SensorManager)getSystemService(Context.SENSOR_SERVICE); accelerSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); linearAccelerSensor = sensorManager.getDefaultSensor(Sensor.TYPE_LINEAR_ACCELERATION); } @Override protected void onResume() { super.onResume(); sensorManager.registerListener(this, accelerSensor, SensorManager.SENSOR_DELAY_NORMAL); sensorManager.registerListener(this, linearAccelerSensor, SensorManager.SENSOR_DELAY_NORMAL); } @Override protected void onPause() { super.onPause(); sensorManager.unregisterListener(this); } @Override public void onSensorChanged(SensorEvent event) { if(event.sensor == accelerSensor) { //include gravity gAccX = event.values[0]; gAccY = event.values[1]; gAccZ = event.values[2]; tempX = alpha * tempX + (1 - alpha) * event.values[0]; tempY = alpha * tempY + (1 - alpha) * event.values[1]; tempZ = alpha * tempZ + (1 - alpha) * event.values[2]; accX = event.values[0] - tempX; accY = event.values[1] - tempY; accZ = event.values[2] - tempZ; gTotal = Math.sqrt(Math.pow(gAccX,2) + Math.pow(gAccY, 2) + Math.pow(gAccZ , 2)); total = Math.sqrt(Math.pow(accX,2) + Math.pow(accY, 2) + Math.pow(accZ , 2)); tvgXaxis.setText("X axis : " + String.format("%.2f", gAccX)); tvgYaxis.setText("Y axis : " + String.format("%.2f", gAccY)); tvgZaxis.setText("Z axis : " + String.format("%.2f", gAccZ)); tvgTotal.setText("Total Gravity : " + String.format("%.2f", gTotal) + " m/s\u00B2"); tvXaxis.setText("X axis : " + String.format("%.2f", accX)); tvYaxis.setText("Y axis : " + String.format("%.2f", accY)); tvZaxis.setText("Z axis : " + String.format("%.2f", accZ)); tvTotal.setText("Total Gravity : " + String.format("%.2f", total) + " m/s\u00B2"); } if(event.sensor == linearAccelerSensor) { //exclude gravity lAccX = event.values[0]; lAccY = event.values[1]; lAccZ = event.values[2]; lTotal = Math.sqrt(Math.pow(lAccX,2) + Math.pow(lAccY, 2) + Math.pow(lAccZ , 2)); tvlXaxis.setText("X axis : " + String.format("%.2f", lAccX)); tvlYaxis.setText("Y axis : " + String.format("%.2f", lAccY)); tvlZaxis.setText("Z axis : " + String.format("%.2f", lAccZ)); tvlTotal.setText("Total Gravity : " + String.format("%.2f", lTotal) + " m/s\u00B2"); } } @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { } }
5.3 Source file
5.4 APK file
- copy coding -
'Android' 카테고리의 다른 글
안드로이드 진동 센서 테스트 (VIBRATOR_SERVICE) (0) | 2018.10.31 |
---|---|
안드로이드 중력 센서 (TYPE_GRAVITY) (0) | 2018.10.13 |
안드로이드 자기장 센서/금속 탐지기 테스트 (TYPE_MAGNETIC_FIELD) (0) | 2018.10.09 |
안드로이드 장치의 회전 방향 확인 (TYPE_GYROSCOPE) (0) | 2018.10.01 |
안드로이드 광 센서 테스트 (TYPE_LIGHT) (0) | 2018.09.27 |