mirror of
https://bitbucket.org/librepilot/librepilot.git
synced 2025-03-15 07:29:15 +01:00
Merge remote-tracking branch 'origin/next' into thread/OP-1504_Vehicle_Name_Setting
Conflicts: ground/openpilotgcs/src/plugins/config/stabilization.ui
This commit is contained in:
commit
2b637080fe
@ -119,5 +119,44 @@ static inline float y_on_curve(float x, const pointf points[], int num_points)
|
||||
// Find the y value on the selected line.
|
||||
return y_on_line(x, &points[end_point - 1], &points[end_point]);
|
||||
}
|
||||
// Fast inverse square root implementation from "quake3-1.32b/code/game/q_math.c"
|
||||
// http://en.wikipedia.org/wiki/Fast_inverse_square_root
|
||||
|
||||
static inline float fast_invsqrtf(float number)
|
||||
{
|
||||
float x2, y;
|
||||
const float threehalfs = 1.5F;
|
||||
|
||||
union {
|
||||
float f;
|
||||
uint32_t u;
|
||||
} i;
|
||||
|
||||
x2 = number * 0.5F;
|
||||
y = number;
|
||||
|
||||
i.f = y; // evil floating point bit level hacking
|
||||
i.u = 0x5f3759df - (i.u >> 1); // what the fxck?
|
||||
y = i.f;
|
||||
y = y * (threehalfs - (x2 * y * y)); // 1st iteration
|
||||
// y = y * ( threehalfs - ( x2 * y * y ) ); // 2nd iteration, this can be removed
|
||||
|
||||
return y;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ultrafast pow() aproximation needed for expo
|
||||
* Based on Algorithm by Martin Ankerl
|
||||
*/
|
||||
static inline float fastPow(float a, float b)
|
||||
{
|
||||
union {
|
||||
double d;
|
||||
int32_t x[2];
|
||||
} u = { (double)a };
|
||||
u.x[1] = (int32_t)(b * (u.x[1] - 1072632447) + 1072632447);
|
||||
u.x[0] = 0;
|
||||
return (float)u.d;
|
||||
}
|
||||
|
||||
#endif /* MATHMISC_H */
|
||||
|
@ -89,9 +89,12 @@ float pid_apply_setpoint(struct pid *pid, const pid_scaler *scaler, const float
|
||||
float diff = ((deriv_gamma * setpoint - measured) - pid->lastErr);
|
||||
pid->lastErr = (deriv_gamma * setpoint - measured);
|
||||
if (pid->d > 0.0f && dT > 0.0f) {
|
||||
// low pass filter derivative term. below formula is the same as
|
||||
// dterm = (1-alpha)*pid->lastDer + alpha * (...)/dT
|
||||
// with alpha = dT/(deriv_tau+dT)
|
||||
dterm = pid->lastDer + dT / (dT + deriv_tau) * ((scaler->d * diff * pid->d / dT) - pid->lastDer);
|
||||
pid->lastDer = dterm; // ^ set constant to 1/(2*pi*f_cutoff)
|
||||
} // 7.9577e-3 means 20 Hz f_cutoff
|
||||
pid->lastDer = dterm;
|
||||
}
|
||||
|
||||
return (err * scaler->p * pid->p) + pid->iAccumulator / 1000.0f + dterm;
|
||||
}
|
||||
|
@ -41,14 +41,23 @@
|
||||
#include "altitude.h"
|
||||
#include "barosensor.h" // object that will be updated by the module
|
||||
#include "revosettings.h"
|
||||
#include <mathmisc.h>
|
||||
#if defined(PIOS_INCLUDE_HCSR04)
|
||||
#include "sonaraltitude.h" // object that will be updated by the module
|
||||
#endif
|
||||
#include "taskinfo.h"
|
||||
|
||||
// Private constants
|
||||
#define STACK_SIZE_BYTES 550
|
||||
#define TASK_PRIORITY (tskIDLE_PRIORITY + 1)
|
||||
#define STACK_SIZE_BYTES 550
|
||||
#define TASK_PRIORITY (tskIDLE_PRIORITY + 1)
|
||||
|
||||
// Interval in number of sample to recalculate temp bias
|
||||
#define TEMP_CALIB_INTERVAL 10
|
||||
|
||||
// LPF
|
||||
#define TEMP_DT (1.0f / 120.0f)
|
||||
#define TEMP_LPF_FC 5.0f
|
||||
static const float temp_alpha = TEMP_DT / (TEMP_DT + 1.0f / (2.0f * M_PI_F * TEMP_LPF_FC));
|
||||
|
||||
// Private types
|
||||
|
||||
@ -57,6 +66,11 @@ static xTaskHandle taskHandle;
|
||||
static RevoSettingsBaroTempCorrectionPolynomialData baroCorrection;
|
||||
static RevoSettingsBaroTempCorrectionExtentData baroCorrectionExtent;
|
||||
static volatile bool tempCorrectionEnabled;
|
||||
|
||||
static float baro_temp_bias = 0;
|
||||
static float baro_temperature = NAN;
|
||||
static uint8_t temp_calibration_count = 0;
|
||||
|
||||
// Private functions
|
||||
static void altitudeTask(void *parameters);
|
||||
static void SettingsUpdatedCb(UAVObjEvent *ev);
|
||||
@ -166,13 +180,22 @@ static void altitudeTask(__attribute__((unused)) void *parameters)
|
||||
temp = PIOS_MS5611_GetTemperature();
|
||||
press = PIOS_MS5611_GetPressure();
|
||||
|
||||
if (tempCorrectionEnabled) {
|
||||
if (isnan(baro_temperature)) {
|
||||
baro_temperature = temp;
|
||||
}
|
||||
|
||||
baro_temperature = temp_alpha * (temp - baro_temperature) + baro_temperature;
|
||||
|
||||
if (tempCorrectionEnabled && !temp_calibration_count) {
|
||||
temp_calibration_count = TEMP_CALIB_INTERVAL;
|
||||
// pressure bias = A + B*t + C*t^2 + D * t^3
|
||||
// in case the temperature is outside of the calibrated range, uses the nearest extremes
|
||||
float ctemp = temp > baroCorrectionExtent.max ? baroCorrectionExtent.max :
|
||||
(temp < baroCorrectionExtent.min ? baroCorrectionExtent.min : temp);
|
||||
press -= baroCorrection.a + ((baroCorrection.d * ctemp + baroCorrection.c) * ctemp + baroCorrection.b) * ctemp;
|
||||
float ctemp = boundf(baro_temperature, baroCorrectionExtent.max, baroCorrectionExtent.min);
|
||||
baro_temp_bias = baroCorrection.a + ((baroCorrection.d * ctemp + baroCorrection.c) * ctemp + baroCorrection.b) * ctemp;
|
||||
}
|
||||
|
||||
press -= baro_temp_bias;
|
||||
|
||||
float altitude = 44330.0f * (1.0f - powf((press) / MS5611_P0, (1.0f / 5.255f)));
|
||||
|
||||
if (!isnan(altitude)) {
|
||||
|
@ -64,8 +64,8 @@
|
||||
|
||||
#include "CoordinateConversions.h"
|
||||
#include <pios_notify.h>
|
||||
|
||||
|
||||
#include <mathmisc.h>
|
||||
#include <pios_constants.h>
|
||||
#include <pios_instrumentation_helper.h>
|
||||
|
||||
PERF_DEFINE_COUNTER(counterUpd);
|
||||
@ -79,16 +79,25 @@ PERF_DEFINE_COUNTER(counterAtt);
|
||||
// - 0xA7710004 number of accel samples read for each loop (cc only).
|
||||
|
||||
// Private constants
|
||||
#define STACK_SIZE_BYTES 540
|
||||
#define TASK_PRIORITY (tskIDLE_PRIORITY + 3)
|
||||
#define STACK_SIZE_BYTES 540
|
||||
#define TASK_PRIORITY (tskIDLE_PRIORITY + 3)
|
||||
|
||||
#define SENSOR_PERIOD 4
|
||||
#define UPDATE_RATE 25.0f
|
||||
// Attitude module loop interval (defined by sensor rate in pios_config.h)
|
||||
static const uint32_t sensor_period_ms = ((uint32_t)1000.0f / PIOS_SENSOR_RATE);
|
||||
|
||||
#define UPDATE_EXPECTED (1.0f / 500.0f)
|
||||
#define UPDATE_MIN 1.0e-6f
|
||||
#define UPDATE_MAX 1.0f
|
||||
#define UPDATE_ALPHA 1.0e-2f
|
||||
#define UPDATE_RATE 25.0f
|
||||
|
||||
// Interval in number of sample to recalculate temp bias
|
||||
#define TEMP_CALIB_INTERVAL 30
|
||||
// LPF
|
||||
#define TEMP_DT (1.0f / PIOS_SENSOR_RATE)
|
||||
#define TEMP_LPF_FC 5.0f
|
||||
static const float temp_alpha = TEMP_DT / (TEMP_DT + 1.0f / (2.0f * M_PI_F * TEMP_LPF_FC));
|
||||
|
||||
#define UPDATE_EXPECTED (1.0f / PIOS_SENSOR_RATE)
|
||||
#define UPDATE_MIN 1.0e-6f
|
||||
#define UPDATE_MAX 1.0f
|
||||
#define UPDATE_ALPHA 1.0e-2f
|
||||
|
||||
// Private types
|
||||
|
||||
@ -130,6 +139,10 @@ static bool apply_accel_temp = false;
|
||||
static AccelGyroSettingsgyro_temp_coeffData gyro_temp_coeff;;
|
||||
static AccelGyroSettingsaccel_temp_coeffData accel_temp_coeff;
|
||||
static AccelGyroSettingstemp_calibrated_extentData temp_calibrated_extent;
|
||||
static float temperature = NAN;
|
||||
static float accel_temp_bias[3] = { 0 };
|
||||
static float gyro_temp_bias[3] = { 0 };
|
||||
static uint8_t temp_calibration_count = 0;
|
||||
|
||||
// Accel and Gyro scaling (this is the product of sensor scale and adjustement in AccelGyroSettings
|
||||
static AccelGyroSettingsgyro_scaleData gyro_scale;
|
||||
@ -142,8 +155,7 @@ static volatile int32_t trim_accels[3];
|
||||
static volatile int32_t trim_samples;
|
||||
int32_t const MAX_TRIM_FLIGHT_SAMPLES = 65535;
|
||||
|
||||
#define GRAV 9.81f
|
||||
#define STD_CC_ACCEL_SCALE (GRAV * 0.004f)
|
||||
#define STD_CC_ACCEL_SCALE (PIOS_CONST_MKS_GRAV_ACCEL_F * 0.004f)
|
||||
/* 0.004f is gravity / LSB */
|
||||
#define STD_CC_ANALOG_GYRO_NEUTRAL 1665
|
||||
#define STD_CC_ANALOG_GYRO_GAIN 0.42f
|
||||
@ -222,12 +234,6 @@ static void AttitudeTask(__attribute__((unused)) void *parameters)
|
||||
|
||||
AlarmsClear(SYSTEMALARMS_ALARM_ATTITUDE);
|
||||
|
||||
// Set critical error and wait until the accel is producing data
|
||||
while (PIOS_ADXL345_FifoElements() == 0) {
|
||||
AlarmsSet(SYSTEMALARMS_ALARM_ATTITUDE, SYSTEMALARMS_ALARM_CRITICAL);
|
||||
PIOS_WDG_UpdateFlag(PIOS_WDG_ATTITUDE);
|
||||
}
|
||||
|
||||
bool cc3d = BOARDISCC3D;
|
||||
|
||||
if (cc3d) {
|
||||
@ -236,6 +242,11 @@ static void AttitudeTask(__attribute__((unused)) void *parameters)
|
||||
#endif
|
||||
} else {
|
||||
#if defined(PIOS_INCLUDE_ADXL345)
|
||||
// Set critical error and wait until the accel is producing data
|
||||
while (PIOS_ADXL345_FifoElements() == 0) {
|
||||
AlarmsSet(SYSTEMALARMS_ALARM_ATTITUDE, SYSTEMALARMS_ALARM_CRITICAL);
|
||||
PIOS_WDG_UpdateFlag(PIOS_WDG_ATTITUDE);
|
||||
}
|
||||
accel_test = PIOS_ADXL345_Test();
|
||||
#endif
|
||||
|
||||
@ -257,7 +268,7 @@ static void AttitudeTask(__attribute__((unused)) void *parameters)
|
||||
settingsUpdatedCb(AttitudeSettingsHandle());
|
||||
|
||||
PIOS_DELTATIME_Init(&dtconfig, UPDATE_EXPECTED, UPDATE_MIN, UPDATE_MAX, UPDATE_ALPHA);
|
||||
|
||||
portTickType lastSysTime = xTaskGetTickCount();
|
||||
// Main task loop
|
||||
while (1) {
|
||||
FlightStatusData flightStatus;
|
||||
@ -317,6 +328,7 @@ static void AttitudeTask(__attribute__((unused)) void *parameters)
|
||||
PERF_MEASURE_PERIOD(counterPeriod);
|
||||
AlarmsClear(SYSTEMALARMS_ALARM_ATTITUDE);
|
||||
}
|
||||
vTaskDelayUntil(&lastSysTime, sensor_period_ms / portTICK_PERIOD_MS);
|
||||
}
|
||||
}
|
||||
|
||||
@ -454,7 +466,7 @@ static int32_t updateSensorsCC3D(AccelStateData *accelStateData, GyroStateData *
|
||||
#if defined(PIOS_INCLUDE_MPU6000)
|
||||
|
||||
xQueueHandle queue = PIOS_MPU6000_GetQueue();
|
||||
BaseType_t ret = xQueueReceive(queue, (void *)&mpu6000_data, SENSOR_PERIOD);
|
||||
BaseType_t ret = xQueueReceive(queue, (void *)&mpu6000_data, sensor_period_ms);
|
||||
while (ret == pdTRUE) {
|
||||
gyros[0] += mpu6000_data.gyro_x;
|
||||
gyros[1] += mpu6000_data.gyro_y;
|
||||
@ -470,6 +482,7 @@ static int32_t updateSensorsCC3D(AccelStateData *accelStateData, GyroStateData *
|
||||
// check if further samples are already in queue
|
||||
ret = xQueueReceive(queue, (void *)&mpu6000_data, 0);
|
||||
}
|
||||
PERF_TRACK_VALUE(counterAccelSamples, count);
|
||||
|
||||
if (!count) {
|
||||
return -1; // Error, no data
|
||||
@ -488,21 +501,39 @@ static int32_t updateSensorsCC3D(AccelStateData *accelStateData, GyroStateData *
|
||||
accels[1] *= accel_scale.Y * invcount;
|
||||
accels[2] *= accel_scale.Z * invcount;
|
||||
temp *= invcount;
|
||||
float ctemp = temp > temp_calibrated_extent.max ? temp_calibrated_extent.max :
|
||||
(temp < temp_calibrated_extent.min ? temp_calibrated_extent.min
|
||||
: temp);
|
||||
|
||||
if (isnan(temperature)) {
|
||||
temperature = temp;
|
||||
}
|
||||
temperature = temp_alpha * (temp - temperature) + temperature;
|
||||
|
||||
if ((apply_gyro_temp || apply_accel_temp) && !temp_calibration_count) {
|
||||
temp_calibration_count = TEMP_CALIB_INTERVAL;
|
||||
float ctemp = boundf(temperature, temp_calibrated_extent.max, temp_calibrated_extent.min);
|
||||
if (apply_gyro_temp) {
|
||||
gyro_temp_bias[0] = (gyro_temp_coeff.X + gyro_temp_coeff.X2 * ctemp) * ctemp;
|
||||
gyro_temp_bias[1] = (gyro_temp_coeff.Y + gyro_temp_coeff.Y2 * ctemp) * ctemp;
|
||||
gyro_temp_bias[2] = (gyro_temp_coeff.Z + gyro_temp_coeff.Z2 * ctemp) * ctemp;
|
||||
}
|
||||
|
||||
if (apply_accel_temp) {
|
||||
accel_temp_bias[0] = accel_temp_coeff.X * ctemp;
|
||||
accel_temp_bias[1] = accel_temp_coeff.Y * ctemp;
|
||||
accel_temp_bias[2] = accel_temp_coeff.Z * ctemp;
|
||||
}
|
||||
}
|
||||
temp_calibration_count--;
|
||||
|
||||
if (apply_gyro_temp) {
|
||||
gyros[0] -= (gyro_temp_coeff.X + gyro_temp_coeff.X2 * ctemp) * ctemp;
|
||||
gyros[1] -= (gyro_temp_coeff.Y + gyro_temp_coeff.Y2 * ctemp) * ctemp;
|
||||
gyros[2] -= (gyro_temp_coeff.Z + gyro_temp_coeff.Z2 * ctemp) * ctemp;
|
||||
gyros[0] -= gyro_temp_bias[0];
|
||||
gyros[1] -= gyro_temp_bias[1];
|
||||
gyros[2] -= gyro_temp_bias[2];
|
||||
}
|
||||
|
||||
if (apply_accel_temp) {
|
||||
accels[0] -= accel_temp_coeff.X * ctemp;
|
||||
accels[1] -= accel_temp_coeff.Y * ctemp;
|
||||
accels[2] -= accel_temp_coeff.Z * ctemp;
|
||||
accels[0] -= accel_temp_bias[0];
|
||||
accels[1] -= accel_temp_bias[1];
|
||||
accels[2] -= accel_temp_bias[2];
|
||||
}
|
||||
// gyrosData->temperature = 35.0f + ((float)mpu6000_data.temperature + 512.0f) / 340.0f;
|
||||
// accelsData->temperature = 35.0f + ((float)mpu6000_data.temperature + 512.0f) / 340.0f;
|
||||
@ -587,24 +618,24 @@ __attribute__((optimize("O3"))) static void updateAttitude(AccelStateData *accel
|
||||
CrossProduct((const float *)accels_filtered, (const float *)grot_filtered, accel_err);
|
||||
|
||||
// Account for accel magnitude
|
||||
float accel_mag = sqrtf(accels_filtered[0] * accels_filtered[0] + accels_filtered[1] * accels_filtered[1] + accels_filtered[2] * accels_filtered[2]);
|
||||
if (accel_mag < 1.0e-3f) {
|
||||
float inv_accel_mag = fast_invsqrtf(accels_filtered[0] * accels_filtered[0] + accels_filtered[1] * accels_filtered[1] + accels_filtered[2] * accels_filtered[2]);
|
||||
if (inv_accel_mag > 1e3f) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Account for filtered gravity vector magnitude
|
||||
float grot_mag;
|
||||
float inv_grot_mag;
|
||||
|
||||
if (accel_filter_enabled) {
|
||||
grot_mag = sqrtf(grot_filtered[0] * grot_filtered[0] + grot_filtered[1] * grot_filtered[1] + grot_filtered[2] * grot_filtered[2]);
|
||||
inv_grot_mag = fast_invsqrtf(grot_filtered[0] * grot_filtered[0] + grot_filtered[1] * grot_filtered[1] + grot_filtered[2] * grot_filtered[2]);
|
||||
} else {
|
||||
grot_mag = 1.0f;
|
||||
inv_grot_mag = 1.0f;
|
||||
}
|
||||
|
||||
if (grot_mag < 1.0e-3f) {
|
||||
if (inv_grot_mag > 1e3f) {
|
||||
return;
|
||||
}
|
||||
const float invMag = 1.0f / (accel_mag * grot_mag);
|
||||
const float invMag = (inv_accel_mag * inv_grot_mag);
|
||||
accel_err[0] *= invMag;
|
||||
accel_err[1] *= invMag;
|
||||
accel_err[2] *= invMag;
|
||||
@ -645,21 +676,20 @@ __attribute__((optimize("O3"))) static void updateAttitude(AccelStateData *accel
|
||||
}
|
||||
|
||||
// Renomalize
|
||||
float qmag = sqrtf(q[0] * q[0] + q[1] * q[1] + q[2] * q[2] + q[3] * q[3]);
|
||||
float inv_qmag = fast_invsqrtf(q[0] * q[0] + q[1] * q[1] + q[2] * q[2] + q[3] * q[3]);
|
||||
|
||||
// If quaternion has become inappropriately short or is nan reinit.
|
||||
// THIS SHOULD NEVER ACTUALLY HAPPEN
|
||||
if ((fabsf(qmag) < 1e-3f) || isnan(qmag)) {
|
||||
if ((fabsf(inv_qmag) > 1e3f) || isnan(inv_qmag)) {
|
||||
q[0] = 1;
|
||||
q[1] = 0;
|
||||
q[2] = 0;
|
||||
q[3] = 0;
|
||||
} else {
|
||||
const float invQmag = 1.0f / qmag;
|
||||
q[0] = q[0] * invQmag;
|
||||
q[1] = q[1] * invQmag;
|
||||
q[2] = q[2] * invQmag;
|
||||
q[3] = q[3] * invQmag;
|
||||
q[0] = q[0] * inv_qmag;
|
||||
q[1] = q[1] * inv_qmag;
|
||||
q[2] = q[2] * inv_qmag;
|
||||
q[3] = q[3] * inv_qmag;
|
||||
}
|
||||
|
||||
AttitudeStateData attitudeState;
|
||||
@ -777,7 +807,7 @@ static void settingsUpdatedCb(__attribute__((unused)) UAVObjEvent *objEv)
|
||||
accelGyroSettings.accel_scale.X = trim_accels[0] / trim_samples;
|
||||
accelGyroSettings.accel_scale.Y = trim_accels[1] / trim_samples;
|
||||
// Z should average -grav
|
||||
accelGyroSettings.accel_scale.Z = trim_accels[2] / trim_samples + GRAV;
|
||||
accelGyroSettings.accel_scale.Z = trim_accels[2] / trim_samples + PIOS_CONST_MKS_GRAV_ACCEL_F;
|
||||
attitudeSettings.TrimFlight = ATTITUDESETTINGS_TRIMFLIGHT_NORMAL;
|
||||
AttitudeSettingsSet(&attitudeSettings);
|
||||
} else {
|
||||
|
@ -99,6 +99,7 @@ void takeOffLocationHandlerInit();
|
||||
((int)FLIGHTMODESETTINGS_STABILIZATION1SETTINGS_AXISLOCK == (int)STABILIZATIONDESIRED_STABILIZATIONMODE_AXISLOCK) && \
|
||||
((int)FLIGHTMODESETTINGS_STABILIZATION1SETTINGS_WEAKLEVELING == (int)STABILIZATIONDESIRED_STABILIZATIONMODE_WEAKLEVELING) && \
|
||||
((int)FLIGHTMODESETTINGS_STABILIZATION1SETTINGS_VIRTUALBAR == (int)STABILIZATIONDESIRED_STABILIZATIONMODE_VIRTUALBAR) && \
|
||||
((int)FLIGHTMODESETTINGS_STABILIZATION1SETTINGS_ACRO == (int)STABILIZATIONDESIRED_STABILIZATIONMODE_ACRO) && \
|
||||
((int)FLIGHTMODESETTINGS_STABILIZATION1SETTINGS_RATTITUDE == (int)STABILIZATIONDESIRED_STABILIZATIONMODE_RATTITUDE) && \
|
||||
((int)FLIGHTMODESETTINGS_STABILIZATION1SETTINGS_RELAYRATE == (int)STABILIZATIONDESIRED_STABILIZATIONMODE_RELAYRATE) && \
|
||||
((int)FLIGHTMODESETTINGS_STABILIZATION1SETTINGS_RELAYATTITUDE == (int)STABILIZATIONDESIRED_STABILIZATIONMODE_RELAYATTITUDE) && \
|
||||
@ -116,6 +117,7 @@ void takeOffLocationHandlerInit();
|
||||
((int)FLIGHTMODESETTINGS_STABILIZATION2SETTINGS_AXISLOCK == (int)STABILIZATIONDESIRED_STABILIZATIONMODE_AXISLOCK) && \
|
||||
((int)FLIGHTMODESETTINGS_STABILIZATION2SETTINGS_WEAKLEVELING == (int)STABILIZATIONDESIRED_STABILIZATIONMODE_WEAKLEVELING) && \
|
||||
((int)FLIGHTMODESETTINGS_STABILIZATION2SETTINGS_VIRTUALBAR == (int)STABILIZATIONDESIRED_STABILIZATIONMODE_VIRTUALBAR) && \
|
||||
((int)FLIGHTMODESETTINGS_STABILIZATION2SETTINGS_ACRO == (int)STABILIZATIONDESIRED_STABILIZATIONMODE_ACRO) && \
|
||||
((int)FLIGHTMODESETTINGS_STABILIZATION2SETTINGS_RATTITUDE == (int)STABILIZATIONDESIRED_STABILIZATIONMODE_RATTITUDE) && \
|
||||
((int)FLIGHTMODESETTINGS_STABILIZATION2SETTINGS_RELAYRATE == (int)STABILIZATIONDESIRED_STABILIZATIONMODE_RELAYRATE) && \
|
||||
((int)FLIGHTMODESETTINGS_STABILIZATION2SETTINGS_RELAYATTITUDE == (int)STABILIZATIONDESIRED_STABILIZATIONMODE_RELAYATTITUDE) && \
|
||||
@ -133,6 +135,7 @@ void takeOffLocationHandlerInit();
|
||||
((int)FLIGHTMODESETTINGS_STABILIZATION3SETTINGS_AXISLOCK == (int)STABILIZATIONDESIRED_STABILIZATIONMODE_AXISLOCK) && \
|
||||
((int)FLIGHTMODESETTINGS_STABILIZATION3SETTINGS_WEAKLEVELING == (int)STABILIZATIONDESIRED_STABILIZATIONMODE_WEAKLEVELING) && \
|
||||
((int)FLIGHTMODESETTINGS_STABILIZATION3SETTINGS_VIRTUALBAR == (int)STABILIZATIONDESIRED_STABILIZATIONMODE_VIRTUALBAR) && \
|
||||
((int)FLIGHTMODESETTINGS_STABILIZATION3SETTINGS_ACRO == (int)STABILIZATIONDESIRED_STABILIZATIONMODE_ACRO) && \
|
||||
((int)FLIGHTMODESETTINGS_STABILIZATION3SETTINGS_RATTITUDE == (int)STABILIZATIONDESIRED_STABILIZATIONMODE_RATTITUDE) && \
|
||||
((int)FLIGHTMODESETTINGS_STABILIZATION3SETTINGS_RELAYRATE == (int)STABILIZATIONDESIRED_STABILIZATIONMODE_RELAYRATE) && \
|
||||
((int)FLIGHTMODESETTINGS_STABILIZATION3SETTINGS_RELAYATTITUDE == (int)STABILIZATIONDESIRED_STABILIZATIONMODE_RELAYATTITUDE) && \
|
||||
@ -150,6 +153,7 @@ void takeOffLocationHandlerInit();
|
||||
((int)FLIGHTMODESETTINGS_STABILIZATION4SETTINGS_AXISLOCK == (int)STABILIZATIONDESIRED_STABILIZATIONMODE_AXISLOCK) && \
|
||||
((int)FLIGHTMODESETTINGS_STABILIZATION4SETTINGS_WEAKLEVELING == (int)STABILIZATIONDESIRED_STABILIZATIONMODE_WEAKLEVELING) && \
|
||||
((int)FLIGHTMODESETTINGS_STABILIZATION4SETTINGS_VIRTUALBAR == (int)STABILIZATIONDESIRED_STABILIZATIONMODE_VIRTUALBAR) && \
|
||||
((int)FLIGHTMODESETTINGS_STABILIZATION4SETTINGS_ACRO == (int)STABILIZATIONDESIRED_STABILIZATIONMODE_ACRO) && \
|
||||
((int)FLIGHTMODESETTINGS_STABILIZATION4SETTINGS_RATTITUDE == (int)STABILIZATIONDESIRED_STABILIZATIONMODE_RATTITUDE) && \
|
||||
((int)FLIGHTMODESETTINGS_STABILIZATION4SETTINGS_RELAYRATE == (int)STABILIZATIONDESIRED_STABILIZATIONMODE_RELAYRATE) && \
|
||||
((int)FLIGHTMODESETTINGS_STABILIZATION4SETTINGS_RELAYATTITUDE == (int)STABILIZATIONDESIRED_STABILIZATIONMODE_RELAYATTITUDE) && \
|
||||
@ -167,6 +171,7 @@ void takeOffLocationHandlerInit();
|
||||
((int)FLIGHTMODESETTINGS_STABILIZATION5SETTINGS_AXISLOCK == (int)STABILIZATIONDESIRED_STABILIZATIONMODE_AXISLOCK) && \
|
||||
((int)FLIGHTMODESETTINGS_STABILIZATION5SETTINGS_WEAKLEVELING == (int)STABILIZATIONDESIRED_STABILIZATIONMODE_WEAKLEVELING) && \
|
||||
((int)FLIGHTMODESETTINGS_STABILIZATION5SETTINGS_VIRTUALBAR == (int)STABILIZATIONDESIRED_STABILIZATIONMODE_VIRTUALBAR) && \
|
||||
((int)FLIGHTMODESETTINGS_STABILIZATION5SETTINGS_ACRO == (int)STABILIZATIONDESIRED_STABILIZATIONMODE_ACRO) && \
|
||||
((int)FLIGHTMODESETTINGS_STABILIZATION5SETTINGS_RATTITUDE == (int)STABILIZATIONDESIRED_STABILIZATIONMODE_RATTITUDE) && \
|
||||
((int)FLIGHTMODESETTINGS_STABILIZATION5SETTINGS_RELAYRATE == (int)STABILIZATIONDESIRED_STABILIZATIONMODE_RELAYRATE) && \
|
||||
((int)FLIGHTMODESETTINGS_STABILIZATION5SETTINGS_RELAYATTITUDE == (int)STABILIZATIONDESIRED_STABILIZATIONMODE_RELAYATTITUDE) && \
|
||||
@ -184,6 +189,7 @@ void takeOffLocationHandlerInit();
|
||||
((int)FLIGHTMODESETTINGS_STABILIZATION6SETTINGS_AXISLOCK == (int)STABILIZATIONDESIRED_STABILIZATIONMODE_AXISLOCK) && \
|
||||
((int)FLIGHTMODESETTINGS_STABILIZATION6SETTINGS_WEAKLEVELING == (int)STABILIZATIONDESIRED_STABILIZATIONMODE_WEAKLEVELING) && \
|
||||
((int)FLIGHTMODESETTINGS_STABILIZATION6SETTINGS_VIRTUALBAR == (int)STABILIZATIONDESIRED_STABILIZATIONMODE_VIRTUALBAR) && \
|
||||
((int)FLIGHTMODESETTINGS_STABILIZATION6SETTINGS_ACRO == (int)STABILIZATIONDESIRED_STABILIZATIONMODE_ACRO) && \
|
||||
((int)FLIGHTMODESETTINGS_STABILIZATION6SETTINGS_RATTITUDE == (int)STABILIZATIONDESIRED_STABILIZATIONMODE_RATTITUDE) && \
|
||||
((int)FLIGHTMODESETTINGS_STABILIZATION6SETTINGS_RELAYRATE == (int)STABILIZATIONDESIRED_STABILIZATIONMODE_RELAYRATE) && \
|
||||
((int)FLIGHTMODESETTINGS_STABILIZATION6SETTINGS_RELAYATTITUDE == (int)STABILIZATIONDESIRED_STABILIZATIONMODE_RELAYATTITUDE) && \
|
||||
|
@ -29,6 +29,7 @@
|
||||
*/
|
||||
|
||||
#include "inc/manualcontrol.h"
|
||||
#include <mathmisc.h>
|
||||
#include <manualcontrolcommand.h>
|
||||
#include <stabilizationdesired.h>
|
||||
#include <flightmodesettings.h>
|
||||
@ -39,6 +40,28 @@
|
||||
// Private types
|
||||
|
||||
// Private functions
|
||||
static float applyExpo(float value, float expo);
|
||||
|
||||
|
||||
static float applyExpo(float value, float expo)
|
||||
{
|
||||
// note: fastPow makes a small error, therefore result needs to be bound
|
||||
float exp = boundf(fastPow(1.00695f, expo), 0.5f, 2.0f);
|
||||
|
||||
// magic number scales expo
|
||||
// so that
|
||||
// expo=100 yields value**10
|
||||
// expo=0 yields value**1
|
||||
// expo=-100 yields value**(1/10)
|
||||
// (pow(2.0,1/100)~=1.00695)
|
||||
if (value > 0.0f) {
|
||||
return boundf(fastPow(value, exp), 0.0f, 1.0f);
|
||||
} else if (value < -0.0f) {
|
||||
return boundf(-fastPow(-value, exp), -1.0f, 0.0f);
|
||||
} else {
|
||||
return 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
@ -64,6 +87,9 @@ void stabilizedHandler(bool newinit)
|
||||
StabilizationBankData stabSettings;
|
||||
StabilizationBankGet(&stabSettings);
|
||||
|
||||
cmd.Roll = applyExpo(cmd.Roll, stabSettings.StickExpo.Roll);
|
||||
cmd.Pitch = applyExpo(cmd.Pitch, stabSettings.StickExpo.Pitch);
|
||||
cmd.Yaw = applyExpo(cmd.Yaw, stabSettings.StickExpo.Yaw);
|
||||
uint8_t *stab_settings;
|
||||
FlightStatusData flightStatus;
|
||||
FlightStatusGet(&flightStatus);
|
||||
@ -100,6 +126,7 @@ void stabilizedHandler(bool newinit)
|
||||
(stab_settings[0] == STABILIZATIONDESIRED_STABILIZATIONMODE_ATTITUDE) ? cmd.Roll * stabSettings.RollMax :
|
||||
(stab_settings[0] == STABILIZATIONDESIRED_STABILIZATIONMODE_AXISLOCK) ? cmd.Roll * stabSettings.ManualRate.Roll :
|
||||
(stab_settings[0] == STABILIZATIONDESIRED_STABILIZATIONMODE_VIRTUALBAR) ? cmd.Roll :
|
||||
(stab_settings[0] == STABILIZATIONDESIRED_STABILIZATIONMODE_ACRO) ? cmd.Roll * stabSettings.ManualRate.Roll :
|
||||
(stab_settings[0] == STABILIZATIONDESIRED_STABILIZATIONMODE_RATTITUDE) ? cmd.Roll * stabSettings.RollMax :
|
||||
(stab_settings[0] == STABILIZATIONDESIRED_STABILIZATIONMODE_RELAYRATE) ? cmd.Roll * stabSettings.ManualRate.Roll :
|
||||
(stab_settings[0] == STABILIZATIONDESIRED_STABILIZATIONMODE_RELAYATTITUDE) ? cmd.Roll * stabSettings.RollMax :
|
||||
@ -112,6 +139,7 @@ void stabilizedHandler(bool newinit)
|
||||
(stab_settings[1] == STABILIZATIONDESIRED_STABILIZATIONMODE_ATTITUDE) ? cmd.Pitch * stabSettings.PitchMax :
|
||||
(stab_settings[1] == STABILIZATIONDESIRED_STABILIZATIONMODE_AXISLOCK) ? cmd.Pitch * stabSettings.ManualRate.Pitch :
|
||||
(stab_settings[1] == STABILIZATIONDESIRED_STABILIZATIONMODE_VIRTUALBAR) ? cmd.Pitch :
|
||||
(stab_settings[1] == STABILIZATIONDESIRED_STABILIZATIONMODE_ACRO) ? cmd.Pitch * stabSettings.ManualRate.Pitch :
|
||||
(stab_settings[1] == STABILIZATIONDESIRED_STABILIZATIONMODE_RATTITUDE) ? cmd.Pitch * stabSettings.PitchMax :
|
||||
(stab_settings[1] == STABILIZATIONDESIRED_STABILIZATIONMODE_RELAYRATE) ? cmd.Pitch * stabSettings.ManualRate.Pitch :
|
||||
(stab_settings[1] == STABILIZATIONDESIRED_STABILIZATIONMODE_RELAYATTITUDE) ? cmd.Pitch * stabSettings.PitchMax :
|
||||
@ -134,6 +162,7 @@ void stabilizedHandler(bool newinit)
|
||||
(stab_settings[2] == STABILIZATIONDESIRED_STABILIZATIONMODE_ATTITUDE) ? cmd.Yaw * stabSettings.YawMax :
|
||||
(stab_settings[2] == STABILIZATIONDESIRED_STABILIZATIONMODE_AXISLOCK) ? cmd.Yaw * stabSettings.ManualRate.Yaw :
|
||||
(stab_settings[2] == STABILIZATIONDESIRED_STABILIZATIONMODE_VIRTUALBAR) ? cmd.Yaw :
|
||||
(stab_settings[2] == STABILIZATIONDESIRED_STABILIZATIONMODE_ACRO) ? cmd.Yaw * stabSettings.ManualRate.Yaw :
|
||||
(stab_settings[2] == STABILIZATIONDESIRED_STABILIZATIONMODE_RATTITUDE) ? cmd.Yaw * stabSettings.YawMax :
|
||||
(stab_settings[2] == STABILIZATIONDESIRED_STABILIZATIONMODE_RELAYRATE) ? cmd.Yaw * stabSettings.ManualRate.Yaw :
|
||||
(stab_settings[2] == STABILIZATIONDESIRED_STABILIZATIONMODE_RELAYATTITUDE) ? cmd.Yaw * stabSettings.YawMax :
|
||||
|
@ -58,19 +58,36 @@
|
||||
#include <accelgyrosettings.h>
|
||||
#include <flightstatus.h>
|
||||
#include <taskinfo.h>
|
||||
|
||||
#include <pios_math.h>
|
||||
#include <CoordinateConversions.h>
|
||||
|
||||
#include <pios_board_info.h>
|
||||
|
||||
// Private constants
|
||||
#define STACK_SIZE_BYTES 1000
|
||||
#define TASK_PRIORITY (tskIDLE_PRIORITY + 3)
|
||||
#define SENSOR_PERIOD 2
|
||||
#define STACK_SIZE_BYTES 1000
|
||||
#define TASK_PRIORITY (tskIDLE_PRIORITY + 3)
|
||||
|
||||
#define ZERO_ROT_ANGLE 0.00001f
|
||||
static const uint32_t sensor_period_ms = ((uint32_t)1000.0f / PIOS_SENSOR_RATE);
|
||||
|
||||
// Interval in number of sample to recalculate temp bias
|
||||
#define TEMP_CALIB_INTERVAL 30
|
||||
|
||||
// LPF
|
||||
#define TEMP_DT (1.0f / PIOS_SENSOR_RATE)
|
||||
#define TEMP_LPF_FC 5.0f
|
||||
static const float temp_alpha = TEMP_DT / (TEMP_DT + 1.0f / (2.0f * M_PI_F * TEMP_LPF_FC));
|
||||
|
||||
#define ZERO_ROT_ANGLE 0.00001f
|
||||
// Private types
|
||||
#define PIOS_INSTRUMENT_MODULE
|
||||
#include <pios_instrumentation_helper.h>
|
||||
|
||||
PERF_DEFINE_COUNTER(counterGyroSamples);
|
||||
PERF_DEFINE_COUNTER(counterSensorPeriod);
|
||||
|
||||
// Counters:
|
||||
// - 0x53000001 Sensor fetch rate(period)
|
||||
// - 0x53000002 number of gyro samples read for each loop
|
||||
|
||||
// Private functions
|
||||
static void SensorsTask(void *parameters);
|
||||
@ -96,6 +113,13 @@ static float mag_transform[3][3] = {
|
||||
static volatile bool gyro_temp_calibrated = false;
|
||||
static volatile bool accel_temp_calibrated = false;
|
||||
|
||||
static float accel_temperature = NAN;
|
||||
static float gyro_temperature = NAN;
|
||||
static float accel_temp_bias[3] = { 0 };
|
||||
static float gyro_temp_bias[3] = { 0 };
|
||||
static uint8_t temp_calibration_count = 0;
|
||||
|
||||
|
||||
static float R[3][3] = {
|
||||
{ 0 }
|
||||
};
|
||||
@ -219,7 +243,8 @@ static void SensorsTask(__attribute__((unused)) void *parameters)
|
||||
vTaskDelay(10);
|
||||
}
|
||||
}
|
||||
|
||||
PERF_INIT_COUNTER(counterGyroSamples, 0x53000001);
|
||||
PERF_INIT_COUNTER(counterSensorPeriod, 0x53000002);
|
||||
// Main task loop
|
||||
lastSysTime = xTaskGetTickCount();
|
||||
bool error = false;
|
||||
@ -234,7 +259,7 @@ static void SensorsTask(__attribute__((unused)) void *parameters)
|
||||
PIOS_WDG_UpdateFlag(PIOS_WDG_SENSORS);
|
||||
#endif
|
||||
lastSysTime = xTaskGetTickCount();
|
||||
vTaskDelayUntil(&lastSysTime, SENSOR_PERIOD / portTICK_RATE_MS);
|
||||
vTaskDelayUntil(&lastSysTime, sensor_period_ms / portTICK_RATE_MS);
|
||||
AlarmsSet(SYSTEMALARMS_ALARM_SENSORS, SYSTEMALARMS_ALARM_CRITICAL);
|
||||
error = false;
|
||||
} else {
|
||||
@ -263,7 +288,7 @@ static void SensorsTask(__attribute__((unused)) void *parameters)
|
||||
|
||||
count = 0;
|
||||
while ((read_good = PIOS_BMA180_ReadFifo(&accel)) != 0 && !error) {
|
||||
error = ((xTaskGetTickCount() - lastSysTime) > SENSOR_PERIOD) ? true : error;
|
||||
error = ((xTaskGetTickCount() - lastSysTime) > sensor_period_ms) ? true : error;
|
||||
}
|
||||
if (error) {
|
||||
// Unfortunately if the BMA180 ever misses getting read, then it will not
|
||||
@ -332,6 +357,9 @@ static void SensorsTask(__attribute__((unused)) void *parameters)
|
||||
accel_samples++;
|
||||
}
|
||||
|
||||
PERF_MEASURE_PERIOD(counterSensorPeriod);
|
||||
PERF_TRACK_VALUE(counterGyroSamples, gyro_samples);
|
||||
|
||||
if (gyro_samples == 0) {
|
||||
PIOS_MPU6000_ReadGyros(&mpu6000_data);
|
||||
error = true;
|
||||
@ -350,24 +378,43 @@ static void SensorsTask(__attribute__((unused)) void *parameters)
|
||||
PIOS_DEBUG_Assert(0);
|
||||
}
|
||||
|
||||
if (isnan(accel_temperature)) {
|
||||
accel_temperature = accelSensorData.temperature;
|
||||
gyro_temperature = gyroSensorData.temperature;
|
||||
}
|
||||
|
||||
accel_temperature = temp_alpha * (accelSensorData.temperature - accel_temperature) + accel_temperature;
|
||||
gyro_temperature = temp_alpha * (gyroSensorData.temperature - gyro_temperature) + gyro_temperature;
|
||||
|
||||
if ((accel_temp_calibrated || gyro_temp_calibrated) && !temp_calibration_count) {
|
||||
temp_calibration_count = TEMP_CALIB_INTERVAL;
|
||||
if (accel_temp_calibrated) {
|
||||
float ctemp = boundf(accel_temperature, agcal.temp_calibrated_extent.max, agcal.temp_calibrated_extent.min);
|
||||
accel_temp_bias[0] = agcal.accel_temp_coeff.X * ctemp;
|
||||
accel_temp_bias[1] = agcal.accel_temp_coeff.Y * ctemp;
|
||||
accel_temp_bias[2] = agcal.accel_temp_coeff.Z * ctemp;
|
||||
}
|
||||
|
||||
if (gyro_temp_calibrated) {
|
||||
float ctemp = boundf(gyro_temperature, agcal.temp_calibrated_extent.max, agcal.temp_calibrated_extent.min);
|
||||
|
||||
gyro_temp_bias[0] = (agcal.gyro_temp_coeff.X + agcal.gyro_temp_coeff.X2 * ctemp) * ctemp;
|
||||
gyro_temp_bias[1] = (agcal.gyro_temp_coeff.Y + agcal.gyro_temp_coeff.Y2 * ctemp) * ctemp;
|
||||
gyro_temp_bias[2] = (agcal.gyro_temp_coeff.Z + agcal.gyro_temp_coeff.Z2 * ctemp) * ctemp;
|
||||
}
|
||||
}
|
||||
temp_calibration_count--;
|
||||
// Scale the accels
|
||||
float accels[3] = { (float)accel_accum[0] / accel_samples,
|
||||
(float)accel_accum[1] / accel_samples,
|
||||
(float)accel_accum[2] / accel_samples };
|
||||
|
||||
|
||||
float accels_out[3] = { accels[0] * accel_scaling * agcal.accel_scale.X - agcal.accel_bias.X,
|
||||
accels[1] * accel_scaling * agcal.accel_scale.Y - agcal.accel_bias.Y,
|
||||
accels[2] * accel_scaling * agcal.accel_scale.Z - agcal.accel_bias.Z };
|
||||
float accels_out[3] = { accels[0] * accel_scaling * agcal.accel_scale.X - agcal.accel_bias.X - accel_temp_bias[0],
|
||||
accels[1] * accel_scaling * agcal.accel_scale.Y - agcal.accel_bias.Y - accel_temp_bias[1],
|
||||
accels[2] * accel_scaling * agcal.accel_scale.Z - agcal.accel_bias.Z - accel_temp_bias[2] };
|
||||
|
||||
|
||||
if (accel_temp_calibrated) {
|
||||
float ctemp = accelSensorData.temperature > agcal.temp_calibrated_extent.max ? agcal.temp_calibrated_extent.max :
|
||||
(accelSensorData.temperature < agcal.temp_calibrated_extent.min ? agcal.temp_calibrated_extent.min
|
||||
: accelSensorData.temperature);
|
||||
accels_out[0] -= agcal.accel_temp_coeff.X * ctemp;
|
||||
accels_out[1] -= agcal.accel_temp_coeff.Y * ctemp;
|
||||
accels_out[2] -= agcal.accel_temp_coeff.Z * ctemp;
|
||||
}
|
||||
if (rotate) {
|
||||
rot_mult(R, accels_out, accels);
|
||||
accelSensorData.x = accels[0];
|
||||
@ -385,18 +432,10 @@ static void SensorsTask(__attribute__((unused)) void *parameters)
|
||||
(float)gyro_accum[1] / gyro_samples,
|
||||
(float)gyro_accum[2] / gyro_samples };
|
||||
|
||||
float gyros_out[3] = { gyros[0] * gyro_scaling * agcal.gyro_scale.X - agcal.gyro_bias.X,
|
||||
gyros[1] * gyro_scaling * agcal.gyro_scale.Y - agcal.gyro_bias.Y,
|
||||
gyros[2] * gyro_scaling * agcal.gyro_scale.Z - agcal.gyro_bias.Z };
|
||||
float gyros_out[3] = { gyros[0] * gyro_scaling * agcal.gyro_scale.X - agcal.gyro_bias.X - gyro_temp_bias[0],
|
||||
gyros[1] * gyro_scaling * agcal.gyro_scale.Y - agcal.gyro_bias.Y - gyro_temp_bias[1],
|
||||
gyros[2] * gyro_scaling * agcal.gyro_scale.Z - agcal.gyro_bias.Z - gyro_temp_bias[2] };
|
||||
|
||||
if (gyro_temp_calibrated) {
|
||||
float ctemp = gyroSensorData.temperature > agcal.temp_calibrated_extent.max ? agcal.temp_calibrated_extent.max :
|
||||
(gyroSensorData.temperature < agcal.temp_calibrated_extent.min ? agcal.temp_calibrated_extent.min
|
||||
: gyroSensorData.temperature);
|
||||
gyros_out[0] -= (agcal.gyro_temp_coeff.X + agcal.gyro_temp_coeff.X2 * ctemp) * ctemp;
|
||||
gyros_out[1] -= (agcal.gyro_temp_coeff.Y + agcal.gyro_temp_coeff.Y2 * ctemp) * ctemp;
|
||||
gyros_out[2] -= (agcal.gyro_temp_coeff.Z + agcal.gyro_temp_coeff.Z2 * ctemp) * ctemp;
|
||||
}
|
||||
if (rotate) {
|
||||
rot_mult(R, gyros_out, gyros);
|
||||
gyroSensorData.x = gyros[0];
|
||||
@ -437,8 +476,7 @@ static void SensorsTask(__attribute__((unused)) void *parameters)
|
||||
#ifdef PIOS_INCLUDE_WDG
|
||||
PIOS_WDG_UpdateFlag(PIOS_WDG_SENSORS);
|
||||
#endif
|
||||
|
||||
lastSysTime = xTaskGetTickCount();
|
||||
vTaskDelayUntil(&lastSysTime, sensor_period_ms / portTICK_RATE_MS);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -42,7 +42,7 @@
|
||||
|
||||
#ifdef REVOLUTION
|
||||
|
||||
#define UPDATE_EXPECTED (1.0f / 666.0f)
|
||||
#define UPDATE_EXPECTED (1.0f / PIOS_SENSOR_RATE)
|
||||
#define UPDATE_MIN 1.0e-6f
|
||||
#define UPDATE_MAX 1.0f
|
||||
#define UPDATE_ALPHA 1.0e-2f
|
||||
|
@ -33,6 +33,7 @@
|
||||
|
||||
#include <openpilot.h>
|
||||
#include <pid.h>
|
||||
#include <sin_lookup.h>
|
||||
#include <callbackinfo.h>
|
||||
#include <ratedesired.h>
|
||||
#include <actuatordesired.h>
|
||||
@ -54,7 +55,7 @@
|
||||
|
||||
#define CALLBACK_PRIORITY CALLBACK_PRIORITY_CRITICAL
|
||||
|
||||
#define UPDATE_EXPECTED (1.0f / 666.0f)
|
||||
#define UPDATE_EXPECTED (1.0f / PIOS_SENSOR_RATE)
|
||||
#define UPDATE_MIN 1.0e-6f
|
||||
#define UPDATE_MAX 1.0f
|
||||
#define UPDATE_ALPHA 1.0e-2f
|
||||
@ -281,6 +282,23 @@ static void stabilizationInnerloopTask()
|
||||
pid_scaler scaler = create_pid_scaler(t);
|
||||
actuatorDesiredAxis[t] = pid_apply_setpoint(&stabSettings.innerPids[t], &scaler, rate[t], gyro_filtered[t], dT);
|
||||
break;
|
||||
case STABILIZATIONSTATUS_INNERLOOP_ACRO:
|
||||
{
|
||||
float stickinput[3];
|
||||
stickinput[0] = boundf(rate[0] / stabSettings.stabBank.ManualRate.Roll, -1.0f, 1.0f);
|
||||
stickinput[1] = boundf(rate[1] / stabSettings.stabBank.ManualRate.Pitch, -1.0f, 1.0f);
|
||||
stickinput[2] = boundf(rate[2] / stabSettings.stabBank.ManualRate.Yaw, -1.0f, 1.0f);
|
||||
rate[t] = boundf(rate[t],
|
||||
-StabilizationBankMaximumRateToArray(stabSettings.stabBank.MaximumRate)[t],
|
||||
StabilizationBankMaximumRateToArray(stabSettings.stabBank.MaximumRate)[t]
|
||||
);
|
||||
pid_scaler ascaler = create_pid_scaler(t);
|
||||
ascaler.i *= boundf(1.0f - (1.5f * fabsf(stickinput[t])), 0.0f, 1.0f); // this prevents Integral from getting too high while controlled manually
|
||||
float arate = pid_apply_setpoint(&stabSettings.innerPids[t], &ascaler, rate[t], gyro_filtered[t], dT);
|
||||
float factor = fabsf(stickinput[t]) * stabSettings.stabBank.AcroInsanityFactor;
|
||||
actuatorDesiredAxis[t] = factor * stickinput[t] + (1.0f - factor) * arate;
|
||||
}
|
||||
break;
|
||||
case STABILIZATIONSTATUS_INNERLOOP_DIRECT:
|
||||
default:
|
||||
actuatorDesiredAxis[t] = rate[t];
|
||||
@ -311,6 +329,18 @@ static void stabilizationInnerloopTask()
|
||||
previous_mode[t] = 255;
|
||||
}
|
||||
}
|
||||
|
||||
if (stabSettings.stabBank.EnablePiroComp == STABILIZATIONBANK_ENABLEPIROCOMP_TRUE && stabSettings.innerPids[0].iLim > 1e-3f && stabSettings.innerPids[1].iLim > 1e-3f) {
|
||||
// attempted piro compensation - rotate pitch and yaw integrals (experimental)
|
||||
float angleYaw = DEG2RAD(gyro_filtered[2] * dT);
|
||||
float sinYaw = sinf(angleYaw);
|
||||
float cosYaw = cosf(angleYaw);
|
||||
float rollAcc = stabSettings.innerPids[0].iAccumulator / stabSettings.innerPids[0].iLim;
|
||||
float pitchAcc = stabSettings.innerPids[1].iAccumulator / stabSettings.innerPids[1].iLim;
|
||||
stabSettings.innerPids[0].iAccumulator = stabSettings.innerPids[0].iLim * (cosYaw * rollAcc + sinYaw * pitchAcc);
|
||||
stabSettings.innerPids[1].iAccumulator = stabSettings.innerPids[1].iLim * (cosYaw * pitchAcc - sinYaw * rollAcc);
|
||||
}
|
||||
|
||||
{
|
||||
uint8_t armed;
|
||||
FlightStatusArmedGet(&armed);
|
||||
|
@ -52,7 +52,7 @@
|
||||
|
||||
#define CALLBACK_PRIORITY CALLBACK_PRIORITY_REGULAR
|
||||
|
||||
#define UPDATE_EXPECTED (1.0f / 666.0f)
|
||||
#define UPDATE_EXPECTED (1.0f / PIOS_SENSOR_RATE)
|
||||
#define UPDATE_MIN 1.0e-6f
|
||||
#define UPDATE_MAX 1.0f
|
||||
#define UPDATE_ALPHA 1.0e-2f
|
||||
|
@ -158,6 +158,10 @@ static void StabilizationDesiredUpdatedCb(__attribute__((unused)) UAVObjEvent *e
|
||||
StabilizationStatusOuterLoopToArray(status.OuterLoop)[t] = STABILIZATIONSTATUS_OUTERLOOP_DIRECT;
|
||||
StabilizationStatusInnerLoopToArray(status.InnerLoop)[t] = STABILIZATIONSTATUS_INNERLOOP_VIRTUALFLYBAR;
|
||||
break;
|
||||
case STABILIZATIONDESIRED_STABILIZATIONMODE_ACRO:
|
||||
StabilizationStatusOuterLoopToArray(status.OuterLoop)[t] = STABILIZATIONSTATUS_OUTERLOOP_DIRECT;
|
||||
StabilizationStatusInnerLoopToArray(status.InnerLoop)[t] = STABILIZATIONSTATUS_INNERLOOP_ACRO;
|
||||
break;
|
||||
case STABILIZATIONDESIRED_STABILIZATIONMODE_RATTITUDE:
|
||||
StabilizationStatusOuterLoopToArray(status.OuterLoop)[t] = STABILIZATIONSTATUS_OUTERLOOP_RATTITUDE;
|
||||
StabilizationStatusInnerLoopToArray(status.InnerLoop)[t] = STABILIZATIONSTATUS_INNERLOOP_RATE;
|
||||
|
@ -47,7 +47,7 @@
|
||||
#define DT_ALPHA 1e-3f
|
||||
#define DT_MIN 1e-6f
|
||||
#define DT_MAX 1.0f
|
||||
#define DT_INIT (1.0f / 666.0f) // initialize with 666 Hz (default sensor update rate on revo)
|
||||
#define DT_INIT (1.0f / PIOS_SENSOR_RATE) // initialize with board sensor rate
|
||||
|
||||
#define IMPORT_SENSOR_IF_UPDATED(shortname, num) \
|
||||
if (IS_SET(state->updated, SENSORUPDATES_##shortname)) { \
|
||||
|
@ -40,7 +40,7 @@
|
||||
#define DT_ALPHA 1e-3f
|
||||
#define DT_MIN 1e-6f
|
||||
#define DT_MAX 1.0f
|
||||
#define DT_INIT (1.0f / 666.0f) // initialize with 666 Hz (default sensor update rate on revo)
|
||||
#define DT_INIT (1.0f / PIOS_SENSOR_RATE) // initialize with board sensor rate
|
||||
|
||||
// Private types
|
||||
struct data {
|
||||
|
@ -83,6 +83,7 @@
|
||||
static void updatePIDs(UAVObjEvent *ev);
|
||||
static uint8_t update(float *var, float val);
|
||||
static uint8_t updateUint8(uint8_t *var, float val);
|
||||
static uint8_t updateInt8(int8_t *var, float val);
|
||||
static float scale(float val, float inMin, float inMax, float outMin, float outMax);
|
||||
|
||||
/**
|
||||
@ -331,9 +332,25 @@ static void updatePIDs(UAVObjEvent *ev)
|
||||
case TXPIDSETTINGS_PIDS_YAWATTITUDERESP:
|
||||
needsUpdateBank |= updateUint8(&bank.YawMax, value);
|
||||
break;
|
||||
case TXPIDSETTINGS_PIDS_ROLLEXPO:
|
||||
needsUpdateBank |= updateInt8(&bank.StickExpo.Roll, value);
|
||||
break;
|
||||
case TXPIDSETTINGS_PIDS_PITCHEXPO:
|
||||
needsUpdateBank |= updateInt8(&bank.StickExpo.Pitch, value);
|
||||
break;
|
||||
case TXPIDSETTINGS_PIDS_ROLLPITCHEXPO:
|
||||
needsUpdateBank |= updateInt8(&bank.StickExpo.Roll, value);
|
||||
needsUpdateBank |= updateInt8(&bank.StickExpo.Pitch, value);
|
||||
break;
|
||||
case TXPIDSETTINGS_PIDS_YAWEXPO:
|
||||
needsUpdateBank |= updateInt8(&bank.StickExpo.Yaw, value);
|
||||
break;
|
||||
case TXPIDSETTINGS_PIDS_GYROTAU:
|
||||
needsUpdateStab |= update(&stab.GyroTau, value);
|
||||
break;
|
||||
case TXPIDSETTINGS_PIDS_ACROPLUSFACTOR:
|
||||
needsUpdateBank |= update(&bank.AcroInsanityFactor, value);
|
||||
break;
|
||||
default:
|
||||
PIOS_Assert(0);
|
||||
}
|
||||
@ -430,6 +447,21 @@ static uint8_t updateUint8(uint8_t *var, float val)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates var using val if needed.
|
||||
* \returns 1 if updated, 0 otherwise
|
||||
*/
|
||||
static uint8_t updateInt8(int8_t *var, float val)
|
||||
{
|
||||
int8_t roundedVal = (int8_t)roundf(val);
|
||||
|
||||
if (*var != roundedVal) {
|
||||
*var = roundedVal;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
@ -216,7 +216,7 @@ static void readFirmwareInfo()
|
||||
struct fw_version_info *fwinfo = (struct fw_version_info *)(bdinfo->fw_base + bdinfo->fw_size);
|
||||
|
||||
memcpy(&sysPkt.fragments.data.commit_tag_name, &fwinfo->commit_tag_name, sizeof(sysPkt.fragments.data.commit_tag_name));
|
||||
memcpy(&sysPkt.fragments.data.sha1sum, &fwinfo->commit_tag_name, sizeof(sysPkt.fragments.data.sha1sum));
|
||||
memcpy(&sysPkt.fragments.data.sha1sum, &fwinfo->sha1sum, sizeof(sysPkt.fragments.data.sha1sum));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -33,15 +33,13 @@
|
||||
|
||||
#ifdef PIOS_INCLUDE_MPU6000
|
||||
|
||||
#include "fifo_buffer.h"
|
||||
|
||||
#include <pios_constants.h>
|
||||
/* Global Variables */
|
||||
|
||||
enum pios_mpu6000_dev_magic {
|
||||
PIOS_MPU6000_DEV_MAGIC = 0x9da9b3ed,
|
||||
};
|
||||
|
||||
#define PIOS_MPU6000_MAX_DOWNSAMPLE 2
|
||||
struct mpu6000_dev {
|
||||
uint32_t spi_id;
|
||||
uint32_t slave_num;
|
||||
@ -53,29 +51,58 @@ struct mpu6000_dev {
|
||||
enum pios_mpu6000_dev_magic magic;
|
||||
};
|
||||
|
||||
#ifdef PIOS_MPU6000_ACCEL
|
||||
#define PIOS_MPU6000_SAMPLES_BYTES 14
|
||||
#define PIOS_MPU6000_SENSOR_FIRST_REG PIOS_MPU6000_ACCEL_X_OUT_MSB
|
||||
#else
|
||||
#define PIOS_MPU6000_SENSOR_FIRST_REG PIOS_MPU6000_TEMP_OUT_MSB
|
||||
#define PIOS_MPU6000_SAMPLES_BYTES 8
|
||||
#endif
|
||||
|
||||
typedef union {
|
||||
uint8_t buffer[1 + PIOS_MPU6000_SAMPLES_BYTES];
|
||||
struct {
|
||||
uint8_t dummy;
|
||||
#ifdef PIOS_MPU6000_ACCEL
|
||||
uint8_t Accel_X_h;
|
||||
uint8_t Accel_X_l;
|
||||
uint8_t Accel_Y_h;
|
||||
uint8_t Accel_Y_l;
|
||||
uint8_t Accel_Z_h;
|
||||
uint8_t Accel_Z_l;
|
||||
#endif
|
||||
uint8_t Temperature_h;
|
||||
uint8_t Temperature_l;
|
||||
uint8_t Gyro_X_h;
|
||||
uint8_t Gyro_X_l;
|
||||
uint8_t Gyro_Y_h;
|
||||
uint8_t Gyro_Y_l;
|
||||
uint8_t Gyro_Z_h;
|
||||
uint8_t Gyro_Z_l;
|
||||
} data;
|
||||
} mpu6000_data_t;
|
||||
|
||||
#define GET_SENSOR_DATA(mpudataptr, sensor) (mpudataptr.data.sensor##_h << 8 | mpudataptr.data.sensor##_l)
|
||||
|
||||
// ! Global structure for this device device
|
||||
static struct mpu6000_dev *dev;
|
||||
volatile bool mpu6000_configured = false;
|
||||
static mpu6000_data_t mpu6000_data;
|
||||
|
||||
// ! Private functions
|
||||
static struct mpu6000_dev *PIOS_MPU6000_alloc(void);
|
||||
static struct mpu6000_dev *PIOS_MPU6000_alloc(const struct pios_mpu6000_cfg *cfg);
|
||||
static int32_t PIOS_MPU6000_Validate(struct mpu6000_dev *dev);
|
||||
static void PIOS_MPU6000_Config(struct pios_mpu6000_cfg const *cfg);
|
||||
static int32_t PIOS_MPU6000_SetReg(uint8_t address, uint8_t buffer);
|
||||
static int32_t PIOS_MPU6000_GetReg(uint8_t address);
|
||||
|
||||
#define GRAV 9.81f
|
||||
|
||||
#ifdef PIOS_MPU6000_ACCEL
|
||||
#define PIOS_MPU6000_SAMPLES_BYTES 14
|
||||
#else
|
||||
#define PIOS_MPU6000_SAMPLES_BYTES 8
|
||||
#endif
|
||||
|
||||
static void PIOS_MPU6000_SetSpeed(const bool fast);
|
||||
static bool PIOS_MPU6000_HandleData();
|
||||
static bool PIOS_MPU6000_ReadFifo(bool *woken);
|
||||
static bool PIOS_MPU6000_ReadSensor(bool *woken);
|
||||
/**
|
||||
* @brief Allocate a new device
|
||||
*/
|
||||
static struct mpu6000_dev *PIOS_MPU6000_alloc(void)
|
||||
static struct mpu6000_dev *PIOS_MPU6000_alloc(const struct pios_mpu6000_cfg *cfg)
|
||||
{
|
||||
struct mpu6000_dev *mpu6000_dev;
|
||||
|
||||
@ -86,7 +113,7 @@ static struct mpu6000_dev *PIOS_MPU6000_alloc(void)
|
||||
|
||||
mpu6000_dev->magic = PIOS_MPU6000_DEV_MAGIC;
|
||||
|
||||
mpu6000_dev->queue = xQueueCreate(PIOS_MPU6000_MAX_DOWNSAMPLE, sizeof(struct pios_mpu6000_data));
|
||||
mpu6000_dev->queue = xQueueCreate(cfg->max_downsample + 1, sizeof(struct pios_mpu6000_data));
|
||||
if (mpu6000_dev->queue == NULL) {
|
||||
vPortFree(mpu6000_dev);
|
||||
return NULL;
|
||||
@ -119,7 +146,7 @@ static int32_t PIOS_MPU6000_Validate(struct mpu6000_dev *vdev)
|
||||
*/
|
||||
int32_t PIOS_MPU6000_Init(uint32_t spi_id, uint32_t slave_num, const struct pios_mpu6000_cfg *cfg)
|
||||
{
|
||||
dev = PIOS_MPU6000_alloc();
|
||||
dev = PIOS_MPU6000_alloc(cfg);
|
||||
if (dev == NULL) {
|
||||
return -1;
|
||||
}
|
||||
@ -129,9 +156,7 @@ int32_t PIOS_MPU6000_Init(uint32_t spi_id, uint32_t slave_num, const struct pios
|
||||
dev->cfg = cfg;
|
||||
|
||||
/* Configure the MPU6000 Sensor */
|
||||
PIOS_SPI_SetClockSpeed(dev->spi_id, PIOS_SPI_PRESCALER_256);
|
||||
PIOS_MPU6000_Config(cfg);
|
||||
PIOS_SPI_SetClockSpeed(dev->spi_id, PIOS_SPI_PRESCALER_16);
|
||||
|
||||
/* Set up EXTI line */
|
||||
PIOS_EXTI_Init(cfg->exti_cfg);
|
||||
@ -234,11 +259,6 @@ int32_t PIOS_MPU6000_ConfigureRanges(
|
||||
return -1;
|
||||
}
|
||||
|
||||
// TODO: check that changing the SPI clock speed is safe
|
||||
// to do here given that interrupts are enabled and the bus has
|
||||
// not been claimed/is not claimed during this call
|
||||
PIOS_SPI_SetClockSpeed(dev->spi_id, PIOS_SPI_PRESCALER_256);
|
||||
|
||||
// update filter settings
|
||||
while (PIOS_MPU6000_SetReg(PIOS_MPU6000_DLPF_CFG_REG, filterSetting) != 0) {
|
||||
;
|
||||
@ -267,7 +287,6 @@ int32_t PIOS_MPU6000_ConfigureRanges(
|
||||
|
||||
dev->accel_range = accelRange;
|
||||
#endif
|
||||
PIOS_SPI_SetClockSpeed(dev->spi_id, PIOS_SPI_PRESCALER_16);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -275,7 +294,7 @@ int32_t PIOS_MPU6000_ConfigureRanges(
|
||||
* @brief Claim the SPI bus for the accel communications and select this chip
|
||||
* @return 0 if successful, -1 for invalid device, -2 if unable to claim bus
|
||||
*/
|
||||
static int32_t PIOS_MPU6000_ClaimBus()
|
||||
static int32_t PIOS_MPU6000_ClaimBus(bool fast_spi)
|
||||
{
|
||||
if (PIOS_MPU6000_Validate(dev) != 0) {
|
||||
return -1;
|
||||
@ -283,17 +302,28 @@ static int32_t PIOS_MPU6000_ClaimBus()
|
||||
if (PIOS_SPI_ClaimBus(dev->spi_id) != 0) {
|
||||
return -2;
|
||||
}
|
||||
PIOS_MPU6000_SetSpeed(fast_spi);
|
||||
PIOS_SPI_RC_PinSet(dev->spi_id, dev->slave_num, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void PIOS_MPU6000_SetSpeed(const bool fast)
|
||||
{
|
||||
if (fast) {
|
||||
PIOS_SPI_SetClockSpeed(dev->spi_id, dev->cfg->fast_prescaler);
|
||||
} else {
|
||||
PIOS_SPI_SetClockSpeed(dev->spi_id, dev->cfg->std_prescaler);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Claim the SPI bus for the accel communications and select this chip
|
||||
* @return 0 if successful, -1 for invalid device, -2 if unable to claim bus
|
||||
* @param woken[in,out] If non-NULL, will be set to true if woken was false and a higher priority
|
||||
* task has is now eligible to run, else unchanged
|
||||
*/
|
||||
static int32_t PIOS_MPU6000_ClaimBusISR(bool *woken)
|
||||
static int32_t PIOS_MPU6000_ClaimBusISR(bool *woken, bool fast_spi)
|
||||
{
|
||||
if (PIOS_MPU6000_Validate(dev) != 0) {
|
||||
return -1;
|
||||
@ -301,6 +331,7 @@ static int32_t PIOS_MPU6000_ClaimBusISR(bool *woken)
|
||||
if (PIOS_SPI_ClaimBusISR(dev->spi_id, woken) != 0) {
|
||||
return -2;
|
||||
}
|
||||
PIOS_MPU6000_SetSpeed(fast_spi);
|
||||
PIOS_SPI_RC_PinSet(dev->spi_id, dev->slave_num, 0);
|
||||
return 0;
|
||||
}
|
||||
@ -342,7 +373,7 @@ static int32_t PIOS_MPU6000_GetReg(uint8_t reg)
|
||||
{
|
||||
uint8_t data;
|
||||
|
||||
if (PIOS_MPU6000_ClaimBus() != 0) {
|
||||
if (PIOS_MPU6000_ClaimBus(false) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -363,7 +394,7 @@ static int32_t PIOS_MPU6000_GetReg(uint8_t reg)
|
||||
*/
|
||||
static int32_t PIOS_MPU6000_SetReg(uint8_t reg, uint8_t data)
|
||||
{
|
||||
if (PIOS_MPU6000_ClaimBus() != 0) {
|
||||
if (PIOS_MPU6000_ClaimBus(false) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -393,7 +424,7 @@ int32_t PIOS_MPU6000_ReadGyros(struct pios_mpu6000_data *data)
|
||||
uint8_t buf[7] = { PIOS_MPU6000_GYRO_X_OUT_MSB | 0x80, 0, 0, 0, 0, 0, 0 };
|
||||
uint8_t rec[7];
|
||||
|
||||
if (PIOS_MPU6000_ClaimBus() != 0) {
|
||||
if (PIOS_MPU6000_ClaimBus(true) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -460,16 +491,16 @@ float PIOS_MPU6000_GetAccelScale()
|
||||
{
|
||||
switch (dev->accel_range) {
|
||||
case PIOS_MPU6000_ACCEL_2G:
|
||||
return GRAV / 16384.0f;
|
||||
return PIOS_CONST_MKS_GRAV_ACCEL_F / 16384.0f;
|
||||
|
||||
case PIOS_MPU6000_ACCEL_4G:
|
||||
return GRAV / 8192.0f;
|
||||
return PIOS_CONST_MKS_GRAV_ACCEL_F / 8192.0f;
|
||||
|
||||
case PIOS_MPU6000_ACCEL_8G:
|
||||
return GRAV / 4096.0f;
|
||||
return PIOS_CONST_MKS_GRAV_ACCEL_F / 4096.0f;
|
||||
|
||||
case PIOS_MPU6000_ACCEL_16G:
|
||||
return GRAV / 2048.0f;
|
||||
return PIOS_CONST_MKS_GRAV_ACCEL_F / 2048.0f;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -504,7 +535,7 @@ static int32_t PIOS_MPU6000_GetInterruptStatusRegISR(bool *woken)
|
||||
/* Interrupt Status register can be read at high SPI clock speed */
|
||||
uint8_t data;
|
||||
|
||||
if (PIOS_MPU6000_ClaimBusISR(woken) != 0) {
|
||||
if (PIOS_MPU6000_ClaimBusISR(woken, false) != 0) {
|
||||
return -1;
|
||||
}
|
||||
PIOS_SPI_TransferByte(dev->spi_id, (0x80 | PIOS_MPU6000_INT_STATUS_REG));
|
||||
@ -525,29 +556,16 @@ static int32_t PIOS_MPU6000_ResetFifoISR(bool *woken)
|
||||
{
|
||||
int32_t result = 0;
|
||||
|
||||
/* Register writes must be at < 1MHz SPI clock.
|
||||
* Speed can only be changed when SPI bus semaphore is held, but
|
||||
* device chip select must not be enabled, so we use the direct
|
||||
* SPI bus claim call here */
|
||||
if (PIOS_SPI_ClaimBusISR(dev->spi_id, woken) != 0) {
|
||||
if (PIOS_MPU6000_ClaimBusISR(woken, false) != 0) {
|
||||
return -1;
|
||||
}
|
||||
/* Reduce SPI clock speed. */
|
||||
PIOS_SPI_SetClockSpeed(dev->spi_id, PIOS_SPI_PRESCALER_256);
|
||||
/* Enable chip select */
|
||||
PIOS_SPI_RC_PinSet(dev->spi_id, dev->slave_num, 0);
|
||||
/* Reset FIFO. */
|
||||
if (PIOS_SPI_TransferByte(dev->spi_id, 0x7f & PIOS_MPU6000_USER_CTRL_REG) != 0) {
|
||||
result = -2;
|
||||
} else if (PIOS_SPI_TransferByte(dev->spi_id, (dev->cfg->User_ctl | PIOS_MPU6000_USERCTL_FIFO_RST)) != 0) {
|
||||
result = -2;
|
||||
}
|
||||
/* Disable chip select. */
|
||||
PIOS_SPI_RC_PinSet(dev->spi_id, dev->slave_num, 1);
|
||||
/* Increase SPI clock speed. */
|
||||
PIOS_SPI_SetClockSpeed(dev->spi_id, PIOS_SPI_PRESCALER_16);
|
||||
/* Release the SPI bus semaphore. */
|
||||
PIOS_SPI_ReleaseBusISR(dev->spi_id, woken);
|
||||
PIOS_MPU6000_ReleaseBusISR(woken);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -562,7 +580,7 @@ static int32_t PIOS_MPU6000_FifoDepthISR(bool *woken)
|
||||
uint8_t mpu6000_send_buf[3] = { PIOS_MPU6000_FIFO_CNT_MSB | 0x80, 0, 0 };
|
||||
uint8_t mpu6000_rec_buf[3];
|
||||
|
||||
if (PIOS_MPU6000_ClaimBusISR(woken) != 0) {
|
||||
if (PIOS_MPU6000_ClaimBusISR(woken, false) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -604,6 +622,97 @@ bool PIOS_MPU6000_IRQHandler(void)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool read_ok = false;
|
||||
if (dev->cfg->User_ctl & PIOS_MPU6000_USERCTL_FIFO_EN) {
|
||||
read_ok = PIOS_MPU6000_ReadFifo(&woken);
|
||||
} else {
|
||||
read_ok = PIOS_MPU6000_ReadSensor(&woken);
|
||||
}
|
||||
if (read_ok) {
|
||||
bool woken2 = PIOS_MPU6000_HandleData();
|
||||
woken |= woken2;
|
||||
}
|
||||
|
||||
mpu6000_irq++;
|
||||
|
||||
mpu6000_time_us = PIOS_DELAY_DiffuS(timeval);
|
||||
|
||||
return woken;
|
||||
}
|
||||
|
||||
static bool PIOS_MPU6000_HandleData()
|
||||
{
|
||||
// Rotate the sensor to OP convention. The datasheet defines X as towards the right
|
||||
// and Y as forward. OP convention transposes this. Also the Z is defined negatively
|
||||
// to our convention
|
||||
|
||||
static struct pios_mpu6000_data data;
|
||||
|
||||
// Currently we only support rotations on top so switch X/Y accordingly
|
||||
switch (dev->cfg->orientation) {
|
||||
case PIOS_MPU6000_TOP_0DEG:
|
||||
#ifdef PIOS_MPU6000_ACCEL
|
||||
data.accel_y = GET_SENSOR_DATA(mpu6000_data, Accel_X); // chip X
|
||||
data.accel_x = GET_SENSOR_DATA(mpu6000_data, Accel_Y); // chip Y
|
||||
#endif
|
||||
data.gyro_y = GET_SENSOR_DATA(mpu6000_data, Gyro_X); // chip X
|
||||
data.gyro_x = GET_SENSOR_DATA(mpu6000_data, Gyro_Y); // chip Y
|
||||
break;
|
||||
case PIOS_MPU6000_TOP_90DEG:
|
||||
// -1 to bring it back to -32768 +32767 range
|
||||
#ifdef PIOS_MPU6000_ACCEL
|
||||
data.accel_y = -1 - (GET_SENSOR_DATA(mpu6000_data, Accel_Y)); // chip Y
|
||||
data.accel_x = GET_SENSOR_DATA(mpu6000_data, Accel_X); // chip X
|
||||
#endif
|
||||
data.gyro_y = -1 - (GET_SENSOR_DATA(mpu6000_data, Gyro_Y)); // chip Y
|
||||
data.gyro_x = GET_SENSOR_DATA(mpu6000_data, Gyro_X); // chip X
|
||||
break;
|
||||
case PIOS_MPU6000_TOP_180DEG:
|
||||
#ifdef PIOS_MPU6000_ACCEL
|
||||
data.accel_y = -1 - (GET_SENSOR_DATA(mpu6000_data, Accel_X)); // chip X
|
||||
data.accel_x = -1 - (GET_SENSOR_DATA(mpu6000_data, Accel_Y)); // chip Y
|
||||
#endif
|
||||
data.gyro_y = -1 - (GET_SENSOR_DATA(mpu6000_data, Gyro_X)); // chip X
|
||||
data.gyro_x = -1 - (GET_SENSOR_DATA(mpu6000_data, Gyro_Y)); // chip Y
|
||||
break;
|
||||
case PIOS_MPU6000_TOP_270DEG:
|
||||
#ifdef PIOS_MPU6000_ACCEL
|
||||
data.accel_y = GET_SENSOR_DATA(mpu6000_data, Accel_Y); // chip Y
|
||||
data.accel_x = -1 - (GET_SENSOR_DATA(mpu6000_data, Accel_X)); // chip X
|
||||
#endif
|
||||
data.gyro_y = GET_SENSOR_DATA(mpu6000_data, Gyro_Y); // chip Y
|
||||
data.gyro_x = -1 - (GET_SENSOR_DATA(mpu6000_data, Gyro_X)); // chip X
|
||||
break;
|
||||
}
|
||||
#ifdef PIOS_MPU6000_ACCEL
|
||||
data.accel_z = -1 - (GET_SENSOR_DATA(mpu6000_data, Accel_Z));
|
||||
#endif
|
||||
data.gyro_z = -1 - (GET_SENSOR_DATA(mpu6000_data, Gyro_Z));
|
||||
data.temperature = GET_SENSOR_DATA(mpu6000_data, Temperature);
|
||||
|
||||
BaseType_t higherPriorityTaskWoken;
|
||||
xQueueSendToBackFromISR(dev->queue, (void *)&data, &higherPriorityTaskWoken);
|
||||
return higherPriorityTaskWoken == pdTRUE;
|
||||
}
|
||||
|
||||
static bool PIOS_MPU6000_ReadSensor(bool *woken)
|
||||
{
|
||||
const uint8_t mpu6000_send_buf[1 + PIOS_MPU6000_SAMPLES_BYTES] = { PIOS_MPU6000_SENSOR_FIRST_REG | 0x80 };
|
||||
|
||||
if (PIOS_MPU6000_ClaimBusISR(woken, true) != 0) {
|
||||
return false;
|
||||
}
|
||||
if (PIOS_SPI_TransferBlock(dev->spi_id, &mpu6000_send_buf[0], &mpu6000_data.buffer[0], sizeof(mpu6000_data_t), NULL) < 0) {
|
||||
PIOS_MPU6000_ReleaseBusISR(woken);
|
||||
mpu6000_fails++;
|
||||
return false;
|
||||
}
|
||||
PIOS_MPU6000_ReleaseBusISR(woken);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool PIOS_MPU6000_ReadFifo(bool *woken)
|
||||
{
|
||||
/* Temporary fix for OP-1049. Expected to be superceded for next major release
|
||||
* by code changes for OP-1039.
|
||||
* Read interrupt status register to check for FIFO overflow. Must be the
|
||||
@ -611,128 +720,57 @@ bool PIOS_MPU6000_IRQHandler(void)
|
||||
* any read clears in the status register (PIOS_MPU6000_INT_CLR_ANYRD set in
|
||||
* interrupt config register) */
|
||||
int32_t result;
|
||||
if ((result = PIOS_MPU6000_GetInterruptStatusRegISR(&woken)) < 0) {
|
||||
return woken;
|
||||
|
||||
if ((result = PIOS_MPU6000_GetInterruptStatusRegISR(woken)) < 0) {
|
||||
return false;
|
||||
}
|
||||
if (result & PIOS_MPU6000_INT_STATUS_FIFO_OVERFLOW) {
|
||||
/* The FIFO has overflowed, so reset it,
|
||||
* to enable sample sync to be recovered.
|
||||
* If the reset fails, we are in trouble, but
|
||||
* we keep trying on subsequent interrupts. */
|
||||
PIOS_MPU6000_ResetFifoISR(&woken);
|
||||
PIOS_MPU6000_ResetFifoISR(woken);
|
||||
/* Return and wait for the next new sample. */
|
||||
return woken;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Usual case - FIFO has not overflowed. */
|
||||
mpu6000_count = PIOS_MPU6000_FifoDepthISR(&woken);
|
||||
mpu6000_count = PIOS_MPU6000_FifoDepthISR(woken);
|
||||
if (mpu6000_count < PIOS_MPU6000_SAMPLES_BYTES) {
|
||||
return woken;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (PIOS_MPU6000_ClaimBusISR(&woken) != 0) {
|
||||
return woken;
|
||||
if (PIOS_MPU6000_ClaimBusISR(woken, true) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
static uint8_t mpu6000_send_buf[1 + PIOS_MPU6000_SAMPLES_BYTES] = { PIOS_MPU6000_FIFO_REG | 0x80 };
|
||||
static uint8_t mpu6000_rec_buf[1 + PIOS_MPU6000_SAMPLES_BYTES];
|
||||
const uint8_t mpu6000_send_buf[1 + PIOS_MPU6000_SAMPLES_BYTES] = { PIOS_MPU6000_FIFO_REG | 0x80 };
|
||||
|
||||
if (PIOS_SPI_TransferBlock(dev->spi_id, &mpu6000_send_buf[0], &mpu6000_rec_buf[0], sizeof(mpu6000_send_buf), NULL) < 0) {
|
||||
PIOS_MPU6000_ReleaseBusISR(&woken);
|
||||
if (PIOS_SPI_TransferBlock(dev->spi_id, &mpu6000_send_buf[0], &mpu6000_data.buffer[0], sizeof(mpu6000_data_t), NULL) < 0) {
|
||||
PIOS_MPU6000_ReleaseBusISR(woken);
|
||||
mpu6000_fails++;
|
||||
return woken;
|
||||
return false;
|
||||
}
|
||||
|
||||
PIOS_MPU6000_ReleaseBusISR(&woken);
|
||||
|
||||
static struct pios_mpu6000_data data;
|
||||
PIOS_MPU6000_ReleaseBusISR(woken);
|
||||
|
||||
// In the case where extras samples backed up grabbed an extra
|
||||
if (mpu6000_count >= PIOS_MPU6000_SAMPLES_BYTES * 2) {
|
||||
mpu6000_fifo_backup++;
|
||||
if (PIOS_MPU6000_ClaimBusISR(&woken) != 0) {
|
||||
return woken;
|
||||
if (PIOS_MPU6000_ClaimBusISR(woken, true) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (PIOS_SPI_TransferBlock(dev->spi_id, &mpu6000_send_buf[0], &mpu6000_rec_buf[0], sizeof(mpu6000_send_buf), NULL) < 0) {
|
||||
PIOS_MPU6000_ReleaseBusISR(&woken);
|
||||
if (PIOS_SPI_TransferBlock(dev->spi_id, &mpu6000_send_buf[0], &mpu6000_data.buffer[0], sizeof(mpu6000_data_t), NULL) < 0) {
|
||||
PIOS_MPU6000_ReleaseBusISR(woken);
|
||||
mpu6000_fails++;
|
||||
return woken;
|
||||
return false;
|
||||
}
|
||||
|
||||
PIOS_MPU6000_ReleaseBusISR(&woken);
|
||||
PIOS_MPU6000_ReleaseBusISR(woken);
|
||||
}
|
||||
|
||||
// Rotate the sensor to OP convention. The datasheet defines X as towards the right
|
||||
// and Y as forward. OP convention transposes this. Also the Z is defined negatively
|
||||
// to our convention
|
||||
#if defined(PIOS_MPU6000_ACCEL)
|
||||
// Currently we only support rotations on top so switch X/Y accordingly
|
||||
switch (dev->cfg->orientation) {
|
||||
case PIOS_MPU6000_TOP_0DEG:
|
||||
data.accel_y = mpu6000_rec_buf[1] << 8 | mpu6000_rec_buf[2]; // chip X
|
||||
data.accel_x = mpu6000_rec_buf[3] << 8 | mpu6000_rec_buf[4]; // chip Y
|
||||
data.gyro_y = mpu6000_rec_buf[9] << 8 | mpu6000_rec_buf[10]; // chip X
|
||||
data.gyro_x = mpu6000_rec_buf[11] << 8 | mpu6000_rec_buf[12]; // chip Y
|
||||
break;
|
||||
case PIOS_MPU6000_TOP_90DEG:
|
||||
// -1 to bring it back to -32768 +32767 range
|
||||
data.accel_y = -1 - (mpu6000_rec_buf[3] << 8 | mpu6000_rec_buf[4]); // chip Y
|
||||
data.accel_x = mpu6000_rec_buf[1] << 8 | mpu6000_rec_buf[2]; // chip X
|
||||
data.gyro_y = -1 - (mpu6000_rec_buf[11] << 8 | mpu6000_rec_buf[12]); // chip Y
|
||||
data.gyro_x = mpu6000_rec_buf[9] << 8 | mpu6000_rec_buf[10]; // chip X
|
||||
break;
|
||||
case PIOS_MPU6000_TOP_180DEG:
|
||||
data.accel_y = -1 - (mpu6000_rec_buf[1] << 8 | mpu6000_rec_buf[2]); // chip X
|
||||
data.accel_x = -1 - (mpu6000_rec_buf[3] << 8 | mpu6000_rec_buf[4]); // chip Y
|
||||
data.gyro_y = -1 - (mpu6000_rec_buf[9] << 8 | mpu6000_rec_buf[10]); // chip X
|
||||
data.gyro_x = -1 - (mpu6000_rec_buf[11] << 8 | mpu6000_rec_buf[12]); // chip Y
|
||||
break;
|
||||
case PIOS_MPU6000_TOP_270DEG:
|
||||
data.accel_y = mpu6000_rec_buf[3] << 8 | mpu6000_rec_buf[4]; // chip Y
|
||||
data.accel_x = -1 - (mpu6000_rec_buf[1] << 8 | mpu6000_rec_buf[2]); // chip X
|
||||
data.gyro_y = mpu6000_rec_buf[11] << 8 | mpu6000_rec_buf[12]; // chip Y
|
||||
data.gyro_x = -1 - (mpu6000_rec_buf[9] << 8 | mpu6000_rec_buf[10]); // chip X
|
||||
break;
|
||||
}
|
||||
data.gyro_z = -1 - (mpu6000_rec_buf[13] << 8 | mpu6000_rec_buf[14]);
|
||||
data.accel_z = -1 - (mpu6000_rec_buf[5] << 8 | mpu6000_rec_buf[6]);
|
||||
data.temperature = mpu6000_rec_buf[7] << 8 | mpu6000_rec_buf[8];
|
||||
#else /* if defined(PIOS_MPU6000_ACCEL) */
|
||||
data.gyro_x = mpu6000_rec_buf[3] << 8 | mpu6000_rec_buf[4];
|
||||
data.gyro_y = mpu6000_rec_buf[5] << 8 | mpu6000_rec_buf[6];
|
||||
switch (dev->cfg->orientation) {
|
||||
case PIOS_MPU6000_TOP_0DEG:
|
||||
data.gyro_y = mpu6000_rec_buf[3] << 8 | mpu6000_rec_buf[4];
|
||||
data.gyro_x = mpu6000_rec_buf[5] << 8 | mpu6000_rec_buf[6];
|
||||
break;
|
||||
case PIOS_MPU6000_TOP_90DEG:
|
||||
data.gyro_y = -1 - (mpu6000_rec_buf[5] << 8 | mpu6000_rec_buf[6]); // chip Y
|
||||
data.gyro_x = mpu6000_rec_buf[3] << 8 | mpu6000_rec_buf[4]; // chip X
|
||||
break;
|
||||
case PIOS_MPU6000_TOP_180DEG:
|
||||
data.gyro_y = -1 - (mpu6000_rec_buf[3] << 8 | mpu6000_rec_buf[4]);
|
||||
data.gyro_x = -1 - (mpu6000_rec_buf[5] << 8 | mpu6000_rec_buf[6]);
|
||||
break;
|
||||
case PIOS_MPU6000_TOP_270DEG:
|
||||
data.gyro_y = mpu6000_rec_buf[5] << 8 | mpu6000_rec_buf[6]; // chip Y
|
||||
data.gyro_x = -1 - (mpu6000_rec_buf[3] << 8 | mpu6000_rec_buf[4]); // chip X
|
||||
break;
|
||||
}
|
||||
data.gyro_z = -1 - (mpu6000_rec_buf[7] << 8 | mpu6000_rec_buf[8]);
|
||||
data.temperature = mpu6000_rec_buf[1] << 8 | mpu6000_rec_buf[2];
|
||||
#endif /* if defined(PIOS_MPU6000_ACCEL) */
|
||||
|
||||
signed portBASE_TYPE higherPriorityTaskWoken;
|
||||
xQueueSendToBackFromISR(dev->queue, (void *)&data, &higherPriorityTaskWoken);
|
||||
|
||||
mpu6000_irq++;
|
||||
|
||||
mpu6000_time_us = PIOS_DELAY_DiffuS(timeval);
|
||||
|
||||
return woken || higherPriorityTaskWoken == pdTRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif /* PIOS_INCLUDE_MPU6000 */
|
||||
|
||||
/**
|
||||
|
@ -116,8 +116,6 @@
|
||||
#define USB_LED_OFF
|
||||
#endif
|
||||
|
||||
#define CONNECTED_LIVE 8
|
||||
|
||||
/* Local type definitions */
|
||||
|
||||
struct pios_rfm22b_transition {
|
||||
@ -360,7 +358,7 @@ static const uint8_t reg_72[] = { 0x30, 0x48, 0x48, 0x48, 0x48, 0x60, 0x90, 0xCD
|
||||
|
||||
static const uint8_t packet_time[] = { 80, 40, 25, 15, 13, 10, 8, 6, 5 };
|
||||
static const uint8_t packet_time_ppm[] = { 26, 25, 25, 15, 13, 10, 8, 6, 5 };
|
||||
static const uint8_t num_channels[] = { 32, 32, 32, 32, 32, 32, 32, 32, 32 };
|
||||
static const uint8_t num_channels[] = { 4, 4, 4, 6, 8, 8, 10, 12, 16 };
|
||||
|
||||
static struct pios_rfm22b_dev *g_rfm22b_dev = NULL;
|
||||
|
||||
@ -608,8 +606,6 @@ void PIOS_RFM22B_SetChannelConfig(uint32_t rfm22b_id, enum rfm22b_datarate datar
|
||||
}
|
||||
}
|
||||
|
||||
rfm22b_dev->num_channels = num_found;
|
||||
|
||||
// Calculate the maximum packet length from the datarate.
|
||||
float bytes_per_period = (float)data_rate[datarate] * (float)(rfm22b_dev->packet_time - 2) / 9000;
|
||||
|
||||
@ -1359,7 +1355,7 @@ static enum pios_radio_event rfm22_init(struct pios_rfm22b_dev *rfm22b_dev)
|
||||
rfm22b_dev->packet_start_ticks = 0;
|
||||
rfm22b_dev->tx_complete_ticks = 0;
|
||||
rfm22b_dev->rfm22b_state = RFM22B_STATE_INITIALIZING;
|
||||
rfm22b_dev->connected_timeout = 0;
|
||||
rfm22b_dev->on_sync_channel = false;
|
||||
|
||||
// software reset the RF chip .. following procedure according to Si4x3x Errata (rev. B)
|
||||
rfm22_write_claim(rfm22b_dev, RFM22_op_and_func_ctrl1, RFM22_opfc1_swres);
|
||||
@ -1803,8 +1799,8 @@ static enum pios_radio_event radio_txStart(struct pios_rfm22b_dev *radio_dev)
|
||||
len += (radio_dev->tx_out_cb)(radio_dev->tx_out_context, p + len, max_data_len - len, NULL, &need_yield);
|
||||
}
|
||||
|
||||
// Always send a packet if this modem is a coordinator.
|
||||
if ((len == 0) && !rfm22_isCoordinator(radio_dev)) {
|
||||
// Always send a packet on the sync channel if this modem is a coordinator.
|
||||
if ((len == 0) && ((radio_dev->channel_index != 0) || !rfm22_isCoordinator(radio_dev))) {
|
||||
return RADIO_EVENT_RX_MODE;
|
||||
}
|
||||
|
||||
@ -1964,16 +1960,12 @@ static enum pios_radio_event radio_receivePacket(struct pios_rfm22b_dev *radio_d
|
||||
(radio_dev->rx_in_cb)(radio_dev->rx_in_context, p, data_len, NULL, &rx_need_yield);
|
||||
}
|
||||
|
||||
/*
|
||||
* If the packet is valid and destined for us we synchronize the clock.
|
||||
*/
|
||||
if (!rfm22_isCoordinator(radio_dev) &&
|
||||
radio_dev->rx_destination_id == rfm22_destinationID(radio_dev)) {
|
||||
// We only synchronize the clock on packets from our coordinator on the sync channel.
|
||||
if (!rfm22_isCoordinator(radio_dev) && (radio_dev->rx_destination_id == rfm22_destinationID(radio_dev)) && (radio_dev->channel_index == 0)) {
|
||||
rfm22_synchronizeClock(radio_dev);
|
||||
radio_dev->stats.link_state = OPLINKSTATUS_LINKSTATE_CONNECTED;
|
||||
radio_dev->on_sync_channel = false;
|
||||
}
|
||||
|
||||
radio_dev->connected_timeout = CONNECTED_LIVE;
|
||||
} else {
|
||||
ret_event = RADIO_EVENT_RX_COMPLETE;
|
||||
}
|
||||
@ -2169,14 +2161,14 @@ static void rfm22_synchronizeClock(struct pios_rfm22b_dev *rfm22b_dev)
|
||||
portTickType start_time = rfm22b_dev->packet_start_ticks;
|
||||
|
||||
// This packet was transmitted on channel 0, calculate the time delta that will force us to transmit on channel 0 at the time this packet started.
|
||||
uint16_t frequency_hop_cycle_time = rfm22b_dev->packet_time * rfm22b_dev->num_channels;
|
||||
uint8_t num_chan = num_channels[rfm22b_dev->datarate];
|
||||
uint16_t frequency_hop_cycle_time = rfm22b_dev->packet_time * num_chan;
|
||||
uint16_t time_delta = start_time % frequency_hop_cycle_time;
|
||||
|
||||
// Calculate the adjustment for the preamble
|
||||
uint8_t offset = (uint8_t)ceil(35000.0F / data_rate[rfm22b_dev->datarate]);
|
||||
|
||||
rfm22b_dev->time_delta = frequency_hop_cycle_time - time_delta + offset +
|
||||
rfm22b_dev->packet_time * rfm22b_dev->channel_index;
|
||||
rfm22b_dev->time_delta = frequency_hop_cycle_time - time_delta + offset;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2231,11 +2223,14 @@ static bool rfm22_timeToSend(struct pios_rfm22b_dev *rfm22b_dev)
|
||||
static uint8_t rfm22_calcChannel(struct pios_rfm22b_dev *rfm22b_dev, uint8_t index)
|
||||
{
|
||||
// Make sure we don't index outside of the range.
|
||||
uint8_t idx = index % rfm22b_dev->num_channels;
|
||||
uint8_t num_chan = num_channels[rfm22b_dev->datarate];
|
||||
uint8_t idx = index % num_chan;
|
||||
|
||||
// Are we switching to a new channel?
|
||||
if (idx != rfm22b_dev->channel_index) {
|
||||
if (!rfm22_isCoordinator(rfm22b_dev) && rfm22b_dev->connected_timeout == 0) {
|
||||
// If the on_sync_channel flag is set, it means that we were on the sync channel, but no packet was received, so transition to a non-connected state.
|
||||
if (!rfm22_isCoordinator(rfm22b_dev) && (rfm22b_dev->channel_index == 0) && rfm22b_dev->on_sync_channel) {
|
||||
rfm22b_dev->on_sync_channel = false;
|
||||
|
||||
// Set the link state to disconnected.
|
||||
if (rfm22b_dev->stats.link_state == OPLINKSTATUS_LINKSTATE_CONNECTED) {
|
||||
@ -2246,14 +2241,14 @@ static uint8_t rfm22_calcChannel(struct pios_rfm22b_dev *rfm22b_dev, uint8_t ind
|
||||
}
|
||||
}
|
||||
|
||||
// Stay on first channel.
|
||||
// Stay on the sync channel.
|
||||
idx = 0;
|
||||
} else if (idx == 0) {
|
||||
// If we're switching to the sync channel, set a flag that can be used to detect if a packet was received.
|
||||
rfm22b_dev->on_sync_channel = true;
|
||||
}
|
||||
|
||||
rfm22b_dev->channel_index = idx;
|
||||
if (rfm22b_dev->connected_timeout > 0)
|
||||
rfm22b_dev->connected_timeout--;
|
||||
|
||||
}
|
||||
|
||||
return rfm22b_dev->channels[idx];
|
||||
@ -2269,7 +2264,8 @@ static uint8_t rfm22_calcChannelFromClock(struct pios_rfm22b_dev *rfm22b_dev)
|
||||
portTickType time = rfm22_coordinatorTime(rfm22b_dev, xTaskGetTickCount());
|
||||
// Divide time into 8ms blocks. Coordinator sends in first 2 ms, and remote send in 5th and 6th ms.
|
||||
// Channel changes occur in the last 2 ms.
|
||||
uint8_t n = (time / rfm22b_dev->packet_time) % rfm22b_dev->num_channels;
|
||||
uint8_t num_chan = num_channels[rfm22b_dev->datarate];
|
||||
uint8_t n = (time / rfm22b_dev->packet_time) % num_chan;
|
||||
|
||||
return rfm22_calcChannel(rfm22b_dev, n);
|
||||
}
|
||||
|
@ -159,6 +159,9 @@ struct pios_mpu6000_cfg {
|
||||
enum pios_mpu6000_range gyro_range;
|
||||
enum pios_mpu6000_filter filter;
|
||||
enum pios_mpu6000_orientation orientation;
|
||||
SPIPrescalerTypeDef fast_prescaler;
|
||||
SPIPrescalerTypeDef std_prescaler;
|
||||
uint8_t max_downsample;
|
||||
};
|
||||
|
||||
/* Public Functions */
|
||||
|
@ -780,7 +780,7 @@ struct pios_rfm22b_dev {
|
||||
portTickType packet_start_ticks;
|
||||
portTickType tx_complete_ticks;
|
||||
portTickType time_delta;
|
||||
uint8_t connected_timeout;
|
||||
bool on_sync_channel;
|
||||
};
|
||||
|
||||
|
||||
|
@ -44,6 +44,7 @@ static bool PIOS_SPI_validate(__attribute__((unused)) struct pios_spi_dev *com_d
|
||||
/* Should check device magic here */
|
||||
return true;
|
||||
}
|
||||
#define SPI_MAX_BLOCK_PIO 128
|
||||
|
||||
#if defined(PIOS_INCLUDE_FREERTOS)
|
||||
static struct pios_spi_dev *PIOS_SPI_alloc(void)
|
||||
@ -432,23 +433,7 @@ int32_t PIOS_SPI_TransferByte(uint32_t spi_id, uint8_t b)
|
||||
return rx_byte;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transfers a block of bytes via DMA.
|
||||
* \param[in] spi SPI number (0 or 1)
|
||||
* \param[in] send_buffer pointer to buffer which should be sent.<BR>
|
||||
* If NULL, 0xff (all-one) will be sent.
|
||||
* \param[in] receive_buffer pointer to buffer which should get the received values.<BR>
|
||||
* If NULL, received bytes will be discarded.
|
||||
* \param[in] len number of bytes which should be transfered
|
||||
* \param[in] callback pointer to callback function which will be executed
|
||||
* from DMA channel interrupt once the transfer is finished.
|
||||
* If NULL, no callback function will be used, and PIOS_SPI_TransferBlock() will
|
||||
* block until the transfer is finished.
|
||||
* \return >= 0 if no error during transfer
|
||||
* \return -1 if disabled SPI port selected
|
||||
* \return -3 if function has been called during an ongoing DMA transfer
|
||||
*/
|
||||
int32_t PIOS_SPI_TransferBlock(uint32_t spi_id, const uint8_t *send_buffer, uint8_t *receive_buffer, uint16_t len, void *callback)
|
||||
static int32_t SPI_DMA_TransferBlock(uint32_t spi_id, const uint8_t *send_buffer, uint8_t *receive_buffer, uint16_t len, void *callback)
|
||||
{
|
||||
struct pios_spi_dev *spi_dev = (struct pios_spi_dev *)spi_id;
|
||||
|
||||
@ -580,6 +565,95 @@ int32_t PIOS_SPI_TransferBlock(uint32_t spi_id, const uint8_t *send_buffer, uint
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transfers a block of bytes via PIO.
|
||||
*
|
||||
* \param[in] spi_id SPI device handle
|
||||
* \param[in] send_buffer pointer to buffer which should be sent.<BR>
|
||||
* If NULL, 0xff (all-one) will be sent.
|
||||
* \param[in] receive_buffer pointer to buffer which should get the received values.<BR>
|
||||
* If NULL, received bytes will be discarded.
|
||||
* \param[in] len number of bytes which should be transfered
|
||||
* \return >= 0 if no error during transfer
|
||||
* \return -1 if disabled SPI port selected
|
||||
* \return -3 if function has been called during an ongoing DMA transfer
|
||||
*/
|
||||
static int32_t SPI_PIO_TransferBlock(uint32_t spi_id, const uint8_t *send_buffer, uint8_t *receive_buffer, uint16_t len)
|
||||
{
|
||||
struct pios_spi_dev *spi_dev = (struct pios_spi_dev *)spi_id;
|
||||
uint8_t b;
|
||||
|
||||
bool valid = PIOS_SPI_validate(spi_dev);
|
||||
|
||||
PIOS_Assert(valid)
|
||||
|
||||
/* Exit if ongoing transfer */
|
||||
if (DMA_GetCurrDataCounter(spi_dev->cfg->dma.rx.channel)) {
|
||||
return -3;
|
||||
}
|
||||
|
||||
/* Make sure the RXNE flag is cleared by reading the DR register */
|
||||
b = spi_dev->cfg->regs->DR;
|
||||
|
||||
while (len--) {
|
||||
/* get the byte to send */
|
||||
b = send_buffer ? *(send_buffer++) : 0xff;
|
||||
|
||||
/* Start the transfer */
|
||||
spi_dev->cfg->regs->DR = b;
|
||||
|
||||
/* Wait until there is a byte to read */
|
||||
while (!(spi_dev->cfg->regs->SR & SPI_I2S_FLAG_RXNE)) {
|
||||
;
|
||||
}
|
||||
|
||||
/* Read the rx'd byte */
|
||||
b = spi_dev->cfg->regs->DR;
|
||||
|
||||
/* save the received byte */
|
||||
if (receive_buffer) {
|
||||
*(receive_buffer++) = b;
|
||||
}
|
||||
|
||||
/* Wait until the TXE goes high */
|
||||
while (!(spi_dev->cfg->regs->SR & SPI_I2S_FLAG_TXE)) {
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
/* Wait for SPI transfer to have fully completed */
|
||||
while (spi_dev->cfg->regs->SR & SPI_I2S_FLAG_BSY) {
|
||||
;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Transfers a block of bytes via PIO or DMA.
|
||||
* \param[in] spi_id SPI device handle
|
||||
* \param[in] send_buffer pointer to buffer which should be sent.<BR>
|
||||
* If NULL, 0xff (all-one) will be sent.
|
||||
* \param[in] receive_buffer pointer to buffer which should get the received values.<BR>
|
||||
* If NULL, received bytes will be discarded.
|
||||
* \param[in] len number of bytes which should be transfered
|
||||
* \param[in] callback pointer to callback function which will be executed
|
||||
* from DMA channel interrupt once the transfer is finished.
|
||||
* If NULL, no callback function will be used, and PIOS_SPI_TransferBlock() will
|
||||
* block until the transfer is finished.
|
||||
* \return >= 0 if no error during transfer
|
||||
* \return -1 if disabled SPI port selected
|
||||
* \return -3 if function has been called during an ongoing DMA transfer
|
||||
*/
|
||||
int32_t PIOS_SPI_TransferBlock(uint32_t spi_id, const uint8_t *send_buffer, uint8_t *receive_buffer, uint16_t len, void *callback)
|
||||
{
|
||||
if (callback || len > SPI_MAX_BLOCK_PIO) {
|
||||
return SPI_DMA_TransferBlock(spi_id, send_buffer, receive_buffer, len, callback);
|
||||
}
|
||||
return SPI_PIO_TransferBlock(spi_id, send_buffer, receive_buffer, len);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a transfer is in progress
|
||||
* \param[in] spi SPI number (0 or 1)
|
||||
|
@ -418,7 +418,9 @@ static uint8_t PIOS_USBHOOK_CLASS_DataOut(void *pdev, uint8_t epnum)
|
||||
|
||||
if ((epnum_idx < NELEMENTS(usb_epout_table)) && usb_epout_table[epnum_idx].cb) {
|
||||
struct usb_ep_entry *ep = &(usb_epout_table[epnum_idx]);
|
||||
if (!ep->cb(ep->context, epnum_idx, ep->max_len)) {
|
||||
uint16_t len = USBD_GetRxCount(pdev, epnum);
|
||||
PIOS_Assert(ep->max_len >= len);
|
||||
if (!ep->cb(ep->context, epnum_idx, len)) {
|
||||
/* NOTE: use real endpoint number including direction bit */
|
||||
DCD_SetEPStatus(pdev, epnum, USB_OTG_EP_RX_NAK);
|
||||
}
|
||||
|
@ -260,7 +260,7 @@ static const struct pios_spi_cfg pios_spi_flash_accel_cfg_cc3d = {
|
||||
.gpio = GPIOB,
|
||||
.init = {
|
||||
.GPIO_Pin = GPIO_Pin_13,
|
||||
.GPIO_Speed = GPIO_Speed_10MHz,
|
||||
.GPIO_Speed = GPIO_Speed_50MHz,
|
||||
.GPIO_Mode = GPIO_Mode_AF_PP,
|
||||
},
|
||||
},
|
||||
@ -268,7 +268,7 @@ static const struct pios_spi_cfg pios_spi_flash_accel_cfg_cc3d = {
|
||||
.gpio = GPIOB,
|
||||
.init = {
|
||||
.GPIO_Pin = GPIO_Pin_14,
|
||||
.GPIO_Speed = GPIO_Speed_10MHz,
|
||||
.GPIO_Speed = GPIO_Speed_50MHz,
|
||||
.GPIO_Mode = GPIO_Mode_IN_FLOATING,
|
||||
},
|
||||
},
|
||||
@ -276,7 +276,7 @@ static const struct pios_spi_cfg pios_spi_flash_accel_cfg_cc3d = {
|
||||
.gpio = GPIOB,
|
||||
.init = {
|
||||
.GPIO_Pin = GPIO_Pin_15,
|
||||
.GPIO_Speed = GPIO_Speed_10MHz,
|
||||
.GPIO_Speed = GPIO_Speed_50MHz,
|
||||
.GPIO_Mode = GPIO_Mode_AF_PP,
|
||||
},
|
||||
},
|
||||
@ -360,7 +360,7 @@ static const struct pios_spi_cfg pios_spi_flash_accel_cfg_cc = {
|
||||
.gpio = GPIOB,
|
||||
.init = {
|
||||
.GPIO_Pin = GPIO_Pin_13,
|
||||
.GPIO_Speed = GPIO_Speed_10MHz,
|
||||
.GPIO_Speed = GPIO_Speed_50MHz,
|
||||
.GPIO_Mode = GPIO_Mode_AF_PP,
|
||||
},
|
||||
},
|
||||
@ -368,7 +368,7 @@ static const struct pios_spi_cfg pios_spi_flash_accel_cfg_cc = {
|
||||
.gpio = GPIOB,
|
||||
.init = {
|
||||
.GPIO_Pin = GPIO_Pin_14,
|
||||
.GPIO_Speed = GPIO_Speed_10MHz,
|
||||
.GPIO_Speed = GPIO_Speed_50MHz,
|
||||
.GPIO_Mode = GPIO_Mode_IN_FLOATING,
|
||||
},
|
||||
},
|
||||
@ -376,7 +376,7 @@ static const struct pios_spi_cfg pios_spi_flash_accel_cfg_cc = {
|
||||
.gpio = GPIOB,
|
||||
.init = {
|
||||
.GPIO_Pin = GPIO_Pin_15,
|
||||
.GPIO_Speed = GPIO_Speed_10MHz,
|
||||
.GPIO_Speed = GPIO_Speed_50MHz,
|
||||
.GPIO_Mode = GPIO_Mode_AF_PP,
|
||||
},
|
||||
},
|
||||
|
@ -92,6 +92,8 @@
|
||||
/* #define PIOS_INCLUDE_ETASV3 */
|
||||
/* #define PIOS_INCLUDE_HCSR04 */
|
||||
|
||||
#define PIOS_SENSOR_RATE 500.0f
|
||||
|
||||
/* PIOS receiver drivers */
|
||||
#define PIOS_INCLUDE_PWM
|
||||
#define PIOS_INCLUDE_PPM
|
||||
|
@ -119,18 +119,21 @@ static const struct pios_exti_cfg pios_exti_mpu6000_cfg __exti_config = {
|
||||
static const struct pios_mpu6000_cfg pios_mpu6000_cfg = {
|
||||
.exti_cfg = &pios_exti_mpu6000_cfg,
|
||||
.Fifo_store = PIOS_MPU6000_FIFO_TEMP_OUT | PIOS_MPU6000_FIFO_GYRO_X_OUT | PIOS_MPU6000_FIFO_GYRO_Y_OUT | PIOS_MPU6000_FIFO_GYRO_Z_OUT,
|
||||
// Clock at 8 khz, downsampled by 16 for 500 Hz
|
||||
.Smpl_rate_div_no_dlp = 15,
|
||||
// Clock at 1 khz, downsampled by 2 for 500 Hz
|
||||
.Smpl_rate_div_dlp = 1,
|
||||
.interrupt_cfg = PIOS_MPU6000_INT_CLR_ANYRD,
|
||||
.interrupt_en = PIOS_MPU6000_INTEN_DATA_RDY,
|
||||
.User_ctl = PIOS_MPU6000_USERCTL_FIFO_EN | PIOS_MPU6000_USERCTL_DIS_I2C,
|
||||
.Pwr_mgmt_clk = PIOS_MPU6000_PWRMGMT_PLL_X_CLK,
|
||||
.accel_range = PIOS_MPU6000_ACCEL_8G,
|
||||
.gyro_range = PIOS_MPU6000_SCALE_2000_DEG,
|
||||
// Clock at 8 khz, downsampled by 8 for 1000 Hz
|
||||
.Smpl_rate_div_no_dlp = 7,
|
||||
// Clock at 1 khz, downsampled by 1 for 1000 Hz
|
||||
.Smpl_rate_div_dlp = 0,
|
||||
.interrupt_cfg = PIOS_MPU6000_INT_CLR_ANYRD,
|
||||
.interrupt_en = PIOS_MPU6000_INTEN_DATA_RDY,
|
||||
.User_ctl = PIOS_MPU6000_USERCTL_DIS_I2C,
|
||||
.Pwr_mgmt_clk = PIOS_MPU6000_PWRMGMT_PLL_X_CLK,
|
||||
.accel_range = PIOS_MPU6000_ACCEL_8G,
|
||||
.gyro_range = PIOS_MPU6000_SCALE_2000_DEG,
|
||||
.filter = PIOS_MPU6000_LOWPASS_256_HZ,
|
||||
.orientation = PIOS_MPU6000_TOP_180DEG
|
||||
.orientation = PIOS_MPU6000_TOP_180DEG,
|
||||
.fast_prescaler = PIOS_SPI_PRESCALER_4,
|
||||
.std_prescaler = PIOS_SPI_PRESCALER_64,
|
||||
.max_downsample = 2
|
||||
};
|
||||
#endif /* PIOS_INCLUDE_MPU6000 */
|
||||
|
||||
|
@ -91,6 +91,9 @@
|
||||
// #define PIOS_INCLUDE_MPXV
|
||||
// #define PIOS_INCLUDE_ETASV3
|
||||
/* #define PIOS_INCLUDE_HCSR04 */
|
||||
|
||||
#define PIOS_SENSOR_RATE 500.0f
|
||||
|
||||
#define PIOS_INCLUDE_WS2811
|
||||
|
||||
/* PIOS receiver drivers */
|
||||
|
@ -1092,6 +1092,53 @@ static const struct pios_usart_cfg pios_usart_hkosd_flexi_cfg = {
|
||||
},
|
||||
};
|
||||
|
||||
static const struct pios_usart_cfg pios_usart_rcvrport_cfg = {
|
||||
.regs = USART6,
|
||||
.remap = GPIO_AF_USART6,
|
||||
.init = {
|
||||
.USART_BaudRate = 57600,
|
||||
.USART_WordLength = USART_WordLength_8b,
|
||||
.USART_Parity = USART_Parity_No,
|
||||
.USART_StopBits = USART_StopBits_1,
|
||||
.USART_HardwareFlowControl = USART_HardwareFlowControl_None,
|
||||
.USART_Mode = USART_Mode_Rx | USART_Mode_Tx,
|
||||
},
|
||||
.irq = {
|
||||
.init = {
|
||||
.NVIC_IRQChannel = USART6_IRQn,
|
||||
.NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_MID,
|
||||
.NVIC_IRQChannelSubPriority = 0,
|
||||
.NVIC_IRQChannelCmd = ENABLE,
|
||||
},
|
||||
},
|
||||
|
||||
.tx = {
|
||||
// * 7: PC6 = TIM8 CH1, USART6 TX
|
||||
.gpio = GPIOC,
|
||||
.init = {
|
||||
.GPIO_Pin = GPIO_Pin_6,
|
||||
.GPIO_Speed = GPIO_Speed_2MHz,
|
||||
.GPIO_Mode = GPIO_Mode_AF,
|
||||
.GPIO_OType = GPIO_OType_PP,
|
||||
.GPIO_PuPd = GPIO_PuPd_UP
|
||||
},
|
||||
.pin_source = GPIO_PinSource6,
|
||||
},
|
||||
|
||||
.rx = {
|
||||
// * 8: PC7 = TIM8 CH2, USART6 RX
|
||||
.gpio = GPIOC,
|
||||
.init = {
|
||||
.GPIO_Pin = GPIO_Pin_7,
|
||||
.GPIO_Speed = GPIO_Speed_2MHz,
|
||||
.GPIO_Mode = GPIO_Mode_AF,
|
||||
.GPIO_OType = GPIO_OType_PP,
|
||||
.GPIO_PuPd = GPIO_PuPd_UP
|
||||
},
|
||||
.pin_source = GPIO_PinSource7,
|
||||
}
|
||||
};
|
||||
|
||||
#if defined(PIOS_INCLUDE_COM)
|
||||
|
||||
#include <pios_com_priv.h>
|
||||
|
@ -91,11 +91,12 @@
|
||||
#define PIOS_INCLUDE_MPXV
|
||||
#define PIOS_INCLUDE_ETASV3
|
||||
#define PIOS_INCLUDE_MS4525DO
|
||||
/* #define PIOS_INCLUDE_HCSR04 */
|
||||
|
||||
#define PIOS_SENSOR_RATE 500.0f
|
||||
|
||||
#define PIOS_INCLUDE_WS2811
|
||||
|
||||
/* #define PIOS_INCLUDE_HCSR04 */
|
||||
|
||||
/* PIOS receiver drivers */
|
||||
#define PIOS_INCLUDE_PWM
|
||||
#define PIOS_INCLUDE_PPM
|
||||
|
@ -192,18 +192,21 @@ static const struct pios_exti_cfg pios_exti_mpu6000_cfg __exti_config = {
|
||||
static const struct pios_mpu6000_cfg pios_mpu6000_cfg = {
|
||||
.exti_cfg = &pios_exti_mpu6000_cfg,
|
||||
.Fifo_store = PIOS_MPU6000_FIFO_TEMP_OUT | PIOS_MPU6000_FIFO_GYRO_X_OUT | PIOS_MPU6000_FIFO_GYRO_Y_OUT | PIOS_MPU6000_FIFO_GYRO_Z_OUT,
|
||||
// Clock at 8 khz, downsampled by 12 for 666Hz
|
||||
.Smpl_rate_div_no_dlp = 11,
|
||||
// with dlp on output rate is 500Hz
|
||||
.Smpl_rate_div_dlp = 1,
|
||||
.interrupt_cfg = PIOS_MPU6000_INT_CLR_ANYRD,
|
||||
.interrupt_en = PIOS_MPU6000_INTEN_DATA_RDY,
|
||||
.User_ctl = PIOS_MPU6000_USERCTL_FIFO_EN | PIOS_MPU6000_USERCTL_DIS_I2C,
|
||||
.Pwr_mgmt_clk = PIOS_MPU6000_PWRMGMT_PLL_X_CLK,
|
||||
.accel_range = PIOS_MPU6000_ACCEL_8G,
|
||||
.gyro_range = PIOS_MPU6000_SCALE_2000_DEG,
|
||||
// Clock at 8 khz
|
||||
.Smpl_rate_div_no_dlp = 0,
|
||||
// with dlp on output rate is 1000Hz
|
||||
.Smpl_rate_div_dlp = 0,
|
||||
.interrupt_cfg = PIOS_MPU6000_INT_CLR_ANYRD,
|
||||
.interrupt_en = PIOS_MPU6000_INTEN_DATA_RDY,
|
||||
.User_ctl = PIOS_MPU6000_USERCTL_DIS_I2C,
|
||||
.Pwr_mgmt_clk = PIOS_MPU6000_PWRMGMT_PLL_X_CLK,
|
||||
.accel_range = PIOS_MPU6000_ACCEL_8G,
|
||||
.gyro_range = PIOS_MPU6000_SCALE_2000_DEG,
|
||||
.filter = PIOS_MPU6000_LOWPASS_256_HZ,
|
||||
.orientation = PIOS_MPU6000_TOP_180DEG
|
||||
.orientation = PIOS_MPU6000_TOP_180DEG,
|
||||
.fast_prescaler = PIOS_SPI_PRESCALER_4,
|
||||
.std_prescaler = PIOS_SPI_PRESCALER_64,
|
||||
.max_downsample = 16,
|
||||
};
|
||||
#endif /* PIOS_INCLUDE_MPU6000 */
|
||||
|
||||
@ -880,25 +883,33 @@ void PIOS_Board_Init(void)
|
||||
case HWSETTINGS_RM_RCVRPORT_PPM:
|
||||
case HWSETTINGS_RM_RCVRPORT_PPMOUTPUTS:
|
||||
case HWSETTINGS_RM_RCVRPORT_PPMPWM:
|
||||
case HWSETTINGS_RM_RCVRPORT_PPMTELEMETRY:
|
||||
#if defined(PIOS_INCLUDE_PPM)
|
||||
PIOS_Board_configure_ppm(&pios_ppm_cfg);
|
||||
|
||||
if (hwsettings_rcvrport == HWSETTINGS_RM_RCVRPORT_PPMOUTPUTS) {
|
||||
// configure servo outputs and the remaining 5 inputs as outputs
|
||||
pios_servo_cfg = &pios_servo_cfg_out_in_ppm;
|
||||
}
|
||||
|
||||
PIOS_Board_configure_ppm(&pios_ppm_cfg);
|
||||
|
||||
// enable pwm on the remaining channels
|
||||
if (hwsettings_rcvrport == HWSETTINGS_RM_RCVRPORT_PPMPWM) {
|
||||
PIOS_Board_configure_pwm(&pios_pwm_ppm_cfg);
|
||||
}
|
||||
|
||||
if (hwsettings_rcvrport == HWSETTINGS_RM_RCVRPORT_PPMTELEMETRY) {
|
||||
PIOS_Board_configure_com(&pios_usart_rcvrport_cfg, PIOS_COM_TELEM_RF_RX_BUF_LEN, PIOS_COM_TELEM_RF_TX_BUF_LEN, &pios_usart_com_driver, &pios_com_telem_rf_id);
|
||||
}
|
||||
|
||||
break;
|
||||
#endif /* PIOS_INCLUDE_PPM */
|
||||
case HWSETTINGS_RM_RCVRPORT_OUTPUTS:
|
||||
// configure only the servo outputs
|
||||
pios_servo_cfg = &pios_servo_cfg_out_in;
|
||||
break;
|
||||
case HWSETTINGS_RM_RCVRPORT_TELEMETRY:
|
||||
PIOS_Board_configure_com(&pios_usart_rcvrport_cfg, PIOS_COM_TELEM_RF_RX_BUF_LEN, PIOS_COM_TELEM_RF_TX_BUF_LEN, &pios_usart_com_driver, &pios_com_telem_rf_id);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
|
@ -89,6 +89,8 @@
|
||||
#define PIOS_INCLUDE_ETASV3
|
||||
/* #define PIOS_INCLUDE_HCSR04 */
|
||||
|
||||
#define PIOS_SENSOR_RATE 500.0f
|
||||
|
||||
/* PIOS receiver drivers */
|
||||
#define PIOS_INCLUDE_PWM
|
||||
#define PIOS_INCLUDE_PPM
|
||||
|
@ -222,18 +222,21 @@ static const struct pios_exti_cfg pios_exti_mpu6000_cfg __exti_config = {
|
||||
static const struct pios_mpu6000_cfg pios_mpu6000_cfg = {
|
||||
.exti_cfg = &pios_exti_mpu6000_cfg,
|
||||
.Fifo_store = PIOS_MPU6000_FIFO_TEMP_OUT | PIOS_MPU6000_FIFO_GYRO_X_OUT | PIOS_MPU6000_FIFO_GYRO_Y_OUT | PIOS_MPU6000_FIFO_GYRO_Z_OUT,
|
||||
// Clock at 8 khz, downsampled by 12 for 666Hz
|
||||
.Smpl_rate_div_no_dlp = 11,
|
||||
// with dlp on output rate is 500Hz
|
||||
.Smpl_rate_div_dlp = 1,
|
||||
.interrupt_cfg = PIOS_MPU6000_INT_CLR_ANYRD,
|
||||
.interrupt_en = PIOS_MPU6000_INTEN_DATA_RDY,
|
||||
.User_ctl = PIOS_MPU6000_USERCTL_FIFO_EN | PIOS_MPU6000_USERCTL_DIS_I2C,
|
||||
.Pwr_mgmt_clk = PIOS_MPU6000_PWRMGMT_PLL_X_CLK,
|
||||
.accel_range = PIOS_MPU6000_ACCEL_8G,
|
||||
.gyro_range = PIOS_MPU6000_SCALE_2000_DEG,
|
||||
// Clock at 8 khz
|
||||
.Smpl_rate_div_no_dlp = 0,
|
||||
// with dlp on output rate is 1000Hz
|
||||
.Smpl_rate_div_dlp = 0,
|
||||
.interrupt_cfg = PIOS_MPU6000_INT_CLR_ANYRD,
|
||||
.interrupt_en = PIOS_MPU6000_INTEN_DATA_RDY,
|
||||
.User_ctl = PIOS_MPU6000_USERCTL_DIS_I2C,
|
||||
.Pwr_mgmt_clk = PIOS_MPU6000_PWRMGMT_PLL_X_CLK,
|
||||
.accel_range = PIOS_MPU6000_ACCEL_8G,
|
||||
.gyro_range = PIOS_MPU6000_SCALE_2000_DEG,
|
||||
.filter = PIOS_MPU6000_LOWPASS_256_HZ,
|
||||
.orientation = PIOS_MPU6000_TOP_0DEG
|
||||
.orientation = PIOS_MPU6000_TOP_0DEG,
|
||||
.fast_prescaler = PIOS_SPI_PRESCALER_4,
|
||||
.std_prescaler = PIOS_SPI_PRESCALER_64,
|
||||
.max_downsample = 16,
|
||||
};
|
||||
#endif /* PIOS_INCLUDE_MPU6000 */
|
||||
|
||||
|
@ -70,6 +70,9 @@
|
||||
// #define PIOS_INCLUDE_MS5611
|
||||
// #define PIOS_INCLUDE_HCSR04
|
||||
#define PIOS_FLASH_ON_ACCEL /* true for second revo */
|
||||
|
||||
#define PIOS_SENSOR_RATE 500.0f
|
||||
|
||||
#define FLASH_FREERTOS
|
||||
/* Com systems to include */
|
||||
#define PIOS_INCLUDE_COM
|
||||
|
559
ground/openpilotgcs/src/libs/utils/mustache.cpp
Normal file
559
ground/openpilotgcs/src/libs/utils/mustache.cpp
Normal file
@ -0,0 +1,559 @@
|
||||
/*
|
||||
Copyright 2012, Robert Knight
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
*/
|
||||
|
||||
#include "mustache.h"
|
||||
|
||||
#include <QtCore/QDebug>
|
||||
#include <QtCore/QFile>
|
||||
#include <QtCore/QStringList>
|
||||
#include <QtCore/QTextStream>
|
||||
|
||||
using namespace Mustache;
|
||||
|
||||
QString Mustache::renderTemplate(const QString & templateString, const QVariantHash & args)
|
||||
{
|
||||
Mustache::QtVariantContext context(args);
|
||||
Mustache::Renderer renderer;
|
||||
|
||||
return renderer.render(templateString, &context);
|
||||
}
|
||||
|
||||
QString escapeHtml(const QString & input)
|
||||
{
|
||||
QString escaped(input);
|
||||
|
||||
for (int i = 0; i < escaped.count();) {
|
||||
const char *replacement = 0;
|
||||
ushort ch = escaped.at(i).unicode();
|
||||
if (ch == '&') {
|
||||
replacement = "&";
|
||||
} else if (ch == '<') {
|
||||
replacement = "<";
|
||||
} else if (ch == '>') {
|
||||
replacement = ">";
|
||||
} else if (ch == '"') {
|
||||
replacement = """;
|
||||
}
|
||||
if (replacement) {
|
||||
escaped.replace(i, 1, QLatin1String(replacement));
|
||||
i += strlen(replacement);
|
||||
} else {
|
||||
++i;
|
||||
}
|
||||
}
|
||||
return escaped;
|
||||
}
|
||||
|
||||
QString unescapeHtml(const QString & escaped)
|
||||
{
|
||||
QString unescaped(escaped);
|
||||
|
||||
unescaped.replace(QLatin1String("<"), QLatin1String("<"));
|
||||
unescaped.replace(QLatin1String(">"), QLatin1String(">"));
|
||||
unescaped.replace(QLatin1String("&"), QLatin1String("&"));
|
||||
unescaped.replace(QLatin1String("""), QLatin1String("\""));
|
||||
return unescaped;
|
||||
}
|
||||
|
||||
Context::Context(PartialResolver *resolver)
|
||||
: m_partialResolver(resolver)
|
||||
{}
|
||||
|
||||
PartialResolver *Context::partialResolver() const
|
||||
{
|
||||
return m_partialResolver;
|
||||
}
|
||||
|
||||
QString Context::partialValue(const QString & key) const
|
||||
{
|
||||
if (!m_partialResolver) {
|
||||
return QString();
|
||||
}
|
||||
return m_partialResolver->getPartial(key);
|
||||
}
|
||||
|
||||
bool Context::canEval(const QString &) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
QString Context::eval(const QString & key, const QString & _template, Renderer *renderer)
|
||||
{
|
||||
Q_UNUSED(key);
|
||||
Q_UNUSED(_template);
|
||||
Q_UNUSED(renderer);
|
||||
|
||||
return QString();
|
||||
}
|
||||
|
||||
QtVariantContext::QtVariantContext(const QVariant & root, PartialResolver *resolver)
|
||||
: Context(resolver)
|
||||
{
|
||||
m_contextStack << root;
|
||||
}
|
||||
|
||||
QVariant variantMapValue(const QVariant & value, const QString & key)
|
||||
{
|
||||
if (value.userType() == QVariant::Map) {
|
||||
return value.toMap().value(key);
|
||||
} else {
|
||||
return value.toHash().value(key);
|
||||
}
|
||||
}
|
||||
|
||||
QVariant variantMapValueForKeyPath(const QVariant & value, const QStringList keyPath)
|
||||
{
|
||||
if (keyPath.count() > 1) {
|
||||
QVariant firstValue = variantMapValue(value, keyPath.first());
|
||||
return firstValue.isNull() ? QVariant() : variantMapValueForKeyPath(firstValue, keyPath.mid(1));
|
||||
} else if (!keyPath.isEmpty()) {
|
||||
return variantMapValue(value, keyPath.first());
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QVariant QtVariantContext::value(const QString & key) const
|
||||
{
|
||||
if (key == "." && !m_contextStack.isEmpty()) {
|
||||
return m_contextStack.last();
|
||||
}
|
||||
QStringList keyPath = key.split(".");
|
||||
for (int i = m_contextStack.count() - 1; i >= 0; i--) {
|
||||
QVariant value = variantMapValueForKeyPath(m_contextStack.at(i), keyPath);
|
||||
if (!value.isNull()) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
bool QtVariantContext::isFalse(const QString & key) const
|
||||
{
|
||||
QVariant value = this->value(key);
|
||||
|
||||
switch (value.userType()) {
|
||||
case QVariant::Bool:
|
||||
return !value.toBool();
|
||||
|
||||
case QVariant::List:
|
||||
return value.toList().isEmpty();
|
||||
|
||||
case QVariant::Hash:
|
||||
return value.toHash().isEmpty();
|
||||
|
||||
case QVariant::Map:
|
||||
return value.toMap().isEmpty();
|
||||
|
||||
default:
|
||||
return value.toString().isEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
QString QtVariantContext::stringValue(const QString & key) const
|
||||
{
|
||||
if (isFalse(key)) {
|
||||
return QString();
|
||||
}
|
||||
return value(key).toString();
|
||||
}
|
||||
|
||||
void QtVariantContext::push(const QString & key, int index)
|
||||
{
|
||||
QVariant mapItem = value(key);
|
||||
|
||||
if (index == -1) {
|
||||
m_contextStack << mapItem;
|
||||
} else {
|
||||
QVariantList list = mapItem.toList();
|
||||
m_contextStack << list.value(index, QVariant());
|
||||
}
|
||||
}
|
||||
|
||||
void QtVariantContext::pop()
|
||||
{
|
||||
m_contextStack.pop();
|
||||
}
|
||||
|
||||
int QtVariantContext::listCount(const QString & key) const
|
||||
{
|
||||
if (value(key).userType() == QVariant::List) {
|
||||
return value(key).toList().count();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool QtVariantContext::canEval(const QString & key) const
|
||||
{
|
||||
return value(key).canConvert<fn_t>();
|
||||
}
|
||||
|
||||
QString QtVariantContext::eval(const QString & key, const QString & _template, Renderer *renderer)
|
||||
{
|
||||
QVariant fn = value(key);
|
||||
|
||||
if (fn.isNull()) {
|
||||
return QString();
|
||||
}
|
||||
return fn.value<fn_t>() (_template, renderer, this);
|
||||
}
|
||||
|
||||
PartialMap::PartialMap(const QHash<QString, QString> & partials)
|
||||
: m_partials(partials)
|
||||
{}
|
||||
|
||||
QString PartialMap::getPartial(const QString & name)
|
||||
{
|
||||
return m_partials.value(name);
|
||||
}
|
||||
|
||||
PartialFileLoader::PartialFileLoader(const QString & basePath)
|
||||
: m_basePath(basePath)
|
||||
{}
|
||||
|
||||
QString PartialFileLoader::getPartial(const QString & name)
|
||||
{
|
||||
if (!m_cache.contains(name)) {
|
||||
QString path = m_basePath + '/' + name + ".mustache";
|
||||
QFile file(path);
|
||||
if (file.open(QIODevice::ReadOnly)) {
|
||||
QTextStream stream(&file);
|
||||
m_cache.insert(name, stream.readAll());
|
||||
}
|
||||
}
|
||||
return m_cache.value(name);
|
||||
}
|
||||
|
||||
Renderer::Renderer()
|
||||
: m_errorPos(-1)
|
||||
, m_defaultTagStartMarker("{{")
|
||||
, m_defaultTagEndMarker("}}")
|
||||
{}
|
||||
|
||||
QString Renderer::error() const
|
||||
{
|
||||
return m_error;
|
||||
}
|
||||
|
||||
int Renderer::errorPos() const
|
||||
{
|
||||
return m_errorPos;
|
||||
}
|
||||
|
||||
QString Renderer::errorPartial() const
|
||||
{
|
||||
return m_errorPartial;
|
||||
}
|
||||
|
||||
QString Renderer::render(const QString & _template, Context *context)
|
||||
{
|
||||
m_error.clear();
|
||||
m_errorPos = -1;
|
||||
m_errorPartial.clear();
|
||||
|
||||
m_tagStartMarker = m_defaultTagStartMarker;
|
||||
m_tagEndMarker = m_defaultTagEndMarker;
|
||||
|
||||
return render(_template, 0, _template.length(), context);
|
||||
}
|
||||
|
||||
QString Renderer::render(const QString & _template, int startPos, int endPos, Context *context)
|
||||
{
|
||||
QString output;
|
||||
int lastTagEnd = startPos;
|
||||
|
||||
while (m_errorPos == -1) {
|
||||
Tag tag = findTag(_template, lastTagEnd, endPos);
|
||||
if (tag.type == Tag::Null) {
|
||||
output += _template.midRef(lastTagEnd, endPos - lastTagEnd);
|
||||
break;
|
||||
}
|
||||
output += _template.midRef(lastTagEnd, tag.start - lastTagEnd);
|
||||
switch (tag.type) {
|
||||
case Tag::Value:
|
||||
{
|
||||
QString value = context->stringValue(tag.key);
|
||||
if (tag.escapeMode == Tag::Escape) {
|
||||
value = escapeHtml(value);
|
||||
} else if (tag.escapeMode == Tag::Unescape) {
|
||||
value = unescapeHtml(value);
|
||||
}
|
||||
output += value;
|
||||
lastTagEnd = tag.end;
|
||||
}
|
||||
break;
|
||||
case Tag::SectionStart:
|
||||
{
|
||||
Tag endTag = findEndTag(_template, tag, endPos);
|
||||
if (endTag.type == Tag::Null) {
|
||||
if (m_errorPos == -1) {
|
||||
setError("No matching end tag found for section", tag.start);
|
||||
}
|
||||
} else {
|
||||
int listCount = context->listCount(tag.key);
|
||||
if (listCount > 0) {
|
||||
for (int i = 0; i < listCount; i++) {
|
||||
context->push(tag.key, i);
|
||||
output += render(_template, tag.end, endTag.start, context);
|
||||
context->pop();
|
||||
}
|
||||
} else if (context->canEval(tag.key)) {
|
||||
output += context->eval(tag.key, _template.mid(tag.end, endTag.start - tag.end), this);
|
||||
} else if (!context->isFalse(tag.key)) {
|
||||
context->push(tag.key);
|
||||
output += render(_template, tag.end, endTag.start, context);
|
||||
context->pop();
|
||||
}
|
||||
lastTagEnd = endTag.end;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Tag::InvertedSectionStart:
|
||||
{
|
||||
Tag endTag = findEndTag(_template, tag, endPos);
|
||||
if (endTag.type == Tag::Null) {
|
||||
if (m_errorPos == -1) {
|
||||
setError("No matching end tag found for inverted section", tag.start);
|
||||
}
|
||||
} else {
|
||||
if (context->isFalse(tag.key)) {
|
||||
output += render(_template, tag.end, endTag.start, context);
|
||||
}
|
||||
lastTagEnd = endTag.end;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Tag::SectionEnd:
|
||||
setError("Unexpected end tag", tag.start);
|
||||
lastTagEnd = tag.end;
|
||||
break;
|
||||
case Tag::Partial:
|
||||
{
|
||||
QString tagStartMarker = m_tagStartMarker;
|
||||
QString tagEndMarker = m_tagEndMarker;
|
||||
|
||||
m_tagStartMarker = m_defaultTagStartMarker;
|
||||
m_tagEndMarker = m_defaultTagEndMarker;
|
||||
|
||||
m_partialStack.push(tag.key);
|
||||
|
||||
QString partial = context->partialValue(tag.key);
|
||||
output += render(partial, 0, partial.length(), context);
|
||||
lastTagEnd = tag.end;
|
||||
|
||||
m_partialStack.pop();
|
||||
|
||||
m_tagStartMarker = tagStartMarker;
|
||||
m_tagEndMarker = tagEndMarker;
|
||||
}
|
||||
break;
|
||||
case Tag::SetDelimiter:
|
||||
lastTagEnd = tag.end;
|
||||
break;
|
||||
case Tag::Comment:
|
||||
lastTagEnd = tag.end;
|
||||
break;
|
||||
case Tag::Null:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
void Renderer::setError(const QString & error, int pos)
|
||||
{
|
||||
Q_ASSERT(!error.isEmpty());
|
||||
Q_ASSERT(pos >= 0);
|
||||
|
||||
m_error = error;
|
||||
m_errorPos = pos;
|
||||
|
||||
if (!m_partialStack.isEmpty()) {
|
||||
m_errorPartial = m_partialStack.top();
|
||||
}
|
||||
}
|
||||
|
||||
Tag Renderer::findTag(const QString & content, int pos, int endPos)
|
||||
{
|
||||
int tagStartPos = content.indexOf(m_tagStartMarker, pos);
|
||||
|
||||
if (tagStartPos == -1 || tagStartPos >= endPos) {
|
||||
return Tag();
|
||||
}
|
||||
|
||||
int tagEndPos = content.indexOf(m_tagEndMarker, tagStartPos + m_tagStartMarker.length());
|
||||
if (tagEndPos == -1) {
|
||||
return Tag();
|
||||
}
|
||||
tagEndPos += m_tagEndMarker.length();
|
||||
|
||||
Tag tag;
|
||||
tag.type = Tag::Value;
|
||||
tag.start = tagStartPos;
|
||||
tag.end = tagEndPos;
|
||||
|
||||
pos = tagStartPos + m_tagStartMarker.length();
|
||||
endPos = tagEndPos - m_tagEndMarker.length();
|
||||
|
||||
QChar typeChar = content.at(pos);
|
||||
|
||||
if (typeChar == '#') {
|
||||
tag.type = Tag::SectionStart;
|
||||
tag.key = readTagName(content, pos + 1, endPos);
|
||||
} else if (typeChar == '^') {
|
||||
tag.type = Tag::InvertedSectionStart;
|
||||
tag.key = readTagName(content, pos + 1, endPos);
|
||||
} else if (typeChar == '/') {
|
||||
tag.type = Tag::SectionEnd;
|
||||
tag.key = readTagName(content, pos + 1, endPos);
|
||||
} else if (typeChar == '!') {
|
||||
tag.type = Tag::Comment;
|
||||
} else if (typeChar == '>') {
|
||||
tag.type = Tag::Partial;
|
||||
tag.key = readTagName(content, pos + 1, endPos);
|
||||
} else if (typeChar == '=') {
|
||||
tag.type = Tag::SetDelimiter;
|
||||
readSetDelimiter(content, pos + 1, tagEndPos - m_tagEndMarker.length());
|
||||
} else {
|
||||
if (typeChar == '&') {
|
||||
tag.escapeMode = Tag::Unescape;
|
||||
++pos;
|
||||
} else if (typeChar == '{') {
|
||||
tag.escapeMode = Tag::Raw;
|
||||
++pos;
|
||||
int endTache = content.indexOf('}', pos);
|
||||
if (endTache == tag.end - m_tagEndMarker.length()) {
|
||||
++tag.end;
|
||||
} else {
|
||||
endPos = endTache;
|
||||
}
|
||||
}
|
||||
tag.type = Tag::Value;
|
||||
tag.key = readTagName(content, pos, endPos);
|
||||
}
|
||||
|
||||
if (tag.type != Tag::Value) {
|
||||
expandTag(tag, content);
|
||||
}
|
||||
|
||||
return tag;
|
||||
}
|
||||
|
||||
QString Renderer::readTagName(const QString & content, int pos, int endPos)
|
||||
{
|
||||
QString name;
|
||||
|
||||
name.reserve(endPos - pos);
|
||||
while (content.at(pos).isSpace()) {
|
||||
++pos;
|
||||
}
|
||||
while (!content.at(pos).isSpace() && pos < endPos) {
|
||||
name += content.at(pos);
|
||||
++pos;
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
void Renderer::readSetDelimiter(const QString & content, int pos, int endPos)
|
||||
{
|
||||
QString startMarker;
|
||||
QString endMarker;
|
||||
|
||||
while (content.at(pos).isSpace() && pos < endPos) {
|
||||
++pos;
|
||||
}
|
||||
|
||||
while (!content.at(pos).isSpace() && pos < endPos) {
|
||||
if (content.at(pos) == '=') {
|
||||
setError("Custom delimiters may not contain '='.", pos);
|
||||
return;
|
||||
}
|
||||
startMarker += content.at(pos);
|
||||
++pos;
|
||||
}
|
||||
|
||||
while (content.at(pos).isSpace() && pos < endPos) {
|
||||
++pos;
|
||||
}
|
||||
|
||||
while (!content.at(pos).isSpace() && pos < endPos - 1) {
|
||||
if (content.at(pos) == '=') {
|
||||
setError("Custom delimiters may not contain '='.", pos);
|
||||
return;
|
||||
}
|
||||
endMarker += content.at(pos);
|
||||
++pos;
|
||||
}
|
||||
|
||||
m_tagStartMarker = startMarker;
|
||||
m_tagEndMarker = endMarker;
|
||||
}
|
||||
|
||||
Tag Renderer::findEndTag(const QString & content, const Tag & startTag, int endPos)
|
||||
{
|
||||
int tagDepth = 1;
|
||||
int pos = startTag.end;
|
||||
|
||||
while (true) {
|
||||
Tag nextTag = findTag(content, pos, endPos);
|
||||
if (nextTag.type == Tag::Null) {
|
||||
return nextTag;
|
||||
} else if (nextTag.type == Tag::SectionStart || nextTag.type == Tag::InvertedSectionStart) {
|
||||
++tagDepth;
|
||||
} else if (nextTag.type == Tag::SectionEnd) {
|
||||
--tagDepth;
|
||||
if (tagDepth == 0) {
|
||||
if (nextTag.key != startTag.key) {
|
||||
setError("Tag start/end key mismatch", nextTag.start);
|
||||
return Tag();
|
||||
}
|
||||
return nextTag;
|
||||
}
|
||||
}
|
||||
pos = nextTag.end;
|
||||
}
|
||||
|
||||
return Tag();
|
||||
}
|
||||
|
||||
void Renderer::setTagMarkers(const QString & startMarker, const QString & endMarker)
|
||||
{
|
||||
m_defaultTagStartMarker = startMarker;
|
||||
m_defaultTagEndMarker = endMarker;
|
||||
}
|
||||
|
||||
void Renderer::expandTag(Tag & tag, const QString & content)
|
||||
{
|
||||
int start = tag.start;
|
||||
int end = tag.end;
|
||||
|
||||
// Move start to beginning of line.
|
||||
while (start > 0 && content.at(start - 1) != QLatin1Char('\n')) {
|
||||
--start;
|
||||
if (!content.at(start).isSpace()) {
|
||||
return; // Not standalone.
|
||||
}
|
||||
}
|
||||
|
||||
// Move end to one past end of line.
|
||||
while (end <= content.size() && content.at(end - 1) != QLatin1Char('\n')) {
|
||||
if (end < content.size() && !content.at(end).isSpace()) {
|
||||
return; // Not standalone.
|
||||
}
|
||||
++end;
|
||||
}
|
||||
|
||||
tag.start = start;
|
||||
tag.end = end;
|
||||
}
|
266
ground/openpilotgcs/src/libs/utils/mustache.h
Normal file
266
ground/openpilotgcs/src/libs/utils/mustache.h
Normal file
@ -0,0 +1,266 @@
|
||||
/*
|
||||
Copyright 2012, Robert Knight
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QtCore/QStack>
|
||||
#include <QtCore/QString>
|
||||
#include <QtCore/QVariant>
|
||||
|
||||
#include "utils_global.h"
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
#include <functional> /* for std::function */
|
||||
#endif
|
||||
|
||||
namespace Mustache {
|
||||
class PartialResolver;
|
||||
class Renderer;
|
||||
|
||||
/** Context is an interface that Mustache::Renderer::render() uses to
|
||||
* fetch substitutions for template tags.
|
||||
*/
|
||||
class QTCREATOR_UTILS_EXPORT Context {
|
||||
public:
|
||||
/** Create a context. @p resolver is used to fetch the expansions for any {{>partial}} tags
|
||||
* which appear in a template.
|
||||
*/
|
||||
explicit Context(PartialResolver *resolver = 0);
|
||||
virtual ~Context() {}
|
||||
|
||||
/** Returns a string representation of the value for @p key in the current context.
|
||||
* This is used to replace a Mustache value tag.
|
||||
*/
|
||||
virtual QString stringValue(const QString & key) const = 0;
|
||||
|
||||
/** Returns true if the value for @p key is 'false' or an empty list.
|
||||
* 'False' values typically include empty strings, the boolean value false etc.
|
||||
*
|
||||
* When processing a section Mustache tag, the section is not rendered if the key
|
||||
* is false, or for an inverted section tag, the section is only rendered if the key
|
||||
* is false.
|
||||
*/
|
||||
virtual bool isFalse(const QString & key) const = 0;
|
||||
|
||||
/** Returns the number of items in the list value for @p key or 0 if
|
||||
* the value for @p key is not a list.
|
||||
*/
|
||||
virtual int listCount(const QString & key) const = 0;
|
||||
|
||||
/** Set the current context to the value for @p key.
|
||||
* If index is >= 0, set the current context to the @p index'th value
|
||||
* in the list value for @p key.
|
||||
*/
|
||||
virtual void push(const QString & key, int index = -1) = 0;
|
||||
|
||||
/** Exit the current context. */
|
||||
virtual void pop() = 0;
|
||||
|
||||
/** Returns the partial template for a given @p key. */
|
||||
QString partialValue(const QString & key) const;
|
||||
|
||||
/** Returns the partial resolver passed to the constructor. */
|
||||
PartialResolver *partialResolver() const;
|
||||
|
||||
/** Returns true if eval() should be used to render section tags using @p key.
|
||||
* If canEval() returns true for a key, the renderer will pass the literal, unrendered
|
||||
* block of text for the section to eval() and replace the section with the result.
|
||||
*
|
||||
* canEval() and eval() are equivalents for callable objects (eg. lambdas) in other
|
||||
* Mustache implementations.
|
||||
*
|
||||
* The default implementation always returns false.
|
||||
*/
|
||||
virtual bool canEval(const QString & key) const;
|
||||
|
||||
/** Callback used to render a template section with the given @p key.
|
||||
* @p renderer will substitute the original section tag with the result of eval().
|
||||
*
|
||||
* The default implementation returns an empty string.
|
||||
*/
|
||||
virtual QString eval(const QString & key, const QString & _template, Renderer *renderer);
|
||||
|
||||
private:
|
||||
PartialResolver *m_partialResolver;
|
||||
};
|
||||
|
||||
/** A context implementation which wraps a QVariantHash or QVariantMap. */
|
||||
class QTCREATOR_UTILS_EXPORT QtVariantContext : public Context {
|
||||
public:
|
||||
/** Construct a QtVariantContext which wraps a dictionary in a QVariantHash
|
||||
* or a QVariantMap.
|
||||
*/
|
||||
#if __cplusplus >= 201103L
|
||||
typedef std::function<QString(const QString &, Mustache::Renderer *, Mustache::Context *)> fn_t;
|
||||
#else
|
||||
typedef QString (*fn_t)(const QString &, Mustache::Renderer *, Mustache::Context *);
|
||||
#endif
|
||||
explicit QtVariantContext(const QVariant & root, PartialResolver *resolver = 0);
|
||||
|
||||
virtual QString stringValue(const QString & key) const;
|
||||
virtual bool isFalse(const QString & key) const;
|
||||
virtual int listCount(const QString & key) const;
|
||||
virtual void push(const QString & key, int index = -1);
|
||||
virtual void pop();
|
||||
virtual bool canEval(const QString & key) const;
|
||||
virtual QString eval(const QString & key, const QString & _template, Mustache::Renderer *renderer);
|
||||
|
||||
private:
|
||||
QVariant value(const QString & key) const;
|
||||
|
||||
QStack<QVariant> m_contextStack;
|
||||
};
|
||||
|
||||
/** Interface for fetching template partials. */
|
||||
class QTCREATOR_UTILS_EXPORT PartialResolver {
|
||||
public:
|
||||
virtual ~PartialResolver() {}
|
||||
|
||||
/** Returns the partial template with a given @p name. */
|
||||
virtual QString getPartial(const QString & name) = 0;
|
||||
};
|
||||
|
||||
/** A simple partial fetcher which returns templates from a map of (partial name -> template)
|
||||
*/
|
||||
class QTCREATOR_UTILS_EXPORT PartialMap : public PartialResolver {
|
||||
public:
|
||||
explicit PartialMap(const QHash<QString, QString> & partials);
|
||||
|
||||
virtual QString getPartial(const QString & name);
|
||||
|
||||
private:
|
||||
QHash<QString, QString> m_partials;
|
||||
};
|
||||
|
||||
/** A partial fetcher when loads templates from '<name>.mustache' files
|
||||
* in a given directory.
|
||||
*
|
||||
* Once a partial has been loaded, it is cached for future use.
|
||||
*/
|
||||
class QTCREATOR_UTILS_EXPORT PartialFileLoader : public PartialResolver {
|
||||
public:
|
||||
explicit PartialFileLoader(const QString & basePath);
|
||||
|
||||
virtual QString getPartial(const QString & name);
|
||||
|
||||
private:
|
||||
QString m_basePath;
|
||||
QHash<QString, QString> m_cache;
|
||||
};
|
||||
|
||||
/** Holds properties of a tag in a mustache template. */
|
||||
struct Tag {
|
||||
enum Type {
|
||||
Null,
|
||||
Value, /// A {{key}} or {{{key}}} tag
|
||||
SectionStart, /// A {{#section}} tag
|
||||
InvertedSectionStart, /// An {{^inverted-section}} tag
|
||||
SectionEnd, /// A {{/section}} tag
|
||||
Partial, /// A {{^partial}} tag
|
||||
Comment, /// A {{! comment }} tag
|
||||
SetDelimiter /// A {{=<% %>=}} tag
|
||||
};
|
||||
|
||||
enum EscapeMode {
|
||||
Escape,
|
||||
Unescape,
|
||||
Raw
|
||||
};
|
||||
|
||||
Tag()
|
||||
: type(Null)
|
||||
, start(0)
|
||||
, end(0)
|
||||
, escapeMode(Escape)
|
||||
{}
|
||||
|
||||
Type type;
|
||||
QString key;
|
||||
int start;
|
||||
int end;
|
||||
EscapeMode escapeMode;
|
||||
};
|
||||
|
||||
/** Renders Mustache templates, replacing mustache tags with
|
||||
* values from a provided context.
|
||||
*/
|
||||
class QTCREATOR_UTILS_EXPORT Renderer {
|
||||
public:
|
||||
Renderer();
|
||||
|
||||
/** Render a Mustache template, using @p context to fetch
|
||||
* the values used to replace Mustache tags.
|
||||
*/
|
||||
QString render(const QString & _template, Context *context);
|
||||
|
||||
/** Returns a message describing the last error encountered by the previous
|
||||
* render() call.
|
||||
*/
|
||||
QString error() const;
|
||||
|
||||
/** Returns the position in the template where the last error occurred
|
||||
* when rendering the template or -1 if no error occurred.
|
||||
*
|
||||
* If the error occurred in a partial template, the returned position is the offset
|
||||
* in the partial template.
|
||||
*/
|
||||
int errorPos() const;
|
||||
|
||||
/** Returns the name of the partial where the error occurred, or an empty string
|
||||
* if the error occurred in the main template.
|
||||
*/
|
||||
QString errorPartial() const;
|
||||
|
||||
/** Sets the default tag start and end markers.
|
||||
* This can be overridden within a template.
|
||||
*/
|
||||
void setTagMarkers(const QString & startMarker, const QString & endMarker);
|
||||
|
||||
private:
|
||||
QString render(const QString & _template, int startPos, int endPos, Context *context);
|
||||
|
||||
Tag findTag(const QString & content, int pos, int endPos);
|
||||
Tag findEndTag(const QString & content, const Tag & startTag, int endPos);
|
||||
void setError(const QString & error, int pos);
|
||||
|
||||
void readSetDelimiter(const QString & content, int pos, int endPos);
|
||||
static QString readTagName(const QString & content, int pos, int endPos);
|
||||
|
||||
/** Expands @p tag to fill the line, but only if it is standalone.
|
||||
*
|
||||
* The start position is moved to the beginning of the line. The end position is
|
||||
* moved to one past the end of the line. If @p tag is not standalone, it is
|
||||
* left unmodified.
|
||||
*
|
||||
* A tag is standalone if it is the only non-whitespace token on the the line.
|
||||
*/
|
||||
static void expandTag(Tag & tag, const QString & content);
|
||||
|
||||
QStack<QString> m_partialStack;
|
||||
QString m_error;
|
||||
int m_errorPos;
|
||||
QString m_errorPartial;
|
||||
|
||||
QString m_tagStartMarker;
|
||||
QString m_tagEndMarker;
|
||||
|
||||
QString m_defaultTagStartMarker;
|
||||
QString m_defaultTagEndMarker;
|
||||
};
|
||||
|
||||
/** A convenience function which renders a template using the given data. */
|
||||
QString renderTemplate(const QString & templateString, const QVariantHash & args);
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(Mustache::QtVariantContext::fn_t)
|
@ -56,7 +56,8 @@ SOURCES += reloadpromptutils.cpp \
|
||||
svgimageprovider.cpp \
|
||||
hostosinfo.cpp \
|
||||
logfile.cpp \
|
||||
crc.cpp
|
||||
crc.cpp \
|
||||
mustache.cpp
|
||||
|
||||
SOURCES += xmlconfig.cpp
|
||||
|
||||
@ -115,7 +116,8 @@ HEADERS += utils_global.h \
|
||||
svgimageprovider.h \
|
||||
hostosinfo.h \
|
||||
logfile.h \
|
||||
crc.h
|
||||
crc.h \
|
||||
mustache.h
|
||||
|
||||
|
||||
HEADERS += xmlconfig.h
|
||||
|
@ -7,3 +7,4 @@ include(../../plugins/uavobjectutil/uavobjectutil.pri)
|
||||
include(../../plugins/uavsettingsimportexport/uavsettingsimportexport.pri)
|
||||
include(../../plugins/uavobjectwidgetutils/uavobjectwidgetutils.pri)
|
||||
include(../../libs/version_info/version_info.pri)
|
||||
include(../../libs/qwt/qwt.pri)
|
||||
|
@ -65,6 +65,8 @@ ConfigRevoHWWidget::ConfigRevoHWWidget(QWidget *parent) : ConfigTaskWidget(paren
|
||||
addWidgetBinding("HwSettings", "GPSSpeed", m_ui->cbMainGPSSpeed);
|
||||
addWidgetBinding("HwSettings", "ComUsbBridgeSpeed", m_ui->cbMainComSpeed);
|
||||
|
||||
addWidgetBinding("HwSettings", "TelemetrySpeed", m_ui->cbRcvrTelemSpeed);
|
||||
|
||||
// Add Gps protocol configuration
|
||||
addWidgetBinding("GPSSettings", "DataProtocol", m_ui->cbMainGPSProtocol);
|
||||
addWidgetBinding("GPSSettings", "DataProtocol", m_ui->cbFlexiGPSProtocol);
|
||||
@ -95,6 +97,7 @@ void ConfigRevoHWWidget::setupCustomCombos()
|
||||
|
||||
connect(m_ui->cbFlexi, SIGNAL(currentIndexChanged(int)), this, SLOT(flexiPortChanged(int)));
|
||||
connect(m_ui->cbMain, SIGNAL(currentIndexChanged(int)), this, SLOT(mainPortChanged(int)));
|
||||
connect(m_ui->cbRcvr, SIGNAL(currentIndexChanged(int)), this, SLOT(rcvrPortChanged(int)));
|
||||
}
|
||||
|
||||
void ConfigRevoHWWidget::refreshWidgetsValues(UAVObject *obj)
|
||||
@ -105,6 +108,7 @@ void ConfigRevoHWWidget::refreshWidgetsValues(UAVObject *obj)
|
||||
usbVCPPortChanged(0);
|
||||
mainPortChanged(0);
|
||||
flexiPortChanged(0);
|
||||
rcvrPortChanged(0);
|
||||
m_refreshing = false;
|
||||
}
|
||||
|
||||
@ -196,6 +200,10 @@ void ConfigRevoHWWidget::flexiPortChanged(int index)
|
||||
if (m_ui->cbMain->currentIndex() == HwSettings::RM_MAINPORT_TELEMETRY) {
|
||||
m_ui->cbMain->setCurrentIndex(HwSettings::RM_MAINPORT_DISABLED);
|
||||
}
|
||||
if (m_ui->cbRcvr->currentIndex() == HwSettings::RM_RCVRPORT_PPMTELEMETRY
|
||||
|| m_ui->cbRcvr->currentIndex() == HwSettings::RM_RCVRPORT_TELEMETRY) {
|
||||
m_ui->cbRcvr->setCurrentIndex(HwSettings::RM_RCVRPORT_DISABLED);
|
||||
}
|
||||
break;
|
||||
case HwSettings::RM_FLEXIPORT_GPS:
|
||||
// Add Gps protocol configuration
|
||||
@ -247,6 +255,10 @@ void ConfigRevoHWWidget::mainPortChanged(int index)
|
||||
if (m_ui->cbFlexi->currentIndex() == HwSettings::RM_FLEXIPORT_TELEMETRY) {
|
||||
m_ui->cbFlexi->setCurrentIndex(HwSettings::RM_FLEXIPORT_DISABLED);
|
||||
}
|
||||
if (m_ui->cbRcvr->currentIndex() == HwSettings::RM_RCVRPORT_PPMTELEMETRY
|
||||
|| m_ui->cbRcvr->currentIndex() == HwSettings::RM_RCVRPORT_TELEMETRY) {
|
||||
m_ui->cbRcvr->setCurrentIndex(HwSettings::RM_RCVRPORT_DISABLED);
|
||||
}
|
||||
break;
|
||||
case HwSettings::RM_MAINPORT_GPS:
|
||||
// Add Gps protocol configuration
|
||||
@ -279,6 +291,30 @@ void ConfigRevoHWWidget::mainPortChanged(int index)
|
||||
}
|
||||
}
|
||||
|
||||
void ConfigRevoHWWidget::rcvrPortChanged(int index)
|
||||
{
|
||||
Q_UNUSED(index);
|
||||
|
||||
switch (m_ui->cbRcvr->currentIndex()) {
|
||||
case HwSettings::RM_RCVRPORT_TELEMETRY:
|
||||
case HwSettings::RM_RCVRPORT_PPMTELEMETRY:
|
||||
m_ui->lblRcvrSpeed->setVisible(true);
|
||||
m_ui->cbRcvrTelemSpeed->setVisible(true);
|
||||
|
||||
if (m_ui->cbFlexi->currentIndex() == HwSettings::RM_FLEXIPORT_TELEMETRY) {
|
||||
m_ui->cbFlexi->setCurrentIndex(HwSettings::RM_FLEXIPORT_DISABLED);
|
||||
}
|
||||
if (m_ui->cbMain->currentIndex() == HwSettings::RM_FLEXIPORT_TELEMETRY) {
|
||||
m_ui->cbMain->setCurrentIndex(HwSettings::RM_FLEXIPORT_DISABLED);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
m_ui->lblRcvrSpeed->setVisible(false);
|
||||
m_ui->cbRcvrTelemSpeed->setVisible(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ConfigRevoHWWidget::openHelp()
|
||||
{
|
||||
QDesktopServices::openUrl(QUrl(tr("http://wiki.openpilot.org/x/GgDBAQ"), QUrl::StrictMode));
|
||||
|
@ -57,6 +57,7 @@ private slots:
|
||||
void usbHIDPortChanged(int index);
|
||||
void flexiPortChanged(int index);
|
||||
void mainPortChanged(int index);
|
||||
void rcvrPortChanged(int index);
|
||||
void openHelp();
|
||||
};
|
||||
|
||||
|
@ -121,9 +121,9 @@
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>810</width>
|
||||
<height>665</height>
|
||||
<y>-87</y>
|
||||
<width>789</width>
|
||||
<height>847</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
@ -139,6 +139,45 @@
|
||||
<property name="bottomMargin">
|
||||
<number>12</number>
|
||||
</property>
|
||||
<item row="3" column="2">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<spacer name="horizontalSpacer_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="2" column="3">
|
||||
<spacer name="horizontalSpacer_5">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="sizePolicy">
|
||||
@ -192,81 +231,100 @@
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<spacer name="horizontalSpacer_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="2" column="3">
|
||||
<spacer name="horizontalSpacer_5">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="3" column="2">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<layout class="QGridLayout" name="gridLayout" rowstretch="0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0">
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout" rowstretch="0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0">
|
||||
<item row="22" column="1">
|
||||
<widget class="QLabel" name="lbFlexiGPSProtocol">
|
||||
<property name="text">
|
||||
<string>USB HID Function</string>
|
||||
<string>Protocol</string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::PlainText</enum>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="24" column="3">
|
||||
<widget class="QComboBox" name="cbMainGPSProtocol"/>
|
||||
</item>
|
||||
<item row="24" column="1">
|
||||
<widget class="QComboBox" name="cbFlexiGPSProtocol"/>
|
||||
</item>
|
||||
<item row="25" column="2">
|
||||
<spacer name="horizontalSpacer_10">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>80</width>
|
||||
<height>10</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="20" column="3">
|
||||
<widget class="QLabel" name="lblMainSpeed">
|
||||
<property name="text">
|
||||
<string>Speed</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignBottom|Qt::AlignHCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="12" column="4">
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<item row="14" column="5">
|
||||
<spacer name="verticalSpacer_7">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>10</height>
|
||||
<width>20</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="19" column="1">
|
||||
<spacer name="horizontalSpacer_7">
|
||||
<item row="17" column="5">
|
||||
<spacer name="verticalSpacer_9">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>13</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="15" column="5">
|
||||
<spacer name="verticalSpacer_5">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>13</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="25" column="3">
|
||||
<spacer name="horizontalSpacer_9">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
@ -281,17 +339,201 @@
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="16" column="3">
|
||||
<widget class="QLabel" name="lbMainGPSProtocol">
|
||||
<item row="13" column="5">
|
||||
<spacer name="verticalSpacer_8">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>13</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="21" column="3">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_6">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QComboBox" name="cbMainTelemSpeed">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="cbMainGPSSpeed"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="cbMainComSpeed"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QComboBox" name="cbRcvr"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<spacer name="verticalSpacer_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>90</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="18" column="0">
|
||||
<spacer name="horizontalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Minimum</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>120</width>
|
||||
<height>10</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Protocol</string>
|
||||
<string>Receiver Port</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
<set>Qt::AlignBottom|Qt::AlignHCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1" rowspan="11" colspan="4" alignment="Qt::AlignHCenter|Qt::AlignVCenter">
|
||||
<item row="11" column="5">
|
||||
<widget class="QLabel" name="label_9">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Sonar Port</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignBottom|Qt::AlignHCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="20" column="1">
|
||||
<widget class="QLabel" name="lblFlexiSpeed">
|
||||
<property name="text">
|
||||
<string>Speed</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignBottom|Qt::AlignHCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="18" column="5">
|
||||
<spacer name="horizontalSpacer_6">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Minimum</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>120</width>
|
||||
<height>10</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="19" column="3">
|
||||
<widget class="QComboBox" name="cbMain"/>
|
||||
</item>
|
||||
<item row="12" column="5">
|
||||
<widget class="QComboBox" name="cbSonar">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="25" column="4">
|
||||
<spacer name="horizontalSpacer_8">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Minimum</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>70</width>
|
||||
<height>10</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="16" column="5">
|
||||
<spacer name="verticalSpacer_6">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="18" column="3">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Main Port</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignBottom|Qt::AlignHCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="19" column="1">
|
||||
<widget class="QComboBox" name="cbFlexi"/>
|
||||
</item>
|
||||
<item row="18" column="1">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Flexi Port</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignBottom|Qt::AlignHCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1" rowspan="17" colspan="4" alignment="Qt::AlignHCenter|Qt::AlignVCenter">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
@ -322,28 +564,12 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="5">
|
||||
<spacer name="verticalSpacer_6">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="15" column="1">
|
||||
<item row="21" column="1">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item alignment="Qt::AlignTop">
|
||||
<item>
|
||||
<widget class="QComboBox" name="cbFlexiTelemSpeed">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
@ -358,64 +584,8 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="13" column="1">
|
||||
<widget class="QComboBox" name="cbFlexi"/>
|
||||
</item>
|
||||
<item row="19" column="4">
|
||||
<spacer name="horizontalSpacer_8">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Minimum</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>70</width>
|
||||
<height>10</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="12" column="1">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Flexi Port</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignBottom|Qt::AlignHCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="5">
|
||||
<widget class="QComboBox" name="cbSonar">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="13" column="3">
|
||||
<widget class="QComboBox" name="cbMain"/>
|
||||
</item>
|
||||
<item row="12" column="3">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Main Port</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignBottom|Qt::AlignHCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="0">
|
||||
<widget class="QComboBox" name="cbUSBVCPSpeed">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="12" column="5">
|
||||
<spacer name="horizontalSpacer_6">
|
||||
<item row="25" column="1">
|
||||
<spacer name="horizontalSpacer_7">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
@ -430,13 +600,80 @@
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="8" column="0">
|
||||
<widget class="QComboBox" name="cbUSBVCPFunction"/>
|
||||
<item row="22" column="3">
|
||||
<widget class="QLabel" name="lbMainGPSProtocol">
|
||||
<property name="text">
|
||||
<string>Protocol</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QComboBox" name="cbUSBHIDFunction"/>
|
||||
<item row="18" column="4">
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>10</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="9" column="0">
|
||||
<item row="4" column="0">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<item>
|
||||
<widget class="QLabel" name="lblRcvrSpeed">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Speed</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="cbRcvrTelemSpeed"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_11">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>50</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="15" column="0">
|
||||
<widget class="QComboBox" name="cbUSBVCPSpeed">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="14" column="0">
|
||||
<widget class="QLabel" name="lblUSBVCPSpeed">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
@ -452,71 +689,10 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="5">
|
||||
<widget class="QLabel" name="label_9">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Sonar Port</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignBottom|Qt::AlignHCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Receiver Port</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignBottom|Qt::AlignHCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<spacer name="verticalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
<item row="13" column="0">
|
||||
<widget class="QComboBox" name="cbUSBVCPFunction"/>
|
||||
</item>
|
||||
<item row="12" column="0">
|
||||
<spacer name="horizontalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Minimum</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>120</width>
|
||||
<height>10</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
@ -532,177 +708,25 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<spacer name="verticalSpacer_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>120</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
<item row="11" column="0">
|
||||
<widget class="QComboBox" name="cbUSBHIDFunction"/>
|
||||
</item>
|
||||
<item row="14" column="1">
|
||||
<widget class="QLabel" name="lblFlexiSpeed">
|
||||
<item row="10" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Speed</string>
|
||||
<string>USB HID Function</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignBottom|Qt::AlignHCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="15" column="3">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_6">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QComboBox" name="cbMainTelemSpeed">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="cbMainGPSSpeed"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="cbMainComSpeed"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QComboBox" name="cbRcvr"/>
|
||||
</item>
|
||||
<item row="19" column="3">
|
||||
<spacer name="horizontalSpacer_9">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Minimum</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>120</width>
|
||||
<height>10</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="7" column="5">
|
||||
<spacer name="verticalSpacer_8">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>13</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="8" column="5">
|
||||
<spacer name="verticalSpacer_7">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="9" column="5">
|
||||
<spacer name="verticalSpacer_5">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>13</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="11" column="5">
|
||||
<spacer name="verticalSpacer_9">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>13</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="19" column="2">
|
||||
<spacer name="horizontalSpacer_10">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>80</width>
|
||||
<height>10</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="14" column="3">
|
||||
<widget class="QLabel" name="lblMainSpeed">
|
||||
<property name="text">
|
||||
<string>Speed</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignBottom|Qt::AlignHCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="16" column="1">
|
||||
<widget class="QLabel" name="lbFlexiGPSProtocol">
|
||||
<property name="text">
|
||||
<string>Protocol</string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::PlainText</enum>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="18" column="3">
|
||||
<widget class="QComboBox" name="cbMainGPSProtocol"/>
|
||||
</item>
|
||||
<item row="18" column="1">
|
||||
<widget class="QComboBox" name="cbFlexiGPSProtocol"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
@ -908,8 +932,8 @@ Beware of not locking yourself out!</string>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="configgadget.qrc"/>
|
||||
<include location="../coreplugin/core.qrc"/>
|
||||
<include location="configgadget.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
@ -43,12 +43,19 @@
|
||||
#include "altitudeholdsettings.h"
|
||||
#include "stabilizationsettings.h"
|
||||
|
||||
#include "qwt/src/qwt.h"
|
||||
#include "qwt/src/qwt_plot.h"
|
||||
#include "qwt/src/qwt_plot_canvas.h"
|
||||
#include "qwt/src/qwt_scale_widget.h"
|
||||
|
||||
ConfigStabilizationWidget::ConfigStabilizationWidget(QWidget *parent) : ConfigTaskWidget(parent),
|
||||
boardModel(0), m_pidBankCount(0), m_currentPIDBank(0)
|
||||
{
|
||||
ui = new Ui_StabilizationWidget();
|
||||
ui->setupUi(this);
|
||||
|
||||
setupExpoPlot();
|
||||
|
||||
StabilizationSettings *stabSettings = qobject_cast<StabilizationSettings *>(getObject("StabilizationSettings"));
|
||||
Q_ASSERT(stabSettings);
|
||||
|
||||
@ -59,7 +66,7 @@ ConfigStabilizationWidget::ConfigStabilizationWidget(QWidget *parent) : ConfigTa
|
||||
m_pidTabBars.append(ui->advancedPIDBankTabBar);
|
||||
foreach(QTabBar * tabBar, m_pidTabBars) {
|
||||
for (int i = 0; i < m_pidBankCount; i++) {
|
||||
tabBar->addTab(tr("PID Bank %1").arg(i + 1));
|
||||
tabBar->addTab(tr("Settings Bank %1").arg(i + 1));
|
||||
tabBar->setTabData(i, QString("StabilizationSettingsBank%1").arg(i + 1));
|
||||
}
|
||||
tabBar->setExpanding(false);
|
||||
@ -144,6 +151,11 @@ ConfigStabilizationWidget::ConfigStabilizationWidget(QWidget *parent) : ConfigTa
|
||||
|
||||
connect(this, SIGNAL(autoPilotConnected()), this, SLOT(onBoardConnected()));
|
||||
|
||||
addWidget(ui->expoPlot);
|
||||
connect(ui->expoSpinnerRoll, SIGNAL(valueChanged(int)), this, SLOT(replotExpoRoll(int)));
|
||||
connect(ui->expoSpinnerPitch, SIGNAL(valueChanged(int)), this, SLOT(replotExpoPitch(int)));
|
||||
connect(ui->expoSpinnerYaw, SIGNAL(valueChanged(int)), this, SLOT(replotExpoYaw(int)));
|
||||
|
||||
disableMouseWheelEvents();
|
||||
updateEnableControls();
|
||||
}
|
||||
@ -175,14 +187,12 @@ void ConfigStabilizationWidget::updateThrottleCurveFromObject()
|
||||
UAVObject *stabBank = getObjectManager()->getObject(QString(m_pidTabBars.at(0)->tabData(m_currentPIDBank).toString()));
|
||||
|
||||
Q_ASSERT(stabBank);
|
||||
qDebug() << "updatingCurveFromObject" << stabBank->getName();
|
||||
|
||||
UAVObjectField *field = stabBank->getField("ThrustPIDScaleCurve");
|
||||
Q_ASSERT(field);
|
||||
|
||||
QList<double> curve;
|
||||
for (quint32 i = 0; i < field->getNumElements(); i++) {
|
||||
qDebug() << field->getName() << field->getElementNames().at(i) << "=>" << field->getValue(i);
|
||||
curve.append(field->getValue(i).toDouble());
|
||||
}
|
||||
|
||||
@ -202,7 +212,6 @@ void ConfigStabilizationWidget::updateObjectFromThrottleCurve()
|
||||
UAVObject *stabBank = getObjectManager()->getObject(QString(m_pidTabBars.at(0)->tabData(m_currentPIDBank).toString()));
|
||||
|
||||
Q_ASSERT(stabBank);
|
||||
qDebug() << "updatingObjectFromCurve" << stabBank->getName();
|
||||
|
||||
UAVObjectField *field = stabBank->getField("ThrustPIDScaleCurve");
|
||||
Q_ASSERT(field);
|
||||
@ -210,7 +219,6 @@ void ConfigStabilizationWidget::updateObjectFromThrottleCurve()
|
||||
QList<double> curve = ui->thrustPIDScalingCurve->getCurve();
|
||||
for (quint32 i = 0; i < field->getNumElements(); i++) {
|
||||
field->setValue(curve.at(i), i);
|
||||
qDebug() << field->getName() << field->getElementNames().at(i) << "<=" << curve.at(i);
|
||||
}
|
||||
|
||||
field = stabBank->getField("EnableThrustPIDScaling");
|
||||
@ -218,6 +226,55 @@ void ConfigStabilizationWidget::updateObjectFromThrottleCurve()
|
||||
field->setValue(ui->enableThrustPIDScalingCheckBox->isChecked() ? "TRUE" : "FALSE");
|
||||
}
|
||||
|
||||
void ConfigStabilizationWidget::setupExpoPlot()
|
||||
{
|
||||
ui->expoPlot->setMouseTracking(false);
|
||||
ui->expoPlot->setAxisScale(QwtPlot::xBottom, 0, 100, 25);
|
||||
|
||||
QwtText title;
|
||||
title.setText(tr("Input %"));
|
||||
title.setFont(ui->expoPlot->axisFont(QwtPlot::xBottom));
|
||||
ui->expoPlot->setAxisTitle(QwtPlot::xBottom, title);
|
||||
ui->expoPlot->setAxisScale(QwtPlot::yLeft, 0, 100, 25);
|
||||
|
||||
title.setText(tr("Output %"));
|
||||
title.setFont(ui->expoPlot->axisFont(QwtPlot::yLeft));
|
||||
ui->expoPlot->setAxisTitle(QwtPlot::yLeft, title);
|
||||
ui->expoPlot->canvas()->setFrameShape(QFrame::NoFrame);
|
||||
ui->expoPlot->canvas()->setCursor(QCursor());
|
||||
|
||||
|
||||
m_plotGrid.setMajPen(QColor(Qt::gray));
|
||||
m_plotGrid.setMinPen(QColor(Qt::lightGray));
|
||||
m_plotGrid.enableXMin(false);
|
||||
m_plotGrid.enableYMin(false);
|
||||
m_plotGrid.attach(ui->expoPlot);
|
||||
|
||||
m_expoPlotCurveRoll.setRenderHint(QwtPlotCurve::RenderAntialiased);
|
||||
QColor rollColor(Qt::red);
|
||||
rollColor.setAlpha(180);
|
||||
m_expoPlotCurveRoll.setPen(QPen(rollColor, 2));
|
||||
m_expoPlotCurveRoll.attach(ui->expoPlot);
|
||||
replotExpoRoll(ui->expoSpinnerRoll->value());
|
||||
m_expoPlotCurveRoll.show();
|
||||
|
||||
QColor pitchColor(Qt::green);
|
||||
pitchColor.setAlpha(180);
|
||||
m_expoPlotCurvePitch.setRenderHint(QwtPlotCurve::RenderAntialiased);
|
||||
m_expoPlotCurvePitch.setPen(QPen(pitchColor, 2));
|
||||
m_expoPlotCurvePitch.attach(ui->expoPlot);
|
||||
replotExpoPitch(ui->expoSpinnerPitch->value());
|
||||
m_expoPlotCurvePitch.show();
|
||||
|
||||
QColor yawColor(Qt::blue);
|
||||
yawColor.setAlpha(180);
|
||||
m_expoPlotCurveYaw.setRenderHint(QwtPlotCurve::RenderAntialiased);
|
||||
m_expoPlotCurveYaw.setPen(QPen(yawColor, 2));
|
||||
m_expoPlotCurveYaw.attach(ui->expoPlot);
|
||||
replotExpoYaw(ui->expoSpinnerYaw->value());
|
||||
m_expoPlotCurveYaw.show();
|
||||
}
|
||||
|
||||
void ConfigStabilizationWidget::resetThrottleCurveToDefault()
|
||||
{
|
||||
UAVDataObject *defaultStabBank = (UAVDataObject *)getObjectManager()->getObject(QString(m_pidTabBars.at(0)->tabData(m_currentPIDBank).toString()));
|
||||
@ -250,6 +307,37 @@ void ConfigStabilizationWidget::throttleCurveUpdated()
|
||||
setDirty(true);
|
||||
}
|
||||
|
||||
void ConfigStabilizationWidget::replotExpo(int value, QwtPlotCurve &curve)
|
||||
{
|
||||
double x[EXPO_CURVE_POINTS_COUNT] = { 0 };
|
||||
double y[EXPO_CURVE_POINTS_COUNT] = { 0 };
|
||||
double factor = pow(EXPO_CURVE_CONSTANT, value);
|
||||
double step = 1.0 / (EXPO_CURVE_POINTS_COUNT - 1);
|
||||
|
||||
for (int i = 0; i < EXPO_CURVE_POINTS_COUNT; i++) {
|
||||
double val = i * step;
|
||||
x[i] = val * 100.0;
|
||||
y[i] = pow(val, factor) * 100.0;
|
||||
}
|
||||
curve.setSamples(x, y, EXPO_CURVE_POINTS_COUNT);
|
||||
ui->expoPlot->replot();
|
||||
}
|
||||
|
||||
void ConfigStabilizationWidget::replotExpoRoll(int value)
|
||||
{
|
||||
replotExpo(value, m_expoPlotCurveRoll);
|
||||
}
|
||||
|
||||
void ConfigStabilizationWidget::replotExpoPitch(int value)
|
||||
{
|
||||
replotExpo(value, m_expoPlotCurvePitch);
|
||||
}
|
||||
|
||||
void ConfigStabilizationWidget::replotExpoYaw(int value)
|
||||
{
|
||||
replotExpo(value, m_expoPlotCurveYaw);
|
||||
}
|
||||
|
||||
void ConfigStabilizationWidget::realtimeUpdatesSlot(bool value)
|
||||
{
|
||||
ui->realTimeUpdates_6->setChecked(value);
|
||||
@ -259,10 +347,8 @@ void ConfigStabilizationWidget::realtimeUpdatesSlot(bool value)
|
||||
|
||||
if (value && !realtimeUpdates->isActive()) {
|
||||
realtimeUpdates->start(AUTOMATIC_UPDATE_RATE);
|
||||
qDebug() << "Instant Update timer started.";
|
||||
} else if (!value && realtimeUpdates->isActive()) {
|
||||
realtimeUpdates->stop();
|
||||
qDebug() << "Instant Update timer stopped.";
|
||||
}
|
||||
}
|
||||
|
||||
@ -359,7 +445,6 @@ void ConfigStabilizationWidget::pidBankChanged(int index)
|
||||
setWidgetBindingObjectEnabled(m_pidTabBars.at(0)->tabData(index).toString(), true);
|
||||
|
||||
m_currentPIDBank = index;
|
||||
qDebug() << "current bank:" << m_currentPIDBank;
|
||||
updateThrottleCurveFromObject();
|
||||
setDirty(dirty);
|
||||
}
|
||||
|
@ -35,7 +35,8 @@
|
||||
#include "stabilizationsettings.h"
|
||||
#include <QWidget>
|
||||
#include <QTimer>
|
||||
|
||||
#include "qwt/src/qwt_plot_curve.h"
|
||||
#include "qwt/src/qwt_plot_grid.h"
|
||||
|
||||
class ConfigStabilizationWidget : public ConfigTaskWidget {
|
||||
Q_OBJECT
|
||||
@ -52,14 +53,23 @@ private:
|
||||
QString m_stabilizationObjectsString;
|
||||
|
||||
// Milliseconds between automatic 'Instant Updates'
|
||||
static const int AUTOMATIC_UPDATE_RATE = 500;
|
||||
static const int AUTOMATIC_UPDATE_RATE = 500;
|
||||
|
||||
static const int EXPO_CURVE_POINTS_COUNT = 100;
|
||||
static const double EXPO_CURVE_CONSTANT = 1.00695;
|
||||
|
||||
int boardModel;
|
||||
int m_pidBankCount;
|
||||
int m_currentPIDBank;
|
||||
|
||||
QwtPlotCurve m_expoPlotCurveRoll;
|
||||
QwtPlotCurve m_expoPlotCurvePitch;
|
||||
QwtPlotCurve m_expoPlotCurveYaw;
|
||||
QwtPlotGrid m_plotGrid;
|
||||
|
||||
void updateThrottleCurveFromObject();
|
||||
void updateObjectFromThrottleCurve();
|
||||
void setupExpoPlot();
|
||||
protected:
|
||||
QString mapObjectName(const QString objectName);
|
||||
|
||||
@ -75,5 +85,9 @@ private slots:
|
||||
void pidBankChanged(int index);
|
||||
void resetThrottleCurveToDefault();
|
||||
void throttleCurveUpdated();
|
||||
void replotExpo(int value, QwtPlotCurve &curve);
|
||||
void replotExpoRoll(int value);
|
||||
void replotExpoPitch(int value);
|
||||
void replotExpoYaw(int value);
|
||||
};
|
||||
#endif // ConfigStabilizationWidget_H
|
||||
|
@ -145,6 +145,25 @@ static bool isAttitudeOption(int pidOption)
|
||||
}
|
||||
}
|
||||
|
||||
static bool isExpoOption(int pidOption)
|
||||
{
|
||||
switch (pidOption) {
|
||||
case TxPIDSettings::PIDS_ROLLEXPO:
|
||||
case TxPIDSettings::PIDS_PITCHEXPO:
|
||||
case TxPIDSettings::PIDS_ROLLPITCHEXPO:
|
||||
case TxPIDSettings::PIDS_YAWEXPO:
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool isAcroPlusFactorOption(int pidOption)
|
||||
{
|
||||
return pidOption == TxPIDSettings::PIDS_ACROPLUSFACTOR;
|
||||
}
|
||||
|
||||
template <class StabilizationSettingsBankX>
|
||||
static float defaultValueForPidOption(const StabilizationSettingsBankX *bank, int pidOption)
|
||||
{
|
||||
@ -260,6 +279,18 @@ static float defaultValueForPidOption(const StabilizationSettingsBankX *bank, in
|
||||
case TxPIDSettings::PIDS_YAWATTITUDERESP:
|
||||
return bank->getYawMax();
|
||||
|
||||
case TxPIDSettings::PIDS_ROLLEXPO:
|
||||
return bank->getStickExpo_Roll();
|
||||
|
||||
case TxPIDSettings::PIDS_PITCHEXPO:
|
||||
return bank->getStickExpo_Pitch();
|
||||
|
||||
case TxPIDSettings::PIDS_ROLLPITCHEXPO:
|
||||
return bank->getStickExpo_Roll();
|
||||
|
||||
case TxPIDSettings::PIDS_YAWEXPO:
|
||||
return bank->getStickExpo_Yaw();
|
||||
|
||||
case -1: // The PID Option field was uninitialized.
|
||||
return 0.0f;
|
||||
|
||||
@ -337,6 +368,20 @@ void ConfigTxPIDWidget::updateSpinBoxProperties(int selectedPidOption)
|
||||
maxPID->setSingleStep(1);
|
||||
minPID->setDecimals(0);
|
||||
maxPID->setDecimals(0);
|
||||
} else if (isExpoOption(selectedPidOption)) {
|
||||
minPID->setRange(-100, 100);
|
||||
maxPID->setRange(-100, 100);
|
||||
minPID->setSingleStep(1);
|
||||
maxPID->setSingleStep(1);
|
||||
minPID->setDecimals(0);
|
||||
maxPID->setDecimals(0);
|
||||
} else if (isAcroPlusFactorOption(selectedPidOption)) {
|
||||
minPID->setRange(0, 1);
|
||||
maxPID->setRange(0, 1);
|
||||
minPID->setSingleStep(0.01);
|
||||
maxPID->setSingleStep(0.01);
|
||||
minPID->setDecimals(2);
|
||||
maxPID->setDecimals(2);
|
||||
} else {
|
||||
minPID->setRange(0, 99.99);
|
||||
maxPID->setRange(0, 99.99);
|
||||
|
@ -179,6 +179,7 @@ ConfigVehicleTypeWidget::~ConfigVehicleTypeWidget()
|
||||
void ConfigVehicleTypeWidget::switchAirframeType(int index)
|
||||
{
|
||||
m_aircraft->airframesWidget->setCurrentWidget(getVehicleConfigWidget(index));
|
||||
m_aircraft->tabWidget->setTabEnabled(1, index != 1);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -116,8 +116,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>772</width>
|
||||
<height>514</height>
|
||||
<width>774</width>
|
||||
<height>505</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
@ -542,8 +542,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>724</width>
|
||||
<height>497</height>
|
||||
<width>758</width>
|
||||
<height>542</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_7" rowstretch="1,0,0,0">
|
||||
@ -1228,7 +1228,7 @@ margin:1px;
|
||||
font:bold;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>PID Bank</string>
|
||||
<string>Settings Bank</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
@ -2044,8 +2044,8 @@ Setup the flight mode channel on the RC Input tab if you have not done so alread
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>407</width>
|
||||
<height>138</height>
|
||||
<width>565</width>
|
||||
<height>159</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -47,8 +47,8 @@ MagicWaypointGadgetWidget::MagicWaypointGadgetWidget(QWidget *parent) : QLabel(p
|
||||
m_magicwaypoint->setupUi(this);
|
||||
|
||||
// Connect object updated event from UAVObject to also update check boxes
|
||||
connect(getPathDesired(), SIGNAL(objectUpdated(UAVObject *)), this, SLOT(positionObjectChanged(UAVObject *)));
|
||||
connect(getPositionState(), SIGNAL(objectUpdated(UAVObject *)), this, SLOT(positionObjectChanged(UAVObject *)));
|
||||
connect(getPathDesired(), SIGNAL(objectUpdated(UAVObject *)), this, SLOT(positionStateChanged(UAVObject *)));
|
||||
connect(getPositionState(), SIGNAL(objectUpdated(UAVObject *)), this, SLOT(positionStateChanged(UAVObject *)));
|
||||
|
||||
// Connect updates from the position widget to this widget
|
||||
connect(m_magicwaypoint->widgetPosition, SIGNAL(positionClicked(double, double)), this, SLOT(positionSelected(double, double)));
|
||||
|
@ -0,0 +1,62 @@
|
||||
<html>
|
||||
<head></head>
|
||||
<body style="font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;">
|
||||
<table width='100%' cellpadding="5">
|
||||
<tr bgcolor='#308BC6'>
|
||||
<td rowspan='1' colspan='4'><b>{{OBJECT_NAME_TITLE}}: </b>{{OBJECT_NAME}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan='1'><b>{{CATEGORY_TITLE}}: </b>{{CATEGORY}}</td>
|
||||
<td colspan='1'><b>{{TYPE_TITLE}}: </b>{{TYPE}}</td>
|
||||
<td colspan='1'><b>{{SIZE_TITLE}}: </b>{{SIZE}} bytes</td>
|
||||
<td colspan='1'><b>{{MULTI_INSTANCE_TITLE}}: </b>{{MULTI_INSTANCE}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan='4' rowspan='1' valign='top'><b>{{DESCRIPTION_TITLE}}: </b>{{DESCRIPTION}}</td>
|
||||
<tr bgcolor='#51A0D3'>
|
||||
<td rowspan='1' colspan='4'><b>{{FIELDS_NAME_TITLE}}</td>
|
||||
</tr>
|
||||
{{#FIELDS}}
|
||||
<tr>
|
||||
<td colspan='4'>
|
||||
<table width='100%' cellpadding="5">
|
||||
<tr bgcolor='#7DBAE2'>
|
||||
<td rowspan='1' colspan='4'><b>{{FIELD_NAME_TITLE}}: </b>{{FIELD_NAME}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan='1' colspan='1'><b>{{FIELD_TYPE_TITLE}}: </b>{{FIELD_TYPE}}</td>
|
||||
{{#FIELD_UNIT_TITLE}}
|
||||
<td rowspan='1' colspan='2'><b>{{FIELD_UNIT_TITLE}}: </b>{{FIELD_UNIT}}</td>
|
||||
{{/FIELD_UNIT_TITLE}}
|
||||
</tr>
|
||||
{{#FIELD_OPTIONS_TITLE}}
|
||||
<tr>
|
||||
<td rowspan='1' colspan='2'><b>{{FIELD_OPTIONS_TITLE}}:
|
||||
</b>{{#FIELD_OPTIONS}}{{FIELD_OPTION_DELIM}}{{FIELD_OPTION}}{{/FIELD_OPTIONS}}</td>
|
||||
</tr>
|
||||
{{/FIELD_OPTIONS_TITLE}}
|
||||
{{#FIELD_ELEMENTS_TITLE}}
|
||||
<tr>
|
||||
<td rowspan='1' colspan='2'><b>{{FIELD_ELEMENTS_TITLE}}:
|
||||
</b>{{#FIELD_ELEMENTS}}{{FIELD_ELEMENT_DELIM}}{{FIELD_ELEMENT}}{{FIELD_ELEMENT_LIMIT}}{{/FIELD_ELEMENTS}}</td>
|
||||
</tr>
|
||||
{{/FIELD_ELEMENTS_TITLE}}
|
||||
{{^FIELD_ELEMENTS_TITLE}}
|
||||
{{#FIELD_LIMIT_TITLE}}
|
||||
<tr>
|
||||
<td rowspan='1' colspan='2'><b>{{FIELD_LIMIT_TITLE}}: </b>{{FIELD_LIMIT}}</td>
|
||||
</tr>
|
||||
{{/FIELD_LIMIT_TITLE}}
|
||||
{{/FIELD_ELEMENTS_TITLE}}
|
||||
{{#FIELD_DESCRIPTION_TITLE}}
|
||||
<tr>
|
||||
<td rowspan='1' colspan='2'><b>{{FIELD_DESCRIPTION_TITLE}}: </b>{{FIELD_DESCRIPTION}}</td>
|
||||
</tr>
|
||||
{{/FIELD_DESCRIPTION_TITLE}}
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
{{/FIELDS}}
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
@ -32,7 +32,8 @@ UAVObjectBrowser::UAVObjectBrowser(QString classId, UAVObjectBrowserWidget *widg
|
||||
m_widget(widget),
|
||||
m_config(NULL)
|
||||
{
|
||||
connect(m_widget, SIGNAL(viewOptionsChanged(bool, bool, bool)), this, SLOT(viewOptionsChangedSlot(bool, bool, bool)));
|
||||
connect(m_widget, SIGNAL(viewOptionsChanged(bool, bool, bool, bool)), this, SLOT(viewOptionsChangedSlot(bool, bool, bool, bool)));
|
||||
connect(m_widget, SIGNAL(splitterChanged(QByteArray)), this, SLOT(splitterChanged(QByteArray)));
|
||||
}
|
||||
|
||||
UAVObjectBrowser::~UAVObjectBrowser()
|
||||
@ -49,14 +50,23 @@ void UAVObjectBrowser::loadConfiguration(IUAVGadgetConfiguration *config)
|
||||
m_widget->setManuallyChangedColor(m->manuallyChangedColor());
|
||||
m_widget->setRecentlyUpdatedTimeout(m->recentlyUpdatedTimeout());
|
||||
m_widget->setOnlyHilightChangedValues(m->onlyHighlightChangedValues());
|
||||
m_widget->setViewOptions(m->categorizedView(), m->scientificView(), m->showMetaData());
|
||||
m_widget->setViewOptions(m->categorizedView(), m->scientificView(), m->showMetaData(), m->showDescription());
|
||||
m_widget->setSplitterState(m->splitterState());
|
||||
}
|
||||
|
||||
void UAVObjectBrowser::viewOptionsChangedSlot(bool categorized, bool scientific, bool metadata)
|
||||
void UAVObjectBrowser::viewOptionsChangedSlot(bool categorized, bool scientific, bool metadata, bool description)
|
||||
{
|
||||
if (m_config) {
|
||||
m_config->setCategorizedView(categorized);
|
||||
m_config->setScientificView(scientific);
|
||||
m_config->setShowMetaData(metadata);
|
||||
m_config->setShowDescription(description);
|
||||
}
|
||||
}
|
||||
|
||||
void UAVObjectBrowser::splitterChanged(QByteArray state)
|
||||
{
|
||||
if (m_config) {
|
||||
m_config->setSplitterState(state);
|
||||
}
|
||||
}
|
||||
|
@ -50,8 +50,11 @@ public:
|
||||
return m_widget;
|
||||
}
|
||||
void loadConfiguration(IUAVGadgetConfiguration *config);
|
||||
|
||||
private slots:
|
||||
void viewOptionsChangedSlot(bool categorized, bool scientific, bool metadata);
|
||||
void viewOptionsChangedSlot(bool categorized, bool scientific, bool metadata, bool description);
|
||||
void splitterChanged(QByteArray state);
|
||||
|
||||
private:
|
||||
UAVObjectBrowserWidget *m_widget;
|
||||
UAVObjectBrowserConfiguration *m_config;
|
||||
|
@ -6,5 +6,6 @@
|
||||
<file>images/up_alt.png</file>
|
||||
<file>images/trash.png</file>
|
||||
<file>images/1343241276_eye.png</file>
|
||||
<file>resources/uavodescription.mustache</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
@ -7,7 +7,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>786</width>
|
||||
<height>300</height>
|
||||
<height>462</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@ -220,7 +220,63 @@
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTreeView" name="treeView"/>
|
||||
<widget class="QWidget" name="widget" native="true">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QSplitter" name="splitter">
|
||||
<property name="lineWidth">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<widget class="QTreeView" name="treeView">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QTextEdit" name="descriptionText">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>150</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="horizontalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
<property name="placeholderText">
|
||||
<string>This space shows a description of the selected UAVObject.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
|
@ -35,22 +35,20 @@ UAVObjectBrowserConfiguration::UAVObjectBrowserConfiguration(QString classId, QS
|
||||
m_recentlyUpdatedTimeout(500),
|
||||
m_useCategorizedView(false),
|
||||
m_useScientificView(false),
|
||||
m_showMetaData(false)
|
||||
m_showMetaData(false),
|
||||
m_showDescription(false)
|
||||
{
|
||||
// if a saved configuration exists load it
|
||||
if (qSettings != 0) {
|
||||
QColor recent = qSettings->value("recentlyUpdatedColor").value<QColor>();
|
||||
QColor manual = qSettings->value("manuallyChangedColor").value<QColor>();
|
||||
int timeout = qSettings->value("recentlyUpdatedTimeout").toInt();
|
||||
bool hilight = qSettings->value("onlyHilightChangedValues").toBool();
|
||||
|
||||
m_useCategorizedView = qSettings->value("CategorizedView").toBool();
|
||||
m_useScientificView = qSettings->value("ScientificView").toBool();
|
||||
m_showMetaData = qSettings->value("showMetaData").toBool();
|
||||
m_recentlyUpdatedColor = recent;
|
||||
m_manuallyChangedColor = manual;
|
||||
m_recentlyUpdatedTimeout = timeout;
|
||||
m_onlyHilightChangedValues = hilight;
|
||||
m_showDescription = qSettings->value("showDescription").toBool();
|
||||
m_splitterState = qSettings->value("splitterState").toByteArray();
|
||||
m_recentlyUpdatedColor = qSettings->value("recentlyUpdatedColor").value<QColor>();
|
||||
m_manuallyChangedColor = qSettings->value("manuallyChangedColor").value<QColor>();
|
||||
m_recentlyUpdatedTimeout = qSettings->value("recentlyUpdatedTimeout").toInt();
|
||||
m_onlyHilightChangedValues = qSettings->value("onlyHilightChangedValues").toBool();
|
||||
}
|
||||
}
|
||||
|
||||
@ -64,7 +62,9 @@ IUAVGadgetConfiguration *UAVObjectBrowserConfiguration::clone()
|
||||
m->m_onlyHilightChangedValues = m_onlyHilightChangedValues;
|
||||
m->m_useCategorizedView = m_useCategorizedView;
|
||||
m->m_useScientificView = m_useScientificView;
|
||||
m->m_splitterState = m_splitterState;
|
||||
m->m_showMetaData = m_showMetaData;
|
||||
m->m_showDescription = m_showDescription;
|
||||
return m;
|
||||
}
|
||||
|
||||
@ -81,4 +81,6 @@ void UAVObjectBrowserConfiguration::saveConfig(QSettings *qSettings) const
|
||||
qSettings->setValue("CategorizedView", m_useCategorizedView);
|
||||
qSettings->setValue("ScientificView", m_useScientificView);
|
||||
qSettings->setValue("showMetaData", m_showMetaData);
|
||||
qSettings->setValue("showDescription", m_showDescription);
|
||||
qSettings->setValue("splitterState", m_splitterState);
|
||||
}
|
||||
|
@ -40,7 +40,9 @@ class UAVObjectBrowserConfiguration : public IUAVGadgetConfiguration {
|
||||
Q_PROPERTY(bool m_onlyHilightChangedValues READ onlyHighlightChangedValues WRITE setOnlyHighlightChangedValues)
|
||||
Q_PROPERTY(bool m_useCategorizedView READ categorizedView WRITE setCategorizedView)
|
||||
Q_PROPERTY(bool m_useScientificView READ scientificView WRITE setScientificView)
|
||||
Q_PROPERTY(bool m_showDescription READ showDescription WRITE setShowDescription)
|
||||
Q_PROPERTY(bool m_showMetaData READ showMetaData WRITE setShowMetaData)
|
||||
Q_PROPERTY(QByteArray m_splitterState READ splitterState WRITE setSplitterState)
|
||||
public:
|
||||
explicit UAVObjectBrowserConfiguration(QString classId, QSettings *qSettings = 0, QObject *parent = 0);
|
||||
|
||||
@ -75,6 +77,15 @@ public:
|
||||
{
|
||||
return m_showMetaData;
|
||||
}
|
||||
bool showDescription() const
|
||||
{
|
||||
return m_showDescription;
|
||||
}
|
||||
|
||||
QByteArray splitterState() const
|
||||
{
|
||||
return m_splitterState;
|
||||
}
|
||||
|
||||
signals:
|
||||
|
||||
@ -107,6 +118,15 @@ public slots:
|
||||
{
|
||||
m_showMetaData = value;
|
||||
}
|
||||
void setShowDescription(bool value)
|
||||
{
|
||||
m_showDescription = value;
|
||||
}
|
||||
|
||||
void setSplitterState(QByteArray arg)
|
||||
{
|
||||
m_splitterState = arg;
|
||||
}
|
||||
|
||||
private:
|
||||
QColor m_recentlyUpdatedColor;
|
||||
@ -116,6 +136,8 @@ private:
|
||||
bool m_useCategorizedView;
|
||||
bool m_useScientificView;
|
||||
bool m_showMetaData;
|
||||
bool m_showDescription;
|
||||
QByteArray m_splitterState;
|
||||
};
|
||||
|
||||
#endif // UAVOBJECTBROWSERCONFIGURATION_H
|
||||
|
@ -39,6 +39,7 @@
|
||||
#include <QtCore/QDebug>
|
||||
#include <QItemEditorFactory>
|
||||
#include "extensionsystem/pluginmanager.h"
|
||||
#include "utils/mustache.h"
|
||||
|
||||
UAVObjectBrowserWidget::UAVObjectBrowserWidget(QWidget *parent) : QWidget(parent)
|
||||
{
|
||||
@ -50,15 +51,19 @@ UAVObjectBrowserWidget::UAVObjectBrowserWidget(QWidget *parent) : QWidget(parent
|
||||
m_model = new UAVObjectTreeModel();
|
||||
m_browser->treeView->setModel(m_model);
|
||||
m_browser->treeView->setColumnWidth(0, 300);
|
||||
// m_browser->treeView->expandAll();
|
||||
BrowserItemDelegate *m_delegate = new BrowserItemDelegate();
|
||||
m_browser->treeView->setItemDelegate(m_delegate);
|
||||
m_browser->treeView->setEditTriggers(QAbstractItemView::AllEditTriggers);
|
||||
m_browser->treeView->setSelectionBehavior(QAbstractItemView::SelectItems);
|
||||
m_browser->splitter->setChildrenCollapsible(false);
|
||||
m_mustacheTemplate = loadFileIntoString(QString(":/uavobjectbrowser/resources/uavodescription.mustache"));
|
||||
showMetaData(m_viewoptions->cbMetaData->isChecked());
|
||||
connect(m_browser->treeView->selectionModel(), SIGNAL(currentChanged(QModelIndex, QModelIndex)), this, SLOT(currentChanged(QModelIndex, QModelIndex)), Qt::UniqueConnection);
|
||||
showDescription(m_viewoptions->cbDescription->isChecked());
|
||||
connect(m_browser->treeView->selectionModel(), SIGNAL(currentChanged(QModelIndex, QModelIndex)),
|
||||
this, SLOT(currentChanged(QModelIndex, QModelIndex)), Qt::UniqueConnection);
|
||||
connect(m_viewoptions->cbMetaData, SIGNAL(toggled(bool)), this, SLOT(showMetaData(bool)));
|
||||
connect(m_viewoptions->cbCategorized, SIGNAL(toggled(bool)), this, SLOT(categorize(bool)));
|
||||
connect(m_viewoptions->cbDescription, SIGNAL(toggled(bool)), this, SLOT(showDescription(bool)));
|
||||
connect(m_browser->saveSDButton, SIGNAL(clicked()), this, SLOT(saveObject()));
|
||||
connect(m_browser->readSDButton, SIGNAL(clicked()), this, SLOT(loadObject()));
|
||||
connect(m_browser->eraseSDButton, SIGNAL(clicked()), this, SLOT(eraseObject()));
|
||||
@ -69,6 +74,8 @@ UAVObjectBrowserWidget::UAVObjectBrowserWidget(QWidget *parent) : QWidget(parent
|
||||
connect(m_viewoptions->cbScientific, SIGNAL(toggled(bool)), this, SLOT(viewOptionsChangedSlot()));
|
||||
connect(m_viewoptions->cbMetaData, SIGNAL(toggled(bool)), this, SLOT(viewOptionsChangedSlot()));
|
||||
connect(m_viewoptions->cbCategorized, SIGNAL(toggled(bool)), this, SLOT(viewOptionsChangedSlot()));
|
||||
connect(m_viewoptions->cbDescription, SIGNAL(toggled(bool)), this, SLOT(viewOptionsChangedSlot()));
|
||||
connect(m_browser->splitter, SIGNAL(splitterMoved(int, int)), this, SLOT(splitterMoved()));
|
||||
enableSendRequest(false);
|
||||
}
|
||||
|
||||
@ -77,11 +84,17 @@ UAVObjectBrowserWidget::~UAVObjectBrowserWidget()
|
||||
delete m_browser;
|
||||
}
|
||||
|
||||
void UAVObjectBrowserWidget::setViewOptions(bool categorized, bool scientific, bool metadata)
|
||||
void UAVObjectBrowserWidget::setViewOptions(bool categorized, bool scientific, bool metadata, bool description)
|
||||
{
|
||||
m_viewoptions->cbCategorized->setChecked(categorized);
|
||||
m_viewoptions->cbMetaData->setChecked(metadata);
|
||||
m_viewoptions->cbScientific->setChecked(scientific);
|
||||
m_viewoptions->cbDescription->setChecked(description);
|
||||
}
|
||||
|
||||
void UAVObjectBrowserWidget::setSplitterState(QByteArray state)
|
||||
{
|
||||
m_browser->splitter->restoreState(state);
|
||||
}
|
||||
|
||||
void UAVObjectBrowserWidget::showMetaData(bool show)
|
||||
@ -92,6 +105,11 @@ void UAVObjectBrowserWidget::showMetaData(bool show)
|
||||
}
|
||||
}
|
||||
|
||||
void UAVObjectBrowserWidget::showDescription(bool show)
|
||||
{
|
||||
m_browser->descriptionText->setVisible(show);
|
||||
}
|
||||
|
||||
void UAVObjectBrowserWidget::categorize(bool categorize)
|
||||
{
|
||||
UAVObjectTreeModel *tmpModel = m_model;
|
||||
@ -160,6 +178,17 @@ ObjectTreeItem *UAVObjectBrowserWidget::findCurrentObjectTreeItem()
|
||||
return objItem;
|
||||
}
|
||||
|
||||
QString UAVObjectBrowserWidget::loadFileIntoString(QString fileName)
|
||||
{
|
||||
QFile file(fileName);
|
||||
|
||||
file.open(QIODevice::ReadOnly);
|
||||
QTextStream stream(&file);
|
||||
QString line = stream.readAll();
|
||||
file.close();
|
||||
return line;
|
||||
}
|
||||
|
||||
void UAVObjectBrowserWidget::saveObject()
|
||||
{
|
||||
this->setFocus();
|
||||
@ -228,6 +257,7 @@ void UAVObjectBrowserWidget::currentChanged(const QModelIndex ¤t, const QM
|
||||
enable = false;
|
||||
}
|
||||
enableSendRequest(enable);
|
||||
updateDescription();
|
||||
}
|
||||
|
||||
void UAVObjectBrowserWidget::viewSlot()
|
||||
@ -244,7 +274,94 @@ void UAVObjectBrowserWidget::viewSlot()
|
||||
|
||||
void UAVObjectBrowserWidget::viewOptionsChangedSlot()
|
||||
{
|
||||
emit viewOptionsChanged(m_viewoptions->cbCategorized->isChecked(), m_viewoptions->cbScientific->isChecked(), m_viewoptions->cbMetaData->isChecked());
|
||||
emit viewOptionsChanged(m_viewoptions->cbCategorized->isChecked(), m_viewoptions->cbScientific->isChecked(),
|
||||
m_viewoptions->cbMetaData->isChecked(), m_viewoptions->cbDescription->isChecked());
|
||||
}
|
||||
|
||||
void UAVObjectBrowserWidget::splitterMoved()
|
||||
{
|
||||
emit splitterChanged(m_browser->splitter->saveState());
|
||||
}
|
||||
|
||||
QString UAVObjectBrowserWidget::createObjectDescription(UAVObject *object)
|
||||
{
|
||||
QString mustache(m_mustacheTemplate);
|
||||
|
||||
QVariantHash uavoHash;
|
||||
|
||||
uavoHash["OBJECT_NAME_TITLE"] = tr("Name");
|
||||
uavoHash["OBJECT_NAME"] = object->getName();
|
||||
uavoHash["CATEGORY_TITLE"] = tr("Category");
|
||||
uavoHash["CATEGORY"] = object->getCategory();
|
||||
uavoHash["TYPE_TITLE"] = tr("Type");
|
||||
uavoHash["TYPE"] = object->isMetaDataObject() ? tr("Metadata") : object->isSettingsObject() ? tr("Setting") : tr("Data");
|
||||
uavoHash["SIZE_TITLE"] = tr("Size");
|
||||
uavoHash["SIZE"] = object->getNumBytes();
|
||||
uavoHash["DESCRIPTION_TITLE"] = tr("Description");
|
||||
uavoHash["DESCRIPTION"] = object->getDescription().replace("@ref", "");
|
||||
uavoHash["MULTI_INSTANCE_TITLE"] = tr("Multi");
|
||||
uavoHash["MULTI_INSTANCE"] = object->isSingleInstance() ? tr("No") : tr("Yes");
|
||||
uavoHash["FIELDS_NAME_TITLE"] = tr("Fields");
|
||||
QVariantList fields;
|
||||
foreach(UAVObjectField * field, object->getFields()) {
|
||||
QVariantHash fieldHash;
|
||||
|
||||
fieldHash["FIELD_NAME_TITLE"] = tr("Name");
|
||||
fieldHash["FIELD_NAME"] = field->getName();
|
||||
fieldHash["FIELD_TYPE_TITLE"] = tr("Type");
|
||||
fieldHash["FIELD_TYPE"] = QString("%1%2").arg(field->getTypeAsString(),
|
||||
(field->getNumElements() > 1 ? QString("[%1]").arg(field->getNumElements()) : QString()));
|
||||
if (!field->getUnits().isEmpty()) {
|
||||
fieldHash["FIELD_UNIT_TITLE"] = tr("Unit");
|
||||
fieldHash["FIELD_UNIT"] = field->getUnits();
|
||||
}
|
||||
if (!field->getOptions().isEmpty()) {
|
||||
fieldHash["FIELD_OPTIONS_TITLE"] = tr("Options");
|
||||
QVariantList options;
|
||||
foreach(QString option, field->getOptions()) {
|
||||
QVariantHash optionHash;
|
||||
|
||||
optionHash["FIELD_OPTION"] = option;
|
||||
if (!options.isEmpty()) {
|
||||
optionHash["FIELD_OPTION_DELIM"] = ", ";
|
||||
}
|
||||
options.append(optionHash);
|
||||
}
|
||||
fieldHash["FIELD_OPTIONS"] = options;
|
||||
}
|
||||
if (field->getElementNames().count() > 1) {
|
||||
fieldHash["FIELD_ELEMENTS_TITLE"] = tr("Elements");
|
||||
QVariantList elements;
|
||||
for (int i = 0; i < field->getElementNames().count(); i++) {
|
||||
QString element = field->getElementNames().at(i);
|
||||
QVariantHash elementHash;
|
||||
elementHash["FIELD_ELEMENT"] = element;
|
||||
QString limitsString = field->getLimitsAsString(i);
|
||||
if (!limitsString.isEmpty()) {
|
||||
elementHash["FIELD_ELEMENT_LIMIT"] = limitsString.prepend(" (").append(")");
|
||||
}
|
||||
if (!elements.isEmpty()) {
|
||||
elementHash["FIELD_ELEMENT_DELIM"] = ", ";
|
||||
}
|
||||
elements.append(elementHash);
|
||||
}
|
||||
fieldHash["FIELD_ELEMENTS"] = elements;
|
||||
} else if (!field->getLimitsAsString(0).isEmpty()) {
|
||||
fieldHash["FIELD_LIMIT_TITLE"] = tr("Limits");
|
||||
fieldHash["FIELD_LIMIT"] = field->getLimitsAsString(0);
|
||||
}
|
||||
|
||||
if (!field->getDescription().isEmpty()) {
|
||||
fieldHash["FIELD_DESCRIPTION_TITLE"] = tr("Description");
|
||||
fieldHash["FIELD_DESCRIPTION"] = field->getDescription();
|
||||
}
|
||||
|
||||
fields.append(fieldHash);
|
||||
}
|
||||
uavoHash["FIELDS"] = fields;
|
||||
Mustache::QtVariantContext context(uavoHash);
|
||||
Mustache::Renderer renderer;
|
||||
return renderer.render(mustache, &context);
|
||||
}
|
||||
|
||||
void UAVObjectBrowserWidget::enableSendRequest(bool enable)
|
||||
@ -255,3 +372,17 @@ void UAVObjectBrowserWidget::enableSendRequest(bool enable)
|
||||
m_browser->readSDButton->setEnabled(enable);
|
||||
m_browser->eraseSDButton->setEnabled(enable);
|
||||
}
|
||||
|
||||
void UAVObjectBrowserWidget::updateDescription()
|
||||
{
|
||||
ObjectTreeItem *objItem = findCurrentObjectTreeItem();
|
||||
|
||||
if (objItem) {
|
||||
UAVObject *obj = objItem->object();
|
||||
if (obj) {
|
||||
m_browser->descriptionText->setText(createObjectDescription(obj));
|
||||
return;
|
||||
}
|
||||
}
|
||||
m_browser->descriptionText->setText("");
|
||||
}
|
||||
|
@ -60,9 +60,11 @@ public:
|
||||
{
|
||||
m_onlyHilightChangedValues = hilight; m_model->setOnlyHilightChangedValues(hilight);
|
||||
}
|
||||
void setViewOptions(bool categorized, bool scientific, bool metadata);
|
||||
void setViewOptions(bool categorized, bool scientific, bool metadata, bool description);
|
||||
void setSplitterState(QByteArray state);
|
||||
public slots:
|
||||
void showMetaData(bool show);
|
||||
void showDescription(bool show);
|
||||
void categorize(bool categorize);
|
||||
void useScientificNotation(bool scientific);
|
||||
|
||||
@ -75,8 +77,11 @@ private slots:
|
||||
void currentChanged(const QModelIndex ¤t, const QModelIndex &previous);
|
||||
void viewSlot();
|
||||
void viewOptionsChangedSlot();
|
||||
void splitterMoved();
|
||||
QString createObjectDescription(UAVObject *object);
|
||||
signals:
|
||||
void viewOptionsChanged(bool categorized, bool scientific, bool metadata);
|
||||
void viewOptionsChanged(bool categorized, bool scientific, bool metadata, bool description);
|
||||
void splitterChanged(QByteArray state);
|
||||
private:
|
||||
QPushButton *m_requestUpdate;
|
||||
QPushButton *m_sendUpdate;
|
||||
@ -89,10 +94,13 @@ private:
|
||||
QColor m_recentlyUpdatedColor;
|
||||
QColor m_manuallyChangedColor;
|
||||
bool m_onlyHilightChangedValues;
|
||||
QString m_mustacheTemplate;
|
||||
|
||||
void updateObjectPersistance(ObjectPersistence::OperationOptions op, UAVObject *obj);
|
||||
void enableSendRequest(bool enable);
|
||||
void updateDescription();
|
||||
ObjectTreeItem *findCurrentObjectTreeItem();
|
||||
QString loadFileIntoString(QString fileName);
|
||||
};
|
||||
|
||||
#endif /* UAVOBJECTBROWSERWIDGET_H_ */
|
||||
|
@ -245,6 +245,7 @@ void UAVObjectTreeModel::addSingleField(int index, UAVObjectField *field, TreeIt
|
||||
Q_ASSERT(false);
|
||||
}
|
||||
item->setHighlightManager(m_highlightManager);
|
||||
item->setDescription(field->getDescription());
|
||||
connect(item, SIGNAL(updateHighlight(TreeItem *)), this, SLOT(updateHighlight(TreeItem *)));
|
||||
parent->appendChild(item);
|
||||
}
|
||||
|
@ -6,8 +6,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>169</width>
|
||||
<height>96</height>
|
||||
<width>172</width>
|
||||
<height>124</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@ -35,6 +35,13 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="cbDescription">
|
||||
<property name="text">
|
||||
<string>Show description</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
|
@ -41,10 +41,10 @@ UAVMetaObject::UAVMetaObject(quint32 objID, const QString & name, UAVObject *par
|
||||
QStringList modesBitField;
|
||||
modesBitField << tr("FlightReadOnly") << tr("GCSReadOnly") << tr("FlightTelemetryAcked") << tr("GCSTelemetryAcked") << tr("FlightUpdatePeriodic") << tr("FlightUpdateOnChange") << tr("GCSUpdatePeriodic") << tr("GCSUpdateOnChange") << tr("LoggingUpdatePeriodic") << tr("LoggingUpdateOnChange");
|
||||
QList<UAVObjectField *> fields;
|
||||
fields.append(new UAVObjectField(tr("Modes"), tr("boolean"), UAVObjectField::BITFIELD, modesBitField, QStringList()));
|
||||
fields.append(new UAVObjectField(tr("Flight Telemetry Update Period"), tr("ms"), UAVObjectField::UINT16, 1, QStringList()));
|
||||
fields.append(new UAVObjectField(tr("GCS Telemetry Update Period"), tr("ms"), UAVObjectField::UINT16, 1, QStringList()));
|
||||
fields.append(new UAVObjectField(tr("Logging Update Period"), tr("ms"), UAVObjectField::UINT16, 1, QStringList()));
|
||||
fields.append(new UAVObjectField(tr("Modes"), tr("Metadata modes"), tr("boolean"), UAVObjectField::BITFIELD, modesBitField, QStringList()));
|
||||
fields.append(new UAVObjectField(tr("Flight Telemetry Update Period"), tr("This is how often flight side will update telemetry data"), tr("ms"), UAVObjectField::UINT16, 1, QStringList()));
|
||||
fields.append(new UAVObjectField(tr("GCS Telemetry Update Period"), tr("This is how often GCS will update telemetry data"), tr("ms"), UAVObjectField::UINT16, 1, QStringList()));
|
||||
fields.append(new UAVObjectField(tr("Logging Update Period"), tr("This is how often logging will be updated."), tr("ms"), UAVObjectField::UINT16, 1, QStringList()));
|
||||
// Initialize parent
|
||||
UAVObject::initialize(0);
|
||||
UAVObject::initializeFields(fields, (quint8 *)&parentMetadata, sizeof(Metadata));
|
||||
|
@ -30,7 +30,7 @@
|
||||
#include <QDebug>
|
||||
#include <QtWidgets>
|
||||
|
||||
UAVObjectField::UAVObjectField(const QString & name, const QString & units, FieldType type, quint32 numElements, const QStringList & options, const QString &limits)
|
||||
UAVObjectField::UAVObjectField(const QString & name, const QString & description, const QString & units, FieldType type, quint32 numElements, const QStringList & options, const QString &limits)
|
||||
{
|
||||
QStringList elementNames;
|
||||
|
||||
@ -39,18 +39,19 @@ UAVObjectField::UAVObjectField(const QString & name, const QString & units, Fiel
|
||||
elementNames.append(QString("%1").arg(n));
|
||||
}
|
||||
// Initialize
|
||||
constructorInitialize(name, units, type, elementNames, options, limits);
|
||||
constructorInitialize(name, description, units, type, elementNames, options, limits);
|
||||
}
|
||||
|
||||
UAVObjectField::UAVObjectField(const QString & name, const QString & units, FieldType type, const QStringList & elementNames, const QStringList & options, const QString &limits)
|
||||
UAVObjectField::UAVObjectField(const QString & name, const QString & description, const QString & units, FieldType type, const QStringList & elementNames, const QStringList & options, const QString &limits)
|
||||
{
|
||||
constructorInitialize(name, units, type, elementNames, options, limits);
|
||||
constructorInitialize(name, description, units, type, elementNames, options, limits);
|
||||
}
|
||||
|
||||
void UAVObjectField::constructorInitialize(const QString & name, const QString & units, FieldType type, const QStringList & elementNames, const QStringList & options, const QString &limits)
|
||||
void UAVObjectField::constructorInitialize(const QString & name, const QString & description, const QString & units, FieldType type, const QStringList & elementNames, const QStringList & options, const QString &limits)
|
||||
{
|
||||
// Copy params
|
||||
this->name = name;
|
||||
this->description = description;
|
||||
this->units = units;
|
||||
this->type = type;
|
||||
this->options = options;
|
||||
@ -458,11 +459,65 @@ bool UAVObjectField::isWithinLimits(QVariant var, quint32 index, int board)
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
QString UAVObjectField::getLimitsAsString(quint32 index, int board)
|
||||
{
|
||||
QString limitString;
|
||||
|
||||
if (elementLimits.keys().contains(index)) {
|
||||
foreach(LimitStruct struc, elementLimits.value(index)) {
|
||||
if ((struc.board != board) && board != 0 && struc.board != 0) {
|
||||
continue;
|
||||
}
|
||||
switch (struc.type) {
|
||||
case EQUAL:
|
||||
{
|
||||
limitString.append(tr("one of")).append(" [");
|
||||
bool first = true;
|
||||
foreach(QVariant var, struc.values) {
|
||||
if (!first) {
|
||||
limitString.append(", ");
|
||||
}
|
||||
limitString.append(var.toString());
|
||||
first = false;
|
||||
}
|
||||
return limitString.append("]");
|
||||
}
|
||||
case NOT_EQUAL:
|
||||
{
|
||||
limitString.append(tr("none of")).append(" [");
|
||||
bool first = true;
|
||||
foreach(QVariant var, struc.values) {
|
||||
if (!first) {
|
||||
limitString.append(", ");
|
||||
}
|
||||
limitString.append(var.toString());
|
||||
first = false;
|
||||
}
|
||||
return limitString.append("]");
|
||||
}
|
||||
case BIGGER: return limitString.append(QString("%1 %2").arg(tr("more than"), struc.values.at(0).toString()));
|
||||
|
||||
case BETWEEN: return limitString.append(QString("%1 %2 %3 %4")
|
||||
.arg(tr("between"), struc.values.at(0).toString(),
|
||||
tr(" and "), struc.values.at(1).toString()));
|
||||
|
||||
case SMALLER: return limitString.append(QString("%1 %2").arg(tr("less than"), struc.values.at(0).toString()));
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return limitString;
|
||||
}
|
||||
|
||||
QVariant UAVObjectField::getMaxLimit(quint32 index, int board)
|
||||
{
|
||||
if (!elementLimits.keys().contains(index)) {
|
||||
@ -478,20 +533,14 @@ QVariant UAVObjectField::getMaxLimit(quint32 index, int board)
|
||||
case BIGGER:
|
||||
return QVariant();
|
||||
|
||||
break;
|
||||
break;
|
||||
case BETWEEN:
|
||||
return struc.values.at(1);
|
||||
|
||||
break;
|
||||
case SMALLER:
|
||||
return struc.values.at(0);
|
||||
|
||||
break;
|
||||
default:
|
||||
return QVariant();
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
return QVariant();
|
||||
@ -511,20 +560,14 @@ QVariant UAVObjectField::getMinLimit(quint32 index, int board)
|
||||
case SMALLER:
|
||||
return QVariant();
|
||||
|
||||
break;
|
||||
break;
|
||||
case BETWEEN:
|
||||
return struc.values.at(0);
|
||||
|
||||
break;
|
||||
case BIGGER:
|
||||
return struc.values.at(0);
|
||||
|
||||
break;
|
||||
default:
|
||||
return QVariant();
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
return QVariant();
|
||||
@ -609,6 +652,11 @@ QString UAVObjectField::getName()
|
||||
return name;
|
||||
}
|
||||
|
||||
QString UAVObjectField::getDescription()
|
||||
{
|
||||
return description;
|
||||
}
|
||||
|
||||
QString UAVObjectField::getUnits()
|
||||
{
|
||||
return units;
|
||||
|
@ -45,20 +45,21 @@ class UAVOBJECTS_EXPORT UAVObjectField : public QObject {
|
||||
|
||||
public:
|
||||
typedef enum { INT8 = 0, INT16, INT32, UINT8, UINT16, UINT32, FLOAT32, ENUM, BITFIELD, STRING } FieldType;
|
||||
typedef enum { EQUAL, NOT_EQUAL, BETWEEN, BIGGER, SMALLER } LimitType;
|
||||
typedef enum { EQUAL, NOT_EQUAL, BETWEEN, BIGGER, SMALLER, UNDEFINED } LimitType;
|
||||
typedef struct {
|
||||
LimitType type;
|
||||
QList<QVariant> values;
|
||||
int board;
|
||||
} LimitStruct;
|
||||
|
||||
UAVObjectField(const QString & name, const QString & units, FieldType type, quint32 numElements, const QStringList & options, const QString & limits = QString());
|
||||
UAVObjectField(const QString & name, const QString & units, FieldType type, const QStringList & elementNames, const QStringList & options, const QString & limits = QString());
|
||||
UAVObjectField(const QString & name, const QString & description, const QString & units, FieldType type, quint32 numElements, const QStringList & options, const QString & limits = QString());
|
||||
UAVObjectField(const QString & name, const QString & description, const QString & units, FieldType type, const QStringList & elementNames, const QStringList & options, const QString & limits = QString());
|
||||
void initialize(quint8 *data, quint32 dataOffset, UAVObject *obj);
|
||||
UAVObject *getObject();
|
||||
FieldType getType();
|
||||
QString getTypeAsString();
|
||||
QString getName();
|
||||
QString getDescription();
|
||||
QString getUnits();
|
||||
quint32 getNumElements();
|
||||
QStringList getElementNames();
|
||||
@ -84,6 +85,7 @@ public:
|
||||
void fromJson(const QJsonObject &jsonObject);
|
||||
|
||||
bool isWithinLimits(QVariant var, quint32 index, int board = 0);
|
||||
QString getLimitsAsString(quint32 index, int board = 0);
|
||||
QVariant getMaxLimit(quint32 index, int board = 0);
|
||||
QVariant getMinLimit(quint32 index, int board = 0);
|
||||
signals:
|
||||
@ -91,6 +93,7 @@ signals:
|
||||
|
||||
protected:
|
||||
QString name;
|
||||
QString description;
|
||||
QString units;
|
||||
FieldType type;
|
||||
QStringList elementNames;
|
||||
@ -102,7 +105,7 @@ protected:
|
||||
UAVObject *obj;
|
||||
QMap<quint32, QList<LimitStruct> > elementLimits;
|
||||
void clear();
|
||||
void constructorInitialize(const QString & name, const QString & units, FieldType type, const QStringList & elementNames, const QStringList & options, const QString &limits);
|
||||
void constructorInitialize(const QString & name, const QString & description, const QString & units, FieldType type, const QStringList & elementNames, const QStringList & options, const QString &limits);
|
||||
void limitsInitialize(const QString &limits);
|
||||
};
|
||||
|
||||
|
@ -10,8 +10,6 @@ Rectangle {
|
||||
sourceComponent: scrollDecorator.flickableItem ? scrollBar : undefined
|
||||
}
|
||||
|
||||
Component.onDestruction: scrollLoader.sourceComponent = undefined
|
||||
|
||||
Component {
|
||||
id: scrollBar
|
||||
Rectangle {
|
||||
|
@ -259,8 +259,9 @@ bool UAVObjectGeneratorGCS::process_object(ObjectInfo *info)
|
||||
.arg(varOptionName)
|
||||
.arg(options[m]));
|
||||
}
|
||||
finit.append(QString(" fields.append( new UAVObjectField(QString(\"%1\"), QString(\"%2\"), UAVObjectField::ENUM, %3, %4, QString(\"%5\")));\n")
|
||||
finit.append(QString(" fields.append( new UAVObjectField(QString(\"%1\"), tr(\"%2\"), QString(\"%3\"), UAVObjectField::ENUM, %4, %5, QString(\"%6\")));\n")
|
||||
.arg(info->fields[n]->name)
|
||||
.arg(info->fields[n]->description)
|
||||
.arg(info->fields[n]->units)
|
||||
.arg(varElemName)
|
||||
.arg(varOptionName)
|
||||
@ -268,8 +269,9 @@ bool UAVObjectGeneratorGCS::process_object(ObjectInfo *info)
|
||||
}
|
||||
// For all other types
|
||||
else {
|
||||
finit.append(QString(" fields.append( new UAVObjectField(QString(\"%1\"), QString(\"%2\"), UAVObjectField::%3, %4, QStringList(), QString(\"%5\")));\n")
|
||||
finit.append(QString(" fields.append( new UAVObjectField(QString(\"%1\"), tr(\"%2\"), QString(\"%3\"), UAVObjectField::%4, %5, QStringList(), QString(\"%6\")));\n")
|
||||
.arg(info->fields[n]->name)
|
||||
.arg(info->fields[n]->description)
|
||||
.arg(info->fields[n]->units)
|
||||
.arg(fieldTypeStrCPPClass[info->fields[n]->type])
|
||||
.arg(varElemName)
|
||||
|
@ -25,7 +25,7 @@
|
||||
*/
|
||||
|
||||
#include "uavobjectparser.h"
|
||||
|
||||
#include <QDebug>
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
@ -441,6 +441,21 @@ QString UAVObjectParser::processObjectFields(QDomNode & childNode, ObjectInfo *i
|
||||
field->name = name;
|
||||
}
|
||||
|
||||
// Get description attribute if any
|
||||
elemAttr = elemAttributes.namedItem("description");
|
||||
if (!elemAttr.isNull()) {
|
||||
field->description = elemAttr.nodeValue();
|
||||
} else {
|
||||
// Look for a child description node
|
||||
QDomNode node = childNode.firstChildElement("description");
|
||||
if (!node.isNull()) {
|
||||
QDomNode description = node.firstChild();
|
||||
if (!description.isNull()) {
|
||||
field->description = description.nodeValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get units attribute
|
||||
elemAttr = elemAttributes.namedItem("units");
|
||||
if (elemAttr.isNull()) {
|
||||
|
@ -49,6 +49,7 @@ typedef enum {
|
||||
|
||||
typedef struct {
|
||||
QString name;
|
||||
QString description;
|
||||
QString units;
|
||||
FieldType type;
|
||||
int numElements;
|
||||
|
@ -1,6 +1,6 @@
|
||||
<xml>
|
||||
<object name="CameraStabSettings" singleinstance="true" settings="true" category="Control">
|
||||
<description>Settings for the @ref CameraStab mmodule</description>
|
||||
<description>Settings for the @ref CameraStab module</description>
|
||||
<field name="Input" units="channel" type="enum" elementnames="Roll,Pitch,Yaw" options="Accessory0,Accessory1,Accessory2,Accessory3,Accessory4,Accessory5,None" defaultvalue="None"/>
|
||||
<field name="InputRange" units="deg" type="uint8" elementnames="Roll,Pitch,Yaw" defaultvalue="20"/>
|
||||
<field name="InputRate" units="deg/s" type="uint8" elementnames="Roll,Pitch,Yaw" defaultvalue="50"/>
|
||||
|
@ -1,7 +1,10 @@
|
||||
<xml>
|
||||
<object name="DebugLogSettings" singleinstance="true" settings="true" category="System">
|
||||
<description>Configure On Board Logging Facilities</description>
|
||||
<field name="LoggingEnabled" units="" type="enum" elements="1" options="Disabled,OnlyWhenArmed,Always" defaultvalue="Disabled" />
|
||||
|
||||
<field name="LoggingEnabled" units="" type="enum" elements="1" options="Disabled,OnlyWhenArmed,Always" defaultvalue="Disabled">
|
||||
<description>If set to OnlyWhenArmed logs will only be saved when craft is armed. Disabled turns logging off, and Always will always log.</description>
|
||||
</field>
|
||||
|
||||
<access gcs="readwrite" flight="readwrite"/>
|
||||
<telemetrygcs acked="true" updatemode="onchange" period="0"/>
|
||||
|
@ -1,10 +1,10 @@
|
||||
<xml>
|
||||
<object name="DebugLogStatus" singleinstance="true" settings="false" category="System">
|
||||
<description>Log Status Object, contains log partition status information</description>
|
||||
<field name="Flight" units="" type="uint16" elements="1" />
|
||||
<field name="Entry" units="" type="uint16" elements="1" />
|
||||
<field name="UsedSlots" units="" type="uint16" elements="1" />
|
||||
<field name="FreeSlots" units="" type="uint16" elements="1" />
|
||||
<field name="Flight" units="" type="uint16" elements="1" description="The current flight number (logging session)"/>
|
||||
<field name="Entry" units="" type="uint16" elements="1" description="The current log entry id"/>
|
||||
<field name="UsedSlots" units="" type="uint16" elements="1" description="Holds the total log entries saved"/>
|
||||
<field name="FreeSlots" units="" type="uint16" elements="1" description="The number of free log slots available"/>
|
||||
<access gcs="readwrite" flight="readwrite"/>
|
||||
<telemetrygcs acked="false" updatemode="manual" period="0"/>
|
||||
<telemetryflight acked="false" updatemode="periodic" period="1000"/>
|
||||
|
@ -7,69 +7,69 @@
|
||||
<!-- Note these options should be identical to those in StabilizationDesired.StabilizationMode -->
|
||||
<field name="Stabilization1Settings" units="" type="enum"
|
||||
elementnames="Roll,Pitch,Yaw,Thrust"
|
||||
options="Manual,Rate,Attitude,AxisLock,WeakLeveling,VirtualBar,Rattitude,RelayRate,RelayAttitude,AltitudeHold,AltitudeVario,CruiseControl"
|
||||
options="Manual,Rate,Attitude,AxisLock,WeakLeveling,VirtualBar,Acro+,Rattitude,RelayRate,RelayAttitude,AltitudeHold,AltitudeVario,CruiseControl"
|
||||
defaultvalue="Attitude,Attitude,AxisLock,Manual"
|
||||
limits="%NE:RelayRate:RelayAttitude:AltitudeHold:AltitudeVario:CruiseControl; \
|
||||
%NE:RelayRate:RelayAttitude:AltitudeHold:AltitudeVario:CruiseControl; \
|
||||
%NE:RelayRate:RelayAttitude:AltitudeHold:AltitudeVario:CruiseControl; \
|
||||
%NE:Rate:Attitude:AxisLock:WeakLeveling:VirtualBar:Rattitude:RelayRate:RelayAttitude,\
|
||||
%0401NE:Rate:Attitude:AxisLock:WeakLeveling:VirtualBar:Rattitude:RelayRate:RelayAttitude:AltitudeHold:AltitudeVario,\
|
||||
%0402NE:Rate:Attitude:AxisLock:WeakLeveling:VirtualBar:Rattitude:RelayRate:RelayAttitude:AltitudeHold:AltitudeVario;"
|
||||
%NE:Rate:Attitude:AxisLock:WeakLeveling:VirtualBar:Acro+:Rattitude:RelayRate:RelayAttitude,\
|
||||
%0401NE:Rate:Attitude:AxisLock:WeakLeveling:VirtualBar:Acro+:Rattitude:RelayRate:RelayAttitude:AltitudeHold:AltitudeVario,\
|
||||
%0402NE:Rate:Attitude:AxisLock:WeakLeveling:VirtualBar:Acro+:Rattitude:RelayRate:RelayAttitude:AltitudeHold:AltitudeVario;"
|
||||
/>
|
||||
<field name="Stabilization2Settings" units="" type="enum"
|
||||
elementnames="Roll,Pitch,Yaw,Thrust"
|
||||
options="Manual,Rate,Attitude,AxisLock,WeakLeveling,VirtualBar,Rattitude,RelayRate,RelayAttitude,AltitudeHold,AltitudeVario,CruiseControl"
|
||||
options="Manual,Rate,Attitude,AxisLock,WeakLeveling,VirtualBar,Acro+,Rattitude,RelayRate,RelayAttitude,AltitudeHold,AltitudeVario,CruiseControl"
|
||||
defaultvalue="Attitude,Attitude,Rate,Manual"
|
||||
limits="%NE:RelayRate:RelayAttitude:AltitudeHold:AltitudeVario:CruiseControl; \
|
||||
%NE:RelayRate:RelayAttitude:AltitudeHold:AltitudeVario:CruiseControl; \
|
||||
%NE:RelayRate:RelayAttitude:AltitudeHold:AltitudeVario:CruiseControl; \
|
||||
%NE:Rate:Attitude:AxisLock:WeakLeveling:VirtualBar:Rattitude:RelayRate:RelayAttitude,\
|
||||
%0401NE:Rate:Attitude:AxisLock:WeakLeveling:VirtualBar:Rattitude:RelayRate:RelayAttitude:AltitudeHold:AltitudeVario,\
|
||||
%0402NE:Rate:Attitude:AxisLock:WeakLeveling:VirtualBar:Rattitude:RelayRate:RelayAttitude:AltitudeHold:AltitudeVario;"
|
||||
%NE:Rate:Attitude:AxisLock:WeakLeveling:VirtualBar:Acro+:Rattitude:RelayRate:RelayAttitude,\
|
||||
%0401NE:Rate:Attitude:AxisLock:WeakLeveling:VirtualBar:Acro+:Rattitude:RelayRate:RelayAttitude:AltitudeHold:AltitudeVario,\
|
||||
%0402NE:Rate:Attitude:AxisLock:WeakLeveling:VirtualBar:Acro+:Rattitude:RelayRate:RelayAttitude:AltitudeHold:AltitudeVario;"
|
||||
/>
|
||||
<field name="Stabilization3Settings" units="" type="enum"
|
||||
elementnames="Roll,Pitch,Yaw,Thrust"
|
||||
options="Manual,Rate,Attitude,AxisLock,WeakLeveling,VirtualBar,Rattitude,RelayRate,RelayAttitude,AltitudeHold,AltitudeVario,CruiseControl"
|
||||
options="Manual,Rate,Attitude,AxisLock,WeakLeveling,VirtualBar,Acro+,Rattitude,RelayRate,RelayAttitude,AltitudeHold,AltitudeVario,CruiseControl"
|
||||
defaultvalue="Rate,Rate,Rate,Manual"
|
||||
limits="%NE:RelayRate:RelayAttitude:AltitudeHold:AltitudeVario:CruiseControl; \
|
||||
%NE:RelayRate:RelayAttitude:AltitudeHold:AltitudeVario:CruiseControl; \
|
||||
%NE:RelayRate:RelayAttitude:AltitudeHold:AltitudeVario:CruiseControl; \
|
||||
%NE:Rate:Attitude:AxisLock:WeakLeveling:VirtualBar:Rattitude:RelayRate:RelayAttitude,\
|
||||
%0401NE:Rate:Attitude:AxisLock:WeakLeveling:VirtualBar:Rattitude:RelayRate:RelayAttitude:AltitudeHold:AltitudeVario,\
|
||||
%0402NE:Rate:Attitude:AxisLock:WeakLeveling:VirtualBar:Rattitude:RelayRate:RelayAttitude:AltitudeHold:AltitudeVario;"
|
||||
%NE:Rate:Attitude:AxisLock:WeakLeveling:VirtualBar:Acro+:Rattitude:RelayRate:RelayAttitude,\
|
||||
%0401NE:Rate:Attitude:AxisLock:WeakLeveling:VirtualBar:Acro+:Rattitude:RelayRate:RelayAttitude:AltitudeHold:AltitudeVario,\
|
||||
%0402NE:Rate:Attitude:AxisLock:WeakLeveling:VirtualBar:Acro+:Rattitude:RelayRate:RelayAttitude:AltitudeHold:AltitudeVario;"
|
||||
/>
|
||||
<field name="Stabilization4Settings" units="" type="enum"
|
||||
elementnames="Roll,Pitch,Yaw,Thrust"
|
||||
options="Manual,Rate,Attitude,AxisLock,WeakLeveling,VirtualBar,Rattitude,RelayRate,RelayAttitude,AltitudeHold,AltitudeVario,CruiseControl"
|
||||
options="Manual,Rate,Attitude,AxisLock,WeakLeveling,VirtualBar,Acro+,Rattitude,RelayRate,RelayAttitude,AltitudeHold,AltitudeVario,CruiseControl"
|
||||
defaultvalue="Attitude,Attitude,AxisLock,CruiseControl"
|
||||
limits="%NE:RelayRate:RelayAttitude:AltitudeHold:AltitudeVario:CruiseControl; \
|
||||
%NE:RelayRate:RelayAttitude:AltitudeHold:AltitudeVario:CruiseControl; \
|
||||
%NE:RelayRate:RelayAttitude:AltitudeHold:AltitudeVario:CruiseControl; \
|
||||
%NE:Rate:Attitude:AxisLock:WeakLeveling:VirtualBar:Rattitude:RelayRate:RelayAttitude,\
|
||||
%0401NE:Rate:Attitude:AxisLock:WeakLeveling:VirtualBar:Rattitude:RelayRate:RelayAttitude:AltitudeHold:AltitudeVario,\
|
||||
%0402NE:Rate:Attitude:AxisLock:WeakLeveling:VirtualBar:Rattitude:RelayRate:RelayAttitude:AltitudeHold:AltitudeVario;"
|
||||
%NE:Rate:Attitude:AxisLock:WeakLeveling:VirtualBar:Acro+:Rattitude:RelayRate:RelayAttitude,\
|
||||
%0401NE:Rate:Attitude:AxisLock:WeakLeveling:VirtualBar:Acro+:Rattitude:RelayRate:RelayAttitude:AltitudeHold:AltitudeVario,\
|
||||
%0402NE:Rate:Attitude:AxisLock:WeakLeveling:VirtualBar:Acro+:Rattitude:RelayRate:RelayAttitude:AltitudeHold:AltitudeVario;"
|
||||
/>
|
||||
<field name="Stabilization5Settings" units="" type="enum"
|
||||
elementnames="Roll,Pitch,Yaw,Thrust"
|
||||
options="Manual,Rate,Attitude,AxisLock,WeakLeveling,VirtualBar,Rattitude,RelayRate,RelayAttitude,AltitudeHold,AltitudeVario,CruiseControl"
|
||||
options="Manual,Rate,Attitude,AxisLock,WeakLeveling,VirtualBar,Acro+,Rattitude,RelayRate,RelayAttitude,AltitudeHold,AltitudeVario,CruiseControl"
|
||||
defaultvalue="Attitude,Attitude,Rate,CruiseControl"
|
||||
limits="%NE:RelayRate:RelayAttitude:AltitudeHold:AltitudeVario:CruiseControl; \
|
||||
%NE:RelayRate:RelayAttitude:AltitudeHold:AltitudeVario:CruiseControl; \
|
||||
%NE:RelayRate:RelayAttitude:AltitudeHold:AltitudeVario:CruiseControl; \
|
||||
%NE:Rate:Attitude:AxisLock:WeakLeveling:VirtualBar:Rattitude:RelayRate:RelayAttitude,\
|
||||
%0401NE:Rate:Attitude:AxisLock:WeakLeveling:VirtualBar:Rattitude:RelayRate:RelayAttitude:AltitudeHold:AltitudeVario,\
|
||||
%0402NE:Rate:Attitude:AxisLock:WeakLeveling:VirtualBar:Rattitude:RelayRate:RelayAttitude:AltitudeHold:AltitudeVario;"
|
||||
%NE:Rate:Attitude:AxisLock:WeakLeveling:VirtualBar:Acro+:Rattitude:RelayRate:RelayAttitude,\
|
||||
%0401NE:Rate:Attitude:AxisLock:WeakLeveling:VirtualBar:Acro+:Rattitude:RelayRate:RelayAttitude:AltitudeHold:AltitudeVario,\
|
||||
%0402NE:Rate:Attitude:AxisLock:WeakLeveling:VirtualBar:Acro+:Rattitude:RelayRate:RelayAttitude:AltitudeHold:AltitudeVario;"
|
||||
/>
|
||||
<field name="Stabilization6Settings" units="" type="enum"
|
||||
elementnames="Roll,Pitch,Yaw,Thrust"
|
||||
options="Manual,Rate,Attitude,AxisLock,WeakLeveling,VirtualBar,Rattitude,RelayRate,RelayAttitude,AltitudeHold,AltitudeVario,CruiseControl"
|
||||
options="Manual,Rate,Attitude,AxisLock,WeakLeveling,VirtualBar,Acro+,Rattitude,RelayRate,RelayAttitude,AltitudeHold,AltitudeVario,CruiseControl"
|
||||
defaultvalue="Rate,Rate,Rate,CruiseControl"
|
||||
limits="%NE:RelayRate:RelayAttitude:AltitudeHold:AltitudeVario:CruiseControl; \
|
||||
%NE:RelayRate:RelayAttitude:AltitudeHold:AltitudeVario:CruiseControl; \
|
||||
%NE:RelayRate:RelayAttitude:AltitudeHold:AltitudeVario:CruiseControl; \
|
||||
%NE:Rate:Attitude:AxisLock:WeakLeveling:VirtualBar:Rattitude:RelayRate:RelayAttitude,\
|
||||
%0401NE:Rate:Attitude:AxisLock:WeakLeveling:VirtualBar:Rattitude:RelayRate:RelayAttitude:AltitudeHold:AltitudeVario,\
|
||||
%0402NE:Rate:Attitude:AxisLock:WeakLeveling:VirtualBar:Rattitude:RelayRate:RelayAttitude:AltitudeHold:AltitudeVario;"
|
||||
%NE:Rate:Attitude:AxisLock:WeakLeveling:VirtualBar:Acro+:Rattitude:RelayRate:RelayAttitude,\
|
||||
%0401NE:Rate:Attitude:AxisLock:WeakLeveling:VirtualBar:Acro+:Rattitude:RelayRate:RelayAttitude:AltitudeHold:AltitudeVario,\
|
||||
%0402NE:Rate:Attitude:AxisLock:WeakLeveling:VirtualBar:Acro+:Rattitude:RelayRate:RelayAttitude:AltitudeHold:AltitudeVario;"
|
||||
/>
|
||||
|
||||
<!-- Note these options values should be identical to those defined in FlightMode -->
|
||||
|
@ -1,6 +1,6 @@
|
||||
<xml>
|
||||
<object name="HomeLocation" singleinstance="true" settings="true" category="Navigation">
|
||||
<description>HomeLocation setting which contains the constants to tranlate from longitutde and latitude to NED reference frame. Automatically set by @ref GPSModule after acquiring a 3D lock. Used by @ref AHRSCommsModule.</description>
|
||||
<description>HomeLocation setting which contains the constants to translate from longitude and latitude to NED reference frame. Automatically set by @ref GPSModule after acquiring a 3D lock. Used by @ref AHRSCommsModule.</description>
|
||||
<field name="Set" units="" type="enum" elements="1" options="FALSE,TRUE" defaultvalue="FALSE"/>
|
||||
<field name="Latitude" units="deg * 10e6" type="int32" elements="1" defaultvalue="0"/>
|
||||
<field name="Longitude" units="deg * 10e6" type="int32" elements="1" defaultvalue="0"/>
|
||||
|
@ -12,7 +12,7 @@
|
||||
<field name="RV_TelemetryPort" units="function" type="enum" elements="1" options="Disabled,Telemetry,ComAux,ComBridge" defaultvalue="Telemetry"/>
|
||||
<field name="RV_GPSPort" units="function" type="enum" elements="1" options="Disabled,Telemetry,GPS,ComAux,ComBridge" defaultvalue="GPS"/>
|
||||
|
||||
<field name="RM_RcvrPort" units="function" type="enum" elements="1" options="Disabled,PWM,PPM,PPM+PWM,PPM+Outputs,Outputs" defaultvalue="PWM"/>
|
||||
<field name="RM_RcvrPort" units="function" type="enum" elements="1" options="Disabled,PWM,PPM,PPM+PWM,PPM+Telemetry,PPM+Outputs,Outputs,Telemetry" defaultvalue="PWM"/>
|
||||
<field name="RM_MainPort" units="function" type="enum" elements="1" options="Disabled,Telemetry,GPS,S.Bus,DSM2,DSMX (10bit),DSMX (11bit),DebugConsole,ComBridge,OsdHk" defaultvalue="Disabled"/>
|
||||
<field name="RM_FlexiPort" units="function" type="enum" elements="1" options="Disabled,Telemetry,GPS,I2C,DSM2,DSMX (10bit),DSMX (11bit),DebugConsole,ComBridge,OsdHk" defaultvalue="Disabled"/>
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
<xml>
|
||||
<object name="ManualControlCommand" singleinstance="true" settings="false" category="Control">
|
||||
<description>The output from the @ref ManualControlModule which descodes the receiver inputs. Overriden by GCS for fly-by-wire control.</description>
|
||||
<description>The output from the @ref ManualControlModule which decodes the receiver inputs. Overriden by GCS for fly-by-wire control.</description>
|
||||
<field name="Connected" units="" type="enum" elements="1" options="False,True"/>
|
||||
<field name="Throttle" units="%" type="float" elements="1"/>
|
||||
<field name="Roll" units="%" type="float" elements="1"/>
|
||||
|
@ -7,14 +7,19 @@
|
||||
<field name="YawMax" units="degrees" type="uint8" elements="1" defaultvalue="42" limits="%BE:0:180"/>
|
||||
<field name="ManualRate" units="degrees/sec" type="float" elementnames="Roll,Pitch,Yaw" defaultvalue="150,150,175" limits="%BE:0:500; %BE:0:500; %BE:0:500"/>
|
||||
<field name="MaximumRate" units="degrees/sec" type="float" elementnames="Roll,Pitch,Yaw" defaultvalue="300,300,50" limits="%BE:0:500; %BE:0:500; %BE:0:500"/>
|
||||
<field name="StickExpo" units="percent" type="int8" elementnames="Roll,Pitch,Yaw" defaultvalue="0,0,0" limits="%BE:-100:100; %BE:-100:100; %BE:-100:100"/>
|
||||
|
||||
<field name="RollRatePID" units="" type="float" elementnames="Kp,Ki,Kd,ILimit" defaultvalue="0.003,0.003,0.00002,0.3" limits="%BE:0:0.01; %BE:0:0.01; ; "/>
|
||||
<field name="PitchRatePID" units="" type="float" elementnames="Kp,Ki,Kd,ILimit" defaultvalue="0.003,0.003,0.00002,0.3" limits="%BE:0:0.01; %BE:0:0.01; ; "/>
|
||||
<field name="YawRatePID" units="" type="float" elementnames="Kp,Ki,Kd,ILimit" defaultvalue="0.0035,0.0035,0,0.3" limits="%BE:0:0.01; %BE:0:0.01 ; ; "/>
|
||||
<field name="RollRatePID" units="" type="float" elementnames="Kp,Ki,Kd,ILimit" defaultvalue="0.003,0.003,0.00002,0.3" limits="%BE:0:0.01; %BE:0:0.015; ; "/>
|
||||
<field name="PitchRatePID" units="" type="float" elementnames="Kp,Ki,Kd,ILimit" defaultvalue="0.003,0.003,0.00002,0.3" limits="%BE:0:0.01; %BE:0:0.015; ; "/>
|
||||
<field name="YawRatePID" units="" type="float" elementnames="Kp,Ki,Kd,ILimit" defaultvalue="0.0035,0.0035,0,0.3" limits="%BE:0:0.01; %BE:0:0.015 ; ; "/>
|
||||
<field name="RollPI" units="" type="float" elementnames="Kp,Ki,ILimit" defaultvalue="2.5,0,50" limits="%BE:0:10; %BE:0:10; "/>
|
||||
<field name="PitchPI" units="" type="float" elementnames="Kp,Ki,ILimit" defaultvalue="2.5,0,50" limits="%BE:0:10; %BE:0:10; "/>
|
||||
<field name="YawPI" units="" type="float" elementnames="Kp,Ki,ILimit"/>
|
||||
|
||||
<field name="AcroInsanityFactor" units="percent" type="float" elements="1" defaultvalue="0.5" limits="%BE:0.0:1.0"/>
|
||||
|
||||
<field name="EnablePiroComp" units="" type="enum" elements="1" options="FALSE,TRUE" defaultvalue="TRUE"/>
|
||||
|
||||
<field name="EnableThrustPIDScaling" units="" type="enum" elements="1" options="FALSE,TRUE" defaultvalue="FALSE"/>
|
||||
<field name="ThrustPIDScaleCurve" units="percent" type="float" elementnames="0,25,50,75,100" defaultvalue="0.3,0.15,0,-0.15,-0.3"/>
|
||||
<field name="ThrustPIDScaleSource" units="" type="enum" elements="1" options="ManualControlThrottle,StabilizationDesiredThrust,ActuatorDesiredThrust" defaultvalue="ActuatorDesiredThrust" />
|
||||
|
@ -6,7 +6,7 @@
|
||||
<field name="Yaw" units="degrees" type="float" elements="1"/>
|
||||
<field name="Thrust" units="%" type="float" elements="1"/>
|
||||
<!-- These values should match those in FlightModeSettings.Stabilization{1,2,3}Settings -->
|
||||
<field name="StabilizationMode" units="" type="enum" elementnames="Roll,Pitch,Yaw,Thrust" options="Manual,Rate,Attitude,AxisLock,WeakLeveling,VirtualBar,Rattitude,RelayRate,RelayAttitude,AltitudeHold,AltitudeVario,CruiseControl"/>
|
||||
<field name="StabilizationMode" units="" type="enum" elementnames="Roll,Pitch,Yaw,Thrust" options="Manual,Rate,Attitude,AxisLock,WeakLeveling,VirtualBar,Acro+,Rattitude,RelayRate,RelayAttitude,AltitudeHold,AltitudeVario,CruiseControl"/>
|
||||
<access gcs="readwrite" flight="readwrite"/>
|
||||
<telemetrygcs acked="false" updatemode="manual" period="0"/>
|
||||
<telemetryflight acked="false" updatemode="periodic" period="1000"/>
|
||||
|
@ -7,14 +7,19 @@
|
||||
<field name="YawMax" units="degrees" type="uint8" elements="1" defaultvalue="35" limits="%BE:0:180"/>
|
||||
<field name="ManualRate" units="degrees/sec" type="float" elementnames="Roll,Pitch,Yaw" defaultvalue="220,220,220" limits="%BE:0:500; %BE:0:500; %BE:0:500"/>
|
||||
<field name="MaximumRate" units="degrees/sec" type="float" elementnames="Roll,Pitch,Yaw" defaultvalue="300,300,300" limits="%BE:0:500; %BE:0:500; %BE:0:500"/>
|
||||
<field name="StickExpo" units="percent" type="int8" elementnames="Roll,Pitch,Yaw" defaultvalue="0,0,0" limits="%BE:-100:100; %BE:-100:100; %BE:-100:100"/>
|
||||
|
||||
<field name="RollRatePID" units="" type="float" elementnames="Kp,Ki,Kd,ILimit" defaultvalue="0.0025,0.004,0.00002,0.3" limits="%BE:0:0.01; %BE:0:0.01; ; "/>
|
||||
<field name="PitchRatePID" units="" type="float" elementnames="Kp,Ki,Kd,ILimit" defaultvalue="0.0025,0.004,0.00002,0.3" limits="%BE:0:0.01; %BE:0:0.01; ; "/>
|
||||
<field name="RollRatePID" units="" type="float" elementnames="Kp,Ki,Kd,ILimit" defaultvalue="0.0025,0.004,0.00002,0.3" limits="%BE:0:0.01; %BE:0:0.015; ; "/>
|
||||
<field name="PitchRatePID" units="" type="float" elementnames="Kp,Ki,Kd,ILimit" defaultvalue="0.0025,0.004,0.00002,0.3" limits="%BE:0:0.01; %BE:0:0.015; ; "/>
|
||||
<field name="YawRatePID" units="" type="float" elementnames="Kp,Ki,Kd,ILimit" defaultvalue="0.00620,0.01000,0.00005,0.3" limits="%BE:0:0.01; %BE:0:0.015 ; ; "/>
|
||||
<field name="RollPI" units="" type="float" elementnames="Kp,Ki,ILimit" defaultvalue="2.5,0,50" limits="%BE:0:10; %BE:0:10; "/>
|
||||
<field name="PitchPI" units="" type="float" elementnames="Kp,Ki,ILimit" defaultvalue="2.5,0,50" limits="%BE:0:10; %BE:0:10; "/>
|
||||
<field name="YawPI" units="" type="float" elementnames="Kp,Ki,ILimit" defaultvalue="2.5,0,50" limits="%BE:0:10; %BE:0:10; "/>
|
||||
|
||||
<field name="AcroInsanityFactor" units="percent" type="float" elements="1" defaultvalue="0.5" limits="%BE:0.0:1.0"/>
|
||||
|
||||
<field name="EnablePiroComp" units="" type="enum" elements="1" options="FALSE,TRUE" defaultvalue="TRUE"/>
|
||||
|
||||
<field name="EnableThrustPIDScaling" units="" type="enum" elements="1" options="FALSE,TRUE" defaultvalue="FALSE"/>
|
||||
<field name="ThrustPIDScaleCurve" units="percent" type="float" elementnames="0,25,50,75,100" defaultvalue="0.3,0.15,0,-0.15,-0.3"/>
|
||||
<field name="ThrustPIDScaleSource" units="" type="enum" elements="1" options="ManualControlThrottle,StabilizationDesiredThrust,ActuatorDesiredThrust" defaultvalue="ActuatorDesiredThrust" />
|
||||
|
@ -7,14 +7,19 @@
|
||||
<field name="YawMax" units="degrees" type="uint8" elements="1" defaultvalue="35" limits="%BE:0:180"/>
|
||||
<field name="ManualRate" units="degrees/sec" type="float" elementnames="Roll,Pitch,Yaw" defaultvalue="220,220,220" limits="%BE:0:500; %BE:0:500; %BE:0:500"/>
|
||||
<field name="MaximumRate" units="degrees/sec" type="float" elementnames="Roll,Pitch,Yaw" defaultvalue="300,300,300" limits="%BE:0:500; %BE:0:500; %BE:0:500"/>
|
||||
<field name="StickExpo" units="percent" type="int8" elementnames="Roll,Pitch,Yaw" defaultvalue="0,0,0" limits="%BE:-100:100; %BE:-100:100; %BE:-100:100"/>
|
||||
|
||||
<field name="RollRatePID" units="" type="float" elementnames="Kp,Ki,Kd,ILimit" defaultvalue="0.0025,0.004,0.00002,0.3" limits="%BE:0:0.01; %BE:0:0.01; ; "/>
|
||||
<field name="PitchRatePID" units="" type="float" elementnames="Kp,Ki,Kd,ILimit" defaultvalue="0.0025,0.004,0.00002,0.3" limits="%BE:0:0.01; %BE:0:0.01; ; "/>
|
||||
<field name="RollRatePID" units="" type="float" elementnames="Kp,Ki,Kd,ILimit" defaultvalue="0.0025,0.004,0.00002,0.3" limits="%BE:0:0.01; %BE:0:0.015; ; "/>
|
||||
<field name="PitchRatePID" units="" type="float" elementnames="Kp,Ki,Kd,ILimit" defaultvalue="0.0025,0.004,0.00002,0.3" limits="%BE:0:0.01; %BE:0:0.015; ; "/>
|
||||
<field name="YawRatePID" units="" type="float" elementnames="Kp,Ki,Kd,ILimit" defaultvalue="0.00620,0.01000,0.00005,0.3" limits="%BE:0:0.01; %BE:0:0.015 ; ; "/>
|
||||
<field name="RollPI" units="" type="float" elementnames="Kp,Ki,ILimit" defaultvalue="2.5,0,50" limits="%BE:0:10; %BE:0:10; "/>
|
||||
<field name="PitchPI" units="" type="float" elementnames="Kp,Ki,ILimit" defaultvalue="2.5,0,50" limits="%BE:0:10; %BE:0:10; "/>
|
||||
<field name="YawPI" units="" type="float" elementnames="Kp,Ki,ILimit" defaultvalue="2.5,0,50" limits="%BE:0:10; %BE:0:10; "/>
|
||||
|
||||
<field name="AcroInsanityFactor" units="percent" type="float" elements="1" defaultvalue="0.5" limits="%BE:0.0:1.0"/>
|
||||
|
||||
<field name="EnablePiroComp" units="" type="enum" elements="1" options="FALSE,TRUE" defaultvalue="TRUE"/>
|
||||
|
||||
<field name="EnableThrustPIDScaling" units="" type="enum" elements="1" options="FALSE,TRUE" defaultvalue="FALSE"/>
|
||||
<field name="ThrustPIDScaleCurve" units="percent" type="float" elementnames="0,25,50,75,100" defaultvalue="0.3,0.15,0,-0.15,-0.3"/>
|
||||
<field name="ThrustPIDScaleSource" units="" type="enum" elements="1" options="ManualControlThrottle,StabilizationDesiredThrust,ActuatorDesiredThrust" defaultvalue="ActuatorDesiredThrust" />
|
||||
|
@ -7,14 +7,19 @@
|
||||
<field name="YawMax" units="degrees" type="uint8" elements="1" defaultvalue="35" limits="%BE:0:180"/>
|
||||
<field name="ManualRate" units="degrees/sec" type="float" elementnames="Roll,Pitch,Yaw" defaultvalue="220,220,220" limits="%BE:0:500; %BE:0:500; %BE:0:500"/>
|
||||
<field name="MaximumRate" units="degrees/sec" type="float" elementnames="Roll,Pitch,Yaw" defaultvalue="300,300,300" limits="%BE:0:500; %BE:0:500; %BE:0:500"/>
|
||||
<field name="StickExpo" units="percent" type="int8" elementnames="Roll,Pitch,Yaw" defaultvalue="0,0,0" limits="%BE:-100:100; %BE:-100:100; %BE:-100:100"/>
|
||||
|
||||
<field name="RollRatePID" units="" type="float" elementnames="Kp,Ki,Kd,ILimit" defaultvalue="0.0025,0.004,0.00002,0.3" limits="%BE:0:0.01; %BE:0:0.01; ; "/>
|
||||
<field name="PitchRatePID" units="" type="float" elementnames="Kp,Ki,Kd,ILimit" defaultvalue="0.0025,0.004,0.00002,0.3" limits="%BE:0:0.01; %BE:0:0.01; ; "/>
|
||||
<field name="RollRatePID" units="" type="float" elementnames="Kp,Ki,Kd,ILimit" defaultvalue="0.0025,0.004,0.00002,0.3" limits="%BE:0:0.01; %BE:0:0.015; ; "/>
|
||||
<field name="PitchRatePID" units="" type="float" elementnames="Kp,Ki,Kd,ILimit" defaultvalue="0.0025,0.004,0.00002,0.3" limits="%BE:0:0.01; %BE:0:0.015; ; "/>
|
||||
<field name="YawRatePID" units="" type="float" elementnames="Kp,Ki,Kd,ILimit" defaultvalue="0.00620,0.01000,0.00005,0.3" limits="%BE:0:0.01; %BE:0:0.015 ; ; "/>
|
||||
<field name="RollPI" units="" type="float" elementnames="Kp,Ki,ILimit" defaultvalue="2.5,0,50" limits="%BE:0:10; %BE:0:10; "/>
|
||||
<field name="PitchPI" units="" type="float" elementnames="Kp,Ki,ILimit" defaultvalue="2.5,0,50" limits="%BE:0:10; %BE:0:10; "/>
|
||||
<field name="YawPI" units="" type="float" elementnames="Kp,Ki,ILimit" defaultvalue="2.5,0,50" limits="%BE:0:10; %BE:0:10; "/>
|
||||
|
||||
<field name="AcroInsanityFactor" units="percent" type="float" elements="1" defaultvalue="0.5" limits="%BE:0.0:1.0"/>
|
||||
|
||||
<field name="EnablePiroComp" units="" type="enum" elements="1" options="FALSE,TRUE" defaultvalue="TRUE"/>
|
||||
|
||||
<field name="EnableThrustPIDScaling" units="" type="enum" elements="1" options="FALSE,TRUE" defaultvalue="FALSE"/>
|
||||
<field name="ThrustPIDScaleCurve" units="percent" type="float" elementnames="0,25,50,75,100" defaultvalue="0.3,0.15,0,-0.15,-0.3"/>
|
||||
<field name="ThrustPIDScaleSource" units="" type="enum" elements="1" options="ManualControlThrottle,StabilizationDesiredThrust,ActuatorDesiredThrust" defaultvalue="ActuatorDesiredThrust" />
|
||||
|
@ -11,7 +11,7 @@
|
||||
<elementname>Thrust</elementname>
|
||||
</elementnames>
|
||||
</field>
|
||||
<field name="InnerLoop" units="" type="enum" options="Direct,VirtualFlyBar,RelayTuning,AxisLock,Rate,CruiseControl">
|
||||
<field name="InnerLoop" units="" type="enum" options="Direct,VirtualFlyBar,Acro+,RelayTuning,AxisLock,Rate,CruiseControl">
|
||||
<elementnames>
|
||||
<elementname>Roll</elementname>
|
||||
<elementname>Pitch</elementname>
|
||||
|
@ -19,7 +19,8 @@
|
||||
Pitch Attitude.Kp, Pitch Attitude.Ki, Pitch Attitude.ILimit, Pitch Attitude.Resp,
|
||||
Roll+Pitch Attitude.Kp, Roll+Pitch Attitude.Ki, Roll+Pitch Attitude.ILimit, Roll+Pitch Attitude.Resp,
|
||||
Yaw Attitude.Kp, Yaw Attitude.Ki, Yaw Attitude.ILimit, Yaw Attitude.Resp,
|
||||
GyroTau"
|
||||
Roll.Expo, Pitch.Expo, Roll+Pitch.Expo, Yaw.Expo,
|
||||
GyroTau,AcroPlusFactor"
|
||||
defaultvalue="Disabled"/>
|
||||
<field name="MinPID" units="" type="float" elementnames="Instance1,Instance2,Instance3" defaultvalue="0"/>
|
||||
<field name="MaxPID" units="" type="float" elementnames="Instance1,Instance2,Instance3" defaultvalue="0"/>
|
||||
|
Loading…
x
Reference in New Issue
Block a user