android 求list平均值_java – 收集特定时期的android传感器并计算平均值

我正在尝试编写一种方法,该方法在特定时间段内收集加速度计传感器值,并返回该时间段内传感器读数的平均值.

它应该是一个同步即阻塞方法,一旦被调用它将阻塞调用线程一段时间然后将返回传感器平均值

我确实检查了下面类似的问题,但似乎没有适合我的案例的正确解决方案:

我也试过使用类似于this question的Executors,但是无法按照我的意愿使用它.

下面是我的代码框架,其中方法sensorAverage是一种阻塞方法,它将计算加速度计传感器在一段时间内的平均值等于超时参数

Average average = new Average(); // Some class to calculate the mean

double sensorAverage(long timeout){

Sensor sensor = sensorManager.getDefaultSensor(Sensor.TYPE_LINEAR_ACCELERATION);

sensorManager.registerListener(this, sensor,SensorManager.SENSOR_DELAY_NORMAL);

// This does not work

Thread.sleep(timeout);

sensorManager.unregisterListener(this);

return average.value();

}

public void onSensorChanged(SensorEvent event) {

if (event.sensor.getType() == Sensor.TYPE_LINEAR_ACCELERATION) {

double x2 = Math.pow(event.values[0], 2);

double y2 = Math.pow(event.values[1], 2);

double z2 = Math.pow(event.values[2], 2);

average.add(Math.sqrt((x2 + y2 + z2)));

}

}

编辑:

我知道我需要另一个线程,但是我需要在特定时间内运行它的问题,到目前为止我找不到合适的工作解决方案.因为当我使用另一个线程时,我得到的传感器平均值始终为0

解决方法:

我设法实现了一个完全符合我想要的解决方案.

一种阻塞方法,用于收集特定时间段的传感器值并返回所有传感器读数的统计数据,即均值和方差.

可以简单地存储所有传感器的值,然后计算均值和方差;但是,如果在长时间内收集高频传感器,可能会耗尽内存.

我找到了一个更好的解决方案,使用下面的RunningStat类实时计算数据流的均值和方差(即不存储传感器值)

示例代码:

// Calculate statistics of accelerometer values over 300 ms (a blocking method)

RunningStat[] stats = SensorUtils.sensorStats(context,

Sensor.TYPE_ACCELEROMETER, 300)

double xMean = stats[0].mean();

double xVar = stats[0].variance();

全班代码:

public class SensorUtils {

// Collect sensors data for specific period and return statistics of

// sensor values e.g. mean and variance for x, y and z-axis

public static RunningStat[] sensorStats(Context context, int sensorType,

long timeout) throws Exception {

ExecutorService executor = Executors.newSingleThreadExecutor();

Future future = executor.submit(new SensorTask(context,

sensorType, timeout));

RunningStat[] stats = future.get();

return stats;

}

private static class SensorTask implements Callable {

private final Context context;

private final long timeout;

private final int sensorType;

// We need a dedicated handler for the onSensorChanged

HandlerThread handler = new HandlerThread("SensorHandlerThread");

public SensorTask(Context context, int sensorType, long timeout) {

this.context = context;

this.timeout = timeout;

this.sensorType = sensorType;

}

@Override

public RunningStat[] call() throws Exception {

final SensorCollector collector = new SensorCollector(context);

handler.start();

Thread sensorThread = new Thread() {

public void run() {

collector.start(sensorType,

new Handler(handler.getLooper()));

};

};

sensorThread.start();

Thread.sleep(timeout);

return collector.finishWithResult();

}

}

private static class SensorCollector implements SensorEventListener {

protected Context context;

protected RunningStat[] runningStat;

protected SensorManager sensorManager;

protected int sensorType;

public SensorCollector(Context context) {

this.context = context;

}

protected void start(int sensorType, Handler handle) {

if (runningStat == null) {

runningStat = new RunningStat[3];

runningStat[0] = new RunningStat(3);

runningStat[1] = new RunningStat(3);

runningStat[2] = new RunningStat(3);

} else {

runningStat[0].clear();

runningStat[1].clear();

runningStat[2].clear();

}

this.sensorType = sensorType;

sensorManager = (SensorManager) context

.getSystemService(Context.SENSOR_SERVICE);

Sensor sensor = sensorManager.getDefaultSensor(sensorType);

sensorManager.registerListener(this, sensor,

SensorManager.SENSOR_DELAY_NORMAL, handle);

}

public RunningStat[] finishWithResult() {

if (sensorManager != null) {

sensorManager.unregisterListener(this);

}

return runningStat;

}

@Override

public void onAccuracyChanged(Sensor sensor, int accuracy) {

}

@Override

public void onSensorChanged(SensorEvent event) {

if (event.sensor.getType() == sensorType) {

runningStat[0].push(event.values[0]);

runningStat[1].push(event.values[1]);

runningStat[2].push(event.values[2]);

}

}

}

}

这是RunningStat代码,它是一个非常方便的类,用于计算数据流的均值和方差而不存储数据本身(非常适合计算内存占用非常小的高频传感器的统计数据)

//See Knuth TAOCP vol 2, 3rd edition, page 232

public class RunningStat {

private int n;

private double oldM, newM, oldS, newS;

private int precision = -1;

// An estimate for the t-value (can be read from the t-distribution table)

private static final double T_THRESHOLD = 1.68;

public RunningStat(int precision) {

this.precision = precision;

}

public RunningStat() {

}

public void clear() {

n = 0;

}

public void push(double x) {

n++;

if (n == 1) {

oldM = newM = x;

oldS = 0.0;

} else {

newM = oldM + (x - oldM) / n;

newS = oldS + (x - oldM) * (x - newM);

// set up for next iteration

oldM = newM;

oldS = newS;

}

}

public int count() {

return n;

}

public double mean() {

double mean = (n > 0) ? newM : 0.0;

if (precision > 0) {

return round(mean, precision);

}

return mean;

}

// The upper bound of the mean confidence interval

public double meanUpper() {

double mean = (n > 0) ? newM : 0.0;

double stdError = stdDeviation() / Math.sqrt(n);

double upperMean = mean + T_THRESHOLD * stdError;

if (precision > 0) {

return round((n > 0) ? upperMean : 0.0, precision);

}

return upperMean;

}

// The lower bound of the mean confidence interval

public double meanLower() {

double mean = (n > 0) ? newM : 0.0;

double stdError = stdDeviation() / Math.sqrt(n);

double lowerMean = mean - T_THRESHOLD * stdError;

if (precision > 0) {

return round((n > 0) ? lowerMean : 0.0, precision);

}

return lowerMean;

}

public double variance() {

if (precision > 0) {

return round(((n > 1) ? newS / (n - 1) : 0.0), precision);

}

return ((n > 1) ? newS / (n - 1) : 0.0);

}

public double stdDeviation() {

if (precision > 0) {

return round(Math.sqrt(variance()), precision);

}

return Math.sqrt(variance());

}

public void setPrecision(int precision) {

this.precision = precision;

}

public static double round(double value, int precision) {

BigDecimal num = new BigDecimal(value);

num = num.round(new MathContext(precision, RoundingMode.HALF_UP));

return num.doubleValue();

}

// A small test case

public static void main(String[] args) {

int n = 100;

RunningStat runningStat = new RunningStat();

double[] data = new double[n];

double sum = 0.0;

for (int i = 0; i < n; i++) {

data[i] = i * i;

sum += data[i];

runningStat.push(data[i]);

System.out.println(runningStat.mean() + " - "

+ runningStat.variance() + " - "

+ runningStat.stdDeviation());

}

double mean = sum / n;

double sum2 = 0.0;

for (int i = 0; i < n; i++) {

sum2 = sum2 + (data[i] - mean) * (data[i] - mean);

}

double variance = sum2 / (n - 1);

System.out.println("\n\n" + mean + " - " + variance + " - "

+ Math.sqrt(variance));

}

}

标签:java,android,multithreading,android-sensors

来源: https://codeday.me/bug/20190517/1120173.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值