整线优化第一版论文定稿工程
增加了整线批量测试 修改了现有min-max模型路径 修改了遗传算法整体框架 估计器增加异常数据剔除 封装优化结果类 修改供料器扫描算法中重复吸嘴组的判定
This commit is contained in:
@ -11,6 +11,7 @@ import math
|
||||
import random
|
||||
import copy
|
||||
import torch
|
||||
import torch.nn
|
||||
import argparse
|
||||
import joblib
|
||||
import pickle
|
||||
@ -20,6 +21,7 @@ import numpy as np
|
||||
import pandas as pd
|
||||
import matplotlib.pyplot as plt
|
||||
import matplotlib
|
||||
import traceback
|
||||
|
||||
matplotlib.use('TkAgg')
|
||||
|
||||
@ -64,6 +66,18 @@ t_fix_camera_check = 0.12 # 固定相机检测时间
|
||||
# 时间参数(整线相关)
|
||||
T_pp, T_tr, T_nc, T_pl = 2, 5, 25, 0
|
||||
|
||||
# 时间参数 (数据拟合获得)
|
||||
Fit_cy, Fit_nz, Fit_pu, Fit_pl, Fit_mv = 0.326, 0.8694, 0.159, 0.041, 0.001
|
||||
|
||||
|
||||
class OptResult:
|
||||
def __init__(self, cp_assign=None, cycle_assign=None, slot_assign=None, place_assign=None, sequence_assign=None):
|
||||
self.component_assign = [] if cp_assign is None else cp_assign
|
||||
self.cycle_assign = [] if cycle_assign is None else cycle_assign
|
||||
self.feeder_slot_assign = [] if slot_assign is None else slot_assign
|
||||
self.placement_assign = [] if place_assign is None else place_assign
|
||||
self.head_sequence = [] if sequence_assign is None else sequence_assign
|
||||
|
||||
|
||||
class OptInfo:
|
||||
def __init__(self):
|
||||
@ -93,6 +107,22 @@ class OptInfo:
|
||||
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}')
|
||||
print(
|
||||
f'-Round time: {self.total_time - self.place_time - self.place_time: .3f}, Place distance: '
|
||||
f'{self.total_distance - self.pickup_distance - self.place_distance: .3f}')
|
||||
|
||||
minutes, seconds = int(self.total_time // 60), int(self.total_time) % 60
|
||||
millisecond = int((self.total_time - minutes * 60 - seconds) * 60)
|
||||
|
||||
print(f'-Operation time: {self.operation_time: .3f}, ', end='')
|
||||
if minutes > 0:
|
||||
print(f'Total time: {minutes: d} min {seconds} s {millisecond: 2d} ms ({self.total_time: .3f}s)')
|
||||
else:
|
||||
print(f'Total time: {seconds} s {millisecond :2d} ms ({self.total_time :.3f}s)')
|
||||
|
||||
def metric(self):
|
||||
return Fit_cy * self.cycle_counter + Fit_nz * self.nozzle_change_counter + Fit_pu * self.pickup_counter + \
|
||||
Fit_pl * self.total_points + Fit_mv * self.pickup_distance
|
||||
|
||||
|
||||
def axis_moving_time(distance, axis=0):
|
||||
@ -438,6 +468,8 @@ def greedy_placement_route_generation(component_data, pcb_data, component_result
|
||||
for cycle_set in range(len(component_result)):
|
||||
floor_cycle, ceil_cycle = sum(cycle_result[:cycle_set]), sum(cycle_result[:(cycle_set + 1)])
|
||||
for cycle in range(floor_cycle, ceil_cycle):
|
||||
if sum(component_result[cycle_set]) == -max_head_index:
|
||||
continue
|
||||
# search_dir = 1 - search_dir
|
||||
assigned_placement = [-1] * max_head_index
|
||||
max_pos = [max(mount_point_pos[component_index], key=lambda x: x[0]) for component_index in
|
||||
@ -936,7 +968,7 @@ def constraint_swap_mutation(component_points, individual, machine_number):
|
||||
for points in component_points.values():
|
||||
if component_index == 0:
|
||||
while True:
|
||||
index1, index2 = random.sample(range(points + machine_number - 2), 2)
|
||||
index1, index2 = random.sample(range(points + machine_number - 1), 2)
|
||||
if offspring[idx + index1] != offspring[idx + index2]:
|
||||
break
|
||||
|
||||
@ -1050,11 +1082,13 @@ def convert_line_assigment(pcb_data, component_data, assignment_result):
|
||||
placement_points = []
|
||||
partial_pcb_data, partial_component_data = defaultdict(pd.DataFrame), defaultdict(pd.DataFrame)
|
||||
for machine_index in range(machine_number):
|
||||
partial_pcb_data[machine_index] = pd.DataFrame(columns=pcb_data.columns)
|
||||
if pcb_data is not None:
|
||||
partial_pcb_data[machine_index] = pd.DataFrame(columns=pcb_data.columns)
|
||||
partial_component_data[machine_index] = component_data.copy(deep=True)
|
||||
placement_points.append(sum(assignment_result[machine_index]))
|
||||
|
||||
assert sum(placement_points) == len(pcb_data)
|
||||
if pcb_data is not None:
|
||||
assert sum(placement_points) == len(pcb_data)
|
||||
|
||||
# === averagely assign available feeder ===
|
||||
for part_index, data in component_data.iterrows():
|
||||
@ -1062,7 +1096,11 @@ def convert_line_assigment(pcb_data, component_data, assignment_result):
|
||||
feeder_points = [assignment_result[machine_index][part_index] for machine_index in range(machine_number)]
|
||||
|
||||
for machine_index in range(machine_number):
|
||||
partial_component_data[machine_index].loc[part_index, 'points'] = 0
|
||||
if pcb_data is None:
|
||||
partial_component_data[machine_index].loc[part_index, 'points'] = assignment_result[machine_index][
|
||||
part_index]
|
||||
else:
|
||||
partial_component_data[machine_index].loc[part_index, 'points'] = 0
|
||||
|
||||
for machine_index in range(machine_number):
|
||||
if feeder_points[machine_index] == 0:
|
||||
@ -1084,80 +1122,81 @@ def convert_line_assigment(pcb_data, component_data, assignment_result):
|
||||
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
|
||||
partial_component_data[assign_machine].loc[part_index, 'fdn'] += 1
|
||||
|
||||
feeder_limit -= 1
|
||||
|
||||
for machine_index in range(machine_number):
|
||||
if feeder_points[machine_index] > 0:
|
||||
assert partial_component_data[machine_index].loc[part_index].fdn > 0
|
||||
|
||||
# === assign placements ===
|
||||
part2idx = defaultdict(int)
|
||||
for idx, data in component_data.iterrows():
|
||||
part2idx[data.part] = idx
|
||||
if pcb_data is not None:
|
||||
part2idx = defaultdict(int)
|
||||
for idx, data in component_data.iterrows():
|
||||
part2idx[data.part] = idx
|
||||
|
||||
machine_average_pos = [[0, 0] for _ in range(machine_number)]
|
||||
machine_step_counter = [0 for _ in range(machine_number)]
|
||||
part_pcb_data = defaultdict(list)
|
||||
for _, data in pcb_data.iterrows():
|
||||
part_pcb_data[part2idx[data.part]].append(data)
|
||||
machine_average_pos = [[0, 0] for _ in range(machine_number)]
|
||||
machine_step_counter = [0 for _ in range(machine_number)]
|
||||
part_pcb_data = defaultdict(list)
|
||||
for _, data in pcb_data.iterrows():
|
||||
part_pcb_data[part2idx[data.part]].append(data)
|
||||
|
||||
multiple_component_index = []
|
||||
for part_index in range(len(component_data)):
|
||||
machine_assign_set = []
|
||||
for machine_index in range(machine_number):
|
||||
if assignment_result[machine_index][part_index]:
|
||||
machine_assign_set.append(machine_index)
|
||||
|
||||
if len(machine_assign_set) == 1:
|
||||
for data in part_pcb_data[part_index]:
|
||||
machine_index = machine_assign_set[0]
|
||||
|
||||
machine_average_pos[machine_index][0] += data.x
|
||||
machine_average_pos[machine_index][1] += data.y
|
||||
|
||||
machine_step_counter[machine_index] += 1
|
||||
|
||||
partial_component_data[machine_index].loc[part_index, 'points'] += 1
|
||||
partial_pcb_data[machine_index] = pd.concat([partial_pcb_data[machine_index], pd.DataFrame(data).T])
|
||||
|
||||
elif len(machine_assign_set) > 1:
|
||||
multiple_component_index.append(part_index)
|
||||
|
||||
for machine_index in range(machine_number):
|
||||
if machine_step_counter[machine_index] == 0:
|
||||
continue
|
||||
machine_average_pos[machine_index][0] /= machine_step_counter[machine_index]
|
||||
machine_average_pos[machine_index][1] /= machine_step_counter[machine_index]
|
||||
|
||||
for part_index in multiple_component_index:
|
||||
for data in part_pcb_data[part_index]:
|
||||
idx = -1
|
||||
min_dist = None
|
||||
multiple_component_index = []
|
||||
for part_index in range(len(component_data)):
|
||||
machine_assign_set = []
|
||||
for machine_index in range(machine_number):
|
||||
if partial_component_data[machine_index].loc[part_index, 'points'] >= \
|
||||
assignment_result[machine_index][part_index]:
|
||||
continue
|
||||
dist = (data.x - machine_average_pos[machine_index][0]) ** 2 + (
|
||||
data.y - machine_average_pos[machine_index][1]) ** 2
|
||||
if min_dist is None or dist < min_dist:
|
||||
min_dist, idx = dist, machine_index
|
||||
if assignment_result[machine_index][part_index]:
|
||||
machine_assign_set.append(machine_index)
|
||||
|
||||
assert idx >= 0
|
||||
machine_step_counter[idx] += 1
|
||||
machine_average_pos[idx][0] += (1 - 1 / machine_step_counter[idx]) * machine_average_pos[idx][0] + data.x / \
|
||||
machine_step_counter[idx]
|
||||
machine_average_pos[idx][1] += (1 - 1 / machine_step_counter[idx]) * machine_average_pos[idx][1] + data.y / \
|
||||
machine_step_counter[idx]
|
||||
if len(machine_assign_set) == 1:
|
||||
for data in part_pcb_data[part_index]:
|
||||
machine_index = machine_assign_set[0]
|
||||
|
||||
partial_component_data[idx].loc[part_index, 'points'] += 1
|
||||
partial_pcb_data[idx] = pd.concat([partial_pcb_data[idx], pd.DataFrame(data).T])
|
||||
machine_average_pos[machine_index][0] += data.x
|
||||
machine_average_pos[machine_index][1] += data.y
|
||||
|
||||
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)
|
||||
machine_step_counter[machine_index] += 1
|
||||
|
||||
partial_component_data[machine_index].loc[part_index, 'points'] += 1
|
||||
partial_pcb_data[machine_index] = pd.concat([partial_pcb_data[machine_index], pd.DataFrame(data).T])
|
||||
|
||||
elif len(machine_assign_set) > 1:
|
||||
multiple_component_index.append(part_index)
|
||||
|
||||
for machine_index in range(machine_number):
|
||||
if machine_step_counter[machine_index] == 0:
|
||||
continue
|
||||
machine_average_pos[machine_index][0] /= machine_step_counter[machine_index]
|
||||
machine_average_pos[machine_index][1] /= machine_step_counter[machine_index]
|
||||
|
||||
for part_index in multiple_component_index:
|
||||
for data in part_pcb_data[part_index]:
|
||||
idx = -1
|
||||
min_dist = None
|
||||
for machine_index in range(machine_number):
|
||||
if partial_component_data[machine_index].loc[part_index, 'points'] >= \
|
||||
assignment_result[machine_index][part_index]:
|
||||
continue
|
||||
dist = (data.x - machine_average_pos[machine_index][0]) ** 2 + (
|
||||
data.y - machine_average_pos[machine_index][1]) ** 2
|
||||
if min_dist is None or dist < min_dist:
|
||||
min_dist, idx = dist, machine_index
|
||||
|
||||
assert idx >= 0
|
||||
machine_step_counter[idx] += 1
|
||||
machine_average_pos[idx][0] += (1 - 1 / machine_step_counter[idx]) * machine_average_pos[idx][0] \
|
||||
+ data.x / machine_step_counter[idx]
|
||||
machine_average_pos[idx][1] += (1 - 1 / machine_step_counter[idx]) * machine_average_pos[idx][1] \
|
||||
+ data.y / machine_step_counter[idx]
|
||||
|
||||
partial_component_data[idx].loc[part_index, 'points'] += 1
|
||||
partial_pcb_data[idx] = pd.concat([partial_pcb_data[idx], pd.DataFrame(data).T])
|
||||
|
||||
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
|
||||
|
||||
|
Reference in New Issue
Block a user