Fix sequential print collision check depending on object list order - #630
Fix sequential print collision check depending on object list order#630KuzuriAo wants to merge 1 commit into
Conversation
|
/bot add-label bug-fix |
|
Hi, @KuzuriAo I am very glad to see your root cause analysis and fix attempts. |
Follow-up: when this fix still isn't enough@zackaree-shen I wanted to bring this up, since I ran into it myself right after posting this PR: this fix resolves the case where a valid print order exists but the old code never searched for it. It does not, and should not, silence a genuinely unavoidable collision. If two objects are both taller than So if you hit the error after this fix and reordering, cutting/pasting, or nudging objects around doesn't clear it no matter what you try, don't assume the fix is broken. It probably means the printer's clearance settings genuinely can't be satisfied by the current plate layout. How to actually fix a genuine oneThe check only cares about Y position, not X. Two tall objects can sit anywhere in X without conflict, they just can't occupy overlapping Y bands (specifically, within In practice this is fiddlier than it sounds if the objects are large: I tried it on a real case and the two conflicting objects each needed to span nearly the plate's full Y depth, leaving only a few mm of margin to work with after finding a split that satisfied both directions of the constraint. A much easier and more reliable fix, if the flagged object is a merged multi-part "Assembly": split it apart and reposition the pieces individually.
Why this works: the collision check uses Quick summary
|
Hi @zackaree-shen,
I believe this is a solid fix for issue #586 that we were discussing.
Fix sequential print collision check depending on object list order, not actual geometry
The bug
I ran into this with models designed for Bambu printers, mostly 3mf files pulled from MakerWorld. They'd slice and print fine in Bambu Studio on an actual Bambu printer. But opening the same file in Snapmaker Orca (or Orca) and switching the printer profile over to a Snapmaker U1 would sometimes throw "Assembly is too tall, and collisions will be caused.", error.
That's was the hint that this isn't a real geometry problem. If a file slices and prints cleanly on in Bambu Studio on a Bambu printer, there's no physical reason it shouldn't also slice cleanly on a Snapmaker U1 or any other printer. Swapping the printer profile doesn't change the objects' heights or positions relative to each other. So the error had to be coming from the slicer's own collision check, not from an actual collision.
That's what turned up in
sequential_print_clearance_valid()insrc/libslic3r/Print.cpp. It's supposed to check whether a sequential print's object heights and positions can actually be printed without the toolhead colliding with already-finished objects. Instead, it just sorts objects by their raw position in the object list (object_index) and checks clearance against that order. If the list order happens to put a tall object before a short one it shouldn't, you get the "too tall" error, even when a valid, non-colliding print order exists. Since a 3mf's object-list order is just an artifact of how the file was authored (Bambu Studio, MakerWorld, whatever produced it), and not something the printer profile changes, this made the error effectively random with respect to which printer profile you picked.The workaround right now is cutting an object out of the model and pasting it back in, which reshuffles its position in the object list and sometimes gets you a list order that happens to work. That's luck, not a fix, and it's easy to end up with a file where no amount of cut/paste helps because the check was never actually looking for a valid order in the first place. It was just checking the one it was handed.
There's also a disabled (
#if 0) block above the current logic that tried to solve this properly with a score-propagation heuristic, but it wasn't guaranteed to converge and was turned off.Where "the object list" actually is
The object list lives in
3D/3dmodel.model, in two places that stay in lockstep: a<resources>block with one<object id="N">entry per top-level printable object, and a<build>block with one<item objectid="N" transform="...">entry per instance placed on the plate. Whatever order those entries appear in the XML is the order libslic3r assigns as each object'sobject_indexwhen it loads the file. It's just file order, with no geometric meaning at all. (Each<object>can itself be a multi-part "Assembly": several sub-meshes with their own per-part extruder/color assignments merged into one printable item, which is exactly what the "Assembly is too tall" wording refers to; that's a separate, unrelated feature from the ordering bug.)I confirmed this directly on one of my failing files, saved twice from the same project: once with a Bambu printer profile selected (worked fine) and once after switching to the Snapmaker U1 profile (threw the error). Diffing the two
3dmodel.modelfiles, the geometry, transforms, and part assignments are identical. The only thing that changed is which of the two top-level "Assembly" objects (a shorter Hilt assembly and a taller Body assembly with arms and wings) is listed first:Same two objects, same everything else, just swapped in the list. Under the old code, only the object printed last gets the full
printable_heightallowance; whichever one lands earlier is capped atextruder_clearance_height_to_lid. So depending purely on which of these two saves you opened, either the taller Body assembly got the "last" slot (fine) or the shorter Hilt did (Body then gets capped and throws "too tall"). Nothing about switching the printer profile changes this ordering. It's an incidental side effect of when and how the file gets re-saved (cut/paste, re-export, whatever). Bambu Studio's own sequential-print handling clearly doesn't treat that raw list order as the print order, or the same 3MF file would have thrown the same false collision on the Bambu printer it was designed for, and it didn't.The Fix
Replace the list-order sort with an actual search for a valid print order. The constraint is: every instance except the one printed last is capped at
extruder_clearance_height_to_lid, or the stricterextruder_clearance_height_to_rodif some later-printed instance overlaps it in Y. So at most one instance can need the "last slot," and among the rest, any two instances that overlap in Y and are both taller than the rod-clearance height need the taller one scheduled first.That's a topological sort over a "must print before" constraint graph. The fix builds that graph and runs Kahn's algorithm, breaking ties by the original object index so the result is the smallest reordering of what you already had, not something arbitrary. If a valid order exists, it's used. If it genuinely doesn't (a real, unavoidable collision), it falls back to the original object-list order so the vertical-clearance check below still fires the same descriptive error it always has. The goal here is to stop false positives, not to hide real ones.
Testing
Test files:
The following was a 3mf that sliced cleanly and printed with no problems in Bambu Studio on a Bambu X1C:
Z-bambu.3mf.zip
You can see it will slice cleanly in Bambu Studio:
However, this is the same file opened in Sn(orca) and had the printer profile changed to Snapmaker U1:
Z-U1 2.3mf.zip
Here is by macOS (Apple Silicon) build with the patch applied and no error, slices cleanly:
Here is by Ubuntu 25.10 (questing) build with the patch applied and no error, slices cleanly:
Tested Builds
Built and tested locally against both OrcaSlicer and Snapmaker Orca on:
Results:
This is a pure logic change in one function. No platform-specific code, so it should behave identically everywhere.
Other bugs
While I don't really see any issues opened on Snapmaker/Orcaslicer (other than mine that I think this applies to), I did find a bunch on the main OrcaSlicer github repository that seem like are referring to this bug:
On OrcaSlicer/OrcaSlicer:
#6876: the same false "too tall" warning, reported in 2024 and closed as completed. It clearly came back (or was never fixed at the root), which lines up with what's in this repo now: a disabled #if 0 heuristic block that looks like an earlier, half-working attempt at this exact problem, later turned off in favor of the naive list-order sort that reintroduced the bug.
#14435: a feature request making essentially the same diagnosis, that using height-to-rod/height-to-lid as blind cutoffs "without checking actual geometry is too crude." Its proposed fix is more ambitious than this one (axis-based bounding-box sectors instead of a height plane), but the root-cause framing matches.
#12386: a cruder version of the same idea, force the tallest object last and skip the check for it. This fix effectively derives that outcome as a special case when it's actually needed, instead of asserting it unconditionally, and without giving up the check for genuine unavoidable collisions. Links its own related cluster: #6601 and #6828.
#12505: the mirror-image bug, where the slicer doesn't warn when it should and a real collision gets through during abort or end-of-print parking. Not something this PR touches (that's end-of-print G-code behavior, closer to the Snapmaker #453 family above), but it's a good reminder that getting the ordering logic right matters in both directions.