From 3fdbbb7832738a69016abc3e8aaf339a0a20e901 Mon Sep 17 00:00:00 2001 From: Nathaniel Palme Date: Tue, 3 Aug 2021 17:40:35 -0500 Subject: [PATCH] Some Small preparations for Java Class && the County Fair Demo stuff --- .idea/compiler.xml | 2 +- .idea/misc.xml | 2 +- .../cyberarm/engine/V2/CyberarmEngine.java | 2 +- .../Calibration/CalibrationEngine.java | 3 +- .../Competition/Autonomous/AutoEngine.java | 2 +- .../Autonomous/FindWobbleGoal.java | 12 +- .../Competition/Demo/DemoControl.java | 39 -- .../Competition/Demo/DemoEngine.java | 8 +- .../Competition/Demo/DemoEngineTank.java | 33 ++ .../Competition/Demo/DemoState.java | 194 +++++++ .../Competition/Demo/DemoStateTank.java | 55 ++ .../UltimateGoal/Competition/Launch.java | 14 +- .../UltimateGoal/Competition/Pause.java | 2 +- .../Competition/PreInit/PreInitEngine.java | 3 +- .../Competition/ProgressRingBelt.java | 14 +- .../UltimateGoal/Competition/Robot.java | 199 ++++--- .../Competition/TeleOp/LaunchControl.java | 1 - .../Competition/TeleOp/Player1.java | 74 ++- .../Competition/TeleOp/Player2.java | 39 +- .../Competition/TeleOp/TeleOpEngine.java | 3 +- .../Competition/TeleOp/powerShotsControl.java | 7 +- .../javaClass/aubrey/AubreyFirstState.java | 22 + .../javaClass/samples/AubreyFirstEngine.java | 26 + .../javaClass/samples/SampleRobot.java | 191 +++++++ .../javaClass/samples/SampleRobotEx.java | 515 ++++++++++++++++++ .../javaClass/samples/SpencerFirstEngine.java | 27 + .../javaClass/spencer/SpencerFirstState.java | 22 + build.gradle | 2 +- gradle/wrapper/gradle-wrapper.properties | 4 +- 29 files changed, 1346 insertions(+), 171 deletions(-) delete mode 100644 TeamCode/src/main/java/org/timecrafters/UltimateGoal/Competition/Demo/DemoControl.java create mode 100644 TeamCode/src/main/java/org/timecrafters/UltimateGoal/Competition/Demo/DemoEngineTank.java create mode 100644 TeamCode/src/main/java/org/timecrafters/UltimateGoal/Competition/Demo/DemoState.java create mode 100644 TeamCode/src/main/java/org/timecrafters/UltimateGoal/Competition/Demo/DemoStateTank.java create mode 100644 TeamCode/src/main/java/org/timecrafters/javaClass/aubrey/AubreyFirstState.java create mode 100644 TeamCode/src/main/java/org/timecrafters/javaClass/samples/AubreyFirstEngine.java create mode 100644 TeamCode/src/main/java/org/timecrafters/javaClass/samples/SampleRobot.java create mode 100644 TeamCode/src/main/java/org/timecrafters/javaClass/samples/SampleRobotEx.java create mode 100644 TeamCode/src/main/java/org/timecrafters/javaClass/samples/SpencerFirstEngine.java create mode 100644 TeamCode/src/main/java/org/timecrafters/javaClass/spencer/SpencerFirstState.java diff --git a/.idea/compiler.xml b/.idea/compiler.xml index fb7f4a8..61a9130 100644 --- a/.idea/compiler.xml +++ b/.idea/compiler.xml @@ -1,6 +1,6 @@ - + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index 860da66..d5d35ec 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,6 +1,6 @@ - + diff --git a/TeamCode/src/main/java/org/cyberarm/engine/V2/CyberarmEngine.java b/TeamCode/src/main/java/org/cyberarm/engine/V2/CyberarmEngine.java index 4a03a27..1ac173a 100644 --- a/TeamCode/src/main/java/org/cyberarm/engine/V2/CyberarmEngine.java +++ b/TeamCode/src/main/java/org/cyberarm/engine/V2/CyberarmEngine.java @@ -150,7 +150,7 @@ public abstract class CyberarmEngine extends OpMode { * Recursively stop states * @param state State to stop */ - private void stopState(CyberarmState state) { + public void stopState(CyberarmState state) { state.setHasFinished(true); state.stop(); diff --git a/TeamCode/src/main/java/org/timecrafters/UltimateGoal/Calibration/CalibrationEngine.java b/TeamCode/src/main/java/org/timecrafters/UltimateGoal/Calibration/CalibrationEngine.java index d24cf37..7f1ed4d 100644 --- a/TeamCode/src/main/java/org/timecrafters/UltimateGoal/Calibration/CalibrationEngine.java +++ b/TeamCode/src/main/java/org/timecrafters/UltimateGoal/Calibration/CalibrationEngine.java @@ -1,10 +1,11 @@ package org.timecrafters.UltimateGoal.Calibration; +import com.qualcomm.robotcore.eventloop.opmode.Disabled; import com.qualcomm.robotcore.eventloop.opmode.TeleOp; import org.cyberarm.engine.V2.CyberarmEngine; import org.timecrafters.UltimateGoal.Competition.Robot; - +@Disabled @TeleOp (name = "Calibration", group = "test") public class CalibrationEngine extends CyberarmEngine { private Robot robot; diff --git a/TeamCode/src/main/java/org/timecrafters/UltimateGoal/Competition/Autonomous/AutoEngine.java b/TeamCode/src/main/java/org/timecrafters/UltimateGoal/Competition/Autonomous/AutoEngine.java index 0a26eb4..d1e542f 100644 --- a/TeamCode/src/main/java/org/timecrafters/UltimateGoal/Competition/Autonomous/AutoEngine.java +++ b/TeamCode/src/main/java/org/timecrafters/UltimateGoal/Competition/Autonomous/AutoEngine.java @@ -35,7 +35,7 @@ public class AutoEngine extends CyberarmEngine { // since we've preloaded three rings, the ring belt stage is set to account for this; robot.ringBeltStage = 3; - //Autonomous specific Variables + //Autonomous specific Configuration Variables float rotation = robot.stateConfiguration.variable("system", "startPos", "direction").value(); double locationX = robot.inchesToTicks((double) robot.stateConfiguration.variable("system", "startPos", "x").value()); double locationY = robot.inchesToTicks((double) robot.stateConfiguration.variable("system", "startPos", "y").value()); diff --git a/TeamCode/src/main/java/org/timecrafters/UltimateGoal/Competition/Autonomous/FindWobbleGoal.java b/TeamCode/src/main/java/org/timecrafters/UltimateGoal/Competition/Autonomous/FindWobbleGoal.java index c5bd4f6..5cc594a 100644 --- a/TeamCode/src/main/java/org/timecrafters/UltimateGoal/Competition/Autonomous/FindWobbleGoal.java +++ b/TeamCode/src/main/java/org/timecrafters/UltimateGoal/Competition/Autonomous/FindWobbleGoal.java @@ -1,5 +1,9 @@ package org.timecrafters.UltimateGoal.Competition.Autonomous; +/* +The FindWobbleGoal state is used in teleOp and Autonomous to aid in capturing the wobble goal. +*/ + import org.cyberarm.engine.V2.CyberarmState; import org.firstinspires.ftc.robotcore.external.navigation.DistanceUnit; import org.timecrafters.UltimateGoal.Competition.Robot; @@ -47,6 +51,7 @@ public class FindWobbleGoal extends CyberarmState { robot.updateLocation(); double sensorValue = robot.wobbleColorSensor.getDistance(DistanceUnit.MM); + //Stage 1: scan back and forth untile the sensor is in line with the wobble goal. if (sensorValue > turnCheck) { float rotation = robot.getRelativeAngle(startRotation,robot.getRotation()); @@ -65,18 +70,23 @@ public class FindWobbleGoal extends CyberarmState { ccCheckPrev = ccCheck; } else { + //Stage 2: drive toward wobble goal until it's close enough to grab if (sensorValue > driveCheck) { if (!foundGoalRotation) { foundGoalRotation = true; wobbleGoalRotation = robot.getRotation(); } - double[] powers = robot.getMecanumPowers(wobbleGoalRotation - 90, power*2 , wobbleGoalRotation); + double[] powers = robot.getMecanumPowers( + wobbleGoalRotation - 90, + power*2 , wobbleGoalRotation); robot.setDrivePower(powers[0],powers[1],powers[2],powers[3]); } else { + //stage 3: grab the wobble goal && finish the state endSearch(); } } + //if the search takes too long, the robot grabs and finishes the state if (runTime() > timeLimit) { endSearch(); } diff --git a/TeamCode/src/main/java/org/timecrafters/UltimateGoal/Competition/Demo/DemoControl.java b/TeamCode/src/main/java/org/timecrafters/UltimateGoal/Competition/Demo/DemoControl.java deleted file mode 100644 index 82a1ed6..0000000 --- a/TeamCode/src/main/java/org/timecrafters/UltimateGoal/Competition/Demo/DemoControl.java +++ /dev/null @@ -1,39 +0,0 @@ -package org.timecrafters.UltimateGoal.Competition.Demo; - -import org.cyberarm.engine.V2.CyberarmState; -import org.timecrafters.UltimateGoal.Competition.Robot; -import org.timecrafters.UltimateGoal.Competition.TeleOp.Player1; -import org.timecrafters.UltimateGoal.Competition.TeleOp.Player2; - -public class DemoControl extends CyberarmState { - - private Robot robot; - - public DemoControl(Robot robot) { - this.robot = robot; - } - - @Override - public void start() { -// addParallelState(new Demo1(robot)); -// addParallelState(new Demo2(robot)); - } - - @Override - public void exec() { - - } - - @Override - public void telemetry() { - - engine.telemetry.addLine("Location"); - engine.telemetry.addData("Position ","("+round(robot.ticksToInches(robot.getLocationX()),0.1)+","+round(robot.ticksToInches(robot.getLocationY()),0.1)+")"); - engine.telemetry.addData("Rotation ", robot.getRotation()); - } - - private float round(double number,double unit) { - return (float) (Math.floor(number/unit) * unit); - } - -} diff --git a/TeamCode/src/main/java/org/timecrafters/UltimateGoal/Competition/Demo/DemoEngine.java b/TeamCode/src/main/java/org/timecrafters/UltimateGoal/Competition/Demo/DemoEngine.java index 3145699..c7c2b3b 100644 --- a/TeamCode/src/main/java/org/timecrafters/UltimateGoal/Competition/Demo/DemoEngine.java +++ b/TeamCode/src/main/java/org/timecrafters/UltimateGoal/Competition/Demo/DemoEngine.java @@ -1,14 +1,12 @@ package org.timecrafters.UltimateGoal.Competition.Demo; -import com.qualcomm.robotcore.eventloop.opmode.Disabled; import com.qualcomm.robotcore.eventloop.opmode.TeleOp; import org.cyberarm.engine.V2.CyberarmEngine; import org.timecrafters.UltimateGoal.Competition.Robot; import org.timecrafters.UltimateGoal.Competition.TeleOp.TeleOpState; -@Disabled -@TeleOp (name = "Demo") +@TeleOp (name = "Demo: Game",group = "demo") public class DemoEngine extends CyberarmEngine { private Robot robot; @@ -17,14 +15,14 @@ public class DemoEngine extends CyberarmEngine { public void init() { robot = new Robot(hardwareMap); robot.initHardware(); - robot.wobbleGrabServo.setPosition(0); + robot.wobbleGrabServo.setPosition(Robot.WOBBLE_SERVO_CLOSED); robot.webCamServo.setPosition(0); super.init(); } @Override public void setup() { - addState(new DemoControl(robot)); + addState(new DemoState(robot)); } @Override diff --git a/TeamCode/src/main/java/org/timecrafters/UltimateGoal/Competition/Demo/DemoEngineTank.java b/TeamCode/src/main/java/org/timecrafters/UltimateGoal/Competition/Demo/DemoEngineTank.java new file mode 100644 index 0000000..3652ed3 --- /dev/null +++ b/TeamCode/src/main/java/org/timecrafters/UltimateGoal/Competition/Demo/DemoEngineTank.java @@ -0,0 +1,33 @@ +package org.timecrafters.UltimateGoal.Competition.Demo; + +import com.qualcomm.robotcore.eventloop.opmode.TeleOp; + +import org.cyberarm.engine.V2.CyberarmEngine; +import org.timecrafters.UltimateGoal.Competition.Robot; + +@TeleOp (name = "Demo: Tank",group = "demo") +public class DemoEngineTank extends CyberarmEngine { + + private Robot robot; + + @Override + public void init() { + robot = new Robot(hardwareMap); + robot.initHardware(); + robot.wobbleGrabServo.setPosition(Robot.WOBBLE_SERVO_CLOSED); + robot.webCamServo.setPosition(0); + super.init(); + } + + @Override + public void setup() { + addState(new DemoStateTank(robot)); + } + + @Override + public void stop() { + robot.deactivateVuforia(); + robot.saveRecording(); + super.stop(); + } +} diff --git a/TeamCode/src/main/java/org/timecrafters/UltimateGoal/Competition/Demo/DemoState.java b/TeamCode/src/main/java/org/timecrafters/UltimateGoal/Competition/Demo/DemoState.java new file mode 100644 index 0000000..e3007c1 --- /dev/null +++ b/TeamCode/src/main/java/org/timecrafters/UltimateGoal/Competition/Demo/DemoState.java @@ -0,0 +1,194 @@ +package org.timecrafters.UltimateGoal.Competition.Demo; + +/* +The Player1 state has all the controls for player one. The Player One and Player Two controls are +kept in separate states so that the childrenHaveFinished() method can be used to easily stop things +from running at the same time that shouldn't be. +*/ + +import com.qualcomm.hardware.rev.RevBlinkinLedDriver; +import com.qualcomm.robotcore.hardware.DcMotor; +import com.qualcomm.robotcore.hardware.Gamepad; + +import org.cyberarm.engine.V2.CyberarmState; +import org.timecrafters.UltimateGoal.Competition.Autonomous.FindWobbleGoal; +import org.timecrafters.UltimateGoal.Competition.Robot; +import org.timecrafters.UltimateGoal.Competition.TeleOp.powerShotsControl; + +public class DemoState extends CyberarmState { + private Robot robot; + + //normal drive control + private float leftJoystickDegrees; + private double leftJoystickMagnitude; + private float rightJoystickDegrees; + private double rightJoystickMagnitude; + private double rightJoystickMagnitudePrevious; + + private double faceControlThreshold; + private float cardinalSnapping; + private float pairSnapping; + + private float faceDirection = 0; + private double[] powers = {0,0,0,0}; + private double drivePower = 1; + private boolean lbPrev; + + private double refinePower; + + public DemoState(Robot robot) { + this.robot = robot; + } + + @Override + public void init() { + cardinalSnapping = robot.stateConfiguration.variable( + "tele","control", "cardinalSnapping").value(); + pairSnapping = robot.stateConfiguration.variable( + "tele","control", "pairSnapping").value(); + faceControlThreshold = robot.stateConfiguration.variable( + "tele","control", "faceControlT").value(); + refinePower = robot.stateConfiguration.variable( + "tele","control", "refPower").value(); + + } + + @Override + public void start() { + faceDirection = robot.getRotation(); + } + + @Override + public void exec() { + robot.updateLocation(); + + Gamepad gamepad = engine.gamepad1; + if (engine.gamepad2.right_trigger != 0) { + gamepad = engine.gamepad2; + } + + //toggle for drive speed + boolean lb = engine.gamepad2.left_stick_button; + if (lb && !lbPrev) { + if (drivePower == 1) { + drivePower = 0.5; + } else { + drivePower = 1; + } + } + lbPrev = lb; + + //Calculate Joystick Vector + double leftJoystickX = gamepad.left_stick_x; + double leftJoystickY = gamepad.left_stick_y; + + leftJoystickDegrees = robot.getRelativeAngle(0, + (float) Math.toDegrees(Math.atan2(leftJoystickX, -leftJoystickY))); + leftJoystickMagnitude = Math.hypot(leftJoystickX, leftJoystickY); + + double rightJoystickX = gamepad.right_stick_x; + double rightJoystickY = gamepad.right_stick_y; + + rightJoystickDegrees = robot.getRelativeAngle(0, + (float) Math.toDegrees(Math.atan2(rightJoystickX, -rightJoystickY))); + rightJoystickMagnitude = Math.hypot(rightJoystickX, rightJoystickY); + + //allows the the driver to indicate which direction the robot is currently looking + //so that the controller and robot can be re-synced in the event of a bad initial + //rotation. + if (gamepad.back) { + float newRotation = 0; + + if (rightJoystickMagnitude != 0) { + newRotation = rightJoystickDegrees; + } + + robot.setLocalization(newRotation, robot.getLocationX(), robot.getLocationY()); + faceDirection = newRotation; + } + + //if the driver is letting go of the face joystick, the robot should maintain it's + //current face direction. + if (rightJoystickMagnitude > faceControlThreshold || + rightJoystickMagnitude - rightJoystickMagnitudePrevious > 0) { + + //if the joystick is close to one of the cardinal directions, it is set to exactly + // the cardinal direction + faceDirection = snapToCardinal(rightJoystickDegrees, cardinalSnapping, 0); + } + rightJoystickMagnitudePrevious = rightJoystickMagnitude; + + //The D-pad is used if the drivers need to get a more precise angle than they can get + //using the face joystick + if (gamepad.dpad_right) { + powers = new double[]{refinePower, -refinePower, refinePower, -refinePower}; + faceDirection = robot.getRotation(); + } else if (gamepad.dpad_left) { + powers = new double[]{-refinePower, refinePower, -refinePower, refinePower}; + faceDirection = robot.getRotation(); + } else if (leftJoystickMagnitude == 0) { + double[] facePowers = robot.getFacePowers(faceDirection, 0.4); + powers = new double[]{facePowers[0], facePowers[1], facePowers[0], facePowers[1]}; + } else { + //drives the robot in the direction of the move joystick while facing the direction + //of the look joystick. if the move direction is almost aligned/perpendicular to the + //look joystick, + powers = robot.getMecanumPowers( + snapToCardinal(leftJoystickDegrees, pairSnapping, faceDirection), + drivePower, faceDirection); + } + + robot.setDrivePower(powers[0], powers[1], powers[2], powers[3]); + + + //LED feedback control + double ringBeltPower = robot.ringBeltMotor.getPower(); + if (ringBeltPower > 0 && Math.abs(robot.ringBeltMotor.getTargetPosition() - + robot.ringBeltMotor.getCurrentPosition()) > 10) { + robot.ledDriver.setPattern(RevBlinkinLedDriver.BlinkinPattern.HEARTBEAT_BLUE ); + } else if (ringBeltPower < 0) { + robot.ledDriver.setPattern(RevBlinkinLedDriver.BlinkinPattern.HEARTBEAT_RED); + } else { + if (drivePower == 1) { + robot.ledDriver.setPattern(RevBlinkinLedDriver.BlinkinPattern.DARK_GREEN); + } else { + robot.ledDriver.setPattern(RevBlinkinLedDriver.BlinkinPattern.GOLD); + } + } + } + + @Override + public void telemetry() { + engine.telemetry.addLine("Controler Directions"); + engine.telemetry.addData("Right", rightJoystickDegrees); + engine.telemetry.addData("Left", leftJoystickDegrees); + + engine.telemetry.addData("face", faceDirection); + + engine.telemetry.addData("Player 1 children", childrenHaveFinished()); + for (CyberarmState state : children) { + if (!state.getHasFinished()) { + engine.telemetry.addLine("" + state.getClass()); + } + } + } + + //This just checks if the wobble arm runmode is already the desired mode before setting it. + //I don't know if this is actually helpful + private void setArmMode(DcMotor.RunMode runMode) { + if (robot.wobbleArmMotor.getMode() != runMode) { + robot.wobbleArmMotor.setMode(runMode); + } + } + + private float snapToCardinal(float angle, float snapping, float offset) { + int o = (int) offset + 180; + o %= 90; + for (int cardinal = o-180; (cardinal <= 180+o && cardinal != angle); cardinal += 90) { + if (angle >= cardinal-snapping && angle <= cardinal+snapping) { + angle = cardinal; + } + } + return angle; + } +} diff --git a/TeamCode/src/main/java/org/timecrafters/UltimateGoal/Competition/Demo/DemoStateTank.java b/TeamCode/src/main/java/org/timecrafters/UltimateGoal/Competition/Demo/DemoStateTank.java new file mode 100644 index 0000000..ecd65e0 --- /dev/null +++ b/TeamCode/src/main/java/org/timecrafters/UltimateGoal/Competition/Demo/DemoStateTank.java @@ -0,0 +1,55 @@ +package org.timecrafters.UltimateGoal.Competition.Demo; + +/* +The Player1 state has all the controls for player one. The Player One and Player Two controls are +kept in separate states so that the childrenHaveFinished() method can be used to easily stop things +from running at the same time that shouldn't be. +*/ + +import com.qualcomm.hardware.rev.RevBlinkinLedDriver; +import com.qualcomm.robotcore.hardware.DcMotor; +import com.qualcomm.robotcore.hardware.Gamepad; + +import org.cyberarm.engine.V2.CyberarmState; +import org.timecrafters.UltimateGoal.Competition.Autonomous.FindWobbleGoal; +import org.timecrafters.UltimateGoal.Competition.Robot; +import org.timecrafters.UltimateGoal.Competition.TeleOp.powerShotsControl; + +public class DemoStateTank extends CyberarmState { + private Robot robot; + + private double drivePower = 1; + private boolean lbPrev; + + + public DemoStateTank(Robot robot) { + this.robot = robot; + } + + @Override + public void exec() { + robot.updateLocation(); + + Gamepad gamepad = engine.gamepad1; + if (engine.gamepad2.right_bumper) { + gamepad = engine.gamepad2; + } + + //toggle for drive speed + boolean lb = engine.gamepad2.left_stick_button; + if (lb && !lbPrev) { + if (drivePower == 1) { + drivePower = 0.5; + } else { + drivePower = 1; + } + } + lbPrev = lb; + + double left = -drivePower * gamepad.left_stick_y; + double right = -drivePower * gamepad.right_stick_y; + robot.setDrivePower(left,right,left,right); + + } + +} diff --git a/TeamCode/src/main/java/org/timecrafters/UltimateGoal/Competition/Launch.java b/TeamCode/src/main/java/org/timecrafters/UltimateGoal/Competition/Launch.java index 1d003c7..9b7d500 100644 --- a/TeamCode/src/main/java/org/timecrafters/UltimateGoal/Competition/Launch.java +++ b/TeamCode/src/main/java/org/timecrafters/UltimateGoal/Competition/Launch.java @@ -1,6 +1,10 @@ package org.timecrafters.UltimateGoal.Competition; -import com.qualcomm.hardware.rev.RevBlinkinLedDriver; +/* +The Launch state is used in teleOp and Autonomous. In addition to launching any rings by cycling the +ring belt, this state returns the ring belt to the starting position +*/ + import com.qualcomm.robotcore.hardware.DcMotor; import org.cyberarm.engine.V2.CyberarmState; @@ -45,10 +49,7 @@ public class Launch extends CyberarmState { @Override public void exec() { - //detect when limit switch is initially triggered - boolean detectingPass = robot.limitSwitch.isPressed(); - int beltPos = robot.ringBeltMotor.getCurrentPosition(); - + //jam counter measures if (robot.beltIsStuck() && childrenHaveFinished()) { long currentTime = System.currentTimeMillis(); if (stuckStartTime == 0) { @@ -60,6 +61,9 @@ public class Launch extends CyberarmState { stuckStartTime = 0; } + //detect when limit switch is initially triggered + boolean detectingPass = robot.limitSwitch.isPressed(); + int beltPos = robot.ringBeltMotor.getCurrentPosition(); if (detectingPass && !detectedPass) { //finish once the ring belt has cycled all the way through and then returned to //the first receiving position. diff --git a/TeamCode/src/main/java/org/timecrafters/UltimateGoal/Competition/Pause.java b/TeamCode/src/main/java/org/timecrafters/UltimateGoal/Competition/Pause.java index 102dcf0..5199b93 100644 --- a/TeamCode/src/main/java/org/timecrafters/UltimateGoal/Competition/Pause.java +++ b/TeamCode/src/main/java/org/timecrafters/UltimateGoal/Competition/Pause.java @@ -16,7 +16,7 @@ public class Pause extends CyberarmState { this.actionName = actionName; } - public Pause(Robot robot, boolean open, long waitTime) { + public Pause(Robot robot, long waitTime) { this.robot = robot; this.waitTime = waitTime; } diff --git a/TeamCode/src/main/java/org/timecrafters/UltimateGoal/Competition/PreInit/PreInitEngine.java b/TeamCode/src/main/java/org/timecrafters/UltimateGoal/Competition/PreInit/PreInitEngine.java index 8693100..64ba7e9 100644 --- a/TeamCode/src/main/java/org/timecrafters/UltimateGoal/Competition/PreInit/PreInitEngine.java +++ b/TeamCode/src/main/java/org/timecrafters/UltimateGoal/Competition/PreInit/PreInitEngine.java @@ -1,10 +1,11 @@ package org.timecrafters.UltimateGoal.Competition.PreInit; import com.qualcomm.robotcore.eventloop.opmode.Autonomous; +import com.qualcomm.robotcore.eventloop.opmode.Disabled; import org.cyberarm.engine.V2.CyberarmEngine; import org.timecrafters.UltimateGoal.Competition.Robot; - +@Disabled @Autonomous (name = "Load Rings") public class PreInitEngine extends CyberarmEngine { diff --git a/TeamCode/src/main/java/org/timecrafters/UltimateGoal/Competition/ProgressRingBelt.java b/TeamCode/src/main/java/org/timecrafters/UltimateGoal/Competition/ProgressRingBelt.java index 4df0635..283f72d 100644 --- a/TeamCode/src/main/java/org/timecrafters/UltimateGoal/Competition/ProgressRingBelt.java +++ b/TeamCode/src/main/java/org/timecrafters/UltimateGoal/Competition/ProgressRingBelt.java @@ -1,8 +1,11 @@ package org.timecrafters.UltimateGoal.Competition; +/* +The ProgressRingBelt state is used in teleOp to automatically move the ring belt. +*/ + import com.qualcomm.hardware.rev.RevBlinkinLedDriver; import com.qualcomm.robotcore.hardware.DcMotor; - import org.cyberarm.engine.V2.CyberarmState; public class ProgressRingBelt extends CyberarmState { @@ -27,13 +30,20 @@ public class ProgressRingBelt extends CyberarmState { @Override public void start() { int currentPos = robot.ringBeltMotor.getCurrentPosition(); + + //The first two progressions should move to preprare for another ring. if (robot.ringBeltStage < 2) { targetPos = currentPos + robot.ringBeltGap; prep(); + + //The third progression needs to only move forward enought to block the ring from + //falling out } else if (robot.ringBeltStage == 2) { targetPos = currentPos + 150; prep(); prepLaunch = !robot.initLauncher; + + //If the ring belt is already full, It does allow another progression } else if (robot.ringBeltStage > 2) { setHasFinished(true); } @@ -44,6 +54,7 @@ public class ProgressRingBelt extends CyberarmState { @Override public void exec() { + //finished state when the target position is reached int currentPos = robot.ringBeltMotor.getCurrentPosition(); if (currentPos >= targetPos) { if(prepLaunch) { @@ -53,6 +64,7 @@ public class ProgressRingBelt extends CyberarmState { setHasFinished(true); } + //belt jam mitigation if (robot.beltIsStuck() && childrenHaveFinished()) { long currentTime = System.currentTimeMillis(); if (stuckStartTime == 0) { diff --git a/TeamCode/src/main/java/org/timecrafters/UltimateGoal/Competition/Robot.java b/TeamCode/src/main/java/org/timecrafters/UltimateGoal/Competition/Robot.java index 89d619a..359665e 100644 --- a/TeamCode/src/main/java/org/timecrafters/UltimateGoal/Competition/Robot.java +++ b/TeamCode/src/main/java/org/timecrafters/UltimateGoal/Competition/Robot.java @@ -1,4 +1,4 @@ -package org.timecrafters.UltimateGoal.Competition; + package org.timecrafters.UltimateGoal.Competition; /* The robot object contains all the hardware and functions that are used in both teleOp and @@ -14,6 +14,7 @@ import com.qualcomm.hardware.rev.RevBlinkinLedDriver; import com.qualcomm.hardware.rev.RevColorSensorV3; import com.qualcomm.hardware.rev.RevTouchSensor; import com.qualcomm.robotcore.hardware.DcMotor; +import com.qualcomm.robotcore.hardware.DcMotorEx; import com.qualcomm.robotcore.hardware.DcMotorSimple; import com.qualcomm.robotcore.hardware.HardwareMap; import com.qualcomm.robotcore.hardware.Servo; @@ -53,7 +54,8 @@ public class Robot { } //The TimeCraftersConfiguration is part of a debugging and tuning tool that allows us to edit - //variables saved on the phone, without having to re-download the whole program. + //variables saved on the phone, without having to re-download the whole program. This is + //especially useful for autonomous route tuning public TimeCraftersConfiguration stateConfiguration = new TimeCraftersConfiguration(); //We use the IMU to get reliable rotation and angular velocity information. Experimentation has @@ -74,6 +76,12 @@ public class Robot { public DcMotor encoderBack; //Motion Constants + + //related graphs + //https://www.desmos.com/calculator/gndnkjndu9 + //https://www.desmos.com/calculator/w0rebnftvg + //https://www.desmos.com/calculator/qxa1rq8hrv + static final double CUBIC_CORRECTION = 0.035; static final double FACE_CUBIC_CORRECTION = 0.025; static final double LINEAR_CORRECTION = 0.055; @@ -81,10 +89,12 @@ public class Robot { static final double FACE_LINEAR_CORRECTION = 0.025; static final double MOMENTUM_CORRECTION = 1.05; static final double MOMENTUM_MAX_CORRECTION = 1.4; - static final double MOMENTUM_HORIZONTAL_CORRECTION = -(Math.log10(MOMENTUM_MAX_CORRECTION-1)/Math.log10(MOMENTUM_CORRECTION)); + static final double MOMENTUM_HORIZONTAL_CORRECTION = + -(Math.log10(MOMENTUM_MAX_CORRECTION-1) / Math.log10(MOMENTUM_CORRECTION)); static final double FACE_MOMENTUM_MAX_CORRECTION = 1.1; static final double FACE_MOMENTUM_CORRECTION = 1.06; - static final double FACE_MOMENTUM_HORIZONTAL_CORRECTION = -(Math.log10(FACE_MOMENTUM_MAX_CORRECTION-1)/Math.log10(FACE_MOMENTUM_CORRECTION)); + static final double FACE_MOMENTUM_HORIZONTAL_CORRECTION = + -(Math.log10(FACE_MOMENTUM_MAX_CORRECTION-1) / Math.log10(FACE_MOMENTUM_CORRECTION)); static final double ZERO_POWER_THRESHOLD = 0.25; //Unit Conversion Constants @@ -107,7 +117,7 @@ public class Robot { private float rotationPrevious = 0; public float angularVelocity; - //vuforia navigation + //vuforia && tensorFlow Stuff private WebcamName webcam; private VuforiaLocalizer vuforia; @@ -118,8 +128,10 @@ public class Robot { // Inches Left of axis of rotation static final float CAMERA_LEFT_DISPLACEMENT = 4f; - static final double CAMERA_DISPLACEMENT_MAG = Math.hypot(CAMERA_FORWARD_DISPLACEMENT,CAMERA_LEFT_DISPLACEMENT); - static final float CAMERA_DISPLACEMENT_DIRECTION = (float) -Math.atan(CAMERA_LEFT_DISPLACEMENT/CAMERA_FORWARD_DISPLACEMENT); + static final double CAMERA_DISPLACEMENT_MAG = + Math.hypot(CAMERA_FORWARD_DISPLACEMENT,CAMERA_LEFT_DISPLACEMENT); + static final float CAMERA_DISPLACEMENT_DIRECTION = + (float) -Math.atan(CAMERA_LEFT_DISPLACEMENT/CAMERA_FORWARD_DISPLACEMENT); public boolean trackableVisible; private VuforiaTrackables targetsUltimateGoal; @@ -145,6 +157,7 @@ public class Robot { public static final double LAUNCH_POWER = 0.715; private static final long LAUNCH_ACCEL_TIME = 500; + //These variables were originally going to be used in both autonomous and teleOp public double launchPositionX; public double launchPositionY; public float launchRotation; @@ -182,22 +195,17 @@ public class Robot { //Debugging public double totalV; - public double visionX; - public double visionY; - public double visionZ; - public float rawAngle; - private String TestingRecord = "x,y"; - + private String TestingRecord = "Raw IMU, Delta, Saved"; public double forwardVector; public double sidewaysVector; - public double traveledForward = 0; - public double traveledRight; + public DcMotorEx motorAmpsTest; + //All our hardware initialization in one place, for everything that is the same in TeleOp and + //Autonomous public void initHardware() { - limitSwitch = hardwareMap.get(RevTouchSensor.class, "magLim"); - + //drive motors driveFrontLeft = hardwareMap.dcMotor.get("driveFrontLeft"); driveFrontRight = hardwareMap.dcMotor.get("driveFrontRight"); driveBackLeft = hardwareMap.dcMotor.get("driveBackLeft"); @@ -226,9 +234,12 @@ public class Robot { wobbleArmMotor.setTargetPosition(0); wobbleArmMotor.setMode(DcMotor.RunMode.RUN_TO_POSITION); - wobbleUpPos = stateConfiguration.variable("system","arm", "up").value(); - wobbleDownPos = stateConfiguration.variable("system","arm", "down").value(); - wobbleDropPos = stateConfiguration.variable("system","arm", "drop").value(); + wobbleUpPos = stateConfiguration.variable( + "system","arm", "up").value(); + wobbleDownPos = stateConfiguration.variable( + "system","arm", "down").value(); + wobbleDropPos = stateConfiguration.variable( + "system","arm", "drop").value(); wobbleGrabServo = hardwareMap.servo.get("wobbleGrab"); @@ -236,7 +247,7 @@ public class Robot { wobbleTouchSensor = hardwareMap.get(RevTouchSensor.class, "touch"); - //init ring belt + //init collection motor collectionMotor = hardwareMap.dcMotor.get("collect"); collectionMotor.setDirection(DcMotorSimple.Direction.REVERSE); @@ -244,10 +255,17 @@ public class Robot { ringBeltMotor = hardwareMap.dcMotor.get("belt"); ringBeltMotor.setMode(DcMotor.RunMode.STOP_AND_RESET_ENCODER); ringBeltMotor .setMode(DcMotor.RunMode.RUN_USING_ENCODER); - beltMaxStopTime = stateConfiguration.variable("system","belt", "maxStopTime").value(); - beltMaxStopTicks = stateConfiguration.variable("system","belt", "maxStopTicks").value(); - beltReverseTicks = stateConfiguration.variable("system","belt", "reverseTicks").value(); - ringBeltGap = stateConfiguration.variable("system","belt","gap").value(); + + limitSwitch = hardwareMap.get(RevTouchSensor.class, "magLim"); + + beltMaxStopTime = stateConfiguration.variable( + "system","belt", "maxStopTime").value(); + beltMaxStopTicks = stateConfiguration.variable( + "system","belt", "maxStopTicks").value(); + beltReverseTicks = stateConfiguration.variable( + "system","belt", "reverseTicks").value(); + ringBeltGap = stateConfiguration.variable( + "system","belt","gap").value(); //init IMU imu = hardwareMap.get(BNO055IMU.class, "imu"); @@ -279,9 +297,12 @@ public class Robot { webCamServo = hardwareMap.servo.get("look"); webCamServo.setDirection(Servo.Direction.REVERSE ); - minCheckVelocity =stateConfiguration.variable("system", "camera", "minCheckV").value(); - vuforiaRotationCull = stateConfiguration.variable("system", "camera", "rCull").value(); - minCheckDurationMs =stateConfiguration.variable("system", "camera", "minCheckMS").value(); + minCheckVelocity =stateConfiguration.variable( + "system", "camera", "minCheckV").value(); + vuforiaRotationCull = stateConfiguration.variable( + "system", "camera", "rCull").value(); + minCheckDurationMs =stateConfiguration.variable( + "system", "camera", "minCheckMS").value(); //Init Launch Motor DcMotor launcher = hardwareMap.dcMotor.get("launcher"); @@ -296,8 +317,12 @@ public class Robot { launchMotor.setMode(DcMotor.RunMode.RUN_USING_ENCODER); launchMotor.setZeroPowerBehavior(DcMotor.ZeroPowerBehavior.FLOAT); - initLauncher = stateConfiguration.action("system","initLauncher").enabled; - reduceLaunchPos = stateConfiguration.variable("system", "launchPos", "reducePower").value(); + //This is a debugging option that automatically turns on the launch wheel during init. + //This can be disabled using a variable in the TimeCraftersConfiguration + initLauncher = stateConfiguration.action( + "system","initLauncher").enabled; + reduceLaunchPos = stateConfiguration.variable( + "system", "launchPos", "reducePower").value(); if (initLauncher) { double launcherPower = 0; @@ -307,10 +332,13 @@ public class Robot { launchMotor.setPower(launcherPower); } } - // - launchPositionX = inchesToTicks((double) stateConfiguration.variable("system", "launchPos","x").value()); - launchPositionY = inchesToTicks((double) stateConfiguration.variable("system", "launchPos","y").value()); - launchRotation = stateConfiguration.variable("system", "launchPos","rot").value(); + + launchPositionX = inchesToTicks((double) stateConfiguration.variable( + "system", "launchPos","x").value()); + launchPositionY = inchesToTicks((double) stateConfiguration.variable( + "system", "launchPos","y").value()); + launchRotation = stateConfiguration.variable( + "system", "launchPos","rot").value(); initTensorFlow(); @@ -319,8 +347,10 @@ public class Robot { private void initVuforia() { - int cameraMonitorViewId = hardwareMap.appContext.getResources().getIdentifier("cameraMonitorViewId", "id", hardwareMap.appContext.getPackageName()); - VuforiaLocalizer.Parameters parameters = new VuforiaLocalizer.Parameters(cameraMonitorViewId); + int cameraMonitorViewId = hardwareMap.appContext.getResources().getIdentifier( + "cameraMonitorViewId", "id", hardwareMap.appContext.getPackageName()); + VuforiaLocalizer.Parameters parameters = + new VuforiaLocalizer.Parameters(cameraMonitorViewId); parameters.vuforiaLicenseKey = "Abmu1jv/////AAABmYzrcgDEi014nv+wD6PkEPVnOlV2pI3S9sGUMMR/X7hF72x20rP1JcVtsU0nI6VK0yUlYbCSA2k+yMo4hQmPDBvrqeqAgXKa57ilPhW5e1cB3BEevP+9VoJ9QYFhKA3JJTiuFS50WQeuFy3dp0gOPoqHL3XClRFZWbhzihyNnLXgXlKiq+i5GbfONECucQU2DgiuuxYlCaeNdUHl1X5C2pO80zZ6y7PYAp3p0ciXJxqfBoVAklhd69avaAE5Z84ctKscvcbxCS16lq81X7XgIFjshLoD/vpWa300llDG83+Y777q7b5v7gsUCZ6FiuK152Rd272HLuBRhoTXAt0ug9Baq5cz3sn0sAIEzSHX1nah"; parameters.cameraName = webcam; @@ -346,20 +376,27 @@ public class Robot { redAllianceTarget.setLocation(OpenGLMatrix .translation(0, -halfField, mmTargetHeight) - .multiplied(Orientation.getRotationMatrix(EXTRINSIC, XYZ, DEGREES, 90, 0, 180))); + .multiplied(Orientation.getRotationMatrix( + EXTRINSIC, XYZ, DEGREES, 90, 0, 180))); frontWallTarget.setLocation(OpenGLMatrix .translation(-halfField, 0, mmTargetHeight) - .multiplied(Orientation.getRotationMatrix(EXTRINSIC, XYZ, DEGREES, 90, 0 , 90))); + .multiplied(Orientation.getRotationMatrix( + EXTRINSIC, XYZ, DEGREES, 90, 0 , 90))); redTowerGoalTarget.setLocation(OpenGLMatrix .translation(halfField, -quadField, mmTargetHeight) - .multiplied(Orientation.getRotationMatrix(EXTRINSIC, XYZ, DEGREES, 90, 0, -90))); + .multiplied(Orientation.getRotationMatrix( + EXTRINSIC, XYZ, DEGREES, 90, 0, -90))); OpenGLMatrix robotFromCamera = OpenGLMatrix - .translation(CAMERA_FORWARD_DISPLACEMENT * mmPerInch, CAMERA_LEFT_DISPLACEMENT * mmPerInch, CAMERA_VERTICAL_DISPLACEMENT * mmPerInch) - .multiplied(Orientation.getRotationMatrix(EXTRINSIC, YZX, DEGREES, -90, 0, 0)); + .translation(CAMERA_FORWARD_DISPLACEMENT * mmPerInch, + CAMERA_LEFT_DISPLACEMENT * mmPerInch, + CAMERA_VERTICAL_DISPLACEMENT * mmPerInch) + .multiplied(Orientation.getRotationMatrix( + EXTRINSIC, YZX, DEGREES, -90, 0, 0)); for (VuforiaTrackable trackable : trackables) { - ((VuforiaTrackableDefaultListener) trackable.getListener()).setPhoneInformation(robotFromCamera, parameters.cameraDirection); + ((VuforiaTrackableDefaultListener) trackable.getListener()) + .setPhoneInformation(robotFromCamera, parameters.cameraDirection); } targetsUltimateGoal.activate(); @@ -373,11 +410,15 @@ public class Robot { int tfodMonitorViewId = hardwareMap.appContext.getResources().getIdentifier( "tfodMonitorViewId", "id", hardwareMap.appContext.getPackageName()); TFObjectDetector.Parameters parameters = new TFObjectDetector.Parameters(tfodMonitorViewId); - parameters.minResultConfidence = stateConfiguration.variable("system", "camera", "minConfidence").value(); + parameters.minResultConfidence = stateConfiguration.variable( + "system", "camera", "minConfidence").value(); tfObjectDetector = ClassFactory.getInstance().createTFObjectDetector(parameters, vuforia); - tfObjectDetector.loadModelFromAsset("UltimateGoal.tflite", "Quad", "Single"); + tfObjectDetector.loadModelFromAsset( + "UltimateGoal.tflite", "Quad", "Single"); } + //Localization Function! This function is represented in a flow diagram, earlier in the + //software section //run this in every exec to track the robot's location. public void updateLocation(){ @@ -417,13 +458,15 @@ public class Robot { ticksPerDegreeForward = TICKS_PER_ROBOT_DEGREE_CLOCKWISE_FORWARD; } - forwardVector = ((encoderLeftChange+encoderRightChange)/2) - (rotationChange* ticksPerDegreeForward); + forwardVector = ((encoderLeftChange+encoderRightChange)/2) - + (rotationChange* ticksPerDegreeForward); traveledForward += forwardVector; sidewaysVector = encoderBackChange + (rotationChange * ticksPerDegreeSideways); double magnitude = Math.sqrt((forwardVector*forwardVector) + (sidewaysVector*sidewaysVector)); - double direction = Math.toRadians(Robot.rotation + (rotationChange/2)) + Math.atan2(sidewaysVector,forwardVector); + double direction = Math.toRadians(Robot.rotation + (rotationChange/2)) + + Math.atan2(sidewaysVector,forwardVector); double xChange = magnitude * (Math.sin(direction)); double yChange = magnitude * (Math.cos(direction)); @@ -434,11 +477,15 @@ public class Robot { Robot.rotation += rotationChange; Robot.rotation = scaleAngleRange(Robot.rotation); - totalV = Math.abs(encoderLeftChange) + Math.abs(encoderRightChange) + Math.abs(encoderBackChange); + totalV = Math.abs(encoderLeftChange) + Math.abs(encoderRightChange) + + Math.abs(encoderBackChange); + +// record(""+System.currentTimeMillis()+", "+imuAngle); } - - + //Experimentation has demonstrated that Vuforia dosen't provide good data while the camera + //is moving or rotating. This function detects if conditions are appropriate to run vuforia and + //get more accurate results public void syncIfStationary() { if (totalV < minCheckVelocity) { long timeCurrent = System.currentTimeMillis(); @@ -459,7 +506,9 @@ public class Robot { trackableVisible = false; for (VuforiaTrackable trackable : trackables) { if (((VuforiaTrackableDefaultListener)trackable.getListener()).isVisible()) { - OpenGLMatrix robotLocation = ((VuforiaTrackableDefaultListener)trackable.getListener()).getUpdatedRobotLocation(); + OpenGLMatrix robotLocation = + ((VuforiaTrackableDefaultListener)trackable.getListener()) + .getUpdatedRobotLocation(); //this is used for debugging purposes. trackableVisible = true; @@ -470,7 +519,8 @@ public class Robot { //For our tournament, it makes sense to make zero degrees towards the goal. //Orientation is inverted to have clockwise be positive. - Orientation orientation = Orientation.getOrientation(lastConfirmendLocation, EXTRINSIC, XYZ, DEGREES); + Orientation orientation = + Orientation.getOrientation(lastConfirmendLocation, EXTRINSIC, XYZ, DEGREES); float vuforiaRotation = 90-orientation.thirdAngle; if (vuforiaRotation > 180) { @@ -484,8 +534,10 @@ public class Robot { double camX = -translation.get(1) / mmPerInch; double camY = translation.get(0) / mmPerInch; - double displaceX = CAMERA_DISPLACEMENT_MAG * Math.sin(Robot.rotation + 180 - CAMERA_DISPLACEMENT_DIRECTION); - double displaceY = CAMERA_DISPLACEMENT_MAG * Math.cos(Robot.rotation + 180 - CAMERA_DISPLACEMENT_DIRECTION); + double displaceX = CAMERA_DISPLACEMENT_MAG * + Math.sin(Robot.rotation + 180 - CAMERA_DISPLACEMENT_DIRECTION); + double displaceY = CAMERA_DISPLACEMENT_MAG * + Math.cos(Robot.rotation + 180 - CAMERA_DISPLACEMENT_DIRECTION); locationX = inchesToTicks(camX - displaceX); locationY = inchesToTicks(camY - displaceY); @@ -508,18 +560,13 @@ public class Robot { return Robot.locationY; } + //This is meant to only be used to indicate starting positions and to reorient the robot. public void setLocalization(float rotation, double x, double y) { Robot.rotation = rotation; Robot.locationX = x; Robot.locationY = y; } - //Manually set the position of the robot on the field. - public void setCurrentPosition(float rotation, double x, double y) { - Robot.rotation = rotation; - Robot.locationX = x; - Robot.locationY = y; - } //returns the angle from the robot's current position to the given target position. public float getAngleToPosition (double x, double y) { @@ -531,7 +578,7 @@ public class Robot { } - //Unit conversion + //Unit conversions public double ticksToInches(double ticks) { return ticks * (ENCODER_CIRCUMFERENCE / COUNTS_PER_REVOLUTION); } @@ -541,26 +588,28 @@ public class Robot { } - //Returns the angle between two angles, with positive angles indicating that the reference is - //to the right (clockwise) of the current. Negative angles indicate that the reference is to the - //left. + //Returns the shortest angle between two directions, with positive angles indicating that the + // reference is to the right (clockwise) of the current. Negative angles indicate that the + // reference is to the left. public float getRelativeAngle(float reference, float current) { return scaleAngleRange(current - reference); } //Drive Functions - public void setDrivePower(double powerFrontLeft, double powerFrontRight, double powerBackLeft, double powerBackRight){ + public void setDrivePower(double powerFrontLeft, double powerFrontRight, + double powerBackLeft, double powerBackRight){ driveFrontLeft.setPower(powerFrontLeft); driveFrontRight.setPower(powerFrontRight); driveBackLeft.setPower(powerBackLeft); driveBackRight.setPower(powerBackRight); } - //returns an array of the powers necessary to execute the provided motion. "degreesDirectionMotion" - //is the angle relative to the field that the robot should drive at. "degreesDirectionFace" is - //the angle the robot should face relative to the field. The order of the output powers is - //is ForwardLeft, ForwardRight, BackLeft, BackRight - public double[] getMecanumPowers(float degreesDirectionMotion, double scalar, float degreesDirectionFace) { + //returns an array of the powers necessary to execute the provided motion. + //"degreesDirectionMotion" is the angle relative to the field that the robot should drive at. + //"degreesDirectionFace" is the angle the robot should face relative to the field. The order of + //the output powers is ForwardLeft, ForwardRight, BackLeft, BackRight + public double[] getMecanumPowers(float degreesDirectionMotion, double scalar, + float degreesDirectionFace) { angularVelocity = imu.getAngularVelocity().xRotationRate; //calculating the base mecanum powers so that the robot drives along the degreesDirectionMotion @@ -582,12 +631,14 @@ public class Robot { LINEAR_CORRECTION * relativeRotation; if (relativeRotation != 0) { - double momentumRelative = angularVelocity * (relativeRotation / Math.abs(relativeRotation)); - double exponential = Math.pow(MOMENTUM_CORRECTION, MOMENTUM_HORIZONTAL_CORRECTION-momentumRelative); + double momentumRelative = angularVelocity * + (relativeRotation / Math.abs(relativeRotation)); + double exponential = + Math.pow(MOMENTUM_CORRECTION, MOMENTUM_HORIZONTAL_CORRECTION-momentumRelative); double momentumCorrection = (MOMENTUM_MAX_CORRECTION*exponential)/(1+exponential); //reduces concern for momentum when the angle is far away from target - turnCorrection *= momentumCorrection + ((Math.abs(relativeRotation) * (1 - momentumCorrection)) / 180 ); -// turnCorrection *= momentumCorrection; + turnCorrection *= momentumCorrection + ((Math.abs(relativeRotation) * + (1 - momentumCorrection)) / 180 ); } double powerForwardRight = scalar * (q + turnCorrection); @@ -660,6 +711,7 @@ public class Robot { return powers; } + //Used to for automated jam countermeasures public boolean beltIsStuck() { int ringBeltPos = ringBeltMotor.getCurrentPosition(); boolean notMoved = (ringBeltPos - ringBeltPrev <= beltMaxStopTicks); @@ -677,6 +729,7 @@ public class Robot { return angle; } + //Debugging tools public void record(String record) { TestingRecord+="\n"+record; } diff --git a/TeamCode/src/main/java/org/timecrafters/UltimateGoal/Competition/TeleOp/LaunchControl.java b/TeamCode/src/main/java/org/timecrafters/UltimateGoal/Competition/TeleOp/LaunchControl.java index 689f396..180f648 100644 --- a/TeamCode/src/main/java/org/timecrafters/UltimateGoal/Competition/TeleOp/LaunchControl.java +++ b/TeamCode/src/main/java/org/timecrafters/UltimateGoal/Competition/TeleOp/LaunchControl.java @@ -17,7 +17,6 @@ public class LaunchControl extends CyberarmState { @Override public void start() { - robot.launchMotor.setPower(Robot.LAUNCH_POWER); if (robot.ringBeltStage > 2) { if (robot.ringBeltStage > 4) { diff --git a/TeamCode/src/main/java/org/timecrafters/UltimateGoal/Competition/TeleOp/Player1.java b/TeamCode/src/main/java/org/timecrafters/UltimateGoal/Competition/TeleOp/Player1.java index 543621b..d25a9d9 100644 --- a/TeamCode/src/main/java/org/timecrafters/UltimateGoal/Competition/TeleOp/Player1.java +++ b/TeamCode/src/main/java/org/timecrafters/UltimateGoal/Competition/TeleOp/Player1.java @@ -1,5 +1,11 @@ package org.timecrafters.UltimateGoal.Competition.TeleOp; +/* +The Player1 state has all the controls for player one. The Player One and Player Two controls are +kept in separate states so that the childrenHaveFinished() method can be used to easily stop things +from running at the same time that shouldn't be. +*/ + import com.qualcomm.hardware.rev.RevBlinkinLedDriver; import org.cyberarm.engine.V2.CyberarmState; @@ -40,6 +46,7 @@ public class Player1 extends CyberarmState { private double endGameX; private double endGameY; private float endGameRot; + private int loopCount; private double refinePower; @@ -49,14 +56,21 @@ public class Player1 extends CyberarmState { @Override public void init() { - cardinalSnapping = robot.stateConfiguration.variable("tele","control", "cardinalSnapping").value(); - pairSnapping = robot.stateConfiguration.variable("tele","control", "pairSnapping").value(); - faceControlThreshold = robot.stateConfiguration.variable("tele","control", "faceControlT").value(); - refinePower = robot.stateConfiguration.variable("tele","control", "refPower").value(); + cardinalSnapping = robot.stateConfiguration.variable( + "tele","control", "cardinalSnapping").value(); + pairSnapping = robot.stateConfiguration.variable( + "tele","control", "pairSnapping").value(); + faceControlThreshold = robot.stateConfiguration.variable( + "tele","control", "faceControlT").value(); + refinePower = robot.stateConfiguration.variable( + "tele","control", "refPower").value(); - endGameX = robot.stateConfiguration.variable("tele","_endGameStart","x").value(); - endGameY = robot.stateConfiguration.variable("tele","_endGameStart","y").value(); - endGameRot = robot.stateConfiguration.variable("tele","_endGameStart", "r").value(); + endGameX = robot.stateConfiguration.variable( + "tele","_endGameStart","x").value(); + endGameY = robot.stateConfiguration.variable( + "tele","_endGameStart","y").value(); + endGameRot = robot.stateConfiguration.variable( + "tele","_endGameStart", "r").value(); } @Override @@ -66,8 +80,11 @@ public class Player1 extends CyberarmState { @Override public void exec() { + loopCount+=1; + robot.record(""+runTime()+", "+loopCount+", "+robot.getRotation()); robot.updateLocation(); + //toggle for drive speed boolean lb = engine.gamepad1.left_stick_button; if (lb && !lbPrev) { if (drivePower == 1) { @@ -78,7 +95,9 @@ public class Player1 extends CyberarmState { } lbPrev = lb; - + //This Runs the FindWobbleGoal state as long as the button is pressed. When it's released, + //the state is interrupted. If the state finishes while the button is still pressed, + //it waits until the button is released before running the state again runNextFindWobble = (findWobbleGoal == null || findWobbleGoal.getHasFinished()); boolean findWobbleInput = engine.gamepad1.x; @@ -89,7 +108,8 @@ public class Player1 extends CyberarmState { faceDirection = robot.getRotation(); if (runNextFindWobble && !findWobbleInputPrev) { - findWobbleGoal = new FindWobbleGoal(robot, "auto", "08_0"); + findWobbleGoal = + new FindWobbleGoal(robot, "auto", "08_0"); addParallelState(findWobbleGoal); } //if the claw is closed, open the claw. @@ -113,6 +133,8 @@ public class Player1 extends CyberarmState { } aPrev = a; + //This logic works the same as the stuff above, accept instead of autonomous wobble grab, + //it runNextDriveToLaunch = (powerShots == null || powerShots.getHasFinished()); boolean driveToLaunchInput = engine.gamepad1.y && !findWobbleInput; @@ -127,29 +149,27 @@ public class Player1 extends CyberarmState { } driveToLaunchInputPrev = driveToLaunchInput; -// if (engine.gamepad1.y) { -// robot.setLocalization(endGameRot,endGameX,endGameY); -// setHasFinished(true); -// } - + //Normal Driver Controls if (childrenHaveFinished()) { - //Normal Driver Controls + double leftJoystickX = engine.gamepad1.left_stick_x; double leftJoystickY = engine.gamepad1.left_stick_y; - leftJoystickDegrees = robot.getRelativeAngle(90, (float) Math.toDegrees(Math.atan2(leftJoystickX, -leftJoystickY))); + leftJoystickDegrees = robot.getRelativeAngle(90, + (float) Math.toDegrees(Math.atan2(leftJoystickX, -leftJoystickY))); leftJoystickMagnitude = Math.hypot(leftJoystickX, leftJoystickY); double rightJoystickX = engine.gamepad1.right_stick_x; double rightJoystickY = engine.gamepad1.right_stick_y; - rightJoystickDegrees = robot.getRelativeAngle(90, (float) Math.toDegrees(Math.atan2(rightJoystickX, -rightJoystickY))); + rightJoystickDegrees = robot.getRelativeAngle(90, + (float) Math.toDegrees(Math.atan2(rightJoystickX, -rightJoystickY))); rightJoystickMagnitude = Math.hypot(rightJoystickX, rightJoystickY); //allows the the driver to indicate which direction the robot is currently looking //so that the controller and robot can be re-synced in the event of a bad initial - //position. + //rotation. if (engine.gamepad1.back) { float newRotation = 0; @@ -161,14 +181,19 @@ public class Player1 extends CyberarmState { faceDirection = newRotation; } - //if the driver is letting go of the face joystick, the robot should maintain it's current face direction. - if (rightJoystickMagnitude > faceControlThreshold || rightJoystickMagnitude - rightJoystickMagnitudePrevious > 0) { + //if the driver is letting go of the face joystick, the robot should maintain it's + //current face direction. + if (rightJoystickMagnitude > faceControlThreshold || + rightJoystickMagnitude - rightJoystickMagnitudePrevious > 0) { - //if the joystick is close to one of the cardinal directions, it is set to exactly the cardinal direction + //if the joystick is close to one of the cardinal directions, it is set to exactly + // the cardinal direction faceDirection = snapToCardinal(rightJoystickDegrees, cardinalSnapping, 0); } rightJoystickMagnitudePrevious = rightJoystickMagnitude; + //The D-pad is used if the drivers need to get a more precise angle than they can get + //using the face joystick if (engine.gamepad1.dpad_right) { powers = new double[]{refinePower, -refinePower, refinePower, -refinePower}; faceDirection = robot.getRotation(); @@ -182,7 +207,9 @@ public class Player1 extends CyberarmState { //drives the robot in the direction of the move joystick while facing the direction //of the look joystick. if the move direction is almost aligned/perpendicular to the //look joystick, - powers = robot.getMecanumPowers(snapToCardinal(leftJoystickDegrees, pairSnapping, faceDirection), drivePower, faceDirection); + powers = robot.getMecanumPowers( + snapToCardinal(leftJoystickDegrees, pairSnapping, faceDirection), + drivePower, faceDirection); } robot.setDrivePower(powers[0], powers[1], powers[2], powers[3]); @@ -190,7 +217,8 @@ public class Player1 extends CyberarmState { //LED feedback control double ringBeltPower = robot.ringBeltMotor.getPower(); - if (ringBeltPower > 0 && Math.abs(robot.ringBeltMotor.getTargetPosition() - robot.ringBeltMotor.getCurrentPosition()) > 10) { + if (ringBeltPower > 0 && Math.abs(robot.ringBeltMotor.getTargetPosition() - + robot.ringBeltMotor.getCurrentPosition()) > 10) { robot.ledDriver.setPattern(RevBlinkinLedDriver.BlinkinPattern.HEARTBEAT_BLUE ); } else if (ringBeltPower < 0) { robot.ledDriver.setPattern(RevBlinkinLedDriver.BlinkinPattern.HEARTBEAT_RED); diff --git a/TeamCode/src/main/java/org/timecrafters/UltimateGoal/Competition/TeleOp/Player2.java b/TeamCode/src/main/java/org/timecrafters/UltimateGoal/Competition/TeleOp/Player2.java index 624665e..70123f7 100644 --- a/TeamCode/src/main/java/org/timecrafters/UltimateGoal/Competition/TeleOp/Player2.java +++ b/TeamCode/src/main/java/org/timecrafters/UltimateGoal/Competition/TeleOp/Player2.java @@ -1,9 +1,15 @@ package org.timecrafters.UltimateGoal.Competition.TeleOp; +/* +The Player2 state has all the controls for player two. This includes a lot of automation and +emergency features, for if the driver wants to take control unexpectedly +*/ + import com.qualcomm.hardware.rev.RevBlinkinLedDriver; import com.qualcomm.robotcore.hardware.DcMotor; import org.cyberarm.engine.V2.CyberarmState; +import org.firstinspires.ftc.robotcore.external.navigation.CurrentUnit; import org.timecrafters.UltimateGoal.Competition.Launch; import org.timecrafters.UltimateGoal.Competition.ProgressRingBelt; import org.timecrafters.UltimateGoal.Competition.Robot; @@ -22,6 +28,7 @@ public class Player2 extends CyberarmState { private DcMotor.RunMode runModePrev; private boolean lbPrev; private boolean manualArmHold; + private int loops = 0; @@ -45,9 +52,10 @@ public class Player2 extends CyberarmState { @Override public void exec() { +// loops+=1; +// robot.record(""+runTime()+", "+loops+", "+robot.getRotation()); //Collector control - double rt = engine.gamepad2.right_trigger; double lt = engine.gamepad2.left_trigger; if (rt < lt) { @@ -58,6 +66,8 @@ public class Player2 extends CyberarmState { robot.collectionMotor.setPower(0); } + //The childrenHaveFinished() method tracks if there are parallel states that are still + //running. if (childrenHaveFinished()) { //belt progression control boolean rb = engine.gamepad2.right_bumper; @@ -140,33 +150,40 @@ public class Player2 extends CyberarmState { } lbPrev = lb; -// if (engine.gamepad1.y) { -// setHasFinished(true); -// } + if (engine.gamepad2.back) { + for (CyberarmState state : children) { + engine.stopState(state); + } + } + } + + //This just checks if the wobble arm runmode is already the desired mode before setting it. + //I don't know if this is actually helpful private void setArmMode(DcMotor.RunMode runMode) { if (robot.wobbleArmMotor.getMode() != runMode) { robot.wobbleArmMotor.setMode(runMode); } } + @Override public void telemetry() { // engine.telemetry.addLine("belt"); // engine.telemetry.addData("power", robot.ringBeltMotor.getPower()); // engine.telemetry.addData("pos", robot.ringBeltMotor.getCurrentPosition()); // engine.telemetry.addData("target", robot.ringBeltMotor.getTargetPosition()); - +// // engine.telemetry.addData("ring belt stage", robot.ringBeltStage); // engine.telemetry.addData("Touch Sensor Pressed", robot.wobbleTouchSensor.isPressed()); // engine.telemetry.addData(" Sensor value", robot.wobbleTouchSensor.getValue()); -// engine.telemetry.addData("Player 2 children", childrenHaveFinished()); -// for (CyberarmState state : children) { -// if (!state.getHasFinished()) { -// engine.telemetry.addLine("" + state.getClass()); -// } -// } + engine.telemetry.addData("Player 2 children", childrenHaveFinished()); + for (CyberarmState state : children) { + if (!state.getHasFinished()) { + engine.telemetry.addLine("" + state.getClass()); + } + } } } diff --git a/TeamCode/src/main/java/org/timecrafters/UltimateGoal/Competition/TeleOp/TeleOpEngine.java b/TeamCode/src/main/java/org/timecrafters/UltimateGoal/Competition/TeleOp/TeleOpEngine.java index a3b3b60..f63409c 100644 --- a/TeamCode/src/main/java/org/timecrafters/UltimateGoal/Competition/TeleOp/TeleOpEngine.java +++ b/TeamCode/src/main/java/org/timecrafters/UltimateGoal/Competition/TeleOp/TeleOpEngine.java @@ -1,12 +1,13 @@ package org.timecrafters.UltimateGoal.Competition.TeleOp; +import com.qualcomm.robotcore.eventloop.opmode.Disabled; import com.qualcomm.robotcore.eventloop.opmode.TeleOp; import org.cyberarm.engine.V2.CyberarmEngine; import org.timecrafters.UltimateGoal.Competition.Autonomous.DriveToCoordinates; import org.timecrafters.UltimateGoal.Competition.Autonomous.Face; import org.timecrafters.UltimateGoal.Competition.Robot; - +@Disabled @TeleOp (name = "TeleOp",group = "comp") public class TeleOpEngine extends CyberarmEngine { diff --git a/TeamCode/src/main/java/org/timecrafters/UltimateGoal/Competition/TeleOp/powerShotsControl.java b/TeamCode/src/main/java/org/timecrafters/UltimateGoal/Competition/TeleOp/powerShotsControl.java index c2e897f..c53dc7b 100644 --- a/TeamCode/src/main/java/org/timecrafters/UltimateGoal/Competition/TeleOp/powerShotsControl.java +++ b/TeamCode/src/main/java/org/timecrafters/UltimateGoal/Competition/TeleOp/powerShotsControl.java @@ -3,6 +3,7 @@ package org.timecrafters.UltimateGoal.Competition.TeleOp; import org.cyberarm.engine.V2.CyberarmState; import org.timecrafters.UltimateGoal.Competition.Autonomous.DriveToCoordinates; import org.timecrafters.UltimateGoal.Competition.Autonomous.Face; +import org.timecrafters.UltimateGoal.Competition.Pause; import org.timecrafters.UltimateGoal.Competition.Robot; import java.util.ArrayList; @@ -15,6 +16,8 @@ public class powerShotsControl extends CyberarmState { private double endGameY; private float endGameRot; + private double endGamePower; + private int nextState = 0; private ArrayList states = new ArrayList(); @@ -28,11 +31,13 @@ public class powerShotsControl extends CyberarmState { endGameX = robot.stateConfiguration.variable("tele","_endGameStart","x").value(); endGameY = robot.stateConfiguration.variable("tele","_endGameStart","y").value(); endGameRot = robot.stateConfiguration.variable("tele","_endGameStart", "r").value(); + endGamePower = robot.stateConfiguration.variable("tele","_endGameStart", "power").value(); endGameX = robot.inchesToTicks(endGameX); endGameY = robot.inchesToTicks(endGameY); endGameRot = (float) robot.inchesToTicks(endGameRot); + states.add(new Pause(robot, "tele","_endGameStart")); states.add(new DriveToCoordinates(robot, "tele", "_pow1")); states.add(new Face(robot,"tele","_faceZero")); states.add(new LaunchControl(robot)); @@ -47,7 +52,7 @@ public class powerShotsControl extends CyberarmState { @Override public void start() { robot.setLocalization(endGameRot,endGameX,endGameY); - robot.launchMotor.setPower(Robot.LAUNCH_POWER); + robot.launchMotor.setPower(endGamePower); } @Override diff --git a/TeamCode/src/main/java/org/timecrafters/javaClass/aubrey/AubreyFirstState.java b/TeamCode/src/main/java/org/timecrafters/javaClass/aubrey/AubreyFirstState.java new file mode 100644 index 0000000..24b2106 --- /dev/null +++ b/TeamCode/src/main/java/org/timecrafters/javaClass/aubrey/AubreyFirstState.java @@ -0,0 +1,22 @@ +package org.timecrafters.javaClass.aubrey; + +import org.cyberarm.engine.V2.CyberarmState; +import org.timecrafters.javaClass.samples.SampleRobot; + +public class AubreyFirstState extends CyberarmState { + + //here, you'll find some of your variables. you can add more as you need them. + private SampleRobot robot; + + //This is the constructor. It lets other code bits run use the code you put here + public AubreyFirstState(SampleRobot robot) { + this.robot = robot; + } + + //This is a method. methods are bits of code that can be run elsewhere. + //This one is set up to repeat every few milliseconds + @Override + public void exec() { + + } +} diff --git a/TeamCode/src/main/java/org/timecrafters/javaClass/samples/AubreyFirstEngine.java b/TeamCode/src/main/java/org/timecrafters/javaClass/samples/AubreyFirstEngine.java new file mode 100644 index 0000000..769f194 --- /dev/null +++ b/TeamCode/src/main/java/org/timecrafters/javaClass/samples/AubreyFirstEngine.java @@ -0,0 +1,26 @@ +package org.timecrafters.javaClass.samples; + +import com.qualcomm.robotcore.eventloop.opmode.Autonomous; + +import org.cyberarm.engine.V2.CyberarmEngine; +import org.timecrafters.UltimateGoal.Competition.Robot; +import org.timecrafters.javaClass.aubrey.AubreyFirstState; + +@Autonomous(name = "Aubrey: First Program", group = "aubrey") +public class AubreyFirstEngine extends CyberarmEngine { + + SampleRobot robot; + + @Override + public void init() { + robot = new SampleRobot(hardwareMap); + robot.initHardware(); + robot.wobbleGrabServo.setPosition(Robot.WOBBLE_SERVO_CLOSED); + super.init(); + } + + @Override + public void setup() { + addState(new AubreyFirstState(robot)); + } +} diff --git a/TeamCode/src/main/java/org/timecrafters/javaClass/samples/SampleRobot.java b/TeamCode/src/main/java/org/timecrafters/javaClass/samples/SampleRobot.java new file mode 100644 index 0000000..543cbec --- /dev/null +++ b/TeamCode/src/main/java/org/timecrafters/javaClass/samples/SampleRobot.java @@ -0,0 +1,191 @@ + package org.timecrafters.javaClass.samples; + +/* +The robot object contains all the hardware and functions that are used in both teleOp and +Autonomous. This includes drive functions, localization functions, shared constants, and a few +general calculations and debugging tools. +*/ + +import android.os.Environment; +import android.util.Log; + +import com.qualcomm.hardware.bosch.BNO055IMU; +import com.qualcomm.hardware.rev.RevBlinkinLedDriver; +import com.qualcomm.hardware.rev.RevColorSensorV3; +import com.qualcomm.hardware.rev.RevTouchSensor; +import com.qualcomm.robotcore.hardware.DcMotor; +import com.qualcomm.robotcore.hardware.DcMotorEx; +import com.qualcomm.robotcore.hardware.DcMotorSimple; +import com.qualcomm.robotcore.hardware.HardwareMap; +import com.qualcomm.robotcore.hardware.Servo; +import com.qualcomm.robotcore.hardware.configuration.typecontainers.MotorConfigurationType; + +import org.firstinspires.ftc.robotcore.external.ClassFactory; +import org.firstinspires.ftc.robotcore.external.hardware.camera.WebcamName; +import org.firstinspires.ftc.robotcore.external.matrices.OpenGLMatrix; +import org.firstinspires.ftc.robotcore.external.matrices.VectorF; +import org.firstinspires.ftc.robotcore.external.navigation.Orientation; +import org.firstinspires.ftc.robotcore.external.navigation.Position; +import org.firstinspires.ftc.robotcore.external.navigation.Velocity; +import org.firstinspires.ftc.robotcore.external.navigation.VuforiaLocalizer; +import org.firstinspires.ftc.robotcore.external.navigation.VuforiaTrackable; +import org.firstinspires.ftc.robotcore.external.navigation.VuforiaTrackableDefaultListener; +import org.firstinspires.ftc.robotcore.external.navigation.VuforiaTrackables; +import org.firstinspires.ftc.robotcore.external.tfod.TFObjectDetector; +import org.timecrafters.TimeCraftersConfigurationTool.TimeCraftersConfiguration; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import static org.firstinspires.ftc.robotcore.external.navigation.AngleUnit.DEGREES; +import static org.firstinspires.ftc.robotcore.external.navigation.AxesOrder.XYZ; +import static org.firstinspires.ftc.robotcore.external.navigation.AxesOrder.YZX; +import static org.firstinspires.ftc.robotcore.external.navigation.AxesReference.EXTRINSIC; + + public class SampleRobot { + + private HardwareMap hardwareMap; + + public SampleRobot(HardwareMap hardwareMap) { + this.hardwareMap = hardwareMap; + } + + //The TimeCraftersConfiguration is part of a debugging and tuning tool that allows us to edit + //variables saved on the phone, without having to re-download the whole program. This is + //especially useful for autonomous route tuning + public TimeCraftersConfiguration stateConfiguration = new TimeCraftersConfiguration(); + + //We use the IMU to get reliable rotation and angular velocity information. Experimentation has + //demonstrated that the accelerometer and related integrations aren't as accurate. + public BNO055IMU imu; + + //The LEDs are used to provide driver feedback and for looking beautiful + public RevBlinkinLedDriver ledDriver; + + //drive and dead-wheal hardware + public DcMotor driveFrontLeft; + public DcMotor driveBackLeft; + public DcMotor driveFrontRight; + public DcMotor driveBackRight; + + public DcMotor encoderLeft; + public DcMotor encoderRight; + public DcMotor encoderBack; + + //Unit Conversion Constants + static final double ENCODER_CIRCUMFERENCE = Math.PI * 2.3622; + static final int COUNTS_PER_REVOLUTION = 8192; + //Launcher + public DcMotor launchMotor; + public static final double LAUNCH_POWER = 0.715; + + //Ring Intake + public DcMotor collectionMotor; + + //Ring Belt + public DcMotor ringBeltMotor; + public RevTouchSensor limitSwitch; + + //Wobble Goal Arm & Grabber + public DcMotor wobbleArmMotor; + public Servo wobbleGrabServo; + public RevColorSensorV3 wobbleColorSensor; + public RevTouchSensor wobbleTouchSensor; + + //All our hardware initialization in one place, for everything that is the same in TeleOp and + //Autonomous + public void initHardware() { + + //drive motors + driveFrontLeft = hardwareMap.dcMotor.get("driveFrontLeft"); + driveFrontRight = hardwareMap.dcMotor.get("driveFrontRight"); + driveBackLeft = hardwareMap.dcMotor.get("driveBackLeft"); + driveBackRight = hardwareMap.dcMotor.get("driveBackRight"); + + driveFrontLeft.setDirection(DcMotorSimple.Direction.FORWARD); + driveFrontRight.setDirection(DcMotorSimple.Direction.REVERSE); + driveBackLeft.setDirection(DcMotorSimple.Direction.FORWARD); + driveBackRight.setDirection(DcMotorSimple.Direction.REVERSE); + + //Localization encoders + encoderRight = hardwareMap.dcMotor.get("driveFrontRight"); + encoderBack = hardwareMap.dcMotor.get("driveFrontLeft"); + encoderLeft = hardwareMap.dcMotor.get("collect"); + + encoderRight.setMode(DcMotor.RunMode.STOP_AND_RESET_ENCODER); + encoderRight.setMode(DcMotor.RunMode.RUN_WITHOUT_ENCODER); + encoderBack.setMode(DcMotor.RunMode.STOP_AND_RESET_ENCODER); + encoderBack.setMode(DcMotor.RunMode.RUN_WITHOUT_ENCODER); + encoderLeft.setMode(DcMotor.RunMode.STOP_AND_RESET_ENCODER); + encoderLeft.setMode(DcMotor.RunMode.RUN_WITHOUT_ENCODER); + + //init wobble arm + wobbleArmMotor = hardwareMap.dcMotor.get("wobbleArm"); + wobbleArmMotor.setMode(DcMotor.RunMode.STOP_AND_RESET_ENCODER); + wobbleArmMotor.setTargetPosition(0); + wobbleArmMotor.setMode(DcMotor.RunMode.RUN_TO_POSITION); + + wobbleGrabServo = hardwareMap.servo.get("wobbleGrab"); + + wobbleColorSensor = hardwareMap.get(RevColorSensorV3.class, "color"); + wobbleTouchSensor = hardwareMap.get(RevTouchSensor.class, "touch"); + + + //init collection motor + collectionMotor = hardwareMap.dcMotor.get("collect"); + collectionMotor.setDirection(DcMotorSimple.Direction.REVERSE); + + //init ring belt + ringBeltMotor = hardwareMap.dcMotor.get("belt"); + ringBeltMotor.setMode(DcMotor.RunMode.STOP_AND_RESET_ENCODER); + ringBeltMotor .setMode(DcMotor.RunMode.RUN_USING_ENCODER); + + limitSwitch = hardwareMap.get(RevTouchSensor.class, "magLim"); + + //init IMU + imu = hardwareMap.get(BNO055IMU.class, "imu"); + + BNO055IMU.Parameters parameters = new BNO055IMU.Parameters(); + + parameters.mode = BNO055IMU.SensorMode.IMU; + parameters.angleUnit = BNO055IMU.AngleUnit.DEGREES; + parameters.accelUnit = BNO055IMU.AccelUnit.METERS_PERSEC_PERSEC; + parameters.loggingEnabled = false; + + imu.initialize(parameters); + + //Init Launch Motor + DcMotor launcher = hardwareMap.dcMotor.get("launcher"); + + MotorConfigurationType launchMotorType = launcher.getMotorType(); + launchMotorType.setGearing(3); + launchMotorType.setTicksPerRev(84); + launchMotorType.setMaxRPM(2400); + + launchMotor = launcher; + launchMotor.setMotorType(launchMotorType); + launchMotor.setMode(DcMotor.RunMode.RUN_USING_ENCODER); + launchMotor.setZeroPowerBehavior(DcMotor.ZeroPowerBehavior.FLOAT); + + ledDriver = hardwareMap.get(RevBlinkinLedDriver.class, "leds"); + } + + public float getIMURotation() { + return imu.getAngularOrientation().firstAngle; + } + + //Unit conversions + public double ticksToInches(double ticks) { + return ticks * (ENCODER_CIRCUMFERENCE / COUNTS_PER_REVOLUTION); + } + + public double inchesToTicks(double inches) { + return inches * (COUNTS_PER_REVOLUTION / ENCODER_CIRCUMFERENCE); + + } + + + } diff --git a/TeamCode/src/main/java/org/timecrafters/javaClass/samples/SampleRobotEx.java b/TeamCode/src/main/java/org/timecrafters/javaClass/samples/SampleRobotEx.java new file mode 100644 index 0000000..91b3321 --- /dev/null +++ b/TeamCode/src/main/java/org/timecrafters/javaClass/samples/SampleRobotEx.java @@ -0,0 +1,515 @@ + package org.timecrafters.javaClass.samples; + +/* +The robot object contains all the hardware and functions that are used in both teleOp and +Autonomous. This includes drive functions, localization functions, shared constants, and a few +general calculations and debugging tools. +*/ + +import com.qualcomm.hardware.bosch.BNO055IMU; +import com.qualcomm.hardware.rev.RevBlinkinLedDriver; +import com.qualcomm.hardware.rev.RevColorSensorV3; +import com.qualcomm.hardware.rev.RevTouchSensor; +import com.qualcomm.robotcore.hardware.DcMotor; +import com.qualcomm.robotcore.hardware.DcMotorEx; +import com.qualcomm.robotcore.hardware.DcMotorSimple; +import com.qualcomm.robotcore.hardware.HardwareMap; +import com.qualcomm.robotcore.hardware.Servo; +import com.qualcomm.robotcore.hardware.configuration.typecontainers.MotorConfigurationType; + +import org.firstinspires.ftc.robotcore.external.hardware.camera.WebcamName; +import org.firstinspires.ftc.robotcore.external.matrices.OpenGLMatrix; +import org.firstinspires.ftc.robotcore.external.navigation.Position; +import org.firstinspires.ftc.robotcore.external.navigation.Velocity; +import org.firstinspires.ftc.robotcore.external.navigation.VuforiaLocalizer; +import org.firstinspires.ftc.robotcore.external.navigation.VuforiaTrackable; +import org.firstinspires.ftc.robotcore.external.navigation.VuforiaTrackables; +import org.firstinspires.ftc.robotcore.external.tfod.TFObjectDetector; +import org.timecrafters.TimeCraftersConfigurationTool.TimeCraftersConfiguration; +import org.timecrafters.UltimateGoal.Competition.Robot; + +import java.util.ArrayList; +import java.util.List; + + public class SampleRobotEx { + + private HardwareMap hardwareMap; + + public SampleRobotEx(HardwareMap hardwareMap) { + this.hardwareMap = hardwareMap; + } + + //The TimeCraftersConfiguration is part of a debugging and tuning tool that allows us to edit + //variables saved on the phone, without having to re-download the whole program. This is + //especially useful for autonomous route tuning + public TimeCraftersConfiguration stateConfiguration = new TimeCraftersConfiguration(); + + //We use the IMU to get reliable rotation and angular velocity information. Experimentation has + //demonstrated that the accelerometer and related integrations aren't as accurate. + public BNO055IMU imu; + + //The LEDs are used to provide driver feedback and for looking beautiful + public RevBlinkinLedDriver ledDriver; + + //drive and dead-wheal hardware + public DcMotor driveFrontLeft; + public DcMotor driveBackLeft; + public DcMotor driveFrontRight; + public DcMotor driveBackRight; + + public DcMotor encoderLeft; + public DcMotor encoderRight; + public DcMotor encoderBack; + + //Motion Constants + static final double CUBIC_CORRECTION = 0.035; + static final double FACE_CUBIC_CORRECTION = 0.025; + static final double LINEAR_CORRECTION = 0.055; + static final double FACE_MIN_CORRECTION = 0.2; + static final double FACE_LINEAR_CORRECTION = 0.025; + static final double MOMENTUM_CORRECTION = 1.05; + static final double MOMENTUM_MAX_CORRECTION = 1.4; + static final double MOMENTUM_HORIZONTAL_CORRECTION = + -(Math.log10(MOMENTUM_MAX_CORRECTION-1) / Math.log10(MOMENTUM_CORRECTION)); + static final double FACE_MOMENTUM_MAX_CORRECTION = 1.1; + static final double FACE_MOMENTUM_CORRECTION = 1.06; + static final double FACE_MOMENTUM_HORIZONTAL_CORRECTION = + -(Math.log10(FACE_MOMENTUM_MAX_CORRECTION-1) / Math.log10(FACE_MOMENTUM_CORRECTION)); + static final double ZERO_POWER_THRESHOLD = 0.25; + + //Unit Conversion Constants + static final double ENCODER_CIRCUMFERENCE = Math.PI * 2.3622; + static final int COUNTS_PER_REVOLUTION = 8192; + static final float mmPerInch = 25.4f; + static final double TICKS_PER_ROBOT_DEGREE_CLOCKWISE_FORWARD = 12.3; + static final double TICKS_PER_ROBOT_DEGREE_COUNTERCLOCKWISE_FORWARD = 18.8; + static final double TICKS_PER_ROBOT_DEGREE_CLOCKWISE = 8.4; + static final double TICKS_PER_ROBOT_DEGREE_COUNTERCLOCKWISE = 8.6; + + //Robot Localization + private static double locationX; + private static double locationY; + private static float rotation; + + private int encoderLeftPrevious = 0; + private int encoderBackPrevious = 0; + private int encoderRightPrevious = 0; + private float rotationPrevious = 0; + public float angularVelocity; + + public double forwardVector; + public double sidewaysVector; + + + //vuforia && tensorFlow Stuff + private WebcamName webcam; + private VuforiaLocalizer vuforia; + + // Inches Forward of axis of rotation + static final float CAMERA_FORWARD_DISPLACEMENT = 8f; + // Inches above Ground + static final float CAMERA_VERTICAL_DISPLACEMENT = 9.5f; + // Inches Left of axis of rotation + static final float CAMERA_LEFT_DISPLACEMENT = 4f; + + static final double CAMERA_DISPLACEMENT_MAG = + Math.hypot(CAMERA_FORWARD_DISPLACEMENT,CAMERA_LEFT_DISPLACEMENT); + static final float CAMERA_DISPLACEMENT_DIRECTION = + (float) -Math.atan(CAMERA_LEFT_DISPLACEMENT/CAMERA_FORWARD_DISPLACEMENT); + + public boolean trackableVisible; + private VuforiaTrackables targetsUltimateGoal; + private List trackables = new ArrayList(); + private OpenGLMatrix lastConfirmendLocation; + + private long timeStartZeroVelocity = 0; + private long minCheckDurationMs = 500; + private int minCheckVelocity = 1; + private float vuforiaRotationCull; + + //The servo mount for our camera allows us to look down for ideal TensorFlow and look up for + //ideal Vuforia Navigation + public Servo webCamServo; + public static final double CAM_SERVO_DOWN = 0.15; + + //TensorFlow Object Detection + public TFObjectDetector tfObjectDetector; + private static final float MINIMUM_CONFIDENCE = 0.8f; + + //Launcher + public DcMotor launchMotor; + public static final double LAUNCH_POWER = 0.715; + + private static final long LAUNCH_ACCEL_TIME = 500; + //These variables were originally going to be used in both autonomous and teleOp + public double launchPositionX; + public double launchPositionY; + public float launchRotation; + public int reduceLaunchPos; + + public boolean initLauncher; + + //Ring Intake + public DcMotor collectionMotor; + + //Ring Belt + public DcMotor ringBeltMotor; + public RevTouchSensor limitSwitch; + public int ringBeltStage; + public int ringBeltGap = 700; + public static final double RING_BELT_SLOW_POWER = 0.2; + public static final double RING_BELT_NORMAL_POWER = 0.6; + private int ringBeltPrev; + public long beltMaxStopTime; + public int beltReverseTicks; + public int beltMaxStopTicks; + + //Wobble Goal Arm & Grabber + public DcMotor wobbleArmMotor; + public Servo wobbleGrabServo; + public int wobbleDownPos; + public int wobbleUpPos; + public int wobbleDropPos; + public static final double WOBBLE_SERVO_OPEN = 0; + public static final double WOBBLE_SERVO_CLOSED = 1; + public RevColorSensorV3 wobbleColorSensor; + public double wobbleScoreX; + public double wobbleScoreY; + public RevTouchSensor wobbleTouchSensor; + + //Debugging + public double totalV; + private String TestingRecord = "Raw IMU, Delta, Saved"; + + public double traveledForward = 0; + public DcMotorEx motorAmpsTest; + + //All our hardware initialization in one place, for everything that is the same in TeleOp and + //Autonomous + public void initHardware() { + + //drive motors + driveFrontLeft = hardwareMap.dcMotor.get("driveFrontLeft"); + driveFrontRight = hardwareMap.dcMotor.get("driveFrontRight"); + driveBackLeft = hardwareMap.dcMotor.get("driveBackLeft"); + driveBackRight = hardwareMap.dcMotor.get("driveBackRight"); + + driveFrontLeft.setDirection(DcMotorSimple.Direction.FORWARD); + driveFrontRight.setDirection(DcMotorSimple.Direction.REVERSE); + driveBackLeft.setDirection(DcMotorSimple.Direction.FORWARD); + driveBackRight.setDirection(DcMotorSimple.Direction.REVERSE); + + //Localization encoders + encoderRight = hardwareMap.dcMotor.get("driveFrontRight"); + encoderBack = hardwareMap.dcMotor.get("driveFrontLeft"); + encoderLeft = hardwareMap.dcMotor.get("collect"); + + encoderRight.setMode(DcMotor.RunMode.STOP_AND_RESET_ENCODER); + encoderRight.setMode(DcMotor.RunMode.RUN_WITHOUT_ENCODER); + encoderBack.setMode(DcMotor.RunMode.STOP_AND_RESET_ENCODER); + encoderBack.setMode(DcMotor.RunMode.RUN_WITHOUT_ENCODER); + encoderLeft.setMode(DcMotor.RunMode.STOP_AND_RESET_ENCODER); + encoderLeft.setMode(DcMotor.RunMode.RUN_WITHOUT_ENCODER); + + //init wobble arm + wobbleArmMotor = hardwareMap.dcMotor.get("wobbleArm"); + wobbleArmMotor.setMode(DcMotor.RunMode.STOP_AND_RESET_ENCODER); + wobbleArmMotor.setTargetPosition(0); + wobbleArmMotor.setMode(DcMotor.RunMode.RUN_TO_POSITION); + + wobbleGrabServo = hardwareMap.servo.get("wobbleGrab"); + + wobbleColorSensor = hardwareMap.get(RevColorSensorV3.class, "color"); + wobbleTouchSensor = hardwareMap.get(RevTouchSensor.class, "touch"); + + + //init collection motor + collectionMotor = hardwareMap.dcMotor.get("collect"); + collectionMotor.setDirection(DcMotorSimple.Direction.REVERSE); + + //init ring belt + ringBeltMotor = hardwareMap.dcMotor.get("belt"); + ringBeltMotor.setMode(DcMotor.RunMode.STOP_AND_RESET_ENCODER); + ringBeltMotor .setMode(DcMotor.RunMode.RUN_USING_ENCODER); + + limitSwitch = hardwareMap.get(RevTouchSensor.class, "magLim"); + + //init IMU + imu = hardwareMap.get(BNO055IMU.class, "imu"); + + BNO055IMU.Parameters parameters = new BNO055IMU.Parameters(); + + parameters.mode = BNO055IMU.SensorMode.IMU; + parameters.angleUnit = BNO055IMU.AngleUnit.DEGREES; + parameters.accelUnit = BNO055IMU.AccelUnit.METERS_PERSEC_PERSEC; + parameters.loggingEnabled = false; + + imu.initialize(parameters); + + Velocity startVelocity = new Velocity(); + startVelocity.xVeloc = 0; + startVelocity.yVeloc = 0; + startVelocity.zVeloc = 0; + + Position startPosition = new Position(); + startPosition.x = 0; + startPosition.y = 0; + startPosition.z = 0; + + imu.startAccelerationIntegration(startPosition,startVelocity, 10); + + //Init Launch Motor + DcMotor launcher = hardwareMap.dcMotor.get("launcher"); + + MotorConfigurationType launchMotorType = launcher.getMotorType(); + launchMotorType.setGearing(3); + launchMotorType.setTicksPerRev(84); + launchMotorType.setMaxRPM(2400); + + launchMotor = launcher; + launchMotor.setMotorType(launchMotorType); + launchMotor.setMode(DcMotor.RunMode.RUN_USING_ENCODER); + launchMotor.setZeroPowerBehavior(DcMotor.ZeroPowerBehavior.FLOAT); + + ledDriver = hardwareMap.get(RevBlinkinLedDriver.class, "leds"); + } + + //Localization Function! This function is represented in a flow diagram, earlier in the + //software section + //run this in every exec to track the robot's location. + public void updateLocation(){ + + // orientation is inverted to have clockwise be positive. + float imuAngle = -imu.getAngularOrientation().firstAngle; + double rotationChange = getRelativeAngle(rotationPrevious, imuAngle); + + int encoderLeftCurrent = -encoderLeft.getCurrentPosition(); + int encoderRightCurrent = encoderRight.getCurrentPosition(); + int encoderBackCurrent = encoderBack.getCurrentPosition(); + + double encoderLeftChange = encoderLeftCurrent - encoderLeftPrevious; + double encoderRightChange = encoderRightCurrent - encoderRightPrevious; + double encoderBackChange = encoderBackCurrent - encoderBackPrevious; + + encoderLeftPrevious = encoderLeftCurrent; + encoderRightPrevious = encoderRightCurrent; + encoderBackPrevious = encoderBackCurrent; + rotationPrevious = imuAngle; + + //The forward Vector has the luxury of having an odometer on both sides of the robot. + //This allows us to reduce the unwanted influence of turning the robot by averaging + //the two. unfortunatly we the current positioning of the odometers + + //Since there isn't a second wheel to remove the influence of robot rotation, we have to + //instead do this by approximating the number of ticks that were removed due to rotation + //based on a separate calibration program. + + double ticksPerDegreeForward; + double ticksPerDegreeSideways; + + if (rotationChange < 0) { + ticksPerDegreeSideways = TICKS_PER_ROBOT_DEGREE_COUNTERCLOCKWISE; + ticksPerDegreeForward = TICKS_PER_ROBOT_DEGREE_COUNTERCLOCKWISE_FORWARD; + } else { + ticksPerDegreeSideways = TICKS_PER_ROBOT_DEGREE_CLOCKWISE; + ticksPerDegreeForward = TICKS_PER_ROBOT_DEGREE_CLOCKWISE_FORWARD; + } + + forwardVector = ((encoderLeftChange+encoderRightChange)/2) - + (rotationChange* ticksPerDegreeForward); + + sidewaysVector = encoderBackChange + (rotationChange * ticksPerDegreeSideways); + + double magnitude = Math.sqrt((forwardVector*forwardVector) + (sidewaysVector*sidewaysVector)); + double direction = Math.toRadians(SampleRobotEx.rotation + (rotationChange/2)) + + Math.atan2(sidewaysVector,forwardVector); + + double xChange = magnitude * (Math.sin(direction)); + double yChange = magnitude * (Math.cos(direction)); + + locationX += xChange; + locationY += yChange; + + SampleRobotEx.rotation += rotationChange; + SampleRobotEx.rotation = scaleAngleRange(SampleRobotEx.rotation); + + } + + public float getRotation() { + return SampleRobotEx.rotation; + } + + public double getLocationX() { + return SampleRobotEx.locationX; + } + + public double getLocationY() { + return SampleRobotEx.locationY; + } + + //This is meant to only be used to indicate starting positions and to reorient the robot. + public void setLocalization(float rotation, double x, double y) { + SampleRobotEx.rotation = rotation; + SampleRobotEx.locationX = x; + SampleRobotEx.locationY = y; + } + + //returns the angle from the robot's current position to the given target position. + public float getAngleToPosition (double x, double y) { + double differenceX = x- getLocationX(); + double differenceY = y- getLocationY(); + double angle = Math.toDegrees(Math.atan2(differenceX, differenceY )); + + return (float) angle; + } + + //Unit conversions + public double ticksToInches(double ticks) { + return ticks * (ENCODER_CIRCUMFERENCE / COUNTS_PER_REVOLUTION); + } + + public double inchesToTicks(double inches) { + return inches * (COUNTS_PER_REVOLUTION / ENCODER_CIRCUMFERENCE); + + } + + //Returns the shortest angle between two directions, with positive angles indicating that the + // reference is to the right (clockwise) of the current. Negative angles indicate that the + // reference is to the left. + public float getRelativeAngle(float reference, float current) { + return scaleAngleRange(current - reference); + } + + //Drive Functions + public void setDrivePower(double powerFrontLeft, double powerFrontRight, + double powerBackLeft, double powerBackRight){ + driveFrontLeft.setPower(powerFrontLeft); + driveFrontRight.setPower(powerFrontRight); + driveBackLeft.setPower(powerBackLeft); + driveBackRight.setPower(powerBackRight); + } + + public void setDrivePower(double[] powers){ + driveFrontLeft.setPower(powers[0]); + driveFrontRight.setPower(powers[1]); + driveBackLeft.setPower(powers[2]); + driveBackRight.setPower(powers[3]); + } + + //returns an array of the powers necessary to execute the provided motion. + //"degreesDirectionMotion" is the angle relative to the field that the robot should drive at. + //"degreesDirectionFace" is the angle the robot should face relative to the field. The order of + //the output powers is ForwardLeft, ForwardRight, BackLeft, BackRight + public double[] getMecanumPowers(float degreesDirectionMotion, double scalar, + float degreesDirectionFace) { + angularVelocity = imu.getAngularVelocity().xRotationRate; + + //calculating the base mecanum powers so that the robot drives along the degreesDirectionMotion + //once it is pointed towards the degreesDirectionFace + double rad = Math.toRadians(getRelativeAngle(degreesDirectionFace,degreesDirectionMotion)); + double y = Math.cos(rad); + double x = Math.sin(rad); + + double p = y + x; + double q = y - x; + + + + //calculating correction needed to steer the robot towards the degreesDirectionFace + float relativeRotation = + getRelativeAngle(degreesDirectionFace, SampleRobotEx.rotation); + double turnCorrection = + Math.pow(CUBIC_CORRECTION * relativeRotation, 3) + + LINEAR_CORRECTION * relativeRotation; + + if (relativeRotation != 0) { + double momentumRelative = angularVelocity * + (relativeRotation / Math.abs(relativeRotation)); + double exponential = + Math.pow(MOMENTUM_CORRECTION, MOMENTUM_HORIZONTAL_CORRECTION-momentumRelative); + double momentumCorrection = (MOMENTUM_MAX_CORRECTION*exponential)/(1+exponential); + //reduces concern for momentum when the angle is far away from target + turnCorrection *= momentumCorrection + ((Math.abs(relativeRotation) * + (1 - momentumCorrection)) / 180 ); + } + + double powerForwardRight = scalar * (q + turnCorrection); + double powerForwardLeft = scalar * (p - turnCorrection); + double powerBackRight = scalar * (p + turnCorrection); + double powerBackLeft = scalar * (q - turnCorrection); + + + // The "extreme" is the power value that is furthest from zero. When this values exceed the + // -1 to 1 power range, dividing the powers by the "extreme" scales everything back into the + // workable range without altering the final motion vector. + + double extreme = Math.max( + Math.max(Math.abs(powerForwardRight),Math.abs(powerForwardLeft)), + Math.max(Math.abs(powerBackRight),Math.abs(powerBackLeft))); + + if (extreme > 1) { + powerForwardRight = powerForwardRight/extreme; + powerForwardLeft = powerForwardLeft/extreme; + powerBackRight = powerBackRight/extreme; + powerBackLeft = powerBackLeft/extreme; + } + + double[] powers = {powerForwardLeft, powerForwardRight, powerBackLeft, powerBackRight}; + + double totalPower = Math.abs(powerForwardLeft) + + Math.abs(powerForwardRight) + + Math.abs(powerBackLeft) + + Math.abs(powerBackRight); + if (totalPower < ZERO_POWER_THRESHOLD) { + powers = new double[] {0,0,0,0}; + } + + + return powers; + } + //Outputs the power necessary to turn and face a provided direction + public double[] getFacePowers(float direction, double power) { + angularVelocity = imu.getAngularVelocity().xRotationRate; + double relativeAngle = getRelativeAngle(direction, SampleRobotEx.rotation); + double scaler = Math.pow(FACE_CUBIC_CORRECTION * relativeAngle, 3) + + FACE_LINEAR_CORRECTION * relativeAngle; + + if (relativeAngle > 0.5) { + scaler += FACE_MIN_CORRECTION; + } else if (relativeAngle < -0.5) { + scaler -= FACE_MIN_CORRECTION; + } + + if (relativeAngle != 0) { + double momentumRelative = angularVelocity * (relativeAngle / Math.abs(relativeAngle)); + double exponential = Math.pow(FACE_MOMENTUM_CORRECTION, + FACE_MOMENTUM_HORIZONTAL_CORRECTION-momentumRelative); + double momentumCorrection = (MOMENTUM_MAX_CORRECTION*exponential)/(1+exponential); + + scaler *= momentumCorrection; + } + + double left = -power * scaler; + double right = power *scaler; + + double[] powers = {left,right}; + + double totalPower = 2 * (Math.abs(left) + Math.abs(right)); + if (totalPower < ZERO_POWER_THRESHOLD) { + powers = new double[] {0,0}; + } + + return powers; + } + + public float scaleAngleRange(float angle) { + if (angle < -180) { + angle += 360; + } + if (angle > 180) { + angle -= 360; + } + return angle; + } + + } diff --git a/TeamCode/src/main/java/org/timecrafters/javaClass/samples/SpencerFirstEngine.java b/TeamCode/src/main/java/org/timecrafters/javaClass/samples/SpencerFirstEngine.java new file mode 100644 index 0000000..97f89bb --- /dev/null +++ b/TeamCode/src/main/java/org/timecrafters/javaClass/samples/SpencerFirstEngine.java @@ -0,0 +1,27 @@ +package org.timecrafters.javaClass.samples; + +import com.qualcomm.robotcore.eventloop.opmode.Autonomous; + +import org.cyberarm.engine.V2.CyberarmEngine; +import org.timecrafters.UltimateGoal.Competition.Robot; +import org.timecrafters.javaClass.aubrey.AubreyFirstState; +import org.timecrafters.javaClass.spencer.SpencerFirstState; + +@Autonomous (name = "Spencer: First Program", group = "spencer") +public class SpencerFirstEngine extends CyberarmEngine { + + SampleRobot robot; + + @Override + public void init() { + robot = new SampleRobot(hardwareMap); + robot.initHardware(); + robot.wobbleGrabServo.setPosition(Robot.WOBBLE_SERVO_CLOSED); + super.init(); + } + + @Override + public void setup() { + addState(new SpencerFirstState(robot)); + } +} diff --git a/TeamCode/src/main/java/org/timecrafters/javaClass/spencer/SpencerFirstState.java b/TeamCode/src/main/java/org/timecrafters/javaClass/spencer/SpencerFirstState.java new file mode 100644 index 0000000..b50d769 --- /dev/null +++ b/TeamCode/src/main/java/org/timecrafters/javaClass/spencer/SpencerFirstState.java @@ -0,0 +1,22 @@ +package org.timecrafters.javaClass.spencer; + +import org.cyberarm.engine.V2.CyberarmState; +import org.timecrafters.javaClass.samples.SampleRobot; + +public class SpencerFirstState extends CyberarmState { + + //here, you'll find some of your variables. you can add more as you need them. + private SampleRobot robot; + + //This is the constructor. It lets other code bits run use the code you put here + public SpencerFirstState(SampleRobot robot) { + this.robot = robot; + } + + //This is a method. methods are bits of code that can be run elsewhere. + //This one is set up to repeat every few milliseconds + @Override + public void exec() { + + } +} diff --git a/build.gradle b/build.gradle index 87f0507..8a2a157 100644 --- a/build.gradle +++ b/build.gradle @@ -15,7 +15,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:4.0.1' + classpath 'com.android.tools.build:gradle:4.1.2' } } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 530fb22..e399ab6 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Fri Jul 24 14:30:03 PDT 2020 +#Sat Jul 24 09:32:10 CDT 2021 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-bin.zip