传感器的应用_计步器的开发和使用

写在前面:最开始仅仅使用加速度传感器开发,效果一般,也不错。后来搜集到陀螺仪传感器通过角速度对大腿运动的模拟判断步行更为科学,进行了改进。最后发现安卓4.4以上的版本自带步行加速度传感器(adb shell pm list features后需要含有 feature:android.hardware.sensor.stepcounter和feature:android.hardware.sensor.stepdetector支持,但是华为手机只有前者没有后者)。

简易版的计步器最重要的部分就是传感器的应用:

本项目用到了加速度传感器和陀螺仪传感器。陀螺仪传感器的最主要的作用在于可以测量角速度。

首先通过加速度传感器进行简易开发:

加速度传感器又叫G-sensor,返回x、y、z三轴的加速度数值。

该数值包含地心引力的影响,单位是m/s^2。

将手机平放在桌面上,x轴默认为0,y轴默认0,z轴默认9.81(由于地球的固有重力)。

将手机朝下放在桌面上,z轴为-9.81。

将手机向左倾斜,x轴为正值。

将手机向右倾斜,x轴为负值。

将手机向上倾斜,y轴为负值。

将手机向下倾斜,y轴为正值。

很简单。第一步,声明加速度传感器,注册监听。

sensorManager=(SensorManager) getSystemService(SENSOR_SERVICE);
sensor=sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); //获取传感器,在计步器中需要使用的是加速度传感器
sensorManager.registerListener(this,sensor,sensorManager.SENSOR_DELAY_UI);

第二步,写一个xml文件。

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:padding="5dp">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:layout_marginTop="30dp"
            android:text="简易计步器"
            android:textSize="25sp" />

        <TextView
            android:id="@+id/tv_step"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:layout_marginTop="5dp"
            android:text="0"
            android:textColor="#DE5347"
            android:textSize="100sp"
            android:textStyle="bold" />

        <Button
            android:id="@+id/btn_start"
            android:layout_width="match_parent"
            android:layout_height="64dp"
            android:text="开始"
            android:textSize="25sp" />

    </LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

 

 

第三步,规定参数,写步数增加的判断逻辑。

分为向上加速度和向下加速度两部分。精度范围控制是否为有效步。Value数组接受传感器的实时数值,然后current_value记录当前加速度的模,last_value记录上一次加速度记录值的模。

这里涉及到一些物理知识,我们综合考虑大腿向前运行的过程,重点考虑竖直方向上向上向下模型,每一次走路都会有一个类似简谐运动的波形,首先会从平衡点向上运动,然后运动到顶点会再向下运动,直到运动到向下的顶点。

由于是加速度传感器,所以必须考虑加速度变化情况。分成从平衡点向上,向下,以及从上顶点回到平衡点和从下顶点回到平衡点四个部分,加速度方向分别向下、向上、向下、向上。于是传感器检测算法执行的时候,要时时刻刻判断顶点位置,如果当前位于顶点,且加速度向下,表示位于最高点;如果当前位于顶点,且加速度向上,表示位于最低点。我们规定,一次从最高点到最高点的运动过程为走一步的过程。所以如果当前位于最高点,且精度大于所给值,就步数++,更改lastvalue值,否则只更改lastvalue值。

最后就是不断更改数值,测试range的值,范围精度过小或过大都会影响传感器正确检测。我测试了很多值,发现range=3或5效果为佳。

private int step;
private double original_value;
private double last_value;
private double current_value;

private boolean motionState=true; //是否处于运动状态
private boolean processState=false;  //是否已经开始计步

double range=5; //设置一个精度范围
float[] value=event.values;
current_value =magnitude(value[0],value[1],value[2]); //计算当前的模

//向上加速的状态
if(motionState==true){
    if (current_value >= last_value)
        last_value = current_value;
    else {
        //检测到一次峰值
        if(Math.abs(current_value-last_value)>range){
            original_value=current_value;
            motionState=false;
        }
    }
}
//向下加速的状态
if(motionState==false){
    if (current_value <= last_value)
        last_value = current_value;
    else {
        //检测到一次峰值
        if(Math.abs(current_value-last_value)>range){
            original_value=current_value;
            if (processState==true){
                step++; //检测到开始记录,步数加1
                if(processState==true){
                    textView_step.setText(step+""); //更新读数
                }
            }
            motionState=true;
        }
    }
}

这种方法还欠缺,可以改进!改进方法就是用陀螺仪传感器更好地模拟运动过程。

陀螺仪最早是法国科学家在1850年在研究地球自转中获得灵感而发明的,如上图所示,将一个高速旋转的陀螺放到一个万向支架上,靠陀螺的方向来计算角速度,其简易图如下所示。

中间金色的转子即为陀螺,它因为惯性作用是不会受到影响的,周边的三个“钢圈”则会因为设备的改变姿态而跟着改变,通过这样来检测设备当前的状态,而这三个“钢圈”所在的轴,也就是三轴陀螺仪里面的“三轴”,即X轴、y轴、Z轴,三个轴围成的立体空间联合检测手机的各种动作,陀螺仪的最主要的作用在于可以测量角速度。

 

 

陀螺仪又叫角速度传感器,一般用来检测手机姿态的,好像手机中的陀螺仪传感器一般都是三轴的!

体感游戏用得最多,手机拍照防抖,GPS惯性导航,飞行姿态判断,还有为APP添加一些动作感应(比如轻轻晃动手机关闭来电铃声)等等

陀螺仪传感器的单位:角速度(弧度/秒)radians/second

获得传感器用的是:Sensor.TYPE_GYROSCOPE

他的三个值依次是沿着X轴,Y轴,Z轴旋转的角速度,手机逆时针旋转,角速度值为正,顺时针则为负值!

首先完成demo测试陀螺仪传感器数值,并摇晃手机观察幅度变化。

这一数据可以为后续步数传感器开发做基础。代码如下:

package com.example.pedometer2;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.util.Log;

public class MainActivity extends AppCompatActivity {



    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
        mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
        mSensorManager.registerListener(mSensorEventListener, mSensor, SensorManager.SENSOR_DELAY_GAME);
    }

    private SensorManager mSensorManager;
    private Sensor mSensor;


    @Override
    protected void onResume() {
        super.onResume();
        mSensorManager.registerListener(mSensorEventListener, mSensor, SensorManager.SENSOR_DELAY_GAME);
    }

    @Override
    protected void onPause() {
        super.onPause();
        mSensorManager.unregisterListener(mSensorEventListener);
    }

    private float timestamp = 0;
    private float angle[] = new float[3];
    private static final float NS2S = 1.0f / 1000000000.0f;
    private float gx = 0,gy = 0,gz = 0;
    private SensorEventListener mSensorEventListener = new SensorEventListener() {
        @Override
        public void onSensorChanged(SensorEvent sensorEvent) {
            if (sensorEvent.accuracy != 0) {
                int type = sensorEvent.sensor.getType();
                switch (type) {
                    case Sensor.TYPE_GYROSCOPE:
                        if (timestamp != 0) {
                            final float dT = (sensorEvent.timestamp - timestamp) * NS2S;
                            angle[0] += sensorEvent.values[0] * dT;
                            angle[1] += sensorEvent.values[1] * dT;
                            angle[2] += sensorEvent.values[2] * dT;

                            float anglex = (float) Math.toDegrees(angle[0]);
                            float angley = (float) Math.toDegrees(angle[1]);
                            float anglez = (float) Math.toDegrees(angle[2]);

                            if(gx != 0){
                                float c = gx - anglex;
                                if(Math.abs(c) >= 0.5 ){
                                    Log.d("================", "anglex------------>" + (gx - anglex));
                                    gx = anglex;
                                }

                            }else{
                                gx = anglex;
                            }
                            if(gy != 0){
                                float c = gy - angley;
                                if(Math.abs(c) >= 0.5 ){
                                    Log.d("================", "angley------------>" + (gy - angley));
                                    gy = angley;
                                }
                            }else{
                                gy = angley;
                            }
                            if(gz != 0){
                                float c = gz - anglez;
                                if(Math.abs(c) >= 0.5 ){
                                    Log.d("================", "anglez------------>" + (gz - anglez));
                                    gz = anglez;
                                }
                            }else{
                                gz = anglez;
                            }


                        }
                        timestamp = sensorEvent.timestamp;
                        break;
                }
            }
        }

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

        }
    };

}

最后,基于陀螺仪传感器开发计步器。

程序框架和1一样,关键代码改变如下:

public void onSensorChanged(SensorEvent sensorEvent) {


        if (timestamp != 0) {
final float dT = (sensorEvent.timestamp - timestamp) * NS2S;
        angle[0] += sensorEvent.values[0] * dT;
        angle[1] += sensorEvent.values[1] * dT;
        angle[2] += sensorEvent.values[2] * dT;

        float anglex = (float) Math.toDegrees(angle[0]);
        float angley = (float) Math.toDegrees(angle[1]);
        float anglez = (float) Math.toDegrees(angle[2]);

        if(magnitude(gx-anglex,gy-angley,gz-anglez)>15 && Math.abs(gz-anglez)>5  && Math.abs(gx-anglex)>5  && Math.abs(gy-angley)>5 ){
                if (processState==true){
                    step++; //检测到开始记录,步数加1
                        textView_step.setText(step+""); //更新读数
                    gx = anglex;
                    gy = angley;
                    gz = anglez;
                }
                motionState=true;
        }

        }
        timestamp = sensorEvent.timestamp;

    }

经过对比,陀螺仪传感器比加速度传感器对于步伐的检测更为准确。还可以改进的地方是,可以整合加速度传感器和陀螺仪传感器!但笔者觉得陀螺仪传感器已经很棒了!

此外,如果手机自带如下

 

 

这两个硬件支持,就可以利用自带的传感器进行步数统计。很可惜华为手机没有。

写在最后:

推荐官方学习文档,我们在进行传感器开发的时候,尽量使用真机测试,同时对于一个期望目标,给出多种传感器和方案,对于每一种都试一试,一定能找出最合适的。

运动传感器  |  Android 开发者  |  Android Developers (google.cn)

推荐几篇博客:

讲陀螺仪传感器的博客:

陀螺仪传感器的简单了解_谁的锅的博客-CSDN博客_陀螺仪传感器(讲解了历史、工作原理和应用)

讲手机自带记步传感器使用的博客:

Android简单的计步器应用实现_椒盐虾呀的博客-CSDN博客_android计步器实现

实测App运行效果:

加速度传感器还可用于摇一摇等开发,和具体应用功能相结合。

注:第一版是用加速度传感器开发的,第二版是陀螺仪传感器数据查看,第三版是基于陀螺仪传感器开发的。生成的Apk只是第三版,但是源码包含了三版。

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
健康计步器Android应用开发主要是为用户提供方便的计步功能,并根据用户的步数和活动信息提供健康指导和建议。以下是开发这种应用的一般步骤和功能要点。 首先,为了实现计步功能,我们需要使用手机中的传感器来检测用户的步数。Android设备通常内置了加速度计传感器,可以用来测量移动的加速度。我们可以通过获取加速度传感器的数据,判断用户行走的步数,并实时显示在应用界面上。 其次,我们可以将步数数据进行累计,并根据用户设置的个人信息(例如身高、体重等)和目标步数,计算出用户的活动量和燃烧的卡路里。用户可以通过应用界面查看自己每天的步数和热量消耗情况,有助于监控自己的健康状况。 除了计步功能,该应用还可以提供其他健康相关的功能。例如,用户可以设置每天的目标步数,并根据达成情况获得奖励或提醒。应用还可以提供健康建议,例如每天建议的步数目标、运动时间和强度等。用户可以根据自己的实际情况和健康目标,合理安排自己的日常运动。 此外,应用还可以提供历史数据的统计和分析功能。用户可以查看自己最近的步数变化趋势和热量消耗情况,从而更好地了解自己的运动习惯和健康状况。用户还可以将自己的数据分享到社交媒体平台上,与朋友们一起比较和互动,增加健康的竞争和互动乐趣。 综上所述,健康计步器Android应用开发主要包括计步功能、热量消耗统计、健康建议和历史数据分析等核心功能。通过设计易用的应用界面和提供个性化的健康服务,我们可以帮助用户更好地管理自己的健康,促进积极的生活方式和习惯。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值