From b21c8c6193784205a3ab01a36744a2497fbd0d5a Mon Sep 17 00:00:00 2001 From: Andrew Duffy Date: Mon, 20 Aug 2012 22:13:28 -0700 Subject: [PATCH] Initial commit of v6.0 --- .gitignore | 1 + BSD_License_for_WPILib_code.txt | 24 ++ README.md | 13 ++ build.properties | 10 + build.xml | 93 ++++++++ nbproject/project.xml | 93 ++++++++ resources/META-INF/MANIFEST.MF | 6 + src/actuator/GRTLed.java | 73 ++++++ src/actuator/GRTRelay.java | 53 +++++ src/actuator/GRTSolenoid.java | 46 ++++ src/actuator/GRTVictor.java | 39 ++++ src/actuator/IMotor.java | 21 ++ src/balancer/BalanceController.java | 63 ++++++ src/balancer/RobotTiltAccel.java | 91 ++++++++ src/balancer/RobotTiltGyro.java | 68 ++++++ src/balancer/balancePD.java | 58 +++++ src/controller/PrimaryDriver.java | 74 ++++++ src/core/Actuator.java | 25 ++ src/core/EventController.java | 39 ++++ src/core/GRTLoggedProcess.java | 93 ++++++++ src/core/IProcess.java | 41 ++++ src/core/PollingSensor.java | 98 ++++++++ src/core/Sensor.java | 67 ++++++ src/deploy/GRTRobot.java | 69 ++++++ src/deploy/MainRobot.java | 136 +++++++++++ src/event/ADXL345Event.java | 39 ++++ src/event/ADXL345Listener.java | 18 ++ src/event/Attack3JoystickEvent.java | 31 +++ src/event/Attack3JoystickListener.java | 15 ++ src/event/BatteryVoltageEvent.java | 32 +++ src/event/BatteryVoltageListener.java | 16 ++ src/event/ButtonEvent.java | 40 ++++ src/event/ButtonListener.java | 18 ++ src/event/DrivingEvent.java | 38 ++++ src/event/DrivingListener.java | 25 ++ src/event/DrivingProfileEvent.java | 32 +++ src/event/DrivingProfileListener.java | 14 ++ src/event/EncoderEvent.java | 23 ++ src/event/EncoderListener.java | 19 ++ src/event/GyroEvent.java | 29 +++ src/event/GyroListener.java | 14 ++ src/event/PotentiometerEvent.java | 31 +++ src/event/PotentiometerListener.java | 13 ++ src/event/RobotTiltEvent.java | 34 +++ src/event/RobotTiltListener.java | 13 ++ src/event/SensorChangeListener.java | 11 + src/event/SensorEvent.java | 34 +++ src/event/SwitchEvent.java | 31 +++ src/event/SwitchListener.java | 15 ++ src/event/XboxJoystickEvent.java | 37 +++ src/event/XboxJoystickListener.java | 23 ++ src/mechanism/GRTDriveTrain.java | 47 ++++ src/mechanism/GRTRobotBase.java | 35 +++ src/networking/GRTClientSocket.java | 156 +++++++++++++ src/networking/GRTServer.java | 226 +++++++++++++++++++ src/networking/GRTSingleClientServer.java | 149 ++++++++++++ src/networking/GRTSocket.java | 15 ++ src/networking/SocketEvent.java | 28 +++ src/networking/SocketListener.java | 8 + src/rpc/RPCConnection.java | 11 + src/rpc/RPCMessage.java | 25 ++ src/rpc/RPCMessageListener.java | 11 + src/rpc/connection/NetworkRPC.java | 101 +++++++++ src/rpc/connection/StreamedRPC.java | 122 ++++++++++ src/rpc/telemetry/SensorLogger.java | 49 ++++ src/sensor/ADXL345DigitalAccelerometer.java | 175 ++++++++++++++ src/sensor/GRTADXL345.java | 78 +++++++ src/sensor/GRTAttack3Joystick.java | 107 +++++++++ src/sensor/GRTBatterySensor.java | 50 ++++ src/sensor/GRTEncoder.java | 45 ++++ src/sensor/GRTGyro.java | 57 +++++ src/sensor/GRTSwitch.java | 54 +++++ src/sensor/GRTXBoxJoystick.java | 161 +++++++++++++ src/sensor/Potentiometer.java | 53 +++++ src/sensor/base/GRTAttack3DriverStation.java | 78 +++++++ src/sensor/base/GRTDriverStation.java | 93 ++++++++ src/sensor/base/GRTXboxDriverStation.java | 113 ++++++++++ src/sensor/base/IDriverProfile.java | 19 ++ src/sensor/base/LinearDrive.java | 17 ++ src/sensor/base/SquareDrive.java | 19 ++ src/sensor/base/TestSwitch.java | 22 ++ src/sensor/base/VictorDriverProfile.java | 25 ++ suite/Base2012-redesign_1.0.0.jar | Bin 0 -> 139398 bytes 83 files changed, 4188 insertions(+) create mode 100644 .gitignore create mode 100644 BSD_License_for_WPILib_code.txt create mode 100644 README.md create mode 100644 build.properties create mode 100644 build.xml create mode 100644 nbproject/project.xml create mode 100644 resources/META-INF/MANIFEST.MF create mode 100644 src/actuator/GRTLed.java create mode 100644 src/actuator/GRTRelay.java create mode 100644 src/actuator/GRTSolenoid.java create mode 100644 src/actuator/GRTVictor.java create mode 100644 src/actuator/IMotor.java create mode 100644 src/balancer/BalanceController.java create mode 100644 src/balancer/RobotTiltAccel.java create mode 100644 src/balancer/RobotTiltGyro.java create mode 100644 src/balancer/balancePD.java create mode 100644 src/controller/PrimaryDriver.java create mode 100644 src/core/Actuator.java create mode 100644 src/core/EventController.java create mode 100644 src/core/GRTLoggedProcess.java create mode 100644 src/core/IProcess.java create mode 100644 src/core/PollingSensor.java create mode 100644 src/core/Sensor.java create mode 100644 src/deploy/GRTRobot.java create mode 100644 src/deploy/MainRobot.java create mode 100644 src/event/ADXL345Event.java create mode 100644 src/event/ADXL345Listener.java create mode 100644 src/event/Attack3JoystickEvent.java create mode 100644 src/event/Attack3JoystickListener.java create mode 100644 src/event/BatteryVoltageEvent.java create mode 100644 src/event/BatteryVoltageListener.java create mode 100644 src/event/ButtonEvent.java create mode 100644 src/event/ButtonListener.java create mode 100644 src/event/DrivingEvent.java create mode 100644 src/event/DrivingListener.java create mode 100644 src/event/DrivingProfileEvent.java create mode 100644 src/event/DrivingProfileListener.java create mode 100644 src/event/EncoderEvent.java create mode 100644 src/event/EncoderListener.java create mode 100644 src/event/GyroEvent.java create mode 100644 src/event/GyroListener.java create mode 100644 src/event/PotentiometerEvent.java create mode 100644 src/event/PotentiometerListener.java create mode 100644 src/event/RobotTiltEvent.java create mode 100644 src/event/RobotTiltListener.java create mode 100644 src/event/SensorChangeListener.java create mode 100644 src/event/SensorEvent.java create mode 100644 src/event/SwitchEvent.java create mode 100644 src/event/SwitchListener.java create mode 100644 src/event/XboxJoystickEvent.java create mode 100644 src/event/XboxJoystickListener.java create mode 100644 src/mechanism/GRTDriveTrain.java create mode 100644 src/mechanism/GRTRobotBase.java create mode 100644 src/networking/GRTClientSocket.java create mode 100644 src/networking/GRTServer.java create mode 100644 src/networking/GRTSingleClientServer.java create mode 100644 src/networking/GRTSocket.java create mode 100644 src/networking/SocketEvent.java create mode 100644 src/networking/SocketListener.java create mode 100644 src/rpc/RPCConnection.java create mode 100644 src/rpc/RPCMessage.java create mode 100644 src/rpc/RPCMessageListener.java create mode 100644 src/rpc/connection/NetworkRPC.java create mode 100644 src/rpc/connection/StreamedRPC.java create mode 100644 src/rpc/telemetry/SensorLogger.java create mode 100644 src/sensor/ADXL345DigitalAccelerometer.java create mode 100644 src/sensor/GRTADXL345.java create mode 100644 src/sensor/GRTAttack3Joystick.java create mode 100644 src/sensor/GRTBatterySensor.java create mode 100644 src/sensor/GRTEncoder.java create mode 100644 src/sensor/GRTGyro.java create mode 100644 src/sensor/GRTSwitch.java create mode 100644 src/sensor/GRTXBoxJoystick.java create mode 100644 src/sensor/Potentiometer.java create mode 100644 src/sensor/base/GRTAttack3DriverStation.java create mode 100644 src/sensor/base/GRTDriverStation.java create mode 100644 src/sensor/base/GRTXboxDriverStation.java create mode 100644 src/sensor/base/IDriverProfile.java create mode 100644 src/sensor/base/LinearDrive.java create mode 100644 src/sensor/base/SquareDrive.java create mode 100644 src/sensor/base/TestSwitch.java create mode 100644 src/sensor/base/VictorDriverProfile.java create mode 100644 suite/Base2012-redesign_1.0.0.jar diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..567609b --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +build/ diff --git a/BSD_License_for_WPILib_code.txt b/BSD_License_for_WPILib_code.txt new file mode 100644 index 0000000..f7ee350 --- /dev/null +++ b/BSD_License_for_WPILib_code.txt @@ -0,0 +1,24 @@ +* Copyright (c) 2009 FIRST +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the FIRST nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY FIRST AND CONTRIBUTORS``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY NONINFRINGEMENT AND FITNESS FOR A PARTICULAR +* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL FIRST OR CONTRIBUTORS BE LIABLE FOR +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..8cede3a --- /dev/null +++ b/README.md @@ -0,0 +1,13 @@ +GRT Framework v6 +================ + +GRTFramework is an asynchronous, event-driven framework built on top of [WPILibJ](http://firstforge.wpi.edu/sf/projects/wpilib), which is provided by FIRST and includes a host of useful low-level hardware classes. + +The purpose of GRTFramework is: +* To provide a framework for rapid FRC robot development +* An asynchronous design and a focus on quality code design +* Coder happiness :) + +Please feel free to email any of the developers if you have questions about the code. + +-FRC Team 192: Gunn Robotics Team (A.K.A "GRT") diff --git a/build.properties b/build.properties new file mode 100644 index 0000000..4ea99c3 --- /dev/null +++ b/build.properties @@ -0,0 +1,10 @@ +# Properties file for a Sun Spot Application +# +# build.properties +# +# This file is the default location for user properties that over-ride the +# defaults in ${sunspot.home}/default.properties. See that file for a full +# listing of the properties that may be set. This file is minimal and contains +# only those properties that a user would generally need to set right away. +# +user.classpath=${wpilibj.home}/src diff --git a/build.xml b/build.xml new file mode 100644 index 0000000..a8f5392 --- /dev/null +++ b/build.xml @@ -0,0 +1,93 @@ + + + + + + + + + + + + + diff --git a/nbproject/project.xml b/nbproject/project.xml new file mode 100644 index 0000000..f6b0258 --- /dev/null +++ b/nbproject/project.xml @@ -0,0 +1,93 @@ + + + + org.netbeans.modules.ant.freeform + + + grtframeworkv6 + + ${user.home}/.sunspotfrc.properties + build.properties + ${sunspot.home}/default.properties + + + + + java + src + + + + + jar-app + + + clean + + + deploy + run + + + clean + jar-app + + + deploy + debug-run + + + javadoc + + + + folder + build + jar-app + + + + + + src + + + build.xml + + + + + + + + + + + + deploy + + + + jar-deploy + + + + + + + + + src + ${sunspot.bootclasspath} + /home/gerberduffy/sunspotfrcsdk/lib/WPILibJ/classes.jar + build + 1.4 + + + + diff --git a/resources/META-INF/MANIFEST.MF b/resources/META-INF/MANIFEST.MF new file mode 100644 index 0000000..a9b02ac --- /dev/null +++ b/resources/META-INF/MANIFEST.MF @@ -0,0 +1,6 @@ +MIDlet-Name: Base2012-redesign +MIDlet-Version: 1.0.0 +MIDlet-Vendor: FIRST +MIDlet-1: MainRobot, , deploy.MainRobot +MicroEdition-Profile: IMP-1.0 +MicroEdition-Configuration: CLDC-1.1 diff --git a/src/actuator/GRTLed.java b/src/actuator/GRTLed.java new file mode 100644 index 0000000..754e647 --- /dev/null +++ b/src/actuator/GRTLed.java @@ -0,0 +1,73 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package actuator; + +import core.Actuator; +import edu.wpi.first.wpilibj.PWM; + +/** + * Abstraction of a standard LED + * @author gerberduffy + */ +public class GRTLed extends Actuator { + + private static final int DEFAULT_BRIGHTNESS = 255; + private static final int HIGHEST_BRIGHTNESS = 255; + private static final int OFF_BRIGHTNESS = 0; + + + private final PWM led; //The PWM input controlling the LED + private int brightness; + + public GRTLed(int channel, String id){ + this(channel, DEFAULT_BRIGHTNESS, id); + } + + public GRTLed(int channel, int brightness, String id){ + super(id); + + this.brightness = brightness; + + led = new PWM(channel); + led.setRaw(brightness); + } + + public void setToBrightness(int bright){ + if (bright > HIGHEST_BRIGHTNESS){ + bright = HIGHEST_BRIGHTNESS; + } else if (bright < OFF_BRIGHTNESS){ + bright = OFF_BRIGHTNESS; + } + + led.setRaw(bright); + + this.brightness = bright; + } + + public void toggleState(){ + if (isOn()){ + led.setRaw(OFF_BRIGHTNESS); + brightness = OFF_BRIGHTNESS; + + } else { + led.setRaw(HIGHEST_BRIGHTNESS); + brightness = HIGHEST_BRIGHTNESS; + } + } + + public int getBrightness(){ + return this.brightness; + } + + public boolean isOn(){ + return this.brightness > OFF_BRIGHTNESS; + } + + public void executeCommand(double command) { + led.setRaw((int) command); + brightness = (int) command; + } + +} diff --git a/src/actuator/GRTRelay.java b/src/actuator/GRTRelay.java new file mode 100644 index 0000000..22dd609 --- /dev/null +++ b/src/actuator/GRTRelay.java @@ -0,0 +1,53 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package actuator; + +import edu.wpi.first.wpilibj.Relay; +import core.Actuator; + +/** + * + * @author calvin + */ +public class GRTRelay extends Actuator{ + private Relay relay; + + private static final double FORWARD = 1.0; + private static final double REVERSE = -1.0; + private static final double OFF = 0.0; + + public GRTRelay(int channel, String name){ + super(name); + relay = new Relay(channel); + } + + /** + * Sends command to relay. If the value of the command is -1.0 the relay is in reverse, + * 1.0 is forward, and 0.0 is off. + * @param c + */ + public void executeCommand(double command) { + if (command == OFF) { + relay.set(Relay.Value.kOff); + } else if(command == FORWARD) { + relay.set(Relay.Value.kForward); + } else if(command == REVERSE) { + relay.set(Relay.Value.kReverse); + } + } +/** + * SEts the state of the relay to off + */ + public void halt() { + relay.set(Relay.Value.kOff); + } +/** + * Returns String + * @return + */ + public String toString() { + return "Relay"; + } +} diff --git a/src/actuator/GRTSolenoid.java b/src/actuator/GRTSolenoid.java new file mode 100644 index 0000000..343ce6a --- /dev/null +++ b/src/actuator/GRTSolenoid.java @@ -0,0 +1,46 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package actuator; + +import core.Actuator; +import edu.wpi.first.wpilibj.Solenoid; + +/** + * + * @author gerberduffy + */ +public class GRTSolenoid extends Actuator { + + private Solenoid sol; + + public static final double ON = 1.0; + public static final double OFF = 0.0; + + public GRTSolenoid(int slot, int channel, String id) { + super(id); + + sol = new Solenoid(slot, channel); + } + + /* + * Engage or disengage the solenoid + */ + public void executeCommand(double command) { + if (command == ON) { + sol.set(true); + } else if (command == OFF) { + sol.set(false); + } + } + + +// @Override + public void halt() { + sol.set(false); + + super.halt(); + + } +} diff --git a/src/actuator/GRTVictor.java b/src/actuator/GRTVictor.java new file mode 100644 index 0000000..35d7be2 --- /dev/null +++ b/src/actuator/GRTVictor.java @@ -0,0 +1,39 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package actuator; + +import core.Actuator; +import edu.wpi.first.wpilibj.Victor; + +/** + * + * @author ajc + */ +public class GRTVictor extends Actuator implements IMotor { + + Victor victor; + + public GRTVictor(int id, String name) { + super(name); + victor = new Victor(id); + } + + public void executeCommand(double command) { + if (enabled) { + victor.set(command); + } + } + + /* + * Set the Victor's speed + * @param speed the new speed to set + */ + public void setSpeed(double speed){ + if(enabled){ + victor.set(speed); +// log(speed); + } + } +} diff --git a/src/actuator/IMotor.java b/src/actuator/IMotor.java new file mode 100644 index 0000000..6020262 --- /dev/null +++ b/src/actuator/IMotor.java @@ -0,0 +1,21 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package actuator; + +import core.IProcess; + +/** + * + * @author ajc + */ +public interface IMotor extends IProcess{ + + /** + * + * @param speed + */ + public void setSpeed(double speed); + +} diff --git a/src/balancer/BalanceController.java b/src/balancer/BalanceController.java new file mode 100644 index 0000000..c2696f2 --- /dev/null +++ b/src/balancer/BalanceController.java @@ -0,0 +1,63 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package balancer; +import balancer.RobotTiltGyro; +import core.EventController; +import event.RobotTiltListener; +import event.RobotTiltEvent; +import mechanism.GRTRobotBase; + + +/** + * + * @author calvin + */ +public class BalanceController extends EventController implements RobotTiltListener{ + + private double previousAngle; + private double currentAngle; + private double deltaAngle; + private double P_CONSTANT = .024; + private double D_CONSTANT = 0; + private final RobotTiltGyro robotTilt; + private final GRTRobotBase base; + private double DRIVE_THRESHOLD = .01; + + public BalanceController(GRTRobotBase base, RobotTiltGyro robotTilt, String name){ + super(name); + this.base = base; + this.robotTilt = robotTilt; + } + + public void startBalancing(){ + startListening(); + } + + public void stopBalancing(){ + stopListening(); + } + + protected void startListening() { + robotTilt.addRobotTiltListeners(this); + } + + protected void stopListening() { + robotTilt.removeRobotTiltListeners(this); + } + + public void RobotTiltChange(RobotTiltEvent e) { + currentAngle = e.getTilt(); + deltaAngle = currentAngle - previousAngle; + double drivePower = P_CONSTANT * currentAngle - D_CONSTANT * deltaAngle; + if(Math.abs(drivePower) >= DRIVE_THRESHOLD) + base.tankDrive(drivePower, drivePower); + else + base.tankDrive(0, 0); + System.out.println(drivePower); + } + + + +} diff --git a/src/balancer/RobotTiltAccel.java b/src/balancer/RobotTiltAccel.java new file mode 100644 index 0000000..cfbe3e5 --- /dev/null +++ b/src/balancer/RobotTiltAccel.java @@ -0,0 +1,91 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +//DO NOT USE--use robotTiltGyro instead +package balancer; + +import com.sun.squawk.util.MathUtils; +import core.Sensor; +import event.ADXL345Event; +import event.ADXL345Listener; +import event.RobotTiltEvent; +import event.RobotTiltListener; +import java.util.Vector; +import sensor.GRTADXL345; + +/** + * + * @author calvin + */ +public class RobotTiltAccel extends Sensor implements ADXL345Listener { + + private Vector robotTiltListeners; + private static final int NUM_DATA = 1;//TODO change + public static final int KEY_ANGLE = 0; + private double angle; + private double xAccel; + private double yAccel; + private double zAccel; + private final GRTADXL345 accelerometer; + + public RobotTiltAccel(GRTADXL345 accelerometer, String name) { + super(name); + this.accelerometer = accelerometer; + robotTiltListeners = new Vector(); + } + +// protected void notifyListeners(int id, double oldDatum, double newDatum) { +// RobotTiltEvent e = new RobotTiltEvent(this, id, newDatum); +// for (int i = 0; i < robotTiltListeners.size(); i++) { +// ((RobotTiltListener) robotTiltListeners.elementAt(i)).RobotTiltChange(e); +// } +// } + + private void updateAngle() { + //magnitude of vector sum of x, y accelerations + double normalDeviation = Math.sqrt(((xAccel) * (xAccel)) + + ((yAccel) * (yAccel))); +// double oldAngle = angle; + angle = MathUtils.atan(normalDeviation / zAccel); + //angle is angle between acceleration vector and z axis + notifyStateChange(KEY_ANGLE, angle); + } + + public double getTilt() { + return angle; + } + + public void addRobotTiltListeners(RobotTiltListener l) { + robotTiltListeners.addElement(l); + } + + public void removeRobotTiltListeners(RobotTiltListener l) { + robotTiltListeners.removeElement(l); + } + + //@Override + protected void startListening() { + accelerometer.addADXL345Listener(this); + } + + protected void stopListening() { + accelerometer.removeADXL345Listener(this); + } + + public void XAccelChange(ADXL345Event e) { + xAccel = e.getAcceleration(); + updateAngle(); + } + + public void YAccelChange(ADXL345Event e) { + yAccel = e.getAcceleration(); + updateAngle(); + } + + public void ZAccelChange(ADXL345Event e) { + zAccel = e.getAcceleration(); + updateAngle(); + } +} \ No newline at end of file diff --git a/src/balancer/RobotTiltGyro.java b/src/balancer/RobotTiltGyro.java new file mode 100644 index 0000000..e8a8f2b --- /dev/null +++ b/src/balancer/RobotTiltGyro.java @@ -0,0 +1,68 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package balancer; +import core.Sensor; +import sensor.GRTGyro; +import event.GyroEvent; +import event.GyroListener; +import java.util.Vector; +import event.RobotTiltEvent; +import event.RobotTiltListener; + +/** + * + * @author calvin + */ + + +public class RobotTiltGyro extends Sensor implements GyroListener{ + private Vector robotTiltListeners; + private double angle; + private double previousAngle; + private GRTGyro g; + + public RobotTiltGyro(GRTGyro g, String name){ + super(name); + this.g = g; + robotTiltListeners = new Vector(); + angle = 0; + previousAngle = 0; + } + public void angleChanged(GyroEvent e) { + updateAngle(); + } + + private void updateAngle(){ + angle += g.getAngle() - previousAngle; + previousAngle = g.getAngle(); + notifyStateChange(0, angle); + notifyListeners(0, angle); + } + + protected void notifyListeners(int id, double newDatum) { + RobotTiltEvent e = new RobotTiltEvent(this, id, newDatum); + for (int i = 0; i < robotTiltListeners.size(); i++) { + ((RobotTiltListener) robotTiltListeners.elementAt(i)).RobotTiltChange(e); + } + + + } + + public void addRobotTiltListeners(RobotTiltListener l) { + robotTiltListeners.addElement(l); + } + + public void removeRobotTiltListeners(RobotTiltListener l) { + robotTiltListeners.removeElement(l); + } + + protected void startListening() { + g.addListener(this); + } + + protected void stopListening() { + g.removeListener(this); + } +} diff --git a/src/balancer/balancePD.java b/src/balancer/balancePD.java new file mode 100644 index 0000000..46de57d --- /dev/null +++ b/src/balancer/balancePD.java @@ -0,0 +1,58 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package balancer; +import balancer.RobotTiltAccel; +import core.EventController; +import event.RobotTiltListener; +import event.RobotTiltEvent; +import mechanism.GRTRobotBase; + + +/** + * + * @author calvin + */ +public class balancePD extends EventController implements RobotTiltListener{ + + private double previousAngle; + private double currentAngle; + private double deltaAngle; + private double P_CONSTANT = 1; + private double D_CONSTANT = 0; + private final RobotTiltAccel robotTilt; + private final GRTRobotBase base; + + public balancePD(GRTRobotBase base, RobotTiltAccel robotTilt, String name){ + super(name); + this.base = base; + this.robotTilt = robotTilt; + } + +// public void startBalancing(){ +// startListening(); +// } +// +// public void stopBalancing(){ +// stopListening(); +// } + + protected void startListening() { + robotTilt.addRobotTiltListeners(this); + } + + protected void stopListening() { + robotTilt.removeRobotTiltListeners(this); + } + + public void RobotTiltChange(RobotTiltEvent e) { + currentAngle = e.getTilt(); + deltaAngle = currentAngle - previousAngle; + double drivePower = P_CONSTANT * currentAngle - D_CONSTANT * deltaAngle; + base.tankDrive(drivePower, drivePower); + } + + + +} diff --git a/src/controller/PrimaryDriver.java b/src/controller/PrimaryDriver.java new file mode 100644 index 0000000..5d93b49 --- /dev/null +++ b/src/controller/PrimaryDriver.java @@ -0,0 +1,74 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package controller; + +import core.EventController; +import edu.wpi.first.wpilibj.DriverStation; +import event.DrivingEvent; +import event.DrivingListener; +import event.DrivingProfileEvent; +import event.DrivingProfileListener; +import event.XboxJoystickEvent; +import event.XboxJoystickListener; +import mechanism.GRTDriveTrain; +import sensor.base.GRTXboxDriverStation; +import mechanism.GRTRobotBase; +import sensor.base.IDriverProfile; +import sensor.base.LinearDrive; +import sensor.GRTXBoxJoystick; +import sensor.base.GRTDriverStation; + +/** + * Robot base driving. + * + * Operates for any DriverStation + * + * @author ajc + */ +public class PrimaryDriver extends EventController implements DrivingListener, DrivingProfileListener { + + //sensor + private final GRTDriverStation ds; + //actuator + private final GRTRobotBase dt; + //drive curve + private IDriverProfile driveProfile; + //state + private double leftVelocity; + private double rightVelocity; + + public PrimaryDriver(GRTRobotBase dt, GRTDriverStation ds, IDriverProfile driveProfile, String name) { + super(name); + this.dt = dt; + this.ds = ds; + this.driveProfile = driveProfile; + } + + protected void startListening() { + ds.addDrivingListener(this); + ds.addDrivingProfileListener(this); + } + + protected void stopListening() { + ds.removeDrivingListener(this); + ds.removeDrivingProfileListener(this); + } + + public void driverLeftSpeed(DrivingEvent e) { + leftVelocity = e.getPercentSpeed(); + + dt.tankDrive(driveProfile.driveSpeed(leftVelocity), driveProfile.driveSpeed(rightVelocity)); + } + + public void driverRightSpeed(DrivingEvent e) { + rightVelocity = e.getPercentSpeed(); + + dt.tankDrive(driveProfile.driveSpeed(leftVelocity), driveProfile.driveSpeed(rightVelocity)); + } + + public void drivingProfileChanged(DrivingProfileEvent e) { + driveProfile = e.getProfile(); + } +} diff --git a/src/core/Actuator.java b/src/core/Actuator.java new file mode 100644 index 0000000..7010c78 --- /dev/null +++ b/src/core/Actuator.java @@ -0,0 +1,25 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package core; + +/** + * An actuator is a driver for low level hardware that directly influences the + * physical world. Actuators can perform actions. + * @author ajc + */ +public abstract class Actuator extends GRTLoggedProcess { + + + public Actuator(String name){ + super(name); + } + + /** + * Performs an action. Actuator must be enabled for this to succeed. + * @param command + */ + public abstract void executeCommand(double command); + +} diff --git a/src/core/EventController.java b/src/core/EventController.java new file mode 100644 index 0000000..1eae9ab --- /dev/null +++ b/src/core/EventController.java @@ -0,0 +1,39 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package core; + +/** + * An EventController describes behavior based on received events. + * @author ajc + */ +public abstract class EventController extends GRTLoggedProcess { + + public EventController(String name) { + super(name); + running = true; //TODO does this belong + } + + /** + * Adds listeners. + */ + protected abstract void startListening(); + + /** + * Removes listeners + */ + protected abstract void stopListening(); + + + public void enable() { + //enable() always works because an EventController is always running + super.enable(); + startListening(); + } + + public void disable() { + super.disable(); + stopListening(); + } +} diff --git a/src/core/GRTLoggedProcess.java b/src/core/GRTLoggedProcess.java new file mode 100644 index 0000000..3c1cb5b --- /dev/null +++ b/src/core/GRTLoggedProcess.java @@ -0,0 +1,93 @@ +package core; + +/** + * A GRTLoggedProcess is a controllable process. It can be initiated/terminated. + * + * When a GRTLoggedProcess is constructed, it is immediately run, but not enabled. + * + * @author ajc + * + */ +public abstract class GRTLoggedProcess extends Thread implements IProcess { + + protected final String name; + protected boolean enabled = false; + protected boolean running = true; + + public GRTLoggedProcess(String name) { + this.name = name; + } + + /** + * + * @param message + */ + protected void log(String message) { + System.out.println(toString() + "\t" + message); + } + + /** + * Logs in format: "[[ClassName:Id]] @name message + * @param name + * @param message + */ + protected void log(String name, String message) { + System.out.println(toString() + "\t" + name + "\t" + message); + } + + /** + * + * @param data + */ + protected void log(double data) { + System.out.println(toString() + "\t" + data); + + } + + /** + * + * @param name + * @param data + */ + protected void log(String name, double data) { + System.out.println(toString() + "\t" + name + "\t" + data); + } + + public void enable() { + enabled = true; + } + + public void disable() { + enabled = false; + } + + public boolean isEnabled() { + return enabled; + } + + public void halt() { + running = false; + disable(); + } + + public boolean isRunning() { + return running; + } + + /** + * Name + * + * @return + */ + public String getID() { + return name; + } + + /* + * To string method, returns loggable string in the formate + * [[ClassName:Id]] + */ + public String toString(){ + return "[[" + getClass().getName() + ":" + getID(); + } +} diff --git a/src/core/IProcess.java b/src/core/IProcess.java new file mode 100644 index 0000000..b38d8b4 --- /dev/null +++ b/src/core/IProcess.java @@ -0,0 +1,41 @@ +package core; + +/** + * An IProcess is a component that produces a certain behavior. + * This behavior can be enabled or disabled for a temporary pausing, or halted. + * Halting stops the behavior from ever being re-enabled again. + * + * @author ajc + * + */ +public interface IProcess { + + /** + * Enables process behavior + */ + public void enable(); + + /** + * Disables process behavior + */ + public void disable(); + + /** + * + * @return true if behavior is active + */ + public boolean isEnabled(); + + /** + * Terminates the behavior forever + */ + public void halt(); + + /** + * + * @return true if the process can be enabled + */ + public boolean isRunning(); + + +} diff --git a/src/core/PollingSensor.java b/src/core/PollingSensor.java new file mode 100644 index 0000000..969d98a --- /dev/null +++ b/src/core/PollingSensor.java @@ -0,0 +1,98 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package core; + +/** + * A PollingSensor directly obtains data through the poll() method, as opposed + * to generic sensors that could receive events. + * + * It additionally stores the state of variables, and automatically performs + * state change checks. + * + * + * @author ajc + */ +public abstract class PollingSensor extends Sensor { + + private double[] data; + private final int sleepTime; + + /** + * Construct a polling sensor. + * Subclasses need to start themselves-- make a call to start(); + * @param name name of the sensor + * @param sleepTime time between polls [ms] + * @param numData number of pieces of data + */ + public PollingSensor(String name, int sleepTime, int numData) { + super(name); + this.sleepTime = sleepTime; + data = new double[numData]; + } + + /** + * Called to poll sensor. + */ + protected abstract void poll(); + + public void run() { + running = true; + while (running) { + + //only poll, and thus only send events, if enabled + if (enabled) { + poll(); + } + + try { + Thread.sleep(sleepTime); + } catch (InterruptedException ex) { + ex.printStackTrace(); + } + } + } + + /** + * Stores a datum, and notifies listeners if the state of it has changed. + * + * @param id key of the data + * @param datum fresh datum + */ + protected void setState(int id, double datum) { + double previous = data[id]; + //notify self and state change listeners if the datum has changed + if (previous != datum) { + notifyListeners(id, previous, datum); + notifyStateChange(id, datum); + } + data[id] = datum; + } + + /** + * Retrieves sensor data + * @param id + * @return + */ + public double getState(int id) { + return data[id]; + } + + /** + * Calls the listener events based on what has changed + * @param id the key of the data that changed + * @param oldDatum the datum's previous value + * @param newDatum the datum's new value + */ + protected abstract void notifyListeners(int id, double oldDatum, double newDatum); + + /* + * Polling sensors do not listen to things, necesserily + */ + protected void startListening() { + } + + protected void stopListening() { + } +} diff --git a/src/core/Sensor.java b/src/core/Sensor.java new file mode 100644 index 0000000..cc75c08 --- /dev/null +++ b/src/core/Sensor.java @@ -0,0 +1,67 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package core; + +import event.SensorChangeListener; +import event.SensorEvent; +import java.util.Vector; + +/** + * A sensor sends sensor event data. They only send data when running. + * + * @author ajc + */ +public abstract class Sensor extends GRTLoggedProcess { + + //Constants + public static final double TRUE = 1.0; + public static final double FALSE = 0.0; + public static final double ERROR = -999; + + //Instance variables + private Vector listeners; //Collection of things that listen to this sensor + + public Sensor(String name) { + super(name); + listeners = new Vector(); + running = true; + } + + /** + * Adds listeners. + */ + protected abstract void startListening(); + + /** + * Removes listeners + */ + protected abstract void stopListening(); + + public void enable() { + //enable() always works because a Sensor is always running + super.enable(); + startListening(); + } + + public void disable() { + super.disable(); + stopListening(); + } + + protected void notifyStateChange(int id, double data) { + SensorEvent e = new SensorEvent(this, id, data); + for (int i = 0; i < listeners.size(); i++) { + ((SensorChangeListener) listeners.elementAt(i)).sensorStateChanged(e); + } + } + + public void addSensorStateChangeListener(SensorChangeListener l) { + listeners.addElement(l); + } + + public void removeSensorStateChangeListener(SensorChangeListener l) { + listeners.removeElement(l); + } +} diff --git a/src/deploy/GRTRobot.java b/src/deploy/GRTRobot.java new file mode 100644 index 0000000..810f06d --- /dev/null +++ b/src/deploy/GRTRobot.java @@ -0,0 +1,69 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) FIRST 2008. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in the root directory of */ +/* the project. */ +/*----------------------------------------------------------------------------*/ +package deploy; + +import core.EventController; +import edu.wpi.first.wpilibj.SimpleRobot; +import java.util.Vector; + +/** + * + * GRTRobot is the entry point. + * + * The VM is configured to automatically run this class, and to call the + * functions corresponding to each mode, as described in the SimpleRobot + * documentation. If you change the name of this class or the package after + * creating this project, you must also update the manifest file in the resource + * directory. + */ +public abstract class GRTRobot extends SimpleRobot { + + private Vector autoControllers; + private Vector teleopControllers; + + public GRTRobot() { + autoControllers = new Vector(); + teleopControllers = new Vector(); + + } + + /** + * This function is called once each time the robot enters autonomous mode. + * All Autonomous controllers are started/resumed, and all teleop controllers are paused. + */ + public void autonomous() { + for (int i = 0; i < teleopControllers.size(); i++) { + ((EventController) teleopControllers.elementAt(i)).disable(); + } + for (int i = 0; i < autoControllers.size(); i++) { + ((EventController) autoControllers.elementAt(i)).enable(); + } + + } + + /** + * This function is called once each time the robot enters operator control. + * All Teleop controllers are started/resumed, and all autonomous controllers are paused. + */ + public void operatorControl() { + for (int i = 0; i < autoControllers.size(); i++) { + ((EventController) autoControllers.elementAt(i)).disable(); + } + for (int i = 0; i < teleopControllers.size(); i++) { + ((EventController) teleopControllers.elementAt(i)).enable(); + } + + } + + public void addAutonomousController(EventController c) { + autoControllers.addElement(c); + } + + public void addTeleopController(EventController c) { + teleopControllers.addElement(c); + } +} diff --git a/src/deploy/MainRobot.java b/src/deploy/MainRobot.java new file mode 100644 index 0000000..8d6c2c9 --- /dev/null +++ b/src/deploy/MainRobot.java @@ -0,0 +1,136 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package deploy; + +import actuator.GRTVictor; +import balancer.RobotTiltAccel; +import controller.PrimaryDriver; +import mechanism.GRTDriveTrain; +import sensor.base.GRTXboxDriverStation; +import mechanism.GRTRobotBase; +import sensor.base.LinearDrive; +import sensor.base.SquareDrive; +import sensor.base.IDriverProfile; +import rpc.connection.NetworkRPC; +import rpc.telemetry.SensorLogger; +import sensor.ADXL345DigitalAccelerometer; +import sensor.GRTADXL345; +import sensor.GRTAttack3Joystick; +import sensor.GRTBatterySensor; +import sensor.GRTEncoder; +import sensor.GRTGyro; +import sensor.GRTSwitch; +import sensor.GRTXBoxJoystick; +import sensor.base.*; + +/** + * + * @author ajc + */ +public class MainRobot extends GRTRobot { + + /** + * Buttons which refer to enumerated driver curve profiles. + * First index refers to Linear drive + * Second index refers to Square drive + */ + public static final int[] DRIVER_PROFILE_KEYS = new int[] {1,2}; + public static final IDriverProfile[] DRIVER_PROFILES = new IDriverProfile[] {new LinearDrive(), new SquareDrive()}; + + + + //Global Controllers + private SensorLogger batteryLogger; + //Teleop Controllers + private PrimaryDriver driveControl; + private GRTDriverStation driverStation; + private GRTRobotBase robotBase; + private GRTADXL345 adxl; +// private final ADXL345DigitalAccelerometer primaryADXL; +// private final RobotTiltAccel tiltSensor; +// private final SensorLogger tiltLogger; + + + public MainRobot() { + + System.out.println("Running grtframeworkv6"); + + //RPC Connection + NetworkRPC rpcConn = new NetworkRPC(180); + + //Driver station components + GRTAttack3Joystick primary = new GRTAttack3Joystick(1, 12, "primary"); + GRTAttack3Joystick secondary = new GRTAttack3Joystick(2, 12, "secondary"); + primary.start(); + secondary.start(); + primary.enable(); + secondary.enable(); + System.out.println("Joysticks initialized"); + + //Battery Sensor + GRTBatterySensor batterySensor = new GRTBatterySensor(10, "battery"); + batterySensor.start(); + batterySensor.enable(); + + // PWM outputs + GRTVictor leftDT1 = new GRTVictor(2, "leftDT1"); + GRTVictor leftDT2 = new GRTVictor(3, "leftDT2"); + GRTVictor rightDT1 = new GRTVictor(8, "rightDT1"); + GRTVictor rightDT2 = new GRTVictor(9, "rightDT2"); + leftDT1.enable(); + leftDT2.enable(); + rightDT1.enable(); + rightDT2.enable(); + System.out.println("Motors initialized"); + + //Mechanisms + GRTDriveTrain dt = new GRTDriveTrain(leftDT1, leftDT2, rightDT1, rightDT2); + robotBase = new GRTRobotBase(dt, batterySensor); + driverStation = new GRTAttack3DriverStation(primary, secondary, DRIVER_PROFILE_KEYS, DRIVER_PROFILES, + "driverStation"); + driverStation.enable(); + System.out.println("Mechanisms initialized"); + + //Controllers + driveControl = new PrimaryDriver(robotBase, driverStation, new LinearDrive(), "driveControl"); + batteryLogger = new SensorLogger(batterySensor, rpcConn, new int[]{23}, "batterylogger"); + System.out.println("Controllers Initialized"); + +// adxl = new GRTADXL345(1, 25, "ADXL345"); +// adxl.enable(); +// adxl.start(); + + +// GRTGyro gyro = new GRTGyro(1, 10, "Gyro"); +// gyro.enable(); +// gyro.start(); + +// tiltSensor = new RobotTiltAccel(adxl, "TiltSensor"); +// tiltLogger = new SensorLogger(tiltSensor, rpcConn, new int[]{210}, "tiltLogger"); + + // Start/prepare controllers +// primaryADXL.enable(); +// batteryLogger.enable(); +// tiltSensor.enable(); + + addTeleopController(driveControl); +// addAutonomousController(tiltLogger); + + GRTEncoder encoder1 = new GRTEncoder(2, 1, 4.0, 10, "EncoderLeft"); + + GRTEncoder encoder2 = new GRTEncoder(3, 4, 4.0, 10, "EncoderRight"); + + + encoder1.start(); encoder1.enable(); + encoder2.start(); encoder2.enable(); + + SensorLogger encoderLogger1 = new SensorLogger(encoder1, rpcConn, new int[]{81, 82, 83}, null); + SensorLogger encoderLogger2 = new SensorLogger(encoder2, rpcConn, new int[]{84,85,86}, null); + + + encoderLogger1.enable(); + encoderLogger2.enable(); + } +} diff --git a/src/event/ADXL345Event.java b/src/event/ADXL345Event.java new file mode 100644 index 0000000..2e13e1d --- /dev/null +++ b/src/event/ADXL345Event.java @@ -0,0 +1,39 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package event; +import sensor.GRTADXL345; + +/** + * + * @author calvin + */ +public class ADXL345Event { + public static final int KEY_X = 0; + public static final int KEY_Y = 1; + public static final int KEY_Z = 2; + + private GRTADXL345 source; + private int id; + private double acceleration; + + public ADXL345Event(GRTADXL345 source, int id, double acceleration) { + this.source = source; + this.id = id; + this.acceleration = acceleration; + } + + //TODO what units + public double getAcceleration() { + return acceleration; + } + + public int getId() { + return id; + } + + public GRTADXL345 getSource() { + return source; + } +} diff --git a/src/event/ADXL345Listener.java b/src/event/ADXL345Listener.java new file mode 100644 index 0000000..c06f406 --- /dev/null +++ b/src/event/ADXL345Listener.java @@ -0,0 +1,18 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package event; + +/** + * + * @author calvin + */ +public interface ADXL345Listener { + + public void XAccelChange(ADXL345Event e); + + public void YAccelChange(ADXL345Event e); + + public void ZAccelChange(ADXL345Event e); +} diff --git a/src/event/Attack3JoystickEvent.java b/src/event/Attack3JoystickEvent.java new file mode 100644 index 0000000..f0feb5f --- /dev/null +++ b/src/event/Attack3JoystickEvent.java @@ -0,0 +1,31 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package event; +import sensor.GRTAttack3Joystick; +/** + * + * @author dan + */ +public class Attack3JoystickEvent { + public static final int DEFAULT = 0; + private int id; + private double value; + private GRTAttack3Joystick source; + + public Attack3JoystickEvent(GRTAttack3Joystick source, int id, double value){ + this.source = source; + this.id = id; + this.value = value; + } + public int getId() { + return id; + } + public GRTAttack3Joystick getSource(){ + return source; + } + public double getValue() { + return value; + } +} diff --git a/src/event/Attack3JoystickListener.java b/src/event/Attack3JoystickListener.java new file mode 100644 index 0000000..7648796 --- /dev/null +++ b/src/event/Attack3JoystickListener.java @@ -0,0 +1,15 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package event; + +/** + * + * @author dan + */ +public interface Attack3JoystickListener { + public void XAxisMoved(Attack3JoystickEvent e); + public void YAxisMoved(Attack3JoystickEvent e); + public void AngleChanged(Attack3JoystickEvent e); +} diff --git a/src/event/BatteryVoltageEvent.java b/src/event/BatteryVoltageEvent.java new file mode 100644 index 0000000..f815ccd --- /dev/null +++ b/src/event/BatteryVoltageEvent.java @@ -0,0 +1,32 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package event; + +import sensor.GRTBatterySensor; + + +/** + * + * @author ajc + */ +public class BatteryVoltageEvent { + private final GRTBatterySensor sensor; + private final double voltage; + + public BatteryVoltageEvent(GRTBatterySensor sensor, double voltage){ + this.sensor = sensor; + this.voltage = voltage; + } + + public GRTBatterySensor getSource(){ + return sensor; + } + + public double getVoltage(){ + return voltage; + } + +} diff --git a/src/event/BatteryVoltageListener.java b/src/event/BatteryVoltageListener.java new file mode 100644 index 0000000..87da8e3 --- /dev/null +++ b/src/event/BatteryVoltageListener.java @@ -0,0 +1,16 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package event; + +/** + * + * @author ajc + */ +public interface BatteryVoltageListener { + + public void batteryVoltageChanged(BatteryVoltageEvent ev); + +} diff --git a/src/event/ButtonEvent.java b/src/event/ButtonEvent.java new file mode 100644 index 0000000..1155d43 --- /dev/null +++ b/src/event/ButtonEvent.java @@ -0,0 +1,40 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package event; + +import core.Sensor; + +/** + * + * @author ajc + */ +public class ButtonEvent { + private final Sensor source; + private final int id; + private final boolean pressed; + + public ButtonEvent(Sensor source, int id, boolean pressed){ + this.source = source; + this.id = id; + this.pressed = pressed; + } + + public Sensor getSource(){ + return source; + } + + public int getButtonID(){ + return id; + } + + public boolean isPressed(){ + return pressed; + } + + public boolean isReleased(){ + return !pressed; + } + +} diff --git a/src/event/ButtonListener.java b/src/event/ButtonListener.java new file mode 100644 index 0000000..63eafb1 --- /dev/null +++ b/src/event/ButtonListener.java @@ -0,0 +1,18 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package event; + + +/** + * + * @author anand + */ +public interface ButtonListener { + + public void buttonPressed(ButtonEvent e); + + public void buttonReleased(ButtonEvent e); +} diff --git a/src/event/DrivingEvent.java b/src/event/DrivingEvent.java new file mode 100644 index 0000000..7a6a157 --- /dev/null +++ b/src/event/DrivingEvent.java @@ -0,0 +1,38 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package event; + +import sensor.base.GRTDriverStation; + +/** + * + * @author ajc + */ +public class DrivingEvent { + + public static final int SIDE_LEFT = 0; + public static final int SIDE_RIGHT = 1; + private final GRTDriverStation source; + private final int sideID; + private final double value; + + public DrivingEvent(GRTDriverStation source, int sideID, double value) { + this.source = source; + this.sideID = sideID; + this.value = value; + } + + public int getSide() { + return sideID; + } + + public double getPercentSpeed() { + return value; + } + + public GRTDriverStation getSource() { + return source; + } +} diff --git a/src/event/DrivingListener.java b/src/event/DrivingListener.java new file mode 100644 index 0000000..b392773 --- /dev/null +++ b/src/event/DrivingListener.java @@ -0,0 +1,25 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package event; + +/** + * A high level interface for robot driving + * @author ajc + */ +public interface DrivingListener { + + /** + * Called to set speed of left drivetrain + * @param e + */ + public void driverLeftSpeed(DrivingEvent e); + + /** + * Called to set speed of right drivetrain + * @param e + */ + public void driverRightSpeed(DrivingEvent e); + +} diff --git a/src/event/DrivingProfileEvent.java b/src/event/DrivingProfileEvent.java new file mode 100644 index 0000000..fb4b79f --- /dev/null +++ b/src/event/DrivingProfileEvent.java @@ -0,0 +1,32 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package event; + +import sensor.base.GRTDriverStation; +import sensor.base.IDriverProfile; + +/** + * + * @author ajc + */ +public class DrivingProfileEvent { + + private final GRTDriverStation source; + private final IDriverProfile profile; + + public DrivingProfileEvent(GRTDriverStation source, IDriverProfile profile) { + this.source = source; + this.profile = profile; + + } + + public IDriverProfile getProfile() { + return profile; + } + + public GRTDriverStation getSource() { + return source; + } +} diff --git a/src/event/DrivingProfileListener.java b/src/event/DrivingProfileListener.java new file mode 100644 index 0000000..3e7e1a6 --- /dev/null +++ b/src/event/DrivingProfileListener.java @@ -0,0 +1,14 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package event; + +/** + * + * @author ajc + */ +public interface DrivingProfileListener { + + public void drivingProfileChanged(DrivingProfileEvent e); +} diff --git a/src/event/EncoderEvent.java b/src/event/EncoderEvent.java new file mode 100644 index 0000000..a144079 --- /dev/null +++ b/src/event/EncoderEvent.java @@ -0,0 +1,23 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package event; + +import sensor.GRTEncoder; + +/** + * + * @author gerberduffy + */ +public class EncoderEvent { + + public static final int ROTATION_STARTED = 0; + public static final int ROTATION_STOPPED = 1; + public static final int DEGREE_CHANGE = 2; + + public EncoderEvent(GRTEncoder source){ + + } + +} diff --git a/src/event/EncoderListener.java b/src/event/EncoderListener.java new file mode 100644 index 0000000..20d98da --- /dev/null +++ b/src/event/EncoderListener.java @@ -0,0 +1,19 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package event; + +/** + * + * @author gerberduffy + */ +public interface EncoderListener { + + public void rotationStarted(EncoderEvent e); + + public void degreeChanged(EncoderEvent e); + + public void rotationStopped(EncoderEvent e); + +} diff --git a/src/event/GyroEvent.java b/src/event/GyroEvent.java new file mode 100644 index 0000000..4583ae8 --- /dev/null +++ b/src/event/GyroEvent.java @@ -0,0 +1,29 @@ +/** To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package event; + +import sensor.GRTGyro; + +/** + * + * @author calvin + */ +public class GyroEvent { + + private GRTGyro source; + private double rotation; + + public GyroEvent(GRTGyro source, double rotation) { + this.source = source; + this.rotation = rotation; + } + + public double getAngle() { + return rotation; + } + + public GRTGyro getSource() { + return source; + } +} diff --git a/src/event/GyroListener.java b/src/event/GyroListener.java new file mode 100644 index 0000000..59bc691 --- /dev/null +++ b/src/event/GyroListener.java @@ -0,0 +1,14 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package event; + +/** + * + * @author calvin + */ +public interface GyroListener { + + public void angleChanged(GyroEvent e); +} diff --git a/src/event/PotentiometerEvent.java b/src/event/PotentiometerEvent.java new file mode 100644 index 0000000..bb57a7b --- /dev/null +++ b/src/event/PotentiometerEvent.java @@ -0,0 +1,31 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package event; + +import sensor.Potentiometer; + +/** + * + * @author calvin + */ +public class PotentiometerEvent { + + private Potentiometer source; + private double value; + + public PotentiometerEvent(Potentiometer source, double value) { + this.source = source; + this.value = value; + } + + public double getAngle() { + return value; + } + + public Potentiometer getSource() { + return source; + } + +} diff --git a/src/event/PotentiometerListener.java b/src/event/PotentiometerListener.java new file mode 100644 index 0000000..0c7f49a --- /dev/null +++ b/src/event/PotentiometerListener.java @@ -0,0 +1,13 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package event; + +/** + * + * @author calvin + */ +public interface PotentiometerListener { + public void valueChanged(); +} diff --git a/src/event/RobotTiltEvent.java b/src/event/RobotTiltEvent.java new file mode 100644 index 0000000..4e0f779 --- /dev/null +++ b/src/event/RobotTiltEvent.java @@ -0,0 +1,34 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package event; +import balancer.RobotTiltGyro; + +/** + * + * @author calvin + */ +public class RobotTiltEvent { + private RobotTiltGyro source; + private int id; + private double tilt; + + public RobotTiltEvent(RobotTiltGyro source, int id, double tilt) { + this.source = source; + this.id = id; + this.tilt = tilt; + } + + public double getTilt() { + return tilt; + } + + public int getId() { + return id; + } + + public RobotTiltGyro getSource() { + return source; + } +} diff --git a/src/event/RobotTiltListener.java b/src/event/RobotTiltListener.java new file mode 100644 index 0000000..c443658 --- /dev/null +++ b/src/event/RobotTiltListener.java @@ -0,0 +1,13 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package event; + +/** + * + * @author calvin + */ +public interface RobotTiltListener { + public void RobotTiltChange(RobotTiltEvent e); +} diff --git a/src/event/SensorChangeListener.java b/src/event/SensorChangeListener.java new file mode 100644 index 0000000..1ae5550 --- /dev/null +++ b/src/event/SensorChangeListener.java @@ -0,0 +1,11 @@ + +package event; + +/** + * + * @author anand, ajc + */ +public interface SensorChangeListener { + + public void sensorStateChanged(SensorEvent e); +} diff --git a/src/event/SensorEvent.java b/src/event/SensorEvent.java new file mode 100644 index 0000000..08563dc --- /dev/null +++ b/src/event/SensorEvent.java @@ -0,0 +1,34 @@ +package event; + +import core.Sensor; +import java.util.Hashtable; + +/** + * + * @author anand, ajc + */ +public class SensorEvent { + + private Sensor source; + private int id; + private double data; + + public SensorEvent(Sensor source, int id, double data) { + this.source = source; + this.id = id; + this.data = data; + } + + public double getData() { + return data; + } + + public int getId() { + return id; + } + + public Sensor getSource() { + return source; + } + +} diff --git a/src/event/SwitchEvent.java b/src/event/SwitchEvent.java new file mode 100644 index 0000000..d00f730 --- /dev/null +++ b/src/event/SwitchEvent.java @@ -0,0 +1,31 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package event; + +import core.PollingSensor; +import sensor.GRTSwitch; + +/** + * + * @author gerberduffy + */ +public class SwitchEvent { + + private boolean state; + private GRTSwitch sw; + + public SwitchEvent(GRTSwitch sw, double newState){ + state = newState == PollingSensor.TRUE; + this.sw = sw; + } + + public GRTSwitch getSource(){ + return this.sw; + } + + public boolean getState(){ + return this.state; + } +} diff --git a/src/event/SwitchListener.java b/src/event/SwitchListener.java new file mode 100644 index 0000000..3606e1b --- /dev/null +++ b/src/event/SwitchListener.java @@ -0,0 +1,15 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package event; + +/** + * + * @author gerberduffy + */ +public interface SwitchListener { + + public void switchStateChanged(event.SwitchEvent e); + +} diff --git a/src/event/XboxJoystickEvent.java b/src/event/XboxJoystickEvent.java new file mode 100644 index 0000000..677bd19 --- /dev/null +++ b/src/event/XboxJoystickEvent.java @@ -0,0 +1,37 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package event; + +import sensor.GRTXBoxJoystick; + +/** + * + * @author student + */ +public class XboxJoystickEvent { + + public static final int DEFAULT = 0; + private GRTXBoxJoystick source; + private int id; + private double value; + + public XboxJoystickEvent(GRTXBoxJoystick source, int id, double value) { + this.source = source; + this.id = id; + this.value = value; + } + + public int getId() { + return id; + } + + public GRTXBoxJoystick getSource() { + return source; + } + + public double getValue() { + return value; + } +} \ No newline at end of file diff --git a/src/event/XboxJoystickListener.java b/src/event/XboxJoystickListener.java new file mode 100644 index 0000000..5483c71 --- /dev/null +++ b/src/event/XboxJoystickListener.java @@ -0,0 +1,23 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package event; + +/** + * + * @author student + */ +public interface XboxJoystickListener { + public void leftXAxisMoved(XboxJoystickEvent e); + public void leftYAxisMoved(XboxJoystickEvent e); + public void leftAngleChanged(XboxJoystickEvent e); + + public void rightXAxisMoved(XboxJoystickEvent e); + public void rightYAxisMoved(XboxJoystickEvent e); + + public void padMoved(XboxJoystickEvent e); + + public void triggerMoved(XboxJoystickEvent e); +} \ No newline at end of file diff --git a/src/mechanism/GRTDriveTrain.java b/src/mechanism/GRTDriveTrain.java new file mode 100644 index 0000000..bef8fd6 --- /dev/null +++ b/src/mechanism/GRTDriveTrain.java @@ -0,0 +1,47 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package mechanism; + +import actuator.IMotor; + +/** + * Standard 4 motor drivetrain. + * @author ajc + */ +public class GRTDriveTrain { + + private final IMotor leftFront; + private final IMotor leftBack; + private final IMotor rightFront; + private final IMotor rightBack; + + /** + * + * @param leftFront left front motor + * @param leftBack left back motor + * @param rightFront right front motor + * @param rightBack right back motor + */ + public GRTDriveTrain(IMotor leftFront, IMotor leftBack, + IMotor rightFront, IMotor rightBack) { + + this.leftFront = leftFront; + this.leftBack = leftBack; + this.rightFront = rightFront; + this.rightBack = rightBack; + } + + /** + * TankDrive uses differential steering. + * @param leftVelocity + * @param rightVelocity + */ + public void tankDrive(double leftVelocity, double rightVelocity) { + leftFront.setSpeed(-leftVelocity); + leftBack.setSpeed(-leftVelocity); + rightFront.setSpeed(-rightVelocity); + rightBack.setSpeed(-rightVelocity); + } +} diff --git a/src/mechanism/GRTRobotBase.java b/src/mechanism/GRTRobotBase.java new file mode 100644 index 0000000..c6c7a72 --- /dev/null +++ b/src/mechanism/GRTRobotBase.java @@ -0,0 +1,35 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package mechanism; + +import sensor.GRTBatterySensor; + +/** + * Encapsulates all components on the robot base. + * + * @author ajc + */ +public class GRTRobotBase { + + private final GRTDriveTrain dt; + private final GRTBatterySensor s; + + public GRTRobotBase(GRTDriveTrain dt, GRTBatterySensor s) { + this.dt = dt; + this.s = s; + } + + public GRTDriveTrain getDriveTrain() { + return dt; + } + + public GRTBatterySensor getBatterySensor(){ + return s; + } + + public void tankDrive(double leftVelocity, double rightVelocity){ + dt.tankDrive(leftVelocity, rightVelocity); + } +} diff --git a/src/networking/GRTClientSocket.java b/src/networking/GRTClientSocket.java new file mode 100644 index 0000000..775c689 --- /dev/null +++ b/src/networking/GRTClientSocket.java @@ -0,0 +1,156 @@ +package networking; + +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.util.Vector; + +import javax.microedition.io.Connector; + +import com.sun.squawk.io.BufferedReader; +import javax.microedition.io.SocketConnection; + +public class GRTClientSocket extends Thread implements GRTSocket { + public static final int POLL_TIME = 50; + + private String host; + private int port; + private boolean connected; + + private boolean running; + private Vector socketListeners; + private SocketConnection connection; + private BufferedReader in; + private OutputStreamWriter out; + private String lastData; + + public GRTClientSocket(String host, int port) { + this.host = host; + this.port = port; + running = connected = false; + socketListeners = new Vector(); + try { + connection = ((SocketConnection) (Connector.open("socket://" + host + + ":" + port))); + } catch (IOException e) { + e.printStackTrace(); + connection = null; + } + } + + public void run() { + running = true; + while (running) { + poll(); + try { + Thread.sleep(POLL_TIME); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + + public synchronized void sendData(String data) { + if (connected) { + try { + out.write(data); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + protected void poll() { + if (!connected) { + connect(); + } + try { + String latest = in.readLine(); + if (latest != null && !latest.equals("")){ + lastData = latest; + notifyListeners(); + } + } catch (Exception e) { + e.printStackTrace(); + disconnect(); + } + } + + public void connect() { + try { + in = new BufferedReader(new InputStreamReader(connection + .openInputStream())); + out = new OutputStreamWriter(connection.openOutputStream()); + connected = true; + notifyConnected(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public String getHost() { + return host; + } + + public int getPort() { + return port; + } + + public boolean isConnected() { + return connected; + } + + public void stop() { + disconnect(); + this.running = false; + } + + public void disconnect() { + if (connected) { + try { + connected = false; + in.close(); + out.close(); + notifyDisconnected(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + public String getLastData() { + return lastData; + } + + private void notifyListeners() { + for (int i = 0; i < socketListeners.size(); i++) { + ((SocketListener) socketListeners.elementAt(i)) + .dataRecieved(new SocketEvent(this, SocketEvent.ON_DATA, + lastData)); + } + } + + private void notifyConnected() { + for (int i = 0; i < socketListeners.size(); i++) { + ((SocketListener) socketListeners.elementAt(i)) + .dataRecieved(new SocketEvent(this, SocketEvent.ON_CONNECT, + null)); + } + } + + private void notifyDisconnected() { + for (int i = 0; i < socketListeners.size(); i++) { + ((SocketListener) socketListeners.elementAt(i)) + .dataRecieved(new SocketEvent(this, SocketEvent.ON_DISCONNECT, + null)); + } + } + + public void addSocketListener(SocketListener s) { + socketListeners.addElement(s); + } + + public void removeSocketListener(SocketListener s) { + socketListeners.removeElement(s); + } +} diff --git a/src/networking/GRTServer.java b/src/networking/GRTServer.java new file mode 100644 index 0000000..b5da4eb --- /dev/null +++ b/src/networking/GRTServer.java @@ -0,0 +1,226 @@ +package networking; + +import com.sun.squawk.io.BufferedReader; +//import com.sun.squawk.microedition.io.ServerSocketConnection; +import java.io.DataInputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.util.Vector; +import javax.microedition.io.Connector; +import javax.microedition.io.ServerSocketConnection; +import javax.microedition.io.StreamConnection; + +/** + * A event driven daemon which makes multiple single client connections + * @author data, ajc + */ +public class GRTServer extends Thread implements GRTSocket { + + /** + * A single client connection to the server. + */ + private class GRTSingleConnect extends Thread implements GRTSocket { + + private StreamConnection client; + private OutputStreamWriter osw; + private BufferedReader in; +// private DataInputStream in; + InputStreamReader isr; + private OutputStreamWriter out; + private boolean running; + private boolean connected = true; + Vector serverSocketListeners; + + public GRTSingleConnect(StreamConnection client) { + try { + this.client = client; +// GRTRobot.getInstance().getLogger().write("GRTServer", client.toString()); + serverSocketListeners = new Vector(); +// isr = new InputStreamReader(client.openInputStream()); +// isr.read + in = new BufferedReader(new InputStreamReader(client.openInputStream()),1); + +// client.openDataInputStream().readUT +// in = client.openDataInputStream(); + out = new OutputStreamWriter(client.openOutputStream()); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public void run() { + running = true; + while (running) { + try { +// System.out.println("Waiting for input..."); + String text = in.readLine(); +// String text = in.readUTF(); + notifyMyListeners(text); + } catch (Exception e) { + this.disconnect(); + e.printStackTrace(); + } + + } + } + + public void stop() { + running = false; + } + + public void sendData(String data) { + try { + out.write(data + "\n"); + } catch (IOException e) { + //GRTRobot.getInstance().getLogger().write("GRTServer", "disconnected from client"); + this.disconnect(); + } catch (Exception e) { + e.printStackTrace(); + + } + + } + + public boolean isConnected() { + return connected; + } + + public void connect() { + connected = true; + } + + public void disconnect() { + try { + in.close(); + out.close(); + client.close(); + clients.removeElement(this); + running = false; + notifyMyDisconnect(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public void addSocketListener(SocketListener s) { + serverSocketListeners.addElement(s); + } + + public void removeSocketListener(SocketListener s) { + serverSocketListeners.removeElement(s); + } + + private void notifyMyListeners(String text) { + if (text == null) { + return; + } + for (int i = 0; i < serverSocketListeners.size(); i++) { + SocketListener s = (SocketListener) serverSocketListeners.elementAt(i); + s.dataRecieved(new SocketEvent(this, SocketEvent.ON_DATA, text)); + } + notifyListeners(text, this); + } + + private void notifyMyDisconnect() { + for (int i = 0; i < serverSocketListeners.size(); i++) { + SocketListener s = (SocketListener) serverSocketListeners.elementAt(i); + s.onDisconnect(new SocketEvent(this, SocketEvent.ON_DISCONNECT, null)); + } + notifyDisconnect(this); + } + } + + public GRTServer(int port) { + server = null; + while (server == null) { + try { +// Connector. + server = (ServerSocketConnection) Connector.open("socket://:" + port); + } catch (IOException e) { + e.printStackTrace(); + System.out.println("Failed to open socket!!!!!!!!"); + server = null; + } + try { + Thread.sleep(1000); + } catch (InterruptedException ex) { + ex.printStackTrace(); + } + } + + serverSocketListeners = new Vector(); + clients = new Vector(); + + } + private ServerSocketConnection server; + private Vector clients; + private boolean running; + private Vector serverSocketListeners; + + public void sendData(String data) { + for (int i = 0; i < clients.size(); i++) { + GRTSingleConnect c = (GRTSingleConnect) clients.elementAt(i); + c.sendData(data); + } + } + + public boolean isConnected() { + return clients.size() > 0; + } + + public void connect() { + try { + StreamConnection client = server.acceptAndOpen(); + GRTSingleConnect c = new GRTSingleConnect(client); + c.start(); + clients.addElement(c); + notifyConnect(c); + } catch (Exception e) { + e.printStackTrace(); + } + + } + + public void run() { + running = true; + while (running) { + connect(); + } + } + + public void disconnect() { + for (int i = 0; i < clients.size(); i++) { + ((GRTSingleConnect) clients.elementAt(i)).stop(); + } + } + + public void addSocketListener(SocketListener s) { + serverSocketListeners.addElement(s); + } + + public void removeSocketListener(SocketListener s) { + serverSocketListeners.removeElement(s); + } + + private void notifyListeners(String text, GRTSocket source) { + for (int i = 0; i < serverSocketListeners.size(); i++) { + SocketListener s = (SocketListener) serverSocketListeners.elementAt(i); + s.dataRecieved(new SocketEvent(source, SocketEvent.ON_DATA, text)); + } + } + + private void notifyDisconnect(GRTSocket source) { + for (int i = 0; i < serverSocketListeners.size(); i++) { + SocketListener s = (SocketListener) serverSocketListeners.elementAt(i); + s.onDisconnect(new SocketEvent(source, SocketEvent.ON_DISCONNECT, null)); + } + } + + private void notifyConnect(GRTSocket source) { + for (int i = 0; i < serverSocketListeners.size(); i++) { + SocketListener s = (SocketListener) serverSocketListeners.elementAt(i); + s.onConnect(new SocketEvent(source, SocketEvent.ON_CONNECT, null)); + } + } +} diff --git a/src/networking/GRTSingleClientServer.java b/src/networking/GRTSingleClientServer.java new file mode 100644 index 0000000..28f519e --- /dev/null +++ b/src/networking/GRTSingleClientServer.java @@ -0,0 +1,149 @@ +package networking; + +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.util.Vector; + +import javax.microedition.io.Connector; +import javax.microedition.io.StreamConnection; + +import com.sun.squawk.io.BufferedReader; +import javax.microedition.io.ServerSocketConnection; + +public class GRTSingleClientServer extends Thread implements GRTSocket { + public static final int POLL_TIME = 50; + + private ServerSocketConnection server; + private StreamConnection client; + private BufferedReader in; + private OutputStreamWriter out; + private boolean connected; + private Vector serverSocketListeners; + private String lastData; + + private boolean running; + + public GRTSingleClientServer(int port) { + try { + server = (ServerSocketConnection) Connector.open("socket://:" + + port); + } catch (IOException e) { + e.printStackTrace(); + server = null; + } + connected = false; + serverSocketListeners = new Vector(); + running = false; + } + + public void run() { + running = true; + while (running) { + poll(); + } + } + + public synchronized void sendData(String data) { + if (connected) { + try { + out.write(data+"\n"); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + public void connect() { + try { + client = server.acceptAndOpen(); + in = new BufferedReader(new InputStreamReader(client + .openInputStream())); + out = new OutputStreamWriter(client.openOutputStream()); + connected = true; + notifyConnected(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + protected void poll() { + if (!connected) { + connect(); + } + try { + String latest = in.readLine(); + if (latest != null && !latest.equals("")){ + lastData = latest; + notifyListeners(); + } + } catch (Exception e) { + e.printStackTrace(); + disconnect(); + } + } + + private void notifyListeners() { + for (int i = 0; i < serverSocketListeners.size(); i++) { + ((SocketListener) serverSocketListeners.elementAt(i)) + .dataRecieved(new SocketEvent(this, SocketEvent.ON_DATA, + lastData)); + } + } + + private void notifyConnected() { + for (int i = 0; i < serverSocketListeners.size(); i++) { + ((SocketListener) serverSocketListeners.elementAt(i)) + .dataRecieved(new SocketEvent(this, SocketEvent.ON_CONNECT, + null)); + } + } + + private void notifyDisconnected() { + for (int i = 0; i < serverSocketListeners.size(); i++) { + ((SocketListener) serverSocketListeners.elementAt(i)) + .dataRecieved(new SocketEvent(this, SocketEvent.ON_DISCONNECT, + null)); + } + } + + public boolean isConnected() { + return connected; + } + + public String getLastData() { + return lastData; + } + + public boolean isRunning() { + return running; + } + + public void stop() { + disconnect(); + this.running = false; + } + + public void disconnect() { + if (connected) { + try { + connected = false; + in.close(); + out.close(); + client.close(); + notifyDisconnected(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + public void addSocketListener(SocketListener s) { + serverSocketListeners.addElement(s); + } + + public void removeSocketListener(SocketListener s) { + serverSocketListeners.removeElement(s); + } + +} diff --git a/src/networking/GRTSocket.java b/src/networking/GRTSocket.java new file mode 100644 index 0000000..6334d0e --- /dev/null +++ b/src/networking/GRTSocket.java @@ -0,0 +1,15 @@ +package networking; + +public interface GRTSocket { + public void sendData(String data); + + public boolean isConnected(); + + public void connect(); + + public void disconnect(); + + public void addSocketListener(SocketListener s); + + public void removeSocketListener(SocketListener s); +} diff --git a/src/networking/SocketEvent.java b/src/networking/SocketEvent.java new file mode 100644 index 0000000..fa8b7e6 --- /dev/null +++ b/src/networking/SocketEvent.java @@ -0,0 +1,28 @@ +package networking; + +public class SocketEvent { + public static final int ON_DATA = 0; + public static final int ON_CONNECT = 1; + public static final int ON_DISCONNECT = 2; + private GRTSocket source; + private int id; + private String data; + + public SocketEvent(GRTSocket source, int id, String data) { + super(); + this.source = source; + this.id = id; + this.data = data; + } + public GRTSocket getSource() { + return source; + } + public int getId() { + return id; + } + public String getData() { + return data; + } + + +} diff --git a/src/networking/SocketListener.java b/src/networking/SocketListener.java new file mode 100644 index 0000000..d8f7206 --- /dev/null +++ b/src/networking/SocketListener.java @@ -0,0 +1,8 @@ +package networking; + +public interface SocketListener { + + public void onConnect(SocketEvent e); + public void onDisconnect(SocketEvent e); + public void dataRecieved(SocketEvent e); +} diff --git a/src/rpc/RPCConnection.java b/src/rpc/RPCConnection.java new file mode 100644 index 0000000..ce429b7 --- /dev/null +++ b/src/rpc/RPCConnection.java @@ -0,0 +1,11 @@ +package rpc; + +public interface RPCConnection { + + public void send(RPCMessage message); + + public void addMessageListener(RPCMessageListener l); + + public void removeMessageListener(RPCMessageListener l); + +} diff --git a/src/rpc/RPCMessage.java b/src/rpc/RPCMessage.java new file mode 100644 index 0000000..2f1f1ad --- /dev/null +++ b/src/rpc/RPCMessage.java @@ -0,0 +1,25 @@ +package rpc; + +public class RPCMessage { + + private final int key; + private final double data; + + public RPCMessage(int key, double data) { + this.key = key; + this.data = data; + } + + public int getKey() { + return key; + } + + public double getData() { + return data; + } + + public String toString() { + return "RPCMessage:" + key + ":" + data; + } + +} diff --git a/src/rpc/RPCMessageListener.java b/src/rpc/RPCMessageListener.java new file mode 100644 index 0000000..6540d21 --- /dev/null +++ b/src/rpc/RPCMessageListener.java @@ -0,0 +1,11 @@ +package rpc; + +/** + * + * @author ajc + * + */ +public interface RPCMessageListener { + + public void messageReceived(RPCMessage message); +} diff --git a/src/rpc/connection/NetworkRPC.java b/src/rpc/connection/NetworkRPC.java new file mode 100644 index 0000000..f6eeba2 --- /dev/null +++ b/src/rpc/connection/NetworkRPC.java @@ -0,0 +1,101 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package rpc.connection; + +import networking.GRTServer; +import networking.SocketEvent; +import networking.SocketListener; +import java.util.Enumeration; +import java.util.Vector; +import rpc.RPCConnection; +import rpc.RPCMessage; +import rpc.RPCMessageListener; + +/** + * NetworkRPC provides an Internet RPC connection. It currently receives + * messages from any connecting host, and sends messages to all connected hosts + * + * @author ajc + */ +public class NetworkRPC implements RPCConnection, SocketListener { + + private GRTServer connection; + private Vector listeners = new Vector(); + + /** + * Opens a new Network RPC connection and starts it. + * @param port + */ + public NetworkRPC(int port) { + connection = new GRTServer(port); + start(); + } + + + private void start(){ + connection.addSocketListener(this); + connection.start(); + } + + //TODO enable sending to a single host + public void send(RPCMessage message) { + connection.sendData(encode(message)); + } + + public void addMessageListener(RPCMessageListener l) { + listeners.addElement(l); + } + + public void removeMessageListener(RPCMessageListener l) { + listeners.removeElement(l); + } + + private void notifyListeners(String received) { + if (isTelemetryLine(received)) { + // RPCMessage message = new RPCMessage(getKey(received), + // getData(received)); + RPCMessage message = decode(received); +// System.out.println(message); + // TODO only notify specific 'keyed' listeners + for (Enumeration e = listeners.elements(); e.hasMoreElements();) { + ((RPCMessageListener) e.nextElement()).messageReceived(message); + } + + } + } + + private static String encode(RPCMessage m) { + // newline to flush all buffers + return ("USB" + m.getKey() + ":" + m.getData() + "\n"); + } + + private static RPCMessage decode(String received) { + return new RPCMessage(getKey(received), getData(received)); + } + + private static boolean isTelemetryLine(String line) { + return line.length() > 3 && line.substring(0, 3).equals("USB");// TODO + // MAGICNUMBERS + } + + private static int getKey(String line) { + return Integer.parseInt(line.substring(3, line.indexOf(':'))); + } + + private static double getData(String line) { + return Double.parseDouble((line.substring(line.indexOf(':') + 1))); + } + + public void onConnect(SocketEvent e) { //TODO + } + + public void onDisconnect(SocketEvent e) { //TODO + } + + public void dataRecieved(SocketEvent e) { +// System.out.println("Data received: " + e.getData()); + notifyListeners(e.getData()); + } +} diff --git a/src/rpc/connection/StreamedRPC.java b/src/rpc/connection/StreamedRPC.java new file mode 100644 index 0000000..fffe211 --- /dev/null +++ b/src/rpc/connection/StreamedRPC.java @@ -0,0 +1,122 @@ +package rpc.connection; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.Enumeration; +import java.util.Vector; + +import rpc.RPCConnection; +import rpc.RPCMessage; +import rpc.RPCMessageListener; + +/** + * Reads lines from an input stream + * + * @author ajc + * + */ +public class StreamedRPC extends Thread implements RPCConnection { + + private static final int MAX_STRING_LENGTH = 1024; + // stores byteform of string until newline + private byte[] buffer = new byte[MAX_STRING_LENGTH]; + private final InputStream in; + private final OutputStream out; + private boolean running; // TODO grtobject type thing + private Vector listeners = new Vector(); + + public StreamedRPC(InputStream in, OutputStream out) { + this.in = in; + this.out = out; + } + + public void run() { + running = true; + while (running) { + poll(); + try { + Thread.sleep(1);// TODO sleeping + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + } + + private void poll() { + int data; + try { + int len = 0; + while ((data = in.read()) > -1) { + if (data == '\n') { + break; + } + buffer[len++] = (byte) data; + } + // System.out.println("READ:\t" + new String(buffer, 0, len));// + // TODO + // selected + // debug: + // prints + notifyListeners(new String(buffer, 0, len)); + } catch (IOException e) { + e.printStackTrace(); + System.exit(-1); + } + } + + private static boolean isTelemetryLine(String line) { + return line.length() > 3 && line.substring(0, 3).equals("USB");// TODO + // MAGICNUMBERS + } + + private static int getKey(String line) { + return Integer.parseInt(line.substring(3, line.indexOf(':'))); + } + + private static double getData(String line) { + return Double.parseDouble((line.substring(line.indexOf(':') + 1))); + } + + public void addMessageListener(RPCMessageListener listener) { + listeners.addElement(listener); + } + + public void removeMessageListener(RPCMessageListener listener) { + listeners.removeElement(listener); + } + + private void notifyListeners(String received) { + if (isTelemetryLine(received)) { + // RPCMessage message = new RPCMessage(getKey(received), + // getData(received)); + RPCMessage message = decode(received); + // System.out.println(message); + // TODO only notify specific 'keyed' listeners + for (Enumeration e = listeners.elements(); e.hasMoreElements();) { + ((RPCMessageListener) e.nextElement()).messageReceived(message); + } + + } + } + + public void send(RPCMessage message) { + try { + out.write(encode(message)); + out.flush(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + private static byte[] encode(RPCMessage m) { + // newline to flush all buffers + return ("USB" + m.getKey() + ":" + m.getData() + "\n").getBytes(); + } + + private static RPCMessage decode(String received) { + return new RPCMessage(getKey(received), getData(received)); + } +} diff --git a/src/rpc/telemetry/SensorLogger.java b/src/rpc/telemetry/SensorLogger.java new file mode 100644 index 0000000..a555625 --- /dev/null +++ b/src/rpc/telemetry/SensorLogger.java @@ -0,0 +1,49 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package rpc.telemetry; + +import core.EventController; +import core.Sensor; +import event.SensorChangeListener; +import event.SensorEvent; +import rpc.RPCConnection; +import rpc.RPCMessage; + +/** + * Automatically sends all data from any sensor. + * @author ajc + */ +public class SensorLogger extends EventController implements SensorChangeListener { + + private final Sensor s; + private final RPCConnection conn; + private final int[] rpcKeys; + + /** + * + * @param s sensor to read from + * @param conn connection to send data with + * @param rpcKeys rpc keys to send data with for each index of sensor + * @param name name of process + */ + public SensorLogger(Sensor s, RPCConnection conn, int[] rpcKeys, String name) { + super(name); + this.s = s; + this.conn = conn; + this.rpcKeys = rpcKeys; + } + + protected void startListening() { + s.addSensorStateChangeListener(this); + } + + protected void stopListening() { + s.removeSensorStateChangeListener(this); + } + + public void sensorStateChanged(SensorEvent e) { + conn.send(new RPCMessage(rpcKeys[e.getId()], e.getData())); + } +} diff --git a/src/sensor/ADXL345DigitalAccelerometer.java b/src/sensor/ADXL345DigitalAccelerometer.java new file mode 100644 index 0000000..e9f68b7 --- /dev/null +++ b/src/sensor/ADXL345DigitalAccelerometer.java @@ -0,0 +1,175 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) FIRST 2008. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in the root directory of */ +/* the project. */ +/*----------------------------------------------------------------------------*/ + +package sensor; + +import edu.wpi.first.wpilibj.DigitalModule; +import edu.wpi.first.wpilibj.I2C; +import edu.wpi.first.wpilibj.SensorBase; + + + +/** + * + * digital accelerometer from the 2010 KOP + * + * this implementation just gets the 3 axis values and allows setting the range + * + * Possible enhancements: + * Add access to other features of the chip + * Add measurement of error during intialization and set channel offsets + */ +public class ADXL345DigitalAccelerometer extends SensorBase { + private I2C i2c; + // default address + private static final byte kAddress = 0x3A; + // register map from datasheet + private static final byte OFSX = 0x1E; + private static final byte OFSY = 0x1F; + private static final byte OFSZ = 0x20; + private static final byte BW_RATE = 0x2C; + private static final byte POWER_CTL = 0x2D; + private static final byte DATA_FORMAT = 0x31; + private static final byte DATAX0 = 0x32; + private static final byte DATAY0 = 0x34; + private static final byte DATAZ0 = 0x36; + private static final byte FIFO_CTL = 0x38; + private static final byte FIFO_STATUS = 0x39; + + + + + // would use enums here if we had them + // BW_RATE 0x2C + private static final byte BW_RATE_R3200B1600 = 0x0F; + private static final byte BW_RATE_R1600B0800 = 0x0E; + private static final byte BW_RATE_R0800B0400 = 0x0D; + private static final byte BW_RATE_R0400B0200 = 0x0C; + private static final byte BW_RATE_R0200B0100 = 0x0B; + private static final byte BW_RATE_R0100B0050 = 0x0A; + private static final byte BW_RATE_R0050B0025 = 0x09; + private static final byte BW_RATE_R0025B0012 = 0x08; + private static final byte BW_RATE_R0012B0006 = 0x07; + private static final byte BW_RATE_R0006B0003 = 0x06; + + private static final byte BW_RATE_LOW_POWER = 0x10; + + // POWER_CTL 0x2D + private static final byte POWER_CTL_LINK = 0x20; + private static final byte POWER_CTL_AUTO_SLEEP = 0x10; + private static final byte POWER_CTL_MEASURE = 0x08; + private static final byte POWER_CTL_SLEEP = 0x04; + private static final byte POWER_CTL_WAKEUP8 = 0x00; + private static final byte POWER_CTL_WAKEUP4 = 0x01; + private static final byte POWER_CTL_WAKEUP2 = 0x02; + private static final byte POWER_CTL_WAKEUP1 = 0x03; + + // DATA_FORMAT + public static final byte DATA_FORMAT_02G = 0x00; + public static final byte DATA_FORMAT_04G = 0x01; + public static final byte DATA_FORMAT_08G = 0x02; + public static final byte DATA_FORMAT_16G = 0x03; + + // store the current + private byte range = DATA_FORMAT_02G; + + public class ADXL345Exception extends RuntimeException { + + /** + * Create a new exception with the given message + * @param message the message to pass with the exception + */ + public ADXL345Exception(String message) { + super(message); + } + + } + + // + // constuctior with slot number parameter + // + public ADXL345DigitalAccelerometer(int slot) { + + i2c = new I2C( DigitalModule.getInstance(1), kAddress ); + } + + // initialize the sensor + public void initialize() + { + // set BW_RATE + i2c.write(BW_RATE, BW_RATE_R0100B0050); + // set POWER_CTL + i2c.write(POWER_CTL, POWER_CTL_MEASURE); + } + + // set he range (default is =/- 2g + public void setRange( byte rangeParam ) + { + if ( !( rangeParam == DATA_FORMAT_02G || + rangeParam == DATA_FORMAT_04G || + rangeParam == DATA_FORMAT_08G || + rangeParam == DATA_FORMAT_16G ) ) + { + throw new ADXL345Exception("Invalid range!"); + } + + + range = rangeParam; + + i2c.write(DATA_FORMAT, range); + } + + // get acceleration routines + public double getXAxis() + { + return getAxis( DATAX0 ); + } + + public double getYAxis() + { + return getAxis( DATAY0 ); + } + + public double getZAxis() + { + return getAxis( DATAZ0 ); + } + + protected double getAxis( byte registerParam ) + { + // setup array for our data + byte[] data = new byte[2]; + // read consecutive registers + this.i2c.read( registerParam, (byte) data.length, data); + + // convert to 2s complement integer + // [0] has low byte [1] has the high byte + // jave does not have unsigned so we have to do it this way + int intResult = ( data[0] & 0xFF ) | ( data[1] << 8 ); + + // convert to double based on 10 bit result + double returnValue = (double)intResult / 512.0 ; + + // now scale based upon our range + switch( range ) + { + case DATA_FORMAT_02G: + returnValue *= 2.0; + break; + case DATA_FORMAT_04G: + returnValue *= 4.0; + break; + case DATA_FORMAT_08G: + returnValue *= 8.0; + break; + case DATA_FORMAT_16G: + returnValue *= 16.0; + break; + } + return returnValue; + } +} diff --git a/src/sensor/GRTADXL345.java b/src/sensor/GRTADXL345.java new file mode 100644 index 0000000..04e5513 --- /dev/null +++ b/src/sensor/GRTADXL345.java @@ -0,0 +1,78 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package sensor; + +import core.PollingSensor; +import edu.wpi.first.wpilibj.ADXL345_I2C; +import event.ADXL345Event; +import event.ADXL345Listener; +import java.util.Vector; +/** + * + * @author gerberduffy + */ +public class GRTADXL345 extends PollingSensor{ + + private ADXL345_I2C i2c; + + private static final int X_AXIS = 0; + private static final int Y_AXIS = 1; + private static final int Z_AXIS = 2; + private static final int NUM_DATA = 3; + + + + private Vector listeners; + + private ADXL345_I2C.AllAxes accelerations; + + public GRTADXL345(int slot, int pollTime, String id){ + super (id, pollTime, NUM_DATA); + i2c = new ADXL345_I2C(slot, ADXL345_I2C.DataFormat_Range.k2G); + + listeners = new Vector(); + } + + protected void poll() { + setState(X_AXIS, i2c.getAcceleration(ADXL345_I2C.Axes.kX)); + setState(Y_AXIS, i2c.getAcceleration(ADXL345_I2C.Axes.kY)); + setState(Z_AXIS, i2c.getAcceleration(ADXL345_I2C.Axes.kZ)); + + System.out.println("ADXL345:\t" + getState(X_AXIS) + "\t" + getState(Y_AXIS) + "\t" + getState(Z_AXIS)); + } + + public void addADXL345Listener(ADXL345Listener l){ + listeners.addElement(l); + } + + public void removeADXL345Listener(ADXL345Listener l){ + listeners.removeElement(l); + } + + protected void notifyListeners(int id, double oldDatum, double newDatum) { + ADXL345Event e = new ADXL345Event(this, id, newDatum); + + switch (id){ + case X_AXIS: { + for (int i=0; i < listeners.size(); i++){ + ((ADXL345Listener)listeners.elementAt(i)).XAccelChange(e); + } + } + + case Y_AXIS: { + for (int i=0; i < listeners.size(); i++){ + ((ADXL345Listener)listeners.elementAt(i)).YAccelChange(e); + } + } + + case Z_AXIS: { + for (int i=0; i < listeners.size(); i++){ + ((ADXL345Listener)listeners.elementAt(i)).ZAccelChange(e); + } + } + } + } + +} diff --git a/src/sensor/GRTAttack3Joystick.java b/src/sensor/GRTAttack3Joystick.java new file mode 100644 index 0000000..b9c4760 --- /dev/null +++ b/src/sensor/GRTAttack3Joystick.java @@ -0,0 +1,107 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package sensor; + +import core.PollingSensor; +import edu.wpi.first.wpilibj.Joystick; +import event.*; +import java.util.Vector; + +/** + * + * @author dan + */ +public class GRTAttack3Joystick extends PollingSensor { + private final Vector joystickListeners; + private final Vector buttonListeners; + private final Joystick joystick; + public static final int KEY_BUTTON_0 = 0; + public static final int KEY_BUTTON_1 = 1; + public static final int KEY_BUTTON_2 = 2; + public static final int KEY_BUTTON_3 = 3; + public static final int KEY_BUTTON_4 = 4; + public static final int KEY_BUTTON_5 = 5; + public static final int KEY_BUTTON_6 = 6; + public static final int KEY_BUTTON_7 = 7; + public static final int KEY_BUTTON_8 = 8; + public static final int KEY_BUTTON_9 = 9; + public static final int KEY_X = 10; + public static final int KEY_Y = 11; + public static final int KEY_JOYSTICK_ANGLE = 12; + private final static int NUM_OF_BUTTONS=10; + private final static int NUM_DATA=13; + public static final double PRESSED = TRUE; + public static final double RELEASED = FALSE; + + public GRTAttack3Joystick(int channel, int pollTime, String name){ + super(name, pollTime, NUM_DATA); + joystick = new Joystick(channel); + joystickListeners = new Vector(); + buttonListeners = new Vector(); + + } + + protected void poll() { + for (int i = 0; i < NUM_OF_BUTTONS; ++i){ + setState(i, joystick.getRawButton(i)?PRESSED:RELEASED); + } + setState(KEY_X, joystick.getX()); + setState(KEY_Y, joystick.getY()); + setState(KEY_JOYSTICK_ANGLE, joystick.getDirectionRadians()); + } + + protected void notifyListeners(int id, double oldDatum, double newDatum) { + if (id < NUM_OF_BUTTONS) { + //ID maps directly to button ID + ButtonEvent e = new ButtonEvent(this, id, newDatum == PRESSED); + if (newDatum == PRESSED) { //true + for (int i = 0; i < buttonListeners.size(); i++) { + ((ButtonListener) buttonListeners.elementAt(i)).buttonPressed(e); + } + } else { + for (int i = 0; i < buttonListeners.size(); i++) { + ((ButtonListener) buttonListeners.elementAt(i)).buttonReleased(e); + } + } + + } else { //we are now a joystick + //only reach here if not a button + Attack3JoystickEvent e = new Attack3JoystickEvent(this, id, newDatum); + switch (id){ + case (KEY_X): + for (int i = 0; i < joystickListeners.size(); i++) { + ((Attack3JoystickListener)joystickListeners.elementAt(i)).XAxisMoved(e); + } + break; + case (KEY_Y): + for (int i = 0; i < joystickListeners.size(); i++) { + ((Attack3JoystickListener)joystickListeners.elementAt(i)).YAxisMoved(e); + } + break; + case (KEY_JOYSTICK_ANGLE): + for (int i = 0; i < joystickListeners.size(); i++) { + ((Attack3JoystickListener)joystickListeners.elementAt(i)).AngleChanged(e); + } + break; + } + } + } + public void addButtonListener(ButtonListener b) { + buttonListeners.addElement(b); + } + + public void removeButtonListener(ButtonListener b) { + buttonListeners.removeElement(b); + } + + public void addJoystickListener(Attack3JoystickListener l) { + joystickListeners.addElement(l); + } + + public void removeJoystickListener(Attack3JoystickListener l) { + joystickListeners.removeElement(l); + } + +} diff --git a/src/sensor/GRTBatterySensor.java b/src/sensor/GRTBatterySensor.java new file mode 100644 index 0000000..ed7d327 --- /dev/null +++ b/src/sensor/GRTBatterySensor.java @@ -0,0 +1,50 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package sensor; + +import core.PollingSensor; +import edu.wpi.first.wpilibj.DriverStation; +import event.BatteryVoltageEvent; +import event.BatteryVoltageListener; +import java.util.Vector; + +/** + * A battery sensor that retrieves main battery voltage from the analog sidecar + * @author ajc + */ +public class GRTBatterySensor extends PollingSensor { + + public static final int KEY_BATTERY_VOLTAGE = 0; + + private final DriverStation ds; + private final Vector listeners; + + public GRTBatterySensor(int pollTime, String name) { + super(name, pollTime, 1); + ds = DriverStation.getInstance(); + listeners = new Vector(); + } + + protected void poll() { + setState(KEY_BATTERY_VOLTAGE, ds.getBatteryVoltage()); + } + + protected void notifyListeners(int id, double oldDatum, double newDatum) { + + BatteryVoltageEvent e = new BatteryVoltageEvent(this, newDatum); + + for (int i = 0; i < listeners.size(); i++) { + ((BatteryVoltageListener) listeners.elementAt(i)).batteryVoltageChanged(e); + } + } + + public void addBatteryVoltageListener(BatteryVoltageListener l) { + listeners.addElement(l); + } + + public void removeBatteryVoltageListener(BatteryVoltageListener l) { + listeners.removeElement(l); + } +} diff --git a/src/sensor/GRTEncoder.java b/src/sensor/GRTEncoder.java new file mode 100644 index 0000000..468d569 --- /dev/null +++ b/src/sensor/GRTEncoder.java @@ -0,0 +1,45 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package sensor; + +import core.PollingSensor; +import edu.wpi.first.wpilibj.Encoder; +import edu.wpi.first.wpilibj.PIDSource; +/** + * + * @author gerberduffy + */ +public class GRTEncoder extends PollingSensor { + + private Encoder rotaryEncoder; + private double distancePerPulse; + + public static final int DISTANCE = 0; + public static final int DEGREES = 1; + public static final int DIRECTION = 2; + + public static final int NUM_DATA = 3; + + public GRTEncoder(int channelA, int channelB, double pulseDistance, int pollTime, String id){ + super(id, pollTime, NUM_DATA); + rotaryEncoder = new Encoder(channelA, channelB); + rotaryEncoder.start(); + + distancePerPulse = pulseDistance; + } + + + protected void poll() { + setState(DISTANCE, rotaryEncoder.getDistance()); + setState(DEGREES, rotaryEncoder.getDistance()/distancePerPulse); + setState(DIRECTION, rotaryEncoder.getDirection() ? TRUE : FALSE); + + System.out.println(getState(DISTANCE) + "\t" + getState(DEGREES) + "\t" + getState(DIRECTION)); + } + + protected void notifyListeners(int id, double oldDatum, double newDatum) { + } + +} diff --git a/src/sensor/GRTGyro.java b/src/sensor/GRTGyro.java new file mode 100644 index 0000000..d4661f2 --- /dev/null +++ b/src/sensor/GRTGyro.java @@ -0,0 +1,57 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package sensor; + +import core.PollingSensor; +import edu.wpi.first.wpilibj.AnalogModule; +import edu.wpi.first.wpilibj.Gyro; +import java.util.Vector; +import event.GyroEvent; +import event.GyroListener; + +/** + * Provides angular position along a single axis through an analog sensor + * @author calvin + */ +public class GRTGyro extends PollingSensor { + + public static final int KEY_ANGLE = 0; + public static final int NUM_DATA = 1; + private Gyro gyro; + private Vector gyroListeners; + + public GRTGyro(int channel, int pollTime, String name) { + super(name, pollTime, NUM_DATA); + gyro = new Gyro(AnalogModule.getDefaultAnalogModule(), channel); + gyroListeners = new Vector(); + } + + public double getAngle(){ + return gyro.getAngle(); + } + + protected void poll() { + setState(KEY_ANGLE, gyro.getAngle()); + + System.out.println("Gyro: \t" + getState(KEY_ANGLE)); + } + + protected void notifyListeners(int id, double oldDatum, double newDatum) { + if (id == KEY_ANGLE) { + GyroEvent e = new GyroEvent(this, newDatum); + for (int i = 0; i < gyroListeners.size(); i++) { + ((GyroListener) gyroListeners.elementAt(i)).angleChanged(e); + } + } + } + + public void addListener(GyroListener l) { + gyroListeners.addElement(l); + } + + public void removeListener(GyroListener l) { + gyroListeners.removeElement(l); + } +} diff --git a/src/sensor/GRTSwitch.java b/src/sensor/GRTSwitch.java new file mode 100644 index 0000000..6d9b9f0 --- /dev/null +++ b/src/sensor/GRTSwitch.java @@ -0,0 +1,54 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package sensor; + +import core.PollingSensor; +import edu.wpi.first.wpilibj.DigitalInput; +import event.SwitchEvent; +import event.SwitchListener; +import java.util.Vector; + +/** + * + * @author gerberduffy + */ +public class GRTSwitch extends PollingSensor { + + private DigitalInput in; + + private static final int STATE = 0; + private static final int NUM_DATA = 1; + + private Vector listeners; + + public GRTSwitch(int slot, int polltime, String id){ + + super(id, polltime, NUM_DATA); + + in = new DigitalInput(slot); + + listeners = new Vector(); + } + + public boolean isOn(){ + return in.get(); + } + + protected void poll() { + setState(STATE, isOn() ? TRUE : FALSE); + System.out.println(getState(STATE)); + } + + protected void notifyListeners(int id, double oldDatum, double newDatum) { + + SwitchEvent e = new SwitchEvent(this, newDatum); + + for (int i=0; i < listeners.size(); i++){ + ((SwitchListener)listeners.elementAt(i)).switchStateChanged(e); + } + } + + +} diff --git a/src/sensor/GRTXBoxJoystick.java b/src/sensor/GRTXBoxJoystick.java new file mode 100644 index 0000000..907b291 --- /dev/null +++ b/src/sensor/GRTXBoxJoystick.java @@ -0,0 +1,161 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package sensor; + +import core.PollingSensor; +import edu.wpi.first.wpilibj.Joystick; +import event.ButtonEvent; +import event.ButtonListener; +import event.XboxJoystickEvent; +import event.XboxJoystickListener; +import java.util.Vector; + +/** + * + * @author ajc + */ +public class GRTXBoxJoystick extends PollingSensor { + + /** + * Keys of data + */ + public static final int KEY_BUTTON_0 = 0; + public static final int KEY_BUTTON_1 = 1; + public static final int KEY_BUTTON_2 = 2; + public static final int KEY_BUTTON_3 = 3; + public static final int KEY_BUTTON_4 = 4; + public static final int KEY_BUTTON_5 = 5; + public static final int KEY_BUTTON_6 = 6; + public static final int KEY_BUTTON_7 = 7; + public static final int KEY_BUTTON_8 = 8; + public static final int KEY_BUTTON_9 = 9; + public static final int KEY_LEFT_X = 10; + public static final int KEY_LEFT_Y = 11; + public static final int KEY_RIGHT_X = 12; + public static final int KEY_RIGHT_Y = 13; + public static final int KEY_JOYSTICK_ANGLE = 14; + public static final int KEY_TRIGGER = 15; + public static final int KEY_PAD = 16; + + private static final int NUM_DATA = 17; + private static final int NUM_OF_BUTTONS = 10; + + /** + * State definitions + */ + public static final double PRESSED = TRUE; + public static final double RELEASED = FALSE; + + private final Joystick joystick; + private final Vector buttonListeners; + private final Vector joystickListeners; + + public GRTXBoxJoystick(int channel, int pollTime, String name) { + super(name, pollTime, NUM_DATA); + joystick = new Joystick(channel); + + buttonListeners = new Vector(); + joystickListeners = new Vector(); + } + + protected void poll() { + for (int i = 0; i < NUM_OF_BUTTONS; i++) { + //if we measure true, this indicates pressed state + setState(i, joystick.getRawButton(i) ? PRESSED : RELEASED); + } + setState(KEY_LEFT_X, joystick.getX()); + setState(KEY_LEFT_Y, joystick.getY()); + setState(KEY_RIGHT_X, joystick.getRawAxis(4)); + setState(KEY_RIGHT_Y, joystick.getRawAxis(5)); + setState(KEY_JOYSTICK_ANGLE, joystick.getDirectionRadians()); + setState(KEY_TRIGGER, joystick.getZ()); + setState(KEY_PAD, joystick.getRawAxis(6)); + } + + protected void notifyListeners(int id, double oldDatum, double newDatum) { + if (id < NUM_OF_BUTTONS) { + //ID maps directly to button ID + ButtonEvent e = new ButtonEvent(this, id, newDatum == PRESSED); + if (newDatum == PRESSED) { //true + for (int i = 0; i < buttonListeners.size(); i++) { + ((ButtonListener) buttonListeners.elementAt(i)).buttonPressed(e); + } + } else { + for (int i = 0; i < buttonListeners.size(); i++) { + ((ButtonListener) buttonListeners.elementAt(i)).buttonReleased(e); + } + } + + } else { //we are now a joystick + //only reach here if not a button + XboxJoystickEvent e = new XboxJoystickEvent(this, id, newDatum); + + //call various events based on which datum we are + switch (id) { + case KEY_LEFT_X: { + for (int i = 0; i < joystickListeners.size(); i++) { + ((XboxJoystickListener) joystickListeners.elementAt(i)).leftXAxisMoved(e); + } + + } + case KEY_LEFT_Y: { + for (int i = 0; i < joystickListeners.size(); i++) { + ((XboxJoystickListener) joystickListeners.elementAt(i)).leftYAxisMoved(e); + } + break; + } + case KEY_RIGHT_X: { + for (int i = 0; i < joystickListeners.size(); i++) { + ((XboxJoystickListener) joystickListeners.elementAt(i)).rightXAxisMoved(e); + } + break; + } + case KEY_RIGHT_Y: { + for (int i = 0; i < joystickListeners.size(); i++) { + ((XboxJoystickListener) joystickListeners.elementAt(i)).rightYAxisMoved(e); + } + break; + } + case KEY_JOYSTICK_ANGLE: { + for (int i = 0; i < joystickListeners.size(); i++) { + ((XboxJoystickListener) joystickListeners.elementAt(i)).leftAngleChanged(e); + } + break; + } + case KEY_TRIGGER: { + for (int i = 0; i < joystickListeners.size(); i++) { + ((XboxJoystickListener) joystickListeners.elementAt(i)).triggerMoved(e); + } + break; + } + case KEY_PAD: { + for (int i = 0; i < joystickListeners.size(); i++) { + ((XboxJoystickListener) joystickListeners.elementAt(i)).padMoved(e); + } + break; + } + + } + } + + + } + + public void addButtonListener(ButtonListener b) { + buttonListeners.addElement(b); + } + + public void removeButtonListener(ButtonListener b) { + buttonListeners.removeElement(b); + } + + public void addJoystickListener(XboxJoystickListener l) { + joystickListeners.addElement(l); + } + + public void removeJoystickListener(XboxJoystickListener l) { + joystickListeners.removeElement(l); + } +} diff --git a/src/sensor/Potentiometer.java b/src/sensor/Potentiometer.java new file mode 100644 index 0000000..08dc037 --- /dev/null +++ b/src/sensor/Potentiometer.java @@ -0,0 +1,53 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package sensor; + +import edu.wpi.first.wpilibj.AnalogChannel; +import core.PollingSensor; +import event.PotentiometerEvent; +import event.PotentiometerListener; +import java.util.Vector; + +/** + * + * @author calvin + */ +public class Potentiometer extends PollingSensor{ + public static final int KEY_VALUE = 0; + public static final int NUM_DATA = 1; + + private int potentiometerType; + private AnalogChannel channel; + public static final int LINEAR = 0; + public static final int LOGARITHMIC = 1; + + public Potentiometer(AnalogChannel channel, int type, int pollTime, String name){ + super(name, pollTime, NUM_DATA); + potentiometerType = type; + this.channel = channel; + } + + protected void poll() { + setState(KEY_VALUE, updateScaledValue()); + } + + private double updateScaledValue(){ + double rawValue = channel.getVoltage(); + double scaledValue; + switch(potentiometerType){ + case LINEAR: + scaledValue = rawValue / 5; + break; + default: + scaledValue = rawValue / 5; + System.out.println("log is broken as of right now"); + } + + return scaledValue; + } + + protected void notifyListeners(int id, double oldDatum, double newDatum) { + } +} diff --git a/src/sensor/base/GRTAttack3DriverStation.java b/src/sensor/base/GRTAttack3DriverStation.java new file mode 100644 index 0000000..a1f0ad0 --- /dev/null +++ b/src/sensor/base/GRTAttack3DriverStation.java @@ -0,0 +1,78 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package sensor.base; + +import event.Attack3JoystickEvent; +import event.Attack3JoystickListener; +import event.ButtonEvent; +import event.ButtonListener; +import sensor.GRTAttack3Joystick; + +/** + * Driver station using 2 Logitech Attack 3 Joysticks + * @author dan + */ +public class GRTAttack3DriverStation extends GRTDriverStation implements Attack3JoystickListener, ButtonListener{ + private final GRTAttack3Joystick left; + private final GRTAttack3Joystick right; + + public GRTAttack3DriverStation(GRTAttack3Joystick left, GRTAttack3Joystick right, + int[] profileButtons, IDriverProfile[] curves, String name){ + super(profileButtons, curves, name); + this.left= left; + this.right = right; + } + + protected void startListening() { + left.addJoystickListener(this); + left.addButtonListener(this); + right.addJoystickListener(this); + right.addButtonListener(this); + } + + protected void stopListening() { + left.removeJoystickListener(this); + left.removeButtonListener(this); + right.removeJoystickListener(this); + right.removeButtonListener(this); + } + + public void XAxisMoved(Attack3JoystickEvent e) { + } + + public void YAxisMoved(Attack3JoystickEvent e) { + if (e.getSource()==left){ + notifyLeftDriveSpeed(e.getValue()); + notifyStateChange(KEY_LEFT_VELOCITY, e.getValue()); + } + else if (e.getSource() ==right){ + notifyRightDriveSpeed(e.getValue()); + notifyStateChange(KEY_RIGHT_VELOCITY, e.getValue()); + } + } + + public void AngleChanged(Attack3JoystickEvent e) { + } + + public void buttonPressed(ButtonEvent e) { + } + + public void buttonReleased(ButtonEvent e) { + int profileID = getIndex(profileButtons, e.getButtonID()); + if (profileID != -1) {//meaning it exists, see #getIndex(int[], int) + notifyProfileChange(profileID); + notifyStateChange(KEY_PROFILE_ID, profileID); + } + } + private static int getIndex(int[] array, int value) { + for (int i = 0; i < array.length; i++) { + if (value == array[i]) { + return i; + } + } + return -1; + } + +} diff --git a/src/sensor/base/GRTDriverStation.java b/src/sensor/base/GRTDriverStation.java new file mode 100644 index 0000000..c76f89c --- /dev/null +++ b/src/sensor/base/GRTDriverStation.java @@ -0,0 +1,93 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package sensor.base; + +import core.Sensor; +import event.DrivingEvent; +import event.DrivingListener; +import event.DrivingProfileEvent; +import event.DrivingProfileListener; +import java.util.Vector; + +/** + * Superclass for all DriverStations. + * + * Handles driver profiles.s + * @author ajc + */ +public abstract class GRTDriverStation extends Sensor { + + /* + * State Keys + */ + public static final int KEY_LEFT_VELOCITY = 0; + public static final int KEY_RIGHT_VELOCITY = 1; + public static final int KEY_PROFILE_ID = 2; + + //profiles + protected IDriverProfile[] curves; + /* + * maps the profile index to the button that should register it + * so {3 4} means button 3 will register PROFILE_LINEAR, + * while button 4 will register PROFILE_SQUARED. + */ + protected final int[] profileButtons; + //listeners + private final Vector drivingListeners; + private final Vector profileListeners; + + /** + * + * @param profileButtons + * @param curves + * @param name + */ + public GRTDriverStation(int[] profileButtons, IDriverProfile[] curves, String name) { + super(name); + this.profileButtons = profileButtons; + this.curves = curves; + + drivingListeners = new Vector(); + profileListeners = new Vector(); + } + + public void addDrivingListener(DrivingListener l) { + drivingListeners.addElement(l); + } + + public void removeDrivingListener(DrivingListener l) { + drivingListeners.removeElement(l); + } + + public void addDrivingProfileListener(DrivingProfileListener l) { + profileListeners.addElement(l); + } + + public void removeDrivingProfileListener(DrivingProfileListener l) { + profileListeners.removeElement(l); + } + + protected void notifyLeftDriveSpeed(double speed) { + DrivingEvent ev = new DrivingEvent(this, DrivingEvent.SIDE_LEFT, speed); + for (int i = 0; i < drivingListeners.size(); i++) { + ((DrivingListener) drivingListeners.elementAt(i)).driverLeftSpeed(ev); + } + } + + protected void notifyRightDriveSpeed(double speed) { + DrivingEvent ev = new DrivingEvent(this, DrivingEvent.SIDE_RIGHT, speed); + for (int i = 0; i < drivingListeners.size(); i++) { + ((DrivingListener) drivingListeners.elementAt(i)).driverRightSpeed(ev); + } + } + + protected void notifyProfileChange(int profileID) { + DrivingProfileEvent e = new DrivingProfileEvent(this, curves[profileID]); + for (int i = 0; i < profileListeners.size(); i++) { + ((DrivingProfileListener) profileListeners.elementAt(i)).drivingProfileChanged(e); + + } + } +} diff --git a/src/sensor/base/GRTXboxDriverStation.java b/src/sensor/base/GRTXboxDriverStation.java new file mode 100644 index 0000000..d5b3ed8 --- /dev/null +++ b/src/sensor/base/GRTXboxDriverStation.java @@ -0,0 +1,113 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package sensor.base; + +import event.ButtonEvent; +import event.ButtonListener; +import event.XboxJoystickEvent; +import event.XboxJoystickListener; +import sensor.GRTXBoxJoystick; + +/** + * Driverstation using XBoxJoysticks + * + * @author ajc + */ +public class GRTXboxDriverStation extends GRTDriverStation implements XboxJoystickListener, ButtonListener { + + private final GRTXBoxJoystick primary; + private final GRTXBoxJoystick secondary; + + /** + * + * @param primary + * @param secondary + * @param profileButtons + * @param curves + * @param name + */ + public GRTXboxDriverStation(GRTXBoxJoystick primary, GRTXBoxJoystick secondary, + int[] profileButtons, IDriverProfile[] curves, String name) { + super(profileButtons, curves, name); + this.primary = primary; + this.secondary = secondary; + + } + + protected void startListening() { + primary.addJoystickListener(this); + primary.addButtonListener(this); + } + + protected void stopListening() { + primary.removeJoystickListener(this); + primary.removeButtonListener(this); + } + + /* + * JOYSTICK EVENTS + */ + public void leftXAxisMoved(XboxJoystickEvent e) { + } + + public void leftYAxisMoved(XboxJoystickEvent e) { + if (e.getSource() == primary) { + notifyLeftDriveSpeed(e.getValue()); + notifyStateChange(KEY_LEFT_VELOCITY, e.getValue()); + } + } + + public void rightXAxisMoved(XboxJoystickEvent e) { + } + + public void rightYAxisMoved(XboxJoystickEvent e) { + if (e.getSource() == primary) { + notifyRightDriveSpeed(e.getValue()); + notifyStateChange(KEY_RIGHT_VELOCITY, e.getValue()); + } + } + + public void padMoved(XboxJoystickEvent e) { + } + + public void triggerMoved(XboxJoystickEvent e) { + } + + /* + * BUTTON EVENTS + */ + public void buttonPressed(ButtonEvent e) { + } + + public void buttonReleased(ButtonEvent e) { + + //we receive the button. + //the button corresponds to an element in the profileButtons list + //we need to find the index from that array that the button ID is + int profileID = getIndex(profileButtons, e.getButtonID()); + if (profileID != -1) {//meaning it exists, see #getIndex(int[], int) + notifyProfileChange(profileID); + notifyStateChange(KEY_PROFILE_ID, profileID); + } + } + + /** + * + * @param array + * @param value + * @return + */ + private static int getIndex(int[] array, int value) { + for (int i = 0; i < array.length; i++) { + if (value == array[i]) { + return i; + } + } + return -1; + } + + public void leftAngleChanged(XboxJoystickEvent e) { + } +} diff --git a/src/sensor/base/IDriverProfile.java b/src/sensor/base/IDriverProfile.java new file mode 100644 index 0000000..173509f --- /dev/null +++ b/src/sensor/base/IDriverProfile.java @@ -0,0 +1,19 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package sensor.base; + +/** + * + * @author ajc + */ +public interface IDriverProfile { + + /** + * + * @param joystickTiltPercent an input percent from [-1.0 - 1.0] + * @return an output from [-1.0 - 1.0] + */ + public double driveSpeed(double joystickTiltPercent); +} diff --git a/src/sensor/base/LinearDrive.java b/src/sensor/base/LinearDrive.java new file mode 100644 index 0000000..995cb24 --- /dev/null +++ b/src/sensor/base/LinearDrive.java @@ -0,0 +1,17 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package sensor.base; + +/** + * + * @author ajc + */ +public class LinearDrive implements IDriverProfile{ + + public double driveSpeed(double joystickTiltPercent) { + return joystickTiltPercent; + } + +} diff --git a/src/sensor/base/SquareDrive.java b/src/sensor/base/SquareDrive.java new file mode 100644 index 0000000..a33ae77 --- /dev/null +++ b/src/sensor/base/SquareDrive.java @@ -0,0 +1,19 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package sensor.base; + +/** + * + * @author ajc + */ +public class SquareDrive implements IDriverProfile { + + public double driveSpeed(double joystickTiltPercent) { + //save the sign: becomes -1 if original was negative, +1 if positive + double sign = joystickTiltPercent > 0 ? +1.0 : -1.0; + //apply sign to square to enable reverse driving + return sign * joystickTiltPercent * joystickTiltPercent; + } +} diff --git a/src/sensor/base/TestSwitch.java b/src/sensor/base/TestSwitch.java new file mode 100644 index 0000000..b3abe42 --- /dev/null +++ b/src/sensor/base/TestSwitch.java @@ -0,0 +1,22 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package sensor.base; + +import core.Sensor; + +/** + * + * @author gerberduffy + */ +public class TestSwitch { + + + protected void startListening() { + } + + protected void stopListening() { + } + +} diff --git a/src/sensor/base/VictorDriverProfile.java b/src/sensor/base/VictorDriverProfile.java new file mode 100644 index 0000000..2e9f355 --- /dev/null +++ b/src/sensor/base/VictorDriverProfile.java @@ -0,0 +1,25 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package sensor.base; + + +/** + * + * Driver profile that transaltes joystick values + * specifically calibrated for Victors + * + * @author gerberduffy + */ +public class VictorDriverProfile implements IDriverProfile { + + public double driveSpeed(double joystickTiltPercent) { + //TODO: IMPLEMENT THE HECK OUT OF THIS. + + return 0.0; + } + + + +} diff --git a/suite/Base2012-redesign_1.0.0.jar b/suite/Base2012-redesign_1.0.0.jar new file mode 100644 index 0000000000000000000000000000000000000000..5c5bbd9f58bd7a7d89e390fe0b8d4a4aa542e776 GIT binary patch literal 139398 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�C!^N*q`?zT4lQ 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

rjzvyl2Mj5Ka)d!$=G`vLhGJ*100?7%L@ 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