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 java.util.HashMap;
010
011import com.ctre.phoenix6.configs.ClosedLoopGeneralConfigs;
012import com.ctre.phoenix6.configs.CurrentLimitsConfigs;
013import com.ctre.phoenix6.configs.FeedbackConfigs;
014import com.ctre.phoenix6.configs.MagnetSensorConfigs;
015import com.ctre.phoenix6.configs.MotionMagicConfigs;
016import com.ctre.phoenix6.configs.MotorOutputConfigs;
017import com.ctre.phoenix6.configs.ParentConfiguration;
018import com.ctre.phoenix6.configs.Slot0Configs;
019import com.ctre.phoenix6.configs.TorqueCurrentConfigs;
020import com.ctre.phoenix6.signals.ExternalFeedbackSensorSourceValue;
021import com.ctre.phoenix6.signals.FeedbackSensorSourceValue;
022import com.ctre.phoenix6.swerve.jni.SwerveJNI;
023
024import edu.wpi.first.units.measure.*;
025import static edu.wpi.first.units.Units.*;
026
027/**
028 * All constants for a swerve module.
029 */
030public class SwerveModuleConstants<
031    DriveMotorConfigsT extends ParentConfiguration,
032    SteerMotorConfigsT extends ParentConfiguration,
033    EncoderConfigsT extends ParentConfiguration
034> {
035    /**
036     * Supported closed-loop output types.
037     */
038    public enum ClosedLoopOutputType {
039        Voltage(0),
040        /** Requires Pro */
041        TorqueCurrentFOC(1);
042
043        public final int value;
044
045        ClosedLoopOutputType(int initValue) {
046            this.value = initValue;
047        }
048
049        private static HashMap<Integer, ClosedLoopOutputType> _map = null;
050        static {
051            _map = new HashMap<Integer, ClosedLoopOutputType>();
052            for (ClosedLoopOutputType type : ClosedLoopOutputType.values()) {
053                _map.put(type.value, type);
054            }
055        }
056
057        /**
058         * Gets ClosedLoopOutputType from specified value
059         *
060         * @param value Value of ClosedLoopOutputType
061         * @return ClosedLoopOutputType of specified value
062         */
063        public static ClosedLoopOutputType valueOf(int value) {
064            ClosedLoopOutputType retval = _map.get(value);
065            if (retval != null)
066                return retval;
067            return ClosedLoopOutputType.values()[0];
068        }
069    }
070
071    /**
072     * Supported feedback sensors for the steer motors.
073     */
074    public enum SteerFeedbackType {
075        /**
076         * Requires Pro; Use {@link FeedbackSensorSourceValue#FusedCANcoder}
077         * for the steer motor.
078         */
079        FusedCANcoder(0),
080        /**
081         * Requires Pro; Use {@link FeedbackSensorSourceValue#SyncCANcoder}
082         * for the steer motor.
083         */
084        SyncCANcoder(1),
085        /**
086         * Use {@link FeedbackSensorSourceValue#RemoteCANcoder}
087         * for the steer motor.
088         */
089        RemoteCANcoder(2),
090        /**
091         * Requires Pro; Use {@link FeedbackSensorSourceValue#FusedCANdiPWM1}
092         * for the steer motor.
093         */
094        FusedCANdiPWM1(3),
095        /**
096         * Requires Pro; Use {@link FeedbackSensorSourceValue#FusedCANdiPWM2}
097         * for the steer motor.
098         */
099        FusedCANdiPWM2(4),
100        /**
101         * Requires Pro; Use {@link FeedbackSensorSourceValue#SyncCANdiPWM1}
102         * for the steer motor.
103         */
104        SyncCANdiPWM1(5),
105        /**
106         * Requires Pro; Use {@link FeedbackSensorSourceValue#SyncCANdiPWM2}
107         * for the steer motor.
108         */
109        SyncCANdiPWM2(6),
110        /**
111         * Use {@link FeedbackSensorSourceValue#RemoteCANdiPWM1}
112         * for the steer motor.
113         */
114        RemoteCANdiPWM1(7),
115        /**
116         * Use {@link FeedbackSensorSourceValue#RemoteCANdiPWM2}
117         * for the steer motor.
118         */
119        RemoteCANdiPWM2(8),
120        /**
121         * Use {@link ExternalFeedbackSensorSourceValue#PulseWidth}
122         * for the steer motor. This requires Talon FXS.
123         */
124        TalonFXS_PulseWidth(9);
125
126        public final int value;
127
128        SteerFeedbackType(int initValue) {
129            this.value = initValue;
130        }
131
132        private static HashMap<Integer, SteerFeedbackType> _map = null;
133        static {
134            _map = new HashMap<Integer, SteerFeedbackType>();
135            for (SteerFeedbackType type : SteerFeedbackType.values()) {
136                _map.put(type.value, type);
137            }
138        }
139
140        /**
141         * Gets SteerFeedbackType from specified value
142         *
143         * @param value Value of SteerFeedbackType
144         * @return SteerFeedbackType of specified value
145         */
146        public static SteerFeedbackType valueOf(int value) {
147            SteerFeedbackType retval = _map.get(value);
148            if (retval != null)
149                return retval;
150            return SteerFeedbackType.values()[0];
151        }
152    }
153    
154    /**
155     * Supported motor arrangements for the drive motors.
156     */
157    public enum DriveMotorArrangement {
158        /**
159         * Talon FX integrated brushless motor.
160         */
161        TalonFX_Integrated(0),
162        /**
163         * Third party NEO brushless motor connected to a Talon FXS over JST.
164         */
165        TalonFXS_NEO_JST(1),
166        /**
167         * Third party VORTEX brushless motor connected to a Talon FXS over JST.
168         */
169        TalonFXS_VORTEX_JST(2);
170
171        public final int value;
172
173        DriveMotorArrangement(int initValue) {
174            this.value = initValue;
175        }
176
177        private static HashMap<Integer, DriveMotorArrangement> _map = null;
178        static {
179            _map = new HashMap<Integer, DriveMotorArrangement>();
180            for (DriveMotorArrangement type : DriveMotorArrangement.values()) {
181                _map.put(type.value, type);
182            }
183        }
184
185        /**
186         * Gets DriveMotorArrangement from specified value
187         *
188         * @param value Value of DriveMotorArrangement
189         * @return DriveMotorArrangement of specified value
190         */
191        public static DriveMotorArrangement valueOf(int value) {
192            DriveMotorArrangement retval = _map.get(value);
193            if (retval != null)
194                return retval;
195            return DriveMotorArrangement.values()[0];
196        }
197    };
198
199    /**
200     * Supported motor arrangements for the steer motors.
201     */
202    public enum SteerMotorArrangement {
203        /**
204         * Talon FX integrated brushless motor.
205         */
206        TalonFX_Integrated(0),
207        /**
208         * CTR Electronics MinionĀ® brushless motor connected to a Talon FXS over JST.
209         */
210        TalonFXS_Minion_JST(1),
211        /**
212         * Third party NEO brushless motor connected to a Talon FXS over JST.
213         */
214        TalonFXS_NEO_JST(2),
215        /**
216         * Third party VORTEX brushless motor connected to a Talon FXS over JST.
217         */
218        TalonFXS_VORTEX_JST(3),
219        /**
220         * Third party NEO550 brushless motor connected to a Talon FXS over JST.
221         */
222        TalonFXS_NEO550_JST(4),
223        /**
224         * Brushed motor connected to a Talon FXS on terminals A and B.
225         */
226        TalonFXS_Brushed_AB(5),
227        /**
228         * Brushed motor connected to a Talon FXS on terminals A and C.
229         */
230        TalonFXS_Brushed_AC(6),
231        /**
232         * Brushed motor connected to a Talon FXS on terminals B and C.
233         */
234        TalonFXS_Brushed_BC(7);
235
236        public final int value;
237
238        SteerMotorArrangement(int initValue) {
239            this.value = initValue;
240        }
241
242        private static HashMap<Integer, SteerMotorArrangement> _map = null;
243        static {
244            _map = new HashMap<Integer, SteerMotorArrangement>();
245            for (SteerMotorArrangement type : SteerMotorArrangement.values()) {
246                _map.put(type.value, type);
247            }
248        }
249
250        /**
251         * Gets SteerMotorArrangement from specified value
252         *
253         * @param value Value of SteerMotorArrangement
254         * @return SteerMotorArrangement of specified value
255         */
256        public static SteerMotorArrangement valueOf(int value) {
257            SteerMotorArrangement retval = _map.get(value);
258            if (retval != null)
259                return retval;
260            return SteerMotorArrangement.values()[0];
261        }
262    };
263
264    /**
265     * CAN ID of the steer motor.
266     */
267    public int SteerMotorId = 0;
268    /**
269     * CAN ID of the drive motor.
270     */
271    public int DriveMotorId = 0;
272    /**
273     * CAN ID of the absolute encoder used for azimuth.
274     */
275    public int EncoderId = 0;
276    /**
277     * Offset of the azimuth encoder.
278     */
279    public double EncoderOffset = 0;
280    /**
281     * The location of this module's wheels relative to the physical center of the
282     * robot in meters along the X axis of the robot.
283     */
284    public double LocationX = 0;
285    /**
286     * The location of this module's wheels relative to the physical center of the
287     * robot in meters along the Y axis of the robot.
288     */
289    public double LocationY = 0;
290    /**
291     * True if the drive motor is inverted.
292     */
293    public boolean DriveMotorInverted = false;
294    /**
295     * True if the steer motor is inverted from the azimuth. The azimuth should
296     * rotate counter-clockwise (as seen from the top of the robot) for a positive
297     * motor output.
298     */
299    public boolean SteerMotorInverted = false;
300    /**
301     * True if the azimuth encoder is inverted from the azimuth. The encoder should
302     * report a positive velocity when the azimuth rotates counter-clockwise (as
303     * seen from the top of the robot).
304     */
305    public boolean EncoderInverted = false;
306    /**
307     * Gear ratio between the drive motor and the wheel.
308     */
309    public double DriveMotorGearRatio = 0;
310    /**
311     * Gear ratio between the steer motor and the azimuth encoder. For example, the
312     * SDS Mk4 has a steering ratio of 12.8.
313     */
314    public double SteerMotorGearRatio = 0;
315    /**
316     * Coupled gear ratio between the azimuth encoder and the drive motor.
317     * <p>
318     * For a typical swerve module, the azimuth turn motor also drives the wheel a
319     * nontrivial amount, which affects the accuracy of odometry and control. This
320     * ratio represents the number of rotations of the drive motor caused by a
321     * rotation of the azimuth.
322     */
323    public double CouplingGearRatio = 0;
324    /**
325     * Radius of the driving wheel in meters.
326     */
327    public double WheelRadius = 0;
328    /**
329     * The steer motor closed-loop gains.
330     * <p>
331     * The steer motor uses the control ouput type specified by {@link
332     * #SteerMotorClosedLoopOutput} and any {@link SwerveModule.SteerRequestType}.
333     * These gains operate on azimuth rotations (after the gear ratio).
334     */
335    public Slot0Configs SteerMotorGains = new Slot0Configs();
336    /**
337     * The drive motor closed-loop gains.
338     * <p>
339     * When using closed-loop control, the drive motor uses the control output type
340     * specified by {@link #DriveMotorClosedLoopOutput} and any closed-loop {@link
341     * SwerveModule.DriveRequestType}. These gains operate on motor rotor rotations
342     * (before the gear ratio).
343     */
344    public Slot0Configs DriveMotorGains = new Slot0Configs();
345    /**
346     * The closed-loop output type to use for the steer motors.
347     */
348    public ClosedLoopOutputType SteerMotorClosedLoopOutput = ClosedLoopOutputType.Voltage;
349    /**
350     * The closed-loop output type to use for the drive motors.
351     */
352    public ClosedLoopOutputType DriveMotorClosedLoopOutput = ClosedLoopOutputType.Voltage;
353    /**
354     * The maximum amount of stator current the drive motors can apply without
355     * slippage.
356     */
357    public double SlipCurrent = 120;
358    /**
359     * When using open-loop drive control, this specifies the measured speed at
360     * which the robot travels when driven with 12 volts. This is used to
361     * approximate the output for a desired velocity; it cannot be used to change
362     * the desired max speed of the robot. If using closed loop control, this value
363     * is ignored.
364     */
365    public double SpeedAt12Volts = 0;
366    /**
367     * Choose the motor used for the drive motor.
368     * <p>
369     * If using a Talon FX, this should be set to TalonFX_Integrated. If using a
370     * Talon FXS, this should be set to the motor attached to the Talon FXS.
371     */
372    public DriveMotorArrangement DriveMotorType = DriveMotorArrangement.TalonFX_Integrated;
373    /**
374     * Choose the motor used for the steer motor.
375     * <p>
376     * If using a Talon FX, this should be set to TalonFX_Integrated. If using a
377     * Talon FXS, this should be set to the motor attached to the Talon FXS.
378     */
379    public SteerMotorArrangement SteerMotorType = SteerMotorArrangement.TalonFX_Integrated;
380    /**
381     * Choose how the feedback sensors should be configured.
382     * <p>
383     * If the robot does not support Pro, then this should be set to RemoteCANcoder.
384     * Otherwise, users have the option to use either FusedCANcoder or SyncCANcoder
385     * depending on if there is a risk that the CANcoder can fail in a way to
386     * provide "good" data.
387     * <p>
388     * If this is set to FusedCANcoder or SyncCANcoder when the steer motor is not
389     * Pro-licensed, the device will automatically fall back to RemoteCANcoder and
390     * report a UsingProFeatureOnUnlicensedDevice status code.
391     */
392    public SteerFeedbackType FeedbackSource = SteerFeedbackType.FusedCANcoder;
393    /**
394     * The initial configs used to configure the drive motor of the swerve module.
395     * The default value is the factory-default.
396     * <p>
397     * Users may change the initial configuration as they need. Any config that's
398     * not referenced in the {@link SwerveModuleConstants} class is available to be
399     * changed.
400     * <p>
401     * The list of configs that will be overwritten is as follows:
402     * 
403     * <ul>
404     *   <li> {@link MotorOutputConfigs#NeutralMode} (Brake mode, overwritten with
405     *        {@link SwerveDrivetrain#configNeutralMode})
406     *   <li> {@link MotorOutputConfigs#Inverted} ({@link
407     *        SwerveModuleConstants#DriveMotorInverted})
408     *   <li> {@link Slot0Configs} ({@link #DriveMotorGains})
409     *   <li> {@link CurrentLimitsConfigs#StatorCurrentLimit} / {@link
410     *        TorqueCurrentConfigs#PeakForwardTorqueCurrent} / {@link
411     *        TorqueCurrentConfigs#PeakReverseTorqueCurrent} ({@link #SlipCurrent})
412     *   <li> {@link CurrentLimitsConfigs#StatorCurrentLimitEnable} (Enabled)
413     *   <li> {@link FeedbackConfigs#RotorToSensorRatio} / {@link
414     *        FeedbackConfigs#SensorToMechanismRatio} (1.0)
415     * </ul>
416     * 
417     */
418    public DriveMotorConfigsT DriveMotorInitialConfigs = null;
419    /**
420     * The initial configs used to configure the steer motor of the swerve module.
421     * The default value is the factory-default.
422     * <p>
423     * Users may change the initial configuration as they need. Any config that's
424     * not referenced in the {@link SwerveModuleConstants} class is available to be
425     * changed.
426     * <p>
427     * The list of configs that will be overwritten is as follows:
428     * 
429     * <ul>
430     *   <li> {@link MotorOutputConfigs#NeutralMode} (Brake mode)
431     *   <li> {@link MotorOutputConfigs#Inverted} ({@link
432     *        SwerveModuleConstants#SteerMotorInverted})
433     *   <li> {@link Slot0Configs} ({@link #SteerMotorGains})
434     *   <li> {@link FeedbackConfigs#FeedbackRemoteSensorID} ({@link
435     *        SwerveModuleConstants#EncoderId})
436     *   <li> {@link FeedbackConfigs#FeedbackSensorSource} ({@link #FeedbackSource})
437     *   <li> {@link FeedbackConfigs#RotorToSensorRatio} ({@link
438     *        #SteerMotorGearRatio})
439     *   <li> {@link FeedbackConfigs#SensorToMechanismRatio} (1.0)
440     *   <li> {@link MotionMagicConfigs#MotionMagicExpo_kV} / {@link
441     *        MotionMagicConfigs#MotionMagicExpo_kA} (Calculated from gear ratios)
442     *   <li> {@link ClosedLoopGeneralConfigs#ContinuousWrap} (true)
443     * </ul>
444     * 
445     */
446    public SteerMotorConfigsT SteerMotorInitialConfigs = null;
447    /**
448     * The initial configs used to configure the azimuth encoder of the swerve
449     * module. The default value is the factory-default.
450     * <p>
451     * Users may change the initial configuration as they need. Any config that's
452     * not referenced in the {@link SwerveModuleConstants} class is available to be
453     * changed.
454     * <p>
455     * For CANcoder, the list of configs that will be overwritten is as follows:
456     * 
457     * <ul>
458     *   <li> {@link MagnetSensorConfigs#MagnetOffset} ({@link
459     *        SwerveModuleConstants#EncoderOffset})
460     *   <li> {@link MagnetSensorConfigs#SensorDirection} ({@link
461     *        SwerveModuleConstants#EncoderInverted})
462     * </ul>
463     * 
464     */
465    public EncoderConfigsT EncoderInitialConfigs = null;
466    /**
467     * Simulated azimuthal inertia.
468     */
469    public double SteerInertia = 0.01;
470    /**
471     * Simulated drive inertia.
472     */
473    public double DriveInertia = 0.035;
474    /**
475     * Simulated steer voltage required to overcome friction.
476     */
477    public double SteerFrictionVoltage = 0.2;
478    /**
479     * Simulated drive voltage required to overcome friction.
480     */
481    public double DriveFrictionVoltage = 0.2;
482    
483    /**
484     * Modifies the SteerMotorId parameter and returns itself.
485     * <p>
486     * CAN ID of the steer motor.
487     *
488     * @param newSteerMotorId Parameter to modify
489     * @return this object
490     */
491    public SwerveModuleConstants<DriveMotorConfigsT, SteerMotorConfigsT, EncoderConfigsT> withSteerMotorId(int newSteerMotorId) {
492        this.SteerMotorId = newSteerMotorId;
493        return this;
494    }
495    
496    /**
497     * Modifies the DriveMotorId parameter and returns itself.
498     * <p>
499     * CAN ID of the drive motor.
500     *
501     * @param newDriveMotorId Parameter to modify
502     * @return this object
503     */
504    public SwerveModuleConstants<DriveMotorConfigsT, SteerMotorConfigsT, EncoderConfigsT> withDriveMotorId(int newDriveMotorId) {
505        this.DriveMotorId = newDriveMotorId;
506        return this;
507    }
508    
509    /**
510     * Modifies the EncoderId parameter and returns itself.
511     * <p>
512     * CAN ID of the absolute encoder used for azimuth.
513     *
514     * @param newEncoderId Parameter to modify
515     * @return this object
516     */
517    public SwerveModuleConstants<DriveMotorConfigsT, SteerMotorConfigsT, EncoderConfigsT> withEncoderId(int newEncoderId) {
518        this.EncoderId = newEncoderId;
519        return this;
520    }
521    
522    /**
523     * Modifies the EncoderOffset parameter and returns itself.
524     * <p>
525     * Offset of the azimuth encoder.
526     *
527     * @param newEncoderOffset Parameter to modify
528     * @return this object
529     */
530    public SwerveModuleConstants<DriveMotorConfigsT, SteerMotorConfigsT, EncoderConfigsT> withEncoderOffset(double newEncoderOffset) {
531        this.EncoderOffset = newEncoderOffset;
532        return this;
533    }
534    
535    /**
536     * Modifies the EncoderOffset parameter and returns itself.
537     * <p>
538     * Offset of the azimuth encoder.
539     *
540     * @param newEncoderOffset Parameter to modify
541     * @return this object
542     */
543    public SwerveModuleConstants<DriveMotorConfigsT, SteerMotorConfigsT, EncoderConfigsT> withEncoderOffset(Angle newEncoderOffset) {
544        this.EncoderOffset = newEncoderOffset.in(Rotations);
545        return this;
546    }
547    
548    /**
549     * Modifies the LocationX parameter and returns itself.
550     * <p>
551     * The location of this module's wheels relative to the physical center of the
552     * robot in meters along the X axis of the robot.
553     *
554     * @param newLocationX Parameter to modify
555     * @return this object
556     */
557    public SwerveModuleConstants<DriveMotorConfigsT, SteerMotorConfigsT, EncoderConfigsT> withLocationX(double newLocationX) {
558        this.LocationX = newLocationX;
559        return this;
560    }
561    
562    /**
563     * Modifies the LocationX parameter and returns itself.
564     * <p>
565     * The location of this module's wheels relative to the physical center of the
566     * robot in meters along the X axis of the robot.
567     *
568     * @param newLocationX Parameter to modify
569     * @return this object
570     */
571    public SwerveModuleConstants<DriveMotorConfigsT, SteerMotorConfigsT, EncoderConfigsT> withLocationX(Distance newLocationX) {
572        this.LocationX = newLocationX.in(Meters);
573        return this;
574    }
575    
576    /**
577     * Modifies the LocationY parameter and returns itself.
578     * <p>
579     * The location of this module's wheels relative to the physical center of the
580     * robot in meters along the Y axis of the robot.
581     *
582     * @param newLocationY Parameter to modify
583     * @return this object
584     */
585    public SwerveModuleConstants<DriveMotorConfigsT, SteerMotorConfigsT, EncoderConfigsT> withLocationY(double newLocationY) {
586        this.LocationY = newLocationY;
587        return this;
588    }
589    
590    /**
591     * Modifies the LocationY parameter and returns itself.
592     * <p>
593     * The location of this module's wheels relative to the physical center of the
594     * robot in meters along the Y axis of the robot.
595     *
596     * @param newLocationY Parameter to modify
597     * @return this object
598     */
599    public SwerveModuleConstants<DriveMotorConfigsT, SteerMotorConfigsT, EncoderConfigsT> withLocationY(Distance newLocationY) {
600        this.LocationY = newLocationY.in(Meters);
601        return this;
602    }
603    
604    /**
605     * Modifies the DriveMotorInverted parameter and returns itself.
606     * <p>
607     * True if the drive motor is inverted.
608     *
609     * @param newDriveMotorInverted Parameter to modify
610     * @return this object
611     */
612    public SwerveModuleConstants<DriveMotorConfigsT, SteerMotorConfigsT, EncoderConfigsT> withDriveMotorInverted(boolean newDriveMotorInverted) {
613        this.DriveMotorInverted = newDriveMotorInverted;
614        return this;
615    }
616    
617    /**
618     * Modifies the SteerMotorInverted parameter and returns itself.
619     * <p>
620     * True if the steer motor is inverted from the azimuth. The azimuth should
621     * rotate counter-clockwise (as seen from the top of the robot) for a positive
622     * motor output.
623     *
624     * @param newSteerMotorInverted Parameter to modify
625     * @return this object
626     */
627    public SwerveModuleConstants<DriveMotorConfigsT, SteerMotorConfigsT, EncoderConfigsT> withSteerMotorInverted(boolean newSteerMotorInverted) {
628        this.SteerMotorInverted = newSteerMotorInverted;
629        return this;
630    }
631    
632    /**
633     * Modifies the EncoderInverted parameter and returns itself.
634     * <p>
635     * True if the azimuth encoder is inverted from the azimuth. The encoder should
636     * report a positive velocity when the azimuth rotates counter-clockwise (as
637     * seen from the top of the robot).
638     *
639     * @param newEncoderInverted Parameter to modify
640     * @return this object
641     */
642    public SwerveModuleConstants<DriveMotorConfigsT, SteerMotorConfigsT, EncoderConfigsT> withEncoderInverted(boolean newEncoderInverted) {
643        this.EncoderInverted = newEncoderInverted;
644        return this;
645    }
646    
647    /**
648     * Modifies the DriveMotorGearRatio parameter and returns itself.
649     * <p>
650     * Gear ratio between the drive motor and the wheel.
651     *
652     * @param newDriveMotorGearRatio Parameter to modify
653     * @return this object
654     */
655    public SwerveModuleConstants<DriveMotorConfigsT, SteerMotorConfigsT, EncoderConfigsT> withDriveMotorGearRatio(double newDriveMotorGearRatio) {
656        this.DriveMotorGearRatio = newDriveMotorGearRatio;
657        return this;
658    }
659    
660    /**
661     * Modifies the SteerMotorGearRatio parameter and returns itself.
662     * <p>
663     * Gear ratio between the steer motor and the azimuth encoder. For example, the
664     * SDS Mk4 has a steering ratio of 12.8.
665     *
666     * @param newSteerMotorGearRatio Parameter to modify
667     * @return this object
668     */
669    public SwerveModuleConstants<DriveMotorConfigsT, SteerMotorConfigsT, EncoderConfigsT> withSteerMotorGearRatio(double newSteerMotorGearRatio) {
670        this.SteerMotorGearRatio = newSteerMotorGearRatio;
671        return this;
672    }
673    
674    /**
675     * Modifies the CouplingGearRatio parameter and returns itself.
676     * <p>
677     * Coupled gear ratio between the azimuth encoder and the drive motor.
678     * <p>
679     * For a typical swerve module, the azimuth turn motor also drives the wheel a
680     * nontrivial amount, which affects the accuracy of odometry and control. This
681     * ratio represents the number of rotations of the drive motor caused by a
682     * rotation of the azimuth.
683     *
684     * @param newCouplingGearRatio Parameter to modify
685     * @return this object
686     */
687    public SwerveModuleConstants<DriveMotorConfigsT, SteerMotorConfigsT, EncoderConfigsT> withCouplingGearRatio(double newCouplingGearRatio) {
688        this.CouplingGearRatio = newCouplingGearRatio;
689        return this;
690    }
691    
692    /**
693     * Modifies the WheelRadius parameter and returns itself.
694     * <p>
695     * Radius of the driving wheel in meters.
696     *
697     * @param newWheelRadius Parameter to modify
698     * @return this object
699     */
700    public SwerveModuleConstants<DriveMotorConfigsT, SteerMotorConfigsT, EncoderConfigsT> withWheelRadius(double newWheelRadius) {
701        this.WheelRadius = newWheelRadius;
702        return this;
703    }
704    
705    /**
706     * Modifies the WheelRadius parameter and returns itself.
707     * <p>
708     * Radius of the driving wheel in meters.
709     *
710     * @param newWheelRadius Parameter to modify
711     * @return this object
712     */
713    public SwerveModuleConstants<DriveMotorConfigsT, SteerMotorConfigsT, EncoderConfigsT> withWheelRadius(Distance newWheelRadius) {
714        this.WheelRadius = newWheelRadius.in(Meters);
715        return this;
716    }
717    
718    /**
719     * Modifies the SteerMotorGains parameter and returns itself.
720     * <p>
721     * The steer motor closed-loop gains.
722     * <p>
723     * The steer motor uses the control ouput type specified by {@link
724     * #SteerMotorClosedLoopOutput} and any {@link SwerveModule.SteerRequestType}.
725     * These gains operate on azimuth rotations (after the gear ratio).
726     *
727     * @param newSteerMotorGains Parameter to modify
728     * @return this object
729     */
730    public SwerveModuleConstants<DriveMotorConfigsT, SteerMotorConfigsT, EncoderConfigsT> withSteerMotorGains(Slot0Configs newSteerMotorGains) {
731        this.SteerMotorGains = newSteerMotorGains;
732        return this;
733    }
734    
735    /**
736     * Modifies the DriveMotorGains parameter and returns itself.
737     * <p>
738     * The drive motor closed-loop gains.
739     * <p>
740     * When using closed-loop control, the drive motor uses the control output type
741     * specified by {@link #DriveMotorClosedLoopOutput} and any closed-loop {@link
742     * SwerveModule.DriveRequestType}. These gains operate on motor rotor rotations
743     * (before the gear ratio).
744     *
745     * @param newDriveMotorGains Parameter to modify
746     * @return this object
747     */
748    public SwerveModuleConstants<DriveMotorConfigsT, SteerMotorConfigsT, EncoderConfigsT> withDriveMotorGains(Slot0Configs newDriveMotorGains) {
749        this.DriveMotorGains = newDriveMotorGains;
750        return this;
751    }
752    
753    /**
754     * Modifies the SteerMotorClosedLoopOutput parameter and returns itself.
755     * <p>
756     * The closed-loop output type to use for the steer motors.
757     *
758     * @param newSteerMotorClosedLoopOutput Parameter to modify
759     * @return this object
760     */
761    public SwerveModuleConstants<DriveMotorConfigsT, SteerMotorConfigsT, EncoderConfigsT> withSteerMotorClosedLoopOutput(ClosedLoopOutputType newSteerMotorClosedLoopOutput) {
762        this.SteerMotorClosedLoopOutput = newSteerMotorClosedLoopOutput;
763        return this;
764    }
765    
766    /**
767     * Modifies the DriveMotorClosedLoopOutput parameter and returns itself.
768     * <p>
769     * The closed-loop output type to use for the drive motors.
770     *
771     * @param newDriveMotorClosedLoopOutput Parameter to modify
772     * @return this object
773     */
774    public SwerveModuleConstants<DriveMotorConfigsT, SteerMotorConfigsT, EncoderConfigsT> withDriveMotorClosedLoopOutput(ClosedLoopOutputType newDriveMotorClosedLoopOutput) {
775        this.DriveMotorClosedLoopOutput = newDriveMotorClosedLoopOutput;
776        return this;
777    }
778    
779    /**
780     * Modifies the SlipCurrent parameter and returns itself.
781     * <p>
782     * The maximum amount of stator current the drive motors can apply without
783     * slippage.
784     *
785     * @param newSlipCurrent Parameter to modify
786     * @return this object
787     */
788    public SwerveModuleConstants<DriveMotorConfigsT, SteerMotorConfigsT, EncoderConfigsT> withSlipCurrent(double newSlipCurrent) {
789        this.SlipCurrent = newSlipCurrent;
790        return this;
791    }
792    
793    /**
794     * Modifies the SlipCurrent parameter and returns itself.
795     * <p>
796     * The maximum amount of stator current the drive motors can apply without
797     * slippage.
798     *
799     * @param newSlipCurrent Parameter to modify
800     * @return this object
801     */
802    public SwerveModuleConstants<DriveMotorConfigsT, SteerMotorConfigsT, EncoderConfigsT> withSlipCurrent(Current newSlipCurrent) {
803        this.SlipCurrent = newSlipCurrent.in(Amps);
804        return this;
805    }
806    
807    /**
808     * Modifies the SpeedAt12Volts parameter and returns itself.
809     * <p>
810     * When using open-loop drive control, this specifies the measured speed at
811     * which the robot travels when driven with 12 volts. This is used to
812     * approximate the output for a desired velocity; it cannot be used to change
813     * the desired max speed of the robot. If using closed loop control, this value
814     * is ignored.
815     *
816     * @param newSpeedAt12Volts Parameter to modify
817     * @return this object
818     */
819    public SwerveModuleConstants<DriveMotorConfigsT, SteerMotorConfigsT, EncoderConfigsT> withSpeedAt12Volts(double newSpeedAt12Volts) {
820        this.SpeedAt12Volts = newSpeedAt12Volts;
821        return this;
822    }
823    
824    /**
825     * Modifies the SpeedAt12Volts parameter and returns itself.
826     * <p>
827     * When using open-loop drive control, this specifies the measured speed at
828     * which the robot travels when driven with 12 volts. This is used to
829     * approximate the output for a desired velocity; it cannot be used to change
830     * the desired max speed of the robot. If using closed loop control, this value
831     * is ignored.
832     *
833     * @param newSpeedAt12Volts Parameter to modify
834     * @return this object
835     */
836    public SwerveModuleConstants<DriveMotorConfigsT, SteerMotorConfigsT, EncoderConfigsT> withSpeedAt12Volts(LinearVelocity newSpeedAt12Volts) {
837        this.SpeedAt12Volts = newSpeedAt12Volts.in(MetersPerSecond);
838        return this;
839    }
840    
841    /**
842     * Modifies the DriveMotorType parameter and returns itself.
843     * <p>
844     * Choose the motor used for the drive motor.
845     * <p>
846     * If using a Talon FX, this should be set to TalonFX_Integrated. If using a
847     * Talon FXS, this should be set to the motor attached to the Talon FXS.
848     *
849     * @param newDriveMotorType Parameter to modify
850     * @return this object
851     */
852    public SwerveModuleConstants<DriveMotorConfigsT, SteerMotorConfigsT, EncoderConfigsT> withDriveMotorType(DriveMotorArrangement newDriveMotorType) {
853        this.DriveMotorType = newDriveMotorType;
854        return this;
855    }
856    
857    /**
858     * Modifies the SteerMotorType parameter and returns itself.
859     * <p>
860     * Choose the motor used for the steer motor.
861     * <p>
862     * If using a Talon FX, this should be set to TalonFX_Integrated. If using a
863     * Talon FXS, this should be set to the motor attached to the Talon FXS.
864     *
865     * @param newSteerMotorType Parameter to modify
866     * @return this object
867     */
868    public SwerveModuleConstants<DriveMotorConfigsT, SteerMotorConfigsT, EncoderConfigsT> withSteerMotorType(SteerMotorArrangement newSteerMotorType) {
869        this.SteerMotorType = newSteerMotorType;
870        return this;
871    }
872    
873    /**
874     * Modifies the FeedbackSource parameter and returns itself.
875     * <p>
876     * Choose how the feedback sensors should be configured.
877     * <p>
878     * If the robot does not support Pro, then this should be set to RemoteCANcoder.
879     * Otherwise, users have the option to use either FusedCANcoder or SyncCANcoder
880     * depending on if there is a risk that the CANcoder can fail in a way to
881     * provide "good" data.
882     * <p>
883     * If this is set to FusedCANcoder or SyncCANcoder when the steer motor is not
884     * Pro-licensed, the device will automatically fall back to RemoteCANcoder and
885     * report a UsingProFeatureOnUnlicensedDevice status code.
886     *
887     * @param newFeedbackSource Parameter to modify
888     * @return this object
889     */
890    public SwerveModuleConstants<DriveMotorConfigsT, SteerMotorConfigsT, EncoderConfigsT> withFeedbackSource(SteerFeedbackType newFeedbackSource) {
891        this.FeedbackSource = newFeedbackSource;
892        return this;
893    }
894    
895    /**
896     * Modifies the DriveMotorInitialConfigs parameter and returns itself.
897     * <p>
898     * The initial configs used to configure the drive motor of the swerve module.
899     * The default value is the factory-default.
900     * <p>
901     * Users may change the initial configuration as they need. Any config that's
902     * not referenced in the {@link SwerveModuleConstants} class is available to be
903     * changed.
904     * <p>
905     * The list of configs that will be overwritten is as follows:
906     * 
907     * <ul>
908     *   <li> {@link MotorOutputConfigs#NeutralMode} (Brake mode, overwritten with
909     *        {@link SwerveDrivetrain#configNeutralMode})
910     *   <li> {@link MotorOutputConfigs#Inverted} ({@link
911     *        SwerveModuleConstants#DriveMotorInverted})
912     *   <li> {@link Slot0Configs} ({@link #DriveMotorGains})
913     *   <li> {@link CurrentLimitsConfigs#StatorCurrentLimit} / {@link
914     *        TorqueCurrentConfigs#PeakForwardTorqueCurrent} / {@link
915     *        TorqueCurrentConfigs#PeakReverseTorqueCurrent} ({@link #SlipCurrent})
916     *   <li> {@link CurrentLimitsConfigs#StatorCurrentLimitEnable} (Enabled)
917     *   <li> {@link FeedbackConfigs#RotorToSensorRatio} / {@link
918     *        FeedbackConfigs#SensorToMechanismRatio} (1.0)
919     * </ul>
920     * 
921     *
922     * @param newDriveMotorInitialConfigs Parameter to modify
923     * @return this object
924     */
925    public SwerveModuleConstants<DriveMotorConfigsT, SteerMotorConfigsT, EncoderConfigsT> withDriveMotorInitialConfigs(DriveMotorConfigsT newDriveMotorInitialConfigs) {
926        this.DriveMotorInitialConfigs = newDriveMotorInitialConfigs;
927        return this;
928    }
929    
930    /**
931     * Modifies the SteerMotorInitialConfigs parameter and returns itself.
932     * <p>
933     * The initial configs used to configure the steer motor of the swerve module.
934     * The default value is the factory-default.
935     * <p>
936     * Users may change the initial configuration as they need. Any config that's
937     * not referenced in the {@link SwerveModuleConstants} class is available to be
938     * changed.
939     * <p>
940     * The list of configs that will be overwritten is as follows:
941     * 
942     * <ul>
943     *   <li> {@link MotorOutputConfigs#NeutralMode} (Brake mode)
944     *   <li> {@link MotorOutputConfigs#Inverted} ({@link
945     *        SwerveModuleConstants#SteerMotorInverted})
946     *   <li> {@link Slot0Configs} ({@link #SteerMotorGains})
947     *   <li> {@link FeedbackConfigs#FeedbackRemoteSensorID} ({@link
948     *        SwerveModuleConstants#EncoderId})
949     *   <li> {@link FeedbackConfigs#FeedbackSensorSource} ({@link #FeedbackSource})
950     *   <li> {@link FeedbackConfigs#RotorToSensorRatio} ({@link
951     *        #SteerMotorGearRatio})
952     *   <li> {@link FeedbackConfigs#SensorToMechanismRatio} (1.0)
953     *   <li> {@link MotionMagicConfigs#MotionMagicExpo_kV} / {@link
954     *        MotionMagicConfigs#MotionMagicExpo_kA} (Calculated from gear ratios)
955     *   <li> {@link ClosedLoopGeneralConfigs#ContinuousWrap} (true)
956     * </ul>
957     * 
958     *
959     * @param newSteerMotorInitialConfigs Parameter to modify
960     * @return this object
961     */
962    public SwerveModuleConstants<DriveMotorConfigsT, SteerMotorConfigsT, EncoderConfigsT> withSteerMotorInitialConfigs(SteerMotorConfigsT newSteerMotorInitialConfigs) {
963        this.SteerMotorInitialConfigs = newSteerMotorInitialConfigs;
964        return this;
965    }
966    
967    /**
968     * Modifies the EncoderInitialConfigs parameter and returns itself.
969     * <p>
970     * The initial configs used to configure the azimuth encoder of the swerve
971     * module. The default value is the factory-default.
972     * <p>
973     * Users may change the initial configuration as they need. Any config that's
974     * not referenced in the {@link SwerveModuleConstants} class is available to be
975     * changed.
976     * <p>
977     * For CANcoder, the list of configs that will be overwritten is as follows:
978     * 
979     * <ul>
980     *   <li> {@link MagnetSensorConfigs#MagnetOffset} ({@link
981     *        SwerveModuleConstants#EncoderOffset})
982     *   <li> {@link MagnetSensorConfigs#SensorDirection} ({@link
983     *        SwerveModuleConstants#EncoderInverted})
984     * </ul>
985     * 
986     *
987     * @param newEncoderInitialConfigs Parameter to modify
988     * @return this object
989     */
990    public SwerveModuleConstants<DriveMotorConfigsT, SteerMotorConfigsT, EncoderConfigsT> withEncoderInitialConfigs(EncoderConfigsT newEncoderInitialConfigs) {
991        this.EncoderInitialConfigs = newEncoderInitialConfigs;
992        return this;
993    }
994    
995    /**
996     * Modifies the SteerInertia parameter and returns itself.
997     * <p>
998     * Simulated azimuthal inertia.
999     *
1000     * @param newSteerInertia Parameter to modify
1001     * @return this object
1002     */
1003    public SwerveModuleConstants<DriveMotorConfigsT, SteerMotorConfigsT, EncoderConfigsT> withSteerInertia(double newSteerInertia) {
1004        this.SteerInertia = newSteerInertia;
1005        return this;
1006    }
1007    
1008    /**
1009     * Modifies the SteerInertia parameter and returns itself.
1010     * <p>
1011     * Simulated azimuthal inertia.
1012     *
1013     * @param newSteerInertia Parameter to modify
1014     * @return this object
1015     */
1016    public SwerveModuleConstants<DriveMotorConfigsT, SteerMotorConfigsT, EncoderConfigsT> withSteerInertia(MomentOfInertia newSteerInertia) {
1017        this.SteerInertia = newSteerInertia.in(KilogramSquareMeters);
1018        return this;
1019    }
1020    
1021    /**
1022     * Modifies the DriveInertia parameter and returns itself.
1023     * <p>
1024     * Simulated drive inertia.
1025     *
1026     * @param newDriveInertia Parameter to modify
1027     * @return this object
1028     */
1029    public SwerveModuleConstants<DriveMotorConfigsT, SteerMotorConfigsT, EncoderConfigsT> withDriveInertia(double newDriveInertia) {
1030        this.DriveInertia = newDriveInertia;
1031        return this;
1032    }
1033    
1034    /**
1035     * Modifies the DriveInertia parameter and returns itself.
1036     * <p>
1037     * Simulated drive inertia.
1038     *
1039     * @param newDriveInertia Parameter to modify
1040     * @return this object
1041     */
1042    public SwerveModuleConstants<DriveMotorConfigsT, SteerMotorConfigsT, EncoderConfigsT> withDriveInertia(MomentOfInertia newDriveInertia) {
1043        this.DriveInertia = newDriveInertia.in(KilogramSquareMeters);
1044        return this;
1045    }
1046    
1047    /**
1048     * Modifies the SteerFrictionVoltage parameter and returns itself.
1049     * <p>
1050     * Simulated steer voltage required to overcome friction.
1051     *
1052     * @param newSteerFrictionVoltage Parameter to modify
1053     * @return this object
1054     */
1055    public SwerveModuleConstants<DriveMotorConfigsT, SteerMotorConfigsT, EncoderConfigsT> withSteerFrictionVoltage(double newSteerFrictionVoltage) {
1056        this.SteerFrictionVoltage = newSteerFrictionVoltage;
1057        return this;
1058    }
1059    
1060    /**
1061     * Modifies the SteerFrictionVoltage parameter and returns itself.
1062     * <p>
1063     * Simulated steer voltage required to overcome friction.
1064     *
1065     * @param newSteerFrictionVoltage Parameter to modify
1066     * @return this object
1067     */
1068    public SwerveModuleConstants<DriveMotorConfigsT, SteerMotorConfigsT, EncoderConfigsT> withSteerFrictionVoltage(Voltage newSteerFrictionVoltage) {
1069        this.SteerFrictionVoltage = newSteerFrictionVoltage.in(Volts);
1070        return this;
1071    }
1072    
1073    /**
1074     * Modifies the DriveFrictionVoltage parameter and returns itself.
1075     * <p>
1076     * Simulated drive voltage required to overcome friction.
1077     *
1078     * @param newDriveFrictionVoltage Parameter to modify
1079     * @return this object
1080     */
1081    public SwerveModuleConstants<DriveMotorConfigsT, SteerMotorConfigsT, EncoderConfigsT> withDriveFrictionVoltage(double newDriveFrictionVoltage) {
1082        this.DriveFrictionVoltage = newDriveFrictionVoltage;
1083        return this;
1084    }
1085    
1086    /**
1087     * Modifies the DriveFrictionVoltage parameter and returns itself.
1088     * <p>
1089     * Simulated drive voltage required to overcome friction.
1090     *
1091     * @param newDriveFrictionVoltage Parameter to modify
1092     * @return this object
1093     */
1094    public SwerveModuleConstants<DriveMotorConfigsT, SteerMotorConfigsT, EncoderConfigsT> withDriveFrictionVoltage(Voltage newDriveFrictionVoltage) {
1095        this.DriveFrictionVoltage = newDriveFrictionVoltage.in(Volts);
1096        return this;
1097    }
1098    
1099    static long createNativeInstance(SwerveModuleConstants<?, ?, ?>[] constantsArr) {
1100        final long retval = SwerveJNI.JNI_CreateModuleConstantsArr(constantsArr.length);
1101        for (int i = 0; i < constantsArr.length; ++i) {
1102            final var constants = constantsArr[i];
1103            SwerveJNI.JNI_SetModuleConstants(
1104                retval, i,
1105                constants.SteerMotorId,
1106                constants.DriveMotorId,
1107                constants.EncoderId,
1108                constants.EncoderOffset,
1109                constants.LocationX,
1110                constants.LocationY,
1111                constants.DriveMotorInverted,
1112                constants.SteerMotorInverted,
1113                constants.EncoderInverted,
1114                constants.DriveMotorGearRatio,
1115                constants.SteerMotorGearRatio,
1116                constants.CouplingGearRatio,
1117                constants.WheelRadius,
1118                constants.SteerMotorClosedLoopOutput.value,
1119                constants.DriveMotorClosedLoopOutput.value,
1120                constants.SlipCurrent,
1121                constants.SpeedAt12Volts,
1122                constants.DriveMotorType.value,
1123                constants.SteerMotorType.value,
1124                constants.FeedbackSource.value,
1125                constants.SteerInertia,
1126                constants.DriveInertia,
1127                constants.SteerFrictionVoltage,
1128                constants.DriveFrictionVoltage
1129            );
1130        }
1131        return retval;
1132    }
1133}