GrabBag/Device/RsLidarDevice/Doc/AngleCoordinateMapping.md

143 lines
2.7 KiB
Markdown
Raw Normal View History

2026-07-11 15:49:14 +08:00
# 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` 非法。