Source: views/GainsAdjustView.js

/**
 * @author Serge Babayan
 * @module views/GainsAdjustView
 * @requires util/Logger
 * @requires models/TelemetryData
 * @requires models/Commands
 * @requires util/Template
 * @requires util/Validator
 * @requires config/gains-config
 * @requires electron
 * @listens models/TelemetryData~TelemetryData:data_received
 * @copyright Waterloo Aerial Robotics Group 2016
 * @licence https://raw.githubusercontent.com/UWARG/WARG-Ground-Station/master/LICENSE
 * @description View for adjusting the aircraft's gain values
 */

var remote = require('electron').remote;
var Template = require('../util/Template');
var TelemetryData = remote.require('./app/models/TelemetryData');
var Commands = remote.require('./app/models/Commands');
var Validator = require('../util/Validator');
var Logger = remote.require('./app/util/Logger');
var gains_config = remote.require('./config/gains-config');

module.exports = function (Marionette) {

  return Marionette.ItemView.extend({
    template: Template('GainsAdjustView'),
    className: 'gainsAdjustView',

    ui: {
      yaw_kd: '#yaw-kd',
      yaw_ki: '#yaw-ki',
      yaw_kp: '#yaw-kp',
      pitch_kd: '#pitch-kd',
      pitch_ki: '#pitch-ki',
      pitch_kp: '#pitch-kp',
      roll_kd: '#roll-kd',
      roll_ki: '#roll-ki',
      roll_kp: '#roll-kp',
      heading_kd: '#heading-kd',
      heading_ki: '#heading-ki',
      heading_kp: '#heading-kp',
      altitude_kd: '#altitude-kd',
      altitude_ki: '#altitude-ki',
      altitude_kp: '#altitude-kp',
      throttle_kd: '#throttle-kd',
      throttle_ki: '#throttle-ki',
      throttle_kp: '#throttle-kp',
      flap_kd: '#flap-kd',
      flap_ki: '#flap-ki',
      flap_kp: '#flap-kp',
      orbit_kp: '#orbit-kp',
      path_kp: '#path-kp',

      send_all: '#send-all-gains-button',
      reset_all: '#reset-default-gains-button',
      yaw_send_button: '#send-yaw-gain-button',
      pitch_send_button: '#send-pitch-gain-button',
      roll_send_button: '#send-roll-gain-button',
      heading_send_button: '#send-heading-gain-button',
      altitude_send_button: '#send-altitude-gain-button',
      throttle_send_button: '#send-throttle-gain-button',
      flap_send_button: '#send-flap-gain-button',
      path_send_button: '#send-path-gain-button',
      orbit_send_button: '#send-orbit-gain-button'
    },

    events: {
      'click #send-all-gains-button': 'sendAllGains',
      'click #save-all-gains-button': 'saveChanges',
      'click #discard-all-gains-button': 'discardChanges',
      'click #reset-default-gains-button': 'resetToDefault',
      'click #send-yaw-gain-button': 'sendYawGains',
      'click #send-pitch-gain-button': 'sendPitchGains',
      'click #send-roll-gain-button': 'sendRollGains',
      'click #send-heading-gain-button': 'sendHeadingGains',
      'click #send-altitude-gain-button': 'sendAltitudeGains',
      'click #send-throttle-gain-button': 'sendThrottleGains',
      'click #send-flap-gain-button': 'sendFlapGains',
      'click #send-orbit-gain-button': 'sendOrbitalGains',
      'click #send-path-gain-button': 'sendPathGains',

      'submit .yaw-form': 'sendYawGains',
      'submit .pitch-form': 'sendPitchGains',
      'submit .roll-form': 'sendRollGains',
      'submit .heading-form': 'sendHeadingGains',
      'submit .altitude-form': 'sendAltitudeGains',
      'submit .throttle-form': 'sendThrottleGains',
      'submit .flap-form': 'sendFlapGains',
      'submit .orbit-form': 'sendOrbitalGains',
      'submit .path-form': 'sendPathGains'
    },

    initialize: function () {
      this.needs_verifying = {
        yaw: {
          status: false,
          ki: 0,
          kp: 0,
          kd: 0
        },
        pitch: {
          status: false,
          ki: 0,
          kp: 0,
          kd: 0
        },
        roll: {
          status: false,
          ki: 0,
          kp: 0,
          kd: 0
        },
        heading: {
          status: false,
          ki: 0,
          kp: 0,
          kd: 0
        },
        flap: {
          status: false,
          ki: 0,
          kp: 0,
          kd: 0
        },
        orbit: {
          status: false,
          ki: 0,
          kp: 0,
          kd: 0
        },
        path: {
          status: false,
          ki: 0,
          kp: 0,
          kd: 0
        },
        throttle: {
          status: false,
          ki: 0,
          kp: 0,
          kd: 0
        },
        altitude: {
          status: false,
          ki: 0,
          kp: 0,
          kd: 0
        }
      };
      this.data_callback = null;
    },

    onRender: function () {
      this.data_callback = this.dataCallback.bind(this);
      TelemetryData.addListener('data_received', this.data_callback);
      this.discardChanges(); //fills in the values from the settings
    },

    onBeforeDestroy: function () {
      TelemetryData.removeListener('data_received', this.data_callback);
    },

    //compares two values of gains with up to 3 decimal places of percision
    compareGains: function (gain1, gain2) {
      gain1 = Number(gain1);
      gain2 = Number(gain2);
      return gain1.toFixed(3) === gain2.toFixed(3);
    },

    dataCallback: function (data) {
      if (this.needs_verifying.yaw.status) {
        if (this.compareGains(data.yaw_kp, this.needs_verifying.yaw.kp) && this.compareGains(data.yaw_ki, this.needs_verifying.yaw.ki) && this.compareGains(data.yaw_kd, this.needs_verifying.yaw.kd)) {
          this.needs_verifying.yaw.status = false;
          Logger.info('[Gains Adjust] Yaw gain successfully verified!');
          this.ui.yaw_send_button.text('Send');
        }
      }
      if (this.needs_verifying.pitch.status) {
        if (this.compareGains(data.pitch_kp, this.needs_verifying.pitch.kp) && this.compareGains(data.pitch_ki, this.needs_verifying.pitch.ki) && this.compareGains(data.pitch_kd, this.needs_verifying.pitch.kd)) {
          this.needs_verifying.pitch.status = false;
          Logger.info('[Gains Adjust] Pitch gain successfully verified!');
          this.ui.pitch_send_button.text('Send');
        }
      }
      if (this.needs_verifying.roll.status) {
        if (this.compareGains(data.roll_kp, this.needs_verifying.roll.kp) && this.compareGains(data.roll_ki, this.needs_verifying.roll.ki) && this.compareGains(data.roll_kd, this.needs_verifying.roll.kd)) {
          this.needs_verifying.roll.status = false;
          Logger.info('[Gains Adjust] Roll gain successfully verified!');
          this.ui.roll_send_button.text('Send');
        }
      }
      if (this.needs_verifying.heading.status) {
        if (this.compareGains(data.heading_kp, this.needs_verifying.heading.kp) && this.compareGains(data.heading_ki, this.needs_verifying.heading.ki) && this.compareGains(data.heading_kd, this.needs_verifying.heading.kd)) {
          this.needs_verifying.heading.status = false;
          Logger.info('[Gains Adjust] Heading gain successfully verified!');
          this.ui.heading_send_button.text('Send');
        }
      }
      if (this.needs_verifying.flap.status) {
        if (this.compareGains(data.flap_kp, this.needs_verifying.flap.kp) && this.compareGains(data.flap_ki, this.needs_verifying.flap.ki) && this.compareGains(data.flap_kd, this.needs_verifying.flap.kd)) {
          this.needs_verifying.flap.status = false;
          Logger.info('[Gains Adjust] Flap gain successfully verified!');
          this.ui.flap_send_button.text('Send');
        }
      }
      if (this.needs_verifying.orbit.status) {
        if (this.compareGains(data.orbit_gain, this.needs_verifying.orbit.kp)) {
          this.needs_verifying.orbit.status = false;
          Logger.info('[Gains Adjust] Orbit gain successfully verified!');
          this.ui.orbit_send_button.text('Send');
        }
      }
      if (this.needs_verifying.throttle.status) {
        if (this.compareGains(data.throttle_kp, this.needs_verifying.throttle.kp) && this.compareGains(data.throttle_ki, this.needs_verifying.throttle.ki) && this.compareGains(data.throttle_kd, this.needs_verifying.throttle.kd)) {
          this.needs_verifying.throttle.status = false;
          Logger.info('[Gains Adjust] Throttle gain successfully verified!');
          this.ui.throttle_send_button.text('Send');
        }
      }
      if (this.needs_verifying.altitude.status) {
        if (this.compareGains(data.altitude_kp, this.needs_verifying.altitude.kp) && this.compareGains(data.altitude_ki, this.needs_verifying.altitude.ki) && this.compareGains(data.altitude_kd, this.needs_verifying.altitude.kd)) {
          this.needs_verifying.altitude.status = false;
          Logger.info('[Gains Adjust] Altitude gain successfully verified!');
          this.ui.altitude_send_button.text('Send');
        }
      }
      if (this.needs_verifying.path.status) {
        if (this.compareGains(data.path_gain, this.needs_verifying.path.kp)) {
          this.needs_verifying.path.status = false;
          Logger.info('[Gains Adjust] Path gain successfully verified!');
          this.ui.path_send_button.text('Send');
        }
      }
    },

    sendYawGains: function (e) {
      if (e) {
        e.preventDefault();
      }
      var ki = Number(this.ui.yaw_ki.val());
      var kd = Number(this.ui.yaw_kd.val());
      var kp = Number(this.ui.yaw_kp.val());
      Commands.sendKPGain('yaw', kp);
      Commands.sendKIGain('yaw', ki);
      Commands.sendKDGain('yaw', kd);
      this.needs_verifying.yaw = {
        status: true,
        ki: ki,
        kd: kd,
        kp: kp
      };
      this.ui.yaw_send_button.text('Verifying...');
    },
    sendPitchGains: function (e) {
      if (e) {
        e.preventDefault();
      }
      var ki = Number(this.ui.pitch_ki.val());
      var kd = Number(this.ui.pitch_kd.val());
      var kp = Number(this.ui.pitch_kp.val());
      Commands.sendKPGain('pitch', kp);
      Commands.sendKIGain('pitch', ki);
      Commands.sendKDGain('pitch', kd);
      this.needs_verifying.pitch = {
        status: true,
        ki: ki,
        kd: kd,
        kp: kp
      };
      this.ui.pitch_send_button.text('Verifying...');
    },
    sendRollGains: function (e) {
      if (e) {
        e.preventDefault();
      }
      var ki = Number(this.ui.roll_ki.val());
      var kd = Number(this.ui.roll_kd.val());
      var kp = Number(this.ui.roll_kp.val());
      Commands.sendKPGain('roll', kp);
      Commands.sendKIGain('roll', ki);
      Commands.sendKDGain('roll', kd);
      this.needs_verifying.roll = {
        status: true,
        ki: ki,
        kd: kd,
        kp: kp
      };
      console.log(this.needs_verifying);
      this.ui.roll_send_button.text('Verifying...');
    },
    sendHeadingGains: function (e) {
      if (e) {
        e.preventDefault();
      }
      var ki = Number(this.ui.heading_ki.val());
      var kd = Number(this.ui.heading_kd.val());
      var kp = Number(this.ui.heading_kp.val());
      Commands.sendKPGain('heading', kp);
      Commands.sendKIGain('heading', ki);
      Commands.sendKDGain('heading', kd);
      this.needs_verifying.heading = {
        status: true,
        ki: ki,
        kd: kd,
        kp: kp
      };
      this.ui.heading_send_button.text('Verifying...');
    },
    sendAltitudeGains: function (e) {
      if (e) {
        e.preventDefault();
      }
      var ki = Number(this.ui.altitude_ki.val());
      var kd = Number(this.ui.altitude_kd.val());
      var kp = Number(this.ui.altitude_kp.val());
      Commands.sendKPGain('altitude', kp);
      Commands.sendKIGain('altitude', ki);
      Commands.sendKDGain('altitude', kd);
      this.needs_verifying.altitude = {
        status: true,
        ki: ki,
        kd: kd,
        kp: kp
      };
      this.ui.altitude_send_button.text('Verifying...');
    },
    sendThrottleGains: function (e) {
      if (e) {
        e.preventDefault();
      }
      var ki = Number(this.ui.throttle_ki.val());
      var kd = Number(this.ui.throttle_kd.val());
      var kp = Number(this.ui.throttle_kp.val());
      Commands.sendKPGain('throttle', kp);
      Commands.sendKIGain('throttle', ki);
      Commands.sendKDGain('throttle', kd);
      this.needs_verifying.throttle = {
        status: true,
        ki: ki,
        kd: kd,
        kp: kp
      };
      this.ui.throttle_send_button.text('Verifying...');
    },
    sendFlapGains: function (e) {
      if (e) {
        e.preventDefault();
      }
      var ki = Number(this.ui.flap_ki.val());
      var kd = Number(this.ui.flap_kd.val());
      var kp = Number(this.ui.flap_kp.val());
      Commands.sendKPGain('flap', kp);
      Commands.sendKIGain('flap', ki);
      Commands.sendKDGain('flap', kd);
      this.needs_verifying.flap = {
        status: true,
        ki: ki,
        kd: kd,
        kp: kp
      };
      this.ui.flap_send_button.text('Verifying...');
    },
    sendOrbitalGains: function (e) {
      if (e) {
        e.preventDefault();
      }
      var kp = Number(this.ui.orbit_kp.val());
      Commands.sendOrbitGain(kp);
      this.needs_verifying.orbit = {
        status: true,
        kp: kp
      };
      this.ui.orbit_send_button.text('Verifying...');
    },
    sendPathGains: function (e) {
      if (e) {
        e.preventDefault();
      }
      var kp = Number(this.ui.path_kp.val());
      Commands.sendPathGain(kp);
      this.needs_verifying.path = {
        status: true,
        kp: kp
      };
      this.ui.path_send_button.text('Verifying...');
    },
    sendAllGains: function () {
      this.sendYawGains();
      this.sendPitchGains();
      this.sendRollGains();
      this.sendHeadingGains();
      this.sendAltitudeGains();
      this.sendThrottleGains();
      this.sendFlapGains();
      this.sendOrbitalGains();
      this.sendPathGains();
    },
    //saves the gain if its a valid number
    checkAndSaveGain: function (id, value) {
      if (Validator.isValidNumber(value)) {
        gains_config.set(id, Number(value));
      }
      else {
        Logger.error('Did not save ' + id + ' gain as its not a valid number');
      }
    },

    saveChanges: function () {
      this.checkAndSaveGain('yaw_kd', this.ui.yaw_kd.val());
      this.checkAndSaveGain('yaw_ki', this.ui.yaw_ki.val());
      this.checkAndSaveGain('yaw_kp', this.ui.yaw_kp.val());
      this.checkAndSaveGain('pitch_kd', this.ui.pitch_kd.val());
      this.checkAndSaveGain('pitch_ki', this.ui.pitch_ki.val());
      this.checkAndSaveGain('pitch_kp', this.ui.pitch_kp.val());
      this.checkAndSaveGain('roll_kd', this.ui.roll_kd.val());
      this.checkAndSaveGain('roll_ki', this.ui.roll_ki.val());
      this.checkAndSaveGain('roll_kp', this.ui.roll_kp.val());
      this.checkAndSaveGain('heading_kd', this.ui.heading_kd.val());
      this.checkAndSaveGain('heading_ki', this.ui.heading_ki.val());
      this.checkAndSaveGain('heading_kp', this.ui.heading_kp.val());
      this.checkAndSaveGain('altitude_kd', this.ui.altitude_kd.val());
      this.checkAndSaveGain('altitude_ki', this.ui.altitude_ki.val());
      this.checkAndSaveGain('altitude_kp', this.ui.altitude_kp.val());
      this.checkAndSaveGain('throttle_kd', this.ui.throttle_kd.val());
      this.checkAndSaveGain('throttle_ki', this.ui.throttle_ki.val());
      this.checkAndSaveGain('throttle_kp', this.ui.throttle_kp.val());
      this.checkAndSaveGain('flap_kd', this.ui.flap_kd.val());
      this.checkAndSaveGain('flap_ki', this.ui.flap_ki.val());
      this.checkAndSaveGain('flap_kp', this.ui.flap_kp.val());
      this.checkAndSaveGain('orbit_kp', this.ui.orbit_kp.val());
      this.checkAndSaveGain('path_kp', this.ui.path_kp.val());
    },
    discardChanges: function () {
      this.ui.yaw_kd.val(gains_config.get('yaw_kd'));
      this.ui.yaw_ki.val(gains_config.get('yaw_ki'));
      this.ui.yaw_kp.val(gains_config.get('yaw_kp'));
      this.ui.pitch_kd.val(gains_config.get('pitch_kd'));
      this.ui.pitch_ki.val(gains_config.get('pitch_ki'));
      this.ui.pitch_kp.val(gains_config.get('pitch_kp'));
      this.ui.roll_kd.val(gains_config.get('roll_kd'));
      this.ui.roll_ki.val(gains_config.get('roll_ki'));
      this.ui.roll_kp.val(gains_config.get('roll_kp'));
      this.ui.heading_kd.val(gains_config.get('heading_kd'));
      this.ui.heading_ki.val(gains_config.get('heading_ki'));
      this.ui.heading_kp.val(gains_config.get('heading_kp'));
      this.ui.altitude_kd.val(gains_config.get('altitude_kd'));
      this.ui.altitude_ki.val(gains_config.get('altitude_ki'));
      this.ui.altitude_kp.val(gains_config.get('altitude_kp'));
      this.ui.throttle_kd.val(gains_config.get('throttle_kd'));
      this.ui.throttle_ki.val(gains_config.get('throttle_ki'));
      this.ui.throttle_kp.val(gains_config.get('throttle_kp'));
      this.ui.flap_kd.val(gains_config.get('flap_kd'));
      this.ui.flap_ki.val(gains_config.get('flap_ki'));
      this.ui.flap_kp.val(gains_config.get('flap_kp'));
      this.ui.orbit_kp.val(gains_config.get('orbit_kp'));
      this.ui.path_kp.val(gains_config.get('path_kp'));
    },
    resetToDefault: function () {
      this.ui.yaw_kd.val(gains_config.default_settings['yaw_kd']);
      this.ui.yaw_ki.val(gains_config.default_settings['yaw_ki']);
      this.ui.yaw_kp.val(gains_config.default_settings['yaw_kp']);
      this.ui.pitch_kd.val(gains_config.default_settings['pitch_kd']);
      this.ui.pitch_ki.val(gains_config.default_settings['pitch_ki']);
      this.ui.pitch_kp.val(gains_config.default_settings['pitch_kp']);
      this.ui.roll_kd.val(gains_config.default_settings['roll_kd']);
      this.ui.roll_ki.val(gains_config.default_settings['roll_ki']);
      this.ui.roll_kp.val(gains_config.default_settings['roll_kp']);
      this.ui.heading_kd.val(gains_config.default_settings['heading_kd']);
      this.ui.heading_ki.val(gains_config.default_settings['heading_ki']);
      this.ui.heading_kp.val(gains_config.default_settings['heading_kp']);
      this.ui.altitude_kd.val(gains_config.default_settings['altitude_kd']);
      this.ui.altitude_ki.val(gains_config.default_settings['altitude_ki']);
      this.ui.altitude_kp.val(gains_config.default_settings['altitude_kp']);
      this.ui.throttle_kd.val(gains_config.default_settings['throttle_kd']);
      this.ui.throttle_ki.val(gains_config.default_settings['throttle_ki']);
      this.ui.throttle_kp.val(gains_config.default_settings['throttle_kp']);
      this.ui.flap_kd.val(gains_config.default_settings['flap_kd']);
      this.ui.flap_ki.val(gains_config.default_settings['flap_ki']);
      this.ui.flap_kp.val(gains_config.default_settings['flap_kp']);
      this.ui.orbit_kp.val(gains_config.default_settings['orbit_kp']);
      this.ui.path_kp.val(gains_config.default_settings['path_kp']);

      this.saveChanges();
    }
  });
};