增加超启发式线体优化算法

This commit is contained in:
2024-05-17 22:52:49 +08:00
parent 6fa1f53f69
commit 7c9a900b95
13 changed files with 1731 additions and 1109 deletions

View File

@ -423,7 +423,7 @@ def optimization_assign_result(component_data, pcb_data, component_result, cycle
component_assign.loc[cycle, 'H{}'.format(head + 1)] = ''
else:
part = component_data.loc[index]['part']
component_assign.loc[cycle, 'H{}'.format(head + 1)] = part
component_assign.loc[cycle, 'H{}'.format(head + 1)] = 'C' + str(index)
print(component_assign)
print('')
@ -446,32 +446,36 @@ def optimization_assign_result(component_data, pcb_data, component_result, cycle
print('')
def placement_time_estimate(component_data, pcb_data, component_result, cycle_result, feeder_slot_result,
placement_result, head_sequence, hinter=True) -> float:
def placement_info_evaluation(component_data, pcb_data, component_result, cycle_result, feeder_slot_result,
placement_result=None, head_sequence=None, hinter=False):
# === 优化结果参数 ===
info = OptInfo()
# === 校验 ===
total_points = 0
info.total_points = 0
for cycle, components in enumerate(component_result):
for head, component in enumerate(components):
if component == -1:
continue
total_points += cycle_result[cycle]
info.total_points += cycle_result[cycle]
if total_points != len(pcb_data):
if info.total_points != len(pcb_data):
warning_info = 'the number of placement points is not match with the PCB data. '
warnings.warn(warning_info, UserWarning)
return 0.
for placements in placement_result:
for placement in placements:
if placement == -1:
continue
total_points -= 1
if placement_result:
total_points = info.total_points
for placements in placement_result:
for placement in placements:
if placement == -1:
continue
total_points -= 1
if total_points != 0:
warnings.warn(
'the optimization result of component assignment result and placement result are not consistent. ',
UserWarning)
return 0.
if total_points != 0:
warnings.warn(
'the optimization result of component assignment result and placement result are not consistent. ',
UserWarning)
return 0.
feeder_arrangement = defaultdict(set)
for cycle, feeder_slots in enumerate(feeder_slot_result):
@ -486,12 +490,6 @@ def placement_time_estimate(component_data, pcb_data, component_result, cycle_re
warnings.warn(info, UserWarning)
return 0.
total_pickup_time, total_round_time, total_place_time = .0, .0, 0 # 拾取用时、往返用时、贴装用时
total_operation_time = .0 # 操作用时
total_nozzle_change_counter = 0 # 总吸嘴更换次数
total_pick_counter = 0 # 总拾取次数
total_mount_distance, total_pick_distance = .0, .0 # 贴装距离、拾取距离
total_distance = 0 # 总移动距离
cur_pos, next_pos = anc_marker_pos, [0, 0] # 贴装头当前位置
# 初始化首个周期的吸嘴装配信息
@ -503,7 +501,6 @@ def placement_time_estimate(component_data, pcb_data, component_result, cycle_re
continue
else:
nozzle_assigned[head] = component_data.loc[idx]['nz']
break
for cycle_set, _ in enumerate(component_result):
floor_cycle, ceil_cycle = sum(cycle_result[:cycle_set]), sum(cycle_result[:(cycle_set + 1)])
@ -527,9 +524,9 @@ def placement_time_estimate(component_data, pcb_data, component_result, cycle_re
next_pos = anc_marker_pos
move_time = max(axis_moving_time(cur_pos[0] - next_pos[0], 0),
axis_moving_time(cur_pos[1] - next_pos[1], 1))
total_round_time += move_time
total_distance += max(abs(cur_pos[0] - next_pos[0]), abs(cur_pos[1] - next_pos[1]))
info.round_time += move_time
info.anc_round_counter += 1
info.total_distance += max(abs(cur_pos[0] - next_pos[0]), abs(cur_pos[1] - next_pos[1]))
cur_pos = next_pos
pick_slot = list(set(pick_slot))
@ -541,94 +538,95 @@ def placement_time_estimate(component_data, pcb_data, component_result, cycle_re
next_pos = [slotf1_pos[0] + slot_interval * (slot - 1), slotf1_pos[1]]
else:
next_pos = [slotr1_pos[0] - slot_interval * (max_slot_index - slot - 1), slotr1_pos[1]]
total_operation_time += t_pick
total_pick_counter += 1
info.operation_time += t_pick
info.pickup_counter += 1
move_time = max(axis_moving_time(cur_pos[0] - next_pos[0], 0),
axis_moving_time(cur_pos[1] - next_pos[1], 1))
if idx == 0:
total_round_time += move_time
info.round_time += move_time
else:
total_pickup_time += move_time
info.pickup_time += move_time
total_distance += max(abs(cur_pos[0] - next_pos[0]), abs(cur_pos[1] - next_pos[1]))
info.total_distance += max(abs(cur_pos[0] - next_pos[0]), abs(cur_pos[1] - next_pos[1]))
if slot != pick_slot[0]:
total_pick_distance += max(abs(cur_pos[0] - next_pos[0]), abs(cur_pos[1] - next_pos[1]))
info.pickup_distance += max(abs(cur_pos[0] - next_pos[0]), abs(cur_pos[1] - next_pos[1]))
cur_pos = next_pos
# 固定相机检测
for head in range(max_head_index):
if component_result[cycle_set][head] == -1:
continue
camera = component_data.loc[component_result[cycle_set][head]]['camera']
if camera == '固定相机':
next_pos = [fix_camera_pos[0] - head * head_interval, fix_camera_pos[1]]
move_time = max(axis_moving_time(cur_pos[0] - next_pos[0], 0),
axis_moving_time(cur_pos[1] - next_pos[1], 1))
total_round_time += move_time
total_distance += max(abs(cur_pos[0] - next_pos[0]), abs(cur_pos[1] - next_pos[1]))
total_operation_time += t_fix_camera_check
cur_pos = next_pos
# for head in range(max_head_index):
# if component_result[cycle_set][head] == -1:
# continue
# camera = component_data.loc[component_result[cycle_set][head]]['camera']
# if camera == '固定相机':
# next_pos = [fix_camera_pos[0] - head * head_interval, fix_camera_pos[1]]
# move_time = max(axis_moving_time(cur_pos[0] - next_pos[0], 0),
# axis_moving_time(cur_pos[1] - next_pos[1], 1))
# info.round_time += move_time
#
# info.total_distance += max(abs(cur_pos[0] - next_pos[0]), abs(cur_pos[1] - next_pos[1]))
# info.operation_time += t_fix_camera_check
# cur_pos = next_pos
# 贴装路径
for head in head_sequence[cycle]:
index = placement_result[cycle][head]
if index == -1:
continue
mount_pos.append([pcb_data.iloc[index]['x'] - head * head_interval + stopper_pos[0],
pcb_data.iloc[index]['y'] + stopper_pos[1]])
mount_angle.append(pcb_data.iloc[index]['r'])
if placement_result and head_sequence:
for head in head_sequence[cycle]:
index = placement_result[cycle][head]
if index == -1:
continue
mount_pos.append([pcb_data.iloc[index]['x'] - head * head_interval + stopper_pos[0],
pcb_data.iloc[index]['y'] + stopper_pos[1]])
mount_angle.append(pcb_data.iloc[index]['r'])
# 单独计算贴装路径
for cntPoints in range(len(mount_pos) - 1):
total_mount_distance += max(abs(mount_pos[cntPoints][0] - mount_pos[cntPoints + 1][0]),
abs(mount_pos[cntPoints][1] - mount_pos[cntPoints + 1][1]))
# 单独计算贴装路径
for cntPoints in range(len(mount_pos) - 1):
info.place_distance += max(abs(mount_pos[cntPoints][0] - mount_pos[cntPoints + 1][0]),
abs(mount_pos[cntPoints][1] - mount_pos[cntPoints + 1][1]))
# 考虑R轴预旋转补偿同轴角度转动带来的额外贴装用时
total_operation_time += head_rotary_time(mount_angle[0]) # 补偿角度转动带来的额外贴装用时
total_operation_time += t_nozzle_put * nozzle_put_counter + t_nozzle_pick * nozzle_pick_counter
for idx, pos in enumerate(mount_pos):
total_operation_time += t_place
move_time = max(axis_moving_time(cur_pos[0] - pos[0], 0), axis_moving_time(cur_pos[1] - pos[1], 1))
if idx == 0:
total_round_time += move_time
else:
total_place_time += move_time
# 考虑R轴预旋转补偿同轴角度转动带来的额外贴装用时
info.operation_time += head_rotary_time(mount_angle[0]) # 补偿角度转动带来的额外贴装用时
info.operation_time += t_nozzle_put * nozzle_put_counter + t_nozzle_pick * nozzle_pick_counter
for idx, pos in enumerate(mount_pos):
info.operation_time += t_place
move_time = max(axis_moving_time(cur_pos[0] - pos[0], 0), axis_moving_time(cur_pos[1] - pos[1], 1))
if idx == 0:
info.round_time += move_time
else:
info.place_time += move_time
total_distance += max(abs(cur_pos[0] - pos[0]), abs(cur_pos[1] - pos[1]))
cur_pos = pos
info.total_distance += max(abs(cur_pos[0] - pos[0]), abs(cur_pos[1] - pos[1]))
cur_pos = pos
total_nozzle_change_counter += nozzle_put_counter + nozzle_pick_counter
total_time = total_pickup_time + total_round_time + total_place_time + total_operation_time
minutes, seconds = int(total_time // 60), int(total_time) % 60
millisecond = int((total_time - minutes * 60 - seconds) * 60)
info.nozzle_change_counter += nozzle_put_counter + nozzle_pick_counter
info.total_time = info.pickup_time + info.round_time + info.place_time + info.operation_time
minutes, seconds = int(info.total_time // 60), int(info.total_time) % 60
millisecond = int((info.total_time - minutes * 60 - seconds) * 60)
info.cycle_counter = sum(cycle_result)
if hinter:
optimization_assign_result(component_data, pcb_data, component_result, cycle_result, feeder_slot_result,
nozzle_hinter=False, component_hinter=False, feeder_hinter=False)
print('-Cycle counter: {}'.format(sum(cycle_result)))
print('-Nozzle change counter: {}'.format(total_nozzle_change_counter // 2))
print('-Pick operation counter: {}'.format(total_pick_counter))
print('-Cycle counter: {}'.format(info.cycle_counter))
print('-Nozzle change counter: {}'.format(info.nozzle_change_counter // 2))
print('-Pick operation counter: {}'.format(info.pickup_counter))
print('-Expected mounting tour length: {} mm'.format(total_mount_distance))
print('-Expected picking tour length: {} mm'.format(total_pick_distance))
print('-Expected total tour length: {} mm'.format(total_distance))
print('-Expected mounting tour length: {} mm'.format(info.place_distance))
print('-Expected picking tour length: {} mm'.format(info.pickup_distance))
print('-Expected total tour length: {} mm'.format(info.total_distance))
print('-Expected total moving time: {} s with pick: {}, round: {}, place = {}'.format(
total_pickup_time + total_round_time + total_place_time, total_pickup_time, total_round_time,
total_place_time))
print('-Expected total operation time: {} s'.format(total_operation_time))
info.pickup_time + info.round_time + info.place_time, info.pickup_time, info.round_time,
info.place_time))
print('-Expected total operation time: {} s'.format(info.operation_time))
if minutes > 0:
print('-Mounting time estimation: {:d} min {} s {:2d} ms ({:.3f}s)'.format(minutes, seconds, millisecond,
total_time))
info.total_time))
else:
print('-Mounting time estimation: {} s {:2d} ms ({:.3f}s)'.format(seconds, millisecond, total_time))
print('-Mounting time estimation: {} s {:2d} ms ({:.3f}s)'.format(seconds, millisecond, info.total_time))
return total_time
return info