
本文深入探讨如何使用python的simpy库构建和模拟复杂的工厂生产线。通过一个具体的工厂模型案例,详细讲解simpy环境、进程、资源(包括操作员、机器人和工装夹具)的定义与交互,以及如何利用优先级资源管理实现零件的有序流转。文章重点阐述了资源请求与释放的正确实践,帮助读者掌握simpy进行离散事件仿真的核心技术。
SimPy是一个基于Python的离散事件仿真(DES)框架。它允许开发者通过模拟事件的发生和资源的使用来建模和分析复杂系统。在工厂生产线建模中,SimPy能够有效地模拟零件在不同工位、机器和操作员之间流转的过程,从而帮助工程师评估生产效率、识别瓶颈并优化资源配置。
与连续系统仿真不同,离散事件仿真关注的是系统状态在特定时间点(事件发生时)的变化。在工厂场景中,这些事件可能包括零件到达、机器完成加工、操作员开始或结束任务等。SimPy通过其核心概念——环境(Environment)、进程(Process)和资源(Resource)——来构建这些复杂的交互。
在构建工厂模型之前,理解SimPy的几个核心概念至关重要:
我们将通过一个具体的工厂生产线模型来演示SimPy的应用。这个模型模拟了零件从入库到出库的完整流程,涉及操作员、多种机器人和多个工装夹具。
首先,定义一些全局常量,如仿真时长、操作员数量以及各种加工步骤所需的时间。这有助于集中管理模型参数,方便后续调整和实验。
import simpy
import itertools
class g: # 全局常量
t_sim = 600 # 仿真时长,这里设置为600秒,方便观察
operator_qty = 2 # 操作员数量
sWeld_t = 2.75 # 点焊时间 (秒/点)
Adh_t = 1/60 # 涂胶时间 (秒/毫米)
ArcStud_t = 5.5 # 弧焊螺柱时间 (秒/个)
ProjStud_t = 10 # 凸焊螺柱时间 (秒/个)cell_model 类封装了整个工厂单元的逻辑,包括环境初始化、资源定义和零件生成器。
在 __init__ 方法中,我们创建SimPy环境并初始化所有必需的资源。这里使用了 PriorityResource,它允许我们为每个请求指定一个优先级。在本例中,零件的ID(p_Id)被用作优先级,确保零件按照生成顺序(FIFO)进行处理。
class cell_model: # 代表整个工厂单元,包含所有进程、资源和仿真环境
def __init__(self): # 单元的初始条件
self.env = simpy.Environment() # 创建SimPy环境
self.part_counter = 0 # 零件计数器
# 定义操作员资源
self.OP = simpy.PriorityResource(self.env, capacity=g.operator_qty)
# 定义机器人资源,每个机器人容量为1
self.R1 = simpy.PriorityResource(self.env, capacity=1)
self.R2 = simpy.PriorityResource(self.env, capacity=1)
self.R3 = simpy.PriorityResource(self.env, capacity=1)
self.R4 = simpy.PriorityResource(self.env, capacity=1)
# 定义工装夹具资源,每个夹具容量为1
self.Fix01 = simpy.PriorityResource(self.env, capacity=1)
self.Fix02 = simpy.PriorityResource(self.env, capacity=1)
self.Fix101 = simpy.PriorityResource(self.env, capacity=1)
# 启动零件生成器进程
self.env.process(self.part_generator())part_generator 方法是一个SimPy进程,负责周期性地生成新的零件。itertools.count() 用于生成唯一的零件ID。yield self.env.timeout(1) 表示每隔1个模拟时间单位生成一个新零件。
def part_generator(self):
for p_Id in itertools.count(): # 无限生成零件ID
yield self.env.timeout(1) # 每隔1秒生成一个新零件
self.env.process(self.make_part(p_Id)) # 为每个零件启动一个加工进程make_part 方法是整个模型的核心,它详细描述了一个零件从开始加工到完成出库的所有步骤。每个步骤都可能涉及请求资源、等待资源、执行任务(env.timeout)和释放资源。
资源请求与释放策略:
在SimPy中,资源请求和释放有两种常见模式:
在下面的代码中,我们将看到这两种模式的混合使用,特别是对原始代码中资源释放逻辑的修正,以避免资源过早释放导致的问题。
def make_part(self,p_Id): # 描述单个零件在单元中的一系列加工过程
# --- 阶段1:操作员取件并放置到夹具Fix01 ---
OP_req1 = self.OP.request(priority=p_Id) # 请求操作员资源
print(f"part {p_Id} OP request at {self.env.now}")
yield OP_req1 # 等待操作员可用
print(f"part {p_Id} OP seized at {self.env.now}")
print("Part ", p_Id, " is next available at ", self.env.now, sep="")
yield self.env.timeout(29) # 操作员将零件搬运到工位,进行准备工作
Fix01_req = self.Fix01.request(priority=p_Id) # 请求夹具Fix01
print(f"part {p_Id} Fix01 request at {self.env.now}")
yield Fix01_req # 等待夹具Fix01可用
print(f"part {p_Id} Fix01 seized at {self.env.now}")
yield self.env.timeout(27) # 操作员装载零件,启动工位
yield self.OP.release(OP_req1) # 释放操作员资源
print(f"part {p_Id} OP released at {self.env.now}")
print("Operator 01 released part ", p_Id, " at ", self.env.now, sep="")
yield self.env.timeout(0) # 短暂等待
# --- 阶段2:R2机器人进行点焊 (Fix01) ---
# R2使用with语句,因为其任务完成后即释放
with self.R2.request(priority=p_Id) as R2_req:
print(f"part {p_Id} R2 request at {self.env.now}")
yield R2_req # 等待R2机器人可用
print(f"part {p_Id} R2 seized at {self.env.now}")
print("R2 moves to Fixture 01 to work on part ", p_Id, " at ", self.env.now, sep="")
yield self.env.timeout(g.sWeld_t * 11) # R2进行11次点焊
print(f"part {p_Id} R2 released at {self.env.now}")
# --- 阶段3:R1机器人搬运零件,进行焊接,并放置到夹具Fix101 ---
R1_req = self.R1.request(priority=p_Id) # 请求R1机器人
print(f"part {p_Id} R1 request at {self.env.now}")
yield R1_req # 等待R1机器人可用
print(f"part {p_Id} R1 seized at {self.env.now}")
yield self.env.timeout(8) # R1将零件从Fix01移出
print("Part ", p_Id, " is leaving Fixture 01 at ", self.env.now, sep="")
yield self.Fix01.release(Fix01_req) # 释放夹具Fix01
print(f"part {p_Id} Fix01 released at {self.env.now}")
yield self.env.timeout(g.sWeld_t * 13) # R1进行13次点焊
yield self.env.timeout(0)
yield self.env.timeout(g.ArcStud_t * 5) # R1进行5次弧焊螺柱
yield self.env.timeout(8) # R1移动到夹具Fix101
Fix101_req = self.Fix101.request(priority=p_Id) # 请求夹具Fix101
print(f"part {p_Id} Fix101 request at {self.env.now}")
yield Fix101_req # 等待夹具Fix101可用
print(f"part {p_Id} Fix101 seized at {self.env.now}")
print("Part ", p_Id, " enters Fixture 101 at ", self.env.now, sep="")
yield self.R1.release(R1_req) # 释放R1机器人
print(f"part {p_Id} R1 released at {self.env.now}")
# --- 阶段4:R4机器人进行弧焊螺柱 (Fix101) ---
# R4使用with语句
with self.R4.request(priority=p_Id) as R4_req:
print(f"part {p_Id} R4 request at {self.env.now}")
yield R4_req # 等待R4机器人可用
print(f"part {p_Id} R4 seized at {self.env.now}")
yield self.env.timeout(g.ArcStud_t * 6) # R4进行6次弧焊螺柱
print(f"part {p_Id} R4 released at {self.env.now}")
# --- 阶段5:R3机器人搬运零件,进行凸焊和涂胶,并放置到夹具Fix02 ---
R3_req = self.R3.request(priority=p_Id) # 请求R3机器人
print(f"part {p_Id} R3 request at {self.env.now}")
yield R3_req # 等待R3机器人可用
print(f"part {p_Id} R3 seized at {self.env.now}")
yield self.env.timeout(8) # R3将零件从Fix101移出
print("Part ", p_Id, " leaves Fixture 101 at ", self.env.now, sep="")
yield self.Fix101.release(Fix101_req) # 释放夹具Fix101
print(f"part {p_Id} Fix101 released at {self.env.now}")
yield self.env.timeout(g.ProjStud_t * 6) # R3进行6次凸焊螺柱
yield self.env.timeout(0)
yield self.env.timeout(225 * g.Adh_t) # R3涂胶225mm
print("Part ", p_Id, " has adhesive stage finished at ", self.env.now, sep="")
yield self.env.timeout(8) # R3移动到夹具Fix02
Fix02_req = self.Fix02.request(priority=p_Id) # 请求夹具Fix02
print(f"part {p_Id} Fix02 request at {self.env.now}")
yield Fix02_req # 等待夹具Fix02可用
print(f"part {p_Id} Fix02 seized at {self.env.now}")
yield self.env.timeout(0)
print("Part ", p_Id, " enters Fixture 02 at ", self.env.now, sep="")
yield self.R3.release(R3_req) # 释放R3机器人
print(f"part {p_Id} R3 released at {self.env.now}")
# --- 阶段6:操作员进行辅助操作 (Fix02) ---
# 操作员使用with语句
with self.OP.request(priority=p_Id) as OP_req2:
print(f"part {p_Id} OP request at {self.env.now}")
yield OP_req2 # 等待操作员可用
print(f"part {p_Id} OP seized at {self.env.now}")
yield self.env.timeout(38) # 操作员进行辅助操作
yield self.env.timeout(0)
print(f"part {p_Id} OP released at {self.env.now}")
# --- 阶段7:R2机器人再次进行点焊 (Fix02) ---
# R2使用with语句
with self.R2.request(priority=p_Id) as R2_req2:
print(f"part {p_Id} R2 request at {self.env.now}")
yield R2_req2 # 等待R2机器人可用
print(f"part {p_Id} R2 seized at {self.env.now}")
print("R2 moves to Fixture 02 to work on part ", p_Id, " at ", self.env.now, sep="")
yield self.env.timeout(g.sWeld_t * 35) # R2进行35次点焊
yield self.env.timeout(0)
print(f"part {p_Id} R2 released at {self.env.now}")
# --- 阶段8:操作员移除零件 (Fix02) ---
# 操作员使用with语句
with self.OP.request(priority=p_Id) as OP_req3:
print(f"part {p_Id} OP request at {self.env.now}")
yield OP_req3 # 等待操作员可用
print(f"part {p_Id} OP seized at {self.env.now}")
yield self.env.timeout(2) # 操作员移除零件
yield self.Fix02.release(Fix02_req) # 释放夹具Fix02
print(f"part {p_Id} Fix02 released at {self.env.now}")
print("Part ", p_Id, " leaves process at ", self.env.now, sep="")
yield self.env.timeout(0)
print(f"part {p_Id} OP released at {self.env.now}")run 方法负责启动仿真环境,并指定仿真运行的时长。
def run(self,t_sim=g.t_sim): # 运行方法启动实体生成器并告诉SimPy运行环境
self.env.run(until=t_sim)最后,实例化 cell_model 并调用其 run 方法来启动整个仿真。
# 运行仿真
print("Simulation Starting...")
my_model=cell_model()
my_model.run()
print("Simulation Finished.")以上就是SimPy离散事件仿真:构建复杂的工厂生产线模型的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号