1414package frc .robot ;
1515
1616import com .pathplanner .lib .auto .AutoBuilder ;
17+ import edu .wpi .first .wpilibj .DriverStation ;
18+ import edu .wpi .first .wpilibj .RobotBase ;
1719import edu .wpi .first .wpilibj2 .command .Command ;
1820import edu .wpi .first .wpilibj2 .command .sysid .SysIdRoutine ;
1921import frc .robot .commands .DriveCommands ;
2022import frc .robot .controller .Controller ;
23+ import frc .robot .controller .PS4Controller ;
24+ import frc .robot .controller .XboxController ;
2125import frc .robot .generated .TunerConstants ;
2226import frc .robot .subsystems .arm .Arm ;
2327import frc .robot .subsystems .arm .ArmIO ;
3337import frc .robot .subsystems .elevator .ElevatorIO ;
3438import frc .robot .subsystems .elevator .ElevatorIOReal ;
3539import frc .robot .subsystems .elevator .ElevatorIOSim ;
40+ import org .littletonrobotics .junction .Logger ;
3641import org .littletonrobotics .junction .networktables .LoggedDashboardChooser ;
3742
3843/**
@@ -53,6 +58,75 @@ public class RobotContainer {
5358 // Keeps track if the controller bindings have been initialized.
5459 private boolean bindingsInitialized = false ;
5560
61+ /** Initializes a 2813 {@link Controller} on the given port; auto detects the controller type.
62+ *
63+ * <p>This method initializes a generic 2813 Controller by auto detecting the type of controller plugged on {@code port}.
64+ *
65+ * <p>This method requires that the driver station is attached or returns an {@link IllegalStateException} exception.
66+ *
67+ * @param port Joystick port to connect controller to.
68+ * @throws IllegalStateException if DriverStation is not attached yet. This is a retryable error.
69+ * @throws InternalError if DriverStation is already attached but detects empty/invalid controller at specified port.
70+ */
71+ private static Controller createControllerWithTypeAutoDetect (int port ) {
72+ if (!DriverStation .isDSAttached ()) {
73+ throw new IllegalStateException ("DriverStation not yet attached." );
74+ }
75+
76+ Controller controller = null ;
77+ String name = DriverStation .getJoystickName (port );
78+ if (name .contains ("Xbox" )) {
79+ name = "XBox" ;
80+ controller = new XboxController (port );
81+ } else if (name .contains ("PS4" ) || name .contains ("Wireless Controller" )) {
82+ name = "PS4" ;
83+ controller = new PS4Controller (port );
84+ } else if (name .contains ("Keyboard" ) && RobotBase .isSimulation ()) {
85+ // Support the emulated Keyboard X controllers in simulation mode.
86+ // Map them to XBox controllers.
87+ // It's up to the user to configure the right number of buttons for them
88+ // (see
89+ // https://docs.wpilib.org/en/stable/docs/software/wpilib-tools/robot-simulation/simulation-gui.html#using-the-keyboard-as-a-joystick).
90+
91+ // Keep `name` as is.
92+ controller = new XboxController (port );
93+ } else {
94+ throw new InternalError ("Unsupported joystick type: [" + name + "]" );
95+ }
96+ Logger .recordOutput ("Controllers/" + port , name + " controller detected" );
97+ return controller ;
98+ }
99+
100+ /**
101+ * Configures robot bindings once.
102+ *
103+ * <p>This function configures robot button bindings the first time
104+ * createControllerWithTypeAutoDetect can auto-detect a valid controller
105+ * port 0. It just passes after that.
106+ *
107+ * <p>The function prints DriverStation error if the driver station is ready
108+ * but it cannot detect a valid joystick connected at port 0.
109+ */
110+ public void configureBindingsOnce () {
111+ if (bindingsInitialized ) return ;
112+
113+ boolean dontPrintStackTrace = false ;
114+ try {
115+ Controller controller = createControllerWithTypeAutoDetect (0 );
116+ configureButtonBindings (controller );
117+ bindingsInitialized = true ;
118+ } catch (IllegalStateException e ) {
119+ // createControllerWithTypeAutoDetect throws this exception when
120+ // DriverStation is not ready yet. Ignore it and continue retrying
121+ // in the next periodic.
122+ DriverStation .reportWarning (e .getMessage (), dontPrintStackTrace );
123+ } catch (InternalError e ) {
124+ // createControllerWithTypeAutoDetect throws this error when there's
125+ // no joystick connected at all, or it cannot recognize it's type.
126+ DriverStation .reportError ("Joistick[0] detection error: " + e , dontPrintStackTrace );
127+ }
128+ }
129+
56130 /** The container for the robot. Contains subsystems, OI devices, and commands. */
57131 public RobotContainer () {
58132 // controller = getController(0);
@@ -113,15 +187,11 @@ public RobotContainer() {
113187 autoChooser .addOption ("Drive SysId (Dynamic Reverse)" , drive .sysIdDynamic (SysIdRoutine .Direction .kReverse ));
114188 }
115189
116- public boolean getBindingsInitialized () {
117- return bindingsInitialized ;
118- }
119-
120190 /**
121191 * Use this method to define your button->command mappings. Buttons can be created by
122192 * instantiating a 2813's {@link Controller} subclasses.
123193 */
124- public void configureButtonBindings (Controller controller ) {
194+ private void configureButtonBindings (Controller controller ) {
125195 // Default command, normal field-relative drive.
126196 // Xbox controller that I got is busted or something, the getRightY() binds to a trigger for some reason.
127197 drive .setDefaultCommand (DriveCommands .joystickDrive (
@@ -160,8 +230,6 @@ public void configureButtonBindings(Controller controller) {
160230 controller .faceRight ().onTrue (arm .setArmPositionCommand (Arm .ArmPositions .EAST ));
161231 controller .faceDown ().onTrue (arm .setArmPositionCommand (Arm .ArmPositions .SOUTH ));
162232 controller .faceLeft ().onTrue (arm .setArmPositionCommand (Arm .ArmPositions .WEST ));
163-
164- bindingsInitialized = true ;
165233 }
166234
167235 /**
0 commit comments