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.StatusCode;
010import com.ctre.phoenix6.controls.jni.ControlJNI;
011
012import java.util.HashMap;
013import java.util.Map;
014
015/**
016 * Requires Phoenix Pro and CANivore;
017 * Requests Motion Magic® to target a final position using a motion profile. 
018 * This dynamic request allows runtime changes to Cruise Velocity, Acceleration,
019 * and Jerk.  Users can optionally provide a duty cycle feedforward.  This
020 * control requires use of a CANivore.
021 * <p>
022 * Motion Magic® produces a motion profile in real-time while attempting to honor the specified Cruise
023 * Velocity, Acceleration, and Jerk value.  This control mode does not use the Expo_kV or Expo_kA configs. 
024 * Target position can be changed on-the-fly and Motion Magic® will do its best to adjust the profile. This
025 * control mode is duty cycle based, so relevant closed-loop gains will use fractional duty cycle for the
026 * numerator:  +1.0 represents full forward output.
027 */
028public class DynamicMotionMagicDutyCycle extends ControlRequest implements Cloneable
029{
030    /**
031     * Position to drive toward in rotations.
032     */
033    public double Position;
034    /**
035     * Cruise velocity for profiling.  The signage does not matter as the device
036     * will use the absolute value for profile generation.
037     */
038    public double Velocity;
039    /**
040     * Acceleration for profiling.  The signage does not matter as the device will
041     * use the absolute value for profile generation
042     */
043    public double Acceleration;
044    /**
045     * Jerk for profiling.  The signage does not matter as the device will use the
046     * absolute value for profile generation
047     */
048    public double Jerk;
049    /**
050     * Set to true to use FOC commutation (requires Phoenix Pro), which increases
051     * peak power by ~15%. Set to false to use trapezoidal commutation.
052     * <p>
053     * FOC improves motor performance by leveraging torque (current) control. 
054     * However, this may be inconvenient for applications that require specifying
055     * duty cycle or voltage.  CTR-Electronics has developed a hybrid method that
056     * combines the performances gains of FOC while still allowing applications to
057     * provide duty cycle or voltage demand.  This not to be confused with simple
058     * sinusoidal control or phase voltage control which lacks the performance
059     * gains.
060     */
061    public boolean EnableFOC;
062    /**
063     * Feedforward to apply in fractional units between -1 and +1.
064     */
065    public double FeedForward;
066    /**
067     * Select which gains are applied by selecting the slot.  Use the configuration
068     * api to set the gain values for the selected slot before enabling this
069     * feature. Slot must be within [0,2].
070     */
071    public int Slot;
072    /**
073     * Set to true to static-brake the rotor when output is zero (or within
074     * deadband).  Set to false to use the NeutralMode configuration setting
075     * (default). This flag exists to provide the fundamental behavior of this
076     * control when output is zero, which is to provide 0V to the motor.
077     */
078    public boolean OverrideBrakeDurNeutral;
079    /**
080     * Set to true to force forward limiting.  This allows users to use other limit
081     * switch sensors connected to robot controller.  This also allows use of active
082     * sensors that require external power.
083     */
084    public boolean LimitForwardMotion;
085    /**
086     * Set to true to force reverse limiting.  This allows users to use other limit
087     * switch sensors connected to robot controller.  This also allows use of active
088     * sensors that require external power.
089     */
090    public boolean LimitReverseMotion;
091
092    /**
093     * The period at which this control will update at.
094     * This is designated in Hertz, with a minimum of 20 Hz
095     * (every 50 ms) and a maximum of 1000 Hz (every 1 ms).
096     * <p>
097     * If this field is set to 0 Hz, the control request will
098     * be sent immediately as a one-shot frame. This may be useful
099     * for advanced applications that require outputs to be
100     * synchronized with data acquisition. In this case, we
101     * recommend not exceeding 50 ms between control calls.
102     */
103    public double UpdateFreqHz = 100; // Default to 100Hz
104
105    /**
106     * Requires Phoenix Pro and CANivore;
107     * Requests Motion Magic® to target a final position using a motion profile. 
108     * This dynamic request allows runtime changes to Cruise Velocity, Acceleration,
109     * and Jerk.  Users can optionally provide a duty cycle feedforward.  This
110     * control requires use of a CANivore.
111     * <p>
112     * Motion Magic® produces a motion profile in real-time while attempting to
113     * honor the specified Cruise Velocity, Acceleration, and Jerk value.  This
114     * control mode does not use the Expo_kV or Expo_kA configs.  Target position
115     * can be changed on-the-fly and Motion Magic® will do its best to adjust the
116     * profile. This control mode is duty cycle based, so relevant closed-loop gains
117     * will use fractional duty cycle for the numerator:  +1.0 represents full
118     * forward output.
119     * 
120     * @param Position    Position to drive toward in rotations.
121     * @param Velocity    Cruise velocity for profiling.  The signage does not
122     *                    matter as the device will use the absolute value for
123     *                    profile generation.
124     * @param Acceleration    Acceleration for profiling.  The signage does not
125     *                        matter as the device will use the absolute value for
126     *                        profile generation
127     * @param Jerk    Jerk for profiling.  The signage does not matter as the device
128     *                will use the absolute value for profile generation
129     * @param EnableFOC    Set to true to use FOC commutation (requires Phoenix
130     *                     Pro), which increases peak power by ~15%. Set to false to
131     *                     use trapezoidal commutation.
132     *                     <p>
133     *                     FOC improves motor performance by leveraging torque
134     *                     (current) control.  However, this may be inconvenient for
135     *                     applications that require specifying duty cycle or
136     *                     voltage.  CTR-Electronics has developed a hybrid method
137     *                     that combines the performances gains of FOC while still
138     *                     allowing applications to provide duty cycle or voltage
139     *                     demand.  This not to be confused with simple sinusoidal
140     *                     control or phase voltage control which lacks the
141     *                     performance gains.
142     * @param FeedForward    Feedforward to apply in fractional units between -1 and
143     *                       +1.
144     * @param Slot    Select which gains are applied by selecting the slot.  Use the
145     *                configuration api to set the gain values for the selected slot
146     *                before enabling this feature. Slot must be within [0,2].
147     * @param OverrideBrakeDurNeutral    Set to true to static-brake the rotor when
148     *                                   output is zero (or within deadband).  Set
149     *                                   to false to use the NeutralMode
150     *                                   configuration setting (default). This flag
151     *                                   exists to provide the fundamental behavior
152     *                                   of this control when output is zero, which
153     *                                   is to provide 0V to the motor.
154     * @param LimitForwardMotion    Set to true to force forward limiting.  This
155     *                              allows users to use other limit switch sensors
156     *                              connected to robot controller.  This also allows
157     *                              use of active sensors that require external
158     *                              power.
159     * @param LimitReverseMotion    Set to true to force reverse limiting.  This
160     *                              allows users to use other limit switch sensors
161     *                              connected to robot controller.  This also allows
162     *                              use of active sensors that require external
163     *                              power.
164     */
165    public DynamicMotionMagicDutyCycle(double Position, double Velocity, double Acceleration, double Jerk, boolean EnableFOC, double FeedForward, int Slot, boolean OverrideBrakeDurNeutral, boolean LimitForwardMotion, boolean LimitReverseMotion)
166    {
167        super("DynamicMotionMagicDutyCycle");
168        this.Position = Position;
169        this.Velocity = Velocity;
170        this.Acceleration = Acceleration;
171        this.Jerk = Jerk;
172        this.EnableFOC = EnableFOC;
173        this.FeedForward = FeedForward;
174        this.Slot = Slot;
175        this.OverrideBrakeDurNeutral = OverrideBrakeDurNeutral;
176        this.LimitForwardMotion = LimitForwardMotion;
177        this.LimitReverseMotion = LimitReverseMotion;
178    }
179
180        /**
181     * Requires Phoenix Pro and CANivore;
182     * Requests Motion Magic® to target a final position using a motion profile. 
183     * This dynamic request allows runtime changes to Cruise Velocity, Acceleration,
184     * and Jerk.  Users can optionally provide a duty cycle feedforward.  This
185     * control requires use of a CANivore.
186     * <p>
187     * Motion Magic® produces a motion profile in real-time while attempting to
188     * honor the specified Cruise Velocity, Acceleration, and Jerk value.  This
189     * control mode does not use the Expo_kV or Expo_kA configs.  Target position
190     * can be changed on-the-fly and Motion Magic® will do its best to adjust the
191     * profile. This control mode is duty cycle based, so relevant closed-loop gains
192     * will use fractional duty cycle for the numerator:  +1.0 represents full
193     * forward output.
194     * 
195     * @param Position    Position to drive toward in rotations.
196     * @param Velocity    Cruise velocity for profiling.  The signage does not
197     *                    matter as the device will use the absolute value for
198     *                    profile generation.
199     * @param Acceleration    Acceleration for profiling.  The signage does not
200     *                        matter as the device will use the absolute value for
201     *                        profile generation
202     * @param Jerk    Jerk for profiling.  The signage does not matter as the device
203     *                will use the absolute value for profile generation
204     */
205    public DynamicMotionMagicDutyCycle(double Position, double Velocity, double Acceleration, double Jerk)
206    {
207        this(Position, Velocity, Acceleration, Jerk, true, 0.0, 0, false, false, false);
208    }
209
210    @Override
211    public String toString()
212    {
213        String ss = "class: DynamicMotionMagicDutyCycle\n";
214        ss += "Position: " + Position + "\n";
215        ss += "Velocity: " + Velocity + "\n";
216        ss += "Acceleration: " + Acceleration + "\n";
217        ss += "Jerk: " + Jerk + "\n";
218        ss += "EnableFOC: " + EnableFOC + "\n";
219        ss += "FeedForward: " + FeedForward + "\n";
220        ss += "Slot: " + Slot + "\n";
221        ss += "OverrideBrakeDurNeutral: " + OverrideBrakeDurNeutral + "\n";
222        ss += "LimitForwardMotion: " + LimitForwardMotion + "\n";
223        ss += "LimitReverseMotion: " + LimitReverseMotion + "\n";
224        return ss;
225    }
226
227    @Override
228    public StatusCode sendRequest(String network, int deviceHash, boolean cancelOtherRequests)
229    {
230        return StatusCode.valueOf(ControlJNI.JNI_RequestControlDynamicMotionMagicDutyCycle(
231                network, deviceHash, UpdateFreqHz, cancelOtherRequests, Position, Velocity, Acceleration, Jerk, EnableFOC, FeedForward, Slot, OverrideBrakeDurNeutral, LimitForwardMotion, LimitReverseMotion));
232    }
233
234    /**
235     * Gets information about this control request.
236     *
237     * @return Map of control parameter names and corresponding applied values
238     */
239    @Override
240    public Map<String, String> getControlInfo()
241    {
242        var controlInfo = new HashMap<String, String>();
243        controlInfo.put("Name", getName());
244        controlInfo.put("Position", String.valueOf(this.Position));
245        controlInfo.put("Velocity", String.valueOf(this.Velocity));
246        controlInfo.put("Acceleration", String.valueOf(this.Acceleration));
247        controlInfo.put("Jerk", String.valueOf(this.Jerk));
248        controlInfo.put("EnableFOC", String.valueOf(this.EnableFOC));
249        controlInfo.put("FeedForward", String.valueOf(this.FeedForward));
250        controlInfo.put("Slot", String.valueOf(this.Slot));
251        controlInfo.put("OverrideBrakeDurNeutral", String.valueOf(this.OverrideBrakeDurNeutral));
252        controlInfo.put("LimitForwardMotion", String.valueOf(this.LimitForwardMotion));
253        controlInfo.put("LimitReverseMotion", String.valueOf(this.LimitReverseMotion));
254        return controlInfo;
255    }
256    
257    /**
258     * Modifies this Control Request's Position parameter and returns itself for
259     * method-chaining and easier to use request API.
260     * <p>
261     * Position to drive toward in rotations.
262     *
263     * @param newPosition Parameter to modify
264     * @return Itself
265     */
266    public DynamicMotionMagicDutyCycle withPosition(double newPosition)
267    {
268        Position = newPosition;
269        return this;
270    }
271    
272    /**
273     * Modifies this Control Request's Velocity parameter and returns itself for
274     * method-chaining and easier to use request API.
275     * <p>
276     * Cruise velocity for profiling.  The signage does not matter as the device
277     * will use the absolute value for profile generation.
278     *
279     * @param newVelocity Parameter to modify
280     * @return Itself
281     */
282    public DynamicMotionMagicDutyCycle withVelocity(double newVelocity)
283    {
284        Velocity = newVelocity;
285        return this;
286    }
287    
288    /**
289     * Modifies this Control Request's Acceleration parameter and returns itself for
290     * method-chaining and easier to use request API.
291     * <p>
292     * Acceleration for profiling.  The signage does not matter as the device will
293     * use the absolute value for profile generation
294     *
295     * @param newAcceleration Parameter to modify
296     * @return Itself
297     */
298    public DynamicMotionMagicDutyCycle withAcceleration(double newAcceleration)
299    {
300        Acceleration = newAcceleration;
301        return this;
302    }
303    
304    /**
305     * Modifies this Control Request's Jerk parameter and returns itself for
306     * method-chaining and easier to use request API.
307     * <p>
308     * Jerk for profiling.  The signage does not matter as the device will use the
309     * absolute value for profile generation
310     *
311     * @param newJerk Parameter to modify
312     * @return Itself
313     */
314    public DynamicMotionMagicDutyCycle withJerk(double newJerk)
315    {
316        Jerk = newJerk;
317        return this;
318    }
319    
320    /**
321     * Modifies this Control Request's EnableFOC parameter and returns itself for
322     * method-chaining and easier to use request API.
323     * <p>
324     * Set to true to use FOC commutation (requires Phoenix Pro), which increases
325     * peak power by ~15%. Set to false to use trapezoidal commutation.
326     * <p>
327     * FOC improves motor performance by leveraging torque (current) control. 
328     * However, this may be inconvenient for applications that require specifying
329     * duty cycle or voltage.  CTR-Electronics has developed a hybrid method that
330     * combines the performances gains of FOC while still allowing applications to
331     * provide duty cycle or voltage demand.  This not to be confused with simple
332     * sinusoidal control or phase voltage control which lacks the performance
333     * gains.
334     *
335     * @param newEnableFOC Parameter to modify
336     * @return Itself
337     */
338    public DynamicMotionMagicDutyCycle withEnableFOC(boolean newEnableFOC)
339    {
340        EnableFOC = newEnableFOC;
341        return this;
342    }
343    
344    /**
345     * Modifies this Control Request's FeedForward parameter and returns itself for
346     * method-chaining and easier to use request API.
347     * <p>
348     * Feedforward to apply in fractional units between -1 and +1.
349     *
350     * @param newFeedForward Parameter to modify
351     * @return Itself
352     */
353    public DynamicMotionMagicDutyCycle withFeedForward(double newFeedForward)
354    {
355        FeedForward = newFeedForward;
356        return this;
357    }
358    
359    /**
360     * Modifies this Control Request's Slot parameter and returns itself for
361     * method-chaining and easier to use request API.
362     * <p>
363     * Select which gains are applied by selecting the slot.  Use the configuration
364     * api to set the gain values for the selected slot before enabling this
365     * feature. Slot must be within [0,2].
366     *
367     * @param newSlot Parameter to modify
368     * @return Itself
369     */
370    public DynamicMotionMagicDutyCycle withSlot(int newSlot)
371    {
372        Slot = newSlot;
373        return this;
374    }
375    
376    /**
377     * Modifies this Control Request's OverrideBrakeDurNeutral parameter and returns itself for
378     * method-chaining and easier to use request API.
379     * <p>
380     * Set to true to static-brake the rotor when output is zero (or within
381     * deadband).  Set to false to use the NeutralMode configuration setting
382     * (default). This flag exists to provide the fundamental behavior of this
383     * control when output is zero, which is to provide 0V to the motor.
384     *
385     * @param newOverrideBrakeDurNeutral Parameter to modify
386     * @return Itself
387     */
388    public DynamicMotionMagicDutyCycle withOverrideBrakeDurNeutral(boolean newOverrideBrakeDurNeutral)
389    {
390        OverrideBrakeDurNeutral = newOverrideBrakeDurNeutral;
391        return this;
392    }
393    
394    /**
395     * Modifies this Control Request's LimitForwardMotion parameter and returns itself for
396     * method-chaining and easier to use request API.
397     * <p>
398     * Set to true to force forward limiting.  This allows users to use other limit
399     * switch sensors connected to robot controller.  This also allows use of active
400     * sensors that require external power.
401     *
402     * @param newLimitForwardMotion Parameter to modify
403     * @return Itself
404     */
405    public DynamicMotionMagicDutyCycle withLimitForwardMotion(boolean newLimitForwardMotion)
406    {
407        LimitForwardMotion = newLimitForwardMotion;
408        return this;
409    }
410    
411    /**
412     * Modifies this Control Request's LimitReverseMotion parameter and returns itself for
413     * method-chaining and easier to use request API.
414     * <p>
415     * Set to true to force reverse limiting.  This allows users to use other limit
416     * switch sensors connected to robot controller.  This also allows use of active
417     * sensors that require external power.
418     *
419     * @param newLimitReverseMotion Parameter to modify
420     * @return Itself
421     */
422    public DynamicMotionMagicDutyCycle withLimitReverseMotion(boolean newLimitReverseMotion)
423    {
424        LimitReverseMotion = newLimitReverseMotion;
425        return this;
426    }
427    /**
428     * Sets the period at which this control will update at.
429     * This is designated in Hertz, with a minimum of 20 Hz
430     * (every 50 ms) and a maximum of 1000 Hz (every 1 ms).
431     * <p>
432     * If this field is set to 0 Hz, the control request will
433     * be sent immediately as a one-shot frame. This may be useful
434     * for advanced applications that require outputs to be
435     * synchronized with data acquisition. In this case, we
436     * recommend not exceeding 50 ms between control calls.
437     *
438     * @param newUpdateFreqHz Parameter to modify
439     * @return Itself
440     */
441    public DynamicMotionMagicDutyCycle withUpdateFreqHz(double newUpdateFreqHz)
442    {
443        UpdateFreqHz = newUpdateFreqHz;
444        return this;
445    }
446
447    @Override
448    public DynamicMotionMagicDutyCycle clone()
449    {
450        try {
451            return (DynamicMotionMagicDutyCycle)super.clone();
452        } catch (CloneNotSupportedException ex) {
453            /* this should never happen */
454            throw new RuntimeException(ex);
455        }
456    }
457}
458