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