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