mirror of
https://github.com/betaflight/betaflight-configurator.git
synced 2025-07-24 00:35:26 +03:00
Merge branch 'development'
This commit is contained in:
commit
716457b0ed
51 changed files with 2251 additions and 1492 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,2 +1,3 @@
|
|||
.DS_store
|
||||
nbproject/
|
||||
|
||||
|
|
|
@ -211,7 +211,7 @@
|
|||
"message": "Request Optional Permissions"
|
||||
},
|
||||
"defaultWelcomeText": {
|
||||
"message": "Welcome to <strong>Cleanflight - Configurator</strong>, a utility designed to simplify updating, configuring and tuning of your flight controller.<br /><br />The application supports all hardware that can run cleanflight (<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=\"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://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/PrestaShop/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/cleanflight/cleanflight\" title=\"www.github.com\" target=\"_blank\">here</a><br />The newest binary firmware image is available <a href=\"https://github.com/cleanflight/cleanflight/releases\" title=\"www.github.com\" 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 />"
|
||||
"message": "Welcome to <strong>Cleanflight - Configurator</strong>, a utility designed to simplify updating, configuring and tuning of your flight controller.<br /><br />The application supports all hardware that can run cleanflight (<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/PrestaShop/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/cleanflight/cleanflight\" title=\"www.github.com\" target=\"_blank\">here</a><br />The newest binary firmware image is available <a href=\"https://github.com/cleanflight/cleanflight/releases\" title=\"www.github.com\" target=\"_blank\">here</a>, development builds available <a href=\"http://cleanflight.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 />"
|
||||
},
|
||||
"defaultContributingHead": {
|
||||
"message": "Contributing"
|
||||
|
@ -372,8 +372,8 @@
|
|||
"initialSetupModel": {
|
||||
"message": "Model: $1"
|
||||
},
|
||||
"initialSetupHeading": {
|
||||
"message": "Heading: $1 deg"
|
||||
"initialSetupAttitude": {
|
||||
"message": "$1 deg"
|
||||
},
|
||||
"initialSetupAccelCalibStarted": {
|
||||
"message": "Accelerometer calibration started"
|
||||
|
@ -426,6 +426,10 @@
|
|||
"configurationFeaturesHelp": {
|
||||
"message": "<strong>Note:</strong> Not all combinations of features are valid. When the flight controller firmware detects invalid feature combinations conflicting features will be disabled.<br /><strong>Note:</strong> Configure serial ports <span style=\"color: red\">before</span> enabling the features that will use the ports."
|
||||
},
|
||||
|
||||
"configurationSerialRXHelp": {
|
||||
"message": "<strong>Note:</strong> Rememer to configure a Serial Port (via Ports tab) and choose a Serial Receiver Provider when using RX_SERIAL feature."
|
||||
},
|
||||
|
||||
"configurationBoardAlignment": {
|
||||
"message": "Board Alignment"
|
||||
|
@ -499,6 +503,18 @@
|
|||
"configurationBatteryMultiwiiCurrent": {
|
||||
"message": "Enable support for legacy Multiwii MSP current output"
|
||||
},
|
||||
"configurationSystem": {
|
||||
"message": "System configuration"
|
||||
},
|
||||
"configurationLoopTime": {
|
||||
"message": "Flight Controller Loop Time"
|
||||
},
|
||||
"configurationCalculatedCyclesSec": {
|
||||
"message": "Cycles/Sec (Hz)"
|
||||
},
|
||||
"configurationLoopTimeHelp": {
|
||||
"message": "<strong>Note:</strong> Changing this may require PID re-tuning."
|
||||
},
|
||||
"configurationGPS": {
|
||||
"message": "GPS"
|
||||
},
|
||||
|
@ -511,6 +527,10 @@
|
|||
"configurationGPSubxSbas": {
|
||||
"message": "Ground Assistance Type"
|
||||
},
|
||||
"configurationGPSHelp": {
|
||||
"message": "<strong>Note:</strong> Remember to configure a Serial Port (via Ports tab) when using GPS feature."
|
||||
},
|
||||
|
||||
"configurationSerialRX": {
|
||||
"message": "Serial Receiver Provider"
|
||||
},
|
||||
|
@ -522,7 +542,10 @@
|
|||
},
|
||||
|
||||
"portsHelp": {
|
||||
"message": "Configure serial ports. <strong>Note:</strong> not all combinations are valid. When the flight controller firmware detects this the serial port configuration will be reset."
|
||||
"message": "<strong>Note:</strong> not all combinations are valid. When the flight controller firmware detects this the serial port configuration will be reset."
|
||||
},
|
||||
"portsMSPHelp": {
|
||||
"message": "<strong>Note:</strong> Do <span style=\"color: red\">NOT</span> disable MSP on the first serial port unless you know what you are doing. You may have to reflash and erase your configuration if you do."
|
||||
},
|
||||
"portsFirmwareUpgradeRequired": {
|
||||
"message": "Firmware upgrade <span style=\"color: red\">required</span>. Serial port configurations of firmware < 1.8.0 is not supported."
|
||||
|
@ -613,6 +636,9 @@
|
|||
"message": "EEPROM <span style=\"color: green\">saved</span>"
|
||||
},
|
||||
|
||||
"receiverHelp": {
|
||||
"message": "Please read receiver chapter of the documentation. Configure serial port (if required), receiver mode (serial/ppm/pwm), provider (for serial receivers), bind receiver, set channel map, configure channel endpoints/range on TX so that all channels go from ~1000 to ~2000. Set midpoint (default 1500), trim channels to 1500, configure stick deadband, verify behaviour when TX is off or out of range.<br /><span style=\"color: red\">IMPORTANT:</span> Before flying read failsafe chapter of documentation and configure failsafe."
|
||||
},
|
||||
"receiverThrottleMid": {
|
||||
"message": "Throttle MID"
|
||||
},
|
||||
|
@ -646,6 +672,9 @@
|
|||
"receiverButtonRefresh": {
|
||||
"message": "Refresh"
|
||||
},
|
||||
"receiverButtonSticks": {
|
||||
"message": "Control sticks"
|
||||
},
|
||||
"receiverDataRefreshed": {
|
||||
"message": "RC Tuning data <strong>refreshed</strong>"
|
||||
},
|
||||
|
@ -791,15 +820,13 @@
|
|||
},
|
||||
|
||||
|
||||
"servosModel": {
|
||||
"message": "Model:"
|
||||
"servosFirmwareUpgradeRequired": {
|
||||
"message": "Servos requires firmware >= 1.10.0."
|
||||
},
|
||||
|
||||
"servosChangeDirection": {
|
||||
"message": "Change Direction in TX To Match"
|
||||
},
|
||||
"servosGyroAccelDirection": {
|
||||
"message": "Gyroscope / Accelerometer Direction"
|
||||
},
|
||||
"servosName": {
|
||||
"message": "Name"
|
||||
},
|
||||
|
@ -812,8 +839,14 @@
|
|||
"servosMax": {
|
||||
"message": "MAX"
|
||||
},
|
||||
"servosDirection": {
|
||||
"message": "Direction"
|
||||
"servosAngleAtMin": {
|
||||
"message": "Angle at min"
|
||||
},
|
||||
"servosAngleAtMax": {
|
||||
"message": "Angle at max"
|
||||
},
|
||||
"servosDirectionAndRate": {
|
||||
"message": "Direction and rate"
|
||||
},
|
||||
"servosLiveMode": {
|
||||
"message": "Enable Live mode:"
|
||||
|
@ -821,9 +854,6 @@
|
|||
"servosButtonSave": {
|
||||
"message": "Save"
|
||||
},
|
||||
"servosModelNoSupport": {
|
||||
"message": "This model doesn't support servos"
|
||||
},
|
||||
"servosNormal": {
|
||||
"message": "Normal"
|
||||
},
|
||||
|
@ -1042,7 +1072,7 @@
|
|||
"message": "Attempt to flash the board automatically (triggered by newly detected serial port)"
|
||||
},
|
||||
"firmwareFlasherFullChipErase": {
|
||||
"message": "Full Chip Erase"
|
||||
"message": "Full chip erase"
|
||||
},
|
||||
"firmwareFlasherFullChipEraseDescription": {
|
||||
"message": "Wipes all configuration data currently stored on the board"
|
||||
|
@ -1054,7 +1084,7 @@
|
|||
"message": "Flash most recent (untested) development firmware"
|
||||
},
|
||||
"firmwareFlasherManualBaud": {
|
||||
"message": "Manual Baud Rate"
|
||||
"message": "Manual baud rate"
|
||||
},
|
||||
"firmwareFlasherManualBaudDescription": {
|
||||
"message": "Manual selection of baud rate for boards that don't support the default speed or for flashing via bluetooth."
|
||||
|
@ -1099,7 +1129,7 @@
|
|||
"message": "Warning"
|
||||
},
|
||||
"firmwareFlasherWarningText": {
|
||||
"message": "Please do not try to flash <strong>non-cleanflight</strong> hardware with this firmware flasher (it wont work).<br />Do not <strong>disconnect</strong> the board or <strong>turn off</strong> your computer while flashing.<br /><br />Note: <strong>STM32</strong> bootloader is stored in <strong>ROM</strong>, it cannot be bricked.<br />Note: <strong>Auto-Connect</strong> is always disabled while you are inside firmware flasher.<br />Note: This can wipe your configuration including but not limited to PIDs, Auxiliary, and FEATURES. Make sure you have a backup.<br />"
|
||||
"message": "Please do <span style=\"color: red\">not</span> try to flash <strong>non-cleanflight</strong> hardware with this firmware flasher.<br />Do <span style=\"color: red\">not</span> <strong>disconnect</strong> the board or <strong>turn off</strong> your computer while flashing.<br /><br /><span style=\"color: green\">Note: </span>STM32 bootloader is stored in ROM, it cannot be bricked.<br />Note: <strong>Auto-Connect</strong> is always disabled while you are inside firmware flasher.<br /><span style=\"color: red\">Note: </span>Make sure you have a backup; some upgrades/downgrades will wipe your configuration.<br /><span style=\"color: green\">Note:</span> If you have problems flashing try disconnecting all cables from your FC.<br /><br /><span style=\"color: green\">Note: </span>If you have lost comminication with your board then power off the board, jumper the bootloader pins, power on, enable 'No reboot sequence', enable 'Full chip erase', re-flash, then power off, remove bootloader jumper, power on and connect (For all firmware except OPBL firmware)."
|
||||
},
|
||||
"firmwareFlasherButtonLeave": {
|
||||
"message": "Leave Firmware Flasher"
|
||||
|
@ -1125,5 +1155,41 @@
|
|||
},
|
||||
"ledStripEepromSaved": {
|
||||
"message": "EEPROM <span style=\"color: green\">saved</span>"
|
||||
},
|
||||
"controlAxisRoll": {
|
||||
"message": "Roll"
|
||||
},
|
||||
"controlAxisPitch": {
|
||||
"message": "Pitch"
|
||||
},
|
||||
"controlAxisYaw": {
|
||||
"message": "Yaw"
|
||||
},
|
||||
"controlAxisThrottle": {
|
||||
"message": "Throttle"
|
||||
},
|
||||
"controlAxisAux1": {
|
||||
"message": "AUX 1"
|
||||
},
|
||||
"controlAxisAux2": {
|
||||
"message": "AUX 2"
|
||||
},
|
||||
"controlAxisAux3": {
|
||||
"message": "AUX 3"
|
||||
},
|
||||
"controlAxisAux4": {
|
||||
"message": "AUX 4"
|
||||
},
|
||||
"controlAxisAux5": {
|
||||
"message": "AUX 5"
|
||||
},
|
||||
"controlAxisAux6": {
|
||||
"message": "AUX 6"
|
||||
},
|
||||
"controlAxisAux7": {
|
||||
"message": "AUX 7"
|
||||
},
|
||||
"controlAxisAux8": {
|
||||
"message": "AUX 8"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,3 +1,12 @@
|
|||
<span>2015.10.31 - 0.66.0 - cleanflight</span>
|
||||
<p>
|
||||
- Update servo configuration (requires firmware >= 1.10.0).<br />
|
||||
- Add some notes and help messages for common issues.<br />
|
||||
- Update sponsors panel and add links to new boards.<br />
|
||||
- Upgrade some JS libraries to latest versions (Three, JQuery/UI, D3)<br />
|
||||
- Allow stick input from UI (when using RX_MSP)<br />
|
||||
- Align servo numbering with firmware and documentation<br />
|
||||
</p>
|
||||
<span>2015.05.23 - 0.65.0 - cleanflight</span>
|
||||
<p>
|
||||
- Support flashing of the SPRacingF3.<br />
|
||||
|
@ -23,10 +32,10 @@
|
|||
</p>
|
||||
<span>2015.03.29 - 0.63.0 - cleanflight</span>
|
||||
<p>
|
||||
- Configuration tab supports auto_disarm_delay and disarm_kill_switch - Requires 1.8.0 firmware.<br />
|
||||
- PID Tuning tab allows TPA Breakpoint changes - Requires 1.8.0 firmware.<br />
|
||||
- Corrected Artificial Horizon Pitch/Roll views.<br />
|
||||
- Changed logging time stamp to include date stamp.<br />
|
||||
- Configuration tab supports auto_disarm_delay and disarm_kill_switch (requires firmware >= 1.8.0).<br />
|
||||
- PID Tuning tab allows TPA Breakpoint changes (requires firmware >= 1.8.0).<br />
|
||||
- Correct Artificial Horizon Pitch/Roll views.<br />
|
||||
- Change logging time stamp to include date stamp.<br />
|
||||
- Support new firmware 1.8 serial port configuration.<br />
|
||||
- Move documentation and help to new tab.<br />
|
||||
- Add contributing section to welcome tab.<br />
|
||||
|
@ -38,7 +47,7 @@
|
|||
<span>2015.02.26 - 0.62.0 - cleanflight</span>
|
||||
<p>
|
||||
- Add flight indicators to setup screen tab.<br />
|
||||
- Add dataflash tab. Requires 1.8.0 firmware.<br />
|
||||
- Add dataflash tab (requires firmware >= 1.8.0)..<br />
|
||||
- Add Cleanflight logos.<br />
|
||||
- Fix loading online flash files - github moved them to amazon aws.<br />
|
||||
- Fix to fallback 3D model.<br />
|
||||
|
@ -46,7 +55,7 @@
|
|||
</p>
|
||||
<span>2015.02.03 - 0.61.0 - cleanflight</span>
|
||||
<p>
|
||||
- Support changing PID controller - there new PID controllers in 1.7.0 firmware.<br />
|
||||
- Support changing PID controller - three new PID controllers in 1.7.0 firmware.<br />
|
||||
- Support for LED thrust ring.<br />
|
||||
- Support for LED colors.<br />
|
||||
- Support for displaying sonar sensor reading on the sensors tab.<br />
|
||||
|
@ -54,21 +63,21 @@
|
|||
- New Logo. (Tom McCullough)<br />
|
||||
- New 3D models (AkFreak).<br />
|
||||
- Update presentation of LEDs that have multiple functions.<br />
|
||||
- Added Documentation and Support panels to welcome tab.<br />
|
||||
- Add Documentation and Support panels to welcome tab.<br />
|
||||
- Add support for backup and restore of LED strip configuration.<br />
|
||||
- Fix for disappearing tabs in chrome 41 beta.<br />
|
||||
- Various other minor improvements.<br />
|
||||
</p>
|
||||
<span>2015.01.08 - 0.60.0 - cleanflight</span>
|
||||
<p>
|
||||
- Add LED strip tab for LED configuration - requires v1.6.0 firmware to save.<br />
|
||||
- Add LED strip tab for LED configuration (requires firmware >= 1.6.0)..<br />
|
||||
- Replace motor order images (stronnag)<br />
|
||||
</p>
|
||||
<span>2015.01.08 - 0.59.1 - cleanflight</span>
|
||||
<p>
|
||||
- Add support for Blackbox flight recorder feature (requires v1.5.0 firmware).<br />
|
||||
- Add support for Blackbox flight recorder feature (requires firmware >= 1.5.0).<br />
|
||||
- Update RSSI channel section to allow any channel.<br />
|
||||
- Implemented configuration migration to aid with backwards compatibility.<br />
|
||||
- Implement configuration migration to aid with backwards compatibility.<br />
|
||||
- Allow CLI access when connecting firmware with an out-of-date API.<br />
|
||||
- Support 'release candidate' and 'stable' releases.
|
||||
</p>
|
||||
|
@ -88,7 +97,7 @@
|
|||
<span>2014.12.06 - 0.57.1 - cleanflight</span>
|
||||
<p>
|
||||
- Latest firmware <strong>required</strong>.<br />
|
||||
- Merged latest baseflight configurator changes.<br />
|
||||
- Merge latest baseflight configurator changes.<br />
|
||||
- Added support for choosing and downloading firmware via the github relases API.<br />
|
||||
- Added Armattan Quads as a sponsor.<br />
|
||||
- Various UI tweaks.<br />
|
||||
|
@ -96,17 +105,17 @@
|
|||
<span>2014.12.06 - 0.57</span>
|
||||
<p>
|
||||
- Firmware flasher now contains firmware builds picker<br />
|
||||
- Implemented new and experimental review mechanism<br />
|
||||
- Implement new and experimental review mechanism<br />
|
||||
- Support for new A-tail Quad craft type<br />
|
||||
- Firmware flasher flashing speed optimizations<br />
|
||||
- Added specific 3D models for atail/vtail quad (norem)<br />
|
||||
- Add specific 3D models for atail/vtail quad (norem)<br />
|
||||
- Major bugfix for stuck UI after delayed port open procedure<br />
|
||||
- Bugfix for GPS distance to home not displaying<br />
|
||||
- Bugfix for backup/restore misbehaving (mostly on OSX)<br />
|
||||
</p>
|
||||
<span>2014.11.04 - 0.56</span>
|
||||
<p>
|
||||
- Added hex plus, hex X, tri, y4, y6 3D models (jef79m)<br />
|
||||
- Add hex plus, hex X, tri, y4, y6 3D models (jef79m)<br />
|
||||
- Bugfix for battery voltage saving sequence<br />
|
||||
- Bugfix for fetching development firmware<br />
|
||||
</p>
|
||||
|
@ -116,9 +125,9 @@
|
|||
- Minimum accepted firmware version set to 2.31<br />
|
||||
- Support for flashing development firmware<br />
|
||||
- Setup tab performance improvements, faster 3D model<br />
|
||||
- Strongly improved amount of data stored in backups<br />
|
||||
- Improved flash on connect in firmware flasher<br />
|
||||
- Rearranged texts and options in firmware flasher<br />
|
||||
- Strongly improve amount of data stored in backups<br />
|
||||
- Improve flash on connect in firmware flasher<br />
|
||||
- Rearrange texts and options in firmware flasher<br />
|
||||
- Bugfix for corrupted minimum window size on Windows 7<br />
|
||||
- Bugfix for incorrect date & time in firmware flasher<br />
|
||||
- Bugfix for port handler firing before port being initialized<br />
|
||||
|
|
|
@ -30,12 +30,21 @@ function configuration_backup(callback) {
|
|||
MSP_codes.MSP_PID,
|
||||
MSP_codes.MSP_RC_TUNING,
|
||||
MSP_codes.MSP_ACC_TRIM,
|
||||
MSP_codes.MSP_SERVO_CONF,
|
||||
MSP_codes.MSP_CHANNEL_FORWARDING,
|
||||
MSP_codes.MSP_SERVO_CONFIGURATIONS,
|
||||
MSP_codes.MSP_MODE_RANGES,
|
||||
MSP_codes.MSP_ADJUSTMENT_RANGES
|
||||
];
|
||||
|
||||
function update_profile_specific_data_list() {
|
||||
if (semver.lt(CONFIG.apiVersion, "1.12.0")) {
|
||||
profileSpecificData.push(MSP_codes.MSP_CHANNEL_FORWARDING);
|
||||
} else {
|
||||
profileSpecificData.push(MSP_codes.MSP_SERVO_MIX_RULES);
|
||||
}
|
||||
}
|
||||
|
||||
update_profile_specific_data_list();
|
||||
|
||||
function fetch_specific_data() {
|
||||
var fetchingProfile = 0,
|
||||
codeKey = 0;
|
||||
|
@ -54,6 +63,7 @@ function configuration_backup(callback) {
|
|||
'RC': jQuery.extend(true, {}, RC_tuning),
|
||||
'AccTrim': jQuery.extend(true, [], CONFIG.accelerometerTrims),
|
||||
'ServoConfig': jQuery.extend(true, [], SERVO_CONFIG),
|
||||
'ServoRules': jQuery.extend(true, [], SERVO_RULES),
|
||||
'ModeRanges': jQuery.extend(true, [], MODE_RANGES),
|
||||
'AdjustmentRanges': jQuery.extend(true, [], ADJUSTMENT_RANGES)
|
||||
});
|
||||
|
@ -428,6 +438,38 @@ function configuration_restore(callback) {
|
|||
}
|
||||
}
|
||||
|
||||
if (semver.lt(migratedVersion, '0.66.0')) {
|
||||
// api 1.12 updated servo configuration protocol and added servo mixer rules
|
||||
for (var profileIndex = 0; i < configuration.profiles.length; i++) {
|
||||
|
||||
if (semver.eq(configuration.apiVersion, '1.10.0')) {
|
||||
// drop two unused servo configurations
|
||||
while (configuration.profiles[profileIndex].ServoConfig.length > 8) {
|
||||
configuration.profiles[profileIndex].ServoConfig.pop();
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 0; i < configuration.profiles[profileIndex].ServoConfig.length; i++) {
|
||||
var servoConfig = profiles[profileIndex].ServoConfig;
|
||||
|
||||
servoConfig[i].angleAtMin = 90;
|
||||
servoConfig[i].angleAtMax = 90;
|
||||
servoConfig[i].reversedInputSources = 0;
|
||||
|
||||
// set the rate to 0 if an invalid value is detected.
|
||||
if (servoConfig[i].rate < -100 || servoConfig[i].rate > 100) {
|
||||
servoConfig[i].rate = 0;
|
||||
}
|
||||
}
|
||||
|
||||
configuration.profiles[profileIndex].ServoRules = [];
|
||||
}
|
||||
|
||||
migratedVersion = '0.66.0';
|
||||
|
||||
appliedMigrationsCount++;
|
||||
}
|
||||
|
||||
if (appliedMigrationsCount > 0) {
|
||||
GUI.log(chrome.i18n.getMessage('configMigrationSuccessful', [appliedMigrationsCount]));
|
||||
}
|
||||
|
@ -444,9 +486,7 @@ function configuration_restore(callback) {
|
|||
MSP_codes.MSP_SET_PID_CONTROLLER,
|
||||
MSP_codes.MSP_SET_PID,
|
||||
MSP_codes.MSP_SET_RC_TUNING,
|
||||
MSP_codes.MSP_SET_ACC_TRIM,
|
||||
MSP_codes.MSP_SET_SERVO_CONF,
|
||||
MSP_codes.MSP_SET_CHANNEL_FORWARDING
|
||||
MSP_codes.MSP_SET_ACC_TRIM
|
||||
];
|
||||
|
||||
MSP.send_message(MSP_codes.MSP_STATUS, false, false, function () {
|
||||
|
@ -472,6 +512,7 @@ function configuration_restore(callback) {
|
|||
RC_tuning = configuration.profiles[profile].RC;
|
||||
CONFIG.accelerometerTrims = configuration.profiles[profile].AccTrim;
|
||||
SERVO_CONFIG = configuration.profiles[profile].ServoConfig;
|
||||
SERVO_RULES = configuration.profiles[profile].ServoRules;
|
||||
MODE_RANGES = configuration.profiles[profile].ModeRanges;
|
||||
ADJUSTMENT_RANGES = configuration.profiles[profile].AdjustmentRanges;
|
||||
}
|
||||
|
@ -501,6 +542,14 @@ function configuration_restore(callback) {
|
|||
});
|
||||
}
|
||||
|
||||
function upload_servo_mix_rules() {
|
||||
MSP.sendServoMixRules(upload_servo_configuration);
|
||||
}
|
||||
|
||||
function upload_servo_configuration() {
|
||||
MSP.sendServoConfigurations(upload_mode_ranges);
|
||||
}
|
||||
|
||||
function upload_mode_ranges() {
|
||||
MSP.sendModeRanges(upload_adjustment_ranges);
|
||||
}
|
||||
|
@ -510,7 +559,7 @@ function configuration_restore(callback) {
|
|||
}
|
||||
// start uploading
|
||||
load_objects(0);
|
||||
upload_mode_ranges();
|
||||
upload_servo_configuration();
|
||||
}
|
||||
|
||||
function upload_unique_data() {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
var CONFIGURATOR = {
|
||||
'releaseDate': 1432389468227, // new Date().getTime() - Sat May 23 2015 14:57:54 GMT+0100 (BST)
|
||||
'releaseDate': 1446278768375, // new Date().getTime() - Fri Oct 02 2015 20:50:49 GMT+0100 (GMT Daylight Time)
|
||||
|
||||
// all versions are specified and compared using semantic versioning http://semver.org/
|
||||
'apiVersionAccepted': '1.2.0',
|
||||
|
@ -86,6 +86,7 @@ var MODE_RANGES = [];
|
|||
var ADJUSTMENT_RANGES = [];
|
||||
|
||||
var SERVO_CONFIG = [];
|
||||
var SERVO_RULES = [];
|
||||
|
||||
var SERIAL_CONFIG = {
|
||||
ports: [],
|
||||
|
|
6
js/libraries/d3.min.js
vendored
6
js/libraries/d3.min.js
vendored
File diff suppressed because one or more lines are too long
4
js/libraries/jquery-2.1.3.min.js
vendored
4
js/libraries/jquery-2.1.3.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
4
js/libraries/jquery-2.1.4.min.js
vendored
Normal file
4
js/libraries/jquery-2.1.4.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
js/libraries/jquery-2.1.4.min.map
Normal file
1
js/libraries/jquery-2.1.4.min.map
Normal file
File diff suppressed because one or more lines are too long
13
js/libraries/jquery-ui-1.11.4.min.js
vendored
Normal file
13
js/libraries/jquery-ui-1.11.4.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
|
@ -16,13 +16,13 @@ THREE.SpriteCanvasMaterial = function ( parameters ) {
|
|||
};
|
||||
|
||||
THREE.SpriteCanvasMaterial.prototype = Object.create( THREE.Material.prototype );
|
||||
THREE.SpriteCanvasMaterial.prototype.constructor = THREE.SpriteCanvasMaterial;
|
||||
|
||||
THREE.SpriteCanvasMaterial.prototype.clone = function () {
|
||||
|
||||
var material = new THREE.SpriteCanvasMaterial();
|
||||
|
||||
THREE.Material.prototype.clone.call( this, material );
|
||||
|
||||
material.copy( this );
|
||||
material.color.copy( this.color );
|
||||
material.program = this.program;
|
||||
|
||||
|
@ -58,12 +58,14 @@ THREE.CanvasRenderer = function ( parameters ) {
|
|||
_viewportWidth = _canvasWidth,
|
||||
_viewportHeight = _canvasHeight,
|
||||
|
||||
pixelRatio = 1,
|
||||
|
||||
_context = _canvas.getContext( '2d', {
|
||||
alpha: parameters.alpha === true
|
||||
} ),
|
||||
|
||||
_clearColor = new THREE.Color( 0x000000 ),
|
||||
_clearAlpha = 0,
|
||||
_clearAlpha = parameters.alpha === true ? 0 : 1,
|
||||
|
||||
_contextGlobalAlpha = 1,
|
||||
_contextGlobalCompositeOperation = 0,
|
||||
|
@ -122,12 +124,6 @@ THREE.CanvasRenderer = function ( parameters ) {
|
|||
|
||||
this.domElement = _canvas;
|
||||
|
||||
this.devicePixelRatio = parameters.devicePixelRatio !== undefined
|
||||
? parameters.devicePixelRatio
|
||||
: self.devicePixelRatio !== undefined
|
||||
? self.devicePixelRatio
|
||||
: 1;
|
||||
|
||||
this.autoClear = true;
|
||||
this.sortObjects = true;
|
||||
this.sortElements = true;
|
||||
|
@ -141,17 +137,43 @@ THREE.CanvasRenderer = function ( parameters ) {
|
|||
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
// WebGLRenderer compatibility
|
||||
|
||||
this.supportsVertexTextures = function () {};
|
||||
this.setFaceCulling = function () {};
|
||||
|
||||
// API
|
||||
|
||||
this.getContext = function () {
|
||||
|
||||
return _context;
|
||||
|
||||
};
|
||||
|
||||
this.getContextAttributes = function () {
|
||||
|
||||
return _context.getContextAttributes();
|
||||
|
||||
};
|
||||
|
||||
this.getPixelRatio = function () {
|
||||
|
||||
return pixelRatio;
|
||||
|
||||
};
|
||||
|
||||
this.setPixelRatio = function ( value ) {
|
||||
|
||||
if ( value !== undefined ) pixelRatio = value;
|
||||
|
||||
};
|
||||
|
||||
this.setSize = function ( width, height, updateStyle ) {
|
||||
|
||||
_canvasWidth = width * this.devicePixelRatio;
|
||||
_canvasHeight = height * this.devicePixelRatio;
|
||||
_canvasWidth = width * pixelRatio;
|
||||
_canvasHeight = height * pixelRatio;
|
||||
|
||||
_canvas.width = _canvasWidth;
|
||||
_canvas.height = _canvasHeight;
|
||||
|
@ -166,7 +188,7 @@ THREE.CanvasRenderer = function ( parameters ) {
|
|||
|
||||
}
|
||||
|
||||
_clipBox.min.set( -_canvasWidthHalf, -_canvasHeightHalf ),
|
||||
_clipBox.min.set( - _canvasWidthHalf, - _canvasHeightHalf );
|
||||
_clipBox.max.set( _canvasWidthHalf, _canvasHeightHalf );
|
||||
|
||||
_clearBox.min.set( - _canvasWidthHalf, - _canvasHeightHalf );
|
||||
|
@ -186,11 +208,11 @@ THREE.CanvasRenderer = function ( parameters ) {
|
|||
|
||||
this.setViewport = function ( x, y, width, height ) {
|
||||
|
||||
_viewportX = x * this.devicePixelRatio;
|
||||
_viewportY = y * this.devicePixelRatio;
|
||||
_viewportX = x * pixelRatio;
|
||||
_viewportY = y * pixelRatio;
|
||||
|
||||
_viewportWidth = width * this.devicePixelRatio;
|
||||
_viewportHeight = height * this.devicePixelRatio;
|
||||
_viewportWidth = width * pixelRatio;
|
||||
_viewportHeight = height * pixelRatio;
|
||||
|
||||
};
|
||||
|
||||
|
@ -240,17 +262,17 @@ THREE.CanvasRenderer = function ( parameters ) {
|
|||
_clearBox.expandByScalar( 2 );
|
||||
|
||||
_clearBox.min.x = _clearBox.min.x + _canvasWidthHalf;
|
||||
_clearBox.min.y = - _clearBox.min.y + _canvasHeightHalf;
|
||||
_clearBox.min.y = - _clearBox.min.y + _canvasHeightHalf; // higher y value !
|
||||
_clearBox.max.x = _clearBox.max.x + _canvasWidthHalf;
|
||||
_clearBox.max.y = - _clearBox.max.y + _canvasHeightHalf;
|
||||
_clearBox.max.y = - _clearBox.max.y + _canvasHeightHalf; // lower y value !
|
||||
|
||||
if ( _clearAlpha < 1 ) {
|
||||
|
||||
_context.clearRect(
|
||||
_clearBox.min.x | 0,
|
||||
_clearBox.min.y | 0,
|
||||
_clearBox.max.y | 0,
|
||||
( _clearBox.max.x - _clearBox.min.x ) | 0,
|
||||
( _clearBox.max.y - _clearBox.min.y ) | 0
|
||||
( _clearBox.min.y - _clearBox.max.y ) | 0
|
||||
);
|
||||
|
||||
}
|
||||
|
@ -264,9 +286,9 @@ THREE.CanvasRenderer = function ( parameters ) {
|
|||
|
||||
_context.fillRect(
|
||||
_clearBox.min.x | 0,
|
||||
_clearBox.min.y | 0,
|
||||
_clearBox.max.y | 0,
|
||||
( _clearBox.max.x - _clearBox.min.x ) | 0,
|
||||
( _clearBox.max.y - _clearBox.min.y ) | 0
|
||||
( _clearBox.min.y - _clearBox.max.y ) | 0
|
||||
);
|
||||
|
||||
}
|
||||
|
@ -496,53 +518,42 @@ THREE.CanvasRenderer = function ( parameters ) {
|
|||
|
||||
var texture = material.map;
|
||||
|
||||
if ( texture !== null && texture.image !== undefined ) {
|
||||
|
||||
if ( texture.hasEventListener( 'update', onTextureUpdate ) === false ) {
|
||||
|
||||
if ( texture.image.width > 0 ) {
|
||||
|
||||
textureToPattern( texture );
|
||||
|
||||
}
|
||||
|
||||
texture.addEventListener( 'update', onTextureUpdate );
|
||||
|
||||
}
|
||||
if ( texture !== null ) {
|
||||
|
||||
var pattern = _patterns[ texture.id ];
|
||||
|
||||
if ( pattern !== undefined ) {
|
||||
if ( pattern === undefined || pattern.version !== texture.version ) {
|
||||
|
||||
setFillStyle( pattern );
|
||||
|
||||
} else {
|
||||
|
||||
setFillStyle( 'rgba( 0, 0, 0, 1 )' );
|
||||
pattern = textureToPattern( texture );
|
||||
_patterns[ texture.id ] = pattern;
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
if ( pattern.canvas !== undefined ) {
|
||||
|
||||
var bitmap = texture.image;
|
||||
setFillStyle( pattern.canvas );
|
||||
|
||||
var ox = bitmap.width * texture.offset.x;
|
||||
var oy = bitmap.height * texture.offset.y;
|
||||
var bitmap = texture.image;
|
||||
|
||||
var sx = bitmap.width * texture.repeat.x;
|
||||
var sy = bitmap.height * texture.repeat.y;
|
||||
var ox = bitmap.width * texture.offset.x;
|
||||
var oy = bitmap.height * texture.offset.y;
|
||||
|
||||
var cx = scaleX / sx;
|
||||
var cy = scaleY / sy;
|
||||
var sx = bitmap.width * texture.repeat.x;
|
||||
var sy = bitmap.height * texture.repeat.y;
|
||||
|
||||
_context.save();
|
||||
_context.translate( v1.x, v1.y );
|
||||
if ( material.rotation !== 0 ) _context.rotate( material.rotation );
|
||||
_context.translate( - scaleX / 2, - scaleY / 2 );
|
||||
_context.scale( cx, cy );
|
||||
_context.translate( - ox, - oy );
|
||||
_context.fillRect( ox, oy, sx, sy );
|
||||
_context.restore();
|
||||
var cx = scaleX / sx;
|
||||
var cy = scaleY / sy;
|
||||
|
||||
_context.save();
|
||||
_context.translate( v1.x, v1.y );
|
||||
if ( material.rotation !== 0 ) _context.rotate( material.rotation );
|
||||
_context.translate( - scaleX / 2, - scaleY / 2 );
|
||||
_context.scale( cx, cy );
|
||||
_context.translate( - ox, - oy );
|
||||
_context.fillRect( ox, oy, sx, sy );
|
||||
_context.restore();
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
|
@ -704,7 +715,9 @@ THREE.CanvasRenderer = function ( parameters ) {
|
|||
|
||||
if ( material.map !== null ) {
|
||||
|
||||
if ( material.map.mapping instanceof THREE.UVMapping ) {
|
||||
var mapping = material.map.mapping;
|
||||
|
||||
if ( mapping === THREE.UVMapping ) {
|
||||
|
||||
_uvs = element.uvs;
|
||||
patternPath( _v1x, _v1y, _v2x, _v2y, _v3x, _v3y, _uvs[ uv1 ].x, _uvs[ uv1 ].y, _uvs[ uv2 ].x, _uvs[ uv2 ].y, _uvs[ uv3 ].x, _uvs[ uv3 ].y, material.map );
|
||||
|
@ -713,7 +726,7 @@ THREE.CanvasRenderer = function ( parameters ) {
|
|||
|
||||
} else if ( material.envMap !== null ) {
|
||||
|
||||
if ( material.envMap.mapping instanceof THREE.SphericalReflectionMapping ) {
|
||||
if ( material.envMap.mapping === THREE.SphericalReflectionMapping ) {
|
||||
|
||||
_normal.copy( element.vertexNormalsModel[ uv1 ] ).applyMatrix3( _normalViewMatrix );
|
||||
_uv1x = 0.5 * _normal.x + 0.5;
|
||||
|
@ -729,25 +742,8 @@ THREE.CanvasRenderer = function ( parameters ) {
|
|||
|
||||
patternPath( _v1x, _v1y, _v2x, _v2y, _v3x, _v3y, _uv1x, _uv1y, _uv2x, _uv2y, _uv3x, _uv3y, material.envMap );
|
||||
|
||||
} else if ( material.envMap.mapping instanceof THREE.SphericalRefractionMapping ) {
|
||||
|
||||
_normal.copy( element.vertexNormalsModel[ uv1 ] ).applyMatrix3( _normalViewMatrix );
|
||||
_uv1x = - 0.5 * _normal.x + 0.5;
|
||||
_uv1y = - 0.5 * _normal.y + 0.5;
|
||||
|
||||
_normal.copy( element.vertexNormalsModel[ uv2 ] ).applyMatrix3( _normalViewMatrix );
|
||||
_uv2x = - 0.5 * _normal.x + 0.5;
|
||||
_uv2y = - 0.5 * _normal.y + 0.5;
|
||||
|
||||
_normal.copy( element.vertexNormalsModel[ uv3 ] ).applyMatrix3( _normalViewMatrix );
|
||||
_uv3x = - 0.5 * _normal.x + 0.5;
|
||||
_uv3y = - 0.5 * _normal.y + 0.5;
|
||||
|
||||
patternPath( _v1x, _v1y, _v2x, _v2y, _v3x, _v3y, _uv1x, _uv1y, _uv2x, _uv2y, _uv3x, _uv3y, material.envMap );
|
||||
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
|
||||
_color.copy( material.color );
|
||||
|
@ -826,18 +822,18 @@ THREE.CanvasRenderer = function ( parameters ) {
|
|||
|
||||
}
|
||||
|
||||
function onTextureUpdate ( event ) {
|
||||
|
||||
textureToPattern( event.target );
|
||||
|
||||
}
|
||||
|
||||
function textureToPattern( texture ) {
|
||||
|
||||
if ( texture instanceof THREE.CompressedTexture ) return;
|
||||
if ( texture.version === 0 ||
|
||||
texture instanceof THREE.CompressedTexture ||
|
||||
texture instanceof THREE.DataTexture ) {
|
||||
|
||||
var repeatX = texture.wrapS === THREE.RepeatWrapping;
|
||||
var repeatY = texture.wrapT === THREE.RepeatWrapping;
|
||||
return {
|
||||
canvas: undefined,
|
||||
version: texture.version
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var image = texture.image;
|
||||
|
||||
|
@ -849,45 +845,51 @@ THREE.CanvasRenderer = function ( parameters ) {
|
|||
context.setTransform( 1, 0, 0, - 1, 0, image.height );
|
||||
context.drawImage( image, 0, 0 );
|
||||
|
||||
_patterns[ texture.id ] = _context.createPattern(
|
||||
canvas, repeatX === true && repeatY === true
|
||||
? 'repeat'
|
||||
: repeatX === true && repeatY === false
|
||||
? 'repeat-x'
|
||||
: repeatX === false && repeatY === true
|
||||
? 'repeat-y'
|
||||
: 'no-repeat'
|
||||
);
|
||||
var repeatX = texture.wrapS === THREE.RepeatWrapping;
|
||||
var repeatY = texture.wrapT === THREE.RepeatWrapping;
|
||||
|
||||
var repeat = 'no-repeat';
|
||||
|
||||
if ( repeatX === true && repeatY === true ) {
|
||||
|
||||
repeat = 'repeat';
|
||||
|
||||
} else if ( repeatX === true ) {
|
||||
|
||||
repeat = 'repeat-x';
|
||||
|
||||
} else if ( repeatY === true ) {
|
||||
|
||||
repeat = 'repeat-y';
|
||||
|
||||
}
|
||||
|
||||
return {
|
||||
canvas: _context.createPattern( canvas, repeat ),
|
||||
version: texture.version
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function patternPath( x0, y0, x1, y1, x2, y2, u0, v0, u1, v1, u2, v2, texture ) {
|
||||
|
||||
if ( texture instanceof THREE.DataTexture ) return;
|
||||
var pattern = _patterns[ texture.id ];
|
||||
|
||||
if ( texture.hasEventListener( 'update', onTextureUpdate ) === false ) {
|
||||
if ( pattern === undefined || pattern.version !== texture.version ) {
|
||||
|
||||
if ( texture.image !== undefined && texture.image.width > 0 ) {
|
||||
|
||||
textureToPattern( texture );
|
||||
|
||||
}
|
||||
|
||||
texture.addEventListener( 'update', onTextureUpdate );
|
||||
pattern = textureToPattern( texture );
|
||||
_patterns[ texture.id ] = pattern;
|
||||
|
||||
}
|
||||
|
||||
var pattern = _patterns[ texture.id ];
|
||||
if ( pattern.canvas !== undefined ) {
|
||||
|
||||
if ( pattern !== undefined ) {
|
||||
|
||||
setFillStyle( pattern );
|
||||
setFillStyle( pattern.canvas );
|
||||
|
||||
} else {
|
||||
|
||||
setFillStyle( 'rgba(0,0,0,1)' );
|
||||
setFillStyle( 'rgba( 0, 0, 0, 1)' );
|
||||
_context.fill();
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ THREE.RenderableObject = function () {
|
|||
|
||||
this.object = null;
|
||||
this.z = 0;
|
||||
this.renderOrder = 0;
|
||||
|
||||
};
|
||||
|
||||
|
@ -33,6 +34,7 @@ THREE.RenderableFace = function () {
|
|||
this.uvs = [ new THREE.Vector2(), new THREE.Vector2(), new THREE.Vector2() ];
|
||||
|
||||
this.z = 0;
|
||||
this.renderOrder = 0;
|
||||
|
||||
};
|
||||
|
||||
|
@ -68,6 +70,7 @@ THREE.RenderableLine = function () {
|
|||
this.material = null;
|
||||
|
||||
this.z = 0;
|
||||
this.renderOrder = 0;
|
||||
|
||||
};
|
||||
|
||||
|
@ -87,6 +90,7 @@ THREE.RenderableSprite = function () {
|
|||
this.scale = new THREE.Vector2();
|
||||
|
||||
this.material = null;
|
||||
this.renderOrder = 0;
|
||||
|
||||
};
|
||||
|
||||
|
@ -102,10 +106,6 @@ THREE.Projector = function () {
|
|||
|
||||
_renderData = { objects: [], lights: [], elements: [] },
|
||||
|
||||
_vA = new THREE.Vector3(),
|
||||
_vB = new THREE.Vector3(),
|
||||
_vC = new THREE.Vector3(),
|
||||
|
||||
_vector3 = new THREE.Vector3(),
|
||||
_vector4 = new THREE.Vector4(),
|
||||
|
||||
|
@ -126,7 +126,7 @@ THREE.Projector = function () {
|
|||
|
||||
_clippedVertex1PositionScreen = new THREE.Vector4(),
|
||||
_clippedVertex2PositionScreen = new THREE.Vector4();
|
||||
|
||||
|
||||
//
|
||||
|
||||
this.projectVector = function ( vector, camera ) {
|
||||
|
@ -145,10 +145,10 @@ THREE.Projector = function () {
|
|||
|
||||
this.pickingRay = function ( vector, camera ) {
|
||||
|
||||
console.error( 'THREE.Projector: .pickingRay() has been removed.' );
|
||||
console.error( 'THREE.Projector: .pickingRay() is now raycaster.setFromCamera().' );
|
||||
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
|
||||
var RenderList = function () {
|
||||
|
@ -247,6 +247,7 @@ THREE.Projector = function () {
|
|||
_line.v1.copy( v1 );
|
||||
_line.v2.copy( v2 );
|
||||
_line.z = ( v1.positionScreen.z + v2.positionScreen.z ) / 2;
|
||||
_line.renderOrder = object.renderOrder;
|
||||
|
||||
_line.material = object.material;
|
||||
|
||||
|
@ -271,19 +272,21 @@ THREE.Projector = function () {
|
|||
_face.v2.copy( v2 );
|
||||
_face.v3.copy( v3 );
|
||||
_face.z = ( v1.positionScreen.z + v2.positionScreen.z + v3.positionScreen.z ) / 3;
|
||||
_face.renderOrder = object.renderOrder;
|
||||
|
||||
// use first vertex normal as face normal
|
||||
|
||||
_face.normalModel.fromArray( normals, a * 3 );
|
||||
_face.normalModel.applyMatrix3( normalMatrix ).normalize();
|
||||
|
||||
for ( var i = 0; i < 3; i ++ ) {
|
||||
|
||||
var offset = arguments[ i ] * 3;
|
||||
var normal = _face.vertexNormalsModel[ i ];
|
||||
|
||||
normal.set( normals[ offset ], normals[ offset + 1 ], normals[ offset + 2 ] );
|
||||
normal.fromArray( normals, arguments[ i ] * 3 );
|
||||
normal.applyMatrix3( normalMatrix ).normalize();
|
||||
|
||||
var offset2 = arguments[ i ] * 2;
|
||||
|
||||
var uv = _face.uvs[ i ];
|
||||
uv.set( uvs[ offset2 ], uvs[ offset2 + 1 ] );
|
||||
uv.fromArray( uvs, arguments[ i ] * 2 );
|
||||
|
||||
}
|
||||
|
||||
|
@ -322,7 +325,7 @@ THREE.Projector = function () {
|
|||
_renderData.elements.length = 0;
|
||||
|
||||
if ( scene.autoUpdate === true ) scene.updateMatrixWorld();
|
||||
if ( camera.parent === undefined ) camera.updateMatrixWorld();
|
||||
if ( camera.parent === null ) camera.updateMatrixWorld();
|
||||
|
||||
_viewMatrix.copy( camera.matrixWorldInverse.getInverse( camera.matrixWorld ) );
|
||||
_viewProjectionMatrix.multiplyMatrices( camera.projectionMatrix, _viewMatrix );
|
||||
|
@ -344,7 +347,9 @@ THREE.Projector = function () {
|
|||
|
||||
} else if ( object instanceof THREE.Mesh || object instanceof THREE.Line || object instanceof THREE.Sprite ) {
|
||||
|
||||
if ( object.material.visible === false ) return;
|
||||
var material = object.material;
|
||||
|
||||
if ( material.visible === false ) return;
|
||||
|
||||
if ( object.frustumCulled === false || _frustum.intersectsObject( object ) === true ) {
|
||||
|
||||
|
@ -352,17 +357,10 @@ THREE.Projector = function () {
|
|||
_object.id = object.id;
|
||||
_object.object = object;
|
||||
|
||||
if ( object.renderDepth !== null ) {
|
||||
|
||||
_object.z = object.renderDepth;
|
||||
|
||||
} else {
|
||||
|
||||
_vector3.setFromMatrixPosition( object.matrixWorld );
|
||||
_vector3.applyProjection( _viewProjectionMatrix );
|
||||
_object.z = _vector3.z;
|
||||
|
||||
}
|
||||
_vector3.setFromMatrixPosition( object.matrixWorld );
|
||||
_vector3.applyProjection( _viewProjectionMatrix );
|
||||
_object.z = _vector3.z;
|
||||
_object.renderOrder = object.renderOrder;
|
||||
|
||||
_renderData.objects.push( _object );
|
||||
|
||||
|
@ -396,7 +394,7 @@ THREE.Projector = function () {
|
|||
if ( geometry instanceof THREE.BufferGeometry ) {
|
||||
|
||||
var attributes = geometry.attributes;
|
||||
var offsets = geometry.offsets;
|
||||
var groups = geometry.groups;
|
||||
|
||||
if ( attributes.position === undefined ) continue;
|
||||
|
||||
|
@ -432,20 +430,19 @@ THREE.Projector = function () {
|
|||
|
||||
}
|
||||
|
||||
if ( attributes.index !== undefined ) {
|
||||
if ( geometry.index !== null ) {
|
||||
|
||||
var indices = attributes.index.array;
|
||||
var indices = geometry.index.array;
|
||||
|
||||
if ( offsets.length > 0 ) {
|
||||
if ( groups.length > 0 ) {
|
||||
|
||||
for ( var o = 0; o < offsets.length; o ++ ) {
|
||||
for ( var o = 0; o < groups.length; o ++ ) {
|
||||
|
||||
var offset = offsets[ o ];
|
||||
var index = offset.index;
|
||||
var group = groups[ o ];
|
||||
|
||||
for ( var i = offset.start, l = offset.start + offset.count; i < l; i += 3 ) {
|
||||
for ( var i = group.start, l = group.start + group.count; i < l; i += 3 ) {
|
||||
|
||||
renderList.pushTriangle( indices[ i ] + index, indices[ i + 1 ] + index, indices[ i + 2 ] + index );
|
||||
renderList.pushTriangle( indices[ i ], indices[ i + 1 ], indices[ i + 2 ] );
|
||||
|
||||
}
|
||||
|
||||
|
@ -479,13 +476,40 @@ THREE.Projector = function () {
|
|||
|
||||
_normalMatrix.getNormalMatrix( _modelMatrix );
|
||||
|
||||
var isFaceMaterial = object.material instanceof THREE.MeshFaceMaterial;
|
||||
var material = object.material;
|
||||
|
||||
var isFaceMaterial = material instanceof THREE.MeshFaceMaterial;
|
||||
var objectMaterials = isFaceMaterial === true ? object.material : null;
|
||||
|
||||
for ( var v = 0, vl = vertices.length; v < vl; v ++ ) {
|
||||
|
||||
var vertex = vertices[ v ];
|
||||
renderList.pushVertex( vertex.x, vertex.y, vertex.z );
|
||||
|
||||
_vector3.copy( vertex );
|
||||
|
||||
if ( material.morphTargets === true ) {
|
||||
|
||||
var morphTargets = geometry.morphTargets;
|
||||
var morphInfluences = object.morphTargetInfluences;
|
||||
|
||||
for ( var t = 0, tl = morphTargets.length; t < tl; t ++ ) {
|
||||
|
||||
var influence = morphInfluences[ t ];
|
||||
|
||||
if ( influence === 0 ) continue;
|
||||
|
||||
var target = morphTargets[ t ];
|
||||
var targetVertex = target.vertices[ v ];
|
||||
|
||||
_vector3.x += ( targetVertex.x - vertex.x ) * influence;
|
||||
_vector3.y += ( targetVertex.y - vertex.y ) * influence;
|
||||
_vector3.z += ( targetVertex.z - vertex.z ) * influence;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
renderList.pushVertex( _vector3.x, _vector3.y, _vector3.z );
|
||||
|
||||
}
|
||||
|
||||
|
@ -493,7 +517,7 @@ THREE.Projector = function () {
|
|||
|
||||
var face = faces[ f ];
|
||||
|
||||
var material = isFaceMaterial === true
|
||||
material = isFaceMaterial === true
|
||||
? objectMaterials.materials[ face.materialIndex ]
|
||||
: object.material;
|
||||
|
||||
|
@ -505,58 +529,15 @@ THREE.Projector = function () {
|
|||
var v2 = _vertexPool[ face.b ];
|
||||
var v3 = _vertexPool[ face.c ];
|
||||
|
||||
if ( material.morphTargets === true ) {
|
||||
|
||||
var morphTargets = geometry.morphTargets;
|
||||
var morphInfluences = object.morphTargetInfluences;
|
||||
|
||||
var v1p = v1.position;
|
||||
var v2p = v2.position;
|
||||
var v3p = v3.position;
|
||||
|
||||
_vA.set( 0, 0, 0 );
|
||||
_vB.set( 0, 0, 0 );
|
||||
_vC.set( 0, 0, 0 );
|
||||
|
||||
for ( var t = 0, tl = morphTargets.length; t < tl; t ++ ) {
|
||||
|
||||
var influence = morphInfluences[ t ];
|
||||
|
||||
if ( influence === 0 ) continue;
|
||||
|
||||
var targets = morphTargets[ t ].vertices;
|
||||
|
||||
_vA.x += ( targets[ face.a ].x - v1p.x ) * influence;
|
||||
_vA.y += ( targets[ face.a ].y - v1p.y ) * influence;
|
||||
_vA.z += ( targets[ face.a ].z - v1p.z ) * influence;
|
||||
|
||||
_vB.x += ( targets[ face.b ].x - v2p.x ) * influence;
|
||||
_vB.y += ( targets[ face.b ].y - v2p.y ) * influence;
|
||||
_vB.z += ( targets[ face.b ].z - v2p.z ) * influence;
|
||||
|
||||
_vC.x += ( targets[ face.c ].x - v3p.x ) * influence;
|
||||
_vC.y += ( targets[ face.c ].y - v3p.y ) * influence;
|
||||
_vC.z += ( targets[ face.c ].z - v3p.z ) * influence;
|
||||
|
||||
}
|
||||
|
||||
v1.position.add( _vA );
|
||||
v2.position.add( _vB );
|
||||
v3.position.add( _vC );
|
||||
|
||||
renderList.projectVertex( v1 );
|
||||
renderList.projectVertex( v2 );
|
||||
renderList.projectVertex( v3 );
|
||||
|
||||
}
|
||||
|
||||
if ( renderList.checkTriangleVisibility( v1, v2, v3 ) === false ) continue;
|
||||
|
||||
var visible = renderList.checkBackfaceCulling( v1, v2, v3 );
|
||||
|
||||
if ( side !== THREE.DoubleSide ) {
|
||||
|
||||
if ( side === THREE.FrontSide && visible === false ) continue;
|
||||
if ( side === THREE.BackSide && visible === true ) continue;
|
||||
|
||||
}
|
||||
|
||||
_face = getNextFaceInPool();
|
||||
|
@ -611,6 +592,7 @@ THREE.Projector = function () {
|
|||
_face.material = material;
|
||||
|
||||
_face.z = ( v1.positionScreen.z + v2.positionScreen.z + v3.positionScreen.z ) / 3;
|
||||
_face.renderOrder = object.renderOrder;
|
||||
|
||||
_renderData.elements.push( _face );
|
||||
|
||||
|
@ -634,9 +616,9 @@ THREE.Projector = function () {
|
|||
|
||||
}
|
||||
|
||||
if ( attributes.index !== undefined ) {
|
||||
if ( geometry.index !== null ) {
|
||||
|
||||
var indices = attributes.index.array;
|
||||
var indices = geometry.index.array;
|
||||
|
||||
for ( var i = 0, l = indices.length; i < l; i += 2 ) {
|
||||
|
||||
|
@ -646,7 +628,7 @@ THREE.Projector = function () {
|
|||
|
||||
} else {
|
||||
|
||||
var step = object.mode === THREE.LinePieces ? 2 : 1;
|
||||
var step = object instanceof THREE.LineSegments ? 2 : 1;
|
||||
|
||||
for ( var i = 0, l = ( positions.length / 3 ) - 1; i < l; i += step ) {
|
||||
|
||||
|
@ -669,8 +651,7 @@ THREE.Projector = function () {
|
|||
v1 = getNextVertexInPool();
|
||||
v1.positionScreen.copy( vertices[ 0 ] ).applyMatrix4( _modelViewProjectionMatrix );
|
||||
|
||||
// Handle LineStrip and LinePieces
|
||||
var step = object.mode === THREE.LinePieces ? 2 : 1;
|
||||
var step = object instanceof THREE.LineSegments ? 2 : 1;
|
||||
|
||||
for ( var v = 1, vl = vertices.length; v < vl; v ++ ) {
|
||||
|
||||
|
@ -697,6 +678,7 @@ THREE.Projector = function () {
|
|||
_line.v2.positionScreen.copy( _clippedVertex2PositionScreen );
|
||||
|
||||
_line.z = Math.max( _clippedVertex1PositionScreen.z, _clippedVertex2PositionScreen.z );
|
||||
_line.renderOrder = object.renderOrder;
|
||||
|
||||
_line.material = object.material;
|
||||
|
||||
|
@ -731,6 +713,7 @@ THREE.Projector = function () {
|
|||
_sprite.x = _vector4.x * invW;
|
||||
_sprite.y = _vector4.y * invW;
|
||||
_sprite.z = _vector4.z;
|
||||
_sprite.renderOrder = object.renderOrder;
|
||||
_sprite.object = object;
|
||||
|
||||
_sprite.rotation = object.rotation;
|
||||
|
@ -816,7 +799,7 @@ THREE.Projector = function () {
|
|||
var line = new THREE.RenderableLine();
|
||||
_linePool.push( line );
|
||||
_linePoolLength ++;
|
||||
_lineCount ++
|
||||
_lineCount ++;
|
||||
return line;
|
||||
|
||||
}
|
||||
|
@ -832,7 +815,7 @@ THREE.Projector = function () {
|
|||
var sprite = new THREE.RenderableSprite();
|
||||
_spritePool.push( sprite );
|
||||
_spritePoolLength ++;
|
||||
_spriteCount ++
|
||||
_spriteCount ++;
|
||||
return sprite;
|
||||
|
||||
}
|
||||
|
@ -845,7 +828,11 @@ THREE.Projector = function () {
|
|||
|
||||
function painterSort( a, b ) {
|
||||
|
||||
if ( a.z !== b.z ) {
|
||||
if ( a.renderOrder !== b.renderOrder ) {
|
||||
|
||||
return a.renderOrder - b.renderOrder;
|
||||
|
||||
} else if ( a.z !== b.z ) {
|
||||
|
||||
return b.z - a.z;
|
||||
|
||||
|
|
1579
js/libraries/three/three.min.js
vendored
1579
js/libraries/three/three.min.js
vendored
File diff suppressed because one or more lines are too long
49
js/model.js
49
js/model.js
|
@ -2,27 +2,30 @@
|
|||
|
||||
// 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: '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'}
|
||||
|
||||
];
|
||||
|
|
280
js/msp.js
280
js/msp.js
|
@ -51,7 +51,7 @@ var MSP_codes = {
|
|||
MSP_PIDNAMES: 117,
|
||||
MSP_WP: 118,
|
||||
MSP_BOXIDS: 119,
|
||||
MSP_SERVO_CONF: 120,
|
||||
MSP_SERVO_CONFIGURATIONS: 120,
|
||||
|
||||
MSP_SET_RAW_RC: 200,
|
||||
MSP_SET_RAW_GPS: 201,
|
||||
|
@ -65,10 +65,13 @@ var MSP_codes = {
|
|||
MSP_SET_WP: 209,
|
||||
MSP_SELECT_SETTING: 210,
|
||||
MSP_SET_HEAD: 211,
|
||||
MSP_SET_SERVO_CONF: 212,
|
||||
MSP_SET_SERVO_CONFIGURATION: 212,
|
||||
MSP_SET_MOTOR: 214,
|
||||
|
||||
// MSP_BIND: 240,
|
||||
|
||||
MSP_SERVO_MIX_RULES: 241,
|
||||
MSP_SET_SERVO_MIX_RULE: 242,
|
||||
|
||||
MSP_EEPROM_WRITE: 250,
|
||||
|
||||
|
@ -80,7 +83,7 @@ var MSP_codes = {
|
|||
MSP_ACC_TRIM: 240, // get acc angle trim values
|
||||
MSP_SET_ACC_TRIM: 239, // set acc angle trim values
|
||||
MSP_GPS_SV_INFO: 164, // get Signal Strength
|
||||
|
||||
|
||||
// Additional private MSP for baseflight configurator (yes thats us \o/)
|
||||
MSP_RX_MAP: 64, // get channel map (also returns number of channels total)
|
||||
MSP_SET_RX_MAP: 65, // set rc map, numchannels to set comes from MSP_RX_MAP
|
||||
|
@ -102,6 +105,7 @@ var MSP = {
|
|||
|
||||
callbacks: [],
|
||||
packet_error: 0,
|
||||
unsupported: 0,
|
||||
|
||||
ledDirectionLetters: ['n', 'e', 's', 'w', 'u', 'd'], // in LSB bit order
|
||||
ledFunctionLetters: ['i', 'w', 'f', 'a', 't', 'r', 'c'], // in LSB bit order
|
||||
|
@ -138,10 +142,14 @@ var MSP = {
|
|||
}
|
||||
break;
|
||||
case 2: // direction (should be >)
|
||||
this.unsupported = 0;
|
||||
if (data[i] == 62) { // >
|
||||
this.message_direction = 1;
|
||||
} else { // <
|
||||
} else if (data[i] == 60) { // <
|
||||
this.message_direction = 0;
|
||||
} else if (data[i] == 33) { // !
|
||||
// FC reports unsupported message error
|
||||
this.unsupported = 1;
|
||||
}
|
||||
|
||||
this.state++;
|
||||
|
@ -202,7 +210,7 @@ var MSP = {
|
|||
process_data: function (code, message_buffer, message_length) {
|
||||
var data = new DataView(message_buffer, 0); // DataView (allowing us to view arrayBuffer as struct/union)
|
||||
|
||||
switch (code) {
|
||||
if (!this.unsupported) switch (code) {
|
||||
case MSP_codes.MSP_IDENT:
|
||||
console.log('Using deprecated msp command: MSP_IDENT');
|
||||
// Deprecated
|
||||
|
@ -444,19 +452,52 @@ var MSP = {
|
|||
AUX_CONFIG_IDS.push(data.getUint8(i));
|
||||
}
|
||||
break;
|
||||
case MSP_codes.MSP_SERVO_CONF:
|
||||
case MSP_codes.MSP_SERVO_MIX_RULES:
|
||||
break;
|
||||
|
||||
case MSP_codes.MSP_SERVO_CONFIGURATIONS:
|
||||
SERVO_CONFIG = []; // empty the array as new data is coming in
|
||||
|
||||
if (data.byteLength % 7 == 0) {
|
||||
for (var i = 0; i < data.byteLength; i += 7) {
|
||||
var arr = {
|
||||
'min': data.getInt16(i, 1),
|
||||
'max': data.getInt16(i + 2, 1),
|
||||
'middle': data.getInt16(i + 4, 1),
|
||||
'rate': data.getInt8(i + 6)
|
||||
};
|
||||
|
||||
SERVO_CONFIG.push(arr);
|
||||
if (semver.gte(CONFIG.apiVersion, "1.12.0")) {
|
||||
if (data.byteLength % 14 == 0) {
|
||||
for (var i = 0; i < data.byteLength; i += 14) {
|
||||
var arr = {
|
||||
'min': data.getInt16(i + 0, 1),
|
||||
'max': data.getInt16(i + 2, 1),
|
||||
'middle': data.getInt16(i + 4, 1),
|
||||
'rate': data.getInt8(i + 6),
|
||||
'angleAtMin': data.getInt8(i + 7),
|
||||
'angleAtMax': data.getInt8(i + 8),
|
||||
'indexOfChannelToForward': data.getInt8(i + 9),
|
||||
'reversedInputSources': data.getUint32(i + 10)
|
||||
};
|
||||
|
||||
SERVO_CONFIG.push(arr);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (data.byteLength % 7 == 0) {
|
||||
for (var i = 0; i < data.byteLength; i += 7) {
|
||||
var arr = {
|
||||
'min': data.getInt16(i + 0, 1),
|
||||
'max': data.getInt16(i + 2, 1),
|
||||
'middle': data.getInt16(i + 4, 1),
|
||||
'rate': data.getInt8(i + 6),
|
||||
'angleAtMin': 90,
|
||||
'angleAtMax': 90,
|
||||
'indexOfChannelToForward': undefined,
|
||||
'reversedInputSources': 0
|
||||
};
|
||||
|
||||
SERVO_CONFIG.push(arr);
|
||||
}
|
||||
}
|
||||
|
||||
if (semver.eq(CONFIG.apiVersion, '1.10.0')) {
|
||||
// drop two unused servo configurations due to MSP rx buffer to small)
|
||||
while (SERVO_CONFIG.length > 8) {
|
||||
SERVO_CONFIG.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -490,7 +531,7 @@ var MSP = {
|
|||
case MSP_codes.MSP_SELECT_SETTING:
|
||||
console.log('Profile selected');
|
||||
break;
|
||||
case MSP_codes.MSP_SET_SERVO_CONF:
|
||||
case MSP_codes.MSP_SET_SERVO_CONFIGURATION:
|
||||
console.log('Servo Configuration saved');
|
||||
break;
|
||||
case MSP_codes.MSP_EEPROM_WRITE:
|
||||
|
@ -798,6 +839,8 @@ var MSP = {
|
|||
|
||||
default:
|
||||
console.log('Unknown code detected: ' + code);
|
||||
} else {
|
||||
console.log('FC reports unsupported message error: ' + code);
|
||||
}
|
||||
|
||||
// trigger callbacks, cleanup/remove callback after trigger
|
||||
|
@ -944,43 +987,43 @@ MSP.crunch = function (code) {
|
|||
case 7:
|
||||
case 8:
|
||||
case 9:
|
||||
buffer.push(parseInt(PIDs[i][0] * 10));
|
||||
buffer.push(parseInt(PIDs[i][1] * 1000));
|
||||
buffer.push(Math.round(PIDs[i][0] * 10));
|
||||
buffer.push(Math.round(PIDs[i][1] * 1000));
|
||||
buffer.push(parseInt(PIDs[i][2]));
|
||||
break;
|
||||
case 4:
|
||||
buffer.push(parseInt(PIDs[i][0] * 100));
|
||||
buffer.push(parseInt(PIDs[i][1] * 100));
|
||||
buffer.push(Math.round(PIDs[i][0] * 100));
|
||||
buffer.push(Math.round(PIDs[i][1] * 100));
|
||||
buffer.push(parseInt(PIDs[i][2]));
|
||||
break;
|
||||
case 5:
|
||||
case 6:
|
||||
buffer.push(parseInt(PIDs[i][0] * 10));
|
||||
buffer.push(parseInt(PIDs[i][1] * 100));
|
||||
buffer.push(parseInt(PIDs[i][2] * 1000));
|
||||
buffer.push(Math.round(PIDs[i][0] * 10));
|
||||
buffer.push(Math.round(PIDs[i][1] * 100));
|
||||
buffer.push(Math.round(PIDs[i][2] * 1000));
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MSP_codes.MSP_SET_RC_TUNING:
|
||||
buffer.push(parseInt(RC_tuning.RC_RATE * 100));
|
||||
buffer.push(parseInt(RC_tuning.RC_EXPO * 100));
|
||||
buffer.push(Math.round(RC_tuning.RC_RATE * 100));
|
||||
buffer.push(Math.round(RC_tuning.RC_EXPO * 100));
|
||||
if (semver.lt(CONFIG.apiVersion, "1.7.0")) {
|
||||
buffer.push(parseInt(RC_tuning.roll_pitch_rate * 100));
|
||||
buffer.push(Math.round(RC_tuning.roll_pitch_rate * 100));
|
||||
} else {
|
||||
buffer.push(parseInt(RC_tuning.roll_rate * 100));
|
||||
buffer.push(parseInt(RC_tuning.pitch_rate * 100));
|
||||
buffer.push(Math.round(RC_tuning.roll_rate * 100));
|
||||
buffer.push(Math.round(RC_tuning.pitch_rate * 100));
|
||||
}
|
||||
buffer.push(parseInt(RC_tuning.yaw_rate * 100));
|
||||
buffer.push(parseInt(RC_tuning.dynamic_THR_PID * 100));
|
||||
buffer.push(parseInt(RC_tuning.throttle_MID * 100));
|
||||
buffer.push(parseInt(RC_tuning.throttle_EXPO * 100));
|
||||
buffer.push(Math.round(RC_tuning.yaw_rate * 100));
|
||||
buffer.push(Math.round(RC_tuning.dynamic_THR_PID * 100));
|
||||
buffer.push(Math.round(RC_tuning.throttle_MID * 100));
|
||||
buffer.push(Math.round(RC_tuning.throttle_EXPO * 100));
|
||||
if (semver.gte(CONFIG.apiVersion, "1.7.0")) {
|
||||
buffer.push(lowByte(RC_tuning.dynamic_THR_breakpoint));
|
||||
buffer.push(highByte(RC_tuning.dynamic_THR_breakpoint));
|
||||
}
|
||||
if (semver.gte(CONFIG.apiVersion, "1.10.0")) {
|
||||
buffer.push(parseInt(RC_tuning.RC_YAW_EXPO * 100));
|
||||
buffer.push(Math.round(RC_tuning.RC_YAW_EXPO * 100));
|
||||
}
|
||||
break;
|
||||
// Disabled, cleanflight does not use MSP_SET_BOX.
|
||||
|
@ -1028,26 +1071,12 @@ MSP.crunch = function (code) {
|
|||
buffer.push(MISC.multiwiicurrentoutput);
|
||||
buffer.push(MISC.rssi_channel);
|
||||
buffer.push(MISC.placeholder2);
|
||||
buffer.push(lowByte(MISC.mag_declination * 10));
|
||||
buffer.push(highByte(MISC.mag_declination * 10));
|
||||
buffer.push(lowByte(Math.round(MISC.mag_declination * 10)));
|
||||
buffer.push(highByte(Math.round(MISC.mag_declination * 10)));
|
||||
buffer.push(MISC.vbatscale);
|
||||
buffer.push(MISC.vbatmincellvoltage * 10);
|
||||
buffer.push(MISC.vbatmaxcellvoltage * 10);
|
||||
buffer.push(MISC.vbatwarningcellvoltage * 10);
|
||||
break;
|
||||
case MSP_codes.MSP_SET_SERVO_CONF:
|
||||
for (var i = 0; i < SERVO_CONFIG.length; i++) {
|
||||
buffer.push(lowByte(SERVO_CONFIG[i].min));
|
||||
buffer.push(highByte(SERVO_CONFIG[i].min));
|
||||
|
||||
buffer.push(lowByte(SERVO_CONFIG[i].max));
|
||||
buffer.push(highByte(SERVO_CONFIG[i].max));
|
||||
|
||||
buffer.push(lowByte(SERVO_CONFIG[i].middle));
|
||||
buffer.push(highByte(SERVO_CONFIG[i].middle));
|
||||
|
||||
buffer.push(lowByte(SERVO_CONFIG[i].rate));
|
||||
}
|
||||
buffer.push(Math.round(MISC.vbatmincellvoltage * 10));
|
||||
buffer.push(Math.round(MISC.vbatmaxcellvoltage * 10));
|
||||
buffer.push(Math.round(MISC.vbatwarningcellvoltage * 10));
|
||||
break;
|
||||
case MSP_codes.MSP_SET_CHANNEL_FORWARDING:
|
||||
for (var i = 0; i < SERVO_CONFIG.length; i++) {
|
||||
|
@ -1108,6 +1137,22 @@ MSP.crunch = function (code) {
|
|||
return buffer;
|
||||
};
|
||||
|
||||
/**
|
||||
* Set raw Rx values over MSP protocol.
|
||||
*
|
||||
* Channels is an array of 16-bit unsigned integer channel values to be sent. 8 channels is probably the maximum.
|
||||
*/
|
||||
MSP.setRawRx = function(channels) {
|
||||
var buffer = [];
|
||||
|
||||
for (var i = 0; i < channels.length; i++) {
|
||||
buffer.push(specificByte(channels[i], 0));
|
||||
buffer.push(specificByte(channels[i], 1));
|
||||
}
|
||||
|
||||
MSP.send_message(MSP_codes.MSP_SET_RAW_RC, buffer, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a request to read a block of data from the dataflash at the given address and pass that address and a dataview
|
||||
* of the returned data to the given callback (or null for the data if an error occured).
|
||||
|
@ -1128,7 +1173,102 @@ MSP.dataflashRead = function(address, onDataCallback) {
|
|||
onDataCallback(address, null);
|
||||
}
|
||||
});
|
||||
} ;
|
||||
};
|
||||
|
||||
MSP.sendServoMixRules = function(onCompleteCallback) {
|
||||
// TODO implement
|
||||
onCompleteCallback();
|
||||
};
|
||||
|
||||
MSP.sendServoConfigurations = function(onCompleteCallback) {
|
||||
var nextFunction = send_next_servo_configuration;
|
||||
|
||||
var servoIndex = 0;
|
||||
|
||||
if (SERVO_CONFIG.length == 0) {
|
||||
onCompleteCallback();
|
||||
}
|
||||
|
||||
nextFunction();
|
||||
|
||||
function send_next_servo_configuration() {
|
||||
|
||||
var buffer = [];
|
||||
|
||||
if (semver.lt(CONFIG.apiVersion, "1.12.0")) {
|
||||
// send all in one go
|
||||
// 1.9.0 had a bug where the MSP input buffer was too small, limit to 8.
|
||||
for (var i = 0; i < SERVO_CONFIG.length && i < 8; i++) {
|
||||
buffer.push(lowByte(SERVO_CONFIG[i].min));
|
||||
buffer.push(highByte(SERVO_CONFIG[i].min));
|
||||
|
||||
buffer.push(lowByte(SERVO_CONFIG[i].max));
|
||||
buffer.push(highByte(SERVO_CONFIG[i].max));
|
||||
|
||||
buffer.push(lowByte(SERVO_CONFIG[i].middle));
|
||||
buffer.push(highByte(SERVO_CONFIG[i].middle));
|
||||
|
||||
buffer.push(lowByte(SERVO_CONFIG[i].rate));
|
||||
}
|
||||
|
||||
nextFunction = send_channel_forwarding;
|
||||
} else {
|
||||
// send one at a time, with index
|
||||
|
||||
var servoConfiguration = SERVO_CONFIG[servoIndex];
|
||||
|
||||
buffer.push(servoIndex);
|
||||
|
||||
buffer.push(lowByte(servoConfiguration.min));
|
||||
buffer.push(highByte(servoConfiguration.min));
|
||||
|
||||
buffer.push(lowByte(servoConfiguration.max));
|
||||
buffer.push(highByte(servoConfiguration.max));
|
||||
|
||||
buffer.push(lowByte(servoConfiguration.middle));
|
||||
buffer.push(highByte(servoConfiguration.middle));
|
||||
|
||||
buffer.push(lowByte(servoConfiguration.rate));
|
||||
|
||||
buffer.push(servoConfiguration.angleAtMin);
|
||||
buffer.push(servoConfiguration.angleAtMax);
|
||||
|
||||
var out = servoConfiguration.indexOfChannelToForward;
|
||||
if (out == undefined) {
|
||||
out = 255; // Cleanflight defines "CHANNEL_FORWARDING_DISABLED" as "(uint8_t)0xFF"
|
||||
}
|
||||
buffer.push(out);
|
||||
|
||||
buffer.push(specificByte(servoConfiguration.reversedInputSources, 0));
|
||||
buffer.push(specificByte(servoConfiguration.reversedInputSources, 1));
|
||||
buffer.push(specificByte(servoConfiguration.reversedInputSources, 2));
|
||||
buffer.push(specificByte(servoConfiguration.reversedInputSources, 3));
|
||||
|
||||
// prepare for next iteration
|
||||
servoIndex++;
|
||||
if (servoIndex == SERVO_CONFIG.length) {
|
||||
nextFunction = onCompleteCallback;
|
||||
}
|
||||
}
|
||||
MSP.send_message(MSP_codes.MSP_SET_SERVO_CONFIGURATION, buffer, false, nextFunction);
|
||||
}
|
||||
|
||||
function send_channel_forwarding() {
|
||||
var buffer = [];
|
||||
|
||||
for (var i = 0; i < SERVO_CONFIG.length; i++) {
|
||||
var out = SERVO_CONFIG[i].indexOfChannelToForward;
|
||||
if (out == undefined) {
|
||||
out = 255; // Cleanflight defines "CHANNEL_FORWARDING_DISABLED" as "(uint8_t)0xFF"
|
||||
}
|
||||
buffer.push(out);
|
||||
}
|
||||
|
||||
nextFunction = onCompleteCallback;
|
||||
|
||||
MSP.send_message(MSP_codes.MSP_SET_CHANNEL_FORWARDING, buffer, false, nextFunction);
|
||||
}
|
||||
};
|
||||
|
||||
MSP.sendModeRanges = function(onCompleteCallback) {
|
||||
var nextFunction = send_next_mode_range;
|
||||
|
@ -1146,12 +1286,12 @@ MSP.sendModeRanges = function(onCompleteCallback) {
|
|||
|
||||
var modeRange = MODE_RANGES[modeRangeIndex];
|
||||
|
||||
var AUX_val_buffer_out = [];
|
||||
AUX_val_buffer_out.push(modeRangeIndex);
|
||||
AUX_val_buffer_out.push(modeRange.id);
|
||||
AUX_val_buffer_out.push(modeRange.auxChannelIndex);
|
||||
AUX_val_buffer_out.push((modeRange.range.start - 900) / 25);
|
||||
AUX_val_buffer_out.push((modeRange.range.end - 900) / 25);
|
||||
var buffer = [];
|
||||
buffer.push(modeRangeIndex);
|
||||
buffer.push(modeRange.id);
|
||||
buffer.push(modeRange.auxChannelIndex);
|
||||
buffer.push((modeRange.range.start - 900) / 25);
|
||||
buffer.push((modeRange.range.end - 900) / 25);
|
||||
|
||||
// prepare for next iteration
|
||||
modeRangeIndex++;
|
||||
|
@ -1159,7 +1299,7 @@ MSP.sendModeRanges = function(onCompleteCallback) {
|
|||
nextFunction = onCompleteCallback;
|
||||
|
||||
}
|
||||
MSP.send_message(MSP_codes.MSP_SET_MODE_RANGE, AUX_val_buffer_out, false, nextFunction);
|
||||
MSP.send_message(MSP_codes.MSP_SET_MODE_RANGE, buffer, false, nextFunction);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1179,14 +1319,14 @@ MSP.sendAdjustmentRanges = function(onCompleteCallback) {
|
|||
|
||||
var adjustmentRange = ADJUSTMENT_RANGES[adjustmentRangeIndex];
|
||||
|
||||
var ADJUSTMENT_val_buffer_out = [];
|
||||
ADJUSTMENT_val_buffer_out.push(adjustmentRangeIndex);
|
||||
ADJUSTMENT_val_buffer_out.push(adjustmentRange.slotIndex);
|
||||
ADJUSTMENT_val_buffer_out.push(adjustmentRange.auxChannelIndex);
|
||||
ADJUSTMENT_val_buffer_out.push((adjustmentRange.range.start - 900) / 25);
|
||||
ADJUSTMENT_val_buffer_out.push((adjustmentRange.range.end - 900) / 25);
|
||||
ADJUSTMENT_val_buffer_out.push(adjustmentRange.adjustmentFunction);
|
||||
ADJUSTMENT_val_buffer_out.push(adjustmentRange.auxSwitchChannelIndex);
|
||||
var buffer = [];
|
||||
buffer.push(adjustmentRangeIndex);
|
||||
buffer.push(adjustmentRange.slotIndex);
|
||||
buffer.push(adjustmentRange.auxChannelIndex);
|
||||
buffer.push((adjustmentRange.range.start - 900) / 25);
|
||||
buffer.push((adjustmentRange.range.end - 900) / 25);
|
||||
buffer.push(adjustmentRange.adjustmentFunction);
|
||||
buffer.push(adjustmentRange.auxSwitchChannelIndex);
|
||||
|
||||
// prepare for next iteration
|
||||
adjustmentRangeIndex++;
|
||||
|
@ -1194,7 +1334,7 @@ MSP.sendAdjustmentRanges = function(onCompleteCallback) {
|
|||
nextFunction = onCompleteCallback;
|
||||
|
||||
}
|
||||
MSP.send_message(MSP_codes.MSP_SET_ADJUSTMENT_RANGE, ADJUSTMENT_val_buffer_out, false, nextFunction);
|
||||
MSP.send_message(MSP_codes.MSP_SET_ADJUSTMENT_RANGE, buffer, false, nextFunction);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -32,8 +32,8 @@
|
|||
|
||||
<script type="text/javascript" src="./js/libraries/q.js"></script>
|
||||
<script type="text/javascript" src="./js/libraries/google-analytics-bundle.js"></script>
|
||||
<script type="text/javascript" src="./js/libraries/jquery-2.1.3.min.js"></script>
|
||||
<script type="text/javascript" src="./js/libraries/jquery-ui-1.11.2.min.js"></script>
|
||||
<script type="text/javascript" src="./js/libraries/jquery-2.1.4.min.js"></script>
|
||||
<script type="text/javascript" src="./js/libraries/jquery-ui-1.11.4.min.js"></script>
|
||||
<script type="text/javascript" src="./js/libraries/d3.min.js"></script>
|
||||
<script type="text/javascript" src="./js/libraries/jquery.nouislider.all.min.js"></script>
|
||||
<script type="text/javascript" src="./js/libraries/three/three.min.js"></script>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"manifest_version": 2,
|
||||
"minimum_chrome_version": "38",
|
||||
"version": "0.65.0",
|
||||
"version": "0.66.0",
|
||||
"author": "Hydra",
|
||||
"name": "Cleanflight - Configurator",
|
||||
"short_name": "cleanflight",
|
||||
|
@ -31,7 +31,8 @@
|
|||
"fileSystem",
|
||||
"fileSystem.write",
|
||||
"fileSystem.retainEntries",
|
||||
"notifications"
|
||||
"notifications",
|
||||
"alwaysOnTopWindows"
|
||||
],
|
||||
|
||||
"optional_permissions": [
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
"DbgName": "Material.003",
|
||||
"colorEmissive": [0.0,0.0,0.0],
|
||||
"mapDiffuse": "fallback.png",
|
||||
"opacity": 0.0,
|
||||
"opacity": 1.0,
|
||||
"specularCoef": 50,
|
||||
"shading": "phong",
|
||||
"mapDiffuseWrap": ["RepeatWrapping","RepeatWrapping"],
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
"visible": true,
|
||||
"blending": "NormalBlending",
|
||||
"DbgIndex": 0,
|
||||
"opacity": 0.0
|
||||
"opacity": 1.0
|
||||
},{
|
||||
"DbgColor": 15597568,
|
||||
"specularCoef": 50,
|
||||
|
@ -45,7 +45,7 @@
|
|||
"visible": true,
|
||||
"blending": "NormalBlending",
|
||||
"DbgIndex": 1,
|
||||
"opacity": 0.0
|
||||
"opacity": 1.0
|
||||
},{
|
||||
"DbgColor": 60928,
|
||||
"specularCoef": 50,
|
||||
|
@ -62,7 +62,7 @@
|
|||
"visible": true,
|
||||
"blending": "NormalBlending",
|
||||
"DbgIndex": 2,
|
||||
"opacity": 0.0
|
||||
"opacity": 1.0
|
||||
},{
|
||||
"DbgColor": 238,
|
||||
"specularCoef": 50,
|
||||
|
@ -79,7 +79,7 @@
|
|||
"visible": true,
|
||||
"blending": "NormalBlending",
|
||||
"DbgIndex": 3,
|
||||
"opacity": 0.0
|
||||
"opacity": 1.0
|
||||
},{
|
||||
"DbgColor": 15658496,
|
||||
"specularCoef": 50,
|
||||
|
@ -96,6 +96,6 @@
|
|||
"visible": true,
|
||||
"blending": "NormalBlending",
|
||||
"DbgIndex": 4,
|
||||
"opacity": 0.0
|
||||
"opacity": 1.0
|
||||
}]
|
||||
}
|
|
@ -28,7 +28,7 @@
|
|||
"visible": true,
|
||||
"blending": "NormalBlending",
|
||||
"DbgIndex": 0,
|
||||
"opacity": 0.0
|
||||
"opacity": 1.0
|
||||
},{
|
||||
"DbgColor": 15597568,
|
||||
"specularCoef": 50,
|
||||
|
@ -45,7 +45,7 @@
|
|||
"visible": true,
|
||||
"blending": "NormalBlending",
|
||||
"DbgIndex": 1,
|
||||
"opacity": 0.0
|
||||
"opacity": 1.0
|
||||
},{
|
||||
"DbgColor": 60928,
|
||||
"specularCoef": 50,
|
||||
|
@ -62,7 +62,7 @@
|
|||
"visible": true,
|
||||
"blending": "NormalBlending",
|
||||
"DbgIndex": 2,
|
||||
"opacity": 0.0
|
||||
"opacity": 1.0
|
||||
},{
|
||||
"DbgColor": 238,
|
||||
"specularCoef": 50,
|
||||
|
@ -79,7 +79,7 @@
|
|||
"visible": true,
|
||||
"blending": "NormalBlending",
|
||||
"DbgIndex": 3,
|
||||
"opacity": 0.0
|
||||
"opacity": 1.0
|
||||
},{
|
||||
"DbgColor": 15658496,
|
||||
"specularCoef": 50,
|
||||
|
@ -96,6 +96,6 @@
|
|||
"visible": true,
|
||||
"blending": "NormalBlending",
|
||||
"DbgIndex": 4,
|
||||
"opacity": 0.0
|
||||
"opacity": 1.0
|
||||
}]
|
||||
}
|
|
@ -28,7 +28,7 @@
|
|||
"visible": true,
|
||||
"blending": "NormalBlending",
|
||||
"DbgIndex": 0,
|
||||
"opacity": 0.0
|
||||
"opacity": 1.0
|
||||
},{
|
||||
"DbgColor": 15597568,
|
||||
"specularCoef": 50,
|
||||
|
@ -45,7 +45,7 @@
|
|||
"visible": true,
|
||||
"blending": "NormalBlending",
|
||||
"DbgIndex": 1,
|
||||
"opacity": 0.0
|
||||
"opacity": 1.0
|
||||
},{
|
||||
"DbgColor": 60928,
|
||||
"specularCoef": 50,
|
||||
|
@ -62,7 +62,7 @@
|
|||
"visible": true,
|
||||
"blending": "NormalBlending",
|
||||
"DbgIndex": 2,
|
||||
"opacity": 0.0
|
||||
"opacity": 1.0
|
||||
},{
|
||||
"DbgColor": 238,
|
||||
"specularCoef": 50,
|
||||
|
@ -79,7 +79,7 @@
|
|||
"visible": true,
|
||||
"blending": "NormalBlending",
|
||||
"DbgIndex": 3,
|
||||
"opacity": 0.0
|
||||
"opacity": 1.0
|
||||
},{
|
||||
"DbgColor": 15658496,
|
||||
"specularCoef": 50,
|
||||
|
@ -96,6 +96,6 @@
|
|||
"visible": true,
|
||||
"blending": "NormalBlending",
|
||||
"DbgIndex": 4,
|
||||
"opacity": 0.0
|
||||
"opacity": 1.0
|
||||
}]
|
||||
}
|
|
@ -28,7 +28,7 @@
|
|||
"visible": true,
|
||||
"blending": "NormalBlending",
|
||||
"DbgIndex": 0,
|
||||
"opacity": 0.0
|
||||
"opacity": 1.0
|
||||
},{
|
||||
"DbgColor": 15597568,
|
||||
"specularCoef": 50,
|
||||
|
@ -45,7 +45,7 @@
|
|||
"visible": true,
|
||||
"blending": "NormalBlending",
|
||||
"DbgIndex": 1,
|
||||
"opacity": 0.0
|
||||
"opacity": 1.0
|
||||
},{
|
||||
"DbgColor": 60928,
|
||||
"specularCoef": 50,
|
||||
|
@ -62,7 +62,7 @@
|
|||
"visible": true,
|
||||
"blending": "NormalBlending",
|
||||
"DbgIndex": 2,
|
||||
"opacity": 0.0
|
||||
"opacity": 1.0
|
||||
},{
|
||||
"DbgColor": 238,
|
||||
"specularCoef": 50,
|
||||
|
@ -79,7 +79,7 @@
|
|||
"visible": true,
|
||||
"blending": "NormalBlending",
|
||||
"DbgIndex": 3,
|
||||
"opacity": 0.0
|
||||
"opacity": 1.0
|
||||
},{
|
||||
"DbgColor": 15658496,
|
||||
"specularCoef": 50,
|
||||
|
@ -96,6 +96,6 @@
|
|||
"visible": true,
|
||||
"blending": "NormalBlending",
|
||||
"DbgIndex": 4,
|
||||
"opacity": 0.0
|
||||
"opacity": 1.0
|
||||
}]
|
||||
}
|
|
@ -28,7 +28,7 @@
|
|||
"visible": true,
|
||||
"blending": "NormalBlending",
|
||||
"DbgIndex": 0,
|
||||
"opacity": 0.0
|
||||
"opacity": 1.0
|
||||
},{
|
||||
"DbgColor": 15597568,
|
||||
"specularCoef": 50,
|
||||
|
@ -45,7 +45,7 @@
|
|||
"visible": true,
|
||||
"blending": "NormalBlending",
|
||||
"DbgIndex": 1,
|
||||
"opacity": 0.0
|
||||
"opacity": 1.0
|
||||
},{
|
||||
"DbgColor": 60928,
|
||||
"specularCoef": 50,
|
||||
|
@ -62,7 +62,7 @@
|
|||
"visible": true,
|
||||
"blending": "NormalBlending",
|
||||
"DbgIndex": 2,
|
||||
"opacity": 0.0
|
||||
"opacity": 1.0
|
||||
},{
|
||||
"DbgColor": 238,
|
||||
"specularCoef": 50,
|
||||
|
@ -79,7 +79,7 @@
|
|||
"visible": true,
|
||||
"blending": "NormalBlending",
|
||||
"DbgIndex": 3,
|
||||
"opacity": 0.0
|
||||
"opacity": 1.0
|
||||
},{
|
||||
"DbgColor": 15658496,
|
||||
"specularCoef": 50,
|
||||
|
@ -96,6 +96,6 @@
|
|||
"visible": true,
|
||||
"blending": "NormalBlending",
|
||||
"DbgIndex": 4,
|
||||
"opacity": 0.0
|
||||
"opacity": 1.0
|
||||
}]
|
||||
}
|
|
@ -28,7 +28,7 @@
|
|||
"visible": true,
|
||||
"blending": "NormalBlending",
|
||||
"DbgIndex": 0,
|
||||
"opacity": 0.0
|
||||
"opacity": 1.0
|
||||
},{
|
||||
"DbgColor": 15597568,
|
||||
"specularCoef": 50,
|
||||
|
@ -45,7 +45,7 @@
|
|||
"visible": true,
|
||||
"blending": "NormalBlending",
|
||||
"DbgIndex": 1,
|
||||
"opacity": 0.0
|
||||
"opacity": 1.0
|
||||
},{
|
||||
"DbgColor": 60928,
|
||||
"specularCoef": 50,
|
||||
|
@ -62,7 +62,7 @@
|
|||
"visible": true,
|
||||
"blending": "NormalBlending",
|
||||
"DbgIndex": 2,
|
||||
"opacity": 0.0
|
||||
"opacity": 1.0
|
||||
},{
|
||||
"DbgColor": 238,
|
||||
"specularCoef": 50,
|
||||
|
@ -79,7 +79,7 @@
|
|||
"visible": true,
|
||||
"blending": "NormalBlending",
|
||||
"DbgIndex": 3,
|
||||
"opacity": 0.0
|
||||
"opacity": 1.0
|
||||
},{
|
||||
"DbgColor": 15658496,
|
||||
"specularCoef": 50,
|
||||
|
@ -96,6 +96,6 @@
|
|||
"visible": true,
|
||||
"blending": "NormalBlending",
|
||||
"DbgIndex": 4,
|
||||
"opacity": 0.0
|
||||
"opacity": 1.0
|
||||
}]
|
||||
}
|
|
@ -28,7 +28,7 @@
|
|||
"visible": true,
|
||||
"blending": "NormalBlending",
|
||||
"DbgIndex": 0,
|
||||
"opacity": 0.0
|
||||
"opacity": 1.0
|
||||
},{
|
||||
"DbgColor": 15597568,
|
||||
"specularCoef": 50,
|
||||
|
@ -45,7 +45,7 @@
|
|||
"visible": true,
|
||||
"blending": "NormalBlending",
|
||||
"DbgIndex": 1,
|
||||
"opacity": 0.0
|
||||
"opacity": 1.0
|
||||
},{
|
||||
"DbgColor": 60928,
|
||||
"specularCoef": 50,
|
||||
|
@ -62,7 +62,7 @@
|
|||
"visible": true,
|
||||
"blending": "NormalBlending",
|
||||
"DbgIndex": 2,
|
||||
"opacity": 0.0
|
||||
"opacity": 1.0
|
||||
},{
|
||||
"DbgColor": 238,
|
||||
"specularCoef": 50,
|
||||
|
@ -79,7 +79,7 @@
|
|||
"visible": true,
|
||||
"blending": "NormalBlending",
|
||||
"DbgIndex": 3,
|
||||
"opacity": 0.0
|
||||
"opacity": 1.0
|
||||
},{
|
||||
"DbgColor": 15658496,
|
||||
"specularCoef": 50,
|
||||
|
@ -96,6 +96,6 @@
|
|||
"visible": true,
|
||||
"blending": "NormalBlending",
|
||||
"DbgIndex": 4,
|
||||
"opacity": 0.0
|
||||
"opacity": 1.0
|
||||
}]
|
||||
}
|
|
@ -28,7 +28,7 @@
|
|||
"visible": true,
|
||||
"blending": "NormalBlending",
|
||||
"DbgIndex": 0,
|
||||
"opacity": 0.0
|
||||
"opacity": 1.0
|
||||
},{
|
||||
"DbgColor": 15597568,
|
||||
"specularCoef": 50,
|
||||
|
@ -45,7 +45,7 @@
|
|||
"visible": true,
|
||||
"blending": "NormalBlending",
|
||||
"DbgIndex": 1,
|
||||
"opacity": 0.0
|
||||
"opacity": 1.0
|
||||
},{
|
||||
"DbgColor": 60928,
|
||||
"specularCoef": 50,
|
||||
|
@ -62,7 +62,7 @@
|
|||
"visible": true,
|
||||
"blending": "NormalBlending",
|
||||
"DbgIndex": 2,
|
||||
"opacity": 0.0
|
||||
"opacity": 1.0
|
||||
},{
|
||||
"DbgColor": 238,
|
||||
"specularCoef": 50,
|
||||
|
@ -79,7 +79,7 @@
|
|||
"visible": true,
|
||||
"blending": "NormalBlending",
|
||||
"DbgIndex": 3,
|
||||
"opacity": 0.0
|
||||
"opacity": 1.0
|
||||
},{
|
||||
"DbgColor": 15658496,
|
||||
"specularCoef": 50,
|
||||
|
@ -96,6 +96,6 @@
|
|||
"visible": true,
|
||||
"blending": "NormalBlending",
|
||||
"DbgIndex": 4,
|
||||
"opacity": 0.0
|
||||
"opacity": 1.0
|
||||
}]
|
||||
}
|
|
@ -315,10 +315,10 @@ def render_vtail
|
|||
m.draw_body 100,180,140,160
|
||||
m.draw_body 100,180,60,160
|
||||
m.end_body
|
||||
m.draw_circle 140,160,"1",Model::CW,Model::SE
|
||||
m.draw_circle 160,40,"2",Model::CCW,Model::NE
|
||||
m.draw_circle 60,160,"3",Model::CCW,Model::SW
|
||||
m.draw_circle 40,40,"4",Model::CW,Model::NW
|
||||
m.draw_circle 140,160,"1",Model::CCW,Model::SE
|
||||
m.draw_circle 160,40,"2",Model::CW,Model::NE
|
||||
m.draw_circle 60,160,"3",Model::CW,Model::SW
|
||||
m.draw_circle 40,40,"4",Model::CCW,Model::NW
|
||||
m.draw_dirn
|
||||
m.close
|
||||
end
|
||||
|
|
|
@ -141,6 +141,13 @@ TABS.cli.read = function (readInfo) {
|
|||
text += "<br />";
|
||||
}
|
||||
break;
|
||||
case 60:
|
||||
text += '<';
|
||||
break;
|
||||
case 62:
|
||||
text += '>';
|
||||
break;
|
||||
|
||||
default:
|
||||
text += String.fromCharCode(data[i]);
|
||||
}
|
||||
|
|
|
@ -99,6 +99,13 @@
|
|||
|
||||
border: 1px solid silver;
|
||||
}
|
||||
|
||||
.tab-configuration .number input.disabled {
|
||||
width: 50px;
|
||||
padding: 0px 5px;
|
||||
background-color: #ececec;
|
||||
}
|
||||
|
||||
.tab-configuration .number span {
|
||||
margin-left: 10px;
|
||||
line-height: 20px;
|
||||
|
@ -154,7 +161,6 @@
|
|||
.tab-configuration .disarm .checkbox span {
|
||||
margin-left: 15px;
|
||||
}
|
||||
|
||||
.tab-configuration .save {
|
||||
display: block;
|
||||
float: right;
|
||||
|
|
|
@ -127,19 +127,10 @@
|
|||
<!-- list generated here -->
|
||||
</select>
|
||||
|
||||
<div class="groupTitle" i18n="configurationRSSI"></div>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th i18n="configurationFeatureEnabled"></th>
|
||||
<th i18n="configurationFeatureName"></th>
|
||||
<th i18n="configurationFeatureDescription"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="features rssi">
|
||||
<!-- table generated here -->
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="help">
|
||||
<p i18n="configurationSerialRXHelp"></p>
|
||||
</div>
|
||||
|
||||
<div class="groupTitle" i18n="configurationFailsafe"></div>
|
||||
<table>
|
||||
<thead>
|
||||
|
@ -159,8 +150,6 @@
|
|||
<span i18n="configurationThrottleFailsafe"></span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
<div class="rightWrapper current voltage">
|
||||
<div class="groupTitle" i18n="configurationBatteryVoltage"></div>
|
||||
|
@ -201,7 +190,7 @@
|
|||
<span i18n="configurationBatteryScale"></span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="groupTitle" i18n="configurationCurrent"></div>
|
||||
<div class="groupTitle" i18n="configurationCurrent"></div>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
|
@ -233,8 +222,42 @@
|
|||
</div>
|
||||
<span i18n="configurationBatteryMultiwiiCurrent"></span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="clear-both"></div>
|
||||
|
||||
<div class="leftWrapper rssi">
|
||||
<div class="groupTitle" i18n="configurationRSSI"></div>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th i18n="configurationFeatureEnabled"></th>
|
||||
<th i18n="configurationFeatureName"></th>
|
||||
<th i18n="configurationFeatureDescription"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="features rssi">
|
||||
<!-- table generated here -->
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="rightWrapper system">
|
||||
<div class="groupTitle" i18n="configurationSystem"></div>
|
||||
<div class="number">
|
||||
<label>
|
||||
<input type="number" name="looptime" step="100" min="0" max="9000"/>
|
||||
<span i18n="configurationLoopTime"></span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="number">
|
||||
<label>
|
||||
<input type="text" name="looptimehz" readonly="readonly" class="disabled"/>
|
||||
<span i18n="configurationCalculatedCyclesSec"></span>
|
||||
</label>
|
||||
</div>
|
||||
<p class="help" i18n="configurationLoopTimeHelp"></p>
|
||||
</div>
|
||||
|
||||
<div class="clear-both"></div>
|
||||
<div class="leftWrapper gps">
|
||||
<div class="groupTitle" i18n="configurationGPS"></div>
|
||||
|
@ -275,6 +298,11 @@
|
|||
<span i18n="configurationMagDeclination"></span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="help">
|
||||
<p i18n="configurationGPSHelp"></p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="rightWrapper">
|
||||
<div class="groupTitle" i18n="configurationFeatures"></div>
|
||||
|
@ -291,6 +319,7 @@
|
|||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="clear-both"></div>
|
||||
<div class="buttons">
|
||||
<a class="save" href="#" i18n="configurationButtonSave"></a>
|
||||
|
|
|
@ -36,7 +36,11 @@ TABS.configuration.initialize = function (callback, scrollPosition) {
|
|||
}
|
||||
|
||||
function load_arming_config() {
|
||||
MSP.send_message(MSP_codes.MSP_ARMING_CONFIG, false, false, load_html);
|
||||
MSP.send_message(MSP_codes.MSP_ARMING_CONFIG, false, false, load_loop_time);
|
||||
}
|
||||
|
||||
function load_loop_time() {
|
||||
MSP.send_message(MSP_codes.MSP_LOOP_TIME, false, false, load_html);
|
||||
}
|
||||
|
||||
function load_html() {
|
||||
|
@ -45,6 +49,17 @@ TABS.configuration.initialize = function (callback, scrollPosition) {
|
|||
|
||||
MSP.send_message(MSP_codes.MSP_IDENT, false, false, load_config);
|
||||
|
||||
function recalculate_cycles_sec() {
|
||||
var looptime = $('input[name="looptime"]').val();
|
||||
|
||||
var message = 'Max';
|
||||
if (looptime > 0) {
|
||||
message = parseFloat((1 / looptime) * 1000 * 1000).toFixed(0);
|
||||
}
|
||||
|
||||
$('input[name="looptimehz"]').val(message);
|
||||
}
|
||||
|
||||
function process_html() {
|
||||
// translate to user-selected language
|
||||
localize();
|
||||
|
@ -73,7 +88,7 @@ TABS.configuration.initialize = function (callback, scrollPosition) {
|
|||
{bit: 3, group: 'rxMode', mode: 'group', name: 'RX_SERIAL', description: 'Serial-based receiver (SPEKSAT, SBUS, SUMD)'},
|
||||
{bit: 4, group: 'esc', name: 'MOTOR_STOP', description: 'Don\'t spin the motors when armed'},
|
||||
{bit: 5, group: 'other', name: 'SERVO_TILT', description: 'Servo gimbal'},
|
||||
{bit: 6, group: 'other', name: 'SOFTSERIAL', description: 'Enable CPU based serial ports (configure port scenario first)'},
|
||||
{bit: 6, group: 'other', name: 'SOFTSERIAL', description: 'Enable CPU based serial ports'},
|
||||
{bit: 7, group: 'gps', name: 'GPS', description: 'GPS (configure port scenario first)'},
|
||||
{bit: 8, group: 'rxFailsafe', name: 'FAILSAFE', description: 'Failsafe settings on RX signal loss'},
|
||||
{bit: 9, group: 'other', name: 'SONAR', description: 'Sonar'},
|
||||
|
@ -88,6 +103,12 @@ TABS.configuration.initialize = function (callback, scrollPosition) {
|
|||
{bit: 18, group: 'esc', name: 'ONESHOT125', description: 'ONESHOT ESC support (disconnect ESCs, remove props)'},
|
||||
{bit: 19, group: 'other', name: 'BLACKBOX', description: 'Blackbox flight data recorder'}
|
||||
];
|
||||
|
||||
if (semver.gte(CONFIG.apiVersion, "1.12.0")) {
|
||||
features.push(
|
||||
{bit: 20, group: 'other', name: 'CHANNEL_FORWARDING', description: 'Forward aux channels to remaining servo outputs'}
|
||||
);
|
||||
}
|
||||
|
||||
var radioGroups = [];
|
||||
|
||||
|
@ -256,7 +277,7 @@ TABS.configuration.initialize = function (callback, scrollPosition) {
|
|||
// fill magnetometer
|
||||
$('input[name="mag_declination"]').val(MISC.mag_declination);
|
||||
|
||||
//fill motor disarm params
|
||||
//fill motor disarm params and FC loop time
|
||||
if(semver.gte(CONFIG.apiVersion, "1.8.0")) {
|
||||
$('input[name="autodisarmdelay"]').val(ARMING_CONFIG.auto_disarm_delay);
|
||||
$('input[name="disarmkillswitch"]').prop('checked', ARMING_CONFIG.disarm_kill_switch);
|
||||
|
@ -265,6 +286,13 @@ TABS.configuration.initialize = function (callback, scrollPosition) {
|
|||
$('div.disarmdelay').show();
|
||||
else
|
||||
$('div.disarmdelay').hide();
|
||||
|
||||
// fill FC loop time
|
||||
$('input[name="looptime"]').val(FC_CONFIG.loopTime);
|
||||
|
||||
recalculate_cycles_sec();
|
||||
|
||||
$('div.cycles').show();
|
||||
}
|
||||
|
||||
// fill throttle
|
||||
|
@ -287,6 +315,10 @@ TABS.configuration.initialize = function (callback, scrollPosition) {
|
|||
|
||||
|
||||
// UI hooks
|
||||
$('input[name="looptime"]').change(function() {
|
||||
recalculate_cycles_sec();
|
||||
});
|
||||
|
||||
$('input[type="checkbox"].feature', features_e).change(function () {
|
||||
var element = $(this),
|
||||
index = element.data('bit'),
|
||||
|
@ -338,6 +370,7 @@ TABS.configuration.initialize = function (callback, scrollPosition) {
|
|||
if(semver.gte(CONFIG.apiVersion, "1.8.0")) {
|
||||
ARMING_CONFIG.auto_disarm_delay = parseInt($('input[name="autodisarmdelay"]').val());
|
||||
ARMING_CONFIG.disarm_kill_switch = ~~$('input[name="disarmkillswitch"]').is(':checked'); // ~~ boolean to decimal conversion
|
||||
FC_CONFIG.loopTime = parseInt($('input[name="looptime"]').val());
|
||||
}
|
||||
|
||||
MISC.minthrottle = parseInt($('input[name="minthrottle"]').val());
|
||||
|
@ -373,7 +406,11 @@ TABS.configuration.initialize = function (callback, scrollPosition) {
|
|||
}
|
||||
|
||||
function save_arming_config() {
|
||||
MSP.send_message(MSP_codes.MSP_SET_ARMING_CONFIG, MSP.crunch(MSP_codes.MSP_SET_ARMING_CONFIG), false, save_to_eeprom);
|
||||
MSP.send_message(MSP_codes.MSP_SET_ARMING_CONFIG, MSP.crunch(MSP_codes.MSP_SET_ARMING_CONFIG), false, save_looptime_config);
|
||||
}
|
||||
|
||||
function save_looptime_config() {
|
||||
MSP.send_message(MSP_codes.MSP_SET_LOOP_TIME, MSP.crunch(MSP_codes.MSP_SET_LOOP_TIME), false, save_to_eeprom);
|
||||
}
|
||||
|
||||
function save_to_eeprom() {
|
||||
|
|
|
@ -146,53 +146,66 @@ TABS.dataflash.initialize = function (callback) {
|
|||
$(".dataflash-saving").addClass("done");
|
||||
}
|
||||
|
||||
function flash_save_begin() {
|
||||
var
|
||||
maxBytes = DATAFLASH.usedSize;
|
||||
|
||||
if (GUI.connected_to) {
|
||||
prepare_file(function(fileWriter) {
|
||||
var
|
||||
nextAddress = 0;
|
||||
|
||||
show_saving_dialog();
|
||||
|
||||
function onChunkRead(chunkAddress, chunkDataView) {
|
||||
if (chunkDataView != null) {
|
||||
// Did we receive any data?
|
||||
if (chunkDataView.byteLength > 0) {
|
||||
nextAddress += chunkDataView.byteLength;
|
||||
|
||||
$(".dataflash-saving progress").attr("value", nextAddress / maxBytes * 100);
|
||||
function flash_update_summary(onDone) {
|
||||
MSP.send_message(MSP_codes.MSP_DATAFLASH_SUMMARY, false, false, function() {
|
||||
update_html();
|
||||
|
||||
if (onDone) {
|
||||
onDone();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
var
|
||||
blob = new Blob([chunkDataView]);
|
||||
|
||||
fileWriter.onwriteend = function(e) {
|
||||
if (saveCancelled || nextAddress >= maxBytes) {
|
||||
if (saveCancelled) {
|
||||
dismiss_saving_dialog();
|
||||
} else {
|
||||
mark_saving_dialog_done();
|
||||
}
|
||||
} else {
|
||||
MSP.dataflashRead(nextAddress, onChunkRead);
|
||||
}
|
||||
};
|
||||
|
||||
fileWriter.write(blob);
|
||||
} else {
|
||||
// A zero-byte block indicates end-of-file, so we're done
|
||||
mark_saving_dialog_done();
|
||||
}
|
||||
} else {
|
||||
// There was an error with the received block (address didn't match the one we asked for), retry
|
||||
MSP.dataflashRead(nextAddress, onChunkRead);
|
||||
}
|
||||
}
|
||||
function flash_save_begin() {
|
||||
if (GUI.connected_to) {
|
||||
// Begin by refreshing the occupied size in case it changed while the tab was open
|
||||
flash_update_summary(function() {
|
||||
var
|
||||
maxBytes = DATAFLASH.usedSize;
|
||||
|
||||
// Fetch the initial block
|
||||
MSP.dataflashRead(nextAddress, onChunkRead);
|
||||
prepare_file(function(fileWriter) {
|
||||
var
|
||||
nextAddress = 0;
|
||||
|
||||
show_saving_dialog();
|
||||
|
||||
function onChunkRead(chunkAddress, chunkDataView) {
|
||||
if (chunkDataView != null) {
|
||||
// Did we receive any data?
|
||||
if (chunkDataView.byteLength > 0) {
|
||||
nextAddress += chunkDataView.byteLength;
|
||||
|
||||
$(".dataflash-saving progress").attr("value", nextAddress / maxBytes * 100);
|
||||
|
||||
var
|
||||
blob = new Blob([chunkDataView]);
|
||||
|
||||
fileWriter.onwriteend = function(e) {
|
||||
if (saveCancelled || nextAddress >= maxBytes) {
|
||||
if (saveCancelled) {
|
||||
dismiss_saving_dialog();
|
||||
} else {
|
||||
mark_saving_dialog_done();
|
||||
}
|
||||
} else {
|
||||
MSP.dataflashRead(nextAddress, onChunkRead);
|
||||
}
|
||||
};
|
||||
|
||||
fileWriter.write(blob);
|
||||
} else {
|
||||
// A zero-byte block indicates end-of-file, so we're done
|
||||
mark_saving_dialog_done();
|
||||
}
|
||||
} else {
|
||||
// There was an error with the received block (address didn't match the one we asked for), retry
|
||||
MSP.dataflashRead(nextAddress, onChunkRead);
|
||||
}
|
||||
}
|
||||
|
||||
// Fetch the initial block
|
||||
MSP.dataflashRead(nextAddress, onChunkRead);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -246,8 +259,7 @@ TABS.dataflash.initialize = function (callback) {
|
|||
}
|
||||
|
||||
function poll_for_erase_completion() {
|
||||
MSP.send_message(MSP_codes.MSP_DATAFLASH_SUMMARY, false, false, function() {
|
||||
update_html();
|
||||
flash_update_summary(function() {
|
||||
if (!eraseCancelled) {
|
||||
if (DATAFLASH.ready) {
|
||||
$(".dataflash-confirm-erase")[0].close();
|
||||
|
|
|
@ -39,7 +39,7 @@ TABS.firmware_flasher.initialize = function (callback) {
|
|||
var showDevReleases = ($('input.show_development_releases').is(':checked'));
|
||||
releases_e.append($("<option value='0'>{0}</option>".format(chrome.i18n.getMessage('firmwareFlasherOptionLabelSelectFirmware'))));
|
||||
|
||||
var releaseDescritpors = [];
|
||||
var releaseDescriptors = [];
|
||||
TABS.firmware_flasher.releases.forEach(function(release){
|
||||
release.assets.forEach(function(asset){
|
||||
var targetFromFilenameExpression = /.*_(.*)\.(.*)/;
|
||||
|
@ -81,11 +81,11 @@ TABS.firmware_flasher.initialize = function (callback) {
|
|||
"status" : release.prerelease ? "release-candidate" : "stable"
|
||||
};
|
||||
|
||||
releaseDescritpors.push(descriptor);
|
||||
releaseDescriptors.push(descriptor);
|
||||
});
|
||||
});
|
||||
|
||||
releaseDescritpors.sort(function(o1,o2){
|
||||
releaseDescriptors.sort(function(o1,o2){
|
||||
// compare versions descending
|
||||
var cmpVal = semver(o2.version).compare(semver(o1.version));
|
||||
if (cmpVal == 0){
|
||||
|
@ -96,7 +96,7 @@ TABS.firmware_flasher.initialize = function (callback) {
|
|||
});
|
||||
|
||||
var optionIndex = 1;
|
||||
releaseDescritpors.forEach(function(descriptor){
|
||||
releaseDescriptors.forEach(function(descriptor){
|
||||
var select_e =
|
||||
$("<option value='{0}'>{1} {2} {3} ({4})</option>".format(
|
||||
optionIndex++,
|
||||
|
|
|
@ -60,6 +60,9 @@
|
|||
<p>
|
||||
• <a href="http://www.overskyrc.com" title="www.overskyrc.com" target="_blank">OverSkyRC</a><br />
|
||||
</p>
|
||||
<p>
|
||||
• <a href="http://multirotormania.com" title="multirotormania.com" target="_blank">Multi Rotor Mania</a><br />
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -272,7 +272,7 @@ TABS.motors.initialize = function (callback) {
|
|||
');
|
||||
|
||||
servos_wrapper.append('\
|
||||
<div class="m-block servo-' + i + '">\
|
||||
<div class="m-block servo-' + (7 - i) + '">\
|
||||
<div class="meter-bar">\
|
||||
<div class="label"></div>\
|
||||
<div class="indicator">\
|
||||
|
|
|
@ -71,13 +71,13 @@
|
|||
border: 1px dashed silver;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.require-support {
|
||||
.tab-ports .require-support {
|
||||
display:none;
|
||||
}
|
||||
.tab-ports.supported .require-support {
|
||||
display:block;
|
||||
}
|
||||
.require-upgrade {
|
||||
.tab-ports .require-upgrade {
|
||||
display:block;
|
||||
}
|
||||
.tab-ports.supported .require-upgrade {
|
||||
|
|
|
@ -18,6 +18,11 @@
|
|||
<tbody>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<div class="help">
|
||||
<p i18n="portsMSPHelp"></p>
|
||||
</div>
|
||||
|
||||
<div class="clear-both"></div>
|
||||
<div class="buttons">
|
||||
<a class="save" href="#" i18n="portsButtonSave"></a>
|
||||
|
|
|
@ -3,6 +3,12 @@
|
|||
.tab-receiver input[type="number"]::-webkit-inner-spin-button {
|
||||
border: 0;
|
||||
}
|
||||
.tab-receiver .help {
|
||||
padding: 10px;
|
||||
background-color: #ffcb18;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.tab-receiver .bars {
|
||||
float: left;
|
||||
width: 45%;
|
||||
|
@ -218,7 +224,7 @@
|
|||
margin: 0 10px 10px 0;
|
||||
|
||||
width: 220px;
|
||||
height: 58px;
|
||||
height: 120px;
|
||||
|
||||
border: 1px solid silver;
|
||||
}
|
||||
|
@ -226,7 +232,7 @@
|
|||
margin: 0 10px 0 0;
|
||||
|
||||
width: 220px;
|
||||
height: 58px;
|
||||
height: 120px;
|
||||
|
||||
border: 1px solid silver;
|
||||
}
|
||||
|
@ -293,6 +299,7 @@
|
|||
position: absolute;
|
||||
bottom: 10px;
|
||||
}
|
||||
.tab-receiver .sticks,
|
||||
.tab-receiver .update,
|
||||
.tab-receiver .refresh {
|
||||
display: block;
|
||||
|
@ -311,6 +318,7 @@
|
|||
border: 1px solid silver;
|
||||
background-color: #ececec;
|
||||
}
|
||||
.tab-receiver .sticks,
|
||||
.tab-receiver .refresh {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
@ -334,4 +342,4 @@
|
|||
fill: none;
|
||||
stroke: #000;
|
||||
shape-rendering: crispEdges;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
<div id="content-watermark"></div>
|
||||
<div class="tab-receiver">
|
||||
<div class="help">
|
||||
<p i18n="receiverHelp"></p>
|
||||
</div>
|
||||
|
||||
<div class="bars">
|
||||
</div>
|
||||
<div class="tunings">
|
||||
|
@ -53,10 +57,10 @@
|
|||
</div>
|
||||
<div class="curves">
|
||||
<div class="throttle_curve">
|
||||
<canvas width="220" height="58"></canvas>
|
||||
<canvas width="220" height="120"></canvas>
|
||||
</div>
|
||||
<div class="pitch_roll_curve">
|
||||
<canvas width="220" height="58"></canvas>
|
||||
<canvas width="220" height="120"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
<div class="clear-both"></div>
|
||||
|
@ -82,5 +86,6 @@
|
|||
<div class="buttons">
|
||||
<a class="update" href="#" i18n="receiverButtonSave"></a>
|
||||
<a class="refresh" href="#" i18n="receiverButtonRefresh"></a>
|
||||
<a class="sticks" href="#" i18n="receiverButtonSticks"></a>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
'use strict';
|
||||
|
||||
TABS.receiver = {};
|
||||
TABS.receiver = {
|
||||
rateChartHeight: 120
|
||||
};
|
||||
|
||||
TABS.receiver.initialize = function (callback) {
|
||||
var self = this;
|
||||
|
||||
|
@ -18,7 +21,12 @@ TABS.receiver.initialize = function (callback) {
|
|||
}
|
||||
|
||||
function get_rc_map() {
|
||||
MSP.send_message(MSP_codes.MSP_RX_MAP, false, false, load_html);
|
||||
MSP.send_message(MSP_codes.MSP_RX_MAP, false, false, load_config);
|
||||
}
|
||||
|
||||
// Fetch features so we can check if RX_MSP is enabled:
|
||||
function load_config() {
|
||||
MSP.send_message(MSP_codes.MSP_BF_CONFIG, false, false, load_html);
|
||||
}
|
||||
|
||||
function load_html() {
|
||||
|
@ -38,11 +46,11 @@ TABS.receiver.initialize = function (callback) {
|
|||
$('.tunings .rate input[name="rate"]').val(RC_tuning.RC_RATE.toFixed(2));
|
||||
$('.tunings .rate input[name="expo"]').val(RC_tuning.RC_EXPO.toFixed(2));
|
||||
$('.tunings .yaw_rate input[name="yaw_expo"]').val(RC_tuning.RC_YAW_EXPO.toFixed(2));
|
||||
|
||||
|
||||
if (semver.lt(CONFIG.apiVersion, "1.10.0")) {
|
||||
$('.tunings .yaw_rate input[name="yaw_expo"]').hide();
|
||||
}
|
||||
|
||||
|
||||
chrome.storage.local.get('rx_refresh_rate', function (result) {
|
||||
if (result.rx_refresh_rate) {
|
||||
$('select[name="rx_refresh_rate"]').val(result.rx_refresh_rate).change();
|
||||
|
@ -52,7 +60,12 @@ TABS.receiver.initialize = function (callback) {
|
|||
});
|
||||
|
||||
// generate bars
|
||||
var bar_names = ['Roll', 'Pitch', 'Yaw', 'Throttle'],
|
||||
var bar_names = [
|
||||
chrome.i18n.getMessage('controlAxisRoll'),
|
||||
chrome.i18n.getMessage('controlAxisPitch'),
|
||||
chrome.i18n.getMessage('controlAxisYaw'),
|
||||
chrome.i18n.getMessage('controlAxisThrottle')
|
||||
],
|
||||
bar_container = $('.tab-receiver .bars'),
|
||||
aux_index = 1;
|
||||
|
||||
|
@ -61,7 +74,7 @@ TABS.receiver.initialize = function (callback) {
|
|||
if (i < bar_names.length) {
|
||||
name = bar_names[i];
|
||||
} else {
|
||||
name = 'AUX ' + aux_index++;
|
||||
name = chrome.i18n.getMessage("controlAxisAux" + (aux_index++));
|
||||
}
|
||||
|
||||
bar_container.append('\
|
||||
|
@ -176,6 +189,8 @@ TABS.receiver.initialize = function (callback) {
|
|||
|
||||
$('select[name="rssi_channel"]').val(MISC.rssi_channel);
|
||||
|
||||
var rateHeight = TABS.receiver.rateChartHeight;
|
||||
|
||||
// UI Hooks
|
||||
// curves
|
||||
$('.tunings .throttle input').on('input change', function () {
|
||||
|
@ -201,14 +216,14 @@ TABS.receiver.initialize = function (callback) {
|
|||
var midx = 220 * mid,
|
||||
midxl = midx * 0.5,
|
||||
midxr = (((220 - midx) * 0.5) + midx),
|
||||
midy = 58 - (midx * (58 / 220)),
|
||||
midyl = 58 - ((58 - midy) * 0.5 *(expo + 1)),
|
||||
midy = rateHeight - (midx * (rateHeight / 220)),
|
||||
midyl = rateHeight - ((rateHeight - midy) * 0.5 *(expo + 1)),
|
||||
midyr = (midy / 2) * (expo + 1);
|
||||
|
||||
// draw
|
||||
context.clearRect(0, 0, 220, 58);
|
||||
context.clearRect(0, 0, 220, rateHeight);
|
||||
context.beginPath();
|
||||
context.moveTo(0, 58);
|
||||
context.moveTo(0, rateHeight);
|
||||
context.quadraticCurveTo(midxl, midyl, midx, midy);
|
||||
context.moveTo(midx, midy);
|
||||
context.quadraticCurveTo(midxr, midyr, 220, 0);
|
||||
|
@ -237,13 +252,13 @@ TABS.receiver.initialize = function (callback) {
|
|||
}
|
||||
|
||||
// math magic by englishman
|
||||
var ratey = 58 * rate;
|
||||
var ratey = rateHeight * rate;
|
||||
|
||||
// draw
|
||||
context.clearRect(0, 0, 220, 58);
|
||||
context.clearRect(0, 0, 220, rateHeight);
|
||||
context.beginPath();
|
||||
context.moveTo(0, 58);
|
||||
context.quadraticCurveTo(110, 58 - ((ratey / 2) * (1 - expo)), 220, 58 - ratey);
|
||||
context.moveTo(0, rateHeight);
|
||||
context.quadraticCurveTo(110, rateHeight - ((ratey / 2) * (1 - expo)), 220, rateHeight - ratey);
|
||||
context.lineWidth = 2;
|
||||
context.stroke();
|
||||
}, 0);
|
||||
|
@ -302,6 +317,35 @@ TABS.receiver.initialize = function (callback) {
|
|||
|
||||
MSP.send_message(MSP_codes.MSP_SET_RC_TUNING, MSP.crunch(MSP_codes.MSP_SET_RC_TUNING), false, save_rc_map);
|
||||
});
|
||||
|
||||
$("a.sticks").click(function() {
|
||||
var
|
||||
windowWidth = 370,
|
||||
windowHeight = 510;
|
||||
|
||||
chrome.app.window.create("/tabs/receiver_msp.html", {
|
||||
id: "receiver_msp",
|
||||
innerBounds: {
|
||||
minWidth: windowWidth, minHeight: windowHeight,
|
||||
width: windowWidth, height: windowHeight,
|
||||
maxWidth: windowWidth, maxHeight: windowHeight
|
||||
},
|
||||
alwaysOnTop: true
|
||||
}, function(createdWindow) {
|
||||
// Give the window a callback it can use to send the channels (otherwise it can't see those objects)
|
||||
createdWindow.contentWindow.setRawRx = function(channels) {
|
||||
if (CONFIGURATOR.connectionValid && GUI.active_tab != 'cli') {
|
||||
MSP.setRawRx(channels);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Only show the MSP control sticks if the MSP Rx feature is enabled
|
||||
$("a.sticks").toggle(bit_check(BF_CONFIG.features, 14 /* RX_MSP */));
|
||||
|
||||
$('select[name="rx_refresh_rate"]').change(function () {
|
||||
var plot_update_rate = parseInt($(this).val(), 10);
|
||||
|
|
109
tabs/receiver_msp.css
Normal file
109
tabs/receiver_msp.css
Normal file
|
@ -0,0 +1,109 @@
|
|||
body {
|
||||
font-family: 'Segoe UI', Tahoma, sans-serif;
|
||||
font-size: 12px;
|
||||
color: #303030;
|
||||
margin: 10px;
|
||||
}
|
||||
|
||||
.control-gimbals {
|
||||
/* A generous padding around the window edges ensures that we continue to receive mousemove events (since
|
||||
* cursor stays in the window for longer)
|
||||
*/
|
||||
padding:25px;
|
||||
padding-bottom:0;
|
||||
text-align:center;
|
||||
}
|
||||
|
||||
.control-gimbal {
|
||||
position:relative;
|
||||
width:120px;
|
||||
height:120px;
|
||||
background-color:#eee;
|
||||
margin-left:1em;
|
||||
margin-right:1em;
|
||||
margin-bottom:2em;
|
||||
display:inline-block;
|
||||
border-radius:5px;
|
||||
|
||||
cursor:pointer;
|
||||
}
|
||||
|
||||
.crosshair {
|
||||
display:block;
|
||||
position:absolute;
|
||||
background-color:#ddd;
|
||||
}
|
||||
|
||||
.crosshair-vert {
|
||||
width:1px;
|
||||
height:100%;
|
||||
left:50%;
|
||||
}
|
||||
|
||||
.crosshair-horz {
|
||||
height:1px;
|
||||
width:100%;
|
||||
top:50%;
|
||||
}
|
||||
|
||||
.gimbal-label {
|
||||
display:block;
|
||||
position:absolute;
|
||||
text-align:center;
|
||||
}
|
||||
|
||||
.gimbal-label-horz {
|
||||
top:calc(100% + 0.5em);
|
||||
width:100%;
|
||||
}
|
||||
|
||||
.gimbal-label-vert {
|
||||
transform:rotate(-90deg);
|
||||
/*transform-origin:0% 100%;*/
|
||||
top:calc(50% - 0.5em);
|
||||
width:100%;
|
||||
left:calc(-50% - 1em);
|
||||
}
|
||||
|
||||
.control-stick {
|
||||
background-color:rgba(255,50,50,1.0);
|
||||
width:20px;
|
||||
height:20px;
|
||||
margin-left:-10px;
|
||||
margin-top:-10px;
|
||||
display:block;
|
||||
border-radius:100%;
|
||||
position:absolute;
|
||||
|
||||
cursor:pointer;
|
||||
}
|
||||
|
||||
.control-slider {
|
||||
margin:20px;
|
||||
}
|
||||
|
||||
.tooltip {
|
||||
position: absolute;
|
||||
left: calc(100% + 24px);
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.control-slider .slider {
|
||||
margin-left:50px;
|
||||
margin-right:50px;
|
||||
}
|
||||
|
||||
.slider-label {
|
||||
position:absolute;
|
||||
text-align:right;
|
||||
width:40px;
|
||||
left:-65px;
|
||||
}
|
||||
|
||||
.button-enable {
|
||||
padding:0.5em;
|
||||
font-size:110%;
|
||||
margin-left:auto;
|
||||
margin-right:auto;
|
||||
display:block;
|
||||
}
|
71
tabs/receiver_msp.html
Normal file
71
tabs/receiver_msp.html
Normal file
|
@ -0,0 +1,71 @@
|
|||
<html>
|
||||
<head>
|
||||
<script type="text/javascript" src="/js/libraries/jquery-2.1.4.min.js"></script>
|
||||
<script type="text/javascript" src="/js/libraries/jquery-ui-1.11.4.min.js"></script>
|
||||
<script type="text/javascript" src="/js/libraries/jquery.nouislider.all.min.js"></script>
|
||||
|
||||
<script type="text/javascript" src="receiver_msp.js"></script>
|
||||
|
||||
<link type="text/css" rel="stylesheet" href="/js/libraries/jquery.nouislider.min.css">
|
||||
<link type="text/css" rel="stylesheet" href="/js/libraries/jquery.nouislider.pips.min.css">
|
||||
|
||||
<link type="text/css" rel="stylesheet" href="receiver_msp.css" media="all" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="control-gimbals">
|
||||
<div class="control-gimbal left">
|
||||
<span class="gimbal-label gimbal-label-vert"></span>
|
||||
<span class="gimbal-label gimbal-label-horz"></span>
|
||||
|
||||
<span class="crosshair crosshair-vert"></span>
|
||||
<span class="crosshair crosshair-horz"></span>
|
||||
<div class="control-stick">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-gimbal right">
|
||||
<span class="gimbal-label gimbal-label-vert"></span>
|
||||
<span class="gimbal-label gimbal-label-horz"></span>
|
||||
|
||||
<span class="crosshair crosshair-vert"></span>
|
||||
<span class="crosshair crosshair-horz"></span>
|
||||
<div class="control-stick">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-sliders">
|
||||
<div class="control-slider">
|
||||
<div class="slider">
|
||||
<span class="slider-label"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-slider">
|
||||
<div class="slider">
|
||||
<span class="slider-label"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-slider">
|
||||
<div class="slider">
|
||||
<span class="slider-label"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-slider">
|
||||
<div class="slider">
|
||||
<span class="slider-label"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="warning">
|
||||
<p>
|
||||
These sticks allow Cleanflight to be armed and tested without a transmitter or receiver being
|
||||
present. However, <strong>this feature is not intended for flight and propellers must not be attached.</strong>
|
||||
</p>
|
||||
<p>
|
||||
This feature does not guarantee reliable control of your craft. <strong>Serious injury is likely to
|
||||
result if propellers are left on.</strong>
|
||||
</p>
|
||||
<button class="button-enable" type="button">Enable controls</button>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
185
tabs/receiver_msp.js
Normal file
185
tabs/receiver_msp.js
Normal file
|
@ -0,0 +1,185 @@
|
|||
"use strict";
|
||||
|
||||
var
|
||||
CHANNEL_MIN_VALUE = 1000,
|
||||
CHANNEL_MID_VALUE = 1500,
|
||||
CHANNEL_MAX_VALUE = 2000,
|
||||
|
||||
// What's the index of each channel in the MSP channel list?
|
||||
channelMSPIndexes = {
|
||||
roll: 0,
|
||||
pitch: 1,
|
||||
yaw: 2,
|
||||
throttle: 3,
|
||||
aux1: 4,
|
||||
aux2: 5,
|
||||
aux3: 6,
|
||||
aux4: 7,
|
||||
},
|
||||
|
||||
// Set reasonable initial stick positions (Mode 2)
|
||||
stickValues = {
|
||||
throttle: CHANNEL_MIN_VALUE,
|
||||
pitch: CHANNEL_MID_VALUE,
|
||||
roll: CHANNEL_MID_VALUE,
|
||||
yaw: CHANNEL_MID_VALUE,
|
||||
aux1: CHANNEL_MIN_VALUE,
|
||||
aux2: CHANNEL_MIN_VALUE,
|
||||
aux3: CHANNEL_MIN_VALUE,
|
||||
aux4: CHANNEL_MIN_VALUE
|
||||
},
|
||||
|
||||
// First the vertical axis, then the horizontal:
|
||||
gimbals = [
|
||||
["throttle", "yaw"],
|
||||
["pitch", "roll"],
|
||||
],
|
||||
|
||||
gimbalElems,
|
||||
sliderElems,
|
||||
|
||||
enableTX = false;
|
||||
|
||||
function transmitChannels() {
|
||||
var
|
||||
channelValues = [0, 0, 0, 0, 0, 0, 0, 0];
|
||||
|
||||
if (!enableTX) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (var stickName in stickValues) {
|
||||
channelValues[channelMSPIndexes[stickName]] = stickValues[stickName];
|
||||
}
|
||||
|
||||
// Callback given to us by the window creator so we can have it send data over MSP for us:
|
||||
if (!window.setRawRx(channelValues)) {
|
||||
// MSP connection has gone away
|
||||
chrome.app.window.current().close();
|
||||
}
|
||||
}
|
||||
|
||||
function stickPortionToChannelValue(portion) {
|
||||
portion = Math.min(Math.max(portion, 0.0), 1.0);
|
||||
|
||||
return Math.round(portion * (CHANNEL_MAX_VALUE - CHANNEL_MIN_VALUE) + CHANNEL_MIN_VALUE);
|
||||
}
|
||||
|
||||
function channelValueToStickPortion(channel) {
|
||||
return (channel - CHANNEL_MIN_VALUE) / (CHANNEL_MAX_VALUE - CHANNEL_MIN_VALUE);
|
||||
}
|
||||
|
||||
function updateControlPositions() {
|
||||
for (var stickName in stickValues) {
|
||||
var
|
||||
stickValue = stickValues[stickName];
|
||||
|
||||
// Look for the gimbal which corresponds to this stick name
|
||||
for (var gimbalIndex in gimbals) {
|
||||
var
|
||||
gimbal = gimbals[gimbalIndex],
|
||||
gimbalElem = gimbalElems.get(gimbalIndex),
|
||||
gimbalSize = $(gimbalElem).width(),
|
||||
stickElem = $(".control-stick", gimbalElem);
|
||||
|
||||
if (gimbal[0] == stickName) {
|
||||
stickElem.css('top', (1.0 - channelValueToStickPortion(stickValue)) * gimbalSize + "px");
|
||||
break;
|
||||
} else if (gimbal[1] == stickName) {
|
||||
stickElem.css('left', channelValueToStickPortion(stickValue) * gimbalSize + "px");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function handleGimbalMouseDrag(e) {
|
||||
var
|
||||
gimbal = $(gimbalElems.get(e.data.gimbalIndex)),
|
||||
gimbalOffset = gimbal.offset(),
|
||||
gimbalSize = gimbal.width();
|
||||
|
||||
stickValues[gimbals[e.data.gimbalIndex][0]] = stickPortionToChannelValue(1.0 - (e.pageY - gimbalOffset.top) / gimbalSize);
|
||||
stickValues[gimbals[e.data.gimbalIndex][1]] = stickPortionToChannelValue((e.pageX - gimbalOffset.left) / gimbalSize);
|
||||
|
||||
updateControlPositions();
|
||||
}
|
||||
|
||||
function localizeAxisNames() {
|
||||
for (var gimbalIndex in gimbals) {
|
||||
var
|
||||
gimbal = gimbalElems.get(gimbalIndex);
|
||||
|
||||
$(".gimbal-label-vert", gimbal).text(chrome.i18n.getMessage("controlAxis" + gimbals[gimbalIndex][0]));
|
||||
$(".gimbal-label-horz", gimbal).text(chrome.i18n.getMessage("controlAxis" + gimbals[gimbalIndex][1]));
|
||||
}
|
||||
|
||||
for (var sliderIndex = 0; sliderIndex < 4; sliderIndex++) {
|
||||
$(".slider-label", sliderElems.get(sliderIndex)).text(chrome.i18n.getMessage("controlAxisAux" + (sliderIndex + 1)));
|
||||
}
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
$(".button-enable").click(function() {
|
||||
var
|
||||
shrinkHeight = $(".warning").height();
|
||||
|
||||
$(".warning").slideUp("short", function() {
|
||||
chrome.app.window.current().innerBounds.minHeight -= shrinkHeight;
|
||||
chrome.app.window.current().innerBounds.height -= shrinkHeight;
|
||||
chrome.app.window.current().innerBounds.maxHeight -= shrinkHeight;
|
||||
});
|
||||
|
||||
enableTX = true;
|
||||
});
|
||||
|
||||
gimbalElems = $(".control-gimbal");
|
||||
sliderElems = $(".control-slider");
|
||||
|
||||
gimbalElems.each(function(gimbalIndex) {
|
||||
$(this).on('mousedown', {gimbalIndex: gimbalIndex}, function(e) {
|
||||
if (e.which == 1) { // Only move sticks on left mouse button
|
||||
handleGimbalMouseDrag(e);
|
||||
|
||||
$(window).on('mousemove', {gimbalIndex: gimbalIndex}, handleGimbalMouseDrag);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$(".slider", sliderElems).each(function(sliderIndex) {
|
||||
var
|
||||
initialValue = stickValues["aux" + (sliderIndex + 1)];
|
||||
|
||||
$(this)
|
||||
.noUiSlider({
|
||||
start: initialValue,
|
||||
range: {
|
||||
min: CHANNEL_MIN_VALUE,
|
||||
max: CHANNEL_MAX_VALUE
|
||||
}
|
||||
}).on('slide change set', function(e, value) {
|
||||
value = Math.round(parseFloat(value));
|
||||
|
||||
stickValues["aux" + (sliderIndex + 1)] = value;
|
||||
|
||||
$(".tooltip", this).text(value);
|
||||
});
|
||||
|
||||
$(this).append('<div class="tooltip"></div>');
|
||||
|
||||
$(".tooltip", this).text(initialValue);
|
||||
});
|
||||
|
||||
/*
|
||||
* Mouseup handler needs to be bound to the window in order to receive mouseup if mouse leaves window.
|
||||
*/
|
||||
$(window).mouseup(function(e) {
|
||||
$(this).off('mousemove', handleGimbalMouseDrag);
|
||||
});
|
||||
|
||||
localizeAxisNames();
|
||||
|
||||
updateControlPositions();
|
||||
|
||||
setInterval(transmitChannels, 50);
|
||||
});
|
|
@ -14,7 +14,8 @@ TABS.sensors.initialize = function (callback) {
|
|||
SENSOR_DATA.accelerometer[i] = 0;
|
||||
SENSOR_DATA.gyroscope[i] = 0;
|
||||
SENSOR_DATA.magnetometer[i] = 0;
|
||||
SENSOR_DATA.sonar[i] = 0;
|
||||
SENSOR_DATA.sonar = 0;
|
||||
SENSOR_DATA.altitude = 0;
|
||||
SENSOR_DATA.debug[i] = 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,10 +3,6 @@
|
|||
.tab-servos input[type="number"]::-webkit-inner-spin-button {
|
||||
border: 0;
|
||||
}
|
||||
.tab-servos .supported_wrapper,
|
||||
.tab-servos .direction_wrapper {
|
||||
display: none;
|
||||
}
|
||||
.tab-servos .title {
|
||||
margin-top: 10px;
|
||||
|
||||
|
@ -129,4 +125,17 @@
|
|||
}
|
||||
.tab-servos .update:hover {
|
||||
background-color: #dedcdc;
|
||||
}
|
||||
}
|
||||
|
||||
.tab-servos .require-support {
|
||||
display:none;
|
||||
}
|
||||
.tab-servos.supported .require-support {
|
||||
display:block;
|
||||
}
|
||||
.tab-servos .require-upgrade {
|
||||
display:block;
|
||||
}
|
||||
.tab-servos.supported .require-upgrade {
|
||||
display:none;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
<div class="tab-servos">
|
||||
<span i18n="servosModel"></span> <strong class="model"></strong>
|
||||
<div class="supported_wrapper">
|
||||
<div class="require-support">
|
||||
<div class="title" i18n="servosChangeDirection"></div>
|
||||
<table class="fields">
|
||||
<tr class="main">
|
||||
|
@ -8,21 +7,14 @@
|
|||
<th style="width: 120px" i18n="servosMid"></th>
|
||||
<th style="width: 120px" i18n="servosMin"></th>
|
||||
<th style="width: 120px" i18n="servosMax"></th>
|
||||
<th style="width: 120px" i18n="servosAngleAtMin"></th>
|
||||
<th style="width: 120px" i18n="servosAngleAtMax"></th>
|
||||
<th style="width: 40px">CH1</th>
|
||||
<th style="width: 40px">CH2</th>
|
||||
<th style="width: 40px">CH3</th>
|
||||
<th style="width: 40px">CH4</th>
|
||||
</tr>
|
||||
</table>
|
||||
<div class="direction_wrapper">
|
||||
<div class="title" style="width: 258px" i18n="servosGyroAccelDirection"></div>
|
||||
<table class="directions" style="width: 260px">
|
||||
<tr class="main">
|
||||
<th style="width: 200px" i18n="servosName"></th>
|
||||
<th i18n="servosDirection"></th>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class="live">
|
||||
<span i18n="servosLiveMode"></span> <input type="checkbox" />
|
||||
</div>
|
||||
|
@ -30,4 +22,7 @@
|
|||
<a class="update" href="#" i18n="servosButtonSave"></a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="note require-upgrade" i18n="servosFirmwareUpgradeRequired">
|
||||
</div>
|
||||
</div>
|
290
tabs/servos.js
290
tabs/servos.js
|
@ -1,9 +1,3 @@
|
|||
/* Please don't take code in this file very seriously !!!
|
||||
|
||||
I was "kinda" forced to write this implementation "this way" because the Servo code implementation
|
||||
from multiwii is so horrible, obstructive and non dynamic, not to mention it doesn't make any sense
|
||||
that there was just no other way around this then hardcoding/implementing each model separately.
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
TABS.servos = {};
|
||||
|
@ -15,15 +9,25 @@ TABS.servos.initialize = function (callback) {
|
|||
googleAnalytics.sendAppView('Servos');
|
||||
}
|
||||
|
||||
function get_servo_conf_data() {
|
||||
MSP.send_message(MSP_codes.MSP_SERVO_CONF, false, false, get_channel_forwarding_data);
|
||||
function get_servo_configurations() {
|
||||
MSP.send_message(MSP_codes.MSP_SERVO_CONFIGURATIONS, false, false, get_servo_mix_rules);
|
||||
}
|
||||
|
||||
function get_channel_forwarding_data() {
|
||||
MSP.send_message(MSP_codes.MSP_CHANNEL_FORWARDING, false, false, get_rc_data);
|
||||
function get_servo_mix_rules() {
|
||||
MSP.send_message(MSP_codes.MSP_SERVO_MIX_RULES, false, false, get_channel_forwarding);
|
||||
}
|
||||
|
||||
function get_rc_data() {
|
||||
function get_channel_forwarding() {
|
||||
var nextFunction = get_rc_data;
|
||||
|
||||
if (semver.lt(CONFIG.apiVersion, "1.12.0")) {
|
||||
MSP.send_message(MSP_codes.MSP_CHANNEL_FORWARDING, false, false, nextFunction);
|
||||
} else {
|
||||
nextFunction();
|
||||
}
|
||||
}
|
||||
|
||||
function get_rc_data() {
|
||||
MSP.send_message(MSP_codes.MSP_RC, false, false, get_boxnames_data);
|
||||
}
|
||||
|
||||
|
@ -35,10 +39,18 @@ TABS.servos.initialize = function (callback) {
|
|||
$('#content').load("./tabs/servos.html", process_html);
|
||||
}
|
||||
|
||||
MSP.send_message(MSP_codes.MSP_IDENT, false, false, get_servo_conf_data);
|
||||
|
||||
function process_html() {
|
||||
|
||||
MSP.send_message(MSP_codes.MSP_IDENT, false, false, get_servo_configurations);
|
||||
|
||||
function update_ui() {
|
||||
|
||||
if (semver.lt(CONFIG.apiVersion, "1.12.0")) {
|
||||
|
||||
$(".tab-servos").removeClass("supported");
|
||||
return;
|
||||
}
|
||||
|
||||
$(".tab-servos").addClass("supported");
|
||||
|
||||
var servoCheckbox = '';
|
||||
var servoHeader = '';
|
||||
for (var i = 0; i < RC.active_channels-4; i++) {
|
||||
|
@ -46,94 +58,52 @@ TABS.servos.initialize = function (callback) {
|
|||
<th >A' + (i+1) + '</th>\
|
||||
';
|
||||
}
|
||||
servoHeader = servoHeader + '<th style="width: 200px" i18n="servosDirection"></th>';
|
||||
servoHeader = servoHeader + '<th style="width: 200px" i18n="servosDirectionAndRate"></th>';
|
||||
|
||||
for (var i = 0; i < RC.active_channels; i++) {
|
||||
servoCheckbox = servoCheckbox + '\
|
||||
<td class="channel"><input type="checkbox"/></td>\
|
||||
';
|
||||
}
|
||||
|
||||
|
||||
|
||||
$('div.tab-servos table.fields tr.main').append(servoHeader);
|
||||
|
||||
function process_directions(name, obj, bitpos) {
|
||||
$('div.direction_wrapper').show();
|
||||
|
||||
var val;
|
||||
|
||||
$('div.tab-servos table.directions').append('\
|
||||
<tr>\
|
||||
<td class="name" style="text-align: center">' + name + '</td>\
|
||||
<td class="direction" style="text-align: right">\
|
||||
<select name="direction">\
|
||||
<option value="0">' + chrome.i18n.getMessage('servosNormal') + '</option>\
|
||||
<option value="1">' + chrome.i18n.getMessage('servosReverse') + '</option>\
|
||||
</select>\
|
||||
</td>\
|
||||
</tr>\
|
||||
');
|
||||
|
||||
if (bit_check(SERVO_CONFIG[obj].rate, bitpos)) val = 1;
|
||||
else val = 0;
|
||||
|
||||
$('div.tab-servos table.directions tr:last select').val(val);
|
||||
$('div.tab-servos table.directions tr:last select').data('info', {'obj': obj, 'bitpos': bitpos});
|
||||
}
|
||||
|
||||
function process_servos(name, alternate, obj, directions) {
|
||||
function process_servos(name, alternate, obj) {
|
||||
|
||||
$('div.supported_wrapper').show();
|
||||
|
||||
|
||||
|
||||
$('div.tab-servos table.fields').append('\
|
||||
<tr> \
|
||||
<td style="text-align: center">' + name + '</td>\
|
||||
<td class="middle"><input type="number" min="1000" max="2000" value="' + SERVO_CONFIG[obj].middle + '" /></td>\
|
||||
<td class="min"><input type="number" min="1000" max="2000" value="' + SERVO_CONFIG[obj].min +'" /></td>\
|
||||
<td class="max"><input type="number" min="1000" max="2000" value="' + SERVO_CONFIG[obj].max +'" /></td>\
|
||||
<td class="middle"><input type="number" min="500" max="2500" value="' + SERVO_CONFIG[obj].middle + '" /></td>\
|
||||
<td class="min"><input type="number" min="500" max="2500" value="' + SERVO_CONFIG[obj].min +'" /></td>\
|
||||
<td class="max"><input type="number" min="500" max="2500" value="' + SERVO_CONFIG[obj].max +'" /></td>\
|
||||
<td class="angleAtMin"><input type="number" min="-90" max="0" value="' + SERVO_CONFIG[obj].angleAtMin +'" /></td>\
|
||||
<td class="angleAtMax"><input type="number" min="0" max="90" value="' + SERVO_CONFIG[obj].angleAtMax +'" /></td>\
|
||||
' + servoCheckbox + '\
|
||||
<td class="direction">\
|
||||
<input class="first" type="checkbox"/><span class="name">' + name + '</span>\
|
||||
<input class="second" type="checkbox"/><span class="alternate">' + alternate + '</span>\
|
||||
</td>\
|
||||
</tr> \
|
||||
');
|
||||
|
||||
|
||||
|
||||
// translate to user-selected language
|
||||
localize();
|
||||
|
||||
$('div.tab-servos table.fields tr:last td.channel input').eq(SERVO_CONFIG[obj].indexOfChannelToForward).prop('checked', true);
|
||||
|
||||
if (directions == true) {
|
||||
$('div.tab-servos table.fields tr:last td.direction input:first').prop('checked', bit_check(SERVO_CONFIG[obj].rate, 0));
|
||||
$('div.tab-servos table.fields tr:last td.direction input:last').prop('checked', bit_check(SERVO_CONFIG[obj].rate, 1));
|
||||
} else if (directions == 2) {
|
||||
// removing checkboxes
|
||||
$('div.tab-servos table.fields tr:last td.direction').html('');
|
||||
|
||||
// adding select box and generating options
|
||||
$('div.tab-servos table.fields tr:last td.direction').append('\
|
||||
<select class="rate" name="rate"></select>\
|
||||
');
|
||||
|
||||
var select = $('div.tab-servos table.fields tr:last td.direction select');
|
||||
|
||||
for (var i = 100; i > -101; i--) {
|
||||
select.append('<option value="' + i + '">Rate: ' + i + '%</option>');
|
||||
}
|
||||
|
||||
// select current rate
|
||||
select.val(SERVO_CONFIG[obj].rate);
|
||||
} else {
|
||||
// removing checkboxes
|
||||
$('div.tab-servos table.fields tr:last td.direction').html('');
|
||||
if (SERVO_CONFIG[obj].indexOfChannelToForward >= 0) {
|
||||
$('div.tab-servos table.fields tr:last td.channel input').eq(SERVO_CONFIG[obj].indexOfChannelToForward).prop('checked', true);
|
||||
}
|
||||
|
||||
// adding select box and generating options
|
||||
$('div.tab-servos table.fields tr:last td.direction').append('\
|
||||
<select class="rate" name="rate"></select>\
|
||||
');
|
||||
|
||||
var select = $('div.tab-servos table.fields tr:last td.direction select');
|
||||
|
||||
for (var i = 100; i > -101; i--) {
|
||||
select.append('<option value="' + i + '">Rate: ' + i + '%</option>');
|
||||
}
|
||||
|
||||
// select current rate
|
||||
select.val(SERVO_CONFIG[obj].rate);
|
||||
|
||||
$('div.tab-servos table.fields tr:last').data('info', {'obj': obj});
|
||||
|
||||
// UI hooks
|
||||
|
@ -146,18 +116,7 @@ TABS.servos.initialize = function (callback) {
|
|||
});
|
||||
}
|
||||
|
||||
function servos_update(save_to_eeprom) {
|
||||
// update bitfields
|
||||
$('div.tab-servos table.directions tr:not(".main")').each(function () {
|
||||
var info = $('select', this).data('info');
|
||||
var val = parseInt($('select', this).val());
|
||||
|
||||
// in this stage we need to know which bitfield and which bitposition needs to be flipped
|
||||
if (val) SERVO_CONFIG[info.obj].rate = bit_set(SERVO_CONFIG[info.obj].rate, info.bitpos);
|
||||
else SERVO_CONFIG[info.obj].rate = bit_clear(SERVO_CONFIG[info.obj].rate, info.bitpos);
|
||||
});
|
||||
|
||||
// update the rest
|
||||
function servos_update(save_configuration_to_eeprom) {
|
||||
$('div.tab-servos table.fields tr:not(".main")').each(function () {
|
||||
var info = $(this).data('info');
|
||||
|
||||
|
@ -174,122 +133,37 @@ TABS.servos.initialize = function (callback) {
|
|||
SERVO_CONFIG[info.obj].middle = parseInt($('.middle input', this).val());
|
||||
SERVO_CONFIG[info.obj].min = parseInt($('.min input', this).val());
|
||||
SERVO_CONFIG[info.obj].max = parseInt($('.max input', this).val());
|
||||
SERVO_CONFIG[info.obj].angleAtMin = parseInt($('.angleAtMin input', this).val());
|
||||
SERVO_CONFIG[info.obj].angleAtMax = parseInt($('.angleAtMax input', this).val());
|
||||
|
||||
// update rate if direction fields exist
|
||||
if ($('.direction input', this).length) {
|
||||
if ($('.direction input:first', this).is(':checked')) SERVO_CONFIG[info.obj].rate = bit_set(SERVO_CONFIG[info.obj].rate, 0);
|
||||
else SERVO_CONFIG[info.obj].rate = bit_clear(SERVO_CONFIG[info.obj].rate, 0);
|
||||
|
||||
if ($('.direction input:last', this).is(':checked')) SERVO_CONFIG[info.obj].rate = bit_set(SERVO_CONFIG[info.obj].rate, 1);
|
||||
else SERVO_CONFIG[info.obj].rate = bit_clear(SERVO_CONFIG[info.obj].rate, 1);
|
||||
} else if ($('.direction select', this).length) {
|
||||
var val = parseInt($('.direction select', this).val());
|
||||
SERVO_CONFIG[info.obj].rate = val;
|
||||
}
|
||||
var val = parseInt($('.direction select', this).val());
|
||||
SERVO_CONFIG[info.obj].rate = val;
|
||||
});
|
||||
|
||||
MSP.send_message(MSP_codes.MSP_SET_CHANNEL_FORWARDING, MSP.crunch(MSP_codes.MSP_SET_CHANNEL_FORWARDING), false, function () {
|
||||
MSP.send_message(MSP_codes.MSP_SET_SERVO_CONF, MSP.crunch(MSP_codes.MSP_SET_SERVO_CONF), false, function () {
|
||||
if (save_to_eeprom) {
|
||||
// Save changes to EEPROM
|
||||
MSP.send_message(MSP_codes.MSP_EEPROM_WRITE, false, false, function () {
|
||||
GUI.log(chrome.i18n.getMessage('servosEepromSave'));
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
//
|
||||
// send data to FC
|
||||
//
|
||||
MSP.sendServoConfigurations(send_servo_mixer_rules);
|
||||
|
||||
function send_servo_mixer_rules() {
|
||||
MSP.sendServoConfigurations(save_to_eeprom);
|
||||
}
|
||||
|
||||
function save_to_eeprom() {
|
||||
if (save_configuration_to_eeprom) {
|
||||
MSP.send_message(MSP_codes.MSP_EEPROM_WRITE, false, false, function () {
|
||||
GUI.log(chrome.i18n.getMessage('servosEepromSave'));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// drop previous table
|
||||
$('div.tab-servos table.fields tr:not(:first)').remove();
|
||||
|
||||
var model = $('div.tab-servos strong.model');
|
||||
var supported_models = [1, 4, 5, 8, 14, 20, 21];
|
||||
|
||||
switch (CONFIG.multiType) {
|
||||
case 1: // TRI
|
||||
// looking ok so far
|
||||
model.text('TRI');
|
||||
|
||||
process_directions('YAW', 5, 0);
|
||||
|
||||
process_servos('Yaw Servo', '', 5, false);
|
||||
break;
|
||||
case 4: // BI
|
||||
// looking ok so far
|
||||
model.text('BI');
|
||||
|
||||
process_directions('L YAW', 4, 1);
|
||||
process_directions('R YAW', 5, 1);
|
||||
process_directions('L NICK', 4, 0);
|
||||
process_directions('R NICK', 5, 0);
|
||||
|
||||
process_servos('Left Servo', '', 4, false);
|
||||
process_servos('Right Servo', '', 5, false);
|
||||
break;
|
||||
case 5: // Gimbal
|
||||
// needs to be verified
|
||||
model.text('Gimbal');
|
||||
|
||||
// rate
|
||||
process_servos('Pitch Servo', '', 0, 2);
|
||||
process_servos('Roll Servo', '', 1, 2);
|
||||
break;
|
||||
case 8: // Flying Wing
|
||||
// looking ok so far
|
||||
model.text('Flying Wing');
|
||||
|
||||
process_directions('L ROLL', 3, 1);
|
||||
process_directions('R ROLL', 4, 1);
|
||||
process_directions('L NICK', 3, 0);
|
||||
process_directions('R NICK', 4, 0);
|
||||
|
||||
process_servos('Left Wing', '', 3, false);
|
||||
process_servos('Right Wing', '', 4, false);
|
||||
break;
|
||||
case 14: // Airplane
|
||||
model.text('Airplane');
|
||||
|
||||
// rate
|
||||
process_servos('Wing 1', '', 3, 2);
|
||||
process_servos('Wing 2', '', 4, 2);
|
||||
process_servos('Rudd', '', 5, 2);
|
||||
process_servos('Elev', '', 6, 2);
|
||||
break;
|
||||
case 20: // Dualcopter
|
||||
// looking ok so far
|
||||
model.text('Dualcopter');
|
||||
|
||||
process_directions('PITCH', 4, 0);
|
||||
process_directions('ROLL', 5, 0);
|
||||
|
||||
process_servos('Roll', '', 5, false);
|
||||
process_servos('Nick', '', 4, false);
|
||||
break;
|
||||
case 21: // Singlecopter
|
||||
// looking ok so far
|
||||
model.text('Singlecopter');
|
||||
|
||||
process_servos('Right', 'R YAW', 3, true);
|
||||
process_servos('Left', 'L YAW', 4, true);
|
||||
process_servos('Front', 'F YAW', 5, true);
|
||||
process_servos('Rear', 'YAW', 6, true);
|
||||
break;
|
||||
|
||||
default:
|
||||
model.text(chrome.i18n.getMessage('servosModelNoSupport'));
|
||||
|
||||
// implementation of feature servo_tilt
|
||||
if (AUX_CONFIG.indexOf('CAMSTAB') > -1 || AUX_CONFIG.indexOf('CAMTRIG') > -1) {
|
||||
// Gimbal on
|
||||
// needs to be verified
|
||||
model.text('Gimbal / Tilt Servos');
|
||||
|
||||
// rate
|
||||
process_servos('Pitch Servo', '', 0, 2);
|
||||
process_servos('Roll Servo', '', 1, 2);
|
||||
}
|
||||
for (var servoIndex = 0; servoIndex < 8; servoIndex++) {
|
||||
process_servos('Servo ' + servoIndex, '', servoIndex, false);
|
||||
}
|
||||
|
||||
// UI hooks for dynamically generated elements
|
||||
|
@ -299,14 +173,20 @@ TABS.servos.initialize = function (callback) {
|
|||
GUI.timeout_add('servos_update', servos_update, 10);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
$('a.update').click(function () {
|
||||
// standard check for supported_models + custom implementation for feature servo_tilt
|
||||
if (supported_models.indexOf(CONFIG.multiType) != -1 || AUX_CONFIG.indexOf('CAMSTAB') > -1 || AUX_CONFIG.indexOf('CAMTRIG') > -1) {
|
||||
servos_update(true);
|
||||
}
|
||||
servos_update(true);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
function process_html() {
|
||||
|
||||
update_ui();
|
||||
|
||||
// translate to user-selected language
|
||||
localize();
|
||||
|
||||
// status data pulled via separate timer with static speed
|
||||
GUI.interval_add('status_pull', function () {
|
||||
MSP.send_message(MSP_codes.MSP_STATUS);
|
||||
|
@ -318,4 +198,4 @@ TABS.servos.initialize = function (callback) {
|
|||
|
||||
TABS.servos.cleanup = function (callback) {
|
||||
if (callback) callback();
|
||||
};
|
||||
};
|
||||
|
|
|
@ -68,12 +68,23 @@
|
|||
border: 1px solid silver;
|
||||
background-color: white;
|
||||
}
|
||||
.tab-setup #interactive_block .heading {
|
||||
.tab-setup #interactive_block .attitude {
|
||||
float: right;
|
||||
height: 15px;
|
||||
margin: 10px 10px 0px 0px
|
||||
}
|
||||
|
||||
margin: 10px 10px 0 0;
|
||||
font-weight: bold;
|
||||
.tab-setup #interactive_block .attitude dt {
|
||||
float: left;
|
||||
width: 64px;
|
||||
font-weight: 700;
|
||||
text-align: right
|
||||
}
|
||||
|
||||
.tab-setup #interactive_block .attitude dd {
|
||||
display: block;
|
||||
margin-left: 64px;
|
||||
width: 64px;
|
||||
text-align: right
|
||||
}
|
||||
.tab-setup #interactive_block a.reset {
|
||||
position: absolute;
|
||||
|
|
|
@ -25,7 +25,13 @@
|
|||
<div id="canvas_wrapper">
|
||||
<canvas id="canvas"></canvas>
|
||||
</div>
|
||||
<span class="heading"></span>
|
||||
<div class="attitude">
|
||||
<dl>
|
||||
<dt>Heading:</dt><dd class="heading"> </dd>
|
||||
<dt>Pitch:</dt><dd class="pitch"> </dd>
|
||||
<dt>Roll:</dt><dd class="roll"> </dd>
|
||||
</dl>
|
||||
</div>
|
||||
<a class="reset" href="#" i18n="initialSetupButtonResetZaxis"></a>
|
||||
</div>
|
||||
<div class="block info">
|
||||
|
|
|
@ -47,8 +47,13 @@ TABS.setup.initialize = function (callback) {
|
|||
// initialize 3D
|
||||
self.initialize3D();
|
||||
|
||||
// set roll in interactive block
|
||||
$('span.roll').text(chrome.i18n.getMessage('initialSetupAttitude', [0]));
|
||||
// set pitch in interactive block
|
||||
$('span.pitch').text(chrome.i18n.getMessage('initialSetupAttitude', [0]));
|
||||
// set heading in interactive block
|
||||
$('span.heading').text(chrome.i18n.getMessage('initialSetupheading', [0]));
|
||||
$('span.heading').text(chrome.i18n.getMessage('initialSetupAttitude', [0]));
|
||||
|
||||
|
||||
// check if we have magnetometer
|
||||
if (!bit_check(CONFIG.activeSensors, 2)) {
|
||||
|
@ -151,7 +156,9 @@ TABS.setup.initialize = function (callback) {
|
|||
gpsSats_e = $('.gpsSats'),
|
||||
gpsLat_e = $('.gpsLat'),
|
||||
gpsLon_e = $('.gpsLon'),
|
||||
heading_e = $('span.heading');
|
||||
roll_e = $('dd.roll'),
|
||||
pitch_e = $('dd.pitch'),
|
||||
heading_e = $('dd.heading');
|
||||
|
||||
function get_slow_data() {
|
||||
MSP.send_message(MSP_codes.MSP_STATUS);
|
||||
|
@ -175,7 +182,9 @@ TABS.setup.initialize = function (callback) {
|
|||
|
||||
function get_fast_data() {
|
||||
MSP.send_message(MSP_codes.MSP_ATTITUDE, false, false, function () {
|
||||
heading_e.text(chrome.i18n.getMessage('initialSetupheading', [SENSOR_DATA.kinematics[2]]));
|
||||
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.updateInstruments();
|
||||
});
|
||||
|
@ -216,13 +225,15 @@ TABS.setup.initialize3D = function (compatibility) {
|
|||
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(), wrapper.height());
|
||||
|
||||
// modelWrapper just adds an extra axis of rotation to avoid gimbal lock withe euler angles
|
||||
|
||||
// // 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;
|
||||
|
@ -237,30 +248,28 @@ TABS.setup.initialize3D = function (compatibility) {
|
|||
useLegacyCustomModel = true;
|
||||
}
|
||||
|
||||
// setup scene
|
||||
scene = new THREE.Scene();
|
||||
|
||||
loader = new THREE.JSONLoader();
|
||||
loader.load('./resources/models/' + model_file + '.json', function (geometry, materials) {
|
||||
model = new THREE.Mesh(geometry, new THREE.MeshFaceMaterial(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);
|
||||
});
|
||||
|
||||
// stacionary camera
|
||||
|
||||
// stationary camera
|
||||
camera = new THREE.PerspectiveCamera(50, wrapper.width() / wrapper.height(), 1, 10000);
|
||||
|
||||
// setup scene
|
||||
scene = new THREE.Scene();
|
||||
|
||||
// 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);
|
||||
|
||||
// initialize render size for current canvas size
|
||||
renderer.setSize(wrapper.width(), wrapper.height());
|
||||
|
||||
// move camera away from the model
|
||||
camera.position.z = 125;
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue