修改文件名属性
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))
|
||||
|
@ -1,11 +1,11 @@
|
||||
# 用于提供对外接口
|
||||
from base_optimizer.optimizer_scanbased import *
|
||||
from base_optimizer.optimizer_celldivision import *
|
||||
from base_optimizer.optimizer_hybridgenetic import *
|
||||
from base_optimizer.optimizer_feederpriority import *
|
||||
from base_optimizer.optimizer_aggregation import *
|
||||
from base_optimizer.optimizer_twophase import *
|
||||
from base_optimizer.optimizer_mathmodel import *
|
||||
from base_optimizer.smopt_scanbased import *
|
||||
from base_optimizer.smopt_celldivision import *
|
||||
from base_optimizer.smopt_hybridgenetic import *
|
||||
from base_optimizer.smopt_feederpriority import *
|
||||
from base_optimizer.smopt_aggregation import *
|
||||
from base_optimizer.smopt_twophase import *
|
||||
from base_optimizer.smopt_mathmodel import *
|
||||
|
||||
from base_optimizer.result_analysis import *
|
||||
|
||||
@ -25,17 +25,17 @@ def base_optimizer(machine_index, pcb_data, component_data, feeder_data=None, me
|
||||
|
||||
elif method == 'hybrid-genetic': # 基于拾取组的混合遗传算法
|
||||
component_result, cycle_result, feeder_slot_result, placement_result, head_sequence = optimizer_hybrid_genetic(
|
||||
pcb_data, component_data, hinter=False)
|
||||
pcb_data, component_data, hinter=hinter)
|
||||
|
||||
elif method == 'aggregation': # 基于batch-level的整数规划 + 启发式算法
|
||||
component_result, cycle_result, feeder_slot_result, placement_result, head_sequence = optimizer_aggregation(
|
||||
component_data, pcb_data)
|
||||
elif method == 'genetic-scanning':
|
||||
component_result, cycle_result, feeder_slot_result, placement_result, head_sequence = optimizer_genetic_scanning(
|
||||
component_data, pcb_data, hinter=False)
|
||||
component_data, pcb_data, hinter=hinter)
|
||||
elif method == 'mip-model':
|
||||
component_result, cycle_result, feeder_slot_result, placement_result, head_sequence = optimizer_mathmodel(
|
||||
component_data, pcb_data, hinter=True)
|
||||
component_data, pcb_data, hinter=hinter)
|
||||
elif method == "two-phase":
|
||||
component_result, feeder_slot_result, cycle_result = gurobi_optimizer(pcb_data, component_data, feeder_data,
|
||||
initial=True, partition=True,
|
||||
@ -46,22 +46,15 @@ def base_optimizer(machine_index, pcb_data, component_data, feeder_data=None, me
|
||||
else:
|
||||
raise 'machine optimizer method ' + method + ' is not existed'
|
||||
|
||||
print('----- Placement machine ' + str(machine_index) + ' ----- ')
|
||||
# 估算贴装用时
|
||||
info = placement_info_evaluation(component_data, pcb_data, component_result, cycle_result, feeder_slot_result,
|
||||
placement_result, head_sequence, hinter=False)
|
||||
|
||||
if hinter:
|
||||
optimization_assign_result(component_data, pcb_data, component_result, cycle_result, feeder_slot_result,
|
||||
nozzle_hinter=True, component_hinter=True, feeder_hinter=True)
|
||||
info.print()
|
||||
|
||||
print('----- Placement machine ' + str(machine_index) + ' ----- ')
|
||||
print('-Cycle counter: {}'.format(info.cycle_counter))
|
||||
|
||||
print(f'-Nozzle change counter: {info.nozzle_change_counter: d}')
|
||||
print(f'-ANC round: {info.anc_round_counter: d}')
|
||||
print(f'-Pick operation counter: {info.pickup_counter: d}')
|
||||
print(f'-Pick time: {info.pickup_time: .3f}, distance: {info.pickup_distance: .3f}')
|
||||
print(f'-Place time: {info.place_time: .3f}, distance: {info.place_distance: .3f}')
|
||||
print('------------------------------ ')
|
||||
print('------------------------------ ')
|
||||
|
||||
return info
|
||||
|
@ -40,7 +40,6 @@ def convert_pcbdata_to_result(pcb_data, component_data):
|
||||
if slot == 'A':
|
||||
slot, part = 0, pcb_data.loc[point_cnt].part
|
||||
else:
|
||||
|
||||
slot, part = int(slot[1:]), pcb_data.loc[point_cnt].fdr.split(' ', 1)[1]
|
||||
head = pcb_data.loc[point_cnt].hd - 1
|
||||
|
||||
@ -423,7 +422,8 @@ 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)] = 'C' + str(index)
|
||||
component_assign.loc[cycle, 'H{}'.format(head + 1)] = part
|
||||
# component_assign.loc[cycle, 'H{}'.format(head + 1)] = 'C' + str(index)
|
||||
|
||||
print(component_assign)
|
||||
print('')
|
||||
@ -450,6 +450,7 @@ def placement_info_evaluation(component_data, pcb_data, component_result, cycle_
|
||||
placement_result=None, head_sequence=None, hinter=False):
|
||||
# === 优化结果参数 ===
|
||||
info = OptInfo()
|
||||
|
||||
# === 校验 ===
|
||||
info.total_points = 0
|
||||
for cycle, components in enumerate(component_result):
|
||||
@ -461,7 +462,7 @@ def placement_info_evaluation(component_data, pcb_data, component_result, cycle_
|
||||
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.
|
||||
return OptInfo()
|
||||
|
||||
if placement_result:
|
||||
total_points = info.total_points
|
||||
@ -475,7 +476,7 @@ def placement_info_evaluation(component_data, pcb_data, component_result, cycle_
|
||||
warnings.warn(
|
||||
'the optimization result of component assignment result and placement result are not consistent. ',
|
||||
UserWarning)
|
||||
return 0.
|
||||
return OptInfo()
|
||||
|
||||
feeder_arrangement = defaultdict(set)
|
||||
for cycle, feeder_slots in enumerate(feeder_slot_result):
|
||||
@ -484,8 +485,9 @@ def placement_info_evaluation(component_data, pcb_data, component_result, cycle_
|
||||
continue
|
||||
feeder_arrangement[component_result[cycle][head]].add(slot)
|
||||
|
||||
info.total_components = len(feeder_arrangement.keys())
|
||||
for part, data in component_data.iterrows():
|
||||
if part in feeder_arrangement.keys() and data['feeder-limit'] < len(feeder_arrangement[part]):
|
||||
if part in feeder_arrangement.keys() and data.fdn < len(feeder_arrangement[part]):
|
||||
info = 'the number of arranged feeder of [' + data['part'] + '] exceeds the quantity limit'
|
||||
warnings.warn(info, UserWarning)
|
||||
return 0.
|
||||
|
@ -21,8 +21,8 @@ def feeder_priority_assignment(component_data, pcb_data, hinter=True):
|
||||
info = placement_info_evaluation(component_data, pcb_data, component_assign, cycle_assign,
|
||||
feeder_slot_assign, None, None, hinter=False)
|
||||
|
||||
val = 0.4 * info.cycle_counter + 2.15 * info.nozzle_change_counter + 0.11 * info.pickup_counter \
|
||||
+ 0.005 * info.anc_round_counter
|
||||
val = 0.356 * info.cycle_counter + 0.949 * info.nozzle_change_counter + 0.159 * info.pickup_counter \
|
||||
+ 0.002 * info.pickup_distance
|
||||
if feeder_allocate_val is None or val < feeder_allocate_val:
|
||||
feeder_allocate_val = val
|
||||
component_result, cycle_result, feeder_slot_result = component_assign, cycle_assign, feeder_slot_assign
|
||||
@ -91,14 +91,17 @@ def feeder_nozzle_pattern(component_data):
|
||||
for _ in range(head):
|
||||
nozzle_pattern_list[-1][head_assign_indexes[-idx]] = nozzle
|
||||
idx += 1
|
||||
|
||||
nozzle_points.pop(min_points_nozzle)
|
||||
# nozzle_pattern_list = []
|
||||
# nozzle_pattern_list.append(['CN220', 'CN220', 'CN065', 'CN065', 'CN140', 'CN140'])
|
||||
return nozzle_pattern_list
|
||||
|
||||
|
||||
def feeder_allocate(component_data, pcb_data, feeder_data, nozzle_pattern, figure=False, hinter=True):
|
||||
|
||||
feeder_points, feeder_division_points = defaultdict(int), defaultdict(int) # 供料器贴装点数
|
||||
mount_center_pos = defaultdict(float)
|
||||
feeder_center_pos = defaultdict(float)
|
||||
|
||||
feeder_limit, feeder_arrange = defaultdict(int), defaultdict(int)
|
||||
part_nozzle = defaultdict(str)
|
||||
@ -109,7 +112,7 @@ def feeder_allocate(component_data, pcb_data, feeder_data, nozzle_pattern, figur
|
||||
for idx, data in component_data.iterrows():
|
||||
component_index[data.part] = idx
|
||||
|
||||
feeder_limit[idx] = data['feeder-limit']
|
||||
feeder_limit[idx] = data.fdn
|
||||
feeder_arrange[idx] = 0
|
||||
|
||||
for _, data in pcb_data.iterrows():
|
||||
@ -118,7 +121,7 @@ def feeder_allocate(component_data, pcb_data, feeder_data, nozzle_pattern, figur
|
||||
part_index = component_index[part]
|
||||
|
||||
feeder_points[part_index] += 1
|
||||
mount_center_pos[part_index] += ((pos - mount_center_pos[part_index]) / feeder_points[part_index])
|
||||
feeder_center_pos[part_index] += ((pos - feeder_center_pos[part_index]) / feeder_points[part_index])
|
||||
part_nozzle[part_index] = component_data.loc[part_index].nz
|
||||
|
||||
for part_index, points in feeder_points.items():
|
||||
@ -198,8 +201,8 @@ def feeder_allocate(component_data, pcb_data, feeder_data, nozzle_pattern, figur
|
||||
if len(tmp_nozzle_component[nozzle]) == 0:
|
||||
continue
|
||||
part = max(tmp_nozzle_component[nozzle],
|
||||
key=lambda x: tmp_feeder_points[x] / tmp_feeder_limit[x] if
|
||||
tmp_feeder_points[x] != 0 else 0)
|
||||
key=lambda x: tmp_feeder_points[x] / tmp_feeder_limit[x]
|
||||
if tmp_feeder_points[x] != 0 else 0)
|
||||
index_ = tmp_nozzle_component[nozzle].index(part)
|
||||
if max_points < tmp_nozzle_component_points[nozzle][index_]:
|
||||
max_points, nozzle_assign = tmp_nozzle_component_points[nozzle][index_], nozzle
|
||||
@ -210,8 +213,8 @@ def feeder_allocate(component_data, pcb_data, feeder_data, nozzle_pattern, figur
|
||||
if len(tmp_nozzle_component[nozzle_assign]) == 0:
|
||||
# 当前头对应吸嘴类型无可用元件,将计划分配的元件压入堆栈
|
||||
part = max(tmp_feeder_points.keys(),
|
||||
key=lambda x: tmp_feeder_points[x] / tmp_feeder_limit[x] if tmp_feeder_limit[
|
||||
x] != 0 else 0)
|
||||
key=lambda x: tmp_feeder_points[x] / tmp_feeder_limit[x]
|
||||
if tmp_feeder_limit[x] != 0 else 0)
|
||||
for nozzle, component_list in tmp_nozzle_component.items():
|
||||
if part in component_list:
|
||||
nozzle_assign = nozzle
|
||||
@ -227,7 +230,6 @@ def feeder_allocate(component_data, pcb_data, feeder_data, nozzle_pattern, figur
|
||||
tmp_feeder_limit[x] != 0 else 0))
|
||||
|
||||
part = tmp_nozzle_component[nozzle_assign][index_]
|
||||
|
||||
feeder_type = component_data.loc[part].fdr
|
||||
extra_width, extra_slot = feeder_width[feeder_type][0] + feeder_width[feeder_type][1] - slot_interval, 1
|
||||
slot_overlap = False
|
||||
@ -341,7 +343,7 @@ def feeder_allocate(component_data, pcb_data, feeder_data, nozzle_pattern, figur
|
||||
for head, feeder_ in enumerate(feeder_assign):
|
||||
if feeder_ < 0:
|
||||
continue
|
||||
average_slot.append((mount_center_pos[feeder_] - slotf1_pos[0]) / slot_interval + 1)
|
||||
average_slot.append((feeder_center_pos[feeder_] - slotf1_pos[0]) / slot_interval + 1)
|
||||
|
||||
if nozzle_pattern and component_data.loc[feeder_].nz != nozzle_pattern[head]:
|
||||
nozzle_change_counter += 1
|
||||
@ -499,7 +501,9 @@ def feeder_base_scan(component_data, pcb_data, feeder_data):
|
||||
raise ValueError(info)
|
||||
component_points[idx] = data.points
|
||||
component_index[data.part] = idx
|
||||
|
||||
if len(feeder_assign_check) != len(component_points) - component_points.count(0):
|
||||
print(feeder_assign_check)
|
||||
print(component_points)
|
||||
assert len(feeder_assign_check) == len(component_points) - component_points.count(0) # 所有供料器均已分配槽位
|
||||
|
||||
mount_center_slot = defaultdict(float)
|
@ -313,7 +313,7 @@ def optimizer_hybrid_genetic(pcb_data, component_data, hinter=True):
|
||||
idx = component_data[component_data['part'] == part].index.tolist()[0]
|
||||
nozzle = component_data.loc[idx]['nz']
|
||||
|
||||
component_feeder_limit[part] = component_data.loc[idx]['feeder-limit']
|
||||
component_feeder_limit[part] = component_data.loc[idx].fdn
|
||||
component_points[part] += 1
|
||||
if nozzle_components[nozzle].count(part) < component_feeder_limit[part]:
|
||||
nozzle_components[nozzle].append(part)
|
@ -1,10 +1,6 @@
|
||||
from base_optimizer.optimizer_common import *
|
||||
|
||||
|
||||
def list_range(start, end=None):
|
||||
return list(range(start)) if end is None else list(range(start, end))
|
||||
|
||||
|
||||
def head_task_model(component_data, pcb_data, hinter=True):
|
||||
|
||||
mdl = Model('pick_route')
|
Reference in New Issue
Block a user