FIFO Queue Problem with Code

Hi There, I need to implement a queue for one of my programs. I seem to have got some problems with getting the intended results.

My program is as follows. It reads a random set of values. The array is of 20 elements. once it is filled (i.e. 20 elements are pushed(queued ?), and the array is full) the first number (FIFO) is popped(dequeued) out. this process is repeated for 100 times. i.e. the first 80 values are popped out sequentially.

Maybe the program itself does not make sense, but actually in my final implementation, the data that are sent are not random numbers but data from a sensor. I plan to make some calculations using an average of the data in the queue before popping them one at a time.

In my implementation I cant seem to push numbers in after first round of 20 elements...

Many Thanks in advance, Genny

        int bufferSize = 20;
        int num=0;
        void setup()
        {
        }
        void draw() {
          background(0);
          println("****");
          QueueDemo queueDemo = new QueueDemo();
          for (int frame = 1; frame <100;frame++) {
            //read data from arduino
            num =   int(random(0, 15));
            //println(num);
            if (frame < bufferSize) {
              queueDemo.push(num);
              queueDemo.display();
            }
            else {
              queueDemo.display();
              queueDemo.pop();
              queueDemo.push(num);
              queueDemo.display();
            }
          }

          exit();
        }

public class QueueDemo {
  final int capacity = bufferSize;
  int arr[] = new int[capacity];
  //int size = 0;
  int top = -1;
  int rear = 0;

  public void push(int pushedElement) {
    if (top < capacity - 1) {
      top++;
      arr[top] = pushedElement;
      println("Element " + pushedElement
        + " is pushed to Queue !");
      //display();
    } 
    else {
      println("Overflow !");
    }
  }

  public void pop() {
    if (top >= rear) {
      rear++;
      println("Pop operation done !");
      //display();
      top--;
    } 
    else {
      println("Underflow !");
    }
  }

  public void display() {
    if (top >= rear) {
      print("Elements in Queue : ");
      for (int i = rear; i <= top; i++) {
        print(arr[i]);
        print(" ");
      }
      println("");
    }
  }
}

Answers

  • edited June 2016 Answer ✓

    Why ru creating your own QueueDemo implementation rather than using Java's bundled libraries? :-&

    I bet using an ArrayDeque as a Queue would be less prone to bugs? %%-

    Take a look at this example:

    /** 
     * Brownian Motion (v2.32)
     * by  Ammon.Owed (2013/Aug)
     * mod GoToLoop
     * 
     * forum.Processing.org/one/topic/controlling-the-length-of-line-
     * from-x-y-to-a-point-which-is-randomly-chosen
     *
     * forum.Processing.org/two/discussion/2829/fifo-queue-problem-with-code
     */
    
    import java.util.Queue;
    import java.util.ArrayDeque;
    
    static final int DIM = 100, MAX = 03000, DETAIL = 1000, DEPTH = 2000;
    static final int HUE = 1<<10, FPS = 60, TOLERANCE = 40, ALIASING = 2;
    
    static final float BOLD = 1.5, AMP = 10.0;
    static final boolean HAS_MAX_LIMIT = true;
    
    final Queue<PVector> points = new ArrayDeque(MAX);
    final PVector cam = new PVector(), lp = new PVector();
    
    float canvasRatio, zNear, zFar;
    
    void setup() {
      size(1000, 700, P3D);
      colorMode(HSB, HUE, 1, 1);
    
      frameRate(FPS);
      smooth(ALIASING);
    
      strokeWeight(BOLD);
      noFill();
    
      canvasRatio = (float) width/height;
    
      final float camZ = .5*height / tan(PI*FPS/360.0);
      zNear = camZ/AMP;
      zFar  = camZ*AMP;
    
      frameRate = TOLERANCE<<1;
    }
    
    void draw() {
      // local-cached & short-named variables:
      int fc = frameCount;
      final int fr = round(frameRate);
    
      // recycled or new vector point:
      final PVector np = 
        HAS_MAX_LIMIT & fc > MAX | !HAS_MAX_LIMIT & fr < TOLERANCE
        ? points.remove() : new PVector();
    
      // interpolated rotating camera aimed at latest added point (tail):
      cam.mult(.99);
      cam.add(PVector.mult(lp, .01, np));
    
      camera(cam.x + sin(fc*.01)*DETAIL, cam.y + cos(10.0 + fc*8e-3)*DETAIL, 
      cam.z - DEPTH, cam.x, cam.y, cam.z, 0, 1, 0);
    
      //perspective();
      perspective(THIRD_PI, canvasRatio, zNear, zFar);
    
      // draw colored curved lines:
      clear();
    
      beginShape();
    
      for (final PVector p : points) {
        stroke(fc++ & HUE-1, 1, 1);
        curveVertex(p.x, p.y, p.z);
      }
    
      endShape();
    
      // generate a new point at specified range:
      PVector.random3D(np, this).mult(DIM); // pick a new random direction.
      np.add(lp);                           // add that up from latest point.
      lp.set(np);                           // this is now the latest point too.
    
      points.add(np);                       // add new point to queue's tail.
    
      frame.setTitle("Brownian Motion   FPS: " + fr +
        "   Size: " + points.size());
    }
    
  • edited February 2014

    Thanks for your suggestion. Actually I wasn't that conversant on Java. Hence the idea of writing the code. But I'm studying your suggested solution as an example. In it I notice that "points" is the Queue. My knowledge on graphics is a bit below par, So the methods used in the example are add, remove only are needed for queue operations : push , pop in my example ?

  • edited February 2014

    Actually, I've got no idea how that algorithm works mathematically either. I'm not its creator! :-S
    Nonetheless, I did tweaked it from a List and its slow remove(0) method to a more efficient Queue (FIFO) data-structure! :ar!

    Yup! Only add() & remove() plus an unnecessary size() are used on the ArrayDeque object referenced by points there!
    And in every draw() iteration, a new PVector is added at its back position (tail).

    However, when some chosen constraint occurs, either MAX # of elements is reached or frameRate drops too much,
    the oldest object is removed from its front position (head), and recycled back as a new element to the back (tail).

    ... push(), pop() in my example ?

    Those method names are traditionally used for Stack (LIFO) structures instead. (%)

  • edited February 2014 Answer ✓

    writing a queue is a pretty useful thing to know how to do, though, even if it's not really necessary. Here's one way to write one:

    class Element {
      int v;
      Element next;
    
      Element(int v, Element next) {
        this.v = v;
        this.next = next;
      }
    }
    
    class Queue {
      private Element first;
      private Element last;
      private int count;
    
      Queue() {
      }
    
      boolean empty() {
        return count == 0;
      }
    
      void push(int v) {
        Element e = new Element(v, null);
        if (this.first == null) {
          this.first = e;
        }
        if (this.last != null) {
          this.last.next = e;
        }
        this.last = e;
        this.count++;
      }
    
      int pop() throws ArrayIndexOutOfBoundsException {
        if (count == 0) {
          throw new ArrayIndexOutOfBoundsException("pop on empty queue");
        }
        int v = this.first.v;
        this.first = this.first.next;
        this.count--;
        return v;
      }
    
      String toString() {
        String buf = "[";
        Element e = this.first;
        while (e != null) {
          buf += e.v;
          if (e.next != null) {
            buf += ", ";
          }
          e = e.next;
        }
        buf += "]";
        return buf;
      }
    }
    
    void setup() {
      noLoop();
    }
    
    void draw() {
      Queue q = new Queue();
      println(q);
      q.push(1);
      println(q);
      q.push(5);
      println(q);
      q.push(12);
      println(q);
      println(q.pop());
      println(q);
      println(q.pop());
      println(q);
      q.push(3);
      println(q);
      q.push(3);
      q.push(97);
      q.push(0);
      q.push(-1);
      while (!q.empty()) {
        println(q);
        q.pop();
      }
    }
    

    the built-int java Queue class is better because it's generic, so you can make a Queue of any type, but a queue is really just a linked list with some methods to help you add and remove elements.

    oh and if you define the method named toString and have it return a String, then that method will be called when you use println (or anything that requires a string, for that matter).

  • edited February 2014

    The built-int java Queue class is better because it's generic, so you can make a Queue of any type,

    Actually it is an interface! And besides being generic, capable of storing PVector references for example,
    it also implements the Iterable interface, so we can use it in a loop! o->

    ... but a queue is really just a linked list with some methods to help you add and remove elements.

    Most queue implementations indeed use linked nodes as yours. But the class I used in my example is an ArrayDeque, which is a resizable array implementation of the Deque interface:

    docs.oracle.com/javase/7/docs/api/java/util/ArrayDeque.html

    For an example of an unbounded thread-safe queue based on linked nodes, try out ConcurrentLinkedQueue class:

    docs.oracle.com/javase/7/docs/api/java/util/concurrent/ConcurrentLinkedQueue.html

    To modify Brownian Motion to use a ConcurrentLinkedQueue instead, just make these 2 tiny changes:

    1. #11 -> import java.util.concurrent.ConcurrentLinkedQueue;
    2. #19 -> final Queue<PVector> points = new ConcurrentLinkedQueue();

    Or even a doubly-linked list implementation -> LinkedList:

    1. #11 -> import java.util.LinkedList;
    2. #19 -> final Queue<PVector> points = new LinkedList();
  • edited February 2014

    Dear All, thank you for the constructive advice. I've tried to re-write my program, using ArrayDequeue class. I seem to have hit a problem with the Pvector implementation in above example. As my programming in processing has been a bit of ver. 1.5 i'm rather new with the pvector class. Can we implement the dequqe for a data type like int used in my example....

    This is my current modified program using ArrayDeque

    import java.util.Queue;
    import java.util.ArrayDeque;
    
    final Queue<PVector> dataQueue = new ArrayDeque(bufferSize);
    
    static final int bufferSize = 20;
    int num=0;
    void setup()
    {
    }
    void draw() {
      background(0);
      println("****");
      println(dataQueue.size());
      //QueueDemo queueDemo = new QueueDemo();
      for (int frame = 1; frame <100;frame++) {
        //read data from arduino
        num =   int(random(0, 15));
        //println(num);
        if (dataQueue.size() < bufferSize) {
          dataQueue.add(num); //error here!
          //queueDemo.display();
        }
        else {
          //queueDemo.display();
          queueDemo.remove();
          //queueDemo.push(num);
          //queueDemo.display();
        }
      }
    
      exit();
    }
    

    in this case, I get an error :The method add(Pvector) in the type Queue is not applicable for the arguments. I noted from a reference site that for the ArrayDequeue : "As with the other collections classes, only Object types are supported." (Does it mean that primitive data types are not supported ?)

  • in line 4 you use pvector, in line 21 you add an int...

  • edited February 2014

    I cant seem to declare line 4 as int...

    final Queue<int> dataQueue = new ArrayDeque(bufferSize);

  • edited February 2014

    Java's API comes bundled w/ what is called the 8 primitive wrapper classes, each 1 representing 1 of the primitive types! @-)
    The corresponding wrapper class for int data-type is called Integer.
    Therefore, to have something like a Queue of int types, closest we can get is:

    static final int BUFFER_SIZE = 20;
    final Queue<Integer> dataQueue = new ArrayDeque(BUFFER_SIZE);

    Take a look at this post below to know more about the differences between primitive & object/reference types:

    http://forum.processing.org/two/discussion/2889/primitives-and-classes

    P.S.: Take notice that an ArrayDeque, just like an ArrayList, is boundless. We don't need to specify its capacity like a BUFFER_SIZE.
    When we add() a new element to it when its capacity is full, it automatically resizes itself bigger. So no worries! :D

  • edited February 2014

    Thank you GotoLoop for your detailed explanation...I didnt know about the wrapper classes. So this is my working program for now

    import java.util.Queue;
    import java.util.ArrayDeque;
    import java.util.Iterator;
    
    static final int bufferSize = 20;
    
    final Queue<Integer> dataQueue = new ArrayDeque(bufferSize);
    
    Integer num = new Integer(0);
    void setup()
    {
    }
    void draw() {
      background(0);
      println("****");
      println(dataQueue.size());
      for (int frame = 1; frame <100;frame++) {
        //read data from arduino
        num =   Integer.parseInt(str(int(random(0, 15))));
        if (dataQueue.size() < bufferSize) {
          dataQueue.add(num); 
          println(dataQueue.size());
          // getLast() will retrieve element at last position
          //int retval = dataQueue.getLast();
          //println("Retrieved Element is = " + retval);
        //println(dataQueue.getLast());
        }
        else {
          dataQueue.remove();
          //queueDemo.push(num);
          //queueDemo.display();
        }
      }
    // iterator() is used to print all the elements
    // next() returns the next element on each iteration
    println("printing elements using iterator:");
    for(Iterator itr = dataQueue.iterator();itr.hasNext();)  {
            System.out.println(itr.next());
      exit();
    }
    }
    

    But I still have some difficulty manipulating the dequeue objects - the method .getLast commented above doesnt work, although it is mentioned in the reference site you indicated.

    I understood your comment on the size. I was not aware of that either, although I knew there must be a dynamic queue implementation

  • edited February 2014

    The method getLast() commented above doesn't work,
    ... although it is mentioned in the reference site you indicated.

    That method isn't mentioned in the Queue interface, b/c it's actually a Stack (FIFO) method:

    http://docs.oracle.com/javase/7/docs/api/java/util/Queue.html

    Since your dataQueue variable is of Queue data-type, it's constrained to use only those set of methods,
    even though an ArrayDeque object has many more!!! >:)

    If you really wanna get access to those FIFO methods, declare dataQueue as a Deque type instead.
    But you would be mixing up LIFO & FIFO together; an unholy mess! X_X

    Anyways, there's no logic in doing so, b/c when we issue the add() method, it enqueues an element as the last 1 already.

    final int num = (int) random(15);
    dataQueue.add(num);  // enqueuing as last element (queue's tail position)
    
    // why would we need getLast() if we already know num is the latest enqueued element???
    int retVal = dataQueue.getLast(); 
    

    Therefore it's really redundant asking for last element when we're doing queues (FIFO)!
    Just use a variable to store and keep track about that information if you need that so! 8-X

  • edited February 2014

    About your latest posted code, you're over complicating things:

    Java automatically takes care on converting back & forth primitive values to their corresponding wrapper classes for us!

    You don't need this wreckage long train of methods:
    Integer num = Integer.parseInt(str(int(random(0, 15))));

    This is quite enough:
    int num = (int) random(15);

    Neither explicitly use an Iterator to traverse any Collection such as an ArrayDeque.
    Java got an enhanced for loop which was created for such cases!
    Look at line #68 in the "Brownian Motion" example I've posted before. No explicit Iterator whatsoever:

    for (PVector p: points)  curveVertex(p.x, p.y, p.z);
    

    I still don't get how you wanna use the queue approach for your Arduino reading code. The following is my guess: :-/

    • Enqueue BUFFER_SIZE elements.
    • Dequeue & enqueue (MAX_READS - BUFFER_SIZE) elements.
    • Display the remaining BUFFER_SIZE elements.

    Anyways, I've tweaked your last code this way: ^#(^

    // forum.processing.org/two/discussion/2829/fifo-queue-problem-with-code
    
    import java.util.Queue;
    import java.util.ArrayDeque;
    
    final int BUFFER_SIZE = 20, MAX_READS = 100;
    final Queue<Integer> dataQueue = new ArrayDeque(BUFFER_SIZE);
    
    for (int frame = 0; frame++ != BUFFER_SIZE;) // filling up queue now.
      dataQueue.add((int) random(15));   // read data from Arduino & enqueue it.
    
    println("Dequeued readings: \n");
    
    for (int frame = BUFFER_SIZE; frame++ != MAX_READS;) {
      print(dataQueue.remove() + "\t");  // dequeue & display it.
      dataQueue.add((int) random(15));   // read data from Arduino & enqueue it.
    }
    
    println("\n\nReadings still enqueued: \n");
    
    // List all enqueued reads via enhanced for loop:
    for (Integer q: dataQueue)  print(q + "\t");
    //for (int q: dataQueue)  print(q + "\t");  // primitive int works as well!  >;-)
    
    println("\n\nFinal queue's size: \n\n" + dataQueue.size());
    
    exit();
    
  • edited February 2014

    Hi GotoLoop, Thank you very much for correcting my elementary mistakes. I thought to add items to the queue it must assigned via the Integer wrapper class object. 8-| I learnt from your suggestions, and modified code. But just to clarify my intentions :

    My code above was purely experimental, but this is roughly what i really wanted to do with processing

    1. Read Arduino Data (x,y) coordinate via COM ports (I know how to handle this, and it works fine)
    2. If elements in defined queue are less than BUFFER_SIZE, add element to the queue (buffer), repeat to step 1. If BUFFER_SIZE, go to step3
    3. When buffer reaches BUFFER_SIZE elements, use all elements in buffer for calculations such as average the Square x,y values of all items in buffer and output (AvgSqX and AvgSqY).
    4. Remove the top value of buffer (oldest) ie. remove item from queue
    5. Repeat from step 1 until end of data

    My experiment of using Integer queue was a start, as i read, i think in processing Pvectors maybe a better suited for my purpose. However, i'm wondering whether the arraydequeue methods will work for this now - As in each loop i have to average the values of all items in the queue.

  • edited February 2014

    I'm wondering whether the ArrayDeque's methods will work for this now.
    As in each loop I have to average the values of all items in the Queue.

    That makes no sense! Both my latest example & "Brownian Motion" codes show clearly we can iterate the whole Queue!

    This Arduino mock-up now demos again how to traverse a Queue and collect each PVector from it to obtain averages[] from it:

    // forum.processing.org/two/discussion/2829/fifo-queue-problem-with-code
    
    import java.util.Queue;
    import java.util.ArrayDeque;
    
    final int BUFFER_SIZE = 20, MAX_READS = 100, AMP = 150;
    final Queue<PVector> dataQueue = new ArrayDeque(BUFFER_SIZE);
    final PVector[] averages = new PVector[MAX_READS - BUFFER_SIZE];
    
    for (int frame = 0; frame++ != BUFFER_SIZE;)
      dataQueue.add(PVector.random2D(this));
    
    for (int frame = BUFFER_SIZE; frame++ != MAX_READS;) {
      final PVector avg = averages[frame - BUFFER_SIZE - 1] = new PVector();
    
      for (PVector dq: dataQueue)  avg.add(dq);
    
      avg.mult(AMP);
      avg.div(BUFFER_SIZE);
    
      dataQueue.remove();
      dataQueue.add(PVector.random2D(this));
    }
    
    println("All of the " + (MAX_READS - BUFFER_SIZE) +
    " Averages of " + BUFFER_SIZE + " PVector coords.: \n");
    
    for (PVector avg: averages)  print(avg + "\t");
    
    println("\n\nFinal Queue's Size: \n\n" + dataQueue.size());
    
    exit();
    
  • edited February 2014

    Thank you Gotoloop, and regret my delay in replying. I've noted the methods for the Pvector class, but how can i restrict the random numbers generated as done in the random function. for one, I cant seem to figure out how to fix the following modification. I've basically created a new Pvector (coord) which gets assigned a 2D random values and add it to the queue. Line 14 seems to be saying the local var may not have initialized.

    // forum.processing.org/two/discussion/2829/fifo-queue-problem-with-code
    
    import java.util.Queue;
    import java.util.ArrayDeque;
    
    final int BUFFER_SIZE = 20, MAX_READS = 100, AMP = 150;
    final Queue<PVector> dataQueue = new ArrayDeque(BUFFER_SIZE);
    final PVector[] averages = new PVector[MAX_READS - BUFFER_SIZE];
    PVector coord;
    
    for (int frame = 0; frame++ != BUFFER_SIZE;)
    
      coord = new PVector(random(0,15),random(0,15));
      dataQueue.add(coord);
    
    for (int frame = BUFFER_SIZE; frame++ != MAX_READS;) {
      final PVector avg = averages[frame - BUFFER_SIZE - 1] = new PVector();
    
      for (PVector dq: dataQueue)  avg.add(dq);
    
      avg.mult(AMP);
      avg.div(BUFFER_SIZE);
    
      dataQueue.remove();
      dataQueue.add(PVector.random2D(this));
    }
    
    println("All of the " + (MAX_READS - BUFFER_SIZE) +
    " Averages of " + BUFFER_SIZE + " PVector coords.: \n");
    
    for (PVector avg: averages)  print(avg + "\t");
    
    println("\n\nFinal Queue's Size: \n\n" + dataQueue.size());
    
    exit();
    
  • edited February 2014

    In branching blocks, like if (), for (), do (), while (), if we have only 1 statement, curly braces are optional.
    Otherwise, we have to scope the block belonging to the branch w/ them! 8-X
    In your case, line #14 doesn't belong to the branch for () @ line #11! (~~)

    Anyways, here's my 1-line block fix. I don't need {} again b/c it's just 1-statement block:

    for (int frame = 0; frame++ != BUFFER_SIZE;)
      dataQueue.add(new PVector(random(AMP), random(AMP)));
    
  • Thank you yes, I did miss the braces..One (hopefully) final question. In my previous code, In the main loop (code lines 16-26) I need to calculate the average of the first three values in queue - Avg(P1,P2,P3) and last three values in queue - Avg (P18,P19,P20) (during each iteration - and output them to screen each time) ) I learnt from you that the queue iteration, can be simple as line 19, but when we want to add only few selected elements in the queue , how would we proceed ?. My understanding is to use a counter, and total values each time.

  • edited February 2014

    Oh, now I got why you wanted the getLast() method from the Deque interface! b-(
    Anyways, since a Queue got its elements ordered, we just need to get both the 1st 3 & last 3 readings while iterating over it! %%-
    And since an enhanced for loop doesn't provide us a counter, we gotta make ourselves 1!
    And this is how I've implemented the whole iteration selective capturing: :ar!

    int counter = -1;
    for (PVector dq: dataQueue)
      if (++counter < SAMPLE)                    oldest.add(dq);
      else if (counter >= BUFFER_SIZE - SAMPLE)  newest.add(dq);
    
    • SAMPLE constant represents the # of elements to average upon. In your case it's 3.
    • When counter is < SAMPLE, sum to the oldest PVector w/ the 1 read from the Queue.
    • BUFFER_SIZE - SAMPLE is the antepenult element of the Queue. That is 20 - 3 = 17.
    • So when counter is >= SAMPLE, sum to the newest PVector the 1 read from the Queue.
    • Otherwise, ignore current dq. [-X

    Whole fixed code below. Any further doubts or tweaks, just ask: =:)

    // forum.processing.org/two/discussion/2829/fifo-queue-problem-with-code
    
    import java.util.Queue;
    import java.util.ArrayDeque;
    
    final int BUFFER_SIZE = 20, MAX_READS = 100, RANGE = 15, SAMPLE = 3;
    final Queue<PVector> dataQueue = new ArrayDeque(BUFFER_SIZE);
    final PVector[] oldAvgs = new PVector[MAX_READS - BUFFER_SIZE];
    final PVector[] newAvgs = new PVector[MAX_READS - BUFFER_SIZE];
    
    for ( int frame = BUFFER_SIZE; --frame != 0; dataQueue.add(
        new PVector(random(RANGE), random(RANGE))) );
    
    println(dataQueue.size() + "\n"); // 19 elements up till now.
    
    for ( int frame = BUFFER_SIZE - 1; ++frame != MAX_READS; dataQueue.remove() ) {
      dataQueue.add( new PVector(random(RANGE), random(RANGE)) ); // full 20 elements.
    
      final PVector oldest = oldAvgs[frame - BUFFER_SIZE] = new PVector();
      final PVector newest = newAvgs[frame - BUFFER_SIZE] = new PVector();
    
      int counter = -1;
      for (PVector dq: dataQueue)
        if (++counter < SAMPLE)                    oldest.add(dq);
        else if (counter >= BUFFER_SIZE - SAMPLE)  newest.add(dq);
    
      oldest.div(SAMPLE);
      newest.div(SAMPLE);
    }
    
    println("All of the " + (MAX_READS - BUFFER_SIZE) +
    " Averages of the " + SAMPLE + " oldest PVector coords. within queue: \n");
    
    for (PVector oldest: oldAvgs)  print(oldest + "\t");
    
    println("\n\nAll of the " + (MAX_READS - BUFFER_SIZE) +
    " Averages of the " + SAMPLE + " newest PVector coords. within queue: \n");
    
    for (PVector newest: newAvgs)  print(newest + "\t");
    
    exit();
    
  • edited February 2014 Answer ✓

    Hey again! I did a remix of the same code. But this time, rather than instantiate a new PVector object when the Queue is full,
    it re-uses the removed oldest PVector, gives it new values, then re-insert it as newest element at the tail of the Queue.
    Just like I did w/ "Brownian Motion" code. Check it out: >:)

    /**
     * Queue Selective Average (v2.0)
     * by  GoToLoop (2014/Feb)
     * for Gennylk
     *
     * forum.processing.org/two/discussion/2829/fifo-queue-problem-with-code
     */
    
    // Import both interface & class for a queue data-structure storage:
    import java.util.Queue;
    import java.util.ArrayDeque;
    
    // Initiate constants and data-structures: 
    final int BUFFER_SIZE = 20, MAX_READS = 100, RANGE = 15, SAMPLE = 3;
    final Queue<PVector> dataQueue = new ArrayDeque(BUFFER_SIZE);
    final PVector[] oldAvgs = new PVector[MAX_READS - BUFFER_SIZE];
    final PVector[] newAvgs = new PVector[MAX_READS - BUFFER_SIZE];
    
    // Fill the queue up:
    for ( int frame = BUFFER_SIZE; frame-- != 0; dataQueue.add(
        new PVector(random(RANGE), random(RANGE))) );
    
    println(dataQueue.size() + "\n"); // Full 20 elements now.
    
    for ( int frame = BUFFER_SIZE - 1; ++frame != MAX_READS; ) {
      // Instantiate 2 PVectors for the current index of the 2 average arrays:
      PVector oldest = oldAvgs[frame - BUFFER_SIZE] = new PVector();
      PVector newest = newAvgs[frame - BUFFER_SIZE] = new PVector();
    
      // Sum of both 1st & last 3 PVector elements:
      int counter = -1;
      for (PVector dq: dataQueue)
        if (++counter < SAMPLE)                    oldest.add(dq);
        else if (counter >= BUFFER_SIZE - SAMPLE)  newest.add(dq);
    
      // Take average of 3 for both PVector current objects:
      oldest.div(SAMPLE);
      newest.div(SAMPLE);
    
      // Remove oldest PVector and recycle it using set() method:
      (newest = dataQueue.remove()).set(random(RANGE), random(RANGE));
    
      // Then re-insert it again as the newest PVector at the end of queue:
      dataQueue.add(newest);
    }
    
    // Display the 80 averages for both the sum of the 3 oldest & latest PVectors:
    println("All of the " + (MAX_READS - BUFFER_SIZE) +
    " Averages of the " + SAMPLE + " oldest PVector coords. within queue: \n");
    for (PVector oldest: oldAvgs)  print(oldest + "\t");
    
    println("\n\nAll of the " + (MAX_READS - BUFFER_SIZE) +
    " Averages of the " + SAMPLE + " newest PVector coords. within queue: \n");
    for (PVector newest: newAvgs)  print(newest + "\t");
    
    exit();
    
  • edited February 2014

    Thank You very much. You have saved me...! Anyway the exact program i wanted is a bit different, I think it works ok for the moment, thanks to your advice. Probably needs a bit more tweaks when reading data from Serial.. Any suggestions on optimising the following code ?

    ** I just saw your modified code. Looks a brilliant idea! :)

    // forum.processing.org/two/discussion/2829/fifo-queue-problem-with-code
    
    import java.util.Queue;
    import java.util.ArrayDeque;
    
    final int BUFFER_SIZE = 20, MAX_READS = 100, MAX_X_COORD = 15, MAX_Y_COORD = 9, SAMPLE = 3;
    final Queue<PVector> dataQueue = new ArrayDeque(BUFFER_SIZE);
    
    for (int frame = 0; frame++ != BUFFER_SIZE;)
      dataQueue.add(new PVector(random(0, MAX_X_COORD), random(0, MAX_Y_COORD))); //Add less than BUFFER_SIZE values to buffer
    
    for (int frame = BUFFER_SIZE; frame++ != MAX_READS;) { //Repeat upto MAX_READS
       //The Program aims to generate following Feature Vectors (F1-F4)
      //- [F1] The accumulated magnitude of movement in the X axis   //- [F2] The accumulated magnitude of movement in the Y axis : just take all the X / Y values in the buffer, square each value, and add these values up 
      //- [F3, F4] The magnitude and angle of rotation between the first Avg of (few values in the buffer) and the Avg of (last few values) in the buffer
      //To compute these features, (this is for F1, do the same for all the Y values for F2).  
    
      final PVector f1f2 = new PVector(); 
      print("\n Squared Element Start is " + f1f2 + "\n");
      for (PVector dq: dataQueue) {
        print ("New Element Entered for Square is : " + dq +"\n");
        f1f2.add(dq.x*dq.x, dq.y*dq.y, 0);
      } //adds square of each element into f1f2 
      print("\n Squared Element is " + f1f2 + "\n"); //F1F2 Values generated to be sent via OSC
    
      final PVector firstFew = new PVector();
      final PVector lastFew = new PVector();
    
      int counter = -1;
      for (PVector dq: dataQueue)
        if (++counter < SAMPLE)                    firstFew.add(dq);
        else if (counter >= BUFFER_SIZE - SAMPLE)  lastFew.add(dq);
      firstFew.div(SAMPLE);
      lastFew.div(SAMPLE);
    
      println(" \n Avg of First Few = "+ firstFew + " Avg of Last Few = "+ lastFew); // Generates avgX1 avgX2, avgY1, avgY2 for Polar Coodinate Calculation which generates F3, F4 for sending via OSC
    
      dataQueue.remove();
      dataQueue.add(new PVector(random(0, MAX_X_COORD), random(0, MAX_Y_COORD)));
    }
    
    
    println("\n\nFinal Queue's Size: \n\n" + dataQueue.size());
    
    exit();
    
  • edited April 2014

    Any suggestions on optimising the following code?

    Well, you've got 2 for (PVector dq: dataQueue) { inner loops
    inside for (int frame = BUFFER_SIZE; frame++ != MAX_READS;) { outer loop!

    Just merged those 2 as 1 iterating loop over Queue! :-j
    Check it out the "new" code:

    // forum.processing.org/two/discussion/2829/fifo-queue-problem-with-code
    
    import java.util.Queue;
    import java.util.ArrayDeque;
    
    final int BUFFER_SIZE = 20, MAX_READS = 100, MAX_X_COORD = 15, MAX_Y_COORD = 9, SAMPLE = 3;
    final Queue<PVector> dataQueue = new ArrayDeque(BUFFER_SIZE);
    
    final PVector f1f2 = new PVector();
    final PVector firstFew = new PVector(), lastFew = new PVector();
    
    //Add less than BUFFER_SIZE values to buffer
    for (int frame = 0; frame++ != BUFFER_SIZE;)
      dataQueue.add( new PVector(random(MAX_X_COORD), random(MAX_Y_COORD)) );
    
    for (int frame = BUFFER_SIZE; frame++ != MAX_READS;) { //Repeat upto MAX_READS
      //The Program aims to generate following Feature Vectors (F1-F4)
      //- [F1] The accumulated magnitude of movement in the X axis
      //- [F2] The accumulated magnitude of movement in the Y axis
      //- just take all X/Y values in the buffer, square each value, and add these values up
      //- [F3, F4] The magnitude and angle of rotation between the first Avg of
      //- (few values in the buffer) and the Avg of (last few values) in the buffer
      //- To compute these features, (this is for F1, do the same for all the Y values for F2).  
    
      f1f2.set(0, 0, 0);
      firstFew.set(0, 0, 0);
      lastFew.set(0, 0, 0);
    
      int counter = -1;
      for (PVector dq: dataQueue) {
        print ("New Element Entered for Square is "+ dq +"\n");
        f1f2.add(dq.x*dq.x, dq.y*dq.y, 0);  //adds square of each element into f1f2
    
        if (++counter < SAMPLE)                    firstFew.add(dq);
        else if (counter >= BUFFER_SIZE - SAMPLE)  lastFew.add(dq);
      }
    
      firstFew.div(SAMPLE);
      lastFew.div(SAMPLE);
    
      print("\nSquared Element  = " + f1f2 + "\n"); //F1F2 Values generated to be sent via OSC
    
      // Generates avgX1 avgX2, avgY1, avgY2 for Polar Coodinate Calculation 
      // which generates F3, F4 for sending via OSC
      println("Avg of First Few = "+ firstFew +"\nAvg of Last Few  = "+ lastFew +"\n"); 
    
      final PVector temp = dataQueue.remove();
      dataQueue.add(temp);
      temp.set(random(MAX_X_COORD), random(MAX_Y_COORD));
    }
    
    println("Final Queue's Size: " + dataQueue.size());
    exit();
    
  • Thank you very much GotoLoop. You should start a consultancy service for giving advice!. Your very helpful.

  • edited June 2014

    Hi GotoLoop, I'm modifying my program slightly, but i'm thinking of how to proceed. this is the problem at hand :

    In the previous example I entered two data (x,y) into the queue. Now I'm getting more data from my hardware for more accuracy, and have data - x,y,z (z can be accommodated in existing pVector) plus another two sets of x,y coordinates Say Xf,Yf and Xs,Ys which I want to calculate using the same way.

    So i'm thinking of repeating another two sets of the above code below each other with two new PVectors. Is there any other shorter method to integrate the Seven data elements into a queue ?(rather than using three PVector Queues ?)

  • edited June 2014

    Well, how about make a better PVector derivative?
    Introducing SuperVec class w/ 2 more additional built-in PVector objects as f & s:

    // forum.processing.org/two/discussion/2829/fifo-queue-problem-with-code
    
    final class SuperVec extends PVector {
      final PVector f = new PVector(), s = new PVector();
    
      void clear() {
        set(0, 0, 0);
        f.set(0, 0, 0);
        s.set(0, 0, 0);
      }
    
      @ Override String toString() {
        return super.toString() + " \tf: " + f.toString() + " \ts: " + s.toString();
      }
    }
    

    Depending on your necessities, you may expand it further by adding up more methods,
    besides clear() & toString() I've already made for ya! =:)

  • Wow, thanks a lot. i'm a little unfamiliar with the extends reserved word, although i have seen it. let me check on it and modify my code.

  • edited June 2014

    You can read about it here: http://processing.org/reference/extends.html

    • It means that the new SuperVec is still a PVector, but w/ more members!
    • Now, besides built-in float fields x, y, & z, it also got 2 more PVector fields: f & s!
    • And a new method: clear().
    • Besides adding new members, we can also @Override the original 1s, like the modified toString()!
    • In short, in 1 swoop, you've got more room for those extra 4 fields you need this time as: f.x, f.y, s.x & s.y!
  • edited July 2014

    Hi GoToLoop, Thanks once again, and sorry for not replying earlier, I was working on a different program and this modification was on pause for some time. Nevertheless I have a few issue in modifying my original program, even though the suggestion by you - on extending the class to accommodate two more Pvectors is crystal clear!.

    I've added the part from my original code suggested by you (and works fine) to explain the problems i have. As I explained previously in my new problem, i'm dealing with a number of Points in 3D. (Original had just one (x,y,z)) So S and F were the two additional points (added correctly to your suggested code).

         //Assume data is in dataX,dataY,dataZ,
         // dataSX,dataSY,dataSZ dataFX,dataFY,dataFZ
    
          if (frame <BUFFER_SIZE) 
          {//Add less than BUFFER_SIZE values to Queue
            dataQueue.add(new PVector(dataX, dataY, dataZ));
              //*****how to add the Three Pvectors into Three DIFFERENT Queues ? 
              //Is it by adding dataQueue.add(new SuperVec()) 
            frame++;
    
          } 
          else 
          { // 20 elements in Queue
            final PVector f1f2 = new PVector(); 
            for (PVector dq: dataQueue) 
            {
                f1f2.add(dq.x, dq.y, dq.z); //adds each element into f1f2 
               //need to add elements to three DIFFERENT Queues
            }     
            final PVector firstFew = new PVector();
            final PVector lastFew = new PVector();
            int counter = -1;
            for (PVector dq: dataQueue)
              if (++counter < SAMPLE)                    firstFew.add(dq); 
            //need for three queues
              else if (counter >= BUFFER_SIZE - SAMPLE)  lastFew.add(dq); /
            firstFew.div(SAMPLE);
            lastFew.div(SAMPLE);
            data[0]=  (lastFew.x-firstFew.x); 
            data[1]=  (lastFew.y-firstFew.y);
            data[2]=  (lastFew.z-firstFew.z);
            data[3]=  //Sending Sx
            data[4]= //Sending Sy
            data[5]= //Sending Sz
            data[6]= //Sending Fx
            data[7]= //Sending Fy
            data[8]= //Sending Fz
            grt.sendData( data );  //Send Process Data
            dataQueue.remove();
            dataQueue.add(new PVector(dataX, dataY, dataZ));
          }
    

    I hope the problem is clear. Basically the MainXYZ, S, and F results need to be computed separately, but within the single loop.

    ** Also in my programme Do i need to use the clear() and toSrting() methods for the superclass ?I feel not, though I am not sure what to add either

    I Really appreciate your assistance! :)

Sign In or Register to comment.