2年前决定用10篇文章讲透调度原理,当时的计划是用每周更新一篇,没想到用了两年才更新完,
主要是这两年确实很累,每天保持15个小时的写代码状态,身心疲惫,经常会忘记更新。
今天是这个系列的最后一篇文章了,我决定多写一点,多分析点东西。
对这个系列做一个完整的总结,彻底结束一下。
车辆运行监控器,这些年我一直没有停止探索,演变史乐意看这篇文章监控器演变史
最近因为效率不够,我又进行了一次重构,这一次从底层开始重构了,所有的图形的展示全部重新写了,目的就是为了提高效率,这一版的效率提升了几倍不止,目前展示千车调度不在卡顿了。
监控器一直是我的心病,最近终于下决心重构了,了却了一桩心事,上面是重构后的监控器。
下面是监控器先后使用的技术。
gojs
jtopo
原生canvas,使用原生重新了底层。
最终版本是这个样子的,这一个版本是通过研究海康的地图编辑器和快仓的地图编辑器,反复打磨完成的一个版本。
这个编辑器使用的是gojs技术,并且使用了多种gojs技术融合开发的。
下面是使用的技术
主界面
拖拽
右键操作
属性修改
这次升级最大的就是,避碰和寻路,他俩是完全重写的,把这两个算法使用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);
}
}
}
模拟器是我的第二块心病,之前的一直处于能用,但是效果不好,最大就能模拟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 车辆控制调度系统开发知识点篇
新篇章:智能工厂软件生态第一篇