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}]";
}
}