添加基础数据结构、公用函数、接口等
This commit is contained in:
51
core/common.py
Normal file
51
core/common.py
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
from functools import wraps, reduce
|
||||||
|
from collections import defaultdict
|
||||||
|
from tqdm import tqdm
|
||||||
|
|
||||||
|
import os
|
||||||
|
import time
|
||||||
|
import math
|
||||||
|
import random
|
||||||
|
import copy
|
||||||
|
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
|
||||||
|
import traceback
|
||||||
|
import openpyxl
|
||||||
|
import itertools
|
||||||
|
|
||||||
|
|
||||||
|
matplotlib.use('TkAgg')
|
||||||
|
|
||||||
|
# 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), 'SME8': (7.25, 7.25),
|
||||||
|
# 'SME12': (7.00, 20.00), 'SME16': (7.00, 22.00), 'SME24': (7.00, 29.00),
|
||||||
|
# 'SME32': (7.00, 44.00), 'Tray Feeder': (7.25, 7.25)}
|
||||||
|
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), 'SME8': (7.25, 7.25),
|
||||||
|
'SME12': (7.25, 7.25), 'SME16': (7.25, 7.25), 'SME24': (7.25, 7.25),
|
||||||
|
'SME32': (7.25, 7.25), 'Tray Feeder': (7.25, 7.25)}
|
||||||
|
|
||||||
|
nozzle_limit = {'CN065': 100, 'CN040': 100, 'CN020': 100, 'CN400': 100, 'CN140': 100, 'CN220': 100, 'CN750': 100}
|
||||||
|
|
||||||
|
|
||||||
|
def timer_wrapper(func):
|
||||||
|
@wraps(func)
|
||||||
|
def measure_time(*args, **kwargs):
|
||||||
|
start_time = time.time()
|
||||||
|
result = func(*args, **kwargs)
|
||||||
|
hinter = True
|
||||||
|
for key, val in kwargs.items():
|
||||||
|
if key == 'hinter':
|
||||||
|
hinter = val
|
||||||
|
if hinter:
|
||||||
|
print(f"function {func.__name__} running time : {time.time() - start_time:.3f} s")
|
||||||
|
return result
|
||||||
|
|
||||||
|
return measure_time
|
||||||
7
core/interface.py
Normal file
7
core/interface.py
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
# 用于提供对外接口
|
||||||
|
from data.type import MachineConfig
|
||||||
|
from opt.smm.basis import *
|
||||||
|
from opt.smm.feeder_priority import FeederPriorityOpt
|
||||||
|
from opt.smm.cell_division import CellDivisionOpt
|
||||||
|
from opt.smm.hybrid_genetic import HybridGeneticOpt
|
||||||
|
from opt.smm.aggregation import Aggregation
|
||||||
67
data/loader.py
Normal file
67
data/loader.py
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
from core.common import *
|
||||||
|
from data.type import Point
|
||||||
|
|
||||||
|
|
||||||
|
def load_data(filename: str):
|
||||||
|
filename = 'file/' + filename
|
||||||
|
origin = Point(0, 0)
|
||||||
|
coordinate = ''
|
||||||
|
part_skiprows, part_rows, step_skiprows, step_rows = -1, -1, -1, -1
|
||||||
|
|
||||||
|
line_counter = 0
|
||||||
|
with open(filename, 'r') as file:
|
||||||
|
while line := file.readline():
|
||||||
|
if line == '[PART]\n':
|
||||||
|
part_skiprows = line_counter + 1
|
||||||
|
elif line == '[STEP]\n':
|
||||||
|
step_skiprows = line_counter + 1
|
||||||
|
elif line == '\n':
|
||||||
|
if part_skiprows != -1 and part_rows == -1:
|
||||||
|
part_rows = line_counter - part_skiprows
|
||||||
|
elif step_skiprows != -1 and step_rows == -1:
|
||||||
|
step_rows = line_counter - step_skiprows
|
||||||
|
|
||||||
|
if line.startswith('Coordinate'):
|
||||||
|
coordinate = line.split('=')[1].strip()
|
||||||
|
elif line.startswith('Placement Origin'):
|
||||||
|
x, y = line.split('=')[1].strip().split(',')
|
||||||
|
origin.x, origin.y = float(x.strip()), float(y.strip())
|
||||||
|
|
||||||
|
line_counter += 1
|
||||||
|
|
||||||
|
if part_skiprows != -1 and part_rows == -1:
|
||||||
|
part_rows = line_counter - part_skiprows
|
||||||
|
if step_skiprows != -1 and step_rows == -1:
|
||||||
|
step_rows = line_counter - step_skiprows
|
||||||
|
|
||||||
|
step_data = pd.DataFrame(
|
||||||
|
pd.read_csv(filepath_or_buffer=filename, skiprows=step_skiprows, nrows=step_rows, sep='\t', header=None))
|
||||||
|
step_data.columns = ["ref", "x", "y", "z", "r", "part", "layer"]
|
||||||
|
|
||||||
|
part_col = ["part", "fdr", "nz", "fdn"]
|
||||||
|
try:
|
||||||
|
if part_skiprows != -1:
|
||||||
|
part_data = pd.DataFrame(pd.read_csv(filepath_or_buffer=filename, sep='\t', header=None,
|
||||||
|
skiprows=part_skiprows, nrows=part_rows))
|
||||||
|
part_data.columns = part_col
|
||||||
|
else:
|
||||||
|
part_data = pd.DataFrame(columns=part_col)
|
||||||
|
except:
|
||||||
|
part_data = pd.DataFrame(columns=part_col)
|
||||||
|
|
||||||
|
for _, data in step_data.iterrows():
|
||||||
|
if data.part not in part_data.part.values:
|
||||||
|
raise Exception("unregistered component: " + data.part)
|
||||||
|
|
||||||
|
if coordinate == "UPPER RIGHT" or coordinate == "LOWER RIGHT":
|
||||||
|
data.x = -data.x
|
||||||
|
if coordinate == "UPPER LEFT" or coordinate == "UPPER RIGHT":
|
||||||
|
data.y = data.y
|
||||||
|
data.x, data.y = data.x + origin.x, data.y + origin.y
|
||||||
|
|
||||||
|
return part_data, step_data
|
||||||
|
|
||||||
|
|
||||||
|
def load_config(filepath: str):
|
||||||
|
pass
|
||||||
|
|
||||||
88
data/type.py
Normal file
88
data/type.py
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
|
||||||
|
|
||||||
|
class Point:
|
||||||
|
def __init__(self, _x, _y, _r=0, _h=None):
|
||||||
|
self.x = _x
|
||||||
|
self.y = _y
|
||||||
|
self.r = _r
|
||||||
|
self.h = _h
|
||||||
|
|
||||||
|
|
||||||
|
class MachineConfig:
|
||||||
|
def __init__(self):
|
||||||
|
self.head_num = 6
|
||||||
|
self.slot_num = 120
|
||||||
|
self.slot_intv = 15
|
||||||
|
self.head_intv = 30
|
||||||
|
self.slotf1_pos = Point(-31.327, 44.)
|
||||||
|
self.slotr1_pos = Point(807., 810.545)
|
||||||
|
self.stopper_pos = Point(665.150, 124.738)
|
||||||
|
self.anc_pos = Point(336.457, 626.230)
|
||||||
|
|
||||||
|
self.pick_time = .078 # ʰȡ<CAB0><C8A1>ʱ
|
||||||
|
self.place_time = .051 # <20><>װ<EFBFBD><D7B0>ʱ
|
||||||
|
self.nozzle_install_time = 0.9 # װ<><D7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ
|
||||||
|
self.nozzle_uninstall_time = 0.75 # ж<><D0B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ
|
||||||
|
|
||||||
|
|
||||||
|
class OptResult:
|
||||||
|
def __init__(self):
|
||||||
|
self.part = []
|
||||||
|
self.cycle = []
|
||||||
|
self.slot = []
|
||||||
|
self.point = []
|
||||||
|
self.sequence = []
|
||||||
|
|
||||||
|
def __add__(self, other):
|
||||||
|
self.part.extend(other.part)
|
||||||
|
self.cycle.extend(other.cycle)
|
||||||
|
self.slot.extend(other.slot)
|
||||||
|
self.point.extend(other.point)
|
||||||
|
self.sequence.extend(other.sequence)
|
||||||
|
|
||||||
|
return self
|
||||||
|
|
||||||
|
|
||||||
|
class OptInfo:
|
||||||
|
def __init__(self):
|
||||||
|
self.total_time = .0 # <20><><EFBFBD><EFBFBD>װʱ<D7B0><CAB1>
|
||||||
|
self.total_points = 0 # <20><><EFBFBD><EFBFBD>װ<EFBFBD><D7B0><EFBFBD><EFBFBD>
|
||||||
|
self.total_components = 0 # <20><>Ԫ<EFBFBD><D4AA><EFBFBD><EFBFBD>
|
||||||
|
|
||||||
|
self.pickup_time = .0 # ʰȡ<CAB0><C8A1><EFBFBD><EFBFBD><EFBFBD>˶<EFBFBD>ʱ<EFBFBD><CAB1>
|
||||||
|
self.round_time = .0 # <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>/<2F><><EFBFBD><EFBFBD><EFBFBD>˶<EFBFBD>ʱ<EFBFBD><CAB1>
|
||||||
|
self.place_time = .0 # <20><>װ<EFBFBD><D7B0><EFBFBD><EFBFBD><EFBFBD>˶<EFBFBD>ʱ<EFBFBD><CAB1>
|
||||||
|
self.operation_time = .0 # ʰȡ/<2F><>װ/<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȼ<EFBFBD>е<EFBFBD><D0B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ
|
||||||
|
|
||||||
|
self.cycle_counter = 0 # <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||||
|
self.nozzle_change_counter = 0 # <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||||
|
self.anc_round_counter = 0 # ǰ<><C7B0>ANC<4E><43><EFBFBD><EFBFBD>
|
||||||
|
self.pickup_counter = 0 # ʰȡ<CAB0><C8A1><EFBFBD><EFBFBD>
|
||||||
|
|
||||||
|
self.total_distance = .0 # <20><><EFBFBD>ƶ<EFBFBD>·<EFBFBD><C2B7>
|
||||||
|
self.place_distance = .0 # <20><>װ<EFBFBD>ƶ<EFBFBD>·<EFBFBD><C2B7>
|
||||||
|
self.pickup_distance = .0 # ʰȡ<CAB0>ƶ<EFBFBD>·<EFBFBD><C2B7>
|
||||||
|
|
||||||
|
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}')
|
||||||
|
print(
|
||||||
|
f'-Round time: {self.total_time - self.operation_time - self.pickup_time - self.place_time: .3f}, Round distance: '
|
||||||
|
f'{self.total_distance - self.pickup_distance - self.place_distance: .3f}')
|
||||||
|
|
||||||
|
print(f'-Round & place time per cycle: {(self.total_time - self.pickup_time - self.operation_time) * 1000.0 / (self.cycle_counter + 1e-10): .3f}, ', end='')
|
||||||
|
print(f'-Round & place distance per cycle: {(self.total_distance - self.pickup_distance) / (self.cycle_counter + 1e-10): .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)')
|
||||||
Reference in New Issue
Block a user