Before a robot trusts its new range finder, an engineer points it at a wall exactly true_d metres away (measured with a tape) and logs a batch of readings. Two numbers describe the sensor:
- its bias: how far its readings are off on average,
mean - true_d(positive means it reads long); - its spread: the sample standard deviation of the readings, \sqrt{\sum (r - \bar r)^2 / (n - 1)}.
Now and then the sensor picks up a stray echo (a person walking past, a reflection from the floor). Such readings must not spoil the two numbers, so the engineer uses this rule:
- Find the median of all the readings (for an even count, the mean of the two middle values).
- A reading is an outlier when it differs from the median by more than
tolmetres. A reading exactlytolaway is kept. - Compute the bias and the spread from the kept readings only.
Write calibrate_range(readings, true_d, tol) that returns a tuple (bias, spread, outliers), where outliers is the list of the positions (indices) of the outliers in readings, in increasing order. If no reading is kept, bias is None; if fewer than two are kept, spread is None.
Examples
Input: readings = [2.04, 2.06, 1.98, 2.03, 3.10, 2.05, 2.01], true_d = 2.0, tol = 0.2
Output: (0.02833333333333332, 0.029268868558020272, [4])
Explanation: the median is 2.04, and 3.10 is 1.06 away from it. The six kept readings
average 2.02833, so the sensor reads 2.8 cm long, with a spread of 2.9 cm.
Input: readings = [1.52, 0.40, 1.47, 1.55], true_d = 1.5, tol = 0.1
Output: (0.01333333333333342, 0.040414518843273836, [1])
Explanation: the median is (1.47 + 1.52) / 2 = 1.495; the echo at 0.40 is dropped.
Input: readings = [5.0], true_d = 4.9, tol = 0.1
Output: (0.09999999999999964, None, [])
Constraints
- answers are compared with a tolerance of
1e-6; do not round
Goals
- Measure a sensor's bias against a known distance and its spread from repeated readings
- Use the median to spot stray readings that would spoil the mean
- Compute the sample standard deviation of the readings that remain