Merge pull request #59 from antstorm/rates-preview
Rates preview for the PID Tuning tab10.3.x-maintenance
commit
99106cb409
|
@ -232,7 +232,7 @@
|
|||
"defaultWelcomeIntro": {
|
||||
"message": "Welcome to <strong>Betaflight - Configurator</strong>, a utility designed to simplify updating, configuring and tuning of your flight controller."
|
||||
},
|
||||
|
||||
|
||||
"defaultWelcomeText": {
|
||||
"message": "The application supports all hardware that can run Betaflight (<a href=\"http://seriouslypro.com/spracingf3\" target=\"_blank\">SPRacingF3</a>, <a href=\"http://www.immersionrc.com/fpv-products/vortex-racing-quad/\" target=\"_blank\">Vortex</a>, <a href=\"https://github.com/TauLabs/TauLabs/wiki/Sparky\" target=\"_blank\">Sparky</a>, <a href=\"http://www.readymaderc.com/store/index.php?main_page=product_info&cPath=76_156&products_id=4221\" target=\"_blank\">DoDo</a>, <a href=\"https://www.openpilot.org/product/coptercontrol/\" target=\"_blank\">CC3D/EVO</a>, <a href=\"http://www.multiwiicopter.com/products/paris-air-hero-32-naze\" target=\"_blank\">Air Hero 32</a>, <a href=\"http://www.readytoflyquads.com/flight-controllers/flip-series\" target=\"_blank\">Flip32/+/Deluxe</a>, <a href=\"http://multirotormania.com/129-dragonfly32\" target=\"_blank\">DragonFly32</a>, <a href=\"http://www.goodluckbuy.com/micro-quadcopter-flight-driver-controller-9dof-9-axis-altitude-sensor-stm32f103.html\" target=\"_blank\">CJMCU Microquad</a>, Chebuzz F3, <a href=\"http://www.st.com/web/catalog/tools/FM116/SC959/SS1532/PF254044\" target=\"_blank\">STM32F3Discovery</a>, <a href=\"http://www.overskyrc.com/hermit-micro-fpv-brushless-quadcopter-145mm-98g-fully-assembled-p-621.html\" target=\"_blank\">Hermit</a>, <a href=\"http://rcexplorer.se/blog/2015/05/introducing-the-naze32-tricopter-frame/\" target=\"_blank\">Naze32 Tricopter Frame</a>, <a href=\"http://www.2dogrc.com/skyline-32-naze-32-bit-flight-controller-acro-version.html\" target=\"_blank\">Skyline32</a>, <a href=\"http://abusemark.com/store/index.php?main_page=index&cPath=1\" target=\"_blank\">Naze/32/Mini/Pro</a>/<a href=\"http://www.massiverc.com/Shop/en/574-massive-acro-blackbox-flight-control-board.html\" target=\"_blank\">Blackbox</a> etc)<br /><br />The firmware source code can be downloaded from <a href=\"https://github.com/Betaflight/Betaflight\" title=\"www.github.com\" target=\"_blank\">here</a><br />The newest binary firmware image is available <a href=\"https://github.com/Betaflight/Betaflight/releases\" title=\"www.github.com\" target=\"_blank\">here</a>, development builds available <a href=\"http://Betaflight.memoryleaks.org/builds/\" target=\"_blank\">here</a><br /><br />Latest <strong>CP210x Drivers</strong> can be downloaded from <a href=\"http://www.silabs.com/products/mcu/pages/usbtouartbridgevcpdrivers.aspx\" title=\"http://www.silabs.com\" target=\"_blank\">here</a><br />Latest <strong>STM USB VCP Drivers</strong> can be downloaded from <a href=\"http://www.st.com/web/en/catalog/tools/PF257938\" title=\"http://www.st.com\" target=\"_blank\">here</a><br />Latest <strong>Zadig</strong> for Windows DFU flashing can be downloaded from <a href=\"http://zadig.akeo.ie/\" title=\"http://zadig.akeo.ie\" target=\"_blank\">here</a><br />"
|
||||
},
|
||||
|
@ -296,7 +296,7 @@
|
|||
"defaultSupport5": {
|
||||
"message": "<a href=\"http://webchat.freenode.net/?channels=Betaflight\" target=\"_blank\">Join via WebClient</a>"
|
||||
},
|
||||
|
||||
|
||||
"initialSetupBackupAndRestoreApiVersion": {
|
||||
"message": "<span style=\"color: red\">Backup and restore functionality disabled.</span> You have firmware with API version <span style=\"color: red\">$1</span>, backup and restore requires <span style=\"color: #ffbb00\">$2</span>. Please backup your settings via the CLI, see Betaflight documentation for procedure."
|
||||
},
|
||||
|
@ -532,7 +532,7 @@
|
|||
"featureAIRMODE": {
|
||||
"message": "Airmode always enabled!"
|
||||
},
|
||||
|
||||
|
||||
"configurationFeatureEnabled": {
|
||||
"message": "Enabled"
|
||||
},
|
||||
|
@ -668,7 +668,7 @@
|
|||
"configurationLoopTime": {
|
||||
"message": "Flight Controller Loop Time"
|
||||
},
|
||||
"configurationCalculatedCyclesSec": {
|
||||
"configurationCalculatedCyclesSec": {
|
||||
"message": "Cycles/Sec (Hz)"
|
||||
},
|
||||
"configurationLoopTimeHelp": {
|
||||
|
@ -766,6 +766,9 @@
|
|||
"pidTuningRate": {
|
||||
"message": "Rate"
|
||||
},
|
||||
"pidTuningRatesPreview": {
|
||||
"message": "Rates Preview"
|
||||
},
|
||||
"pidTuningRcExpo": {
|
||||
"message": "RC Expo"
|
||||
},
|
||||
|
@ -832,7 +835,7 @@
|
|||
},
|
||||
"receiverHelpYawDeadband": {
|
||||
"message": "These are values (in us) by how much RC input can be different before it's considered valid. For transmitters with jitter on outputs, this value can be increased if rc inputs twitch while idle. <strong>This setting is for Yaw only.</strong>"
|
||||
},
|
||||
},
|
||||
"receiverYawDeadband": {
|
||||
"message": "Yaw Deadband"
|
||||
},
|
||||
|
@ -1078,7 +1081,7 @@
|
|||
},
|
||||
"transponderDataInvalid": {
|
||||
"message": "Transponder data is <span style=\"color: red\">invalid</span>"
|
||||
},
|
||||
},
|
||||
"transponderEepromSaved": {
|
||||
"message": "EEPROM <span style=\"color: #ffbb00\">saved</span>"
|
||||
},
|
||||
|
@ -1251,14 +1254,14 @@
|
|||
"blackboxButtonSave": {
|
||||
"message": "Save and reboot"
|
||||
},
|
||||
|
||||
|
||||
"serialLoggingSupportedNote": {
|
||||
"message": "You can log to an external logging device (such as an OpenLog or compatible clone) by using a serial port. Configure the port on the Ports tab."
|
||||
},
|
||||
"sdcardNote": {
|
||||
"message": "Flight logs can be recorded to your flight controller's onboard SD card slot."
|
||||
},
|
||||
|
||||
|
||||
"dataflashNote": {
|
||||
"message": "Flight logs can be recorded to your flight controller's onboard dataflash chip."
|
||||
},
|
||||
|
@ -1304,7 +1307,7 @@
|
|||
"dataflashFileWriteFailed": {
|
||||
"message": "Failed to write to the file you selected, are the permissions on that folder okay?"
|
||||
},
|
||||
|
||||
|
||||
"firmwareFlasherReleaseSummaryHead": {
|
||||
"message": "Release info"
|
||||
},
|
||||
|
@ -1460,7 +1463,7 @@
|
|||
"ledStripEepromSaved": {
|
||||
"message": "EEPROM <span style=\"color: #ffbb00\">saved</span>"
|
||||
},
|
||||
|
||||
|
||||
"controlAxisRoll": {
|
||||
"message": "Roll"
|
||||
},
|
||||
|
@ -1521,7 +1524,7 @@
|
|||
"controlAxisAux16": {
|
||||
"message": "AUX 16"
|
||||
},
|
||||
|
||||
|
||||
"pidTuningBasic": {
|
||||
"message": "Basic/Acro"
|
||||
},
|
||||
|
@ -1545,7 +1548,7 @@
|
|||
},
|
||||
"pidTuningLevelD": {
|
||||
"message": "Transition (Horizon)"
|
||||
},
|
||||
},
|
||||
"pidTuningLevelHelp": {
|
||||
"message": "The values below change the behaviour of the ANGLE and HORIZON flight modes. Different PID controllers handle the LEVEL values differently. Please check the documentation."
|
||||
},
|
||||
|
@ -1669,5 +1672,5 @@
|
|||
"configurationMagHardware": {
|
||||
"message": "Magnetometer (if supported)"
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
167
js/model.js
167
js/model.js
|
@ -2,30 +2,145 @@
|
|||
|
||||
// generate mixer
|
||||
var mixerList = [
|
||||
{name: 'Tricopter', model: 'tricopter', image: 'tri'},
|
||||
{name: 'Quad +', model: 'quad_x', image: 'quad_p'},
|
||||
{name: 'Quad X', model: 'quad_x', image: 'quad_x'},
|
||||
{name: 'Bicopter', model: 'custom', image: 'bicopter'},
|
||||
{name: 'Gimbal', model: 'custom', image: 'custom'},
|
||||
{name: 'Y6', model: 'y6', image: 'y6'},
|
||||
{name: 'Hex +', model: 'hex_plus', image: 'hex_p'},
|
||||
{name: 'Flying Wing', model: 'custom', image: 'flying_wing'},
|
||||
{name: 'Y4', model: 'y4', image: 'y4'},
|
||||
{name: 'Hex X', model: 'hex_x', image: 'hex_x'},
|
||||
{name: 'Octo X8', model: 'custom', image: 'octo_x8'},
|
||||
{name: 'Octo Flat +', model: 'custom', image: 'octo_flat_p'},
|
||||
{name: 'Octo Flat X', model: 'custom', image: 'octo_flat_x'},
|
||||
{name: 'Airplane', model: 'custom', image: 'airplane'},
|
||||
{name: 'Heli 120', model: 'custom', image: 'custom'},
|
||||
{name: 'Heli 90', model: 'custom', image: 'custom'},
|
||||
{name: 'V-tail Quad', model: 'quad_vtail', image: 'vtail_quad'},
|
||||
{name: 'Hex H', model: 'custom', image: 'custom'},
|
||||
{name: 'PPM to SERVO', model: 'custom', image: 'custom'},
|
||||
{name: 'Dualcopter', model: 'custom', image: 'custom'},
|
||||
{name: 'Singlecopter', model: 'custom', image: 'custom'},
|
||||
{name: 'A-tail Quad', model: 'quad_atail', image: 'atail_quad'},
|
||||
{name: 'Custom', model: 'custom', image: 'custom'},
|
||||
{name: 'Custom Airplane', model: 'custom', image: 'custom'},
|
||||
{name: 'Custom Tricopter', model: 'custom', image: 'custom'}
|
||||
|
||||
{name: 'Tricopter', model: 'tricopter', image: 'tri'},
|
||||
{name: 'Quad +', model: 'quad_x', image: 'quad_p'},
|
||||
{name: 'Quad X', model: 'quad_x', image: 'quad_x'},
|
||||
{name: 'Bicopter', model: 'custom', image: 'bicopter'},
|
||||
{name: 'Gimbal', model: 'custom', image: 'custom'},
|
||||
{name: 'Y6', model: 'y6', image: 'y6'},
|
||||
{name: 'Hex +', model: 'hex_plus', image: 'hex_p'},
|
||||
{name: 'Flying Wing', model: 'custom', image: 'flying_wing'},
|
||||
{name: 'Y4', model: 'y4', image: 'y4'},
|
||||
{name: 'Hex X', model: 'hex_x', image: 'hex_x'},
|
||||
{name: 'Octo X8', model: 'custom', image: 'octo_x8'},
|
||||
{name: 'Octo Flat +', model: 'custom', image: 'octo_flat_p'},
|
||||
{name: 'Octo Flat X', model: 'custom', image: 'octo_flat_x'},
|
||||
{name: 'Airplane', model: 'custom', image: 'airplane'},
|
||||
{name: 'Heli 120', model: 'custom', image: 'custom'},
|
||||
{name: 'Heli 90', model: 'custom', image: 'custom'},
|
||||
{name: 'V-tail Quad', model: 'quad_vtail', image: 'vtail_quad'},
|
||||
{name: 'Hex H', model: 'custom', image: 'custom'},
|
||||
{name: 'PPM to SERVO', model: 'custom', image: 'custom'},
|
||||
{name: 'Dualcopter', model: 'custom', image: 'custom'},
|
||||
{name: 'Singlecopter', model: 'custom', image: 'custom'},
|
||||
{name: 'A-tail Quad', model: 'quad_atail', image: 'atail_quad'},
|
||||
{name: 'Custom', model: 'custom', image: 'custom'},
|
||||
{name: 'Custom Airplane', model: 'custom', image: 'custom'},
|
||||
{name: 'Custom Tricopter', model: 'custom', image: 'custom'}
|
||||
];
|
||||
|
||||
|
||||
// 3D model
|
||||
var Model = function (wrapper, canvas) {
|
||||
var useWebGLRenderer = this.canUseWebGLRenderer();
|
||||
|
||||
this.wrapper = wrapper;
|
||||
this.canvas = canvas;
|
||||
|
||||
if (useWebGLRenderer) {
|
||||
this.renderer = new THREE.WebGLRenderer({ canvas: this.canvas[0], alpha: true, antialias: true });
|
||||
} else {
|
||||
this.renderer = new THREE.CanvasRenderer({ canvas: this.canvas[0], alpha: true });
|
||||
}
|
||||
|
||||
// initialize render size for current canvas size
|
||||
this.renderer.setSize(this.wrapper.width() * 2, this.wrapper.height() * 2);
|
||||
|
||||
// load the model including materials
|
||||
var model_file = useWebGLRenderer ? mixerList[CONFIG.multiType - 1].model : 'fallback';
|
||||
|
||||
// Temporary workaround for 'custom' model until akfreak's custom model is merged.
|
||||
if (model_file == 'custom') { model_file = 'fallback'; }
|
||||
|
||||
// setup scene
|
||||
this.scene = new THREE.Scene();
|
||||
|
||||
// modelWrapper adds an extra axis of rotation to avoid gimbal lock with the euler angles
|
||||
this.modelWrapper = new THREE.Object3D();
|
||||
|
||||
// stationary camera
|
||||
this.camera = new THREE.PerspectiveCamera(60, this.wrapper.width() / this.wrapper.height(), 1, 10000);
|
||||
|
||||
// move camera away from the model
|
||||
this.camera.position.z = 125;
|
||||
|
||||
// some light
|
||||
var light = new THREE.AmbientLight(0x404040);
|
||||
var light2 = new THREE.DirectionalLight(new THREE.Color(1, 1, 1), 1.5);
|
||||
light2.position.set(0, 1, 0);
|
||||
|
||||
// add camera, model, light to the foreground scene
|
||||
this.scene.add(light);
|
||||
this.scene.add(light2);
|
||||
this.scene.add(this.camera);
|
||||
this.scene.add(this.modelWrapper);
|
||||
|
||||
// Load model file, add to scene and render it
|
||||
this.loadJSON(model_file, (function (model) {
|
||||
this.model = model;
|
||||
|
||||
this.modelWrapper.add(model);
|
||||
this.scene.add(this.modelWrapper);
|
||||
|
||||
this.render();
|
||||
}).bind(this));
|
||||
};
|
||||
|
||||
Model.prototype.loadJSON = function (model_file, callback) {
|
||||
var loader = new THREE.JSONLoader();
|
||||
|
||||
loader.load('./resources/models/' + model_file + '.json', function (geometry, materials) {
|
||||
var modelMaterial = new THREE.MeshFaceMaterial(materials),
|
||||
model = new THREE.Mesh(geometry, modelMaterial);
|
||||
|
||||
model.scale.set(15, 15, 15);
|
||||
|
||||
callback(model);
|
||||
});
|
||||
};
|
||||
|
||||
Model.prototype.canUseWebGLRenderer = function () {
|
||||
// webgl capability detector
|
||||
// it would seem the webgl "enabling" through advanced settings will be ignored in the future
|
||||
// and webgl will be supported if gpu supports it by default (canary 40.0.2175.0), keep an eye on this one
|
||||
var detector_canvas = document.createElement('canvas');
|
||||
|
||||
return window.WebGLRenderingContext && (detector_canvas.getContext('webgl') || detector_canvas.getContext('experimental-webgl'))
|
||||
};
|
||||
|
||||
Model.prototype.rotateTo = function (x, y, z) {
|
||||
if (!this.model) { return; }
|
||||
|
||||
this.model.rotation.x = x;
|
||||
this.modelWrapper.rotation.y = y;
|
||||
this.model.rotation.z = z;
|
||||
|
||||
this.render();
|
||||
};
|
||||
|
||||
Model.prototype.rotateBy = function (x, y, z) {
|
||||
if (!this.model) { return; }
|
||||
|
||||
this.model.rotateX(x);
|
||||
this.model.rotateY(y);
|
||||
this.model.rotateZ(z);
|
||||
|
||||
this.render();
|
||||
};
|
||||
|
||||
Model.prototype.render = function () {
|
||||
if (!this.model) { return; }
|
||||
|
||||
// draw
|
||||
this.renderer.render(this.scene, this.camera);
|
||||
};
|
||||
|
||||
// handle canvas resize
|
||||
Model.prototype.resize = function () {
|
||||
this.renderer.setSize(this.wrapper.width() * 2, this.wrapper.height() * 2);
|
||||
|
||||
this.camera.aspect = this.wrapper.width() / this.wrapper.height();
|
||||
this.camera.updateProjectionMatrix();
|
||||
|
||||
this.render();
|
||||
};
|
||||
|
|
|
@ -177,11 +177,6 @@
|
|||
border-top-right-radius: 3px;
|
||||
}
|
||||
|
||||
.tab-pid_tuning .tpa {
|
||||
/*border: 0px solid #ccc; */
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.tab-pid_tuning .rc_curve {
|
||||
float: right;
|
||||
width: calc(100% - 2px); /* - ( "virtual" margin) */
|
||||
|
@ -580,3 +575,21 @@
|
|||
margin-top: -28px;
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
.tab-pid_tuning .rates_preview_cell {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 0;
|
||||
padding-bottom: 100%;
|
||||
}
|
||||
|
||||
.tab-pid_tuning .rates_preview {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-image: url(../images/paper.jpg);
|
||||
background-size: 100%;
|
||||
background-position: center;
|
||||
}
|
||||
|
|
|
@ -199,50 +199,74 @@
|
|||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="cf_column half topspacer">
|
||||
<div>
|
||||
<table class="rc_curve cf">
|
||||
<thead>
|
||||
<tr>
|
||||
<th i18n="rcCurve"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
</tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="spacer" style="margin-top: 10px; margin-bottom: 10px;">
|
||||
<div class="pitch_roll_curve">
|
||||
<canvas height="120px" style="width: 100%; height: 100%"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="clear-both"></div>
|
||||
</div>
|
||||
<div class="topspacer">
|
||||
<table class="rc_yaw_curve cf">
|
||||
<thead>
|
||||
<tr>
|
||||
<th i18n="rcYawCurve"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
</tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="spacer" style="margin-top: 10px; margin-bottom: 10px;">
|
||||
<div class="yaw_curve">
|
||||
<canvas height="120px" style="width: 100%; height: 100%"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="clear-both"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="cf_column half topspacer">
|
||||
<table class="tpa cf">
|
||||
<thead>
|
||||
<tr>
|
||||
<th i18n="pidTuningRatesPreview"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="rates_preview_cell">
|
||||
<div class="rates_preview">
|
||||
<canvas id="canvas"></canvas>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="cf_column third_right">
|
||||
<div class="spacer_left">
|
||||
<table class="rc_curve cf">
|
||||
<thead>
|
||||
<tr>
|
||||
<th i18n="rcCurve"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
</tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="spacer" style="margin-top: 10px; margin-bottom: 10px;">
|
||||
<div class="pitch_roll_curve">
|
||||
<canvas height="120px" style="width: 100%; height: 100%"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="spacer_left topspacer">
|
||||
<table class="rc_yaw_curve cf">
|
||||
<thead>
|
||||
<tr>
|
||||
<th i18n="rcYawCurve"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
</tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="spacer" style="margin-top: 10px; margin-bottom: 10px;">
|
||||
<div class="yaw_curve">
|
||||
<canvas height="120px" style="width: 100%; height: 100%"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="spacer_left throttle topspacer">
|
||||
<div class="spacer_left throttle">
|
||||
<table class="cf">
|
||||
<thead>
|
||||
<tr>
|
||||
|
@ -259,15 +283,23 @@
|
|||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="spacer_left topspacer">
|
||||
<table class="tpa cf">
|
||||
<thead>
|
||||
<tr>
|
||||
<th i18n="receiverThrottleMid"></th>
|
||||
<th i18n="receiverThrottleExpo"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><input type="number" name="mid" step="0.01" min="0" max="1" /></td>
|
||||
<td><input type="number" name="expo" step="0.01" min="0" max="1" /></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="spacer_left topspacer">
|
||||
|
|
|
@ -315,7 +315,6 @@ TABS.pid_tuning.initialize = function (callback) {
|
|||
}
|
||||
});
|
||||
|
||||
|
||||
pid_and_rc_to_form();
|
||||
|
||||
var pidController_e = $('select[name="controller"]');
|
||||
|
@ -339,12 +338,12 @@ TABS.pid_tuning.initialize = function (callback) {
|
|||
{ name: "Float"},
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
for (var i = 0; i < pidControllerList.length; i++) {
|
||||
pidController_e.append('<option value="' + (i) + '">' + pidControllerList[i].name + '</option>');
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
var form_e = $('#pid-tuning');
|
||||
|
||||
if (GUI.canChangePidController) {
|
||||
|
@ -532,6 +531,13 @@ TABS.pid_tuning.initialize = function (callback) {
|
|||
}
|
||||
});
|
||||
|
||||
// Setup model for rates preview
|
||||
self.initRatesPreview();
|
||||
self.renderModel();
|
||||
|
||||
// enable RC data pulling for rates preview
|
||||
GUI.interval_add('receiver_pull', self.getRecieverData, true);
|
||||
|
||||
// status data pulled via separate timer with static speed
|
||||
GUI.interval_add('status_pull', function status_pull() {
|
||||
MSP.send_message(MSP_codes.MSP_STATUS);
|
||||
|
@ -541,8 +547,42 @@ TABS.pid_tuning.initialize = function (callback) {
|
|||
}
|
||||
};
|
||||
|
||||
TABS.pid_tuning.cleanup = function (callback) {
|
||||
if (callback) {
|
||||
callback();
|
||||
TABS.pid_tuning.getRecieverData = function () {
|
||||
MSP.send_message(MSP_codes.MSP_RC, false, false);
|
||||
};
|
||||
|
||||
TABS.pid_tuning.initRatesPreview = function () {
|
||||
this.keepRendering = true;
|
||||
this.model = new Model($('.rates_preview'), $('.rates_preview canvas'));
|
||||
|
||||
var scale = d3.scale.linear().domain([900, 2100]);
|
||||
|
||||
this.rollScale = scale.range([Math.PI * 2, -Math.PI * 2]);
|
||||
this.pitchScale = scale.range([Math.PI * 2, -Math.PI * 2]);
|
||||
this.yawScale = scale.range([Math.PI * 2, -Math.PI * 2]);
|
||||
|
||||
$(window).on('resize', $.proxy(this.model.resize, this.model));
|
||||
};
|
||||
|
||||
TABS.pid_tuning.renderModel = function () {
|
||||
if (this.keepRendering) { requestAnimationFrame(this.renderModel.bind(this)); }
|
||||
|
||||
if (!this.clock) { this.clock = new THREE.Clock(); }
|
||||
|
||||
if (RC.channels[0] && RC.channels[1] && RC.channels[2]) {
|
||||
var delta = this.clock.getDelta(),
|
||||
roll = delta * this.rollScale(RC.channels[0]),
|
||||
pitch = delta * this.pitchScale(RC.channels[1]),
|
||||
yaw = delta * this.yawScale(RC.channels[2]);
|
||||
|
||||
this.model.rotateBy(pitch, yaw, roll);
|
||||
}
|
||||
};
|
||||
|
||||
TABS.pid_tuning.cleanup = function (callback) {
|
||||
$(window).off('resize', $.proxy(this.model.resize, this.model));
|
||||
|
||||
this.keepRendering = false;
|
||||
|
||||
if (callback) callback();
|
||||
};
|
||||
|
|
110
tabs/setup.js
110
tabs/setup.js
|
@ -43,8 +43,9 @@ TABS.setup.initialize = function (callback) {
|
|||
|
||||
GUI.log(chrome.i18n.getMessage('initialSetupBackupAndRestoreApiVersion', [CONFIG.apiVersion, CONFIGURATOR.backupRestoreMinApiVersionAccepted]));
|
||||
}
|
||||
// initialize 3D
|
||||
self.initialize3D();
|
||||
|
||||
// initialize 3D Model
|
||||
self.initModel();
|
||||
|
||||
// set roll in interactive block
|
||||
$('span.roll').text(chrome.i18n.getMessage('initialSetupAttitude', [0]));
|
||||
|
@ -191,7 +192,8 @@ TABS.setup.initialize = function (callback) {
|
|||
roll_e.text(chrome.i18n.getMessage('initialSetupAttitude', [SENSOR_DATA.kinematics[0]]));
|
||||
pitch_e.text(chrome.i18n.getMessage('initialSetupAttitude', [SENSOR_DATA.kinematics[1]]));
|
||||
heading_e.text(chrome.i18n.getMessage('initialSetupAttitude', [SENSOR_DATA.kinematics[2]]));
|
||||
self.render3D();
|
||||
|
||||
self.renderModel();
|
||||
self.updateInstruments();
|
||||
});
|
||||
}
|
||||
|
@ -215,104 +217,22 @@ TABS.setup.initializeInstruments = function() {
|
|||
};
|
||||
};
|
||||
|
||||
TABS.setup.initialize3D = function (compatibility) {
|
||||
var self = this,
|
||||
loader, canvas, wrapper, renderer, camera, scene, light, light2, modelWrapper, model, model_file,
|
||||
useWebGlRenderer = false;
|
||||
TABS.setup.initModel = function () {
|
||||
this.model = new Model($('.model-and-info #canvas_wrapper'), $('.model-and-info #canvas'));
|
||||
|
||||
canvas = $('.model-and-info #canvas');
|
||||
wrapper = $('.model-and-info #canvas_wrapper');
|
||||
$(window).on('resize', $.proxy(this.model.resize, this.model));
|
||||
};
|
||||
|
||||
// webgl capability detector
|
||||
// it would seem the webgl "enabling" through advanced settings will be ignored in the future
|
||||
// and webgl will be supported if gpu supports it by default (canary 40.0.2175.0), keep an eye on this one
|
||||
var detector_canvas = document.createElement('canvas');
|
||||
if (window.WebGLRenderingContext && (detector_canvas.getContext('webgl') || detector_canvas.getContext('experimental-webgl'))) {
|
||||
renderer = new THREE.WebGLRenderer({canvas: canvas.get(0), alpha: true, antialias: true});
|
||||
useWebGlRenderer = true;
|
||||
} else {
|
||||
renderer = new THREE.CanvasRenderer({canvas: canvas.get(0), alpha: true});
|
||||
}
|
||||
// initialize render size for current canvas size
|
||||
renderer.setSize(wrapper.width()*2, wrapper.height()*2);
|
||||
TABS.setup.renderModel = function () {
|
||||
var x = (SENSOR_DATA.kinematics[1] * -1.0) * 0.017453292519943295,
|
||||
y = ((SENSOR_DATA.kinematics[2] * -1.0) - this.yaw_fix) * 0.017453292519943295,
|
||||
z = (SENSOR_DATA.kinematics[0] * -1.0) * 0.017453292519943295;
|
||||
|
||||
|
||||
// // modelWrapper adds an extra axis of rotation to avoid gimbal lock with the euler angles
|
||||
modelWrapper = new THREE.Object3D()
|
||||
//
|
||||
// load the model including materials
|
||||
if (useWebGlRenderer) {
|
||||
model_file = mixerList[CONFIG.multiType - 1].model;
|
||||
} else {
|
||||
model_file = 'fallback'
|
||||
}
|
||||
|
||||
// Temporary workaround for 'custom' model until akfreak's custom model is merged.
|
||||
var useLegacyCustomModel = false;
|
||||
if (model_file == 'custom') {
|
||||
model_file = 'fallback';
|
||||
useLegacyCustomModel = true;
|
||||
}
|
||||
|
||||
// setup scene
|
||||
scene = new THREE.Scene();
|
||||
|
||||
loader = new THREE.JSONLoader();
|
||||
loader.load('./resources/models/' + model_file + '.json', function (geometry, materials) {
|
||||
var modelMaterial = new THREE.MeshFaceMaterial(materials);
|
||||
model = new THREE.Mesh(geometry, modelMaterial);
|
||||
|
||||
model.scale.set(15, 15, 15);
|
||||
|
||||
modelWrapper.add(model);
|
||||
scene.add(modelWrapper);
|
||||
});
|
||||
|
||||
// stationary camera
|
||||
camera = new THREE.PerspectiveCamera(50, wrapper.width() / wrapper.height(), 1, 10000);
|
||||
|
||||
// some light
|
||||
light = new THREE.AmbientLight(0x404040);
|
||||
light2 = new THREE.DirectionalLight(new THREE.Color(1, 1, 1), 1.5);
|
||||
light2.position.set(0, 1, 0);
|
||||
|
||||
// move camera away from the model
|
||||
camera.position.z = 125;
|
||||
|
||||
// add camera, model, light to the foreground scene
|
||||
scene.add(light);
|
||||
scene.add(light2);
|
||||
scene.add(camera);
|
||||
scene.add(modelWrapper);
|
||||
|
||||
this.render3D = function () {
|
||||
if (!model) {
|
||||
return;
|
||||
}
|
||||
|
||||
// compute the changes
|
||||
model.rotation.x = (SENSOR_DATA.kinematics[1] * -1.0) * 0.017453292519943295;
|
||||
modelWrapper.rotation.y = ((SENSOR_DATA.kinematics[2] * -1.0) - self.yaw_fix) * 0.017453292519943295;
|
||||
model.rotation.z = (SENSOR_DATA.kinematics[0] * -1.0) * 0.017453292519943295;
|
||||
|
||||
// draw
|
||||
renderer.render(scene, camera);
|
||||
};
|
||||
|
||||
// handle canvas resize
|
||||
this.resize3D = function () {
|
||||
renderer.setSize(wrapper.width()*2, wrapper.height()*2);
|
||||
camera.aspect = wrapper.width() / wrapper.height();
|
||||
camera.updateProjectionMatrix();
|
||||
|
||||
self.render3D();
|
||||
};
|
||||
|
||||
$(window).on('resize', this.resize3D);
|
||||
this.model.rotateTo(x, y, z);
|
||||
};
|
||||
|
||||
TABS.setup.cleanup = function (callback) {
|
||||
$(window).off('resize', this.resize3D);
|
||||
$(window).off('resize', $.proxy(this.model.resize, this.model));
|
||||
|
||||
if (callback) callback();
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue