ниже вы увидите мой класс диспетчера датчиков. У меня он отлично работает с виртуальным компасом, но при нажатии я пытаюсь получить значение азимута, которое, согласно документации Google, должно возвращать 0 = север, 90 = восток, 180 = юг , а 270 = запад...
мое приложение настроено только на ландшафтный режим..
забавно, если
мой телефон держится в ПОРТРЕТ я получаю: 90 для севера, 180 для востока, -90 для юга и 0 для запада
если я держу его в режиме lanscape: от -40 до -60 для севера около 30 для востока -12 для юга -156 для запада
тот же код вращает матричный компас openGl, который виден, и именно так я сравниваю числа с тем, что магнитометр на самом деле считает магнитным севером .. я так запутался .. кто-нибудь, пожалуйста, помогите.
мой класс датчиков:
public void start(Context context,final int displayOrientation) {
listener = new SensorEventListener() {
private int displayOri = displayOrientation;
public void onAccuracyChanged(Sensor arg0, int arg1){}
public void onSensorChanged(SensorEvent evt) {
int type=evt.sensor.getType();
if (type == Sensor.TYPE_MAGNETIC_FIELD) {
orientation[0]=(orientation[0]*1+evt.values[0])*0.5f;
orientation[1]=(orientation[1]*1+evt.values[1])*0.5f;
orientation[2]=(orientation[2]*1+evt.values[2])*0.5f;
} else if (type == Sensor.TYPE_ACCELEROMETER) {
acceleration[0]=(acceleration[0]*2+evt.values[0])*0.33334f;
acceleration[1]=(acceleration[1]*2+evt.values[1])*0.33334f;
acceleration[2]=(acceleration[2]*2+evt.values[2])*0.33334f;
}
if ((type==Sensor.TYPE_MAGNETIC_FIELD) || (type==Sensor.TYPE_ACCELEROMETER)) {
float newMat[]=new float[16];
//Toast toast = Toast.makeText(ctx.getApplicationContext(), "accel", Toast.LENGTH_SHORT);
//toast.show();
SensorManager.getRotationMatrix(newMat, null, acceleration, orientation);
if(displayOri==0||displayOri==2){
SensorManager.remapCoordinateSystem(newMat,SensorManager.AXIS_X*-1, SensorManager.AXIS_MINUS_Y*-1,newMat);
}else{
SensorManager.remapCoordinateSystem(newMat,SensorManager.AXIS_Y, SensorManager.AXIS_MINUS_X,newMat);
}
matrix=newMat;
SensorManager.getOrientation (newMat, orientationValues);
}
}
};
sensorMan = (SensorManager)context.getSystemService(Context.SENSOR_SERVICE);
sensorAcce = sensorMan.getSensorList(Sensor.TYPE_ACCELEROMETER).get(0);
sensorMagn = sensorMan.getSensorList(Sensor.TYPE_MAGNETIC_FIELD).get(0);
//sensorOri = sensorMan.getSensorList(Sensor.TYPE_ORIENTATION).get(0);
sensorMan.registerListener(listener, sensorAcce, SensorManager.SENSOR_DELAY_UI);
sensorMan.registerListener(listener, sensorMagn, SensorManager.SENSOR_DELAY_UI);
//sensorMan.registerListener(listener, sensorOri, SensorManager.SENSOR_DELAY_UI);
}
public float[] getMatrix() {
return matrix;
}
public float getRoll(){
return roll;
}
public float[] getACC(){
return acceleration;
}
public float[] getORI(){
return orientationValues;
}
public float getIncline(){
return sensorMan.getInclination(matrix);
}
public void finish() {
sensorMan.unregisterListener(listener);
}
public void onPause() {
sensorMan.unregisterListener(listener);
}
public void onResume(){
sensorMan.registerListener(listener, sensorAcce, SensorManager.SENSOR_DELAY_UI);
sensorMan.registerListener(listener, sensorMagn, SensorManager.SENSOR_DELAY_UI);
//sensorMan.registerListener(listener, sensorOri, SensorManager.SENSOR_DELAY_UI);
}
}
Документация гугла:
*SENSOR_ORIENTATION, SENSOR_ORIENTATION_RAW: все значения представляют собой углы в градусах. values[0]: Азимут, вращение вокруг оси Z (0‹=азимут‹360). 0 = север, 90 = восток, 180 = юг, 270 = запад значения[1]: шаг, вращение вокруг оси X (-180‹=шаг‹=180), с положительными значениями, когда ось z движется к оси y- ось. values[2]: Roll, вращение вокруг оси Y (-90‹=roll‹=90), с положительными значениями, когда ось z движется к оси x. Обратите внимание, что это определение рыскания, тангажа и крена отличается от традиционного определения, используемого в авиации, где ось X проходит вдоль длинной стороны самолета (от хвоста к носу). обратите внимание, что я не использую sensor.orientation сейчас, так как он говорит, что метод, который я использую сейчас, более точен*
Я также включаю класс openGL, который создает точный компас, используя те же данные датчика, с функцией длительного нажатия, называемой newTAg, которая выдает мне данные датчика в тосте.
тост выглядит так:
Toast.makeText(getContext(), "INLCINE:"+phoneOri.getIncline()+" azimuth:"+Math.toDegrees(tagOri[0])+" pitch:"+Math.toDegrees(tagOri[1])+" roll:"+Math.toDegrees(tagOri[2]),Toast.LENGTH_LONG).show();
public GLLayer(Context context, int orientation) {
super(context);
this.context = context;
//this.square = new Square();
this.cRing = new Circle();
this.cNeedle = new CompassNeedle();
this.mNorth = new MarkerNorth();
this.mEast = new MarkerEast();
this.mSouth = new MarkerSouth();
this.mWest = new MarkerWest();
this.mSWest = new MarkerSouthWest();
this.mSEast = new MarkerSouthEast();
this.mNWest = new MarkerNorthWest();
this.mNEast = new MarkerNorthEast();
this.mtag = new tagImage();
phoneOri=new PhoneOrientation(context); // sensor manager and interpreter
// settings for translucent glView
this.setEGLConfigChooser(8, 8, 8, 8, 16, 0);
this.getHolder().setFormat(PixelFormat.TRANSLUCENT);
// set render to inline
this.setRenderer(this);
phoneOri.start(context, orientation);
}
@Override
public void onDrawFrame(GL10 gl) {
gl.glEnable(GL10.GL_TEXTURE_2D);
// clear Screen and Depth Buffer
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
// Reset the Modelview Matrix
gl.glLoadIdentity();
//GLU.gluLookAt(gl, eyeX, eyeY, eyeZ, centerX, centerY, centerZ, upX, upY, upZ);
GLU.gluLookAt(gl,0, 0, 0, 0, 0, 0, 0, 0, 0);
//GLU.gluLookAt(gl, 90.0f, 1.0f, 5.0f, 0.0f, 0.0f, 0.0f, 0, 1.0f, 0);
float floatMat[]=phoneOri.getMatrix();
gl.glMatrixMode(GL10.GL_MODELVIEW);
//
//gl.glTranslatef(0,0,-200.0f);
//cRing.draw(gl);
//DrawCompass Needle and Markers
gl.glLoadMatrixf(floatMat, 0);
for(int i=0;i<tags.size();i++){
gl.glPushMatrix();
//GLU.gluLookAt(gl,0, 0, 0, 0, 0, 0, 0, 0, 0);
//float angle = phoneOri.sensorMan,getAngleChange();
gl.glRotatef(90,2, 0,0);
mtag.draw(gl);
gl.glLoadMatrixf(floatMat,0);
}
gl.glPushMatrix();
gl.glTranslatef(0,0,-10.0f);
cNeedle.draw(gl);
gl.glLoadMatrixf(floatMat,0);
//Draw compass ring
//gl.glPushMatrix();
gl.glTranslatef(0,0,10.0f);
cRing.draw(gl);
//Draw South
gl.glTranslatef(0.0f,-150.0f,-10.0f);
mSouth.draw(gl);
//Draw West
gl.glTranslatef(-150.0f,150.0f,0.0f);
mWest.draw(gl);
//DrawNorth
gl.glTranslatef(150.0f,150.0f,0.0f);
mNorth.draw(gl);
//DrawEast
gl.glTranslatef(150.0f,-150.0f,0.0f);
mEast.draw(gl);
//SW
gl.glTranslatef(-225.0f, -75.0f, 0.0f);
mSWest.draw(gl);
// NW
gl.glTranslatef(0.0f,150.f,0);
mNWest.draw(gl);
gl.glTranslatef(150.0f, 0f, 0f);
mNEast.draw(gl);
gl.glTranslatef(0.0f,-150.0f,0.0f);
mSEast.draw(gl);
// Drawing
//gl.glNormal3f(0,0,1);
//gl.glTranslatef(0.0f,-150.0f,0.0f); // move 5 units INTO the screen
//square.draw(gl); // Draw the square
gl.glPushMatrix();
}
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
if(height == 0) { //Prevent A Divide By Zero By
height = 1; //Making Height Equal One
}
float ratio = (float) width / height;
gl.glViewport(0, 0, width, height); //Reset The Current Viewport
gl.glMatrixMode(GL10.GL_PROJECTION); //Select The Projection Matrix
gl.glLoadIdentity(); //Reset The Projection Matrix
//Calculate The Aspect Ratio Of The Window
//gl.glFrustumf(-ratio, ratio, -1, 1, 1, 100);
GLU.gluPerspective(gl, 35.0f, (float)width / (float)height, 5.0f, 200.0f);
gl.glMatrixMode(GL10.GL_MODELVIEW); //Select The Modelview Matrix
gl.glLoadIdentity(); //Reset The Modelview Matrix
GLU.gluLookAt(gl, 0, 1.0f, 5.0f, 0, 0, 0, 0, 1.0f, 0);
}
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig arg1) {
// Load the texture for the square
//square.loadGLTexture(gl, this.context);
cRing.loadGLTexture(gl, this.context);
cNeedle.loadGLTexture(gl, this.context);
mNorth.loadGLTexture(gl, this.context);
mEast.loadGLTexture(gl, this.context);
mSouth.loadGLTexture(gl, this.context);
mWest.loadGLTexture(gl, this.context);
mSWest.loadGLTexture(gl, this.context);
mNWest.loadGLTexture(gl, this.context);
mSEast.loadGLTexture(gl, this.context);
mNEast.loadGLTexture(gl, this.context);
gl.glEnable(GL10.GL_TEXTURE_2D); //Enable Texture Mapping ( NEW )
gl.glShadeModel(GL10.GL_SMOOTH); //Enable Smooth Shading
gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); //Black Background
gl.glClearDepthf(1.0f); //Depth Buffer Setup
gl.glEnable(GL10.GL_DEPTH_TEST); //Enables Depth Testing
gl.glDepthFunc(GL10.GL_LEQUAL); //The Type Of Depth Testing To Do
//Really Nice Perspective Calculations
//gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST);
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_SMOOTH);
}
@Override
public void onPreviewFrame(byte[] data, Camera camera) {
// TODO Auto-generated method stub
}
public void newTag(){
float tagOri[] = new float[3];
tagOri = phoneOri.getORI();
tags.add(phoneOri.getMatrix());
Toast.makeText(getContext(), "INLCINE:"+phoneOri.getIncline()+" azimuth:"+Math.toDegrees(tagOri[0])+" pitch:"+Math.toDegrees(tagOri[1])+" roll:"+Math.toDegrees(tagOri[2]),Toast.LENGTH_LONG).show();
}
}