Skip to content

Auto-packer pushes large chip off-board when group has many small siblings #2272

@gsdali

Description

@gsdali

Summary

When a <group pcbX={x} pcbY={y}> contains a large chip (e.g. a 12 ×
12 mm RF module) along with a handful of small siblings (decoupling
caps, pull-ups, etc.), the auto-packer can place the chip itself
many millimetres off-board
while the small siblings cluster around
the group anchor. The chip "falls off" instead of dominating the
group.

This was concretely reproducible on our project — an InsightSiP
ISP3080-UX 12×12 mm module landed at X=−56.91 on a 50 mm-wide board
(over 30 mm past the left edge) when its region_mcu group
contained ~10 children. Smaller chips (U_CHG DSBGA-8, U_BUCK
SOT-563, etc.) in groups with 3–5 siblings landed cleanly at the
group anchor in the same run.

Repro

<board width="50mm" height="14mm">
  <group name="region_mcu" pcbX={-18} pcbY={0}>
    {/* ~10 children competing for the anchor — chip is the largest
        but the packer pushes it out instead of pinning it to the
        anchor and packing the small parts around it. */}
    <chip name="U_RF" footprint={largeModuleFootprint /* 12×12 mm */} />
    <capacitor name="C7" capacitance="100nF" footprint="0402" />
    <capacitor name="C7b" capacitance="100nF" footprint="0402" />
    <capacitor name="C7c" capacitance="100nF" footprint="0402" />
    <resistor name="R_RST" resistance="10k" footprint="0402" />
    <resistor name="R_SDA" resistance="4.7k" footprint="0402" />
    <resistor name="R_SCL" resistance="4.7k" footprint="0402" />
    <switch name="SW_RST" />
    {/* etc. */}
  </group>
</board>

Expected: U_RF lands at (−18, 0) (group anchor); small siblings
pack around it with the configured pcbPackGap clearance.

Actual: U_RF ends up at e.g. (−56.91, −12.72) — off-board by
~32 mm — while several small siblings sit clustered at the group
anchor.

Diagnosis

Likely the largest_to_smallest ordering in calculate-packing's
PackSolver2 places U_RF first into the empty space, then small
parts shoulder it out of position when their candidate scores
prefer the anchor zone. The chip's "won" position is then a
candidate the next-iteration adjustment moves further away.

Workaround we ended up using: hand-pin the chip with explicit
pcbX/pcbY (chip then becomes static; small siblings pack around
it correctly). But that defeats the purpose of having an auto-placer.

Suggested investigation

  1. Reproduce in tscircuit/core tests with a board similar to the
    above and assert U_RF.center.x === -18 (or within a 1 mm
    tolerance).
  2. Trace why the chip gets displaced after initial placement —
    PackSolver2's iterative refinement looks like the most likely
    suspect.
  3. A simple guard: if a child's footprint is larger than 50 % of the
    group's free area, treat it as static (effectively force the user
    to place big-relative-to-group parts explicitly OR bias the
    packer to anchor them first and move only small parts around
    them).

Why it matters

Every board with a wireless module, a connector, or a similar
"dominant footprint" hits this. With the workaround the layout
becomes a chain of explicit pcbX/pcbY calls, which is what the
auto-placer is supposed to obviate.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions