fix(delta2d): correct measurement packet angle decoding

This commit is contained in:
Julien Denizot
2026-10-03 17:45:48 +02:00
parent 7fef98aa9f
commit fee3ac8598
@@ -353,54 +353,56 @@ impl Delta2DPacketReader {
return Ok(LidarScan { points });
}
// Byte 0: Motor speed indicator (ignored)
// Bytes 1-2: Offset angle (angle increment between points) (BE) * 0.01 degrees
// Bytes 3-4: Start angle (BE) * 0.01 degrees
let offset_angle_raw = ((payload[1] as u16) << 8) | (payload[2] as u16);
// Byte 0: Motor speed indicator
// Bytes 1-2: Offset angle field
// Bytes 3-4: Start angle (BE), 0.01 degree units
let _offset_angle_raw = ((payload[1] as u16) << 8) | (payload[2] as u16);
let start_angle_raw = ((payload[3] as u16) << 8) | (payload[4] as u16);
// Convert offset angle to degrees (angle increment between consecutive points)
let angle_increment_deg = offset_angle_raw as f32 * 0.01;
let start_angle_deg = start_angle_raw as f32 * 0.01;
// Parse measurement points (3 bytes each)
let mut i = 5;
let mut point_index = 0;
// Each sample is:
// quality: 1 byte
// distance: 2 bytes
let sample_count = (payload.len() - 5) / 3;
if sample_count == 0 {
return Ok(LidarScan { points });
}
// Delta-2D divides one revolution into 16 sectors.
// Each packet represents one sector (~22.5 degrees).
let angle_increment_deg = 360.0 / (16.0 * sample_count as f32);
for point_index in 0..sample_count {
let i = 5 + point_index * 3;
while i + 3 <= payload.len() {
let quality = payload[i];
let distance_raw = ((payload[i + 1] as u16) << 8) | (payload[i + 2] as u16);
// Convert to physical units
// Angle: start_angle + (point_index * angle_increment)
// Distance: raw * 0.25mm = raw * 0.00025m
let angle_deg =
(start_angle_raw as f32 * 0.01) + (point_index as f32 * angle_increment_deg);
(start_angle_deg + point_index as f32 * angle_increment_deg).rem_euclid(360.0);
let raw_angle_rad = angle_deg.to_radians();
let distance_m = distance_raw as f32 * 0.00025;
// Apply configurable transform (identity = no change)
let mut angle_rad = self.angle_transform.apply(raw_angle_rad);
// Normalize to [0, 2π) for consistency
while angle_rad < 0.0 {
angle_rad += TAU;
}
while angle_rad >= TAU {
angle_rad -= TAU;
}
// Only add valid points (distance > 0, quality > 0)
// Also validate angle range
if distance_raw > 0 && quality > 0 && (0.0..=360.0).contains(&angle_deg) {
if distance_raw > 0 && quality > 0 {
points.push(LidarPoint {
angle: angle_rad,
distance: distance_m,
quality,
});
}
i += 3;
point_index += 1;
}
Ok(LidarScan { points })