A museum guide robot localises itself among round pillars whose positions are known: landmarks[j] = (lx, ly) (metres, x to the right, y up). Its belief is a mean mu = (x, y, theta) (heading in radians, counter-clockwise from +x) and a 3 by 3 covariance P. Each entry of steps is a tuple (v, w, readings): a commanded speed v and turn rate w held for dt seconds, then a list of readings (r, b), each a range and a bearing (from the heading, counter-clockwise positive, in (-\pi, \pi]) to some pillar; the sensor does not say which one, and some readings are reflections that match none.
For each step:
- Predict. Euler step along the old heading: x' = x + v\,dt\cos\theta, y' = y + v\,dt\sin\theta, \theta' = \theta + w\,dt; covariance P' = G P G^T + Q, with G the Jacobian of this step with respect to (x, y, \theta) at the old mean.
- Each reading, in the given order, using the mean and covariance as they are at that moment (after the previous readings of the step):
- for every pillar
j: the expected range \hat{r} = \sqrt{\Delta x^2 + \Delta y^2} and bearing \hat{b} = \operatorname{atan2}(\Delta y, \Delta x) - \theta with \Delta x = l_x - x, \Delta y = l_y - y; the innovation \nu = (r - \hat{r},\ b - \hat{b}) with the bearing part wrapped to (-\pi, \pi]; the 2 by 3 Jacobian H of (\hat{r}, \hat{b}) with respect to (x, y, \theta); S = H P H^T + R; and the squared Mahalanobis distance \nu^T S^{-1} \nu; - the reading belongs to the pillar with the smallest such distance among those at most
gate(ties: the lowest index). If there is none, skip the reading; - otherwise apply the EKF update with that pillar: K = P H^T S^{-1}, \mu \leftarrow \mu + K\nu, P \leftarrow (I - K H)P.
- for every pillar
- Record the mean.
Keep every heading wrapped to (-\pi, \pi]. Write ekf_localize(mu, P, landmarks, steps, dt, Q, R, gate) that returns a tuple (means, matches): the recorded means, one list [x, y, theta] per step, and for each step the list of matched pillar indices, one per reading (-1 for a skipped reading). numpy is available.
The setup provides museum_run(T, seed), which returns the arguments of a simulated T-step tour among six pillars (with a reflection now and then), so ekf_localize(*museum_run(40, 7)) runs your filter on it. Press Run with plot(xs, ys) of your means to see the tour.
Examples
Input: mu = (0, 0, 0), P = [[0.01, 0, 0], [0, 0.01, 0], [0, 0, 0.01]], landmarks = [(5, 0), (0, 5), (5, 5)],
steps = [(1.0, 0.0, [(3.955, 0.025), (6.325, 0.922)]),
(1.0, 0.5, [(5.41, 1.443), (2.0, -2.5)]),
(1.0, 0.5, [(2.151, -1.293), (4.898, 0.127)])],
dt = 1.0, Q = [[0.002, 0, 0], [0, 0.002, 0], [0, 0, 0.001]], R = [[0.01, 0], [0, 0.0025]], gate = 9.21
Output: ([[1.039637388581427, 0.013459062760948642, -0.020270454841982755],
[2.035219843542808, -0.008717509477236065, 0.4947812423815255],
[2.928953332283443, 0.5325428297976338, 1.01808779168252]],
[[0, 2], [1, -1], [0, 2]])
Explanation: after the first prediction the robot expects pillar 0 at range 4, bearing 0; the reading
(3.955, 0.025) is 0.12 from it in squared Mahalanobis distance and over 200 from the others.
The reading (2.0, -2.5) in the second step fits no pillar and is skipped.
Input: mu = (0, 0, 3.1), P = [[0.02, 0, 0], [0, 0.02, 0], [0, 0, 0.02]], landmarks = [(-4, 0.2), (3, 0)],
steps = [(0.5, 0.0, [(3.52, 3.14), (3.47, 0.05)])], dt = 1.0, the same Q and R, gate = 9.21
Output: ([[-0.5191334941702317, 0.12444447122557009, 3.086925641508269]], [[1, 0]])
Explanation: pillar 1 is behind the robot: expected bearing -3.106, measured 3.14. The
difference wraps to -0.037, a close match.
Constraints
P,QandRare symmetric covariances (Rpositive definite);dt > 0;gate > 0- no pillar is ever within
0.1m of the robot's mean position - answers are compared with a tolerance of
1e-6; numpy arrays or tuples are accepted in place of lists
Goals
- Run an EKF localizer end to end: predict with the odometry, then update with every reading
- Decide which pillar each unlabeled reading belongs to by Mahalanobis distance in measurement space
- Ignore readings that fit no pillar, and keep the updates in order within a step