1
0
Fork 0
mirror of https://github.com/iNavFlight/inav-configurator.git synced 2025-07-16 21:05:28 +03:00

Merge branch 'master' into capacity_settings_and_data

This commit is contained in:
Michel Pastor 2018-02-18 07:12:59 +01:00
commit 8d50387bf7
11 changed files with 203 additions and 28 deletions

View file

@ -886,6 +886,15 @@
"pidTuningYawRate": { "pidTuningYawRate": {
"message": "YAW rate" "message": "YAW rate"
}, },
"pidTuningManualRollRate": {
"message": "Manual ROLL rate"
},
"pidTuningManualPitchRate": {
"message": "Manual PITCH rate"
},
"pidTuningManualYawRate": {
"message": "Manual YAW rate"
},
"magHoldYawRate": { "magHoldYawRate": {
"message": "MagHold rate" "message": "MagHold rate"
}, },
@ -947,6 +956,12 @@
"receiverRcYawExpo": { "receiverRcYawExpo": {
"message": "RC Yaw Expo" "message": "RC Yaw Expo"
}, },
"receiverManualRcExpo": {
"message": "Manual RC Expo"
},
"receiverManualRcYawExpo": {
"message": "Manual RC Yaw Expo"
},
"receiverChannelMap": { "receiverChannelMap": {
"message": "Channel Map" "message": "Channel Map"
}, },

View file

@ -143,7 +143,12 @@ var FC = {
throttle_MID: 0, throttle_MID: 0,
throttle_EXPO: 0, throttle_EXPO: 0,
dynamic_THR_breakpoint: 0, dynamic_THR_breakpoint: 0,
RC_YAW_EXPO: 0 RC_YAW_EXPO: 0,
manual_RC_EXPO: 0,
manual_RC_YAW_EXPO: 0,
manual_roll_rate: 0,
manual_pitch_rate: 0,
manual_yaw_rate: 0,
}; };
AUX_CONFIG = []; AUX_CONFIG = [];

View file

@ -161,6 +161,7 @@ var MSPCodes = {
MSPV2_INAV_MISC: 0x2003, MSPV2_INAV_MISC: 0x2003,
MSPV2_INAV_SET_MISC: 0x2004, MSPV2_INAV_SET_MISC: 0x2004,
MSPV2_INAV_BATTERY_CONFIG: 0x2005, MSPV2_INAV_BATTERY_CONFIG: 0x2005,
MSPV2_INAV_SET_BATTERY_CONFIG: 0x2006 MSPV2_INAV_SET_BATTERY_CONFIG: 0x2006,
MSPV2_INAV_RATE_PROFILE: 0x2007,
MSPV2_INAV_SET_RATE_PROFILE: 0x2008,
}; };

View file

@ -282,6 +282,32 @@ var mspHelper = (function (gui) {
offset += 2; offset += 2;
RC_tuning.RC_YAW_EXPO = parseFloat((data.getUint8(offset++) / 100).toFixed(2)); RC_tuning.RC_YAW_EXPO = parseFloat((data.getUint8(offset++) / 100).toFixed(2));
break; break;
case MSPCodes.MSPV2_INAV_RATE_PROFILE:
// compat
RC_tuning.RC_RATE = 100;
RC_tuning.roll_pitch_rate = 0;
// throttle
RC_tuning.throttle_MID = parseFloat((data.getUint8(offset++) / 100).toFixed(2));
RC_tuning.throttle_EXPO = parseFloat((data.getUint8(offset++) / 100).toFixed(2));
RC_tuning.dynamic_THR_PID = parseInt(data.getUint8(offset++));
RC_tuning.dynamic_THR_breakpoint = data.getUint16(offset, true);
offset += 2;
// stabilized
RC_tuning.RC_EXPO = parseFloat((data.getUint8(offset++) / 100).toFixed(2));
RC_tuning.RC_YAW_EXPO = parseFloat((data.getUint8(offset++) / 100).toFixed(2));
RC_tuning.roll_rate = data.getUint8(offset++) * 10;
RC_tuning.pitch_rate = data.getUint8(offset++) * 10;
RC_tuning.yaw_rate = data.getUint8(offset++) * 10;
// manual
RC_tuning.manual_RC_EXPO = parseFloat((data.getUint8(offset++) / 100).toFixed(2));
RC_tuning.manual_RC_YAW_EXPO = parseFloat((data.getUint8(offset++) / 100).toFixed(2));
RC_tuning.manual_roll_rate = data.getUint8(offset++);
RC_tuning.manual_pitch_rate = data.getUint8(offset++);
RC_tuning.manual_yaw_rate = data.getUint8(offset++);
break;
case MSPCodes.MSP_PID: case MSPCodes.MSP_PID:
// PID data arrived, we need to scale it and save to appropriate bank / array // PID data arrived, we need to scale it and save to appropriate bank / array
for (i = 0, needle = 0; i < (dataHandler.message_length_expected / 3); i++, needle += 3) { for (i = 0, needle = 0; i < (dataHandler.message_length_expected / 3); i++, needle += 3) {
@ -352,7 +378,7 @@ var mspHelper = (function (gui) {
offset += 4; offset += 4;
MISC.battery_capacity_critical = data.getUint32(offset, true); MISC.battery_capacity_critical = data.getUint32(offset, true);
offset += 4; offset += 4;
MISC.battery_capacity_unit = (data.getUint8(offset++) ? 'mWh' : 'mAh'); MISC.battery_capacity_unit = (data.getUint8(offset++) ? 'Wh' : 'mAh');
break; break;
case MSPCodes.MSPV2_INAV_BATTERY_CONFIG: case MSPCodes.MSPV2_INAV_BATTERY_CONFIG:
BATTERY_CONFIG.vbatscale = data.getUint16(offset, true); BATTERY_CONFIG.vbatscale = data.getUint16(offset, true);
@ -1326,6 +1352,28 @@ var mspHelper = (function (gui) {
buffer.push(highByte(RC_tuning.dynamic_THR_breakpoint)); buffer.push(highByte(RC_tuning.dynamic_THR_breakpoint));
buffer.push(Math.round(RC_tuning.RC_YAW_EXPO * 100)); buffer.push(Math.round(RC_tuning.RC_YAW_EXPO * 100));
break; break;
case MSPCodes.MSPV2_INAV_SET_RATE_PROFILE:
// throttle
buffer.push(Math.round(RC_tuning.throttle_MID * 100));
buffer.push(Math.round(RC_tuning.throttle_EXPO * 100));
buffer.push(RC_tuning.dynamic_THR_PID);
buffer.push(lowByte(RC_tuning.dynamic_THR_breakpoint));
buffer.push(highByte(RC_tuning.dynamic_THR_breakpoint));
// stabilized
buffer.push(Math.round(RC_tuning.RC_EXPO * 100));
buffer.push(Math.round(RC_tuning.RC_YAW_EXPO * 100));
buffer.push(Math.round(RC_tuning.roll_rate / 10));
buffer.push(Math.round(RC_tuning.pitch_rate / 10));
buffer.push(Math.round(RC_tuning.yaw_rate / 10));
// manual
buffer.push(Math.round(RC_tuning.manual_RC_EXPO * 100));
buffer.push(Math.round(RC_tuning.manual_RC_YAW_EXPO * 100));
buffer.push(RC_tuning.manual_roll_rate);
buffer.push(RC_tuning.manual_pitch_rate);
buffer.push(RC_tuning.manual_yaw_rate);
break;
case MSPCodes.MSP_SET_RX_MAP: case MSPCodes.MSP_SET_RX_MAP:
for (i = 0; i < RC_MAP.length; i++) { for (i = 0; i < RC_MAP.length; i++) {
@ -2325,6 +2373,10 @@ var mspHelper = (function (gui) {
MSP.send_message(MSPCodes.MSP_RC_TUNING, false, false, callback); MSP.send_message(MSPCodes.MSP_RC_TUNING, false, false, callback);
}; };
self.loadRateProfileData = function (callback) {
MSP.send_message(MSPCodes.MSPV2_INAV_RATE_PROFILE, false, false, callback);
};
self.loadPidData = function (callback) { self.loadPidData = function (callback) {
MSP.send_message(MSPCodes.MSP_PID, false, false, callback); MSP.send_message(MSPCodes.MSP_PID, false, false, callback);
}; };
@ -2453,6 +2505,10 @@ var mspHelper = (function (gui) {
MSP.send_message(MSPCodes.MSP_SET_RC_TUNING, mspHelper.crunch(MSPCodes.MSP_SET_RC_TUNING), false, callback); MSP.send_message(MSPCodes.MSP_SET_RC_TUNING, mspHelper.crunch(MSPCodes.MSP_SET_RC_TUNING), false, callback);
}; };
self.saveRateProfileData = function (callback) {
MSP.send_message(MSPCodes.MSPV2_INAV_SET_RATE_PROFILE, mspHelper.crunch(MSPCodes.MSPV2_INAV_SET_RATE_PROFILE), false, callback);
};
self.savePidAdvanced = function (callback) { self.savePidAdvanced = function (callback) {
if (semver.gte(CONFIG.flightControllerVersion, "1.4.0")) { if (semver.gte(CONFIG.flightControllerVersion, "1.4.0")) {
MSP.send_message(MSPCodes.MSP_SET_PID_ADVANCED, mspHelper.crunch(MSPCodes.MSP_SET_PID_ADVANCED), false, callback); MSP.send_message(MSPCodes.MSP_SET_PID_ADVANCED, mspHelper.crunch(MSPCodes.MSP_SET_PID_ADVANCED), false, callback);

View file

@ -330,6 +330,17 @@
background-position: center; background-position: center;
} }
.tab-receiver .manual_pitch_roll_curve {
margin: 0 0px 0px 0;
width: 200px;
height: 117px;
border: 1px solid silver;
border-radius: 3px;
background-image: url(../../../images/paper.jpg);
background-size: 200%;
background-position: center;
}
.tab-receiver #RX_plot { .tab-receiver #RX_plot {
width: 100%; width: 100%;
height: 200px; height: 200px;

View file

@ -437,12 +437,6 @@
<span data-i18n="configurationBatteryCurrent"></span> <span data-i18n="configurationBatteryCurrent"></span>
</label> </label>
</div> </div>
<div class="checkbox">
<input type="checkbox" id="multiwiicurrentoutput" name="multiwiicurrentoutput" class="toggle" />
<label for="multiwiicurrentoutput">
<span data-i18n="configurationBatteryMultiwiiCurrent"></span>
</label>
</div>
</div> </div>
</div> </div>
<div class="config-section gui_box grey requires-v1_8_1"> <div class="config-section gui_box grey requires-v1_8_1">

View file

@ -341,7 +341,6 @@ TABS.configuration.initialize = function (callback, scrollPosition) {
// fill current // fill current
$('#currentscale').val(BF_CONFIG.currentscale); $('#currentscale').val(BF_CONFIG.currentscale);
$('#currentoffset').val(BF_CONFIG.currentoffset); $('#currentoffset').val(BF_CONFIG.currentoffset);
$('#multiwiicurrentoutput').prop('checked', MISC.multiwiicurrentoutput);
// fill battery capacity // fill battery capacity
$('#battery_capacity').val(MISC.battery_capacity); $('#battery_capacity').val(MISC.battery_capacity);
@ -683,7 +682,6 @@ TABS.configuration.initialize = function (callback, scrollPosition) {
BF_CONFIG.currentscale = parseInt($('#currentscale').val()); BF_CONFIG.currentscale = parseInt($('#currentscale').val());
BF_CONFIG.currentoffset = parseInt($('#currentoffset').val()); BF_CONFIG.currentoffset = parseInt($('#currentoffset').val());
MISC.multiwiicurrentoutput = ~~$('#multiwiicurrentoutput').is(':checked'); // ~~ boolean to decimal conversion
_3D.deadband3d_low = parseInt($('#3ddeadbandlow').val()); _3D.deadband3d_low = parseInt($('#3ddeadbandlow').val());
_3D.deadband3d_high = parseInt($('#3ddeadbandhigh').val()); _3D.deadband3d_high = parseInt($('#3ddeadbandhigh').val());

View file

@ -167,6 +167,24 @@
<input type="number" name="yaw" class="rate-tpa_input" step="10" min="20" max="1800" /> degrees per second <input type="number" name="yaw" class="rate-tpa_input" step="10" min="20" max="1800" /> degrees per second
</td> </td>
</tr> </tr>
<tr>
<th class="roll" data-i18n="pidTuningManualRollRate"></th>
<td class="roll">
<input type="number" name="manual_roll" class="rate-tpa_input" step="1" min="0" max="100" /> %
</td>
</tr>
<tr>
<th class="pitch" data-i18n="pidTuningManualPitchRate"></th>
<td class="pitch">
<input type="number" name="manual_pitch" class="rate-tpa_input" step="1" min="0" max="100" /> %
</td>
</tr>
<tr>
<th class="yaw" data-i18n="pidTuningManualYawRate"></th>
<td class="yaw">
<input type="number" name="manual_yaw" class="rate-tpa_input" step="1" min="0" max="100" /> %
</td>
</tr>
<tr class="requires-v1_4"> <tr class="requires-v1_4">
<th data-i18n="magHoldYawRate"></th> <th data-i18n="magHoldYawRate"></th>
<td > <td >

View file

@ -9,14 +9,21 @@ TABS.pid_tuning.initialize = function (callback) {
var loadChainer = new MSPChainerClass(); var loadChainer = new MSPChainerClass();
loadChainer.setChain([ var loadChain = [
mspHelper.loadPidNames, mspHelper.loadPidNames,
mspHelper.loadPidData, mspHelper.loadPidData,
mspHelper.loadRcTuningData,
mspHelper.loadINAVPidConfig, mspHelper.loadINAVPidConfig,
mspHelper.loadPidAdvanced, mspHelper.loadPidAdvanced,
mspHelper.loadFilterConfig mspHelper.loadFilterConfig
]); ];
if (semver.gte(CONFIG.flightControllerVersion, '1.8.1')) {
loadChain.push(mspHelper.loadRateProfileData);
} else {
loadChain.push(mspHelper.loadRcTuningData);
}
loadChainer.setChain(loadChain);
loadChainer.setExitPoint(load_html); loadChainer.setExitPoint(load_html);
loadChainer.execute(); loadChainer.execute();
@ -58,6 +65,10 @@ TABS.pid_tuning.initialize = function (callback) {
$('.rate-tpa input[name="yaw"]').val(RC_tuning.yaw_rate.toFixed(2)); $('.rate-tpa input[name="yaw"]').val(RC_tuning.yaw_rate.toFixed(2));
} }
$('.rate-tpa input[name="manual_roll"]').val(RC_tuning.manual_roll_rate);
$('.rate-tpa input[name="manual_pitch"]').val(RC_tuning.manual_pitch_rate);
$('.rate-tpa input[name="manual_yaw"]').val(RC_tuning.manual_yaw_rate);
$('#tpa').val(RC_tuning.dynamic_THR_PID); $('#tpa').val(RC_tuning.dynamic_THR_PID);
$('#tpa-breakpoint').val(RC_tuning.dynamic_THR_breakpoint); $('#tpa-breakpoint').val(RC_tuning.dynamic_THR_breakpoint);
} }
@ -80,6 +91,10 @@ TABS.pid_tuning.initialize = function (callback) {
RC_tuning.yaw_rate = parseFloat($('.rate-tpa input[name="yaw"]:visible').val()); RC_tuning.yaw_rate = parseFloat($('.rate-tpa input[name="yaw"]:visible').val());
RC_tuning.dynamic_THR_PID = parseInt($('#tpa').val()); RC_tuning.dynamic_THR_PID = parseInt($('#tpa').val());
RC_tuning.dynamic_THR_breakpoint = parseInt($('#tpa-breakpoint').val()); RC_tuning.dynamic_THR_breakpoint = parseInt($('#tpa-breakpoint').val());
RC_tuning.manual_roll_rate = $('.rate-tpa input[name="manual_roll"]:visible').val();
RC_tuning.manual_pitch_rate = $('.rate-tpa input[name="manual_pitch"]:visible').val();
RC_tuning.manual_yaw_rate = $('.rate-tpa input[name="manual_yaw"]:visible').val();
} }
function hideUnusedPids(sensors_detected) { function hideUnusedPids(sensors_detected) {
$('.tab-pid_tuning table.pid_tuning').hide(); $('.tab-pid_tuning table.pid_tuning').hide();
@ -231,8 +246,12 @@ TABS.pid_tuning.initialize = function (callback) {
} }
function send_rc_tuning_changes() { function send_rc_tuning_changes() {
if (semver.gte(CONFIG.flightControllerVersion, '1.8.1')) {
MSP.send_message(MSPCodes.MSPV2_INAV_SET_RATE_PROFILE, mspHelper.crunch(MSPCodes.MSPV2_INAV_SET_RATE_PROFILE), false, saveINAVPidConfig);
} else {
MSP.send_message(MSPCodes.MSP_SET_RC_TUNING, mspHelper.crunch(MSPCodes.MSP_SET_RC_TUNING), false, saveINAVPidConfig); MSP.send_message(MSPCodes.MSP_SET_RC_TUNING, mspHelper.crunch(MSPCodes.MSP_SET_RC_TUNING), false, saveINAVPidConfig);
} }
}
function saveINAVPidConfig() { function saveINAVPidConfig() {
var next_callback = savePidAdvanced; var next_callback = savePidAdvanced;

View file

@ -74,26 +74,41 @@
</div> </div>
<div class="gui_box grey" style="float: right;"> <div class="gui_box grey" style="float: right;">
<div class="spacer" style="margin-top: 10px; margin-bottom: 10px;"> <div class="spacer" style="margin-top: 10px; margin-bottom: 10px;">
<div class="cf_column curves" style="width: calc(50% - 10px);"> <div class="fc_column curves" style="width: calc(50% - 10px);">
<table>
<tr>
<td>
<div class="pitch_roll_curve"> <div class="pitch_roll_curve">
<canvas width="200" height="117"></canvas> <canvas width="200" height="117"></canvas>
</div> </div>
</td>
<td>
<div class="manual_pitch_roll_curve">
<canvas width="200" height="117"></canvas>
</div> </div>
<div class="fc_column half tunings"> </td>
</tr>
</table>
</div>
<div class="fc_column half tunings" style="width: calc(50% - 10px);">
<table class="rate"> <table class="rate">
<tr> <tr>
<th data-i18n="receiverRcExpo"></th> <th data-i18n="receiverRcExpo"></th>
<th data-i18n="receiverManualRcExpo"></th>
</tr> </tr>
<tr> <tr>
<td><input type="number" name="expo" step="0.01" min="0" max="1" /></td> <td><input type="number" name="expo" step="0.01" min="0" max="1" /></td>
<td><input type="number" name="manual_expo" step="0.01" min="0" max="1" /></td>
</tr> </tr>
</table> </table>
<table class="yaw_rate" style="margin-bottom: 0;"> <table class="yaw_rate" style="margin-bottom: 0;">
<tr> <tr>
<th data-i18n="receiverRcYawExpo"></th> <th data-i18n="receiverRcYawExpo"></th>
<th data-i18n="receiverManualRcYawExpo"></th>
</tr> </tr>
<tr> <tr>
<td><input type="number" name="yaw_expo" step="0.01" min="0" max="1" /></td> <td><input type="number" name="yaw_expo" step="0.01" min="0" max="1" /></td>
<td><input type="number" name="manual_yaw_expo" step="0.01" min="0" max="1" /></td>
</tr> </tr>
</table> </table>
</div> </div>

View file

@ -16,14 +16,21 @@ TABS.receiver.initialize = function (callback) {
var loadChainer = new MSPChainerClass(); var loadChainer = new MSPChainerClass();
loadChainer.setChain([ var loadChain = [
mspHelper.loadRcTuningData,
mspHelper.loadMisc, mspHelper.loadMisc,
mspHelper.loadRcData, mspHelper.loadRcData,
mspHelper.loadRcMap, mspHelper.loadRcMap,
mspHelper.loadBfConfig, mspHelper.loadBfConfig,
mspHelper.loadRcDeadband mspHelper.loadRcDeadband
]); ];
if (semver.gte(CONFIG.flightControllerVersion, '1.8.1')) {
loadChain.push(mspHelper.loadRateProfileData);
} else {
loadChain.push(mspHelper.loadRcTuningData);
}
loadChainer.setChain(loadChain);
loadChainer.setExitPoint(load_html); loadChainer.setExitPoint(load_html);
loadChainer.execute(); loadChainer.execute();
@ -42,6 +49,9 @@ TABS.receiver.initialize = function (callback) {
$('.tunings .rate input[name="expo"]').val(RC_tuning.RC_EXPO.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)); $('.tunings .yaw_rate input[name="yaw_expo"]').val(RC_tuning.RC_YAW_EXPO.toFixed(2));
$('.tunings .rate input[name="manual_expo"]').val(RC_tuning.manual_RC_EXPO.toFixed(2));
$('.tunings .yaw_rate input[name="manual_yaw_expo"]').val(RC_tuning.manual_RC_YAW_EXPO.toFixed(2));
$('.deadband input[name="yaw_deadband"]').val(RC_deadband.yaw_deadband); $('.deadband input[name="yaw_deadband"]').val(RC_deadband.yaw_deadband);
$('.deadband input[name="deadband"]').val(RC_deadband.deadband); $('.deadband input[name="deadband"]').val(RC_deadband.deadband);
@ -248,6 +258,32 @@ TABS.receiver.initialize = function (callback) {
}, 0); }, 0);
}).trigger('input'); }).trigger('input');
$('.tunings .rate input').on('input change', function () {
setTimeout(function () { // let global validation trigger and adjust the values first
var expoE = $('.tunings .rate input[name="manual_expo"]'),
expo = parseFloat(expoE.val()),
pitch_roll_curve = $('.manual_pitch_roll_curve canvas').get(0),
context = pitch_roll_curve.getContext("2d");
// local validation to deal with input event
if (expo >= parseFloat(expoE.prop('min')) &&
expo <= parseFloat(expoE.prop('max'))) {
// continue
} else {
return;
}
// draw
context.clearRect(0, 0, 200, rateHeight);
context.beginPath();
context.moveTo(0, rateHeight);
context.quadraticCurveTo(110, rateHeight - ((rateHeight / 2) * (1 - expo)), 200, 0);
context.lineWidth = 2;
context.strokeStyle = '#37a8db';
context.stroke();
}, 0);
}).trigger('input');
$('a.refresh').click(function () { $('a.refresh').click(function () {
MSP.send_message(MSPCodes.MSP_RC_TUNING, false, false, function () { MSP.send_message(MSPCodes.MSP_RC_TUNING, false, false, function () {
GUI.log(chrome.i18n.getMessage('receiverDataRefreshed')); GUI.log(chrome.i18n.getMessage('receiverDataRefreshed'));
@ -272,6 +308,9 @@ TABS.receiver.initialize = function (callback) {
RC_tuning.RC_EXPO = parseFloat($('.tunings .rate input[name="expo"]').val()); RC_tuning.RC_EXPO = parseFloat($('.tunings .rate input[name="expo"]').val());
RC_tuning.RC_YAW_EXPO = parseFloat($('.tunings .yaw_rate input[name="yaw_expo"]').val()); RC_tuning.RC_YAW_EXPO = parseFloat($('.tunings .yaw_rate input[name="yaw_expo"]').val());
RC_tuning.manual_RC_EXPO = parseFloat($('.tunings .rate input[name="manual_expo"]').val());
RC_tuning.manual_RC_YAW_EXPO = parseFloat($('.tunings .yaw_rate input[name="manual_yaw_expo"]').val());
RC_deadband.yaw_deadband = parseInt($('.deadband input[name="yaw_deadband"]').val()); RC_deadband.yaw_deadband = parseInt($('.deadband input[name="yaw_deadband"]').val());
RC_deadband.deadband = parseInt($('.deadband input[name="deadband"]').val()); RC_deadband.deadband = parseInt($('.deadband input[name="deadband"]').val());
@ -309,7 +348,11 @@ TABS.receiver.initialize = function (callback) {
}); });
} }
if (semver.gte(CONFIG.flightControllerVersion, '1.8.1')) {
MSP.send_message(MSPCodes.MSPV2_INAV_SET_RATE_PROFILE, mspHelper.crunch(MSPCodes.MSPV2_INAV_SET_RATE_PROFILE), false, save_rc_map);
} else {
MSP.send_message(MSPCodes.MSP_SET_RC_TUNING, mspHelper.crunch(MSPCodes.MSP_SET_RC_TUNING), false, save_rc_map); MSP.send_message(MSPCodes.MSP_SET_RC_TUNING, mspHelper.crunch(MSPCodes.MSP_SET_RC_TUNING), false, save_rc_map);
}
}); });
$("a.sticks").click(function () { $("a.sticks").click(function () {