gpt4 book ai didi

java - Androidplot:具有特定扫描速率的动态绘图

转载 作者:行者123 更新时间:2023-12-01 12:29:06 25 4
gpt4 key购买 nike

我正在使用 androidplot 每分钟循环显示脉冲(本质上是相对较短的点序列)n 次,其余时间显示平坦值。开始处有一个删除栏,可删除 50 个最旧的点。但我不知道如何以特定的时间间隔(run() 中的延迟)更新该图形,以便该系列以 25 毫米/秒的速度扫描。

private class PulseXYSeries implements XYSeries {

private ArrayList<Integer> values;
private String title;
public PulseXYSeries(String title, int size) {
values = new ArrayList<Integer>(size);
for(int i = 0; i < size;i++) {
values.add(null);
}
this.title = title;
}
@Override
public String getTitle() {
return title;
}

public void remove(int idx) {
values.set(idx, null);
}
public void setY(int val, int idx) {
values.set(idx, val);
}
@Override
public Number getX(int idx) {
return idx;
}

@Override
public Number getY(int idx) {
if(idx >= values.size())
return null;
return values.get(idx);
}

@Override
public int size() {
return values.size();
}

}

private class MonitorDataSource implements Runnable {
private final int SAMPLE_SIZE = 1000;
private boolean keepRunning = false;
private List<Integer> queue;
private int flat;
private Thread rd;

MonitorDataSource(View rootView) {
queue = getSelectedPointData(rootView);
flat = queue.get(0);
rd = new Thread(/** runnable that calls dynamicPlot.redraw() at 30Hz **/);
rd.start();
}
public void stopThread() {
keepRunning = false;
rd.interrupt();
}

public void run() {
try {
Log.i(TAG,"Running pulse thread");
keepRunning = true;
int i=0;
boolean pulsing = true;
long lastPulse = SystemClock.elapsedRealtime();
long pulseDelay = 1000*60/mHeartRatePicker.getValue();
int position = 0;
// we need to scan at 25mm/sec
long delay = 10;
DisplayMetrics dp = getResources().getDisplayMetrics();
float plotWidth = dynamicPlot.getGraphWidget().getWidgetDimensions().canvasRect.width();
float plotWidthMm = plotWidth / dp.xdpi * 25.4f;
float widthPerTickInMm = plotWidthMm/(float)SAMPLE_SIZE;
Log.i(TAG,"Width per tick: "+widthPerTickInMm+" plot width px="+plotWidth+" in mm="+plotWidthMm+" xdpi="+dp.xdpi+" xdpmm="+(dp.xdpi*(1.0f/25.4f)));
long currTime,loopStart = SystemClock.elapsedRealtimeNanos();
while (keepRunning) {
// plot 4 points at a time
for (int j = 0; j < 3; j++) {
if(pulsing) {
mMovingWaveSeries.setY(queue.get(i),position);
if(++i == queue.size()-1) {
pulsing = false;
i=0;
}
} else {
mMovingWaveSeries.setY(flat,position);
currTime = SystemClock.elapsedRealtime();
if(currTime - lastPulse >= pulseDelay) {
pulsing = true;
lastPulse = currTime;
}
}
mMovingWaveSeries.remove(((position + 50) % SAMPLE_SIZE));
position = (position+1) % SAMPLE_SIZE;
if(position +1 >= SAMPLE_SIZE) {
float diff = (SystemClock.elapsedRealtimeNanos() - loopStart )/ 1000000000f;
loopStart = SystemClock.elapsedRealtimeNanos();
Log.i(TAG,"Looped through "+plotWidthMm+"mm in "+diff+"s = "+ (plotWidthMm/diff) +"mm/s");
}
}
Thread.sleep(delay);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

最佳答案

您的代码中似乎缺少的是当前扫描速率的瞬时测量(以毫米为单位)。您可以使用此值来调整绘图域的比例以获得所需的效果。这是通过XYPlot.setDomainBoundaries(...)完成的。可以调整域比例和采样频率(似乎由代码中的“延迟”表示)以相互补偿,因此如果您需要保持特定的域比例,请相应地调整采样频率。如果做得正确,渲染频率根本不重要,并且可以允许 float ......事实上,调节刷新率来补偿采样率通常会导致缓冲区溢出/欠载问题。

更新(回复以下评论)

看来您实际上是在限制数据源(采样率),而不是绘图(刷新率),这很好。您需要做的第一件事是根据 widthPerTickInMm 和每个循环中绘制的点数确定达到 25 毫米/秒所需的循环频率:

频率(Hz) = 25/(widthPerTickInMm * pointsPerLoop)

使用此值来调整数据源更新循环。以下是如何以给定频率动态调制任意循环的示例:

       float hz = 5; // modulate at 5hz
long budget = (long) ((1/hz) * 1000f);
long loopDurationMs = 0;
long loopStartMs = 0;
while(true) {
// calculate how long this loop took:
long now = System.currentTimeMillis();
loopDurationMs = now - loopStartMs;
long sleepTime = budget - loopDurationMs;
loopStartMs = now;
if(sleepTime > 0) {
try {
Thread.sleep(sleepTime);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}

只是一个警告 - 我没有尝试编译或运行代码,但概念就在那里。 (这仅在您的潜在循环频率 > 所需频率时才有效......可能很明显,但以防万一)

关于java - Androidplot:具有特定扫描速率的动态绘图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26095538/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com