FlexSim实战练习(二)——多品种小批量订单拣选作业

FlexSim实战练习(二)

提示:这里需要用到脚本函数有两个

  • Array.splic(int fromindex,int count)
  • Array.splic(int fromindex,int count,Array insert())
Array cars = ["Volvo","BMW","Audi","Ford"];
cars.splice(2,2); // ["Volvo", "Ford"]
cars.splice(3, 1, ["Lotus", "Kia"]);  	// ["Volvo", "BMW", "Lotus", "Kia", "Ford"]

Array.append(Array otherArray)

Array myArray = [1,2,3,4,5];
myArray.append([7,8,9]);   //[1,2,3,4,5,7,8,9]

以上FlexSim软件版本为19版。


1、案例背景及3D布局说明

在这里插入图片描述

如图所示,系统会按照时间表(Arrival Schedule)生成不同类型的产品。
首先,根据产品类型分别进入对应的两个传送带上;
然后,根据产品的批次在合成器上进行合成;
最后,进入到一个暂存区进行缓存,等待订单计划下达。

产品到达
在这里插入图片描述
其中,ID表示产品编号,Type表示产品类型,B_ID表示产品一批次的数量。
在这里插入图片描述
这张图表示,一共有4种类型的订单(该全局表名称“info”),其中类型1订单需要{ST101,ST102,ST103,ST104}共4种产品组成,类型2,、类型3以及类型4订单如图所示。


2、详细流程图文解释

在整个仿真项目流程中,一共可以分为三个部分:

  • 产品在发生器上产生,通过传送带进入合成器进行合成批次,最后进入缓存区等待订单下达;
  • 订单下达指令;
  • 订单下达后,操作员就会前往缓存区,对缓存区上的产品进行刷选,选择下达订单需要的产品搬运至放有tote的暂存区上进行订单组成。当满足订单需求后,操作员就会搬运该订单前往中转场。

第一步在这里插入图片描述

完成后,你的模型布局应该类似于上图。
具体操作如下:

  1. 从Library模型库中拖出3个Source,4个Queue,2个Straight Conveyor,2个Combiner;
  2. 按照图中连线方式进行"A"链接;

注意,2个Source、2个Queue与2个Combiner链接时,必须要Source首先链接到Combiner,且2个Source都产生Pallet.

  1. 2个Conveyor的上游Queue,双击打开,找到send to port,并选择By Expression>item.Type;
  2. 选择一个Combiner,在进入触发和离开触发中,写上代码如下:
//进入触发
if (port == 2) 
{  
	int de=item.B_ID;
  Table thelist = getvarnode(current, "componentlist");
  treenode thesum = getvarnode(current, "targetcomponentsum");
 // thesum.value = 0;
  for(int index = 1; index <= thelist.numRows; index++) 
  {
   thelist[index][1] = item.B_ID;
    //inc(thesum, item.B_ID);
  }
}
//离开触发
item.labels.assert("B_ID").value = item.first.B_ID;
item.labels.assert("ID").value = item.first.ID;
//把产品上的标识赋值给下面的托盘。
  1. 对combiner下游的Queue,在进入触发里设置Push to List1,并打开List1列表,进行如下的设置;
    在这里插入图片描述
    以上是"第一部分"流程的所有活动。


第二步

具体操作如下:

  1. 从库中将以下实体添加到model中:
    (1)1个 Source
    (2)1个Queue
    (3) 1个"Operator1"
  2. 将Source和Queue进行"A"链接;
  3. 在Queue的进入触发上,写上如下代码:
treenode OP=Model.find("Operator1");
senddelayedmessage(OP,0,current,item.Order,0,0);//item.Order对应的是订单编号

应该会有人问,这第二步的作用是什么。它的作用就是:利用发生器按时间间隔发送一个Box到Queue上,使进入触发的代码被触发,这一个流程来模拟"订单下发"动作。
Source的设置可以参考我的,当然,你也可以自己编写。
在这里插入图片描述
以上是"第二部分"流程的所有活动。


第三步

  1. 从库中将以下实体添加到"model中:
    (1)1个 Source;
    (2)12个Queu;
    (3)1个BasicFR;
  2. 按照文章第一张图布局的样子,对Source与1个Queue进行"A"链接,同时,Queue与另外10个Queue进行"A"链接;
  3. 对下游10个Queue的进入触发中设置Push to List1:
if(true) 
	{
		string listName = "List1";
		List(listName).push(item,2);
	}
  1. Process Flow>Add a general Process Flow,最终流程图样如下:
    在这里插入图片描述

以下操作都将在Process Flow 上进行:
(1)拉入1个事件监听的发生器,并用吸管吸取操作员的On Message,同时在Msg Param1这一行,写入"Order",并选择assign,Order表示订单编号。
(2)拉入1个Pull form List 和1个List,通过Pull form List右边的感叹号与List进行链接。打开Pull form List,在Assign to 中写入token.Pallet,并在Partition ID填入2,表示为拉入的token.Pallet是10个Queue进入的Tote。
(3)拉入2个Assign Labels,并分别命名为“goal_01”和“Array”。goal_01的作用是获取当前下达订单对应需要几种产品,因此,代码为Table("info").cell(token.Order,1).as(Table).numRows。Array的作用是将当前订单对应的产品编号,通过数组的形式存储到对应的Queue上,即up(token.Pallet)。代码如下:

Table dd=Table("info").cell(token.Order,1);
Array Save =up(token.Pallet).as(Object).save;
for(int i=1;i<=token.goal;i++)
{
	string name=dd.cell(i,1).value;
	Save.append([name]);
}
	return Save;
  1. 拉入1个Assign Labels,并命名为“OP”,用于将model中的操作员以及中转场进行赋值。
    在这里插入图片描述
  2. 拉入1个Assign Labels:“goal_02”,1个Wait for event,1个Delay,1个Decide,并进行连线,如图所示。
    在这里插入图片描述
    这里,goal_02的作用是获取进入缓存区的产品数量Queue_Num=token.Q_01.subnodes.length,在Decide中进行判断token.Queue_Num >=1,如果成立,token就会顺着直线往下走;否则,token就会前往Wait for event等待并监听缓存区有产品进入后,再次判断token.Queue_Num >=1是否成立。
  3. 拉入1个Custom Code,1个Assign Labels,1个Delay,1个Decide,并进行连线,如图所示。
    在这里插入图片描述
    其中Custom Code的代码如下:
treenode BF=Model.find("BasicFR1");//就是之前拉入的BasicFR,这边需要注意名字要一样,或者改成你model中BF的名字;
int Queue_num=token.Q_01.subnodes.length;//再次获取缓存区中产品的数量值,确定for循环的次数。
Array save_item=Model.find("BasicFR1").save_item;//获取BF上的Array数组(以下简称BF);
Array Save=up(token.Pallet).save;//获取Tote存放的Queue上的Array数组(以下简称Qu);
for(int i=1;i<=Queue_num;i++)
{
	treenode item=token.Q_01.subnodes[i];
	string item_id=item.ID;
	for(int j=1;j<=Save.length;j++)
	{
		string order_id=Save[j];
		if(item_id==order_id)//如果缓存区中有产品属于当前订单组成部分,则把Qu中该产品编号从数组中剔除出去,并在BF中添加被剔除的产品编号
		{
			Save.splice(j,1);
			save_item.append([order_id]);
			break;
		}
	}	
}
int array_num=save_item.length;
if(array_num == 4)//获取BF数组长度,如果长度==4,说明目前产品已满足订单需求;如果长度==0,说明目前产品不属于该订单;
{
	BF.panduan = 1;
}
else if(array_num ==0)
{
	BF.panduan = 3;
}
else
{
	BF.panduan = 2;
}

判断完毕后,将判断结果赋值给BasicFR的panduan标签。最后通过Decide把token送到对应的下游去。
8. 这一步没有什么好讲的,主要是从BF上save_item存着需要搬运的订单组,以及订单组的长度save_item_L;
在这里插入图片描述
在这里插入图片描述
9. 这里的代码需要注意的是,把BF上存放订单的Array("save_item ")清空,用于下个token进入时的保存。
在这里插入图片描述
以上是第三步的所有活动。


总结

由于篇幅的限制,许多知识点无法详细说明,而且其中一些代码只适用于订单数量为4个的时候,存在优化的空间。

FlexSim软件中,token是指在模拟过程中代表实体或者物体的标识符。每个token都有一些属性和行为,可以在模型中进行操作和控制。在引用\[1\]中提到的例子中,token被用来模拟公交车的到达和站点的序号。其中,token的属性包括ID和ID_num。ID表示公交车到达的站点序号,而ID_num表示模拟公交车的站点名。通过对这些属性进行操作和控制,可以实现公交车在不同站点之间的移动和行为。在FlexSim中,可以使用脚本函数如Numtostring(num value)或者string.fromNum(double num, int precision = -1)来处理数字和字符串的转换。此外,还可以使用Concat函数来连接字符串。在模拟过程中,可以通过设置token的属性和行为来模拟不同的场景和行为。 #### 引用[.reference_title] - *1* *2* [FlexSim实战练习(一)——公交车上下乘客](https://blog.csdn.net/qq_39571346/article/details/112824376)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [四种发生器的使用方法——FlexSim](https://blog.csdn.net/qq_39571346/article/details/112765515)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值