双伸堆垛机的调度感想
最近接到电信电话,说是办理宽带,赠送的手机卡要每个月用到10G流量;否者就要收费15元;如果用到10G以上,就不收费; 第一次听说过这样奇怪的收费原则;怎么才能肆无忌惮的用掉这么多流量,厂家推荐,在家或在公司,手机不要用连wifi了,直接用4g流量; 当然原因也可以理解,马上5G到了,各大营运商要抓紧让用户养成奢侈的使用流量的习惯;双伸位的堆垛机也有类似的奇怪的地方,既要先进先出,又要减少移动;
在如今地皮越来越紧张的情况下,自动化仓库里,双伸位的堆垛机也越来越普遍了;可是很多客户都有先入先出的要求,而双伸位的堆垛机,是后入先出,类似于计算机里的堆栈概念;这还是稍微有点冲突的;另外如果只是出里面货位的,还要必须把外面的货位临时移走; 当里面的出完了,还可能要求把外面的再移回到以前的地方;这些都要我们做针对性的逻辑调度;
下面老朽从5个方面去构思各个环节的处理;
1. 双伸货位的关键属性:
a.内侧 或 外侧 ,又叫近货位 或远货位(相对堆垛机的位置);
b. 当前货位的兄弟货位号,这个在程序关联处理时将会非常有用;内外侧货位,哪一个为兄,哪一个为弟; 为了便于理解,内侧为弟,外侧为兄; 可以编一个故事理解: 在远古时代,一个山洞只能容纳两个人;为了保护弟弟,让他进入山洞内侧,哥哥留在躲在外侧保护着弟弟;当剑齿虎来吃他们的时候,先用獠牙把外侧的哥哥勾走;
c .两个兄弟货位的最小(或最大)入库时间;这个属性便于在出库分配的时候做一起同时出库的优化处理;
d. 锁定托盘号; 某个货位上,可能指定托盘号;也就是说,只要是这个托盘号准备入库的时候,就一定要分配到这个位置上(除非这个货位上有货 或者 被外侧挡住);这个主要用在某些客户,要求托盘 拣选后 ,托盘还要回到原来的位置;或者因为取内侧托盘导致的外侧移库,等内侧做完,外侧还要移回来;
2. 入库货位分配原则:
a. 内侧无货但是外侧有货,这种情况下,内侧货位不能被分配;
b. 指定托盘号的货位,如果正在入库的托盘和它一致,直接分配该货位 ;否者这些指定托盘号的货位就不要用来分配,打个比喻;这种货位,已经“名花有主”了;
c. 内侧有货外侧无货,将要入库的产品和和内侧一致,生产日期也是同一天的(当然也可能是其他条件,具体项目具体对待),就优先把这个外侧的货位分配掉;这样尽量让两个货位同时填满;打仗亲兄弟,一起上战场,再尽量一起同时为国捐躯;尽量两个货位同时填满,再同时出库;
d. “孤独”货位优先使用,有的货位因为立柱消防等原因,没有兄弟货位;属于“鳏寡孤独” ,这样的货位更适合多多使用,因为是单身汉,自在又潇洒,来去无牵挂;使用起来就和单伸一样,相对不容易出故障;但也要考虑这些单身货位是否距离出库口太远,如果都在远处,这个原则也可以不要;反正具体问题具体分析,而且很多规范的仓库,往往没有这样的货位;
e.内外侧都无货的货位,兄弟货位同时“干净“, 这种货位优先分配内侧;
f. 内侧有货外侧无货,但是将要入库的托盘上的货物和内侧的不一致,这种情况是,在库内无其他货位可分配的情况下,被逼让让这两个货位搭伙过日子;因为出库的时候,大概率是不会一起共同出库的;所以这种分配形式的优先级是最低的;
j.内侧有货外侧无货,但是内侧托盘有待出库的任务,这个时候,万万不可分配到外侧去,哪怕整个巷道就剩下这一个货位了,也不行;
3. 出库备货分配原则:
a. 绝对的精确到秒的先进先出不行;因为大概率的是先入库的放在内侧;所以我们往往以天为单位,方式同一天入库的,先进先出的级别是一样的,也就是说早上8点和晚上5点入库的两个托盘,出库的时候,先出后面的,也不算违反先进先出;
b. 兄弟货位作为一个整体,取他们两个最小(或最大也行)时间作为原则,这个可以精确到秒,分配的时候,以这个时间作为第二优先级排序,这样备货分配的时候,基本上能尽量把两个货位同时分配,也兼顾了同一天入库的,优先出先入库的;
c.外侧货位优先出库,这样万一备货分配到兄弟货位上,只需要一托的时候,就不会出里面的,减少不不要的移动;
d. 已经在出库“半路上”的拣选托盘,这种情况下,备货的时候,也可能分配到这个托盘上,这种情况没法避免的;而且我们需要最优先分配这样的托盘,因为这样的好处是,尽量把一托上拼上多个拣选任务,最好能够把托盘出完,变成整托不用回库; 这就类似出租车最好多拼几个人;当然,从动作上来做,这里也分两种情况:
1.到达拣选货位之前,追加了任务,这个最好处理,在PDA上确认拣货的时候,会显示多条同时确认;
2.在回库的半路上,如果追加了拣选任务,就半路掉头,继续去相应的拣选站台;这就好比洲际导弹,本来去攻击对方兵工厂的,半路上收到消息,对方把东西全部挪到一个新地方了,这时候可以给导弹发送变更目的地指示;具体实现上:如果是AGV搬运回库,那么在给AGV发送任务指示的时候,就判断一下,是否有新的追加的拣选任务,如果有,就走了一半再给AGV发送变更指令;如果是输送线搬运,那么就在读码器等交互位置,重新给PLC新的目的地指示;如果托盘已经回到堆垛机入口了,那么堆垛机就直接把它调度到出口,如果这个时候出口堵住,临时入库,不停判断出口是否释放,一旦释放,在调度出来,然后再通过AGV或输送线调度到相应的拣选站台; 这个看起来复杂,其实也不麻烦,就是我们的调度任务要能够根据具体情况,能够中途变更,变更的同时,可能要马上给相应的调度设备发送变更指示,如果暂时不能发送,等下一个环节,在按变更的流程处理;
4. 出库货位选择原则:
a.大的原则是,按照备货生成的出库任务的优先级顺序执行;但是我们内部要稍微微调一下顺序,就是在同一个兄弟货位上,优先出外侧的;这样就不会尽量避免先出内侧的,要导致外侧移动;
为了安全起见,程序会做个锁处理,凡是外侧货位有出库任务,那么内侧货位的出库任务就会临时被屏蔽掉,直到这个外侧货位的出库任务做完,这个内侧货位的出库任务才重新被激活;
b.如果备货就是分配到内侧了,而外侧没有任务,这种情况下:我们程序一旦发现找到的出库任务的货位是这种情况,就会马上生成外侧货位的移库任务,移到那里,不立刻分配; 等下一个任务扫描周期到来,按照优先级,必然会先处理这个外侧货位的移库任务,这时候再做动态分配,正常情况下,会分配当前巷道的另一个货位以供使用,但是万一这时候可用货位没了,那就分配到出库站台去,临时让这个外侧的托盘出库,然后再通过AGV或输送线把这个托盘再调回到入库站台,重新入库;如果出库站台也堵死了,上天无路入地无门,没法像土行孙那样能到处乱窜;还有一招,窜到其他巷道去,有些客户的项目,各个巷道的中间,也有站台互相连着,就跟赤壁之战曹操的战船都互相连着类似,当年意气风发的阿瞒站在固若金汤的甲板上,感叹“对酒当歌人生几何”;可以像穿地鼠那样窜到左边或右边巷道,但是窜到其他巷道后,那对方巷道也是满了,怎么办,那就是其他巷道的事情了,它也可以再把它甩给其他巷道,做一个踢皮球的游戏;就像垃圾分类之前,很多城市垃圾消化不了的时候,就趁月黑风高的时候,偷偷的运到其他城市;当然,货位爆仓应该是个小概率事件,但是很多客户就好这口,就喜欢把货位全部用完,不留一个活口,就像我们下围棋,也要至少留出两个眼才能活;所以你在设计的时候都要防备着;当然你可以说,就留部分货位不允许入库,以防不测;但是有些客户不愿意,就是喜欢挑战那种极限的感觉;我们在监控和看板上做红色预警,也是视而不见;
c. 固定货位处理,有些项目,客户要求,一些特殊的产品,托盘一旦入到某个货位,就不能动了;如果要出到内侧的托盘,那么你可以把这个外侧的临时移走,但是把内侧的拿走后,外侧的还的挪回来,就更回旋镖一样; 这里处理的时候,我们要注意这个移回的时机,一定要等内侧的出来后,我们才能生成外侧的回库任务;所以我们可以在内侧出库的这个任务上做一个标记,记录上外侧需要移动的托盘;这就类似于大学课程里《数据结构》里的链表,把需要关联的任务通过类似指针的方法串起来; 这里有个细节,对于要求某个托盘指定货位的需求; 上位系统再下达任务的时候,不要直接在任务里指定货位,因为堆垛机的调度逻辑全是动态分配,而且万一上位指定的位置不对或者外侧挡住不可去内侧,就导致没法调度,你只要再指定货位上标记这个托盘就行,调度的时候会优先考虑这个,但也不能保证100%,因为指定的货位可能不满足真实的场景;实际上如果堆垛机调度逻辑里,既有动态分配又有指定分配,这就加大了复杂度,可能要写很多支离破碎的分支,网上看到那些加班猝死的工程师,可能就是到处是多层IF 嵌套,如意大利面条那样,最终因客户的各种新需求而难以继续补丁下去;所以设计的时候要深度思考,遏制个性化高成本的开发思路;
5. 异常处理:
异常处理是个相对麻烦的问题,很多项目这个地方都是处理的不够完善的; 而且每个项目,因为要和不同的上下游合作,每次都有些忐忑,不知道会有那些以前没考虑到的异常再去构思,也不知道是否有能力去搞定;正常流程做的势如破竹,而异常投入的精力往往不足;异常包含的环节很多,比如上位系统提供的不严谨的数据,下位设备反馈的错误矛盾的信息;甚至自身逻辑在一些特殊场景下的也会出错;想起文天祥在被押往崖山的路上感叹:山河破碎风飘絮,身世浮沉雨打萍;总会有无奈失败的时候, 毕竟一个项目不可能是一个人的盛宴,要靠各个环节的多个团队一起发力;但是内耗折腾贯穿始终;往往都会把麻烦困难的异常处理推给对方;这对于自身也会成长缓慢;所以很多打工者认不清,多做点艰难险阻的事情有什么不好呢;反正很多闲着的时光都被涮手机无情的带走,还不如在项目中多做点贡献;拈轻怕重能占到什么实惠了,只会导致未来的中年危机无所适从;
双伸堆垛机特有的异常主要有下面两点:
a. 取深浅有,就是取内侧的托盘的时候,发现外侧挡住了,一般是出库操作;3个可能:1.设备假报警 ; 2.软件调度自身有漏洞;3.之前有人工手动操作在外侧放了托盘; 对付这些情况的处理逻辑:
1.给堆垛机发送任务取消指令;
2. 如果系统里记录的外侧确实有货,那说明之前的调度处理有误,就把外侧的托盘生成一个移库任务(理论上不应该发生,但是如果莫名其妙的发生了,也要处理);
否者外侧货位上标记一个虚拟的货物,托盘号用一个特殊的随机条码,把该托盘生成一个出库任务;
这样的话,堆垛机的调度程序,下一个扫描周期,就会先把外侧的托盘出出来(如果出口堵住,这时候堆垛机会停住或做其他任务,直到出口释放)或移库;当然如果这种异常是堆垛机误报的,就会导致后面的空出,空出报警时,该任务和虚拟托盘号 也会清除掉; 一切还原,继续做当初的任务;如果在报假警,就会死循环的做下去;类似电影:《前目的地》 《恐怖游轮》的桥段;走不出去了;这种情况实际上是有的,一般是光电微小的误差导致的误判断,但是多循环几次,设备一般是会正常的;
a. 放深浅有,就是放内侧托盘的时候,发现被外侧挡住了,一般是入库操作;处理和上面的类似,也要给外侧生成一个移走的任务,但是比上面那个异常稍微麻烦一些,因为这时候堆垛机货叉上已经有货了,不能取消掉,要给它先分配另外一个货位入库;
其实调度这块,不同的人都有不同的思路,我这边的主要思想是:
1.每一步的调度都动态控制,利用上设备,任务所有提供的所有信号;
2. 所有的判断以托盘和货位的关系表为准;其他数据,如库存,任务;这些数据只使用他们的托盘号,货位从 托盘货位的关系表 里带出;这就类似手表定律;只以一个地方为源头;否者数据矛盾,到底以那个为准;
3. 不要相信上一步的逻辑,走一步看一步,任意环节都要考虑异常,异常不仅来自别人,也可能是自己上一步的处理就有问题,所以当前步骤也要考虑;
走在大街上,你会发现宠物狗和流浪狗 看你的眼神不一样;流浪狗如无根的浮萍,没有安全感,眼神飘忽不定,既想和你靠近又有些胆怯;当我们接到一个项目消息的时候,不知道对方提供什么团队,是否能够有信心合作顺利,都是未知数,这种感觉让我们更倾向于一直在老的合作关系里不能自拔;在设计的时候,更多的要把各种艰难险阻放到自己这边;才更能靠谱的执行下去;如果大家都愿意多思考,多把困难留给自己,把方便留给别人;就像早年韦唯的一首歌《爱的奉献》,只要人人都献出一点爱,世界将变成美好的人间;
No comment