blob: 7657d379eb87d732dd3718baf2c7212b2d1a576c [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';
James Kuszmaul0d7df892021-04-09 22:19:49 -07006import {Point} from 'org_frc971/aos/network/www/plotter';
James Kuszmaul5f5e1232020-12-22 20:58:00 -08007import {Table} from 'org_frc971/aos/network/www/reflection';
8import {ByteBuffer} from 'org_frc971/external/com_github_google_flatbuffers/ts/byte-buffer';
James Kuszmaulf8355ff2021-12-19 22:08:45 -08009import {Long} from 'org_frc971/external/com_github_google_flatbuffers/ts/long';
James Kuszmaul5f5e1232020-12-22 20:58:00 -080010
11import Schema = configuration.reflection.Schema;
12import IMUValuesBatch = imu.frc971.IMUValuesBatch;
13import IMUValues = imu.frc971.IMUValues;
14
James Kuszmaulac2b6b42021-03-07 22:38:06 -080015const FILTER_WINDOW_SIZE = 100;
16
James Kuszmaul5f5e1232020-12-22 20:58:00 -080017export class ImuMessageHandler extends MessageHandler {
James Kuszmaulac2b6b42021-03-07 22:38:06 -080018 // Calculated magnitude of the measured acceleration from the IMU.
James Kuszmaul0d7df892021-04-09 22:19:49 -070019 private acceleration_magnitudes: Point[] = [];
James Kuszmaul5f5e1232020-12-22 20:58:00 -080020 constructor(private readonly schema: Schema) {
21 super(schema);
22 }
James Kuszmaulf8355ff2021-12-19 22:08:45 -080023 private readScalar(table: Table, fieldName: string): number|Long|null {
James Kuszmaulac2b6b42021-03-07 22:38:06 -080024 return this.parser.readScalar(table, fieldName);
25 }
James Kuszmaul5f5e1232020-12-22 20:58:00 -080026 addMessage(data: Uint8Array, time: number): void {
27 const batch = IMUValuesBatch.getRootAsIMUValuesBatch(
28 new ByteBuffer(data) as unknown as flatbuffers.ByteBuffer);
29 for (let ii = 0; ii < batch.readingsLength(); ++ii) {
30 const message = batch.readings(ii);
31 const table = Table.getNamedTable(
32 message.bb as unknown as ByteBuffer, this.schema, 'frc971.IMUValues',
33 message.bb_pos);
34 if (this.parser.readScalar(table, "monotonic_timestamp_ns") == null) {
35 console.log('Ignoring unpopulated IMU values: ');
36 console.log(this.parser.toObject(table));
37 continue;
38 }
James Kuszmaulac2b6b42021-03-07 22:38:06 -080039 const time = message.monotonicTimestampNs().toFloat64() * 1e-9;
40 this.messages.push(new TimestampedMessage(table, time));
James Kuszmaul0d7df892021-04-09 22:19:49 -070041 this.acceleration_magnitudes.push(new Point(
42 time,
43 Math.hypot(
44 message.accelerometerX(), message.accelerometerY(),
45 message.accelerometerZ())));
James Kuszmaulac2b6b42021-03-07 22:38:06 -080046 }
47 }
48
49 // Computes a moving average for a given input, using a basic window centered
50 // on each value.
James Kuszmaul0d7df892021-04-09 22:19:49 -070051 private movingAverageCentered(input: Point[]): Point[] {
52 const num_measurements = input.length;
53 const filtered_measurements = [];
James Kuszmaulac2b6b42021-03-07 22:38:06 -080054 for (let ii = 0; ii < num_measurements; ++ii) {
55 let sum = 0;
56 let count = 0;
57 for (let jj = Math.max(0, Math.ceil(ii - FILTER_WINDOW_SIZE / 2));
58 jj < Math.min(num_measurements, ii + FILTER_WINDOW_SIZE / 2); ++jj) {
James Kuszmaul0d7df892021-04-09 22:19:49 -070059 sum += input[jj].y;
James Kuszmaulac2b6b42021-03-07 22:38:06 -080060 ++count;
61 }
James Kuszmaul0d7df892021-04-09 22:19:49 -070062 filtered_measurements.push(new Point(input[ii].x, sum / count));
James Kuszmaulac2b6b42021-03-07 22:38:06 -080063 }
James Kuszmaul0d7df892021-04-09 22:19:49 -070064 return filtered_measurements;
James Kuszmaulac2b6b42021-03-07 22:38:06 -080065 }
66
James Kuszmaul0d7df892021-04-09 22:19:49 -070067 getField(field: string[]): Point[] {
James Kuszmaulac2b6b42021-03-07 22:38:06 -080068 // Any requested input that ends with "_filtered" will get a moving average
69 // applied to the original field.
70 const filtered_suffix = "_filtered";
71 if (field[0] == "acceleration_magnitude") {
James Kuszmaul0d7df892021-04-09 22:19:49 -070072 return this.acceleration_magnitudes;
James Kuszmaulac2b6b42021-03-07 22:38:06 -080073 } else if (field[0].endsWith(filtered_suffix)) {
74 return this.movingAverageCentered(this.getField(
75 [field[0].slice(0, field[0].length - filtered_suffix.length)]));
76 } else {
77 return super.getField(field);
James Kuszmaul5f5e1232020-12-22 20:58:00 -080078 }
79 }
80}