Source Listings
Full text of every standalone snippet this workshop runs, so nothing you're asked to run is
hidden off-page. Each was written only to run in this workshop (not shipped as part of
sunnypilot itself) and lives under snippets/ in this workshop's own directory.
process_inventory.py
Run with: python3 sunnypilot-architecture/snippets/process_inventory.py (no live publisher
needed — this one only imports the process registry and evaluates its condition functions
statically). Cited from Module 1; output on the Log page.
1 # Standalone, self-contained snippet -- not part of manager.py.
2 # Statically evaluates every registered process's condition function to see
3 # which processes would run offroad vs onroad, without ever starting a process
4 # or touching hardware.
5 from cereal import car
6 from openpilot.common.params import Params
7 from openpilot.system.manager.process_config import managed_processes
8
9 params = Params()
10 CP = car.CarParams.new_message()
11
12 offroad = [n for n, p in managed_processes.items() if p.enabled and p.should_run(False, params, CP)]
13 onroad = [n for n, p in managed_processes.items() if p.enabled and p.should_run(True, params, CP)]
14
15 print(f'total registered: {len(managed_processes)}')
16 print(f'enabled on this machine: {sum(p.enabled for p in managed_processes.values())} / {len(managed_processes)}')
17 print(f'would run OFFROAD (started=False): {len(offroad)}')
18 print(sorted(offroad))
19 print()
20 print(f'would run ONROAD (started=True): {len(onroad)}')
21 print(sorted(onroad))
22 print()
23 onroad_only = sorted(set(onroad) - set(offroad))
24 print(f'onroad-only ({len(onroad_only)}):', onroad_only)
dump_msgs.py
Run with: python3 sunnypilot-architecture/snippets/dump_msgs.py against a live publisher, e.g.
./tools/replay/replay --demo --no-vipc -c 3 -s 45 & in another terminal first. Cited from
Module 2 and Module 3; output on the
Log page.
1 # Standalone, self-contained snippet -- not part of any daemon.
2 # Subscribes to the live cereal pub/sub bus and prints a curated set of
3 # fields from each message the moment it first arrives.
4 #
5 # Run against a live publisher, e.g. in another terminal:
6 # ./tools/replay/replay --demo --no-vipc
7 # then, with the same venv active:
8 # python3 sunnypilot-architecture/snippets/dump_msgs.py
9 import time
10 import cereal.messaging as messaging
11
12 sm = messaging.SubMaster(['carState', 'modelV2', 'longitudinalPlan', 'radarState', 'selfdriveState', 'carControl'])
13
14 deadline = time.monotonic() + 15
15 seen = set()
16 while time.monotonic() < deadline and len(seen) < 6:
17 sm.update(100)
18 for k in sm.data.keys():
19 if sm.updated[k] and k not in seen:
20 seen.add(k)
21 print(f"=== {k} (valid={sm.valid[k]}) ===")
22 if k == 'carState':
23 cs = sm[k]
24 print(f" vEgo={cs.vEgo:.3f} m/s gasPressed={cs.gasPressed} "
25 f"cruiseState.speed={cs.cruiseState.speed:.3f} standstill={cs.standstill}")
26 elif k == 'carControl':
27 cc = sm[k]
28 print(f" latActive={cc.latActive} longActive={cc.longActive} "
29 f"cruiseControl.override={cc.cruiseControl.override} "
30 f"actuators.accel={cc.actuators.accel:.3f} actuators.curvature={cc.actuators.curvature:.5f}")
31 elif k == 'selfdriveState':
32 ss = sm[k]
33 print(f" state={ss.state} enabled={ss.enabled} active={ss.active} "
34 f"alertType={ss.alertType!r}")
35 elif k == 'modelV2':
36 mv = sm[k]
37 print(f" frameId={mv.frameId} laneLineProbs={[round(p, 3) for p in mv.laneLineProbs]} "
38 f"leadsV3[0].prob={mv.leadsV3[0].prob:.3f} action.desiredAcceleration={mv.action.desiredAcceleration:.3f}")
39 elif k == 'longitudinalPlan':
40 lp = sm[k]
41 print(f" longitudinalPlanSource={lp.longitudinalPlanSource} aTarget={lp.aTarget:.3f} "
42 f"hasLead={lp.hasLead} speeds[0]={lp.speeds[0]:.3f} speeds[-1]={lp.speeds[-1]:.3f}")
43 elif k == 'radarState':
44 rs = sm[k]
45 print(f" leadOne.status={rs.leadOne.status} leadOne.dRel={rs.leadOne.dRel:.3f}")
46 print()
47
48 print("seen:", seen)
dump_state_transitions.py
Run with: python3 sunnypilot-architecture/snippets/dump_state_transitions.py against a live
publisher played faster than real time, e.g.
./tools/replay/replay --demo --no-vipc -c 5 -x 3 --no-loop &. Cited from
Module 4; output on the Log page.
1 # Standalone, self-contained snippet -- not part of any daemon.
2 # Watches selfdriveState.state over time and prints every transition,
3 # together with the carState/carControl context that likely caused it.
4 #
5 # Run against a live publisher, e.g. in another terminal:
6 # ./tools/replay/replay --demo --no-vipc -x 3
7 # then, with the same venv active:
8 # python3 sunnypilot-architecture/snippets/dump_state_transitions.py
9 import time
10 import cereal.messaging as messaging
11
12 sm = messaging.SubMaster(['selfdriveState', 'carState', 'carControl'])
13
14 last_state = None
15 deadline = time.monotonic() + 45
16 transitions = 0
17 while time.monotonic() < deadline and transitions < 8:
18 sm.update(100)
19 if not sm.valid['selfdriveState']:
20 continue
21 state = str(sm['selfdriveState'].state)
22 if state != last_state:
23 transitions += 1
24 cs = sm['carState']
25 cc = sm['carControl']
26 print(f"[{transitions}] state -> {state} "
27 f"(gasPressed={cs.gasPressed}, vEgo={cs.vEgo:.2f}, "
28 f"latActive={cc.latActive}, longActive={cc.longActive}, "
29 f"alertType={sm['selfdriveState'].alertType!r})")
30 last_state = state
31
32 print("done, transitions:", transitions)