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.phoenixpro.controls;
008
009import com.ctre.phoenixpro.StatusCode;
010import com.ctre.phoenixpro.controls.jni.ControlJNI;
011import com.ctre.phoenixpro.controls.jni.ControlConfigJNI;
012
013/**
014 * Request a specified motor current (field oriented control).
015 * <p>
016 * This control request will drive the motor to the requested motor (stator) current value.  This leverages
017 * field oriented control (FOC), which means greater peak power than what is documented.  This scales to
018 * torque based on Motor's kT constant.
019 */
020public class TorqueCurrentFOC extends ControlRequest
021{
022    private boolean applyConfigsOnRequest;
023    /**
024     * Amount of motor current in Amperes
025     */
026    public double Output;
027    /**
028     * The maximum absolute motor output that can be applied, which effectively
029     * limits the velocity. For example, 0.50 means no more than 50% output in
030     * either direction.  This is useful for preventing the motor from spinning to
031     * its terminal velocity when there is no external torque applied unto the
032     * rotor.  Note this is absolute maximum, so the value should be between zero
033     * and one.
034     */
035    public double MaxAbsDutyCycle;
036    /**
037     * Deadband in Amperes.  If torque request is within deadband, the bridge output
038     * is neutral. If deadband is set to zero then there is effectively no deadband.
039     * Note if deadband is zero, a free spinning motor will spin for quite a while
040     * as the firmware attempts to hold the motor's bemf. If user expects motor to
041     * cease spinning quickly with a demand of zero, we recommend a deadband of one
042     * Ampere. This value will be converted to an integral value of amps.
043     */
044    public double Deadband;
045    /**
046     * Set to true to coast the rotor when output is zero (or within deadband).  Set
047     * to false to use the NeutralMode configuration setting (default). This flag
048     * exists to provide the fundamental behavior of this control when output is
049     * zero, which is to provide 0A (zero torque).
050     */
051    public boolean OverrideCoastDurNeutral;
052
053    
054    /**
055     * The period at which this control will update at.
056     * This is designated in Hertz, with a minimum of 20 Hz
057     * (every 50 ms) and a maximum of 1000 Hz (every 1 ms).
058     * <p>
059     * If this field is set to 0 Hz, the control request will
060     * be sent immediately as a one-shot frame. This may be useful
061     * for advanced applications that require outputs to be
062     * synchronized with data acquisition. In this case, we
063     * recommend not exceeding 50 ms between control calls.
064     */
065    public double UpdateFreqHz = 100; // Default to 100Hz
066
067    /**
068     * The timeout when sending configs associated with this control
069     */
070    public double configTimeout = 0.1;
071
072    /**
073     * Request a specified motor current (field oriented control).
074     * <p>
075     * This control request will drive the motor to the requested motor (stator)
076     * current value.  This leverages field oriented control (FOC), which means
077     * greater peak power than what is documented.  This scales to torque based
078     * on Motor's kT constant.
079     *
080     * @param Output     Amount of motor current in Amperes
081     * @param MaxAbsDutyCycle     The maximum absolute motor output that can be
082     *                            applied, which effectively limits the
083     *                            velocity. For example, 0.50 means no more than
084     *                            50% output in either direction.  This is
085     *                            useful for preventing the motor from spinning
086     *                            to its terminal velocity when there is no
087     *                            external torque applied unto the rotor.  Note
088     *                            this is absolute maximum, so the value should
089     *                            be between zero and one.
090     * @param Deadband     Deadband in Amperes.  If torque request is within
091     *                     deadband, the bridge output is neutral. If deadband
092     *                     is set to zero then there is effectively no deadband.
093     *                     Note if deadband is zero, a free spinning motor will
094     *                     spin for quite a while as the firmware attempts to
095     *                     hold the motor's bemf. If user expects motor to cease
096     *                     spinning quickly with a demand of zero, we recommend
097     *                     a deadband of one Ampere. This value will be
098     *                     converted to an integral value of amps.
099     * @param OverrideCoastDurNeutral     Set to true to coast the rotor when
100     *                                    output is zero (or within deadband). 
101     *                                    Set to false to use the NeutralMode
102     *                                    configuration setting (default). This
103     *                                    flag exists to provide the fundamental
104     *                                    behavior of this control when output
105     *                                    is zero, which is to provide 0A (zero
106     *                                    torque).
107     */
108    public TorqueCurrentFOC(double Output, double MaxAbsDutyCycle, double Deadband, boolean OverrideCoastDurNeutral)
109    {
110        super("TorqueCurrentFOC");
111        this.Output = Output;
112        this.MaxAbsDutyCycle = MaxAbsDutyCycle;
113        this.Deadband = Deadband;
114        this.OverrideCoastDurNeutral = OverrideCoastDurNeutral;
115    }
116
117    /**
118     * Request a specified motor current (field oriented control).
119     * <p>
120     * This control request will drive the motor to the requested motor (stator)
121     * current value.  This leverages field oriented control (FOC), which means
122     * greater peak power than what is documented.  This scales to torque based
123     * on Motor's kT constant.
124     *
125     * @param Output     Amount of motor current in Amperes
126     */
127    public TorqueCurrentFOC(double Output)
128    {
129        this(Output, 1.0, 0.0, false);
130    }
131
132    @Override
133    public String toString()
134    {
135        String ss = "class: TorqueCurrentFOC\n";
136        ss += "Output: " + Output + "\n";
137        ss += "MaxAbsDutyCycle: " + MaxAbsDutyCycle + "\n";
138        ss += "Deadband: " + Deadband + "\n";
139        ss += "OverrideCoastDurNeutral: " + OverrideCoastDurNeutral + "\n";
140        return ss;
141    }
142
143    @Override
144    public StatusCode sendRequest(String network, int deviceHash, boolean cancelOtherRequests)
145    {
146        var ref = requestReference.getNameValues();
147        ref.put("Output", String.valueOf(this.Output));
148        ref.put("MaxAbsDutyCycle", String.valueOf(this.MaxAbsDutyCycle));
149        ref.put("Deadband", String.valueOf(this.Deadband));
150        ref.put("OverrideCoastDurNeutral", String.valueOf(this.OverrideCoastDurNeutral));
151        String ss = "";
152        
153        ControlConfigJNI.JNI_RequestConfigApply(network, deviceHash, configTimeout, ss, applyConfigsOnRequest);
154        applyConfigsOnRequest = false;
155        return StatusCode.valueOf(ControlJNI.JNI_RequestControlTorqueCurrentFOC(
156                network, deviceHash, UpdateFreqHz, cancelOtherRequests, Output, MaxAbsDutyCycle, Deadband, OverrideCoastDurNeutral));
157    }
158    
159    /**
160     * Modifies this Control Request's Output parameter and returns itself for
161     * method-chaining and easier to use request API.
162     *
163     * @param newOutput Parameter to modify
164     * @return Itself
165     */
166    public TorqueCurrentFOC withOutput(double newOutput)
167    {
168        Output = newOutput;
169        return this;
170    }
171    
172    /**
173     * Modifies this Control Request's MaxAbsDutyCycle parameter and returns itself for
174     * method-chaining and easier to use request API.
175     *
176     * @param newMaxAbsDutyCycle Parameter to modify
177     * @return Itself
178     */
179    public TorqueCurrentFOC withMaxAbsDutyCycle(double newMaxAbsDutyCycle)
180    {
181        MaxAbsDutyCycle = newMaxAbsDutyCycle;
182        return this;
183    }
184    
185    /**
186     * Modifies this Control Request's Deadband parameter and returns itself for
187     * method-chaining and easier to use request API.
188     *
189     * @param newDeadband Parameter to modify
190     * @return Itself
191     */
192    public TorqueCurrentFOC withDeadband(double newDeadband)
193    {
194        Deadband = newDeadband;
195        return this;
196    }
197    
198    /**
199     * Modifies this Control Request's OverrideCoastDurNeutral parameter and returns itself for
200     * method-chaining and easier to use request API.
201     *
202     * @param newOverrideCoastDurNeutral Parameter to modify
203     * @return Itself
204     */
205    public TorqueCurrentFOC withOverrideCoastDurNeutral(boolean newOverrideCoastDurNeutral)
206    {
207        OverrideCoastDurNeutral = newOverrideCoastDurNeutral;
208        return this;
209    }
210    /**
211     * Sets the period at which this control will update at.
212     * This is designated in Hertz, with a minimum of 20 Hz
213     * (every 50 ms) and a maximum of 1000 Hz (every 1 ms).
214     * <p>
215     * If this field is set to 0 Hz, the control request will
216     * be sent immediately as a one-shot frame. This may be useful
217     * for advanced applications that require outputs to be
218     * synchronized with data acquisition. In this case, we
219     * recommend not exceeding 50 ms between control calls.
220     *
221     * @param newUpdateFreqHz Parameter to modify
222     * @return Itself
223     */
224    public TorqueCurrentFOC withUpdateFreqHz(double newUpdateFreqHz)
225    {
226        UpdateFreqHz = newUpdateFreqHz;
227        return this;
228    }
229    /**
230     * Forces configs to be applied the next time this is used in a setControl.
231     * <p>
232     * This is not necessary in the majority of cases, because Phoenix will make sure configs are
233     * properly set when they are not already set
234     */
235    public void forceApplyConfigs() { applyConfigsOnRequest = true; }
236}
237