2014-09-29 1 views
0

나는 펄스의 표시를 반복하는 androidplot을 사용하여 분당 n 회 및 평평한 값을 남깁니다. 50 개의 가장 오래된 점을 제거하는 시작 부분에 지우기 표시 줄이 있습니다. 하지만 특정 간격 (run()의 지연)으로 해당 그래프를 업데이트하는 방법을 알 수 없기 때문에 시리즈가 25mm/초로 스캔됩니다.Androidplot : 특정 스캔 속도의 동적 플롯

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(); 
     } 
    } 
} 
+0

데이터가 화면에서 25 밀리미터/초의 속도로 스크롤되기를 원하십니까? 그렇다면 현재 귀하가 현재 가지고있는 것에 얼마나 가까운 결과가 있습니까? – Nick

+0

맞습니다. –

답변

1

코드에서 부족한 부분은 현재 스캔 속도 (mm)의 즉각적인 측정입니다. 이 값을 사용하여 원하는 효과를 얻으려면 플롯 도메인의 크기를 조정할 수 있습니다. 이것은 XYPlot.setDomainBoundaries (...)을 통해 이루어집니다. 도메인 규모와 샘플 빈도 (코드에서 "지연"으로 표시)는 서로 보정 할 수 있으므로 특정 도메인 배율을 유지해야하는 경우 이에 따라 샘플링 빈도를 조정하십시오. 제대로 실행되면 렌더링 빈도가 전혀 중요하지 않아서 플로트 할 수 있습니다. 실제로 샘플 속도를 보정하기 위해 주사율을 변조하면 일반적으로 버퍼 오버런/언더런 문제가 발생합니다.

UPDATE (아래 주석에 응답)

실제로 데이터 소스 (샘플 속도)를 조절하고 있다는 나타납니다, 괜찮하지 플롯 (주사율). 가장 먼저 할 일은 widthPerTickInMm을 기준으로 25mm/초를 달성하는 데 필요한 루프 빈도와 각 루프에서 그리는 점의 수를 결정하는 것입니다.

주파수 (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); 
       } 
      } 
     } 

그냥 경고 : 다음은 동적으로 주어진 주파수에서 임의의 루프를 조절하는 방법의 예입니다. (이것은 잠재적 인 루프 주파수가 원하는 주파수보다 큰 경우에만 작동합니다 ... 아마도 분명하지만 그렇습니다)

+0

경계가 결코 바뀌지 않도록 플롯이 시작 지점으로 돌아갈 때 도메인 경계를 조정하고 싶지 않습니다. 내 테스트에서 그것은 ~ 5.2s에서 음모의 폭을 스캔합니다. 또한,'redraw()'를 반복적으로 호출하면 GC가 실행되고, androidplot 소스에서 할당이 발생하는 위치를 파악할 수 없다. 저는 매 루프마다 3 점을 플로팅하여 24.5mm/s를 달성했습니다. 지연이나 각 루프에서 플롯 된 점의 수를 자동으로 조정할 수있는 방법에 대한 몇 가지 코드를 제공 할 수 있습니까? 내 코드를 업데이트했습니다. –

+0

내 대답 업데이트 – Nick