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.configs;
008
009import com.ctre.phoenix6.StatusCode;
010import com.ctre.phoenix6.configs.jni.ConfigJNI;
011import com.ctre.phoenix6.spns.*;
012import com.ctre.phoenix6.signals.*;
013
014import edu.wpi.first.units.*;
015
016import edu.wpi.first.units.measure.*;
017import static edu.wpi.first.units.Units.*;
018
019/**
020 * Configs that affect the magnet sensor and how to interpret it.
021 * <p>
022 * Includes sensor direction, the sensor discontinuity point, and the
023 * magnet offset.
024 */
025public class MagnetSensorConfigs implements ParentConfiguration
026{
027    /**
028     * Direction of the sensor to determine positive rotation, as seen
029     * facing the LED side of the CANcoder.
030     * 
031     */
032    public SensorDirectionValue SensorDirection = SensorDirectionValue.CounterClockwise_Positive;
033    /**
034     * This offset is added to the reported position, allowing the
035     * application to trim the zero position.  When set to the default
036     * value of zero, position reports zero when magnet north pole aligns
037     * with the LED.
038     * 
039     * <ul>
040     *   <li> <b>Minimum Value:</b> -1
041     *   <li> <b>Maximum Value:</b> 1
042     *   <li> <b>Default Value:</b> 0
043     *   <li> <b>Units:</b> rotations
044     * </ul>
045     */
046    public double MagnetOffset = 0;
047    /**
048     * The positive discontinuity point of the absolute sensor in
049     * rotations. This determines the point at which the absolute sensor
050     * wraps around, keeping the absolute position (after offset) in the
051     * range [x-1, x).
052     * 
053     * <ul>
054     *   <li> Setting this to 1 makes the absolute position unsigned [0,
055     * 1)
056     *   <li> Setting this to 0.5 makes the absolute position signed
057     * [-0.5, 0.5)
058     *   <li> Setting this to 0 makes the absolute position always
059     * negative [-1, 0)
060     * </ul>
061     * 
062     * Many rotational mechanisms such as arms have a region of motion
063     * that is unreachable. This should be set to the center of that
064     * region of motion, in non-negative rotations. This affects the
065     * position of the device at bootup.
066     * <p>
067     * For example, consider an arm which can travel from -0.2 to 0.6
068     * rotations with a little leeway, where 0 is horizontally forward.
069     * Since -0.2 rotations has the same absolute position as 0.8
070     * rotations, we can say that the arm typically does not travel in the
071     * range (0.6, 0.8) rotations. As a result, the discontinuity point
072     * would be the center of that range, which is 0.7 rotations. This
073     * results in an absolute sensor range of [-0.3, 0.7) rotations.
074     * <p>
075     * Given a total range of motion less than 1 rotation, users can
076     * calculate the discontinuity point using mean(lowerLimit,
077     * upperLimit) + 0.5. If that results in a value outside the range [0,
078     * 1], either cap the value to [0, 1], or add/subtract 1.0 rotation
079     * from your lower and upper limits of motion.
080     * <p>
081     * On a Talon motor controller, this is only supported when using the
082     * PulseWidth sensor source.
083     * 
084     * <ul>
085     *   <li> <b>Minimum Value:</b> 0.0
086     *   <li> <b>Maximum Value:</b> 1.0
087     *   <li> <b>Default Value:</b> 0.5
088     *   <li> <b>Units:</b> rotations
089     * </ul>
090     */
091    public double AbsoluteSensorDiscontinuityPoint = 0.5;
092    
093    /**
094     * Modifies this configuration's SensorDirection parameter and returns itself for
095     * method-chaining and easier to use config API.
096     * <p>
097     * Direction of the sensor to determine positive rotation, as seen
098     * facing the LED side of the CANcoder.
099     * 
100     *
101     * @param newSensorDirection Parameter to modify
102     * @return Itself
103     */
104    public MagnetSensorConfigs withSensorDirection(SensorDirectionValue newSensorDirection)
105    {
106        SensorDirection = newSensorDirection;
107        return this;
108    }
109    
110    /**
111     * Modifies this configuration's MagnetOffset parameter and returns itself for
112     * method-chaining and easier to use config API.
113     * <p>
114     * This offset is added to the reported position, allowing the
115     * application to trim the zero position.  When set to the default
116     * value of zero, position reports zero when magnet north pole aligns
117     * with the LED.
118     * 
119     * <ul>
120     *   <li> <b>Minimum Value:</b> -1
121     *   <li> <b>Maximum Value:</b> 1
122     *   <li> <b>Default Value:</b> 0
123     *   <li> <b>Units:</b> rotations
124     * </ul>
125     *
126     * @param newMagnetOffset Parameter to modify
127     * @return Itself
128     */
129    public MagnetSensorConfigs withMagnetOffset(double newMagnetOffset)
130    {
131        MagnetOffset = newMagnetOffset;
132        return this;
133    }
134    
135    /**
136     * Modifies this configuration's MagnetOffset parameter and returns itself for
137     * method-chaining and easier to use config API.
138     * <p>
139     * This offset is added to the reported position, allowing the
140     * application to trim the zero position.  When set to the default
141     * value of zero, position reports zero when magnet north pole aligns
142     * with the LED.
143     * 
144     * <ul>
145     *   <li> <b>Minimum Value:</b> -1
146     *   <li> <b>Maximum Value:</b> 1
147     *   <li> <b>Default Value:</b> 0
148     *   <li> <b>Units:</b> rotations
149     * </ul>
150     *
151     * @param newMagnetOffset Parameter to modify
152     * @return Itself
153     */
154    public MagnetSensorConfigs withMagnetOffset(Angle newMagnetOffset)
155    {
156        MagnetOffset = newMagnetOffset.in(Rotations);
157        return this;
158    }
159    
160    /**
161     * Helper method to get this configuration's MagnetOffset parameter converted
162     * to a unit type. If not using the Java units library, {@link #MagnetOffset}
163     * can be accessed directly instead.
164     * <p>
165     * This offset is added to the reported position, allowing the
166     * application to trim the zero position.  When set to the default
167     * value of zero, position reports zero when magnet north pole aligns
168     * with the LED.
169     * 
170     * <ul>
171     *   <li> <b>Minimum Value:</b> -1
172     *   <li> <b>Maximum Value:</b> 1
173     *   <li> <b>Default Value:</b> 0
174     *   <li> <b>Units:</b> rotations
175     * </ul>
176     *
177     * @return MagnetOffset
178     */
179    public Angle getMagnetOffsetMeasure()
180    {
181        return Rotations.of(MagnetOffset);
182    }
183    
184    /**
185     * Modifies this configuration's AbsoluteSensorDiscontinuityPoint parameter and returns itself for
186     * method-chaining and easier to use config API.
187     * <p>
188     * The positive discontinuity point of the absolute sensor in
189     * rotations. This determines the point at which the absolute sensor
190     * wraps around, keeping the absolute position (after offset) in the
191     * range [x-1, x).
192     * 
193     * <ul>
194     *   <li> Setting this to 1 makes the absolute position unsigned [0,
195     * 1)
196     *   <li> Setting this to 0.5 makes the absolute position signed
197     * [-0.5, 0.5)
198     *   <li> Setting this to 0 makes the absolute position always
199     * negative [-1, 0)
200     * </ul>
201     * 
202     * Many rotational mechanisms such as arms have a region of motion
203     * that is unreachable. This should be set to the center of that
204     * region of motion, in non-negative rotations. This affects the
205     * position of the device at bootup.
206     * <p>
207     * For example, consider an arm which can travel from -0.2 to 0.6
208     * rotations with a little leeway, where 0 is horizontally forward.
209     * Since -0.2 rotations has the same absolute position as 0.8
210     * rotations, we can say that the arm typically does not travel in the
211     * range (0.6, 0.8) rotations. As a result, the discontinuity point
212     * would be the center of that range, which is 0.7 rotations. This
213     * results in an absolute sensor range of [-0.3, 0.7) rotations.
214     * <p>
215     * Given a total range of motion less than 1 rotation, users can
216     * calculate the discontinuity point using mean(lowerLimit,
217     * upperLimit) + 0.5. If that results in a value outside the range [0,
218     * 1], either cap the value to [0, 1], or add/subtract 1.0 rotation
219     * from your lower and upper limits of motion.
220     * <p>
221     * On a Talon motor controller, this is only supported when using the
222     * PulseWidth sensor source.
223     * 
224     * <ul>
225     *   <li> <b>Minimum Value:</b> 0.0
226     *   <li> <b>Maximum Value:</b> 1.0
227     *   <li> <b>Default Value:</b> 0.5
228     *   <li> <b>Units:</b> rotations
229     * </ul>
230     *
231     * @param newAbsoluteSensorDiscontinuityPoint Parameter to modify
232     * @return Itself
233     */
234    public MagnetSensorConfigs withAbsoluteSensorDiscontinuityPoint(double newAbsoluteSensorDiscontinuityPoint)
235    {
236        AbsoluteSensorDiscontinuityPoint = newAbsoluteSensorDiscontinuityPoint;
237        return this;
238    }
239    
240    /**
241     * Modifies this configuration's AbsoluteSensorDiscontinuityPoint parameter and returns itself for
242     * method-chaining and easier to use config API.
243     * <p>
244     * The positive discontinuity point of the absolute sensor in
245     * rotations. This determines the point at which the absolute sensor
246     * wraps around, keeping the absolute position (after offset) in the
247     * range [x-1, x).
248     * 
249     * <ul>
250     *   <li> Setting this to 1 makes the absolute position unsigned [0,
251     * 1)
252     *   <li> Setting this to 0.5 makes the absolute position signed
253     * [-0.5, 0.5)
254     *   <li> Setting this to 0 makes the absolute position always
255     * negative [-1, 0)
256     * </ul>
257     * 
258     * Many rotational mechanisms such as arms have a region of motion
259     * that is unreachable. This should be set to the center of that
260     * region of motion, in non-negative rotations. This affects the
261     * position of the device at bootup.
262     * <p>
263     * For example, consider an arm which can travel from -0.2 to 0.6
264     * rotations with a little leeway, where 0 is horizontally forward.
265     * Since -0.2 rotations has the same absolute position as 0.8
266     * rotations, we can say that the arm typically does not travel in the
267     * range (0.6, 0.8) rotations. As a result, the discontinuity point
268     * would be the center of that range, which is 0.7 rotations. This
269     * results in an absolute sensor range of [-0.3, 0.7) rotations.
270     * <p>
271     * Given a total range of motion less than 1 rotation, users can
272     * calculate the discontinuity point using mean(lowerLimit,
273     * upperLimit) + 0.5. If that results in a value outside the range [0,
274     * 1], either cap the value to [0, 1], or add/subtract 1.0 rotation
275     * from your lower and upper limits of motion.
276     * <p>
277     * On a Talon motor controller, this is only supported when using the
278     * PulseWidth sensor source.
279     * 
280     * <ul>
281     *   <li> <b>Minimum Value:</b> 0.0
282     *   <li> <b>Maximum Value:</b> 1.0
283     *   <li> <b>Default Value:</b> 0.5
284     *   <li> <b>Units:</b> rotations
285     * </ul>
286     *
287     * @param newAbsoluteSensorDiscontinuityPoint Parameter to modify
288     * @return Itself
289     */
290    public MagnetSensorConfigs withAbsoluteSensorDiscontinuityPoint(Angle newAbsoluteSensorDiscontinuityPoint)
291    {
292        AbsoluteSensorDiscontinuityPoint = newAbsoluteSensorDiscontinuityPoint.in(Rotations);
293        return this;
294    }
295    
296    /**
297     * Helper method to get this configuration's AbsoluteSensorDiscontinuityPoint parameter converted
298     * to a unit type. If not using the Java units library, {@link #AbsoluteSensorDiscontinuityPoint}
299     * can be accessed directly instead.
300     * <p>
301     * The positive discontinuity point of the absolute sensor in
302     * rotations. This determines the point at which the absolute sensor
303     * wraps around, keeping the absolute position (after offset) in the
304     * range [x-1, x).
305     * 
306     * <ul>
307     *   <li> Setting this to 1 makes the absolute position unsigned [0,
308     * 1)
309     *   <li> Setting this to 0.5 makes the absolute position signed
310     * [-0.5, 0.5)
311     *   <li> Setting this to 0 makes the absolute position always
312     * negative [-1, 0)
313     * </ul>
314     * 
315     * Many rotational mechanisms such as arms have a region of motion
316     * that is unreachable. This should be set to the center of that
317     * region of motion, in non-negative rotations. This affects the
318     * position of the device at bootup.
319     * <p>
320     * For example, consider an arm which can travel from -0.2 to 0.6
321     * rotations with a little leeway, where 0 is horizontally forward.
322     * Since -0.2 rotations has the same absolute position as 0.8
323     * rotations, we can say that the arm typically does not travel in the
324     * range (0.6, 0.8) rotations. As a result, the discontinuity point
325     * would be the center of that range, which is 0.7 rotations. This
326     * results in an absolute sensor range of [-0.3, 0.7) rotations.
327     * <p>
328     * Given a total range of motion less than 1 rotation, users can
329     * calculate the discontinuity point using mean(lowerLimit,
330     * upperLimit) + 0.5. If that results in a value outside the range [0,
331     * 1], either cap the value to [0, 1], or add/subtract 1.0 rotation
332     * from your lower and upper limits of motion.
333     * <p>
334     * On a Talon motor controller, this is only supported when using the
335     * PulseWidth sensor source.
336     * 
337     * <ul>
338     *   <li> <b>Minimum Value:</b> 0.0
339     *   <li> <b>Maximum Value:</b> 1.0
340     *   <li> <b>Default Value:</b> 0.5
341     *   <li> <b>Units:</b> rotations
342     * </ul>
343     *
344     * @return AbsoluteSensorDiscontinuityPoint
345     */
346    public Angle getAbsoluteSensorDiscontinuityPointMeasure()
347    {
348        return Rotations.of(AbsoluteSensorDiscontinuityPoint);
349    }
350
351    
352
353    @Override
354    public String toString()
355    {
356        String ss = "Config Group: MagnetSensor\n";
357        ss += "    SensorDirection: " + SensorDirection + "\n";
358        ss += "    MagnetOffset: " + MagnetOffset + " rotations" + "\n";
359        ss += "    AbsoluteSensorDiscontinuityPoint: " + AbsoluteSensorDiscontinuityPoint + " rotations" + "\n";
360        return ss;
361    }
362
363    /**
364     *
365     */
366    public StatusCode deserialize(String to_deserialize)
367    {
368        SensorDirection = SensorDirectionValue.valueOf(ConfigJNI.Deserializeint(SpnValue.CANcoder_SensorDirection.value, to_deserialize));
369        MagnetOffset = ConfigJNI.Deserializedouble(SpnValue.CANCoder_MagnetOffset.value, to_deserialize);
370        AbsoluteSensorDiscontinuityPoint = ConfigJNI.Deserializedouble(SpnValue.Config_AbsoluteSensorDiscontinuityPoint.value, to_deserialize);
371        return  StatusCode.OK;
372    }
373
374    /**
375     *
376     */
377    public String serialize()
378    {
379        String ss = "";
380        ss += ConfigJNI.Serializeint(SpnValue.CANcoder_SensorDirection.value, SensorDirection.value);
381        ss += ConfigJNI.Serializedouble(SpnValue.CANCoder_MagnetOffset.value, MagnetOffset);
382        ss += ConfigJNI.Serializedouble(SpnValue.Config_AbsoluteSensorDiscontinuityPoint.value, AbsoluteSensorDiscontinuityPoint);
383        return ss;
384    }
385}
386