加速度传感器
借用别人的图片,以及理解:
加速度传感器分为 x,y,z;
我们可以借助三轴上的值来确定设备的状态(请参考上面的坐标图),比如:
1、当x轴的值接近重力加速度时,说明设备的左边朝下。
2、当x轴的值接近负的g值时,说明设备的右边朝下。
3、当y轴的值接近g值时,说明设备的下边超下(与上图一样)。
4、当y轴的值接近负的g值时,说明设备的上边朝下(倒置)。
5、当z轴的值接近g值时,说明设备的屏幕朝上。
6、当z轴的值接近负的g值时,说明设备屏幕朝下。
说到加速都传感器,还有一个线性加速都传感器:
线性加速度传感器简称LA-sensor。
线性加速度传感器是加速度传感器减去重力影响获取的数据。
单位是m/s^2,坐标系统与加速度传感器相同。
加速度传感器、重力传感器和线性加速度传感器的计算公式如下:
加速度 = 重力 + 线性加速度
加速度传感器计算步数
大概的想法是取得加速度传感器的矢量和,如果不动,他应该是一个g。
当我们抬脚落脚属于一步,这时候加速度传感器会有一个一个波峰和波谷。我们计算出两者之间的差值,就可以判断是否为一步。
下面是我看到别人写的:
每50ms取一个加速度的采样点作为一个交易日。
如果连续两个交易日保持在均线之上,上涨趋势成立,可能是波峰
如果连续两个交易日保持在均线之下,下跌趋势成立,可能是波谷
波谷之后,才可能有波峰
波峰之后,才可能有波谷
记录到的高底两点,差值大于某个值时更可能是真正行走的一步(剔除轻微抖动)
两步间隔不少于250ms。容忍高达240每分钟的步频。一般人走路步频100上下,跑步180上下。
另外移动平均线取64个采用点的移动平均线。(尽量取多一点,确保不受瞬时影响,尽量取少一点,确保响应跟得上。取了64个点,3秒多,刚好)。
如何判断波峰呢,应该有下面几个条件:
1 当前的点处于下降状态,也就是说比上次记录的数值要低。
2 上一个点是上升状态,只有上升下降只有才可能到达波峰
3 上升的点数为n个,这个次数要具体测试,因为可能是手动的上下移动手机
4 记录波谷的数值,波峰和波谷的值要在一定的范围之内。
检测的一个简单算法,从网上看到的
/*
* 检测步子,并开始计步
* 1.传入sersor中的数据
* 2.如果检测到了波峰,并且符合时间差以及阈值的条件,则判定为1步
* 3.符合时间差条件,波峰波谷差值大于initialValue,则将该差值纳入阈值的计算中
* */
public void detectorNewStep(float values) {
// 需要看一下上次的数值是什么,也就是说判断是上升还是下降
if (gravityOld == 0) {
gravityOld = values;
} else {
//如果是波峰,如果不为0 那么检测是否为波峰
if (DetectorPeak(values, gravityOld)) {
/*
*这个是设置波峰的时间,也就是说把这次波峰的时间设置
* */
timeOfLastPeak = timeOfThisPeak;
timeOfNow = System.currentTimeMillis();
/*
* 如果两次波峰的时间大于200
* 波峰和波谷的差值大于 阈值
* 波峰的时间差小于连两秒
* */
if (timeOfNow - timeOfLastPeak >= 200
&& (peakOfWave - valleyOfWave >= ThreadValue) && (timeOfNow - timeOfLastPeak) <= 2000) {
timeOfThisPeak = timeOfNow;
//更新界面的处理,不涉及到算法
preStep();
}
if (timeOfNow - timeOfLastPeak >= 200
&& (peakOfWave - valleyOfWave >= initialValue)) {
timeOfThisPeak = timeOfNow;
ThreadValue = Peak_Valley_Thread(peakOfWave - valleyOfWave);
}
}
}
gravityOld = values;
}
private void preStep() {
if (CountTimeState == 0) {
// 开启计时器
time = new TimeCount(duration, 700);
time.start();
CountTimeState = 1;
Log.v(TAG, "开启计时器");
} else if (CountTimeState == 1) {
TEMP_STEP++;
Log.v(TAG, "计步中 TEMP_STEP:" + TEMP_STEP);
} else if (CountTimeState == 2) {
CURRENT_SETP++;
if (onSensorChangeListener != null) {
onSensorChangeListener.onChange();
}
}
}
/*
* 检测波峰
* 以下四个条件判断为波峰:
* 1.目前点为下降的趋势:isDirectionUp为false
* 2.之前的点为上升的趋势:lastStatus为true
* 3.到波峰为止,持续上升大于等于2次
* 4.波峰值大于1.2g,小于2g
* 记录波谷值
* 1.观察波形图,可以发现在出现步子的地方,波谷的下一个就是波峰,有比较明显的特征以及差值
* 2.所以要记录每次的波谷值,为了和下次的波峰做对比
* */
public boolean DetectorPeak(float newValue, float oldValue) {
lastStatus = isDirectionUp;
/*
* 如果新的数值大于旧的,则可以看作是上升、
* 上升的次数加1
* */
if (newValue >= oldValue) {
isDirectionUp = true;
continueUpCount++;
} else {
/*
* 持续上升的次数
* 因为这次是下降,所以我们把上升清零
* */
continueUpFormerCount = continueUpCount;
continueUpCount = 0;
isDirectionUp = false;
}
Log.v(TAG, "oldValue:" + oldValue);
if (!isDirectionUp && lastStatus
&& (continueUpFormerCount >= 2 && (oldValue >= minValue && oldValue < maxValue))) {
// 检测到波峰,则设置波峰的值
peakOfWave = oldValue;
return true;
// 上一点的位置
/*
* 上一个点的状态是下降 并且当前点为上升 则认为是i波谷
* */
} else if (!lastStatus && isDirectionUp) {
valleyOfWave = oldValue;
return false;
} else {
return false;
}
}