Pages and contents

Docs
Skills
Subagents
Lessons (pitfalls)
Research

Docs · docs/compliant.md · Markdown

Snap fits and compliant features

cadagent.mechanical.compliant sizes and checks snap-fit joints so an agent does not re-derive the equations, guess a permissible strain or forget layer lines. It is the calculator half of the compliant-mechanism work (#94); the method, sources and open questions are in research/compliant-mechanisms.md.

Why it is built, not adopted. The survey of 2026-10-31 (research/agent-toolkits-2026-10.md) found agent skills for snap fits (static74/3dp-compliant-mechanisms, the AgentCAD snap-fits skill) but they are prompts only: no calculator and no tests against the design guides' worked examples, and static74's printed strain limits are about twice those the filament datasheets support. This module is tested against the guide's own examples, and every material value names its source.

What it does

  • Cantilever, torsion and annular snaps by the closed-form method of the Covestro (formerly Bayer) guide Snap-Fit Joints for Plastics – A Design Guide: permissible deflection from strain, thickness for a target deflection, deflection force from the secant modulus, mating and separation force from friction and the lead and return angles, the torsion-bar and annular-joint relations. Rectangular and ring-segment sections (the guide's Example II section is computed exactly).
  • Deterministic pass/fail rows for a declared snap: root strain against the allowable, root radius (at least 0.38 mm; R/h below 0.6 concentrates strain), mating force against a limit, retention force against a minimum.
  • Allowable strain with its source: moulded resins from the Covestro Table 2 and DuPont Table 10.06; 11 printed filaments (13 entries: two have dry and wet values) from their manufacturers' data sheets by print direction (allowables.py).
  • Along the insertion: engagement() gives the root strain and the push to mate as the mating edge rides the hook's lead, slides along its land and drops off (a snap engaging).
  • Figures: tools/snapfit_figures.py draws the cantilever with its dimensions, and tools/readme_anim.py animates one engaging (docs/img/compliant/).

Example I from the Covestro guide, computed: a tapered polycarbonate cantilever hook with its length, thicknesses and deflection drawn to scale, root strain 2.00 percent

Example I of the Covestro guide (polycarbonate, tapered hook), drawn by tools/snapfit_figures.py from the module's own result: the arm length, root thickness and undercut are the guide's inputs; the 2.00 % root strain and the forces are computed by the module, not typed in.

Declaring snaps

# snaps.yaml: cad-agent snapfit snaps.yaml --output exports/snap-checks.json
snaps:
  - name: lid-latch
    material: copa-polymaker-dry   # a printed filament: orientation decides the allowable
    orientation: along             # bending stress along the layers (arm lies in XY); 'across' = arm built along Z
    repeated: true                 # opened and closed often: 60 % of the single-joining strain
    length_mm: 14
    undercut_mm: 0.5
    design: 1                      # 1 constant section, 2 thickness tapered to h/2, 3 width tapered to b/4
    section: {rect: {width_mm: 6, thickness_mm: 1.6}}
    root_radius_mm: 0.8
    lead_deg: 30
    return_deg: 45
    max_mating_n: 30
  - name: example-I                # the guide's Example I, moulded polycarbonate
    material: pc
    process: moulding
    length_mm: 19
    undercut_mm: 2.4
    design: 2
    section: {rect: {width_mm: 9.5, thickness_mm: 3.28}}
    lead_deg: 30
    return_deg: 90
    root_radius_mm: 1.0

cad-agent snapfit FILE prints one PASS/FAIL line per snap with the root strain, the allowable and the forces, and any warnings. It exits 0 if every check passes, 1 if any fails and 2 for an unreadable or out-of-range file (the message names the snap and the field). --output writes every row, the material derivation and the limits as JSON.

Fields:

  • Required: name, material (a name below, or {name, strain, source, secant_mpa, friction} with strain a fraction: 0.03 = 3 %), length_mm, undercut_mm, section (rect: {width_mm, thickness_mm} or ring: {r_inner_mm, r_outer_mm, arc_deg, tension}), root_radius_mm, and process (moulding, fdm, sla, sls or mjf; a printed filament implies fdm).
  • Optional: design (default 1), repeated, share (0.5 when both parts flex equally), secant_mpa, friction, same_material, lead_deg, return_deg, max_mating_n, min_retention_n.
  • Layered processes: a printed filament needs orientation (along or across the layers). Any other material in a layered process needs orientation, process_factor (0–1: a derating) and process_source.

Nothing passes unchecked. A missing process, orientation, derating or root radius is a failing row. A declared max_mating_n or min_retention_n that cannot be computed fails and names what is missing: no secant modulus (only pc has guide points; give secant_mpa otherwise), no friction (PLA and PETG are not in the guide's table) or no angle. A self-locking hook (μ·tan α ≥ 1, e.g. a 90° return) cannot be pulled apart, so its retention is the hook's own strength, which this method does not compute: a declared retention minimum fails there. Where the guide gives secant-modulus points, the modulus is interpolated at the arm's actual root strain.

Materials

Moulded (permissible strain for one joining; frequent use in brackets): Covestro Table 2 — pc 4 % (2.4), pc-high-heat 4 %, pc-abs 2.5 % (1.5), pc-blend 3.5 %, pc-gf10 2.2 %, pc-gf20 2.0 %. DuPont Table 10.06 — pom-delrin-100 8 % (2), pom-delrin-500 6 % (2), pa66-dry 4 % (2), pa66-50rh 6 % (3), pa66-gf-dry 0.8 % (0.5), pa66-gf-50rh 1.5 % (1.0), pet-gf 1 % (0.5), pbt-gf 1.2 % (0.6), tpc-hytrel 20 % (10). Where DuPont gives a range the lower end is used.

Printed, single joining, along / across the layers (derived from the datasheet; ×0.6 for frequent use):

Name Along Across Name Along Across
pla-polymaker 1.1 % 0.9 % asa-polymaker 1.3 % 0.8 %
pla-bambu-basic 0.95 % 0.95 % asa-bambu 1.06 % 1.02 %
pla-bambu-matte 1.07 % 0.92 % copa-polymaker-dry 2.0 % 0.65 %
petg-polymaker 1.7 % 1.6 % copa-polymaker-wet 3.3 % 0.85 %
petg-bambu-basic 1.28 % 0.96 % pa6-cf20-polymaker-dry 0.8 % 0.8 %
petg-bambu-hf 1.3 % 1.0 % pa6-cf20-polymaker-wet 1.5 % 1.5 %
petg-cf-bambu 1.0 % 1.0 %

The rule, per direction: min(0.7 × UTS / E, 0.5 × elongation at break) — the guide's 70 %-of-yield rule for amorphous resin with UTS/E as a lower bound on the yield strain, and its half-the-elongation rule for materials without a yield point. Across the layers the smaller of the Z and XY values is used. Nylon is capped at the moulded value of its family: CoPA at PA66 (the cap never binds), carbon-filled PA6 at DuPont's glass-filled PA66 (0.8 % dry, 1.5 % at 50 % RH; both bind, from derived 0.89 % and 1.53 %). The "wet" rows are water-saturated datasheet specimens. The direction matters more than strength suggests: across the layers the PLA, PETG, ASA and CoPA datasheets keep 40–89 % of the in-plane strength but only 10–61 % of the elongation at break, and snap fits are limited by strain. (Polymaker's carbon-filled PA6 keeps 90–96 % of its elongation: the fibre already limits it in-plane.)

Which data-sheet edition each value comes from (#156)

Makers reissue their sheets. Bambu's current V3.0 sheets, served from its store, give lower strengths than the V2.0 copies resellers still serve: PETG-CF's tensile strength falls from 59 / 38 MPa to 35 / 29 MPa, so its allowable falls from 1.7 % to 1.0 %. V3.0 PETG Basic is a reformulated filament sold under the same name, and a spool does not say which it is. So every edition read is kept, each as a complete set of values, and the cautious one is taken per quantity:

  • allowable strain: the lowest any edition gives;
  • mating force: from the highest modulus any edition gives, so it stays an upper bound;
  • retention force: from the lowest, since a softer arm holds less. It is still optimistic: the secant modulus at the design strain is below every sheet's tensile modulus.

The root strain at a given deflection does not depend on E. petg-bambu-basic takes its allowable and its mating modulus from V3.0 (1.28 / 0.96 % and 2780 / 2550 MPa; V2.0 would allow 2.3 %) and its retention modulus from V2.0 (1460 / 1120 MPa). pla-bambu-basic takes its allowable and retention modulus from V3.0 and its mating modulus from V2.0 (2680 / 2160 MPa, 4–5 % above V3.0's). The --output JSON names the edition behind each number (xy.sheet, z.sheet, modulus.mating.sheet, modulus.retention.sheet), and research/compliant-mechanisms.md §5 and §10 list every sheet with its date and link.

What this costs in allowable strain depends on which limit governs. Across the layers the allowable is 75–100 % of the in-plane value for PLA and PETG, 97 % for Bambu ASA, 64 % for Polymaker ASA and 26–32 % for CoPA, where half the elongation at break governs: 2.0 % with the arm lying in the bed plane against 0.65 % built upright. Layer lines also act as notches, which no tensile test shows, so lay flexing arms in the bed plane whatever the numbers say.

Try it: the snap-arm explorer

Size a rectangular cantilever arm and see where it fails. The arm bends along its computed curve, coloured by strain. The panel shows the root strain, the force at the hook and pass or fail against the filament's allowable strain for the print direction you choose. The default arm is CoPA laid flat on the bed, and it passes at 44 % of its allowable. Print the same arm upright and it fails at 138 %.

Snap-arm explorer, before its controls load: a CoPA arm 20 mm long, 1.6 mm thick at the root and 6 mm wide, bent 1.5 mm at the hook along its computed curve; root strain 0.90 %, 44 % of the 2.02 % allowed along the layers, a pass; force 3.10 N

The numbers come from cadagent.formulas.snap_arm, which uses the Covestro method exactly as cad-agent snapfit does. The browser runs a port of it that is tested against the Python on shared vectors (see Engineering formulas). The curve is the exact small-deflection shape for the section you choose.

  • Force. It uses the datasheet modulus, which is higher than the secant modulus at the design strain, so the force shown is an upper bound.
  • Small deflection. When the deflection passes a tenth of the length, the verdict says so: the arm is then outside small deflection.
  • Root radius. The explorer does not check the root radius. cad-agent snapfit does.

Try it: the torsion-snap explorer

A torsion snap is a lever on a bar that twists instead of bending, like the guide's rocker on two bars (its Fig. 21). The bar's peak shear strain is in the middle of its long sides. The default is a PLA rocker on two 15 mm bars: pressed 8°, it uses 86 % of its allowable, and it fails past 9.3°.

Torsion-snap explorer, before its controls load: two bars of Bambu PLA Basic, each 15 mm long, 4 × 1.2 mm, twisted 8° by a 10 mm lever; peak shear strain 1.11 %, 86 % of the 1.28 % allowed across the layers, a pass; 3.45 N at the lever

Try these: one bar halves the force (1.73 N) at the same strain; a 30 mm bar halves both; opened often it fails at 144 %; PETG (Polymaker) passes at 52 %, and CoPA fails at 126 %, since its strain across the layers is low.

The numbers come from cadagent.formulas.torsion_snap_bar: Saint-Venant torsion of a rectangle (Roark, Table 10.1) and the guide's allowable shear strain, (1 + ν) ε with ν = 0.35 (Section C).

  • Across the layers, always. However the bar lies, it shears its layer interfaces at 74 to 100 % of the peak (lying flat, its short sides do), so the check uses the filament's allowable across the layers.
  • Force. From the highest datasheet modulus, so at small twist it is an upper bound. The lever is taken as rigid.
  • Small twist. Twisted far, a wide thin bar's edges stretch along it (the trapeze effect), which stiffens it and strains its edges. The explorer warns when that would add more than a tenth to the torque: a 30 × 12 × 0.6 mm bar at 30° gains 41 %, with 0.37 % strain along its edges, which the check leaves out.
  • Short bars. The ends are taken as free to warp. A short bar held at both ends is stiffer and more strained near them than this says.

A snap engaging, computed

One printed arm, laid flat on the bed, in two filaments. As the mating part's edge rides the hook's lead, the arm bends and its root strain rises. The same strain passes in one filament and fails in the other.

A printed snap arm 15 mm long, 1.6 by 6 mm, bends as a mating part's edge rides its hook's 30° lead over a 1.3 mm undercut. Its root strain rises to 1.38 %: 68 % of the 2.02 % allowed for Polymaker PolyMide CoPA (dry), a pass, and 139 % of the 1.00 % allowed for Bambu PETG-CF, a fail. The push to mate peaks at 10.1 N for CoPA on CoPA

The toolkit's closed-form calculator (cadagent.mechanical.compliant.snapfit, the Covestro method) on the stated arm, animated by tools/readme_anim.py: not a measurement. Allowables from the data sheets Polymaker PolyMide CoPA V5.4 and Bambu Lab PETG-CF V3.0. Printed snaps need a test print.

  • Strain is geometry. At a given deflection the root strain depends only on the arm (ε = y h / 0.67 L²). The filament sets the allowable. PETG-CF's V3.0 sheet allows 1.00 % (its V2.0 sheet, 1.7 %): this arm goes over it 1.63 mm up the 2.25 mm lead, before the hook clears.
  • The push. snapfit.engagement() gives it along the travel. Up the lead it rises to the guide's W = P (μ + tan α) / (1 − μ tan α), 10.1 N for CoPA. That μ, 0.525, is the guide's PA value for the plastic on itself (same_material, the default), so the mating part is CoPA too; against steel (same_material: false) it is 0.35. On the land only friction resists (μ P), and then the hook drops. PETG is not in the guide's friction table, so PETG-CF gets no push force; declare friction to get one.
  • The drawing. It is at true scale, the arm bent along its computed curve. It turns the hook with the arm's tip, as a real hook turns; the closed form, like the guide, does not. So the drawn edge tops the lead after 1.95 mm of travel, not 2.25 mm, and there it rides a face turned 7.4°: at 37.4°, not 30°. On that face the guide's formula gives CoPA a push of 13.7 N, not 10.1 N. Near the top of a steep lead, or on a short arm, the closed form under-states the push: check those with FEA or a push test.

The figure's spec, tools/anim/snap-engagement.yaml, is a snap declaration too: cad-agent snapfit tools/anim/snap-engagement.yaml prints the same two verdicts. tests/test_anim_snapfit.py runs the calculator again and checks the figure against it (animated figures).

Limits

  • A pass has no extra margin. It means the root strain is within the allowable; the guide's own examples design to half the permissible strain.
  • Closed-form, small-deflection beam theory with one part rigid: no large deflection, contact, creep, fatigue or wall deflection at the root. A warning is given when the deflection exceeds a tenth of the arm length (the guide's Example I is at 0.13). Large-deflection force-travel curves need FEA (CalculiX is the planned external solver).
  • Printed allowables are hypotheses until a coupon is measured: the datasheets are for 100 % infill on one printer and profile. Forces for printed snaps use the datasheet tensile modulus, which is higher than the secant modulus at the design strain, so mating forces are conservative and retention forces optimistic; the force rows say so. Where a filament has several editions, mating takes the highest modulus and retention the lowest.
  • Hook-face geometry and mould release are not checked. CAD and calculation do not prove a joint: print it and measure.

Tests that keep it honest

tests/test_snapfit.py reproduces the guide's worked examples — Example I (h 3.28 mm, P 32.5 N, W 58.5 N), Example II (ring-segment hook, y 2.11 mm) and the annular lamp cover (P 748 N, W 1346 N) — checks that every printed row matches the derived table in the research note, that direction changes the verdict for the same geometry, that uncomputable limits, out-of-range inputs and unstated processes fail, the ring section against numerical integration (arcs up to 360°), the torsion relations from first principles, and that this page's YAML example and printed table match the code. tests/test_torsion_snap_boss.py checks the torsion bar against Saint-Venant's series solution and this page's explorer numbers against the Python. The stated elongation and strength ranges are checked against the datasheet rows too.