[英]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.