본문 바로가기

open coding

open coding. 안드로이드 스튜디오 방위 측정하기/ direction finder = 마그네틱필드에+가속도센서

반응형

마그네틱필드에 가속도센서 같이 하면 정확한 방위측정가능.

 동 + 서 - 

범위 -180~+180

........................................

1. Manifest : 스크린 고정(방향측정해야하니)

screenOrientation = "portrait"

2.

센서 data 받기 listener

(magnetic field, acceleration sensor 두개)

3.

나침반 이미지이용(저작권문제로 임시이미지 이용)

-image.setRoation(360 - 방위값) : 방위값만큼 이미지가 회전함.

- 이미지가 북쪽방향을 가리키며 돌아가게 360- 방위값.

- 우리가알고 있는 동서남북방향.

 

<Manifest> screenOrientation = "portrait"

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.www.orientation">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity"
            android:screenOrientation="portrait">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

<MainActivity>

package com.www.orientation;

import androidx.appcompat.app.AppCompatActivity;

import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

    //define variables
    TextView textView;
    ImageView imageView;

    SensorManager manager;
    SensorListener listener;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        textView = findViewById(R.id.textView);
        imageView = findViewById(R.id.imageView);
        imageView.setImageResource(R.drawable.ic_launcher_foreground);  //image setting

        manager = (SensorManager)getSystemService(SENSOR_SERVICE); //각 객체설정
        listener = new SensorListener();

    }//finish

//sensor start method -> onclick도 설정
    public void startSensor(View view){

        Sensor sensor1 = manager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);    //가속도 센서
        Sensor sensor2 = manager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);    //Magnetic센서
        //아래 만들었던 리스너 연결
        manager.registerListener(listener, sensor1, SensorManager.SENSOR_DELAY_UI);
        manager.registerListener(listener, sensor2, SensorManager.SENSOR_DELAY_UI);

    }

 //sensor stop method -> onclick 도 설정
    public void stopSensor(View view){
        manager.unregisterListener(listener);
    }



//sensor data 받기 listener 설정 (Magnetic field, acceleration sensor 두개)
    class SensorListener implements SensorEventListener {
        //각 센터 측정된 값 담을 배열
        float [] accVlaue = new float[3];
        float [] magVlaue = new float[3];

        boolean isGetAcc = false;
        boolean isGetMag = false;

        @Override
        public void onSensorChanged(SensorEvent event) {//센서변화
           //sensor 타입 구분
            int type = event.sensor.getType();

            switch (type){
                case Sensor.TYPE_ACCELEROMETER : //가속센서 라면
                    System.arraycopy(event.values,0, accVlaue, 0, event.values.length);
                    isGetAcc = true;
                    break;
                case Sensor.TYPE_MAGNETIC_FIELD : //마그네틱 필드 라면
                    System.arraycopy(event.values,0, magVlaue, 0, event.values.length);
                    isGetMag = true;
                    break;
            }
            //두가지 data 받는다면 -> 방위값
            if(isGetAcc == true && isGetMag == true){
                //행렬 계산위해 사용할 배열
                float [] R = new float[9];
                float [] I = new float[9];
                //행렬계산
                SensorManager.getRotationMatrix(R,I, accVlaue,magVlaue);
                //계산된 결과(R) -> 방위값으로 환산
                float [] values = new float[3];
                SensorManager.getOrientation(R, values);

                //방위값(라디언단위) -> 각도단위로 변경
                //아래는 계기판 용어들이다.
                float azimuth = (float) Math.toDegrees(values[0]); // 방위값(-180 ~ +180)
                float pitch = (float) Math.toDegrees(values[1]);    //좌우기울기 값
                float roll = (float) Math.toDegrees(values[2]);     //앞뒤 기울기 값

                if(azimuth < 0){
                    azimuth += 360;     //범위가 -180~180이라 -값은 양수값으로 변환.
                }

                textView.setText("방위값 : "+azimuth + "\n");
                textView.append("좌우 기울기 값 : "+pitch  + "\n");
                textView.append("앞뒤 기울기 값 : "+roll + "\n");

                //이미지로도 방위값 나타내기
                imageView.setRotation(360 - azimuth);   //북쪽방향향해서 돌아가도록 360 -

            }
        }
        @Override
        public void onAccuracyChanged(Sensor sensor, int accuracy) {//감도변화

        }
    }//finish

}