开源AGV调度系统OpenTCS中的路由器(router)详解

OpenTCS中的任务分派器router详解

  • 1. 引言
  • 2. 路由器(router)
    • 2.1 代价计算函数(Cost functions)
    • 2.2 2.1 Routing groups
    • 2.1 默认的停车位置选择
    • 2.2 可选停车位置属性
    • 2.3 默认的充电位置选择
    • 2.4 即时运输订单分配
  • 3. 默认任务分派器的配置项
  • 4. 参考资料与源码

1. 引言

openTCS是一项著名的开源运输控制系统,我在之前的文章中对该系统也做了初步介绍:

  • 开源AGV调度系统 OpenTCS 5.4 开发环境配置与编译运行
  • 开源AGV调度系统OpenTCS中的任务分派器(dispatcher)详解
    在这里插入图片描述

2. 路由器(router)

openTCS中默认的任务路由器(Default router)是openTCS内置的重要策略模块,当然也是允许用户自定义和替换的。
默认路由器会在行驶路线上找到从一点到另一点消耗成本最低的路线。通过使用Dijkstra算法的实现来实现。它考虑已经被锁定的路径,但不考虑其他车辆的位置或被假定的未来行为。因此它不会绕过速度较慢或停在路上的车辆。

2.1 代价计算函数(Cost functions)

可用于评估驾驶过程中路径的成本函数可以通过配置进行选择。以下成本函数/配置选项可用:
DISTANCE (default):路由成本等同于路径长度;
TRAVELTIME:路由成本的计算是以在路径上行驶的预期时间,即路径长度/车辆允许的最大速度;
EXPLICIT_PROPERTIES:路径上行驶车辆的路由成本通过以下两个带键的路径属性中获取 tcs:routingCostForward and tcs:routingCostReverse。
HOPS:模型中每条路径的路由成本为1,得到的路由代价最小路径/点被选中。

2.2 2.1 Routing groups

计算车辆的路径时,对工厂中的不同车辆以不同的方式处理是可以的,如果车辆有不同的特点并且实际上路径行驶有不同的最佳路线,那么这是可取的。
为了实现这一点,模型中的路径或所用的成本函数需要反映出来这种差异。默认情况下不会这样做,因为默认路由器为所有的车辆计算路径同样的方式,除非另有指示。
要让路由器知道它应该单独计算车辆的路由,可以将键tcs:routingGroup的属性设置为任意字符串。(具有相同值集的车辆共享相同的路由表,空字符串为所有车辆的默认值。)

2.1 默认的停车位置选择

当一辆小车被派往停车点时,默认选择最接近(依据路由)且未被占用的停车点。可以通过设置以下关键属性来给车辆分配固定的位置。

  • tcs:preferredParkingPosition:模型中的点名。如果此停车点已被占用,则车辆选择附近距离最近的停车点代替。
  • tcs:assignedParkingPosition:模型中的点名。如果此停车点已被占用,则车辆不会前往到其他停车点,而是保持原地不动。
    assignedParkingPosition优先级高于preferredParkingPosition

2.2 可选停车位置属性

停车位置的优先级是可以明确的,车辆也可以按照一种新的停车序列进行重新停车操作。例如将车辆停放在运输订单频繁的第一目的地附近的位置。
要给停车点设置一个优先级,可以用tcs:parkingPositionPriority键设置一个属性在点上。该属性的值应为十进制整数,值越小,则会导致停车位的优先级更高。
1.3. Default recharging location selection

2.3 默认的充电位置选择

当车辆被派往充电位置时,默认选择最接近(依据路由)且未被占用的充电位置。也可通过为以下键设置属性来给车辆分配固定位置:

  • preferredRechargeLocation:如果此充电位置已被占用,则选择附近距离最近的充电位置。
  • assignedRechargeLocation:如果此充电位置已被选择,则车辆不会被派往到其他充电位置。
    assignedRechargeLocation优先级高于preferredRechargeLocation

2.4 即时运输订单分配

系统除了根据默认的流程和规则分配运输订单外,还可以显式分配运输订单(即时)。运输订单的即时分配支持具有预期车辆的运输订单。在这样的情况下,运输订单及其预期车辆通常处于可能进行分配的状态,但在常规调度程序流中被某些过滤条件阻止,因此采取这种方法将会很有用。

Although the immediate assignment of transport orders bypasses some of the filter criteria in the regular dispatcher flow, it works only in specific situations. Regarding the transport order’s state:

尽管传输订单的即时分配绕过了常规调度流程中的一些过滤条件,但它只在特定情况下起作用。考虑运输订单的状态:

  • 运输订单的状态必须是可指派的(DISPATCHABLE)。
  • 运输订单不能是订单序列的一部分。
  • 必须设置运输订单的预定车辆。

至于(预定)车辆的状态:

  • 车辆的处理状态必须为IDLE
  • 车辆状态必须为IDLECHARGING
  • 车辆的集成级别必须是TO_BE_UTILIZED
  • 车辆必须被报告在已知位置。
  • 车辆不得处理订单序列。

除了运输订单和预定车辆的各自状态之外,分派器可能还有其他特定的原因来拒绝即时分配。

3. 默认任务分派器的配置项

默认任务分派器提供以下配置项实现可配置.
defaultdispatcher.orderCandidatePriorities

  • Type: Comma-separated list of strings 逗号分隔的字符串列表
  • Trigger for changes to be applied: on application start 触发要应用的更改:在应用程序启动时
  • Description: Keys by which to prioritize transport order candidates for assignment.
    Possible values:
  • BY_AGE: Sort by transport order age, oldest first.
  • BY_DEADLINE: Sort by transport order deadline, most urgent first.
  • DEADLINE_AT_RISK_FIRST: Sort orders with deadlines at risk first.
  • BY_COMPLETE_ROUTING_COSTS: Sort by complete routing costs, lowest first.
  • BY_INITIAL_ROUTING_COSTS: Sort by routing costs for the first destination.
  • BY_ORDER_NAME: Sort by transport order name, lexicographically.

defaultdispatcher.orderPriorities

  • Type: Comma-separated list of strings
  • Trigger for changes to be applied: on application start
  • Description: Keys by which to prioritize transport orders for assignment.
    Possible values:
    BY_AGE: Sort by age, oldest first.
    BY_DEADLINE: Sort by deadline, most urgent first.
    DEADLINE_AT_RISK_FIRST: Sort orders with deadlines at risk first.
    BY_NAME: Sort by name, lexicographically.

defaultdispatcher.vehicleCandidatePriorities

  • Type: Comma-separated list of strings
  • Trigger for changes to be applied: on application start
  • Description: Keys by which to prioritize vehicle candidates for assignment.
    Possible values:
    BY_ENERGY_LEVEL: Sort by energy level of the vehicle, highest first.
    IDLE_FIRST: Sort vehicles with state IDLE first.
    BY_COMPLETE_ROUTING_COSTS: Sort by complete routing costs, lowest first.
    BY_INITIAL_ROUTING_COSTS: Sort by routing costs for the first destination.
    BY_VEHICLE_NAME: Sort by vehicle name, lexicographically.

defaultdispatcher.vehiclePriorities

  • Type: Comma-separated list of strings
  • Trigger for changes to be applied: on application start
  • Description: Keys by which to prioritize vehicles for assignment.
    Possible values:
    BY_ENERGY_LEVEL: Sort by energy level, highest first.
    IDLE_FIRST: Sort vehicles with state IDLE first.
    BY_NAME: Sort by name, lexicographically.

defaultdispatcher.deadlineAtRiskPeriod
Type: Integer
Trigger for changes to be applied: on application start
Description: The time window (in ms) before its deadline in which an order becomes urgent.

defaultdispatcher.assignRedundantOrders

  • Type: Boolean
  • Trigger for changes to be applied: instantly
  • Description: Whether orders to the current position with no operation should be assigned.

defaultdispatcher.dismissUnroutableTransportOrders

  • Type: Boolean
  • Trigger for changes to be applied: instantly
  • Description: Whether unroutable incoming transport orders should be marked as UNROUTABLE.

defaultdispatcher.reroutingImpossibleStrategy

  • Type: String
  • Trigger for changes to be applied: instantly
  • Description: The strategy to use when rerouting of a vehicle results in no route at all.
    The vehicle then continues to use the previous route in the configured way.
    Possible values:
    IGNORE_PATH_LOCKS: Stick to the previous route, ignoring path locks.
    PAUSE_IMMEDIATELY: Do not send further orders to the vehicle; wait for another rerouting opportunity.
    PAUSE_AT_PATH_LOCK: Send further orders to the vehicle only until it reaches a locked path; then wait for another rerouting opportunity.

defaultdispatcher.parkIdleVehicles

  • Type: Boolean
  • Trigger for changes to be applied: instantly
  • Description: Whether to automatically create parking orders for idle vehicles.

defaultdispatcher.considerParkingPositionPriorities

  • Type: Boolean
  • Trigger for changes to be applied: instantly
  • Description: Whether to consider parking position priorities when creating parking orders.

defaultdispatcher.reparkVehiclesToHigherPriorityPositions

  • Type: Boolean
  • Trigger for changes to be applied: instantly
  • Description: Whether to repark vehicles to parking positions with higher priorities.

defaultdispatcher.rechargeIdleVehicles

  • Type: Boolean
  • Trigger for changes to be applied: instantly
  • Description: Whether to automatically create recharge orders for idle vehicles.

defaultdispatcher.keepRechargingUntilFullyCharged

  • Type: Boolean
  • Trigger for changes to be applied: instantly
  • Description: Whether vehicles must be recharged until they are fully charged.
    If false, vehicle must only be recharged until sufficiently charged.

defaultdispatcher.idleVehicleRedispatchingInterval

  • Type: Integer
  • Trigger for changes to be applied: when/after plant model is loaded
  • Description: The interval between redispatching of vehicles.

4. 参考资料与源码

本文内容参考:官方文档

该模块源码位于:
openTCS-Strategies-Default/src/main/java/org/opentcs/strategies/basic/dispatching/DefaultDispatcher.java,代码如下:

 public DefaultDispatcher(OrderReservationPool orderReservationPool,TransportOrderUtil transportOrderUtil,InternalVehicleService vehicleService,@ApplicationEventBus EventSource eventSource,@KernelExecutor ScheduledExecutorService kernelExecutor,FullDispatchTask fullDispatchTask,Provider<PeriodicVehicleRedispatchingTask> periodicDispatchTaskProvider,DefaultDispatcherConfiguration configuration,RerouteUtil rerouteUtil,OrderAssigner orderAssigner,TransportOrderAssignmentChecker transportOrderAssignmentChecker) {this.orderReservationPool = requireNonNull(orderReservationPool, "orderReservationPool");this.transportOrderUtil = requireNonNull(transportOrderUtil, "transportOrderUtil");this.vehicleService = requireNonNull(vehicleService, "vehicleService");this.eventSource = requireNonNull(eventSource, "eventSource");this.kernelExecutor = requireNonNull(kernelExecutor, "kernelExecutor");this.fullDispatchTask = requireNonNull(fullDispatchTask, "fullDispatchTask");this.periodicDispatchTaskProvider = requireNonNull(periodicDispatchTaskProvider,"periodicDispatchTaskProvider");this.configuration = requireNonNull(configuration, "configuration");this.rerouteUtil = requireNonNull(rerouteUtil, "rerouteUtil");this.orderAssigner = requireNonNull(orderAssigner, "orderAssigner");this.transportOrderAssignmentChecker = requireNonNull(transportOrderAssignmentChecker,"transportOrderAssignmentChecker");}@Overridepublic void initialize() {if (isInitialized()) {return;}LOG.debug("Initializing...");transportOrderUtil.initialize();orderReservationPool.clear();fullDispatchTask.initialize();implicitDispatchTrigger = new ImplicitDispatchTrigger(this);eventSource.subscribe(implicitDispatchTrigger);LOG.debug("Scheduling periodic dispatch task with interval of {} ms...",configuration.idleVehicleRedispatchingInterval());periodicDispatchTaskFuture = kernelExecutor.scheduleAtFixedRate(periodicDispatchTaskProvider.get(),configuration.idleVehicleRedispatchingInterval(),configuration.idleVehicleRedispatchingInterval(),TimeUnit.MILLISECONDS);initialized = true;}@Overridepublic void terminate() {if (!isInitialized()) {return;}LOG.debug("Terminating...");periodicDispatchTaskFuture.cancel(false);periodicDispatchTaskFuture = null;eventSource.unsubscribe(implicitDispatchTrigger);implicitDispatchTrigger = null;fullDispatchTask.terminate();initialized = false;}@Overridepublic boolean isInitialized() {return initialized;}@Overridepublic void dispatch() {LOG.debug("Scheduling dispatch task...");// Schedule this to be executed by the kernel executor.kernelExecutor.submit(fullDispatchTask);}@Overridepublic void withdrawOrder(TransportOrder order, boolean immediateAbort) {requireNonNull(order, "order");checkState(isInitialized(), "Not initialized");// Schedule this to be executed by the kernel executor.kernelExecutor.submit(() -> {LOG.debug("Scheduling withdrawal for transport order '{}' (immediate={})...",order.getName(),immediateAbort);transportOrderUtil.abortOrder(order, immediateAbort);});}@Overridepublic void withdrawOrder(Vehicle vehicle, boolean immediateAbort) {requireNonNull(vehicle, "vehicle");checkState(isInitialized(), "Not initialized");// Schedule this to be executed by the kernel executor.kernelExecutor.submit(() -> {LOG.debug("Scheduling withdrawal for vehicle '{}' (immediate={})...",vehicle.getName(),immediateAbort);transportOrderUtil.abortOrder(vehicle, immediateAbort);});}@Overridepublic void topologyChanged() {if (configuration.rerouteOnTopologyChanges()) {LOG.debug("Scheduling reroute task...");kernelExecutor.submit(() -> {LOG.info("Rerouting all vehicles due to topology change...");rerouteUtil.reroute(vehicleService.fetchObjects(Vehicle.class), ReroutingType.REGULAR);});}}@Overridepublic void reroute(Vehicle vehicle, ReroutingType reroutingType) {LOG.debug("Scheduling reroute task...");kernelExecutor.submit(() -> {LOG.info("Rerouting vehicle due to explicit request: {} ({}, current position {})...",vehicle.getName(),reroutingType,vehicle.getCurrentPosition() == null ? null : vehicle.getCurrentPosition().getName());rerouteUtil.reroute(vehicle, reroutingType);});}@Overridepublic void assignNow(TransportOrder transportOrder)throws TransportOrderAssignmentException {requireNonNull(transportOrder, "transportOrder");TransportOrderAssignmentVeto assignmentVeto= transportOrderAssignmentChecker.checkTransportOrderAssignment(transportOrder);if (assignmentVeto != TransportOrderAssignmentVeto.NO_VETO) {throw new TransportOrderAssignmentException(transportOrder.getReference(),transportOrder.getIntendedVehicle(),assignmentVeto);}orderAssigner.tryAssignments(List.of(vehicleService.fetchObject(Vehicle.class, transportOrder.getIntendedVehicle())),List.of(transportOrder));}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/354777.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

想要高效回复客户消息?来看看这个款微信神器

不管是销售还是客服来说&#xff0c;能及时回复客户的反馈和问题&#xff0c;是确保顾客满意度的关键因素。 今天&#xff0c;就给大家分享一个职场必备神器——个微管理系统&#xff0c;帮助大家提高回复效率&#xff01; 首先&#xff0c;你可以在系统上设置自动通过好友后自…

Windows10安装Docker Desktop(实操步骤版)

1&#xff0c;下载Docker Desktop 官网下载地址&#xff1a; https://desktop.docker.com/win/stable/amd64/Docker%20Desktop%20Installer.exe 国内镜像下载地址&#xff08;本人下载这个&#xff09;&#xff1a; https://smartidedl.blob.core.chinacloudapi.cn/docker/2…

基于Quartus Prime18.1的安装与FPGA的基础仿真(联合Modelsim)教程

Quartus是一种美国科技公司Intel&#xff08;英特尔&#xff09;公司开发的FPGA&#xff08;现场可编辑门阵列&#xff09;设计编译软件&#xff0c;用作设计、仿真、综合和布局、支持多种编程语言&#xff0c;包括VHDL、Verilog等&#xff0c;并具有丰富的功能和工具库&#x…

T200HSA单路SDI/HDMI+1路3.5音频高清万能采集卡

产品简介&#xff1a; 同三维T200HSA单路高清万能采集卡&#xff0c;可以采集1路SDI/HDMI高清信号1路3.5音频信号&#xff0c;卡上有1个是HDMI接口1个是SDI接口1个3.5音频口&#xff0c;配件有&#xff1a; 1个小档板&#xff0c;PCI-E2.0 X1&#xff0c;分辨率最高可以达到10…

可信计算和数字水印技术

可信计算 可信计算可信计算基础概述可信计算关键技术要素可信性认证可信计算优劣 数字水印技术数字版权保护技术 可信计算 可信计算基础概述 可信计算&#xff08;Trusted Computing&#xff0c;TC&#xff09;&#xff1a;在计算和网络通信系统中广泛使用的、基于硬件安全模块…

【我是产品经理_注册安全分析报告】

前言 由于网站注册入口容易被黑客攻击&#xff0c;存在如下安全问题&#xff1a; 暴力破解密码&#xff0c;造成用户信息泄露短信盗刷的安全问题&#xff0c;影响业务及导致用户投诉带来经济损失&#xff0c;尤其是后付费客户&#xff0c;风险巨大&#xff0c;造成亏损无底洞 …

【单片机】DS2431芯片,读写128个字节,程序

ds2431pt&r stm32读写程序&#xff1a; 部分程序&#xff1a; #include "sys.h" #include "delay.h" #include "usart.h"#include <stdio.h> #include <stdlib.h> #include <string.h>#include "sys.h" #incl…

二开的精美UI站长源码分享论坛网站源码 可切换皮肤界面

二开的精美UI站长源码分享论坛网站源码 可切换皮肤界面 二开的精美UI站长源码分享论坛网站源码 可切换皮肤界面

C语言入门系列:数据类型之字面量类型

文章目录 一&#xff0c;什么是字面量二&#xff0c;字面量为什么需要类型&#xff1f;三&#xff0c;变量类型和字面量类型的区别1&#xff0c;作用不同2&#xff0c;方式不同 四&#xff0c;编译器如何推断字面量类型1&#xff0c;整数2&#xff0c;浮点数3&#xff0c;字面量…

2024最新AI大模型-LLm八股合集(八)-Transformer模型

更多2024最新AI大模型-LLm八股合集可以拉到文末&#xff01;&#xff01;&#xff01; MHA & MQA & MGA &#xff08;1&#xff09;MHA 从多头注意力的结构图中&#xff0c;貌似这个所谓的多个头就是指多组线性变换层&#xff0c;其实并不是&#xff0c;只有使用了一…

E36150系列 自动量程台式电源

E36150系列 自动量程台式电源 <<<KEYSIGHT是德科技>>> “ Keysight E36150 系列自动量程台式直流电源包含两个型号&#xff0c;其单通道输出功率可达 800 W。 E36150 系列可输出高达 60 V 的电压和 80 A 的电流&#xff0c;其可用功率足以满足您的测试需…

360vr党建线上主题展立体化呈现企业的文化理念和品牌形象

在现代科技的引领下&#xff0c;艺术与VR虚拟现实技术相融合必将成为趋势&#xff0c;深圳VR公司华锐视点荣幸地推出VR艺术品虚拟展厅&#xff0c;为您带来前所未有的艺术观赏体验。体验者足不出户即可置身于一个充满创意与灵感的虚拟艺术空间。 我们深入了解每一位客户的需求与…

maven archetype项目构架

1、设置环境变量 set MAVEN_HOMED:\SF\java\apache-maven-3.6.3 set path%path%;%MAVEN_HOME%\bin;2、制作archetype mvn -s "D:\SF\java\apache-maven-3.6.3\conf\settings.xml" archetype:create-from-project -DpackageNamecom.demo.esb-s:指定maven的setting文…

MYSQL数据库安装

一.编译安装MySQL服务 1.安装环境依赖包 2.将安装mysql 所需软件包传到/opt目录下 mysql-boost-5.7.44.tar tar zxvf mysql-boost-5.7.44.tar.gz 3.配置软件模块 cd /opt/mysql-5.7.44/ cmake \ -DCMAKE_INSTALL_PREFIX/usr/local/mysql \ -DMYSQL_UNIX_ADDR/usr/local/mysq…

10W+人都在看的年度技术精选、游戏行业安全、私域、AI实践指南报告整合,码住!

在网易工作了十多年&#xff0c;不说别的&#xff0c;小智在这里光学习就学习到很多干货&#xff0c;今天将这些干货内容统一分享给同仁&#xff01;真的是集齐精华&#xff0c;大家先点赞收藏关注&#x1f44d; 往年&#xff0c;基于网易数智在娱乐社交、游戏、泛零售、政务、…

智慧乡村和美人家信息化系统

一、简介 智慧乡村和美人家信息化系统是一个综合管理平台&#xff0c;集成了首页概览、一张图可视化、数据填报、智能评估、便捷申报、公开公示、任务管理、活动发布和灵活配置等功能。该系统不仅提升了乡村管理效率&#xff0c;也优化了家庭生活的便捷性。通过一张图&#xf…

基于STM32和人工智能的智能楼宇安防系统

目录 引言环境准备智能楼宇安防系统基础代码实现&#xff1a;实现智能楼宇安防系统 4.1 数据采集模块4.2 数据处理与分析4.3 控制系统4.4 用户界面与数据可视化应用场景&#xff1a;智能楼宇安防管理与优化问题解决方案与优化收尾与总结 1. 引言 随着物联网和人工智能技术的…

7,KQM模块的驱动

1&#xff0c;查资料&#xff0c;查模块的通信接口&#xff08;单片机和模块之间采用什么方式通信&#xff09;硬件接口&#xff0c;驱动方式(串口驱动用串口发送接收PC10&#xff0c;PC11) 只用了三个脚&#xff1a;VCC &#xff27;&#xff2e;&#xff24; &#xff34;&…

1.搭建SpringBoot项目三种方式

目录 1.使用Spring Initializr 1.1访问Spring Initializr: 1.2填写项目基本信息 1.3配置项目元数据: 1.4添加依赖: 1.5生成项目: 1.6下载项目: 1.7解压项目: 1.8导入项目到IDE: 1.9运行项目: 1.10创建控制器: 1.11访问应用 2.使用IDE&#xff08;集成开发环境&…

web安全渗透测试十大常规项(一):web渗透测试之PHP反序列化

渗透测试之PHP反序列化 1. PHP反序列化1.1 什么是反序列化操作? - 类型转换1.2 常见PHP魔术方法?- 对象逻辑(见图)1.2.1 construct和destruct1.2.2 construct和sleep1.2.2 construct和wakeup1.2.2 INVOKE1.2.2 toString1.2.2 CALL1.2.2 get()1.2.2 set()1.2.2 isset()1.2.2…