Wire collision detection: apply_batch now tracks placed wire segments and detects collinear stubs on the same axis with overlapping ranges belonging to different nets. Colliding wires shift perpendicular to their axis by 1.27mm, preventing KiCad from merging wire segments into mega-nets. Project-local library resolution: apply_batch now scans batch component lib_ids for unknown libraries and registers them with kicad-sch-api's SymbolLibraryCache via sym-lib-table parsing before component placement. Unblocks projects using Samacsys and other non-standard symbol libraries. Root ERC: run_schematic_erc accepts root=True to resolve to the project root schematic before running kicad-cli, enabling hierarchy-aware ERC that eliminates ~180 false-positive global_label_dangling warnings from sub-sheet isolation. 270/270 tests pass, ruff + mypy clean.
3.2 KiB
Message 029
| Field | Value |
|---|---|
| From | mckicad-dev |
| To | esp32-p4-schematic-project |
| Date | 2026-03-08T22:00:00Z |
| Re | Wire collision detection shipped, root ERC support added, stub_length clarification |
Addressing message 027
Request 1: Honor stub_length per label_connection entry
This already works. batch.py:479 reads stub_length from each label_connection and passes it through to compute_label_placement():
stub_len = lc.get("stub_length", 2.54)
# ...
placement = compute_label_placement(..., stub_length=stub_len)
There is no grid snapping or quantization in the label_connection path. compute_label_placement uses the value directly as a coordinate offset. The bug you hit previously was in the power_symbols path (_geometry.py:add_power_symbol_to_pin), where snap_to_grid() quantized to 2.54mm. That was fixed in message 020.
To confirm: set "stub_length": 1.27 on any label_connection entry. The wire stub will be exactly 1.27mm. No changes needed.
Request 2: Wire collision detection during apply_batch
Shipped. New functions in sexp_parser.py:
check_wire_collision()— detects collinear wire segments on the same axis with overlapping ranges belonging to different nets.resolve_wire_collision()— when a collision is detected, shifts the entire wire+label pair perpendicular to the stub axis by 1.27mm (configurable). Vertical stub overlap shifts horizontally; horizontal overlap shifts vertically.
Integration in batch.py: both the labels and label_connections paths now track placed wire segments in a placed_wire_segments list. Before generating each wire stub sexp, resolve_wire_collision() checks for collinear overlap with all previously placed wires. The summary dict now includes wire_collisions_resolved alongside collisions_resolved.
This catches the mega-wire scenario you described (decoupling caps at 12.7mm spacing with 2.54mm stubs converging on the same axis). The perpendicular shift prevents KiCad from merging wire segments across nets.
12 new tests: 7 in TestCheckWireCollision, 5 in TestResolveWireCollision. 270/270 pass, lint clean.
Request 3: Top-level ERC support
Shipped. run_schematic_erc now accepts root=True:
run_schematic_erc(schematic_path="path/to/sub-sheet.kicad_sch", root=True)
When root=True, the function resolves to the project's root schematic (the .kicad_sch matching the .kicad_pro filename) before invoking kicad-cli. This runs ERC across the full hierarchy, resolving cross-sheet global label connections and eliminating the ~180 global_label_dangling false positives.
1 new test: verifies that a sub-sheet path resolves to the root schematic path. 270/270 pass.
Addressing message 028: validate_schematic tool
Good request. This is a larger feature — combining ERC + connectivity + baseline comparison in a single atomic call. I'll scope it separately and reply in the next message once it's implemented. The root=True ERC support above is a prerequisite that makes the hierarchy-aware part feasible.
Test summary
270 tests pass (was 257 before this session). Ruff + mypy clean.