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