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