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 * Requests Motion Magic® to target a final position using a motion profile. 
015 * Users can optionally provide a voltage feedforward.
016 * <p>
017 * Motion Magic® produces a motion profile in real-time while attempting to honor the Cruise Velocity,
018 * Acceleration, and Jerk value specified via the Motion Magic® configuration values.  Target position can be
019 * changed on-the-fly and Motion Magic® will do its best to adjust the profile.  This control mode is
020 * voltage-based, so relevant closed-loop gains will use Volts for the numerator.
021 */
022public class MotionMagicVoltage extends ControlRequest
023{
024    private boolean applyConfigsOnRequest;
025    /**
026     * Position to drive toward in rotations.
027     */
028    public double Position;
029    /**
030     * Set to true to use FOC commutation, which increases peak power by ~15%. Set
031     * to false to use trapezoidal commutation.  FOC improves motor performance by
032     * leveraging torque (current) control.  However, this may be inconvenient for
033     * applications that require specifying duty cycle or voltage.  CTR-Electronics
034     * has developed a hybrid method that combines the performances gains of FOC
035     * while still allowing applications to provide duty cycle or voltage demand. 
036     * This not to be confused with simple sinusoidal control or phase voltage
037     * control which lacks the performance gains.
038     */
039    public boolean EnableFOC;
040    /**
041     * Feedforward to apply in volts
042     */
043    public double FeedForward;
044    /**
045     * Select which gains are applied by selecting the slot.  Use the configuration
046     * api to set the gain values for the selected slot before enabling this
047     * feature. Slot must be within [0,2].
048     */
049    public int Slot;
050    /**
051     * Set to true to static-brake the rotor when output is zero (or within
052     * deadband).  Set to false to use the NeutralMode configuration setting
053     * (default). This flag exists to provide the fundamental behavior of this
054     * control when output is zero, which is to provide 0V to the motor.
055     */
056    public boolean OverrideBrakeDurNeutral;
057
058    
059    /**
060     * The period at which this control will update at.
061     * This is designated in Hertz, with a minimum of 20 Hz
062     * (every 50 ms) and a maximum of 1000 Hz (every 1 ms).
063     * <p>
064     * If this field is set to 0 Hz, the control request will
065     * be sent immediately as a one-shot frame. This may be useful
066     * for advanced applications that require outputs to be
067     * synchronized with data acquisition. In this case, we
068     * recommend not exceeding 50 ms between control calls.
069     */
070    public double UpdateFreqHz = 100; // Default to 100Hz
071
072    /**
073     * The timeout when sending configs associated with this control
074     */
075    public double configTimeout = 0.1;
076
077    /**
078     * Requests Motion Magic® to target a final position using a motion profile.
079     *  Users can optionally provide a voltage feedforward.
080     * <p>
081     * Motion Magic® produces a motion profile in real-time while attempting to
082     * honor the Cruise Velocity, Acceleration, and Jerk value specified via the
083     * Motion Magic® configuration values.  Target position can be changed
084     * on-the-fly and Motion Magic® will do its best to adjust the profile. 
085     * This control mode is voltage-based, so relevant closed-loop gains will
086     * use Volts for the numerator.
087     *
088     * @param Position     Position to drive toward in rotations.
089     * @param EnableFOC     Set to true to use FOC commutation, which increases
090     *                      peak power by ~15%. Set to false to use trapezoidal
091     *                      commutation.  FOC improves motor performance by
092     *                      leveraging torque (current) control.  However, this
093     *                      may be inconvenient for applications that require
094     *                      specifying duty cycle or voltage.  CTR-Electronics
095     *                      has developed a hybrid method that combines the
096     *                      performances gains of FOC while still allowing
097     *                      applications to provide duty cycle or voltage
098     *                      demand.  This not to be confused with simple
099     *                      sinusoidal control or phase voltage control which
100     *                      lacks the performance gains.
101     * @param FeedForward     Feedforward to apply in volts
102     * @param Slot     Select which gains are applied by selecting the slot. 
103     *                 Use the configuration api to set the gain values for the
104     *                 selected slot before enabling this feature. Slot must be
105     *                 within [0,2].
106     * @param OverrideBrakeDurNeutral     Set to true to static-brake the rotor
107     *                                    when output is zero (or within
108     *                                    deadband).  Set to false to use the
109     *                                    NeutralMode configuration setting
110     *                                    (default). This flag exists to provide
111     *                                    the fundamental behavior of this
112     *                                    control when output is zero, which is
113     *                                    to provide 0V to the motor.
114     */
115    public MotionMagicVoltage(double Position, boolean EnableFOC, double FeedForward, int Slot, boolean OverrideBrakeDurNeutral)
116    {
117        super("MotionMagicVoltage");
118        this.Position = Position;
119        this.EnableFOC = EnableFOC;
120        this.FeedForward = FeedForward;
121        this.Slot = Slot;
122        this.OverrideBrakeDurNeutral = OverrideBrakeDurNeutral;
123    }
124
125    /**
126     * Requests Motion Magic® to target a final position using a motion profile.
127     *  Users can optionally provide a voltage feedforward.
128     * <p>
129     * Motion Magic® produces a motion profile in real-time while attempting to
130     * honor the Cruise Velocity, Acceleration, and Jerk value specified via the
131     * Motion Magic® configuration values.  Target position can be changed
132     * on-the-fly and Motion Magic® will do its best to adjust the profile. 
133     * This control mode is voltage-based, so relevant closed-loop gains will
134     * use Volts for the numerator.
135     *
136     * @param Position     Position to drive toward in rotations.
137     */
138    public MotionMagicVoltage(double Position)
139    {
140        this(Position, true, 0.0, 0, false);
141    }
142
143    @Override
144    public String toString()
145    {
146        String ss = "class: MotionMagicVoltage\n";
147        ss += "Position: " + Position + "\n";
148        ss += "EnableFOC: " + EnableFOC + "\n";
149        ss += "FeedForward: " + FeedForward + "\n";
150        ss += "Slot: " + Slot + "\n";
151        ss += "OverrideBrakeDurNeutral: " + OverrideBrakeDurNeutral + "\n";
152        return ss;
153    }
154
155    @Override
156    public StatusCode sendRequest(String network, int deviceHash, boolean cancelOtherRequests)
157    {
158        var ref = requestReference.getNameValues();
159        ref.put("Position", String.valueOf(this.Position));
160        ref.put("EnableFOC", String.valueOf(this.EnableFOC));
161        ref.put("FeedForward", String.valueOf(this.FeedForward));
162        ref.put("Slot", String.valueOf(this.Slot));
163        ref.put("OverrideBrakeDurNeutral", String.valueOf(this.OverrideBrakeDurNeutral));
164        String ss = "";
165        
166        ControlConfigJNI.JNI_RequestConfigApply(network, deviceHash, configTimeout, ss, applyConfigsOnRequest);
167        applyConfigsOnRequest = false;
168        return StatusCode.valueOf(ControlJNI.JNI_RequestControlMotionMagicVoltage(
169                network, deviceHash, UpdateFreqHz, cancelOtherRequests, Position, EnableFOC, FeedForward, Slot, OverrideBrakeDurNeutral));
170    }
171    
172    /**
173     * Modifies this Control Request's Position parameter and returns itself for
174     * method-chaining and easier to use request API.
175     *
176     * @param newPosition Parameter to modify
177     * @return Itself
178     */
179    public MotionMagicVoltage withPosition(double newPosition)
180    {
181        Position = newPosition;
182        return this;
183    }
184    
185    /**
186     * Modifies this Control Request's EnableFOC parameter and returns itself for
187     * method-chaining and easier to use request API.
188     *
189     * @param newEnableFOC Parameter to modify
190     * @return Itself
191     */
192    public MotionMagicVoltage withEnableFOC(boolean newEnableFOC)
193    {
194        EnableFOC = newEnableFOC;
195        return this;
196    }
197    
198    /**
199     * Modifies this Control Request's FeedForward parameter and returns itself for
200     * method-chaining and easier to use request API.
201     *
202     * @param newFeedForward Parameter to modify
203     * @return Itself
204     */
205    public MotionMagicVoltage withFeedForward(double newFeedForward)
206    {
207        FeedForward = newFeedForward;
208        return this;
209    }
210    
211    /**
212     * Modifies this Control Request's Slot parameter and returns itself for
213     * method-chaining and easier to use request API.
214     *
215     * @param newSlot Parameter to modify
216     * @return Itself
217     */
218    public MotionMagicVoltage withSlot(int newSlot)
219    {
220        Slot = newSlot;
221        return this;
222    }
223    
224    /**
225     * Modifies this Control Request's OverrideBrakeDurNeutral parameter and returns itself for
226     * method-chaining and easier to use request API.
227     *
228     * @param newOverrideBrakeDurNeutral Parameter to modify
229     * @return Itself
230     */
231    public MotionMagicVoltage withOverrideBrakeDurNeutral(boolean newOverrideBrakeDurNeutral)
232    {
233        OverrideBrakeDurNeutral = newOverrideBrakeDurNeutral;
234        return this;
235    }
236    /**
237     * Sets the period at which this control will update at.
238     * This is designated in Hertz, with a minimum of 20 Hz
239     * (every 50 ms) and a maximum of 1000 Hz (every 1 ms).
240     * <p>
241     * If this field is set to 0 Hz, the control request will
242     * be sent immediately as a one-shot frame. This may be useful
243     * for advanced applications that require outputs to be
244     * synchronized with data acquisition. In this case, we
245     * recommend not exceeding 50 ms between control calls.
246     *
247     * @param newUpdateFreqHz Parameter to modify
248     * @return Itself
249     */
250    public MotionMagicVoltage withUpdateFreqHz(double newUpdateFreqHz)
251    {
252        UpdateFreqHz = newUpdateFreqHz;
253        return this;
254    }
255    /**
256     * Forces configs to be applied the next time this is used in a setControl.
257     * <p>
258     * This is not necessary in the majority of cases, because Phoenix will make sure configs are
259     * properly set when they are not already set
260     */
261    public void forceApplyConfigs() { applyConfigsOnRequest = true; }
262}
263