使用手册 - Simple:coder(路径编译器)机制详解:修订间差异

来自MDCS wiki
跳到导航 跳到搜索
(创建页面,内容为“== 1.概念 == 路径编译是MDCS架构中一个重要概念,它是上位调度系统与下位车端系统之间的桥梁。路径编译发生在寻路完成之后,路径编译的操作对象是由“站点、路径、站点、路径......”构成的序列,路径编译的结果是一串AGV可以执行的命令脚本,该脚本对应车端SimpleAGVInterface里面定义的接口。 == 2.机制介绍 == 我们将编译器称为“coder”,实际业务…”)
 
无编辑摘要
第13行: 第13行:
== 3.TemplateCoderSettings使用方法 ==
== 3.TemplateCoderSettings使用方法 ==


=== 3.1 CoderSettings编码方法 ===
=== 3.1 CoderSettings中字段含义 ===
<code>TemplateTrackCoderSettings</code>和<code>TemplateSiteCoderSittings</code>是分别实现trackCoder和SiteCoder的[https://learn.microsoft.com/zh-cn/dotnet/csharp/advanced-topics/reflection-and-attributes/attribute-tutorial Attribute],通过在Simple工程中xxxCar.cs中小车类之前添加<code>TemplateTrackCoderSettings</code>和<code>TemplateSiteCoderSittings</code>定义站点编译器。下方DummyCar的示例,无条件地将所有路径编译为agv.Go()这一动作:<syntaxhighlight lang="c#" line="1">
<code>TemplateTrackCoderSettings</code>和<code>TemplateSiteCoderSittings</code>是分别实现trackCoder和SiteCoder的[https://learn.microsoft.com/zh-cn/dotnet/csharp/advanced-topics/reflection-and-attributes/attribute-tutorial Attribute],通过在Simple工程中xxxCar.cs中小车类之前添加<code>TemplateTrackCoderSettings</code>和<code>TemplateSiteCoderSittings</code>定义站点编译器。下方DummyCar的示例,无条件地将所有路径编译为agv.Go()这一动作:<syntaxhighlight lang="c#" line="1">
class DummyCarTrackField
class DummyCarTrackField
第66行: 第66行:
|触发后,若blockVerb为"true",则不再检查其他优先级更低的coder;若为"false",则继续检查剩余优先级更低的coder。默认为"false"
|触发后,若blockVerb为"true",则不再检查其他优先级更低的coder;若为"false",则继续检查剩余优先级更低的coder。默认为"false"
|}
|}
其中,<code>templateString</code>、<code>useVerb</code>、<code>blockVerb</code>都是字符串,通过[https://github.com/sebastienros/jint Jint]将字符串视为JavaScript代码,进行解析执行。
<code>templateString</code>、<code>useVerb</code>、<code>blockVerb</code>中可以使用如下定义好的对象。'''注意,<code>TemplateCoderSittings</code>中不可使用<code>src</code>这一字段,<code>dst</code>代表当前站点。'''
{| class="wikitable"
|+
!对象
!含义
! colspan="2" |包含字段
|-
| rowspan="2" |car
| rowspan="2" |当前plan所使用的小车
|car.id
|小车id
|-
| colspan="2" |carFields中定义的其他字段
|-
| rowspan="4" |src
| rowspan="4" |路径起点
|src.id
|起点的id
|-
|src.x
|起点的x坐标
|-
|src.y
|起点的y坐标
|-
| colspan="2" |siteFields中定义的其他字段
|-
| rowspan="4" |dst
| rowspan="4" |路径终点
|dst.id
|终点的id
|-
|dst.x
|终点的x坐标
|-
|dst.y
|终点的y坐标
|-
| colspan="2" |siteFields中定义的其他字段
|-
| rowspan="4" |plan
| rowspan="4" |当前任务
|segN
|任务总元素数
|-
|curSeg
|当前元素下标
|-
|src
|任务起点
|-
|dst
|任务终点
|-
|prev
|前一个segment,若无返回null
|
|
|-
|next
|后一个segment,若无返回null
|
|
|}
<code>templateString</code>、<code>useVerb</code>、<code>blockVerb</code>中还预定义了如下方法:
{| class="wikitable"
|+
!'''方法'''
!'''含义'''
|-
|getSite
|返回指定id的站点
|-
|getTrack
|返回指定id的路径
|-
|getCar
|返回指定id的小车
|-
|getSegment
|返回指定下标的segment
|}
=== 3.2 编写自己的coderSitting ===
以最常见的取放货为例,首席需要将使用的字段定义在类中,站点字段定义在SiteFields类中,路径字段定义在TrackFields类中。
下述coder的执行条件为<code>plan.action=='put'&& dst.shelf</code>,即站点上标记了<code>shelf = true</code>字段,并且这是放货plan时,才会下发<code>templateString</code>中的脚本,并且站点及路径上标记的响应字段的值也会跟随脚本下发。<syntaxhighlight lang="c#" line="1">
class SiteFields
    {
        public bool shelf = false;
        public int obArea = -1;
        public int ASNub = -1;
        public float angle = 0;
        public float shelfWidth = 1030;
        public float distance = 500;
    }
[TemplateTrackCoderSettings(
        priority = 5,
        useVerb = "plan.action=='put' && dst.shelf ",
        templateString = "agv.Wait();agv.Put(${dst.ASNub},${dst.shelfWidth},${dst.obArea},${src.x},${src.y},${src.id},${dst.x},${dst.y},${dst.id},${track.id},${track.speed},${dst.reverse},${dst.xbias},${dst.ybias},${dst.angle},${dst.distance});agv.Wait();",
        blockVerb = "true",
        siteFields = typeof(SiteFields),
        trackFields = typeof(TrackFields),
        planFields = typeof(PlanField))]
</syntaxhighlight>
=== 3.3 simple内置的coder ===
所有的小车类均继承了车体抽象类<code>AbstractCar</code>,抽象类中定义了如下几个coder:
队列动作。在站点的codeQueue字段上定义脚本,在该站点发生路径切换时执行。<syntaxhighlight lang="c#" line="1">
[TemplateSiteCoderSettings(priority = 100,
    useVerb = "dst.codeQueue!=null",
    templateString = "agv.Queue(()=>{},()=>{${dst.codeQueue}});",
    blockVerb = "true",
    siteFields = typeof(StandardSiteFields))]
</syntaxhighlight>到达动作。在站点的codeArrive字段上定义AGV脚本,在AGV达到该站点发时(完全停车后)执行。<syntaxhighlight lang="c#" line="1">
[TemplateSiteCoderSettings(priority = 100,
    useVerb = "dst.codeArrive!=null && plan.curSeg!=0",
    templateString = "agv.Wait(); ${dst.codeArrive};",
    siteFields = typeof(StandardSiteFields))]
</syntaxhighlight>离开动作。在站点的codeLeave字段上定义AGV脚本,在AGV从该站点离开之前执行。<syntaxhighlight lang="c#" line="1">
[TemplateSiteCoderSettings(priority = 100,
    useVerb = "dst.codeLeave!=null && plan.curSeg!=plan.segN-1",
    templateString = "agv.Wait(); ${dst.codeLeave};",
    siteFields = typeof(StandardSiteFields))]
</syntaxhighlight>空路径。即指定某段路径不执行具体动作(相当于直接跳过)。<syntaxhighlight lang="c#" line="1">
[TemplateTrackCoderSettings(
    priority = 100,
    siteFields = typeof(StandardSiteFields),
    useVerb = "track.nop && (track.nopDst==-1 || track.nopDst==dst.id)",
    blockVerb = "true",
    templateString = "agv.Nop(${src.id},${dst.id},${track.id});",
    trackFields = typeof(StandardTrackFields))]
</syntaxhighlight>切换动作。在站点的switchString字段上定义脚本,在该站点发生路径切换时执行。一般用于进行障碍物切换。<syntaxhighlight lang="c#" line="1">
[TemplateTrackCoderSettings(
    priority = 20,
    useVerb = "track.switcher",
    templateString = "agv.Queue(()=>{}, ()=>{${dst.switchString};});",
    siteFields = typeof(StandardSiteFields),
    trackFields = typeof(StandardTrackFields))]
</syntaxhighlight>

2023年10月26日 (四) 11:09的版本

1.概念

路径编译是MDCS架构中一个重要概念,它是上位调度系统与下位车端系统之间的桥梁。路径编译发生在寻路完成之后,路径编译的操作对象是由“站点、路径、站点、路径......”构成的序列,路径编译的结果是一串AGV可以执行的命令脚本,该脚本对应车端SimpleAGVInterface里面定义的接口。

2.机制介绍

我们将编译器称为“coder”,实际业务中,整个编译逻辑是由若干的coder构成的。也就是说,coder在同一个站点或者可以叠加使用。处理路径的,称为trackCoder;处理站点的,称为siteCoder。定义好某个车型的所有coder,就完成了该车型的业务层面的所有行为定义(即,在什么路径/站点上触发什么样的行为)。下面用一个具体的例子详细解释coder运行的机制。

我们将“小车从A到B”的过程称为一个“plan”。如上图所示,假设已经生成了`模拟车1`的一段plan。该plan包含6个site(站点)、5段track(路径),共11个segment。编译路径时,依据通行顺序检查所有segment。对于每一个segment,若它是站点,则检查所有的siteCoder;若它是路径,则检查所有的路径trackCoder。对于每一个被检查的coder,依次判断其是否能够触发,触发后生成AGV脚本,并判断是否继续检查剩余的coder。如下图所示,为车辆执行的脚本。

3.TemplateCoderSettings使用方法

3.1 CoderSettings中字段含义

TemplateTrackCoderSettingsTemplateSiteCoderSittings是分别实现trackCoder和SiteCoder的Attribute,通过在Simple工程中xxxCar.cs中小车类之前添加TemplateTrackCoderSettingsTemplateSiteCoderSittings定义站点编译器。下方DummyCar的示例,无条件地将所有路径编译为agv.Go()这一动作:

class DummyCarTrackField
{
    public int speed = -1;
    public bool reverse = false;
    public int reverseDst = -1;
}

[TemplateTrackCoderSettings(
    templateString = "agv.Go(${src.x},${src.y},${src.id},${dst.x},${dst.y},${dst.id},${track.id},${track.speed},${track.reverse || track.reverseDst == dst.id});",
    priority = 0,
    trackFields = typeof(DummyCarTrackField),
    useVerb = "true",
    blck)]

[CarType("模拟车")]
public class DummyCar : Car

CoderSitting中包含以下字段:

字段 类型 含义
templateString string 编译后执行的命令
priority int 优先级,数值越大越先被检查
siteFields Type 定义站点字段的类的Type
trackFields Type 定义路径字段的类的Type
planFields Type 定义车辆字段的类的Type
useVerb string 触发条件。默认为"true"
blockVerb string 触发后,若blockVerb为"true",则不再检查其他优先级更低的coder;若为"false",则继续检查剩余优先级更低的coder。默认为"false"

其中,templateStringuseVerbblockVerb都是字符串,通过Jint将字符串视为JavaScript代码,进行解析执行。

templateStringuseVerbblockVerb中可以使用如下定义好的对象。注意,TemplateCoderSittings中不可使用src这一字段,dst代表当前站点。

对象 含义 包含字段
car 当前plan所使用的小车 car.id 小车id
carFields中定义的其他字段
src 路径起点 src.id 起点的id
src.x 起点的x坐标
src.y 起点的y坐标
siteFields中定义的其他字段
dst 路径终点 dst.id 终点的id
dst.x 终点的x坐标
dst.y 终点的y坐标
siteFields中定义的其他字段
plan 当前任务 segN 任务总元素数
curSeg 当前元素下标
src 任务起点
dst 任务终点
prev 前一个segment,若无返回null
next 后一个segment,若无返回null

templateStringuseVerbblockVerb中还预定义了如下方法:

方法 含义
getSite 返回指定id的站点
getTrack 返回指定id的路径
getCar 返回指定id的小车
getSegment 返回指定下标的segment

3.2 编写自己的coderSitting

以最常见的取放货为例,首席需要将使用的字段定义在类中,站点字段定义在SiteFields类中,路径字段定义在TrackFields类中。

下述coder的执行条件为plan.action=='put'&& dst.shelf,即站点上标记了shelf = true字段,并且这是放货plan时,才会下发templateString中的脚本,并且站点及路径上标记的响应字段的值也会跟随脚本下发。

class SiteFields
    {
        public bool shelf = false;
        public int obArea = -1;
        public int ASNub = -1;
        public float angle = 0;
        public float shelfWidth = 1030;
        public float distance = 500; 
    }
 [TemplateTrackCoderSettings(
        priority = 5,
        useVerb = "plan.action=='put' && dst.shelf ",
        templateString = "agv.Wait();agv.Put(${dst.ASNub},${dst.shelfWidth},${dst.obArea},${src.x},${src.y},${src.id},${dst.x},${dst.y},${dst.id},${track.id},${track.speed},${dst.reverse},${dst.xbias},${dst.ybias},${dst.angle},${dst.distance});agv.Wait();",
        blockVerb = "true",
        siteFields = typeof(SiteFields),
        trackFields = typeof(TrackFields),
        planFields = typeof(PlanField))]

3.3 simple内置的coder

所有的小车类均继承了车体抽象类AbstractCar,抽象类中定义了如下几个coder:

队列动作。在站点的codeQueue字段上定义脚本,在该站点发生路径切换时执行。

[TemplateSiteCoderSettings(priority = 100,
    useVerb = "dst.codeQueue!=null",
    templateString = "agv.Queue(()=>{},()=>{${dst.codeQueue}});",
    blockVerb = "true",
    siteFields = typeof(StandardSiteFields))]

到达动作。在站点的codeArrive字段上定义AGV脚本,在AGV达到该站点发时(完全停车后)执行。

[TemplateSiteCoderSettings(priority = 100,
    useVerb = "dst.codeArrive!=null && plan.curSeg!=0",
    templateString = "agv.Wait(); ${dst.codeArrive};",
    siteFields = typeof(StandardSiteFields))]

离开动作。在站点的codeLeave字段上定义AGV脚本,在AGV从该站点离开之前执行。

[TemplateSiteCoderSettings(priority = 100, 
    useVerb = "dst.codeLeave!=null && plan.curSeg!=plan.segN-1",
    templateString = "agv.Wait(); ${dst.codeLeave};",
    siteFields = typeof(StandardSiteFields))]

空路径。即指定某段路径不执行具体动作(相当于直接跳过)。

[TemplateTrackCoderSettings(
    priority = 100,
    siteFields = typeof(StandardSiteFields),
    useVerb = "track.nop && (track.nopDst==-1 || track.nopDst==dst.id)",
    blockVerb = "true",
    templateString = "agv.Nop(${src.id},${dst.id},${track.id});",
    trackFields = typeof(StandardTrackFields))]

切换动作。在站点的switchString字段上定义脚本,在该站点发生路径切换时执行。一般用于进行障碍物切换。

[TemplateTrackCoderSettings(
    priority = 20,
    useVerb = "track.switcher",
    templateString = "agv.Queue(()=>{}, ()=>{${dst.switchString};});",
    siteFields = typeof(StandardSiteFields),
    trackFields = typeof(StandardTrackFields))]