aboutsummaryrefslogtreecommitdiffstats
path: root/klippy
diff options
context:
space:
mode:
authorKevin O'Connor <kevin@koconnor.net>2017-10-29 10:42:12 -0400
committerKevin O'Connor <kevin@koconnor.net>2017-12-08 18:09:19 -0500
commitefb4a5daa191c9724f1e2faa619f075f89e3085b (patch)
tree9ddf0c9d0363e089a0650105ac13df23f600dc6f /klippy
parente0c947e1888ce8dd5b6948afc3d4782469fe5f28 (diff)
downloadkutter-efb4a5daa191c9724f1e2faa619f075f89e3085b.tar.gz
kutter-efb4a5daa191c9724f1e2faa619f075f89e3085b.tar.xz
kutter-efb4a5daa191c9724f1e2faa619f075f89e3085b.zip
delta: Rework actuator_to_cartesian() using trilateration
Use the formulas for trilateration (instead of the circumcenter formulas) when calculating the position of the nozzle from the position of the carriages. The trilateration formula is more general and it allows each tower to have a different arm length. Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
Diffstat (limited to 'klippy')
-rw-r--r--klippy/delta.py49
1 files changed, 23 insertions, 26 deletions
diff --git a/klippy/delta.py b/klippy/delta.py
index 3b3f24ef..0ab914cf 100644
--- a/klippy/delta.py
+++ b/klippy/delta.py
@@ -66,36 +66,30 @@ class DeltaKinematics:
- (self.towers[i][1] - coord[1])**2) + coord[2]
for i in StepList]
def _actuator_to_cartesian(self, pos):
- # Based on code from Smoothieware
- tower1 = list(self.towers[0]) + [pos[0]]
- tower2 = list(self.towers[1]) + [pos[1]]
- tower3 = list(self.towers[2]) + [pos[2]]
+ # Find nozzle position using trilateration (see wikipedia)
+ carriage1 = list(self.towers[0]) + [pos[0]]
+ carriage2 = list(self.towers[1]) + [pos[1]]
+ carriage3 = list(self.towers[2]) + [pos[2]]
- s12 = matrix_sub(tower1, tower2)
- s23 = matrix_sub(tower2, tower3)
- s13 = matrix_sub(tower1, tower3)
+ s21 = matrix_sub(carriage2, carriage1)
+ s31 = matrix_sub(carriage3, carriage1)
- normal = matrix_cross(s12, s23)
+ d = math.sqrt(matrix_magsq(s21))
+ ex = matrix_mul(s21, 1. / d)
+ i = matrix_dot(ex, s31)
+ vect_ey = matrix_sub(s31, matrix_mul(ex, i))
+ ey = matrix_mul(vect_ey, 1. / math.sqrt(matrix_magsq(vect_ey)))
+ ez = matrix_cross(ex, ey)
+ j = matrix_dot(ey, s31)
- magsq_s12 = matrix_magsq(s12)
- magsq_s23 = matrix_magsq(s23)
- magsq_s13 = matrix_magsq(s13)
+ x = d**2 / (2. * d)
+ y = (j**2 + (x-i)**2 - x**2) / (2. * j)
+ z = -math.sqrt(self.arm_length2 - x**2 - y**2)
- inv_nmag_sq = 1.0 / matrix_magsq(normal)
- q = 0.5 * inv_nmag_sq
-
- a = q * magsq_s23 * matrix_dot(s12, s13)
- b = -q * magsq_s13 * matrix_dot(s12, s23) # negate because we use s12 instead of s21
- c = q * magsq_s12 * matrix_dot(s13, s23)
-
- circumcenter = [tower1[0] * a + tower2[0] * b + tower3[0] * c,
- tower1[1] * a + tower2[1] * b + tower3[1] * c,
- tower1[2] * a + tower2[2] * b + tower3[2] * c]
-
- r_sq = 0.5 * q * magsq_s12 * magsq_s23 * magsq_s13
- dist = math.sqrt(inv_nmag_sq * (self.arm_length2 - r_sq))
-
- return matrix_sub(circumcenter, matrix_mul(normal, dist))
+ ex_x = matrix_mul(ex, x)
+ ey_y = matrix_mul(ey, y)
+ ez_z = matrix_mul(ez, z)
+ return matrix_add(carriage1, matrix_add(ex_x, matrix_add(ey_y, ez_z)))
def set_position(self, newpos):
pos = self._cartesian_to_actuator(newpos)
for i in StepList:
@@ -236,6 +230,9 @@ def matrix_dot(m1, m2):
def matrix_magsq(m1):
return m1[0]**2 + m1[1]**2 + m1[2]**2
+def matrix_add(m1, m2):
+ return [m1[0] + m2[0], m1[1] + m2[1], m1[2] + m2[2]]
+
def matrix_sub(m1, m2):
return [m1[0] - m2[0], m1[1] - m2[1], m1[2] - m2[2]]