GetPath.cs 14.7 KB
using XingYe_ACS.BaseStruct;
using XingYe_ACS.Common;
using XingYe_ACS.WebApi;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace XingYe_ACS.Business
{
    public class GetPath
    {
        /// <summary>
        /// 为子任务分配路径
        /// </summary>
        public static void AssignePath()
        {
            try
            {
                foreach (Agv agv in App.AgvList)
                {
                    try
                    {
                        FTask task = agv.agvTask;
                        if (task == null || task.sonTaskList.Count == 0 || task.sonTaskList[0].sonTaskState > EnumMsg.SonTaskState.重建路径中) continue;
                        List<PathPoint> pathPointList = GetPathList(agv);
                        SonTask sonTask = task.sonTaskList[0];
                        string sqlUpdate = "";
                        if (pathPointList == null)
                        {
                            sqlUpdate = string.Format("UPDATE T_SonTask SET sonTaskState = 2  WHERE intSonTaskNo = '{0}';", sonTask.intSonTaskNo);
                            int intSqlResult = DbHelperSQL.ExecuteSql(sqlUpdate);
                            if (intSqlResult < 1) continue;
                            sonTask.sonTaskState = EnumMsg.SonTaskState.建立路径失败;
                            continue;
                        }
                        string sqlInsert = "";
                        for (int i = 1; i <= pathPointList.Count; i++)
                        {
                            //拐点进行判断
                            PathPoint pathPoint = pathPointList[i - 1];
                            if (pathPoint.isCorner)
                            {
                                if (pathPoint.point.pointType == EnumMsg.PointType.整体旋转点)
                                {
                                    pathPoint.pathPointType = EnumMsg.PointType.整体旋转点;
                                }
                                else if (pathPointList[i - 2].point.pointType == EnumMsg.PointType.整体旋转点)
                                {
                                    //pathPointList[i - 2].pathPointType = EnumMsg.PointType.托盘旋转点;
                                }
                                else if (pathPointList[i] != null && pathPointList[i].point.pointType == EnumMsg.PointType.整体旋转点)
                                {
                                    //pathPointList[i].pathPointType = EnumMsg.PointType.托盘旋转点;
                                }
                            }
                        }
                        for (int i = 1; i <= pathPointList.Count; i++)
                        {
                            sqlInsert += string.Format(@"INSERT INTO T_Base_PathPoint (areaType,intSonTaskNo,strBarcode,intSerialNo,pathDirection,isCorner,pathPointType) VALUES('{0}','{1}','{2}','{3}','{4}','{5}','{6}');"
                                            , pathPointList[i - 1].point.AreaType, sonTask.intSonTaskNo, pathPointList[i - 1].point.strBarcode, i, (int)pathPointList[i - 1].pathDirection, pathPointList[i - 1].isCorner == false ? "0" : "1", (int)pathPointList[i - 1].pathPointType);
                        }
                        sqlUpdate = string.Format("UPDATE T_SonTask SET sonTaskState = 4  WHERE intSonTaskNo = '{0}';", sonTask.intSonTaskNo);
                        bool isSqlResult = DbHelperSQL.SqlTransOperator(sqlInsert + sqlUpdate);
                        if (isSqlResult)
                        {
                            sonTask.pathPointList = pathPointList;
                            sonTask.sonTaskState = EnumMsg.SonTaskState.已建立路径;
                        }
                    }
                    catch (Exception Ex)
                    {
                        App.ExFile.MessageError("AssignePath", Ex.StackTrace);
                    }
                }
            }
            catch (Exception Ex)
            {
                App.ExFile.MessageError("AssignePath", Ex.Message.Replace(Environment.NewLine, ""));
            }
        }

        /// <summary>
        /// 生成路径
        /// </summary>
        /// <returns>路径集合</returns>
        public static List<PathPoint> GetPathList(Agv agv)
        {
            try
            {
                SonTask sonTask = agv.agvTask.sonTaskList[0];
                Point startPoint = App.PointList.FirstOrDefault(a => a.strBarcode == agv.strBarcode);
                Point endPoint = sonTask.endPoint;
                //20201113 (临时)创建路径时终点若被lock,则创建路径失败
                if (endPoint.lockedAgv != null && endPoint.lockedAgv != agv) return null;
                //20210422判断是否有去往终点的AGV
                var result = App.TaskList.Where(a => a.strTaskAgv != "" && a.strTaskAgv != agv.strAgvNo).ToList().SelectMany(b => b.sonTaskList).ToList();
                var result1 = result.Exists(a => a.sonTaskState != EnumMsg.SonTaskState.初始化 && a.endPoint == endPoint);
                if (result1) return null;
                
                //判断是否在同一区域
                List<Point> listPoints = ComnMethod.GetAreaPoint(startPoint, endPoint);
                startPoint = listPoints.First();
                endPoint = listPoints.LastOrDefault();
                EnumMsg.AgvTaskType taskType = sonTask.sonTaskType;
                switch (taskType)
                {
                    case EnumMsg.AgvTaskType.行走:
                        if (startPoint == endPoint)
                            return new List<PathPoint>() { ComnMethod.GetPathPoint(endPoint) };
                        PathAStar pathAStar = new PathAStar();
                        List<Point> listApoint = GetCanUseApoint(agv);
                        ClearParentPoint();
                        Point Parent = pathAStar.GetPathPoint(listApoint, startPoint, endPoint, agv,2);
                        if (Parent == null || (Parent != null && Parent != endPoint))
                        {
                            App.ExFile.MessageLog("TaskPathFail" + agv.strAgvNo, "路径创建失败" + endPoint.strBarcode + ";" + endPoint.AreaType + ";" + startPoint.strBarcode + ";" + startPoint.AreaType);
                            sonTask.sonTaskState = EnumMsg.SonTaskState.建立路径失败;
                            return null;
                        }
                        List<PathPoint> listPathPoint = GetPathPointList(Parent);
                        //获取路径方点的方向
                        GetPathDirection(listPathPoint);
                        //获取路径点的拐点
                        bool isResult = GetPathCorner(listPathPoint, startPoint);
                        //锁定临时方向锁
                        OriLock(listPathPoint, agv);
                        return listPathPoint;
                    case EnumMsg.AgvTaskType.顶升:
                    case EnumMsg.AgvTaskType.下降:
                    case EnumMsg.AgvTaskType.直接顶升:
                    case EnumMsg.AgvTaskType.直接下降:
                    case EnumMsg.AgvTaskType.充电:
                    case EnumMsg.AgvTaskType.取消充电:
                    case EnumMsg.AgvTaskType.原地旋转:
                    case EnumMsg.AgvTaskType.等待:
                        return new List<PathPoint>() { ComnMethod.GetPathPoint(endPoint) };
                    default:
                        throw new Exception("创建路径时无此任务类型:" + taskType.ToString());
                }
            }
            catch (Exception Ex)
            {
                throw new Exception("GetPathList:" + Ex.Message.Replace(Environment.NewLine, ""));
            }
        }

        /// <summary>
        /// 清除点的父类属性
        /// </summary>
        public static void ClearParentPoint()
        {
            foreach (Point point in App.PointList)
            {
                if (point.ParentPoint != null)
                    point.ParentPoint = null;
            }
        }

        /// <summary>
        ///获取可用的路径点
        /// </summary>
        static List<Point> GetCanUseApoint(Agv agv)
        {
            SonTask sonTask = agv.agvTask.sonTaskList[0];
            Point startPoint = sonTask.startPoint;
            if (sonTask.sonTaskState == EnumMsg.SonTaskState.重建路径中)
            {
                startPoint = App.PointList.Find(a => a.strBarcode == agv.strBarcode);
            }
            Point endPoint = sonTask.endPoint;
            //获取可用点
            List<Point> listApoint = new List<Point>();
            foreach (Point point in App.PointList)
            {
                if (point != startPoint && point != endPoint)
                {
                    //起点周围点被锁定,且车的位置也在此点,则不建路径
                    //解决异常重建时,路径依旧堵死的问题
                    if (point == startPoint.xNegPoint && point.lockedAgv != null && point.lockedAgv.strBarcode == point.strBarcode) continue;
                    if (point == startPoint.xPosPoint && point.lockedAgv != null && point.lockedAgv.strBarcode == point.strBarcode) continue;
                    if (point == startPoint.yNegPoint && point.lockedAgv != null && point.lockedAgv.strBarcode == point.strBarcode) continue;
                    if (point == startPoint.yPosPoint && point.lockedAgv != null && point.lockedAgv.strBarcode == point.strBarcode) continue;

                    //以下点类型不使用
                    if (point.pointType == EnumMsg.PointType.死点) continue;//
                    //if (point.pointType == EnumMsg.PointType.站台点
                    //    && !App.StationList.Find(a => a.strBarcode == point.strBarcode).strStationNo.Contains("Empty")) continue;
                    //被占用,不使用
                    if (point.isOccupy) continue;
                    //不包含agv的区域则不选择
                    //if (point.AreaType != agv.agvMap) continue;
                }
                listApoint.Add(point);
            }

            return listApoint;
        }

        /// <summary>
        /// 路径点添加至路径集合
        /// </summary>
        /// <param name="Parent"></param>
        /// <param name="type">任务预览/派发路径</param>
        /// <returns></returns>
        public static List<PathPoint> GetPathPointList(Point Parent)
        {
            List<PathPoint> listPathPoint = new List<PathPoint>();
            while (Parent != null)
            {
                listPathPoint.Add(ComnMethod.GetPathPoint(Parent));
                Parent = Parent.ParentPoint;
            }
            listPathPoint.Reverse();
            for (int i = 0; i < listPathPoint.Count; i++)
            {
                listPathPoint[i].intSerialNo = i + 1;
            }
            return listPathPoint;
        }

        #region 获取路径方向
        /// <summary>
        /// 获取路径方向
        /// </summary>
        /// <param name="pathList">路径集合</param>
        public static void GetPathDirection(List<PathPoint> pathList)
        {
            //终点不比较
            for (int i = 0; i < pathList.Count - 1; i++)
            {
                Point point = pathList[i].point;
                Point nextPoint = pathList[i + 1].point;
                PathAStar pathAStar = new PathAStar();
                EnumMsg.OriType pathDirection = pathAStar.GetDircition(nextPoint, point);
                pathList[i].pathDirection = pathDirection;
                pathList[i].keyValuePairs.Add(point.strBarcode, (int)pathDirection);
            }
        }
        #endregion

        #region 获取路径拐点
        /// <summary>
        /// 获取路径拐点
        /// </summary>
        /// <param name="pathList">路径点</param>
        public static bool GetPathCorner(List<PathPoint> pathList, Point beginPoint)
        {
            try
            {
                if (beginPoint == null)
                    throw new Exception("获取路径拐点失败,起点终点不能为空");
                for (int i = 0; i < pathList.Count - 1; i++)
                {
                    //当前路径点
                    PathPoint currentPoint = pathList[i];
                    if (currentPoint.point == beginPoint)
                    {
                        //currentPoint.isCorner = true;
                        continue;
                    }
                    //上个路径点
                    PathPoint beforePoint = pathList[i - 1];
                    if (currentPoint.pathDirection != beforePoint.pathDirection)
                    {
                        currentPoint.isCorner = true;
                    }
                    else
                    {
                        currentPoint.isCorner = false;
                    }
                }
                return true;
            }
            catch (Exception Ex)
            {
                throw new Exception("GetPathCorner:" + Ex.Message.Replace(Environment.NewLine, ""));
            }
        }
        #endregion

        #region 锁定路径方向
        /// <summary>
        /// 锁定路径方向
        /// </summary>
        /// <param name="pathList"></param>
        public static void OriLock(List<PathPoint> pathList, Agv agv)
        {
            //终点不比较
            // int dir0 = 0;
            for (int i = 0; i < pathList.Count - 1; i++)
            {
                Point point = pathList[i].point;
                Point nextPoint = pathList[i + 1].point;
                if (point == nextPoint || point.strRegionName.Contains("Rotote") || point.strRegionName.Contains("Mutex") || point.strRegionName.Contains("area"))
                    continue;
                if (nextPoint.pointType == EnumMsg.PointType.站台点 && point.pointType == EnumMsg.PointType.站台附属点) continue;
                PathAStar pathAStar = new PathAStar();
                EnumMsg.OriType pathDirection = pathAStar.GetDircition(nextPoint, point);
                pathList[i].pathDirection = pathDirection;
                TmpDirection td = new TmpDirection();
                td.pathDirection = pathDirection;
                td.strAgvNo = agv.strAgvNo;
                point.tmpDirectionList.Add(td);
            }
        }
        #endregion

        #region Demo查找路径方法
        /// <summary>
        /// 清除点的父类属性
        /// </summary>
        public static void ClearDemoParentPoint()
        {
            foreach (Point point in App.DemoPointList)
            {
                if (point.ParentPoint != null)
                    point.ParentPoint = null;
            }
        }
        #endregion
    }
}