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.controls;
008
009import com.ctre.phoenix6.CANBus;
010import com.ctre.phoenix6.StatusCode;
011import com.ctre.phoenix6.controls.jni.ControlJNI;
012import com.ctre.phoenix6.hardware.traits.*;
013
014import edu.wpi.first.units.*;
015import edu.wpi.first.units.measure.*;
016import static edu.wpi.first.units.Units.*;
017
018import java.util.HashMap;
019import java.util.Map;
020
021/**
022 * Requires Phoenix Pro and CANivore;
023 * Requests Motion Magic® Expo to target a final position using an exponential
024 * motion profile.  This dynamic request allows runtime changes to the profile
025 * kV, kA, and (optional) Cruise Velocity.  Users can optionally provide a duty
026 * cycle feedforward.
027 * <p>
028 * Motion Magic® Expo produces a motion profile in real-time while attempting to honor the specified Cruise
029 * Velocity (optional) and the mechanism kV and kA.  Note that unlike the slot gains, the Expo_kV and Expo_kA
030 * parameters are always in output units of Volts.
031 * <p>
032 * Setting the Cruise Velocity to 0 will allow the profile to run to the max possible velocity based on
033 * Expo_kV.  This control mode does not use the Acceleration or Jerk configs.
034 * <p>
035 * Target position can be changed on-the-fly and Motion Magic® will do its best to adjust the profile. This
036 * control mode is duty cycle based, so relevant closed-loop gains will use fractional duty cycle for the
037 * numerator:  +1.0 represents full forward output.
038 */
039public final class DynamicMotionMagicExpoDutyCycle implements ControlRequest, Cloneable {
040    /**
041     * Position to drive toward in rotations.
042     * 
043     * <ul>
044     *   <li> Units: rotations
045     * </ul>
046     * 
047     */
048    public double Position;
049    /**
050     * Mechanism kV for profiling.  Unlike the kV slot gain, this is always in units
051     * of V/rps.
052     * <p>
053     * This represents the amount of voltage necessary to hold a velocity.  In terms
054     * of the Motion Magic® Expo profile, a higher kV results in a slower maximum
055     * velocity.
056     * 
057     * <ul>
058     *   <li> Units: V/rps
059     * </ul>
060     * 
061     */
062    public double kV;
063    /**
064     * Mechanism kA for profiling.  Unlike the kA slot gain, this is always in units
065     * of V/rps².
066     * <p>
067     * This represents the amount of voltage necessary to achieve an acceleration. 
068     * In terms of the Motion Magic® Expo profile, a higher kA results in a slower
069     * acceleration.
070     * 
071     * <ul>
072     *   <li> Units: V/rps²
073     * </ul>
074     * 
075     */
076    public double kA;
077    /**
078     * Cruise velocity for profiling.  The signage does not matter as the device
079     * will use the absolute value for profile generation.  Setting this to 0 will
080     * allow the profile to run to the max possible velocity based on Expo_kV.
081     * 
082     * <ul>
083     *   <li> Units: rotations per second
084     * </ul>
085     * 
086     */
087    public double Velocity = 0;
088    /**
089     * Set to true to use FOC commutation (requires Phoenix Pro), which increases
090     * peak power by ~15% on supported devices (see {@link SupportsFOC}). Set to
091     * false to use trapezoidal commutation.
092     * <p>
093     * FOC improves motor performance by leveraging torque (current) control. 
094     * However, this may be inconvenient for applications that require specifying
095     * duty cycle or voltage.  CTR-Electronics has developed a hybrid method that
096     * combines the performances gains of FOC while still allowing applications to
097     * provide duty cycle or voltage demand.  This not to be confused with simple
098     * sinusoidal control or phase voltage control which lacks the performance
099     * gains.
100     */
101    public boolean EnableFOC = true;
102    /**
103     * Feedforward to apply in fractional units between -1 and +1. This is added to
104     * the output of the onboard feedforward terms.
105     * 
106     * <ul>
107     *   <li> Units: fractional
108     * </ul>
109     * 
110     */
111    public double FeedForward = 0.0;
112    /**
113     * Select which gains are applied by selecting the slot.  Use the configuration
114     * api to set the gain values for the selected slot before enabling this
115     * feature. Slot must be within [0,2].
116     */
117    public int Slot = 0;
118    /**
119     * Set to true to static-brake the rotor when output is zero (or within
120     * deadband).  Set to false to use the NeutralMode configuration setting
121     * (default). This flag exists to provide the fundamental behavior of this
122     * control when output is zero, which is to provide 0V to the motor.
123     */
124    public boolean OverrideBrakeDurNeutral = false;
125    /**
126     * Set to true to force forward limiting.  This allows users to use other limit
127     * switch sensors connected to robot controller.  This also allows use of active
128     * sensors that require external power.
129     */
130    public boolean LimitForwardMotion = false;
131    /**
132     * Set to true to force reverse limiting.  This allows users to use other limit
133     * switch sensors connected to robot controller.  This also allows use of active
134     * sensors that require external power.
135     */
136    public boolean LimitReverseMotion = false;
137    /**
138     * Set to true to ignore hardware limit switches and the LimitForwardMotion and
139     * LimitReverseMotion parameters, instead allowing motion.
140     * <p>
141     * This can be useful on mechanisms such as an intake/feeder, where a limit
142     * switch stops motion while intaking but should be ignored when feeding to a
143     * shooter.
144     * <p>
145     * The hardware limit faults and Forward/ReverseLimit signals will still report
146     * the values of the limit switches regardless of this parameter.
147     */
148    public boolean IgnoreHardwareLimits = false;
149    /**
150     * Set to true to ignore software limits, instead allowing motion.
151     * <p>
152     * This can be useful when calibrating the zero point of a mechanism such as an
153     * elevator.
154     * <p>
155     * The software limit faults will still report the values of the software limits
156     * regardless of this parameter.
157     */
158    public boolean IgnoreSoftwareLimits = false;
159    /**
160     * Set to true to delay applying this control request until a timesync boundary
161     * (requires Phoenix Pro and CANivore). This eliminates the impact of
162     * nondeterministic network delays in exchange for a larger but deterministic
163     * control latency.
164     * <p>
165     * This requires setting the ControlTimesyncFreqHz config in MotorOutputConfigs.
166     * Additionally, when this is enabled, the UpdateFreqHz of this request should
167     * be set to 0 Hz.
168     */
169    public boolean UseTimesync = false;
170
171    /**
172     * The frequency at which this control will update.
173     * This is designated in Hertz, with a minimum of 20 Hz
174     * (every 50 ms) and a maximum of 1000 Hz (every 1 ms).
175     * Some update frequencies are not supported and will be
176     * promoted up to the next highest supported frequency.
177     * <p>
178     * If this field is set to 0 Hz, the control request will
179     * be sent immediately as a one-shot frame. This may be useful
180     * for advanced applications that require outputs to be
181     * synchronized with data acquisition. In this case, we
182     * recommend not exceeding 50 ms between control calls.
183     */
184    public double UpdateFreqHz = 100;
185
186    /**
187     * Requires Phoenix Pro and CANivore;
188     * Requests Motion Magic® Expo to target a final position using an exponential
189     * motion profile.  This dynamic request allows runtime changes to the profile
190     * kV, kA, and (optional) Cruise Velocity.  Users can optionally provide a duty
191     * cycle feedforward.
192     * <p>
193     * Motion Magic® Expo produces a motion profile in real-time while attempting to
194     * honor the specified Cruise Velocity (optional) and the mechanism kV and kA. 
195     * Note that unlike the slot gains, the Expo_kV and Expo_kA parameters are
196     * always in output units of Volts.
197     * <p>
198     * Setting the Cruise Velocity to 0 will allow the profile to run to the max
199     * possible velocity based on Expo_kV.  This control mode does not use the
200     * Acceleration or Jerk configs.
201     * <p>
202     * Target position can be changed on-the-fly and Motion Magic® will do its best
203     * to adjust the profile. This control mode is duty cycle based, so relevant
204     * closed-loop gains will use fractional duty cycle for the numerator:  +1.0
205     * represents full forward output.
206     * 
207     * @param Position Position to drive toward in rotations.
208     * @param kV Mechanism kV for profiling.  Unlike the kV slot gain, this is
209     *           always in units of V/rps.
210     *           <p>
211     *           This represents the amount of voltage necessary to hold a velocity.
212     *            In terms of the Motion Magic® Expo profile, a higher kV results in
213     *           a slower maximum velocity.
214     * @param kA Mechanism kA for profiling.  Unlike the kA slot gain, this is
215     *           always in units of V/rps².
216     *           <p>
217     *           This represents the amount of voltage necessary to achieve an
218     *           acceleration.  In terms of the Motion Magic® Expo profile, a higher
219     *           kA results in a slower acceleration.
220     */
221    public DynamicMotionMagicExpoDutyCycle(double Position, double kV, double kA) {
222        this.Position = Position;
223        this.kV = kV;
224        this.kA = kA;
225    }
226
227    /**
228     * Requires Phoenix Pro and CANivore;
229     * Requests Motion Magic® Expo to target a final position using an exponential
230     * motion profile.  This dynamic request allows runtime changes to the profile
231     * kV, kA, and (optional) Cruise Velocity.  Users can optionally provide a duty
232     * cycle feedforward.
233     * <p>
234     * Motion Magic® Expo produces a motion profile in real-time while attempting to
235     * honor the specified Cruise Velocity (optional) and the mechanism kV and kA. 
236     * Note that unlike the slot gains, the Expo_kV and Expo_kA parameters are
237     * always in output units of Volts.
238     * <p>
239     * Setting the Cruise Velocity to 0 will allow the profile to run to the max
240     * possible velocity based on Expo_kV.  This control mode does not use the
241     * Acceleration or Jerk configs.
242     * <p>
243     * Target position can be changed on-the-fly and Motion Magic® will do its best
244     * to adjust the profile. This control mode is duty cycle based, so relevant
245     * closed-loop gains will use fractional duty cycle for the numerator:  +1.0
246     * represents full forward output.
247     * 
248     * @param Position Position to drive toward in rotations.
249     * @param kV Mechanism kV for profiling.  Unlike the kV slot gain, this is
250     *           always in units of V/rps.
251     *           <p>
252     *           This represents the amount of voltage necessary to hold a velocity.
253     *            In terms of the Motion Magic® Expo profile, a higher kV results in
254     *           a slower maximum velocity.
255     * @param kA Mechanism kA for profiling.  Unlike the kA slot gain, this is
256     *           always in units of V/rps².
257     *           <p>
258     *           This represents the amount of voltage necessary to achieve an
259     *           acceleration.  In terms of the Motion Magic® Expo profile, a higher
260     *           kA results in a slower acceleration.
261     */
262    public DynamicMotionMagicExpoDutyCycle(Angle Position, Per<VoltageUnit, AngularVelocityUnit> kV, Per<VoltageUnit, AngularAccelerationUnit> kA) {
263        this(Position.in(Rotations), kV.in(Volts.per(RotationsPerSecond)), kA.in(Volts.per(RotationsPerSecondPerSecond)));
264    }
265
266    @Override
267    public String getName() {
268        return "DynamicMotionMagicExpoDutyCycle";
269    }
270
271    @Override
272    public String toString() {
273        String ss = "Control: DynamicMotionMagicExpoDutyCycle\n";
274        ss += "    Position: " + Position + " rotations" + "\n";
275        ss += "    kV: " + kV + " V/rps" + "\n";
276        ss += "    kA: " + kA + " V/rps²" + "\n";
277        ss += "    Velocity: " + Velocity + " rotations per second" + "\n";
278        ss += "    EnableFOC: " + EnableFOC + "\n";
279        ss += "    FeedForward: " + FeedForward + " fractional" + "\n";
280        ss += "    Slot: " + Slot + "\n";
281        ss += "    OverrideBrakeDurNeutral: " + OverrideBrakeDurNeutral + "\n";
282        ss += "    LimitForwardMotion: " + LimitForwardMotion + "\n";
283        ss += "    LimitReverseMotion: " + LimitReverseMotion + "\n";
284        ss += "    IgnoreHardwareLimits: " + IgnoreHardwareLimits + "\n";
285        ss += "    IgnoreSoftwareLimits: " + IgnoreSoftwareLimits + "\n";
286        ss += "    UseTimesync: " + UseTimesync + "\n";
287        return ss;
288    }
289
290    @Override
291    public StatusCode sendRequest(CANBus network, int deviceHash) {
292        return StatusCode.valueOf(ControlJNI.JNI_RequestControlDynamicMotionMagicExpoDutyCycle(
293                network.getNameUTF8Bytes(), deviceHash, UpdateFreqHz, Position, kV, kA, Velocity, EnableFOC, FeedForward, Slot, OverrideBrakeDurNeutral, LimitForwardMotion, LimitReverseMotion, IgnoreHardwareLimits, IgnoreSoftwareLimits, UseTimesync));
294    }
295
296    /**
297     * Gets information about this control request.
298     *
299     * @return Map of control parameter names and corresponding applied values
300     */
301    @Override
302    public Map<String, String> getControlInfo() {
303        var controlInfo = new HashMap<String, String>();
304        controlInfo.put("Name", getName());
305        controlInfo.put("Position", String.valueOf(this.Position));
306        controlInfo.put("kV", String.valueOf(this.kV));
307        controlInfo.put("kA", String.valueOf(this.kA));
308        controlInfo.put("Velocity", String.valueOf(this.Velocity));
309        controlInfo.put("EnableFOC", String.valueOf(this.EnableFOC));
310        controlInfo.put("FeedForward", String.valueOf(this.FeedForward));
311        controlInfo.put("Slot", String.valueOf(this.Slot));
312        controlInfo.put("OverrideBrakeDurNeutral", String.valueOf(this.OverrideBrakeDurNeutral));
313        controlInfo.put("LimitForwardMotion", String.valueOf(this.LimitForwardMotion));
314        controlInfo.put("LimitReverseMotion", String.valueOf(this.LimitReverseMotion));
315        controlInfo.put("IgnoreHardwareLimits", String.valueOf(this.IgnoreHardwareLimits));
316        controlInfo.put("IgnoreSoftwareLimits", String.valueOf(this.IgnoreSoftwareLimits));
317        controlInfo.put("UseTimesync", String.valueOf(this.UseTimesync));
318        return controlInfo;
319    }
320    
321    /**
322     * Modifies this Control Request's Position parameter and returns itself for
323     * method-chaining and easier to use request API.
324     * <p>
325     * Position to drive toward in rotations.
326     * 
327     * <ul>
328     *   <li> Units: rotations
329     * </ul>
330     * 
331     *
332     * @param newPosition Parameter to modify
333     * @return Itself
334     */
335    public DynamicMotionMagicExpoDutyCycle withPosition(double newPosition) {
336        Position = newPosition;
337        return this;
338    }
339    
340    /**
341     * Modifies this Control Request's Position parameter and returns itself for
342     * method-chaining and easier to use request API.
343     * <p>
344     * Position to drive toward in rotations.
345     * 
346     * <ul>
347     *   <li> Units: rotations
348     * </ul>
349     * 
350     *
351     * @param newPosition Parameter to modify
352     * @return Itself
353     */
354    public DynamicMotionMagicExpoDutyCycle withPosition(Angle newPosition) {
355        Position = newPosition.in(Rotations);
356        return this;
357    }
358    
359    /**
360     * Helper method to get this Control Request's Position parameter converted
361     * to a unit type. If not using the Java units library, {@link #Position}
362     * can be accessed directly instead.
363     * <p>
364     * Position to drive toward in rotations.
365     * 
366     * <ul>
367     *   <li> Units: rotations
368     * </ul>
369     * 
370     *
371     * @return Position
372     */
373    public Angle getPositionMeasure() {
374        return Rotations.of(Position);
375    }
376    
377    /**
378     * Modifies this Control Request's kV parameter and returns itself for
379     * method-chaining and easier to use request API.
380     * <p>
381     * Mechanism kV for profiling.  Unlike the kV slot gain, this is always in units
382     * of V/rps.
383     * <p>
384     * This represents the amount of voltage necessary to hold a velocity.  In terms
385     * of the Motion Magic® Expo profile, a higher kV results in a slower maximum
386     * velocity.
387     * 
388     * <ul>
389     *   <li> Units: V/rps
390     * </ul>
391     * 
392     *
393     * @param newKV Parameter to modify
394     * @return Itself
395     */
396    public DynamicMotionMagicExpoDutyCycle withKV(double newKV) {
397        kV = newKV;
398        return this;
399    }
400    
401    /**
402     * Modifies this Control Request's kV parameter and returns itself for
403     * method-chaining and easier to use request API.
404     * <p>
405     * Mechanism kV for profiling.  Unlike the kV slot gain, this is always in units
406     * of V/rps.
407     * <p>
408     * This represents the amount of voltage necessary to hold a velocity.  In terms
409     * of the Motion Magic® Expo profile, a higher kV results in a slower maximum
410     * velocity.
411     * 
412     * <ul>
413     *   <li> Units: V/rps
414     * </ul>
415     * 
416     *
417     * @param newKV Parameter to modify
418     * @return Itself
419     */
420    public DynamicMotionMagicExpoDutyCycle withKV(Per<VoltageUnit, AngularVelocityUnit> newKV) {
421        kV = newKV.in(Volts.per(RotationsPerSecond));
422        return this;
423    }
424    
425    /**
426     * Helper method to get this Control Request's kV parameter converted
427     * to a unit type. If not using the Java units library, {@link #kV}
428     * can be accessed directly instead.
429     * <p>
430     * Mechanism kV for profiling.  Unlike the kV slot gain, this is always in units
431     * of V/rps.
432     * <p>
433     * This represents the amount of voltage necessary to hold a velocity.  In terms
434     * of the Motion Magic® Expo profile, a higher kV results in a slower maximum
435     * velocity.
436     * 
437     * <ul>
438     *   <li> Units: V/rps
439     * </ul>
440     * 
441     *
442     * @return kV
443     */
444    public Per<VoltageUnit, AngularVelocityUnit> getKVMeasure() {
445        return Volts.per(RotationsPerSecond).ofNative(kV);
446    }
447    
448    /**
449     * Modifies this Control Request's kA parameter and returns itself for
450     * method-chaining and easier to use request API.
451     * <p>
452     * Mechanism kA for profiling.  Unlike the kA slot gain, this is always in units
453     * of V/rps².
454     * <p>
455     * This represents the amount of voltage necessary to achieve an acceleration. 
456     * In terms of the Motion Magic® Expo profile, a higher kA results in a slower
457     * acceleration.
458     * 
459     * <ul>
460     *   <li> Units: V/rps²
461     * </ul>
462     * 
463     *
464     * @param newKA Parameter to modify
465     * @return Itself
466     */
467    public DynamicMotionMagicExpoDutyCycle withKA(double newKA) {
468        kA = newKA;
469        return this;
470    }
471    
472    /**
473     * Modifies this Control Request's kA parameter and returns itself for
474     * method-chaining and easier to use request API.
475     * <p>
476     * Mechanism kA for profiling.  Unlike the kA slot gain, this is always in units
477     * of V/rps².
478     * <p>
479     * This represents the amount of voltage necessary to achieve an acceleration. 
480     * In terms of the Motion Magic® Expo profile, a higher kA results in a slower
481     * acceleration.
482     * 
483     * <ul>
484     *   <li> Units: V/rps²
485     * </ul>
486     * 
487     *
488     * @param newKA Parameter to modify
489     * @return Itself
490     */
491    public DynamicMotionMagicExpoDutyCycle withKA(Per<VoltageUnit, AngularAccelerationUnit> newKA) {
492        kA = newKA.in(Volts.per(RotationsPerSecondPerSecond));
493        return this;
494    }
495    
496    /**
497     * Helper method to get this Control Request's kA parameter converted
498     * to a unit type. If not using the Java units library, {@link #kA}
499     * can be accessed directly instead.
500     * <p>
501     * Mechanism kA for profiling.  Unlike the kA slot gain, this is always in units
502     * of V/rps².
503     * <p>
504     * This represents the amount of voltage necessary to achieve an acceleration. 
505     * In terms of the Motion Magic® Expo profile, a higher kA results in a slower
506     * acceleration.
507     * 
508     * <ul>
509     *   <li> Units: V/rps²
510     * </ul>
511     * 
512     *
513     * @return kA
514     */
515    public Per<VoltageUnit, AngularAccelerationUnit> getKAMeasure() {
516        return Volts.per(RotationsPerSecondPerSecond).ofNative(kA);
517    }
518    
519    /**
520     * Modifies this Control Request's Velocity parameter and returns itself for
521     * method-chaining and easier to use request API.
522     * <p>
523     * Cruise velocity for profiling.  The signage does not matter as the device
524     * will use the absolute value for profile generation.  Setting this to 0 will
525     * allow the profile to run to the max possible velocity based on Expo_kV.
526     * 
527     * <ul>
528     *   <li> Units: rotations per second
529     * </ul>
530     * 
531     *
532     * @param newVelocity Parameter to modify
533     * @return Itself
534     */
535    public DynamicMotionMagicExpoDutyCycle withVelocity(double newVelocity) {
536        Velocity = newVelocity;
537        return this;
538    }
539    
540    /**
541     * Modifies this Control Request's Velocity parameter and returns itself for
542     * method-chaining and easier to use request API.
543     * <p>
544     * Cruise velocity for profiling.  The signage does not matter as the device
545     * will use the absolute value for profile generation.  Setting this to 0 will
546     * allow the profile to run to the max possible velocity based on Expo_kV.
547     * 
548     * <ul>
549     *   <li> Units: rotations per second
550     * </ul>
551     * 
552     *
553     * @param newVelocity Parameter to modify
554     * @return Itself
555     */
556    public DynamicMotionMagicExpoDutyCycle withVelocity(AngularVelocity newVelocity) {
557        Velocity = newVelocity.in(RotationsPerSecond);
558        return this;
559    }
560    
561    /**
562     * Helper method to get this Control Request's Velocity parameter converted
563     * to a unit type. If not using the Java units library, {@link #Velocity}
564     * can be accessed directly instead.
565     * <p>
566     * Cruise velocity for profiling.  The signage does not matter as the device
567     * will use the absolute value for profile generation.  Setting this to 0 will
568     * allow the profile to run to the max possible velocity based on Expo_kV.
569     * 
570     * <ul>
571     *   <li> Units: rotations per second
572     * </ul>
573     * 
574     *
575     * @return Velocity
576     */
577    public AngularVelocity getVelocityMeasure() {
578        return RotationsPerSecond.of(Velocity);
579    }
580    
581    /**
582     * Modifies this Control Request's EnableFOC parameter and returns itself for
583     * method-chaining and easier to use request API.
584     * <p>
585     * Set to true to use FOC commutation (requires Phoenix Pro), which increases
586     * peak power by ~15% on supported devices (see {@link SupportsFOC}). Set to
587     * false to use trapezoidal commutation.
588     * <p>
589     * FOC improves motor performance by leveraging torque (current) control. 
590     * However, this may be inconvenient for applications that require specifying
591     * duty cycle or voltage.  CTR-Electronics has developed a hybrid method that
592     * combines the performances gains of FOC while still allowing applications to
593     * provide duty cycle or voltage demand.  This not to be confused with simple
594     * sinusoidal control or phase voltage control which lacks the performance
595     * gains.
596     *
597     * @param newEnableFOC Parameter to modify
598     * @return Itself
599     */
600    public DynamicMotionMagicExpoDutyCycle withEnableFOC(boolean newEnableFOC) {
601        EnableFOC = newEnableFOC;
602        return this;
603    }
604    
605    /**
606     * Modifies this Control Request's FeedForward parameter and returns itself for
607     * method-chaining and easier to use request API.
608     * <p>
609     * Feedforward to apply in fractional units between -1 and +1. This is added to
610     * the output of the onboard feedforward terms.
611     * 
612     * <ul>
613     *   <li> Units: fractional
614     * </ul>
615     * 
616     *
617     * @param newFeedForward Parameter to modify
618     * @return Itself
619     */
620    public DynamicMotionMagicExpoDutyCycle withFeedForward(double newFeedForward) {
621        FeedForward = newFeedForward;
622        return this;
623    }
624    
625    /**
626     * Modifies this Control Request's Slot parameter and returns itself for
627     * method-chaining and easier to use request API.
628     * <p>
629     * Select which gains are applied by selecting the slot.  Use the configuration
630     * api to set the gain values for the selected slot before enabling this
631     * feature. Slot must be within [0,2].
632     *
633     * @param newSlot Parameter to modify
634     * @return Itself
635     */
636    public DynamicMotionMagicExpoDutyCycle withSlot(int newSlot) {
637        Slot = newSlot;
638        return this;
639    }
640    
641    /**
642     * Modifies this Control Request's OverrideBrakeDurNeutral parameter and returns itself for
643     * method-chaining and easier to use request API.
644     * <p>
645     * Set to true to static-brake the rotor when output is zero (or within
646     * deadband).  Set to false to use the NeutralMode configuration setting
647     * (default). This flag exists to provide the fundamental behavior of this
648     * control when output is zero, which is to provide 0V to the motor.
649     *
650     * @param newOverrideBrakeDurNeutral Parameter to modify
651     * @return Itself
652     */
653    public DynamicMotionMagicExpoDutyCycle withOverrideBrakeDurNeutral(boolean newOverrideBrakeDurNeutral) {
654        OverrideBrakeDurNeutral = newOverrideBrakeDurNeutral;
655        return this;
656    }
657    
658    /**
659     * Modifies this Control Request's LimitForwardMotion parameter and returns itself for
660     * method-chaining and easier to use request API.
661     * <p>
662     * Set to true to force forward limiting.  This allows users to use other limit
663     * switch sensors connected to robot controller.  This also allows use of active
664     * sensors that require external power.
665     *
666     * @param newLimitForwardMotion Parameter to modify
667     * @return Itself
668     */
669    public DynamicMotionMagicExpoDutyCycle withLimitForwardMotion(boolean newLimitForwardMotion) {
670        LimitForwardMotion = newLimitForwardMotion;
671        return this;
672    }
673    
674    /**
675     * Modifies this Control Request's LimitReverseMotion parameter and returns itself for
676     * method-chaining and easier to use request API.
677     * <p>
678     * Set to true to force reverse limiting.  This allows users to use other limit
679     * switch sensors connected to robot controller.  This also allows use of active
680     * sensors that require external power.
681     *
682     * @param newLimitReverseMotion Parameter to modify
683     * @return Itself
684     */
685    public DynamicMotionMagicExpoDutyCycle withLimitReverseMotion(boolean newLimitReverseMotion) {
686        LimitReverseMotion = newLimitReverseMotion;
687        return this;
688    }
689    
690    /**
691     * Modifies this Control Request's IgnoreHardwareLimits parameter and returns itself for
692     * method-chaining and easier to use request API.
693     * <p>
694     * Set to true to ignore hardware limit switches and the LimitForwardMotion and
695     * LimitReverseMotion parameters, instead allowing motion.
696     * <p>
697     * This can be useful on mechanisms such as an intake/feeder, where a limit
698     * switch stops motion while intaking but should be ignored when feeding to a
699     * shooter.
700     * <p>
701     * The hardware limit faults and Forward/ReverseLimit signals will still report
702     * the values of the limit switches regardless of this parameter.
703     *
704     * @param newIgnoreHardwareLimits Parameter to modify
705     * @return Itself
706     */
707    public DynamicMotionMagicExpoDutyCycle withIgnoreHardwareLimits(boolean newIgnoreHardwareLimits) {
708        IgnoreHardwareLimits = newIgnoreHardwareLimits;
709        return this;
710    }
711    
712    /**
713     * Modifies this Control Request's IgnoreSoftwareLimits parameter and returns itself for
714     * method-chaining and easier to use request API.
715     * <p>
716     * Set to true to ignore software limits, instead allowing motion.
717     * <p>
718     * This can be useful when calibrating the zero point of a mechanism such as an
719     * elevator.
720     * <p>
721     * The software limit faults will still report the values of the software limits
722     * regardless of this parameter.
723     *
724     * @param newIgnoreSoftwareLimits Parameter to modify
725     * @return Itself
726     */
727    public DynamicMotionMagicExpoDutyCycle withIgnoreSoftwareLimits(boolean newIgnoreSoftwareLimits) {
728        IgnoreSoftwareLimits = newIgnoreSoftwareLimits;
729        return this;
730    }
731    
732    /**
733     * Modifies this Control Request's UseTimesync parameter and returns itself for
734     * method-chaining and easier to use request API.
735     * <p>
736     * Set to true to delay applying this control request until a timesync boundary
737     * (requires Phoenix Pro and CANivore). This eliminates the impact of
738     * nondeterministic network delays in exchange for a larger but deterministic
739     * control latency.
740     * <p>
741     * This requires setting the ControlTimesyncFreqHz config in MotorOutputConfigs.
742     * Additionally, when this is enabled, the UpdateFreqHz of this request should
743     * be set to 0 Hz.
744     *
745     * @param newUseTimesync Parameter to modify
746     * @return Itself
747     */
748    public DynamicMotionMagicExpoDutyCycle withUseTimesync(boolean newUseTimesync) {
749        UseTimesync = newUseTimesync;
750        return this;
751    }
752
753    /**
754     * Sets the frequency at which this control will update.
755     * This is designated in Hertz, with a minimum of 20 Hz
756     * (every 50 ms) and a maximum of 1000 Hz (every 1 ms).
757     * Some update frequencies are not supported and will be
758     * promoted up to the next highest supported frequency.
759     * <p>
760     * If this field is set to 0 Hz, the control request will
761     * be sent immediately as a one-shot frame. This may be useful
762     * for advanced applications that require outputs to be
763     * synchronized with data acquisition. In this case, we
764     * recommend not exceeding 50 ms between control calls.
765     *
766     * @param newUpdateFreqHz Parameter to modify
767     * @return Itself
768     */
769    @Override
770    public DynamicMotionMagicExpoDutyCycle withUpdateFreqHz(double newUpdateFreqHz) {
771        UpdateFreqHz = newUpdateFreqHz;
772        return this;
773    }
774
775    /**
776     * Sets the frequency at which this control will update.
777     * This is designated in Hertz, with a minimum of 20 Hz
778     * (every 50 ms) and a maximum of 1000 Hz (every 1 ms).
779     * Some update frequencies are not supported and will be
780     * promoted up to the next highest supported frequency.
781     * <p>
782     * If this field is set to 0 Hz, the control request will
783     * be sent immediately as a one-shot frame. This may be useful
784     * for advanced applications that require outputs to be
785     * synchronized with data acquisition. In this case, we
786     * recommend not exceeding 50 ms between control calls.
787     *
788     * @param newUpdateFreqHz Parameter to modify
789     * @return Itself
790     */
791    @Override
792    public DynamicMotionMagicExpoDutyCycle withUpdateFreqHz(Frequency newUpdateFreqHz) {
793        UpdateFreqHz = newUpdateFreqHz.in(Hertz);
794        return this;
795    }
796
797    @Override
798    public DynamicMotionMagicExpoDutyCycle clone() {
799        try {
800            return (DynamicMotionMagicExpoDutyCycle)super.clone();
801        } catch (CloneNotSupportedException ex) {
802            /* this should never happen */
803            throw new RuntimeException(ex);
804        }
805    }
806}
807