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 com.ctre.phoenix6.swerve.ffi.SwerveNative.*; 010import static org.wpilib.units.Units.*; 011 012import java.lang.foreign.Arena; 013import java.lang.foreign.ValueLayout; 014import java.util.HashMap; 015 016import com.ctre.phoenix6.StatusCode; 017import com.ctre.phoenix6.controls.CoastOut; 018import com.ctre.phoenix6.controls.PositionTorqueCurrentFOC; 019import com.ctre.phoenix6.controls.PositionVoltage; 020import com.ctre.phoenix6.controls.VoltageOut; 021import com.ctre.phoenix6.swerve.SwerveDrivetrain.SwerveControlParameters; 022import com.ctre.phoenix6.swerve.utility.PhoenixPIDController; 023 024import org.wpilib.math.geometry.Rotation2d; 025import org.wpilib.math.geometry.Translation2d; 026import org.wpilib.math.kinematics.ChassisVelocities; 027import org.wpilib.math.kinematics.SwerveDriveKinematics; 028import org.wpilib.units.measure.*; 029 030/** 031 * Container for all the Swerve Requests. Use this to find all applicable swerve 032 * drive requests. 033 * <p> 034 * This is also an interface common to all swerve drive control requests that 035 * allow the request to calculate the state to apply to the modules. 036 */ 037public interface SwerveRequest { 038 /** 039 * In field-centric control, the direction of "forward" is sometimes different 040 * depending on perspective. This addresses which forward to use. 041 */ 042 public enum ForwardPerspectiveValue { 043 /** 044 * "Forward" (positive X) is determined from the operator's perspective. This 045 * is important for most teleop driven field-centric requests, where positive 046 * X means to drive away from the operator. 047 * <p> 048 * Important: Users must specify the OperatorForwardDirection in the SwerveDrivetrain object. 049 */ 050 OperatorPerspective(0), 051 /** 052 * "Forward" (positive X) is always from the perspective of the blue alliance (i.e. towards 053 * the red alliance). This is important in situations such as path following where positive 054 * X is always from the blue alliance perspective, regardless of where the operator is 055 * physically located. 056 */ 057 BlueAlliance(1); 058 059 public final int value; 060 061 ForwardPerspectiveValue(int initValue) { 062 this.value = initValue; 063 } 064 065 private static HashMap<Integer, ForwardPerspectiveValue> _map = null; 066 static { 067 _map = new HashMap<Integer, ForwardPerspectiveValue>(); 068 for (ForwardPerspectiveValue type : ForwardPerspectiveValue.values()) { 069 _map.put(type.value, type); 070 } 071 } 072 073 /** 074 * Gets ForwardPerspectiveValue from specified value 075 * 076 * @param value Value of ForwardPerspectiveValue 077 * @return ForwardPerspectiveValue of specified value 078 */ 079 public static ForwardPerspectiveValue valueOf(int value) { 080 ForwardPerspectiveValue retval = _map.get(value); 081 if (retval != null) 082 return retval; 083 return ForwardPerspectiveValue.values()[0]; 084 } 085 } 086 087 /** 088 * In field-centric control, the direction of "forward" for the target direction sometimes 089 * differs from "forward" for translation. This addresses which forward to use. 090 */ 091 public enum TargetDirectionPerspectiveValue { 092 /** 093 * Match the ForwardPerspective parameter for heading control. 094 */ 095 UseForwardPerspective(0), 096 /** 097 * "Forward" (0 deg) is always from the perspective of the blue alliance (i.e. 098 * towards the red alliance). This can be used to allow for the robot rotation to track 099 * vision targets while using operator-perspective joystick control for translation. 100 */ 101 BlueAlliance(1); 102 103 public final int value; 104 105 TargetDirectionPerspectiveValue(int initValue) { 106 this.value = initValue; 107 } 108 109 private static HashMap<Integer, TargetDirectionPerspectiveValue> _map = null; 110 static { 111 _map = new HashMap<Integer, TargetDirectionPerspectiveValue>(); 112 for (TargetDirectionPerspectiveValue type : TargetDirectionPerspectiveValue.values()) { 113 _map.put(type.value, type); 114 } 115 } 116 117 /** 118 * Gets TargetDirectionPerspectiveValue from specified value 119 * 120 * @param value Value of TargetDirectionPerspectiveValue 121 * @return TargetDirectionPerspectiveValue of specified value 122 */ 123 public static TargetDirectionPerspectiveValue valueOf(int value) { 124 TargetDirectionPerspectiveValue retval = _map.get(value); 125 if (retval != null) 126 return retval; 127 return TargetDirectionPerspectiveValue.values()[0]; 128 } 129 } 130 131 /** 132 * Applies this swerve request to the given modules. This is 133 * typically called by the SwerveDrivetrain odometry thread. 134 * <p> 135 * For native swerve requests, this API can be called from a 136 * non-native request's {@code apply} to compose the two together. 137 * 138 * @param parameters Parameters the control request needs to calculate the module state 139 * @param modulesToApply Modules to which the control request is applied 140 * @return Status code of sending the request 141 */ 142 public StatusCode apply(SwerveControlParameters parameters, SwerveModule<?, ?, ?>... modulesToApply); 143 144 /** Swerve requests implemented in native code. */ 145 public interface NativeSwerveRequest extends SwerveRequest { 146 /** 147 * Applies a native swerve request to the native drivetrain with the provided ID. 148 * <p> 149 * When this is implemented, the regular {@link #apply} function should do nothing 150 * (return OK). Additionally, this cannot be called from another swerve request's 151 * apply method, as this overrides the native swerve request of the drivetrain. 152 * <p> 153 * Unlike {@link #apply}, this function is called every time {@link SwerveDrivetrain#setControl} 154 * is run, not every loop of the odometry thread. Instead, the underlying native 155 * request is run at the full update frequency of the odometry thread. 156 * 157 * @param id ID of the native swerve drivetrain 158 */ 159 public void applyNative(int id); 160 } 161 162 163 /** 164 * Does nothing to the swerve module state. This is the default state of a newly 165 * created swerve drive mechanism. 166 */ 167 public static class Idle implements NativeSwerveRequest { 168 169 170 171 public StatusCode apply(SwerveControlParameters parameters, SwerveModule<?, ?, ?>... modulesToApply) { 172 return StatusCode.valueOf(c_ctre_phoenix6_swerve_request_apply_idle( 173 parameters.drivetrainId 174 )); 175 } 176 177 public void applyNative(int id) { 178 c_ctre_phoenix6_swerve_drivetrain_set_control_idle( 179 id 180 ); 181 } 182 } 183 184 /** 185 * Sets the swerve drive module states to point inward on the robot in an "X" 186 * fashion, creating a natural brake which will oppose any motion. 187 */ 188 public static class SwerveDriveBrake implements NativeSwerveRequest { 189 /** 190 * The type of control request to use for the drive motor. 191 */ 192 public SwerveModule.DriveRequestType DriveRequestType = SwerveModule.DriveRequestType.OpenLoopVoltage; 193 /** 194 * The type of control request to use for the drive motor. 195 */ 196 public SwerveModule.SteerRequestType SteerRequestType = SwerveModule.SteerRequestType.Position; 197 198 /** 199 * Modifies the DriveRequestType parameter and returns itself. 200 * <p> 201 * The type of control request to use for the drive motor. 202 * 203 * @param newDriveRequestType Parameter to modify 204 * @return this object 205 */ 206 public final SwerveDriveBrake withDriveRequestType(SwerveModule.DriveRequestType newDriveRequestType) { 207 this.DriveRequestType = newDriveRequestType; 208 return this; 209 } 210 211 /** 212 * Modifies the SteerRequestType parameter and returns itself. 213 * <p> 214 * The type of control request to use for the drive motor. 215 * 216 * @param newSteerRequestType Parameter to modify 217 * @return this object 218 */ 219 public final SwerveDriveBrake withSteerRequestType(SwerveModule.SteerRequestType newSteerRequestType) { 220 this.SteerRequestType = newSteerRequestType; 221 return this; 222 } 223 224 public StatusCode apply(SwerveControlParameters parameters, SwerveModule<?, ?, ?>... modulesToApply) { 225 return StatusCode.valueOf(c_ctre_phoenix6_swerve_request_apply_swerve_drive_brake( 226 parameters.drivetrainId, 227 DriveRequestType.value, 228 SteerRequestType.value 229 )); 230 } 231 232 public void applyNative(int id) { 233 c_ctre_phoenix6_swerve_drivetrain_set_control_swerve_drive_brake( 234 id, 235 DriveRequestType.value, 236 SteerRequestType.value 237 ); 238 } 239 } 240 241 /** 242 * Drives the swerve drivetrain in a field-centric manner. This request is 243 * optimized for joystick control during teleop with built-in deadbands. 244 * <p> 245 * This request specifies the direction the robot should travel oriented against 246 * the field, and the rate at which their robot should rotate about the center 247 * of the robot. 248 * <p> 249 * An example scenario is that the robot is oriented to the field +Y (left), the 250 * VelocityX is +5 m/s, VelocityY is 0 m/s, and RotationRate is 0.5 rad/s. In 251 * this scenario, the robot would drive along the field +X (forward) at 5 m/s 252 * and turn counterclockwise at 0.5 rad/s. 253 */ 254 public static class FieldCentric implements NativeSwerveRequest { 255 /** 256 * The velocity in the X direction, in m/s. X is defined as forward according to 257 * WPILib convention, so this determines how fast to travel forward. 258 */ 259 public double VelocityX = 0; 260 /** 261 * The velocity in the Y direction, in m/s. Y is defined as to the left 262 * according to WPILib convention, so this determines how fast to travel to the 263 * left. 264 */ 265 public double VelocityY = 0; 266 /** 267 * The angular rate to rotate at, in radians per second. Angular rate is defined 268 * as counterclockwise positive, so this determines how fast to turn 269 * counterclockwise. 270 */ 271 public double RotationalRate = 0; 272 /** 273 * The allowable deadband of the request, in m/s. 274 */ 275 public double Deadband = 0; 276 /** 277 * The rotational deadband of the request, in radians per second. 278 */ 279 public double RotationalDeadband = 0; 280 /** 281 * The center of rotation the robot should rotate around. This is (0,0) by 282 * default, which will rotate around the center of the robot. 283 */ 284 public Translation2d CenterOfRotation = new Translation2d(); 285 /** 286 * The type of control request to use for the drive motor. 287 */ 288 public SwerveModule.DriveRequestType DriveRequestType = SwerveModule.DriveRequestType.OpenLoopVoltage; 289 /** 290 * The type of control request to use for the drive motor. 291 */ 292 public SwerveModule.SteerRequestType SteerRequestType = SwerveModule.SteerRequestType.Position; 293 /** 294 * Whether to desaturate wheel velocities before applying. For more information, 295 * see the documentation of {@link 296 * SwerveDriveKinematics#desaturateWheelVelocities}. 297 */ 298 public boolean DesaturateWheelVelocities = true; 299 /** 300 * The perspective to use when determining which direction is forward. 301 */ 302 public ForwardPerspectiveValue ForwardPerspective = ForwardPerspectiveValue.OperatorPerspective; 303 304 /** 305 * Modifies the VelocityX parameter and returns itself. 306 * <p> 307 * The velocity in the X direction, in m/s. X is defined as forward according to 308 * WPILib convention, so this determines how fast to travel forward. 309 * 310 * @param newVelocityX Parameter to modify 311 * @return this object 312 */ 313 public final FieldCentric withVelocityX(double newVelocityX) { 314 this.VelocityX = newVelocityX; 315 return this; 316 } 317 318 /** 319 * Modifies the VelocityX parameter and returns itself. 320 * <p> 321 * The velocity in the X direction, in m/s. X is defined as forward according to 322 * WPILib convention, so this determines how fast to travel forward. 323 * 324 * @param newVelocityX Parameter to modify 325 * @return this object 326 */ 327 public final FieldCentric withVelocityX(LinearVelocity newVelocityX) { 328 this.VelocityX = newVelocityX.in(MetersPerSecond); 329 return this; 330 } 331 332 /** 333 * Modifies the VelocityY parameter and returns itself. 334 * <p> 335 * The velocity in the Y direction, in m/s. Y is defined as to the left 336 * according to WPILib convention, so this determines how fast to travel to the 337 * left. 338 * 339 * @param newVelocityY Parameter to modify 340 * @return this object 341 */ 342 public final FieldCentric withVelocityY(double newVelocityY) { 343 this.VelocityY = newVelocityY; 344 return this; 345 } 346 347 /** 348 * Modifies the VelocityY parameter and returns itself. 349 * <p> 350 * The velocity in the Y direction, in m/s. Y is defined as to the left 351 * according to WPILib convention, so this determines how fast to travel to the 352 * left. 353 * 354 * @param newVelocityY Parameter to modify 355 * @return this object 356 */ 357 public final FieldCentric withVelocityY(LinearVelocity newVelocityY) { 358 this.VelocityY = newVelocityY.in(MetersPerSecond); 359 return this; 360 } 361 362 /** 363 * Modifies the RotationalRate parameter and returns itself. 364 * <p> 365 * The angular rate to rotate at, in radians per second. Angular rate is defined 366 * as counterclockwise positive, so this determines how fast to turn 367 * counterclockwise. 368 * 369 * @param newRotationalRate Parameter to modify 370 * @return this object 371 */ 372 public final FieldCentric withRotationalRate(double newRotationalRate) { 373 this.RotationalRate = newRotationalRate; 374 return this; 375 } 376 377 /** 378 * Modifies the RotationalRate parameter and returns itself. 379 * <p> 380 * The angular rate to rotate at, in radians per second. Angular rate is defined 381 * as counterclockwise positive, so this determines how fast to turn 382 * counterclockwise. 383 * 384 * @param newRotationalRate Parameter to modify 385 * @return this object 386 */ 387 public final FieldCentric withRotationalRate(AngularVelocity newRotationalRate) { 388 this.RotationalRate = newRotationalRate.in(RadiansPerSecond); 389 return this; 390 } 391 392 /** 393 * Modifies the Deadband parameter and returns itself. 394 * <p> 395 * The allowable deadband of the request, in m/s. 396 * 397 * @param newDeadband Parameter to modify 398 * @return this object 399 */ 400 public final FieldCentric withDeadband(double newDeadband) { 401 this.Deadband = newDeadband; 402 return this; 403 } 404 405 /** 406 * Modifies the Deadband parameter and returns itself. 407 * <p> 408 * The allowable deadband of the request, in m/s. 409 * 410 * @param newDeadband Parameter to modify 411 * @return this object 412 */ 413 public final FieldCentric withDeadband(LinearVelocity newDeadband) { 414 this.Deadband = newDeadband.in(MetersPerSecond); 415 return this; 416 } 417 418 /** 419 * Modifies the RotationalDeadband parameter and returns itself. 420 * <p> 421 * The rotational deadband of the request, in radians per second. 422 * 423 * @param newRotationalDeadband Parameter to modify 424 * @return this object 425 */ 426 public final FieldCentric withRotationalDeadband(double newRotationalDeadband) { 427 this.RotationalDeadband = newRotationalDeadband; 428 return this; 429 } 430 431 /** 432 * Modifies the RotationalDeadband parameter and returns itself. 433 * <p> 434 * The rotational deadband of the request, in radians per second. 435 * 436 * @param newRotationalDeadband Parameter to modify 437 * @return this object 438 */ 439 public final FieldCentric withRotationalDeadband(AngularVelocity newRotationalDeadband) { 440 this.RotationalDeadband = newRotationalDeadband.in(RadiansPerSecond); 441 return this; 442 } 443 444 /** 445 * Modifies the CenterOfRotation parameter and returns itself. 446 * <p> 447 * The center of rotation the robot should rotate around. This is (0,0) by 448 * default, which will rotate around the center of the robot. 449 * 450 * @param newCenterOfRotation Parameter to modify 451 * @return this object 452 */ 453 public final FieldCentric withCenterOfRotation(Translation2d newCenterOfRotation) { 454 this.CenterOfRotation = newCenterOfRotation; 455 return this; 456 } 457 458 /** 459 * Modifies the DriveRequestType parameter and returns itself. 460 * <p> 461 * The type of control request to use for the drive motor. 462 * 463 * @param newDriveRequestType Parameter to modify 464 * @return this object 465 */ 466 public final FieldCentric withDriveRequestType(SwerveModule.DriveRequestType newDriveRequestType) { 467 this.DriveRequestType = newDriveRequestType; 468 return this; 469 } 470 471 /** 472 * Modifies the SteerRequestType parameter and returns itself. 473 * <p> 474 * The type of control request to use for the drive motor. 475 * 476 * @param newSteerRequestType Parameter to modify 477 * @return this object 478 */ 479 public final FieldCentric withSteerRequestType(SwerveModule.SteerRequestType newSteerRequestType) { 480 this.SteerRequestType = newSteerRequestType; 481 return this; 482 } 483 484 /** 485 * Modifies the DesaturateWheelVelocities parameter and returns itself. 486 * <p> 487 * Whether to desaturate wheel velocities before applying. For more information, 488 * see the documentation of {@link 489 * SwerveDriveKinematics#desaturateWheelVelocities}. 490 * 491 * @param newDesaturateWheelVelocities Parameter to modify 492 * @return this object 493 */ 494 public final FieldCentric withDesaturateWheelVelocities(boolean newDesaturateWheelVelocities) { 495 this.DesaturateWheelVelocities = newDesaturateWheelVelocities; 496 return this; 497 } 498 499 /** 500 * Modifies the ForwardPerspective parameter and returns itself. 501 * <p> 502 * The perspective to use when determining which direction is forward. 503 * 504 * @param newForwardPerspective Parameter to modify 505 * @return this object 506 */ 507 public final FieldCentric withForwardPerspective(ForwardPerspectiveValue newForwardPerspective) { 508 this.ForwardPerspective = newForwardPerspective; 509 return this; 510 } 511 512 public StatusCode apply(SwerveControlParameters parameters, SwerveModule<?, ?, ?>... modulesToApply) { 513 return StatusCode.valueOf(c_ctre_phoenix6_swerve_request_apply_field_centric( 514 parameters.drivetrainId, 515 VelocityX, 516 VelocityY, 517 RotationalRate, 518 Deadband, 519 RotationalDeadband, 520 CenterOfRotation.getX(), 521 CenterOfRotation.getY(), 522 DriveRequestType.value, 523 SteerRequestType.value, 524 DesaturateWheelVelocities, 525 ForwardPerspective.value 526 )); 527 } 528 529 public void applyNative(int id) { 530 c_ctre_phoenix6_swerve_drivetrain_set_control_field_centric( 531 id, 532 VelocityX, 533 VelocityY, 534 RotationalRate, 535 Deadband, 536 RotationalDeadband, 537 CenterOfRotation.getX(), 538 CenterOfRotation.getY(), 539 DriveRequestType.value, 540 SteerRequestType.value, 541 DesaturateWheelVelocities, 542 ForwardPerspective.value 543 ); 544 } 545 } 546 547 /** 548 * Drives the swerve drivetrain in a robot-centric manner. This request is 549 * optimized for joystick control during teleop with built-in deadbands. 550 * <p> 551 * This request specifies the direction the robot should travel oriented against 552 * the robot itself, and the rate at which their robot should rotate about the 553 * center of the robot. 554 * <p> 555 * An example scenario is that the robot is oriented to the field +Y (left), the 556 * VelocityX is +5 m/s, VelocityY is 0 m/s, and RotationRate is 0.5 rad/s. In 557 * this scenario, the robot would drive forward relative to itself (or left 558 * along the field +Y) at 5 m/s and turn counterclockwise at 0.5 rad/s. 559 */ 560 public static class RobotCentric implements NativeSwerveRequest { 561 /** 562 * The velocity in the X direction, in m/s. X is defined as forward according to 563 * WPILib convention, so this determines how fast to travel forward. 564 */ 565 public double VelocityX = 0; 566 /** 567 * The velocity in the Y direction, in m/s. Y is defined as to the left 568 * according to WPILib convention, so this determines how fast to travel to the 569 * left. 570 */ 571 public double VelocityY = 0; 572 /** 573 * The angular rate to rotate at, in radians per second. Angular rate is defined 574 * as counterclockwise positive, so this determines how fast to turn 575 * counterclockwise. 576 */ 577 public double RotationalRate = 0; 578 /** 579 * The allowable deadband of the request, in m/s. 580 */ 581 public double Deadband = 0; 582 /** 583 * The rotational deadband of the request, in radians per second. 584 */ 585 public double RotationalDeadband = 0; 586 /** 587 * The center of rotation the robot should rotate around. This is (0,0) by 588 * default, which will rotate around the center of the robot. 589 */ 590 public Translation2d CenterOfRotation = new Translation2d(); 591 /** 592 * The type of control request to use for the drive motor. 593 */ 594 public SwerveModule.DriveRequestType DriveRequestType = SwerveModule.DriveRequestType.OpenLoopVoltage; 595 /** 596 * The type of control request to use for the drive motor. 597 */ 598 public SwerveModule.SteerRequestType SteerRequestType = SwerveModule.SteerRequestType.Position; 599 /** 600 * Whether to desaturate wheel velocities before applying. For more information, 601 * see the documentation of {@link 602 * SwerveDriveKinematics#desaturateWheelVelocities}. 603 */ 604 public boolean DesaturateWheelVelocities = true; 605 606 /** 607 * Modifies the VelocityX parameter and returns itself. 608 * <p> 609 * The velocity in the X direction, in m/s. X is defined as forward according to 610 * WPILib convention, so this determines how fast to travel forward. 611 * 612 * @param newVelocityX Parameter to modify 613 * @return this object 614 */ 615 public final RobotCentric withVelocityX(double newVelocityX) { 616 this.VelocityX = newVelocityX; 617 return this; 618 } 619 620 /** 621 * Modifies the VelocityX parameter and returns itself. 622 * <p> 623 * The velocity in the X direction, in m/s. X is defined as forward according to 624 * WPILib convention, so this determines how fast to travel forward. 625 * 626 * @param newVelocityX Parameter to modify 627 * @return this object 628 */ 629 public final RobotCentric withVelocityX(LinearVelocity newVelocityX) { 630 this.VelocityX = newVelocityX.in(MetersPerSecond); 631 return this; 632 } 633 634 /** 635 * Modifies the VelocityY parameter and returns itself. 636 * <p> 637 * The velocity in the Y direction, in m/s. Y is defined as to the left 638 * according to WPILib convention, so this determines how fast to travel to the 639 * left. 640 * 641 * @param newVelocityY Parameter to modify 642 * @return this object 643 */ 644 public final RobotCentric withVelocityY(double newVelocityY) { 645 this.VelocityY = newVelocityY; 646 return this; 647 } 648 649 /** 650 * Modifies the VelocityY parameter and returns itself. 651 * <p> 652 * The velocity in the Y direction, in m/s. Y is defined as to the left 653 * according to WPILib convention, so this determines how fast to travel to the 654 * left. 655 * 656 * @param newVelocityY Parameter to modify 657 * @return this object 658 */ 659 public final RobotCentric withVelocityY(LinearVelocity newVelocityY) { 660 this.VelocityY = newVelocityY.in(MetersPerSecond); 661 return this; 662 } 663 664 /** 665 * Modifies the RotationalRate parameter and returns itself. 666 * <p> 667 * The angular rate to rotate at, in radians per second. Angular rate is defined 668 * as counterclockwise positive, so this determines how fast to turn 669 * counterclockwise. 670 * 671 * @param newRotationalRate Parameter to modify 672 * @return this object 673 */ 674 public final RobotCentric withRotationalRate(double newRotationalRate) { 675 this.RotationalRate = newRotationalRate; 676 return this; 677 } 678 679 /** 680 * Modifies the RotationalRate parameter and returns itself. 681 * <p> 682 * The angular rate to rotate at, in radians per second. Angular rate is defined 683 * as counterclockwise positive, so this determines how fast to turn 684 * counterclockwise. 685 * 686 * @param newRotationalRate Parameter to modify 687 * @return this object 688 */ 689 public final RobotCentric withRotationalRate(AngularVelocity newRotationalRate) { 690 this.RotationalRate = newRotationalRate.in(RadiansPerSecond); 691 return this; 692 } 693 694 /** 695 * Modifies the Deadband parameter and returns itself. 696 * <p> 697 * The allowable deadband of the request, in m/s. 698 * 699 * @param newDeadband Parameter to modify 700 * @return this object 701 */ 702 public final RobotCentric withDeadband(double newDeadband) { 703 this.Deadband = newDeadband; 704 return this; 705 } 706 707 /** 708 * Modifies the Deadband parameter and returns itself. 709 * <p> 710 * The allowable deadband of the request, in m/s. 711 * 712 * @param newDeadband Parameter to modify 713 * @return this object 714 */ 715 public final RobotCentric withDeadband(LinearVelocity newDeadband) { 716 this.Deadband = newDeadband.in(MetersPerSecond); 717 return this; 718 } 719 720 /** 721 * Modifies the RotationalDeadband parameter and returns itself. 722 * <p> 723 * The rotational deadband of the request, in radians per second. 724 * 725 * @param newRotationalDeadband Parameter to modify 726 * @return this object 727 */ 728 public final RobotCentric withRotationalDeadband(double newRotationalDeadband) { 729 this.RotationalDeadband = newRotationalDeadband; 730 return this; 731 } 732 733 /** 734 * Modifies the RotationalDeadband parameter and returns itself. 735 * <p> 736 * The rotational deadband of the request, in radians per second. 737 * 738 * @param newRotationalDeadband Parameter to modify 739 * @return this object 740 */ 741 public final RobotCentric withRotationalDeadband(AngularVelocity newRotationalDeadband) { 742 this.RotationalDeadband = newRotationalDeadband.in(RadiansPerSecond); 743 return this; 744 } 745 746 /** 747 * Modifies the CenterOfRotation parameter and returns itself. 748 * <p> 749 * The center of rotation the robot should rotate around. This is (0,0) by 750 * default, which will rotate around the center of the robot. 751 * 752 * @param newCenterOfRotation Parameter to modify 753 * @return this object 754 */ 755 public final RobotCentric withCenterOfRotation(Translation2d newCenterOfRotation) { 756 this.CenterOfRotation = newCenterOfRotation; 757 return this; 758 } 759 760 /** 761 * Modifies the DriveRequestType parameter and returns itself. 762 * <p> 763 * The type of control request to use for the drive motor. 764 * 765 * @param newDriveRequestType Parameter to modify 766 * @return this object 767 */ 768 public final RobotCentric withDriveRequestType(SwerveModule.DriveRequestType newDriveRequestType) { 769 this.DriveRequestType = newDriveRequestType; 770 return this; 771 } 772 773 /** 774 * Modifies the SteerRequestType parameter and returns itself. 775 * <p> 776 * The type of control request to use for the drive motor. 777 * 778 * @param newSteerRequestType Parameter to modify 779 * @return this object 780 */ 781 public final RobotCentric withSteerRequestType(SwerveModule.SteerRequestType newSteerRequestType) { 782 this.SteerRequestType = newSteerRequestType; 783 return this; 784 } 785 786 /** 787 * Modifies the DesaturateWheelVelocities parameter and returns itself. 788 * <p> 789 * Whether to desaturate wheel velocities before applying. For more information, 790 * see the documentation of {@link 791 * SwerveDriveKinematics#desaturateWheelVelocities}. 792 * 793 * @param newDesaturateWheelVelocities Parameter to modify 794 * @return this object 795 */ 796 public final RobotCentric withDesaturateWheelVelocities(boolean newDesaturateWheelVelocities) { 797 this.DesaturateWheelVelocities = newDesaturateWheelVelocities; 798 return this; 799 } 800 801 public StatusCode apply(SwerveControlParameters parameters, SwerveModule<?, ?, ?>... modulesToApply) { 802 return StatusCode.valueOf(c_ctre_phoenix6_swerve_request_apply_robot_centric( 803 parameters.drivetrainId, 804 VelocityX, 805 VelocityY, 806 RotationalRate, 807 Deadband, 808 RotationalDeadband, 809 CenterOfRotation.getX(), 810 CenterOfRotation.getY(), 811 DriveRequestType.value, 812 SteerRequestType.value, 813 DesaturateWheelVelocities 814 )); 815 } 816 817 public void applyNative(int id) { 818 c_ctre_phoenix6_swerve_drivetrain_set_control_robot_centric( 819 id, 820 VelocityX, 821 VelocityY, 822 RotationalRate, 823 Deadband, 824 RotationalDeadband, 825 CenterOfRotation.getX(), 826 CenterOfRotation.getY(), 827 DriveRequestType.value, 828 SteerRequestType.value, 829 DesaturateWheelVelocities 830 ); 831 } 832 } 833 834 /** 835 * Sets the swerve drive modules to point to a specified direction. 836 */ 837 public static class PointWheelsAt implements NativeSwerveRequest { 838 /** 839 * The direction to point the modules toward. This direction is still optimized 840 * to what the module was previously at. 841 */ 842 public Rotation2d ModuleDirection = new Rotation2d(); 843 /** 844 * The type of control request to use for the drive motor. 845 */ 846 public SwerveModule.DriveRequestType DriveRequestType = SwerveModule.DriveRequestType.OpenLoopVoltage; 847 /** 848 * The type of control request to use for the drive motor. 849 */ 850 public SwerveModule.SteerRequestType SteerRequestType = SwerveModule.SteerRequestType.Position; 851 852 /** 853 * Modifies the ModuleDirection parameter and returns itself. 854 * <p> 855 * The direction to point the modules toward. This direction is still optimized 856 * to what the module was previously at. 857 * 858 * @param newModuleDirection Parameter to modify 859 * @return this object 860 */ 861 public final PointWheelsAt withModuleDirection(Rotation2d newModuleDirection) { 862 this.ModuleDirection = newModuleDirection; 863 return this; 864 } 865 866 /** 867 * Modifies the DriveRequestType parameter and returns itself. 868 * <p> 869 * The type of control request to use for the drive motor. 870 * 871 * @param newDriveRequestType Parameter to modify 872 * @return this object 873 */ 874 public final PointWheelsAt withDriveRequestType(SwerveModule.DriveRequestType newDriveRequestType) { 875 this.DriveRequestType = newDriveRequestType; 876 return this; 877 } 878 879 /** 880 * Modifies the SteerRequestType parameter and returns itself. 881 * <p> 882 * The type of control request to use for the drive motor. 883 * 884 * @param newSteerRequestType Parameter to modify 885 * @return this object 886 */ 887 public final PointWheelsAt withSteerRequestType(SwerveModule.SteerRequestType newSteerRequestType) { 888 this.SteerRequestType = newSteerRequestType; 889 return this; 890 } 891 892 public StatusCode apply(SwerveControlParameters parameters, SwerveModule<?, ?, ?>... modulesToApply) { 893 return StatusCode.valueOf(c_ctre_phoenix6_swerve_request_apply_point_wheels_at( 894 parameters.drivetrainId, 895 ModuleDirection.getRadians(), 896 DriveRequestType.value, 897 SteerRequestType.value 898 )); 899 } 900 901 public void applyNative(int id) { 902 c_ctre_phoenix6_swerve_drivetrain_set_control_point_wheels_at( 903 id, 904 ModuleDirection.getRadians(), 905 DriveRequestType.value, 906 SteerRequestType.value 907 ); 908 } 909 } 910 911 /** 912 * Accepts a generic robot-centric ChassisVelocities to apply to the drivetrain. 913 * This request is optimized for autonomous or profiled control, which typically 914 * directly provides ChassisVelocities and optionally wheel force feedforwards. 915 * <p> 916 * Unlike the field-centric requests, this request does not automatically 917 * discretize the provided ChassisVelocities. 918 */ 919 public static class ApplyRobotVelocity implements NativeSwerveRequest { 920 /** 921 * The robot-centric chassis velocity to apply to the drivetrain. 922 * Users must manually discretize the velocity if appropriate. 923 */ 924 public ChassisVelocities Velocity = new ChassisVelocities(); 925 /** 926 * Robot-centric wheel force feedforwards to apply in the X direction, in 927 * newtons. X is defined as forward according to WPILib convention, so this 928 * determines the forward forces to apply. 929 * <p> 930 * These forces should include friction applied to the ground. 931 * <p> 932 * The order of the forces should match the order of the modules returned from 933 * SwerveDrivetrain. 934 */ 935 public double[] WheelForceFeedforwardsX = {}; 936 /** 937 * Robot-centric wheel force feedforwards to apply in the Y direction, in 938 * newtons. Y is defined as to the left according to WPILib convention, so this 939 * determines the forces to apply to the left. 940 * <p> 941 * These forces should include friction applied to the ground. 942 * <p> 943 * The order of the forces should match the order of the modules returned from 944 * SwerveDrivetrain. 945 */ 946 public double[] WheelForceFeedforwardsY = {}; 947 /** 948 * The center of rotation the robot should rotate around. This is (0,0) by 949 * default, which will rotate around the center of the robot. 950 */ 951 public Translation2d CenterOfRotation = new Translation2d(); 952 /** 953 * The type of control request to use for the drive motor. 954 */ 955 public SwerveModule.DriveRequestType DriveRequestType = SwerveModule.DriveRequestType.OpenLoopVoltage; 956 /** 957 * The type of control request to use for the drive motor. 958 */ 959 public SwerveModule.SteerRequestType SteerRequestType = SwerveModule.SteerRequestType.Position; 960 /** 961 * Whether to desaturate wheel velocities before applying. For more information, see 962 * the documentation of {@link SwerveDriveKinematics#desaturateWheelVelocities}. 963 */ 964 public boolean DesaturateWheelVelocities = true; 965 966 /** 967 * Modifies the Velocity parameter and returns itself. 968 * <p> 969 * The robot-centric chassis velocity to apply to the drivetrain. 970 * Users must manually discretize the velocity if appropriate. 971 * 972 * @param newVelocity Parameter to modify 973 * @return this object 974 */ 975 public final ApplyRobotVelocity withVelocity(ChassisVelocities newVelocity) { 976 this.Velocity = newVelocity; 977 return this; 978 } 979 980 /** 981 * Modifies the WheelForceFeedforwardsX parameter and returns itself. 982 * <p> 983 * Robot-centric wheel force feedforwards to apply in the X direction, in 984 * newtons. X is defined as forward according to WPILib convention, so this 985 * determines the forward forces to apply. 986 * <p> 987 * These forces should include friction applied to the ground. 988 * <p> 989 * The order of the forces should match the order of the modules returned from 990 * SwerveDrivetrain. 991 * 992 * @param newWheelForceFeedforwardsX Parameter to modify 993 * @return this object 994 */ 995 public final ApplyRobotVelocity withWheelForceFeedforwardsX(double[] newWheelForceFeedforwardsX) { 996 this.WheelForceFeedforwardsX = newWheelForceFeedforwardsX; 997 return this; 998 } 999 1000 /** 1001 * Modifies the WheelForceFeedforwardsX parameter and returns itself. 1002 * <p> 1003 * Robot-centric wheel force feedforwards to apply in the X direction, in 1004 * newtons. X is defined as forward according to WPILib convention, so this 1005 * determines the forward forces to apply. 1006 * <p> 1007 * These forces should include friction applied to the ground. 1008 * <p> 1009 * The order of the forces should match the order of the modules returned from 1010 * SwerveDrivetrain. 1011 * 1012 * @param newWheelForceFeedforwardsX Parameter to modify 1013 * @return this object 1014 */ 1015 public final ApplyRobotVelocity withWheelForceFeedforwardsX(Force[] newWheelForceFeedforwardsX) { 1016 if (this.WheelForceFeedforwardsX.length != newWheelForceFeedforwardsX.length) { 1017 this.WheelForceFeedforwardsX = new double[newWheelForceFeedforwardsX.length]; 1018 } 1019 for (int i = 0; i < this.WheelForceFeedforwardsX.length; ++i) { 1020 this.WheelForceFeedforwardsX[i] = newWheelForceFeedforwardsX[i].in(Newtons); 1021 } 1022 1023 return this; 1024 } 1025 1026 /** 1027 * Modifies the WheelForceFeedforwardsY parameter and returns itself. 1028 * <p> 1029 * Robot-centric wheel force feedforwards to apply in the Y direction, in 1030 * newtons. Y is defined as to the left according to WPILib convention, so this 1031 * determines the forces to apply to the left. 1032 * <p> 1033 * These forces should include friction applied to the ground. 1034 * <p> 1035 * The order of the forces should match the order of the modules returned from 1036 * SwerveDrivetrain. 1037 * 1038 * @param newWheelForceFeedforwardsY Parameter to modify 1039 * @return this object 1040 */ 1041 public final ApplyRobotVelocity withWheelForceFeedforwardsY(double[] newWheelForceFeedforwardsY) { 1042 this.WheelForceFeedforwardsY = newWheelForceFeedforwardsY; 1043 return this; 1044 } 1045 1046 /** 1047 * Modifies the WheelForceFeedforwardsY parameter and returns itself. 1048 * <p> 1049 * Robot-centric wheel force feedforwards to apply in the Y direction, in 1050 * newtons. Y is defined as to the left according to WPILib convention, so this 1051 * determines the forces to apply to the left. 1052 * <p> 1053 * These forces should include friction applied to the ground. 1054 * <p> 1055 * The order of the forces should match the order of the modules returned from 1056 * SwerveDrivetrain. 1057 * 1058 * @param newWheelForceFeedforwardsY Parameter to modify 1059 * @return this object 1060 */ 1061 public final ApplyRobotVelocity withWheelForceFeedforwardsY(Force[] newWheelForceFeedforwardsY) { 1062 if (this.WheelForceFeedforwardsY.length != newWheelForceFeedforwardsY.length) { 1063 this.WheelForceFeedforwardsY = new double[newWheelForceFeedforwardsY.length]; 1064 } 1065 for (int i = 0; i < this.WheelForceFeedforwardsY.length; ++i) { 1066 this.WheelForceFeedforwardsY[i] = newWheelForceFeedforwardsY[i].in(Newtons); 1067 } 1068 1069 return this; 1070 } 1071 1072 /** 1073 * Modifies the CenterOfRotation parameter and returns itself. 1074 * <p> 1075 * The center of rotation the robot should rotate around. This is (0,0) by 1076 * default, which will rotate around the center of the robot. 1077 * 1078 * @param newCenterOfRotation Parameter to modify 1079 * @return this object 1080 */ 1081 public final ApplyRobotVelocity withCenterOfRotation(Translation2d newCenterOfRotation) { 1082 this.CenterOfRotation = newCenterOfRotation; 1083 return this; 1084 } 1085 1086 /** 1087 * Modifies the DriveRequestType parameter and returns itself. 1088 * <p> 1089 * The type of control request to use for the drive motor. 1090 * 1091 * @param newDriveRequestType Parameter to modify 1092 * @return this object 1093 */ 1094 public final ApplyRobotVelocity withDriveRequestType(SwerveModule.DriveRequestType newDriveRequestType) { 1095 this.DriveRequestType = newDriveRequestType; 1096 return this; 1097 } 1098 1099 /** 1100 * Modifies the SteerRequestType parameter and returns itself. 1101 * <p> 1102 * The type of control request to use for the drive motor. 1103 * 1104 * @param newSteerRequestType Parameter to modify 1105 * @return this object 1106 */ 1107 public final ApplyRobotVelocity withSteerRequestType(SwerveModule.SteerRequestType newSteerRequestType) { 1108 this.SteerRequestType = newSteerRequestType; 1109 return this; 1110 } 1111 1112 /** 1113 * Modifies the DesaturateWheelVelocities parameter and returns itself. 1114 * <p> 1115 * Whether to desaturate wheel velocities before applying. For more information, see 1116 * the documentation of {@link SwerveDriveKinematics#desaturateWheelVelocities}. 1117 * 1118 * @param newDesaturateWheelVelocities Parameter to modify 1119 * @return this object 1120 */ 1121 public final ApplyRobotVelocity withDesaturateWheelVelocities(boolean newDesaturateWheelVelocities) { 1122 this.DesaturateWheelVelocities = newDesaturateWheelVelocities; 1123 return this; 1124 } 1125 1126 public StatusCode apply(SwerveControlParameters parameters, SwerveModule<?, ?, ?>... modulesToApply) { 1127 try (final var arena = Arena.ofConfined()) { 1128 return StatusCode.valueOf(c_ctre_phoenix6_swerve_request_apply_apply_robot_velocity( 1129 parameters.drivetrainId, 1130 Velocity.vx, 1131 Velocity.vy, 1132 Velocity.omega, 1133 arena.allocateFrom(ValueLayout.JAVA_DOUBLE, WheelForceFeedforwardsX), 1134 WheelForceFeedforwardsX.length, 1135 arena.allocateFrom(ValueLayout.JAVA_DOUBLE, WheelForceFeedforwardsY), 1136 WheelForceFeedforwardsY.length, 1137 CenterOfRotation.getX(), 1138 CenterOfRotation.getY(), 1139 DriveRequestType.value, 1140 SteerRequestType.value, 1141 DesaturateWheelVelocities 1142 )); 1143 } 1144 } 1145 1146 public void applyNative(int id) { 1147 try (final var arena = Arena.ofConfined()) { 1148 c_ctre_phoenix6_swerve_drivetrain_set_control_apply_robot_velocity( 1149 id, 1150 Velocity.vx, 1151 Velocity.vy, 1152 Velocity.omega, 1153 arena.allocateFrom(ValueLayout.JAVA_DOUBLE, WheelForceFeedforwardsX), 1154 WheelForceFeedforwardsX.length, 1155 arena.allocateFrom(ValueLayout.JAVA_DOUBLE, WheelForceFeedforwardsY), 1156 WheelForceFeedforwardsY.length, 1157 CenterOfRotation.getX(), 1158 CenterOfRotation.getY(), 1159 DriveRequestType.value, 1160 SteerRequestType.value, 1161 DesaturateWheelVelocities 1162 ); 1163 } 1164 } 1165 } 1166 1167 /** 1168 * Accepts a generic field-centric ChassisVelocities to apply to the drivetrain. 1169 * This request is optimized for autonomous or profiled control, which typically 1170 * directly provides ChassisVelocities and optionally wheel force feedforwards. 1171 */ 1172 public static class ApplyFieldVelocity implements NativeSwerveRequest { 1173 /** 1174 * The field-centric chassis velocity to apply to the drivetrain. 1175 */ 1176 public ChassisVelocities Velocity = new ChassisVelocities(); 1177 /** 1178 * Field-centric wheel force feedforwards to apply in the X direction, in 1179 * newtons. X is defined as forward according to WPILib convention, so this 1180 * determines the forward forces to apply. 1181 * <p> 1182 * These forces should include friction applied to the ground. 1183 * <p> 1184 * The order of the forces should match the order of the modules returned from 1185 * SwerveDrivetrain. 1186 */ 1187 public double[] WheelForceFeedforwardsX = {}; 1188 /** 1189 * Field-centric wheel force feedforwards to apply in the Y direction, in 1190 * newtons. Y is defined as to the left according to WPILib convention, so this 1191 * determines the forces to apply to the left. 1192 * <p> 1193 * These forces should include friction applied to the ground. 1194 * <p> 1195 * The order of the forces should match the order of the modules returned from 1196 * SwerveDrivetrain. 1197 */ 1198 public double[] WheelForceFeedforwardsY = {}; 1199 /** 1200 * The center of rotation the robot should rotate around. This is (0,0) by 1201 * default, which will rotate around the center of the robot. 1202 */ 1203 public Translation2d CenterOfRotation = new Translation2d(); 1204 /** 1205 * The type of control request to use for the drive motor. 1206 */ 1207 public SwerveModule.DriveRequestType DriveRequestType = SwerveModule.DriveRequestType.OpenLoopVoltage; 1208 /** 1209 * The type of control request to use for the drive motor. 1210 */ 1211 public SwerveModule.SteerRequestType SteerRequestType = SwerveModule.SteerRequestType.Position; 1212 /** 1213 * Whether to desaturate wheel velocities before applying. For more information, see 1214 * the documentation of {@link SwerveDriveKinematics#desaturateWheelVelocities}. 1215 */ 1216 public boolean DesaturateWheelVelocities = true; 1217 /** 1218 * The perspective to use when determining which direction is forward. 1219 */ 1220 public ForwardPerspectiveValue ForwardPerspective = ForwardPerspectiveValue.BlueAlliance; 1221 1222 /** 1223 * Modifies the Velocity parameter and returns itself. 1224 * <p> 1225 * The field-centric chassis velocity to apply to the drivetrain. 1226 * 1227 * @param newVelocity Parameter to modify 1228 * @return this object 1229 */ 1230 public final ApplyFieldVelocity withVelocity(ChassisVelocities newVelocity) { 1231 this.Velocity = newVelocity; 1232 return this; 1233 } 1234 1235 /** 1236 * Modifies the WheelForceFeedforwardsX parameter and returns itself. 1237 * <p> 1238 * Field-centric wheel force feedforwards to apply in the X direction, in 1239 * newtons. X is defined as forward according to WPILib convention, so this 1240 * determines the forward forces to apply. 1241 * <p> 1242 * These forces should include friction applied to the ground. 1243 * <p> 1244 * The order of the forces should match the order of the modules returned from 1245 * SwerveDrivetrain. 1246 * 1247 * @param newWheelForceFeedforwardsX Parameter to modify 1248 * @return this object 1249 */ 1250 public final ApplyFieldVelocity withWheelForceFeedforwardsX(double[] newWheelForceFeedforwardsX) { 1251 this.WheelForceFeedforwardsX = newWheelForceFeedforwardsX; 1252 return this; 1253 } 1254 1255 /** 1256 * Modifies the WheelForceFeedforwardsX parameter and returns itself. 1257 * <p> 1258 * Field-centric wheel force feedforwards to apply in the X direction, in 1259 * newtons. X is defined as forward according to WPILib convention, so this 1260 * determines the forward forces to apply. 1261 * <p> 1262 * These forces should include friction applied to the ground. 1263 * <p> 1264 * The order of the forces should match the order of the modules returned from 1265 * SwerveDrivetrain. 1266 * 1267 * @param newWheelForceFeedforwardsX Parameter to modify 1268 * @return this object 1269 */ 1270 public final ApplyFieldVelocity withWheelForceFeedforwardsX(Force[] newWheelForceFeedforwardsX) { 1271 if (this.WheelForceFeedforwardsX.length != newWheelForceFeedforwardsX.length) { 1272 this.WheelForceFeedforwardsX = new double[newWheelForceFeedforwardsX.length]; 1273 } 1274 for (int i = 0; i < this.WheelForceFeedforwardsX.length; ++i) { 1275 this.WheelForceFeedforwardsX[i] = newWheelForceFeedforwardsX[i].in(Newtons); 1276 } 1277 1278 return this; 1279 } 1280 1281 /** 1282 * Modifies the WheelForceFeedforwardsY parameter and returns itself. 1283 * <p> 1284 * Field-centric wheel force feedforwards to apply in the Y direction, in 1285 * newtons. Y is defined as to the left according to WPILib convention, so this 1286 * determines the forces to apply to the left. 1287 * <p> 1288 * These forces should include friction applied to the ground. 1289 * <p> 1290 * The order of the forces should match the order of the modules returned from 1291 * SwerveDrivetrain. 1292 * 1293 * @param newWheelForceFeedforwardsY Parameter to modify 1294 * @return this object 1295 */ 1296 public final ApplyFieldVelocity withWheelForceFeedforwardsY(double[] newWheelForceFeedforwardsY) { 1297 this.WheelForceFeedforwardsY = newWheelForceFeedforwardsY; 1298 return this; 1299 } 1300 1301 /** 1302 * Modifies the WheelForceFeedforwardsY parameter and returns itself. 1303 * <p> 1304 * Field-centric wheel force feedforwards to apply in the Y direction, in 1305 * newtons. Y is defined as to the left according to WPILib convention, so this 1306 * determines the forces to apply to the left. 1307 * <p> 1308 * These forces should include friction applied to the ground. 1309 * <p> 1310 * The order of the forces should match the order of the modules returned from 1311 * SwerveDrivetrain. 1312 * 1313 * @param newWheelForceFeedforwardsY Parameter to modify 1314 * @return this object 1315 */ 1316 public final ApplyFieldVelocity withWheelForceFeedforwardsY(Force[] newWheelForceFeedforwardsY) { 1317 if (this.WheelForceFeedforwardsY.length != newWheelForceFeedforwardsY.length) { 1318 this.WheelForceFeedforwardsY = new double[newWheelForceFeedforwardsY.length]; 1319 } 1320 for (int i = 0; i < this.WheelForceFeedforwardsY.length; ++i) { 1321 this.WheelForceFeedforwardsY[i] = newWheelForceFeedforwardsY[i].in(Newtons); 1322 } 1323 1324 return this; 1325 } 1326 1327 /** 1328 * Modifies the CenterOfRotation parameter and returns itself. 1329 * <p> 1330 * The center of rotation the robot should rotate around. This is (0,0) by 1331 * default, which will rotate around the center of the robot. 1332 * 1333 * @param newCenterOfRotation Parameter to modify 1334 * @return this object 1335 */ 1336 public final ApplyFieldVelocity withCenterOfRotation(Translation2d newCenterOfRotation) { 1337 this.CenterOfRotation = newCenterOfRotation; 1338 return this; 1339 } 1340 1341 /** 1342 * Modifies the DriveRequestType parameter and returns itself. 1343 * <p> 1344 * The type of control request to use for the drive motor. 1345 * 1346 * @param newDriveRequestType Parameter to modify 1347 * @return this object 1348 */ 1349 public final ApplyFieldVelocity withDriveRequestType(SwerveModule.DriveRequestType newDriveRequestType) { 1350 this.DriveRequestType = newDriveRequestType; 1351 return this; 1352 } 1353 1354 /** 1355 * Modifies the SteerRequestType parameter and returns itself. 1356 * <p> 1357 * The type of control request to use for the drive motor. 1358 * 1359 * @param newSteerRequestType Parameter to modify 1360 * @return this object 1361 */ 1362 public final ApplyFieldVelocity withSteerRequestType(SwerveModule.SteerRequestType newSteerRequestType) { 1363 this.SteerRequestType = newSteerRequestType; 1364 return this; 1365 } 1366 1367 /** 1368 * Modifies the DesaturateWheelVelocities parameter and returns itself. 1369 * <p> 1370 * Whether to desaturate wheel velocities before applying. For more information, see 1371 * the documentation of {@link SwerveDriveKinematics#desaturateWheelVelocities}. 1372 * 1373 * @param newDesaturateWheelVelocities Parameter to modify 1374 * @return this object 1375 */ 1376 public final ApplyFieldVelocity withDesaturateWheelVelocities(boolean newDesaturateWheelVelocities) { 1377 this.DesaturateWheelVelocities = newDesaturateWheelVelocities; 1378 return this; 1379 } 1380 1381 /** 1382 * Modifies the ForwardPerspective parameter and returns itself. 1383 * <p> 1384 * The perspective to use when determining which direction is forward. 1385 * 1386 * @param newForwardPerspective Parameter to modify 1387 * @return this object 1388 */ 1389 public final ApplyFieldVelocity withForwardPerspective(ForwardPerspectiveValue newForwardPerspective) { 1390 this.ForwardPerspective = newForwardPerspective; 1391 return this; 1392 } 1393 1394 public StatusCode apply(SwerveControlParameters parameters, SwerveModule<?, ?, ?>... modulesToApply) { 1395 try (final var arena = Arena.ofConfined()) { 1396 return StatusCode.valueOf(c_ctre_phoenix6_swerve_request_apply_apply_field_velocity( 1397 parameters.drivetrainId, 1398 Velocity.vx, 1399 Velocity.vy, 1400 Velocity.omega, 1401 arena.allocateFrom(ValueLayout.JAVA_DOUBLE, WheelForceFeedforwardsX), 1402 WheelForceFeedforwardsX.length, 1403 arena.allocateFrom(ValueLayout.JAVA_DOUBLE, WheelForceFeedforwardsY), 1404 WheelForceFeedforwardsY.length, 1405 CenterOfRotation.getX(), 1406 CenterOfRotation.getY(), 1407 DriveRequestType.value, 1408 SteerRequestType.value, 1409 DesaturateWheelVelocities, 1410 ForwardPerspective.value 1411 )); 1412 } 1413 } 1414 1415 public void applyNative(int id) { 1416 try (final var arena = Arena.ofConfined()) { 1417 c_ctre_phoenix6_swerve_drivetrain_set_control_apply_field_velocity( 1418 id, 1419 Velocity.vx, 1420 Velocity.vy, 1421 Velocity.omega, 1422 arena.allocateFrom(ValueLayout.JAVA_DOUBLE, WheelForceFeedforwardsX), 1423 WheelForceFeedforwardsX.length, 1424 arena.allocateFrom(ValueLayout.JAVA_DOUBLE, WheelForceFeedforwardsY), 1425 WheelForceFeedforwardsY.length, 1426 CenterOfRotation.getX(), 1427 CenterOfRotation.getY(), 1428 DriveRequestType.value, 1429 SteerRequestType.value, 1430 DesaturateWheelVelocities, 1431 ForwardPerspective.value 1432 ); 1433 } 1434 } 1435 } 1436 1437 /** 1438 * Drives the swerve drivetrain in a field-centric manner, maintaining a 1439 * specified heading angle to ensure the robot is facing the desired direction 1440 * <p> 1441 * When users use this request, they specify the direction the robot should 1442 * travel oriented against the field, and the direction the robot should be facing. 1443 * <p> 1444 * An example scenario is that the robot is oriented to the east, the VelocityX 1445 * is +5 m/s, VelocityY is 0 m/s, and TargetDirection is 180 degrees. 1446 * In this scenario, the robot would drive northward at 5 m/s and turn clockwise 1447 * to a target of 180 degrees. 1448 * <p> 1449 * This control request is especially useful for autonomous control, where the 1450 * robot should be facing a changing direction throughout the motion. 1451 */ 1452 public static class FieldCentricFacingAngle implements SwerveRequest { 1453 /** 1454 * The velocity in the X direction, in m/s. 1455 * X is defined as forward according to WPILib convention, 1456 * so this determines how fast to travel forward. 1457 */ 1458 public double VelocityX = 0; 1459 /** 1460 * The velocity in the Y direction, in m/s. 1461 * Y is defined as to the left according to WPILib convention, 1462 * so this determines how fast to travel to the left. 1463 */ 1464 public double VelocityY = 0; 1465 /** 1466 * The desired direction to face. 1467 * 0 Degrees is defined as in the direction of the X axis. 1468 * As a result, a TargetDirection of 90 degrees will point along 1469 * the Y axis, or to the left. 1470 */ 1471 public Rotation2d TargetDirection = new Rotation2d(); 1472 /** 1473 * The rotational rate feedforward to add to the output of the heading 1474 * controller, in radians per second. When using a motion profile for the 1475 * target direction, this can be set to the current velocity reference of 1476 * the profile. 1477 */ 1478 public double TargetRateFeedforward = 0; 1479 1480 /** 1481 * The allowable deadband of the request, in m/s. 1482 */ 1483 public double Deadband = 0; 1484 /** 1485 * The rotational deadband of the request, in radians per second. 1486 */ 1487 public double RotationalDeadband = 0; 1488 /** 1489 * The maximum absolute rotational rate to allow, in radians per second. 1490 * Setting this to 0 results in no cap to rotational rate. 1491 */ 1492 public double MaxAbsRotationalRate = 0; 1493 /** 1494 * The center of rotation the robot should rotate around. 1495 * This is (0,0) by default, which will rotate around the center of the robot. 1496 */ 1497 public Translation2d CenterOfRotation = new Translation2d(); 1498 1499 /** 1500 * The type of control request to use for the drive motor. 1501 */ 1502 public SwerveModule.DriveRequestType DriveRequestType = SwerveModule.DriveRequestType.OpenLoopVoltage; 1503 /** 1504 * The type of control request to use for the steer motor. 1505 */ 1506 public SwerveModule.SteerRequestType SteerRequestType = SwerveModule.SteerRequestType.Position; 1507 /** 1508 * Whether to desaturate wheel velocities before applying. 1509 * For more information, see the documentation of {@link SwerveDriveKinematics#desaturateWheelVelocities}. 1510 */ 1511 public boolean DesaturateWheelVelocities = true; 1512 1513 /** 1514 * The perspective to use when determining which direction is forward. 1515 */ 1516 public ForwardPerspectiveValue ForwardPerspective = ForwardPerspectiveValue.OperatorPerspective; 1517 /** 1518 * The perspective to use when determining which direction is forward for the 1519 * {@link #TargetDirection}. This allows for the heading control to use a different 1520 * perspective from the translation control. 1521 */ 1522 public TargetDirectionPerspectiveValue TargetDirectionPerspective = TargetDirectionPerspectiveValue.UseForwardPerspective; 1523 1524 /** 1525 * The PID controller used to maintain the desired heading. 1526 * Users can specify the PID gains to change how aggressively to maintain 1527 * heading. 1528 * <p> 1529 * This PID controller operates on heading radians and outputs a target 1530 * rotational rate in radians per second. Note that continuous input should 1531 * be enabled on the range [-pi, pi]. 1532 */ 1533 public PhoenixPIDController HeadingController = new PhoenixPIDController(0, 0, 0); 1534 1535 private final FieldCentric m_fieldCentric = new FieldCentric(); 1536 1537 public FieldCentricFacingAngle() { 1538 HeadingController.enableContinuousInput(-Math.PI, Math.PI); 1539 } 1540 1541 public StatusCode apply(SwerveControlParameters parameters, SwerveModule<?, ?, ?>... modulesToApply) { 1542 Rotation2d angleToFace = TargetDirection; 1543 if ( 1544 TargetDirectionPerspective == TargetDirectionPerspectiveValue.UseForwardPerspective && 1545 ForwardPerspective == ForwardPerspectiveValue.OperatorPerspective 1546 ) { 1547 /* If we're operator perspective, rotate the direction we want to face by the angle */ 1548 angleToFace = angleToFace.rotateBy(parameters.operatorForwardDirection); 1549 } 1550 1551 double toApplyOmega = TargetRateFeedforward + 1552 HeadingController.calculate( 1553 parameters.currentPose.getRotation().getRadians(), 1554 angleToFace.getRadians(), 1555 parameters.timestamp 1556 ); 1557 if (MaxAbsRotationalRate > 0.0) { 1558 if (toApplyOmega > MaxAbsRotationalRate) { 1559 toApplyOmega = MaxAbsRotationalRate; 1560 } else if (toApplyOmega < -MaxAbsRotationalRate) { 1561 toApplyOmega = -MaxAbsRotationalRate; 1562 } 1563 } 1564 1565 return m_fieldCentric 1566 .withVelocityX(VelocityX) 1567 .withVelocityY(VelocityY) 1568 .withRotationalRate(toApplyOmega) 1569 .withDeadband(Deadband) 1570 .withRotationalDeadband(RotationalDeadband) 1571 .withCenterOfRotation(CenterOfRotation) 1572 .withDriveRequestType(DriveRequestType) 1573 .withSteerRequestType(SteerRequestType) 1574 .withDesaturateWheelVelocities(DesaturateWheelVelocities) 1575 .withForwardPerspective(ForwardPerspective) 1576 .apply(parameters, modulesToApply); 1577 } 1578 1579 /** 1580 * Modifies the PID gains of the HeadingController parameter and returns itself. 1581 * <p> 1582 * Sets the proportional, integral, and differential coefficients used to maintain 1583 * the desired heading. Users can specify the PID gains to change how aggressively to 1584 * maintain heading. 1585 * <p> 1586 * This PID controller operates on heading radians and outputs a target 1587 * rotational rate in radians per second. 1588 * 1589 * @param kP The proportional coefficient; must be >= 0 1590 * @param kI The integral coefficient; must be >= 0 1591 * @param kD The differential coefficient; must be >= 0 1592 * @return this object 1593 */ 1594 public final FieldCentricFacingAngle withHeadingPID(double kP, double kI, double kD) 1595 { 1596 this.HeadingController.setPID(kP, kI, kD); 1597 return this; 1598 } 1599 1600 /** 1601 * Modifies the VelocityX parameter and returns itself. 1602 * <p> 1603 * The velocity in the X direction, in m/s. X is defined as forward according to 1604 * WPILib convention, so this determines how fast to travel forward. 1605 * 1606 * @param newVelocityX Parameter to modify 1607 * @return this object 1608 */ 1609 public final FieldCentricFacingAngle withVelocityX(double newVelocityX) { 1610 this.VelocityX = newVelocityX; 1611 return this; 1612 } 1613 1614 /** 1615 * Modifies the VelocityX parameter and returns itself. 1616 * <p> 1617 * The velocity in the X direction, in m/s. X is defined as forward according to 1618 * WPILib convention, so this determines how fast to travel forward. 1619 * 1620 * @param newVelocityX Parameter to modify 1621 * @return this object 1622 */ 1623 public final FieldCentricFacingAngle withVelocityX(LinearVelocity newVelocityX) { 1624 this.VelocityX = newVelocityX.in(MetersPerSecond); 1625 return this; 1626 } 1627 1628 /** 1629 * Modifies the VelocityY parameter and returns itself. 1630 * <p> 1631 * The velocity in the Y direction, in m/s. Y is defined as to the left 1632 * according to WPILib convention, so this determines how fast to travel to the 1633 * left. 1634 * 1635 * @param newVelocityY Parameter to modify 1636 * @return this object 1637 */ 1638 public final FieldCentricFacingAngle withVelocityY(double newVelocityY) { 1639 this.VelocityY = newVelocityY; 1640 return this; 1641 } 1642 1643 /** 1644 * Modifies the VelocityY parameter and returns itself. 1645 * <p> 1646 * The velocity in the Y direction, in m/s. Y is defined as to the left 1647 * according to WPILib convention, so this determines how fast to travel to the 1648 * left. 1649 * 1650 * @param newVelocityY Parameter to modify 1651 * @return this object 1652 */ 1653 public final FieldCentricFacingAngle withVelocityY(LinearVelocity newVelocityY) { 1654 this.VelocityY = newVelocityY.in(MetersPerSecond); 1655 return this; 1656 } 1657 1658 /** 1659 * Modifies the TargetDirection parameter and returns itself. 1660 * <p> 1661 * The desired direction to face. 0 Degrees is defined as in the direction of 1662 * the X axis. As a result, a TargetDirection of 90 degrees will point along 1663 * the Y axis, or to the left. 1664 * 1665 * @param newTargetDirection Parameter to modify 1666 * @return this object 1667 */ 1668 public final FieldCentricFacingAngle withTargetDirection(Rotation2d newTargetDirection) { 1669 this.TargetDirection = newTargetDirection; 1670 return this; 1671 } 1672 1673 /** 1674 * Modifies the TargetRateFeedforward parameter and returns itself. 1675 * <p> 1676 * The rotational rate feedforward to add to the output of the heading 1677 * controller, in radians per second. When using a motion profile for the 1678 * target direction, this can be set to the current velocity reference of 1679 * the profile. 1680 * 1681 * @param newTargetRateFeedforward Parameter to modify 1682 * @return this object 1683 */ 1684 public final FieldCentricFacingAngle withTargetRateFeedforward(double newTargetRateFeedforward) { 1685 this.TargetRateFeedforward = newTargetRateFeedforward; 1686 return this; 1687 } 1688 /** 1689 * Modifies the TargetRateFeedforward parameter and returns itself. 1690 * <p> 1691 * The rotational rate feedforward to add to the output of the heading 1692 * controller, in radians per second. When using a motion profile for the 1693 * target direction, this can be set to the current velocity reference of 1694 * the profile. 1695 * 1696 * @param newTargetRateFeedforward Parameter to modify 1697 * @return this object 1698 */ 1699 public final FieldCentricFacingAngle withTargetRateFeedforward(AngularVelocity newTargetRateFeedforward) { 1700 this.TargetRateFeedforward = newTargetRateFeedforward.in(RadiansPerSecond); 1701 return this; 1702 } 1703 1704 /** 1705 * Modifies the Deadband parameter and returns itself. 1706 * <p> 1707 * The allowable deadband of the request, in m/s. 1708 * 1709 * @param newDeadband Parameter to modify 1710 * @return this object 1711 */ 1712 public final FieldCentricFacingAngle withDeadband(double newDeadband) { 1713 this.Deadband = newDeadband; 1714 return this; 1715 } 1716 1717 /** 1718 * Modifies the Deadband parameter and returns itself. 1719 * <p> 1720 * The allowable deadband of the request, in m/s. 1721 * 1722 * @param newDeadband Parameter to modify 1723 * @return this object 1724 */ 1725 public final FieldCentricFacingAngle withDeadband(LinearVelocity newDeadband) { 1726 this.Deadband = newDeadband.in(MetersPerSecond); 1727 return this; 1728 } 1729 1730 /** 1731 * Modifies the RotationalDeadband parameter and returns itself. 1732 * <p> 1733 * The rotational deadband of the request, in radians per second. 1734 * 1735 * @param newRotationalDeadband Parameter to modify 1736 * @return this object 1737 */ 1738 public final FieldCentricFacingAngle withRotationalDeadband(double newRotationalDeadband) { 1739 this.RotationalDeadband = newRotationalDeadband; 1740 return this; 1741 } 1742 1743 /** 1744 * Modifies the RotationalDeadband parameter and returns itself. 1745 * <p> 1746 * The rotational deadband of the request, in radians per second. 1747 * 1748 * @param newRotationalDeadband Parameter to modify 1749 * @return this object 1750 */ 1751 public final FieldCentricFacingAngle withRotationalDeadband(AngularVelocity newRotationalDeadband) { 1752 this.RotationalDeadband = newRotationalDeadband.in(RadiansPerSecond); 1753 return this; 1754 } 1755 1756 /** 1757 * Modifies the MaxAbsRotationalRate parameter and returns itself. 1758 * <p> 1759 * The maximum absolute rotational rate to allow, in radians per second. 1760 * Setting this to 0 results in no cap to rotational rate. 1761 * 1762 * @param newMaxAbsRotationalRate Parameter to modify 1763 * @return this object 1764 */ 1765 public final FieldCentricFacingAngle withMaxAbsRotationalRate(double newMaxAbsRotationalRate) { 1766 this.MaxAbsRotationalRate = newMaxAbsRotationalRate; 1767 return this; 1768 } 1769 1770 /** 1771 * Modifies the MaxAbsRotationalRate parameter and returns itself. 1772 * <p> 1773 * The maximum absolute rotational rate to allow, in radians per second. 1774 * Setting this to 0 results in no cap to rotational rate. 1775 * 1776 * @param newMaxAbsRotationalRate Parameter to modify 1777 * @return this object 1778 */ 1779 public final FieldCentricFacingAngle withMaxAbsRotationalRate(AngularVelocity newMaxAbsRotationalRate) { 1780 this.MaxAbsRotationalRate = newMaxAbsRotationalRate.in(RadiansPerSecond); 1781 return this; 1782 } 1783 1784 /** 1785 * Modifies the CenterOfRotation parameter and returns itself. 1786 * <p> 1787 * The center of rotation the robot should rotate around. This is (0,0) by 1788 * default, which will rotate around the center of the robot. 1789 * 1790 * @param newCenterOfRotation Parameter to modify 1791 * @return this object 1792 */ 1793 public final FieldCentricFacingAngle withCenterOfRotation(Translation2d newCenterOfRotation) { 1794 this.CenterOfRotation = newCenterOfRotation; 1795 return this; 1796 } 1797 1798 /** 1799 * Modifies the DriveRequestType parameter and returns itself. 1800 * <p> 1801 * The type of control request to use for the drive motor. 1802 * 1803 * @param newDriveRequestType Parameter to modify 1804 * @return this object 1805 */ 1806 public final FieldCentricFacingAngle withDriveRequestType(SwerveModule.DriveRequestType newDriveRequestType) { 1807 this.DriveRequestType = newDriveRequestType; 1808 return this; 1809 } 1810 1811 /** 1812 * Modifies the SteerRequestType parameter and returns itself. 1813 * <p> 1814 * The type of control request to use for the drive motor. 1815 * 1816 * @param newSteerRequestType Parameter to modify 1817 * @return this object 1818 */ 1819 public final FieldCentricFacingAngle withSteerRequestType(SwerveModule.SteerRequestType newSteerRequestType) { 1820 this.SteerRequestType = newSteerRequestType; 1821 return this; 1822 } 1823 1824 /** 1825 * Modifies the DesaturateWheelVelocities parameter and returns itself. 1826 * <p> 1827 * Whether to desaturate wheel velocities before applying. For more information, see 1828 * the documentation of {@link SwerveDriveKinematics#desaturateWheelVelocities}. 1829 * 1830 * @param newDesaturateWheelVelocities Parameter to modify 1831 * @return this object 1832 */ 1833 public final FieldCentricFacingAngle withDesaturateWheelVelocities(boolean newDesaturateWheelVelocities) { 1834 this.DesaturateWheelVelocities = newDesaturateWheelVelocities; 1835 return this; 1836 } 1837 1838 /** 1839 * Modifies the ForwardPerspective parameter and returns itself. 1840 * <p> 1841 * The perspective to use when determining which direction is forward. 1842 * 1843 * @param newForwardPerspective Parameter to modify 1844 * @return this object 1845 */ 1846 public final FieldCentricFacingAngle withForwardPerspective(ForwardPerspectiveValue newForwardPerspective) { 1847 this.ForwardPerspective = newForwardPerspective; 1848 return this; 1849 } 1850 1851 /** 1852 * Modifies the TargetDirectionPerspective parameter and returns itself. 1853 * <p> 1854 * The perspective to use when determining which direction is forward for the 1855 * {@link #TargetDirection}. This allows for the heading control to use a different 1856 * perspective from the translation control. 1857 * 1858 * @param newTargetDirectionPerspective Parameter to modify 1859 * @return this object 1860 */ 1861 public final FieldCentricFacingAngle withTargetDirectionPerspective(TargetDirectionPerspectiveValue newTargetDirectionPerspective) { 1862 this.TargetDirectionPerspective = newTargetDirectionPerspective; 1863 return this; 1864 } 1865 } 1866 1867 /** 1868 * Drives the swerve drivetrain in a robot-centric manner, maintaining a 1869 * specified heading angle to ensure the robot is facing the desired direction 1870 * <p> 1871 * When users use this request, they specify the direction the robot should 1872 * travel oriented against the robot itself, and the direction the robot should 1873 * be facing relative to the field. 1874 * <p> 1875 * An example scenario is that the robot is oriented to the east, the VelocityX 1876 * is +5 m/s, VelocityY is 0 m/s, and TargetDirection is 180 degrees. 1877 * In this scenario, the robot would drive forward at 5 m/s and turn clockwise 1878 * to a target of 180 degrees. 1879 * <p> 1880 * This control request is especially useful for vision control, where the 1881 * robot should be facing a vision target throughout the motion. 1882 */ 1883 public static class RobotCentricFacingAngle implements SwerveRequest { 1884 /** 1885 * The velocity in the X direction, in m/s. 1886 * X is defined as forward according to WPILib convention, 1887 * so this determines how fast to travel forward. 1888 */ 1889 public double VelocityX = 0; 1890 /** 1891 * The velocity in the Y direction, in m/s. 1892 * Y is defined as to the left according to WPILib convention, 1893 * so this determines how fast to travel to the left. 1894 */ 1895 public double VelocityY = 0; 1896 /** 1897 * The desired direction to face. 1898 * 0 Degrees is defined as in the direction of the X axis. 1899 * As a result, a TargetDirection of 90 degrees will point along 1900 * the Y axis, or to the left. 1901 */ 1902 public Rotation2d TargetDirection = new Rotation2d(); 1903 /** 1904 * The rotational rate feedforward to add to the output of the heading 1905 * controller, in radians per second. When using a motion profile for the 1906 * target direction, this can be set to the current velocity reference of 1907 * the profile. 1908 */ 1909 public double TargetRateFeedforward = 0; 1910 1911 /** 1912 * The allowable deadband of the request, in m/s. 1913 */ 1914 public double Deadband = 0; 1915 /** 1916 * The rotational deadband of the request, in radians per second. 1917 */ 1918 public double RotationalDeadband = 0; 1919 /** 1920 * The maximum absolute rotational rate to allow, in radians per second. 1921 * Setting this to 0 results in no cap to rotational rate. 1922 */ 1923 public double MaxAbsRotationalRate = 0; 1924 /** 1925 * The center of rotation the robot should rotate around. 1926 * This is (0,0) by default, which will rotate around the center of the robot. 1927 */ 1928 public Translation2d CenterOfRotation = new Translation2d(); 1929 1930 /** 1931 * The type of control request to use for the drive motor. 1932 */ 1933 public SwerveModule.DriveRequestType DriveRequestType = SwerveModule.DriveRequestType.OpenLoopVoltage; 1934 /** 1935 * The type of control request to use for the steer motor. 1936 */ 1937 public SwerveModule.SteerRequestType SteerRequestType = SwerveModule.SteerRequestType.Position; 1938 /** 1939 * Whether to desaturate wheel velocities before applying. 1940 * For more information, see the documentation of {@link SwerveDriveKinematics#desaturateWheelVelocities}. 1941 */ 1942 public boolean DesaturateWheelVelocities = true; 1943 1944 /** 1945 * The perspective to use when determining which direction is forward 1946 * for the target heading. 1947 */ 1948 public ForwardPerspectiveValue ForwardPerspective = ForwardPerspectiveValue.OperatorPerspective; 1949 1950 /** 1951 * The PID controller used to maintain the desired heading. 1952 * Users can specify the PID gains to change how aggressively to maintain 1953 * heading. 1954 * <p> 1955 * This PID controller operates on heading radians and outputs a target 1956 * rotational rate in radians per second. Note that continuous input should 1957 * be enabled on the range [-pi, pi]. 1958 */ 1959 public PhoenixPIDController HeadingController = new PhoenixPIDController(0, 0, 0); 1960 1961 private final RobotCentric m_robotCentric = new RobotCentric(); 1962 1963 public RobotCentricFacingAngle() { 1964 HeadingController.enableContinuousInput(-Math.PI, Math.PI); 1965 } 1966 1967 public StatusCode apply(SwerveControlParameters parameters, SwerveModule<?, ?, ?>... modulesToApply) { 1968 Rotation2d angleToFace = TargetDirection; 1969 if (ForwardPerspective == ForwardPerspectiveValue.OperatorPerspective) { 1970 /* If we're operator perspective, rotate the direction we want to face by the angle */ 1971 angleToFace = angleToFace.rotateBy(parameters.operatorForwardDirection); 1972 } 1973 1974 double toApplyOmega = TargetRateFeedforward + 1975 HeadingController.calculate( 1976 parameters.currentPose.getRotation().getRadians(), 1977 angleToFace.getRadians(), 1978 parameters.timestamp 1979 ); 1980 if (MaxAbsRotationalRate > 0.0) { 1981 if (toApplyOmega > MaxAbsRotationalRate) { 1982 toApplyOmega = MaxAbsRotationalRate; 1983 } else if (toApplyOmega < -MaxAbsRotationalRate) { 1984 toApplyOmega = -MaxAbsRotationalRate; 1985 } 1986 } 1987 1988 return m_robotCentric 1989 .withVelocityX(VelocityX) 1990 .withVelocityY(VelocityY) 1991 .withRotationalRate(toApplyOmega) 1992 .withDeadband(Deadband) 1993 .withRotationalDeadband(RotationalDeadband) 1994 .withCenterOfRotation(CenterOfRotation) 1995 .withDriveRequestType(DriveRequestType) 1996 .withSteerRequestType(SteerRequestType) 1997 .withDesaturateWheelVelocities(DesaturateWheelVelocities) 1998 .apply(parameters, modulesToApply); 1999 } 2000 2001 /** 2002 * Modifies the PID gains of the HeadingController parameter and returns itself. 2003 * <p> 2004 * Sets the proportional, integral, and differential coefficients used to maintain 2005 * the desired heading. Users can specify the PID gains to change how aggressively to 2006 * maintain heading. 2007 * <p> 2008 * This PID controller operates on heading radians and outputs a target 2009 * rotational rate in radians per second. 2010 * 2011 * @param kP The proportional coefficient; must be >= 0 2012 * @param kI The integral coefficient; must be >= 0 2013 * @param kD The differential coefficient; must be >= 0 2014 * @return this object 2015 */ 2016 public final RobotCentricFacingAngle withHeadingPID(double kP, double kI, double kD) 2017 { 2018 this.HeadingController.setPID(kP, kI, kD); 2019 return this; 2020 } 2021 2022 /** 2023 * Modifies the VelocityX parameter and returns itself. 2024 * <p> 2025 * The velocity in the X direction, in m/s. X is defined as forward according to 2026 * WPILib convention, so this determines how fast to travel forward. 2027 * 2028 * @param newVelocityX Parameter to modify 2029 * @return this object 2030 */ 2031 public final RobotCentricFacingAngle withVelocityX(double newVelocityX) { 2032 this.VelocityX = newVelocityX; 2033 return this; 2034 } 2035 2036 /** 2037 * Modifies the VelocityX parameter and returns itself. 2038 * <p> 2039 * The velocity in the X direction, in m/s. X is defined as forward according to 2040 * WPILib convention, so this determines how fast to travel forward. 2041 * 2042 * @param newVelocityX Parameter to modify 2043 * @return this object 2044 */ 2045 public final RobotCentricFacingAngle withVelocityX(LinearVelocity newVelocityX) { 2046 this.VelocityX = newVelocityX.in(MetersPerSecond); 2047 return this; 2048 } 2049 2050 /** 2051 * Modifies the VelocityY parameter and returns itself. 2052 * <p> 2053 * The velocity in the Y direction, in m/s. Y is defined as to the left 2054 * according to WPILib convention, so this determines how fast to travel to the 2055 * left. 2056 * 2057 * @param newVelocityY Parameter to modify 2058 * @return this object 2059 */ 2060 public final RobotCentricFacingAngle withVelocityY(double newVelocityY) { 2061 this.VelocityY = newVelocityY; 2062 return this; 2063 } 2064 2065 /** 2066 * Modifies the VelocityY parameter and returns itself. 2067 * <p> 2068 * The velocity in the Y direction, in m/s. Y is defined as to the left 2069 * according to WPILib convention, so this determines how fast to travel to the 2070 * left. 2071 * 2072 * @param newVelocityY Parameter to modify 2073 * @return this object 2074 */ 2075 public final RobotCentricFacingAngle withVelocityY(LinearVelocity newVelocityY) { 2076 this.VelocityY = newVelocityY.in(MetersPerSecond); 2077 return this; 2078 } 2079 2080 /** 2081 * Modifies the TargetDirection parameter and returns itself. 2082 * <p> 2083 * The desired direction to face. 0 Degrees is defined as in the direction of 2084 * the X axis. As a result, a TargetDirection of 90 degrees will point along 2085 * the Y axis, or to the left. 2086 * 2087 * @param newTargetDirection Parameter to modify 2088 * @return this object 2089 */ 2090 public final RobotCentricFacingAngle withTargetDirection(Rotation2d newTargetDirection) { 2091 this.TargetDirection = newTargetDirection; 2092 return this; 2093 } 2094 2095 /** 2096 * Modifies the TargetRateFeedforward parameter and returns itself. 2097 * <p> 2098 * The rotational rate feedforward to add to the output of the heading 2099 * controller, in radians per second. When using a motion profile for the 2100 * target direction, this can be set to the current velocity reference of 2101 * the profile. 2102 * 2103 * @param newTargetRateFeedforward Parameter to modify 2104 * @return this object 2105 */ 2106 public final RobotCentricFacingAngle withTargetRateFeedforward(double newTargetRateFeedforward) { 2107 this.TargetRateFeedforward = newTargetRateFeedforward; 2108 return this; 2109 } 2110 /** 2111 * Modifies the TargetRateFeedforward parameter and returns itself. 2112 * <p> 2113 * The rotational rate feedforward to add to the output of the heading 2114 * controller, in radians per second. When using a motion profile for the 2115 * target direction, this can be set to the current velocity reference of 2116 * the profile. 2117 * 2118 * @param newTargetRateFeedforward Parameter to modify 2119 * @return this object 2120 */ 2121 public final RobotCentricFacingAngle withTargetRateFeedforward(AngularVelocity newTargetRateFeedforward) { 2122 this.TargetRateFeedforward = newTargetRateFeedforward.in(RadiansPerSecond); 2123 return this; 2124 } 2125 2126 /** 2127 * Modifies the Deadband parameter and returns itself. 2128 * <p> 2129 * The allowable deadband of the request, in m/s. 2130 * 2131 * @param newDeadband Parameter to modify 2132 * @return this object 2133 */ 2134 public final RobotCentricFacingAngle withDeadband(double newDeadband) { 2135 this.Deadband = newDeadband; 2136 return this; 2137 } 2138 2139 /** 2140 * Modifies the Deadband parameter and returns itself. 2141 * <p> 2142 * The allowable deadband of the request, in m/s. 2143 * 2144 * @param newDeadband Parameter to modify 2145 * @return this object 2146 */ 2147 public final RobotCentricFacingAngle withDeadband(LinearVelocity newDeadband) { 2148 this.Deadband = newDeadband.in(MetersPerSecond); 2149 return this; 2150 } 2151 2152 /** 2153 * Modifies the RotationalDeadband parameter and returns itself. 2154 * <p> 2155 * The rotational deadband of the request, in radians per second. 2156 * 2157 * @param newRotationalDeadband Parameter to modify 2158 * @return this object 2159 */ 2160 public final RobotCentricFacingAngle withRotationalDeadband(double newRotationalDeadband) { 2161 this.RotationalDeadband = newRotationalDeadband; 2162 return this; 2163 } 2164 2165 /** 2166 * Modifies the RotationalDeadband parameter and returns itself. 2167 * <p> 2168 * The rotational deadband of the request, in radians per second. 2169 * 2170 * @param newRotationalDeadband Parameter to modify 2171 * @return this object 2172 */ 2173 public final RobotCentricFacingAngle withRotationalDeadband(AngularVelocity newRotationalDeadband) { 2174 this.RotationalDeadband = newRotationalDeadband.in(RadiansPerSecond); 2175 return this; 2176 } 2177 2178 /** 2179 * Modifies the MaxAbsRotationalRate parameter and returns itself. 2180 * <p> 2181 * The maximum absolute rotational rate to allow, in radians per second. 2182 * Setting this to 0 results in no cap to rotational rate. 2183 * 2184 * @param newMaxAbsRotationalRate Parameter to modify 2185 * @return this object 2186 */ 2187 public final RobotCentricFacingAngle withMaxAbsRotationalRate(double newMaxAbsRotationalRate) { 2188 this.MaxAbsRotationalRate = newMaxAbsRotationalRate; 2189 return this; 2190 } 2191 2192 /** 2193 * Modifies the MaxAbsRotationalRate parameter and returns itself. 2194 * <p> 2195 * The maximum absolute rotational rate to allow, in radians per second. 2196 * Setting this to 0 results in no cap to rotational rate. 2197 * 2198 * @param newMaxAbsRotationalRate Parameter to modify 2199 * @return this object 2200 */ 2201 public final RobotCentricFacingAngle withMaxAbsRotationalRate(AngularVelocity newMaxAbsRotationalRate) { 2202 this.MaxAbsRotationalRate = newMaxAbsRotationalRate.in(RadiansPerSecond); 2203 return this; 2204 } 2205 2206 /** 2207 * Modifies the CenterOfRotation parameter and returns itself. 2208 * <p> 2209 * The center of rotation the robot should rotate around. This is (0,0) by 2210 * default, which will rotate around the center of the robot. 2211 * 2212 * @param newCenterOfRotation Parameter to modify 2213 * @return this object 2214 */ 2215 public final RobotCentricFacingAngle withCenterOfRotation(Translation2d newCenterOfRotation) { 2216 this.CenterOfRotation = newCenterOfRotation; 2217 return this; 2218 } 2219 2220 /** 2221 * Modifies the DriveRequestType parameter and returns itself. 2222 * <p> 2223 * The type of control request to use for the drive motor. 2224 * 2225 * @param newDriveRequestType Parameter to modify 2226 * @return this object 2227 */ 2228 public final RobotCentricFacingAngle withDriveRequestType(SwerveModule.DriveRequestType newDriveRequestType) { 2229 this.DriveRequestType = newDriveRequestType; 2230 return this; 2231 } 2232 2233 /** 2234 * Modifies the SteerRequestType parameter and returns itself. 2235 * <p> 2236 * The type of control request to use for the drive motor. 2237 * 2238 * @param newSteerRequestType Parameter to modify 2239 * @return this object 2240 */ 2241 public final RobotCentricFacingAngle withSteerRequestType(SwerveModule.SteerRequestType newSteerRequestType) { 2242 this.SteerRequestType = newSteerRequestType; 2243 return this; 2244 } 2245 2246 /** 2247 * Modifies the DesaturateWheelVelocities parameter and returns itself. 2248 * <p> 2249 * Whether to desaturate wheel velocities before applying. For more information, see 2250 * the documentation of {@link SwerveDriveKinematics#desaturateWheelVelocities}. 2251 * 2252 * @param newDesaturateWheelVelocities Parameter to modify 2253 * @return this object 2254 */ 2255 public final RobotCentricFacingAngle withDesaturateWheelVelocities(boolean newDesaturateWheelVelocities) { 2256 this.DesaturateWheelVelocities = newDesaturateWheelVelocities; 2257 return this; 2258 } 2259 2260 /** 2261 * Modifies the ForwardPerspective parameter and returns itself. 2262 * <p> 2263 * The perspective to use when determining which direction is forward 2264 * for the target heading. 2265 * 2266 * @param newForwardPerspective Parameter to modify 2267 * @return this object 2268 */ 2269 public final RobotCentricFacingAngle withForwardPerspective(ForwardPerspectiveValue newForwardPerspective) { 2270 this.ForwardPerspective = newForwardPerspective; 2271 return this; 2272 } 2273 } 2274 2275 /** 2276 * SysId-specific SwerveRequest to characterize the translational 2277 * characteristics of a swerve drivetrain. 2278 */ 2279 public static class SysIdSwerveTranslation implements SwerveRequest { 2280 /** 2281 * Voltage to apply to drive wheels. 2282 */ 2283 public double VoltsToApply = 0; 2284 2285 /** Local reference to a voltage request for the drive motors */ 2286 private final VoltageOut m_driveRequest = new VoltageOut(0); 2287 /** Local reference to a position voltage request for the steer motors */ 2288 private final PositionVoltage m_steerRequest_Voltage = new PositionVoltage(0); 2289 /** Local reference to a position torque current request for the steer motors */ 2290 private final PositionTorqueCurrentFOC m_steerRequest_TorqueCurrent = new PositionTorqueCurrentFOC(0); 2291 2292 public StatusCode apply(SwerveControlParameters parameters, SwerveModule<?, ?, ?>... modulesToApply) { 2293 for (int i = 0; i < modulesToApply.length; ++i) { 2294 switch (modulesToApply[i].getSteerClosedLoopOutputType()) { 2295 case Voltage: 2296 modulesToApply[i].apply( 2297 m_driveRequest.withOutput(VoltsToApply), 2298 m_steerRequest_Voltage.withPosition(0) 2299 ); 2300 break; 2301 case TorqueCurrentFOC: 2302 modulesToApply[i].apply( 2303 m_driveRequest.withOutput(VoltsToApply), 2304 m_steerRequest_TorqueCurrent.withPosition(0) 2305 ); 2306 break; 2307 } 2308 } 2309 return StatusCode.OK; 2310 } 2311 2312 /** 2313 * Sets the voltage to apply to the drive wheels. 2314 * 2315 * @param volts Voltage to apply 2316 * @return this request 2317 */ 2318 public final SysIdSwerveTranslation withVolts(double volts) { 2319 VoltsToApply = volts; 2320 return this; 2321 } 2322 /** 2323 * Sets the voltage to apply to the drive wheels. 2324 * 2325 * @param volts Voltage to apply 2326 * @return this request 2327 */ 2328 public final SysIdSwerveTranslation withVolts(Voltage volts) { 2329 VoltsToApply = volts.in(Volts); 2330 return this; 2331 } 2332 } 2333 2334 /** 2335 * SysId-specific SwerveRequest to characterize the rotational 2336 * characteristics of a swerve drivetrain. This is useful to 2337 * characterize the heading controller for FieldCentricFacingAngle. 2338 * <p> 2339 * The RotationalRate of this swerve request should be logged. 2340 * When importing the log to SysId, set the "voltage" to 2341 * RotationalRate, "position" to the Pigeon 2 Yaw, and "velocity" 2342 * to the Pigeon 2 AngularVelocityZWorld. Note that the position 2343 * and velocity will both need to be scaled by pi/180. 2344 * <p> 2345 * Alternatively, the MotorVoltage of one of the drive motors can 2346 * be loaded into the SysId "voltage" field, which can be useful 2347 * when determining the MOI of the robot. 2348 */ 2349 public static class SysIdSwerveRotation implements SwerveRequest { 2350 /** 2351 * The angular rate to rotate at, in radians per second. 2352 */ 2353 public double RotationalRate = 0; 2354 2355 /** Local reference to a voltage request for the drive motors */ 2356 private final VoltageOut m_driveRequest = new VoltageOut(0); 2357 /** Local reference to a position voltage request for the steer motors */ 2358 private final PositionVoltage m_steerRequest_Voltage = new PositionVoltage(0); 2359 /** Local reference to a position torque current request for the steer motors */ 2360 private final PositionTorqueCurrentFOC m_steerRequest_TorqueCurrent = new PositionTorqueCurrentFOC(0); 2361 2362 public StatusCode apply(SwerveControlParameters parameters, SwerveModule<?, ?, ?>... modulesToApply) { 2363 for (int i = 0; i < modulesToApply.length; ++i) { 2364 var velocityMps = RotationalRate * parameters.moduleLocations[i].getNorm(); 2365 var driveVoltage = velocityMps / parameters.kMaxSpeedMps * 12.0; 2366 2367 var angle = parameters.moduleLocations[i].getAngle().orElse(Rotation2d.ZERO).plus(Rotation2d.CCW_90DEG); 2368 2369 switch (modulesToApply[i].getSteerClosedLoopOutputType()) { 2370 case Voltage: 2371 modulesToApply[i].apply( 2372 m_driveRequest.withOutput(driveVoltage), 2373 m_steerRequest_Voltage.withPosition(angle.getRotations()) 2374 ); 2375 break; 2376 case TorqueCurrentFOC: 2377 modulesToApply[i].apply( 2378 m_driveRequest.withOutput(driveVoltage), 2379 m_steerRequest_TorqueCurrent.withPosition(angle.getRotations()) 2380 ); 2381 break; 2382 } 2383 } 2384 return StatusCode.OK; 2385 } 2386 2387 /** 2388 * Update the angular rate to rotate at, in radians per second. 2389 * 2390 * @param newRotationalRate Angular rate to rotate at 2391 * @return this request 2392 */ 2393 public final SysIdSwerveRotation withRotationalRate(double newRotationalRate) { 2394 RotationalRate = newRotationalRate; 2395 return this; 2396 } 2397 /** 2398 * Update the angular rate to rotate at. 2399 * 2400 * @param newRotationalRate The angular rate to rotate at 2401 * @return this request 2402 */ 2403 public final SysIdSwerveRotation withRotationalRate(AngularVelocity newRotationalRate) { 2404 RotationalRate = newRotationalRate.in(RadiansPerSecond); 2405 return this; 2406 } 2407 } 2408 2409 /** 2410 * SysId-specific SwerveRequest to characterize the steer module 2411 * characteristics of a swerve drivetrain. 2412 */ 2413 public static class SysIdSwerveSteerGains implements SwerveRequest { 2414 /** 2415 * Voltage to apply to steer motors. 2416 */ 2417 public double VoltsToApply = 0; 2418 2419 /** Local reference to a coast request for the drive motors */ 2420 private final CoastOut m_driveRequest = new CoastOut(); 2421 /** Local reference to a voltage request for the steer motors */ 2422 private final VoltageOut m_steerRequest = new VoltageOut(0); 2423 2424 public StatusCode apply(SwerveControlParameters parameters, SwerveModule<?, ?, ?>... modulesToApply) { 2425 for (int i = 0; i < modulesToApply.length; ++i) { 2426 modulesToApply[i].apply(m_driveRequest, m_steerRequest.withOutput(VoltsToApply)); 2427 } 2428 return StatusCode.OK; 2429 } 2430 2431 /** 2432 * Sets the voltage to apply to the steer motors. 2433 * 2434 * @param volts Voltage to apply 2435 * @return this request 2436 */ 2437 public final SysIdSwerveSteerGains withVolts(double volts) { 2438 VoltsToApply = volts; 2439 return this; 2440 } 2441 /** 2442 * Sets the voltage to apply to the steer motors. 2443 * 2444 * @param volts Voltage to apply 2445 * @return this request 2446 */ 2447 public final SysIdSwerveSteerGains withVolts(Voltage volts) { 2448 VoltsToApply = volts.in(Volts); 2449 return this; 2450 } 2451 } 2452}