blob: 8193c29393555ea21f635f9dad36e0836378b3f5 [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.
3import * as configuration from 'org_frc971/aos/configuration_generated';
4import * as imu from 'org_frc971/frc971/wpilib/imu_batch_generated';
5import {MessageHandler, TimestampedMessage} from 'org_frc971/aos/network/www/aos_plotter';
6import {Table} from 'org_frc971/aos/network/www/reflection';
7import {ByteBuffer} from 'org_frc971/external/com_github_google_flatbuffers/ts/byte-buffer';
8
9import Schema = configuration.reflection.Schema;
10import IMUValuesBatch = imu.frc971.IMUValuesBatch;
11import IMUValues = imu.frc971.IMUValues;
12
James Kuszmaulac2b6b42021-03-07 22:38:06 -080013const FILTER_WINDOW_SIZE = 100;
14
James Kuszmaul5f5e1232020-12-22 20:58:00 -080015export class ImuMessageHandler extends MessageHandler {
James Kuszmaulac2b6b42021-03-07 22:38:06 -080016 // Calculated magnitude of the measured acceleration from the IMU.
17 private acceleration_magnitudes: number[] = [];
James Kuszmaul5f5e1232020-12-22 20:58:00 -080018 constructor(private readonly schema: Schema) {
19 super(schema);
20 }
James Kuszmaulac2b6b42021-03-07 22:38:06 -080021 private readScalar(table: Table, fieldName: string): number {
22 return this.parser.readScalar(table, fieldName);
23 }
James Kuszmaul5f5e1232020-12-22 20:58:00 -080024 addMessage(data: Uint8Array, time: number): void {
25 const batch = IMUValuesBatch.getRootAsIMUValuesBatch(
26 new ByteBuffer(data) as unknown as flatbuffers.ByteBuffer);
27 for (let ii = 0; ii < batch.readingsLength(); ++ii) {
28 const message = batch.readings(ii);
29 const table = Table.getNamedTable(
30 message.bb as unknown as ByteBuffer, this.schema, 'frc971.IMUValues',
31 message.bb_pos);
32 if (this.parser.readScalar(table, "monotonic_timestamp_ns") == null) {
33 console.log('Ignoring unpopulated IMU values: ');
34 console.log(this.parser.toObject(table));
35 continue;
36 }
James Kuszmaulac2b6b42021-03-07 22:38:06 -080037 const time = message.monotonicTimestampNs().toFloat64() * 1e-9;
38 this.messages.push(new TimestampedMessage(table, time));
39 this.acceleration_magnitudes.push(time);
40 this.acceleration_magnitudes.push(Math.hypot(
41 message.accelerometerX(), message.accelerometerY(),
42 message.accelerometerZ()));
43 }
44 }
45
46 // Computes a moving average for a given input, using a basic window centered
47 // on each value.
48 private movingAverageCentered(input: Float32Array): Float32Array {
49 const num_measurements = input.length / 2;
50 const filtered_measurements = new Float32Array(input);
51 for (let ii = 0; ii < num_measurements; ++ii) {
52 let sum = 0;
53 let count = 0;
54 for (let jj = Math.max(0, Math.ceil(ii - FILTER_WINDOW_SIZE / 2));
55 jj < Math.min(num_measurements, ii + FILTER_WINDOW_SIZE / 2); ++jj) {
56 sum += input[jj * 2 + 1];
57 ++count;
58 }
59 filtered_measurements[ii * 2 + 1] = sum / count;
60 }
61 return new Float32Array(filtered_measurements);
62 }
63
64 getField(field: string[]): Float32Array {
65 // Any requested input that ends with "_filtered" will get a moving average
66 // applied to the original field.
67 const filtered_suffix = "_filtered";
68 if (field[0] == "acceleration_magnitude") {
69 return new Float32Array(this.acceleration_magnitudes);
70 } else if (field[0].endsWith(filtered_suffix)) {
71 return this.movingAverageCentered(this.getField(
72 [field[0].slice(0, field[0].length - filtered_suffix.length)]));
73 } else {
74 return super.getField(field);
James Kuszmaul5f5e1232020-12-22 20:58:00 -080075 }
76 }
77}