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