Files
StandardSence/StandardScene.Magnetic/docs/MagFass2Car使用指南.html
T

1820 lines
46 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8" />
<title>MagFass2Car Guide</title>
<style>
@page { size: A4; margin: 18mm 16mm; }
body { font-family: "Microsoft YaHei", "Segoe UI", sans-serif; color: #222; line-height: 1.55; font-size: 11pt; }
h1 { font-size: 22pt; border-bottom: 2px solid #2563eb; padding-bottom: 8px; margin-top: 0; }
h2 { font-size: 16pt; color: #1e40af; margin-top: 22px; page-break-after: avoid; }
h3 { font-size: 13pt; color: #1d4ed8; margin-top: 16px; page-break-after: avoid; }
h4, h5 { font-size: 11.5pt; margin-top: 12px; page-break-after: avoid; }
p, li { orphans: 3; widows: 3; }
code, pre { font-family: Consolas, "Courier New", monospace; }
code { background: #f3f4f6; padding: 1px 4px; border-radius: 3px; font-size: 10pt; }
pre { background: #f8fafc; border: 1px solid #e5e7eb; padding: 10px; overflow-x: auto; font-size: 9.5pt; }
pre code { background: transparent; padding: 0; }
table { border-collapse: collapse; width: 100%; margin: 10px 0 14px; font-size: 10pt; page-break-inside: avoid; }
th, td { border: 1px solid #d1d5db; padding: 6px 8px; vertical-align: top; }
th { background: #eff6ff; text-align: left; }
tr:nth-child(even) td { background: #fafafa; }
blockquote { border-left: 4px solid #93c5fd; margin: 10px 0; padding: 6px 12px; color: #374151; background: #f8fafc; }
hr { border: none; border-top: 1px solid #e5e7eb; margin: 18px 0; }
ul, ol { margin: 6px 0 10px 20px; }
</style>
</head>
<body>
<h1>MagFass2CarFASS 2.0)使用指南</h1>
<blockquote><p>适用对象:第一次接触磁导航 + FASS 2.0 的调试/实施人员 </p></blockquote>
<blockquote><p>插件:`StandardScene.Magnetic.dll` </p></blockquote>
<blockquote><p>车型:`MagFass2Car` </p></blockquote>
<blockquote><p>最后更新:2026-07</p></blockquote>
<hr/>
<h2>目录</h2>
<ol>
<li>[这套系统能做什么](#1-这套系统能做什么)</li>
<li>[5 分钟快速上手](#2-5-分钟快速上手)</li>
<li>[整体架构(新手必读)](#3-整体架构新手必读)</li>
<li>[场景与进程配置](#4-场景与进程配置)</li>
<li>[车辆参数说明](#5-车辆参数说明)</li>
<li>[通讯模式:UDP 与 TCP](#6-通讯模式udp-与-tcp)</li>
<li>[三种移动方式对比](#7-三种移动方式对比)</li>
<li>[地图配置:站点与路径](#8-地图配置站点与路径)</li>
</ol>
<p> - [8.1 节点块结构](#81-协议节点块25-字节结构)</p>
<p> - [8.2 站点 fields 详细说明](#82-站点-fields-详细说明)</p>
<p> - [8.3 路径 Track fields 详细说明](#83-路径-track-fields-详细说明)</p>
<p> - [8.4 组包优先级与默认规则](#84-组包优先级与默认规则)</p>
<p> - [8.5 典型场景配置示例](#85-典型场景配置示例)</p>
<ol>
<li>[LoopMission 环线任务](#9-loopmission-环线任务)</li>
<li>[任务状态机与协议下发](#10-任务状态机与协议下发)</li>
<li>[状态查看与手动操作](#11-状态查看与手动操作)</li>
<li>[常见问题排查](#12-常见问题排查)</li>
<li>[参数推荐与检查清单](#13-参数推荐与检查清单)</li>
<li>[术语表](#14-术语表)</li>
</ol>
<hr/>
<h2>1. 这套系统能做什么</h2>
<p><code>MagFass2Car</code> 是 StandardScene **磁导航平台插件**里的 FASS 2.0 车型,主要能力:</p>
<table>
<thead><tr>
<th>能力</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td>路径下发</td>
<td>通过 <code>0xB1</code> 下发站点序列(每帧最多 10 站)</td>
</tr>
<tr>
<td>动作下发</td>
<td>通过 <code>0xA1</code> 补发站点动作(顶升、充电等)</td>
</tr>
<tr>
<td>状态接收</td>
<td>UDP 模式:车体主动上报 100B,调度回 <code>0x10</code></td>
</tr>
<tr>
<td>站点业务</td>
<td>从地图 <code>fields</code> 读取启停、分叉、顶升等,拼进任务</td>
</tr>
<tr>
<td>环线配合</td>
<td>与 Core <code>LoopMission</code> 配合,自动跑 <code>goalSite</code></td>
</tr>
<tr>
<td>任务闭环</td>
<td>状态机判断到站 + 动作是否完成,再发下一段</td>
</tr>
</tbody>
</table>
<p>同一插件内还有 **<code>MagCar</code>FASS 1.0 TCP**,两者可并存,注意车型和 Mission 不要配混。</p>
<hr/>
<h2>2. 5 分钟快速上手</h2>
<h3>步骤 1:加载插件</h3>
<p>确认场景已加载 <code>scene.mag</code><code>StandardScene.Magnetic.scene.json</code>),提供:</p>
<ul>
<li>车型:<code>MagCar</code><code>MagFass2Car</code></li>
<li>进程:<code>EventCarMission</code><code>MagFass2LoopMission</code></li>
</ul>
<h3>步骤 2:添加一辆车</h3>
<ol>
<li>在场景中添加车型 **<code>MagFass2Car</code>**</li>
<li>填写基本参数(UDP 模式示例):</li>
</ol>
<table>
<thead><tr>
<th>参数</th>
<th>示例值</th>
<th>含义</th>
</tr>
</thead>
<tbody><tr>
<td><code>address</code></td>
<td><code>192.168.1.100</code></td>
<td>车体 IP</td>
</tr>
<tr>
<td><code>Port</code></td>
<td><code>5000</code></td>
<td>下发命令的目标端口</td>
</tr>
<tr>
<td><code>ListenPort</code></td>
<td><code>20103</code></td>
<td>调度监听车体上报的端口</td>
</tr>
<tr>
<td><code>VehicleCode</code></td>
<td><code>1</code></td>
<td>车体编号,须与上报帧一致</td>
</tr>
<tr>
<td><code>CommMode</code></td>
<td><code>Udp</code></td>
<td>PCB/UDP 模式(推荐)</td>
</tr>
</tbody>
</table>
<h3>步骤 3:确认在线</h3>
<ul>
<li>车体开始 UDP 上报后,车辆状态应显示「上线」</li>
<li><code>keepAlive</code> 日志出现 <code>keepAlive udp ok</code></li>
<li>枚举里 <code>Protocol</code> = <code>FASS2.0/UDP</code></li>
</ul>
<h3>步骤 4:手动走一步(验证通讯)</h3>
<p>在车辆方法里点 **「查询状态」**,再点 **「启动」**,确认有日志且无报错。</p>
<h3>步骤 5:跑一段路径</h3>
<p>**方式 A — 手动 Go(Web/调度下发)** </p>
<p>用系统自带的「去某站」功能,内部会编译脚本,例如:</p>
<pre><code>
agv.MagFass2Go(1, 2, 0.2);
agv.MagFass2Go(2, 5, 0.2);
</code></pre>
<p>**方式 B — LoopMission 环线** </p>
<ol>
<li>添加 **<code>LoopMission</code>** 或 **<code>磁导航FASS2环线</code>**</li>
<li>配置 <code>tasklist.json</code></li>
<li>启动进程</li>
<li>车到站后自动分配 <code>goalSite</code> 并导航</li>
</ol>
<hr/>
<h2>3. 整体架构(新手必读)</h2>
<pre><code>
┌─────────────────────────────────────────────────────────┐
│ 业务层:LoopMission / 手动 Go / 脚本 │
│ (分配 goalSite 或编译多行 MagFass2Go
└────────────────────────┬────────────────────────────────┘
┌─────────────────────────────────────────────────────────┐
│ MagFass2Car 执行层 │
&#183; 脚本拦截(Loop + goalSite)→ 一次全程任务 │
&#183; Fass2TaskBuilder:路径 + fields → 节点序列 │
&#183; Fass2TaskStateMachine:滑动窗口下发 + 动作闭环 │
└────────────────────────┬────────────────────────────────┘
┌─────────────────────────────────────────────────────────┐
│ 协议层:Fass2Protocol + Fass2UdpHub │
&#183; 收 100B 状态 → 回 0x10 │
&#183; 发 0x01/0xB1/0xA1 到 address:Port │
└────────────────────────┬────────────────────────────────┘
AGV 车体
</code></pre>
<p>**关键理解:**</p>
<ul>
<li>**LoopMissionCore** 只负责「给谁分配哪个目标站」(写 <code>goalSite</code> 标签)</li>
<li>**MagFass2Car** 负责「怎么走过去」(拼包、下发、等到站)</li>
<li>**阶段 4** 后,Loop 不再逐行执行多段脚本,而是**拦截为一次全程任务**(可关)</li>
</ul>
<hr/>
<h2>4. 场景与进程配置</h2>
<h3>4.1 插件清单</h3>
<p>文件:<code>StandardScene.Magnetic.scene.json</code></p>
<pre><code>
{
&quot;carTypes&quot;: [ &quot;MagCar&quot;, &quot;MagFass2Car&quot; ],
&quot;missionTypes&quot;: [ &quot;EventCarMission&quot;, &quot;MagFass2LoopMission&quot; ]
}
</code></pre>
<h3>4.2 选哪个 Mission</h3>
<table>
<thead><tr>
<th>Mission</th>
<th>来源</th>
<th>适用</th>
</tr>
</thead>
<tbody><tr>
<td><code>LoopMission</code></td>
<td>Core</td>
<td>通用环线,MagFass2Car 同样可用</td>
</tr>
<tr>
<td><code>磁导航FASS2环线</code><code>MagFass2LoopMission</code></td>
<td>Magnetic 插件</td>
<td>逻辑与 LoopMission 相同,名称标识磁导航 FASS2 场景</td>
</tr>
<tr>
<td><code>FASS车辆事件进程</code><code>EventCarMission</code></td>
<td>Magnetic 插件</td>
<td>**仅 MagCarFASS 1.0**,不驱动 MagFass2Car</td>
</tr>
</tbody>
</table>
<blockquote><p>新手建议:MagFass2Car 环线用 **`LoopMission`** 或 **`磁导航FASS2环线`** 均可。</p></blockquote>
<h3>4.3 tasklist.json 最小示例</h3>
<pre><code>
{
&quot;tasks&quot;: [
{
&quot;id&quot;: &quot;loop-1-2&quot;,
&quot;startType&quot;: &quot;AutoLoop&quot;,
&quot;kind&quot;: &quot;Loop&quot;,
&quot;currentStationId&quot;: 1,
&quot;targetStationId&quot;: 2,
&quot;priority&quot;: 1,
&quot;trafficControl&quot;: 2
},
{
&quot;id&quot;: &quot;loop-2-1&quot;,
&quot;startType&quot;: &quot;AutoLoop&quot;,
&quot;kind&quot;: &quot;Loop&quot;,
&quot;currentStationId&quot;: 2,
&quot;targetStationId&quot;: 1,
&quot;priority&quot;: 1,
&quot;trafficControl&quot;: 2
}
]
}
</code></pre>
<p>含义:车到站 1 → 自动分配目标站 2;到站 2 → 自动分配目标站 1,形成环线。</p>
<hr/>
<h2>5. 车辆参数说明</h2>
<p>在场景编辑器中选中 <code>MagFass2Car</code>,常用字段如下。</p>
<h3>5.1 通讯</h3>
<table>
<thead><tr>
<th>字段</th>
<th>默认</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td><code>CommMode</code></td>
<td><code>Udp</code></td>
<td><code>Udp</code>=PCB 被动收状态;<code>Tcp</code>=PLC 主动查询</td>
</tr>
<tr>
<td><code>address</code></td>
<td></td>
<td>车体 IP</td>
</tr>
<tr>
<td><code>Port</code></td>
<td><code>5000</code></td>
<td>命令下发端口</td>
</tr>
<tr>
<td><code>ListenPort</code></td>
<td><code>20103</code></td>
<td>调度 UDP 监听端口</td>
</tr>
<tr>
<td><code>VehicleCode</code></td>
<td><code>0</code></td>
<td>必须与车体上报的 <code>Car</code> 字段一致</td>
</tr>
<tr>
<td><code>UdpOfflineTimeoutMs</code></td>
<td><code>15000</code></td>
<td>超过此时间未收到上报视为离线</td>
</tr>
</tbody>
</table>
<h3>5.2 任务与状态机</h3>
<table>
<thead><tr>
<th>字段</th>
<th>默认</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td><code>EnableTaskStateMachine</code></td>
<td><code>true</code></td>
<td>开启任务状态机(推荐)</td>
</tr>
<tr>
<td><code>EnableLoopTaskDrive</code></td>
<td><code>true</code></td>
<td>Loop 场景拦截多段脚本,改全程任务</td>
</tr>
<tr>
<td><code>LockCount</code></td>
<td><code>4</code></td>
<td>每次 <code>0xB1</code> 滑动窗口站数(≤10</td>
</tr>
<tr>
<td><code>TaskResendIntervalMs</code></td>
<td><code>500</code></td>
<td>周期重发 <code>0xB1</code> 间隔</td>
</tr>
<tr>
<td><code>ActionRetryIntervalMs</code></td>
<td><code>1000</code></td>
<td>动作未完成时 <code>0xA1</code> 重试间隔</td>
</tr>
<tr>
<td><code>MoveTimeoutSeconds</code></td>
<td><code>120</code></td>
<td>单次移动超时(秒)</td>
</tr>
<tr>
<td><code>StartBeforeMove</code></td>
<td><code>true</code></td>
<td>移动前发 <code>0x01</code> 启动</td>
</tr>
</tbody>
</table>
<h3>5.3 地图节点映射</h3>
<table>
<thead><tr>
<th>字段</th>
<th>默认</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td><code>UseTagValueAsNode</code></td>
<td><code>false</code></td>
<td><code>true</code> 时用站点 <code>TagValue</code> 作为协议 <code>Node</code></td>
</tr>
</tbody>
</table>
<h3>5.4 调试</h3>
<table>
<thead><tr>
<th>字段</th>
<th>默认</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td><code>EnableDetailLog</code></td>
<td><code>true</code></td>
<td>详细日志</td>
</tr>
<tr>
<td><code>LogRawFrame</code></td>
<td><code>true</code></td>
<td>打印收发十六进制</td>
</tr>
</tbody>
</table>
<hr/>
<h2>6. 通讯模式:UDP 与 TCP</h2>
<h3>6.1 UDP/PCB(推荐,现场 FASS 2.0 新车默认)</h3>
<pre><code>
车体 ──UDP──► 调度 ListenPort100B 状态)
调度 ──UDP──► 车体 address:Port0x10 应答)
调度 ──UDP──► 车体 address:Port0xB1/0xA1/0x01,独立发送)
</code></pre>
<p>特点:</p>
<ul>
<li>调度**不主动轮询**,靠车体上报驱动状态机</li>
<li>每收到一帧状态,**必须回 <code>0x10</code>**(已由 <code>Fass2UdpHub</code> 自动处理)</li>
<li>下发命令**不等待同步应答**(异步)</li>
</ul>
<h3>6.2 TCP/PLC(调试/兼容)</h3>
<ul>
<li>调度主动发 <code>0x00</code> 查询,同步收 100B</li>
<li>适合仿真器或无 UDP 上报的环境</li>
<li>设置 <code>CommMode = Tcp</code>,配置 <code>ConnectTimeoutMs</code></li>
</ul>
<h3>6.3 端口核对清单</h3>
<table>
<thead><tr>
<th>检查项</th>
<th>操作</th>
</tr>
</thead>
<tbody><tr>
<td>车体上报发到哪</td>
<td>确认发往调度机 <code>ListenPort</code></td>
</tr>
<tr>
<td>调度命令发到哪</td>
<td>确认 <code>address:Port</code> 与车体监听一致</td>
</tr>
<tr>
<td>编号一致</td>
<td><code>VehicleCode</code> = 上报帧内 <code>Car</code> 字段</td>
</tr>
<tr>
<td>防火墙</td>
<td>放行 UDP 双向</td>
</tr>
</tbody>
</table>
<hr/>
<h2>7. 三种移动方式对比</h2>
<h3>方式 1:多段脚本(传统)</h3>
<p>**触发**:手动 Go、<code>EnableLoopTaskDrive=false</code> 时的 Loop、任意编译脚本。</p>
<p>**流程**</p>
<pre><code>
FindRoute → Compile → 多行脚本:
agv.MagFass2Go(1,2,speed);
agv.MagFass2Go(2,3,speed);
...
→ SelfEvaluating 逐行执行
→ 每行:锁终点 → 发 0xB1 → 等到站 → 释放起点
</code></pre>
<p>**特点**:每**条边**一段任务,多次 <code>taskId</code>,与交管「逐段锁点」一致。</p>
<hr/>
<h3>方式 2:Loop 全程任务(阶段 4,默认)</h3>
<p>**触发**<code>goalSite</code> 标签 + 编译脚本含 <code>MagFass2Go</code> + <code>EnableLoopTaskDrive=true</code></p>
<p>**流程**</p>
<pre><code>
LoopMission 写 goalSite
→ GoSite 仍 Compile 多行脚本(Core 不变)
→ actualSendScript 拦截,不逐行执行
→ ExecuteGoalTaskAsync(当前站 → goalSite)
→ 状态机一次规划全程,滑动窗口发 0xB1
</code></pre>
<p>**特点**:业务上一次任务,协议上仍遵守每帧 ≤10 站。</p>
<hr/>
<h3>方式 3:单段 MagFass2Go(脚本一行)</h3>
<p>**触发**:脚本里只有一行,或无 <code>goalSite</code> 的测试。</p>
<p>**流程**:与方式 1 的单行相同,状态机只跑 <code>src → dst</code> 一段。</p>
<hr/>
<h3>对比表</h3>
<table>
<thead><tr>
<th>维度</th>
<th>多段脚本</th>
<th>Loop 全程任务</th>
</tr>
</thead>
<tbody><tr>
<td>规划范围</td>
<td>每条边</td>
<td>当前站 → goalSite</td>
</tr>
<tr>
<td>taskId</td>
<td>每段一个</td>
<td>全程一个</td>
</tr>
<tr>
<td>交通锁</td>
<td>每段锁终点</td>
<td>只锁 goalSite</td>
</tr>
<tr>
<td>适用</td>
<td>手动调试、兼容旧逻辑</td>
<td>环线自动跑</td>
</tr>
<tr>
<td>开关</td>
<td><code>EnableLoopTaskDrive=false</code></td>
<td><code>EnableLoopTaskDrive=true</code>(默认)</td>
</tr>
</tbody>
</table>
<hr/>
<h2>8. 地图配置:站点与路径</h2>
<p>任务组包时,调度读取地图中站点(Site)和路径(Track)的 <code>fields</code> 键值,合并写入 FASS 2.0 的 <code>0xB1</code> 节点块(每站 25 字节)。</p>
<p>**配置位置**:地图编辑器 → 选中站点或路径 → 属性/fields 面板 → 添加键值对。</p>
<p>**命名约定**</p>
<ul>
<li>业务动作字段统一以 <code>Fass2_</code> 开头(代码常量见 <code>Fass2SiteFields.cs</code></li>
<li>值为**十进制整数**字符串,例如 <code>Fass2_Lift</code> = <code>1</code></li>
<li>布尔字段写 <code>true</code> / <code>false</code><code>1</code> / <code>0</code></li>
</ul>
<hr/>
<h3>8.1 协议节点块(25 字节结构)</h3>
<p>每个站点在 <code>0xB1</code> 中对应一个节点,主要字段如下(与 <code>Fass2NodeMessage</code> 一致):</p>
<table>
<thead><tr>
<th>偏移</th>
<th>字段</th>
<th>类型</th>
<th>来源</th>
</tr>
</thead>
<tbody><tr>
<td>01</td>
<td><code>Node</code></td>
<td>ushort</td>
<td>站点 <code>TagValue</code><code>site.id</code></td>
</tr>
<tr>
<td>23</td>
<td><code>Distance</code></td>
<td>ushort</td>
<td>上一站到本站的边长(mm 量级)</td>
</tr>
<tr>
<td>4</td>
<td><code>StartStop</code></td>
<td>byte</td>
<td>站点 <code>Fass2_StartStop</code> / 默认规则</td>
</tr>
<tr>
<td>5</td>
<td><code>Direction</code></td>
<td>byte</td>
<td>站点或边 fields</td>
</tr>
<tr>
<td>6</td>
<td><code>Orientation</code></td>
<td>byte</td>
<td>边朝向计算或站点覆盖</td>
</tr>
<tr>
<td>7</td>
<td><code>Byroad</code></td>
<td>byte</td>
<td>分叉选择,站点或边</td>
</tr>
<tr>
<td>89</td>
<td><code>Speed</code></td>
<td>ushort</td>
<td><code>Speed</code> 换算(0.1 m/min 单位)</td>
</tr>
<tr>
<td>10</td>
<td><code>Obstacle</code></td>
<td>byte</td>
<td>站点</td>
</tr>
<tr>
<td>11</td>
<td><code>Audio</code></td>
<td>byte</td>
<td>站点</td>
</tr>
<tr>
<td>12</td>
<td><code>Light</code></td>
<td>byte</td>
<td>站点</td>
</tr>
<tr>
<td>13</td>
<td><code>Charge</code></td>
<td>byte</td>
<td>站点</td>
</tr>
<tr>
<td>14</td>
<td><code>Rest</code></td>
<td>byte</td>
<td>站点</td>
</tr>
<tr>
<td>15</td>
<td><code>Lift</code></td>
<td>byte</td>
<td>站点</td>
</tr>
<tr>
<td>16</td>
<td><code>Clamp</code></td>
<td>byte</td>
<td>站点</td>
</tr>
<tr>
<td>17</td>
<td><code>Tray</code></td>
<td>byte</td>
<td>站点</td>
</tr>
<tr>
<td>18</td>
<td><code>Roll</code></td>
<td>byte</td>
<td>站点</td>
</tr>
<tr>
<td>19</td>
<td><code>Shutdown</code></td>
<td>byte</td>
<td>站点</td>
</tr>
</tbody>
</table>
<p>状态机到站后,会比对车体上报状态帧中**同一节点块**的字段是否达到期望值;未达标则补发 <code>0xA1</code></p>
<hr/>
<h3>8.2 站点 fields 详细说明</h3>
<h4>8.2.1 节点与调度类</h4>
<h5>`TagValue`int,可选)</h5>
<table>
<thead><tr>
<th>项目</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td>映射协议字段</td>
<td><code>Node</code>(节点号)</td>
</tr>
<tr>
<td>何时配置</td>
<td>磁导航地标号与地图 <code>site.id</code> **不一致**时必须配置</td>
</tr>
<tr>
<td>车辆开关</td>
<td><code>MagFass2Car.UseTagValueAsNode = true</code></td>
</tr>
<tr>
<td>示例</td>
<td><code>TagValue = 10086</code></td>
</tr>
<tr>
<td>注意</td>
<td>未配置且 <code>UseTagValueAsNode=false</code> 时,直接用 <code>site.id</code> 作为节点号</td>
</tr>
</tbody>
</table>
<h5>`goSite`int,可选)</h5>
<table>
<thead><tr>
<th>项目</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td>映射协议字段</td>
<td>无(不参与 0xB1 组包)</td>
</tr>
<tr>
<td>用途</td>
<td>LoopMission 在该站无任务匹配时,读取此字段作为默认下一目标</td>
</tr>
<tr>
<td>读取方</td>
<td>Core <code>AbstractLoopMission.LoopStartAction</code></td>
</tr>
<tr>
<td>示例</td>
<td>站 3 配 <code>goSite = 5</code>,车到站 3 且无 tasklist 匹配时,自动写 <code>goalSite=5</code></td>
</tr>
</tbody>
</table>
<h5>`Fass2_WaitMode`string,预留)</h5>
<table>
<thead><tr>
<th>项目</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td>映射协议字段</td>
<td>无(当前版本不直接写入节点块)</td>
</tr>
<tr>
<td>规划值</td>
<td><code>None</code> / <code>Button</code> / <code>Plc</code> / <code>Api</code></td>
</tr>
<tr>
<td>当前状态</td>
<td>字段已定义,**等待放行联动逻辑待扩展**;可通过修改 <code>Fass2_StartStop</code> 或外部改 fields 触发重发</td>
</tr>
</tbody>
</table>
<hr/>
<h4>8.2.2 `Fass2_StartStop` — 启停模式(byte</h4>
<p>映射协议字段:<code>StartStop</code>(节点块第 5 字节)</p>
<table>
<thead><tr>
<th></th>
<th>含义(对齐 FASS 2.0 字典)</th>
<th>典型场景</th>
</tr>
</thead>
<tbody><tr>
<td><code>1</code></td>
<td>过站(不停)</td>
<td>路径中间站、通道站</td>
</tr>
<tr>
<td><code>2</code></td>
<td>普通停车</td>
<td>工位、等待点、装卸点</td>
</tr>
<tr>
<td><code>11</code></td>
<td>管控启动</td>
<td>管控区入口,需授权后启动</td>
</tr>
<tr>
<td><code>12</code></td>
<td>管控停止</td>
<td>管控区停车等待</td>
</tr>
<tr>
<td><code>22</code></td>
<td>精准停止</td>
<td>装配、对接,精度要求高</td>
</tr>
</tbody>
</table>
<p>**默认规则**(未显式配置 <code>Fass2_StartStop</code> 时,<code>Fass2TaskBuilder</code> 自动决定):</p>
<table>
<thead><tr>
<th>站点位置</th>
<th>默认 <code>StartStop</code></th>
</tr>
</thead>
<tbody><tr>
<td>中间站</td>
<td><code>1</code>(过站)</td>
</tr>
<tr>
<td>末站(goalSite</td>
<td><code>2</code>(停车)</td>
</tr>
<tr>
<td>末站 + <code>Fass2_PrecisionStop=true</code></td>
<td><code>22</code>(精准停)</td>
</tr>
</tbody>
</table>
<p>**动作完成判定**:若配置了非过站值,状态机要求上报 <code>Node.StartStop</code> 与期望值一致,且车体非运行态(<code>State≠1</code>),才推进下一段。</p>
<p>**与 <code>Fass2_PrecisionStop</code> 关系**</p>
<ul>
<li>可直接写 <code>Fass2_StartStop = 22</code></li>
<li>或末站写 <code>Fass2_PrecisionStop = true</code>,由组包器自动设为 <code>22</code></li>
</ul>
<hr/>
<h4>8.2.3 `Fass2_PrecisionStop` — 精准停(bool</h4>
<table>
<thead><tr>
<th>项目</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td>类型</td>
<td><code>true</code> / <code>false</code> / <code>1</code> / <code>0</code></td>
</tr>
<tr>
<td>效果</td>
<td>仅对**路径末站**生效,等价于 <code>StartStop = 22</code></td>
</tr>
<tr>
<td>优先级</td>
<td>低于显式 <code>Fass2_StartStop</code>(若同时配置,以 <code>Fass2_StartStop</code> 为准)</td>
</tr>
<tr>
<td>示例</td>
<td>装配工位末站:<code>Fass2_PrecisionStop = true</code></td>
</tr>
</tbody>
</table>
<hr/>
<h4>8.2.4 `Fass2_Byroad` — 分叉选择(byte</h4>
<p>映射协议字段:<code>Byroad</code></p>
<table>
<thead><tr>
<th>项目</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td>取值范围</td>
<td>通常 <code>0</code><code>3</code>,表示磁分叉/岔路选择序号</td>
</tr>
<tr>
<td>站点 vs 边</td>
<td>站点显式配置优先;未配置时继承**进入该站的边** <code>Fass2_Byroad</code><code>magSelect</code></td>
</tr>
<tr>
<td>典型场景</td>
<td>Y 型路口、多磁条岔口</td>
</tr>
<tr>
<td>完成判定</td>
<td>若期望值非 0,上报 <code>Node.Byroad</code> 须一致</td>
</tr>
</tbody>
</table>
<hr/>
<h4>8.2.5 `Fass2_Direction` — 车头旋转(byte</h4>
<p>映射协议字段:<code>Direction</code></p>
<table>
<thead><tr>
<th>项目</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td>含义</td>
<td>到站后车头旋转指令(具体角度定义以车体协议为准)</td>
</tr>
<tr>
<td>站点 vs 边</td>
<td>站点配置覆盖边配置</td>
</tr>
<tr>
<td>完成判定</td>
<td>上报 <code>Node.Direction</code> 与期望值一致</td>
</tr>
</tbody>
</table>
<hr/>
<h4>8.2.6 `Fass2_Orientation` — 行驶朝向(byte</h4>
<p>映射协议字段:<code>Orientation</code></p>
<table>
<thead><tr>
<th>项目</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td>含义</td>
<td>进出该站时的前进/后退/横移朝向(0–255,对应 0&#176;360&#176; 量化)</td>
</tr>
<tr>
<td>默认</td>
<td>由边几何计算:<code>atan2(Δy, Δx)</code> + <code>Reverse</code> + <code>CarDirectionBias</code></td>
</tr>
<tr>
<td>覆盖</td>
<td>站点或边显式配置 <code>Fass2_Orientation</code> 时直接使用</td>
</tr>
<tr>
<td>完成判定</td>
<td>非 0 期望值时须上报一致</td>
</tr>
</tbody>
</table>
<hr/>
<h4>8.2.7 `Fass2_Lift` — 顶升/举升(byte</h4>
<p>映射协议字段:<code>Lift</code></p>
<table>
<thead><tr>
<th></th>
<th>含义(对齐 backend 字典)</th>
</tr>
</thead>
<tbody><tr>
<td><code>1</code></td>
<td>上升到位</td>
</tr>
<tr>
<td><code>2</code></td>
<td>下降到位</td>
</tr>
<tr>
<td><code>3</code></td>
<td>上升中</td>
</tr>
<tr>
<td><code>4</code></td>
<td>下降中</td>
</tr>
</tbody>
</table>
<table>
<thead><tr>
<th>项目</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td>典型场景</td>
<td>顶升搬运、装卸高度切换</td>
</tr>
<tr>
<td>配置建议</td>
<td>工位停车(<code>StartStop=2</code>+ <code>Fass2_Lift=1</code><code>2</code></td>
</tr>
<tr>
<td>完成判定</td>
<td>上报 <code>Node.Lift</code> 等于配置值;未完成自动 <code>0xA1</code> 补发</td>
</tr>
<tr>
<td>注意</td>
<td>一般配**到位值**(1/2),不要配中间态(3/4)除非明确需要</td>
</tr>
</tbody>
</table>
<hr/>
<h4>8.2.8 `Fass2_Roll` — 滚筒(byte</h4>
<p>映射协议字段:<code>Roll</code></p>
<table>
<thead><tr>
<th>项目</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td>用途</td>
<td>滚筒输送启停/方向</td>
</tr>
<tr>
<td>取值</td>
<td>以现场车体协议为准(写入节点块第 19 字节)</td>
</tr>
<tr>
<td>完成判定</td>
<td>期望值非 0 时须上报一致</td>
</tr>
</tbody>
</table>
<hr/>
<h4>8.2.9 `Fass2_Charge` — 充电(byte</h4>
<p>映射协议字段:<code>Charge</code></p>
<table>
<thead><tr>
<th></th>
<th>含义</th>
</tr>
</thead>
<tbody><tr>
<td><code>1</code></td>
<td>停止充电</td>
</tr>
<tr>
<td><code>2</code></td>
<td>开始充电</td>
</tr>
</tbody>
</table>
<table>
<thead><tr>
<th>项目</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td>典型场景</td>
<td>充电站、<code>LoopMission</code> 充电触发任务</td>
</tr>
<tr>
<td>配置建议</td>
<td>充电工位:<code>Fass2_StartStop=2</code> + <code>Fass2_Charge=2</code></td>
</tr>
<tr>
<td>离站</td>
<td>下一任务或离站前可配 <code>Fass2_Charge=1</code></td>
</tr>
</tbody>
</table>
<hr/>
<h4>8.2.10 `Fass2_Rest` — 休眠(byte</h4>
<p>映射协议字段:<code>Rest</code></p>
<table>
<thead><tr>
<th></th>
<th>含义</th>
</tr>
</thead>
<tbody><tr>
<td><code>1</code></td>
<td>停止睡眠</td>
</tr>
<tr>
<td><code>2</code></td>
<td>开始睡眠</td>
</tr>
</tbody>
</table>
<table>
<thead><tr>
<th>项目</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td>典型场景</td>
<td>长时间待机工位、低功耗停车区</td>
</tr>
</tbody>
</table>
<hr/>
<h4>8.2.11 `Fass2_Obstacle` — 避障区(byte</h4>
<p>映射协议字段:<code>Obstacle</code></p>
<table>
<thead><tr>
<th>项目</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td>用途</td>
<td>切换车体避障区域/模式</td>
</tr>
<tr>
<td>取值</td>
<td>以车体协议定义为准(区域编号)</td>
</tr>
<tr>
<td>典型场景</td>
<td>进入狭窄通道、人机混行区</td>
</tr>
</tbody>
</table>
<hr/>
<h4>8.2.12 `Fass2_Audio` / `Fass2_Light` — 声光(byte</h4>
<table>
<thead><tr>
<th>字段</th>
<th>协议字段</th>
<th>用途</th>
</tr>
</thead>
<tbody><tr>
<td><code>Fass2_Audio</code></td>
<td><code>Audio</code></td>
<td>提示音、播报</td>
</tr>
<tr>
<td><code>Fass2_Light</code></td>
<td><code>Light</code></td>
<td>警示灯、状态灯</td>
</tr>
</tbody>
</table>
<p>取值以车体协议为准,一般为模式/曲目/灯色编号。</p>
<hr/>
<h4>8.2.13 `Fass2_Clamp` — 夹抱(byte</h4>
<p>映射协议字段:<code>Clamp</code></p>
<table>
<thead><tr>
<th>项目</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td>用途</td>
<td>夹紧/松开机构</td>
</tr>
<tr>
<td>典型场景</td>
<td>夹抱式 AGV、治具锁紧</td>
</tr>
</tbody>
</table>
<hr/>
<h4>8.2.14 `Fass2_Tray` — 托盘(byte</h4>
<p>映射协议字段:<code>Tray</code></p>
<table>
<thead><tr>
<th>项目</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td>用途</td>
<td>托盘旋转/伸缩等机构</td>
</tr>
<tr>
<td>典型场景</td>
<td>多工位转台、托盘调角</td>
</tr>
</tbody>
</table>
<hr/>
<h4>8.2.15 `Fass2_Shutdown` — 关机(byte</h4>
<p>映射协议字段:<code>Shutdown</code></p>
<table>
<thead><tr>
<th>项目</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td>用途</td>
<td>到站后车体软关机/深度待机</td>
</tr>
<tr>
<td>注意</td>
<td>与全局 <code>0x06</code> 关机指令不同;此为**任务节点内**动作</td>
</tr>
<tr>
<td>风险</td>
<td>配置后车体可能下线,需人工或远程重启</td>
</tr>
</tbody>
</table>
<hr/>
<h4>8.2.16 站点 fields 速查总表</h4>
<table>
<thead><tr>
<th>字段键</th>
<th>类型</th>
<th>协议字段</th>
<th>是否参与动作闭环</th>
</tr>
</thead>
<tbody><tr>
<td><code>TagValue</code></td>
<td>int</td>
<td><code>Node</code></td>
<td>否(仅节点映射)</td>
</tr>
<tr>
<td><code>goSite</code></td>
<td>int</td>
<td></td>
<td>否(Loop 调度用)</td>
</tr>
<tr>
<td><code>Fass2_StartStop</code></td>
<td>byte</td>
<td><code>StartStop</code></td>
<td></td>
</tr>
<tr>
<td><code>Fass2_PrecisionStop</code></td>
<td>bool</td>
<td><code>StartStop</code>→22</td>
<td></td>
</tr>
<tr>
<td><code>Fass2_Byroad</code></td>
<td>byte</td>
<td><code>Byroad</code></td>
<td>是(非 0 时)</td>
</tr>
<tr>
<td><code>Fass2_Direction</code></td>
<td>byte</td>
<td><code>Direction</code></td>
<td>是(非 0 时)</td>
</tr>
<tr>
<td><code>Fass2_Orientation</code></td>
<td>byte</td>
<td><code>Orientation</code></td>
<td>是(非 0 时)</td>
</tr>
<tr>
<td><code>Fass2_Lift</code></td>
<td>byte</td>
<td><code>Lift</code></td>
<td>是(非 0 时)</td>
</tr>
<tr>
<td><code>Fass2_Roll</code></td>
<td>byte</td>
<td><code>Roll</code></td>
<td>是(非 0 时)</td>
</tr>
<tr>
<td><code>Fass2_Charge</code></td>
<td>byte</td>
<td><code>Charge</code></td>
<td>是(非 0 时)</td>
</tr>
<tr>
<td><code>Fass2_Obstacle</code></td>
<td>byte</td>
<td><code>Obstacle</code></td>
<td>是(非 0 时)</td>
</tr>
<tr>
<td><code>Fass2_Audio</code></td>
<td>byte</td>
<td><code>Audio</code></td>
<td>是(非 0 时)</td>
</tr>
<tr>
<td><code>Fass2_Light</code></td>
<td>byte</td>
<td><code>Light</code></td>
<td>是(非 0 时)</td>
</tr>
<tr>
<td><code>Fass2_Rest</code></td>
<td>byte</td>
<td><code>Rest</code></td>
<td>是(非 0 时)</td>
</tr>
<tr>
<td><code>Fass2_Clamp</code></td>
<td>byte</td>
<td><code>Clamp</code></td>
<td>是(非 0 时)</td>
</tr>
<tr>
<td><code>Fass2_Tray</code></td>
<td>byte</td>
<td><code>Tray</code></td>
<td>是(非 0 时)</td>
</tr>
<tr>
<td><code>Fass2_Shutdown</code></td>
<td>byte</td>
<td><code>Shutdown</code></td>
<td>是(非 0 时)</td>
</tr>
<tr>
<td><code>Fass2_WaitMode</code></td>
<td>string</td>
<td></td>
<td>预留</td>
</tr>
</tbody>
</table>
<hr/>
<h3>8.3 路径 Track fields 详细说明</h3>
<p>路径 fields 主要影响**进入该站的那段边**(距离、速度、朝向、分叉)。</p>
<table>
<thead><tr>
<th>字段键</th>
<th>类型</th>
<th>映射</th>
<th>详细说明</th>
</tr>
</thead>
<tbody><tr>
<td><code>Speed</code></td>
<td>float</td>
<td><code>Speed</code></td>
<td>边速度。<code>≤1</code> 按 **m/s**(协议值 = speed&#215;600);<code>&gt;1</code> 按 **m/min**(协议值 = speed&#215;10)。未配置默认 0.2 m/s</td>
</tr>
<tr>
<td><code>Reverse</code></td>
<td>bool</td>
<td><code>Orientation</code></td>
<td><code>true</code> 时朝向 +180&#176;</td>
</tr>
<tr>
<td><code>CarDirectionBias</code></td>
<td>float</td>
<td><code>Orientation</code></td>
<td>朝向偏置(度),叠加到几何朝向</td>
</tr>
<tr>
<td><code>EnableCarAbsoluteDirection</code></td>
<td>bool</td>
<td><code>Orientation</code></td>
<td><code>true</code> 时用 <code>CarAbsoluteDirection</code> 代替几何计算</td>
</tr>
<tr>
<td><code>CarAbsoluteDirection</code></td>
<td>float</td>
<td><code>Orientation</code></td>
<td>绝对朝向(度,0360</td>
</tr>
<tr>
<td><code>Fass2_Byroad</code></td>
<td>byte</td>
<td><code>Byroad</code></td>
<td>边级分叉;站点未配 <code>Fass2_Byroad</code> 时生效</td>
</tr>
<tr>
<td><code>magSelect</code></td>
<td>byte</td>
<td><code>Byroad</code></td>
<td>磁导航 coder 分叉序号;<code>Fass2_Byroad</code> 为空时作为 Byroad 备选</td>
</tr>
<tr>
<td><code>Fass2_Direction</code></td>
<td>byte</td>
<td><code>Direction</code></td>
<td>边级车头旋转;站点未覆盖时生效</td>
</tr>
<tr>
<td><code>Fass2_Orientation</code></td>
<td>byte</td>
<td><code>Orientation</code></td>
<td>边级朝向;站点未覆盖时生效</td>
</tr>
<tr>
<td><code>Magnet</code></td>
<td>bool</td>
<td></td>
<td><code>true</code> 启用 <code>MagneticTrackCoder</code><code>agv.MagGo</code> 等),与 <code>MagFass2Go</code> 模板独立</td>
</tr>
<tr>
<td><code>ReverseDst</code></td>
<td>int</td>
<td></td>
<td>倒车目的地站 ID;磁 coder 跳过该边</td>
</tr>
</tbody>
</table>
<p>**距离 <code>Distance</code>**:由地图坐标自动计算(上一站与本站欧氏距离,mm 取整),一般无需手配。</p>
<hr/>
<h3>8.4 组包优先级与默认规则</h3>
<p>当同一协议字段在站点和边都有配置时:</p>
<pre><code>
站点 Fass2_* &gt; 边 Fass2_* &gt; 边通用字段(Speed/Reverse/magSelect&gt; 系统默认
</code></pre>
<p>**<code>StartStop</code> 决定逻辑**</p>
<pre><code>
1. 若站点有 Fass2_StartStop → 直接用
2. 否则若是路径末站且 Fass2_PrecisionStop=true → 22
3. 否则若是路径末站 → 2
4. 否则 → 1(过站)
</code></pre>
<p>**<code>Byroad</code> 决定逻辑**</p>
<pre><code>
1. 站点 Fass2_Byroad
2. 边 Fass2_Byroad
3. 边 magSelect
4. 0
</code></pre>
<p>**fields 变化重发**:任务执行中,若**尚未到达的站点** <code>Fass2_*</code> 签名变化,状态机会从当前站重新 <code>BuildTaskPlan</code> 并分配新 <code>taskId</code></p>
<hr/>
<h3>8.5 典型场景配置示例</h3>
<h4>场景 A:通道过站(无动作)</h4>
<p>站点 fields:**无需配置**(中间站默认 <code>StartStop=1</code></p>
<hr/>
<h4>场景 B:普通停车工位</h4>
<pre><code>
Fass2_StartStop = 2
</code></pre>
<hr/>
<h4>场景 C:精准对接工位(末站)</h4>
<pre><code>
Fass2_PrecisionStop = true
</code></pre>
<p></p>
<pre><code>
Fass2_StartStop = 22
</code></pre>
<hr/>
<h4>场景 D:顶升装卸工位</h4>
<pre><code>
Fass2_StartStop = 2
Fass2_Lift = 1 # 到站升起到位
</code></pre>
<p>离站下一任务可在目标站配 <code>Fass2_Lift = 2</code> 下降,或通过后续路径站点 fields 覆盖。</p>
<hr/>
<h4>场景 E:充电工位</h4>
<pre><code>
Fass2_StartStop = 2
Fass2_Charge = 2 # 开始充电
</code></pre>
<hr/>
<h4>场景 FY 型磁分叉口</h4>
<p>**站点**(推荐在岔口站配):</p>
<pre><code>
Fass2_Byroad = 1 # 选择磁条 1
</code></pre>
<p>或在该站**进入边**上配:</p>
<pre><code>
magSelect = 1
# 或
Fass2_Byroad = 1
</code></pre>
<hr/>
<h4>场景 G:磁地标与站 ID 不同</h4>
<p>**站点**</p>
<pre><code>
TagValue = 10086
</code></pre>
<p>**车辆**</p>
<pre><code>
UseTagValueAsNode = true
</code></pre>
<hr/>
<h4>场景 HLoop 默认下一跳</h4>
<p>**站点 3**(车到 3 后若 tasklist 无匹配,自动去 5):</p>
<pre><code>
goSite = 5
</code></pre>
<hr/>
<h4>场景 I:完整工位(停车 + 顶升 + 精准)</h4>
<pre><code>
TagValue = 2001
Fass2_StartStop = 22
Fass2_Lift = 1
Fass2_Obstacle = 2
</code></pre>
<hr/>
<p>**配置禁忌(新手易错)**</p>
<table>
<thead><tr>
<th>错误</th>
<th>后果</th>
<th>建议</th>
</tr>
</thead>
<tbody><tr>
<td>中间站误配 <code>StartStop=2</code></td>
<td>路径中间不必要的停车</td>
<td>仅工位/末站停车</td>
</tr>
<tr>
<td><code>Lift=3/4</code>(运动中)作为目标</td>
<td>动作可能永不完成</td>
<td>用到位值 <code>1</code>/<code>2</code></td>
</tr>
<tr>
<td><code>TagValue</code> 重复</td>
<td>节点映射错乱</td>
<td>全图唯一</td>
</tr>
<tr>
<td>只配站点不配 <code>UseTagValueAsNode</code></td>
<td>下发节点号仍是 site.id</td>
<td>成对配置</td>
</tr>
</tbody>
</table>
<hr/>
<h2>9. LoopMission 环线任务</h2>
<h3>9.1 运行流程</h3>
<pre><code>
1. 车到站 NLoopMission 检测可用
2. 匹配 tasklistcurrentStationId = N → 分配 targetStationId
3. 写 tagsgoalSite = 目标站 ID
4. LoopStartAction 调用 GoSite
5. MagFass2Car 拦截 → 全程任务到 goalSite
6. 到达后 GoSite 清理 goalSite / occupied / loopAssigned
7. 下一轮任务匹配
</code></pre>
<h3>9.2 相关 tags</h3>
<table>
<thead><tr>
<th>标签</th>
<th>含义</th>
</tr>
</thead>
<tbody><tr>
<td><code>goalSite</code></td>
<td>当前要去的目标站 ID</td>
</tr>
<tr>
<td><code>loopAssigned</code></td>
<td>分配时间戳</td>
</tr>
<tr>
<td><code>occupied</code></td>
<td>车辆占用中,值如 <code>go5</code></td>
</tr>
</tbody>
</table>
<h3>9.3 与 Core 的关系</h3>
<ul>
<li>**不需要改 Core**<code>LoopMission</code> 逻辑完全沿用</li>
<li><code>磁导航FASS2环线</code> 仅为场景标识,行为与 <code>LoopMission</code> 相同</li>
<li>真正区别在 **车型** 是否 <code>MagFass2Car</code><code>EnableLoopTaskDrive=true</code></li>
</ul>
<h3>9.4 关闭 Loop 拦截(恢复多段脚本)</h3>
<pre><code>
EnableLoopTaskDrive = false
</code></pre>
<p>Loop 仍走 Compile 多行 <code>MagFass2Go</code>,每行一段边。</p>
<hr/>
<h2>10. 任务状态机与协议下发</h2>
<h3>10.1 状态流转</h3>
<pre><code>
Idle → Planning → Moving → AtStation → SegmentDone → … → Complete
Fault(急停/故障/超时)
</code></pre>
<h3>10.2 单帧最多 10 站 — 不冲突</h3>
<ul>
<li>**规划**:全程可能有 20+ 站,存在内存 <code>Plan</code></li>
<li>**下发**:每次只发滑动窗口 <code>min(LockCount, 剩余, 10)</code></li>
<li>**推进**:当前站动作完成 → <code>CurrentIndex++</code> → 再发下一段</li>
<li>**同一 taskId**:全程复用,周期重发当前窗口</li>
</ul>
<p>示例(15 站路径,<code>LockCount=4</code>):</p>
<pre><code>
第1次 0xB1:站 1,2,3,4
到站 1 后: 站 2,3,4,5
到站 2 后: 站 3,4,5,6
…直到 goalSite
</code></pre>
<p>若车体需要首帧更多预发,可将 <code>LockCount</code> 调至 **10**(不超过协议上限)。</p>
<h3>10.3 动作闭环</h3>
<p>到站后比对上报 25B 节点与期望:</p>
<table>
<thead><tr>
<th>场景</th>
<th>完成条件</th>
</tr>
</thead>
<tbody><tr>
<td>过站</td>
<td>到达节点且非运行态(<code>State≠1</code></td>
</tr>
<tr>
<td>停车</td>
<td><code>StartStop</code> 匹配</td>
</tr>
<tr>
<td>顶升/充电等</td>
<td>对应字段在状态帧中达标</td>
</tr>
<tr>
<td>未完成</td>
<td>自动补发 <code>0xA1</code>,按 <code>ActionRetryIntervalMs</code> 节流</td>
</tr>
</tbody>
</table>
<h3>10.4 车辆状态枚举(调试看)</h3>
<table>
<thead><tr>
<th>枚举键</th>
<th>含义</th>
</tr>
</thead>
<tbody><tr>
<td><code>TaskPhase</code></td>
<td>任务阶段(Idle/Moving/AtStation/…)</td>
</tr>
<tr>
<td><code>TaskGoal</code></td>
<td>目标站 ID</td>
</tr>
<tr>
<td><code>TaskIndex</code></td>
<td>当前站点索引</td>
</tr>
<tr>
<td><code>State</code></td>
<td>车体状态文字</td>
</tr>
<tr>
<td><code>CurrentNode</code></td>
<td>当前节点号</td>
</tr>
<tr>
<td><code>Task</code></td>
<td>车体上报的任务号</td>
</tr>
</tbody>
</table>
<h3>10.5 重启恢复(可选)</h3>
<p>任务上下文会写入 <code>car.tags</code><code>Fass2Task_*</code> 前缀)。重启后 <code>keepAlive</code> 尝试恢复,需等车体再次 UDP 上报后状态机继续推进。</p>
<hr/>
<h2>11. 状态查看与手动操作</h2>
<p>车辆右键方法(界面中):</p>
<table>
<thead><tr>
<th>方法</th>
<th>协议</th>
<th>用途</th>
</tr>
</thead>
<tbody><tr>
<td>查询状态</td>
<td><code>0x00</code></td>
<td>TCP 模式主动查;UDP 模式看缓存</td>
</tr>
<tr>
<td>启动</td>
<td><code>0x01</code></td>
<td>启动车体</td>
</tr>
<tr>
<td>停止</td>
<td><code>0x02</code></td>
<td>停止</td>
</tr>
<tr>
<td>急停</td>
<td><code>0x03</code></td>
<td>急停</td>
</tr>
<tr>
<td>重置UDP监听</td>
<td></td>
<td>重新注册 UDP 会话</td>
</tr>
<tr>
<td>重置TCP连接</td>
<td></td>
<td>关闭长连接(TCP 模式)</td>
</tr>
</tbody>
</table>
<p>日志前缀:<code>[MagFass2Car:车名(id)]</code>,任务状态机:<code>task-sm</code></p>
<hr/>
<h2>12. 常见问题排查</h2>
<h3>Q1:车显示离线(UDP</h3>
<table>
<thead><tr>
<th>可能原因</th>
<th>处理</th>
</tr>
</thead>
<tbody><tr>
<td>车体未上报</td>
<td>查车体是否发往 <code>ListenPort</code></td>
</tr>
<tr>
<td><code>VehicleCode</code> 不匹配</td>
<td>对照上报帧 <code>Car</code> 字段</td>
</tr>
<tr>
<td>超时</td>
<td>调大 <code>UdpOfflineTimeoutMs</code> 或查网络</td>
</tr>
<tr>
<td>IP/端口错误</td>
<td>核对 <code>address</code><code>Port</code></td>
</tr>
</tbody>
</table>
<h3>Q2:发了 0xB1 车不动</h3>
<table>
<thead><tr>
<th>可能原因</th>
<th>处理</th>
</tr>
</thead>
<tbody><tr>
<td>未启动</td>
<td>确认 <code>StartBeforeMove</code> 或手动点启动</td>
</tr>
<tr>
<td>节点号不对</td>
<td>检查 <code>UseTagValueAsNode</code><code>TagValue</code></td>
</tr>
<tr>
<td>TCP/UDP 模式搞反</td>
<td>确认 <code>CommMode</code></td>
</tr>
<tr>
<td>状态机 Fault</td>
<td><code>TaskPhase</code><code>TaskFault</code></td>
</tr>
</tbody>
</table>
<h3>Q3Loop 不分配任务</h3>
<table>
<thead><tr>
<th>可能原因</th>
<th>处理</th>
</tr>
</thead>
<tbody><tr>
<td>进程未启动</td>
<td>启动 LoopMission / 磁导航FASS2环线</td>
</tr>
<tr>
<td>tasklist 不匹配</td>
<td><code>currentStationId</code> 要等于车所在站</td>
</tr>
<tr>
<td>车不可用</td>
<td><code>Commons.SelectCar</code> 条件</td>
</tr>
<tr>
<td>已有 <code>goalSite</code></td>
<td>等上一次完成</td>
</tr>
</tbody>
</table>
<h3>Q4:到站但不继续</h3>
<table>
<thead><tr>
<th>可能原因</th>
<th>处理</th>
</tr>
</thead>
<tbody><tr>
<td>动作未完成</td>
<td><code>Lift</code>/<code>StartStop</code> 等是否与配置一致</td>
</tr>
<tr>
<td>状态机 AtStation</td>
<td><code>0xA1</code> 或检查车体动作</td>
</tr>
<tr>
<td>超时</td>
<td>调大 <code>MoveTimeoutSeconds</code></td>
</tr>
</tbody>
</table>
<h3>Q5Loop 和多段脚本哪个在生效?</h3>
<p>看日志:</p>
<ul>
<li><code>loop goal drive intercept</code> → 全程任务(阶段 4</li>
<li><code>script begin</code> + 多行 <code>MagFass2Go</code> → 多段脚本</li>
</ul>
<h3>Q6:与 MagCar 混用注意事项</h3>
<ul>
<li><code>EventCarMission</code> **只控制 MagCar**</li>
<li>同场景两种车型时,tasklist 和车辆类型要对应</li>
<li>FASS 1.0 用 <code>MagCar</code>FASS 2.0 用 <code>MagFass2Car</code></li>
</ul>
<hr/>
<h2>13. 参数推荐与检查清单</h2>
<h3>13.1 首次联调推荐配置</h3>
<pre><code>
CommMode = Udp
EnableTaskStateMachine = true
EnableLoopTaskDrive = true
LockCount = 4 (车体需更多预发可改 10)
StartBeforeMove = true
EnableDetailLog = true
LogRawFrame = true
MoveTimeoutSeconds = 120
</code></pre>
<h3>13.2 上线前检查清单</h3>
<ul>
<li>[ ] 插件 <code>StandardScene.Magnetic.dll</code> 已加载</li>
<li>[ ] 车型为 <code>MagFass2Car</code>(不是 <code>MagCar</code></li>
<li>[ ] <code>VehicleCode</code>、IP、端口与车体一致</li>
<li>[ ] UDP 能收到 100B,日志有 <code>0x10</code> 应答</li>
<li>[ ] 关键站点 <code>TagValue</code> / <code>Fass2_*</code> 已配置</li>
<li>[ ] LoopMission 已启动,<code>tasklist.json</code> 路径正确</li>
<li>[ ] 单车手动 Go 一站成功后再开环线</li>
</ul>
<hr/>
<h2>14. 术语表</h2>
<table>
<thead><tr>
<th>术语</th>
<th>解释</th>
</tr>
</thead>
<tbody><tr>
<td><code>0xB1</code></td>
<td>路径/任务下发命令,最多 10 个站点节点</td>
</tr>
<tr>
<td><code>0xA1</code></td>
<td>单站点动作下发</td>
</tr>
<tr>
<td><code>0x10</code></td>
<td>UDP 状态应答(时间戳)</td>
</tr>
<tr>
<td><code>goalSite</code></td>
<td>LoopMission 给车分配的目标站标签</td>
</tr>
<tr>
<td><code>LockCount</code></td>
<td>每次下发的滑动窗口站数</td>
</tr>
<tr>
<td><code>TaskBuilder</code></td>
<td>将地图路径+fields 拼成节点序列</td>
</tr>
<tr>
<td><code>状态机</code></td>
<td>控制规划→下发→到站→推进的自动流程</td>
</tr>
<tr>
<td>PCB/UDP</td>
<td>车体主动上报,调度被动接收</td>
</tr>
<tr>
<td>PLC/TCP</td>
<td>调度主动查询车体</td>
</tr>
</tbody>
</table>
<hr/>
<h2>附录:相关源码路径</h2>
<table>
<thead><tr>
<th>模块</th>
<th>路径</th>
</tr>
</thead>
<tbody><tr>
<td>车型</td>
<td><code>CarTypes/MagFass2Car.cs</code></td>
</tr>
<tr>
<td>协议</td>
<td><code>Protocol/Fass2Protocol.cs</code><code>Fass2UdpHub.cs</code></td>
</tr>
<tr>
<td>组包</td>
<td><code>Tasking/Fass2TaskBuilder.cs</code></td>
</tr>
<tr>
<td>状态机</td>
<td><code>Tasking/Fass2TaskStateMachine.cs</code></td>
</tr>
<tr>
<td>动作判定</td>
<td><code>Tasking/Fass2ActionResolver.cs</code></td>
</tr>
<tr>
<td>环线 Mission</td>
<td><code>Chained/MagFass2LoopMission.cs</code></td>
</tr>
<tr>
<td>站点字段常量</td>
<td><code>Tasking/Fass2SiteFields.cs</code></td>
</tr>
</tbody>
</table>
<hr/>
<p>*文档随代码演进,若参数或行为有变更,以源码为准。*</p>
</body>
</html>