我想在沉浸式卡片中使用game_rotation_vector sensor。当前版本的Glass(XE17)不提供此传感器。所以我想知道如何获得相同的值。
实际上我想获得偏航,俯仰和方位角值。我目前使用rotation_vector传感器来做到这一点。我计算了开始值和当前值之间的差值,它给出了当前的度数。但是,当用户摇动水平值时,我的应用程序计算的程度很差。
答案 0 :(得分:2)
我写了一个帮助类来管理Glass的方向,因为我在a Glass app showing real-time transit info计算了几次。
/*
* Copyright (C) 2014 Sean J. Barbeau, University of South Florida
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.joulespersecond.oba.glass;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import java.util.ArrayList;
/**
* Implements a sensor-based orientation helper for Glass, which allows listeners to receive
* orientation updates
*/
public class OrientationHelper implements SensorEventListener {
public interface Listener {
/**
* Called every time there is an update to the orientation
*
* @param deltaHeading change in heading from last heading value
* @param deltaPitch change in pitch from last pitch value
*/
void onOrientationChanged(float heading, float pitch, float deltaHeading, float deltaPitch);
}
static final String TAG = "OrientationHelper";
Context mContext;
SensorManager mSensorManager;
private float[] mRotationMatrix = new float[16];
private float[] mOrientation = new float[9];
private float[] history = new float[2];
private float mHeading;
private float mPitch;
ArrayList<Listener> mListeners = new ArrayList<Listener>();
public OrientationHelper(Context context) {
mContext = context;
mSensorManager = (SensorManager) mContext.getSystemService(Context.SENSOR_SERVICE);
}
public synchronized void registerListener(Listener listener) {
if (!mListeners.contains(listener)) {
mListeners.add(listener);
}
// If this is the first listener, make sure we're monitoring the sensors to provide updates
if (mListeners.size() == 1) {
mSensorManager.registerListener(this,
mSensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR),
SensorManager.SENSOR_DELAY_UI);
}
}
public synchronized void unregisterListener(Listener listener) {
if (mListeners.contains(listener)) {
mListeners.remove(listener);
}
if (mListeners.size() == 0) {
mSensorManager.unregisterListener(this);
}
}
public synchronized void onResume() {
mSensorManager.registerListener(this,
mSensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR),
SensorManager.SENSOR_DELAY_UI);
}
public synchronized void onPause() {
mSensorManager.unregisterListener(this);
}
@Override
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() == Sensor.TYPE_ROTATION_VECTOR) {
SensorManager.getRotationMatrixFromVector(mRotationMatrix, event.values);
SensorManager.remapCoordinateSystem(mRotationMatrix, SensorManager.AXIS_X,
SensorManager.AXIS_Z, mRotationMatrix);
SensorManager.getOrientation(mRotationMatrix, mOrientation);
mHeading = (float) Math.toDegrees(mOrientation[0]);
mPitch = (float) Math.toDegrees(mOrientation[1]);
float xDelta = history[0] - mHeading; // Currently unused
float yDelta = history[1] - mPitch;
history[0] = mHeading;
history[1] = mPitch;
// Use magnetic field to compute true (geographic) north, if data is available
// Note that if Glass doesn't have location info (e.g., it isn't paired and doesn't have a data connection), this should still work, you just can't correct for magnetic north
Float magneticDeclination = LocationHelper.getMagneticDeclination();
if (magneticDeclination != null) {
mHeading += magneticDeclination;
}
// Make sure value is between 0-360
mHeading = MathUtils.mod(mHeading, 360.0f);
for (Listener l : mListeners) {
l.onOrientationChanged(mHeading, mPitch, xDelta, yDelta);
}
}
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
}
这是MathUtil.java:
package com.joulespersecond.oba.glass;
/**
* A utility class containing arithmetic and geometry helper methods.
*
* (from Glass Compass sample)
*/
public class MathUtils {
/**
* Calculates {@code a mod b} in a way that respects negative values (for example,
* {@code mod(-1, 5) == 4}, rather than {@code -1}).
*
* @param a the dividend
* @param b the divisor
* @return {@code a mod b}
*/
public static float mod(float a, float b) {
return (a % b + b) % b;
}
}
...用于校正磁北的LocationHelper
显示为here。如果无法确定某个位置(例如,Glass未配对并且没有数据连接),这仍然有效,您只是无法纠正磁性北(错误会有所不同,取决于你在世界的哪个地方)。
要使用方向助手,您可以实现侦听器界面,例如在View
中,当方位角(标题)和音高发生变化时,您可以根据方向重新绘制内容:< / p>
public class MyView extends View implements OrientationHelper.Listener {
private float mHeading;
private float mPitch;
private float mXDelta;
private float mYDelta;
...
@Override
public void onOrientationChanged(float heading, float pitch, float xDelta, float yDelta) {
mHeading = heading;
mPitch = pitch;
mXDelta = xDelta;
mYDelta = yDelta;
invalidate();
}
@Override
protected void onDraw(Canvas canvas) {
// Draw something based on orientation
...
}
}
..并在您的服务或活动中创建视图时注册监听器:
mOrientationHelper = new OrientationHelper(this);
mOrientationHelper.registerListener(mMyView);
在您的活动mOrientationHelper.onResume();
中调用onResume()
,在您的活动mOrientationHelper.onPause();
中调用onPause()
以启动/停止传感器。
Google Glass GDK Compass sample是如何在Glass上使用方向的另一个很好的例子。
这一切都适用于一般的Android,除了这里的坐标重新映射固定为Glass的方向。要在可以更改方向的设备上使用此功能,您需要根据方向重新映射坐标系,这将在here中进行讨论。