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