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