Repository navigation
Expand file tree
/
Copy pathClimb.java
More file actions
138 lines (114 loc) · 4.59 KB
/
Copy pathClimb.java
File metadata and controls
138 lines (114 loc) · 4.59 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
/*
* Climb.java
*/
/*
* Copyright (C) 2025-2026 Team 5924 - Golden Gate Robotics and/or its affiliates.
*
* This file, and the associated project, are offered under the GNU General
* Public License v3.0. A copy of this license can be found in LICENSE.md
* at the root of this project.
*
* If this file has been separated from the original project, you should have
* received a copy of the GNU General Public License along with it.
* If you did not, see <https://www.gnu.org/licenses>.
*/
package org.team5924.frc2026.subsystems.climb;
import edu.wpi.first.wpilibj.Alert;
import edu.wpi.first.wpilibj.DriverStation;
import edu.wpi.first.wpilibj2.command.SubsystemBase;
import java.util.function.DoubleSupplier;
import lombok.Getter;
import org.littletonrobotics.junction.Logger;
import org.team5924.frc2026.RobotState;
import org.team5924.frc2026.subsystems.sensors.BeamBreakIO;
import org.team5924.frc2026.subsystems.sensors.BeamBreakIOInputsAutoLogged;
import org.team5924.frc2026.util.Elastic;
import org.team5924.frc2026.util.Elastic.Notification;
import org.team5924.frc2026.util.Elastic.Notification.NotificationLevel;
import org.team5924.frc2026.util.LoggedTunableNumber;
public class Climb extends SubsystemBase {
private final ClimbIO io;
private final ClimbIOInputsAutoLogged inputs = new ClimbIOInputsAutoLogged();
public enum ClimbState { // TODO: Update climb level values - distance not rads!!!
STOW(new LoggedTunableNumber("Climb/Stow", 0)),
LEVEL_ONE(new LoggedTunableNumber("Climb/LevelOne", 0)),
LEVEL_TWO(new LoggedTunableNumber("Climb/LevelTwo", 0)),
LEVEL_THREE(new LoggedTunableNumber("Climb/LevelThree", 0)),
CLIMB_DOWN(new LoggedTunableNumber("Climb/ClimbDown", 0)),
DEPLOY(new LoggedTunableNumber("Climb/Deploy", 0)),
DROP(new LoggedTunableNumber("Climb/Drop", 0)),
MOVING(() -> 0.0),
// voltage at which the climb subsystem motor moves when controlled by the operator
OPERATOR_CONTROL(new LoggedTunableNumber("Climb/OperatorVoltage", 4.5));
// TODO: add distance to rads method
private final DoubleSupplier rads;
ClimbState(DoubleSupplier rads) {
this.rads = rads;
}
}
@Getter private ClimbState goalState;
private final Alert climbMotorDisconnected;
private final Notification climbMotorDisconnectedNotification;
private boolean wasClimbMotorConnected = true;
// Climb Beam Break
private final BeamBreakIO beamBreakIO;
private final BeamBreakIOInputsAutoLogged beamBreakInputs = new BeamBreakIOInputsAutoLogged();
public Climb(ClimbIO io, BeamBreakIO beamBreakIO) {
this.io = io;
this.goalState = ClimbState.STOW;
this.climbMotorDisconnected =
new Alert("Climb System Motor Disconnected!", Alert.AlertType.kWarning);
this.climbMotorDisconnectedNotification =
new Notification(NotificationLevel.WARNING, "Climb System Motor Disconnected", "");
this.beamBreakIO = beamBreakIO;
}
@Override
public void periodic() {
io.periodicUpdates();
io.updateInputs(inputs);
beamBreakIO.updateInputs(beamBreakInputs);
Logger.processInputs("Climb", inputs);
Logger.processInputs("Climb/BeamBreak", beamBreakInputs);
Logger.recordOutput("Climb/GoalState", goalState.toString());
Logger.recordOutput("Climb/CurrentState", RobotState.getInstance().getClimbState().toString());
Logger.recordOutput("Climb/TargetRads", goalState.rads.getAsDouble());
climbMotorDisconnected.set(!inputs.climbMotorConnected);
handleCurrentState();
if (!inputs.climbMotorConnected && wasClimbMotorConnected) {
Elastic.sendNotification(climbMotorDisconnectedNotification);
}
wasClimbMotorConnected = inputs.climbMotorConnected;
}
public void runVolts(double volts) {
io.runVolts(volts);
}
public void setGoalState(ClimbState goalState) {
this.goalState = goalState;
switch (goalState) {
case OPERATOR_CONTROL:
RobotState.getInstance().setClimbState(ClimbState.OPERATOR_CONTROL);
break;
case MOVING:
DriverStation.reportError(
"Climb: MOVING is an invalid goal state; it is a transition state!!", null);
break;
default:
RobotState.getInstance().setClimbState(goalState);
break;
}
}
private void handleCurrentState() {
switch (goalState) {
case OPERATOR_CONTROL:
io.runVolts(goalState.rads.getAsDouble());
break;
case MOVING:
// Transition state - no direct motor command
break;
default:
// Closed-loop position handdled by io.setPosition(...)
io.setPosition(goalState.rads.getAsDouble());
break;
}
}
}