GrabBag/Device/RsLidarDevice/Doc/AngleCoordinateMapping.md
2026-07-11 15:49:14 +08:00

143 lines
2.7 KiB
Markdown
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.

# RSEM4 angle and XYZ formulas
本文只说明 `RsLidarDevice` 中 RSEM4 雷达角度、距离与
`PointCloudCallback` 输出 XYZ 之间的正算和逆算公式。
代码依据:`Src/RsLidarDevice.cpp::fillRsem4Point()`
## 单位约定
- 原始距离分辨率:`1 unit = 0.005 m`
- 公式中的 `distance_m` 单位为米。
- `PointCloudCallback` 输出的 `X/Y/Z` 单位为毫米。
- 代码中的角度单位为 `0.01°`,例如 `1300 = 13.00°`
- 三角函数计算时需要先把 `0.01°` 转成弧度:
```text
angle_rad = angle_deg01 * pi / 18000
```
## 角度定义
水平角:
```text
yaw_deg01 = yawBase_deg01 + yawOffset_deg01[ring / 20]
```
垂直角:
```text
pitch_deg01 = pitchAngle_deg01[ring] + surfacePitchOffset_deg01[surfaceIndex]
```
转换成弧度:
```text
yaw_rad = yaw_deg01 * pi / 18000
pitch_rad = pitch_deg01 * pi / 18000
```
## 正算公式angle + distance -> XYZ
雷达内部先按标准球坐标计算:
```text
x0_m = distance_m * cos(pitch_rad) * cos(yaw_rad)
y0_m = distance_m * cos(pitch_rad) * sin(yaw_rad)
z0_m = distance_m * sin(pitch_rad)
```
再转换成 `PointCloudCallback` 输出坐标:
```text
X_mm = -y0_m * 1000
Y_mm = -z0_m * 1000
Z_mm = x0_m * 1000
```
合并后:
```text
X_mm = -distance_m * cos(pitch_rad) * sin(yaw_rad) * 1000
Y_mm = -distance_m * sin(pitch_rad) * 1000
Z_mm = distance_m * cos(pitch_rad) * cos(yaw_rad) * 1000
```
强度值:
```text
intensity = 原始 intensity
```
## 逆算公式XYZ -> angle + distance
给定 `PointCloudCallback` 输出点:
```text
X_mm = point.x
Y_mm = point.y
Z_mm = point.z
```
距离:
```text
range_mm = sqrt(X_mm * X_mm + Y_mm * Y_mm + Z_mm * Z_mm)
range_m = range_mm / 1000
```
水平角:
```text
yaw_rad = atan2(-X_mm, Z_mm)
yaw_deg = yaw_rad * 180 / pi
```
如果需要归一化到 `[0, 360)`
```text
if yaw_deg < 0:
yaw_deg += 360
```
垂直角:
```text
pitch_rad = asin(-Y_mm / range_mm)
pitch_deg = pitch_rad * 180 / pi
```
转换成代码中的 `0.01°` 单位:
```text
yaw_deg01 = yaw_deg * 100
pitch_deg01 = pitch_deg * 100
```
## 反推原始角度
上面的逆算得到的是已经叠加 DIFOP 标定补偿后的实际出射角。
如果已知当前点的 `ring``surfaceIndex` 和 DIFOP 标定表,则可继续反推:
```text
yawBase_deg01 = yaw_deg01 - yawOffset_deg01[ring / 20]
pitchAngle_deg01[ring] = pitch_deg01 - surfacePitchOffset_deg01[surfaceIndex]
```
如果只拿到 XYZ不知道 `ring``surfaceIndex` 和 DIFOP 标定表,则不能唯一反推原始包里的
`yawAngle``pitchAngle``surfaceId`
## 无效点
当输出点为零点时:
```text
X_mm = 0
Y_mm = 0
Z_mm = 0
```
不能进行角度逆算。零点可能来自距离越界或 `surfaceIndex` 非法。