@openhps/web-sensors
Version:
Open Hybrid Positioning System - Web Sensors API
118 lines (107 loc) • 4.36 kB
text/typescript
import {
Acceleration,
AngularVelocity,
DataFrame,
Orientation,
SensorSourceOptions,
SourceNode,
AbsoluteOrientationSensor as AbsoluteOrientationSensorObject,
Gyroscope as GyroscopeObject,
Accelerometer as AccelerometerObject,
DataObject,
AccelerationUnit,
AngularVelocityUnit,
} from '@openhps/core';
import { SensorSourceNodeInterface } from '../SensorSourceNodeInterface';
/**
* IMU source using the HTML5 browser API for device motion and device orientation.
* @category Source node
*/
export class SensorSourceNode extends SourceNode<DataFrame> implements SensorSourceNodeInterface {
protected options: SensorSourceOptions;
constructor(options?: SensorSourceOptions) {
super(options);
this.options.source = this.options.source ?? new DataObject(this.uid);
if (this.options.autoStart) {
this.once('build', this.start.bind(this));
}
this.once('destroy', this.stop.bind(this));
}
requestPermission(): Promise<void> {
return Promise.resolve();
}
start(): Promise<void> {
return new Promise((resolve) => {
const sensorUID = this.source ? this.source.uid : this.uid;
window.addEventListener(
'devicemotion',
(event) => {
// Create a new data frame for the orientation change
const dataFrame = new DataFrame();
const frequency = 1000 / event.interval;
dataFrame.addSensor(
new AccelerometerObject(
sensorUID + '_accl',
new Acceleration(
event.accelerationIncludingGravity.x,
event.accelerationIncludingGravity.y,
event.accelerationIncludingGravity.z,
AccelerationUnit.METER_PER_SECOND_SQUARE,
),
frequency,
),
);
dataFrame.addSensor(
new GyroscopeObject(
sensorUID + '_gyro',
new AngularVelocity(
event.rotationRate.beta,
event.rotationRate.gamma,
event.rotationRate.alpha,
AngularVelocityUnit.RADIAN_PER_SECOND,
),
frequency,
),
);
dataFrame.addSensor(
new AccelerometerObject(
sensorUID + '_linearaccl',
new Acceleration(
event.acceleration.x,
event.acceleration.y,
event.acceleration.z,
AccelerationUnit.METER_PER_SECOND_SQUARE,
),
frequency,
),
);
const source = this.source;
source.getPosition().angularVelocity = dataFrame.getSensor(GyroscopeObject).value;
dataFrame.addSensor(
new AbsoluteOrientationSensorObject(
sensorUID + '_orientation',
source.getPosition().orientation,
),
);
dataFrame.source = source;
this.push(dataFrame);
},
true,
);
window.addEventListener('deviceorientation', (event) => {
const source = this.source;
source.getPosition().orientation = Orientation.fromEuler([event.beta, event.gamma, event.alpha]);
});
this.logger('debug', 'Browser orientation and motion events registered!');
resolve();
});
}
stop(): Promise<void> {
return Promise.resolve();
}
public onPull(): Promise<DataFrame> {
return new Promise<DataFrame>((resolve) => {
resolve(undefined);
});
}
}