找到合适的 Android 传感器并使用它们

Finding the right kind of Android sensors and using them

我尝试在 google 和此处搜索我的问题的解决方案,我认为之前没有人问过(或者我在搜索中使用了错误的词?^ ^')

无论如何,这就是我想要的:一个可以根据平板电脑的方向旋转的 OpenGL 表面视图(例如显示一个立方体)。到目前为止,我猜没有什么难的,我有下面的代码可以很好地工作

public class RotationVectorDemo extends Activity {
private GLSurfaceView mGLSurfaceView;
private SensorManager mSensorManager;
private MyRenderer mRenderer;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // Get an instance of the SensorManager
    mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
    // Create our Preview view and set it as the content of our
    // Activity
    mRenderer = new MyRenderer();
    mGLSurfaceView = new GLSurfaceView(this);
    mGLSurfaceView.setRenderer(mRenderer);
    setContentView(mGLSurfaceView);
}
@Override
protected void onResume() {
    // Ideally a game should implement onResume() and onPause()
    // to take appropriate action when the activity looses focus
    super.onResume();
    mRenderer.start();
    mGLSurfaceView.onResume();
}
@Override
protected void onPause() {
    // Ideally a game should implement onResume() and onPause()
    // to take appropriate action when the activity looses focus
    super.onPause();
    mRenderer.stop();
    mGLSurfaceView.onPause();
}
class MyRenderer implements GLSurfaceView.Renderer, SensorEventListener {
    private Cube mCube;
    private Sensor mRotationVectorSensor;
    private final float[] mRotationMatrix = new float[16];
    public MyRenderer() {
        // find the rotation-vector sensor
        mRotationVectorSensor = mSensorManager.getDefaultSensor(
                Sensor.TYPE_ROTATION_VECTOR);
        mCube = new Cube();
        // initialize the rotation matrix to identity
        mRotationMatrix[ 0] = 1;
        mRotationMatrix[ 4] = 1;
        mRotationMatrix[ 8] = 1;
        mRotationMatrix[12] = 1;
    }
    public void start() {
        // enable our sensor when the activity is resumed, ask for
        // 10 ms updates.
        mSensorManager.registerListener(this, mRotationVectorSensor, 10000);
    }
    public void stop() {
        // make sure to turn our sensor off when the activity is paused
        mSensorManager.unregisterListener(this);
    }
    public void onSensorChanged(SensorEvent event) {
        // we received a sensor event. it is a good practice to check
        // that we received the proper event
        if (event.sensor.getType() == Sensor.TYPE_ROTATION_VECTOR) {
            // convert the rotation-vector to a 4x4 matrix. the matrix
            // is interpreted by Open GL as the inverse of the
            // rotation-vector, which is what we want.
            SensorManager.getRotationMatrixFromVector(
                    mRotationMatrix , event.values);
        }
    }
    public void onDrawFrame(GL10 gl) {
        // clear screen
        gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
        // set-up modelview matrix
        gl.glMatrixMode(GL10.GL_MODELVIEW);
        gl.glLoadIdentity();
        gl.glTranslatef(0, 0, -3.0f);
        gl.glMultMatrixf(mRotationMatrix, 0);
        // draw our object
        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
        gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
        mCube.draw(gl);
    }
    public void onSurfaceChanged(GL10 gl, int width, int height) {
        // set view-port
        gl.glViewport(0, 0, width, height);
        // set projection matrix
        float ratio = (float) width / height;
        gl.glMatrixMode(GL10.GL_PROJECTION);
        gl.glLoadIdentity();
        gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10);
    }
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        // dither is enabled by default, we don't need it
        gl.glDisable(GL10.GL_DITHER);
        // clear screen in white
        gl.glClearColor(1,1,1,1);
    }
    class Cube {
        // initialize our cube
        private FloatBuffer mVertexBuffer;
        private FloatBuffer mColorBuffer;
        private ByteBuffer  mIndexBuffer;
        public Cube() {
            final float vertices[] = {
                    -1, -1, -1,      1, -1, -1,
                    1,  1, -1,      -1,  1, -1,
                    -1, -1,  1,      1, -1,  1,
                    1,  1,  1,     -1,  1,  1,
            };
            final float colors[] = {
                    0,  0,  0,  1,  1,  0,  0,  1,
                    1,  1,  0,  1,  0,  1,  0,  1,
                    0,  0,  1,  1,  1,  0,  1,  1,
                    1,  1,  1,  1,  0,  1,  1,  1,
            };
            final byte indices[] = {
                    0, 4, 5,    0, 5, 1,
                    1, 5, 6,    1, 6, 2,
                    2, 6, 7,    2, 7, 3,
                    3, 7, 4,    3, 4, 0,
                    4, 7, 6,    4, 6, 5,
                    3, 0, 1,    3, 1, 2
            };
            ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length*4);
            vbb.order(ByteOrder.nativeOrder());
            mVertexBuffer = vbb.asFloatBuffer();
            mVertexBuffer.put(vertices);
            mVertexBuffer.position(0);
            ByteBuffer cbb = ByteBuffer.allocateDirect(colors.length*4);
            cbb.order(ByteOrder.nativeOrder());
            mColorBuffer = cbb.asFloatBuffer();
            mColorBuffer.put(colors);
            mColorBuffer.position(0);
            mIndexBuffer = ByteBuffer.allocateDirect(indices.length);
            mIndexBuffer.put(indices);
            mIndexBuffer.position(0);
        }
        public void draw(GL10 gl) {
            gl.glEnable(GL10.GL_CULL_FACE);
            gl.glFrontFace(GL10.GL_CW);
            gl.glShadeModel(GL10.GL_SMOOTH);
            gl.glVertexPointer(3, GL10.GL_FLOAT, 0, mVertexBuffer);
            gl.glColorPointer(4, GL10.GL_FLOAT, 0, mColorBuffer);
            gl.glDrawElements(GL10.GL_TRIANGLES, 36, GL10.GL_UNSIGNED_BYTE, mIndexBuffer);
        }
    }
    public void onAccuracyChanged(Sensor sensor, int accuracy) {
    }
}

}

但是,当我锁定屏幕、四处移动并随后解锁时,立方体也移动了。这是合乎逻辑的,我完全理解为什么。然而,我想知道是否有可能避免这种情况,比如重置传感器或类似的东西,以及我该怎么做。

我不确定我是否使用了好的传感器,是否应该更改它,或者它是否可以在代码中解决。请耐心等待,因为我才刚刚开始使用 android 传感器。

基本上,这个问题与我在一个更大的应用程序中遇到的另一个问题有关,但我发现使用这个示例来尝试解决这个问题会更简单。但是,如果你想知道我的更大应用程序中的问题是什么,除了移动立方体,人们可以使用他们的手指 (finger_mode) 或传感器 (phone_mode) 之外,它基本上是相同的。我想要的是以某种方式能够用手指旋转立方体,而无需注意传感器,当我进入 sensor_mode 时,它们不会仅仅因为它们被激活而改变立方体的方向。我不确定是否清楚,如果不清楚,让我知道。

我猜,因为我使用触摸来修改 OpenGL 使用的旋转矩阵,所以可能可以对旋转矩阵执行一些操作来解决我的问题。或者这可能只是传感器问题。也许到目前为止我都不知道,但这些是我一直在尝试使用的不同解决方案。

在此先感谢您帮助我解决这个问题。

最佳,

所以旋转矢量绝对是一种很好的传感器。加速度计和陀螺仪对我想做的事情没有任何帮助。

但是我仍然需要弄清楚如何处理我现在拥有的旋转矩阵。