修改文件名属性
This commit is contained in:
@ -3,6 +3,7 @@ from collections import defaultdict
|
||||
from tqdm import tqdm
|
||||
from gurobipy import *
|
||||
from sklearn.linear_model import LinearRegression
|
||||
from sklearn.svm import SVR
|
||||
|
||||
import os
|
||||
import time
|
||||
@ -14,9 +15,13 @@ import argparse
|
||||
import joblib
|
||||
import pickle
|
||||
import warnings
|
||||
import heapq
|
||||
import numpy as np
|
||||
import pandas as pd
|
||||
import matplotlib.pyplot as plt
|
||||
import matplotlib
|
||||
|
||||
matplotlib.use('TkAgg')
|
||||
|
||||
# 机器参数
|
||||
max_head_index, max_slot_index = 6, 120
|
||||
@ -29,7 +34,7 @@ head_nozzle = ['' for _ in range(max_head_index)] # 头上已经分配吸嘴
|
||||
slotf1_pos, slotr1_pos = [-31.267, 44.], [807., 810.545] # F1(前基座最左侧)、R1(后基座最右侧)位置
|
||||
fix_camera_pos = [269.531, 694.823] # 固定相机位置
|
||||
anc_marker_pos = [336.457, 626.230] # ANC基准点位置
|
||||
stopper_pos = [535.150, 124.738] # 止档块位置
|
||||
stopper_pos = [665.150, 124.738] # 止档块位置
|
||||
|
||||
# 算法权重参数
|
||||
e_nz_change, e_gang_pick = 4, 0.6
|
||||
@ -39,12 +44,14 @@ head_rotary_velocity = 8e-5 # 贴装头R轴旋转时间
|
||||
x_max_velocity, y_max_velocity = 1.4, 1.2
|
||||
x_max_acceleration, y_max_acceleration = x_max_velocity / 0.079, y_max_velocity / 0.079
|
||||
|
||||
# 不同种类供料器宽度
|
||||
feeder_width = {'SM8': (7.25, 7.25), 'SM12': (7.00, 20.00), 'SM16': (7.00, 22.00),
|
||||
'SM24': (7.00, 29.00), 'SM32': (7.00, 44.00)}
|
||||
# TODO: 不同种类供料器宽度
|
||||
feeder_width = {'SM8': (7.25, 7.25), 'SM12': (7.25, 7.25), 'SM16': (7.25, 7.25),
|
||||
'SM24': (7.25, 7.25), 'SM32': (7.25, 7.25)}
|
||||
# feeder_width = {'SM8': (7.25, 7.25), 'SM12': (7.00, 20.00), 'SM16': (7.00, 22.00),
|
||||
# 'SM24': (7.00, 29.00), 'SM32': (7.00, 44.00)}
|
||||
|
||||
# 可用吸嘴数量限制
|
||||
nozzle_limit = {'CN065': 6, 'CN040': 6, 'CN220': 6, 'CN400': 6, 'CN140': 6}
|
||||
nozzle_limit = {'CN065': 6, 'CN040': 6, 'CN020': 6, 'CN400': 6, 'CN140': 6}
|
||||
|
||||
# 时间参数
|
||||
t_cycle = 0.3
|
||||
@ -61,21 +68,31 @@ T_pp, T_tr, T_nc, T_pl = 2, 5, 25, 0
|
||||
class OptInfo:
|
||||
def __init__(self):
|
||||
self.total_time = .0 # 总组装时间
|
||||
self.total_points = .0 # 总贴装点数
|
||||
self.total_points = 0 # 总贴装点数
|
||||
self.total_components = 0 # 总元件数
|
||||
|
||||
self.pickup_time = .0 # 拾取过程运动时间
|
||||
self.round_time = .0 # 往返基座/基板运动时间
|
||||
self.place_time = .0 # 贴装过程运动时间
|
||||
self.operation_time = .0 # 拾取/贴装/换吸嘴等机械动作用时
|
||||
|
||||
self.cycle_counter = 0 # 周期数
|
||||
self.nozzle_change_counter = 0 # 吸嘴更换次数
|
||||
self.anc_round_counter = 0 # 前往ANC次数
|
||||
self.pickup_counter = 0 # 拾取次数
|
||||
self.cycle_counter = 0 # 周期数
|
||||
self.nozzle_change_counter = 0 # 吸嘴更换次数
|
||||
self.anc_round_counter = 0 # 前往ANC次数
|
||||
self.pickup_counter = 0 # 拾取次数
|
||||
|
||||
self.total_distance = .0 # 总移动路径
|
||||
self.place_distance = .0 # 贴装移动路径
|
||||
self.pickup_distance = .0 # 拾取移动路径
|
||||
self.total_distance = .0 # 总移动路径
|
||||
self.place_distance = .0 # 贴装移动路径
|
||||
self.pickup_distance = .0 # 拾取移动路径
|
||||
|
||||
def print(self):
|
||||
print('-Cycle counter: {}'.format(self.cycle_counter))
|
||||
|
||||
print(f'-Nozzle change counter: {self.nozzle_change_counter: d}')
|
||||
print(f'-ANC round: {self.anc_round_counter: d}')
|
||||
print(f'-Pick operation counter: {self.pickup_counter: d}')
|
||||
print(f'-Pick time: {self.pickup_time: .3f}, Pick distance: {self.pickup_distance: .3f}')
|
||||
print(f'-Place time: {self.place_time: .3f}, Place distance: {self.place_distance: .3f}')
|
||||
|
||||
|
||||
def axis_moving_time(distance, axis=0):
|
||||
@ -145,12 +162,13 @@ def feeder_assignment(component_data, pcb_data, component_result, cycle_result):
|
||||
feeder_slot_result, feeder_group_result = [], []
|
||||
feeder_limit = defaultdict(int)
|
||||
for component in range(len(component_data)):
|
||||
feeder_limit[component] = component_data.loc[component]['feeder-limit']
|
||||
feeder_limit[component] = component_data.loc[component].fdn
|
||||
|
||||
for component_cycle in component_result:
|
||||
new_feeder_group = []
|
||||
for component in component_cycle:
|
||||
if component == -1 or feeder_limit[component] == 0 or new_feeder_group.count(component) >= feeder_limit[component]:
|
||||
if component == -1 or feeder_limit[component] == 0 or new_feeder_group.count(component) >= feeder_limit[
|
||||
component]:
|
||||
new_feeder_group.append(-1)
|
||||
else:
|
||||
new_feeder_group.append(component)
|
||||
@ -401,8 +419,11 @@ def dynamic_programming_cycle_path(pcb_data, cycle_placement, assigned_feeder):
|
||||
|
||||
|
||||
@timer_wrapper
|
||||
def greedy_placement_route_generation(component_data, pcb_data, component_result, cycle_result, feeder_slot_result, hinter=True):
|
||||
def greedy_placement_route_generation(component_data, pcb_data, component_result, cycle_result, feeder_slot_result,
|
||||
hinter=True):
|
||||
placement_result, head_sequence_result = [], []
|
||||
if len(pcb_data) == 0:
|
||||
return placement_result, head_sequence_result
|
||||
mount_point_index = [[] for _ in range(len(component_data))]
|
||||
mount_point_pos = [[] for _ in range(len(component_data))]
|
||||
|
||||
@ -1037,7 +1058,7 @@ def convert_line_assigment(pcb_data, component_data, assignment_result):
|
||||
|
||||
# === averagely assign available feeder ===
|
||||
for part_index, data in component_data.iterrows():
|
||||
feeder_limit = data['feeder-limit']
|
||||
feeder_limit = data.fdn
|
||||
feeder_points = [assignment_result[machine_index][part_index] for machine_index in range(machine_number)]
|
||||
|
||||
for machine_index in range(machine_number):
|
||||
@ -1047,23 +1068,30 @@ def convert_line_assigment(pcb_data, component_data, assignment_result):
|
||||
if feeder_points[machine_index] == 0:
|
||||
continue
|
||||
|
||||
arg_feeder = max(math.floor(feeder_points[machine_index] / sum(feeder_points) * data['feeder-limit']), 1)
|
||||
|
||||
partial_component_data[machine_index].loc[part_index, 'feeder-limit'] = arg_feeder
|
||||
feeder_limit -= arg_feeder
|
||||
|
||||
for machine_index in range(machine_number):
|
||||
if feeder_limit <= 0:
|
||||
break
|
||||
|
||||
if feeder_points[machine_index] == 0:
|
||||
continue
|
||||
partial_component_data[machine_index].loc[part_index, 'feeder-limit'] += 1
|
||||
partial_component_data[machine_index].loc[part_index].fdn = 1
|
||||
feeder_limit -= 1
|
||||
|
||||
while feeder_limit:
|
||||
assign_machine = None
|
||||
for machine_index in range(machine_number):
|
||||
if feeder_limit <= 0:
|
||||
break
|
||||
|
||||
if feeder_points[machine_index] == 0:
|
||||
continue
|
||||
|
||||
if assign_machine is None or feeder_points[machine_index] / \
|
||||
partial_component_data[machine_index].loc[part_index].fdn > feeder_points[
|
||||
assign_machine] / partial_component_data[assign_machine].loc[part_index].fdn:
|
||||
assign_machine = machine_index
|
||||
|
||||
partial_component_data[assign_machine].loc[part_index, 'fdn'] += 1
|
||||
feeder_limit -= 1
|
||||
assert assign_machine is not None
|
||||
|
||||
for machine_index in range(machine_number):
|
||||
if feeder_points[machine_index] > 0:
|
||||
assert partial_component_data[machine_index].loc[part_index, 'feeder-limit'] > 0
|
||||
assert partial_component_data[machine_index].loc[part_index].fdn > 0
|
||||
|
||||
# === assign placements ===
|
||||
part2idx = defaultdict(int)
|
||||
@ -1127,57 +1155,23 @@ def convert_line_assigment(pcb_data, component_data, assignment_result):
|
||||
partial_component_data[idx].loc[part_index, 'points'] += 1
|
||||
partial_pcb_data[idx] = pd.concat([partial_pcb_data[idx], pd.DataFrame(data).T])
|
||||
|
||||
# === adjust the number of available feeders for single optimization separately ===
|
||||
# for machine_index, data in partial_pcb_data.items():
|
||||
# part_info = [] # part info list:(part index, part points, available feeder-num, upper feeder-num)
|
||||
# for part_index, cp_data in partial_component_data[machine_index].iterrows():
|
||||
# if assignment_result[machine_index][part_index]:
|
||||
# part_info.append(
|
||||
# [part_index, assignment_result[machine_index][part_index], 1, cp_data['feeder-limit']])
|
||||
#
|
||||
# part_info = sorted(part_info, key=lambda x: x[1], reverse=True)
|
||||
# start_index, end_index = 0, min(max_head_index - 1, len(part_info) - 1)
|
||||
# while start_index < len(part_info):
|
||||
# assign_part_point, assign_part_index = [], []
|
||||
# for idx_ in range(start_index, end_index + 1):
|
||||
# for _ in range(part_info[idx_][2]):
|
||||
# assign_part_point.append(part_info[idx_][1] / part_info[idx_][2])
|
||||
# assign_part_index.append(idx_)
|
||||
#
|
||||
# variance = np.std(assign_part_point)
|
||||
# while start_index <= end_index:
|
||||
# part_info_index = assign_part_index[np.argmax(assign_part_point)]
|
||||
#
|
||||
# if part_info[part_info_index][2] < part_info[part_info_index][3]: # 供料器数目上限的限制
|
||||
# part_info[part_info_index][2] += 1
|
||||
# end_index -= 1
|
||||
#
|
||||
# new_assign_part_point, new_assign_part_index = [], []
|
||||
# for idx_ in range(start_index, end_index + 1):
|
||||
# for _ in range(part_info[idx_][2]):
|
||||
# new_assign_part_point.append(part_info[idx_][1] / part_info[idx_][2])
|
||||
# new_assign_part_index.append(idx_)
|
||||
#
|
||||
# new_variance = np.std(new_assign_part_point)
|
||||
# if variance < new_variance:
|
||||
# part_info[part_info_index][2] -= 1
|
||||
# end_index += 1
|
||||
# break
|
||||
#
|
||||
# variance = new_variance
|
||||
# assign_part_index, assign_part_point = new_assign_part_index.copy(), new_assign_part_point.copy()
|
||||
# else:
|
||||
# break
|
||||
#
|
||||
# start_index = end_index + 1
|
||||
# end_index = min(start_index + max_head_index - 1, len(part_info) - 1)
|
||||
#
|
||||
# max_avl_feeder = max(part_info, key=lambda x: x[2])[2]
|
||||
# for info in part_info:
|
||||
# partial_component_data[machine_index].loc[info[0], 'feeder-limit'] = math.ceil(info[2] / max_avl_feeder)
|
||||
|
||||
for machine_index in range(machine_number):
|
||||
partial_component_data[machine_index] = partial_component_data[machine_index][
|
||||
partial_component_data[machine_index]['points'] != 0].reset_index(drop=True)
|
||||
|
||||
return partial_pcb_data, partial_component_data
|
||||
|
||||
|
||||
def random_division(num, div):
|
||||
assert num >= div
|
||||
res = [1 for _ in range(num)]
|
||||
while sum(res) < num:
|
||||
pos = random.randint(0, num - 1)
|
||||
val = random.randint(1, num - sum(res))
|
||||
res[pos] = val
|
||||
|
||||
return res
|
||||
|
||||
|
||||
def list_range(start, end=None):
|
||||
return list(range(start)) if end is None else list(range(start, end))
|
||||
|
Reference in New Issue
Block a user