wouterbulten/slacjs

View on GitHub
src/app/app-local.js

Summary

Maintainability
A
1 hr
Test Coverage
import SimulatedUser from './simulation/user';
import FixedUser from './simulation/fixed-user';
import { SimulatedLandmarkSet } from './simulation/landmark';
import SlacController from './slac-controller';
import SimulationRenderder from './view/simulation-renderer';
import config from './config';
import { randn } from './util/math';

window.SlacENV = config.environment;

window.SlacApp = {

    user: undefined,
    renderer: undefined,
    controller: undefined,
    landmarks: undefined,

    error: {avg: 0},

    initialize: function() {
        'use strict';

        //Update the initial pose with the true starting position
        config.particles.user.defaultPose = config.simulation.user;

        //Reset the device height as in the simulation everything is in the same plane
        config.landmarkConfig.distToFloor = 0;
        config.landmarkConfig.deviceHeight = 0;

        config.particles.user.sdStep = config.simulation.user.sdStep;
        config.particles.user.sdHeading = config.simulation.user.sdHeading;

        //Create a new controller
        this.controller = new SlacController(config);

        this.controller.start();

        //Bind renderer to controller
        this.controller.onUpdate((particles) => this.renderer.render(particles, this.user));

        this.user = new FixedUser(config.simulation.user, config.simulation.path);

        this.landmarks = new SimulatedLandmarkSet(
            20,
            {xRange: config.simulation.xMax, yRange: config.simulation.yMax},
            config.simulation.sensorUpdateRate,
            config.landmarkConfig,
            config.simulation.landmarks
        );

        //Create a renderer for the canvas view
        this.renderer = new SimulationRenderder(
            'slacjs-map',
            config.simulation.landmarks,
            config.simulation.xMax,
            config.simulation.yMax,
            0, 0
        );
    },

    reset: function() {
        //Create a new controller
        this.controller = new SlacController(config);

        this.controller.start();

        //Bind renderer to controller
        this.controller.onUpdate((particles) => this.renderer.render(particles, this.user));
    },

    step: function() {

        const success = this.user.walk();

        if (!success) {
            return false;
        }

        //Simulated broadcasts
        this.landmarks.simulateBroadcasts(config.simulation.broadcastsPerStep, this.controller, this.user);

        //Transform to angle and distance
        //Simulate this by getting the control from the simulated user
        let {r, theta} = this.user.getLastControl();

        r = randn(r, 0.15);
        theta = randn(theta, 0.1);

        //As we simulate a user, and not the raw sensors we inject the data into the controller
        this.controller._stepSize = r;
        this.controller.heading = theta;

        //Run the private update function as we do not use the pedometer part of the controller
        this.controller._update();

        this._calculateLandmarkError();

        return true;
    },

    /**
     * Calculate the landmark error and show on screen
     * @return {[type]} [description]
     */
    _calculateLandmarkError() {

        const distArr = [];
        let landmarkErrorsStr = '';

        this.controller.particleSet.bestParticle().landmarks.forEach((l) => {

            const trueL = config.simulation.landmarks[l.name];

            const dist = Math.sqrt(Math.pow(trueL.x - l.x, 2) + Math.pow(trueL.y - l.y, 2));

            distArr.push(dist);
            this.error[l.name] = dist;

            landmarkErrorsStr += l.name + ': ' + dist + '<br>';
        });

        if (distArr.length > 0) {
            $('.landmark-individual-error').html(landmarkErrorsStr);

            const avg = distArr.reduce(function(total, d) { return total + d; }, 0) / distArr.length;

            this.error.avg = avg;

            $('.landmark-error').html(Math.round((avg * 100)) / 100);
        }
    }
};