Hi, thank you for your reply, the lookahead code treats linear and circular segments equally, because I think, for the lookahead code, an arc is nothing more than a line segment that has two tangents.
# Class to track each move request
class Move:
def __init__(self, toolhead, start_pos, end_pos, speed):
# source code ...
# 圆弧插补
self.LineType = 1
self.tangent_s = [self.axes_r[0], self.axes_r[1]]
self.tangent_e = [self.axes_r[0], self.axes_r[1]]
class Move_Arc(Move):
def __init__(self, toolhead, start_pos, end_pos, speed, IJ, G23):
self.toolhead = toolhead
self.start_pos = tuple(start_pos)
self.end_pos = tuple(end_pos)
self.accel = toolhead.max_accel
self.junction_deviation = toolhead.junction_deviation
self.timing_callbacks = []
velocity = min(speed, toolhead.max_velocity)
self.is_kinematic_move = True
self.axes_d = axes_d = [ep - sp for sp, ep in zip(start_pos, end_pos)]
self.LineType = 2
if G23 == False: self.LineType = 3
self.I = I = IJ[0]
self.J = J = IJ[1]
Radius = math.sqrt(I * I + J * J)
dx = axes_d[0]
dy = axes_d[1]
tangent_s = [0., 0.]
tangent_e = [0., 0.]
U = [-I / Radius, -J / Radius]
V = [(dx - I) / Radius, (dy - J) / Radius]
beta = math.acos(max(-1., min(1., U[0]*V[0] + U[1]*V[1])))
cross = U[0] * V[1] - U[1] * V[0]
if G23 == True: # G2 clockwise
Theta = beta
if cross >= 0: Theta = 2.0 * math.pi - beta
tangent_s[0] = -J / Radius
tangent_s[1] = I / Radius
tangent_e[0] = (dy - J) / Radius
tangent_e[1] = (I - dx) / Radius
else: # G3 counter-clockwise
Theta = beta
if cross <= 0: Theta = 2.0 * math.pi - beta
tangent_s[0] = J / Radius
tangent_s[1] = -I / Radius
tangent_e[0] = -(dy - J) / Radius
tangent_e[1] = -(I - dx) / Radius
self.tangent_s = tangent_s
self.tangent_e = tangent_e
self.move_d = move_d = Radius * Theta
if move_d < .000000001: # Extrude only move
self.end_pos = ((start_pos[0], start_pos[1], start_pos[2])
+ self.end_pos[3:])
axes_d[0] = axes_d[1] = axes_d[2] = 0.
self.move_d = move_d = max([abs(ad) for ad in axes_d[3:]])
inv_move_d = 0.
if move_d: inv_move_d = 1. / move_d
self.accel = 99999999.9
velocity = speed
self.is_kinematic_move = False
else:
inv_move_d = 1. / move_d
self.axes_r = [d * inv_move_d for d in axes_d]
# X, Y axes must be active for arc moves
self.axes_r[0] = 0.5 * (1.0 - self.axes_r[3])
self.axes_r[1] = 0.5 * (1.0 - self.axes_r[3])
self.min_move_t = move_d / velocity
self.max_start_v2 = 0.
self.max_cruise_v2 = velocity**2
self.delta_v2 = 2.0 * move_d * self.accel
self.next_junction_v2 = 999999999.9
self.max_mcr_start_v2 = 0.
self.mcr_delta_v2 = 2.0 * move_d * toolhead.mcr_pseudo_accel
def calc_junction(self, prev_move):
if not self.is_kinematic_move or not prev_move.is_kinematic_move:
return
# Allow extra axes to calculate maximum junction
ea_v2 = [ea.calc_junction(prev_move, self, e_index+3)
for e_index, ea in enumerate(self.toolhead.extra_axes)]
# Find max velocity using tangent vectors at junction
junction_cos_theta = -(self.tangent_s[0] * prev_move.tangent_e[0]
+ self.tangent_s[1] * prev_move.tangent_e[1])
sin_theta_d2 = math.sqrt(max(0.5 * (1.0 - junction_cos_theta), 0.))
cos_theta_d2 = math.sqrt(max(0.5 * (1.0 + junction_cos_theta), 0.))
one_minus_sin_theta_d2 = 1. - sin_theta_d2
if one_minus_sin_theta_d2 > 0. and cos_theta_d2 > 0.:
R_jd = sin_theta_d2 / one_minus_sin_theta_d2
move_jd_v2 = R_jd * self.junction_deviation * self.accel
pmove_jd_v2 = R_jd * prev_move.junction_deviation * prev_move.accel
quarter_tan_theta_d2 = .25 * sin_theta_d2 / cos_theta_d2
move_centripetal_v2 = self.delta_v2 * quarter_tan_theta_d2
pmove_centripetal_v2 = prev_move.delta_v2 * quarter_tan_theta_d2
max_start_v2 = min([self.max_cruise_v2,
prev_move.max_cruise_v2,
prev_move.next_junction_v2,
prev_move.max_start_v2 + prev_move.delta_v2,
move_jd_v2, pmove_jd_v2,
move_centripetal_v2, pmove_centripetal_v2]
+ ea_v2)
self.max_start_v2 = max_start_v2
self.max_mcr_start_v2 = min(
max_start_v2,
prev_move.max_mcr_start_v2 + prev_move.mcr_delta_v2)
junction_cos_theta is determined by:
junction_cos_theta = -(self.tangent_s[0] * prev_move.tangent_e[0]
+ self.tangent_s[1] * prev_move.tangent_e[1])