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 * Request a specified motor duty cycle with a differential position
017 * closed-loop.
018 * <p>
019 * This control mode will output a proportion of the supplied voltage which is supplied by the user. It will
020 * also set the motor's differential position setpoint to the specified position.
021 */
022public class DifferentialDutyCycle extends ControlRequest implements Cloneable
023{
024    /**
025     * Proportion of supply voltage to apply in fractional units between -1 and +1
026     */
027    public double TargetOutput;
028    /**
029     * Differential position to drive towards in rotations
030     */
031    public double DifferentialPosition;
032    /**
033     * Set to true to use FOC commutation (requires Phoenix Pro), which increases
034     * peak power by ~15%. Set to false to use trapezoidal commutation.
035     * <p>
036     * FOC improves motor performance by leveraging torque (current) control. 
037     * However, this may be inconvenient for applications that require specifying
038     * duty cycle or voltage.  CTR-Electronics has developed a hybrid method that
039     * combines the performances gains of FOC while still allowing applications to
040     * provide duty cycle or voltage demand.  This not to be confused with simple
041     * sinusoidal control or phase voltage control which lacks the performance
042     * gains.
043     */
044    public boolean EnableFOC;
045    /**
046     * Select which gains are applied to the differential controller by selecting
047     * the slot.  Use the configuration api to set the gain values for the selected
048     * slot before enabling this feature. Slot must be within [0,2].
049     */
050    public int DifferentialSlot;
051    /**
052     * Set to true to static-brake the rotor when output is zero (or within
053     * deadband).  Set to false to use the NeutralMode configuration setting
054     * (default). This flag exists to provide the fundamental behavior of this
055     * control when output is zero, which is to provide 0V to the motor.
056     */
057    public boolean OverrideBrakeDurNeutral;
058    /**
059     * Set to true to force forward limiting.  This allows users to use other limit
060     * switch sensors connected to robot controller.  This also allows use of active
061     * sensors that require external power.
062     */
063    public boolean LimitForwardMotion;
064    /**
065     * Set to true to force reverse limiting.  This allows users to use other limit
066     * switch sensors connected to robot controller.  This also allows use of active
067     * sensors that require external power.
068     */
069    public boolean LimitReverseMotion;
070
071    /**
072     * The period at which this control will update at.
073     * This is designated in Hertz, with a minimum of 20 Hz
074     * (every 50 ms) and a maximum of 1000 Hz (every 1 ms).
075     * <p>
076     * If this field is set to 0 Hz, the control request will
077     * be sent immediately as a one-shot frame. This may be useful
078     * for advanced applications that require outputs to be
079     * synchronized with data acquisition. In this case, we
080     * recommend not exceeding 50 ms between control calls.
081     */
082    public double UpdateFreqHz = 100; // Default to 100Hz
083
084    /**
085     * Request a specified motor duty cycle with a differential position
086     * closed-loop.
087     * <p>
088     * This control mode will output a proportion of the supplied voltage which is
089     * supplied by the user. It will also set the motor's differential position
090     * setpoint to the specified position.
091     * 
092     * @param TargetOutput    Proportion of supply voltage to apply in fractional
093     *                        units between -1 and +1
094     * @param DifferentialPosition    Differential position to drive towards in
095     *                                rotations
096     * @param EnableFOC    Set to true to use FOC commutation (requires Phoenix
097     *                     Pro), which increases peak power by ~15%. Set to false to
098     *                     use trapezoidal commutation.
099     *                     <p>
100     *                     FOC improves motor performance by leveraging torque
101     *                     (current) control.  However, this may be inconvenient for
102     *                     applications that require specifying duty cycle or
103     *                     voltage.  CTR-Electronics has developed a hybrid method
104     *                     that combines the performances gains of FOC while still
105     *                     allowing applications to provide duty cycle or voltage
106     *                     demand.  This not to be confused with simple sinusoidal
107     *                     control or phase voltage control which lacks the
108     *                     performance gains.
109     * @param DifferentialSlot    Select which gains are applied to the differential
110     *                            controller by selecting the slot.  Use the
111     *                            configuration api to set the gain values for the
112     *                            selected slot before enabling this feature. Slot
113     *                            must be within [0,2].
114     * @param OverrideBrakeDurNeutral    Set to true to static-brake the rotor when
115     *                                   output is zero (or within deadband).  Set
116     *                                   to false to use the NeutralMode
117     *                                   configuration setting (default). This flag
118     *                                   exists to provide the fundamental behavior
119     *                                   of this control when output is zero, which
120     *                                   is to provide 0V to the motor.
121     * @param LimitForwardMotion    Set to true to force forward limiting.  This
122     *                              allows users to use other limit switch sensors
123     *                              connected to robot controller.  This also allows
124     *                              use of active sensors that require external
125     *                              power.
126     * @param LimitReverseMotion    Set to true to force reverse limiting.  This
127     *                              allows users to use other limit switch sensors
128     *                              connected to robot controller.  This also allows
129     *                              use of active sensors that require external
130     *                              power.
131     */
132    public DifferentialDutyCycle(double TargetOutput, double DifferentialPosition, boolean EnableFOC, int DifferentialSlot, boolean OverrideBrakeDurNeutral, boolean LimitForwardMotion, boolean LimitReverseMotion)
133    {
134        super("DifferentialDutyCycle");
135        this.TargetOutput = TargetOutput;
136        this.DifferentialPosition = DifferentialPosition;
137        this.EnableFOC = EnableFOC;
138        this.DifferentialSlot = DifferentialSlot;
139        this.OverrideBrakeDurNeutral = OverrideBrakeDurNeutral;
140        this.LimitForwardMotion = LimitForwardMotion;
141        this.LimitReverseMotion = LimitReverseMotion;
142    }
143
144        /**
145     * Request a specified motor duty cycle with a differential position
146     * closed-loop.
147     * <p>
148     * This control mode will output a proportion of the supplied voltage which is
149     * supplied by the user. It will also set the motor's differential position
150     * setpoint to the specified position.
151     * 
152     * @param TargetOutput    Proportion of supply voltage to apply in fractional
153     *                        units between -1 and +1
154     * @param DifferentialPosition    Differential position to drive towards in
155     *                                rotations
156     */
157    public DifferentialDutyCycle(double TargetOutput, double DifferentialPosition)
158    {
159        this(TargetOutput, DifferentialPosition, true, 1, false, false, false);
160    }
161
162    @Override
163    public String toString()
164    {
165        String ss = "class: DifferentialDutyCycle\n";
166        ss += "TargetOutput: " + TargetOutput + "\n";
167        ss += "DifferentialPosition: " + DifferentialPosition + "\n";
168        ss += "EnableFOC: " + EnableFOC + "\n";
169        ss += "DifferentialSlot: " + DifferentialSlot + "\n";
170        ss += "OverrideBrakeDurNeutral: " + OverrideBrakeDurNeutral + "\n";
171        ss += "LimitForwardMotion: " + LimitForwardMotion + "\n";
172        ss += "LimitReverseMotion: " + LimitReverseMotion + "\n";
173        return ss;
174    }
175
176    @Override
177    public StatusCode sendRequest(String network, int deviceHash, boolean cancelOtherRequests)
178    {
179        return StatusCode.valueOf(ControlJNI.JNI_RequestControlDifferentialDutyCycle(
180                network, deviceHash, UpdateFreqHz, cancelOtherRequests, TargetOutput, DifferentialPosition, EnableFOC, DifferentialSlot, OverrideBrakeDurNeutral, LimitForwardMotion, LimitReverseMotion));
181    }
182
183    /**
184     * Gets information about this control request.
185     *
186     * @return Map of control parameter names and corresponding applied values
187     */
188    @Override
189    public Map<String, String> getControlInfo()
190    {
191        var controlInfo = new HashMap<String, String>();
192        controlInfo.put("Name", getName());
193        controlInfo.put("TargetOutput", String.valueOf(this.TargetOutput));
194        controlInfo.put("DifferentialPosition", String.valueOf(this.DifferentialPosition));
195        controlInfo.put("EnableFOC", String.valueOf(this.EnableFOC));
196        controlInfo.put("DifferentialSlot", String.valueOf(this.DifferentialSlot));
197        controlInfo.put("OverrideBrakeDurNeutral", String.valueOf(this.OverrideBrakeDurNeutral));
198        controlInfo.put("LimitForwardMotion", String.valueOf(this.LimitForwardMotion));
199        controlInfo.put("LimitReverseMotion", String.valueOf(this.LimitReverseMotion));
200        return controlInfo;
201    }
202    
203    /**
204     * Modifies this Control Request's TargetOutput parameter and returns itself for
205     * method-chaining and easier to use request API.
206     * <p>
207     * Proportion of supply voltage to apply in fractional units between -1 and +1
208     *
209     * @param newTargetOutput Parameter to modify
210     * @return Itself
211     */
212    public DifferentialDutyCycle withTargetOutput(double newTargetOutput)
213    {
214        TargetOutput = newTargetOutput;
215        return this;
216    }
217    
218    /**
219     * Modifies this Control Request's DifferentialPosition parameter and returns itself for
220     * method-chaining and easier to use request API.
221     * <p>
222     * Differential position to drive towards in rotations
223     *
224     * @param newDifferentialPosition Parameter to modify
225     * @return Itself
226     */
227    public DifferentialDutyCycle withDifferentialPosition(double newDifferentialPosition)
228    {
229        DifferentialPosition = newDifferentialPosition;
230        return this;
231    }
232    
233    /**
234     * Modifies this Control Request's EnableFOC parameter and returns itself for
235     * method-chaining and easier to use request API.
236     * <p>
237     * Set to true to use FOC commutation (requires Phoenix Pro), which increases
238     * peak power by ~15%. Set to false to use trapezoidal commutation.
239     * <p>
240     * FOC improves motor performance by leveraging torque (current) control. 
241     * However, this may be inconvenient for applications that require specifying
242     * duty cycle or voltage.  CTR-Electronics has developed a hybrid method that
243     * combines the performances gains of FOC while still allowing applications to
244     * provide duty cycle or voltage demand.  This not to be confused with simple
245     * sinusoidal control or phase voltage control which lacks the performance
246     * gains.
247     *
248     * @param newEnableFOC Parameter to modify
249     * @return Itself
250     */
251    public DifferentialDutyCycle withEnableFOC(boolean newEnableFOC)
252    {
253        EnableFOC = newEnableFOC;
254        return this;
255    }
256    
257    /**
258     * Modifies this Control Request's DifferentialSlot parameter and returns itself for
259     * method-chaining and easier to use request API.
260     * <p>
261     * Select which gains are applied to the differential controller by selecting
262     * the slot.  Use the configuration api to set the gain values for the selected
263     * slot before enabling this feature. Slot must be within [0,2].
264     *
265     * @param newDifferentialSlot Parameter to modify
266     * @return Itself
267     */
268    public DifferentialDutyCycle withDifferentialSlot(int newDifferentialSlot)
269    {
270        DifferentialSlot = newDifferentialSlot;
271        return this;
272    }
273    
274    /**
275     * Modifies this Control Request's OverrideBrakeDurNeutral parameter and returns itself for
276     * method-chaining and easier to use request API.
277     * <p>
278     * Set to true to static-brake the rotor when output is zero (or within
279     * deadband).  Set to false to use the NeutralMode configuration setting
280     * (default). This flag exists to provide the fundamental behavior of this
281     * control when output is zero, which is to provide 0V to the motor.
282     *
283     * @param newOverrideBrakeDurNeutral Parameter to modify
284     * @return Itself
285     */
286    public DifferentialDutyCycle withOverrideBrakeDurNeutral(boolean newOverrideBrakeDurNeutral)
287    {
288        OverrideBrakeDurNeutral = newOverrideBrakeDurNeutral;
289        return this;
290    }
291    
292    /**
293     * Modifies this Control Request's LimitForwardMotion parameter and returns itself for
294     * method-chaining and easier to use request API.
295     * <p>
296     * Set to true to force forward limiting.  This allows users to use other limit
297     * switch sensors connected to robot controller.  This also allows use of active
298     * sensors that require external power.
299     *
300     * @param newLimitForwardMotion Parameter to modify
301     * @return Itself
302     */
303    public DifferentialDutyCycle withLimitForwardMotion(boolean newLimitForwardMotion)
304    {
305        LimitForwardMotion = newLimitForwardMotion;
306        return this;
307    }
308    
309    /**
310     * Modifies this Control Request's LimitReverseMotion parameter and returns itself for
311     * method-chaining and easier to use request API.
312     * <p>
313     * Set to true to force reverse limiting.  This allows users to use other limit
314     * switch sensors connected to robot controller.  This also allows use of active
315     * sensors that require external power.
316     *
317     * @param newLimitReverseMotion Parameter to modify
318     * @return Itself
319     */
320    public DifferentialDutyCycle withLimitReverseMotion(boolean newLimitReverseMotion)
321    {
322        LimitReverseMotion = newLimitReverseMotion;
323        return this;
324    }
325    /**
326     * Sets the period at which this control will update at.
327     * This is designated in Hertz, with a minimum of 20 Hz
328     * (every 50 ms) and a maximum of 1000 Hz (every 1 ms).
329     * <p>
330     * If this field is set to 0 Hz, the control request will
331     * be sent immediately as a one-shot frame. This may be useful
332     * for advanced applications that require outputs to be
333     * synchronized with data acquisition. In this case, we
334     * recommend not exceeding 50 ms between control calls.
335     *
336     * @param newUpdateFreqHz Parameter to modify
337     * @return Itself
338     */
339    public DifferentialDutyCycle withUpdateFreqHz(double newUpdateFreqHz)
340    {
341        UpdateFreqHz = newUpdateFreqHz;
342        return this;
343    }
344
345    @Override
346    public DifferentialDutyCycle clone()
347    {
348        try {
349            return (DifferentialDutyCycle)super.clone();
350        } catch (CloneNotSupportedException ex) {
351            /* this should never happen */
352            throw new RuntimeException(ex);
353        }
354    }
355}
356