namespace Olei.LidarSensor; /// /// Complete LiDAR data packet (1240 bytes total) /// Contains header (40 bytes) + 150 data blocks (1200 bytes) /// public sealed class LidarDataPacket { /// /// Total packet size in bytes /// public const int PACKET_SIZE = 1240; /// /// Header size in bytes /// public const int HEADER_SIZE = 40; /// /// Number of data blocks per packet /// public const int DATA_BLOCK_COUNT = 150; /// /// Size of each data block in bytes /// public const int DATA_BLOCK_SIZE = 8; /// /// Total size of all data blocks /// public const int DATA_BLOCKS_TOTAL_SIZE = DATA_BLOCK_COUNT * DATA_BLOCK_SIZE; /// /// Packet header information /// public LidarHeader Header { get; set; } /// /// Array of data blocks (150 blocks) /// Using array instead of list for better performance /// public LidarDataBlock[] DataBlocks { get; } /// /// Timestamp when this packet was received /// public DateTime ReceivedTime { get; set; } public LidarDataPacket() { DataBlocks = new LidarDataBlock[DATA_BLOCK_COUNT]; ReceivedTime = DateTime.UtcNow; } /// /// Get all valid data points (where angle is valid) /// public IEnumerable GetValidDataBlocks() { for (int i = 0; i < DATA_BLOCK_COUNT; i++) { if (DataBlocks[i].IsValid) { yield return DataBlocks[i]; } } } /// /// Get count of valid data blocks /// public int GetValidDataBlockCount() { int count = 0; for (int i = 0; i < DATA_BLOCK_COUNT; i++) { if (DataBlocks[i].IsValid) { count++; } } return count; } /// /// Get all valid points as (angle, distance) tuples /// public IEnumerable<(double angle, double distance)> GetValidPoints() { byte distanceScale = Header.DistanceScale; for (int i = 0; i < DATA_BLOCK_COUNT; i++) { if (DataBlocks[i].IsValid) { yield return ( DataBlocks[i].GetAngleDegrees(), DataBlocks[i].GetDistance(distanceScale) ); } } } /// /// Get all valid points in Cartesian coordinates (X, Y) /// public IEnumerable<(double x, double y)> GetValidCartesianPoints() { byte distanceScale = Header.DistanceScale; for (int i = 0; i < DATA_BLOCK_COUNT; i++) { if (DataBlocks[i].IsValid) { yield return ( DataBlocks[i].GetX(distanceScale), DataBlocks[i].GetY(distanceScale) ); } } } /// /// Get summary information about this packet /// public override string ToString() { return $"LidarPacket [Valid: {Header.IsValidFrame}, ValidBlocks: {GetValidDataBlockCount()}/{DATA_BLOCK_COUNT}, " + $"RotationRate: {Header.RotationRate}, HasError: {Header.HasError}, Time: {ReceivedTime:HH:mm:ss.fff}]"; } }