android笔记,山寨版摇动判断算法的设计过程。

我参与的学校的创新工程项目有一个计步器的需求,由于未知原因,前两天模仿着写的程序始终搞不定。。于是干脆自己写一个Demo来看看效果,也是多学学,加深印象。

计步器的核心就是根据重力传感器的xyz三轴测得的数值来判定用户是不是走了一步。


当手机向某个方向加速时,三轴对应的读数也会增加(或减少,如果是反方向加速的话)。


粗略点的话,可以分别把三轴数值的绝对值相加,得到粗略的加速度,超过一定的阙值之后就可以判定为跑了一步(震了一下)。对于加速方向,则可以无视,因为计步器没这个需求。


还有个精确些的想法:由于三轴中任意两轴呈直角,可以用算斜边的公(x平方加y平方再开方)先将xy轴的合力算出来,再把合力与z轴如法炮制一遍,就可以得到三轴的合力。这个合力的好处就是手机无论是怎样放置的,它的读数都一致,可以得到更真实的加速度,这正是我要的。

然后我实机测试了一下,发现只摇一下,读数确快速增加了很多。恩。。。即使是性能较差的手机,计算速度也是很快的,一次判断晃动后要等一下子才能再次进行判断才行。


再试一次,可以了,效果不错。但是还有个问题。。:如果有条件可以持续提供超出阙值的加速度(比如超级跑车?呵呵),这种算法的读数不也会持续增加么。。

当然正常情况下这种bug不会出现。。因为如果能持续维持住瞬间摇动时的加速度的话,我们的手机抽根烟工夫就能快过子弹了。。(粗略估计。勿较真。。)不过这倒提供了另一个思路:对摇动的判断条件应该是在一定时间内完成往复加速才完整。


过过吐槽瘾:

对我这个项目肯定是用不上了。。不过这倒是个不错的练习题,也许还可以加上加速方向的判定,不过这东西貌似只有在3d游戏中才有用啊。。而3d游戏。。人家有物理引擎。。。。。。残念。。索爱那样用在音乐播放器上?向右摔是下一首,左是上一首,然后就一群人天天甩来甩去。。。线控明明很方便的说。。甩动换歌真心是个脑残主意。。。还要先把手机拿在手上。那样直接按键不是更好。。。


忘上代码了。。

PedometerDemoActivity.java:

package com.gaga.PedometerDemo;

import android.app.Activity;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.util.Log;
import android.widget.RelativeLayout;
import android.widget.TextView;

public class PedometerDemoActivity extends Activity {
	
	private String TAG = "My Pedometer";
	
	private TextView mStepCounter;
	private TextView mx;
	private TextView my;
	private TextView mz;
	
	private int steps;
	private SensorManager mSensorManager;
	private Sensor mSensor;
	private StepDetector mStepDetector;
	
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        mStepCounter = (TextView)findViewById(R.id.txt_StepsCount);
        mx = (TextView)findViewById(R.id.x);
        my = (TextView)findViewById(R.id.y);
        mz = (TextView)findViewById(R.id.z);
        
        steps = 0;
        mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
        mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        registerStepListener();
    }
    
    private void registerStepListener() {
    	if (mStepDetector == null) {
    		mStepDetector = new StepDetector();
    	}
		mSensorManager.registerListener(mStepDetector, mSensor, SensorManager.SENSOR_DELAY_FASTEST);
	}
    
    @Override
	protected void onPause() {
		Log.d(TAG, "onPause");
		super.onPause();
		mSensorManager.unregisterListener(mStepDetector);
	}

	@Override
	protected void onResume() {
		registerStepListener();
		super.onResume();
	}

	private class StepDetector implements SensorEventListener {

		@Override
		public void onAccuracyChanged(Sensor sensor, int accuracy) {
		}

		@Override
		public void onSensorChanged(SensorEvent event) {
			if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
				updateImage(event.values[0], event.values[1], event.values[2]);
				isStep(event.values);
			}
		}
		
		private void updateImage(float x,float y, float z) {
			RelativeLayout.LayoutParams mxLayoutParams = (RelativeLayout.LayoutParams)mx.getLayoutParams();
			RelativeLayout.LayoutParams myLayoutParams = (RelativeLayout.LayoutParams)my.getLayoutParams();
			RelativeLayout.LayoutParams mzLayoutParams = (RelativeLayout.LayoutParams)mz.getLayoutParams();
			mxLayoutParams.height = (int)x*10+50;
			myLayoutParams.height = (int)y*10+50;
			mzLayoutParams.height = (int)z*10+50;
			mx.setLayoutParams(mxLayoutParams);
			my.setLayoutParams(myLayoutParams);
			mz.setLayoutParams(mzLayoutParams);
		}
		
		private float offset = 50;	//随便设的阙值
		private long lastStepTime = 0;
		
		private void isStep(float[] values) {
			float value = Math.abs(values[0])+Math.abs(values[1])+Math.abs(values[2]);
			
			if (value > offset) {
				//判定为一步后要等一下,不然读数会猛跳。
				long curTime = System.currentTimeMillis();
				if ((curTime - lastStepTime) > 200) {
					increaseAndSetSteps();
					lastStepTime = curTime;
				}
			}
		}
		
		private void increaseAndSetSteps() {
			steps ++;
			mStepCounter.setText(String.valueOf(steps));
		}
    }
}

main.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" android:background="#fff">

    <TextView
        android:id="@+id/StepsHere"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="Steps Here!"
        android:textColor="#232725"
		android:shadowColor="#666"
		android:shadowRadius="0.5"
		android:textSize="40dp"
		android:shadowDx="1.0"
		android:shadowDy="1.0"/>

    <TextView
        android:id="@+id/x"
        android:layout_width="50px"
        android:layout_height="20px"
        android:layout_above="@+id/StepsHere"
        android:layout_alignLeft="@+id/StepsHere"
        android:text=""
        android:background="#18270a" />

    <TextView
        android:id="@+id/y"
        android:layout_width="50px"
        android:layout_height="20px"
        android:layout_above="@+id/StepsHere"
        android:layout_toRightOf="@+id/x"
        android:background="#3b7306"
        android:text=""/>

    <TextView
        android:id="@+id/z"
        android:layout_width="50px"
        android:layout_height="20px"
        android:layout_above="@+id/StepsHere"
        android:layout_toRightOf="@+id/y"
        android:background="#488c03"
        android:text=""/>

    <TextView
        android:id="@+id/txt_StepsCount"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/StepsHere"
        android:layout_below="@+id/StepsHere"
        android:shadowColor="#666"
        android:shadowDx="1.0"
        android:shadowDy="1.0"
        android:shadowRadius="0.5"
        android:text="0"
        android:textColor="#cbd9b8"
        android:textSize="190dp" />

</RelativeLayout>

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值