{"action":"created","issue":{"url":"https://api.github.com/repos/MarlinFirmware/Marlin/issues/8576","repository_url":"https://api.github.com/repos/MarlinFirmware/Marlin","labels_url":"https://api.github.com/repos/MarlinFirmware/Marlin/issues/8576/labels{/name}","comments_url":"https://api.github.com/repos/MarlinFirmware/Marlin/issues/8576/comments","events_url":"https://api.github.com/repos/MarlinFirmware/Marlin/issues/8576/events","html_url":"https://github.com/MarlinFirmware/Marlin/issues/8576","id":276950719,"number":8576,"title":"UBL 3 Point Tilting of mesh produces unexpected results","user":{"login":"Koshu","id":1508787,"avatar_url":"https://avatars1.githubusercontent.com/u/1508787?v=4","gravatar_id":"","url":"https://api.github.com/users/Koshu","html_url":"https://github.com/Koshu","followers_url":"https://api.github.com/users/Koshu/followers","following_url":"https://api.github.com/users/Koshu/following{/other_user}","gists_url":"https://api.github.com/users/Koshu/gists{/gist_id}","starred_url":"https://api.github.com/users/Koshu/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Koshu/subscriptions","organizations_url":"https://api.github.com/users/Koshu/orgs","repos_url":"https://api.github.com/users/Koshu/repos","events_url":"https://api.github.com/users/Koshu/events{/privacy}","received_events_url":"https://api.github.com/users/Koshu/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":0,"created_at":"2017-11-27T09:28:24Z","updated_at":"2017-11-27T14:58:56Z","closed_at":null,"author_association":"NONE","body":"I build a new printer (with probe and z-max endstop) and played around with UBL to get the 3 point tilt (G29 J) compensation working. My understanding of what it should do or at least what I hoped it would do is the following (If it was not supposed to work that way then I guess this becomes an feature request rather than a bug report): \r\n\r\nYou initially build your mesh (G29 P1 etc etc) which takes quite bit of time and than do 3 point tilt compensation right before every print. The 3 point tilt compensation then calculates the tilt around the x and y axes as well as displacements along the z axis and corrects them in the mesh. The result would be a perfect leveled mesh as long as the warping of the bed didn't change.\r\n\r\nNow, while trying out this setup I noticed that my mesh started to look really weird with values that should not be possible (20 mm and more offset of the mesh). I found a way to reproduce the error. For readability I changed my mesh to an 3x3 Grid and zeroed all mesh points:\r\n\r\nFirst the initial mesh:\r\n```\r\n>>G29 T\r\nBed Topography Report:\r\n\r\n(0,2)           (2,2)\r\n(20,200)        (200,200)\r\n  0.000    0.000  [ 0.000] \r\n \r\n  0.000    0.000    0.000  \r\n \r\n  0.000    0.000    0.000  \r\n(20,20)            (200,20)\r\n(0,0)             (2,0)\r\nok\r\n```\r\n\r\nThen I executed the compensation:\r\n```\r\n>>G29 J V4 T\r\nBed X: 21.000 Y: 21.000 Z: 0.352\r\necho:busy: processing\r\necho:busy: processing\r\necho:busy: processing\r\nBed X: 199.000 Y: 21.000 Z: 0.312\r\necho:busy: processing\r\necho:busy: processing\r\nBed X: 110.000 Y: 199.000 Z: 0.387\r\necho:busy: processing\r\nbed plane normal = [0.0002247,-0.0003090,1.0000000]\r\nrotation matrix:+1.000000 +0.000000 -0.000225 \r\n+0.000000 +1.000000 +0.000309 \r\n+0.000225 -0.000309 +1.000000 \r\nD constant: 0.3507303 \r\n\r\nBed Topography Report:\r\n\r\n(0,2)           (2,2)\r\n(20,200)        (200,200)\r\n -0.293   -0.314   -0.334  \r\n \r\n -0.321  [-0.341]  -0.362  \r\n \r\n -0.349   -0.369   -0.389  \r\n(20,20)            (200,20)\r\n(0,0)             (2,0)\r\nok\r\n```\r\nSo far so good. The values doesn't seem to be to much off and might or might not be correct. Also, I expected the mesh points near the probe points to be a bit closer than that. It starts to get really weird as soon as you execute G29 J multiple times:\r\n\r\n```\r\nBed X: 21.000 Y: 21.000 Z: 0.355\r\necho:busy: processing\r\necho:busy: processing\r\necho:busy: processing\r\nBed X: 199.000 Y: 21.000 Z: 0.310\r\necho:busy: processing\r\necho:busy: processing\r\nBed X: 110.000 Y: 199.000 Z: 0.382\r\necho:busy: processing\r\nbed plane normal = [0.0000281,0.0000281,1.0000000]\r\nrotation matrix:+1.000000 +0.000000 -0.000028 \r\n-0.000000 +1.000000 -0.000028 \r\n+0.000028 +0.000028 +1.000000 \r\nD constant: 0.7051403 \r\n\r\nBed Topography Report:\r\n\r\n(0,2)           (2,2)\r\n(20,200)        (200,200)\r\n -1.298   -1.341   -1.384  \r\n \r\n -1.351  [-1.394]  -1.437  \r\n \r\n -1.404   -1.447   -1.490  \r\n(20,20)            (200,20)\r\n(0,0)             (2,0)\r\nok\r\necho:busy: processing\r\nBed X: 21.000 Y: 21.000 Z: 0.355\r\necho:busy: processing\r\necho:busy: processing\r\necho:busy: processing\r\nBed X: 199.000 Y: 21.000 Z: 0.312\r\necho:busy: processing\r\necho:busy: processing\r\nBed X: 110.000 Y: 199.000 Z: 0.385\r\necho:busy: processing\r\nbed plane normal = [-0.0002388,0.0003020,1.0000000]\r\nrotation matrix:+1.000000 +0.000000 +0.000239 \r\n+0.000000 +1.000000 -0.000302 \r\n-0.000239 +0.000302 +1.000000 \r\nD constant: 1.7605686 \r\n\r\nBed Topography Report:\r\n\r\n(0,2)           (2,2)\r\n(20,200)        (200,200)\r\n -4.413   -4.477   -4.541  \r\n \r\n -4.492  [-4.556]  -4.620  \r\n \r\n -4.571   -4.635   -4.699  \r\n(20,20)            (200,20)\r\n(0,0)             (2,0)\r\nok\r\n```\r\n\r\nNow, if the compensation would work as (I) expected than executing the command multiple times should always produce the exact same result as the tilt hasn't changed. Instead the error of the mesh gets larger and larger with each iteration.\r\n\r\n\r\n**One possible Solution**\r\nI digged through the code to find out what is causing this behavior but  I couldn't wrap my head around how the rotation matrix is constructed and how the rotation itself is executed. Might be an easy fix but that has to be done by someone who knows this code better than I do. Since I need this function for my new printer I decided to rewrite the function with a simpler approach and might as well share it. This is what I came up with:\r\n\r\n```\r\n    void unified_bed_leveling::tilt_mesh_based_on_3pts(const float &z1, const float &z2, const float &z3) {\r\n      matrix_3x3 rotation;\r\n      vector_3 v1 = vector_3( (UBL_PROBE_PT_1_X - UBL_PROBE_PT_2_X),\r\n                              (UBL_PROBE_PT_1_Y - UBL_PROBE_PT_2_Y),\r\n                              (z1 - z2) ),\r\n\r\n               v2 = vector_3( (UBL_PROBE_PT_3_X - UBL_PROBE_PT_2_X),\r\n                              (UBL_PROBE_PT_3_Y - UBL_PROBE_PT_2_Y),\r\n                              (z3 - z2) ),\r\n\r\n    //First we calculated the tilted plane using the point-normal form, with va being the normal and va being the receptor point.\r\n    //The tilt of original mesh has already been substracted in the previous function. No extra steps required.\r\n               va = vector_3(UBL_PROBE_PT_2_X, UBL_PROBE_PT_2_Y, z2),\r\n\r\n               vn = vector_3::cross(v1, v2);\r\n\r\n      for (uint8_t i = 0; i < GRID_MAX_POINTS_X; i++) {\r\n        for (uint8_t j = 0; j < GRID_MAX_POINTS_Y; j++) {\r\n          float x_tmp = mesh_index_to_xpos(i),\r\n                y_tmp = mesh_index_to_ypos(j),\r\n                z_tmp = z_values[i][j];\r\n\r\n    //We translate the point-normal form of the plane to the general form and solve for z.\r\n          float z_shift = -(vn.x*x_tmp + vn.y*y_tmp - vn.x*va.x - vn.y*va.y - vn.z*va.z) / vn.z;\r\n\r\n          z_values[i][j] += z_shift;\r\n        }\r\n      }\r\n    }\r\n```\r\nInstead of doing a accurate rotation of the points this function uses more of an projection by translating the offsets of the original (tilted) plane to the new measured plane. I will do a bit more testing but seems to work quite nicely:\r\n\r\nSame steps as above. Original Mesh:\r\n```\r\nBed Topography Report:\r\n\r\n(0,2)           (2,2)\r\n(20,200)        (200,200)\r\n  0.000    0.000  [ 0.000] \r\n \r\n  0.000    0.000    0.000  \r\n \r\n  0.000    0.000    0.000  \r\n(20,20)            (200,20)\r\n(0,0)             (2,0)\r\nok\r\n```\r\n\r\nExecuting G29 J multiple times:\r\n```\r\nBed X: 21.000 Y: 21.000 Z: 0.355\r\necho:busy: processing\r\necho:busy: processing\r\necho:busy: processing\r\nBed X: 199.000 Y: 21.000 Z: 0.310\r\necho:busy: processing\r\necho:busy: processing\r\nBed X: 110.000 Y: 199.000 Z: 0.392\r\necho:busy: processing\r\n\r\nBed Topography Report:\r\n\r\n(0,2)           (2,2)\r\n(20,200)        (200,200)\r\n  0.416    0.393    0.370  \r\n \r\n  0.385  [ 0.362]   0.340  \r\n \r\n  0.355    0.332    0.309  \r\n(20,20)            (200,20)\r\n(0,0)             (2,0)\r\nok\r\necho:busy: processing\r\necho:busy: processing\r\necho:busy: processing\r\necho:busy: processing\r\necho:busy: processing\r\necho:busy: processing\r\necho:busy: processing\r\nok\r\n\r\nBed Topography Report:\r\n\r\n(0,2)           (2,2)\r\n(20,200)        (200,200)\r\n  0.412    0.390    0.369  \r\n \r\n  0.382  [ 0.361]   0.339  \r\n \r\n  0.352    0.331    0.309  \r\n(20,20)            (200,20)\r\n(0,0)             (2,0)\r\nok\r\necho:busy: processing\r\necho:busy: processing\r\necho:busy: processing\r\necho:busy: processing\r\necho:busy: processing\r\necho:busy: processing\r\necho:busy: processing\r\nok\r\n\r\nBed Topography Report:\r\n\r\n(0,2)           (2,2)\r\n(20,200)        (200,200)\r\n  0.417    0.393    0.369  \r\n \r\n  0.387  [ 0.363]   0.339  \r\n \r\n  0.357    0.333    0.309  \r\n(20,20)            (200,20)\r\n(0,0)             (2,0)\r\nok\r\n```\r\nEven if executed multiple times G29 J now produces always the same mesh (in margin of the measurement deviation). Further, the mesh points close to the probe point now have an accurate value."},"comment":{"url":"https://api.github.com/repos/MarlinFirmware/Marlin/issues/comments/347207618","html_url":"https://github.com/MarlinFirmware/Marlin/issues/8576#issuecomment-347207618","issue_url":"https://api.github.com/repos/MarlinFirmware/Marlin/issues/8576","id":347207618,"user":{"login":"Roxy-3D","id":8404322,"avatar_url":"https://avatars0.githubusercontent.com/u/8404322?v=4","gravatar_id":"","url":"https://api.github.com/users/Roxy-3D","html_url":"https://github.com/Roxy-3D","followers_url":"https://api.github.com/users/Roxy-3D/followers","following_url":"https://api.github.com/users/Roxy-3D/following{/other_user}","gists_url":"https://api.github.com/users/Roxy-3D/gists{/gist_id}","starred_url":"https://api.github.com/users/Roxy-3D/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Roxy-3D/subscriptions","organizations_url":"https://api.github.com/users/Roxy-3D/orgs","repos_url":"https://api.github.com/users/Roxy-3D/repos","events_url":"https://api.github.com/users/Roxy-3D/events{/privacy}","received_events_url":"https://api.github.com/users/Roxy-3D/received_events","type":"User","site_admin":false},"created_at":"2017-11-27T14:58:56Z","updated_at":"2017-11-27T14:58:56Z","author_association":"CONTRIBUTOR","body":"I'll try to check for an regressions in the 3-point leveling today.   It used to work exactly as you say you expect it to work."}}
{"actor":{"display_login":"Roxy-3D"}}