Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adaptive slicing #1386

Merged
merged 82 commits into from Sep 24, 2017
Merged

Adaptive slicing #1386

merged 82 commits into from Sep 24, 2017

Conversation

platsch
Copy link
Member

@platsch platsch commented Aug 12, 2013

This is a first approach towards automatic layer height configuration.
The new Print Settings option "Adaptive slicing" determines the height of each individual layer by evaluating the objects surface at this region. It attempts to maintain the error caused by the stair-stepping-effect below the given cusp-value, basically as described in (e.g.) http://www-rp.me.vt.edu/bohn/projects/sabourin/thesis.pdf p.33ff, but with some modifications.

Some technical implementation details:
I've added a sub slice_adaptive in Object.pm which can be called instead of slice. Slice_adaptive makes use of some more or less generalized functions provided by AdaptiveSlicing.pm, where the surface evaluation stuff is stored.
The cusp-height algorithm needs min and max layer height capabilities for every extruder in use. This options are therefore added to the Extruder config in Printer Settings.
The first layer height is taken from the config. Subsequent layers are generated based on the normals of the facets crossing the $print_z layer and refined to match horizontal features and peaks/abrupt slopes.
Some basic testing is implemented in adaptive_slicing.t.

This is work in progress. Please give some feedback/opinion whether people are interested in this feature and about my implementation and integration into Slic3r. My experience in open source development is very limited and I'd like to avoid spending a lot of time on things no one will ever use :)

Next step would be implementing further control parameters for surface quality and overhanging areas and multi-extruder support to mix extruder diameters depending on the local structure of an object.

adaptive_servo_gcode

@alranel
Copy link
Member

alranel commented Aug 12, 2013

Wow, interesting. Thank you. I wish we had a chance to discuss this a bit earlier, as this is not going to be compatible with the work in the xsslice branch.

Can you explain why you need to generate layers while slicing? In other words, why can't we do a first analyze pass to determine the full list of Z planes (layers), and then proceed with slicing using the existing logic?

@platsch
Copy link
Member Author

platsch commented Aug 13, 2013

Originally, I implemented slicing while analyzing because my first approach was a bit different and also I needed some time to understand the existing code structure :). At the current state this is no longer necessary and could be easily changed. But: the next steps in this work include local adaptive slicing and support for automatic multi extruder based slicing. Both require the polygon loops of at least the last layer, maybe even more, to make a decision for the next step. I am currently not fully aware of how to integrate this into the existing mechanisms in detail. E.g: local adaptive slicing requires a concept of a layer-stack per branch, but as far as I understand, Slic3r heavily relies on the concept of one layer for the entire object (except for the microlayering feature).

Do you have any documentation/outline of the xsslice branch? Maybe I can take the new architecture into account for future development.

@alranel
Copy link
Member

alranel commented Aug 13, 2013

Hello, thank you for the answer. Can you please explain what do "local adaptive slicing" and "support for automatic multi extruder based slicing" mean? RTFM is a valid answer, if the linked paper (which I didn't read carefully) already explains them. :) In other words, what problems do they solve and how.
Regarding xsslice you can find an outline in the TriangleMesh.cpp file. As you can see that code enforces a modular design where the set of Z coordinates is ready before the slicing job begins (the goal here is optimal speed and memory usage). Let's see together if your (very interesting) plans fit this architecture or can be adapted somehow. Thank you!

@platsch
Copy link
Member Author

platsch commented Aug 14, 2013

Hello again. Sorry for the delay on my answers, I'm currently bothered with some urgent trouble and don't have as much time for this as I I'd like to :/

Local adaptive slicing basically means different layer heights for different parts of one object. In my screenshot you can more or less see two "towers". The left one with some structure in it. It is not necessary to apply the low layer height induced by the left one to both of them (what the algorithm currently still does). One approach is outlined in this paper http://www-rp.me.vt.edu/bohn/projects/tyberg/thesis.pdf, but I don't like the concept of big slabs introduced in this work, as they are not very flexible, and thus I'm trying to find a more flexible solution. Independent of the technical details, this requires some kind of "spatial parallel" layers in one object, to implement different layer heights at the same z-level. Hope my point is comprehensible...

Automatic multi extruder based slicing is not defined in any way, it's just my attempt to describe it quickly. Consider a setting where you have two or more extruders with different diameter but same material (e.g. PLA). Now let the algorithm decide which part of an object should be printed with which extruder, depending on the objects structure. Thin walls or high detail features should be printed with the smaller extruder. This can be detected by analyzing the polygon loop of a layer, e.g. by performing something similar to an r-Regular Shape Reconstruction, a technique used in image analysis. The choice of an extruder diameter for every single layer obviously affects the possible height for this layer.

I'm aware that this is some work and I'm not sure about the outcome. It's more intended as a research project and I'm going to spend some effort on this for university related work. I'd be happy to have the chance to contribute to the slic3r project and create something useful with that research.

I checked your outline in TriangleMesh.cpp. Are you planning to implement the three subfunctions in one single method? Are you going to change the general procedure? Because, all I had to change in your perl code was replacing the slice_facet sub by a (simpler) one, which calls intersect facet with a number of facets on one layer instead a number of layers on one facet. I admit that I didn't think through all the performance implications yet, but it seems not to make that much of a difference.

Great to see you are interested, looking forward to the next steps.

@nothinman
Copy link

I see a lot of randomness on the photo, but it's a very good idea and I was thinking about this for a while too.
Nice work, keep it up!

@platsch
Copy link
Member Author

platsch commented Oct 9, 2013

Ok, I've taken a closer look to the XS code and made a few changes to get my code compatible. As a quick solution I simply call the new cpp slice function with only one Z-coordinate per iteration to obtain the desired single layer. Despite the overhead, I get surprisingly high performance even with bigger objects. It might be reasonable to port the layer height estimation to cpp, because it requires frequent access to the facets and normals, but it works for now.
Is there a reason to combine the 3 former TriangleMesh methods in a single large block of code? I don't see how performance suffers from calling 3 or 4 submethods. That would allow to call only the parts needed for cases that differ from the first intention (and maybe improve readability a bit...).

@jipsina
Copy link

jipsina commented Oct 14, 2013

Speaking of different extruder widths. Even a single extruder should be easily able to print wide range of widths - from about the nozzle diameter to about twice that (and pretty much down to zero if filling a gap between two perimeters). It would be nice if slic3r was able to automatically adjust the width to e.g. avoid gaps or "machine gun" filling.

@nothinman
Copy link

...and this has actually been implemented when filling top layer. you can use 'thinner lines'. this would be good if used for other stuff too, such as infill and small gaps (zigzags sound like they want to destroy my printer -- I have a big one, 350x300mm build plate, and vibrations are horrible :/)

@platsch
Copy link
Member Author

platsch commented Oct 17, 2013

My experiments with different widths from a single extruder have produced satisfying results for small variations. A factor of more than ~1.5 lowers the quality significantly. E.g: printing the same object with a 0.5mm nozzle scaled to 0.25mm results in pretty poor quality compared to a print with a 0.25mm nozzle. The string tends to rip, the surface gets blurry and the objects strength decreases.
But your argument is valid, maybe a generic solution, where the range of available widths gets extended by a second extruder, might by an option.

@alranel
Copy link
Member

alranel commented Oct 26, 2013

Whoops, sorry for the delay in answering to this.
Feel free to propose a refactoring of TriangleMesh::slice(). I'm fine with splitting it in several public methods, as long as there's no overhead added.

Regarding variable extrusion width, that's already being used to fill gaps. See lib/Slic3r/Layer/Region.pm:_fill_gaps(), where thinner widths are being used to get into narrow gaps.

@platsch
Copy link
Member Author

platsch commented Oct 26, 2013

ahm, sorry, variable extrusion width was not intended for public, thats code for a number of experiments I'm running, i pushed that to the wrong branch accidentally. Thank you for the hint, I've already seen the code for small gaps. Going to revoke that next week.

@platsch
Copy link
Member Author

platsch commented Aug 18, 2014

Heyho,
after a long brake I'd like to eventually clean up this work :)

I've reduced the code to its core components, removing some non-compatible or potentially needless parts. What it basically does now is computing a set of layer heights depending on the angle of the surface. The set of z-planes is generated before the actual slicing. No more extruder switching or local adaptive slicing.
There is now a blog entry explaining some technical background. The implementation works with the current git master, however, the cusp value logic is still implemented in perl.

I have 2 additional annotations / questions:

  • It is tricky to analyze the surfaces for modified objects because the final shape of the resulting object gets only created after the actual slicing process and contains no surface normals. I considered running the analysis over both objects, but that would reduce the layer height if the modifier object contains slopy surfaces which do not intersect with the main object. The only clean solution I'm able to come up with so far is generating the difference of the meshes and running the analysis over the result, but that seems to be a fundamentally different approach from the implementation in slic3r. I circumvented the problem for now by simply ignoring the modifiers.
  • Why can a region have multiple volumes? as far as I understand, a region corresponds to one part of a multimaterial object or a modifier. In earlier versions, every region hold exactly one mesh.

@oysteinkrog
Copy link

Has there been any progress on this?
I think this would be an awesome feature and if there is something blocking the merge it would be nice to know what, so that those who wanted to could work on it.

@platsch
Copy link
Member Author

platsch commented Mar 4, 2015

I have not touched it since my last commit in Aug. 2014. I tried to make it easy to merge this feature into the master branch back then and spend quite some time on it. I'm not fully aware of all the changes in slic3r, so I'm not sure how easy the merge would be now.
I dropped my efforts since no one seemed to be really interested in this work, but would of course be willing to contribute again if that changes.

@alranel
Copy link
Member

alranel commented Mar 4, 2015

@platsch, I'm definitely interested. I'm just overwhelmed by the amount of work on Slic3r (and other things, as Slic3r lies in my spare time...) but I'll definitely get back to you.

@platsch
Copy link
Member Author

platsch commented Mar 4, 2015

Well, yes, I see your problem, any chance to spread the work on more shoulders in the mid/long-term?

@lordofhyphens
Copy link
Member

@platsch if you want to port it to the XSslicer and produce some test cases for it I will take a look at merging it in.

@platsch
Copy link
Member Author

platsch commented May 23, 2016

Uhm, it's been a while since I touched the code, but sure, I'd still love to see it integrated. Give me a few days, I try to find the time for a port.

Conflicts:
	lib/Slic3r/GUI/Tab.pm
	lib/Slic3r/Print/Object.pm
	lib/Slic3r/Test.pm
	xs/src/libslic3r/PrintConfig.cpp
	xs/src/libslic3r/PrintConfig.hpp
	xs/src/libslic3r/PrintObject.cpp
@platsch
Copy link
Member Author

platsch commented Jun 6, 2016

@lordofhyphens I updated the code to be compatible with the recent master branch. However, the computations are still done in perl, but porting as much as possible to XS is on my todo-list.
What is your requirement for test cases? There already is a set of perl unit tests for the adaptive slicing implementation.

@lordofhyphens
Copy link
Member

lordofhyphens commented Jun 6, 2016 via email

@lordofhyphens lordofhyphens added this to the 1.3.1 milestone Jun 6, 2016
@corthiclem
Copy link

@platsch there is something in the Settings tab that might be confusing.
When the adaptive quality is changed in the "Adaptive Layer tab", it creates an overidable "Adaptive slicing quality" in the Parts tab. (See screenshots below).

adaptive_slicing_0
adaptive_slicing_1

It seems that changing from the Adaptive Layers Tab changes the input in the Parts Tab but changing from the Parts Tab doesn't change the Adaptive Layers Tab:

adaptive_slicing_2
adaptive_slicing_3

I think the user will be confused and won't know which tab gives the correct Adaptive Slicing Quality.
What is the purpose of creating the overidable "Adaptive slicing quality" in the Parts tab? Which value of Adaptive Slicing Quality will be used when 'Ok' is clicked?

@lordofhyphens
Copy link
Member

@platsch seems to be missing the three icons for variable layer height.

@VanessaE
Copy link
Collaborator

VanessaE commented Jun 23, 2017

Screenshot relevant to @lordofhyphens' comment above:

image

EDIT: I reset and pulled to HEAD, and re-applied this PR. The crash previously reported does not happen anymore.

@ehybrid
Copy link

ehybrid commented Jun 23, 2017 via email

@VanessaE
Copy link
Collaborator

VanessaE commented Jun 23, 2017

(this is a re-post because I made a few errors)

Meanwhile, could you add a setting that'll let me limit how thin the layers are on parts of the model containing overhangs? I ask because my setup has some limits: when printing with 0.1 mm layers, I can't get good overhangs beyond 55 or so degrees, depending on how much the plastic curls up and how much more "stuff" there is to print above the overhang. At 0.2 mm layers, I can rock out an 85 degree overhang with ease.

So, consider this simple drawing (a variation on the 30-to-85 degree arch overhang test on Thingiverse):
image
("Please excuse the crudity of this model. I didn't have time to build it to scale or paint it")

In zones 1 through 6, I would expect the adaptive code to start out with thick layers (say 0.35 mm, since I have a 0.4 mm nozzle), using gradually-decreasing layer heights as it goes up. However, when it gets to zones 7 and 8, although the program will want to use thin layers to make the top-side slopes on the right look nice, the layers would have to remain thick enough to accommodate the overhang on the left (assume the overhang is much steeper than in the picture). Zone 9 would return to thinner layers again since there's no overhang there (just vertical and top sloping surfaces).

@VanessaE
Copy link
Collaborator

Another glitch:

  1. Load some model, preferably something complex but small enough to slice quickly.
  2. Click on the model, then open the Layer Heights dialog. Let it generate the preview.
  3. Close the dialog, and go change some relevant setting elsewhere in Slic3r, such as turning support material on.
  4. Re-open the Layer Heights dialog. No preview will be displayed -- you must twiddle the quality slider to get it to generate a new preview.

@VanessaE
Copy link
Collaborator

As an aside: I like the highlight on the sliced result when you mouse over the layer heights graph, but I think it would be a good idea if you also displayed the height of the currently-highlighted layer somewhere.

@platsch
Copy link
Member Author

platsch commented Jun 26, 2017

Yeah, lots of feedback :)

@corthiclem it should work in both directions, but the values are updated only after closing and opening the dialog. I just use slic3rs config mechanism, the slider in the layer-preview tab changes the overridable per object (which makes sense, since we want to tweak the parameter per object) and Slic3r automatically adds the modified value to the object settings section. But I agree that instant synchronization would be desirable.

@lordofhyphens ahm, yes. Fixed it.

@VanessaE regarding your overhang-feature request: I was discussing the same idea for some time with a few colleagues. We came up with two opinions:

  • It is useful to implement this as an option and limit the layer thickness below a certain negative threshold similar to the support structure threshold.
  • There are too many situations and exceptions where this wouldn't help, just let the user modify the height distribution manually.

I will probably try to implement this as soon as I find some time.

For the preview update problem: I experienced the same, but had the impression that it is not related to adaptive slicing since the Preview tab also didn't update. The UI update and changed background processing logic caused some trouble, but I'm not able to reproduce this since the last merge.

Current mousover-layer-height is now displayed.

@platsch
Copy link
Member Author

platsch commented Aug 22, 2017

FYI: we just published a paper on this topic at the 13th IEEE Conference on Automation Science and Engineering (CASE2017). Thx for a lot of inspiration that I got in this thread.

@lordofhyphens
Copy link
Member

Congratulations on the conference paper. I know those can be quite a pain to get into a good conference. Any plans for a longer journal article?

@platsch
Copy link
Member Author

platsch commented Sep 7, 2017

@lordofhyphens currently not. I think the main ideas are documented now, getting a good journal article published is a lot of extra work and I'd prefer to spend this time on the electronic printing project (or on getting the adaptive feature merged...).

@lordofhyphens lordofhyphens merged commit ebe4fe8 into slic3r:master Sep 24, 2017
@lordofhyphens
Copy link
Member

@platsch It's merged; I had to resolve a minor merge conflict (the changes for 3MF happened to hit similar lines).

Thank you, and I'll be sure to tag you when people write up issues about it ;)

@platsch
Copy link
Member Author

platsch commented Sep 25, 2017

@lordofhyphens Great! So I better prepare myself for the wave of issues and bug reports ;-)

@Patola
Copy link

Patola commented Sep 26, 2017

hooray!!!! This is great!!! Thank you @platsch and @lordofhyphens !!!

@lordofhyphens
Copy link
Member

@platsch would you be willing to write a description and a brief how-to guide for the Manual? I promise it won't take nearly as long to merge ;)

@platsch
Copy link
Member Author

platsch commented Oct 9, 2017

Yes, of course I'm willing, good point. I also found 2 bugs in my implementation and AMF support is still on the todo. It's merely a time issue...

@lordofhyphens
Copy link
Member

@curiouspl2
Copy link

+1 on the overhangs problem, as in #2120

i think this could be simply implemented as running your code as usual, and then running detect overhang pass to detect overhung layers .
it is great You did implement the 'quality' slider and i think same system could be used for deciding about overhangs :)

it would be great if user could set up at least two thresholds, like up to certain % of overhang actually lower layer height looks better so this could be 'overhang lower threshold'
then after this threshold increasing layer height helps instead of decreasing.
it would be great that another range could be selected for boosting layer height for overhangs ,
with default of sth like 20-40%.
then final range for 40-100% would be nice with separate boost value.

Then also i like the Layers... dialog with the graph, and with all those three sliders there user could quickly set the model up , especially if overhangs could be also painted on graph for visual cue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet