AGV调度系统实现(二)——交通管制交流

    所谓交通管控,很容易理解,就是在某个固定区域中,哪辆AGV小车先行,哪辆AGV小车后走的问题;

一、前提条件

     要想系统进行管制,必须要有良好的网络条件(无论wifi或者射频),此外AGV的硬件一定要好,否则数据丢包会变成家常便饭;此外,一定要进行多测试,进行压力测试,场景越多越好,代码写的再好场景测试不足,再好的代码也是瞎的。之前我们公司的项目曾经在无线模块上吃过亏,1600元的模块和200元的模块差异还是很大的,不要轻易相信厂家所谓的“我们用的没有问题”,一定要进行现场实地测试;

二、算法分析

    简单的交通管控,如下图所示:

                                           

      以上区域就构成了一个简单的交通管控区域,A、D为入口点,C、B分别为出口点,简单的算法只要小车到入口点停止,然后系统判断该区域中是否有运行的小车即可,如果没有小车那么直接放行改agv即可;如果有小车那么需要,将小车加入等待队列,且用前一辆车进行管控,当且仅当前一辆车出管制区后才能放行;

此处建议大伙将程序写成单例的,否则太耗资源了,单例代码如下:

        private static readonly AgvControlService instance = new AgvControlService();
        private AgvControlService()
        {
        }
        public static AgvControlService GetInstance()
        {
            return instance;
        }

判断逻辑如下:(1)先校验是否需要进行管控,如果需要在判断是否在出口

//管控点是否需要管控
                  if (!checkNeedControl(currentLankMark))
                    {
                        logger.Info("[AGV-NO-NEED-CONTROL]:Landmarks:{0},AGV:{1}", currentLankMark, agv.Id);
                        return;
                    }
                    
                         ControlPoint controlPoint = controlPointList.Where(m => m.LandMarkId == currentLankMark).FirstOrDefault();
                        if (controlPoint == null)
                        {
                            return;
                        }

                        #region 判断是出口
                        if (controlPoint.IsExported)
                        {
                            #region 将小车移除管制区
                            AgvControlGroupModelList.RemoveAll(m => m.Agv.Id == agv.Id && m.ControlPoint.ControlGroupId == controlPoint.ControlGroupId);
                            #endregion

                            #region 遍历这个管制区是否有被该车管制住等待的小车  放行等待的车
                            AgvControlGroupModel currentControlGroupAgv = AgvControlGroupModelList.Where(m => m.ControlAgv == agv.Id && m.ControlPoint.ControlGroupId == controlPoint.ControlGroupId).OrderBy(m => m.EnterTime).FirstOrDefault();
                            if (currentControlGroupAgv != null)
                            {                                
                                    startAgv(currentControlGroupAgv.Agv);
                                    AgvControlGroupModelList.Remove(currentControlGroupAgv);
                                    currentControlGroupAgv.ControlState = ControlState.Entering;
                                    AgvControlGroupModelList.Add(currentControlGroupAgv);
                                return;
                            }
                            #endregion                          
                            return;
                        }

                        #endregion

(2)判断是否在入口

    #region 判断是入口
                        if (!controlPoint.IsExported)
                        {
                            #region 第一步 判断管制区有木有车?
                            //没有车直接放行
                            var enteringAGV = AgvControlGroupModelList.Where(m => m.ControlPoint.ControlGroupId == controlPoint.ControlGroupId && m.ControlState == ControlState.Entering);
                            if (enteringAGV == null || enteringAGV.Count() < 1)
                            {
                                logger.Info("[AGV-CONTROL-MSG]NO CARS IN THIS AREA ,SO RELEASE THIS AGV[{0}]", agv.Id);
                                AgvControlGroupModel enterAgvControlGroupModel = new AgvControlGroupModel()
                                {
                                    Agv = agv,
                                    ControlPoint = controlPoint,
                                    ControlState = ControlState.Entering,
                                    EnterTime = DateTime.Now
                                };
                                AgvControlGroupModelList.RemoveAll(m => m.Agv.Id == agv.Id && m.ControlPoint.ControlGroupId == controlPoint.ControlGroupId);
                                AgvControlGroupModelList.Add(enterAgvControlGroupModel);
                                startAgv(agv);
                                return;
                            }
                            #endregion

                            #region 第二步 判断正在运行的小车是否是这个
                           var list = enteringAGV.Where(m=>m.Agv.Id==agv.Id);
                            if (list!= null&&list.Count()>0)
                            {
                                logger.Info("[AGV-CONTROL-MSG]THIS CAR IS ENTERING CAR ,SO NO COMMAND AGV[{0}]", agv.Id);
                                startAgv(agv);
                                return;
                            }
                            #endregion

                            #region 第三步 判断正在等待的小车是否是这个
                            var waitAGV = AgvControlGroupModelList.Where(m => m.ControlPoint.ControlGroupId == controlPoint.ControlGroupId && m.ControlState == ControlState.Wait);
                            if (waitAGV != null && waitAGV.Count() > 0)
                            {
                                List<AGV> waitList = waitAGV.Select(m => m.Agv).ToList();
                                if (waitList.FindAll(m => m.Id == agv.Id) != null)
                                {
                                    logger.Info("[AGV-CONTROL-MSG]THIS CAR IS WAIT CAR ,SO NO COMMAND AGV[{0}]", agv.Id);
                                    return;
                                }
                               // return;
                            }
                            #endregion
                            //先等待的车管制后进的小车
                            AgvControlGroupModel newWaitControlGroupModel = new AgvControlGroupModel()
                            {
                                Agv = agv,
                                ControlPoint = controlPoint,
                                ControlState = ControlState.Wait,
                                EnterTime = DateTime.Now,
                                ControlAgv = item.Agv.Id
                            };
                            AgvControlGroupModelList.RemoveAll(m => m.Agv.Id == agv.Id && m.ControlPoint.ControlGroupId == controlPoint.ControlGroupId);
                            AgvControlGroupModelList.Add(newWaitControlGroupModel);
                            quickStopAgv(agv);
                            return;
                        }
                        #endregion

      这样就可以实现一个最简单的交通管制了,但是此方法在业务层面上,效率不是很高;可能存在A->B或者D->C同时存在两辆车,如果后一辆车必须等着前一辆车出管制区,才能启动的话,效率就有点低了;为此我们可以认为A->B是同一类型的,D->C是同一类型的,如果此种情况同时出现,我们可以在放行前一辆车的同时放行后一辆车

var item = enteringAGV.OrderByDescending(m => m.EnterTime).FirstOrDefault();
                            if (!string.IsNullOrEmpty(controlPoint.Name) && !string.IsNullOrEmpty(item.ControlPoint.Name) && controlPoint.Name.Equals(item.ControlPoint.Name))
                            {
                                AgvControlGroupModel enterAgvControlGroupModel = new AgvControlGroupModel()
                                {
                                    Agv = agv,
                                    ControlPoint = controlPoint,
                                    ControlState = ControlState.Entering,
                                    EnterTime = DateTime.Now
                                };
                                AgvControlGroupModelList.RemoveAll(m => m.Agv.Id == agv.Id && m.ControlPoint.ControlGroupId == controlPoint.ControlGroupId);
                                AgvControlGroupModelList.Add(enterAgvControlGroupModel);
                                startAgv(agv);
                                return;
                            }

 复杂的交通管制,会在管制区中嵌套多个管制区,或者再管制区中再对接其他的指令,这种情况就需要现场仔细调试了。

   

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值