001// Copyright (c) FIRST and other WPILib contributors. 002// Open Source Software; you can modify and/or share it under the terms of 003// the WPILib BSD license file in the root directory of this project. 004 005package edu.wpi.first.wpilibj; 006 007import edu.wpi.first.hal.FRCNetComm.tResourceType; 008import edu.wpi.first.hal.HAL; 009import edu.wpi.first.wpilibj.event.BooleanEvent; 010import edu.wpi.first.wpilibj.event.EventLoop; 011 012/** 013 * Handle input from Xbox 360 or Xbox One controllers connected to the Driver Station. 014 * 015 * <p>This class handles Xbox input that comes from the Driver Station. Each time a value is 016 * requested the most recent value is returned. There is a single class instance for each controller 017 * and the mapping of ports to hardware buttons depends on the code in the Driver Station. 018 */ 019public class XboxController extends GenericHID { 020 /** Represents a digital button on an XboxController. */ 021 public enum Button { 022 kLeftBumper(5), 023 kRightBumper(6), 024 kLeftStick(9), 025 kRightStick(10), 026 kA(1), 027 kB(2), 028 kX(3), 029 kY(4), 030 kBack(7), 031 kStart(8); 032 033 public final int value; 034 035 Button(int value) { 036 this.value = value; 037 } 038 039 /** 040 * Get the human-friendly name of the button, matching the relevant methods. This is done by 041 * stripping the leading `k`, and if not a Bumper button append `Button`. 042 * 043 * <p>Primarily used for automated unit tests. 044 * 045 * @return the human-friendly name of the button. 046 */ 047 @Override 048 public String toString() { 049 var name = this.name().substring(1); // Remove leading `k` 050 if (name.endsWith("Bumper")) { 051 return name; 052 } 053 return name + "Button"; 054 } 055 } 056 057 /** Represents an axis on an XboxController. */ 058 public enum Axis { 059 kLeftX(0), 060 kRightX(4), 061 kLeftY(1), 062 kRightY(5), 063 kLeftTrigger(2), 064 kRightTrigger(3); 065 066 public final int value; 067 068 Axis(int value) { 069 this.value = value; 070 } 071 072 /** 073 * Get the human-friendly name of the axis, matching the relevant methods. This is done by 074 * stripping the leading `k`, and if a trigger axis append `Axis`. 075 * 076 * <p>Primarily used for automated unit tests. 077 * 078 * @return the human-friendly name of the axis. 079 */ 080 @Override 081 public String toString() { 082 var name = this.name().substring(1); // Remove leading `k` 083 if (name.endsWith("Trigger")) { 084 return name + "Axis"; 085 } 086 return name; 087 } 088 } 089 090 /** 091 * Construct an instance of a controller. 092 * 093 * @param port The port index on the Driver Station that the controller is plugged into. 094 */ 095 public XboxController(final int port) { 096 super(port); 097 098 HAL.report(tResourceType.kResourceType_XboxController, port + 1); 099 } 100 101 /** 102 * Get the X axis value of left side of the controller. 103 * 104 * @return The axis value. 105 */ 106 public double getLeftX() { 107 return getRawAxis(Axis.kLeftX.value); 108 } 109 110 /** 111 * Get the X axis value of right side of the controller. 112 * 113 * @return The axis value. 114 */ 115 public double getRightX() { 116 return getRawAxis(Axis.kRightX.value); 117 } 118 119 /** 120 * Get the Y axis value of left side of the controller. 121 * 122 * @return The axis value. 123 */ 124 public double getLeftY() { 125 return getRawAxis(Axis.kLeftY.value); 126 } 127 128 /** 129 * Get the Y axis value of right side of the controller. 130 * 131 * @return The axis value. 132 */ 133 public double getRightY() { 134 return getRawAxis(Axis.kRightY.value); 135 } 136 137 /** 138 * Get the left trigger (LT) axis value of the controller. Note that this axis is bound to the 139 * range of [0, 1] as opposed to the usual [-1, 1]. 140 * 141 * @return The axis value. 142 */ 143 public double getLeftTriggerAxis() { 144 return getRawAxis(Axis.kLeftTrigger.value); 145 } 146 147 /** 148 * Get the right trigger (RT) axis value of the controller. Note that this axis is bound to the 149 * range of [0, 1] as opposed to the usual [-1, 1]. 150 * 151 * @return The axis value. 152 */ 153 public double getRightTriggerAxis() { 154 return getRawAxis(Axis.kRightTrigger.value); 155 } 156 157 /** 158 * Read the value of the left bumper (LB) button on the controller. 159 * 160 * @return The state of the button. 161 */ 162 public boolean getLeftBumper() { 163 return getRawButton(Button.kLeftBumper.value); 164 } 165 166 /** 167 * Read the value of the right bumper (RB) button on the controller. 168 * 169 * @return The state of the button. 170 */ 171 public boolean getRightBumper() { 172 return getRawButton(Button.kRightBumper.value); 173 } 174 175 /** 176 * Whether the left bumper (LB) was pressed since the last check. 177 * 178 * @return Whether the button was pressed since the last check. 179 */ 180 public boolean getLeftBumperPressed() { 181 return getRawButtonPressed(Button.kLeftBumper.value); 182 } 183 184 /** 185 * Whether the right bumper (RB) was pressed since the last check. 186 * 187 * @return Whether the button was pressed since the last check. 188 */ 189 public boolean getRightBumperPressed() { 190 return getRawButtonPressed(Button.kRightBumper.value); 191 } 192 193 /** 194 * Whether the left bumper (LB) was released since the last check. 195 * 196 * @return Whether the button was released since the last check. 197 */ 198 public boolean getLeftBumperReleased() { 199 return getRawButtonReleased(Button.kLeftBumper.value); 200 } 201 202 /** 203 * Whether the right bumper (RB) was released since the last check. 204 * 205 * @return Whether the button was released since the last check. 206 */ 207 public boolean getRightBumperReleased() { 208 return getRawButtonReleased(Button.kRightBumper.value); 209 } 210 211 /** 212 * Constructs an event instance around the right bumper's digital signal. 213 * 214 * @param loop the event loop instance to attach the event to. 215 * @return an event instance representing the right bumper's digital signal attached to the given 216 * loop. 217 */ 218 public BooleanEvent leftBumper(EventLoop loop) { 219 return new BooleanEvent(loop, this::getLeftBumper); 220 } 221 222 /** 223 * Constructs an event instance around the left bumper's digital signal. 224 * 225 * @param loop the event loop instance to attach the event to. 226 * @return an event instance representing the left bumper's digital signal attached to the given 227 * loop. 228 */ 229 public BooleanEvent rightBumper(EventLoop loop) { 230 return new BooleanEvent(loop, this::getRightBumper); 231 } 232 233 /** 234 * Read the value of the left stick button (LSB) on the controller. 235 * 236 * @return The state of the button. 237 */ 238 public boolean getLeftStickButton() { 239 return getRawButton(Button.kLeftStick.value); 240 } 241 242 /** 243 * Read the value of the right stick button (RSB) on the controller. 244 * 245 * @return The state of the button. 246 */ 247 public boolean getRightStickButton() { 248 return getRawButton(Button.kRightStick.value); 249 } 250 251 /** 252 * Whether the left stick button (LSB) was pressed since the last check. 253 * 254 * @return Whether the button was pressed since the last check. 255 */ 256 public boolean getLeftStickButtonPressed() { 257 return getRawButtonPressed(Button.kLeftStick.value); 258 } 259 260 /** 261 * Whether the right stick button (RSB) was pressed since the last check. 262 * 263 * @return Whether the button was pressed since the last check. 264 */ 265 public boolean getRightStickButtonPressed() { 266 return getRawButtonPressed(Button.kRightStick.value); 267 } 268 269 /** 270 * Whether the left stick button (LSB) was released since the last check. 271 * 272 * @return Whether the button was released since the last check. 273 */ 274 public boolean getLeftStickButtonReleased() { 275 return getRawButtonReleased(Button.kLeftStick.value); 276 } 277 278 /** 279 * Whether the right stick (RSB) button was released since the last check. 280 * 281 * @return Whether the button was released since the last check. 282 */ 283 public boolean getRightStickButtonReleased() { 284 return getRawButtonReleased(Button.kRightStick.value); 285 } 286 287 /** 288 * Constructs an event instance around the left stick button's digital signal. 289 * 290 * @param loop the event loop instance to attach the event to. 291 * @return an event instance representing the left stick button's digital signal attached to the 292 * given loop. 293 */ 294 public BooleanEvent leftStick(EventLoop loop) { 295 return new BooleanEvent(loop, this::getLeftStickButton); 296 } 297 298 /** 299 * Constructs an event instance around the right stick button's digital signal. 300 * 301 * @param loop the event loop instance to attach the event to. 302 * @return an event instance representing the right stick button's digital signal attached to the 303 * given loop. 304 */ 305 public BooleanEvent rightStick(EventLoop loop) { 306 return new BooleanEvent(loop, this::getRightStickButton); 307 } 308 309 /** 310 * Read the value of the A button on the controller. 311 * 312 * @return The state of the button. 313 */ 314 public boolean getAButton() { 315 return getRawButton(Button.kA.value); 316 } 317 318 /** 319 * Whether the A button was pressed since the last check. 320 * 321 * @return Whether the button was pressed since the last check. 322 */ 323 public boolean getAButtonPressed() { 324 return getRawButtonPressed(Button.kA.value); 325 } 326 327 /** 328 * Whether the A button was released since the last check. 329 * 330 * @return Whether the button was released since the last check. 331 */ 332 public boolean getAButtonReleased() { 333 return getRawButtonReleased(Button.kA.value); 334 } 335 336 /** 337 * Constructs an event instance around the A button's digital signal. 338 * 339 * @param loop the event loop instance to attach the event to. 340 * @return an event instance representing the A button's digital signal attached to the given 341 * loop. 342 */ 343 @SuppressWarnings("MethodName") 344 public BooleanEvent a(EventLoop loop) { 345 return new BooleanEvent(loop, this::getAButton); 346 } 347 348 /** 349 * Read the value of the B button on the controller. 350 * 351 * @return The state of the button. 352 */ 353 public boolean getBButton() { 354 return getRawButton(Button.kB.value); 355 } 356 357 /** 358 * Whether the B button was pressed since the last check. 359 * 360 * @return Whether the button was pressed since the last check. 361 */ 362 public boolean getBButtonPressed() { 363 return getRawButtonPressed(Button.kB.value); 364 } 365 366 /** 367 * Whether the B button was released since the last check. 368 * 369 * @return Whether the button was released since the last check. 370 */ 371 public boolean getBButtonReleased() { 372 return getRawButtonReleased(Button.kB.value); 373 } 374 375 /** 376 * Constructs an event instance around the B button's digital signal. 377 * 378 * @param loop the event loop instance to attach the event to. 379 * @return an event instance representing the B button's digital signal attached to the given 380 * loop. 381 */ 382 @SuppressWarnings("MethodName") 383 public BooleanEvent b(EventLoop loop) { 384 return new BooleanEvent(loop, this::getBButton); 385 } 386 387 /** 388 * Read the value of the X button on the controller. 389 * 390 * @return The state of the button. 391 */ 392 public boolean getXButton() { 393 return getRawButton(Button.kX.value); 394 } 395 396 /** 397 * Whether the X button was pressed since the last check. 398 * 399 * @return Whether the button was pressed since the last check. 400 */ 401 public boolean getXButtonPressed() { 402 return getRawButtonPressed(Button.kX.value); 403 } 404 405 /** 406 * Whether the X button was released since the last check. 407 * 408 * @return Whether the button was released since the last check. 409 */ 410 public boolean getXButtonReleased() { 411 return getRawButtonReleased(Button.kX.value); 412 } 413 414 /** 415 * Constructs an event instance around the X button's digital signal. 416 * 417 * @param loop the event loop instance to attach the event to. 418 * @return an event instance representing the X button's digital signal attached to the given 419 * loop. 420 */ 421 @SuppressWarnings("MethodName") 422 public BooleanEvent x(EventLoop loop) { 423 return new BooleanEvent(loop, this::getXButton); 424 } 425 426 /** 427 * Read the value of the Y button on the controller. 428 * 429 * @return The state of the button. 430 */ 431 public boolean getYButton() { 432 return getRawButton(Button.kY.value); 433 } 434 435 /** 436 * Whether the Y button was pressed since the last check. 437 * 438 * @return Whether the button was pressed since the last check. 439 */ 440 public boolean getYButtonPressed() { 441 return getRawButtonPressed(Button.kY.value); 442 } 443 444 /** 445 * Whether the Y button was released since the last check. 446 * 447 * @return Whether the button was released since the last check. 448 */ 449 public boolean getYButtonReleased() { 450 return getRawButtonReleased(Button.kY.value); 451 } 452 453 /** 454 * Constructs an event instance around the Y button's digital signal. 455 * 456 * @param loop the event loop instance to attach the event to. 457 * @return an event instance representing the Y button's digital signal attached to the given 458 * loop. 459 */ 460 @SuppressWarnings("MethodName") 461 public BooleanEvent y(EventLoop loop) { 462 return new BooleanEvent(loop, this::getYButton); 463 } 464 465 /** 466 * Read the value of the back button on the controller. 467 * 468 * @return The state of the button. 469 */ 470 public boolean getBackButton() { 471 return getRawButton(Button.kBack.value); 472 } 473 474 /** 475 * Whether the back button was pressed since the last check. 476 * 477 * @return Whether the button was pressed since the last check. 478 */ 479 public boolean getBackButtonPressed() { 480 return getRawButtonPressed(Button.kBack.value); 481 } 482 483 /** 484 * Whether the back button was released since the last check. 485 * 486 * @return Whether the button was released since the last check. 487 */ 488 public boolean getBackButtonReleased() { 489 return getRawButtonReleased(Button.kBack.value); 490 } 491 492 /** 493 * Constructs an event instance around the back button's digital signal. 494 * 495 * @param loop the event loop instance to attach the event to. 496 * @return an event instance representing the back button's digital signal attached to the given 497 * loop. 498 */ 499 public BooleanEvent back(EventLoop loop) { 500 return new BooleanEvent(loop, this::getBackButton); 501 } 502 503 /** 504 * Read the value of the start button on the controller. 505 * 506 * @return The state of the button. 507 */ 508 public boolean getStartButton() { 509 return getRawButton(Button.kStart.value); 510 } 511 512 /** 513 * Whether the start button was pressed since the last check. 514 * 515 * @return Whether the button was pressed since the last check. 516 */ 517 public boolean getStartButtonPressed() { 518 return getRawButtonPressed(Button.kStart.value); 519 } 520 521 /** 522 * Whether the start button was released since the last check. 523 * 524 * @return Whether the button was released since the last check. 525 */ 526 public boolean getStartButtonReleased() { 527 return getRawButtonReleased(Button.kStart.value); 528 } 529 530 /** 531 * Constructs an event instance around the start button's digital signal. 532 * 533 * @param loop the event loop instance to attach the event to. 534 * @return an event instance representing the start button's digital signal attached to the given 535 * loop. 536 */ 537 public BooleanEvent start(EventLoop loop) { 538 return new BooleanEvent(loop, this::getStartButton); 539 } 540 541 /** 542 * Constructs an event instance around the axis value of the left trigger. The returned trigger 543 * will be true when the axis value is greater than {@code threshold}. 544 * 545 * @param threshold the minimum axis value for the returned {@link BooleanEvent} to be true. This 546 * value should be in the range [0, 1] where 0 is the unpressed state of the axis. 547 * @param loop the event loop instance to attach the event to. 548 * @return an event instance that is true when the left trigger's axis exceeds the provided 549 * threshold, attached to the given event loop 550 */ 551 public BooleanEvent leftTrigger(double threshold, EventLoop loop) { 552 return new BooleanEvent(loop, () -> getLeftTriggerAxis() > threshold); 553 } 554 555 /** 556 * Constructs an event instance around the axis value of the left trigger. The returned trigger 557 * will be true when the axis value is greater than 0.5. 558 * 559 * @param loop the event loop instance to attach the event to. 560 * @return an event instance that is true when the left trigger's axis exceeds the provided 561 * threshold, attached to the given event loop 562 */ 563 public BooleanEvent leftTrigger(EventLoop loop) { 564 return leftTrigger(0.5, loop); 565 } 566 567 /** 568 * Constructs an event instance around the axis value of the right trigger. The returned trigger 569 * will be true when the axis value is greater than {@code threshold}. 570 * 571 * @param threshold the minimum axis value for the returned {@link BooleanEvent} to be true. This 572 * value should be in the range [0, 1] where 0 is the unpressed state of the axis. 573 * @param loop the event loop instance to attach the event to. 574 * @return an event instance that is true when the right trigger's axis exceeds the provided 575 * threshold, attached to the given event loop 576 */ 577 public BooleanEvent rightTrigger(double threshold, EventLoop loop) { 578 return new BooleanEvent(loop, () -> getRightTriggerAxis() > threshold); 579 } 580 581 /** 582 * Constructs an event instance around the axis value of the right trigger. The returned trigger 583 * will be true when the axis value is greater than 0.5. 584 * 585 * @param loop the event loop instance to attach the event to. 586 * @return an event instance that is true when the right trigger's axis exceeds the provided 587 * threshold, attached to the given event loop 588 */ 589 public BooleanEvent rightTrigger(EventLoop loop) { 590 return rightTrigger(0.5, loop); 591 } 592}