pre-spring break
This commit is contained in:
@@ -15,6 +15,10 @@ import com.qualcomm.robotcore.hardware.Servo;
|
|||||||
import com.qualcomm.robotcore.hardware.CRServo;
|
import com.qualcomm.robotcore.hardware.CRServo;
|
||||||
import com.qualcomm.robotcore.hardware.SwitchableLight;
|
import com.qualcomm.robotcore.hardware.SwitchableLight;
|
||||||
|
|
||||||
|
|
||||||
|
import com.qualcomm.robotcore.hardware.ServoImplEx;
|
||||||
|
import com.qualcomm.robotcore.hardware.PwmControl;
|
||||||
|
|
||||||
import org.firstinspires.ftc.teamcode.teleOp.Constants;
|
import org.firstinspires.ftc.teamcode.teleOp.Constants;
|
||||||
import org.firstinspires.ftc.vision.apriltag.AprilTagDetection;
|
import org.firstinspires.ftc.vision.apriltag.AprilTagDetection;
|
||||||
|
|
||||||
@@ -35,10 +39,24 @@ public class hwMap {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static class LedHwMap {
|
public static class LedHwMap {
|
||||||
public org.firstinspires.ftc.teamcode.Prism.GoBildaPrismDriver led;
|
private ServoImplEx led;
|
||||||
|
|
||||||
public LedHwMap(HardwareMap hardwareMap) {
|
public LedHwMap(HardwareMap hardwareMap) {
|
||||||
//led = hardwareMap.get(org.firstinspires.ftc.teamcode.Prism.GoBildaPrismDriver.class, Constants.LEDConstants.LED);
|
|
||||||
|
led = hardwareMap.get(ServoImplEx.class, Constants.LEDConstants.LED);
|
||||||
|
led.setPwmRange(new PwmControl.PwmRange(500, 2500));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLedPos(double pos) {
|
||||||
|
led.setPosition(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLedOn(boolean yes) {
|
||||||
|
if (yes) {
|
||||||
|
led.setPwmEnable();
|
||||||
|
} else {
|
||||||
|
led.setPwmDisable();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -248,7 +266,7 @@ public class hwMap {
|
|||||||
private double lastKnownDistance = 0.0;
|
private double lastKnownDistance = 0.0;
|
||||||
private ElapsedTime noTargetTimer = new ElapsedTime();
|
private ElapsedTime noTargetTimer = new ElapsedTime();
|
||||||
|
|
||||||
PIDFCoefficients pidfCoefficients = new PIDFCoefficients(30, 0, 10, 15);
|
PIDFCoefficients pidfCoefficients = new PIDFCoefficients(10, 0, 11, 14.3);
|
||||||
|
|
||||||
public TurretHwMap(HardwareMap hardwareMap) {
|
public TurretHwMap(HardwareMap hardwareMap) {
|
||||||
noTargetTimer.reset();
|
noTargetTimer.reset();
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import com.pedropathing.follower.Follower;
|
|||||||
import com.pedropathing.geometry.BezierCurve;
|
import com.pedropathing.geometry.BezierCurve;
|
||||||
import com.pedropathing.geometry.BezierLine;
|
import com.pedropathing.geometry.BezierLine;
|
||||||
import com.pedropathing.geometry.Pose;
|
import com.pedropathing.geometry.Pose;
|
||||||
|
import com.pedropathing.math.Vector;
|
||||||
import com.pedropathing.paths.PathChain;
|
import com.pedropathing.paths.PathChain;
|
||||||
import com.pedropathing.util.Timer;
|
import com.pedropathing.util.Timer;
|
||||||
import com.qualcomm.robotcore.eventloop.opmode.Autonomous;
|
import com.qualcomm.robotcore.eventloop.opmode.Autonomous;
|
||||||
@@ -116,7 +117,7 @@ public class Auton {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void buildPaths() {
|
public void buildPaths() {
|
||||||
startPose = new Pose(31.5, 137, Math.toRadians(180));
|
startPose = new Pose(21, 124, Math.toRadians(143.5));
|
||||||
follower.setStartingPose(startPose);
|
follower.setStartingPose(startPose);
|
||||||
|
|
||||||
// Waypoints
|
// Waypoints
|
||||||
@@ -124,9 +125,9 @@ public class Auton {
|
|||||||
Pose set2DrivePose = new Pose(39, 60, Math.toRadians(180));
|
Pose set2DrivePose = new Pose(39, 60, Math.toRadians(180));
|
||||||
Pose set2PickPose = new Pose(14, 60, Math.toRadians(180)); // tangential
|
Pose set2PickPose = new Pose(14, 60, Math.toRadians(180)); // tangential
|
||||||
Pose set2ScorePose = new Pose(54, 90, Math.toRadians(144));
|
Pose set2ScorePose = new Pose(54, 90, Math.toRadians(144));
|
||||||
Pose gate1PickPose = new Pose(10.652, 61.079, Math.toRadians(140));
|
Pose gate1PickPose = new Pose(9, 60, Math.toRadians(143.5));
|
||||||
Pose gate1ScorePose = new Pose(54, 90, Math.toRadians(144));
|
Pose gate1ScorePose = new Pose(54, 90, Math.toRadians(144));
|
||||||
Pose gate2PickPose = new Pose(10.652, 61.079, Math.toRadians(140));
|
Pose gate2PickPose = new Pose(9, 60, Math.toRadians(143.5));
|
||||||
Pose gate2ScorePose = new Pose(54, 90, Math.toRadians(144));
|
Pose gate2ScorePose = new Pose(54, 90, Math.toRadians(144));
|
||||||
Pose set3DrivePose = new Pose(38.515, 47.156, Math.toRadians(220));
|
Pose set3DrivePose = new Pose(38.515, 47.156, Math.toRadians(220));
|
||||||
Pose set3PickPose = new Pose(16.419, 35.945, Math.toRadians(185));
|
Pose set3PickPose = new Pose(16.419, 35.945, Math.toRadians(185));
|
||||||
@@ -137,7 +138,6 @@ public class Auton {
|
|||||||
Pose parkTargetPose = new Pose(36.219, 93.170, Math.toRadians(148));
|
Pose parkTargetPose = new Pose(36.219, 93.170, Math.toRadians(148));
|
||||||
|
|
||||||
// Controls
|
// Controls
|
||||||
Pose preloadControl = new Pose(27.400, 115.541);
|
|
||||||
Pose set2ScoreControl = new Pose(50.386, 78.923);
|
Pose set2ScoreControl = new Pose(50.386, 78.923);
|
||||||
Pose gate1PickControl = new Pose(40.119, 55.595);
|
Pose gate1PickControl = new Pose(40.119, 55.595);
|
||||||
Pose gate1ScoreControl = new Pose(41.918, 62.187);
|
Pose gate1ScoreControl = new Pose(41.918, 62.187);
|
||||||
@@ -148,7 +148,7 @@ public class Auton {
|
|||||||
Pose set1PickControl = new Pose(14.863, 77.692);
|
Pose set1PickControl = new Pose(14.863, 77.692);
|
||||||
|
|
||||||
scorePreloadPath = follower.pathBuilder()
|
scorePreloadPath = follower.pathBuilder()
|
||||||
.addPath(new BezierCurve(startPose, preloadControl, preloadScorePose))
|
.addPath(new BezierLine(startPose, preloadScorePose))
|
||||||
.setLinearHeadingInterpolation(startPose.getHeading(), preloadScorePose.getHeading())
|
.setLinearHeadingInterpolation(startPose.getHeading(), preloadScorePose.getHeading())
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
@@ -319,7 +319,7 @@ public class Auton {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void buildPaths() {
|
public void buildPaths() {
|
||||||
startPose = new Pose(112.5, 137, Math.toRadians(0));
|
startPose = new Pose(122, 125.5, Math.toRadians(36));
|
||||||
follower.setStartingPose(startPose);
|
follower.setStartingPose(startPose);
|
||||||
|
|
||||||
// Waypoints
|
// Waypoints
|
||||||
@@ -327,9 +327,9 @@ public class Auton {
|
|||||||
Pose set2DrivePose = new Pose(105, 60, Math.toRadians(0));
|
Pose set2DrivePose = new Pose(105, 60, Math.toRadians(0));
|
||||||
Pose set2PickPose = new Pose(130, 60, Math.toRadians(0)); // tangential
|
Pose set2PickPose = new Pose(130, 60, Math.toRadians(0)); // tangential
|
||||||
Pose set2ScorePose = new Pose(90, 90, Math.toRadians(36));
|
Pose set2ScorePose = new Pose(90, 90, Math.toRadians(36));
|
||||||
Pose gate1PickPose = new Pose(133.348, 61.079, Math.toRadians(40));
|
Pose gate1PickPose = new Pose(132.7, 56, Math.toRadians(36));
|
||||||
Pose gate1ScorePose = new Pose(90, 90, Math.toRadians(36));
|
Pose gate1ScorePose = new Pose(90, 90, Math.toRadians(36));
|
||||||
Pose gate2PickPose = new Pose(133.348, 61.079, Math.toRadians(40));
|
Pose gate2PickPose = new Pose(132.7, 56, Math.toRadians(36));
|
||||||
Pose gate2ScorePose = new Pose(90, 90, Math.toRadians(36));
|
Pose gate2ScorePose = new Pose(90, 90, Math.toRadians(36));
|
||||||
Pose set3DrivePose = new Pose(105.485, 47.156, Math.toRadians(-40));
|
Pose set3DrivePose = new Pose(105.485, 47.156, Math.toRadians(-40));
|
||||||
Pose set3PickPose = new Pose(127.581, 35.945, Math.toRadians(-5));
|
Pose set3PickPose = new Pose(127.581, 35.945, Math.toRadians(-5));
|
||||||
@@ -442,8 +442,8 @@ public class Auton {
|
|||||||
protected final boolean isNet;
|
protected final boolean isNet;
|
||||||
protected final boolean useTimer;
|
protected final boolean useTimer;
|
||||||
|
|
||||||
public static double timerTimeout = 4;
|
public static double timerTimeout = 4.5;
|
||||||
public static double gateWaitTime = 3.0;
|
public static double gateWaitTime = 4.0;
|
||||||
|
|
||||||
protected Pose startPose;
|
protected Pose startPose;
|
||||||
|
|
||||||
@@ -517,8 +517,6 @@ public class Auton {
|
|||||||
hwMap.TransferHwMap transferHw = new hwMap.TransferHwMap(hardwareMap);
|
hwMap.TransferHwMap transferHw = new hwMap.TransferHwMap(hardwareMap);
|
||||||
hwMap.TurretHwMap turretHw = new hwMap.TurretHwMap(hardwareMap);
|
hwMap.TurretHwMap turretHw = new hwMap.TurretHwMap(hardwareMap);
|
||||||
|
|
||||||
turretHw.setPIDF(120, 0, 10, 15);
|
|
||||||
|
|
||||||
systems = new pedroStateMachine(intakeHw, transferHw, turretHw);
|
systems = new pedroStateMachine(intakeHw, transferHw, turretHw);
|
||||||
systems.setAlliance(allianceTarget);
|
systems.setAlliance(allianceTarget);
|
||||||
|
|
||||||
@@ -538,7 +536,7 @@ public class Auton {
|
|||||||
turretHw.resetTurret();
|
turretHw.resetTurret();
|
||||||
|
|
||||||
waitForStart();
|
waitForStart();
|
||||||
systems.update(allianceTarget, follower.getPose());
|
systems.update(allianceTarget, follower.getPose(), new Vector(0, 0));
|
||||||
opmodeTimer.resetTimer();
|
opmodeTimer.resetTimer();
|
||||||
setPathState(PathState.DRIVE_TO_SCORE_PRELOAD);
|
setPathState(PathState.DRIVE_TO_SCORE_PRELOAD);
|
||||||
|
|
||||||
@@ -548,7 +546,7 @@ public class Auton {
|
|||||||
}
|
}
|
||||||
follower.update();
|
follower.update();
|
||||||
statePathUpdate();
|
statePathUpdate();
|
||||||
systems.update(allianceTarget, follower.getPose());
|
systems.update(allianceTarget, follower.getPose(), follower.getVelocity());
|
||||||
|
|
||||||
telemetry.addData("Path State", pathState);
|
telemetry.addData("Path State", pathState);
|
||||||
telemetry.addData("System State", systems.getCurrentState());
|
telemetry.addData("System State", systems.getCurrentState());
|
||||||
|
|||||||
@@ -137,7 +137,7 @@ public abstract class TimeAuton extends LinearOpMode {
|
|||||||
timer.reset();
|
timer.reset();
|
||||||
while(opModeIsActive() && timer.seconds() < 2.0) {
|
while(opModeIsActive() && timer.seconds() < 2.0) {
|
||||||
updateSystems();
|
updateSystems();
|
||||||
if(turret.isTurretReady()) break;
|
if(turret.isTurretReady(true)) break;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -167,13 +167,13 @@ public abstract class TimeAuton extends LinearOpMode {
|
|||||||
AutoTransfer.updatePose(currentPose);
|
AutoTransfer.updatePose(currentPose);
|
||||||
|
|
||||||
// Update Turret with current Pose
|
// Update Turret with current Pose
|
||||||
turret.updateAuton(alliance, currentPose, 0.2);
|
turret.updateAuton(alliance, currentPose, follower.getVelocity(), 0.2);
|
||||||
|
|
||||||
transfer.updateTurretReady(turret.isTurretReady());
|
transfer.updateTurretReady(turret.isTurretReady(true));
|
||||||
transfer.update();
|
transfer.update();
|
||||||
|
|
||||||
// Telemetry for debugging
|
// Telemetry for debugging
|
||||||
telemetry.addData("Turret Ready", turret.isTurretReady());
|
telemetry.addData("Turret Ready", turret.isTurretReady(false));
|
||||||
telemetry.addData("Transfer State", transfer.getTransferState());
|
telemetry.addData("Transfer State", transfer.getTransferState());
|
||||||
telemetry.update();
|
telemetry.update();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package org.firstinspires.ftc.teamcode.auton;
|
package org.firstinspires.ftc.teamcode.auton;
|
||||||
|
|
||||||
import com.pedropathing.geometry.Pose;
|
import com.pedropathing.geometry.Pose;
|
||||||
|
import com.pedropathing.math.Vector;
|
||||||
|
|
||||||
import org.firstinspires.ftc.teamcode.Hware.hwMap;
|
import org.firstinspires.ftc.teamcode.Hware.hwMap;
|
||||||
import org.firstinspires.ftc.teamcode.subsystems.DriveTrain; // Unused but kept for reference
|
import org.firstinspires.ftc.teamcode.subsystems.DriveTrain; // Unused but kept for reference
|
||||||
@@ -88,8 +89,8 @@ public class pedroStateMachine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void update(int allianceTarget, Pose currentPose) {
|
public void update(int allianceTarget, Pose currentPose, Vector currentVelocity) {
|
||||||
m_turret.updateAuton(allianceTarget, currentPose, 0.2);
|
m_turret.updateAuton(allianceTarget, currentPose, currentVelocity, 0.2);
|
||||||
|
|
||||||
if (currentState == AutonState.SCORING) {
|
if (currentState == AutonState.SCORING) {
|
||||||
m_transfer.updateTurretReady(m_turret.hasReachedVelocity());
|
m_transfer.updateTurretReady(m_turret.hasReachedVelocity());
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ public class DriveTrain {
|
|||||||
public enum DriveState {
|
public enum DriveState {
|
||||||
NORMAL, TURBO, PRECISION, STOP
|
NORMAL, TURBO, PRECISION, STOP
|
||||||
}
|
}
|
||||||
private DriveState currentState = DriveState.NORMAL;
|
private DriveState currentState = DriveState.TURBO;
|
||||||
private double speedMultiplier = 1.0;
|
private double speedMultiplier = 1.0;
|
||||||
|
|
||||||
public DriveTrain(hwMap.DriveHwMap hardware) {
|
public DriveTrain(hwMap.DriveHwMap hardware) {
|
||||||
@@ -59,8 +59,8 @@ public class DriveTrain {
|
|||||||
if(dt == 0) dt = 0.001;
|
if(dt == 0) dt = 0.001;
|
||||||
lastLoopTime = currentTime;
|
lastLoopTime = currentTime;
|
||||||
|
|
||||||
double currentFwd = h_driveTrain.backRightMotor.getCurrentPosition();
|
double currentFwd = h_driveTrain.frontLeftMotor.getCurrentPosition();
|
||||||
double currentStrafe = h_driveTrain.frontLeftMotor.getCurrentPosition();
|
double currentStrafe = h_driveTrain.frontRightMotor.getCurrentPosition();
|
||||||
double currentHeading = getHeadingDegrees();
|
double currentHeading = getHeadingDegrees();
|
||||||
|
|
||||||
// 2. Calculate Errors
|
// 2. Calculate Errors
|
||||||
@@ -72,8 +72,6 @@ public class DriveTrain {
|
|||||||
while (errorTurn > 180) errorTurn -= 360;
|
while (errorTurn > 180) errorTurn -= 360;
|
||||||
while (errorTurn < -180) errorTurn += 360;
|
while (errorTurn < -180) errorTurn += 360;
|
||||||
|
|
||||||
// 3. PID Calculations
|
|
||||||
|
|
||||||
// Forward
|
// Forward
|
||||||
sumFwd += errorForward * dt;
|
sumFwd += errorForward * dt;
|
||||||
double dFwd = (errorForward - lastFwdErr) / dt;
|
double dFwd = (errorForward - lastFwdErr) / dt;
|
||||||
|
|||||||
@@ -1,36 +1,20 @@
|
|||||||
package org.firstinspires.ftc.teamcode.subsystems;
|
package org.firstinspires.ftc.teamcode.subsystems;
|
||||||
|
|
||||||
import org.firstinspires.ftc.robotcore.external.Const;
|
|
||||||
import org.firstinspires.ftc.teamcode.Hware.hwMap;
|
import org.firstinspires.ftc.teamcode.Hware.hwMap;
|
||||||
import org.firstinspires.ftc.teamcode.Prism.Color;
|
|
||||||
import org.firstinspires.ftc.teamcode.Prism.GoBildaPrismDriver.LayerHeight;
|
|
||||||
import org.firstinspires.ftc.teamcode.Prism.PrismAnimations;
|
|
||||||
import org.firstinspires.ftc.teamcode.teleOp.Constants;
|
import org.firstinspires.ftc.teamcode.teleOp.Constants;
|
||||||
|
|
||||||
public class LED {
|
public class LED {
|
||||||
private final hwMap.LedHwMap hardware;
|
private final hwMap.LedHwMap hardware;
|
||||||
|
|
||||||
// Track states to prevent spamming the I2C bus
|
|
||||||
private int currentLedState = -1;
|
private int currentLedState = -1;
|
||||||
|
|
||||||
// Reusable animations for efficiency
|
|
||||||
private final PrismAnimations.Solid solidRed = new PrismAnimations.Solid(Color.RED);
|
|
||||||
private final PrismAnimations.Solid solidOrange = new PrismAnimations.Solid(Color.ORANGE);
|
|
||||||
private final PrismAnimations.Solid solidYellow = new PrismAnimations.Solid(Color.YELLOW);
|
|
||||||
private final PrismAnimations.Solid solidGreen = new PrismAnimations.Solid(Color.GREEN);
|
|
||||||
|
|
||||||
public LED(hwMap.LedHwMap hardware) {
|
public LED(hwMap.LedHwMap hardware) {
|
||||||
this.hardware = hardware;
|
this.hardware = hardware;
|
||||||
|
turnOn();
|
||||||
int LED_BRIGHTNESS = Constants.LEDConstants.LAYER_BRIGHTNESS;
|
|
||||||
solidRed.setBrightness(LED_BRIGHTNESS);
|
|
||||||
solidOrange.setBrightness(LED_BRIGHTNESS);
|
|
||||||
solidYellow.setBrightness(LED_BRIGHTNESS);
|
|
||||||
solidGreen.setBrightness(LED_BRIGHTNESS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void update(boolean isTurretLocked, boolean isFlywheelUpToSpeed) {
|
public void update(boolean isTurretLocked, boolean isFlywheelUpToSpeed) {
|
||||||
/*int newLedState = 0;
|
int newLedState = 0;
|
||||||
|
|
||||||
if (isTurretLocked && isFlywheelUpToSpeed) {
|
if (isTurretLocked && isFlywheelUpToSpeed) {
|
||||||
newLedState = 1;
|
newLedState = 1;
|
||||||
@@ -42,15 +26,25 @@ public class LED {
|
|||||||
|
|
||||||
if (newLedState != currentLedState) {
|
if (newLedState != currentLedState) {
|
||||||
if (newLedState == 0) {
|
if (newLedState == 0) {
|
||||||
hardware.led.insertAndUpdateAnimation(LayerHeight.LAYER_0, solidRed);
|
hardware.setLedPos(Constants.LEDConstants.COLOR_RED);
|
||||||
} else if (newLedState == 1) {
|
} else if (newLedState == 1) {
|
||||||
hardware.led.insertAndUpdateAnimation(LayerHeight.LAYER_0, solidGreen);
|
hardware.setLedPos(Constants.LEDConstants.COLOR_GREEN);
|
||||||
} else if (newLedState == 2) {
|
} else if (newLedState == 2) {
|
||||||
hardware.led.insertAndUpdateAnimation(LayerHeight.LAYER_0, solidOrange);
|
hardware.setLedPos(Constants.LEDConstants.COLOR_ORANGE);
|
||||||
} else if (newLedState == 3) {
|
} else if (newLedState == 3) {
|
||||||
hardware.led.insertAndUpdateAnimation(LayerHeight.LAYER_0, solidYellow);
|
hardware.setLedPos(Constants.LEDConstants.COLOR_YELLOW);
|
||||||
}
|
}
|
||||||
|
|
||||||
currentLedState = newLedState;
|
currentLedState = newLedState;
|
||||||
}*/
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void turnOff() {
|
||||||
|
hardware.setLedOn(false);
|
||||||
|
currentLedState = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void turnOn() {
|
||||||
|
hardware.setLedOn(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -7,6 +7,8 @@ import com.qualcomm.robotcore.util.Range;
|
|||||||
import org.firstinspires.ftc.teamcode.Hware.hwMap;
|
import org.firstinspires.ftc.teamcode.Hware.hwMap;
|
||||||
import org.firstinspires.ftc.teamcode.teleOp.Constants;
|
import org.firstinspires.ftc.teamcode.teleOp.Constants;
|
||||||
|
|
||||||
|
import com.pedropathing.math.Vector;
|
||||||
|
|
||||||
public class Turret {
|
public class Turret {
|
||||||
|
|
||||||
private final hwMap.TurretHwMap hardware;
|
private final hwMap.TurretHwMap hardware;
|
||||||
@@ -24,11 +26,14 @@ public class Turret {
|
|||||||
private double targetCorrectionOffsetTicks = 0;
|
private double targetCorrectionOffsetTicks = 0;
|
||||||
private double fusedTargetTicks = 0;
|
private double fusedTargetTicks = 0;
|
||||||
public double turretPowerRotation;
|
public double turretPowerRotation;
|
||||||
public static double offsetTicks = 0.0;
|
private double offsetTicks = 0.0;
|
||||||
|
|
||||||
public double offsetHood = 0;
|
public double offsetHood = 0;
|
||||||
|
|
||||||
private Pose robotPose;
|
private Pose robotPose;
|
||||||
|
private Vector robotVelocity = new Vector(0,0); // NEW
|
||||||
|
private double kinematicDistanceOffset = 0.0; // NEW
|
||||||
|
private double kinematicAngularOffsetTicks = 0.0; // NEW
|
||||||
|
|
||||||
public double targetTick;
|
public double targetTick;
|
||||||
|
|
||||||
@@ -59,6 +64,7 @@ public class Turret {
|
|||||||
if (this.alliance != alliance) {
|
if (this.alliance != alliance) {
|
||||||
this.alliance = alliance;
|
this.alliance = alliance;
|
||||||
targetCorrectionOffsetTicks = 0; // Reset correction when alliance changes
|
targetCorrectionOffsetTicks = 0; // Reset correction when alliance changes
|
||||||
|
offsetTicks = 0; // Reset manual offset when alliance changes
|
||||||
if (alliance == 2) {
|
if (alliance == 2) {
|
||||||
hardware.setPipeline(Constants.TurretConstants.LIMELIGHT_PIPELINE_RED_TARGET);
|
hardware.setPipeline(Constants.TurretConstants.LIMELIGHT_PIPELINE_RED_TARGET);
|
||||||
} else if (alliance == 1) {
|
} else if (alliance == 1) {
|
||||||
@@ -108,17 +114,17 @@ public class Turret {
|
|||||||
return hardware.hasTarget();
|
return hardware.hasTarget();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void update(boolean manualTracking, boolean manualSAM, Pose currentPose, double elapsedTime) {
|
public void update(boolean manualTracking, boolean manualSAM, Pose currentPose, Vector currentVelocity, double elapsedTime) {
|
||||||
double dt = loopTimer.seconds();
|
double dt = loopTimer.seconds();
|
||||||
loopTimer.reset();
|
loopTimer.reset();
|
||||||
if (dt < 0.001) dt = 0.001;
|
if (dt < 0.001) dt = 0.001;
|
||||||
|
|
||||||
updatePose(currentPose);
|
updatePose(currentPose, currentVelocity);
|
||||||
|
|
||||||
double rawTicks = hardware.getTurretRotationPosition();
|
double rawTicks = hardware.getTurretRotationPosition();
|
||||||
double currentDegrees = rawTicks / Constants.TurretConstants.TICKS_PER_DEGREE;
|
double currentDegrees = rawTicks / Constants.TurretConstants.TICKS_PER_DEGREE;
|
||||||
|
|
||||||
distance = getDistance();
|
distance = getDistance() + kinematicDistanceOffset;
|
||||||
|
|
||||||
if (!manualTracking) {
|
if (!manualTracking) {
|
||||||
calculateHybridTarget(currentPose, currentDegrees, rawTicks);
|
calculateHybridTarget(currentPose, currentDegrees, rawTicks);
|
||||||
@@ -131,19 +137,21 @@ public class Turret {
|
|||||||
handleLaunchLogic(elapsedTime);
|
handleLaunchLogic(elapsedTime);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// idleLaunch();
|
idleLaunch();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public void idleLaunch() {
|
public void idleLaunch() {
|
||||||
hardware.setTurretVelocity(1000);
|
hardware.setTurretVelocity(1300);
|
||||||
|
|
||||||
double calculatedHoodPos = getHoodPOS(65);
|
double calculatedHoodPos = getHoodPOS(65);
|
||||||
setHoodPos(calculatedHoodPos);
|
setHoodPos(calculatedHoodPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateAuton(int alliance, Pose currentPose, double offset) {
|
public void updateAuton(int alliance, Pose currentPose, Vector currentVelocity, double offset) {
|
||||||
updatePose(currentPose);
|
updatePose(currentPose, currentVelocity); // Updated
|
||||||
double dt = loopTimer.seconds();
|
double dt = loopTimer.seconds();
|
||||||
loopTimer.reset();
|
loopTimer.reset();
|
||||||
if (dt < 0.001) dt = 0.001;
|
if (dt < 0.001) dt = 0.001;
|
||||||
@@ -158,11 +166,11 @@ public class Turret {
|
|||||||
double rawTicks = hardware.getTurretRotationPosition();
|
double rawTicks = hardware.getTurretRotationPosition();
|
||||||
double currentDegrees = rawTicks / Constants.TurretConstants.TICKS_PER_DEGREE;
|
double currentDegrees = rawTicks / Constants.TurretConstants.TICKS_PER_DEGREE;
|
||||||
|
|
||||||
distance = getDistance();
|
distance = getDistance() + kinematicDistanceOffset;
|
||||||
|
|
||||||
calculateHybridTarget(currentPose, currentDegrees, rawTicks);
|
calculateHybridTarget(currentPose, currentDegrees, rawTicks);
|
||||||
runPIDControl(rawTicks, dt);
|
runPIDControl(rawTicks, dt);
|
||||||
handleLaunchLogicOffset(-offset);
|
handleLaunchLogicOffset(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleLaunchLogic(double elapsedTime) {
|
private void handleLaunchLogic(double elapsedTime) {
|
||||||
@@ -170,11 +178,6 @@ public class Turret {
|
|||||||
double baseVelocity = getFlywheelVelocity(distance);
|
double baseVelocity = getFlywheelVelocity(distance);
|
||||||
double t = stateTimer.seconds();
|
double t = stateTimer.seconds();
|
||||||
|
|
||||||
/* TUNING GUIDE:
|
|
||||||
* 1. Adjust ARTIFACT_1_WINDOW and ARTIFACT_2_WINDOW in Constants.java to match your launch sequence timing.
|
|
||||||
* 2. Adjust ARTIFACT_OFFSET_LOW to lower the velocity for the 1st and 3rd artifacts.
|
|
||||||
* 3. ARTIFACT_OFFSET_NORMAL (usually 0) is for the 2nd artifact.
|
|
||||||
*/
|
|
||||||
double compensation;
|
double compensation;
|
||||||
if (t < Constants.TurretConstants.ARTIFACT_1_WINDOW) {
|
if (t < Constants.TurretConstants.ARTIFACT_1_WINDOW) {
|
||||||
compensation = Constants.TurretConstants.ARTIFACT_1;
|
compensation = Constants.TurretConstants.ARTIFACT_1;
|
||||||
@@ -190,7 +193,7 @@ public class Turret {
|
|||||||
double calculatedHoodPos = getHoodPOS(distance);
|
double calculatedHoodPos = getHoodPOS(distance);
|
||||||
double currentVel = hardware.getFlywheelVelocities()[1];
|
double currentVel = hardware.getFlywheelVelocities()[1];
|
||||||
|
|
||||||
double recoilOffset = (currentVel - targetVelocity) * -0.000185;
|
double recoilOffset = (currentVel - targetVelocity) * -0.000385;
|
||||||
|
|
||||||
setHoodPos(calculatedHoodPos + recoilOffset - 0.03);
|
setHoodPos(calculatedHoodPos + recoilOffset - 0.03);
|
||||||
} else {
|
} else {
|
||||||
@@ -218,7 +221,7 @@ public class Turret {
|
|||||||
double calculatedHoodPos = getHoodPOS(distance);
|
double calculatedHoodPos = getHoodPOS(distance);
|
||||||
double currentVel = hardware.getFlywheelVelocities()[1];
|
double currentVel = hardware.getFlywheelVelocities()[1];
|
||||||
|
|
||||||
double recoilOffset = (currentVel - targetVelocity) * -0.000185;
|
double recoilOffset = (currentVel - targetVelocity) * -0.000385;
|
||||||
|
|
||||||
setHoodPos(calculatedHoodPos + recoilOffset);
|
setHoodPos(calculatedHoodPos + recoilOffset);
|
||||||
} else {
|
} else {
|
||||||
@@ -226,21 +229,27 @@ public class Turret {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private void calculateHybridTarget(Pose robotPose, double currentDegrees, double currentTicks) {
|
private void calculateHybridTarget(Pose robotPose, double currentDegrees, double currentTicks) {
|
||||||
double odoTargetTicks = calculateOdometryTargetTicks(robotPose);
|
double odoTargetTicks = calculateOdometryTargetTicks(robotPose);
|
||||||
LLResult result = hardware.getLimelightResult();
|
LLResult result = hardware.getLimelightResult();
|
||||||
|
|
||||||
if (result != null && result.isValid()) {
|
if (result != null && result.isValid()) {
|
||||||
// 1. Calculate Vision Truth: Where the goal sits based on the camera right now
|
|
||||||
double tx = result.getTx();
|
double tx = result.getTx();
|
||||||
double visionTargetDegrees = currentDegrees + (tx * Constants.TurretConstants.LL_LOGIC_MULTIPLIER);
|
double visionTargetDegrees = currentDegrees + (tx * Constants.TurretConstants.LL_LOGIC_MULTIPLIER);
|
||||||
double finalVisionDegrees = visionTargetDegrees + Constants.TurretConstants.LL_TARGET_OFFSET_DEGREES;
|
double finalVisionDegrees = visionTargetDegrees + Constants.TurretConstants.LL_TARGET_OFFSET_DEGREES;
|
||||||
double visionTargetTicks = finalVisionDegrees * Constants.TurretConstants.TICKS_PER_DEGREE;
|
double visionTargetTicks = finalVisionDegrees * Constants.TurretConstants.TICKS_PER_DEGREE;
|
||||||
|
|
||||||
// 2. Calculate Current Fused Target: Where we currently think the goal is (Odo + existing Offset)
|
visionTargetTicks += kinematicAngularOffsetTicks;
|
||||||
|
|
||||||
|
// Shift the vision target by our manual offset so LL doesn't fight it
|
||||||
|
double visionTargetWithManualOffset = visionTargetTicks + offsetTicks;
|
||||||
|
|
||||||
double currentFusedTarget = odoTargetTicks + targetCorrectionOffsetTicks;
|
double currentFusedTarget = odoTargetTicks + targetCorrectionOffsetTicks;
|
||||||
|
|
||||||
double correctionError = visionTargetTicks - currentFusedTarget;
|
double correctionError = visionTargetWithManualOffset - currentFusedTarget;
|
||||||
|
|
||||||
// 4. Normalize the error for wrapping (360 degrees)
|
// 4. Normalize the error for wrapping (360 degrees)
|
||||||
double ticksPerRev = 360.0 * Constants.TurretConstants.TICKS_PER_DEGREE;
|
double ticksPerRev = 360.0 * Constants.TurretConstants.TICKS_PER_DEGREE;
|
||||||
@@ -277,21 +286,19 @@ public class Turret {
|
|||||||
|
|
||||||
while (relativeRad > Math.PI) relativeRad -= (2 * Math.PI);
|
while (relativeRad > Math.PI) relativeRad -= (2 * Math.PI);
|
||||||
while (relativeRad < -Math.PI) relativeRad += (2 * Math.PI);
|
while (relativeRad < -Math.PI) relativeRad += (2 * Math.PI);
|
||||||
|
|
||||||
double relativeDegrees = Math.toDegrees(relativeRad);
|
double relativeDegrees = Math.toDegrees(relativeRad);
|
||||||
double staticOffset = (alliance == 2) ? Constants.TurretConstants.RED_TARGET_OFFSET_DEGREES : Constants.TurretConstants.BLUE_TARGET_OFFSET_DEGREES;
|
double staticOffset = (alliance == 2) ? Constants.TurretConstants.RED_TARGET_OFFSET_DEGREES : Constants.TurretConstants.BLUE_TARGET_OFFSET_DEGREES;
|
||||||
|
|
||||||
return (relativeDegrees + staticOffset) * Constants.TurretConstants.TICKS_PER_DEGREE;
|
// APPLY THE KINEMATIC SHIFT
|
||||||
|
return ((relativeDegrees + staticOffset) * Constants.TurretConstants.TICKS_PER_DEGREE) + kinematicAngularOffsetTicks;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void runPIDControl(double currentTicks, double dt) {
|
private void runPIDControl(double currentTicks, double dt) {
|
||||||
fusedTargetTicks = fusedTargetTicks + offsetTicks;
|
|
||||||
double error = fusedTargetTicks - currentTicks;
|
double error = fusedTargetTicks - currentTicks;
|
||||||
double derivative = (error - lastError) / dt;
|
double derivative = (error - lastError) / dt;
|
||||||
|
|
||||||
// Hysteresis thresholds for mode switching
|
double entryThreshold = 10;
|
||||||
double entryThreshold = 15; // Enter hold mode if error is within this range
|
double exitThreshold = 30;
|
||||||
double exitThreshold = 30; // Exit hold mode if error exceeds this range
|
|
||||||
|
|
||||||
if (!turretModeHold && Math.abs(error) <= entryThreshold) {
|
if (!turretModeHold && Math.abs(error) <= entryThreshold) {
|
||||||
turretModeHold = true;
|
turretModeHold = true;
|
||||||
@@ -302,7 +309,7 @@ public class Turret {
|
|||||||
if (turretModeHold) {
|
if (turretModeHold) {
|
||||||
if (lastTurretModeHold != turretModeHold) {
|
if (lastTurretModeHold != turretModeHold) {
|
||||||
hardware.runToPos((int) fusedTargetTicks); // Set target first
|
hardware.runToPos((int) fusedTargetTicks); // Set target first
|
||||||
hardware.enableTurretHold(); // Then set mode
|
hardware.enableTurretHold();
|
||||||
hardware.setTurretRotationPower(Constants.TurretConstants.TURRET_HOLD_POWER); // Set a holding power
|
hardware.setTurretRotationPower(Constants.TurretConstants.TURRET_HOLD_POWER); // Set a holding power
|
||||||
}
|
}
|
||||||
hardware.runToPos((int) fusedTargetTicks); // Keep target updated even in hold mode
|
hardware.runToPos((int) fusedTargetTicks); // Keep target updated even in hold mode
|
||||||
@@ -337,20 +344,60 @@ public class Turret {
|
|||||||
double absTarget = Math.abs(targetVelocity);
|
double absTarget = Math.abs(targetVelocity);
|
||||||
|
|
||||||
double error = Math.abs(absCurrent - absTarget);
|
double error = Math.abs(absCurrent - absTarget);
|
||||||
double tolerance = absTarget * 0.03;
|
double tolerance = absTarget * 0.05;
|
||||||
|
|
||||||
return error <= tolerance;
|
return error <= tolerance;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isTurretReady() {
|
public boolean isTurretReady(boolean isAuton) {
|
||||||
return hasReachedVelocity() && isTurretRotationLocked();
|
|
||||||
|
if (!isAuton) return hasReachedVelocity() && isTurretRotationLocked();
|
||||||
|
else return hasReachedVelocity();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void updatePose(Pose robotPose) {
|
public void updatePose(Pose robotPose) { // Fallback if called somewhere else without velocity
|
||||||
|
updatePose(robotPose, new Vector(0,0));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updatePose(Pose robotPose, Vector robotVelocity) {
|
||||||
this.robotPose = robotPose;
|
this.robotPose = robotPose;
|
||||||
|
this.robotVelocity = robotVelocity != null ? robotVelocity : new Vector(0,0);
|
||||||
|
calculateKinematicOffsets();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void calculateKinematicOffsets() {
|
||||||
|
if (robotPose == null || robotVelocity == null) {
|
||||||
|
kinematicDistanceOffset = 0;
|
||||||
|
kinematicAngularOffsetTicks = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
double targetX = (alliance == 2) ? Constants.TurretConstants.GOAL_RED_X : Constants.TurretConstants.GOAL_BLUE_X;
|
||||||
|
double targetY = (alliance == 2) ? Constants.TurretConstants.GOAL_RED_Y : Constants.TurretConstants.GOAL_BLUE_Y;
|
||||||
|
|
||||||
|
double virtualX = targetX - (robotVelocity.getXComponent() * Constants.TurretConstants.SHOT_TIME_OF_FLIGHT);
|
||||||
|
double virtualY = targetY - (robotVelocity.getYComponent() * Constants.TurretConstants.SHOT_TIME_OF_FLIGHT);
|
||||||
|
|
||||||
|
double realDx = targetX - robotPose.getX();
|
||||||
|
double realDy = targetY - robotPose.getY();
|
||||||
|
double virtualDx = virtualX - robotPose.getX();
|
||||||
|
double virtualDy = virtualY - robotPose.getY();
|
||||||
|
|
||||||
|
double realDistance = Math.hypot(realDx, realDy);
|
||||||
|
double virtualDistance = Math.hypot(virtualDx, virtualDy);
|
||||||
|
kinematicDistanceOffset = virtualDistance - realDistance;
|
||||||
|
|
||||||
|
double realAngle = Math.atan2(realDy, realDx);
|
||||||
|
double virtualAngle = Math.atan2(virtualDy, virtualDx);
|
||||||
|
|
||||||
|
double angleDiff = virtualAngle - realAngle;
|
||||||
|
while (angleDiff > Math.PI) angleDiff -= (2 * Math.PI);
|
||||||
|
while (angleDiff < -Math.PI) angleDiff += (2 * Math.PI);
|
||||||
|
|
||||||
|
kinematicAngularOffsetTicks = Math.toDegrees(angleDiff) * Constants.TurretConstants.TICKS_PER_DEGREE;
|
||||||
}
|
}
|
||||||
|
|
||||||
public double getDistance() {
|
public double getDistance() {
|
||||||
@@ -375,7 +422,11 @@ public class Turret {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private double getFlywheelVelocity(double dist) {
|
private double getFlywheelVelocity(double dist) {
|
||||||
return (0.0000433916 * Math.pow((dist), 4) - 0.0090065 * Math.pow(dist, 3) + 0.588434 * Math.pow(dist, 2) + (-7.67701 * dist) + 1485.89126);
|
return (-0.0000144121 * Math.pow(dist, 4)
|
||||||
|
+ 0.00398607 * Math.pow(dist, 3)
|
||||||
|
- 0.342198 * Math.pow(dist, 2)
|
||||||
|
+ (16.43014 * dist)
|
||||||
|
+ 1198.24434);
|
||||||
}
|
}
|
||||||
|
|
||||||
private double getHoodPOS(double dist) {
|
private double getHoodPOS(double dist) {
|
||||||
@@ -392,6 +443,7 @@ public class Turret {
|
|||||||
|
|
||||||
public void updateOffsetTicks(double change) {
|
public void updateOffsetTicks(double change) {
|
||||||
offsetTicks += change;
|
offsetTicks += change;
|
||||||
|
targetCorrectionOffsetTicks += change;
|
||||||
}
|
}
|
||||||
|
|
||||||
public double getTurretPower() {
|
public double getTurretPower() {
|
||||||
@@ -407,11 +459,11 @@ public class Turret {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void resetTurret() {
|
public void resetTurret() {
|
||||||
hardware.resetTurret();
|
hardware.resetTurret();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isTurretRotationLocked() {
|
public boolean isTurretRotationLocked() {
|
||||||
return turretModeHold && Math.abs(lastError) <= 10;
|
return turretModeHold && Math.abs(lastError) <= 10;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -40,8 +40,12 @@ public class Constants {
|
|||||||
|
|
||||||
public static class LEDConstants {
|
public static class LEDConstants {
|
||||||
public static final String LED = "prism";
|
public static final String LED = "prism";
|
||||||
public static final int LAYER_BRIGHTNESS = 50;
|
|
||||||
|
|
||||||
|
// TODO: Tune these!
|
||||||
|
public static final double COLOR_RED = 0.28;
|
||||||
|
public static final double COLOR_GREEN = 0.45;
|
||||||
|
public static final double COLOR_ORANGE = 0.32;
|
||||||
|
public static final double COLOR_YELLOW = 0.38;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -93,7 +97,7 @@ public class Constants {
|
|||||||
|
|
||||||
public static final double UNLOCK_POS = 0.82;
|
public static final double UNLOCK_POS = 0.82;
|
||||||
|
|
||||||
public static double launch_duration = 0.77;
|
public static double launch_duration = 0.9;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,8 +126,8 @@ public class Constants {
|
|||||||
|
|
||||||
public static final DcMotorSimple.Direction TURRET_ROTATION_DIR = DcMotorSimple.Direction.FORWARD;
|
public static final DcMotorSimple.Direction TURRET_ROTATION_DIR = DcMotorSimple.Direction.FORWARD;
|
||||||
|
|
||||||
public static double SOFT_LIMIT_NEG = -324;
|
public static double SOFT_LIMIT_NEG = -370;
|
||||||
public static double SOFT_LIMIT_POS = 195;
|
public static double SOFT_LIMIT_POS = 370;
|
||||||
|
|
||||||
public static final double HOOD_POS_CLOSE = 0.3;
|
public static final double HOOD_POS_CLOSE = 0.3;
|
||||||
public static final double HOOD_POS_FAR = 0.7;
|
public static final double HOOD_POS_FAR = 0.7;
|
||||||
@@ -167,13 +171,15 @@ public class Constants {
|
|||||||
// Artifact Compensation Tuning
|
// Artifact Compensation Tuning
|
||||||
// Lower (negative offset) for 1st and 3rd, Normal (0 offset) for 2
|
// Lower (negative offset) for 1st and 3rd, Normal (0 offset) for 2
|
||||||
public static double ARTIFACT_1 = -95.0;
|
public static double ARTIFACT_1 = -95.0;
|
||||||
public static double ARTIFACT_2 = 20.0;
|
public static double ARTIFACT_2 = 45.0;
|
||||||
|
|
||||||
public static double ARTIFACT_3 = -20.0;
|
public static double ARTIFACT_3 = 20.0;
|
||||||
|
|
||||||
// Timing Windows (seconds)
|
// Timing Windows (seconds)
|
||||||
public static double ARTIFACT_1_WINDOW = 0.35;
|
public static double ARTIFACT_1_WINDOW = 0.35;
|
||||||
public static double ARTIFACT_2_WINDOW = 0.55;
|
public static double ARTIFACT_2_WINDOW = 0.55;
|
||||||
|
|
||||||
|
public static double SHOT_TIME_OF_FLIGHT = 0.83;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -12,10 +12,15 @@ import org.firstinspires.ftc.teamcode.subsystems.Intake;
|
|||||||
import org.firstinspires.ftc.teamcode.subsystems.TransferSys;
|
import org.firstinspires.ftc.teamcode.subsystems.TransferSys;
|
||||||
import org.firstinspires.ftc.teamcode.util.AutoTransfer;
|
import org.firstinspires.ftc.teamcode.util.AutoTransfer;
|
||||||
import org.firstinspires.ftc.teamcode.util.FPSCounter;
|
import org.firstinspires.ftc.teamcode.util.FPSCounter;
|
||||||
|
|
||||||
import com.qualcomm.hardware.lynx.LynxModule;
|
import com.qualcomm.hardware.lynx.LynxModule;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.pedropathing.math.Vector;
|
||||||
|
|
||||||
import com.qualcomm.robotcore.hardware.VoltageSensor;
|
import com.qualcomm.robotcore.hardware.VoltageSensor;
|
||||||
|
|
||||||
public class SOLOTeleOP {
|
public class SOLOTeleOP {
|
||||||
|
|
||||||
@TeleOp(name = "Red SOLO", group = "FINAL")
|
@TeleOp(name = "Red SOLO", group = "FINAL")
|
||||||
@@ -24,6 +29,7 @@ public class SOLOTeleOP {
|
|||||||
super(2);
|
super(2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TeleOp(name = "Blue SOLO", group = "FINAL")
|
@TeleOp(name = "Blue SOLO", group = "FINAL")
|
||||||
public static class BlueSOLO extends BaseSoloTeleOp {
|
public static class BlueSOLO extends BaseSoloTeleOp {
|
||||||
public BlueSOLO() {
|
public BlueSOLO() {
|
||||||
@@ -96,8 +102,9 @@ public class SOLOTeleOP {
|
|||||||
|
|
||||||
follower.update();
|
follower.update();
|
||||||
Pose currentPose = follower.getPose();
|
Pose currentPose = follower.getPose();
|
||||||
|
Vector currentVelocity = follower.getVelocity();
|
||||||
|
|
||||||
stateMachine.update(false, false, currentPose);
|
stateMachine.update(false, false, currentPose, currentVelocity);
|
||||||
|
|
||||||
|
|
||||||
handleGlobalLogic();
|
handleGlobalLogic();
|
||||||
@@ -173,9 +180,12 @@ public class SOLOTeleOP {
|
|||||||
|
|
||||||
private void handleDriverControls() {
|
private void handleDriverControls() {
|
||||||
|
|
||||||
if (gamepad1.dpad_up) stateMachine.getDriveTrain().setDriveState(DriveTrain.DriveState.TURBO);
|
if (gamepad1.dpad_up)
|
||||||
else if (gamepad1.dpad_left) stateMachine.getDriveTrain().setDriveState(DriveTrain.DriveState.NORMAL);
|
stateMachine.getDriveTrain().setDriveState(DriveTrain.DriveState.TURBO);
|
||||||
else if (gamepad1.dpad_down) stateMachine.getDriveTrain().setDriveState(DriveTrain.DriveState.PRECISION);
|
else if (gamepad1.dpad_left)
|
||||||
|
stateMachine.getDriveTrain().setDriveState(DriveTrain.DriveState.NORMAL);
|
||||||
|
else if (gamepad1.dpad_down)
|
||||||
|
stateMachine.getDriveTrain().setDriveState(DriveTrain.DriveState.PRECISION);
|
||||||
|
|
||||||
if (stateMachine.getCurrentGameState() != GameState.SCORING) {
|
if (stateMachine.getCurrentGameState() != GameState.SCORING) {
|
||||||
if (gamepad1.right_trigger > 0.1) {
|
if (gamepad1.right_trigger > 0.1) {
|
||||||
@@ -193,18 +203,19 @@ public class SOLOTeleOP {
|
|||||||
if (gamepad1.yWasPressed()) {
|
if (gamepad1.yWasPressed()) {
|
||||||
isScoringActive = !isScoringActive;
|
isScoringActive = !isScoringActive;
|
||||||
if (isScoringActive) stateMachine.setGameState(GameState.SCORING);
|
if (isScoringActive) stateMachine.setGameState(GameState.SCORING);
|
||||||
else if (stateMachine.getCurrentGameState() == GameState.SCORING) stateMachine.setGameState(GameState.IDLE);
|
else if (stateMachine.getCurrentGameState() == GameState.SCORING)
|
||||||
|
stateMachine.setGameState(GameState.IDLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gamepad1.right_bumper) stateMachine.getTurret().updateOffsetTicks(0.2);
|
if (gamepad1.right_bumper) stateMachine.getTurret().updateOffsetTicks(3);
|
||||||
if (gamepad1.left_bumper) stateMachine.getTurret().updateOffsetTicks(-0.2);
|
if (gamepad1.left_bumper) stateMachine.getTurret().updateOffsetTicks(-3);
|
||||||
|
|
||||||
if (gamepad1.aWasPressed()) {
|
if (gamepad1.aWasPressed()) {
|
||||||
stateMachine.forceLaunchSequence();
|
stateMachine.forceLaunchSequence();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateTelemetry(Pose p) {
|
private void updateTelemetry(Pose p) {
|
||||||
telemetry.addData("OpMode", "SOLO TeleOp");
|
telemetry.addData("OpMode", "SOLO TeleOp");
|
||||||
telemetry.addData("Avg FPS", "%.2f", fpsCounter.getAverageFps());
|
telemetry.addData("Avg FPS", "%.2f", fpsCounter.getAverageFps());
|
||||||
|
|
||||||
@@ -220,10 +231,10 @@ public class SOLOTeleOP {
|
|||||||
telemetry.addLine("▰▰▰▰▰▰▰ TRACKING ▰▰▰▰▰▰▰");
|
telemetry.addLine("▰▰▰▰▰▰▰ TRACKING ▰▰▰▰▰▰▰");
|
||||||
telemetry.addData("Pose", "X:%.1f Y:%.1f H:%.1f°", p.getX(), p.getY(), Math.toDegrees(p.getHeading()));
|
telemetry.addData("Pose", "X:%.1f Y:%.1f H:%.1f°", p.getX(), p.getY(), Math.toDegrees(p.getHeading()));
|
||||||
telemetry.addData("Distance", "%.1f in", stateMachine.getTurret().getDistance());
|
telemetry.addData("Distance", "%.1f in", stateMachine.getTurret().getDistance());
|
||||||
telemetry.addData("Turret Ready", stateMachine.getTurret().isTurretReady());
|
telemetry.addData("Turret Ready", stateMachine.getTurret().isTurretReady(false));
|
||||||
telemetry.addData("Target Tick", stateMachine.getTurret().targetTick);
|
telemetry.addData("Target Tick", stateMachine.getTurret().targetTick);
|
||||||
|
|
||||||
telemetry.update();
|
telemetry.update();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,9 @@
|
|||||||
package org.firstinspires.ftc.teamcode.teleOp;
|
package org.firstinspires.ftc.teamcode.teleOp;
|
||||||
|
|
||||||
import com.pedropathing.geometry.Pose; // ADDED
|
import com.pedropathing.geometry.Pose; // ADDED
|
||||||
|
import com.pedropathing.math.Vector;
|
||||||
import com.qualcomm.robotcore.hardware.HardwareMap;
|
import com.qualcomm.robotcore.hardware.HardwareMap;
|
||||||
|
import com.qualcomm.robotcore.util.ElapsedTime;
|
||||||
|
|
||||||
import org.firstinspires.ftc.teamcode.Hware.hwMap;
|
import org.firstinspires.ftc.teamcode.Hware.hwMap;
|
||||||
import org.firstinspires.ftc.teamcode.subsystems.DriveTrain;
|
import org.firstinspires.ftc.teamcode.subsystems.DriveTrain;
|
||||||
@@ -29,11 +31,13 @@ public class StateMachine {
|
|||||||
private final Lift m_lift;
|
private final Lift m_lift;
|
||||||
|
|
||||||
private final LED m_led;
|
private final LED m_led;
|
||||||
|
private final ElapsedTime ledTimer = new ElapsedTime();
|
||||||
|
|
||||||
boolean isMotifEdited = false;
|
boolean isMotifEdited = false;
|
||||||
private long lastIndexAllArtifactsTime = 0;
|
private long lastIndexAllArtifactsTime = 0;
|
||||||
|
|
||||||
public boolean isIntakeLaunching = false;
|
public boolean isIntakeLaunching = false;
|
||||||
|
private boolean isForceLaunch = false;
|
||||||
|
|
||||||
public StateMachine(hwMap.DriveHwMap h_driveTrain, hwMap.IntakeHwMap h_intake, hwMap.LiftHwMap h_lift, hwMap.TransferHwMap h_transfer, hwMap.TurretHwMap h_turret, hwMap.LedHwMap h_led, int initialMotif, int alliance) {
|
public StateMachine(hwMap.DriveHwMap h_driveTrain, hwMap.IntakeHwMap h_intake, hwMap.LiftHwMap h_lift, hwMap.TransferHwMap h_transfer, hwMap.TurretHwMap h_turret, hwMap.LedHwMap h_led, int initialMotif, int alliance) {
|
||||||
this.m_driveTrain = new DriveTrain(h_driveTrain);
|
this.m_driveTrain = new DriveTrain(h_driveTrain);
|
||||||
@@ -69,6 +73,7 @@ public class StateMachine {
|
|||||||
m_turret.setTurretState(Turret.TurretState.IDLE);
|
m_turret.setTurretState(Turret.TurretState.IDLE);
|
||||||
m_intake.setIntakeState(Intake.IntakeState.IDLE);
|
m_intake.setIntakeState(Intake.IntakeState.IDLE);
|
||||||
isIntakeLaunching = false;
|
isIntakeLaunching = false;
|
||||||
|
isForceLaunch = false;
|
||||||
//m_driveTrain.setDriveState(DriveTrain.DriveState.NORMAL);
|
//m_driveTrain.setDriveState(DriveTrain.DriveState.NORMAL);
|
||||||
m_driveTrain.stopAnchor();
|
m_driveTrain.stopAnchor();
|
||||||
break;
|
break;
|
||||||
@@ -78,14 +83,17 @@ public class StateMachine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void update(boolean manualSAM, boolean manualTracking, Pose currentPose) {
|
public void update(boolean manualSAM, boolean manualTracking, Pose currentPose, Vector currentVelocity) {
|
||||||
m_driveTrain.update();
|
m_driveTrain.update();
|
||||||
|
|
||||||
m_turret.update(manualTracking, manualSAM, currentPose, m_transfer.getLaunchElapsedTime());
|
m_turret.update(manualTracking, manualSAM, currentPose, currentVelocity, m_transfer.getLaunchElapsedTime());
|
||||||
|
|
||||||
if (currentGameState == GameState.SCORING) {
|
if (currentGameState == GameState.SCORING) {
|
||||||
m_transfer.updateTurretReady(m_turret.hasReachedVelocity());
|
if (!isForceLaunch) {
|
||||||
if (m_turret.hasReachedVelocity()) {
|
m_transfer.updateTurretReady(m_turret.hasReachedVelocity());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_turret.hasReachedVelocity() || isForceLaunch) {
|
||||||
isIntakeLaunching = true;
|
isIntakeLaunching = true;
|
||||||
m_intake.setIntakeState(Intake.IntakeState.LAUNCH);
|
m_intake.setIntakeState(Intake.IntakeState.LAUNCH);
|
||||||
}
|
}
|
||||||
@@ -182,6 +190,7 @@ public class StateMachine {
|
|||||||
|
|
||||||
public void forceLaunchSequence() {
|
public void forceLaunchSequence() {
|
||||||
setGameState(GameState.SCORING);
|
setGameState(GameState.SCORING);
|
||||||
|
isForceLaunch = true;
|
||||||
m_transfer.updateTurretReady(true);
|
m_transfer.updateTurretReady(true);
|
||||||
m_intake.setIntakeState(Intake.IntakeState.LAUNCH);
|
m_intake.setIntakeState(Intake.IntakeState.LAUNCH);
|
||||||
isIntakeLaunching = true;
|
isIntakeLaunching = true;
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ import org.firstinspires.ftc.teamcode.util.FPSCounter;
|
|||||||
import com.qualcomm.hardware.lynx.LynxModule;
|
import com.qualcomm.hardware.lynx.LynxModule;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.pedropathing.math.Vector;
|
||||||
|
|
||||||
public class finalTeleOp {
|
public class finalTeleOp {
|
||||||
|
|
||||||
@TeleOp(name = "Red Final", group = "FINAL")
|
@TeleOp(name = "Red Final", group = "FINAL")
|
||||||
@@ -91,7 +93,7 @@ public class finalTeleOp {
|
|||||||
|
|
||||||
if (stateMachine.getCurrentGameState() != GameState.SCORING) {
|
if (stateMachine.getCurrentGameState() != GameState.SCORING) {
|
||||||
stateMachine.getTransfer().closeLimiter();
|
stateMachine.getTransfer().closeLimiter();
|
||||||
} else if (stateMachine.getCurrentGameState() == GameState.SCORING && stateMachine.getTurret().isTurretReady()) {
|
} else if (stateMachine.getCurrentGameState() == GameState.SCORING && stateMachine.getTurret().isTurretReady(false)) {
|
||||||
stateMachine.getTransfer().openLimiter();
|
stateMachine.getTransfer().openLimiter();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,12 +103,14 @@ public class finalTeleOp {
|
|||||||
|
|
||||||
follower.update();
|
follower.update();
|
||||||
Pose currentPose = follower.getPose();
|
Pose currentPose = follower.getPose();
|
||||||
|
Vector currentVelocity = follower.getVelocity();
|
||||||
|
|
||||||
|
|
||||||
handleGlobalLogic();
|
handleGlobalLogic();
|
||||||
handleDriverInput();
|
handleDriverInput();
|
||||||
handleOperatorInput();
|
handleOperatorInput();
|
||||||
|
|
||||||
stateMachine.update(manualSAM, manualTracking, currentPose);
|
stateMachine.update(manualSAM, manualTracking, currentPose, currentVelocity);
|
||||||
|
|
||||||
if (gamepad2.a) {
|
if (gamepad2.a) {
|
||||||
stateMachine.getTransfer().openLimiter();
|
stateMachine.getTransfer().openLimiter();
|
||||||
@@ -273,7 +277,7 @@ public class finalTeleOp {
|
|||||||
telemetry.addLine("▰▰▰▰▰▰▰ TRACKING ▰▰▰▰▰▰▰");
|
telemetry.addLine("▰▰▰▰▰▰▰ TRACKING ▰▰▰▰▰▰▰");
|
||||||
telemetry.addData("Pose", "X:%.1f Y:%.1f H:%.1f°", p.getX(), p.getY(), Math.toDegrees(p.getHeading()));
|
telemetry.addData("Pose", "X:%.1f Y:%.1f H:%.1f°", p.getX(), p.getY(), Math.toDegrees(p.getHeading()));
|
||||||
telemetry.addData("Distance", "%.1f in", stateMachine.getTurret().getDistance());
|
telemetry.addData("Distance", "%.1f in", stateMachine.getTurret().getDistance());
|
||||||
telemetry.addData("Turret Ready", stateMachine.getTurret().isTurretReady());
|
telemetry.addData("Turret Ready", stateMachine.getTurret().isTurretReady(false));
|
||||||
telemetry.addData("Hood Offset", stateMachine.getTurret().offsetHood);
|
telemetry.addData("Hood Offset", stateMachine.getTurret().offsetHood);
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import com.qualcomm.robotcore.eventloop.opmode.TeleOp;
|
|||||||
import com.qualcomm.robotcore.hardware.DcMotor;
|
import com.qualcomm.robotcore.hardware.DcMotor;
|
||||||
import com.qualcomm.robotcore.hardware.DcMotorEx;
|
import com.qualcomm.robotcore.hardware.DcMotorEx;
|
||||||
import com.qualcomm.robotcore.hardware.DcMotorSimple;
|
import com.qualcomm.robotcore.hardware.DcMotorSimple;
|
||||||
|
import com.qualcomm.robotcore.hardware.PIDFCoefficients;
|
||||||
import com.qualcomm.robotcore.hardware.Servo;
|
import com.qualcomm.robotcore.hardware.Servo;
|
||||||
import com.qualcomm.robotcore.util.Range;
|
import com.qualcomm.robotcore.util.Range;
|
||||||
|
|
||||||
@@ -35,17 +36,14 @@ public class flywheelTuning extends OpMode {
|
|||||||
public Servo hoodServo;
|
public Servo hoodServo;
|
||||||
public Servo limiter;
|
public Servo limiter;
|
||||||
|
|
||||||
// Configurable / Dashboard variables
|
|
||||||
public static boolean autoMode = false;
|
public static boolean autoMode = false;
|
||||||
public static double curTargetVelocity = 0;
|
public static double curTargetVelocity = 0;
|
||||||
public static double targetPOS = 0;
|
public static double targetPOS = 0;
|
||||||
public static int pipeline = 1;
|
public static int pipeline = 1;
|
||||||
public static boolean reverse = false;
|
public static boolean reverse = false;
|
||||||
|
|
||||||
// Standard runtime variables
|
|
||||||
double distance = 0;
|
double distance = 0;
|
||||||
|
|
||||||
// State machine and tracking variables
|
|
||||||
CalibrationState calibState = CalibrationState.IDLE;
|
CalibrationState calibState = CalibrationState.IDLE;
|
||||||
boolean lastX = false;
|
boolean lastX = false;
|
||||||
|
|
||||||
@@ -63,6 +61,8 @@ public class flywheelTuning extends OpMode {
|
|||||||
flywheelMotorL.setMode(DcMotorEx.RunMode.RUN_USING_ENCODER);
|
flywheelMotorL.setMode(DcMotorEx.RunMode.RUN_USING_ENCODER);
|
||||||
flywheelMotorL.setDirection(reverse ? DcMotorSimple.Direction.FORWARD : DcMotorSimple.Direction.REVERSE);
|
flywheelMotorL.setDirection(reverse ? DcMotorSimple.Direction.FORWARD : DcMotorSimple.Direction.REVERSE);
|
||||||
|
|
||||||
|
flywheelMotorR.setPIDFCoefficients(DcMotor.RunMode.RUN_USING_ENCODER, new PIDFCoefficients(2, 0, 11, 14.3));
|
||||||
|
flywheelMotorL.setPIDFCoefficients(DcMotor.RunMode.RUN_USING_ENCODER, new PIDFCoefficients(2, 0, 11, 14.3));
|
||||||
hoodServo = hardwareMap.servo.get("hoodservo");
|
hoodServo = hardwareMap.servo.get("hoodservo");
|
||||||
hoodServo.setDirection(Servo.Direction.REVERSE);
|
hoodServo.setDirection(Servo.Direction.REVERSE);
|
||||||
|
|
||||||
@@ -184,7 +184,9 @@ public class flywheelTuning extends OpMode {
|
|||||||
intake.setPower(0);
|
intake.setPower(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
hoodServo.setPosition(Range.clip(applyHood, Constants.TurretConstants.SERVO_MIN, Constants.TurretConstants.SERVO_MAX));
|
double recoilOffset = (currentVel - applyVel) * -0.000185;
|
||||||
|
|
||||||
|
hoodServo.setPosition(Range.clip(applyHood + recoilOffset, Constants.TurretConstants.SERVO_MIN, Constants.TurretConstants.SERVO_MAX));
|
||||||
|
|
||||||
|
|
||||||
// --- TELEMETRY ---
|
// --- TELEMETRY ---
|
||||||
@@ -213,19 +215,19 @@ public class flywheelTuning extends OpMode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private double getTrigBasedDistance(double targetOffsetAngleVertical) {
|
private double getTrigBasedDistance(double targetOffsetAngleVertical) {
|
||||||
return (29.5-12.75) / Math.tan(Math.toRadians(19.9 + targetOffsetAngleVertical));
|
return (29.5-12.75) / Math.tan(Math.toRadians(19.8 + targetOffsetAngleVertical));
|
||||||
// ^ GOAL - CAMERA HEIGHT ^ Offset Degrees
|
// ^ GOAL - CAMERA HEIGHT ^ Offset Degrees
|
||||||
}
|
}
|
||||||
|
|
||||||
private double getFlywheelVelocity(double dist) {
|
private double getFlywheelVelocity(double dist) {
|
||||||
return (0.0000119972 * Math.pow(dist, 4)
|
return (-0.0000144121 * Math.pow(dist, 4)
|
||||||
- 0.00249603 * Math.pow(dist, 3)
|
+ 0.00398607 * Math.pow(dist, 3)
|
||||||
+ 0.179513 * Math.pow(dist, 2)
|
- 0.342198 * Math.pow(dist, 2)
|
||||||
+ (0.0519688 * dist)
|
+ (16.43014 * dist)
|
||||||
+ 1489.8908);
|
+ 1198.24434);
|
||||||
}
|
}
|
||||||
|
|
||||||
private double getHoodPOS(double dist) {
|
private double getHoodPOS(double dist) {
|
||||||
return ((-(8.57654 * Math.pow(10, -9)) * Math.pow(dist, 4)) + (0.00000166094 * Math.pow(dist, 3)) - (0.0000796795 * Math.pow(dist, 2)) + (-0.00326804 * dist) + 0.433859);
|
return (((3.55794 * Math.pow(10, -8)) * Math.pow(dist, 4)) + (-0.00000995887 * Math.pow(dist, 3)) - (0.000924672 * Math.pow(dist, 2)) + (-0.037262 * dist) + 0.943067);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
package org.firstinspires.ftc.teamcode.tuning;
|
||||||
|
|
||||||
|
import com.qualcomm.robotcore.eventloop.opmode.OpMode;
|
||||||
|
import com.qualcomm.robotcore.eventloop.opmode.TeleOp;
|
||||||
|
import com.qualcomm.robotcore.hardware.ServoImplEx;
|
||||||
|
import com.qualcomm.robotcore.hardware.PwmControl;
|
||||||
|
import com.bylazar.configurables.annotations.Configurable;
|
||||||
|
|
||||||
|
@Configurable
|
||||||
|
@TeleOp(name = "GoBilda RGB Indicator Test", group = "Tests")
|
||||||
|
public class ledTest extends OpMode {
|
||||||
|
|
||||||
|
// Declare the light as a ServoImplEx
|
||||||
|
private ServoImplEx rgbLight;
|
||||||
|
|
||||||
|
public static double LED1 = 0.33;
|
||||||
|
public static double LED2 = 0.66;
|
||||||
|
public static double LED3 = 0.99;
|
||||||
|
|
||||||
|
private boolean lightOn = false;
|
||||||
|
|
||||||
|
private double lightPosition = 0;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init() {
|
||||||
|
rgbLight = hardwareMap.get(ServoImplEx.class, "prism");
|
||||||
|
|
||||||
|
rgbLight.setPwmRange(new PwmControl.PwmRange(500, 2500));
|
||||||
|
|
||||||
|
telemetry.addData("Status", "Initialized. Ready to test colors.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void loop() {
|
||||||
|
|
||||||
|
if (gamepad1.psWasPressed()) {
|
||||||
|
lightOn = !lightOn;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gamepad1.a) {
|
||||||
|
lightPosition = LED1;
|
||||||
|
}
|
||||||
|
else if (gamepad1.b) {
|
||||||
|
lightPosition = 0;
|
||||||
|
}
|
||||||
|
else if (gamepad1.x) {
|
||||||
|
lightPosition = LED2;
|
||||||
|
}
|
||||||
|
else if (gamepad1.y) {
|
||||||
|
lightPosition = LED3;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gamepad1.right_trigger > 0.1) {
|
||||||
|
lightPosition = gamepad1.right_trigger;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lightOn) {
|
||||||
|
rgbLight.setPwmEnable();
|
||||||
|
} else {
|
||||||
|
rgbLight.setPwmDisable();
|
||||||
|
}
|
||||||
|
|
||||||
|
rgbLight.setPosition(lightPosition);
|
||||||
|
|
||||||
|
telemetry.addData("Current Light Position", rgbLight.getPosition());
|
||||||
|
telemetry.update();
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user