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.
017 * <p>
018 * This control mode will output a proportion of the supplied voltage which is supplied by the user.
019 */
020public class DutyCycleOut extends ControlRequest implements Cloneable
021{
022    /**
023     * Proportion of supply voltage to apply in fractional units between -1 and +1
024     */
025    public double Output;
026    /**
027     * Set to true to use FOC commutation (requires Phoenix Pro), which increases
028     * peak power by ~15%. Set to false to use trapezoidal commutation.  FOC
029     * improves motor performance by leveraging torque (current) control.  However,
030     * this may be inconvenient for applications that require specifying duty cycle
031     * or voltage.  CTR-Electronics has developed a hybrid method that combines the
032     * performances gains of FOC while still allowing applications to provide duty
033     * cycle or voltage demand.  This not to be confused with simple sinusoidal
034     * control or phase voltage control which lacks the performance gains.
035     */
036    public boolean EnableFOC;
037    /**
038     * Set to true to static-brake the rotor when output is zero (or within
039     * deadband).  Set to false to use the NeutralMode configuration setting
040     * (default). This flag exists to provide the fundamental behavior of this
041     * control when output is zero, which is to provide 0V to the motor.
042     */
043    public boolean OverrideBrakeDurNeutral;
044    /**
045     * Set to true to force forward limiting.  This allows users to use other limit
046     * switch sensors connected to robot controller.  This also allows use of active
047     * sensors that require external power.
048     */
049    public boolean LimitForwardMotion;
050    /**
051     * Set to true to force reverse limiting.  This allows users to use other limit
052     * switch sensors connected to robot controller.  This also allows use of active
053     * sensors that require external power.
054     */
055    public boolean LimitReverseMotion;
056
057    /**
058     * The period at which this control will update at.
059     * This is designated in Hertz, with a minimum of 20 Hz
060     * (every 50 ms) and a maximum of 1000 Hz (every 1 ms).
061     * <p>
062     * If this field is set to 0 Hz, the control request will
063     * be sent immediately as a one-shot frame. This may be useful
064     * for advanced applications that require outputs to be
065     * synchronized with data acquisition. In this case, we
066     * recommend not exceeding 50 ms between control calls.
067     */
068    public double UpdateFreqHz = 100; // Default to 100Hz
069
070    /**
071     * Request a specified motor duty cycle.
072     * <p>
073     * This control mode will output a proportion of the supplied voltage which is
074     * supplied by the user.
075     * 
076     * @param Output    Proportion of supply voltage to apply in fractional units
077     *                  between -1 and +1
078     * @param EnableFOC    Set to true to use FOC commutation (requires Phoenix
079     *                     Pro), which increases peak power by ~15%. Set to false to
080     *                     use trapezoidal commutation.  FOC improves motor
081     *                     performance by leveraging torque (current) control. 
082     *                     However, this may be inconvenient for applications that
083     *                     require specifying duty cycle or voltage. 
084     *                     CTR-Electronics has developed a hybrid method that
085     *                     combines the performances gains of FOC while still
086     *                     allowing applications to provide duty cycle or voltage
087     *                     demand.  This not to be confused with simple sinusoidal
088     *                     control or phase voltage control which lacks the
089     *                     performance gains.
090     * @param OverrideBrakeDurNeutral    Set to true to static-brake the rotor when
091     *                                   output is zero (or within deadband).  Set
092     *                                   to false to use the NeutralMode
093     *                                   configuration setting (default). This flag
094     *                                   exists to provide the fundamental behavior
095     *                                   of this control when output is zero, which
096     *                                   is to provide 0V to the motor.
097     * @param LimitForwardMotion    Set to true to force forward limiting.  This
098     *                              allows users to use other limit switch sensors
099     *                              connected to robot controller.  This also allows
100     *                              use of active sensors that require external
101     *                              power.
102     * @param LimitReverseMotion    Set to true to force reverse limiting.  This
103     *                              allows users to use other limit switch sensors
104     *                              connected to robot controller.  This also allows
105     *                              use of active sensors that require external
106     *                              power.
107     */
108    public DutyCycleOut(double Output, boolean EnableFOC, boolean OverrideBrakeDurNeutral, boolean LimitForwardMotion, boolean LimitReverseMotion)
109    {
110        super("DutyCycleOut");
111        this.Output = Output;
112        this.EnableFOC = EnableFOC;
113        this.OverrideBrakeDurNeutral = OverrideBrakeDurNeutral;
114        this.LimitForwardMotion = LimitForwardMotion;
115        this.LimitReverseMotion = LimitReverseMotion;
116    }
117
118        /**
119     * Request a specified motor duty cycle.
120     * <p>
121     * This control mode will output a proportion of the supplied voltage which is
122     * supplied by the user.
123     * 
124     * @param Output    Proportion of supply voltage to apply in fractional units
125     *                  between -1 and +1
126     */
127    public DutyCycleOut(double Output)
128    {
129        this(Output, true, false, false, false);
130    }
131
132    @Override
133    public String toString()
134    {
135        String ss = "class: DutyCycleOut\n";
136        ss += "Output: " + Output + "\n";
137        ss += "EnableFOC: " + EnableFOC + "\n";
138        ss += "OverrideBrakeDurNeutral: " + OverrideBrakeDurNeutral + "\n";
139        ss += "LimitForwardMotion: " + LimitForwardMotion + "\n";
140        ss += "LimitReverseMotion: " + LimitReverseMotion + "\n";
141        return ss;
142    }
143
144    @Override
145    public StatusCode sendRequest(String network, int deviceHash, boolean cancelOtherRequests)
146    {
147        return StatusCode.valueOf(ControlJNI.JNI_RequestControlDutyCycleOut(
148                network, deviceHash, UpdateFreqHz, cancelOtherRequests, Output, EnableFOC, OverrideBrakeDurNeutral, LimitForwardMotion, LimitReverseMotion));
149    }
150
151    /**
152     * Gets information about this control request.
153     *
154     * @return Map of control parameter names and corresponding applied values
155     */
156    @Override
157    public Map<String, String> getControlInfo()
158    {
159        var controlInfo = new HashMap<String, String>();
160        controlInfo.put("Name", getName());
161        controlInfo.put("Output", String.valueOf(this.Output));
162        controlInfo.put("EnableFOC", String.valueOf(this.EnableFOC));
163        controlInfo.put("OverrideBrakeDurNeutral", String.valueOf(this.OverrideBrakeDurNeutral));
164        controlInfo.put("LimitForwardMotion", String.valueOf(this.LimitForwardMotion));
165        controlInfo.put("LimitReverseMotion", String.valueOf(this.LimitReverseMotion));
166        return controlInfo;
167    }
168    
169    /**
170     * Modifies this Control Request's Output parameter and returns itself for
171     * method-chaining and easier to use request API.
172     *
173     * @param newOutput Parameter to modify
174     * @return Itself
175     */
176    public DutyCycleOut withOutput(double newOutput)
177    {
178        Output = newOutput;
179        return this;
180    }
181    
182    /**
183     * Modifies this Control Request's EnableFOC parameter and returns itself for
184     * method-chaining and easier to use request API.
185     *
186     * @param newEnableFOC Parameter to modify
187     * @return Itself
188     */
189    public DutyCycleOut withEnableFOC(boolean newEnableFOC)
190    {
191        EnableFOC = newEnableFOC;
192        return this;
193    }
194    
195    /**
196     * Modifies this Control Request's OverrideBrakeDurNeutral parameter and returns itself for
197     * method-chaining and easier to use request API.
198     *
199     * @param newOverrideBrakeDurNeutral Parameter to modify
200     * @return Itself
201     */
202    public DutyCycleOut withOverrideBrakeDurNeutral(boolean newOverrideBrakeDurNeutral)
203    {
204        OverrideBrakeDurNeutral = newOverrideBrakeDurNeutral;
205        return this;
206    }
207    
208    /**
209     * Modifies this Control Request's LimitForwardMotion parameter and returns itself for
210     * method-chaining and easier to use request API.
211     *
212     * @param newLimitForwardMotion Parameter to modify
213     * @return Itself
214     */
215    public DutyCycleOut withLimitForwardMotion(boolean newLimitForwardMotion)
216    {
217        LimitForwardMotion = newLimitForwardMotion;
218        return this;
219    }
220    
221    /**
222     * Modifies this Control Request's LimitReverseMotion parameter and returns itself for
223     * method-chaining and easier to use request API.
224     *
225     * @param newLimitReverseMotion Parameter to modify
226     * @return Itself
227     */
228    public DutyCycleOut withLimitReverseMotion(boolean newLimitReverseMotion)
229    {
230        LimitReverseMotion = newLimitReverseMotion;
231        return this;
232    }
233    /**
234     * Sets the period at which this control will update at.
235     * This is designated in Hertz, with a minimum of 20 Hz
236     * (every 50 ms) and a maximum of 1000 Hz (every 1 ms).
237     * <p>
238     * If this field is set to 0 Hz, the control request will
239     * be sent immediately as a one-shot frame. This may be useful
240     * for advanced applications that require outputs to be
241     * synchronized with data acquisition. In this case, we
242     * recommend not exceeding 50 ms between control calls.
243     *
244     * @param newUpdateFreqHz Parameter to modify
245     * @return Itself
246     */
247    public DutyCycleOut withUpdateFreqHz(double newUpdateFreqHz)
248    {
249        UpdateFreqHz = newUpdateFreqHz;
250        return this;
251    }
252
253    @Override
254    public DutyCycleOut clone()
255    {
256        try {
257            return (DutyCycleOut)super.clone();
258        } catch (CloneNotSupportedException ex) {
259            /* this should never happen */
260            throw new RuntimeException(ex);
261        }
262    }
263}
264