-
-
Notifications
You must be signed in to change notification settings - Fork 5.3k
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
bed_mesh: Implement adaptive bed mesh #6461
Conversation
Amazing! Thank you for all your impressive work on this! 😄 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
small typo in md
2c7fd4e
to
08a8a1d
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks. Overall the implementation looks good. I have some comments, however the are minor and mostly centered around code organization.
klippy/extras/bed_mesh.py
Outdated
# If adaptive meshing is enabled and there are defined objects, | ||
# generate adaptive mesh | ||
if do_adaptive and exclude_object is not None and \ | ||
len(exclude_object.objects) != 0: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It isn't valid to directly access the member attributes from a class in another module. Fortunately exclude_object
exposes its objects via get_status
, ie:
objects = exclude_object.get_status().get("objects", {})
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why isn't it valid? ExcludeObject._reset_state()
is being called from the constructor so the member attribute should always be defined. I can switch the code as your suggestion gives me the same result but I just want to understand your comment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's against our coding conventions as mentioned at: https://www.klipper3d.org/Code_Overview.html#adding-a-host-module
Accessing the internal member variables of other objects leads to a maintenance burden. Other developers working on ExcludeObject wont know that some other module has accessed its interanl state and those developers may make a local change that could subtly break the bed_mesh module. So, the convention is to avoid doing that.
-Kevin
08a8a1d
to
ace129d
Compare
The latest changes look good. One minor thing I missed earlier is that we should add the |
a494621
to
d4037ba
Compare
Done. I also re-ran the simulated tests with the latest revision and compared it against the graphs that were generated with the original version submitted with the PR to make sure that thing did not break during the review edits. |
Thanks. Happy to commit. I think we should give a few days to see if there are any other comments. Assuming nothing else comes up, I'll look to commit next week. -Kevin |
Amazing, thank you so much! |
d4037ba
to
fcc25d2
Compare
Hello, I'm interested in this PR. I think this has to be careful and think it would be helpful to include a note or a labeling method in the document. |
I am not sure that I understand. Are you asking for the purge line area to be probed or to document that the purge line area is not probed? Whether the purge line will be probed depends entirely on the slicer-generated gcode. If the slicer generates a purge line that is labeled as an object, it will be probed. Otherwise, it won't. I think that describing all of that and documenting slicer behavior is beyond the scope of Klipper documentation. |
Yes, this is my opinion.
I think it would be kind to include this content or simply the first half to the document. This may reduce a user accidentally scratching the table. |
There is the Speaking from experience here, I’ve ran many, many adaptive meshes and have used many different purge configurations (adaptive and static) and have not damaged a buildplate or nozzle. I believe it should be left up to the user what they feel is best to handle that, however I do not foresee it being a problem. |
I understand. I appreciate your consideration for all. |
I appreciate you understanding. I do, however, agree that although I've had no problems with it in the past, if someone's machine is a unique setup or has mechanical issues causing them to rely on a full mesh, that should be laid out clearly. It would require a fairly unique complication with the machine, but I suppose it is possible afterall that issuing print moves outside of the adaptive meshing area can be problematic. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added some verbiage for potential pitfalls when attempting print moves outside of an adaptive mesh's bounds on machines that have mechanical issues that a full mesh typically compensates for. I also added a note that adaptive bed meshes are not meant to be reused, and are best utilized by building a mesh prior to every print.
the area of the bed used by the objects being printed. When used, the method will | ||
automatically adjust the mesh parameters based on the area occupied by the defined | ||
print objects. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is important to consider that adaptive bed meshing is best implemented on machines that can normally probe the entire bed and achieve a maximum variance less than or equal to 1 layer height. Machines that have mechanical issues that a full bed mesh normally compensates for may have undesirable results when attempting print moves **outside** of the detected print object area. If a full bed mesh on your machine typically has a variance greater than 1 layer height, caution must be taken when attempting print moves outside of the meshed area. | |
Due to the nature of using an adapted bed mesh, it is not recommended that a user load a saved adaptive mesh to re-use for printing. Adaptive bed meshing is best utilized by generating a new mesh prior to every print. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The updated documentation looks good to me. This also adds context to your previous PR regarding BED_MESH_CLEAR
. I think we should disable autosave when adaptive is enabled. It will be relatively easy, just a few lines of code. I'll make the recommendations here, but I can submit it as a follow-up PR if you prefer not to merge them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The updated documentation looks good to me. This also adds context to your previous PR regarding
BED_MESH_CLEAR
. I think we should disable autosave when adaptive is enabled. It will be relatively easy, just a few lines of code. I'll make the recommendations here, but I can submit it as a follow-up PR if you prefer not to merge them.
Yes, please. The recommendation would be appreciated. I actually do prefer to merge them since doing them separately will introduce a window during which it would be possible to save an adapted mesh. Plus, I was already thinking along the lines of restricting it in the actual code. Just didn't know exactly how (due to the issues with my previous PR).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See the review point here. Hopefully its clear enough, Github doesn't seem to allow suggestions outside of the modified code. Essentially we just set self._profile_name = None
right before returning True
from set_adaptive_mesh()
. Then we modify the last line probe_finalize()
to prevent from sending the None
value save_profile()
.
@marbocub's concern is essentially valid. In the support activities, I have seen enough bed topologies that range from -0.5 to +0.5 or even worse. It seems that many users mistake bed-meshing as an alternative to leveled bed or generally have completely crooked beds. Maybe a sound recommendation would be building a mesh of the entire bed and review it. If it deviates more than 1 layer-height, adaptive meshing should be used with caution. |
In addition: Not sure if the adaptive meshing changes anything here, but usually the "boundary" points of a mesh are carried over to the unmeshed region. |
Yeah, I fully agree here. I will adjust the suggestion I've made with some more verbiage about this. I can fully relate with seeing some... "interesting" mesh results, so the concern is totally valid.
This is correct, I actually just double-checked this was the behavior today because I was not sure how that is handled. But yes. You can imagine it sort or like a bowl with a very wide flange. The edges of the mesh are scaled out in XY to infinity. Some of these cases we are imagining are very extreme, almost as if generating a bed mesh on a waffle-iron, but they are absolutely within the realm of possibility. |
fcc25d2
to
8740e32
Compare
As a short note, yes the empty string is the issue, @meteyou is already working on it. @pedrolamas: you need to check that for Fluidd also |
@matmen I do not doubt that, we saw the same as long a mesh like default was loaded before the execution with ADAPTIVE=1. Your picture shows also the name default. So you should test if again if fluidd does not name a mesh with an empty name string default. @voidtrance can you check that the name will also be an empty string if a mesh was already loaded, currently it looks like the name stays whatever it was before. Here is a picture of the data when you load a default mesh at Klipper init. E.g. using a delayed_gcode |
@zellneralex The default bed mesh shows up because it's defined in my config - fluidd just shows the reported mesh list, which doesn't include the adaptive mesh (with an empty name). We only use the bed mesh name for showing which mesh profile is active, which is why the "default" profile in the screenshot is showing a load button. If there's no bed mesh profiles reported, we just show a message, but the visualization still shows up: |
Perfect, then fluidd should be save. |
FWIW, #6473 will add profile names to the adaptive mesh. It will be something like |
Really appreciate the rapid and collaborative work to patch this you guys. 😄 Thanks for doing that. I've been monitoring some discord servers and forums and it seems like there are some areas the documentation is still lacking. I'll fork klipper and make some changes to the docs to improve any gaps in configuration/setup and make a PR. Really it just boils down to setting up exclude_object correctly and some other small things. Thank you again! |
@Arksine Is it maybe a good idea to add an option to make save_config ignore adaptive-xxxx meshes? |
Arksine already mentioned in his fix up commit message that he is explicitly allowing the saving of adaptive meshes in case anyone wants to use them for some type of testing/research. |
You have to explicitly call |
🤦♀️ whoops, I totally missed that. Sounds great, thank you both. |
@kot0005 remove the bed_mesh_profile load=default line, and send a screenshot of your start gcode settings in slicer. |
hi, this is my start g code in slicer START_PRINT BED_TEMP=[first_layer_bed_temperature] EXTRUDER_TEMP=[first_layer_temperature] if i remove the line you mentioned, will it still use the mesh it calibrated from the calibrate command ? ty |
@kot0005 if you leave the line in there, it most definitely won't work. Try adding M117 before you call start_print in slicer start gcode. |
|
mate the M117 in the slicer makes my printer start printing the file without heating anything.. ty for the help but i have gone back to my original gcode base adaptive mesh and working perfectly. This is def not ready for plug and play. |
@kot0005 if adding M117 before print start makes your print start not work, your config is severely broken. Swing by the discord server and we can get it working, don't want to continue spamming this pr. The feature works exactly as expected, this is a config issue. |
Isnt the whole point of PRINT_START is to use the Gcode macros set up in the config file ? adding M117 Ignores all of this, not to mention it could damage the hotend extruder if its starts to print without heating up. Luckily mine was already heated a bit from previous test print. I opened a topic on discord with my config file now. I dont think there is anything wrong with it. |
@kot0005 m117 simply clears the display. It absolutely does not stop print_start from working. I assume that you have misread and have replaced print_start with m117, which is not what I suggested. |
i did not replace print start.. i added M117 before print start like you suggested. |
What we really need is a sliced gcode file, we have seen that the exclude object definition was placed below the first user defined gcode. As said the feature works as intended, for setup help and debugging of your system use the Klipper discord. |
@kot0005 Please, let's not use the PR thread for debugging issues. There are other forums better suited for this.
For what it's worth, a PR was merged a couple of days ago to the preprocessing script that fixes this and the |
Moonraker's dependency on preprocess-cancellation has been updated. The next time a user updates Moonraker it should be installed. |
Do moonraker updates through the update manager also update the virtual environment? The script is installed in there, if I am not mistaken. |
Yes, it will update Moonraker's virtualenv. |
Adaptive bed mesh allows the bed mesh algorithm to probe only the area of the bed that is being used by the current print. It uses [exclude_objects] to get a list of the printed objects and their area on the bed. It, then, modifies the bed mesh parameters so only the area used by the objects is measured. Adaptive bed mesh works on both cartesian and delta kinematics printers. On Delta printers, the algorithm, adjusts the origin point and radius in order to translate the area of the bed being probe. Signed-off-by: Mitko Haralanov <[email protected]> Signed-off-by: Kyle Hansen <[email protected]> Signed-off-by: Kevin O'Connor <[email protected]>
This PR is for an implementation of adaptive bed meshes. Adaptive bed meshes use the exclude objects data to determine the area of the print bed being used and only create a mesh for that bed area. This has the benefit of greatly decreasing the amount of time needed to start a print without compromising print quality.
These changes have been tested on both Cartesian and Delta printers through the use of SimulAVR (with some custom Klipper modifications to enable it to report probe point z offset through Moonraker) and by many actual users in the Voron Discord.
Below is a ZIP archive containing two HTML files that show the behavior of the adaptive mesh. Plots where generated using test data from the SimulAVR simulation.
adaptive-mesh-plots.zip
The commands issues to define the print objects that produce these plots are below:
commands-cartesian.txt
commands-delta.txt