-
Notifications
You must be signed in to change notification settings - Fork 7
Supercycling implementation #170
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
1f645e3
386fcf9
6ec4f49
990a636
0bbab27
6c0df53
36173e5
b66aa89
8af86a7
a307498
eedf143
d5f2c8b
5559a0d
dc77351
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -272,6 +272,8 @@ private void configureSuperStructureBindings() { | |
.onTrue( | ||
selectScoringHeight(BranchHeight.CORAL_LEVEL_ONE, AlgaeIntakeHeight.ALGAE_LEVEL_GROUND) | ||
.withName("coral level 1, algae ground level")); | ||
|
||
// Processor scoring and left coral pre-score | ||
driverController | ||
.leftTrigger() | ||
.onTrue( | ||
|
@@ -283,11 +285,24 @@ private void configureSuperStructureBindings() { | |
superStructure.algaeProcessorScore( | ||
driverController.rightBumper()), | ||
Commands.waitSeconds(0.7), | ||
getAlgaeIntakeCommand()) | ||
Commands.deferredProxy( | ||
() -> | ||
switch (sensors.intakeSensor.inIntakeSwitchable()) { | ||
case 1 -> Commands.sequence( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there an enum for this? Try to avoid numerics in a switch to ease future maintenance. |
||
Commands.runOnce( | ||
() -> scoringMode = ScoringMode.CORAL) | ||
.alongWith(scoringModeSelectRumble()) | ||
.withName("Coral Scoring Mode"), | ||
superStructure | ||
.superCycleCoralHandoff() | ||
.withName("supercycle handoff")); | ||
default -> getAlgaeIntakeCommand(); | ||
})) | ||
.withName("Processor score"); | ||
}) | ||
.withName("Schedule processor score")); | ||
|
||
// Algae mode | ||
operatorController | ||
.leftBumper() | ||
.onTrue( | ||
|
@@ -297,14 +312,22 @@ private void configureSuperStructureBindings() { | |
.onTrue( | ||
Commands.runOnce(() -> CommandScheduler.getInstance().schedule(getAlgaeIntakeCommand())) | ||
.withName("run algae intake")); | ||
|
||
// Coral Mode | ||
operatorController // should work??? | ||
.leftTrigger() | ||
.onTrue( | ||
Commands.runOnce(() -> scoringMode = ScoringMode.CORAL) | ||
.alongWith(scoringModeSelectRumble()) | ||
.withName("Coral Scoring Mode")) | ||
.onTrue(superStructure.coralPreIntake()) | ||
.onTrue(s.climbPivotSubsystem.toStow()); | ||
.onTrue(s.climbPivotSubsystem.toStow()) | ||
.onTrue( | ||
s.groundArm | ||
.moveToPosition(GroundArm.STOWED_POSITION) | ||
.withName("Ground stowed position")); | ||
|
||
// Stow Mode | ||
operatorController | ||
.povLeft() | ||
.onTrue( | ||
|
@@ -371,6 +394,8 @@ private void configureSuperStructureBindings() { | |
: Commands.none()) | ||
.withName("Automatic Intake")); | ||
} | ||
|
||
// Net scoring and right coral pre-score | ||
driverController | ||
.rightTrigger() | ||
.onTrue( | ||
|
@@ -387,7 +412,21 @@ private void configureSuperStructureBindings() { | |
() -> getDriveY(), | ||
() -> getDriveRotate(), | ||
driverController.rightBumper()), | ||
getAlgaeIntakeCommand()) | ||
// If we are supercycling (have a coral), hand it off and switch | ||
// to coral mode | ||
Commands.deferredProxy( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is the same code as above. Instead of duplicating code move it to it's own routine, then call that routine. |
||
() -> | ||
switch (sensors.intakeSensor.inIntakeSwitchable()) { | ||
case 1 -> Commands.sequence( | ||
Commands.runOnce( | ||
() -> scoringMode = ScoringMode.CORAL) | ||
.alongWith(scoringModeSelectRumble()) | ||
.withName("Coral Scoring Mode"), | ||
superStructure | ||
.superCycleCoralHandoff() | ||
.withName("supercycle handoff")); | ||
default -> getAlgaeIntakeCommand(); | ||
})) | ||
.withName("Algae score then intake"); | ||
}; | ||
CommandScheduler.getInstance().schedule(scoreCommand); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -59,4 +59,9 @@ public Trigger inIntake() { | |
}) | ||
.debounce(0.1); | ||
} | ||
|
||
public int inIntakeSwitchable() { | ||
double distance = getSensorDistance().in(Meters); | ||
return (distance > INTAKE_LOWER_LIMIT && distance < INTAKE_UPPER_LIMIT) ? 1 : 0; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Instead of 1 or 0, use enums or true/false returns. |
||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -56,6 +56,9 @@ public enum TargetPositions { | |
private final double CLIMB_HOLD_CLIMBED = -0.0705; | ||
private final double CLIMB_IN_SPEED = -0.75; | ||
|
||
private final double climbInKp = 30; | ||
private final double climbOutKp = 50; | ||
|
||
// positions for relation between motor encoder and WCP encoder | ||
// relative to eachother, likely not accurately zero'ed when obtained. | ||
private static final double MIN_ROTOR_POSITION = -50.45; | ||
|
@@ -83,6 +86,8 @@ public enum TargetPositions { | |
|
||
// the target speed | ||
private double setSpeed = 0; | ||
private double speedToSet = 0; | ||
private double pError = 0; | ||
|
||
// alerts for checking if either motor is or isnt connected | ||
private final Alert NotConnectedErrorOne = | ||
|
@@ -390,12 +395,15 @@ public Command advanceClimbCheck() { | |
setSpeed = 0; | ||
} else { | ||
if (!moveComplete) { | ||
if (minTargetPos > getClimbPosition()) { | ||
motorLeft.set(CLIMB_OUT_SPEED); | ||
setSpeed = CLIMB_OUT_SPEED; | ||
pError = minTargetPos - getClimbPosition(); | ||
if (pError > 0) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is a pError of 0 realistic or is there some minimum variance, e.g. (pError > 0.001) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We haven't had any issues with variance or inaccuracies of this sort during drive practice yet. Not saying it isn't possible, but in the ~7 hours of practice that we've been running this, its been precise enough for our use case. Regardless, ill look into any possible causes of variance in the code. (For context, I wrote the Climb pivot subsystem, and while Tristan wrote the PID stuff, I understand it entirely) FYI, these funnel PID changes were merged earlier in a separate PR, and are only present here because we wanted to test it all on one PR before it was merged. Feel free to make an Issue about any code logic errors or faults you see though! We watch the issue list frequently. (Im just going to put this on all of the climb comments here)
|
||
speedToSet = CLIMB_OUT_SPEED * pError * climbOutKp; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is your intent for speed to slow as it gets closer to the target? Why is that necessary as opposed to consistent speed on this. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, so that it gets to the target accurately and efficiently without overshooting. We had consistent speed before, but it frequently overshot and wasnt precise, so we added a PID loop (actually just P in the climb, but normally contains PID as well) as you can see in the code. FYI, these funnel PID changes were merged earlier in a separate PR, and are only present here because we wanted to test it all on one PR before it was merged. Feel free to make an Issue about any code logic errors or faults you see though! We watch the issue list frequently. (Im just going to put this on all of the climb comments here)
|
||
motorLeft.set(speedToSet); | ||
setSpeed = speedToSet; | ||
} else { | ||
motorLeft.set(CLIMB_IN_SPEED); | ||
setSpeed = CLIMB_IN_SPEED; | ||
speedToSet = CLIMB_IN_SPEED * -pError * climbInKp; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is this code needed? Are you trying to set the speed to 0? pError here is 0, so speedToSet will be 0. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. pError is modified elsewhere in the code, which this depends on. FYI, these funnel PID changes were merged earlier in a separate PR, and are only present here because we wanted to test it all on one PR before it was merged. Feel free to make an Issue about any code logic errors or faults you see though! We watch the issue list frequently
|
||
motorLeft.set(speedToSet); | ||
setSpeed = speedToSet; | ||
} | ||
} | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -203,6 +203,60 @@ public Command groundIntake(BooleanSupplier retract) { | |
} | ||
} | ||
|
||
public Command supercycleGroundIntake(BooleanSupplier retract) { | ||
return // Core intake sequence | ||
Commands.sequence( | ||
// Deploy the ground arm (and wait until it reaches the position). | ||
groundArm.moveToPosition(GroundArm.GROUND_POSITION), | ||
// Once it's out, set the ground spinny speed | ||
groundSpinny.setGroundIntakePower(), | ||
// After it's deployed, apply a constant voltage to press it into the bumper | ||
// and continue. | ||
groundArm.setVoltage(GroundArm.GROUND_HOLD_VOLTAGE)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is the impact on battery for this? Is there risk of pulling too much from the battery limiting other actions? Does this reduce battery life? Just wondering if superCycling will have a negative impact on battery life that needs to be considered or are we doing OK with battery life in competition such that it's a non-issue. |
||
|
||
// Move on from the intake being down when stuff is triggered | ||
.withDeadline(Commands.waitUntil(intakeSensor.inIntake().or(retract))) | ||
// And bring it back inside the robot | ||
.andThen( | ||
Commands.sequence( | ||
// Move ground intake to in positiong and hold it there | ||
groundArm.moveToPosition(GroundArm.UP_POSITION).andThen(Commands.idle()), | ||
// Set ground intake power to just hold the coral tightly | ||
groundSpinny.holdCoralPower())); | ||
} | ||
|
||
// This is called when a coral is in the ground intake and the robot has just scored an algae | ||
public Command superCycleCoralHandoff() { | ||
return Commands.sequence( | ||
// Initial setup- Move elevator high enough for ground arm to be clear, start moving | ||
// arm pivot, stop the spinny claw, and start spinning the ground intake | ||
Commands.parallel( | ||
elevator.setLevel(ElevatorSubsystem.MIN_FULL_GROUND_INTAKE), | ||
armPivot.moveToPosition(ArmPivot.CORAL_QUICK_INTAKE), | ||
spinnyClaw.stop(), // just as a backup in case things are silly | ||
groundSpinny.setGroundIntakePower()) | ||
// Move on even if arm isn't in position yet as long as elevator is high enough | ||
.until(elevator.above(ElevatorSubsystem.MIN_FULL_GROUND_INTAKE)), | ||
// Move the ground intake out | ||
groundArm.moveToPosition(GroundArm.MIN_OUT_QUICK_HANDOFF), | ||
// Prep is done, now do the handoff | ||
Commands.parallel( | ||
// These three are the initial setup: Move elevator down to the handoff | ||
// height, make sure armPivot finishes moving to the right height, and | ||
// spin claw | ||
elevator.setLevel(ElevatorSubsystem.CORAL_QUICK_INTAKE), | ||
armPivot.moveToPosition(ArmPivot.CORAL_QUICK_INTAKE), | ||
spinnyClaw.coralIntakePower()), | ||
// Start the sequence of handing off the coral | ||
groundArm | ||
.moveToPosition(GroundArm.STOWED_POSITION) | ||
.until(groundArm.atPosition(GroundArm.QUICK_INTAKE_POSITION)), | ||
// Spin groundSpinny out, but skip if we lost the coral. | ||
groundSpinny.setQuickHandoffExtakeSpeed().onlyIf(armSensor.inClaw()), | ||
// Go back to stow, but skip if we lost the coral. | ||
coralStow().onlyIf(armSensor.inClaw())); | ||
} | ||
|
||
// This is the actual version in use. It moves the coral directly into the claw. | ||
public Command quickGroundIntake(BooleanSupplier retract) { // thanks joseph | ||
if (groundSpinny == null || groundArm == null || intakeSensor == null) { | ||
|
@@ -370,7 +424,8 @@ public Command algaeLevelThreeFourIntake() { // removes algae from upper reef | |
Commands.parallel( | ||
spinnyClaw.algaeIntakePower(), | ||
armPivot.moveToPosition(ArmPivot.ALGAE_REMOVE), | ||
elevator.setLevel(ElevatorSubsystem.ALGAE_LEVEL_THREE_FOUR))) | ||
groundArm.moveToPosition(GroundArm.UP_POSITION).andThen(Commands.idle())), | ||
elevator.setLevel(ElevatorSubsystem.ALGAE_LEVEL_THREE_FOUR)) | ||
.withName("Algae L3-L4 Intake"); | ||
} | ||
|
||
|
@@ -379,7 +434,8 @@ public Command algaeLevelTwoThreeIntake() { // removes algae from lower reef | |
Commands.parallel( | ||
spinnyClaw.algaeIntakePower(), | ||
armPivot.moveToPosition(ArmPivot.ALGAE_REMOVE), | ||
elevator.setLevel(ElevatorSubsystem.ALGAE_LEVEL_TWO_THREE))) | ||
elevator.setLevel(ElevatorSubsystem.ALGAE_LEVEL_TWO_THREE)), | ||
groundArm.moveToPosition(GroundArm.STOWED_POSITION).andThen(Commands.idle())) | ||
.withName("Algae L2-L3 Intake"); | ||
} | ||
|
||
|
@@ -388,7 +444,9 @@ public Command algaeLevelTwoThreeIntake() { // removes algae from lower reef | |
return Commands.parallel( | ||
spinnyClaw.algaeIntakePower(), | ||
Commands.sequence( | ||
armPivot.moveToPosition(ArmPivot.ALGAE_GROUND_INTAKE), | ||
Commands.parallel( | ||
armPivot.moveToPosition(ArmPivot.ALGAE_GROUND_INTAKE), | ||
groundArm.moveToPosition(GroundArm.STOWED_POSITION).andThen(Commands.idle())), | ||
elevator.setLevel(ElevatorSubsystem.ALGAE_GROUND_INTAKE))) | ||
.withName("Algae Ground Intake"); | ||
} | ||
|
@@ -417,7 +475,7 @@ public Command algaeProcessorScore(BooleanSupplier score) { // scores algae in p | |
public Command algaeNetScore(BooleanSupplier score) { | ||
return Commands.sequence( | ||
Commands.parallel( | ||
elevator.setLevel(ElevatorSubsystem.ALGAE_NET_SCORE), | ||
groundArm.moveToPosition(GroundArm.UP_POSITION).andThen(Commands.idle()), | ||
armPivot.moveToPosition(ArmPivot.ALGAE_NET_SCORE), | ||
spinnyClaw.algaeIntakePower()), | ||
Commands.waitUntil(score), | ||
|
Uh oh!
There was an error while loading. Please reload this page.