(data: ArrayBuffer)
| 744 | * [56-59] f32 velocity_y |
| 745 | */ |
| 746 | export function decodeObstacles(data: ArrayBuffer): DecodedObstacle[] | null { |
| 747 | if (data.byteLength < OBSTACLES_HEADER_SIZE) { |
| 748 | return null; |
| 749 | } |
| 750 | |
| 751 | const view = new DataView(data); |
| 752 | if (view.getUint8(0) !== MSG_OBSTACLES) { |
| 753 | return null; |
| 754 | } |
| 755 | |
| 756 | const count = view.getUint8(1); |
| 757 | const expectedLen = OBSTACLES_HEADER_SIZE + count * OBSTACLE_RECORD_SIZE; |
| 758 | if (data.byteLength < expectedLen) { |
| 759 | return null; |
| 760 | } |
| 761 | |
| 762 | const obstacles: DecodedObstacle[] = []; |
| 763 | for (let i = 0; i < count; i++) { |
| 764 | const offset = OBSTACLES_HEADER_SIZE + i * OBSTACLE_RECORD_SIZE; |
| 765 | obstacles.push({ |
| 766 | trackId: view.getUint32(offset, true), |
| 767 | obstacleClass: view.getUint8(offset + 4), |
| 768 | confidence: view.getUint8(offset + 5), |
| 769 | age: view.getUint16(offset + 6, true), |
| 770 | centroidX: view.getFloat32(offset + 8, true), |
| 771 | centroidY: view.getFloat32(offset + 12, true), |
| 772 | bboxMinX: view.getFloat32(offset + 16, true), |
| 773 | bboxMinY: view.getFloat32(offset + 20, true), |
| 774 | bboxMaxX: view.getFloat32(offset + 24, true), |
| 775 | bboxMaxY: view.getFloat32(offset + 28, true), |
| 776 | cellCount: view.getUint32(offset + 32, true), |
| 777 | area: view.getFloat32(offset + 36, true), |
| 778 | minZ: view.getFloat32(offset + 40, true), |
| 779 | maxZ: view.getFloat32(offset + 44, true), |
| 780 | rotation: view.getFloat32(offset + 48, true), |
| 781 | velocityX: view.getFloat32(offset + 52, true), |
| 782 | velocityY: view.getFloat32(offset + 56, true), |
| 783 | }); |
| 784 | } |
| 785 | |
| 786 | return obstacles; |
| 787 | } |
| 788 | |
| 789 | // ============================================================================ |
| 790 | // Navigation Path Decoding (MSG_PATH = 0x25) |
no test coverage detected