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>
This commit is contained in:
parent
e0c947e188
commit
efb4a5daa1
|
@ -66,36 +66,30 @@ class DeltaKinematics:
|
||||||
- (self.towers[i][1] - coord[1])**2) + coord[2]
|
- (self.towers[i][1] - coord[1])**2) + coord[2]
|
||||||
for i in StepList]
|
for i in StepList]
|
||||||
def _actuator_to_cartesian(self, pos):
|
def _actuator_to_cartesian(self, pos):
|
||||||
# Based on code from Smoothieware
|
# Find nozzle position using trilateration (see wikipedia)
|
||||||
tower1 = list(self.towers[0]) + [pos[0]]
|
carriage1 = list(self.towers[0]) + [pos[0]]
|
||||||
tower2 = list(self.towers[1]) + [pos[1]]
|
carriage2 = list(self.towers[1]) + [pos[1]]
|
||||||
tower3 = list(self.towers[2]) + [pos[2]]
|
carriage3 = list(self.towers[2]) + [pos[2]]
|
||||||
|
|
||||||
s12 = matrix_sub(tower1, tower2)
|
s21 = matrix_sub(carriage2, carriage1)
|
||||||
s23 = matrix_sub(tower2, tower3)
|
s31 = matrix_sub(carriage3, carriage1)
|
||||||
s13 = matrix_sub(tower1, tower3)
|
|
||||||
|
|
||||||
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)
|
x = d**2 / (2. * d)
|
||||||
magsq_s23 = matrix_magsq(s23)
|
y = (j**2 + (x-i)**2 - x**2) / (2. * j)
|
||||||
magsq_s13 = matrix_magsq(s13)
|
z = -math.sqrt(self.arm_length2 - x**2 - y**2)
|
||||||
|
|
||||||
inv_nmag_sq = 1.0 / matrix_magsq(normal)
|
ex_x = matrix_mul(ex, x)
|
||||||
q = 0.5 * inv_nmag_sq
|
ey_y = matrix_mul(ey, y)
|
||||||
|
ez_z = matrix_mul(ez, z)
|
||||||
a = q * magsq_s23 * matrix_dot(s12, s13)
|
return matrix_add(carriage1, matrix_add(ex_x, matrix_add(ey_y, ez_z)))
|
||||||
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))
|
|
||||||
def set_position(self, newpos):
|
def set_position(self, newpos):
|
||||||
pos = self._cartesian_to_actuator(newpos)
|
pos = self._cartesian_to_actuator(newpos)
|
||||||
for i in StepList:
|
for i in StepList:
|
||||||
|
@ -236,6 +230,9 @@ def matrix_dot(m1, m2):
|
||||||
def matrix_magsq(m1):
|
def matrix_magsq(m1):
|
||||||
return m1[0]**2 + m1[1]**2 + m1[2]**2
|
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):
|
def matrix_sub(m1, m2):
|
||||||
return [m1[0] - m2[0], m1[1] - m2[1], m1[2] - m2[2]]
|
return [m1[0] - m2[0], m1[1] - m2[1], m1[2] - m2[2]]
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue