getRotationMatrix 和 getOrientation 教程
我一直在努力使用 getOrientation 获取设备的实际方向。通过 TYPE_ACCELEROMETER 和 TYPE_MAGNETIC_FIELD 获取加速度计和磁场读数非常简单,就像通过 TYPE_ORIENTATION 获取方向一样。但是使用 getOrientation 根据世界坐标系获取方向。 此处有许多不错的教程 和 这里但我还没有把它们放在一起。为此,我正在开发一个应用程序,它可以简单地输出加速度计、磁场、原始方向数据和来自 getOrientation 的方向数据。我已附上代码,但它在我的手机上经常失败。有什么建议吗?
package com.sensorall;
import com.sensorall.R;
import android.hardware.*;
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
public class OrientationAccelerometer extends Activity {
SensorManager sensorManager;
float[] mGravs = new float[3];
float[] mGeoMags = new float[3];
float[] mRotationM = new float[16];
float[] mInclinationM = new float[16];
float[] mOrientation = new float[3];
float[] mOldOreintation = new float[3];
String[] mAccelerometer = new String[3];
String[] mMagnetic = new String[3];
String[] mRotation = new String[16];
String[] mInclination = new String[16];
String[] mOrientationString = new String[3];
String[] mOldOreintationString = new String[3];
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.orientationaccelerometer);
sensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
} /* End onCreate activity */
private SensorEventListener sensorEventListener = new SensorEventListener() {
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
/* Get the Sensors */
public void onSensorChanged(SensorEvent event) {
switch (event.sensor.getType()) {
case Sensor.TYPE_ACCELEROMETER:
System.arraycopy(event.values, 0, mGravs, 0, 3);
break;
case Sensor.TYPE_MAGNETIC_FIELD:
System.arraycopy(event.values, 0, mGeoMags, 0, 3);
break;
case Sensor.TYPE_ORIENTATION:
System.arraycopy(event.values, 0, mOldOreintation, 0, 3);
break;
default:
return;
}
// If mGravs and mGeoMags have values then find rotation matrix
if (mGravs != null && mGeoMags != null) {
// checks that the rotation matrix is found
boolean success = SensorManager.getRotationMatrix(mRotationM, mInclinationM, mGravs, mGeoMags);
if (success) {
/* getOrientation Values */
SensorManager.getOrientation(mRotationM, mOrientation);
for(int i=0; i<2; i++){
mAccelerometer[i] = Float.toString(mGravs[i]);
mMagnetic[i] = Float.toString(mGeoMags[i]);
mOrientationString[i] = Float.toString(mOrientation[i]);
mOldOreintationString[i] = Float.toString(mOldOreintation[i]);
}
/* Make everything text to show on device */
TextView xaxisAccelerometerText = (TextView)findViewById(R.id.xaxisAccelerometer);
xaxisAccelerometerText.setText(mAccelerometer[0]);
TextView yaxisAccelerometerText = (TextView)findViewById(R.id.yaxisAccelerometer);
yaxisAccelerometerText.setText(mAccelerometer[1]);
TextView zaxisAccelerometerText = (TextView)findViewById(R.id.zaxisAccelerometer);
zaxisAccelerometerText.setText(mAccelerometer[2]);
TextView xaxisMagneticText = (TextView)findViewById(R.id.xaxisMagnetic);
xaxisMagneticText.setText(mMagnetic[0]);
TextView yaxisMagneticText = (TextView)findViewById(R.id.yaxisMagnetic);
yaxisMagneticText.setText(mMagnetic[1]);
TextView zaxisMagneticText = (TextView)findViewById(R.id.zaxisMagnetic);
zaxisMagneticText.setText(mMagnetic[2]);
TextView xaxisOrientationText = (TextView)findViewById(R.id.xaxisOrientation);
xaxisOrientationText.setText(mOrientationString[0]);
TextView yaxisOrientationText = (TextView)findViewById(R.id.yaxisOrientation);
yaxisOrientationText.setText(mOrientationString[1]);
TextView zaxisOrientationText = (TextView)findViewById(R.id.zaxisOrientation);
zaxisOrientationText.setText(mOrientationString[2]);
TextView xaxisOldOrientationText = (TextView)findViewById(R.id.xaxisOldOrientation);
xaxisOldOrientationText.setText(mOldOreintationString[0]);
TextView yaxisOldOrientationText = (TextView)findViewById(R.id.yaxisOldOrientation);
yaxisOldOrientationText.setText(mOldOreintationString[1]);
TextView zaxisOldOrientationText = (TextView)findViewById(R.id.zaxisOldOrientation);
zaxisOldOrientationText.setText(mOldOreintationString[2]);
}else{
/* Make everything text to show on device even if getRotationMatrix fails*/
String matrixFailed = "Rotation Matrix Failed";
TextView xaxisAccelerometerText = (TextView)findViewById(R.id.xaxisAccelerometer);
xaxisAccelerometerText.setText(mAccelerometer[0]);
TextView yaxisAccelerometerText = (TextView)findViewById(R.id.yaxisAccelerometer);
yaxisAccelerometerText.setText(mAccelerometer[1]);
TextView zaxisAccelerometerText = (TextView)findViewById(R.id.zaxisAccelerometer);
zaxisAccelerometerText.setText(mAccelerometer[2]);
TextView xaxisMagneticText = (TextView)findViewById(R.id.xaxisMagnetic);
xaxisMagneticText.setText(mMagnetic[0]);
TextView yaxisMagneticText = (TextView)findViewById(R.id.yaxisMagnetic);
yaxisMagneticText.setText(mMagnetic[1]);
TextView zaxisMagneticText = (TextView)findViewById(R.id.zaxisMagnetic);
zaxisMagneticText.setText(mMagnetic[2]);
TextView xaxisOrientationText = (TextView)findViewById(R.id.xaxisOrientation);
xaxisOrientationText.setText(matrixFailed);
TextView yaxisOrientationText = (TextView)findViewById(R.id.yaxisOrientation);
yaxisOrientationText.setText(matrixFailed);
TextView zaxisOrientationText = (TextView)findViewById(R.id.zaxisOrientation);
zaxisOrientationText.setText(matrixFailed);
TextView xaxisOldOrientationText = (TextView)findViewById(R.id.xaxisOldOrientation);
xaxisOldOrientationText.setText(mOldOreintationString[0]);
TextView yaxisOldOrientationText = (TextView)findViewById(R.id.yaxisOldOrientation);
yaxisOldOrientationText.setText(mOldOreintationString[1]);
TextView zaxisOldOrientationText = (TextView)findViewById(R.id.zaxisOldOrientation);
zaxisOldOrientationText.setText(mOldOreintationString[2]);
}
}
}
};
@Override
protected void onResume() {
super.onResume();
sensorManager.registerListener(sensorEventListener, sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_NORMAL);
sensorManager.registerListener(sensorEventListener, sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD), SensorManager.SENSOR_DELAY_NORMAL);
sensorManager.registerListener(sensorEventListener, sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION), SensorManager.SENSOR_DELAY_NORMAL);
}
protected void onPause() {
super.onPause();
sensorManager.unregisterListener(sensorEventListener);
}
}
I have been struggling with getting the actual orientation of my device using getOrientation. Getting the accelerometer and magnetic field readings via TYPE_ACCELEROMETER and TYPE_MAGNETIC_FIELD is straightforward as is getting the orientation via TYPE_ORIENTATION. But getting the orientation according to the world coordinate-system using getOrientation. There are a number of good tutorials out there here and here but I have yet to put it all together. To that end I was developing an app that simply spit out the Accelerometer, Magnetic Field, raw Orientation data, and Orientation data from getOrientation. I have attached the code but it constantly fails on my phone. ANy suggestions?
package com.sensorall;
import com.sensorall.R;
import android.hardware.*;
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
public class OrientationAccelerometer extends Activity {
SensorManager sensorManager;
float[] mGravs = new float[3];
float[] mGeoMags = new float[3];
float[] mRotationM = new float[16];
float[] mInclinationM = new float[16];
float[] mOrientation = new float[3];
float[] mOldOreintation = new float[3];
String[] mAccelerometer = new String[3];
String[] mMagnetic = new String[3];
String[] mRotation = new String[16];
String[] mInclination = new String[16];
String[] mOrientationString = new String[3];
String[] mOldOreintationString = new String[3];
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.orientationaccelerometer);
sensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
} /* End onCreate activity */
private SensorEventListener sensorEventListener = new SensorEventListener() {
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
/* Get the Sensors */
public void onSensorChanged(SensorEvent event) {
switch (event.sensor.getType()) {
case Sensor.TYPE_ACCELEROMETER:
System.arraycopy(event.values, 0, mGravs, 0, 3);
break;
case Sensor.TYPE_MAGNETIC_FIELD:
System.arraycopy(event.values, 0, mGeoMags, 0, 3);
break;
case Sensor.TYPE_ORIENTATION:
System.arraycopy(event.values, 0, mOldOreintation, 0, 3);
break;
default:
return;
}
// If mGravs and mGeoMags have values then find rotation matrix
if (mGravs != null && mGeoMags != null) {
// checks that the rotation matrix is found
boolean success = SensorManager.getRotationMatrix(mRotationM, mInclinationM, mGravs, mGeoMags);
if (success) {
/* getOrientation Values */
SensorManager.getOrientation(mRotationM, mOrientation);
for(int i=0; i<2; i++){
mAccelerometer[i] = Float.toString(mGravs[i]);
mMagnetic[i] = Float.toString(mGeoMags[i]);
mOrientationString[i] = Float.toString(mOrientation[i]);
mOldOreintationString[i] = Float.toString(mOldOreintation[i]);
}
/* Make everything text to show on device */
TextView xaxisAccelerometerText = (TextView)findViewById(R.id.xaxisAccelerometer);
xaxisAccelerometerText.setText(mAccelerometer[0]);
TextView yaxisAccelerometerText = (TextView)findViewById(R.id.yaxisAccelerometer);
yaxisAccelerometerText.setText(mAccelerometer[1]);
TextView zaxisAccelerometerText = (TextView)findViewById(R.id.zaxisAccelerometer);
zaxisAccelerometerText.setText(mAccelerometer[2]);
TextView xaxisMagneticText = (TextView)findViewById(R.id.xaxisMagnetic);
xaxisMagneticText.setText(mMagnetic[0]);
TextView yaxisMagneticText = (TextView)findViewById(R.id.yaxisMagnetic);
yaxisMagneticText.setText(mMagnetic[1]);
TextView zaxisMagneticText = (TextView)findViewById(R.id.zaxisMagnetic);
zaxisMagneticText.setText(mMagnetic[2]);
TextView xaxisOrientationText = (TextView)findViewById(R.id.xaxisOrientation);
xaxisOrientationText.setText(mOrientationString[0]);
TextView yaxisOrientationText = (TextView)findViewById(R.id.yaxisOrientation);
yaxisOrientationText.setText(mOrientationString[1]);
TextView zaxisOrientationText = (TextView)findViewById(R.id.zaxisOrientation);
zaxisOrientationText.setText(mOrientationString[2]);
TextView xaxisOldOrientationText = (TextView)findViewById(R.id.xaxisOldOrientation);
xaxisOldOrientationText.setText(mOldOreintationString[0]);
TextView yaxisOldOrientationText = (TextView)findViewById(R.id.yaxisOldOrientation);
yaxisOldOrientationText.setText(mOldOreintationString[1]);
TextView zaxisOldOrientationText = (TextView)findViewById(R.id.zaxisOldOrientation);
zaxisOldOrientationText.setText(mOldOreintationString[2]);
}else{
/* Make everything text to show on device even if getRotationMatrix fails*/
String matrixFailed = "Rotation Matrix Failed";
TextView xaxisAccelerometerText = (TextView)findViewById(R.id.xaxisAccelerometer);
xaxisAccelerometerText.setText(mAccelerometer[0]);
TextView yaxisAccelerometerText = (TextView)findViewById(R.id.yaxisAccelerometer);
yaxisAccelerometerText.setText(mAccelerometer[1]);
TextView zaxisAccelerometerText = (TextView)findViewById(R.id.zaxisAccelerometer);
zaxisAccelerometerText.setText(mAccelerometer[2]);
TextView xaxisMagneticText = (TextView)findViewById(R.id.xaxisMagnetic);
xaxisMagneticText.setText(mMagnetic[0]);
TextView yaxisMagneticText = (TextView)findViewById(R.id.yaxisMagnetic);
yaxisMagneticText.setText(mMagnetic[1]);
TextView zaxisMagneticText = (TextView)findViewById(R.id.zaxisMagnetic);
zaxisMagneticText.setText(mMagnetic[2]);
TextView xaxisOrientationText = (TextView)findViewById(R.id.xaxisOrientation);
xaxisOrientationText.setText(matrixFailed);
TextView yaxisOrientationText = (TextView)findViewById(R.id.yaxisOrientation);
yaxisOrientationText.setText(matrixFailed);
TextView zaxisOrientationText = (TextView)findViewById(R.id.zaxisOrientation);
zaxisOrientationText.setText(matrixFailed);
TextView xaxisOldOrientationText = (TextView)findViewById(R.id.xaxisOldOrientation);
xaxisOldOrientationText.setText(mOldOreintationString[0]);
TextView yaxisOldOrientationText = (TextView)findViewById(R.id.yaxisOldOrientation);
yaxisOldOrientationText.setText(mOldOreintationString[1]);
TextView zaxisOldOrientationText = (TextView)findViewById(R.id.zaxisOldOrientation);
zaxisOldOrientationText.setText(mOldOreintationString[2]);
}
}
}
};
@Override
protected void onResume() {
super.onResume();
sensorManager.registerListener(sensorEventListener, sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_NORMAL);
sensorManager.registerListener(sensorEventListener, sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD), SensorManager.SENSOR_DELAY_NORMAL);
sensorManager.registerListener(sensorEventListener, sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION), SensorManager.SENSOR_DELAY_NORMAL);
}
protected void onPause() {
super.onPause();
sensorManager.unregisterListener(sensorEventListener);
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
以下内容对我有用:
使用null表示我
是4而不是3。但是您只使用 3。
此代码< /a> 为我工作。
The following worked with me:
Use null for I
Yes 4 not 3. However you use only 3.
This code worked for me.
这可能不适用于您的代码,但就一般使用 getRotationMatrix() 而言,它可能会解决其他人的问题。
我不确定这是否是我这边的版本控制问题,但我检查了 getRotationMatrix() 方法的源代码,与文档中有关 R[] 的内容不同 和
I[]
参数,它们不能为空。声明我的R
和I
如下:float[] r = new float[9];
float[] i = new float[9];
该方法运行正确。
SensorManager.getRotationMatrix(r,i,重力,地磁)
-->true
...奇怪的文档错误。
This probably doesn't apply to your code, but in terms of using getRotationMatrix() in general, it might solve others' problems.
I'm not sure if this was a versioning issue on my side, but I checked out the source code for the
getRotationMatrix()
method and, unlike what the documentation says about theR[]
andI[]
parameters, they CANNOT be null. After declaring myR
andI
like this:float[] r = new float[9];
float[] i = new float[9];
The method operated correctly.
SensorManager.getRotationMatrix(r,i,gravity,geomagnetic)
-->true
...strange documentation error.
为了回答您的应用程序需要强制关闭的问题,在我看来,您在 UI 线程上做的事情太多了。您正在从 3 个不同的传感器接收数据,延迟为
SENSOR_DELAY_NORMAL
。虽然这应该是大约 5 个读数/秒,但我发现它可能超过每秒 20 个读数(因为传感器延迟只是建议的延迟)。因此,所有 3 个传感器每秒可能会收到超过 60 个读数。对于每次阅读,您都会更新 12 个TextView
,因此每秒可能会执行超过 720 次 UI 更新。这也导致我的手机崩溃。尝试设置 UI 更新之间的最短时间:您可以以较快的间隔存储数据以供需要时使用,但会减慢 UI 更新的速度。
In answer to your app requiring a force close, it sounds to me like you're doing too much on the UI thread too often. You are receiving data from 3 different sensors with a delay of
SENSOR_DELAY_NORMAL
. While that should be around 5 readings/sec, I've seen it can be more than 20 readings per second (since the sensor delay is only a suggested delay). So you COULD be receiving more than 60 readings per second for all 3 sensors. for each reading, you are updating 12TextView
's, so you could be doing more than 720 UI updates per second. This caused my phone to crash as well. Try setting a minimum time between UI updates:You can store the data at the fast intervals for use if you need it, but slow down the UI updates.
事件的接收不遵循线性程序执行流程。
为了避免出现问题,最好将与传感器事件接收相关的代码放置在互斥块中。
我的意思是:
希望这有帮助。
The reception of events does not follow a linear program execution flow.
In order to avoid problems, it is a good recommendation to place the code related to reception of sensor events in a mutual exclusion block.
I mean:
Hope this helps.