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.*;
012
013import edu.wpi.first.units.*;
014
015import edu.wpi.first.units.measure.*;
016import static edu.wpi.first.units.Units.*;
017
018/**
019 * Configs that affect the ToF Proximity detection
020 * <p>
021 * Includes proximity mode and the threshold for simple detection
022 */
023public class ProximityParamsConfigs implements ParentConfiguration, Cloneable {
024    /**
025     * Threshold for object detection.
026     * 
027     * <ul>
028     *   <li> <b>Minimum Value:</b> 0
029     *   <li> <b>Maximum Value:</b> 4
030     *   <li> <b>Default Value:</b> 0.4
031     *   <li> <b>Units:</b> m
032     * </ul>
033     */
034    public double ProximityThreshold = 0.4;
035    /**
036     * How far above and below the threshold the distance needs to be to
037     * trigger undetected and detected, respectively. This is used to
038     * prevent bouncing between the detected and undetected states for
039     * objects on the threshold.
040     * <p>
041     * If the threshold is set to 0.1 meters, and the hysteresis is 0.01
042     * meters, then an object needs to be within 0.09 meters to be
043     * detected. After the object is first detected, the distance then
044     * needs to exceed 0.11 meters to become undetected again.
045     * 
046     * <ul>
047     *   <li> <b>Minimum Value:</b> 0
048     *   <li> <b>Maximum Value:</b> 1
049     *   <li> <b>Default Value:</b> 0.01
050     *   <li> <b>Units:</b> m
051     * </ul>
052     */
053    public double ProximityHysteresis = 0.01;
054    /**
055     * The minimum allowable signal strength before determining the
056     * measurement is valid.
057     * <p>
058     * If the signal strength is particularly low, this typically means
059     * the object is far away and there's fewer total samples to derive
060     * the distance from. Set this value to be below the lowest strength
061     * you see when you're detecting an object with the CANrange; the
062     * default of 2500 is typically acceptable in most cases.
063     * 
064     * <ul>
065     *   <li> <b>Minimum Value:</b> 1
066     *   <li> <b>Maximum Value:</b> 15000
067     *   <li> <b>Default Value:</b> 2500
068     *   <li> <b>Units:</b> 
069     * </ul>
070     */
071    public double MinSignalStrengthForValidMeasurement = 2500;
072    
073    /**
074     * Modifies this configuration's ProximityThreshold parameter and returns itself for
075     * method-chaining and easier to use config API.
076     * <p>
077     * Threshold for object detection.
078     * 
079     * <ul>
080     *   <li> <b>Minimum Value:</b> 0
081     *   <li> <b>Maximum Value:</b> 4
082     *   <li> <b>Default Value:</b> 0.4
083     *   <li> <b>Units:</b> m
084     * </ul>
085     *
086     * @param newProximityThreshold Parameter to modify
087     * @return Itself
088     */
089    public final ProximityParamsConfigs withProximityThreshold(double newProximityThreshold)
090    {
091        ProximityThreshold = newProximityThreshold;
092        return this;
093    }
094    
095    /**
096     * Modifies this configuration's ProximityThreshold parameter and returns itself for
097     * method-chaining and easier to use config API.
098     * <p>
099     * Threshold for object detection.
100     * 
101     * <ul>
102     *   <li> <b>Minimum Value:</b> 0
103     *   <li> <b>Maximum Value:</b> 4
104     *   <li> <b>Default Value:</b> 0.4
105     *   <li> <b>Units:</b> m
106     * </ul>
107     *
108     * @param newProximityThreshold Parameter to modify
109     * @return Itself
110     */
111    public final ProximityParamsConfigs withProximityThreshold(Distance newProximityThreshold)
112    {
113        ProximityThreshold = newProximityThreshold.in(Meters);
114        return this;
115    }
116    
117    /**
118     * Helper method to get this configuration's ProximityThreshold parameter converted
119     * to a unit type. If not using the Java units library, {@link #ProximityThreshold}
120     * can be accessed directly instead.
121     * <p>
122     * Threshold for object detection.
123     * 
124     * <ul>
125     *   <li> <b>Minimum Value:</b> 0
126     *   <li> <b>Maximum Value:</b> 4
127     *   <li> <b>Default Value:</b> 0.4
128     *   <li> <b>Units:</b> m
129     * </ul>
130     *
131     * @return ProximityThreshold
132     */
133    public final Distance getProximityThresholdMeasure()
134    {
135        return Meters.of(ProximityThreshold);
136    }
137    
138    /**
139     * Modifies this configuration's ProximityHysteresis parameter and returns itself for
140     * method-chaining and easier to use config API.
141     * <p>
142     * How far above and below the threshold the distance needs to be to
143     * trigger undetected and detected, respectively. This is used to
144     * prevent bouncing between the detected and undetected states for
145     * objects on the threshold.
146     * <p>
147     * If the threshold is set to 0.1 meters, and the hysteresis is 0.01
148     * meters, then an object needs to be within 0.09 meters to be
149     * detected. After the object is first detected, the distance then
150     * needs to exceed 0.11 meters to become undetected again.
151     * 
152     * <ul>
153     *   <li> <b>Minimum Value:</b> 0
154     *   <li> <b>Maximum Value:</b> 1
155     *   <li> <b>Default Value:</b> 0.01
156     *   <li> <b>Units:</b> m
157     * </ul>
158     *
159     * @param newProximityHysteresis Parameter to modify
160     * @return Itself
161     */
162    public final ProximityParamsConfigs withProximityHysteresis(double newProximityHysteresis)
163    {
164        ProximityHysteresis = newProximityHysteresis;
165        return this;
166    }
167    
168    /**
169     * Modifies this configuration's ProximityHysteresis parameter and returns itself for
170     * method-chaining and easier to use config API.
171     * <p>
172     * How far above and below the threshold the distance needs to be to
173     * trigger undetected and detected, respectively. This is used to
174     * prevent bouncing between the detected and undetected states for
175     * objects on the threshold.
176     * <p>
177     * If the threshold is set to 0.1 meters, and the hysteresis is 0.01
178     * meters, then an object needs to be within 0.09 meters to be
179     * detected. After the object is first detected, the distance then
180     * needs to exceed 0.11 meters to become undetected again.
181     * 
182     * <ul>
183     *   <li> <b>Minimum Value:</b> 0
184     *   <li> <b>Maximum Value:</b> 1
185     *   <li> <b>Default Value:</b> 0.01
186     *   <li> <b>Units:</b> m
187     * </ul>
188     *
189     * @param newProximityHysteresis Parameter to modify
190     * @return Itself
191     */
192    public final ProximityParamsConfigs withProximityHysteresis(Distance newProximityHysteresis)
193    {
194        ProximityHysteresis = newProximityHysteresis.in(Meters);
195        return this;
196    }
197    
198    /**
199     * Helper method to get this configuration's ProximityHysteresis parameter converted
200     * to a unit type. If not using the Java units library, {@link #ProximityHysteresis}
201     * can be accessed directly instead.
202     * <p>
203     * How far above and below the threshold the distance needs to be to
204     * trigger undetected and detected, respectively. This is used to
205     * prevent bouncing between the detected and undetected states for
206     * objects on the threshold.
207     * <p>
208     * If the threshold is set to 0.1 meters, and the hysteresis is 0.01
209     * meters, then an object needs to be within 0.09 meters to be
210     * detected. After the object is first detected, the distance then
211     * needs to exceed 0.11 meters to become undetected again.
212     * 
213     * <ul>
214     *   <li> <b>Minimum Value:</b> 0
215     *   <li> <b>Maximum Value:</b> 1
216     *   <li> <b>Default Value:</b> 0.01
217     *   <li> <b>Units:</b> m
218     * </ul>
219     *
220     * @return ProximityHysteresis
221     */
222    public final Distance getProximityHysteresisMeasure()
223    {
224        return Meters.of(ProximityHysteresis);
225    }
226    
227    /**
228     * Modifies this configuration's MinSignalStrengthForValidMeasurement parameter and returns itself for
229     * method-chaining and easier to use config API.
230     * <p>
231     * The minimum allowable signal strength before determining the
232     * measurement is valid.
233     * <p>
234     * If the signal strength is particularly low, this typically means
235     * the object is far away and there's fewer total samples to derive
236     * the distance from. Set this value to be below the lowest strength
237     * you see when you're detecting an object with the CANrange; the
238     * default of 2500 is typically acceptable in most cases.
239     * 
240     * <ul>
241     *   <li> <b>Minimum Value:</b> 1
242     *   <li> <b>Maximum Value:</b> 15000
243     *   <li> <b>Default Value:</b> 2500
244     *   <li> <b>Units:</b> 
245     * </ul>
246     *
247     * @param newMinSignalStrengthForValidMeasurement Parameter to modify
248     * @return Itself
249     */
250    public final ProximityParamsConfigs withMinSignalStrengthForValidMeasurement(double newMinSignalStrengthForValidMeasurement)
251    {
252        MinSignalStrengthForValidMeasurement = newMinSignalStrengthForValidMeasurement;
253        return this;
254    }
255
256    
257
258    @Override
259    public String toString() {
260        String ss = "Config Group: ProximityParams\n";
261        ss += "    ProximityThreshold: " + ProximityThreshold + " m" + "\n";
262        ss += "    ProximityHysteresis: " + ProximityHysteresis + " m" + "\n";
263        ss += "    MinSignalStrengthForValidMeasurement: " + MinSignalStrengthForValidMeasurement + "\n";
264        return ss;
265    }
266
267    /**
268     * Get the serialized form of this configuration group.
269     *
270     * @return Serialized form of this config group
271     */
272    @Override
273    public final String serialize() {
274        String ss = "";
275        ss += ConfigJNI.Serializedouble(SpnValue.CANrange_ProximityThreshold.value, ProximityThreshold);
276        ss += ConfigJNI.Serializedouble(SpnValue.CANrange_ProximityHysteresis.value, ProximityHysteresis);
277        ss += ConfigJNI.Serializedouble(SpnValue.CANrange_MinSigStrengthForValidMeas.value, MinSignalStrengthForValidMeasurement);
278        return ss;
279    }
280
281    /**
282     * Take a string and deserialize it to this configuration group.
283     *
284     * @return Return code of the deserialize method
285     */
286    @Override
287    public final StatusCode deserialize(String to_deserialize) {
288        ProximityThreshold = ConfigJNI.Deserializedouble(SpnValue.CANrange_ProximityThreshold.value, to_deserialize);
289        ProximityHysteresis = ConfigJNI.Deserializedouble(SpnValue.CANrange_ProximityHysteresis.value, to_deserialize);
290        MinSignalStrengthForValidMeasurement = ConfigJNI.Deserializedouble(SpnValue.CANrange_MinSigStrengthForValidMeas.value, to_deserialize);
291        return  StatusCode.OK;
292    }
293
294    @Override
295    public ProximityParamsConfigs clone() {
296        try {
297            return (ProximityParamsConfigs)super.clone();
298        } catch (CloneNotSupportedException ex) {
299            /* this should never happen */
300            throw new RuntimeException(ex);
301        }
302    }
303}
304