From 0447dc6b870397badb7252bac70cc05c53c1b078 Mon Sep 17 00:00:00 2001 From: LoadingPleaseWait Date: Thu, 10 Mar 2016 22:26:38 -0600 Subject: [PATCH 1/3] Add initial support for encoders in simulation closes #35 --- .../edu/wpi/first/wpilibj/hal/EncoderJNI.java | 57 +++++++++++++++++++ .../assets/toast/patches/patches.txt | 3 +- 2 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 patches/src/main/java/edu/wpi/first/wpilibj/hal/EncoderJNI.java diff --git a/patches/src/main/java/edu/wpi/first/wpilibj/hal/EncoderJNI.java b/patches/src/main/java/edu/wpi/first/wpilibj/hal/EncoderJNI.java new file mode 100644 index 0000000..2bf9365 --- /dev/null +++ b/patches/src/main/java/edu/wpi/first/wpilibj/hal/EncoderJNI.java @@ -0,0 +1,57 @@ +package edu.wpi.first.wpilibj.hal; + +import java.nio.IntBuffer; + +/** + * JNIWrapper for encoders + */ +public class EncoderJNI extends JNIWrapper { + + public static long initializeEncoder(byte port_a_module, int port_a_pin, + boolean port_a_analog_trigger, byte port_b_module, int port_b_pin, boolean port_b_analog_trigger, + boolean reverseDirection, IntBuffer index){ + return 0; + } + + public static void freeEncoder(long encoder_pointer){ + } + + public static void resetEncoder(long encoder_pointer){ + } + + public static int getEncoder(long encoder_pointer){ + return 0; + } + + public static double getEncoderPeriod(long encoder_pointer){ + return 0; + } + + public static void setEncoderMaxPeriod(long encoder_pointer, double maxPeriod){ + } + + public static boolean getEncoderStopped(long encoder_pointer){ + return false; + } + + public static boolean getEncoderDirection(long encoder_pointer){ + return false; + } + + public static void setEncoderReverseDirection(long encoder_pointer, + boolean reverseDirection){ + } + + public static void setEncoderSamplesToAverage(long encoder_pointer, + int samplesToAverage){ + } + + public static int getEncoderSamplesToAverage(long encoder_pointer){ + return 0; + } + + public static void setEncoderIndexSource(long digital_port, int pin, + boolean analogTrigger, boolean activeHigh, boolean edgeSensitive){ + } + +} diff --git a/src/main/resources/assets/toast/patches/patches.txt b/src/main/resources/assets/toast/patches/patches.txt index 6d739c8..99a79df 100644 --- a/src/main/resources/assets/toast/patches/patches.txt +++ b/src/main/resources/assets/toast/patches/patches.txt @@ -8,6 +8,7 @@ edu/wpi/first/wpilibj/communication/FRCNetworkCommunicationsLibrary.sim edu/wpi/first/wpilibj/hal/AccelerometerJNI.sim edu/wpi/first/wpilibj/hal/AnalogJNI.sim edu/wpi/first/wpilibj/hal/DIOJNI.sim +edu/wpi/first/wpilibj/hal/EncoderJNI.sim edu/wpi/first/wpilibj/hal/HALUtil.sim edu/wpi/first/wpilibj/hal/InterruptJNI$InterruptJNIHandlerFunction.sim edu/wpi/first/wpilibj/hal/InterruptJNI.sim @@ -19,4 +20,4 @@ edu/wpi/first/wpilibj/hal/RelayJNI.sim edu/wpi/first/wpilibj/hal/SolenoidJNI.sim edu/wpi/first/wpilibj/hal/CanTalonJNI.sim edu/wpi/first/wpilibj/hal/DigitalGlitchFilterJNI.sim -edu/wpi/first/wpilibj/hal/NotifierJNI.sim \ No newline at end of file +edu/wpi/first/wpilibj/hal/NotifierJNI.sim From 872fc4ced11a61d885327222f605da5499e59488 Mon Sep 17 00:00:00 2001 From: LoadingPleaseWait Date: Fri, 11 Mar 2016 14:57:55 -0600 Subject: [PATCH 2/3] GUI controls for encoders and analog input --- .../edu/wpi/first/wpilibj/hal/AnalogJNI.java | 4 +++- .../edu/wpi/first/wpilibj/hal/EncoderJNI.java | 6 ++++-- .../loader/simulation/SimulationData.java | 11 +++++++++++ .../core/loader/simulation/SimulationGUI.java | 19 +++++++++++++++++++ 4 files changed, 37 insertions(+), 3 deletions(-) diff --git a/patches/src/main/java/edu/wpi/first/wpilibj/hal/AnalogJNI.java b/patches/src/main/java/edu/wpi/first/wpilibj/hal/AnalogJNI.java index e9fe3c6..20b7f73 100644 --- a/patches/src/main/java/edu/wpi/first/wpilibj/hal/AnalogJNI.java +++ b/patches/src/main/java/edu/wpi/first/wpilibj/hal/AnalogJNI.java @@ -3,6 +3,8 @@ import java.nio.IntBuffer; import java.nio.LongBuffer; +import jaci.openrio.toast.core.loader.simulation.SimulationData; + /** * Analog Input/Output */ @@ -92,7 +94,7 @@ public static boolean getAnalogTriggerTriggerState(long analog_trigger_pointer){ } public static short getAnalogValue(long analog_port_pointer){ - return 0; + return SimulationData.analogValues[(int) analog_port_pointer]; } public static double getAnalogVoltage(long analog_port_pointer){ diff --git a/patches/src/main/java/edu/wpi/first/wpilibj/hal/EncoderJNI.java b/patches/src/main/java/edu/wpi/first/wpilibj/hal/EncoderJNI.java index 2bf9365..403d2ea 100644 --- a/patches/src/main/java/edu/wpi/first/wpilibj/hal/EncoderJNI.java +++ b/patches/src/main/java/edu/wpi/first/wpilibj/hal/EncoderJNI.java @@ -2,6 +2,8 @@ import java.nio.IntBuffer; +import jaci.openrio.toast.core.loader.simulation.SimulationData; + /** * JNIWrapper for encoders */ @@ -20,11 +22,11 @@ public static void resetEncoder(long encoder_pointer){ } public static int getEncoder(long encoder_pointer){ - return 0; + return 4 * SimulationData.encoderValue; } public static double getEncoderPeriod(long encoder_pointer){ - return 0; + return 1 / SimulationData.encoderRate; } public static void setEncoderMaxPeriod(long encoder_pointer, double maxPeriod){ diff --git a/src/main/java/jaci/openrio/toast/core/loader/simulation/SimulationData.java b/src/main/java/jaci/openrio/toast/core/loader/simulation/SimulationData.java index 527a7d6..8f3fd21 100644 --- a/src/main/java/jaci/openrio/toast/core/loader/simulation/SimulationData.java +++ b/src/main/java/jaci/openrio/toast/core/loader/simulation/SimulationData.java @@ -26,6 +26,17 @@ public class SimulationData { */ public static byte[] dioValues = new byte[10]; public static byte[] dioDirections = new byte[10]; + + /** + * ANALOG INPUT * + */ + public static short[] analogValues = new short[4]; + + /** + * ENCODER * + */ + public static int encoderValue; + public static double encoderRate; /** * Set the Digital IO on the given port with the given value diff --git a/src/main/java/jaci/openrio/toast/core/loader/simulation/SimulationGUI.java b/src/main/java/jaci/openrio/toast/core/loader/simulation/SimulationGUI.java index d15591c..98b4330 100644 --- a/src/main/java/jaci/openrio/toast/core/loader/simulation/SimulationGUI.java +++ b/src/main/java/jaci/openrio/toast/core/loader/simulation/SimulationGUI.java @@ -173,6 +173,15 @@ public void callback(double value) { } }); } + + // interface for encoder values + createLabel("Encoder", 130, 10, 100, 14, new Color(180, 180, 180)); + createLabel("Count", 165, 25, 100, 12, Color.GRAY); + createLabel("Rate", 165, 45, 100, 14, Color.GRAY); + GuiNumberSpinner count = new GuiNumberSpinner(115, 30, 0, 1, -10, 10, true, this); + count.setCallback(value -> SimulationData.encoderValue = (int) value); + GuiNumberSpinner rate = new GuiNumberSpinner(115, 50, 1, .1, -10, 10, true, this); + rate.setCallback(value -> SimulationData.encoderRate = value); createLabel("Power", 210, 10, 100, 14, new Color(180, 180, 180)); @@ -236,6 +245,16 @@ public void onClick() { } public void onToggle(boolean state) { } }); + + // GuiNumberSpinners for controlling analog input + GuiNumberSpinner analog0 = new GuiNumberSpinner(355, 470, 0, 1, -10, 10, true, this); + analog0.setCallback(value -> SimulationData.analogValues[0] = (short) value); + GuiNumberSpinner analog1 = new GuiNumberSpinner(380, 485, 0, 1, -10, 10, true, this); + analog1.setCallback(value -> SimulationData.analogValues[1] = (short) value); + GuiNumberSpinner analog2 = new GuiNumberSpinner(410, 470, 0, 1, -10, 10, true, this); + analog2.setCallback(value -> SimulationData.analogValues[2] = (short) value); + GuiNumberSpinner analog3 = new GuiNumberSpinner(435, 485, 0, 1, -10, 10, true, this); + analog3.setCallback(value -> SimulationData.analogValues[3] = (short) value); } /** From ad640dab6d86feb088faafd00babd10526fcd7b4 Mon Sep 17 00:00:00 2001 From: LoadingPleaseWait Date: Sun, 13 Mar 2016 22:44:31 -0500 Subject: [PATCH 3/3] Window for encoder simulation --- .../edu/wpi/first/wpilibj/hal/EncoderJNI.java | 10 +- .../loader/simulation/SimulationData.java | 6 - .../core/loader/simulation/SimulationGUI.java | 58 +++++--- .../loader/simulation/encoder/EncoderGUI.java | 127 ++++++++++++++++++ .../loader/simulation/encoder/EncoderReg.java | 52 +++++++ 5 files changed, 228 insertions(+), 25 deletions(-) create mode 100644 src/main/java/jaci/openrio/toast/core/loader/simulation/encoder/EncoderGUI.java create mode 100644 src/main/java/jaci/openrio/toast/core/loader/simulation/encoder/EncoderReg.java diff --git a/patches/src/main/java/edu/wpi/first/wpilibj/hal/EncoderJNI.java b/patches/src/main/java/edu/wpi/first/wpilibj/hal/EncoderJNI.java index 403d2ea..b5476ca 100644 --- a/patches/src/main/java/edu/wpi/first/wpilibj/hal/EncoderJNI.java +++ b/patches/src/main/java/edu/wpi/first/wpilibj/hal/EncoderJNI.java @@ -2,7 +2,7 @@ import java.nio.IntBuffer; -import jaci.openrio.toast.core.loader.simulation.SimulationData; +import jaci.openrio.toast.core.loader.simulation.encoder.EncoderReg; /** * JNIWrapper for encoders @@ -12,7 +12,9 @@ public class EncoderJNI extends JNIWrapper { public static long initializeEncoder(byte port_a_module, int port_a_pin, boolean port_a_analog_trigger, byte port_b_module, int port_b_pin, boolean port_b_analog_trigger, boolean reverseDirection, IntBuffer index){ - return 0; + long pointer = EncoderReg.wrappers.size(); + EncoderReg.wrappers.put(pointer, new EncoderReg.EncoderWrapper()); + return pointer; } public static void freeEncoder(long encoder_pointer){ @@ -22,11 +24,11 @@ public static void resetEncoder(long encoder_pointer){ } public static int getEncoder(long encoder_pointer){ - return 4 * SimulationData.encoderValue; + return 4 * EncoderReg.wrappers.get(encoder_pointer).getValue(); } public static double getEncoderPeriod(long encoder_pointer){ - return 1 / SimulationData.encoderRate; + return 1 / EncoderReg.wrappers.get(encoder_pointer).getRate(); } public static void setEncoderMaxPeriod(long encoder_pointer, double maxPeriod){ diff --git a/src/main/java/jaci/openrio/toast/core/loader/simulation/SimulationData.java b/src/main/java/jaci/openrio/toast/core/loader/simulation/SimulationData.java index 8f3fd21..7cf3b5e 100644 --- a/src/main/java/jaci/openrio/toast/core/loader/simulation/SimulationData.java +++ b/src/main/java/jaci/openrio/toast/core/loader/simulation/SimulationData.java @@ -31,12 +31,6 @@ public class SimulationData { * ANALOG INPUT * */ public static short[] analogValues = new short[4]; - - /** - * ENCODER * - */ - public static int encoderValue; - public static double encoderRate; /** * Set the Digital IO on the given port with the given value diff --git a/src/main/java/jaci/openrio/toast/core/loader/simulation/SimulationGUI.java b/src/main/java/jaci/openrio/toast/core/loader/simulation/SimulationGUI.java index 98b4330..961d09f 100644 --- a/src/main/java/jaci/openrio/toast/core/loader/simulation/SimulationGUI.java +++ b/src/main/java/jaci/openrio/toast/core/loader/simulation/SimulationGUI.java @@ -1,17 +1,28 @@ package jaci.openrio.toast.core.loader.simulation; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.RenderingHints; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; + +import javax.imageio.ImageIO; +import javax.swing.ImageIcon; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; + import jaci.openrio.toast.core.Toast; +import jaci.openrio.toast.core.loader.simulation.encoder.EncoderGUI; import jaci.openrio.toast.core.loader.simulation.jni.InterruptContainer; import jaci.openrio.toast.core.loader.simulation.srx.TalonSRX_GUI; import jaci.openrio.toast.lib.profiler.Profiler; import jaci.openrio.toast.lib.state.RobotState; -import javax.imageio.ImageIO; -import javax.swing.*; -import java.awt.*; -import java.awt.event.WindowAdapter; -import java.awt.event.WindowEvent; - /** * This is the Rat's nest of code that is the Simulation GUI. There is no clean way to programmatically create a GUI * with Swing. Most of the code called in this class is only called once, at runtime. This class is mostly self-contained @@ -174,15 +185,6 @@ public void callback(double value) { }); } - // interface for encoder values - createLabel("Encoder", 130, 10, 100, 14, new Color(180, 180, 180)); - createLabel("Count", 165, 25, 100, 12, Color.GRAY); - createLabel("Rate", 165, 45, 100, 14, Color.GRAY); - GuiNumberSpinner count = new GuiNumberSpinner(115, 30, 0, 1, -10, 10, true, this); - count.setCallback(value -> SimulationData.encoderValue = (int) value); - GuiNumberSpinner rate = new GuiNumberSpinner(115, 50, 1, .1, -10, 10, true, this); - rate.setCallback(value -> SimulationData.encoderRate = value); - createLabel("Power", 210, 10, 100, 14, new Color(180, 180, 180)); GuiNumberSpinner voltage = new GuiNumberSpinner(205, 30, 12.5, 0.1, 5, 12.8, true, this); @@ -246,6 +248,24 @@ public void onClick() { public void onToggle(boolean state) { } }); + GuiButton encoderButton = new GuiButton(20, 180, 100, 30, false, "Encoders", false, this); + encoderButton.setCallback(new GuiButton.ButtonCallback() { + + /* (non-Javadoc) + * @see jaci.openrio.toast.core.loader.simulation.GuiButton.ButtonCallback#onToggle(boolean) + */ + public void onToggle(boolean state) { + } + + /* (non-Javadoc) + * @see jaci.openrio.toast.core.loader.simulation.GuiButton.ButtonCallback#onClick() + */ + @Override + public void onClick() { + openEncoder(); + } + }); + // GuiNumberSpinners for controlling analog input GuiNumberSpinner analog0 = new GuiNumberSpinner(355, 470, 0, 1, -10, 10, true, this); analog0.setCallback(value -> SimulationData.analogValues[0] = (short) value); @@ -272,6 +292,14 @@ public void openPneumatics() { if (PneumaticsGUI.INSTANCE == null) PneumaticsGUI.create(); } + + /** + * Open the Encoder GUI + */ + public void openEncoder(){ + if (EncoderGUI.INSTANCE == null) + EncoderGUI.create(); + } /** * Create a JLabel to place next to various components. diff --git a/src/main/java/jaci/openrio/toast/core/loader/simulation/encoder/EncoderGUI.java b/src/main/java/jaci/openrio/toast/core/loader/simulation/encoder/EncoderGUI.java new file mode 100644 index 0000000..624e2dd --- /dev/null +++ b/src/main/java/jaci/openrio/toast/core/loader/simulation/encoder/EncoderGUI.java @@ -0,0 +1,127 @@ +package jaci.openrio.toast.core.loader.simulation.encoder; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; + +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; + +import jaci.openrio.toast.core.loader.simulation.GuiNumberSpinner; +import jaci.openrio.toast.core.loader.simulation.GuiNumberSpinner.Callback; + +/** + * Panel for simulated encoders + * + * @author LoadingPleaseWait + */ +public class EncoderGUI extends JPanel { + + private static final long serialVersionUID = -5795176560686508623L; + + public static EncoderGUI INSTANCE; + + /** + * @return EncoderGUI instance + */ + public static JPanel create() { + JFrame frame = new JFrame("Toast Encoder GUI"); + JPanel panel = new EncoderGUI(); + frame.add(panel); + frame.pack(); + frame.setLocationRelativeTo(null); + frame.setPreferredSize(new Dimension(400, 375)); + frame.setVisible(true); + frame.setResizable(true); + frame.addWindowListener(new WindowAdapter() { + /* (non-Javadoc) + * @see java.awt.event.WindowAdapter#windowOpened(java.awt.event.WindowEvent) + */ + @Override + public void windowOpened(WindowEvent event) { + super.windowOpened(event); + } + + /* (non-Javadoc) + * @see java.awt.event.WindowAdapter#windowClosing(java.awt.event.WindowEvent) + */ + @Override + public void windowClosing(WindowEvent event) { + super.windowClosing(event); + INSTANCE = null; + } + }); + + return panel; + } + + /** + * Set up the JPanel + */ + public EncoderGUI(){ + INSTANCE = this; + + this.setBackground(new Color(11, 11, 11)); + this.setPreferredSize(new Dimension(400, 375)); + this.setVisible(true); + this.setLayout(null); + + initElements(); + } + + /** + * Remove everything and then add everything back + */ + public void reinitElements(){ + removeAll(); + initElements(); + } + + /** + * Initialize elements in the panel + */ + public void initElements(){ + // labels and number spinners for each encoder + for(Long key : EncoderReg.wrappers.keySet()){ + JLabel encoderLabel = new JLabel("Encoder " + key); + encoderLabel.setForeground(Color.WHITE);// white text + encoderLabel.setBounds(10, key.intValue() * 20 + 10, 100, 20); + add(encoderLabel); + // encoder value + JLabel countLabel = new JLabel("Count"); + countLabel.setForeground(Color.WHITE); + countLabel.setBounds(120, key.intValue() * 20 + 10, 100, 20); + add(countLabel); + GuiNumberSpinner countSpinner = new GuiNumberSpinner(170, key.intValue() * 20 + 15, 0, 1, -10, 10, true, this); + countSpinner.setCallback(new Callback() { + + /* (non-Javadoc) + * @see jaci.openrio.toast.core.loader.simulation.GuiNumberSpinner.Callback#callback(double) + */ + @Override + public void callback(double value) { + EncoderReg.wrappers.get(key).setValue((int) value); + } + }); + // encoder rate + JLabel rateLabel = new JLabel("Rate"); + rateLabel.setForeground(Color.WHITE); + rateLabel.setBounds(260, key.intValue() * 20 + 10, 100, 20); + add(rateLabel); + GuiNumberSpinner rateSpinner = new GuiNumberSpinner(300, key.intValue() * 20 + 15, 1, 0.1, -5, 5, true, this); + rateSpinner.setCallback(new Callback() { + + /* (non-Javadoc) + * @see jaci.openrio.toast.core.loader.simulation.GuiNumberSpinner.Callback#callback(double) + */ + @Override + public void callback(double value) { + EncoderReg.wrappers.get(key).setRate(value); + } + }); + } + } + +} diff --git a/src/main/java/jaci/openrio/toast/core/loader/simulation/encoder/EncoderReg.java b/src/main/java/jaci/openrio/toast/core/loader/simulation/encoder/EncoderReg.java new file mode 100644 index 0000000..8fce192 --- /dev/null +++ b/src/main/java/jaci/openrio/toast/core/loader/simulation/encoder/EncoderReg.java @@ -0,0 +1,52 @@ +package jaci.openrio.toast.core.loader.simulation.encoder; + +import java.util.HashMap; + +/** + * Registry for simulated encoders + * + * @author LoadingPleaseWait + */ +public class EncoderReg { + + public static HashMap wrappers = new HashMap<>(); + + /** + * Wrapper for simulated encoders to be put in the EncoderRegistry + */ + public static class EncoderWrapper{ + + private int value; + private double rate; + + /** + * @return the value + */ + public int getValue() { + return value; + } + + /** + * @param value the value to set + */ + public void setValue(int value) { + this.value = value; + } + + /** + * @return the rate + */ + public double getRate() { + return rate; + } + + /** + * @param rate the rate to set + */ + public void setRate(double rate) { + this.rate = rate; + } + + } + +}