这次国赛整体比较顺利,由于对A题偏微分方程的知识所知甚少,出题当晚即确定了B题,并和队友讨论清楚了RGV的整个运转过程,差点没忍住当晚就开始写代码哈哈哈。第一天晚上粗略计算到带故障排除的一道工序情况,但直到第二天晚上才顺利解出并修正所有结果。此外,一定要规划好写作的内容和进度,得出的成果在论文中展现不出来就白搭。
这次的赛题并不好套用智能算法,因此不妨尝试自己建立模型,整个RGV调度过程会很清晰地被模拟出来。以下是具体解题过程:
RGV有互斥的四种状态:移动、停止等待、上下料和清洗作业。
上下料:在第一次操作时,在CNC上没有熟料时(即CNC未开始工作时),RGV只对其进行上料操作,但是由于两个机械爪是连在一个机械臂上的,下料操作也会被被执行。也就是说,RGV对CNC完成一次上下料的时间是固定的,而不管CNC上是否有熟料。
清洗作业:清洗作业包括放熟料到清洗槽、取成料到下料传送带共两步(实际清洗时间可忽略)。在RGV在第一次进行清洗作业时,清洗槽内没有成料,但是由于两个机械爪是连在一个机械臂上的,取成料操作也会被执行。也就是说,RGV的清洗作业时间是固定的,而不管清洗槽内是否有成料。
移动:题目中默认RGV只有在收到某CNC需求信号后,才会移动至该CNC处,对其进行上下料操作。
由于上、下料传送带都既能连动,也能独立运动。因此CNC在从上料传送带取生料时、将成料放到下料传送带时,RGV均无需等待或移动,可直接操作。
首先,RGV根据距离就近原则选择下一操作的CNC。在RGV对所有CNC完成一次上料操作后,不断进行上下料->清洗作业->上下料…的循环操作。
matlab代码如下,输出结果见case_1_result变量,可直接导入对应的Excel。
clear all;clc;
%cnc:
% 第一行:cnc位置常量
% 第二行:cnc工作变量,空闲为0,忙碌为1
% 第三行:cnc工作时间,为常量560
% 第四行:cnc上下料时间
% 第五行:cnc预计完成时间
% 第六行:cnc加工物料数
cnc = load ('1_cnc_1.txt');
cnc(6,:)=-1;
%rgv:
% 第一行:rgv初始位置变量,初始为1
% 第二行:rgv工作变量,进行上下料或清洗作业,空闲为0,忙碌为1
% 第三行:rgv一次清洗作业时间
% 第四行:rgv预计完成时间
rgv = load ('1_rgv_1.txt');
%speedRgv:
%移动1~3个单位所需时间
speedRgv = load('1_speedRgv_1.txt');
case_1_result = (1:800)';
t = 0;
r = 1; %仅计数用
while t <= 28800 %以秒为计数单位
%1.在rgv和cnc均空闲状态下,找到距离最近的cnc编号
dist = 4;
signal = 0;
for i=1:8
if cnc(2,i) == 0 %如果cnc空闲
if abs(cnc(1,i)-rgv(1))= cnc(5,i) && cnc(5,i) ~= 0
cnc(2,i) = 0;
end
end
if signal == 0
t = t +1;
%else
%continue;
end
end
%计算下料开始时间,即改cnc的下一次上料时间
for i = 1:800
for j =i+1:800
if case_1_result(i,2)==case_1_result(j,2)
case_1_result(i,4)=case_1_result(j,3);
break;
end
end
end
采用的是第一组数据,txt文件如下。第二、三组数据以同样格式生成即可。下同,不再赘述。
1_cnc_1.txt:
1 1 2 2 3 3 4 4
0 0 0 0 0 0 0 0
560 560 560 560 560 560 560 560
28 31 28 31 28 31 28 31
0 0 0 0 0 0 0 0
1_rgv_1.txt:
1
0
25
0
1_speedRgv_1.txt:
20
33
46
首先,将加工第一道工序的CNC记为A类CNC;加工第二道工序的CNC为B类CNC。RGV在对所有A类CNC进行一次上下料之后,不断进行A->B->A->B…的循环访问,即RGV从A类CNC处取到半熟料后,下一操作只能是对B类CNC进行上下料操作;RGV在清洗作业完成后,下一操作只能是对A类CNC进行上下料操作。对A、B类CNC的数目和位置分布,采用全排列暴力解决(运行时间较长,应再优化),找出A类和B类CNC的比例和在8个位置上最优的分布位置。
matlab代码如下:
clear all;clc;
%全局搜索判优使用
% ls = [1,2,3,4,5,6,7,8];
% tmp = 0;
% f = perms(ls);
% for ii = 1:length(f)
% ls1 = f(ii,1:4);
% ls2 = f(ii,5:8);
%做第一、二道工序的cnc:
ls1=[1,4,6,8];
ls2=[2,3,5,7];
work1=400;
work2=378;
%%数据导入
%1.cnc:
% 第一行:cnc位置常量
% 第二行:cnc工作变量,空闲为0,忙碌为1
% 第三行:cnc工作时间
% 第四行:cnc上下料时间
% 第五行:cnc预计完成时间
% 第六行:正在加工的物料编号
% 第七行:cnc是否初始判断,0为初始,1位正常
cnc = load ('2_cnc_1.txt');
for i=ls1
cnc(3,i)=work1;
end
for i=ls2
cnc(3,i)=work2;
end
%2.rgv:
% 第一行:rgv初始位置变量,初始为1
% 第二行:rgv工作变量,进行上下料或清洗作业,空闲为0,忙碌为1
% 第三行:rgv一次清洗作业时间
% 第四行:rgv预计完成时间
% 第五行:正在操作的物料编号
rgv = load ('2_rgv_1.txt');
%3.speedRgv:
%移动1~3个单位所需时间
speedRgv = load('2_speedRgv_1.txt');
case_1_result = (1:800)';
t = 0;
r = 1; %计数
flag = 0; %rgv上有半成品物料为1,没有为0;
while t <= 28800 %以秒为计数单位
%1.在rgv和cnc均空闲状态下,找到距离最近的cnc,并让rgv移动过去
% 第一道加工:
dist = 4; signal = 0;
for i=ls1
if cnc(2,i) == 0 && flag == 0 %如果cnc空闲,rgv上没有半成品物料
if abs(cnc(1,i)-rgv(1)) 1 %若该cnc不是初始化状态
rgv(5) = cnc(6,cncNum1); %记录rgv操作的前一个是哪一个物料
flag = 1; % 表示rgv拿了一个物料
end
cnc(5,cncNum1) = t + cnc(3,cncNum1); %cnc预计完成时间=上下料+工作时间
cnc(6,cncNum1) = r; %被加工物料的编号
r = r + 1;
end
%3.rgv在第一道工序的cnc处取物料后,寻找最近的第二道工序cnc
dist = 4;
if cnc(7,cncNum1) > 1 && flag == 1 %如果第一道工序的cnc不是初始状态,且rgv携带了半成品物料
for i=ls2
if cnc(2,i) == 0 %如果第二道工序cnc空闲
if abs(cnc(1,i)-rgv(1)) 1 && cnc(2,cncNum2)==0 && flag == 1 %第二道工序cnc空闲,第一道工序cnc不为初始状态,rgv上有半成品物料
cnc(2,cncNum2) = 1;
flag = 0;
%记录加工cnc的编号
case_1_result(rgv(5),5) = cncNum2;
case_1_result(rgv(5),6) = t;
cnc(6,cncNum2) = rgv(5); %正在被加工物料的编号
t = t + cnc(4,cncNum2); %上下料
signal = 1;
cnc(5,cncNum2) = t + cnc(3,cncNum2); %第二道工序cnc预计完成时间=上下料+工作时间
if cnc(7,cncNum2) > 0
t = t + rgv(3); %时间=上下料+清洗时间
end
cnc(7,cncNum2) = cnc(7,cncNum2) + 1;
end
%5.所有的cnc均忙碌,rgv在等待
for i = 1:8
if t >= cnc(5,i) && cnc(5,i) ~= 0
cnc(2,i) = 0;
end
end
if signal == 0
t = t +1; %若rgv在原地等待
else
continue;
end
end
%计算下料开始时间,即改cnc的下一次上料时间
for i = 1:800
for j =i+1:800
if case_1_result(i,2)==case_1_result(j,2)
case_1_result(i,4)=case_1_result(j,3);
break;
end
end
for k =i+1:800
if case_1_result(i,5)==case_1_result(k,5)
case_1_result(i,7)=case_1_result(k,6);
break;
end
end
end
%全局搜索判优使用
% for i = 1:800
% if case_1_result(i,7)==0
% set = i;
% break;
% end
% end
% if tmp
数据文件如下:
2_cnc_1.txt:
1 1 2 2 3 3 4 4
0 0 0 0 0 0 0 0
378 400 378 400 378 400 378 400
28 31 28 31 28 31 28 31
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
2_rgv_1.txt:
1
0
25
0
0
2_speedRgv_1.txt:
20
33
46
情况三要求考虑机器故障的情况,产生故障的实现方法如下,设置三个变量:1)可能故障时间t1:0到CNC加工完成一个一道工序的物料所需时间之间的随机整数;2)维修时间t2:600到1200之间的随机整数,对应10~20分钟维修时间;3)故障概率p:从均匀分布U(0,1)中随机取一个数小于等于0.01的概率,对应1%。
每一次CNC运行前,判断若p发生,则CNC工作至t1时刻发生故障,再维修t2的时间后,该CNC再次以空闲状态投入使用,并记录本次操作的物料发生异常。
由于代码重合度过高,此处只提供故障判断和处理的代码,添加到CNC上下料操作后即可。
if probability() == 1
fault = unidrnd(cnc(3,1)); %在工作时间内随机产生一个时间点
tBroken = 600 + unidrnd(600); %维修时间在10~20分钟之间
disp('发生故障!');
r = r - 1;
case_1_result(r,4) = inf; %未正常下料标记
case_1_result(r,6) = t + fault; %故障开始时间
case_1_result(r,7) = t + fault + tBroken; %故障结束的时间
case_1_result(r,5) = inf; %发生故障的标志
r = r + 1;
cnc(5,cncNum) = t + fault + tBroken; %cnc故障:cnc预计人工修理完成时间
else
cnc(5,cncNum) = t + cnc(3,cncNum); %正常情况:cnc预计完成时间=上下料+工作时间
cnc(6,cncNum) = cnc(6,cncNum) + 1;
end
%百分之一概率生成函数
function [key] = probability()
R=rand(1,1000);
if(R(100)<=0.01)
key = 1;
else
key = 0;
end
end
默认情况下RGV收到CNC信号才会移动,因此提出基于RGV的预判模型,使RGV在等待时根据CNC工作情况,预先移动到下一要操作的CNC处,从而提高系统的运行效率。
关于RGV在等待时选择下一操作CNC时的判断变量:
S = RGV从当前位置移动到目标CNC处所花的时间t1 + 目标CNC的剩余完成时间t2。
遍历每一个CNC,选出S值最小的CNC作为下一操作CNC。
以一道工序的情况为例,给出预判下的改进模型代码:
clear all;clc;
%cnc:
% 第一行:cnc位置常量
% 第二行:cnc工作变量,空闲为0,忙碌为1
% 第三行:cnc工作时间,为常量560
% 第四行:cnc上下料时间
% 第五行:cnc预计完成时间
% 第六行:cnc加工物料数
cnc = load ('1_cnc_1.txt');
cnc(6,:)=-1;
%rgv:
% 第一行:rgv初始位置变量,初始为1
% 第二行:rgv工作变量,进行上下料或清洗作业,空闲为0,忙碌为1
% 第三行:rgv一次清洗作业时间
% 第四行:rgv预计完成时间
rgv = load ('1_rgv_1.txt');
%speedRgv:
%移动1~3个单位所需时间
speedRgv = load('1_speedRgv_1.txt');
case_1_result = (1:800)';
t = 0;
r = 1; %仅计数用
wait = 0;
while t <= 28800 %以秒为计数单位
%1.在rgv和cnc均空闲状态下,找到距离最近的cnc编号
dist = 4;
signal = 0;
for i=1:8
if cnc(2,i) == 0 %如果cnc空闲
if abs(cnc(1,i)-rgv(1))= cnc(5,i) && cnc(5,i) ~= 0
cnc(2,i) = 0;
end
end
if signal == 0
t = t +1;
wait = 1;
else
continue;
end
end
%计算下料开始时间,即改cnc的下一次上料时间
for i = 1:800
for j =i+1:800
if case_1_result(i,2)==case_1_result(j,2)
case_1_result(i,4)=case_1_result(j,3);
break;
end
end
end
此文仅对本次数模国赛的解题做一个总结希望此文能帮助到有需要的朋友。最后,不得不说这个比赛的写作非常考验数学功底了,一大堆公式看的眼花,所以非常感谢建模小姐姐带飞~
关于数据文件,
生成数据:链接:https://pan.baidu.com/s/1x-7l2INpEkZPWB1bBBH41A 密码:ga49
2020.4 更新下结果,拿了省一,导师说差一点送国家级评选。
新上传了完整的论文、代码和输出结果表格。
本文最后一次更新了,今年就毕业啦,感谢大家的关注。
论文+代码+数据:https://download.csdn.net/download/qq_41148224/12367708