You are the referee. The provided car is driving its lap of gentle at 8 m/s, and at every step, twenty times a second, someone has to write down two numbers about it. One is how far along the road it has got, which decides when the lap is finished. The other is how far it is from the centre of its lane: the lateral error that Meet your car graded. The simulator has been the referee all along, and every grade in this course comes from its two numbers. This lesson is about how it gets them.
How far along the road is the car, and how far from its lane centre?
By the end you will write to_road_frame and lane_errors, two short functions that turn a position in the world into the road's own pair of coordinates. They will reproduce the simulator's lateral error and the heading ψ of Your first perception box at every one of the 1778 steps of a lap, with a difference of exactly zero.

Those are the referee's two numbers at one step: 159.011 m along the road, 0.528 m left of the lane centre. Neither is a world coordinate. In the world frame of Positions and headings the car's front axle is at x = 154.659 m, y = 19.854 m, and neither 159.011 nor 0.528 can be read off those two numbers. The rest of this lesson builds the road's coordinates, and the code that computes them, one step at a time.
The lateral error you would guess
The world frame's x axis runs along the road's first straight, its y axis to the left, and the car starts at (0, −1.8), on the lane centre and facing east. On that straight the lane centre is the line y = −1.8. So a first guess for the lateral error is
A car at y = −1.5 is 0.3 m north of the line y = −1.8, which on the first straight is 0.3 m to its left, and the guess says +0.3 m.
Guess first: over the whole lap, how far from the true does this guess get?

Answer: 163.6 m, on the far straight, 53.80 s in. On the first straight the guess is exact: it differs from the true by 0.0 m at every step up to 12.50 s. It goes wrong as soon as the road bends: 0.01 m out at 12.70 s, only 1.6 m into the bend, and 1 m out by 14.10 s. On the far straight it is absurd. At 45.00 s the car is at y = 161.55 m, the guess says it is 163.35 m left of its lane centre, and the true is 0.248 m.
The guess measures sideways along the world's y axis. That direction is the car's left only while the road points east. Once the road turns, its left turns with it. On the far straight the road runs back west, and the left of a car facing west is south, the direction of −y.
A cleverer guess fixes the lane centre's position. Instead of −1.8, subtract the y of the point of the lane centre nearest the car. It is still a difference of world y values, and it still fails.
Guess first: near the end of the first bend, where the road runs almost due west, will the cleverer guess be too big, too small, or the wrong sign?

Answer: the wrong sign. At 43.30 s the guess is −0.528 m while the car is +0.531 m left of its lane centre, 1.059 m apart, almost exactly twice . With the road running west, "more y" means further to the car's right, so the difference in y comes out with the sign flipped.
Both guesses fail for one reason: sideways is not a direction of the world. It has to be measured from the road itself, from the road's nearest point, at right angles to the road's direction there. To do that, you need the road written down.
In the simulator a road is a list of points along the middle of its yellow paint, the centreline. It is stored as an (N, 2) array named centerline, one row (x, y) per point, the layout of The view from the driver's seat. Joining each point to the next with a straight line gives a chain of short straight pieces, called a polyline. Each point is a vertex, and each straight piece between two neighbouring vertices is a segment.

gentle's centreline has 7028 vertices, between 0.099971 m and 0.1 m apart. It is closed: its last vertex joins back to its first, so it also has 7028 segments, and their lengths add up to 702.65 m. curvy is open: it has two ends, 2591 vertices and 2590 segments. The distance from the car to the road is its distance to the nearest point of one of these segments. So start with one segment.
Projecting onto a segment
Take one segment, from vertex to vertex , and a point . Which point of the segment is nearest , and how far away is it?
Work it with hand numbers: , and . The segment's arrow is . Its length, by Pythagoras, is . Divide the arrow by its length and you get an arrow 1 m long along the segment, , read "u-hat". It is a unit vector, like the heading arrow of Positions and headings: it is the heading arrow of someone standing at and facing .
Now ask, as Positions and headings did for a cone, how far ahead of that someone is, and how far to the left. The arrow from to is . Its forward part is a dot product with , and its left part a 2D cross product:
Guess first: where on the segment is the point nearest , and how far is from it?

Answer: 6 m along the segment from , at , and 3.0 m away, exactly the left part. Walking 6 m forward from brings you level with , and what is left is a step straight to the left.
That nearest point is called the foot, because the line from it to stands at a right angle on the segment, like a foot on the ground. Its distance along the segment from is written , read "tee", not the bold t of The view from the driver's seat. Here .
How we got: the foot is the nearest point
Every point of the segment's straight line is for some distance (the Greek letter tau, read "tau") along it from . Seen from that point, is further forward and still 3 to the left, because moving along never changes the left part. By Pythagoras its squared distance is
The never changes, and is smallest, zero, at . So the nearest point is the one level with , and its distance is the left part, 3. With any numbers, 6 is the forward part and 3 is the left part.
You have met this pair before. It is the driver's-seat view of The view from the driver's seat, for a driver standing at and facing along the segment. The segment's direction is atan2(6, 8) = 0.6435 rad, and world_to_ego((2, 1, 0.6435), p) gives (6, 3): ahead and 3 m to the left.
The rule has a flaw at the ends. Try a second point, :
The forward part, 12 m, is longer than the segment, 10 m.
Guess first: is really 4.0 m from the segment?

Answer: no. 4.0 m is the distance to (11.6, 8.2), a point on the segment's line 2 m past , where there is no road. The nearest point that is on the segment is its end , and is m from it. The rule needs one more step: clamp , which means cutting it to 0 if it is negative and to the segment's length if it is longer. In NumPy that is np.clip(t, 0, length). For , becomes , and the foot becomes .
A distance is never negative, so it cannot say which side is on. The left part can: it is −4.0, so is to the right of the segment's line. A helper, project_to_segment(a, b, p), returns two numbers: , and the distance from the point to its foot, with the sign of the left part. For it returns (6.0, +3.0); for it returns (10.0, −4.4721). Finding the foot is called projecting the point onto the segment.
Which segment, and which side
A road has thousands of segments, and each one gives the point its own foot. The road's nearest point is the nearest of all those feet. Try a small road of two segments, an L: from (0, 0) east to (10, 0), then north to (10, 10). Take , inside the corner.
Guess first: which segment's foot is nearer ?

Answer: the second. Its foot, (10, 3), is 2.0 m away, against 3.0 m for the first segment's foot at (8, 0). You do not need to know in advance which segment is nearest. Project the point onto every segment, then pick the smallest distance. The position of the smallest number in a list is called its argmin, read "arg min", and NumPy's np.argmin finds it. The second segment runs north, so its left is west, and is west of it: the left part is positive, and the point is 2.0 m to the left.
That signed distance from the nearest point of the centreline is the road's sideways coordinate. It is written , read "dee": metres to the left of the centreline, negative to the right. Careful: in Your first perception box, and were distances forward, from the car to the two lane-centre points ahead of it. This is sideways. On gentle, is the middle of the yellow line, your lane centre is m, and the white line is m.

Outside the corner the two segments tie. The point (12, −2) is 2.828 m from their shared vertex, which is the foot on both. Both give the same foot, so both give the same , −2.828 m. The last section comes back to ties.
On gentle there are 7028 segments. On the laptop that wrote this lesson, a Python loop that projected one position onto each segment in turn took between a twentieth and a tenth of a second, depending on what else the laptop was doing, so a lap of 1778 positions would take minutes. Written with whole (N, 2) arrays, the way Images are arrays did arithmetic on every pixel at once, the same steps on all 7028 segments took under a millisecond per position, a few hundred times faster. Your times will differ; the ratio is the point. The array version is the one the lab asks for.
How far along: arc length
The second coordinate says how far along the road the point is. Start at the first vertex of the centreline and walk along it, segment by segment, to the foot. The distance walked is the arc length to the foot, written , read "ess". It has two parts: the lengths of all the segments before the nearest one, added up, and , how far along the nearest one the foot is.

The total length of the segments before segment is written , read "s nought i". gentle's first straight is 1000 segments of exactly 0.1 m, so segment 1000, the first one of the bend, starts at m. NumPy's np.cumsum builds every running total in one call. Then
In the L, the first segment is 10 m long, so , 3 m along the second segment, has m, and its road coordinates are .
Guess first: at step 400, 20.00 s in, the car has driven 8 m/s × 20.00 s = 160 m. Is its more than 160 m, or less?

Answer: less. The nearest segment is number 1590, which starts at m, and the foot is m along it, so m while the car has driven 160.000 m. is measured along the yellow line. On a left bend your lane is on the outside of the turn, on a bigger circle: at step 400 the car is 81.2717 m from the bend's centre, (100, 80), while the yellow line is 80 m from it. Over the whole lap the car drives 710.80 m while runs from 0 to 702.65 m. The lane centre's own loop, two 100 m straights and a full circle of radius 81.8 m, is m long, and the car cuts slightly inside it on the bends.
gentle is a loop, and its last segment runs from the last vertex back to the first, so climbs to 702.65 m at the start line and starts again at 0 on segment 0. On a closed road is taken as the remainder after dividing by the road's length, s % 702.65, where % is Python's remainder; it only turns a foot exactly on the first vertex, = 702.65, into 0, and the graders accept either there. An open road like curvy needs no remainder, because the clamp at its two ends already keeps between 0 and its length.
That is your first function, to_road_frame(centerline, closed, p), returning (s, d).
Guess first: the world frame's grid lines are straight. Draw the lines of constant and of constant over the first bend. What shape are they?

Answer: they bend with the road. The rungs of constant point at the bend's centre, and every line of constant is a circle around it, 80 m minus from it: the car at step 400 has , and 80 + 1.2717 = 81.2717 m. In these coordinates your lane is a straight strip, from −3.6 to 0, all the way round the loop. The pair is the road frame: coordinates attached to the road, not to the world or to the car.
The simulator's tel.progress_m adds up the change in from each step to the next, and the lap counts as complete once the total reaches the road's length. This lap ends at 702.699 m, just past 702.65 m. Adding up changes across the start line needs care; the challenge problems ask how.
The two errors the controller needs
The lane centre is at , and is the distance to the left of the lane centre, so is just measured from −1.8 instead of from 0:
At step 400, m, so m: the car is 0.53 m left of its lane centre, toward the inside of the bend, as Meet your car found.
Guess first: the car is off the road once m. Which values of is that?

Answer: , over the yellow line, or , over the white line. Every maps to its by the same shift of 1.8 m.
The second error is the heading. Positions and headings gave the car's yaw , read "theta": where the car points, measured anticlockwise from east. The road has a direction too: the direction of the nearest segment, np.arctan2(dy, dx) for its arrow . Call it , read "theta road". θ is where the car points; ψ, the heading of Your first perception box, is the yaw minus the road's direction, wrapped with the wrap_angle of Positions and headings:
At step 400, rad and rad, so rad: the car points 0.034 rad, about 2°, to the right of the road.
Both errors are what a driver standing at the foot, facing along the road, would see. That driver's pose is the foot with the angle .

From that frame, world_to_ego puts the car at (, −1.2717). The first number is zero up to rounding, because the foot is level with the car by construction, and the second is . The road frame is the driver's-seat view taken from the road's nearest point, wherever the car is.
Is the wrap needed? and are both directions, and the car never points far from the road.
Guess first: leave out the wrap and take the plain difference . On how much of the lap is it wrong?

Answer: on 639 of the 1778 steps, 35.9 % of the lap, it is wrong by a whole turn, = 6.2832 rad. The simulator never wraps the car's yaw: it adds up each step's turn, and it ends the lap at rad, a whole turn less 0.057 rad. atan2, as Positions and headings showed, always answers between −π and π. At 56.95 s, as the road turns past due west, atan2's answer for the road jumps from near +π to near −π: rad while rad. Their plain difference is +6.3057 rad; wrapped, it is +0.0225 rad. From that step to the end of the lap the plain difference is a whole turn too big.
Your second function, lane_errors(centerline, closed, pose), takes the car's pose and returns . It finds the nearest segment the way to_road_frame does, then uses that one segment for both: its foot gives , and its direction gives .
Guess first: run both functions on every step of the provided car's lap. How close do they come to the simulator's own tel.lat and tel.head_err, its records of the true and ?

Answer: exactly. On all 1778 steps the largest difference is 0.0, for , , and alike. This is not an approximation of the referee: it is the referee's own measurement. The simulator does the same arithmetic in the same order, so the same numbers come out to the last bit.
Corners in the polyline
The simulator's centreline has a vertex every 0.1 m. Suppose instead you were handed the same road with a vertex only every 5 m. Two things change.
First, a shortcut that looked harmless stops working. Skip the segments: find the nearest vertex and use the distance to it as . On the simulator's 0.1 m centreline its worst error over the lap is 0.00098 m, under a millimetre.
Guess first: with a vertex every 5 m, how far out can the shortcut be?

Answer: by 1.550 m, at 43.30 s, with the car 1.27 m from the line. Projecting onto the 5 m segments is out by only 0.0391 m. The nearest vertex is not the nearest point. Midway between two vertices 5 m apart on a straight, the nearest vertex is 2.5 m along the road, so a car 1.8 m from the line is m from it, 1.281 m too far.
Second, even the segments miss. A straight segment between two points of a circle is a chord, and a chord cuts across the inside of the curve. The gap between a chord and its arc is largest at the chord's middle, and that largest gap is called the sagitta, read "SAJ-it-uh", Latin for arrow. For a chord of length on a circle of radius it is about

How we got c² / (8R)
Your first perception box found that a circle of radius curves away from a straight line by about at metres ahead. In this lesson is sideways, so write for the distance ahead: the curve-away is .
Stand at the middle of the arc, facing along it. The chord runs parallel to your direction, and its two ends are ahead and behind you. At the circle has curved away by
Both ends of the chord sit that far from your line, so the straight chord between them passes from the arc's middle. For m and m it is m.
Guess first: at 1 m and 10 m spacing, will projecting onto segments still miss by exactly the sagitta?

Answer: yes, to four decimal places. Projection misses by 0.0016, 0.0391 and 0.1562 m at 1, 5 and 10 m, and gives the same three numbers. The formula is an approximation, but here it is good to four decimals. The shortcut is 61 times worse at 1 m, 40 times at 5 m and 25 times at 10 m.
For the simulator's own 0.1 m segments the sagitta is m, 16 millionths of a metre. That is why straight segments are good enough to describe a round road. It is also the geometry behind the chord bias of Your first perception box: there the box's chord was metres long, so it cut far inside the bend.

One case is left. Sometimes the nearest point of the road is a vertex, shared by two segments, and both segments' feet are that same point. On the lap that happens at 22 of the 1778 steps, 1.2 %; at 20 of them the two segments point in different directions, and the other 2 are on straights. is the same either way, but is the direction of whichever segment you pick, and neighbouring segments on gentle's bends differ by one corner angle, rad. The simulator keeps the first of the tied segments. The steps in this lesson, done in the same order, keep the same one, and match it exactly. Keeping the last tied segment instead is 0.00125 rad off on those 20 steps. The graders accept either tied segment.
Recap
- Sideways is measured from the road, not along a world axis. is exact on the first straight and 163.6 m wrong on the far straight.
- Projecting onto a segment: is the forward part, clamped to the segment, and the signed distance to the foot takes the left part's sign. The nearest foot over all segments wins.
- The road frame : is the arc length along the yellow line, the signed distance from it. and reproduce the simulator's
latandhead_errexactly. - On a sparse polyline, use segments, not vertices; even segments miss a bend by about .

In a tunnel the GPS goes quiet. The car can still count its wheels' turns and read its own steering angle, so at every step it knows how far it moved and how much it turned since the last step, in its own frame. It has nothing else. If the car knows only how it moved since the last step, can it still know where it is?
That is the next lesson, Poses you can chain.
Challenge problems
Optional. The first is hard; all three use only this lesson and the ones before it.
- The lane centre from the driver's seat. On
gentle's first bend, at = 260 m, put the car 0.3 m left of its lane centre () and pointing 0.04 rad left of the road (). Seen in the ego frame, how far to the left is the lane centre at metres ahead?- (a) Show that for small it is about , where = 81.8 m is the lane centre's radius. Use the curve-away from Your first perception box and a rotation by a small angle from The view from the driver's seat.
- (b) The true values, from
world_to_egoapplied to the simulator's lane centre, are −0.3469, −0.0874, +1.3653 and +4.1277 m at = 5, 10, 20 and 30 m. Compute the quadratic and the straight line at each . Roughly where is each first 0.1 m out?

- Progress across the start line. The last two steps of the lap have = 702.306 m and then = 0.045 m.
- (a) What does the plain difference say the car moved in that step?
- (b) Wrap the difference the way wrap brings an angle into one turn, but into , where = 702.655 m is the road's length to one more decimal. What do you get, and why is it a little less than the 0.40 m that one step at 8 m/s covers?
- (c) How fast would the car have to go for this wrap to give the wrong answer?
- Why the shortcut is worst near the line. On a straight road with a vertex every 5 m, put a point midway between two vertices, from the line. Show that the nearest-vertex shortcut is out by , and evaluate it at = 3.6, 1.8, 1.0 and 0.5 m. Is a car near the line or far from it hurt more?
Answers
(a) Stand at the lane-centre point level with the car, facing along the road. A point of the lane centre ahead along the road has curved to the left, and the car is to the left of where you stand. So from a frame at the car pointing along the road, the lane centre ahead is about to the left. The car's own frame is turned further left. The view from the driver's seat gives the left part of an arrow seen from a frame turned by as , which for a small angle is about . Together: .
(b) The quadratic gives −0.3472, −0.0888, +1.3450 and +4.0012 m, out by 0.0003, 0.0013, 0.0203 and 0.1265 m. The line gives −0.5, −0.7, −1.1 and −1.5 m, out by 0.1531, 0.6126, 2.4653 and 5.6277 m. The quadratic is first 0.1 m out at 28.49 m; the line already at 4.05 m. The line ignores the bend, and the bend's grows fast.
(a) m: the car would have driven most of a lap backwards in 0.05 s.
(b) Adding brings the difference into range: m (+0.3936 m before rounding). It is less than 0.40 m because the car is on the second bend, on the outside of the yellow line, and is measured along the yellow line, which is the shorter circle.
(c) The wrap gives the wrong answer only if one step moves more than = 351.3 m, which at 0.05 s per step is 7027 m/s.
The nearest vertex is 2.5 m along the road and across, so by Pythagoras it is away, while the road is away. At 3.6, 1.8, 1.0 and 0.5 m the error is 0.783, 1.281, 1.693 and 2.050 m. A car near the line is hurt more: as shrinks toward 0 the error grows toward the whole 2.5 m.