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