Bootstrap

Agv车辆控制调度系统开发第十篇-终结篇

Agv车辆控制调度系统开发第十篇-终结篇


前言

![在这里插入图片描述](https://img-blog.csdnimg.cn/3a9ca3de786847e29b606576ec380967.png

2年前决定用10篇文章讲透调度原理,当时的计划是用每周更新一篇,没想到用了两年才更新完,
主要是这两年确实很累,每天保持15个小时的写代码状态,身心疲惫,经常会忘记更新。
今天是这个系列的最后一篇文章了,我决定多写一点,多分析点东西。
对这个系列做一个完整的总结,彻底结束一下。

一、工具部分

1.监控器

车辆运行监控器,这些年我一直没有停止探索,演变史乐意看这篇文章监控器演变史
最近因为效率不够,我又进行了一次重构,这一次从底层开始重构了,所有的图形的展示全部重新写了,目的就是为了提高效率,这一版的效率提升了几倍不止,目前展示千车调度不在卡顿了。
在这里插入图片描述
监控器一直是我的心病,最近终于下决心重构了,了却了一桩心事,上面是重构后的监控器。

下面是监控器先后使用的技术。
gojs
jtopo
原生canvas,使用原生重新了底层。

1.地图编辑器

在这里插入图片描述
最终版本是这个样子的,这一个版本是通过研究海康的地图编辑器和快仓的地图编辑器,反复打磨完成的一个版本。
这个编辑器使用的是gojs技术,并且使用了多种gojs技术融合开发的。
下面是使用的技术
主界面
拖拽
右键操作
属性修改

二、调度算法

1.避碰算法和寻路算法

这次升级最大的就是,避碰和寻路,他俩是完全重写的,把这两个算法使用cbs算法做了技术融合,效率提升了几十倍。
为了能调度更多的车,这次的重构完全是基于多线程的重构,所以现在我的调度可以轻松调度几千台车。
下面是我参考的代码

using System.Collections.Generic;

namespace CBSAlgorithm
{
    class Node
    {
        public int x;
        public int y;
        public Node parent;
        public double g;
        public double h;

        public Node(int x, int y)
        {
            this.x = x;
            this.y = y;
        }

        public double f
        {
            get { return g + h; }
        }
    };

    class Path
    {
        public List<Node> nodes = new List<Node>();
        public double cost;
    };

    class CBS
    {
        public static bool run(Node start, Node goal, Dictionary<string, Node> obstacles,
                           List<Path> paths)
        {
            // 搜索路径规划冲突解决方案
            while (true)
            {
                if (checkConflicts(paths))
                {
                    Path conflictPath1 = null;
                    Path conflictPath2 = null;
                    Node conflictNode = null;

                    findFirstConflict(paths, out conflictPath1, out conflictPath2, out conflictNode);

                    if (conflictPath1 == null || conflictPath2 == null)
                    {
                        Console.WriteLine("CBS Algorithm finished!");
                        return true;
                    }
                    else
                    {
                        Path newPath1 = replan(conflictPath1, conflictNode, obstacles);
                        Path newPath2 = replan(conflictPath2, conflictNode, obstacles);

                        if (newPath1 != null && newPath2 != null)
                        {
                            paths[paths.IndexOf(conflictPath1)] = newPath1;
                            paths[paths.IndexOf(conflictPath2)] = newPath2;
                        }
                        else
                        {
                            Console.WriteLine("CBS Algorithm failed!");
                            return false;
                        }
                    }
                }
                else
                {
                    Console.WriteLine("CBS Algorithm finished!");
                    return true;
                }
            }
        }

        private static bool checkConflicts(List<Path> paths)
        {
            // TODO 判断路径规划是否存在冲突
            return false;
        }

        private static void findFirstConflict(List<Path> paths, out Path path1,
                                        out Path path2, out Node conflictNode)
        {
            // TODO 查找第一个冲突发生在哪里
            path1 = null;
            path2 = null;
            conflictNode = null;
        }

        private static Path replan(Path path, Node conflictNode, Dictionary<string, Node> obstacles)
        {
            // TODO 根据现有路径和产生冲突的节点重新规划路径
            return new Path();
        }
    };

    class Program
    {
        static void Main(string[] args)
        {
            // 初始化场景
            Node start = new Node(0, 0);
            Node goal = new Node(5, 5);
            Dictionary<string, Node> obstacles = new Dictionary<string, Node>();
            obstacles.Add("obs1", new Node(2, 2));
            obstacles.Add("obs2", new Node(3, 3));

            // 定义多个机器人的路径
            List<Node> path1 = new List<Node>();
            path1.Add(new Node(0, 1));
            path1.Add(new Node(0, 2));
            path1.Add(new Node(0, 3));
            path1.Add(new Node(0, 4));
            path1.Add(goal);

            List<Node> path2 = new List<Node>();
            path2.Add(new Node(1, 0));
            path2.Add(new Node(2, 0));
            path2.Add(new Node(3, 0));
            path2.Add(new Node(4, 0));
            path2.Add(goal);

            List<Path> paths = new List<Path>();
            Path robotPath1 = new Path();
            robotPath1.nodes = path1;
            Path robotPath2 = new Path();
            robotPath2.nodes = path2;
            paths.Add(robotPath1);
            paths.Add(robotPath2);

            CBS.run(start, goal, obstacles, paths);
        }
    }
}

2.模拟器

模拟器是我的第二块心病,之前的一直处于能用,但是效果不好,最大就能模拟100台,
这次重写后可以轻松模拟几千台车。
这里面主要加入了多线程技术。

总结

调度真的没有多少东西可讲,大部分的理论和知识这些年都分析了。
到今天发现没啥可讲的了,当然细节的东西很多,那些东西都不值得去讲,因为大家都能做。
这个系列的文章就是给大家起一个引导的作用,让大家可以理解调度是什么,有什么东西,用什么技术。
当然我的技术肯定还会不断更新进步,不过后面就不在分享了。
承诺大家的事情我做到了,再次感谢大家喜欢我的文章,谢谢。
后面我开启了新篇章,有兴趣的可以继续关注
新篇章:智能工厂软件生态第一篇

系列文章链接

Agv、Rgv 车辆控制调度系统开发第一篇
Agv、Rgv 车辆控制调度系统开发第二篇
Agv、Rgv 车辆控制调度系统开发第三篇
Agv、Rgv 车辆控制调度系统开发第四篇
Agv、Rgv 车辆控制调度系统开发第五篇-避碰
Agv、Rgv 车辆控制调度系统开发第六篇-流程控制器
Agv、Rgv 车辆控制调度系统开发第七篇-选车算法
Agv、Rgv 车辆控制调度系统开发第八篇-错误纠正
Agv、Rgv 车辆控制调度系统开发第9篇-性能测试
Agv车辆控制调度系统开发第十篇-终结篇

其他文章

调度系统核心算法第一篇-交通管制
agv车辆调度系统-技术篇
agv调度系统3.0技术介绍
调度算法研究交流群的建立-欢迎加群交流
Agv、Rgv 车辆控制调度系统开发知识点篇
好玩的调度技术
好玩的调度技术-录制和回放
调度的多维空间技术

新篇章

新篇章:智能工厂软件生态第一篇

;