blob: 08b3c13542244348a389ebc3a9c9ba6d164bc72b [file] [log] [blame]
James Kuszmaul5f5e1232020-12-22 20:58:00 -08001// This script provides a basic utility for de-batching the IMUValues
2// message. See imu_plotter.ts for usage.
James Kuszmauldac091f2022-03-22 09:35:06 -07003import {IMUValuesBatch} from 'org_frc971/frc971/wpilib/imu_batch_generated';
James Kuszmaul5f5e1232020-12-22 20:58:00 -08004import {MessageHandler, TimestampedMessage} from 'org_frc971/aos/network/www/aos_plotter';
James Kuszmaul0d7df892021-04-09 22:19:49 -07005import {Point} from 'org_frc971/aos/network/www/plotter';
James Kuszmaul5f5e1232020-12-22 20:58:00 -08006import {Table} from 'org_frc971/aos/network/www/reflection';
James Kuszmauldac091f2022-03-22 09:35:06 -07007import {ByteBuffer} from 'flatbuffers';
8import {Schema} from 'org_frc971/external/com_github_google_flatbuffers/reflection/reflection_generated';
James Kuszmaul5f5e1232020-12-22 20:58:00 -08009
James Kuszmaulac2b6b42021-03-07 22:38:06 -080010const FILTER_WINDOW_SIZE = 100;
11
James Kuszmaul5f5e1232020-12-22 20:58:00 -080012export class ImuMessageHandler extends MessageHandler {
James Kuszmaulac2b6b42021-03-07 22:38:06 -080013 // Calculated magnitude of the measured acceleration from the IMU.
James Kuszmaul0d7df892021-04-09 22:19:49 -070014 private acceleration_magnitudes: Point[] = [];
James Kuszmaul5f5e1232020-12-22 20:58:00 -080015 constructor(private readonly schema: Schema) {
16 super(schema);
17 }
James Kuszmauldac091f2022-03-22 09:35:06 -070018 private readScalar(table: Table, fieldName: string): number|BigInt|null {
James Kuszmaulac2b6b42021-03-07 22:38:06 -080019 return this.parser.readScalar(table, fieldName);
20 }
James Kuszmaul5f5e1232020-12-22 20:58:00 -080021 addMessage(data: Uint8Array, time: number): void {
James Kuszmauldac091f2022-03-22 09:35:06 -070022 const batch = IMUValuesBatch.getRootAsIMUValuesBatch(new ByteBuffer(data));
James Kuszmaul5f5e1232020-12-22 20:58:00 -080023 for (let ii = 0; ii < batch.readingsLength(); ++ii) {
24 const message = batch.readings(ii);
25 const table = Table.getNamedTable(
James Kuszmauldac091f2022-03-22 09:35:06 -070026 message.bb, this.schema, 'frc971.IMUValues', message.bb_pos);
James Kuszmaul5f5e1232020-12-22 20:58:00 -080027 if (this.parser.readScalar(table, "monotonic_timestamp_ns") == null) {
28 console.log('Ignoring unpopulated IMU values: ');
29 console.log(this.parser.toObject(table));
30 continue;
31 }
James Kuszmauldac091f2022-03-22 09:35:06 -070032 const time = Number(message.monotonicTimestampNs()) * 1e-9;
James Kuszmaulac2b6b42021-03-07 22:38:06 -080033 this.messages.push(new TimestampedMessage(table, time));
James Kuszmaul0d7df892021-04-09 22:19:49 -070034 this.acceleration_magnitudes.push(new Point(
35 time,
36 Math.hypot(
37 message.accelerometerX(), message.accelerometerY(),
38 message.accelerometerZ())));
James Kuszmaulac2b6b42021-03-07 22:38:06 -080039 }
40 }
41
42 // Computes a moving average for a given input, using a basic window centered
43 // on each value.
James Kuszmaul0d7df892021-04-09 22:19:49 -070044 private movingAverageCentered(input: Point[]): Point[] {
45 const num_measurements = input.length;
46 const filtered_measurements = [];
James Kuszmaulac2b6b42021-03-07 22:38:06 -080047 for (let ii = 0; ii < num_measurements; ++ii) {
48 let sum = 0;
49 let count = 0;
50 for (let jj = Math.max(0, Math.ceil(ii - FILTER_WINDOW_SIZE / 2));
51 jj < Math.min(num_measurements, ii + FILTER_WINDOW_SIZE / 2); ++jj) {
James Kuszmaul0d7df892021-04-09 22:19:49 -070052 sum += input[jj].y;
James Kuszmaulac2b6b42021-03-07 22:38:06 -080053 ++count;
54 }
James Kuszmaul0d7df892021-04-09 22:19:49 -070055 filtered_measurements.push(new Point(input[ii].x, sum / count));
James Kuszmaulac2b6b42021-03-07 22:38:06 -080056 }
James Kuszmaul0d7df892021-04-09 22:19:49 -070057 return filtered_measurements;
James Kuszmaulac2b6b42021-03-07 22:38:06 -080058 }
59
James Kuszmaul0d7df892021-04-09 22:19:49 -070060 getField(field: string[]): Point[] {
James Kuszmaulac2b6b42021-03-07 22:38:06 -080061 // Any requested input that ends with "_filtered" will get a moving average
62 // applied to the original field.
63 const filtered_suffix = "_filtered";
64 if (field[0] == "acceleration_magnitude") {
James Kuszmaul0d7df892021-04-09 22:19:49 -070065 return this.acceleration_magnitudes;
James Kuszmaulac2b6b42021-03-07 22:38:06 -080066 } else if (field[0].endsWith(filtered_suffix)) {
67 return this.movingAverageCentered(this.getField(
68 [field[0].slice(0, field[0].length - filtered_suffix.length)]));
69 } else {
70 return super.getField(field);
James Kuszmaul5f5e1232020-12-22 20:58:00 -080071 }
72 }
73}