389 lines
20 KiB
Markdown
389 lines
20 KiB
Markdown
# Detour 定位接口信息确认(源码答复)
|
||
|
||
用途:答复控制程序(`MultiWheelC` / `StateEstimation`)使用定位结果所必需的接口语义。
|
||
依据:本仓库 `DetourCore` 源码(`Location.cs`、`TightCoupler.cs`、`Frame.cs`、`LidarOdometry.cs`、`LidarMap.cs`、`WebAPI.cs`、`G.cs`)。
|
||
仓库内**没有**名为 `getCartLocation()` 的函数;控制侧该调用对应 Detour 的两类对外位姿出口。下文按字段对齐后统一说明。
|
||
|
||
---
|
||
|
||
## 对外位姿出口(先对齐接口)
|
||
|
||
控制程序看到的 `x / y / theta / tick / l_step`,来自下面之一(或对它们的封装)。字段名在源码里是 `th`,不是 `theta`。
|
||
|
||
| 出口 | 入口 | 字段 | `tick` 的真实来源 |
|
||
|---|---|---|---|
|
||
| HTTP `GET /getPos` | `CartLocation.FormatPosition()` | JSON:`x, y, th, l_step, tick`,异常时多 `error` | `tick = CartLocation.st_time`(观测时刻) |
|
||
| 共享对象 `DetourPos{shareObjectTag}` | `TightCoupler.CommitLocation` 每次提交后 `Post` | 二进制:`x, y, th, tick, l_step, error` | `tick = DateTime.Now.Ticks`(提交/推送时刻) |
|
||
|
||
默认 HTTP 端口:`Configuration.conf.guru.DetourPort`,默认 `4321`。
|
||
`shareObjectTag` 必须与控制侧 Clumsy 的 soTag 一致。
|
||
|
||
两种出口的 `x/y` 都已经过:
|
||
|
||
```
|
||
x_out = 内部x / guru.inputScale + guru.biasX
|
||
y_out = 内部y / guru.inputScale + guru.biasY
|
||
```
|
||
|
||
默认 `inputScale = 1`、`biasX = biasY = 0`,因此默认单位就是内部单位(毫米)。
|
||
`th` / `l_step` 不做缩放。
|
||
|
||
---
|
||
|
||
## 1. `getCartLocation()` 字段定义
|
||
|
||
### 1.1 各字段含义
|
||
|
||
| 字段 | 源码名 | 含义 |
|
||
|---|---|---|
|
||
| `x` | `CartLocation.x` | 车体原点在**当前地图坐标系**中的 X。已从传感器坐标系经安装外参反变换到车体中心(`TightCoupler.CommitLocation` 里 `ReverseTransform(传感器位姿, 组件安装位姿)`)。 |
|
||
| `y` | `CartLocation.y` | 同上,Y。 |
|
||
| `theta` | `CartLocation.th` | 车体航向。`0°` 朝向地图 `+X`,逆时针为正(内部用 `cos(th)` / `sin(th)` 画朝向)。 |
|
||
| `tick` | 见上表 | **不是**统一的一种时间。HTTP 是观测时间 `st_time`;DObject 是提交瞬间的 `DateTime.Now.Ticks`。控制侧必须先确认自己走的是哪条通道。 |
|
||
| `l_step` | `Frame.l_step` | **到已标注(labeled)关键帧的图上步数**,用来表达“离可信锚点有多远”,**不是**优化迭代次数,也不是匹配分数。注释原文:`steps to labeled keyframe`。 |
|
||
|
||
### 1.2 单位、正方向、坐标系
|
||
|
||
- **内部单位**:`x`、`y` 为毫米。UI 直接按 `mm` 显示。
|
||
- **对外单位**:默认仍是毫米;只有改了 `guru.inputScale`(例如设为 `1000` 输出米)才会变。
|
||
- **角度单位**:度。
|
||
- **坐标系**:当前加载的 SLAM 地图坐标系。原点由建图/标注关键帧决定,不是 GNSS 或车体启动点。
|
||
- **车体姿态**:输出的是**车体原点**,不是雷达原点。雷达/相机安装位姿在 `layout.components` 的 `x,y,th` 里。
|
||
- **右手平面**:`+X` 为航向 0,`+Y` 为航向 +90°。
|
||
|
||
### 1.3 `theta` 取值范围
|
||
|
||
**不是严格的 `[-180°, 180°]`。**
|
||
|
||
`LessMath.normalizeTh` 只在绝对值 ≥ 360 时按 360° 回绕,`(-360, 360)` 内原样返回。因此对外可能看到 `200`、`-270` 这类值。控制程序若假设 `[-180, 180]` 或 `[0, 360)`,应自己归一化。内部比较角度用 `LessMath.thDiff`,会按最短弧处理。
|
||
|
||
### 1.4 一次调用的字段是否同一帧
|
||
|
||
**是。** 一次读取对应同一个 `CartLocation` 对象上的 `x/y/th/l_step/st_time`。
|
||
`getPos` 先用当前 `latest` 判断 Timeout/Unstable,再序列化;若这两步之间恰好发生新提交,状态字和位姿可能差一帧,但单次 JSON 里的数值字段仍来自同一个对象。
|
||
|
||
---
|
||
|
||
## 2. `tick` 的准确含义(优先)
|
||
|
||
### 2.1 它是什么时刻
|
||
|
||
分通道:
|
||
|
||
**HTTP `/getPos` 的 `tick` = `st_time`**
|
||
|
||
- `st_time` 在 `Frame` 上的注释是:传感器数据**到达 Detour 时**由 `G.watch` 打的时间,不是激光头硬件曝光时刻,也不是 HTTP 返回时刻。
|
||
- 激光采集线程会按扫描周期做轻微平滑,并加上 `time_bias_ms`。
|
||
- 里程计把 `frame.st_time` 原样交给 `TightCoupler.CommitLocation`,再写入 `CartLocation.st_time`。
|
||
- 因此:`tick` ≈ **该位姿所对应的那帧观测到达时刻**。SLAM 计算发生在这之后,接口返回更晚。
|
||
|
||
**DObject `DetourPos` 的 `tick` = `DateTime.Now.Ticks`**
|
||
|
||
- 这是 **TightCoupler 提交并推送的本地时刻**,100 纳秒为单位,从公元 1 年 1 月 1 日起算(.NET `DateTime.Ticks`)。
|
||
- 它**不是**传感器采集时刻,也**不是** Unix epoch。
|
||
- 受本机本地时钟、时区、校时影响,必要时可能回跳。
|
||
|
||
### 2.2 单位、频率、单调、回绕
|
||
|
||
| 项目 | HTTP `tick`(`st_time`) | DObject `tick`(`DateTime.Now.Ticks`) |
|
||
|---|---|---|
|
||
| 单位 | 毫秒 | 100 ns(1 ms = 10000) |
|
||
| 时钟 | 进程启动时锚定一次 UTC,之后用 `Stopwatch` 单调累加:`ElapsedTicks*1000/Frequency + stMillis` | 本机本地 `DateTime.Now` |
|
||
| 更新频率 | 随传感器/融合提交,通常接近雷达帧率(常见 10–20 Hz,取决于设备 `timeBudget`) | 每次 `CommitLocation` 成功推一次 |
|
||
| 单调 | 进程内单调递增(不受事后改系统时间影响) | 一般递增;改系统时间或 DST 可能回跳 |
|
||
| 回绕 | `long` 毫秒,实际不会回绕 | `long` ticks,实际不会回绕 |
|
||
| 进程重启 | 重新锚定当前 UTC,**不会从 0 开始**,但与重启前不保证连续 | 继续跟本机时钟,与进程无关 |
|
||
|
||
`G.watch.TimeStampMillis` **不是** Unix 毫秒(1970),而是从公元 1 年起算的 UTC 毫秒,再加上启动后的单调流逝。
|
||
|
||
### 2.3 多车能否用 `tick` 对齐
|
||
|
||
**不能当作已同步的多车时钟。**
|
||
|
||
- 各车各自启动 `G.watch`,没有 PTP/NTP 协议,也没有跨车时间服务。
|
||
- HTTP `tick`:若各车系统 UTC 在启动时大致同步,数值会接近“同一套绝对时间”,但仍有启动锚定误差和各车处理延迟,**不能直接当多车位姿对齐的主时钟**。
|
||
- DObject `tick`:本地时间 ticks,跨时区会直接错开,更不适合多车对齐。
|
||
- 进程重启、暂停(`G.paused`)、提交失败都会造成时间空洞。
|
||
|
||
控制侧建议:单车内部用 `tick` 做延迟估计和短时预测;多车对齐应使用外部统一时钟,或只把 Detour `tick` 当相对时间。
|
||
|
||
---
|
||
|
||
## 3. 定位延迟与更新方式
|
||
|
||
### 3.1 输出位姿比真实运动滞后多少
|
||
|
||
源码**没有**标定“官方延迟 xx ms”。能确定的是延迟结构:
|
||
|
||
```
|
||
真实运动 → 雷达扫描/到达(st_time) → 里程计配准 → TightCoupler 融合 → 写入 CartLocation.latest → 接口读到缓存
|
||
```
|
||
|
||
经验上由源码阈值约束:
|
||
|
||
- 激光一圈通常几十毫秒(`Lidar2DStat.timeBudget`)。
|
||
- TightCoupler 常用窗口 `TCtimeWndSz = 150 ms`,上限 `TCtimeWndLimit = 700 ms`。
|
||
- `LidarOdometry` 把 `reg_ms > 200` 记为 `bad perf`。
|
||
- `/getPos` 若 `now - st_time > 500 ms` 打 `Timeout`。
|
||
|
||
因此正常运行时,**从观测到可读位姿大约是 1 帧雷达周期 + 配准/融合,常见几十到两百毫秒;超过 500 ms 会被 HTTP 接口判超时。** 这是实现上的门槛,不是出厂标定值。
|
||
|
||
### 3.2 `getCartLocation()` 是否返回最近一次缓存
|
||
|
||
**是。**
|
||
|
||
- `CartLocation.latest` 是全局缓存。
|
||
- 只有 `TightCoupler.CommitLocation` 成功后才会替换(取 `history` 中 `st_time` 最新的一帧)。
|
||
- `/getPos` 只读缓存,不触发新的 SLAM 计算。
|
||
- 配准失败、`CommitLocation` 返回 `null`(`bad variance` / `bad trace`)、或 `G.paused` 时,缓存停在上一帧。
|
||
|
||
### 3.3 原地自转时频率/延迟是否明显变化
|
||
|
||
**轮询频率不变,有效更新和延迟会变差。**
|
||
|
||
- 接口仍按调用方频率读同一缓存。
|
||
- 原地旋转时二维扫描重叠变差,帧间分、相位锁分容易掉,`allowCommit` 更常失败,缓存更容易停住。
|
||
- 配准变慢时单帧 `reg_ms` 上升;失败后 `l_step` 被加大(见第 4 节),看起来像“转的时候定位变钝”。
|
||
- 源码没有“自转专用降频”。
|
||
|
||
控制侧:自转短时预测应假设**有效位姿更新可能变稀、变老**,不要假设 `tick` 仍按雷达周期前进。
|
||
|
||
---
|
||
|
||
## 4. `l_step` 的含义(优先)
|
||
|
||
### 4.1 它是什么
|
||
|
||
**定位质量的图距离,不是优化迭代次数,也不是匹配状态枚举。**
|
||
|
||
定义:当前位姿/关键帧沿约束图走到**已标注关键帧**还要几步。
|
||
|
||
- `0`:本身就是标注帧(`labeledXY` / `labeledTh`),或刚被标成锚点。
|
||
- `1`:刚和地图/标注帧配准成功(`LidarMap` 成功后会把 `compared.l_step = 1`)。
|
||
- 正常递推:新关键帧 `l_step = 旧关键帧.l_step + lstepInc`。
|
||
- TightCoupler 提交时:有参考关键帧则 `reference.l_step + 1`;没有则 `latest.l_step + 3`。
|
||
- `9999`:未定位、手动设位、或与标注图断开。这是 `Frame` / 初始 `CartLocation` 的默认值。
|
||
|
||
**越小越好、越可信。**
|
||
`AIImplementationNote.md` 里“越小越不确定”与源码相反,不要采用。
|
||
|
||
内部用途包括:
|
||
|
||
- TightCoupler 边权:`l_step > 10 → 1`,`> 5 → 2`,`> 2 → 3`,否则 `4`;标注帧权 1000。
|
||
- 图优化用 `1/(l_step+0.01)` 当权。
|
||
- `l_step` 大时 `LidarMap` 更容易走全局配准(`forceGRegStep`、`GregThresK * l_step`)。
|
||
- `l_step > 1000` 且孤立的关键帧可被删掉。
|
||
|
||
源码 TODO 也写过:希望将来“去掉 `l_step`,改用误差圆”。当前对外接口仍是这个整数。
|
||
|
||
### 4.2 为什么原地自转会从 2~4 升到几十、上百
|
||
|
||
自转本身不会改公式,但会让 **`lstepInc` 连续被惩罚**,再在切关键帧时一次性加到 `l_step` 上。
|
||
|
||
`LidarOdometry` 里常见加项:
|
||
|
||
| 条件 | `lstepInc` 增量 |
|
||
|---|---|
|
||
| 帧间隔过大 | `+3`~`+20` |
|
||
| 时间落后 > 1 s | 可到 `+1000` 量级并重启局部图 |
|
||
| 有效点太少 | `+3` |
|
||
| 掩膜后点过少 | `+10` |
|
||
| 帧间序贯配准失败 | `+5` |
|
||
| 局部里程计分过低 | `+15` |
|
||
| 历史分偏低 | `+1`~`+15` |
|
||
| 局部图重启 / 相位锁差 | `+2` |
|
||
| 上一帧能提交、这一帧不能 | `+100` |
|
||
| 离开 hard 区域 | 默认再 `+20` |
|
||
|
||
原地自转时典型连锁是:旋转导致重叠变差 → 分数掉 → `lstepInc` 累加 → 因“新点变多 / 超时 / restart”切关键帧 → `新 l_step = 旧值 + lstepInc`。
|
||
若此时地图匹配也失败,TightCoupler 按 `latest.l_step + 3` 继续推高。
|
||
所以 2~4 很快可以变成几十,失败恢复前看到上百是符合实现的。
|
||
|
||
匹配一旦重新成功,关键帧会被改回 `l_step = 1`,输出也会掉下来。
|
||
|
||
### 4.3 有没有官方阈值
|
||
|
||
**没有写给控制程序的官方阈值表。** 下面是源码内部实际在用的分档,可作控制侧初值,现场仍要按地图和雷达标定。
|
||
|
||
| `l_step` | 源码含义 | 给控制程序的建议 |
|
||
|---|---|---|
|
||
| `0` | 标注锚点 | 最可信 |
|
||
| `1`~`2` | 刚贴上地图 / 离锚点很近 | **正常,接受** |
|
||
| `3`~`5` | TightCoupler 已降权 | 可用,开始警惕跳变 |
|
||
| `6`~`10` | 权更低;地图更倾向全局配准 | **退化,降低信任 / 收紧预测** |
|
||
| `11`~`98` | 最低权;曾从不稳定区回到 `2` 时会打工作区快照 | **明显退化,不宜做精细控制** |
|
||
| `≥ 99` | TightCoupler 允许关键帧被推得更狠 | 按不可靠处理 |
|
||
| `≥ 1000` | 孤立帧可删 | 基本断开 |
|
||
| `9999` | 未定位 / 手动设位 / 断开 | **不可用,应安全停止或等待重定位** |
|
||
|
||
Detour 自己判断“车是否静止可做全局重定位”时用:`l_step > 2` 且 TightCoupler 速度估计很小。这是内部策略,不是对外状态机。
|
||
|
||
---
|
||
|
||
## 5. 坐标跳变与重定位行为(优先)
|
||
|
||
### 5.1 重定位、回环、失败恢复后,`x/y/theta` 会不会永久跳变
|
||
|
||
**会。跳变是设计行为,不是毛刺。**
|
||
|
||
会改当前输出的情况:
|
||
|
||
1. **地图配准成功**:`LidarMap` 把当前关键帧改到匹配位姿,并 `l_step = 1`,再交给 TightCoupler。下一帧 `CartLocation` 跟着新参考走,表现为一次台阶。
|
||
2. **全局重定位**(`/relocalize` 或 UI Relocalize):定位器进入 `relocalizing`,按全图关键帧搜索(`source = 9`)。第一次更好的匹配会 `TightCoupler.Reset`,位姿被拉到地图上,通常是大幅度永久跳变。
|
||
3. **回环 + `GraphOptimizer`**:关键帧 `x/y/th` 被就地改写。当前参考帧若被挪动,后续融合位姿跟着变。优化有动量平滑,但仍可能出现肉眼可见的台阶。
|
||
4. **手动 `/setLocation`**:直接改 `CartLocation.latest` 并重置融合窗口。
|
||
5. **匹配长期失败后突然恢复**:从里程计漂过的位置一下子贴回地图,跳变幅度等于累计漂移。
|
||
|
||
没有“只在内部跳、对外插值抹平”的保证。控制程序必须自己做跳变连续化或拒绝。
|
||
|
||
### 5.2 跳变后还在原来的地图坐标系吗
|
||
|
||
**同一张已加载地图内:是。**
|
||
跳的是车在这张图里的估计,不是换了一套轴。
|
||
|
||
会换坐标系的只有:换图(`/loadMap`)、`Remapper`(GNSS/外参映射)、或手动把车标到另一个锚点。这些不是普通重定位。
|
||
|
||
### 5.3 有没有“正在重定位 / 定位丢失 / 地图坐标调整”标志
|
||
|
||
**定位结果包里没有这些标志。**
|
||
|
||
内部有、但**不随 `getPos` / `DetourPos` 下发**:
|
||
|
||
| 内部量 | 作用 | 是否对外 |
|
||
|---|---|---|
|
||
| `Locator.relocalizing` / `relocalized` | 地图层正在/已经全局搜 | 否 |
|
||
| `G.IsSettingPosition` | 正在手动设位 | 否(`/getStat` 的 `globalStat` 里能看到) |
|
||
| `G.paused` | 定位暂停 | 否(同上,或调 `/pause` `/resume`) |
|
||
| `CartLocation.unstable` | 本帧掩膜过狠、场景不稳定 | **仅 HTTP**:`error = "Unstable"`。DObject 当前推送的 `error` 被写成空串 |
|
||
| `l_step` 升到很大 / `9999` | 实际的“丢了” | 是,但这是间接指标 |
|
||
| 图优化改关键帧 | “地图坐标调整” | 无单独标志 |
|
||
|
||
HTTP `/getPos` 仅有的显式错误:
|
||
|
||
- `"Timeout"`:`st_time` 已超过 500 ms
|
||
- `"Unstable"`:`latest.unstable == true`
|
||
|
||
没有 `"Relocalizing"`、`"Lost"`、`"MapAdjusted"`。
|
||
`/getStat` 可拉到各模块 `StatusMember`(雷达间隔、里程计状态、TC 状态等),但不是每帧位姿附属字段,也不适合当硬实时互锁。
|
||
|
||
控制侧应自己构造状态:
|
||
|
||
- **疑似丢失**:`error` 为 Timeout/Unstable,或 `l_step ≥ 99`,或 `tick` 长期不涨。
|
||
- **疑似重定位/回环跳变**:相邻两帧 `x/y/th` 突变,同时 `l_step` 突然掉回 1~2。
|
||
- **地图在拧**:跳变较缓、持续多帧,且 `l_step` 并不爆掉。
|
||
|
||
---
|
||
|
||
## 6. 可用的定位质量接口(优先)
|
||
|
||
### 6.1 除 `l_step` 外还能拿到什么
|
||
|
||
**位姿包几乎只有 `l_step` + HTTP 的 `error`。**
|
||
|
||
| 信息 | 有没有 | 说明 |
|
||
|---|---|---|
|
||
| 匹配得分 | 对控制程序:无 | 在 `LidarOdometry` / `LidarMap` 内部(`score`、`phaselocker_score`),不下发 |
|
||
| 协方差 | 对控制程序:无 | `Frame.errXX/errXY/errYY` 已预留,**未填进 `/getPos` 或 `DetourLocation`** |
|
||
| 置信度 | 间接 | 就是 `l_step`;源码 TODO 想换成误差圆,尚未做 |
|
||
| 定位状态 | 很弱 | HTTP:`Timeout` / `Unstable`;DObject:`error` 目前恒为空 |
|
||
| 错误码 | 无枚举 | 只有上述字符串 |
|
||
| 系统状态 | 有,但是慢接口 | `GET /getStat` → 布局/里程计/定位器/TC/GO/`G.paused`/`G.IsSettingPosition` |
|
||
|
||
因此控制程序**不能**指望每帧拿到匹配分或协方差。
|
||
|
||
### 6.2 Detour 实际用什么条件接受一帧(可当作官方内部规则)
|
||
|
||
源码里“接受并提交”的条件是分层的,没有单独的对外规范文档:
|
||
|
||
1. **里程计层**(`LidarOdometry.updateLocation`)
|
||
- 分数过低会把 `strength` 压下去,甚至不把 `reference` 挂上。
|
||
- 掩膜过狠 → `unstable = true`。
|
||
- 点太少、序贯/局部配准失败 → 不切健康关键帧,并加大 `lstepInc`。
|
||
2. **融合层**(`TightCoupler.CommitLocation`)
|
||
- 传感器处于 `bad variance` / `bad trace` → 直接丢弃,返回 `null`。
|
||
- 丢弃后该源会被禁一段时间(约 1~2 s)。
|
||
3. **地图层**(`LidarMap`)
|
||
- `result.score < ScoreThres` 丢弃。
|
||
- 相对已有位姿的 `xy/th` 偏差超过按 `l_step` 放大的门限则丢弃(防止乱跳)。
|
||
- 落到无效区域丢弃。
|
||
4. **HTTP 出口**
|
||
- 缓存超过 500 ms → `Timeout`。
|
||
- `unstable` → `Unstable`。
|
||
|
||
### 6.3 建议控制程序如何接受/拒绝一帧
|
||
|
||
源码没有写给 `MultiWheelC` 的官方判据。按上面的内部规则,建议:
|
||
|
||
**接受(正常闭环)**
|
||
|
||
- HTTP:无 `error`(DObject:至少 `tick` 在前进)。
|
||
- `l_step ≤ 5`。
|
||
- `tick` 新鲜(HTTP:`now - tick < 300 ms` 较稳妥;DObject:换算成 ms 后同样看提交间隔)。
|
||
- 相对上一接受帧:位移/转角不超过本底盘短周期能达到的上限。
|
||
|
||
**降级(短时预测、降低增益、禁止精细对位)**
|
||
|
||
- `6 ≤ l_step ≤ 10`,或偶发 Timeout 后立刻恢复。
|
||
- 原地自转期间 `l_step` 爬升但 `tick` 仍在更新。
|
||
|
||
**拒绝并安全停止 / 等待**
|
||
|
||
- `error == "Timeout"` 持续,或 `error == "Unstable"`。
|
||
- `l_step ≥ 99`(含 `9999`)。
|
||
- 单帧出现与运动学不符的永久台阶(尤其伴随 `l_step` 从很大突然回到 1):先当重定位跳变,做连续化或刹停,不要直接当编码器。
|
||
|
||
**不要做的事**
|
||
|
||
- 不要用 `l_step` 当 ICP 迭代次数或“正在计算中”。
|
||
- 不要假设 `theta ∈ [-180, 180]`。
|
||
- 不要用 `tick` 做多车时间同步主时钟。
|
||
- 不要假设 DObject 的 `error` 会带 Timeout/Unstable(当前实现是空的)。
|
||
|
||
---
|
||
|
||
## 对 `StateEstimation` 的直接含义
|
||
|
||
清单里最优先的 2 / 4 / 5 / 6,对应控制侧应这样定:
|
||
|
||
1. **时间同步**
|
||
- 先确认 `getCartLocation` 走 HTTP 还是 `DetourPos`。两条通道的 `tick` **单位和语义都不同**。
|
||
- 单车:用 `tick` 估延迟、做自转短时预测。
|
||
- 多车:另选同步时钟。
|
||
|
||
2. **自转短时预测**
|
||
- 自转时有效更新可能变稀,`l_step` 会从个位数爬到几十上百。
|
||
- 这是质量变差,不是接口卡死。预测窗口应随 `tick` 变老、`l_step` 变大而缩短。
|
||
|
||
3. **跳变连续化**
|
||
- 重定位、回环、失败恢复都会造成**同地图下的永久台阶**。
|
||
- 没有“正在改图”标志;用位姿差分 + `l_step` 回落来识别。
|
||
|
||
4. **安全停止**
|
||
- 硬条件:`Timeout` / `Unstable` / `l_step ≥ 99` / `tick` 停更。
|
||
- `l_step` 建议按 `≤5` 正常、`6–10` 退化、`>10` 不可用于精细控制。
|
||
|
||
---
|
||
|
||
## 源码锚点
|
||
|
||
| 主题 | 位置 |
|
||
|---|---|
|
||
| 对外 JSON / Timeout / Unstable | `DetourCore/Location.cs`:`ConstructRet`、`FormatPosition` |
|
||
| HTTP 路由 | `DetourCore/WebAPI.cs`:`/getPos`、`/setLocation`、`/relocalize`、`/getStat` |
|
||
| DObject 推送与 `tick=DateTime.Now.Ticks` | `DetourCore/Algorithms/TightCoupler.cs`:`DetourLocation`、`CommitLocation` |
|
||
| `l_step` 定义 | `DetourCore/Types/Frame.cs` |
|
||
| 车体中心变换、提交缓存 | `TightCoupler.CommitLocation` |
|
||
| 时钟 | `DetourCore/G.cs`:`DetourWatch.TimeStampMillis` |
|
||
| 角度回绕 | `DetourCore/LessMath.cs`:`normalizeTh` |
|
||
| 自转时 `l_step` 被加大 | `DetourCore/Algorithms/LidarOdometry.cs`(`lstepInc`) |
|
||
| 匹配成功后的位姿跳变 | `DetourCore/LocatorTypes/LidarMap.cs`(loop / relocalize) |
|
||
| 回环拧图 | `DetourCore/Algorithms/GraphOptimizer.cs` |
|
||
| 全局重定位入口 | `DetourCore/DetourLib.cs`:`Relocalize()` |
|
||
| 单位缩放 | `DetourCore/Configuration.cs`:`GuruOptions.inputScale / biasX / biasY` |
|
||
|
||
---
|
||
|
||
## 修订记录
|
||
|
||
- 2026-08-24:按当前 Detour 源码逐条答复原《Detour 信息确认清单》。
|