简体   繁体   English

Android跌倒检测问题

[英]Android Fall Detection Issue

I'm trying to implement a simple fall detection algorithm using android's accelerometer . 我正在尝试使用android的accelerometer实现一个简单的跌倒检测算法。

The current acceleration of the phone is stored in mAccel and if a sudden shake is detected Timer t begins. 手机的当前加速度存储在mAccel ,如果检测到突然震动,则Timer t开始。 Inside the Timer are two CountDownTimers . Timer内部有两个CountDownTimers

The firstTimer is used to register a "fall" if the user hasn't moved in the last 5 seconds and the secondTimer to confirm that fall if the user hasn't pressed a button (not implemented yet). 如果用户在最近5秒钟内没有移动,则firstTimer用于注册“下降”,如果用户尚未按下按钮(尚未实现),则使用secondTimer确认该下降。

public void onSensorChanged(SensorEvent event) {

    if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
        mGravity = event.values.clone();

        float x = mGravity[0];
        float y = mGravity[1];
        float z = mGravity[2];
        mAccelLast = mAccelCurrent;
        mAccelCurrent = (float) Math.sqrt(x * x + y * y + z * z);
        float delta = mAccelCurrent - mAccelLast;
        mAccel = mAccel * 0.9f + delta;
        mAccel = abs(mAccel);
        textView.setText("a:"+mAccel);
        if (abs(mAccel) > 5.0f) { // Shake detection
            t();
        }
    }
}
public void t () {

    firstTimer = new CountDownTimer(5000, 1000) {  //fall registration timer

        @Override
        public void onTick(long millisUntilFinished) {
            //if there is movement before 5 seconds pass cancel the timer
            if (abs(mAccel) > 2.0f) {
                firstTimer.cancel();
                firstTimer = null;
            }
        }

        @Override
        public void onFinish() {
            toast.show();

            secondTimer = new CountDownTimer(30*1000, 1000) { //fall confirmation timer

                @Override
                public void onTick(long millisUntilFinished) {
                    textView2.setText("" + millisUntilFinished / 1000);
                }

                @Override
                public void onFinish() {
                    Toast toast = Toast.makeText(getApplicationContext(),
                                  "Fall Registered!", Toast.LENGTH_LONG);
                        toast.show();
                    }
                }.start();
            }
        }.start();
    }

The main issue is that most times firstTimer is accessed, it gets cancelled due to the mAccel being over the 2.0 threshold, while it is decelerating. 主要问题是大多数时候访问firstTimer ,由于mAccel在减速时超过2.0阈值,因此取消了它。

I tried to use Timer.schedule() to delay the activation of firstTimer until after the acceleration value has "rested" but it won't work with it. 我尝试使用Timer.schedule()来延迟firstTimer的激活,直到加速度值“静止”之后,但它无法使用。

I created a new Timer object mTimer and this seems to work on every case. 我创建了一个新的Timer对象mTimer,这似乎适用于每种情况。

CountDownTimer firstTimer = new CountDownTimer(5000, 1000) {  //fall registration timer

        @Override
        public void onTick(long millisUntilFinished) {
            //if there is movement before 5 seconds pass cancel the timer
            if (abs(mAccel) > 2.0f) {
                Toast toast = Toast.makeText(getApplicationContext(),
                              "Fall not Detected", Toast.LENGTH_SHORT);
                toast.show();
                firstTimer.cancel();
            }
        }

        @Override
        public void onFinish() {
            Toast toast = Toast.makeText(getApplicationContext(),
                          "Fall Detected!", Toast.LENGTH_SHORT);
            toast.show();
            secondTimer.start();
        }
    };

    CountDownTimer secondTimer = new CountDownTimer(30*1000, 1000) {
    //fall confirmation timer

        @Override
        public void onTick(long millisUntilFinished) {
            textView2.setText("" + millisUntilFinished / 1000);
        }

        @Override
        public void onFinish() {
            Toast toast = Toast.makeText(getApplicationContext(),
            "Fall Registered!", Toast.LENGTH_LONG);
            toast.show();
        }
    };


@Override
public void onSensorChanged(SensorEvent event) {

    if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
        mGravity = event.values.clone();
        float x = mGravity[0];
        float y = mGravity[1];
        float z = mGravity[2];
        mAccelLast = mAccelCurrent;
        mAccelCurrent = (float) Math.sqrt(x * x + y * y + z * z);
        float delta = mAccelCurrent - mAccelLast;
        mAccel = mAccel * 0.9f + delta;
        mAccel = abs(mAccel);
        textView.setText("a:"+mAccel);
        if (abs(mAccel) > 5.0f) { // Shake detection
            mTimer.schedule(new TimerTask() { 
            //start after 2 second delay to make acceleration values "rest"

                @Override
                public void run() {
                    firstTimer.start();
                }

            }, 2000);
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM