"""Replay the saved seed-7 synthetic gyro samples; no physical sensor measurements. 100 Hz; affine changes to constant bias and white-noise amplitude; prefix duration. Analyze every selected sample; display only the first 10 s of the raw trace. """ import math from pathlib import Path import time import numpy as np from imu_kernel import analyze, BLOCK_SIZES _saved = None def samples(): global _saved if _saved is None: local = Path(__file__).with_name('imu-synthetic.csv') path = local if local.exists() else Path(__file__).parent.parent/'expansion/imu-synthetic.csv' _saved = np.loadtxt(path, delimiter=',', skiprows=1) return _saved def run(name, p): if name != 'imu' or set(p) != {'bias', 'noise_std', 'duration'}: raise ValueError('Unknown experiment or parameters') for key, lo, hi in [('bias', -.05, .05), ('noise_std', .0005, .01), ('duration', 10, 600)]: value = p[key] if type(value) not in (int, float) or not math.isfinite(value) or not lo <= value <= hi: raise ValueError('Parameter out of range: ' + key) if p['duration'] % 10 != 0: raise ValueError('Duration must use 10-second steps') start = time.perf_counter() source = samples()[:int(100*p['duration'])] t = source[:, 0] y = p['bias']+(source[:, 1]-.01)*(p['noise_std']/.002) stats, rows = analyze(t, y, BLOCK_SIZES[len(t)]) def series(ident, x, y, unit='rad/s'): return dict(id=ident, x=x.tolist(), y=y.tolist(), x_unit='s', y_unit=unit) return dict( metrics=[dict(id='gyro_mean', value=stats['mean_rad_s'], unit='rad/s'), dict(id='gyro_std', value=stats['std_rad_s'], unit='rad/s'), dict(id='gyro_samples', value=stats['samples'], unit='count'), dict(id='allan_longest_tau', value=float(rows[-1, 0]), unit='s'), dict(id='allan_min_pairs', value=int(rows[:, 2].min()), unit='count')], series=[series('gyro_trace', t[:1000], y[:1000]), series('allan_deviation', rows[:, 0], rows[:, 1]), series('white_expectation', rows[:, 0], p['noise_std']/np.sqrt(rows[:, 0]*100)), series('adjacent_pairs', rows[:, 0], rows[:, 2], 'count')], stdout='', provenance=dict(data_type='synthetic', compute_ms=(time.perf_counter()-start)*1000)) if __name__ == '__main__': import argparse import json parser = argparse.ArgumentParser(description=__doc__) parser.add_argument('--parameters', default='{"bias":0.01,"noise_std":0.002,"duration":600}') args = parser.parse_args() print(json.dumps(run('imu', json.loads(args.parameters)), allow_nan=False))