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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions