diff --git a/FRC-Robot-2019/src/main/java/frc/robot/RingBuffer.java b/FRC-Robot-2019/src/main/java/frc/robot/RingBuffer.java index 9a0a277..2529508 100644 --- a/FRC-Robot-2019/src/main/java/frc/robot/RingBuffer.java +++ b/FRC-Robot-2019/src/main/java/frc/robot/RingBuffer.java @@ -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 compute() is nesessary. + */ + private boolean justComputed = true; /** * Creates a RingBuffer object. @@ -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; @@ -51,7 +72,9 @@ 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() { @@ -59,5 +82,84 @@ public int getLength() { 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); + } } \ No newline at end of file diff --git a/FRC-Robot-2019/src/main/java/frc/robot/subsystems/SerialPortSubsystem.java b/FRC-Robot-2019/src/main/java/frc/robot/subsystems/SerialPortSubsystem.java index 48e7e8a..97f7384 100644 --- a/FRC-Robot-2019/src/main/java/frc/robot/subsystems/SerialPortSubsystem.java +++ b/FRC-Robot-2019/src/main/java/frc/robot/subsystems/SerialPortSubsystem.java @@ -5,9 +5,8 @@ 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 @@ -15,7 +14,7 @@ public class SerialPortSubsystem extends Subsystem { private int[] distanceArray = new int[4]; -private ArrayList distanceAvgArray; +private ArrayList distanceAvgArray; private StringBuilder serialResults = new StringBuilder(); private SerialPort arduinoSerial; private boolean serialExists = true; @@ -31,11 +30,11 @@ public SerialPortSubsystem() { } logTimer = System.currentTimeMillis(); - distanceAvgArray = new ArrayList(); //4 elements, each is a Deque for 10 elements of distance - distanceAvgArray.add(0, new ArrayDeque()); - distanceAvgArray.add(1, new ArrayDeque()); - distanceAvgArray.add(2, new ArrayDeque()); - distanceAvgArray.add(3, new ArrayDeque()); + distanceAvgArray = new ArrayList(); //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)); } @@ -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 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 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 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 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 { @@ -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) - } } } \ No newline at end of file