因此,我使用加速度计来检查手机是否掉落。这部分工作很好。我将以下给出的链接用于上述目的。https://github.com/altermarkive/experimental-fall-detector-android-app
现在,下一步是计算它垂直移动的距离。我为此目的尝试了很多事情,但是每次高度都不正确时。另外,高度在不同设备上的变化也不同。
我从加速度传感器获得加速度数据,之后我使用下面给出的公式来计算行进距离。
我尝试的第一个代码:-
long curTime = System.currentTimeMillis();
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
// sampling frequency f= 10Hz.
if ((curTime - lastUpdate) > CHECK_INTERVAL) {
long diffTime = (curTime - lastUpdate);
lastUpdate = curTime;
accel_values = event.values.clone();
if (last_accel_values != null) {
mAccelLast = mAccelCurrent;
mAccelCurrent =(float)Math.sqrt(accel_values[0]* accel_values[0] +
accel_values[1]*accel_values[1]
+ accel_values[2]*accel_values[2]);
Message msg = mHandler.obtainMessage(Constants.MESSAGE_CHANGED);
Bundle bundle = new Bundle();
bundle.putFloat(Constants.VALUE, mAccelCurrent);
msg.setData(bundle);
mHandler.sendMessage(msg);
mWindow.add(mAccelCurrent);
if (mWindow.isFull() && mWindow.isFallDetected()){
Log.w(TAG, "Fall detected by window class");
actime = curTime - diffTime;
velocity = actime * acceleration;
avgvelocity = velocity / 2;
height = avgvelocity * actime;
mWindow.clear();
msg = mHandler.obtainMessage(Constants.MESSAGE_EMERGENCY);
mHandler.sendMessage(msg);
}
}
last_accel_values = accel_values.clone();
}
}
我尝试的第二个代码:-
final double alpha = 0.8;
double gravity[] = new double[3], linear_acceleration[] = new double[3];
// Isolate the force of gravity with the low-pass filter.
gravity[0] = alpha * gravity[0] + (1 - alpha) * sensorEvent.values[0];
gravity[1] = alpha * gravity[1] + (1 - alpha) * sensorEvent.values[1];
gravity[2] = alpha * gravity[2] + (1 - alpha) * sensorEvent.values[2];
double curr_gravity = gravity[0] + gravity[1] + gravity[2];
// Remove the gravity contribution with the high-pass filter.
linear_acceleration[0] = sensorEvent.values[0] - gravity[0];
linear_acceleration[1] = sensorEvent.values[1] - gravity[1];
linear_acceleration[2] = sensorEvent.values[2] - gravity[2];
double curr_acc = linear_acceleration[0] + linear_acceleration[1] + linear_acceleration[2];
long seconds = System.currentTimeMillis();
double velocity = curr_acc * seconds;
double init_vel = velocity / 2;
double time = (velocity - init_vel) / curr_gravity;
double height = (((seconds * 9.8)/2) - init_vel);
我尝试的第三个公式:-
long curTime = System.currentTimeMillis();
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
// sampling frequency f= 10Hz.
if ((curTime - lastUpdate) > CHECK_INTERVAL) {
long diffTime = (curTime - lastUpdate);
lastUpdate = curTime;
accel_values = event.values.clone();
if (last_accel_values != null) {
mAccelLast = mAccelCurrent;
mAccelCurrent =(float)Math.sqrt(accel_values[0]* accel_values[0] +
accel_values[1]*accel_values[1]
+ accel_values[2]*accel_values[2]);
Message msg = mHandler.obtainMessage(Constants.MESSAGE_CHANGED);
Bundle bundle = new Bundle();
bundle.putFloat(Constants.VALUE, mAccelCurrent);
msg.setData(bundle);
mHandler.sendMessage(msg);
mWindow.add(mAccelCurrent);
if (mWindow.isFull() && mWindow.isFallDetected()){
Log.w(TAG, "Fall detected by window class");
actime = curTime - diffTime;
height = 0.5*9.8*actime*actime;
mWindow.clear();
msg = mHandler.obtainMessage(Constants.MESSAGE_EMERGENCY);
mHandler.sendMessage(msg);
}
}
last_accel_values = accel_values.clone();
}
}
我还尝试过将其他传感器用于同一目的,例如晴雨表,但从中得到相同的结果(高度并没有达到预期的水平)。另外,我尝试寻找第三方SDK,但它们也使用自己的硬件。任何帮助将不胜感激。同样,如果有人可以以正确的方式进行指导,那将非常有帮助。预先感谢。
似乎您在这三种方法中都有相同的错误。在这三者中,有时都将加速度乘以System.currentTimeMillis()
的绝对时间戳。这是自1970年以来的毫秒数,在您的情况下没有直接含义,除非您使用它来计算时间间隔作为差异。在某些示例中,您执行了此操作,但是您再次从System.currentTimeMillis()
中减去了它,这再次导致自1970年以来的毫秒数。
似乎您尝试实现s = 1/2 at²,但这仅对于在时间间隔t内从静止状态持续加速的情况下有效。如果要从一系列测量加速度中得出距离,则需要对它们进行数值积分(听起来比实际困难),并且可能需要使用一些滤波。
但是,我的建议是假设自由落体的加速度为9.81 m /s²。这忽略了空气阻力或地球加速度的局部变化,但是除非您想在某些奇怪的情况下使用它,否则它可能比使用传感器的读数精确得多。特别是当手机旋转时,还由于校准不当以及某些过滤将实际加速度与重力加速度分开,我不希望传感器的读数优于逼近完美的自由落体。毕竟,智能手机是比较稠密的物体,不受空气阻力的影响很大。
好处是,您可以简单地使用s = 1/2 at²。只要确保t不是1970年以来的时间间隔,而是从跌落开始(您说可以可靠地检测到)到跌落结束(即开始和结束之间的时间戳记之差)的计时器间隔即可。最后的时间戳记)。另外,我建议使用来自传感器事件的时间而不是System.currentTimeMillis()
,因为它具有更好的分辨率,并且是针对这种类型的计算而设计的。