package aima.gui.swing.applications.robotics.simple;
import aima.core.robotics.impl.datatypes.Angle;
import aima.core.robotics.impl.datatypes.AbstractRangeReading;
import aima.core.util.Util;
/**
* A simple range reading that extends {@link AbstractRangeReading} by adding the range noise model.
*
* @author Arno von Borries
* @author Jan Phillip Kretzschmar
* @author Andreas Walscheid
*
*/
public final class SimpleRangeReading extends AbstractRangeReading {
private static double RANGE_NOISE;
private static double BAD_DELTA;
private static double SENSOR_RANGE;
/**
* Sets the noise model for all range readings.
* @param value the noise of the model.
*/
public static void setRangeNoise(double value) {
RANGE_NOISE = value;
}
/**
* Sets the delta between two range readings, above which a weight of zero is calculated.
* @param badDelta the worst acceptable delta.
*/
public static void setBadDelta(double badDelta) {
BAD_DELTA = badDelta;
}
/**
* Sets the sensor range that the virtual robot can measure at most.
* @param sensorRange the range of the robot's sensor.
*/
public static void setSensorRange(double sensorRange) {
SENSOR_RANGE = sensorRange;
}
/**
* Constructor for a range reading that has a zero angle.
* @param value the range reading.
*/
public SimpleRangeReading(double value) {
super(value);
}
/**
* Constructor for a range reading at a given angle.
* @param value the range reading.
* @param angle the angle of the range reading.
*/
public SimpleRangeReading(double value, Angle angle) {
super(value, angle);
}
/**
* Generates noise onto the range reading.
* @return a new range reading with noise applied.
*/
public AbstractRangeReading addRangeNoise() {
if(Double.isInfinite(getValue())) return this;
final double adaptedRangeReading = Util.generateRandomDoubleBetween(getValue() - RANGE_NOISE, getValue() + RANGE_NOISE);
return new SimpleRangeReading(adaptedRangeReading,getAngle());
}
@Override
public double calculateWeight(AbstractRangeReading secondRange) {
final AbstractRangeReading firstRange = addRangeNoise();
if(firstRange.getValue() < 0 || secondRange.getValue() < 0) return 0;
if(Double.isInfinite(firstRange.getValue()) && Double.isInfinite(secondRange.getValue())) return 1;
final double firstRangeValue;
if(Double.isInfinite(firstRange.getValue()) || firstRange.getValue() > SENSOR_RANGE) firstRangeValue = SENSOR_RANGE;
else firstRangeValue = firstRange.getValue();
final double secondRangeValue;
if(Double.isInfinite(secondRange.getValue()) || secondRange.getValue() > SENSOR_RANGE) secondRangeValue = SENSOR_RANGE;
else secondRangeValue = secondRange.getValue();
final double delta = Math.abs(firstRangeValue - secondRangeValue);
if(delta > BAD_DELTA) return 0.0f;
return (float) (1.0d - delta / BAD_DELTA);
}
}