先分析下OpenTCS的一些策略方面的东西,这是OpenTCS的基础。
首先需要先明确下OpenTCS内核中的三个概念:
路由(Route) : 决定了车辆通过什么样的方式和算法来获得一段路径,未来车辆将沿着此路径运行。
派遣(Dispacher): 决定了一个订单应该关联哪一辆小车,即为订单分配车辆和为车辆分配订单。
调度(schedule):狭义上的调度,交通管制的核心,决定了何时分配共享资源,何时释放拥有的资源。
以上是来自内核的约定,即如果二次开发,必须要按照这样的概念进行设计,当然OpenTCS提供了默认的算法实现(可修改和替换)。这些默认实现包含在openTCS-Strategies-Default子项目中。
本节先来分析下OpenTCS提供的默认Route策略,按照我的理解记录如下:
1、路由算法。
主要是实现了最短路径算法,OpenTCS提供了三种路由算法供选择,分别是:
迪杰斯特拉算法
贝尔曼-福特算法
弗洛伊德算法。
一般来说我们直接使用迪杰斯特拉算法就行了,因为我们的移动机器人一般只需要计算单源最短路径(机器人到目标点),也不需要处理负权边。
这里有意思的是,OpenTCS支持为每一台机器人设置不同的路由计算器,存在类似这样的结构:
//只做示意,OpenTCS中并未存在这样的代码
Map vehicleToRouter;
这样当我们在项目中由不同类型的机器人时,可以更加灵活的选择路由。
2、静态规划。
遗憾的是,OpenTCS不支持动态路由,只支持静态计算路由。这样发生死锁的概率其实高很多,特别是当任务存在关联性时,如果不对任务的下发加以处理,死锁就经常性的发生了。
另外当所有车的路由算法都一致时,车辆占道的情况不能处理,具体体现如下:
当有两辆车分别位于7和8点,其中7点的车发往13号点(7-9-10-11-13),假设其在11号点发生了故障或者遇到了障碍物需要静止运行。
此时第二辆车若需要去14点,默认的算法就会蒙圈,他依然是傻傻的选择路由(8-10-11-12-14),可想而知,如果前面的车一直占用11点,两辆车就会死锁。
关于此问题的改进,需要进行动态规划,后面有机会再说......
3、自定义路由算法。
如果需要自定义路由算法,则只需要通过实现以下PointRouter接口(此接口只有两个成员函数)即可。
//路由的算法接口
public interface PointRouter {
//此函数必须返回点到点的Steps
List getRouteSteps(Point srcPoint, Point destPoint);
//此函数必须返回点到点所需要的代价(在派遣阶段可以此决策是否关联订单)
public long getCosts(TCSObjectReference srcPointRef,
TCSObjectReference destPointRef);
}
因此,我们在二次开发的过程中,如果某辆车的路由是特殊的算法(即不能使用上面所说的三种路由算法)时,即可通过实现上述接口自己开发对应的算法来处理啦。