计步器源代码实现的俩种方式-阿里云开发者社区

开发者社区> 人工智能> 正文
登录阅读全文

计步器源代码实现的俩种方式

简介:

网上比较流行的计步好多都是用第一中方法写,是一套算法:

下边是第一种的代码,个人感觉准确度不是很好,误差经常在好几十往上,但是也还能用:下载地址:http://download.csdn.net/detail/u012808234/8539079

package com.example.pedometerdemo;

import java.util.List;
import java.util.Timer;

import android.app.ActivityManager;
import android.app.ActivityManager.RunningTaskInfo;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.IBinder;
import android.util.Log;



public class pedometerService extends Service implements SensorEventListener {

    public static final String STEP_CHANGE = "step_change";
    public static final String ADD_STEPS = "add_Step";
    
    private static final int notifiId = 11;
    private Intent intent;
    private ActivityManager activityManager;
    private SensorManager sensorManager;
    private Timer timer = new Timer();
    private long lastTime;// 上次记步的时间

    private float mLimit = 6.44f;
    private int interval_time;
    private float mLastValues[] = new float[3 * 2];
    private float mScale[] = new float[2];
    private float mYOffset;

    private float mLastDirections[] = new float[3 * 2];
    private float mLastExtremes[][] = { new float[3 * 2], new float[3 * 2] };
    private float mLastDiff[] = new float[3 * 2];
    private int mLastMatch = -1;

    private int startStep;

    private Service instance;
    
    private float[] xyz=new float[3];
    @Override
    public IBinder onBind(Intent intent) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public void onCreate() {
        // TODO Auto-generated method stub
        super.onCreate();
        instance = this;
        initData();
        initStepDetector();
        interval_time = 200;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        // TODO Auto-generated method stub
        System.out.println("启动");
        return START_REDELIVER_INTENT;
    }

    @Override
    public void onDestroy() {
        // TODO Auto-generated method stub
        super.onDestroy();
        sensorManager.unregisterListener(this);
    }

    @Override
    public void onSensorChanged(SensorEvent event) {
        // TODO Auto-generated method stub
        Sensor sensor = event.sensor;
        synchronized (this) {
            if (System.currentTimeMillis() - lastTime < interval_time) {
                return;
            }
            if (sensor.getType() == Sensor.TYPE_ORIENTATION) {
            } else {
                int j = (sensor.getType() == Sensor.TYPE_ACCELEROMETER) ? 1 : 0;
                
                if (j == 1) {
                    float vSum = 0;
                    
                
                    for (int i = 0; i < 3; i++) {
                        final float v = mYOffset + event.values[i] * mScale[j];
                        
                        vSum += v;
                    }
                    int k = 0;
                    float v = vSum / 3;

                    float direction = (v > mLastValues[k] ? 1 : (v < mLastValues[k] ? -1 : 0));
                    if (direction == -mLastDirections[k]) {
                        // Direction changed
                        int extType = (direction > 0 ? 0 : 1); // minumum or
                                                                // maximum?
                        mLastExtremes[extType][k] = mLastValues[k];
                        float diff = Math.abs(mLastExtremes[extType][k] - mLastExtremes[1 - extType][k]);

                        if (diff > mLimit) {
                            boolean isAlmostAsLargeAsPrevious = diff > (mLastDiff[k] * 2 / 3);
                            boolean isPreviousLargeEnough = mLastDiff[k] > (diff / 3);
                            boolean isNotContra = (mLastMatch != 1 - extType);

                            if (isAlmostAsLargeAsPrevious && isPreviousLargeEnough && isNotContra) {
                                long currentTime = System.currentTimeMillis();
                                if (currentTime - lastTime > 2000) {
                                    
                                    startStep = 0;
                                } else {
                                   Log.e("STEP", startStep+++"");
                                }
                                mLastMatch = extType;
                                lastTime = currentTime;
                            } else {
                                mLastMatch = -1;
                            }
                        }
                        mLastDiff[k] = diff;
                    }
                    mLastDirections[k] = direction;
                    mLastValues[k] = v;
                }
            }
        }
    }

    private boolean appIsTop() {
        if (activityManager == null) {
            activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
        }
        List<RunningTaskInfo> rti = activityManager.getRunningTasks(1);
        String packagename = rti.get(0).topActivity.getPackageName();
        if (packagename.equals(getPackageName())) {
            return true;
        }
        return false;
    }

    public void initStepDetector() {
        int h = 480; // TODO: remove this constant
        mYOffset = h * 0.5f;
        mScale[0] = -(h * 0.5f * (1.0f / (SensorManager.STANDARD_GRAVITY * 2)));
        mScale[1] = -(h * 0.5f * (1.0f / (SensorManager.MAGNETIC_FIELD_EARTH_MAX)));
    }

    @Override
    public void onAccuracyChanged(Sensor arg0, int arg1) {
        // TODO Auto-generated method stub

    }
    private void initData() {
        sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
        if (sensorManager != null) {// 注册监听器
            sensorManager.registerListener(this, sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_FASTEST);
            // 第一个参数是Listener,第二个参数是所得传感器类型,第三个参数值获取传感器信息的频率
        }

    }
    
}


还有第二种,我觉得是误差小点的,自己测试了下,不管别的情况的,就是正常走路的误差在10步左右:看看代码,他是封成了好几个方法,上最主要的逻辑代码:

 下载地址:http://download.csdn.net/detail/u012808234/8539095

/*
 * Copyright 2013 Google Inc.
 *
 * 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.google.android.apps.simplepedometer;

/**
 * Receives sensor updates and alerts a StepListener when a step has been detected.
 */
public class SimpleStepDetector {

  private static final int ACCEL_RING_SIZE = 50;
  private static final int VEL_RING_SIZE = 10;
  private static final float STEP_THRESHOLD = 4f;
  private static final int STEP_DELAY_NS = 250000000;

  private int accelRingCounter = 0;
  private float[] accelRingX = new float[ACCEL_RING_SIZE];
  private float[] accelRingY = new float[ACCEL_RING_SIZE];
  private float[] accelRingZ = new float[ACCEL_RING_SIZE];
  private int velRingCounter = 0;
  private float[] velRing = new float[VEL_RING_SIZE];
  private long lastStepTimeNs = 0;
  private float oldVelocityEstimate = 0;

  private StepListener listener;

  public void registerListener(StepListener listener) {
    this.listener = listener;
  }

  /**
   * Accepts updates from the accelerometer.
   */
  public void updateAccel(long timeNs, float x, float y, float z) {
    float[] currentAccel = new float[3];
    currentAccel[0] = x;
    currentAccel[1] = y;
    currentAccel[2] = z;

    // First step is to update our guess of where the global z vector is.
    accelRingCounter++;
    accelRingX[accelRingCounter % ACCEL_RING_SIZE] = currentAccel[0];
    accelRingY[accelRingCounter % ACCEL_RING_SIZE] = currentAccel[1];
    accelRingZ[accelRingCounter % ACCEL_RING_SIZE] = currentAccel[2];

    float[] worldZ = new float[3];
    worldZ[0] = SensorFusionMath.sum(accelRingX) / Math.min(accelRingCounter, ACCEL_RING_SIZE);
    worldZ[1] = SensorFusionMath.sum(accelRingY) / Math.min(accelRingCounter, ACCEL_RING_SIZE);
    worldZ[2] = SensorFusionMath.sum(accelRingZ) / Math.min(accelRingCounter, ACCEL_RING_SIZE);

    float normalization_factor = SensorFusionMath.norm(worldZ);

    worldZ[0] = worldZ[0] / normalization_factor;
    worldZ[1] = worldZ[1] / normalization_factor;
    worldZ[2] = worldZ[2] / normalization_factor;

    // Next step is to figure out the component of the current acceleration
    // in the direction of world_z and subtract gravity's contribution
    float currentZ = SensorFusionMath.dot(worldZ, currentAccel) - normalization_factor;
    velRingCounter++;
    velRing[velRingCounter % VEL_RING_SIZE] = currentZ;

    float velocityEstimate = SensorFusionMath.sum(velRing);

    if (velocityEstimate > STEP_THRESHOLD && oldVelocityEstimate <= STEP_THRESHOLD
        && (timeNs - lastStepTimeNs > STEP_DELAY_NS)) {
      listener.step(timeNs);
      lastStepTimeNs = timeNs;
    }
    oldVelocityEstimate = velocityEstimate;
  }
}



版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

分享:
人工智能
使用钉钉扫一扫加入圈子
+ 订阅

了解行业+人工智能最先进的技术和实践,参与行业+人工智能实践项目

其他文章