klipper
klipper copied to clipboard
Add X twist compensation module
Hi,
This is a fork of the PR #6048. This is a feature I'd very like to see merged, so I took the liberty of taking the commits of @koonweee and fixing the comments made on his PR.
I can squash my commits if you prefer a cleaner history.
The changes include:
- A few bug fixes
- Some typos pointed out in the review
- Removal of the profile system, the rationale is that the twist only depends on the printer, not the temperature etc
- Rename of the module to axis_twist_compensation so that if we need some day to calibrate for another axis, there will be less changes to make to the user's configuration
On another note, I kept the recommended z offset feature from the original PR, which is also present in the Marlin implementation. This z offset has always been off in my tests. I also don't understand how making the average of the z offset from left to right makes sense to calculate a single z offset. The printer will only probe the middle of the bed when homing anyway, so that's the only offset that we should apply.
Also, a small difference from the original PR is that since I removed the profile system, there is always a configuration loaded when klipper starts.
TODO:
- [x] documentation (still unmodified from original PR, waiting for a first review)
Hey! Thanks for continuing development of this. I have been using the original implementation on my sv06 and been super happy with it, but would love to see this polished up for klipper of course. I will not have time until after my exams in May to work on this, but will be glad to review and assist here where possible 👍
Thanks a lot for your work on this, I've been using this feature for a month on my sv06, it really helped! Good luck on your exams :)
Fantastic work @koonweee, and @blastrock thanks a lot for the updates!
I haven't tested it yet, but I will very soon.
I do have 2 questions:
- Why the requirement to have at least 3 points? Reading the algorithm, it's only interpolating points 2by2. So, it would seem the more points, the more possibility of measurement error. With the current logic, 2 points would be sufficient, and actually preferable, no? Or am I missing something?
- As a follow-up to
1.
, instead of interpolating on 2 points only, could we use linear regression to fit the best straight line? Again, I'm not sure I fully understand the concept of this z adjustment. So, just to make sure I follow: we are trying to fit a straight line, correct? That straight line is the representation of the x asis gantry, correct? Or did I misunderstand?
If I did misunderstand the logic and you don't feel like re-explaining everything (which is fair), I'd be happy if you could point me to some resources for further reading 🙂
Thanks again for your amazing work 👍
Why the requirement to have at least 3 points?
I'd have to check, but I think it comes from the Marlin implementation. I'm pretty sure it would work with 2 points too, as you suggest.
As a follow-up to 1., instead of interpolating on 2 points only, could we use linear regression to fit the best straight line?
You are assuming that the twist leads to a linear z offset correction, and I did too!
I studied the problem the best as I could, and noticed there are 3 twists combining on my SV06:
- The print head is not the same orientation on the left and on the right of the printer and rotates around the X axis. That's the first intuition people have, and it's easy to notice it by holding a level on the print head and moving it. This one is probably linear.
- When the print head is in the middle of the axis, it leans forward with its own weight. So it rotates around the X axis in one direction until the middle where it rotates back in the other direction. This one is definitely not linear.
- This last one is hard to believe, and I'm even not sure I reached the right conclusion, but it looks like the print head rotates ever so slightly around the Y axis when traveling from left to right, kind of following a ◠ shape. So, the probe being to the right of the nozzle, it's offset too far from the bed when the print head is on the left, and too close when it's on the right. This last one might be linear? But it's around the Y axis, I'm not even sure how it combines with the others.
On my printer, I currently have the following correction offsets: 0.064583, -0.014167, -0.050417
, which makes it quite non-linear ^^
Why the requirement to have at least 3 points?
I'd have to check, but I think it comes from the Marlin implementation. I'm pretty sure it would work with 2 points too, as you suggest.
As a follow-up to 1., instead of interpolating on 2 points only, could we use linear regression to fit the best straight line?
You are assuming that the twist leads to a linear z offset correction, and I did too!
I studied the problem the best as I could, and noticed there are 3 twists combining on my SV06:
- The print head is not the same orientation on the left and on the right of the printer and rotates around the X axis. That's the first intuition people have, and it's easy to notice it by holding a level on the print head and moving it. This one is probably linear.
- When the print head is in the middle of the axis, it leans forward with its own weight. So it rotates around the X axis in one direction until the middle where it rotates back in the other direction. This one is definitely not linear.
- This last one is hard to believe, and I'm even not sure I reached the right conclusion, but it looks like the print head rotates ever so slightly around the Y axis when traveling from left to right, kind of following a ◠ shape. So, the probe being to the right of the nozzle, it's offset too far from the bed when the print head is on the left, and too close when it's on the right. This last one might be linear? But it's around the Y axis, I'm not even sure how it combines with the others.
On my printer, I currently have the following correction offsets:
0.064583, -0.014167, -0.050417
, which makes it quite non-linear ^^
This is very interesting. On my SV06 the offset is pretty linear. I did some measurements with a dial gauge and a mount at the nozzle and at the probe position.
If you look at the attached picture you can see the blue line where I have significant twist its pretty linear. On the red line there is very little twist and you can see something like you describe in number 2
That's interesting. I'm not sure I get the graph though. Is the blue line the distance between the probe and the bed and the red line the distance between the nozzle and the bed?
No both lines are the difference between the distance from probe to bed and nozzle to bed as measured with a dial gauge. It is the z offset tlyou have to correct for vs the x axis position. The blue line is in a situation w severe x twist. The red line is after I fixed it
Oh that's nice! In the end, the only way I found to make the offset linear is to move the probe, but it blocks the extruder screw, which is also a bit incovenient.
Anyway, supporting non-linear twists will at least help people with a stock SV06 who don't want to tweak it ^^
Fixed @murdock62 and @hiddentr0ll's bug mentioned here https://github.com/Klipper3d/klipper/pull/6048#issuecomment-1435689190
Hey 👋 Just catching up now, busy week, as always. 😅 Thanks for your answer, the conversation is very interesting.
If I’m being honest I didn’t fully understand the problem when I posted my last message. I didn’t even realize we were talking about x axis twist. I had tilt in mind and none of the calculations made sense. I couldn’t figure out why the bed mesh couldn’t compensate for a slight tilt. But I tried and it worked 🤷♂️.
Then I realized that we were talking about twist and it made a lot more sense.
But I still felt it should possibly follow a sort of theoretical curve. My intuition made me guess it would be either a straight line or a sine wave. I tried to model the path in fusion, but got stuck with my lack of skills and ended up with components hard-struck together that wouldn’t move the moment I introduce some mis-alignment of the rods 😅
Your explanation would indeed make me less hopeful that there is a theoretical optimal curve. You have a very good point with twist 2), I didn’t consider it at all and @Jayksopp ’s graph helped me understand it. I’m not sure why twist 3) would happen, but I can believe it might.
However, I believe the impact of twist 2) and 3) is somewhat negligible, I still think we may be able to fit a straight line to the points. The reason I believe this is because, between then and now, I did some experiments with linear regression and they’ve proven very successful for my particular setup 😃 (also SV06). Also it seems to confirm @Jayksopp 's own results.
The process
- I measured 5 points with a feeler gauge (blue)
- Then I measured 9 points with a feeler gauge (red)
- Finally I re-measured 9 points with a sheet of paper this time (yellow)
All 3 sets of measurements fit almost exactly the same line, with an average error of 0.005
(vs the 9 points with feeler gauge).
- I then generated 3 interpolated points to put in the config file
The result is, in my case at least, near perfect first layer on all 4 corners of the bed
Out of curiosity I fitted a line to your results as well, they fit quite nicely too. With a R² of 96%
I’ll be implementing linear regression in my own fork in a few days, for personal use, but I understand if you or the community prefers to go with point to point interpolation. The reason I prefer to use linear regression is because it allows me to not worry about having perfect measurements, as we can see the 9 points measured with paper were taking in a fraction of the time it took me to do the measurements with a feeler gauge and yet yield the same trendline.
If you’re curious, the algorithm is quite simple (I stole it from the internet).
# Sample data points
indexes = [0, 1, 2, 3, 4]
z_offsets = [0.109125, 0.03725, -0.0315, -0.059, -0.055875]
# Calculate the mean of x and y values
mean_indexes = sum(indexes) / len(indexes)
mean_z_offsets = sum(z_offsets) / len(z_offsets)
# Calculate the covariance and variance
covar = sum((indexes[i] - mean_indexes) * (z_offsets[i] - mean_z_offsets) for i in range(len(indexes)))
var = sum((indexes[i] - mean_indexes)**2 for i in range(len(indexes)))
# Compute the slope (m) and intercept (b) of the best-fit line
m = covar / var
b = mean_z_offsets - m * mean_indexes
# Print the equation of the best-fit line
print(f"The equation of the best-fit line is: y = {m} * x + {b}")
Thanks a lot for taking the time to go in depth with the explanations, it’s very much appreciated 🙏
On a sidenote, @Jayksopp , how did you connect the z-rods to the top bar? Do you mean the lead screw (because the rods are already attached to the top)?
Hey 👋 Just catching up now, busy week, as always. 😅 Thanks for your answer, the conversation is very interesting.
If I’m being honest I didn’t fully understand the problem when I posted my last message. I didn’t even realize we were talking about x axis twist. I had tilt in mind and none of the calculations made sense. I couldn’t figure out why the bed mesh couldn’t compensate for a slight tilt. But I tried and it worked 🤷♂️.
Then I realized that we were talking about twist and it made a lot more sense.
But I still felt it should possibly follow a sort of theoretical curve. My intuition made me guess it would be either a straight line or a sine wave. I tried to model the path in fusion, but got stuck with my lack of skills and ended up with components hard-struck together that wouldn’t move the moment I introduce some mis-alignment of the rods 😅
Your explanation would indeed make me less hopeful that there is a theoretical optimal curve. You have a very good point with twist 2), I didn’t consider it at all and @Jayksopp ’s graph helped me understand it. I’m not sure why twist 3) would happen, but I can believe it might.
However, I believe the impact of twist 2) and 3) is somewhat negligible, I still think we may be able to fit a straight line to the points. The reason I believe this is because, between then and now, I did some experiments with linear regression and they’ve proven very successful for my particular setup 😃 (also SV06). Also it seems to confirm @Jayksopp 's own results.
The process
- I measured 5 points with a feeler gauge (blue)
- Then I measured 9 points with a feeler gauge (red)
- Finally I re-measured 9 points with a sheet of paper this time (yellow)
All 3 sets of measurements fit almost exactly the same line, with an average error of
0.005
(vs the 9 points with feeler gauge).
- I then generated 3 interpolated points to put in the config file
The result is, in my case at least, near perfect first layer on all 4 corners of the bed
Out of curiosity I fitted a line to your results as well, they fit quite nicely too. With a R² of 96%
I’ll be implementing linear regression in my own fork in a few days, for personal use, but I understand if you or the community prefers to go with point to point interpolation. The reason I prefer to use linear regression is because it allows me to not worry about having perfect measurements, as we can see the 9 points measured with paper were taking in a fraction of the time it took me to do the measurements with a feeler gauge and yet yield the same trendline.
If you’re curious, the algorithm is quite simple (I stole it from the internet).
# Sample data points indexes = [0, 1, 2, 3, 4] z_offsets = [0.109125, 0.03725, -0.0315, -0.059, -0.055875] # Calculate the mean of x and y values mean_indexes = sum(indexes) / len(indexes) mean_z_offsets = sum(z_offsets) / len(z_offsets) # Calculate the covariance and variance covar = sum((indexes[i] - mean_indexes) * (z_offsets[i] - mean_z_offsets) for i in range(len(indexes))) var = sum((indexes[i] - mean_indexes)**2 for i in range(len(indexes))) # Compute the slope (m) and intercept (b) of the best-fit line m = covar / var b = mean_z_offsets - m * mean_indexes # Print the equation of the best-fit line print(f"The equation of the best-fit line is: y = {m} * x + {b}")
Thanks a lot for taking the time to go in depth with the explanations, it’s very much appreciated 🙏
On a sidenote, @Jayksopp , how did you connect the z-rods to the top bar? Do you mean the lead screw (because the rods are already attached to the top)?
Nice work!
part of the text is missing. It said "x twist disappears when z rods are not connected to the top bar" . For a while I printed without top z blocks :D then I upgraded the top bar to a piece of 2020 extrusion with custom top z blocks and this completely fixed the issue.
@HelloThisIsFlo Thanks for the detailed answer!
Your measurements look very linear indeed, and your point about doing a linear regression to cancel measurement errors makes sense.
You convinced me to make a 9 point calibration, for science! So this is a stock SV06 with only one mod at the moment, the top right rod block is 2mm shorter so that the print head has the same inclination on the leftmost and rightmost positions. The measurements are done with a paper test, using a gauge is bothersome as you said. Here's the result:
It looks similar to @Jayksopp's blue curve in that post above, but opposite direction. It is linear on the left, then mostly flat. The red line is done manually with just my eyes, I don't know how to do linear regressions in libreoffice ><
So, on some configurations, the correction is linear, and sometimes it is not. It might make sense to support both with a config option. Thanks for the code snippet, I'll try to integrate it, maybe tomorrow if I have some time.
As a side note, the current code gives me satisfying results, but in theory the correction shouldn't be multiple linear interpolations, it should be something smoother, like a cubic interpolation I guess. I am not very mathematically inclined so I'm not sure a cubic interpolation is what would make most sense here. Please tell me if you think of another way of smoothing the correction.
Hi, maybe this can help shed some light on the non linear offsets that we are seeing. A while back I did an experiment where I attached one z rod to a non square tower:
Both side twisted linear offset, one side twisted linear and then flat ?
Hi there, I remember I did some manual measurements on my setup (Geeetech A30 with twisted gantry/x-axis), and my setup was defintively not linear.
I also checked the axis_twist_compensation code, and as far as I can tell, doing more/enough points will account for non-linear twist, as the linear interpolation happens between the closest two compensation points.
Having a non-linear twist-profile (for whatever reason) means doing linear regression or any other approximation introduces errors to the actual offset.
Instead I'd suppose to do it like the BedMesh does: do multiple measurements on the same point to improve accuracy/eliminate errors. To improve it, the script could also calculate the variance/std deviation of each point, and recommend further measurements or a redo of certain points. Or: let the user repeat the measurement, until a certain std deviation is matched, along with elimating outliers to speed things up (could be done by the automatic bedmesh probing, too).
One other thing I saw in the code: the compensation values are still based on the mean z_offset (from the compensation measurements). I thought this was not recommended? I think, it makes sense to use a fixed-point z_offset as base for the compensation, like i.e. the z_offset at the middle of your bed. Because the offset might change i.e. with a nozzle-swap, but the compensation would still be valid. With the "virtual" offset, you have to redo the compensation to get the new offset.
Some updates:
- integrated linear regression from @HelloThisIsFlo's code
- removed recommended z offset
- simplified the code a lot
- updated documentation
- squashed commits
@HelloThisIsFlo I tested the linear regression code, it seems to work, but I can't confirm it since it doesn't produce good results on my printer, could you test it?
@LHARD
Instead I'd suppose to do it like the BedMesh does: do multiple measurements on the same point to improve accuracy/eliminate errors. To improve it, the script could also calculate the variance/std deviation of each point, and recommend further measurements or a redo of certain points. Or: let the user repeat the measurement, until a certain std deviation is matched, along with elimating outliers to speed things up (could be done by the automatic bedmesh probing, too).
The probe measurement is already done 3 times as per Klipper's default behavior. I don't think repeating the manual measurement would help. Once you find the right distance, that distance should never change. If you home your printer, it should be able to get back to that exact position with a very small error. In my experience, the measurements have been very repeatable.
One other thing I saw in the code: the compensation values are still based on the mean z_offset (from the compensation measurements). I thought this was not recommended? I think, it makes sense to use a fixed-point z_offset as base for the compensation, like i.e. the z_offset at the middle of your bed. Because the offset might change i.e. with a nozzle-swap, but the compensation would still be valid. With the "virtual" offset, you have to redo the compensation to get the new offset.
The problem with taking the z_offset of the middle of the bed is that when doing the axis twist calibration, there may be no point in the middle of the bed, for example if you use an even number of points, or if your min/max X are not symmetric with the middle of the bed.
But it turns out taking the average of the offsets (or any value actually) is not a problem at all. The addition of the average to the Z corrections is only there as a normalization. The exact value is not important because they are only used to calibrate the bed mesh which is a relative mesh (and is probably normalized with the average too). The Z correction is also applied when doing probe calibration, but that's not a problem either, you just need to do it after the axis twist calibration. The probe calibration will always add a constant offset (from the twist compensation), and it does not have any impact. What's important is that the probe calibration and bed mesh are done after the twist calibration.
@blastrock
@HelloThisIsFlo I tested the linear regression code, it seems to work, but I can't confirm it since it doesn't produce good results on my printer, could you test it?
If the results are bad, it might be the case that your axis_twist just is not linear. in that case the linear regression can't be applied. Looking at my printer, it can't be linear, as the gantry-mounting (parts connecting x-axis on both ends to the z-axis) is inside the print-volume. And while these parts could carry the twisting force (like from the gantry in my case), they will also stiffen the x_axis near the ends. That would explain why for some of us the twist is like zero on one or both ends. This could also explain the findings of @Jayksopp. Loosening the towers could remove the twisting forces. BTW: I wouldn't do a linear regression on that values either.
The probe measurement is already done 3 times as per Klipper's default behavior. I don't think repeating the manual measurement would help. Once you find the right distance, that distance should never change. If you home your printer, it should be able to get back to that exact position with a very small error. In my experience, the measurements have been very repeatable.
I totally agree on the the PROBE measurements! What I meant was the manual measurements (like paper-test) (sorry for not beeing precise enough) If you repeat them multiple times, they should get more precise (with a little math). A good way could be following: after you did the manual adjustment for every point once, the script could go back to the first one with i.e. 0.2mm additional offset, and ask the user to redo the adjustment. to make it even better, the repeating measurements could be done without showing the current value, as that might influence the adjustment.
The problem with taking the z_offset of the middle of the bed is that when doing the axis twist calibration, there may be no point in the middle of the bed, for example if you use an even number of points, or if your min/max X are not symmetric with the middle of the bed.
But it turns out taking the average of the offsets (or any value actually) is not a problem at all. The addition of the average to the Z corrections is only there as a normalization. The exact value is not important because they are only used to calibrate the bed mesh which is a relative mesh (and is probably normalized with the average too). The Z correction is also applied when doing probe calibration, but that's not a problem either, you just need to do it after the axis twist calibration. The probe calibration will always add a constant offset (from the twist compensation), and it does not have any impact. What's important is that the probe calibration and bed mesh are done after the twist calibration.
Again sorry for unprecise description: Ususaly you (I?) use PROBE_CALIBRATE for z_offset adjustment, which you usually do always in the same spot (like the middle of your bed). After changing your nozzle, you propably will redo z_offest adjustment again on that spot, leaving your bed_mesh untouched. axis_twist could do the calibration just referenced/normalized to that offset (which was done before axis_twist_calibration), whether that exact point was measured by the script makes no difference. Now, the next time you i.e. change your nozzle, you just redo PROBE_CALIBRATE (which of course must be done without axis_twist_compensation).
Doing everything after axis_twist_calibration should work too, and I if got it right (in my head ;-) ) doing a PROBE_CALIBRATE after axis_twist_compensation, should give you the same value regardless of the position, right? And that would not be the actual offset from probe to nozzle, but the new mean offset, right? I'm just thinking and asking to understand what all the values will mean/actually describe.
If the results are bad, it might be the case that your axis_twist just is not linear
Yup, that's exactly the case. This is why I'm asking @HelloThisIsFlo to test this code since his printer only needs a linear correction.
If you repeat them multiple times, they should get more precise (with a little math).
In my experience, redoing the calibration multiple times gives results very close (or identical) each time. It's kind of the same reasoning as the simple Z offset calibration in the middle of the bed, your printer is precise enough to get to the exact same position you measured a hundred times (unless it's wobbly, but that would be another problem ^^). The only way to get more precise results is to use a feeler gauge, but then again, doing it once is enough.
axis_twist could do the calibration just referenced/normalized to that offset (which was done before axis_twist_calibration), whether that exact point was measured by the script makes no difference
I see, yeah that would work. However it wouldn't make a difference since all these calibrations are relative.
Now, the next time you i.e. change your nozzle, you just redo PROBE_CALIBRATE (which of course must be done without axis_twist_compensation).
That's already what I do when I change nozzle, there's no need to rerun the axis_twist_compensation calibration, even if the Z offset in the middle of the bed has changed. The axis twist compensation only measures relative offsets from left to right, similarly to the bed mesh. The bed mesh is always normalized with its average, and you don't need to redo it when your z offset changes.
For the math, the z offsets from the axis twist compensation get added to the bed mesh values. So even if all your correction offsets are between 10 and 11, your bed mesh will all be around 10-11, but it will be normalized to its average, canceling whatever offset was applied to the corrections and bringing it back to around 0.
Hey there,
Thanks for your detailed responses too. It’s very interesting topic. I’ll try to catchup on everything, let me know if I forgot something.
@blastrock I can see you already implemented linear regression, that was quick! I’d be happy to test it out of course.
What do you think is the best process to test it?
- Run the calibration on my machine, and print a first layer test?
- Or put debug statements in the code to make sure it generates the same values I got with the excel sheet (which are proven to work on my setup)?
On a side-note, in the meantime I also tried to clearly mis-align the gantry (by manually twisting one of the Z rods a few millimeters up) and ran a test print without re-calibrating axis_twist_compensation
. I was surprised to see that the same values for axist_twist_compensation
were still compensating perfectly (although my bed was showing as seriously tilted, which is expected). That’s why I didn’t end up implementing linear regression in my own fork, since it’s a set-and-forget measurement I felt it wasn’t worth it. But still very happy to help with the testing of your implementation.
However, looking at other people’s answer, it seems that I’m more the exception than the rule 🤔 Thanks to your detailed measurements, and @LHARD and @Jayksopp comments, I’m starting to wonder if my machine being linear is not more of a coincidence than anything else. So … event though it was my suggestion, I’m starting to back down on this linear regression idea. Because, as @LHARD mentioned, if the twist progression is mathematically not a linear line, then by using linear regression we may be introducing error more than anything else 😕 If that’s the case, it may just be that linear regression is wrong even in my setup, but the error it introduces is less than the measurement error I had before linear regression, so it works out.
The previous paragraph is a long way of saying: Maybe @LHARd suggestion of doing multiple Z-offset measurements at each point and averaging the results would be an even better way of protecting against measurement error than my idea of linear regression.
I can see you @blastrock had repeatable measurements, but as you can see on the graph of my original post …
… there is a measurement variance, in my measurements at least. Yes using a feeler gauge does help, but it’s much faster to do 2 or 3 measurements with paper, than it is doing 1 single feeler gauge measurement. The measurement error does not come from the printer being at an incorrect location, but from the user (me) having difficulty to perfectly decide when it has the “exact same friction” as the point before. That being said … the average difference between the min and the max measurement at each point is only 0.023
… so maybe it’s not worth the trouble?
Still I think offering the option to repeat measurement and take the average would remove all this potential for user error. As suggested by @LHARD, if we could do them all at once, and then do another pass it may be even better (as the user gets used to what friction “feels like” after doing the first pass). And requiring a “minimum difference between the results” between confirming would be the ultimate safety guard.
Finally, one point I’d like to mention is that I greatly appreciate the time you take to incorporate our feedback. But maybe we could go with a “good enough” version for now (and the current version is pretty great considering it fixed my printer 😃), get it merged, and then discuss about potential improvements. What do you think? Do we know what is blocking this from being merged?
TL;DR:
- I'm backing out of my idea of using Linear Regression, I believe repeated and averaged measurements would be more reliable way to prevent against user measurement errors (@LHARD suggestion)
- Still happy to help with the testing of your implementation of the feature (see above I have 2 questions regarding testing)
- The repeated & averaged measurements method would be even better with the other @LHARD suggestions
- Doing 1 full pass, then another full pass
- Keep doing passes until the desired precision is achieved on all points
- Finally, this PR is already incredibly useful in its current state, so maybe we could focus on getting it merged, and open another PR later for potential improvements like the ones suggested above?
Thanks again for all your hard work,
Flo
What do you think is the best process to test it?
I didn't think of that. I guess you can add a couple prints for the m and b values and check that they are close to the ones you found.
Because, as @LHARD mentioned, if the twist progression is mathematically not a linear line, then by using linear regression we may be introducing error more than anything else
That's the problem, you'd have to know beforehand that your twist is linear. Well now that it's done, I guess it can stay. If the reviewer doesn't want it, I'll remove it.
That being said … the average difference between the min and the max measurement at each point is only 0.023 … so maybe it’s not worth the trouble?
That's my reasoning. I do my paper test with a 0.025 step anyway, so this is an acceptable error for me ^^
Finally, one point I’d like to mention is that I greatly appreciate the time you take to incorporate our feedback
Thanks!
we could go with a “good enough” version for now
That's also what I'm thinking, we can still improve on this later. I won't have much time to work more on this in the near future. I'm not sure what's the procedure to get this merged. I read somewhere that reviewers pick their PR themselves, I'll check again the instructions and maybe ping one.
Hello, is there anyway I can get some installation instructions on how to install this? I believe I modified all of my Klipper files to match the "files changed" here, but the "AXIS_TWIST_COMPENSATION_CALIBRATE" command is unknown. I also tried to retrofit Koonweee's original installation instructions, but I still can't get Klipper to recognize the command. What I tried was this,
cd klipper
git remote add blastrock https://github.com/blastrock/klipper.git
git fetch blastrock
git checkout remotes/blastrock/jt/x-twist-compensation-simple klippy/extras/axis_twist_compensation.py klippy/extras/probe.py
git checkout remotes/blastrock/twist klippy/extras/axis_twist_compensation.py klippy/extras/probe.py
Thanks! p.s. I hope this gets merged into Klipper soon! It's so useful!!!
Hello, is there anyway I can get some installation instructions on how to install this? I believe I modified all of my Klipper files to match the "files changed" here, but the "AXIS_TWIST_COMPENSATION_CALIBRATE" command is unknown. I also tried to retrofit Koonweee's original installation instructions, but I still can't get Klipper to recognize the command. What I tried was this,
cd klipper
git remote add blastrock https://github.com/blastrock/klipper.git
git fetch blastrock
git checkout remotes/blastrock/jt/x-twist-compensation-simple klippy/extras/axis_twist_compensation.py klippy/extras/probe.py
git checkout remotes/blastrock/twist klippy/extras/axis_twist_compensation.py klippy/extras/probe.py
Thanks! p.s. I hope this gets merged into Klipper soon! It's so useful!!!
Did you restart the klipper service after checking out the files?
Also did you add the axis_twist_compensation section to your printer.cfg?
Did you restart the klipper service after checking out the files?
Yes, I did.
Also did you add the axis_twist_compensation section to your printer.cfg?
This was what I was missing!
Thanks to both of you for your help!
Additionally, if anyone ends up in a similar situation to me and reads this, don't run this command git checkout remotes/blastrock/twist klippy/extras/axis_twist_compensation.py klippy/extras/probe.py
it uses remotes/blastrock/twist when you need to be using remotes/blastrock/jt/x-twist-compensation-simple.
Hey @blastrock
I just completed some tests and I can confirm that the implementation of linear regression is working 🎉
I plugged in the values I got from my original measurements. I logged the m
and b
values, and I get the exact same straight line and interpolated values.
(the blue dots don't show on the graph because they perfectly line up with the yellow ones)
Just to make sure I then made a test print and it looked great!
Regarding the idea of doing multiple measurements during initial calibration, I still think it would be a nice improvement. The worst case error in my measurement was 0.03 and I usually do PROBE_CALIBRATE
down to 0.01
. But again, it is absolutely not a blocker.
You did a great job 🎉, and I think if we can get this PR merged it will help so many people in the community. After it's merged, maybe I could open a PR to add that multiple measurement feature at some point, but maybe I'll also decide it's not worth the hassle 😅. For now, LGTM 😃
Thanks again for your work and you too @koonweee . You made my printer super reliable 😃
Hi @blastrock,
I tested your changes, and I am very happy with the result (SV06). Big thanks for implementing! The guide in the documentation had been great and it worked quite well! The procedure had been easy to do, too 🙂 As a 3d printing novice, here is some feedback:
- It hasn't been obvious that it's possible to switch between 'linear' and 'multilinear' after calibration (and if it's not, I am still very happy with the result :) ). That means if the result doesn't change, just try the other one and see if that 'fixes' it. As I'd already done a 9 points run, I haven't been inclined to do everything again... I would mention that in the overview section as tip. It's described later but IMO it's very useful to mention sooner than later.
- The guide in the documentation doesn't mention how to change the number of points. The gcode spec does, but one might think oversee that.
- I think (and might be wrong here) that 'multilinear' works better with more points, doesn't it? If yes, than I would increase the default number of points to 9 and try both 'linear' and 'multilinear' and check which one works "better". Saves time & effort. But that's just a personal preference because I am lazy and z probing is annoying.
Hello, I tried to apply this fix to my SV06, but I'm confused. Some of the documentation references commands like X_TWIST_COMPENSATE_STATUS, or X_TWIST_PROFILE_LOAD NAME=<profile_name>. Seems like now there's AXIS instead of X in the names, but I can only do "CALIBRATE". How do I make sure that the compensation is active? The "STATUS" command doesn't seem to be there, neither does the rest. Apologies for my confusion, just installed Klipper for the first time today and I'm very new.
That's the old documentation, you should look at this pull request for the latest doc.
Once you have done the calibration and save_config, the values are saved to your printer.cfg. The compensation is always active unless your clear it or remove the line from printer.cfg.
@Gitii thanks for testing and for the feeedback.
I patched the documentation, it should help with the first two points you mentioned.
About defaulting to 9 points, I'm not sure, since it is annoying to do the calibration, and 3 points already gives very good results. Also it's the default value for Marlin too.
Hi everyone,
I tried using this with a Klicky probe on a Voron Trident but I got stuck trying to figure out how to get it to attach and dock the probe at the right time during calibration.
If one does a plain AXIS_TWIST_COMPENSATION_CALIBRATE command it immediately moves to the first calibration point without picking up the Klicky and fails with "Probe triggered prior to movement" which I guess is good (or it would crash into the plate).
Now if I wrap this in a naive macro that does ATTACH_PROBE first, then it picks up the Klicky, automatically probes the first point then goes into manual nozzle offset calibration. Here the Klicky needs to be detached somehow. If I manually remove it, then do TESTZ and ACCEPT it immediately moves on to the next calibration point without giving me a chance to reattach the Klicky so again it fails with "Probe triggered prior to movement".
Is there a way to write a macro that can do ATTACH_PROBE and DOCK_PROBE at the right time between each calibration point? Is it even desirable to do automatically or will tool head X-Y movement between the automatic and manual probing steps deteriorate the calibration accuracy?
If not automatic, can the AXIS_TWIST_COMPENSATION_CALIBRATE command be extended to make a pause to allow manual attach/detach of the Klicky between each point?
Finally, what is the correct way to write my own calibration values in the config if I want to play around with it? The docs mention z_compensation but doesn't describe the layout in detail. Is it as simple as a comma separated list of z values like so:
z_compensation: 0.05, 0.07, 0.08
Or does it also contain x and y coordinates?