UNPKG

johnny-five

Version:

The JavaScript Robotics and Hardware Programming Framework. Use with: Arduino (all models), Electric Imp, Beagle Bone, Intel Galileo & Edison, Linino One, Pinoccio, pcDuino3, Raspberry Pi, Particle/Spark Core & Photon, Tessel 2, TI Launchpad and more!

207 lines (173 loc) 4.41 kB
var Emitter = require("events").EventEmitter; var util = require("util"); var Board = require("./board"); var priv = new Map(); var Controllers = { BNO055: { initialize: { value: function(opts, dataHandler) { var IMU = require("./imu"), driver = IMU.Drivers.get(this.board, "BNO055", opts); driver.on("data", function(data) { dataHandler(data); }); } }, toScaledEuler: { value: function(raw) { return { heading: raw.euler.heading / 16, roll: raw.euler.roll / 16, pitch: raw.euler.pitch / 16, }; } }, toScaledQuarternion: { value: function(raw) { return { w: raw.quarternion.w * (1 / (1 << 14)), x: raw.quarternion.x * (1 / (1 << 14)), y: raw.quarternion.y * (1 / (1 << 14)), z: raw.quarternion.z * (1 / (1 << 14)), }; } }, calibration: { get: function() { return priv.get(this).calibration; } }, isCalibrated: { get: function() { //only returns true if the calibration of the NDOF/Fusion algo is calibrated return ((this.calibration >> 6) & 0x03) === 0x03; //are we fully calibrated } } }, }; /** * Orientation * @constructor * * five.Orientation(); * * five.Orientation({ * controller: "BNO055", * freq: 50, * }); * * * Device Shorthands: * * "BNO055": new five.Orientation() * * * @param {Object} opts [description] * */ function Orientation(opts) { if (!(this instanceof Orientation)) { return new Orientation(opts); } Board.Component.call( this, opts = Board.Options(opts) ); var freq = opts.freq || 25; var controller = null; var raw = null; var state = { euler: { heading: 0, roll: 0, pitch: 0, }, quarternion: { w: 0, x: 0, y: 0, z: 0, }, calibration: 0, }; if (opts.controller && typeof opts.controller === "string") { controller = Controllers[opts.controller.toUpperCase()]; } else { controller = opts.controller; } if (controller === null || typeof controller !== "object") { throw new Error("Missing valid Orientation controller"); } Board.Controller.call(this, controller, opts); if (!this.toScaledQuarternion) { this.toScaledQuarternion = opts.toScaledQuarternion || function(raw) { return raw; }; } if (!this.toScaledEuler) { this.toScaledEuler = opts.toScaledEuler || function(raw) { return raw; }; } priv.set(this, state); if (typeof this.initialize === "function") { this.initialize(opts, function(data) { raw = data; }); } setInterval(function() { if (raw === null) { return; } var didOrientationChange = false; var didCalibrationChange = false; ["heading", "roll", "pitch"].forEach(function(el) { if (state.euler[el] !== raw.orientation.euler[el]) { didOrientationChange = true; } state.euler[el] = raw.orientation.euler[el]; }); ["w", "x", "y", "z"].forEach(function(el) { if (state.quarternion[el] !== raw.orientation.quarternion[el]) { didOrientationChange = true; } state.quarternion[el] = raw.orientation.quarternion[el]; }); //if we have a raw calibration state... // not sure if this is the best place... some devices may not have a calibration state... if (raw.calibration) { if (state.calibration !== raw.calibration) { didCalibrationChange = true; } state.calibration = raw.calibration; } var data = { euler: this.euler, quarternion: this.quarternion, calibration: this.calibration }; this.emit("data", data); if (didOrientationChange) { this.emit("change", data); } //not sure how we can get this event into other drivers if (didCalibrationChange) { this.emit("calibration", this.calibration); } }.bind(this), freq); } util.inherits(Orientation, Emitter); Object.defineProperties(Orientation.prototype, { euler: { get: function() { var state = priv.get(this); return this.toScaledEuler(state); } }, quarternion: { get: function() { var state = priv.get(this); return this.toScaledQuarternion(state); } } }); module.exports = Orientation;