Module 3: One Instant in a Drive
Predict
longitudinalPlan.longitudinalPlanSource in your capture reads e2e ("end-to-end" — the
driving model's own suggestion, as opposed to a classical control-theory solver reacting to a
tracked lead car). Before reading the code: if the source is e2e, do you expect
longitudinalPlan.aTarget to be a straight copy of whatever the model suggested, or something
else derived from it?
Run
Line up the five messages from your own capture into the order they were produced, each one naming which of the earlier ones it depends on:
| stage | message | depends on | key field(s), your capture |
|---|---|---|---|
| 1. perception | modelV2 |
camera frame | action.desiredAcceleration = 0.306, laneLineProbs = [0.56, 0.92, 0.39, 0.03] |
| 2. radar tracking | radarState |
can (radar returns) |
leadOne.status = False (no lead) |
| 3. planning | longitudinalPlan |
modelV2 + radarState + carState |
longitudinalPlanSource = e2e, aTarget = 0.306 |
| 4. control | carControl |
longitudinalPlan + carState |
longActive = True, actuators.accel = 0.277 |
| 5. state | selfdriveState |
driver + system events | state = enabled, active = True |
(cross-check: Log page)
Now check the claim from Predict against the actual planner code, selfdrive/controls/lib/longitudinal_planner.py:
output_a_target_e2e = sm['modelV2'].action.desiredAcceleration
output_should_stop_e2e = sm['modelV2'].action.shouldStop
if self.is_e2e(sm):
output_a_target = min(output_a_target_e2e, output_a_target_mpc)
self.output_should_stop = output_should_stop_e2e or output_should_stop_mpc
if output_a_target < output_a_target_mpc:
self.mpc.source = LongitudinalPlanSource.e2e
else:
output_a_target = output_a_target_mpc
self.output_should_stop = output_should_stop_mpc
(selfdrive/controls/lib/longitudinal_planner.py lines 160-170.) output_a_target_mpc, computed
two lines above this excerpt in the same function via get_accel_from_plan, comes from a
completely separate classical solver, LongitudinalMpc, which reacts to radarState's tracked
lead car and cruise speed — not to the model at all.
Observe
Your capture: modelV2.action.desiredAcceleration = 0.306, longitudinalPlan.aTarget = 0.306 —
identical, to three decimal places, not merely similar.
Explain
That equality isn't a coincidence and it isn't the model's value being copied through
unconditionally either: it's min(output_a_target_e2e, output_a_target_mpc) landing on the first
argument. The label longitudinalPlanSource = e2e doesn't mean "the plan is the model's opinion,"
it means "the model's suggestion was the more conservative of two independently computed
candidates, this cycle" — the code sets that label only if output_a_target < output_a_target_mpc.
There's a second, purely classical estimate, output_a_target_mpc, computed every cycle whether
or not it ends up winning, and the system always takes whichever of the two asks for less
acceleration. In this instant, since there was no lead car (radarState.leadOne.status = False)
and cruise was still well above current speed (33.528 vs. 27.209 m/s), the classical solver
had reason to accelerate harder toward the cruise target than the model did — so the model's more
conservative number won and got labeled e2e. A different instant, with a lead car close ahead,
would very plausibly flip which side wins, still under the exact same min(...) rule.
This is the same shape as Module 1's "the manager loop re-decides every iteration, not once at
boot": here too, the safer-looking label (e2e, evoking a single learned model driving the car)
turns out to name the outcome of a race between two independent estimates, computed every
cycle, rather than a mode switch the system committed to once.
Diagram: the message chain
Boxes are processes, arrows are the one message flowing between them relevant to this instant.
radard and plannerd are drawn as separate boxes because they are: radard doesn't plan
anything, it only turns raw CAN radar returns into a tracked radarState, and plannerd is the
one that reads both modelV2 and radarState to decide aTarget.
Quiz
- If the demo route had approached slow traffic (a real lead car close ahead), would you expect
output_a_target_mpcto go up or down relative to what you measured, and what effect would that have on which source labellongitudinalPlanreports? radarState.leadOne.statuswasFalsein your capture. Trace through themin(...)logic: does the absence of a lead car push the winning source towarde2eor away from it, and why?carControl.longActivewasTruein your capture even thoughcarState.gasPressedwasFalse. Module 4 covers exactly this signal in depth — for now, just from the message chain above, which upstream message would you check first to understand why longitudinal control was active at this instant?
Answer Key — Module 3
- Slow traffic close ahead makes the classical solver brake or hold back, so
output_a_target_mpcwould go down — likely negative if a real braking response were needed. Whether the source label flips depends on which of the two is now smaller: if the MPC solver's braking response is more conservative than whatever the model itself is suggesting, the MPC side would win instead, andlongitudinalPlanSourcewould no longer reade2efor that cycle. - Away from
e2e, not toward it, in a specific sense: with no lead car, the classical solver's job simplifies to "get to cruise speed," which especially below the cruise set point tends to ask for more acceleration, not less — exactly what you measured (cruise33.528 m/swell abovevEgo = 27.209 m/s). That makes the MPC side the more aggressive of the two, which is precisely why the more conservative model side won themin(...)and got labelede2ehere. A lead car appearing would give the MPC side a reason to be conservative too, making the outcome closer and harder to predict from cruise speed alone. selfdriveState, notlongitudinalPlan.longActiveiscarControl's own field, set bycontrolsdfromselfdriveState.active(whether the whole system is currently allowed to actuate) combined withlongitudinalPlan's output — but whether the system is active at all is a decisionselfdrivedmakes independently of any single plan, and that's exactly what Module 4 traces.