1. 안드로이드 지자기 정보 활용

sensor magnetic

IPS 에서 지구 자기장 강도를 Finger Print 방식으로 실내에서 위치를 찾는다고 하는데 실제 Android 코드로 어떤 값이 어떤식으로 수집되고 사용되는지 알아보고자 하였다.

Android Sensor 에서는 자기장에 대하여 X,Y,Z 방향에 대한 자기장 강도를 리턴하는 것으로 확인하였으며, 각각의 값은 스마트폰의 회전 등 움직임에 크게 영향을 받기 때문에Finger Print 방식으로 지자기 값을 사용하고자 한다면 자기장의 총량 값을 사용하는 것이 맞는 것으로 보이며, 총량값은 간단하게 아래와 같이 계산된다. (그림에서 보면M값)

Math.sqrt( (Xvalue*Xvalue) + (Yvalue*Yvalue) + (Zvalue*Zvalue) );

K-060

fingerprint 방식으로 건물 전체의 지자기 값을 측정하여 그림으로 표현한다면 위와 같이 될 것 같다. 다만, 지자기 값은 같은 위치에서도 높낮이 방향등에 따라 상당히 예민하게 값이 바뀌기 때문에 이를 보정하기 위한 아이디어들이 필요할 것으로 보인다.

물론 지자기 값을 일반적인 건물에서 사용하기 위한 많은 알고리즘들이 수년전부터 사용화 되어 있다. 다만, 이러한 지자기 데이터는 철골 구조물이 고정적이라는 가정하에 사용되고 있어, 공장과 같이 철골 구조물이 이동하는 경우에는 정보 왜곡이 발생할 수 있어 애로 사항이 발생한다.

이러한 문제를 해결하기 위하여 앞으로 더 자료를 찾아보고자 하는 내용은 아래와 같은 철골 구조물에 의한 자기장 왜곡을 시뮬레이션 할 수 있는가 여부이다.

Magnetic%20Field%20Distortion-web

[참조 논문] Numerical analysis of the magnetic field for arbitrary magnetic susceptibility distributions in 3D  (35.9 달러 -_- ;; 유료..)

This paper demonstrates a method to calculate the magnetic field distribution in and around a 3D object when it is magnetized by a strong homogeneous magnetic field. The numerical technique is based on the explicit finite difference method. The calculation method is validated against analytical solutions for a sphere. As an application cylinders with different ratios of lengths and diameter are studied.

http://www.sciencedirect.com/science/article/pii/0730725X94923574

 

[예제]

public class TestOrientationActivity extends Activity implements SensorEventListener
{
// 센서 관련 객체
SensorManager m_sensor_manager;
Sensor m_acc_sensor, m_mag_sensor;

// 데이터를 저장할 변수들
float[] m_acc_data = null, m_mag_data = null;
float[] m_rotation = new float[9];
float[] m_result_data = new float[3];

@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

// 시스템서비스로부터 SensorManager 객체를 얻는다.
m_sensor_manager = (SensorManager)getSystemService(SENSOR_SERVICE);

// SensorManager 를 이용해서 가속센서와 자기장 센서 객체를 얻는다.
m_acc_sensor = m_sensor_manager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
m_mag_sensor = m_sensor_manager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
}

// 해당 액티비티가 포커스를 얻으면 가속 데이터와 자기장 데이터를 얻을 수 있도록
// 리스너를 등록한다.
protected void onResume() {
super.onResume();
m_check_count = 0;

// 센서 값을 이 컨텍스트에서 받아볼 수 있도록 리스너를 등록한다.
m_sensor_manager.registerListener(this, m_acc_sensor, SensorManager.SENSOR_DELAY_UI);
m_sensor_manager.registerListener(this, m_mag_sensor, SensorManager.SENSOR_DELAY_UI);
}

// 측정한 값을 전달해주는 메소드.
public void onSensorChanged(SensorEvent event)
{
if(event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
m_acc_data = event.values.clone();
} else if(event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {
m_mag_data = event.values.clone();
}

// 데이터가 존재하는 경우
if(m_acc_data != null && m_mag_data != null) {
// 가속 데이터와 자기장 데이터로 회전 매트릭스를 얻는다.
SensorManager.getRotationMatrix(m_rotation, null, m_acc_data, m_mag_data);
// 회전 매트릭스로 방향 데이터를 얻는다.
SensorManager.getOrientation(m_rotation, m_result_data);

(float)Math.toDegrees(m_result_data[0]);  //방위
(float)Math.toDegrees(m_result_data[1]);  //경사
(float)Math.toDegrees(m_result_data[2]);  //회전

m_mag_data[0] ; // 자기장 X 방향
m_mag_data[1] ; // 자기장 Y 방향
m_mag_data[2] ; // 자기장 Z 방향

//자기장 총량의 값은 0 ~ 200 , 실질적으로 지구에서는 20 ~ 70
double teslaXYZ = Math.sqrt((m_mag_data[0] *m_mag_data[0] )+(m_mag_data[1] *m_mag_data[1] )+(m_mag_data[2] *m_mag_data[2] ));

…. (중략)

 

Categories: Android

Leave a Reply

Your email address will not be published. Required fields are marked *