Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Incorporate RingBuffer #1

Open
wants to merge 7 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 109 additions & 7 deletions FRC-Robot-2019/src/main/java/frc/robot/RingBuffer.java
Original file line number Diff line number Diff line change
@@ -1,17 +1,38 @@
package frc.robot;

/**
* A RingBuffer object is essentially a double array with a head.
* A RingBuffer object is essentially an integer array with a head.
* The head increments every time a new value is incremented.
*
* @author Kevin Li
*/
public class RingBuffer {
// TODO: Use this class to replace Deques in other classes

private double[] array;
/**
* The array in which the values are stored
*/
private int[] array;
/**
* The "beginning" of the RingBuffer.
*/
private int head = 0;
/**
* Whether or not the RingBuffer has wrapped all the way to the beginning of the array.
* Used to figure the length of the RingBuffer.
*/
private boolean wrapped = false;
/**
* The maximum value of the RingBuffer.
*/
private int max = 0;
/**
* The minimum value of the RingBuffer.
*/
private int min = 0;
/**
* Whether or not the maximum and minimum values are updated.
* Opposite of whether or not <code>compute()</code> is nesessary.
*/
private boolean justComputed = true;

/**
* Creates a RingBuffer object.
Expand All @@ -21,14 +42,14 @@ public class RingBuffer {
public RingBuffer(int length) {
if (length <= 0)
throw new IllegalArgumentException("Length must be positive.");
array = new double[length];
array = new int[length];
}

/**
* Inserts a value to the RingBuffer at index head.
* @param value the value to be inserted into the RingBuffer
*/
public void add(double value) {
public void add(int value) {
array[head++] = value;
if (head >= array.length) {
head = 0;
Expand All @@ -51,13 +72,94 @@ public double get(int index) {
}

/**
* Gets the length of the RingBuffer. //TODO: Change documentation
* Gets the length of the RingBuffer.
* If the array has wrapped, the full length of the array is returned.
* Otherwise, the value of the head is returned.
* @return the length of the RingBuffer
*/
public int getLength() {
if (wrapped) return array.length;
else return head;
}

/**
* Gets the head of the RingBuffer.
* @return the head
*/
public int getHead() {
return head;
}

/**
* Computes and updates the minimum and maximum of all values in the RingBuffer.
* Using the min or max method (or any method that in any way invokes those methods - e.g. avg)
* will automatically invoke this method, if necessary.
*/
public void compute() {
max = array[0];
min = array[0];
for (int i = 1; i < getLength(); i++) {
if (max < array[i])
max = array[i];
if (min < array[i])
min = array[i];
}
justComputed = true;
}

/**
* Gets the minimum value of the RingBuffer.
* @return the minimum value in the RingBuffer
*/
public int min() {
if (!justComputed)
compute();
return min;
}

/**
* Gets the maximum value of the RingBuffer.
* @return the maximum value in the RingBuffer
*/
public int max() {
if (!justComputed)
compute();
return max;
}

/**
* Gets the sum of all of the values in the RingBuffer.
* @return the sum of the values in the RingBuffer
*/
public int total() {
int sum = 0;
for (int i = 0; i <= getLength(); i++) {
if (i >= getLength())
i = 0;
sum += array[i];
}
return sum;
}

/**
* Gets the mean of all values in the RingBuffer.
* @return the average of the values in the RingBuffer
*/
public double avg() {
if (getLength() == 0)
return 0;
else
return total() / getLength();
}

/**
* Gets the mean of all values in the RingBuffer (ignoring the minimum and maximum).
* @return the average of the values in the RingBuffer, ignoring the minimum and maximum
*/
public double olympicAvg() {
if (getLength() <= 2)
return 0;
else
return (total() - min() - max()) / (getLength() - 2);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,16 @@
import edu.wpi.first.hal.util.UncleanStatusException;
import java.lang.StringBuilder;
import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard;
import frc.robot.RingBuffer;
import frc.robot.RobotMap;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.ArrayList;

//Listens on USB Serial port for LIDAR distance data from the arduino

public class SerialPortSubsystem extends Subsystem {

private int[] distanceArray = new int[4];
private ArrayList<Deque> distanceAvgArray;
private ArrayList<RingBuffer> distanceAvgArray;
private StringBuilder serialResults = new StringBuilder();
private SerialPort arduinoSerial;
private boolean serialExists = true;
Expand All @@ -31,11 +30,11 @@ public SerialPortSubsystem() {
}

logTimer = System.currentTimeMillis();
distanceAvgArray = new ArrayList<Deque>(); //4 elements, each is a Deque for 10 elements of distance
distanceAvgArray.add(0, new ArrayDeque<Integer>());
distanceAvgArray.add(1, new ArrayDeque<Integer>());
distanceAvgArray.add(2, new ArrayDeque<Integer>());
distanceAvgArray.add(3, new ArrayDeque<Integer>());
distanceAvgArray = new ArrayList<RingBuffer>(); //4 elements, each is a RingBuffer for 10 elements of distance
distanceAvgArray.add(0, new RingBuffer(10));
distanceAvgArray.add(1, new RingBuffer(10));
distanceAvgArray.add(2, new RingBuffer(10));
distanceAvgArray.add(3, new RingBuffer(10));


}
Expand All @@ -58,65 +57,23 @@ public int getDistance(int sensor) { //return last distance measure for LIDAR se

public Integer getDistanceAvg(int sensor) { //return olympic average of last 10 readings of LIDAR sensor

Deque<Integer> tempDeque = distanceAvgArray.get(sensor-1);
Integer[] tempArray = tempDeque.toArray(new Integer[0]); //switch from ArrayDeque to actual array so we can get each element
Integer average = 0;
Integer sum = 0;
Integer max = 0;
Integer min = 10000;
RingBuffer tempRingBuffer = distanceAvgArray.get(sensor-1);

if (!serialExists)
return 0;
else {
for (int i = 0; i<distanceAvgArray.get(sensor-1).size(); i++) {
if(tempArray[i] > max)
{
max = tempArray[i];
}
if(tempArray[i] < min)
{
min = tempArray[i];
}
sum = sum + tempArray[i];
}
if ((distanceAvgArray.get(sensor-1).size()-2)!=0) {
average = (sum-max-min) / (distanceAvgArray.get(sensor-1).size()-2); //return average, not including max or min reading (olympic)
return average;
}
else return 0;
}
else
return (int) tempRingBuffer.olympicAvg();
}

public Boolean isReliable(int sensor, double percent){ //check sensor to see if last 10 measurements are within a certain deviation
Integer max = 0;
Integer min = 10000;
Deque<Integer> tempDeque = distanceAvgArray.get(sensor-1);
Integer[] tempArray = tempDeque.toArray(new Integer[0]);
RingBuffer tempRingBuffer = distanceAvgArray.get(sensor-1);

if (!serialExists)
return false;
else {
for (int i = 0; i<distanceAvgArray.get(sensor-1).size(); i++) {
if(tempArray[i] > max)
{
max = tempArray[i];
}
if(tempArray[i] < min)
{
min = tempArray[i];
}
}

if(max != 0)
if(tempRingBuffer.max() > 0)
{
if(min/max >= percent)
{
return true;
}
else
{
return false;
}
return (tempRingBuffer.max() / tempRingBuffer.min() >= percent);
}
else
{
Expand Down Expand Up @@ -251,9 +208,5 @@ public void processMessage(StringBuilder serialResults){

distanceArray[sensor-1]=distance;//set read distance to correct LIDAR based on read sensor ID
distanceAvgArray.get(sensor-1).add(distance);//add to rolling average array
if(distanceAvgArray.get(sensor-1).size() > 10)//keep most recent 10 valuse in array
{
distanceAvgArray.get(sensor-1).remove(); //remove oldest reading (queue)
}
}
}