fix(delta2d): correct measurement packet angle decoding
This commit is contained in:
@@ -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 })
|
||||
|
||||
Reference in New Issue
Block a user