Skip to content

Commit 6fef9f6

Browse files
authored
Add special case performance optimization for large game piece arrays (#478)
1 parent 3a1a169 commit 6fef9f6

2 files changed

Lines changed: 65 additions & 0 deletions

File tree

src/shared/geometry.ts

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,31 @@ export function grabTranslation2dArray(log: Log, key: string, timestamp: number,
479479
}
480480

481481
export function grabTranslation3dArray(log: Log, key: string, timestamp: number, uuid?: string): AnnotatedPose3d[] {
482+
// Try reading directly from the raw WPILib struct byte array
483+
// Special case to support large arrays of game piece poses (#477 workaround)
484+
let rawData = getOrDefault(log, key, LoggableType.Raw, timestamp, null, uuid);
485+
if (rawData !== null) {
486+
let poses: AnnotatedPose3d[] = [];
487+
let dataView = new DataView(rawData.buffer, rawData.byteOffset, rawData.byteLength);
488+
489+
// A Translation3d WPILib struct is 3 little-endian doubles (24 bytes)
490+
for (let i = 0; i <= rawData.byteLength - 24; i += 24) {
491+
poses.push({
492+
pose: {
493+
translation: [
494+
dataView.getFloat64(i, true), // x
495+
dataView.getFloat64(i + 8, true), // y
496+
dataView.getFloat64(i + 16, true) // z
497+
],
498+
rotation: Rotation3dZero
499+
},
500+
annotation: { is2DSource: false }
501+
});
502+
}
503+
return poses;
504+
}
505+
506+
// Fallback to reading parsed child fields
482507
return indexArray(getOrDefault(log, key + "/length", LoggableType.Number, timestamp, 0, uuid)).reduce(
483508
(array, index) => array.concat(grabTranslation3d(log, key + "/" + index.toString(), timestamp)),
484509
[] as AnnotatedPose3d[]
@@ -551,6 +576,36 @@ export function grabChoreoSampleArray(log: Log, key: string, timestamp: number,
551576
}
552577

553578
export function grabPose3dArray(log: Log, key: string, timestamp: number, uuid?: string): AnnotatedPose3d[] {
579+
// Try reading directly from the raw WPILib struct byte array
580+
// Special case to support large arrays of game piece poses (#477 workaround)
581+
let rawData = getOrDefault(log, key, LoggableType.Raw, timestamp, null, uuid);
582+
if (rawData !== null) {
583+
let poses: AnnotatedPose3d[] = [];
584+
let dataView = new DataView(rawData.buffer, rawData.byteOffset, rawData.byteLength);
585+
586+
// A Pose3d/Transform3d WPILib struct is 7 little-endian doubles (56 bytes)
587+
for (let i = 0; i <= rawData.byteLength - 56; i += 56) {
588+
poses.push({
589+
pose: {
590+
translation: [
591+
dataView.getFloat64(i, true), // x
592+
dataView.getFloat64(i + 8, true), // y
593+
dataView.getFloat64(i + 16, true) // z
594+
],
595+
rotation: [
596+
dataView.getFloat64(i + 24, true), // w
597+
dataView.getFloat64(i + 32, true), // x
598+
dataView.getFloat64(i + 40, true), // y
599+
dataView.getFloat64(i + 48, true) // z
600+
]
601+
},
602+
annotation: { is2DSource: false }
603+
});
604+
}
605+
return poses;
606+
}
607+
608+
// Fallback to reading parsed child fields
554609
return indexArray(getOrDefault(log, key + "/length", LoggableType.Number, timestamp, 0, uuid)).reduce(
555610
(array, index) => array.concat(grabPose3d(log, key + "/" + index.toString(), timestamp)),
556611
[] as AnnotatedPose3d[]

src/shared/log/Log.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -796,6 +796,16 @@ export default class Log {
796796
if (this.fields[key].getType() === LoggableType.Raw) {
797797
this.setGeneratedParent(key);
798798
this.setStructuredType(key, schemaType + (isArray ? "[]" : ""));
799+
800+
if (
801+
(schemaType === "Translation3d" || schemaType === "Pose3d" || schemaType === "Transform3d") &&
802+
value.length > 5000
803+
) {
804+
// Special case: skip full decoding for large arrays of game piece poses (#477 workaround)
805+
return;
806+
}
807+
808+
// Decode data
799809
let decodedData: { data: unknown; schemaTypes: { [key: string]: string } } | null = null;
800810
try {
801811
decodedData = isArray

0 commit comments

Comments
 (0)