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 PS4 controllers connected to the Driver Station. 014 * 015 * <p>This class handles PS4 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 PS4Controller extends GenericHID { 020 /** 021 * Construct an instance of a device. 022 * 023 * @param port The port index on the Driver Station that the device is plugged into. 024 */ 025 public PS4Controller(int port) { 026 super(port); 027 HAL.report(tResourceType.kResourceType_PS4Controller, port + 1); 028 } 029 030 /** Represents a digital button on a PS4Controller. */ 031 public enum Button { 032 kSquare(1), 033 kCross(2), 034 kCircle(3), 035 kTriangle(4), 036 kL1(5), 037 kR1(6), 038 kL2(7), 039 kR2(8), 040 kShare(9), 041 kOptions(10), 042 kL3(11), 043 kR3(12), 044 kPS(13), 045 kTouchpad(14); 046 047 public final int value; 048 049 Button(int index) { 050 this.value = index; 051 } 052 053 /** 054 * Get the human-friendly name of the button, matching the relevant methods. This is done by 055 * stripping the leading `k`, and if not the touchpad append `Button`. 056 * 057 * <p>Primarily used for automated unit tests. 058 * 059 * @return the human-friendly name of the button. 060 */ 061 @Override 062 public String toString() { 063 var name = this.name().substring(1); // Remove leading `k` 064 if (this == kTouchpad) { 065 return name; 066 } 067 return name + "Button"; 068 } 069 } 070 071 /** Represents an axis on a PS4Controller. */ 072 public enum Axis { 073 kLeftX(0), 074 kLeftY(1), 075 kRightX(2), 076 kRightY(5), 077 kL2(3), 078 kR2(4); 079 080 public final int value; 081 082 Axis(int index) { 083 value = index; 084 } 085 086 /** 087 * Get the human-friendly name of the axis, matching the relevant methods. This is done by 088 * stripping the leading `k`, and if one of L2/R2 append `Axis`. 089 * 090 * <p>Primarily used for automated unit tests. 091 * 092 * @return the human-friendly name of the axis. 093 */ 094 @Override 095 public String toString() { 096 var name = this.name().substring(1); // Remove leading `k` 097 if (name.endsWith("2")) { 098 return name + "Axis"; 099 } 100 return name; 101 } 102 } 103 104 /** 105 * Get the X axis value of left side of the controller. 106 * 107 * @return the axis value. 108 */ 109 public double getLeftX() { 110 return getRawAxis(Axis.kLeftX.value); 111 } 112 113 /** 114 * Get the X axis value of right side of the controller. 115 * 116 * @return the axis value. 117 */ 118 public double getRightX() { 119 return getRawAxis(Axis.kRightX.value); 120 } 121 122 /** 123 * Get the Y axis value of left side of the controller. 124 * 125 * @return the axis value. 126 */ 127 public double getLeftY() { 128 return getRawAxis(Axis.kLeftY.value); 129 } 130 131 /** 132 * Get the Y axis value of right side of the controller. 133 * 134 * @return the axis value. 135 */ 136 public double getRightY() { 137 return getRawAxis(Axis.kRightY.value); 138 } 139 140 /** 141 * Get the L2 axis value of the controller. Note that this axis is bound to the range of [0, 1] as 142 * opposed to the usual [-1, 1]. 143 * 144 * @return the axis value. 145 */ 146 public double getL2Axis() { 147 return getRawAxis(Axis.kL2.value); 148 } 149 150 /** 151 * Get the R2 axis value of the controller. Note that this axis is bound to the range of [0, 1] as 152 * opposed to the usual [-1, 1]. 153 * 154 * @return the axis value. 155 */ 156 public double getR2Axis() { 157 return getRawAxis(Axis.kR2.value); 158 } 159 160 /** 161 * Read the value of the left trigger button on the controller. 162 * 163 * @return The state of the button. 164 */ 165 public boolean getL2Button() { 166 return getRawButton(Button.kL2.value); 167 } 168 169 /** 170 * Read the value of the right trigger button on the controller. 171 * 172 * @return The state of the button. 173 */ 174 public boolean getR2Button() { 175 return getRawButton(Button.kR2.value); 176 } 177 178 /** 179 * Whether the L2 button was pressed since the last check. 180 * 181 * @return Whether the button was pressed since the last check. 182 */ 183 public boolean getL2ButtonPressed() { 184 return getRawButtonPressed(Button.kL2.value); 185 } 186 187 /** 188 * Whether the R2 button was pressed since the last check. 189 * 190 * @return Whether the button was pressed since the last check. 191 */ 192 public boolean getR2ButtonPressed() { 193 return getRawButtonPressed(Button.kR2.value); 194 } 195 196 /** 197 * Whether the L2 button was released since the last check. 198 * 199 * @return Whether the button was released since the last check. 200 */ 201 public boolean getL2ButtonReleased() { 202 return getRawButtonReleased(Button.kL2.value); 203 } 204 205 /** 206 * Whether the R2 button was released since the last check. 207 * 208 * @return Whether the button was released since the last check. 209 */ 210 public boolean getR2ButtonReleased() { 211 return getRawButtonReleased(Button.kR2.value); 212 } 213 214 /** 215 * Constructs an event instance around the L2 button's digital signal. 216 * 217 * @param loop the event loop instance to attach the event to. 218 * @return an event instance representing the L2 button's digital signal attached to the given 219 * loop. 220 */ 221 @SuppressWarnings("MethodName") 222 public BooleanEvent L2(EventLoop loop) { 223 return new BooleanEvent(loop, this::getL2Button); 224 } 225 226 /** 227 * Constructs an event instance around the R2 button's digital signal. 228 * 229 * @param loop the event loop instance to attach the event to. 230 * @return an event instance representing the R2 button's digital signal attached to the given 231 * loop. 232 */ 233 @SuppressWarnings("MethodName") 234 public BooleanEvent R2(EventLoop loop) { 235 return new BooleanEvent(loop, this::getR2Button); 236 } 237 238 /** 239 * Read the value of the L1 button on the controller. 240 * 241 * @return The state of the button. 242 */ 243 public boolean getL1Button() { 244 return getRawButton(Button.kL1.value); 245 } 246 247 /** 248 * Read the value of the R1 button on the controller. 249 * 250 * @return The state of the button. 251 */ 252 public boolean getR1Button() { 253 return getRawButton(Button.kR1.value); 254 } 255 256 /** 257 * Whether the L1 button was pressed since the last check. 258 * 259 * @return Whether the button was pressed since the last check. 260 */ 261 public boolean getL1ButtonPressed() { 262 return getRawButtonPressed(Button.kL1.value); 263 } 264 265 /** 266 * Whether the R1 button was pressed since the last check. 267 * 268 * @return Whether the button was pressed since the last check. 269 */ 270 public boolean getR1ButtonPressed() { 271 return getRawButtonPressed(Button.kR1.value); 272 } 273 274 /** 275 * Whether the L1 button was released since the last check. 276 * 277 * @return Whether the button was released since the last check. 278 */ 279 public boolean getL1ButtonReleased() { 280 return getRawButtonReleased(Button.kL1.value); 281 } 282 283 /** 284 * Whether the R1 button was released since the last check. 285 * 286 * @return Whether the button was released since the last check. 287 */ 288 public boolean getR1ButtonReleased() { 289 return getRawButtonReleased(Button.kR1.value); 290 } 291 292 /** 293 * Constructs an event instance around the L1 button's digital signal. 294 * 295 * @param loop the event loop instance to attach the event to. 296 * @return an event instance representing the L1 button's digital signal attached to the given 297 * loop. 298 */ 299 @SuppressWarnings("MethodName") 300 public BooleanEvent L1(EventLoop loop) { 301 return new BooleanEvent(loop, this::getL1Button); 302 } 303 304 /** 305 * Constructs an event instance around the R1 button's digital signal. 306 * 307 * @param loop the event loop instance to attach the event to. 308 * @return an event instance representing the R1 button's digital signal attached to the given 309 * loop. 310 */ 311 @SuppressWarnings("MethodName") 312 public BooleanEvent R1(EventLoop loop) { 313 return new BooleanEvent(loop, this::getR1Button); 314 } 315 316 /** 317 * Read the value of the L3 button (pressing the left analog stick) on the controller. 318 * 319 * @return The state of the button. 320 */ 321 public boolean getL3Button() { 322 return getRawButton(Button.kL3.value); 323 } 324 325 /** 326 * Read the value of the R3 button (pressing the right analog stick) on the controller. 327 * 328 * @return The state of the button. 329 */ 330 public boolean getR3Button() { 331 return getRawButton(Button.kR3.value); 332 } 333 334 /** 335 * Whether the L3 (left stick) button was pressed since the last check. 336 * 337 * @return Whether the button was pressed since the last check. 338 */ 339 public boolean getL3ButtonPressed() { 340 return getRawButtonPressed(Button.kL3.value); 341 } 342 343 /** 344 * Whether the R3 (right stick) button was pressed since the last check. 345 * 346 * @return Whether the button was pressed since the last check. 347 */ 348 public boolean getR3ButtonPressed() { 349 return getRawButtonPressed(Button.kR3.value); 350 } 351 352 /** 353 * Whether the L3 (left stick) button was released since the last check. 354 * 355 * @return Whether the button was released since the last check. 356 */ 357 public boolean getL3ButtonReleased() { 358 return getRawButtonReleased(Button.kL3.value); 359 } 360 361 /** 362 * Whether the R3 (right stick) button was released since the last check. 363 * 364 * @return Whether the button was released since the last check. 365 */ 366 public boolean getR3ButtonReleased() { 367 return getRawButtonReleased(Button.kR3.value); 368 } 369 370 /** 371 * Constructs an event instance around the L3 button's digital signal. 372 * 373 * @param loop the event loop instance to attach the event to. 374 * @return an event instance representing the L3 button's digital signal attached to the given 375 * loop. 376 */ 377 @SuppressWarnings("MethodName") 378 public BooleanEvent L3(EventLoop loop) { 379 return new BooleanEvent(loop, this::getL3Button); 380 } 381 382 /** 383 * Constructs an event instance around the R3 button's digital signal. 384 * 385 * @param loop the event loop instance to attach the event to. 386 * @return an event instance representing the R3 button's digital signal attached to the given 387 * loop. 388 */ 389 @SuppressWarnings("MethodName") 390 public BooleanEvent R3(EventLoop loop) { 391 return new BooleanEvent(loop, this::getR3Button); 392 } 393 394 /** 395 * Read the value of the Square button on the controller. 396 * 397 * @return The state of the button. 398 */ 399 public boolean getSquareButton() { 400 return getRawButton(Button.kSquare.value); 401 } 402 403 /** 404 * Whether the Square button was pressed since the last check. 405 * 406 * @return Whether the button was pressed since the last check. 407 */ 408 public boolean getSquareButtonPressed() { 409 return getRawButtonPressed(Button.kSquare.value); 410 } 411 412 /** 413 * Whether the Square button was released since the last check. 414 * 415 * @return Whether the button was released since the last check. 416 */ 417 public boolean getSquareButtonReleased() { 418 return getRawButtonReleased(Button.kSquare.value); 419 } 420 421 /** 422 * Constructs an event instance around the square button's digital signal. 423 * 424 * @param loop the event loop instance to attach the event to. 425 * @return an event instance representing the square button's digital signal attached to the given 426 * loop. 427 */ 428 public BooleanEvent square(EventLoop loop) { 429 return new BooleanEvent(loop, this::getSquareButton); 430 } 431 432 /** 433 * Read the value of the Cross button on the controller. 434 * 435 * @return The state of the button. 436 */ 437 public boolean getCrossButton() { 438 return getRawButton(Button.kCross.value); 439 } 440 441 /** 442 * Whether the Cross button was pressed since the last check. 443 * 444 * @return Whether the button was pressed since the last check. 445 */ 446 public boolean getCrossButtonPressed() { 447 return getRawButtonPressed(Button.kCross.value); 448 } 449 450 /** 451 * Whether the Cross button was released since the last check. 452 * 453 * @return Whether the button was released since the last check. 454 */ 455 public boolean getCrossButtonReleased() { 456 return getRawButtonReleased(Button.kCross.value); 457 } 458 459 /** 460 * Constructs an event instance around the cross button's digital signal. 461 * 462 * @param loop the event loop instance to attach the event to. 463 * @return an event instance representing the cross button's digital signal attached to the given 464 * loop. 465 */ 466 public BooleanEvent cross(EventLoop loop) { 467 return new BooleanEvent(loop, this::getCrossButton); 468 } 469 470 /** 471 * Read the value of the Triangle button on the controller. 472 * 473 * @return The state of the button. 474 */ 475 public boolean getTriangleButton() { 476 return getRawButton(Button.kTriangle.value); 477 } 478 479 /** 480 * Whether the Triangle button was pressed since the last check. 481 * 482 * @return Whether the button was pressed since the last check. 483 */ 484 public boolean getTriangleButtonPressed() { 485 return getRawButtonPressed(Button.kTriangle.value); 486 } 487 488 /** 489 * Whether the Triangle button was released since the last check. 490 * 491 * @return Whether the button was released since the last check. 492 */ 493 public boolean getTriangleButtonReleased() { 494 return getRawButtonReleased(Button.kTriangle.value); 495 } 496 497 /** 498 * Constructs an event instance around the triangle button's digital signal. 499 * 500 * @param loop the event loop instance to attach the event to. 501 * @return an event instance representing the triangle button's digital signal attached to the 502 * given loop. 503 */ 504 public BooleanEvent triangle(EventLoop loop) { 505 return new BooleanEvent(loop, this::getTriangleButton); 506 } 507 508 /** 509 * Read the value of the Circle button on the controller. 510 * 511 * @return The state of the button. 512 */ 513 public boolean getCircleButton() { 514 return getRawButton(Button.kCircle.value); 515 } 516 517 /** 518 * Whether the Circle button was pressed since the last check. 519 * 520 * @return Whether the button was pressed since the last check. 521 */ 522 public boolean getCircleButtonPressed() { 523 return getRawButtonPressed(Button.kCircle.value); 524 } 525 526 /** 527 * Whether the Circle button was released since the last check. 528 * 529 * @return Whether the button was released since the last check. 530 */ 531 public boolean getCircleButtonReleased() { 532 return getRawButtonReleased(Button.kCircle.value); 533 } 534 535 /** 536 * Constructs an event instance around the circle button's digital signal. 537 * 538 * @param loop the event loop instance to attach the event to. 539 * @return an event instance representing the circle button's digital signal attached to the given 540 * loop. 541 */ 542 public BooleanEvent circle(EventLoop loop) { 543 return new BooleanEvent(loop, this::getCircleButton); 544 } 545 546 /** 547 * Read the value of the share button on the controller. 548 * 549 * @return The state of the button. 550 */ 551 public boolean getShareButton() { 552 return getRawButton(Button.kShare.value); 553 } 554 555 /** 556 * Whether the share button was pressed since the last check. 557 * 558 * @return Whether the button was pressed since the last check. 559 */ 560 public boolean getShareButtonPressed() { 561 return getRawButtonPressed(Button.kShare.value); 562 } 563 564 /** 565 * Whether the share button was released since the last check. 566 * 567 * @return Whether the button was released since the last check. 568 */ 569 public boolean getShareButtonReleased() { 570 return getRawButtonReleased(Button.kShare.value); 571 } 572 573 /** 574 * Constructs an event instance around the share button's digital signal. 575 * 576 * @param loop the event loop instance to attach the event to. 577 * @return an event instance representing the share button's digital signal attached to the given 578 * loop. 579 */ 580 @SuppressWarnings("MethodName") 581 public BooleanEvent share(EventLoop loop) { 582 return new BooleanEvent(loop, this::getShareButton); 583 } 584 585 /** 586 * Read the value of the PS button on the controller. 587 * 588 * @return The state of the button. 589 */ 590 public boolean getPSButton() { 591 return getRawButton(Button.kPS.value); 592 } 593 594 /** 595 * Whether the PS button was pressed since the last check. 596 * 597 * @return Whether the button was pressed since the last check. 598 */ 599 public boolean getPSButtonPressed() { 600 return getRawButtonPressed(Button.kPS.value); 601 } 602 603 /** 604 * Whether the PS button was released since the last check. 605 * 606 * @return Whether the button was released since the last check. 607 */ 608 public boolean getPSButtonReleased() { 609 return getRawButtonReleased(Button.kPS.value); 610 } 611 612 /** 613 * Constructs an event instance around the PS button's digital signal. 614 * 615 * @param loop the event loop instance to attach the event to. 616 * @return an event instance representing the PS button's digital signal attached to the given 617 * loop. 618 */ 619 @SuppressWarnings("MethodName") 620 public BooleanEvent PS(EventLoop loop) { 621 return new BooleanEvent(loop, this::getPSButton); 622 } 623 624 /** 625 * Read the value of the options button on the controller. 626 * 627 * @return The state of the button. 628 */ 629 public boolean getOptionsButton() { 630 return getRawButton(Button.kOptions.value); 631 } 632 633 /** 634 * Whether the options button was pressed since the last check. 635 * 636 * @return Whether the button was pressed since the last check. 637 */ 638 public boolean getOptionsButtonPressed() { 639 return getRawButtonPressed(Button.kOptions.value); 640 } 641 642 /** 643 * Whether the options button was released since the last check. 644 * 645 * @return Whether the button was released since the last check. 646 */ 647 public boolean getOptionsButtonReleased() { 648 return getRawButtonReleased(Button.kOptions.value); 649 } 650 651 /** 652 * Constructs an event instance around the options button's digital signal. 653 * 654 * @param loop the event loop instance to attach the event to. 655 * @return an event instance representing the options button's digital signal attached to the 656 * given loop. 657 */ 658 public BooleanEvent options(EventLoop loop) { 659 return new BooleanEvent(loop, this::getOptionsButton); 660 } 661 662 /** 663 * Read the value of the touchpad on the controller. 664 * 665 * @return The state of the touchpad. 666 */ 667 public boolean getTouchpad() { 668 return getRawButton(Button.kTouchpad.value); 669 } 670 671 /** 672 * Whether the touchpad was pressed since the last check. 673 * 674 * @return Whether the touchpad was pressed since the last check. 675 */ 676 public boolean getTouchpadPressed() { 677 return getRawButtonPressed(Button.kTouchpad.value); 678 } 679 680 /** 681 * Whether the touchpad was released since the last check. 682 * 683 * @return Whether the touchpad was released since the last check. 684 */ 685 public boolean getTouchpadReleased() { 686 return getRawButtonReleased(Button.kTouchpad.value); 687 } 688 689 /** 690 * Constructs an event instance around the touchpad's digital signal. 691 * 692 * @param loop the event loop instance to attach the event to. 693 * @return an event instance representing the touchpad's digital signal attached to the given 694 * loop. 695 */ 696 public BooleanEvent touchpad(EventLoop loop) { 697 return new BooleanEvent(loop, this::getTouchpad); 698 } 699}