mirror of
https://bitbucket.org/librepilot/librepilot.git
synced 2024-11-29 07:24:13 +01:00
Merge remote-tracking branch 'origin/rel-15.02.02' into next
Conflicts: flight/modules/Actuator/actuator.c
This commit is contained in:
commit
143f09d216
24
WHATSNEW.txt
24
WHATSNEW.txt
@ -1,3 +1,27 @@
|
||||
--- RELEASE-15.02.02-RC3 ---
|
||||
This release fixes a bug that prevents revo onboard mag to work correctly.
|
||||
|
||||
Release Notes - OpenPilot - Version RELEASE-15.02.02
|
||||
|
||||
The full list of bugfixes in this release is accessible here:
|
||||
https://progress.openpilot.org/issues/?filter=12262
|
||||
|
||||
** Bug
|
||||
* [OP-1820] - fix onboard mag orientation
|
||||
* [OP-1821] - Tricopter tail servo wrong speed on wizard
|
||||
* [OP-1827] - Version ID wrong in Windows uninstaller
|
||||
* [OP-1857] - PPM on Flexi does not work on CC/CC3D
|
||||
* [OP-1872] - Vehicle Wiz Tricopter tail servo settings don't save
|
||||
|
||||
** Improvement
|
||||
* [OP-1835] - Add motor constraints in place of overhead throttle buffer for enhanced stability and power. Add swash constraints for helis.
|
||||
|
||||
|
||||
** Task
|
||||
* [OP-1831] - due to oneshot higher pid values ki now shows "red" warning in stabilization page
|
||||
|
||||
|
||||
|
||||
--- RELEASE-15.02.01 ---
|
||||
This release fixes an in important bug that may prevent failsafe to work correctly using CC3D/CC with a PWM receiver.
|
||||
|
||||
|
@ -40,6 +40,7 @@
|
||||
#include "actuatordesired.h"
|
||||
#include "actuatorcommand.h"
|
||||
#include "flightstatus.h"
|
||||
#include <flightmodesettings.h>
|
||||
#include "mixersettings.h"
|
||||
#include "mixerstatus.h"
|
||||
#include "cameradesired.h"
|
||||
@ -98,9 +99,10 @@ static int mixer_settings_count = 2;
|
||||
// Private functions
|
||||
static void actuatorTask(void *parameters);
|
||||
static int16_t scaleChannel(float value, int16_t max, int16_t min, int16_t neutral);
|
||||
static int16_t scaleMotor(float value, int16_t max, int16_t min, int16_t neutral, float maxMotor, float minMotor, bool armed, bool AlwaysStabilizeWhenArmed, float throttleDesired);
|
||||
static void setFailsafe();
|
||||
static float MixerCurveFullRangeProportional(const float input, const float *curve, uint8_t elements);
|
||||
static float MixerCurveFullRangeAbsolute(const float input, const float *curve, uint8_t elements);
|
||||
static float MixerCurveFullRangeProportional(const float input, const float *curve, uint8_t elements, bool multirotor);
|
||||
static float MixerCurveFullRangeAbsolute(const float input, const float *curve, uint8_t elements, bool multirotor);
|
||||
static bool set_channel(uint8_t mixer_channel, uint16_t value);
|
||||
static void actuator_update_rate_if_changed(bool force_update);
|
||||
static void MixerSettingsUpdatedCb(UAVObjEvent *ev);
|
||||
@ -108,7 +110,7 @@ static void ActuatorSettingsUpdatedCb(UAVObjEvent *ev);
|
||||
static void SettingsUpdatedCb(UAVObjEvent *ev);
|
||||
float ProcessMixer(const int index, const float curve1, const float curve2,
|
||||
ActuatorDesiredData *desired,
|
||||
const float period);
|
||||
const float period, bool multirotor);
|
||||
|
||||
// this structure is equivalent to the UAVObjects for one mixer.
|
||||
typedef struct {
|
||||
@ -199,6 +201,7 @@ static void actuatorTask(__attribute__((unused)) void *parameters)
|
||||
ActuatorCommandData command;
|
||||
ActuatorDesiredData desired;
|
||||
MixerStatusData mixerStatus;
|
||||
FlightModeSettingsData settings;
|
||||
FlightStatusData flightStatus;
|
||||
float throttleDesired;
|
||||
float collectiveDesired;
|
||||
@ -245,6 +248,7 @@ static void actuatorTask(__attribute__((unused)) void *parameters)
|
||||
dTSeconds = dTMilliseconds * 0.001f;
|
||||
|
||||
FlightStatusGet(&flightStatus);
|
||||
FlightModeSettingsGet(&settings);
|
||||
ActuatorDesiredGet(&desired);
|
||||
ActuatorCommandGet(&command);
|
||||
|
||||
@ -266,22 +270,32 @@ static void actuatorTask(__attribute__((unused)) void *parameters)
|
||||
bool armed = flightStatus.Armed == FLIGHTSTATUS_ARMED_ARMED;
|
||||
bool activeThrottle = (throttleDesired < -0.001f || throttleDesired > 0.001f); // for ground and reversible motors
|
||||
bool positiveThrottle = (throttleDesired > 0.00f);
|
||||
bool multirotor = (GetCurrentFrameType() == FRAME_TYPE_MULTIROTOR); // check if frame is a multirotor.
|
||||
bool alwaysArmed = settings.Arming == FLIGHTMODESETTINGS_ARMING_ALWAYSARMED;
|
||||
bool AlwaysStabilizeWhenArmed = settings.AlwaysStabilizeWhenArmed == FLIGHTMODESETTINGS_ALWAYSSTABILIZEWHENARMED_TRUE;
|
||||
|
||||
if (alwaysArmed) {
|
||||
AlwaysStabilizeWhenArmed = false; // Do not allow always stabilize when alwaysArmed is active. This is dangerous.
|
||||
}
|
||||
// safety settings
|
||||
if (!armed) {
|
||||
throttleDesired = 0;
|
||||
throttleDesired = 0.00f; // this also happens in scaleMotors as a per axis check
|
||||
}
|
||||
|
||||
if ((frameType == FRAME_TYPE_GROUND && !activeThrottle) || (frameType != FRAME_TYPE_GROUND && throttleDesired <= 0.00f) || !armed) {
|
||||
// throttleDesired should never be 0 or go below 0.
|
||||
// force set all other controls to zero if throttle is cut (previously set in Stabilization)
|
||||
if (actuatorSettings.LowThrottleZeroAxis.Roll == ACTUATORSETTINGS_LOWTHROTTLEZEROAXIS_TRUE) {
|
||||
desired.Roll = 0;
|
||||
}
|
||||
if (actuatorSettings.LowThrottleZeroAxis.Pitch == ACTUATORSETTINGS_LOWTHROTTLEZEROAXIS_TRUE) {
|
||||
desired.Pitch = 0;
|
||||
}
|
||||
if (actuatorSettings.LowThrottleZeroAxis.Yaw == ACTUATORSETTINGS_LOWTHROTTLEZEROAXIS_TRUE) {
|
||||
desired.Yaw = 0;
|
||||
// todo: can probably remove this
|
||||
if (!(multirotor && AlwaysStabilizeWhenArmed && armed)) { // we don't do this if this is a multirotor AND AlwaysStabilizeWhenArmed is true and the model is armed
|
||||
if (actuatorSettings.LowThrottleZeroAxis.Roll == ACTUATORSETTINGS_LOWTHROTTLEZEROAXIS_TRUE) {
|
||||
desired.Roll = 0.00f;
|
||||
}
|
||||
if (actuatorSettings.LowThrottleZeroAxis.Pitch == ACTUATORSETTINGS_LOWTHROTTLEZEROAXIS_TRUE) {
|
||||
desired.Pitch = 0.00f;
|
||||
}
|
||||
if (actuatorSettings.LowThrottleZeroAxis.Yaw == ACTUATORSETTINGS_LOWTHROTTLEZEROAXIS_TRUE) {
|
||||
desired.Yaw = 0.00f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -296,13 +310,13 @@ static void actuatorTask(__attribute__((unused)) void *parameters)
|
||||
|
||||
AlarmsClear(SYSTEMALARMS_ALARM_ACTUATOR);
|
||||
|
||||
float curve1 = 0.0f;
|
||||
float curve1 = 0.0f; // curve 1 is the throttle curve applied to all motors.
|
||||
float curve2 = 0.0f;
|
||||
|
||||
// Interpolate curve 1 from throttleDesired as input.
|
||||
// assume reversible motor/mixer initially. We can later reverse this. The difference is simply that -ve throttleDesired values
|
||||
// map differently
|
||||
curve1 = MixerCurveFullRangeProportional(throttleDesired, mixerSettings.ThrottleCurve1, MIXERSETTINGS_THROTTLECURVE1_NUMELEM);
|
||||
curve1 = MixerCurveFullRangeProportional(throttleDesired, mixerSettings.ThrottleCurve1, MIXERSETTINGS_THROTTLECURVE1_NUMELEM, multirotor);
|
||||
|
||||
// The source for the secondary curve is selectable
|
||||
AccessoryDesiredData accessory;
|
||||
@ -310,25 +324,38 @@ static void actuatorTask(__attribute__((unused)) void *parameters)
|
||||
switch (curve2Source) {
|
||||
case MIXERSETTINGS_CURVE2SOURCE_THROTTLE:
|
||||
// assume reversible motor/mixer initially
|
||||
curve2 = MixerCurveFullRangeProportional(throttleDesired, mixerSettings.ThrottleCurve2, MIXERSETTINGS_THROTTLECURVE2_NUMELEM);
|
||||
curve2 = MixerCurveFullRangeProportional(throttleDesired, mixerSettings.ThrottleCurve2, MIXERSETTINGS_THROTTLECURVE2_NUMELEM, multirotor);
|
||||
break;
|
||||
case MIXERSETTINGS_CURVE2SOURCE_ROLL:
|
||||
// Throttle curve contribution the same for +ve vs -ve roll
|
||||
curve2 = MixerCurveFullRangeAbsolute(desired.Roll, mixerSettings.ThrottleCurve2, MIXERSETTINGS_THROTTLECURVE2_NUMELEM);
|
||||
if (multirotor) {
|
||||
curve2 = MixerCurveFullRangeProportional(desired.Roll, mixerSettings.ThrottleCurve2, MIXERSETTINGS_THROTTLECURVE2_NUMELEM, multirotor);
|
||||
} else {
|
||||
curve2 = MixerCurveFullRangeAbsolute(desired.Roll, mixerSettings.ThrottleCurve2, MIXERSETTINGS_THROTTLECURVE2_NUMELEM, multirotor);
|
||||
}
|
||||
break;
|
||||
case MIXERSETTINGS_CURVE2SOURCE_PITCH:
|
||||
// Throttle curve contribution the same for +ve vs -ve pitch
|
||||
curve2 = MixerCurveFullRangeAbsolute(desired.Pitch, mixerSettings.ThrottleCurve2,
|
||||
MIXERSETTINGS_THROTTLECURVE2_NUMELEM);
|
||||
if (multirotor) {
|
||||
curve2 = MixerCurveFullRangeProportional(desired.Pitch, mixerSettings.ThrottleCurve2,
|
||||
MIXERSETTINGS_THROTTLECURVE2_NUMELEM, multirotor);
|
||||
} else {
|
||||
curve2 = MixerCurveFullRangeAbsolute(desired.Pitch, mixerSettings.ThrottleCurve2,
|
||||
MIXERSETTINGS_THROTTLECURVE2_NUMELEM, multirotor);
|
||||
}
|
||||
break;
|
||||
case MIXERSETTINGS_CURVE2SOURCE_YAW:
|
||||
// Throttle curve contribution the same for +ve vs -ve yaw
|
||||
curve2 = MixerCurveFullRangeAbsolute(desired.Yaw, mixerSettings.ThrottleCurve2, MIXERSETTINGS_THROTTLECURVE2_NUMELEM);
|
||||
if (multirotor) {
|
||||
curve2 = MixerCurveFullRangeProportional(desired.Yaw, mixerSettings.ThrottleCurve2, MIXERSETTINGS_THROTTLECURVE2_NUMELEM, multirotor);
|
||||
} else {
|
||||
curve2 = MixerCurveFullRangeAbsolute(desired.Yaw, mixerSettings.ThrottleCurve2, MIXERSETTINGS_THROTTLECURVE2_NUMELEM, multirotor);
|
||||
}
|
||||
break;
|
||||
case MIXERSETTINGS_CURVE2SOURCE_COLLECTIVE:
|
||||
// assume reversible motor/mixer initially
|
||||
curve2 = MixerCurveFullRangeProportional(collectiveDesired, mixerSettings.ThrottleCurve2,
|
||||
MIXERSETTINGS_THROTTLECURVE2_NUMELEM);
|
||||
MIXERSETTINGS_THROTTLECURVE2_NUMELEM, multirotor);
|
||||
break;
|
||||
case MIXERSETTINGS_CURVE2SOURCE_ACCESSORY0:
|
||||
case MIXERSETTINGS_CURVE2SOURCE_ACCESSORY1:
|
||||
@ -338,7 +365,7 @@ static void actuatorTask(__attribute__((unused)) void *parameters)
|
||||
case MIXERSETTINGS_CURVE2SOURCE_ACCESSORY5:
|
||||
if (AccessoryDesiredInstGet(mixerSettings.Curve2Source - MIXERSETTINGS_CURVE2SOURCE_ACCESSORY0, &accessory) == 0) {
|
||||
// Throttle curve contribution the same for +ve vs -ve accessory....maybe not want we want.
|
||||
curve2 = MixerCurveFullRangeAbsolute(accessory.AccessoryVal, mixerSettings.ThrottleCurve2, MIXERSETTINGS_THROTTLECURVE2_NUMELEM);
|
||||
curve2 = MixerCurveFullRangeAbsolute(accessory.AccessoryVal, mixerSettings.ThrottleCurve2, MIXERSETTINGS_THROTTLECURVE2_NUMELEM, multirotor);
|
||||
} else {
|
||||
curve2 = 0.0f;
|
||||
}
|
||||
@ -350,6 +377,8 @@ static void actuatorTask(__attribute__((unused)) void *parameters)
|
||||
|
||||
float *status = (float *)&mixerStatus; // access status objects as an array of floats
|
||||
Mixer_t *mixers = (Mixer_t *)&mixerSettings.Mixer1Type;
|
||||
float maxMotor = -1.0f; // highest motor value. Addition method needs this to be -1.0f, division method needs this to be 1.0f
|
||||
float minMotor = 1.0f; // lowest motor value Addition method needs this to be 1.0f, division method needs this to be -1.0f
|
||||
|
||||
for (int ct = 0; ct < MAX_MIX_ACTUATORS; ct++) {
|
||||
// During boot all camera actuators should be completely disabled (PWM pulse = 0).
|
||||
@ -373,9 +402,11 @@ static void actuatorTask(__attribute__((unused)) void *parameters)
|
||||
nonreversible_curve1 = 0.0f;
|
||||
}
|
||||
if (nonreversible_curve2 < 0.0f) {
|
||||
nonreversible_curve2 = 0.0f;
|
||||
if (!multirotor) { // allow negative throttle if multirotor. function scaleMotors handles the sanity checks.
|
||||
nonreversible_curve2 = 0.0f;
|
||||
}
|
||||
}
|
||||
status[ct] = ProcessMixer(ct, nonreversible_curve1, nonreversible_curve2, &desired, dTSeconds);
|
||||
status[ct] = ProcessMixer(ct, nonreversible_curve1, nonreversible_curve2, &desired, dTSeconds, multirotor);
|
||||
// If not armed or motors aren't meant to spin all the time
|
||||
if (!armed ||
|
||||
(!spinWhileArmed && !positiveThrottle)) {
|
||||
@ -386,10 +417,14 @@ static void actuatorTask(__attribute__((unused)) void *parameters)
|
||||
// If armed meant to keep spinning,
|
||||
else if ((spinWhileArmed && !positiveThrottle) ||
|
||||
(status[ct] < 0)) {
|
||||
status[ct] = 0;
|
||||
if (!multirotor) {
|
||||
status[ct] = 0;
|
||||
// allow throttle values lower than 0 if multirotor.
|
||||
// Values will be scaled to 0 if they need to be in the scaleMotor function
|
||||
}
|
||||
}
|
||||
} else if (mixer_type == MIXERSETTINGS_MIXER1TYPE_REVERSABLEMOTOR) {
|
||||
status[ct] = ProcessMixer(ct, curve1, curve2, &desired, dTSeconds);
|
||||
status[ct] = ProcessMixer(ct, curve1, curve2, &desired, dTSeconds, multirotor);
|
||||
// Reversable Motors are like Motors but go to neutral instead of minimum
|
||||
// If not armed or motor is inactive - no "spinwhilearmed" for this engine type
|
||||
if (!armed || !activeThrottle) {
|
||||
@ -398,7 +433,7 @@ static void actuatorTask(__attribute__((unused)) void *parameters)
|
||||
status[ct] = 0; // force neutral throttle
|
||||
}
|
||||
} else if (mixer_type == MIXERSETTINGS_MIXER1TYPE_SERVO) {
|
||||
status[ct] = ProcessMixer(ct, curve1, curve2, &desired, dTSeconds);
|
||||
status[ct] = ProcessMixer(ct, curve1, curve2, &desired, dTSeconds, multirotor);
|
||||
} else {
|
||||
status[ct] = -1;
|
||||
|
||||
@ -444,16 +479,39 @@ static void actuatorTask(__attribute__((unused)) void *parameters)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If mixer type is motor we need to find which motor has the highest value and which motor has the lowest value.
|
||||
// For use in function scaleMotor
|
||||
if (mixers[ct].type == MIXERSETTINGS_MIXER1TYPE_MOTOR) {
|
||||
if (maxMotor < status[ct]) {
|
||||
maxMotor = status[ct];
|
||||
}
|
||||
if (minMotor > status[ct]) {
|
||||
minMotor = status[ct];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Set real actuator output values scaling them from mixers. All channels
|
||||
// will be set except explicitly disabled (which will have PWM pulse = 0).
|
||||
for (int i = 0; i < MAX_MIX_ACTUATORS; i++) {
|
||||
if (command.Channel[i]) {
|
||||
command.Channel[i] = scaleChannel(status[i],
|
||||
actuatorSettings.ChannelMax[i],
|
||||
actuatorSettings.ChannelMin[i],
|
||||
actuatorSettings.ChannelNeutral[i]);
|
||||
if (mixers[i].type == MIXERSETTINGS_MIXER1TYPE_MOTOR) { // If mixer is for a motor we need to find the highest value of all motors
|
||||
command.Channel[i] = scaleMotor(status[i],
|
||||
actuatorSettings.ChannelMax[i],
|
||||
actuatorSettings.ChannelMin[i],
|
||||
actuatorSettings.ChannelNeutral[i],
|
||||
maxMotor,
|
||||
minMotor,
|
||||
armed,
|
||||
AlwaysStabilizeWhenArmed,
|
||||
throttleDesired);
|
||||
} else { // else we scale the channel
|
||||
command.Channel[i] = scaleChannel(status[i],
|
||||
actuatorSettings.ChannelMax[i],
|
||||
actuatorSettings.ChannelMin[i],
|
||||
actuatorSettings.ChannelNeutral[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -497,7 +555,7 @@ static void actuatorTask(__attribute__((unused)) void *parameters)
|
||||
* Process mixing for one actuator
|
||||
*/
|
||||
float ProcessMixer(const int index, const float curve1, const float curve2,
|
||||
ActuatorDesiredData *desired, const float period)
|
||||
ActuatorDesiredData *desired, const float period, bool multirotor)
|
||||
{
|
||||
static float lastFilteredResult[MAX_MIX_ACTUATORS];
|
||||
const Mixer_t *mixers = (Mixer_t *)&mixerSettings.Mixer1Type; // pointer to array of mixers in UAVObjects
|
||||
@ -511,8 +569,10 @@ float ProcessMixer(const int index, const float curve1, const float curve2,
|
||||
|
||||
// note: no feedforward for reversable motors yet for safety reasons
|
||||
if (mixer->type == MIXERSETTINGS_MIXER1TYPE_MOTOR) {
|
||||
if (result < 0.0f) { // idle throttle
|
||||
result = 0.0f;
|
||||
if (!multirotor) { // we allow negative throttle with a multirotor
|
||||
if (result < 0.0f) { // zero throttle
|
||||
result = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
// feed forward
|
||||
@ -560,9 +620,9 @@ float ProcessMixer(const int index, const float curve1, const float curve2,
|
||||
* Input of 0 -> lookup(0)
|
||||
* Input of 1 -> lookup(1)
|
||||
*/
|
||||
static float MixerCurveFullRangeProportional(const float input, const float *curve, uint8_t elements)
|
||||
static float MixerCurveFullRangeProportional(const float input, const float *curve, uint8_t elements, bool multirotor)
|
||||
{
|
||||
float unsigned_value = MixerCurveFullRangeAbsolute(input, curve, elements);
|
||||
float unsigned_value = MixerCurveFullRangeAbsolute(input, curve, elements, multirotor);
|
||||
|
||||
if (input < 0.0f) {
|
||||
return -unsigned_value;
|
||||
@ -580,7 +640,7 @@ static float MixerCurveFullRangeProportional(const float input, const float *cur
|
||||
* Input of 0 -> lookup(0)
|
||||
* Input of 1 -> lookup(1)
|
||||
*/
|
||||
static float MixerCurveFullRangeAbsolute(const float input, const float *curve, uint8_t elements)
|
||||
static float MixerCurveFullRangeAbsolute(const float input, const float *curve, uint8_t elements, bool multirotor)
|
||||
{
|
||||
float abs_input = fabsf(input);
|
||||
float scale = abs_input * (float)(elements - 1);
|
||||
@ -594,6 +654,16 @@ static float MixerCurveFullRangeAbsolute(const float input, const float *curve,
|
||||
if (idx2 >= elements) {
|
||||
idx2 = elements - 1; // clamp to highest entry in table
|
||||
if (idx1 >= elements) {
|
||||
if (multirotor) {
|
||||
// if multirotor frame we can return throttle values higher than 100%.
|
||||
// Since the we don't have elements in the curve higher than 100% we return
|
||||
// the last element multiplied by the throttle float
|
||||
if (input < 2.0f) { // this limits positive throttle to 200% of max value in table (Maybe this is too much allowance)
|
||||
return curve[idx2] * input;
|
||||
} else {
|
||||
return curve[idx2] * 2.0f; // return 200% of max value in table
|
||||
}
|
||||
}
|
||||
idx1 = elements - 1;
|
||||
}
|
||||
}
|
||||
@ -636,6 +706,73 @@ static int16_t scaleChannel(float value, int16_t max, int16_t min, int16_t neutr
|
||||
return valueScaled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constrain motor values to keep any one motor value from going too far out of range of another motor
|
||||
*/
|
||||
static int16_t scaleMotor(float value, int16_t max, int16_t min, int16_t neutral, float maxMotor, float minMotor, bool armed, bool AlwaysStabilizeWhenArmed, float throttleDesired)
|
||||
{
|
||||
int16_t valueScaled;
|
||||
int16_t maxMotorScaled;
|
||||
int16_t minMotorScaled;
|
||||
int16_t diff;
|
||||
|
||||
// Scale
|
||||
valueScaled = (int16_t)(value * ((float)(max - neutral))) + neutral;
|
||||
maxMotorScaled = (int16_t)(maxMotor * ((float)(max - neutral))) + neutral;
|
||||
minMotorScaled = (int16_t)(minMotor * ((float)(max - neutral))) + neutral;
|
||||
|
||||
|
||||
if (max > min) {
|
||||
diff = max - maxMotorScaled; // difference between max allowed and actual max motor
|
||||
if (diff < 0) { // if the difference is smaller than 0 we add it to the scaled value
|
||||
valueScaled += diff;
|
||||
}
|
||||
diff = neutral - minMotorScaled; // difference between min allowed and actual min motor
|
||||
if (diff > 0) { // if the difference is larger than 0 we add it to the scaled value
|
||||
valueScaled += diff;
|
||||
}
|
||||
// todo: make this flow easier to understand
|
||||
if (valueScaled > max) {
|
||||
valueScaled = max; // clamp to max value only after scaling is done.
|
||||
}
|
||||
|
||||
if ((valueScaled < neutral) && (spinWhileArmed) && AlwaysStabilizeWhenArmed) {
|
||||
valueScaled = neutral; // clamp to neutral value only after scaling is done.
|
||||
} else if ((valueScaled < neutral) && (!spinWhileArmed) && AlwaysStabilizeWhenArmed) {
|
||||
valueScaled = neutral; // clamp to neutral value only after scaling is done. //throttle goes to min if throttledesired is equal to or less than 0 below
|
||||
} else if (valueScaled < neutral) {
|
||||
valueScaled = min; // clamp to min value only after scaling is done.
|
||||
}
|
||||
} else {
|
||||
// not sure what to do about reversed polarity right now. Why would anyone do this?
|
||||
if (valueScaled < max) {
|
||||
valueScaled = max; // clamp to max value only after scaling is done.
|
||||
}
|
||||
if (valueScaled > min) {
|
||||
valueScaled = min; // clamp to min value only after scaling is done.
|
||||
}
|
||||
}
|
||||
|
||||
// I've added the bool AlwaysStabilizeWhenArmed to this function. Right now we command the motors at min or a range between neutral and max.
|
||||
// NEVER should a motor be command at between min and neutral. I don't like the idea of stabilization ever commanding a motor to min, but we give people the option
|
||||
// This prevents motors startup sync issues causing possible ESC failures.
|
||||
|
||||
// safety checks
|
||||
if (!armed) {
|
||||
// if not armed return min EVERYTIME!
|
||||
valueScaled = min;
|
||||
} else if (!AlwaysStabilizeWhenArmed && (throttleDesired <= 0.0f) && spinWhileArmed) {
|
||||
// all motors idle is AlwaysStabilizeWhenArmed is false, throttle is less than or equal to neutral and spin while armed
|
||||
// stabilize when armed?
|
||||
valueScaled = neutral;
|
||||
} else if (!spinWhileArmed && (throttleDesired <= 0.0f)) {
|
||||
// soft disarm
|
||||
valueScaled = min;
|
||||
}
|
||||
|
||||
return valueScaled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set actuator output to the neutral values (failsafe)
|
||||
*/
|
||||
|
@ -242,6 +242,7 @@ static void stabilizationInnerloopTask()
|
||||
float *actuatorDesiredAxis = &actuator.Roll;
|
||||
int t;
|
||||
float dT;
|
||||
bool multirotor = (GetCurrentFrameType() == FRAME_TYPE_MULTIROTOR); // check if frame is a multirotor
|
||||
dT = PIOS_DELTATIME_GetAverageSeconds(&timeval);
|
||||
|
||||
StabilizationStatusOuterLoopData outerLoop;
|
||||
@ -324,7 +325,12 @@ static void stabilizationInnerloopTask()
|
||||
}
|
||||
}
|
||||
|
||||
actuatorDesiredAxis[t] = boundf(actuatorDesiredAxis[t], -1.0f, 1.0f);
|
||||
if (!multirotor) {
|
||||
// we only need to clamp the desired axis to a sane range if the frame is not a multirotor type
|
||||
// we don't want to do any clamping until after the motors are calculated and scaled.
|
||||
// need to figure out what to do with a tricopter tail servo.
|
||||
actuatorDesiredAxis[t] = boundf(actuatorDesiredAxis[t], -1.0f, 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
actuator.UpdateTime = dT * 1000;
|
||||
|
@ -97,7 +97,7 @@
|
||||
/* PIOS receiver drivers */
|
||||
#define PIOS_INCLUDE_PWM
|
||||
#define PIOS_INCLUDE_PPM
|
||||
/* #define PIOS_INCLUDE_PPM_FLEXI */
|
||||
#define PIOS_INCLUDE_PPM_FLEXI
|
||||
#define PIOS_INCLUDE_DSM
|
||||
#define PIOS_INCLUDE_SBUS
|
||||
/* #define PIOS_INCLUDE_GCSRCVR */
|
||||
|
@ -5621,13 +5621,16 @@ Beware of not locking yourself out!</source>
|
||||
<source>If enabled, a fast recalibration of gyro zero point will be done
|
||||
whenever the frame is armed. Do not move the airframe while
|
||||
arming it in that case!</source>
|
||||
<translation>每次解锁航模时,控制器以解锁时摆放状态做一次快速水平校准。
|
||||
打开此项设置后,请务必保证每次解锁时候航模静止放置!</translation>
|
||||
<translation>每次解锁航模时,为陀螺仪传感器零点位置做一次快速调整。
|
||||
打开此项设置后,请务必保证每次解锁时候航模静止放置!
|
||||
陀螺仪传感器的作用是测量旋转量,不是用来确保飞行器维持
|
||||
对地水平的。加速度传感器Z轴读取到的重力加速度才是用来维持
|
||||
水平飞行稳定的参考值!</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location/>
|
||||
<source>Zero gyros while arming aircraft</source>
|
||||
<translation>每次解锁时,重置陀螺仪读取数值</translation>
|
||||
<translation>除非你对自己智商足够自信,且透彻明白陀螺仪传感器和加速度传感器的作用和区别,否则请勿自作聪明取消此项设置</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location/>
|
||||
@ -9244,32 +9247,32 @@ Please select the type of multirotor you want to create a configuration for belo
|
||||
</message>
|
||||
<message>
|
||||
<location/>
|
||||
<location filename="../../../src/plugins/setupwizard/pages/outputcalibrationpage.cpp" line="+435"/>
|
||||
<location line="+104"/>
|
||||
<location filename="../../../src/plugins/setupwizard/pages/outputcalibrationpage.cpp" line="+561"/>
|
||||
<location line="+131"/>
|
||||
<source>Start</source>
|
||||
<translation>开始</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../src/plugins/setupwizard/pages/outputcalibrationpage.cpp" line="-198"/>
|
||||
<location filename="../../../src/plugins/setupwizard/pages/outputcalibrationpage.cpp" line="-268"/>
|
||||
<location line="+8"/>
|
||||
<location line="+178"/>
|
||||
<location line="+25"/>
|
||||
<location line="+243"/>
|
||||
<location line="+38"/>
|
||||
<source>Output value : <b>%1</b> µs</source>
|
||||
<translation>输出值:<b>%1</b>µs</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location line="-206"/>
|
||||
<location line="-284"/>
|
||||
<source><html><head/><body><p><span style=" font-size:10pt;">To find </span><span style=" font-size:10pt; font-weight:600;">the neutral rate for this reversable motor</span><span style=" font-size:10pt;">, press the Start button below and slide the slider to the right or left until you find the value where the motor doesn't start. <br/><br/>When done press button again to stop.</span></p></body></html></source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location line="+89"/>
|
||||
<location line="+104"/>
|
||||
<location line="+132"/>
|
||||
<location line="+131"/>
|
||||
<source>Stop</source>
|
||||
<translation>停止</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location line="-43"/>
|
||||
<location line="-59"/>
|
||||
<source>The actuator module is in an error state.
|
||||
|
||||
Please make sure the correct firmware version is used then restart the wizard and try again. If the problem persists please consult the openpilot.org support forum.</source>
|
||||
@ -9277,6 +9280,16 @@ Please make sure the correct firmware version is used then restart the wizard an
|
||||
|
||||
请确认设备上固件版本是否正确,然后重新启动设置向导。如果问题继续存在,请到openpilot.org官网论坛寻求进一步技术支持。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location line="+132"/>
|
||||
<source>Output value : <b>%1</b> µs (Min)</source>
|
||||
<translation>输出值:<b>%1</b>µs (最小)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location line="+31"/>
|
||||
<source>Output value : <b>%1</b> µs (Max)</source>
|
||||
<translation>输出值:<b>%1</b>µs (最大)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../src/plugins/setupwizard/pages/outputcalibrationpage.ui"/>
|
||||
<source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
@ -9370,6 +9383,11 @@ p, li { white-space: pre-wrap; }
|
||||
<source>Output value: 1000µs</source>
|
||||
<translation>输出值:1000µs</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location/>
|
||||
<source>Calibrate all motor outputs at the same time</source>
|
||||
<translation type="unfinished">一次性给所有电机设置相同怠速点</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>SavePage</name>
|
||||
@ -10268,7 +10286,7 @@ Do you still want to proceed?</source>
|
||||
<translation>在设置向导结束以后会停留在“解锁设置”选项页,请务必修改遥控器解锁方式。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location line="+210"/>
|
||||
<location line="+212"/>
|
||||
<source>Next</source>
|
||||
<translation>下一步</translation>
|
||||
</message>
|
||||
@ -10348,6 +10366,16 @@ You can press 'back' at any time to return to the previous screen or p
|
||||
<source>For a Quad: Elevator is Pitch, Ailerons are Roll, and Rudder is Yaw.</source>
|
||||
<translation>对于多旋翼飞行器,升降舵(ELEV)控制俯仰,副翼(AILE)控制横滚,方向舵(RUDD)控制方向。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location line="+1016"/>
|
||||
<source>Warning</source>
|
||||
<translation>警告</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location line="+0"/>
|
||||
<source><p>There is something wrong with Throttle range. Please redo calibration and move <b>ALL sticks</b>, Throttle stick included.</p></source>
|
||||
<translation><p>油门行程识别出错。请重新拨动<b>所有操纵杆</b>再次进行校准,切记不要忽略油门摇杆。</p></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Please center all controls and trims and press Next when ready.
|
||||
|
||||
@ -10377,7 +10405,7 @@ IMPORTANT: These new settings have not been saved to the board yet. After pressi
|
||||
注意:遥控器校准结果尚未保存,请点击“下一步”进入“解锁设置”页,将解锁动作设置好以后,再点击”保存“按钮将所有遥控器输入设置信息保存。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location line="+191"/>
|
||||
<location line="-825"/>
|
||||
<source>Please enable throttle hold mode.
|
||||
|
||||
Move the Collective Pitch stick.</source>
|
||||
@ -10419,7 +10447,7 @@ Move the %1 stick.</source>
|
||||
<translation>结束手动校准</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location line="+3"/>
|
||||
<location line="+4"/>
|
||||
<source><p>Arming Settings are now set to 'Always Disarmed' for your safety.</p><p>Be sure your receiver is powered with an external source and Transmitter is on.</p><p align='center'><b>Stop Manual Calibration</b> when done</p></source>
|
||||
<translation><p>安全起见,在后续操作开始之前,强制遥控器进入永久锁定状态。</p><p>请确认遥控器发射机和接收器已经打开。</p><p align='center'>完成手动校准后,请点击<b>结束手动校准</b></p></translation>
|
||||
</message>
|
||||
@ -10429,12 +10457,12 @@ Move the %1 stick.</source>
|
||||
<translation>手动校准结束后,请打开“解锁设置”选项页设置飞行器解锁动作。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location line="+33"/>
|
||||
<location line="+51"/>
|
||||
<source>Start Manual Calibration</source>
|
||||
<translation>开始手动校准</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location line="-764"/>
|
||||
<location line="-783"/>
|
||||
<source> Alternatively, click Next to skip this channel.</source>
|
||||
<translation>你也可以点击“下一步/跳过”忽略该项。</translation>
|
||||
</message>
|
||||
@ -10762,14 +10790,14 @@ Move the %1 stick.</source>
|
||||
<location line="+24"/>
|
||||
<location line="+6"/>
|
||||
<location line="+19"/>
|
||||
<location line="+16"/>
|
||||
<location line="+19"/>
|
||||
<location line="+16"/>
|
||||
<location line="+38"/>
|
||||
<source>Unknown</source>
|
||||
<translation>未知设备</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location line="-182"/>
|
||||
<location line="-185"/>
|
||||
<source>Vehicle type: </source>
|
||||
<translation>航模类型: </translation>
|
||||
</message>
|
||||
@ -10927,6 +10955,11 @@ Move the %1 stick.</source>
|
||||
</message>
|
||||
<message>
|
||||
<location line="+9"/>
|
||||
<source>Synched ESC</source>
|
||||
<translation>Synched电调</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location line="+3"/>
|
||||
<source>Oneshot ESC</source>
|
||||
<translation>Oneshot电调</translation>
|
||||
</message>
|
||||
@ -11040,7 +11073,7 @@ Move the %1 stick.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location line="+199"/>
|
||||
<location line="+196"/>
|
||||
<location line="+32"/>
|
||||
<location line="+37"/>
|
||||
<source>Writing actuator settings</source>
|
||||
@ -11073,7 +11106,7 @@ Move the %1 stick.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location line="+146"/>
|
||||
<location line="+144"/>
|
||||
<source>Writing mixer settings</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
@ -13400,7 +13433,7 @@ p, li { white-space: pre-wrap; }
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../src/plugins/setupwizard/pages/esccalibrationpage.cpp" line="+49"/>
|
||||
<location line="+49"/>
|
||||
<location line="+58"/>
|
||||
<location line="+42"/>
|
||||
<location line="+7"/>
|
||||
<location line="+9"/>
|
||||
@ -14305,7 +14338,7 @@ Please first select the area of the map to rip with <CTRL>+Left mouse clic
|
||||
<location line="+3"/>
|
||||
<location line="+261"/>
|
||||
<source>%1 Hz</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location line="-201"/>
|
||||
@ -14329,8 +14362,12 @@ Please first select the area of the map to rip with <CTRL>+Left mouse clic
|
||||
</message>
|
||||
<message>
|
||||
<location line="+32"/>
|
||||
<source>OneShot and PWMSync output only works with Receiver Port settings marked with '+OneShot'<br>When using Receiver Port setting 'PPM_PIN8+OneShot' <b><font color='%1'>Bank %2</font></b> must be set to PWM</source>
|
||||
<translation>要打开OneShot以及PWMSync输出,请确保遥控接收器端口设置为“+OneShot”<br>当接收器端口设置为“PPM_PIN8+OneShot”时,<b><font color='#C3A8FF'>输出集%2</font></b>必须设置为PWM</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>OneShot only works with Receiver Port settings marked with '+OneShot'<br>When using Receiver Port setting 'PPM_PIN8+OneShot' <b><font color='%1'>Bank %2</font></b> must be set to PWM</source>
|
||||
<translation>遥控接收器端口设置为“+OneShot”后才能<br>正常工作。假设设置为“PPM_PIN6+OneShot”,则<b><font color='%1'>输出集%2</font></b>必须设置为PWM</translation>
|
||||
<translation type="vanished">遥控接收器端口设置为“+OneShot”后才能<br>正常工作。假设设置为“PPM_PIN6+OneShot”,则<b><font color='%1'>输出集%2</font></b>必须设置为PWM</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>OneShot only works with Receiver Port settings marked with '+OneShot'<br>When using Receiver Port setting 'PPM_PIN6+OneShot' <b><font color='#C3A8FF'>Bank 4 (output 6,9-10)</font></b> must be set to PWM</source>
|
||||
|
@ -420,7 +420,7 @@ void ConfigMultiRotorWidget::refreshWidgetsValues(QString frameType)
|
||||
m_aircraft->multiThrottleCurve->initCurve(&curveValues);
|
||||
} else {
|
||||
// no, init a straight curve
|
||||
m_aircraft->multiThrottleCurve->initLinearCurve(curveValues.count(), 0.9);
|
||||
m_aircraft->multiThrottleCurve->initLinearCurve(curveValues.count(), 1.0);
|
||||
}
|
||||
|
||||
GUIConfigDataUnion config = getConfigData();
|
||||
|
@ -690,6 +690,8 @@ void OutputCalibrationPage::on_motorNeutralSlider_valueChanged(int value)
|
||||
void OutputCalibrationPage::on_servoButton_toggled(bool checked)
|
||||
{
|
||||
ui->servoButton->setText(checked ? tr("Stop") : tr("Start"));
|
||||
// Now we set servos, motors are done (Tricopter fix)
|
||||
ui->calibrateAllMotors->setChecked(false);
|
||||
|
||||
QList<quint16> currentChannels;
|
||||
getCurrentChannels(currentChannels);
|
||||
|
@ -433,7 +433,6 @@ void VehicleConfigurationHelper::applyActuatorConfiguration()
|
||||
if (m_configSource->getControllerType() == VehicleConfigurationSource::CONTROLLER_CC ||
|
||||
m_configSource->getControllerType() == VehicleConfigurationSource::CONTROLLER_CC3D) {
|
||||
data.BankUpdateFreq[1] = servoFrequence;
|
||||
data.BankMode[1] = bankMode;
|
||||
} else if (m_configSource->getControllerType() == VehicleConfigurationSource::CONTROLLER_REVO) {
|
||||
data.BankUpdateFreq[1] = escFrequence;
|
||||
data.BankMode[1] = bankMode;
|
||||
@ -711,7 +710,7 @@ void VehicleConfigurationHelper::applyMixerConfiguration(mixerChannelSettings ch
|
||||
}
|
||||
|
||||
// Default maxThrottle and minThrottle
|
||||
float maxThrottle = 0.9;
|
||||
float maxThrottle = 1;
|
||||
float minThrottle = 0;
|
||||
|
||||
|
||||
@ -1011,7 +1010,7 @@ void VehicleConfigurationHelper::resetVehicleConfig()
|
||||
Q_ASSERT(field);
|
||||
// Set default curve at 90% max for Multirotors
|
||||
for (quint32 i = 0; i < field->getNumElements(); i++) {
|
||||
field->setValue(i * (0.9f / (field->getNumElements() - 1)), i);
|
||||
field->setValue(i * (1.0f / (field->getNumElements() - 1)), i);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -296,7 +296,7 @@ Section ; create uninstall info
|
||||
WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenPilot" "UninstallString" '"$INSTDIR\Uninstall.exe"'
|
||||
WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenPilot" "DisplayIcon" '"$INSTDIR\bin\openpilotgcs.exe"'
|
||||
WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenPilot" "Publisher" "OpenPilot Team"
|
||||
WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenPilot" "DisplayVersion" "Ragin’ Cajun"
|
||||
WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenPilot" "DisplayVersion" "Ragin' Cajun"
|
||||
WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenPilot" "URLInfoAbout" "http://www.openpilot.org"
|
||||
WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenPilot" "HelpLink" "http://wiki.openpilot.org"
|
||||
WriteRegDWORD HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenPilot" "EstimatedSize" 100600
|
||||
|
@ -105,6 +105,7 @@
|
||||
%0402NE:PositionHold:CourseLock:PositionRoam:HomeLeash:AbsolutePosition:ReturnToBase:Land:PathPlanner:POI:AutoCruise,AutoTakeoff\
|
||||
%0903NE:POI:PathPlanner:AutoCruise;"/>
|
||||
|
||||
<field name="AlwaysStabilizeWhenArmed" units="" type="enum" elements="1" options="FALSE,TRUE" defaultvalue="FALSE" description="For Multirotors. Always stabilize no matter the throttle setting when vehicle is armed. Does not work when vehicle is set to Always Armed."/>
|
||||
<field name="ArmedTimeout" units="ms" type="uint16" elements="1" defaultvalue="30000"/>
|
||||
<field name="ArmingSequenceTime" units="ms" type="uint16" elements="1" defaultvalue="1000"/>
|
||||
<field name="DisarmingSequenceTime" units="ms" type="uint16" elements="1" defaultvalue="1000"/>
|
||||
|
Loading…
Reference in New Issue
Block a user