001/* 002 * Copyright (C) Cross The Road Electronics. All rights reserved. 003 * License information can be found in CTRE_LICENSE.txt 004 * For support and suggestions contact support@ctr-electronics.com or file 005 * an issue tracker at https://github.com/CrossTheRoadElec/Phoenix-Releases 006 */ 007package com.ctre.phoenix6.swerve; 008 009import static edu.wpi.first.units.Units.*; 010 011import java.util.HashMap; 012 013import com.ctre.phoenix6.StatusCode; 014import com.ctre.phoenix6.controls.CoastOut; 015import com.ctre.phoenix6.controls.PositionTorqueCurrentFOC; 016import com.ctre.phoenix6.controls.PositionVoltage; 017import com.ctre.phoenix6.controls.VoltageOut; 018import com.ctre.phoenix6.swerve.SwerveDrivetrain.SwerveControlParameters; 019import com.ctre.phoenix6.swerve.jni.SwerveJNI; 020import com.ctre.phoenix6.swerve.utility.PhoenixPIDController; 021 022import edu.wpi.first.math.geometry.Rotation2d; 023import edu.wpi.first.math.geometry.Translation2d; 024import edu.wpi.first.math.kinematics.ChassisSpeeds; 025import edu.wpi.first.math.kinematics.SwerveDriveKinematics; 026import edu.wpi.first.units.measure.*; 027 028/** 029 * Container for all the Swerve Requests. Use this to find all applicable swerve 030 * drive requests. 031 * <p> 032 * This is also an interface common to all swerve drive control requests that 033 * allow the request to calculate the state to apply to the modules. 034 */ 035public interface SwerveRequest { 036 /** 037 * In field-centric control, the direction of "forward" is sometimes different 038 * depending on perspective. This addresses which forward to use. 039 */ 040 public enum ForwardPerspectiveValue { 041 /** 042 * "Forward" (positive X) is determined from the operator's perspective. This 043 * is important for most teleop driven field-centric requests, where positive 044 * X means to drive away from the operator. 045 * <p> 046 * Important: Users must specify the OperatorPerspective in the SwerveDrivetrain object 047 */ 048 OperatorPerspective(0), 049 /** 050 * "Forward" (positive X) is always from the perspective of the blue alliance (i.e. towards 051 * the red alliance). This is important in situations such as path following where positive 052 * X is always from the blue alliance perspective, regardless of where the operator is 053 * physically located. 054 */ 055 BlueAlliance(1); 056 057 public final int value; 058 059 ForwardPerspectiveValue(int initValue) { 060 this.value = initValue; 061 } 062 063 private static HashMap<Integer, ForwardPerspectiveValue> _map = null; 064 static { 065 _map = new HashMap<Integer, ForwardPerspectiveValue>(); 066 for (ForwardPerspectiveValue type : ForwardPerspectiveValue.values()) { 067 _map.put(type.value, type); 068 } 069 } 070 071 /** 072 * Gets ForwardPerspectiveValue from specified value 073 * 074 * @param value Value of ForwardPerspectiveValue 075 * @return ForwardPerspectiveValue of specified value 076 */ 077 public static ForwardPerspectiveValue valueOf(int value) { 078 ForwardPerspectiveValue retval = _map.get(value); 079 if (retval != null) 080 return retval; 081 return ForwardPerspectiveValue.values()[0]; 082 } 083 } 084 085 /** 086 * Applies this swerve request to the given modules. This is 087 * typically called by the SwerveDrivetrain odometry thread. 088 * <p> 089 * For native swerve requests, this API can be called from a 090 * non-native request's {@code apply} to compose the two together. 091 * 092 * @param parameters Parameters the control request needs to calculate the module state 093 * @param modulesToApply Modules to which the control request is applied 094 * @return Status code of sending the request 095 */ 096 public StatusCode apply(SwerveControlParameters parameters, SwerveModule<?, ?, ?>... modulesToApply); 097 098 /** Swerve requests implemented in native code. */ 099 public interface NativeSwerveRequest extends SwerveRequest { 100 /** 101 * Applies a native swerve request to the native drivetrain with the provided ID. 102 * <p> 103 * When this is implemented, the regular {@link #apply} function should do nothing 104 * (return OK). Additionally, this cannot be called from another swerve request's 105 * apply method, as this overrides the native swerve request of the drivetrain. 106 * <p> 107 * Unlike {@link #apply}, this function is called every time {@link SwerveDrivetrain#setControl} 108 * is run, not every loop of the odometry thread. Instead, the underlying native 109 * request is run at the full update frequency of the odometry thread. 110 * 111 * @param id ID of the native swerve drivetrain 112 */ 113 public void applyNative(int id); 114 } 115 116 117 /** 118 * Does nothing to the swerve module state. This is the default state of a newly 119 * created swerve drive mechanism. 120 */ 121 public static class Idle implements NativeSwerveRequest { 122 123 124 125 public StatusCode apply(SwerveControlParameters parameters, SwerveModule<?, ?, ?>... modulesToApply) { 126 return StatusCode.valueOf(SwerveJNI.JNI_Request_Apply_Idle(parameters.drivetrainId)); 127 } 128 129 public void applyNative(int id) { 130 SwerveJNI.JNI_SetControl_Idle(id); 131 } 132 } 133 134 /** 135 * Sets the swerve drive module states to point inward on the robot in an "X" 136 * fashion, creating a natural brake which will oppose any motion. 137 */ 138 public static class SwerveDriveBrake implements NativeSwerveRequest { 139 /** 140 * The type of control request to use for the drive motor. 141 */ 142 public SwerveModule.DriveRequestType DriveRequestType = SwerveModule.DriveRequestType.OpenLoopVoltage; 143 /** 144 * The type of control request to use for the drive motor. 145 */ 146 public SwerveModule.SteerRequestType SteerRequestType = SwerveModule.SteerRequestType.Position; 147 148 /** 149 * Modifies the DriveRequestType parameter and returns itself. 150 * <p> 151 * The type of control request to use for the drive motor. 152 * 153 * @param newDriveRequestType Parameter to modify 154 * @return this object 155 */ 156 public SwerveDriveBrake withDriveRequestType(SwerveModule.DriveRequestType newDriveRequestType) { 157 this.DriveRequestType = newDriveRequestType; 158 return this; 159 } 160 161 /** 162 * Modifies the SteerRequestType parameter and returns itself. 163 * <p> 164 * The type of control request to use for the drive motor. 165 * 166 * @param newSteerRequestType Parameter to modify 167 * @return this object 168 */ 169 public SwerveDriveBrake withSteerRequestType(SwerveModule.SteerRequestType newSteerRequestType) { 170 this.SteerRequestType = newSteerRequestType; 171 return this; 172 } 173 174 public StatusCode apply(SwerveControlParameters parameters, SwerveModule<?, ?, ?>... modulesToApply) { 175 return StatusCode.valueOf(SwerveJNI.JNI_Request_Apply_SwerveDriveBrake(parameters.drivetrainId, 176 DriveRequestType.value, 177 SteerRequestType.value)); 178 } 179 180 public void applyNative(int id) { 181 SwerveJNI.JNI_SetControl_SwerveDriveBrake(id, 182 DriveRequestType.value, 183 SteerRequestType.value); 184 } 185 } 186 187 /** 188 * Drives the swerve drivetrain in a field-centric manner. 189 * <p> 190 * When users use this request, they specify the direction the robot should 191 * travel oriented against the field, and the rate at which their robot should 192 * rotate about the center of the robot. 193 * <p> 194 * An example scenario is that the robot is oriented to the east, the VelocityX 195 * is +5 m/s, VelocityY is 0 m/s, and RotationRate is 0.5 rad/s. In this 196 * scenario, the robot would drive northward at 5 m/s and turn counterclockwise 197 * at 0.5 rad/s. 198 */ 199 public static class FieldCentric implements NativeSwerveRequest { 200 /** 201 * The velocity in the X direction, in m/s. X is defined as forward according to 202 * WPILib convention, so this determines how fast to travel forward. 203 */ 204 public double VelocityX = 0; 205 /** 206 * The velocity in the Y direction, in m/s. Y is defined as to the left 207 * according to WPILib convention, so this determines how fast to travel to the 208 * left. 209 */ 210 public double VelocityY = 0; 211 /** 212 * The angular rate to rotate at, in radians per second. Angular rate is defined 213 * as counterclockwise positive, so this determines how fast to turn 214 * counterclockwise. 215 */ 216 public double RotationalRate = 0; 217 /** 218 * The allowable deadband of the request, in m/s. 219 */ 220 public double Deadband = 0; 221 /** 222 * The rotational deadband of the request, in radians per second. 223 */ 224 public double RotationalDeadband = 0; 225 /** 226 * The center of rotation the robot should rotate around. This is (0,0) by 227 * default, which will rotate around the center of the robot. 228 */ 229 public Translation2d CenterOfRotation = new Translation2d(); 230 /** 231 * The type of control request to use for the drive motor. 232 */ 233 public SwerveModule.DriveRequestType DriveRequestType = SwerveModule.DriveRequestType.OpenLoopVoltage; 234 /** 235 * The type of control request to use for the drive motor. 236 */ 237 public SwerveModule.SteerRequestType SteerRequestType = SwerveModule.SteerRequestType.Position; 238 /** 239 * Whether to desaturate wheel speeds before applying. For more information, see 240 * the documentation of {@link SwerveDriveKinematics#desaturateWheelSpeeds}. 241 */ 242 public boolean DesaturateWheelSpeeds = true; 243 /** 244 * The perspective to use when determining which direction is forward. 245 */ 246 public ForwardPerspectiveValue ForwardPerspective = ForwardPerspectiveValue.OperatorPerspective; 247 248 /** 249 * Modifies the VelocityX parameter and returns itself. 250 * <p> 251 * The velocity in the X direction, in m/s. X is defined as forward according to 252 * WPILib convention, so this determines how fast to travel forward. 253 * 254 * @param newVelocityX Parameter to modify 255 * @return this object 256 */ 257 public FieldCentric withVelocityX(double newVelocityX) { 258 this.VelocityX = newVelocityX; 259 return this; 260 } 261 262 /** 263 * Modifies the VelocityX parameter and returns itself. 264 * <p> 265 * The velocity in the X direction, in m/s. X is defined as forward according to 266 * WPILib convention, so this determines how fast to travel forward. 267 * 268 * @param newVelocityX Parameter to modify 269 * @return this object 270 */ 271 public FieldCentric withVelocityX(LinearVelocity newVelocityX) { 272 this.VelocityX = newVelocityX.in(MetersPerSecond); 273 return this; 274 } 275 276 /** 277 * Modifies the VelocityY parameter and returns itself. 278 * <p> 279 * The velocity in the Y direction, in m/s. Y is defined as to the left 280 * according to WPILib convention, so this determines how fast to travel to the 281 * left. 282 * 283 * @param newVelocityY Parameter to modify 284 * @return this object 285 */ 286 public FieldCentric withVelocityY(double newVelocityY) { 287 this.VelocityY = newVelocityY; 288 return this; 289 } 290 291 /** 292 * Modifies the VelocityY parameter and returns itself. 293 * <p> 294 * The velocity in the Y direction, in m/s. Y is defined as to the left 295 * according to WPILib convention, so this determines how fast to travel to the 296 * left. 297 * 298 * @param newVelocityY Parameter to modify 299 * @return this object 300 */ 301 public FieldCentric withVelocityY(LinearVelocity newVelocityY) { 302 this.VelocityY = newVelocityY.in(MetersPerSecond); 303 return this; 304 } 305 306 /** 307 * Modifies the RotationalRate parameter and returns itself. 308 * <p> 309 * The angular rate to rotate at, in radians per second. Angular rate is defined 310 * as counterclockwise positive, so this determines how fast to turn 311 * counterclockwise. 312 * 313 * @param newRotationalRate Parameter to modify 314 * @return this object 315 */ 316 public FieldCentric withRotationalRate(double newRotationalRate) { 317 this.RotationalRate = newRotationalRate; 318 return this; 319 } 320 321 /** 322 * Modifies the RotationalRate parameter and returns itself. 323 * <p> 324 * The angular rate to rotate at, in radians per second. Angular rate is defined 325 * as counterclockwise positive, so this determines how fast to turn 326 * counterclockwise. 327 * 328 * @param newRotationalRate Parameter to modify 329 * @return this object 330 */ 331 public FieldCentric withRotationalRate(AngularVelocity newRotationalRate) { 332 this.RotationalRate = newRotationalRate.in(RadiansPerSecond); 333 return this; 334 } 335 336 /** 337 * Modifies the Deadband parameter and returns itself. 338 * <p> 339 * The allowable deadband of the request, in m/s. 340 * 341 * @param newDeadband Parameter to modify 342 * @return this object 343 */ 344 public FieldCentric withDeadband(double newDeadband) { 345 this.Deadband = newDeadband; 346 return this; 347 } 348 349 /** 350 * Modifies the Deadband parameter and returns itself. 351 * <p> 352 * The allowable deadband of the request, in m/s. 353 * 354 * @param newDeadband Parameter to modify 355 * @return this object 356 */ 357 public FieldCentric withDeadband(LinearVelocity newDeadband) { 358 this.Deadband = newDeadband.in(MetersPerSecond); 359 return this; 360 } 361 362 /** 363 * Modifies the RotationalDeadband parameter and returns itself. 364 * <p> 365 * The rotational deadband of the request, in radians per second. 366 * 367 * @param newRotationalDeadband Parameter to modify 368 * @return this object 369 */ 370 public FieldCentric withRotationalDeadband(double newRotationalDeadband) { 371 this.RotationalDeadband = newRotationalDeadband; 372 return this; 373 } 374 375 /** 376 * Modifies the RotationalDeadband parameter and returns itself. 377 * <p> 378 * The rotational deadband of the request, in radians per second. 379 * 380 * @param newRotationalDeadband Parameter to modify 381 * @return this object 382 */ 383 public FieldCentric withRotationalDeadband(AngularVelocity newRotationalDeadband) { 384 this.RotationalDeadband = newRotationalDeadband.in(RadiansPerSecond); 385 return this; 386 } 387 388 /** 389 * Modifies the CenterOfRotation parameter and returns itself. 390 * <p> 391 * The center of rotation the robot should rotate around. This is (0,0) by 392 * default, which will rotate around the center of the robot. 393 * 394 * @param newCenterOfRotation Parameter to modify 395 * @return this object 396 */ 397 public FieldCentric withCenterOfRotation(Translation2d newCenterOfRotation) { 398 this.CenterOfRotation = newCenterOfRotation; 399 return this; 400 } 401 402 /** 403 * Modifies the DriveRequestType parameter and returns itself. 404 * <p> 405 * The type of control request to use for the drive motor. 406 * 407 * @param newDriveRequestType Parameter to modify 408 * @return this object 409 */ 410 public FieldCentric withDriveRequestType(SwerveModule.DriveRequestType newDriveRequestType) { 411 this.DriveRequestType = newDriveRequestType; 412 return this; 413 } 414 415 /** 416 * Modifies the SteerRequestType parameter and returns itself. 417 * <p> 418 * The type of control request to use for the drive motor. 419 * 420 * @param newSteerRequestType Parameter to modify 421 * @return this object 422 */ 423 public FieldCentric withSteerRequestType(SwerveModule.SteerRequestType newSteerRequestType) { 424 this.SteerRequestType = newSteerRequestType; 425 return this; 426 } 427 428 /** 429 * Modifies the DesaturateWheelSpeeds parameter and returns itself. 430 * <p> 431 * Whether to desaturate wheel speeds before applying. For more information, see 432 * the documentation of {@link SwerveDriveKinematics#desaturateWheelSpeeds}. 433 * 434 * @param newDesaturateWheelSpeeds Parameter to modify 435 * @return this object 436 */ 437 public FieldCentric withDesaturateWheelSpeeds(boolean newDesaturateWheelSpeeds) { 438 this.DesaturateWheelSpeeds = newDesaturateWheelSpeeds; 439 return this; 440 } 441 442 /** 443 * Modifies the ForwardPerspective parameter and returns itself. 444 * <p> 445 * The perspective to use when determining which direction is forward. 446 * 447 * @param newForwardPerspective Parameter to modify 448 * @return this object 449 */ 450 public FieldCentric withForwardPerspective(ForwardPerspectiveValue newForwardPerspective) { 451 this.ForwardPerspective = newForwardPerspective; 452 return this; 453 } 454 455 public StatusCode apply(SwerveControlParameters parameters, SwerveModule<?, ?, ?>... modulesToApply) { 456 return StatusCode.valueOf(SwerveJNI.JNI_Request_Apply_FieldCentric(parameters.drivetrainId, 457 VelocityX, 458 VelocityY, 459 RotationalRate, 460 Deadband, 461 RotationalDeadband, 462 CenterOfRotation.getX(), 463 CenterOfRotation.getY(), 464 DriveRequestType.value, 465 SteerRequestType.value, 466 DesaturateWheelSpeeds, 467 ForwardPerspective.value)); 468 } 469 470 public void applyNative(int id) { 471 SwerveJNI.JNI_SetControl_FieldCentric(id, 472 VelocityX, 473 VelocityY, 474 RotationalRate, 475 Deadband, 476 RotationalDeadband, 477 CenterOfRotation.getX(), 478 CenterOfRotation.getY(), 479 DriveRequestType.value, 480 SteerRequestType.value, 481 DesaturateWheelSpeeds, 482 ForwardPerspective.value); 483 } 484 } 485 486 /** 487 * Drives the swerve drivetrain in a robot-centric manner. 488 * <p> 489 * When users use this request, they specify the direction the robot should 490 * travel oriented against the robot itself, and the rate at which their robot 491 * should rotate about the center of the robot. 492 * <p> 493 * An example scenario is that the robot is oriented to the east, the VelocityX 494 * is +5 m/s, VelocityY is 0 m/s, and RotationRate is 0.5 rad/s. In this 495 * scenario, the robot would drive eastward at 5 m/s and turn counterclockwise 496 * at 0.5 rad/s. 497 */ 498 public static class RobotCentric implements NativeSwerveRequest { 499 /** 500 * The velocity in the X direction, in m/s. X is defined as forward according to 501 * WPILib convention, so this determines how fast to travel forward. 502 */ 503 public double VelocityX = 0; 504 /** 505 * The velocity in the Y direction, in m/s. Y is defined as to the left 506 * according to WPILib convention, so this determines how fast to travel to the 507 * left. 508 */ 509 public double VelocityY = 0; 510 /** 511 * The angular rate to rotate at, in radians per second. Angular rate is defined 512 * as counterclockwise positive, so this determines how fast to turn 513 * counterclockwise. 514 */ 515 public double RotationalRate = 0; 516 /** 517 * The allowable deadband of the request, in m/s. 518 */ 519 public double Deadband = 0; 520 /** 521 * The rotational deadband of the request, in radians per second. 522 */ 523 public double RotationalDeadband = 0; 524 /** 525 * The center of rotation the robot should rotate around. This is (0,0) by 526 * default, which will rotate around the center of the robot. 527 */ 528 public Translation2d CenterOfRotation = new Translation2d(); 529 /** 530 * The type of control request to use for the drive motor. 531 */ 532 public SwerveModule.DriveRequestType DriveRequestType = SwerveModule.DriveRequestType.OpenLoopVoltage; 533 /** 534 * The type of control request to use for the drive motor. 535 */ 536 public SwerveModule.SteerRequestType SteerRequestType = SwerveModule.SteerRequestType.Position; 537 /** 538 * Whether to desaturate wheel speeds before applying. For more information, see 539 * the documentation of {@link SwerveDriveKinematics#desaturateWheelSpeeds}. 540 */ 541 public boolean DesaturateWheelSpeeds = true; 542 543 /** 544 * Modifies the VelocityX parameter and returns itself. 545 * <p> 546 * The velocity in the X direction, in m/s. X is defined as forward according to 547 * WPILib convention, so this determines how fast to travel forward. 548 * 549 * @param newVelocityX Parameter to modify 550 * @return this object 551 */ 552 public RobotCentric withVelocityX(double newVelocityX) { 553 this.VelocityX = newVelocityX; 554 return this; 555 } 556 557 /** 558 * Modifies the VelocityX parameter and returns itself. 559 * <p> 560 * The velocity in the X direction, in m/s. X is defined as forward according to 561 * WPILib convention, so this determines how fast to travel forward. 562 * 563 * @param newVelocityX Parameter to modify 564 * @return this object 565 */ 566 public RobotCentric withVelocityX(LinearVelocity newVelocityX) { 567 this.VelocityX = newVelocityX.in(MetersPerSecond); 568 return this; 569 } 570 571 /** 572 * Modifies the VelocityY parameter and returns itself. 573 * <p> 574 * The velocity in the Y direction, in m/s. Y is defined as to the left 575 * according to WPILib convention, so this determines how fast to travel to the 576 * left. 577 * 578 * @param newVelocityY Parameter to modify 579 * @return this object 580 */ 581 public RobotCentric withVelocityY(double newVelocityY) { 582 this.VelocityY = newVelocityY; 583 return this; 584 } 585 586 /** 587 * Modifies the VelocityY parameter and returns itself. 588 * <p> 589 * The velocity in the Y direction, in m/s. Y is defined as to the left 590 * according to WPILib convention, so this determines how fast to travel to the 591 * left. 592 * 593 * @param newVelocityY Parameter to modify 594 * @return this object 595 */ 596 public RobotCentric withVelocityY(LinearVelocity newVelocityY) { 597 this.VelocityY = newVelocityY.in(MetersPerSecond); 598 return this; 599 } 600 601 /** 602 * Modifies the RotationalRate parameter and returns itself. 603 * <p> 604 * The angular rate to rotate at, in radians per second. Angular rate is defined 605 * as counterclockwise positive, so this determines how fast to turn 606 * counterclockwise. 607 * 608 * @param newRotationalRate Parameter to modify 609 * @return this object 610 */ 611 public RobotCentric withRotationalRate(double newRotationalRate) { 612 this.RotationalRate = newRotationalRate; 613 return this; 614 } 615 616 /** 617 * Modifies the RotationalRate parameter and returns itself. 618 * <p> 619 * The angular rate to rotate at, in radians per second. Angular rate is defined 620 * as counterclockwise positive, so this determines how fast to turn 621 * counterclockwise. 622 * 623 * @param newRotationalRate Parameter to modify 624 * @return this object 625 */ 626 public RobotCentric withRotationalRate(AngularVelocity newRotationalRate) { 627 this.RotationalRate = newRotationalRate.in(RadiansPerSecond); 628 return this; 629 } 630 631 /** 632 * Modifies the Deadband parameter and returns itself. 633 * <p> 634 * The allowable deadband of the request, in m/s. 635 * 636 * @param newDeadband Parameter to modify 637 * @return this object 638 */ 639 public RobotCentric withDeadband(double newDeadband) { 640 this.Deadband = newDeadband; 641 return this; 642 } 643 644 /** 645 * Modifies the Deadband parameter and returns itself. 646 * <p> 647 * The allowable deadband of the request, in m/s. 648 * 649 * @param newDeadband Parameter to modify 650 * @return this object 651 */ 652 public RobotCentric withDeadband(LinearVelocity newDeadband) { 653 this.Deadband = newDeadband.in(MetersPerSecond); 654 return this; 655 } 656 657 /** 658 * Modifies the RotationalDeadband parameter and returns itself. 659 * <p> 660 * The rotational deadband of the request, in radians per second. 661 * 662 * @param newRotationalDeadband Parameter to modify 663 * @return this object 664 */ 665 public RobotCentric withRotationalDeadband(double newRotationalDeadband) { 666 this.RotationalDeadband = newRotationalDeadband; 667 return this; 668 } 669 670 /** 671 * Modifies the RotationalDeadband parameter and returns itself. 672 * <p> 673 * The rotational deadband of the request, in radians per second. 674 * 675 * @param newRotationalDeadband Parameter to modify 676 * @return this object 677 */ 678 public RobotCentric withRotationalDeadband(AngularVelocity newRotationalDeadband) { 679 this.RotationalDeadband = newRotationalDeadband.in(RadiansPerSecond); 680 return this; 681 } 682 683 /** 684 * Modifies the CenterOfRotation parameter and returns itself. 685 * <p> 686 * The center of rotation the robot should rotate around. This is (0,0) by 687 * default, which will rotate around the center of the robot. 688 * 689 * @param newCenterOfRotation Parameter to modify 690 * @return this object 691 */ 692 public RobotCentric withCenterOfRotation(Translation2d newCenterOfRotation) { 693 this.CenterOfRotation = newCenterOfRotation; 694 return this; 695 } 696 697 /** 698 * Modifies the DriveRequestType parameter and returns itself. 699 * <p> 700 * The type of control request to use for the drive motor. 701 * 702 * @param newDriveRequestType Parameter to modify 703 * @return this object 704 */ 705 public RobotCentric withDriveRequestType(SwerveModule.DriveRequestType newDriveRequestType) { 706 this.DriveRequestType = newDriveRequestType; 707 return this; 708 } 709 710 /** 711 * Modifies the SteerRequestType parameter and returns itself. 712 * <p> 713 * The type of control request to use for the drive motor. 714 * 715 * @param newSteerRequestType Parameter to modify 716 * @return this object 717 */ 718 public RobotCentric withSteerRequestType(SwerveModule.SteerRequestType newSteerRequestType) { 719 this.SteerRequestType = newSteerRequestType; 720 return this; 721 } 722 723 /** 724 * Modifies the DesaturateWheelSpeeds parameter and returns itself. 725 * <p> 726 * Whether to desaturate wheel speeds before applying. For more information, see 727 * the documentation of {@link SwerveDriveKinematics#desaturateWheelSpeeds}. 728 * 729 * @param newDesaturateWheelSpeeds Parameter to modify 730 * @return this object 731 */ 732 public RobotCentric withDesaturateWheelSpeeds(boolean newDesaturateWheelSpeeds) { 733 this.DesaturateWheelSpeeds = newDesaturateWheelSpeeds; 734 return this; 735 } 736 737 public StatusCode apply(SwerveControlParameters parameters, SwerveModule<?, ?, ?>... modulesToApply) { 738 return StatusCode.valueOf(SwerveJNI.JNI_Request_Apply_RobotCentric(parameters.drivetrainId, 739 VelocityX, 740 VelocityY, 741 RotationalRate, 742 Deadband, 743 RotationalDeadband, 744 CenterOfRotation.getX(), 745 CenterOfRotation.getY(), 746 DriveRequestType.value, 747 SteerRequestType.value, 748 DesaturateWheelSpeeds)); 749 } 750 751 public void applyNative(int id) { 752 SwerveJNI.JNI_SetControl_RobotCentric(id, 753 VelocityX, 754 VelocityY, 755 RotationalRate, 756 Deadband, 757 RotationalDeadband, 758 CenterOfRotation.getX(), 759 CenterOfRotation.getY(), 760 DriveRequestType.value, 761 SteerRequestType.value, 762 DesaturateWheelSpeeds); 763 } 764 } 765 766 /** 767 * Sets the swerve drive modules to point to a specified direction. 768 */ 769 public static class PointWheelsAt implements NativeSwerveRequest { 770 /** 771 * The direction to point the modules toward. This direction is still optimized 772 * to what the module was previously at. 773 */ 774 public Rotation2d ModuleDirection = new Rotation2d(); 775 /** 776 * The type of control request to use for the drive motor. 777 */ 778 public SwerveModule.DriveRequestType DriveRequestType = SwerveModule.DriveRequestType.OpenLoopVoltage; 779 /** 780 * The type of control request to use for the drive motor. 781 */ 782 public SwerveModule.SteerRequestType SteerRequestType = SwerveModule.SteerRequestType.Position; 783 784 /** 785 * Modifies the ModuleDirection parameter and returns itself. 786 * <p> 787 * The direction to point the modules toward. This direction is still optimized 788 * to what the module was previously at. 789 * 790 * @param newModuleDirection Parameter to modify 791 * @return this object 792 */ 793 public PointWheelsAt withModuleDirection(Rotation2d newModuleDirection) { 794 this.ModuleDirection = newModuleDirection; 795 return this; 796 } 797 798 /** 799 * Modifies the DriveRequestType parameter and returns itself. 800 * <p> 801 * The type of control request to use for the drive motor. 802 * 803 * @param newDriveRequestType Parameter to modify 804 * @return this object 805 */ 806 public PointWheelsAt withDriveRequestType(SwerveModule.DriveRequestType newDriveRequestType) { 807 this.DriveRequestType = newDriveRequestType; 808 return this; 809 } 810 811 /** 812 * Modifies the SteerRequestType parameter and returns itself. 813 * <p> 814 * The type of control request to use for the drive motor. 815 * 816 * @param newSteerRequestType Parameter to modify 817 * @return this object 818 */ 819 public PointWheelsAt withSteerRequestType(SwerveModule.SteerRequestType newSteerRequestType) { 820 this.SteerRequestType = newSteerRequestType; 821 return this; 822 } 823 824 public StatusCode apply(SwerveControlParameters parameters, SwerveModule<?, ?, ?>... modulesToApply) { 825 return StatusCode.valueOf(SwerveJNI.JNI_Request_Apply_PointWheelsAt(parameters.drivetrainId, 826 ModuleDirection.getRadians(), 827 DriveRequestType.value, 828 SteerRequestType.value)); 829 } 830 831 public void applyNative(int id) { 832 SwerveJNI.JNI_SetControl_PointWheelsAt(id, 833 ModuleDirection.getRadians(), 834 DriveRequestType.value, 835 SteerRequestType.value); 836 } 837 } 838 839 /** 840 * Accepts a generic robot-centric ChassisSpeeds to apply to the drivetrain. 841 */ 842 public static class ApplyRobotSpeeds implements NativeSwerveRequest { 843 /** 844 * The robot-centric chassis speeds to apply to the drivetrain. 845 */ 846 public ChassisSpeeds Speeds = new ChassisSpeeds(); 847 /** 848 * Robot-centric wheel force feedforwards to apply in the X direction, in 849 * newtons. X is defined as forward according to WPILib convention, so this 850 * determines the forward forces to apply. 851 * <p> 852 * These forces should include friction applied to the ground. 853 * <p> 854 * The order of the forces should match the order of the modules returned from 855 * SwerveDrivetrain. 856 */ 857 public double[] WheelForceFeedforwardsX = {}; 858 /** 859 * Robot-centric wheel force feedforwards to apply in the Y direction, in 860 * newtons. Y is defined as to the left according to WPILib convention, so this 861 * determines the forces to apply to the left. 862 * <p> 863 * These forces should include friction applied to the ground. 864 * <p> 865 * The order of the forces should match the order of the modules returned from 866 * SwerveDrivetrain. 867 */ 868 public double[] WheelForceFeedforwardsY = {}; 869 /** 870 * The center of rotation the robot should rotate around. This is (0,0) by 871 * default, which will rotate around the center of the robot. 872 */ 873 public Translation2d CenterOfRotation = new Translation2d(); 874 /** 875 * The type of control request to use for the drive motor. 876 */ 877 public SwerveModule.DriveRequestType DriveRequestType = SwerveModule.DriveRequestType.OpenLoopVoltage; 878 /** 879 * The type of control request to use for the drive motor. 880 */ 881 public SwerveModule.SteerRequestType SteerRequestType = SwerveModule.SteerRequestType.Position; 882 /** 883 * Whether to desaturate wheel speeds before applying. For more information, see 884 * the documentation of {@link SwerveDriveKinematics#desaturateWheelSpeeds}. 885 */ 886 public boolean DesaturateWheelSpeeds = true; 887 888 /** 889 * Modifies the Speeds parameter and returns itself. 890 * <p> 891 * The robot-centric chassis speeds to apply to the drivetrain. 892 * 893 * @param newSpeeds Parameter to modify 894 * @return this object 895 */ 896 public ApplyRobotSpeeds withSpeeds(ChassisSpeeds newSpeeds) { 897 this.Speeds = newSpeeds; 898 return this; 899 } 900 901 /** 902 * Modifies the WheelForceFeedforwardsX parameter and returns itself. 903 * <p> 904 * Robot-centric wheel force feedforwards to apply in the X direction, in 905 * newtons. X is defined as forward according to WPILib convention, so this 906 * determines the forward forces to apply. 907 * <p> 908 * These forces should include friction applied to the ground. 909 * <p> 910 * The order of the forces should match the order of the modules returned from 911 * SwerveDrivetrain. 912 * 913 * @param newWheelForceFeedforwardsX Parameter to modify 914 * @return this object 915 */ 916 public ApplyRobotSpeeds withWheelForceFeedforwardsX(double[] newWheelForceFeedforwardsX) { 917 this.WheelForceFeedforwardsX = newWheelForceFeedforwardsX; 918 return this; 919 } 920 921 /** 922 * Modifies the WheelForceFeedforwardsX parameter and returns itself. 923 * <p> 924 * Robot-centric wheel force feedforwards to apply in the X direction, in 925 * newtons. X is defined as forward according to WPILib convention, so this 926 * determines the forward forces to apply. 927 * <p> 928 * These forces should include friction applied to the ground. 929 * <p> 930 * The order of the forces should match the order of the modules returned from 931 * SwerveDrivetrain. 932 * 933 * @param newWheelForceFeedforwardsX Parameter to modify 934 * @return this object 935 */ 936 public ApplyRobotSpeeds withWheelForceFeedforwardsX(Force[] newWheelForceFeedforwardsX) { 937 if (this.WheelForceFeedforwardsX.length != newWheelForceFeedforwardsX.length) { 938 this.WheelForceFeedforwardsX = new double[newWheelForceFeedforwardsX.length]; 939 } 940 for (int i = 0; i < this.WheelForceFeedforwardsX.length; ++i) { 941 this.WheelForceFeedforwardsX[i] = newWheelForceFeedforwardsX[i].in(Newtons); 942 } 943 944 return this; 945 } 946 947 /** 948 * Modifies the WheelForceFeedforwardsY parameter and returns itself. 949 * <p> 950 * Robot-centric wheel force feedforwards to apply in the Y direction, in 951 * newtons. Y is defined as to the left according to WPILib convention, so this 952 * determines the forces to apply to the left. 953 * <p> 954 * These forces should include friction applied to the ground. 955 * <p> 956 * The order of the forces should match the order of the modules returned from 957 * SwerveDrivetrain. 958 * 959 * @param newWheelForceFeedforwardsY Parameter to modify 960 * @return this object 961 */ 962 public ApplyRobotSpeeds withWheelForceFeedforwardsY(double[] newWheelForceFeedforwardsY) { 963 this.WheelForceFeedforwardsY = newWheelForceFeedforwardsY; 964 return this; 965 } 966 967 /** 968 * Modifies the WheelForceFeedforwardsY parameter and returns itself. 969 * <p> 970 * Robot-centric wheel force feedforwards to apply in the Y direction, in 971 * newtons. Y is defined as to the left according to WPILib convention, so this 972 * determines the forces to apply to the left. 973 * <p> 974 * These forces should include friction applied to the ground. 975 * <p> 976 * The order of the forces should match the order of the modules returned from 977 * SwerveDrivetrain. 978 * 979 * @param newWheelForceFeedforwardsY Parameter to modify 980 * @return this object 981 */ 982 public ApplyRobotSpeeds withWheelForceFeedforwardsY(Force[] newWheelForceFeedforwardsY) { 983 if (this.WheelForceFeedforwardsY.length != newWheelForceFeedforwardsY.length) { 984 this.WheelForceFeedforwardsY = new double[newWheelForceFeedforwardsY.length]; 985 } 986 for (int i = 0; i < this.WheelForceFeedforwardsY.length; ++i) { 987 this.WheelForceFeedforwardsY[i] = newWheelForceFeedforwardsY[i].in(Newtons); 988 } 989 990 return this; 991 } 992 993 /** 994 * Modifies the CenterOfRotation parameter and returns itself. 995 * <p> 996 * The center of rotation the robot should rotate around. This is (0,0) by 997 * default, which will rotate around the center of the robot. 998 * 999 * @param newCenterOfRotation Parameter to modify 1000 * @return this object 1001 */ 1002 public ApplyRobotSpeeds withCenterOfRotation(Translation2d newCenterOfRotation) { 1003 this.CenterOfRotation = newCenterOfRotation; 1004 return this; 1005 } 1006 1007 /** 1008 * Modifies the DriveRequestType parameter and returns itself. 1009 * <p> 1010 * The type of control request to use for the drive motor. 1011 * 1012 * @param newDriveRequestType Parameter to modify 1013 * @return this object 1014 */ 1015 public ApplyRobotSpeeds withDriveRequestType(SwerveModule.DriveRequestType newDriveRequestType) { 1016 this.DriveRequestType = newDriveRequestType; 1017 return this; 1018 } 1019 1020 /** 1021 * Modifies the SteerRequestType parameter and returns itself. 1022 * <p> 1023 * The type of control request to use for the drive motor. 1024 * 1025 * @param newSteerRequestType Parameter to modify 1026 * @return this object 1027 */ 1028 public ApplyRobotSpeeds withSteerRequestType(SwerveModule.SteerRequestType newSteerRequestType) { 1029 this.SteerRequestType = newSteerRequestType; 1030 return this; 1031 } 1032 1033 /** 1034 * Modifies the DesaturateWheelSpeeds parameter and returns itself. 1035 * <p> 1036 * Whether to desaturate wheel speeds before applying. For more information, see 1037 * the documentation of {@link SwerveDriveKinematics#desaturateWheelSpeeds}. 1038 * 1039 * @param newDesaturateWheelSpeeds Parameter to modify 1040 * @return this object 1041 */ 1042 public ApplyRobotSpeeds withDesaturateWheelSpeeds(boolean newDesaturateWheelSpeeds) { 1043 this.DesaturateWheelSpeeds = newDesaturateWheelSpeeds; 1044 return this; 1045 } 1046 1047 public StatusCode apply(SwerveControlParameters parameters, SwerveModule<?, ?, ?>... modulesToApply) { 1048 return StatusCode.valueOf(SwerveJNI.JNI_Request_Apply_ApplyRobotSpeeds(parameters.drivetrainId, 1049 Speeds.vxMetersPerSecond, 1050 Speeds.vyMetersPerSecond, 1051 Speeds.omegaRadiansPerSecond, 1052 WheelForceFeedforwardsX, 1053 WheelForceFeedforwardsY, 1054 CenterOfRotation.getX(), 1055 CenterOfRotation.getY(), 1056 DriveRequestType.value, 1057 SteerRequestType.value, 1058 DesaturateWheelSpeeds)); 1059 } 1060 1061 public void applyNative(int id) { 1062 SwerveJNI.JNI_SetControl_ApplyRobotSpeeds(id, 1063 Speeds.vxMetersPerSecond, 1064 Speeds.vyMetersPerSecond, 1065 Speeds.omegaRadiansPerSecond, 1066 WheelForceFeedforwardsX, 1067 WheelForceFeedforwardsY, 1068 CenterOfRotation.getX(), 1069 CenterOfRotation.getY(), 1070 DriveRequestType.value, 1071 SteerRequestType.value, 1072 DesaturateWheelSpeeds); 1073 } 1074 } 1075 1076 /** 1077 * Accepts a generic robot-centric ChassisSpeeds to apply to the drivetrain. 1078 * 1079 * @deprecated Use {@link ApplyRobotSpeeds} instead 1080 */ 1081 @Deprecated(forRemoval = true, since = "2025") 1082 public static class ApplyChassisSpeeds extends ApplyRobotSpeeds {} 1083 1084 /** 1085 * Accepts a generic field-centric ChassisSpeeds to apply to the drivetrain. 1086 */ 1087 public static class ApplyFieldSpeeds implements NativeSwerveRequest { 1088 /** 1089 * The field-centric chassis speeds to apply to the drivetrain. 1090 */ 1091 public ChassisSpeeds Speeds = new ChassisSpeeds(); 1092 /** 1093 * Field-centric wheel force feedforwards to apply in the X direction, in 1094 * newtons. X is defined as forward according to WPILib convention, so this 1095 * determines the forward forces to apply. 1096 * <p> 1097 * These forces should include friction applied to the ground. 1098 * <p> 1099 * The order of the forces should match the order of the modules returned from 1100 * SwerveDrivetrain. 1101 */ 1102 public double[] WheelForceFeedforwardsX = {}; 1103 /** 1104 * Field-centric wheel force feedforwards to apply in the Y direction, in 1105 * newtons. Y is defined as to the left according to WPILib convention, so this 1106 * determines the forces to apply to the left. 1107 * <p> 1108 * These forces should include friction applied to the ground. 1109 * <p> 1110 * The order of the forces should match the order of the modules returned from 1111 * SwerveDrivetrain. 1112 */ 1113 public double[] WheelForceFeedforwardsY = {}; 1114 /** 1115 * The center of rotation the robot should rotate around. This is (0,0) by 1116 * default, which will rotate around the center of the robot. 1117 */ 1118 public Translation2d CenterOfRotation = new Translation2d(); 1119 /** 1120 * The type of control request to use for the drive motor. 1121 */ 1122 public SwerveModule.DriveRequestType DriveRequestType = SwerveModule.DriveRequestType.OpenLoopVoltage; 1123 /** 1124 * The type of control request to use for the drive motor. 1125 */ 1126 public SwerveModule.SteerRequestType SteerRequestType = SwerveModule.SteerRequestType.Position; 1127 /** 1128 * Whether to desaturate wheel speeds before applying. For more information, see 1129 * the documentation of {@link SwerveDriveKinematics#desaturateWheelSpeeds}. 1130 */ 1131 public boolean DesaturateWheelSpeeds = true; 1132 /** 1133 * The perspective to use when determining which direction is forward. 1134 */ 1135 public ForwardPerspectiveValue ForwardPerspective = ForwardPerspectiveValue.BlueAlliance; 1136 1137 /** 1138 * Modifies the Speeds parameter and returns itself. 1139 * <p> 1140 * The field-centric chassis speeds to apply to the drivetrain. 1141 * 1142 * @param newSpeeds Parameter to modify 1143 * @return this object 1144 */ 1145 public ApplyFieldSpeeds withSpeeds(ChassisSpeeds newSpeeds) { 1146 this.Speeds = newSpeeds; 1147 return this; 1148 } 1149 1150 /** 1151 * Modifies the WheelForceFeedforwardsX parameter and returns itself. 1152 * <p> 1153 * Field-centric wheel force feedforwards to apply in the X direction, in 1154 * newtons. X is defined as forward according to WPILib convention, so this 1155 * determines the forward forces to apply. 1156 * <p> 1157 * These forces should include friction applied to the ground. 1158 * <p> 1159 * The order of the forces should match the order of the modules returned from 1160 * SwerveDrivetrain. 1161 * 1162 * @param newWheelForceFeedforwardsX Parameter to modify 1163 * @return this object 1164 */ 1165 public ApplyFieldSpeeds withWheelForceFeedforwardsX(double[] newWheelForceFeedforwardsX) { 1166 this.WheelForceFeedforwardsX = newWheelForceFeedforwardsX; 1167 return this; 1168 } 1169 1170 /** 1171 * Modifies the WheelForceFeedforwardsX parameter and returns itself. 1172 * <p> 1173 * Field-centric wheel force feedforwards to apply in the X direction, in 1174 * newtons. X is defined as forward according to WPILib convention, so this 1175 * determines the forward forces to apply. 1176 * <p> 1177 * These forces should include friction applied to the ground. 1178 * <p> 1179 * The order of the forces should match the order of the modules returned from 1180 * SwerveDrivetrain. 1181 * 1182 * @param newWheelForceFeedforwardsX Parameter to modify 1183 * @return this object 1184 */ 1185 public ApplyFieldSpeeds withWheelForceFeedforwardsX(Force[] newWheelForceFeedforwardsX) { 1186 if (this.WheelForceFeedforwardsX.length != newWheelForceFeedforwardsX.length) { 1187 this.WheelForceFeedforwardsX = new double[newWheelForceFeedforwardsX.length]; 1188 } 1189 for (int i = 0; i < this.WheelForceFeedforwardsX.length; ++i) { 1190 this.WheelForceFeedforwardsX[i] = newWheelForceFeedforwardsX[i].in(Newtons); 1191 } 1192 1193 return this; 1194 } 1195 1196 /** 1197 * Modifies the WheelForceFeedforwardsY parameter and returns itself. 1198 * <p> 1199 * Field-centric wheel force feedforwards to apply in the Y direction, in 1200 * newtons. Y is defined as to the left according to WPILib convention, so this 1201 * determines the forces to apply to the left. 1202 * <p> 1203 * These forces should include friction applied to the ground. 1204 * <p> 1205 * The order of the forces should match the order of the modules returned from 1206 * SwerveDrivetrain. 1207 * 1208 * @param newWheelForceFeedforwardsY Parameter to modify 1209 * @return this object 1210 */ 1211 public ApplyFieldSpeeds withWheelForceFeedforwardsY(double[] newWheelForceFeedforwardsY) { 1212 this.WheelForceFeedforwardsY = newWheelForceFeedforwardsY; 1213 return this; 1214 } 1215 1216 /** 1217 * Modifies the WheelForceFeedforwardsY parameter and returns itself. 1218 * <p> 1219 * Field-centric wheel force feedforwards to apply in the Y direction, in 1220 * newtons. Y is defined as to the left according to WPILib convention, so this 1221 * determines the forces to apply to the left. 1222 * <p> 1223 * These forces should include friction applied to the ground. 1224 * <p> 1225 * The order of the forces should match the order of the modules returned from 1226 * SwerveDrivetrain. 1227 * 1228 * @param newWheelForceFeedforwardsY Parameter to modify 1229 * @return this object 1230 */ 1231 public ApplyFieldSpeeds withWheelForceFeedforwardsY(Force[] newWheelForceFeedforwardsY) { 1232 if (this.WheelForceFeedforwardsY.length != newWheelForceFeedforwardsY.length) { 1233 this.WheelForceFeedforwardsY = new double[newWheelForceFeedforwardsY.length]; 1234 } 1235 for (int i = 0; i < this.WheelForceFeedforwardsY.length; ++i) { 1236 this.WheelForceFeedforwardsY[i] = newWheelForceFeedforwardsY[i].in(Newtons); 1237 } 1238 1239 return this; 1240 } 1241 1242 /** 1243 * Modifies the CenterOfRotation parameter and returns itself. 1244 * <p> 1245 * The center of rotation the robot should rotate around. This is (0,0) by 1246 * default, which will rotate around the center of the robot. 1247 * 1248 * @param newCenterOfRotation Parameter to modify 1249 * @return this object 1250 */ 1251 public ApplyFieldSpeeds withCenterOfRotation(Translation2d newCenterOfRotation) { 1252 this.CenterOfRotation = newCenterOfRotation; 1253 return this; 1254 } 1255 1256 /** 1257 * Modifies the DriveRequestType parameter and returns itself. 1258 * <p> 1259 * The type of control request to use for the drive motor. 1260 * 1261 * @param newDriveRequestType Parameter to modify 1262 * @return this object 1263 */ 1264 public ApplyFieldSpeeds withDriveRequestType(SwerveModule.DriveRequestType newDriveRequestType) { 1265 this.DriveRequestType = newDriveRequestType; 1266 return this; 1267 } 1268 1269 /** 1270 * Modifies the SteerRequestType parameter and returns itself. 1271 * <p> 1272 * The type of control request to use for the drive motor. 1273 * 1274 * @param newSteerRequestType Parameter to modify 1275 * @return this object 1276 */ 1277 public ApplyFieldSpeeds withSteerRequestType(SwerveModule.SteerRequestType newSteerRequestType) { 1278 this.SteerRequestType = newSteerRequestType; 1279 return this; 1280 } 1281 1282 /** 1283 * Modifies the DesaturateWheelSpeeds parameter and returns itself. 1284 * <p> 1285 * Whether to desaturate wheel speeds before applying. For more information, see 1286 * the documentation of {@link SwerveDriveKinematics#desaturateWheelSpeeds}. 1287 * 1288 * @param newDesaturateWheelSpeeds Parameter to modify 1289 * @return this object 1290 */ 1291 public ApplyFieldSpeeds withDesaturateWheelSpeeds(boolean newDesaturateWheelSpeeds) { 1292 this.DesaturateWheelSpeeds = newDesaturateWheelSpeeds; 1293 return this; 1294 } 1295 1296 /** 1297 * Modifies the ForwardPerspective parameter and returns itself. 1298 * <p> 1299 * The perspective to use when determining which direction is forward. 1300 * 1301 * @param newForwardPerspective Parameter to modify 1302 * @return this object 1303 */ 1304 public ApplyFieldSpeeds withForwardPerspective(ForwardPerspectiveValue newForwardPerspective) { 1305 this.ForwardPerspective = newForwardPerspective; 1306 return this; 1307 } 1308 1309 public StatusCode apply(SwerveControlParameters parameters, SwerveModule<?, ?, ?>... modulesToApply) { 1310 return StatusCode.valueOf(SwerveJNI.JNI_Request_Apply_ApplyFieldSpeeds(parameters.drivetrainId, 1311 Speeds.vxMetersPerSecond, 1312 Speeds.vyMetersPerSecond, 1313 Speeds.omegaRadiansPerSecond, 1314 WheelForceFeedforwardsX, 1315 WheelForceFeedforwardsY, 1316 CenterOfRotation.getX(), 1317 CenterOfRotation.getY(), 1318 DriveRequestType.value, 1319 SteerRequestType.value, 1320 DesaturateWheelSpeeds, 1321 ForwardPerspective.value)); 1322 } 1323 1324 public void applyNative(int id) { 1325 SwerveJNI.JNI_SetControl_ApplyFieldSpeeds(id, 1326 Speeds.vxMetersPerSecond, 1327 Speeds.vyMetersPerSecond, 1328 Speeds.omegaRadiansPerSecond, 1329 WheelForceFeedforwardsX, 1330 WheelForceFeedforwardsY, 1331 CenterOfRotation.getX(), 1332 CenterOfRotation.getY(), 1333 DriveRequestType.value, 1334 SteerRequestType.value, 1335 DesaturateWheelSpeeds, 1336 ForwardPerspective.value); 1337 } 1338 } 1339 1340 /** 1341 * Drives the swerve drivetrain in a field-centric manner, maintaining a 1342 * specified heading angle to ensure the robot is facing the desired direction 1343 * <p> 1344 * When users use this request, they specify the direction the robot should 1345 * travel oriented against the field, and the direction the robot should be facing. 1346 * <p> 1347 * An example scenario is that the robot is oriented to the east, the VelocityX 1348 * is +5 m/s, VelocityY is 0 m/s, and TargetDirection is 180 degrees. 1349 * In this scenario, the robot would drive northward at 5 m/s and turn clockwise 1350 * to a target of 180 degrees. 1351 * <p> 1352 * This control request is especially useful for autonomous control, where the 1353 * robot should be facing a changing direction throughout the motion. 1354 */ 1355 public static class FieldCentricFacingAngle implements SwerveRequest { 1356 /** 1357 * The velocity in the X direction, in m/s. 1358 * X is defined as forward according to WPILib convention, 1359 * so this determines how fast to travel forward. 1360 */ 1361 public double VelocityX = 0; 1362 /** 1363 * The velocity in the Y direction, in m/s. 1364 * Y is defined as to the left according to WPILib convention, 1365 * so this determines how fast to travel to the left. 1366 */ 1367 public double VelocityY = 0; 1368 /** 1369 * The desired direction to face. 1370 * 0 Degrees is defined as in the direction of the X axis. 1371 * As a result, a TargetDirection of 90 degrees will point along 1372 * the Y axis, or to the left. 1373 */ 1374 public Rotation2d TargetDirection = new Rotation2d(); 1375 /** 1376 * The rotational rate feedforward to add to the output of the heading 1377 * controller, in radians per second. When using a motion profile for the 1378 * target direction, this can be set to the current velocity reference of 1379 * the profile. 1380 */ 1381 public double TargetRateFeedforward = 0; 1382 1383 /** 1384 * The allowable deadband of the request, in m/s. 1385 */ 1386 public double Deadband = 0; 1387 /** 1388 * The rotational deadband of the request, in radians per second. 1389 */ 1390 public double RotationalDeadband = 0; 1391 /** 1392 * The center of rotation the robot should rotate around. 1393 * This is (0,0) by default, which will rotate around the center of the robot. 1394 */ 1395 public Translation2d CenterOfRotation = new Translation2d(); 1396 1397 /** 1398 * The type of control request to use for the drive motor. 1399 */ 1400 public SwerveModule.DriveRequestType DriveRequestType = SwerveModule.DriveRequestType.OpenLoopVoltage; 1401 /** 1402 * The type of control request to use for the steer motor. 1403 */ 1404 public SwerveModule.SteerRequestType SteerRequestType = SwerveModule.SteerRequestType.Position; 1405 /** 1406 * Whether to desaturate wheel speeds before applying. 1407 * For more information, see the documentation of {@link SwerveDriveKinematics#desaturateWheelSpeeds}. 1408 */ 1409 public boolean DesaturateWheelSpeeds = true; 1410 1411 /** 1412 * The perspective to use when determining which direction is forward. 1413 */ 1414 public ForwardPerspectiveValue ForwardPerspective = ForwardPerspectiveValue.OperatorPerspective; 1415 1416 /** 1417 * The PID controller used to maintain the desired heading. 1418 * Users can specify the PID gains to change how aggressively to maintain 1419 * heading. 1420 * <p> 1421 * This PID controller operates on heading radians and outputs a target 1422 * rotational rate in radians per second. Note that continuous input should 1423 * be enabled on the range [-pi, pi]. 1424 */ 1425 public PhoenixPIDController HeadingController = new PhoenixPIDController(0, 0, 0); 1426 1427 private final FieldCentric m_fieldCentric = new FieldCentric(); 1428 1429 public FieldCentricFacingAngle() { 1430 HeadingController.enableContinuousInput(-Math.PI, Math.PI); 1431 } 1432 1433 public StatusCode apply(SwerveControlParameters parameters, SwerveModule<?, ?, ?>... modulesToApply) { 1434 Rotation2d angleToFace = TargetDirection; 1435 if (ForwardPerspective == ForwardPerspectiveValue.OperatorPerspective) { 1436 /* If we're operator perspective, rotate the direction we want to face by the angle */ 1437 angleToFace = angleToFace.rotateBy(parameters.operatorForwardDirection); 1438 } 1439 1440 double toApplyOmega = TargetRateFeedforward + 1441 HeadingController.calculate( 1442 parameters.currentPose.getRotation().getRadians(), 1443 angleToFace.getRadians(), 1444 parameters.timestamp 1445 ); 1446 1447 return m_fieldCentric 1448 .withVelocityX(VelocityX) 1449 .withVelocityY(VelocityY) 1450 .withRotationalRate(toApplyOmega) 1451 .withDeadband(Deadband) 1452 .withRotationalDeadband(RotationalDeadband) 1453 .withCenterOfRotation(CenterOfRotation) 1454 .withDriveRequestType(DriveRequestType) 1455 .withSteerRequestType(SteerRequestType) 1456 .withDesaturateWheelSpeeds(DesaturateWheelSpeeds) 1457 .withForwardPerspective(ForwardPerspective) 1458 .apply(parameters, modulesToApply); 1459 } 1460 1461 /** 1462 * Modifies the VelocityX parameter and returns itself. 1463 * <p> 1464 * The velocity in the X direction, in m/s. X is defined as forward according to 1465 * WPILib convention, so this determines how fast to travel forward. 1466 * 1467 * @param newVelocityX Parameter to modify 1468 * @return this object 1469 */ 1470 public FieldCentricFacingAngle withVelocityX(double newVelocityX) { 1471 this.VelocityX = newVelocityX; 1472 return this; 1473 } 1474 1475 /** 1476 * Modifies the VelocityX parameter and returns itself. 1477 * <p> 1478 * The velocity in the X direction, in m/s. X is defined as forward according to 1479 * WPILib convention, so this determines how fast to travel forward. 1480 * 1481 * @param newVelocityX Parameter to modify 1482 * @return this object 1483 */ 1484 public FieldCentricFacingAngle withVelocityX(LinearVelocity newVelocityX) { 1485 this.VelocityX = newVelocityX.in(MetersPerSecond); 1486 return this; 1487 } 1488 1489 /** 1490 * Modifies the VelocityY parameter and returns itself. 1491 * <p> 1492 * The velocity in the Y direction, in m/s. Y is defined as to the left 1493 * according to WPILib convention, so this determines how fast to travel to the 1494 * left. 1495 * 1496 * @param newVelocityY Parameter to modify 1497 * @return this object 1498 */ 1499 public FieldCentricFacingAngle withVelocityY(double newVelocityY) { 1500 this.VelocityY = newVelocityY; 1501 return this; 1502 } 1503 1504 /** 1505 * Modifies the VelocityY parameter and returns itself. 1506 * <p> 1507 * The velocity in the Y direction, in m/s. Y is defined as to the left 1508 * according to WPILib convention, so this determines how fast to travel to the 1509 * left. 1510 * 1511 * @param newVelocityY Parameter to modify 1512 * @return this object 1513 */ 1514 public FieldCentricFacingAngle withVelocityY(LinearVelocity newVelocityY) { 1515 this.VelocityY = newVelocityY.in(MetersPerSecond); 1516 return this; 1517 } 1518 1519 /** 1520 * Modifies the TargetDirection parameter and returns itself. 1521 * <p> 1522 * The desired direction to face. 0 Degrees is defined as in the direction of 1523 * the X axis. As a result, a TargetDirection of 90 degrees will point along 1524 * the Y axis, or to the left. 1525 * 1526 * @param newTargetDirection Parameter to modify 1527 * @return this object 1528 */ 1529 public FieldCentricFacingAngle withTargetDirection(Rotation2d newTargetDirection) { 1530 this.TargetDirection = newTargetDirection; 1531 return this; 1532 } 1533 1534 /** 1535 * Modifies the TargetRateFeedforward parameter and returns itself. 1536 * <p> 1537 * The rotational rate feedforward to add to the output of the heading 1538 * controller, in radians per second. When using a motion profile for the 1539 * target direction, this can be set to the current velocity reference of 1540 * the profile. 1541 * 1542 * @param newTargetRateFeedforward Parameter to modify 1543 * @return this object 1544 */ 1545 public FieldCentricFacingAngle withTargetRateFeedforward(double newTargetRateFeedforward) { 1546 this.TargetRateFeedforward = newTargetRateFeedforward; 1547 return this; 1548 } 1549 /** 1550 * Modifies the TargetRateFeedforward parameter and returns itself. 1551 * <p> 1552 * The rotational rate feedforward to add to the output of the heading 1553 * controller, in radians per second. When using a motion profile for the 1554 * target direction, this can be set to the current velocity reference of 1555 * the profile. 1556 * 1557 * @param newTargetRateFeedforward Parameter to modify 1558 * @return this object 1559 */ 1560 public FieldCentricFacingAngle withTargetRateFeedforward(AngularVelocity newTargetRateFeedforward) { 1561 this.TargetRateFeedforward = newTargetRateFeedforward.in(RadiansPerSecond); 1562 return this; 1563 } 1564 1565 /** 1566 * Modifies the Deadband parameter and returns itself. 1567 * <p> 1568 * The allowable deadband of the request, in m/s. 1569 * 1570 * @param newDeadband Parameter to modify 1571 * @return this object 1572 */ 1573 public FieldCentricFacingAngle withDeadband(double newDeadband) { 1574 this.Deadband = newDeadband; 1575 return this; 1576 } 1577 1578 /** 1579 * Modifies the Deadband parameter and returns itself. 1580 * <p> 1581 * The allowable deadband of the request, in m/s. 1582 * 1583 * @param newDeadband Parameter to modify 1584 * @return this object 1585 */ 1586 public FieldCentricFacingAngle withDeadband(LinearVelocity newDeadband) { 1587 this.Deadband = newDeadband.in(MetersPerSecond); 1588 return this; 1589 } 1590 1591 /** 1592 * Modifies the RotationalDeadband parameter and returns itself. 1593 * <p> 1594 * The rotational deadband of the request, in radians per second. 1595 * 1596 * @param newRotationalDeadband Parameter to modify 1597 * @return this object 1598 */ 1599 public FieldCentricFacingAngle withRotationalDeadband(double newRotationalDeadband) { 1600 this.RotationalDeadband = newRotationalDeadband; 1601 return this; 1602 } 1603 1604 /** 1605 * Modifies the RotationalDeadband parameter and returns itself. 1606 * <p> 1607 * The rotational deadband of the request, in radians per second. 1608 * 1609 * @param newRotationalDeadband Parameter to modify 1610 * @return this object 1611 */ 1612 public FieldCentricFacingAngle withRotationalDeadband(AngularVelocity newRotationalDeadband) { 1613 this.RotationalDeadband = newRotationalDeadband.in(RadiansPerSecond); 1614 return this; 1615 } 1616 1617 /** 1618 * Modifies the CenterOfRotation parameter and returns itself. 1619 * <p> 1620 * The center of rotation the robot should rotate around. This is (0,0) by 1621 * default, which will rotate around the center of the robot. 1622 * 1623 * @param newCenterOfRotation Parameter to modify 1624 * @return this object 1625 */ 1626 public FieldCentricFacingAngle withCenterOfRotation(Translation2d newCenterOfRotation) { 1627 this.CenterOfRotation = newCenterOfRotation; 1628 return this; 1629 } 1630 1631 /** 1632 * Modifies the DriveRequestType parameter and returns itself. 1633 * <p> 1634 * The type of control request to use for the drive motor. 1635 * 1636 * @param newDriveRequestType Parameter to modify 1637 * @return this object 1638 */ 1639 public FieldCentricFacingAngle withDriveRequestType(SwerveModule.DriveRequestType newDriveRequestType) { 1640 this.DriveRequestType = newDriveRequestType; 1641 return this; 1642 } 1643 1644 /** 1645 * Modifies the SteerRequestType parameter and returns itself. 1646 * <p> 1647 * The type of control request to use for the drive motor. 1648 * 1649 * @param newSteerRequestType Parameter to modify 1650 * @return this object 1651 */ 1652 public FieldCentricFacingAngle withSteerRequestType(SwerveModule.SteerRequestType newSteerRequestType) { 1653 this.SteerRequestType = newSteerRequestType; 1654 return this; 1655 } 1656 1657 /** 1658 * Modifies the DesaturateWheelSpeeds parameter and returns itself. 1659 * <p> 1660 * Whether to desaturate wheel speeds before applying. For more information, see 1661 * the documentation of {@link SwerveDriveKinematics#desaturateWheelSpeeds}. 1662 * 1663 * @param newDesaturateWheelSpeeds Parameter to modify 1664 * @return this object 1665 */ 1666 public FieldCentricFacingAngle withDesaturateWheelSpeeds(boolean newDesaturateWheelSpeeds) { 1667 this.DesaturateWheelSpeeds = newDesaturateWheelSpeeds; 1668 return this; 1669 } 1670 1671 /** 1672 * Modifies the ForwardPerspective parameter and returns itself. 1673 * <p> 1674 * The perspective to use when determining which direction is forward. 1675 * 1676 * @param newForwardPerspective Parameter to modify 1677 * @return this object 1678 */ 1679 public FieldCentricFacingAngle withForwardPerspective(ForwardPerspectiveValue newForwardPerspective) { 1680 this.ForwardPerspective = newForwardPerspective; 1681 return this; 1682 } 1683 } 1684 1685 /** 1686 * SysId-specific SwerveRequest to characterize the translational 1687 * characteristics of a swerve drivetrain. 1688 */ 1689 public static class SysIdSwerveTranslation implements SwerveRequest { 1690 /** 1691 * Voltage to apply to drive wheels. 1692 */ 1693 public double VoltsToApply = 0; 1694 1695 /** Local reference to a voltage request for the drive motors */ 1696 private final VoltageOut m_driveRequest = new VoltageOut(0); 1697 /** Local reference to a position voltage request for the steer motors */ 1698 private final PositionVoltage m_steerRequest_Voltage = new PositionVoltage(0); 1699 /** Local reference to a position torque current request for the steer motors */ 1700 private final PositionTorqueCurrentFOC m_steerRequest_TorqueCurrent = new PositionTorqueCurrentFOC(0); 1701 1702 public StatusCode apply(SwerveControlParameters parameters, SwerveModule<?, ?, ?>... modulesToApply) { 1703 for (int i = 0; i < modulesToApply.length; ++i) { 1704 switch (modulesToApply[i].getSteerClosedLoopOutputType()) { 1705 case Voltage: 1706 modulesToApply[i].apply( 1707 m_driveRequest.withOutput(VoltsToApply), 1708 m_steerRequest_Voltage.withPosition(0) 1709 ); 1710 break; 1711 case TorqueCurrentFOC: 1712 modulesToApply[i].apply( 1713 m_driveRequest.withOutput(VoltsToApply), 1714 m_steerRequest_TorqueCurrent.withPosition(0) 1715 ); 1716 break; 1717 } 1718 } 1719 return StatusCode.OK; 1720 } 1721 1722 /** 1723 * Sets the voltage to apply to the drive wheels. 1724 * 1725 * @param volts Voltage to apply 1726 * @return this request 1727 */ 1728 public SysIdSwerveTranslation withVolts(double volts) { 1729 VoltsToApply = volts; 1730 return this; 1731 } 1732 /** 1733 * Sets the voltage to apply to the drive wheels. 1734 * 1735 * @param volts Voltage to apply 1736 * @return this request 1737 */ 1738 public SysIdSwerveTranslation withVolts(Voltage volts) { 1739 VoltsToApply = volts.in(Volts); 1740 return this; 1741 } 1742 } 1743 1744 /** 1745 * SysId-specific SwerveRequest to characterize the rotational 1746 * characteristics of a swerve drivetrain. This is useful to 1747 * characterize the heading controller for FieldCentricFacingAngle. 1748 * <p> 1749 * The RotationalRate of this swerve request should be logged. 1750 * When importing the log to SysId, set the "voltage" to 1751 * RotationalRate, "position" to the Pigeon 2 Yaw, and "velocity" 1752 * to the Pigeon 2 AngularVelocityZWorld. Note that the position 1753 * and velocity will both need to be scaled by pi/180. 1754 * <p> 1755 * Alternatively, the MotorVoltage of one of the drive motors can 1756 * be loaded into the SysId "voltage" field, which can be useful 1757 * when determining the MOI of the robot. 1758 */ 1759 public static class SysIdSwerveRotation implements SwerveRequest { 1760 /** 1761 * The angular rate to rotate at, in radians per second. 1762 */ 1763 public double RotationalRate = 0; 1764 1765 /** Local reference to a voltage request for the drive motors */ 1766 private final VoltageOut m_driveRequest = new VoltageOut(0); 1767 /** Local reference to a position voltage request for the steer motors */ 1768 private final PositionVoltage m_steerRequest_Voltage = new PositionVoltage(0); 1769 /** Local reference to a position torque current request for the steer motors */ 1770 private final PositionTorqueCurrentFOC m_steerRequest_TorqueCurrent = new PositionTorqueCurrentFOC(0); 1771 1772 public StatusCode apply(SwerveControlParameters parameters, SwerveModule<?, ?, ?>... modulesToApply) { 1773 for (int i = 0; i < modulesToApply.length; ++i) { 1774 var speedMps = RotationalRate * parameters.moduleLocations[i].getNorm(); 1775 var driveVoltage = speedMps / parameters.kMaxSpeedMps * 12.0; 1776 1777 var angle = parameters.moduleLocations[i].getAngle().plus(Rotation2d.kCCW_90deg); 1778 1779 switch (modulesToApply[i].getSteerClosedLoopOutputType()) { 1780 case Voltage: 1781 modulesToApply[i].apply( 1782 m_driveRequest.withOutput(driveVoltage), 1783 m_steerRequest_Voltage.withPosition(angle.getRotations()) 1784 ); 1785 break; 1786 case TorqueCurrentFOC: 1787 modulesToApply[i].apply( 1788 m_driveRequest.withOutput(driveVoltage), 1789 m_steerRequest_TorqueCurrent.withPosition(angle.getRotations()) 1790 ); 1791 break; 1792 } 1793 } 1794 return StatusCode.OK; 1795 } 1796 1797 /** 1798 * Update the angular rate to rotate at, in radians per second. 1799 * 1800 * @param newRotationalRate Angular rate to rotate at 1801 * @return this request 1802 */ 1803 public SysIdSwerveRotation withRotationalRate(double newRotationalRate) { 1804 RotationalRate = newRotationalRate; 1805 return this; 1806 } 1807 /** 1808 * Update the angular rate to rotate at. 1809 * 1810 * @param newRotationalRate The angular rate to rotate at 1811 * @return this request 1812 */ 1813 public SysIdSwerveRotation withRotationalRate(AngularVelocity newRotationalRate) { 1814 RotationalRate = newRotationalRate.in(RadiansPerSecond); 1815 return this; 1816 } 1817 } 1818 1819 /** 1820 * SysId-specific SwerveRequest to characterize the steer module 1821 * characteristics of a swerve drivetrain. 1822 */ 1823 public static class SysIdSwerveSteerGains implements SwerveRequest { 1824 /** 1825 * Voltage to apply to steer motors. 1826 */ 1827 public double VoltsToApply = 0; 1828 1829 /** Local reference to a coast request for the drive motors */ 1830 private final CoastOut m_driveRequest = new CoastOut(); 1831 /** Local reference to a voltage request for the steer motors */ 1832 private final VoltageOut m_steerRequest = new VoltageOut(0); 1833 1834 public StatusCode apply(SwerveControlParameters parameters, SwerveModule<?, ?, ?>... modulesToApply) { 1835 for (int i = 0; i < modulesToApply.length; ++i) { 1836 modulesToApply[i].apply(m_driveRequest, m_steerRequest.withOutput(VoltsToApply)); 1837 } 1838 return StatusCode.OK; 1839 } 1840 1841 /** 1842 * Sets the voltage to apply to the steer motors. 1843 * 1844 * @param volts Voltage to apply 1845 * @return this request 1846 */ 1847 public SysIdSwerveSteerGains withVolts(double volts) { 1848 VoltsToApply = volts; 1849 return this; 1850 } 1851 /** 1852 * Sets the voltage to apply to the steer motors. 1853 * 1854 * @param volts Voltage to apply 1855 * @return this request 1856 */ 1857 public SysIdSwerveSteerGains withVolts(Voltage volts) { 1858 VoltsToApply = volts.in(Volts); 1859 return this; 1860 } 1861 } 1862}